From 2821bf132378a9222ffb5830d08a6de6be67c699 Mon Sep 17 00:00:00 2001 From: Kedar Patil Date: Tue, 16 May 2017 18:25:37 +0530 Subject: [PATCH] Initial open source release of OpenCL 2.2 CTS. --- .gitignore | 4 + CMakeLists.txt | 211 + CMakeVendor.txt | 15 + build_android.py | 159 + build_lnx.sh | 6 + build_win.bat | 32 + clean_tests.py | 104 + license.txt | 4 + readme-spir-v-binaries.txt | 42 + test_common/Makefile | 32 + test_common/autotest/autotest.hpp | 58 + test_common/autotest/test_case.hpp | 41 + test_common/autotest/test_suite.hpp | 83 + test_common/config.hpp | 41 + test_common/gl/gl_headers.h | 60 + test_common/gl/helpers.cpp | 2496 ++++ test_common/gl/helpers.h | 362 + test_common/gl/setup.h | 48 + test_common/gl/setup_osx.cpp | 156 + test_common/gl/setup_win32.cpp | 209 + test_common/gl/setup_x11.cpp | 122 + test_common/gles/gl_headers.h | 64 + test_common/gles/helpers.cpp | 1282 ++ test_common/gles/helpers.h | 247 + test_common/gles/setup.h | 46 + test_common/harness/Jamfile | 18 + test_common/harness/Makefile | 41 + test_common/harness/ThreadPool.c | 931 ++ test_common/harness/ThreadPool.h | 76 + test_common/harness/clImageHelper.h | 290 + test_common/harness/compat.h | 388 + test_common/harness/conversions.c | 1198 ++ test_common/harness/conversions.h | 126 + test_common/harness/errorHelpers.c | 813 + test_common/harness/errorHelpers.h | 164 + test_common/harness/fpcontrol.h | 104 + test_common/harness/genericThread.cpp | 53 + test_common/harness/genericThread.h | 42 + test_common/harness/imageHelpers.cpp | 3857 +++++ test_common/harness/imageHelpers.h | 646 + test_common/harness/kernelHelpers.c | 1290 ++ test_common/harness/kernelHelpers.h | 172 + test_common/harness/mingw_compat.c | 59 + test_common/harness/mingw_compat.h | 31 + test_common/harness/msvc9.c | 774 + test_common/harness/mt19937.c | 280 + test_common/harness/mt19937.h | 99 + test_common/harness/os_helpers.cpp | 564 + test_common/harness/os_helpers.h | 53 + test_common/harness/parseParameters.cpp | 129 + test_common/harness/parseParameters.h | 37 + test_common/harness/ref_counting.h | 49 + test_common/harness/rounding_mode.c | 241 + test_common/harness/rounding_mode.h | 69 + test_common/harness/testHarness.c | 849 ++ test_common/harness/testHarness.h | 102 + test_common/harness/test_mt19937.c | 51 + test_common/harness/threadTesting.c | 100 + test_common/harness/threadTesting.h | 32 + test_common/harness/typeWrappers.cpp | 481 + test_common/harness/typeWrappers.h | 332 + test_common/miniz/CMakeLists.txt | 8 + test_common/miniz/miniz.c | 4153 ++++++ test_common/miniz/miniz.h | 749 + test_conformance/CMakeCommon.txt | 13 + test_conformance/CMakeLists.txt | 92 + test_conformance/Jamfile | 24 + test_conformance/Makefile | 61 + test_conformance/SVM/CMakeLists.txt | 26 + test_conformance/SVM/Makefile | 54 + test_conformance/SVM/common.h | 101 + test_conformance/SVM/main.cpp | 317 + .../SVM/test_allocate_shared_buffer.cpp | 107 + .../SVM/test_byte_granularity.cpp | 148 + .../SVM/test_cross_buffer_pointers.cpp | 219 + test_conformance/SVM/test_enqueue_api.cpp | 254 + .../test_fine_grain_memory_consistency.cpp | 168 + .../SVM/test_fine_grain_sync_buffers.cpp | 105 + test_conformance/SVM/test_migrate.cpp | 330 + test_conformance/SVM/test_pointer_passing.cpp | 115 + .../test_set_kernel_exec_info_svm_ptrs.cpp | 153 + ...test_shared_address_space_coarse_grain.cpp | 282 + .../test_shared_address_space_fine_grain.cpp | 101 + ...hared_address_space_fine_grain_buffers.cpp | 138 + .../SVM/test_shared_sub_buffers.cpp | 241 + test_conformance/allocations/CMakeLists.txt | 19 + test_conformance/allocations/Jamfile | 19 + test_conformance/allocations/Makefile | 46 + .../allocations/allocation_execute.cpp | 333 + .../allocations/allocation_execute.h | 22 + .../allocations/allocation_fill.cpp | 338 + .../allocations/allocation_fill.h | 19 + .../allocations/allocation_functions.cpp | 287 + .../allocations/allocation_functions.h | 24 + .../allocations/allocation_utils.cpp | 87 + .../allocations/allocation_utils.h | 24 + test_conformance/allocations/main.cpp | 411 + test_conformance/allocations/testBase.h | 62 + test_conformance/api/CMakeLists.txt | 39 + test_conformance/api/Jamfile | 27 + test_conformance/api/Makefile | 61 + test_conformance/api/main.c | 223 + test_conformance/api/procs.h | 111 + test_conformance/api/testBase.h | 31 + test_conformance/api/test_api_min_max.c | 2115 +++ test_conformance/api/test_binary.cpp | 218 + test_conformance/api/test_bool.c | 52 + test_conformance/api/test_clone_kernel.cpp | 411 + .../api/test_create_context_from_type.cpp | 130 + test_conformance/api/test_create_kernels.c | 595 + ...ice_min_data_type_align_size_alignment.cpp | 60 + .../api/test_kernel_arg_changes.cpp | 141 + test_conformance/api/test_kernel_arg_info.c | 5976 ++++++++ .../api/test_kernel_arg_multi_setup.cpp | 277 + test_conformance/api/test_kernels.c | 695 + test_conformance/api/test_mem_object_info.cpp | 756 + test_conformance/api/test_mem_objects.cpp | 108 + test_conformance/api/test_native_kernel.cpp | 121 + test_conformance/api/test_null_buffer_arg.c | 206 + test_conformance/api/test_platform.cpp | 289 + test_conformance/api/test_queries.cpp | 643 + test_conformance/api/test_queue_hint.cpp | 191 + test_conformance/api/test_retain.cpp | 234 + test_conformance/api/test_retain_program.c | 105 + .../api/test_sub_group_dispatch.cpp | 218 + .../api/test_zero_sized_enqueue.cpp | 209 + test_conformance/atomics/CMakeLists.txt | 18 + test_conformance/atomics/Jamfile | 17 + test_conformance/atomics/Makefile | 44 + test_conformance/atomics/main.c | 71 + test_conformance/atomics/procs.h | 39 + test_conformance/atomics/testBase.h | 31 + test_conformance/atomics/test_atomics.cpp | 1126 ++ test_conformance/atomics/test_indexed_cases.c | 380 + test_conformance/basic/CMakeLists.txt | 83 + test_conformance/basic/Jamfile | 74 + test_conformance/basic/Makefile | 103 + test_conformance/basic/main.c | 303 + test_conformance/basic/procs.h | 160 + test_conformance/basic/run_array | 3 + test_conformance/basic/run_array_image_copy | 3 + test_conformance/basic/run_image | 17 + test_conformance/basic/run_multi_read_image | 4 + test_conformance/basic/test_arraycopy.c | 201 + test_conformance/basic/test_arrayimagecopy.c | 143 + .../basic/test_arrayimagecopy3d.c | 144 + test_conformance/basic/test_arrayreadwrite.c | 95 + test_conformance/basic/test_astype.cpp | 288 + test_conformance/basic/test_async_copy.cpp | 279 + .../basic/test_async_strided_copy.cpp | 274 + test_conformance/basic/test_barrier.c | 159 + .../basic/test_basic_parameter_types.c | 303 + .../basic/test_bufferreadwriterect.c | 564 + test_conformance/basic/test_constant.c | 262 + .../basic/test_constant_source.cpp | 101 + .../basic/test_createkernelsinprogram.c | 105 + test_conformance/basic/test_enqueue_map.cpp | 254 + .../basic/test_enqueued_local_size.c | 123 + test_conformance/basic/test_explicit_s2v.cpp | 385 + test_conformance/basic/test_float2int.c | 145 + test_conformance/basic/test_fpmath_float.c | 271 + test_conformance/basic/test_fpmath_float2.c | 269 + test_conformance/basic/test_fpmath_float4.c | 270 + .../basic/test_get_linear_ids.cpp | 191 + .../basic/test_global_linear_id.c | 121 + .../basic/test_global_work_offsets.cpp | 284 + test_conformance/basic/test_hiloeo.c | 421 + test_conformance/basic/test_hostptr.c | 277 + test_conformance/basic/test_if.c | 166 + test_conformance/basic/test_image_multipass.c | 654 + test_conformance/basic/test_image_param.c | 290 + test_conformance/basic/test_image_r8.c | 183 + test_conformance/basic/test_imagearraycopy.c | 146 + .../basic/test_imagearraycopy3d.c | 143 + test_conformance/basic/test_imagecopy.c | 235 + test_conformance/basic/test_imagecopy3d.c | 238 + test_conformance/basic/test_imagedim.c | 524 + test_conformance/basic/test_imagenpot.c | 226 + test_conformance/basic/test_imagerandomcopy.c | 270 + test_conformance/basic/test_imagereadwrite.c | 418 + .../basic/test_imagereadwrite3d.c | 418 + test_conformance/basic/test_int2float.c | 144 + test_conformance/basic/test_intmath_int.c | 334 + test_conformance/basic/test_intmath_int2.c | 333 + test_conformance/basic/test_intmath_int4.c | 332 + test_conformance/basic/test_intmath_long.c | 342 + test_conformance/basic/test_intmath_long2.c | 340 + test_conformance/basic/test_intmath_long4.c | 340 + .../test_kernel_call_kernel_function.cpp | 253 + .../basic/test_kernel_memory_alignment.cpp | 570 + test_conformance/basic/test_local.c | 368 + .../basic/test_local_kernel_scope.cpp | 139 + test_conformance/basic/test_local_linear_id.c | 122 + test_conformance/basic/test_loop.c | 185 + .../basic/test_multireadimagemultifmt.c | 236 + .../basic/test_multireadimageonefmt.c | 204 + .../basic/test_numeric_constants.cpp | 710 + test_conformance/basic/test_pointercast.c | 141 + test_conformance/basic/test_preprocessors.cpp | 393 + test_conformance/basic/test_progvar.cpp | 1555 ++ test_conformance/basic/test_queue_priority.c | 358 + test_conformance/basic/test_readimage.c | 297 + test_conformance/basic/test_readimage3d.c | 237 + .../basic/test_readimage3d_fp32.c | 153 + .../basic/test_readimage3d_int16.c | 152 + test_conformance/basic/test_readimage_fp32.c | 173 + test_conformance/basic/test_readimage_int16.c | 172 + .../basic/test_rw_image_access_qualifier.c | 167 + .../basic/test_simple_image_pitch.c | 153 + test_conformance/basic/test_sizeof.c | 397 + test_conformance/basic/test_vec_type_hint.c | 107 + .../basic/test_vector_creation.cpp | 406 + test_conformance/basic/test_vloadstore.c | 986 ++ test_conformance/basic/test_wg_barrier.c | 153 + .../basic/test_work_item_functions.cpp | 178 + test_conformance/basic/test_writeimage.c | 354 + test_conformance/basic/test_writeimage_fp32.c | 189 + .../basic/test_writeimage_int16.c | 195 + test_conformance/buffers/CMakeLists.txt | 26 + test_conformance/buffers/Jamfile | 24 + test_conformance/buffers/Makefile | 49 + test_conformance/buffers/array_info.c | 63 + test_conformance/buffers/main.c | 246 + test_conformance/buffers/procs.h | 132 + test_conformance/buffers/test_buffer_copy.c | 295 + test_conformance/buffers/test_buffer_fill.c | 1560 ++ test_conformance/buffers/test_buffer_map.c | 703 + test_conformance/buffers/test_buffer_mem.c | 524 + .../buffers/test_buffer_migrate.c | 417 + test_conformance/buffers/test_buffer_read.c | 1463 ++ test_conformance/buffers/test_buffer_write.c | 1956 +++ test_conformance/buffers/test_image_migrate.c | 487 + test_conformance/buffers/test_sub_buffers.cpp | 631 + test_conformance/c11_atomics/CMakeLists.txt | 17 + test_conformance/c11_atomics/Makefile | 46 + test_conformance/c11_atomics/common.cpp | 208 + test_conformance/c11_atomics/common.h | 1179 ++ test_conformance/c11_atomics/host_atomics.cpp | 66 + test_conformance/c11_atomics/host_atomics.h | 250 + test_conformance/c11_atomics/main.cpp | 230 + test_conformance/c11_atomics/test_atomics.cpp | 2142 +++ test_conformance/clcpp/CMakeLists.txt | 21 + .../clcpp/address_spaces/CMakeLists.txt | 12 + .../clcpp/address_spaces/common.hpp | 203 + .../clcpp/address_spaces/main.cpp | 30 + .../address_spaces/test_pointer_types.hpp | 411 + .../address_spaces/test_storage_types.hpp | 418 + test_conformance/clcpp/api/CMakeLists.txt | 12 + test_conformance/clcpp/api/main.cpp | 32 + test_conformance/clcpp/api/test_ctors.hpp | 481 + .../clcpp/api/test_ctors_dtors.hpp | 185 + test_conformance/clcpp/api/test_dtors.hpp | 553 + .../clcpp/api/test_spec_consts.hpp | 474 + test_conformance/clcpp/atomics/CMakeLists.txt | 12 + .../clcpp/atomics/atomic_fetch.hpp | 306 + test_conformance/clcpp/atomics/main.cpp | 30 + .../clcpp/attributes/CMakeLists.txt | 12 + test_conformance/clcpp/attributes/main.cpp | 32 + .../clcpp/attributes/test_ivdep.hpp | 418 + .../clcpp/attributes/test_max_size.hpp | 266 + .../test_required_num_sub_groups.hpp | 285 + test_conformance/clcpp/common.hpp | 51 + .../clcpp/common_funcs/CMakeLists.txt | 12 + .../clcpp/common_funcs/common_funcs.hpp | 417 + test_conformance/clcpp/common_funcs/main.cpp | 48 + test_conformance/clcpp/convert/CMakeLists.txt | 12 + .../clcpp/convert/convert_cast.hpp | 309 + test_conformance/clcpp/convert/main.cpp | 30 + .../clcpp/device_queue/CMakeLists.txt | 12 + test_conformance/clcpp/device_queue/main.cpp | 30 + .../clcpp/device_queue/test_enqueue.hpp | 699 + test_conformance/clcpp/funcs_test_utils.hpp | 72 + .../clcpp/geometric_funcs/CMakeLists.txt | 12 + .../geometric_funcs/fast_geometric_funcs.hpp | 229 + .../clcpp/geometric_funcs/geometric_funcs.hpp | 389 + .../clcpp/geometric_funcs/main.cpp | 49 + test_conformance/clcpp/images/CMakeLists.txt | 15 + test_conformance/clcpp/images/common.hpp | 198 + test_conformance/clcpp/images/main.cpp | 32 + test_conformance/clcpp/images/test_read.hpp | 307 + test_conformance/clcpp/images/test_sample.hpp | 363 + test_conformance/clcpp/images/test_write.hpp | 327 + .../clcpp/integer_funcs/24bit_funcs.hpp | 142 + .../clcpp/integer_funcs/CMakeLists.txt | 12 + .../clcpp/integer_funcs/bitwise_funcs.hpp | 232 + .../clcpp/integer_funcs/common.hpp | 26 + test_conformance/clcpp/integer_funcs/main.cpp | 31 + .../clcpp/integer_funcs/numeric_funcs.hpp | 703 + .../clcpp/math_funcs/CMakeLists.txt | 12 + test_conformance/clcpp/math_funcs/common.hpp | 347 + .../clcpp/math_funcs/comparison_funcs.hpp | 59 + .../clcpp/math_funcs/exponential_funcs.hpp | 139 + .../clcpp/math_funcs/floating_point_funcs.hpp | 733 + .../clcpp/math_funcs/half_math_funcs.hpp | 106 + .../clcpp/math_funcs/logarithmic_funcs.hpp | 260 + test_conformance/clcpp/math_funcs/main.cpp | 55 + .../clcpp/math_funcs/other_funcs.hpp | 75 + .../clcpp/math_funcs/power_funcs.hpp | 153 + .../clcpp/math_funcs/reference.hpp | 315 + .../clcpp/math_funcs/trigonometric_funcs.hpp | 222 + test_conformance/clcpp/pipes/CMakeLists.txt | 12 + test_conformance/clcpp/pipes/main.cpp | 30 + test_conformance/clcpp/pipes/test_pipes.hpp | 632 + .../program_scope_ctors_dtors/CMakeLists.txt | 12 + .../program_scope_ctors_dtors/common.hpp | 284 + .../clcpp/program_scope_ctors_dtors/main.cpp | 29 + .../test_ctors_dtors.hpp | 324 + .../clcpp/reinterpret/CMakeLists.txt | 12 + .../clcpp/reinterpret/as_type.hpp | 223 + test_conformance/clcpp/reinterpret/main.cpp | 30 + .../clcpp/relational_funcs/CMakeLists.txt | 12 + .../clcpp/relational_funcs/common.hpp | 112 + .../relational_funcs/comparison_funcs.hpp | 150 + .../clcpp/relational_funcs/main.cpp | 31 + .../clcpp/relational_funcs/select_funcs.hpp | 158 + .../clcpp/relational_funcs/test_funcs.hpp | 336 + .../clcpp/spec_constants/CMakeLists.txt | 12 + .../clcpp/spec_constants/common.hpp | 257 + .../clcpp/spec_constants/main.cpp | 31 + .../test_spec_consts_attributes.hpp | 281 + .../spec_constants/test_spec_consts_if.hpp | 161 + .../test_spec_consts_init_vars.hpp | 174 + .../clcpp/subgroups/CMakeLists.txt | 12 + test_conformance/clcpp/subgroups/common.hpp | 97 + test_conformance/clcpp/subgroups/main.cpp | 34 + .../clcpp/subgroups/test_sg_all.hpp | 219 + .../clcpp/subgroups/test_sg_any.hpp | 219 + .../clcpp/subgroups/test_sg_broadcast.hpp | 204 + .../clcpp/subgroups/test_sg_reduce.hpp | 345 + .../subgroups/test_sg_scan_exclusive.hpp | 325 + .../subgroups/test_sg_scan_inclusive.hpp | 332 + .../clcpp/synchronization/CMakeLists.txt | 12 + .../clcpp/synchronization/main.cpp | 32 + .../synchronization/named_barrier/common.hpp | 171 + .../named_barrier/test_named_barrier.hpp | 490 + .../named_barrier/test_spec_example.hpp | 323 + .../test_sub_group_barrier.hpp | 342 + .../test_work_group_barrier.hpp | 330 + .../clcpp/utils_common/errors.hpp | 134 + .../clcpp/utils_common/is_vector_type.hpp | 60 + .../clcpp/utils_common/kernel_helpers.hpp | 50 + .../clcpp/utils_common/make_vector_type.hpp | 65 + .../clcpp/utils_common/scalar_type.hpp | 64 + .../clcpp/utils_common/string.hpp | 70 + .../clcpp/utils_common/type_name.hpp | 65 + .../clcpp/utils_common/type_supported.hpp | 106 + .../clcpp/utils_common/vector_size.hpp | 61 + test_conformance/clcpp/utils_test/binary.hpp | 308 + test_conformance/clcpp/utils_test/compare.hpp | 161 + .../utils_test/detail/base_func_type.hpp | 112 + .../clcpp/utils_test/detail/vec_helpers.hpp | 104 + .../clcpp/utils_test/generate_inputs.hpp | 331 + test_conformance/clcpp/utils_test/ternary.hpp | 368 + test_conformance/clcpp/utils_test/unary.hpp | 261 + .../clcpp/vload_vstore/CMakeLists.txt | 12 + .../clcpp/vload_vstore/common.hpp | 81 + .../clcpp/vload_vstore/half_utils.hpp | 136 + test_conformance/clcpp/vload_vstore/main.cpp | 30 + .../clcpp/vload_vstore/vload_funcs.hpp | 363 + .../clcpp/vload_vstore/vstore_funcs.hpp | 348 + .../clcpp/workgroups/CMakeLists.txt | 12 + test_conformance/clcpp/workgroups/common.hpp | 97 + test_conformance/clcpp/workgroups/main.cpp | 34 + .../clcpp/workgroups/test_wg_all.hpp | 218 + .../clcpp/workgroups/test_wg_any.hpp | 218 + .../clcpp/workgroups/test_wg_broadcast.hpp | 458 + .../clcpp/workgroups/test_wg_reduce.hpp | 331 + .../workgroups/test_wg_scan_exclusive.hpp | 324 + .../workgroups/test_wg_scan_inclusive.hpp | 324 + .../clcpp/workitems/CMakeLists.txt | 12 + test_conformance/clcpp/workitems/main.cpp | 30 + .../clcpp/workitems/test_workitems.hpp | 418 + test_conformance/commonfns/CMakeLists.txt | 33 + test_conformance/commonfns/Jamfile | 33 + test_conformance/commonfns/Makefile | 45 + test_conformance/commonfns/main.c | 87 + test_conformance/commonfns/procs.h | 54 + test_conformance/commonfns/test_binary_fn.c | 260 + test_conformance/commonfns/test_clamp.c | 311 + test_conformance/commonfns/test_degrees.c | 472 + test_conformance/commonfns/test_fmax.c | 235 + test_conformance/commonfns/test_fmaxf.c | 243 + test_conformance/commonfns/test_fmin.c | 239 + test_conformance/commonfns/test_fminf.c | 237 + test_conformance/commonfns/test_max.c | 60 + test_conformance/commonfns/test_maxf.c | 64 + test_conformance/commonfns/test_min.c | 56 + test_conformance/commonfns/test_minf.c | 70 + test_conformance/commonfns/test_mix.c | 195 + test_conformance/commonfns/test_radians.c | 470 + test_conformance/commonfns/test_sign.c | 440 + test_conformance/commonfns/test_smoothstep.c | 278 + test_conformance/commonfns/test_smoothstepf.c | 255 + test_conformance/commonfns/test_step.c | 541 + test_conformance/commonfns/test_stepf.c | 540 + test_conformance/compatibility/CMakeLists.txt | 1 + .../compatibility/test_common/Makefile | 26 + .../compatibility/test_common/gl/gl_headers.h | 52 + .../compatibility/test_common/gl/helpers.cpp | 1622 ++ .../compatibility/test_common/gl/helpers.h | 283 + .../compatibility/test_common/gl/setup.h | 48 + .../test_common/gl/setup_osx.cpp | 156 + .../test_common/gl/setup_win32.cpp | 204 + .../test_common/gl/setup_x11.cpp | 122 + .../compatibility/test_common/harness/Jamfile | 18 + .../test_common/harness/Makefile | 41 + .../test_common/harness/ThreadPool.c | 899 ++ .../test_common/harness/ThreadPool.h | 76 + .../test_common/harness/clImageHelper.h | 253 + .../test_common/harness/compat.h | 216 + .../test_common/harness/conversions.c | 1198 ++ .../test_common/harness/conversions.h | 126 + .../test_common/harness/errorHelpers.c | 579 + .../test_common/harness/errorHelpers.h | 149 + .../test_common/harness/fpcontrol.h | 104 + .../test_common/harness/genericThread.cpp | 53 + .../test_common/harness/genericThread.h | 42 + .../test_common/harness/imageHelpers.cpp | 249 + .../test_common/harness/imageHelpers.h | 37 + .../test_common/harness/kernelHelpers.c | 684 + .../test_common/harness/kernelHelpers.h | 128 + .../test_common/harness/mingw_compat.c | 59 + .../test_common/harness/mingw_compat.h | 31 + .../compatibility/test_common/harness/msvc9.c | 754 + .../test_common/harness/mt19937.c | 274 + .../test_common/harness/mt19937.h | 99 + .../test_common/harness/ref_counting.h | 49 + .../test_common/harness/rounding_mode.c | 175 + .../test_common/harness/rounding_mode.h | 71 + .../test_common/harness/testHarness.c | 842 ++ .../test_common/harness/testHarness.h | 100 + .../test_common/harness/test_mt19937.c | 51 + .../test_common/harness/threadTesting.c | 106 + .../test_common/harness/threadTesting.h | 32 + .../test_common/harness/typeWrappers.cpp | 481 + .../test_common/harness/typeWrappers.h | 333 + .../test_conformance/CMakeLists.txt | 2 + .../test_conformance/api/CMakeLists.txt | 34 + .../test_conformance/api/Jamfile | 27 + .../test_conformance/api/Makefile | 61 + .../compatibility/test_conformance/api/main.c | 214 + .../test_conformance/api/procs.h | 108 + .../test_conformance/api/testBase.h | 31 + .../test_conformance/api/test_api_min_max.c | 2059 +++ .../test_conformance/api/test_binary.cpp | 226 + .../test_conformance/api/test_bool.c | 52 + .../api/test_create_context_from_type.cpp | 130 + .../api/test_create_kernels.c | 643 + ...ice_min_data_type_align_size_alignment.cpp | 60 + .../api/test_kernel_arg_changes.cpp | 141 + .../api/test_kernel_arg_info.c | 5192 +++++++ .../api/test_kernel_arg_multi_setup.cpp | 277 + .../test_conformance/api/test_kernels.c | 704 + .../api/test_mem_object_info.cpp | 750 + .../test_conformance/api/test_mem_objects.cpp | 108 + .../api/test_native_kernel.cpp | 121 + .../api/test_null_buffer_arg.c | 162 + .../test_conformance/api/test_platform.cpp | 289 + .../test_conformance/api/test_queries.cpp | 635 + .../test_conformance/api/test_retain.cpp | 234 + .../api/test_retain_program.c | 109 + .../test_conformance/basic/CMakeLists.txt | 65 + .../test_conformance/basic/Jamfile | 75 + .../test_conformance/basic/Makefile | 94 + .../test_conformance/basic/main.c | 263 + .../test_conformance/basic/procs.h | 142 + .../test_conformance/basic/run_array | 3 + .../basic/run_array_image_copy | 3 + .../test_conformance/basic/run_image | 17 + .../basic/run_multi_read_image | 4 + .../test_conformance/basic/test_arraycopy.c | 201 + .../basic/test_arrayimagecopy.c | 143 + .../basic/test_arrayimagecopy3d.c | 144 + .../basic/test_arrayreadwrite.c | 94 + .../test_conformance/basic/test_astype.cpp | 289 + .../basic/test_async_copy.cpp | 276 + .../basic/test_async_strided_copy.cpp | 267 + .../test_conformance/basic/test_barrier.c | 158 + .../basic/test_basic_parameter_types.c | 302 + .../basic/test_bufferreadwriterect.c | 529 + .../test_conformance/basic/test_constant.c | 261 + .../basic/test_constant_source.cpp | 100 + .../basic/test_createkernelsinprogram.c | 121 + .../basic/test_enqueue_map.cpp | 253 + .../basic/test_explicit_s2v.cpp | 384 + .../test_conformance/basic/test_float2int.c | 160 + .../basic/test_fpmath_float.c | 270 + .../basic/test_fpmath_float2.c | 268 + .../basic/test_fpmath_float4.c | 269 + .../basic/test_global_work_offsets.cpp | 284 + .../test_conformance/basic/test_hiloeo.c | 421 + .../test_conformance/basic/test_hostptr.c | 276 + .../test_conformance/basic/test_if.c | 165 + .../basic/test_image_multipass.c | 643 + .../test_conformance/basic/test_image_param.c | 251 + .../test_conformance/basic/test_image_r8.c | 176 + .../basic/test_imagearraycopy.c | 146 + .../basic/test_imagearraycopy3d.c | 144 + .../test_conformance/basic/test_imagecopy.c | 234 + .../test_conformance/basic/test_imagecopy3d.c | 237 + .../test_conformance/basic/test_imagedim.c | 514 + .../test_conformance/basic/test_imagenpot.c | 220 + .../basic/test_imagerandomcopy.c | 269 + .../basic/test_imagereadwrite.c | 417 + .../basic/test_imagereadwrite3d.c | 417 + .../test_conformance/basic/test_int2float.c | 159 + .../test_conformance/basic/test_intmath_int.c | 389 + .../basic/test_intmath_int2.c | 388 + .../basic/test_intmath_int4.c | 387 + .../basic/test_intmath_long.c | 397 + .../basic/test_intmath_long2.c | 395 + .../basic/test_intmath_long4.c | 395 + .../test_kernel_call_kernel_function.cpp | 253 + .../basic/test_kernel_memory_alignment.cpp | 572 + .../test_conformance/basic/test_local.c | 372 + .../basic/test_local_kernel_scope.cpp | 138 + .../test_conformance/basic/test_loop.c | 184 + .../basic/test_multireadimagemultifmt.c | 230 + .../basic/test_multireadimageonefmt.c | 198 + .../basic/test_numeric_constants.cpp | 710 + .../test_conformance/basic/test_pointercast.c | 140 + .../basic/test_preprocessors.cpp | 393 + .../test_conformance/basic/test_readimage.c | 244 + .../test_conformance/basic/test_readimage3d.c | 230 + .../basic/test_readimage3d_fp32.c | 147 + .../basic/test_readimage3d_int16.c | 146 + .../basic/test_readimage_fp32.c | 167 + .../basic/test_readimage_int16.c | 166 + .../test_conformance/basic/test_sizeof.c | 396 + .../basic/test_vec_type_hint.c | 97 + .../basic/test_vector_creation.cpp | 406 + .../test_conformance/basic/test_vloadstore.c | 985 ++ .../basic/test_work_item_functions.cpp | 177 + .../test_conformance/basic/test_writeimage.c | 300 + .../basic/test_writeimage_fp32.c | 188 + .../basic/test_writeimage_int16.c | 194 + .../test_conformance/images/image_helpers.h | 534 + test_conformance/compiler/CMakeLists.txt | 25 + test_conformance/compiler/Jamfile | 27 + test_conformance/compiler/Makefile | 51 + .../includeTestDirectory/testIncludeFile.h | 16 + test_conformance/compiler/main.c | 168 + test_conformance/compiler/procs.h | 88 + .../testIncludeFile.h | 16 + test_conformance/compiler/testBase.h | 31 + test_conformance/compiler/test_async_build.c | 94 + .../compiler/test_build_helpers.c | 571 + .../compiler/test_build_options.cpp | 410 + test_conformance/compiler/test_compile.c | 3170 ++++ .../test_compiler_defines_for_extensions.cpp | 420 + test_conformance/compiler/test_image_macro.c | 95 + .../compiler/test_pragma_unroll.c | 290 + test_conformance/compiler/test_preprocessor.c | 342 + test_conformance/computeinfo/CMakeLists.txt | 12 + test_conformance/computeinfo/Jamfile | 13 + test_conformance/computeinfo/Makefile | 32 + test_conformance/computeinfo/main.c | 873 ++ test_conformance/contractions/CMakeLists.txt | 15 + test_conformance/contractions/Jamfile | 13 + test_conformance/contractions/Makefile | 32 + test_conformance/contractions/contractions.c | 1217 ++ test_conformance/conversions/CMakeLists.txt | 48 + test_conformance/conversions/Jamfile | 17 + test_conformance/conversions/Makefile | 50 + test_conformance/conversions/Sleep.c | 120 + test_conformance/conversions/Sleep.h | 32 + .../conversions/basic_test_conversions.c | 2246 +++ .../conversions/basic_test_conversions.h | 73 + test_conformance/conversions/fplib.c | 221 + test_conformance/conversions/fplib.h | 29 + test_conformance/conversions/run_batch | 16 + .../conversions/test_conversions.c | 1865 +++ test_conformance/d3d10/CMakeLists.txt | 47 + test_conformance/d3d10/buffer.cpp | 310 + test_conformance/d3d10/harness.cpp | 413 + test_conformance/d3d10/harness.h | 213 + test_conformance/d3d10/main.cpp | 433 + test_conformance/d3d10/misc.cpp | 259 + test_conformance/d3d10/texture2d.cpp | 694 + test_conformance/d3d10/texture3d.cpp | 491 + test_conformance/d3d11/CMakeLists.txt | 47 + test_conformance/d3d11/buffer.cpp | 321 + test_conformance/d3d11/harness.cpp | 456 + test_conformance/d3d11/harness.h | 221 + test_conformance/d3d11/main.cpp | 464 + test_conformance/d3d11/misc.cpp | 224 + test_conformance/d3d11/texture2d.cpp | 749 + test_conformance/d3d11/texture3d.cpp | 489 + .../device_execution/CMakeLists.txt | 27 + test_conformance/device_execution/Makefile | 52 + .../device_execution/device_info.cpp | 106 + .../device_execution/device_queue.cpp | 188 + .../device_execution/enqueue_block.cpp | 684 + .../device_execution/enqueue_flags.cpp | 756 + .../device_execution/enqueue_multi_queue.cpp | 198 + .../device_execution/enqueue_ndrange.cpp | 681 + .../device_execution/enqueue_wg_size.cpp | 1724 +++ .../device_execution/execute_block.cpp | 1050 ++ .../device_execution/host_multi_queue.cpp | 228 + .../device_execution/host_queue_order.cpp | 185 + test_conformance/device_execution/main.c | 101 + .../device_execution/nested_blocks.cpp | 374 + test_conformance/device_execution/procs.h | 40 + test_conformance/device_execution/utils.cpp | 76 + test_conformance/device_execution/utils.h | 73 + .../device_partition/CMakeLists.txt | 17 + test_conformance/device_partition/Jamfile | 32 + test_conformance/device_partition/Makefile | 45 + test_conformance/device_partition/main.c | 60 + test_conformance/device_partition/procs.h | 29 + test_conformance/device_partition/testBase.h | 31 + .../test_device_partition.cpp | 589 + test_conformance/device_timer/CMakeLists.txt | 13 + test_conformance/device_timer/main.c | 45 + test_conformance/device_timer/procs.h | 24 + .../device_timer/test_device_timer.c | 165 + test_conformance/events/CMakeLists.txt | 25 + test_conformance/events/Jamfile | 18 + test_conformance/events/Makefile | 51 + test_conformance/events/action_classes.cpp | 658 + test_conformance/events/action_classes.h | 326 + test_conformance/events/main.c | 108 + test_conformance/events/procs.h | 61 + test_conformance/events/testBase.h | 31 + test_conformance/events/test_callbacks.cpp | 341 + .../events/test_event_dependencies.cpp | 509 + test_conformance/events/test_events.cpp | 682 + test_conformance/events/test_userevents.cpp | 293 + .../events/test_userevents_multithreaded.cpp | 82 + test_conformance/events/test_waitlists.cpp | 322 + .../generic_address_space/CMakeLists.txt | 18 + .../generic_address_space/Makefile | 44 + .../generic_address_space/advanced_tests.cpp | 1031 ++ test_conformance/generic_address_space/base.h | 39 + .../generic_address_space/basic_tests.cpp | 877 ++ .../generic_address_space/main.cpp | 106 + .../generic_address_space/stress_tests.cpp | 173 + test_conformance/geometrics/CMakeLists.txt | 24 + test_conformance/geometrics/Jamfile | 17 + test_conformance/geometrics/Makefile | 44 + test_conformance/geometrics/main.c | 61 + test_conformance/geometrics/procs.h | 38 + test_conformance/geometrics/testBase.h | 31 + .../geometrics/test_geometrics.cpp | 1109 ++ .../geometrics/test_geometrics_double.cpp | 941 ++ test_conformance/gl/CMakeLists.txt | 63 + test_conformance/gl/GLEW/GL/glew.h | 12262 ++++++++++++++++ test_conformance/gl/GLEW/GL/glxew.h | 1397 ++ test_conformance/gl/GLEW/GL/wglew.h | 1165 ++ test_conformance/gl/GLEW/glew.c | 10835 ++++++++++++++ test_conformance/gl/Jamfile | 28 + test_conformance/gl/Makefile | 62 + test_conformance/gl/common.h | 78 + test_conformance/gl/helpers.cpp | 657 + test_conformance/gl/main.cpp | 453 + test_conformance/gl/procs.h | 140 + test_conformance/gl/testBase.h | 65 + test_conformance/gl/test_buffers.cpp | 357 + test_conformance/gl/test_fence_sync.cpp | 730 + test_conformance/gl/test_image_methods.cpp | 405 + test_conformance/gl/test_images_1D.cpp | 141 + test_conformance/gl/test_images_1Darray.cpp | 90 + test_conformance/gl/test_images_2D.cpp | 190 + test_conformance/gl/test_images_2Darray.cpp | 93 + test_conformance/gl/test_images_3D.cpp | 109 + test_conformance/gl/test_images_depth.cpp | 162 + .../gl/test_images_getinfo_common.cpp | 262 + .../gl/test_images_multisample.cpp | 118 + .../gl/test_images_read_common.cpp | 736 + .../gl/test_images_write_common.cpp | 868 ++ test_conformance/gl/test_renderbuffer.cpp | 479 + .../gl/test_renderbuffer_info.cpp | 133 + test_conformance/gles/CMakeLists.txt | 34 + test_conformance/gles/helpers.cpp | 481 + test_conformance/gles/main.cpp | 402 + test_conformance/gles/procs.h | 35 + test_conformance/gles/setup_egl.cpp | 215 + test_conformance/gles/testBase.h | 71 + test_conformance/gles/test_buffers.cpp | 402 + test_conformance/gles/test_fence_sync.cpp | 664 + test_conformance/gles/test_images_2D.cpp | 749 + test_conformance/gles/test_images_2D_info.cpp | 256 + test_conformance/gles/test_images_3D.cpp | 268 + test_conformance/gles/test_images_3D_info.cpp | 166 + test_conformance/gles/test_renderbuffer.cpp | 373 + .../gles/test_renderbuffer_info.cpp | 119 + test_conformance/half/CMakeLists.txt | 17 + test_conformance/half/Jamfile | 22 + test_conformance/half/Makefile | 45 + .../half/Test_half.xcodeproj/project.pbxproj | 292 + test_conformance/half/Test_roundTrip.c | 398 + test_conformance/half/Test_vLoadHalf.c | 628 + test_conformance/half/Test_vStoreHalf.c | 1947 +++ test_conformance/half/cl_utils.c | 493 + test_conformance/half/cl_utils.h | 162 + test_conformance/half/main.c | 434 + test_conformance/half/test_config.h | 41 + test_conformance/half/tests.h | 41 + test_conformance/headers/CMakeLists.txt | 87 + test_conformance/headers/Makefile | 38 + test_conformance/headers/README.txt | 26 + test_conformance/headers/test_cl.h.c | 27 + test_conformance/headers/test_cl_gl.h.c | 27 + test_conformance/headers/test_cl_platform.h.c | 27 + test_conformance/headers/test_headers.c | 650 + test_conformance/headers/test_opencl.h.c | 27 + test_conformance/images/CMakeLists.txt | 15 + test_conformance/images/Jamfile | 9 + test_conformance/images/Makefile | 31 + .../images/clCopyImage/CMakeLists.txt | 28 + test_conformance/images/clCopyImage/Jamfile | 19 + test_conformance/images/clCopyImage/Makefile | 56 + test_conformance/images/clCopyImage/main.cpp | 265 + .../images/clCopyImage/test_copy_1D.cpp | 235 + .../images/clCopyImage/test_copy_1D_array.cpp | 248 + .../images/clCopyImage/test_copy_2D.cpp | 248 + .../clCopyImage/test_copy_2D_2D_array.cpp | 419 + .../images/clCopyImage/test_copy_2D_3D.cpp | 401 + .../images/clCopyImage/test_copy_2D_array.cpp | 205 + .../images/clCopyImage/test_copy_3D.cpp | 192 + .../clCopyImage/test_copy_3D_2D_array.cpp | 442 + .../images/clCopyImage/test_copy_generic.cpp | 763 + .../images/clCopyImage/test_loops.cpp | 274 + .../images/clFillImage/CMakeLists.txt | 27 + test_conformance/images/clFillImage/Jamfile | 19 + test_conformance/images/clFillImage/Makefile | 53 + test_conformance/images/clFillImage/main.cpp | 252 + .../images/clFillImage/test_fill_1D.cpp | 181 + .../images/clFillImage/test_fill_1D_array.cpp | 193 + .../images/clFillImage/test_fill_2D.cpp | 189 + .../images/clFillImage/test_fill_2D_array.cpp | 200 + .../images/clFillImage/test_fill_3D.cpp | 200 + .../images/clFillImage/test_fill_generic.cpp | 556 + .../images/clFillImage/test_loops.cpp | 327 + .../images/clGetInfo/CMakeLists.txt | 22 + test_conformance/images/clGetInfo/Jamfile | 18 + test_conformance/images/clGetInfo/Makefile | 50 + test_conformance/images/clGetInfo/main.cpp | 287 + test_conformance/images/clGetInfo/test_1D.cpp | 138 + .../images/clGetInfo/test_1D_2D_array.cpp | 279 + test_conformance/images/clGetInfo/test_2D.cpp | 385 + test_conformance/images/clGetInfo/test_3D.cpp | 158 + .../images/clGetInfo/test_loops.cpp | 228 + .../images/clReadWriteImage/CMakeLists.txt | 24 + .../images/clReadWriteImage/Jamfile | 18 + .../images/clReadWriteImage/Makefile | 51 + .../images/clReadWriteImage/main.cpp | 265 + .../images/clReadWriteImage/test_loops.cpp | 227 + .../images/clReadWriteImage/test_read_1D.cpp | 273 + .../clReadWriteImage/test_read_1D_array.cpp | 287 + .../images/clReadWriteImage/test_read_2D.cpp | 286 + .../clReadWriteImage/test_read_2D_array.cpp | 272 + .../images/clReadWriteImage/test_read_3D.cpp | 276 + .../kernel_image_methods/CMakeLists.txt | 23 + .../images/kernel_image_methods/Jamfile | 18 + .../images/kernel_image_methods/Makefile | 51 + .../images/kernel_image_methods/main.cpp | 262 + .../images/kernel_image_methods/test_1D.cpp | 237 + .../kernel_image_methods/test_1D_array.cpp | 255 + .../images/kernel_image_methods/test_2D.cpp | 295 + .../kernel_image_methods/test_2D_array.cpp | 272 + .../images/kernel_image_methods/test_3D.cpp | 131 + .../kernel_image_methods/test_loops.cpp | 219 + .../images/kernel_read_write/CMakeLists.txt | 29 + .../images/kernel_read_write/Jamfile | 19 + .../images/kernel_read_write/Makefile | 56 + .../images/kernel_read_write/main.cpp | 659 + .../kernel_read_write/test_iterations.cpp | 1765 +++ .../images/kernel_read_write/test_loops.cpp | 466 + .../images/kernel_read_write/test_read_1D.cpp | 1169 ++ .../kernel_read_write/test_read_1D_array.cpp | 1284 ++ .../kernel_read_write/test_read_2D_array.cpp | 1502 ++ .../images/kernel_read_write/test_read_3D.cpp | 1328 ++ .../kernel_read_write/test_write_1D.cpp | 696 + .../kernel_read_write/test_write_1D_array.cpp | 723 + .../kernel_read_write/test_write_2D_array.cpp | 771 + .../kernel_read_write/test_write_3D.cpp | 768 + .../kernel_read_write/test_write_image.cpp | 887 ++ .../images/samplerlessReads/CMakeLists.txt | 24 + .../images/samplerlessReads/Jamfile | 19 + .../images/samplerlessReads/Makefile | 52 + .../images/samplerlessReads/main.cpp | 303 + .../samplerlessReads/test_iterations.cpp | 337 + .../images/samplerlessReads/test_loops.cpp | 305 + .../images/samplerlessReads/test_read_1D.cpp | 332 + .../samplerlessReads/test_read_1D_array.cpp | 336 + .../samplerlessReads/test_read_1D_buffer.cpp | 324 + .../samplerlessReads/test_read_2D_array.cpp | 334 + .../images/samplerlessReads/test_read_3D.cpp | 337 + test_conformance/images/testBase.h | 78 + test_conformance/integer_ops/CMakeLists.txt | 26 + test_conformance/integer_ops/Jamfile | 28 + test_conformance/integer_ops/Makefile | 52 + test_conformance/integer_ops/main.c | 347 + test_conformance/integer_ops/procs.h | 143 + test_conformance/integer_ops/testBase.h | 31 + test_conformance/integer_ops/test_abs.c | 335 + test_conformance/integer_ops/test_absdiff.c | 374 + test_conformance/integer_ops/test_add_sat.c | 378 + .../integer_ops/test_int_basic_ops.c | 1551 ++ .../integer_ops/test_integers.cpp | 1889 +++ test_conformance/integer_ops/test_intmad24.c | 365 + test_conformance/integer_ops/test_intmul24.c | 390 + test_conformance/integer_ops/test_popcount.c | 248 + test_conformance/integer_ops/test_sub_sat.c | 376 + .../integer_ops/test_unary_ops.cpp | 211 + .../integer_ops/test_upsample.cpp | 263 + .../verification_and_generation_functions.c | 1675 +++ .../math_brute_force/CMakeLists.txt | 86 + .../math_brute_force/FunctionList.c | 180 + .../math_brute_force/FunctionList.h | 99 + test_conformance/math_brute_force/Jamfile | 36 + test_conformance/math_brute_force/Makefile | 33 + test_conformance/math_brute_force/README.txt | 150 + test_conformance/math_brute_force/Sleep.c | 118 + test_conformance/math_brute_force/Sleep.h | 24 + test_conformance/math_brute_force/Utility.c | 169 + test_conformance/math_brute_force/Utility.h | 280 + test_conformance/math_brute_force/binary.c | 1537 ++ .../math_brute_force/binaryOperator.c | 1455 ++ test_conformance/math_brute_force/binary_i.c | 1214 ++ .../math_brute_force/binary_two_results_i.c | 1133 ++ test_conformance/math_brute_force/i_unary.c | 629 + .../math_brute_force/macro_binary.c | 1215 ++ .../math_brute_force/macro_unary.c | 965 ++ test_conformance/math_brute_force/mad.c | 1131 ++ test_conformance/math_brute_force/main.c | 1571 ++ .../math_brute_force/reference_math.c | 5499 +++++++ .../math_brute_force/reference_math.h | 232 + .../run_math_brute_force_in_parallel.py | 110 + test_conformance/math_brute_force/ternary.c | 1361 ++ test_conformance/math_brute_force/unary.c | 1191 ++ .../math_brute_force/unary_two_results.c | 993 ++ .../math_brute_force/unary_two_results_i.c | 802 + test_conformance/math_brute_force/unary_u.c | 694 + .../mem_host_flags/CMakeLists.txt | 20 + .../mem_host_flags/C_host_memory_block.h | 252 + test_conformance/mem_host_flags/Makefile | 46 + test_conformance/mem_host_flags/checker.h | 326 + .../checker_image_mem_host_no_access.hpp | 151 + .../checker_image_mem_host_read_only.hpp | 281 + .../checker_image_mem_host_write_only.hpp | 293 + .../checker_mem_host_no_access.hpp | 202 + .../checker_mem_host_read_only.hpp | 264 + .../checker_mem_host_write_only.hpp | 333 + test_conformance/mem_host_flags/main.cpp | 68 + .../mem_host_flags/mem_host_buffer.cpp | 487 + .../mem_host_flags/mem_host_image.cpp | 364 + test_conformance/mem_host_flags/procs.h | 45 + test_conformance/mem_host_flags/testBase.h | 40 + .../multiple_device_context/CMakeLists.txt | 35 + .../multiple_device_context/Jamfile | 17 + .../multiple_device_context/Makefile | 46 + .../multiple_device_context/main.c | 62 + .../multiple_device_context/procs.h | 31 + .../multiple_device_context/testBase.h | 31 + .../test_multiple_contexts.c | 529 + .../test_multiple_devices.cpp | 236 + .../non_uniform_work_group/CMakeLists.txt | 20 + .../non_uniform_work_group/Makefile | 46 + .../TestNonUniformWorkGroup.cpp | 751 + .../TestNonUniformWorkGroup.h | 146 + .../non_uniform_work_group/main.cpp | 88 + .../non_uniform_work_group/procs.h | 32 + .../test_advanced_2d.cpp | 383 + .../test_advanced_3d.cpp | 410 + .../test_advanced_other.cpp | 279 + .../non_uniform_work_group/test_basic.cpp | 398 + .../non_uniform_work_group/tools.cpp | 274 + .../non_uniform_work_group/tools.h | 109 + ...opencl_conformance_tests_21_full_spirv.csv | 122 + ...encl_conformance_tests_21_legacy_wimpy.csv | 103 + .../opencl_conformance_tests_22.csv | 45 + .../opencl_conformance_tests_conversions.csv | 4 + .../opencl_conformance_tests_d3d.csv | 7 + .../opencl_conformance_tests_full.csv | 117 + ...ance_tests_full_no_math_or_conversions.csv | 92 + ...pencl_conformance_tests_generate_spirv.csv | 73 + .../opencl_conformance_tests_math.csv | 4 + .../opencl_conformance_tests_quick.csv | 90 + test_conformance/pipes/CMakeLists.txt | 22 + test_conformance/pipes/kernels.h | 130 + test_conformance/pipes/main.c | 147 + test_conformance/pipes/procs.h | 92 + test_conformance/pipes/test_pipe_info.c | 109 + test_conformance/pipes/test_pipe_limits.c | 1085 ++ .../pipes/test_pipe_query_functions.c | 544 + test_conformance/pipes/test_pipe_read_write.c | 1809 +++ .../pipes/test_pipe_readwrite_errors.c | 312 + test_conformance/pipes/test_pipe_subgroups.c | 339 + test_conformance/printf/CMakeLists.txt | 18 + test_conformance/printf/Jamfile | 5 + test_conformance/printf/Makefile | 44 + test_conformance/printf/test_printf.c | 813 + test_conformance/printf/test_printf.h | 133 + test_conformance/printf/util_printf.c | 894 ++ test_conformance/profiling/CMakeLists.txt | 23 + test_conformance/profiling/Jamfile | 22 + test_conformance/profiling/Makefile | 45 + test_conformance/profiling/copy.c | 869 ++ test_conformance/profiling/execute.c | 440 + .../profiling/execute_multipass.c | 314 + test_conformance/profiling/main.c | 173 + test_conformance/profiling/procs.h | 65 + test_conformance/profiling/readArray.c | 997 ++ test_conformance/profiling/readImage.c | 386 + test_conformance/profiling/writeArray.c | 1375 ++ test_conformance/profiling/writeImage.c | 683 + test_conformance/relationals/CMakeLists.txt | 20 + test_conformance/relationals/Jamfile | 19 + test_conformance/relationals/Makefile | 46 + test_conformance/relationals/main.c | 100 + test_conformance/relationals/procs.h | 56 + test_conformance/relationals/testBase.h | 31 + .../relationals/test_comparisons_double.cpp | 361 + .../relationals/test_comparisons_float.cpp | 361 + .../relationals/test_relationals.cpp | 785 + .../relationals/test_shuffles.cpp | 932 ++ test_conformance/run_conformance.py | 357 + test_conformance/select/CMakeLists.txt | 14 + test_conformance/select/Jamfile | 21 + test_conformance/select/Makefile | 33 + test_conformance/select/test_select.c | 755 + test_conformance/select/test_select.h | 117 + test_conformance/select/util_select.c | 734 + test_conformance/spir/CMakeLists.txt | 45 + test_conformance/spir/Makefile | 45 + test_conformance/spir/api.zip | Bin 0 -> 1089254 bytes test_conformance/spir/atomics.zip | Bin 0 -> 159717 bytes test_conformance/spir/basic.zip | Bin 0 -> 2583318 bytes test_conformance/spir/binary_type.zip | Bin 0 -> 2777 bytes test_conformance/spir/commonfns.zip | Bin 0 -> 321005 bytes test_conformance/spir/compile_and_link.zip | Bin 0 -> 21576 bytes test_conformance/spir/conversions.zip | Bin 0 -> 6386745 bytes test_conformance/spir/datagen.cpp | 644 + test_conformance/spir/datagen.h | 1066 ++ test_conformance/spir/enum_values.zip | Bin 0 -> 10746 bytes test_conformance/spir/exceptions.h | 53 + test_conformance/spir/geometrics.zip | Bin 0 -> 157176 bytes test_conformance/spir/half.zip | Bin 0 -> 1270366 bytes .../spir/images_kernel_read_write.zip | Bin 0 -> 164635 bytes .../spir/images_samplerlessRead.zip | Bin 0 -> 70004 bytes test_conformance/spir/integer_ops.zip | Bin 0 -> 2517236 bytes test_conformance/spir/kernel_attributes.zip | Bin 0 -> 3353 bytes .../spir/kernel_image_methods.zip | Bin 0 -> 19849 bytes test_conformance/spir/kernelargs.cpp | 24 + test_conformance/spir/kernelargs.h | 444 + test_conformance/spir/khr.csv | 2176 +++ test_conformance/spir/main.cpp | 6985 +++++++++ test_conformance/spir/math_brute_force.zip | Bin 0 -> 3404925 bytes test_conformance/spir/printf.zip | Bin 0 -> 34910 bytes test_conformance/spir/profiling.zip | Bin 0 -> 7959 bytes test_conformance/spir/relationals.zip | Bin 0 -> 2721341 bytes test_conformance/spir/run_build_test.cpp | 422 + test_conformance/spir/run_build_test.h | 145 + test_conformance/spir/run_services.cpp | 767 + test_conformance/spir/run_services.h | 222 + test_conformance/spir/sampler_enumeration.zip | Bin 0 -> 63862 bytes test_conformance/spir/select.zip | Bin 0 -> 431587 bytes test_conformance/spir/typeinfo.h | 208 + test_conformance/spir/vec_align.zip | Bin 0 -> 214384 bytes test_conformance/spir/vec_step.zip | Bin 0 -> 184591 bytes test_conformance/subgroups/CMakeLists.txt | 20 + test_conformance/subgroups/Jamfile | 26 + test_conformance/subgroups/main.cpp | 60 + test_conformance/subgroups/procs.h | 43 + test_conformance/subgroups/subhelpers.h | 286 + test_conformance/subgroups/test_barrier.cpp | 147 + test_conformance/subgroups/test_queries.cpp | 136 + test_conformance/subgroups/test_workgroup.cpp | 867 ++ test_conformance/subgroups/test_workitem.cpp | 252 + .../submission_details_template.txt | 145 + .../thread_dimensions/CMakeLists.txt | 20 + test_conformance/thread_dimensions/Jamfile | 16 + test_conformance/thread_dimensions/Makefile | 44 + test_conformance/thread_dimensions/main.c | 64 + test_conformance/thread_dimensions/procs.h | 37 + .../test_thread_dimensions.c | 991 ++ test_conformance/vec_align/CMakeLists.txt | 22 + test_conformance/vec_align/Jamfile | 19 + test_conformance/vec_align/Makefile | 46 + test_conformance/vec_align/defines.h | 42 + test_conformance/vec_align/globals.c | 59 + test_conformance/vec_align/main.c | 57 + test_conformance/vec_align/procs.h | 39 + test_conformance/vec_align/structs.c | 375 + test_conformance/vec_align/structs.h | 73 + test_conformance/vec_align/testBase.h | 28 + test_conformance/vec_align/test_vec_align.c | 545 + test_conformance/vec_align/type_replacer.c | 115 + test_conformance/vec_align/type_replacer.h | 23 + test_conformance/vec_step/CMakeLists.txt | 20 + test_conformance/vec_step/Jamfile | 19 + test_conformance/vec_step/Makefile | 46 + test_conformance/vec_step/defines.h | 41 + test_conformance/vec_step/globals.c | 52 + test_conformance/vec_step/main.c | 54 + test_conformance/vec_step/procs.h | 43 + test_conformance/vec_step/structs.c | 285 + test_conformance/vec_step/structs.h | 67 + test_conformance/vec_step/testBase.h | 28 + test_conformance/vec_step/test_step.c | 253 + test_conformance/vec_step/type_replacer.c | 115 + test_conformance/vec_step/type_replacer.h | 23 + test_conformance/workgroups/CMakeLists.txt | 26 + test_conformance/workgroups/Makefile | 50 + test_conformance/workgroups/main.c | 70 + test_conformance/workgroups/procs.h | 38 + test_conformance/workgroups/testBase.h | 31 + test_conformance/workgroups/test_wg_all.c | 167 + test_conformance/workgroups/test_wg_any.c | 167 + .../workgroups/test_wg_broadcast.c | 523 + test_conformance/workgroups/test_wg_reduce.c | 580 + .../workgroups/test_wg_reduce_max.c | 580 + .../workgroups/test_wg_reduce_min.c | 580 + .../workgroups/test_wg_scan_exclusive_add.c | 588 + .../workgroups/test_wg_scan_exclusive_max.c | 579 + .../workgroups/test_wg_scan_exclusive_min.c | 580 + .../workgroups/test_wg_scan_inclusive_add.c | 577 + .../workgroups/test_wg_scan_inclusive_max.c | 579 + .../workgroups/test_wg_scan_inclusive_min.c | 579 + test_extensions/media_sharing/CMakeLists.txt | 33 + test_extensions/media_sharing/Makefile | 34 + test_extensions/media_sharing/main.cpp | 222 + .../media_sharing/test_create_context.cpp | 305 + .../media_sharing/test_functions_api.cpp | 604 + .../media_sharing/test_functions_kernel.cpp | 433 + .../media_sharing/test_get_device_ids.cpp | 183 + .../media_sharing/test_interop_sync.cpp | 342 + .../media_sharing/test_memory_access.cpp | 455 + .../media_sharing/test_other_data_types.cpp | 1009 ++ test_extensions/media_sharing/utils.cpp | 1937 +++ test_extensions/media_sharing/utils.h | 171 + test_extensions/media_sharing/wrappers.cpp | 550 + test_extensions/media_sharing/wrappers.h | 170 + 1035 files changed, 343518 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 CMakeVendor.txt create mode 100644 build_android.py create mode 100644 build_lnx.sh create mode 100644 build_win.bat create mode 100644 clean_tests.py create mode 100644 license.txt create mode 100644 readme-spir-v-binaries.txt create mode 100644 test_common/Makefile create mode 100644 test_common/autotest/autotest.hpp create mode 100644 test_common/autotest/test_case.hpp create mode 100644 test_common/autotest/test_suite.hpp create mode 100644 test_common/config.hpp create mode 100644 test_common/gl/gl_headers.h create mode 100644 test_common/gl/helpers.cpp create mode 100644 test_common/gl/helpers.h create mode 100644 test_common/gl/setup.h create mode 100644 test_common/gl/setup_osx.cpp create mode 100644 test_common/gl/setup_win32.cpp create mode 100644 test_common/gl/setup_x11.cpp create mode 100644 test_common/gles/gl_headers.h create mode 100644 test_common/gles/helpers.cpp create mode 100644 test_common/gles/helpers.h create mode 100644 test_common/gles/setup.h create mode 100644 test_common/harness/Jamfile create mode 100644 test_common/harness/Makefile create mode 100644 test_common/harness/ThreadPool.c create mode 100644 test_common/harness/ThreadPool.h create mode 100644 test_common/harness/clImageHelper.h create mode 100644 test_common/harness/compat.h create mode 100644 test_common/harness/conversions.c create mode 100644 test_common/harness/conversions.h create mode 100644 test_common/harness/errorHelpers.c create mode 100644 test_common/harness/errorHelpers.h create mode 100644 test_common/harness/fpcontrol.h create mode 100644 test_common/harness/genericThread.cpp create mode 100644 test_common/harness/genericThread.h create mode 100644 test_common/harness/imageHelpers.cpp create mode 100644 test_common/harness/imageHelpers.h create mode 100644 test_common/harness/kernelHelpers.c create mode 100644 test_common/harness/kernelHelpers.h create mode 100644 test_common/harness/mingw_compat.c create mode 100644 test_common/harness/mingw_compat.h create mode 100644 test_common/harness/msvc9.c create mode 100644 test_common/harness/mt19937.c create mode 100644 test_common/harness/mt19937.h create mode 100644 test_common/harness/os_helpers.cpp create mode 100644 test_common/harness/os_helpers.h create mode 100644 test_common/harness/parseParameters.cpp create mode 100644 test_common/harness/parseParameters.h create mode 100644 test_common/harness/ref_counting.h create mode 100644 test_common/harness/rounding_mode.c create mode 100644 test_common/harness/rounding_mode.h create mode 100644 test_common/harness/testHarness.c create mode 100644 test_common/harness/testHarness.h create mode 100644 test_common/harness/test_mt19937.c create mode 100644 test_common/harness/threadTesting.c create mode 100644 test_common/harness/threadTesting.h create mode 100644 test_common/harness/typeWrappers.cpp create mode 100644 test_common/harness/typeWrappers.h create mode 100644 test_common/miniz/CMakeLists.txt create mode 100644 test_common/miniz/miniz.c create mode 100644 test_common/miniz/miniz.h create mode 100644 test_conformance/CMakeCommon.txt create mode 100644 test_conformance/CMakeLists.txt create mode 100644 test_conformance/Jamfile create mode 100644 test_conformance/Makefile create mode 100644 test_conformance/SVM/CMakeLists.txt create mode 100644 test_conformance/SVM/Makefile create mode 100644 test_conformance/SVM/common.h create mode 100644 test_conformance/SVM/main.cpp create mode 100644 test_conformance/SVM/test_allocate_shared_buffer.cpp create mode 100644 test_conformance/SVM/test_byte_granularity.cpp create mode 100644 test_conformance/SVM/test_cross_buffer_pointers.cpp create mode 100644 test_conformance/SVM/test_enqueue_api.cpp create mode 100644 test_conformance/SVM/test_fine_grain_memory_consistency.cpp create mode 100644 test_conformance/SVM/test_fine_grain_sync_buffers.cpp create mode 100644 test_conformance/SVM/test_migrate.cpp create mode 100644 test_conformance/SVM/test_pointer_passing.cpp create mode 100644 test_conformance/SVM/test_set_kernel_exec_info_svm_ptrs.cpp create mode 100644 test_conformance/SVM/test_shared_address_space_coarse_grain.cpp create mode 100644 test_conformance/SVM/test_shared_address_space_fine_grain.cpp create mode 100644 test_conformance/SVM/test_shared_address_space_fine_grain_buffers.cpp create mode 100644 test_conformance/SVM/test_shared_sub_buffers.cpp create mode 100644 test_conformance/allocations/CMakeLists.txt create mode 100644 test_conformance/allocations/Jamfile create mode 100644 test_conformance/allocations/Makefile create mode 100644 test_conformance/allocations/allocation_execute.cpp create mode 100644 test_conformance/allocations/allocation_execute.h create mode 100644 test_conformance/allocations/allocation_fill.cpp create mode 100644 test_conformance/allocations/allocation_fill.h create mode 100644 test_conformance/allocations/allocation_functions.cpp create mode 100644 test_conformance/allocations/allocation_functions.h create mode 100644 test_conformance/allocations/allocation_utils.cpp create mode 100644 test_conformance/allocations/allocation_utils.h create mode 100644 test_conformance/allocations/main.cpp create mode 100644 test_conformance/allocations/testBase.h create mode 100644 test_conformance/api/CMakeLists.txt create mode 100644 test_conformance/api/Jamfile create mode 100644 test_conformance/api/Makefile create mode 100644 test_conformance/api/main.c create mode 100644 test_conformance/api/procs.h create mode 100644 test_conformance/api/testBase.h create mode 100644 test_conformance/api/test_api_min_max.c create mode 100644 test_conformance/api/test_binary.cpp create mode 100644 test_conformance/api/test_bool.c create mode 100644 test_conformance/api/test_clone_kernel.cpp create mode 100644 test_conformance/api/test_create_context_from_type.cpp create mode 100644 test_conformance/api/test_create_kernels.c create mode 100644 test_conformance/api/test_device_min_data_type_align_size_alignment.cpp create mode 100644 test_conformance/api/test_kernel_arg_changes.cpp create mode 100644 test_conformance/api/test_kernel_arg_info.c create mode 100644 test_conformance/api/test_kernel_arg_multi_setup.cpp create mode 100644 test_conformance/api/test_kernels.c create mode 100644 test_conformance/api/test_mem_object_info.cpp create mode 100644 test_conformance/api/test_mem_objects.cpp create mode 100644 test_conformance/api/test_native_kernel.cpp create mode 100644 test_conformance/api/test_null_buffer_arg.c create mode 100644 test_conformance/api/test_platform.cpp create mode 100644 test_conformance/api/test_queries.cpp create mode 100644 test_conformance/api/test_queue_hint.cpp create mode 100644 test_conformance/api/test_retain.cpp create mode 100644 test_conformance/api/test_retain_program.c create mode 100644 test_conformance/api/test_sub_group_dispatch.cpp create mode 100644 test_conformance/api/test_zero_sized_enqueue.cpp create mode 100644 test_conformance/atomics/CMakeLists.txt create mode 100644 test_conformance/atomics/Jamfile create mode 100644 test_conformance/atomics/Makefile create mode 100644 test_conformance/atomics/main.c create mode 100644 test_conformance/atomics/procs.h create mode 100644 test_conformance/atomics/testBase.h create mode 100644 test_conformance/atomics/test_atomics.cpp create mode 100644 test_conformance/atomics/test_indexed_cases.c create mode 100644 test_conformance/basic/CMakeLists.txt create mode 100644 test_conformance/basic/Jamfile create mode 100644 test_conformance/basic/Makefile create mode 100644 test_conformance/basic/main.c create mode 100644 test_conformance/basic/procs.h create mode 100644 test_conformance/basic/run_array create mode 100644 test_conformance/basic/run_array_image_copy create mode 100644 test_conformance/basic/run_image create mode 100644 test_conformance/basic/run_multi_read_image create mode 100644 test_conformance/basic/test_arraycopy.c create mode 100644 test_conformance/basic/test_arrayimagecopy.c create mode 100644 test_conformance/basic/test_arrayimagecopy3d.c create mode 100644 test_conformance/basic/test_arrayreadwrite.c create mode 100644 test_conformance/basic/test_astype.cpp create mode 100644 test_conformance/basic/test_async_copy.cpp create mode 100644 test_conformance/basic/test_async_strided_copy.cpp create mode 100644 test_conformance/basic/test_barrier.c create mode 100644 test_conformance/basic/test_basic_parameter_types.c create mode 100644 test_conformance/basic/test_bufferreadwriterect.c create mode 100644 test_conformance/basic/test_constant.c create mode 100644 test_conformance/basic/test_constant_source.cpp create mode 100644 test_conformance/basic/test_createkernelsinprogram.c create mode 100644 test_conformance/basic/test_enqueue_map.cpp create mode 100644 test_conformance/basic/test_enqueued_local_size.c create mode 100644 test_conformance/basic/test_explicit_s2v.cpp create mode 100644 test_conformance/basic/test_float2int.c create mode 100644 test_conformance/basic/test_fpmath_float.c create mode 100644 test_conformance/basic/test_fpmath_float2.c create mode 100644 test_conformance/basic/test_fpmath_float4.c create mode 100644 test_conformance/basic/test_get_linear_ids.cpp create mode 100644 test_conformance/basic/test_global_linear_id.c create mode 100644 test_conformance/basic/test_global_work_offsets.cpp create mode 100644 test_conformance/basic/test_hiloeo.c create mode 100644 test_conformance/basic/test_hostptr.c create mode 100644 test_conformance/basic/test_if.c create mode 100644 test_conformance/basic/test_image_multipass.c create mode 100644 test_conformance/basic/test_image_param.c create mode 100644 test_conformance/basic/test_image_r8.c create mode 100644 test_conformance/basic/test_imagearraycopy.c create mode 100644 test_conformance/basic/test_imagearraycopy3d.c create mode 100644 test_conformance/basic/test_imagecopy.c create mode 100644 test_conformance/basic/test_imagecopy3d.c create mode 100644 test_conformance/basic/test_imagedim.c create mode 100644 test_conformance/basic/test_imagenpot.c create mode 100644 test_conformance/basic/test_imagerandomcopy.c create mode 100644 test_conformance/basic/test_imagereadwrite.c create mode 100644 test_conformance/basic/test_imagereadwrite3d.c create mode 100644 test_conformance/basic/test_int2float.c create mode 100644 test_conformance/basic/test_intmath_int.c create mode 100644 test_conformance/basic/test_intmath_int2.c create mode 100644 test_conformance/basic/test_intmath_int4.c create mode 100644 test_conformance/basic/test_intmath_long.c create mode 100644 test_conformance/basic/test_intmath_long2.c create mode 100644 test_conformance/basic/test_intmath_long4.c create mode 100644 test_conformance/basic/test_kernel_call_kernel_function.cpp create mode 100644 test_conformance/basic/test_kernel_memory_alignment.cpp create mode 100644 test_conformance/basic/test_local.c create mode 100644 test_conformance/basic/test_local_kernel_scope.cpp create mode 100644 test_conformance/basic/test_local_linear_id.c create mode 100644 test_conformance/basic/test_loop.c create mode 100644 test_conformance/basic/test_multireadimagemultifmt.c create mode 100644 test_conformance/basic/test_multireadimageonefmt.c create mode 100644 test_conformance/basic/test_numeric_constants.cpp create mode 100644 test_conformance/basic/test_pointercast.c create mode 100644 test_conformance/basic/test_preprocessors.cpp create mode 100644 test_conformance/basic/test_progvar.cpp create mode 100644 test_conformance/basic/test_queue_priority.c create mode 100644 test_conformance/basic/test_readimage.c create mode 100644 test_conformance/basic/test_readimage3d.c create mode 100644 test_conformance/basic/test_readimage3d_fp32.c create mode 100644 test_conformance/basic/test_readimage3d_int16.c create mode 100644 test_conformance/basic/test_readimage_fp32.c create mode 100644 test_conformance/basic/test_readimage_int16.c create mode 100644 test_conformance/basic/test_rw_image_access_qualifier.c create mode 100644 test_conformance/basic/test_simple_image_pitch.c create mode 100644 test_conformance/basic/test_sizeof.c create mode 100644 test_conformance/basic/test_vec_type_hint.c create mode 100644 test_conformance/basic/test_vector_creation.cpp create mode 100644 test_conformance/basic/test_vloadstore.c create mode 100644 test_conformance/basic/test_wg_barrier.c create mode 100644 test_conformance/basic/test_work_item_functions.cpp create mode 100644 test_conformance/basic/test_writeimage.c create mode 100644 test_conformance/basic/test_writeimage_fp32.c create mode 100644 test_conformance/basic/test_writeimage_int16.c create mode 100644 test_conformance/buffers/CMakeLists.txt create mode 100644 test_conformance/buffers/Jamfile create mode 100644 test_conformance/buffers/Makefile create mode 100644 test_conformance/buffers/array_info.c create mode 100644 test_conformance/buffers/main.c create mode 100644 test_conformance/buffers/procs.h create mode 100644 test_conformance/buffers/test_buffer_copy.c create mode 100644 test_conformance/buffers/test_buffer_fill.c create mode 100644 test_conformance/buffers/test_buffer_map.c create mode 100644 test_conformance/buffers/test_buffer_mem.c create mode 100644 test_conformance/buffers/test_buffer_migrate.c create mode 100644 test_conformance/buffers/test_buffer_read.c create mode 100644 test_conformance/buffers/test_buffer_write.c create mode 100644 test_conformance/buffers/test_image_migrate.c create mode 100644 test_conformance/buffers/test_sub_buffers.cpp create mode 100644 test_conformance/c11_atomics/CMakeLists.txt create mode 100644 test_conformance/c11_atomics/Makefile create mode 100644 test_conformance/c11_atomics/common.cpp create mode 100644 test_conformance/c11_atomics/common.h create mode 100644 test_conformance/c11_atomics/host_atomics.cpp create mode 100644 test_conformance/c11_atomics/host_atomics.h create mode 100644 test_conformance/c11_atomics/main.cpp create mode 100644 test_conformance/c11_atomics/test_atomics.cpp create mode 100644 test_conformance/clcpp/CMakeLists.txt create mode 100644 test_conformance/clcpp/address_spaces/CMakeLists.txt create mode 100644 test_conformance/clcpp/address_spaces/common.hpp create mode 100644 test_conformance/clcpp/address_spaces/main.cpp create mode 100644 test_conformance/clcpp/address_spaces/test_pointer_types.hpp create mode 100644 test_conformance/clcpp/address_spaces/test_storage_types.hpp create mode 100644 test_conformance/clcpp/api/CMakeLists.txt create mode 100644 test_conformance/clcpp/api/main.cpp create mode 100644 test_conformance/clcpp/api/test_ctors.hpp create mode 100644 test_conformance/clcpp/api/test_ctors_dtors.hpp create mode 100644 test_conformance/clcpp/api/test_dtors.hpp create mode 100644 test_conformance/clcpp/api/test_spec_consts.hpp create mode 100644 test_conformance/clcpp/atomics/CMakeLists.txt create mode 100644 test_conformance/clcpp/atomics/atomic_fetch.hpp create mode 100644 test_conformance/clcpp/atomics/main.cpp create mode 100644 test_conformance/clcpp/attributes/CMakeLists.txt create mode 100644 test_conformance/clcpp/attributes/main.cpp create mode 100644 test_conformance/clcpp/attributes/test_ivdep.hpp create mode 100644 test_conformance/clcpp/attributes/test_max_size.hpp create mode 100644 test_conformance/clcpp/attributes/test_required_num_sub_groups.hpp create mode 100644 test_conformance/clcpp/common.hpp create mode 100644 test_conformance/clcpp/common_funcs/CMakeLists.txt create mode 100644 test_conformance/clcpp/common_funcs/common_funcs.hpp create mode 100644 test_conformance/clcpp/common_funcs/main.cpp create mode 100644 test_conformance/clcpp/convert/CMakeLists.txt create mode 100644 test_conformance/clcpp/convert/convert_cast.hpp create mode 100644 test_conformance/clcpp/convert/main.cpp create mode 100644 test_conformance/clcpp/device_queue/CMakeLists.txt create mode 100644 test_conformance/clcpp/device_queue/main.cpp create mode 100644 test_conformance/clcpp/device_queue/test_enqueue.hpp create mode 100644 test_conformance/clcpp/funcs_test_utils.hpp create mode 100644 test_conformance/clcpp/geometric_funcs/CMakeLists.txt create mode 100644 test_conformance/clcpp/geometric_funcs/fast_geometric_funcs.hpp create mode 100644 test_conformance/clcpp/geometric_funcs/geometric_funcs.hpp create mode 100644 test_conformance/clcpp/geometric_funcs/main.cpp create mode 100644 test_conformance/clcpp/images/CMakeLists.txt create mode 100644 test_conformance/clcpp/images/common.hpp create mode 100644 test_conformance/clcpp/images/main.cpp create mode 100644 test_conformance/clcpp/images/test_read.hpp create mode 100644 test_conformance/clcpp/images/test_sample.hpp create mode 100644 test_conformance/clcpp/images/test_write.hpp create mode 100644 test_conformance/clcpp/integer_funcs/24bit_funcs.hpp create mode 100644 test_conformance/clcpp/integer_funcs/CMakeLists.txt create mode 100644 test_conformance/clcpp/integer_funcs/bitwise_funcs.hpp create mode 100644 test_conformance/clcpp/integer_funcs/common.hpp create mode 100644 test_conformance/clcpp/integer_funcs/main.cpp create mode 100644 test_conformance/clcpp/integer_funcs/numeric_funcs.hpp create mode 100644 test_conformance/clcpp/math_funcs/CMakeLists.txt create mode 100644 test_conformance/clcpp/math_funcs/common.hpp create mode 100644 test_conformance/clcpp/math_funcs/comparison_funcs.hpp create mode 100644 test_conformance/clcpp/math_funcs/exponential_funcs.hpp create mode 100644 test_conformance/clcpp/math_funcs/floating_point_funcs.hpp create mode 100644 test_conformance/clcpp/math_funcs/half_math_funcs.hpp create mode 100644 test_conformance/clcpp/math_funcs/logarithmic_funcs.hpp create mode 100644 test_conformance/clcpp/math_funcs/main.cpp create mode 100644 test_conformance/clcpp/math_funcs/other_funcs.hpp create mode 100644 test_conformance/clcpp/math_funcs/power_funcs.hpp create mode 100644 test_conformance/clcpp/math_funcs/reference.hpp create mode 100644 test_conformance/clcpp/math_funcs/trigonometric_funcs.hpp create mode 100644 test_conformance/clcpp/pipes/CMakeLists.txt create mode 100644 test_conformance/clcpp/pipes/main.cpp create mode 100644 test_conformance/clcpp/pipes/test_pipes.hpp create mode 100644 test_conformance/clcpp/program_scope_ctors_dtors/CMakeLists.txt create mode 100644 test_conformance/clcpp/program_scope_ctors_dtors/common.hpp create mode 100644 test_conformance/clcpp/program_scope_ctors_dtors/main.cpp create mode 100644 test_conformance/clcpp/program_scope_ctors_dtors/test_ctors_dtors.hpp create mode 100644 test_conformance/clcpp/reinterpret/CMakeLists.txt create mode 100644 test_conformance/clcpp/reinterpret/as_type.hpp create mode 100644 test_conformance/clcpp/reinterpret/main.cpp create mode 100644 test_conformance/clcpp/relational_funcs/CMakeLists.txt create mode 100644 test_conformance/clcpp/relational_funcs/common.hpp create mode 100644 test_conformance/clcpp/relational_funcs/comparison_funcs.hpp create mode 100644 test_conformance/clcpp/relational_funcs/main.cpp create mode 100644 test_conformance/clcpp/relational_funcs/select_funcs.hpp create mode 100644 test_conformance/clcpp/relational_funcs/test_funcs.hpp create mode 100644 test_conformance/clcpp/spec_constants/CMakeLists.txt create mode 100644 test_conformance/clcpp/spec_constants/common.hpp create mode 100644 test_conformance/clcpp/spec_constants/main.cpp create mode 100644 test_conformance/clcpp/spec_constants/test_spec_consts_attributes.hpp create mode 100644 test_conformance/clcpp/spec_constants/test_spec_consts_if.hpp create mode 100644 test_conformance/clcpp/spec_constants/test_spec_consts_init_vars.hpp create mode 100644 test_conformance/clcpp/subgroups/CMakeLists.txt create mode 100644 test_conformance/clcpp/subgroups/common.hpp create mode 100644 test_conformance/clcpp/subgroups/main.cpp create mode 100644 test_conformance/clcpp/subgroups/test_sg_all.hpp create mode 100644 test_conformance/clcpp/subgroups/test_sg_any.hpp create mode 100644 test_conformance/clcpp/subgroups/test_sg_broadcast.hpp create mode 100644 test_conformance/clcpp/subgroups/test_sg_reduce.hpp create mode 100644 test_conformance/clcpp/subgroups/test_sg_scan_exclusive.hpp create mode 100644 test_conformance/clcpp/subgroups/test_sg_scan_inclusive.hpp create mode 100644 test_conformance/clcpp/synchronization/CMakeLists.txt create mode 100644 test_conformance/clcpp/synchronization/main.cpp create mode 100644 test_conformance/clcpp/synchronization/named_barrier/common.hpp create mode 100644 test_conformance/clcpp/synchronization/named_barrier/test_named_barrier.hpp create mode 100644 test_conformance/clcpp/synchronization/named_barrier/test_spec_example.hpp create mode 100644 test_conformance/clcpp/synchronization/test_sub_group_barrier.hpp create mode 100644 test_conformance/clcpp/synchronization/test_work_group_barrier.hpp create mode 100644 test_conformance/clcpp/utils_common/errors.hpp create mode 100644 test_conformance/clcpp/utils_common/is_vector_type.hpp create mode 100644 test_conformance/clcpp/utils_common/kernel_helpers.hpp create mode 100644 test_conformance/clcpp/utils_common/make_vector_type.hpp create mode 100644 test_conformance/clcpp/utils_common/scalar_type.hpp create mode 100644 test_conformance/clcpp/utils_common/string.hpp create mode 100644 test_conformance/clcpp/utils_common/type_name.hpp create mode 100644 test_conformance/clcpp/utils_common/type_supported.hpp create mode 100644 test_conformance/clcpp/utils_common/vector_size.hpp create mode 100644 test_conformance/clcpp/utils_test/binary.hpp create mode 100644 test_conformance/clcpp/utils_test/compare.hpp create mode 100644 test_conformance/clcpp/utils_test/detail/base_func_type.hpp create mode 100644 test_conformance/clcpp/utils_test/detail/vec_helpers.hpp create mode 100644 test_conformance/clcpp/utils_test/generate_inputs.hpp create mode 100644 test_conformance/clcpp/utils_test/ternary.hpp create mode 100644 test_conformance/clcpp/utils_test/unary.hpp create mode 100644 test_conformance/clcpp/vload_vstore/CMakeLists.txt create mode 100644 test_conformance/clcpp/vload_vstore/common.hpp create mode 100644 test_conformance/clcpp/vload_vstore/half_utils.hpp create mode 100644 test_conformance/clcpp/vload_vstore/main.cpp create mode 100644 test_conformance/clcpp/vload_vstore/vload_funcs.hpp create mode 100644 test_conformance/clcpp/vload_vstore/vstore_funcs.hpp create mode 100644 test_conformance/clcpp/workgroups/CMakeLists.txt create mode 100644 test_conformance/clcpp/workgroups/common.hpp create mode 100644 test_conformance/clcpp/workgroups/main.cpp create mode 100644 test_conformance/clcpp/workgroups/test_wg_all.hpp create mode 100644 test_conformance/clcpp/workgroups/test_wg_any.hpp create mode 100644 test_conformance/clcpp/workgroups/test_wg_broadcast.hpp create mode 100644 test_conformance/clcpp/workgroups/test_wg_reduce.hpp create mode 100644 test_conformance/clcpp/workgroups/test_wg_scan_exclusive.hpp create mode 100644 test_conformance/clcpp/workgroups/test_wg_scan_inclusive.hpp create mode 100644 test_conformance/clcpp/workitems/CMakeLists.txt create mode 100644 test_conformance/clcpp/workitems/main.cpp create mode 100644 test_conformance/clcpp/workitems/test_workitems.hpp create mode 100644 test_conformance/commonfns/CMakeLists.txt create mode 100644 test_conformance/commonfns/Jamfile create mode 100644 test_conformance/commonfns/Makefile create mode 100644 test_conformance/commonfns/main.c create mode 100644 test_conformance/commonfns/procs.h create mode 100644 test_conformance/commonfns/test_binary_fn.c create mode 100644 test_conformance/commonfns/test_clamp.c create mode 100644 test_conformance/commonfns/test_degrees.c create mode 100644 test_conformance/commonfns/test_fmax.c create mode 100644 test_conformance/commonfns/test_fmaxf.c create mode 100644 test_conformance/commonfns/test_fmin.c create mode 100644 test_conformance/commonfns/test_fminf.c create mode 100644 test_conformance/commonfns/test_max.c create mode 100644 test_conformance/commonfns/test_maxf.c create mode 100644 test_conformance/commonfns/test_min.c create mode 100644 test_conformance/commonfns/test_minf.c create mode 100644 test_conformance/commonfns/test_mix.c create mode 100644 test_conformance/commonfns/test_radians.c create mode 100644 test_conformance/commonfns/test_sign.c create mode 100644 test_conformance/commonfns/test_smoothstep.c create mode 100644 test_conformance/commonfns/test_smoothstepf.c create mode 100644 test_conformance/commonfns/test_step.c create mode 100644 test_conformance/commonfns/test_stepf.c create mode 100644 test_conformance/compatibility/CMakeLists.txt create mode 100644 test_conformance/compatibility/test_common/Makefile create mode 100644 test_conformance/compatibility/test_common/gl/gl_headers.h create mode 100644 test_conformance/compatibility/test_common/gl/helpers.cpp create mode 100644 test_conformance/compatibility/test_common/gl/helpers.h create mode 100644 test_conformance/compatibility/test_common/gl/setup.h create mode 100644 test_conformance/compatibility/test_common/gl/setup_osx.cpp create mode 100644 test_conformance/compatibility/test_common/gl/setup_win32.cpp create mode 100644 test_conformance/compatibility/test_common/gl/setup_x11.cpp create mode 100644 test_conformance/compatibility/test_common/harness/Jamfile create mode 100644 test_conformance/compatibility/test_common/harness/Makefile create mode 100644 test_conformance/compatibility/test_common/harness/ThreadPool.c create mode 100644 test_conformance/compatibility/test_common/harness/ThreadPool.h create mode 100644 test_conformance/compatibility/test_common/harness/clImageHelper.h create mode 100644 test_conformance/compatibility/test_common/harness/compat.h create mode 100644 test_conformance/compatibility/test_common/harness/conversions.c create mode 100644 test_conformance/compatibility/test_common/harness/conversions.h create mode 100644 test_conformance/compatibility/test_common/harness/errorHelpers.c create mode 100644 test_conformance/compatibility/test_common/harness/errorHelpers.h create mode 100644 test_conformance/compatibility/test_common/harness/fpcontrol.h create mode 100644 test_conformance/compatibility/test_common/harness/genericThread.cpp create mode 100644 test_conformance/compatibility/test_common/harness/genericThread.h create mode 100644 test_conformance/compatibility/test_common/harness/imageHelpers.cpp create mode 100644 test_conformance/compatibility/test_common/harness/imageHelpers.h create mode 100644 test_conformance/compatibility/test_common/harness/kernelHelpers.c create mode 100644 test_conformance/compatibility/test_common/harness/kernelHelpers.h create mode 100644 test_conformance/compatibility/test_common/harness/mingw_compat.c create mode 100644 test_conformance/compatibility/test_common/harness/mingw_compat.h create mode 100644 test_conformance/compatibility/test_common/harness/msvc9.c create mode 100644 test_conformance/compatibility/test_common/harness/mt19937.c create mode 100644 test_conformance/compatibility/test_common/harness/mt19937.h create mode 100644 test_conformance/compatibility/test_common/harness/ref_counting.h create mode 100644 test_conformance/compatibility/test_common/harness/rounding_mode.c create mode 100644 test_conformance/compatibility/test_common/harness/rounding_mode.h create mode 100644 test_conformance/compatibility/test_common/harness/testHarness.c create mode 100644 test_conformance/compatibility/test_common/harness/testHarness.h create mode 100644 test_conformance/compatibility/test_common/harness/test_mt19937.c create mode 100644 test_conformance/compatibility/test_common/harness/threadTesting.c create mode 100644 test_conformance/compatibility/test_common/harness/threadTesting.h create mode 100644 test_conformance/compatibility/test_common/harness/typeWrappers.cpp create mode 100644 test_conformance/compatibility/test_common/harness/typeWrappers.h create mode 100644 test_conformance/compatibility/test_conformance/CMakeLists.txt create mode 100644 test_conformance/compatibility/test_conformance/api/CMakeLists.txt create mode 100644 test_conformance/compatibility/test_conformance/api/Jamfile create mode 100644 test_conformance/compatibility/test_conformance/api/Makefile create mode 100644 test_conformance/compatibility/test_conformance/api/main.c create mode 100644 test_conformance/compatibility/test_conformance/api/procs.h create mode 100644 test_conformance/compatibility/test_conformance/api/testBase.h create mode 100644 test_conformance/compatibility/test_conformance/api/test_api_min_max.c create mode 100644 test_conformance/compatibility/test_conformance/api/test_binary.cpp create mode 100644 test_conformance/compatibility/test_conformance/api/test_bool.c create mode 100644 test_conformance/compatibility/test_conformance/api/test_create_context_from_type.cpp create mode 100644 test_conformance/compatibility/test_conformance/api/test_create_kernels.c create mode 100644 test_conformance/compatibility/test_conformance/api/test_device_min_data_type_align_size_alignment.cpp create mode 100644 test_conformance/compatibility/test_conformance/api/test_kernel_arg_changes.cpp create mode 100644 test_conformance/compatibility/test_conformance/api/test_kernel_arg_info.c create mode 100644 test_conformance/compatibility/test_conformance/api/test_kernel_arg_multi_setup.cpp create mode 100644 test_conformance/compatibility/test_conformance/api/test_kernels.c create mode 100644 test_conformance/compatibility/test_conformance/api/test_mem_object_info.cpp create mode 100644 test_conformance/compatibility/test_conformance/api/test_mem_objects.cpp create mode 100644 test_conformance/compatibility/test_conformance/api/test_native_kernel.cpp create mode 100644 test_conformance/compatibility/test_conformance/api/test_null_buffer_arg.c create mode 100644 test_conformance/compatibility/test_conformance/api/test_platform.cpp create mode 100644 test_conformance/compatibility/test_conformance/api/test_queries.cpp create mode 100644 test_conformance/compatibility/test_conformance/api/test_retain.cpp create mode 100644 test_conformance/compatibility/test_conformance/api/test_retain_program.c create mode 100644 test_conformance/compatibility/test_conformance/basic/CMakeLists.txt create mode 100644 test_conformance/compatibility/test_conformance/basic/Jamfile create mode 100644 test_conformance/compatibility/test_conformance/basic/Makefile create mode 100644 test_conformance/compatibility/test_conformance/basic/main.c create mode 100644 test_conformance/compatibility/test_conformance/basic/procs.h create mode 100644 test_conformance/compatibility/test_conformance/basic/run_array create mode 100644 test_conformance/compatibility/test_conformance/basic/run_array_image_copy create mode 100644 test_conformance/compatibility/test_conformance/basic/run_image create mode 100644 test_conformance/compatibility/test_conformance/basic/run_multi_read_image create mode 100644 test_conformance/compatibility/test_conformance/basic/test_arraycopy.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_arrayimagecopy.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_arrayimagecopy3d.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_arrayreadwrite.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_astype.cpp create mode 100644 test_conformance/compatibility/test_conformance/basic/test_async_copy.cpp create mode 100644 test_conformance/compatibility/test_conformance/basic/test_async_strided_copy.cpp create mode 100644 test_conformance/compatibility/test_conformance/basic/test_barrier.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_basic_parameter_types.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_bufferreadwriterect.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_constant.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_constant_source.cpp create mode 100644 test_conformance/compatibility/test_conformance/basic/test_createkernelsinprogram.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_enqueue_map.cpp create mode 100644 test_conformance/compatibility/test_conformance/basic/test_explicit_s2v.cpp create mode 100644 test_conformance/compatibility/test_conformance/basic/test_float2int.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_fpmath_float.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_fpmath_float2.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_fpmath_float4.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_global_work_offsets.cpp create mode 100644 test_conformance/compatibility/test_conformance/basic/test_hiloeo.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_hostptr.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_if.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_image_multipass.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_image_param.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_image_r8.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_imagearraycopy.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_imagearraycopy3d.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_imagecopy.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_imagecopy3d.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_imagedim.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_imagenpot.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_imagerandomcopy.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_imagereadwrite.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_imagereadwrite3d.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_int2float.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_intmath_int.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_intmath_int2.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_intmath_int4.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_intmath_long.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_intmath_long2.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_intmath_long4.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_kernel_call_kernel_function.cpp create mode 100644 test_conformance/compatibility/test_conformance/basic/test_kernel_memory_alignment.cpp create mode 100644 test_conformance/compatibility/test_conformance/basic/test_local.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_local_kernel_scope.cpp create mode 100644 test_conformance/compatibility/test_conformance/basic/test_loop.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_multireadimagemultifmt.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_multireadimageonefmt.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_numeric_constants.cpp create mode 100644 test_conformance/compatibility/test_conformance/basic/test_pointercast.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_preprocessors.cpp create mode 100644 test_conformance/compatibility/test_conformance/basic/test_readimage.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_readimage3d.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_readimage3d_fp32.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_readimage3d_int16.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_readimage_fp32.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_readimage_int16.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_sizeof.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_vec_type_hint.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_vector_creation.cpp create mode 100644 test_conformance/compatibility/test_conformance/basic/test_vloadstore.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_work_item_functions.cpp create mode 100644 test_conformance/compatibility/test_conformance/basic/test_writeimage.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_writeimage_fp32.c create mode 100644 test_conformance/compatibility/test_conformance/basic/test_writeimage_int16.c create mode 100644 test_conformance/compatibility/test_conformance/images/image_helpers.h create mode 100644 test_conformance/compiler/CMakeLists.txt create mode 100644 test_conformance/compiler/Jamfile create mode 100644 test_conformance/compiler/Makefile create mode 100644 test_conformance/compiler/includeTestDirectory/testIncludeFile.h create mode 100644 test_conformance/compiler/main.c create mode 100644 test_conformance/compiler/procs.h create mode 100644 test_conformance/compiler/secondIncludeTestDirectory/testIncludeFile.h create mode 100644 test_conformance/compiler/testBase.h create mode 100644 test_conformance/compiler/test_async_build.c create mode 100644 test_conformance/compiler/test_build_helpers.c create mode 100644 test_conformance/compiler/test_build_options.cpp create mode 100644 test_conformance/compiler/test_compile.c create mode 100644 test_conformance/compiler/test_compiler_defines_for_extensions.cpp create mode 100644 test_conformance/compiler/test_image_macro.c create mode 100644 test_conformance/compiler/test_pragma_unroll.c create mode 100644 test_conformance/compiler/test_preprocessor.c create mode 100644 test_conformance/computeinfo/CMakeLists.txt create mode 100644 test_conformance/computeinfo/Jamfile create mode 100644 test_conformance/computeinfo/Makefile create mode 100644 test_conformance/computeinfo/main.c create mode 100644 test_conformance/contractions/CMakeLists.txt create mode 100644 test_conformance/contractions/Jamfile create mode 100644 test_conformance/contractions/Makefile create mode 100644 test_conformance/contractions/contractions.c create mode 100644 test_conformance/conversions/CMakeLists.txt create mode 100644 test_conformance/conversions/Jamfile create mode 100644 test_conformance/conversions/Makefile create mode 100644 test_conformance/conversions/Sleep.c create mode 100644 test_conformance/conversions/Sleep.h create mode 100644 test_conformance/conversions/basic_test_conversions.c create mode 100644 test_conformance/conversions/basic_test_conversions.h create mode 100644 test_conformance/conversions/fplib.c create mode 100644 test_conformance/conversions/fplib.h create mode 100644 test_conformance/conversions/run_batch create mode 100644 test_conformance/conversions/test_conversions.c create mode 100644 test_conformance/d3d10/CMakeLists.txt create mode 100644 test_conformance/d3d10/buffer.cpp create mode 100644 test_conformance/d3d10/harness.cpp create mode 100644 test_conformance/d3d10/harness.h create mode 100644 test_conformance/d3d10/main.cpp create mode 100644 test_conformance/d3d10/misc.cpp create mode 100644 test_conformance/d3d10/texture2d.cpp create mode 100644 test_conformance/d3d10/texture3d.cpp create mode 100644 test_conformance/d3d11/CMakeLists.txt create mode 100644 test_conformance/d3d11/buffer.cpp create mode 100644 test_conformance/d3d11/harness.cpp create mode 100644 test_conformance/d3d11/harness.h create mode 100644 test_conformance/d3d11/main.cpp create mode 100644 test_conformance/d3d11/misc.cpp create mode 100644 test_conformance/d3d11/texture2d.cpp create mode 100644 test_conformance/d3d11/texture3d.cpp create mode 100644 test_conformance/device_execution/CMakeLists.txt create mode 100644 test_conformance/device_execution/Makefile create mode 100644 test_conformance/device_execution/device_info.cpp create mode 100644 test_conformance/device_execution/device_queue.cpp create mode 100644 test_conformance/device_execution/enqueue_block.cpp create mode 100644 test_conformance/device_execution/enqueue_flags.cpp create mode 100644 test_conformance/device_execution/enqueue_multi_queue.cpp create mode 100644 test_conformance/device_execution/enqueue_ndrange.cpp create mode 100644 test_conformance/device_execution/enqueue_wg_size.cpp create mode 100644 test_conformance/device_execution/execute_block.cpp create mode 100644 test_conformance/device_execution/host_multi_queue.cpp create mode 100644 test_conformance/device_execution/host_queue_order.cpp create mode 100644 test_conformance/device_execution/main.c create mode 100644 test_conformance/device_execution/nested_blocks.cpp create mode 100644 test_conformance/device_execution/procs.h create mode 100644 test_conformance/device_execution/utils.cpp create mode 100644 test_conformance/device_execution/utils.h create mode 100644 test_conformance/device_partition/CMakeLists.txt create mode 100644 test_conformance/device_partition/Jamfile create mode 100644 test_conformance/device_partition/Makefile create mode 100644 test_conformance/device_partition/main.c create mode 100644 test_conformance/device_partition/procs.h create mode 100644 test_conformance/device_partition/testBase.h create mode 100644 test_conformance/device_partition/test_device_partition.cpp create mode 100644 test_conformance/device_timer/CMakeLists.txt create mode 100644 test_conformance/device_timer/main.c create mode 100644 test_conformance/device_timer/procs.h create mode 100644 test_conformance/device_timer/test_device_timer.c create mode 100644 test_conformance/events/CMakeLists.txt create mode 100644 test_conformance/events/Jamfile create mode 100644 test_conformance/events/Makefile create mode 100644 test_conformance/events/action_classes.cpp create mode 100644 test_conformance/events/action_classes.h create mode 100644 test_conformance/events/main.c create mode 100644 test_conformance/events/procs.h create mode 100644 test_conformance/events/testBase.h create mode 100644 test_conformance/events/test_callbacks.cpp create mode 100644 test_conformance/events/test_event_dependencies.cpp create mode 100644 test_conformance/events/test_events.cpp create mode 100644 test_conformance/events/test_userevents.cpp create mode 100644 test_conformance/events/test_userevents_multithreaded.cpp create mode 100644 test_conformance/events/test_waitlists.cpp create mode 100644 test_conformance/generic_address_space/CMakeLists.txt create mode 100644 test_conformance/generic_address_space/Makefile create mode 100644 test_conformance/generic_address_space/advanced_tests.cpp create mode 100644 test_conformance/generic_address_space/base.h create mode 100644 test_conformance/generic_address_space/basic_tests.cpp create mode 100644 test_conformance/generic_address_space/main.cpp create mode 100644 test_conformance/generic_address_space/stress_tests.cpp create mode 100644 test_conformance/geometrics/CMakeLists.txt create mode 100644 test_conformance/geometrics/Jamfile create mode 100644 test_conformance/geometrics/Makefile create mode 100644 test_conformance/geometrics/main.c create mode 100644 test_conformance/geometrics/procs.h create mode 100644 test_conformance/geometrics/testBase.h create mode 100644 test_conformance/geometrics/test_geometrics.cpp create mode 100644 test_conformance/geometrics/test_geometrics_double.cpp create mode 100644 test_conformance/gl/CMakeLists.txt create mode 100644 test_conformance/gl/GLEW/GL/glew.h create mode 100644 test_conformance/gl/GLEW/GL/glxew.h create mode 100644 test_conformance/gl/GLEW/GL/wglew.h create mode 100644 test_conformance/gl/GLEW/glew.c create mode 100644 test_conformance/gl/Jamfile create mode 100644 test_conformance/gl/Makefile create mode 100644 test_conformance/gl/common.h create mode 100644 test_conformance/gl/helpers.cpp create mode 100644 test_conformance/gl/main.cpp create mode 100644 test_conformance/gl/procs.h create mode 100644 test_conformance/gl/testBase.h create mode 100644 test_conformance/gl/test_buffers.cpp create mode 100644 test_conformance/gl/test_fence_sync.cpp create mode 100644 test_conformance/gl/test_image_methods.cpp create mode 100644 test_conformance/gl/test_images_1D.cpp create mode 100644 test_conformance/gl/test_images_1Darray.cpp create mode 100644 test_conformance/gl/test_images_2D.cpp create mode 100644 test_conformance/gl/test_images_2Darray.cpp create mode 100644 test_conformance/gl/test_images_3D.cpp create mode 100644 test_conformance/gl/test_images_depth.cpp create mode 100644 test_conformance/gl/test_images_getinfo_common.cpp create mode 100644 test_conformance/gl/test_images_multisample.cpp create mode 100644 test_conformance/gl/test_images_read_common.cpp create mode 100644 test_conformance/gl/test_images_write_common.cpp create mode 100644 test_conformance/gl/test_renderbuffer.cpp create mode 100644 test_conformance/gl/test_renderbuffer_info.cpp create mode 100644 test_conformance/gles/CMakeLists.txt create mode 100644 test_conformance/gles/helpers.cpp create mode 100644 test_conformance/gles/main.cpp create mode 100644 test_conformance/gles/procs.h create mode 100644 test_conformance/gles/setup_egl.cpp create mode 100644 test_conformance/gles/testBase.h create mode 100644 test_conformance/gles/test_buffers.cpp create mode 100644 test_conformance/gles/test_fence_sync.cpp create mode 100644 test_conformance/gles/test_images_2D.cpp create mode 100644 test_conformance/gles/test_images_2D_info.cpp create mode 100644 test_conformance/gles/test_images_3D.cpp create mode 100644 test_conformance/gles/test_images_3D_info.cpp create mode 100644 test_conformance/gles/test_renderbuffer.cpp create mode 100644 test_conformance/gles/test_renderbuffer_info.cpp create mode 100644 test_conformance/half/CMakeLists.txt create mode 100644 test_conformance/half/Jamfile create mode 100644 test_conformance/half/Makefile create mode 100644 test_conformance/half/Test_half.xcodeproj/project.pbxproj create mode 100644 test_conformance/half/Test_roundTrip.c create mode 100644 test_conformance/half/Test_vLoadHalf.c create mode 100644 test_conformance/half/Test_vStoreHalf.c create mode 100644 test_conformance/half/cl_utils.c create mode 100644 test_conformance/half/cl_utils.h create mode 100644 test_conformance/half/main.c create mode 100644 test_conformance/half/test_config.h create mode 100644 test_conformance/half/tests.h create mode 100644 test_conformance/headers/CMakeLists.txt create mode 100644 test_conformance/headers/Makefile create mode 100644 test_conformance/headers/README.txt create mode 100644 test_conformance/headers/test_cl.h.c create mode 100644 test_conformance/headers/test_cl_gl.h.c create mode 100644 test_conformance/headers/test_cl_platform.h.c create mode 100644 test_conformance/headers/test_headers.c create mode 100644 test_conformance/headers/test_opencl.h.c create mode 100644 test_conformance/images/CMakeLists.txt create mode 100644 test_conformance/images/Jamfile create mode 100644 test_conformance/images/Makefile create mode 100644 test_conformance/images/clCopyImage/CMakeLists.txt create mode 100644 test_conformance/images/clCopyImage/Jamfile create mode 100644 test_conformance/images/clCopyImage/Makefile create mode 100644 test_conformance/images/clCopyImage/main.cpp create mode 100644 test_conformance/images/clCopyImage/test_copy_1D.cpp create mode 100644 test_conformance/images/clCopyImage/test_copy_1D_array.cpp create mode 100644 test_conformance/images/clCopyImage/test_copy_2D.cpp create mode 100644 test_conformance/images/clCopyImage/test_copy_2D_2D_array.cpp create mode 100644 test_conformance/images/clCopyImage/test_copy_2D_3D.cpp create mode 100644 test_conformance/images/clCopyImage/test_copy_2D_array.cpp create mode 100644 test_conformance/images/clCopyImage/test_copy_3D.cpp create mode 100644 test_conformance/images/clCopyImage/test_copy_3D_2D_array.cpp create mode 100644 test_conformance/images/clCopyImage/test_copy_generic.cpp create mode 100644 test_conformance/images/clCopyImage/test_loops.cpp create mode 100644 test_conformance/images/clFillImage/CMakeLists.txt create mode 100644 test_conformance/images/clFillImage/Jamfile create mode 100644 test_conformance/images/clFillImage/Makefile create mode 100644 test_conformance/images/clFillImage/main.cpp create mode 100644 test_conformance/images/clFillImage/test_fill_1D.cpp create mode 100644 test_conformance/images/clFillImage/test_fill_1D_array.cpp create mode 100644 test_conformance/images/clFillImage/test_fill_2D.cpp create mode 100644 test_conformance/images/clFillImage/test_fill_2D_array.cpp create mode 100644 test_conformance/images/clFillImage/test_fill_3D.cpp create mode 100644 test_conformance/images/clFillImage/test_fill_generic.cpp create mode 100644 test_conformance/images/clFillImage/test_loops.cpp create mode 100644 test_conformance/images/clGetInfo/CMakeLists.txt create mode 100644 test_conformance/images/clGetInfo/Jamfile create mode 100644 test_conformance/images/clGetInfo/Makefile create mode 100644 test_conformance/images/clGetInfo/main.cpp create mode 100644 test_conformance/images/clGetInfo/test_1D.cpp create mode 100644 test_conformance/images/clGetInfo/test_1D_2D_array.cpp create mode 100644 test_conformance/images/clGetInfo/test_2D.cpp create mode 100644 test_conformance/images/clGetInfo/test_3D.cpp create mode 100644 test_conformance/images/clGetInfo/test_loops.cpp create mode 100644 test_conformance/images/clReadWriteImage/CMakeLists.txt create mode 100644 test_conformance/images/clReadWriteImage/Jamfile create mode 100644 test_conformance/images/clReadWriteImage/Makefile create mode 100644 test_conformance/images/clReadWriteImage/main.cpp create mode 100644 test_conformance/images/clReadWriteImage/test_loops.cpp create mode 100644 test_conformance/images/clReadWriteImage/test_read_1D.cpp create mode 100644 test_conformance/images/clReadWriteImage/test_read_1D_array.cpp create mode 100644 test_conformance/images/clReadWriteImage/test_read_2D.cpp create mode 100644 test_conformance/images/clReadWriteImage/test_read_2D_array.cpp create mode 100644 test_conformance/images/clReadWriteImage/test_read_3D.cpp create mode 100644 test_conformance/images/kernel_image_methods/CMakeLists.txt create mode 100644 test_conformance/images/kernel_image_methods/Jamfile create mode 100644 test_conformance/images/kernel_image_methods/Makefile create mode 100644 test_conformance/images/kernel_image_methods/main.cpp create mode 100644 test_conformance/images/kernel_image_methods/test_1D.cpp create mode 100644 test_conformance/images/kernel_image_methods/test_1D_array.cpp create mode 100644 test_conformance/images/kernel_image_methods/test_2D.cpp create mode 100644 test_conformance/images/kernel_image_methods/test_2D_array.cpp create mode 100644 test_conformance/images/kernel_image_methods/test_3D.cpp create mode 100644 test_conformance/images/kernel_image_methods/test_loops.cpp create mode 100644 test_conformance/images/kernel_read_write/CMakeLists.txt create mode 100644 test_conformance/images/kernel_read_write/Jamfile create mode 100644 test_conformance/images/kernel_read_write/Makefile create mode 100644 test_conformance/images/kernel_read_write/main.cpp create mode 100644 test_conformance/images/kernel_read_write/test_iterations.cpp create mode 100644 test_conformance/images/kernel_read_write/test_loops.cpp create mode 100644 test_conformance/images/kernel_read_write/test_read_1D.cpp create mode 100644 test_conformance/images/kernel_read_write/test_read_1D_array.cpp create mode 100644 test_conformance/images/kernel_read_write/test_read_2D_array.cpp create mode 100644 test_conformance/images/kernel_read_write/test_read_3D.cpp create mode 100644 test_conformance/images/kernel_read_write/test_write_1D.cpp create mode 100644 test_conformance/images/kernel_read_write/test_write_1D_array.cpp create mode 100644 test_conformance/images/kernel_read_write/test_write_2D_array.cpp create mode 100644 test_conformance/images/kernel_read_write/test_write_3D.cpp create mode 100644 test_conformance/images/kernel_read_write/test_write_image.cpp create mode 100644 test_conformance/images/samplerlessReads/CMakeLists.txt create mode 100644 test_conformance/images/samplerlessReads/Jamfile create mode 100644 test_conformance/images/samplerlessReads/Makefile create mode 100644 test_conformance/images/samplerlessReads/main.cpp create mode 100644 test_conformance/images/samplerlessReads/test_iterations.cpp create mode 100644 test_conformance/images/samplerlessReads/test_loops.cpp create mode 100644 test_conformance/images/samplerlessReads/test_read_1D.cpp create mode 100644 test_conformance/images/samplerlessReads/test_read_1D_array.cpp create mode 100644 test_conformance/images/samplerlessReads/test_read_1D_buffer.cpp create mode 100644 test_conformance/images/samplerlessReads/test_read_2D_array.cpp create mode 100644 test_conformance/images/samplerlessReads/test_read_3D.cpp create mode 100644 test_conformance/images/testBase.h create mode 100644 test_conformance/integer_ops/CMakeLists.txt create mode 100644 test_conformance/integer_ops/Jamfile create mode 100644 test_conformance/integer_ops/Makefile create mode 100644 test_conformance/integer_ops/main.c create mode 100644 test_conformance/integer_ops/procs.h create mode 100644 test_conformance/integer_ops/testBase.h create mode 100644 test_conformance/integer_ops/test_abs.c create mode 100644 test_conformance/integer_ops/test_absdiff.c create mode 100644 test_conformance/integer_ops/test_add_sat.c create mode 100644 test_conformance/integer_ops/test_int_basic_ops.c create mode 100644 test_conformance/integer_ops/test_integers.cpp create mode 100644 test_conformance/integer_ops/test_intmad24.c create mode 100644 test_conformance/integer_ops/test_intmul24.c create mode 100644 test_conformance/integer_ops/test_popcount.c create mode 100644 test_conformance/integer_ops/test_sub_sat.c create mode 100644 test_conformance/integer_ops/test_unary_ops.cpp create mode 100644 test_conformance/integer_ops/test_upsample.cpp create mode 100644 test_conformance/integer_ops/verification_and_generation_functions.c create mode 100644 test_conformance/math_brute_force/CMakeLists.txt create mode 100644 test_conformance/math_brute_force/FunctionList.c create mode 100644 test_conformance/math_brute_force/FunctionList.h create mode 100644 test_conformance/math_brute_force/Jamfile create mode 100644 test_conformance/math_brute_force/Makefile create mode 100644 test_conformance/math_brute_force/README.txt create mode 100644 test_conformance/math_brute_force/Sleep.c create mode 100644 test_conformance/math_brute_force/Sleep.h create mode 100644 test_conformance/math_brute_force/Utility.c create mode 100644 test_conformance/math_brute_force/Utility.h create mode 100644 test_conformance/math_brute_force/binary.c create mode 100644 test_conformance/math_brute_force/binaryOperator.c create mode 100644 test_conformance/math_brute_force/binary_i.c create mode 100644 test_conformance/math_brute_force/binary_two_results_i.c create mode 100644 test_conformance/math_brute_force/i_unary.c create mode 100644 test_conformance/math_brute_force/macro_binary.c create mode 100644 test_conformance/math_brute_force/macro_unary.c create mode 100644 test_conformance/math_brute_force/mad.c create mode 100644 test_conformance/math_brute_force/main.c create mode 100644 test_conformance/math_brute_force/reference_math.c create mode 100644 test_conformance/math_brute_force/reference_math.h create mode 100644 test_conformance/math_brute_force/run_math_brute_force_in_parallel.py create mode 100644 test_conformance/math_brute_force/ternary.c create mode 100644 test_conformance/math_brute_force/unary.c create mode 100644 test_conformance/math_brute_force/unary_two_results.c create mode 100644 test_conformance/math_brute_force/unary_two_results_i.c create mode 100644 test_conformance/math_brute_force/unary_u.c create mode 100644 test_conformance/mem_host_flags/CMakeLists.txt create mode 100644 test_conformance/mem_host_flags/C_host_memory_block.h create mode 100644 test_conformance/mem_host_flags/Makefile create mode 100644 test_conformance/mem_host_flags/checker.h create mode 100644 test_conformance/mem_host_flags/checker_image_mem_host_no_access.hpp create mode 100644 test_conformance/mem_host_flags/checker_image_mem_host_read_only.hpp create mode 100644 test_conformance/mem_host_flags/checker_image_mem_host_write_only.hpp create mode 100644 test_conformance/mem_host_flags/checker_mem_host_no_access.hpp create mode 100644 test_conformance/mem_host_flags/checker_mem_host_read_only.hpp create mode 100644 test_conformance/mem_host_flags/checker_mem_host_write_only.hpp create mode 100644 test_conformance/mem_host_flags/main.cpp create mode 100644 test_conformance/mem_host_flags/mem_host_buffer.cpp create mode 100644 test_conformance/mem_host_flags/mem_host_image.cpp create mode 100644 test_conformance/mem_host_flags/procs.h create mode 100644 test_conformance/mem_host_flags/testBase.h create mode 100644 test_conformance/multiple_device_context/CMakeLists.txt create mode 100644 test_conformance/multiple_device_context/Jamfile create mode 100644 test_conformance/multiple_device_context/Makefile create mode 100644 test_conformance/multiple_device_context/main.c create mode 100644 test_conformance/multiple_device_context/procs.h create mode 100644 test_conformance/multiple_device_context/testBase.h create mode 100644 test_conformance/multiple_device_context/test_multiple_contexts.c create mode 100644 test_conformance/multiple_device_context/test_multiple_devices.cpp create mode 100644 test_conformance/non_uniform_work_group/CMakeLists.txt create mode 100644 test_conformance/non_uniform_work_group/Makefile create mode 100644 test_conformance/non_uniform_work_group/TestNonUniformWorkGroup.cpp create mode 100644 test_conformance/non_uniform_work_group/TestNonUniformWorkGroup.h create mode 100644 test_conformance/non_uniform_work_group/main.cpp create mode 100644 test_conformance/non_uniform_work_group/procs.h create mode 100644 test_conformance/non_uniform_work_group/test_advanced_2d.cpp create mode 100644 test_conformance/non_uniform_work_group/test_advanced_3d.cpp create mode 100644 test_conformance/non_uniform_work_group/test_advanced_other.cpp create mode 100644 test_conformance/non_uniform_work_group/test_basic.cpp create mode 100644 test_conformance/non_uniform_work_group/tools.cpp create mode 100644 test_conformance/non_uniform_work_group/tools.h create mode 100644 test_conformance/opencl_conformance_tests_21_full_spirv.csv create mode 100644 test_conformance/opencl_conformance_tests_21_legacy_wimpy.csv create mode 100644 test_conformance/opencl_conformance_tests_22.csv create mode 100644 test_conformance/opencl_conformance_tests_conversions.csv create mode 100644 test_conformance/opencl_conformance_tests_d3d.csv create mode 100644 test_conformance/opencl_conformance_tests_full.csv create mode 100644 test_conformance/opencl_conformance_tests_full_no_math_or_conversions.csv create mode 100644 test_conformance/opencl_conformance_tests_generate_spirv.csv create mode 100644 test_conformance/opencl_conformance_tests_math.csv create mode 100644 test_conformance/opencl_conformance_tests_quick.csv create mode 100644 test_conformance/pipes/CMakeLists.txt create mode 100644 test_conformance/pipes/kernels.h create mode 100644 test_conformance/pipes/main.c create mode 100644 test_conformance/pipes/procs.h create mode 100644 test_conformance/pipes/test_pipe_info.c create mode 100644 test_conformance/pipes/test_pipe_limits.c create mode 100644 test_conformance/pipes/test_pipe_query_functions.c create mode 100644 test_conformance/pipes/test_pipe_read_write.c create mode 100644 test_conformance/pipes/test_pipe_readwrite_errors.c create mode 100644 test_conformance/pipes/test_pipe_subgroups.c create mode 100644 test_conformance/printf/CMakeLists.txt create mode 100644 test_conformance/printf/Jamfile create mode 100644 test_conformance/printf/Makefile create mode 100644 test_conformance/printf/test_printf.c create mode 100644 test_conformance/printf/test_printf.h create mode 100644 test_conformance/printf/util_printf.c create mode 100644 test_conformance/profiling/CMakeLists.txt create mode 100644 test_conformance/profiling/Jamfile create mode 100644 test_conformance/profiling/Makefile create mode 100644 test_conformance/profiling/copy.c create mode 100644 test_conformance/profiling/execute.c create mode 100644 test_conformance/profiling/execute_multipass.c create mode 100644 test_conformance/profiling/main.c create mode 100644 test_conformance/profiling/procs.h create mode 100644 test_conformance/profiling/readArray.c create mode 100644 test_conformance/profiling/readImage.c create mode 100644 test_conformance/profiling/writeArray.c create mode 100644 test_conformance/profiling/writeImage.c create mode 100644 test_conformance/relationals/CMakeLists.txt create mode 100644 test_conformance/relationals/Jamfile create mode 100644 test_conformance/relationals/Makefile create mode 100644 test_conformance/relationals/main.c create mode 100644 test_conformance/relationals/procs.h create mode 100644 test_conformance/relationals/testBase.h create mode 100644 test_conformance/relationals/test_comparisons_double.cpp create mode 100644 test_conformance/relationals/test_comparisons_float.cpp create mode 100644 test_conformance/relationals/test_relationals.cpp create mode 100644 test_conformance/relationals/test_shuffles.cpp create mode 100644 test_conformance/run_conformance.py create mode 100644 test_conformance/select/CMakeLists.txt create mode 100644 test_conformance/select/Jamfile create mode 100644 test_conformance/select/Makefile create mode 100644 test_conformance/select/test_select.c create mode 100644 test_conformance/select/test_select.h create mode 100644 test_conformance/select/util_select.c create mode 100644 test_conformance/spir/CMakeLists.txt create mode 100644 test_conformance/spir/Makefile create mode 100644 test_conformance/spir/api.zip create mode 100644 test_conformance/spir/atomics.zip create mode 100644 test_conformance/spir/basic.zip create mode 100644 test_conformance/spir/binary_type.zip create mode 100644 test_conformance/spir/commonfns.zip create mode 100644 test_conformance/spir/compile_and_link.zip create mode 100644 test_conformance/spir/conversions.zip create mode 100644 test_conformance/spir/datagen.cpp create mode 100644 test_conformance/spir/datagen.h create mode 100644 test_conformance/spir/enum_values.zip create mode 100644 test_conformance/spir/exceptions.h create mode 100644 test_conformance/spir/geometrics.zip create mode 100644 test_conformance/spir/half.zip create mode 100644 test_conformance/spir/images_kernel_read_write.zip create mode 100644 test_conformance/spir/images_samplerlessRead.zip create mode 100644 test_conformance/spir/integer_ops.zip create mode 100644 test_conformance/spir/kernel_attributes.zip create mode 100644 test_conformance/spir/kernel_image_methods.zip create mode 100644 test_conformance/spir/kernelargs.cpp create mode 100644 test_conformance/spir/kernelargs.h create mode 100644 test_conformance/spir/khr.csv create mode 100644 test_conformance/spir/main.cpp create mode 100644 test_conformance/spir/math_brute_force.zip create mode 100644 test_conformance/spir/printf.zip create mode 100644 test_conformance/spir/profiling.zip create mode 100644 test_conformance/spir/relationals.zip create mode 100644 test_conformance/spir/run_build_test.cpp create mode 100644 test_conformance/spir/run_build_test.h create mode 100644 test_conformance/spir/run_services.cpp create mode 100644 test_conformance/spir/run_services.h create mode 100644 test_conformance/spir/sampler_enumeration.zip create mode 100644 test_conformance/spir/select.zip create mode 100644 test_conformance/spir/typeinfo.h create mode 100644 test_conformance/spir/vec_align.zip create mode 100644 test_conformance/spir/vec_step.zip create mode 100644 test_conformance/subgroups/CMakeLists.txt create mode 100644 test_conformance/subgroups/Jamfile create mode 100644 test_conformance/subgroups/main.cpp create mode 100644 test_conformance/subgroups/procs.h create mode 100644 test_conformance/subgroups/subhelpers.h create mode 100644 test_conformance/subgroups/test_barrier.cpp create mode 100644 test_conformance/subgroups/test_queries.cpp create mode 100644 test_conformance/subgroups/test_workgroup.cpp create mode 100644 test_conformance/subgroups/test_workitem.cpp create mode 100644 test_conformance/submission_details_template.txt create mode 100644 test_conformance/thread_dimensions/CMakeLists.txt create mode 100644 test_conformance/thread_dimensions/Jamfile create mode 100644 test_conformance/thread_dimensions/Makefile create mode 100644 test_conformance/thread_dimensions/main.c create mode 100644 test_conformance/thread_dimensions/procs.h create mode 100644 test_conformance/thread_dimensions/test_thread_dimensions.c create mode 100644 test_conformance/vec_align/CMakeLists.txt create mode 100644 test_conformance/vec_align/Jamfile create mode 100644 test_conformance/vec_align/Makefile create mode 100644 test_conformance/vec_align/defines.h create mode 100644 test_conformance/vec_align/globals.c create mode 100644 test_conformance/vec_align/main.c create mode 100644 test_conformance/vec_align/procs.h create mode 100644 test_conformance/vec_align/structs.c create mode 100644 test_conformance/vec_align/structs.h create mode 100644 test_conformance/vec_align/testBase.h create mode 100644 test_conformance/vec_align/test_vec_align.c create mode 100644 test_conformance/vec_align/type_replacer.c create mode 100644 test_conformance/vec_align/type_replacer.h create mode 100644 test_conformance/vec_step/CMakeLists.txt create mode 100644 test_conformance/vec_step/Jamfile create mode 100644 test_conformance/vec_step/Makefile create mode 100644 test_conformance/vec_step/defines.h create mode 100644 test_conformance/vec_step/globals.c create mode 100644 test_conformance/vec_step/main.c create mode 100644 test_conformance/vec_step/procs.h create mode 100644 test_conformance/vec_step/structs.c create mode 100644 test_conformance/vec_step/structs.h create mode 100644 test_conformance/vec_step/testBase.h create mode 100644 test_conformance/vec_step/test_step.c create mode 100644 test_conformance/vec_step/type_replacer.c create mode 100644 test_conformance/vec_step/type_replacer.h create mode 100644 test_conformance/workgroups/CMakeLists.txt create mode 100644 test_conformance/workgroups/Makefile create mode 100644 test_conformance/workgroups/main.c create mode 100644 test_conformance/workgroups/procs.h create mode 100644 test_conformance/workgroups/testBase.h create mode 100644 test_conformance/workgroups/test_wg_all.c create mode 100644 test_conformance/workgroups/test_wg_any.c create mode 100644 test_conformance/workgroups/test_wg_broadcast.c create mode 100644 test_conformance/workgroups/test_wg_reduce.c create mode 100644 test_conformance/workgroups/test_wg_reduce_max.c create mode 100644 test_conformance/workgroups/test_wg_reduce_min.c create mode 100644 test_conformance/workgroups/test_wg_scan_exclusive_add.c create mode 100644 test_conformance/workgroups/test_wg_scan_exclusive_max.c create mode 100644 test_conformance/workgroups/test_wg_scan_exclusive_min.c create mode 100644 test_conformance/workgroups/test_wg_scan_inclusive_add.c create mode 100644 test_conformance/workgroups/test_wg_scan_inclusive_max.c create mode 100644 test_conformance/workgroups/test_wg_scan_inclusive_min.c create mode 100644 test_extensions/media_sharing/CMakeLists.txt create mode 100644 test_extensions/media_sharing/Makefile create mode 100644 test_extensions/media_sharing/main.cpp create mode 100644 test_extensions/media_sharing/test_create_context.cpp create mode 100644 test_extensions/media_sharing/test_functions_api.cpp create mode 100644 test_extensions/media_sharing/test_functions_kernel.cpp create mode 100644 test_extensions/media_sharing/test_get_device_ids.cpp create mode 100644 test_extensions/media_sharing/test_interop_sync.cpp create mode 100644 test_extensions/media_sharing/test_memory_access.cpp create mode 100644 test_extensions/media_sharing/test_other_data_types.cpp create mode 100644 test_extensions/media_sharing/utils.cpp create mode 100644 test_extensions/media_sharing/utils.h create mode 100644 test_extensions/media_sharing/wrappers.cpp create mode 100644 test_extensions/media_sharing/wrappers.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..b826e68b --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# build directories +build/ +build_lnx/ +build_win/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..a1f40261 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,211 @@ +set( CONFORMANCE_SUFFIX "" ) +set(CLConform_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + +project(CLConform${CONFORMANCE_SUFFIX}) + +if(CMAKE_BUILD_TYPE STREQUAL "release") + set (BUILD_FLAVOR "release") +else(CMAKE_BUILD_TYPE STREQUAL "release") + set (BUILD_FLAVOR "debug") +endif(CMAKE_BUILD_TYPE STREQUAL "release") + +set(CLConform_VERSION_MAJOR "2") +set(CLConform_VERSION_MINOR "2") +set(CLConform_VERSION_MICRO "0") +set(CLConform_VERSION_EXTRA "") +set(CLConform_VERSION "${CLConform_VERSION_MAJOR}.${CLConform_VERSION_MINOR}") +set(CLConform_VERSION_FULL + "${CLConform_VERSION}.${CLConform_VERSION_MICRO}${CLConform_VERSION_EXTRA}") + +cmake_minimum_required(VERSION 2.8) + +add_definitions(-DCL_USE_DEPRECATED_OPENCL_2_1_APIS=1) +add_definitions(-DCL_USE_DEPRECATED_OPENCL_2_0_APIS=1) +add_definitions(-DCL_USE_DEPRECATED_OPENCL_1_2_APIS=1) +add_definitions(-DCL_USE_DEPRECATED_OPENCL_1_1_APIS=1) +add_definitions(-DCL_USE_DEPRECATED_OPENCL_1_0_APIS=1) + +# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) + + +# Support both VS2008 and VS2012. +set(BUILD_DIR "$ENV{ADRENO_DRIVER}/build") +if(MSVC90) + set(VS_BUILD_DIR "${BUILD_DIR}/vs2008") +else(MSVC110) + set(VS_BUILD_DIR "${BUILD_DIR}/vs2012") +endif(MSVC90) + +#----------------------------------------------------------- +# Default Configurable Test Set +#----------------------------------------------------------- +set(D3D10_IS_SUPPORTED) +set(D3D11_IS_SUPPORTED) +set(GL_IS_SUPPORTED) + + +#----------------------------------------------------------- +# Tests prefix and suffix +#----------------------------------------------------------- +# Set the prefix and suffix for the generated executables +# For example, if you want the api executable to be test_conformance_api_12 +# Set previx to "test_conformance_" and suffix to "_12" +set(CONFORMANCE_PREFIX "test_" ) +set(CONFORMNACE_SUFFIX "" ) + +#----------------------------------------------------------- +# Vendor Customization +#----------------------------------------------------------- +#Vendor Customization File can be included here to provide a way to automatically +#build driver as a depencency of the conformance tests, or other such CMake customization +option(USE_VENDOR_CUSTOM_FILE "Use Vendor Customization File" OFF) +if(USE_VENDOR_CUSTOM_FILE) + include(CMakeVendor.txt OPTIONAL) +endif(USE_VENDOR_CUSTOM_FILE) + +#----------------------------------------------------------- +# Development options for OpenCL C++ tests +#----------------------------------------------------------- +# Use OpenCL C kernels instead of OpenCL C++ kernels +option(CLPP_DEVELOPMENT_USE_OPENCLC_KERNELS "Use OpenCL C kernels in OpenCL C++ tests" OFF) +if(CLPP_DEVELOPMENT_USE_OPENCLC_KERNELS) + set(CLPP_DEVELOPMENT_OPTIONS ${CLPP_DEVELOPMENT_OPTIONS} -DCLPP_DEVELOPMENT_USE_OPENCLC_KERNELS) +endif(CLPP_DEVELOPMENT_USE_OPENCLC_KERNELS) +# Only check if OpenCL C++ kernels compile to SPIR-V +option(CLPP_DEVELOPMENT_ONLY_SPIRV_COMPILATION "Only check if OpenCL C++ kernels compile to SPIR-V" OFF) +if(CLPP_DEVELOPMENT_ONLY_SPIRV_COMPILATION) + if(CLPP_DEVELOPMENT_USE_OPENCLC_KERNELS) + message(FATAL_ERROR "Can't use OpenCL C kernels and compile to SPIR-V.") + endif(CLPP_DEVELOPMENT_USE_OPENCLC_KERNELS) + set(CLPP_DEVELOPMENT_OPTIONS ${CLPP_DEVELOPMENT_OPTIONS} -DCLPP_DEVELOPMENT_ONLY_SPIRV_COMPILATION) +endif(CLPP_DEVELOPMENT_ONLY_SPIRV_COMPILATION) +# +if(CLPP_DEVELOPMENT_OPTIONS) + add_definitions(-DCLPP_DEVELOPMENT_OPTIONS) + add_definitions(${CLPP_DEVELOPMENT_OPTIONS}) +endif(CLPP_DEVELOPMENT_OPTIONS) + +# Offline OpenCL C/C++ compiler provided by Khronos is the only supported +# offline compiler. +# +# Path to offline OpenCL C/C++ compiler provided by Khronos. +# See https://github.com/KhronosGroup/SPIR/ (spirv-1.1 branch or newer SPIR-V-ready +# branch should be used). +if(CL_OFFLINE_COMPILER) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DCL_OFFLINE_COMPILER=${CL_OFFLINE_COMPILER}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCL_OFFLINE_COMPILER=${CL_OFFLINE_COMPILER}") + # Additional OpenCL C/C++ compiler option. + if(CL_OFFLINE_COMPILER_OPTIONS) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DCL_OFFLINE_COMPILER_OPTIONS=${CL_OFFLINE_COMPILER_OPTIONS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCL_OFFLINE_COMPILER_OPTIONS=${CL_OFFLINE_COMPILER_OPTIONS}") + endif(CL_OFFLINE_COMPILER_OPTIONS) +else(CL_OFFLINE_COMPILER) + message(STATUS "OpenCL C/C++ compiler hasn't been found!") + message(FATAL_ERROR "Pass path to OpenCL C/C++ compiler in CL_OFFLINE_COMPILER") +endif(CL_OFFLINE_COMPILER) + +# CL_LIBCLCXX_DIR - path to dir with OpenCL C++ STL (libclcxx) +# CL_INCLUDE_DIR - path to dir with OpenCL headers +# CL_LIBCLCXX_DIR - path to dir with OpenCL library +if(CL_INCLUDE_DIR AND CL_LIB_DIR AND CL_LIBCLCXX_DIR) + set(OPENCL_INCLUDE_DIR ${CL_INCLUDE_DIR}) + link_directories(${CL_LIB_DIR}) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DCL_LIBCLCXX_DIR=${CL_LIBCLCXX_DIR}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCL_LIBCLCXX_DIR=${CL_LIBCLCXX_DIR}") +else(CL_INCLUDE_DIR AND CL_LIB_DIR AND CL_LIBCLCXX_DIR) + message(STATUS "OpenCL hasn't been found!") + message(FATAL_ERROR "Either install OpenCL or pass -DCL_INCLUDE_DIR, -DCL_LIB_DIR and -DCL_LIBCLCXX_DIR") +endif(CL_INCLUDE_DIR AND CL_LIB_DIR AND CL_LIBCLCXX_DIR) + +include(CheckFunctionExists) +include(CheckIncludeFiles) + +if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # -msse -mfpmath=sse to force gcc to use sse for float math, + # avoiding excess precision problems that cause tests like int2float + # to falsely fail. -ffloat-store also works, but WG suggested + # that sse would be better. + if(CMAKE_ARM_COMPILER OR ANDROID) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -std=gnu99 -Wno-narrowing") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=gnu++11 -Wno-narrowing") + else(CMAKE_ARM_COMPILER OR ANDROID) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -std=gnu99 -msse -mfpmath=sse -Wno-narrowing") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -msse -mfpmath=sse -std=gnu++11 -Wno-narrowing") + endif(CMAKE_ARM_COMPILER OR ANDROID) +else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D__SSE__") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D__SSE__") +endif() + +list(APPEND CLConform_LIBRARIES ${OPENCL_LIBRARIES}) +if(ANDROID) + list(APPEND CLConform_LIBRARIES m) +elseif(NOT WIN32) + list(APPEND CLConform_LIBRARIES pthread) +endif(ANDROID) + +if(APPLE) + find_library(corefoundation CoreFoundation) + find_library(iokit IOKit) + list(APPEND CLConform_LIBRARIES ${corefoundation}) + list(APPEND CLConform_LIBRARIES ${iokit}) +endif(APPLE) + +include_directories(SYSTEM ${OPENCL_INCLUDE_DIR}) +include_directories(${CLConform_SOURCE_DIR}/test_common/harness + ${CLConform_SOURCE_DIR}/test_common/gles + ${CLConform_SOURCE_DIR}/test_common/gl + ${CMAKE_CURRENT_SOURCE_DIR}/test_common/harness) + +if(CMAKE_BUILD_TYPE STREQUAL "release") + set (BUILD_FLAVOR "release") +elseif (CMAKE_BUILD_TYPE STREQUAL "debug") + set (BUILD_FLAVOR "debug") +endif(CMAKE_BUILD_TYPE STREQUAL "release") + + +add_subdirectory(test_conformance) + +set (PY_PATH "${CLConform_SOURCE_DIR}/test_conformance/*.py") +set (CSV_PATH "${CLConform_SOURCE_DIR}/test_conformance/*.csv") +# Support both VS2008 and VS2012. +set (DLL_FILES "${VS_BUILD_DIR}/Debug/*.dll") +set (DST_DIR "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug/") + +if (WIN32) + set (COPY "echo") + add_custom_target(COPY_DLL${CONFORMANCE_SUFFIX} ALL + COMMAND ${COPY} "${DLL_FILES}" "${DST_DIR}" + COMMENT "Copying dll files.. ") +else (WIN32) + set (COPY cp) + add_custom_target(COPY_DLL${CONFORMANCE_SUFFIX}) +endif(WIN32) + +set_property(TARGET COPY_DLL${CONFORMANCE_SUFFIX} PROPERTY FOLDER "CONFORMANCE${CONFORMANCE_SUFFIX}") + +if(WIN32) + add_custom_target( COPY_FILES${CONFORMANCE_SUFFIX} ALL + COMMAND ${COPY} ${PY_PATH} ${DST_DIR} + COMMAND ${COPY} ${CSV_PATH} ${DST_DIR} + COMMAND ${COPY} ${DLL_FILES} ${DST_DIR} + COMMENT "Copying other files to output folder..." ) +else(WIN32) + add_custom_target( COPY_FILES${CONFORMANCE_SUFFIX} ) +endif(WIN32) + +# Copy required CL include directories into the build directory +# as required for the compiler testing. + +# ... For running the compiler test on the command line. +file(COPY "${CLConform_SOURCE_DIR}/test_conformance/compiler/includeTestDirectory" DESTINATION ${DST_DIR}) +file(COPY "${CLConform_SOURCE_DIR}/test_conformance/compiler/secondIncludeTestDirectory" DESTINATION ${DST_DIR}) + +# ... For running the compiler test with VisualStudio. +if(MSVC) + file(COPY "${CLConform_SOURCE_DIR}/test_conformance/compiler/includeTestDirectory" DESTINATION "${CLConform_SOURCE_DIR}/build/test_conformance/compiler") + file(COPY "${CLConform_SOURCE_DIR}/test_conformance/compiler/secondIncludeTestDirectory" DESTINATION "${CLConform_SOURCE_DIR}/build/test_conformance/compiler") +endif(MSVC) + +set_property(TARGET COPY_FILES${CONFORMANCE_SUFFIX} PROPERTY FOLDER "CONFORMANCE${CONFORMANCE_SUFFIX}") diff --git a/CMakeVendor.txt b/CMakeVendor.txt new file mode 100644 index 00000000..0f59481e --- /dev/null +++ b/CMakeVendor.txt @@ -0,0 +1,15 @@ +# Include cmake files to build driver +# to build driver as a dependency of tests +# in this example environment variable $OPENCL_DRIVER points to driver base +# Ex include($ENV{OPENCL_DRIVER}/driver.cmake) + +# We intentionally hardcode "_win32" to ensure backwards compatibility (to avoid breaking HAAVE) +if(ANDROID) + if(ARM64_V8A) + set(ARCH "64") + else(ARM64_V8A) + set(ARCH "32") + endif(ARM64_V8A) +endif (ANDROID) + +set (CL_INCLUDE_DIR "$ENV{OPENCL_DRIVER}/include/public/") diff --git a/build_android.py b/build_android.py new file mode 100644 index 00000000..2bd7f5c8 --- /dev/null +++ b/build_android.py @@ -0,0 +1,159 @@ +#!/usr/bin/python + + +#-------------------------------------------------------------------------------# +# android-cmake and android-ndk based build script for conformance +#-------------------------------------------------------------------------------# +""" +Dependencies: + +1) android-ndk version android-ndk-r10d or higher is required. Further, the environment + variable ANDROID_NDK should be defined to point to it. + +2) android-cmake should be installed (else the script can install it for you). If installed, + the environment variable ANDROID_CMAKE should point to install location, unless it is in the current + working directory in which case it is picked up by default. + +3) CL_INCLUDE_DIR should be defined to point to CL headers. Alternately, this can be provided + as an input (-I) + +4) Path to opencl library to link against (libOpenCL.so) can be provided using -L. If this isn't + available the script will try to use CL_LIB_DIR_64 or CL_LIB_DIR_32 environment variables - + if available - to pick up the right library for the architecture being built. + + +""" + +import os +import sys +import subprocess +import argparse +import time +import shlex + +start = time.time() +script = os.path.basename( sys.argv[ 0 ] ) + +def die (msg): + print msg + exit(-1) + +def execute (cmdline): + retcode = subprocess.call(cmdline) + if retcode != 0: + raise Exception("Failed to execute '%s', got %d" % (commandLine, retcode)) + +def build(args): + if not (args.testDir): + print("building...") + execute("make") + else: + if os.path.exists( os.path.join(args.bld_dir, "test_conformance", args.testDir) ): + os.chdir( os.path.join("test_conformance",args.testDir) ) + print("Building test: %s..." %args.testDir) + execute("make") + os.chdir(args.bld_dir) + else: + print ("Error: %s test doesn't exist" %args.testDir) + + +def configure (args): + print("configuring...") + cmdline = [] + cmdline.extend(['cmake', "-DCMAKE_TOOLCHAIN_FILE=" + os.path.join(args.android_cmake,"android.toolchain.cmake")]) + for var in args.cmake_defs : + cmdline.extend([ '-D', var ]) + cmdline.extend(['-DCL_INCLUDE_DIR=' + args.inc_dir]) + cmdline.extend(['-DCL_LIB_DIR=' + args.lib_dir]) + cmdline.extend(['-DANDROID_NATIVE_API_LEVEL=' + "android-21"]) + if args.arch == "64": + cmdline.extend(['-DANDROID_ABI=arm64-v8a']) + cmdline.extend(['-DANDROID_SO_UNDEFINED=ON']) + cmdline.extend([args.src_dir]) + execute(cmdline) + +def check_var (parser, args, name): + if not(args.__dict__[name]): + parser.error("%s needs to be defined" % name) + +def print_config(args): + print("----------CONFIGURATION--------------\n") + print("android_cmake: %s" % args.android_cmake) + print("android_ndk: %s" % args.android_ndk) + print("lib_dir: %s" % args.lib_dir) + print("inc_dir: %s" % args.inc_dir) + if len(args.cmake_defs): + print("cmake options:" + "\n:".join( [ " `%s'" % dir for dir in args.cmake_defs ] )) + print("architecture: %s" % args.arch) + print("-------------------------------------\n") + +def get_input(): + yes = set(['yes','y', 'ye', '']) + no = set(['no','n']) + + choice = raw_input().lower() + if choice in yes: + return True + elif choice in no: + return False + else: + sys.stdout.write("Please respond with 'yes' or 'no'") + exit() + +def install_android_cmake(): + parser.print_help() + print "\nandroid-cmake doesn't seem to be installed - It should be provided as a) cmdline input b) environment variable $ANDROID_CMAKE or c) present in the current directory\n" + print "if you would like to download and install it in the current directory please enter yes\n" + print "if you would like to provide an environment variable($ANDROID_CMAKE) or command-line input(--android_cmake) rerun the script enter no\n" + print "input: " + if get_input(): + print("installing android-cmake") + subprocess.call(['git', 'clone', 'https://github.com/taka-no-me/android-cmake']) + args.android_cmake = os.path.join(args.src_dir,"android-cmake") + else: + exit() + +try: + parser = argparse.ArgumentParser() + parser.add_argument('--android_cmake', dest='android_cmake', default=os.environ.get('ANDROID_CMAKE'), help="Path to android-cmake (can also be set using environment variable $ANDROID_CMAKE).") + parser.add_argument('--android_ndk', dest='android_ndk', default=os.environ.get('ANDROID_NDK'), help="Path to android-ndk (can also be set using environment variable $ANDROID_NDK).") + parser.add_argument('-L','--lib_dir', dest='lib_dir', default="", help="Path to libOpenCL to link against (can also be set using environment variable $CL_LIB_DIR_32 and $CL_LIB_DIR_64).") + parser.add_argument('-I','--include_dir', dest='inc_dir', default=os.environ.get('CL_INCLUDE_DIR'), help="Path to headers (can also be set using environment variable $CL_INCLUDE_DIR).") + parser.add_argument('-D', dest='cmake_defs', action='append', default=[], help="Define CMAKE variable") + parser.add_argument('-a','--arch', default="32", help="Architecture to build for (32 or 64)") + parser.add_argument('-t','--test', dest='testDir', default="", help="Builds the given test") + + args = parser.parse_args() + + args.src_dir = os.path.realpath(os.path.dirname( sys.argv[ 0 ])) + + if not (args.android_cmake): + if os.path.exists(os.path.join(args.src_dir,"android-cmake")): + args.android_cmake = os.path.join(args.src_dir,"android-cmake") + else: + install_android_cmake() + + if not (args.lib_dir): + lib_var_name = "CL_LIB_DIR_" + ("32" if (args.arch == "32") else "64") + args.lib_dir = os.environ.get(lib_var_name) + + check_var(parser, args, "android_cmake") + check_var(parser, args, "lib_dir") + check_var(parser, args, "inc_dir") + check_var(parser, args, "android_ndk") + + print_config(args) + + args.bld_dir = os.path.join(args.src_dir, 'bld_android_%s' % args.arch) + if not os.path.exists(args.bld_dir): + os.makedirs(args.bld_dir) + os.chdir(args.bld_dir) + + configure(args) + build(args) + + sys.exit( 0 ) + +finally: + finish = time.time() + print("Elapsed time: %.0f s." % ( finish - start ) ) diff --git a/build_lnx.sh b/build_lnx.sh new file mode 100644 index 00000000..c9bde6e1 --- /dev/null +++ b/build_lnx.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +mkdir -p build_lnx +cd build_lnx +cmake -g "Unix Makefiles" ../ -DCL_OFFLINE_COMPILER= -DCL_LIBCLCXX_DIR= -DCL_INCLUDE_DIR= -DCL_LIB_DIR= -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=. -DOPENCL_LIBRARIES=OpenCL +make --jobs 8 diff --git a/build_win.bat b/build_win.bat new file mode 100644 index 00000000..0e715656 --- /dev/null +++ b/build_win.bat @@ -0,0 +1,32 @@ +@ECHO off +setlocal ENABLEDELAYEDEXPANSION + +IF DEFINED ProgramFiles(x86) SET ProgFilesDir=%ProgramFiles(x86)% +IF NOT DEFINED ProgFilesDir SET ProgFilesDir=%ProgramFiles% + +rem -------------------------------- Update these to match what's on your PC ------------------------------------------------ + +SET VCPATH="%ProgFilesDir%\Microsoft Visual Studio 14.0\Common7\IDE\devenv.com" + +SET PATH=%CMAKEPATH%;%PATH% + +rem ------------------------------------------------------------------------------------------------------------------------- + +setlocal ENABLEDELAYEDEXPANSION + +call "%VS140COMNTOOLS%\vsvars32.bat" + +mkdir build_win +pushd build_win +IF NOT EXIST CLConform.sln ( + echo "Solution file not found, running Cmake" + cmake -G "Visual Studio 14 2015 Win64" ..\. -DCL_OFFLINE_COMPILER= -DCL_LIBCLCXX_DIR= -DCL_INCLUDE_DIR= -DCL_LIB_DIR= -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=. -DOPENCL_LIBRARIES=OpenCL +) else ( + echo "Solution file found CLConform.sln " +) + +echo Building CLConform.sln... +%VCPATH% CLConform.sln /build + + +GOTO:EOF diff --git a/clean_tests.py b/clean_tests.py new file mode 100644 index 00000000..4ee0294f --- /dev/null +++ b/clean_tests.py @@ -0,0 +1,104 @@ +#!/usr/bin/python + +import sys, os, re +from subprocess import Popen, PIPE +from optparse import OptionParser + +# trail_spaces: This method removes the trailing whitespaces and trailing tabs +def trail_spaces(line): + newline=line + carreturn = 0 + if re.search("\r\n",line): + carreturn = 1 + status = re.search("\s+$",line) + if status: + if carreturn: + newline = re.sub("\s+$","\r\n",line) + else: + newline = re.sub("\s+$","\n",line) + + status = re.search("\t+$",newline) + if status: + newline = re.sub("\t+$","",newline) + return newline + +#convert_tabs: This methos converts tabs to 4 spaces +def convert_tabs(line): + newline=line + status = re.search("\t",line) + if status: + newline = re.sub("\t"," ",line) + return newline + +#convert_lineends: This method converts lineendings from DOS to Unix +def convert_lineends(line): + newline=line + status = re.search("\r\n",line) + if status: + newline = re.sub("\r\n","\n",line) + return newline + +#processfile: This method processes each file passed to it depending +# on the flags passed + +def processfile(file,tabs, lineends,trails,verbose): + processed_data = [] + if verbose: + print "processing file: "+file + + with open(file,'r') as fr: + data = fr.readlines() + for line in data: + if tabs: + line = convert_tabs(line) + if lineends: + line = convert_lineends(line) + if trails: + line = trail_spaces(line) + processed_data.append(line) + + with open(file,'w') as fw: + fw.writelines(processed_data) + +#findfiles: This method finds all the code files present in current +# directory and subdirectories. + +def findfiles(tabs,lineends,trails,verbose): + testfiles = [] + for root, dirs, files in os.walk("./"): + for file in files: + for extn in ('.c','.cpp','.h','.hpp'): + if file.endswith(extn): + testfiles.append(os.path.join(root, file)) + for file in testfiles: + processfile(file,tabs,lineends,trails,verbose) + +# Main function + +def main(): + + parser = OptionParser() + parser.add_option("--notabs", dest="tabs", action="store_false", default=True, help="Disable converting tabs to 4 spaces.") + parser.add_option("--notrails", dest="trails", action="store_false", default=True, help="Disable removing trailing whitespaces and trailing tabs.") + parser.add_option("--nolineends", dest="lineends", action="store_false", default=True, help=" Disable converting line endings to Unix from DOS.") + parser.add_option("--verbose", dest="verbose", action="store_true", default=False, help="Prints out the files being processed.") + parser.add_option("--git", dest="SHA1", default="", help="Processes only the files present in the particular commit.") + parser.add_option('-o', action="store", default=True, help="Default: All the code files (.c,.cpp,.h,.hpp) in the current directory and subdirectories will be processed") + + (options, args) = parser.parse_args() + + if options.SHA1: + pl = Popen(["git","show", "--pretty=format:", "--name-only",options.SHA1], stdout=PIPE) + cmdout = pl.communicate()[0] + gitout=cmdout.split("\n") + for file in gitout: + print file + if file: + processfile(file,options.tabs,options.lineends,options.trails,options.verbose) + + + if not options.SHA1: + findfiles(options.tabs,options.lineends,options.trails,options.verbose) + +# start the process by calling main +main() diff --git a/license.txt b/license.txt new file mode 100644 index 00000000..2784a09d --- /dev/null +++ b/license.txt @@ -0,0 +1,4 @@ +The code inside this directory and its subdirectories is +"Open GL (including Open CL) Automated Test System - Common Code" +and is subject to the license agreement between Apple and the licensee. + diff --git a/readme-spir-v-binaries.txt b/readme-spir-v-binaries.txt new file mode 100644 index 00000000..1b6df9bc --- /dev/null +++ b/readme-spir-v-binaries.txt @@ -0,0 +1,42 @@ +To run the 2.2 conformance tests test suite for the C++ features you need need +SPIR-V binaries. + +If you are using a conformance package then the binaries are included in the +package. If you are using conformance tests from gitlab repositories then the +binaries need to be picked up from Khronos SVN URL mentioned below: + +https://cvs.khronos.org/svn/repos/OpenCL/trunk/Khronos/spirv/spirv10_2015.11.25.zip + + +Alternatively you can check out and build all of the below repositories. + +1. SPIRV-LLVM +LLVM with support for SPIR-V (required by clang compiler) +Repository: https://gitlab.khronos.org/opencl/SPIRV-LLVM +Branch: spec_constants +Notes: spirv-3.6.1 is a main branch with support for OpenCL C++ kernel language, + spec_constants is based on it, but it adds support for specialization constants. + +2. Clang +Clang with support for OpenCL C++ kernel language +Repository: https://gitlab.khronos.org/opencl/clang +Branch: spec_constants +Notes: spirv-1.1 is a main branch with support for OpenCL C++ kernel language, + spec_constants is based on it, but it adds support for specialization constants. + +3. libclcxx +OpenCL C++ Standard Library +Repository: https://gitlab.khronos.org/opencl/libclcxx +Branch: lit_tests_cl22 +Notes: lit_tests_cl22 branch includes both LIT tests and changes introduced in + spec_constants branch, that is, implementation of Specialization Constants Library. + +4. OpenCL 2.2 headers +OpenCL 2.2 headers +Repository: https://gitlab.khronos.org/opencl/headers +Branch: opencl22 + +5. OpenCL ICD (with 2.2 support) +OpenCL ICD +Repository: https://gitlab.khronos.org/opencl/icd +Branch: dev_cl22 \ No newline at end of file diff --git a/test_common/Makefile b/test_common/Makefile new file mode 100644 index 00000000..6b930323 --- /dev/null +++ b/test_common/Makefile @@ -0,0 +1,32 @@ + +PRODUCTS = harness/\ + +# utils/ + +TOP=$(shell pwd) + +all: $(PRODUCTS) + +clean: + @for testdir in $(dir $(PRODUCTS)) ; \ + do ( \ + echo "==================================================================================" ; \ + echo "Cleaning $$testdir" ; \ + echo "==================================================================================" ; \ + if test -d $$testdir; \ + then cd $$testdir && make clean; \ + else echo "Warning: Directory '$$testdir' Does Not Exist"; \ + fi; \ + ); \ + done \ + +$(PRODUCTS): + @echo "==================================================================================" ; + @echo "(`date "+%H:%M:%S"`) Make $@" ; + @echo "==================================================================================" ; + @if test -d $@; \ + then cd $(dir $@) && make; \ + else echo "Warning: Directory '$@' Does Not Exist"; \ + fi; \ + +.PHONY: clean $(PRODUCTS) all diff --git a/test_common/autotest/autotest.hpp b/test_common/autotest/autotest.hpp new file mode 100644 index 00000000..cdaca6c3 --- /dev/null +++ b/test_common/autotest/autotest.hpp @@ -0,0 +1,58 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_COMMON_AUTOTEST_AUTOTEST_HPP +#define TEST_COMMON_AUTOTEST_AUTOTEST_HPP + +#include "test_suite.hpp" +#include "test_case.hpp" + +namespace autotest { + inline std::vector get_strings_ptrs(const std::vector& list) + { + std::vector v; + for(auto& s : list) + { + v.push_back(s.c_str()); + } + return v; + } +} + +#define STR_JOIN( X, Y ) STR_DO_JOIN( X, Y ) +#define STR_DO_JOIN( X, Y ) STR_DO_JOIN_2(X,Y) +#define STR_DO_JOIN_2( X, Y ) X##Y + + +// How to use AUTO_TEST_CASE macro: +// +// AUTO_TEST_CASE()(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +// { +// (test case code...) +// } +// +// It automatically registers created test case to global test_suite object. Test functions +// names and pointers to those functions can be later retrieved this way: +// - std::vector test_functions_list = autotest::test_suite::get_test_functions(); +// - std::vector test_functions_names = autotest::test_suite::get_test_names(); +// +// Helper function which constructs vector of const char pointers to test functions names: +// - std::vector test_functions_names_c_str = autotest::get_strings_ptrs(test_functions_names); +#define AUTO_TEST_CASE(name) \ + struct name { static int run_test(cl_device_id, cl_context, cl_command_queue, int); }; \ + static autotest::detail::test_case_registration STR_JOIN(name, STR_JOIN(_registration, __LINE__)) (#name, name::run_test); \ + int name::run_test + +#endif //TEST_COMMON_AUTOTEST_AUTOTEST_HPP \ No newline at end of file diff --git a/test_common/autotest/test_case.hpp b/test_common/autotest/test_case.hpp new file mode 100644 index 00000000..17e68aac --- /dev/null +++ b/test_common/autotest/test_case.hpp @@ -0,0 +1,41 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_COMMON_AUTOTEST_TEST_CASE_HPP +#define TEST_COMMON_AUTOTEST_TEST_CASE_HPP + +#include + +#include "../../test_common/harness/threadTesting.h" + +namespace autotest +{ + +struct test_case { + // Test case name + const std::string name; + // Pointer to test function. + const basefn function_pointer; + + test_case(const std::string& name, const basefn function_ptr) + : name(name), function_pointer(function_ptr) + { + + } +}; + +} // end namespace autotest + +#endif // TEST_COMMON_AUTOTEST_TEST_CASE_HPP diff --git a/test_common/autotest/test_suite.hpp b/test_common/autotest/test_suite.hpp new file mode 100644 index 00000000..70b3e4eb --- /dev/null +++ b/test_common/autotest/test_suite.hpp @@ -0,0 +1,83 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_COMMON_AUTOTEST_TEST_SUITE_HPP +#define TEST_COMMON_AUTOTEST_TEST_SUITE_HPP + +#include +#include + +#include "test_case.hpp" + +namespace autotest { + +struct test_suite { + test_suite(const std::string& name) + : name(name) + { + + } + + void add(const test_case& tc) + { + test_cases.push_back(tc); + } + + static std::vector get_test_functions() + { + std::vector v; + for(auto& tc: global_test_suite().test_cases) + { + v.push_back(tc.function_pointer); + } + return v; + } + + static std::vector get_test_names() + { + std::vector v; + for(auto& tc : global_test_suite().test_cases) + { + v.push_back(tc.name); + } + return v; + } + + // List of test cases + std::vector test_cases; + // Test suite name + const std::string name; + + static test_suite& global_test_suite() + { + static test_suite global_test_suite("global"); + return global_test_suite; + } +}; + +namespace detail { + +struct test_case_registration +{ + test_case_registration(const std::string& name, const basefn ptr) + { + ::autotest::test_suite::global_test_suite().add(test_case(name, ptr)); + } +}; + +} // end detail namespace +} // end autotest namespace + +#endif // TEST_COMMON_AUTOTEST_TEST_SUITE_HPP diff --git a/test_common/config.hpp b/test_common/config.hpp new file mode 100644 index 00000000..a037d4e4 --- /dev/null +++ b/test_common/config.hpp @@ -0,0 +1,41 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_COMMON_CONFIG_HPP +#define TEST_COMMON_CONFIG_HPP + +// Enable development options for OpenCL C++ tests (test_conformance/clpp) +// #define DEVELOPMENT +#if defined(CLPP_DEVELOPMENT_OPTIONS) && !defined(DEVELOPMENT) + #define DEVELOPMENT +#endif + +#ifdef DEVELOPMENT + // If defined OpenCL C++ tests only checks if OpenCL C++ kernels compiles correctly + // #define ONLY_SPIRV_COMPILATION + #if defined(CLPP_DEVELOPMENT_ONLY_SPIRV_COMPILATION) && !defined(ONLY_SPIRV_COMPILATION) + #define ONLY_SPIRV_COMPILATION + #endif + + #ifndef ONLY_SPIRV_COMPILATION + // If defined OpenCL C++ tests are run using OpenCL C kernels + // #define USE_OPENCLC_KERNELS + #if defined(CLPP_DEVELOPMENT_USE_OPENCLC_KERNELS) && !defined(USE_OPENCLC_KERNELS) + #define USE_OPENCLC_KERNELS + #endif + #endif +#endif + +#endif // TEST_COMMON_CONFIG_HPP \ No newline at end of file diff --git a/test_common/gl/gl_headers.h b/test_common/gl/gl_headers.h new file mode 100644 index 00000000..61fbe63c --- /dev/null +++ b/test_common/gl/gl_headers.h @@ -0,0 +1,60 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _gl_headers_h +#define _gl_headers_h + +#if defined( __APPLE__ ) + #include +#if defined(CGL_VERSION_1_3) + #include + #include +#else + #include + #include +#endif + #include +#else +#ifdef _WIN32 + #include +#endif +#if defined( __ANDROID__ ) + #ifndef GL_GLEXT_PROTOTYPES + #define GL_GLEXT_PROTOTYPES + #endif + #include + #include +#else + #include + #include + #include +#endif +#ifdef _WIN32 + #include +#elif !defined(__ANDROID__) + #include +#endif + +#endif + +#ifdef _WIN32 + GLboolean gluCheckExtension(const GLubyte *extName, const GLubyte *extString); + // No glutGetProcAddress in the standard glut v3.7. + #define glutGetProcAddress(procName) wglGetProcAddress(procName) +#endif + + +#endif // __gl_headers_h + diff --git a/test_common/gl/helpers.cpp b/test_common/gl/helpers.cpp new file mode 100644 index 00000000..c02a4b12 --- /dev/null +++ b/test_common/gl/helpers.cpp @@ -0,0 +1,2496 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "helpers.h" +#include "../harness/imageHelpers.h" + +// convert_float_to_half and convert_half_to_float may be found in test_conformance/images/image_helpers.cpp +cl_ushort convert_float_to_half( cl_float f ); +cl_float convert_half_to_float( cl_ushort h ); + +#if defined( __APPLE__ ) + #include +#else + #include +#endif + +#if defined(__linux__) +// On linux we dont link to GLU library to avoid comaptibility issues with +// libstdc++ +// FIXME: Implement this +const GLubyte* gluErrorString (GLenum error) +{ + const char* gl_Error = "OpenGL Error"; + return (const GLubyte*)gl_Error; +} +#endif + +void * CreateGLTexture1DArray(size_t width, size_t length, + GLenum target, GLenum glFormat, GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, int *outError, + bool allocateMem, MTdata d) +{ + *outError = 0; + GLenum err = 0; + + char * buffer; + unsigned int size = 0; + + // width_in_pixels * pixel_width * number_of_images: + if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) ) + { + size = width * length; + } + else + { + size = width * length * 4; + } + + buffer = (char *)CreateRandomData(type, size, d); + + glGenTextures( 1, outTextureID ); + glBindTexture( get_base_gl_target( target ), *outTextureID ); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + err = glGetError(); + if( err != GL_NO_ERROR ) { + log_error( "ERROR: Failed to create GL texture object: %s!\n", gluErrorString( err )); + *outError = -1; + free( buffer ); + return NULL; + } + + // use TexImage2D to pump the 1D array fill of bits: + glTexImage2D( get_base_gl_target(target), 0, internalFormat, (GLsizei)width, + (GLsizei)length, 0, glFormat, glType, buffer ); + + err = glGetError(); + if( err != GL_NO_ERROR ) { + if (err != GL_OUT_OF_MEMORY) { + log_error( "ERROR: Unable to load data using glTexImage2D for " + "TEXTURE_1D_ARRAY : %s : %s : %d : %d : %s : %s : Error %s\n", + GetGLTargetName(target), + GetGLFormatName(internalFormat), + (int)(width), (int)(length), + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + + *outError = -1; + } else { + log_info( "WARNING: Unable to load data using glTexImage2D for " + "TEXTURE_1D_ARRAY : %s : %s : %d : %d : %s : %s : Error %s\n", + GetGLTargetName(target), + GetGLFormatName(internalFormat), + (int)(width), (int)(length), + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + + *outError = -2; + } + free( buffer ); + return NULL; + } + + if( !allocateMem ) { + free( buffer ); + return NULL; + } + + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * length; i++ ) { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } + else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * length; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc1; + p[ i * 4 + 1 ] = uc2; + p[ i * 4 + 2 ] = uc3; + p[ i * 4 + 3 ] = uc0; + } + } + + return buffer; +} + +void * CreateGLTexture2DArray(size_t width, size_t height, size_t length, + GLenum target, GLenum glFormat, GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, int *outError, + bool allocateMem, MTdata d) +{ + *outError = 0; + + char * buffer; + unsigned int size = 0; + + if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) ) + { + size = width * height * length; + } + else + { + size = width * height * length * 4; + } + + buffer = (char *)CreateRandomData(type, size, d); + + if( type == kFloat && allocateMem ) + { + // Re-fill the created buffer to just have [0-1] floats, since that's what it'd expect + cl_float *p = (cl_float *)buffer; + for( size_t i = 0; i < size; i++ ) + { + p[ i ] = (float) genrand_real1( d ); + } + } + else if( !allocateMem ) + memset( buffer, 0, size * get_explicit_type_size( type ) ); + + glGenTextures( 1, outTextureID ); + + glBindTexture( target, *outTextureID ); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + glGetError(); + //the default alignment in OpenGL is 4 bytes and need to be changed for GL_DEPTH_COMPONENT16 which is aligned to 2 bytes + if (internalFormat == GL_DEPTH_COMPONENT16) + glPixelStorei(GL_UNPACK_ALIGNMENT, get_explicit_type_size( type )); + + glTexImage3D( target, 0, internalFormat, (GLsizei)width, (GLsizei)height, + (GLsizei)length, 0, glFormat, glType, buffer ); + + if (internalFormat == GL_DEPTH_COMPONENT16) + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + + GLenum err = glGetError(); + if( err != GL_NO_ERROR ) + { + if (err != GL_OUT_OF_MEMORY) { + log_error( "ERROR: Unable to load data into GL texture (%s) format %s " + "type %s internal format %s\n", gluErrorString( err ), + GetGLFormatName( glFormat ), get_explicit_type_name( type ), + GetGLFormatName( internalFormat ) ); + *outError = -1; + } else { + log_info( "WARNING: Unable to load data into GL texture (%s) format %s " + "type %s internal format %s\n", gluErrorString( err ), + GetGLFormatName( glFormat ), get_explicit_type_name( type ), + GetGLFormatName( internalFormat ) ); + *outError = -2; + } + delete [] buffer; + return NULL; + } + + if( !allocateMem ) + { + delete [] buffer; + return NULL; + } + + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * height * length; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } + else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * length; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc1; + p[ i * 4 + 1 ] = uc2; + p[ i * 4 + 2 ] = uc3; + p[ i * 4 + 3 ] = uc0; + } + } + + return buffer; +} + +void * CreateGLTextureBuffer(size_t width, GLenum target, + GLenum glFormat, GLenum internalFormat, GLenum glType, ExplicitType type, + GLuint *outTex, GLuint *outBuf, int *outError, bool allocateMem, MTdata d) +{ + // First, generate a regular GL Buffer from random data. + *outError = 0; + GLenum err = 0; + + char * buffer; + unsigned int size = 0; + + // The buffer should be the array width * number of elements * element pitch + if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) ) + { + size = width; + } + else + { + size = width * 4; + } + + buffer = (char*)CreateRandomData(type, size, d); + + err = glGetError(); + + glGenBuffers(1, outBuf); + glBindBuffer(GL_TEXTURE_BUFFER, *outBuf); + + // Need to multiply by the type size: + size *= ( GetGLTypeSize( GetGLTypeForExplicitType(type) ) ); + + glBufferData(GL_TEXTURE_BUFFER, size, buffer, GL_DYNAMIC_DRAW); + + // Now make a Texture out of this Buffer: + + glGenTextures(1, outTex); + glBindTexture(GL_TEXTURE_BUFFER, *outTex); + glTexBuffer(GL_TEXTURE_BUFFER, internalFormat, *outBuf); + + if ((err = glGetError())) { + log_error( "ERROR: Unable to load data into glTexBuffer : %s : %s : %d : %s : %s : Error %s\n", + GetGLTargetName(target), + GetGLFormatName(internalFormat), + (int)(size), + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + *outError = -1; + delete [] buffer; + return NULL; + } + + if( !allocateMem ) { + free( buffer ); + return NULL; + } + + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width; i++ ) { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } + else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc1; + p[ i * 4 + 1 ] = uc2; + p[ i * 4 + 2 ] = uc3; + p[ i * 4 + 3 ] = uc0; + } + } + + return buffer; +} + +void* CreateGLTexture1D( size_t width, GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, ExplicitType type, + GLuint *outTextureID, int *outError, bool allocateMem, MTdata d ) +{ + *outError = 0; + GLenum err = 0; + + char * buffer; + unsigned int size = 0; + + // The buffer should be the array width * number of elements * element pitch + if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) ) + { + size = width; + } + else + { + size = width * 4; + } + + buffer = (char*)CreateRandomData(type, size, d); + + glGenTextures( 1, outTextureID ); + glBindTexture( get_base_gl_target( target ), *outTextureID ); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Failed to create GL texture object: %s!\n", gluErrorString( err )); + *outError = -1; + free( buffer ); + return NULL; + } + + glTexImage1D( get_base_gl_target(target), 0, internalFormat, (GLsizei)width, + 0, glFormat, glType, buffer ); + + err = glGetError(); + if( err != GL_NO_ERROR ) + { + if (err != GL_OUT_OF_MEMORY) { + log_error( "ERROR: Unable to load data into glTexImage1D : %s : %s : %d : %s : %s : Error %s\n", + GetGLTargetName(target), + GetGLFormatName(internalFormat), + (int)(width), + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + *outError = -1; + } else { + log_info( "WARNING: Unable to load data into glTexImage1D : %s : %s : %d : %s : %s : Error %s\n", + GetGLTargetName(target), + GetGLFormatName(internalFormat), + (int)(width), + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + *outError = -2; + } + free( buffer ); + return NULL; + } + + if( !allocateMem ) { + free( buffer ); + return NULL; + } + + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width; i++ ) { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } + else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc1; + p[ i * 4 + 1 ] = uc2; + p[ i * 4 + 2 ] = uc3; + p[ i * 4 + 3 ] = uc0; + } + } + + return buffer; +} + +void * CreateGLTexture2D( size_t width, size_t height, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, bool allocateMem, MTdata d ) +{ + *outError = 0; + GLenum err = 0; + + char * buffer; + unsigned int size = 0; + + if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) ) + { + size = width * height; + } + else + { + size = width * height * 4; + } + + buffer = (char *)CreateRandomData(type, size, d); + + glGenTextures( 1, outTextureID ); + glBindTexture( get_base_gl_target( target ), *outTextureID ); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Failed to create GL texture object: %s!\n", gluErrorString( err )); + *outError = -1; + free( buffer ); + return NULL; + } + + if( get_base_gl_target( target ) == GL_TEXTURE_CUBE_MAP ) + { + char * temp = (char *)malloc(size * get_explicit_type_size( type ) * sizeof(cl_char)); + if(allocateMem) + memcpy( temp, buffer, size * get_explicit_type_size( type ) ); + else + memset( temp, 0, size * get_explicit_type_size( type ) ); + + glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + free(temp); + } + else + { +#ifdef DEBUG + log_info("- glTexImage2D : %s : %s : %d : %d : %s : %s\n", + GetGLTargetName(target), + GetGLFormatName(internalFormat), + width, height, + GetGLFormatName(glFormat), + GetGLTypeName(glType)); + + DumpGLBuffer(glType, width, height, buffer); +#endif + + //the default alignment in OpenGL is 4 bytes and need to be changed for GL_DEPTH_COMPONENT16 which is aligned to 2 bytes + if (internalFormat == GL_DEPTH_COMPONENT16) + glPixelStorei(GL_UNPACK_ALIGNMENT, get_explicit_type_size( type )); + + glTexImage2D( get_base_gl_target(target), 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, buffer ); + + if (internalFormat == GL_DEPTH_COMPONENT16) + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + } + + err = glGetError(); + if( err != GL_NO_ERROR ) + { + if (err != GL_OUT_OF_MEMORY) { + log_error( "ERROR: Unable to load data into glTexImage2D : %s : %s : %d : %d : %s : %s : Error %s\n", + GetGLTargetName(target), + GetGLFormatName(internalFormat), + (int)(width), (int)(height), + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + *outError = -1; + } else { + log_info( "WARNING: Unable to load data into glTexImage2D : %s : %s : %d : %d : %s : %s : Error %s\n", + GetGLTargetName(target), + GetGLFormatName(internalFormat), + (int)(width), (int)(height), + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + *outError = -2; + } + free( buffer ); + return NULL; + } + +#ifdef DEBUG + char * test = (char *)malloc(width * height * 4 * get_explicit_type_size( type )); + memset(test, 0, width * height * 4 * get_explicit_type_size( type )); + + if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) ) + { + glFormat = GL_RGBA; + glType = GL_FLOAT; + } + + log_info("- glGetTexImage : %s : %s : %s\n", + GetGLTargetName(target), + GetGLFormatName(glFormat), + GetGLTypeName(glType)); + + glGetTexImage(target, 0, glFormat, glType, test); + + DumpGLBuffer(glType, width, height, test); + + free(test); + + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Unable to read data from glGetTexImage : %s : %s : %s : Error %s\n", + GetGLTargetName(target), + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + return NULL; + } +#endif + + if( !allocateMem ) + { + free( buffer ); + return NULL; + } + + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * height; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } + else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * height; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc1; + p[ i * 4 + 1 ] = uc2; + p[ i * 4 + 2 ] = uc3; + p[ i * 4 + 3 ] = uc0; + } + } + + return buffer; +} + +void * CreateGLTexture3D( size_t width, size_t height, size_t depth, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, MTdata d, bool allocateMem) +{ + *outError = 0; + + char * buffer; + unsigned int size = 0; + + if ( (glType == GL_UNSIGNED_INT_2_10_10_10_REV) || (glType == GL_UNSIGNED_INT_10_10_10_2) ) + { + size = width * height * depth; + } + else + { + size = width * height * depth * 4; + } + + buffer = (char *)create_random_data( type, d, size ); + + if( type == kFloat && allocateMem ) + { + // Re-fill the created buffer to just have [0-1] floats, since that's what it'd expect + cl_float *p = (cl_float *)buffer; + for( size_t i = 0; i < size; i++ ) + { + p[ i ] = (float) genrand_real1( d ); + } + } + else if( !allocateMem ) + memset( buffer, 0, size * get_explicit_type_size( type ) ); + + glGenTextures( 1, outTextureID ); + + glBindTexture( target, *outTextureID ); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + glGetError(); + glTexImage3D( target, 0, internalFormat, (GLsizei)width, (GLsizei)height, (GLsizei)depth, 0, glFormat, glType, buffer ); + GLenum err = glGetError(); + if( err != GL_NO_ERROR ) + { + if (err != GL_OUT_OF_MEMORY) { + log_error( "ERROR: Unable to load data into GL texture (%s) format %s type %s internal format %s\n", gluErrorString( err ), GetGLFormatName( glFormat ), get_explicit_type_name( type ), GetGLFormatName( internalFormat ) ); + *outError = -1; + } else { + log_info( "WARNING: Unable to load data into GL texture (%s) format %s type %s internal format %s\n", gluErrorString( err ), GetGLFormatName( glFormat ), get_explicit_type_name( type ), GetGLFormatName( internalFormat ) ); + *outError = -2; + } + delete [] buffer; + return NULL; + } + + if( !allocateMem ) + { + delete [] buffer; + return NULL; + } + + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * height * depth; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } + else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * height * depth; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc1; + p[ i * 4 + 1 ] = uc2; + p[ i * 4 + 2 ] = uc3; + p[ i * 4 + 3 ] = uc0; + } + } + + return buffer; +} + +void * ReadGLTexture( GLenum glTarget, GLuint glTexture, GLuint glBuf, GLint width, + GLenum glFormat, GLenum glInternalFormat, + GLenum glType, ExplicitType typeToReadAs, + size_t outWidth, size_t outHeight ) +{ + // Read results from the GL texture + glBindTexture(get_base_gl_target(glTarget), glTexture); + + GLint realWidth, realHeight, realDepth; + glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_WIDTH, &realWidth ); + glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_HEIGHT, &realHeight ); + glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_DEPTH, &realDepth ); + + realDepth = (realDepth) ? realDepth : 1; + + GLint realInternalFormat; + glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &realInternalFormat ); + +#ifdef DEBUG + log_info( "- Reading back from GL: %d x %d : %s : %s : %s : %s (stored as %s)\n", + realWidth, realHeight, + GetGLTargetName( glTarget), + GetGLFormatName( glInternalFormat ), + GetGLFormatName( glFormat ), + GetGLTypeName( glType ), + GetGLFormatName( realInternalFormat )); +#endif + + GLenum readBackFormat; + switch(glFormat) + { + case GL_RGBA_INTEGER_EXT: + readBackFormat = GL_RGBA_INTEGER_EXT; + break; + case GL_DEPTH_COMPONENT: + readBackFormat = GL_DEPTH_COMPONENT; + break; + case GL_DEPTH_STENCIL: + readBackFormat = GL_DEPTH_STENCIL; + break; + default: + readBackFormat = GL_RGBA; + break; + } + + GLenum readBackType; + switch (glType) { +#ifdef __APPLE__ + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + readBackType = GL_UNSIGNED_BYTE; + break; +#endif + case GL_HALF_FLOAT: + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT: + case GL_UNSIGNED_INT: + case GL_BYTE: + case GL_SHORT: + case GL_INT: + case GL_FLOAT: + default: + readBackType = glType; + } + + size_t outBytes; + if (get_base_gl_target(glTarget) != GL_TEXTURE_BUFFER) { + outBytes = realWidth * realHeight * realDepth * 4 + * GetGLTypeSize(readBackType); + } + else { + outBytes = width * 4; + + outBytes *= ( GetGLTypeSize( GetGLTypeForExplicitType(typeToReadAs) ) ); + } + + cl_char *outBuffer = (cl_char *)malloc( outBytes ); + memset(outBuffer, 0, outBytes); + + if (get_base_gl_target(glTarget) != GL_TEXTURE_BUFFER) { + //the default alignment in OpenGL is 4 bytes and need to be changed for GL_DEPTH_COMPONENT16 which is aligned to 2 bytes + if (realInternalFormat == GL_DEPTH_COMPONENT16) + glPixelStorei(GL_PACK_ALIGNMENT, 2); + + glGetTexImage( glTarget, 0, readBackFormat, readBackType, outBuffer ); + + if (realInternalFormat == GL_DEPTH_COMPONENT16) + glPixelStorei(GL_PACK_ALIGNMENT, 4); + } + else { + glBindBuffer(GL_ARRAY_BUFFER, glBuf); + glGetBufferSubData(GL_ARRAY_BUFFER, 0, outBytes, outBuffer); + } + +#ifdef DEBUG + + log_info( "- glGetTexImage: %s : %s : %s \n", + GetGLTargetName( glTarget), + GetGLFormatName(readBackFormat), + GetGLTypeName(readBackType)); + + DumpGLBuffer(readBackType, realWidth, realHeight, (void*)outBuffer); + +#endif + + return (void *)outBuffer; +} + +int CreateGLRenderbufferRaw( GLsizei width, GLsizei height, + GLenum attachment, GLenum glFormat, + GLenum internalFormat, GLenum glType, + GLuint *outFramebuffer, + GLuint *outRenderbuffer ) +{ + GLenum err = 0; + + // Generate a renderbuffer and bind + glGenRenderbuffersEXT( 1, outRenderbuffer ); + glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, *outRenderbuffer ); + + // Allocate storage to the renderbuffer + glGetError(); + glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, internalFormat, (GLsizei)width, (GLsizei)height ); + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error("Failed to allocate render buffer storage!\n"); + return 1701; + } + + GLint realInternalFormat; + glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &realInternalFormat ); + internalFormat = realInternalFormat; + +#ifdef DEBUG + GLint rsize, gsize, bsize, asize; + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_RED_SIZE_EXT,&rsize); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_GREEN_SIZE_EXT,&gsize); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_BLUE_SIZE_EXT,&bsize); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_ALPHA_SIZE_EXT,&asize); + + log_info("Renderbuffer internal format requested: %s actual: %s sizes: r=%d g=%d b=%d a=%d\n", + GetGLFormatName( internalFormat ), GetGLFormatName( realInternalFormat ), + rsize, gsize, bsize, asize ); +#endif + + // Create and bind a framebuffer to render with + glGenFramebuffersEXT( 1, outFramebuffer ); + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, *outFramebuffer ); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Unable to bind framebuffer : Error %s\n", + gluErrorString( err )); + + return -1; + } + + // Attach to the framebuffer + glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, *outRenderbuffer ); + err = glGetError(); + GLint status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ); + if( status != GL_FRAMEBUFFER_COMPLETE_EXT ) + { + log_error( "ERROR: Unable to attach renderbuffer to framebuffer (%s, status %x)\n", gluErrorString( err ), (int)status ); + return -1; + } + + return 0; +} + + +void reorder_verification_buffer(GLenum glFormat, GLenum glType, char* buffer, size_t num_pixels) +{ + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < num_pixels; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } + else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < num_pixels; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc1; + p[ i * 4 + 1 ] = uc2; + p[ i * 4 + 2 ] = uc3; + p[ i * 4 + 3 ] = uc0; + } + } +} + + +#ifdef GL_VERSION_3_2 + +#define check_gl_error() \ +{ \ + GLenum errnom = GL_NO_ERROR;\ + if ((errnom = glGetError()) != GL_NO_ERROR)\ + log_error("GL Error: 0x%04X at %s:%d\n", errnom, __FILE__, __LINE__);\ +} + +const char *get_gl_vector_type( GLenum internalformat ) +{ + switch (internalformat) { + case GL_RGBA8: + case GL_RGBA16: + case GL_RGBA32F_ARB: + case GL_RGBA16F_ARB: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT32F: + case GL_DEPTH24_STENCIL8: + case GL_DEPTH32F_STENCIL8: + return "vec4"; + break; + case GL_RGBA8I_EXT: + case GL_RGBA16I_EXT: + case GL_RGBA32I_EXT: + return "ivec4"; + break; + case GL_RGBA8UI_EXT: + case GL_RGBA16UI_EXT: + case GL_RGBA32UI_EXT: + return "uvec4"; + break; + default: + log_error("Test error: unsupported data type\n"); + return ""; + break; + } +} + +const char *get_gl_data_type( GLenum internalformat ) +{ + switch (internalformat) { + case GL_RGBA8: + case GL_RGBA16: + case GL_RGBA32F_ARB: + case GL_RGBA16F_ARB: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT32F: + case GL_DEPTH24_STENCIL8: + case GL_DEPTH32F_STENCIL8: + return "float"; + break; + case GL_RGBA8I_EXT: + case GL_RGBA16I_EXT: + case GL_RGBA32I_EXT: + return "int"; + break; + case GL_RGBA8UI_EXT: + case GL_RGBA16UI_EXT: + case GL_RGBA32UI_EXT: + return "uint"; + break; + default: + log_error("Test error: unsupported data type\n"); + return ""; + break; + } +} + + +void * CreateGLTexture2DMultisample( size_t width, size_t height, size_t samples, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, bool allocateMem, MTdata d , bool fixedSampleLocations) +{ + // This function creates a multisample texture and renders into each sample + // using a GLSL shader + + // Check if the renderer supports enough samples + GLint max_samples = get_gl_max_samples(target, internalFormat); + check_gl_error() + + if (max_samples < (GLint)samples) + log_error("GL error: requested samples (%d) exceeds renderer max samples (%d)\n", samples, max_samples); + + // Setup the GLSL program + const GLchar *vertex_source = + "#version 140\n" + "in vec4 att0;\n" + "void main (void) {\n" + " gl_Position = vec4(att0.xy,0.0,1.0);\n" + "}\n"; + + const GLchar *fragmentSource = + "#version 140\n" + "out %s out0;\n" + "uniform %s colorVal;\n" + "uniform float depthVal;\n" + "void main (void) {\n" + " out0 = %s(colorVal);\n" + " gl_FragDepth = depthVal;\n" + "}\n"; + + GLchar fragmentShader[256]; + sprintf(fragmentShader, fragmentSource, get_gl_vector_type(internalFormat), get_gl_data_type(internalFormat), get_gl_vector_type(internalFormat)); + const GLchar *fragment_source = &fragmentShader[0]; + + glShaderWrapper vertex_shader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertex_shader, 1, &vertex_source, NULL); + glCompileShader(vertex_shader); + check_gl_error() + + glShaderWrapper fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragment_shader, 1, &fragment_source, NULL); + glCompileShader(fragment_shader); + check_gl_error() + + GLuint prog = glCreateProgram(); + glAttachShader(prog, vertex_shader); + glAttachShader(prog, fragment_shader); + check_gl_error() + + glBindAttribLocation(prog, 0, "att0"); + glLinkProgram(prog); + check_gl_error() + + // Setup the FBO and texture + glFramebufferWrapper fbo; + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + check_gl_error() + + glViewport(0, 0, width, height); + check_gl_error() + + GLuint tex = 0; + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex); + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalFormat, width, height, fixedSampleLocations); + check_gl_error() + + GLint attachment; + switch (internalFormat) { + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT32F: + attachment = GL_DEPTH_ATTACHMENT; + break; + case GL_DEPTH24_STENCIL8: + case GL_DEPTH32F_STENCIL8: + attachment = GL_DEPTH_STENCIL_ATTACHMENT; + break; + default: + attachment = GL_COLOR_ATTACHMENT0; + break; + } + + glFramebufferTexture(GL_FRAMEBUFFER, attachment, tex, 0); + check_gl_error() + + GLint status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status == GL_FRAMEBUFFER_UNSUPPORTED) { + log_info("GL status: GL_FRAMEBUFFER_UNSUPPORTED format %s multisample is not supported\n", GetGLFormatName(internalFormat)); + *outTextureID = 0; + *outError = GL_FRAMEBUFFER_UNSUPPORTED; + return NULL; + } + + if (status != GL_FRAMEBUFFER_COMPLETE) { + log_error("GL error: framebuffer incomplete status 0x%04X\n",status); + *outTextureID = 0; + *outError = status; + return NULL; + } + + // Check if the framebuffer supports enough samples + GLint fbo_samples = 0; + glGetIntegerv(GL_SAMPLES, &fbo_samples); + check_gl_error(); + + if (fbo_samples < (GLint)samples) + log_error("GL Error: requested samples (%d) exceeds FBO capability (%d)\n", samples, fbo_samples); + + glUseProgram(prog); + check_gl_error() + + if (attachment != GL_DEPTH_ATTACHMENT && attachment != GL_DEPTH_STENCIL_ATTACHMENT) { + glDisable(GL_DEPTH_TEST); + check_gl_error() + } + else { + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + check_gl_error() + } + + // Setup the VBO for rendering a quad + GLfloat quad[] = { + -1.0f, -1.0f, + 1.0f, -1.0f, + 1.0f, 1.0f, + -1.0f, 1.0f + }; + + glBufferWrapper vbo; + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STREAM_DRAW); + check_gl_error() + + glVertexArraysWrapper vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*2, 0); + check_gl_error() + + //clearing color and depth buffer + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + glClearDepth(1.0); + glClear(GL_DEPTH_BUFFER_BIT); + + //calculating colors + double color_delta = 1.0 / samples; + double color = color_delta; + + glEnable(GL_SAMPLE_MASK); + for (size_t i=0;i!=samples;++i) { + glSampleMaski(0, 1< + +GLboolean gluCheckExtension(const GLubyte *extName, const GLubyte *extString) +{ + const size_t len = strlen((const char*)extName); + const char* str = (const char*)extString; + + while (str != NULL) { + str = strstr(str, (const char*)extName); + if (str == NULL) { + break; + } + if ((str > (const char*)extString || str[-1] == ' ') + && (str[len] == ' ' || str[len] == '\0')) { + return GL_TRUE; + } + str = strchr(str + len, ' '); + } + + return GL_FALSE; +} + +#endif + +// Function pointers for the GL/CL calls +clCreateFromGLBuffer_fn clCreateFromGLBuffer_ptr; +clCreateFromGLTexture_fn clCreateFromGLTexture_ptr; +clCreateFromGLTexture2D_fn clCreateFromGLTexture2D_ptr; +clCreateFromGLTexture3D_fn clCreateFromGLTexture3D_ptr; +clCreateFromGLRenderbuffer_fn clCreateFromGLRenderbuffer_ptr; +clGetGLObjectInfo_fn clGetGLObjectInfo_ptr; +clGetGLTextureInfo_fn clGetGLTextureInfo_ptr; +clEnqueueAcquireGLObjects_fn clEnqueueAcquireGLObjects_ptr; +clEnqueueReleaseGLObjects_fn clEnqueueReleaseGLObjects_ptr; + +int init_clgl_ext() { + + // As OpenCL for the platforms. Warn if more than one platform found, + // since this might not be the platform we want. By default, we simply + // use the first returned platform. + + cl_uint nplatforms; + cl_platform_id platform; + clGetPlatformIDs(0, NULL, &nplatforms); + clGetPlatformIDs(1, &platform, NULL); + + if (nplatforms > 1) { + log_info("clGetPlatformIDs returned multiple values. This is not " + "an error, but might result in obtaining incorrect function " + "pointers if you do not want the first returned platform.\n"); + + // Show them the platform name, in case it is a problem. + + size_t size; + char *name; + + clGetPlatformInfo(platform, CL_PLATFORM_NAME, 0, NULL, &size); + name = (char*)malloc(size); + clGetPlatformInfo(platform, CL_PLATFORM_NAME, size, name, NULL); + + log_info("Using platform with name: %s \n", name); + free(name); + } + + // Create the function pointer table + clCreateFromGLBuffer_ptr = (clCreateFromGLBuffer_fn)clGetExtensionFunctionAddressForPlatform(platform,"clCreateFromGLBuffer"); + if (clCreateFromGLBuffer_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clCreateFromGLBuffer) returned NULL.\n"); + return -1; + } + clCreateFromGLTexture2D_ptr = (clCreateFromGLTexture2D_fn)clGetExtensionFunctionAddressForPlatform(platform,"clCreateFromGLTexture2D"); + if (clCreateFromGLTexture2D_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clCreateFromGLTexture2D) returned NULL.\n"); + return -1; + } + clCreateFromGLTexture3D_ptr = (clCreateFromGLTexture3D_fn)clGetExtensionFunctionAddressForPlatform(platform,"clCreateFromGLTexture3D"); + if (clCreateFromGLTexture3D_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clCreateFromGLTexture3D\") returned NULL.\n"); + return -1; + } + clCreateFromGLTexture_ptr = (clCreateFromGLTexture_fn)clGetExtensionFunctionAddressForPlatform(platform,"clCreateFromGLTexture"); + if (clCreateFromGLTexture_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,\"clCreateFromGLTexture\") returned NULL.\n"); + return -1; + } + clCreateFromGLRenderbuffer_ptr = (clCreateFromGLRenderbuffer_fn)clGetExtensionFunctionAddressForPlatform(platform,"clCreateFromGLRenderbuffer"); + if (clCreateFromGLRenderbuffer_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clCreateFromGLRenderbuffer) returned NULL.\n"); + return -1; + } + clGetGLObjectInfo_ptr = (clGetGLObjectInfo_fn)clGetExtensionFunctionAddressForPlatform(platform,"clGetGLObjectInfo"); + if (clGetGLObjectInfo_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clGetGLObjectInfo) returned NULL.\n"); + return -1; + } + clGetGLTextureInfo_ptr = (clGetGLTextureInfo_fn)clGetExtensionFunctionAddressForPlatform(platform,"clGetGLTextureInfo"); + if (clGetGLTextureInfo_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clGetGLTextureInfo) returned NULL.\n"); + return -1; + } + clEnqueueAcquireGLObjects_ptr = (clEnqueueAcquireGLObjects_fn)clGetExtensionFunctionAddressForPlatform(platform,"clEnqueueAcquireGLObjects"); + if (clEnqueueAcquireGLObjects_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clEnqueueAcquireGLObjects) returned NULL.\n"); + return -1; + } + clEnqueueReleaseGLObjects_ptr = (clEnqueueReleaseGLObjects_fn)clGetExtensionFunctionAddressForPlatform(platform,"clEnqueueReleaseGLObjects"); + if (clEnqueueReleaseGLObjects_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clEnqueueReleaseGLObjects) returned NULL.\n"); + return -1; + } + + return 0; +} + +GLint get_gl_max_samples( GLenum target, GLenum internalformat ) +{ + GLint max_samples = 0; +#ifdef GL_VERSION_4_2 + glGetInternalformativ(target, internalformat, GL_SAMPLES, 1, &max_samples); +#else + switch (internalformat) + { + case GL_RGBA8I: + case GL_RGBA16I: + case GL_RGBA32I: + case GL_RGBA8UI: + case GL_RGBA16UI: + case GL_RGBA32UI: + glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &max_samples); + break; + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT32F: + case GL_DEPTH24_STENCIL8: + case GL_DEPTH32F_STENCIL8: + glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &max_samples); + break; + default: + glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &max_samples); + break; + } +#endif + return max_samples; +} diff --git a/test_common/gl/helpers.h b/test_common/gl/helpers.h new file mode 100644 index 00000000..ace1d16a --- /dev/null +++ b/test_common/gl/helpers.h @@ -0,0 +1,362 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _helpers_h +#define _helpers_h + +#include "../harness/compat.h" +#include +#include +#include + +#include +#include + +#if !defined (__APPLE__) +#include +#include "gl_headers.h" +#include +#else +#include "gl_headers.h" +#endif + +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/threadTesting.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/mt19937.h" + +typedef cl_mem +(CL_API_CALL *clCreateFromGLBuffer_fn)(cl_context context, + cl_mem_flags flags, + GLuint bufobj, + int * errcode_ret); + +typedef cl_mem +(CL_API_CALL *clCreateFromGLTexture_fn)(cl_context context , + cl_mem_flags flags , + GLenum target , + GLint miplevel , + GLuint texture , + cl_int * errcode_ret) ; + +typedef cl_mem +(CL_API_CALL *clCreateFromGLTexture2D_fn)(cl_context context , + cl_mem_flags flags , + GLenum target , + GLint miplevel , + GLuint texture , + cl_int * errcode_ret) ; + +typedef cl_mem +(CL_API_CALL *clCreateFromGLTexture3D_fn)(cl_context context , + cl_mem_flags flags , + GLenum target , + GLint miplevel , + GLuint texture , + cl_int * errcode_ret) ; + +typedef cl_mem +(CL_API_CALL *clCreateFromGLRenderbuffer_fn)(cl_context context , + cl_mem_flags flags , + GLuint renderbuffer , + cl_int * errcode_ret) ; + +typedef cl_int +(CL_API_CALL *clGetGLObjectInfo_fn)(cl_mem memobj , + cl_gl_object_type * gl_object_type , + GLuint * gl_object_name) ; + +typedef cl_int +(CL_API_CALL *clGetGLTextureInfo_fn)(cl_mem memobj , + cl_gl_texture_info param_name , + size_t param_value_size , + void * param_value , + size_t * param_value_size_ret) ; + +typedef cl_int +(CL_API_CALL *clEnqueueAcquireGLObjects_fn)(cl_command_queue command_queue , + cl_uint num_objects , + const cl_mem * mem_objects , + cl_uint num_events_in_wait_list , + const cl_event * event_wait_list , + cl_event * event) ; + +typedef cl_int +(CL_API_CALL *clEnqueueReleaseGLObjects_fn)(cl_command_queue command_queue , + cl_uint num_objects , + const cl_mem * mem_objects , + cl_uint num_events_in_wait_list , + const cl_event * event_wait_list , + cl_event * event) ; + + +extern clCreateFromGLBuffer_fn clCreateFromGLBuffer_ptr; +extern clCreateFromGLTexture_fn clCreateFromGLTexture_ptr; +extern clCreateFromGLTexture2D_fn clCreateFromGLTexture2D_ptr; +extern clCreateFromGLTexture3D_fn clCreateFromGLTexture3D_ptr; +extern clCreateFromGLRenderbuffer_fn clCreateFromGLRenderbuffer_ptr; +extern clGetGLObjectInfo_fn clGetGLObjectInfo_ptr; +extern clGetGLTextureInfo_fn clGetGLTextureInfo_ptr; +extern clEnqueueAcquireGLObjects_fn clEnqueueAcquireGLObjects_ptr; +extern clEnqueueReleaseGLObjects_fn clEnqueueReleaseGLObjects_ptr; + + +class glBufferWrapper +{ + public: + glBufferWrapper() { mBuffer = 0; } + glBufferWrapper( GLuint b ) { mBuffer = b; } + ~glBufferWrapper() { if( mBuffer != 0 ) glDeleteBuffers( 1, &mBuffer ); } + + glBufferWrapper & operator=( const GLuint &rhs ) { mBuffer = rhs; return *this; } + operator GLuint() { return mBuffer; } + operator GLuint *() { return &mBuffer; } + + GLuint * operator&() { return &mBuffer; } + + bool operator==( GLuint rhs ) { return mBuffer == rhs; } + + protected: + + GLuint mBuffer; +}; + +class glTextureWrapper +{ + public: + glTextureWrapper() { mHandle = 0; } + glTextureWrapper( GLuint b ) { mHandle = b; } + ~glTextureWrapper() { + if( mHandle != 0 ) glDeleteTextures( 1, &mHandle ); + } + + glTextureWrapper & operator=( const GLuint &rhs ) { mHandle = rhs; return *this; } + operator GLuint() { return mHandle; } + operator GLuint *() { return &mHandle; } + + GLuint * operator&() { return &mHandle; } + + bool operator==( GLuint rhs ) { return mHandle == rhs; } + + protected: + + // The texture handle. + GLuint mHandle; +}; + +class glRenderbufferWrapper +{ + public: + glRenderbufferWrapper() { mBuffer = 0; } + glRenderbufferWrapper( GLuint b ) { mBuffer = b; } + ~glRenderbufferWrapper() { if( mBuffer != 0 ) glDeleteRenderbuffersEXT( 1, &mBuffer ); } + + glRenderbufferWrapper & operator=( const GLuint &rhs ) { mBuffer = rhs; return *this; } + operator GLuint() { return mBuffer; } + operator GLuint *() { return &mBuffer; } + + GLuint * operator&() { return &mBuffer; } + + bool operator==( GLuint rhs ) { return mBuffer == rhs; } + + protected: + + GLuint mBuffer; +}; + +class glFramebufferWrapper +{ + public: + glFramebufferWrapper() { mBuffer = 0; } + glFramebufferWrapper( GLuint b ) { mBuffer = b; } + ~glFramebufferWrapper() { if( mBuffer != 0 ) glDeleteFramebuffersEXT( 1, &mBuffer ); } + + glFramebufferWrapper & operator=( const GLuint &rhs ) { mBuffer = rhs; return *this; } + operator GLuint() { return mBuffer; } + operator GLuint *() { return &mBuffer; } + + GLuint * operator&() { return &mBuffer; } + + bool operator==( GLuint rhs ) { return mBuffer == rhs; } + + protected: + + GLuint mBuffer; +}; + +class glVertexArraysWrapper +{ +public: + glVertexArraysWrapper() { mBuffer = 0; } + glVertexArraysWrapper( GLuint b ) { mBuffer = b; } + ~glVertexArraysWrapper() { if( mBuffer != 0 ) glDeleteVertexArrays( 1, &mBuffer ); } + + glVertexArraysWrapper & operator=( const GLuint &rhs ) { mBuffer = rhs; return *this; } + operator GLuint() { return mBuffer; } + operator GLuint *() { return &mBuffer; } + + GLuint * operator&() { return &mBuffer; } + + bool operator==( GLuint rhs ) { return mBuffer == rhs; } + +protected: + + GLuint mBuffer; +}; + +class glProgramWrapper +{ +public: + glProgramWrapper() { mProgram = 0; } + glProgramWrapper( GLuint b ) { mProgram = b; } + ~glProgramWrapper() { if( mProgram != 0 ) glDeleteProgram( mProgram ); } + + glProgramWrapper & operator=( const GLuint &rhs ) { mProgram = rhs; return *this; } + operator GLuint() { return mProgram; } + operator GLuint *() { return &mProgram; } + + GLuint * operator&() { return &mProgram; } + + bool operator==( GLuint rhs ) { return mProgram == rhs; } + +protected: + + GLuint mProgram; +}; + +class glShaderWrapper +{ +public: + glShaderWrapper() { mShader = 0; } + glShaderWrapper( GLuint b ) { mShader = b; } + ~glShaderWrapper() { if( mShader != 0 ) glDeleteShader( mShader ); } + + glShaderWrapper & operator=( const GLuint &rhs ) { mShader = rhs; return *this; } + operator GLuint() { return mShader; } + operator GLuint *() { return &mShader; } + + GLuint * operator&() { return &mShader; } + + bool operator==( GLuint rhs ) { return mShader == rhs; } + +protected: + + GLuint mShader; +}; + +// Helper functions (defined in helpers.cpp) + +extern void * CreateGLTexture1DArray( size_t width, size_t length, + GLenum target, GLenum glFormat, GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, int *outError, + bool allocateMem, MTdata d); + +extern void * CreateGLTexture2DArray( size_t width, size_t height, size_t length, + GLenum target, GLenum glFormat, GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, int *outError, + bool allocateMem, MTdata d); + +extern void * CreateGLTextureBuffer( size_t width, + GLenum target, GLenum glFormat, GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTex, GLuint *outBuf, int *outError, + bool allocateMem, MTdata d); + +extern void * CreateGLTexture1D(size_t width, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, bool allocateMem, MTdata d ); + +extern void * CreateGLTexture2D( size_t width, size_t height, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, bool allocateMem, MTdata d ); + + +extern void * CreateGLTexture3D( size_t width, size_t height, size_t depth, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, MTdata d, bool allocateMem = true ); + +#ifdef GL_VERSION_3_2 +extern void * CreateGLTexture2DMultisample( size_t width, size_t height, size_t samples, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, bool allocateMem, MTdata d, + bool fixedSampleLocations ); + +extern void * CreateGLTexture2DArrayMultisample( size_t width, size_t height, + size_t length, size_t samples, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, bool allocateMem, MTdata d, + bool fixedSampleLocations ); +#endif + +extern void * ReadGLTexture( GLenum glTarget, GLuint glTexture, GLuint glBuf, GLint width, + GLenum glFormat, GLenum glInternalFormat, + GLenum glType, ExplicitType typeToReadAs, + size_t outWidth, size_t outHeight ); + +extern int CreateGLRenderbufferRaw( GLsizei width, GLsizei height, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + GLuint *outFramebuffer, + GLuint *outRenderbuffer ); + +extern void * CreateGLRenderbuffer( GLsizei width, GLsizei height, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, + GLuint *outFramebuffer, + GLuint *outRenderbuffer, + int *outError, MTdata d, bool allocateMem ); + +extern void * ReadGLRenderbuffer( GLuint glFramebuffer, GLuint glRenderbuffer, + GLenum attachment, GLenum glFormat, + GLenum glInternalFormat, GLenum glType, + ExplicitType typeToReadAs, + size_t outWidth, size_t outHeight ); + +extern void DumpGLBuffer(GLenum type, size_t width, size_t height, void* buffer); +extern const char *GetGLTypeName( GLenum type ); +extern const char *GetGLAttachmentName( GLenum att ); +extern const char *GetGLTargetName( GLenum tgt ); +extern const char *GetGLBaseFormatName( GLenum baseformat ); +extern const char *GetGLFormatName( GLenum format ); + +extern void* CreateRandomData( ExplicitType type, size_t count, MTdata d ); + +extern GLenum GetGLFormat(GLenum internalFormat); +extern GLenum GetGLTypeForExplicitType(ExplicitType type); +extern size_t GetGLTypeSize(GLenum type); +extern ExplicitType GetExplicitTypeForGLType(GLenum type); + +extern GLenum get_base_gl_target( GLenum target ); + +extern int init_clgl_ext( void ); + +extern GLint get_gl_max_samples( GLenum target, GLenum internalformat ); + +#endif // _helpers_h + + + diff --git a/test_common/gl/setup.h b/test_common/gl/setup.h new file mode 100644 index 00000000..6ee810bb --- /dev/null +++ b/test_common/gl/setup.h @@ -0,0 +1,48 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _setup_h +#define _setup_h + +#include +#include +#include +#include "gl_headers.h" +#ifdef __APPLE__ +#include +#else +#include +#endif + + +// Note: the idea here is to have every platform define their own setup.cpp file that implements a GLEnvironment +// subclass internally, then return it as a definition for GLEnvironment::Create + +class GLEnvironment +{ + public: + GLEnvironment() {} + virtual ~GLEnvironment() {} + + virtual int Init( int *argc, char **argv, int use_opengl_32 ) = 0; + virtual cl_context CreateCLContext( void ) = 0; + virtual int SupportsCLGLInterop( cl_device_type device_type) = 0; + + static GLEnvironment * Instance( void ); + + +}; + +#endif // _setup_h diff --git a/test_common/gl/setup_osx.cpp b/test_common/gl/setup_osx.cpp new file mode 100644 index 00000000..01641be0 --- /dev/null +++ b/test_common/gl/setup_osx.cpp @@ -0,0 +1,156 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "setup.h" +#include "../../test_common/harness/errorHelpers.h" +#include + +class OSXGLEnvironment : public GLEnvironment +{ + public: + OSXGLEnvironment() + { + mCGLContext = NULL; + } + + virtual int Init( int *argc, char **argv, int use_opengl_32 ) + { + if (!use_opengl_32) { + + // Create a GLUT window to render into + glutInit( argc, argv ); + glutInitWindowSize( 512, 512 ); + glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); + glutCreateWindow( "OpenCL <-> OpenGL Test" ); + } + + else { + + CGLPixelFormatAttribute attribs[] = { + kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core, + kCGLPFAAllowOfflineRenderers, + kCGLPFANoRecovery, + kCGLPFAAccelerated, + kCGLPFADoubleBuffer, + (CGLPixelFormatAttribute)0 + }; + + CGLError err; + CGLPixelFormatObj pix; + GLint npix; + err = CGLChoosePixelFormat (attribs, &pix, &npix); + if(err != kCGLNoError) + { + log_error("Failed to choose pixel format\n"); + return -1; + } + err = CGLCreateContext(pix, NULL, &mCGLContext); + if(err != kCGLNoError) + { + log_error("Failed to create GL context\n"); + return -1; + } + CGLSetCurrentContext(mCGLContext); + } + + return 0; + } + + virtual cl_context CreateCLContext( void ) + { + int error; + + if( mCGLContext == NULL ) + mCGLContext = CGLGetCurrentContext(); + + CGLShareGroupObj share_group = CGLGetShareGroup(mCGLContext); + cl_context_properties properties[] = { CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)share_group, 0 }; + cl_context context = clCreateContext(properties, 0, 0, 0, 0, &error); + if (error) { + print_error(error, "clCreateContext failed"); + return NULL; + } + + // Verify that all devices in the context support the required extension + cl_device_id devices[64]; + size_t size_out; + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, sizeof(devices), devices, &size_out); + if (error) { + print_error(error, "clGetContextInfo failed"); + return NULL; + } + + char extensions[8192]; + for (int i=0; i<(int)(size_out/sizeof(cl_device_id)); i++) { + error = clGetDeviceInfo(devices[i], CL_DEVICE_EXTENSIONS, sizeof(extensions), extensions, NULL); + if (error) { + print_error(error, "clGetDeviceInfo failed"); + return NULL; + } + + if (strstr(extensions, "cl_APPLE_gl_sharing") == NULL) { + log_error("Device %d does not supporte required extension cl_APPLE_gl_sharing.\n", i); + return NULL; + } + } + return context; + } + + virtual int SupportsCLGLInterop( cl_device_type device_type ) + { + int found_valid_device = 0; + cl_device_id devices[64]; + cl_uint num_of_devices; + int error; + error = clGetDeviceIDs(NULL, device_type, 64, devices, &num_of_devices); + if (error) { + print_error(error, "clGetDeviceIDs failed"); + return -1; + } + + char extensions[8192]; + for (int i=0; i<(int)num_of_devices; i++) { + error = clGetDeviceInfo(devices[i], CL_DEVICE_EXTENSIONS, sizeof(extensions), extensions, NULL); + if (error) { + print_error(error, "clGetDeviceInfo failed"); + return -1; + } + + if (strstr(extensions, "cl_APPLE_gl_sharing") == NULL) { + log_info("Device %d of %d does not support required extension cl_APPLE_gl_sharing.\n", i, num_of_devices); + } else { + log_info("Device %d of %d does support required extension cl_APPLE_gl_sharing.\n", i, num_of_devices); + found_valid_device = 1; + } + } + return found_valid_device; + } + + virtual ~OSXGLEnvironment() + { + CGLDestroyContext( mCGLContext ); + } + + CGLContextObj mCGLContext; + +}; + +GLEnvironment * GLEnvironment::Instance( void ) +{ + static OSXGLEnvironment * env = NULL; + if( env == NULL ) + env = new OSXGLEnvironment(); + return env; +} diff --git a/test_common/gl/setup_win32.cpp b/test_common/gl/setup_win32.cpp new file mode 100644 index 00000000..1c7b4b2f --- /dev/null +++ b/test_common/gl/setup_win32.cpp @@ -0,0 +1,209 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#define GL_GLEXT_PROTOTYPES + +#include "setup.h" +#include "testBase.h" +#include "../../test_common/harness/errorHelpers.h" + +#include +#include +#include +#include +#include + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetGLContextInfoKHR_fn)( + const cl_context_properties *properties, + cl_gl_context_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret); + +// Rename references to this dynamically linked function to avoid +// collision with static link version +#define clGetGLContextInfoKHR clGetGLContextInfoKHR_proc +static clGetGLContextInfoKHR_fn clGetGLContextInfoKHR; + +#define MAX_DEVICES 32 + +class WGLEnvironment : public GLEnvironment +{ +private: + cl_device_id m_devices[MAX_DEVICES]; + int m_device_count; + cl_platform_id m_platform; + bool m_is_glut_init; + +public: + WGLEnvironment() + { + m_device_count = 0; + m_platform = 0; + m_is_glut_init = false; + } + virtual int Init( int *argc, char **argv, int use_opengl_32 ) + { + if (!m_is_glut_init) + { + // Create a GLUT window to render into + glutInit( argc, argv ); + glutInitWindowSize( 512, 512 ); + glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); + glutCreateWindow( "OpenCL <-> OpenGL Test" ); + glewInit(); + m_is_glut_init = true; + } + return 0; + } + + virtual cl_context CreateCLContext( void ) + { + HGLRC hGLRC = wglGetCurrentContext(); + HDC hDC = wglGetCurrentDC(); + cl_context_properties properties[] = { + CL_CONTEXT_PLATFORM, (cl_context_properties) m_platform, + CL_GL_CONTEXT_KHR, (cl_context_properties) hGLRC, + CL_WGL_HDC_KHR, (cl_context_properties) hDC, + 0 + }; + cl_device_id devices[MAX_DEVICES]; + size_t dev_size; + cl_int status; + + if (!hGLRC || !hDC) { + print_error(CL_INVALID_CONTEXT, "No GL context bound"); + return 0; + } + + if (!clGetGLContextInfoKHR) { + // As OpenCL for the platforms. Warn if more than one platform found, + // since this might not be the platform we want. By default, we simply + // use the first returned platform. + + cl_uint nplatforms; + cl_platform_id platform; + clGetPlatformIDs(0, NULL, &nplatforms); + clGetPlatformIDs(1, &platform, NULL); + + if (nplatforms > 1) { + log_info("clGetPlatformIDs returned multiple values. This is not " + "an error, but might result in obtaining incorrect function " + "pointers if you do not want the first returned platform.\n"); + + // Show them the platform name, in case it is a problem. + + size_t size; + char *name; + + clGetPlatformInfo(platform, CL_PLATFORM_NAME, 0, NULL, &size); + name = (char*)malloc(size); + clGetPlatformInfo(platform, CL_PLATFORM_NAME, size, name, NULL); + + log_info("Using platform with name: %s \n", name); + free(name); + } + + clGetGLContextInfoKHR = (clGetGLContextInfoKHR_fn) clGetExtensionFunctionAddressForPlatform(platform, "clGetGLContextInfoKHR"); + if (!clGetGLContextInfoKHR) { + print_error(CL_INVALID_PLATFORM, "Failed to query proc address for clGetGLContextInfoKHR"); + } + } + + status = clGetGLContextInfoKHR(properties, + CL_DEVICES_FOR_GL_CONTEXT_KHR, + sizeof(devices), + devices, + &dev_size); + if (status != CL_SUCCESS) { + print_error(status, "clGetGLContextInfoKHR failed"); + return 0; + } + dev_size /= sizeof(cl_device_id); + log_info("GL context supports %d compute devices\n", dev_size); + + status = clGetGLContextInfoKHR(properties, + CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR, + sizeof(devices), + devices, + &dev_size); + if (status != CL_SUCCESS) { + print_error(status, "clGetGLContextInfoKHR failed"); + return 0; + } + + cl_device_id ctxDevice = m_devices[0]; + if (dev_size > 0) { + log_info("GL context current device: 0x%x\n", devices[0]); + for (int i = 0; i < m_device_count; i++) { + if (m_devices[i] == devices[0]) { + ctxDevice = devices[0]; + break; + } + } + } else { + log_info("GL context current device is not a CL device, using device %d.\n", ctxDevice); + } + + return clCreateContext(properties, 1, &ctxDevice, NULL, NULL, &status); + } + + virtual int SupportsCLGLInterop( cl_device_type device_type ) + { + cl_device_id devices[MAX_DEVICES]; + cl_uint num_of_devices; + int error; + error = clGetPlatformIDs(1, &m_platform, NULL); + if (error) { + print_error(error, "clGetPlatformIDs failed"); + return -1; + } + error = clGetDeviceIDs(m_platform, device_type, MAX_DEVICES, devices, &num_of_devices); + if (error) { + print_error(error, "clGetDeviceIDs failed"); + return -1; + } + + // Check all devices, search for one that supports cl_khr_gl_sharing + char extensions[8192]; + for (int i=0; i<(int)num_of_devices; i++) { + error = clGetDeviceInfo(devices[i], CL_DEVICE_EXTENSIONS, sizeof(extensions), extensions, NULL); + if (error) { + print_error(error, "clGetDeviceInfo failed"); + return -1; + } + + if (strstr(extensions, "cl_khr_gl_sharing") == NULL) { + log_info("Device %d of %d does not support required extension cl_khr_gl_sharing.\n", i+1, num_of_devices); + } else { + log_info("Device %d of %d supports required extension cl_khr_gl_sharing.\n", i+1, num_of_devices); + m_devices[m_device_count++] = devices[i]; + } + } + return m_device_count > 0; + } + + virtual ~WGLEnvironment() + { + } +}; + +GLEnvironment * GLEnvironment::Instance( void ) +{ + static WGLEnvironment * env = NULL; + if( env == NULL ) + env = new WGLEnvironment(); + return env; +} diff --git a/test_common/gl/setup_x11.cpp b/test_common/gl/setup_x11.cpp new file mode 100644 index 00000000..22bc7eed --- /dev/null +++ b/test_common/gl/setup_x11.cpp @@ -0,0 +1,122 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#define GL_GLEXT_PROTOTYPES + +#include "setup.h" +#include "testBase.h" +#include "../../test_common/harness/errorHelpers.h" + +#include +#include +#include +#include +#include +#include + +class X11GLEnvironment : public GLEnvironment +{ +private: + cl_device_id m_devices[64]; + cl_uint m_device_count; + +public: + X11GLEnvironment() + { + m_device_count = 0; + } + virtual int Init( int *argc, char **argv, int use_opencl_32 ) + { + // Create a GLUT window to render into + glutInit( argc, argv ); + glutInitWindowSize( 512, 512 ); + glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); + glutCreateWindow( "OpenCL <-> OpenGL Test" ); + glewInit(); + return 0; + } + + virtual cl_context CreateCLContext( void ) + { + GLXContext context = glXGetCurrentContext(); + Display *dpy = glXGetCurrentDisplay(); + + cl_context_properties properties[] = { + CL_GL_CONTEXT_KHR, (cl_context_properties) context, + CL_GLX_DISPLAY_KHR, (cl_context_properties) dpy, + 0 + }; + cl_int status; + + if (!context || !dpy) { + print_error(CL_INVALID_CONTEXT, "No GL context bound"); + return 0; + } + + return clCreateContext(properties, 1, m_devices, NULL, NULL, &status); + } + + virtual int SupportsCLGLInterop( cl_device_type device_type ) + { + int found_valid_device = 0; + cl_platform_id platform; + cl_device_id devices[64]; + cl_uint num_of_devices; + int error; + error = clGetPlatformIDs(1, &platform, NULL); + if (error) { + print_error(error, "clGetPlatformIDs failed"); + return -1; + } + error = clGetDeviceIDs(platform, device_type, 64, devices, &num_of_devices); + // If this platform doesn't have any of the requested device_type (namely GPUs) then return 0 + if (error == CL_DEVICE_NOT_FOUND) + return 0; + if (error) { + print_error(error, "clGetDeviceIDs failed"); + return -1; + } + + char extensions[8192]; + for (int i=0; i<(int)num_of_devices; i++) { + error = clGetDeviceInfo(devices[i], CL_DEVICE_EXTENSIONS, sizeof(extensions), extensions, NULL); + if (error) { + print_error(error, "clGetDeviceInfo failed"); + return -1; + } + + if (strstr(extensions, "cl_khr_gl_sharing ") == NULL) { + log_info("Device %d of %d does not support required extension cl_khr_gl_sharing.\n", i+1, num_of_devices); + } else { + log_info("Device %d of %d supports required extension cl_khr_gl_sharing.\n", i+1, num_of_devices); + found_valid_device = 1; + m_devices[m_device_count++] = devices[i]; + } + } + return found_valid_device; + } + + virtual ~X11GLEnvironment() + { + } +}; + +GLEnvironment * GLEnvironment::Instance( void ) +{ + static X11GLEnvironment * env = NULL; + if( env == NULL ) + env = new X11GLEnvironment(); + return env; +} diff --git a/test_common/gles/gl_headers.h b/test_common/gles/gl_headers.h new file mode 100644 index 00000000..849da719 --- /dev/null +++ b/test_common/gles/gl_headers.h @@ -0,0 +1,64 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _gl_headers_h +#define _gl_headers_h + +#define GL_GLEXT_PROTOTYPES 1 + +#include + +#ifdef GLES3 +#include +#else +#include +#endif + +#include +#include + +// Some macros to minimize the changes in the tests from GL to GLES2 +#define glGenRenderbuffersEXT glGenRenderbuffers +#define glDeleteRenderbuffersEXT glDeleteRenderbuffers +#define glBindRenderbufferEXT glBindRenderbuffer +#define glRenderbufferStorageEXT glRenderbufferStorage +#define glGetRenderbufferParameterivEXT glGetRenderbufferParameteriv +#define glCheckFramebufferStatusEXT glCheckFramebufferStatus +#define glGenFramebuffersEXT glGenFramebuffers +#define glDeleteFramebuffersEXT glDeleteFramebuffers +#define glBindFramebufferEXT glBindFramebuffer +#define glFramebufferRenderbufferEXT glFramebufferRenderbuffer +#define glTexImage3D glTexImage3DOES +#define glutGetProcAddress eglGetProcAddress + +#define GL_FRAMEBUFFER_EXT GL_FRAMEBUFFER +#define GL_FRAMEBUFFER_COMPLETE_EXT GL_FRAMEBUFFER_COMPLETE +#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT GL_RENDERBUFFER_INTERNAL_FORMAT +#define GL_RENDERBUFFER_EXT GL_RENDERBUFFER +#define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0 +#define GL_DEPTH_ATTACHMENT_EXT GL_DEPTH_ATTACHMENT +#define GL_TEXTURE_3D GL_TEXTURE_3D_OES +#define GL_READ_ONLY GL_BUFFER_ACCESS_OES + +#define GL_HALF_FLOAT_ARB GL_HALF_FLOAT_OES +#define GL_BGRA GL_BGRA_EXT +#define GL_RGBA32F_ARB GL_RGBA + +typedef unsigned short GLhalf; + +GLboolean gluCheckExtension(const GLubyte *extName, const GLubyte *extString); + +#endif // __gl_headers_h + diff --git a/test_common/gles/helpers.cpp b/test_common/gles/helpers.cpp new file mode 100644 index 00000000..188f9039 --- /dev/null +++ b/test_common/gles/helpers.cpp @@ -0,0 +1,1282 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "helpers.h" + +#include "gl_headers.h" + +#define CHECK_ERROR()\ + {GLint __error = glGetError(); if(__error) {log_error( "GL ERROR: %s!\n", gluErrorString( err ));}} + +#if defined(__linux__) || defined(GL_ES_VERSION_2_0) +// On linux we dont link to GLU library to avoid comaptibility issues with +// libstdc++ +// FIXME: Implement this +const GLubyte* gluErrorString (GLenum error) +{ + const char* gl_Error = "OpenGL Error"; + return (const GLubyte*)gl_Error; +} +#endif + +static void DrawQuad(void); + +void * CreateGLTexture2D( size_t width, size_t height, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, bool allocateMem, MTdata d ) +{ + *outError = 0; + GLenum err = 0; + + char * buffer = (char *)CreateRandomData(type, width * height * 4, d); + + glGenTextures( 1, outTextureID ); + glBindTexture( get_base_gl_target( target ), *outTextureID ); + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Failed to create GL texture object: %s!\n", gluErrorString( err )); + *outError = -1; + free( buffer ); + return NULL; + } + +#ifndef GL_ES_VERSION_2_0 + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); +#endif + glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + if( get_base_gl_target( target ) == GL_TEXTURE_CUBE_MAP ) + { + char * temp = (char *)malloc(width * height * 4 * get_explicit_type_size( type ) * sizeof(cl_char)); + if(allocateMem) + memcpy( temp, buffer, width * height * 4 * get_explicit_type_size( type ) ); + else + memset( temp, 0, width * height * 4 * get_explicit_type_size( type ) ); + + glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + free(temp); + } + else + { +#ifdef GLES_DEBUG + log_info("- glTexImage2D : %s : %s : %d : %d : %s : %s\n", + GetGLTargetName(target), + GetGLFormatName(internalFormat), + width, height, + GetGLFormatName(glFormat), + GetGLTypeName(glType)); + + DumpGLBuffer(glType, width, height, buffer); + +#endif + glTexImage2D( get_base_gl_target(target), 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, buffer ); + } + + err = glGetError(); + if( err != GL_NO_ERROR ) + { + /** In section 9.8.3.1. of the CL 1.1. spec it says that: + * + * If a GL texture object with an internal format from table 9.4 is successfully created by + * OpenGL, then there is guaranteed to be a mapping to one of the corresponding CL image + * format(s) in that table. + * + * Notice that some of the formats in table 9.4 are not supported in OpenGL ES 2.0. + */ + log_info( "Warning: Skipping %s : %s : %d : %d : %s : %s : because glTexImage2D returned %s\n", + GetGLTargetName(target), + GetGLFormatName(internalFormat), + (int)(width), (int)(height), + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + + glDeleteTextures( 1, outTextureID ); + *outTextureID = 0; + *outError = 0; + free( buffer ); + err = glGetError(); + return NULL; + } + +#ifdef GLES_DEBUG + memset(buffer, 0, width * height * 4 * get_explicit_type_size( type )); + + log_info("- glGetTexImage : %s : %s : %s\n", + GetGLTargetName(target), + GetGLFormatName(glFormat), + GetGLTypeName(glType)); + + glGetTexImage(target, 0, glFormat, glType, buffer); + + DumpGLBuffer(type, width, height, buffer); + + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Unable to read data from glGetTexImage : %s : %s : %s : Error %s\n", + GetGLTargetName(target), + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + return NULL; + } +#endif + + if( !allocateMem ) + { + free( buffer ); + return NULL; + } + +#ifndef GL_ES_VERSION_2_0 + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * height; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } +#endif + + return buffer; +} + +void * CreateGLTexture3D( size_t width, size_t height, size_t depth, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, MTdata d, bool allocateMem) +{ + *outError = 0; + + char * buffer = (char *)create_random_data( type, d, width * height * depth * 4 ); + + if( type == kFloat && allocateMem ) + { + // Re-fill the created buffer to just have [0-1] floats, since that's what it'd expect + cl_float *p = (cl_float *)buffer; + for( size_t i = 0; i < width * height * depth * 4; i++ ) + { + p[ i ] = (float) genrand_real1( d ); + } + } + else if( !allocateMem ) + memset( buffer, 0, width * height * depth * 4 * get_explicit_type_size( type ) ); + + glGenTextures( 1, outTextureID ); + + glBindTexture( target, *outTextureID ); +#ifndef GL_ES_VERSION_2_0 + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); +#endif + glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + glGetError(); + glTexImage3D( target, 0, internalFormat, (GLsizei)width, (GLsizei)height, (GLsizei)depth, 0, glFormat, glType, buffer ); + GLenum err = glGetError(); + if( err != GL_NO_ERROR ) + { + /** In section 9.8.3.1. of the CL 1.1. spec it says that: + * + * If a GL texture object with an internal format from table 9.4 is successfully created by + * OpenGL, then there is guaranteed to be a mapping to one of the corresponding CL image + * format(s) in that table. + * + * Notice that some of the formats in table 9.4 are not supported in OpenGL ES 2.0. + */ + log_info( "Warning: Skipping %s : %s : %d : %d : %s : %s : because glTexImage3D returned %s\n", + GetGLTargetName(target), + GetGLFormatName(internalFormat), + (int)(width), (int)(height), + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + + *outError = 0; + delete[] buffer; + return NULL; + } + + if( !allocateMem ) + { + delete [] buffer; + return NULL; + } + +#ifndef GL_ES_VERSION_2_0 + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * height * depth; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } +#endif + + return buffer; +} + +void * ReadGLTexture( GLenum glTarget, GLuint glTexture, + GLenum glFormat, GLenum glInternalFormat, + GLenum glType, ExplicitType typeToReadAs, + size_t outWidth, size_t outHeight ) +{ + // Read results from the GL texture + glBindTexture(get_base_gl_target(glTarget), glTexture); + + GLint realWidth, realHeight; + GLint realInternalFormat; + GLenum readBackFormat = GL_RGBA; + GLenum readBackType = glType; + glFramebufferWrapper glFramebuffer; + glRenderbufferWrapper glRenderbuffer; + size_t outBytes = outWidth * outHeight * 4 * GetGLTypeSize(readBackType); + cl_char *outBuffer = (cl_char *)malloc( outBytes ); + GLenum err = 0; + + memset(outBuffer, 0, outBytes); + glGenFramebuffersEXT( 1, &glFramebuffer ); + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, glFramebuffer ); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, glTarget, glTexture, 0); + err = glGetError(); + if (err != GL_NO_ERROR) + { + log_error("Failed to attach texture to FBO!\n"); + return NULL; + } + + glReadPixels( 0, 0, (GLsizei)outWidth, (GLsizei)outHeight, readBackFormat, readBackType, outBuffer ); + +#ifdef GLES_DEBUG + + log_info( "- glGetTexImage: %s : %s : %s \n", + GetGLTargetName( glTarget), + GetGLFormatName(readBackFormat), + GetGLTypeName(readBackType)); + + DumpGLBuffer(readBackType, realWidth, realHeight, (void*)outBuffer); + +#endif + + return (void *)outBuffer; +} + +int CreateGLRenderbufferRaw( GLsizei width, GLsizei height, + GLenum attachment, + GLenum rbFormat, GLenum rbType, + GLuint *outFramebuffer, + GLuint *outRenderbuffer ) +{ + GLenum err = 0; + + // Generate a renderbuffer and bind + glGenRenderbuffersEXT( 1, outRenderbuffer ); + glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, *outRenderbuffer ); + + // Allocate storage to the renderbuffer + glGetError(); + glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, rbFormat, (GLsizei)width, (GLsizei)height ); + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error("Failed to allocate render buffer storage!\n"); + return 1701; + } + + GLint realInternalFormat; + glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &realInternalFormat ); + rbFormat = realInternalFormat; + +#ifdef GLES_DEBUG + GLint rsize, gsize, bsize, asize; + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_RED_SIZE_EXT,&rsize); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_GREEN_SIZE_EXT,&gsize); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_BLUE_SIZE_EXT,&bsize); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_ALPHA_SIZE_EXT,&asize); + + log_info("Renderbuffer internal format requested: %s actual: %s sizes: r=%d g=%d b=%d a=%d\n", + GetGLFormatName( internalFormat ), GetGLFormatName( realInternalFormat ), + rsize, gsize, bsize, asize ); +#endif + + // Create and bind a framebuffer to render with + glGenFramebuffersEXT( 1, outFramebuffer ); + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, *outFramebuffer ); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Unable to bind framebuffer : Error %s\n", + gluErrorString( err )); + + return -1; + } + + // Attach to the framebuffer + glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, *outRenderbuffer ); + err = glGetError(); + GLint status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ); + if( status != GL_FRAMEBUFFER_COMPLETE_EXT ) + { + log_error( "ERROR: Unable to attach renderbuffer to framebuffer (%s, status %x)\n", gluErrorString( err ), (int)status ); + return -1; + } + + return 0; +} + +static void DrawQuad(void) +{ + const char *vssrc = + "varying mediump vec2 texCoord;\n" + "attribute vec2 inPosition;\n" + "void main() {\n" + " texCoord = vec2((inPosition.x+1.0)/2.0, (inPosition.y+1.0)/2.0);\n" + " gl_Position = vec4(inPosition.x, inPosition.y, 0.0, 1.0);\n" + "}\n"; + const char *fssrc = + "uniform sampler2D tex;\n" + "varying mediump vec2 texCoord;\n" + "void main() {\n" + " gl_FragColor = texture2D(tex, texCoord);\n" + "}\n"; + GLuint vs, fs, program; + GLuint positionIdx = 0; + GLfloat x1 = -1.0f, x2 = 1.0f, y1 = -1.0f, y2 = 1.0f; + GLfloat vertices[4][2]; + vertices[0][0] = x1; vertices[0][1] = y1; + vertices[1][0] = x2; vertices[1][1] = y1; + vertices[2][0] = x1; vertices[2][1] = y2; + vertices[3][0] = x2; vertices[3][1] = y2; + + vs = glCreateShader(GL_VERTEX_SHADER); + fs = glCreateShader(GL_FRAGMENT_SHADER); + + glShaderSource(vs, 1, &vssrc, NULL); + glShaderSource(fs, 1, &fssrc, NULL); + + glCompileShader(vs); + glCompileShader(fs); + + program = glCreateProgram(); + glAttachShader(program, vs); + glAttachShader(program, fs); + glLinkProgram(program); + glUseProgram(program); + + positionIdx = glGetAttribLocation(program, "inPosition"); + glEnableVertexAttribArray(positionIdx); + glVertexAttribPointer(positionIdx, 2, GL_FLOAT, GL_FALSE, 0, vertices); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glUseProgram(0); + glDeleteProgram(program); + glDeleteShader(vs); + glDeleteShader(fs); +} + +void * CreateGLRenderbuffer( GLsizei width, GLsizei height, + GLenum attachment, + GLenum rbFormat, GLenum rbType, + GLenum texFormat, GLenum texType, + ExplicitType type, + GLuint *outFramebuffer, + GLuint *outRenderbuffer, + int *outError, MTdata d, bool allocateMem ) +{ + *outError = CreateGLRenderbufferRaw( width, height, attachment, rbFormat, rbType, outFramebuffer, outRenderbuffer ); + + if( *outError != 0 ) + return NULL; + + GLenum err = 0; + + // Generate a renderbuffer and bind + glGenRenderbuffersEXT( 1, outRenderbuffer ); + glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, *outRenderbuffer ); + + // Allocate storage to the renderbuffer + glGetError(); + glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, rbFormat, (GLsizei)width, (GLsizei)height ); + err = glGetError(); + if( err != GL_NO_ERROR ) + { + *outError = 1701; + log_error("Failed to allocate render buffer storage!\n"); + return NULL; + } + + GLint realInternalFormat; + glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &realInternalFormat ); + rbFormat = realInternalFormat; + +#ifdef GLES_DEBUG + GLint rsize, gsize, bsize, asize; + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_RED_SIZE_EXT,&rsize); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_GREEN_SIZE_EXT,&gsize); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_BLUE_SIZE_EXT,&bsize); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_ALPHA_SIZE_EXT,&asize); + + log_info("Renderbuffer internal format requested: %s actual: %s sizes: r=%d g=%d b=%d a=%d\n", + GetGLFormatName( internalFormat ), GetGLFormatName( realInternalFormat ), + rsize, gsize, bsize, asize ); +#endif + + // Create and bind a framebuffer to render with + glGenFramebuffersEXT( 1, outFramebuffer ); + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, *outFramebuffer ); + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Unable to bind framebuffer : Error %s\n", + gluErrorString( err )); + + *outError = -1; + return NULL; + } + + // Attach to the framebuffer + glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, *outRenderbuffer ); + CHECK_ERROR(); + GLint status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ); + if( status != GL_FRAMEBUFFER_COMPLETE_EXT ) + { + *outError = -1; + log_error( "ERROR: Unable to attach renderbuffer to framebuffer (%s, status %x)\n", gluErrorString( err ), (int)status ); + return NULL; + } + + void* buffer = CreateRandomData(type, width * height * 4, d); + +#ifdef GLES_DEBUG + log_info( "- Fillling renderbuffer: %d : %d : %s : %s \n", + (int)width, (int)height, + GetGLFormatName(glFormat), + GetGLTypeName(glType)); + + DumpGLBuffer(glType, (int)width, (int)height, (void*)buffer); +#endif + + CHECK_ERROR(); + + // Fill a texture with our input data + glTextureWrapper texture; + glGenTextures( 1, &texture ); + glBindTexture( GL_TEXTURE_2D, texture ); + CHECK_ERROR(); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + CHECK_ERROR(); + glTexImage2D( GL_TEXTURE_2D, 0, texFormat, width, height, 0, texFormat, texType, buffer ); + CHECK_ERROR(); + + // Render fullscreen textured quad + glViewport(0, 0, width, height); + DrawQuad(); + CHECK_ERROR(); + + // Read back the data in the renderbuffer + memset(buffer, 0, width * height * 4 * get_explicit_type_size( type )); + glReadPixels( 0, 0, (GLsizei)width, (GLsizei)height, texFormat, texType, buffer ); + + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Unable to read data via glReadPixels : %d : %d : %s : %s : Error %s\n", + (int)width, (int)height, + GetGLFormatName(texFormat), + GetGLTypeName(texType), + gluErrorString( err )); + *outError = -1; + } + +#ifdef GLES_DEBUG + log_info( "- glReadPixels: %d : %d : %s : %s \n", + (int)width, (int)height, + GetGLFormatName(glFormat), + GetGLTypeName(glType)); + + DumpGLBuffer(glType, (int)width, (int)height, (void*)buffer); +#endif + + if( !allocateMem ) + { + free( buffer ); + return NULL; + } + +#ifndef GL_ES_VERSION_2_0 + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < (size_t)width * height; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } +#endif + + return buffer; +} + +void * ReadGLRenderbuffer( GLuint glFramebuffer, GLuint glRenderbuffer, + GLenum attachment, + GLenum rbFormat, GLenum rbType, + GLenum texFormat, GLenum texType, + ExplicitType typeToReadAs, + size_t outWidth, size_t outHeight ) +{ + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, glFramebuffer ); + glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, glRenderbuffer ); + + // Attach to the framebuffer + GLint err = glGetError(); + if( glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ) != GL_FRAMEBUFFER_COMPLETE_EXT ) + { + log_error( "ERROR: Unable to attach renderbuffer to framebuffer (%s)\n", gluErrorString( err ) ); + return NULL; + } + + // Read results from the GL renderbuffer +#ifdef GLES_DEBUG + log_info( "- Reading back from GL: %d x %d : %s : %s : %s\n", + (int)outWidth, (int)outHeight, + GetGLFormatName( glInternalFormat ), + GetGLFormatName( glFormat ), + GetGLTypeName( glType )); +#endif + + GLenum readBackFormat = GL_RGBA; + GLenum readBackType = texType; + + size_t outBytes = outWidth * outHeight * 4 * GetGLTypeSize(readBackType); + void *outBuffer = malloc( outBytes ); + memset(outBuffer, 0, outBytes); + + glReadPixels( 0, 0, (GLsizei)outWidth, (GLsizei)outHeight, readBackFormat, readBackType, outBuffer ); + +#ifdef GLES_DEBUG + log_info( "- glReadPixels: %d : %d : %s : %s \n", + (int)outWidth, (int)outHeight, + GetGLFormatName(readBackFormat), + GetGLTypeName(readBackType)); + + DumpGLBuffer(readBackType, outWidth, outHeight, outBuffer); +#endif + + return (void *)outBuffer; +} + +GLenum +GetGLFormat(GLenum internalFormat) +{ + GLenum glFormat; + switch (internalFormat) + { + case GL_BGRA: +#ifndef GL_ES_VERSION_2_0 + case GL_RGBA8: + case GL_RGBA16: + case GL_RGBA32F_ARB: +#endif + glFormat = GL_RGBA; + break; +#ifndef GL_ES_VERSION_2_0 + case GL_RGBA8I_EXT: + case GL_RGBA16I_EXT: + case GL_RGBA32I_EXT: + case GL_RGBA8UI_EXT: + case GL_RGBA16UI_EXT: + case GL_RGBA32UI_EXT: + glFormat = GL_RGBA_INTEGER_EXT; + break; +#endif + default: + glFormat = GL_RGBA; + break; + } + + return glFormat; +} + +GLenum GetGLTypeForExplicitType(ExplicitType type) +{ + switch( type ) + { + case kFloat: + return GL_FLOAT; + case kInt: + return GL_INT; + case kUInt: + return GL_UNSIGNED_INT; + case kShort: + return GL_SHORT; + case kUShort: + return GL_UNSIGNED_SHORT; + case kChar: + return GL_BYTE; + case kUChar: + return GL_UNSIGNED_BYTE; + case kHalf: +#if defined( __APPLE__ ) + return GL_HALF_FLOAT; +#else + return GL_HALF_FLOAT_ARB; +#endif + default: + return GL_INT; + }; +} + +size_t GetGLTypeSize(GLenum type) +{ + switch( type ) + { + case GL_FLOAT: + return sizeof(GLfloat); + case GL_INT: + return sizeof(GLint); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + case GL_SHORT: + return sizeof(GLshort); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_BYTE: + return sizeof(GLbyte); + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); +#if defined( __APPLE__ ) + case GL_HALF_FLOAT: +#else + case GL_HALF_FLOAT_ARB: +#endif + return sizeof(GLhalf); + default: + return kFloat; + }; +} + +ExplicitType GetExplicitTypeForGLType(GLenum type) +{ + switch( type ) + { + case GL_FLOAT: + return kFloat; + case GL_INT: + return kInt; + case GL_UNSIGNED_INT: + return kUInt; + case GL_SHORT: + return kShort; + case GL_UNSIGNED_SHORT: + return kUShort; + case GL_BYTE: + return kChar; + case GL_UNSIGNED_BYTE: + return kUChar; +#if defined( __APPLE__ ) + case GL_HALF_FLOAT: +#else + case GL_HALF_FLOAT_ARB: +#endif + return kHalf; + default: + return kFloat; + }; +} + +GLenum get_base_gl_target( GLenum target ) +{ + switch( target ) + { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + return GL_TEXTURE_CUBE_MAP; + default: + return target; + } +} + +const char *GetGLTypeName( GLenum type ) +{ + switch( type ) + { + case GL_BYTE: return "GL_BYTE"; + case GL_UNSIGNED_BYTE: return "GL_UNSIGNED_BYTE"; + case GL_INT: return "GL_INT"; + case GL_UNSIGNED_INT: return "GL_UNSIGNED_INT"; + case GL_SHORT: return "GL_SHORT"; + case GL_UNSIGNED_SHORT: return "GL_UNSIGNED_SHORT"; +#if defined( __APPLE__ ) + case GL_HALF_FLOAT: return "GL_HALF_FLOAT"; +#else + case GL_HALF_FLOAT_ARB: return "GL_HALF_FLOAT_ARB"; +#endif + case GL_FLOAT: return "GL_FLOAT"; +#ifndef GL_ES_VERSION_2_0 + case GL_UNSIGNED_INT_8_8_8_8: return "GL_UNSIGNED_INT_8_8_8_8"; + case GL_UNSIGNED_INT_8_8_8_8_REV: return "GL_UNSIGNED_INT_8_8_8_8_REV"; +#endif + default: + { + static char foo[ 128 ]; + sprintf( foo, "(Unknown:0x%08x)", (int)type ); + return foo; + } + } +} + +const char *GetGLTargetName( GLenum tgt ) +{ + if( tgt == GL_TEXTURE_2D ) return "GL_TEXTURE_2D"; + if( tgt == GL_TEXTURE_3D ) return "GL_TEXTURE_3D"; +#ifndef GL_ES_VERSION_2_0 + if( tgt == GL_TEXTURE_RECTANGLE_EXT ) return "GL_TEXTURE_RECTANGLE_EXT"; +#endif + if( tgt == GL_TEXTURE_CUBE_MAP_POSITIVE_X ) return "GL_TEXTURE_CUBE_MAP_POSITIVE_X"; + if( tgt == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ) return "GL_TEXTURE_CUBE_MAP_POSITIVE_Y"; + if( tgt == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ) return "GL_TEXTURE_CUBE_MAP_POSITIVE_Z"; + if( tgt == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ) return "GL_TEXTURE_CUBE_MAP_NEGATIVE_X"; + if( tgt == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ) return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y"; + if( tgt == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ) return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z"; + return ""; +} + +const char *GetGLAttachmentName( GLenum att ) +{ + if( att == GL_COLOR_ATTACHMENT0_EXT ) return "GL_COLOR_ATTACHMENT0_EXT"; +#ifndef GL_ES_VERSION_2_0 + if( att == GL_COLOR_ATTACHMENT1_EXT ) return "GL_COLOR_ATTACHMENT1_EXT"; + if( att == GL_COLOR_ATTACHMENT2_EXT ) return "GL_COLOR_ATTACHMENT2_EXT"; + if( att == GL_COLOR_ATTACHMENT3_EXT ) return "GL_COLOR_ATTACHMENT3_EXT"; + if( att == GL_COLOR_ATTACHMENT4_EXT ) return "GL_COLOR_ATTACHMENT4_EXT"; + if( att == GL_COLOR_ATTACHMENT5_EXT ) return "GL_COLOR_ATTACHMENT5_EXT"; + if( att == GL_COLOR_ATTACHMENT6_EXT ) return "GL_COLOR_ATTACHMENT6_EXT"; + if( att == GL_COLOR_ATTACHMENT7_EXT ) return "GL_COLOR_ATTACHMENT7_EXT"; + if( att == GL_COLOR_ATTACHMENT8_EXT ) return "GL_COLOR_ATTACHMENT8_EXT"; +#endif + if( att == GL_DEPTH_ATTACHMENT_EXT ) return "GL_DEPTH_ATTACHMENT_EXT"; + return ""; +} +const char *GetGLBaseFormatName( GLenum baseformat ) +{ + switch( baseformat ) + { + case GL_RGBA: return "GL_RGBA"; +#ifdef GL_ES_VERSION_2_0 + case GL_BGRA_EXT: return "GL_BGRA_EXT"; +#else + case GL_RGBA8: return "GL_RGBA"; + case GL_RGBA16: return "GL_RGBA"; + case GL_BGRA: return "GL_BGRA"; + case GL_RGBA8I_EXT: return "GL_RGBA_INTEGER_EXT"; + case GL_RGBA16I_EXT: return "GL_RGBA_INTEGER_EXT"; + case GL_RGBA32I_EXT: return "GL_RGBA_INTEGER_EXT"; + case GL_RGBA8UI_EXT: return "GL_RGBA_INTEGER_EXT"; + case GL_RGBA16UI_EXT: return "GL_RGBA_INTEGER_EXT"; + case GL_RGBA32UI_EXT: return "GL_RGBA_INTEGER_EXT"; + case GL_RGBA32F_ARB: return "GL_RGBA"; + + case GL_RGBA_INTEGER_EXT: return "GL_RGBA_INTEGER_EXT"; + + case GL_ALPHA4: return "GL_ALPHA"; + case GL_ALPHA8: return "GL_ALPHA"; + case GL_ALPHA12: return "GL_ALPHA"; + case GL_ALPHA16: return "GL_ALPHA"; + case GL_LUMINANCE4: return "GL_LUMINANCE"; + case GL_LUMINANCE8: return "GL_LUMINANCE"; + case GL_LUMINANCE12: return "GL_LUMINANCE"; + case GL_LUMINANCE16: return "GL_LUMINANCE"; + case GL_LUMINANCE4_ALPHA4: return "GL_LUMINANCE_ALPHA"; + case GL_LUMINANCE6_ALPHA2: return "GL_LUMINANCE_ALPHA"; + case GL_LUMINANCE8_ALPHA8: return "GL_LUMINANCE_ALPHA"; + case GL_LUMINANCE12_ALPHA4: return "GL_LUMINANCE_ALPHA"; + case GL_LUMINANCE12_ALPHA12: return "GL_LUMINANCE_ALPHA"; + case GL_LUMINANCE16_ALPHA16: return "GL_LUMINANCE_ALPHA"; + case GL_INTENSITY: return "GL_INTENSITY"; + case GL_INTENSITY4: return "GL_INTENSITY"; + case GL_INTENSITY8: return "GL_INTENSITY"; + case GL_INTENSITY12: return "GL_INTENSITY"; + case GL_INTENSITY16: return "GL_INTENSITY"; + case GL_R3_G3_B2: return "GL_RGB"; + case GL_RGB4: return "GL_RGB"; + case GL_RGB5: return "GL_RGB"; + case GL_RGB8: return "GL_RGB"; + case GL_RGB10: return "GL_RGB"; + case GL_RGB12: return "GL_RGB"; + case GL_RGB16: return "GL_RGB"; + case GL_RGBA2: return "GL_RGBA"; + case GL_RGBA4: return "GL_RGBA"; + case GL_RGB5_A1: return "GL_RGBA"; + case GL_RGB10_A2: return "GL_RGBA"; + case GL_RGBA12: return "GL_RGBA"; +#endif + + default: + { + static char foo[ 128 ]; + sprintf( foo, "(Unknown:0x%08x)", (int)baseformat ); + return foo; + } + } +} + +const char *GetGLFormatName( GLenum format ) +{ + switch( format ) + { + case GL_RGBA: return "GL_RGBA"; +#ifdef GL_ES_VERSION_2_0 + case GL_BGRA_EXT: return "GL_BGRA_EXT"; +#else + case GL_RGBA8: return "GL_RGBA8"; + case GL_RGBA16: return "GL_RGBA16"; + case GL_BGRA: return "GL_BGRA"; + case GL_RGBA8I_EXT: return "GL_RGBA8I_EXT"; + case GL_RGBA16I_EXT: return "GL_RGBA16I_EXT"; + case GL_RGBA32I_EXT: return "GL_RGBA32I_EXT"; + case GL_RGBA8UI_EXT: return "GL_RGBA8UI_EXT"; + case GL_RGBA16UI_EXT: return "GL_RGBA16UI_EXT"; + case GL_RGBA32UI_EXT: return "GL_RGBA32UI_EXT"; + case GL_RGBA32F_ARB: return "GL_RGBA32F_ARB"; + + case GL_RGBA_INTEGER_EXT: return "GL_RGBA_INTEGER_EXT"; + + case GL_ALPHA4: return "GL_ALPHA4"; + case GL_ALPHA8: return "GL_ALPHA8"; + case GL_ALPHA12: return "GL_ALPHA12"; + case GL_ALPHA16: return "GL_ALPHA16"; + case GL_LUMINANCE4: return "GL_LUMINANCE4"; + case GL_LUMINANCE8: return "GL_LUMINANCE8"; + case GL_LUMINANCE12: return "GL_LUMINANCE12"; + case GL_LUMINANCE16: return "GL_LUMINANCE16"; + case GL_LUMINANCE4_ALPHA4: return "GL_LUMINANCE4_ALPHA4"; + case GL_LUMINANCE6_ALPHA2: return "GL_LUMINANCE6_ALPHA2"; + case GL_LUMINANCE8_ALPHA8: return "GL_LUMINANCE8_ALPHA8"; + case GL_LUMINANCE12_ALPHA4: return "GL_LUMINANCE12_ALPHA4"; + case GL_LUMINANCE12_ALPHA12: return "GL_LUMINANCE12_ALPHA12"; + case GL_LUMINANCE16_ALPHA16: return "GL_LUMINANCE16_ALPHA16"; + case GL_INTENSITY: return "GL_INTENSITY"; + case GL_INTENSITY4: return "GL_INTENSITY4"; + case GL_INTENSITY8: return "GL_INTENSITY8"; + case GL_INTENSITY12: return "GL_INTENSITY12"; + case GL_INTENSITY16: return "GL_INTENSITY16"; + case GL_R3_G3_B2: return "GL_R3_G3_B2"; + case GL_RGB4: return "GL_RGB4"; + case GL_RGB5: return "GL_RGB5"; + case GL_RGB8: return "GL_RGB8"; + case GL_RGB10: return "GL_RGB10"; + case GL_RGB12: return "GL_RGB12"; + case GL_RGB16: return "GL_RGB16"; + case GL_RGBA2: return "GL_RGBA2"; + case GL_RGBA4: return "GL_RGBA4"; + case GL_RGB5_A1: return "GL_RGB5_A1"; + case GL_RGB10_A2: return "GL_RGB10_A2"; + case GL_RGBA12: return "GL_RGBA12"; +#endif + case GL_INT: return "GL_INT"; + case GL_UNSIGNED_INT: return "GL_UNSIGNED_INT"; + case GL_SHORT: return "GL_SHORT"; + case GL_UNSIGNED_SHORT: return "GL_UNSIGNED_SHORT"; + case GL_BYTE: return "GL_BYTE"; + case GL_UNSIGNED_BYTE: return "GL_UNSIGNED_BYTE"; + case GL_FLOAT: return "GL_FLOAT"; +#ifdef GL_ES_VERSION_2_0 + case GL_HALF_FLOAT_OES: return "GL_HALF_FLOAT_OES"; +#else +#if defined( __APPLE__ ) + case GL_HALF_FLOAT: return "GL_HALF_FLOAT"; +#else + case GL_HALF_FLOAT_ARB: return "GL_HALF_FLOAT_ARB"; +#endif +#endif + + default: + { + static char foo[ 128 ]; + sprintf( foo, "(Unknown:0x%08x)", (int)format ); + return foo; + } + } +} + +cl_ushort float2half_rte( float f ) +{ + union{ float f; cl_uint u; } u = {f}; + cl_uint sign = (u.u >> 16) & 0x8000; + float x = fabsf(f); + + //Nan + if( x != x ) + { + u.u >>= (24-11); + u.u &= 0x7fff; + u.u |= 0x0200; //silence the NaN + return u.u | sign; + } + + // overflow + if( x >= MAKE_HEX_FLOAT(0x1.ffep15f, 0x1ffeL, 3) ) + return 0x7c00 | sign; + + // underflow + if( x <= MAKE_HEX_FLOAT(0x1.0p-25f, 0x1L, -25) ) + return sign; // The halfway case can return 0x0001 or 0. 0 is even. + + // very small + if( x < MAKE_HEX_FLOAT(0x1.8p-24f, 0x18L, -28) ) + return sign | 1; + + // half denormal + if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) ) + { + u.f = x * MAKE_HEX_FLOAT(0x1.0p-125f, 0x1L, -125); + return sign | u.u; + } + + u.f *= MAKE_HEX_FLOAT(0x1.0p13f, 0x1L, 13); + u.u &= 0x7f800000; + x += u.f; + u.f = x - u.f; + u.f *= MAKE_HEX_FLOAT(0x1.0p-112f, 0x1L, -112); + + return (u.u >> (24-11)) | sign; +} + +void* CreateRandomData( ExplicitType type, size_t count, MTdata d ) +{ + switch(type) + { + case (kChar): + { + cl_char *p = (cl_char *)malloc(count * sizeof(cl_char)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = (cl_char)genrand_int32(d); + } + return (void*)p; + } + case (kUChar): + { + cl_uchar *p = (cl_uchar *)malloc(count * sizeof(cl_uchar)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = (cl_uchar)genrand_int32(d); + } + + return (void*)p; + } + case (kShort): + { + cl_short *p = (cl_short *)malloc(count * sizeof(cl_short)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = (cl_short)genrand_int32(d); + } + + return (void*)p; + } + case (kUShort): + { + cl_ushort *p = (cl_ushort *)malloc(count * sizeof(cl_ushort)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = (cl_ushort)genrand_int32(d); + } + + return (void*)p; + } + case (kInt): + { + cl_int *p = (cl_int *)malloc(count * sizeof(cl_int)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = (cl_int)genrand_int32(d); + } + + return (void*)p; + } + case (kUInt): + { + cl_uint *p = (cl_uint *)malloc(count * sizeof(cl_uint)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = (cl_uint)genrand_int32(d); + } + + return (void*)p; + } + + case (kFloat): + { + cl_float *p = (cl_float *)malloc(count * sizeof(cl_float)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = get_random_float( 0.f, 1.f, d ); + } + + return (void*)p; + } + /* added support for half floats */ + case (kHalf): + { + cl_half *p = (cl_half *)malloc(count * sizeof(cl_half)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = float2half_rte(get_random_float( 0.f, 1.f, d )); + } + + return (void*)p; + } + default: + { + log_error("Invalid explicit type specified for create random data!\n"); + return 0; + } + } + return 0; +} + +void DumpGLBuffer(GLenum type, size_t width, size_t height, void* buffer) +{ + size_t i; + size_t count = width * height; + if(type == GL_BYTE) + { + cl_char* p = (cl_char*)buffer; + for(i = 0; i < count; i++) + log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), + p[i* 4 + 0], + p[i* 4 + 1], + p[i* 4 + 2], + p[i* 4 + 3]); + } + else if(type == GL_UNSIGNED_BYTE) + { + cl_uchar* p = (cl_uchar*)buffer; + for(i = 0; i < count; i++) + log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), + p[i* 4 + 0], + p[i* 4 + 1], + p[i* 4 + 2], + p[i* 4 + 3]); + } + else if(type == GL_INT) + { + cl_int* p = (cl_int*)buffer; + for(i = 0; i < count; i++) + log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), + p[i* 4 + 0], + p[i* 4 + 1], + p[i* 4 + 2], + p[i* 4 + 3]); + } + else if(type == GL_UNSIGNED_INT) + { + cl_uint* p = (cl_uint*)buffer; + for(i = 0; i < count; i++) + log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), + p[i* 4 + 0], + p[i* 4 + 1], + p[i* 4 + 2], + p[i* 4 + 3]); + } + else if(type == GL_SHORT) + { + cl_short* p = (cl_short*)buffer; + for(i = 0; i < count; i++) + log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), + p[i* 4 + 0], + p[i* 4 + 1], + p[i* 4 + 2], + p[i* 4 + 3]); + } + else if(type == GL_UNSIGNED_SHORT) + { + cl_ushort* p = (cl_ushort*)buffer; + for(i = 0; i < count; i++) + log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), + p[i* 4 + 0], + p[i* 4 + 1], + p[i* 4 + 2], + p[i* 4 + 3]); + } + else if(type == GL_FLOAT) + { + cl_float* p = (cl_float*)buffer; + for(i = 0; i < count; i++) + log_info("[%4d] %#f %#f %#f %#f\n", (unsigned int)(i), + p[i* 4 + 0], + p[i* 4 + 1], + p[i* 4 + 2], + p[i* 4 + 3]); + } +} + +#if defined(_WIN32) +#include + +GLboolean gluCheckExtension(const GLubyte *extName, const GLubyte *extString) +{ + const size_t len = strlen((const char*)extName); + const char* str = (const char*)extString; + + while (str != NULL) { + str = strstr(str, (const char*)extName); + if (str == NULL) { + break; + } + if ((str > (const char*)extString || str[-1] == ' ') + && (str[len] == ' ' || str[len] == '\0')) { + return GL_TRUE; + } + str = strchr(str + len, ' '); + } + + return GL_FALSE; +} + +#endif + +// Function pointers for the GL/CL calls +clCreateFromGLBuffer_fn clCreateFromGLBuffer_ptr; +clCreateFromGLTexture_fn clCreateFromGLTexture_ptr; +clCreateFromGLRenderbuffer_fn clCreateFromGLRenderbuffer_ptr; +clGetGLObjectInfo_fn clGetGLObjectInfo_ptr; +clGetGLTextureInfo_fn clGetGLTextureInfo_ptr; +clEnqueueAcquireGLObjects_fn clEnqueueAcquireGLObjects_ptr; +clEnqueueReleaseGLObjects_fn clEnqueueReleaseGLObjects_ptr; + +int init_clgl_ext(cl_platform_id platform_id) +{ + // Create the function pointer table + clCreateFromGLBuffer_ptr = (clCreateFromGLBuffer_fn)clGetExtensionFunctionAddressForPlatform(platform_id, "clCreateFromGLBuffer"); + if (clCreateFromGLBuffer_ptr == NULL) + { + log_error("clGetExtensionFunctionAddressForPlatform(clCreateFromGLBuffer) returned NULL.\n"); + return -1; + } + + clCreateFromGLTexture_ptr = (clCreateFromGLTexture_fn)clGetExtensionFunctionAddressForPlatform(platform_id, "clCreateFromGLTexture"); + if (clCreateFromGLTexture_ptr == NULL) + { + log_error("clGetExtensionFunctionAddressForPlatform(clCreateFromGLTexture) returned NULL.\n"); + return -1; + } + + clCreateFromGLRenderbuffer_ptr = (clCreateFromGLRenderbuffer_fn)clGetExtensionFunctionAddressForPlatform(platform_id, "clCreateFromGLRenderbuffer"); + if (clCreateFromGLRenderbuffer_ptr == NULL) + { + log_error("clGetExtensionFunctionAddressForPlatform(clCreateFromGLRenderbuffer) returned NULL.\n"); + return -1; + } + + clGetGLObjectInfo_ptr = (clGetGLObjectInfo_fn)clGetExtensionFunctionAddressForPlatform(platform_id, "clGetGLObjectInfo"); + if (clGetGLObjectInfo_ptr == NULL) + { + log_error("clGetExtensionFunctionAddressForPlatform(clGetGLObjectInfo) returned NULL.\n"); + return -1; + } + + clGetGLTextureInfo_ptr = (clGetGLTextureInfo_fn)clGetExtensionFunctionAddressForPlatform(platform_id, "clGetGLTextureInfo"); + if (clGetGLTextureInfo_ptr == NULL) + { + log_error("clGetExtensionFunctionAddressForPlatform(clGetGLTextureInfo) returned NULL.\n"); + return -1; + } + + clEnqueueAcquireGLObjects_ptr = (clEnqueueAcquireGLObjects_fn)clGetExtensionFunctionAddressForPlatform(platform_id, "clEnqueueAcquireGLObjects"); + if (clEnqueueAcquireGLObjects_ptr == NULL) + { + log_error("clGetExtensionFunctionAddressForPlatform(clEnqueueAcquireGLObjects) returned NULL.\n"); + return -1; + } + + clEnqueueReleaseGLObjects_ptr = (clEnqueueReleaseGLObjects_fn)clGetExtensionFunctionAddressForPlatform(platform_id, "clEnqueueReleaseGLObjects"); + if (clEnqueueReleaseGLObjects_ptr == NULL) + { + log_error("clGetExtensionFunctionAddressForPlatform(clEnqueueReleaseGLObjects) returned NULL.\n"); + return -1; + } + + return 0; +} + + diff --git a/test_common/gles/helpers.h b/test_common/gles/helpers.h new file mode 100644 index 00000000..95faae12 --- /dev/null +++ b/test_common/gles/helpers.h @@ -0,0 +1,247 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _helpers_h +#define _helpers_h + +#include +#include +#include +#include + +#if !defined(_WIN32) +#include +#endif + +#include +#include + +#if !defined (__APPLE__) +#include +#include "gl_headers.h" +#include +#else +#include "gl_headers.h" +#endif + +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/threadTesting.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/mt19937.h" + +typedef cl_mem +(CL_API_CALL *clCreateFromGLBuffer_fn)(cl_context context, + cl_mem_flags flags, + GLuint bufobj, + int * errcode_ret); + +typedef cl_mem +(CL_API_CALL *clCreateFromGLTexture_fn)(cl_context context , + cl_mem_flags flags , + GLenum target , + GLint miplevel , + GLuint texture , + cl_int * errcode_ret) ; + +typedef cl_mem +(CL_API_CALL *clCreateFromGLRenderbuffer_fn)(cl_context context , + cl_mem_flags flags , + GLuint renderbuffer , + cl_int * errcode_ret) ; + +typedef cl_int +(CL_API_CALL *clGetGLObjectInfo_fn)(cl_mem memobj , + cl_gl_object_type * gl_object_type , + GLuint * gl_object_name) ; + +typedef cl_int +(CL_API_CALL *clGetGLTextureInfo_fn)(cl_mem memobj , + cl_gl_texture_info param_name , + size_t param_value_size , + void * param_value , + size_t * param_value_size_ret) ; + +typedef cl_int +(CL_API_CALL *clEnqueueAcquireGLObjects_fn)(cl_command_queue command_queue , + cl_uint num_objects , + const cl_mem * mem_objects , + cl_uint num_events_in_wait_list , + const cl_event * event_wait_list , + cl_event * event) ; + +typedef cl_int +(CL_API_CALL *clEnqueueReleaseGLObjects_fn)(cl_command_queue command_queue , + cl_uint num_objects , + const cl_mem * mem_objects , + cl_uint num_events_in_wait_list , + const cl_event * event_wait_list , + cl_event * event) ; + + +extern clCreateFromGLBuffer_fn clCreateFromGLBuffer_ptr; +extern clCreateFromGLTexture_fn clCreateFromGLTexture_ptr; +extern clCreateFromGLRenderbuffer_fn clCreateFromGLRenderbuffer_ptr; +extern clGetGLObjectInfo_fn clGetGLObjectInfo_ptr; +extern clGetGLTextureInfo_fn clGetGLTextureInfo_ptr; +extern clEnqueueAcquireGLObjects_fn clEnqueueAcquireGLObjects_ptr; +extern clEnqueueReleaseGLObjects_fn clEnqueueReleaseGLObjects_ptr; + + +class glBufferWrapper +{ + public: + glBufferWrapper() { mBuffer = 0; } + glBufferWrapper( GLuint b ) { mBuffer = b; } + ~glBufferWrapper() { if( mBuffer != 0 ) glDeleteBuffers( 1, &mBuffer ); } + + glBufferWrapper & operator=( const GLuint &rhs ) { mBuffer = rhs; return *this; } + operator GLuint() { return mBuffer; } + operator GLuint *() { return &mBuffer; } + + GLuint * operator&() { return &mBuffer; } + + bool operator==( GLuint rhs ) { return mBuffer == rhs; } + + protected: + + GLuint mBuffer; +}; + +class glTextureWrapper +{ + public: + glTextureWrapper() { mBuffer = 0; } + glTextureWrapper( GLuint b ) { mBuffer = b; } + ~glTextureWrapper() { if( mBuffer != 0 ) glDeleteTextures( 1, &mBuffer ); } + + glTextureWrapper & operator=( const GLuint &rhs ) { mBuffer = rhs; return *this; } + operator GLuint() { return mBuffer; } + operator GLuint *() { return &mBuffer; } + + GLuint * operator&() { return &mBuffer; } + + bool operator==( GLuint rhs ) { return mBuffer == rhs; } + + protected: + + GLuint mBuffer; +}; + +class glRenderbufferWrapper +{ + public: + glRenderbufferWrapper() { mBuffer = 0; } + glRenderbufferWrapper( GLuint b ) { mBuffer = b; } + ~glRenderbufferWrapper() { if( mBuffer != 0 ) glDeleteRenderbuffersEXT( 1, &mBuffer ); } + + glRenderbufferWrapper & operator=( const GLuint &rhs ) { mBuffer = rhs; return *this; } + operator GLuint() { return mBuffer; } + operator GLuint *() { return &mBuffer; } + + GLuint * operator&() { return &mBuffer; } + + bool operator==( GLuint rhs ) { return mBuffer == rhs; } + + protected: + + GLuint mBuffer; +}; + +class glFramebufferWrapper +{ + public: + glFramebufferWrapper() { mBuffer = 0; } + glFramebufferWrapper( GLuint b ) { mBuffer = b; } + ~glFramebufferWrapper() { if( mBuffer != 0 ) glDeleteFramebuffersEXT( 1, &mBuffer ); } + + glFramebufferWrapper & operator=( const GLuint &rhs ) { mBuffer = rhs; return *this; } + operator GLuint() { return mBuffer; } + operator GLuint *() { return &mBuffer; } + + GLuint * operator&() { return &mBuffer; } + + bool operator==( GLuint rhs ) { return mBuffer == rhs; } + + protected: + + GLuint mBuffer; +}; + + +// Helper functions (defined in helpers.cpp) +extern void * CreateGLTexture2D( size_t width, size_t height, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, bool allocateMem, MTdata d ); + + +extern void * CreateGLTexture3D( size_t width, size_t height, size_t depth, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, MTdata d, bool allocateMem = true ); + +extern void * ReadGLTexture( GLenum glTarget, GLuint glTexture, + GLenum glFormat, GLenum glInternalFormat, + GLenum glType, ExplicitType typeToReadAs, + size_t outWidth, size_t outHeight ); + +void * CreateGLRenderbuffer( GLsizei width, GLsizei height, + GLenum attachment, + GLenum rbFormat, GLenum rbType, + GLenum texFormat, GLenum texType, + ExplicitType type, + GLuint *outFramebuffer, + GLuint *outRenderbuffer, + int *outError, MTdata d, bool allocateMem ); + +int CreateGLRenderbufferRaw( GLsizei width, GLsizei height, + GLenum attachment, + GLenum rbFormat, GLenum rbType, + GLuint *outFramebuffer, + GLuint *outRenderbuffer ); + +void * ReadGLRenderbuffer( GLuint glFramebuffer, GLuint glRenderbuffer, + GLenum attachment, + GLenum rbFormat, GLenum rbType, + GLenum texFormat, GLenum texType, + ExplicitType typeToReadAs, + size_t outWidth, size_t outHeight ); + +extern void DumpGLBuffer(GLenum type, size_t width, size_t height, void* buffer); +extern const char *GetGLTypeName( GLenum type ); +extern const char *GetGLAttachmentName( GLenum att ); +extern const char *GetGLTargetName( GLenum tgt ); +extern const char *GetGLBaseFormatName( GLenum baseformat ); +extern const char *GetGLFormatName( GLenum format ); + +extern void* CreateRandomData( ExplicitType type, size_t count, MTdata d ); + +extern GLenum GetGLFormat(GLenum internalFormat); +extern GLenum GetGLTypeForExplicitType(ExplicitType type); +extern size_t GetGLTypeSize(GLenum type); +extern ExplicitType GetExplicitTypeForGLType(GLenum type); + +extern GLenum get_base_gl_target( GLenum target ); + +extern int init_clgl_ext( cl_platform_id platform_id ); + +#endif // _helpers_h + + + diff --git a/test_common/gles/setup.h b/test_common/gles/setup.h new file mode 100644 index 00000000..0b2a9fdf --- /dev/null +++ b/test_common/gles/setup.h @@ -0,0 +1,46 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _setup_h +#define _setup_h + +#include +#include +#include +#include "gl_headers.h" +#include + + +// Note: the idea here is to have every platform define their own setup.cpp file that implements a GLEnvironment +// subclass internally, then return it as a definition for GLEnvironment::Create + +class GLEnvironment +{ + public: + GLEnvironment() {} + virtual ~GLEnvironment() {} + + virtual int Init( int *argc, char **argv, int use_opengl_32 ) = 0; + virtual cl_context CreateCLContext( void ) = 0; + virtual int SupportsCLGLInterop( cl_device_type device_type) = 0; + + // cleanup EGL environment properly when the test exit. + // This change does not affect any functionality of the test + virtual void terminate_egl_display() = 0; + + static GLEnvironment * Instance( void ); +}; + +#endif // _setup_h diff --git a/test_common/harness/Jamfile b/test_common/harness/Jamfile new file mode 100644 index 00000000..21ebcc24 --- /dev/null +++ b/test_common/harness/Jamfile @@ -0,0 +1,18 @@ +project + : requirements . + gcc:"-xc++" + msvc:"/TP" + off + : usage-requirements . + ; + +local harness.objs ; +for source in [ glob *.c *.cpp ] +{ + harness.objs += [ obj $(source:B).obj : $(source) ] ; +} + +alias harness : $(harness.objs) + : /Runtime//OpenCL.lib : + : /Runtime//OpenCL.lib + ; diff --git a/test_common/harness/Makefile b/test_common/harness/Makefile new file mode 100644 index 00000000..2ac60643 --- /dev/null +++ b/test_common/harness/Makefile @@ -0,0 +1,41 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = conversions.c \ + errorHelpers.c \ + genericThread.cpp \ + imageHelpers.cpp \ + kernelHelpers.c \ + mt19937.c \ + rounding_mode.c \ + testHarness.c \ + testHarness.cpp \ + ThreadPool.c \ + threadTesting.c \ + typeWrappers.cpp + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +HEADERS = +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +all: $(OBJECTS) + +clean: + rm -f $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_common/harness/ThreadPool.c b/test_common/harness/ThreadPool.c new file mode 100644 index 00000000..16f31e74 --- /dev/null +++ b/test_common/harness/ThreadPool.c @@ -0,0 +1,931 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "ThreadPool.h" +#include "errorHelpers.h" +#include "fpcontrol.h" +#include +#include + +#if defined( __APPLE__ ) || defined( __linux__ ) || defined( _WIN32 ) // or any other POSIX system + +#if defined( _WIN32 ) +#include +#if defined(_MSC_VER) +#include +#endif +#include "mingw_compat.h" +#include +#else // !_WIN32 +#include +#include +#include +#ifdef __linux__ +#include +#endif +#endif // !_WIN32 + +// declarations +#ifdef _WIN32 +void ThreadPool_WorkerFunc( void *p ); +#else +void *ThreadPool_WorkerFunc( void *p ); +#endif +void ThreadPool_Init(void); +void ThreadPool_Exit(void); + +#if defined (__MINGW32__) + // Mutex for implementing super heavy atomic operations if you don't have GCC or MSVC + CRITICAL_SECTION gAtomicLock; +#elif defined( __GNUC__ ) || defined( _MSC_VER) +#else + pthread_mutex_t gAtomicLock; +#endif + +// Atomic add operator with mem barrier. Mem barrier needed to protect state modified by the worker functions. +cl_int ThreadPool_AtomicAdd( volatile cl_int *a, cl_int b ) +{ +#if defined (__MINGW32__) + // No atomics on Mingw32 + EnterCriticalSection(&gAtomicLock); + cl_int old = *a; + *a = old + b; + LeaveCriticalSection(&gAtomicLock); + return old; +#elif defined( __GNUC__ ) + // GCC extension: http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html#Atomic-Builtins + return __sync_fetch_and_add( a, b ); + // do we need __sync_synchronize() here, too? GCC docs are unclear whether __sync_fetch_and_add does a synchronize +#elif defined( _MSC_VER ) + return (cl_int) _InterlockedExchangeAdd( (volatile LONG*) a, (LONG) b ); +#else + #warning Please add a atomic add implementation here, with memory barrier. Fallback code is slow. + if( pthread_mutex_lock(&gAtomicLock) ) + log_error( "Atomic operation failed. pthread_mutex_lock(&gAtomicLock) returned an error\n"); + cl_int old = *a; + *a = old + b; + if( pthread_mutex_unlock(&gAtomicLock) ) + log_error( "Failed to release gAtomicLock. Further atomic operations may deadlock!\n"); + return old; +#endif +} + +#if defined( _WIN32 ) +// Uncomment the following line if Windows XP support is not required. +// #define HAS_INIT_ONCE_EXECUTE_ONCE 1 + +#if defined(HAS_INIT_ONCE_EXECUTE_ONCE) +#define _INIT_ONCE INIT_ONCE +#define _PINIT_ONCE PINIT_ONCE +#define _InitOnceExecuteOnce InitOnceExecuteOnce +#else // !HAS_INIT_ONCE_EXECUTE_ONCE + +typedef volatile LONG _INIT_ONCE; +typedef _INIT_ONCE *_PINIT_ONCE; +typedef BOOL (CALLBACK *_PINIT_ONCE_FN)(_PINIT_ONCE, PVOID, PVOID *); + +#define _INIT_ONCE_UNINITIALIZED 0 +#define _INIT_ONCE_IN_PROGRESS 1 +#define _INIT_ONCE_DONE 2 + +static BOOL _InitOnceExecuteOnce( + _PINIT_ONCE InitOnce, + _PINIT_ONCE_FN InitFn, + PVOID Parameter, + LPVOID *Context +) +{ + while ( *InitOnce != _INIT_ONCE_DONE ) + { + if (*InitOnce != _INIT_ONCE_IN_PROGRESS && _InterlockedCompareExchange( InitOnce, _INIT_ONCE_IN_PROGRESS, _INIT_ONCE_UNINITIALIZED ) == _INIT_ONCE_UNINITIALIZED ) + { + InitFn( InitOnce, Parameter, Context ); + *InitOnce = _INIT_ONCE_DONE; + return TRUE; + } + Sleep( 1 ); + } + return TRUE; +} +#endif // !HAS_INIT_ONCE_EXECUTE_ONCE + +// Uncomment the following line if Windows XP support is not required. +// #define HAS_CONDITION_VARIABLE 1 + +#if defined(HAS_CONDITION_VARIABLE) +#define _CONDITION_VARIABLE CONDITION_VARIABLE +#define _InitializeConditionVariable InitializeConditionVariable +#define _SleepConditionVariableCS SleepConditionVariableCS +#define _WakeAllConditionVariable WakeAllConditionVariable +#else // !HAS_CONDITION_VARIABLE +typedef struct +{ + HANDLE mEvent; // Used to park the thread. + CRITICAL_SECTION mLock[1]; // Used to protect mWaiters, mGeneration and mReleaseCount. + volatile cl_int mWaiters; // Number of threads waiting on this cond var. + volatile cl_int mGeneration; // Wait generation count. + volatile cl_int mReleaseCount; // Number of releases to execute before reseting the event. +} _CONDITION_VARIABLE; + +typedef _CONDITION_VARIABLE *_PCONDITION_VARIABLE; + +static void _InitializeConditionVariable( _PCONDITION_VARIABLE cond_var ) +{ + cond_var->mEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); + InitializeCriticalSection( cond_var->mLock ); + cond_var->mWaiters = 0; + cond_var->mGeneration = 0; +#if !defined ( NDEBUG ) + cond_var->mReleaseCount = 0; +#endif // !NDEBUG +} + +static void _SleepConditionVariableCS( _PCONDITION_VARIABLE cond_var, PCRITICAL_SECTION cond_lock, DWORD ignored) +{ + EnterCriticalSection( cond_var->mLock ); + cl_int generation = cond_var->mGeneration; + ++cond_var->mWaiters; + LeaveCriticalSection( cond_var->mLock ); + LeaveCriticalSection( cond_lock ); + + while ( TRUE ) + { + WaitForSingleObject( cond_var->mEvent, INFINITE ); + EnterCriticalSection( cond_var->mLock ); + BOOL done = cond_var->mReleaseCount > 0 && cond_var->mGeneration != generation; + LeaveCriticalSection( cond_var->mLock ); + if ( done ) + { + break; + } + } + + EnterCriticalSection( cond_lock ); + EnterCriticalSection( cond_var->mLock ); + if ( --cond_var->mReleaseCount == 0 ) + { + ResetEvent( cond_var->mEvent ); + } + --cond_var->mWaiters; + LeaveCriticalSection( cond_var->mLock ); +} + +static void _WakeAllConditionVariable( _PCONDITION_VARIABLE cond_var ) +{ + EnterCriticalSection( cond_var->mLock ); + if (cond_var->mWaiters > 0 ) + { + ++cond_var->mGeneration; + cond_var->mReleaseCount = cond_var->mWaiters; + SetEvent( cond_var->mEvent ); + } + LeaveCriticalSection( cond_var->mLock ); +} +#endif // !HAS_CONDITION_VARIABLE +#endif // _WIN32 + +#define MAX_COUNT (1<<29) + +// Global state to coordinate whether the threads have been launched successfully or not +#if defined( _MSC_VER ) && (_WIN32_WINNT >= 0x600) +static _INIT_ONCE threadpool_init_control; +#elif defined (_WIN32) // MingW of XP +static int threadpool_init_control; +#else // Posix platforms +pthread_once_t threadpool_init_control = PTHREAD_ONCE_INIT; +#endif +cl_int threadPoolInitErr = -1; // set to CL_SUCCESS on successful thread launch + +// critical region lock around ThreadPool_Do. We can only run one ThreadPool_Do at a time, +// because we are too lazy to set up a queue here, and don't expect to need one. +#if defined( _WIN32 ) +CRITICAL_SECTION gThreadPoolLock[1]; +#else // !_WIN32 +pthread_mutex_t gThreadPoolLock; +#endif // !_WIN32 + +// Condition variable to park ThreadPool threads when not working +#if defined( _WIN32 ) +CRITICAL_SECTION cond_lock[1]; +_CONDITION_VARIABLE cond_var[1]; +#else // !_WIN32 +pthread_mutex_t cond_lock; +pthread_cond_t cond_var; +#endif // !_WIN32 +volatile cl_int gRunCount = 0; // Condition variable state. How many iterations on the function left to run. + // set to CL_INT_MAX to cause worker threads to exit. Note: this value might go negative. + +// State that only changes when the threadpool is not working. +volatile TPFuncPtr gFunc_ptr = NULL; +volatile void *gUserInfo = NULL; +volatile cl_int gJobCount = 0; + +// State that may change while the thread pool is working +volatile cl_int jobError = CL_SUCCESS; // err code return for the job as a whole + +// Condition variable to park caller while waiting +#if defined( _WIN32 ) +HANDLE caller_event; +#else // !_WIN32 +pthread_mutex_t caller_cond_lock; +pthread_cond_t caller_cond_var; +#endif // !_WIN32 +volatile cl_int gRunning = 0; // # of threads intended to be running. Running threads will decrement this as they discover they've run out of work to do. + +// The total number of threads launched. +volatile cl_int gThreadCount = 0; +#ifdef _WIN32 +void ThreadPool_WorkerFunc( void *p ) +#else +void *ThreadPool_WorkerFunc( void *p ) +#endif +{ + cl_uint threadID = ThreadPool_AtomicAdd( (volatile cl_int *) p, 1 ); + cl_int item = ThreadPool_AtomicAdd( &gRunCount, -1 ); +// log_info( "ThreadPool_WorkerFunc start: gRunning = %d\n", gRunning ); + + while( MAX_COUNT > item ) + { + cl_int err; + + // check for more work to do + if( 0 >= item ) + { +// log_info( "Thread %d has run out of work.\n", threadID ); + + // No work to do. Attempt to block waiting for work +#if defined( _WIN32 ) + EnterCriticalSection( cond_lock ); +#else // !_WIN32 + if((err = pthread_mutex_lock( &cond_lock) )) + { + log_error("Error %d from pthread_mutex_lock. Worker %d unable to block waiting for work. ThreadPool_WorkerFunc failed.\n", err, threadID ); + goto exit; + } +#endif // !_WIN32 + + cl_int remaining = ThreadPool_AtomicAdd( &gRunning, -1 ); +// log_info( "ThreadPool_WorkerFunc: gRunning = %d\n", remaining - 1 ); + if( 1 == remaining ) + { // last thread out signal the main thread to wake up +#if defined( _WIN32 ) + SetEvent( caller_event ); +#else // !_WIN32 + if((err = pthread_mutex_lock( &caller_cond_lock) )) + { + log_error("Error %d from pthread_mutex_lock. Unable to wake caller.\n", err ); + goto exit; + } + if( (err = pthread_cond_broadcast( &caller_cond_var ))) + { + log_error("Error %d from pthread_cond_broadcast. Unable to wake up main thread. ThreadPool_WorkerFunc failed.\n", err ); + goto exit; + } + if((err = pthread_mutex_unlock( &caller_cond_lock) )) + { + log_error("Error %d from pthread_mutex_lock. Unable to wake caller.\n", err ); + goto exit; + } +#endif // !_WIN32 + } + + // loop in case we are woken only to discover that some other thread already did all the work + while( 0 >= item ) + { +#if defined( _WIN32 ) + _SleepConditionVariableCS( cond_var, cond_lock, INFINITE ); +#else // !_WIN32 + if((err = pthread_cond_wait( &cond_var, &cond_lock) )) + { + log_error("Error %d from pthread_cond_wait. Unable to block for waiting for work. ThreadPool_WorkerFunc failed.\n", err ); + pthread_mutex_unlock( &cond_lock); + goto exit; + } +#endif // !_WIN32 + + // try again to get a valid item id + item = ThreadPool_AtomicAdd( &gRunCount, -1 ); + if( MAX_COUNT <= item ) // exit if we are done + { +#if defined( _WIN32 ) + LeaveCriticalSection( cond_lock ); +#else // !_WIN32 + pthread_mutex_unlock( &cond_lock); +#endif // !_WIN32 + goto exit; + } + } + + ThreadPool_AtomicAdd( &gRunning, 1 ); +// log_info( "Thread %d has found work.\n", threadID); + +#if defined( _WIN32 ) + LeaveCriticalSection( cond_lock ); +#else // !_WIN32 + if((err = pthread_mutex_unlock( &cond_lock) )) + { + log_error("Error %d from pthread_mutex_unlock. Unable to block for waiting for work. ThreadPool_WorkerFunc failed.\n", err ); + goto exit; + } +#endif // !_WIN32 + + } + + // we have a valid item, so do the work + if( CL_SUCCESS == jobError ) // but only if we haven't already encountered an error + { +// log_info( "Thread %d doing job %d\n", threadID, item - 1); + +#if defined(__APPLE__) && defined(__arm__) + // On most platforms which support denorm, default is FTZ off. However, + // on some hardware where the reference is computed, default might be flush denorms to zero e.g. arm. + // This creates issues in result verification. Since spec allows the implementation to either flush or + // not flush denorms to zero, an implementation may choose not be flush i.e. return denorm result whereas + // reference result may be zero (flushed denorm). Hence we need to disable denorm flushing on host side + // where reference is being computed to make sure we get non-flushed reference result. If implementation + // returns flushed result, we correctly take care of that in verification code. + FPU_mode_type oldMode; + DisableFTZ( &oldMode ); +#endif + + // Call the user's function with this item ID + err = gFunc_ptr( item - 1, threadID, (void*) gUserInfo ); +#if defined(__APPLE__) && defined(__arm__) + // Restore FP state + RestoreFPState( &oldMode ); +#endif + + if( err ) + { +#if (__MINGW32__) + EnterCriticalSection(&gAtomicLock); + if( jobError == CL_SUCCESS ); + jobError = err; + gRunCount = 0; + LeaveCriticalSection(&gAtomicLock); +#elif defined( __GNUC__ ) + // GCC extension: http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html#Atomic-Builtins + // set the new error if we are the first one there. + __sync_val_compare_and_swap( &jobError, CL_SUCCESS, err ); + + // drop run count to 0 + gRunCount = 0; + __sync_synchronize(); +#elif defined( _MSC_VER ) + // set the new error if we are the first one there. + _InterlockedCompareExchange( (volatile LONG*) &jobError, err, CL_SUCCESS ); + + // drop run count to 0 + gRunCount = 0; + _mm_mfence(); +#else + if( pthread_mutex_lock(&gAtomicLock) ) + log_error( "Atomic operation failed. pthread_mutex_lock(&gAtomicLock) returned an error\n"); + if( jobError == CL_SUCCESS ); + jobError = err; + gRunCount = 0; + if( pthread_mutex_unlock(&gAtomicLock) ) + log_error( "Failed to release gAtomicLock. Further atomic operations may deadlock\n"); +#endif + } + } + + // get the next item + item = ThreadPool_AtomicAdd( &gRunCount, -1 ); + } + +exit: + log_info( "ThreadPool: thread %d exiting.\n", threadID ); + ThreadPool_AtomicAdd( &gThreadCount, -1 ); +#if !defined(_WIN32) + return NULL; +#endif +} + +// SetThreadCount() may be used to artifically set the number of worker threads +// If the value is 0 (the default) the number of threads will be determined based on +// the number of CPU cores. If it is a unicore machine, then 2 will be used, so +// that we still get some testing for thread safety. +// +// If count < 2 or the CL_TEST_SINGLE_THREADED environment variable is set then the +// code will run single threaded, but will report an error to indicate that the test +// is invalid. This option is intended for debugging purposes only. It is suggested +// as a convention that test apps set the thread count to 1 in response to the -m flag. +// +// SetThreadCount() must be called before the first call to GetThreadCount() or ThreadPool_Do(), +// otherwise the behavior is indefined. +void SetThreadCount( int count ) +{ + if( threadPoolInitErr == CL_SUCCESS ) + { + log_error( "Error: It is illegal to set the thread count after the first call to ThreadPool_Do or GetThreadCount\n" ); + abort(); + } + + gThreadCount = count; +} + +void ThreadPool_Init(void) +{ + cl_int i; + int err; + volatile cl_uint threadID = 0; + + // Check for manual override of multithreading code. We add this for better debuggability. + if( getenv( "CL_TEST_SINGLE_THREADED" ) ) + { + gThreadCount = 1; + return; + } + + // Figure out how many threads to run -- check first for non-zero to give the implementation the chance + if( 0 == gThreadCount ) + { +#if defined(_MSC_VER) || defined (__MINGW64__) + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL; + DWORD length = 0; + + GetLogicalProcessorInformation( NULL, &length ); + buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION) malloc( length ); + if( buffer != NULL ) + { + if ( GetLogicalProcessorInformation( buffer, &length ) == TRUE ) + { + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = buffer; + while( ptr < &buffer[ length / sizeof( SYSTEM_LOGICAL_PROCESSOR_INFORMATION ) ] ) + { + if( ptr->Relationship == RelationProcessorCore ) + { + // Count the number of bits in ProcessorMask (number of logical cores) + ULONG mask = ptr->ProcessorMask; + while( mask ) + { + ++gThreadCount; + mask &= mask - 1; // Remove 1 bit at a time + } + } + ++ptr; + } + } + free(buffer); + } +#elif defined (__MINGW32__) + { + #warning How about this, instead of hard coding it to 2? + SYSTEM_INFO sysinfo; + GetSystemInfo( &sysinfo ); + gThreadCount = sysinfo.dwNumberOfProcessors; + } +#elif defined (__linux__) && !defined(__ANDROID__) + cpu_set_t affinity; + if ( 0 == sched_getaffinity(0, sizeof(cpu_set_t), &affinity) ) + { +#if !(defined(CPU_COUNT)) + gThreadCount = 1; +#else + gThreadCount = CPU_COUNT(&affinity); +#endif + } + else + { + gThreadCount = (cl_int) sysconf(_SC_NPROCESSORS_CONF); // Hopefully your system returns logical cpus here, as does MacOS X + } +#else // !_WIN32 + gThreadCount = (cl_int) sysconf(_SC_NPROCESSORS_CONF); // Hopefully your system returns logical cpus here, as does MacOS X +#endif // !_WIN32 + + // Multithreaded tests are required to run multithreaded even on unicore systems so as to test thread safety + if( 1 == gThreadCount ) + gThreadCount = 2; + } + + // When working in 32 bit limit the thread number to 12 + // This fix was made due to memory issues in integer_ops test + // When running integer_ops, the test opens as many threads as the + // machine has and each thread allocates a fixed amount of memory + // When running this test on dual socket machine in 32-bit, the + // process memory is not sufficient and the test fails + #if defined(_WIN32) && !defined(_M_X64) + if (gThreadCount > 12) { + gThreadCount = 12; + } + #endif + + //Allow the app to set thread count to <0 for debugging purposes. This will cause the test to run single threaded. + if( gThreadCount < 2 ) + { + log_error( "ERROR: Running single threaded because thread count < 2. \n*** TEST IS INVALID! ***\n"); + gThreadCount = 1; + return; + } + +#if defined( _WIN32 ) + InitializeCriticalSection( gThreadPoolLock ); + InitializeCriticalSection( cond_lock ); + _InitializeConditionVariable( cond_var ); + caller_event = CreateEvent( NULL, FALSE, FALSE, NULL ); +#elif defined (__GNUC__) + // Dont rely on PTHREAD_MUTEX_INITIALIZER for intialization of a mutex since it might cause problem + // with some flavors of gcc compilers. + pthread_cond_init(&cond_var, NULL); + pthread_mutex_init(&cond_lock ,NULL); + pthread_cond_init(&caller_cond_var, NULL); + pthread_mutex_init(&caller_cond_lock, NULL); + pthread_mutex_init(&gThreadPoolLock, NULL); +#endif + +#if !(defined(__GNUC__) || defined(_MSC_VER) || defined(__MINGW32__)) + pthread_mutex_initialize(gAtomicLock); +#elif defined (__MINGW32__) + InitializeCriticalSection(&gAtomicLock); +#endif + // Make sure the last thread done in the work pool doesn't signal us to wake before we get to the point where we are supposed to wait + // That would cause a deadlock. +#if !defined( _WIN32 ) + if((err = pthread_mutex_lock( &caller_cond_lock) )) + { + log_error("Error %d from pthread_mutex_lock. Unable to block for work to finish. ThreadPool_Init failed.\n", err ); + gThreadCount = 1; + return; + } +#endif // !_WIN32 + + gRunning = gThreadCount; + // init threads + for( i = 0; i < gThreadCount; i++ ) + { +#if defined( _WIN32 ) + uintptr_t handle = _beginthread(ThreadPool_WorkerFunc, 0, (void*) &threadID); + err = ( handle == 0 ); +#else // !_WIN32 + pthread_t tid = 0; + err = pthread_create( &tid, NULL, ThreadPool_WorkerFunc, (void*) &threadID ); +#endif // !_WIN32 + if( err ) + { + log_error( "Error %d launching thread %d\n", err, i ); + threadPoolInitErr = err; + gThreadCount = i; + break; + } + } + + atexit( ThreadPool_Exit ); + +// block until they are done launching. + do + { +#if defined( _WIN32 ) + WaitForSingleObject( caller_event, INFINITE ); +#else // !_WIN32 + if((err = pthread_cond_wait( &caller_cond_var, &caller_cond_lock) )) + { + log_error("Error %d from pthread_cond_wait. Unable to block for work to finish. ThreadPool_Init failed.\n", err ); + pthread_mutex_unlock( &caller_cond_lock); + return; + } +#endif // !_WIN32 + } + while( gRunCount != -gThreadCount ); +#if !defined( _WIN32 ) + if((err = pthread_mutex_unlock( &caller_cond_lock) )) + { + log_error("Error %d from pthread_mutex_unlock. Unable to block for work to finish. ThreadPool_Init failed.\n", err ); + return; + } +#endif // !_WIN32 + + threadPoolInitErr = CL_SUCCESS; +} + +#if defined(_MSC_VER) +static BOOL CALLBACK _ThreadPool_Init(_PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContex) +{ + ThreadPool_Init(); + return TRUE; +} +#endif + +void ThreadPool_Exit(void) +{ + int err, count; + gRunCount = CL_INT_MAX; + +#if defined( __GNUC__ ) + // GCC extension: http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html#Atomic-Builtins + __sync_synchronize(); +#elif defined( _MSC_VER ) + _mm_mfence(); +#else + #warning If this is a weakly ordered memory system, please add a memory barrier here to force this and everything else to memory before we proceed +#endif + + // spin waiting for threads to die + for (count = 0; 0 != gThreadCount && count < 1000; count++) + { +#if defined( _WIN32 ) + _WakeAllConditionVariable( cond_var ); + Sleep(1); +#else // !_WIN32 + if( (err = pthread_cond_broadcast( &cond_var ))) + { + log_error("Error %d from pthread_cond_broadcast. Unable to wake up work threads. ThreadPool_Exit failed.\n", err ); + break; + } + usleep(1000); +#endif // !_WIN32 + } + + if( gThreadCount ) + log_error( "Error: Thread pool timed out after 1 second with %d threads still active.\n", gThreadCount ); + else + log_info( "Thread pool exited in a orderly fashion.\n" ); +} + + +// Blocking API that farms out count jobs to a thread pool. +// It may return with some work undone if func_ptr() returns a non-zero +// result. +// +// This function obviously has its shortcommings. Only one call to ThreadPool_Do +// can be running at a time. It is not intended for general purpose use. +// If clEnqueueNativeKernelFn, out of order queues and a CL_DEVICE_TYPE_CPU were +// all available then it would make more sense to use those features. +cl_int ThreadPool_Do( TPFuncPtr func_ptr, + cl_uint count, + void *userInfo ) +{ + cl_int newErr; + cl_int err = 0; + // Lazily set up our threads +#if defined(_MSC_VER) && (_WIN32_WINNT >= 0x600) + err = !_InitOnceExecuteOnce( &threadpool_init_control, _ThreadPool_Init, NULL, NULL ); +#elif defined (_WIN32) + if (threadpool_init_control == 0) { + #warning This is buggy and race prone. Find a better way. + ThreadPool_Init(); + threadpool_init_control = 1; + } +#else //posix platform + err = pthread_once( &threadpool_init_control, ThreadPool_Init ); + if( err ) + { + log_error("Error %d from pthread_once. Unable to init threads. ThreadPool_Do failed.\n", err ); + return err; + } +#endif + // Single threaded code to handle case where threadpool wasn't allocated or was disabled by environment variable + if( threadPoolInitErr ) + { + cl_uint currentJob = 0; + cl_int result = CL_SUCCESS; + +#if defined(__APPLE__) && defined(__arm__) + // On most platforms which support denorm, default is FTZ off. However, + // on some hardware where the reference is computed, default might be flush denorms to zero e.g. arm. + // This creates issues in result verification. Since spec allows the implementation to either flush or + // not flush denorms to zero, an implementation may choose not be flush i.e. return denorm result whereas + // reference result may be zero (flushed denorm). Hence we need to disable denorm flushing on host side + // where reference is being computed to make sure we get non-flushed reference result. If implementation + // returns flushed result, we correctly take care of that in verification code. + FPU_mode_type oldMode; + DisableFTZ( &oldMode ); +#endif + for( currentJob = 0; currentJob < count; currentJob++ ) + if((result = func_ptr( currentJob, 0, userInfo ))) + { +#if defined(__APPLE__) && defined(__arm__) + // Restore FP state before leaving + RestoreFPState( &oldMode ); +#endif + return result; + } + +#if defined(__APPLE__) && defined(__arm__) + // Restore FP state before leaving + RestoreFPState( &oldMode ); +#endif + + return CL_SUCCESS; + } + + if( count >= MAX_COUNT ) + { + log_error("Error: ThreadPool_Do count %d >= max threadpool count of %d\n", count, MAX_COUNT ); + return -1; + } + + // Enter critical region +#if defined( _WIN32 ) + EnterCriticalSection( gThreadPoolLock ); +#else // !_WIN32 + if( (err = pthread_mutex_lock( &gThreadPoolLock ))) + { + switch (err) + { + case EDEADLK: + log_error("Error EDEADLK returned in ThreadPool_Do(). ThreadPool_Do is not designed to work recursively!\n" ); + break; + case EINVAL: + log_error("Error EINVAL returned in ThreadPool_Do(). How did we end up with an invalid gThreadPoolLock?\n" ); + break; + default: + break; + } + return err; + } +#endif // !_WIN32 + + // Start modifying the job state observable by worker threads +#if defined( _WIN32 ) + EnterCriticalSection( cond_lock ); +#else // !_WIN32 + if((err = pthread_mutex_lock( &cond_lock) )) + { + log_error("Error %d from pthread_mutex_lock. Unable to wake up work threads. ThreadPool_Do failed.\n", err ); + goto exit; + } +#endif // !_WIN32 + + // Make sure the last thread done in the work pool doesn't signal us to wake before we get to the point where we are supposed to wait + // That would cause a deadlock. +#if !defined( _WIN32 ) + if((err = pthread_mutex_lock( &caller_cond_lock) )) + { + log_error("Error %d from pthread_mutex_lock. Unable to block for work to finish. ThreadPool_Do failed.\n", err ); + goto exit; + } +#endif // !_WIN32 + + // Prime the worker threads to get going + jobError = CL_SUCCESS; + gRunCount = gJobCount = count; + gFunc_ptr = func_ptr; + gUserInfo = userInfo; + +#if defined( _WIN32 ) + ResetEvent(caller_event); + _WakeAllConditionVariable( cond_var ); + LeaveCriticalSection( cond_lock ); +#else // !_WIN32 + if( (err = pthread_cond_broadcast( &cond_var ))) + { + log_error("Error %d from pthread_cond_broadcast. Unable to wake up work threads. ThreadPool_Do failed.\n", err ); + goto exit; + } + if((err = pthread_mutex_unlock( &cond_lock) )) + { + log_error("Error %d from pthread_mutex_unlock. Unable to wake up work threads. ThreadPool_Do failed.\n", err ); + goto exit; + } +#endif // !_WIN32 + +// block until they are done. It would be slightly more efficient to do some of the work here though. + do + { +#if defined( _WIN32 ) + WaitForSingleObject( caller_event, INFINITE ); +#else // !_WIN32 + if((err = pthread_cond_wait( &caller_cond_var, &caller_cond_lock) )) + { + log_error("Error %d from pthread_cond_wait. Unable to block for work to finish. ThreadPool_Do failed.\n", err ); + pthread_mutex_unlock( &caller_cond_lock); + goto exit; + } +#endif // !_WIN32 + } + while( gRunning ); +#if !defined(_WIN32) + if((err = pthread_mutex_unlock( &caller_cond_lock) )) + { + log_error("Error %d from pthread_mutex_unlock. Unable to block for work to finish. ThreadPool_Do failed.\n", err ); + goto exit; + } +#endif // !_WIN32 + + err = jobError; + +exit: + // exit critical region +#if defined( _WIN32 ) + LeaveCriticalSection( gThreadPoolLock ); +#else // !_WIN32 + newErr = pthread_mutex_unlock( &gThreadPoolLock ); + if( newErr) + { + log_error("Error %d from pthread_mutex_unlock. Unable to exit critical region. ThreadPool_Do failed.\n", newErr ); + return err; + } +#endif // !_WIN32 + + return err; +} + +cl_uint GetThreadCount( void ) +{ + // Lazily set up our threads +#if defined(_MSC_VER) && (_WIN32_WINNT >= 0x600) + cl_int err = !_InitOnceExecuteOnce( &threadpool_init_control, _ThreadPool_Init, NULL, NULL ); +#elif defined (_WIN32) + if (threadpool_init_control == 0) { + #warning This is buggy and race prone. Find a better way. + ThreadPool_Init(); + threadpool_init_control = 1; + } +#else + cl_int err = pthread_once( &threadpool_init_control, ThreadPool_Init ); + if( err ) + { + log_error("Error %d from pthread_once. Unable to init threads. ThreadPool_Do failed.\n", err ); + return err; + } +#endif // !_WIN32 + + if( gThreadCount < 1 ) + return 1; + + return gThreadCount; +} + +#else + +#ifndef MY_OS_REALLY_REALLY_DOESNT_SUPPORT_THREADS + #error ThreadPool implementation has not been multithreaded for this operating system. You must multithread this section. +#endif +// +// We require multithreading in parts of the test as a means of simultaneously testing reentrancy requirements +// of OpenCL API, while also checking +// +// A sample single threaded implementation follows, for documentation / bootstrapping purposes. +// It is not okay to use this for conformance testing!!! +// +// Exception: If your operating system does not support multithreaded execution of any kind, then you may use this code. +// + +cl_int ThreadPool_AtomicAdd( volatile cl_int *a, cl_int b ) +{ + cl_uint r = *a; + + // since this fallback code path is not multithreaded, we just do a regular add here + // If your operating system supports memory-barrier-atomics, use those here + *a = r + b; + + return r; +} + +// Blocking API that farms out count jobs to a thread pool. +// It may return with some work undone if func_ptr() returns a non-zero +// result. +cl_int ThreadPool_Do( TPFuncPtr func_ptr, + cl_uint count, + void *userInfo ) +{ + cl_uint currentJob = 0; + cl_int result = CL_SUCCESS; + +#ifndef MY_OS_REALLY_REALLY_DOESNT_SUPPORT_THREADS + // THIS FUNCTION IS NOT INTENDED FOR USE!! + log_error( "ERROR: Test must be multithreaded!\n" ); + exit(-1); +#else + static int spewCount = 0; + + if( 0 == spewCount ) + { + log_info( "\nWARNING: The operating system is claimed not to support threads of any sort. Running single threaded.\n" ); + spewCount = 1; + } +#endif + +// The multithreaded code should mimic this behavior: + for( currentJob = 0; currentJob < count; currentJob++ ) + if((result = func_ptr( currentJob, 0, userInfo ))) + return result; + + return CL_SUCCESS; +} + +cl_uint GetThreadCount( void ) +{ + return 1; +} + +void SetThreadCount( int count ) +{ + if( count > 1 ) + log_info( "WARNING: SetThreadCount(%d) ignored\n", count ); +} + +#endif diff --git a/test_common/harness/ThreadPool.h b/test_common/harness/ThreadPool.h new file mode 100644 index 00000000..7c392306 --- /dev/null +++ b/test_common/harness/ThreadPool.h @@ -0,0 +1,76 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef THREAD_POOL_H +#define THREAD_POOL_H + +#if defined( __APPLE__ ) + #include +#else + #include +#endif + +#if defined(__cplusplus) + extern "C" { +#endif + +// +// An atomic add operator +cl_int ThreadPool_AtomicAdd( volatile cl_int *a, cl_int b ); // returns old value + +// Your function prototype +// +// A function pointer to the function you want to execute in a multithreaded context. No +// synchronization primitives are provided, other than the atomic add above. You may not +// call ThreadPool_Do from your function. ThreadPool_AtomicAdd() and GetThreadCount() should +// work, however. +// +// job ids and thread ids are 0 based. If number of jobs or threads was 8, they will numbered be 0 through 7. +// Note that while every job will be run, it is not guaranteed that every thread will wake up before +// the work is done. +typedef cl_int (*TPFuncPtr)( cl_uint /*job_id*/, cl_uint /* thread_id */, void *userInfo ); + +// returns first non-zero result from func_ptr, or CL_SUCCESS if all are zero. +// Some workitems may not run if a non-zero result is returned from func_ptr(). +// This function may not be called from a TPFuncPtr. +cl_int ThreadPool_Do( TPFuncPtr func_ptr, + cl_uint count, + void *userInfo ); + +// Returns the number of worker threads that underlie the threadpool. The value passed +// as the TPFuncPtrs thread_id will be between 0 and this value less one, inclusive. +// This is safe to call from a TPFuncPtr. +cl_uint GetThreadCount( void ); + +// SetThreadCount() may be used to artifically set the number of worker threads +// If the value is 0 (the default) the number of threads will be determined based on +// the number of CPU cores. If it is a unicore machine, then 2 will be used, so +// that we still get some testing for thread safety. +// +// If count < 2 or the CL_TEST_SINGLE_THREADED environment variable is set then the +// code will run single threaded, but will report an error to indicate that the test +// is invalid. This option is intended for debugging purposes only. It is suggested +// as a convention that test apps set the thread count to 1 in response to the -m flag. +// +// SetThreadCount() must be called before the first call to GetThreadCount() or ThreadPool_Do(), +// otherwise the behavior is indefined. It may not be called from a TPFuncPtr. +void SetThreadCount( int count ); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* THREAD_POOL_H */ diff --git a/test_common/harness/clImageHelper.h b/test_common/harness/clImageHelper.h new file mode 100644 index 00000000..b09b7bd4 --- /dev/null +++ b/test_common/harness/clImageHelper.h @@ -0,0 +1,290 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef test_conformance_clImageHelper_h +#define test_conformance_clImageHelper_h + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include "errorHelpers.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + // helper function to replace clCreateImage2D , to make the existing code use + // the functions of version 1.2 and veriosn 1.1 respectively + + static inline cl_mem create_image_2d (cl_context context, + cl_mem_flags flags, + const cl_image_format *image_format, + size_t image_width, + size_t image_height, + size_t image_row_pitch, + void *host_ptr, + cl_int *errcode_ret) + { + cl_mem mImage = NULL; + +#ifdef CL_VERSION_1_2 + cl_image_desc image_desc_dest; + image_desc_dest.image_type = CL_MEM_OBJECT_IMAGE2D;; + image_desc_dest.image_width = image_width; + image_desc_dest.image_height = image_height; + image_desc_dest.image_depth= 0;// not usedfor 2d + image_desc_dest.image_array_size = 0;// not used for 2d + image_desc_dest.image_row_pitch = image_row_pitch; + image_desc_dest.image_slice_pitch = 0; + image_desc_dest.num_mip_levels = 0; + image_desc_dest.num_samples = 0; + image_desc_dest.mem_object = NULL;// no image type of CL_MEM_OBJECT_IMAGE1D_BUFFER in CL_VERSION_1_1, so always is NULL + mImage = clCreateImage( context, flags, image_format, &image_desc_dest, host_ptr, errcode_ret ); + if (errcode_ret && (*errcode_ret)) { + // Log an info message and rely on the calling function to produce an error + // if necessary. + log_info("clCreateImage failed (%d)\n", *errcode_ret); + } + +#else + mImage = clCreateImage2D( context, flags, image_format, image_width, image_height, image_row_pitch, host_ptr, errcode_ret ); + if (errcode_ret && (*errcode_ret)) { + // Log an info message and rely on the calling function to produce an error + // if necessary. + log_info("clCreateImage2D failed (%d)\n", *errcode_ret); + } +#endif + + return mImage; + } + + // helper function to replace clCreateImage2D , to make the existing code use + // the functions of version 1.2 and veriosn 1.1 respectively + + static inline cl_mem create_image_2d_buffer (cl_context context, + cl_mem_flags flags, + const cl_image_format *image_format, + size_t image_width, + size_t image_height, + size_t image_row_pitch, + cl_mem buffer, + cl_int *errcode_ret) + { + cl_mem mImage = NULL; + + cl_image_desc image_desc_dest; + image_desc_dest.image_type = CL_MEM_OBJECT_IMAGE2D;; + image_desc_dest.image_width = image_width; + image_desc_dest.image_height = image_height; + image_desc_dest.image_depth= 0;// not usedfor 2d + image_desc_dest.image_array_size = 0;// not used for 2d + image_desc_dest.image_row_pitch = image_row_pitch; + image_desc_dest.image_slice_pitch = 0; + image_desc_dest.num_mip_levels = 0; + image_desc_dest.num_samples = 0; + image_desc_dest.mem_object = buffer; + mImage = clCreateImage( context, flags, image_format, &image_desc_dest, NULL, errcode_ret ); + if (errcode_ret && (*errcode_ret)) { + // Log an info message and rely on the calling function to produce an error + // if necessary. + log_info("clCreateImage failed (%d)\n", *errcode_ret); + } + + return mImage; + } + + + + static inline cl_mem create_image_3d (cl_context context, + cl_mem_flags flags, + const cl_image_format *image_format, + size_t image_width, + size_t image_height, + size_t image_depth, + size_t image_row_pitch, + size_t image_slice_pitch, + void *host_ptr, + cl_int *errcode_ret) + { + cl_mem mImage; + +#ifdef CL_VERSION_1_2 + cl_image_desc image_desc; + image_desc.image_type = CL_MEM_OBJECT_IMAGE3D; + image_desc.image_width = image_width; + image_desc.image_height = image_height; + image_desc.image_depth = image_depth; + image_desc.image_array_size = 0;// not used for one image + image_desc.image_row_pitch = image_row_pitch; + image_desc.image_slice_pitch = image_slice_pitch; + image_desc.num_mip_levels = 0; + image_desc.num_samples = 0; + image_desc.mem_object = NULL; // no image type of CL_MEM_OBJECT_IMAGE1D_BUFFER in CL_VERSION_1_1, so always is NULL + mImage = clCreateImage( context, + flags, + image_format, + &image_desc, + host_ptr, + errcode_ret ); + if (errcode_ret && (*errcode_ret)) { + // Log an info message and rely on the calling function to produce an error + // if necessary. + log_info("clCreateImage failed (%d)\n", *errcode_ret); + } + +#else + mImage = clCreateImage3D( context, + flags, image_format, + image_width, + image_height, + image_depth, + image_row_pitch, + image_slice_pitch, + host_ptr, + errcode_ret ); + if (errcode_ret && (*errcode_ret)) { + // Log an info message and rely on the calling function to produce an error + // if necessary. + log_info("clCreateImage3D failed (%d)\n", *errcode_ret); + } +#endif + + return mImage; + } + + static inline cl_mem create_image_2d_array (cl_context context, + cl_mem_flags flags, + const cl_image_format *image_format, + size_t image_width, + size_t image_height, + size_t image_array_size, + size_t image_row_pitch, + size_t image_slice_pitch, + void *host_ptr, + cl_int *errcode_ret) + { + cl_mem mImage; + + cl_image_desc image_desc; + image_desc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + image_desc.image_width = image_width; + image_desc.image_height = image_height; + image_desc.image_depth = 1; + image_desc.image_array_size = image_array_size; + image_desc.image_row_pitch = image_row_pitch; + image_desc.image_slice_pitch = image_slice_pitch; + image_desc.num_mip_levels = 0; + image_desc.num_samples = 0; + image_desc.mem_object = NULL; + mImage = clCreateImage( context, + flags, + image_format, + &image_desc, + host_ptr, + errcode_ret ); + if (errcode_ret && (*errcode_ret)) { + // Log an info message and rely on the calling function to produce an error + // if necessary. + log_info("clCreateImage failed (%d)\n", *errcode_ret); + } + + return mImage; + } + + static inline cl_mem create_image_1d_array (cl_context context, + cl_mem_flags flags, + const cl_image_format *image_format, + size_t image_width, + size_t image_array_size, + size_t image_row_pitch, + size_t image_slice_pitch, + void *host_ptr, + cl_int *errcode_ret) + { + cl_mem mImage; + + cl_image_desc image_desc; + image_desc.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + image_desc.image_width = image_width; + image_desc.image_height = 1; + image_desc.image_depth = 1; + image_desc.image_array_size = image_array_size; + image_desc.image_row_pitch = image_row_pitch; + image_desc.image_slice_pitch = image_slice_pitch; + image_desc.num_mip_levels = 0; + image_desc.num_samples = 0; + image_desc.mem_object = NULL; + mImage = clCreateImage( context, + flags, + image_format, + &image_desc, + host_ptr, + errcode_ret ); + if (errcode_ret && (*errcode_ret)) { + // Log an info message and rely on the calling function to produce an error + // if necessary. + log_info("clCreateImage failed (%d)\n", *errcode_ret); + } + + return mImage; + } + + static inline cl_mem create_image_1d (cl_context context, + cl_mem_flags flags, + const cl_image_format *image_format, + size_t image_width, + size_t image_row_pitch, + void *host_ptr, + cl_mem buffer, + cl_int *errcode_ret) + { + cl_mem mImage; + + cl_image_desc image_desc; + image_desc.image_type = buffer ? CL_MEM_OBJECT_IMAGE1D_BUFFER: CL_MEM_OBJECT_IMAGE1D; + image_desc.image_width = image_width; + image_desc.image_height = 1; + image_desc.image_depth = 1; + image_desc.image_row_pitch = image_row_pitch; + image_desc.image_slice_pitch = 0; + image_desc.num_mip_levels = 0; + image_desc.num_samples = 0; + image_desc.mem_object = buffer; + mImage = clCreateImage( context, + flags, + image_format, + &image_desc, + host_ptr, + errcode_ret ); + if (errcode_ret && (*errcode_ret)) { + // Log an info message and rely on the calling function to produce an error + // if necessary. + log_info("clCreateImage failed (%d)\n", *errcode_ret); + } + + return mImage; + } + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test_common/harness/compat.h b/test_common/harness/compat.h new file mode 100644 index 00000000..23445c8e --- /dev/null +++ b/test_common/harness/compat.h @@ -0,0 +1,388 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _COMPAT_H_ +#define _COMPAT_H_ + +#if defined(_WIN32) && defined (_MSC_VER) +#include +#endif + +#ifdef __cplusplus + #define EXTERN_C extern "C" +#else + #define EXTERN_C +#endif + + +// +// stdlib.h +// + +#include // On Windows, _MAX_PATH defined there. + +// llabs appeared in MS C v16 (VS 10/2010). +#if defined( _MSC_VER ) && _MSC_VER <= 1500 + EXTERN_C inline long long llabs(long long __x) { return __x >= 0 ? __x : -__x; } +#endif + + +// +// stdbool.h +// + +// stdbool.h appeared in MS C v18 (VS 12/2013). +#if defined( _MSC_VER ) && MSC_VER <= 1700 +#if !defined(__cplusplus) +typedef char bool; + #define true 1 + #define false 0 + #endif +#else + #include +#endif + + + +// +// stdint.h +// + +// stdint.h appeared in MS C v16 (VS 10/2010) and Intel C v12. +#if defined( _MSC_VER ) && ( ! defined( __INTEL_COMPILER ) && _MSC_VER <= 1500 || defined( __INTEL_COMPILER ) && __INTEL_COMPILER < 1200 ) +typedef unsigned char uint8_t; +typedef char int8_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned long long uint64_t; +typedef long long int64_t; +#else +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif + #include +#endif + + + +// +// float.h +// + +#include + + + +// +// fenv.h +// + +// fenv.h appeared in MS C v18 (VS 12/2013). +#if defined( _MSC_VER ) && _MSC_VER <= 1700 && ! defined( __INTEL_COMPILER ) + // reimplement fenv.h because windows doesn't have it + #define FE_INEXACT 0x0020 + #define FE_UNDERFLOW 0x0010 + #define FE_OVERFLOW 0x0008 + #define FE_DIVBYZERO 0x0004 + #define FE_INVALID 0x0001 + #define FE_ALL_EXCEPT 0x003D + int fetestexcept(int excepts); + int feclearexcept(int excepts); +#else + #include +#endif + + +// +// math.h +// + +#if defined( __INTEL_COMPILER ) + #include +#else + #include +#endif + +#if defined( _MSC_VER ) + + #ifdef __cplusplus + extern "C" { + #endif + +#ifndef M_PI + #define M_PI 3.14159265358979323846264338327950288 +#endif + + #if ! defined( __INTEL_COMPILER ) + + #ifndef NAN + #define NAN (INFINITY - INFINITY) + #endif + #ifndef HUGE_VALF + #define HUGE_VALF (float)HUGE_VAL + #endif + #ifndef INFINITY + #define INFINITY (FLT_MAX + FLT_MAX) + #endif + #ifndef isfinite + #define isfinite(x) _finite(x) + #endif + #ifndef isnan +#define isnan( x ) ((x) != (x)) + #endif + #ifndef isinf +#define isinf( _x) ((_x) == INFINITY || (_x) == -INFINITY) + #endif + +double rint( double x); +float rintf( float x); +long double rintl( long double x); + +float cbrtf( float ); +double cbrt( double ); + +int ilogb( double x); +int ilogbf (float x); +int ilogbl(long double x); + +double fmax(double x, double y); +double fmin(double x, double y); +float fmaxf( float x, float y ); +float fminf(float x, float y); + +double log2(double x); +long double log2l(long double x); + +double exp2(double x); +long double exp2l(long double x); + +double fdim(double x, double y); +float fdimf(float x, float y); +long double fdiml(long double x, long double y); + +double remquo( double x, double y, int *quo); +float remquof( float x, float y, int *quo); +long double remquol( long double x, long double y, int *quo); + +long double scalblnl(long double x, long n); + +float hypotf(float x, float y); +long double hypotl(long double x, long double y) ; +double lgamma(double x); +float lgammaf(float x); + +double trunc(double x); +float truncf(float x); + +double log1p(double x); +float log1pf(float x); +long double log1pl(long double x); + +double copysign(double x, double y); +float copysignf(float x, float y); +long double copysignl(long double x, long double y); + +long lround(double x); +long lroundf(float x); +//long lroundl(long double x) + +double round(double x); +float roundf(float x); +long double roundl(long double x); + + int cf_signbit(double x); + int cf_signbitf(float x); + +// Added in _MSC_VER == 1800 (Visual Studio 2013) +#if _MSC_VER < 1800 + static int signbit(double x) { return cf_signbit(x); } +#endif + static int signbitf(float x) { return cf_signbitf(x); } + +long int lrint (double flt); +long int lrintf (float flt); + +float int2float (int32_t ix); +int32_t float2int (float fx); + + #endif + + #if ! defined( __INTEL_COMPILER ) || __INTEL_COMPILER < 1300 + // These functions appeared in Intel C v13. + float nanf( const char* str); + double nan( const char* str); + long double nanl( const char* str); + #endif + + #ifdef __cplusplus + } + #endif + +#endif + +#if defined( __ANDROID__ ) + #define log2(X) (log(X)/log(2)) +#endif + + + +// +// stdio.h +// + +#if defined(_MSC_VER) + // snprintf added in _MSC_VER == 1900 (Visual Studio 2015) + #if _MSC_VER < 1900 + #define snprintf sprintf_s + #endif +#endif + + + +// +// unistd.h +// + +#if defined( _MSC_VER ) + EXTERN_C unsigned int sleep( unsigned int sec ); + EXTERN_C int usleep( int usec ); +#endif + + + +// +// syscall.h +// + +#if defined( __ANDROID__ ) + // Android bionic's isn't providing SYS_sysctl wrappers. + #define SYS__sysctl __NR__sysctl +#endif + + + +// Some tests use _malloca which defined in malloc.h. +#if !defined (__APPLE__) +#include +#endif + + +// +// ??? +// + +#if defined( _MSC_VER ) + + #define MAXPATHLEN _MAX_PATH + + EXTERN_C uint64_t ReadTime( void ); + EXTERN_C double SubtractTime( uint64_t endTime, uint64_t startTime ); + +/** Returns the number of leading 0-bits in x, + starting at the most significant bit position. + If x is 0, the result is undefined. +*/ + EXTERN_C int __builtin_clz(unsigned int pattern); + +#endif + +#ifndef MIN + #define MIN(x,y) (((x)<(y))?(x):(y)) +#endif +#ifndef MAX + #define MAX(x,y) (((x)>(y))?(x):(y)) +#endif + + +/* + ------------------------------------------------------------------------------------------------ + WARNING: DO NOT USE THESE MACROS: MAKE_HEX_FLOAT, MAKE_HEX_DOUBLE, MAKE_HEX_LONG. + + This is a typical usage of the macros: + + double yhi = MAKE_HEX_DOUBLE(0x1.5555555555555p-2,0x15555555555555LL,-2); + + (taken from math_brute_force/reference_math.c). There are two problems: + + 1. There is an error here. On Windows in will produce incorrect result + `0x1.5555555555555p+50'. To have a correct result it should be written as + `MAKE_HEX_DOUBLE(0x1.5555555555555p-2,0x15555555555555LL,-54)'. A proper value of the + third argument is not obvious -- sometimes it should be the same as exponent of the + first argument, but sometimes not. + + 2. Information is duplicated. It is easy to make a mistake. + + Use HEX_FLT, HEX_DBL, HEX_LDBL macros instead (see them in the bottom of the file). + ------------------------------------------------------------------------------------------------ +*/ +#if defined ( _MSC_VER ) && ! defined( __INTEL_COMPILER ) + + #define MAKE_HEX_FLOAT(x,y,z) ((float)ldexp( (float)(y), z)) + #define MAKE_HEX_DOUBLE(x,y,z) ldexp( (double)(y), z) + #define MAKE_HEX_LONG(x,y,z) ((long double) ldexp( (long double)(y), z)) + +#else + +// Do not use these macros in new code, use HEX_FLT, HEX_DBL, HEX_LDBL instead. +#define MAKE_HEX_FLOAT(x,y,z) x +#define MAKE_HEX_DOUBLE(x,y,z) x +#define MAKE_HEX_LONG(x,y,z) x + +#endif + + +/* + ------------------------------------------------------------------------------------------------ + HEX_FLT, HEXT_DBL, HEX_LDBL -- Create hex floating point literal of type float, double, long + double respectively. Arguments: + + sm -- sign of number, + int -- integer part of mantissa (without `0x' prefix), + fract -- fractional part of mantissa (without decimal point and `L' or `LL' suffixes), + se -- sign of exponent, + exp -- absolute value of (binary) exponent. + + Example: + + double yhi = HEX_DBL( +, 1, 5555555555555, -, 2 ); // == 0x1.5555555555555p-2 + + Note: + + We have to pass signs as separate arguments because gcc pass negative integer values + (e. g. `-2') into a macro as two separate tokens, so `HEX_FLT( 1, 0, -2 )' produces result + `0x1.0p- 2' (note a space between minus and two) which is not a correct floating point + literal. + ------------------------------------------------------------------------------------------------ +*/ +#if defined ( _MSC_VER ) && ! defined( __INTEL_COMPILER ) + // If compiler does not support hex floating point literals: + #define HEX_FLT( sm, int, fract, se, exp ) sm ldexpf( (float)( 0x ## int ## fract ## UL ), se exp + ilogbf( (float) 0x ## int ) - ilogbf( ( float )( 0x ## int ## fract ## UL ) ) ) + #define HEX_DBL( sm, int, fract, se, exp ) sm ldexp( (double)( 0x ## int ## fract ## ULL ), se exp + ilogb( (double) 0x ## int ) - ilogb( ( double )( 0x ## int ## fract ## ULL ) ) ) + #define HEX_LDBL( sm, int, fract, se, exp ) sm ldexpl( (long double)( 0x ## int ## fract ## ULL ), se exp + ilogbl( (long double) 0x ## int ) - ilogbl( ( long double )( 0x ## int ## fract ## ULL ) ) ) +#else + // If compiler supports hex floating point literals: just concatenate all the parts into a literal. + #define HEX_FLT( sm, int, fract, se, exp ) sm 0x ## int ## . ## fract ## p ## se ## exp ## F + #define HEX_DBL( sm, int, fract, se, exp ) sm 0x ## int ## . ## fract ## p ## se ## exp + #define HEX_LDBL( sm, int, fract, se, exp ) sm 0x ## int ## . ## fract ## p ## se ## exp ## L +#endif + +#if defined(__MINGW32__) + #include + #define sleep(sec) Sleep((sec) * 1000) +#endif + +#endif // _COMPAT_H_ diff --git a/test_common/harness/conversions.c b/test_common/harness/conversions.c new file mode 100644 index 00000000..72fd8cb3 --- /dev/null +++ b/test_common/harness/conversions.c @@ -0,0 +1,1198 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "conversions.h" +#include +#include +#include +#include "mt19937.h" +#include "compat.h" + +#if defined( __SSE__ ) || defined (_MSC_VER) + #include +#endif +#if defined( __SSE2__ ) || defined (_MSC_VER) + #include +#endif + +void print_type_to_string(ExplicitType type, void *data, char* string) { + switch (type) { + case kBool: + if (*(char*)data) + sprintf(string, "true"); + else + sprintf(string, "false"); + return; + case kChar: + sprintf(string, "%d", (int)*((cl_char*)data)); + return; + case kUChar: + case kUnsignedChar: + sprintf(string, "%u", (int)*((cl_uchar*)data)); + return; + case kShort: + sprintf(string, "%d", (int)*((cl_short*)data)); + return; + case kUShort: + case kUnsignedShort: + sprintf(string, "%u", (int)*((cl_ushort*)data)); + return; + case kInt: + sprintf(string, "%d", *((cl_int*)data)); + return; + case kUInt: + case kUnsignedInt: + sprintf(string, "%u", *((cl_uint*)data)); + return; + case kLong: + sprintf(string, "%lld", *((cl_long*)data)); + return; + case kULong: + case kUnsignedLong: + sprintf(string, "%llu", *((cl_ulong*)data)); + return; + case kFloat: + sprintf(string, "%f", *((cl_float*)data)); + return; + case kHalf: + sprintf(string, "half"); + return; + case kDouble: + sprintf(string, "%g", *((cl_double*)data)); + return; + default: + sprintf(string, "INVALID"); + return; + } + +} + +size_t get_explicit_type_size( ExplicitType type ) +{ + /* Quick method to avoid branching: make sure the following array matches the Enum order */ + static size_t sExplicitTypeSizes[] = { + sizeof( cl_bool ), + sizeof( cl_char ), + sizeof( cl_uchar ), + sizeof( cl_uchar ), + sizeof( cl_short ), + sizeof( cl_ushort ), + sizeof( cl_ushort ), + sizeof( cl_int ), + sizeof( cl_uint ), + sizeof( cl_uint ), + sizeof( cl_long ), + sizeof( cl_ulong ), + sizeof( cl_ulong ), + sizeof( cl_float ), + sizeof( cl_half ), + sizeof( cl_double ) + }; + + return sExplicitTypeSizes[ type ]; +} + +const char * get_explicit_type_name( ExplicitType type ) +{ + /* Quick method to avoid branching: make sure the following array matches the Enum order */ + static const char *sExplicitTypeNames[] = { "bool", "char", "uchar", "unsigned char", "short", "ushort", "unsigned short", "int", + "uint", "unsigned int", "long", "ulong", "unsigned long", "float", "half", "double" }; + + return sExplicitTypeNames[ type ]; +} + +static long lrintf_clamped( float f ); +static long lrintf_clamped( float f ) +{ + static const float magic[2] = { MAKE_HEX_FLOAT( 0x1.0p23f, 0x1, 23), - MAKE_HEX_FLOAT( 0x1.0p23f, 0x1, 23) }; + + if( f >= -(float) LONG_MIN ) + return LONG_MAX; + + if( f <= (float) LONG_MIN ) + return LONG_MIN; + + // Round fractional values to integer in round towards nearest mode + if( fabsf(f) < MAKE_HEX_FLOAT( 0x1.0p23f, 0x1, 23 ) ) + { + volatile float x = f; + float magicVal = magic[ f < 0 ]; + +#if defined( __SSE__ ) || defined (_WIN32) + // Defeat x87 based arithmetic, which cant do FTZ, and will round this incorrectly + __m128 v = _mm_set_ss( x ); + __m128 m = _mm_set_ss( magicVal ); + v = _mm_add_ss( v, m ); + v = _mm_sub_ss( v, m ); + _mm_store_ss( (float*) &x, v ); +#else + x += magicVal; + x -= magicVal; +#endif + f = x; + } + + return (long) f; +} + +static long lrint_clamped( double f ); +static long lrint_clamped( double f ) +{ + static const double magic[2] = { MAKE_HEX_DOUBLE(0x1.0p52, 0x1LL, 52), MAKE_HEX_DOUBLE(-0x1.0p52, -0x1LL, 52) }; + + if( sizeof( long ) > 4 ) + { + if( f >= -(double) LONG_MIN ) + return LONG_MAX; + } + else + { + if( f >= LONG_MAX ) + return LONG_MAX; + } + + if( f <= (double) LONG_MIN ) + return LONG_MIN; + + // Round fractional values to integer in round towards nearest mode + if( fabs(f) < MAKE_HEX_DOUBLE(0x1.0p52, 0x1LL, 52) ) + { + volatile double x = f; + double magicVal = magic[ f < 0 ]; +#if defined( __SSE2__ ) || (defined (_MSC_VER)) + // Defeat x87 based arithmetic, which cant do FTZ, and will round this incorrectly + __m128d v = _mm_set_sd( x ); + __m128d m = _mm_set_sd( magicVal ); + v = _mm_add_sd( v, m ); + v = _mm_sub_sd( v, m ); + _mm_store_sd( (double*) &x, v ); +#else + x += magicVal; + x -= magicVal; +#endif + f = x; + } + + return (long) f; +} + + +typedef cl_long Long; +typedef cl_ulong ULong; + +static ULong sUpperLimits[ kNumExplicitTypes ] = + { + 0, + 127, 255, 255, + 32767, 65535, 65535, + 0x7fffffffLL, 0xffffffffLL, 0xffffffffLL, + 0x7fffffffffffffffLL, 0xffffffffffffffffLL, 0xffffffffffffffffLL, + 0, 0 }; // Last two values aren't stored here + +static Long sLowerLimits[ kNumExplicitTypes ] = + { + -1, + -128, 0, 0, + -32768, 0, 0, + 0xffffffff80000000LL, 0, 0, + 0x8000000000000000LL, 0, 0, + 0, 0 }; // Last two values aren't stored here + +#define BOOL_CASE(inType) \ + case kBool: \ + boolPtr = (bool *)outRaw; \ + *boolPtr = ( *inType##Ptr ) != 0 ? true : false; \ + break; + +#define SIMPLE_CAST_CASE(inType,outEnum,outType) \ + case outEnum: \ + outType##Ptr = (outType *)outRaw; \ + *outType##Ptr = (outType)(*inType##Ptr); \ + break; + +// Sadly, the ULong downcasting cases need a separate #define to get rid of signed/unsigned comparison warnings +#define DOWN_CAST_CASE(inType,outEnum,outType,sat) \ + case outEnum: \ + outType##Ptr = (outType *)outRaw; \ + if( sat ) \ + { \ + if( ( sLowerLimits[outEnum] < 0 && *inType##Ptr > (Long)sUpperLimits[outEnum] ) || ( sLowerLimits[outEnum] == 0 && (ULong)*inType##Ptr > sUpperLimits[outEnum] ) )\ + *outType##Ptr = (outType)sUpperLimits[outEnum];\ + else if( *inType##Ptr < sLowerLimits[outEnum] )\ + *outType##Ptr = (outType)sLowerLimits[outEnum]; \ + else \ + *outType##Ptr = (outType)*inType##Ptr; \ + } else { \ + *outType##Ptr = (outType)( *inType##Ptr & ( 0xffffffffffffffffLL >> ( 64 - ( sizeof( outType ) * 8 ) ) ) ); \ + } \ + break; + +#define U_DOWN_CAST_CASE(inType,outEnum,outType,sat) \ + case outEnum: \ + outType##Ptr = (outType *)outRaw; \ + if( sat ) \ + { \ + if( (ULong)*inType##Ptr > sUpperLimits[outEnum] )\ + *outType##Ptr = (outType)sUpperLimits[outEnum];\ + else \ + *outType##Ptr = (outType)*inType##Ptr; \ + } else { \ + *outType##Ptr = (outType)( *inType##Ptr & ( 0xffffffffffffffffLL >> ( 64 - ( sizeof( outType ) * 8 ) ) ) ); \ + } \ + break; + +#define TO_FLOAT_CASE(inType) \ + case kFloat: \ + floatPtr = (float *)outRaw; \ + *floatPtr = (float)(*inType##Ptr); \ + break; +#define TO_DOUBLE_CASE(inType) \ + case kDouble: \ + doublePtr = (double *)outRaw; \ + *doublePtr = (double)(*inType##Ptr); \ + break; + + +/* Note: we use lrintf here to force the rounding instead of whatever the processor's current rounding mode is */ +#define FLOAT_ROUND_TO_NEAREST_CASE(outEnum,outType) \ + case outEnum: \ + outType##Ptr = (outType *)outRaw; \ + *outType##Ptr = (outType)lrintf_clamped( *floatPtr ); \ + break; + +#define FLOAT_ROUND_CASE(outEnum,outType,rounding,sat) \ + case outEnum: \ + { \ + outType##Ptr = (outType *)outRaw; \ + /* Get the tens digit */ \ + Long wholeValue = (Long)*floatPtr;\ + float largeRemainder = ( *floatPtr - (float)wholeValue ) * 10.f; \ + /* What do we do based on that? */ \ + if( rounding == kRoundToEven ) \ + { \ + if( wholeValue & 1LL ) /*between 1 and 1.99 */ \ + wholeValue += 1LL; /* round up to even */ \ + } \ + else if( rounding == kRoundToZero ) \ + { \ + /* Nothing to do, round-to-zero is what C casting does */ \ + } \ + else if( rounding == kRoundToPosInf ) \ + { \ + /* Only positive numbers are wrong */ \ + if( largeRemainder != 0.f && wholeValue >= 0 ) \ + wholeValue++; \ + } \ + else if( rounding == kRoundToNegInf ) \ + { \ + /* Only negative numbers are off */ \ + if( largeRemainder != 0.f && wholeValue < 0 ) \ + wholeValue--; \ + } \ + else \ + { /* Default is round-to-nearest */ \ + wholeValue = (Long)lrintf_clamped( *floatPtr ); \ + } \ + /* Now apply saturation rules */ \ + if( sat ) \ + { \ + if( ( sLowerLimits[outEnum] < 0 && wholeValue > (Long)sUpperLimits[outEnum] ) || ( sLowerLimits[outEnum] == 0 && (ULong)wholeValue > sUpperLimits[outEnum] ) )\ + *outType##Ptr = (outType)sUpperLimits[outEnum];\ + else if( wholeValue < sLowerLimits[outEnum] )\ + *outType##Ptr = (outType)sLowerLimits[outEnum]; \ + else \ + *outType##Ptr = (outType)wholeValue; \ + } else { \ + *outType##Ptr = (outType)( wholeValue & ( 0xffffffffffffffffLL >> ( 64 - ( sizeof( outType ) * 8 ) ) ) ); \ + } \ + } \ + break; + +#define DOUBLE_ROUND_CASE(outEnum,outType,rounding,sat) \ + case outEnum: \ + { \ + outType##Ptr = (outType *)outRaw; \ + /* Get the tens digit */ \ + Long wholeValue = (Long)*doublePtr;\ + double largeRemainder = ( *doublePtr - (double)wholeValue ) * 10.0; \ + /* What do we do based on that? */ \ + if( rounding == kRoundToEven ) \ + { \ + if( wholeValue & 1LL ) /*between 1 and 1.99 */ \ + wholeValue += 1LL; /* round up to even */ \ + } \ + else if( rounding == kRoundToZero ) \ + { \ + /* Nothing to do, round-to-zero is what C casting does */ \ + } \ + else if( rounding == kRoundToPosInf ) \ + { \ + /* Only positive numbers are wrong */ \ + if( largeRemainder != 0.0 && wholeValue >= 0 ) \ + wholeValue++; \ + } \ + else if( rounding == kRoundToNegInf ) \ + { \ + /* Only negative numbers are off */ \ + if( largeRemainder != 0.0 && wholeValue < 0 ) \ + wholeValue--; \ + } \ + else \ + { /* Default is round-to-nearest */ \ + wholeValue = (Long)lrint_clamped( *doublePtr ); \ + } \ + /* Now apply saturation rules */ \ + if( sat ) \ + { \ + if( ( sLowerLimits[outEnum] < 0 && wholeValue > (Long)sUpperLimits[outEnum] ) || ( sLowerLimits[outEnum] == 0 && (ULong)wholeValue > sUpperLimits[outEnum] ) )\ + *outType##Ptr = (outType)sUpperLimits[outEnum];\ + else if( wholeValue < sLowerLimits[outEnum] )\ + *outType##Ptr = (outType)sLowerLimits[outEnum]; \ + else \ + *outType##Ptr = (outType)wholeValue; \ + } else { \ + *outType##Ptr = (outType)( wholeValue & ( 0xffffffffffffffffLL >> ( 64 - ( sizeof( outType ) * 8 ) ) ) ); \ + } \ + } \ + break; + +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; + +void convert_explicit_value( void *inRaw, void *outRaw, ExplicitType inType, bool saturate, RoundingType roundType, ExplicitType outType ) +{ + bool *boolPtr; + char *charPtr; + uchar *ucharPtr; + short *shortPtr; + ushort *ushortPtr; + int *intPtr; + uint *uintPtr; + Long *LongPtr; + ULong *ULongPtr; + float *floatPtr; + double *doublePtr; + + + switch( inType ) + { + case kBool: + boolPtr = (bool *)inRaw; + switch( outType ) + { + case kBool: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + case kChar: + case kUChar: + case kUnsignedChar: + case kShort: + case kUShort: + case kUnsignedShort: + case kInt: + case kUInt: + case kUnsignedInt: + case kLong: + case kULong: + case kUnsignedLong: + memset( outRaw, *boolPtr ? 0xff : 0, get_explicit_type_size( outType ) ); + break; + + case kFloat: + floatPtr = (float *)outRaw; + *floatPtr = ( *boolPtr ) ? -1.f : 0.f; + break; + case kDouble: + doublePtr = (double *)outRaw; + *doublePtr = ( *boolPtr ) ? -1.0 : 0.0; + break; + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kChar: + charPtr = (char *)inRaw; + switch( outType ) + { + BOOL_CASE(char) + + case kChar: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(char,kUChar,uchar,saturate) + SIMPLE_CAST_CASE(char,kUnsignedChar,uchar) + SIMPLE_CAST_CASE(char,kShort,short) + SIMPLE_CAST_CASE(char,kUShort,ushort) + SIMPLE_CAST_CASE(char,kUnsignedShort,ushort) + SIMPLE_CAST_CASE(char,kInt,int) + SIMPLE_CAST_CASE(char,kUInt,uint) + SIMPLE_CAST_CASE(char,kUnsignedInt,uint) + SIMPLE_CAST_CASE(char,kLong,Long) + SIMPLE_CAST_CASE(char,kULong,ULong) + SIMPLE_CAST_CASE(char,kUnsignedLong,ULong) + + TO_FLOAT_CASE(char) + TO_DOUBLE_CASE(char) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kUChar: + ucharPtr = (uchar *)inRaw; + switch( outType ) + { + BOOL_CASE(uchar) + + case kUChar: + case kUnsignedChar: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(uchar,kChar,char,saturate) + SIMPLE_CAST_CASE(uchar,kShort,short) + SIMPLE_CAST_CASE(uchar,kUShort,ushort) + SIMPLE_CAST_CASE(uchar,kUnsignedShort,ushort) + SIMPLE_CAST_CASE(uchar,kInt,int) + SIMPLE_CAST_CASE(uchar,kUInt,uint) + SIMPLE_CAST_CASE(uchar,kUnsignedInt,uint) + SIMPLE_CAST_CASE(uchar,kLong,Long) + SIMPLE_CAST_CASE(uchar,kULong,ULong) + SIMPLE_CAST_CASE(uchar,kUnsignedLong,ULong) + + TO_FLOAT_CASE(uchar) + TO_DOUBLE_CASE(uchar) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kUnsignedChar: + ucharPtr = (uchar *)inRaw; + switch( outType ) + { + BOOL_CASE(uchar) + + case kUChar: + case kUnsignedChar: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(uchar,kChar,char,saturate) + SIMPLE_CAST_CASE(uchar,kShort,short) + SIMPLE_CAST_CASE(uchar,kUShort,ushort) + SIMPLE_CAST_CASE(uchar,kUnsignedShort,ushort) + SIMPLE_CAST_CASE(uchar,kInt,int) + SIMPLE_CAST_CASE(uchar,kUInt,uint) + SIMPLE_CAST_CASE(uchar,kUnsignedInt,uint) + SIMPLE_CAST_CASE(uchar,kLong,Long) + SIMPLE_CAST_CASE(uchar,kULong,ULong) + SIMPLE_CAST_CASE(uchar,kUnsignedLong,ULong) + + TO_FLOAT_CASE(uchar) + TO_DOUBLE_CASE(uchar) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kShort: + shortPtr = (short *)inRaw; + switch( outType ) + { + BOOL_CASE(short) + + case kShort: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(short,kChar,char,saturate) + DOWN_CAST_CASE(short,kUChar,uchar,saturate) + DOWN_CAST_CASE(short,kUnsignedChar,uchar,saturate) + DOWN_CAST_CASE(short,kUShort,ushort,saturate) + DOWN_CAST_CASE(short,kUnsignedShort,ushort,saturate) + SIMPLE_CAST_CASE(short,kInt,int) + SIMPLE_CAST_CASE(short,kUInt,uint) + SIMPLE_CAST_CASE(short,kUnsignedInt,uint) + SIMPLE_CAST_CASE(short,kLong,Long) + SIMPLE_CAST_CASE(short,kULong,ULong) + SIMPLE_CAST_CASE(short,kUnsignedLong,ULong) + + TO_FLOAT_CASE(short) + TO_DOUBLE_CASE(short) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kUShort: + ushortPtr = (ushort *)inRaw; + switch( outType ) + { + BOOL_CASE(ushort) + + case kUShort: + case kUnsignedShort: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(ushort,kChar,char,saturate) + DOWN_CAST_CASE(ushort,kUChar,uchar,saturate) + DOWN_CAST_CASE(ushort,kUnsignedChar,uchar,saturate) + DOWN_CAST_CASE(ushort,kShort,short,saturate) + SIMPLE_CAST_CASE(ushort,kInt,int) + SIMPLE_CAST_CASE(ushort,kUInt,uint) + SIMPLE_CAST_CASE(ushort,kUnsignedInt,uint) + SIMPLE_CAST_CASE(ushort,kLong,Long) + SIMPLE_CAST_CASE(ushort,kULong,ULong) + SIMPLE_CAST_CASE(ushort,kUnsignedLong,ULong) + + TO_FLOAT_CASE(ushort) + TO_DOUBLE_CASE(ushort) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kUnsignedShort: + ushortPtr = (ushort *)inRaw; + switch( outType ) + { + BOOL_CASE(ushort) + + case kUShort: + case kUnsignedShort: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(ushort,kChar,char,saturate) + DOWN_CAST_CASE(ushort,kUChar,uchar,saturate) + DOWN_CAST_CASE(ushort,kUnsignedChar,uchar,saturate) + DOWN_CAST_CASE(ushort,kShort,short,saturate) + SIMPLE_CAST_CASE(ushort,kInt,int) + SIMPLE_CAST_CASE(ushort,kUInt,uint) + SIMPLE_CAST_CASE(ushort,kUnsignedInt,uint) + SIMPLE_CAST_CASE(ushort,kLong,Long) + SIMPLE_CAST_CASE(ushort,kULong,ULong) + SIMPLE_CAST_CASE(ushort,kUnsignedLong,ULong) + + TO_FLOAT_CASE(ushort) + TO_DOUBLE_CASE(ushort) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kInt: + intPtr = (int *)inRaw; + switch( outType ) + { + BOOL_CASE(int) + + case kInt: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(int,kChar,char,saturate) + DOWN_CAST_CASE(int,kUChar,uchar,saturate) + DOWN_CAST_CASE(int,kUnsignedChar,uchar,saturate) + DOWN_CAST_CASE(int,kShort,short,saturate) + DOWN_CAST_CASE(int,kUShort,ushort,saturate) + DOWN_CAST_CASE(int,kUnsignedShort,ushort,saturate) + DOWN_CAST_CASE(int,kUInt,uint,saturate) + DOWN_CAST_CASE(int,kUnsignedInt,uint,saturate) + SIMPLE_CAST_CASE(int,kLong,Long) + SIMPLE_CAST_CASE(int,kULong,ULong) + SIMPLE_CAST_CASE(int,kUnsignedLong,ULong) + + TO_FLOAT_CASE(int) + TO_DOUBLE_CASE(int) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kUInt: + uintPtr = (uint *)inRaw; + switch( outType ) + { + BOOL_CASE(uint) + + case kUInt: + case kUnsignedInt: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(uint,kChar,char,saturate) + DOWN_CAST_CASE(uint,kUChar,uchar,saturate) + DOWN_CAST_CASE(uint,kUnsignedChar,uchar,saturate) + DOWN_CAST_CASE(uint,kShort,short,saturate) + DOWN_CAST_CASE(uint,kUShort,ushort,saturate) + DOWN_CAST_CASE(uint,kUnsignedShort,ushort,saturate) + DOWN_CAST_CASE(uint,kInt,int,saturate) + SIMPLE_CAST_CASE(uint,kLong,Long) + SIMPLE_CAST_CASE(uint,kULong,ULong) + SIMPLE_CAST_CASE(uint,kUnsignedLong,ULong) + + TO_FLOAT_CASE(uint) + TO_DOUBLE_CASE(uint) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kUnsignedInt: + uintPtr = (uint *)inRaw; + switch( outType ) + { + BOOL_CASE(uint) + + case kUInt: + case kUnsignedInt: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(uint,kChar,char,saturate) + DOWN_CAST_CASE(uint,kUChar,uchar,saturate) + DOWN_CAST_CASE(uint,kUnsignedChar,uchar,saturate) + DOWN_CAST_CASE(uint,kShort,short,saturate) + DOWN_CAST_CASE(uint,kUShort,ushort,saturate) + DOWN_CAST_CASE(uint,kUnsignedShort,ushort,saturate) + DOWN_CAST_CASE(uint,kInt,int,saturate) + SIMPLE_CAST_CASE(uint,kLong,Long) + SIMPLE_CAST_CASE(uint,kULong,ULong) + SIMPLE_CAST_CASE(uint,kUnsignedLong,ULong) + + TO_FLOAT_CASE(uint) + TO_DOUBLE_CASE(uint) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kLong: + LongPtr = (Long *)inRaw; + switch( outType ) + { + BOOL_CASE(Long) + + case kLong: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(Long,kChar,char,saturate) + DOWN_CAST_CASE(Long,kUChar,uchar,saturate) + DOWN_CAST_CASE(Long,kUnsignedChar,uchar,saturate) + DOWN_CAST_CASE(Long,kShort,short,saturate) + DOWN_CAST_CASE(Long,kUShort,ushort,saturate) + DOWN_CAST_CASE(Long,kUnsignedShort,ushort,saturate) + DOWN_CAST_CASE(Long,kInt,int,saturate) + DOWN_CAST_CASE(Long,kUInt,uint,saturate) + DOWN_CAST_CASE(Long,kUnsignedInt,uint,saturate) + DOWN_CAST_CASE(Long,kULong,ULong,saturate) + DOWN_CAST_CASE(Long,kUnsignedLong,ULong,saturate) + + TO_FLOAT_CASE(Long) + TO_DOUBLE_CASE(Long) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kULong: + ULongPtr = (ULong *)inRaw; + switch( outType ) + { + BOOL_CASE(ULong) + + case kUnsignedLong: + case kULong: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + U_DOWN_CAST_CASE(ULong,kChar,char,saturate) + U_DOWN_CAST_CASE(ULong,kUChar,uchar,saturate) + U_DOWN_CAST_CASE(ULong,kUnsignedChar,uchar,saturate) + U_DOWN_CAST_CASE(ULong,kShort,short,saturate) + U_DOWN_CAST_CASE(ULong,kUShort,ushort,saturate) + U_DOWN_CAST_CASE(ULong,kUnsignedShort,ushort,saturate) + U_DOWN_CAST_CASE(ULong,kInt,int,saturate) + U_DOWN_CAST_CASE(ULong,kUInt,uint,saturate) + U_DOWN_CAST_CASE(ULong,kUnsignedInt,uint,saturate) + U_DOWN_CAST_CASE(ULong,kLong,Long,saturate) + + TO_FLOAT_CASE(ULong) + TO_DOUBLE_CASE(ULong) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kUnsignedLong: + ULongPtr = (ULong *)inRaw; + switch( outType ) + { + BOOL_CASE(ULong) + + case kULong: + case kUnsignedLong: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + U_DOWN_CAST_CASE(ULong,kChar,char,saturate) + U_DOWN_CAST_CASE(ULong,kUChar,uchar,saturate) + U_DOWN_CAST_CASE(ULong,kUnsignedChar,uchar,saturate) + U_DOWN_CAST_CASE(ULong,kShort,short,saturate) + U_DOWN_CAST_CASE(ULong,kUShort,ushort,saturate) + U_DOWN_CAST_CASE(ULong,kUnsignedShort,ushort,saturate) + U_DOWN_CAST_CASE(ULong,kInt,int,saturate) + U_DOWN_CAST_CASE(ULong,kUInt,uint,saturate) + U_DOWN_CAST_CASE(ULong,kUnsignedInt,uint,saturate) + U_DOWN_CAST_CASE(ULong,kLong,Long,saturate) + + TO_FLOAT_CASE(ULong) + TO_DOUBLE_CASE(ULong) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kFloat: + floatPtr = (float *)inRaw; + switch( outType ) + { + BOOL_CASE(float) + + FLOAT_ROUND_CASE(kChar,char,roundType,saturate) + FLOAT_ROUND_CASE(kUChar,uchar,roundType,saturate) + FLOAT_ROUND_CASE(kUnsignedChar,uchar,roundType,saturate) + FLOAT_ROUND_CASE(kShort,short,roundType,saturate) + FLOAT_ROUND_CASE(kUShort,ushort,roundType,saturate) + FLOAT_ROUND_CASE(kUnsignedShort,ushort,roundType,saturate) + FLOAT_ROUND_CASE(kInt,int,roundType,saturate) + FLOAT_ROUND_CASE(kUInt,uint,roundType,saturate) + FLOAT_ROUND_CASE(kUnsignedInt,uint,roundType,saturate) + FLOAT_ROUND_CASE(kLong,Long,roundType,saturate) + FLOAT_ROUND_CASE(kULong,ULong,roundType,saturate) + FLOAT_ROUND_CASE(kUnsignedLong,ULong,roundType,saturate) + + case kFloat: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + TO_DOUBLE_CASE(float); + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kDouble: + doublePtr = (double *)inRaw; + switch( outType ) + { + BOOL_CASE(double) + + DOUBLE_ROUND_CASE(kChar,char,roundType,saturate) + DOUBLE_ROUND_CASE(kUChar,uchar,roundType,saturate) + DOUBLE_ROUND_CASE(kUnsignedChar,uchar,roundType,saturate) + DOUBLE_ROUND_CASE(kShort,short,roundType,saturate) + DOUBLE_ROUND_CASE(kUShort,ushort,roundType,saturate) + DOUBLE_ROUND_CASE(kUnsignedShort,ushort,roundType,saturate) + DOUBLE_ROUND_CASE(kInt,int,roundType,saturate) + DOUBLE_ROUND_CASE(kUInt,uint,roundType,saturate) + DOUBLE_ROUND_CASE(kUnsignedInt,uint,roundType,saturate) + DOUBLE_ROUND_CASE(kLong,Long,roundType,saturate) + DOUBLE_ROUND_CASE(kULong,ULong,roundType,saturate) + DOUBLE_ROUND_CASE(kUnsignedLong,ULong,roundType,saturate) + + TO_FLOAT_CASE(double); + + case kDouble: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } +} + +void generate_random_data( ExplicitType type, size_t count, MTdata d, void *outData ) +{ + bool *boolPtr; + cl_char *charPtr; + cl_uchar *ucharPtr; + cl_short *shortPtr; + cl_ushort *ushortPtr; + cl_int *intPtr; + cl_uint *uintPtr; + cl_long *longPtr; + cl_ulong *ulongPtr; + cl_float *floatPtr; + cl_double *doublePtr; + cl_ushort *halfPtr; + size_t i; + cl_uint bits = genrand_int32(d); + cl_uint bitsLeft = 32; + + switch( type ) + { + case kBool: + boolPtr = (bool *)outData; + for( i = 0; i < count; i++ ) + { + if( 0 == bitsLeft) + { + bits = genrand_int32(d); + bitsLeft = 32; + } + boolPtr[i] = ( bits & 1 ) ? true : false; + bits >>= 1; bitsLeft -= 1; + } + break; + + case kChar: + charPtr = (cl_char *)outData; + for( i = 0; i < count; i++ ) + { + if( 0 == bitsLeft) + { + bits = genrand_int32(d); + bitsLeft = 32; + } + charPtr[i] = (cl_char)( (cl_int)(bits & 255 ) - 127 ); + bits >>= 8; bitsLeft -= 8; + } + break; + + case kUChar: + case kUnsignedChar: + ucharPtr = (cl_uchar *)outData; + for( i = 0; i < count; i++ ) + { + if( 0 == bitsLeft) + { + bits = genrand_int32(d); + bitsLeft = 32; + } + ucharPtr[i] = (cl_uchar)( bits & 255 ); + bits >>= 8; bitsLeft -= 8; + } + break; + + case kShort: + shortPtr = (cl_short *)outData; + for( i = 0; i < count; i++ ) + { + if( 0 == bitsLeft) + { + bits = genrand_int32(d); + bitsLeft = 32; + } + shortPtr[i] = (cl_short)( (cl_int)( bits & 65535 ) - 32767 ); + bits >>= 16; bitsLeft -= 16; + } + break; + + case kUShort: + case kUnsignedShort: + ushortPtr = (cl_ushort *)outData; + for( i = 0; i < count; i++ ) + { + if( 0 == bitsLeft) + { + bits = genrand_int32(d); + bitsLeft = 32; + } + ushortPtr[i] = (cl_ushort)( (cl_int)( bits & 65535 ) ); + bits >>= 16; bitsLeft -= 16; + } + break; + + case kInt: + intPtr = (cl_int *)outData; + for( i = 0; i < count; i++ ) + { + intPtr[i] = (cl_int)genrand_int32(d); + } + break; + + case kUInt: + case kUnsignedInt: + uintPtr = (cl_uint *)outData; + for( i = 0; i < count; i++ ) + { + uintPtr[i] = (unsigned int)genrand_int32(d); + } + break; + + case kLong: + longPtr = (cl_long *)outData; + for( i = 0; i < count; i++ ) + { + longPtr[i] = (cl_long)genrand_int32(d) | ( (cl_long)genrand_int32(d) << 32 ); + } + break; + + case kULong: + case kUnsignedLong: + ulongPtr = (cl_ulong *)outData; + for( i = 0; i < count; i++ ) + { + ulongPtr[i] = (cl_ulong)genrand_int32(d) | ( (cl_ulong)genrand_int32(d) << 32 ); + } + break; + + case kFloat: + floatPtr = (cl_float *)outData; + for( i = 0; i < count; i++ ) + { + // [ -(double) 0x7fffffff, (double) 0x7fffffff ] + double t = genrand_real1(d); + floatPtr[i] = (float) ((1.0 - t) * -(double) 0x7fffffff + t * (double) 0x7fffffff); + } + break; + + case kDouble: + doublePtr = (cl_double *)outData; + for( i = 0; i < count; i++ ) + { + cl_long u = (cl_long)genrand_int32(d) | ( (cl_long)genrand_int32(d) << 32 ); + double t = (double) u; + t *= MAKE_HEX_DOUBLE( 0x1.0p-32, 0x1, -32 ); // scale [-2**63, 2**63] to [-2**31, 2**31] + doublePtr[i] = t; + } + break; + + case kHalf: + halfPtr = (ushort *)outData; + for( i = 0; i < count; i++ ) + { + if( 0 == bitsLeft) + { + bits = genrand_int32(d); + bitsLeft = 32; + } + halfPtr[i] = bits & 65535; /* Kindly generates random bits for us */ + bits >>= 16; bitsLeft -= 16; + } + break; + + default: + log_error( "ERROR: Invalid type passed in to generate_random_data!\n" ); + break; + } +} + +void * create_random_data( ExplicitType type, MTdata d, size_t count ) +{ + void *data = malloc( get_explicit_type_size( type ) * count ); + generate_random_data( type, count, d, data ); + return data; +} + +cl_long read_upscale_signed( void *inRaw, ExplicitType inType ) +{ + switch( inType ) + { + case kChar: + return (cl_long)( *( (cl_char *)inRaw ) ); + case kUChar: + case kUnsignedChar: + return (cl_long)( *( (cl_uchar *)inRaw ) ); + case kShort: + return (cl_long)( *( (cl_short *)inRaw ) ); + case kUShort: + case kUnsignedShort: + return (cl_long)( *( (cl_ushort *)inRaw ) ); + case kInt: + return (cl_long)( *( (cl_int *)inRaw ) ); + case kUInt: + case kUnsignedInt: + return (cl_long)( *( (cl_uint *)inRaw ) ); + case kLong: + return (cl_long)( *( (cl_long *)inRaw ) ); + case kULong: + case kUnsignedLong: + return (cl_long)( *( (cl_ulong *)inRaw ) ); + default: + return 0; + } +} + +cl_ulong read_upscale_unsigned( void *inRaw, ExplicitType inType ) +{ + switch( inType ) + { + case kChar: + return (cl_ulong)( *( (cl_char *)inRaw ) ); + case kUChar: + case kUnsignedChar: + return (cl_ulong)( *( (cl_uchar *)inRaw ) ); + case kShort: + return (cl_ulong)( *( (cl_short *)inRaw ) ); + case kUShort: + case kUnsignedShort: + return (cl_ulong)( *( (cl_ushort *)inRaw ) ); + case kInt: + return (cl_ulong)( *( (cl_int *)inRaw ) ); + case kUInt: + case kUnsignedInt: + return (cl_ulong)( *( (cl_uint *)inRaw ) ); + case kLong: + return (cl_ulong)( *( (cl_long *)inRaw ) ); + case kULong: + case kUnsignedLong: + return (cl_ulong)( *( (cl_ulong *)inRaw ) ); + default: + return 0; + } +} + +float read_as_float( void *inRaw, ExplicitType inType ) +{ + switch( inType ) + { + case kChar: + return (float)( *( (cl_char *)inRaw ) ); + case kUChar: + case kUnsignedChar: + return (float)( *( (cl_char *)inRaw ) ); + case kShort: + return (float)( *( (cl_short *)inRaw ) ); + case kUShort: + case kUnsignedShort: + return (float)( *( (cl_ushort *)inRaw ) ); + case kInt: + return (float)( *( (cl_int *)inRaw ) ); + case kUInt: + case kUnsignedInt: + return (float)( *( (cl_uint *)inRaw ) ); + case kLong: + return (float)( *( (cl_long *)inRaw ) ); + case kULong: + case kUnsignedLong: + return (float)( *( (cl_ulong *)inRaw ) ); + case kFloat: + return *( (float *)inRaw ); + case kDouble: + return (float) *( (double*)inRaw ); + default: + return 0; + } +} + +float get_random_float(float low, float high, MTdata d) +{ + float t = (float)((double)genrand_int32(d) / (double)0xFFFFFFFF); + return (1.0f - t) * low + t * high; +} + +double get_random_double(double low, double high, MTdata d) +{ + cl_ulong u = (cl_ulong) genrand_int32(d) | ((cl_ulong) genrand_int32(d) << 32 ); + double t = (double) u * MAKE_HEX_DOUBLE( 0x1.0p-64, 0x1, -64); + return (1.0f - t) * low + t * high; +} + +float any_float( MTdata d ) +{ + union + { + float f; + cl_uint u; + }u; + + u.u = genrand_int32(d); + return u.f; +} + + +double any_double( MTdata d ) +{ + union + { + double f; + cl_ulong u; + }u; + + u.u = (cl_ulong) genrand_int32(d) | ((cl_ulong) genrand_int32(d) << 32); + return u.f; +} + +int random_in_range( int minV, int maxV, MTdata d ) +{ + cl_ulong r = ((cl_ulong) genrand_int32(d) ) * (maxV - minV + 1); + return (cl_uint)(r >> 32) + minV; +} + +size_t get_random_size_t(size_t low, size_t high, MTdata d) +{ + enum { N = sizeof(size_t)/sizeof(int) }; + + union { + int word[N]; + size_t size; + } u; + + for (unsigned i=0; i != N; ++i) { + u.word[i] = genrand_int32(d); + } + + assert(low <= high && "Invalid random number range specified"); + size_t range = high - low; + + return (range) ? low + ((u.size - low) % range) : low; +} + + diff --git a/test_common/harness/conversions.h b/test_common/harness/conversions.h new file mode 100644 index 00000000..aa3cb6b4 --- /dev/null +++ b/test_common/harness/conversions.h @@ -0,0 +1,126 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _conversions_h +#define _conversions_h + +#include "compat.h" + +#include "errorHelpers.h" +#include "mt19937.h" +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Note: the next three all have to match in size and order!! */ + +enum ExplicitTypes +{ + kBool = 0, + kChar, + kUChar, + kUnsignedChar, + kShort, + kUShort, + kUnsignedShort, + kInt, + kUInt, + kUnsignedInt, + kLong, + kULong, + kUnsignedLong, + kFloat, + kHalf, + kDouble, + kNumExplicitTypes +}; + +typedef enum ExplicitTypes ExplicitType; + +enum RoundingTypes +{ + kRoundToEven = 0, + kRoundToZero, + kRoundToPosInf, + kRoundToNegInf, + kRoundToNearest, + + kNumRoundingTypes, + + kDefaultRoundingType = kRoundToNearest +}; + +typedef enum RoundingTypes RoundingType; + +extern void print_type_to_string(ExplicitType type, void *data, char* string); +extern size_t get_explicit_type_size( ExplicitType type ); +extern const char * get_explicit_type_name( ExplicitType type ); +extern void convert_explicit_value( void *inRaw, void *outRaw, ExplicitType inType, bool saturate, RoundingType roundType, ExplicitType outType ); + +extern void generate_random_data( ExplicitType type, size_t count, MTdata d, void *outData ); +extern void * create_random_data( ExplicitType type, MTdata d, size_t count ); + +extern cl_long read_upscale_signed( void *inRaw, ExplicitType inType ); +extern cl_ulong read_upscale_unsigned( void *inRaw, ExplicitType inType ); +extern float read_as_float( void *inRaw, ExplicitType inType ); + +extern float get_random_float(float low, float high, MTdata d); +extern double get_random_double(double low, double high, MTdata d); +extern float any_float( MTdata d ); +extern double any_double( MTdata d ); + +extern int random_in_range( int minV, int maxV, MTdata d ); + +size_t get_random_size_t(size_t low, size_t high, MTdata d); + +// Note: though this takes a double, this is for use with single precision tests +static inline int IsFloatSubnormal( float x ) +{ +#if 2 == FLT_RADIX + // Do this in integer to avoid problems with FTZ behavior + union{ float d; uint32_t u;}u; + u.d = fabsf(x); + return (u.u-1) < 0x007fffffU; +#else + // rely on floating point hardware for non-radix2 non-IEEE-754 hardware -- will fail if you flush subnormals to zero + return fabs(x) < (double) FLT_MIN && x != 0.0; +#endif +} + +static inline int IsDoubleSubnormal( double x ) +{ +#if 2 == FLT_RADIX + // Do this in integer to avoid problems with FTZ behavior + union{ double d; uint64_t u;}u; + u.d = fabs( x); + return (u.u-1) < 0x000fffffffffffffULL; +#else + // rely on floating point hardware for non-radix2 non-IEEE-754 hardware -- will fail if you flush subnormals to zero + return fabs(x) < (double) DBL_MIN && x != 0.0; +#endif +} + +#if defined(__cplusplus) +} +#endif + +#endif // _conversions_h + + diff --git a/test_common/harness/errorHelpers.c b/test_common/harness/errorHelpers.c new file mode 100644 index 00000000..db26e456 --- /dev/null +++ b/test_common/harness/errorHelpers.c @@ -0,0 +1,813 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "compat.h" +#include +#include +#include + +#include "errorHelpers.h" + +extern bool gOfflineCompiler; + +const char *IGetErrorString( int clErrorCode ) +{ + switch( clErrorCode ) + { + case CL_SUCCESS: return "CL_SUCCESS"; + case CL_DEVICE_NOT_FOUND: return "CL_DEVICE_NOT_FOUND"; + case CL_DEVICE_NOT_AVAILABLE: return "CL_DEVICE_NOT_AVAILABLE"; + case CL_COMPILER_NOT_AVAILABLE: return "CL_COMPILER_NOT_AVAILABLE"; + case CL_MEM_OBJECT_ALLOCATION_FAILURE: return "CL_MEM_OBJECT_ALLOCATION_FAILURE"; + case CL_OUT_OF_RESOURCES: return "CL_OUT_OF_RESOURCES"; + case CL_OUT_OF_HOST_MEMORY: return "CL_OUT_OF_HOST_MEMORY"; + case CL_PROFILING_INFO_NOT_AVAILABLE: return "CL_PROFILING_INFO_NOT_AVAILABLE"; + case CL_MEM_COPY_OVERLAP: return "CL_MEM_COPY_OVERLAP"; + case CL_IMAGE_FORMAT_MISMATCH: return "CL_IMAGE_FORMAT_MISMATCH"; + case CL_IMAGE_FORMAT_NOT_SUPPORTED: return "CL_IMAGE_FORMAT_NOT_SUPPORTED"; + case CL_BUILD_PROGRAM_FAILURE: return "CL_BUILD_PROGRAM_FAILURE"; + case CL_MAP_FAILURE: return "CL_MAP_FAILURE"; + case CL_MISALIGNED_SUB_BUFFER_OFFSET: return "CL_MISALIGNED_SUB_BUFFER_OFFSET"; + case CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST: return "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST"; + case CL_COMPILE_PROGRAM_FAILURE: return "CL_COMPILE_PROGRAM_FAILURE"; + case CL_LINKER_NOT_AVAILABLE: return "CL_LINKER_NOT_AVAILABLE"; + case CL_LINK_PROGRAM_FAILURE: return "CL_LINK_PROGRAM_FAILURE"; + case CL_DEVICE_PARTITION_FAILED: return "CL_DEVICE_PARTITION_FAILED"; + case CL_KERNEL_ARG_INFO_NOT_AVAILABLE: return "CL_KERNEL_ARG_INFO_NOT_AVAILABLE"; + case CL_INVALID_VALUE: return "CL_INVALID_VALUE"; + case CL_INVALID_DEVICE_TYPE: return "CL_INVALID_DEVICE_TYPE"; + case CL_INVALID_DEVICE: return "CL_INVALID_DEVICE"; + case CL_INVALID_CONTEXT: return "CL_INVALID_CONTEXT"; + case CL_INVALID_QUEUE_PROPERTIES: return "CL_INVALID_QUEUE_PROPERTIES"; + case CL_INVALID_COMMAND_QUEUE: return "CL_INVALID_COMMAND_QUEUE"; + case CL_INVALID_HOST_PTR: return "CL_INVALID_HOST_PTR"; + case CL_INVALID_MEM_OBJECT: return "CL_INVALID_MEM_OBJECT"; + case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR: return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR"; + case CL_INVALID_IMAGE_SIZE: return "CL_INVALID_IMAGE_SIZE"; + case CL_INVALID_SAMPLER: return "CL_INVALID_SAMPLER"; + case CL_INVALID_BINARY: return "CL_INVALID_BINARY"; + case CL_INVALID_BUILD_OPTIONS: return "CL_INVALID_BUILD_OPTIONS"; + case CL_INVALID_PROGRAM: return "CL_INVALID_PROGRAM"; + case CL_INVALID_PROGRAM_EXECUTABLE: return "CL_INVALID_PROGRAM_EXECUTABLE"; + case CL_INVALID_KERNEL_NAME: return "CL_INVALID_KERNEL_NAME"; + case CL_INVALID_KERNEL_DEFINITION: return "CL_INVALID_KERNEL_DEFINITION"; + case CL_INVALID_KERNEL: return "CL_INVALID_KERNEL"; + case CL_INVALID_ARG_INDEX: return "CL_INVALID_ARG_INDEX"; + case CL_INVALID_ARG_VALUE: return "CL_INVALID_ARG_VALUE"; + case CL_INVALID_ARG_SIZE: return "CL_INVALID_ARG_SIZE"; + case CL_INVALID_KERNEL_ARGS: return "CL_INVALID_KERNEL_ARGS"; + case CL_INVALID_WORK_DIMENSION: return "CL_INVALID_WORK_DIMENSION"; + case CL_INVALID_WORK_GROUP_SIZE: return "CL_INVALID_WORK_GROUP_SIZE"; + case CL_INVALID_WORK_ITEM_SIZE: return "CL_INVALID_WORK_ITEM_SIZE"; + case CL_INVALID_GLOBAL_OFFSET: return "CL_INVALID_GLOBAL_OFFSET"; + case CL_INVALID_EVENT_WAIT_LIST: return "CL_INVALID_EVENT_WAIT_LIST"; + case CL_INVALID_EVENT: return "CL_INVALID_EVENT"; + case CL_INVALID_OPERATION: return "CL_INVALID_OPERATION"; + case CL_INVALID_GL_OBJECT: return "CL_INVALID_GL_OBJECT"; + case CL_INVALID_BUFFER_SIZE: return "CL_INVALID_BUFFER_SIZE"; + case CL_INVALID_MIP_LEVEL: return "CL_INVALID_MIP_LEVEL"; + case CL_INVALID_GLOBAL_WORK_SIZE: return "CL_INVALID_GLOBAL_WORK_SIZE"; + case CL_INVALID_PROPERTY: return "CL_INVALID_PROPERTY"; + case CL_INVALID_IMAGE_DESCRIPTOR: return "CL_INVALID_IMAGE_DESCRIPTOR"; + case CL_INVALID_COMPILER_OPTIONS: return "CL_INVALID_COMPILER_OPTIONS"; + case CL_INVALID_LINKER_OPTIONS: return "CL_INVALID_LINKER_OPTIONS"; + case CL_INVALID_DEVICE_PARTITION_COUNT: return "CL_INVALID_DEVICE_PARTITION_COUNT"; + default: return "(unknown)"; + } +} + +const char *GetChannelOrderName( cl_channel_order order ) +{ + switch( order ) + { + case CL_R: return "CL_R"; + case CL_A: return "CL_A"; + case CL_Rx: return "CL_Rx"; + case CL_RG: return "CL_RG"; + case CL_RA: return "CL_RA"; + case CL_RGx: return "CL_RGx"; + case CL_RGB: return "CL_RGB"; + case CL_RGBx: return "CL_RGBx"; + case CL_RGBA: return "CL_RGBA"; + case CL_ARGB: return "CL_ARGB"; + case CL_BGRA: return "CL_BGRA"; + case CL_INTENSITY: return "CL_INTENSITY"; + case CL_LUMINANCE: return "CL_LUMINANCE"; +#if defined CL_1RGB_APPLE + case CL_1RGB_APPLE: return "CL_1RGB_APPLE"; +#endif +#if defined CL_BGR1_APPLE + case CL_BGR1_APPLE: return "CL_BGR1_APPLE"; +#endif +#if defined CL_ABGR_APPLE + case CL_ABGR_APPLE: return "CL_ABGR_APPLE"; +#endif + case CL_DEPTH: return "CL_DEPTH"; + case CL_DEPTH_STENCIL: return "CL_DEPTH_STENCIL"; + case CL_sRGB: return "CL_sRGB"; + case CL_sRGBA: return "CL_sRGBA"; + case CL_sRGBx: return "CL_sRGBx"; + case CL_sBGRA: return "CL_sBGRA"; + case CL_ABGR: return "CL_ABGR"; + default: return NULL; + } +} + +int IsChannelOrderSupported( cl_channel_order order ) +{ + switch( order ) + { + case CL_R: + case CL_A: + case CL_Rx: + case CL_RG: + case CL_RA: + case CL_RGx: + case CL_RGB: + case CL_RGBx: + case CL_RGBA: + case CL_ARGB: + case CL_BGRA: + case CL_INTENSITY: + case CL_LUMINANCE: + case CL_ABGR: + case CL_sRGB: + case CL_sRGBx: + case CL_sBGRA: + case CL_sRGBA: + case CL_DEPTH: + return 1; +#if defined CL_1RGB_APPLE + case CL_1RGB_APPLE: + return 1; +#endif +#if defined CL_BGR1_APPLE + case CL_BGR1_APPLE: + return 1; +#endif + default: + return 0; + } +} + +const char *GetChannelTypeName( cl_channel_type type ) +{ + switch( type ) + { + case CL_SNORM_INT8: return "CL_SNORM_INT8"; + case CL_SNORM_INT16: return "CL_SNORM_INT16"; + case CL_UNORM_INT8: return "CL_UNORM_INT8"; + case CL_UNORM_INT16: return "CL_UNORM_INT16"; + case CL_UNORM_SHORT_565: return "CL_UNORM_SHORT_565"; + case CL_UNORM_SHORT_555: return "CL_UNORM_SHORT_555"; + case CL_UNORM_INT_101010: return "CL_UNORM_INT_101010"; + case CL_SIGNED_INT8: return "CL_SIGNED_INT8"; + case CL_SIGNED_INT16: return "CL_SIGNED_INT16"; + case CL_SIGNED_INT32: return "CL_SIGNED_INT32"; + case CL_UNSIGNED_INT8: return "CL_UNSIGNED_INT8"; + case CL_UNSIGNED_INT16: return "CL_UNSIGNED_INT16"; + case CL_UNSIGNED_INT32: return "CL_UNSIGNED_INT32"; + case CL_HALF_FLOAT: return "CL_HALF_FLOAT"; + case CL_FLOAT: return "CL_FLOAT"; +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: return "CL_SFIXED14_APPLE"; +#endif + case CL_UNORM_INT24: return "CL_UNORM_INT24"; + default: return NULL; + } +} + +int IsChannelTypeSupported( cl_channel_type type ) +{ + switch( type ) + { + case CL_SNORM_INT8: + case CL_SNORM_INT16: + case CL_UNORM_INT8: + case CL_UNORM_INT16: + case CL_UNORM_INT24: + case CL_UNORM_SHORT_565: + case CL_UNORM_SHORT_555: + case CL_UNORM_INT_101010: + case CL_SIGNED_INT8: + case CL_SIGNED_INT16: + case CL_SIGNED_INT32: + case CL_UNSIGNED_INT8: + case CL_UNSIGNED_INT16: + case CL_UNSIGNED_INT32: + case CL_HALF_FLOAT: + case CL_FLOAT: + return 1; +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: + return 1; +#endif + default: + return 0; + } +} + +const char *GetAddressModeName( cl_addressing_mode mode ) +{ + switch( mode ) + { + case CL_ADDRESS_NONE: return "CL_ADDRESS_NONE"; + case CL_ADDRESS_CLAMP_TO_EDGE: return "CL_ADDRESS_CLAMP_TO_EDGE"; + case CL_ADDRESS_CLAMP: return "CL_ADDRESS_CLAMP"; + case CL_ADDRESS_REPEAT: return "CL_ADDRESS_REPEAT"; + case CL_ADDRESS_MIRRORED_REPEAT: return "CL_ADDRESS_MIRRORED_REPEAT"; + default: return NULL; + } +} + +const char *GetDeviceTypeName( cl_device_type type ) +{ + switch( type ) + { + case CL_DEVICE_TYPE_GPU: return "CL_DEVICE_TYPE_GPU"; + case CL_DEVICE_TYPE_CPU: return "CL_DEVICE_TYPE_CPU"; + case CL_DEVICE_TYPE_ACCELERATOR: return "CL_DEVICE_TYPE_ACCELERATOR"; + case CL_DEVICE_TYPE_ALL: return "CL_DEVICE_TYPE_ALL"; + default: return NULL; + } +} + +const char *GetDataVectorString( void *dataBuffer, size_t typeSize, size_t vecSize, char *buffer ) +{ + static char scratch[ 1024 ]; + size_t i, j; + + if( buffer == NULL ) + buffer = scratch; + + unsigned char *p = (unsigned char *)dataBuffer; + char *bPtr; + + buffer[ 0 ] = 0; + bPtr = buffer; + for( i = 0; i < vecSize; i++ ) + { + if( i > 0 ) + { + bPtr[ 0 ] = ' '; + bPtr++; + } + for( j = 0; j < typeSize; j++ ) + { + sprintf( bPtr, "%02x", (unsigned int)p[ typeSize - j - 1 ] ); + bPtr += 2; + } + p += typeSize; + } + bPtr[ 0 ] = 0; + + return buffer; +} + +#ifndef MAX +#define MAX( _a, _b ) ((_a) > (_b) ? (_a) : (_b)) +#endif + +#if defined( _MSC_VER ) +#define scalbnf(_a, _i ) ldexpf( _a, _i ) +#define scalbn(_a, _i ) ldexp( _a, _i ) +#define scalbnl(_a, _i ) ldexpl( _a, _i ) +#endif + +static float Ulp_Error_Half_Float( float test, double reference ); +static inline float half2float( cl_ushort half ); + +// taken from math tests +#define HALF_MIN_EXP -13 +#define HALF_MANT_DIG 11 +static float Ulp_Error_Half_Float( float test, double reference ) +{ + union{ double d; uint64_t u; }u; u.d = reference; + + // Note: This function presumes that someone has already tested whether the result is correctly, + // rounded before calling this function. That test: + // + // if( (float) reference == test ) + // return 0.0f; + // + // would ensure that cases like fabs(reference) > FLT_MAX are weeded out before we get here. + // Otherwise, we'll return inf ulp error here, for what are otherwise correctly rounded + // results. + + double testVal = test; + if( u.u & 0x000fffffffffffffULL ) + { // Non-power of two and NaN + if( isnan( reference ) && isnan( test ) ) + return 0.0f; // if we are expecting a NaN, any NaN is fine + + // The unbiased exponent of the ulp unit place + int ulp_exp = HALF_MANT_DIG - 1 - MAX( ilogb( reference), HALF_MIN_EXP-1 ); + + // Scale the exponent of the error + return (float) scalbn( testVal - reference, ulp_exp ); + } + + if( isinf( reference ) ) + { + if( (double) test == reference ) + return 0.0f; + + return (float) (testVal - reference ); + } + + // reference is a normal power of two or a zero + int ulp_exp = HALF_MANT_DIG - 1 - MAX( ilogb( reference) - 1, HALF_MIN_EXP-1 ); + + // Scale the exponent of the error + return (float) scalbn( testVal - reference, ulp_exp ); +} + +// Taken from vLoadHalf test +static inline float half2float( cl_ushort us ) +{ + uint32_t u = us; + uint32_t sign = (u << 16) & 0x80000000; + int32_t exponent = (u & 0x7c00) >> 10; + uint32_t mantissa = (u & 0x03ff) << 13; + union{ unsigned int u; float f;}uu; + + if( exponent == 0 ) + { + if( mantissa == 0 ) + return sign ? -0.0f : 0.0f; + + int shift = __builtin_clz( mantissa ) - 8; + exponent -= shift-1; + mantissa <<= shift; + mantissa &= 0x007fffff; + } + else + if( exponent == 31) + { + uu.u = mantissa | sign; + if( mantissa ) + uu.u |= 0x7fc00000; + else + uu.u |= 0x7f800000; + + return uu.f; + } + + exponent += 127 - 15; + exponent <<= 23; + + exponent |= mantissa; + uu.u = exponent | sign; + + return uu.f; +} + +float Ulp_Error_Half( cl_ushort test, float reference ) +{ + return Ulp_Error_Half_Float( half2float(test), reference ); +} + + +float Ulp_Error( float test, double reference ) +{ + union{ double d; uint64_t u; }u; u.d = reference; + double testVal = test; + + // Note: This function presumes that someone has already tested whether the result is correctly, + // rounded before calling this function. That test: + // + // if( (float) reference == test ) + // return 0.0f; + // + // would ensure that cases like fabs(reference) > FLT_MAX are weeded out before we get here. + // Otherwise, we'll return inf ulp error here, for what are otherwise correctly rounded + // results. + + + if( isinf( reference ) ) + { + if( testVal == reference ) + return 0.0f; + + return (float) (testVal - reference ); + } + + if( isinf( testVal) ) + { // infinite test value, but finite (but possibly overflowing in float) reference. + // + // The function probably overflowed prematurely here. Formally, the spec says this is + // an infinite ulp error and should not be tolerated. Unfortunately, this would mean + // that the internal precision of some half_pow implementations would have to be 29+ bits + // at half_powr( 0x1.fffffep+31, 4) to correctly determine that 4*log2( 0x1.fffffep+31 ) + // is not exactly 128.0. You might represent this for example as 4*(32 - ~2**-24), which + // after rounding to single is 4*32 = 128, which will ultimately result in premature + // overflow, even though a good faith representation would be correct to within 2**-29 + // interally. + + // In the interest of not requiring the implementation go to extraordinary lengths to + // deliver a half precision function, we allow premature overflow within the limit + // of the allowed ulp error. Towards, that end, we "pretend" the test value is actually + // 2**128, the next value that would appear in the number line if float had sufficient range. + testVal = copysign( MAKE_HEX_DOUBLE(0x1.0p128, 0x1LL, 128), testVal ); + + // Note that the same hack may not work in long double, which is not guaranteed to have + // more range than double. It is not clear that premature overflow should be tolerated for + // double. + } + + if( u.u & 0x000fffffffffffffULL ) + { // Non-power of two and NaN + if( isnan( reference ) && isnan( test ) ) + return 0.0f; // if we are expecting a NaN, any NaN is fine + + // The unbiased exponent of the ulp unit place + int ulp_exp = FLT_MANT_DIG - 1 - MAX( ilogb( reference), FLT_MIN_EXP-1 ); + + // Scale the exponent of the error + return (float) scalbn( testVal - reference, ulp_exp ); + } + + // reference is a normal power of two or a zero + // The unbiased exponent of the ulp unit place + int ulp_exp = FLT_MANT_DIG - 1 - MAX( ilogb( reference) - 1, FLT_MIN_EXP-1 ); + + // Scale the exponent of the error + return (float) scalbn( testVal - reference, ulp_exp ); +} + +float Ulp_Error_Double( double test, long double reference ) +{ + // Deal with long double = double + // On most systems long double is a higher precision type than double. They provide either + // a 80-bit or greater floating point type, or they provide a head-tail double double format. + // That is sufficient to represent the accuracy of a floating point result to many more bits + // than double and we can calculate sub-ulp errors. This is the standard system for which this + // test suite is designed. + // + // On some systems double and long double are the same thing. Then we run into a problem, + // because our representation of the infinitely precise result (passed in as reference above) + // can be off by as much as a half double precision ulp itself. In this case, we inflate the + // reported error by half an ulp to take this into account. A more correct and permanent fix + // would be to undertake refactoring the reference code to return results in this format: + // + // typedef struct DoubleReference + // { // true value = correctlyRoundedResult + ulps * ulp(correctlyRoundedResult) (infinitely precise) + // double correctlyRoundedResult; // as best we can + // double ulps; // plus a fractional amount to account for the difference + // }DoubleReference; // between infinitely precise result and correctlyRoundedResult, in units of ulps. + // + // This would provide a useful higher-than-double precision format for everyone that we can use, + // and would solve a few problems with representing absolute errors below DBL_MIN and over DBL_MAX for systems + // that use a head to tail double double for long double. + + // Note: This function presumes that someone has already tested whether the result is correctly, + // rounded before calling this function. That test: + // + // if( (float) reference == test ) + // return 0.0f; + // + // would ensure that cases like fabs(reference) > FLT_MAX are weeded out before we get here. + // Otherwise, we'll return inf ulp error here, for what are otherwise correctly rounded + // results. + + + int x; + long double testVal = test; + if( 0.5L != frexpl( reference, &x) ) + { // Non-power of two and NaN + if( isinf( reference ) ) + { + if( testVal == reference ) + return 0.0f; + + return (float) ( testVal - reference ); + } + + if( isnan( reference ) && isnan( test ) ) + return 0.0f; // if we are expecting a NaN, any NaN is fine + + // The unbiased exponent of the ulp unit place + int ulp_exp = DBL_MANT_DIG - 1 - MAX( ilogbl( reference), DBL_MIN_EXP-1 ); + + // Scale the exponent of the error + float result = (float) scalbnl( testVal - reference, ulp_exp ); + + // account for rounding error in reference result on systems that do not have a higher precision floating point type (see above) + if( sizeof(long double) == sizeof( double ) ) + result += copysignf( 0.5f, result); + + return result; + + } + + // reference is a normal power of two or a zero + // The unbiased exponent of the ulp unit place + int ulp_exp = DBL_MANT_DIG - 1 - MAX( ilogbl( reference) - 1, DBL_MIN_EXP-1 ); + + // Scale the exponent of the error + float result = (float) scalbnl( testVal - reference, ulp_exp ); + + // account for rounding error in reference result on systems that do not have a higher precision floating point type (see above) + if( sizeof(long double) == sizeof( double ) ) + result += copysignf( 0.5f, result); + + return result; +} + +cl_int OutputBuildLogs(cl_program program, cl_uint num_devices, cl_device_id *device_list) +{ + int error; + size_t size_ret; + + // Does the program object exist? + if (program != NULL) { + + // Was the number of devices given + if (num_devices == 0) { + + // If zero devices were specified then allocate and query the device list from the context + cl_context context; + error = clGetProgramInfo(program, CL_PROGRAM_CONTEXT, sizeof(context), &context, NULL); + test_error( error, "Unable to query program's context" ); + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &size_ret); + test_error( error, "Unable to query context's device size" ); + num_devices = size_ret / sizeof(cl_device_id); + device_list = (cl_device_id *) malloc(size_ret); + if (device_list == NULL) { + print_error( error, "malloc failed" ); + return CL_OUT_OF_HOST_MEMORY; + } + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, size_ret, device_list, NULL); + test_error( error, "Unable to query context's devices" ); + + } + + // For each device in the device_list + unsigned int i; + for (i = 0; i < num_devices; i++) { + + // Get the build status + cl_build_status build_status; + error = clGetProgramBuildInfo(program, + device_list[i], + CL_PROGRAM_BUILD_STATUS, + sizeof(build_status), + &build_status, + &size_ret); + test_error( error, "Unable to query build status" ); + + // If the build failed then log the status, and allocate the build log, log it and free it + if (build_status != CL_BUILD_SUCCESS) { + + log_error("ERROR: CL_PROGRAM_BUILD_STATUS=%d\n", (int) build_status); + error = clGetProgramBuildInfo(program, device_list[i], CL_PROGRAM_BUILD_LOG, 0, NULL, &size_ret); + test_error( error, "Unable to query build log size" ); + char *build_log = (char *) malloc(size_ret); + error = clGetProgramBuildInfo(program, device_list[i], CL_PROGRAM_BUILD_LOG, size_ret, build_log, &size_ret); + test_error( error, "Unable to query build log" ); + log_error("ERROR: CL_PROGRAM_BUILD_LOG:\n%s\n", build_log); + free(build_log); + + } + + } + + // Was the number of devices given + if (num_devices == 0) { + + // If zero devices were specified then free the device list + free(device_list); + + } + + } + + return CL_SUCCESS; +} + +const char * subtests_requiring_opencl_1_2[] = { + "device_partition_equally", + "device_partition_by_counts", + "device_partition_by_affinity_domain_numa", + "device_partition_by_affinity_domain_l4_cache", + "device_partition_by_affinity_domain_l3_cache", + "device_partition_by_affinity_domain_l2_cache", + "device_partition_by_affinity_domain_l1_cache", + "device_partition_by_affinity_domain_next_partitionable", + "device_partition_all", + "buffer_fill_int", + "buffer_fill_uint", + "buffer_fill_short", + "buffer_fill_ushort", + "buffer_fill_char", + "buffer_fill_uchar", + "buffer_fill_long", + "buffer_fill_ulong", + "buffer_fill_float", + "buffer_fill_struct", + "test_mem_host_write_only_buffer", + "test_mem_host_write_only_subbuffer", + "test_mem_host_no_access_buffer", + "test_mem_host_no_access_subbuffer", + "test_mem_host_read_only_image", + "test_mem_host_write_only_image", + "test_mem_host_no_access_image", + // CL_MEM_HOST_{READ|WRITE}_ONLY api/ + "get_buffer_info", + "get_image1d_info", + "get_image1d_array_info", + "get_image2d_array_info", + // gl/ + "images_read_1D", + "images_write_1D", + "images_1D_getinfo", + "images_read_1Darray", + "images_write_1Darray", + "images_1Darray_getinfo", + "images_read_2Darray", + "images_write_2Darray", + "images_2Darray_getinfo", + "buffer_migrate", + "image_migrate", + // compiler/ + "load_program_source", + "load_multistring_source", + "load_two_kernel_source", + "load_null_terminated_source", + "load_null_terminated_multi_line_source", + "load_null_terminated_partial_multi_line_source", + "load_discreet_length_source", + "get_program_source", + "get_program_build_info", + "get_program_info", + "large_compile", + "async_build", + "options_build_optimizations", + "options_build_macro", + "options_build_macro_existence", + "options_include_directory", + "options_denorm_cache", + "preprocessor_define_udef", + "preprocessor_include", + "preprocessor_line_error", + "preprocessor_pragma", + "compiler_defines_for_extensions", + "image_macro", + "simple_compile_only", + "simple_static_compile_only", + "simple_extern_compile_only", + "simple_compile_with_callback", + "simple_embedded_header_compile", + "simple_link_only", + "two_file_regular_variable_access", + "two_file_regular_struct_access", + "two_file_regular_function_access", + "simple_link_with_callback", + "simple_embedded_header_link", + "execute_after_simple_compile_and_link", + "execute_after_simple_compile_and_link_no_device_info", + "execute_after_simple_compile_and_link_with_defines", + "execute_after_simple_compile_and_link_with_callbacks", + "execute_after_simple_library_with_link", + "execute_after_two_file_link", + "execute_after_two_file_link", + "execute_after_embedded_header_link", + "execute_after_included_header_link", + "execute_after_serialize_reload_object", + "execute_after_serialize_reload_library", + "simple_library_only", + "simple_library_with_callback", + "simple_library_with_link", + "two_file_link", + "multi_file_libraries", + "multiple_files", + "multiple_libraries", + "multiple_files_multiple_libraries", + "multiple_embedded_headers", + "program_binary_type", + "compile_and_link_status_options_log", + // CL_PROGRAM_NUM_KERNELS, in api/ + "get_kernel_arg_info", + "create_kernels_in_program", + // clEnqueue..WithWaitList, in events/ + "event_enqueue_marker_with_event_list", + "event_enqueue_barrier_with_event_list", + "popcount" +}; + +const char * subtests_to_skip_with_offline_compiler[] = { + "get_kernel_arg_info", + "binary_create", + "load_program_source", + "load_multistring_source", + "load_two_kernel_source", + "load_null_terminated_source", + "load_null_terminated_multi_line_source", + "load_null_terminated_partial_multi_line_source", + "load_discreet_length_source", + "get_program_source", + "get_program_build_info", + "options_build_optimizations", + "options_build_macro", + "options_build_macro_existence", + "options_include_directory", + "options_denorm_cache", + "preprocessor_define_udef", + "preprocessor_include", + "preprocessor_line_error", + "preprocessor_pragma", + "compiler_defines_for_extensions", + "image_macro", + "simple_extern_compile_only", + "simple_embedded_header_compile", + "two_file_regular_variable_access", + "two_file_regular_struct_access", + "two_file_regular_function_access", + "simple_embedded_header_link", + "execute_after_simple_compile_and_link_with_defines", + "execute_after_simple_compile_and_link_with_callbacks", + "execute_after_embedded_header_link", + "execute_after_included_header_link", + "multi_file_libraries", + "multiple_files", + "multiple_libraries", + "multiple_files_multiple_libraries", + "multiple_embedded_headers", + "program_binary_type", + "compile_and_link_status_options_log", +}; + +int check_opencl_version_with_testname(const char *subtestname, cl_device_id device) +{ + int nRequiring12 = sizeof(subtests_requiring_opencl_1_2)/sizeof(char *); + size_t i; + for(i=0; i < nRequiring12; ++i) { + if(!strcmp(subtestname, subtests_requiring_opencl_1_2[i])) { + return check_opencl_version(device, 1, 2); + } + } + return 0; +} + +int check_opencl_version(cl_device_id device, cl_uint requestedMajorVersion, cl_uint requestedMinorVersion) { + int error; + char device_version[1024]; + cl_uint majorVersion = 0, minorVersion = 0; + const char * required_version_ocl_12="OpenCL 1.2 "; + + memset( device_version, 0, sizeof( device_version ) ); + error = clGetDeviceInfo( device, CL_DEVICE_VERSION, sizeof(device_version), device_version, NULL ); + test_error(error, "unable to get CL_DEVICE_VERSION"); + + if ( strncmp( device_version, "OpenCL 1.2", 10 ) == 0 && ( device_version[ 10 ] == 0 || device_version[ 10 ] == ' ' ) ) { + majorVersion = 1; + minorVersion = 2; + } else if ( strncmp( device_version, "OpenCL 1.1", 10 ) == 0 && ( device_version[ 10 ] == 0 || device_version[ 10 ] == ' ' ) ) { + majorVersion = 1; + minorVersion = 1; + } else if ( strncmp( device_version, "OpenCL 2.0", 10 ) == 0 && ( device_version[ 10 ] == 0 || device_version[ 10 ] == ' ' ) ) { + majorVersion = 2; + minorVersion = 0; + } else if ( strncmp( device_version, "OpenCL 2.1", 10 ) == 0 && ( device_version[ 10 ] == 0 || device_version[ 10 ] == ' ' ) ) { + majorVersion = 2; + minorVersion = 1; + } else { + log_error( "ERROR: Unexpected version string: `%s'.\n", device_version ); + return 1; + }; + + if (majorVersion >= requestedMajorVersion) + return 0; + + if (minorVersion >= requestedMinorVersion) + return 0; + + return 1; +} + +int check_functions_for_offline_compiler(const char *subtestname, cl_device_id device) +{ + if(gOfflineCompiler) + { + int nNotRequiredWithOfflineCompiler = sizeof(subtests_to_skip_with_offline_compiler)/sizeof(char *); + size_t i; + for(i=0; i < nNotRequiredWithOfflineCompiler; ++i) { + if(!strcmp(subtestname, subtests_to_skip_with_offline_compiler[i])) { + return 1; + } + } + } + return 0; +} diff --git a/test_common/harness/errorHelpers.h b/test_common/harness/errorHelpers.h new file mode 100644 index 00000000..3612c8c7 --- /dev/null +++ b/test_common/harness/errorHelpers.h @@ -0,0 +1,164 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _errorHelpers_h +#define _errorHelpers_h + +#ifdef __APPLE__ +#include +#else +#include +#endif +#include +#ifdef __cplusplus +extern "C" { +#endif + +#define LOWER_IS_BETTER 0 +#define HIGHER_IS_BETTER 1 + +// If USE_ATF is defined, all log_error and log_info calls can be routed to test library +// functions as described below. This is helpful for integration into an automated testing +// system. +#if USE_ATF +// export BUILD_WITH_ATF=1 + #include + #define test_start() ATFTestStart() + #define log_info ATFLogInfo + #define log_error ATFLogError + #define log_missing_feature ATFLogMissingFeature + #define log_perf(_number, _higherBetter, _numType, _format, ...) ATFLogPerformanceNumber(_number, _higherBetter, _numType, _format, ##__VA_ARGS__) + #define test_finish() ATFTestFinish() + #define vlog_perf(_number, _higherBetter, _numType, _format, ...) ATFLogPerformanceNumber(_number, _higherBetter, _numType, _format,##__VA_ARGS__) + #define vlog ATFLogInfo + #define vlog_error ATFLogError +#else + #include + #define test_start() + #define log_info printf + #define log_error printf + #define log_missing_feature printf + #define log_perf(_number, _higherBetter, _numType, _format, ...) printf("Performance Number " _format " (in %s, %s): %g\n",##__VA_ARGS__, _numType, \ + _higherBetter?"higher is better":"lower is better", _number ) + #define test_finish() + #define vlog_perf(_number, _higherBetter, _numType, _format, ...) printf("Performance Number " _format " (in %s, %s): %g\n",##__VA_ARGS__, _numType, \ + _higherBetter?"higher is better":"lower is better" , _number) + #ifdef _WIN32 + #ifdef __MINGW32__ + // Use __mingw_printf since it supports "%a" format specifier + #define vlog __mingw_printf + #define vlog_error __mingw_printf + #else + // Use home-baked function that treats "%a" as "%f" + static int vlog_win32(const char *format, ...); + #define vlog vlog_win32 + #define vlog_error vlog_win32 + #endif + #else + #define vlog_error printf + #define vlog printf + #endif +#endif + +#define ct_assert(b) ct_assert_i(b, __LINE__) +#define ct_assert_i(b, line) ct_assert_ii(b, line) +#define ct_assert_ii(b, line) int _compile_time_assertion_on_line_##line[b ? 1 : -1]; + +#define test_error(errCode,msg) test_error_ret(errCode,msg,errCode) +#define test_error_ret(errCode,msg,retValue) { if( errCode != CL_SUCCESS ) { print_error( errCode, msg ); return retValue ; } } +#define print_error(errCode,msg) log_error( "ERROR: %s! (%s from %s:%d)\n", msg, IGetErrorString( errCode ), __FILE__, __LINE__ ); + +#define test_missing_feature(errCode, msg) test_missing_feature_ret(errCode, msg, errCode) +// this macro should always return CL_SUCCESS, but print the missing feature message +#define test_missing_feature_ret(errCode,msg,retValue) { if( errCode != CL_SUCCESS ) { print_missing_feature( errCode, msg ); return CL_SUCCESS ; } } +#define print_missing_feature(errCode, msg) log_missing_feature("ERROR: Subtest %s tests a feature not supported by the device version! (from %s:%d)\n", msg, __FILE__, __LINE__ ); + +#define test_missing_support_offline_cmpiler(errCode, msg) test_missing_support_offline_cmpiler_ret(errCode, msg, errCode) +// this macro should always return CL_SUCCESS, but print the skip message on test not supported with offline compiler +#define test_missing_support_offline_cmpiler_ret(errCode,msg,retValue) { if( errCode != CL_SUCCESS ) { log_info( "INFO: Subtest %s tests is not supported in offline compiler execution path! (from %s:%d)\n", msg, __FILE__, __LINE__ ); return CL_SUCCESS ; } } + +// expected error code vs. what we got +#define test_failure_error(errCode, expectedErrCode, msg) test_failure_error_ret(errCode, expectedErrCode, msg, errCode != expectedErrCode) +#define test_failure_error_ret(errCode, expectedErrCode, msg, retValue) { if( errCode != expectedErrCode ) { print_failure_error( errCode, expectedErrCode, msg ); return retValue ; } } +#define print_failure_error(errCode, expectedErrCode, msg) log_error( "ERROR: %s! (Got %s, expected %s from %s:%d)\n", msg, IGetErrorString( errCode ), IGetErrorString( expectedErrCode ), __FILE__, __LINE__ ); +#define test_failure_warning(errCode, expectedErrCode, msg) test_failure_warning_ret(errCode, expectedErrCode, msg, errCode != expectedErrCode) +#define test_failure_warning_ret(errCode, expectedErrCode, msg, retValue) { if( errCode != expectedErrCode ) { print_failure_warning( errCode, expectedErrCode, msg ); warnings++ ; } } +#define print_failure_warning(errCode, expectedErrCode, msg) log_error( "WARNING: %s! (Got %s, expected %s from %s:%d)\n", msg, IGetErrorString( errCode ), IGetErrorString( expectedErrCode ), __FILE__, __LINE__ ); + +extern const char *IGetErrorString( int clErrorCode ); + +extern float Ulp_Error_Half( cl_ushort test, float reference ); +extern float Ulp_Error( float test, double reference ); +extern float Ulp_Error_Double( double test, long double reference ); + +extern const char *GetChannelTypeName( cl_channel_type type ); +extern int IsChannelTypeSupported( cl_channel_type type ); +extern const char *GetChannelOrderName( cl_channel_order order ); +extern int IsChannelOrderSupported( cl_channel_order order ); +extern const char *GetAddressModeName( cl_addressing_mode mode ); + +extern const char *GetDeviceTypeName( cl_device_type type ); +int check_opencl_version_with_testname(const char *subtestname, cl_device_id device); +int check_opencl_version(cl_device_id device, cl_uint requestedMajorVersion, cl_uint requestedMinorVersion); +int check_functions_for_offline_compiler(const char *subtestname, cl_device_id device); + +// NON-REENTRANT UNLESS YOU PROVIDE A BUFFER PTR (pass null to use static storage, but it's not reentrant then!) +extern const char *GetDataVectorString( void *dataBuffer, size_t typeSize, size_t vecSize, char *buffer ); + +#if defined (_WIN32) && !defined(__MINGW32__) +#include +#include +#include +static int vlog_win32(const char *format, ...) +{ + const char *new_format = format; + + if (strstr(format, "%a")) { + char *temp; + if ((temp = strdup(format)) == NULL) { + printf("vlog_win32: Failed to allocate memory for strdup\n"); + return -1; + } + new_format = temp; + while (*temp) { + // replace %a with %f + if ((*temp == '%') && (*(temp+1) == 'a')) { + *(temp+1) = 'f'; + } + temp++; + } + } + + va_list args; + va_start(args, format); + vprintf(new_format, args); + va_end(args); + + if (new_format != format) { + free((void*)new_format); + } + + return 0; +} +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // _errorHelpers_h + + diff --git a/test_common/harness/fpcontrol.h b/test_common/harness/fpcontrol.h new file mode 100644 index 00000000..4835db45 --- /dev/null +++ b/test_common/harness/fpcontrol.h @@ -0,0 +1,104 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _fpcontrol_h +#define _fpcontrol_h + +// In order to get tests for correctly rounded operations (e.g. multiply) to work properly we need to be able to set the reference hardware +// to FTZ mode if the device hardware is running in that mode. We have explored all other options short of writing correctly rounded operations +// in integer code, and have found this is the only way to correctly verify operation. +// +// Non-Apple implementations will need to provide their own implentation for these features. If the reference hardware and device are both +// running in the same state (either FTZ or IEEE compliant modes) then these functions may be empty. If the device is running in non-default +// rounding mode (e.g. round toward zero), then these functions should also set the reference device into that rounding mode. +#if defined( __APPLE__ ) || defined( _MSC_VER ) || defined( __linux__ ) || defined (__MINGW32__) + typedef int FPU_mode_type; +#if defined( __i386__ ) || defined( __x86_64__ ) || defined( _MSC_VER ) || defined( __MINGW32__ ) + #include +#elif defined( __PPC__ ) + #include + extern __thread fpu_control_t fpu_control; +#endif + // Set the reference hardware floating point unit to FTZ mode + static inline void ForceFTZ( FPU_mode_type *mode ) + { +#if defined( __i386__ ) || defined( __x86_64__ ) || defined( _MSC_VER ) || defined (__MINGW32__) + *mode = _mm_getcsr(); + _mm_setcsr( *mode | 0x8040); +#elif defined( __PPC__ ) + *mode = fpu_control; + fpu_control |= _FPU_MASK_NI; +#elif defined ( __arm__ ) + unsigned fpscr; + __asm__ volatile ("fmrx %0, fpscr" : "=r"(fpscr)); + *mode = fpscr; + __asm__ volatile ("fmxr fpscr, %0" :: "r"(fpscr | (1U << 24))); + // Add 64 bit support +#elif defined (__aarch64__) + unsigned fpscr; + __asm__ volatile ("mrs %0, fpcr" : "=r"(fpscr)); + *mode = fpscr; + __asm__ volatile ("msr fpcr, %0" :: "r"(fpscr | (1U << 24))); +#else + #error ForceFTZ needs an implentation +#endif + } + + // Disable the denorm flush to zero + static inline void DisableFTZ( FPU_mode_type *mode ) + { +#if defined( __i386__ ) || defined( __x86_64__ ) || defined( _MSC_VER ) || defined (__MINGW32__) + *mode = _mm_getcsr(); + _mm_setcsr( *mode & ~0x8040); +#elif defined( __PPC__ ) + *mode = fpu_control; + fpu_control &= ~_FPU_MASK_NI; +#elif defined ( __arm__ ) + unsigned fpscr; + __asm__ volatile ("fmrx %0, fpscr" : "=r"(fpscr)); + *mode = fpscr; + __asm__ volatile ("fmxr fpscr, %0" :: "r"(fpscr & ~(1U << 24))); + // Add 64 bit support +#elif defined (__aarch64__) + unsigned fpscr; + __asm__ volatile ("mrs %0, fpcr" : "=r"(fpscr)); + *mode = fpscr; + __asm__ volatile ("msr fpcr, %0" :: "r"(fpscr & ~(1U << 24))); +#else + #error DisableFTZ needs an implentation +#endif + } + + // Restore the reference hardware to floating point state indicated by *mode + static inline void RestoreFPState( FPU_mode_type *mode ) + { +#if defined( __i386__ ) || defined( __x86_64__ ) || defined( _MSC_VER ) || defined (__MINGW32__) + _mm_setcsr( *mode ); +#elif defined( __PPC__) + fpu_control = *mode; +#elif defined (__arm__) + __asm__ volatile ("fmxr fpscr, %0" :: "r"(*mode)); + // Add 64 bit support +#elif defined (__aarch64__) + __asm__ volatile ("msr fpcr, %0" :: "r"(*mode)); +#else + #error RestoreFPState needs an implementation +#endif + } +#else + #error ForceFTZ and RestoreFPState need implentations +#endif + +#endif diff --git a/test_common/harness/genericThread.cpp b/test_common/harness/genericThread.cpp new file mode 100644 index 00000000..2b742fa3 --- /dev/null +++ b/test_common/harness/genericThread.cpp @@ -0,0 +1,53 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "genericThread.h" + +#if defined(_WIN32) +#include +#else // !_WIN32 +#include +#endif + +void * genericThread::IStaticReflector( void * data ) +{ + genericThread *t = (genericThread *)data; + return t->IRun(); +} + +bool genericThread::Start( void ) +{ +#if defined(_WIN32) + mHandle = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) IStaticReflector, this, 0, NULL ); + return ( mHandle != NULL ); +#else // !_WIN32 + int error = pthread_create( (pthread_t*)&mHandle, NULL, IStaticReflector, (void *)this ); + return ( error == 0 ); +#endif // !_WIN32 +} + +void * genericThread::Join( void ) +{ +#if defined(_WIN32) + WaitForSingleObject( (HANDLE)mHandle, INFINITE ); + return NULL; +#else // !_WIN32 + void * retVal; + int error = pthread_join( (pthread_t)mHandle, &retVal ); + if( error != 0 ) + retVal = NULL; + return retVal; +#endif // !_WIN32 +} diff --git a/test_common/harness/genericThread.h b/test_common/harness/genericThread.h new file mode 100644 index 00000000..168b7407 --- /dev/null +++ b/test_common/harness/genericThread.h @@ -0,0 +1,42 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _genericThread_h +#define _genericThread_h + +#include + +class genericThread +{ + public: + + virtual ~genericThread() {} + + bool Start( void ); + void * Join( void ); + + protected: + + virtual void * IRun( void ) = 0; + + private: + + void* mHandle; + + static void * IStaticReflector( void * data ); +}; + +#endif // _genericThread_h + diff --git a/test_common/harness/imageHelpers.cpp b/test_common/harness/imageHelpers.cpp new file mode 100644 index 00000000..3b47e271 --- /dev/null +++ b/test_common/harness/imageHelpers.cpp @@ -0,0 +1,3857 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "imageHelpers.h" +#include +#if defined( __APPLE__ ) +#include +#endif +#if !defined (_WIN32) && !defined(__APPLE__) +#include +#endif + +int gTestCount = 0; +int gTestFailure = 0; +RoundingMode gFloatToHalfRoundingMode = kDefaultRoundingMode; + +static cl_ushort float2half_rte( float f ); +static cl_ushort float2half_rtz( float f ); + +double +sRGBmap(float fc) +{ + double c = (double)fc; + +#if !defined (_WIN32) + if (isnan(c)) + c = 0.0; +#else + if (_isnan(c)) + c = 0.0; +#endif + + if (c > 1.0) + c = 1.0; + else if (c < 0.0) + c = 0.0; + else if (c < 0.0031308) + c = 12.92 * c; + else + c = (1055.0/1000.0) * pow(c, 5.0/12.0) - (55.0/1000.0); + + return c * 255.0; +} + +double +sRGBunmap(float fc) +{ + double c = (double)fc; + double result; + + if (c <= 0.04045) + result = c / 12.92; + else + result = pow((c + 0.055) / 1.055, 2.4); + + return result; +} + + +size_t get_format_type_size( const cl_image_format *format ) +{ + return get_channel_data_type_size( format->image_channel_data_type ); +} + +size_t get_channel_data_type_size( cl_channel_type channelType ) +{ + switch( channelType ) + { + case CL_SNORM_INT8: + case CL_UNORM_INT8: + case CL_SIGNED_INT8: + case CL_UNSIGNED_INT8: + return 1; + + case CL_SNORM_INT16: + case CL_UNORM_INT16: + case CL_SIGNED_INT16: + case CL_UNSIGNED_INT16: + case CL_HALF_FLOAT: +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: +#endif + return sizeof( cl_short ); + + case CL_SIGNED_INT32: + case CL_UNSIGNED_INT32: + return sizeof( cl_int ); + + case CL_UNORM_SHORT_565: + case CL_UNORM_SHORT_555: +#ifdef OBSOLETE_FORAMT + case CL_UNORM_SHORT_565_REV: + case CL_UNORM_SHORT_555_REV: +#endif + return 2; + +#ifdef OBSOLETE_FORAMT + case CL_UNORM_INT_8888: + case CL_UNORM_INT_8888_REV: + return 4; +#endif + + case CL_UNORM_INT_101010: +#ifdef OBSOLETE_FORAMT + case CL_UNORM_INT_101010_REV: +#endif + return 4; + + case CL_FLOAT: + return sizeof( cl_float ); + + default: + return 0; + } +} + +size_t get_format_channel_count( const cl_image_format *format ) +{ + return get_channel_order_channel_count( format->image_channel_order ); +} + +size_t get_channel_order_channel_count( cl_channel_order order ) +{ + switch( order ) + { + case CL_R: + case CL_A: + case CL_Rx: + case CL_INTENSITY: + case CL_LUMINANCE: + case CL_DEPTH: + case CL_DEPTH_STENCIL: + return 1; + + case CL_RG: + case CL_RA: + case CL_RGx: + return 2; + + case CL_RGB: + case CL_RGBx: + case CL_sRGB: + case CL_sRGBx: + return 3; + + case CL_RGBA: + case CL_ARGB: + case CL_BGRA: + case CL_sRGBA: + case CL_sBGRA: + case CL_ABGR: +#ifdef CL_1RGB_APPLE + case CL_1RGB_APPLE: +#endif +#ifdef CL_BGR1_APPLE + case CL_BGR1_APPLE: +#endif +#ifdef CL_ABGR_APPLE + case CL_ABGR_APPLE: +#endif + return 4; + + default: + log_error("%s does not support 0x%x\n",__FUNCTION__,order); + return 0; + } +} + +cl_channel_type get_channel_type_from_name( const char *name ) +{ + struct { + cl_channel_type type; + const char *name; + } typeNames[] = { + { CL_SNORM_INT8, "CL_SNORM_INT8" }, + { CL_SNORM_INT16, "CL_SNORM_INT16" }, + { CL_UNORM_INT8, "CL_UNORM_INT8" }, + { CL_UNORM_INT16, "CL_UNORM_INT16" }, + { CL_UNORM_INT24, "CL_UNORM_INT24" }, + { CL_UNORM_SHORT_565, "CL_UNORM_SHORT_565" }, + { CL_UNORM_SHORT_555, "CL_UNORM_SHORT_555" }, + { CL_UNORM_INT_101010, "CL_UNORM_INT_101010" }, + { CL_SIGNED_INT8, "CL_SIGNED_INT8" }, + { CL_SIGNED_INT16, "CL_SIGNED_INT16" }, + { CL_SIGNED_INT32, "CL_SIGNED_INT32" }, + { CL_UNSIGNED_INT8, "CL_UNSIGNED_INT8" }, + { CL_UNSIGNED_INT16, "CL_UNSIGNED_INT16" }, + { CL_UNSIGNED_INT32, "CL_UNSIGNED_INT32" }, + { CL_HALF_FLOAT, "CL_HALF_FLOAT" }, + { CL_FLOAT, "CL_FLOAT" }, +#ifdef CL_SFIXED14_APPLE + { CL_SFIXED14_APPLE, "CL_SFIXED14_APPLE" } +#endif + }; + for( size_t i = 0; i < sizeof( typeNames ) / sizeof( typeNames[ 0 ] ); i++ ) + { + if( strcmp( typeNames[ i ].name, name ) == 0 || strcmp( typeNames[ i ].name + 3, name ) == 0 ) + return typeNames[ i ].type; + } + return (cl_channel_type)-1; +} + +cl_channel_order get_channel_order_from_name( const char *name ) +{ + const struct + { + cl_channel_order order; + const char *name; + }orderNames[] = + { + { CL_R, "CL_R" }, + { CL_A, "CL_A" }, + { CL_Rx, "CL_Rx" }, + { CL_RG, "CL_RG" }, + { CL_RA, "CL_RA" }, + { CL_RGx, "CL_RGx" }, + { CL_RGB, "CL_RGB" }, + { CL_RGBx, "CL_RGBx" }, + { CL_RGBA, "CL_RGBA" }, + { CL_BGRA, "CL_BGRA" }, + { CL_ARGB, "CL_ARGB" }, + { CL_INTENSITY, "CL_INTENSITY"}, + { CL_LUMINANCE, "CL_LUMINANCE"}, + { CL_DEPTH, "CL_DEPTH" }, + { CL_DEPTH_STENCIL, "CL_DEPTH_STENCIL" }, + { CL_sRGB, "CL_sRGB" }, + { CL_sRGBx, "CL_sRGBx" }, + { CL_sRGBA, "CL_sRGBA" }, + { CL_sBGRA, "CL_sBGRA" }, + { CL_ABGR, "CL_ABGR" }, +#ifdef CL_1RGB_APPLE + { CL_1RGB_APPLE, "CL_1RGB_APPLE" }, +#endif +#ifdef CL_BGR1_APPLE + { CL_BGR1_APPLE, "CL_BGR1_APPLE" }, +#endif + }; + + for( size_t i = 0; i < sizeof( orderNames ) / sizeof( orderNames[ 0 ] ); i++ ) + { + if( strcmp( orderNames[ i ].name, name ) == 0 || strcmp( orderNames[ i ].name + 3, name ) == 0 ) + return orderNames[ i ].order; + } + return (cl_channel_order)-1; +} + + +int is_format_signed( const cl_image_format *format ) +{ + switch( format->image_channel_data_type ) + { + case CL_SNORM_INT8: + case CL_SIGNED_INT8: + case CL_SNORM_INT16: + case CL_SIGNED_INT16: + case CL_SIGNED_INT32: + case CL_HALF_FLOAT: + case CL_FLOAT: +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: +#endif + return 1; + + default: + return 0; + } +} + +size_t get_pixel_size( cl_image_format *format ) +{ + switch( format->image_channel_data_type ) + { + case CL_SNORM_INT8: + case CL_UNORM_INT8: + case CL_SIGNED_INT8: + case CL_UNSIGNED_INT8: + return get_format_channel_count( format ); + + case CL_SNORM_INT16: + case CL_UNORM_INT16: + case CL_SIGNED_INT16: + case CL_UNSIGNED_INT16: + case CL_HALF_FLOAT: +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: +#endif + return get_format_channel_count( format ) * sizeof( cl_ushort ); + + case CL_SIGNED_INT32: + case CL_UNSIGNED_INT32: + return get_format_channel_count( format ) * sizeof( cl_int ); + + case CL_UNORM_SHORT_565: + case CL_UNORM_SHORT_555: +#ifdef OBSOLETE_FORAMT + case CL_UNORM_SHORT_565_REV: + case CL_UNORM_SHORT_555_REV: +#endif + return 2; + +#ifdef OBSOLETE_FORAMT + case CL_UNORM_INT_8888: + case CL_UNORM_INT_8888_REV: + return 4; +#endif + + case CL_UNORM_INT_101010: +#ifdef OBSOLETE_FORAMT + case CL_UNORM_INT_101010_REV: +#endif + return 4; + + case CL_FLOAT: + return get_format_channel_count( format ) * sizeof( cl_float ); + + default: + return 0; + } +} + +int get_8_bit_image_format( cl_context context, cl_mem_object_type objType, cl_mem_flags flags, size_t channelCount, cl_image_format *outFormat ) +{ + cl_image_format formatList[ 128 ]; + unsigned int outFormatCount, i; + int error; + + + /* Make sure each image format is supported */ + if ((error = clGetSupportedImageFormats( context, flags, objType, 128, formatList, &outFormatCount ))) + return error; + + + /* Look for one that is an 8-bit format */ + for( i = 0; i < outFormatCount; i++ ) + { + if( formatList[ i ].image_channel_data_type == CL_SNORM_INT8 || + formatList[ i ].image_channel_data_type == CL_UNORM_INT8 || + formatList[ i ].image_channel_data_type == CL_SIGNED_INT8 || + formatList[ i ].image_channel_data_type == CL_UNSIGNED_INT8 ) + { + if ( !channelCount || ( channelCount && ( get_format_channel_count( &formatList[ i ] ) == channelCount ) ) ) + { + *outFormat = formatList[ i ]; + return 0; + } + } + } + + return -1; +} + +int get_32_bit_image_format( cl_context context, cl_mem_object_type objType, cl_mem_flags flags, size_t channelCount, cl_image_format *outFormat ) +{ + cl_image_format formatList[ 128 ]; + unsigned int outFormatCount, i; + int error; + + + /* Make sure each image format is supported */ + if ((error = clGetSupportedImageFormats( context, flags, objType, 128, formatList, &outFormatCount ))) + return error; + + /* Look for one that is an 8-bit format */ + for( i = 0; i < outFormatCount; i++ ) + { + if( formatList[ i ].image_channel_data_type == CL_UNORM_INT_101010 || + formatList[ i ].image_channel_data_type == CL_FLOAT || + formatList[ i ].image_channel_data_type == CL_SIGNED_INT32 || + formatList[ i ].image_channel_data_type == CL_UNSIGNED_INT32 ) + { + if ( !channelCount || ( channelCount && ( get_format_channel_count( &formatList[ i ] ) == channelCount ) ) ) + { + *outFormat = formatList[ i ]; + return 0; + } + } + } + + return -1; +} + +int random_log_in_range( int minV, int maxV, MTdata d ) +{ + double v = log2( ( (double)genrand_int32(d) / (double)0xffffffff ) + 1 ); + int iv = (int)( (float)( maxV - minV ) * v ); + return iv + minV; +} + + +// Define the addressing functions +typedef int (*AddressFn)( int value, size_t maxValue ); + +int NoAddressFn( int value, size_t maxValue ) { return value; } +int RepeatAddressFn( int value, size_t maxValue ) +{ + if( value < 0 ) + value += (int)maxValue; + else if( value >= (int)maxValue ) + value -= (int)maxValue; + return value; +} +int MirroredRepeatAddressFn( int value, size_t maxValue ) +{ + if( value < 0 ) + value = 0; + else if( (size_t) value >= maxValue ) + value = (int) (maxValue - 1); + return value; +} +int ClampAddressFn( int value, size_t maxValue ) { return ( value < -1 ) ? -1 : ( ( value > (cl_long) maxValue ) ? (int)maxValue : value ); } +int ClampToEdgeNearestFn( int value, size_t maxValue ) { return ( value < 0 ) ? 0 : ( ( (size_t)value > maxValue - 1 ) ? (int)maxValue - 1 : value ); } +AddressFn ClampToEdgeLinearFn = ClampToEdgeNearestFn; + +// Note: normalized coords get repeated in normalized space, not unnormalized space! hence the special case here +volatile float gFloatHome; +float RepeatNormalizedAddressFn( float fValue, size_t maxValue ) +{ +#ifndef _MSC_VER // Use original if not the VS compiler. + // General computation for repeat + return (fValue - floorf( fValue )) * (float) maxValue; // Reduce to [0, 1.f] +#else // Otherwise, use this instead: + // Home the subtraction to a float to break up the sequence of x87 + // instructions emitted by the VS compiler. + gFloatHome = fValue - floorf(fValue); + return gFloatHome * (float)maxValue; +#endif +} + +float MirroredRepeatNormalizedAddressFn( float fValue, size_t maxValue ) +{ + // Round to nearest multiple of two + float s_prime = 2.0f * rintf( fValue * 0.5f ); // Note halfway values flip flop here due to rte, but they both end up pointing the same place at the end of the day + + // Reduce to [-1, 1], Apply mirroring -> [0, 1] + s_prime = fabsf( fValue - s_prime ); + + // un-normalize + return s_prime * (float) maxValue; +} + +struct AddressingTable +{ + AddressingTable() + { + ct_assert( ( CL_ADDRESS_MIRRORED_REPEAT - CL_ADDRESS_NONE < 6 ) ); + ct_assert( CL_FILTER_NEAREST - CL_FILTER_LINEAR < 2 ); + + mTable[ CL_ADDRESS_NONE - CL_ADDRESS_NONE ][ CL_FILTER_NEAREST - CL_FILTER_NEAREST ] = NoAddressFn; + mTable[ CL_ADDRESS_NONE - CL_ADDRESS_NONE ][ CL_FILTER_LINEAR - CL_FILTER_NEAREST ] = NoAddressFn; + mTable[ CL_ADDRESS_REPEAT - CL_ADDRESS_NONE ][ CL_FILTER_NEAREST - CL_FILTER_NEAREST ] = RepeatAddressFn; + mTable[ CL_ADDRESS_REPEAT - CL_ADDRESS_NONE ][ CL_FILTER_LINEAR - CL_FILTER_NEAREST ] = RepeatAddressFn; + mTable[ CL_ADDRESS_CLAMP_TO_EDGE - CL_ADDRESS_NONE ][ CL_FILTER_NEAREST - CL_FILTER_NEAREST ] = ClampToEdgeNearestFn; + mTable[ CL_ADDRESS_CLAMP_TO_EDGE - CL_ADDRESS_NONE ][ CL_FILTER_LINEAR - CL_FILTER_NEAREST ] = ClampToEdgeLinearFn; + mTable[ CL_ADDRESS_CLAMP - CL_ADDRESS_NONE ][ CL_FILTER_NEAREST - CL_FILTER_NEAREST ] = ClampAddressFn; + mTable[ CL_ADDRESS_CLAMP - CL_ADDRESS_NONE ][ CL_FILTER_LINEAR - CL_FILTER_NEAREST ] = ClampAddressFn; + mTable[ CL_ADDRESS_MIRRORED_REPEAT - CL_ADDRESS_NONE ][ CL_FILTER_NEAREST - CL_FILTER_NEAREST ] = MirroredRepeatAddressFn; + mTable[ CL_ADDRESS_MIRRORED_REPEAT - CL_ADDRESS_NONE ][ CL_FILTER_LINEAR - CL_FILTER_NEAREST ] = MirroredRepeatAddressFn; + } + + AddressFn operator[]( image_sampler_data *sampler ) + { + return mTable[ (int)sampler->addressing_mode - CL_ADDRESS_NONE ][ (int)sampler->filter_mode - CL_FILTER_NEAREST ]; + } + + AddressFn mTable[ 6 ][ 2 ]; +}; + +static AddressingTable sAddressingTable; + +bool alpha_is_x(cl_image_format *format){ + switch (format->image_channel_order) { + case CL_RGBx: + case CL_sRGBx: + return true; + default: + return false; + } +} + +bool is_sRGBA_order(cl_channel_order image_channel_order){ + switch (image_channel_order) { + case CL_sRGB: + case CL_sRGBx: + case CL_sRGBA: + case CL_sBGRA: + return true; + default: + return false; + } +} + +// Format helpers + +int has_alpha(cl_image_format *format) { + switch (format->image_channel_order) { + case CL_R: + return 0; + case CL_A: + case CL_Rx: + return 1; + case CL_RG: + return 0; + case CL_RA: + case CL_RGx: + return 1; + case CL_RGB: + case CL_sRGB: + return 0; + case CL_RGBx: + case CL_sRGBx: + return 1; + case CL_RGBA: + return 1; + case CL_BGRA: + return 1; + case CL_ARGB: + return 1; + case CL_INTENSITY: + return 1; + case CL_LUMINANCE: + return 0; +#ifdef CL_BGR1_APPLE + case CL_BGR1_APPLE: return 1; +#endif +#ifdef CL_1RGB_APPLE + case CL_1RGB_APPLE: return 1; +#endif + case CL_sRGBA: + case CL_sBGRA: + return 1; + case CL_DEPTH: + return 0; + default: + log_error("Invalid image channel order: %d\n", format->image_channel_order); + return 0; + } + +} + +#define PRINT_MAX_SIZE_LOGIC 0 + +#define SWAP( _a, _b ) do{ _a ^= _b; _b ^= _a; _a ^= _b; }while(0) +#ifndef MAX + #define MAX( _a, _b ) ((_a) > (_b) ? (_a) : (_b)) +#endif + +void get_max_sizes(size_t *numberOfSizes, const int maxNumberOfSizes, + size_t sizes[][3], size_t maxWidth, size_t maxHeight, size_t maxDepth, size_t maxArraySize, + const cl_ulong maxIndividualAllocSize, // CL_DEVICE_MAX_MEM_ALLOC_SIZE + const cl_ulong maxTotalAllocSize, // CL_DEVICE_GLOBAL_MEM_SIZE + cl_mem_object_type image_type, cl_image_format *format, int usingMaxPixelSizeBuffer) { + + bool is3D = (image_type == CL_MEM_OBJECT_IMAGE3D); + bool isArray = (image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY || image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY); + + // Validate we have a reasonable max depth for 3D + if (is3D && maxDepth < 2) { + log_error("ERROR: Requesting max image sizes for 3D images when max depth is < 2.\n"); + *numberOfSizes = 0; + return; + } + // Validate we have a reasonable max array size for 1D & 2D image arrays + if (isArray && maxArraySize < 2) { + log_error("ERROR: Requesting max image sizes for an image array when max array size is < 1.\n"); + *numberOfSizes = 0; + return; + } + + // Reduce the maximum because we are trying to test the max image dimensions, not the memory allocation + cl_ulong adjustedMaxTotalAllocSize = maxTotalAllocSize / 4; + cl_ulong adjustedMaxIndividualAllocSize = maxIndividualAllocSize / 4; + log_info("Note: max individual allocation adjusted down from %gMB to %gMB and max total allocation adjusted down from %gMB to %gMB.\n", + maxIndividualAllocSize/(1024.0*1024.0), adjustedMaxIndividualAllocSize/(1024.0*1024.0), + maxTotalAllocSize/(1024.0*1024.0), adjustedMaxTotalAllocSize/(1024.0*1024.0)); + + // Cap our max allocation to 1.0GB. + // FIXME -- why? In the interest of not taking a long time? We should still test this stuff... + if (adjustedMaxTotalAllocSize > (cl_ulong)1024*1024*1024) { + adjustedMaxTotalAllocSize = (cl_ulong)1024*1024*1024; + log_info("Limiting max total allocation size to %gMB (down from %gMB) for test.\n", + adjustedMaxTotalAllocSize/(1024.0*1024.0), maxTotalAllocSize/(1024.0*1024.0)); + } + + cl_ulong maxAllocSize = adjustedMaxIndividualAllocSize; + if (adjustedMaxTotalAllocSize < adjustedMaxIndividualAllocSize*2) + maxAllocSize = adjustedMaxTotalAllocSize/2; + + size_t raw_pixel_size = get_pixel_size(format); + // If the test will be creating input (src) buffer of type int4 or float4, number of pixels will be + // governed by sizeof(int4 or float4) and not sizeof(dest fomat) + // Also if pixel size is 12 bytes i.e. RGB or RGBx, we adjust it to 16 bytes as GPUs has no concept + // of 3 channel images. GPUs expand these to four channel RGBA. + if(usingMaxPixelSizeBuffer || raw_pixel_size == 12) + raw_pixel_size = 16; + size_t max_pixels = (size_t)maxAllocSize / raw_pixel_size; + + log_info("Maximums: [%ld x %ld x %ld], raw pixel size %lu bytes, per-allocation limit %gMB.\n", + maxWidth, maxHeight, isArray ? maxArraySize : maxDepth, raw_pixel_size, (maxAllocSize/(1024.0*1024.0))); + + // Keep track of the maximum sizes for each dimension + size_t maximum_sizes[] = { maxWidth, maxHeight, maxDepth }; + + switch (image_type) { + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + maximum_sizes[1] = maxArraySize; + maximum_sizes[2] = 1; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + maximum_sizes[2] = maxArraySize; + break; + } + + + // Given one fixed sized dimension, this code finds one or two other dimensions, + // both with very small size, such that the size does not exceed the maximum + // passed to this function + +#if defined(__x86_64) || defined (__arm64__) || defined (__ppc64__) + size_t other_sizes[] = { 2, 3, 5, 6, 7, 9, 10, 11, 13, 15}; +#else + size_t other_sizes[] = { 2, 3, 5, 6, 7, 9, 11, 13}; +#endif + + static size_t other_size = 0; + enum { num_other_sizes = sizeof(other_sizes)/sizeof(size_t) }; + + (*numberOfSizes) = 0; + + if (image_type == CL_MEM_OBJECT_IMAGE1D) { + + double M = maximum_sizes[0]; + + // Store the size + sizes[(*numberOfSizes)][0] = (size_t)M; + sizes[(*numberOfSizes)][1] = 1; + sizes[(*numberOfSizes)][2] = 1; + ++(*numberOfSizes); + } + + else if (image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY || image_type == CL_MEM_OBJECT_IMAGE2D) { + + for (int fixed_dim=0;fixed_dim<2;++fixed_dim) { + + // Determine the size of the fixed dimension + double M = maximum_sizes[fixed_dim]; + double A = max_pixels; + + int x0_dim = !fixed_dim; + double x0 = fmin(fmin(other_sizes[(other_size++)%num_other_sizes],A/M), maximum_sizes[x0_dim]); + + // Store the size + sizes[(*numberOfSizes)][fixed_dim] = (size_t)M; + sizes[(*numberOfSizes)][x0_dim] = (size_t)x0; + sizes[(*numberOfSizes)][2] = 1; + ++(*numberOfSizes); + } + } + + else if (image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY || image_type == CL_MEM_OBJECT_IMAGE3D) { + + // Iterate over dimensions, finding sizes for the non-fixed dimension + for (int fixed_dim=0;fixed_dim<3;++fixed_dim) { + + // Determine the size of the fixed dimension + double M = maximum_sizes[fixed_dim]; + double A = max_pixels; + + // Find two other dimensions, x0 and x1 + int x0_dim = (fixed_dim == 0) ? 1 : 0; + int x1_dim = (fixed_dim == 2) ? 1 : 2; + + // Choose two other sizes for these dimensions + double x0 = fmin(fmin(A/M,maximum_sizes[x0_dim]),other_sizes[(other_size++)%num_other_sizes]); + // GPUs have certain restrictions on minimum width (row alignment) of images which has given us issues + // testing small widths in this test (say we set width to 3 for testing, and compute size based on this width and decide + // it fits within vram ... but GPU driver decides that, due to row alignment requirements, it has to use + // width of 16 which doesnt fit in vram). For this purpose we are not testing width < 16 for this test. + if(x0_dim == 0 && x0 < 16) + x0 = 16; + double x1 = fmin(fmin(A/M/x0,maximum_sizes[x1_dim]),other_sizes[(other_size++)%num_other_sizes]); + // Store the size + sizes[(*numberOfSizes)][fixed_dim] = (size_t)M; + sizes[(*numberOfSizes)][x0_dim] = (size_t)x0; + sizes[(*numberOfSizes)][x1_dim] = (size_t)x1; + ++(*numberOfSizes); + } + } + + // Log the results + for (int j=0; j<(int)(*numberOfSizes); j++) { + switch (image_type) { + case CL_MEM_OBJECT_IMAGE1D: + log_info(" size[%d] = [%ld] (%g MB image)\n", + j, sizes[j][0], raw_pixel_size*sizes[j][0]*sizes[j][1]*sizes[j][2]/(1024.0*1024.0)); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE2D: + log_info(" size[%d] = [%ld %ld] (%g MB image)\n", + j, sizes[j][0], sizes[j][1], raw_pixel_size*sizes[j][0]*sizes[j][1]*sizes[j][2]/(1024.0*1024.0)); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + case CL_MEM_OBJECT_IMAGE3D: + log_info(" size[%d] = [%ld %ld %ld] (%g MB image)\n", + j, sizes[j][0], sizes[j][1], sizes[j][2], raw_pixel_size*sizes[j][0]*sizes[j][1]*sizes[j][2]/(1024.0*1024.0)); + break; + } + } +} + +int issubnormal(float a) +{ + union { cl_int i; cl_float f; } u; + u.f = a; + return (u.i & 0x7f800000U) == 0; +} + +float get_max_absolute_error( cl_image_format *format, image_sampler_data *sampler) { + if (sampler->filter_mode == CL_FILTER_NEAREST) + return 0.0f; + + switch (format->image_channel_data_type) { + case CL_SNORM_INT8: + return 1.0f/127.0f; + case CL_UNORM_INT8: + return 1.0f/255.0f; + case CL_UNORM_INT16: + return 1.0f/65535.0f; + case CL_SNORM_INT16: + return 1.0f/32767.0f; + case CL_FLOAT: + return CL_FLT_MIN; +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: + return 0x1.0p-14f; +#endif + default: + return 0.0f; + } +} + +float get_max_relative_error( cl_image_format *format, image_sampler_data *sampler, int is3D, int isLinearFilter ) +{ + float maxError = 0.0f; + float sampleCount = 1.0f; + if( isLinearFilter ) + sampleCount = is3D ? 8.0f : 4.0f; + + // Note that the ULP is defined here as the unit in the last place of the maximum + // magnitude sample used for filtering. + + // Section 8.3 + switch( format->image_channel_data_type ) + { + // The spec allows 2 ulps of error for normalized formats + case CL_SNORM_INT8: + case CL_UNORM_INT8: + case CL_SNORM_INT16: + case CL_UNORM_INT16: + case CL_UNORM_SHORT_565: + case CL_UNORM_SHORT_555: + case CL_UNORM_INT_101010: + maxError = 2*FLT_EPSILON*sampleCount; // Maximum sampling error for round to zero normalization based on multiplication + // by reciprocal (using reciprocal generated in round to +inf mode, so that 1.0 matches spec) + break; + + // If the implementation supports these formats then it will have to allow rounding error here too, + // because not all 32-bit ints are exactly representable in float + case CL_SIGNED_INT32: + case CL_UNSIGNED_INT32: + maxError = 1*FLT_EPSILON; + break; + } + + + // Section 8.2 + if( sampler->addressing_mode == CL_ADDRESS_REPEAT || sampler->addressing_mode == CL_ADDRESS_MIRRORED_REPEAT || sampler->filter_mode != CL_FILTER_NEAREST || sampler->normalized_coords ) +#if defined( __APPLE__ ) + { + if( sampler->filter_mode != CL_FILTER_NEAREST ) + { + extern cl_device_type gDeviceType; + // The maximum + if( gDeviceType == CL_DEVICE_TYPE_GPU ) + maxError += MAKE_HEX_FLOAT(0x1.0p-4f, 0x1L, -4); // Some GPUs ain't so accurate + else + // The standard method of 2d linear filtering delivers 4.0 ulps of error in round to nearest (8 in rtz). + maxError += 4.0f * FLT_EPSILON; + } + else + maxError += 4.0f * FLT_EPSILON; // normalized coordinates will introduce some error into the fractional part of the address, affecting results + } +#else + { +#if !defined(_WIN32) +#warning Implementations will likely wish to pick a max allowable sampling error policy here that is better than the spec +#endif + // The spec allows linear filters to return any result most of the time. + // That's fine for implementations but a problem for testing. After all + // users aren't going to like garbage images. We have "picked a number" + // here that we are going to attempt to conform to. Implementations are + // free to pick another number, like infinity, if they like. + // We picked a number for you, to provide /some/ sanity + maxError = MAKE_HEX_FLOAT(0x1.0p-7f, 0x1L, -7); + // ...but this is what the spec allows: + // maxError = INFINITY; + // Please feel free to pick any positive number. (NaN wont work.) + } +#endif + + // The error calculation itself can introduce error + maxError += FLT_EPSILON * 2; + + return maxError; +} + +size_t get_format_max_int( cl_image_format *format ) +{ + switch( format->image_channel_data_type ) + { + case CL_SNORM_INT8: + case CL_SIGNED_INT8: + return 127; + case CL_UNORM_INT8: + case CL_UNSIGNED_INT8: + return 255; + + case CL_SNORM_INT16: + case CL_SIGNED_INT16: + return 32767; + + case CL_UNORM_INT16: + case CL_UNSIGNED_INT16: + return 65535; + + case CL_SIGNED_INT32: + return 2147483647L; + + case CL_UNSIGNED_INT32: + return 4294967295LL; + + case CL_UNORM_SHORT_565: + case CL_UNORM_SHORT_555: + return 31; + + case CL_UNORM_INT_101010: + return 1023; + + case CL_HALF_FLOAT: + return 1<<10; + +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: + return 16384; +#endif + default: + return 0; + } +} + +int get_format_min_int( cl_image_format *format ) +{ + switch( format->image_channel_data_type ) + { + case CL_SNORM_INT8: + case CL_SIGNED_INT8: + return -128; + case CL_UNORM_INT8: + case CL_UNSIGNED_INT8: + return 0; + + case CL_SNORM_INT16: + case CL_SIGNED_INT16: + return -32768; + + case CL_UNORM_INT16: + case CL_UNSIGNED_INT16: + return 0; + + case CL_SIGNED_INT32: + return -2147483648LL; + + case CL_UNSIGNED_INT32: + return 0; + + case CL_UNORM_SHORT_565: + case CL_UNORM_SHORT_555: + case CL_UNORM_INT_101010: + return 0; + + case CL_HALF_FLOAT: + return -1<<10; + +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: + return -16384; +#endif + + default: + return 0; + } +} + +float convert_half_to_float( unsigned short halfValue ) +{ + // We have to take care of a few special cases, but in general, we just extract + // the same components from the half that exist in the float and re-stuff them + // For a description of the actual half format, see http://en.wikipedia.org/wiki/Half_precision + // Note: we store these in 32-bit ints to make the bit manipulations easier later + int sign = ( halfValue >> 15 ) & 0x0001; + int exponent = ( halfValue >> 10 ) & 0x001f; + int mantissa = ( halfValue ) & 0x03ff; + + // Note: we use a union here to be able to access the bits of a float directly + union + { + unsigned int bits; + float floatValue; + } outFloat; + + // Special cases first + if( exponent == 0 ) + { + if( mantissa == 0 ) + { + // If both exponent and mantissa are 0, the number is +/- 0 + outFloat.bits = sign << 31; + return outFloat.floatValue; // Already done! + } + + // If exponent is 0, it's a denormalized number, so we renormalize it + // Note: this is not terribly efficient, but oh well + while( ( mantissa & 0x00000400 ) == 0 ) + { + mantissa <<= 1; + exponent--; + } + + // The first bit is implicit, so we take it off and inc the exponent accordingly + exponent++; + mantissa &= ~(0x00000400); + } + else if( exponent == 31 ) // Special-case "numbers" + { + // If the exponent is 31, it's a special case number (+/- infinity or NAN). + // If the mantissa is 0, it's infinity, else it's NAN, but in either case, the packing + // method is the same + outFloat.bits = ( sign << 31 ) | 0x7f800000 | ( mantissa << 13 ); + return outFloat.floatValue; + } + + // Plain ol' normalized number, so adjust to the ranges a 32-bit float expects and repack + exponent += ( 127 - 15 ); + mantissa <<= 13; + + outFloat.bits = ( sign << 31 ) | ( exponent << 23 ) | mantissa; + return outFloat.floatValue; +} + + + +cl_ushort convert_float_to_half( float f ) +{ + switch( gFloatToHalfRoundingMode ) + { + case kRoundToNearestEven: + return float2half_rte( f ); + case kRoundTowardZero: + return float2half_rtz( f ); + default: + log_error( "ERROR: Test internal error -- unhandled or unknown float->half rounding mode.\n" ); + exit(-1); + return 0xffff; + } + +} + +cl_ushort float2half_rte( float f ) + { + union{ float f; cl_uint u; } u = {f}; + cl_uint sign = (u.u >> 16) & 0x8000; + float x = fabsf(f); + + //Nan + if( x != x ) + { + u.u >>= (24-11); + u.u &= 0x7fff; + u.u |= 0x0200; //silence the NaN + return u.u | sign; + } + + // overflow + if( x >= MAKE_HEX_FLOAT(0x1.ffep15f, 0x1ffeL, 3) ) + return 0x7c00 | sign; + + // underflow + if( x <= MAKE_HEX_FLOAT(0x1.0p-25f, 0x1L, -25) ) + return sign; // The halfway case can return 0x0001 or 0. 0 is even. + + // very small + if( x < MAKE_HEX_FLOAT(0x1.8p-24f, 0x18L, -28) ) + return sign | 1; + + // half denormal + if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) ) + { + u.f = x * MAKE_HEX_FLOAT(0x1.0p-125f, 0x1L, -125); + return sign | u.u; + } + + u.f *= MAKE_HEX_FLOAT(0x1.0p13f, 0x1L, 13); + u.u &= 0x7f800000; + x += u.f; + u.f = x - u.f; + u.f *= MAKE_HEX_FLOAT(0x1.0p-112f, 0x1L, -112); + + return (u.u >> (24-11)) | sign; + } + +cl_ushort float2half_rtz( float f ) + { + union{ float f; cl_uint u; } u = {f}; + cl_uint sign = (u.u >> 16) & 0x8000; + float x = fabsf(f); + + //Nan + if( x != x ) + { + u.u >>= (24-11); + u.u &= 0x7fff; + u.u |= 0x0200; //silence the NaN + return u.u | sign; + } + + // overflow + if( x >= MAKE_HEX_FLOAT(0x1.0p16f, 0x1L, 16) ) + { + if( x == INFINITY ) + return 0x7c00 | sign; + + return 0x7bff | sign; + } + + // underflow + if( x < MAKE_HEX_FLOAT(0x1.0p-24f, 0x1L, -24) ) + return sign; // The halfway case can return 0x0001 or 0. 0 is even. + + // half denormal + if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) ) + { + x *= MAKE_HEX_FLOAT(0x1.0p24f, 0x1L, 24); + return (cl_ushort)((int) x | sign); + } + + u.u &= 0xFFFFE000U; + u.u -= 0x38000000U; + + return (u.u >> (24-11)) | sign; +} + +class TEST +{ +public: + TEST(); +}; + +static TEST t; +void __vstore_half_rte(float f, size_t index, uint16_t *p) +{ + union{ unsigned int u; float f;} u; + + u.f = f; + unsigned short r = (u.u >> 16) & 0x8000; + u.u &= 0x7fffffff; + if( u.u >= 0x33000000U ) + { + if( u.u >= 0x47800000 ) + { + if( u.u <= 0x7f800000 ) + r |= 0x7c00; + else + { + r |= 0x7e00 | ( (u.u >> 13) & 0x3ff ); + } + } + else + { + float x = u.f; + if( u.u < 0x38800000 ) + u.u = 0x3f000000; + else + u.u += 0x06800000; + u.u &= 0x7f800000U; + x += u.f; + x -= u.f; + u.f = x * MAKE_HEX_FLOAT(0x1.0p-112f, 0x1L, -112); + u.u >>= 13; + r |= (unsigned short) u.u; + } + } + + ((unsigned short*)p)[index] = r; +} + +TEST::TEST() +{ + return; + union + { + float f; + uint32_t i; + } test; + uint16_t control, myval; + + log_info(" &&&&&&&&&&&&&&&&&&&&&&&&&&&& TESTING HALFS &&&&&&&&&&&&&&&&&&&&\n" ); + test.i = 0; + do + { + if( ( test.i & 0xffffff ) == 0 ) + { + if( ( test.i & 0xfffffff ) == 0 ) + log_info( "*" ); + else + log_info( "." ); + fflush(stdout); + } + __vstore_half_rte( test.f, 0, &control ); + myval = convert_float_to_half( test.f ); + if( myval != control ) + { + log_info( "\n******** ERROR: MyVal %04x control %04x source %12.24f\n", myval, control, test.f ); + log_info( " source bits: %08x %a\n", test.i, test.f ); + float t, c; + c = convert_half_to_float( control ); + t = convert_half_to_float( myval ); + log_info( " converted control: %12.24f myval: %12.24f\n", c, t ); + } + test.i++; + } while( test.i != 0 ); + log_info("\n &&&&&&&&&&&&&&&&&&&&&&&&&&&& TESTING HALFS &&&&&&&&&&&&&&&&&&&&\n" ); + +} + +cl_ulong get_image_size( image_descriptor const *imageInfo ) +{ + cl_ulong imageSize; + + // Assumes rowPitch and slicePitch are always correctly defined + if ( /*gTestMipmaps*/ imageInfo->num_mip_levels > 1 ) + { + imageSize = (size_t) compute_mipmapped_image_size(*imageInfo); + } + else + { + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + imageSize = imageInfo->rowPitch; + break; + case CL_MEM_OBJECT_IMAGE2D: + imageSize = imageInfo->height * imageInfo->rowPitch; + break; + case CL_MEM_OBJECT_IMAGE3D: + imageSize = imageInfo->depth * imageInfo->slicePitch; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + imageSize = imageInfo->arraySize * imageInfo->slicePitch; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + imageSize = imageInfo->arraySize * imageInfo->slicePitch; + break; + default: + log_error("ERROR: Cannot identify image type %x\n", imageInfo->type); + abort(); + } + } + return imageSize; +} + +// Calculate image size in megabytes (strictly, mebibytes). Result is rounded up. +cl_ulong get_image_size_mb( image_descriptor const *imageInfo ) +{ + cl_ulong imageSize = get_image_size( imageInfo ); + cl_ulong mb = imageSize / ( 1024 * 1024 ); + if ( imageSize % ( 1024 * 1024 ) > 0 ) + { + mb += 1; + } + return mb; +} + + +extern bool gTestRounding; +uint64_t gRoundingStartValue = 0; + + +void escape_inf_nan_values( char* data, size_t allocSize ) { + // filter values with 8 not-quite-highest bits + unsigned int *intPtr = (unsigned int *)data; + for( size_t i = 0; i < allocSize >> 2; i++ ) + { + if( ( intPtr[ i ] & 0x7F800000 ) == 0x7F800000 ) + intPtr[ i ] ^= 0x40000000; + } + + // Ditto with half floats (16-bit numbers with the 5 not-quite-highest bits = 0x7C00 are special) + unsigned short *shortPtr = (unsigned short *)data; + for( size_t i = 0; i < allocSize >> 1; i++ ) + { + if( ( shortPtr[ i ] & 0x7C00 ) == 0x7C00 ) + shortPtr[ i ] ^= 0x4000; + } +} + +char * generate_random_image_data( image_descriptor *imageInfo, BufferOwningPtr &P, MTdata d ) +{ + size_t allocSize = get_image_size( imageInfo ); + size_t pixelRowBytes = imageInfo->width * get_pixel_size( imageInfo->format ); + size_t i; + + if (imageInfo->num_mip_levels > 1) + allocSize = compute_mipmapped_image_size(*imageInfo); + +#if defined (__APPLE__ ) + char *data = NULL; + if (gDeviceType == CL_DEVICE_TYPE_CPU) { + size_t mapSize = ((allocSize + 4095L) & -4096L) + 8192; + + void *map = mmap(0, mapSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); + intptr_t data_end = (intptr_t)map + mapSize - 4096; + data = (char *)(data_end - (intptr_t)allocSize); + + mprotect(map, 4096, PROT_NONE); + mprotect((void *)((char *)map + mapSize - 4096), 4096, PROT_NONE); + P.reset(data, map, mapSize,allocSize); + } else { + data = (char *)malloc(allocSize); + P.reset(data,NULL,0,allocSize); + } +#else + P.reset( NULL ); // Free already allocated memory first, then try to allocate new block. +#if defined (_WIN32) && defined(_MSC_VER) + char *data = (char *)_aligned_malloc(allocSize, get_pixel_size(imageInfo->format)); +#elif defined(__MINGW32__) + char *data = (char *)__mingw_aligned_malloc(allocSize, get_pixel_size(imageInfo->format)); +#else + char *data = (char *)memalign(get_pixel_size(imageInfo->format), allocSize); +#endif + P.reset(data,NULL,0,allocSize, true); +#endif + + if (data == NULL) { + log_error( "ERROR: Unable to malloc %lu bytes for generate_random_image_data\n", allocSize ); + return 0; + } + + if( gTestRounding ) + { + // Special case: fill with a ramp from 0 to the size of the type + size_t typeSize = get_format_type_size( imageInfo->format ); + switch( typeSize ) + { + case 1: + { + char *ptr = data; + for( i = 0; i < allocSize; i++ ) + ptr[i] = (cl_char) (i + gRoundingStartValue); + } + break; + case 2: + { + cl_short *ptr = (cl_short*) data; + for( i = 0; i < allocSize / 2; i++ ) + ptr[i] = (cl_short) (i + gRoundingStartValue); + } + break; + case 4: + { + cl_int *ptr = (cl_int*) data; + for( i = 0; i < allocSize / 4; i++ ) + ptr[i] = (cl_int) (i + gRoundingStartValue); + } + break; + } + + // Note: inf or nan float values would cause problems, although we don't know this will + // actually be a float, so we just know what to look for + escape_inf_nan_values( data, allocSize ); + return data; + } + + // Otherwise, we should be able to just fill with random bits no matter what + cl_uint *p = (cl_uint*) data; + for( i = 0; i + 4 <= allocSize; i += 4 ) + p[ i / 4 ] = genrand_int32(d); + + for( ; i < allocSize; i++ ) + data[i] = genrand_int32(d); + + // Note: inf or nan float values would cause problems, although we don't know this will + // actually be a float, so we just know what to look for + escape_inf_nan_values( data, allocSize ); + + if ( /*!gTestMipmaps*/ imageInfo->num_mip_levels < 2 ) + { + // Fill unused edges with -1, NaN for float + if (imageInfo->rowPitch > pixelRowBytes) + { + size_t height = 0; + + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE2D: + case CL_MEM_OBJECT_IMAGE3D: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + height = imageInfo->height; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + height = imageInfo->arraySize; + break; + } + + // Fill in the row padding regions + for( i = 0; i < height; i++ ) + { + size_t offset = i * imageInfo->rowPitch + pixelRowBytes; + size_t length = imageInfo->rowPitch - pixelRowBytes; + memset( data + offset, 0xff, length ); + } + } + + // Fill in the slice padding regions, if necessary: + + size_t slice_dimension = imageInfo->height; + if (imageInfo->type == CL_MEM_OBJECT_IMAGE1D_ARRAY) { + slice_dimension = imageInfo->arraySize; + } + + if (imageInfo->slicePitch > slice_dimension*imageInfo->rowPitch) + { + size_t depth = 0; + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE2D: + case CL_MEM_OBJECT_IMAGE3D: + depth = imageInfo->depth; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + depth = imageInfo->arraySize; + break; + } + + for( i = 0; i < depth; i++ ) + { + size_t offset = i * imageInfo->slicePitch + slice_dimension*imageInfo->rowPitch; + size_t length = imageInfo->slicePitch - slice_dimension*imageInfo->rowPitch; + memset( data + offset, 0xff, length ); + } + } + } + + return data; +} + +#define CLAMP_FLOAT( v ) ( fmaxf( fminf( v, 1.f ), -1.f ) ) + + +void read_image_pixel_float( void *imageData, image_descriptor *imageInfo, + int x, int y, int z, float *outData, int lod ) +{ + size_t width_lod = imageInfo->width, height_lod = imageInfo->height, depth_lod = imageInfo->depth; + size_t slice_pitch_lod = 0, row_pitch_lod = 0; + + if ( imageInfo->num_mip_levels > 1 ) + { + switch(imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE3D : + depth_lod = ( imageInfo->depth >> lod ) ? ( imageInfo->depth >> lod ) : 1; + case CL_MEM_OBJECT_IMAGE2D : + case CL_MEM_OBJECT_IMAGE2D_ARRAY : + height_lod = ( imageInfo->height >> lod ) ? ( imageInfo->height >> lod ) : 1; + default : + width_lod = ( imageInfo->width >> lod ) ? ( imageInfo->width >> lod ) : 1; + } + row_pitch_lod = width_lod * get_pixel_size(imageInfo->format); + if ( imageInfo->type == CL_MEM_OBJECT_IMAGE1D_ARRAY ) + slice_pitch_lod = row_pitch_lod; + else if ( imageInfo->type == CL_MEM_OBJECT_IMAGE3D || imageInfo->type == CL_MEM_OBJECT_IMAGE2D_ARRAY) + slice_pitch_lod = row_pitch_lod * height_lod; + } + else + { + row_pitch_lod = imageInfo->rowPitch; + slice_pitch_lod = imageInfo->slicePitch; + } + if ( x < 0 || y < 0 || z < 0 || x >= (int)width_lod + || ( height_lod != 0 && y >= (int)height_lod ) + || ( depth_lod != 0 && z >= (int)depth_lod ) + || ( imageInfo->arraySize != 0 && z >= (int)imageInfo->arraySize ) ) + { + // Border color + if (imageInfo->format->image_channel_order == CL_DEPTH) + { + outData[ 0 ] = 0; + } + else { + outData[ 0 ] = outData[ 1 ] = outData[ 2 ] = outData[ 3 ] = 0; + if (!has_alpha(imageInfo->format)) + outData[3] = alpha_is_x(imageInfo->format) ? 0 : 1; + } + return; + } + + cl_image_format *format = imageInfo->format; + + unsigned int i; + float tempData[ 4 ]; + + // Advance to the right spot + char *ptr = (char *)imageData; + size_t pixelSize = get_pixel_size( format ); + + ptr += z * slice_pitch_lod + y * row_pitch_lod + x * pixelSize; + + // OpenCL only supports reading floats from certain formats + size_t channelCount = get_format_channel_count( format ); + switch( format->image_channel_data_type ) + { + case CL_SNORM_INT8: + { + char *dPtr = (char *)ptr; + for( i = 0; i < channelCount; i++ ) + tempData[ i ] = CLAMP_FLOAT( (float)dPtr[ i ] / 127.0f ); + break; + } + + case CL_UNORM_INT8: + { + unsigned char *dPtr = (unsigned char *)ptr; + for( i = 0; i < channelCount; i++ ) { + if((is_sRGBA_order(imageInfo->format->image_channel_order)) && i<3) // only RGB need to be converted for sRGBA + tempData[ i ] = (float)sRGBunmap((float)dPtr[ i ] / 255.0f) ; + else + tempData[ i ] = (float)dPtr[ i ] / 255.0f; + } + break; + } + + case CL_SIGNED_INT8: + { + cl_char *dPtr = (cl_char *)ptr; + for( i = 0; i < channelCount; i++ ) + tempData[ i ] = (float)dPtr[ i ]; + break; + } + + case CL_UNSIGNED_INT8: + { + cl_uchar *dPtr = (cl_uchar *)ptr; + for( i = 0; i < channelCount; i++ ) + tempData[ i ] = (float) dPtr[ i ]; + break; + } + + case CL_SNORM_INT16: + { + cl_short *dPtr = (cl_short *)ptr; + for( i = 0; i < channelCount; i++ ) + tempData[ i ] = CLAMP_FLOAT( (float)dPtr[ i ] / 32767.0f ); + break; + } + + case CL_UNORM_INT16: + { + cl_ushort *dPtr = (cl_ushort *)ptr; + for( i = 0; i < channelCount; i++ ) + tempData[ i ] = (float)dPtr[ i ] / 65535.0f; + break; + } + + case CL_SIGNED_INT16: + { + cl_short *dPtr = (cl_short *)ptr; + for( i = 0; i < channelCount; i++ ) + tempData[ i ] = (float)dPtr[ i ]; + break; + } + + case CL_UNSIGNED_INT16: + { + cl_ushort *dPtr = (cl_ushort *)ptr; + for( i = 0; i < channelCount; i++ ) + tempData[ i ] = (float) dPtr[ i ]; + break; + } + + case CL_HALF_FLOAT: + { + cl_ushort *dPtr = (cl_ushort *)ptr; + for( i = 0; i < channelCount; i++ ) + tempData[ i ] = convert_half_to_float( dPtr[ i ] ); + break; + } + + case CL_SIGNED_INT32: + { + cl_int *dPtr = (cl_int *)ptr; + for( i = 0; i < channelCount; i++ ) + tempData[ i ] = (float)dPtr[ i ]; + break; + } + + case CL_UNSIGNED_INT32: + { + cl_uint *dPtr = (cl_uint *)ptr; + for( i = 0; i < channelCount; i++ ) + tempData[ i ] = (float)dPtr[ i ]; + break; + } + + case CL_UNORM_SHORT_565: + { + cl_ushort *dPtr = (cl_ushort *)ptr; + tempData[ 0 ] = (float)( dPtr[ 0 ] >> 11 ) / (float)31; + tempData[ 1 ] = (float)( ( dPtr[ 0 ] >> 5 ) & 63 ) / (float)63; + tempData[ 2 ] = (float)( dPtr[ 0 ] & 31 ) / (float)31; + break; + } + + case CL_UNORM_SHORT_555: + { + cl_ushort *dPtr = (cl_ushort *)ptr; + tempData[ 0 ] = (float)( ( dPtr[ 0 ] >> 10 ) & 31 ) / (float)31; + tempData[ 1 ] = (float)( ( dPtr[ 0 ] >> 5 ) & 31 ) / (float)31; + tempData[ 2 ] = (float)( dPtr[ 0 ] & 31 ) / (float)31; + break; + } + + case CL_UNORM_INT_101010: + { + cl_uint *dPtr = (cl_uint *)ptr; + tempData[ 0 ] = (float)( ( dPtr[ 0 ] >> 20 ) & 0x3ff ) / (float)1023; + tempData[ 1 ] = (float)( ( dPtr[ 0 ] >> 10 ) & 0x3ff ) / (float)1023; + tempData[ 2 ] = (float)( dPtr[ 0 ] & 0x3ff ) / (float)1023; + break; + } + + case CL_FLOAT: + { + float *dPtr = (float *)ptr; + for( i = 0; i < channelCount; i++ ) + tempData[ i ] = (float)dPtr[ i ]; + break; + } +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: + { + cl_ushort *dPtr = (cl_ushort*) ptr; + for( i = 0; i < channelCount; i++ ) + tempData[i] = ((int) dPtr[i] - 16384) * 0x1.0p-14f; + break; + } +#endif + } + + + outData[ 0 ] = outData[ 1 ] = outData[ 2 ] = 0; + outData[ 3 ] = 1; + + switch( format->image_channel_order ) + { + case CL_A: + outData[ 3 ] = tempData[ 0 ]; + break; + case CL_R: + case CL_Rx: + outData[ 0 ] = tempData[ 0 ]; + break; + case CL_RA: + outData[ 0 ] = tempData[ 0 ]; + outData[ 3 ] = tempData[ 1 ]; + break; + case CL_RG: + case CL_RGx: + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 1 ]; + break; + case CL_RGB: + case CL_RGBx: + case CL_sRGB: + case CL_sRGBx: + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 1 ]; + outData[ 2 ] = tempData[ 2 ]; + break; + case CL_RGBA: + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 1 ]; + outData[ 2 ] = tempData[ 2 ]; + outData[ 3 ] = tempData[ 3 ]; + break; + case CL_ARGB: + outData[ 0 ] = tempData[ 1 ]; + outData[ 1 ] = tempData[ 2 ]; + outData[ 2 ] = tempData[ 3 ]; + outData[ 3 ] = tempData[ 0 ]; + break; + case CL_BGRA: + case CL_sBGRA: + outData[ 0 ] = tempData[ 2 ]; + outData[ 1 ] = tempData[ 1 ]; + outData[ 2 ] = tempData[ 0 ]; + outData[ 3 ] = tempData[ 3 ]; + break; + case CL_INTENSITY: + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 0 ]; + outData[ 2 ] = tempData[ 0 ]; + outData[ 3 ] = tempData[ 0 ]; + break; + case CL_LUMINANCE: + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 0 ]; + outData[ 2 ] = tempData[ 0 ]; + break; +#ifdef CL_1RGB_APPLE + case CL_1RGB_APPLE: + outData[ 0 ] = tempData[ 1 ]; + outData[ 1 ] = tempData[ 2 ]; + outData[ 2 ] = tempData[ 3 ]; + outData[ 3 ] = 1.0f; + break; +#endif +#ifdef CL_BGR1_APPLE + case CL_BGR1_APPLE: + outData[ 0 ] = tempData[ 2 ]; + outData[ 1 ] = tempData[ 1 ]; + outData[ 2 ] = tempData[ 0 ]; + outData[ 3 ] = 1.0f; + break; +#endif + case CL_sRGBA: + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 1 ]; + outData[ 2 ] = tempData[ 2 ]; + outData[ 3 ] = tempData[ 3 ]; + break; + case CL_DEPTH: + outData[ 0 ] = tempData[ 0 ]; + break; + default: + log_error("Invalid format:"); + print_header(format, true); + break; + } +} + +void read_image_pixel_float( void *imageData, image_descriptor *imageInfo, + int x, int y, int z, float *outData ) +{ + read_image_pixel_float( imageData, imageInfo, x, y, z, outData, 0 ); +} + +bool get_integer_coords( float x, float y, float z, size_t width, size_t height, size_t depth, image_sampler_data *imageSampler, image_descriptor *imageInfo, int &outX, int &outY, int &outZ ) { + return get_integer_coords_offset(x, y, z, 0.0f, 0.0f, 0.0f, width, height, depth, imageSampler, imageInfo, outX, outY, outZ); +} + +bool get_integer_coords_offset( float x, float y, float z, float xAddressOffset, float yAddressOffset, float zAddressOffset, + size_t width, size_t height, size_t depth, image_sampler_data *imageSampler, image_descriptor *imageInfo, int &outX, int &outY, int &outZ ) +{ + AddressFn adFn = sAddressingTable[ imageSampler ]; + + float refX = floorf( x ), refY = floorf( y ), refZ = floorf( z ); + + // Handle sampler-directed coordinate normalization + clamping. Note that + // the array coordinate for image array types is expected to be + // unnormalized, and is clamped to 0..arraySize-1. + if( imageSampler->normalized_coords ) + { + switch (imageSampler->addressing_mode) + { + case CL_ADDRESS_REPEAT: + x = RepeatNormalizedAddressFn( x, width ); + if (height != 0) { + if (imageInfo->type != CL_MEM_OBJECT_IMAGE1D_ARRAY) + y = RepeatNormalizedAddressFn( y, height ); + } + if (depth != 0) { + if (imageInfo->type != CL_MEM_OBJECT_IMAGE2D_ARRAY) + z = RepeatNormalizedAddressFn( z, depth ); + } + + if (xAddressOffset != 0.0) { + // Add in the offset + x += xAddressOffset; + // Handle wrapping + if (x > width) + x -= (float)width; + if (x < 0) + x += (float)width; + } + if ( (yAddressOffset != 0.0) && (imageInfo->type != CL_MEM_OBJECT_IMAGE1D_ARRAY) ) { + // Add in the offset + y += yAddressOffset; + // Handle wrapping + if (y > height) + y -= (float)height; + if (y < 0) + y += (float)height; + } + if ( (zAddressOffset != 0.0) && (imageInfo->type != CL_MEM_OBJECT_IMAGE2D_ARRAY) ) { + // Add in the offset + z += zAddressOffset; + // Handle wrapping + if (z > depth) + z -= (float)depth; + if (z < 0) + z += (float)depth; + } + break; + + case CL_ADDRESS_MIRRORED_REPEAT: + x = MirroredRepeatNormalizedAddressFn( x, width ); + if (height != 0) { + if (imageInfo->type != CL_MEM_OBJECT_IMAGE1D_ARRAY) + y = MirroredRepeatNormalizedAddressFn( y, height ); + } + if (depth != 0) { + if (imageInfo->type != CL_MEM_OBJECT_IMAGE2D_ARRAY) + z = MirroredRepeatNormalizedAddressFn( z, depth ); + } + + if (xAddressOffset != 0.0) + { + float temp = x + xAddressOffset; + if( temp > (float) width ) + temp = (float) width - (temp - (float) width ); + x = fabsf( temp ); + } + if ( (yAddressOffset != 0.0) && (imageInfo->type != CL_MEM_OBJECT_IMAGE1D_ARRAY) ) { + float temp = y + yAddressOffset; + if( temp > (float) height ) + temp = (float) height - (temp - (float) height ); + y = fabsf( temp ); + } + if ( (zAddressOffset != 0.0) && (imageInfo->type != CL_MEM_OBJECT_IMAGE2D_ARRAY) ) { + float temp = z + zAddressOffset; + if( temp > (float) depth ) + temp = (float) depth - (temp - (float) depth ); + z = fabsf( temp ); + } + break; + + default: + // Also, remultiply to the original coords. This simulates any truncation in + // the pass to OpenCL + x *= (float)width; + x += xAddressOffset; + + if (imageInfo->type != CL_MEM_OBJECT_IMAGE1D_ARRAY) + { + y *= (float)height; + y += yAddressOffset; + } + + if (imageInfo->type != CL_MEM_OBJECT_IMAGE2D_ARRAY) + { + z *= (float)depth; + z += zAddressOffset; + } + break; + } + } + + // At this point, we're dealing with non-normalized coordinates. + + outX = adFn( floorf( x ), width ); + + // 1D and 2D arrays require special care for the index coordinate: + + switch (imageInfo->type) { + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + outY = calculate_array_index(y, (float)imageInfo->arraySize - 1.0f); + outZ = 0.0f; /* don't care! */ + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + outY = adFn( floorf( y ), height ); + outZ = calculate_array_index(z, (float)imageInfo->arraySize - 1.0f); + break; + default: + // legacy path: + if (height != 0) + outY = adFn( floorf( y ), height ); + if( depth != 0 ) + outZ = adFn( floorf( z ), depth ); + } + + return !( (int)refX == outX && (int)refY == outY && (int)refZ == outZ ); +} + +static float frac(float a) { + return a - floorf(a); +} + +static inline void pixelMax( const float a[4], const float b[4], float *results ); +static inline void pixelMax( const float a[4], const float b[4], float *results ) +{ + for( int i = 0; i < 4; i++ ) + results[i] = errMax( fabsf(a[i]), fabsf(b[i]) ); +} + +// If containsDenorms is NULL, flush denorms to zero +// if containsDenorms is not NULL, record whether there are any denorms +static inline void check_for_denorms(float a[4], int *containsDenorms ); +static inline void check_for_denorms(float a[4], int *containsDenorms ) +{ + if( NULL == containsDenorms ) + { + for( int i = 0; i < 4; i++ ) + { + if( fabsf(a[i]) < FLT_MIN ) + a[i] = copysignf( 0.0f, a[i] ); + } + } + else + { + for( int i = 0; i < 4; i++ ) + { + if( fabs(a[i]) < FLT_MIN ) + { + *containsDenorms = 1; + break; + } + } + } +} + +inline float calculate_array_index( float coord, float extent ) { + // from Section 8.4 of the 1.2 Spec 'Selecting an Image from an Image Array' + // + // given coordinate 'w' that represents an index: + // layer_index = clamp( rint(w), 0, image_array_size - 1) + + float ret = rintf( coord ); + ret = ret > extent ? extent : ret; + ret = ret < 0.0f ? 0.0f : ret; + + return ret; +} + +/* + * Utility function to unnormalized a coordinate given a particular sampler. + * + * name - the name of the coordinate, used for verbose debugging only + * coord - the coordinate requiring unnormalization + * offset - an addressing offset to be added to the coordinate + * extent - the max value for this coordinate (e.g. width for x) + */ +static float unnormalize_coordinate( const char* name, float coord, + float offset, float extent, cl_addressing_mode addressing_mode, int verbose ) +{ + float ret = 0.0f; + + switch (addressing_mode) { + case CL_ADDRESS_REPEAT: + ret = RepeatNormalizedAddressFn( coord, extent ); + + if ( verbose ) { + log_info( "\tRepeat filter denormalizes %s (%f) to %f\n", + name, coord, ret ); + } + + if (offset != 0.0) { + // Add in the offset, and handle wrapping. + ret += offset; + if (ret > extent) ret -= extent; + if (ret < 0.0) ret += extent; + } + + if (verbose && offset != 0.0f) { + log_info( "\tAddress offset of %f added to get %f\n", offset, ret ); + } + break; + + case CL_ADDRESS_MIRRORED_REPEAT: + ret = MirroredRepeatNormalizedAddressFn( coord, extent ); + + if ( verbose ) { + log_info( "\tMirrored repeat filter denormalizes %s (%f) to %f\n", + name, coord, ret ); + } + + if (offset != 0.0) { + float temp = ret + offset; + if( temp > extent ) + temp = extent - (temp - extent ); + ret = fabsf( temp ); + } + + if (verbose && offset != 0.0f) { + log_info( "\tAddress offset of %f added to get %f\n", offset, ret ); + } + break; + + default: + + ret = coord * extent; + + if ( verbose ) { + log_info( "\tFilter denormalizes %s to %f (%f * %f)\n", + name, ret, coord, extent); + } + + ret += offset; + + if (verbose && offset != 0.0f) { + log_info( "\tAddress offset of %f added to get %f\n", offset, ret ); + } + } + + return ret; +} + +FloatPixel sample_image_pixel_float( void *imageData, image_descriptor *imageInfo, + float x, float y, float z, + image_sampler_data *imageSampler, float *outData, int verbose, int *containsDenorms ) { + return sample_image_pixel_float_offset(imageData, imageInfo, x, y, z, 0.0f, 0.0f, 0.0f, imageSampler, outData, verbose, containsDenorms); +} + +// returns max pixel value of the pixels touched +FloatPixel sample_image_pixel_float( void *imageData, image_descriptor *imageInfo, + float x, float y, float z, + image_sampler_data *imageSampler, float *outData, int verbose, int *containsDenorms , int lod) { + return sample_image_pixel_float_offset(imageData, imageInfo, x, y, z, 0.0f, 0.0f, 0.0f, imageSampler, outData, verbose, containsDenorms, lod); +} +FloatPixel sample_image_pixel_float_offset( void *imageData, image_descriptor *imageInfo, + float x, float y, float z, float xAddressOffset, float yAddressOffset, float zAddressOffset, + image_sampler_data *imageSampler, float *outData, int verbose, int *containsDenorms , int lod) +{ + AddressFn adFn = sAddressingTable[ imageSampler ]; + FloatPixel returnVal; + size_t width_lod = imageInfo->width, height_lod = imageInfo->height, depth_lod = imageInfo->depth; + size_t slice_pitch_lod = 0, row_pitch_lod = 0; + + if ( imageInfo->num_mip_levels > 1 ) + { + switch(imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE3D : + depth_lod = ( imageInfo->depth >> lod ) ? ( imageInfo->depth >> lod ) : 1; + case CL_MEM_OBJECT_IMAGE2D : + case CL_MEM_OBJECT_IMAGE2D_ARRAY : + height_lod = ( imageInfo->height >> lod ) ? ( imageInfo->height >> lod ) : 1; + default : + width_lod = ( imageInfo->width >> lod ) ? ( imageInfo->width >> lod ) : 1; + } + row_pitch_lod = width_lod * get_pixel_size(imageInfo->format); + if ( imageInfo->type == CL_MEM_OBJECT_IMAGE1D_ARRAY ) + slice_pitch_lod = row_pitch_lod; + else if ( imageInfo->type == CL_MEM_OBJECT_IMAGE3D || imageInfo->type == CL_MEM_OBJECT_IMAGE2D_ARRAY) + slice_pitch_lod = row_pitch_lod * height_lod; + } + else + { + slice_pitch_lod = imageInfo->slicePitch; + row_pitch_lod = imageInfo->rowPitch; + } + + if( containsDenorms ) + *containsDenorms = 0; + + if( imageSampler->normalized_coords ) { + + // We need to unnormalize our coordinates differently depending on + // the image type, but 'x' is always processed the same way. + + x = unnormalize_coordinate("x", x, xAddressOffset, (float)width_lod, + imageSampler->addressing_mode, verbose); + + switch (imageInfo->type) { + + // The image array types require special care: + + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + z = 0; // don't care -- unused for 1D arrays + break; + + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + y = unnormalize_coordinate("y", y, yAddressOffset, (float)height_lod, + imageSampler->addressing_mode, verbose); + break; + + // Everybody else: + + default: + y = unnormalize_coordinate("y", y, yAddressOffset, (float)height_lod, + imageSampler->addressing_mode, verbose); + z = unnormalize_coordinate("z", z, zAddressOffset, (float)depth_lod, + imageSampler->addressing_mode, verbose); + } + + } else if ( verbose ) { + + switch (imageInfo->type) { + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + log_info("Starting coordinate: %f, array index %f\n", x, y); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + log_info("Starting coordinate: %f, %f, array index %f\n", x, y, z); + break; + case CL_MEM_OBJECT_IMAGE1D: + case CL_MEM_OBJECT_IMAGE1D_BUFFER: + log_info("Starting coordinate: %f\b", x); + break; + case CL_MEM_OBJECT_IMAGE2D: + log_info("Starting coordinate: %f, %f\n", x, y); + break; + case CL_MEM_OBJECT_IMAGE3D: + default: + log_info("Starting coordinate: %f, %f, %f\n", x, y, z); + } + } + + // At this point, we have unnormalized coordinates. + + if( imageSampler->filter_mode == CL_FILTER_NEAREST ) + { + int ix, iy, iz; + + // We apply the addressing function to the now-unnormalized + // coordinates. Note that the array cases again require special + // care, per section 8.4 in the OpenCL 1.2 Specification. + + ix = adFn( floorf( x ), width_lod ); + + switch (imageInfo->type) { + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + iy = calculate_array_index( y, (float)(imageInfo->arraySize - 1) ); + iz = 0; + if( verbose ) { + log_info("\tArray index %f evaluates to %d\n",y, iy ); + } + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + iy = adFn( floorf( y ), height_lod ); + iz = calculate_array_index( z, (float)(imageInfo->arraySize - 1) ); + if( verbose ) { + log_info("\tArray index %f evaluates to %d\n",z, iz ); + } + break; + default: + iy = adFn( floorf( y ), height_lod ); + if( depth_lod != 0 ) + iz = adFn( floorf( z ), depth_lod ); + else + iz = 0; + } + + if( verbose ) { + if( iz ) + log_info( "\tReference integer coords calculated: { %d, %d, %d }\n", ix, iy, iz ); + else + log_info( "\tReference integer coords calculated: { %d, %d }\n", ix, iy ); + } + + read_image_pixel_float( imageData, imageInfo, ix, iy, iz, outData, lod ); + check_for_denorms( outData, containsDenorms ); + for( int i = 0; i < 4; i++ ) + returnVal.p[i] = fabsf( outData[i] ); + return returnVal; + } + else + { + // Linear filtering cases. + + size_t width = width_lod, height = height_lod, depth = depth_lod; + + // Image arrays can use 2D filtering, but require us to walk into the + // image a certain number of slices before reading. + + if( depth == 0 || imageInfo->type == CL_MEM_OBJECT_IMAGE2D_ARRAY || + imageInfo->type == CL_MEM_OBJECT_IMAGE1D_ARRAY) + { + float array_index = 0; + + size_t layer_offset = 0; + + if (imageInfo->type == CL_MEM_OBJECT_IMAGE2D_ARRAY) { + array_index = calculate_array_index(z, (float)(imageInfo->arraySize - 1)); + layer_offset = slice_pitch_lod * (size_t)array_index; + } + else if (imageInfo->type == CL_MEM_OBJECT_IMAGE1D_ARRAY) { + array_index = calculate_array_index(y, (float)(imageInfo->arraySize - 1)); + layer_offset = slice_pitch_lod * (size_t)array_index; + + // Set up y and height so that the filtering below is correct + // 1D filtering on a single slice. + height = 1; + } + + int x1 = adFn( floorf( x - 0.5f ), width ); + int y1 = 0; + int x2 = adFn( floorf( x - 0.5f ) + 1, width ); + int y2 = 0; + if ((imageInfo->type != CL_MEM_OBJECT_IMAGE1D) && + (imageInfo->type != CL_MEM_OBJECT_IMAGE1D_ARRAY) && + (imageInfo->type != CL_MEM_OBJECT_IMAGE1D_BUFFER)) { + y1 = adFn( floorf( y - 0.5f ), height ); + y2 = adFn( floorf( y - 0.5f ) + 1, height ); + } else { + y = 0.5f; + } + + if( verbose ) { + log_info( "\tActual integer coords used (i = floor(x-.5)): i0:{ %d, %d } and i1:{ %d, %d }\n", x1, y1, x2, y2 ); + log_info( "\tArray coordinate is %f\n", array_index); + } + + // Walk to beginning of the 'correct' slice, if needed. + char* imgPtr = ((char*)imageData) + layer_offset; + + float upLeft[ 4 ], upRight[ 4 ], lowLeft[ 4 ], lowRight[ 4 ]; + float maxUp[4], maxLow[4]; + read_image_pixel_float( imgPtr, imageInfo, x1, y1, 0, upLeft, lod ); + read_image_pixel_float( imgPtr, imageInfo, x2, y1, 0, upRight, lod ); + check_for_denorms( upLeft, containsDenorms ); + check_for_denorms( upRight, containsDenorms ); + pixelMax( upLeft, upRight, maxUp ); + read_image_pixel_float( imgPtr, imageInfo, x1, y2, 0, lowLeft, lod ); + read_image_pixel_float( imgPtr, imageInfo, x2, y2, 0, lowRight, lod ); + check_for_denorms( lowLeft, containsDenorms ); + check_for_denorms( lowRight, containsDenorms ); + pixelMax( lowLeft, lowRight, maxLow ); + pixelMax( maxUp, maxLow, returnVal.p ); + + if( verbose ) + { + if( NULL == containsDenorms ) + log_info( "\tSampled pixels (rgba order, denorms flushed to zero):\n" ); + else + log_info( "\tSampled pixels (rgba order):\n" ); + log_info( "\t\tp00: %f, %f, %f, %f\n", upLeft[0], upLeft[1], upLeft[2], upLeft[3] ); + log_info( "\t\tp01: %f, %f, %f, %f\n", upRight[0], upRight[1], upRight[2], upRight[3] ); + log_info( "\t\tp10: %f, %f, %f, %f\n", lowLeft[0], lowLeft[1], lowLeft[2], lowLeft[3] ); + log_info( "\t\tp11: %f, %f, %f, %f\n", lowRight[0], lowRight[1], lowRight[2], lowRight[3] ); + } + + bool printMe = false; + if( x1 <= 0 || x2 <= 0 || x1 >= (int)width-1 || x2 >= (int)width-1 ) + printMe = true; + if( y1 <= 0 || y2 <= 0 || y1 >= (int)height-1 || y2 >= (int)height-1 ) + printMe = true; + + double weights[ 2 ][ 2 ]; + + weights[ 0 ][ 0 ] = weights[ 0 ][ 1 ] = 1.0 - frac( x - 0.5f ); + weights[ 1 ][ 0 ] = weights[ 1 ][ 1 ] = frac( x - 0.5f ); + weights[ 0 ][ 0 ] *= 1.0 - frac( y - 0.5f ); + weights[ 1 ][ 0 ] *= 1.0 - frac( y - 0.5f ); + weights[ 0 ][ 1 ] *= frac( y - 0.5f ); + weights[ 1 ][ 1 ] *= frac( y - 0.5f ); + + if( verbose ) + log_info( "\tfrac( x - 0.5f ) = %f, frac( y - 0.5f ) = %f\n", frac( x - 0.5f ), frac( y - 0.5f ) ); + + for( int i = 0; i < 3; i++ ) + { + outData[ i ] = (float)( ( upLeft[ i ] * weights[ 0 ][ 0 ] ) + + ( upRight[ i ] * weights[ 1 ][ 0 ] ) + + ( lowLeft[ i ] * weights[ 0 ][ 1 ] ) + + ( lowRight[ i ] * weights[ 1 ][ 1 ] )); + // flush subnormal results to zero if necessary + if( NULL == containsDenorms && fabs(outData[i]) < FLT_MIN ) + outData[i] = copysignf( 0.0f, outData[i] ); + } + outData[ 3 ] = (float)( ( upLeft[ 3 ] * weights[ 0 ][ 0 ] ) + + ( upRight[ 3 ] * weights[ 1 ][ 0 ] ) + + ( lowLeft[ 3 ] * weights[ 0 ][ 1 ] ) + + ( lowRight[ 3 ] * weights[ 1 ][ 1 ] )); + // flush subnormal results to zero if necessary + if( NULL == containsDenorms && fabs(outData[3]) < FLT_MIN ) + outData[3] = copysignf( 0.0f, outData[3] ); + } + else + { + // 3D linear filtering + int x1 = adFn( floorf( x - 0.5f ), width_lod ); + int y1 = adFn( floorf( y - 0.5f ), height_lod ); + int z1 = adFn( floorf( z - 0.5f ), depth_lod ); + int x2 = adFn( floorf( x - 0.5f ) + 1, width_lod ); + int y2 = adFn( floorf( y - 0.5f ) + 1, height_lod ); + int z2 = adFn( floorf( z - 0.5f ) + 1, depth_lod ); + + if( verbose ) + log_info( "\tActual integer coords used (i = floor(x-.5)): i0:{%d, %d, %d} and i1:{%d, %d, %d}\n", x1, y1, z1, x2, y2, z2 ); + + float upLeftA[ 4 ], upRightA[ 4 ], lowLeftA[ 4 ], lowRightA[ 4 ]; + float upLeftB[ 4 ], upRightB[ 4 ], lowLeftB[ 4 ], lowRightB[ 4 ]; + float pixelMaxA[4], pixelMaxB[4]; + read_image_pixel_float( imageData, imageInfo, x1, y1, z1, upLeftA, lod ); + read_image_pixel_float( imageData, imageInfo, x2, y1, z1, upRightA, lod ); + check_for_denorms( upLeftA, containsDenorms ); + check_for_denorms( upRightA, containsDenorms ); + pixelMax( upLeftA, upRightA, pixelMaxA ); + read_image_pixel_float( imageData, imageInfo, x1, y2, z1, lowLeftA, lod ); + read_image_pixel_float( imageData, imageInfo, x2, y2, z1, lowRightA, lod ); + check_for_denorms( lowLeftA, containsDenorms ); + check_for_denorms( lowRightA, containsDenorms ); + pixelMax( lowLeftA, lowRightA, pixelMaxB ); + pixelMax( pixelMaxA, pixelMaxB, returnVal.p); + read_image_pixel_float( imageData, imageInfo, x1, y1, z2, upLeftB, lod ); + read_image_pixel_float( imageData, imageInfo, x2, y1, z2, upRightB, lod ); + check_for_denorms( upLeftB, containsDenorms ); + check_for_denorms( upRightB, containsDenorms ); + pixelMax( upLeftB, upRightB, pixelMaxA ); + read_image_pixel_float( imageData, imageInfo, x1, y2, z2, lowLeftB, lod ); + read_image_pixel_float( imageData, imageInfo, x2, y2, z2, lowRightB, lod ); + check_for_denorms( lowLeftB, containsDenorms ); + check_for_denorms( lowRightB, containsDenorms ); + pixelMax( lowLeftB, lowRightB, pixelMaxB ); + pixelMax( pixelMaxA, pixelMaxB, pixelMaxA); + pixelMax( pixelMaxA, returnVal.p, returnVal.p ); + + if( verbose ) + { + if( NULL == containsDenorms ) + log_info( "\tSampled pixels (rgba order, denorms flushed to zero):\n" ); + else + log_info( "\tSampled pixels (rgba order):\n" ); + log_info( "\t\tp000: %f, %f, %f, %f\n", upLeftA[0], upLeftA[1], upLeftA[2], upLeftA[3] ); + log_info( "\t\tp001: %f, %f, %f, %f\n", upRightA[0], upRightA[1], upRightA[2], upRightA[3] ); + log_info( "\t\tp010: %f, %f, %f, %f\n", lowLeftA[0], lowLeftA[1], lowLeftA[2], lowLeftA[3] ); + log_info( "\t\tp011: %f, %f, %f, %f\n\n", lowRightA[0], lowRightA[1], lowRightA[2], lowRightA[3] ); + log_info( "\t\tp100: %f, %f, %f, %f\n", upLeftB[0], upLeftB[1], upLeftB[2], upLeftB[3] ); + log_info( "\t\tp101: %f, %f, %f, %f\n", upRightB[0], upRightB[1], upRightB[2], upRightB[3] ); + log_info( "\t\tp110: %f, %f, %f, %f\n", lowLeftB[0], lowLeftB[1], lowLeftB[2], lowLeftB[3] ); + log_info( "\t\tp111: %f, %f, %f, %f\n", lowRightB[0], lowRightB[1], lowRightB[2], lowRightB[3] ); + } + + double weights[ 2 ][ 2 ][ 2 ]; + + float a = frac( x - 0.5f ), b = frac( y - 0.5f ), c = frac( z - 0.5f ); + weights[ 0 ][ 0 ][ 0 ] = weights[ 0 ][ 1 ][ 0 ] = weights[ 0 ][ 0 ][ 1 ] = weights[ 0 ][ 1 ][ 1 ] = 1.f - a; + weights[ 1 ][ 0 ][ 0 ] = weights[ 1 ][ 1 ][ 0 ] = weights[ 1 ][ 0 ][ 1 ] = weights[ 1 ][ 1 ][ 1 ] = a; + weights[ 0 ][ 0 ][ 0 ] *= 1.f - b; + weights[ 1 ][ 0 ][ 0 ] *= 1.f - b; + weights[ 0 ][ 0 ][ 1 ] *= 1.f - b; + weights[ 1 ][ 0 ][ 1 ] *= 1.f - b; + weights[ 0 ][ 1 ][ 0 ] *= b; + weights[ 1 ][ 1 ][ 0 ] *= b; + weights[ 0 ][ 1 ][ 1 ] *= b; + weights[ 1 ][ 1 ][ 1 ] *= b; + weights[ 0 ][ 0 ][ 0 ] *= 1.f - c; + weights[ 0 ][ 1 ][ 0 ] *= 1.f - c; + weights[ 1 ][ 0 ][ 0 ] *= 1.f - c; + weights[ 1 ][ 1 ][ 0 ] *= 1.f - c; + weights[ 0 ][ 0 ][ 1 ] *= c; + weights[ 0 ][ 1 ][ 1 ] *= c; + weights[ 1 ][ 0 ][ 1 ] *= c; + weights[ 1 ][ 1 ][ 1 ] *= c; + + if( verbose ) + log_info( "\tfrac( x - 0.5f ) = %f, frac( y - 0.5f ) = %f, frac( z - 0.5f ) = %f\n", + frac( x - 0.5f ), frac( y - 0.5f ), frac( z - 0.5f ) ); + + for( int i = 0; i < 3; i++ ) + { + outData[ i ] = (float)( ( upLeftA[ i ] * weights[ 0 ][ 0 ][ 0 ] ) + + ( upRightA[ i ] * weights[ 1 ][ 0 ][ 0 ] ) + + ( lowLeftA[ i ] * weights[ 0 ][ 1 ][ 0 ] ) + + ( lowRightA[ i ] * weights[ 1 ][ 1 ][ 0 ] ) + + ( upLeftB[ i ] * weights[ 0 ][ 0 ][ 1 ] ) + + ( upRightB[ i ] * weights[ 1 ][ 0 ][ 1 ] ) + + ( lowLeftB[ i ] * weights[ 0 ][ 1 ][ 1 ] ) + + ( lowRightB[ i ] * weights[ 1 ][ 1 ][ 1 ] )); + // flush subnormal results to zero if necessary + if( NULL == containsDenorms && fabs(outData[i]) < FLT_MIN ) + outData[i] = copysignf( 0.0f, outData[i] ); + } + outData[ 3 ] = (float)( ( upLeftA[ 3 ] * weights[ 0 ][ 0 ][ 0 ] ) + + ( upRightA[ 3 ] * weights[ 1 ][ 0 ][ 0 ] ) + + ( lowLeftA[ 3 ] * weights[ 0 ][ 1 ][ 0 ] ) + + ( lowRightA[ 3 ] * weights[ 1 ][ 1 ][ 0 ] ) + + ( upLeftB[ 3 ] * weights[ 0 ][ 0 ][ 1 ] ) + + ( upRightB[ 3 ] * weights[ 1 ][ 0 ][ 1 ] ) + + ( lowLeftB[ 3 ] * weights[ 0 ][ 1 ][ 1 ] ) + + ( lowRightB[ 3 ] * weights[ 1 ][ 1 ][ 1 ] )); + // flush subnormal results to zero if necessary + if( NULL == containsDenorms && fabs(outData[3]) < FLT_MIN ) + outData[3] = copysignf( 0.0f, outData[3] ); + } + + return returnVal; + } +} + +FloatPixel sample_image_pixel_float_offset( void *imageData, image_descriptor *imageInfo, + float x, float y, float z, float xAddressOffset, float yAddressOffset, float zAddressOffset, + image_sampler_data *imageSampler, float *outData, int verbose, int *containsDenorms ) +{ + return sample_image_pixel_float_offset( imageData, imageInfo, x, y, z, xAddressOffset, yAddressOffset, zAddressOffset, + imageSampler, outData, verbose, containsDenorms, 0); +} + + +int debug_find_vector_in_image( void *imagePtr, image_descriptor *imageInfo, + void *vectorToFind, size_t vectorSize, int *outX, int *outY, int *outZ, size_t lod ) +{ + int foundCount = 0; + char *iPtr = (char *)imagePtr; + size_t width; + size_t depth; + size_t height; + size_t row_pitch; + size_t slice_pitch; + + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + width = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1; + height = 1; + depth = 1; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + width = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1; + height = 1; + depth = imageInfo->arraySize; + break; + case CL_MEM_OBJECT_IMAGE2D: + width = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1; + height = (imageInfo->height >> lod) ? (imageInfo->height >> lod) : 1; + depth = 1; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + width = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1; + height = (imageInfo->height >> lod) ? (imageInfo->height >> lod) : 1; + depth = imageInfo->arraySize; + break; + case CL_MEM_OBJECT_IMAGE3D: + width = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1; + height = (imageInfo->height >> lod) ? (imageInfo->height >> lod) : 1; + depth = (imageInfo->depth >> lod) ? (imageInfo->depth >> lod) : 1; + break; + } + + row_pitch = width * get_pixel_size( imageInfo->format ); + slice_pitch = row_pitch * height; + + for( size_t z = 0; z < depth; z++ ) + { + for( size_t y = 0; y < height; y++ ) + { + for( size_t x = 0; x < width; x++) + { + if( memcmp( iPtr, vectorToFind, vectorSize ) == 0 ) + { + if( foundCount == 0 ) + { + *outX = (int)x; + if (outY != NULL) + *outY = (int)y; + if( outZ != NULL ) + *outZ = (int)z; + } + foundCount++; + } + iPtr += vectorSize; + } + iPtr += row_pitch - ( width * vectorSize ); + } + iPtr += slice_pitch - ( height * row_pitch ); + } + return foundCount; +} + +int debug_find_pixel_in_image( void *imagePtr, image_descriptor *imageInfo, + unsigned int *valuesToFind, int *outX, int *outY, int *outZ, int lod ) +{ + char vectorToFind[ 4 * 4 ]; + size_t vectorSize = get_format_channel_count( imageInfo->format ); + + + if( imageInfo->format->image_channel_data_type == CL_UNSIGNED_INT8 ) + { + unsigned char *p = (unsigned char *)vectorToFind; + for( unsigned int i = 0; i < vectorSize; i++ ) + p[i] = (unsigned char)valuesToFind[i]; + } + else if( imageInfo->format->image_channel_data_type == CL_UNSIGNED_INT16 ) + { + unsigned short *p = (unsigned short *)vectorToFind; + for( unsigned int i = 0; i < vectorSize; i++ ) + p[i] = (unsigned short)valuesToFind[i]; + vectorSize *= 2; + } + else if( imageInfo->format->image_channel_data_type == CL_UNSIGNED_INT32 ) + { + unsigned int *p = (unsigned int *)vectorToFind; + for( unsigned int i = 0; i < vectorSize; i++ ) + p[i] = (unsigned int)valuesToFind[i]; + vectorSize *= 4; + } + else + { + log_info( "WARNING: Unable to search for debug pixel: invalid image format\n" ); + return false; + } + return debug_find_vector_in_image( imagePtr, imageInfo, vectorToFind, vectorSize, outX, outY, outZ, lod ); +} + +int debug_find_pixel_in_image( void *imagePtr, image_descriptor *imageInfo, + int *valuesToFind, int *outX, int *outY, int *outZ, int lod ) +{ + char vectorToFind[ 4 * 4 ]; + size_t vectorSize = get_format_channel_count( imageInfo->format ); + + if( imageInfo->format->image_channel_data_type == CL_SIGNED_INT8 ) + { + char *p = (char *)vectorToFind; + for( unsigned int i = 0; i < vectorSize; i++ ) + p[i] = (char)valuesToFind[i]; + } + else if( imageInfo->format->image_channel_data_type == CL_SIGNED_INT16 ) + { + short *p = (short *)vectorToFind; + for( unsigned int i = 0; i < vectorSize; i++ ) + p[i] = (short)valuesToFind[i]; + vectorSize *= 2; + } + else if( imageInfo->format->image_channel_data_type == CL_SIGNED_INT32 ) + { + int *p = (int *)vectorToFind; + for( unsigned int i = 0; i < vectorSize; i++ ) + p[i] = (int)valuesToFind[i]; + vectorSize *= 4; + } + else + { + log_info( "WARNING: Unable to search for debug pixel: invalid image format\n" ); + return false; + } + return debug_find_vector_in_image( imagePtr, imageInfo, vectorToFind, vectorSize, outX, outY, outZ, lod ); +} + +int debug_find_pixel_in_image( void *imagePtr, image_descriptor *imageInfo, + float *valuesToFind, int *outX, int *outY, int *outZ, int lod ) +{ + char vectorToFind[ 4 * 4 ]; + float swizzled[4]; + memcpy( swizzled, valuesToFind, sizeof( swizzled ) ); + size_t vectorSize = get_pixel_size( imageInfo->format ); + pack_image_pixel( swizzled, imageInfo->format, vectorToFind ); + return debug_find_vector_in_image( imagePtr, imageInfo, vectorToFind, vectorSize, outX, outY, outZ, lod ); +} + +template void swizzle_vector_for_image( T *srcVector, const cl_image_format *imageFormat ) +{ + T temp; + switch( imageFormat->image_channel_order ) + { + case CL_A: + srcVector[ 0 ] = srcVector[ 3 ]; + break; + case CL_R: + case CL_Rx: + case CL_RG: + case CL_RGx: + case CL_RGB: + case CL_RGBx: + case CL_RGBA: + case CL_sRGB: + case CL_sRGBx: + case CL_sRGBA: + break; + case CL_RA: + srcVector[ 1 ] = srcVector[ 3 ]; + break; + case CL_ARGB: + temp = srcVector[ 3 ]; + srcVector[ 3 ] = srcVector[ 2 ]; + srcVector[ 2 ] = srcVector[ 1 ]; + srcVector[ 1 ] = srcVector[ 0 ]; + srcVector[ 0 ] = temp; + break; + case CL_BGRA: + case CL_sBGRA: + temp = srcVector[ 0 ]; + srcVector[ 0 ] = srcVector[ 2 ]; + srcVector[ 2 ] = temp; + break; + case CL_INTENSITY: + srcVector[ 3 ] = srcVector[ 0 ]; + srcVector[ 2 ] = srcVector[ 0 ]; + srcVector[ 1 ] = srcVector[ 0 ]; + break; + case CL_LUMINANCE: + srcVector[ 2 ] = srcVector[ 0 ]; + srcVector[ 1 ] = srcVector[ 0 ]; + break; +#ifdef CL_1RGB_APPLE + case CL_1RGB_APPLE: + temp = srcVector[ 3 ]; + srcVector[ 3 ] = srcVector[ 2 ]; + srcVector[ 2 ] = srcVector[ 1 ]; + srcVector[ 1 ] = srcVector[ 0 ]; + srcVector[ 0 ] = temp; + break; +#endif +#ifdef CL_BGR1_APPLE + case CL_BGR1_APPLE: + temp = srcVector[ 0 ]; + srcVector[ 0 ] = srcVector[ 2 ]; + srcVector[ 2 ] = temp; + break; +#endif + } +} + +#define SATURATE( v, min, max ) ( v < min ? min : ( v > max ? max : v ) ) + +void pack_image_pixel( unsigned int *srcVector, const cl_image_format *imageFormat, void *outData ) +{ + swizzle_vector_for_image( srcVector, imageFormat ); + size_t channelCount = get_format_channel_count( imageFormat ); + + switch( imageFormat->image_channel_data_type ) + { + case CL_UNSIGNED_INT8: + { + unsigned char *ptr = (unsigned char *)outData; + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = (unsigned char)SATURATE( srcVector[ i ], 0, 255 ); + break; + } + case CL_UNSIGNED_INT16: + { + unsigned short *ptr = (unsigned short *)outData; + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = (unsigned short)SATURATE( srcVector[ i ], 0, 65535 ); + break; + } + case CL_UNSIGNED_INT32: + { + unsigned int *ptr = (unsigned int *)outData; + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = (unsigned int)srcVector[ i ]; + break; + } + default: + break; + } +} + +void pack_image_pixel( int *srcVector, const cl_image_format *imageFormat, void *outData ) +{ + swizzle_vector_for_image( srcVector, imageFormat ); + size_t chanelCount = get_format_channel_count( imageFormat ); + + switch( imageFormat->image_channel_data_type ) + { + case CL_SIGNED_INT8: + { + char *ptr = (char *)outData; + for( unsigned int i = 0; i < chanelCount; i++ ) + ptr[ i ] = (char)SATURATE( srcVector[ i ], -128, 127 ); + break; + } + case CL_SIGNED_INT16: + { + short *ptr = (short *)outData; + for( unsigned int i = 0; i < chanelCount; i++ ) + ptr[ i ] = (short)SATURATE( srcVector[ i ], -32768, 32767 ); + break; + } + case CL_SIGNED_INT32: + { + int *ptr = (int *)outData; + for( unsigned int i = 0; i < chanelCount; i++ ) + ptr[ i ] = (int)srcVector[ i ]; + break; + } + default: + break; + } +} + +int round_to_even( float v ) +{ + // clamp overflow + if( v >= - (float) INT_MIN ) + return INT_MAX; + if( v <= (float) INT_MIN ) + return INT_MIN; + + // round fractional values to integer value + if( fabsf(v) < MAKE_HEX_FLOAT(0x1.0p23f, 0x1L, 23) ) + { + static const float magic[2] = { MAKE_HEX_FLOAT(0x1.0p23f, 0x1L, 23), MAKE_HEX_FLOAT(-0x1.0p23f, -0x1L, 23) }; + float magicVal = magic[ v < 0.0f ]; + v += magicVal; + v -= magicVal; + } + + return (int) v; +} + +void pack_image_pixel( float *srcVector, const cl_image_format *imageFormat, void *outData ) +{ + swizzle_vector_for_image( srcVector, imageFormat ); + size_t channelCount = get_format_channel_count( imageFormat ); + switch( imageFormat->image_channel_data_type ) + { + case CL_HALF_FLOAT: + { + cl_ushort *ptr = (cl_ushort *)outData; + + switch( gFloatToHalfRoundingMode ) + { + case kRoundToNearestEven: + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = float2half_rte( srcVector[ i ] ); + break; + case kRoundTowardZero: + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = float2half_rtz( srcVector[ i ] ); + break; + default: + log_error( "ERROR: Test internal error -- unhandled or unknown float->half rounding mode.\n" ); + exit(-1); + break; + } + break; + } + + case CL_FLOAT: + { + cl_float *ptr = (cl_float *)outData; + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = srcVector[ i ]; + break; + } + + case CL_SNORM_INT8: + { + cl_char *ptr = (cl_char *)outData; + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = (char)NORMALIZE_SIGNED( srcVector[ i ], -127.0f, 127.f ); + break; + } + case CL_SNORM_INT16: + { + cl_short *ptr = (cl_short *)outData; + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = (short)NORMALIZE_SIGNED( srcVector[ i ], -32767.f, 32767.f ); + break; + } + case CL_UNORM_INT8: + { + cl_uchar *ptr = (cl_uchar *)outData; + if ( is_sRGBA_order(imageFormat->image_channel_order) ) + { + ptr[ 0 ] = (unsigned char)( sRGBmap( srcVector[ 0 ] ) + 0.5 ); + ptr[ 1 ] = (unsigned char)( sRGBmap( srcVector[ 1 ] ) + 0.5 ); + ptr[ 2 ] = (unsigned char)( sRGBmap( srcVector[ 2 ] ) + 0.5 ); + if (channelCount == 4) + ptr[ 3 ] = (unsigned char)NORMALIZE( srcVector[ 3 ], 255.f ); + } + else + { + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = (unsigned char)NORMALIZE( srcVector[ i ], 255.f ); + } +#ifdef CL_1RGB_APPLE + if( imageFormat->image_channel_order == CL_1RGB_APPLE ) + ptr[0] = 255.0f; +#endif +#ifdef CL_BGR1_APPLE + if( imageFormat->image_channel_order == CL_BGR1_APPLE ) + ptr[3] = 255.0f; +#endif + break; + } + case CL_UNORM_INT16: + { + cl_ushort *ptr = (cl_ushort *)outData; + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = (unsigned short)NORMALIZE( srcVector[ i ], 65535.f ); + break; + } + case CL_UNORM_SHORT_555: + { + cl_ushort *ptr = (cl_ushort *)outData; + ptr[ 0 ] = ( ( (unsigned short)NORMALIZE( srcVector[ 0 ], 31.f ) & 31 ) << 10 ) | + ( ( (unsigned short)NORMALIZE( srcVector[ 1 ], 31.f ) & 31 ) << 5 ) | + ( ( (unsigned short)NORMALIZE( srcVector[ 2 ], 31.f ) & 31 ) << 0 ); + break; + } + case CL_UNORM_SHORT_565: + { + cl_ushort *ptr = (cl_ushort *)outData; + ptr[ 0 ] = ( ( (unsigned short)NORMALIZE( srcVector[ 0 ], 31.f ) & 31 ) << 11 ) | + ( ( (unsigned short)NORMALIZE( srcVector[ 1 ], 63.f ) & 63 ) << 5 ) | + ( ( (unsigned short)NORMALIZE( srcVector[ 2 ], 31.f ) & 31 ) << 0 ); + break; + } + case CL_UNORM_INT_101010: + { + cl_uint *ptr = (cl_uint *)outData; + ptr[ 0 ] = ( ( (unsigned int)NORMALIZE( srcVector[ 0 ], 1023.f ) & 1023 ) << 20 ) | + ( ( (unsigned int)NORMALIZE( srcVector[ 1 ], 1023.f ) & 1023 ) << 10 ) | + ( ( (unsigned int)NORMALIZE( srcVector[ 2 ], 1023.f ) & 1023 ) << 0 ); + break; + } + case CL_SIGNED_INT8: + { + cl_char *ptr = (cl_char *)outData; + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = (char)CONVERT_INT( srcVector[ i ], -127.0f, 127.f, 127 ); + break; + } + case CL_SIGNED_INT16: + { + cl_short *ptr = (cl_short *)outData; + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = (short)CONVERT_INT( srcVector[ i ], -32767.f, 32767.f, 32767 ); + break; + } + case CL_SIGNED_INT32: + { + cl_int *ptr = (cl_int *)outData; + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = (int)CONVERT_INT( srcVector[ i ], MAKE_HEX_FLOAT( -0x1.0p31f, -1, 31), MAKE_HEX_FLOAT( 0x1.fffffep30f, 0x1fffffe, 30-23), CL_INT_MAX ); + break; + } + case CL_UNSIGNED_INT8: + { + cl_uchar *ptr = (cl_uchar *)outData; + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = (cl_uchar)CONVERT_UINT( srcVector[ i ], 255.f, CL_UCHAR_MAX ); + break; + } + case CL_UNSIGNED_INT16: + { + cl_ushort *ptr = (cl_ushort *)outData; + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = (cl_ushort)CONVERT_UINT( srcVector[ i ], 32767.f, CL_USHRT_MAX ); + break; + } + case CL_UNSIGNED_INT32: + { + cl_uint *ptr = (cl_uint *)outData; + for( unsigned int i = 0; i < channelCount; i++ ) + ptr[ i ] = (cl_uint)CONVERT_UINT( srcVector[ i ], MAKE_HEX_FLOAT( 0x1.fffffep31f, 0x1fffffe, 31-23), CL_UINT_MAX ); + break; + } +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: + { + cl_ushort *ptr = (cl_ushort*)outData; + for( unsigned int i = 0; i < channelCount; i++ ) + { + cl_float f = fmaxf( srcVector[i], -1.0f ); + f = fminf( f, 3.0f ); + cl_int d = rintf(f * 0x1.0p14f); + d += 16384; + if( d > CL_USHRT_MAX ) + d = CL_USHRT_MAX; + ptr[i] = d; + } + break; + } +#endif + default: + log_error( "INTERNAL ERROR: unknown format (%d)\n", imageFormat->image_channel_data_type); + exit(-1); + break; + } +} + +void pack_image_pixel_error( const float *srcVector, const cl_image_format *imageFormat, const void *results, float *errors ) +{ + size_t channelCount = get_format_channel_count( imageFormat ); + switch( imageFormat->image_channel_data_type ) + { + case CL_HALF_FLOAT: + { + const cl_ushort *ptr = (const cl_ushort *)results; + + for( unsigned int i = 0; i < channelCount; i++ ) + errors[i] = Ulp_Error_Half( ptr[i], srcVector[i] ); + + break; + } + + case CL_FLOAT: + { + const cl_ushort *ptr = (const cl_ushort *)results; + + for( unsigned int i = 0; i < channelCount; i++ ) + errors[i] = Ulp_Error( ptr[i], srcVector[i] ); + + break; + } + + case CL_SNORM_INT8: + { + const cl_char *ptr = (const cl_char *)results; + + for( unsigned int i = 0; i < channelCount; i++ ) + errors[i] = ptr[i] - NORMALIZE_SIGNED_UNROUNDED( srcVector[ i ], -127.0f, 127.f ); + + break; + } + case CL_SNORM_INT16: + { + const cl_short *ptr = (const cl_short *)results; + + for( unsigned int i = 0; i < channelCount; i++ ) + errors[i] = ptr[i] - NORMALIZE_SIGNED_UNROUNDED( srcVector[ i ], -32767.f, 32767.f ); + + break; + } + case CL_UNORM_INT8: + { + const cl_uchar *ptr = (const cl_uchar *)results; + + for( unsigned int i = 0; i < channelCount; i++ ) + errors[i] = ptr[i] - NORMALIZE_UNROUNDED( srcVector[ i ], 255.f ); + + break; + } + case CL_UNORM_INT16: + { + const cl_ushort *ptr = (const cl_ushort *)results; + + for( unsigned int i = 0; i < channelCount; i++ ) + errors[i] = ptr[i] - NORMALIZE_UNROUNDED( srcVector[ i ], 65535.f ); + + break; + } + case CL_UNORM_SHORT_555: + { + const cl_ushort *ptr = (const cl_ushort *)results; + + errors[0] = ((ptr[0] >> 10) & 31) - NORMALIZE_UNROUNDED( srcVector[ 0 ], 31.f ); + errors[1] = ((ptr[0] >> 5) & 31) - NORMALIZE_UNROUNDED( srcVector[ 1 ], 31.f ); + errors[2] = ((ptr[0] >> 0) & 31) - NORMALIZE_UNROUNDED( srcVector[ 2 ], 31.f ); + + break; + } + case CL_UNORM_SHORT_565: + { + const cl_ushort *ptr = (const cl_ushort *)results; + + errors[0] = ((ptr[0] >> 11) & 31) - NORMALIZE_UNROUNDED( srcVector[ 0 ], 31.f ); + errors[1] = ((ptr[0] >> 5) & 63) - NORMALIZE_UNROUNDED( srcVector[ 1 ], 63.f ); + errors[2] = ((ptr[0] >> 0) & 31) - NORMALIZE_UNROUNDED( srcVector[ 2 ], 31.f ); + + break; + } + case CL_UNORM_INT_101010: + { + const cl_uint *ptr = (const cl_uint *)results; + + errors[0] = ((ptr[0] >> 20) & 1023) - NORMALIZE_UNROUNDED( srcVector[ 0 ], 1023.f ); + errors[1] = ((ptr[0] >> 10) & 1023) - NORMALIZE_UNROUNDED( srcVector[ 1 ], 1023.f ); + errors[2] = ((ptr[0] >> 0) & 1023) - NORMALIZE_UNROUNDED( srcVector[ 2 ], 1023.f ); + + break; + } + case CL_SIGNED_INT8: + { + const cl_char *ptr = (const cl_char *)results; + + for( unsigned int i = 0; i < channelCount; i++ ) + errors[ i ] = ptr[i] - CONVERT_INT( srcVector[ i ], -127.0f, 127.f, 127 ); + + break; + } + case CL_SIGNED_INT16: + { + const cl_short *ptr = (const cl_short *)results; + for( unsigned int i = 0; i < channelCount; i++ ) + errors[i] = ptr[ i ] - CONVERT_INT( srcVector[ i ], -32767.f, 32767.f, 32767 ); + break; + } + case CL_SIGNED_INT32: + { + const cl_int *ptr = (const cl_int *)results; + for( unsigned int i = 0; i < channelCount; i++ ) + errors[i] = (cl_float)((cl_long) ptr[ i ] - (cl_long) CONVERT_INT( srcVector[ i ], MAKE_HEX_FLOAT( -0x1.0p31f, -1, 31), MAKE_HEX_FLOAT( 0x1.fffffep30f, 0x1fffffe, 30-23), CL_INT_MAX )); + break; + } + case CL_UNSIGNED_INT8: + { + const cl_uchar *ptr = (const cl_uchar *)results; + for( unsigned int i = 0; i < channelCount; i++ ) + errors[i] = (cl_int) ptr[ i ] - (cl_int) CONVERT_UINT( srcVector[ i ], 255.f, CL_UCHAR_MAX ); + break; + } + case CL_UNSIGNED_INT16: + { + const cl_ushort *ptr = (const cl_ushort *)results; + for( unsigned int i = 0; i < channelCount; i++ ) + errors[i] = (cl_int) ptr[ i ] - (cl_int) CONVERT_UINT( srcVector[ i ], 32767.f, CL_USHRT_MAX ); + break; + } + case CL_UNSIGNED_INT32: + { + const cl_uint *ptr = (const cl_uint *)results; + for( unsigned int i = 0; i < channelCount; i++ ) + errors[i] = (cl_float)((cl_long) ptr[ i ] - (cl_long)CONVERT_UINT( srcVector[ i ], MAKE_HEX_FLOAT( 0x1.fffffep31f, 0x1fffffe, 31-23), CL_UINT_MAX )); + break; + } +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: + { + const cl_ushort *ptr = (const cl_ushort *)results; + + for( unsigned int i = 0; i < channelCount; i++ ) + errors[i] = ptr[i] - NORMALIZE_SIGNED_UNROUNDED( ((int) srcVector[ i ] - 16384), -16384.f, 49151.f ); + + break; + } +#endif + default: + log_error( "INTERNAL ERROR: unknown format (%d)\n", imageFormat->image_channel_data_type); + exit(-1); + break; + } +} + + +// +// Autodetect which rounding mode is used for image writes to CL_HALF_FLOAT +// This should be called lazily before attempting to verify image writes, otherwise an error will occur. +// +int DetectFloatToHalfRoundingMode( cl_command_queue q ) // Returns CL_SUCCESS on success +{ + cl_int err = CL_SUCCESS; + + if( gFloatToHalfRoundingMode == kDefaultRoundingMode ) + { + // Some numbers near 0.5f, that we look at to see how the values are rounded. + static const cl_uint inData[4*4] = { 0x3f000fffU, 0x3f001000U, 0x3f001001U, 0U, 0x3f001fffU, 0x3f002000U, 0x3f002001U, 0U, + 0x3f002fffU, 0x3f003000U, 0x3f003001U, 0U, 0x3f003fffU, 0x3f004000U, 0x3f004001U, 0U }; + static const size_t count = sizeof( inData ) / (4*sizeof( inData[0] )); + const float *inp = (const float*) inData; + cl_context context = NULL; + + // Create an input buffer + err = clGetCommandQueueInfo( q, CL_QUEUE_CONTEXT, sizeof(context), &context, NULL ); + if( err ) + { + log_error( "Error: could not get context from command queue in DetectFloatToHalfRoundingMode (%d)", err ); + return err; + } + + cl_mem inBuf = clCreateBuffer( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR | CL_MEM_ALLOC_HOST_PTR, sizeof( inData ), (void*) inData, &err ); + if( NULL == inBuf || err ) + { + log_error( "Error: could not create input buffer in DetectFloatToHalfRoundingMode (err: %d)", err ); + return err; + } + + // Create a small output image + cl_image_format fmt = { CL_RGBA, CL_HALF_FLOAT }; + cl_mem outImage = create_image_2d( context, CL_MEM_WRITE_ONLY, &fmt, count, 1, 0, NULL, &err ); + if( NULL == outImage || err ) + { + log_error( "Error: could not create half float out image in DetectFloatToHalfRoundingMode (err: %d)", err ); + clReleaseMemObject( inBuf ); + return err; + } + + // Create our program, and a kernel + const char *kernel[1] = { + "kernel void detect_round( global float4 *in, write_only image2d_t out )\n" + "{\n" + " write_imagef( out, (int2)(get_global_id(0),0), in[get_global_id(0)] );\n" + "}\n" }; + + clProgramWrapper program; + err = create_single_kernel_helper_create_program(context, &program, 1, kernel); + + if( NULL == program || err ) + { + log_error( "Error: could not create program in DetectFloatToHalfRoundingMode (err: %d)", err ); + clReleaseMemObject( inBuf ); + clReleaseMemObject( outImage ); + return err; + } + + cl_device_id device = NULL; + err = clGetCommandQueueInfo( q, CL_QUEUE_DEVICE, sizeof(device), &device, NULL ); + if( err ) + { + log_error( "Error: could not get device from command queue in DetectFloatToHalfRoundingMode (%d)", err ); + clReleaseMemObject( inBuf ); + clReleaseMemObject( outImage ); + return err; + } + + err = clBuildProgram( program, 1, &device, "", NULL, NULL ); + if( err ) + { + log_error( "Error: could not build program in DetectFloatToHalfRoundingMode (%d)", err ); + clReleaseMemObject( inBuf ); + clReleaseMemObject( outImage ); + return err; + } + + cl_kernel k = clCreateKernel( program, "detect_round", &err ); + if( NULL == k || err ) + { + log_error( "Error: could not create kernel in DetectFloatToHalfRoundingMode (%d)", err ); + clReleaseMemObject( inBuf ); + clReleaseMemObject( outImage ); + return err; + } + + err = clSetKernelArg( k, 0, sizeof( cl_mem ), &inBuf ); + if( err ) + { + log_error( "Error: could not set argument 0 of kernel in DetectFloatToHalfRoundingMode (%d)", err ); + clReleaseMemObject( inBuf ); + clReleaseMemObject( outImage ); + clReleaseKernel( k ); + return err; + } + + err = clSetKernelArg( k, 1, sizeof( cl_mem ), &outImage ); + if( err ) + { + log_error( "Error: could not set argument 1 of kernel in DetectFloatToHalfRoundingMode (%d)", err ); + clReleaseMemObject( inBuf ); + clReleaseMemObject( outImage ); + clReleaseKernel( k ); + return err; + } + + // Run the kernel + size_t global_work_size = count; + err = clEnqueueNDRangeKernel( q, k, 1, NULL, &global_work_size, NULL, 0, NULL, NULL ); + if( err ) + { + log_error( "Error: could not enqueue kernel in DetectFloatToHalfRoundingMode (%d)", err ); + clReleaseMemObject( inBuf ); + clReleaseMemObject( outImage ); + clReleaseKernel( k ); + return err; + } + + // read the results + cl_ushort outBuf[count*4]; + memset( outBuf, -1, sizeof( outBuf ) ); + size_t origin[3] = {0,0,0}; + size_t region[3] = {count,1,1}; + err = clEnqueueReadImage( q, outImage, CL_TRUE, origin, region, 0, 0, outBuf, 0, NULL, NULL ); + if( err ) + { + log_error( "Error: could not read output image in DetectFloatToHalfRoundingMode (%d)", err ); + clReleaseMemObject( inBuf ); + clReleaseMemObject( outImage ); + clReleaseKernel( k ); + return err; + } + + // Generate our list of reference results + cl_ushort rte_ref[count*4]; + cl_ushort rtz_ref[count*4]; + for( size_t i = 0; i < 4 * count; i++ ) + { + rte_ref[i] = float2half_rte( inp[i] ); + rtz_ref[i] = float2half_rtz( inp[i] ); + } + + // Verify that we got something in either rtz or rte mode + if( 0 == memcmp( rte_ref, outBuf, sizeof( rte_ref )) ) + { + log_info( "Autodetected float->half rounding mode to be rte\n" ); + gFloatToHalfRoundingMode = kRoundToNearestEven; + } + else if ( 0 == memcmp( rtz_ref, outBuf, sizeof( rtz_ref )) ) + { + log_info( "Autodetected float->half rounding mode to be rtz\n" ); + gFloatToHalfRoundingMode = kRoundTowardZero; + } + else + { + log_error( "ERROR: float to half conversions proceed with invalid rounding mode!\n" ); + log_info( "\nfor:" ); + for( size_t i = 0; i < count; i++ ) + log_info( " {%a, %a, %a, %a},", inp[4*i], inp[4*i+1], inp[4*i+2], inp[4*i+3] ); + log_info( "\ngot:" ); + for( size_t i = 0; i < count; i++ ) + log_info( " {0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x},", outBuf[4*i], outBuf[4*i+1], outBuf[4*i+2], outBuf[4*i+3] ); + log_info( "\nrte:" ); + for( size_t i = 0; i < count; i++ ) + log_info( " {0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x},", rte_ref[4*i], rte_ref[4*i+1], rte_ref[4*i+2], rte_ref[4*i+3] ); + log_info( "\nrtz:" ); + for( size_t i = 0; i < count; i++ ) + log_info( " {0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x},", rtz_ref[4*i], rtz_ref[4*i+1], rtz_ref[4*i+2], rtz_ref[4*i+3] ); + log_info( "\n" ); + err = -1; + gFloatToHalfRoundingMode = kRoundingModeCount; // illegal value + } + + // clean up + clReleaseMemObject( inBuf ); + clReleaseMemObject( outImage ); + clReleaseKernel( k ); + return err; + } + + // Make sure that the rounding mode was successfully detected, if we checked earlier + if( gFloatToHalfRoundingMode != kRoundToNearestEven && gFloatToHalfRoundingMode != kRoundTowardZero) + return -2; + + return err; +} + +char *create_random_image_data( ExplicitType dataType, image_descriptor *imageInfo, BufferOwningPtr &P, MTdata d, bool image2DFromBuffer ) +{ + size_t allocSize, numPixels; + if ( /*gTestMipmaps*/ imageInfo->num_mip_levels > 1 ) + { + allocSize = (size_t) (compute_mipmapped_image_size(*imageInfo) * 4 * get_explicit_type_size( dataType ))/get_pixel_size(imageInfo->format); + numPixels = allocSize / (get_explicit_type_size( dataType ) * 4); + } + else + { + numPixels = (image2DFromBuffer? imageInfo->rowPitch: imageInfo->width) * imageInfo->height + * (imageInfo->depth ? imageInfo->depth : 1) + * (imageInfo->arraySize ? imageInfo->arraySize : 1); + allocSize = numPixels * 4 * get_explicit_type_size( dataType ); + } + +#if 0 // DEBUG + { + fprintf(stderr,"--- create_random_image_data:\n"); + fprintf(stderr,"allocSize = %zu\n",allocSize); + fprintf(stderr,"numPixels = %zu\n",numPixels); + fprintf(stderr,"width = %zu\n",imageInfo->width); + fprintf(stderr,"height = %zu\n",imageInfo->height); + fprintf(stderr,"depth = %zu\n",imageInfo->depth); + fprintf(stderr,"rowPitch = %zu\n",imageInfo->rowPitch); + fprintf(stderr,"slicePitch = %zu\n",imageInfo->slicePitch); + fprintf(stderr,"arraySize = %zu\n",imageInfo->arraySize); + fprintf(stderr,"explicit_type_size = %zu\n",get_explicit_type_size(dataType)); + } +#endif + +#if defined( __APPLE__ ) + char *data = NULL; + if (gDeviceType == CL_DEVICE_TYPE_CPU) { + size_t mapSize = ((allocSize + 4095L) & -4096L) + 8192; // alloc two extra pages. + + void *map = mmap(0, mapSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); + if (map == MAP_FAILED) + { + perror("create_random_image_data: mmap"); + log_error("%s:%d: mmap failed, mapSize = %zu\n",__FILE__,__LINE__,mapSize); + } + intptr_t data_end = (intptr_t)map + mapSize - 4096; + data = (char *)(data_end - (intptr_t)allocSize); + + mprotect(map, 4096, PROT_NONE); + mprotect((void *)((char *)map + mapSize - 4096), 4096, PROT_NONE); + P.reset(data, map, mapSize); + } else { + data = (char *)malloc(allocSize); + P.reset(data); + } +#else +#if defined (_WIN32) && defined(_MSC_VER) + char *data = (char *)_aligned_malloc(allocSize, get_pixel_size(imageInfo->format)); +#elif defined(__MINGW32__) + char *data = (char *)__mingw_aligned_malloc(allocSize, get_pixel_size(imageInfo->format)); +#else + char *data = (char *)memalign(get_pixel_size(imageInfo->format), allocSize); +#endif + + P.reset(data,NULL,0,allocSize,true); +#endif + + if (data == NULL) { + log_error( "ERROR: Unable to malloc %lu bytes for create_random_image_data\n", allocSize ); + return NULL; + } + + switch( dataType ) + { + case kFloat: + { + float *inputValues = (float *)data; + switch (imageInfo->format->image_channel_data_type) + { + case CL_HALF_FLOAT: + { + // Generate data that is (mostly) inside the range of a half float + // const float HALF_MIN = 5.96046448e-08f; + const float HALF_MAX = 65504.0f; + + size_t i = 0; + inputValues[ i++ ] = 0.f; + inputValues[ i++ ] = 1.f; + inputValues[ i++ ] = -1.f; + inputValues[ i++ ] = 2.f; + for( ; i < numPixels * 4; i++ ) + inputValues[ i ] = get_random_float( -HALF_MAX - 2.f, HALF_MAX + 2.f, d ); + } + break; +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: + { + size_t i = 0; + if( numPixels * 4 >= 8 ) + { + inputValues[ i++ ] = INFINITY; + inputValues[ i++ ] = 0x1.0p14f; + inputValues[ i++ ] = 0x1.0p31f; + inputValues[ i++ ] = 0x1.0p32f; + inputValues[ i++ ] = -INFINITY; + inputValues[ i++ ] = -0x1.0p14f; + inputValues[ i++ ] = -0x1.0p31f; + inputValues[ i++ ] = -0x1.1p31f; + } + for( ; i < numPixels * 4; i++ ) + inputValues[ i ] = get_random_float( -1.1f, 3.1f, d ); + } + break; +#endif + case CL_FLOAT: + { + size_t i = 0; + inputValues[ i++ ] = INFINITY; + inputValues[ i++ ] = -INFINITY; + inputValues[ i++ ] = 0.0f; + inputValues[ i++ ] = 0.0f; + cl_uint *p = (cl_uint *)data; + for( ; i < numPixels * 4; i++ ) + p[ i ] = genrand_int32(d); + } + break; + + default: + size_t i = 0; + if( numPixels * 4 >= 36 ) + { + inputValues[ i++ ] = 0.0f; + inputValues[ i++ ] = 0.5f; + inputValues[ i++ ] = 31.5f; + inputValues[ i++ ] = 32.0f; + inputValues[ i++ ] = 127.5f; + inputValues[ i++ ] = 128.0f; + inputValues[ i++ ] = 255.5f; + inputValues[ i++ ] = 256.0f; + inputValues[ i++ ] = 1023.5f; + inputValues[ i++ ] = 1024.0f; + inputValues[ i++ ] = 32767.5f; + inputValues[ i++ ] = 32768.0f; + inputValues[ i++ ] = 65535.5f; + inputValues[ i++ ] = 65536.0f; + inputValues[ i++ ] = 2147483648.0f; + inputValues[ i++ ] = 4294967296.0f; + inputValues[ i++ ] = MAKE_HEX_FLOAT( 0x1.0p63f, 1, 63 ); + inputValues[ i++ ] = MAKE_HEX_FLOAT( 0x1.0p64f, 1, 64 ); + inputValues[ i++ ] = -0.0f; + inputValues[ i++ ] = -0.5f; + inputValues[ i++ ] = -31.5f; + inputValues[ i++ ] = -32.0f; + inputValues[ i++ ] = -127.5f; + inputValues[ i++ ] = -128.0f; + inputValues[ i++ ] = -255.5f; + inputValues[ i++ ] = -256.0f; + inputValues[ i++ ] = -1023.5f; + inputValues[ i++ ] = -1024.0f; + inputValues[ i++ ] = -32767.5f; + inputValues[ i++ ] = -32768.0f; + inputValues[ i++ ] = -65535.5f; + inputValues[ i++ ] = -65536.0f; + inputValues[ i++ ] = -2147483648.0f; + inputValues[ i++ ] = -4294967296.0f; + inputValues[ i++ ] = -MAKE_HEX_FLOAT( 0x1.0p63f, 1, 63 ); + inputValues[ i++ ] = -MAKE_HEX_FLOAT( 0x1.0p64f, 1, 64 ); + } + if( is_format_signed(imageInfo->format) ) + { + for( ; i < numPixels * 4; i++ ) + inputValues[ i ] = get_random_float( -1.1f, 1.1f, d ); + } + else + { + for( ; i < numPixels * 4; i++ ) + inputValues[ i ] = get_random_float( -0.1f, 1.1f, d ); + } + break; + } + } + + case kInt: + { + int *imageData = (int *)data; + + // We want to generate ints (mostly) in range of the target format + int formatMin = get_format_min_int( imageInfo->format ); + size_t formatMax = get_format_max_int( imageInfo->format ); + if( formatMin == 0 ) + { + // Unsigned values, but we are only an int, so cap the actual max at the max of signed ints + if( formatMax > 2147483647L ) + formatMax = 2147483647L; + } + // If the final format is small enough, give us a bit of room for out-of-range values to test + if( formatMax < 2147483647L ) + formatMax += 2; + if( formatMin > -2147483648LL ) + formatMin -= 2; + + // Now gen + for( size_t i = 0; i < numPixels * 4; i++ ) + { + imageData[ i ] = random_in_range( formatMin, (int)formatMax, d ); + } + break; + } + + case kUInt: + case kUnsignedInt: + { + unsigned int *imageData = (unsigned int *)data; + + // We want to generate ints (mostly) in range of the target format + int formatMin = get_format_min_int( imageInfo->format ); + size_t formatMax = get_format_max_int( imageInfo->format ); + if( formatMin < 0 ) + formatMin = 0; + // If the final format is small enough, give us a bit of room for out-of-range values to test + if( formatMax < 4294967295LL ) + formatMax += 2; + + // Now gen + for( size_t i = 0; i < numPixels * 4; i++ ) + { + imageData[ i ] = random_in_range( formatMin, (int)formatMax, d ); + } + break; + } + default: + // Unsupported source format + delete [] data; + return NULL; + } + + return data; +} + +/* + deprecated +bool clamp_image_coord( image_sampler_data *imageSampler, float value, size_t max, int &outValue ) +{ + int v = (int)value; + + switch(imageSampler->addressing_mode) + { + case CL_ADDRESS_REPEAT: + outValue = v; + while( v < 0 ) + v += (int)max; + while( v >= (int)max ) + v -= (int)max; + if( v != outValue ) + { + outValue = v; + return true; + } + return false; + + case CL_ADDRESS_MIRRORED_REPEAT: + log_info( "ERROR: unimplemented for CL_ADDRESS_MIRRORED_REPEAT. Do we ever use this? + exit(-1); + + default: + if( v < 0 ) + { + outValue = 0; + return true; + } + if( v >= (int)max ) + { + outValue = (int)max - 1; + return true; + } + outValue = v; + return false; + } + +} +*/ + +void get_sampler_kernel_code( image_sampler_data *imageSampler, char *outLine ) +{ + const char *normalized; + const char *addressMode; + const char *filterMode; + + if( imageSampler->addressing_mode == CL_ADDRESS_CLAMP ) + addressMode = "CLK_ADDRESS_CLAMP"; + else if( imageSampler->addressing_mode == CL_ADDRESS_CLAMP_TO_EDGE ) + addressMode = "CLK_ADDRESS_CLAMP_TO_EDGE"; + else if( imageSampler->addressing_mode == CL_ADDRESS_REPEAT ) + addressMode = "CLK_ADDRESS_REPEAT"; + else if( imageSampler->addressing_mode == CL_ADDRESS_MIRRORED_REPEAT ) + addressMode = "CLK_ADDRESS_MIRRORED_REPEAT"; + else if( imageSampler->addressing_mode == CL_ADDRESS_NONE ) + addressMode = "CLK_ADDRESS_NONE"; + else + { + log_error( "**Error: Unknown addressing mode! Aborting...\n" ); + abort(); + } + + if( imageSampler->normalized_coords ) + normalized = "CLK_NORMALIZED_COORDS_TRUE"; + else + normalized = "CLK_NORMALIZED_COORDS_FALSE"; + + if( imageSampler->filter_mode == CL_FILTER_LINEAR ) + filterMode = "CLK_FILTER_LINEAR"; + else + filterMode = "CLK_FILTER_NEAREST"; + + sprintf( outLine, " const sampler_t imageSampler = %s | %s | %s;\n", addressMode, filterMode, normalized ); +} + +void copy_image_data( image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, void *imageValues, void *destImageValues, + const size_t sourcePos[], const size_t destPos[], const size_t regionSize[] ) +{ + // assert( srcImageInfo->format == dstImageInfo->format ); + + size_t src_mip_level_offset = 0, dst_mip_level_offset = 0; + size_t sourcePos_lod[3], destPos_lod[3], src_lod, dst_lod; + size_t src_row_pitch_lod, src_slice_pitch_lod; + size_t dst_row_pitch_lod, dst_slice_pitch_lod; + + size_t pixelSize = get_pixel_size( srcImageInfo->format ); + + sourcePos_lod[0] = sourcePos[0]; + sourcePos_lod[1] = sourcePos[1]; + sourcePos_lod[2] = sourcePos[2]; + destPos_lod[0] = destPos[0]; + destPos_lod[1] = destPos[1]; + destPos_lod[2] = destPos[2]; + src_row_pitch_lod = srcImageInfo->rowPitch; + dst_row_pitch_lod = dstImageInfo->rowPitch; + src_slice_pitch_lod = srcImageInfo->slicePitch; + dst_slice_pitch_lod = dstImageInfo->slicePitch; + + if( srcImageInfo->num_mip_levels > 1) + { + size_t src_width_lod = 1/*srcImageInfo->width*/; + size_t src_height_lod = 1/*srcImageInfo->height*/; + size_t src_depth_lod = 1/*srcImageInfo->depth*/; + + switch( srcImageInfo->type ) + { + case CL_MEM_OBJECT_IMAGE1D: + src_lod = sourcePos[1]; + sourcePos_lod[1] = sourcePos_lod[2] = 0; + src_width_lod = (srcImageInfo->width >> src_lod ) ? ( srcImageInfo->width >> src_lod ): 1; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE2D: + src_lod = sourcePos[2]; + sourcePos_lod[1] = sourcePos[1]; + sourcePos_lod[2] = 0; + src_width_lod = (srcImageInfo->width >> src_lod ) ? ( srcImageInfo->width >> src_lod ): 1; + if( srcImageInfo->type == CL_MEM_OBJECT_IMAGE2D ) + src_height_lod = (srcImageInfo->height >> src_lod ) ? ( srcImageInfo->height >> src_lod ): 1; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + case CL_MEM_OBJECT_IMAGE3D: + src_lod = sourcePos[3]; + sourcePos_lod[1] = sourcePos[1]; + sourcePos_lod[2] = sourcePos[2]; + src_width_lod = (srcImageInfo->width >> src_lod ) ? ( srcImageInfo->width >> src_lod ): 1; + src_height_lod = (srcImageInfo->height >> src_lod ) ? ( srcImageInfo->height >> src_lod ): 1; + if( srcImageInfo->type == CL_MEM_OBJECT_IMAGE3D ) + src_depth_lod = (srcImageInfo->depth >> src_lod ) ? ( srcImageInfo->depth >> src_lod ): 1; + break; + + } + src_mip_level_offset = compute_mip_level_offset( srcImageInfo, src_lod ); + src_row_pitch_lod = src_width_lod * get_pixel_size( srcImageInfo->format ); + src_slice_pitch_lod = src_row_pitch_lod * src_height_lod; + } + + if( dstImageInfo->num_mip_levels > 1) + { + size_t dst_width_lod = 1/*dstImageInfo->width*/; + size_t dst_height_lod = 1/*dstImageInfo->height*/; + size_t dst_depth_lod = 1 /*dstImageInfo->depth*/; + switch( dstImageInfo->type ) + { + case CL_MEM_OBJECT_IMAGE1D: + dst_lod = destPos[1]; + destPos_lod[1] = destPos_lod[2] = 0; + dst_width_lod = (dstImageInfo->width >> dst_lod ) ? ( dstImageInfo->width >> dst_lod ): 1; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE2D: + dst_lod = destPos[2]; + destPos_lod[1] = destPos[1]; + destPos_lod[2] = 0; + dst_width_lod = (dstImageInfo->width >> dst_lod ) ? ( dstImageInfo->width >> dst_lod ): 1; + if( dstImageInfo->type == CL_MEM_OBJECT_IMAGE2D ) + dst_height_lod = (dstImageInfo->height >> dst_lod ) ? ( dstImageInfo->height >> dst_lod ): 1; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + case CL_MEM_OBJECT_IMAGE3D: + dst_lod = destPos[3]; + destPos_lod[1] = destPos[1]; + destPos_lod[2] = destPos[2]; + dst_width_lod = (dstImageInfo->width >> dst_lod ) ? ( dstImageInfo->width >> dst_lod ): 1; + dst_height_lod = (dstImageInfo->height >> dst_lod ) ? ( dstImageInfo->height >> dst_lod ): 1; + if( dstImageInfo->type == CL_MEM_OBJECT_IMAGE3D ) + dst_depth_lod = (dstImageInfo->depth >> dst_lod ) ? ( dstImageInfo->depth >> dst_lod ): 1; + break; + + } + dst_mip_level_offset = compute_mip_level_offset( dstImageInfo, dst_lod ); + dst_row_pitch_lod = dst_width_lod * get_pixel_size( dstImageInfo->format); + dst_slice_pitch_lod = dst_row_pitch_lod * dst_height_lod; + } + + // Get initial pointers + char *sourcePtr = (char *)imageValues + sourcePos_lod[ 2 ] * src_slice_pitch_lod + sourcePos_lod[ 1 ] * src_row_pitch_lod + pixelSize * sourcePos_lod[ 0 ] + src_mip_level_offset; + char *destPtr = (char *)destImageValues + destPos_lod[ 2 ] * dst_slice_pitch_lod + destPos_lod[ 1 ] * dst_row_pitch_lod + pixelSize * destPos_lod[ 0 ] + dst_mip_level_offset; + + for( size_t z = 0; z < ( regionSize[ 2 ] > 0 ? regionSize[ 2 ] : 1 ); z++ ) + { + char *rowSourcePtr = sourcePtr; + char *rowDestPtr = destPtr; + for( size_t y = 0; y < regionSize[ 1 ]; y++ ) + { + memcpy( rowDestPtr, rowSourcePtr, pixelSize * regionSize[ 0 ] ); + rowSourcePtr += src_row_pitch_lod; + rowDestPtr += dst_row_pitch_lod; + } + + sourcePtr += src_slice_pitch_lod; + destPtr += dst_slice_pitch_lod; + } +} + +float random_float(float low, float high, MTdata d) +{ + float t = (float) genrand_real1(d); + return (1.0f - t) * low + t * high; +} + +CoordWalker::CoordWalker( void * coords, bool useFloats, size_t vecSize ) +{ + if( useFloats ) + { + mFloatCoords = (cl_float *)coords; + mIntCoords = NULL; + } + else + { + mFloatCoords = NULL; + mIntCoords = (cl_int *)coords; + } + mVecSize = vecSize; +} + +CoordWalker::~CoordWalker() +{ +} + +cl_float CoordWalker::Get( size_t idx, size_t el ) +{ + if( mIntCoords != NULL ) + return (cl_float)mIntCoords[ idx * mVecSize + el ]; + else + return mFloatCoords[ idx * mVecSize + el ]; +} + + +void print_read_header( cl_image_format *format, image_sampler_data *sampler, bool err, int t ) +{ + const char *addressMode = NULL; + const char *normalizedNames[2] = { "UNNORMALIZED", "NORMALIZED" }; + + if( sampler->addressing_mode == CL_ADDRESS_CLAMP ) + addressMode = "CL_ADDRESS_CLAMP"; + else if( sampler->addressing_mode == CL_ADDRESS_CLAMP_TO_EDGE ) + addressMode = "CL_ADDRESS_CLAMP_TO_EDGE"; + else if( sampler->addressing_mode == CL_ADDRESS_REPEAT ) + addressMode = "CL_ADDRESS_REPEAT"; + else if( sampler->addressing_mode == CL_ADDRESS_MIRRORED_REPEAT ) + addressMode = "CL_ADDRESS_MIRRORED_REPEAT"; + else + addressMode = "CL_ADDRESS_NONE"; + + if( t ) + { + if( err ) + log_error( "[%-7s %-24s %d] - %s - %s - %s - %s\n", GetChannelOrderName( format->image_channel_order ), + GetChannelTypeName( format->image_channel_data_type ), + (int)get_format_channel_count( format ), + sampler->filter_mode == CL_FILTER_NEAREST ? "CL_FILTER_NEAREST" : "CL_FILTER_LINEAR", + addressMode, + normalizedNames[sampler->normalized_coords ? 1 : 0], + t == 1 ? "TRANSPOSED" : "NON-TRANSPOSED" ); + else + log_info( "[%-7s %-24s %d] - %s - %s - %s - %s\n", GetChannelOrderName( format->image_channel_order ), + GetChannelTypeName( format->image_channel_data_type ), + (int)get_format_channel_count( format ), + sampler->filter_mode == CL_FILTER_NEAREST ? "CL_FILTER_NEAREST" : "CL_FILTER_LINEAR", + addressMode, + normalizedNames[sampler->normalized_coords ? 1 : 0], + t == 1 ? "TRANSPOSED" : "NON-TRANSPOSED" ); + } + else + { + if( err ) + log_error( "[%-7s %-24s %d] - %s - %s - %s\n", GetChannelOrderName( format->image_channel_order ), + GetChannelTypeName( format->image_channel_data_type ), + (int)get_format_channel_count( format ), + sampler->filter_mode == CL_FILTER_NEAREST ? "CL_FILTER_NEAREST" : "CL_FILTER_LINEAR", + addressMode, + normalizedNames[sampler->normalized_coords ? 1 : 0] ); + else + log_info( "[%-7s %-24s %d] - %s - %s - %s\n", GetChannelOrderName( format->image_channel_order ), + GetChannelTypeName( format->image_channel_data_type ), + (int)get_format_channel_count( format ), + sampler->filter_mode == CL_FILTER_NEAREST ? "CL_FILTER_NEAREST" : "CL_FILTER_LINEAR", + addressMode, + normalizedNames[sampler->normalized_coords ? 1 : 0] ); + } + +} + +void print_write_header( cl_image_format *format, bool err = false) +{ + if( err ) + log_error( "[%-7s %-24s %d]\n", GetChannelOrderName( format->image_channel_order ), + GetChannelTypeName( format->image_channel_data_type ), + (int)get_format_channel_count( format ) ); + else + log_info( "[%-7s %-24s %d]\n", GetChannelOrderName( format->image_channel_order ), + GetChannelTypeName( format->image_channel_data_type ), + (int)get_format_channel_count( format ) ); +} + + +void print_header( cl_image_format *format, bool err = false ) +{ + if (err) { + log_error( "[%-7s %-24s %d]\n", GetChannelOrderName( format->image_channel_order ), + GetChannelTypeName( format->image_channel_data_type ), + (int)get_format_channel_count( format ) ); + } else { + log_info( "[%-7s %-24s %d]\n", GetChannelOrderName( format->image_channel_order ), + GetChannelTypeName( format->image_channel_data_type ), + (int)get_format_channel_count( format ) ); + } +} + +bool find_format( cl_image_format *formatList, unsigned int numFormats, cl_image_format *formatToFind ) +{ + for( unsigned int i = 0; i < numFormats; i++ ) + { + if( formatList[ i ].image_channel_order == formatToFind->image_channel_order && + formatList[ i ].image_channel_data_type == formatToFind->image_channel_data_type ) + return true; + } + return false; +} + +bool check_minimum_supported( cl_image_format *formatList, unsigned int numFormats, cl_mem_flags flags ) +{ + cl_image_format readFormatsToSupport[] = { { CL_RGBA, CL_UNORM_INT8 }, + { CL_RGBA, CL_UNORM_INT16 }, + { CL_RGBA, CL_SIGNED_INT8 }, + { CL_RGBA, CL_SIGNED_INT16 }, + { CL_RGBA, CL_SIGNED_INT32 }, + { CL_RGBA, CL_UNSIGNED_INT8 }, + { CL_RGBA, CL_UNSIGNED_INT16 }, + { CL_RGBA, CL_UNSIGNED_INT32 }, + { CL_RGBA, CL_HALF_FLOAT }, + { CL_RGBA, CL_FLOAT }, + { CL_BGRA, CL_UNORM_INT8} }; + + cl_image_format writeFormatsToSupport[] = { { CL_RGBA, CL_UNORM_INT8 }, + { CL_RGBA, CL_UNORM_INT16 }, + { CL_RGBA, CL_SIGNED_INT8 }, + { CL_RGBA, CL_SIGNED_INT16 }, + { CL_RGBA, CL_SIGNED_INT32 }, + { CL_RGBA, CL_UNSIGNED_INT8 }, + { CL_RGBA, CL_UNSIGNED_INT16 }, + { CL_RGBA, CL_UNSIGNED_INT32 }, + { CL_RGBA, CL_HALF_FLOAT }, + { CL_RGBA, CL_FLOAT }, + { CL_BGRA, CL_UNORM_INT8} }; + + cl_image_format *formatsToTest; + unsigned int testCount; + bool passed = true; + + if( flags == CL_MEM_READ_ONLY ) + { + formatsToTest = readFormatsToSupport; + testCount = sizeof( readFormatsToSupport ) / sizeof( readFormatsToSupport[ 0 ] ); + } + else + { + formatsToTest = writeFormatsToSupport; + testCount = sizeof( writeFormatsToSupport ) / sizeof( writeFormatsToSupport[ 0 ] ); + } + + for( unsigned int i = 0; i < testCount; i++ ) + { + if( !find_format( formatList, numFormats, &formatsToTest[ i ] ) ) + { + log_error( "ERROR: Format required by OpenCL 1.0 is not supported: " ); + print_header( &formatsToTest[ i ], true ); + gTestCount++; + gTestFailure++; + passed = false; + } + } + return passed; +} + +cl_uint compute_max_mip_levels( size_t width, size_t height, size_t depth) +{ + cl_uint retMaxMipLevels=0, max_dim = 0; + + max_dim = width; + max_dim = height > max_dim ? height : max_dim; + max_dim = depth > max_dim ? depth : max_dim; + + while(max_dim) { + retMaxMipLevels++; + max_dim >>= 1; + } + return retMaxMipLevels; +} + +cl_ulong compute_mipmapped_image_size( image_descriptor imageInfo) +{ + cl_ulong retSize = 0; + size_t curr_width, curr_height, curr_depth, curr_array_size; + curr_width = imageInfo.width; + curr_height = imageInfo.height; + curr_depth = imageInfo.depth; + curr_array_size = imageInfo.arraySize; + + for (int i=0; i < (int) imageInfo.num_mip_levels; i++) + { + switch ( imageInfo.type ) + { + case CL_MEM_OBJECT_IMAGE3D : + retSize += (cl_ulong)curr_width * curr_height * curr_depth * get_pixel_size(imageInfo.format); + break; + case CL_MEM_OBJECT_IMAGE2D : + retSize += (cl_ulong)curr_width * curr_height * get_pixel_size(imageInfo.format); + break; + case CL_MEM_OBJECT_IMAGE1D : + retSize += (cl_ulong)curr_width * get_pixel_size(imageInfo.format); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY : + retSize += (cl_ulong)curr_width * curr_array_size * get_pixel_size(imageInfo.format); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY : + retSize += (cl_ulong)curr_width * curr_height * curr_array_size * get_pixel_size(imageInfo.format); + break; + } + + switch ( imageInfo.type ) + { + case CL_MEM_OBJECT_IMAGE3D : + curr_depth = curr_depth >> 1 ? curr_depth >> 1: 1; + case CL_MEM_OBJECT_IMAGE2D : + case CL_MEM_OBJECT_IMAGE2D_ARRAY : + curr_height = curr_height >> 1? curr_height >> 1 : 1; + case CL_MEM_OBJECT_IMAGE1D : + case CL_MEM_OBJECT_IMAGE1D_ARRAY : + curr_width = curr_width >> 1? curr_width >> 1 : 1; + } + } + + return retSize; +} + +size_t compute_mip_level_offset( image_descriptor * imageInfo , size_t lod) +{ + size_t retOffset = 0; + size_t width, height, depth; + width = imageInfo->width; + height = imageInfo->height; + depth = imageInfo->depth; + + for(size_t i=0; i < lod; i++) + { + switch(imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + retOffset += (size_t) width * height * imageInfo->arraySize * get_pixel_size( imageInfo->format ); + break; + case CL_MEM_OBJECT_IMAGE3D: + retOffset += (size_t) width * height * depth * get_pixel_size( imageInfo->format ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + retOffset += (size_t) width * imageInfo->arraySize * get_pixel_size( imageInfo->format ); + break; + case CL_MEM_OBJECT_IMAGE2D: + retOffset += (size_t) width * height * get_pixel_size( imageInfo->format ); + break; + case CL_MEM_OBJECT_IMAGE1D: + retOffset += (size_t) width * get_pixel_size( imageInfo->format ); + break; + } + + // Compute next lod dimensions + switch(imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE3D: + depth = ( depth >> 1 ) ? ( depth >> 1 ) : 1; + case CL_MEM_OBJECT_IMAGE2D: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + height = ( height >> 1 ) ? ( height >> 1 ) : 1; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE1D: + width = ( width >> 1 ) ? ( width >> 1 ) : 1; + } + + } + return retOffset; +} diff --git a/test_common/harness/imageHelpers.h b/test_common/harness/imageHelpers.h new file mode 100644 index 00000000..83ff1377 --- /dev/null +++ b/test_common/harness/imageHelpers.h @@ -0,0 +1,646 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _imageHelpers_h +#define _imageHelpers_h + +#include "compat.h" + +#include +#include +#include +#include +#include + +#if !defined(_WIN32) +#include +#endif + +#include + +#include "errorHelpers.h" + +#include "conversions.h" +#include "typeWrappers.h" +#include "kernelHelpers.h" +#include "errorHelpers.h" +#include "mt19937.h" +#include "rounding_mode.h" +#include "clImageHelper.h" + +extern int gTestCount; +extern int gTestFailure; +extern cl_device_type gDeviceType; + +// Number of iterations per image format to test if not testing max images, rounding, or small images +#define NUM_IMAGE_ITERATIONS 3 + + +// Definition for our own sampler type, to mirror the cl_sampler internals +#define MAX_sRGB_TO_lRGB_CONVERSION_ERROR 0.5 +#define MAX_lRGB_TO_sRGB_CONVERSION_ERROR 0.6 + +// Definition for our own sampler type, to mirror the cl_sampler internals +typedef struct { + cl_addressing_mode addressing_mode; + cl_filter_mode filter_mode; + bool normalized_coords; +} image_sampler_data; + +int round_to_even( float v ); + +#define NORMALIZE( v, max ) ( v < 0 ? 0 : ( v > 1.f ? max : round_to_even( v * max ) ) ) +#define NORMALIZE_UNROUNDED( v, max ) ( v < 0 ? 0 : ( v > 1.f ? max : v * max ) ) +#define NORMALIZE_SIGNED( v, min, max ) ( v < -1.0f ? min : ( v > 1.f ? max : round_to_even( v * max ) ) ) +#define NORMALIZE_SIGNED_UNROUNDED( v, min, max ) ( v < -1.0f ? min : ( v > 1.f ? max : v * max ) ) +#define CONVERT_INT( v, min, max, max_val) ( v < min ? min : ( v > max ? max_val : round_to_even( v ) ) ) +#define CONVERT_UINT( v, max, max_val) ( v < 0 ? 0 : ( v > max ? max_val : round_to_even( v ) ) ) + +extern void print_read_header( cl_image_format *format, image_sampler_data *sampler, bool err = false, int t = 0 ); +extern void print_write_header( cl_image_format *format, bool err); +extern void print_header( cl_image_format *format, bool err ); +extern bool find_format( cl_image_format *formatList, unsigned int numFormats, cl_image_format *formatToFind ); +extern bool check_minimum_supported( cl_image_format *formatList, unsigned int numFormats, cl_mem_flags flags ); + +extern size_t get_format_type_size( const cl_image_format *format ); +extern size_t get_channel_data_type_size( cl_channel_type channelType ); +extern size_t get_format_channel_count( const cl_image_format *format ); +extern size_t get_channel_order_channel_count( cl_channel_order order ); +cl_channel_type get_channel_type_from_name( const char *name ); +cl_channel_order get_channel_order_from_name( const char *name ); +extern int is_format_signed( const cl_image_format *format ); +extern size_t get_pixel_size( cl_image_format *format ); + +/* Helper to get any ol image format as long as it is 8-bits-per-channel */ +extern int get_8_bit_image_format( cl_context context, cl_mem_object_type objType, cl_mem_flags flags, size_t channelCount, cl_image_format *outFormat ); + +/* Helper to get any ol image format as long as it is 32-bits-per-channel */ +extern int get_32_bit_image_format( cl_context context, cl_mem_object_type objType, cl_mem_flags flags, size_t channelCount, cl_image_format *outFormat ); + +int random_in_range( int minV, int maxV, MTdata d ); +int random_log_in_range( int minV, int maxV, MTdata d ); + +typedef struct +{ + size_t width; + size_t height; + size_t depth; + size_t rowPitch; + size_t slicePitch; + size_t arraySize; + cl_image_format *format; + cl_mem buffer; + cl_mem_object_type type; + cl_uint num_mip_levels; +} image_descriptor; + +typedef struct +{ + float p[4]; +}FloatPixel; + +void get_max_sizes(size_t *numberOfSizes, const int maxNumberOfSizes, + size_t sizes[][3], size_t maxWidth, size_t maxHeight, size_t maxDepth, size_t maxArraySize, + const cl_ulong maxIndividualAllocSize, const cl_ulong maxTotalAllocSize, cl_mem_object_type image_type, cl_image_format *format, int usingMaxPixelSize=0); +extern size_t get_format_max_int( cl_image_format *format ); + +extern cl_ulong get_image_size( image_descriptor const *imageInfo ); +extern cl_ulong get_image_size_mb( image_descriptor const *imageInfo ); + +extern char * generate_random_image_data( image_descriptor *imageInfo, BufferOwningPtr &Owner, MTdata d ); + +extern int debug_find_vector_in_image( void *imagePtr, image_descriptor *imageInfo, + void *vectorToFind, size_t vectorSize, int *outX, int *outY, int *outZ, size_t lod = 0 ); + +extern int debug_find_pixel_in_image( void *imagePtr, image_descriptor *imageInfo, + unsigned int *valuesToFind, int *outX, int *outY, int *outZ, int lod = 0 ); +extern int debug_find_pixel_in_image( void *imagePtr, image_descriptor *imageInfo, + int *valuesToFind, int *outX, int *outY, int *outZ, int lod = 0 ); +extern int debug_find_pixel_in_image( void *imagePtr, image_descriptor *imageInfo, + float *valuesToFind, int *outX, int *outY, int *outZ, int lod = 0 ); + +extern void copy_image_data( image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, void *imageValues, void *destImageValues, + const size_t sourcePos[], const size_t destPos[], const size_t regionSize[] ); + +int has_alpha(cl_image_format *format); + +extern bool alpha_is_x(cl_image_format *format); + +extern bool is_sRGBA_order(cl_channel_order image_channel_order); + +inline float calculate_array_index( float coord, float extent ); + +cl_uint compute_max_mip_levels( size_t width, size_t height, size_t depth); +cl_ulong compute_mipmapped_image_size( image_descriptor imageInfo); +size_t compute_mip_level_offset( image_descriptor * imageInfo , size_t lod); + +template void read_image_pixel( void *imageData, image_descriptor *imageInfo, + int x, int y, int z, T *outData, int lod ) +{ + float convert_half_to_float( unsigned short halfValue ); + size_t width_lod = imageInfo->width, height_lod = imageInfo->height, depth_lod = imageInfo->depth, slice_pitch_lod = 0/*imageInfo->slicePitch*/ , row_pitch_lod = 0/*imageInfo->rowPitch*/; + width_lod = ( imageInfo->width >> lod) ?( imageInfo->width >> lod):1; + + if ( imageInfo->type != CL_MEM_OBJECT_IMAGE1D_ARRAY && imageInfo->type != CL_MEM_OBJECT_IMAGE1D) + height_lod = ( imageInfo->height >> lod) ?( imageInfo->height >> lod):1; + + if(imageInfo->type == CL_MEM_OBJECT_IMAGE3D) + depth_lod = ( imageInfo->depth >> lod) ? ( imageInfo->depth >> lod) : 1; + row_pitch_lod = (imageInfo->num_mip_levels > 0)? (width_lod * get_pixel_size( imageInfo->format )): imageInfo->rowPitch; + slice_pitch_lod = (imageInfo->num_mip_levels > 0)? (row_pitch_lod * height_lod): imageInfo->slicePitch; + + // correct depth_lod and height_lod for array image types in order to avoid + // return + if (imageInfo->type == CL_MEM_OBJECT_IMAGE1D_ARRAY && height_lod == 1 && depth_lod == 1) { + depth_lod = 0; + height_lod = 0; + + } + + if (imageInfo->type == CL_MEM_OBJECT_IMAGE2D_ARRAY && depth_lod == 1) { + depth_lod = 0; + } + + if ( x < 0 || x >= (int)width_lod + || ( height_lod != 0 && ( y < 0 || y >= (int)height_lod ) ) + || ( depth_lod != 0 && ( z < 0 || z >= (int)depth_lod ) ) + || ( imageInfo->arraySize != 0 && ( z < 0 || z >= (int)imageInfo->arraySize ) ) ) + { + // Border color + if (imageInfo->format->image_channel_order == CL_DEPTH) + { + outData[ 0 ] = 1; + } + else { + outData[ 0 ] = outData[ 1 ] = outData[ 2 ] = outData[ 3 ] = 0; + if (!has_alpha(imageInfo->format)) + outData[3] = 1; + } + return; + } + + cl_image_format *format = imageInfo->format; + + unsigned int i; + T tempData[ 4 ]; + + // Advance to the right spot + char *ptr = (char *)imageData; + size_t pixelSize = get_pixel_size( format ); + + ptr += z * slice_pitch_lod + y * row_pitch_lod + x * pixelSize; + + // OpenCL only supports reading floats from certain formats + switch( format->image_channel_data_type ) + { + case CL_SNORM_INT8: + { + cl_char *dPtr = (cl_char *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_UNORM_INT8: + { + cl_uchar *dPtr = (cl_uchar *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_SIGNED_INT8: + { + cl_char *dPtr = (cl_char *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_UNSIGNED_INT8: + { + cl_uchar *dPtr = (cl_uchar*)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_SNORM_INT16: + { + cl_short *dPtr = (cl_short *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_UNORM_INT16: + { + cl_ushort *dPtr = (cl_ushort *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_SIGNED_INT16: + { + cl_short *dPtr = (cl_short *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_UNSIGNED_INT16: + { + cl_ushort *dPtr = (cl_ushort *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_HALF_FLOAT: + { + cl_ushort *dPtr = (cl_ushort *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)convert_half_to_float( dPtr[ i ] ); + break; + } + + case CL_SIGNED_INT32: + { + cl_int *dPtr = (cl_int *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_UNSIGNED_INT32: + { + cl_uint *dPtr = (cl_uint *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_UNORM_SHORT_565: + { + cl_ushort *dPtr = (cl_ushort*)ptr; + tempData[ 0 ] = (T)( dPtr[ 0 ] >> 11 ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 5 ) & 63 ); + tempData[ 2 ] = (T)( dPtr[ 0 ] & 31 ); + break; + } + +#ifdef OBSOLETE_FORMAT + case CL_UNORM_SHORT_565_REV: + { + unsigned short *dPtr = (unsigned short *)ptr; + tempData[ 2 ] = (T)( dPtr[ 0 ] >> 11 ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 5 ) & 63 ); + tempData[ 0 ] = (T)( dPtr[ 0 ] & 31 ); + break; + } + + case CL_UNORM_SHORT_555_REV: + { + unsigned short *dPtr = (unsigned short *)ptr; + tempData[ 2 ] = (T)( ( dPtr[ 0 ] >> 10 ) & 31 ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 5 ) & 31 ); + tempData[ 0 ] = (T)( dPtr[ 0 ] & 31 ); + break; + } + + case CL_UNORM_INT_8888: + { + unsigned int *dPtr = (unsigned int *)ptr; + tempData[ 3 ] = (T)( dPtr[ 0 ] >> 24 ); + tempData[ 2 ] = (T)( ( dPtr[ 0 ] >> 16 ) & 0xff ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 8 ) & 0xff ); + tempData[ 0 ] = (T)( dPtr[ 0 ] & 0xff ); + break; + } + case CL_UNORM_INT_8888_REV: + { + unsigned int *dPtr = (unsigned int *)ptr; + tempData[ 0 ] = (T)( dPtr[ 0 ] >> 24 ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 16 ) & 0xff ); + tempData[ 2 ] = (T)( ( dPtr[ 0 ] >> 8 ) & 0xff ); + tempData[ 3 ] = (T)( dPtr[ 0 ] & 0xff ); + break; + } + + case CL_UNORM_INT_101010_REV: + { + unsigned int *dPtr = (unsigned int *)ptr; + tempData[ 2 ] = (T)( ( dPtr[ 0 ] >> 20 ) & 0x3ff ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 10 ) & 0x3ff ); + tempData[ 0 ] = (T)( dPtr[ 0 ] & 0x3ff ); + break; + } +#endif + case CL_UNORM_SHORT_555: + { + cl_ushort *dPtr = (cl_ushort *)ptr; + tempData[ 0 ] = (T)( ( dPtr[ 0 ] >> 10 ) & 31 ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 5 ) & 31 ); + tempData[ 2 ] = (T)( dPtr[ 0 ] & 31 ); + break; + } + + case CL_UNORM_INT_101010: + { + cl_uint *dPtr = (cl_uint *)ptr; + tempData[ 0 ] = (T)( ( dPtr[ 0 ] >> 20 ) & 0x3ff ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 10 ) & 0x3ff ); + tempData[ 2 ] = (T)( dPtr[ 0 ] & 0x3ff ); + break; + } + + case CL_FLOAT: + { + cl_float *dPtr = (cl_float *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: + { + cl_float *dPtr = (cl_float *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ] + 0x4000; + break; + } +#endif + } + + + outData[ 0 ] = outData[ 1 ] = outData[ 2 ] = 0; + outData[ 3 ] = 1; + + if( format->image_channel_order == CL_A ) + { + outData[ 3 ] = tempData[ 0 ]; + } + else if( format->image_channel_order == CL_R ) + { + outData[ 0 ] = tempData[ 0 ]; + } + else if( format->image_channel_order == CL_Rx ) + { + outData[ 0 ] = tempData[ 0 ]; + } + else if( format->image_channel_order == CL_RA ) + { + outData[ 0 ] = tempData[ 0 ]; + outData[ 3 ] = tempData[ 1 ]; + } + else if( format->image_channel_order == CL_RG ) + { + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 1 ]; + } + else if( format->image_channel_order == CL_RGx ) + { + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 1 ]; + } + else if(( format->image_channel_order == CL_RGB ) || ( format->image_channel_order == CL_sRGB )) + { + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 1 ]; + outData[ 2 ] = tempData[ 2 ]; + } + else if(( format->image_channel_order == CL_RGBx ) || ( format->image_channel_order == CL_sRGBx )) + { + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 1 ]; + outData[ 2 ] = tempData[ 2 ]; + outData[ 3 ] = 0; + } + else if(( format->image_channel_order == CL_RGBA ) || ( format->image_channel_order == CL_sRGBA )) + { + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 1 ]; + outData[ 2 ] = tempData[ 2 ]; + outData[ 3 ] = tempData[ 3 ]; + } + else if( format->image_channel_order == CL_ARGB ) + { + outData[ 0 ] = tempData[ 1 ]; + outData[ 1 ] = tempData[ 2 ]; + outData[ 2 ] = tempData[ 3 ]; + outData[ 3 ] = tempData[ 0 ]; + } + else if(( format->image_channel_order == CL_BGRA ) || ( format->image_channel_order == CL_sBGRA )) + { + outData[ 0 ] = tempData[ 2 ]; + outData[ 1 ] = tempData[ 1 ]; + outData[ 2 ] = tempData[ 0 ]; + outData[ 3 ] = tempData[ 3 ]; + } + else if( format->image_channel_order == CL_INTENSITY ) + { + outData[ 1 ] = tempData[ 0 ]; + outData[ 2 ] = tempData[ 0 ]; + outData[ 3 ] = tempData[ 0 ]; + } + else if( format->image_channel_order == CL_LUMINANCE ) + { + outData[ 1 ] = tempData[ 0 ]; + outData[ 2 ] = tempData[ 0 ]; + } + else if( format->image_channel_order == CL_DEPTH ) + { + outData[ 0 ] = tempData[ 0 ]; + } +#ifdef CL_1RGB_APPLE + else if( format->image_channel_order == CL_1RGB_APPLE ) + { + outData[ 0 ] = tempData[ 1 ]; + outData[ 1 ] = tempData[ 2 ]; + outData[ 2 ] = tempData[ 3 ]; + outData[ 3 ] = 0xff; + } +#endif +#ifdef CL_BGR1_APPLE + else if( format->image_channel_order == CL_BGR1_APPLE ) + { + outData[ 0 ] = tempData[ 2 ]; + outData[ 1 ] = tempData[ 1 ]; + outData[ 2 ] = tempData[ 0 ]; + outData[ 3 ] = 0xff; + } +#endif + else + { + log_error("Invalid format:"); + print_header(format, true); + } +} + +template void read_image_pixel( void *imageData, image_descriptor *imageInfo, + int x, int y, int z, T *outData ) +{ + read_image_pixel( imageData, imageInfo, x, y, z, outData, 0); +} + +// Stupid template rules +bool get_integer_coords( float x, float y, float z, + size_t width, size_t height, size_t depth, + image_sampler_data *imageSampler, image_descriptor *imageInfo, + int &outX, int &outY, int &outZ ); +bool get_integer_coords_offset( float x, float y, float z, + float xAddressOffset, float yAddressOffset, float zAddressOffset, + size_t width, size_t height, size_t depth, + image_sampler_data *imageSampler, image_descriptor *imageInfo, + int &outX, int &outY, int &outZ ); + + +template void sample_image_pixel_offset( void *imageData, image_descriptor *imageInfo, + float x, float y, float z, float xAddressOffset, float yAddressOffset, float zAddressOffset, + image_sampler_data *imageSampler, T *outData, int lod ) +{ + int iX = 0, iY = 0, iZ = 0; + + float max_w = imageInfo->width; + float max_h; + float max_d; + + switch (imageInfo->type) { + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + max_h = imageInfo->arraySize; + max_d = 0; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + max_h = imageInfo->height; + max_d = imageInfo->arraySize; + break; + default: + max_h = imageInfo->height; + max_d = imageInfo->depth; + break; + } + + if( /*gTestMipmaps*/ imageInfo->num_mip_levels > 1 ) + { + switch (imageInfo->type) { + case CL_MEM_OBJECT_IMAGE3D: + max_d = (float)((imageInfo->depth >> lod) ? (imageInfo->depth >> lod) : 1); + case CL_MEM_OBJECT_IMAGE2D: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + max_h = (float)((imageInfo->height >> lod) ? (imageInfo->height >> lod) : 1); + break; + default: + ; + + } + max_w = (float)((imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1); + } + get_integer_coords_offset( x, y, z, xAddressOffset, yAddressOffset, zAddressOffset, max_w, max_h, max_d, imageSampler, imageInfo, iX, iY, iZ ); + + read_image_pixel( imageData, imageInfo, iX, iY, iZ, outData, lod ); +} + +template void sample_image_pixel_offset( void *imageData, image_descriptor *imageInfo, + float x, float y, float z, float xAddressOffset, float yAddressOffset, float zAddressOffset, + image_sampler_data *imageSampler, T *outData) +{ + sample_image_pixel_offset( imageData, imageInfo, x, y, z, xAddressOffset, yAddressOffset, zAddressOffset, + imageSampler, outData, 0); +} + +template void sample_image_pixel( void *imageData, image_descriptor *imageInfo, + float x, float y, float z, image_sampler_data *imageSampler, T *outData ) +{ + return sample_image_pixel_offset(imageData, imageInfo, x, y, z, 0.0f, 0.0f, 0.0f, imageSampler, outData); +} + +FloatPixel sample_image_pixel_float( void *imageData, image_descriptor *imageInfo, + float x, float y, float z, image_sampler_data *imageSampler, float *outData, int verbose, int *containsDenorms ); + +FloatPixel sample_image_pixel_float( void *imageData, image_descriptor *imageInfo, + float x, float y, float z, image_sampler_data *imageSampler, float *outData, int verbose, int *containsDenorms, int lod ); + +FloatPixel sample_image_pixel_float_offset( void *imageData, image_descriptor *imageInfo, + float x, float y, float z, float xAddressOffset, float yAddressOffset, float zAddressOffset, + image_sampler_data *imageSampler, float *outData, int verbose, int *containsDenorms ); +FloatPixel sample_image_pixel_float_offset( void *imageData, image_descriptor *imageInfo, + float x, float y, float z, float xAddressOffset, float yAddressOffset, float zAddressOffset, + image_sampler_data *imageSampler, float *outData, int verbose, int *containsDenorms, int lod ); + + +extern void pack_image_pixel( unsigned int *srcVector, const cl_image_format *imageFormat, void *outData ); +extern void pack_image_pixel( int *srcVector, const cl_image_format *imageFormat, void *outData ); +extern void pack_image_pixel( float *srcVector, const cl_image_format *imageFormat, void *outData ); +extern void pack_image_pixel_error( const float *srcVector, const cl_image_format *imageFormat, const void *results, float *errors ); + +extern char *create_random_image_data( ExplicitType dataType, image_descriptor *imageInfo, BufferOwningPtr &P, MTdata d, bool image2DFromBuffer = false ); + +// deprecated +//extern bool clamp_image_coord( image_sampler_data *imageSampler, float value, size_t max, int &outValue ); + +extern void get_sampler_kernel_code( image_sampler_data *imageSampler, char *outLine ); +extern float get_max_absolute_error( cl_image_format *format, image_sampler_data *sampler); +extern float get_max_relative_error( cl_image_format *format, image_sampler_data *sampler, int is3D, int isLinearFilter ); +extern int issubnormal(float); + + +#define errMax( _x , _y ) ( (_x) != (_x) ? (_x) : (_x) > (_y) ? (_x) : (_y) ) + +static inline cl_uint abs_diff_uint( cl_uint x, cl_uint y ) +{ + return y > x ? y - x : x - y; +} + +static inline cl_uint abs_diff_int( cl_int x, cl_int y ) +{ + return (cl_uint) (y > x ? y - x : x - y); +} + +static inline cl_float relative_error( float test, float expected ) +{ + // 0-0/0 is 0 in this case, not NaN + if( test == 0.0f && expected == 0.0f ) + return 0.0f; + + return (test - expected) / expected; +} + +extern float random_float(float low, float high); + +class CoordWalker +{ +public: + CoordWalker( void * coords, bool useFloats, size_t vecSize ); + ~CoordWalker(); + + cl_float Get( size_t idx, size_t el ); + +protected: + cl_float * mFloatCoords; + cl_int * mIntCoords; + size_t mVecSize; +}; + +extern int DetectFloatToHalfRoundingMode( cl_command_queue ); // Returns CL_SUCCESS on success + +int inline is_half_nan( cl_ushort half ){ return (half & 0x7fff) > 0x7c00; } + +cl_ushort convert_float_to_half( cl_float f ); +cl_float convert_half_to_float( cl_ushort h ); + +extern double sRGBmap(float fc); + +#endif // _imageHelpers_h diff --git a/test_common/harness/kernelHelpers.c b/test_common/harness/kernelHelpers.c new file mode 100644 index 00000000..591ab038 --- /dev/null +++ b/test_common/harness/kernelHelpers.c @@ -0,0 +1,1290 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "kernelHelpers.h" +#include "errorHelpers.h" +#include "imageHelpers.h" +#include "typeWrappers.h" +#include "testHarness.h" +#include "parseParameters.h" + +#include +#include +#include +#include +#include + +#if defined(__MINGW32__) +#include "mingw_compat.h" +#endif + +#if defined(_WIN32) +std::string slash = "\\"; +#else +std::string slash = "/"; +#endif + +std::string get_file_name(const std::string &baseName, int index, const std::string &extension) +{ + std::ostringstream fileName; + fileName << baseName << "." << index << extension; + return fileName.str(); +} + +long get_file_size(const std::string &fileName) +{ + std::ifstream ifs(fileName.c_str(), std::ios::binary); + if (!ifs.good()) + return 0; + // get length of file: + ifs.seekg(0, std::ios::end); + std::ios::pos_type length = ifs.tellg(); + return static_cast(length); +} + +std::vector get_file_content(const std::string &fileName) +{ + std::ifstream ifs(fileName.c_str(), std::ios::binary); + if (!ifs.good()) + return std::vector(0); + // get length of file: + ifs.seekg(0, std::ios::end); + std::ios::pos_type length = ifs.tellg(); + ifs.seekg(0, std::ios::beg); + + // allocate memory: + std::vector content(static_cast(length)); + + // read data as a block: + ifs.read(&content[0], length); + return content; +} + +std::string get_kernel_name(const std::string &source) +{ + cl_uint crc = 0; + + // Count CRC + for (cl_uint i = 0; i < source.size() - source.size() % sizeof(cl_uint); i += sizeof(cl_uint)) + { + cl_uint *ptr = (cl_uint *)&source[i]; + crc += *ptr; + } + cl_uint remainder = 0; + memcpy(&remainder, &source[0] + source.size() - source.size() % sizeof(cl_uint), source.size() % sizeof(cl_uint)); + crc += remainder; + + // Create list of kernel names + std::string kernelsList; + size_t kPos = source.find("kernel"); + while (kPos != std::string::npos) + { + // check for '__kernel' + size_t pos = kPos; + if (pos >= 2 && source[pos - 1] == '_' && source[pos - 2] == '_') + pos -= 2; + + //check character before 'kernel' (white space expected) + size_t wsPos = source.find_last_of(" \t\r\n", pos); + if (wsPos == std::string::npos || wsPos + 1 == pos) + { + //check character after 'kernel' (white space expected) + size_t akPos = kPos + sizeof("kernel") - 1; + wsPos = source.find_first_of(" \t\r\n", akPos); + if (!(wsPos == akPos)) + { + kPos = source.find("kernel", kPos + 1); + continue; + } + + bool attributeFound; + do + { + attributeFound = false; + // find '(' after kernel name name + size_t pPos = source.find("(", akPos); + if (!(pPos != std::string::npos)) + continue; + + // check for not empty kernel name before '(' + pos = source.find_last_not_of(" \t\r\n", pPos - 1); + if (!(pos != std::string::npos && pos > akPos)) + continue; + + //find character before kernel name + wsPos = source.find_last_of(" \t\r\n", pos); + if (!(wsPos != std::string::npos && wsPos >= akPos)) + continue; + + std::string name = source.substr(wsPos + 1, pos + 1 - (wsPos + 1)); + //check for kernel attribute + if (name == "__attribute__") + { + attributeFound = true; + int pCount = 1; + akPos = pPos + 1; + while (pCount > 0 && akPos != std::string::npos) + { + akPos = source.find_first_of("()", akPos + 1); + if (akPos != std::string::npos) + { + if (source[akPos] == '(') + pCount++; + else + pCount--; + } + } + } + else + { + kernelsList += name + "."; + } + } while (attributeFound); + } + kPos = source.find("kernel", kPos + 1); + } + std::ostringstream oss; + if (MAX_LEN_FOR_KERNEL_LIST > 0) + { + if (kernelsList.size() > MAX_LEN_FOR_KERNEL_LIST + 1) + { + kernelsList = kernelsList.substr(0, MAX_LEN_FOR_KERNEL_LIST + 1); + kernelsList[kernelsList.size() - 1] = '.'; + kernelsList[kernelsList.size() - 1] = '.'; + } + oss << kernelsList; + } + oss << std::hex << std::setfill('0') << std::setw(8) << crc; + return oss.str(); +} + +std::string add_build_options(const std::string &baseName, const char *options) +{ + if (options == 0 || options[0] == 0) + return get_file_name(baseName, 0, ""); + + bool equal = false; + int i = 0; + + do + { + i++; + std::string fileName = gSpirVPath + slash + get_file_name(baseName, i, ".options"); + long fileSize = get_file_size(fileName); + if (fileSize == 0) + break; + //if(fileSize == strlen(options)) + { + std::vector options2 = get_file_content(fileName); + options2.push_back(0); //terminate string + equal = strcmp(options, &options2[0]) == 0; + } + } while (!equal); + if (equal) + return get_file_name(baseName, i, ""); + + std::string fileName = gSpirVPath + slash + get_file_name(baseName, i, ".options"); + std::ofstream ofs(fileName.c_str(), std::ios::binary); + if (!ofs.good()) + { + log_info("OfflineCompiler: can't create options: %s\n", fileName.c_str()); + return ""; + } + // write data as a block: + ofs.write(options, strlen(options)); + log_info("OfflineCompiler: options added: %s\n", fileName.c_str()); + return get_file_name(baseName, i, ""); +} + +int create_single_kernel_helper_create_program(cl_context context, + cl_program *outProgram, + unsigned int numKernelLines, + const char **kernelProgram, + const char *buildOptions, + const bool openclCXX) +{ + int error = CL_SUCCESS; + std::string modifiedKernelStr; + const char* modifiedKernelCode; + + if (gOfflineCompiler) + { + #ifndef CL_OFFLINE_COMPILER + log_error("Offline compilation is not possible: CL_OFFLINE_COMPILER was not defined.\n"); + return -1; + #endif // !CL_OFFLINE_COMPILER + + std::string kernel; + for (size_t i = 0; i < numKernelLines; ++i) + { + std::string chunk(kernelProgram[i], 0, std::string::npos); + kernel += chunk; + } + + std::string kernelName = get_kernel_name(kernel); + + // set build options + std::string bOptions; + bOptions += buildOptions ? std::string(buildOptions) : ""; + + kernelName = add_build_options(kernelName, buildOptions); + + std::string gOfflineCompilerInput = gSpirVPath + slash + kernelName + ".cl"; + std::string gOfflineCompilerOutput = gSpirVPath + slash + kernelName; + + // Get device CL_DEVICE_ADDRESS_BITS + cl_uint device_address_space_size = 0; + if (gOfflineCompilerOutputType == kSpir_v) + { + cl_device_id device; + cl_uint numDevices = 0; + cl_int error = clGetContextInfo(context, CL_CONTEXT_NUM_DEVICES, sizeof(cl_uint), &numDevices, 0); + if (error != CL_SUCCESS) + { + print_error(error, "clGetContextInfo failed"); + return error; + } + + std::vector devices(numDevices, 0); + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, numDevices*sizeof(cl_device_id), &devices[0], 0); + if (error != CL_SUCCESS) + { + print_error(error, "clGetContextInfo failed"); + return error; + } + + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, numDevices*sizeof(cl_device_id), &devices[0], NULL); + if (error != CL_SUCCESS) + { + print_error(error, "clGetContextInfo failed"); + return error; + } + + if ((0 == device_address_space_size) && ((error = clGetDeviceInfo(devices[0], CL_DEVICE_ADDRESS_BITS, sizeof(cl_uint), &device_address_space_size, NULL)))) + { + print_error(error, "Unable to obtain device address bits"); + return -1; + } + + if (device_address_space_size == 32) + { + gOfflineCompilerOutput += ".spv32"; + } + else if (device_address_space_size == 64) + { + gOfflineCompilerOutput += ".spv64"; + } + } + + // try to read cached output file when test is run with gForceSpirVGenerate = false + std::ifstream ifs(gOfflineCompilerOutput.c_str(), std::ios::binary); + if (!ifs.good() || gForceSpirVGenerate) + { + if (gForceSpirVCache) + { + log_info("OfflineCompiler: can't open cached SpirV file: %s\n", gOfflineCompilerOutput.c_str()); + return -1; + } + + ifs.close(); + + if (!gForceSpirVGenerate) + log_info("OfflineCompiler: can't find cached SpirV file: %s\n", gOfflineCompilerOutput.c_str()); + + std::ofstream ofs(gOfflineCompilerInput.c_str(), std::ios::binary); + if (!ofs.good()) + { + log_info("OfflineCompiler: can't create source file: %s\n", gOfflineCompilerInput.c_str()); + return -1; + } + + // write source to input file + ofs.write(kernel.c_str(), kernel.size()); + ofs.close(); + + // Set compiler options + // Emit SPIR-V + std::string compilerOptions = " -cc1 -emit-spirv"; + // : for 32 bit SPIR-V use spir-unknown-unknown, for 64 bit SPIR-V use spir64-unknown-unknown. + if(device_address_space_size == 32) + { + compilerOptions += " -triple=spir-unknown-unknown"; + } + else + { + compilerOptions += " -triple=spir64-unknown-unknown"; + } + // Set OpenCL C++ flag required by SPIR-V-ready clang (compiler provided by Khronos) + if(openclCXX) + { + compilerOptions = compilerOptions + " -cl-std=c++"; + } + // Set correct includes + if(openclCXX) + { + compilerOptions += " -I "; + compilerOptions += STRINGIFY_VALUE(CL_LIBCLCXX_DIR); + } + else + { + compilerOptions += " -include opencl.h"; + } + + #ifdef CL_OFFLINE_COMPILER_OPTIONS + compilerOptions += STRINGIFY_VALUE(CL_OFFLINE_COMPILER_OPTIONS); + #endif + + // Add build options passed to this function + compilerOptions += " " + bOptions; + compilerOptions += + " " + gOfflineCompilerInput + + " -o " + gOfflineCompilerOutput; + std::string runString = STRINGIFY_VALUE(CL_OFFLINE_COMPILER) + compilerOptions; + + // execute script + log_info("Executing command: %s\n", runString.c_str()); + fflush(stdout); + int returnCode = system(runString.c_str()); + if (returnCode != 0) + { + log_error("ERROR: Command finished with error: 0x%x\n", returnCode); + return CL_COMPILE_PROGRAM_FAILURE; + } + // read output file + ifs.open(gOfflineCompilerOutput.c_str(), std::ios::binary); + if (!ifs.good()) + { + log_info("OfflineCompiler: can't read output file: %s\n", gOfflineCompilerOutput.c_str()); + return -1; + } + } + + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + // Only OpenCL C++ to SPIR-V compilation + #if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + if(openclCXX) + { + return CL_SUCCESS; + } + #endif + + ifs.seekg(0, ifs.end); + int length = ifs.tellg(); + ifs.seekg(0, ifs.beg); + + //treat modifiedProgram as input for clCreateProgramWithSource + if (gOfflineCompilerOutputType == kSource) + { + // read source from file: + std::vector modifiedKernelBuf(length); + + ifs.read(&modifiedKernelBuf[0], length); + ifs.close(); + + for (int i = 0; i < length; i++) + modifiedKernelStr.push_back(modifiedKernelBuf[i]); + + modifiedKernelCode = &modifiedKernelStr[0]; + + /* Create the program object from source - to be removed in the future as we will use offline compiler here */ + *outProgram = clCreateProgramWithSource(context, numKernelLines, &modifiedKernelCode, NULL, &error); + if (*outProgram == NULL || error != CL_SUCCESS) + { + print_error(error, "clCreateProgramWithSource failed"); + return error; + } + } + //treat modifiedProgram as input for clCreateProgramWithBinary + else if (gOfflineCompilerOutputType == kBinary) + { + // read binary from file: + std::vector modifiedKernelBuf(length); + + ifs.read((char *)&modifiedKernelBuf[0], length); + ifs.close(); + + cl_uint numDevices = 0; + cl_int error = clGetContextInfo(context, CL_CONTEXT_NUM_DEVICES, sizeof(cl_uint), &numDevices, 0); + test_error(error, "clGetContextInfo failed"); + + std::vector devices(numDevices, 0); + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, numDevices*sizeof(cl_device_id), &devices[0], 0); + test_error(error, "clGetContextInfo failed"); + + size_t lengths = modifiedKernelBuf.size(); + const unsigned char *binaries = { &modifiedKernelBuf[0] }; + log_info("offlineCompiler: clCreateProgramWithSource replaced with clCreateProgramWithBinary\n"); + *outProgram = clCreateProgramWithBinary(context, 1, &devices[0], &lengths, &binaries, NULL, &error); + if (*outProgram == NULL || error != CL_SUCCESS) + { + print_error(error, "clCreateProgramWithBinary failed"); + return error; + } + } + //treat modifiedProgram as input for clCreateProgramWithIL + else if (gOfflineCompilerOutputType == kSpir_v) + { + // read spir-v from file: + std::vector modifiedKernelBuf(length); + + ifs.read((char *)&modifiedKernelBuf[0], length); + ifs.close(); + + size_t length = modifiedKernelBuf.size(); + log_info("offlineCompiler: clCreateProgramWithSource replaced with clCreateProgramWithIL\n"); + + *outProgram = clCreateProgramWithIL(context, &modifiedKernelBuf[0], length, &error); + if (*outProgram == NULL || error != CL_SUCCESS) + { + print_error(error, "clCreateProgramWithIL failed"); + return error; + } + } + } + else // gOfflineCompiler == false + { + /* Create the program object from source */ + *outProgram = clCreateProgramWithSource(context, numKernelLines, kernelProgram, NULL, &error); + if (*outProgram == NULL || error != CL_SUCCESS) + { + print_error(error, "clCreateProgramWithSource failed"); + return error; + } + } + return 0; +} + +int create_single_kernel_helper_with_build_options(cl_context context, + cl_program *outProgram, + cl_kernel *outKernel, + unsigned int numKernelLines, + const char **kernelProgram, + const char *kernelName, + const char *buildOptions, + const bool openclCXX) +{ + return create_single_kernel_helper(context, outProgram, outKernel, numKernelLines, kernelProgram, kernelName, buildOptions, openclCXX); +} + +// Creates and builds OpenCL C/C++ program, and creates a kernel +int create_single_kernel_helper(cl_context context, + cl_program *outProgram, + cl_kernel *outKernel, + unsigned int numKernelLines, + const char **kernelProgram, + const char *kernelName, + const char *buildOptions, + const bool openclCXX) +{ + int error; + // Create OpenCL C++ program + if(openclCXX) + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + // Only OpenCL C++ to SPIR-V compilation + #if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + // Save global variable + bool tempgForceSpirVGenerate = gForceSpirVGenerate; + // Force OpenCL C++ -> SPIR-V compilation on every run + gForceSpirVGenerate = true; + #endif + error = create_openclcpp_program( + context, outProgram, numKernelLines, kernelProgram, buildOptions + ); + if (error != CL_SUCCESS) + { + log_error("Create program failed: %d, line: %d\n", error, __LINE__); + return error; + } + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + // Restore global variables + gForceSpirVGenerate = tempgForceSpirVGenerate; + log_info("WARNING: KERNEL %s WAS ONLY COMPILED TO SPIR-V\n", kernelName); + return error; + #endif + } + // Create OpenCL C program + else + { + error = create_single_kernel_helper_create_program( + context, outProgram, numKernelLines, kernelProgram, buildOptions + ); + if (error != CL_SUCCESS) + { + log_error("Create program failed: %d, line: %d\n", error, __LINE__); + return error; + } + } + // Remove offline-compiler-only build options + std::string newBuildOptions; + if (buildOptions != NULL) + { + newBuildOptions = buildOptions; + std::string offlineCompierOptions[] = { + "-cl-fp16-enable", + "-cl-fp64-enable", + "-cl-zero-init-local-mem-vars" + }; + for(auto& s : offlineCompierOptions) + { + std::string::size_type i = newBuildOptions.find(s); + if (i != std::string::npos) + newBuildOptions.erase(i, s.length()); + } + } + // Build program and create kernel + return build_program_create_kernel_helper( + context, outProgram, outKernel, numKernelLines, kernelProgram, kernelName, newBuildOptions.c_str() + ); +} + +// Creates OpenCL C++ program +int create_openclcpp_program(cl_context context, + cl_program *outProgram, + unsigned int numKernelLines, + const char **kernelProgram, + const char *buildOptions) +{ + // Save global variables + bool tempgOfflineCompiler = gOfflineCompiler; + OfflineCompilerOutputType tempgOfflineCompilerOutputType = gOfflineCompilerOutputType; + // Force offline compilation to SPIR-V + gOfflineCompiler = true; + gOfflineCompilerOutputType = OfflineCompilerOutputType::kSpir_v; + // Create program + int error = create_single_kernel_helper_create_program( + context, outProgram, numKernelLines, kernelProgram, buildOptions, true + ); + // Restore global variable + gOfflineCompiler = tempgOfflineCompiler; + gOfflineCompilerOutputType = tempgOfflineCompilerOutputType; + // Return result + return error; +} + +// Builds OpenCL C/C++ program and creates +int build_program_create_kernel_helper(cl_context context, + cl_program *outProgram, + cl_kernel *outKernel, + unsigned int numKernelLines, + const char **kernelProgram, + const char *kernelName, + const char *buildOptions) +{ + int error; + /* Compile the program */ + int buildProgramFailed = 0; + int printedSource = 0; + error = clBuildProgram(*outProgram, 0, NULL, buildOptions, NULL, NULL); + if (error != CL_SUCCESS) + { + unsigned int i; + print_error(error, "clBuildProgram failed"); + buildProgramFailed = 1; + printedSource = 1; + log_error("Build options: %s\n", buildOptions); + log_error("Original source is: ------------\n"); + for (i = 0; i < numKernelLines; i++) + log_error("%s", kernelProgram[i]); + } + + // Verify the build status on all devices + cl_uint deviceCount = 0; + error = clGetProgramInfo(*outProgram, CL_PROGRAM_NUM_DEVICES, sizeof(deviceCount), &deviceCount, NULL); + if (error != CL_SUCCESS) + { + print_error(error, "clGetProgramInfo CL_PROGRAM_NUM_DEVICES failed"); + return error; + } + + if (deviceCount == 0) + { + log_error("No devices found for program.\n"); + return -1; + } + + cl_device_id *devices = (cl_device_id *)malloc(deviceCount * sizeof(cl_device_id)); + if (NULL == devices) + return -1; + BufferOwningPtr devicesBuf(devices); + + memset(devices, 0, deviceCount * sizeof(cl_device_id)); + error = clGetProgramInfo(*outProgram, CL_PROGRAM_DEVICES, sizeof(cl_device_id) * deviceCount, devices, NULL); + if (error != CL_SUCCESS) + { + print_error(error, "clGetProgramInfo CL_PROGRAM_DEVICES failed"); + return error; + } + + cl_uint z; + bool buildFailed = false; + for (z = 0; z < deviceCount; z++) + { + char deviceName[4096] = ""; + error = clGetDeviceInfo(devices[z], CL_DEVICE_NAME, sizeof(deviceName), deviceName, NULL); + if (error != CL_SUCCESS || deviceName[0] == '\0') + { + log_error("Device \"%d\" failed to return a name\n", z); + print_error(error, "clGetDeviceInfo CL_DEVICE_NAME failed"); + } + + cl_build_status buildStatus; + error = clGetProgramBuildInfo(*outProgram, devices[z], CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL); + if (error != CL_SUCCESS) + { + print_error(error, "clGetProgramBuildInfo CL_PROGRAM_BUILD_STATUS failed"); + return error; + } + + if (buildStatus == CL_BUILD_SUCCESS && buildProgramFailed && deviceCount == 1) + { + buildFailed = true; + log_error("clBuildProgram returned an error, but buildStatus is marked as CL_BUILD_SUCCESS.\n"); + } + + if (buildStatus != CL_BUILD_SUCCESS) + { + + char statusString[64] = ""; + if (buildStatus == (cl_build_status)CL_BUILD_SUCCESS) + sprintf(statusString, "CL_BUILD_SUCCESS"); + else if (buildStatus == (cl_build_status)CL_BUILD_NONE) + sprintf(statusString, "CL_BUILD_NONE"); + else if (buildStatus == (cl_build_status)CL_BUILD_ERROR) + sprintf(statusString, "CL_BUILD_ERROR"); + else if (buildStatus == (cl_build_status)CL_BUILD_IN_PROGRESS) + sprintf(statusString, "CL_BUILD_IN_PROGRESS"); + else + sprintf(statusString, "UNKNOWN (%d)", buildStatus); + + if (buildStatus != CL_BUILD_SUCCESS) + log_error("Build not successful for device \"%s\", status: %s\n", deviceName, statusString); + size_t paramSize = 0; + error = clGetProgramBuildInfo(*outProgram, devices[z], CL_PROGRAM_BUILD_LOG, 0, NULL, ¶mSize); + if (error != CL_SUCCESS) + { + + print_error(error, "clGetProgramBuildInfo CL_PROGRAM_BUILD_LOG failed"); + return error; + } + + std::string log; + log.resize(paramSize / sizeof(char)); + error = clGetProgramBuildInfo(*outProgram, devices[z], CL_PROGRAM_BUILD_LOG, paramSize, &log[0], NULL); + if (error != CL_SUCCESS || log[0] == '\0') + { + log_error("Device %d (%s) failed to return a build log\n", z, deviceName); + if (error) + { + print_error(error, "clGetProgramBuildInfo CL_PROGRAM_BUILD_LOG failed"); + return error; + } + else + { + log_error("clGetProgramBuildInfo returned an empty log.\n"); + return -1; + } + } + // In this case we've already printed out the code above. + if (!printedSource) + { + unsigned int i; + log_error("Original source is: ------------\n"); + for (i = 0; i < numKernelLines; i++) + log_error("%s", kernelProgram[i]); + printedSource = 1; + } + log_error("Build log for device \"%s\" is: ------------\n", deviceName); + log_error("%s\n", log.c_str()); + log_error("\n----------\n"); + return -1; + } + } + + if (buildFailed) + { + return -1; + } + + /* And create a kernel from it */ + if (kernelName != NULL) + { + *outKernel = clCreateKernel(*outProgram, kernelName, &error); + if (*outKernel == NULL || error != CL_SUCCESS) + { + print_error(error, "Unable to create kernel"); + return error; + } + } + + return 0; +} + +int get_device_version( cl_device_id id, size_t* major, size_t* minor) +{ + cl_char buffer[ 4098 ]; + size_t length; + + // Device version should fit the regex "OpenCL [0-9]+\.[0-9]+ *.*" + cl_int error = clGetDeviceInfo( id, CL_DEVICE_VERSION, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get device version string" ); + + char *p1 = (char *)buffer + strlen( "OpenCL " ); + char *p2; + while( *p1 == ' ' ) + p1++; + *major = strtol( p1, &p2, 10 ); + error = *p2 != '.'; + test_error(error, "ERROR: Version number must contain a decimal point!"); + *minor = strtol( ++p2, NULL, 10 ); + return error; +} + +int get_max_allowed_work_group_size( cl_context context, cl_kernel kernel, size_t *outMaxSize, size_t *outLimits ) +{ + cl_device_id *devices; + size_t size, maxCommonSize = 0; + int numDevices, i, j, error; + cl_uint numDims; + size_t outSize; + size_t sizeLimit[]={1,1,1}; + + + /* Assume fewer than 16 devices will be returned */ + error = clGetContextInfo( context, CL_CONTEXT_DEVICES, 0, NULL, &outSize ); + test_error( error, "Unable to obtain list of devices size for context" ); + devices = (cl_device_id *)malloc(outSize); + BufferOwningPtr devicesBuf(devices); + + error = clGetContextInfo( context, CL_CONTEXT_DEVICES, outSize, devices, NULL ); + test_error( error, "Unable to obtain list of devices for context" ); + + numDevices = (int)( outSize / sizeof( cl_device_id ) ); + + for( i = 0; i < numDevices; i++ ) + { + error = clGetDeviceInfo( devices[i], CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof( size ), &size, NULL ); + test_error( error, "Unable to obtain max work group size for device" ); + if( size < maxCommonSize || maxCommonSize == 0) + maxCommonSize = size; + + error = clGetKernelWorkGroupInfo( kernel, devices[i], CL_KERNEL_WORK_GROUP_SIZE, sizeof( size ), &size, NULL ); + test_error( error, "Unable to obtain max work group size for device and kernel combo" ); + if( size < maxCommonSize || maxCommonSize == 0) + maxCommonSize = size; + + error= clGetDeviceInfo( devices[i], CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof( numDims ), &numDims, NULL); + test_error( error, "clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS"); + sizeLimit[0] = 1; + error= clGetDeviceInfo( devices[i], CL_DEVICE_MAX_WORK_ITEM_SIZES, numDims*sizeof(size_t), sizeLimit, NULL); + test_error( error, "clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_SIZES"); + + if (outLimits != NULL) + { + if (i == 0) { + for (j=0; j<3; j++) + outLimits[j] = sizeLimit[j]; + } else { + for (j=0; j<(int)numDims; j++) { + if (sizeLimit[j] < outLimits[j]) + outLimits[j] = sizeLimit[j]; + } + } + } + } + + *outMaxSize = (unsigned int)maxCommonSize; + return 0; +} + + +int get_max_common_work_group_size( cl_context context, cl_kernel kernel, + size_t globalThreadSize, size_t *outMaxSize ) +{ + size_t sizeLimit[3]; + int error = get_max_allowed_work_group_size( context, kernel, outMaxSize, sizeLimit ); + if( error != 0 ) + return error; + + /* Now find the largest factor of globalThreadSize that is <= maxCommonSize */ + /* Note for speed, we don't need to check the range of maxCommonSize, b/c once it gets to 1, + the modulo test will succeed and break the loop anyway */ + for( ; ( globalThreadSize % *outMaxSize ) != 0 || (*outMaxSize > sizeLimit[0]); (*outMaxSize)-- ) + ; + return 0; +} + +int get_max_common_2D_work_group_size( cl_context context, cl_kernel kernel, + size_t *globalThreadSizes, size_t *outMaxSizes ) +{ + size_t sizeLimit[3]; + size_t maxSize; + int error = get_max_allowed_work_group_size( context, kernel, &maxSize, sizeLimit ); + if( error != 0 ) + return error; + + /* Now find a set of factors, multiplied together less than maxSize, but each a factor of the global + sizes */ + + /* Simple case */ + if( globalThreadSizes[ 0 ] * globalThreadSizes[ 1 ] <= maxSize ) + { + if (globalThreadSizes[ 0 ] <= sizeLimit[0] && globalThreadSizes[ 1 ] <= sizeLimit[1]) { + outMaxSizes[ 0 ] = globalThreadSizes[ 0 ]; + outMaxSizes[ 1 ] = globalThreadSizes[ 1 ]; + return 0; + } + } + + size_t remainingSize, sizeForThisOne; + remainingSize = maxSize; + int i, j; + for (i=0 ; i<2; i++) { + if (globalThreadSizes[i] > remainingSize) + sizeForThisOne = remainingSize; + else + sizeForThisOne = globalThreadSizes[i]; + for (; (globalThreadSizes[i] % sizeForThisOne) != 0 || (sizeForThisOne > sizeLimit[i]); sizeForThisOne--) ; + outMaxSizes[i] = sizeForThisOne; + remainingSize = maxSize; + for (j=0; j<=i; j++) + remainingSize /=outMaxSizes[j]; + } + + return 0; +} + +int get_max_common_3D_work_group_size( cl_context context, cl_kernel kernel, + size_t *globalThreadSizes, size_t *outMaxSizes ) +{ + size_t sizeLimit[3]; + size_t maxSize; + int error = get_max_allowed_work_group_size( context, kernel, &maxSize, sizeLimit ); + if( error != 0 ) + return error; + /* Now find a set of factors, multiplied together less than maxSize, but each a factor of the global + sizes */ + + /* Simple case */ + if( globalThreadSizes[ 0 ] * globalThreadSizes[ 1 ] * globalThreadSizes[ 2 ] <= maxSize ) + { + if (globalThreadSizes[ 0 ] <= sizeLimit[0] && globalThreadSizes[ 1 ] <= sizeLimit[1] && globalThreadSizes[ 2 ] <= sizeLimit[2]) { + outMaxSizes[ 0 ] = globalThreadSizes[ 0 ]; + outMaxSizes[ 1 ] = globalThreadSizes[ 1 ]; + outMaxSizes[ 2 ] = globalThreadSizes[ 2 ]; + return 0; + } + } + + size_t remainingSize, sizeForThisOne; + remainingSize = maxSize; + int i, j; + for (i=0 ; i<3; i++) { + if (globalThreadSizes[i] > remainingSize) + sizeForThisOne = remainingSize; + else + sizeForThisOne = globalThreadSizes[i]; + for (; (globalThreadSizes[i] % sizeForThisOne) != 0 || (sizeForThisOne > sizeLimit[i]); sizeForThisOne--) ; + outMaxSizes[i] = sizeForThisOne; + remainingSize = maxSize; + for (j=0; j<=i; j++) + remainingSize /=outMaxSizes[j]; + } + + return 0; +} + +/* Helper to determine if an extension is supported by a device */ +int is_extension_available( cl_device_id device, const char *extensionName ) +{ + char *extString; + size_t size = 0; + int err; + int result = 0; + + if(( err = clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, 0, NULL, &size) )) + { + log_error( "Error: failed to determine size of device extensions string at %s:%d (err = %d)\n", __FILE__, __LINE__, err ); + return 0; + } + + if( 0 == size ) + return 0; + + extString = (char*) malloc( size ); + + if( NULL == extString ) + { + log_error( "Error: unable to allocate %ld byte buffer for extension string at %s:%d (err = %d)\n", size, __FILE__, __LINE__, err ); + return 0; + } + BufferOwningPtr extStringBuf(extString); + + if(( err = clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, size, extString, NULL) )) + { + log_error( "Error: failed to obtain device extensions string at %s:%d (err = %d)\n", __FILE__, __LINE__, err ); + return 0; + } + + if( strstr( extString, extensionName ) ) + result = 1; + + return result; +} + +/* Helper to determine if a device supports an image format */ +int is_image_format_supported( cl_context context, cl_mem_flags flags, cl_mem_object_type image_type, const cl_image_format *fmt ) +{ + cl_image_format *list; + cl_uint count = 0; + cl_int err = clGetSupportedImageFormats( context, flags, image_type, 128, NULL, &count ); + if( count == 0 ) + return 0; + + list = (cl_image_format*) malloc( count * sizeof( cl_image_format ) ); + if( NULL == list ) + { + log_error( "Error: unable to allocate %ld byte buffer for image format list at %s:%d (err = %d)\n", count * sizeof( cl_image_format ), __FILE__, __LINE__, err ); + return 0; + } + BufferOwningPtr listBuf(list); + + + cl_int error = clGetSupportedImageFormats( context, flags, image_type, count, list, NULL ); + if( error ) + { + log_error( "Error: failed to obtain supported image type list at %s:%d (err = %d)\n", __FILE__, __LINE__, err ); + return 0; + } + + // iterate looking for a match. + cl_uint i; + for( i = 0; i < count; i++ ) + { + if( fmt->image_channel_data_type == list[ i ].image_channel_data_type && + fmt->image_channel_order == list[ i ].image_channel_order ) + break; + } + + return ( i < count ) ? 1 : 0; +} + +size_t get_pixel_bytes( const cl_image_format *fmt ); +size_t get_pixel_bytes( const cl_image_format *fmt ) +{ + size_t chanCount; + switch( fmt->image_channel_order ) + { + case CL_R: + case CL_A: + case CL_Rx: + case CL_INTENSITY: + case CL_LUMINANCE: + case CL_DEPTH: + chanCount = 1; + break; + case CL_RG: + case CL_RA: + case CL_RGx: + chanCount = 2; + break; + case CL_RGB: + case CL_RGBx: + case CL_sRGB: + case CL_sRGBx: + chanCount = 3; + break; + case CL_RGBA: + case CL_ARGB: + case CL_BGRA: + case CL_sBGRA: + case CL_sRGBA: +#ifdef CL_1RGB_APPLE + case CL_1RGB_APPLE: +#endif +#ifdef CL_BGR1_APPLE + case CL_BGR1_APPLE: +#endif + chanCount = 4; + break; + default: + log_error("Unknown channel order at %s:%d!\n", __FILE__, __LINE__ ); + abort(); + break; + } + + switch( fmt->image_channel_data_type ) + { + case CL_UNORM_SHORT_565: + case CL_UNORM_SHORT_555: + return 2; + + case CL_UNORM_INT_101010: + return 4; + + case CL_SNORM_INT8: + case CL_UNORM_INT8: + case CL_SIGNED_INT8: + case CL_UNSIGNED_INT8: + return chanCount; + + case CL_SNORM_INT16: + case CL_UNORM_INT16: + case CL_HALF_FLOAT: + case CL_SIGNED_INT16: + case CL_UNSIGNED_INT16: +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: +#endif + return chanCount * 2; + + case CL_SIGNED_INT32: + case CL_UNSIGNED_INT32: + case CL_FLOAT: + return chanCount * 4; + + default: + log_error("Unknown channel data type at %s:%d!\n", __FILE__, __LINE__ ); + abort(); + } + + return 0; +} + +int verifyImageSupport( cl_device_id device ) +{ + if( checkForImageSupport( device ) ) + { + log_error( "ERROR: Device does not supported images as required by this test!\n" ); + return CL_IMAGE_FORMAT_NOT_SUPPORTED; + } + return 0; +} + +int checkForImageSupport( cl_device_id device ) +{ + cl_uint i; + int error; + + + /* Check the device props to see if images are supported at all first */ + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE_SUPPORT, sizeof( i ), &i, NULL ); + test_error( error, "Unable to query device for image support" ); + if( i == 0 ) + { + return CL_IMAGE_FORMAT_NOT_SUPPORTED; + } + + /* So our support is good */ + return 0; +} + +int checkFor3DImageSupport( cl_device_id device ) +{ + cl_uint i; + int error; + + /* Check the device props to see if images are supported at all first */ + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE_SUPPORT, sizeof( i ), &i, NULL ); + test_error( error, "Unable to query device for image support" ); + if( i == 0 ) + { + return CL_IMAGE_FORMAT_NOT_SUPPORTED; + } + + char profile[128]; + error = clGetDeviceInfo( device, CL_DEVICE_PROFILE, sizeof(profile ), profile, NULL ); + test_error( error, "Unable to query device for CL_DEVICE_PROFILE" ); + if( 0 == strcmp( profile, "EMBEDDED_PROFILE" ) ) + { + size_t width = -1L; + size_t height = -1L; + size_t depth = -1L; + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof(width), &width, NULL ); + test_error( error, "Unable to get CL_DEVICE_IMAGE3D_MAX_WIDTH" ); + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof(height), &height, NULL ); + test_error( error, "Unable to get CL_DEVICE_IMAGE3D_MAX_HEIGHT" ); + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(depth), &depth, NULL ); + test_error( error, "Unable to get CL_DEVICE_IMAGE3D_MAX_DEPTH" ); + + if( 0 == (height | width | depth )) + return CL_IMAGE_FORMAT_NOT_SUPPORTED; + } + + /* So our support is good */ + return 0; +} + +void * align_malloc(size_t size, size_t alignment) +{ +#if defined(_WIN32) && defined(_MSC_VER) + return _aligned_malloc(size, alignment); +#elif defined(__linux__) || defined (linux) || defined(__APPLE__) + void * ptr = NULL; + // alignemnt must be a power of two and multiple of sizeof(void *). + if ( alignment < sizeof( void * ) ) + { + alignment = sizeof( void * ); + } +#if defined(__ANDROID__) + ptr = memalign(alignment, size); + if ( ptr ) + return ptr; +#else + if (0 == posix_memalign(&ptr, alignment, size)) + return ptr; +#endif + return NULL; +#elif defined(__MINGW32__) + return __mingw_aligned_malloc(size, alignment); +#else + #error "Please add support OS for aligned malloc" +#endif +} + +void align_free(void * ptr) +{ +#if defined(_WIN32) && defined(_MSC_VER) + _aligned_free(ptr); +#elif defined(__linux__) || defined (linux) || defined(__APPLE__) + return free(ptr); +#elif defined(__MINGW32__) + return __mingw_aligned_free(ptr); +#else + #error "Please add support OS for aligned free" +#endif +} + +size_t get_min_alignment(cl_context context) +{ + static cl_uint align_size = 0; + + if( 0 == align_size ) + { + cl_device_id * devices; + size_t devices_size = 0; + cl_uint result = 0; + cl_int error; + int i; + + error = clGetContextInfo (context, + CL_CONTEXT_DEVICES, + 0, + NULL, + &devices_size); + test_error_ret(error, "clGetContextInfo failed", 0); + + devices = (cl_device_id*)malloc(devices_size); + if (devices == NULL) { + print_error( error, "malloc failed" ); + return 0; + } + + error = clGetContextInfo (context, + CL_CONTEXT_DEVICES, + devices_size, + (void*)devices, + NULL); + test_error_ret(error, "clGetContextInfo failed", 0); + + for (i = 0; i < (int)(devices_size/sizeof(cl_device_id)); i++) + { + cl_uint alignment = 0; + + error = clGetDeviceInfo (devices[i], + CL_DEVICE_MEM_BASE_ADDR_ALIGN, + sizeof(cl_uint), + (void*)&alignment, + NULL); + + if (error == CL_SUCCESS) + { + alignment >>= 3; // convert bits to bytes + result = (alignment > result) ? alignment : result; + } + else + print_error( error, "clGetDeviceInfo failed" ); + } + + align_size = result; + free(devices); + } + + return align_size; +} + +cl_device_fp_config get_default_rounding_mode( cl_device_id device ) +{ + char profileStr[128] = ""; + cl_device_fp_config single = 0; + int error = clGetDeviceInfo( device, CL_DEVICE_SINGLE_FP_CONFIG, sizeof( single ), &single, NULL ); + if( error ) + test_error_ret( error, "Unable to get device CL_DEVICE_SINGLE_FP_CONFIG", 0 ); + + if( single & CL_FP_ROUND_TO_NEAREST ) + return CL_FP_ROUND_TO_NEAREST; + + if( 0 == (single & CL_FP_ROUND_TO_ZERO) ) + test_error_ret( -1, "FAILURE: device must support either CL_DEVICE_SINGLE_FP_CONFIG or CL_FP_ROUND_TO_NEAREST", 0 ); + + // Make sure we are an embedded device before allowing a pass + if( (error = clGetDeviceInfo( device, CL_DEVICE_PROFILE, sizeof( profileStr ), &profileStr, NULL ) )) + test_error_ret( error, "FAILURE: Unable to get CL_DEVICE_PROFILE", 0 ); + + if( strcmp( profileStr, "EMBEDDED_PROFILE" ) ) + test_error_ret( error, "FAILURE: non-EMBEDDED_PROFILE devices must support CL_FP_ROUND_TO_NEAREST", 0 ); + + return CL_FP_ROUND_TO_ZERO; +} + +int checkDeviceForQueueSupport( cl_device_id device, cl_command_queue_properties prop ) +{ + cl_command_queue_properties realProps; + cl_int error = clGetDeviceInfo( device, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES, sizeof( realProps ), &realProps, NULL ); + test_error_ret( error, "FAILURE: Unable to get device queue properties", 0 ); + + return ( realProps & prop ) ? 1 : 0; +} + +int printDeviceHeader( cl_device_id device ) +{ + char deviceName[ 512 ], deviceVendor[ 512 ], deviceVersion[ 512 ], cLangVersion[ 512 ]; + int error; + + error = clGetDeviceInfo( device, CL_DEVICE_NAME, sizeof( deviceName ), deviceName, NULL ); + test_error( error, "Unable to get CL_DEVICE_NAME for device" ); + + error = clGetDeviceInfo( device, CL_DEVICE_VENDOR, sizeof( deviceVendor ), deviceVendor, NULL ); + test_error( error, "Unable to get CL_DEVICE_VENDOR for device" ); + + error = clGetDeviceInfo( device, CL_DEVICE_VERSION, sizeof( deviceVersion ), deviceVersion, NULL ); + test_error( error, "Unable to get CL_DEVICE_VERSION for device" ); + + error = clGetDeviceInfo( device, CL_DEVICE_OPENCL_C_VERSION, sizeof( cLangVersion ), cLangVersion, NULL ); + test_error( error, "Unable to get CL_DEVICE_OPENCL_C_VERSION for device" ); + + log_info("Compute Device Name = %s, Compute Device Vendor = %s, Compute Device Version = %s%s%s\n", + deviceName, deviceVendor, deviceVersion, ( error == CL_SUCCESS ) ? ", CL C Version = " : "", + ( error == CL_SUCCESS ) ? cLangVersion : "" ); + + return CL_SUCCESS; +} diff --git a/test_common/harness/kernelHelpers.h b/test_common/harness/kernelHelpers.h new file mode 100644 index 00000000..b39113ec --- /dev/null +++ b/test_common/harness/kernelHelpers.h @@ -0,0 +1,172 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _kernelHelpers_h +#define _kernelHelpers_h + +// Configuration +#include "../config.hpp" + +#include "compat.h" + +#include +#include + +#if defined (__MINGW32__) +#include +#endif + +#include + +#ifdef __APPLE__ + #include +#else + #include +#endif + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/* + * The below code is intended to be used at the top of kernels that appear inline in files to set line and file info for the kernel: + * + * const char *source = { + * INIT_OPENCL_DEBUG_INFO + * "__kernel void foo( int x )\n" + * "{\n" + * " ...\n" + * "}\n" + * }; + */ +#define INIT_OPENCL_DEBUG_INFO SET_OPENCL_LINE_INFO( __LINE__, __FILE__ ) +#define SET_OPENCL_LINE_INFO(_line, _file) "#line " STRINGIFY(_line) " " STRINGIFY(_file) "\n" +#ifndef STRINGIFY_VALUE + #define STRINGIFY_VALUE(_x) STRINGIFY(_x) +#endif +#ifndef STRINGIFY + #define STRINGIFY(_x) #_x +#endif + +const int MAX_LEN_FOR_KERNEL_LIST = 20; + +/* Helper that creates a single program and kernel from a single-kernel program source */ +extern int create_single_kernel_helper(cl_context context, + cl_program *outProgram, + cl_kernel *outKernel, + unsigned int numKernelLines, + const char **kernelProgram, + const char *kernelName, + const char *buildOptions = NULL, + const bool openclCXX = false); + +extern int create_single_kernel_helper_with_build_options(cl_context context, + cl_program *outProgram, + cl_kernel *outKernel, + unsigned int numKernelLines, + const char **kernelProgram, + const char *kernelName, + const char *buildOptions, + const bool openclCXX = false); + +extern int create_single_kernel_helper_create_program(cl_context context, + cl_program *outProgram, + unsigned int numKernelLines, + const char **kernelProgram, + const char *buildOptions = NULL, + const bool openclCXX = false); + +/* Creates OpenCL C++ program. This one must be used for creating OpenCL C++ program. */ +extern int create_openclcpp_program(cl_context context, + cl_program *outProgram, + unsigned int numKernelLines, + const char **kernelProgram, + const char *buildOptions = NULL); + +/* Builds program (outProgram) and creates one kernel */ +int build_program_create_kernel_helper(cl_context context, + cl_program *outProgram, + cl_kernel *outKernel, + unsigned int numKernelLines, + const char **kernelProgram, + const char *kernelName, + const char *buildOptions = NULL); + +/* Helper to obtain the biggest fit work group size for all the devices in a given group and for the given global thread size */ +extern int get_max_common_work_group_size( cl_context context, cl_kernel kernel, size_t globalThreadSize, size_t *outSize ); + +/* Helper to obtain the biggest fit work group size for all the devices in a given group and for the given global thread size */ +extern int get_max_common_2D_work_group_size( cl_context context, cl_kernel kernel, size_t *globalThreadSize, size_t *outSizes ); + +/* Helper to obtain the biggest fit work group size for all the devices in a given group and for the given global thread size */ +extern int get_max_common_3D_work_group_size( cl_context context, cl_kernel kernel, size_t *globalThreadSize, size_t *outSizes ); + +/* Helper to get major/minor number for a device */ +extern int get_device_version( cl_device_id id, size_t* major, size_t* minor); + +/* Helper to obtain the biggest allowed work group size for all the devices in a given group */ +extern int get_max_allowed_work_group_size( cl_context context, cl_kernel kernel, size_t *outSize, size_t *outLimits ); + +/* Helper to determine if an extension is supported by a device */ +extern int is_extension_available( cl_device_id device, const char *extensionName ); + +/* Helper to determine if a device supports an image format */ +extern int is_image_format_supported( cl_context context, cl_mem_flags flags, cl_mem_object_type image_type, const cl_image_format *fmt ); + +/* Helper to get pixel size for a pixel format */ +size_t get_pixel_bytes( const cl_image_format *fmt ); + +/* Verify the given device supports images. 0 means you're good to go, otherwise an error */ +extern int verifyImageSupport( cl_device_id device ); + +/* Checks that the given device supports images. Same as verify, but doesn't print an error */ +extern int checkForImageSupport( cl_device_id device ); +extern int checkFor3DImageSupport( cl_device_id device ); + +/* Checks that a given queue property is supported on the specified device. Returns 1 if supported, 0 if not or an error. */ +extern int checkDeviceForQueueSupport( cl_device_id device, cl_command_queue_properties prop ); + +/* Helper for aligned memory allocation */ +void * align_malloc(size_t size, size_t alignment); +void align_free(void *); + +/* Helper to obtain the min alignment for a given context, i.e the max of all min alignments for devices attached to the context*/ +size_t get_min_alignment(cl_context context); + +/* Helper to obtain the default rounding mode for single precision computation. (Double is always CL_FP_ROUND_TO_NEAREST.) Returns 0 on error. */ +cl_device_fp_config get_default_rounding_mode( cl_device_id device ); + +#define PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) \ + if( checkForImageSupport( device ) ) \ + { \ + log_info( "\n\tNote: device does not support images. Skipping test...\n" ); \ + return 0; \ + } + +#define PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( device ) \ + if( checkFor3DImageSupport( device ) ) \ + { \ + log_info( "\n\tNote: device does not support 3D images. Skipping test...\n" ); \ + return 0; \ + } + +/* Prints out the standard device header for all tests given the device to print for */ +extern int printDeviceHeader( cl_device_id device ); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // _kernelHelpers_h diff --git a/test_common/harness/mingw_compat.c b/test_common/harness/mingw_compat.c new file mode 100644 index 00000000..54c44635 --- /dev/null +++ b/test_common/harness/mingw_compat.c @@ -0,0 +1,59 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#if defined(__MINGW32__) + +#include "mingw_compat.h" +#include +#include + +//This function is unavailable on various mingw compilers, +//especially 64 bit so implementing it here +const char *basename_dot="."; +char* +basename(char *path) +{ + char *p = path, *b = NULL; + int len = strlen(path); + + if (path == NULL) { + return (char*)basename_dot; + } + + // Not absolute path on windows + if (path[1] != ':') { + return path; + } + + // Trim trailing path seperators + if (path[len - 1] == '\\' || + path[len - 1] == '/' ) { + len--; + path[len] = '\0'; + } + + while (len) { + while((*p != '\\' || *p != '/') && len) { + p++; + len--; + } + p++; + b = p; + } + + return b; +} + +#endif \ No newline at end of file diff --git a/test_common/harness/mingw_compat.h b/test_common/harness/mingw_compat.h new file mode 100644 index 00000000..ab28f398 --- /dev/null +++ b/test_common/harness/mingw_compat.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MINGW_COMPAT_H +#define MINGW_COMPAT_H + +#if defined(__MINGW32__) +char *basename(char *path); +#include + +#if defined(__MINGW64__) +//mingw-w64 doesnot have __mingw_aligned_malloc, instead it has _aligned_malloc +#define __mingw_aligned_malloc _aligned_malloc +#define __mingw_aligned_free _aligned_free +#include +#endif //(__MINGW64__) + +#endif //(__MINGW32__) +#endif // MINGW_COMPAT_H diff --git a/test_common/harness/msvc9.c b/test_common/harness/msvc9.c new file mode 100644 index 00000000..3b168453 --- /dev/null +++ b/test_common/harness/msvc9.c @@ -0,0 +1,774 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "compat.h" + +#if defined ( _MSC_VER ) + +#include +#include + +#include + +#include + +#if ! defined( __INTEL_COMPILER ) + +/////////////////////////////////////////////////////////////////// +// +// rint, rintf +// +/////////////////////////////////////////////////////////////////// + +float copysignf( float x, float y ) +{ + union{ cl_uint u; float f; }ux, uy; + + ux.f = x; + uy.f = y; + + ux.u = (ux.u & 0x7fffffffU) | (uy.u & 0x80000000U); + + return ux.f; +} + +double copysign( double x, double y ) +{ + union{ cl_ulong u; double f; }ux, uy; + + ux.f = x; + uy.f = y; + + ux.u = (ux.u & 0x7fffffffffffffffULL) | (uy.u & 0x8000000000000000ULL); + + return ux.f; +} + +long double copysignl( long double x, long double y ) +{ + union + { + long double f; + struct{ cl_ulong m; cl_ushort sexp; }u; + }ux, uy; + + ux.f = x; + uy.f = y; + + ux.u.sexp = (ux.u.sexp & 0x7fff) | (uy.u.sexp & 0x8000); + + return ux.f; +} + +float rintf(float x) +{ + float absx = fabsf(x); + + if( absx < 8388608.0f /* 0x1.0p23f */ ) + { + float magic = copysignf( 8388608.0f /* 0x1.0p23f */, x ); + float rounded = x + magic; + rounded -= magic; + x = copysignf( rounded, x ); + } + + return x; +} + +double rint(double x) +{ + double absx = fabs(x); + + if( absx < 4503599627370496.0 /* 0x1.0p52f */ ) + { + double magic = copysign( 4503599627370496.0 /* 0x1.0p52 */, x ); + double rounded = x + magic; + rounded -= magic; + x = copysign( rounded, x ); + } + + return x; +} + +long double rintl(long double x) +{ + double absx = fabs(x); + + if( absx < 9223372036854775808.0L /* 0x1.0p64f */ ) + { + long double magic = copysignl( 9223372036854775808.0L /* 0x1.0p63L */, x ); + long double rounded = x + magic; + rounded -= magic; + x = copysignl( rounded, x ); + } + + return x; +} + + +/////////////////////////////////////////////////////////////////// +// +// ilogb, ilogbf, ilogbl +// +/////////////////////////////////////////////////////////////////// +#ifndef FP_ILOGB0 + #define FP_ILOGB0 INT_MIN +#endif + +#ifndef FP_ILOGBNAN + #define FP_ILOGBNAN INT_MIN +#endif + +int ilogb (double x) +{ + union{ double f; cl_ulong u;} u; + u.f = x; + + cl_ulong absx = u.u & CL_LONG_MAX; + if( absx - 0x0001000000000000ULL >= 0x7ff0000000000000ULL - 0x0001000000000000ULL) + { + switch( absx ) + { + case 0: + return FP_ILOGB0; + case 0x7ff0000000000000ULL: + return INT_MAX; + default: + if( absx > 0x7ff0000000000000ULL ) + return FP_ILOGBNAN; + + // subnormal + u.u = absx | 0x3ff0000000000000ULL; + u.f -= 1.0; + return (u.u >> 52) - (1023 + 1022); + } + } + + return (absx >> 52) - 1023; +} + + +int ilogbf (float x) +{ + union{ float f; cl_uint u;} u; + u.f = x; + + cl_uint absx = u.u & 0x7fffffff; + if( absx - 0x00800000U >= 0x7f800000U - 0x00800000U) + { + switch( absx ) + { + case 0: + return FP_ILOGB0; + case 0x7f800000U: + return INT_MAX; + default: + if( absx > 0x7f800000 ) + return FP_ILOGBNAN; + + // subnormal + u.u = absx | 0x3f800000U; + u.f -= 1.0f; + return (u.u >> 23) - (127 + 126); + } + } + + return (absx >> 23) - 127; +} + +int ilogbl (long double x) +{ + union + { + long double f; + struct{ cl_ulong m; cl_ushort sexp; }u; + } u; + u.f = x; + + int exp = u.u.sexp & 0x7fff; + if( 0 == exp ) + { + if( 0 == u.u.m ) + return FP_ILOGB0; + + //subnormal + u.u.sexp = 0x3fff; + u.f -= 1.0f; + exp = u.u.sexp & 0x7fff; + + return exp - (0x3fff + 0x3ffe); + } + else if( 0x7fff == exp ) + { + if( u.u.m & CL_LONG_MAX ) + return FP_ILOGBNAN; + + return INT_MAX; + } + + return exp - 0x3fff; +} + + + +/////////////////////////////////////////////////////////////////// +// +// fmax, fmin, fmaxf, fminf +// +/////////////////////////////////////////////////////////////////// + +static void GET_BITS_SP32(float fx, unsigned int* ux) +{ + volatile union {float f; unsigned int u;} _bitsy; + _bitsy.f = (fx); + *ux = _bitsy.u; +} +/* static void GET_BITS_SP32(float fx, unsigned int* ux) */ +/* { */ +/* volatile union {float f; unsigned int i;} _bitsy; */ +/* _bitsy.f = (fx); */ +/* *ux = _bitsy.i; */ +/* } */ +static void PUT_BITS_SP32(unsigned int ux, float* fx) +{ + volatile union {float f; unsigned int u;} _bitsy; + _bitsy.u = (ux); + *fx = _bitsy.f; +} +/* static void PUT_BITS_SP32(unsigned int ux, float* fx) */ +/* { */ +/* volatile union {float f; unsigned int i;} _bitsy; */ +/* _bitsy.i = (ux); */ +/* *fx = _bitsy.f; */ +/* } */ +static void GET_BITS_DP64(double dx, unsigned __int64* lx) +{ + volatile union {double d; unsigned __int64 l;} _bitsy; + _bitsy.d = (dx); + *lx = _bitsy.l; +} +static void PUT_BITS_DP64(unsigned __int64 lx, double* dx) +{ + volatile union {double d; unsigned __int64 l;} _bitsy; + _bitsy.l = (lx); + *dx = _bitsy.d; +} + +#if 0 +int SIGNBIT_DP64(double x ) +{ + int hx; + _GET_HIGH_WORD(hx,x); + return((hx>>31)); +} +#endif + +/* fmax(x, y) returns the larger (more positive) of x and y. + NaNs are treated as missing values: if one argument is NaN, + the other argument is returned. If both arguments are NaN, + the first argument is returned. */ + +/* This works so long as the compiler knows that (x != x) means + that x is NaN; gcc does. */ +double fmax(double x, double y) +{ + if( isnan(y) ) + return x; + + return x >= y ? x : y; +} + + +/* fmin(x, y) returns the smaller (more negative) of x and y. + NaNs are treated as missing values: if one argument is NaN, + the other argument is returned. If both arguments are NaN, + the first argument is returned. */ + +double fmin(double x, double y) +{ + if( isnan(y) ) + return x; + + return x <= y ? x : y; +} + + +float fmaxf( float x, float y ) +{ + if( isnan(y) ) + return x; + + return x >= y ? x : y; +} + +/* fminf(x, y) returns the smaller (more negative) of x and y. + NaNs are treated as missing values: if one argument is NaN, + the other argument is returned. If both arguments are NaN, + the first argument is returned. */ + +float fminf(float x, float y) +{ + if( isnan(y) ) + return x; + + return x <= y ? x : y; +} + +long double scalblnl(long double x, long n) +{ + union + { + long double d; + struct{ cl_ulong m; cl_ushort sexp;}u; + }u; + u.u.m = CL_LONG_MIN; + + if( x == 0.0L || n < -2200) + return copysignl( 0.0L, x ); + + if( n > 2200 ) + return INFINITY; + + if( n < 0 ) + { + u.u.sexp = 0x3fff - 1022; + while( n <= -1022 ) + { + x *= u.d; + n += 1022; + } + u.u.sexp = 0x3fff + n; + x *= u.d; + return x; + } + + if( n > 0 ) + { + u.u.sexp = 0x3fff + 1023; + while( n >= 1023 ) + { + x *= u.d; + n -= 1023; + } + u.u.sexp = 0x3fff + n; + x *= u.d; + return x; + } + + return x; +} + +/////////////////////////////////////////////////////////////////// +// +// log2 +// +/////////////////////////////////////////////////////////////////// +const static cl_double log_e_base2 = 1.4426950408889634074; +const static cl_double log_10_base2 = 3.3219280948873623478; + +//double log10(double x); + +double log2(double x) +{ + return 1.44269504088896340735992468100189214 * log(x); +} + +long double log2l(long double x) +{ + return 1.44269504088896340735992468100189214L * log(x); +} + +double trunc(double x) +{ + double absx = fabs(x); + + if( absx < 4503599627370496.0 /* 0x1.0p52f */ ) + { + cl_long rounded = x; + x = copysign( (double) rounded, x ); + } + + return x; +} + +float truncf(float x) +{ + float absx = fabsf(x); + + if( absx < 8388608.0f /* 0x1.0p23f */ ) + { + cl_int rounded = x; + x = copysignf( (float) rounded, x ); + } + + return x; +} + +long lround(double x) +{ + double absx = fabs(x); + + if( absx < 0.5 ) + return 0; + + if( absx < 4503599627370496.0 /* 0x1.0p52 */) + { + absx += 0.5; + cl_long rounded = absx; + absx = rounded; + x = copysign( absx, x ); + } + + if( x >= (double) LONG_MAX ) + return LONG_MAX; + + return (long) x; +} + +long lroundf(float x) +{ + float absx = fabsf(x); + + if( absx < 0.5f ) + return 0; + + if( absx < 8388608.0f ) + { + absx += 0.5f; + cl_int rounded = absx; + absx = rounded; + x = copysignf( absx, x ); + } + + if( x >= (float) LONG_MAX ) + return LONG_MAX; + + return (long) x; +} + +double round(double x) +{ + double absx = fabs(x); + + if( absx < 0.5 ) + return copysign( 0.0, x); + + if( absx < 4503599627370496.0 /* 0x1.0p52 */) + { + absx += 0.5; + cl_long rounded = absx; + absx = rounded; + x = copysign( absx, x ); + } + + return x; +} + +float roundf(float x) +{ + float absx = fabsf(x); + + if( absx < 0.5f ) + return copysignf( 0.0f, x); + + if( absx < 8388608.0f ) + { + absx += 0.5f; + cl_int rounded = absx; + absx = rounded; + x = copysignf( absx, x ); + } + + return x; +} + +long double roundl(long double x) +{ + long double absx = fabsl(x); + + if( absx < 0.5L ) + return copysignl( 0.0L, x); + + if( absx < 9223372036854775808.0L /*0x1.0p63L*/ ) + { + absx += 0.5L; + cl_ulong rounded = absx; + absx = rounded; + x = copysignl( absx, x ); + } + + return x; +} + +float cbrtf( float x ) +{ + float z = pow( fabs((double) x), 1.0 / 3.0 ); + return copysignf( z, x ); +} + +double cbrt( double x ) +{ + return copysign( pow( fabs( x ), 1.0 / 3.0 ), x ); +} + +long int lrint (double x) +{ + double absx = fabs(x); + + if( x >= (double) LONG_MAX ) + return LONG_MAX; + + if( absx < 4503599627370496.0 /* 0x1.0p52 */ ) + { + double magic = copysign( 4503599627370496.0 /* 0x1.0p52 */, x ); + double rounded = x + magic; + rounded -= magic; + return (long int) rounded; + } + + return (long int) x; +} + +long int lrintf (float x) +{ + float absx = fabsf(x); + + if( x >= (float) LONG_MAX ) + return LONG_MAX; + + if( absx < 8388608.0f /* 0x1.0p23f */ ) + { + float magic = copysignf( 8388608.0f /* 0x1.0p23f */, x ); + float rounded = x + magic; + rounded -= magic; + return (long int) rounded; + } + + return (long int) x; +} + + +/////////////////////////////////////////////////////////////////// +// +// fenv functions +// +/////////////////////////////////////////////////////////////////// + +#if _MSC_VER < 1900 +int fetestexcept(int excepts) +{ + unsigned int status = _statusfp(); + return excepts & ( + ((status & _SW_INEXACT) ? FE_INEXACT : 0) | + ((status & _SW_UNDERFLOW) ? FE_UNDERFLOW : 0) | + ((status & _SW_OVERFLOW) ? FE_OVERFLOW : 0) | + ((status & _SW_ZERODIVIDE) ? FE_DIVBYZERO : 0) | + ((status & _SW_INVALID) ? FE_INVALID : 0) + ); +} + +int feclearexcept(int excepts) +{ + _clearfp(); + return 0; +} +#endif + +#endif // __INTEL_COMPILER + +#if ! defined( __INTEL_COMPILER ) || __INTEL_COMPILER < 1300 + +float make_nan() +{ +/* This is the IEEE 754 single-precision format: + unsigned int mantissa: 22; + unsigned int quiet_nan: 1; + unsigned int exponent: 8; + unsigned int negative: 1; +*/ + //const static unsigned + static const int32_t _nan = 0x7fc00000; + return *(const float*)(&_nan); +} + +float nanf( const char* str) +{ + cl_uint u = atoi( str ); + u |= 0x7fc00000U; + return *( float*)(&u); +} + + +double nan( const char* str) +{ + cl_ulong u = atoi( str ); + u |= 0x7ff8000000000000ULL; + return *( double*)(&u); +} + +// double check this implementatation +long double nanl( const char* str) +{ + union + { + long double f; + struct { cl_ulong m; cl_ushort sexp; }u; + }u; + u.u.sexp = 0x7fff; + u.u.m = 0x8000000000000000ULL | atoi( str ); + + return u.f; +} + +#endif + +/////////////////////////////////////////////////////////////////// +// +// misc functions +// +/////////////////////////////////////////////////////////////////// + +/* +// This function is commented out because the Windows implementation should never call munmap. +// If it is calling it, we have a bug. Please file a bugzilla. +int munmap(void *addr, size_t len) +{ +// FIXME: this is not correct. munmap is like free() http://www.opengroup.org/onlinepubs/7990989775/xsh/munmap.html + + return (int)VirtualAlloc( (LPVOID)addr, len, + MEM_COMMIT|MEM_RESERVE, PAGE_NOACCESS ); +} +*/ + +uint64_t ReadTime( void ) +{ + LARGE_INTEGER current; + QueryPerformanceCounter(¤t); + return (uint64_t)current.QuadPart; +} + +double SubtractTime( uint64_t endTime, uint64_t startTime ) +{ + static double PerformanceFrequency = 0.0; + + if (PerformanceFrequency == 0.0) { + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + PerformanceFrequency = (double) frequency.QuadPart; + } + + return (double)(endTime - startTime) / PerformanceFrequency * 1e9; +} + +int cf_signbit(double x) +{ + union + { + double f; + cl_ulong u; + }u; + u.f = x; + return u.u >> 63; +} + +int cf_signbitf(float x) +{ + union + { + float f; + cl_uint u; + }u; + u.f = x; + return u.u >> 31; +} + +float int2float (int32_t ix) +{ + union { + float f; + int32_t i; + } u; + u.i = ix; + return u.f; +} + +int32_t float2int (float fx) +{ + union { + float f; + int32_t i; + } u; + u.f = fx; + return u.i; +} + +#if !defined(_WIN64) +/** Returns the number of leading 0-bits in x, + starting at the most significant bit position. + If x is 0, the result is undefined. +*/ +int __builtin_clz(unsigned int pattern) +{ +#if 0 + int res; + __asm { + mov eax, pattern + bsr eax, eax + mov res, eax + } + return 31 - res; +#endif + unsigned long index; + unsigned char res = _BitScanReverse( &index, pattern); + if (res) { + return 8*sizeof(int) - 1 - index; + } else { + return 8*sizeof(int); + } +} +#else +int __builtin_clz(unsigned int pattern) +{ + int count; + if (pattern == 0u) { + return 32; + } + count = 31; + if (pattern >= 1u<<16) { pattern >>= 16; count -= 16; } + if (pattern >= 1u<<8) { pattern >>= 8; count -= 8; } + if (pattern >= 1u<<4) { pattern >>= 4; count -= 4; } + if (pattern >= 1u<<2) { pattern >>= 2; count -= 2; } + if (pattern >= 1u<<1) { count -= 1; } + return count; +} + +#endif // !defined(_WIN64) + +#include +#include + +int usleep(int usec) +{ + Sleep((usec + 999) / 1000); + return 0; +} + +unsigned int sleep( unsigned int sec ) +{ + Sleep( sec * 1000 ); + return 0; +} + +#endif // defined( _MSC_VER ) diff --git a/test_common/harness/mt19937.c b/test_common/harness/mt19937.c new file mode 100644 index 00000000..baa19fb8 --- /dev/null +++ b/test_common/harness/mt19937.c @@ -0,0 +1,280 @@ +/* + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) + + Modifications for use in OpenCL by Ian Ollmann, Apple Inc. + +*/ + +#include +#include +#include "mt19937.h" +#include "mingw_compat.h" + +#ifdef __SSE2__ + #include +#endif + +static void * align_malloc(size_t size, size_t alignment) +{ +#if defined(_WIN32) && defined(_MSC_VER) + return _aligned_malloc(size, alignment); +#elif defined(__linux__) || defined (linux) || defined(__APPLE__) + void * ptr = NULL; +#if defined(__ANDROID__) + ptr = memalign(alignment, size); + if ( ptr ) + return ptr; +#else + if (0 == posix_memalign(&ptr, alignment, size)) + return ptr; +#endif + return NULL; +#elif defined(__MINGW32__) + return __mingw_aligned_malloc(size, alignment); +#else + #error "Please add support OS for aligned malloc" +#endif +} + +static void align_free(void * ptr) +{ +#if defined(_WIN32) && defined(_MSC_VER) + _aligned_free(ptr); +#elif defined(__linux__) || defined (linux) || defined(__APPLE__) + return free(ptr); +#elif defined(__MINGW32__) + return __mingw_aligned_free(ptr); +#else + #error "Please add support OS for aligned free" +#endif +} + + +/* Period parameters */ +#define N 624 /* vector code requires multiple of 4 here */ +#define M 397 +#define MATRIX_A (cl_uint) 0x9908b0dfUL /* constant vector a */ +#define UPPER_MASK (cl_uint) 0x80000000UL /* most significant w-r bits */ +#define LOWER_MASK (cl_uint) 0x7fffffffUL /* least significant r bits */ + +typedef struct _MTdata +{ + cl_uint mt[N]; +#ifdef __SSE2__ + cl_uint cache[N]; +#endif + cl_int mti; +}_MTdata; + +/* initializes mt[N] with a seed */ +MTdata init_genrand(cl_uint s) +{ + MTdata r = (MTdata) align_malloc( sizeof( _MTdata ), 16 ); + if( NULL != r ) + { + cl_uint *mt = r->mt; + int mti = 0; + mt[0]= s; // & 0xffffffffUL; + for (mti=1; mti> 30)) + mti); + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array mt[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + // mt[mti] &= 0xffffffffUL; + /* for >32 bit machines */ + } + r->mti = mti; + } + + return r; +} + +void free_mtdata( MTdata d ) +{ + if(d) + align_free(d); +} + +/* generates a random number on [0,0xffffffff]-interval */ +cl_uint genrand_int32( MTdata d) +{ + /* mag01[x] = x * MATRIX_A for x=0,1 */ + static const cl_uint mag01[2]={0x0UL, MATRIX_A}; +#ifdef __SSE2__ + static volatile int init = 0; + static union{ __m128i v; cl_uint s[4]; } upper_mask, lower_mask, one, matrix_a, c0, c1; +#endif + + + cl_uint *mt = d->mt; + cl_uint y; + + if (d->mti == N) + { /* generate N words at one time */ + int kk; + +#ifdef __SSE2__ + if( 0 == init ) + { + upper_mask.s[0] = upper_mask.s[1] = upper_mask.s[2] = upper_mask.s[3] = UPPER_MASK; + lower_mask.s[0] = lower_mask.s[1] = lower_mask.s[2] = lower_mask.s[3] = LOWER_MASK; + one.s[0] = one.s[1] = one.s[2] = one.s[3] = 1; + matrix_a.s[0] = matrix_a.s[1] = matrix_a.s[2] = matrix_a.s[3] = MATRIX_A; + c0.s[0] = c0.s[1] = c0.s[2] = c0.s[3] = (cl_uint) 0x9d2c5680UL; + c1.s[0] = c1.s[1] = c1.s[2] = c1.s[3] = (cl_uint) 0xefc60000UL; + init = 1; + } +#endif + + kk = 0; +#ifdef __SSE2__ + // vector loop + for( ; kk + 4 <= N-M; kk += 4 ) + { + __m128i vy = _mm_or_si128( _mm_and_si128( _mm_load_si128( (__m128i*)(mt + kk) ), upper_mask.v ), + _mm_and_si128( _mm_loadu_si128( (__m128i*)(mt + kk + 1) ), lower_mask.v )); // ((mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK)) + + __m128i mask = _mm_cmpeq_epi32( _mm_and_si128( vy, one.v), one.v ); // y & 1 ? -1 : 0 + __m128i vmag01 = _mm_and_si128( mask, matrix_a.v ); // y & 1 ? MATRIX_A, 0 = mag01[y & (cl_uint) 0x1UL] + __m128i vr = _mm_xor_si128( _mm_loadu_si128( (__m128i*)(mt + kk + M)), (__m128i) _mm_srli_epi32( vy, 1 ) ); // mt[kk+M] ^ (y >> 1) + vr = _mm_xor_si128( vr, vmag01 ); // mt[kk+M] ^ (y >> 1) ^ mag01[y & (cl_uint) 0x1UL] + _mm_store_si128( (__m128i*) (mt + kk ), vr ); + } +#endif + for ( ;kk> 1) ^ mag01[y & (cl_uint) 0x1UL]; + } + +#ifdef __SSE2__ + // advance to next aligned location + for (;kk> 1) ^ mag01[y & (cl_uint) 0x1UL]; + } + + // vector loop + for( ; kk + 4 <= N-1; kk += 4 ) + { + __m128i vy = _mm_or_si128( _mm_and_si128( _mm_load_si128( (__m128i*)(mt + kk) ), upper_mask.v ), + _mm_and_si128( _mm_loadu_si128( (__m128i*)(mt + kk + 1) ), lower_mask.v )); // ((mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK)) + + __m128i mask = _mm_cmpeq_epi32( _mm_and_si128( vy, one.v), one.v ); // y & 1 ? -1 : 0 + __m128i vmag01 = _mm_and_si128( mask, matrix_a.v ); // y & 1 ? MATRIX_A, 0 = mag01[y & (cl_uint) 0x1UL] + __m128i vr = _mm_xor_si128( _mm_loadu_si128( (__m128i*)(mt + kk + M - N)), _mm_srli_epi32( vy, 1 ) ); // mt[kk+M-N] ^ (y >> 1) + vr = _mm_xor_si128( vr, vmag01 ); // mt[kk+M] ^ (y >> 1) ^ mag01[y & (cl_uint) 0x1UL] + _mm_store_si128( (__m128i*) (mt + kk ), vr ); + } +#endif + + for (;kk> 1) ^ mag01[y & (cl_uint) 0x1UL]; + } + y = (cl_uint)((mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK)); + mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & (cl_uint) 0x1UL]; + +#ifdef __SSE2__ + // Do the tempering ahead of time in vector code + for( kk = 0; kk + 4 <= N; kk += 4 ) + { + __m128i vy = _mm_load_si128( (__m128i*)(mt + kk ) ); // y = mt[k]; + vy = _mm_xor_si128( vy, _mm_srli_epi32( vy, 11 ) ); // y ^= (y >> 11); + vy = _mm_xor_si128( vy, _mm_and_si128( _mm_slli_epi32( vy, 7 ), c0.v) ); // y ^= (y << 7) & (cl_uint) 0x9d2c5680UL; + vy = _mm_xor_si128( vy, _mm_and_si128( _mm_slli_epi32( vy, 15 ), c1.v) ); // y ^= (y << 15) & (cl_uint) 0xefc60000UL; + vy = _mm_xor_si128( vy, _mm_srli_epi32( vy, 18 ) ); // y ^= (y >> 18); + _mm_store_si128( (__m128i*)(d->cache+kk), vy ); + } +#endif + + d->mti = 0; + } +#ifdef __SSE2__ + y = d->cache[d->mti++]; +#else + y = mt[d->mti++]; + + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & (cl_uint) 0x9d2c5680UL; + y ^= (y << 15) & (cl_uint) 0xefc60000UL; + y ^= (y >> 18); +#endif + + + return y; +} + +cl_ulong genrand_int64( MTdata d) +{ + return ((cl_ulong) genrand_int32(d) << 32) | (cl_uint) genrand_int32(d); +} + +/* generates a random number on [0,1]-real-interval */ +double genrand_real1(MTdata d) +{ + return genrand_int32(d)*(1.0/4294967295.0); + /* divided by 2^32-1 */ +} + +/* generates a random number on [0,1)-real-interval */ +double genrand_real2(MTdata d) +{ + return genrand_int32(d)*(1.0/4294967296.0); + /* divided by 2^32 */ +} + +/* generates a random number on (0,1)-real-interval */ +double genrand_real3(MTdata d) +{ + return (((double)genrand_int32(d)) + 0.5)*(1.0/4294967296.0); + /* divided by 2^32 */ +} + +/* generates a random number on [0,1) with 53-bit resolution*/ +double genrand_res53(MTdata d) +{ + unsigned long a=genrand_int32(d)>>5, b=genrand_int32(d)>>6; + return(a*67108864.0+b)*(1.0/9007199254740992.0); +} diff --git a/test_common/harness/mt19937.h b/test_common/harness/mt19937.h new file mode 100644 index 00000000..d05beed1 --- /dev/null +++ b/test_common/harness/mt19937.h @@ -0,0 +1,99 @@ + +/* + * mt19937.h + * + * Mersenne Twister. + * + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) + */ + +#ifndef MT19937_H +#define MT19937_H 1 + +#if defined( __APPLE__ ) + #include +#else + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* + * Interfaces here have been modified from original sources so that they + * are safe to call reentrantly, so long as a different MTdata is used + * on each thread. + */ + +typedef struct _MTdata *MTdata; + +/* Create the random number generator with seed */ +MTdata init_genrand( cl_uint /*seed*/ ); + +/* release memory used by a MTdata private data */ +void free_mtdata( MTdata /*data*/ ); + +/* generates a random number on [0,0xffffffff]-interval */ +cl_uint genrand_int32( MTdata /*data*/); + +/* generates a random number on [0,0xffffffffffffffffULL]-interval */ +cl_ulong genrand_int64( MTdata /*data*/); + +/* generates a random number on [0,1]-real-interval */ +double genrand_real1( MTdata /*data*/); + +/* generates a random number on [0,1)-real-interval */ +double genrand_real2( MTdata /*data*/); + +/* generates a random number on (0,1)-real-interval */ +double genrand_real3( MTdata /*data*/); + +/* generates a random number on [0,1) with 53-bit resolution*/ +double genrand_res53( MTdata /*data*/ ); + + +#ifdef __cplusplus + } +#endif + +#endif /* MT19937_H */ diff --git a/test_common/harness/os_helpers.cpp b/test_common/harness/os_helpers.cpp new file mode 100644 index 00000000..ecc55a22 --- /dev/null +++ b/test_common/harness/os_helpers.cpp @@ -0,0 +1,564 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "os_helpers.h" +#include "errorHelpers.h" + +// ================================================================================================= +// C++ interface. +// ================================================================================================= + +#include // errno, error constants +#include // PATH_MAX +#include // abort, _splitpath, _makepath +#include // strdup, strerror_r +#include + +#include + +#define CHECK_PTR( ptr ) \ + if ( (ptr) == NULL ) { \ + abort(); \ + } + +typedef std::vector< char > buffer_t; + +#if ! defined( PATH_MAX ) + #define PATH_MAX 1000 +#endif + +int const _size = PATH_MAX + 1; // Initial buffer size for path. +int const _count = 8; // How many times we will try to double buffer size. + +// ------------------------------------------------------------------------------------------------- +// MacOS X +// ------------------------------------------------------------------------------------------------- + +#if defined( __APPLE__ ) + + + #include // _NSGetExecutablePath + #include // dirname + + + static + std::string + _err_msg( + int err, // Error number (e. g. errno). + int level // Nesting level, for avoiding infinite recursion. + ) { + + /* + There are 3 incompatible versions of strerror_r: + + char * strerror_r( int, char *, size_t ); // GNU version + int strerror_r( int, char *, size_t ); // BSD version + int strerror_r( int, char *, size_t ); // XSI version + + BSD version returns error code, while XSI version returns 0 or -1 and sets errno. + + */ + + // BSD version of strerror_r. + buffer_t buffer( 100 ); + int count = _count; + for ( ; ; ) { + int rc = strerror_r( err, & buffer.front(), buffer.size() ); + if ( rc == EINVAL ) { + // Error code is not recognized, but anyway we got the message. + return & buffer.front(); + } else if ( rc == ERANGE ) { + // Buffer is not enough. + if ( count > 0 ) { + // Enlarge the buffer. + -- count; + buffer.resize( buffer.size() * 2 ); + } else { + std::stringstream ostr; + ostr + << "Error " << err << " " + << "(Getting error message failed: " + << "Buffer of " << buffer.size() << " bytes is still too small" + << ")"; + return ostr.str(); + }; // if + } else if ( rc == 0 ) { + // We got the message. + return & buffer.front(); + } else { + std::stringstream ostr; + ostr + << "Error " << err << " " + << "(Getting error message failed: " + << ( level < 2 ? _err_msg( rc, level + 1 ) : "Oops" ) + << ")"; + return ostr.str(); + }; // if + }; // forever + + } // _err_msg + + + std::string + dir_sep( + ) { + return "/"; + } // dir_sep + + + std::string + exe_path( + ) { + buffer_t path( _size ); + int count = _count; + for ( ; ; ) { + uint32_t size = path.size(); + int rc = _NSGetExecutablePath( & path.front(), & size ); + if ( rc == 0 ) { + break; + }; // if + if ( count > 0 ) { + -- count; + path.resize( size ); + } else { + log_error( + "ERROR: Getting executable path failed: " + "_NSGetExecutablePath failed: Buffer of %lu bytes is still too small\n", + (unsigned long) path.size() + ); + exit( 2 ); + }; // if + }; // forever + return & path.front(); + } // exe_path + + + std::string + exe_dir( + ) { + std::string path = exe_path(); + // We cannot pass path.c_str() to `dirname' bacause `dirname' modifies its argument. + buffer_t buffer( path.c_str(), path.c_str() + path.size() + 1 ); // Copy with trailing zero. + return dirname( & buffer.front() ); + } // exe_dir + + +#endif // __APPLE__ + +// ------------------------------------------------------------------------------------------------- +// Linux +// ------------------------------------------------------------------------------------------------- + +#if defined( __linux__ ) + + + #include // errno + #include // dirname + #include // readlink + + + static + std::string + _err_msg( + int err, + int level + ) { + + /* + There are 3 incompatible versions of strerror_r: + + char * strerror_r( int, char *, size_t ); // GNU version + int strerror_r( int, char *, size_t ); // BSD version + int strerror_r( int, char *, size_t ); // XSI version + + BSD version returns error code, while XSI version returns 0 or -1 and sets errno. + + */ + + #if defined(__ANDROID__) || ( ( _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 ) && ! _GNU_SOURCE ) + + // XSI version of strerror_r. + #warning Not tested! + buffer_t buffer( 200 ); + int count = _count; + for ( ; ; ) { + int rc = strerror_r( err, & buffer.front(), buffer.size() ); + if ( rc == -1 ) { + int _err = errno; + if ( _err == ERANGE ) { + if ( count > 0 ) { + // Enlarge the buffer. + -- count; + buffer.resize( buffer.size() * 2 ); + } else { + std::stringstream ostr; + ostr + << "Error " << err << " " + << "(Getting error message failed: " + << "Buffer of " << buffer.size() << " bytes is still too small" + << ")"; + return ostr.str(); + }; // if + } else { + std::stringstream ostr; + ostr + << "Error " << err << " " + << "(Getting error message failed: " + << ( level < 2 ? _err_msg( _err, level + 1 ) : "Oops" ) + << ")"; + return ostr.str(); + }; // if + } else { + // We got the message. + return & buffer.front(); + }; // if + }; // forever + + #else + + // GNU version of strerror_r. + char buffer[ 2000 ]; + return strerror_r( err, buffer, sizeof( buffer ) ); + + #endif + + } // _err_msg + + + std::string + dir_sep( + ) { + return "/"; + } // dir_sep + + + std::string + exe_path( + ) { + + static std::string const exe = "/proc/self/exe"; + + buffer_t path( _size ); + int count = _count; // Max number of iterations. + + for ( ; ; ) { + + ssize_t len = readlink( exe.c_str(), & path.front(), path.size() ); + + if ( len < 0 ) { + // Oops. + int err = errno; + log_error( + "ERROR: Getting executable path failed: " + "Reading symlink `%s' failed: %s\n", + exe.c_str(), err_msg( err ).c_str() + ); + exit( 2 ); + }; // if + + if ( len < path.size() ) { + // We got the path. + path.resize( len ); + break; + }; // if + + // Oops, buffer is too small. + if ( count > 0 ) { + -- count; + // Enlarge the buffer. + path.resize( path.size() * 2 ); + } else { + log_error( + "ERROR: Getting executable path failed: " + "Reading symlink `%s' failed: Buffer of %lu bytes is still too small\n", + exe.c_str(), + (unsigned long) path.size() + ); + exit( 2 ); + }; // if + + }; // forever + + return std::string( & path.front(), path.size() ); + + } // exe_path + + + std::string + exe_dir( + ) { + std::string path = exe_path(); + // We cannot pass path.c_str() to `dirname' bacause `dirname' modifies its argument. + buffer_t buffer( path.c_str(), path.c_str() + path.size() + 1 ); // Copy with trailing zero. + return dirname( & buffer.front() ); + } // exe_dir + +#endif // __linux__ + +// ------------------------------------------------------------------------------------------------- +// MS Windows +// ------------------------------------------------------------------------------------------------- + +#if defined( _WIN32 ) + + + #include + #if defined( max ) + #undef max + #endif + + #include + #include + + + static + std::string + _err_msg( + int err, + int level + ) { + + std::string msg; + + LPSTR buffer = NULL; + DWORD flags = + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS; + + DWORD len = + FormatMessageA( + flags, + NULL, + err, + LANG_USER_DEFAULT, + reinterpret_cast< LPSTR >( & buffer ), + 0, + NULL + ); + + if ( buffer == NULL || len == 0 ) { + + int _err = GetLastError(); + char str[1024] = { 0 }; + snprintf(str, sizeof(str), "Error 0x%08x (Getting error message failed: %s )", err, ( level < 2 ? _err_msg( _err, level + 1 ).c_str() : "Oops" )); + msg = std::string(str); + + } else { + + // Trim trailing whitespace (including `\r' and `\n'). + while ( len > 0 && isspace( buffer[ len - 1 ] ) ) { + -- len; + }; // while + + // Drop trailing full stop. + if ( len > 0 && buffer[ len - 1 ] == '.' ) { + -- len; + }; // if + + msg.assign( buffer, len ); + + }; //if + + if ( buffer != NULL ) { + LocalFree( buffer ); + }; // if + + return msg; + + } // _get_err_msg + + + std::string + dir_sep( + ) { + return "\\"; + } // dir_sep + + + std::string + exe_path( + ) { + + buffer_t path( _size ); + int count = _count; + + for ( ; ; ) { + + DWORD len = GetModuleFileNameA( NULL, & path.front(), path.size() ); + + if ( len == 0 ) { + int err = GetLastError(); + log_error( "ERROR: Getting executable path failed: %s\n", err_msg( err ).c_str() ); + exit( 2 ); + }; // if + + if ( len < path.size() ) { + path.resize( len ); + break; + }; // if + + // Buffer too small. + if ( count > 0 ) { + -- count; + path.resize( path.size() * 2 ); + } else { + log_error( + "ERROR: Getting executable path failed: " + "Buffer of %lu bytes is still too small\n", + (unsigned long) path.size() + ); + exit( 2 ); + }; // if + + }; // forever + + return std::string( & path.front(), path.size() ); + + } // exe_path + + + std::string + exe_dir( + ) { + + std::string exe = exe_path(); + int count = 0; + + // Splitting path into components. + buffer_t drv( _MAX_DRIVE ); + buffer_t dir( _MAX_DIR ); + count = _count; +#if defined(_MSC_VER) + for ( ; ; ) { + int rc = + _splitpath_s( + exe.c_str(), + & drv.front(), drv.size(), + & dir.front(), dir.size(), + NULL, 0, // We need neither name + NULL, 0 // nor extension + ); + if ( rc == 0 ) { + break; + } else if ( rc == ERANGE ) { + if ( count > 0 ) { + -- count; + // Buffer is too small, but it is not clear which one. + // So we have to enlarge all. + drv.resize( drv.size() * 2 ); + dir.resize( dir.size() * 2 ); + } else { + log_error( + "ERROR: Getting executable path failed: " + "Splitting path `%s' to components failed: " + "Buffers of %lu and %lu bytes are still too small\n", + exe.c_str(), + (unsigned long) drv.size(), + (unsigned long) dir.size() + ); + exit( 2 ); + }; // if + } else { + log_error( + "ERROR: Getting executable path failed: " + "Splitting path `%s' to components failed: %s\n", + exe.c_str(), + err_msg( rc ).c_str() + ); + exit( 2 ); + }; // if + }; // forever + +#else // __MINGW32__ + + // MinGW does not have the "secure" _splitpath_s, use the insecure version instead. + _splitpath( + exe.c_str(), + & drv.front(), + & dir.front(), + NULL, // We need neither name + NULL // nor extension + ); +#endif // __MINGW32__ + + // Combining components back to path. + // I failed with "secure" `_makepath_s'. If buffer is too small, instead of returning + // ERANGE, `_makepath_s' pops up dialog box and offers to debug the program. D'oh! + // So let us try to guess the size of result and go with insecure `_makepath'. + buffer_t path( std::max( drv.size() + dir.size(), size_t( _MAX_PATH ) ) + 10 ); + _makepath( & path.front(), & drv.front(), & dir.front(), NULL, NULL ); + + return & path.front(); + + } // exe_dir + + +#endif // _WIN32 + + +std::string +err_msg( + int err +) { + + return _err_msg( err, 0 ); + +} // err_msg + + +// ================================================================================================= +// C interface. +// ================================================================================================= + + +char * +get_err_msg( + int err +) { + char * msg = strdup( err_msg( err ).c_str() ); + CHECK_PTR( msg ); + return msg; +} // get_err_msg + + +char * +get_dir_sep( +) { + char * sep = strdup( dir_sep().c_str() ); + CHECK_PTR( sep ); + return sep; +} // get_dir_sep + + +char * +get_exe_path( +) { + char * path = strdup( exe_path().c_str() ); + CHECK_PTR( path ); + return path; +} // get_exe_path + + +char * +get_exe_dir( +) { + char * dir = strdup( exe_dir().c_str() ); + CHECK_PTR( dir ); + return dir; +} // get_exe_dir + + +// end of file // diff --git a/test_common/harness/os_helpers.h b/test_common/harness/os_helpers.h new file mode 100644 index 00000000..21625841 --- /dev/null +++ b/test_common/harness/os_helpers.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef __os_helpers_h__ +#define __os_helpers_h__ + +#include "compat.h" + +// ------------------------------------------------------------------------------------------------- +// C++ interface. +// ------------------------------------------------------------------------------------------------- + +#ifdef __cplusplus + + #include + + std::string err_msg( int err ); + std::string dir_sep(); + std::string exe_path(); + std::string exe_dir(); + +#endif // __cplusplus + +// ------------------------------------------------------------------------------------------------- +// C interface. +// ------------------------------------------------------------------------------------------------- + +#ifdef __cplusplus + extern "C" { +#endif // __cplusplus + +char * get_err_msg( int err ); // Returns system error message. Subject to free. +char * get_dir_sep(); // Returns dir separator. Subject to free. +char * get_exe_path(); // Returns path of current executable. Subject to free. +char * get_exe_dir(); // Returns dir of current executable. Subject to free. + +#ifdef __cplusplus + } // extern "C" +#endif // __cplusplus + +#endif // __os_helpers_h__ diff --git a/test_common/harness/parseParameters.cpp b/test_common/harness/parseParameters.cpp new file mode 100644 index 00000000..9c227a14 --- /dev/null +++ b/test_common/harness/parseParameters.cpp @@ -0,0 +1,129 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "parseParameters.h" + +#include "errorHelpers.h" +#include "testHarness.h" +#include "ThreadPool.h" + +#include +#include +#include +#include +#include + +using namespace std; + +bool gOfflineCompiler = false; +bool gForceSpirVCache = false; +bool gForceSpirVGenerate = false; +std::string gSpirVPath = "."; +OfflineCompilerOutputType gOfflineCompilerOutputType; + +void helpInfo () +{ + log_info(" '-offlineCompiler ': use offline compiler\n"); + log_info(" ' output_type binary - \"../build_script_binary.py\" is invoked\n"); + log_info(" ' output_type source - \"../build_script_source.py\" is invoked\n"); + log_info(" ' output_type spir_v - \"../cl_build_script_spir_v.py\" is invoked, optional modes: generate, cache\n"); + log_info(" ' mode generate - force binary generation\n"); + log_info(" ' mode cache - force reading binary files from cache\n"); + log_info("\n"); +} + +int parseCustomParam (int argc, const char *argv[], const char *ignore) +{ + int delArg = 0; + + for (int i=1; i \n"); + return -1; + } + } + + //cleaning parameters from argv tab + for (int j=i; j + +extern bool gOfflineCompiler; +extern bool gForceSpirVCache; +extern bool gForceSpirVGenerate; +extern std::string gSpirVPath; + +enum OfflineCompilerOutputType +{ + kBinary = 0, + kSource, + kSpir_v +}; + +extern OfflineCompilerOutputType gOfflineCompilerOutputType; + +extern int parseCustomParam (int argc, const char *argv[], const char *ignore = 0 ); + +#endif // _parseParameters_h diff --git a/test_common/harness/ref_counting.h b/test_common/harness/ref_counting.h new file mode 100644 index 00000000..1a2aceee --- /dev/null +++ b/test_common/harness/ref_counting.h @@ -0,0 +1,49 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _ref_counting_h +#define _ref_counting_h + +#define MARK_REF_COUNT_BASE( c, type, bigType ) \ + cl_uint c##_refCount; \ + error = clGet##type##Info( c, CL_##bigType##_REFERENCE_COUNT, sizeof( c##_refCount ), &c##_refCount, NULL ); \ + test_error( error, "Unable to check reference count for " #type ); + +#define TEST_REF_COUNT_BASE( c, type, bigType ) \ + cl_uint c##_refCount_new; \ + error = clGet##type##Info( c, CL_##bigType##_REFERENCE_COUNT, sizeof( c##_refCount_new ), &c##_refCount_new, NULL ); \ + test_error( error, "Unable to check reference count for " #type ); \ + if( c##_refCount != c##_refCount_new ) \ + { \ + log_error( "ERROR: Reference count for " #type " changed! (was %d, now %d)\n", c##_refCount, c##_refCount_new ); \ + return -1; \ + } + +#define MARK_REF_COUNT_CONTEXT( c ) MARK_REF_COUNT_BASE( c, Context, CONTEXT ) +#define TEST_REF_COUNT_CONTEXT( c ) TEST_REF_COUNT_BASE( c, Context, CONTEXT ) + +#define MARK_REF_COUNT_DEVICE( c ) MARK_REF_COUNT_BASE( c, Device, DEVICE ) +#define TEST_REF_COUNT_DEVICE( c ) TEST_REF_COUNT_BASE( c, Device, DEVICE ) + +#define MARK_REF_COUNT_QUEUE( c ) MARK_REF_COUNT_BASE( c, CommandQueue, QUEUE ) +#define TEST_REF_COUNT_QUEUE( c ) TEST_REF_COUNT_BASE( c, CommandQueue, QUEUE ) + +#define MARK_REF_COUNT_PROGRAM( c ) MARK_REF_COUNT_BASE( c, Program, PROGRAM ) +#define TEST_REF_COUNT_PROGRAM( c ) TEST_REF_COUNT_BASE( c, Program, PROGRAM ) + +#define MARK_REF_COUNT_MEM( c ) MARK_REF_COUNT_BASE( c, MemObject, MEM ) +#define TEST_REF_COUNT_MEM( c ) TEST_REF_COUNT_BASE( c, MemObject, MEM ) + +#endif // _ref_counting_h diff --git a/test_common/harness/rounding_mode.c b/test_common/harness/rounding_mode.c new file mode 100644 index 00000000..ff38a7e4 --- /dev/null +++ b/test_common/harness/rounding_mode.c @@ -0,0 +1,241 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "rounding_mode.h" + +#if (defined( __arm__ ) || defined(__aarch64__)) + #define FPSCR_FZ (1 << 24) // Flush-To-Zero mode + #define FPSCR_ROUND_MASK (3 << 22) // Rounding mode: + + #define _ARM_FE_FTZ 0x1000000 + #define _ARM_FE_NFTZ 0x0 + #if defined(__aarch64__) + #define _FPU_GETCW(cw) __asm__ ("MRS %0,FPCR" : "=r" (cw)) + #define _FPU_SETCW(cw) __asm__ ("MSR FPCR,%0" : :"ri" (cw)) + #else + #define _FPU_GETCW(cw) __asm__ ("VMRS %0,FPSCR" : "=r" (cw)) + #define _FPU_SETCW(cw) __asm__ ("VMSR FPSCR,%0" : :"ri" (cw)) + #endif +#endif + +#if (defined( __arm__ ) || defined(__aarch64__)) && defined( __GNUC__ ) +#define _ARM_FE_TONEAREST 0x0 +#define _ARM_FE_UPWARD 0x400000 +#define _ARM_FE_DOWNWARD 0x800000 +#define _ARM_FE_TOWARDZERO 0xc00000 +RoundingMode set_round( RoundingMode r, Type outType ) +{ + static const int flt_rounds[ kRoundingModeCount ] = { _ARM_FE_TONEAREST, + _ARM_FE_TONEAREST, _ARM_FE_UPWARD, _ARM_FE_DOWNWARD, _ARM_FE_TOWARDZERO }; + static const int int_rounds[ kRoundingModeCount ] = { _ARM_FE_TOWARDZERO, + _ARM_FE_TONEAREST, _ARM_FE_UPWARD, _ARM_FE_DOWNWARD, _ARM_FE_TOWARDZERO }; + const int *p = int_rounds; + if( outType == kfloat || outType == kdouble ) + p = flt_rounds; + + int fpscr = 0; + RoundingMode oldRound = get_round(); + + _FPU_GETCW(fpscr); + _FPU_SETCW( p[r] | (fpscr & ~FPSCR_ROUND_MASK)); + + return oldRound; +} + +RoundingMode get_round( void ) +{ + int fpscr; + int oldRound; + + _FPU_GETCW(fpscr); + oldRound = (fpscr & FPSCR_ROUND_MASK); + + switch( oldRound ) + { + case _ARM_FE_TONEAREST: + return kRoundToNearestEven; + case _ARM_FE_UPWARD: + return kRoundUp; + case _ARM_FE_DOWNWARD: + return kRoundDown; + case _ARM_FE_TOWARDZERO: + return kRoundTowardZero; + } + + return kDefaultRoundingMode; +} + +#elif !(defined(_WIN32) && defined(_MSC_VER)) +RoundingMode set_round( RoundingMode r, Type outType ) +{ + static const int flt_rounds[ kRoundingModeCount ] = { FE_TONEAREST, FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO }; + static const int int_rounds[ kRoundingModeCount ] = { FE_TOWARDZERO, FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO }; + const int *p = int_rounds; + if( outType == kfloat || outType == kdouble ) + p = flt_rounds; + int oldRound = fegetround(); + fesetround( p[r] ); + + switch( oldRound ) + { + case FE_TONEAREST: + return kRoundToNearestEven; + case FE_UPWARD: + return kRoundUp; + case FE_DOWNWARD: + return kRoundDown; + case FE_TOWARDZERO: + return kRoundTowardZero; + default: + abort(); // ??! + } + return kDefaultRoundingMode; //never happens +} + +RoundingMode get_round( void ) +{ + int oldRound = fegetround(); + + switch( oldRound ) + { + case FE_TONEAREST: + return kRoundToNearestEven; + case FE_UPWARD: + return kRoundUp; + case FE_DOWNWARD: + return kRoundDown; + case FE_TOWARDZERO: + return kRoundTowardZero; + } + + return kDefaultRoundingMode; +} + +#else +RoundingMode set_round( RoundingMode r, Type outType ) +{ + static const int flt_rounds[ kRoundingModeCount ] = { _RC_NEAR, _RC_NEAR, _RC_UP, _RC_DOWN, _RC_CHOP }; + static const int int_rounds[ kRoundingModeCount ] = { _RC_CHOP, _RC_NEAR, _RC_UP, _RC_DOWN, _RC_CHOP }; + const int *p = ( outType == kfloat || outType == kdouble )? flt_rounds : int_rounds; + unsigned int oldRound; + + int err = _controlfp_s(&oldRound, 0, 0); //get rounding mode into oldRound + if (err) { + vlog_error("\t\tERROR: -- cannot get rounding mode in %s:%d\n", __FILE__, __LINE__); + return kDefaultRoundingMode; //what else never happens + } + + oldRound &= _MCW_RC; + + RoundingMode old = + (oldRound == _RC_NEAR)? kRoundToNearestEven : + (oldRound == _RC_UP)? kRoundUp : + (oldRound == _RC_DOWN)? kRoundDown : + (oldRound == _RC_CHOP)? kRoundTowardZero: + kDefaultRoundingMode; + + _controlfp_s(&oldRound, p[r], _MCW_RC); //setting new rounding mode + return old; //returning old rounding mode +} + +RoundingMode get_round( void ) +{ + unsigned int oldRound; + + int err = _controlfp_s(&oldRound, 0, 0); //get rounding mode into oldRound + oldRound &= _MCW_RC; + return + (oldRound == _RC_NEAR)? kRoundToNearestEven : + (oldRound == _RC_UP)? kRoundUp : + (oldRound == _RC_DOWN)? kRoundDown : + (oldRound == _RC_CHOP)? kRoundTowardZero: + kDefaultRoundingMode; +} + +#endif + +// +// FlushToZero() sets the host processor into ftz mode. It is intended to have a remote effect on the behavior of the code in +// basic_test_conversions.c. Some host processors may not support this mode, which case you'll need to do some clamping in +// software by testing against FLT_MIN or DBL_MIN in that file. +// +// Note: IEEE-754 says conversions are basic operations. As such they do *NOT* have the behavior in section 7.5.3 of +// the OpenCL spec. They *ALWAYS* flush to zero for subnormal inputs or outputs when FTZ mode is on like other basic +// operators do (e.g. add, subtract, multiply, divide, etc.) +// +// Configuring hardware to FTZ mode varies by platform. +// CAUTION: Some C implementations may also fail to behave properly in this mode. +// +// On PowerPC, it is done by setting the FPSCR into non-IEEE mode. +// On Intel, you can do this by turning on the FZ and DAZ bits in the MXCSR -- provided that SSE/SSE2 +// is used for floating point computation! If your OS uses x87, you'll need to figure out how +// to turn that off for the conversions code in basic_test_conversions.c so that they flush to +// zero properly. Otherwise, you'll need to add appropriate software clamping to basic_test_conversions.c +// in which case, these function are at liberty to do nothing. +// +#if defined( __i386__ ) || defined( __x86_64__ ) || defined (_WIN32) + #include +#elif defined( __PPC__ ) + #include +#endif +void *FlushToZero( void ) +{ +#if defined( __APPLE__ ) || defined(__linux__) || defined (_WIN32) + #if defined( __i386__ ) || defined( __x86_64__ ) || defined(_MSC_VER) + union{ int i; void *p; }u = { _mm_getcsr() }; + _mm_setcsr( u.i | 0x8040 ); + return u.p; + #elif defined( __arm__ ) || defined(__aarch64__) + int fpscr; + _FPU_GETCW(fpscr); + _FPU_SETCW(fpscr | FPSCR_FZ); + return NULL; + #elif defined( __PPC__ ) + fpu_control_t flags = 0; + _FPU_GETCW(flags); + flags |= _FPU_MASK_NI; + _FPU_SETCW(flags); + return NULL; + #else + #error Unknown arch + #endif +#else + #error Please configure FlushToZero and UnFlushToZero to behave properly on this operating system. +#endif +} + +// Undo the effects of FlushToZero above, restoring the host to default behavior, using the information passed in p. +void UnFlushToZero( void *p) +{ +#if defined( __APPLE__ ) || defined(__linux__) || defined (_WIN32) + #if defined( __i386__ ) || defined( __x86_64__ ) || defined(_MSC_VER) + union{ void *p; int i; }u = { p }; + _mm_setcsr( u.i ); + #elif defined( __arm__ ) || defined(__aarch64__) + int fpscr; + _FPU_GETCW(fpscr); + _FPU_SETCW(fpscr & ~FPSCR_FZ); + #elif defined( __PPC__) + fpu_control_t flags = 0; + _FPU_GETCW(flags); + flags &= ~_FPU_MASK_NI; + _FPU_SETCW(flags); + #else + #error Unknown arch + #endif +#else + #error Please configure FlushToZero and UnFlushToZero to behave properly on this operating system. +#endif +} diff --git a/test_common/harness/rounding_mode.h b/test_common/harness/rounding_mode.h new file mode 100644 index 00000000..b7eb9758 --- /dev/null +++ b/test_common/harness/rounding_mode.h @@ -0,0 +1,69 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef __ROUNDING_MODE_H__ +#define __ROUNDING_MODE_H__ + +#include "compat.h" + +#if (defined(_WIN32) && defined (_MSC_VER)) +#include "errorHelpers.h" +#include "testHarness.h" +#endif + +typedef enum +{ + kDefaultRoundingMode = 0, + kRoundToNearestEven, + kRoundUp, + kRoundDown, + kRoundTowardZero, + + kRoundingModeCount +}RoundingMode; + +typedef enum +{ + kuchar = 0, + kchar = 1, + kushort = 2, + kshort = 3, + kuint = 4, + kint = 5, + kfloat = 6, + kdouble = 7, + kulong = 8, + klong = 9, + + //This goes last + kTypeCount +}Type; + +#ifdef __cplusplus +extern "C" { +#endif + +extern RoundingMode set_round( RoundingMode r, Type outType ); +extern RoundingMode get_round( void ); +extern void *FlushToZero( void ); +extern void UnFlushToZero( void *p); + +#ifdef __cplusplus +} +#endif + + + +#endif /* __ROUNDING_MODE_H__ */ diff --git a/test_common/harness/testHarness.c b/test_common/harness/testHarness.c new file mode 100644 index 00000000..f513f787 --- /dev/null +++ b/test_common/harness/testHarness.c @@ -0,0 +1,849 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testHarness.h" +#include "compat.h" +#include +#include +#include "threadTesting.h" +#include "errorHelpers.h" +#include "kernelHelpers.h" +#include "fpcontrol.h" +#include "typeWrappers.h" +#include "parseParameters.h" + +#if !defined(_WIN32) +#include +#endif + +#include + +#if !defined (__APPLE__) +#include +#endif + +int gTestsPassed = 0; +int gTestsFailed = 0; +cl_uint gRandomSeed = 0; +cl_uint gReSeed = 0; + +int gFlushDenormsToZero = 0; +int gInfNanSupport = 1; +int gIsEmbedded = 0; +int gIsOpenCL_C_1_0_Device = 0; +int gIsOpenCL_1_0_Device = 0; +int gHasLong = 1; + +#define DEFAULT_NUM_ELEMENTS 0x4000 + +int runTestHarness( int argc, const char *argv[], unsigned int num_fns, + basefn fnList[], const char *fnNames[], + int imageSupportRequired, int forceNoContextCreation, cl_command_queue_properties queueProps ) +{ + return runTestHarnessWithCheck( argc, argv, num_fns, fnList, fnNames, imageSupportRequired, forceNoContextCreation, queueProps, + ( imageSupportRequired ) ? verifyImageSupport : NULL ); +} + +int runTestHarnessWithCheck( int argc, const char *argv[], unsigned int num_fns, + basefn fnList[], const char *fnNames[], + int imageSupportRequired, int forceNoContextCreation, cl_command_queue_properties queueProps, + DeviceCheckFn deviceCheckFn ) +{ + test_start(); + + cl_device_type device_type = CL_DEVICE_TYPE_DEFAULT; + cl_uint num_platforms = 0; + cl_platform_id *platforms; + cl_device_id device; + int num_elements = DEFAULT_NUM_ELEMENTS; + cl_uint num_devices = 0; + cl_device_id *devices = NULL; + cl_uint choosen_device_index = 0; + cl_uint choosen_platform_index = 0; + + int err, ret; + char *endPtr; + unsigned int i; + int based_on_env_var = 0; + + + /* Check for environment variable to set device type */ + char *env_mode = getenv( "CL_DEVICE_TYPE" ); + if( env_mode != NULL ) + { + based_on_env_var = 1; + if( strcmp( env_mode, "gpu" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_GPU" ) == 0 ) + device_type = CL_DEVICE_TYPE_GPU; + else if( strcmp( env_mode, "cpu" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_CPU" ) == 0 ) + device_type = CL_DEVICE_TYPE_CPU; + else if( strcmp( env_mode, "accelerator" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + device_type = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( env_mode, "default" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + device_type = CL_DEVICE_TYPE_DEFAULT; + else + { + log_error( "Unknown CL_DEVICE_TYPE env variable setting: %s.\nAborting...\n", env_mode ); + abort(); + } + } + +#if defined( __APPLE__ ) + { + // report on any unusual library search path indirection + char *libSearchPath = getenv( "DYLD_LIBRARY_PATH"); + if( libSearchPath ) + log_info( "*** DYLD_LIBRARY_PATH = \"%s\"\n", libSearchPath ); + + // report on any unusual framework search path indirection + char *frameworkSearchPath = getenv( "DYLD_FRAMEWORK_PATH"); + if( libSearchPath ) + log_info( "*** DYLD_FRAMEWORK_PATH = \"%s\"\n", frameworkSearchPath ); + } +#endif + + env_mode = getenv( "CL_DEVICE_INDEX" ); + if( env_mode != NULL ) + { + choosen_device_index = atoi(env_mode); + } + + env_mode = getenv( "CL_PLATFORM_INDEX" ); + if( env_mode != NULL ) + { + choosen_platform_index = atoi(env_mode); + } + + /* Process the command line arguments */ + + argc = parseCustomParam(argc, argv); + if (argc == -1) + { + test_finish(); + return 0; + } + + /* Special case: just list the tests */ + if( ( argc > 1 ) && (!strcmp( argv[ 1 ], "-list" ) || !strcmp( argv[ 1 ], "-h" ) || !strcmp( argv[ 1 ], "--help" ))) + { + log_info( "Usage: %s [*] [pid] [id] []\n", argv[0] ); + log_info( "\t\tOne or more of: (wildcard character '*') (default *)\n"); + log_info( "\tpid\t\tIndicates platform at index should be used (default 0).\n" ); + log_info( "\tid\t\tIndicates device at index should be used (default 0).\n" ); + log_info( "\t\tcpu|gpu|accelerator| (default CL_DEVICE_TYPE_DEFAULT)\n" ); + + for( i = 0; i < num_fns - 1; i++ ) + { + log_info( "\t\t%s\n", fnNames[ i ] ); + } + test_finish(); + return 0; + } + + /* How are we supposed to seed the random # generators? */ + if( argc > 1 && strcmp( argv[ argc - 1 ], "randomize" ) == 0 ) + { + gRandomSeed = (cl_uint) time( NULL ); + log_info( "Random seed: %u.\n", gRandomSeed ); + gReSeed = 1; + argc--; + } + else + { + log_info(" Initializing random seed to 0.\n"); + } + + /* Do we have an integer to specify the number of elements to pass to tests? */ + if( argc > 1 ) + { + ret = (int)strtol( argv[ argc - 1 ], &endPtr, 10 ); + if( endPtr != argv[ argc - 1 ] && *endPtr == 0 ) + { + /* By spec, this means the entire string was a valid integer, so we treat it as a num_elements spec */ + /* (hence why we stored the result in ret first) */ + num_elements = ret; + log_info( "Testing with num_elements of %d\n", num_elements ); + argc--; + } + } + + /* Do we have a CPU/GPU specification? */ + if( argc > 1 ) + { + if( strcmp( argv[ argc - 1 ], "gpu" ) == 0 || strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_GPU" ) == 0 ) + { + device_type = CL_DEVICE_TYPE_GPU; + argc--; + } + else if( strcmp( argv[ argc - 1 ], "cpu" ) == 0 || strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_CPU" ) == 0 ) + { + device_type = CL_DEVICE_TYPE_CPU; + argc--; + } + else if( strcmp( argv[ argc - 1 ], "accelerator" ) == 0 || strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + { + device_type = CL_DEVICE_TYPE_ACCELERATOR; + argc--; + } + else if( strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + { + device_type = CL_DEVICE_TYPE_DEFAULT; + argc--; + } + } + + /* Did we choose a specific device index? */ + if( argc > 1 ) + { + if( strlen( argv[ argc - 1 ] ) >= 3 && argv[ argc - 1 ][0] == 'i' && argv[ argc - 1 ][1] == 'd' ) + { + choosen_device_index = atoi( &(argv[ argc - 1 ][2]) ); + argc--; + } + } + + /* Did we choose a specific platform index? */ + if( argc > 1 ) + { + if( strlen( argv[ argc - 1 ] ) >= 3 && argv[ argc - 1 ][0] == 'p' && argv[ argc - 1 ][1] == 'i' && argv[ argc - 1 ][2] == 'd') + { + choosen_platform_index = atoi( &(argv[ argc - 1 ][3]) ); + argc--; + } + } + + switch( device_type ) + { + case CL_DEVICE_TYPE_GPU: log_info( "Requesting GPU device " ); break; + case CL_DEVICE_TYPE_CPU: log_info( "Requesting CPU device " ); break; + case CL_DEVICE_TYPE_ACCELERATOR: log_info( "Requesting Accelerator device " ); break; + case CL_DEVICE_TYPE_DEFAULT: log_info( "Requesting Default device " ); break; + default: log_error( "Requesting unknown device "); return -1; + } + log_info( based_on_env_var ? "based on environment variable " : "based on command line " ); + log_info( "for platform index %d and device index %d\n", choosen_platform_index, choosen_device_index); + +#if defined( __APPLE__ ) +#if defined( __i386__ ) || defined( __x86_64__ ) +#define kHasSSE3 0x00000008 +#define kHasSupplementalSSE3 0x00000100 +#define kHasSSE4_1 0x00000400 +#define kHasSSE4_2 0x00000800 + /* check our environment for a hint to disable SSE variants */ + { + const char *env = getenv( "CL_MAX_SSE" ); + if( env ) + { + extern int _cpu_capabilities; + int mask = 0; + if( 0 == strcasecmp( env, "SSE4.1" ) ) + mask = kHasSSE4_2; + else if( 0 == strcasecmp( env, "SSSE3" ) ) + mask = kHasSSE4_2 | kHasSSE4_1; + else if( 0 == strcasecmp( env, "SSE3" ) ) + mask = kHasSSE4_2 | kHasSSE4_1 | kHasSupplementalSSE3; + else if( 0 == strcasecmp( env, "SSE2" ) ) + mask = kHasSSE4_2 | kHasSSE4_1 | kHasSupplementalSSE3 | kHasSSE3; + else + { + log_error( "Error: Unknown CL_MAX_SSE setting: %s\n", env ); + return -2; + } + + log_info( "*** Environment: CL_MAX_SSE = %s ***\n", env ); + _cpu_capabilities &= ~mask; + } + } +#endif +#endif + + /* Get the platform */ + err = clGetPlatformIDs(0, NULL, &num_platforms); + if (err) { + print_error(err, "clGetPlatformIDs failed"); + test_finish(); + return -1; + } + + platforms = (cl_platform_id *) malloc( num_platforms * sizeof( cl_platform_id ) ); + if (!platforms || choosen_platform_index >= num_platforms) { + log_error( "platform index out of range -- choosen_platform_index (%d) >= num_platforms (%d)\n", choosen_platform_index, num_platforms ); + test_finish(); + return -1; + } + BufferOwningPtr platformsBuf(platforms); + + err = clGetPlatformIDs(num_platforms, platforms, NULL); + if (err) { + print_error(err, "clGetPlatformIDs failed"); + test_finish(); + return -1; + } + + /* Get the number of requested devices */ + err = clGetDeviceIDs(platforms[choosen_platform_index], device_type, 0, NULL, &num_devices ); + if (err) { + print_error(err, "clGetDeviceIDs failed"); + test_finish(); + return -1; + } + + devices = (cl_device_id *) malloc( num_devices * sizeof( cl_device_id ) ); + if (!devices || choosen_device_index >= num_devices) { + log_error( "device index out of range -- choosen_device_index (%d) >= num_devices (%d)\n", choosen_device_index, num_devices ); + test_finish(); + return -1; + } + BufferOwningPtr devicesBuf(devices); + + + /* Get the requested device */ + err = clGetDeviceIDs(platforms[choosen_platform_index], device_type, num_devices, devices, NULL ); + if (err) { + print_error(err, "clGetDeviceIDs failed"); + test_finish(); + return -1; + } + + device = devices[choosen_device_index]; + + if( printDeviceHeader( device ) != CL_SUCCESS ) + { + test_finish(); + return -1; + } + + cl_device_fp_config fpconfig = 0; + err = clGetDeviceInfo( device, CL_DEVICE_SINGLE_FP_CONFIG, sizeof( fpconfig ), &fpconfig, NULL ); + if (err) { + print_error(err, "clGetDeviceInfo for CL_DEVICE_SINGLE_FP_CONFIG failed"); + test_finish(); + return -1; + } + + gFlushDenormsToZero = ( 0 == (fpconfig & CL_FP_DENORM)); + log_info( "Supports single precision denormals: %s\n", gFlushDenormsToZero ? "NO" : "YES" ); + log_info( "sizeof( void*) = %d (host)\n", (int) sizeof( void* ) ); + + //detect whether profile of the device is embedded + char profile[1024] = ""; + err = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL); + if (err) + { + print_error(err, "clGetDeviceInfo for CL_DEVICE_PROFILE failed\n" ); + test_finish(); + return -1; + } + gIsEmbedded = NULL != strstr(profile, "EMBEDDED_PROFILE"); + + //detect the floating point capabilities + cl_device_fp_config floatCapabilities = 0; + err = clGetDeviceInfo(device, CL_DEVICE_SINGLE_FP_CONFIG, sizeof(floatCapabilities), &floatCapabilities, NULL); + if (err) + { + print_error(err, "clGetDeviceInfo for CL_DEVICE_SINGLE_FP_CONFIG failed\n"); + test_finish(); + return -1; + } + + // Check for problems that only embedded will have + if( gIsEmbedded ) + { + //If the device is embedded, we need to detect if the device supports Infinity and NaN + if ((floatCapabilities & CL_FP_INF_NAN) == 0) + gInfNanSupport = 0; + + // check the extensions list to see if ulong and long are supported + size_t extensionsStringSize = 0; + if( (err = clGetDeviceInfo( device, CL_DEVICE_EXTENSIONS, 0, NULL, &extensionsStringSize ) )) + { + print_error( err, "Unable to get extensions string size for embedded device" ); + test_finish(); + return -1; + } + char *extensions_string = (char*) malloc(extensionsStringSize); + if( NULL == extensions_string ) + { + print_error( CL_OUT_OF_HOST_MEMORY, "Unable to allocate storage for extensions string for embedded device" ); + test_finish(); + return -1; + } + BufferOwningPtr extensions_stringBuf(extensions_string); + + if( (err = clGetDeviceInfo( device, CL_DEVICE_EXTENSIONS, extensionsStringSize, extensions_string, NULL ) )) + { + print_error( err, "Unable to get extensions string for embedded device" ); + test_finish(); + return -1; + } + + if( extensions_string[extensionsStringSize-1] != '\0' ) + { + log_error( "FAILURE: extensions string for embedded device is not NUL terminated" ); + test_finish(); + return -1; + } + + if( NULL == strstr( extensions_string, "cles_khr_int64" )) + gHasLong = 0; + } + + if( getenv( "OPENCL_1_0_DEVICE" ) ) + { + char c_version[1024]; + gIsOpenCL_1_0_Device = 1; + memset( c_version, 0, sizeof( c_version ) ); + + if( (err = clGetDeviceInfo( device, CL_DEVICE_OPENCL_C_VERSION, sizeof(c_version), c_version, NULL )) ) + { + log_error( "FAILURE: unable to get CL_DEVICE_OPENCL_C_VERSION on 1.0 device. (%d)\n", err ); + test_finish(); + return -1; + } + + if( 0 == strncmp( c_version, "OpenCL C 1.0 ", strlen( "OpenCL C 1.0 " ) ) ) + { + gIsOpenCL_C_1_0_Device = 1; + log_info( "Device is a OpenCL C 1.0 device\n" ); + } + else + log_info( "Device is a OpenCL 1.0 device, but supports OpenCL C 1.1\n" ); + } + + cl_uint device_address_bits = 0; + if( (err = clGetDeviceInfo( device, CL_DEVICE_ADDRESS_BITS, sizeof( device_address_bits ), &device_address_bits, NULL ) )) + { + print_error( err, "Unable to obtain device address bits" ); + test_finish(); + return -1; + } + if( device_address_bits ) + log_info( "sizeof( void*) = %d (device)\n", device_address_bits/8 ); + else + { + log_error("Invalid device address bit size returned by device.\n"); + test_finish(); + return -1; + } + + + /* If we have a device checking function, run it */ + if( ( deviceCheckFn != NULL ) && deviceCheckFn( device ) != CL_SUCCESS ) + { + test_finish(); + return -1; + } + + if (num_elements <= 0) + num_elements = DEFAULT_NUM_ELEMENTS; + + // On most platforms which support denorm, default is FTZ off. However, + // on some hardware where the reference is computed, default might be flush denorms to zero e.g. arm. + // This creates issues in result verification. Since spec allows the implementation to either flush or + // not flush denorms to zero, an implementation may choose not be flush i.e. return denorm result whereas + // reference result may be zero (flushed denorm). Hence we need to disable denorm flushing on host side + // where reference is being computed to make sure we get non-flushed reference result. If implementation + // returns flushed result, we correctly take care of that in verification code. +#if defined(__APPLE__) && defined(__arm__) + FPU_mode_type oldMode; + DisableFTZ( &oldMode ); +#endif + + int error = parseAndCallCommandLineTests( argc, argv, device, num_fns, fnList, fnNames, forceNoContextCreation, queueProps, num_elements ); + + #if defined(__APPLE__) && defined(__arm__) + // Restore the old FP mode before leaving. + RestoreFPState( &oldMode ); +#endif + + return error; +} + +static int find_wildcard_matching_functions( const char *fnNames[], unsigned char fnsToCall[], unsigned int num_fns, + const char *wildcard ) +{ + int found_tests = 0; + size_t wildcard_length = strlen( wildcard ) - 1; /* -1 for the asterisk */ + + for( unsigned int fnIndex = 0; fnIndex < num_fns; fnIndex++ ) + { + if( strncmp( fnNames[ fnIndex ], wildcard, wildcard_length ) == 0 ) + { + if( fnsToCall[ fnIndex ] ) + { + log_error( "ERROR: Test '%s' has already been selected.\n", fnNames[ fnIndex ] ); + return EXIT_FAILURE; + } + + fnsToCall[ fnIndex ] = 1; + found_tests = 1; + } + } + + if( !found_tests ) + { + log_error( "ERROR: The wildcard '%s' did not match any test names.\n", wildcard ); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +static int find_argument_matching_function( const char *fnNames[], unsigned char *fnsToCall, unsigned int num_fns, + const char *argument ) +{ + unsigned int fnIndex; + + for( fnIndex = 0; fnIndex < num_fns; fnIndex++ ) + { + if( strcmp( argument, fnNames[ fnIndex ] ) == 0 ) + { + if( fnsToCall[ fnIndex ] ) + { + log_error( "ERROR: Test '%s' has already been selected.\n", fnNames[ fnIndex ] ); + return EXIT_FAILURE; + } + else + { + fnsToCall[ fnIndex ] = 1; + break; + } + } + } + + if( fnIndex == num_fns ) + { + log_error( "ERROR: The argument '%s' did not match any test names.\n", argument ); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +int parseAndCallCommandLineTests( int argc, const char *argv[], cl_device_id device, unsigned int num_fns, + basefn fnList[], const char *fnNames[], int forceNoContextCreation, + cl_command_queue_properties queueProps, int num_elements ) +{ + int ret = EXIT_SUCCESS; + + unsigned char *fnsToCall = ( unsigned char* ) calloc( num_fns, 1 ); + + if( argc == 1 ) + { + /* No actual arguments, all tests will be run. */ + memset( fnsToCall, 1, num_fns ); + } + else + { + for( int argIndex = 1; argIndex < argc; argIndex++ ) + { + if( strchr( argv[ argIndex ], '*' ) != NULL ) + { + ret = find_wildcard_matching_functions( fnNames, fnsToCall, num_fns, argv[ argIndex ] ); + } + else + { + if( strcmp( argv[ argIndex ], "all" ) == 0 ) + { + memset( fnsToCall, 1, num_fns ); + break; + } + else + { + ret = find_argument_matching_function( fnNames, fnsToCall, num_fns, argv[ argIndex ] ); + } + } + + if( ret == EXIT_FAILURE ) + { + break; + } + } + } + + if( ret == EXIT_SUCCESS ) + { + ret = callTestFunctions( fnList, fnNames, fnsToCall, num_fns, device, forceNoContextCreation, num_elements, queueProps ); + + if( gTestsFailed == 0 ) + { + if( gTestsPassed > 1 ) + { + log_info("PASSED %d of %d tests.\n", gTestsPassed, gTestsPassed); + } + else if( gTestsPassed > 0 ) + { + log_info("PASSED test.\n"); + } + } + else if( gTestsFailed > 0 ) + { + if( gTestsFailed+gTestsPassed > 1 ) + { + log_error("FAILED %d of %d tests.\n", gTestsFailed, gTestsFailed+gTestsPassed); + } + else + { + log_error("FAILED test.\n"); + } + } + } + + test_finish(); + + free( fnsToCall ); + + return ret; +} + +int callTestFunctions( basefn functionList[], const char *functionNames[], unsigned char functionsToCall[], + int numFunctions, cl_device_id deviceToUse, int forceNoContextCreation, + int numElementsToUse, cl_command_queue_properties queueProps ) +{ + int numErrors = 0; + + for( int i = 0; i < numFunctions; ++i ) + { + if( functionsToCall[ i ] ) + { + /* Skip any unimplemented tests. */ + if( functionList[ i ] != NULL ) + { + numErrors += callSingleTestFunction( functionList[ i ], functionNames[ i ], deviceToUse, + forceNoContextCreation, numElementsToUse, queueProps ); + } + else + { + log_info( "%s test currently not implemented\n", functionNames[ i ] ); + } + } + } + + return numErrors; +} + +void CL_CALLBACK notify_callback(const char *errinfo, const void *private_info, size_t cb, void *user_data) +{ + log_info( "%s\n", errinfo ); +} + +// Actual function execution +int callSingleTestFunction( basefn functionToCall, const char *functionName, + cl_device_id deviceToUse, int forceNoContextCreation, + int numElementsToUse, const cl_queue_properties queueProps ) +{ + int numErrors = 0, ret; + cl_int error; + cl_context context = NULL; + cl_command_queue queue = NULL; + const cl_command_queue_properties cmd_queueProps = (queueProps)?CL_QUEUE_PROPERTIES:0; + cl_command_queue_properties queueCreateProps[] = {cmd_queueProps, queueProps, 0}; + + /* Create a context to work with, unless we're told not to */ + if( !forceNoContextCreation ) + { + context = clCreateContext(NULL, 1, &deviceToUse, notify_callback, NULL, &error ); + if (!context) + { + print_error( error, "Unable to create testing context" ); + return 1; + } + + queue = clCreateCommandQueueWithProperties( context, deviceToUse, &queueCreateProps[0], &error ); + if( queue == NULL ) + { + print_error( error, "Unable to create testing command queue" ); + return 1; + } + } + + /* Run the test and print the result */ + log_info( "%s...\n", functionName ); + fflush( stdout ); + + error = check_opencl_version_with_testname(functionName, deviceToUse); + test_missing_feature(error, functionName); + + error = check_functions_for_offline_compiler(functionName, deviceToUse); + test_missing_support_offline_cmpiler(error, functionName); + + ret = functionToCall( deviceToUse, context, queue, numElementsToUse); //test_threaded_function( ptr_basefn_list[i], group, context, num_elements); + if( ret == TEST_NOT_IMPLEMENTED ) + { + /* Tests can also let us know they're not implemented yet */ + log_info("%s test currently not implemented\n\n", functionName); + } + else + { + /* Print result */ + if( ret == 0 ) { + log_info( "%s PASSED\n", functionName ); + gTestsPassed++; + } + else + { + numErrors++; + log_error( "%s FAILED\n", functionName ); + gTestsFailed++; + } + } + + /* Release the context */ + if( !forceNoContextCreation ) + { + int error = clFinish(queue); + if (error) { + log_error("clFinish failed: %d", error); + numErrors++; + } + clReleaseCommandQueue( queue ); + clReleaseContext( context ); + } + + return numErrors; +} + +void checkDeviceTypeOverride( cl_device_type *inOutType ) +{ + /* Check if we are forced to CPU mode */ + char *force_cpu = getenv( "CL_DEVICE_TYPE" ); + if( force_cpu != NULL ) + { + if( strcmp( force_cpu, "gpu" ) == 0 || strcmp( force_cpu, "CL_DEVICE_TYPE_GPU" ) == 0 ) + *inOutType = CL_DEVICE_TYPE_GPU; + else if( strcmp( force_cpu, "cpu" ) == 0 || strcmp( force_cpu, "CL_DEVICE_TYPE_CPU" ) == 0 ) + *inOutType = CL_DEVICE_TYPE_CPU; + else if( strcmp( force_cpu, "accelerator" ) == 0 || strcmp( force_cpu, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + *inOutType = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( force_cpu, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + *inOutType = CL_DEVICE_TYPE_DEFAULT; + } + + switch( *inOutType ) + { + case CL_DEVICE_TYPE_GPU: log_info( "Requesting GPU device " ); break; + case CL_DEVICE_TYPE_CPU: log_info( "Requesting CPU device " ); break; + case CL_DEVICE_TYPE_ACCELERATOR: log_info( "Requesting Accelerator device " ); break; + case CL_DEVICE_TYPE_DEFAULT: log_info( "Requesting Default device " ); break; + default: break; + } + log_info( force_cpu != NULL ? "based on environment variable\n" : "based on command line\n" ); + +#if defined( __APPLE__ ) + { + // report on any unusual library search path indirection + char *libSearchPath = getenv( "DYLD_LIBRARY_PATH"); + if( libSearchPath ) + log_info( "*** DYLD_LIBRARY_PATH = \"%s\"\n", libSearchPath ); + + // report on any unusual framework search path indirection + char *frameworkSearchPath = getenv( "DYLD_FRAMEWORK_PATH"); + if( libSearchPath ) + log_info( "*** DYLD_FRAMEWORK_PATH = \"%s\"\n", frameworkSearchPath ); + } +#endif + +} + +#if ! defined( __APPLE__ ) +void memset_pattern4(void *dest, const void *src_pattern, size_t bytes ) +{ + uint32_t pat = ((uint32_t*) src_pattern)[0]; + size_t count = bytes / 4; + size_t i; + uint32_t *d = (uint32_t*)dest; + + for( i = 0; i < count; i++ ) + d[i] = pat; + + d += i; + + bytes &= 3; + if( bytes ) + memcpy( d, src_pattern, bytes ); +} +#endif + +extern cl_device_type GetDeviceType( cl_device_id d ) +{ + cl_device_type result = -1; + cl_int err = clGetDeviceInfo( d, CL_DEVICE_TYPE, sizeof( result ), &result, NULL ); + if( CL_SUCCESS != err ) + log_error( "ERROR: Unable to get device type for device %p\n", d ); + return result; +} + + +cl_device_id GetOpposingDevice( cl_device_id device ) +{ + cl_int error; + cl_device_id *otherDevices; + cl_uint actualCount; + cl_platform_id plat; + + // Get the platform of the device to use for getting a list of devices + error = clGetDeviceInfo( device, CL_DEVICE_PLATFORM, sizeof( plat ), &plat, NULL ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to get device's platform" ); + return NULL; + } + + // Get a list of all devices + error = clGetDeviceIDs( plat, CL_DEVICE_TYPE_ALL, 0, NULL, &actualCount ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to get list of devices size" ); + return NULL; + } + otherDevices = (cl_device_id *)malloc(actualCount*sizeof(cl_device_id)); + if (NULL == otherDevices) { + print_error( error, "Unable to allocate list of other devices." ); + return NULL; + } + BufferOwningPtr otherDevicesBuf(otherDevices); + + error = clGetDeviceIDs( plat, CL_DEVICE_TYPE_ALL, actualCount, otherDevices, NULL ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to get list of devices" ); + return NULL; + } + + if( actualCount == 1 ) + { + return device; // NULL means error, returning self means we couldn't find another one + } + + // Loop and just find one that isn't the one we were given + cl_uint i; + for( i = 0; i < actualCount; i++ ) + { + if( otherDevices[ i ] != device ) + { + cl_device_type newType; + error = clGetDeviceInfo( otherDevices[ i ], CL_DEVICE_TYPE, sizeof( newType ), &newType, NULL ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to get device type for other device" ); + return NULL; + } + cl_device_id result = otherDevices[ i ]; + return result; + } + } + + // Should never get here + return NULL; +} diff --git a/test_common/harness/testHarness.h b/test_common/harness/testHarness.h new file mode 100644 index 00000000..2816b2a0 --- /dev/null +++ b/test_common/harness/testHarness.h @@ -0,0 +1,102 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testHarness_h +#define _testHarness_h + +#include "threadTesting.h" +#include "clImageHelper.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern cl_uint gReSeed; +extern cl_uint gRandomSeed; + +// Supply a list of functions to test here. This will allocate a CL device, create a context, all that +// setup work, and then call each function in turn as dictatated by the passed arguments. +extern int runTestHarness( int argc, const char *argv[], unsigned int num_fns, + basefn fnList[], const char *fnNames[], + int imageSupportRequired, int forceNoContextCreation, cl_command_queue_properties queueProps ); + +// Device checking function. See runTestHarnessWithCheck. If this function returns anything other than CL_SUCCESS (0), the harness exits. +typedef int (*DeviceCheckFn)( cl_device_id device ); + +// Same as runTestHarness, but also supplies a function that checks the created device for required functionality. +extern int runTestHarnessWithCheck( int argc, const char *argv[], unsigned int num_fns, + basefn fnList[], const char *fnNames[], + int imageSupportRequired, int forceNoContextCreation, cl_command_queue_properties queueProps, DeviceCheckFn deviceCheckFn ); + +// The command line parser used by runTestHarness to break up parameters into calls to callTestFunctions +extern int parseAndCallCommandLineTests( int argc, const char *argv[], cl_device_id device, unsigned int num_fns, + basefn *fnList, const char *fnNames[], + int forceNoContextCreation, cl_command_queue_properties queueProps, int num_elements ); + +// Call this function if you need to do all the setup work yourself, and just need the function list called/ +// managed. +// functionList is the actual array of functions +// functionNames is an array of strings representing the name of each function +// functionsToCall is an array of integers (treated as bools) which tell which function is to be called, +// each element at index i, corresponds to the element in functionList at index i +// numFunctions is the number of elements in the arrays +// contextProps are used to create a testing context for each test +// deviceToUse and numElementsToUse are all just passed to each test function +extern int callTestFunctions( basefn functionList[], const char *functionNames[], unsigned char functionsToCall[], + int numFunctions, cl_device_id deviceToUse, int forceNoContextCreation, + int numElementsToUse, cl_command_queue_properties queueProps ); + +// This function is called by callTestFunctions, once per function, to do setup, call, logging and cleanup +extern int callSingleTestFunction( basefn functionToCall, const char *functionName, + cl_device_id deviceToUse, int forceNoContextCreation, + int numElementsToUse, cl_command_queue_properties queueProps ); + +///// Miscellaneous steps + +// Given a pre-existing device type choice, check the environment for an override, then print what +// choice was made and how (and return the overridden choice, if there is one) +extern void checkDeviceTypeOverride( cl_device_type *inOutType ); + +// standard callback function for context pfn_notify +extern void CL_CALLBACK notify_callback(const char *errinfo, const void *private_info, size_t cb, void *user_data); + +extern cl_device_type GetDeviceType( cl_device_id ); + +// Given a device (most likely passed in by the harness, but not required), will attempt to find +// a DIFFERENT device and return it. Useful for finding another device to run multi-device tests against. +// Note that returning NULL means an error was hit, but if no error was hit and the device passed in +// is the only device available, the SAME device is returned, so check! +extern cl_device_id GetOpposingDevice( cl_device_id device ); + + +extern int gFlushDenormsToZero; // This is set to 1 if the device does not support denorms (CL_FP_DENORM) +extern int gInfNanSupport; // This is set to 1 if the device supports infinities and NaNs +extern int gIsEmbedded; // This is set to 1 if the device is an embedded device +extern int gHasLong; // This is set to 1 if the device suppots long and ulong types in OpenCL C. +extern int gIsOpenCL_C_1_0_Device; // This is set to 1 if the device supports only OpenCL C 1.0. + +#if ! defined( __APPLE__ ) + void memset_pattern4(void *, const void *, size_t); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // _testHarness_h + + diff --git a/test_common/harness/test_mt19937.c b/test_common/harness/test_mt19937.c new file mode 100644 index 00000000..c0498ea9 --- /dev/null +++ b/test_common/harness/test_mt19937.c @@ -0,0 +1,51 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "mt19937.h" +#include + +int main( void ) +{ + MTdata d = init_genrand(42); + int i; + const cl_uint reference[16] = { 0x5fe1dc66, 0x8b255210, 0x0380b0c8, 0xc87d2ce4, + 0x55c31f24, 0x8bcd21ab, 0x14d5fef5, 0x9416d2b6, + 0xdf875de9, 0x00517d76, 0xd861c944, 0xa7676404, + 0x5491aff4, 0x67616209, 0xc368b3fb, 0x929dfc92 }; + int errcount = 0; + + for( i = 0; i < 65536; i++ ) + { + cl_uint u = genrand_int32( d ); + if( 0 == (i & 4095) ) + { + if( u != reference[i>>12] ) + { + printf("ERROR: expected *0x%8.8x at %d. Got 0x%8.8x\n", reference[i>>12], i, u ); + errcount++; + } + } + } + + free_mtdata(d); + + if( errcount ) + printf("mt19937 test failed.\n"); + else + printf("mt19937 test passed.\n"); + + + return 0; +} \ No newline at end of file diff --git a/test_common/harness/threadTesting.c b/test_common/harness/threadTesting.c new file mode 100644 index 00000000..1a07f974 --- /dev/null +++ b/test_common/harness/threadTesting.c @@ -0,0 +1,100 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "compat.h" +#include "threadTesting.h" +#include "errorHelpers.h" +#include +#include + +#if !defined(_WIN32) +#include +#endif + +#if 0 // Disabed for now + +typedef struct +{ + basefn mFunction; + cl_device_id mDevice; + cl_context mContext; + int mNumElements; +} TestFnArgs; + +//////////////////////////////////////////////////////////////////////////////// +// Thread-based testing. Spawns a new thread to run the given test function, +// then waits for it to complete. The entire idea is that, if the thread crashes, +// we can catch it and report it as a failure instead of crashing the entire suite +//////////////////////////////////////////////////////////////////////////////// + +void *test_thread_wrapper( void *data ) +{ + TestFnArgs *args; + int retVal; + cl_context context; + + args = (TestFnArgs *)data; + + /* Create a new context to use (contexts can't cross threads) */ + context = clCreateContext(NULL, args->mDeviceGroup); + if( context == NULL ) + { + log_error("clCreateContext failed for new thread\n"); + return (void *)(-1); + } + + /* Call function */ + retVal = args->mFunction( args->mDeviceGroup, args->mDevice, context, args->mNumElements ); + + clReleaseContext( context ); + + return (void *)retVal; +} + +int test_threaded_function( basefn fnToTest, cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + int error; + pthread_t threadHdl; + void *retVal; + TestFnArgs args; + + + args.mFunction = fnToTest; + args.mDeviceGroup = deviceGroup; + args.mDevice = device; + args.mContext = context; + args.mNumElements = numElements; + + + error = pthread_create( &threadHdl, NULL, test_thread_wrapper, (void *)&args ); + if( error != 0 ) + { + log_error( "ERROR: Unable to create thread for testing!\n" ); + return -1; + } + + /* Thread has been started, now just wait for it to complete (or crash) */ + error = pthread_join( threadHdl, &retVal ); + if( error != 0 ) + { + log_error( "ERROR: Unable to join testing thread!\n" ); + return -1; + } + + return (int)((intptr_t)retVal); +} +#endif + + diff --git a/test_common/harness/threadTesting.h b/test_common/harness/threadTesting.h new file mode 100644 index 00000000..81a5757b --- /dev/null +++ b/test_common/harness/threadTesting.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _threadTesting_h +#define _threadTesting_h + +#ifdef __APPLE__ + #include +#else + #include +#endif + +#define TEST_NOT_IMPLEMENTED -99 + +typedef int (*basefn)(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_threaded_function( basefn fnToTest, cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); + +#endif // _threadTesting_h + + diff --git a/test_common/harness/typeWrappers.cpp b/test_common/harness/typeWrappers.cpp new file mode 100644 index 00000000..d4e08fb9 --- /dev/null +++ b/test_common/harness/typeWrappers.cpp @@ -0,0 +1,481 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "typeWrappers.h" +#include "kernelHelpers.h" +#include "errorHelpers.h" +#include +#include "clImageHelper.h" + +#define ROUND_SIZE_UP( _size, _align ) (((size_t)(_size) + (size_t)(_align) - 1) & -((size_t)(_align))) + +#if defined( __APPLE__ ) + #define kPageSize 4096 + #include + #include +#elif defined(__linux__) + #include + #define kPageSize (getpagesize()) +#endif + +clProtectedImage::clProtectedImage( cl_context context, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width, cl_int *errcode_ret ) +{ + cl_int err = Create( context, mem_flags, fmt, width ); + if( errcode_ret != NULL ) + *errcode_ret = err; +} + +cl_int clProtectedImage::Create( cl_context context, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width ) +{ + cl_int error; +#if defined( __APPLE__ ) + int protect_pages = 1; + cl_device_id devices[16]; + size_t number_of_devices; + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, sizeof(devices), devices, &number_of_devices); + test_error(error, "clGetContextInfo for CL_CONTEXT_DEVICES failed"); + + number_of_devices /= sizeof(cl_device_id); + for (int i=0; i<(int)number_of_devices; i++) { + cl_device_type type; + error = clGetDeviceInfo(devices[i], CL_DEVICE_TYPE, sizeof(type), &type, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_TYPE failed"); + if (type == CL_DEVICE_TYPE_GPU) { + protect_pages = 0; + break; + } + } + + if (protect_pages) { + size_t pixelBytes = get_pixel_bytes(fmt); + size_t rowBytes = ROUND_SIZE_UP( width * pixelBytes, kPageSize ); + size_t rowStride = rowBytes + kPageSize; + + // create backing store + backingStoreSize = rowStride + 8 * rowStride; + backingStore = mmap(0, backingStoreSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); + + // add guard pages + size_t row; + char *p = (char*) backingStore; + char *imagePtr = (char*) backingStore + 4 * rowStride; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + p += rowBytes; + mprotect( p, kPageSize, PROT_NONE ); p += rowStride; + p -= rowBytes; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + + if( getenv( "CL_ALIGN_RIGHT" ) ) + { + static int spewEnv = 1; + if(spewEnv) + { + log_info( "***CL_ALIGN_RIGHT is set. Aligning images at right edge of page\n" ); + spewEnv = 0; + } + imagePtr += rowBytes - pixelBytes * width; + } + + image = create_image_1d( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, rowStride, imagePtr, NULL, &error ); + } else { + backingStore = NULL; + image = create_image_1d( context, mem_flags, fmt, width, 0, NULL, NULL, &error ); + + } +#else + + backingStore = NULL; + image = create_image_1d( context, mem_flags, fmt, width, 0, NULL, NULL, &error ); + +#endif + return error; +} + + +clProtectedImage::clProtectedImage( cl_context context, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width, size_t height, cl_int *errcode_ret ) +{ + cl_int err = Create( context, mem_flags, fmt, width, height ); + if( errcode_ret != NULL ) + *errcode_ret = err; +} + +cl_int clProtectedImage::Create( cl_context context, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width, size_t height ) +{ + cl_int error; +#if defined( __APPLE__ ) + int protect_pages = 1; + cl_device_id devices[16]; + size_t number_of_devices; + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, sizeof(devices), devices, &number_of_devices); + test_error(error, "clGetContextInfo for CL_CONTEXT_DEVICES failed"); + + number_of_devices /= sizeof(cl_device_id); + for (int i=0; i<(int)number_of_devices; i++) { + cl_device_type type; + error = clGetDeviceInfo(devices[i], CL_DEVICE_TYPE, sizeof(type), &type, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_TYPE failed"); + if (type == CL_DEVICE_TYPE_GPU) { + protect_pages = 0; + break; + } + } + + if (protect_pages) { + size_t pixelBytes = get_pixel_bytes(fmt); + size_t rowBytes = ROUND_SIZE_UP( width * pixelBytes, kPageSize ); + size_t rowStride = rowBytes + kPageSize; + + // create backing store + backingStoreSize = height * rowStride + 8 * rowStride; + backingStore = mmap(0, backingStoreSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); + + // add guard pages + size_t row; + char *p = (char*) backingStore; + char *imagePtr = (char*) backingStore + 4 * rowStride; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + p += rowBytes; + for( row = 0; row < height; row++ ) + { + mprotect( p, kPageSize, PROT_NONE ); p += rowStride; + } + p -= rowBytes; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + + if( getenv( "CL_ALIGN_RIGHT" ) ) + { + static int spewEnv = 1; + if(spewEnv) + { + log_info( "***CL_ALIGN_RIGHT is set. Aligning images at right edge of page\n" ); + spewEnv = 0; + } + imagePtr += rowBytes - pixelBytes * width; + } + + image = create_image_2d( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, height, rowStride, imagePtr, &error ); + } else { + backingStore = NULL; + image = create_image_2d( context, mem_flags, fmt, width, height, 0, NULL, &error ); + + } +#else + + backingStore = NULL; + image = create_image_2d( context, mem_flags, fmt, width, height, 0, NULL, &error ); + +#endif + return error; +} + +clProtectedImage::clProtectedImage( cl_context context, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth, cl_int *errcode_ret ) +{ + cl_int err = Create( context, mem_flags, fmt, width, height, depth ); + if( errcode_ret != NULL ) + *errcode_ret = err; +} + +cl_int clProtectedImage::Create( cl_context context, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth ) +{ + cl_int error; + +#if defined( __APPLE__ ) + int protect_pages = 1; + cl_device_id devices[16]; + size_t number_of_devices; + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, sizeof(devices), devices, &number_of_devices); + test_error(error, "clGetContextInfo for CL_CONTEXT_DEVICES failed"); + + number_of_devices /= sizeof(cl_device_id); + for (int i=0; i<(int)number_of_devices; i++) { + cl_device_type type; + error = clGetDeviceInfo(devices[i], CL_DEVICE_TYPE, sizeof(type), &type, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_TYPE failed"); + if (type == CL_DEVICE_TYPE_GPU) { + protect_pages = 0; + break; + } + } + + if (protect_pages) { + size_t pixelBytes = get_pixel_bytes(fmt); + size_t rowBytes = ROUND_SIZE_UP( width * pixelBytes, kPageSize ); + size_t rowStride = rowBytes + kPageSize; + + // create backing store + backingStoreSize = height * depth * rowStride + 8 * rowStride; + backingStore = mmap(0, backingStoreSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); + + // add guard pages + size_t row; + char *p = (char*) backingStore; + char *imagePtr = (char*) backingStore + 4 * rowStride; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + p += rowBytes; + for( row = 0; row < height*depth; row++ ) + { + mprotect( p, kPageSize, PROT_NONE ); p += rowStride; + } + p -= rowBytes; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + + if( getenv( "CL_ALIGN_RIGHT" ) ) + { + static int spewEnv = 1; + if(spewEnv) + { + log_info( "***CL_ALIGN_RIGHT is set. Aligning images at right edge of page\n" ); + spewEnv = 0; + } + imagePtr += rowBytes - pixelBytes * width; + } + + image = create_image_3d( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, height, depth, rowStride, height*rowStride, imagePtr, &error ); + } else { + backingStore = NULL; + image = create_image_3d( context, mem_flags, fmt, width, height, depth, 0, 0, NULL, &error ); + } +#else + + backingStore = NULL; + image = create_image_3d( context, mem_flags, fmt, width, height, depth, 0, 0, NULL, &error ); + +#endif + + return error; +} + + +clProtectedImage::clProtectedImage( cl_context context, cl_mem_object_type imageType, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth, size_t arraySize, cl_int *errcode_ret ) +{ + cl_int err = Create( context, imageType, mem_flags, fmt, width, height, depth, arraySize ); + if( errcode_ret != NULL ) + *errcode_ret = err; +} + +cl_int clProtectedImage::Create( cl_context context, cl_mem_object_type imageType, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth, size_t arraySize ) +{ + cl_int error; +#if defined( __APPLE__ ) + int protect_pages = 1; + cl_device_id devices[16]; + size_t number_of_devices; + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, sizeof(devices), devices, &number_of_devices); + test_error(error, "clGetContextInfo for CL_CONTEXT_DEVICES failed"); + + number_of_devices /= sizeof(cl_device_id); + for (int i=0; i<(int)number_of_devices; i++) { + cl_device_type type; + error = clGetDeviceInfo(devices[i], CL_DEVICE_TYPE, sizeof(type), &type, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_TYPE failed"); + if (type == CL_DEVICE_TYPE_GPU) { + protect_pages = 0; + break; + } + } + + if (protect_pages) { + size_t pixelBytes = get_pixel_bytes(fmt); + size_t rowBytes = ROUND_SIZE_UP( width * pixelBytes, kPageSize ); + size_t rowStride = rowBytes + kPageSize; + + // create backing store + switch (imageType) + { + case CL_MEM_OBJECT_IMAGE1D: + backingStoreSize = rowStride + 8 * rowStride; + break; + case CL_MEM_OBJECT_IMAGE2D: + backingStoreSize = height * rowStride + 8 * rowStride; + break; + case CL_MEM_OBJECT_IMAGE3D: + backingStoreSize = height * depth * rowStride + 8 * rowStride; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + backingStoreSize = arraySize * rowStride + 8 * rowStride; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + backingStoreSize = height * arraySize * rowStride + 8 * rowStride; + break; + } + backingStore = mmap(0, backingStoreSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); + + // add guard pages + size_t row; + char *p = (char*) backingStore; + char *imagePtr = (char*) backingStore + 4 * rowStride; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + p += rowBytes; + size_t sz = (height > 0 ? height : 1) * (depth > 0 ? depth : 1) * (arraySize > 0 ? arraySize : 1); + for( row = 0; row < sz; row++ ) + { + mprotect( p, kPageSize, PROT_NONE ); p += rowStride; + } + p -= rowBytes; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + + if( getenv( "CL_ALIGN_RIGHT" ) ) + { + static int spewEnv = 1; + if(spewEnv) + { + log_info( "***CL_ALIGN_RIGHT is set. Aligning images at right edge of page\n" ); + spewEnv = 0; + } + imagePtr += rowBytes - pixelBytes * width; + } + + switch (imageType) + { + case CL_MEM_OBJECT_IMAGE1D: + image = create_image_1d( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, rowStride, imagePtr, NULL, &error ); + break; + case CL_MEM_OBJECT_IMAGE2D: + image = create_image_2d( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, height, rowStride, imagePtr, &error ); + break; + case CL_MEM_OBJECT_IMAGE3D: + image = create_image_3d( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, height, depth, rowStride, height*rowStride, imagePtr, &error ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + image = create_image_1d_array( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, arraySize, rowStride, rowStride, imagePtr, &error ); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + image = create_image_2d_array( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, height, arraySize, rowStride, height*rowStride, imagePtr, &error ); + break; + } + } else { + backingStore = NULL; + switch (imageType) + { + case CL_MEM_OBJECT_IMAGE1D: + image = create_image_1d( context, mem_flags, fmt, width, 0, NULL, NULL, &error ); + break; + case CL_MEM_OBJECT_IMAGE2D: + image = create_image_2d( context, mem_flags, fmt, width, height, 0, NULL, &error ); + break; + case CL_MEM_OBJECT_IMAGE3D: + image = create_image_3d( context, mem_flags, fmt, width, height, depth, 0, 0, NULL, &error );; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + image = create_image_1d_array( context, mem_flags, fmt, width, arraySize, 0, 0, NULL, &error ); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + image = create_image_2d_array( context, mem_flags, fmt, width, height, arraySize, 0, 0, NULL, &error ); + break; + } + + } +#else + + backingStore = NULL; + switch (imageType) + { + case CL_MEM_OBJECT_IMAGE1D: + image = create_image_1d( context, mem_flags, fmt, width, 0, NULL, NULL, &error ); + break; + case CL_MEM_OBJECT_IMAGE2D: + image = create_image_2d( context, mem_flags, fmt, width, height, 0, NULL, &error ); + break; + case CL_MEM_OBJECT_IMAGE3D: + image = create_image_3d( context, mem_flags, fmt, width, height, depth, 0, 0, NULL, &error );; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + image = create_image_1d_array( context, mem_flags, fmt, width, arraySize, 0, 0, NULL, &error ); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + image = create_image_2d_array( context, mem_flags, fmt, width, height, arraySize, 0, 0, NULL, &error ); + break; + } +#endif + return error; +} + + + +/******* + * clProtectedArray implementation + *******/ +clProtectedArray::clProtectedArray() +{ + mBuffer = mValidBuffer = NULL; +} + +clProtectedArray::clProtectedArray( size_t sizeInBytes ) +{ + mBuffer = mValidBuffer = NULL; + Allocate( sizeInBytes ); +} + +clProtectedArray::~clProtectedArray() +{ + if( mBuffer != NULL ) { +#if defined( __APPLE__ ) + int error = munmap( mBuffer, mRealSize ); + if (error) log_error("WARNING: munmap failed in clProtectedArray.\n"); +#else + free( mBuffer ); +#endif + } +} + +void clProtectedArray::Allocate( size_t sizeInBytes ) +{ + +#if defined( __APPLE__ ) + + // Allocate enough space to: round up our actual allocation to an even number of pages + // and allocate two pages on either side + mRoundedSize = ROUND_SIZE_UP( sizeInBytes, kPageSize ); + mRealSize = mRoundedSize + kPageSize * 2; + + // Use mmap here to ensure we start on a page boundary, so the mprotect calls will work OK + mBuffer = (char *)mmap(0, mRealSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); + + mValidBuffer = mBuffer + kPageSize; + + // Protect guard area from access + mprotect( mValidBuffer - kPageSize, kPageSize, PROT_NONE ); + mprotect( mValidBuffer + mRoundedSize, kPageSize, PROT_NONE ); +#else + mRoundedSize = mRealSize = sizeInBytes; + mBuffer = mValidBuffer = (char *)calloc(1, mRealSize); +#endif +} + + diff --git a/test_common/harness/typeWrappers.h b/test_common/harness/typeWrappers.h new file mode 100644 index 00000000..d767a99d --- /dev/null +++ b/test_common/harness/typeWrappers.h @@ -0,0 +1,332 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _typeWrappers_h +#define _typeWrappers_h + +#include +#include + +#if !defined(_WIN32) +#include +#endif + +#include "compat.h" +#include +#include "mt19937.h" +#include "errorHelpers.h" +#include "kernelHelpers.h" + +extern "C" cl_uint gReSeed; +extern "C" cl_uint gRandomSeed; + +/* cl_context wrapper */ + +class clContextWrapper +{ + public: + clContextWrapper() { mContext = NULL; } + clContextWrapper( cl_context program ) { mContext = program; } + ~clContextWrapper() { if( mContext != NULL ) clReleaseContext( mContext ); } + + clContextWrapper & operator=( const cl_context &rhs ) { mContext = rhs; return *this; } + operator cl_context() const { return mContext; } + + cl_context * operator&() { return &mContext; } + + bool operator==( const cl_context &rhs ) { return mContext == rhs; } + + protected: + + cl_context mContext; +}; + +/* cl_program wrapper */ + +class clProgramWrapper +{ + public: + clProgramWrapper() { mProgram = NULL; } + clProgramWrapper( cl_program program ) { mProgram = program; } + ~clProgramWrapper() { if( mProgram != NULL ) clReleaseProgram( mProgram ); } + + clProgramWrapper & operator=( const cl_program &rhs ) { mProgram = rhs; return *this; } + operator cl_program() const { return mProgram; } + + cl_program * operator&() { return &mProgram; } + + bool operator==( const cl_program &rhs ) { return mProgram == rhs; } + + protected: + + cl_program mProgram; +}; + +/* cl_kernel wrapper */ + +class clKernelWrapper +{ + public: + clKernelWrapper() { mKernel = NULL; } + clKernelWrapper( cl_kernel kernel ) { mKernel = kernel; } + ~clKernelWrapper() { if( mKernel != NULL ) clReleaseKernel( mKernel ); } + + clKernelWrapper & operator=( const cl_kernel &rhs ) { mKernel = rhs; return *this; } + operator cl_kernel() const { return mKernel; } + + cl_kernel * operator&() { return &mKernel; } + + bool operator==( const cl_kernel &rhs ) { return mKernel == rhs; } + + protected: + + cl_kernel mKernel; +}; + +/* cl_mem (stream) wrapper */ + +class clMemWrapper +{ + public: + clMemWrapper() { mMem = NULL; } + clMemWrapper( cl_mem mem ) { mMem = mem; } + ~clMemWrapper() { if( mMem != NULL ) clReleaseMemObject( mMem ); } + + clMemWrapper & operator=( const cl_mem &rhs ) { mMem = rhs; return *this; } + operator cl_mem() const { return mMem; } + + cl_mem * operator&() { return &mMem; } + + bool operator==( const cl_mem &rhs ) { return mMem == rhs; } + + protected: + + cl_mem mMem; +}; + +class clProtectedImage +{ + public: + clProtectedImage() { image = NULL; backingStore = NULL; } + clProtectedImage( cl_context context, cl_mem_flags flags, const cl_image_format *fmt, size_t width, cl_int *errcode_ret ); + clProtectedImage( cl_context context, cl_mem_flags flags, const cl_image_format *fmt, size_t width, size_t height, cl_int *errcode_ret ); + clProtectedImage( cl_context context, cl_mem_flags flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth, cl_int *errcode_ret ); + clProtectedImage( cl_context context, cl_mem_object_type imageType, cl_mem_flags flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth, size_t arraySize, cl_int *errcode_ret ); + ~clProtectedImage() + { + if( image != NULL ) + clReleaseMemObject( image ); + +#if defined( __APPLE__ ) + if(backingStore) + munmap(backingStore, backingStoreSize); +#endif + } + + cl_int Create( cl_context context, cl_mem_flags flags, const cl_image_format *fmt, size_t width ); + cl_int Create( cl_context context, cl_mem_flags flags, const cl_image_format *fmt, size_t width, size_t height ); + cl_int Create( cl_context context, cl_mem_flags flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth ); + cl_int Create( cl_context context, cl_mem_object_type imageType, cl_mem_flags flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth, size_t arraySize ); + + clProtectedImage & operator=( const cl_mem &rhs ) { image = rhs; backingStore = NULL; return *this; } + operator cl_mem() { return image; } + + cl_mem * operator&() { return ℑ } + + bool operator==( const cl_mem &rhs ) { return image == rhs; } + + protected: + void *backingStore; + size_t backingStoreSize; + cl_mem image; +}; + +/* cl_command_queue wrapper */ +class clCommandQueueWrapper +{ + public: + clCommandQueueWrapper() { mMem = NULL; } + clCommandQueueWrapper( cl_command_queue mem ) { mMem = mem; } + ~clCommandQueueWrapper() { if( mMem != NULL ) { clReleaseCommandQueue( mMem ); } } + + clCommandQueueWrapper & operator=( const cl_command_queue &rhs ) { mMem = rhs; return *this; } + operator cl_command_queue() const { return mMem; } + + cl_command_queue * operator&() { return &mMem; } + + bool operator==( const cl_command_queue &rhs ) { return mMem == rhs; } + + protected: + + cl_command_queue mMem; +}; + +/* cl_sampler wrapper */ +class clSamplerWrapper +{ + public: + clSamplerWrapper() { mMem = NULL; } + clSamplerWrapper( cl_sampler mem ) { mMem = mem; } + ~clSamplerWrapper() { if( mMem != NULL ) clReleaseSampler( mMem ); } + + clSamplerWrapper & operator=( const cl_sampler &rhs ) { mMem = rhs; return *this; } + operator cl_sampler() const { return mMem; } + + cl_sampler * operator&() { return &mMem; } + + bool operator==( const cl_sampler &rhs ) { return mMem == rhs; } + + protected: + + cl_sampler mMem; +}; + +/* cl_event wrapper */ +class clEventWrapper +{ + public: + clEventWrapper() { mMem = NULL; } + clEventWrapper( cl_event mem ) { mMem = mem; } + ~clEventWrapper() { if( mMem != NULL ) clReleaseEvent( mMem ); } + + clEventWrapper & operator=( const cl_event &rhs ) { mMem = rhs; return *this; } + operator cl_event() const { return mMem; } + + cl_event * operator&() { return &mMem; } + + bool operator==( const cl_event &rhs ) { return mMem == rhs; } + + protected: + + cl_event mMem; +}; + +/* Generic protected memory buffer, for verifying access within bounds */ +class clProtectedArray +{ + public: + clProtectedArray(); + clProtectedArray( size_t sizeInBytes ); + virtual ~clProtectedArray(); + + void Allocate( size_t sizeInBytes ); + + operator void *() { return (void *)mValidBuffer; } + operator const void *() const { return (const void *)mValidBuffer; } + + protected: + + char * mBuffer; + char * mValidBuffer; + size_t mRealSize, mRoundedSize; +}; + +class RandomSeed +{ + public: + RandomSeed( cl_uint seed ){ if(seed) log_info( "(seed = %10.10u) ", seed ); mtData = init_genrand(seed); } + ~RandomSeed() + { + if( gReSeed ) + gRandomSeed = genrand_int32( mtData ); + free_mtdata(mtData); + } + + operator MTdata () {return mtData;} + + protected: + MTdata mtData; +}; + + +template class BufferOwningPtr +{ + BufferOwningPtr(BufferOwningPtr const &); // do not implement + void operator=(BufferOwningPtr const &); // do not implement + + void *ptr; + void *map; + size_t mapsize; // Bytes allocated total, pointed to by map. + size_t allocsize; // Bytes allocated in unprotected pages, pointed to by ptr. + bool aligned; + public: + explicit BufferOwningPtr(void *p = 0) : ptr(p), map(0), mapsize(0), allocsize(0), aligned(false) {} + explicit BufferOwningPtr(void *p, void *m, size_t s) + : ptr(p), map(m), mapsize(s), allocsize(0), aligned(false) + { +#if ! defined( __APPLE__ ) + if(m) + { + log_error( "ERROR: unhandled code path. BufferOwningPtr allocated with mapped buffer!" ); + abort(); + } +#endif + } + ~BufferOwningPtr() { + if (map) { +#if defined( __APPLE__ ) + int error = munmap(map, mapsize); + if (error) log_error("WARNING: munmap failed in BufferOwningPtr.\n"); +#endif + } else { + if ( aligned ) + { + align_free(ptr); + } + else + { + free(ptr); + } + } + } + void reset(void *p, void *m = 0, size_t mapsize_ = 0, size_t allocsize_ = 0, bool aligned_ = false) { + if (map){ +#if defined( __APPLE__ ) + int error = munmap(map, mapsize); + if (error) log_error("WARNING: munmap failed in BufferOwningPtr.\n"); +#else + log_error( "ERROR: unhandled code path. BufferOwningPtr reset with mapped buffer!" ); + abort(); +#endif + } else { + if ( aligned ) + { + align_free(ptr); + } + else + { + free(ptr); + } + } + ptr = p; + map = m; + mapsize = mapsize_; + allocsize = (ptr != NULL) ? allocsize_ : 0; // Force allocsize to zero if ptr is NULL. + aligned = aligned_; +#if ! defined( __APPLE__ ) + if(m) + { + log_error( "ERROR: unhandled code path. BufferOwningPtr allocated with mapped buffer!" ); + abort(); + } +#endif + } + operator T*() { return (T*)ptr; } + + size_t getSize() const { return allocsize; }; +}; + +#endif // _typeWrappers_h + diff --git a/test_common/miniz/CMakeLists.txt b/test_common/miniz/CMakeLists.txt new file mode 100644 index 00000000..600db01d --- /dev/null +++ b/test_common/miniz/CMakeLists.txt @@ -0,0 +1,8 @@ +set(TARGET_NAME miniz) + +add_library( + ${TARGET_NAME} + STATIC + miniz.c + miniz.h +) diff --git a/test_common/miniz/miniz.c b/test_common/miniz/miniz.c new file mode 100644 index 00000000..f893bd86 --- /dev/null +++ b/test_common/miniz/miniz.c @@ -0,0 +1,4153 @@ +/* miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing + See "unlicense" statement at the end of this file. + Rich Geldreich , last updated Oct. 13, 2013 + Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt + + Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define + MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros). + + * Change History + 10/13/13 v1.15 r4 - Interim bugfix release while I work on the next major release with Zip64 support (almost there!): + - Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug (thanks kahmyong.moon@hp.com) which could cause locate files to not find files. This bug + would only have occured in earlier versions if you explicitly used this flag, OR if you used mz_zip_extract_archive_file_to_heap() or mz_zip_add_mem_to_archive_file_in_place() + (which used this flag). If you can't switch to v1.15 but want to fix this bug, just remove the uses of this flag from both helper funcs (and of course don't use the flag). + - Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when pUser_read_buf is not NULL and compressed size is > uncompressed size + - Fixing mz_zip_reader_extract_*() funcs so they don't try to extract compressed data from directory entries, to account for weird zipfiles which contain zero-size compressed data on dir entries. + Hopefully this fix won't cause any issues on weird zip archives, because it assumes the low 16-bits of zip external attributes are DOS attributes (which I believe they always are in practice). + - Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the internal attributes, just the filename and external attributes + - mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed + - Added cmake support for Linux builds which builds all the examples, tested with clang v3.3 and gcc v4.6. + - Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti + - Merged MZ_FORCEINLINE fix from hdeanclark + - Fix include before config #ifdef, thanks emil.brink + - Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping (super useful for OpenGL apps), and explicit control over the compression level (so you can + set it to 1 for real-time compression). + - Merged in some compiler fixes from paulharris's github repro. + - Retested this build under Windows (VS 2010, including static analysis), tcc 0.9.26, gcc v4.6 and clang v3.3. + - Added example6.c, which dumps an image of the mandelbrot set to a PNG file. + - Modified example2 to help test the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more. + - In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix possible src file fclose() leak if alignment bytes+local header file write faiiled + - In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader(): Was pushing the wrong central dir header offset, appears harmless in this release, but it became a problem in the zip64 branch + 5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include (thanks fermtect). + 5/19/12 v1.13 - From jason@cornsyrup.org and kelwert@mtu.edu - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit. + - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files. + - Eliminated a bunch of warnings when compiling with GCC 32-bit/64. + - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly + "Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning). + - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64. + - Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test. + - Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives. + - Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.) + - Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself). + 4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's. + level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson for the feedback/bug report. + 5/28/11 v1.11 - Added statement from unlicense.org + 5/27/11 v1.10 - Substantial compressor optimizations: + - Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a + - Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86). + - Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types. + - Refactored the compression code for better readability and maintainability. + - Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large + drop in throughput on some files). + 5/15/11 v1.09 - Initial stable release. + + * Low-level Deflate/Inflate implementation notes: + + Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or + greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses + approximately as well as zlib. + + Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function + coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory + block large enough to hold the entire file. + + The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation. + + * zlib-style API notes: + + miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in + zlib replacement in many apps: + The z_stream struct, optional memory allocation callbacks + deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound + inflateInit/inflateInit2/inflate/inflateEnd + compress, compress2, compressBound, uncompress + CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines. + Supports raw deflate streams or standard zlib streams with adler-32 checking. + + Limitations: + The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries. + I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but + there are no guarantees that miniz.c pulls this off perfectly. + + * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by + Alex Evans. Supports 1-4 bytes/pixel images. + + * ZIP archive API notes: + + The ZIP archive API's where designed with simplicity and efficiency in mind, with just enough abstraction to + get the job done with minimal fuss. There are simple API's to retrieve file information, read files from + existing archives, create new archives, append new files to existing archives, or clone archive data from + one archive to another. It supports archives located in memory or the heap, on disk (using stdio.h), + or you can specify custom file read/write callbacks. + + - Archive reading: Just call this function to read a single file from a disk archive: + + void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, + size_t *pSize, mz_uint zip_flags); + + For more complex cases, use the "mz_zip_reader" functions. Upon opening an archive, the entire central + directory is located and read as-is into memory, and subsequent file access only occurs when reading individual files. + + - Archives file scanning: The simple way is to use this function to scan a loaded archive for a specific file: + + int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); + + The locate operation can optionally check file comments too, which (as one example) can be used to identify + multiple versions of the same file in an archive. This function uses a simple linear search through the central + directory, so it's not very fast. + + Alternately, you can iterate through all the files in an archive (using mz_zip_reader_get_num_files()) and + retrieve detailed info on each file by calling mz_zip_reader_file_stat(). + + - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer immediately writes compressed file data + to disk and builds an exact image of the central directory in memory. The central directory image is written + all at once at the end of the archive file when the archive is finalized. + + The archive writer can optionally align each file's local header and file data to any power of 2 alignment, + which can be useful when the archive will be read from optical media. Also, the writer supports placing + arbitrary data blobs at the very beginning of ZIP archives. Archives written using either feature are still + readable by any ZIP tool. + + - Archive appending: The simple way to add a single file to an archive is to call this function: + + mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, + const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); + + The archive will be created if it doesn't already exist, otherwise it'll be appended to. + Note the appending is done in-place and is not an atomic operation, so if something goes wrong + during the operation it's possible the archive could be left without a central directory (although the local + file headers and file data will be fine, so the archive will be recoverable). + + For more complex archive modification scenarios: + 1. The safest way is to use a mz_zip_reader to read the existing archive, cloning only those bits you want to + preserve into a new archive using using the mz_zip_writer_add_from_zip_reader() function (which compiles the + compressed file data as-is). When you're done, delete the old archive and rename the newly written archive, and + you're done. This is safe but requires a bunch of temporary disk space or heap memory. + + 2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using mz_zip_writer_init_from_reader(), + append new files as needed, then finalize the archive which will write an updated central directory to the + original archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place() does.) There's a + possibility that the archive's central directory could be lost with this method if anything goes wrong, though. + + - ZIP archive support limitations: + No zip64 or spanning support. Extraction functions can only handle unencrypted, stored or deflated files. + Requires streams capable of seeking. + + * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the + below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it. + + * Important: For best perf. be sure to customize the below macros for your target platform: + #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 + #define MINIZ_LITTLE_ENDIAN 1 + #define MINIZ_HAS_64BIT_REGISTERS 1 + + * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before including miniz.c to ensure miniz + uses the 64-bit variants: fopen64(), stat64(), etc. Otherwise you won't be able to process large files + (i.e. 32-bit stat() fails for me on files > 0x7FFFFFFF bytes). +*/ + +#include "miniz.h" + +typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1]; +typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1]; +typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1]; + +#include +#include + +#define MZ_ASSERT(x) assert(x) + +#ifdef MINIZ_NO_MALLOC + #define MZ_MALLOC(x) NULL + #define MZ_FREE(x) (void)x, ((void)0) + #define MZ_REALLOC(p, x) NULL +#else + #define MZ_MALLOC(x) malloc(x) + #define MZ_FREE(x) free(x) + #define MZ_REALLOC(p, x) realloc(p, x) +#endif + +#define MZ_MAX(a,b) (((a)>(b))?(a):(b)) +#define MZ_MIN(a,b) (((a)<(b))?(a):(b)) +#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj)) + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + #define MZ_READ_LE16(p) *((const mz_uint16 *)(p)) + #define MZ_READ_LE32(p) *((const mz_uint32 *)(p)) +#else + #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U)) + #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U)) +#endif + +#ifdef _MSC_VER + #define MZ_FORCEINLINE __forceinline +#elif defined(__GNUC__) + #define MZ_FORCEINLINE inline __attribute__((__always_inline__)) +#else + #define MZ_FORCEINLINE inline +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +// ------------------- zlib-style API's + +mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) +{ + mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552; + if (!ptr) return MZ_ADLER32_INIT; + while (buf_len) { + for (i = 0; i + 7 < block_len; i += 8, ptr += 8) { + s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; + s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; + } + for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; + s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; + } + return (s2 << 16) + s1; +} + +// Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ +mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) +{ + static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; + mz_uint32 crcu32 = (mz_uint32)crc; + if (!ptr) return MZ_CRC32_INIT; + crcu32 = ~crcu32; while (buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; } + return ~crcu32; +} + +void mz_free(void *p) +{ + MZ_FREE(p); +} + +#ifndef MINIZ_NO_ZLIB_APIS + +static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque, (void)items, (void)size; return MZ_MALLOC(items * size); } +static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); } +static void *def_realloc_func(void *opaque, void *address, size_t items, size_t size) { (void)opaque, (void)address, (void)items, (void)size; return MZ_REALLOC(address, items * size); } + +const char *mz_version(void) +{ + return MZ_VERSION; +} + +int mz_deflateInit(mz_streamp pStream, int level) +{ + return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY); +} + +int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy) +{ + tdefl_compressor *pComp; + mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy); + + if (!pStream) return MZ_STREAM_ERROR; + if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR; + + pStream->data_type = 0; + pStream->adler = MZ_ADLER32_INIT; + pStream->msg = NULL; + pStream->reserved = 0; + pStream->total_in = 0; + pStream->total_out = 0; + if (!pStream->zalloc) pStream->zalloc = def_alloc_func; + if (!pStream->zfree) pStream->zfree = def_free_func; + + pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor)); + if (!pComp) + return MZ_MEM_ERROR; + + pStream->state = (struct mz_internal_state *)pComp; + + if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) + { + mz_deflateEnd(pStream); + return MZ_PARAM_ERROR; + } + + return MZ_OK; +} + +int mz_deflateReset(mz_streamp pStream) +{ + if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR; + pStream->total_in = pStream->total_out = 0; + tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags); + return MZ_OK; +} + +int mz_deflate(mz_streamp pStream, int flush) +{ + size_t in_bytes, out_bytes; + mz_ulong orig_total_in, orig_total_out; + int mz_status = MZ_OK; + + if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR; + if (!pStream->avail_out) return MZ_BUF_ERROR; + + if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; + + if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE) + return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR; + + orig_total_in = pStream->total_in; orig_total_out = pStream->total_out; + for ( ; ; ) + { + tdefl_status defl_status; + in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; + + defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush); + pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state); + + pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; + pStream->total_out += (mz_uint)out_bytes; + + if (defl_status < 0) + { + mz_status = MZ_STREAM_ERROR; + break; + } + else if (defl_status == TDEFL_STATUS_DONE) + { + mz_status = MZ_STREAM_END; + break; + } + else if (!pStream->avail_out) + break; + else if ((!pStream->avail_in) && (flush != MZ_FINISH)) + { + if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out)) + break; + return MZ_BUF_ERROR; // Can't make forward progress without some input. + } + } + return mz_status; +} + +int mz_deflateEnd(mz_streamp pStream) +{ + if (!pStream) return MZ_STREAM_ERROR; + if (pStream->state) + { + pStream->zfree(pStream->opaque, pStream->state); + pStream->state = NULL; + } + return MZ_OK; +} + +mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) +{ + (void)pStream; + // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) + return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5); +} + +int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level) +{ + int status; + mz_stream stream; + memset(&stream, 0, sizeof(stream)); + + // In case mz_ulong is 64-bits (argh I hate longs). + if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; + + stream.next_in = pSource; + stream.avail_in = (mz_uint32)source_len; + stream.next_out = pDest; + stream.avail_out = (mz_uint32)*pDest_len; + + status = mz_deflateInit(&stream, level); + if (status != MZ_OK) return status; + + status = mz_deflate(&stream, MZ_FINISH); + if (status != MZ_STREAM_END) + { + mz_deflateEnd(&stream); + return (status == MZ_OK) ? MZ_BUF_ERROR : status; + } + + *pDest_len = stream.total_out; + return mz_deflateEnd(&stream); +} + +int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) +{ + return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION); +} + +mz_ulong mz_compressBound(mz_ulong source_len) +{ + return mz_deflateBound(NULL, source_len); +} + +typedef struct +{ + tinfl_decompressor m_decomp; + mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits; + mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]; + tinfl_status m_last_status; +} inflate_state; + +int mz_inflateInit2(mz_streamp pStream, int window_bits) +{ + inflate_state *pDecomp; + if (!pStream) return MZ_STREAM_ERROR; + if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR; + + pStream->data_type = 0; + pStream->adler = 0; + pStream->msg = NULL; + pStream->total_in = 0; + pStream->total_out = 0; + pStream->reserved = 0; + if (!pStream->zalloc) pStream->zalloc = def_alloc_func; + if (!pStream->zfree) pStream->zfree = def_free_func; + + pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state)); + if (!pDecomp) return MZ_MEM_ERROR; + + pStream->state = (struct mz_internal_state *)pDecomp; + + tinfl_init(&pDecomp->m_decomp); + pDecomp->m_dict_ofs = 0; + pDecomp->m_dict_avail = 0; + pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; + pDecomp->m_first_call = 1; + pDecomp->m_has_flushed = 0; + pDecomp->m_window_bits = window_bits; + + return MZ_OK; +} + +int mz_inflateInit(mz_streamp pStream) +{ + return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS); +} + +int mz_inflate(mz_streamp pStream, int flush) +{ + inflate_state* pState; + mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32; + size_t in_bytes, out_bytes, orig_avail_in; + tinfl_status status; + + if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR; + if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; + if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; + + pState = (inflate_state*)pStream->state; + if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER; + orig_avail_in = pStream->avail_in; + + first_call = pState->m_first_call; pState->m_first_call = 0; + if (pState->m_last_status < 0) return MZ_DATA_ERROR; + + if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; + pState->m_has_flushed |= (flush == MZ_FINISH); + + if ((flush == MZ_FINISH) && (first_call)) + { + // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. + decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; + in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags); + pState->m_last_status = status; + pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tinfl_get_adler32(&pState->m_decomp); + pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes; + + if (status < 0) + return MZ_DATA_ERROR; + else if (status != TINFL_STATUS_DONE) + { + pState->m_last_status = TINFL_STATUS_FAILED; + return MZ_BUF_ERROR; + } + return MZ_STREAM_END; + } + // flush != MZ_FINISH then we must assume there's more input. + if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT; + + if (pState->m_dict_avail) + { + n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; + pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; + } + + for ( ; ; ) + { + in_bytes = pStream->avail_in; + out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs; + + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags); + pState->m_last_status = status; + + pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp); + + pState->m_dict_avail = (mz_uint)out_bytes; + + n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; + pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + + if (status < 0) + return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). + else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in)) + return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. + else if (flush == MZ_FINISH) + { + // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. + if (status == TINFL_STATUS_DONE) + return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END; + // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. + else if (!pStream->avail_out) + return MZ_BUF_ERROR; + } + else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail)) + break; + } + + return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; +} + +int mz_inflateEnd(mz_streamp pStream) +{ + if (!pStream) + return MZ_STREAM_ERROR; + if (pStream->state) + { + pStream->zfree(pStream->opaque, pStream->state); + pStream->state = NULL; + } + return MZ_OK; +} + +int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) +{ + mz_stream stream; + int status; + memset(&stream, 0, sizeof(stream)); + + // In case mz_ulong is 64-bits (argh I hate longs). + if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; + + stream.next_in = pSource; + stream.avail_in = (mz_uint32)source_len; + stream.next_out = pDest; + stream.avail_out = (mz_uint32)*pDest_len; + + status = mz_inflateInit(&stream); + if (status != MZ_OK) + return status; + + status = mz_inflate(&stream, MZ_FINISH); + if (status != MZ_STREAM_END) + { + mz_inflateEnd(&stream); + return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status; + } + *pDest_len = stream.total_out; + + return mz_inflateEnd(&stream); +} + +const char *mz_error(int err) +{ + static struct { int m_err; const char *m_pDesc; } s_error_descs[] = + { + { MZ_OK, "" }, + { MZ_STREAM_END, "stream end" }, + { MZ_NEED_DICT, "need dictionary" }, + { MZ_ERRNO, "file error" }, + { MZ_STREAM_ERROR, "stream error" }, + { MZ_DATA_ERROR, "data error" }, + { MZ_MEM_ERROR, "out of memory" }, + { MZ_BUF_ERROR, "buf error" }, + { MZ_VERSION_ERROR, "version error" }, + { MZ_PARAM_ERROR, "parameter error" } + }; + mz_uint i; + for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) + if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc; + return NULL; +} + +#endif //MINIZ_NO_ZLIB_APIS + +// ------------------- Low-level Decompression (completely independent from all compression API's) + +#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l) +#define TINFL_MEMSET(p, c, l) memset(p, c, l) + +#define TINFL_CR_BEGIN switch(r->m_state) { case 0: +#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END +#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END +#define TINFL_CR_FINISH } + +// TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never +// reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario. +#define TINFL_GET_BYTE(state_index, c) do { \ + if (pIn_buf_cur >= pIn_buf_end) { \ + for ( ; ; ) { \ + if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \ + TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \ + if (pIn_buf_cur < pIn_buf_end) { \ + c = *pIn_buf_cur++; \ + break; \ + } \ + } else { \ + c = 0; \ + break; \ + } \ + } \ + } else c = *pIn_buf_cur++; } MZ_MACRO_END + +#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n)) +#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END +#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END + +// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. +// It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a +// Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the +// bit buffer contains >=15 bits (deflate's max. Huffman code size). +#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \ + do { \ + temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \ + if (temp >= 0) { \ + code_len = temp >> 9; \ + if ((code_len) && (num_bits >= code_len)) \ + break; \ + } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \ + code_len = TINFL_FAST_LOOKUP_BITS; \ + do { \ + temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ + } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \ + } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \ + } while (num_bits < 15); + +// TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read +// beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully +// decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. +// The slow path is only executed at the very end of the input buffer. +#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \ + int temp; mz_uint code_len, c; \ + if (num_bits < 15) { \ + if ((pIn_buf_end - pIn_buf_cur) < 2) { \ + TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \ + } else { \ + bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \ + } \ + } \ + if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \ + code_len = temp >> 9, temp &= 511; \ + else { \ + code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \ + } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END + +tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags) +{ + static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 }; + static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + static const int s_min_table_sizes[3] = { 257, 1, 4 }; + + tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf; + const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size; + mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size; + size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start; + + // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). + if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; } + + num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start; + TINFL_CR_BEGIN + + bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1; + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) + { + TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1); + counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); + if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4))))); + if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); } + } + + do + { + TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1; + if (r->m_type == 0) + { + TINFL_SKIP_BITS(5, num_bits & 7); + for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); } + if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); } + while ((counter) && (num_bits)) + { + TINFL_GET_BITS(51, dist, 8); + while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); } + *pOut_buf_cur++ = (mz_uint8)dist; + counter--; + } + while (counter) + { + size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); } + while (pIn_buf_cur >= pIn_buf_end) + { + if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) + { + TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT); + } + else + { + TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED); + } + } + n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter); + TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n; + } + } + else if (r->m_type == 3) + { + TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); + } + else + { + if (r->m_type == 1) + { + mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i; + r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32); + for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8; + } + else + { + for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; } + MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; } + r->m_table_sizes[2] = 19; + } + for ( ; (int)r->m_type >= 0; r->m_type--) + { + int tree_next, tree_cur; tinfl_huff_table *pTable; + mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree); + for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++; + used_syms = 0, total = 0; next_code[0] = next_code[1] = 0; + for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); } + if ((65536 != total) && (used_syms > 1)) + { + TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); + } + for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) + { + mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue; + cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1); + if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; } + if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } + rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); + for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) + { + tree_cur -= ((rev_code >>= 1) & 1); + if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1]; + } + tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index; + } + if (r->m_type == 2) + { + for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); ) + { + mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; } + if ((dist == 16) && (!counter)) + { + TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); + } + num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16]; + TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s; + } + if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) + { + TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); + } + TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]); + } + } + for ( ; ; ) + { + mz_uint8 *pSrc; + for ( ; ; ) + { + if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) + { + TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]); + if (counter >= 256) + break; + while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); } + *pOut_buf_cur++ = (mz_uint8)counter; + } + else + { + int sym2; mz_uint code_len; +#if TINFL_USE_64BIT_BITBUF + if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; } +#else + if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } +#endif + if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + code_len = sym2 >> 9; + else + { + code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); + } + counter = sym2; bit_buf >>= code_len; num_bits -= code_len; + if (counter & 256) + break; + +#if !TINFL_USE_64BIT_BITBUF + if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } +#endif + if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + code_len = sym2 >> 9; + else + { + code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); + } + bit_buf >>= code_len; num_bits -= code_len; + + pOut_buf_cur[0] = (mz_uint8)counter; + if (sym2 & 256) + { + pOut_buf_cur++; + counter = sym2; + break; + } + pOut_buf_cur[1] = (mz_uint8)sym2; + pOut_buf_cur += 2; + } + } + if ((counter &= 511) == 256) break; + + num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257]; + if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; } + + TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]); + num_extra = s_dist_extra[dist]; dist = s_dist_base[dist]; + if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; } + + dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; + if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) + { + TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); + } + + pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask); + + if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) + { + while (counter--) + { + while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); } + *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask]; + } + continue; + } +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES + else if ((counter >= 9) && (counter <= dist)) + { + const mz_uint8 *pSrc_end = pSrc + (counter & ~7); + do + { + ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0]; + ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1]; + pOut_buf_cur += 8; + } while ((pSrc += 8) < pSrc_end); + if ((counter &= 7) < 3) + { + if (counter) + { + pOut_buf_cur[0] = pSrc[0]; + if (counter > 1) + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + continue; + } + } +#endif + do + { + pOut_buf_cur[0] = pSrc[0]; + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur[2] = pSrc[2]; + pOut_buf_cur += 3; pSrc += 3; + } while ((int)(counter -= 3) > 2); + if ((int)counter > 0) + { + pOut_buf_cur[0] = pSrc[0]; + if ((int)counter > 1) + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + } + } + } while (!(r->m_final & 1)); + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) + { + TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; } + } + TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE); + TINFL_CR_FINISH + +common_exit: + r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start; + *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next; + if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0)) + { + const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size; + mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552; + while (buf_len) + { + for (i = 0; i + 7 < block_len; i += 8, ptr += 8) + { + s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; + s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; + } + for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; + s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; + } + r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH; + } + return status; +} + +// Higher level helper functions. +void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) +{ + tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0; + *pOut_len = 0; + tinfl_init(&decomp); + for ( ; ; ) + { + size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity; + tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size, + (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) + { + MZ_FREE(pBuf); *pOut_len = 0; return NULL; + } + src_buf_ofs += src_buf_size; + *pOut_len += dst_buf_size; + if (status == TINFL_STATUS_DONE) break; + new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128; + pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); + if (!pNew_buf) + { + MZ_FREE(pBuf); *pOut_len = 0; return NULL; + } + pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity; + } + return pBuf; +} + +size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) +{ + tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp); + status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len; +} + +int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +{ + int result = 0; + tinfl_decompressor decomp; + mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0; + if (!pDict) + return TINFL_STATUS_FAILED; + tinfl_init(&decomp); + for ( ; ; ) + { + size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; + tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, + (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); + in_buf_ofs += in_buf_size; + if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) + break; + if (status != TINFL_STATUS_HAS_MORE_OUTPUT) + { + result = (status == TINFL_STATUS_DONE); + break; + } + dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1); + } + MZ_FREE(pDict); + *pIn_buf_size = in_buf_ofs; + return result; +} + +// ------------------- Low-level Compression (independent from all decompression API's) + +// Purposely making these tables static for faster init and thread safety. +static const mz_uint16 s_tdefl_len_sym[256] = { + 257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272, + 273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276, + 277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278, + 279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280, + 281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281, + 282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282, + 283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283, + 284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 }; + +static const mz_uint8 s_tdefl_len_extra[256] = { + 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0 }; + +static const mz_uint8 s_tdefl_small_dist_sym[512] = { + 0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 }; + +static const mz_uint8 s_tdefl_small_dist_extra[512] = { + 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7 }; + +static const mz_uint8 s_tdefl_large_dist_sym[128] = { + 0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26, + 26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28, + 28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 }; + +static const mz_uint8 s_tdefl_large_dist_extra[128] = { + 0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 }; + +// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. +typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq; +static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1) +{ + mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist); + for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; } + while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--; + for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) + { + const mz_uint32* pHist = &hist[pass << 8]; + mz_uint offsets[256], cur_ofs = 0; + for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; } + for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; + { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; } + } + return pCur_syms; +} + +// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. +static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) +{ + int root, leaf, next, avbl, used, dpth; + if (n==0) return; else if (n==1) { A[0].m_key = 1; return; } + A[0].m_key += A[1].m_key; root = 0; leaf = 2; + for (next=1; next < n-1; next++) + { + if (leaf>=n || A[root].m_key=n || (root=0; next--) A[next].m_key = A[A[next].m_key].m_key+1; + avbl = 1; used = dpth = 0; root = n-2; next = n-1; + while (avbl>0) + { + while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; } + while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; } + avbl = 2*used; dpth++; used = 0; + } +} + +// Limits canonical Huffman code table's max code size. +enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 }; +static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size) +{ + int i; mz_uint32 total = 0; if (code_list_len <= 1) return; + for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i]; + for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i)); + while (total != (1UL << max_code_size)) + { + pNum_codes[max_code_size]--; + for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; } + total--; + } +} + +static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table) +{ + int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes); + if (static_table) + { + for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++; + } + else + { + tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; + int num_used_syms = 0; + const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0]; + for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; } + + pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); + + for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++; + + tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit); + + MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]); + for (i = 1, j = num_used_syms; i <= code_size_limit; i++) + for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i); + } + + next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1); + + for (i = 0; i < table_len; i++) + { + mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue; + code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1); + d->m_huff_codes[table_num][i] = (mz_uint16)rev_code; + } +} + +#define TDEFL_PUT_BITS(b, l) do { \ + mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \ + d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \ + while (d->m_bits_in >= 8) { \ + if (d->m_pOutput_buf < d->m_pOutput_buf_end) \ + *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \ + d->m_bit_buffer >>= 8; \ + d->m_bits_in -= 8; \ + } \ +} MZ_MACRO_END + +#define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \ + if (rle_repeat_count < 3) { \ + d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \ + while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \ + } else { \ + d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \ +} rle_repeat_count = 0; } } + +#define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \ + if (rle_z_count < 3) { \ + d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \ + } else if (rle_z_count <= 10) { \ + d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \ + } else { \ + d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \ +} rle_z_count = 0; } } + +static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + +static void tdefl_start_dynamic_block(tdefl_compressor *d) +{ + int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index; + mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF; + + d->m_huff_count[0][256] = 1; + + tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE); + tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE); + + for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break; + for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break; + + memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes); + memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes); + total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0; + + memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); + for (i = 0; i < total_code_sizes_to_pack; i++) + { + mz_uint8 code_size = code_sizes_to_pack[i]; + if (!code_size) + { + TDEFL_RLE_PREV_CODE_SIZE(); + if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); } + } + else + { + TDEFL_RLE_ZERO_CODE_SIZE(); + if (code_size != prev_code_size) + { + TDEFL_RLE_PREV_CODE_SIZE(); + d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size; + } + else if (++rle_repeat_count == 6) + { + TDEFL_RLE_PREV_CODE_SIZE(); + } + } + prev_code_size = code_size; + } + if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); } + + tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE); + + TDEFL_PUT_BITS(2, 2); + + TDEFL_PUT_BITS(num_lit_codes - 257, 5); + TDEFL_PUT_BITS(num_dist_codes - 1, 5); + + for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break; + num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4); + for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3); + + for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; ) + { + mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); + TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]); + if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]); + } +} + +static void tdefl_start_static_block(tdefl_compressor *d) +{ + mz_uint i; + mz_uint8 *p = &d->m_huff_code_sizes[0][0]; + + for (i = 0; i <= 143; ++i) *p++ = 8; + for ( ; i <= 255; ++i) *p++ = 9; + for ( ; i <= 279; ++i) *p++ = 7; + for ( ; i <= 287; ++i) *p++ = 8; + + memset(d->m_huff_code_sizes[1], 5, 32); + + tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE); + tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE); + + TDEFL_PUT_BITS(1, 2); +} + +static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS +static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) +{ + mz_uint flags; + mz_uint8 *pLZ_codes; + mz_uint8 *pOutput_buf = d->m_pOutput_buf; + mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf; + mz_uint64 bit_buffer = d->m_bit_buffer; + mz_uint bits_in = d->m_bits_in; + +#define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); } + + flags = 1; + for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) + { + if (flags == 1) + flags = *pLZ_codes++ | 0x100; + + if (flags & 1) + { + mz_uint s0, s1, n0, n1, sym, num_extra_bits; + mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3; + + MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); + + // This sequence coaxes MSVC into using cmov's vs. jmp's. + s0 = s_tdefl_small_dist_sym[match_dist & 511]; + n0 = s_tdefl_small_dist_extra[match_dist & 511]; + s1 = s_tdefl_large_dist_sym[match_dist >> 8]; + n1 = s_tdefl_large_dist_extra[match_dist >> 8]; + sym = (match_dist < 512) ? s0 : s1; + num_extra_bits = (match_dist < 512) ? n0 : n1; + + MZ_ASSERT(d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); + } + else + { + mz_uint lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + + if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) + { + flags >>= 1; + lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + + if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) + { + flags >>= 1; + lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + } + } + } + + if (pOutput_buf >= d->m_pOutput_buf_end) + return MZ_FALSE; + + *(mz_uint64*)pOutput_buf = bit_buffer; + pOutput_buf += (bits_in >> 3); + bit_buffer >>= (bits_in & ~7); + bits_in &= 7; + } + +#undef TDEFL_PUT_BITS_FAST + + d->m_pOutput_buf = pOutput_buf; + d->m_bits_in = 0; + d->m_bit_buffer = 0; + + while (bits_in) + { + mz_uint32 n = MZ_MIN(bits_in, 16); + TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n); + bit_buffer >>= n; + bits_in -= n; + } + + TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); + + return (d->m_pOutput_buf < d->m_pOutput_buf_end); +} +#else +static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) +{ + mz_uint flags; + mz_uint8 *pLZ_codes; + + flags = 1; + for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1) + { + if (flags == 1) + flags = *pLZ_codes++ | 0x100; + if (flags & 1) + { + mz_uint sym, num_extra_bits; + mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3; + + MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); + + if (match_dist < 512) + { + sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist]; + } + else + { + sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8]; + } + MZ_ASSERT(d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); + } + else + { + mz_uint lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + } + } + + TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); + + return (d->m_pOutput_buf < d->m_pOutput_buf_end); +} +#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS + +static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) +{ + if (static_block) + tdefl_start_static_block(d); + else + tdefl_start_dynamic_block(d); + return tdefl_compress_lz_codes(d); +} + +static int tdefl_flush_block(tdefl_compressor *d, int flush) +{ + mz_uint saved_bit_buf, saved_bits_in; + mz_uint8 *pSaved_output_buf; + mz_bool comp_block_succeeded = MZ_FALSE; + int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; + mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf; + + d->m_pOutput_buf = pOutput_buf_start; + d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; + + MZ_ASSERT(!d->m_output_flush_remaining); + d->m_output_flush_ofs = 0; + d->m_output_flush_remaining = 0; + + *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left); + d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); + + if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) + { + TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8); + } + + TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1); + + pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in; + + if (!use_raw_block) + comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48)); + + // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. + if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) && + ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) ) + { + mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; + TDEFL_PUT_BITS(0, 2); + if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } + for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) + { + TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); + } + for (i = 0; i < d->m_total_lz_bytes; ++i) + { + TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8); + } + } + // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. + else if (!comp_block_succeeded) + { + d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; + tdefl_compress_block(d, MZ_TRUE); + } + + if (flush) + { + if (flush == TDEFL_FINISH) + { + if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } + if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } } + } + else + { + mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); } + } + } + + MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end); + + memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); + memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); + + d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++; + + if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) + { + if (d->m_pPut_buf_func) + { + *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; + if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) + return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); + } + else if (pOutput_buf_start == d->m_output_buf) + { + int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs)); + memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy); + d->m_out_buf_ofs += bytes_to_copy; + if ((n -= bytes_to_copy) != 0) + { + d->m_output_flush_ofs = bytes_to_copy; + d->m_output_flush_remaining = n; + } + } + else + { + d->m_out_buf_ofs += n; + } + } + + return d->m_output_flush_remaining; +} + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES +#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p) +static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) +{ + mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; + mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; + const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q; + mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s); + MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; + for ( ; ; ) + { + for ( ; ; ) + { + if (--num_probes_left == 0) return; + #define TDEFL_PROBE \ + next_probe_pos = d->m_next[probe_pos]; \ + if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ + probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ + if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break; + TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; + } + if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32; + do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && + (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); + if (!probe_len) + { + *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break; + } + else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len) + { + *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break; + c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]); + } + } +} +#else +static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) +{ + mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; + mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; + const mz_uint8 *s = d->m_dict + pos, *p, *q; + mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1]; + MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; + for ( ; ; ) + { + for ( ; ; ) + { + if (--num_probes_left == 0) return; + #define TDEFL_PROBE \ + next_probe_pos = d->m_next[probe_pos]; \ + if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ + probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ + if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break; + TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; + } + if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break; + if (probe_len > match_len) + { + *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return; + c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1]; + } + } +} +#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN +static mz_bool tdefl_compress_fast(tdefl_compressor *d) +{ + // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. + mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left; + mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags; + mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; + + while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) + { + const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; + mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; + mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size); + d->m_src_buf_left -= num_bytes_to_process; + lookahead_size += num_bytes_to_process; + + while (num_bytes_to_process) + { + mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process); + memcpy(d->m_dict + dst_pos, d->m_pSrc, n); + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); + d->m_pSrc += n; + dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; + num_bytes_to_process -= n; + } + + dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size); + if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break; + + while (lookahead_size >= 4) + { + mz_uint cur_match_dist, cur_match_len = 1; + mz_uint8 *pCur_dict = d->m_dict + cur_pos; + mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF; + mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK; + mz_uint probe_pos = d->m_hash[hash]; + d->m_hash[hash] = (mz_uint16)lookahead_pos; + + if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) + { + const mz_uint16 *p = (const mz_uint16 *)pCur_dict; + const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos); + mz_uint32 probe_len = 32; + do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && + (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); + cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q); + if (!probe_len) + cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; + + if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U))) + { + cur_match_len = 1; + *pLZ_code_buf++ = (mz_uint8)first_trigram; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + d->m_huff_count[0][(mz_uint8)first_trigram]++; + } + else + { + mz_uint32 s0, s1; + cur_match_len = MZ_MIN(cur_match_len, lookahead_size); + + MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE)); + + cur_match_dist--; + + pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); + *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; + pLZ_code_buf += 3; + *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); + + s0 = s_tdefl_small_dist_sym[cur_match_dist & 511]; + s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8]; + d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++; + + d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++; + } + } + else + { + *pLZ_code_buf++ = (mz_uint8)first_trigram; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + d->m_huff_count[0][(mz_uint8)first_trigram]++; + } + + if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } + + total_lz_bytes += cur_match_len; + lookahead_pos += cur_match_len; + dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE); + cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK; + MZ_ASSERT(lookahead_size >= cur_match_len); + lookahead_size -= cur_match_len; + + if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) + { + int n; + d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; + } + } + + while (lookahead_size) + { + mz_uint8 lit = d->m_dict[cur_pos]; + + total_lz_bytes++; + *pLZ_code_buf++ = lit; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } + + d->m_huff_count[0][lit]++; + + lookahead_pos++; + dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE); + cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; + lookahead_size--; + + if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) + { + int n; + d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; + } + } + } + + d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; + return MZ_TRUE; +} +#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + +static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit) +{ + d->m_total_lz_bytes++; + *d->m_pLZ_code_buf++ = lit; + *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } + d->m_huff_count[0][lit]++; +} + +static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) +{ + mz_uint32 s0, s1; + + MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE)); + + d->m_total_lz_bytes += match_len; + + d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN); + + match_dist -= 1; + d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF); + d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3; + + *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } + + s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127]; + d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; + + if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; +} + +static mz_bool tdefl_compress_normal(tdefl_compressor *d) +{ + const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left; + tdefl_flush flush = d->m_flush; + + while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) + { + mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; + // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. + if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) + { + mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2; + mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]; + mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size); + const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process; + src_buf_left -= num_bytes_to_process; + d->m_lookahead_size += num_bytes_to_process; + while (pSrc != pSrc_end) + { + mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; + hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); + d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); + dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++; + } + } + else + { + while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) + { + mz_uint8 c = *pSrc++; + mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; + src_buf_left--; + d->m_dict[dst_pos] = c; + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; + if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) + { + mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2; + mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); + d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); + } + } + } + d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size); + if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) + break; + + // Simple lazy/greedy parsing state machine. + len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; + if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) + { + if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) + { + mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; + cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; } + if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1; + } + } + else + { + tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len); + } + if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) + { + cur_match_dist = cur_match_len = 0; + } + if (d->m_saved_match_len) + { + if (cur_match_len > d->m_saved_match_len) + { + tdefl_record_literal(d, (mz_uint8)d->m_saved_lit); + if (cur_match_len >= 128) + { + tdefl_record_match(d, cur_match_len, cur_match_dist); + d->m_saved_match_len = 0; len_to_move = cur_match_len; + } + else + { + d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; + } + } + else + { + tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist); + len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0; + } + } + else if (!cur_match_dist) + tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]); + else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) + { + tdefl_record_match(d, cur_match_len, cur_match_dist); + len_to_move = cur_match_len; + } + else + { + d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; + } + // Move the lookahead forward by len_to_move bytes. + d->m_lookahead_pos += len_to_move; + MZ_ASSERT(d->m_lookahead_size >= len_to_move); + d->m_lookahead_size -= len_to_move; + d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE); + // Check if it's time to flush the current LZ codes to the internal output buffer. + if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || + ( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) ) + { + int n; + d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + } + } + + d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; + return MZ_TRUE; +} + +static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) +{ + if (d->m_pIn_buf_size) + { + *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; + } + + if (d->m_pOut_buf_size) + { + size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining); + memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n); + d->m_output_flush_ofs += (mz_uint)n; + d->m_output_flush_remaining -= (mz_uint)n; + d->m_out_buf_ofs += n; + + *d->m_pOut_buf_size = d->m_out_buf_ofs; + } + + return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY; +} + +tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush) +{ + if (!d) + { + if (pIn_buf_size) *pIn_buf_size = 0; + if (pOut_buf_size) *pOut_buf_size = 0; + return TDEFL_STATUS_BAD_PARAM; + } + + d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size; + d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size; + d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0; + d->m_out_buf_ofs = 0; + d->m_flush = flush; + + if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) || + (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) ) + { + if (pIn_buf_size) *pIn_buf_size = 0; + if (pOut_buf_size) *pOut_buf_size = 0; + return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); + } + d->m_wants_to_finish |= (flush == TDEFL_FINISH); + + if ((d->m_output_flush_remaining) || (d->m_finished)) + return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && + ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) && + ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0)) + { + if (!tdefl_compress_fast(d)) + return d->m_prev_return_status; + } + else +#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + { + if (!tdefl_compress_normal(d)) + return d->m_prev_return_status; + } + + if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) + d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf); + + if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) + { + if (tdefl_flush_block(d, flush) < 0) + return d->m_prev_return_status; + d->m_finished = (flush == TDEFL_FINISH); + if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; } + } + + return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); +} + +tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush) +{ + MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); +} + +tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +{ + d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user; + d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; + d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; + if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash); + d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0; + d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0; + d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; + d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY; + d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1; + d->m_pIn_buf = NULL; d->m_pOut_buf = NULL; + d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL; + d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0; + memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); + memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); + return TDEFL_STATUS_OKAY; +} + +tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) +{ + return d->m_prev_return_status; +} + +mz_uint32 tdefl_get_adler32(tdefl_compressor *d) +{ + return d->m_adler32; +} + +mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +{ + tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE; + pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE; + succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY); + succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE); + MZ_FREE(pComp); return succeeded; +} + +typedef struct +{ + size_t m_size, m_capacity; + mz_uint8 *m_pBuf; + mz_bool m_expandable; +} tdefl_output_buffer; + +static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser) +{ + tdefl_output_buffer *p = (tdefl_output_buffer *)pUser; + size_t new_size = p->m_size + len; + if (new_size > p->m_capacity) + { + size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE; + do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity); + pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE; + p->m_pBuf = pNew_buf; p->m_capacity = new_capacity; + } + memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size; + return MZ_TRUE; +} + +void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) +{ + tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); + if (!pOut_len) return MZ_FALSE; else *pOut_len = 0; + out_buf.m_expandable = MZ_TRUE; + if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL; + *pOut_len = out_buf.m_size; return out_buf.m_pBuf; +} + +size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) +{ + tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); + if (!pOut_buf) return 0; + out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len; + if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0; + return out_buf.m_size; +} + +#ifndef MINIZ_NO_ZLIB_APIS +static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; + +// level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). +mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy) +{ + mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); + if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER; + + if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; + else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES; + else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK; + else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; + else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES; + + return comp_flags; +} +#endif //MINIZ_NO_ZLIB_APIS + +#ifdef _MSC_VER +#pragma warning (push) +#pragma warning (disable:4204) // nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) +#endif + +// Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at +// http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/. +// This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. +void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip) +{ + // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. + static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; + tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0; + if (!pComp) return NULL; + MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; } + // write dummy header + for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf); + // compress image data + tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER); + for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); } + if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } + // write real header + *pLen_out = out_buf.m_size-41; + { + static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06}; + mz_uint8 pnghdr[41]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52, + 0,0,(mz_uint8)(w>>8),(mz_uint8)w,0,0,(mz_uint8)(h>>8),(mz_uint8)h,8,chans[num_chans],0,0,0,0,0,0,0, + (mz_uint8)(*pLen_out>>24),(mz_uint8)(*pLen_out>>16),(mz_uint8)(*pLen_out>>8),(mz_uint8)*pLen_out,0x49,0x44,0x41,0x54}; + c=(mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17); for (i=0; i<4; ++i, c<<=8) ((mz_uint8*)(pnghdr+29))[i]=(mz_uint8)(c>>24); + memcpy(out_buf.m_pBuf, pnghdr, 41); + } + // write footer (IDAT CRC-32, followed by IEND chunk) + if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } + c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4); for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24); + // compute final size of file, grab compressed data buffer and return + *pLen_out += 57; MZ_FREE(pComp); return out_buf.m_pBuf; +} +void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out) +{ + // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) + return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE); +} + +#ifdef _MSC_VER +#pragma warning (pop) +#endif + +// ------------------- .ZIP archive reading + +#ifndef MINIZ_NO_ARCHIVE_APIS + +#ifdef MINIZ_NO_STDIO + #define MZ_FILE void * +#else + #include + #include + + #if defined(_MSC_VER) //|| defined(__MINGW64__) + static FILE *mz_fopen(const char *pFilename, const char *pMode) + { + FILE* pFile = NULL; + fopen_s(&pFile, pFilename, pMode); + return pFile; + } + static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) + { + FILE* pFile = NULL; + if (freopen_s(&pFile, pPath, pMode, pStream)) + return NULL; + return pFile; + } + #ifndef MINIZ_NO_TIME + #include + #endif + #define MZ_FILE FILE + #define MZ_FOPEN mz_fopen + #define MZ_FCLOSE fclose + #define MZ_FREAD fread + #define MZ_FWRITE fwrite + #define MZ_FTELL64 _ftelli64 + #define MZ_FSEEK64 _fseeki64 + #define MZ_FILE_STAT_STRUCT _stat + #define MZ_FILE_STAT _stat + #define MZ_FFLUSH fflush + #define MZ_FREOPEN mz_freopen + #define MZ_DELETE_FILE remove + #elif defined(__MINGW32__) || defined(__MINGW64__) + #ifndef MINIZ_NO_TIME + #include + #endif + #define MZ_FILE FILE + #define MZ_FOPEN(f, m) fopen(f, m) + #define MZ_FCLOSE fclose + #define MZ_FREAD fread + #define MZ_FWRITE fwrite + #define MZ_FTELL64 ftello64 + #define MZ_FSEEK64 fseeko64 + #define MZ_FILE_STAT_STRUCT _stat + #define MZ_FILE_STAT _stat + #define MZ_FFLUSH fflush + #define MZ_FREOPEN(f, m, s) freopen(f, m, s) + #define MZ_DELETE_FILE remove + #elif defined(__TINYC__) + #ifndef MINIZ_NO_TIME + #include + #endif + #define MZ_FILE FILE + #define MZ_FOPEN(f, m) fopen(f, m) + #define MZ_FCLOSE fclose + #define MZ_FREAD fread + #define MZ_FWRITE fwrite + #define MZ_FTELL64 ftell + #define MZ_FSEEK64 fseek + #define MZ_FILE_STAT_STRUCT stat + #define MZ_FILE_STAT stat + #define MZ_FFLUSH fflush + #define MZ_FREOPEN(f, m, s) freopen(f, m, s) + #define MZ_DELETE_FILE remove + #elif defined(__GNUC__) && _LARGEFILE64_SOURCE + #ifndef MINIZ_NO_TIME + #include + #endif + #define MZ_FILE FILE + #define MZ_FOPEN(f, m) fopen64(f, m) + #define MZ_FCLOSE fclose + #define MZ_FREAD fread + #define MZ_FWRITE fwrite + #define MZ_FTELL64 ftello64 + #define MZ_FSEEK64 fseeko64 + #define MZ_FILE_STAT_STRUCT stat64 + #define MZ_FILE_STAT stat64 + #define MZ_FFLUSH fflush + #define MZ_FREOPEN(p, m, s) freopen64(p, m, s) + #define MZ_DELETE_FILE remove + #else + #ifndef MINIZ_NO_TIME + #include + #endif + #define MZ_FILE FILE + #define MZ_FOPEN(f, m) fopen(f, m) + #define MZ_FCLOSE fclose + #define MZ_FREAD fread + #define MZ_FWRITE fwrite + #define MZ_FTELL64 ftello + #define MZ_FSEEK64 fseeko + #define MZ_FILE_STAT_STRUCT stat + #define MZ_FILE_STAT stat + #define MZ_FFLUSH fflush + #define MZ_FREOPEN(f, m, s) freopen(f, m, s) + #define MZ_DELETE_FILE remove + #endif // #ifdef _MSC_VER +#endif // #ifdef MINIZ_NO_STDIO + +#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c)) + +// Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. +enum +{ + // ZIP archive identifiers and record sizes + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50, + MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, + // Central directory header record offsets + MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, MZ_ZIP_CDH_BIT_FLAG_OFS = 8, + MZ_ZIP_CDH_METHOD_OFS = 10, MZ_ZIP_CDH_FILE_TIME_OFS = 12, MZ_ZIP_CDH_FILE_DATE_OFS = 14, MZ_ZIP_CDH_CRC32_OFS = 16, + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, MZ_ZIP_CDH_EXTRA_LEN_OFS = 30, + MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, MZ_ZIP_CDH_DISK_START_OFS = 34, MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42, + // Local directory header offsets + MZ_ZIP_LDH_SIG_OFS = 0, MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, MZ_ZIP_LDH_BIT_FLAG_OFS = 6, MZ_ZIP_LDH_METHOD_OFS = 8, MZ_ZIP_LDH_FILE_TIME_OFS = 10, + MZ_ZIP_LDH_FILE_DATE_OFS = 12, MZ_ZIP_LDH_CRC32_OFS = 14, MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22, + MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, MZ_ZIP_LDH_EXTRA_LEN_OFS = 28, + // End of central directory offsets + MZ_ZIP_ECDH_SIG_OFS = 0, MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8, + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, +}; + +typedef struct +{ + void *m_p; + size_t m_size, m_capacity; + mz_uint m_element_size; +} mz_zip_array; + +struct mz_zip_internal_state_tag +{ + mz_zip_array m_central_dir; + mz_zip_array m_central_dir_offsets; + mz_zip_array m_sorted_central_dir_offsets; + MZ_FILE *m_pFile; + void *m_pMem; + size_t m_mem_size; + size_t m_mem_capacity; +}; + +#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size +#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index] + +static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray) +{ + pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p); + memset(pArray, 0, sizeof(mz_zip_array)); +} + +static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing) +{ + void *pNew_p; size_t new_capacity = min_new_capacity; MZ_ASSERT(pArray->m_element_size); if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE; + if (growing) { new_capacity = MZ_MAX(1, pArray->m_capacity); while (new_capacity < min_new_capacity) new_capacity *= 2; } + if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE; + pArray->m_p = pNew_p; pArray->m_capacity = new_capacity; + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing) +{ + if (new_capacity > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; } + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing) +{ + if (new_size > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; } + pArray->m_size = new_size; + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n) +{ + return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE); +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n) +{ + size_t orig_size = pArray->m_size; if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE; + memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size); + return MZ_TRUE; +} + +#ifndef MINIZ_NO_TIME +static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date) +{ + struct tm tm; + memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1; + tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; tm.tm_mon = ((dos_date >> 5) & 15) - 1; tm.tm_mday = dos_date & 31; + tm.tm_hour = (dos_time >> 11) & 31; tm.tm_min = (dos_time >> 5) & 63; tm.tm_sec = (dos_time << 1) & 62; + return mktime(&tm); +} + +static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) +{ +#ifdef _MSC_VER + struct tm tm_struct; + struct tm *tm = &tm_struct; + errno_t err = localtime_s(tm, &time); + if (err) + { + *pDOS_date = 0; *pDOS_time = 0; + return; + } +#else + struct tm *tm = localtime(&time); +#endif + *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1)); + *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday); +} +#endif + +#ifndef MINIZ_NO_STDIO +static mz_bool mz_zip_get_file_modified_time(const char *pFilename, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) +{ +#ifdef MINIZ_NO_TIME + (void)pFilename; *pDOS_date = *pDOS_time = 0; +#else + struct MZ_FILE_STAT_STRUCT file_stat; + // On Linux with x86 glibc, this call will fail on large files (>= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. + if (MZ_FILE_STAT(pFilename, &file_stat) != 0) + return MZ_FALSE; + mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date); +#endif // #ifdef MINIZ_NO_TIME + return MZ_TRUE; +} + +#ifndef MINIZ_NO_TIME +static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, time_t modified_time) +{ + struct utimbuf t; t.actime = access_time; t.modtime = modified_time; + return !utime(pFilename, &t); +} +#endif // #ifndef MINIZ_NO_TIME +#endif // #ifndef MINIZ_NO_STDIO + +static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint32 flags) +{ + (void)flags; + if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) + return MZ_FALSE; + + if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; + if (!pZip->m_pFree) pZip->m_pFree = def_free_func; + if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; + + pZip->m_zip_mode = MZ_ZIP_MODE_READING; + pZip->m_archive_size = 0; + pZip->m_central_directory_file_ofs = 0; + pZip->m_total_files = 0; + + if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) + return MZ_FALSE; + memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index) +{ + const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; + const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index)); + mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS); + mz_uint8 l = 0, r = 0; + pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pE = pL + MZ_MIN(l_len, r_len); + while (pL < pE) + { + if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) + break; + pL++; pR++; + } + return (pL == pE) ? (l_len < r_len) : (l < r); +} + +#define MZ_SWAP_UINT32(a, b) do { mz_uint32 t = a; a = b; b = t; } MZ_MACRO_END + +// Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) +static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) +{ + mz_zip_internal_state *pState = pZip->m_pState; + const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; + const mz_zip_array *pCentral_dir = &pState->m_central_dir; + mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); + const int size = pZip->m_total_files; + int start = (size - 2) >> 1, end; + while (start >= 0) + { + int child, root = start; + for ( ; ; ) + { + if ((child = (root << 1) + 1) >= size) + break; + child += (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1]))); + if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) + break; + MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; + } + start--; + } + + end = size - 1; + while (end > 0) + { + int child, root = 0; + MZ_SWAP_UINT32(pIndices[end], pIndices[0]); + for ( ; ; ) + { + if ((child = (root << 1) + 1) >= end) + break; + child += (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1])); + if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) + break; + MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; + } + end--; + } +} + +static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint32 flags) +{ + mz_uint cdir_size, num_this_disk, cdir_disk_index; + mz_uint64 cdir_ofs; + mz_int64 cur_file_ofs; + const mz_uint8 *p; + mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint8 *pBuf = (mz_uint8 *)buf_u32; + mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); + // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. + if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return MZ_FALSE; + // Find the end of central directory record by scanning the file from the end towards the beginning. + cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); + for ( ; ; ) + { + int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) + return MZ_FALSE; + for (i = n - 4; i >= 0; --i) + if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) + break; + if (i >= 0) + { + cur_file_ofs += i; + break; + } + if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) + return MZ_FALSE; + cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); + } + // Read and verify the end of central directory record. + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) || + ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS))) + return MZ_FALSE; + + num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); + cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); + if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1))) + return MZ_FALSE; + + if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) + return MZ_FALSE; + + cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); + if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) + return MZ_FALSE; + + pZip->m_central_directory_file_ofs = cdir_ofs; + + if (pZip->m_total_files) + { + mz_uint i, n; + + // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices. + if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) || + (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE))) + return MZ_FALSE; + + if (sort_central_dir) + { + if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE)) + return MZ_FALSE; + } + + if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size) + return MZ_FALSE; + + // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported). + p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p; + for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) + { + mz_uint total_header_size, comp_size, decomp_size, disk_index; + if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) + return MZ_FALSE; + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p); + if (sort_central_dir) + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i; + comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF)) + return MZ_FALSE; + disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); + if ((disk_index != num_this_disk) && (disk_index != 1)) + return MZ_FALSE; + if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) + return MZ_FALSE; + if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n) + return MZ_FALSE; + n -= total_header_size; p += total_header_size; + } + } + + if (sort_central_dir) + mz_zip_reader_sort_central_dir_offsets_by_filename(pZip); + + return MZ_TRUE; +} + +mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags) +{ + if ((!pZip) || (!pZip->m_pRead)) + return MZ_FALSE; + if (!mz_zip_reader_init_internal(pZip, flags)) + return MZ_FALSE; + pZip->m_archive_size = size; + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end(pZip); + return MZ_FALSE; + } + return MZ_TRUE; +} + +static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n); + memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s); + return s; +} + +mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags) +{ + if (!mz_zip_reader_init_internal(pZip, flags)) + return MZ_FALSE; + pZip->m_archive_size = size; + pZip->m_pRead = mz_zip_mem_read_func; + pZip->m_pIO_opaque = pZip; +#ifdef __cplusplus + pZip->m_pState->m_pMem = const_cast(pMem); +#else + pZip->m_pState->m_pMem = (void *)pMem; +#endif + pZip->m_pState->m_mem_size = size; + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end(pZip); + return MZ_FALSE; + } + return MZ_TRUE; +} + +#ifndef MINIZ_NO_STDIO +static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); + if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) + return 0; + return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile); +} + +mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags) +{ + mz_uint64 file_size; + MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb"); + if (!pFile) + return MZ_FALSE; + if (MZ_FSEEK64(pFile, 0, SEEK_END)) + { + MZ_FCLOSE(pFile); + return MZ_FALSE; + } + file_size = MZ_FTELL64(pFile); + if (!mz_zip_reader_init_internal(pZip, flags)) + { + MZ_FCLOSE(pFile); + return MZ_FALSE; + } + pZip->m_pRead = mz_zip_file_read_func; + pZip->m_pIO_opaque = pZip; + pZip->m_pState->m_pFile = pFile; + pZip->m_archive_size = file_size; + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end(pZip); + return MZ_FALSE; + } + return MZ_TRUE; +} +#endif // #ifndef MINIZ_NO_STDIO + +mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) +{ + return pZip ? pZip->m_total_files : 0; +} + +static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index) +{ + if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + return NULL; + return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); +} + +mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index) +{ + mz_uint m_bit_flag; + const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); + if (!p) + return MZ_FALSE; + m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + return (m_bit_flag & 1); +} + +mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index) +{ + mz_uint filename_len, external_attr; + const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); + if (!p) + return MZ_FALSE; + + // First see if the filename ends with a '/' character. + filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + if (filename_len) + { + if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/') + return MZ_TRUE; + } + + // Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. + // Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. + // FIXME: Remove this check? Is it necessary - we already check the filename. + external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); + if ((external_attr & 0x10) != 0) + return MZ_TRUE; + + return MZ_FALSE; +} + +mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat) +{ + mz_uint n; + const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); + if ((!p) || (!pStat)) + return MZ_FALSE; + + // Unpack the central directory record. + pStat->m_file_index = file_index; + pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index); + pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS); + pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS); + pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); +#ifndef MINIZ_NO_TIME + pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS)); +#endif + pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS); + pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS); + pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); + pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); + + // Copy as much of the filename and comment as possible. + n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1); + memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); pStat->m_filename[n] = '\0'; + + n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1); + pStat->m_comment_size = n; + memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); pStat->m_comment[n] = '\0'; + + return MZ_TRUE; +} + +mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size) +{ + mz_uint n; + const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); + if (!p) { if (filename_buf_size) pFilename[0] = '\0'; return 0; } + n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + if (filename_buf_size) + { + n = MZ_MIN(n, filename_buf_size - 1); + memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); + pFilename[n] = '\0'; + } + return n + 1; +} + +static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags) +{ + mz_uint i; + if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE) + return 0 == memcmp(pA, pB, len); + for (i = 0; i < len; ++i) + if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) + return MZ_FALSE; + return MZ_TRUE; +} + +static MZ_FORCEINLINE int mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len) +{ + const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; + mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS); + mz_uint8 l = 0, r = 0; + pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pE = pL + MZ_MIN(l_len, r_len); + while (pL < pE) + { + if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) + break; + pL++; pR++; + } + return (pL == pE) ? (int)(l_len - r_len) : (l - r); +} + +static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename) +{ + mz_zip_internal_state *pState = pZip->m_pState; + const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; + const mz_zip_array *pCentral_dir = &pState->m_central_dir; + mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); + const int size = pZip->m_total_files; + const mz_uint filename_len = (mz_uint)strlen(pFilename); + int l = 0, h = size - 1; + while (l <= h) + { + int m = (l + h) >> 1, file_index = pIndices[m], comp = mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len); + if (!comp) + return file_index; + else if (comp < 0) + l = m + 1; + else + h = m - 1; + } + return -1; +} + +int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags) +{ + mz_uint file_index; size_t name_len, comment_len; + if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + return -1; + if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size)) + return mz_zip_reader_locate_file_binary_search(pZip, pName); + name_len = strlen(pName); if (name_len > 0xFFFF) return -1; + comment_len = pComment ? strlen(pComment) : 0; if (comment_len > 0xFFFF) return -1; + for (file_index = 0; file_index < pZip->m_total_files; file_index++) + { + const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); + mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS); + const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + if (filename_len < name_len) + continue; + if (comment_len) + { + mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS); + const char *pFile_comment = pFilename + filename_len + file_extra_len; + if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal(pComment, pFile_comment, file_comment_len, flags))) + continue; + } + if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) + { + int ofs = filename_len - 1; + do + { + if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':')) + break; + } while (--ofs >= 0); + ofs++; + pFilename += ofs; filename_len -= ofs; + } + if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags))) + return file_index; + } + return -1; +} + +mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) +{ + int status = TINFL_STATUS_DONE; + mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail; + mz_zip_archive_file_stat file_stat; + void *pRead_buf; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + tinfl_decompressor inflator; + + if ((buf_size) && (!pBuf)) + return MZ_FALSE; + + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; + + // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes) + if (!file_stat.m_comp_size) + return MZ_TRUE; + + // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers). + // I'm torn how to handle this case - should it fail instead? + if (mz_zip_reader_is_file_a_directory(pZip, file_index)) + return MZ_TRUE; + + // Encryption and patch files are not supported. + if (file_stat.m_bit_flag & (1 | 32)) + return MZ_FALSE; + + // This function only supports stored and deflate. + if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) + return MZ_FALSE; + + // Ensure supplied output buffer is large enough. + needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size; + if (buf_size < needed_size) + return MZ_FALSE; + + // Read and parse the local directory entry. + cur_file_ofs = file_stat.m_local_header_ofs; + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return MZ_FALSE; + + cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) + return MZ_FALSE; + + if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) + { + // The file is stored or the caller has requested the compressed data. + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size) + return MZ_FALSE; + return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32); + } + + // Decompress the file either directly from memory or from a file input buffer. + tinfl_init(&inflator); + + if (pZip->m_pState->m_pMem) + { + // Read directly from the archive in memory. + pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; + read_buf_size = read_buf_avail = file_stat.m_comp_size; + comp_remaining = 0; + } + else if (pUser_read_buf) + { + // Use a user provided read buffer. + if (!user_read_buf_size) + return MZ_FALSE; + pRead_buf = (mz_uint8 *)pUser_read_buf; + read_buf_size = user_read_buf_size; + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } + else + { + // Temporarily allocate a read buffer. + read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); +#ifdef _MSC_VER + if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) +#else + if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) +#endif + return MZ_FALSE; + if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) + return MZ_FALSE; + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } + + do + { + size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs); + if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) + { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + status = TINFL_STATUS_FAILED; + break; + } + cur_file_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + read_buf_ofs = 0; + } + in_buf_size = (size_t)read_buf_avail; + status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0)); + read_buf_avail -= in_buf_size; + read_buf_ofs += in_buf_size; + out_buf_ofs += out_buf_size; + } while (status == TINFL_STATUS_NEEDS_MORE_INPUT); + + if (status == TINFL_STATUS_DONE) + { + // Make sure the entire file was decompressed, and check its CRC. + if ((out_buf_ofs != file_stat.m_uncomp_size) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)) + status = TINFL_STATUS_FAILED; + } + + if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf)) + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + + return status == TINFL_STATUS_DONE; +} + +mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) +{ + int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); + if (file_index < 0) + return MZ_FALSE; + return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size); +} + +mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags) +{ + return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0); +} + +mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags) +{ + return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0); +} + +void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags) +{ + mz_uint64 comp_size, uncomp_size, alloc_size; + const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); + void *pBuf; + + if (pSize) + *pSize = 0; + if (!p) + return NULL; + + comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + + alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size; +#ifdef _MSC_VER + if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) +#else + if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) +#endif + return NULL; + if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size))) + return NULL; + + if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return NULL; + } + + if (pSize) *pSize = (size_t)alloc_size; + return pBuf; +} + +void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags) +{ + int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); + if (file_index < 0) + { + if (pSize) *pSize = 0; + return MZ_FALSE; + } + return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags); +} + +mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) +{ + int status = TINFL_STATUS_DONE; mz_uint file_crc32 = MZ_CRC32_INIT; + mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs; + mz_zip_archive_file_stat file_stat; + void *pRead_buf = NULL; void *pWrite_buf = NULL; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; + + // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes) + if (!file_stat.m_comp_size) + return MZ_TRUE; + + // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers). + // I'm torn how to handle this case - should it fail instead? + if (mz_zip_reader_is_file_a_directory(pZip, file_index)) + return MZ_TRUE; + + // Encryption and patch files are not supported. + if (file_stat.m_bit_flag & (1 | 32)) + return MZ_FALSE; + + // This function only supports stored and deflate. + if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) + return MZ_FALSE; + + // Read and parse the local directory entry. + cur_file_ofs = file_stat.m_local_header_ofs; + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return MZ_FALSE; + + cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) + return MZ_FALSE; + + // Decompress the file either directly from memory or from a file input buffer. + if (pZip->m_pState->m_pMem) + { + pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; + read_buf_size = read_buf_avail = file_stat.m_comp_size; + comp_remaining = 0; + } + else + { + read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); + if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) + return MZ_FALSE; + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } + + if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) + { + // The file is stored or the caller has requested the compressed data. + if (pZip->m_pState->m_pMem) + { +#ifdef _MSC_VER + if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) +#else + if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) +#endif + return MZ_FALSE; + if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size) + status = TINFL_STATUS_FAILED; + else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size); + cur_file_ofs += file_stat.m_comp_size; + out_buf_ofs += file_stat.m_comp_size; + comp_remaining = 0; + } + else + { + while (comp_remaining) + { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + status = TINFL_STATUS_FAILED; + break; + } + + if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail); + + if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + status = TINFL_STATUS_FAILED; + break; + } + cur_file_ofs += read_buf_avail; + out_buf_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + } + } + } + else + { + tinfl_decompressor inflator; + tinfl_init(&inflator); + + if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) + status = TINFL_STATUS_FAILED; + else + { + do + { + mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); + size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); + if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) + { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + status = TINFL_STATUS_FAILED; + break; + } + cur_file_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + read_buf_ofs = 0; + } + + in_buf_size = (size_t)read_buf_avail; + status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0); + read_buf_avail -= in_buf_size; + read_buf_ofs += in_buf_size; + + if (out_buf_size) + { + if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size) + { + status = TINFL_STATUS_FAILED; + break; + } + file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size); + if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) + { + status = TINFL_STATUS_FAILED; + break; + } + } + } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT)); + } + } + + if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) + { + // Make sure the entire file was decompressed, and check its CRC. + if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32)) + status = TINFL_STATUS_FAILED; + } + + if (!pZip->m_pState->m_pMem) + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + if (pWrite_buf) + pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf); + + return status == TINFL_STATUS_DONE; +} + +mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) +{ + int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); + if (file_index < 0) + return MZ_FALSE; + return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags); +} + +#ifndef MINIZ_NO_STDIO +static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n) +{ + (void)ofs; return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque); +} + +mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags) +{ + mz_bool status; + mz_zip_archive_file_stat file_stat; + MZ_FILE *pFile; + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; + pFile = MZ_FOPEN(pDst_filename, "wb"); + if (!pFile) + return MZ_FALSE; + status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags); + if (MZ_FCLOSE(pFile) == EOF) + return MZ_FALSE; +#ifndef MINIZ_NO_TIME + if (status) + mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time); +#endif + return status; +} +#endif // #ifndef MINIZ_NO_STDIO + +mz_bool mz_zip_reader_end(mz_zip_archive *pZip) +{ + if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + return MZ_FALSE; + + if (pZip->m_pState) + { + mz_zip_internal_state *pState = pZip->m_pState; pZip->m_pState = NULL; + mz_zip_array_clear(pZip, &pState->m_central_dir); + mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); + mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); + +#ifndef MINIZ_NO_STDIO + if (pState->m_pFile) + { + MZ_FCLOSE(pState->m_pFile); + pState->m_pFile = NULL; + } +#endif // #ifndef MINIZ_NO_STDIO + + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + } + pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; + + return MZ_TRUE; +} + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags) +{ + int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags); + if (file_index < 0) + return MZ_FALSE; + return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags); +} +#endif + +// ------------------- .ZIP archive writing + +#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + +static void mz_write_le16(mz_uint8 *p, mz_uint16 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); } +static void mz_write_le32(mz_uint8 *p, mz_uint32 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); p[2] = (mz_uint8)(v >> 16); p[3] = (mz_uint8)(v >> 24); } +#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v)) +#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v)) + +mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) +{ + if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) + return MZ_FALSE; + + if (pZip->m_file_offset_alignment) + { + // Ensure user specified file offset alignment is a power of 2. + if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1)) + return MZ_FALSE; + } + + if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; + if (!pZip->m_pFree) pZip->m_pFree = def_free_func; + if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; + + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; + pZip->m_archive_size = existing_size; + pZip->m_central_directory_file_ofs = 0; + pZip->m_total_files = 0; + + if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) + return MZ_FALSE; + memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); + return MZ_TRUE; +} + +static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + mz_zip_internal_state *pState = pZip->m_pState; + mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size); +#ifdef _MSC_VER + if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) +#else + if ((!n) || ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) +#endif + return 0; + if (new_size > pState->m_mem_capacity) + { + void *pNew_block; + size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); while (new_capacity < new_size) new_capacity *= 2; + if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity))) + return 0; + pState->m_pMem = pNew_block; pState->m_mem_capacity = new_capacity; + } + memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n); + pState->m_mem_size = (size_t)new_size; + return n; +} + +mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size) +{ + pZip->m_pWrite = mz_zip_heap_write_func; + pZip->m_pIO_opaque = pZip; + if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) + return MZ_FALSE; + if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning))) + { + if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size))) + { + mz_zip_writer_end(pZip); + return MZ_FALSE; + } + pZip->m_pState->m_mem_capacity = initial_allocation_size; + } + return MZ_TRUE; +} + +#ifndef MINIZ_NO_STDIO +static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); + if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) + return 0; + return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile); +} + +mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning) +{ + MZ_FILE *pFile; + pZip->m_pWrite = mz_zip_file_write_func; + pZip->m_pIO_opaque = pZip; + if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) + return MZ_FALSE; + if (NULL == (pFile = MZ_FOPEN(pFilename, "wb"))) + { + mz_zip_writer_end(pZip); + return MZ_FALSE; + } + pZip->m_pState->m_pFile = pFile; + if (size_to_reserve_at_beginning) + { + mz_uint64 cur_ofs = 0; char buf[4096]; MZ_CLEAR_OBJ(buf); + do + { + size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) + { + mz_zip_writer_end(pZip); + return MZ_FALSE; + } + cur_ofs += n; size_to_reserve_at_beginning -= n; + } while (size_to_reserve_at_beginning); + } + return MZ_TRUE; +} +#endif // #ifndef MINIZ_NO_STDIO + +mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename) +{ + mz_zip_internal_state *pState; + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + return MZ_FALSE; + // No sense in trying to write to an archive that's already at the support max size + if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) + return MZ_FALSE; + + pState = pZip->m_pState; + + if (pState->m_pFile) + { +#ifdef MINIZ_NO_STDIO + pFilename; return MZ_FALSE; +#else + // Archive is being read from stdio - try to reopen as writable. + if (pZip->m_pIO_opaque != pZip) + return MZ_FALSE; + if (!pFilename) + return MZ_FALSE; + pZip->m_pWrite = mz_zip_file_write_func; + if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) + { + // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. + mz_zip_reader_end(pZip); + return MZ_FALSE; + } +#endif // #ifdef MINIZ_NO_STDIO + } + else if (pState->m_pMem) + { + // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. + if (pZip->m_pIO_opaque != pZip) + return MZ_FALSE; + pState->m_mem_capacity = pState->m_mem_size; + pZip->m_pWrite = mz_zip_heap_write_func; + } + // Archive is being read via a user provided read function - make sure the user has specified a write function too. + else if (!pZip->m_pWrite) + return MZ_FALSE; + + // Start writing new files at the archive's current central directory location. + pZip->m_archive_size = pZip->m_central_directory_file_ofs; + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; + pZip->m_central_directory_file_ofs = 0; + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags) +{ + return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0); +} + +typedef struct +{ + mz_zip_archive *m_pZip; + mz_uint64 m_cur_archive_file_ofs; + mz_uint64 m_comp_size; +} mz_zip_writer_add_state; + +static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void *pUser) +{ + mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser; + if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len) + return MZ_FALSE; + pState->m_cur_archive_file_ofs += len; + pState->m_comp_size += len; + return MZ_TRUE; +} + +static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date) +{ + (void)pZip; + memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size); + return MZ_TRUE; +} + +static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) +{ + (void)pZip; + memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs); + return MZ_TRUE; +} + +static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) +{ + mz_zip_internal_state *pState = pZip->m_pState; + mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size; + size_t orig_central_dir_size = pState->m_central_dir.m_size; + mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; + + // No zip64 support yet + if ((local_header_ofs > 0xFFFFFFFF) || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + comment_size) > 0xFFFFFFFF)) + return MZ_FALSE; + + if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes)) + return MZ_FALSE; + + if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, ¢ral_dir_ofs, 1))) + { + // Try to push the central directory array back into its original state. + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return MZ_FALSE; + } + + return MZ_TRUE; +} + +static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) +{ + // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. + if (*pArchive_name == '/') + return MZ_FALSE; + while (*pArchive_name) + { + if ((*pArchive_name == '\\') || (*pArchive_name == ':')) + return MZ_FALSE; + pArchive_name++; + } + return MZ_TRUE; +} + +static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) +{ + mz_uint32 n; + if (!pZip->m_file_offset_alignment) + return 0; + n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1)); + return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1); +} + +static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n) +{ + char buf[4096]; + memset(buf, 0, MZ_MIN(sizeof(buf), n)); + while (n) + { + mz_uint32 s = MZ_MIN(sizeof(buf), n); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s) + return MZ_FALSE; + cur_file_ofs += s; n -= s; + } + return MZ_TRUE; +} + +mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32) +{ + mz_uint16 method = 0, dos_time = 0, dos_date = 0; + mz_uint level, ext_attributes = 0, num_alignment_padding_bytes; + mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0; + size_t archive_name_size; + mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; + tdefl_compressor *pComp = NULL; + mz_bool store_data_uncompressed; + mz_zip_internal_state *pState; + + if ((int)level_and_flags < 0) + level_and_flags = MZ_DEFAULT_LEVEL; + level = level_and_flags & 0xF; + store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)); + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION)) + return MZ_FALSE; + + pState = pZip->m_pState; + + if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size)) + return MZ_FALSE; + // No zip64 support yet + if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) + return MZ_FALSE; + if (!mz_zip_writer_validate_archive_name(pArchive_name)) + return MZ_FALSE; + +#ifndef MINIZ_NO_TIME + { + time_t cur_time; time(&cur_time); + mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date); + } +#endif // #ifndef MINIZ_NO_TIME + + archive_name_size = strlen(pArchive_name); + if (archive_name_size > 0xFFFF) + return MZ_FALSE; + + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + + // no zip64 support yet + if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) + return MZ_FALSE; + + if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) + { + // Set DOS Subdirectory attribute bit. + ext_attributes |= 0x10; + // Subdirectories cannot contain data. + if ((buf_size) || (uncomp_size)) + return MZ_FALSE; + } + + // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) + if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1))) + return MZ_FALSE; + + if ((!store_data_uncompressed) && (buf_size)) + { + if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)))) + return MZ_FALSE; + } + + if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + local_dir_header_ofs += num_alignment_padding_bytes; + if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } + cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); + + MZ_CLEAR_OBJ(local_dir_header); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + cur_archive_file_ofs += archive_name_size; + + if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + { + uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size); + uncomp_size = buf_size; + if (uncomp_size <= 3) + { + level = 0; + store_data_uncompressed = MZ_TRUE; + } + } + + if (store_data_uncompressed) + { + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + + cur_archive_file_ofs += buf_size; + comp_size = buf_size; + + if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) + method = MZ_DEFLATED; + } + else if (buf_size) + { + mz_zip_writer_add_state state; + + state.m_pZip = pZip; + state.m_cur_archive_file_ofs = cur_archive_file_ofs; + state.m_comp_size = 0; + + if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) || + (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + + comp_size = state.m_comp_size; + cur_archive_file_ofs = state.m_cur_archive_file_ofs; + + method = MZ_DEFLATED; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + pComp = NULL; + + // no zip64 support yet + if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) + return MZ_FALSE; + + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) + return MZ_FALSE; + + if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return MZ_FALSE; + + if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) + return MZ_FALSE; + + pZip->m_total_files++; + pZip->m_archive_size = cur_archive_file_ofs; + + return MZ_TRUE; +} + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) +{ + mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes; + mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0; + mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0; + size_t archive_name_size; + mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; + MZ_FILE *pSrc_file = NULL; + + if ((int)level_and_flags < 0) + level_and_flags = MZ_DEFAULT_LEVEL; + level = level_and_flags & 0xF; + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION)) + return MZ_FALSE; + if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) + return MZ_FALSE; + if (!mz_zip_writer_validate_archive_name(pArchive_name)) + return MZ_FALSE; + + archive_name_size = strlen(pArchive_name); + if (archive_name_size > 0xFFFF) + return MZ_FALSE; + + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + + // no zip64 support yet + if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) + return MZ_FALSE; + + if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date)) + return MZ_FALSE; + + pSrc_file = MZ_FOPEN(pSrc_filename, "rb"); + if (!pSrc_file) + return MZ_FALSE; + MZ_FSEEK64(pSrc_file, 0, SEEK_END); + uncomp_size = MZ_FTELL64(pSrc_file); + MZ_FSEEK64(pSrc_file, 0, SEEK_SET); + + if (uncomp_size > 0xFFFFFFFF) + { + // No zip64 support yet + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + if (uncomp_size <= 3) + level = 0; + + if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) + { + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + local_dir_header_ofs += num_alignment_padding_bytes; + if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } + cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); + + MZ_CLEAR_OBJ(local_dir_header); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + { + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + cur_archive_file_ofs += archive_name_size; + + if (uncomp_size) + { + mz_uint64 uncomp_remaining = uncomp_size; + void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE); + if (!pRead_buf) + { + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + + if (!level) + { + while (uncomp_remaining) + { + mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining); + if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n); + uncomp_remaining -= n; + cur_archive_file_ofs += n; + } + comp_size = uncomp_size; + } + else + { + mz_bool result = MZ_FALSE; + mz_zip_writer_add_state state; + tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)); + if (!pComp) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + + state.m_pZip = pZip; + state.m_cur_archive_file_ofs = cur_archive_file_ofs; + state.m_comp_size = 0; + + if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + + for ( ; ; ) + { + size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE); + tdefl_status status; + + if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size) + break; + + uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size); + uncomp_remaining -= in_buf_size; + + status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH); + if (status == TDEFL_STATUS_DONE) + { + result = MZ_TRUE; + break; + } + else if (status != TDEFL_STATUS_OKAY) + break; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + + if (!result) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + + comp_size = state.m_comp_size; + cur_archive_file_ofs = state.m_cur_archive_file_ofs; + + method = MZ_DEFLATED; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + } + + MZ_FCLOSE(pSrc_file); pSrc_file = NULL; + + // no zip64 support yet + if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) + return MZ_FALSE; + + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) + return MZ_FALSE; + + if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return MZ_FALSE; + + if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) + return MZ_FALSE; + + pZip->m_total_files++; + pZip->m_archive_size = cur_archive_file_ofs; + + return MZ_TRUE; +} +#endif // #ifndef MINIZ_NO_STDIO + +mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index) +{ + mz_uint n, bit_flags, num_alignment_padding_bytes; + mz_uint64 comp_bytes_remaining, local_dir_header_ofs; + mz_uint64 cur_src_file_ofs, cur_dst_file_ofs; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; + size_t orig_central_dir_size; + mz_zip_internal_state *pState; + void *pBuf; const mz_uint8 *pSrc_central_header; + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) + return MZ_FALSE; + if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index))) + return MZ_FALSE; + pState = pZip->m_pState; + + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + + // no zip64 support yet + if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) + return MZ_FALSE; + + cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS); + cur_dst_file_ofs = pZip->m_archive_size; + + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return MZ_FALSE; + cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; + + if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes)) + return MZ_FALSE; + cur_dst_file_ofs += num_alignment_padding_bytes; + local_dir_header_ofs = cur_dst_file_ofs; + if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; + + n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + + if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(sizeof(mz_uint32) * 4, MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining))))) + return MZ_FALSE; + + while (comp_bytes_remaining) + { + n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining); + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } + cur_src_file_ofs += n; + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } + cur_dst_file_ofs += n; + + comp_bytes_remaining -= n; + } + + bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); + if (bit_flags & 8) + { + // Copy data descriptor + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } + + n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } + + cur_src_file_ofs += n; + cur_dst_file_ofs += n; + } + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + + // no zip64 support yet + if (cur_dst_file_ofs > 0xFFFFFFFF) + return MZ_FALSE; + + orig_central_dir_size = pState->m_central_dir.m_size; + + memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs); + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) + return MZ_FALSE; + + n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS); + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n)) + { + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return MZ_FALSE; + } + + if (pState->m_central_dir.m_size > 0xFFFFFFFF) + return MZ_FALSE; + n = (mz_uint32)orig_central_dir_size; + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) + { + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return MZ_FALSE; + } + + pZip->m_total_files++; + pZip->m_archive_size = cur_dst_file_ofs; + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) +{ + mz_zip_internal_state *pState; + mz_uint64 central_dir_ofs, central_dir_size; + mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE]; + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) + return MZ_FALSE; + + pState = pZip->m_pState; + + // no zip64 support yet + if ((pZip->m_total_files > 0xFFFF) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) + return MZ_FALSE; + + central_dir_ofs = 0; + central_dir_size = 0; + if (pZip->m_total_files) + { + // Write central directory + central_dir_ofs = pZip->m_archive_size; + central_dir_size = pState->m_central_dir.m_size; + pZip->m_central_directory_file_ofs = central_dir_ofs; + if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size) + return MZ_FALSE; + pZip->m_archive_size += central_dir_size; + } + + // Write end of central directory record + MZ_CLEAR_OBJ(hdr); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files); + MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr)) + return MZ_FALSE; +#ifndef MINIZ_NO_STDIO + if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) + return MZ_FALSE; +#endif // #ifndef MINIZ_NO_STDIO + + pZip->m_archive_size += sizeof(hdr); + + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED; + return MZ_TRUE; +} + +mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize) +{ + if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize)) + return MZ_FALSE; + if (pZip->m_pWrite != mz_zip_heap_write_func) + return MZ_FALSE; + if (!mz_zip_writer_finalize_archive(pZip)) + return MZ_FALSE; + + *pBuf = pZip->m_pState->m_pMem; + *pSize = pZip->m_pState->m_mem_size; + pZip->m_pState->m_pMem = NULL; + pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0; + return MZ_TRUE; +} + +mz_bool mz_zip_writer_end(mz_zip_archive *pZip) +{ + mz_zip_internal_state *pState; + mz_bool status = MZ_TRUE; + if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))) + return MZ_FALSE; + + pState = pZip->m_pState; + pZip->m_pState = NULL; + mz_zip_array_clear(pZip, &pState->m_central_dir); + mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); + mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); + +#ifndef MINIZ_NO_STDIO + if (pState->m_pFile) + { + MZ_FCLOSE(pState->m_pFile); + pState->m_pFile = NULL; + } +#endif // #ifndef MINIZ_NO_STDIO + + if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem); + pState->m_pMem = NULL; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; + return status; +} + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) +{ + mz_bool status, created_new_archive = MZ_FALSE; + mz_zip_archive zip_archive; + struct MZ_FILE_STAT_STRUCT file_stat; + MZ_CLEAR_OBJ(zip_archive); + if ((int)level_and_flags < 0) + level_and_flags = MZ_DEFAULT_LEVEL; + if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION)) + return MZ_FALSE; + if (!mz_zip_writer_validate_archive_name(pArchive_name)) + return MZ_FALSE; + if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) + { + // Create a new archive. + if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0)) + return MZ_FALSE; + created_new_archive = MZ_TRUE; + } + else + { + // Append to an existing archive. + if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) + return MZ_FALSE; + if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename)) + { + mz_zip_reader_end(&zip_archive); + return MZ_FALSE; + } + } + status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0); + // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) + if (!mz_zip_writer_finalize_archive(&zip_archive)) + status = MZ_FALSE; + if (!mz_zip_writer_end(&zip_archive)) + status = MZ_FALSE; + if ((!status) && (created_new_archive)) + { + // It's a new archive and something went wrong, so just delete it. + int ignoredStatus = MZ_DELETE_FILE(pZip_filename); + (void)ignoredStatus; + } + return status; +} + +void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags) +{ + int file_index; + mz_zip_archive zip_archive; + void *p = NULL; + + if (pSize) + *pSize = 0; + + if ((!pZip_filename) || (!pArchive_name)) + return NULL; + + MZ_CLEAR_OBJ(zip_archive); + if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) + return NULL; + + if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL, flags)) >= 0) + p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags); + + mz_zip_reader_end(&zip_archive); + return p; +} + +#endif // #ifndef MINIZ_NO_STDIO + +#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + +#endif // #ifndef MINIZ_NO_ARCHIVE_APIS + +#ifdef __cplusplus +} +#endif + +/* + This is free and unencumbered software released into the public domain. + + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + For more information, please refer to +*/ diff --git a/test_common/miniz/miniz.h b/test_common/miniz/miniz.h new file mode 100644 index 00000000..18681fe7 --- /dev/null +++ b/test_common/miniz/miniz.h @@ -0,0 +1,749 @@ +#ifndef MINIZ_HEADER_INCLUDED +#define MINIZ_HEADER_INCLUDED + +#include + +#if defined(__TINYC__) && (defined(__linux) || defined(__linux__)) + // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux + #define MINIZ_NO_TIME +#endif + +#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS) + #include +#endif + +#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__) +// MINIZ_X86_OR_X64_CPU is only used to help set the below macros. +#define MINIZ_X86_OR_X64_CPU 1 +#endif + +#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU +// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. +#define MINIZ_LITTLE_ENDIAN 1 +#endif + +#if MINIZ_X86_OR_X64_CPU +// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. +#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 +#endif + +#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__) +// Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions). +#define MINIZ_HAS_64BIT_REGISTERS 1 +#endif + +// Return status codes. MZ_PARAM_ERROR is non-standard. +enum { + MZ_OK = 0, + MZ_STREAM_END = 1, + MZ_NEED_DICT = 2, + MZ_ERRNO = -1, + MZ_STREAM_ERROR = -2, + MZ_DATA_ERROR = -3, + MZ_MEM_ERROR = -4, + MZ_BUF_ERROR = -5, + MZ_VERSION_ERROR = -6, + MZ_PARAM_ERROR = -10000 +}; + +typedef unsigned long mz_ulong; + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------- zlib-style API Definitions. + +// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap. +void mz_free(void *p); + +#define MZ_ADLER32_INIT (1) +// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL. +mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len); + +#define MZ_CRC32_INIT (0) +// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL. +mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len); + +// Compression strategies. +enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 }; + +// Method +#define MZ_DEFLATED 8 + +#ifndef MINIZ_NO_ZLIB_APIS + +// Heap allocation callbacks. +// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long. +typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size); +typedef void (*mz_free_func)(void *opaque, void *address); +typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size); + +#define MZ_VERSION "9.1.15" +#define MZ_VERNUM 0x91F0 +#define MZ_VER_MAJOR 9 +#define MZ_VER_MINOR 1 +#define MZ_VER_REVISION 15 +#define MZ_VER_SUBREVISION 0 + +// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs). +enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 }; + +// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. +enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 }; + +// Window bits +#define MZ_DEFAULT_WINDOW_BITS 15 + +struct mz_internal_state; + +// Compression/decompression stream struct. +typedef struct mz_stream_s +{ + const unsigned char *next_in; // pointer to next byte to read + unsigned int avail_in; // number of bytes available at next_in + mz_ulong total_in; // total number of bytes consumed so far + + unsigned char *next_out; // pointer to next byte to write + unsigned int avail_out; // number of bytes that can be written to next_out + mz_ulong total_out; // total number of bytes produced so far + + char *msg; // error msg (unused) + struct mz_internal_state *state; // internal state, allocated by zalloc/zfree + + mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc) + mz_free_func zfree; // optional heap free function (defaults to free) + void *opaque; // heap alloc function user pointer + + int data_type; // data_type (unused) + mz_ulong adler; // adler32 of the source or uncompressed data + mz_ulong reserved; // not used +} mz_stream; + +typedef mz_stream *mz_streamp; + +// Returns the version string of miniz.c. +const char *mz_version(void); + +// mz_deflateInit() initializes a compressor with default options: +// Parameters: +// pStream must point to an initialized mz_stream struct. +// level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION]. +// level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio. +// (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.) +// Return values: +// MZ_OK on success. +// MZ_STREAM_ERROR if the stream is bogus. +// MZ_PARAM_ERROR if the input parameters are bogus. +// MZ_MEM_ERROR on out of memory. +int mz_deflateInit(mz_streamp pStream, int level); + +// mz_deflateInit2() is like mz_deflate(), except with more control: +// Additional parameters: +// method must be MZ_DEFLATED +// window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer) +// mem_level must be between [1, 9] (it's checked but ignored by miniz.c) +int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy); + +// Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2(). +int mz_deflateReset(mz_streamp pStream); + +// mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible. +// Parameters: +// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. +// flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH. +// Return values: +// MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full). +// MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore. +// MZ_STREAM_ERROR if the stream is bogus. +// MZ_PARAM_ERROR if one of the parameters is invalid. +// MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.) +int mz_deflate(mz_streamp pStream, int flush); + +// mz_deflateEnd() deinitializes a compressor: +// Return values: +// MZ_OK on success. +// MZ_STREAM_ERROR if the stream is bogus. +int mz_deflateEnd(mz_streamp pStream); + +// mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH. +mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len); + +// Single-call compression functions mz_compress() and mz_compress2(): +// Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure. +int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); +int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level); + +// mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress(). +mz_ulong mz_compressBound(mz_ulong source_len); + +// Initializes a decompressor. +int mz_inflateInit(mz_streamp pStream); + +// mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer: +// window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate). +int mz_inflateInit2(mz_streamp pStream, int window_bits); + +// Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible. +// Parameters: +// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. +// flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. +// On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster). +// MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data. +// Return values: +// MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full. +// MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified. +// MZ_STREAM_ERROR if the stream is bogus. +// MZ_DATA_ERROR if the deflate stream is invalid. +// MZ_PARAM_ERROR if one of the parameters is invalid. +// MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again +// with more input data, or with more room in the output buffer (except when using single call decompression, described above). +int mz_inflate(mz_streamp pStream, int flush); + +// Deinitializes a decompressor. +int mz_inflateEnd(mz_streamp pStream); + +// Single-call decompression. +// Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure. +int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); + +// Returns a string description of the specified error code, or NULL if the error code is invalid. +const char *mz_error(int err); + +// Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports. +// Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project. +#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES + typedef unsigned char Byte; + typedef unsigned int uInt; + typedef mz_ulong uLong; + typedef Byte Bytef; + typedef uInt uIntf; + typedef char charf; + typedef int intf; + typedef void *voidpf; + typedef uLong uLongf; + typedef void *voidp; + typedef void *const voidpc; + #define Z_NULL 0 + #define Z_NO_FLUSH MZ_NO_FLUSH + #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH + #define Z_SYNC_FLUSH MZ_SYNC_FLUSH + #define Z_FULL_FLUSH MZ_FULL_FLUSH + #define Z_FINISH MZ_FINISH + #define Z_BLOCK MZ_BLOCK + #define Z_OK MZ_OK + #define Z_STREAM_END MZ_STREAM_END + #define Z_NEED_DICT MZ_NEED_DICT + #define Z_ERRNO MZ_ERRNO + #define Z_STREAM_ERROR MZ_STREAM_ERROR + #define Z_DATA_ERROR MZ_DATA_ERROR + #define Z_MEM_ERROR MZ_MEM_ERROR + #define Z_BUF_ERROR MZ_BUF_ERROR + #define Z_VERSION_ERROR MZ_VERSION_ERROR + #define Z_PARAM_ERROR MZ_PARAM_ERROR + #define Z_NO_COMPRESSION MZ_NO_COMPRESSION + #define Z_BEST_SPEED MZ_BEST_SPEED + #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION + #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION + #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY + #define Z_FILTERED MZ_FILTERED + #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY + #define Z_RLE MZ_RLE + #define Z_FIXED MZ_FIXED + #define Z_DEFLATED MZ_DEFLATED + #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS + #define alloc_func mz_alloc_func + #define free_func mz_free_func + #define internal_state mz_internal_state + #define z_stream mz_stream + #define deflateInit mz_deflateInit + #define deflateInit2 mz_deflateInit2 + #define deflateReset mz_deflateReset + #define deflate mz_deflate + #define deflateEnd mz_deflateEnd + #define deflateBound mz_deflateBound + #define compress mz_compress + #define compress2 mz_compress2 + #define compressBound mz_compressBound + #define inflateInit mz_inflateInit + #define inflateInit2 mz_inflateInit2 + #define inflate mz_inflate + #define inflateEnd mz_inflateEnd + #define uncompress mz_uncompress + #define crc32 mz_crc32 + #define adler32 mz_adler32 + #define MAX_WBITS 15 + #define MAX_MEM_LEVEL 9 + #define zError mz_error + #define ZLIB_VERSION MZ_VERSION + #define ZLIB_VERNUM MZ_VERNUM + #define ZLIB_VER_MAJOR MZ_VER_MAJOR + #define ZLIB_VER_MINOR MZ_VER_MINOR + #define ZLIB_VER_REVISION MZ_VER_REVISION + #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION + #define zlibVersion mz_version + #define zlib_version mz_version() +#endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES + +#endif // MINIZ_NO_ZLIB_APIS + +// ------------------- Types and macros + +typedef unsigned char mz_uint8; +typedef signed short mz_int16; +typedef unsigned short mz_uint16; +typedef unsigned int mz_uint32; +typedef unsigned int mz_uint; +typedef long long mz_int64; +typedef unsigned long long mz_uint64; +typedef int mz_bool; + +#define MZ_FALSE (0) +#define MZ_TRUE (1) + +// An attempt to work around MSVC's spammy "warning C4127: conditional expression is constant" message. +#ifdef _MSC_VER + #define MZ_MACRO_END while (0, 0) +#else + #define MZ_MACRO_END while (0) +#endif + +// ------------------- ZIP archive reading/writing + +#ifndef MINIZ_NO_ARCHIVE_APIS + +enum +{ + MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024, + MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260, + MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256 +}; + +typedef struct +{ + mz_uint32 m_file_index; + mz_uint32 m_central_dir_ofs; + mz_uint16 m_version_made_by; + mz_uint16 m_version_needed; + mz_uint16 m_bit_flag; + mz_uint16 m_method; +#ifndef MINIZ_NO_TIME + time_t m_time; +#endif + mz_uint32 m_crc32; + mz_uint64 m_comp_size; + mz_uint64 m_uncomp_size; + mz_uint16 m_internal_attr; + mz_uint32 m_external_attr; + mz_uint64 m_local_header_ofs; + mz_uint32 m_comment_size; + char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]; + char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE]; +} mz_zip_archive_file_stat; + +typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n); +typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n); + +struct mz_zip_internal_state_tag; +typedef struct mz_zip_internal_state_tag mz_zip_internal_state; + +typedef enum +{ + MZ_ZIP_MODE_INVALID = 0, + MZ_ZIP_MODE_READING = 1, + MZ_ZIP_MODE_WRITING = 2, + MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 +} mz_zip_mode; + +typedef struct mz_zip_archive_tag +{ + mz_uint64 m_archive_size; + mz_uint64 m_central_directory_file_ofs; + mz_uint m_total_files; + mz_zip_mode m_zip_mode; + + mz_uint m_file_offset_alignment; + + mz_alloc_func m_pAlloc; + mz_free_func m_pFree; + mz_realloc_func m_pRealloc; + void *m_pAlloc_opaque; + + mz_file_read_func m_pRead; + mz_file_write_func m_pWrite; + void *m_pIO_opaque; + + mz_zip_internal_state *m_pState; + +} mz_zip_archive; + +typedef enum +{ + MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100, + MZ_ZIP_FLAG_IGNORE_PATH = 0x0200, + MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400, + MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800 +} mz_zip_flags; + +// ZIP archive reading + +// Inits a ZIP archive reader. +// These functions read and validate the archive's central directory. +mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags); +mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags); + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags); +#endif + +// Returns the total number of files in the archive. +mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip); + +// Returns detailed information about an archive file entry. +mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat); + +// Determines if an archive file entry is a directory entry. +mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index); +mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index); + +// Retrieves the filename of an archive file entry. +// Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename. +mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size); + +// Attempts to locates a file in the archive's central directory. +// Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH +// Returns -1 if the file cannot be found. +int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); + +// Extracts a archive file to a memory buffer using no memory allocation. +mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); +mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); + +// Extracts a archive file to a memory buffer. +mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags); + +// Extracts a archive file to a dynamically allocated heap buffer. +void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags); +void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags); + +// Extracts a archive file using a callback function to output the file's data. +mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); + +#ifndef MINIZ_NO_STDIO +// Extracts a archive file to a disk file and sets its last accessed and modified times. +// This function only extracts files, not archive directory records. +mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags); +#endif + +// Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used. +mz_bool mz_zip_reader_end(mz_zip_archive *pZip); + +// ZIP archive writing + +#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + +// Inits a ZIP archive writer. +mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size); +mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size); + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning); +#endif + +// Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive. +// For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called. +// For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it). +// Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL. +// Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before +// the archive is finalized the file's central directory will be hosed. +mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename); + +// Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive. +// To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer. +// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. +mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags); +mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32); + +#ifndef MINIZ_NO_STDIO +// Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive. +// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. +mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); +#endif + +// Adds a file to an archive by fully cloning the data from another archive. +// This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields. +mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index); + +// Finalizes the archive by writing the central directory records followed by the end of central directory record. +// After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end(). +// An archive must be manually finalized by calling this function for it to be valid. +mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip); +mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize); + +// Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used. +// Note for the archive to be valid, it must have been finalized before ending. +mz_bool mz_zip_writer_end(mz_zip_archive *pZip); + +// Misc. high-level helper functions: + +// mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive. +// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. +mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); + +// Reads a single file from an archive into a heap block. +// Returns NULL on failure. +void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags); + +#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + +#endif // #ifndef MINIZ_NO_ARCHIVE_APIS + +// ------------------- Low-level Decompression API Definitions + +// Decompression flags used by tinfl_decompress(). +// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream. +// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input. +// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB). +// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes. +enum +{ + TINFL_FLAG_PARSE_ZLIB_HEADER = 1, + TINFL_FLAG_HAS_MORE_INPUT = 2, + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4, + TINFL_FLAG_COMPUTE_ADLER32 = 8 +}; + +// High level decompression functions: +// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc(). +// On entry: +// pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress. +// On return: +// Function returns a pointer to the decompressed data, or NULL on failure. +// *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data. +// The caller must call mz_free() on the returned block when it's no longer needed. +void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); + +// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory. +// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success. +#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1)) +size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); + +// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer. +// Returns 1 on success or 0 on failure. +typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); +int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor; + +// Max size of LZ dictionary. +#define TINFL_LZ_DICT_SIZE 32768 + +// Return status. +typedef enum +{ + TINFL_STATUS_BAD_PARAM = -3, + TINFL_STATUS_ADLER32_MISMATCH = -2, + TINFL_STATUS_FAILED = -1, + TINFL_STATUS_DONE = 0, + TINFL_STATUS_NEEDS_MORE_INPUT = 1, + TINFL_STATUS_HAS_MORE_OUTPUT = 2 +} tinfl_status; + +// Initializes the decompressor to its initial state. +#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END +#define tinfl_get_adler32(r) (r)->m_check_adler32 + +// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. +// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. +tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags); + +// Internal/private bits follow. +enum +{ + TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19, + TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS +}; + +typedef struct +{ + mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0]; + mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; +} tinfl_huff_table; + +#if MINIZ_HAS_64BIT_REGISTERS + #define TINFL_USE_64BIT_BITBUF 1 +#endif + +#if TINFL_USE_64BIT_BITBUF + typedef mz_uint64 tinfl_bit_buf_t; + #define TINFL_BITBUF_SIZE (64) +#else + typedef mz_uint32 tinfl_bit_buf_t; + #define TINFL_BITBUF_SIZE (32) +#endif + +struct tinfl_decompressor_tag +{ + mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES]; + tinfl_bit_buf_t m_bit_buf; + size_t m_dist_from_out_buf_start; + tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES]; + mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137]; +}; + +// ------------------- Low-level Compression API Definitions + +// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently). +#define TDEFL_LESS_MEMORY 0 + +// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search): +// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression). +enum +{ + TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF +}; + +// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data. +// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers). +// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing. +// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory). +// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1) +// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. +// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables. +// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks. +// The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK). +enum +{ + TDEFL_WRITE_ZLIB_HEADER = 0x01000, + TDEFL_COMPUTE_ADLER32 = 0x02000, + TDEFL_GREEDY_PARSING_FLAG = 0x04000, + TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000, + TDEFL_RLE_MATCHES = 0x10000, + TDEFL_FILTER_MATCHES = 0x20000, + TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000, + TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000 +}; + +// High level compression functions: +// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc(). +// On entry: +// pSrc_buf, src_buf_len: Pointer and size of source block to compress. +// flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression. +// On return: +// Function returns a pointer to the compressed data, or NULL on failure. +// *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. +// The caller must free() the returned block when it's no longer needed. +void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); + +// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. +// Returns 0 on failure. +size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); + +// Compresses an image to a compressed PNG file in memory. +// On entry: +// pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. +// The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory. +// level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL +// If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps). +// On return: +// Function returns a pointer to the compressed data, or NULL on failure. +// *pLen_out will be set to the size of the PNG image file. +// The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed. +void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip); +void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out); + +// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. +typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); + +// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. +mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 }; + +// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes). +#if TDEFL_LESS_MEMORY +enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; +#else +enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; +#endif + +// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions. +typedef enum +{ + TDEFL_STATUS_BAD_PARAM = -2, + TDEFL_STATUS_PUT_BUF_FAILED = -1, + TDEFL_STATUS_OKAY = 0, + TDEFL_STATUS_DONE = 1, +} tdefl_status; + +// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums +typedef enum +{ + TDEFL_NO_FLUSH = 0, + TDEFL_SYNC_FLUSH = 2, + TDEFL_FULL_FLUSH = 3, + TDEFL_FINISH = 4 +} tdefl_flush; + +// tdefl's compression state structure. +typedef struct +{ + tdefl_put_buf_func_ptr m_pPut_buf_func; + void *m_pPut_buf_user; + mz_uint m_flags, m_max_probes[2]; + int m_greedy_parsing; + mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size; + mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end; + mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer; + mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish; + tdefl_status m_prev_return_status; + const void *m_pIn_buf; + void *m_pOut_buf; + size_t *m_pIn_buf_size, *m_pOut_buf_size; + tdefl_flush m_flush; + const mz_uint8 *m_pSrc; + size_t m_src_buf_left, m_out_buf_ofs; + mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1]; + mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]; + mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]; + mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]; + mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]; +} tdefl_compressor; + +// Initializes the compressor. +// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory. +// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. +// If pBut_buf_func is NULL the user should always call the tdefl_compress() API. +// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) +tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. +tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush); + +// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. +// tdefl_compress_buffer() always consumes the entire input buffer. +tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush); + +tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d); +mz_uint32 tdefl_get_adler32(tdefl_compressor *d); + +// Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros. +#ifndef MINIZ_NO_ZLIB_APIS +// Create tdefl_compress() flags given zlib-style compression parameters. +// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files) +// window_bits may be -15 (raw deflate) or 15 (zlib) +// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED +mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy); +#endif // #ifndef MINIZ_NO_ZLIB_APIS + +#ifdef __cplusplus +} +#endif + +#endif // MINIZ_HEADER_INCLUDED diff --git a/test_conformance/CMakeCommon.txt b/test_conformance/CMakeCommon.txt new file mode 100644 index 00000000..62c339d7 --- /dev/null +++ b/test_conformance/CMakeCommon.txt @@ -0,0 +1,13 @@ +set_source_files_properties(COMPILE_FLAGS -msse2) + +string(TOLOWER ${MODULE_NAME} MODULE_NAME_LOWER) + +set(${MODULE_NAME}_OUT ${CONFORMANCE_PREFIX}${MODULE_NAME_LOWER}${CONFORMANCE_SUFFIX}) + +add_executable(${${MODULE_NAME}_OUT} ${${MODULE_NAME}_SOURCES}) + +set_source_files_properties(${${MODULE_NAME}_SOURCES} PROPERTIES LANGUAGE CXX) + +set_property(TARGET ${${MODULE_NAME}_OUT} PROPERTY FOLDER "CONFORMANCE${CONFORMANCE_SUFFIX}") + +TARGET_LINK_LIBRARIES(${${MODULE_NAME}_OUT} ${CLConform_LIBRARIES}) diff --git a/test_conformance/CMakeLists.txt b/test_conformance/CMakeLists.txt new file mode 100644 index 00000000..deb9d2ff --- /dev/null +++ b/test_conformance/CMakeLists.txt @@ -0,0 +1,92 @@ +# Remember current source directory (`test_conformance'). +set( CLConf_Install_Base_Dir "${CMAKE_CURRENT_SOURCE_DIR}" ) + +add_subdirectory( allocations ) +add_subdirectory( api ) +add_subdirectory( atomics ) +add_subdirectory( basic ) +add_subdirectory( buffers ) +add_subdirectory( commonfns ) +add_subdirectory( compatibility ) +add_subdirectory( compiler ) +add_subdirectory( computeinfo ) +add_subdirectory( contractions ) +add_subdirectory( conversions ) +if(D3D10_IS_SUPPORTED) + add_subdirectory( d3d10 ) +endif(D3D10_IS_SUPPORTED) +if(D3D11_IS_SUPPORTED) + add_subdirectory( d3d11 ) +endif(D3D11_IS_SUPPORTED) +add_subdirectory( device_partition ) +add_subdirectory( events ) +add_subdirectory( geometrics ) +if(GL_IS_SUPPORTED) + add_subdirectory( gl ) +endif(GL_IS_SUPPORTED) +if(GLES_IS_SUPPORTED) + add_subdirectory(gles) +endif(GLES_IS_SUPPORTED) +add_subdirectory( half ) +add_subdirectory( headers ) +add_subdirectory( images ) +add_subdirectory( integer_ops ) +add_subdirectory( math_brute_force ) +add_subdirectory( mem_host_flags ) +add_subdirectory( multiple_device_context ) +add_subdirectory( printf ) +add_subdirectory( profiling ) +add_subdirectory( relationals ) +add_subdirectory( select ) +add_subdirectory( thread_dimensions ) +add_subdirectory( vec_align ) +add_subdirectory( vec_step ) +add_subdirectory( c11_atomics ) +add_subdirectory( device_execution ) +add_subdirectory( non_uniform_work_group ) +add_subdirectory( SVM ) +add_subdirectory( generic_address_space ) +add_subdirectory( subgroups ) +add_subdirectory( workgroups ) +add_subdirectory( pipes ) +add_subdirectory( device_timer ) +add_subdirectory( clcpp ) + +set(CSV_FILES + opencl_conformance_tests_21_full_spirv.csv + opencl_conformance_tests_21_legacy_wimpy.csv + opencl_conformance_tests_22.csv + opencl_conformance_tests_generate_spirv.csv + opencl_conformance_tests_conversions.csv + opencl_conformance_tests_d3d.csv + opencl_conformance_tests_full.csv + opencl_conformance_tests_full_no_math_or_conversions.csv + opencl_conformance_tests_math.csv + opencl_conformance_tests_quick.csv +) +set(PY_FILES + run_conformance.py +) + +# Copy .csv files +foreach(FILE ${CSV_FILES}) + configure_file(${FILE} ${FILE} COPYONLY) +endforeach() + +# Copy test run script +foreach(FILE ${PY_FILES}) + if(WIN32) + configure_file(${FILE} ${FILE} COPYONLY) + else(WIN32) + # Copy to CMakeFiles + configure_file(${FILE} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${FILE} COPYONLY) + # Copy to final destination and set permissions + file(COPY ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${FILE} + DESTINATION ${CMAKE_BINARY_DIR}/test_conformance + FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ + GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + endif(WIN32) +endforeach() +foreach(FILE test_conformance/${PY_FILES}) + +endforeach() \ No newline at end of file diff --git a/test_conformance/Jamfile b/test_conformance/Jamfile new file mode 100644 index 00000000..5065fe45 --- /dev/null +++ b/test_conformance/Jamfile @@ -0,0 +1,24 @@ +project + : requirements + /harness//harness + off + ; + +use-project /harness : ../test_common/harness ; + +proj_lst = allocations api atomics basic buffers commonfns compiler + computeinfo contractions conversions events geometrics gl + half images integer_ops math_brute_force multiple_device_context + profiling relationals select thread_dimensions ; + +for proj in $(proj_lst) +{ + build-project $(proj) ; +} + +install data + : [ glob *.csv ] [ glob *.py ] + : debug:$(DIST)/debug/tests/test_conformance + release:$(DIST)/release/tests/test_conformance + ; + diff --git a/test_conformance/Makefile b/test_conformance/Makefile new file mode 100644 index 00000000..cfcb271b --- /dev/null +++ b/test_conformance/Makefile @@ -0,0 +1,61 @@ + +PRODUCTS = \ + allocations/ \ + api/ \ + atomics/ \ + basic/ \ + buffers/ \ + commonfns/ \ + compatibility/test_conformance/ \ + compiler/ \ + computeinfo/ \ + contractions/ \ + conversions/ \ + device_partition/ \ + events/ \ + geometrics/ \ + gl/ \ + half/ \ + headers/ \ + images/ \ + integer_ops/ \ + math_brute_force/ \ + mem_host_flags/ \ + multiple_device_context/ \ + printf/ \ + profiling/ \ + relationals/ \ + select/ \ + thread_dimensions/ \ + vec_align/ \ + vec_step/ \ + workgroups/ + + +TOP=$(shell pwd) + +all: $(PRODUCTS) + +clean: + @for testdir in $(dir $(PRODUCTS)) ; \ + do ( \ + echo "==================================================================================" ; \ + echo "Cleaning $$testdir" ; \ + echo "==================================================================================" ; \ + if test -d $$testdir; \ + then cd $$testdir && make clean; \ + else echo "Warning: Directory '$$testdir' Does Not Exist"; \ + fi; \ + ); \ + done \ + +$(PRODUCTS): + @echo "==================================================================================" ; + @echo "(`date "+%H:%M:%S"`) Make $@" ; + @echo "==================================================================================" ; + @if test -d $@; \ + then cd $(dir $@) && make -i; \ + else echo "Warning: Directory '$@' Does Not Exist"; \ + fi; \ + +.PHONY: clean $(PRODUCTS) all diff --git a/test_conformance/SVM/CMakeLists.txt b/test_conformance/SVM/CMakeLists.txt new file mode 100644 index 00000000..c7d0219e --- /dev/null +++ b/test_conformance/SVM/CMakeLists.txt @@ -0,0 +1,26 @@ +set(MODULE_NAME SVM) + +set(${MODULE_NAME}_SOURCES + main.cpp + test_allocate_shared_buffer.cpp + test_byte_granularity.cpp + test_cross_buffer_pointers.cpp + test_enqueue_api.cpp + test_fine_grain_memory_consistency.cpp + test_fine_grain_sync_buffers.cpp + test_pointer_passing.cpp + test_set_kernel_exec_info_svm_ptrs.cpp + test_shared_address_space_coarse_grain.cpp + test_shared_address_space_fine_grain.cpp + test_shared_address_space_fine_grain_buffers.cpp + test_shared_sub_buffers.cpp + test_migrate.cpp + ../../test_common/harness/testHarness.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) diff --git a/test_conformance/SVM/Makefile b/test_conformance/SVM/Makefile new file mode 100644 index 00000000..35487d35 --- /dev/null +++ b/test_conformance/SVM/Makefile @@ -0,0 +1,54 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + test_allocate_shared_buffer.cpp \ + test_byte_granularity.cpp \ + test_cross_buffer_pointers.cpp \ + test_enqueue_api.cpp \ + test_fine_grain_memory_consistency.cpp \ + test_fine_grain_sync_buffers.cpp \ + test_pointer_passing.cpp \ + test_set_kernel_exec_info_svm_ptrs.cpp \ + test_shared_address_space_coarse_grain.cpp \ + test_shared_address_space_fine_grain_buffers.cpp \ + test_shared_address_space_fine_grain.cpp \ + test_shared_sub_buffers.cpp \ + test_migrate.cpp \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/typeWrappers.cpp \ + ../../test_common/harness/mt19937.c \ + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +HEADERS = +TARGET = test_SVM +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/SVM/common.h b/test_conformance/SVM/common.h new file mode 100644 index 00000000..a1d57a5f --- /dev/null +++ b/test_conformance/SVM/common.h @@ -0,0 +1,101 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include "../../test_common/harness/compat.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/typeWrappers.h" + +#if (defined(_WIN32) || defined(_WIN64)) && defined(_MSC_VER) + #include +#endif + +typedef enum { + memory_order_relaxed, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst +} cl_memory_order; + +cl_int AtomicLoadExplicit(volatile cl_int * pValue, cl_memory_order order); +cl_int AtomicFetchAddExplicit(volatile cl_int *object, cl_int operand, cl_memory_order o); + +template +bool AtomicCompareExchangeStrongExplicit(volatile T *a, T *expected, T desired, + cl_memory_order order_success, + cl_memory_order order_failure) +{ + T tmp; +#if defined( _MSC_VER ) || (defined( __INTEL_COMPILER ) && defined(WIN32)) + tmp = (T)InterlockedCompareExchange((volatile LONG *)a, (LONG)desired, *(LONG *)expected); +#elif defined(__GNUC__) + tmp = (T)__sync_val_compare_and_swap((volatile intptr_t*)a, (intptr_t)(*expected), (intptr_t)desired); +#else + log_info("Host function not implemented: atomic_compare_exchange\n"); + tmp = 0; +#endif + if(tmp == *expected) + return true; + *expected = tmp; + return false; +} + +// this checks for a NULL ptr and/or an error code +#define test_error2(error_code, ptr, msg) { if(error != 0) { test_error(error_code, msg); } else { if(NULL == ptr) {print_null_error(msg); return -1;} } } +#define print_null_error(msg) log_error("ERROR: %s! (NULL pointer detected %s:%d)\n", msg, __FILE__, __LINE__ ); + +// max possible number of queues needed, 1 for each device in platform. +#define MAXQ 32 + +typedef struct Node{ + cl_int global_id; + cl_int position_in_list; + struct Node* pNext; +} Node; + +extern void create_linked_lists(Node* pNodes, size_t num_lists, int list_length); +extern cl_int verify_linked_lists(Node* pNodes, size_t num_lists, int list_length); + +extern cl_int create_linked_lists_on_device(int qi, cl_command_queue q, cl_mem allocator, cl_kernel k, size_t numLists ); +extern cl_int verify_linked_lists_on_device(int qi, cl_command_queue q, cl_mem num_correct, cl_kernel k, cl_int ListLength, size_t numLists ); +extern cl_int create_linked_lists_on_device_no_map(int qi, cl_command_queue q, size_t *pAllocator, cl_kernel k, size_t numLists ); +extern cl_int verify_linked_lists_on_device_no_map(int qi, cl_command_queue q, cl_int *pNum_correct, cl_kernel k, cl_int ListLength, size_t numLists ); + +extern int test_byte_granularity(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_set_kernel_exec_info_svm_ptrs(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_fine_grain_memory_consistency(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_fine_grain_sync_buffers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_shared_address_space_coarse_grain_old_api(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_shared_address_space_coarse_grain_new_api(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_shared_address_space_fine_grain_buffers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_shared_address_space_fine_grain(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_cross_buffer_pointers_coarse_grain(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_svm_pointer_passing(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_allocate_shared_buffer(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_shared_sub_buffers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_enqueue_api(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_migrate(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern cl_int create_cl_objects(cl_device_id device_from_harness, const char** ppCodeString, cl_context* context, cl_program *program, cl_command_queue *queues, cl_uint *num_devices, cl_device_svm_capabilities required_svm_caps); + +extern const char *linked_list_create_and_verify_kernels[]; + +#endif // #ifndef __COMMON_H__ + diff --git a/test_conformance/SVM/main.cpp b/test_conformance/SVM/main.cpp new file mode 100644 index 00000000..87c786da --- /dev/null +++ b/test_conformance/SVM/main.cpp @@ -0,0 +1,317 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/kernelHelpers.h" + +#include "common.h" + +// SVM Atomic wrappers. +// Platforms that support SVM atomics (atomics that work across the host and devices) need to implement these host side functions correctly. +// Platforms that do not support SVM atomics can simpy implement these functions as empty stubs since the functions will not be called. +// For now only Windows x86 is implemented, add support for other platforms as needed. +cl_int AtomicLoadExplicit(volatile cl_int * pValue, cl_memory_order order) +{ +#if (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))) || (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) + return *pValue; // provided the value is aligned x86 doesn't need anything more than this for seq_cst. +#elif defined(__GNUC__) + return __sync_add_and_fetch(pValue, 0); +#else + log_error("ERROR: AtomicLoadExplicit function not implemented\n"); + return -1; +#endif +} +// all the x86 atomics are seq_cst, so don't need to do anything with the memory order parameter. +cl_int AtomicFetchAddExplicit(volatile cl_int *object, cl_int operand, cl_memory_order o) +{ +#if (defined(_WIN32) || defined(_WIN64)) && defined(_MSC_VER) + return InterlockedExchangeAdd( (volatile LONG*) object, operand); +#elif defined(__GNUC__) + return __sync_fetch_and_add(object, operand); +#else + log_error("ERROR: AtomicFetchAddExplicit function not implemented\n"); + return -1; +#endif +} + +cl_int AtomicExchangeExplicit(volatile cl_int *object, cl_int desired, cl_memory_order mo) +{ +#if (defined(_WIN32) || defined(_WIN64)) && defined(_MSC_VER) + return InterlockedExchange( (volatile LONG*) object, desired); +#elif defined(__GNUC__) + return __sync_lock_test_and_set(object, desired); +#else + log_error("ERROR: AtomicExchangeExplicit function not implemented\n"); + return -1; +#endif +} + + +const char *linked_list_create_and_verify_kernels[] = { + "typedef struct Node {\n" + " int global_id;\n" + " int position_in_list;\n" + " __global struct Node* pNext;\n" + "} Node;\n" + "\n" + // The allocation_index parameter must be initialized on the host to N work-items + // The first N nodes in pNodes will be the heads of the lists. + "__kernel void create_linked_lists(__global Node* pNodes, volatile __attribute__((nosvm)) __global int* allocation_index, int list_length)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " __global Node *pNode = &pNodes[i];\n" + "\n" + " pNode->global_id = i;\n" + " pNode->position_in_list = 0;\n" + "\n" + " __global Node *pNew;\n" + " for(int j=1; j < list_length; j++)\n" + " {\n" + " pNew = &pNodes[ atomic_inc(allocation_index) ];// allocate a new node\n" + " pNew->global_id = i;\n" + " pNew->position_in_list = j;\n" + " pNode->pNext = pNew; // link new node onto end of list\n" + " pNode = pNew; // move to end of list\n" + " }\n" + "}\n" + + "__kernel void verify_linked_lists(__global Node* pNodes, volatile __global uint* num_correct, int list_length)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " __global Node *pNode = &pNodes[i];\n" + "\n" + " for(int j=0; j < list_length; j++)\n" + " {\n" + " if( pNode->global_id == i && pNode->position_in_list == j)\n" + " {\n" + " atomic_inc(num_correct);\n" + " } \n" + " else {\n" + " break;\n" + " }\n" + " pNode = pNode->pNext;\n" + " }\n" + "}\n" +}; + + +// The first N nodes in pNodes will be the heads of the lists. +void create_linked_lists(Node* pNodes, size_t num_lists, int list_length) +{ + size_t allocation_index = num_lists; // heads of lists are in first num_lists nodes. + + for(cl_uint i = 0; i < num_lists; i++) + { + Node *pNode = &pNodes[i]; + pNode->global_id = i; + pNode->position_in_list = 0; + Node *pNew; + for(int j=1; j < list_length; j++) + { + pNew = &pNodes[ allocation_index++ ];// allocate a new node + pNew->global_id = i; + pNew->position_in_list = j; + pNode->pNext = pNew; // link new node onto end of list + pNode = pNew; // move to end of list + } + } +} + +cl_int verify_linked_lists(Node* pNodes, size_t num_lists, int list_length) +{ + cl_int error = CL_SUCCESS; + int numCorrect = 0; + + log_info(" and verifying on host "); + for(cl_uint i=0; i < num_lists; i++) + { + Node *pNode = &pNodes[i]; + for(int j=0; j < list_length; j++) + { + if( pNode->global_id == i && pNode->position_in_list == j) + { + numCorrect++; + } + else { + break; + } + pNode = pNode->pNext; + } + } + if(numCorrect != list_length * (cl_uint)num_lists) + { + error = -1; + log_info("Failed\n"); + } + else + log_info("Passed\n"); + + return error; +} + +// Note that we don't use the context provided by the test harness since it doesn't support multiple devices, +// so we create are own context here that has all devices, we use the same platform that the harness used. +cl_int create_cl_objects(cl_device_id device_from_harness, const char** ppCodeString, cl_context* context, cl_program *program, cl_command_queue *queues, cl_uint *num_devices, cl_device_svm_capabilities required_svm_caps) +{ + cl_int error; + + cl_platform_id platform_id; + // find out what platform the harness is using. + error = clGetDeviceInfo(device_from_harness, CL_DEVICE_PLATFORM,sizeof(cl_platform_id),&platform_id,NULL); + test_error(error,"clGetDeviceInfo failed"); + + error = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ALL, 0, NULL, num_devices ); + test_error(error, "clGetDeviceIDs failed"); + + std::vector devicesTmp(*num_devices), devices, capable_devices; + + error = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ALL, *num_devices, &devicesTmp[0], NULL ); + test_error(error, "clGetDeviceIDs failed"); + + devices.push_back(device_from_harness); + for (size_t i = 0; i < devicesTmp.size(); ++i) + { + if (device_from_harness != devicesTmp[i]) + devices.push_back(devicesTmp[i]); + } + + // Select only the devices that support the SVM level needed for the test. + // Note that if requested SVM capabilities are not supported by any device then the test still passes (even though it does not execute). + cl_device_svm_capabilities caps; + cl_uint num_capable_devices = 0; + for(cl_uint i = 0; i < *num_devices; i++) + { + size_t ret_len = 0; + error = clGetDeviceInfo(devices[i], CL_DEVICE_VERSION, 0, 0, &ret_len); + if (error != CL_SUCCESS) + { + log_error("clGetDeviceInfo failed %s\n", IGetErrorString(error)); + return -1; + } + + std::vector oclVersion(ret_len + 1); + error = clGetDeviceInfo(devices[i], CL_DEVICE_VERSION, sizeof(char) * oclVersion.size(), &oclVersion[0], 0); + if (error != CL_SUCCESS) + { + log_error("clGetDeviceInfo failed %s\n", IGetErrorString(error)); + return -1; + } + + std::string versionStr(&oclVersion[7]); + std::stringstream stream; + stream << versionStr; + + double version = 0.0; + stream >> version; + + if(device_from_harness != devices[i] && version < 2.0) + { + continue; + } + + error = clGetDeviceInfo(devices[i], CL_DEVICE_SVM_CAPABILITIES, sizeof(cl_device_svm_capabilities), &caps, NULL); + test_error(error,"clGetDeviceInfo failed for CL_DEVICE_MEM_SHARING"); + if(caps & (~(CL_DEVICE_SVM_COARSE_GRAIN_BUFFER | CL_DEVICE_SVM_FINE_GRAIN_BUFFER | CL_DEVICE_SVM_FINE_GRAIN_SYSTEM | CL_DEVICE_SVM_ATOMICS))) + { + log_error("clGetDeviceInfo returned an invalid cl_device_svm_capabilities value"); + return -1; + } + if((caps & required_svm_caps) == required_svm_caps) + { + capable_devices.push_back(devices[i]); + ++num_capable_devices; + } + } + devices = capable_devices; // the only devices we care about from here on are the ones capable of supporting the requested SVM level. + *num_devices = num_capable_devices; + if(num_capable_devices == 0) + // if(svm_level > CL_DEVICE_COARSE_SVM && 0 == num_capable_devices) + { + log_info("Requested SVM level not supported by any device on this platform, test not executed.\n"); + return 1; // 1 indicates do not execute, but counts as passing. + } + + cl_context_properties context_properties[3] = {CL_CONTEXT_PLATFORM, (cl_context_properties)platform_id, NULL }; + *context = clCreateContext(context_properties, *num_devices, &devices[0], NULL, NULL, &error); + test_error(error, "Unable to create context" ); + + // *queues = (cl_command_queue *) malloc( *num_devices * sizeof( cl_command_queue ) ); + + for(cl_uint i = 0; i < *num_devices; i++) + { + queues[i] = clCreateCommandQueueWithProperties(*context, devices[i], 0, &error); + test_error(error, "clCreateCommandQueue failed"); + } + + if(ppCodeString) + { + error = create_single_kernel_helper(*context, program, 0, 1, ppCodeString, 0, "-cl-std=CL2.0"); + test_error( error, "failed to create program" ); + } + + return 0; +} + +basefn basefn_list[] = { + test_byte_granularity, + test_set_kernel_exec_info_svm_ptrs, + test_fine_grain_memory_consistency, + test_fine_grain_sync_buffers, + test_shared_address_space_fine_grain, + test_shared_sub_buffers, + test_shared_address_space_fine_grain_buffers, + test_allocate_shared_buffer, + test_shared_address_space_coarse_grain_old_api, + test_shared_address_space_coarse_grain_new_api, + test_cross_buffer_pointers_coarse_grain, + test_svm_pointer_passing, + test_enqueue_api, + test_migrate, +}; + +const char *basefn_names[] = { + "svm_byte_granularity", + "svm_set_kernel_exec_info_svm_ptrs", + "svm_fine_grain_memory_consistency", + "svm_fine_grain_sync_buffers", + "svm_shared_address_space_fine_grain", + "svm_shared_sub_buffers", + "svm_shared_address_space_fine_grain_buffers", + "svm_allocate_shared_buffer", + "svm_shared_address_space_coarse_grain_old_api", + "svm_shared_address_space_coarse_grain_new_api", + "svm_cross_buffer_pointers_coarse_grain", + "svm_pointer_passing", + "svm_enqueue_api", + "svm_migrate_mem", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + + +int main(int argc, const char *argv[]) +{ + return runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false, true, 0 ); +} + + + diff --git a/test_conformance/SVM/test_allocate_shared_buffer.cpp b/test_conformance/SVM/test_allocate_shared_buffer.cpp new file mode 100644 index 00000000..7d555c8d --- /dev/null +++ b/test_conformance/SVM/test_allocate_shared_buffer.cpp @@ -0,0 +1,107 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" + +const cl_mem_flags flag_set[] = { + CL_MEM_READ_WRITE, + CL_MEM_WRITE_ONLY, + CL_MEM_READ_ONLY, + CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER, + CL_MEM_WRITE_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER, + CL_MEM_READ_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER, + CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS, + CL_MEM_WRITE_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS, + CL_MEM_READ_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS, + 0 +}; +const char* flag_set_names[] = { + "CL_MEM_READ_WRITE", + "CL_MEM_WRITE_ONLY", + "CL_MEM_READ_ONLY", + "CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER", + "CL_MEM_WRITE_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER", + "CL_MEM_READ_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER", + "CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS", + "CL_MEM_WRITE_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS", + "CL_MEM_READ_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS", + "0" +}; + + +int test_allocate_shared_buffer(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements) +{ + clContextWrapper context = NULL; + clProgramWrapper program = NULL; + cl_uint num_devices = 0; + cl_int err = CL_SUCCESS; + clCommandQueueWrapper queues[MAXQ]; + + cl_device_svm_capabilities caps; + err = clGetDeviceInfo(deviceID, CL_DEVICE_SVM_CAPABILITIES, sizeof(cl_device_svm_capabilities), &caps, NULL); + test_error(err,"clGetDeviceInfo failed for CL_DEVICE_SVM_CAPABILITIES"); + + // under construction... + err = create_cl_objects(deviceID, NULL, &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER); + if(err) return -1; + + size_t size = 1024; + + // iteration over flag combos + int num_flags = sizeof(flag_set)/sizeof(cl_mem_flags); + for(int i = 0; i < num_flags; i++) + { + if (((flag_set[i] & CL_MEM_SVM_FINE_GRAIN_BUFFER) != 0 && (caps & CL_DEVICE_SVM_FINE_GRAIN_BUFFER) == 0) + || ((flag_set[i] & CL_MEM_SVM_ATOMICS) != 0 && (caps & CL_DEVICE_SVM_ATOMICS) == 0)) + { + log_info("Skipping clSVMalloc with flags: %s\n", flag_set_names[i]); + continue; + } + + log_info("Testing clSVMalloc with flags: %s\n", flag_set_names[i]); + cl_char *pBufData1 = (cl_char*) clSVMAlloc(context, flag_set[i], size, 0); + if(pBufData1 == NULL) + { + log_error("SVMalloc returned NULL"); + return -1; + } + + { + clMemWrapper buf = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, size, pBufData1, &err); + test_error(err,"clCreateBuffer failed"); + + cl_char *pBufData2 = NULL; + cl_uint flags = CL_MAP_READ | CL_MAP_READ; + if(flag_set[i] & CL_MEM_HOST_READ_ONLY) flags ^= CL_MAP_WRITE; + if(flag_set[i] & CL_MEM_HOST_WRITE_ONLY) flags ^= CL_MAP_READ; + + if(!(flag_set[i] & CL_MEM_HOST_NO_ACCESS)) + { + pBufData2 = (cl_char*) clEnqueueMapBuffer(queues[0], buf, CL_TRUE, flags, 0, size, 0, NULL,NULL, &err); + test_error(err, "clEnqueueMapBuffer failed"); + + if(pBufData2 != pBufData1 || NULL == pBufData1) + { + log_error("SVM pointer returned by clEnqueueMapBuffer doesn't match pointer returned by clSVMalloc"); + return -1; + } + } + } + + clSVMFree(context, pBufData1); + } + + return 0; +} diff --git a/test_conformance/SVM/test_byte_granularity.cpp b/test_conformance/SVM/test_byte_granularity.cpp new file mode 100644 index 00000000..f1e58f70 --- /dev/null +++ b/test_conformance/SVM/test_byte_granularity.cpp @@ -0,0 +1,148 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" + +const char *byte_manipulation_kernels[] = { + // Each device will write it's id into the bytes that it "owns", ownership is based on round robin (global_id % num_id) + // num_id is equal to number of SVM devices in the system plus one (for the host code). + // id is the index (id) of the device that this kernel is executing on. + // For example, if there are 2 SVM devices and the host; the buffer should look like this after each device and the host write their id's: + // 0, 1, 2, 0, 1, 2, 0, 1, 2... + "__kernel void write_owned_locations(__global char* a, uint num_id, uint id)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " int owner = i % num_id;\n" + " if(id == owner) \n" + " a[i] = id;\n" // modify location if it belongs to this device, write id + "}\n" + + // Verify that a device can see the byte sized updates from the other devices, sum up the device id's and see if they match expected value. + // Note: this must be called with a reduced NDRange so that neighbor acesses don't go past end of buffer. + // For example if there are two SVM devices and the host (3 total devices) the buffer should look like this: + // 0,1,2,0,1,2... + // and the expected sum at each point is 0+1+2 = 3. + "__kernel void sum_neighbor_locations(__global char* a, uint num_devices, volatile __global uint* error_count)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " uint expected_sum = (num_devices * (num_devices - 1))/2;\n" + " uint sum = 0;\n" + " for(uint j=0; j 0) + failed = true; + } + cl_uint expected = (num_devices_plus_host * (num_devices_plus_host - 1))/2; + // check that host can see the byte writes made by the devices. + for(cl_uint i = 0; i < num_elements - num_devices_plus_host; i++) + { + int sum = 0; + for(cl_uint j=0; j < num_devices_plus_host; j++) sum += pA[i+j]; + if(sum != expected) + failed = true; + } + + clSVMFree(context, pA); + for(cl_uint i=0; i < num_devices; i++) clSVMFree(context, error_counts[i]); + + if(failed) + return -1; + return 0; +} diff --git a/test_conformance/SVM/test_cross_buffer_pointers.cpp b/test_conformance/SVM/test_cross_buffer_pointers.cpp new file mode 100644 index 00000000..2ee76d92 --- /dev/null +++ b/test_conformance/SVM/test_cross_buffer_pointers.cpp @@ -0,0 +1,219 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" + +// create linked lists that use nodes from two different buffers. +const char *SVMCrossBufferPointers_test_kernel[] = { + "\n" + "typedef struct Node {\n" + " int global_id;\n" + " int position_in_list;\n" + " __global struct Node* pNext;\n" + "} Node;\n" + "\n" + "__global Node* allocate_node(__global Node* pNodes1, __global Node* pNodes2, volatile __global int* allocation_index, size_t i)\n" + "{\n" + // mix things up, adjacent work items will allocate from different buffers + " if(i & 0x1)\n" + " return &pNodes1[atomic_inc(allocation_index)];\n" + " else\n" + " return &pNodes2[atomic_inc(allocation_index)];\n" + "}\n" + "\n" + // The allocation_index parameter must be initialized on the host to N work-items + // The first N nodes in pNodes will be the heads of the lists. + "__kernel void create_linked_lists(__global Node* pNodes, __global Node* pNodes2, volatile __global int* allocation_index, int list_length)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " __global Node *pNode = &pNodes[i];\n" + "\n" + " pNode->global_id = i;\n" + " pNode->position_in_list = 0;\n" + "\n" + " __global Node *pNew;\n" + " for(int j=1; j < list_length; j++)\n" + " {\n" + " pNew = allocate_node(pNodes, pNodes2, allocation_index, i);\n" + " pNew->global_id = i;\n" + " pNew->position_in_list = j;\n" + " pNode->pNext = pNew; // link new node onto end of list\n" + " pNode = pNew; // move to end of list\n" + " }\n" + "}\n" + "\n" + "__kernel void verify_linked_lists(__global Node* pNodes, __global Node* pNodes2, volatile __global uint* num_correct, int list_length)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " __global Node *pNode = &pNodes[i];\n" + "\n" + " for(int j=0; j < list_length; j++)\n" + " {\n" + " if( pNode->global_id == i && pNode->position_in_list == j)\n" + " {\n" + " atomic_inc(num_correct);\n" + " }\n" + " else {\n" + " break;\n" + " }\n" + " pNode = pNode->pNext;\n" + " }\n" + "}\n" +}; + + +// Creates linked list using host code. +cl_int create_linked_lists_on_host(cl_command_queue cmdq, cl_mem nodes, cl_mem nodes2, cl_int ListLength, size_t numLists ) +{ + cl_int error = CL_SUCCESS; + + log_info("SVM: creating linked list on host "); + + Node *pNodes = (Node*) clEnqueueMapBuffer(cmdq, nodes, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(Node)*ListLength*numLists, 0, NULL,NULL, &error); + test_error2(error, pNodes, "clEnqueueMapBuffer failed"); + + Node *pNodes2 = (Node*) clEnqueueMapBuffer(cmdq, nodes2, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(Node)*ListLength*numLists, 0, NULL,NULL, &error); + test_error2(error, pNodes2, "clEnqueueMapBuffer failed"); + + create_linked_lists(pNodes, numLists, ListLength); + + error = clEnqueueUnmapMemObject(cmdq, nodes, pNodes, 0,NULL,NULL); + test_error(error, "clEnqueueUnmapMemObject failed"); + error = clEnqueueUnmapMemObject(cmdq, nodes2, pNodes2, 0,NULL,NULL); + test_error(error, "clEnqueueUnmapMemObject failed"); + error = clFinish(cmdq); + test_error(error, "clFinish failed"); + return error; +} + +// Verify correctness of the linked list using host code. +cl_int verify_linked_lists_on_host(int ci, cl_command_queue cmdq, cl_mem nodes, cl_mem nodes2, cl_int ListLength, size_t numLists ) +{ + cl_int error = CL_SUCCESS; + + //log_info(" and verifying on host "); + + Node *pNodes = (Node*) clEnqueueMapBuffer(cmdq, nodes, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(Node)*ListLength * numLists, 0, NULL,NULL, &error); + test_error2(error, pNodes, "clEnqueueMapBuffer failed"); + Node *pNodes2 = (Node*) clEnqueueMapBuffer(cmdq, nodes2, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(Node)*ListLength * numLists, 0, NULL,NULL, &error); + test_error2(error, pNodes, "clEnqueueMapBuffer failed"); + + error = verify_linked_lists(pNodes, numLists, ListLength); + if(error) return -1; + + error = clEnqueueUnmapMemObject(cmdq, nodes, pNodes, 0,NULL,NULL); + test_error(error, "clEnqueueUnmapMemObject failed"); + error = clEnqueueUnmapMemObject(cmdq, nodes2, pNodes2, 0,NULL,NULL); + test_error(error, "clEnqueueUnmapMemObject failed"); + error = clFinish(cmdq); + test_error(error, "clFinish failed"); + return error; +} + +// This tests that shared buffers are able to contain pointers that point to other shared buffers. +// This tests that all devices and the host share a common address space; using only the coarse-grain features. +// This is done by creating a linked list on a device and then verifying the correctness of the list +// on another device or the host. +// The linked list nodes are allocated from two different buffers this is done to ensure that cross buffer pointers work correctly. +// This basic test is performed for all combinations of devices and the host. +int test_cross_buffer_pointers_coarse_grain(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements) +{ + clContextWrapper context = NULL; + clProgramWrapper program = NULL; + cl_uint num_devices = 0; + cl_int error = CL_SUCCESS; + clCommandQueueWrapper queues[MAXQ]; + + error = create_cl_objects(deviceID, &SVMCrossBufferPointers_test_kernel[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER); + if(error) return -1; + + size_t numLists = num_elements; + cl_int ListLength = 32; + + clKernelWrapper kernel_create_lists = clCreateKernel(program, "create_linked_lists", &error); + test_error(error, "clCreateKernel failed"); + + clKernelWrapper kernel_verify_lists = clCreateKernel(program, "verify_linked_lists", &error); + test_error(error, "clCreateKernel failed"); + + // this buffer holds some of the linked list nodes. + Node* pNodes = (Node*) clSVMAlloc(context, CL_MEM_READ_WRITE, sizeof(Node)*ListLength*numLists, 0); + + // this buffer holds some of the linked list nodes. + Node* pNodes2 = (Node*) clSVMAlloc(context, CL_MEM_READ_WRITE, sizeof(Node)*ListLength*numLists, 0); + + { + clMemWrapper nodes = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(Node)*ListLength*numLists, pNodes, &error); + test_error(error, "clCreateBuffer failed."); + + clMemWrapper nodes2 = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(Node)*ListLength*numLists, pNodes2, &error); + test_error(error, "clCreateBuffer failed."); + + // this buffer holds the index into the nodes buffer that is used for node allocation + clMemWrapper allocator = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, &error); + test_error(error, "clCreateBuffer failed."); + + // this buffer holds the count of correct nodes which is computed by the verify kernel. + clMemWrapper num_correct = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, &error); + test_error(error, "clCreateBuffer failed."); + + error |= clSetKernelArg(kernel_create_lists, 0, sizeof(void*), (void *) &nodes); + //error |= clSetKernelArgSVMPointer(kernel_create_lists, 0, (void *) pNodes); + error |= clSetKernelArg(kernel_create_lists, 1, sizeof(void*), (void *) &nodes2); + error |= clSetKernelArg(kernel_create_lists, 2, sizeof(void*), (void *) &allocator); + error |= clSetKernelArg(kernel_create_lists, 3, sizeof(cl_int), (void *) &ListLength); + + error |= clSetKernelArg(kernel_verify_lists, 0, sizeof(void*), (void *) &nodes); + error |= clSetKernelArg(kernel_verify_lists, 1, sizeof(void*), (void *) &nodes2); + error |= clSetKernelArg(kernel_verify_lists, 2, sizeof(void*), (void *) &num_correct); + error |= clSetKernelArg(kernel_verify_lists, 3, sizeof(cl_int), (void *) &ListLength); + test_error(error, "clSetKernelArg failed"); + + // Create linked list on one device and verify on another device (or the host). + // Do this for all possible combinations of devices and host within the platform. + for (int ci=0; ci<(int)num_devices+1; ci++) // ci is CreationIndex, index of device/q to create linked list on + { + for (int vi=0; vi<(int)num_devices+1; vi++) // vi is VerificationIndex, index of device/q to verify linked list on + { + if(ci == num_devices) // last device index represents the host, note the num_device+1 above. + { + error = create_linked_lists_on_host(queues[0], nodes, nodes2, ListLength, numLists); + if(error) return -1; + } + else + { + error = create_linked_lists_on_device(ci, queues[ci], allocator, kernel_create_lists, numLists); + if(error) return -1; + } + + if(vi == num_devices) + { + error = verify_linked_lists_on_host(vi, queues[0], nodes, nodes2, ListLength, numLists); + if(error) return -1; + } + else + { + error = verify_linked_lists_on_device(vi, queues[vi], num_correct, kernel_verify_lists, ListLength, numLists); + if(error) return -1; + } + } // inner loop, vi + } // outer loop, ci + } + + clSVMFree(context, pNodes2); + clSVMFree(context, pNodes); + + return 0; +} diff --git a/test_conformance/SVM/test_enqueue_api.cpp b/test_conformance/SVM/test_enqueue_api.cpp new file mode 100644 index 00000000..6a04e955 --- /dev/null +++ b/test_conformance/SVM/test_enqueue_api.cpp @@ -0,0 +1,254 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" +#include "../../test_common/harness/mt19937.h" + +#include + +typedef struct +{ + cl_uint status; + cl_uint num_svm_pointers; + std::vector svm_pointers; +} CallbackData; + +void generate_data(std::vector &data, size_t size, MTdata seed) +{ + cl_uint randomData = genrand_int32(seed); + cl_uint bitsLeft = 32; + + for( size_t i = 0; i < size; i++ ) + { + if( 0 == bitsLeft) + { + randomData = genrand_int32(seed); + bitsLeft = 32; + } + data[i] = (cl_uchar)( randomData & 255 ); + randomData >>= 8; randomData -= 8; + } +} + +//callback which will be passed to clEnqueueSVMFree command +void CL_CALLBACK callback_svm_free(cl_command_queue queue, cl_uint num_svm_pointers, void * svm_pointers[], void * user_data) +{ + CallbackData *data = (CallbackData *)user_data; + data->num_svm_pointers = num_svm_pointers; + data->svm_pointers.resize(num_svm_pointers, 0); + + cl_context context; + if(clGetCommandQueueInfo(queue, CL_QUEUE_CONTEXT, sizeof(cl_context), &context, 0) != CL_SUCCESS) + { + log_error("clGetCommandQueueInfo failed in the callback\n"); + return; + } + + for (size_t i = 0; i < num_svm_pointers; ++i) + { + data->svm_pointers[i] = svm_pointers[i]; + clSVMFree(context, svm_pointers[i]); + } + + data->status = 1; +} + +int test_enqueue_api(cl_device_id deviceID, cl_context c, cl_command_queue queue, int num_elements) +{ + clContextWrapper context = NULL; + clCommandQueueWrapper queues[MAXQ]; + cl_uint num_devices = 0; + const size_t elementNum = 1024; + const size_t numSVMBuffers = 32; + cl_int error = CL_SUCCESS; + RandomSeed seed(0); + + error = create_cl_objects(deviceID, NULL, &context, NULL, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER); + if(error) return -1; + + queue = queues[0]; + + //all possible sizes of vectors and scalars + size_t typeSizes[] = { + sizeof(cl_uchar), + sizeof(cl_uchar2), + sizeof(cl_uchar3), + sizeof(cl_uchar4), + sizeof(cl_uchar8), + sizeof(cl_uchar16), + sizeof(cl_ushort), + sizeof(cl_ushort2), + sizeof(cl_ushort3), + sizeof(cl_ushort4), + sizeof(cl_ushort8), + sizeof(cl_ushort16), + sizeof(cl_uint), + sizeof(cl_uint2), + sizeof(cl_uint3), + sizeof(cl_uint4), + sizeof(cl_uint8), + sizeof(cl_uint16), + sizeof(cl_ulong), + sizeof(cl_ulong2), + sizeof(cl_ulong3), + sizeof(cl_ulong4), + sizeof(cl_ulong8), + sizeof(cl_ulong16), + }; + + for (size_t i = 0; i < ( sizeof(typeSizes) / sizeof(typeSizes[0]) ); ++i) + { + //generate initial data + std::vector fillData0(typeSizes[i]), fillData1(typeSizes[i], 0), fillData2(typeSizes[i]); + generate_data(fillData0, typeSizes[i], seed); + generate_data(fillData2, typeSizes[i], seed); + + cl_uchar *srcBuffer = (cl_uchar *)clSVMAlloc(context, CL_MEM_READ_WRITE, elementNum * typeSizes[i], 0); + cl_uchar *dstBuffer = (cl_uchar *)clSVMAlloc(context, CL_MEM_READ_WRITE, elementNum * typeSizes[i], 0); + + clEventWrapper userEvent = clCreateUserEvent(context, &error); + test_error(error, "clCreateUserEvent failed"); + + clEventWrapper eventMemFill; + error = clEnqueueSVMMemFill(queue, srcBuffer, &fillData0[0], typeSizes[i], elementNum * typeSizes[i], 1, &userEvent, &eventMemFill); + test_error(error, "clEnqueueSVMMemFill failed"); + + clEventWrapper eventMemcpy; + error = clEnqueueSVMMemcpy(queue, CL_FALSE, dstBuffer, srcBuffer, elementNum * typeSizes[i], 1, &eventMemFill, &eventMemcpy); + test_error(error, "clEnqueueSVMMemcpy failed"); + + error = clSetUserEventStatus(userEvent, CL_COMPLETE); + test_error(error, "clSetUserEventStatus failed"); + + clEventWrapper eventMap; + error = clEnqueueSVMMap(queue, CL_FALSE, CL_MAP_READ | CL_MAP_WRITE, dstBuffer, elementNum * typeSizes[i], 1, &eventMemcpy, &eventMap); + test_error(error, "clEnqueueSVMMap failed"); + + error = clWaitForEvents(1, &eventMap); + test_error(error, "clWaitForEvents failed"); + + //data verification + for (size_t j = 0; j < elementNum * typeSizes[i]; ++j) + { + if (dstBuffer[j] != fillData0[j % typeSizes[i]]) + { + log_error("Invalid data at index %ld, expected %d, got %d\n", j, fillData0[j % typeSizes[i]], dstBuffer[j]); + return -1; + } + } + + clEventWrapper eventUnmap; + error = clEnqueueSVMUnmap(queue, dstBuffer, 0, 0, &eventUnmap); + test_error(error, "clEnqueueSVMUnmap failed"); + + error = clEnqueueSVMMemFill(queue, srcBuffer, &fillData2[0], typeSizes[i], elementNum * typeSizes[i] / 2, 0, 0, 0); + test_error(error, "clEnqueueSVMMemFill failed"); + + error = clEnqueueSVMMemFill(queue, dstBuffer + elementNum * typeSizes[i] / 2, &fillData2[0], typeSizes[i], elementNum * typeSizes[i] / 2, 0, 0, 0); + test_error(error, "clEnqueueSVMMemFill failed"); + + error = clEnqueueSVMMemcpy(queue, CL_FALSE, dstBuffer, srcBuffer, elementNum * typeSizes[i] / 2, 0, 0, 0); + test_error(error, "clEnqueueSVMMemcpy failed"); + + error = clEnqueueSVMMemcpy(queue, CL_TRUE, dstBuffer + elementNum * typeSizes[i] / 2, srcBuffer + elementNum * typeSizes[i] / 2, elementNum * typeSizes[i] / 2, 0, 0, 0); + test_error(error, "clEnqueueSVMMemcpy failed"); + + void *ptrs[] = {(void *)srcBuffer, (void *)dstBuffer}; + + clEventWrapper eventFree; + error = clEnqueueSVMFree(queue, 2, ptrs, 0, 0, 0, 0, &eventFree); + test_error(error, "clEnqueueSVMFree failed"); + + error = clWaitForEvents(1, &eventFree); + test_error(error, "clWaitForEvents failed"); + + //event info verification for new SVM commands + cl_command_type commandType; + error = clGetEventInfo(eventMemFill, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL); + test_error(error, "clGetEventInfo failed"); + if (commandType != CL_COMMAND_SVM_MEMFILL) + { + log_error("Invalid command type returned for clEnqueueSVMMemFill\n"); + return -1; + } + + error = clGetEventInfo(eventMemcpy, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL); + test_error(error, "clGetEventInfo failed"); + if (commandType != CL_COMMAND_SVM_MEMCPY) + { + log_error("Invalid command type returned for clEnqueueSVMMemcpy\n"); + return -1; + } + + error = clGetEventInfo(eventMap, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL); + test_error(error, "clGetEventInfo failed"); + if (commandType != CL_COMMAND_SVM_MAP) + { + log_error("Invalid command type returned for clEnqueueSVMMap\n"); + return -1; + } + + error = clGetEventInfo(eventUnmap, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL); + test_error(error, "clGetEventInfo failed"); + if (commandType != CL_COMMAND_SVM_UNMAP) + { + log_error("Invalid command type returned for clEnqueueSVMUnmap\n"); + return -1; + } + + error = clGetEventInfo(eventFree, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL); + test_error(error, "clGetEventInfo failed"); + if (commandType != CL_COMMAND_SVM_FREE) + { + log_error("Invalid command type returned for clEnqueueSVMFree\n"); + return -1; + } + } + + std::vector buffers(numSVMBuffers, 0); + for(size_t i = 0; i < numSVMBuffers; ++i) buffers[i] = clSVMAlloc(context, CL_MEM_READ_WRITE, elementNum, 0); + + //verify if callback is triggered correctly + CallbackData data; + data.status = 0; + + error = clEnqueueSVMFree(queue, buffers.size(), &buffers[0], callback_svm_free, &data, 0, 0, 0); + test_error(error, "clEnqueueSVMFree failed"); + + error = clFinish(queue); + test_error(error, "clFinish failed"); + + //wait for the callback + while(data.status == 0) { } + + //check if number of SVM pointers returned in the callback matches with expected + if (data.num_svm_pointers != buffers.size()) + { + log_error("Invalid number of SVM pointers returned in the callback, expected: %ld, got: %d\n", buffers.size(), data.num_svm_pointers); + return -1; + } + + //check if pointers returned in callback are correct + for (size_t i = 0; i < buffers.size(); ++i) + { + if (data.svm_pointers[i] != buffers[i]) + { + log_error("Invalid SVM pointer returned in the callback, idx: %ld\n", i); + return -1; + } + } + + return 0; +} \ No newline at end of file diff --git a/test_conformance/SVM/test_fine_grain_memory_consistency.cpp b/test_conformance/SVM/test_fine_grain_memory_consistency.cpp new file mode 100644 index 00000000..9d9ddbf2 --- /dev/null +++ b/test_conformance/SVM/test_fine_grain_memory_consistency.cpp @@ -0,0 +1,168 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" + +const char *hash_table_kernel[] = { + "typedef struct BinNode {\n" + " int value;\n" + " atomic_uintptr_t pNext;\n" + "} BinNode;\n" + + "__kernel void build_hash_table(__global uint* input, __global BinNode* pNodes, volatile __global atomic_uint* pNumNodes, uint numBins)\n" + "{\n" + " __global BinNode *pNew = &pNodes[ atomic_fetch_add_explicit(pNumNodes, 1, memory_order_relaxed, memory_scope_all_svm_devices) ];\n" + " uint i = get_global_id(0);\n" + " uint b = input[i] % numBins;\n" + " pNew->value = input[i];\n" + " uintptr_t next = atomic_load_explicit(&(pNodes[b].pNext), memory_order_seq_cst, memory_scope_all_svm_devices);\n" + " do\n" + " {\n" + " atomic_store_explicit(&(pNew->pNext), next, memory_order_seq_cst, memory_scope_all_svm_devices);\n" // always inserting at head of list + " } while(!atomic_compare_exchange_strong_explicit(&(pNodes[b].pNext), &next, (uintptr_t)pNew, memory_order_seq_cst, memory_order_relaxed, memory_scope_all_svm_devices));\n" + "}\n" +}; + +typedef struct BinNode{ + cl_uint value; + struct BinNode* pNext; +} BinNode; + +void build_hash_table_on_host(cl_context c, cl_uint* input, size_t inputSize, BinNode* pNodes, cl_int volatile *pNumNodes, cl_uint numBins) +{ + for(cl_uint i = 0; i < inputSize; i++) + { + BinNode *pNew = &pNodes[ AtomicFetchAddExplicit(pNumNodes, 1, memory_order_relaxed) ]; + cl_uint b = input[i] % numBins; + pNew->value = input[i]; + + BinNode *next = pNodes[b].pNext; + do { + pNew->pNext = next; // always inserting at head of list + } while(!AtomicCompareExchangeStrongExplicit(&(pNodes[b].pNext), &next, pNew, memory_order_relaxed, memory_order_seq_cst)); + } +} + + +int launch_kernels_and_verify(clContextWrapper &context, clCommandQueueWrapper* queues, clKernelWrapper &kernel, cl_uint num_devices, cl_uint numBins, size_t num_pixels) +{ + int err = CL_SUCCESS; + cl_uint *pInputImage = (cl_uint*) clSVMAlloc(context, CL_MEM_READ_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER, sizeof(cl_uint) * num_pixels, 0); + BinNode *pNodes = (BinNode*) clSVMAlloc(context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS, sizeof(BinNode) * (num_pixels * (num_devices + 1) + numBins), 0); + cl_int *pNumNodes = (cl_int*) clSVMAlloc(context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS, sizeof(cl_int), 0); + + *pNumNodes = numBins; // using the first numBins nodes to hold the list heads. + for(cl_uint i=0;ivalue % numBins) != i) + { + log_error("Something went wrong, item is in wrong hash bucket\n"); + break; + } + num_items++; + pNode = pNode->pNext; + } + } + + clSVMFree(context, pInputImage); + clSVMFree(context, pNodes); + clSVMFree(context, pNumNodes); + // each device and the host inserted all of the pixels, check that none are missing. + if(num_items != num_pixels * (num_devices + 1) ) + { + log_error("The hash table is not correct, num items %d, expected num items: %d\n", num_items, num_pixels * (num_devices + 1)); + return -1; // test did not pass + } + return 0; +} + +// This tests for memory consistency across devices and the host. +// Each device and the host simultaneously insert values into a single hash table. +// Each bin in the hash table is a linked list. Each bin is protected against simultaneous +// update using a lock free technique. The correctness of the list is verfied on the host. +// This test requires the new OpenCL 2.0 atomic operations that implement the new seq_cst memory ordering. +int test_fine_grain_memory_consistency(cl_device_id deviceID, cl_context c, cl_command_queue queue, int num_elements) +{ + clContextWrapper context; + clProgramWrapper program; + clKernelWrapper kernel; + clCommandQueueWrapper queues[MAXQ]; + + cl_uint num_devices = 0; + cl_int err = CL_SUCCESS; + + if (sizeof(void *) == 8 && (!is_extension_available(deviceID, "cl_khr_int64_base_atomics") || !is_extension_available(deviceID, "cl_khr_int64_extended_atomics"))) + { + log_info("WARNING: test skipped. 'cl_khr_int64_base_atomics' and 'cl_khr_int64_extended_atomics' extensions are not supported\n"); + return 0; + } + + err = create_cl_objects(deviceID, &hash_table_kernel[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_FINE_GRAIN_BUFFER | CL_DEVICE_SVM_ATOMICS); + if(err == 1) return 0; // no devices capable of requested SVM level, so don't execute but count test as passing. + if(err < 0) return -1; // fail test. + + kernel = clCreateKernel(program, "build_hash_table", &err); + test_error(err, "clCreateKernel failed"); + size_t num_pixels = num_elements; + + int result; + cl_uint numBins = 1; // all work groups in all devices and the host code will hammer on this one lock. + result = launch_kernels_and_verify(context, queues, kernel, num_devices, numBins, num_pixels); + if(result == -1) return result; + + numBins = 2; // 2 locks within in same cache line will get hit from different devices and host. + result = launch_kernels_and_verify(context, queues, kernel, num_devices, numBins, num_pixels); + if(result == -1) return result; + + numBins = 29; // locks span a few cache lines. + result = launch_kernels_and_verify(context, queues, kernel, num_devices, numBins, num_pixels); + if(result == -1) return result; + + return result; +} diff --git a/test_conformance/SVM/test_fine_grain_sync_buffers.cpp b/test_conformance/SVM/test_fine_grain_sync_buffers.cpp new file mode 100644 index 00000000..064a3147 --- /dev/null +++ b/test_conformance/SVM/test_fine_grain_sync_buffers.cpp @@ -0,0 +1,105 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" + +const char *find_targets_kernel[] = { + + "__kernel void find_targets(__global uint* image, uint target, volatile __global atomic_uint *numTargetsFound, volatile __global atomic_uint *targetLocations)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " uint index;\n" + " if(image[i] == target) {\n" + " index = atomic_fetch_add_explicit(numTargetsFound, 1, memory_order_relaxed, memory_scope_device); \n" + " atomic_exchange_explicit(&targetLocations[index], i, memory_order_relaxed, memory_scope_all_svm_devices); \n" + " }\n" + "}\n" +}; + + +void spawnAnalysisTask(int location) +{ + // printf("found target at location %d\n", location); +} + +#define MAX_TARGETS 1024 + +// Goals: demonstrate use of SVM's atomics to do fine grain synchronization between the device and host. +// Concept: a device kernel is used to search an input image for regions that match a target pattern. +// The device immediately notifies the host when it finds a target (via an atomic operation that works across host and devices). +// The host is then able to spawn a task that further analyzes the target while the device continues searching for more targets. +int test_fine_grain_sync_buffers(cl_device_id deviceID, cl_context c, cl_command_queue queue, int num_elements) +{ + clContextWrapper context = NULL; + clProgramWrapper program = NULL; + cl_uint num_devices = 0; + cl_int err = CL_SUCCESS; + clCommandQueueWrapper queues[MAXQ]; + + err = create_cl_objects(deviceID, &find_targets_kernel[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_FINE_GRAIN_BUFFER | CL_DEVICE_SVM_ATOMICS); + if(err == 1) return 0; // no devices capable of requested SVM level, so don't execute but count test as passing. + if(err < 0) return -1; // fail test. + + clKernelWrapper kernel = clCreateKernel(program, "find_targets", &err); + test_error(err, "clCreateKernel failed"); + + size_t num_pixels = num_elements; + //cl_uint num_pixels = 1024*1024*32; + + cl_uint *pInputImage = (cl_uint*) clSVMAlloc(context, CL_MEM_READ_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER, sizeof(cl_uint) * num_pixels, 0); + cl_uint *pNumTargetsFound = (cl_uint*) clSVMAlloc(context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS, sizeof(cl_uint), 0); + cl_int *pTargetLocations = (cl_int* ) clSVMAlloc(context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS, sizeof(cl_int) * MAX_TARGETS, 0); + + cl_uint targetDescriptor = 777; + *pNumTargetsFound = 0; + cl_uint i; + for(i=0; i < MAX_TARGETS; i++) pTargetLocations[i] = -1; + for(i=0; i < num_pixels; i++) pInputImage[i] = 0; + pInputImage[0] = targetDescriptor; + pInputImage[3] = targetDescriptor; + pInputImage[num_pixels - 1] = targetDescriptor; + + err |= clSetKernelArgSVMPointer(kernel, 0, pInputImage); + err |= clSetKernelArg(kernel, 1, sizeof(cl_uint), (void*) &targetDescriptor); + err |= clSetKernelArgSVMPointer(kernel, 2, pNumTargetsFound); + err |= clSetKernelArgSVMPointer(kernel, 3, pTargetLocations); + test_error(err, "clSetKernelArg failed"); + + cl_event done; + err = clEnqueueNDRangeKernel(queues[0], kernel, 1, NULL, &num_pixels, NULL, 0, NULL, &done); + test_error(err,"clEnqueueNDRangeKernel failed"); + clFlush(queues[0]); + + + i=0; + cl_int status; + // check for new targets, if found spawn a task to analyze target. + do { + err = clGetEventInfo(done,CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(cl_int), &status, NULL); + test_error(err,"clGetEventInfo failed"); + if( AtomicLoadExplicit(&pTargetLocations[i], memory_order_relaxed) != -1) // -1 indicates slot not used yet. + { + spawnAnalysisTask(pTargetLocations[i]); + i++; + } + } while (status != CL_COMPLETE || AtomicLoadExplicit(&pTargetLocations[i], memory_order_relaxed) != -1); + + clSVMFree(context, pInputImage); + clSVMFree(context, pNumTargetsFound); + clSVMFree(context, pTargetLocations); + + if(i != 3) return -1; + return 0; +} diff --git a/test_conformance/SVM/test_migrate.cpp b/test_conformance/SVM/test_migrate.cpp new file mode 100644 index 00000000..704f8060 --- /dev/null +++ b/test_conformance/SVM/test_migrate.cpp @@ -0,0 +1,330 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" +#include "../../test_common/harness/mt19937.h" + +#define GLOBAL_SIZE 65536 + +static const char *sources[] = { +"__kernel void migrate_kernel(__global uint * restrict a, __global uint * restrict b, __global uint * restrict c)\n" +"{\n" +" size_t i = get_global_id(0);\n" +" a[i] ^= 0x13579bdf;\n" +" b[i] ^= 0x2468ace0;\n" +" c[i] ^= 0x731fec8f;\n" +"}\n" +}; + +static void +fill_buffer(cl_uint* p, size_t n, MTdata seed) +{ + for (size_t i=0; i 1) { + log_info(" Running on two devices.\n"); + queue1 = queues[1]; + } else { + // Ensure we have two distinct queues + cl_device_id did; + error = clGetCommandQueueInfo(queue0, CL_QUEUE_DEVICE, sizeof(did), (void *)&did, NULL); + test_error(error, "clGetCommandQueueInfo failed"); + + cl_command_queue_properties cqp; + error = clGetCommandQueueInfo(queue0, CL_QUEUE_PROPERTIES, sizeof(cqp), &cqp, NULL); + test_error(error, "clGetCommandQueueInfo failed"); + + cl_queue_properties qp[3] = { CL_QUEUE_PROPERTIES, cqp, 0 }; + queue1 = clCreateCommandQueueWithProperties(context, did, qp, &error); + test_error(error, "clCteateCommandQueueWithProperties failed"); + } + + clKernelWrapper kernel = clCreateKernel(program, "migrate_kernel", &error); + test_error(error, "clCreateKernel failed"); + + char* asvm = (char*)clSVMAlloc(context, CL_MEM_READ_WRITE, global_size*sizeof(cl_uint), 16); + if (asvm == NULL) { + log_error("ERROR: clSVMAlloc returned NULL at %s:%d\n", __FILE__, __LINE__); + return -1; + } + + char* bsvm = (char *)clSVMAlloc(context, CL_MEM_READ_WRITE, global_size*sizeof(cl_uint), 16); + if (bsvm == NULL) { + log_error("ERROR: clSVMAlloc returned NULL at %s:%d\n", __FILE__, __LINE__); + clSVMFree(context, asvm); + return -1; + } + + char* csvm = (char *)clSVMAlloc(context, CL_MEM_READ_WRITE, global_size*sizeof(cl_uint), 16); + if (csvm == NULL) { + log_error("ERROR: clSVMAlloc returned NULL at %s:%d\n", __FILE__, __LINE__); + clSVMFree(context, bsvm); + clSVMFree(context, asvm); + return -1; + } + + error = clSetKernelArgSVMPointer(kernel, 0, (void*)asvm); + test_error(error, "clSetKernelArgSVMPointer failed"); + + error = clSetKernelArgSVMPointer(kernel, 1, (void*)bsvm); + test_error(error, "clSetKernelArgSVMPointer failed"); + + error = clSetKernelArgSVMPointer(kernel, 2, (void*)csvm); + test_error(error, "clSetKernelArgSVMPointer failed"); + + // Initialize host copy of data (and result) + fill_buffer(amem, global_size, seed); + fill_buffer(bmem, global_size, seed); + fill_buffer(cmem, global_size, seed); + + // Now we're ready to start + { + // First, fill in the data on device0 + cl_uint patt[] = { 0, 0, 0, 0}; + error = clEnqueueSVMMemFill(queue0, (void *)asvm, patt, sizeof(patt), global_size*sizeof(cl_uint), 0, NULL, &evs[0]); + test_error(error, "clEnqueueSVMMemFill failed"); + + error = clEnqueueSVMMemFill(queue0, (void *)bsvm, patt, sizeof(patt), global_size*sizeof(cl_uint), 0, NULL, &evs[1]); + test_error(error, "clEnqueueSVMMemFill failed"); + + error = clEnqueueSVMMemFill(queue0, (void *)csvm, patt, sizeof(patt), global_size*sizeof(cl_uint), 0, NULL, &evs[2]); + test_error(error, "clEnqueueSVMMemFill failed"); + } + + { + // Now migrate fully to device 1 and discard the data + char* ptrs[] = { asvm, bsvm, csvm }; + error = clEnqueueSVMMigrateMem(queue1, 3, (const void**)ptrs, NULL, CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED, 1, &evs[2], &evs[3]); + test_error(error, "clEnqueueSVMMigrateMem failed"); + } + + { + // Test host flag + char *ptrs[] = { asvm+1, bsvm+3, csvm+5 }; + const size_t szs[] = { 1, 1, 0 }; + error = clEnqueueSVMMigrateMem(queue0, 3, (const void**)ptrs, szs, CL_MIGRATE_MEM_OBJECT_HOST, 1, &evs[3], &evs[4]); + test_error(error, "clEnqueueSVMMigrateMem failed"); + } + + { + // Next fill with known data + error = clEnqueueSVMMap(queue1, CL_FALSE, CL_MAP_WRITE, (void*)asvm, global_size*sizeof(cl_uint), 1, &evs[4], &evs[5]); + test_error(error, "clEnqueueSVMMap failed"); + + error = clEnqueueSVMMap(queue1, CL_FALSE, CL_MAP_WRITE, (void*)bsvm, global_size*sizeof(cl_uint), 0, NULL, &evs[6]); + test_error(error, "clEnqueueSVMMap failed"); + + error = clEnqueueSVMMap(queue1, CL_FALSE, CL_MAP_WRITE, (void*)csvm, global_size*sizeof(cl_uint), 0, NULL, &evs[7]); + test_error(error, "clEnqueueSVMMap failed"); + } + + error = clFlush(queue0); + test_error(error, "clFlush failed"); + + error = clFlush(queue1); + test_error(error, "clFlush failed"); + + error = wait_and_release("first batch", evs, 8); + if (error) + return -1; + + memcpy((void *)asvm, (void *)amem, global_size*sizeof(cl_uint)); + memcpy((void *)bsvm, (void *)bmem, global_size*sizeof(cl_uint)); + memcpy((void *)csvm, (void *)cmem, global_size*sizeof(cl_uint)); + + { + error = clEnqueueSVMUnmap(queue1, (void *)asvm, 0, NULL, &evs[0]); + test_error(error, "clEnqueueSVMUnmap failed"); + + error = clEnqueueSVMUnmap(queue1, (void *)bsvm, 0, NULL, &evs[1]); + test_error(error, "clEnqueueSVMUnmap failed"); + + error = clEnqueueSVMUnmap(queue1, (void *)csvm, 0, NULL, &evs[2]); + test_error(error, "clEnqueueSVMUnmap failed"); + } + + + { + // Now try some overlapping regions, and operate on the result + char *ptrs[] = { asvm+100, bsvm+17, csvm+1000, asvm+101, bsvm+19, csvm+1017 }; + const size_t szs[] = { 13, 23, 43, 3, 7, 11 }; + + error = clEnqueueSVMMigrateMem(queue0, 3, (const void**)ptrs, szs, 0, 1, &evs[2], &evs[3]); + test_error(error, "clEnqueueSVMMigrateMem failed"); + + error = clEnqueueNDRangeKernel(queue0, kernel, 1, NULL, &global_size, NULL, 0, NULL, &evs[4]); + test_error(error, "clEnqueueNDRangeKernel failed"); + } + + { + // Now another pair + char *ptrs[] = { asvm+8, bsvm+17, csvm+31, csvm+83 }; + const size_t szs[] = { 0, 1, 3, 7 }; + + error = clEnqueueSVMMigrateMem(queue1, 4, (const void**)ptrs, szs, 0, 1, &evs[4], &evs[5]); + test_error(error, "clEnqueueSVMMigrateMem failed"); + + error = clEnqueueNDRangeKernel(queue1, kernel, 1, NULL, &global_size, NULL, 0, NULL, &evs[6]); + test_error(error, "clEnqueueNDRangeKernel failed"); + } + + { + // Another pair + char *ptrs[] = { asvm+64, asvm+128, bsvm+64, bsvm+128, csvm, csvm+64 }; + const size_t szs[] = { 64, 64, 64, 64, 64, 64 }; + + error = clEnqueueSVMMigrateMem(queue0, 6, (const void**)ptrs, szs, 0, 1, &evs[6], &evs[7]); + test_error(error, "clEnqueueSVMMigrateMem failed"); + + error = clEnqueueNDRangeKernel(queue0, kernel, 1, NULL, &global_size, NULL, 0, NULL, &evs[8]); + test_error(error, "clEnqueueNDRangeKernel failed"); + } + + { + // Final pair + char *ptrs[] = { asvm, asvm, bsvm, csvm, csvm }; + const size_t szs[] = { 0, 1, 0, 1, 0 }; + + error = clEnqueueSVMMigrateMem(queue1, 5, (const void**)ptrs, szs, 0, 1, &evs[8], &evs[9]); + test_error(error, "clEnqueueSVMMigrateMem failed"); + + error = clEnqueueNDRangeKernel(queue1, kernel, 1, NULL, &global_size, NULL, 0, NULL, &evs[10]); + test_error(error, "clEnqueueNDRangeKernel failed"); + } + + { + error = clEnqueueSVMMap(queue1, CL_FALSE, CL_MAP_READ, (void*)asvm, global_size*sizeof(cl_uint), 0, NULL, &evs[11]); + test_error(error, "clEnqueueSVMMap failed"); + + error = clEnqueueSVMMap(queue1, CL_FALSE, CL_MAP_READ, (void*)bsvm, global_size*sizeof(cl_uint), 0, NULL, &evs[12]); + test_error(error, "clEnqueueSVMMap failed"); + + error = clEnqueueSVMMap(queue1, CL_FALSE, CL_MAP_READ, (void*)csvm, global_size*sizeof(cl_uint), 0, NULL, &evs[13]); + test_error(error, "clEnqueueSVMMap failed"); + } + + error = clFlush(queue0); + test_error(error, "clFlush failed"); + + error = clFlush(queue1); + test_error(error, "clFlush failed"); + + error = wait_and_release("batch 2", evs, 14); + if (error) + return -1; + + // Check kernel results + bool ok = check("memory a", (cl_uint *)asvm, amem, global_size); + ok &= check("memory b", (cl_uint *)bsvm, bmem, global_size); + ok &= check("memory c", (cl_uint *)csvm, cmem, global_size); + + { + void *ptrs[] = { asvm, bsvm, csvm }; + + error = clEnqueueSVMUnmap(queue1, (void *)asvm, 0, NULL, &evs[0]); + test_error(error, "clEnqueueSVMUnmap failed"); + + error = clEnqueueSVMUnmap(queue1, (void *)bsvm, 0, NULL, &evs[1]); + test_error(error, "clEnqueueSVMUnmap failed"); + + error = clEnqueueSVMUnmap(queue1, (void *)csvm, 0, NULL, &evs[2]); + test_error(error, "clEnqueueSVMUnmap failed"); + + error = clEnqueueSVMFree(queue1, 3, ptrs, NULL, NULL, 0, NULL, &evs[3]); + } + + error = clFlush(queue1); + test_error(error, "clFlush failed"); + + error = wait_and_release("batch 3", evs, 4); + if (error) + return -1; + + clSVMFree(context, asvm); + clSVMFree(context, bsvm); + clSVMFree(context, csvm); + + // The wrappers will clean up the rest + return ok ? 0 : -1; +} + diff --git a/test_conformance/SVM/test_pointer_passing.cpp b/test_conformance/SVM/test_pointer_passing.cpp new file mode 100644 index 00000000..6ef074d3 --- /dev/null +++ b/test_conformance/SVM/test_pointer_passing.cpp @@ -0,0 +1,115 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" + +const char *SVMPointerPassing_test_kernel[] = { + "__kernel void verify_char(__global uchar* pChar, volatile __global uint* num_correct, uchar expected)\n" + "{\n" + " if(0 == get_global_id(0))\n" + " {\n" + " *num_correct = 0;\n" + " if(*pChar == expected)\n" + " {\n" + " *num_correct=1;\n" + " }\n" + " }\n" + "}\n" +}; + + +// Test that arbitrarily aligned char pointers into shared buffers can be passed directly to a kernel. +// This iterates through a buffer passing a pointer to each location to the kernel. +// The buffer is initialized to known values at each location. +// The kernel checks that it finds the expected value at each location. +// TODO: possibly make this work across all base types (including typeN?), also check ptr arithmetic ++,--. +int test_svm_pointer_passing(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements) +{ + clContextWrapper context = NULL; + clProgramWrapper program = NULL; + cl_uint num_devices = 0; + cl_int error = CL_SUCCESS; + clCommandQueueWrapper queues[MAXQ]; + + error = create_cl_objects(deviceID, &SVMPointerPassing_test_kernel[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER); + if(error) return -1; + + clKernelWrapper kernel_verify_char = clCreateKernel(program, "verify_char", &error); + test_error(error,"clCreateKernel failed"); + + size_t bufSize = 256; + char *pbuf = (char*) clSVMAlloc(context, CL_MEM_READ_WRITE, sizeof(cl_uchar)*bufSize, 0); + + cl_int *pNumCorrect = NULL; + pNumCorrect = (cl_int*) clSVMAlloc(context, CL_MEM_READ_WRITE, sizeof(cl_int), 0); + + { + clMemWrapper buf = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(cl_uchar)*bufSize, pbuf, &error); + test_error(error, "clCreateBuffer failed."); + + clMemWrapper num_correct = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(cl_int), pNumCorrect, &error); + test_error(error, "clCreateBuffer failed."); + + error = clSetKernelArg(kernel_verify_char, 1, sizeof(void*), (void *) &num_correct); + test_error(error, "clSetKernelArg failed"); + + // put values into buf so that we can expect to see these values in the kernel when we pass a pointer to them. + cl_command_queue cmdq = queues[0]; + cl_uchar* pBuf = (cl_uchar*) clEnqueueMapBuffer(cmdq, buf, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(cl_uchar)*bufSize, 0, NULL,NULL, &error); + test_error2(error, pBuf, "clEnqueueMapBuffer failed"); + for(int i = 0; i<(int)bufSize; i++) + { + pBuf[i]= (cl_uchar)i; + } + error = clEnqueueUnmapMemObject(cmdq, buf, pBuf, 0,NULL,NULL); + test_error(error, "clEnqueueUnmapMemObject failed."); + + for (cl_uint ii = 0; iipA[i]++;\n" + " pBufs->pB[i]++;\n" + " pBufs->pC[i]++;\n" + "}\n" +}; + +// Test that clSetKernelExecInfo works correctly with CL_KERNEL_EXEC_INFO_SVM_PTRS flag. +// +int test_set_kernel_exec_info_svm_ptrs(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements) +{ + clContextWrapper c = NULL; + clProgramWrapper program = NULL; + cl_uint num_devices = 0; + cl_int error = CL_SUCCESS; + clCommandQueueWrapper q; + + //error = create_cl_objects(deviceID, &set_kernel_exec_info_svm_ptrs_kernel[0], &context, &program, &q, &num_devices, CL_DEVICE_SVM_FINE_GRAIN); + error = create_cl_objects(deviceID, &set_kernel_exec_info_svm_ptrs_kernel[0], &c, &program, &q, &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER); + if(error == 1) return 0; // no devices capable of requested SVM level, so don't execute but count test as passing. + if(error < 0) return -1; // fail test. + + + clKernelWrapper k = clCreateKernel(program, "set_kernel_exec_info_test", &error); + test_error(error, "clCreateKernel failed"); + + size_t size = num_elements*sizeof(int); + //int* pA = (int*) clSVMalloc(c, CL_MEM_READ_WRITE | CL_DEVICE_SVM_FINE_GRAIN_SYSTEM, sizeof(int)*num_elements, 0); + //int* pB = (int*) clSVMalloc(c, CL_MEM_READ_WRITE | CL_DEVICE_SVM_FINE_GRAIN_SYSTEM, sizeof(int)*num_elements, 0); + //int* pC = (int*) clSVMalloc(c, CL_MEM_READ_WRITE | CL_DEVICE_SVM_FINE_GRAIN_SYSTEM, sizeof(int)*num_elements, 0); + int* pA = (int*) clSVMAlloc(c, CL_MEM_READ_WRITE, size, 0); + int* pB = (int*) clSVMAlloc(c, CL_MEM_READ_WRITE, size, 0); + int* pC = (int*) clSVMAlloc(c, CL_MEM_READ_WRITE, size, 0); + BufPtrs* pBuf = (BufPtrs*) clSVMAlloc(c, CL_MEM_READ_WRITE, sizeof(BufPtrs), 0); + + bool failed = false; + { + clMemWrapper ba,bb,bc,bBuf; + ba = clCreateBuffer(c, CL_MEM_USE_HOST_PTR, size, pA, &error); + test_error(error, "clCreateBuffer failed"); + bb = clCreateBuffer(c, CL_MEM_USE_HOST_PTR, size, pB, &error); + test_error(error, "clCreateBuffer failed"); + bc = clCreateBuffer(c, CL_MEM_USE_HOST_PTR, size, pC, &error); + test_error(error, "clCreateBuffer failed"); + bBuf = clCreateBuffer(c, CL_MEM_USE_HOST_PTR, sizeof(BufPtrs), pBuf, &error); + test_error(error, "clCreateBuffer failed"); + + clEnqueueMapBuffer(q, ba, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, size, 0, NULL, NULL, &error); + test_error(error, "clEnqueueMapBuffer failed"); + clEnqueueMapBuffer(q, bb, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, size, 0, NULL, NULL, &error); + test_error(error, "clEnqueueMapBuffer failed"); + clEnqueueMapBuffer(q, bc, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, size, 0, NULL, NULL, &error); + test_error(error, "clEnqueueMapBuffer failed"); + clEnqueueMapBuffer(q, bBuf, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(BufPtrs), 0, NULL, NULL, &error); + test_error(error, "clEnqueueMapBuffer failed"); + + for(int i = 0; i < num_elements; i++) pA[i] = pB[i] = pC[i] = 0; + + pBuf->pA = pA; + pBuf->pB = pB; + pBuf->pC = pC; + + error = clEnqueueUnmapMemObject(q, ba, pA, 0,NULL,NULL); + test_error(error, " clEnqueueUnmapMemObject failed."); + error = clEnqueueUnmapMemObject(q, bb, pB, 0,NULL,NULL); + test_error(error, " clEnqueueUnmapMemObject failed."); + error = clEnqueueUnmapMemObject(q, bc, pC, 0,NULL,NULL); + test_error(error, " clEnqueueUnmapMemObject failed."); + error = clEnqueueUnmapMemObject(q, bBuf, pBuf, 0,NULL,NULL); + test_error(error, " clEnqueueUnmapMemObject failed."); + + + error = clSetKernelArgSVMPointer(k, 0, pBuf); + test_error(error, "clSetKernelArg failed"); + + error = clSetKernelExecInfo(k, CL_KERNEL_EXEC_INFO_SVM_PTRS, sizeof(BufPtrs), pBuf); + test_error(error, "clSetKernelExecInfo failed"); + + size_t range = num_elements; + error = clEnqueueNDRangeKernel(q, k, 1, NULL, &range, NULL, 0, NULL, NULL); + test_error(error,"clEnqueueNDRangeKernel failed"); + + error = clFinish(q); + test_error(error, "clFinish failed."); + + clEnqueueMapBuffer(q, ba, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, size, 0, NULL, NULL, &error); + test_error(error, "clEnqueueMapBuffer failed"); + clEnqueueMapBuffer(q, bb, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, size, 0, NULL, NULL, &error); + test_error(error, "clEnqueueMapBuffer failed"); + clEnqueueMapBuffer(q, bc, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, size, 0, NULL, NULL, &error); + test_error(error, "clEnqueueMapBuffer failed"); + + for(int i = 0; i < num_elements; i++) + { + if(pA[i] + pB[i] + pC[i] != 3) + failed = true; + } + + error = clEnqueueUnmapMemObject(q, ba, pA, 0,NULL,NULL); + test_error(error, " clEnqueueUnmapMemObject failed."); + error = clEnqueueUnmapMemObject(q, bb, pB, 0,NULL,NULL); + test_error(error, " clEnqueueUnmapMemObject failed."); + error = clEnqueueUnmapMemObject(q, bc, pC, 0,NULL,NULL); + test_error(error, " clEnqueueUnmapMemObject failed."); + } + + error = clFinish(q); + test_error(error, " clFinish failed."); + + clSVMFree(c, pA); + clSVMFree(c, pB); + clSVMFree(c, pC); + clSVMFree(c, pBuf); + + if(failed) return -1; + + return 0; +} diff --git a/test_conformance/SVM/test_shared_address_space_coarse_grain.cpp b/test_conformance/SVM/test_shared_address_space_coarse_grain.cpp new file mode 100644 index 00000000..a2a9387a --- /dev/null +++ b/test_conformance/SVM/test_shared_address_space_coarse_grain.cpp @@ -0,0 +1,282 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" + +// Creates linked list using host code +cl_int create_linked_lists_on_host(cl_command_queue cmdq, cl_mem nodes, Node *pNodes2, cl_int ListLength, size_t numLists, cl_bool useNewAPI ) +{ + cl_int error = CL_SUCCESS; + + log_info("SVM: creating linked list on host "); + + Node *pNodes; + if (useNewAPI == CL_FALSE) + { + pNodes = (Node*) clEnqueueMapBuffer(cmdq, nodes, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(Node)*ListLength*numLists, 0, NULL,NULL, &error); + test_error2(error, pNodes, "clEnqMapBuffer failed"); + } + else + { + pNodes = pNodes2; + error = clEnqueueSVMMap(cmdq, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, pNodes2, sizeof(Node)*ListLength*numLists, 0, NULL,NULL); + test_error2(error, pNodes, "clEnqueueSVMMap failed"); + } + + create_linked_lists(pNodes, numLists, ListLength); + + if (useNewAPI == CL_FALSE) + { + error = clEnqueueUnmapMemObject(cmdq, nodes, pNodes, 0,NULL,NULL); + test_error(error, "clEnqueueUnmapMemObject failed."); + } + else + { + error = clEnqueueSVMUnmap(cmdq, pNodes2, 0, NULL, NULL); + test_error(error, "clEnqueueSVMUnmap failed."); + } + + error = clFinish(cmdq); + test_error(error, "clFinish failed."); + return error; +} + +// Purpose: uses host code to verify correctness of the linked list +cl_int verify_linked_lists_on_host(int ci, cl_command_queue cmdq, cl_mem nodes, Node *pNodes2, cl_int ListLength, size_t numLists, cl_bool useNewAPI ) +{ + cl_int error = CL_SUCCESS; + cl_int correct_count; + + Node *pNodes; + if (useNewAPI == CL_FALSE) + { + pNodes = (Node*) clEnqueueMapBuffer(cmdq, nodes, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(Node)*ListLength * numLists, 0, NULL,NULL, &error); + test_error2(error, pNodes, "clEnqueueMapBuffer failed"); + } + else + { + pNodes = pNodes2; + error = clEnqueueSVMMap(cmdq, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, pNodes2, sizeof(Node)*ListLength * numLists, 0, NULL,NULL); + test_error2(error, pNodes, "clEnqueueSVMMap failed"); + } + + correct_count = 0; + + error = verify_linked_lists(pNodes, numLists, ListLength); + if(error) return -1; + + if (useNewAPI == CL_FALSE) + { + error = clEnqueueUnmapMemObject(cmdq, nodes, pNodes, 0,NULL,NULL); + test_error(error, "clEnqueueUnmapMemObject failed."); + } + else + { + error = clEnqueueSVMUnmap(cmdq, pNodes2, 0,NULL,NULL); + test_error(error, "clEnqueueSVMUnmap failed."); + } + + error = clFinish(cmdq); + test_error(error, "clFinish failed."); + return error; +} + +cl_int create_linked_lists_on_device(int ci, cl_command_queue cmdq, cl_mem allocator, cl_kernel kernel_create_lists, size_t numLists ) +{ + cl_int error = CL_SUCCESS; + log_info("SVM: creating linked list on device: %d ", ci); + + size_t *pAllocator = (size_t*) clEnqueueMapBuffer(cmdq, allocator, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(cl_int), 0, NULL,NULL, &error); + test_error2(error, pAllocator, "clEnqueueMapBuffer failed"); + // reset allocator index + *pAllocator = numLists; // the first numLists elements of the nodes array are already allocated (they hold the head of each list). + error = clEnqueueUnmapMemObject(cmdq, allocator, pAllocator, 0,NULL,NULL); + test_error(error, " clEnqueueUnmapMemObject failed."); + + error = clEnqueueNDRangeKernel(cmdq, kernel_create_lists, 1, NULL, &numLists, NULL, 0, NULL, NULL); + test_error(error, "clEnqueueNDRange failed."); + error = clFinish(cmdq); + test_error(error, "clFinish failed."); + + return error; +} + +cl_int verify_linked_lists_on_device(int vi, cl_command_queue cmdq,cl_mem num_correct, cl_kernel kernel_verify_lists, cl_int ListLength, size_t numLists ) +{ + cl_int error = CL_SUCCESS; + + log_info(" and verifying on device: %d ", vi); + + cl_int *pNumCorrect = (cl_int*) clEnqueueMapBuffer(cmdq, num_correct, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(cl_int), 0, NULL,NULL, &error); + test_error2(error, pNumCorrect, "clEnqueueMapBuffer failed"); + + *pNumCorrect = 0; // reset numCorrect to zero + + error = clEnqueueUnmapMemObject(cmdq, num_correct, pNumCorrect, 0,NULL,NULL); + test_error(error, "clEnqueueUnmapMemObject failed."); + + error = clEnqueueNDRangeKernel(cmdq, kernel_verify_lists, 1, NULL, &numLists, NULL, 0, NULL, NULL); + test_error(error,"clEnqueueNDRangeKernel failed"); + + pNumCorrect = (cl_int*) clEnqueueMapBuffer(cmdq, num_correct, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(cl_int), 0, NULL,NULL, &error); + test_error2(error, pNumCorrect, "clEnqueueMapBuffer failed"); + cl_int correct_count = *pNumCorrect; + error = clEnqueueUnmapMemObject(cmdq, num_correct, pNumCorrect, 0,NULL,NULL); + test_error(error, "clEnqueueUnmapMemObject failed"); + clFinish(cmdq); + test_error(error,"clFinish failed"); + + if(correct_count != ListLength * (cl_uint)numLists) + { + error = -1; + log_info("Failed\n"); + } + else + log_info("Passed\n"); + + return error; +} + +// This tests that all devices and the host share a common address space; using only the coarse-grain features. +// This is done by creating a linked list on a device and then verifying the correctness of the list +// on another device or the host. This basic test is performed for all combinations of devices and the host that exist within +// the platform. The test passes only if every combination passes. +int shared_address_space_coarse_grain(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements, cl_bool useNewAPI) +{ + clContextWrapper context = NULL; + clProgramWrapper program = NULL; + cl_uint num_devices = 0; + cl_int error = CL_SUCCESS; + clCommandQueueWrapper queues[MAXQ]; + + error = create_cl_objects(deviceID, &linked_list_create_and_verify_kernels[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER); + if(error) return -1; + + size_t numLists = num_elements; + cl_int ListLength = 32; + + clKernelWrapper kernel_create_lists = clCreateKernel(program, "create_linked_lists", &error); + test_error(error, "clCreateKernel failed"); + + clKernelWrapper kernel_verify_lists = clCreateKernel(program, "verify_linked_lists", &error); + test_error(error, "clCreateKernel failed"); + + // this buffer holds the linked list nodes. + Node* pNodes = (Node*) clSVMAlloc(context, CL_MEM_READ_WRITE, sizeof(Node)*ListLength*numLists, 0); + + { + cl_bool usesSVMpointer = CL_FALSE; + clMemWrapper nodes; + if (useNewAPI == CL_FALSE) + { + nodes = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(Node)*ListLength*numLists, pNodes, &error); + test_error(error, "clCreateBuffer failed."); + + // verify if buffer uses SVM pointer + size_t paramSize = 0; + error = clGetMemObjectInfo(nodes, CL_MEM_USES_SVM_POINTER, 0, 0, ¶mSize); + test_error(error, "clGetMemObjectInfo failed."); + + if (paramSize != sizeof(cl_bool)) + { + log_error("clGetMemObjectInfo(CL_MEM_USES_SVM_POINTER) returned wrong size."); + return -1; + } + + error = clGetMemObjectInfo(nodes, CL_MEM_USES_SVM_POINTER, sizeof(cl_bool), &usesSVMpointer, 0); + test_error(error, "clGetMemObjectInfo failed."); + + if (usesSVMpointer != CL_TRUE) + { + log_error("clGetMemObjectInfo(CL_MEM_USES_SVM_POINTER) returned CL_FALSE for buffer created from SVM pointer."); + return -1; + } + } + + // this buffer holds an index into the nodes buffer, it is used for node allocation + clMemWrapper allocator = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, &error); + test_error(error, "clCreateBuffer failed."); + + error = clGetMemObjectInfo(allocator, CL_MEM_USES_SVM_POINTER, sizeof(cl_bool), &usesSVMpointer, 0); + test_error(error, "clGetMemObjectInfo failed."); + + if (usesSVMpointer != CL_FALSE) + { + log_error("clGetMemObjectInfo(CL_MEM_USES_SVM_POINTER) returned CL_TRUE for non-SVM buffer."); + return -1; + } + + // this buffer holds the count of correct nodes, which is computed by the verify kernel. + clMemWrapper num_correct = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, &error); + test_error(error, "clCreateBuffer failed."); + + if (useNewAPI == CL_TRUE) + error |= clSetKernelArgSVMPointer(kernel_create_lists, 0, pNodes); + else + error |= clSetKernelArg(kernel_create_lists, 0, sizeof(void*), (void *) &nodes); + + error |= clSetKernelArg(kernel_create_lists, 1, sizeof(void*), (void *) &allocator); + error |= clSetKernelArg(kernel_create_lists, 2, sizeof(cl_int), (void *) &ListLength); + + error |= clSetKernelArgSVMPointer(kernel_verify_lists, 0, pNodes); + error |= clSetKernelArg(kernel_verify_lists, 1, sizeof(void*), (void *) &num_correct); + error |= clSetKernelArg(kernel_verify_lists, 2, sizeof(cl_int), (void *) &ListLength); + test_error(error, "clSetKernelArg failed"); + + // Create linked list on one device and verify on another device (or the host). + // Do this for all possible combinations of devices and host within the platform. + for (int ci=0; ci<(int)num_devices+1; ci++) // ci is CreationIndex, index of device/q to create linked list on + { + for (int vi=0; vi<(int)num_devices+1; vi++) // vi is VerificationIndex, index of device/q to verify linked list on + { + if(ci == num_devices) // last device index represents the host, note the num_device+1 above. + { + error = create_linked_lists_on_host(queues[0], nodes, pNodes, ListLength, numLists, useNewAPI); + if(error) return -1; + } + else + { + error = create_linked_lists_on_device(ci, queues[ci], allocator, kernel_create_lists, numLists); + if(error) return -1; + } + + if(vi == num_devices) + { + error = verify_linked_lists_on_host(vi, queues[0], nodes, pNodes, ListLength, numLists, useNewAPI); + if(error) return -1; + } + else + { + error = verify_linked_lists_on_device(vi, queues[vi], num_correct, kernel_verify_lists, ListLength, numLists); + if(error) return -1; + } + } + } + } + + clSVMFree(context, pNodes); + + return 0; +} + +int test_shared_address_space_coarse_grain_old_api(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements) +{ + return shared_address_space_coarse_grain(deviceID, context2, queue, num_elements, CL_FALSE); +} + +int test_shared_address_space_coarse_grain_new_api(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements) +{ + return shared_address_space_coarse_grain(deviceID, context2, queue, num_elements, CL_TRUE); +} diff --git a/test_conformance/SVM/test_shared_address_space_fine_grain.cpp b/test_conformance/SVM/test_shared_address_space_fine_grain.cpp new file mode 100644 index 00000000..ece3320d --- /dev/null +++ b/test_conformance/SVM/test_shared_address_space_fine_grain.cpp @@ -0,0 +1,101 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" + + +// This tests that all devices and the host share a common address space using fine-grain mode with no buffers. +// This is done by creating a linked list on a device and then verifying the correctness of the list +// on another device or the host. This basic test is performed for all combinations of devices and the host that exist within +// the platform. The test passes only if every combination passes. +int test_shared_address_space_fine_grain(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements) +{ + clContextWrapper context = NULL; + clProgramWrapper program = NULL; + cl_uint num_devices = 0; + cl_int error = CL_SUCCESS; + clCommandQueueWrapper queues[MAXQ]; + + error = create_cl_objects(deviceID, &linked_list_create_and_verify_kernels[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_FINE_GRAIN_SYSTEM); + if(error == 1) return 0; // no devices capable of requested SVM level, so don't execute but count test as passing. + if(error < 0) return -1; // fail test. + + size_t numLists = num_elements; + cl_int ListLength = 32; + + clKernelWrapper kernel_create_lists = clCreateKernel(program, "create_linked_lists", &error); + test_error(error, "clCreateKernel failed"); + + clKernelWrapper kernel_verify_lists = clCreateKernel(program, "verify_linked_lists", &error); + test_error(error, "clCreateKernel failed"); + + // this allocation holds the linked list nodes. + // FIXME: remove the alignment once prototype can handle it + Node* pNodes = (Node*) align_malloc(numLists*ListLength*sizeof(Node),128); + test_error2(error, pNodes, "malloc failed"); + + // this allocation holds an index into the nodes buffer, it is used for node allocation + size_t* pAllocator = (size_t*) align_malloc(sizeof(cl_int), 128); + test_error2(error, pAllocator, "malloc failed"); + + // this allocation holds the count of correct nodes, which is computed by the verify kernel. + cl_int* pNum_correct = (cl_int*) align_malloc(sizeof(cl_int), 128); + test_error2(error, pNum_correct, "malloc failed"); + + + error |= clSetKernelArgSVMPointer(kernel_create_lists, 0, pNodes); + error |= clSetKernelArgSVMPointer(kernel_create_lists, 1, pAllocator); + error |= clSetKernelArg(kernel_create_lists, 2, sizeof(cl_int),(void *) &ListLength); + + error |= clSetKernelArgSVMPointer(kernel_verify_lists, 0, pNodes); + error |= clSetKernelArgSVMPointer(kernel_verify_lists, 1, pNum_correct); + error |= clSetKernelArg(kernel_verify_lists, 2, sizeof(cl_int), (void *) &ListLength); + test_error(error, "clSetKernelArg failed"); + + // Create linked list on one device and verify on another device (or the host). + // Do this for all possible combinations of devices and host within the platform. + for (int ci=0; ci<(int)num_devices+1; ci++) // ci is CreationIndex, index of device/q to create linked list on + { + for (int vi=0; vi<(int)num_devices+1; vi++) // vi is VerificationIndex, index of device/q to verify linked list on + { + if(ci == num_devices) // last device index represents the host, note the num_device+1 above. + { + log_info("creating linked list on host "); + create_linked_lists(pNodes, numLists, ListLength); + } + else + { + error = create_linked_lists_on_device_no_map(ci, queues[ci], pAllocator, kernel_create_lists, numLists); + if(error) return -1; + } + + if(vi == num_devices) + { + error = verify_linked_lists(pNodes, numLists, ListLength); + if(error) return -1; + } + else + { + error = verify_linked_lists_on_device_no_map(vi, queues[vi], pNum_correct, kernel_verify_lists, ListLength, numLists); + if(error) return -1; + } + } + } + + align_free(pNodes); + align_free(pAllocator); + align_free(pNum_correct); + return 0; +} diff --git a/test_conformance/SVM/test_shared_address_space_fine_grain_buffers.cpp b/test_conformance/SVM/test_shared_address_space_fine_grain_buffers.cpp new file mode 100644 index 00000000..e1210f92 --- /dev/null +++ b/test_conformance/SVM/test_shared_address_space_fine_grain_buffers.cpp @@ -0,0 +1,138 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" + + + + +cl_int create_linked_lists_on_device_no_map(int ci, cl_command_queue cmdq, size_t* pAllocator, cl_kernel kernel_create_lists, size_t numLists ) +{ + cl_int error = CL_SUCCESS; + log_info("SVM: creating linked list on device: %d ", ci); + + // reset allocator index + *pAllocator = numLists; // the first numLists elements of the nodes array are already allocated (they hold the head of each list). + error = clEnqueueNDRangeKernel(cmdq, kernel_create_lists, 1, NULL, &numLists, NULL, 0, NULL, NULL); + test_error(error, "clEnqueueNDRange failed."); + error = clFinish(cmdq); + test_error(error, "clFinish failed."); + return error; +} + +cl_int verify_linked_lists_on_device_no_map(int vi, cl_command_queue cmdq,cl_int* pNumCorrect, cl_kernel kernel_verify_lists, cl_int ListLength, size_t numLists ) +{ + cl_int error = CL_SUCCESS; + + log_info(" and verifying on device: %d ", vi); + + *pNumCorrect = 0; // reset numCorrect to zero + + error = clEnqueueNDRangeKernel(cmdq, kernel_verify_lists, 1, NULL, &numLists, NULL, 0, NULL, NULL); + test_error(error,"clEnqueueNDRangeKernel failed"); + clFinish(cmdq); + test_error(error,"clFinish failed"); + + cl_int correct_count = *pNumCorrect; + if(correct_count != ListLength * (cl_uint)numLists) + { + error = -1; + log_info("Failed\n"); + } + else + log_info("Passed\n"); + + return error; +} + +// This tests that all devices and the host share a common address space; using only the fine-grain with buffers mode. +// This is done by creating a linked list on a device and then verifying the correctness of the list +// on another device or the host. This basic test is performed for all combinations of devices and the host that exist within +// the platform. The test passes only if every combination passes. +int test_shared_address_space_fine_grain_buffers(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements) +{ + clContextWrapper context = NULL; + clProgramWrapper program = NULL; + cl_uint num_devices = 0; + cl_int error = CL_SUCCESS; + clCommandQueueWrapper queues[MAXQ]; + + error = create_cl_objects(deviceID, &linked_list_create_and_verify_kernels[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_FINE_GRAIN_BUFFER); + if(error == 1) return 0; // no devices capable of requested SVM level, so don't execute but count test as passing. + if(error < 0) return -1; // fail test. + + size_t numLists = num_elements; + cl_int ListLength = 32; + + clKernelWrapper kernel_create_lists = clCreateKernel(program, "create_linked_lists", &error); + test_error(error, "clCreateKernel failed"); + + clKernelWrapper kernel_verify_lists = clCreateKernel(program, "verify_linked_lists", &error); + test_error(error, "clCreateKernel failed"); + + // this buffer holds the linked list nodes. + Node* pNodes = (Node*) clSVMAlloc(context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER, sizeof(Node)*ListLength*numLists, 0); + + // this buffer holds an index into the nodes buffer, it is used for node allocation + size_t *pAllocator = (size_t*) clSVMAlloc(context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER, sizeof(size_t), 0); + + // this buffer holds the count of correct nodes, which is computed by the verify kernel. + cl_int *pNumCorrect = (cl_int*) clSVMAlloc(context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER, sizeof(cl_int), 0); + + error |= clSetKernelArgSVMPointer(kernel_create_lists, 0, pNodes); + error |= clSetKernelArgSVMPointer(kernel_create_lists, 1, pAllocator); + error |= clSetKernelArg(kernel_create_lists, 2, sizeof(cl_int), (void *) &ListLength); + + error |= clSetKernelArgSVMPointer(kernel_verify_lists, 0, pNodes); + error |= clSetKernelArgSVMPointer(kernel_verify_lists, 1, pNumCorrect); + error |= clSetKernelArg(kernel_verify_lists, 2, sizeof(cl_int), (void *) &ListLength); + test_error(error, "clSetKernelArg failed"); + + // Create linked list on one device and verify on another device (or the host). + // Do this for all possible combinations of devices and host within the platform. + for (int ci=0; ci<(int)num_devices+1; ci++) // ci is CreationIndex, index of device/q to create linked list on + { + for (int vi=0; vi<(int)num_devices+1; vi++) // vi is VerificationIndex, index of device/q to verify linked list on + { + if(ci == num_devices) // last device index represents the host, note the num_device+1 above. + { + log_info("SVM: creating linked list on host "); + create_linked_lists(pNodes, numLists, ListLength); + } + else + { + error = create_linked_lists_on_device_no_map(ci, queues[ci], pAllocator, kernel_create_lists, numLists); + if(error) return -1; + } + + if(vi == num_devices) + { + error = verify_linked_lists(pNodes, numLists, ListLength); + if(error) return -1; + } + else + { + error = verify_linked_lists_on_device_no_map(vi, queues[vi], pNumCorrect, kernel_verify_lists, ListLength, numLists); + if(error) return -1; + } + } + } + + clSVMFree(context, pNodes); + clSVMFree(context, pAllocator); + clSVMFree(context, pNumCorrect); + + return 0; +} diff --git a/test_conformance/SVM/test_shared_sub_buffers.cpp b/test_conformance/SVM/test_shared_sub_buffers.cpp new file mode 100644 index 00000000..7cf26ad0 --- /dev/null +++ b/test_conformance/SVM/test_shared_sub_buffers.cpp @@ -0,0 +1,241 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" + +const char *shared_sub_buffers_test_kernel[] = { + "typedef struct Node {\n" + " int global_id;\n" + " int position_in_list;\n" + " __global struct Node* pNext;\n" + "} Node;\n" + + // create linked lists that use nodes from 2 different buffers + "__global Node* allocate_node(__global Node* pNodes1, __global Node* pNodes2, volatile __global int* allocation_index, size_t i)\n" + "{\n" + // mix things up, adjacent work items will allocate from different buffers + " if(i & 0x1)\n" + " return &pNodes1[atomic_inc(allocation_index)];\n" + " else\n" + " return &pNodes2[atomic_inc(allocation_index)];\n" + "}\n" + + // The allocation_index parameter must be initialized on the host to N work-items + // The first N nodes in pNodes will be the heads of the lists. + // This tests passing 4 different sub-buffers that come from two parent buffers. + // Note that we have arguments that appear to be unused, but they are required so that system knows to get all the sub-buffers on to the device + "__kernel void create_linked_lists(__global Node* pNodes_sub1, __global Node* pNodes2_sub1, __global Node* pNodes_sub2, __global Node* pNodes2_sub2, volatile __global int* allocation_index, int list_length) \n" + "{\n" + " size_t i = get_global_id(0);\n" + " __global Node *pNode = &pNodes_sub1[i];\n" + " pNode->global_id = i;\n" + " pNode->position_in_list = 0;\n" + " __global Node *pNew;\n" + " for(int j=1; j < list_length; j++) {\n" + " pNew = allocate_node(pNodes_sub1, pNodes2_sub1, allocation_index, i);\n" + " pNew->global_id = i;\n" + " pNew->position_in_list = j;\n" + " pNode->pNext = pNew; // link new node onto end of list\n" + " pNode = pNew; // move to end of list\n" + " }\n" + "}\n" + // Note that we have arguments that appear to be unused, but they are required so that system knows to get all the sub-buffers on to the device + "__kernel void verify_linked_lists(__global Node* pNodes_sub1, __global Node* pNodes2_sub1, __global Node* pNodes_sub2, __global Node* pNodes2_sub2, volatile __global uint* num_correct, int list_length)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " __global Node *pNode = &pNodes_sub1[i];\n" + " for(int j=0; j < list_length; j++) {\n" + " if( pNode->global_id == i && pNode->position_in_list == j)\n" + " atomic_inc(num_correct);\n" + " else \n" + " break;\n" + " pNode = pNode->pNext;\n" + " }\n" + "}\n" +}; + + +// Creates linked list using host code. +cl_int create_linked_lists_on_host_sb(cl_command_queue cmdq, cl_mem nodes, cl_mem nodes2, cl_int ListLength, size_t numLists ) +{ + cl_int error = CL_SUCCESS; + + log_info("SVM: creating linked list on host "); + + Node *pNodes = (Node*) clEnqueueMapBuffer(cmdq, nodes, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(Node)*ListLength*numLists, 0, NULL,NULL, &error); + test_error2(error, pNodes, "clEnqueueMapBuffer failed"); + + Node *pNodes2 = (Node*) clEnqueueMapBuffer(cmdq, nodes2, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(Node)*ListLength*numLists, 0, NULL,NULL, &error); + test_error2(error, pNodes2, "clEnqueueMapBuffer failed"); + + create_linked_lists(pNodes, numLists, ListLength); + + error = clEnqueueUnmapMemObject(cmdq, nodes, pNodes, 0,NULL,NULL); + test_error(error, "clEnqueueUnmapMemObject failed"); + error = clEnqueueUnmapMemObject(cmdq, nodes2, pNodes2, 0,NULL,NULL); + test_error(error, "clEnqueueUnmapMemObject failed"); + error = clFinish(cmdq); + test_error(error, "clFinish failed"); + return error; +} + +// Verify correctness of the linked list using host code. +cl_int verify_linked_lists_on_host_sb(int ci, cl_command_queue cmdq, cl_mem nodes, cl_mem nodes2, cl_int ListLength, size_t numLists ) +{ + cl_int error = CL_SUCCESS; + + //log_info(" and verifying on host "); + + Node *pNodes = (Node*) clEnqueueMapBuffer(cmdq, nodes, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(Node)*ListLength * numLists, 0, NULL,NULL, &error); + test_error2(error, pNodes, "clEnqueueMapBuffer failed"); + Node *pNodes2 = (Node*) clEnqueueMapBuffer(cmdq, nodes2, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(Node)*ListLength * numLists, 0, NULL,NULL, &error); + test_error2(error, pNodes, "clEnqueueMapBuffer failed"); + + error = verify_linked_lists(pNodes, numLists, ListLength); + if(error) return -1; + + error = clEnqueueUnmapMemObject(cmdq, nodes, pNodes, 0,NULL,NULL); + test_error(error, "clEnqueueUnmapMemObject failed"); + error = clEnqueueUnmapMemObject(cmdq, nodes2, pNodes2, 0,NULL,NULL); + test_error(error, "clEnqueueUnmapMemObject failed"); + error = clFinish(cmdq); + test_error(error, "clFinish failed"); + return error; +} + + +// This tests that shared sub-buffers can be created and that they inherit the flags from the parent buffer when no flags are specified. +// This tests that passing only the sub-buffers to a kernel works. +// The test is derived from the cross-buffer pointers test which +// tests that shared buffers are able to contain pointers that point to other shared buffers. +// This tests that all devices and the host share a common address space; using only the coarse-grain features. +// This is done by creating a linked list on a device and then verifying the correctness of the list +// on another device or the host. +// The linked list nodes are allocated from two different buffers this is done to ensure that cross buffer pointers work correctly. +// This basic test is performed for all combinations of devices and the host. +int test_shared_sub_buffers(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements) +{ + clContextWrapper context = NULL; + clProgramWrapper program = NULL; + cl_uint num_devices = 0; + cl_int error = CL_SUCCESS; + clCommandQueueWrapper queues[MAXQ]; + + error = create_cl_objects(deviceID, &shared_sub_buffers_test_kernel[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER); + if(error) return -1; + + size_t numLists = num_elements; + if(numLists & 0x1) numLists++; // force even size, so we can easily create two sub-buffers of same size. + + cl_int ListLength = 32; + + clKernelWrapper kernel_create_lists = clCreateKernel(program, "create_linked_lists", &error); + test_error(error, "clCreateKernel failed"); + + clKernelWrapper kernel_verify_lists = clCreateKernel(program, "verify_linked_lists", &error); + test_error(error, "clCreateKernel failed"); + + size_t nodes_bufsize = sizeof(Node)*ListLength*numLists; + Node* pNodes = (Node*) clSVMAlloc(context, CL_MEM_READ_WRITE, nodes_bufsize, 0); + Node* pNodes2 = (Node*) clSVMAlloc(context, CL_MEM_READ_WRITE, nodes_bufsize, 0); + + { + // this buffer holds some of the linked list nodes. + clMemWrapper nodes = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, nodes_bufsize, pNodes, &error); + test_error(error, "clCreateBuffer failed."); + + cl_buffer_region r; + r.origin = 0; + r.size = nodes_bufsize / 2; + // this should inherit the flag settings from nodes buffer + clMemWrapper nodes_sb1 = clCreateSubBuffer(nodes, 0, CL_BUFFER_CREATE_TYPE_REGION, (void*)&r, &error); + test_error(error, "clCreateSubBuffer"); + r.origin = nodes_bufsize / 2; + clMemWrapper nodes_sb2 = clCreateSubBuffer(nodes, 0, CL_BUFFER_CREATE_TYPE_REGION, (void*)&r, &error); + test_error(error, "clCreateSubBuffer"); + + + // this buffer holds some of the linked list nodes. + clMemWrapper nodes2 = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(Node)*ListLength*numLists, pNodes2, &error); + test_error(error, "clCreateBuffer failed."); + r.origin = 0; + r.size = nodes_bufsize / 2; + // this should inherit the flag settings from nodes buffer + clMemWrapper nodes2_sb1 = clCreateSubBuffer(nodes2, 0, CL_BUFFER_CREATE_TYPE_REGION, (void*)&r, &error); + test_error(error, "clCreateSubBuffer"); + r.origin = nodes_bufsize / 2; + clMemWrapper nodes2_sb2 = clCreateSubBuffer(nodes2, 0, CL_BUFFER_CREATE_TYPE_REGION,(void*)&r, &error); + test_error(error, "clCreateSubBuffer"); + + + + // this buffer holds the index into the nodes buffer that is used for node allocation + clMemWrapper allocator = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, &error); + test_error(error, "clCreateBuffer failed."); + + // this buffer holds the count of correct nodes which is computed by the verify kernel. + clMemWrapper num_correct = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, &error); + test_error(error, "clCreateBuffer failed."); + + error |= clSetKernelArg(kernel_create_lists, 0, sizeof(void*), (void *) &nodes_sb1); + error |= clSetKernelArg(kernel_create_lists, 1, sizeof(void*), (void *) &nodes2_sb1); + error |= clSetKernelArg(kernel_create_lists, 2, sizeof(void*), (void *) &nodes_sb2); + error |= clSetKernelArg(kernel_create_lists, 3, sizeof(void*), (void *) &nodes2_sb2); + error |= clSetKernelArg(kernel_create_lists, 4, sizeof(void*), (void *) &allocator); + error |= clSetKernelArg(kernel_create_lists, 5, sizeof(cl_int),(void *) &ListLength); + + error |= clSetKernelArg(kernel_verify_lists, 0, sizeof(void*), (void *) &nodes_sb1); + error |= clSetKernelArg(kernel_verify_lists, 1, sizeof(void*), (void *) &nodes2_sb1); + error |= clSetKernelArg(kernel_verify_lists, 2, sizeof(void*), (void *) &nodes_sb2); + error |= clSetKernelArg(kernel_verify_lists, 3, sizeof(void*), (void *) &nodes2_sb2); + error |= clSetKernelArg(kernel_verify_lists, 4, sizeof(void*), (void *) &num_correct); + error |= clSetKernelArg(kernel_verify_lists, 5, sizeof(cl_int),(void *) &ListLength); + test_error(error, "clSetKernelArg failed"); + + // Create linked list on one device and verify on another device (or the host). + // Do this for all possible combinations of devices and host within the platform. + for (int ci=0; ci<(int)num_devices+1; ci++) // ci is CreationIndex, index of device/q to create linked list on + { + for (int vi=0; vi<(int)num_devices+1; vi++) // vi is VerificationIndex, index of device/q to verify linked list on + { + if(ci == num_devices) // last device index represents the host, note the num_device+1 above. + { + error = create_linked_lists_on_host_sb(queues[0], nodes, nodes2, ListLength, numLists); + if(error) return -1; + } + else + { + error = create_linked_lists_on_device(ci, queues[ci], allocator, kernel_create_lists, numLists); + if(error) return -1; + } + + if(vi == num_devices) + { + error = verify_linked_lists_on_host_sb(vi, queues[0], nodes, nodes2, ListLength, numLists); + if(error) return -1; + } + else + { + error = verify_linked_lists_on_device(vi, queues[vi], num_correct, kernel_verify_lists, ListLength, numLists); + if(error) return -1; + } + } // inner loop, vi + } // outer loop, ci + } + clSVMFree(context, pNodes2); + clSVMFree(context, pNodes); + + return 0; +} diff --git a/test_conformance/allocations/CMakeLists.txt b/test_conformance/allocations/CMakeLists.txt new file mode 100644 index 00000000..a42288b4 --- /dev/null +++ b/test_conformance/allocations/CMakeLists.txt @@ -0,0 +1,19 @@ +set(MODULE_NAME ALLOCATIONS) + +set(${MODULE_NAME}_SOURCES + main.cpp + allocation_execute.cpp + allocation_fill.cpp + allocation_functions.cpp + allocation_utils.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/typeWrappers.cpp + ../../test_common/harness/mt19937.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) diff --git a/test_conformance/allocations/Jamfile b/test_conformance/allocations/Jamfile new file mode 100644 index 00000000..aeb88d71 --- /dev/null +++ b/test_conformance/allocations/Jamfile @@ -0,0 +1,19 @@ +project + : requirements +# gcc:-xc++ +# msvc:"/TP" + ; + +exe test_allocations + : allocation_execute.cpp + allocation_fill.cpp + allocation_functions.cpp + allocation_utils.cpp + main.cpp + ; + +install dist + : test_allocations + : debug:$(DIST)/debug/tests/test_conformance/allocations + release:$(DIST)/release/tests/test_conformance/allocations + ; diff --git a/test_conformance/allocations/Makefile b/test_conformance/allocations/Makefile new file mode 100644 index 00000000..096e91cd --- /dev/null +++ b/test_conformance/allocations/Makefile @@ -0,0 +1,46 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.cpp \ + allocation_functions.cpp \ + allocation_fill.cpp \ + allocation_utils.cpp \ + allocation_execute.cpp \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/typeWrappers.cpp + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = $(SOURCES) +HEADERS = +TARGET = test_allocations +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/allocations/allocation_execute.cpp b/test_conformance/allocations/allocation_execute.cpp new file mode 100644 index 00000000..5168cfa4 --- /dev/null +++ b/test_conformance/allocations/allocation_execute.cpp @@ -0,0 +1,333 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "allocation_execute.h" +#include "allocation_functions.h" + + +const char *buffer_kernel_pattern = { + "__kernel void sample_test(%s __global uint *result, __global uint *array_sizes, uint per_item)\n" + "{\n" + "\tint tid = get_global_id(0);\n" + "\tuint r = 0;\n" + "\tuint i;\n" + "\tfor(i=tid*per_item; i<(1+tid)*per_item; i++) {\n" + "%s" + "\t}\n" + "\tresult[tid] = r;\n" + "}\n" }; + +const char *image_kernel_pattern = { + "__kernel void sample_test(%s __global uint *result)\n" + "{\n" + "\tuint4 color;\n" + "\tcolor = (uint4)(0);\n" + "%s" + "\tint x, y;\n" + "%s" + "\tresult[get_global_id(0)] += color.x + color.y + color.z + color.w;\n" + "}\n" }; + +const char *read_pattern = { + "\tfor(y=0; y max_size) + max_size = (cl_uint)(size/sizeof(cl_uint)); + } + buffer_sizes = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, sizeof(cl_uint)*number_of_mems_used, sizes, &error); + test_error_abort(error, "clCreateBuffer failed"); + error = clSetKernelArg(kernel, number_of_mems_used+1, sizeof(cl_mem), &buffer_sizes); + test_error(error, "clSetKernelArg failed"); + per_item = (cl_uint)ceil((double)max_size/global_dims[0]); + if (per_item > CL_UINT_MAX) + log_error("Size is too large for a uint parameter to the kernel. Expect invalid results.\n"); + per_item_uint = (cl_uint)per_item; + error = clSetKernelArg(kernel, number_of_mems_used+2, sizeof(per_item_uint), &per_item_uint); + test_error(error, "clSetKernelArg failed"); + free(sizes); + } + + size_t local_dims[3] = {1,1,1}; + error = get_max_common_work_group_size(context, kernel, global_dims[0], &local_dims[0]); + test_error(error, "get_max_common_work_group_size failed"); + + // Execute the kernel + error = clEnqueueNDRangeKernel(*queue, kernel, 1, NULL, global_dims, local_dims, 0, NULL, &event); + result = check_allocation_error(context, device_id, error, queue); + if (result != SUCCEEDED) { + if (result == FAILED_TOO_BIG) + log_info("\t\tExecute kernel failed: %s (global dim: %ld, local dim: %ld)\n", IGetErrorString(error), global_dims[0], local_dims[0]); + else + print_error(error, "clEnqueueNDRangeKernel failed"); + return result; + } + + // Finish the test + error = clFinish(*queue); + + result = check_allocation_error(context, device_id, error, queue); + + if (result != SUCCEEDED) { + if (result == FAILED_TOO_BIG) + log_info("\t\tclFinish failed: %s.\n", IGetErrorString(error)); + else + print_error(error, "clFinish failed"); + return result; + } + + // Verify that the event from the execution did not have an error + error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL); + test_error_abort(error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed"); + if (event_status < 0) { + result = check_allocation_error(context, device_id, event_status, queue); + if (result != SUCCEEDED) { + if (result == FAILED_TOO_BIG) + log_info("\t\tEvent returned from kernel execution indicates failure: %s.\n", IGetErrorString(event_status)); + else + print_error(event_status, "clEnqueueNDRangeKernel failed"); + return result; + } + } + + // If we are not verifying the checksum return here + if (!verify_checksum) { + log_info("Note: Allocations were not initialized so kernel execution can not verify correct results.\n"); + return SUCCEEDED; + } + + // Verify the checksum. + // Read back the result + error = clEnqueueReadBuffer(*queue, result_mem, CL_TRUE, 0, sizeof(cl_uint)*NUM_OF_WORK_ITEMS, &returned_results, 0, NULL, NULL); + test_error_abort(error, "clEnqueueReadBuffer failed"); + final_result = 0; + if (test == BUFFER || test == IMAGE_READ || test == BUFFER_NON_BLOCKING || test == IMAGE_READ_NON_BLOCKING) { + // For buffers or read images we are just looking at the sum of what each thread summed up + for (i=0; i size) + size_to_use = size; + + data = (cl_uint*)malloc(size_to_use); + if (data == NULL) { + log_error("Failed to malloc host buffer for writing into buffer.\n"); + return FAILED_ABORT; + } + for (i=0; i height) + image_lines_to_use = height; + + data = (cl_uint*)malloc(width*4*sizeof(cl_uint)*image_lines_to_use); + if (data == NULL) { + log_error("Failed to malloc host buffer for writing into image.\n"); + return FAILED_ABORT; + } + origin[0] = 0; + origin[1] = 0; + origin[2] = 0; + region[0] = width; + region[1] = image_lines_to_use; + region[2] = 1; + for (origin[1] = 0; origin[1] < height - image_lines_to_use; origin[1] += image_lines_to_use) { + // Put values in the data, and keep a checksum as we go along. + for (j=0; j (max_width*max_height)) { + if(NULL != max_size) { + *max_size = max_width * max_height * sizeof(cl_uint) * 4; + } + return FAILED_TOO_BIG; + } + + // We want a close-to-square aspect ratio. + // Note that this implicitly assumes that max width >= max height + found_width = (int)sqrt( (double) num_pixels ); + if( found_width > max_width ) { + found_width = max_width; + } + if (found_width == 0) + found_width = 1; + + found_height = (size_t)num_pixels/found_width; + if (found_height > max_height) { + found_height = max_height; + } + if (found_height == 0) + found_height = 1; + + *width = found_width; + *height = found_height; + + if(NULL != max_size) { + *max_size = found_width * found_height * sizeof(cl_uint) * 4; + } + + return SUCCEEDED; +} + + +int allocate_image2d_read(cl_context context, cl_command_queue *queue, cl_device_id device_id, cl_mem *mem, size_t size_to_allocate, cl_bool blocking_write) { + size_t width, height; + int error; + + error = find_good_image_size(device_id, size_to_allocate, &width, &height, NULL); + if (error != SUCCEEDED) + return error; + + log_info("\t\tAttempting to allocate a %gMB read-only image (%d x %d) and fill with %s writes.\n", + (size_to_allocate/(1024.0*1024.0)), (int)width, (int)height, (blocking_write ? "blocking" : "non-blocking")); + *mem = create_image_2d(context, CL_MEM_READ_ONLY, &image_format, width, height, 0, NULL, &error); + + return check_allocation_error(context, device_id, error, queue); +} + + +int allocate_image2d_write(cl_context context, cl_command_queue *queue, cl_device_id device_id, cl_mem *mem, size_t size_to_allocate, cl_bool blocking_write) { + size_t width, height; + int error; + + error = find_good_image_size(device_id, size_to_allocate, &width, &height, NULL); + if (error != SUCCEEDED) + return error; + + //log_info("\t\tAttempting to allocate a %gMB write-only image (%d x %d) and fill with %s writes.\n", + //(size_to_allocate/(1024.0*1024.0)), (int)width, (int)height, (blocking_write ? "blocking" : "non-blocking")); + *mem = create_image_2d(context, CL_MEM_WRITE_ONLY, &image_format, width, height, 0, NULL, &error); + + return check_allocation_error(context, device_id, error, queue); +} + +int do_allocation(cl_context context, cl_command_queue *queue, cl_device_id device_id, size_t size_to_allocate, int type, cl_mem *mem) { + if (type == BUFFER) return allocate_buffer(context, queue, device_id, mem, size_to_allocate, true); + if (type == IMAGE_READ) return allocate_image2d_read(context, queue, device_id, mem, size_to_allocate, true); + if (type == IMAGE_WRITE) return allocate_image2d_write(context, queue, device_id, mem, size_to_allocate, true); + if (type == BUFFER_NON_BLOCKING) return allocate_buffer(context, queue, device_id, mem, size_to_allocate, false); + if (type == IMAGE_READ_NON_BLOCKING) return allocate_image2d_read(context, queue, device_id, mem, size_to_allocate, false); + if (type == IMAGE_WRITE_NON_BLOCKING) return allocate_image2d_write(context, queue, device_id, mem, size_to_allocate, false); + log_error("Invalid allocation type: %d\n", type); + return FAILED_ABORT; +} + + +int allocate_size(cl_context context, cl_command_queue *queue, cl_device_id device_id, int multiple_allocations, size_t size_to_allocate, + int type, cl_mem mems[], int *number_of_mems, size_t *final_size, int force_fill, MTdata d) { + + cl_ulong max_individual_allocation_size, global_mem_size; + int error, result; + size_t amount_allocated; + size_t reduction_amount; + int current_allocation; + size_t allocation_this_time, actual_allocation; + + // Set the number of mems used to 0 so if we fail to create even a single one we don't end up returning a garbage value + *number_of_mems = 0; + + error = clGetDeviceInfo(device_id, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(max_individual_allocation_size), &max_individual_allocation_size, NULL); + test_error_abort( error, "clGetDeviceInfo failed for CL_DEVICE_MAX_MEM_ALLOC_SIZE"); + error = clGetDeviceInfo(device_id, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(global_mem_size), &global_mem_size, NULL); + test_error_abort( error, "clGetDeviceInfo failed for CL_DEVICE_GLOBAL_MEM_SIZE"); + + if (global_mem_size > (cl_ulong)SIZE_MAX) { + global_mem_size = (cl_ulong)SIZE_MAX; + } + +// log_info("Device reports CL_DEVICE_MAX_MEM_ALLOC_SIZE=%llu bytes (%gMB), CL_DEVICE_GLOBAL_MEM_SIZE=%llu bytes (%gMB).\n", +// max_individual_allocation_size, toMB(max_individual_allocation_size), +// global_mem_size, toMB(global_mem_size)); + + if (size_to_allocate > global_mem_size) { + log_error("Can not allocate more than the global memory size.\n"); + return FAILED_ABORT; + } + + amount_allocated = 0; + current_allocation = 0; + + // If allocating for images, reduce the maximum allocation size to the maximum image size. + // If we don't do this, then the value of CL_DEVICE_MAX_MEM_ALLOC_SIZE / 4 can be higher + // than the maximum image size on systems with 16GB or RAM or more. In this case, we + // succeed in allocating an image but its size is less than CL_DEVICE_MAX_MEM_ALLOC_SIZE / 4 + // (min_allocation_allowed) and thus we fail the allocation below. + if(type == IMAGE_READ || type == IMAGE_READ_NON_BLOCKING || type == IMAGE_WRITE || type == IMAGE_WRITE_NON_BLOCKING) { + size_t width; + size_t height; + size_t max_size; + error = find_good_image_size(device_id, size_to_allocate, &width, &height, &max_size); + if (!(error == SUCCEEDED || error == FAILED_TOO_BIG)) + return error; + if(max_size < max_individual_allocation_size) + max_individual_allocation_size = max_size; + } + + reduction_amount = (size_t)max_individual_allocation_size/16; + + if (type == BUFFER || type == BUFFER_NON_BLOCKING) log_info("\tAttempting to allocate a buffer of size %gMB.\n", toMB(size_to_allocate)); + else if (type == IMAGE_READ || type == IMAGE_READ_NON_BLOCKING) log_info("\tAttempting to allocate a read-only image of size %gMB.\n", toMB(size_to_allocate)); + else if (type == IMAGE_WRITE || type == IMAGE_WRITE_NON_BLOCKING) log_info("\tAttempting to allocate a write-only image of size %gMB.\n", toMB(size_to_allocate)); + +// log_info("\t\t(Reduction size is %gMB per iteration, minimum allowable individual allocation size is %gMB.)\n", +// toMB(reduction_amount), toMB(min_allocation_allowed)); +// if (force_fill && type != IMAGE_WRITE && type != IMAGE_WRITE_NON_BLOCKING) log_info("\t\t(Allocations will be filled with random data for checksum calculation.)\n"); + + // If we are only doing a single allocation, only allow 1 + int max_to_allocate = multiple_allocations ? MAX_NUMBER_TO_ALLOCATE : 1; + + // Make sure that the maximum number of images allocated is constrained by the + // maximum that may be passed to a kernel + if (type != BUFFER && type != BUFFER_NON_BLOCKING) { + cl_device_info param_name = (type == IMAGE_READ || type == IMAGE_READ_NON_BLOCKING) ? + CL_DEVICE_MAX_READ_IMAGE_ARGS : CL_DEVICE_MAX_WRITE_IMAGE_ARGS; + + cl_uint max_image_args; + error = clGetDeviceInfo(device_id, param_name, sizeof(max_image_args), &max_image_args, NULL); + test_error( error, "clGetDeviceInfo failed for CL_DEVICE_MAX IMAGE_ARGS"); + + if ((int)max_image_args < max_to_allocate) { + log_info("\t\tMaximum number of images per kernel limited to %d\n",(int)max_image_args); + max_to_allocate = max_image_args; + } + } + + + // Try to allocate the requested amount. + while (amount_allocated != size_to_allocate && current_allocation < max_to_allocate) { + + // Determine how much more is needed + allocation_this_time = size_to_allocate - amount_allocated; + + // Bound by the individual allocation size + if (allocation_this_time > max_individual_allocation_size) + allocation_this_time = (size_t)max_individual_allocation_size; + + // Allocate the largest object possible + result = FAILED_TOO_BIG; + //log_info("\t\tTrying sub-allocation %d at size %gMB.\n", current_allocation, toMB(allocation_this_time)); + while (result == FAILED_TOO_BIG && allocation_this_time != 0) { + + // Create the object + result = do_allocation(context, queue, device_id, allocation_this_time, type, &mems[current_allocation]); + if (result == SUCCEEDED) { + // Allocation succeeded, another memory object was added to the array + *number_of_mems = (current_allocation+1); + + // Verify the size is correct to within 1MB. + actual_allocation = get_actual_allocation_size(mems[current_allocation]); + if (fabs((double)allocation_this_time - (double)actual_allocation) > 1024.0*1024.0) { + log_error("Allocation not of expected size. Expected %gMB, got %gMB.\n", toMB(allocation_this_time), toMB( actual_allocation)); + return FAILED_ABORT; + } + + // If we are filling the allocation for verification do so + if (force_fill) { + //log_info("\t\t\tWriting random values to object and calculating checksum.\n"); + cl_bool blocking_write = true; + if (type == BUFFER_NON_BLOCKING || type == IMAGE_READ_NON_BLOCKING || type == IMAGE_WRITE_NON_BLOCKING) { + blocking_write = false; + } + result = fill_mem_with_data(context, device_id, queue, mems[current_allocation], d, blocking_write); + } + } + + // If creation failed, try to create a smaller object + if (result == FAILED_TOO_BIG) { + //log_info("\t\t\tAllocation %d failed at size %gMB. Trying smaller.\n", current_allocation, toMB(allocation_this_time)); + if (allocation_this_time > reduction_amount) + allocation_this_time -= reduction_amount; + else if (reduction_amount > 1) { + reduction_amount /= 2; + } + else { + allocation_this_time = 0; + } + + } + } + + if (result == FAILED_ABORT) { + log_error("\t\tAllocation failed.\n"); + return FAILED_ABORT; + } + + if (!allocation_this_time) { + log_info("\t\tFailed to allocate %gMB across several objects.\n", toMB(size_to_allocate)); + return FAILED_TOO_BIG; + } + + // Otherwise we succeeded + if (result != SUCCEEDED) { + log_error("Test logic error."); + test_finish(); + exit(-1); + } + amount_allocated += allocation_this_time; + + *final_size = amount_allocated; + + current_allocation++; + } + + log_info("\t\tSucceeded in allocating %gMB using %d memory objects.\n", toMB(amount_allocated), current_allocation); + return SUCCEEDED; +} diff --git a/test_conformance/allocations/allocation_functions.h b/test_conformance/allocations/allocation_functions.h new file mode 100644 index 00000000..939a993b --- /dev/null +++ b/test_conformance/allocations/allocation_functions.h @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "allocation_utils.h" + +int do_allocation(cl_context context, cl_command_queue *queue, cl_device_id device_id, size_t size_to_allocate, int type, cl_mem *mem); +int allocate_buffer(cl_context context, cl_command_queue *queue, cl_device_id device_id, cl_mem *mem, size_t size_to_allocate); +int allocate_image2d_read(cl_context context, cl_command_queue *queue, cl_device_id device_id, cl_mem *mem, size_t size_to_allocate); +int allocate_image2d_write(cl_context context, cl_command_queue *queue, cl_device_id device_id, cl_mem *mem, size_t size_to_allocate); +int allocate_size(cl_context context, cl_command_queue *queue, cl_device_id device_id, int multiple_allocations, size_t size_to_allocate, + int type, cl_mem mems[], int *number_of_mems, size_t *final_size, int force_fill, MTdata d); diff --git a/test_conformance/allocations/allocation_utils.cpp b/test_conformance/allocations/allocation_utils.cpp new file mode 100644 index 00000000..38282dfa --- /dev/null +++ b/test_conformance/allocations/allocation_utils.cpp @@ -0,0 +1,87 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "allocation_utils.h" + +cl_command_queue reset_queue(cl_context context, cl_device_id device_id, cl_command_queue *queue, int *error) +{ + log_info("Invalid command queue. Releasing and recreating the command queue.\n"); + clReleaseCommandQueue(*queue); + *queue = clCreateCommandQueueWithProperties(context, device_id, 0, error); + return *queue; +} + +int check_allocation_error(cl_context context, cl_device_id device_id, int error, cl_command_queue *queue) { + //log_info("check_allocation_error context=%p device_id=%p error=%d *queue=%p\n", context, device_id, error, *queue); + if ((error == CL_MEM_OBJECT_ALLOCATION_FAILURE ) || (error == CL_OUT_OF_RESOURCES ) || (error == CL_OUT_OF_HOST_MEMORY) || (error == CL_INVALID_IMAGE_SIZE)) { + return FAILED_TOO_BIG; + } else if (error == CL_INVALID_COMMAND_QUEUE) { + *queue = reset_queue(context, device_id, queue, &error); + if (CL_SUCCESS != error) + { + log_error("Failed to reset command queue after corrupted queue: %s\n", IGetErrorString(error)); + return FAILED_ABORT; + } + // Try again with smaller resources. + return FAILED_TOO_BIG; + } else if (error != CL_SUCCESS) { + log_error("Allocation failed with %s.\n", IGetErrorString(error)); + return FAILED_ABORT; + } + return SUCCEEDED; +} + + +double toMB(cl_ulong size_in) { + return (double)size_in/(1024.0*1024.0); +} + +size_t get_actual_allocation_size(cl_mem mem) { + int error; + cl_mem_object_type type; + size_t size, width, height; + + error = clGetMemObjectInfo(mem, CL_MEM_TYPE, sizeof(type), &type, NULL); + if (error) { + print_error(error, "clGetMemObjectInfo failed for CL_MEM_TYPE."); + return 0; + } + + if (type == CL_MEM_OBJECT_BUFFER) { + error = clGetMemObjectInfo(mem, CL_MEM_SIZE, sizeof(size), &size, NULL); + if (error) { + print_error(error, "clGetMemObjectInfo failed for CL_MEM_SIZE."); + return 0; + } + return size; + } else if (type == CL_MEM_OBJECT_IMAGE2D) { + error = clGetImageInfo(mem, CL_IMAGE_WIDTH, sizeof(width), &width, NULL); + if (error) { + print_error(error, "clGetMemObjectInfo failed for CL_IMAGE_WIDTH."); + return 0; + } + error = clGetImageInfo(mem, CL_IMAGE_HEIGHT, sizeof(height), &height, NULL); + if (error) { + print_error(error, "clGetMemObjectInfo failed for CL_IMAGE_HEIGHT."); + return 0; + } + return width*height*4*sizeof(cl_uint); + } + + log_error("Invalid CL_MEM_TYPE: %d\n", type); + return 0; +} + + diff --git a/test_conformance/allocations/allocation_utils.h b/test_conformance/allocations/allocation_utils.h new file mode 100644 index 00000000..a91a1235 --- /dev/null +++ b/test_conformance/allocations/allocation_utils.h @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +extern cl_uint checksum; + +int check_allocation_error(cl_context context, cl_device_id device_id, int error, cl_command_queue *queue); +double toMB(cl_ulong size_in); +size_t get_actual_allocation_size(cl_mem mem); + + diff --git a/test_conformance/allocations/main.cpp b/test_conformance/allocations/main.cpp new file mode 100644 index 00000000..d41470be --- /dev/null +++ b/test_conformance/allocations/main.cpp @@ -0,0 +1,411 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +#include "allocation_functions.h" +#include "allocation_fill.h" +#include "allocation_execute.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/parseParameters.h" +#include + +typedef long long unsigned llu; + +cl_device_id g_device_id; +cl_device_type g_device_type = CL_DEVICE_TYPE_DEFAULT; +clContextWrapper g_context; +clCommandQueueWrapper g_queue; +int g_repetition_count = 1; +int g_tests_to_run = 0; +int g_reduction_percentage = 100; +int g_write_allocations = 1; +int g_multiple_allocations = 0; +int g_execute_kernel = 1; + +cl_uint checksum; + +void printUsage( const char *execName ) +{ + const char *p = strrchr( execName, '/' ); + if( p != NULL ) + execName = p + 1; + + log_info( "Usage: %s [single|multiple] [numReps] [reduction%%] allocType\n", execName ); + log_info( "Where:\n" ); + log_info( "\tsingle - Tests using a single allocation as large as possible\n" ); + log_info( "\tmultiple - Tests using as many allocations as possible\n" ); + log_info( "\n" ); + log_info( "\tnumReps - Optional integer specifying the number of repetitions to run and average the result (defaults to 1)\n" ); + log_info( "\treduction%% - Optional integer, followed by a %% sign, that acts as a multiplier for the target amount of memory.\n" ); + log_info( "\t Example: target amount of 512MB and a reduction of 75%% will result in a target of 384MB.\n" ); + log_info( "\n" ); + log_info( "\tallocType - Allocation type to test with. Can be one of the following:\n" ); + log_info( "\t\tbuffer\n"); + log_info( "\t\timage2d_read\n"); + log_info( "\t\timage2d_write\n"); + log_info( "\t\tbuffer_non_blocking\n"); + log_info( "\t\timage2d_read_non_blocking\n"); + log_info( "\t\timage2d_write_non_blocking\n"); + log_info( "\t\tall (runs all of the above in sequence)\n" ); + log_info( "\tdo_not_force_fill - Disable explicitly write data to all memory objects after creating them.\n" ); + log_info( "\t Without this, the kernel execution can not verify its checksum.\n" ); + log_info( "\tdo_not_execute - Disable executing a kernel that accesses all of the memory objects.\n" ); +} + + +int init_cl() { + cl_platform_id platform; + int error; + + error = clGetPlatformIDs(1, &platform, NULL); + test_error(error, "clGetPlatformIDs failed"); + + error = clGetDeviceIDs(platform, g_device_type, 1, &g_device_id, NULL); + test_error(error, "clGetDeviceIDs failed"); + + /* Create a context */ + g_context = clCreateContext( NULL, 1, &g_device_id, notify_callback, NULL, &error ); + test_error(error, "clCreateContext failed"); + + /* Create command queue */ + g_queue = clCreateCommandQueueWithProperties( g_context, g_device_id, 0, &error ); + test_error(error, "clCreateCommandQueue failed"); + + return error; +} + + +int main(int argc, const char *argv[]) +{ + int error; + int count; + cl_mem mems[MAX_NUMBER_TO_ALLOCATE]; + cl_ulong max_individual_allocation_size, global_mem_size; + char str[ 128 ], *endPtr; + int r; + int number_of_mems_used; + int failure_counts = 0; + int test, test_to_run = 0; + int randomize = 0; + size_t final_size, max_size, current_test_size; + + test_start(); + + argc = parseCustomParam(argc, argv); + if (argc == -1) + { + test_finish(); + return -1; + } + + // Parse arguments + checkDeviceTypeOverride( &g_device_type ); + for( int i = 1; i < argc; i++ ) + { + strncpy( str, argv[ i ], sizeof( str ) - 1 ); + + if( strcmp( str, "cpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_CPU" ) == 0 ) + g_device_type = CL_DEVICE_TYPE_CPU; + else if( strcmp( str, "gpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_GPU" ) == 0 ) + g_device_type = CL_DEVICE_TYPE_GPU; + else if( strcmp( str, "accelerator" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + g_device_type = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( str, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + g_device_type = CL_DEVICE_TYPE_DEFAULT; + + else if( strcmp( str, "multiple" ) == 0 ) + g_multiple_allocations = 1; + else if( strcmp( str, "randomize" ) == 0 ) + randomize = 1; + else if( strcmp( str, "single" ) == 0 ) + g_multiple_allocations = 0; + + else if( ( r = (int)strtol( str, &endPtr, 10 ) ) && ( endPtr != str ) && ( *endPtr == 0 ) ) + { + // By spec, that means the entire string was an integer, so take it as a repetition count + g_repetition_count = r; + } + + else if( strcmp( str, "all" ) == 0 ) + { + g_tests_to_run = BUFFER | IMAGE_READ | IMAGE_WRITE | BUFFER_NON_BLOCKING | IMAGE_READ_NON_BLOCKING | IMAGE_WRITE_NON_BLOCKING; + } + + else if( strchr( str, '%' ) != NULL ) + { + // Reduction percentage (let strtol ignore the percentage) + g_reduction_percentage = (int)strtol( str, NULL, 10 ); + } + + else if( g_tests_to_run == 0 ) + { + if( strcmp( str, "buffer" ) == 0 ) + { + g_tests_to_run |= BUFFER; + } + else if( strcmp( str, "image2d_read" ) == 0 ) + { + g_tests_to_run |= IMAGE_READ; + } + else if( strcmp( str, "image2d_write" ) == 0 ) + { + g_tests_to_run |= IMAGE_WRITE; + } + else if( strcmp( str, "buffer_non_blocking" ) == 0 ) + { + g_tests_to_run |= BUFFER_NON_BLOCKING; + } + else if( strcmp( str, "image2d_read_non_blocking" ) == 0 ) + { + g_tests_to_run |= IMAGE_READ_NON_BLOCKING; + } + else if( strcmp( str, "image2d_write_non_blocking" ) == 0 ) + { + g_tests_to_run |= IMAGE_WRITE_NON_BLOCKING; + } + if( g_tests_to_run == 0 ) + break; // Argument is invalid; break to print usage + } + + else if( strcmp( str, "do_not_force_fill" ) == 0 ) + { + g_write_allocations = 0; + } + + else if( strcmp( str, "do_not_execute" ) == 0 ) + { + g_execute_kernel = 0; + } + + } + + if( randomize ) + { + gRandomSeed = (cl_uint) time( NULL ); + log_info( "Random seed: %u.\n", gRandomSeed ); + gReSeed = 1; + } + + if( g_tests_to_run == 0 ) + { + // Allocation type was never specified, or one of the arguments was invalid. Print usage and bail + printUsage( argv[ 0 ] ); + return -1; + } + + // All ready to go, so set up an environment + error = init_cl(); + if (error) { + test_finish(); + return -1; + } + + if( printDeviceHeader( g_device_id ) != CL_SUCCESS ) + { + test_finish(); + return -1; + } + + + error = clGetDeviceInfo(g_device_id, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(max_individual_allocation_size), &max_individual_allocation_size, NULL); + if ( error ) { + print_error( error, "clGetDeviceInfo failed for CL_DEVICE_MAX_MEM_ALLOC_SIZE"); + test_finish(); + return -1; + } + error = clGetDeviceInfo(g_device_id, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(global_mem_size), &global_mem_size, NULL); + if ( error ) { + print_error( error, "clGetDeviceInfo failed for CL_DEVICE_GLOBAL_MEM_SIZE"); + test_finish(); + return -1; + } + + log_info("Device reports CL_DEVICE_MAX_MEM_ALLOC_SIZE=%llu bytes (%gMB), CL_DEVICE_GLOBAL_MEM_SIZE=%llu bytes (%gMB).\n", + llu( max_individual_allocation_size ), toMB(max_individual_allocation_size), + llu( global_mem_size ), toMB(global_mem_size)); + + if (global_mem_size > (cl_ulong)SIZE_MAX) { + global_mem_size = (cl_ulong)SIZE_MAX; + } + + if( max_individual_allocation_size > global_mem_size ) + { + log_error( "FAILURE: CL_DEVICE_MAX_MEM_ALLOC_SIZE (%llu) is greater than the CL_DEVICE_GLOBAL_MEM_SIZE (%llu)\n", llu( max_individual_allocation_size ), llu( global_mem_size ) ); + test_finish(); + return -1; + } + + // We may need to back off the global_mem_size on unified memory devices to leave room for application and operating system code + // and associated data in the working set, so we dont start pathologically paging. + // Check to see if we are a unified memory device + cl_bool hasUnifiedMemory = CL_FALSE; + if( ( error = clGetDeviceInfo( g_device_id, CL_DEVICE_HOST_UNIFIED_MEMORY, sizeof( hasUnifiedMemory ), &hasUnifiedMemory, NULL ))) + { + print_error( error, "clGetDeviceInfo failed for CL_DEVICE_HOST_UNIFIED_MEMORY"); + test_finish(); + return -1; + } + // we share unified memory so back off to 1/2 the global memory size. + if( CL_TRUE == hasUnifiedMemory ) + { + global_mem_size -= global_mem_size /2; + log_info( "Device shares memory with the host, so backing off the maximum combined allocation size to be %gMB to avoid rampant paging.\n", toMB( global_mem_size ) ); + } + else + { + // Lets just use 60% of total available memory as framework/driver may not allow using all of it + // e.g. vram on GPU is used by window server and even for this test, we need some space for context, + // queue, kernel code on GPU. + global_mem_size *= 0.60; + } + + // Pick the baseline size based on whether we are doing a single large or multiple allocations + if (!g_multiple_allocations) { + max_size = (size_t)max_individual_allocation_size; + } else { + max_size = (size_t)global_mem_size; + } + + + // Adjust based on the percentage + if (g_reduction_percentage != 100) { + log_info("NOTE: reducing max allocations to %d%%.\n", g_reduction_percentage); + max_size = (size_t)((double)max_size * (double)g_reduction_percentage/100.0); + } + + // Round to nearest MB. + max_size &= (size_t)(0xFFFFFFFFFF00000ULL); + + log_info("** Target allocation size (rounded to nearest MB) is: %lu bytes (%gMB).\n", max_size, toMB(max_size)); + + // Run all the requested tests + RandomSeed seed( gRandomSeed ); + for (test=0; test<6; test++) { + if (test == 0) test_to_run = BUFFER; + if (test == 1) test_to_run = IMAGE_READ; + if (test == 2) test_to_run = IMAGE_WRITE; + if (test == 3) test_to_run = BUFFER_NON_BLOCKING; + if (test == 4) test_to_run = IMAGE_READ_NON_BLOCKING; + if (test == 5) test_to_run = IMAGE_WRITE_NON_BLOCKING; + if (!(g_tests_to_run & test_to_run)) + continue; + + // Skip image tests if we don't support images on the device + if (test > 0 && checkForImageSupport(g_device_id)) { + log_info("Can not test image allocation because device does not support images.\n"); + continue; + } + + // This section was added in order to fix a bug in the test + // If CL_DEVICE_MAX_MEM_ALLOC_SIZE is much grater than CL_DEVICE_IMAGE2D_MAX_WIDTH * CL_DEVICE_IMAGE2D_MAX_HEIGHT + // The test will fail in image allocations as the size requested for the allocation will be much grater than the maximum size allowed for image + if ( (test_to_run != BUFFER) && (test_to_run != BUFFER_NON_BLOCKING) ) { + size_t max_width, max_height; + cl_ulong max_image2d_size; + error = clGetDeviceInfo(g_device_id, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( max_width ), &max_width, NULL ); + test_error_abort( error, "clGetDeviceInfo failed for CL_DEVICE_IMAGE2D_MAX_WIDTH"); + error = clGetDeviceInfo(g_device_id, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( max_height ), &max_height, NULL ); + test_error_abort( error, "clGetDeviceInfo failed for CL_DEVICE_IMAGE2D_MAX_HEIGHT"); + max_image2d_size = (cl_ulong)max_height*max_width*4*sizeof(cl_uint); + + if (max_individual_allocation_size > max_image2d_size) + { + max_individual_allocation_size = max_image2d_size; + } + } + + // Pick the baseline size based on whether we are doing a single large or multiple allocations + if (!g_multiple_allocations) { + max_size = (size_t)max_individual_allocation_size; + } else { + max_size = (size_t)global_mem_size; + } + + // Adjust based on the percentage + if (g_reduction_percentage != 100) { + log_info("NOTE: reducing max allocations to %d%%.\n", g_reduction_percentage); + max_size = (size_t)((double)max_size * (double)g_reduction_percentage/100.0); + } + + // Round to nearest MB. + max_size &= (size_t)(0xFFFFFFFFFF00000ULL); + + log_info("** Target allocation size (rounded to nearest MB) is: %llu bytes (%gMB).\n", llu( max_size ), toMB(max_size)); + + if (test_to_run == BUFFER || test_to_run == BUFFER_NON_BLOCKING) log_info("** Allocating buffer(s) to size %gMB.\n", toMB(max_size)); + else if (test_to_run == IMAGE_READ || test_to_run == IMAGE_READ_NON_BLOCKING) log_info("** Allocating read-only image(s) to size %gMB.\n", toMB(max_size)); + else if (test_to_run == IMAGE_WRITE || test_to_run == IMAGE_WRITE_NON_BLOCKING) log_info("** Allocating write-only image(s) to size %gMB.\n", toMB(max_size)); + else {log_error("Test logic error.\n"); return -1;} + + // Run the test the requested number of times + for (count = 0; count < g_repetition_count; count++) { + current_test_size = max_size; + error = FAILED_TOO_BIG; + log_info(" => Allocation %d\n", count+1); + + while (error == FAILED_TOO_BIG && current_test_size > max_size/8) { + // Reset our checksum for each allocation + checksum = 0; + + // Do the allocation + error = allocate_size(g_context, &g_queue, g_device_id, g_multiple_allocations, current_test_size, test_to_run, mems, &number_of_mems_used, &final_size, g_write_allocations, seed); + + // If we succeeded and we're supposed to execute a kernel, do so. + if (error == SUCCEEDED && g_execute_kernel) { + log_info("\tExecuting kernel with memory objects.\n"); + error = execute_kernel(g_context, &g_queue, g_device_id, test_to_run, mems, number_of_mems_used, g_write_allocations); + } + + // If we failed to allocate more than 1/8th of the requested amount return a failure. + if (final_size < (size_t)max_size/8) { + // log_error("===> Allocation %d failed to allocate more than 1/8th of the requested size.\n", count+1); + failure_counts++; + } + // Clean up. + for (int i=0; i Allocation %d failed.\n", count+1); + failure_counts++; + } + + if (error == FAILED_TOO_BIG) { + current_test_size -= max_size/16; + // log_info("\tFailed at this size; trying a smaller size of %gMB.\n", toMB(current_test_size)); + } + } + if (error == SUCCEEDED && current_test_size == max_size) + log_info("\tPASS: Allocation succeeded.\n"); + else if (error == SUCCEEDED && current_test_size > max_size/8) + log_info("\tPASS: Allocation succeeded at reduced size.\n"); + else { + log_error("\tFAIL: Allocation failed.\n"); + failure_counts++; + } + } + } + + if (failure_counts) + log_error("FAILED allocations test.\n"); + else + log_info("PASSED allocations test.\n"); + + test_finish(); + return failure_counts; +} + + diff --git a/test_conformance/allocations/testBase.h b/test_conformance/allocations/testBase.h new file mode 100644 index 00000000..eadcd188 --- /dev/null +++ b/test_conformance/allocations/testBase.h @@ -0,0 +1,62 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testBase_h +#define _testBase_h + +#include "../../test_common/harness/compat.h" +#include +#include +#include + +#include +#include + +#if !defined(_WIN32) +#include +#endif + +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/testHarness.h" + + +#define MAX_NUMBER_TO_ALLOCATE 100 + +#define FAILED_CORRUPTED_QUEUE -2 +#define FAILED_ABORT -1 +#define FAILED_TOO_BIG 1 +// On Windows macro `SUCCEEDED' is defined in `WinError.h'. It causes compiler warnings. Let us avoid them. +#if defined( _WIN32 ) && defined( SUCCEEDED ) + #undef SUCCEEDED +#endif +#define SUCCEEDED 0 + +#define BUFFER 1 +#define IMAGE_READ 2 +#define IMAGE_WRITE 4 +#define BUFFER_NON_BLOCKING 8 +#define IMAGE_READ_NON_BLOCKING 16 +#define IMAGE_WRITE_NON_BLOCKING 32 + +#define test_error_abort(errCode,msg) test_error_ret_abort(errCode,msg,errCode) +#define test_error_ret_abort(errCode,msg,retValue) { if( errCode != CL_SUCCESS ) { print_error( errCode, msg ); return FAILED_ABORT ; } } + + +#endif // _testBase_h + + + diff --git a/test_conformance/api/CMakeLists.txt b/test_conformance/api/CMakeLists.txt new file mode 100644 index 00000000..bf3a126b --- /dev/null +++ b/test_conformance/api/CMakeLists.txt @@ -0,0 +1,39 @@ +set(MODULE_NAME API) + +set(${MODULE_NAME}_SOURCES + main.c + test_bool.c + test_retain.cpp + test_retain_program.c + test_queries.cpp + test_create_kernels.c + test_kernels.c + test_api_min_max.c + test_kernel_arg_changes.cpp + test_kernel_arg_multi_setup.cpp + test_binary.cpp + test_native_kernel.cpp + test_mem_objects.cpp + test_create_context_from_type.cpp + test_device_min_data_type_align_size_alignment.cpp + test_platform.cpp + test_kernel_arg_info.c + test_null_buffer_arg.c + test_mem_object_info.cpp + test_queue_hint.cpp + test_sub_group_dispatch.cpp + test_clone_kernel.cpp + test_zero_sized_enqueue.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/typeWrappers.cpp + ../../test_common/harness/conversions.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/imageHelpers.cpp + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) diff --git a/test_conformance/api/Jamfile b/test_conformance/api/Jamfile new file mode 100644 index 00000000..704b5ce1 --- /dev/null +++ b/test_conformance/api/Jamfile @@ -0,0 +1,27 @@ +project + : requirements + gcc:-xc++ + msvc:"/TP" + ; + + +exe test_api + : main.c + test_api_min_max.c + test_binary.cpp + test_create_kernels.c + test_create_context_from_type.cpp + test_kernel_arg_changes.cpp + test_kernel_arg_multi_setup.cpp + test_kernels.c + test_native_kernel.cpp + test_queries.cpp + test_retain_program.c + test_platform.cpp + ; + +install dist + : test_api #test.lst + : debug:$(DIST)/debug/tests/test_conformance/api + release:$(DIST)/release/tests/test_conformance/api + ; diff --git a/test_conformance/api/Makefile b/test_conformance/api/Makefile new file mode 100644 index 00000000..44cfaee3 --- /dev/null +++ b/test_conformance/api/Makefile @@ -0,0 +1,61 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + test_retain_program.c \ + test_queries.cpp \ + test_create_kernels.c \ + test_kernels.c \ + test_kernel_arg_info.c \ + test_api_min_max.c \ + test_kernel_arg_changes.cpp \ + test_kernel_arg_multi_setup.cpp \ + test_binary.cpp \ + test_native_kernel.cpp \ + test_create_context_from_type.cpp \ + test_platform.cpp \ + test_retain.cpp \ + test_device_min_data_type_align_size_alignment.cpp \ + test_mem_objects.cpp \ + test_bool.c \ + test_null_buffer_arg.c \ + test_mem_object_info.cpp \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/imageHelpers.cpp \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/typeWrappers.cpp \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/conversions.c + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +HEADERS = +TARGET = test_api +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/api/main.c b/test_conformance/api/main.c new file mode 100644 index 00000000..7f014382 --- /dev/null +++ b/test_conformance/api/main.c @@ -0,0 +1,223 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" +#include +#include + +#include +#include "procs.h" +#include "../../test_common/harness/testHarness.h" + +#if !defined(_WIN32) +#include +#endif + +// FIXME: To use certain functions in ../../test_common/harness/imageHelpers.h +// (for example, generate_random_image_data()), the tests are required to declare +// the following variables (): +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +bool gTestRounding = false; + +basefn basefn_list[] = { + test_get_platform_info, + test_get_sampler_info, + test_get_command_queue_info, + test_get_context_info, + test_get_device_info, + test_enqueue_task, + test_binary_get, + test_program_binary_create, + test_kernel_required_group_size, + + test_release_kernel_order, + test_release_during_execute, + + test_load_single_kernel, + test_load_two_kernels, + test_load_two_kernels_in_one, + test_load_two_kernels_manually, + test_get_program_info_kernel_names, + test_get_kernel_arg_info, + test_create_kernels_in_program, + test_get_kernel_info, + test_execute_kernel_local_sizes, + test_set_kernel_arg_by_index, + test_set_kernel_arg_constant, + test_set_kernel_arg_struct_array, + test_kernel_global_constant, + + test_min_max_thread_dimensions, + test_min_max_work_items_sizes, + test_min_max_work_group_size, + test_min_max_read_image_args, + test_min_max_write_image_args, + test_min_max_mem_alloc_size, + test_min_max_image_2d_width, + test_min_max_image_2d_height, + test_min_max_image_3d_width, + test_min_max_image_3d_height, + test_min_max_image_3d_depth, + test_min_max_image_array_size, + test_min_max_image_buffer_size, + test_min_max_parameter_size, + test_min_max_samplers, + test_min_max_constant_buffer_size, + test_min_max_constant_args, + test_min_max_compute_units, + test_min_max_address_bits, + test_min_max_single_fp_config, + test_min_max_double_fp_config, + test_min_max_local_mem_size, + test_min_max_kernel_preferred_work_group_size_multiple, + test_min_max_execution_capabilities, + test_min_max_queue_properties, + test_min_max_device_version, + test_min_max_language_version, + + test_kernel_arg_changes, + test_kernel_arg_multi_setup_random, + + test_native_kernel, + + test_create_context_from_type, + + test_platform_extensions, + test_get_platform_ids, + test_for_bool_type, + + test_repeated_setup_cleanup, + + test_retain_queue_single, + test_retain_queue_multiple, + test_retain_mem_object_single, + test_retain_mem_object_multiple, + test_min_data_type_align_size_alignment, + + test_mem_object_destructor_callback, + test_null_buffer_arg, + test_get_buffer_info, + test_get_image2d_info, + test_get_image3d_info, + test_get_image1d_info, + test_get_image1d_array_info, + test_get_image2d_array_info, + test_queue_hint, + test_sub_group_dispatch, + test_clone_kernel, + test_zero_sized_enqueue +}; + + +const char *basefn_names[] = { + "get_platform_info", + "get_sampler_info", + "get_command_queue_info", + "get_context_info", + "get_device_info", + "enqueue_task", + "binary_get", + "binary_create", + "kernel_required_group_size", + + "release_kernel_order", + "release_during_execute", + + "load_single_kernel", + "load_two_kernels", + "load_two_kernels_in_one", + "load_two_kernels_manually", + "get_program_info_kernel_names", + "get_kernel_arg_info", + "create_kernels_in_program", + "get_kernel_info", + "execute_kernel_local_sizes", + "set_kernel_arg_by_index", + "set_kernel_arg_constant", + "set_kernel_arg_struct_array", + "kernel_global_constant", + + "min_max_thread_dimensions", + "min_max_work_items_sizes", + "min_max_work_group_size", + "min_max_read_image_args", + "min_max_write_image_args", + "min_max_mem_alloc_size", + "min_max_image_2d_width", + "min_max_image_2d_height", + "min_max_image_3d_width", + "min_max_image_3d_height", + "min_max_image_3d_depth", + "min_max_image_array_size", + "min_max_image_buffer_size", + "min_max_parameter_size", + "min_max_samplers", + "min_max_constant_buffer_size", + "min_max_constant_args", + "min_max_compute_units", + "min_max_address_bits", + "min_max_single_fp_config", + "min_max_double_fp_config", + "min_max_local_mem_size", + "min_max_kernel_preferred_work_group_size_multiple", + "min_max_execution_capabilities", + "min_max_queue_properties", + "min_max_device_version", + "min_max_language_version", + + "kernel_arg_changes", + "kernel_arg_multi_setup_random", + + "native_kernel", + + "create_context_from_type", + "platform_extensions", + + "get_platform_ids", + "bool_type", + + "repeated_setup_cleanup", + + "retain_queue_single", + "retain_queue_multiple", + "retain_mem_object_single", + "retain_mem_object_multiple", + + "min_data_type_align_size_alignment", + + "mem_object_destructor_callback", + "null_buffer_arg", + "get_buffer_info", + "get_image2d_info", + "get_image3d_info", + "get_image1d_info", + "get_image1d_array_info", + "get_image2d_array_info", + "queue_hint", + "sub_group_dispatch", + "clone_kernel", + "zero_sized_enqueue", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + +int main(int argc, const char *argv[]) +{ + return runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false, false, 0 ); +} + + diff --git a/test_conformance/api/procs.h b/test_conformance/api/procs.h new file mode 100644 index 00000000..89713c5c --- /dev/null +++ b/test_conformance/api/procs.h @@ -0,0 +1,111 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/clImageHelper.h" +#include "../../test_common/harness/imageHelpers.h" +extern float calculate_ulperror(float a, float b); + +extern int test_load_single_kernel(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_load_two_kernels(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_load_two_kernels_in_one(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_load_two_kernels_manually(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_get_program_info_kernel_names( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_create_kernels_in_program(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_enqueue_task(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_repeated_setup_cleanup(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_for_bool_type(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_platform_extensions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_get_platform_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_get_sampler_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_get_command_queue_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_get_context_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_get_device_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_kernel_required_group_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_binary_get(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_program_binary_create(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_release_kernel_order(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_release_during_execute(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_get_kernel_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_execute_kernel_local_sizes(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_set_kernel_arg_by_index(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_set_kernel_arg_struct(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_set_kernel_arg_constant(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_set_kernel_arg_struct_array(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_kernel_global_constant(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_min_max_thread_dimensions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_work_items_sizes(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_work_group_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_read_image_args(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_write_image_args(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_mem_alloc_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_image_2d_width(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_image_2d_height(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_image_3d_width(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_image_3d_height(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_image_3d_depth(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_image_array_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_image_buffer_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_parameter_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_samplers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_constant_buffer_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_constant_args(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_compute_units(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_address_bits(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_single_fp_config(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_double_fp_config(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_local_mem_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_kernel_preferred_work_group_size_multiple(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_execution_capabilities(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_queue_properties(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_device_version(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_language_version(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_native_kernel(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); + +extern int test_create_context_from_type(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_get_platform_ids(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_kernel_arg_changes(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_kernel_arg_multi_setup_random(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_retain_queue_single(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_retain_queue_multiple(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_retain_mem_object_single(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_retain_mem_object_multiple(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_data_type_align_size_alignment(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); + +extern int test_mem_object_destructor_callback(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_null_buffer_arg( cl_device_id device_id, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_get_buffer_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ); +extern int test_get_image2d_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ); +extern int test_get_image3d_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ); +extern int test_get_image1d_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ); +extern int test_get_image1d_array_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ); +extern int test_get_image2d_array_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ); +extern int test_get_kernel_arg_info( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_queue_hint(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_sub_group_dispatch(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_clone_kernel(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_zero_sized_enqueue(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); diff --git a/test_conformance/api/testBase.h b/test_conformance/api/testBase.h new file mode 100644 index 00000000..8d58eeb6 --- /dev/null +++ b/test_conformance/api/testBase.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testBase_h +#define _testBase_h + +#include "../../test_common/harness/compat.h" +#include +#include +#include +#include +#include + +#include "procs.h" + +#endif // _testBase_h + + + diff --git a/test_conformance/api/test_api_min_max.c b/test_conformance/api/test_api_min_max.c new file mode 100644 index 00000000..57b0ab64 --- /dev/null +++ b/test_conformance/api/test_api_min_max.c @@ -0,0 +1,2115 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/testHarness.h" +#include +#include + +extern cl_uint gRandomSeed; + +const char *sample_single_param_kernel[] = { + "__kernel void sample_test(__global int *src)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + "}\n" }; + +const char *sample_single_param_write_kernel[] = { + "__kernel void sample_test(__global int *src)\n" + "{\n" + " int tid = get_global_id(0);\n" + " src[tid] = tid;\n" + "\n" + "}\n" }; + +const char *sample_read_image_kernel_pattern[] = { + "__kernel void sample_test( __global float *result, ", " )\n" + "{\n" + " sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST;\n" + " int tid = get_global_id(0);\n" + " result[0] = 0.0f;\n", + "\n" + "}\n" }; + +const char *sample_write_image_kernel_pattern[] = { + "__kernel void sample_test( ", " )\n" + "{\n" + " int tid = get_global_id(0);\n", + "\n" + "}\n" }; + + +const char *sample_large_parmam_kernel_pattern[] = { + "__kernel void sample_test(%s, __global long *result)\n" + "{\n" + "result[0] = 0;\n" + "%s" + "\n" + "}\n" }; + +const char *sample_large_int_parmam_kernel_pattern[] = { + "__kernel void sample_test(%s, __global int *result)\n" + "{\n" + "result[0] = 0;\n" + "%s" + "\n" + "}\n" }; + +const char *sample_sampler_kernel_pattern[] = { + "__kernel void sample_test( read_only image2d_t src, __global int4 *dst", ", sampler_t sampler%d", ")\n" + "{\n" + " int tid = get_global_id(0);\n", + " dst[ 0 ] = read_imagei( src, sampler%d, (int2)( 0, 0 ) );\n", + "\n" + "}\n" }; + +const char *sample_const_arg_kernel[] = { + "__kernel void sample_test(__constant int *src1, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src1[tid];\n" + "\n" + "}\n" }; + +const char *sample_local_arg_kernel[] = { + "__kernel void sample_test(__local int *src1, __global int *global_src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " src1[tid] = global_src[tid];\n" + " barrier(CLK_GLOBAL_MEM_FENCE);\n" + " dst[tid] = src1[tid];\n" + "\n" + "}\n" }; + +const char *sample_const_max_arg_kernel_pattern = +"__kernel void sample_test(__constant int *src1 %s, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = src1[tid];\n" +"%s" +"\n" +"}\n"; + +int test_min_max_thread_dimensions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error, retVal; + unsigned int maxThreadDim, threadDim, i; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[1]; + size_t *threads, *localThreads; + cl_event event; + cl_int event_status; + + + /* Get the max thread dimensions */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof( maxThreadDim ), &maxThreadDim, NULL ); + test_error( error, "Unable to get max work item dimensions from device" ); + + if( maxThreadDim < 3 ) + { + log_error( "ERROR: Reported max work item dimensions is less than required! (%d)\n", maxThreadDim ); + return -1; + } + + log_info("Reported max thread dimensions of %d.\n", maxThreadDim); + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_single_param_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 100, NULL, &error ); + if( streams[0] == NULL ) + { + log_error("ERROR: Creating test array failed!\n"); + return -1; + } + + /* Set the arguments */ + error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set kernel arguments" ); + + retVal = 0; + + /* Now try running the kernel with up to that many threads */ + for (threadDim=1; threadDim <= maxThreadDim; threadDim++) + { + threads = (size_t *)malloc( sizeof( size_t ) * maxThreadDim ); + localThreads = (size_t *)malloc( sizeof( size_t ) * maxThreadDim ); + for( i = 0; i < maxThreadDim; i++ ) + { + threads[ i ] = 1; + localThreads[i] = 1; + } + + error = clEnqueueNDRangeKernel( queue, kernel, maxThreadDim, NULL, threads, localThreads, 0, NULL, &event ); + test_error( error, "Failed clEnqueueNDRangeKernel"); + + // Verify that the event does not return an error from the execution + error = clWaitForEvents(1, &event); + test_error( error, "clWaitForEvent failed"); + error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL); + test_error( error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed"); + clReleaseEvent(event); + if (event_status < 0) + test_error(error, "Kernel execution event returned error"); + + /* All done */ + free( threads ); + free( localThreads ); + } + + return retVal; +} + + +int test_min_max_work_items_sizes(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t *deviceMaxWorkItemSize; + unsigned int maxWorkItemDim; + + /* Get the max work item dimensions */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof( maxWorkItemDim ), &maxWorkItemDim, NULL ); + test_error( error, "Unable to get max work item dimensions from device" ); + + log_info("CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS returned %d\n", maxWorkItemDim); + deviceMaxWorkItemSize = (size_t*)malloc(sizeof(size_t)*maxWorkItemDim); + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(size_t)*maxWorkItemDim, deviceMaxWorkItemSize, NULL ); + test_error( error, "clDeviceInfo for CL_DEVICE_MAX_WORK_ITEM_SIZES failed" ); + + unsigned int i; + int errors = 0; + for(i=0; i= 128 && maxParameterSize == 1024) + { + error = clGetDeviceInfo( deviceID, CL_DEVICE_TYPE, sizeof( deviceType ), &deviceType, NULL ); + test_error( error, "Unable to get device type from device" ); + + if(deviceType != CL_DEVICE_TYPE_CUSTOM) + { + maxReadImages = 127; + } + } + // Subtract the size of the result + maxParameterSize -= deviceAddressSize; + + // Calculate the number we can use + if (maxParameterSize/deviceAddressSize < maxReadImages) { + log_info("WARNING: Max parameter size of %d bytes limits test to %d max image arguments.\n", (int)maxParameterSize, (int)(maxParameterSize/deviceAddressSize)); + maxReadImages = (unsigned int)(maxParameterSize/deviceAddressSize); + } + + /* Create a program with that many read args */ + programSrc = (char *)malloc( strlen( sample_read_image_kernel_pattern[ 0 ] ) + ( strlen( readArgPattern ) + 6 ) * ( maxReadImages ) + + strlen( sample_read_image_kernel_pattern[ 1 ] ) + 1 + 40240); + + strcpy( programSrc, sample_read_image_kernel_pattern[ 0 ] ); + strcat( programSrc, "read_only image2d_t srcimg0" ); + for( i = 0; i < maxReadImages-1; i++ ) + { + sprintf( readArgLine, readArgPattern, i+1 ); + strcat( programSrc, readArgLine ); + } + strcat( programSrc, sample_read_image_kernel_pattern[ 1 ] ); + for ( i = 0; i < maxReadImages; i++) { + sprintf( readArgLine, "\tresult[0] += read_imagef( srcimg%d, sampler, (int2)(0,0)).x;\n", i); + strcat( programSrc, readArgLine ); + } + strcat( programSrc, sample_read_image_kernel_pattern[ 2 ] ); + + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&programSrc, "sample_test"); + test_error( error, "Failed to create the program and kernel."); + free( programSrc ); + + result = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float), NULL, &error); + test_error( error, "clCreateBufer failed"); + + /* Create some I/O streams */ + streams = new clMemWrapper[maxReadImages + 1]; + for( i = 0; i < maxReadImages; i++ ) + { + image_data[0]=i; + image_result+= image_data[0]; + streams[i] = create_image_2d( context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, &image_format_desc, 4, 4, 0, image_data, &error ); + test_error( error, "Unable to allocate test image" ); + } + + error = clSetKernelArg( kernel, 0, sizeof( result ), &result ); + test_error( error, "Unable to set kernel arguments" ); + + /* Set the arguments */ + for( i = 1; i < maxReadImages+1; i++ ) + { + error = clSetKernelArg( kernel, i, sizeof( streams[i-1] ), &streams[i-1] ); + test_error( error, "Unable to set kernel arguments" ); + } + + /* Now try running the kernel */ + threads[0] = threads[1] = 1; + error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, &event ); + test_error( error, "clEnqueueNDRangeKernel failed"); + + // Verify that the event does not return an error from the execution + error = clWaitForEvents(1, &event); + test_error( error, "clWaitForEvent failed"); + error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL); + test_error( error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed"); + clReleaseEvent(event); + if (event_status < 0) + test_error(error, "Kernel execution event returned error"); + + error = clEnqueueReadBuffer(queue, result, CL_TRUE, 0, sizeof(cl_float), &actual_image_result, 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + delete[] streams; + + if (actual_image_result != image_result) { + log_error("Result failed to verify. Got %g, expected %g.\n", actual_image_result, image_result); + return 1; + } + + return 0; +} + +int test_min_max_write_image_args(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + unsigned int maxWriteImages, i; + clProgramWrapper program; + char writeArgLine[128], *programSrc; + const char *writeArgPattern = ", write_only image2d_t dstimg%d"; + clKernelWrapper kernel; + clMemWrapper *streams; + size_t threads[2]; + cl_image_format image_format_desc; + size_t maxParameterSize; + cl_event event; + cl_int event_status; + cl_uint minRequiredWriteImages = gIsEmbedded ? 1 : 8; + + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ) + image_format_desc.image_channel_order = CL_RGBA; + image_format_desc.image_channel_data_type = CL_UNORM_INT8; + + /* Get the max read image arg count */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, sizeof( maxWriteImages ), &maxWriteImages, NULL ); + test_error( error, "Unable to get max write image arg count from device" ); + + if( maxWriteImages == 0 ) + { + log_info( "WARNING: Device reports 0 for a max write image arg count (write image arguments unsupported). Skipping test (implicitly passes). This is only valid if the number of image formats is also 0.\n" ); + return 0; + } + + if( maxWriteImages < minRequiredWriteImages ) + { + log_error( "ERROR: Reported max write image arg count is less than required! (%d)\n", maxWriteImages ); + return -1; + } + + log_info("Reported %d max write image args.\n", maxWriteImages); + + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof( maxParameterSize ), &maxParameterSize, NULL ); + test_error( error, "Unable to get max parameter size from device" ); + + // Calculate the number we can use + if (maxParameterSize/sizeof(cl_mem) < maxWriteImages) { + log_info("WARNING: Max parameter size of %d bytes limits test to %d max image arguments.\n", (int)maxParameterSize, (int)(maxParameterSize/sizeof(cl_mem))); + maxWriteImages = (unsigned int)(maxParameterSize/sizeof(cl_mem)); + } + + /* Create a program with that many write args + 1 */ + programSrc = (char *)malloc( strlen( sample_write_image_kernel_pattern[ 0 ] ) + ( strlen( writeArgPattern ) + 6 ) * ( maxWriteImages + 1 ) + + strlen( sample_write_image_kernel_pattern[ 1 ] ) + 1 + 40240 ); + + strcpy( programSrc, sample_write_image_kernel_pattern[ 0 ] ); + strcat( programSrc, "write_only image2d_t dstimg0" ); + for( i = 1; i < maxWriteImages; i++ ) + { + sprintf( writeArgLine, writeArgPattern, i ); + strcat( programSrc, writeArgLine ); + } + strcat( programSrc, sample_write_image_kernel_pattern[ 1 ] ); + for ( i = 0; i < maxWriteImages; i++) { + sprintf( writeArgLine, "\twrite_imagef( dstimg%d, (int2)(0,0), (float4)(0,0,0,0));\n", i); + strcat( programSrc, writeArgLine ); + } + strcat( programSrc, sample_write_image_kernel_pattern[ 2 ] ); + + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&programSrc, "sample_test"); + test_error( error, "Failed to create the program and kernel."); + free( programSrc ); + + + /* Create some I/O streams */ + streams = new clMemWrapper[maxWriteImages + 1]; + for( i = 0; i < maxWriteImages; i++ ) + { + streams[i] = create_image_2d( context, CL_MEM_READ_WRITE, &image_format_desc, 16, 16, 0, NULL, &error ); + test_error( error, "Unable to allocate test image" ); + } + + /* Set the arguments */ + for( i = 0; i < maxWriteImages; i++ ) + { + error = clSetKernelArg( kernel, i, sizeof( streams[i] ), &streams[i] ); + test_error( error, "Unable to set kernel arguments" ); + } + + /* Now try running the kernel */ + threads[0] = threads[1] = 16; + error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, &event ); + test_error( error, "clEnqueueNDRangeKernel failed."); + + // Verify that the event does not return an error from the execution + error = clWaitForEvents(1, &event); + test_error( error, "clWaitForEvent failed"); + error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL); + test_error( error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed"); + clReleaseEvent(event); + if (event_status < 0) + test_error(error, "Kernel execution event returned error"); + + /* All done */ + delete[] streams; + return 0; +} + +int test_min_max_mem_alloc_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_ulong maxAllocSize, memSize, minSizeToTry; + clMemWrapper memHdl; + + cl_ulong requiredAllocSize; + + if (gIsEmbedded) + requiredAllocSize = 1 * 1024 * 1024; + else + requiredAllocSize = 128 * 1024 * 1024; + + /* Get the max mem alloc size */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get max mem alloc size from device" ); + + error = clGetDeviceInfo( deviceID, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get global memory size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( maxAllocSize < requiredAllocSize) + { + log_error( "ERROR: Reported max allocation size is less than required %lldMB! (%llu or %lluMB, from a total mem size of %lldMB)\n", (requiredAllocSize / 1024) / 1024, maxAllocSize, (maxAllocSize / 1024)/1024, (memSize / 1024)/1024 ); + return -1; + } + + requiredAllocSize = ((memSize / 4) > (1024 * 1024 * 1024)) ? 1024 * 1024 * 1024 : memSize / 4; + + if (gIsEmbedded) + requiredAllocSize = (requiredAllocSize < 1 * 1024 * 1024) ? 1 * 1024 * 1024 : requiredAllocSize; + else + requiredAllocSize = (requiredAllocSize < 128 * 1024 * 1024) ? 128 * 1024 * 1024 : requiredAllocSize; + + if( maxAllocSize < requiredAllocSize ) + { + log_error( "ERROR: Reported max allocation size is less than required of total memory! (%llu or %lluMB, from a total mem size of %lluMB)\n", maxAllocSize, (maxAllocSize / 1024)/1024, (requiredAllocSize / 1024)/1024 ); + return -1; + } + + log_info("Reported max allocation size of %lld bytes (%gMB) and global mem size of %lld bytes (%gMB).\n", + maxAllocSize, maxAllocSize/(1024.0*1024.0), requiredAllocSize, requiredAllocSize/(1024.0*1024.0)); + + if ( memSize < maxAllocSize ) { + log_info("Global memory size is less than max allocation size, using that.\n"); + maxAllocSize = memSize; + } + + minSizeToTry = maxAllocSize/16; + while (maxAllocSize > (maxAllocSize/4)) { + + log_info("Trying to create a buffer of size of %lld bytes (%gMB).\n", maxAllocSize, (double)maxAllocSize/(1024.0*1024.0)); + memHdl = clCreateBuffer( context, CL_MEM_READ_ONLY, (size_t)maxAllocSize, NULL, &error ); + if (error == CL_MEM_OBJECT_ALLOCATION_FAILURE || error == CL_OUT_OF_RESOURCES || error == CL_OUT_OF_HOST_MEMORY) { + log_info("\tAllocation failed at size of %lld bytes (%gMB).\n", maxAllocSize, (double)maxAllocSize/(1024.0*1024.0)); + maxAllocSize -= minSizeToTry; + continue; + } + test_error( error, "clCreateBuffer failed for maximum sized buffer."); + return 0; + } + log_error("Failed to allocate even %lld bytes (%gMB).\n", maxAllocSize, (double)maxAllocSize/(1024.0*1024.0)); + return -1; +} + +int test_min_max_image_2d_width(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t maxDimension; + clMemWrapper streams[1]; + cl_image_format image_format_desc; + cl_ulong maxAllocSize; + cl_uint minRequiredDimension; + cl_char buffer[ 4098 ]; + size_t length; + + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ) + + // Device version should fit the regex "OpenCL [0-9]+\.[0-9]+ *.*" + error = clGetDeviceInfo( deviceID, CL_DEVICE_VERSION, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get device version string" ); + if( memcmp( buffer, "OpenCL 2.0", strlen( "OpenCL 2.0" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 8192; + else if( memcmp( buffer, "OpenCL 2.1", strlen( "OpenCL 2.1" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 8192; + else if( memcmp( buffer, "OpenCL 1.2", strlen( "OpenCL 1.2" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 8192; + else if( memcmp( buffer, "OpenCL 1.1", strlen( "OpenCL 1.1" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 8192; + else if ( memcmp( buffer, "OpenCL 1.0", strlen( "OpenCL 1.0" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 4096; + else + { + log_error( "ERROR: device version string does not match required format! (returned: %s)\n", (char *)buffer ); + return -1; + } + + + /* Just get any ol format to test with */ + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE2D, CL_MEM_READ_WRITE, 0, &image_format_desc ); + test_error( error, "Unable to obtain suitable image format to test with!" ); + + /* Get the max 2d image width */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxDimension ), &maxDimension, NULL ); + test_error( error, "Unable to get max image 2d width from device" ); + + if( maxDimension < minRequiredDimension ) + { + log_error( "ERROR: Reported max image 2d width is less than required! (%d)\n", (int)maxDimension ); + return -1; + } + log_info("Max reported width is %ld.\n", maxDimension); + + /* Verify we can use the format */ + image_format_desc.image_channel_data_type = CL_UNORM_INT8; + image_format_desc.image_channel_order = CL_RGBA; + if (!is_image_format_supported( context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE2D, &image_format_desc)) { + log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test."); + return -1; + } + + /* Verify that we can actually allocate an image that large */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof ( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE." ); + if ( (cl_ulong)maxDimension*1*4 > maxAllocSize ) { + log_error("Can not allocate a large enough image (min size: %lld bytes, max allowed: %lld bytes) to test.\n", + (cl_ulong)maxDimension*1*4, maxAllocSize); + return -1; + } + + log_info("Attempting to create an image of size %d x 1 = %gMB.\n", (int)maxDimension, ((float)maxDimension*4/1024.0/1024.0)); + + /* Try to allocate a very big image */ + streams[0] = create_image_2d( context, CL_MEM_READ_ONLY, &image_format_desc, maxDimension, 1, 0, NULL, &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "Image 2D creation failed for maximum width" ); + return -1; + } + + return 0; +} + +int test_min_max_image_2d_height(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t maxDimension; + clMemWrapper streams[1]; + cl_image_format image_format_desc; + cl_ulong maxAllocSize; + cl_uint minRequiredDimension; + cl_char buffer[ 4098 ]; + size_t length; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ) + + // Device version should fit the regex "OpenCL [0-9]+\.[0-9]+ *.*" + error = clGetDeviceInfo( deviceID, CL_DEVICE_VERSION, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get device version string" ); + if( memcmp( buffer, "OpenCL 2.0", strlen( "OpenCL 2.0" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 8192; + else if( memcmp( buffer, "OpenCL 2.1", strlen( "OpenCL 2.1" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 8192; + else if( memcmp( buffer, "OpenCL 1.2", strlen( "OpenCL 1.2" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 8192; + else if( memcmp( buffer, "OpenCL 1.1", strlen( "OpenCL 1.1" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 8192; + else if ( memcmp( buffer, "OpenCL 1.0", strlen( "OpenCL 1.0" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 4096; + else + { + log_error( "ERROR: device version string does not match required format! (returned: %s)\n", (char *)buffer ); + return -1; + } + + /* Just get any ol format to test with */ + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE2D, CL_MEM_READ_WRITE, 0, &image_format_desc ); + test_error( error, "Unable to obtain suitable image format to test with!" ); + + /* Get the max 2d image width */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxDimension ), &maxDimension, NULL ); + test_error( error, "Unable to get max image 2d height from device" ); + + if( maxDimension < minRequiredDimension ) + { + log_error( "ERROR: Reported max image 2d height is less than required! (%d)\n", (int)maxDimension ); + return -1; + } + log_info("Max reported height is %ld.\n", maxDimension); + + /* Verify we can use the format */ + image_format_desc.image_channel_data_type = CL_UNORM_INT8; + image_format_desc.image_channel_order = CL_RGBA; + if (!is_image_format_supported( context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE2D, &image_format_desc)) { + log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test."); + return -1; + } + + /* Verify that we can actually allocate an image that large */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof ( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE." ); + if ( (cl_ulong)maxDimension*1*4 > maxAllocSize ) { + log_error("Can not allocate a large enough image (min size: %lld bytes, max allowed: %lld bytes) to test.\n", + (cl_ulong)maxDimension*1*4, maxAllocSize); + return -1; + } + + log_info("Attempting to create an image of size 1 x %d = %gMB.\n", (int)maxDimension, ((float)maxDimension*4/1024.0/1024.0)); + + /* Try to allocate a very big image */ + streams[0] = create_image_2d( context, CL_MEM_READ_ONLY, &image_format_desc, 1, maxDimension, 0, NULL, &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "Image 2D creation failed for maximum height" ); + return -1; + } + + return 0; +} + +int test_min_max_image_3d_width(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t maxDimension; + clMemWrapper streams[1]; + cl_image_format image_format_desc; + cl_ulong maxAllocSize; + + + PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( deviceID ) + + /* Just get any ol format to test with */ + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE3D, CL_MEM_READ_WRITE, 0, &image_format_desc ); + test_error( error, "Unable to obtain suitable image format to test with!" ); + + /* Get the max 2d image width */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxDimension ), &maxDimension, NULL ); + test_error( error, "Unable to get max image 3d width from device" ); + + if( maxDimension < 2048 ) + { + log_error( "ERROR: Reported max image 3d width is less than required! (%d)\n", (int)maxDimension ); + return -1; + } + log_info("Max reported width is %ld.\n", maxDimension); + + /* Verify we can use the format */ + image_format_desc.image_channel_data_type = CL_UNORM_INT8; + image_format_desc.image_channel_order = CL_RGBA; + if (!is_image_format_supported( context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE3D, &image_format_desc)) { + log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test."); + return -1; + } + + /* Verify that we can actually allocate an image that large */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof ( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE." ); + if ( (cl_ulong)maxDimension*2*4 > maxAllocSize ) { + log_error("Can not allocate a large enough image (min size: %lld bytes, max allowed: %lld bytes) to test.\n", + (cl_ulong)maxDimension*2*4, maxAllocSize); + return -1; + } + + log_info("Attempting to create an image of size %d x 1 x 2 = %gMB.\n", (int)maxDimension, (2*(float)maxDimension*4/1024.0/1024.0)); + + /* Try to allocate a very big image */ + streams[0] = create_image_3d( context, CL_MEM_READ_ONLY, &image_format_desc, maxDimension, 1, 2, 0, 0, NULL, &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "Image 3D creation failed for maximum width" ); + return -1; + } + + return 0; +} + +int test_min_max_image_3d_height(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t maxDimension; + clMemWrapper streams[1]; + cl_image_format image_format_desc; + cl_ulong maxAllocSize; + + + PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( deviceID ) + + /* Just get any ol format to test with */ + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE3D, CL_MEM_READ_WRITE, 0, &image_format_desc ); + test_error( error, "Unable to obtain suitable image format to test with!" ); + + /* Get the max 2d image width */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxDimension ), &maxDimension, NULL ); + test_error( error, "Unable to get max image 3d height from device" ); + + if( maxDimension < 2048 ) + { + log_error( "ERROR: Reported max image 3d height is less than required! (%d)\n", (int)maxDimension ); + return -1; + } + log_info("Max reported height is %ld.\n", maxDimension); + + /* Verify we can use the format */ + image_format_desc.image_channel_data_type = CL_UNORM_INT8; + image_format_desc.image_channel_order = CL_RGBA; + if (!is_image_format_supported( context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE3D, &image_format_desc)) { + log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test."); + return -1; + } + + /* Verify that we can actually allocate an image that large */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof ( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE." ); + if ( (cl_ulong)maxDimension*2*4 > maxAllocSize ) { + log_error("Can not allocate a large enough image (min size: %lld bytes, max allowed: %lld bytes) to test.\n", + (cl_ulong)maxDimension*2*4, maxAllocSize); + return -1; + } + + log_info("Attempting to create an image of size 1 x %d x 2 = %gMB.\n", (int)maxDimension, (2*(float)maxDimension*4/1024.0/1024.0)); + + /* Try to allocate a very big image */ + streams[0] = create_image_3d( context, CL_MEM_READ_ONLY, &image_format_desc, 1, maxDimension, 2, 0, 0, NULL, &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "Image 3D creation failed for maximum height" ); + return -1; + } + + return 0; +} + + +int test_min_max_image_3d_depth(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t maxDimension; + clMemWrapper streams[1]; + cl_image_format image_format_desc; + cl_ulong maxAllocSize; + + + PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( deviceID ) + + /* Just get any ol format to test with */ + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE3D, CL_MEM_READ_WRITE, 0, &image_format_desc ); + test_error( error, "Unable to obtain suitable image format to test with!" ); + + /* Get the max 2d image width */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDimension ), &maxDimension, NULL ); + test_error( error, "Unable to get max image 3d depth from device" ); + + if( maxDimension < 2048 ) + { + log_error( "ERROR: Reported max image 3d depth is less than required! (%d)\n", (int)maxDimension ); + return -1; + } + log_info("Max reported depth is %ld.\n", maxDimension); + + /* Verify we can use the format */ + image_format_desc.image_channel_data_type = CL_UNORM_INT8; + image_format_desc.image_channel_order = CL_RGBA; + if (!is_image_format_supported( context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE3D, &image_format_desc)) { + log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test."); + return -1; + } + + /* Verify that we can actually allocate an image that large */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof ( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE." ); + if ( (cl_ulong)maxDimension*1*4 > maxAllocSize ) { + log_error("Can not allocate a large enough image (min size: %lld bytes, max allowed: %lld bytes) to test.\n", + (cl_ulong)maxDimension*1*4, maxAllocSize); + return -1; + } + + log_info("Attempting to create an image of size 1 x 1 x %d = %gMB.\n", (int)maxDimension, ((float)maxDimension*4/1024.0/1024.0)); + + /* Try to allocate a very big image */ + streams[0] = create_image_3d( context, CL_MEM_READ_ONLY, &image_format_desc, 1, 1, maxDimension, 0, 0, NULL, &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "Image 3D creation failed for maximum depth" ); + return -1; + } + + return 0; +} + +int test_min_max_image_array_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t maxDimension; + clMemWrapper streams[1]; + cl_image_format image_format_desc; + cl_ulong maxAllocSize; + size_t minRequiredDimension = gIsEmbedded ? 256 : 2048; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ); + + /* Just get any ol format to test with */ + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE2D_ARRAY, CL_MEM_READ_WRITE, 0, &image_format_desc ); + test_error( error, "Unable to obtain suitable image format to test with!" ); + + /* Get the max image array width */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxDimension ), &maxDimension, NULL ); + test_error( error, "Unable to get max image array size from device" ); + + if( maxDimension < minRequiredDimension ) + { + log_error( "ERROR: Reported max image array size is less than required! (%d)\n", (int)maxDimension ); + return -1; + } + log_info("Max reported image array size is %ld.\n", maxDimension); + + /* Verify we can use the format */ + image_format_desc.image_channel_data_type = CL_UNORM_INT8; + image_format_desc.image_channel_order = CL_RGBA; + if (!is_image_format_supported( context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE2D_ARRAY, &image_format_desc)) { + log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test."); + return -1; + } + + /* Verify that we can actually allocate an image that large */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof ( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE." ); + if ( (cl_ulong)maxDimension*1*4 > maxAllocSize ) { + log_error("Can not allocate a large enough image (min size: %lld bytes, max allowed: %lld bytes) to test.\n", + (cl_ulong)maxDimension*1*4, maxAllocSize); + return -1; + } + + log_info("Attempting to create an image of size 1 x 1 x %d = %gMB.\n", (int)maxDimension, ((float)maxDimension*4/1024.0/1024.0)); + + /* Try to allocate a very big image */ + streams[0] = create_image_2d_array( context, CL_MEM_READ_ONLY, &image_format_desc, 1, 1, maxDimension, 0, 0, NULL, &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "2D Image Array creation failed for maximum array size" ); + return -1; + } + + return 0; +} + +int test_min_max_image_buffer_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t maxDimensionPixels; + clMemWrapper streams[2]; + cl_image_format image_format_desc = {0}; + cl_ulong maxAllocSize; + size_t minRequiredDimension = gIsEmbedded ? 2048 : 65536; + unsigned int i = 0; + size_t pixelBytes = 0; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ); + + /* Get the max memory allocation size */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof ( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE." ); + + /* Get the max image array width */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE_MAX_BUFFER_SIZE, sizeof( maxDimensionPixels ), &maxDimensionPixels, NULL ); + test_error( error, "Unable to get max image buffer size from device" ); + + if( maxDimensionPixels < minRequiredDimension ) + { + log_error( "ERROR: Reported max image buffer size is less than required! (%d)\n", (int)maxDimensionPixels ); + return -1; + } + log_info("Max reported image buffer size is %ld pixels.\n", maxDimensionPixels); + + pixelBytes = maxAllocSize / maxDimensionPixels; + if ( pixelBytes == 0 ) + { + log_error( "Value of CL_DEVICE_IMAGE_MAX_BUFFER_SIZE is greater than CL_MAX_MEM_ALLOC_SIZE so there is no way to allocate image of maximum size!\n" ); + return -1; + } + + error = -1; + for ( i = pixelBytes; i > 0; --i ) + { + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE1D, CL_MEM_READ_ONLY, i, &image_format_desc ); + if ( error == CL_SUCCESS ) + { + pixelBytes = i; + break; + } + } + test_error( error, "Device does not support format to be used to allocate image of CL_DEVICE_IMAGE_MAX_BUFFER_SIZE\n" ); + + log_info("Attempting to create an 1D image with channel order %s from buffer of size %d = %gMB.\n", + GetChannelOrderName( image_format_desc.image_channel_order ), (int)maxDimensionPixels, ((float)maxDimensionPixels*pixelBytes/1024.0/1024.0)); + + /* Try to allocate a buffer */ + streams[0] = clCreateBuffer( context, CL_MEM_READ_ONLY, maxDimensionPixels*pixelBytes, NULL, &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "Buffer creation failed for maximum image buffer size" ); + return -1; + } + + /* Try to allocate a 1D image array from buffer */ + streams[1] = create_image_1d( context, CL_MEM_READ_ONLY, &image_format_desc, maxDimensionPixels, 0, NULL, streams[0], &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "1D Image from buffer creation failed for maximum image buffer size" ); + return -1; + } + + return 0; +} + + + +int test_min_max_parameter_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error, retVal, i; + size_t maxSize; + char *programSrc; + char *ptr; + size_t numberExpected; + long numberOfIntParametersToTry; + char *argumentLine, *codeLines; + void *data; + cl_long long_result, expectedResult; + cl_int int_result; + size_t decrement; + cl_event event; + cl_int event_status; + + + /* Get the max param size */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof( maxSize ), &maxSize, NULL ); + test_error( error, "Unable to get max parameter size from device" ); + + + if( ((!gIsEmbedded) && (maxSize < 1024)) || ((gIsEmbedded) && (maxSize < 256)) ) + { + log_error( "ERROR: Reported max parameter size is less than required! (%d)\n", (int)maxSize ); + return -1; + } + + /* The embedded profile does not require longs, so use ints */ + if(gIsEmbedded) + numberOfIntParametersToTry = numberExpected = (maxSize-sizeof(cl_mem))/sizeof(cl_int); + else + numberOfIntParametersToTry = numberExpected = (maxSize-sizeof(cl_mem))/sizeof(cl_long); + + decrement = (size_t)(numberOfIntParametersToTry/8); + if (decrement < 1) + decrement = 1; + log_info("Reported max parameter size of %d bytes.\n", (int)maxSize); + + while (numberOfIntParametersToTry > 0) { + // These need to be inside to be deallocated automatically on each loop iteration. + clProgramWrapper program; + clMemWrapper mem; + clKernelWrapper kernel; + + if(gIsEmbedded) + { + log_info("Trying a kernel with %ld int arguments (%ld bytes) and one cl_mem (%ld bytes) for %ld bytes total.\n", + numberOfIntParametersToTry, sizeof(cl_int)*numberOfIntParametersToTry, sizeof(cl_mem), + sizeof(cl_mem)+numberOfIntParametersToTry*sizeof(cl_int)); + } + else + { + log_info("Trying a kernel with %ld long arguments (%ld bytes) and one cl_mem (%ld bytes) for %ld bytes total.\n", + numberOfIntParametersToTry, sizeof(cl_long)*numberOfIntParametersToTry, sizeof(cl_mem), + sizeof(cl_mem)+numberOfIntParametersToTry*sizeof(cl_long)); + } + + // Allocate memory for the program storage + data = malloc(sizeof(cl_long)*numberOfIntParametersToTry); + + argumentLine = (char*)malloc(sizeof(char)*numberOfIntParametersToTry*32); + codeLines = (char*)malloc(sizeof(char)*numberOfIntParametersToTry*32); + programSrc = (char*)malloc(sizeof(char)*(numberOfIntParametersToTry*64+1024)); + argumentLine[0] = '\0'; + codeLines[0] = '\0'; + programSrc[0] = '\0'; + + // Generate our results + expectedResult = 0; + for (i=0; i<(int)numberOfIntParametersToTry; i++) + { + if( gHasLong ) + { + ((cl_long *)data)[i] = i; + expectedResult += i; + } + else + { + ((cl_int *)data)[i] = i; + expectedResult += i; + } + } + + // Build the program + if( gHasLong) + sprintf(argumentLine, "%s", "long arg0"); + else + sprintf(argumentLine, "%s", "int arg0"); + + sprintf(codeLines, "%s", "result[0] += arg0;"); + for (i=1; i<(int)numberOfIntParametersToTry; i++) + { + if( gHasLong) + sprintf(argumentLine + strlen( argumentLine), ", long arg%d", i); + else + sprintf(argumentLine + strlen( argumentLine), ", int arg%d", i); + + sprintf(codeLines + strlen( codeLines), "\nresult[0] += arg%d;", i); + } + + /* Create a kernel to test with */ + sprintf( programSrc, gHasLong ? sample_large_parmam_kernel_pattern[0]: + sample_large_int_parmam_kernel_pattern[0], argumentLine, codeLines); + + ptr = programSrc; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&ptr, "sample_test" ) != 0 ) + { + log_info("Create program failed, decrementing number of parameters to try.\n"); + numberOfIntParametersToTry -= decrement; + continue; + } + + /* Try to set a large argument to the kernel */ + retVal = 0; + + mem = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_long), NULL, &error); + test_error(error, "clCreateBuffer failed"); + + for (i=0; i<(int)numberOfIntParametersToTry; i++) { + if(gHasLong) + error = clSetKernelArg(kernel, i, sizeof(cl_long), &(((cl_long*)data)[i])); + else + error = clSetKernelArg(kernel, i, sizeof(cl_int), &(((cl_int*)data)[i])); + + if (error != CL_SUCCESS) { + log_info( "clSetKernelArg failed (%s), decrementing number of parameters to try.\n", IGetErrorString(error)); + numberOfIntParametersToTry -= decrement; + break; + } + } + if (error != CL_SUCCESS) + continue; + + + error = clSetKernelArg(kernel, i, sizeof(cl_mem), &mem); + if (error != CL_SUCCESS) { + log_info( "clSetKernelArg failed (%s), decrementing number of parameters to try.\n", IGetErrorString(error)); + numberOfIntParametersToTry -= decrement; + continue; + } + + size_t globalDim[3]={1,1,1}, localDim[3]={1,1,1}; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, globalDim, localDim, 0, NULL, &event); + if (error != CL_SUCCESS) { + log_info( "clEnqueueNDRangeKernel failed (%s), decrementing number of parameters to try.\n", IGetErrorString(error)); + numberOfIntParametersToTry -= decrement; + continue; + } + + // Verify that the event does not return an error from the execution + error = clWaitForEvents(1, &event); + test_error( error, "clWaitForEvent failed"); + error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL); + test_error( error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed"); + clReleaseEvent(event); + if (event_status < 0) + test_error(error, "Kernel execution event returned error"); + + if(gHasLong) + error = clEnqueueReadBuffer(queue, mem, CL_TRUE, 0, sizeof(cl_long), &long_result, 0, NULL, NULL); + else + error = clEnqueueReadBuffer(queue, mem, CL_TRUE, 0, sizeof(cl_int), &int_result, 0, NULL, NULL); + + test_error(error, "clEnqueueReadBuffer failed") + + free(data); + free(argumentLine); + free(codeLines); + free(programSrc); + + if(gHasLong) + { + if (long_result != expectedResult) { + log_error("Expected result (%lld) does not equal actual result (%lld).\n", expectedResult, long_result); + numberOfIntParametersToTry -= decrement; + continue; + } else { + log_info("Results verified at %ld bytes of arguments.\n", sizeof(cl_mem)+numberOfIntParametersToTry*sizeof(cl_long)); + break; + } + } + else + { + if (int_result != expectedResult) { + log_error("Expected result (%lld) does not equal actual result (%d).\n", expectedResult, int_result); + numberOfIntParametersToTry -= decrement; + continue; + } else { + log_info("Results verified at %ld bytes of arguments.\n", sizeof(cl_mem)+numberOfIntParametersToTry*sizeof(cl_int)); + break; + } + } + } + + if (numberOfIntParametersToTry == (long)numberExpected) + return 0; + return -1; +} + +int test_min_max_samplers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_uint maxSamplers, i; + clProgramWrapper program; + clKernelWrapper kernel; + char *programSrc, samplerLine[1024]; + size_t maxParameterSize; + cl_event event; + cl_int event_status; + cl_uint minRequiredSamplers = gIsEmbedded ? 8 : 16; + + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ) + + /* Get the max value */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_SAMPLERS, sizeof( maxSamplers ), &maxSamplers, NULL ); + test_error( error, "Unable to get max sampler count from device" ); + + if( maxSamplers < minRequiredSamplers ) + { + log_error( "ERROR: Reported max sampler count is less than required! (%d)\n", (int)maxSamplers ); + return -1; + } + + log_info("Reported max %d samplers.\n", maxSamplers); + + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof( maxParameterSize ), &maxParameterSize, NULL ); + test_error( error, "Unable to get max parameter size from device" ); + + // Subtract the size of the result + maxParameterSize -= 2*sizeof(cl_mem); + + // Calculate the number we can use + if (maxParameterSize/sizeof(cl_sampler) < maxSamplers) { + log_info("WARNING: Max parameter size of %d bytes limits test to %d max sampler arguments.\n", (int)maxParameterSize, (int)(maxParameterSize/sizeof(cl_sampler))); + maxSamplers = (unsigned int)(maxParameterSize/sizeof(cl_sampler)); + } + + /* Create a kernel to test with */ + programSrc = (char *)malloc( ( strlen( sample_sampler_kernel_pattern[ 1 ] ) + 8 ) * ( maxSamplers ) + + strlen( sample_sampler_kernel_pattern[ 0 ] ) + strlen( sample_sampler_kernel_pattern[ 2 ] ) + + ( strlen( sample_sampler_kernel_pattern[ 3 ] ) + 8 ) * maxSamplers + + strlen( sample_sampler_kernel_pattern[ 4 ] ) ); + strcpy( programSrc, sample_sampler_kernel_pattern[ 0 ] ); + for( i = 0; i < maxSamplers; i++ ) + { + sprintf( samplerLine, sample_sampler_kernel_pattern[ 1 ], i ); + strcat( programSrc, samplerLine ); + } + strcat( programSrc, sample_sampler_kernel_pattern[ 2 ] ); + for( i = 0; i < maxSamplers; i++ ) + { + sprintf( samplerLine, sample_sampler_kernel_pattern[ 3 ], i ); + strcat( programSrc, samplerLine ); + } + strcat( programSrc, sample_sampler_kernel_pattern[ 4 ] ); + + + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&programSrc, "sample_test"); + test_error( error, "Failed to create the program and kernel."); + + // We have to set up some fake parameters so it'll work + clSamplerWrapper *samplers = new clSamplerWrapper[maxSamplers]; + + cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 }; + + clMemWrapper image = create_image_2d( context, CL_MEM_READ_WRITE, &format, 16, 16, 0, NULL, &error ); + test_error( error, "Unable to create a test image" ); + + clMemWrapper stream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), 16, NULL, &error ); + test_error( error, "Unable to create test buffer" ); + + error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &image ); + error |= clSetKernelArg( kernel, 1, sizeof( cl_mem ), &stream ); + test_error( error, "Unable to set kernel arguments" ); + for( i = 0; i < maxSamplers; i++ ) + { + samplers[ i ] = clCreateSampler( context, CL_FALSE, CL_ADDRESS_NONE, CL_FILTER_NEAREST, &error ); + test_error( error, "Unable to create sampler" ); + + error = clSetKernelArg( kernel, 2 + i, sizeof( cl_sampler ), &samplers[ i ] ); + test_error( error, "Unable to set sampler argument" ); + } + + size_t globalDim[3]={1,1,1}, localDim[3]={1,1,1}; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, globalDim, localDim, 0, NULL, &event); + test_error(error, "clEnqueueNDRangeKernel failed with maximum number of samplers."); + + // Verify that the event does not return an error from the execution + error = clWaitForEvents(1, &event); + test_error( error, "clWaitForEvent failed"); + error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL); + test_error( error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed"); + clReleaseEvent(event); + if (event_status < 0) + test_error(error, "Kernel execution event returned error"); + + free( programSrc ); + delete[] samplers; + return 0; +} + +#define PASSING_FRACTION 4 +int test_min_max_constant_buffer_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[3]; + size_t threads[1], localThreads[1]; + cl_int *constantData, *resultData; + cl_ulong maxSize, stepSize, currentSize; + int i; + cl_event event; + cl_int event_status; + MTdata d; + + /* Verify our test buffer won't be bigger than allowed */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof( maxSize ), &maxSize, 0 ); + test_error( error, "Unable to get max constant buffer size" ); + + if( ( 0 == gIsEmbedded && maxSize < 64L * 1024L ) || maxSize < 1L * 1024L ) + { + log_error( "ERROR: Reported max constant buffer size less than required by OpenCL 1.0 (reported %d KB)\n", (int)( maxSize / 1024L ) ); + return -1; + } + + log_info("Reported max constant buffer size of %lld bytes.\n", maxSize); + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_const_arg_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Try the returned max size and decrease it until we get one that works. */ + stepSize = maxSize/16; + currentSize = maxSize; + int allocPassed = 0; + d = init_genrand( gRandomSeed ); + while (!allocPassed && currentSize >= maxSize/PASSING_FRACTION) { + log_info("Attempting to allocate constant buffer of size %lld bytes\n", maxSize); + + /* Create some I/O streams */ + size_t sizeToAllocate = ((size_t)currentSize/sizeof( cl_int ))*sizeof(cl_int); + size_t numberOfInts = sizeToAllocate/sizeof(cl_int); + constantData = (cl_int *)malloc( sizeToAllocate); + for(i=0; i<(int)(numberOfInts); i++) + constantData[i] = (int)genrand_int32(d); + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeToAllocate, constantData, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeToAllocate, NULL, &error); + test_error( error, "Creating test array failed" ); + + + /* Set the arguments */ + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + + + /* Test running the kernel and verifying it */ + threads[0] = numberOfInts; + localThreads[0] = 1; + log_info("Filling constant buffer with %d cl_ints (%d bytes).\n", (int)threads[0], (int)(threads[0]*sizeof(cl_int))); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, &event ); + /* If we failed due to a resource issue, reduce the size and try again. */ + if ((error == CL_OUT_OF_RESOURCES) || (error == CL_MEM_OBJECT_ALLOCATION_FAILURE) || (error == CL_OUT_OF_HOST_MEMORY)) { + log_info("Kernel enqueue failed at size %lld, trying at a reduced size.\n", currentSize); + currentSize -= stepSize; + free(constantData); + continue; + } + test_error( error, "clEnqueueNDRangeKernel with maximum constant buffer size failed."); + + // Verify that the event does not return an error from the execution + error = clWaitForEvents(1, &event); + test_error( error, "clWaitForEvent failed"); + error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL); + test_error( error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed"); + clReleaseEvent(event); + if (event_status < 0) { + if ((event_status == CL_OUT_OF_RESOURCES) || (event_status == CL_MEM_OBJECT_ALLOCATION_FAILURE) || (event_status == CL_OUT_OF_HOST_MEMORY)) { + log_info("Kernel event indicates failure at size %lld, trying at a reduced size.\n", currentSize); + currentSize -= stepSize; + free(constantData); + continue; + } else { + test_error(error, "Kernel execution event returned error"); + } + } + + /* Otherwise we did not fail due to resource issues. */ + allocPassed = 1; + + resultData = (cl_int *)malloc(sizeToAllocate); + error = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, sizeToAllocate, resultData, 0, NULL, NULL); + test_error( error, "clEnqueueReadBuffer failed"); + + for(i=0; i<(int)(numberOfInts); i++) + if (constantData[i] != resultData[i]) { + log_error("Data failed to verify: constantData[%d]=%d != resultData[%d]=%d\n", + i, constantData[i], i, resultData[i]); + free( constantData ); + free(resultData); + free_mtdata(d); d = NULL; + return -1; + } + + free( constantData ); + free(resultData); + } + free_mtdata(d); d = NULL; + + if (allocPassed) { + if (currentSize < maxSize/PASSING_FRACTION) { + log_error("Failed to allocate at least 1/4 of the reported constant size.\n"); + return -1; + } else if (currentSize != maxSize) { + log_info("Passed at reduced size. (%lld of %lld bytes)\n", currentSize, maxSize); + return 0; + } + return 0; + } + return -1; +} + +int test_min_max_constant_args(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper *streams; + size_t threads[1], localThreads[1]; + cl_uint i, maxArgs; + cl_ulong maxSize; + cl_ulong maxParameterSize; + size_t individualBufferSize; + char *programSrc, *constArgs, *str2; + char str[512]; + const char *ptr; + cl_event event; + cl_int event_status; + + + /* Verify our test buffer won't be bigger than allowed */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_CONSTANT_ARGS, sizeof( maxArgs ), &maxArgs, 0 ); + test_error( error, "Unable to get max constant arg count" ); + + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof( maxParameterSize ), &maxParameterSize, NULL ); + test_error( error, "Unable to get max parameter size from device" ); + + // Subtract the size of the result + maxParameterSize -= sizeof(cl_mem); + + // Calculate the number we can use + if (maxParameterSize/sizeof(cl_mem) < maxArgs) { + log_info("WARNING: Max parameter size of %d bytes limits test to %d max image arguments.\n", (int)maxParameterSize, (int)(maxParameterSize/sizeof(cl_mem))); + maxArgs = (unsigned int)(maxParameterSize/sizeof(cl_mem)); + } + + + if( maxArgs < (gIsEmbedded ? 4 : 8) ) + { + log_error( "ERROR: Reported max constant arg count less than required by OpenCL 1.0 (reported %d)\n", (int)maxArgs ); + return -1; + } + + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof( maxSize ), &maxSize, 0 ); + test_error( error, "Unable to get max constant buffer size" ); + individualBufferSize = ((int)maxSize/2)/maxArgs; + + log_info("Reported max constant arg count of %d and max constant buffer size of %d. Test will attempt to allocate half of that, or %d buffers of size %d.\n", + (int)maxArgs, (int)maxSize, (int)maxArgs, (int)individualBufferSize); + + str2 = (char*)malloc(sizeof(char)*32*(maxArgs+2)); + constArgs = (char*)malloc(sizeof(char)*32*(maxArgs+2)); + programSrc = (char*)malloc(sizeof(char)*32*2*(maxArgs+2)+1024); + + /* Create a test program */ + constArgs[0] = 0; + str2[0] = 0; + for( i = 0; i < maxArgs-1; i++ ) + { + sprintf( str, ", __constant int *src%d", (int)( i + 2 ) ); + strcat( constArgs, str ); + sprintf( str2 + strlen( str2), "\tdst[tid] += src%d[tid];\n", (int)(i+2)); + if (strlen(str2) > (sizeof(char)*32*(maxArgs+2)-32) || strlen(constArgs) > (sizeof(char)*32*(maxArgs+2)-32)) { + log_info("Limiting number of arguments tested to %d due to test program allocation size.\n", i); + break; + } + } + sprintf( programSrc, sample_const_max_arg_kernel_pattern, constArgs, str2 ); + + /* Create a kernel to test with */ + ptr = programSrc; + if( create_single_kernel_helper( context, &program, &kernel, 1, &ptr, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + streams = new clMemWrapper[ maxArgs + 1 ]; + for( i = 0; i < maxArgs + 1; i++ ) + { + streams[i] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), individualBufferSize, NULL, &error); + test_error( error, "Creating test array failed" ); + } + + /* Set the arguments */ + for( i = 0; i < maxArgs + 1; i++ ) + { + error = clSetKernelArg(kernel, i, sizeof( streams[i] ), &streams[i]); + test_error( error, "Unable to set kernel argument" ); + } + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)10; + while (threads[0]*sizeof(cl_int) > individualBufferSize) + threads[0]--; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, &event ); + test_error( error, "clEnqueueNDRangeKernel failed"); + + // Verify that the event does not return an error from the execution + error = clWaitForEvents(1, &event); + test_error( error, "clWaitForEvent failed"); + error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL); + test_error( error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed"); + clReleaseEvent(event); + if (event_status < 0) + test_error(error, "Kernel execution event returned error"); + + error = clFinish(queue); + test_error( error, "clFinish failed."); + + delete [] streams; + free(str2); + free(constArgs); + free(programSrc); + return 0; +} + +int test_min_max_compute_units(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_uint value; + + + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof( value ), &value, 0 ); + test_error( error, "Unable to get compute unit count" ); + + if( value < 1 ) + { + log_error( "ERROR: Reported compute unit count less than required by OpenCL 1.0 (reported %d)\n", (int)value ); + return -1; + } + + log_info("Reported %d max compute units.\n", value); + + return 0; +} + +int test_min_max_address_bits(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_uint value; + + + error = clGetDeviceInfo( deviceID, CL_DEVICE_ADDRESS_BITS, sizeof( value ), &value, 0 ); + test_error( error, "Unable to get address bit count" ); + + if( value != 32 && value != 64 ) + { + log_error( "ERROR: Reported address bit count not valid by OpenCL 1.0 (reported %d)\n", (int)value ); + return -1; + } + + log_info("Reported %d device address bits.\n", value); + + return 0; +} + +int test_min_max_single_fp_config(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_device_fp_config value; + char profile[128] = ""; + + error = clGetDeviceInfo( deviceID, CL_DEVICE_SINGLE_FP_CONFIG, sizeof( value ), &value, 0 ); + test_error( error, "Unable to get device single fp config" ); + + //Check to see if we are an embedded profile device + if((error = clGetDeviceInfo( deviceID, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL ))) + { + log_error( "FAILURE: Unable to get CL_DEVICE_PROFILE: error %d\n", error ); + return error; + } + + if( 0 == strcmp( profile, "EMBEDDED_PROFILE" )) + { // embedded device + + if( 0 == (value & (CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO))) + { + log_error( "FAILURE: embedded device supports neither CL_FP_ROUND_TO_NEAREST or CL_FP_ROUND_TO_ZERO\n" ); + return -1; + } + } + else + { // Full profile + if( ( value & ( CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN )) != ( CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN ) ) + { + log_error( "ERROR: Reported single fp config doesn't meet minimum set by OpenCL 1.0 (reported 0x%08x)\n", (int)value ); + return -1; + } + } + return 0; +} + +int test_min_max_double_fp_config(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_device_fp_config value; + + error = clGetDeviceInfo( deviceID, CL_DEVICE_DOUBLE_FP_CONFIG, sizeof( value ), &value, 0 ); + test_error( error, "Unable to get device double fp config" ); + + if (value == 0) + return 0; + + if( ( value & (CL_FP_FMA | CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO | CL_FP_ROUND_TO_INF | CL_FP_INF_NAN | CL_FP_DENORM)) != ( CL_FP_FMA | CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO | CL_FP_ROUND_TO_INF | CL_FP_INF_NAN | CL_FP_DENORM) ) + { + log_error( "ERROR: Reported double fp config doesn't meet minimum set by OpenCL 1.0 (reported 0x%08x)\n", (int)value ); + return -1; + } + return 0; +} + +int test_min_max_local_mem_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[3]; + size_t threads[1], localThreads[1]; + cl_int *localData, *resultData; + cl_ulong maxSize, kernelLocalUsage, min_max_local_mem_size; + cl_char buffer[ 4098 ]; + size_t length; + int i; + int err = 0; + MTdata d; + + /* Verify our test buffer won't be bigger than allowed */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_LOCAL_MEM_SIZE, sizeof( maxSize ), &maxSize, 0 ); + test_error( error, "Unable to get max local buffer size" ); + + // Device version should fit the regex "OpenCL [0-9]+\.[0-9]+ *.*" + error = clGetDeviceInfo( deviceID, CL_DEVICE_VERSION, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get device version string" ); + if (!gIsEmbedded) + { + if( memcmp( buffer, "OpenCL 2.0", strlen( "OpenCL 2.0" ) ) == 0 ) + min_max_local_mem_size = 16L * 1024L; + else if( memcmp( buffer, "OpenCL 2.1", strlen( "OpenCL 2.1" ) ) != 0 ) + min_max_local_mem_size = 16L * 1024L; + else if( memcmp( buffer, "OpenCL 1.2", strlen( "OpenCL 1.2" ) ) != 0 ) + min_max_local_mem_size = 16L * 1024L; + else if( memcmp( buffer, "OpenCL 1.1", strlen( "OpenCL 1.1" ) ) != 0 ) + min_max_local_mem_size = 16L * 1024L; + else if ( memcmp( buffer, "OpenCL 1.0", strlen( "OpenCL 1.0" ) ) != 0 ) + min_max_local_mem_size = 32L * 1024L; + else + { + log_error( "ERROR: device version string does not match required format! (returned: %s)\n", (char *)buffer ); + return -1; + } + } + + if( maxSize < (gIsEmbedded ? 1L * 1024L : min_max_local_mem_size) ) + { + log_error( "ERROR: Reported local mem size less than required by OpenCL 1.1 (reported %dKb)\n", (int)( maxSize / 1024L ) ); + return -1; + } + + log_info("Reported max local buffer size for device: %lld bytes.\n", maxSize); + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_local_arg_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + error = clGetKernelWorkGroupInfo(kernel, deviceID, CL_KERNEL_LOCAL_MEM_SIZE, sizeof(kernelLocalUsage), &kernelLocalUsage, NULL); + test_error(error, "clGetKernelWorkGroupInfo for CL_KERNEL_LOCAL_MEM_SIZE failed"); + + log_info("Reported local buffer usage for kernel (CL_KERNEL_LOCAL_MEM_SIZE): %lld bytes.\n", kernelLocalUsage); + + /* Create some I/O streams */ + size_t sizeToAllocate = ((size_t)(maxSize-kernelLocalUsage)/sizeof( cl_int ))*sizeof(cl_int); + size_t numberOfInts = sizeToAllocate/sizeof(cl_int); + + log_info("Attempting to use %lld bytes of local memory.\n", (cl_ulong)sizeToAllocate); + + localData = (cl_int *)malloc( sizeToAllocate ); + d = init_genrand( gRandomSeed ); + for(i=0; i<(int)(numberOfInts); i++) + localData[i] = (int)genrand_int32(d); + free_mtdata(d); d = NULL; + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeToAllocate, localData, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeToAllocate, NULL, &error); + test_error( error, "Creating test array failed" ); + + + /* Set the arguments */ + error = clSetKernelArg(kernel, 0, sizeToAllocate, NULL); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 2, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + + + /* Test running the kernel and verifying it */ + threads[0] = numberOfInts; + localThreads[0] = 1; + log_info("Creating local buffer with %d cl_ints (%d bytes).\n", (int)numberOfInts, (int)sizeToAllocate); + + cl_event evt; + cl_int evt_err; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, &evt ); + test_error(error, "clEnqueueNDRangeKernel failed"); + + error = clFinish(queue); + test_error( error, "clFinish failed"); + + error = clGetEventInfo(evt, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof evt_err, &evt_err, NULL); + test_error( error, "clGetEventInfo with maximum local buffer size failed."); + + if (evt_err != CL_COMPLETE) { + print_error(evt_err, "Kernel event returned error"); + clReleaseEvent(evt); + return -1; + } + + resultData = (cl_int *)malloc(sizeToAllocate); + + error = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, sizeToAllocate, resultData, 0, NULL, NULL); + test_error( error, "clEnqueueReadBuffer failed"); + + for(i=0; i<(int)(numberOfInts); i++) + if (localData[i] != resultData[i]) { + clReleaseEvent(evt); + free( localData ); + free(resultData); + log_error("Results failed to verify.\n"); + return -1; + } + clReleaseEvent(evt); + free( localData ); + free(resultData); + + return err; +} + +int test_min_max_kernel_preferred_work_group_size_multiple(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int err; + clProgramWrapper program; + clKernelWrapper kernel; + + size_t max_local_workgroup_size[3]; + size_t max_workgroup_size = 0, preferred_workgroup_size = 0; + + err = create_single_kernel_helper(context, &program, &kernel, 1, sample_local_arg_kernel, "sample_test" ); + test_error(err, "Failed to build kernel/program."); + + err = clGetKernelWorkGroupInfo(kernel, deviceID, CL_KERNEL_WORK_GROUP_SIZE, + sizeof(max_workgroup_size), &max_workgroup_size, NULL); + test_error(err, "clGetKernelWorkgroupInfo failed."); + + err = clGetKernelWorkGroupInfo(kernel, deviceID, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, + sizeof(preferred_workgroup_size), &preferred_workgroup_size, NULL); + test_error(err, "clGetKernelWorkgroupInfo failed."); + + err = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(max_local_workgroup_size), max_local_workgroup_size, NULL); + test_error(err, "clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_SIZES"); + + // Since the preferred size is only a performance hint, we can only really check that we get a sane value + // back + log_info( "size: %ld preferred: %ld max: %ld\n", max_workgroup_size, preferred_workgroup_size, max_local_workgroup_size[0] ); + + if( preferred_workgroup_size > max_workgroup_size ) + { + log_error( "ERROR: Reported preferred workgroup multiple larger than max workgroup size (preferred %ld, max %ld)\n", preferred_workgroup_size, max_workgroup_size ); + return -1; + } + + return 0; +} + +int test_min_max_execution_capabilities(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_device_exec_capabilities value; + + + error = clGetDeviceInfo( deviceID, CL_DEVICE_EXECUTION_CAPABILITIES, sizeof( value ), &value, 0 ); + test_error( error, "Unable to get execution capabilities" ); + + if( ( value & CL_EXEC_KERNEL ) != CL_EXEC_KERNEL ) + { + log_error( "ERROR: Reported execution capabilities less than required by OpenCL 1.0 (reported 0x%08x)\n", (int)value ); + return -1; + } + return 0; +} + +int test_min_max_queue_properties(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_command_queue_properties value; + + + error = clGetDeviceInfo( deviceID, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES, sizeof( value ), &value, 0 ); + test_error( error, "Unable to get queue properties" ); + + if( ( value & CL_QUEUE_PROFILING_ENABLE ) != CL_QUEUE_PROFILING_ENABLE ) + { + log_error( "ERROR: Reported queue properties less than required by OpenCL 1.0 (reported 0x%08x)\n", (int)value ); + return -1; + } + return 0; +} + +int test_min_max_device_version(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int error, i; + cl_char buffer[ 4098 ]; + size_t length; + + + // Device version should fit the regex "OpenCL [0-9]+\.[0-9]+ *.*" + error = clGetDeviceInfo( deviceID, CL_DEVICE_VERSION, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get device version string" ); + if( memcmp( buffer, "OpenCL ", strlen( "OpenCL " ) ) != 0 ) + { + log_error( "ERROR: Initial part of device version string does not match required format! (returned: %s)\n", (char *)buffer ); + return -1; + } + + log_info("Returned version %s.\n", buffer); + + char *p1 = (char *)buffer + strlen( "OpenCL " ); + while( *p1 == ' ' ) + p1++; + char *p2 = p1; + if( ! isdigit(*p2) ) + { + log_error( "ERROR: Major revision number must follow space behind OpenCL! (returned %s)\n", (char*) buffer ); + return -1; + } + while( isdigit( *p2 ) ) + p2++; + if( *p2 != '.' ) + { + log_error( "ERROR: Version number must contain a decimal point! (returned: %s)\n", (char *)buffer ); + return -1; + } + char *p3 = p2 + 1; + if( ! isdigit(*p3) ) + { + log_error( "ERROR: Minor revision number is missing or does not abut the decimal point! (returned %s)\n", (char*) buffer ); + return -1; + } + while( isdigit( *p3 ) ) + p3++; + if( *p3 != ' ' ) + { + log_error( "ERROR: A space must appear after the minor version! (returned: %s)\n", (char *)buffer ); + return -1; + } + *p2 = ' '; // Put in a space for atoi below. + p2++; + + int major = atoi( p1 ); + int minor = atoi( p2 ); + int minor_revision = 2; + if( getenv("OPENCL_1_0_DEVICE")) + { + minor_revision = 0; + log_info( "WARNING: This test was run with OPENCL_1_0_DEVICE defined! This is not a OpenCL 1.1 or OpenCL 1.2 compatible device!!!\n" ); + } + else if( getenv("OPENCL_1_1_DEVICE")) + { + minor_revision = 1; + log_info( "WARNING: This test was run with OPENCL_1_1_DEVICE defined! This is not a OpenCL 1.2 compatible device!!!\n" ); + } + if( major * 10 + minor < 10 + minor_revision ) + { + log_error( "ERROR: OpenCL device version returned is less than 1.%d! (Returned: %s)\n", minor_revision, (char *)buffer ); + return -1; + } + + // Sanity checks on the returned values + if( length != (strlen( (char *)buffer ) + 1 )) + { + log_error( "ERROR: Returned length of version string does not match actual length (actual: %d, returned: %d)\n", (int)strlen( (char *)buffer ), (int)length ); + return -1; + } + + // Make sure 2.0 devices support required extensions for 2.0 + const char *requiredExtensions20[] = + { + "cl_khr_byte_addressable_store", + "cl_khr_3d_image_writes", + "cl_khr_image2d_from_buffer", + "cl_khr_depth_images", + "cl_khr_fp64", + }; + + // Make sure 1.1 devices support required extensions for 1.1 + const char *requiredExtensions[] = + { + "cl_khr_global_int32_base_atomics", + "cl_khr_global_int32_extended_atomics", + "cl_khr_local_int32_base_atomics", + "cl_khr_local_int32_extended_atomics", + "cl_khr_byte_addressable_store", + NULL + }; + + if( major * 10 + minor >= 11 ) + { + char *extensions; + size_t extensions_size = 0; + + log_info( "Checking for required extensions for OpenCL 1.1 and later devices...\n" ); + + if( (error = clGetDeviceInfo(deviceID, CL_DEVICE_EXTENSIONS, 0, NULL, &extensions_size))) + { + log_error( "ERROR: could not get extensions size. Err # %d\n", error ); + return -1; + } + + if( extensions_size < 1 ) + { + log_error( "ERROR: invalid extensions size. Err # %d\n", error ); + return -1; + } + + extensions = (char*) malloc(extensions_size); + if( NULL == extensions ) + { + log_error( "ERROR: cannot allocate %ld bytes to hold extension string.\n", extensions_size ); + return -1; + } + memset( extensions, -1, extensions_size ); + + if( (error = clGetDeviceInfo(deviceID, CL_DEVICE_EXTENSIONS, extensions_size, extensions, NULL))) + { + log_error( "ERROR: could not get extensions. Err # %d\n", error ); + free( extensions ); + return -1; + } + + if( '\0' != extensions[ extensions_size - 1 ] ) + { + if( -1 == extensions[ extensions_size - 1 ] ) + log_error( "ERROR: extensions size reported incorrectly. Last byte is not NUL. Size too big. Reported: %ld. Should be: %ld\n", extensions_size, strlen(extensions) + 1 ); + else + log_error( "ERROR: extensions size reported incorrectly. Last byte is not NUL. Size too small. \n" ); + + free( extensions ); + return -1; + } + + for( i = 0; NULL != requiredExtensions[i]; i++ ) + { + if( NULL == strstr( extensions, requiredExtensions[i] ) ) + { + log_error( "ERROR: Required extension for 1.1 and greater devices is not in extension string: %s\n", requiredExtensions[i] ); + free( extensions ); + return -1; + } + else + log_info( "\t%s\n", requiredExtensions[i] ); + } + + if( major >= 2 ) + { + log_info( "Checking for required extensions for OpenCL 2.0 and later devices...\n" ); + + // Check if double precision is supported, if it is, then check the extension "cl_khr_fp64" + cl_device_fp_config value; + int numRequiredExtension20 = sizeof(requiredExtensions20)/sizeof(char *); + + error = clGetDeviceInfo( deviceID, CL_DEVICE_DOUBLE_FP_CONFIG, sizeof( value ), &value, 0 ); + test_error( error, "Unable to get device double fp config" ); + + // if double precision is not supported, then don't check extension "cl_khr_fp64" + numRequiredExtension20 -= (value == 0); + + for( i = 0; i -0.5f);\n" + " if(myBool)\n" + " {\n" + " dst[tid] = (int)src[tid];\n" + " }\n" + " else\n" + " {\n" + " dst[tid] = 0;\n" + " }\n" + "\n" + "}\n" +}; + +int test_for_bool_type(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements) +{ + + cl_program program; + cl_kernel kernel; + + int err = create_single_kernel_helper(context, + &program, + &kernel, + 1, kernel_with_bool, + "kernel_with_bool" ); + return err; +} + diff --git a/test_conformance/api/test_clone_kernel.cpp b/test_conformance/api/test_clone_kernel.cpp new file mode 100644 index 00000000..5826d7dc --- /dev/null +++ b/test_conformance/api/test_clone_kernel.cpp @@ -0,0 +1,411 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" +#include +#include +#include + +using namespace std; + +const char *clone_kernel_test_img[] = +{ + "__kernel void img_read_kernel(read_only image2d_t img, sampler_t sampler, __global int* outbuf)\n" + "{\n" + " uint4 color;\n" + "\n" + " color = read_imageui(img, sampler, (int2)(0,0));\n" + " \n" + " // 7, 8, 9, 10th DWORD\n" + " outbuf[7] = color.x;\n" + " outbuf[8] = color.y;\n" + " outbuf[9] = color.z;\n" + " outbuf[10] = color.w;\n" + "}\n" + "\n" + "__kernel void img_write_kernel(write_only image2d_t img, uint4 color)\n" + "{\n" + " write_imageui (img, (int2)(0, 0), color);\n" + "}\n" + +}; + +const char *clone_kernel_test_double[] = +{ + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void clone_kernel_test1(double d, __global double* outbuf)\n" + "{\n" + " // use the same outbuf as rest of the tests\n" + " outbuf[2] = d;\n" + "}\n" +}; + +const char *clone_kernel_test_kernel[] = { +"typedef struct\n" +"{\n" +" int i;\n" +" float f;\n" +"} structArg;\n" +"\n" +"// value type test\n" +"__kernel void clone_kernel_test0(int iarg, float farg, structArg sarg, __local int* localbuf, __global int* outbuf)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" outbuf[0] = iarg;\n" +" outbuf[1] = sarg.i;\n" +" \n" +" ((__global float*)outbuf)[2] = farg;\n" +" ((__global float*)outbuf)[3] = sarg.f;\n" +"}\n" +"\n" +"__kernel void buf_read_kernel(__global int* buf, __global int* outbuf)\n" +"{\n" +" // 6th DWORD\n" +" outbuf[6] = buf[0];\n" +"}\n" +"\n" +"__kernel void buf_write_kernel(__global int* buf, int write_val)\n" +"{\n" +" buf[0] = write_val;\n" +"}\n" + + }; + +const int BUF_SIZE = 128; + +struct structArg +{ + int i; + float f; +}; + +static unsigned char * +generate_8888_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i 0.0000001) + { + test_error( error, "clCloneKernel test failed." ); + return -1; + } + + return 0; +} + +int test_clone_kernel(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clKernelWrapper kernel_pipe_read; + clKernelWrapper kernel_buf_read; + clKernelWrapper kernel_pipe_write; + clKernelWrapper kernel_buf_write; + + clKernelWrapper kernel_pipe_read_cloned; + clKernelWrapper kernel_buf_read_cloned; + size_t ndrange1 = 1; + + int write_val = 123; + + + cl_bool bimg = CL_FALSE; + cl_bool bdouble = CL_FALSE; + // test image support + error = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE_SUPPORT, sizeof(cl_bool), &bimg, NULL); + test_error( error, "clGetDeviceInfo failed." ); + + // test double support + size_t ext_str_size; + error = clGetDeviceInfo(deviceID, CL_DEVICE_EXTENSIONS, 0, NULL, &ext_str_size); + test_error( error, "clGetDeviceInfo failed." ); + char* ext_str = new char[ext_str_size+1]; + + error = clGetDeviceInfo(deviceID, CL_DEVICE_EXTENSIONS, ext_str_size, ext_str, NULL); + test_error( error, "clGetDeviceInfo failed." ); + + ext_str[ext_str_size] = '\0'; + + stringstream ss; + ss << ext_str; + + while (!ss.eof()) + { + string s; + ss >> s; + if (s == "cl_khr_fp64") + { + bdouble = CL_TRUE; + break; + } + } + + /* Create kernels to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, clone_kernel_test_kernel, "clone_kernel_test0" ) != 0 ) + { + return -1; + } + + if( create_single_kernel_helper( context, &program, &kernel_buf_read, 1, clone_kernel_test_kernel, "buf_read_kernel" ) != 0 ) + { + return -1; + } + + if( create_single_kernel_helper( context, &program, &kernel_buf_write, 1, clone_kernel_test_kernel, "buf_write_kernel" ) != 0 ) + { + return -1; + } + + // Kernel args + // Value type + int intarg = 0; + float farg = 1.0; + structArg sa = { 1, 1.0f }; + + // cl_mem + clMemWrapper buf, bufOut; + + char* pbuf = new char[BUF_SIZE]; + char* pbufRes = new char[BUF_SIZE]; + buf = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, BUF_SIZE, pbuf, &error); + test_error( error, "clCreateBuffer failed." ); + + bufOut = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, BUF_SIZE, NULL, &error); + test_error( error, "clCreateBuffer failed." ); + + clMemWrapper pipe = clCreatePipe(context, CL_MEM_HOST_NO_ACCESS, sizeof(int), 16, NULL, &error); + test_error( error, "clCreatePipe failed." ); + + error = clSetKernelArg(kernel, 0, sizeof(int), &intarg); + error += clSetKernelArg(kernel, 1, sizeof(float), &farg); + error += clSetKernelArg(kernel, 2, sizeof(structArg), &sa); + error += clSetKernelArg(kernel, 3, 128, NULL); // local mem + + test_error( error, "clSetKernelArg failed." ); + + // clone the kernel + clKernelWrapper clonek = clCloneKernel(kernel, &error); + test_error( error, "clCloneKernel failed." ); + + // set the last arg and enqueue + error = clSetKernelArg(clonek, 4, sizeof(cl_mem), &bufOut); + test_error( error, "clSetKernelArg failed." ); + error = clEnqueueNDRangeKernel(queue, clonek, 1, NULL, &ndrange1, NULL, 0, NULL, NULL); + test_error( error, "clEnqueueNDRangeKernel failed." ); + + // shallow clone tests for buffer, svm and pipes + error = clSetKernelArg(kernel_buf_write, 0, sizeof(cl_mem), &buf); + error += clSetKernelArg(kernel_buf_write, 1, sizeof(int), &write_val); + test_error( error, "clSetKernelArg failed." ); + error = clEnqueueNDRangeKernel(queue, kernel_buf_write, 1, NULL, &ndrange1, NULL, 0, NULL, NULL); + test_error( error, "clEnqueueNDRangeKernel failed." ); + + error = clSetKernelArg(kernel_buf_read, 0, sizeof(cl_mem), &buf); + error += clSetKernelArg(kernel_buf_read, 1, sizeof(cl_mem), &bufOut); + test_error( error, "clSetKernelArg failed." ); + + // clone the kernel + kernel_buf_read_cloned = clCloneKernel(kernel_buf_read, &error); + test_error( error, "clCloneKernel API call failed." ); + error = clEnqueueNDRangeKernel(queue, kernel_buf_read_cloned, 1, NULL, &ndrange1, NULL, 0, NULL, NULL); + test_error( error, "clEnqueueNDRangeKernel failed." ); + + // read result back + error = clEnqueueReadBuffer(queue, bufOut, CL_TRUE, 0, BUF_SIZE, pbufRes, 0, NULL, NULL); + test_error( error, "clEnqueueReadBuffer failed." ); + + // Compare the results + if (((int*)pbufRes)[0] != intarg) + { + test_error( error, "clCloneKernel test failed. Failed to clone integer type argument." ); + return -1; + } + + if (((int*)pbufRes)[1] != sa.i) + { + test_error( error, "clCloneKernel test failed. Failed to clone structure type argument." ); + return -1; + } + + if (((float*)pbufRes)[2] != farg) + { + test_error( error, "clCloneKernel test failed. Failed to clone structure type argument." ); + return -1; + } + + if (((float*)pbufRes)[3] != sa.f) + { + test_error( error, "clCloneKernel test failed. Failed to clone float type argument." ); + return -1; + } + + if (((int*)pbufRes)[6] != write_val) + { + test_error( error, "clCloneKernel test failed. Failed to clone cl_mem argument." ); + return -1; + } + + if (bimg) + { + error = test_image_arg_shallow_clone(deviceID, context, queue, num_elements, pbufRes, bufOut); + test_error( error, "image arg shallow clone test failed." ); + } + + if (bdouble) + { + error = test_double_arg_clone(deviceID, context, queue, num_elements, pbufRes, bufOut); + test_error( error, "double arg clone test failed." ); + } + + delete [] pbuf; + delete [] pbufRes; + delete [] ext_str; + + return 0; +} + diff --git a/test_conformance/api/test_create_context_from_type.cpp b/test_conformance/api/test_create_context_from_type.cpp new file mode 100644 index 00000000..4f560148 --- /dev/null +++ b/test_conformance/api/test_create_context_from_type.cpp @@ -0,0 +1,130 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/testHarness.h" + +#ifndef _WIN32 +#include +#endif + +#include "../../test_common/harness/conversions.h" + +extern cl_uint gRandomSeed; + +int test_create_context_from_type(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + clContextWrapper context_to_test; + clCommandQueueWrapper queue_to_test; + size_t threads[1], localThreads[1]; + cl_float inputData[10]; + cl_int outputData[10]; + int i; + RandomSeed seed( gRandomSeed ); + + const char *sample_single_test_kernel[] = { + "__kernel void sample_test(__global float *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (int)src[tid];\n" + "\n" + "}\n" }; + + cl_device_type type; + error = clGetDeviceInfo(deviceID, CL_DEVICE_TYPE, sizeof(type), &type, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_TYPE failed\n"); + + cl_platform_id platform; + error = clGetDeviceInfo(deviceID, CL_DEVICE_PLATFORM, sizeof(platform), &platform, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_PLATFORM failed\n"); + + cl_context_properties properties[3] = { + (cl_context_properties)CL_CONTEXT_PLATFORM, + (cl_context_properties)platform, + NULL + }; + + context_to_test = clCreateContextFromType(properties, type, notify_callback, NULL, &error); + test_error(error, "clCreateContextFromType failed"); + if (context_to_test == NULL) { + log_error("clCreateContextFromType returned NULL, but error was CL_SUCCESS."); + return -1; + } + + queue_to_test = clCreateCommandQueueWithProperties(context_to_test, deviceID, NULL, &error); + test_error(error, "clCreateCommandQueue failed"); + if (queue_to_test == NULL) { + log_error("clCreateCommandQueue returned NULL, but error was CL_SUCCESS."); + return -1; + } + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context_to_test, &program, &kernel, 1, sample_single_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + streams[0] = clCreateBuffer(context_to_test, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context_to_test, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Write some test data */ + memset( outputData, 0, sizeof( outputData ) ); + + for (i=0; i<10; i++) + inputData[i] = get_random_float(-(float) 0x7fffffff, (float) 0x7fffffff, seed); + + error = clEnqueueWriteBuffer(queue_to_test, streams[0], CL_TRUE, 0, sizeof(cl_float)*10, (void *)inputData, 0, NULL, NULL); + test_error( error, "Unable to set testing kernel data" ); + + /* Test setting the arguments by index manually */ + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)10; + + error = get_max_common_work_group_size( context_to_test, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue_to_test, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue_to_test, streams[1], CL_TRUE, 0, sizeof(cl_int)*10, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<10; i++) + { + if (outputData[i] != (int)inputData[i]) + { + log_error( "ERROR: Data did not verify on first pass!\n" ); + return -1; + } + } + + return 0; +} + + diff --git a/test_conformance/api/test_create_kernels.c b/test_conformance/api/test_create_kernels.c new file mode 100644 index 00000000..ceb18732 --- /dev/null +++ b/test_conformance/api/test_create_kernels.c @@ -0,0 +1,595 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/testHarness.h" + + +const char *sample_single_kernel[] = { + "__kernel void sample_test(__global float *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (int)src[tid];\n" + "\n" + "}\n" }; + +size_t sample_single_kernel_lengths[1]; + +const char *sample_two_kernels[] = { + "__kernel void sample_test(__global float *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (int)src[tid];\n" + "\n" + "}\n", + "__kernel void sample_test2(__global int *src, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (float)src[tid];\n" + "\n" + "}\n" }; + +size_t sample_two_kernel_lengths[2]; + +const char *sample_two_kernels_in_1[] = { + "__kernel void sample_test(__global float *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (int)src[tid];\n" + "\n" + "}\n" + "__kernel void sample_test2(__global int *src, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (float)src[tid];\n" + "\n" + "}\n" }; + +size_t sample_two_kernels_in_1_lengths[1]; + + +const char *repeate_test_kernel = +"__kernel void test_kernel(__global int *src, __global int *dst)\n" +"{\n" +" dst[get_global_id(0)] = src[get_global_id(0)]+1;\n" +"}\n"; + + + +int test_load_single_kernel(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + cl_program testProgram; + clKernelWrapper kernel; + cl_context testContext; + unsigned int numKernels; + cl_char testName[512]; + cl_uint testArgCount; + size_t realSize; + + + error = create_single_kernel_helper(context, &program, NULL, 1, sample_single_kernel, NULL); + test_error( error, "Unable to build test program" ); + + error = clCreateKernelsInProgram(program, 1, &kernel, &numKernels); + test_error( error, "Unable to create single kernel program" ); + + /* Check program and context pointers */ + error = clGetKernelInfo( kernel, CL_KERNEL_PROGRAM, sizeof( cl_program ), &testProgram, &realSize ); + test_error( error, "Unable to get kernel's program" ); + if( (cl_program)testProgram != (cl_program)program ) + { + log_error( "ERROR: Returned kernel's program does not match program used to create it! (Got %p, expected %p)\n", (cl_program)testProgram, (cl_program)program ); + return -1; + } + if( realSize != sizeof( cl_program ) ) + { + log_error( "ERROR: Returned size of kernel's program does not match expected size (expected %d, got %d)\n", (int)sizeof( cl_program ), (int)realSize ); + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_CONTEXT, sizeof( cl_context ), &testContext, &realSize ); + test_error( error, "Unable to get kernel's context" ); + if( (cl_context)testContext != (cl_context)context ) + { + log_error( "ERROR: Returned kernel's context does not match program used to create it! (Got %p, expected %p)\n", (cl_context)testContext, (cl_context)context ); + return -1; + } + if( realSize != sizeof( cl_context ) ) + { + log_error( "ERROR: Returned size of kernel's context does not match expected size (expected %d, got %d)\n", (int)sizeof( cl_context ), (int)realSize ); + return -1; + } + + /* Test arg count */ + error = clGetKernelInfo( kernel, CL_KERNEL_NUM_ARGS, 0, NULL, &realSize ); + test_error( error, "Unable to get size of arg count info from kernel" ); + + if( realSize != sizeof( testArgCount ) ) + { + log_error( "ERROR: size of arg count not valid! %d\n", (int)realSize ); + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_NUM_ARGS, sizeof( testArgCount ), &testArgCount, NULL ); + test_error( error, "Unable to get arg count from kernel" ); + + if( testArgCount != 2 ) + { + log_error( "ERROR: Kernel arg count does not match!\n" ); + return -1; + } + + + /* Test function name */ + error = clGetKernelInfo( kernel, CL_KERNEL_FUNCTION_NAME, sizeof( testName ), testName, &realSize ); + test_error( error, "Unable to get name from kernel" ); + + if( strcmp( (char *)testName, "sample_test" ) != 0 ) + { + log_error( "ERROR: Kernel names do not match!\n" ); + return -1; + } + if( realSize != strlen( (char *)testName ) + 1 ) + { + log_error( "ERROR: Length of kernel name returned does not validate (expected %d, got %d)\n", (int)strlen( (char *)testName ) + 1, (int)realSize ); + return -1; + } + + /* All done */ + + return 0; +} + +int test_load_two_kernels(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel[2]; + unsigned int numKernels; + cl_char testName[ 512 ]; + cl_uint testArgCount; + + + error = create_single_kernel_helper(context, &program, NULL, 2, sample_two_kernels, NULL); + test_error( error, "Unable to build test program" ); + + error = clCreateKernelsInProgram(program, 2, &kernel[0], &numKernels); + test_error( error, "Unable to create dual kernel program" ); + + if( numKernels != 2 ) + { + log_error( "ERROR: wrong # of kernels! (%d)\n", numKernels ); + return -1; + } + + /* Check first kernel */ + error = clGetKernelInfo( kernel[0], CL_KERNEL_FUNCTION_NAME, sizeof( testName ), testName, NULL ); + test_error( error, "Unable to get function name from kernel" ); + + int found_kernel1 = 0, found_kernel2 = 0; + + if( strcmp( (char *)testName, "sample_test" ) == 0 ) { + found_kernel1 = 1; + } else if( strcmp( (char *)testName, "sample_test2" ) == 0 ) { + found_kernel2 = 1; + } else { + log_error( "ERROR: Invalid kernel name returned: \"%s\" expected \"%s\" or \"%s\".\n", testName, "sample_test", "sample_test2"); + return -1; + } + + error = clGetKernelInfo( kernel[1], CL_KERNEL_FUNCTION_NAME, sizeof( testName ), testName, NULL ); + test_error( error, "Unable to get function name from second kernel" ); + + if( strcmp( (char *)testName, "sample_test" ) == 0 ) { + if (found_kernel1) { + log_error("Kernel \"%s\" returned twice.\n", (char *)testName); + return -1; + } + found_kernel1 = 1; + } else if( strcmp( (char *)testName, "sample_test2" ) == 0 ) { + if (found_kernel2) { + log_error("Kernel \"%s\" returned twice.\n", (char *)testName); + return -1; + } + found_kernel2 = 1; + } else { + log_error( "ERROR: Invalid kernel name returned: \"%s\" expected \"%s\" or \"%s\".\n", testName, "sample_test", "sample_test2"); + return -1; + } + + if( !found_kernel1 || !found_kernel2 ) + { + log_error( "ERROR: Kernel names do not match.\n" ); + if (!found_kernel1) + log_error("Kernel \"%s\" not returned.\n", "sample_test"); + if (!found_kernel2) + log_error("Kernel \"%s\" not returned.\n", "sample_test"); + return -1; + } + + error = clGetKernelInfo( kernel[0], CL_KERNEL_NUM_ARGS, sizeof( testArgCount ), &testArgCount, NULL ); + test_error( error, "Unable to get arg count from kernel" ); + + if( testArgCount != 2 ) + { + log_error( "ERROR: wrong # of args for kernel\n" ); + return -1; + } + + /* All done */ + return 0; +} + +int test_load_two_kernels_in_one(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel[2]; + unsigned int numKernels; + cl_char testName[512]; + cl_uint testArgCount; + + + error = create_single_kernel_helper(context, &program, NULL, 1, sample_two_kernels_in_1, NULL); + test_error( error, "Unable to build test program" ); + + error = clCreateKernelsInProgram(program, 2, &kernel[0], &numKernels); + test_error( error, "Unable to create dual kernel program" ); + + if( numKernels != 2 ) + { + log_error( "ERROR: wrong # of kernels! (%d)\n", numKernels ); + return -1; + } + + /* Check first kernel */ + error = clGetKernelInfo( kernel[0], CL_KERNEL_FUNCTION_NAME, sizeof( testName ), testName, NULL ); + test_error( error, "Unable to get function name from kernel" ); + + int found_kernel1 = 0, found_kernel2 = 0; + + if( strcmp( (char *)testName, "sample_test" ) == 0 ) { + found_kernel1 = 1; + } else if( strcmp( (char *)testName, "sample_test2" ) == 0 ) { + found_kernel2 = 1; + } else { + log_error( "ERROR: Invalid kernel name returned: \"%s\" expected \"%s\" or \"%s\".\n", testName, "sample_test", "sample_test2"); + return -1; + } + + error = clGetKernelInfo( kernel[0], CL_KERNEL_NUM_ARGS, sizeof( testArgCount ), &testArgCount, NULL ); + test_error( error, "Unable to get arg count from kernel" ); + + if( testArgCount != 2 ) + { + log_error( "ERROR: wrong # of args for kernel\n" ); + return -1; + } + + /* Check second kernel */ + error = clGetKernelInfo( kernel[1], CL_KERNEL_FUNCTION_NAME, sizeof( testName ), testName, NULL ); + test_error( error, "Unable to get function name from kernel" ); + + if( strcmp( (char *)testName, "sample_test" ) == 0 ) { + if (found_kernel1) { + log_error("Kernel \"%s\" returned twice.\n", (char *)testName); + return -1; + } + found_kernel1 = 1; + } else if( strcmp( (char *)testName, "sample_test2" ) == 0 ) { + if (found_kernel2) { + log_error("Kernel \"%s\" returned twice.\n", (char *)testName); + return -1; + } + found_kernel2 = 1; + } else { + log_error( "ERROR: Invalid kernel name returned: \"%s\" expected \"%s\" or \"%s\".\n", testName, "sample_test", "sample_test2"); + return -1; + } + + if( !found_kernel1 || !found_kernel2 ) + { + log_error( "ERROR: Kernel names do not match.\n" ); + if (!found_kernel1) + log_error("Kernel \"%s\" not returned.\n", "sample_test"); + if (!found_kernel2) + log_error("Kernel \"%s\" not returned.\n", "sample_test"); + return -1; + } + + /* All done */ + return 0; +} + +int test_load_two_kernels_manually( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel1, kernel2; + int error; + + + /* Now create a test program */ + error = create_single_kernel_helper(context, &program, NULL, 1, sample_two_kernels_in_1, NULL); + test_error( error, "Unable to build test program" ); + + /* Try manually creating kernels (backwards just in case) */ + kernel1 = clCreateKernel( program, "sample_test2", &error ); + + if( kernel1 == NULL || error != CL_SUCCESS ) + { + print_error( error, "Could not get kernel 1" ); + return -1; + } + + kernel2 = clCreateKernel( program, "sample_test", &error ); + + if( kernel2 == NULL ) + { + print_error( error, "Could not get kernel 2" ); + return -1; + } + + return 0; +} + +int test_get_program_info_kernel_names( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel1, kernel2; + int error; + size_t i; + + /* Now create a test program */ + error = create_single_kernel_helper(context, &program, NULL, 1, sample_two_kernels_in_1, NULL); + test_error( error, "Unable to build test program" ); + + /* Lookup the number of kernels in the program. */ + size_t total_kernels = 0; + error = clGetProgramInfo(program, CL_PROGRAM_NUM_KERNELS, sizeof(size_t),&total_kernels,NULL); + test_error( error, "Unable to get program info num kernels"); + + if (total_kernels != 2) + { + print_error( error, "Program did not contain two kernels" ); + return -1; + } + + /* Lookup the kernel names. */ + const char* actual_names[] = { "sample_test;sample_test2", "sample_test2;sample_test"} ; + + size_t kernel_names_len = 0; + error = clGetProgramInfo(program,CL_PROGRAM_KERNEL_NAMES,0,NULL,&kernel_names_len); + test_error( error, "Unable to get length of kernel names list." ); + + if (kernel_names_len != (strlen(actual_names[0])+1)) + { + print_error( error, "Kernel names length did not match"); + return -1; + } + + const size_t len = (kernel_names_len+1)*sizeof(char); + char* kernel_names = (char*)malloc(len); + error = clGetProgramInfo(program,CL_PROGRAM_KERNEL_NAMES,len,kernel_names,&kernel_names_len); + test_error( error, "Unable to get kernel names list." ); + + /* Check to see if the kernel name array is null terminated. */ + if (kernel_names[kernel_names_len-1] != '\0') + { + free(kernel_names); + print_error( error, "Kernel name list was not null terminated"); + return -1; + } + + /* Check to see if the correct kernel name string was returned. */ + for( i = 0; i < sizeof( actual_names ) / sizeof( actual_names[0] ); i++ ) + if( 0 == strcmp(actual_names[i],kernel_names) ) + break; + + if (i == sizeof( actual_names ) / sizeof( actual_names[0] ) ) + { + free(kernel_names); + log_error( "Kernel names \"%s\" did not match:\n", kernel_names ); + for( i = 0; i < sizeof( actual_names ) / sizeof( actual_names[0] ); i++ ) + log_error( "\t\t\"%s\"\n", actual_names[0] ); + return -1; + } + free(kernel_names); + + /* Try manually creating kernels (backwards just in case) */ + kernel1 = clCreateKernel( program, "sample_test", &error ); + if( kernel1 == NULL || error != CL_SUCCESS ) + { + print_error( error, "Could not get kernel 1" ); + return -1; + } + + kernel2 = clCreateKernel( program, "sample_test2", &error ); + if( kernel2 == NULL ) + { + print_error( error, "Could not get kernel 2" ); + return -1; + } + + return 0; +} + +static const char *single_task_kernel[] = { + "__kernel void sample_test(__global int *dst, int count)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " for( int i = 0; i < count; i++ )\n" + " dst[i] = tid + i;\n" + "\n" + "}\n" }; + +int test_enqueue_task(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper output; + cl_int count; + + + if( create_single_kernel_helper( context, &program, &kernel, 1, single_task_kernel, "sample_test" ) ) + return -1; + + // Create args + count = 100; + output = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof( cl_int ) * count, NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &output ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 1, sizeof( cl_int ), &count ); + test_error( error, "Unable to set kernel argument" ); + + // Run task + error = clEnqueueTask( queue, kernel, 0, NULL, NULL ); + test_error( error, "Unable to run task" ); + + // Read results + cl_int *results = (cl_int*)malloc(sizeof(cl_int)*count); + error = clEnqueueReadBuffer( queue, output, CL_TRUE, 0, sizeof( cl_int ) * count, results, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + // Validate + for( cl_int i = 0; i < count; i++ ) + { + if( results[ i ] != i ) + { + log_error( "ERROR: Task result value %d did not validate! Expected %d, got %d\n", (int)i, (int)i, (int)results[ i ] ); + free(results); + return -1; + } + } + + /* All done */ + free(results); + return 0; +} + + + +#define TEST_SIZE 1000 +int test_repeated_setup_cleanup(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + + cl_context local_context; + cl_command_queue local_queue; + cl_program local_program; + cl_kernel local_kernel; + cl_mem local_mem_in, local_mem_out; + cl_event local_event; + size_t global_dim[3]; + int i, j, error; + global_dim[0] = TEST_SIZE; + global_dim[1] = 1; global_dim[2] = 1; + cl_int *inData, *outData; + cl_int status; + + inData = (cl_int*)malloc(sizeof(cl_int)*TEST_SIZE); + outData = (cl_int*)malloc(sizeof(cl_int)*TEST_SIZE); + for (i=0; i +#endif + +int IsAPowerOfTwo( unsigned long x ) +{ + return 0 == (x & (x-1)); +} + + +int test_min_data_type_align_size_alignment(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + cl_uint min_alignment; + + if (gHasLong) + min_alignment = sizeof(cl_long)*16; + else + min_alignment = sizeof(cl_int)*16; + + int error = 0; + cl_uint alignment; + + error = clGetDeviceInfo(device, CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof(alignment), &alignment, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_MEM_BASE_ADDR_ALIGN failed"); + log_info("Device reported CL_DEVICE_MEM_BASE_ADDR_ALIGN = %lu bits.\n", (unsigned long)alignment); + + // Verify the size is large enough + if (alignment < min_alignment*8) { + log_error("ERROR: alignment too small. Minimum alignment for %s16 is %lu bits, device reported %lu bits.", + (gHasLong) ? "long" : "int", + (unsigned long)(min_alignment*8), (unsigned long)alignment); + return -1; + } + + // Verify the size is a power of two + if (!IsAPowerOfTwo((unsigned long)alignment)) { + log_error("ERROR: alignment is not a power of two.\n"); + return -1; + } + + return 0; + +} diff --git a/test_conformance/api/test_kernel_arg_changes.cpp b/test_conformance/api/test_kernel_arg_changes.cpp new file mode 100644 index 00000000..b7aba632 --- /dev/null +++ b/test_conformance/api/test_kernel_arg_changes.cpp @@ -0,0 +1,141 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +extern "C" { extern cl_uint gRandomSeed;} + +// This test is designed to stress changing kernel arguments between execute calls (that are asynchronous and thus +// potentially overlapping) to make sure each kernel gets the right arguments + +// Note: put a delay loop in the kernel to make sure we have time to queue the next kernel before this one finishes +const char *inspect_image_kernel_source[] = { +"__kernel void sample_test(read_only image2d_t src, __global int *outDimensions )\n" +"{\n" +" int tid = get_global_id(0), i;\n" +" for( i = 0; i < 100000; i++ ); \n" +" outDimensions[tid * 2] = get_image_width(src) * tid;\n" +" outDimensions[tid * 2 + 1] = get_image_height(src) * tid;\n" +"\n" +"}\n" }; + +#define NUM_TRIES 100 +#define NUM_THREADS 2048 + +int test_kernel_arg_changes(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel; + int error, i; + clMemWrapper images[ NUM_TRIES ]; + size_t sizes[ NUM_TRIES ][ 2 ]; + clMemWrapper results[ NUM_TRIES ]; + cl_image_format imageFormat; + size_t maxWidth, maxHeight; + size_t threads[1], localThreads[1]; + cl_int resultArray[ NUM_THREADS * 2 ]; + char errStr[ 128 ]; + RandomSeed seed( gRandomSeed ); + + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + // Just get any ol format to test with + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE2D, CL_MEM_READ_WRITE, 0, &imageFormat ); + test_error( error, "Unable to obtain suitable image format to test with!" ); + + // Create our testing kernel + error = create_single_kernel_helper( context, &program, &kernel, 1, inspect_image_kernel_source, "sample_test" ); + test_error( error, "Unable to create testing kernel" ); + + // Get max dimensions for each of our images + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + test_error( error, "Unable to get max image dimensions for device" ); + + // Get the number of threads we'll be able to run + threads[0] = NUM_THREADS; + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size for kernel" ); + + // Create a variety of images and output arrays + for( i = 0; i < NUM_TRIES; i++ ) + { + sizes[ i ][ 0 ] = genrand_int32(seed) % (maxWidth/32) + 1; + sizes[ i ][ 1 ] = genrand_int32(seed) % (maxHeight/32) + 1; + + images[ i ] = create_image_2d( context, (cl_mem_flags)(CL_MEM_READ_ONLY), + &imageFormat, sizes[ i ][ 0], sizes[ i ][ 1 ], 0, NULL, &error ); + if( images[i] == NULL ) + { + log_error("Failed to create image %d of size %d x %d (%s).\n", i, (int)sizes[i][0], (int)sizes[i][1], IGetErrorString( error )); + return -1; + } + results[ i ] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof( cl_int ) * threads[0] * 2, NULL, &error ); + if( results[i] == NULL) + { + log_error("Failed to create array %d of size %d.\n", i, (int)threads[0]*2); + return -1; + } + } + + // Start setting arguments and executing kernels + for( i = 0; i < NUM_TRIES; i++ ) + { + // Set the arguments for this try + error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &images[ i ] ); + sprintf( errStr, "Unable to set argument 0 for kernel try %d", i ); + test_error( error, errStr ); + + error = clSetKernelArg( kernel, 1, sizeof( cl_mem ), &results[ i ] ); + sprintf( errStr, "Unable to set argument 1 for kernel try %d", i ); + test_error( error, errStr ); + + // Queue up execution + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + sprintf( errStr, "Unable to execute kernel try %d", i ); + test_error( error, errStr ); + } + + // Read the results back out, one at a time, and verify + for( i = 0; i < NUM_TRIES; i++ ) + { + error = clEnqueueReadBuffer( queue, results[ i ], CL_TRUE, 0, sizeof( cl_int ) * threads[0] * 2, resultArray, 0, NULL, NULL ); + sprintf( errStr, "Unable to read results for kernel try %d", i ); + test_error( error, errStr ); + + // Verify. Each entry should be n * the (width/height) of image i + for( int j = 0; j < NUM_THREADS; j++ ) + { + if( resultArray[ j * 2 + 0 ] != (int)sizes[ i ][ 0 ] * j ) + { + log_error( "ERROR: Verficiation for kernel try %d, sample %d FAILED, expected a width of %d, got %d\n", + i, j, (int)sizes[ i ][ 0 ] * j, resultArray[ j * 2 + 0 ] ); + return -1; + } + if( resultArray[ j * 2 + 1 ] != (int)sizes[ i ][ 1 ] * j ) + { + log_error( "ERROR: Verficiation for kernel try %d, sample %d FAILED, expected a height of %d, got %d\n", + i, j, (int)sizes[ i ][ 1 ] * j, resultArray[ j * 2 + 1 ] ); + return -1; + } + } + } + + // If we got here, everything verified successfully + return 0; +} + + diff --git a/test_conformance/api/test_kernel_arg_info.c b/test_conformance/api/test_kernel_arg_info.c new file mode 100644 index 00000000..27d58987 --- /dev/null +++ b/test_conformance/api/test_kernel_arg_info.c @@ -0,0 +1,5976 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include +#include +#ifndef _WIN32 +#include +#endif + +#define ARG_INFO_FIELD_COUNT 5 + +#define ARG_INFO_ADDR_OFFSET 1 +#define ARG_INFO_ACCESS_OFFSET 2 +#define ARG_INFO_TYPE_QUAL_OFFSET 3 +#define ARG_INFO_TYPE_NAME_OFFSET 4 +#define ARG_INFO_ARG_NAME_OFFSET 5 + + +typedef char const * kernel_args_t[]; + +kernel_args_t required_kernel_args = { + "typedef float4 typedef_type;\n" + "\n" + "typedef struct struct_type {\n" + " float4 float4d;\n" + " int intd;\n" + "} typedef_struct_type;\n" + "\n" + "typedef union union_type {\n" + " float4 float4d;\n" + " uint4 uint4d;\n" + "} typedef_union_type;\n" + "\n" + "typedef enum enum_type {\n" + " enum_type_zero,\n" + " enum_type_one,\n" + " enum_type_two\n" + "} typedef_enum_type;\n" + "\n" + "kernel void constant_scalar_p0(constant void*constantvoidp,\n" + " constant char *constantcharp,\n" + " constant uchar* constantucharp,\n" + " constant unsigned char * constantunsignedcharp)\n" + "{}\n", + "kernel void constant_scalar_p1(constant short*constantshortp,\n" + " constant ushort *constantushortp,\n" + " constant unsigned short* constantunsignedshortp,\n" + " constant int * constantintp)\n" + "{}\n", + "kernel void constant_scalar_p2(constant uint*constantuintp,\n" + " constant unsigned int *constantunsignedintp)\n" + "{}\n", + "kernel void constant_scalar_p3(constant float *constantfloatp)\n" + "{}\n", + "\n" + "kernel void constant_scalar_restrict_p0(constant void* restrict constantvoidrestrictp,\n" + " constant char * restrict constantcharrestrictp,\n" + " constant uchar*restrict constantucharrestrictp,\n" + " constant unsigned char *restrict constantunsignedcharrestrictp)\n" + "{}\n", + "kernel void constant_scalar_restrict_p1(constant short* restrict constantshortrestrictp,\n" + " constant ushort * restrict constantushortrestrictp,\n" + " constant unsigned short*restrict constantunsignedshortrestrictp,\n" + " constant int *restrict constantintrestrictp)\n" + "{}\n", + "kernel void constant_scalar_restrict_p2(constant uint* restrict constantuintrestrictp,\n" + " constant unsigned int * restrict constantunsignedintrestrictp)\n" + "{}\n", + "kernel void constant_scalar_restrict_p3(constant float * restrict constantfloatrestrictp)\n" + "{}\n", + "\n" + "kernel void global_scalar_p(global void*globalvoidp,\n" + " global char *globalcharp,\n" + " global uchar* globalucharp,\n" + " global unsigned char * globalunsignedcharp,\n" + " global short*globalshortp,\n" + " global ushort *globalushortp,\n" + " global unsigned short* globalunsignedshortp,\n" + " global int * globalintp,\n" + " global uint*globaluintp,\n" + " global unsigned int *globalunsignedintp,\n" + " global float *globalfloatp)\n" + "{}\n", + "\n" + "kernel void global_scalar_restrict_p(global void* restrict globalvoidrestrictp,\n" + " global char * restrict globalcharrestrictp,\n" + " global uchar*restrict globalucharrestrictp,\n" + " global unsigned char *restrict globalunsignedcharrestrictp,\n" + " global short* restrict globalshortrestrictp,\n" + " global ushort * restrict globalushortrestrictp,\n" + " global unsigned short*restrict globalunsignedshortrestrictp,\n" + " global int *restrict globalintrestrictp,\n" + " global uint* restrict globaluintrestrictp,\n" + " global unsigned int * restrict globalunsignedintrestrictp,\n" + " global float * restrict globalfloatrestrictp)\n" + "{}\n", + "\n" + "kernel void global_const_scalar_p(global const void*globalconstvoidp,\n" + " global const char *globalconstcharp,\n" + " global const uchar* globalconstucharp,\n" + " global const unsigned char * globalconstunsignedcharp,\n" + " global const short*globalconstshortp,\n" + " global const ushort *globalconstushortp,\n" + " global const unsigned short* globalconstunsignedshortp,\n" + " global const int * globalconstintp,\n" + " global const uint*globalconstuintp,\n" + " global const unsigned int *globalconstunsignedintp,\n" + " global const float *globalconstfloatp)\n" + "{}\n", + "\n" + "kernel void global_const_scalar_restrict_p(global const void* restrict globalconstvoidrestrictp,\n" + " global const char * restrict globalconstcharrestrictp,\n" + " global const uchar*restrict globalconstucharrestrictp,\n" + " global const unsigned char *restrict globalconstunsignedcharrestrictp,\n" + " global const short* restrict globalconstshortrestrictp,\n" + " global const ushort * restrict globalconstushortrestrictp,\n" + " global const unsigned short*restrict globalconstunsignedshortrestrictp,\n" + " global const int *restrict globalconstintrestrictp,\n" + " global const uint* restrict globalconstuintrestrictp,\n" + " global const unsigned int * restrict globalconstunsignedintrestrictp,\n" + " global const float * restrict globalconstfloatrestrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_scalar_p(global volatile void*globalvolatilevoidp,\n" + " global volatile char *globalvolatilecharp,\n" + " global volatile uchar* globalvolatileucharp,\n" + " global volatile unsigned char * globalvolatileunsignedcharp,\n" + " global volatile short*globalvolatileshortp,\n" + " global volatile ushort *globalvolatileushortp,\n" + " global volatile unsigned short* globalvolatileunsignedshortp,\n" + " global volatile int * globalvolatileintp,\n" + " global volatile uint*globalvolatileuintp,\n" + " global volatile unsigned int *globalvolatileunsignedintp,\n" + " global volatile float *globalvolatilefloatp)\n" + "{}\n", + "\n" + "kernel void global_volatile_scalar_restrict_p(global volatile void* restrict globalvolatilevoidrestrictp,\n" + " global volatile char * restrict globalvolatilecharrestrictp,\n" + " global volatile uchar*restrict globalvolatileucharrestrictp,\n" + " global volatile unsigned char *restrict globalvolatileunsignedcharrestrictp,\n" + " global volatile short* restrict globalvolatileshortrestrictp,\n" + " global volatile ushort * restrict globalvolatileushortrestrictp,\n" + " global volatile unsigned short*restrict globalvolatileunsignedshortrestrictp,\n" + " global volatile int *restrict globalvolatileintrestrictp,\n" + " global volatile uint* restrict globalvolatileuintrestrictp,\n" + " global volatile unsigned int * restrict globalvolatileunsignedintrestrictp,\n" + " global volatile float * restrict globalvolatilefloatrestrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_scalar_p(global const volatile void*globalconstvolatilevoidp,\n" + " global const volatile char *globalconstvolatilecharp,\n" + " global const volatile uchar* globalconstvolatileucharp,\n" + " global const volatile unsigned char * globalconstvolatileunsignedcharp,\n" + " global const volatile short*globalconstvolatileshortp,\n" + " global const volatile ushort *globalconstvolatileushortp,\n" + " global const volatile unsigned short* globalconstvolatileunsignedshortp,\n" + " global const volatile int * globalconstvolatileintp,\n" + " global const volatile uint*globalconstvolatileuintp,\n" + " global const volatile unsigned int *globalconstvolatileunsignedintp,\n" + " global const volatile float *globalconstvolatilefloatp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_scalar_restrict_p(global const volatile void* restrict globalconstvolatilevoidrestrictp,\n" + " global const volatile char * restrict globalconstvolatilecharrestrictp,\n" + " global const volatile uchar*restrict globalconstvolatileucharrestrictp,\n" + " global const volatile unsigned char *restrict globalconstvolatileunsignedcharrestrictp,\n" + " global const volatile short* restrict globalconstvolatileshortrestrictp,\n" + " global const volatile ushort * restrict globalconstvolatileushortrestrictp,\n" + " global const volatile unsigned short*restrict globalconstvolatileunsignedshortrestrictp,\n" + " global const volatile int *restrict globalconstvolatileintrestrictp,\n" + " global const volatile uint* restrict globalconstvolatileuintrestrictp,\n" + " global const volatile unsigned int * restrict globalconstvolatileunsignedintrestrictp,\n" + " global const volatile float * restrict globalconstvolatilefloatrestrictp)\n" + "{}\n", + "\n" + "kernel void local_scalar_p(local void*localvoidp,\n" + " local char *localcharp,\n" + " local uchar* localucharp,\n" + " local unsigned char * localunsignedcharp,\n" + " local short*localshortp,\n" + " local ushort *localushortp,\n" + " local unsigned short* localunsignedshortp,\n" + " local int * localintp,\n" + " local uint*localuintp,\n" + " local unsigned int *localunsignedintp,\n" + " local float *localfloatp)\n" + "{}\n", + "\n" + "kernel void local_scalar_restrict_p(local void* restrict localvoidrestrictp,\n" + " local char * restrict localcharrestrictp,\n" + " local uchar*restrict localucharrestrictp,\n" + " local unsigned char *restrict localunsignedcharrestrictp,\n" + " local short* restrict localshortrestrictp,\n" + " local ushort * restrict localushortrestrictp,\n" + " local unsigned short*restrict localunsignedshortrestrictp,\n" + " local int *restrict localintrestrictp,\n" + " local uint* restrict localuintrestrictp,\n" + " local unsigned int * restrict localunsignedintrestrictp,\n" + " local float * restrict localfloatrestrictp)\n" + "{}\n", + "\n" + "kernel void local_const_scalar_p(local const void*localconstvoidp,\n" + " local const char *localconstcharp,\n" + " local const uchar* localconstucharp,\n" + " local const unsigned char * localconstunsignedcharp,\n" + " local const short*localconstshortp,\n" + " local const ushort *localconstushortp,\n" + " local const unsigned short* localconstunsignedshortp,\n" + " local const int * localconstintp,\n" + " local const uint*localconstuintp,\n" + " local const unsigned int *localconstunsignedintp,\n" + " local const float *localconstfloatp)\n" + "{}\n", + "\n" + "kernel void local_const_scalar_restrict_p(local const void* restrict localconstvoidrestrictp,\n" + " local const char * restrict localconstcharrestrictp,\n" + " local const uchar*restrict localconstucharrestrictp,\n" + " local const unsigned char *restrict localconstunsignedcharrestrictp,\n" + " local const short* restrict localconstshortrestrictp,\n" + " local const ushort * restrict localconstushortrestrictp,\n" + " local const unsigned short*restrict localconstunsignedshortrestrictp,\n" + " local const int *restrict localconstintrestrictp,\n" + " local const uint* restrict localconstuintrestrictp,\n" + " local const unsigned int * restrict localconstunsignedintrestrictp,\n" + " local const float * restrict localconstfloatrestrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_scalar_p(local volatile void*localvolatilevoidp,\n" + " local volatile char *localvolatilecharp,\n" + " local volatile uchar* localvolatileucharp,\n" + " local volatile unsigned char * localvolatileunsignedcharp,\n" + " local volatile short*localvolatileshortp,\n" + " local volatile ushort *localvolatileushortp,\n" + " local volatile unsigned short* localvolatileunsignedshortp,\n" + " local volatile int * localvolatileintp,\n" + " local volatile uint*localvolatileuintp,\n" + " local volatile unsigned int *localvolatileunsignedintp,\n" + " local volatile float *localvolatilefloatp)\n" + "{}\n", + "\n" + "kernel void local_volatile_scalar_restrict_p(local volatile void* restrict localvolatilevoidrestrictp,\n" + " local volatile char * restrict localvolatilecharrestrictp,\n" + " local volatile uchar*restrict localvolatileucharrestrictp,\n" + " local volatile unsigned char *restrict localvolatileunsignedcharrestrictp,\n" + " local volatile short* restrict localvolatileshortrestrictp,\n" + " local volatile ushort * restrict localvolatileushortrestrictp,\n" + " local volatile unsigned short*restrict localvolatileunsignedshortrestrictp,\n" + " local volatile int *restrict localvolatileintrestrictp,\n" + " local volatile uint* restrict localvolatileuintrestrictp,\n" + " local volatile unsigned int * restrict localvolatileunsignedintrestrictp,\n" + " local volatile float * restrict localvolatilefloatrestrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_scalar_p(local const volatile void*localconstvolatilevoidp,\n" + " local const volatile char *localconstvolatilecharp,\n" + " local const volatile uchar* localconstvolatileucharp,\n" + " local const volatile unsigned char * localconstvolatileunsignedcharp,\n" + " local const volatile short*localconstvolatileshortp,\n" + " local const volatile ushort *localconstvolatileushortp,\n" + " local const volatile unsigned short* localconstvolatileunsignedshortp,\n" + " local const volatile int * localconstvolatileintp,\n" + " local const volatile uint*localconstvolatileuintp,\n" + " local const volatile unsigned int *localconstvolatileunsignedintp,\n" + " local const volatile float *localconstvolatilefloatp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_scalar_restrict_p(local const volatile void* restrict localconstvolatilevoidrestrictp,\n" + " local const volatile char * restrict localconstvolatilecharrestrictp,\n" + " local const volatile uchar*restrict localconstvolatileucharrestrictp,\n" + " local const volatile unsigned char *restrict localconstvolatileunsignedcharrestrictp,\n" + " local const volatile short* restrict localconstvolatileshortrestrictp,\n" + " local const volatile ushort * restrict localconstvolatileushortrestrictp,\n" + " local const volatile unsigned short*restrict localconstvolatileunsignedshortrestrictp,\n" + " local const volatile int *restrict localconstvolatileintrestrictp,\n" + " local const volatile uint* restrict localconstvolatileuintrestrictp,\n" + " local const volatile unsigned int * restrict localconstvolatileunsignedintrestrictp,\n" + " local const volatile float * restrict localconstvolatilefloatrestrictp)\n" + "{}\n", + "\n" + "kernel void scalar_d(char chard,\n" + " uchar uchard,\n" + " unsigned char unsignedchard,\n" + " short shortd,\n" + " ushort ushortd,\n" + " unsigned short unsignedshortd,\n" + " int intd,\n" + " uint uintd,\n" + " unsigned int unsignedintd,\n" + " float floatd)\n" + "{}\n", + "\n" + "kernel void const_scalar_d(const char constchard,\n" + " const uchar constuchard,\n" + " const unsigned char constunsignedchard,\n" + " const short constshortd,\n" + " const ushort constushortd,\n" + " const unsigned short constunsignedshortd,\n" + " const int constintd,\n" + " const uint constuintd,\n" + " const unsigned int constunsignedintd,\n" + " const float constfloatd)\n" + "{}\n", + "\n" + "kernel void private_scalar_d(private char privatechard,\n" + " private uchar privateuchard,\n" + " private unsigned char privateunsignedchard,\n" + " private short privateshortd,\n" + " private ushort privateushortd,\n" + " private unsigned short privateunsignedshortd,\n" + " private int privateintd,\n" + " private uint privateuintd,\n" + " private unsigned int privateunsignedintd,\n" + " private float privatefloatd)\n" + "{}\n", + "\n" + "kernel void private_const_scalar_d(private const char privateconstchard,\n" + " private const uchar privateconstuchard,\n" + " private const unsigned char privateconstunsignedchard,\n" + " private const short privateconstshortd,\n" + " private const ushort privateconstushortd,\n" + " private const unsigned short privateconstunsignedshortd,\n" + " private const int privateconstintd,\n" + " private const uint privateconstuintd,\n" + " private const unsigned int privateconstunsignedintd,\n" + " private const float privateconstfloatd)\n" + "{}\n", + "\n" + "kernel void constant_vector2_p0(constant char2*constantchar2p,\n" + " constant uchar2 *constantuchar2p,\n" + " constant short2* constantshort2p,\n" + " constant ushort2 * constantushort2p)\n" + "{}\n", + "\n" + "kernel void constant_vector2_p1(constant int2*constantint2p,\n" + " constant uint2 *constantuint2p)\n" + "{}\n", + "\n" + "kernel void constant_vector2_p2(constant float2*constantfloat2p)\n" + "{}\n", + "\n" + "kernel void constant_vector2_restrict_p0(constant char2 *restrict constantchar2restrictp,\n" + " constant uchar2* restrict constantuchar2restrictp,\n" + " constant short2 * restrict constantshort2restrictp,\n" + " constant ushort2*restrict constantushort2restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector2_restrict_p1(constant int2 *restrict constantint2restrictp,\n" + " constant uint2* restrict constantuint2restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector2_restrict_p2(constant float2 *restrict constantfloat2restrictp)\n" + "{}\n", + "\n" + "kernel void global_vector2_p(global char2*globalchar2p,\n" + " global uchar2 *globaluchar2p,\n" + " global short2* globalshort2p,\n" + " global ushort2 * globalushort2p,\n" + " global int2*globalint2p,\n" + " global uint2 *globaluint2p,\n" + " global float2*globalfloat2p)\n" + "{}\n", + "\n" + "kernel void global_vector2_restrict_p(global char2 *restrict globalchar2restrictp,\n" + " global uchar2* restrict globaluchar2restrictp,\n" + " global short2 * restrict globalshort2restrictp,\n" + " global ushort2*restrict globalushort2restrictp,\n" + " global int2 *restrict globalint2restrictp,\n" + " global uint2* restrict globaluint2restrictp,\n" + " global float2 *restrict globalfloat2restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_vector2_p(global const char2* globalconstchar2p,\n" + " global const uchar2 * globalconstuchar2p,\n" + " global const short2*globalconstshort2p,\n" + " global const ushort2 *globalconstushort2p,\n" + " global const int2* globalconstint2p,\n" + " global const uint2 * globalconstuint2p,\n" + " global const float2* globalconstfloat2p)\n" + "{}\n", + "\n" + "kernel void global_const_vector2_restrict_p(global const char2 * restrict globalconstchar2restrictp,\n" + " global const uchar2*restrict globalconstuchar2restrictp,\n" + " global const short2 *restrict globalconstshort2restrictp,\n" + " global const ushort2* restrict globalconstushort2restrictp,\n" + " global const int2 * restrict globalconstint2restrictp,\n" + " global const uint2*restrict globalconstuint2restrictp,\n" + " global const float2 * restrict globalconstfloat2restrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector2_p(global volatile char2*globalvolatilechar2p,\n" + " global volatile uchar2 *globalvolatileuchar2p,\n" + " global volatile short2* globalvolatileshort2p,\n" + " global volatile ushort2 * globalvolatileushort2p,\n" + " global volatile int2*globalvolatileint2p,\n" + " global volatile uint2 *globalvolatileuint2p,\n" + " global volatile float2*globalvolatilefloat2p)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector2_restrict_p(global volatile char2 *restrict globalvolatilechar2restrictp,\n" + " global volatile uchar2* restrict globalvolatileuchar2restrictp,\n" + " global volatile short2 * restrict globalvolatileshort2restrictp,\n" + " global volatile ushort2*restrict globalvolatileushort2restrictp,\n" + " global volatile int2 *restrict globalvolatileint2restrictp,\n" + " global volatile uint2* restrict globalvolatileuint2restrictp,\n" + " global volatile float2 *restrict globalvolatilefloat2restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector2_p(global const volatile char2* globalconstvolatilechar2p,\n" + " global const volatile uchar2 * globalconstvolatileuchar2p,\n" + " global const volatile short2*globalconstvolatileshort2p,\n" + " global const volatile ushort2 *globalconstvolatileushort2p,\n" + " global const volatile int2* globalconstvolatileint2p,\n" + " global const volatile uint2 * globalconstvolatileuint2p,\n" + " global const volatile float2* globalconstvolatilefloat2p)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector2_restrict_p(global const volatile char2 * restrict globalconstvolatilechar2restrictp,\n" + " global const volatile uchar2*restrict globalconstvolatileuchar2restrictp,\n" + " global const volatile short2 *restrict globalconstvolatileshort2restrictp,\n" + " global const volatile ushort2* restrict globalconstvolatileushort2restrictp,\n" + " global const volatile int2 * restrict globalconstvolatileint2restrictp,\n" + " global const volatile uint2*restrict globalconstvolatileuint2restrictp,\n" + " global const volatile float2 * restrict globalconstvolatilefloat2restrictp)\n" + "{}\n", + "\n" + "kernel void local_vector2_p(local char2*localchar2p,\n" + " local uchar2 *localuchar2p,\n" + " local short2* localshort2p,\n" + " local ushort2 * localushort2p,\n" + " local int2*localint2p,\n" + " local uint2 *localuint2p,\n" + " local float2*localfloat2p)\n" + "{}\n", + "\n" + "kernel void local_vector2_restrict_p(local char2 *restrict localchar2restrictp,\n" + " local uchar2* restrict localuchar2restrictp,\n" + " local short2 * restrict localshort2restrictp,\n" + " local ushort2*restrict localushort2restrictp,\n" + " local int2 *restrict localint2restrictp,\n" + " local uint2* restrict localuint2restrictp,\n" + " local float2 *restrict localfloat2restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_vector2_p(local const char2* localconstchar2p,\n" + " local const uchar2 * localconstuchar2p,\n" + " local const short2*localconstshort2p,\n" + " local const ushort2 *localconstushort2p,\n" + " local const int2* localconstint2p,\n" + " local const uint2 * localconstuint2p,\n" + " local const float2* localconstfloat2p)\n" + "{}\n", + "\n" + "kernel void local_const_vector2_restrict_p(local const char2 * restrict localconstchar2restrictp,\n" + " local const uchar2*restrict localconstuchar2restrictp,\n" + " local const short2 *restrict localconstshort2restrictp,\n" + " local const ushort2* restrict localconstushort2restrictp,\n" + " local const int2 * restrict localconstint2restrictp,\n" + " local const uint2*restrict localconstuint2restrictp,\n" + " local const float2 * restrict localconstfloat2restrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector2_p(local volatile char2*localvolatilechar2p,\n" + " local volatile uchar2 *localvolatileuchar2p,\n" + " local volatile short2* localvolatileshort2p,\n" + " local volatile ushort2 * localvolatileushort2p,\n" + " local volatile int2*localvolatileint2p,\n" + " local volatile uint2 *localvolatileuint2p,\n" + " local volatile float2*localvolatilefloat2p)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector2_restrict_p(local volatile char2 *restrict localvolatilechar2restrictp,\n" + " local volatile uchar2* restrict localvolatileuchar2restrictp,\n" + " local volatile short2 * restrict localvolatileshort2restrictp,\n" + " local volatile ushort2*restrict localvolatileushort2restrictp,\n" + " local volatile int2 *restrict localvolatileint2restrictp,\n" + " local volatile uint2* restrict localvolatileuint2restrictp,\n" + " local volatile float2 *restrict localvolatilefloat2restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector2_p(local const volatile char2* localconstvolatilechar2p,\n" + " local const volatile uchar2 * localconstvolatileuchar2p,\n" + " local const volatile short2*localconstvolatileshort2p,\n" + " local const volatile ushort2 *localconstvolatileushort2p,\n" + " local const volatile int2* localconstvolatileint2p,\n" + " local const volatile uint2 * localconstvolatileuint2p,\n" + " local const volatile float2* localconstvolatilefloat2p)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector2_restrict_p(local const volatile char2 * restrict localconstvolatilechar2restrictp,\n" + " local const volatile uchar2*restrict localconstvolatileuchar2restrictp,\n" + " local const volatile short2 *restrict localconstvolatileshort2restrictp,\n" + " local const volatile ushort2* restrict localconstvolatileushort2restrictp,\n" + " local const volatile int2 * restrict localconstvolatileint2restrictp,\n" + " local const volatile uint2*restrict localconstvolatileuint2restrictp,\n" + " local const volatile float2 * restrict localconstvolatilefloat2restrictp)\n" + "{}\n", + "\n" + "kernel void vector2_d(char2 char2d,\n" + " uchar2 uchar2d,\n" + " short2 short2d,\n" + " ushort2 ushort2d,\n" + " int2 int2d,\n" + " uint2 uint2d,\n" + " float2 float2d)\n" + "{}\n", + "\n" + "kernel void const_vector2_d(const char2 constchar2d,\n" + " const uchar2 constuchar2d,\n" + " const short2 constshort2d,\n" + " const ushort2 constushort2d,\n" + " const int2 constint2d,\n" + " const uint2 constuint2d,\n" + " const float2 constfloat2d)\n" + "{}\n", + "\n" + "kernel void private_vector2_d(private char2 privatechar2d,\n" + " private uchar2 privateuchar2d,\n" + " private short2 privateshort2d,\n" + " private ushort2 privateushort2d,\n" + " private int2 privateint2d,\n" + " private uint2 privateuint2d,\n" + " private float2 privatefloat2d)\n" + "{}\n", + "\n" + "kernel void private_const_vector2_d(private const char2 privateconstchar2d,\n" + " private const uchar2 privateconstuchar2d,\n" + " private const short2 privateconstshort2d,\n" + " private const ushort2 privateconstushort2d,\n" + " private const int2 privateconstint2d,\n" + " private const uint2 privateconstuint2d,\n" + " private const float2 privateconstfloat2d)\n" + "{}\n", + "\n" + "kernel void constant_vector3_p0(constant char3*constantchar3p,\n" + " constant uchar3 *constantuchar3p,\n" + " constant short3* constantshort3p,\n" + " constant ushort3 * constantushort3p)\n" + "{}\n", + "\n" + "kernel void constant_vector3_p1(constant int3*constantint3p,\n" + " constant uint3 *constantuint3p)\n" + "{}\n", + "\n" + "kernel void constant_vector3_p2(constant float3*constantfloat3p)\n" + "{}\n", + "\n" + "kernel void constant_vector3_restrict_p0(constant char3 *restrict constantchar3restrictp,\n" + " constant uchar3* restrict constantuchar3restrictp,\n" + " constant short3 * restrict constantshort3restrictp,\n" + " constant ushort3*restrict constantushort3restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector3_restrict_p1(constant int3 *restrict constantint3restrictp,\n" + " constant uint3* restrict constantuint3restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector3_restrict_p2(constant float3 *restrict constantfloat3restrictp)\n" + "{}\n", + "\n" + "kernel void global_vector3_p(global char3*globalchar3p,\n" + " global uchar3 *globaluchar3p,\n" + " global short3* globalshort3p,\n" + " global ushort3 * globalushort3p,\n" + " global int3*globalint3p,\n" + " global uint3 *globaluint3p,\n" + " global float3*globalfloat3p)\n" + "{}\n", + "\n" + "kernel void global_vector3_restrict_p(global char3 *restrict globalchar3restrictp,\n" + " global uchar3* restrict globaluchar3restrictp,\n" + " global short3 * restrict globalshort3restrictp,\n" + " global ushort3*restrict globalushort3restrictp,\n" + " global int3 *restrict globalint3restrictp,\n" + " global uint3* restrict globaluint3restrictp,\n" + " global float3 *restrict globalfloat3restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_vector3_p(global const char3* globalconstchar3p,\n" + " global const uchar3 * globalconstuchar3p,\n" + " global const short3*globalconstshort3p,\n" + " global const ushort3 *globalconstushort3p,\n" + " global const int3* globalconstint3p,\n" + " global const uint3 * globalconstuint3p,\n" + " global const float3* globalconstfloat3p)\n" + "{}\n", + "\n" + "kernel void global_const_vector3_restrict_p(global const char3 * restrict globalconstchar3restrictp,\n" + " global const uchar3*restrict globalconstuchar3restrictp,\n" + " global const short3 *restrict globalconstshort3restrictp,\n" + " global const ushort3* restrict globalconstushort3restrictp,\n" + " global const int3 * restrict globalconstint3restrictp,\n" + " global const uint3*restrict globalconstuint3restrictp,\n" + " global const float3 * restrict globalconstfloat3restrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector3_p(global volatile char3*globalvolatilechar3p,\n" + " global volatile uchar3 *globalvolatileuchar3p,\n" + " global volatile short3* globalvolatileshort3p,\n" + " global volatile ushort3 * globalvolatileushort3p,\n" + " global volatile int3*globalvolatileint3p,\n" + " global volatile uint3 *globalvolatileuint3p,\n" + " global volatile float3*globalvolatilefloat3p)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector3_restrict_p(global volatile char3 *restrict globalvolatilechar3restrictp,\n" + " global volatile uchar3* restrict globalvolatileuchar3restrictp,\n" + " global volatile short3 * restrict globalvolatileshort3restrictp,\n" + " global volatile ushort3*restrict globalvolatileushort3restrictp,\n" + " global volatile int3 *restrict globalvolatileint3restrictp,\n" + " global volatile uint3* restrict globalvolatileuint3restrictp,\n" + " global volatile float3 *restrict globalvolatilefloat3restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector3_p(global const volatile char3* globalconstvolatilechar3p,\n" + " global const volatile uchar3 * globalconstvolatileuchar3p,\n" + " global const volatile short3*globalconstvolatileshort3p,\n" + " global const volatile ushort3 *globalconstvolatileushort3p,\n" + " global const volatile int3* globalconstvolatileint3p,\n" + " global const volatile uint3 * globalconstvolatileuint3p,\n" + " global const volatile float3* globalconstvolatilefloat3p)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector3_restrict_p(global const volatile char3 * restrict globalconstvolatilechar3restrictp,\n" + " global const volatile uchar3*restrict globalconstvolatileuchar3restrictp,\n" + " global const volatile short3 *restrict globalconstvolatileshort3restrictp,\n" + " global const volatile ushort3* restrict globalconstvolatileushort3restrictp,\n" + " global const volatile int3 * restrict globalconstvolatileint3restrictp,\n" + " global const volatile uint3*restrict globalconstvolatileuint3restrictp,\n" + " global const volatile float3 * restrict globalconstvolatilefloat3restrictp)\n" + "{}\n", + "\n" + "kernel void local_vector3_p(local char3*localchar3p,\n" + " local uchar3 *localuchar3p,\n" + " local short3* localshort3p,\n" + " local ushort3 * localushort3p,\n" + " local int3*localint3p,\n" + " local uint3 *localuint3p,\n" + " local float3*localfloat3p)\n" + "{}\n", + "\n" + "kernel void local_vector3_restrict_p(local char3 *restrict localchar3restrictp,\n" + " local uchar3* restrict localuchar3restrictp,\n" + " local short3 * restrict localshort3restrictp,\n" + " local ushort3*restrict localushort3restrictp,\n" + " local int3 *restrict localint3restrictp,\n" + " local uint3* restrict localuint3restrictp,\n" + " local float3 *restrict localfloat3restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_vector3_p(local const char3* localconstchar3p,\n" + " local const uchar3 * localconstuchar3p,\n" + " local const short3*localconstshort3p,\n" + " local const ushort3 *localconstushort3p,\n" + " local const int3* localconstint3p,\n" + " local const uint3 * localconstuint3p,\n" + " local const float3* localconstfloat3p)\n" + "{}\n", + "\n" + "kernel void local_const_vector3_restrict_p(local const char3 * restrict localconstchar3restrictp,\n" + " local const uchar3*restrict localconstuchar3restrictp,\n" + " local const short3 *restrict localconstshort3restrictp,\n" + " local const ushort3* restrict localconstushort3restrictp,\n" + " local const int3 * restrict localconstint3restrictp,\n" + " local const uint3*restrict localconstuint3restrictp,\n" + " local const float3 * restrict localconstfloat3restrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector3_p(local volatile char3*localvolatilechar3p,\n" + " local volatile uchar3 *localvolatileuchar3p,\n" + " local volatile short3* localvolatileshort3p,\n" + " local volatile ushort3 * localvolatileushort3p,\n" + " local volatile int3*localvolatileint3p,\n" + " local volatile uint3 *localvolatileuint3p,\n" + " local volatile float3*localvolatilefloat3p)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector3_restrict_p(local volatile char3 *restrict localvolatilechar3restrictp,\n" + " local volatile uchar3* restrict localvolatileuchar3restrictp,\n" + " local volatile short3 * restrict localvolatileshort3restrictp,\n" + " local volatile ushort3*restrict localvolatileushort3restrictp,\n" + " local volatile int3 *restrict localvolatileint3restrictp,\n" + " local volatile uint3* restrict localvolatileuint3restrictp,\n" + " local volatile float3 *restrict localvolatilefloat3restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector3_p(local const volatile char3* localconstvolatilechar3p,\n" + " local const volatile uchar3 * localconstvolatileuchar3p,\n" + " local const volatile short3*localconstvolatileshort3p,\n" + " local const volatile ushort3 *localconstvolatileushort3p,\n" + " local const volatile int3* localconstvolatileint3p,\n" + " local const volatile uint3 * localconstvolatileuint3p,\n" + " local const volatile float3* localconstvolatilefloat3p)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector3_restrict_p(local const volatile char3 * restrict localconstvolatilechar3restrictp,\n" + " local const volatile uchar3*restrict localconstvolatileuchar3restrictp,\n" + " local const volatile short3 *restrict localconstvolatileshort3restrictp,\n" + " local const volatile ushort3* restrict localconstvolatileushort3restrictp,\n" + " local const volatile int3 * restrict localconstvolatileint3restrictp,\n" + " local const volatile uint3*restrict localconstvolatileuint3restrictp,\n" + " local const volatile float3 * restrict localconstvolatilefloat3restrictp)\n" + "{}\n", + "\n" + "kernel void vector3_d(char3 char3d,\n" + " uchar3 uchar3d,\n" + " short3 short3d,\n" + " ushort3 ushort3d,\n" + " int3 int3d,\n" + " uint3 uint3d,\n" + " float3 float3d)\n" + "{}\n", + "\n" + "kernel void const_vector3_d(const char3 constchar3d,\n" + " const uchar3 constuchar3d,\n" + " const short3 constshort3d,\n" + " const ushort3 constushort3d,\n" + " const int3 constint3d,\n" + " const uint3 constuint3d,\n" + " const float3 constfloat3d)\n" + "{}\n", + "\n" + "kernel void private_vector3_d(private char3 privatechar3d,\n" + " private uchar3 privateuchar3d,\n" + " private short3 privateshort3d,\n" + " private ushort3 privateushort3d,\n" + " private int3 privateint3d,\n" + " private uint3 privateuint3d,\n" + " private float3 privatefloat3d)\n" + "{}\n", + "\n" + "kernel void private_const_vector3_d(private const char3 privateconstchar3d,\n" + " private const uchar3 privateconstuchar3d,\n" + " private const short3 privateconstshort3d,\n" + " private const ushort3 privateconstushort3d,\n" + " private const int3 privateconstint3d,\n" + " private const uint3 privateconstuint3d,\n" + " private const float3 privateconstfloat3d)\n" + "{}\n", + "\n" + "kernel void constant_vector4_p0(constant char4*constantchar4p,\n" + " constant uchar4 *constantuchar4p,\n" + " constant short4* constantshort4p,\n" + " constant ushort4 * constantushort4p)\n" + "{}\n", + "\n" + "kernel void constant_vector4_p1(constant int4*constantint4p,\n" + " constant uint4 *constantuint4p)\n" + "{}\n", + "\n" + "kernel void constant_vector4_p2(constant float4*constantfloat4p)\n" + "{}\n", + "\n" + "kernel void constant_vector4_restrict_p0(constant char4 *restrict constantchar4restrictp,\n" + " constant uchar4* restrict constantuchar4restrictp,\n" + " constant short4 * restrict constantshort4restrictp,\n" + " constant ushort4*restrict constantushort4restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector4_restrict_p1(constant int4 *restrict constantint4restrictp,\n" + " constant uint4* restrict constantuint4restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector4_restrict_p2(constant float4 *restrict constantfloat4restrictp)\n" + "{}\n", + "\n" + "kernel void global_vector4_p(global char4*globalchar4p,\n" + " global uchar4 *globaluchar4p,\n" + " global short4* globalshort4p,\n" + " global ushort4 * globalushort4p,\n" + " global int4*globalint4p,\n" + " global uint4 *globaluint4p,\n" + " global float4*globalfloat4p)\n" + "{}\n", + "\n" + "kernel void global_vector4_restrict_p(global char4 *restrict globalchar4restrictp,\n" + " global uchar4* restrict globaluchar4restrictp,\n" + " global short4 * restrict globalshort4restrictp,\n" + " global ushort4*restrict globalushort4restrictp,\n" + " global int4 *restrict globalint4restrictp,\n" + " global uint4* restrict globaluint4restrictp,\n" + " global float4 *restrict globalfloat4restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_vector4_p(global const char4* globalconstchar4p,\n" + " global const uchar4 * globalconstuchar4p,\n" + " global const short4*globalconstshort4p,\n" + " global const ushort4 *globalconstushort4p,\n" + " global const int4* globalconstint4p,\n" + " global const uint4 * globalconstuint4p,\n" + " global const float4* globalconstfloat4p)\n" + "{}\n", + "\n" + "kernel void global_const_vector4_restrict_p(global const char4 * restrict globalconstchar4restrictp,\n" + " global const uchar4*restrict globalconstuchar4restrictp,\n" + " global const short4 *restrict globalconstshort4restrictp,\n" + " global const ushort4* restrict globalconstushort4restrictp,\n" + " global const int4 * restrict globalconstint4restrictp,\n" + " global const uint4*restrict globalconstuint4restrictp,\n" + " global const float4 * restrict globalconstfloat4restrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector4_p(global volatile char4*globalvolatilechar4p,\n" + " global volatile uchar4 *globalvolatileuchar4p,\n" + " global volatile short4* globalvolatileshort4p,\n" + " global volatile ushort4 * globalvolatileushort4p,\n" + " global volatile int4*globalvolatileint4p,\n" + " global volatile uint4 *globalvolatileuint4p,\n" + " global volatile float4*globalvolatilefloat4p)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector4_restrict_p(global volatile char4 *restrict globalvolatilechar4restrictp,\n" + " global volatile uchar4* restrict globalvolatileuchar4restrictp,\n" + " global volatile short4 * restrict globalvolatileshort4restrictp,\n" + " global volatile ushort4*restrict globalvolatileushort4restrictp,\n" + " global volatile int4 *restrict globalvolatileint4restrictp,\n" + " global volatile uint4* restrict globalvolatileuint4restrictp,\n" + " global volatile float4 *restrict globalvolatilefloat4restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector4_p(global const volatile char4* globalconstvolatilechar4p,\n" + " global const volatile uchar4 * globalconstvolatileuchar4p,\n" + " global const volatile short4*globalconstvolatileshort4p,\n" + " global const volatile ushort4 *globalconstvolatileushort4p,\n" + " global const volatile int4* globalconstvolatileint4p,\n" + " global const volatile uint4 * globalconstvolatileuint4p,\n" + " global const volatile float4* globalconstvolatilefloat4p)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector4_restrict_p(global const volatile char4 * restrict globalconstvolatilechar4restrictp,\n" + " global const volatile uchar4*restrict globalconstvolatileuchar4restrictp,\n" + " global const volatile short4 *restrict globalconstvolatileshort4restrictp,\n" + " global const volatile ushort4* restrict globalconstvolatileushort4restrictp,\n" + " global const volatile int4 * restrict globalconstvolatileint4restrictp,\n" + " global const volatile uint4*restrict globalconstvolatileuint4restrictp,\n" + " global const volatile float4 * restrict globalconstvolatilefloat4restrictp)\n" + "{}\n", + "\n" + "kernel void local_vector4_p(local char4*localchar4p,\n" + " local uchar4 *localuchar4p,\n" + " local short4* localshort4p,\n" + " local ushort4 * localushort4p,\n" + " local int4*localint4p,\n" + " local uint4 *localuint4p,\n" + " local float4*localfloat4p)\n" + "{}\n", + "\n" + "kernel void local_vector4_restrict_p(local char4 *restrict localchar4restrictp,\n" + " local uchar4* restrict localuchar4restrictp,\n" + " local short4 * restrict localshort4restrictp,\n" + " local ushort4*restrict localushort4restrictp,\n" + " local int4 *restrict localint4restrictp,\n" + " local uint4* restrict localuint4restrictp,\n" + " local float4 *restrict localfloat4restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_vector4_p(local const char4* localconstchar4p,\n" + " local const uchar4 * localconstuchar4p,\n" + " local const short4*localconstshort4p,\n" + " local const ushort4 *localconstushort4p,\n" + " local const int4* localconstint4p,\n" + " local const uint4 * localconstuint4p,\n" + " local const float4* localconstfloat4p)\n" + "{}\n", + "\n" + "kernel void local_const_vector4_restrict_p(local const char4 * restrict localconstchar4restrictp,\n" + " local const uchar4*restrict localconstuchar4restrictp,\n" + " local const short4 *restrict localconstshort4restrictp,\n" + " local const ushort4* restrict localconstushort4restrictp,\n" + " local const int4 * restrict localconstint4restrictp,\n" + " local const uint4*restrict localconstuint4restrictp,\n" + " local const float4 * restrict localconstfloat4restrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector4_p(local volatile char4*localvolatilechar4p,\n" + " local volatile uchar4 *localvolatileuchar4p,\n" + " local volatile short4* localvolatileshort4p,\n" + " local volatile ushort4 * localvolatileushort4p,\n" + " local volatile int4*localvolatileint4p,\n" + " local volatile uint4 *localvolatileuint4p,\n" + " local volatile float4*localvolatilefloat4p)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector4_restrict_p(local volatile char4 *restrict localvolatilechar4restrictp,\n" + " local volatile uchar4* restrict localvolatileuchar4restrictp,\n" + " local volatile short4 * restrict localvolatileshort4restrictp,\n" + " local volatile ushort4*restrict localvolatileushort4restrictp,\n" + " local volatile int4 *restrict localvolatileint4restrictp,\n" + " local volatile uint4* restrict localvolatileuint4restrictp,\n" + " local volatile float4 *restrict localvolatilefloat4restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector4_p(local const volatile char4* localconstvolatilechar4p,\n" + " local const volatile uchar4 * localconstvolatileuchar4p,\n" + " local const volatile short4*localconstvolatileshort4p,\n" + " local const volatile ushort4 *localconstvolatileushort4p,\n" + " local const volatile int4* localconstvolatileint4p,\n" + " local const volatile uint4 * localconstvolatileuint4p,\n" + " local const volatile float4* localconstvolatilefloat4p)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector4_restrict_p(local const volatile char4 * restrict localconstvolatilechar4restrictp,\n" + " local const volatile uchar4*restrict localconstvolatileuchar4restrictp,\n" + " local const volatile short4 *restrict localconstvolatileshort4restrictp,\n" + " local const volatile ushort4* restrict localconstvolatileushort4restrictp,\n" + " local const volatile int4 * restrict localconstvolatileint4restrictp,\n" + " local const volatile uint4*restrict localconstvolatileuint4restrictp,\n" + " local const volatile float4 * restrict localconstvolatilefloat4restrictp)\n" + "{}\n", + "\n" + "kernel void vector4_d(char4 char4d,\n" + " uchar4 uchar4d,\n" + " short4 short4d,\n" + " ushort4 ushort4d,\n" + " int4 int4d,\n" + " uint4 uint4d,\n" + " float4 float4d)\n" + "{}\n", + "\n" + "kernel void const_vector4_d(const char4 constchar4d,\n" + " const uchar4 constuchar4d,\n" + " const short4 constshort4d,\n" + " const ushort4 constushort4d,\n" + " const int4 constint4d,\n" + " const uint4 constuint4d,\n" + " const float4 constfloat4d)\n" + "{}\n", + "\n" + "kernel void private_vector4_d(private char4 privatechar4d,\n" + " private uchar4 privateuchar4d,\n" + " private short4 privateshort4d,\n" + " private ushort4 privateushort4d,\n" + " private int4 privateint4d,\n" + " private uint4 privateuint4d,\n" + " private float4 privatefloat4d)\n" + "{}\n", + "\n" + "kernel void private_const_vector4_d(private const char4 privateconstchar4d,\n" + " private const uchar4 privateconstuchar4d,\n" + " private const short4 privateconstshort4d,\n" + " private const ushort4 privateconstushort4d,\n" + " private const int4 privateconstint4d,\n" + " private const uint4 privateconstuint4d,\n" + " private const float4 privateconstfloat4d)\n" + "{}\n", + "\n" + "kernel void constant_vector8_p0(constant char8*constantchar8p,\n" + " constant uchar8 *constantuchar8p,\n" + " constant short8* constantshort8p,\n" + " constant ushort8 * constantushort8p)\n" + "{}\n", + "\n" + "kernel void constant_vector8_p1(constant int8*constantint8p,\n" + " constant uint8 *constantuint8p)\n" + "{}\n", + "\n" + "kernel void constant_vector8_p2(constant float8*constantfloat8p)\n" + "{}\n", + "\n" + "kernel void constant_vector8_restrict_p0(constant char8 *restrict constantchar8restrictp,\n" + " constant uchar8* restrict constantuchar8restrictp,\n" + " constant short8 * restrict constantshort8restrictp,\n" + " constant ushort8*restrict constantushort8restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector8_restrict_p1(constant int8 *restrict constantint8restrictp,\n" + " constant uint8* restrict constantuint8restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector8_restrict_p2(constant float8 *restrict constantfloat8restrictp)\n" + "{}\n", + "\n" + "kernel void global_vector8_p(global char8*globalchar8p,\n" + " global uchar8 *globaluchar8p,\n" + " global short8* globalshort8p,\n" + " global ushort8 * globalushort8p,\n" + " global int8*globalint8p,\n" + " global uint8 *globaluint8p,\n" + " global float8*globalfloat8p)\n" + "{}\n", + "\n" + "kernel void global_vector8_restrict_p(global char8 *restrict globalchar8restrictp,\n" + " global uchar8* restrict globaluchar8restrictp,\n" + " global short8 * restrict globalshort8restrictp,\n" + " global ushort8*restrict globalushort8restrictp,\n" + " global int8 *restrict globalint8restrictp,\n" + " global uint8* restrict globaluint8restrictp,\n" + " global float8 *restrict globalfloat8restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_vector8_p(global const char8* globalconstchar8p,\n" + " global const uchar8 * globalconstuchar8p,\n" + " global const short8*globalconstshort8p,\n" + " global const ushort8 *globalconstushort8p,\n" + " global const int8* globalconstint8p,\n" + " global const uint8 * globalconstuint8p,\n" + " global const float8* globalconstfloat8p)\n" + "{}\n", + "\n" + "kernel void global_const_vector8_restrict_p(global const char8 * restrict globalconstchar8restrictp,\n" + " global const uchar8*restrict globalconstuchar8restrictp,\n" + " global const short8 *restrict globalconstshort8restrictp,\n" + " global const ushort8* restrict globalconstushort8restrictp,\n" + " global const int8 * restrict globalconstint8restrictp,\n" + " global const uint8*restrict globalconstuint8restrictp,\n" + " global const float8 * restrict globalconstfloat8restrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector8_p(global volatile char8*globalvolatilechar8p,\n" + " global volatile uchar8 *globalvolatileuchar8p,\n" + " global volatile short8* globalvolatileshort8p,\n" + " global volatile ushort8 * globalvolatileushort8p,\n" + " global volatile int8*globalvolatileint8p,\n" + " global volatile uint8 *globalvolatileuint8p,\n" + " global volatile float8*globalvolatilefloat8p)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector8_restrict_p(global volatile char8 *restrict globalvolatilechar8restrictp,\n" + " global volatile uchar8* restrict globalvolatileuchar8restrictp,\n" + " global volatile short8 * restrict globalvolatileshort8restrictp,\n" + " global volatile ushort8*restrict globalvolatileushort8restrictp,\n" + " global volatile int8 *restrict globalvolatileint8restrictp,\n" + " global volatile uint8* restrict globalvolatileuint8restrictp,\n" + " global volatile float8 *restrict globalvolatilefloat8restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector8_p(global const volatile char8* globalconstvolatilechar8p,\n" + " global const volatile uchar8 * globalconstvolatileuchar8p,\n" + " global const volatile short8*globalconstvolatileshort8p,\n" + " global const volatile ushort8 *globalconstvolatileushort8p,\n" + " global const volatile int8* globalconstvolatileint8p,\n" + " global const volatile uint8 * globalconstvolatileuint8p,\n" + " global const volatile float8* globalconstvolatilefloat8p)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector8_restrict_p(global const volatile char8 * restrict globalconstvolatilechar8restrictp,\n" + " global const volatile uchar8*restrict globalconstvolatileuchar8restrictp,\n" + " global const volatile short8 *restrict globalconstvolatileshort8restrictp,\n" + " global const volatile ushort8* restrict globalconstvolatileushort8restrictp,\n" + " global const volatile int8 * restrict globalconstvolatileint8restrictp,\n" + " global const volatile uint8*restrict globalconstvolatileuint8restrictp,\n" + " global const volatile float8 * restrict globalconstvolatilefloat8restrictp)\n" + "{}\n", + "\n" + "kernel void local_vector8_p(local char8*localchar8p,\n" + " local uchar8 *localuchar8p,\n" + " local short8* localshort8p,\n" + " local ushort8 * localushort8p,\n" + " local int8*localint8p,\n" + " local uint8 *localuint8p,\n" + " local float8*localfloat8p)\n" + "{}\n", + "\n" + "kernel void local_vector8_restrict_p(local char8 *restrict localchar8restrictp,\n" + " local uchar8* restrict localuchar8restrictp,\n" + " local short8 * restrict localshort8restrictp,\n" + " local ushort8*restrict localushort8restrictp,\n" + " local int8 *restrict localint8restrictp,\n" + " local uint8* restrict localuint8restrictp,\n" + " local float8 *restrict localfloat8restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_vector8_p(local const char8* localconstchar8p,\n" + " local const uchar8 * localconstuchar8p,\n" + " local const short8*localconstshort8p,\n" + " local const ushort8 *localconstushort8p,\n" + " local const int8* localconstint8p,\n" + " local const uint8 * localconstuint8p,\n" + " local const float8* localconstfloat8p)\n" + "{}\n", + "\n" + "kernel void local_const_vector8_restrict_p(local const char8 * restrict localconstchar8restrictp,\n" + " local const uchar8*restrict localconstuchar8restrictp,\n" + " local const short8 *restrict localconstshort8restrictp,\n" + " local const ushort8* restrict localconstushort8restrictp,\n" + " local const int8 * restrict localconstint8restrictp,\n" + " local const uint8*restrict localconstuint8restrictp,\n" + " local const float8 * restrict localconstfloat8restrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector8_p(local volatile char8*localvolatilechar8p,\n" + " local volatile uchar8 *localvolatileuchar8p,\n" + " local volatile short8* localvolatileshort8p,\n" + " local volatile ushort8 * localvolatileushort8p,\n" + " local volatile int8*localvolatileint8p,\n" + " local volatile uint8 *localvolatileuint8p,\n" + " local volatile float8*localvolatilefloat8p)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector8_restrict_p(local volatile char8 *restrict localvolatilechar8restrictp,\n" + " local volatile uchar8* restrict localvolatileuchar8restrictp,\n" + " local volatile short8 * restrict localvolatileshort8restrictp,\n" + " local volatile ushort8*restrict localvolatileushort8restrictp,\n" + " local volatile int8 *restrict localvolatileint8restrictp,\n" + " local volatile uint8* restrict localvolatileuint8restrictp,\n" + " local volatile float8 *restrict localvolatilefloat8restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector8_p(local const volatile char8* localconstvolatilechar8p,\n" + " local const volatile uchar8 * localconstvolatileuchar8p,\n" + " local const volatile short8*localconstvolatileshort8p,\n" + " local const volatile ushort8 *localconstvolatileushort8p,\n" + " local const volatile int8* localconstvolatileint8p,\n" + " local const volatile uint8 * localconstvolatileuint8p,\n" + " local const volatile float8* localconstvolatilefloat8p)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector8_restrict_p(local const volatile char8 * restrict localconstvolatilechar8restrictp,\n" + " local const volatile uchar8*restrict localconstvolatileuchar8restrictp,\n" + " local const volatile short8 *restrict localconstvolatileshort8restrictp,\n" + " local const volatile ushort8* restrict localconstvolatileushort8restrictp,\n" + " local const volatile int8 * restrict localconstvolatileint8restrictp,\n" + " local const volatile uint8*restrict localconstvolatileuint8restrictp,\n" + " local const volatile float8 * restrict localconstvolatilefloat8restrictp)\n" + "{}\n", + "\n" + "kernel void vector8_d(char8 char8d,\n" + " uchar8 uchar8d,\n" + " short8 short8d,\n" + " ushort8 ushort8d,\n" + " int8 int8d,\n" + " uint8 uint8d,\n" + " float8 float8d)\n" + "{}\n", + "\n" + "kernel void const_vector8_d(const char8 constchar8d,\n" + " const uchar8 constuchar8d,\n" + " const short8 constshort8d,\n" + " const ushort8 constushort8d,\n" + " const int8 constint8d,\n" + " const uint8 constuint8d,\n" + " const float8 constfloat8d)\n" + "{}\n", + "\n" + "kernel void private_vector8_d(private char8 privatechar8d,\n" + " private uchar8 privateuchar8d,\n" + " private short8 privateshort8d,\n" + " private ushort8 privateushort8d,\n" + " private int8 privateint8d,\n" + " private uint8 privateuint8d,\n" + " private float8 privatefloat8d)\n" + "{}\n", + "\n" + "kernel void private_const_vector8_d(private const char8 privateconstchar8d,\n" + " private const uchar8 privateconstuchar8d,\n" + " private const short8 privateconstshort8d,\n" + " private const ushort8 privateconstushort8d,\n" + " private const int8 privateconstint8d,\n" + " private const uint8 privateconstuint8d,\n" + " private const float8 privateconstfloat8d)\n" + "{}\n", + "\n" + "kernel void constant_vector16_p0(constant char16*constantchar16p,\n" + " constant uchar16 *constantuchar16p,\n" + " constant short16* constantshort16p,\n" + " constant ushort16 * constantushort16p)\n" + "{}\n", + "\n" + "kernel void constant_vector16_p1(constant int16*constantint16p,\n" + " constant uint16 *constantuint16p)\n" + "{}\n", + "\n" + "kernel void constant_vector16_p2(constant float16*constantfloat16p)\n" + "{}\n", + "\n" + "kernel void constant_vector16_restrict_p0(constant char16 *restrict constantchar16restrictp,\n" + " constant uchar16* restrict constantuchar16restrictp,\n" + " constant short16 * restrict constantshort16restrictp,\n" + " constant ushort16*restrict constantushort16restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector16_restrict_p1(constant int16 *restrict constantint16restrictp,\n" + " constant uint16* restrict constantuint16restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector16_restrict_p2(constant float16 *restrict constantfloat16restrictp)\n" + "{}\n", + "\n" + "kernel void global_vector16_p(global char16*globalchar16p,\n" + " global uchar16 *globaluchar16p,\n" + " global short16* globalshort16p,\n" + " global ushort16 * globalushort16p,\n" + " global int16*globalint16p,\n" + " global uint16 *globaluint16p,\n" + " global float16*globalfloat16p)\n" + "{}\n", + "\n" + "kernel void global_vector16_restrict_p(global char16 *restrict globalchar16restrictp,\n" + " global uchar16* restrict globaluchar16restrictp,\n" + " global short16 * restrict globalshort16restrictp,\n" + " global ushort16*restrict globalushort16restrictp,\n" + " global int16 *restrict globalint16restrictp,\n" + " global uint16* restrict globaluint16restrictp,\n" + " global float16 *restrict globalfloat16restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_vector16_p(global const char16* globalconstchar16p,\n" + " global const uchar16 * globalconstuchar16p,\n" + " global const short16*globalconstshort16p,\n" + " global const ushort16 *globalconstushort16p,\n" + " global const int16* globalconstint16p,\n" + " global const uint16 * globalconstuint16p,\n" + " global const float16* globalconstfloat16p)\n" + "{}\n", + "\n" + "kernel void global_const_vector16_restrict_p(global const char16 * restrict globalconstchar16restrictp,\n" + " global const uchar16*restrict globalconstuchar16restrictp,\n" + " global const short16 *restrict globalconstshort16restrictp,\n" + " global const ushort16* restrict globalconstushort16restrictp,\n" + " global const int16 * restrict globalconstint16restrictp,\n" + " global const uint16*restrict globalconstuint16restrictp,\n" + " global const float16 * restrict globalconstfloat16restrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector16_p(global volatile char16*globalvolatilechar16p,\n" + " global volatile uchar16 *globalvolatileuchar16p,\n" + " global volatile short16* globalvolatileshort16p,\n" + " global volatile ushort16 * globalvolatileushort16p,\n" + " global volatile int16*globalvolatileint16p,\n" + " global volatile uint16 *globalvolatileuint16p,\n" + " global volatile float16*globalvolatilefloat16p)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector16_restrict_p(global volatile char16 *restrict globalvolatilechar16restrictp,\n" + " global volatile uchar16* restrict globalvolatileuchar16restrictp,\n" + " global volatile short16 * restrict globalvolatileshort16restrictp,\n" + " global volatile ushort16*restrict globalvolatileushort16restrictp,\n" + " global volatile int16 *restrict globalvolatileint16restrictp,\n" + " global volatile uint16* restrict globalvolatileuint16restrictp,\n" + " global volatile float16 *restrict globalvolatilefloat16restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector16_p(global const volatile char16* globalconstvolatilechar16p,\n" + " global const volatile uchar16 * globalconstvolatileuchar16p,\n" + " global const volatile short16*globalconstvolatileshort16p,\n" + " global const volatile ushort16 *globalconstvolatileushort16p,\n" + " global const volatile int16* globalconstvolatileint16p,\n" + " global const volatile uint16 * globalconstvolatileuint16p,\n" + " global const volatile float16* globalconstvolatilefloat16p)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector16_restrict_p(global const volatile char16 * restrict globalconstvolatilechar16restrictp,\n" + " global const volatile uchar16*restrict globalconstvolatileuchar16restrictp,\n" + " global const volatile short16 *restrict globalconstvolatileshort16restrictp,\n" + " global const volatile ushort16* restrict globalconstvolatileushort16restrictp,\n" + " global const volatile int16 * restrict globalconstvolatileint16restrictp,\n" + " global const volatile uint16*restrict globalconstvolatileuint16restrictp,\n" + " global const volatile float16 * restrict globalconstvolatilefloat16restrictp)\n" + "{}\n", + "\n" + "kernel void local_vector16_p(local char16*localchar16p,\n" + " local uchar16 *localuchar16p,\n" + " local short16* localshort16p,\n" + " local ushort16 * localushort16p,\n" + " local int16*localint16p,\n" + " local uint16 *localuint16p,\n" + " local float16*localfloat16p)\n" + "{}\n", + "\n" + "kernel void local_vector16_restrict_p(local char16 *restrict localchar16restrictp,\n" + " local uchar16* restrict localuchar16restrictp,\n" + " local short16 * restrict localshort16restrictp,\n" + " local ushort16*restrict localushort16restrictp,\n" + " local int16 *restrict localint16restrictp,\n" + " local uint16* restrict localuint16restrictp,\n" + " local float16 *restrict localfloat16restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_vector16_p(local const char16* localconstchar16p,\n" + " local const uchar16 * localconstuchar16p,\n" + " local const short16*localconstshort16p,\n" + " local const ushort16 *localconstushort16p,\n" + " local const int16* localconstint16p,\n" + " local const uint16 * localconstuint16p,\n" + " local const float16* localconstfloat16p)\n" + "{}\n", + "\n" + "kernel void local_const_vector16_restrict_p(local const char16 * restrict localconstchar16restrictp,\n" + " local const uchar16*restrict localconstuchar16restrictp,\n" + " local const short16 *restrict localconstshort16restrictp,\n" + " local const ushort16* restrict localconstushort16restrictp,\n" + " local const int16 * restrict localconstint16restrictp,\n" + " local const uint16*restrict localconstuint16restrictp,\n" + " local const float16 * restrict localconstfloat16restrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector16_p(local volatile char16*localvolatilechar16p,\n" + " local volatile uchar16 *localvolatileuchar16p,\n" + " local volatile short16* localvolatileshort16p,\n" + " local volatile ushort16 * localvolatileushort16p,\n" + " local volatile int16*localvolatileint16p,\n" + " local volatile uint16 *localvolatileuint16p,\n" + " local volatile float16*localvolatilefloat16p)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector16_restrict_p(local volatile char16 *restrict localvolatilechar16restrictp,\n" + " local volatile uchar16* restrict localvolatileuchar16restrictp,\n" + " local volatile short16 * restrict localvolatileshort16restrictp,\n" + " local volatile ushort16*restrict localvolatileushort16restrictp,\n" + " local volatile int16 *restrict localvolatileint16restrictp,\n" + " local volatile uint16* restrict localvolatileuint16restrictp,\n" + " local volatile float16 *restrict localvolatilefloat16restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector16_p(local const volatile char16* localconstvolatilechar16p,\n" + " local const volatile uchar16 * localconstvolatileuchar16p,\n" + " local const volatile short16*localconstvolatileshort16p,\n" + " local const volatile ushort16 *localconstvolatileushort16p,\n" + " local const volatile int16* localconstvolatileint16p,\n" + " local const volatile uint16 * localconstvolatileuint16p,\n" + " local const volatile float16* localconstvolatilefloat16p)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector16_restrict_p(local const volatile char16 * restrict localconstvolatilechar16restrictp,\n" + " local const volatile uchar16*restrict localconstvolatileuchar16restrictp,\n" + " local const volatile short16 *restrict localconstvolatileshort16restrictp,\n" + " local const volatile ushort16* restrict localconstvolatileushort16restrictp,\n" + " local const volatile int16 * restrict localconstvolatileint16restrictp,\n" + " local const volatile uint16*restrict localconstvolatileuint16restrictp,\n" + " local const volatile float16 * restrict localconstvolatilefloat16restrictp)\n" + "{}\n", + "\n" + "kernel void vector16_d(char16 char16d,\n" + " uchar16 uchar16d,\n" + " short16 short16d,\n" + " ushort16 ushort16d,\n" + " int16 int16d,\n" + " uint16 uint16d,\n" + " float16 float16d)\n" + "{}\n", + "\n" + "kernel void const_vector16_d(const char16 constchar16d,\n" + " const uchar16 constuchar16d,\n" + " const short16 constshort16d,\n" + " const ushort16 constushort16d,\n" + " const int16 constint16d,\n" + " const uint16 constuint16d,\n" + " const float16 constfloat16d)\n" + "{}\n", + "\n" + "kernel void private_vector16_d(private char16 privatechar16d,\n" + " private uchar16 privateuchar16d,\n" + " private short16 privateshort16d,\n" + " private ushort16 privateushort16d,\n" + " private int16 privateint16d,\n" + " private uint16 privateuint16d,\n" + " private float16 privatefloat16d)\n" + "{}\n", + "\n" + "kernel void private_const_vector16_d(private const char16 privateconstchar16d,\n" + " private const uchar16 privateconstuchar16d,\n" + " private const short16 privateconstshort16d,\n" + " private const ushort16 privateconstushort16d,\n" + " private const int16 privateconstint16d,\n" + " private const uint16 privateconstuint16d,\n" + " private const float16 privateconstfloat16d)\n" + "{}\n", + "\n" + "kernel void constant_derived_p0(constant typedef_type*constanttypedef_typep,\n" + " constant struct struct_type *constantstructstruct_typep,\n" + " constant typedef_struct_type* constanttypedef_struct_typep,\n" + " constant union union_type * constantunionunion_typep)\n" + "{}\n", + "\n" + "kernel void constant_derived_p1(constant typedef_union_type*constanttypedef_union_typep,\n" + " constant enum enum_type *constantenumenum_typep,\n" + " constant typedef_enum_type* constanttypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void constant_derived_restrict_p0(constant typedef_type * restrict constanttypedef_typerestrictp,\n" + " constant struct struct_type*restrict constantstructstruct_typerestrictp,\n" + " constant typedef_struct_type *restrict constanttypedef_struct_typerestrictp,\n" + " constant union union_type* restrict constantunionunion_typerestrictp)\n" + "{}\n", + "\n" + "kernel void constant_derived_restrict_p1(constant typedef_union_type * restrict constanttypedef_union_typerestrictp,\n" + " constant enum enum_type*restrict constantenumenum_typerestrictp,\n" + " constant typedef_enum_type *restrict constanttypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void global_derived_p(global typedef_type*globaltypedef_typep,\n" + " global struct struct_type *globalstructstruct_typep,\n" + " global typedef_struct_type* globaltypedef_struct_typep,\n" + " global union union_type * globalunionunion_typep,\n" + " global typedef_union_type*globaltypedef_union_typep,\n" + " global enum enum_type *globalenumenum_typep,\n" + " global typedef_enum_type* globaltypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void global_derived_restrict_p(global typedef_type * restrict globaltypedef_typerestrictp,\n" + " global struct struct_type*restrict globalstructstruct_typerestrictp,\n" + " global typedef_struct_type *restrict globaltypedef_struct_typerestrictp,\n" + " global union union_type* restrict globalunionunion_typerestrictp,\n" + " global typedef_union_type * restrict globaltypedef_union_typerestrictp,\n" + " global enum enum_type*restrict globalenumenum_typerestrictp,\n" + " global typedef_enum_type *restrict globaltypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void global_const_derived_p(global const typedef_type* globalconsttypedef_typep,\n" + " global const struct struct_type * globalconststructstruct_typep,\n" + " global const typedef_struct_type*globalconsttypedef_struct_typep,\n" + " global const union union_type *globalconstunionunion_typep,\n" + " global const typedef_union_type* globalconsttypedef_union_typep,\n" + " global const enum enum_type * globalconstenumenum_typep,\n" + " global const typedef_enum_type*globalconsttypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void global_const_derived_restrict_p(global const typedef_type *restrict globalconsttypedef_typerestrictp,\n" + " global const struct struct_type* restrict globalconststructstruct_typerestrictp,\n" + " global const typedef_struct_type * restrict globalconsttypedef_struct_typerestrictp,\n" + " global const union union_type*restrict globalconstunionunion_typerestrictp,\n" + " global const typedef_union_type *restrict globalconsttypedef_union_typerestrictp,\n" + " global const enum enum_type* restrict globalconstenumenum_typerestrictp,\n" + " global const typedef_enum_type * restrict globalconsttypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_derived_p(global volatile typedef_type*globalvolatiletypedef_typep,\n" + " global volatile struct struct_type *globalvolatilestructstruct_typep,\n" + " global volatile typedef_struct_type* globalvolatiletypedef_struct_typep,\n" + " global volatile union union_type * globalvolatileunionunion_typep,\n" + " global volatile typedef_union_type*globalvolatiletypedef_union_typep,\n" + " global volatile enum enum_type *globalvolatileenumenum_typep,\n" + " global volatile typedef_enum_type* globalvolatiletypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void global_volatile_derived_restrict_p(global volatile typedef_type * restrict globalvolatiletypedef_typerestrictp,\n" + " global volatile struct struct_type*restrict globalvolatilestructstruct_typerestrictp,\n" + " global volatile typedef_struct_type *restrict globalvolatiletypedef_struct_typerestrictp,\n" + " global volatile union union_type* restrict globalvolatileunionunion_typerestrictp,\n" + " global volatile typedef_union_type * restrict globalvolatiletypedef_union_typerestrictp,\n" + " global volatile enum enum_type*restrict globalvolatileenumenum_typerestrictp,\n" + " global volatile typedef_enum_type *restrict globalvolatiletypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_derived_p(global const volatile typedef_type* globalconstvolatiletypedef_typep,\n" + " global const volatile struct struct_type * globalconstvolatilestructstruct_typep,\n" + " global const volatile typedef_struct_type*globalconstvolatiletypedef_struct_typep,\n" + " global const volatile union union_type *globalconstvolatileunionunion_typep,\n" + " global const volatile typedef_union_type* globalconstvolatiletypedef_union_typep,\n" + " global const volatile enum enum_type * globalconstvolatileenumenum_typep,\n" + " global const volatile typedef_enum_type*globalconstvolatiletypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_derived_restrict_p(global const volatile typedef_type *restrict globalconstvolatiletypedef_typerestrictp,\n" + " global const volatile struct struct_type* restrict globalconstvolatilestructstruct_typerestrictp,\n" + " global const volatile typedef_struct_type * restrict globalconstvolatiletypedef_struct_typerestrictp,\n" + " global const volatile union union_type*restrict globalconstvolatileunionunion_typerestrictp,\n" + " global const volatile typedef_union_type *restrict globalconstvolatiletypedef_union_typerestrictp,\n" + " global const volatile enum enum_type* restrict globalconstvolatileenumenum_typerestrictp,\n" + " global const volatile typedef_enum_type * restrict globalconstvolatiletypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void local_derived_p(local typedef_type*localtypedef_typep,\n" + " local struct struct_type *localstructstruct_typep,\n" + " local typedef_struct_type* localtypedef_struct_typep,\n" + " local union union_type * localunionunion_typep,\n" + " local typedef_union_type*localtypedef_union_typep,\n" + " local enum enum_type *localenumenum_typep,\n" + " local typedef_enum_type* localtypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void local_derived_restrict_p(local typedef_type * restrict localtypedef_typerestrictp,\n" + " local struct struct_type*restrict localstructstruct_typerestrictp,\n" + " local typedef_struct_type *restrict localtypedef_struct_typerestrictp,\n" + " local union union_type* restrict localunionunion_typerestrictp,\n" + " local typedef_union_type * restrict localtypedef_union_typerestrictp,\n" + " local enum enum_type*restrict localenumenum_typerestrictp,\n" + " local typedef_enum_type *restrict localtypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void local_const_derived_p(local const typedef_type* localconsttypedef_typep,\n" + " local const struct struct_type * localconststructstruct_typep,\n" + " local const typedef_struct_type*localconsttypedef_struct_typep,\n" + " local const union union_type *localconstunionunion_typep,\n" + " local const typedef_union_type* localconsttypedef_union_typep,\n" + " local const enum enum_type * localconstenumenum_typep,\n" + " local const typedef_enum_type*localconsttypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void local_const_derived_restrict_p(local const typedef_type *restrict localconsttypedef_typerestrictp,\n" + " local const struct struct_type* restrict localconststructstruct_typerestrictp,\n" + " local const typedef_struct_type * restrict localconsttypedef_struct_typerestrictp,\n" + " local const union union_type*restrict localconstunionunion_typerestrictp,\n" + " local const typedef_union_type *restrict localconsttypedef_union_typerestrictp,\n" + " local const enum enum_type* restrict localconstenumenum_typerestrictp,\n" + " local const typedef_enum_type * restrict localconsttypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_derived_p(local volatile typedef_type*localvolatiletypedef_typep,\n" + " local volatile struct struct_type *localvolatilestructstruct_typep,\n" + " local volatile typedef_struct_type* localvolatiletypedef_struct_typep,\n" + " local volatile union union_type * localvolatileunionunion_typep,\n" + " local volatile typedef_union_type*localvolatiletypedef_union_typep,\n" + " local volatile enum enum_type *localvolatileenumenum_typep,\n" + " local volatile typedef_enum_type* localvolatiletypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void local_volatile_derived_restrict_p(local volatile typedef_type * restrict localvolatiletypedef_typerestrictp,\n" + " local volatile struct struct_type*restrict localvolatilestructstruct_typerestrictp,\n" + " local volatile typedef_struct_type *restrict localvolatiletypedef_struct_typerestrictp,\n" + " local volatile union union_type* restrict localvolatileunionunion_typerestrictp,\n" + " local volatile typedef_union_type * restrict localvolatiletypedef_union_typerestrictp,\n" + " local volatile enum enum_type*restrict localvolatileenumenum_typerestrictp,\n" + " local volatile typedef_enum_type *restrict localvolatiletypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_derived_p(local const volatile typedef_type* localconstvolatiletypedef_typep,\n" + " local const volatile struct struct_type * localconstvolatilestructstruct_typep,\n" + " local const volatile typedef_struct_type*localconstvolatiletypedef_struct_typep,\n" + " local const volatile union union_type *localconstvolatileunionunion_typep,\n" + " local const volatile typedef_union_type* localconstvolatiletypedef_union_typep,\n" + " local const volatile enum enum_type * localconstvolatileenumenum_typep,\n" + " local const volatile typedef_enum_type*localconstvolatiletypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_derived_restrict_p(local const volatile typedef_type *restrict localconstvolatiletypedef_typerestrictp,\n" + " local const volatile struct struct_type* restrict localconstvolatilestructstruct_typerestrictp,\n" + " local const volatile typedef_struct_type * restrict localconstvolatiletypedef_struct_typerestrictp,\n" + " local const volatile union union_type*restrict localconstvolatileunionunion_typerestrictp,\n" + " local const volatile typedef_union_type *restrict localconstvolatiletypedef_union_typerestrictp,\n" + " local const volatile enum enum_type* restrict localconstvolatileenumenum_typerestrictp,\n" + " local const volatile typedef_enum_type * restrict localconstvolatiletypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void derived_d(typedef_type typedef_typed,\n" + " struct struct_type structstruct_typed,\n" + " typedef_struct_type typedef_struct_typed,\n" + " union union_type unionunion_typed,\n" + " typedef_union_type typedef_union_typed,\n" + " enum enum_type enumenum_typed,\n" + " typedef_enum_type typedef_enum_typed)\n" + "{}\n", + "\n" + "kernel void const_derived_d(const typedef_type consttypedef_typed,\n" + " const struct struct_type conststructstruct_typed,\n" + " const typedef_struct_type consttypedef_struct_typed,\n" + " const union union_type constunionunion_typed,\n" + " const typedef_union_type consttypedef_union_typed,\n" + " const enum enum_type constenumenum_typed,\n" + " const typedef_enum_type consttypedef_enum_typed)\n" + "{}\n", + "\n" + "kernel void private_derived_d(private typedef_type privatetypedef_typed,\n" + " private struct struct_type privatestructstruct_typed,\n" + " private typedef_struct_type privatetypedef_struct_typed,\n" + " private union union_type privateunionunion_typed,\n" + " private typedef_union_type privatetypedef_union_typed,\n" + " private enum enum_type privateenumenum_typed,\n" + " private typedef_enum_type privatetypedef_enum_typed)\n" + "{}\n", + "\n" + "kernel void private_const_derived_d(private const typedef_type privateconsttypedef_typed,\n" + " private const struct struct_type privateconststructstruct_typed,\n" + " private const typedef_struct_type privateconsttypedef_struct_typed,\n" + " private const union union_type privateconstunionunion_typed,\n" + " private const typedef_union_type privateconsttypedef_union_typed,\n" + " private const enum enum_type privateconstenumenum_typed,\n" + " private const typedef_enum_type privateconsttypedef_enum_typed)\n" + "{}\n", + "\n" +}; + +const char * required_arg_info[][72] = { + // The minimum value of CL_DEVICE_MAX_CONSTANT_ARGS is 4 + { + "constant_scalar_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "void*", "constantvoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char*", "constantcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar*", "constantucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar*", "constantunsignedcharp", + NULL + }, + { + "constant_scalar_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short*", "constantshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort*", "constantushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort*", "constantunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int*", "constantintp", + NULL + }, + { + "constant_scalar_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint*", "constantuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint*", "constantunsignedintp", + NULL + }, + { + "constant_scalar_p3", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float*", "constantfloatp", + NULL + }, + { + "constant_scalar_restrict_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "constantvoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "constantcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "constantucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "constantunsignedcharrestrictp", + NULL + }, + { + "constant_scalar_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "constantshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "constantushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "constantunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "constantintrestrictp", + NULL + }, + { + "constant_scalar_restrict_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "constantuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "constantunsignedintrestrictp", + NULL + }, + { + "constant_scalar_restrict_p3", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "constantfloatrestrictp", + NULL + }, + { + "global_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "void*", "globalvoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char*", "globalcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar*", "globalucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar*", "globalunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short*", "globalshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort*", "globalushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort*", "globalunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int*", "globalintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint*", "globaluintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint*", "globalunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float*", "globalfloatp", + NULL + }, + { + "global_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "globalvoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "globalcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "globalshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "globalintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globaluintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globalunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "globalfloatrestrictp", + NULL + }, + { + "global_const_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "void*", "globalconstvoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char*", "globalconstcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar*", "globalconstucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar*", "globalconstunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short*", "globalconstshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort*", "globalconstushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort*", "globalconstunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int*", "globalconstintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint*", "globalconstuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint*", "globalconstunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float*", "globalconstfloatp", + NULL + }, + { + "global_const_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "globalconstvoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "globalconstcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalconstucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalconstunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "globalconstshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalconstushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalconstunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "globalconstintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globalconstuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globalconstunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "globalconstfloatrestrictp", + NULL + }, + { + "global_volatile_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "void*", "globalvolatilevoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char*", "globalvolatilecharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "globalvolatileucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "globalvolatileunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short*", "globalvolatileshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "globalvolatileushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "globalvolatileunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int*", "globalvolatileintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "globalvolatileuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "globalvolatileunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float*", "globalvolatilefloatp", + NULL + }, + { + "global_volatile_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "globalvolatilevoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "globalvolatilecharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalvolatileucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalvolatileunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "globalvolatileshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalvolatileushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalvolatileunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "globalvolatileintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globalvolatileuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globalvolatileunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "globalvolatilefloatrestrictp", + NULL + }, + { + "global_const_volatile_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "void*", "globalconstvolatilevoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char*", "globalconstvolatilecharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "globalconstvolatileucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "globalconstvolatileunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short*", "globalconstvolatileshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "globalconstvolatileushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "globalconstvolatileunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int*", "globalconstvolatileintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "globalconstvolatileuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "globalconstvolatileunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float*", "globalconstvolatilefloatp", + NULL + }, + { + "global_const_volatile_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "globalconstvolatilevoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "globalconstvolatilecharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalconstvolatileucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalconstvolatileunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "globalconstvolatileshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalconstvolatileushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalconstvolatileunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "globalconstvolatileintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globalconstvolatileuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globalconstvolatileunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "globalconstvolatilefloatrestrictp", + NULL + }, + { + "local_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "void*", "localvoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char*", "localcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar*", "localucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar*", "localunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short*", "localshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort*", "localushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort*", "localunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int*", "localintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint*", "localuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint*", "localunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float*", "localfloatp", + NULL + }, + { + "local_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "localvoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "localcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "localshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "localintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "localfloatrestrictp", + NULL + }, + { + "local_const_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "void*", "localconstvoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char*", "localconstcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar*", "localconstucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar*", "localconstunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short*", "localconstshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort*", "localconstushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort*", "localconstunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int*", "localconstintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint*", "localconstuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint*", "localconstunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float*", "localconstfloatp", + NULL + }, + { + "local_const_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "localconstvoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "localconstcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localconstucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localconstunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "localconstshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localconstushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localconstunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "localconstintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localconstuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localconstunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "localconstfloatrestrictp", + NULL + }, + { + "local_volatile_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "void*", "localvolatilevoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char*", "localvolatilecharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "localvolatileucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "localvolatileunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short*", "localvolatileshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "localvolatileushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "localvolatileunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int*", "localvolatileintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "localvolatileuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "localvolatileunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float*", "localvolatilefloatp", + NULL + }, + { + "local_volatile_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "localvolatilevoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "localvolatilecharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localvolatileucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localvolatileunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "localvolatileshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localvolatileushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localvolatileunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "localvolatileintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localvolatileuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localvolatileunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "localvolatilefloatrestrictp", + NULL + }, + { + "local_const_volatile_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "void*", "localconstvolatilevoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char*", "localconstvolatilecharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "localconstvolatileucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "localconstvolatileunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short*", "localconstvolatileshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "localconstvolatileushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "localconstvolatileunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int*", "localconstvolatileintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "localconstvolatileuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "localconstvolatileunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float*", "localconstvolatilefloatp", + NULL + }, + { + "local_const_volatile_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "localconstvolatilevoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "localconstvolatilecharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localconstvolatileucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localconstvolatileunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "localconstvolatileshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localconstvolatileushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localconstvolatileunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "localconstvolatileintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localconstvolatileuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localconstvolatileunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "localconstvolatilefloatrestrictp", + NULL + }, + { + "scalar_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char", "chard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "uchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "unsignedchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short", "shortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "ushortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "unsignedshortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int", "intd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "uintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "unsignedintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float", "floatd", + NULL + }, + { + "const_scalar_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char", "constchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "constuchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "constunsignedchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short", "constshortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "constushortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "constunsignedshortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int", "constintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "constuintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "constunsignedintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float", "constfloatd", + NULL + }, + { + "private_scalar_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char", "privatechard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "privateuchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "privateunsignedchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short", "privateshortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "privateushortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "privateunsignedshortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int", "privateintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "privateuintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "privateunsignedintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float", "privatefloatd", + NULL + }, + { + "private_const_scalar_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char", "privateconstchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "privateconstuchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "privateconstunsignedchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short", "privateconstshortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "privateconstushortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "privateconstunsignedshortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int", "privateconstintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "privateconstuintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "privateconstunsignedintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float", "privateconstfloatd", + NULL + }, + { + "constant_vector2_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char2*", "constantchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar2*", "constantuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short2*", "constantshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort2*", "constantushort2p", + NULL + }, + { + "constant_vector2_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int2*", "constantint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint2*", "constantuint2p", + NULL + }, + { + "constant_vector2_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float2*", "constantfloat2p", + NULL + }, + { + "constant_vector2_restrict_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "constantchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "constantuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "constantshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "constantushort2restrictp", + NULL + }, + { + "constant_vector2_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "constantint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "constantuint2restrictp", + NULL + }, + { + "constant_vector2_restrict_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "constantfloat2restrictp", + NULL + }, + { + "global_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char2*", "globalchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar2*", "globaluchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short2*", "globalshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort2*", "globalushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int2*", "globalint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint2*", "globaluint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float2*", "globalfloat2p", + NULL + }, + { + "global_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "globalchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "globaluchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "globalshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "globalushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "globalint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "globaluint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "globalfloat2restrictp", + NULL + }, + { + "global_const_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char2*", "globalconstchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar2*", "globalconstuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short2*", "globalconstshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort2*", "globalconstushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int2*", "globalconstint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint2*", "globalconstuint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float2*", "globalconstfloat2p", + NULL + }, + { + "global_const_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "globalconstchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "globalconstuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "globalconstshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "globalconstushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "globalconstint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "globalconstuint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "globalconstfloat2restrictp", + NULL + }, + { + "global_volatile_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char2*", "globalvolatilechar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar2*", "globalvolatileuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short2*", "globalvolatileshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort2*", "globalvolatileushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int2*", "globalvolatileint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint2*", "globalvolatileuint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float2*", "globalvolatilefloat2p", + NULL + }, + { + "global_volatile_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "globalvolatilechar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "globalvolatileuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "globalvolatileshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "globalvolatileushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "globalvolatileint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "globalvolatileuint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "globalvolatilefloat2restrictp", + NULL + }, + { + "global_const_volatile_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char2*", "globalconstvolatilechar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar2*", "globalconstvolatileuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short2*", "globalconstvolatileshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort2*", "globalconstvolatileushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int2*", "globalconstvolatileint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint2*", "globalconstvolatileuint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float2*", "globalconstvolatilefloat2p", + NULL + }, + { + "global_const_volatile_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "globalconstvolatilechar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "globalconstvolatileuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "globalconstvolatileshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "globalconstvolatileushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "globalconstvolatileint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "globalconstvolatileuint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "globalconstvolatilefloat2restrictp", + NULL + }, + { + "local_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char2*", "localchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar2*", "localuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short2*", "localshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort2*", "localushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int2*", "localint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint2*", "localuint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float2*", "localfloat2p", + NULL + }, + { + "local_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "localchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "localuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "localshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "localushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "localint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "localuint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "localfloat2restrictp", + NULL + }, + { + "local_const_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char2*", "localconstchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar2*", "localconstuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short2*", "localconstshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort2*", "localconstushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int2*", "localconstint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint2*", "localconstuint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float2*", "localconstfloat2p", + NULL + }, + { + "local_const_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "localconstchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "localconstuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "localconstshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "localconstushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "localconstint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "localconstuint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "localconstfloat2restrictp", + NULL + }, + { + "local_volatile_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char2*", "localvolatilechar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar2*", "localvolatileuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short2*", "localvolatileshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort2*", "localvolatileushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int2*", "localvolatileint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint2*", "localvolatileuint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float2*", "localvolatilefloat2p", + NULL + }, + { + "local_volatile_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "localvolatilechar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "localvolatileuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "localvolatileshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "localvolatileushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "localvolatileint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "localvolatileuint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "localvolatilefloat2restrictp", + NULL + }, + { + "local_const_volatile_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char2*", "localconstvolatilechar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar2*", "localconstvolatileuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short2*", "localconstvolatileshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort2*", "localconstvolatileushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int2*", "localconstvolatileint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint2*", "localconstvolatileuint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float2*", "localconstvolatilefloat2p", + NULL + }, + { + "local_const_volatile_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "localconstvolatilechar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "localconstvolatileuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "localconstvolatileshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "localconstvolatileushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "localconstvolatileint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "localconstvolatileuint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "localconstvolatilefloat2restrictp", + NULL + }, + { + "vector2_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char2", "char2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar2", "uchar2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short2", "short2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort2", "ushort2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int2", "int2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint2", "uint2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float2", "float2d", + NULL + }, + { + "const_vector2_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char2", "constchar2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar2", "constuchar2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short2", "constshort2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort2", "constushort2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int2", "constint2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint2", "constuint2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float2", "constfloat2d", + NULL + }, + { + "private_vector2_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char2", "privatechar2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar2", "privateuchar2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short2", "privateshort2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort2", "privateushort2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int2", "privateint2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint2", "privateuint2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float2", "privatefloat2d", + NULL + }, + { + "private_const_vector2_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char2", "privateconstchar2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar2", "privateconstuchar2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short2", "privateconstshort2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort2", "privateconstushort2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int2", "privateconstint2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint2", "privateconstuint2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float2", "privateconstfloat2d", + NULL + }, + { + "constant_vector3_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char3*", "constantchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar3*", "constantuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short3*", "constantshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort3*", "constantushort3p", + NULL + }, + { + "constant_vector3_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int3*", "constantint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint3*", "constantuint3p", + NULL + }, + { + "constant_vector3_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float3*", "constantfloat3p", + NULL + }, + { + "constant_vector3_restrict_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "constantchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "constantuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "constantshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "constantushort3restrictp", + NULL + }, + { + "constant_vector3_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "constantint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "constantuint3restrictp", + NULL + }, + { + "constant_vector3_restrict_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "constantfloat3restrictp", + NULL + }, + { + "global_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char3*", "globalchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar3*", "globaluchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short3*", "globalshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort3*", "globalushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int3*", "globalint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint3*", "globaluint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float3*", "globalfloat3p", + NULL + }, + { + "global_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "globalchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "globaluchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "globalshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "globalushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "globalint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "globaluint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "globalfloat3restrictp", + NULL + }, + { + "global_const_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char3*", "globalconstchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar3*", "globalconstuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short3*", "globalconstshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort3*", "globalconstushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int3*", "globalconstint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint3*", "globalconstuint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float3*", "globalconstfloat3p", + NULL + }, + { + "global_const_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "globalconstchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "globalconstuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "globalconstshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "globalconstushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "globalconstint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "globalconstuint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "globalconstfloat3restrictp", + NULL + }, + { + "global_volatile_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char3*", "globalvolatilechar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar3*", "globalvolatileuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short3*", "globalvolatileshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort3*", "globalvolatileushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int3*", "globalvolatileint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint3*", "globalvolatileuint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float3*", "globalvolatilefloat3p", + NULL + }, + { + "global_volatile_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "globalvolatilechar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "globalvolatileuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "globalvolatileshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "globalvolatileushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "globalvolatileint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "globalvolatileuint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "globalvolatilefloat3restrictp", + NULL + }, + { + "global_const_volatile_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char3*", "globalconstvolatilechar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar3*", "globalconstvolatileuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short3*", "globalconstvolatileshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort3*", "globalconstvolatileushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int3*", "globalconstvolatileint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint3*", "globalconstvolatileuint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float3*", "globalconstvolatilefloat3p", + NULL + }, + { + "global_const_volatile_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "globalconstvolatilechar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "globalconstvolatileuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "globalconstvolatileshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "globalconstvolatileushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "globalconstvolatileint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "globalconstvolatileuint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "globalconstvolatilefloat3restrictp", + NULL + }, + { + "local_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char3*", "localchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar3*", "localuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short3*", "localshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort3*", "localushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int3*", "localint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint3*", "localuint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float3*", "localfloat3p", + NULL + }, + { + "local_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "localchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "localuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "localshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "localushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "localint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "localuint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "localfloat3restrictp", + NULL + }, + { + "local_const_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char3*", "localconstchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar3*", "localconstuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short3*", "localconstshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort3*", "localconstushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int3*", "localconstint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint3*", "localconstuint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float3*", "localconstfloat3p", + NULL + }, + { + "local_const_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "localconstchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "localconstuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "localconstshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "localconstushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "localconstint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "localconstuint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "localconstfloat3restrictp", + NULL + }, + { + "local_volatile_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char3*", "localvolatilechar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar3*", "localvolatileuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short3*", "localvolatileshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort3*", "localvolatileushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int3*", "localvolatileint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint3*", "localvolatileuint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float3*", "localvolatilefloat3p", + NULL + }, + { + "local_volatile_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "localvolatilechar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "localvolatileuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "localvolatileshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "localvolatileushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "localvolatileint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "localvolatileuint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "localvolatilefloat3restrictp", + NULL + }, + { + "local_const_volatile_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char3*", "localconstvolatilechar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar3*", "localconstvolatileuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short3*", "localconstvolatileshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort3*", "localconstvolatileushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int3*", "localconstvolatileint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint3*", "localconstvolatileuint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float3*", "localconstvolatilefloat3p", + NULL + }, + { + "local_const_volatile_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "localconstvolatilechar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "localconstvolatileuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "localconstvolatileshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "localconstvolatileushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "localconstvolatileint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "localconstvolatileuint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "localconstvolatilefloat3restrictp", + NULL + }, + { + "vector3_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char3", "char3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar3", "uchar3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short3", "short3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort3", "ushort3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int3", "int3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint3", "uint3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float3", "float3d", + NULL + }, + { + "const_vector3_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char3", "constchar3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar3", "constuchar3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short3", "constshort3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort3", "constushort3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int3", "constint3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint3", "constuint3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float3", "constfloat3d", + NULL + }, + { + "private_vector3_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char3", "privatechar3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar3", "privateuchar3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short3", "privateshort3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort3", "privateushort3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int3", "privateint3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint3", "privateuint3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float3", "privatefloat3d", + NULL + }, + { + "private_const_vector3_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char3", "privateconstchar3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar3", "privateconstuchar3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short3", "privateconstshort3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort3", "privateconstushort3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int3", "privateconstint3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint3", "privateconstuint3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float3", "privateconstfloat3d", + NULL + }, + { + "constant_vector4_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char4*", "constantchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar4*", "constantuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short4*", "constantshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort4*", "constantushort4p", + NULL + }, + { + "constant_vector4_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int4*", "constantint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint4*", "constantuint4p", + NULL + }, + { + "constant_vector4_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float4*", "constantfloat4p", + NULL + }, + { + "constant_vector4_restrict_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "constantchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "constantuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "constantshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "constantushort4restrictp", + NULL + }, + { + "constant_vector4_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "constantint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "constantuint4restrictp", + NULL + }, + { + "constant_vector4_restrict_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "constantfloat4restrictp", + NULL + }, + { + "global_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char4*", "globalchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar4*", "globaluchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short4*", "globalshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort4*", "globalushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int4*", "globalint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint4*", "globaluint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float4*", "globalfloat4p", + NULL + }, + { + "global_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "globalchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "globaluchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "globalshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "globalushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "globalint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "globaluint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "globalfloat4restrictp", + NULL + }, + { + "global_const_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char4*", "globalconstchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar4*", "globalconstuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short4*", "globalconstshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort4*", "globalconstushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int4*", "globalconstint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint4*", "globalconstuint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float4*", "globalconstfloat4p", + NULL + }, + { + "global_const_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "globalconstchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "globalconstuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "globalconstshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "globalconstushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "globalconstint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "globalconstuint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "globalconstfloat4restrictp", + NULL + }, + { + "global_volatile_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char4*", "globalvolatilechar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar4*", "globalvolatileuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short4*", "globalvolatileshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort4*", "globalvolatileushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int4*", "globalvolatileint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint4*", "globalvolatileuint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float4*", "globalvolatilefloat4p", + NULL + }, + { + "global_volatile_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "globalvolatilechar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "globalvolatileuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "globalvolatileshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "globalvolatileushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "globalvolatileint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "globalvolatileuint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "globalvolatilefloat4restrictp", + NULL + }, + { + "global_const_volatile_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char4*", "globalconstvolatilechar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar4*", "globalconstvolatileuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short4*", "globalconstvolatileshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort4*", "globalconstvolatileushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int4*", "globalconstvolatileint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint4*", "globalconstvolatileuint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float4*", "globalconstvolatilefloat4p", + NULL + }, + { + "global_const_volatile_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "globalconstvolatilechar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "globalconstvolatileuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "globalconstvolatileshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "globalconstvolatileushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "globalconstvolatileint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "globalconstvolatileuint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "globalconstvolatilefloat4restrictp", + NULL + }, + { + "local_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char4*", "localchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar4*", "localuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short4*", "localshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort4*", "localushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int4*", "localint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint4*", "localuint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float4*", "localfloat4p", + NULL + }, + { + "local_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "localchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "localuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "localshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "localushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "localint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "localuint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "localfloat4restrictp", + NULL + }, + { + "local_const_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char4*", "localconstchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar4*", "localconstuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short4*", "localconstshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort4*", "localconstushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int4*", "localconstint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint4*", "localconstuint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float4*", "localconstfloat4p", + NULL + }, + { + "local_const_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "localconstchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "localconstuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "localconstshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "localconstushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "localconstint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "localconstuint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "localconstfloat4restrictp", + NULL + }, + { + "local_volatile_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char4*", "localvolatilechar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar4*", "localvolatileuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short4*", "localvolatileshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort4*", "localvolatileushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int4*", "localvolatileint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint4*", "localvolatileuint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float4*", "localvolatilefloat4p", + NULL + }, + { + "local_volatile_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "localvolatilechar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "localvolatileuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "localvolatileshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "localvolatileushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "localvolatileint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "localvolatileuint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "localvolatilefloat4restrictp", + NULL + }, + { + "local_const_volatile_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char4*", "localconstvolatilechar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar4*", "localconstvolatileuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short4*", "localconstvolatileshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort4*", "localconstvolatileushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int4*", "localconstvolatileint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint4*", "localconstvolatileuint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float4*", "localconstvolatilefloat4p", + NULL + }, + { + "local_const_volatile_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "localconstvolatilechar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "localconstvolatileuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "localconstvolatileshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "localconstvolatileushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "localconstvolatileint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "localconstvolatileuint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "localconstvolatilefloat4restrictp", + NULL + }, + { + "vector4_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char4", "char4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar4", "uchar4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short4", "short4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort4", "ushort4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int4", "int4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint4", "uint4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float4", "float4d", + NULL + }, + { + "const_vector4_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char4", "constchar4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar4", "constuchar4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short4", "constshort4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort4", "constushort4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int4", "constint4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint4", "constuint4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float4", "constfloat4d", + NULL + }, + { + "private_vector4_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char4", "privatechar4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar4", "privateuchar4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short4", "privateshort4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort4", "privateushort4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int4", "privateint4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint4", "privateuint4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float4", "privatefloat4d", + NULL + }, + { + "private_const_vector4_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char4", "privateconstchar4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar4", "privateconstuchar4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short4", "privateconstshort4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort4", "privateconstushort4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int4", "privateconstint4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint4", "privateconstuint4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float4", "privateconstfloat4d", + NULL + }, + { + "constant_vector8_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char8*", "constantchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar8*", "constantuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short8*", "constantshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort8*", "constantushort8p", + NULL + }, + { + "constant_vector8_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int8*", "constantint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint8*", "constantuint8p", + NULL + }, + { + "constant_vector8_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float8*", "constantfloat8p", + NULL + }, + { + "constant_vector8_restrict_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "constantchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "constantuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "constantshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "constantushort8restrictp", + NULL + }, + { + "constant_vector8_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "constantint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "constantuint8restrictp", + NULL + }, + { + "constant_vector8_restrict_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "constantfloat8restrictp", + NULL + }, + { + "global_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char8*", "globalchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar8*", "globaluchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short8*", "globalshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort8*", "globalushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int8*", "globalint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint8*", "globaluint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float8*", "globalfloat8p", + NULL + }, + { + "global_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "globalchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "globaluchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "globalshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "globalushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "globalint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "globaluint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "globalfloat8restrictp", + NULL + }, + { + "global_const_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char8*", "globalconstchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar8*", "globalconstuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short8*", "globalconstshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort8*", "globalconstushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int8*", "globalconstint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint8*", "globalconstuint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float8*", "globalconstfloat8p", + NULL + }, + { + "global_const_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "globalconstchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "globalconstuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "globalconstshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "globalconstushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "globalconstint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "globalconstuint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "globalconstfloat8restrictp", + NULL + }, + { + "global_volatile_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char8*", "globalvolatilechar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar8*", "globalvolatileuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short8*", "globalvolatileshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort8*", "globalvolatileushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int8*", "globalvolatileint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint8*", "globalvolatileuint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float8*", "globalvolatilefloat8p", + NULL + }, + { + "global_volatile_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "globalvolatilechar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "globalvolatileuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "globalvolatileshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "globalvolatileushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "globalvolatileint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "globalvolatileuint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "globalvolatilefloat8restrictp", + NULL + }, + { + "global_const_volatile_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char8*", "globalconstvolatilechar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar8*", "globalconstvolatileuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short8*", "globalconstvolatileshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort8*", "globalconstvolatileushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int8*", "globalconstvolatileint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint8*", "globalconstvolatileuint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float8*", "globalconstvolatilefloat8p", + NULL + }, + { + "global_const_volatile_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "globalconstvolatilechar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "globalconstvolatileuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "globalconstvolatileshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "globalconstvolatileushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "globalconstvolatileint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "globalconstvolatileuint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "globalconstvolatilefloat8restrictp", + NULL + }, + { + "local_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char8*", "localchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar8*", "localuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short8*", "localshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort8*", "localushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int8*", "localint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint8*", "localuint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float8*", "localfloat8p", + NULL + }, + { + "local_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "localchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "localuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "localshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "localushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "localint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "localuint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "localfloat8restrictp", + NULL + }, + { + "local_const_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char8*", "localconstchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar8*", "localconstuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short8*", "localconstshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort8*", "localconstushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int8*", "localconstint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint8*", "localconstuint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float8*", "localconstfloat8p", + NULL + }, + { + "local_const_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "localconstchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "localconstuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "localconstshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "localconstushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "localconstint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "localconstuint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "localconstfloat8restrictp", + NULL + }, + { + "local_volatile_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char8*", "localvolatilechar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar8*", "localvolatileuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short8*", "localvolatileshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort8*", "localvolatileushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int8*", "localvolatileint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint8*", "localvolatileuint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float8*", "localvolatilefloat8p", + NULL + }, + { + "local_volatile_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "localvolatilechar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "localvolatileuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "localvolatileshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "localvolatileushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "localvolatileint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "localvolatileuint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "localvolatilefloat8restrictp", + NULL + }, + { + "local_const_volatile_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char8*", "localconstvolatilechar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar8*", "localconstvolatileuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short8*", "localconstvolatileshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort8*", "localconstvolatileushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int8*", "localconstvolatileint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint8*", "localconstvolatileuint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float8*", "localconstvolatilefloat8p", + NULL + }, + { + "local_const_volatile_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "localconstvolatilechar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "localconstvolatileuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "localconstvolatileshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "localconstvolatileushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "localconstvolatileint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "localconstvolatileuint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "localconstvolatilefloat8restrictp", + NULL + }, + { + "vector8_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char8", "char8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar8", "uchar8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short8", "short8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort8", "ushort8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int8", "int8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint8", "uint8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float8", "float8d", + NULL + }, + { + "const_vector8_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char8", "constchar8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar8", "constuchar8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short8", "constshort8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort8", "constushort8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int8", "constint8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint8", "constuint8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float8", "constfloat8d", + NULL + }, + { + "private_vector8_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char8", "privatechar8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar8", "privateuchar8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short8", "privateshort8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort8", "privateushort8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int8", "privateint8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint8", "privateuint8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float8", "privatefloat8d", + NULL + }, + { + "private_const_vector8_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char8", "privateconstchar8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar8", "privateconstuchar8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short8", "privateconstshort8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort8", "privateconstushort8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int8", "privateconstint8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint8", "privateconstuint8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float8", "privateconstfloat8d", + NULL + }, + { + "constant_vector16_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char16*", "constantchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar16*", "constantuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short16*", "constantshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort16*", "constantushort16p", + NULL + }, + { + "constant_vector16_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int16*", "constantint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint16*", "constantuint16p", + NULL + }, + { + "constant_vector16_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float16*", "constantfloat16p", + NULL + }, + { + "constant_vector16_restrict_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "constantchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "constantuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "constantshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "constantushort16restrictp", + NULL + }, + { + "constant_vector16_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "constantint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "constantuint16restrictp", + NULL + }, + { + "constant_vector16_restrict_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "constantfloat16restrictp", + NULL + }, + { + "global_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char16*", "globalchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar16*", "globaluchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short16*", "globalshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort16*", "globalushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int16*", "globalint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint16*", "globaluint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float16*", "globalfloat16p", + NULL + }, + { + "global_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "globalchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "globaluchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "globalshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "globalushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "globalint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "globaluint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "globalfloat16restrictp", + NULL + }, + { + "global_const_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char16*", "globalconstchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar16*", "globalconstuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short16*", "globalconstshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort16*", "globalconstushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int16*", "globalconstint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint16*", "globalconstuint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float16*", "globalconstfloat16p", + NULL + }, + { + "global_const_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "globalconstchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "globalconstuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "globalconstshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "globalconstushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "globalconstint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "globalconstuint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "globalconstfloat16restrictp", + NULL + }, + { + "global_volatile_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char16*", "globalvolatilechar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar16*", "globalvolatileuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short16*", "globalvolatileshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort16*", "globalvolatileushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int16*", "globalvolatileint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint16*", "globalvolatileuint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float16*", "globalvolatilefloat16p", + NULL + }, + { + "global_volatile_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "globalvolatilechar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "globalvolatileuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "globalvolatileshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "globalvolatileushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "globalvolatileint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "globalvolatileuint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "globalvolatilefloat16restrictp", + NULL + }, + { + "global_const_volatile_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char16*", "globalconstvolatilechar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar16*", "globalconstvolatileuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short16*", "globalconstvolatileshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort16*", "globalconstvolatileushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int16*", "globalconstvolatileint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint16*", "globalconstvolatileuint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float16*", "globalconstvolatilefloat16p", + NULL + }, + { + "global_const_volatile_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "globalconstvolatilechar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "globalconstvolatileuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "globalconstvolatileshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "globalconstvolatileushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "globalconstvolatileint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "globalconstvolatileuint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "globalconstvolatilefloat16restrictp", + NULL + }, + { + "local_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char16*", "localchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar16*", "localuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short16*", "localshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort16*", "localushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int16*", "localint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint16*", "localuint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float16*", "localfloat16p", + NULL + }, + { + "local_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "localchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "localuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "localshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "localushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "localint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "localuint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "localfloat16restrictp", + NULL + }, + { + "local_const_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char16*", "localconstchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar16*", "localconstuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short16*", "localconstshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort16*", "localconstushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int16*", "localconstint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint16*", "localconstuint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float16*", "localconstfloat16p", + NULL + }, + { + "local_const_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "localconstchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "localconstuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "localconstshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "localconstushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "localconstint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "localconstuint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "localconstfloat16restrictp", + NULL + }, + { + "local_volatile_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char16*", "localvolatilechar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar16*", "localvolatileuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short16*", "localvolatileshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort16*", "localvolatileushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int16*", "localvolatileint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint16*", "localvolatileuint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float16*", "localvolatilefloat16p", + NULL + }, + { + "local_volatile_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "localvolatilechar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "localvolatileuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "localvolatileshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "localvolatileushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "localvolatileint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "localvolatileuint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "localvolatilefloat16restrictp", + NULL + }, + { + "local_const_volatile_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char16*", "localconstvolatilechar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar16*", "localconstvolatileuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short16*", "localconstvolatileshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort16*", "localconstvolatileushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int16*", "localconstvolatileint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint16*", "localconstvolatileuint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float16*", "localconstvolatilefloat16p", + NULL + }, + { + "local_const_volatile_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "localconstvolatilechar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "localconstvolatileuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "localconstvolatileshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "localconstvolatileushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "localconstvolatileint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "localconstvolatileuint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "localconstvolatilefloat16restrictp", + NULL + }, + { + "vector16_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char16", "char16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar16", "uchar16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short16", "short16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort16", "ushort16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int16", "int16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint16", "uint16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float16", "float16d", + NULL + }, + { + "const_vector16_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char16", "constchar16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar16", "constuchar16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short16", "constshort16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort16", "constushort16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int16", "constint16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint16", "constuint16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float16", "constfloat16d", + NULL + }, + { + "private_vector16_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char16", "privatechar16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar16", "privateuchar16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short16", "privateshort16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort16", "privateushort16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int16", "privateint16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint16", "privateuint16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float16", "privatefloat16d", + NULL + }, + { + "private_const_vector16_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char16", "privateconstchar16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar16", "privateconstuchar16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short16", "privateconstshort16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort16", "privateconstushort16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int16", "privateconstint16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint16", "privateconstuint16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float16", "privateconstfloat16d", + NULL + }, + { + "constant_derived_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_type*", "constanttypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "struct struct_type*", "constantstructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_struct_type*", "constanttypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "union union_type*", "constantunionunion_typep", + NULL + }, + { + "constant_derived_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_union_type*", "constanttypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "enum enum_type*", "constantenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_enum_type*", "constanttypedef_enum_typep", + NULL + }, + { + "constant_derived_restrict_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "constanttypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "constantstructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "constanttypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "constantunionunion_typerestrictp", + NULL + }, + { + "constant_derived_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "constanttypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "constantenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "constanttypedef_enum_typerestrictp", + NULL + }, + { + "global_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_type*", "globaltypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "struct struct_type*", "globalstructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_struct_type*", "globaltypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "union union_type*", "globalunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_union_type*", "globaltypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "enum enum_type*", "globalenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_enum_type*", "globaltypedef_enum_typep", + NULL + }, + { + "global_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "globaltypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "globalstructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "globaltypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "globalunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "globaltypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "globalenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "globaltypedef_enum_typerestrictp", + NULL + }, + { + "global_const_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_type*", "globalconsttypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "struct struct_type*", "globalconststructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_struct_type*", "globalconsttypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "union union_type*", "globalconstunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_union_type*", "globalconsttypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "enum enum_type*", "globalconstenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_enum_type*", "globalconsttypedef_enum_typep", + NULL + }, + { + "global_const_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "globalconsttypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "globalconststructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "globalconsttypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "globalconstunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "globalconsttypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "globalconstenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "globalconsttypedef_enum_typerestrictp", + NULL + }, + { + "global_volatile_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_type*", "globalvolatiletypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "struct struct_type*", "globalvolatilestructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_struct_type*", "globalvolatiletypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "union union_type*", "globalvolatileunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_union_type*", "globalvolatiletypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "enum enum_type*", "globalvolatileenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_enum_type*", "globalvolatiletypedef_enum_typep", + NULL + }, + { + "global_volatile_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "globalvolatiletypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "globalvolatilestructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "globalvolatiletypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "globalvolatileunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "globalvolatiletypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "globalvolatileenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "globalvolatiletypedef_enum_typerestrictp", + NULL + }, + { + "global_const_volatile_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_type*", "globalconstvolatiletypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "struct struct_type*", "globalconstvolatilestructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_struct_type*", "globalconstvolatiletypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "union union_type*", "globalconstvolatileunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_union_type*", "globalconstvolatiletypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "enum enum_type*", "globalconstvolatileenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_enum_type*", "globalconstvolatiletypedef_enum_typep", + NULL + }, + { + "global_const_volatile_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "globalconstvolatiletypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "globalconstvolatilestructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "globalconstvolatiletypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "globalconstvolatileunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "globalconstvolatiletypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "globalconstvolatileenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "globalconstvolatiletypedef_enum_typerestrictp", + NULL + }, + { + "local_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_type*", "localtypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "struct struct_type*", "localstructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_struct_type*", "localtypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "union union_type*", "localunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_union_type*", "localtypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "enum enum_type*", "localenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_enum_type*", "localtypedef_enum_typep", + NULL + }, + { + "local_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "localtypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "localstructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "localtypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "localunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "localtypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "localenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "localtypedef_enum_typerestrictp", + NULL + }, + { + "local_const_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_type*", "localconsttypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "struct struct_type*", "localconststructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_struct_type*", "localconsttypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "union union_type*", "localconstunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_union_type*", "localconsttypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "enum enum_type*", "localconstenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_enum_type*", "localconsttypedef_enum_typep", + NULL + }, + { + "local_const_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "localconsttypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "localconststructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "localconsttypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "localconstunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "localconsttypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "localconstenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "localconsttypedef_enum_typerestrictp", + NULL + }, + { + "local_volatile_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_type*", "localvolatiletypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "struct struct_type*", "localvolatilestructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_struct_type*", "localvolatiletypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "union union_type*", "localvolatileunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_union_type*", "localvolatiletypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "enum enum_type*", "localvolatileenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_enum_type*", "localvolatiletypedef_enum_typep", + NULL + }, + { + "local_volatile_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "localvolatiletypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "localvolatilestructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "localvolatiletypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "localvolatileunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "localvolatiletypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "localvolatileenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "localvolatiletypedef_enum_typerestrictp", + NULL + }, + { + "local_const_volatile_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_type*", "localconstvolatiletypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "struct struct_type*", "localconstvolatilestructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_struct_type*", "localconstvolatiletypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "union union_type*", "localconstvolatileunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_union_type*", "localconstvolatiletypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "enum enum_type*", "localconstvolatileenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_enum_type*", "localconstvolatiletypedef_enum_typep", + NULL + }, + { + "local_const_volatile_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "localconstvolatiletypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "localconstvolatilestructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "localconstvolatiletypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "localconstvolatileunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "localconstvolatiletypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "localconstvolatileenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "localconstvolatiletypedef_enum_typerestrictp", + NULL + }, + { + "derived_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_type", "typedef_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "struct struct_type", "structstruct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_struct_type", "typedef_struct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "union union_type", "unionunion_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_union_type", "typedef_union_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "enum enum_type", "enumenum_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_enum_type", "typedef_enum_typed", + NULL + }, + { + "const_derived_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_type", "consttypedef_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "struct struct_type", "conststructstruct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_struct_type", "consttypedef_struct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "union union_type", "constunionunion_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_union_type", "consttypedef_union_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "enum enum_type", "constenumenum_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_enum_type", "consttypedef_enum_typed", + NULL + }, + { + "private_derived_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_type", "privatetypedef_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "struct struct_type", "privatestructstruct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_struct_type", "privatetypedef_struct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "union union_type", "privateunionunion_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_union_type", "privatetypedef_union_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "enum enum_type", "privateenumenum_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_enum_type", "privatetypedef_enum_typed", + NULL + }, + { + "private_const_derived_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_type", "privateconsttypedef_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "struct struct_type", "privateconststructstruct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_struct_type", "privateconsttypedef_struct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "union union_type", "privateconstunionunion_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_union_type", "privateconsttypedef_union_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "enum enum_type", "privateconstenumenum_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_enum_type", "privateconsttypedef_enum_typed", + NULL + }, +}; + +// Support for optional image data type +const char * image_kernel_args[] = { + "#pragma OPENCL EXTENSION cl_khr_3d_image_writes: enable \n" + "kernel void image_d(read_only image2d_t image2d_td0,\n" + " write_only image2d_t image2d_td1,\n" + " read_only image3d_t image3d_td2,\n" + " write_only image3d_t image3d_td3,\n" + " read_only image2d_array_t image2d_array_td4,\n" + " write_only image2d_array_t image2d_array_td5,\n" + " read_only image1d_t image1d_td6,\n" + " write_only image1d_t image1d_td7,\n" + " read_only image1d_buffer_t image1d_buffer_td8,\n" + " write_only image1d_buffer_t image1d_buffer_td9,\n" + " read_only image1d_array_t image1d_array_td10,\n" + " write_only image1d_array_t image1d_array_td11,\n" + " sampler_t sampler_td12)\n" + "{}\n", + "\n" +}; + +const char * image_arg_info[][67] = { + { + "image_d", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_READ_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image2d_t", "image2d_td0", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_WRITE_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image2d_t", "image2d_td1", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_READ_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image3d_t", "image3d_td2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_WRITE_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image3d_t", "image3d_td3", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_READ_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image2d_array_t", "image2d_array_td4", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_WRITE_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image2d_array_t", "image2d_array_td5", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_READ_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image1d_t", "image1d_td6", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_WRITE_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image1d_t", "image1d_td7", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_READ_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image1d_buffer_t", "image1d_buffer_td8", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_WRITE_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image1d_buffer_t", "image1d_buffer_td9", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_READ_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image1d_array_t", "image1d_array_td10", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_WRITE_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image1d_array_t", "image1d_array_td11", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "sampler_t", "sampler_td12", + NULL + }, +}; + +// Support for optional double data type +const char * double_kernel_args[] = { + "kernel void double_scalar_p(constant double*constantdoublep,\n" + " constant double *restrict constantdoublerestrictp,\n" + " global double*globaldoublep,\n" + " global double *restrict globaldoublerestrictp,\n" + " global const double* globalconstdoublep,\n" + " global const double * restrict globalconstdoublerestrictp,\n" + " global volatile double*globalvolatiledoublep,\n" + " global volatile double *restrict globalvolatiledoublerestrictp,\n" + " global const volatile double* globalconstvolatiledoublep)\n" + "{}\n", + "\n" + "kernel void double_scalar_p2(global const volatile double * restrict globalconstvolatiledoublerestrictp,\n" + " local double*localdoublep,\n" + " local double *restrict localdoublerestrictp,\n" + " local const double* localconstdoublep,\n" + " local const double * restrict localconstdoublerestrictp,\n" + " local volatile double*localvolatiledoublep,\n" + " local volatile double *restrict localvolatiledoublerestrictp,\n" + " local const volatile double* localconstvolatiledoublep,\n" + " local const volatile double * restrict localconstvolatiledoublerestrictp)\n" + "{}\n", + "\n" + "kernel void double_scalar_d(double doubled,\n" + " const double constdoubled,\n" + " private double privatedoubled,\n" + " private const double privateconstdoubled)\n" + "{}\n", + "\n" + "kernel void double_vector2_p(constant double2*constantdouble2p,\n" + " constant double2 *restrict constantdouble2restrictp,\n" + " global double2*globaldouble2p,\n" + " global double2 *restrict globaldouble2restrictp,\n" + " global const double2* globalconstdouble2p,\n" + " global const double2 * restrict globalconstdouble2restrictp,\n" + " global volatile double2*globalvolatiledouble2p,\n" + " global volatile double2 *restrict globalvolatiledouble2restrictp,\n" + " global const volatile double2* globalconstvolatiledouble2p)\n" + "{}\n", + "\n" + "kernel void double_vector2_p2(global const volatile double2 * restrict globalconstvolatiledouble2restrictp,\n" + " local double2*localdouble2p,\n" + " local double2 *restrict localdouble2restrictp,\n" + " local const double2* localconstdouble2p,\n" + " local const double2 * restrict localconstdouble2restrictp,\n" + " local volatile double2*localvolatiledouble2p,\n" + " local volatile double2 *restrict localvolatiledouble2restrictp,\n" + " local const volatile double2* localconstvolatiledouble2p,\n" + " local const volatile double2 * restrict localconstvolatiledouble2restrictp)\n" + "{}\n", + "\n" + "kernel void double_vector2_d(double2 double2d,\n" + " const double2 constdouble2d,\n" + " private double2 privatedouble2d,\n" + " private const double2 privateconstdouble2d)\n" + "{}\n", + "\n" + "kernel void double_vector3_p(constant double3*constantdouble3p,\n" + " constant double3 *restrict constantdouble3restrictp,\n" + " global double3*globaldouble3p,\n" + " global double3 *restrict globaldouble3restrictp,\n" + " global const double3* globalconstdouble3p,\n" + " global const double3 * restrict globalconstdouble3restrictp,\n" + " global volatile double3*globalvolatiledouble3p,\n" + " global volatile double3 *restrict globalvolatiledouble3restrictp,\n" + " global const volatile double3* globalconstvolatiledouble3p)\n" + "{}\n", + "\n" + "kernel void double_vector3_p2(global const volatile double3 * restrict globalconstvolatiledouble3restrictp,\n" + " local double3*localdouble3p,\n" + " local double3 *restrict localdouble3restrictp,\n" + " local const double3* localconstdouble3p,\n" + " local const double3 * restrict localconstdouble3restrictp,\n" + " local volatile double3*localvolatiledouble3p,\n" + " local volatile double3 *restrict localvolatiledouble3restrictp,\n" + " local const volatile double3* localconstvolatiledouble3p,\n" + " local const volatile double3 * restrict localconstvolatiledouble3restrictp)\n" + "{}\n", + "\n" + "kernel void double_vector3_d(double3 double3d,\n" + " const double3 constdouble3d,\n" + " private double3 privatedouble3d,\n" + " private const double3 privateconstdouble3d)\n" + "{}\n", + "\n" + "kernel void double_vector4_p(constant double4*constantdouble4p,\n" + " constant double4 *restrict constantdouble4restrictp,\n" + " global double4*globaldouble4p,\n" + " global double4 *restrict globaldouble4restrictp,\n" + " global const double4* globalconstdouble4p,\n" + " global const double4 * restrict globalconstdouble4restrictp,\n" + " global volatile double4*globalvolatiledouble4p,\n" + " global volatile double4 *restrict globalvolatiledouble4restrictp,\n" + " global const volatile double4* globalconstvolatiledouble4p)\n" + "{}\n", + "\n" + "kernel void double_vector4_p2(global const volatile double4 * restrict globalconstvolatiledouble4restrictp,\n" + " local double4*localdouble4p,\n" + " local double4 *restrict localdouble4restrictp,\n" + " local const double4* localconstdouble4p,\n" + " local const double4 * restrict localconstdouble4restrictp,\n" + " local volatile double4*localvolatiledouble4p,\n" + " local volatile double4 *restrict localvolatiledouble4restrictp,\n" + " local const volatile double4* localconstvolatiledouble4p,\n" + " local const volatile double4 * restrict localconstvolatiledouble4restrictp)\n" + "{}\n", + "\n" + "kernel void double_vector4_d(double4 double4d,\n" + " const double4 constdouble4d,\n" + " private double4 privatedouble4d,\n" + " private const double4 privateconstdouble4d)\n" + "{}\n", + "\n" + "kernel void double_vector8_p(constant double8*constantdouble8p,\n" + " constant double8 *restrict constantdouble8restrictp,\n" + " global double8*globaldouble8p,\n" + " global double8 *restrict globaldouble8restrictp,\n" + " global const double8* globalconstdouble8p,\n" + " global const double8 * restrict globalconstdouble8restrictp,\n" + " global volatile double8*globalvolatiledouble8p,\n" + " global volatile double8 *restrict globalvolatiledouble8restrictp,\n" + " global const volatile double8* globalconstvolatiledouble8p)\n" + "{}\n", + "\n" + "kernel void double_vector8_p2(global const volatile double8 * restrict globalconstvolatiledouble8restrictp,\n" + " local double8*localdouble8p,\n" + " local double8 *restrict localdouble8restrictp,\n" + " local const double8* localconstdouble8p,\n" + " local const double8 * restrict localconstdouble8restrictp,\n" + " local volatile double8*localvolatiledouble8p,\n" + " local volatile double8 *restrict localvolatiledouble8restrictp,\n" + " local const volatile double8* localconstvolatiledouble8p,\n" + " local const volatile double8 * restrict localconstvolatiledouble8restrictp)\n" + "{}\n", + "\n" + "kernel void double_vector8_d(double8 double8d,\n" + " const double8 constdouble8d,\n" + " private double8 privatedouble8d,\n" + " private const double8 privateconstdouble8d)\n" + "{}\n", + "\n" + "kernel void double_vector16_p(constant double16*constantdouble16p,\n" + " constant double16 *restrict constantdouble16restrictp,\n" + " global double16*globaldouble16p,\n" + " global double16 *restrict globaldouble16restrictp,\n" + " global const double16* globalconstdouble16p,\n" + " global const double16 * restrict globalconstdouble16restrictp,\n" + " global volatile double16*globalvolatiledouble16p,\n" + " global volatile double16 *restrict globalvolatiledouble16restrictp,\n" + " global const volatile double16* globalconstvolatiledouble16p)\n" + "{}\n", + "\n" + "kernel void double_vector16_p2(global const volatile double16 * restrict globalconstvolatiledouble16restrictp,\n" + " local double16*localdouble16p,\n" + " local double16 *restrict localdouble16restrictp,\n" + " local const double16* localconstdouble16p,\n" + " local const double16 * restrict localconstdouble16restrictp,\n" + " local volatile double16*localvolatiledouble16p,\n" + " local volatile double16 *restrict localvolatiledouble16restrictp,\n" + " local const volatile double16* localconstvolatiledouble16p,\n" + " local const volatile double16 * restrict localconstvolatiledouble16restrictp)\n" + "{}\n", + "\n" + "kernel void double_vector16_d(double16 double16d,\n" + " const double16 constdouble16d,\n" + " private double16 privatedouble16d,\n" + " private const double16 privateconstdouble16d)\n" + "{}\n", + "\n" +}; + +// Support for optional 3D image data type +const char * image_3D_kernel_args[] = { + "#pragma OPENCL EXTENSION cl_khr_3d_image_writes: enable \n" + "kernel void image_d(read_only image3d_t image3d_td2,\n" + " write_only image3d_t image3d_td3)\n" + "{}\n", + "\n" +}; + +const char * image_3D_arg_info[][67] = { + { + "image_d", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_READ_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image3d_t", "image3d_td2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_WRITE_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image3d_t", "image3d_td3", + NULL + }, +}; + +const char * double_arg_info[][77] = { + { + "double_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double*", "constantdoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "constantdoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double*", "globaldoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "globaldoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double*", "globalconstdoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "globalconstdoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double*", "globalvolatiledoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "globalvolatiledoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double*", "globalconstvolatiledoublep", + NULL + }, + { + "double_scalar_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "globalconstvolatiledoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double*", "localdoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "localdoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double*", "localconstdoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "localconstdoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double*", "localvolatiledoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "localvolatiledoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double*", "localconstvolatiledoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "localconstvolatiledoublerestrictp", + NULL + }, + { + "double_scalar_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double", "doubled", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double", "constdoubled", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double", "privatedoubled", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double", "privateconstdoubled", + NULL + }, + { + "double_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double2*", "constantdouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "constantdouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double2*", "globaldouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "globaldouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double2*", "globalconstdouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "globalconstdouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double2*", "globalvolatiledouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "globalvolatiledouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double2*", "globalconstvolatiledouble2p", + NULL + }, + { + "double_vector2_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "globalconstvolatiledouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double2*", "localdouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "localdouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double2*", "localconstdouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "localconstdouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double2*", "localvolatiledouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "localvolatiledouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double2*", "localconstvolatiledouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "localconstvolatiledouble2restrictp", + NULL + }, + { + "double_vector2_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double2", "double2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double2", "constdouble2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double2", "privatedouble2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double2", "privateconstdouble2d", + NULL + }, + { + "double_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double3*", "constantdouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "constantdouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double3*", "globaldouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "globaldouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double3*", "globalconstdouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "globalconstdouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double3*", "globalvolatiledouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "globalvolatiledouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double3*", "globalconstvolatiledouble3p", + NULL + }, + { + "double_vector3_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "globalconstvolatiledouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double3*", "localdouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "localdouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double3*", "localconstdouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "localconstdouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double3*", "localvolatiledouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "localvolatiledouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double3*", "localconstvolatiledouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "localconstvolatiledouble3restrictp", + NULL + }, + { + "double_vector3_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double3", "double3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double3", "constdouble3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double3", "privatedouble3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double3", "privateconstdouble3d", + NULL + }, + { + "double_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double4*", "constantdouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "constantdouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double4*", "globaldouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "globaldouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double4*", "globalconstdouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "globalconstdouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double4*", "globalvolatiledouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "globalvolatiledouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double4*", "globalconstvolatiledouble4p", + NULL + }, + { + "double_vector4_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "globalconstvolatiledouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double4*", "localdouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "localdouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double4*", "localconstdouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "localconstdouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double4*", "localvolatiledouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "localvolatiledouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double4*", "localconstvolatiledouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "localconstvolatiledouble4restrictp", + NULL + }, + { + "double_vector4_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double4", "double4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double4", "constdouble4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double4", "privatedouble4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double4", "privateconstdouble4d", + NULL + }, + { + "double_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double8*", "constantdouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "constantdouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double8*", "globaldouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "globaldouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double8*", "globalconstdouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "globalconstdouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double8*", "globalvolatiledouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "globalvolatiledouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double8*", "globalconstvolatiledouble8p", + NULL + }, + { + "double_vector8_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "globalconstvolatiledouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double8*", "localdouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "localdouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double8*", "localconstdouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "localconstdouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double8*", "localvolatiledouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "localvolatiledouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double8*", "localconstvolatiledouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "localconstvolatiledouble8restrictp", + NULL + }, + { + "double_vector8_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double8", "double8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double8", "constdouble8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double8", "privatedouble8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double8", "privateconstdouble8d", + NULL + }, + { + "double_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double16*", "constantdouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "constantdouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double16*", "globaldouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "globaldouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double16*", "globalconstdouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "globalconstdouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double16*", "globalvolatiledouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "globalvolatiledouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double16*", "globalconstvolatiledouble16p", + NULL + }, + { + "double_vector16_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "globalconstvolatiledouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double16*", "localdouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "localdouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double16*", "localconstdouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "localconstdouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double16*", "localvolatiledouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "localvolatiledouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double16*", "localconstvolatiledouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "localconstvolatiledouble16restrictp", + NULL + }, + { + "double_vector16_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double16", "double16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double16", "constdouble16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double16", "privatedouble16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double16", "privateconstdouble16d", + NULL + }, +}; + + +// Support for optional half data type +const char * half_kernel_args[] = { + "#pragma OPENCL EXTENSION cl_khr_fp16 : enable\n" + "\n" + "kernel void half_scalar_p(constant half*constanthalfp,\n" + " constant half *restrict constanthalfrestrictp,\n" + " global half*globalhalfp,\n" + " global half *restrict globalhalfrestrictp,\n" + " global const half* globalconsthalfp,\n" + " global const half * restrict globalconsthalfrestrictp,\n" + " global volatile half*globalvolatilehalfp,\n" + " global volatile half *restrict globalvolatilehalfrestrictp,\n" + " global const volatile half* globalconstvolatilehalfp)\n" + "{}\n", + "\n" + "kernel void half_scalar_p2(global const volatile half * restrict globalconstvolatilehalfrestrictp,\n" + " local half*localhalfp,\n" + " local half *restrict localhalfrestrictp,\n" + " local const half* localconsthalfp,\n" + " local const half * restrict localconsthalfrestrictp,\n" + " local volatile half*localvolatilehalfp,\n" + " local volatile half *restrict localvolatilehalfrestrictp,\n" + " local const volatile half* localconstvolatilehalfp,\n" + " local const volatile half * restrict localconstvolatilehalfrestrictp)\n" + "{}\n", + "\n" + "kernel void half_vector2_p(constant half2*constanthalf2p,\n" + " constant half2 *restrict constanthalf2restrictp,\n" + " global half2*globalhalf2p,\n" + " global half2 *restrict globalhalf2restrictp,\n" + " global const half2* globalconsthalf2p,\n" + " global const half2 * restrict globalconsthalf2restrictp,\n" + " global volatile half2*globalvolatilehalf2p,\n" + " global volatile half2 *restrict globalvolatilehalf2restrictp,\n" + " global const volatile half2* globalconstvolatilehalf2p)\n" + "{}\n", + "\n" + "kernel void half_vector2_p2(global const volatile half2 * restrict globalconstvolatilehalf2restrictp,\n" + " local half2*localhalf2p,\n" + " local half2 *restrict localhalf2restrictp,\n" + " local const half2* localconsthalf2p,\n" + " local const half2 * restrict localconsthalf2restrictp,\n" + " local volatile half2*localvolatilehalf2p,\n" + " local volatile half2 *restrict localvolatilehalf2restrictp,\n" + " local const volatile half2* localconstvolatilehalf2p,\n" + " local const volatile half2 * restrict localconstvolatilehalf2restrictp)\n" + "{}\n", + "\n" + "kernel void half_vector3_p(constant half3*constanthalf3p,\n" + " constant half3 *restrict constanthalf3restrictp,\n" + " global half3*globalhalf3p,\n" + " global half3 *restrict globalhalf3restrictp,\n" + " global const half3* globalconsthalf3p,\n" + " global const half3 * restrict globalconsthalf3restrictp,\n" + " global volatile half3*globalvolatilehalf3p,\n" + " global volatile half3 *restrict globalvolatilehalf3restrictp,\n" + " global const volatile half3* globalconstvolatilehalf3p)\n" + "{}\n", + "\n" + "kernel void half_vector3_p2(global const volatile half3 * restrict globalconstvolatilehalf3restrictp,\n" + " local half3*localhalf3p,\n" + " local half3 *restrict localhalf3restrictp,\n" + " local const half3* localconsthalf3p,\n" + " local const half3 * restrict localconsthalf3restrictp,\n" + " local volatile half3*localvolatilehalf3p,\n" + " local volatile half3 *restrict localvolatilehalf3restrictp,\n" + " local const volatile half3* localconstvolatilehalf3p,\n" + " local const volatile half3 * restrict localconstvolatilehalf3restrictp)\n" + "{}\n", + "\n" + "kernel void half_vector4_p(constant half4*constanthalf4p,\n" + " constant half4 *restrict constanthalf4restrictp,\n" + " global half4*globalhalf4p,\n" + " global half4 *restrict globalhalf4restrictp,\n" + " global const half4* globalconsthalf4p,\n" + " global const half4 * restrict globalconsthalf4restrictp,\n" + " global volatile half4*globalvolatilehalf4p,\n" + " global volatile half4 *restrict globalvolatilehalf4restrictp,\n" + " global const volatile half4* globalconstvolatilehalf4p)\n" + "{}\n", + "\n" + "kernel void half_vector4_p2(global const volatile half4 * restrict globalconstvolatilehalf4restrictp,\n" + " local half4*localhalf4p,\n" + " local half4 *restrict localhalf4restrictp,\n" + " local const half4* localconsthalf4p,\n" + " local const half4 * restrict localconsthalf4restrictp,\n" + " local volatile half4*localvolatilehalf4p,\n" + " local volatile half4 *restrict localvolatilehalf4restrictp,\n" + " local const volatile half4* localconstvolatilehalf4p,\n" + " local const volatile half4 * restrict localconstvolatilehalf4restrictp)\n" + "{}\n", + "\n" + "kernel void half_vector8_p(constant half8*constanthalf8p,\n" + " constant half8 *restrict constanthalf8restrictp,\n" + " global half8*globalhalf8p,\n" + " global half8 *restrict globalhalf8restrictp,\n" + " global const half8* globalconsthalf8p,\n" + " global const half8 * restrict globalconsthalf8restrictp,\n" + " global volatile half8*globalvolatilehalf8p,\n" + " global volatile half8 *restrict globalvolatilehalf8restrictp,\n" + " global const volatile half8* globalconstvolatilehalf8p)\n" + "{}\n", + "\n" + "kernel void half_vector8_p2(global const volatile half8 * restrict globalconstvolatilehalf8restrictp,\n" + " local half8*localhalf8p,\n" + " local half8 *restrict localhalf8restrictp,\n" + " local const half8* localconsthalf8p,\n" + " local const half8 * restrict localconsthalf8restrictp,\n" + " local volatile half8*localvolatilehalf8p,\n" + " local volatile half8 *restrict localvolatilehalf8restrictp,\n" + " local const volatile half8* localconstvolatilehalf8p,\n" + " local const volatile half8 * restrict localconstvolatilehalf8restrictp)\n" + "{}\n", + "\n" + "kernel void half_vector16_p(constant half16*constanthalf16p,\n" + " constant half16 *restrict constanthalf16restrictp,\n" + " global half16*globalhalf16p,\n" + " global half16 *restrict globalhalf16restrictp,\n" + " global const half16* globalconsthalf16p,\n" + " global const half16 * restrict globalconsthalf16restrictp,\n" + " global volatile half16*globalvolatilehalf16p,\n" + " global volatile half16 *restrict globalvolatilehalf16restrictp,\n" + " global const volatile half16* globalconstvolatilehalf16p)\n" + "{}\n", + "\n" + "kernel void half_vector16_p2(global const volatile half16 * restrict globalconstvolatilehalf16restrictp,\n" + " local half16*localhalf16p,\n" + " local half16 *restrict localhalf16restrictp,\n" + " local const half16* localconsthalf16p,\n" + " local const half16 * restrict localconsthalf16restrictp,\n" + " local volatile half16*localvolatilehalf16p,\n" + " local volatile half16 *restrict localvolatilehalf16restrictp,\n" + " local const volatile half16* localconstvolatilehalf16p,\n" + " local const volatile half16 * restrict localconstvolatilehalf16restrictp)\n" + "{}\n", + "\n" +}; + +const char * half_arg_info[][77] = { + { + "half_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half*", "constanthalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "constanthalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half*", "globalhalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "globalhalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half*", "globalconsthalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "globalconsthalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half*", "globalvolatilehalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "globalvolatilehalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half*", "globalconstvolatilehalfp", + NULL + }, + { + "half_scalar_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "globalconstvolatilehalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half*", "localhalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "localhalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half*", "localconsthalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "localconsthalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half*", "localvolatilehalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "localvolatilehalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half*", "localconstvolatilehalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "localconstvolatilehalfrestrictp", + NULL + }, + { + "half_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half2*", "constanthalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "constanthalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half2*", "globalhalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "globalhalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half2*", "globalconsthalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "globalconsthalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half2*", "globalvolatilehalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "globalvolatilehalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half2*", "globalconstvolatilehalf2p", + NULL + }, + { + "half_vector2_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "globalconstvolatilehalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half2*", "localhalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "localhalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half2*", "localconsthalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "localconsthalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half2*", "localvolatilehalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "localvolatilehalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half2*", "localconstvolatilehalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "localconstvolatilehalf2restrictp", + NULL + }, + { + "half_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half3*", "constanthalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "constanthalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half3*", "globalhalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "globalhalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half3*", "globalconsthalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "globalconsthalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half3*", "globalvolatilehalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "globalvolatilehalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half3*", "globalconstvolatilehalf3p", + NULL + }, + { + "half_vector3_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "globalconstvolatilehalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half3*", "localhalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "localhalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half3*", "localconsthalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "localconsthalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half3*", "localvolatilehalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "localvolatilehalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half3*", "localconstvolatilehalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "localconstvolatilehalf3restrictp", + NULL + }, + { + "half_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half4*", "constanthalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "constanthalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half4*", "globalhalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "globalhalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half4*", "globalconsthalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "globalconsthalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half4*", "globalvolatilehalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "globalvolatilehalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half4*", "globalconstvolatilehalf4p", + NULL + }, + { + "half_vector4_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "globalconstvolatilehalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half4*", "localhalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "localhalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half4*", "localconsthalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "localconsthalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half4*", "localvolatilehalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "localvolatilehalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half4*", "localconstvolatilehalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "localconstvolatilehalf4restrictp", + NULL + }, + { + "half_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half8*", "constanthalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "constanthalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half8*", "globalhalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "globalhalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half8*", "globalconsthalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "globalconsthalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half8*", "globalvolatilehalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "globalvolatilehalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half8*", "globalconstvolatilehalf8p", + NULL + }, + { + "half_vector8_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "globalconstvolatilehalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half8*", "localhalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "localhalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half8*", "localconsthalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "localconsthalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half8*", "localvolatilehalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "localvolatilehalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half8*", "localconstvolatilehalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "localconstvolatilehalf8restrictp", + NULL + }, + { + "half_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half16*", "constanthalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "constanthalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half16*", "globalhalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "globalhalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half16*", "globalconsthalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "globalconsthalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half16*", "globalvolatilehalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "globalvolatilehalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half16*", "globalconstvolatilehalf16p", + NULL + }, + { + "half_vector16_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "globalconstvolatilehalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half16*", "localhalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "localhalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half16*", "localconsthalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "localconsthalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half16*", "localvolatilehalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "localvolatilehalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half16*", "localconstvolatilehalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "localconstvolatilehalf16restrictp", + NULL + }, +}; + +const char * long_kernel_args[] = { + "kernel void constant_scalar_p2(constant long* constantlongp,\n" + " constant ulong * constantulongp)\n" + "{}\n", + "kernel void constant_scalar_p3(constant unsigned long*constantunsignedlongp)\n" + "{}\n", + "\n" + "kernel void constant_scalar_restrict_p2(constant long*restrict constantlongrestrictp,\n" + " constant ulong *restrict constantulongrestrictp)\n" + "{}\n", + "kernel void constant_scalar_restrict_p3(constant unsigned long* restrict constantunsignedlongrestrictp)\n" + "{}\n", + "\n" + "kernel void global_scalar_p(global long* globallongp,\n" + " global ulong * globalulongp,\n" + " global unsigned long*globalunsignedlongp)\n" + "{}\n", + "\n" + "kernel void global_scalar_restrict_p(global long*restrict globallongrestrictp,\n" + " global ulong *restrict globalulongrestrictp,\n" + " global unsigned long* restrict globalunsignedlongrestrictp)\n" + "{}\n", + "\n" + "kernel void global_const_scalar_p(global const long* globalconstlongp,\n" + " global const ulong * globalconstulongp,\n" + " global const unsigned long*globalconstunsignedlongp)\n" + "{}\n", + "\n" + "kernel void global_const_scalar_restrict_p(global const long*restrict globalconstlongrestrictp,\n" + " global const ulong *restrict globalconstulongrestrictp,\n" + " global const unsigned long* restrict globalconstunsignedlongrestrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_scalar_p(global volatile long* globalvolatilelongp,\n" + " global volatile ulong * globalvolatileulongp,\n" + " global volatile unsigned long*globalvolatileunsignedlongp)\n" + "{}\n", + "\n" + "kernel void global_volatile_scalar_restrict_p(global volatile long*restrict globalvolatilelongrestrictp,\n" + " global volatile ulong *restrict globalvolatileulongrestrictp,\n" + " global volatile unsigned long* restrict globalvolatileunsignedlongrestrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_scalar_p(global const volatile long* globalconstvolatilelongp,\n" + " global const volatile ulong * globalconstvolatileulongp,\n" + " global const volatile unsigned long*globalconstvolatileunsignedlongp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_scalar_restrict_p(global const volatile long*restrict globalconstvolatilelongrestrictp,\n" + " global const volatile ulong *restrict globalconstvolatileulongrestrictp,\n" + " global const volatile unsigned long* restrict globalconstvolatileunsignedlongrestrictp)\n" + "{}\n", + "\n" + "kernel void local_scalar_p(local long* locallongp,\n" + " local ulong * localulongp,\n" + " local unsigned long*localunsignedlongp)\n" + "{}\n", + "\n" + "kernel void local_scalar_restrict_p(local long*restrict locallongrestrictp,\n" + " local ulong *restrict localulongrestrictp,\n" + " local unsigned long* restrict localunsignedlongrestrictp)\n" + "{}\n", + "\n" + "kernel void local_const_scalar_p(local const long* localconstlongp,\n" + " local const ulong * localconstulongp,\n" + " local const unsigned long*localconstunsignedlongp)\n" + "{}\n", + "\n" + "kernel void local_const_scalar_restrict_p(local const long*restrict localconstlongrestrictp,\n" + " local const ulong *restrict localconstulongrestrictp,\n" + " local const unsigned long* restrict localconstunsignedlongrestrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_scalar_p(local volatile long* localvolatilelongp,\n" + " local volatile ulong * localvolatileulongp,\n" + " local volatile unsigned long*localvolatileunsignedlongp)\n" + "{}\n", + "\n" + "kernel void local_volatile_scalar_restrict_p(local volatile long*restrict localvolatilelongrestrictp,\n" + " local volatile ulong *restrict localvolatileulongrestrictp,\n" + " local volatile unsigned long* restrict localvolatileunsignedlongrestrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_scalar_p(local const volatile long* localconstvolatilelongp,\n" + " local const volatile ulong * localconstvolatileulongp,\n" + " local const volatile unsigned long*localconstvolatileunsignedlongp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_scalar_restrict_p(local const volatile long*restrict localconstvolatilelongrestrictp,\n" + " local const volatile ulong *restrict localconstvolatileulongrestrictp,\n" + " local const volatile unsigned long* restrict localconstvolatileunsignedlongrestrictp)\n" + "{}\n", + "\n" + "kernel void scalar_d(long longd,\n" + " ulong ulongd,\n" + " unsigned long unsignedlongd)\n" + "{}\n", + "\n" + "kernel void const_scalar_d(const long constlongd,\n" + " const ulong constulongd,\n" + " const unsigned long constunsignedlongd)\n" + "{}\n", + "\n" + "kernel void private_scalar_d(private long privatelongd,\n" + " private ulong privateulongd,\n" + " private unsigned long privateunsignedlongd)\n" + "{}\n", + "\n" + "kernel void private_const_scalar_d(private const long privateconstlongd,\n" + " private const ulong privateconstulongd,\n" + " private const unsigned long privateconstunsignedlongd)\n" + "{}\n", + "\n" + "kernel void constant_vector2_p1(constant long2* constantlong2p,\n" + " constant ulong2 * constantulong2p)\n" + "{}\n", + "\n" + "kernel void constant_vector2_restrict_p1(constant long2 * restrict constantlong2restrictp,\n" + " constant ulong2*restrict constantulong2restrictp)\n" + "{}\n", + "\n" + "kernel void global_vector2_p(global long2* globallong2p,\n" + " global ulong2 * globalulong2p)\n" + "{}\n", + "\n" + "kernel void global_vector2_restrict_p(global long2 * restrict globallong2restrictp,\n" + " global ulong2*restrict globalulong2restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_vector2_p(global const long2*globalconstlong2p,\n" + " global const ulong2 *globalconstulong2p)\n" + "{}\n", + "\n" + "kernel void global_const_vector2_restrict_p(global const long2 *restrict globalconstlong2restrictp,\n" + " global const ulong2* restrict globalconstulong2restrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector2_p(global volatile long2* globalvolatilelong2p,\n" + " global volatile ulong2 * globalvolatileulong2p)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector2_restrict_p(global volatile long2 * restrict globalvolatilelong2restrictp,\n" + " global volatile ulong2*restrict globalvolatileulong2restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector2_p(global const volatile long2*globalconstvolatilelong2p,\n" + " global const volatile ulong2 *globalconstvolatileulong2p)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector2_restrict_p(global const volatile long2 *restrict globalconstvolatilelong2restrictp,\n" + " global const volatile ulong2* restrict globalconstvolatileulong2restrictp)\n" + "{}\n", + "\n" + "kernel void local_vector2_p(local long2* locallong2p,\n" + " local ulong2 * localulong2p)\n" + "{}\n", + "\n" + "kernel void local_vector2_restrict_p(local long2 * restrict locallong2restrictp,\n" + " local ulong2*restrict localulong2restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_vector2_p(local const long2*localconstlong2p,\n" + " local const ulong2 *localconstulong2p)\n" + "{}\n", + "\n" + "kernel void local_const_vector2_restrict_p(local const long2 *restrict localconstlong2restrictp,\n" + " local const ulong2* restrict localconstulong2restrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector2_p(local volatile long2* localvolatilelong2p,\n" + " local volatile ulong2 * localvolatileulong2p)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector2_restrict_p(local volatile long2 * restrict localvolatilelong2restrictp,\n" + " local volatile ulong2*restrict localvolatileulong2restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector2_p(local const volatile long2*localconstvolatilelong2p,\n" + " local const volatile ulong2 *localconstvolatileulong2p)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector2_restrict_p(local const volatile long2 *restrict localconstvolatilelong2restrictp,\n" + " local const volatile ulong2* restrict localconstvolatileulong2restrictp)\n" + "{}\n", + "\n" + "kernel void vector2_d(long2 long2d,\n" + " ulong2 ulong2d)\n" + "{}\n", + "\n" + "kernel void const_vector2_d(const long2 constlong2d,\n" + " const ulong2 constulong2d)\n" + "{}\n", + "\n" + "kernel void private_vector2_d(private long2 privatelong2d,\n" + " private ulong2 privateulong2d)\n" + "{}\n", + "\n" + "kernel void private_const_vector2_d(private const long2 privateconstlong2d,\n" + " private const ulong2 privateconstulong2d)\n" + "{}\n", + "\n" + "kernel void constant_vector3_p1(constant long3* constantlong3p,\n" + " constant ulong3 * constantulong3p)\n" + "{}\n", + "\n" + "kernel void constant_vector3_restrict_p1(constant long3 * restrict constantlong3restrictp,\n" + " constant ulong3*restrict constantulong3restrictp)\n" + "{}\n", + "\n" + "kernel void global_vector3_p(global long3* globallong3p,\n" + " global ulong3 * globalulong3p)\n" + "{}\n", + "\n" + "kernel void global_vector3_restrict_p(global long3 * restrict globallong3restrictp,\n" + " global ulong3*restrict globalulong3restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_vector3_p(global const long3*globalconstlong3p,\n" + " global const ulong3 *globalconstulong3p)\n" + "{}\n", + "\n" + "kernel void global_const_vector3_restrict_p(global const long3 *restrict globalconstlong3restrictp,\n" + " global const ulong3* restrict globalconstulong3restrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector3_p(global volatile long3* globalvolatilelong3p,\n" + " global volatile ulong3 * globalvolatileulong3p)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector3_restrict_p(global volatile long3 * restrict globalvolatilelong3restrictp,\n" + " global volatile ulong3*restrict globalvolatileulong3restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector3_p(global const volatile long3*globalconstvolatilelong3p,\n" + " global const volatile ulong3 *globalconstvolatileulong3p)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector3_restrict_p(global const volatile long3 *restrict globalconstvolatilelong3restrictp,\n" + " global const volatile ulong3* restrict globalconstvolatileulong3restrictp)\n" + "{}\n", + "\n" + "kernel void local_vector3_p(local long3* locallong3p,\n" + " local ulong3 * localulong3p)\n" + "{}\n", + "\n" + "kernel void local_vector3_restrict_p(local long3 * restrict locallong3restrictp,\n" + " local ulong3*restrict localulong3restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_vector3_p(local const long3*localconstlong3p,\n" + " local const ulong3 *localconstulong3p)\n" + "{}\n", + "\n" + "kernel void local_const_vector3_restrict_p(local const long3 *restrict localconstlong3restrictp,\n" + " local const ulong3* restrict localconstulong3restrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector3_p(local volatile long3* localvolatilelong3p,\n" + " local volatile ulong3 * localvolatileulong3p)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector3_restrict_p(local volatile long3 * restrict localvolatilelong3restrictp,\n" + " local volatile ulong3*restrict localvolatileulong3restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector3_p(local const volatile long3*localconstvolatilelong3p,\n" + " local const volatile ulong3 *localconstvolatileulong3p)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector3_restrict_p(local const volatile long3 *restrict localconstvolatilelong3restrictp,\n" + " local const volatile ulong3* restrict localconstvolatileulong3restrictp)\n" + "{}\n", + "\n" + "kernel void vector3_d(long3 long3d,\n" + " ulong3 ulong3d)\n" + "{}\n", + "\n" + "kernel void const_vector3_d(const long3 constlong3d,\n" + " const ulong3 constulong3d)\n" + "{}\n", + "\n" + "kernel void private_vector3_d(private long3 privatelong3d,\n" + " private ulong3 privateulong3d)\n" + "{}\n", + "\n" + "kernel void private_const_vector3_d(private const long3 privateconstlong3d,\n" + " private const ulong3 privateconstulong3d)\n" + "{}\n", + "\n" + "kernel void constant_vector4_p1(constant long4* constantlong4p,\n" + " constant ulong4 * constantulong4p)\n" + "{}\n", + "\n" + "kernel void constant_vector4_restrict_p1(constant long4 * restrict constantlong4restrictp,\n" + " constant ulong4*restrict constantulong4restrictp)\n" + "{}\n", + "\n" + "kernel void global_vector4_p(global long4* globallong4p,\n" + " global ulong4 * globalulong4p)\n" + "{}\n", + "\n" + "kernel void global_vector4_restrict_p(global long4 * restrict globallong4restrictp,\n" + " global ulong4*restrict globalulong4restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_vector4_p(global const long4*globalconstlong4p,\n" + " global const ulong4 *globalconstulong4p)\n" + "{}\n", + "\n" + "kernel void global_const_vector4_restrict_p(global const long4 *restrict globalconstlong4restrictp,\n" + " global const ulong4* restrict globalconstulong4restrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector4_p(global volatile long4* globalvolatilelong4p,\n" + " global volatile ulong4 * globalvolatileulong4p)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector4_restrict_p(global volatile long4 * restrict globalvolatilelong4restrictp,\n" + " global volatile ulong4*restrict globalvolatileulong4restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector4_p(global const volatile long4*globalconstvolatilelong4p,\n" + " global const volatile ulong4 *globalconstvolatileulong4p)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector4_restrict_p(global const volatile long4 *restrict globalconstvolatilelong4restrictp,\n" + " global const volatile ulong4* restrict globalconstvolatileulong4restrictp)\n" + "{}\n", + "\n" + "kernel void local_vector4_p(local long4* locallong4p,\n" + " local ulong4 * localulong4p)\n" + "{}\n", + "\n" + "kernel void local_vector4_restrict_p(local long4 * restrict locallong4restrictp,\n" + " local ulong4*restrict localulong4restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_vector4_p(local const long4*localconstlong4p,\n" + " local const ulong4 *localconstulong4p)\n" + "{}\n", + "\n" + "kernel void local_const_vector4_restrict_p(local const long4 *restrict localconstlong4restrictp,\n" + " local const ulong4* restrict localconstulong4restrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector4_p(local volatile long4* localvolatilelong4p,\n" + " local volatile ulong4 * localvolatileulong4p)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector4_restrict_p(local volatile long4 * restrict localvolatilelong4restrictp,\n" + " local volatile ulong4*restrict localvolatileulong4restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector4_p(local const volatile long4*localconstvolatilelong4p,\n" + " local const volatile ulong4 *localconstvolatileulong4p)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector4_restrict_p(local const volatile long4 *restrict localconstvolatilelong4restrictp,\n" + " local const volatile ulong4* restrict localconstvolatileulong4restrictp)\n" + "{}\n", + "\n" + "kernel void vector4_d(long4 long4d,\n" + " ulong4 ulong4d)\n" + "{}\n", + "\n" + "kernel void const_vector4_d(const long4 constlong4d,\n" + " const ulong4 constulong4d)\n" + "{}\n", + "\n" + "kernel void private_vector4_d(private long4 privatelong4d,\n" + " private ulong4 privateulong4d)\n" + "{}\n", + "\n" + "kernel void private_const_vector4_d(private const long4 privateconstlong4d,\n" + " private const ulong4 privateconstulong4d)\n" + "{}\n", + "\n" + "kernel void constant_vector8_p1(constant long8* constantlong8p,\n" + " constant ulong8 * constantulong8p)\n" + "{}\n", + "\n" + "kernel void constant_vector8_restrict_p1(constant long8 * restrict constantlong8restrictp,\n" + " constant ulong8*restrict constantulong8restrictp)\n" + "{}\n", + "\n" + "kernel void global_vector8_p(global long8* globallong8p,\n" + " global ulong8 * globalulong8p)\n" + "{}\n", + "\n" + "kernel void global_vector8_restrict_p(global long8 * restrict globallong8restrictp,\n" + " global ulong8*restrict globalulong8restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_vector8_p(global const long8*globalconstlong8p,\n" + " global const ulong8 *globalconstulong8p)\n" + "{}\n", + "\n" + "kernel void global_const_vector8_restrict_p(global const long8 *restrict globalconstlong8restrictp,\n" + " global const ulong8* restrict globalconstulong8restrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector8_p(global volatile long8* globalvolatilelong8p,\n" + " global volatile ulong8 * globalvolatileulong8p)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector8_restrict_p(global volatile long8 * restrict globalvolatilelong8restrictp,\n" + " global volatile ulong8*restrict globalvolatileulong8restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector8_p(global const volatile long8*globalconstvolatilelong8p,\n" + " global const volatile ulong8 *globalconstvolatileulong8p)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector8_restrict_p(global const volatile long8 *restrict globalconstvolatilelong8restrictp,\n" + " global const volatile ulong8* restrict globalconstvolatileulong8restrictp)\n" + "{}\n", + "\n" + "kernel void local_vector8_p(local long8* locallong8p,\n" + " local ulong8 * localulong8p)\n" + "{}\n", + "\n" + "kernel void local_vector8_restrict_p(local long8 * restrict locallong8restrictp,\n" + " local ulong8*restrict localulong8restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_vector8_p(local const long8*localconstlong8p,\n" + " local const ulong8 *localconstulong8p)\n" + "{}\n", + "\n" + "kernel void local_const_vector8_restrict_p(local const long8 *restrict localconstlong8restrictp,\n" + " local const ulong8* restrict localconstulong8restrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector8_p(local volatile long8* localvolatilelong8p,\n" + " local volatile ulong8 * localvolatileulong8p)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector8_restrict_p(local volatile long8 * restrict localvolatilelong8restrictp,\n" + " local volatile ulong8*restrict localvolatileulong8restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector8_p(local const volatile long8*localconstvolatilelong8p,\n" + " local const volatile ulong8 *localconstvolatileulong8p)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector8_restrict_p(local const volatile long8 *restrict localconstvolatilelong8restrictp,\n" + " local const volatile ulong8* restrict localconstvolatileulong8restrictp)\n" + "{}\n", + "\n" + "kernel void vector8_d(long8 long8d,\n" + " ulong8 ulong8d)\n" + "{}\n", + "\n" + "kernel void const_vector8_d(const long8 constlong8d,\n" + " const ulong8 constulong8d)\n" + "{}\n", + "\n" + "kernel void private_vector8_d(private long8 privatelong8d,\n" + " private ulong8 privateulong8d)\n" + "{}\n", + "\n" + "kernel void private_const_vector8_d(private const long8 privateconstlong8d,\n" + " private const ulong8 privateconstulong8d)\n" + "{}\n", + "\n" + "kernel void constant_vector16_p1(constant long16* constantlong16p,\n" + " constant ulong16 * constantulong16p)\n" + "{}\n", + "\n" + "kernel void constant_vector16_restrict_p1(constant long16 * restrict constantlong16restrictp,\n" + " constant ulong16*restrict constantulong16restrictp)\n" + "{}\n", + "\n" + "kernel void global_vector16_p(global long16* globallong16p,\n" + " global ulong16 * globalulong16p)\n" + "{}\n", + "\n" + "kernel void global_vector16_restrict_p(global long16 * restrict globallong16restrictp,\n" + " global ulong16*restrict globalulong16restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_vector16_p(global const long16*globalconstlong16p,\n" + " global const ulong16 *globalconstulong16p)\n" + "{}\n", + "\n" + "kernel void global_const_vector16_restrict_p(global const long16 *restrict globalconstlong16restrictp,\n" + " global const ulong16* restrict globalconstulong16restrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector16_p(global volatile long16* globalvolatilelong16p,\n" + " global volatile ulong16 * globalvolatileulong16p)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector16_restrict_p(global volatile long16 * restrict globalvolatilelong16restrictp,\n" + " global volatile ulong16*restrict globalvolatileulong16restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector16_p(global const volatile long16*globalconstvolatilelong16p,\n" + " global const volatile ulong16 *globalconstvolatileulong16p)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector16_restrict_p(global const volatile long16 *restrict globalconstvolatilelong16restrictp,\n" + " global const volatile ulong16* restrict globalconstvolatileulong16restrictp)\n" + "{}\n", + "\n" + "kernel void local_vector16_p(local long16* locallong16p,\n" + " local ulong16 * localulong16p)\n" + "{}\n", + "\n" + "kernel void local_vector16_restrict_p(local long16 * restrict locallong16restrictp,\n" + " local ulong16*restrict localulong16restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_vector16_p(local const long16*localconstlong16p,\n" + " local const ulong16 *localconstulong16p)\n" + "{}\n", + "\n" + "kernel void local_const_vector16_restrict_p(local const long16 *restrict localconstlong16restrictp,\n" + " local const ulong16* restrict localconstulong16restrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector16_p(local volatile long16* localvolatilelong16p,\n" + " local volatile ulong16 * localvolatileulong16p)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector16_restrict_p(local volatile long16 * restrict localvolatilelong16restrictp,\n" + " local volatile ulong16*restrict localvolatileulong16restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector16_p(local const volatile long16*localconstvolatilelong16p,\n" + " local const volatile ulong16 *localconstvolatileulong16p)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector16_restrict_p(local const volatile long16 *restrict localconstvolatilelong16restrictp,\n" + " local const volatile ulong16* restrict localconstvolatileulong16restrictp)\n" + "{}\n", + "\n" + "kernel void vector16_d(long16 long16d,\n" + " ulong16 ulong16d)\n" + "{}\n", + "\n" + "kernel void const_vector16_d(const long16 constlong16d,\n" + " const ulong16 constulong16d)\n" + "{}\n", + "\n" + "kernel void private_vector16_d(private long16 privatelong16d,\n" + " private ulong16 privateulong16d)\n" + "{}\n", + "\n" + "kernel void private_const_vector16_d(private const long16 privateconstlong16d,\n" + " private const ulong16 privateconstulong16d)\n" + "{}\n", + "\n" +}; + +const char * long_arg_info[][72] = { + // The minimum value of CL_DEVICE_MAX_CONSTANT_ARGS is 4 + { + "constant_scalar_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long*", "constantlongp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong*", "constantulongp", + NULL + }, + { + "constant_scalar_p3", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong*", "constantunsignedlongp", + NULL + }, + { + "constant_scalar_restrict_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "constantlongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "constantulongrestrictp", + NULL + }, + { + "constant_scalar_restrict_p3", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "constantunsignedlongrestrictp", + NULL + }, + { + "global_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long*", "globallongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong*", "globalulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong*", "globalunsignedlongp", + NULL + }, + { + "global_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "globallongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalunsignedlongrestrictp", + NULL + }, + { + "global_const_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long*", "globalconstlongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong*", "globalconstulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong*", "globalconstunsignedlongp", + NULL + }, + { + "global_const_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "globalconstlongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalconstulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalconstunsignedlongrestrictp", + NULL + }, + { + "global_volatile_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long*", "globalvolatilelongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "globalvolatileulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "globalvolatileunsignedlongp", + NULL + }, + { + "global_volatile_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "globalvolatilelongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalvolatileulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalvolatileunsignedlongrestrictp", + NULL + }, + { + "global_const_volatile_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long*", "globalconstvolatilelongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "globalconstvolatileulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "globalconstvolatileunsignedlongp", + NULL + }, + { + "global_const_volatile_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "globalconstvolatilelongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalconstvolatileulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalconstvolatileunsignedlongrestrictp", + NULL + }, + { + "local_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long*", "locallongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong*", "localulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong*", "localunsignedlongp", + NULL + }, + { + "local_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "locallongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localunsignedlongrestrictp", + NULL + }, + { + "local_const_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long*", "localconstlongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong*", "localconstulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong*", "localconstunsignedlongp", + NULL + }, + { + "local_const_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "localconstlongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localconstulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localconstunsignedlongrestrictp", + NULL + }, + { + "local_volatile_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long*", "localvolatilelongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "localvolatileulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "localvolatileunsignedlongp", + NULL + }, + { + "local_volatile_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "localvolatilelongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localvolatileulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localvolatileunsignedlongrestrictp", + NULL + }, + { + "local_const_volatile_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long*", "localconstvolatilelongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "localconstvolatileulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "localconstvolatileunsignedlongp", + NULL + }, + { + "local_const_volatile_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "localconstvolatilelongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localconstvolatileulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localconstvolatileunsignedlongrestrictp", + NULL + }, + { + "scalar_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long", "longd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "ulongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "unsignedlongd", + NULL + }, + { + "const_scalar_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long", "constlongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "constulongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "constunsignedlongd", + NULL + }, + { + "private_scalar_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long", "privatelongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "privateulongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "privateunsignedlongd", + NULL + }, + { + "private_const_scalar_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long", "privateconstlongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "privateconstulongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "privateconstunsignedlongd", + NULL + }, + { + "constant_vector2_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long2*", "constantlong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong2*", "constantulong2p", + NULL + }, + { + "constant_vector2_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "constantlong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "constantulong2restrictp", + NULL + }, + { + "global_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long2*", "globallong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong2*", "globalulong2p", + NULL + }, + { + "global_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "globallong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "globalulong2restrictp", + NULL + }, + { + "global_const_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long2*", "globalconstlong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong2*", "globalconstulong2p", + NULL + }, + { + "global_const_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "globalconstlong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "globalconstulong2restrictp", + NULL + }, + { + "global_volatile_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long2*", "globalvolatilelong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong2*", "globalvolatileulong2p", + NULL + }, + { + "global_volatile_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "globalvolatilelong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "globalvolatileulong2restrictp", + NULL + }, + { + "global_const_volatile_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long2*", "globalconstvolatilelong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong2*", "globalconstvolatileulong2p", + NULL + }, + { + "global_const_volatile_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "globalconstvolatilelong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "globalconstvolatileulong2restrictp", + NULL + }, + { + "local_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long2*", "locallong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong2*", "localulong2p", + NULL + }, + { + "local_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "locallong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "localulong2restrictp", + NULL + }, + { + "local_const_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long2*", "localconstlong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong2*", "localconstulong2p", + NULL + }, + { + "local_const_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "localconstlong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "localconstulong2restrictp", + NULL + }, + { + "local_volatile_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long2*", "localvolatilelong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong2*", "localvolatileulong2p", + NULL + }, + { + "local_volatile_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "localvolatilelong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "localvolatileulong2restrictp", + NULL + }, + { + "local_const_volatile_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long2*", "localconstvolatilelong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong2*", "localconstvolatileulong2p", + NULL + }, + { + "local_const_volatile_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "localconstvolatilelong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "localconstvolatileulong2restrictp", + NULL + }, + { + "vector2_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long2", "long2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong2", "ulong2d", + NULL + }, + { + "const_vector2_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long2", "constlong2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong2", "constulong2d", + NULL + }, + { + "private_vector2_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long2", "privatelong2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong2", "privateulong2d", + NULL + }, + { + "private_const_vector2_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long2", "privateconstlong2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong2", "privateconstulong2d", + NULL + }, + { + "constant_vector3_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long3*", "constantlong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong3*", "constantulong3p", + NULL + }, + { + "constant_vector3_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "constantlong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "constantulong3restrictp", + NULL + }, + { + "global_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long3*", "globallong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong3*", "globalulong3p", + NULL + }, + { + "global_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "globallong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "globalulong3restrictp", + NULL + }, + { + "global_const_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long3*", "globalconstlong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong3*", "globalconstulong3p", + NULL + }, + { + "global_const_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "globalconstlong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "globalconstulong3restrictp", + NULL + }, + { + "global_volatile_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long3*", "globalvolatilelong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong3*", "globalvolatileulong3p", + NULL + }, + { + "global_volatile_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "globalvolatilelong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "globalvolatileulong3restrictp", + NULL + }, + { + "global_const_volatile_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long3*", "globalconstvolatilelong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong3*", "globalconstvolatileulong3p", + NULL + }, + { + "global_const_volatile_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "globalconstvolatilelong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "globalconstvolatileulong3restrictp", + NULL + }, + { + "local_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long3*", "locallong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong3*", "localulong3p", + NULL + }, + { + "local_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "locallong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "localulong3restrictp", + NULL + }, + { + "local_const_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long3*", "localconstlong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong3*", "localconstulong3p", + NULL + }, + { + "local_const_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "localconstlong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "localconstulong3restrictp", + NULL + }, + { + "local_volatile_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long3*", "localvolatilelong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong3*", "localvolatileulong3p", + NULL + }, + { + "local_volatile_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "localvolatilelong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "localvolatileulong3restrictp", + NULL + }, + { + "local_const_volatile_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long3*", "localconstvolatilelong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong3*", "localconstvolatileulong3p", + NULL + }, + { + "local_const_volatile_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "localconstvolatilelong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "localconstvolatileulong3restrictp", + NULL + }, + { + "vector3_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long3", "long3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong3", "ulong3d", + NULL + }, + { + "const_vector3_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long3", "constlong3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong3", "constulong3d", + NULL + }, + { + "private_vector3_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long3", "privatelong3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong3", "privateulong3d", + NULL + }, + { + "private_const_vector3_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long3", "privateconstlong3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong3", "privateconstulong3d", + NULL + }, + { + "constant_vector4_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long4*", "constantlong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong4*", "constantulong4p", + NULL + }, + { + "constant_vector4_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "constantlong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "constantulong4restrictp", + NULL + }, + { + "global_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long4*", "globallong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong4*", "globalulong4p", + NULL + }, + { + "global_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "globallong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "globalulong4restrictp", + NULL + }, + { + "global_const_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long4*", "globalconstlong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong4*", "globalconstulong4p", + NULL + }, + { + "global_const_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "globalconstlong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "globalconstulong4restrictp", + NULL + }, + { + "global_volatile_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long4*", "globalvolatilelong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong4*", "globalvolatileulong4p", + NULL + }, + { + "global_volatile_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "globalvolatilelong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "globalvolatileulong4restrictp", + NULL + }, + { + "global_const_volatile_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long4*", "globalconstvolatilelong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong4*", "globalconstvolatileulong4p", + NULL + }, + { + "global_const_volatile_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "globalconstvolatilelong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "globalconstvolatileulong4restrictp", + NULL + }, + { + "local_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long4*", "locallong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong4*", "localulong4p", + NULL + }, + { + "local_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "locallong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "localulong4restrictp", + NULL + }, + { + "local_const_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long4*", "localconstlong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong4*", "localconstulong4p", + NULL + }, + { + "local_const_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "localconstlong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "localconstulong4restrictp", + NULL + }, + { + "local_volatile_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long4*", "localvolatilelong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong4*", "localvolatileulong4p", + NULL + }, + { + "local_volatile_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "localvolatilelong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "localvolatileulong4restrictp", + NULL + }, + { + "local_const_volatile_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long4*", "localconstvolatilelong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong4*", "localconstvolatileulong4p", + NULL + }, + { + "local_const_volatile_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "localconstvolatilelong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "localconstvolatileulong4restrictp", + NULL + }, + { + "vector4_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long4", "long4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong4", "ulong4d", + NULL + }, + { + "const_vector4_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long4", "constlong4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong4", "constulong4d", + NULL + }, + { + "private_vector4_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long4", "privatelong4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong4", "privateulong4d", + NULL + }, + { + "private_const_vector4_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long4", "privateconstlong4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong4", "privateconstulong4d", + NULL + }, + { + "constant_vector8_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long8*", "constantlong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong8*", "constantulong8p", + NULL + }, + { + "constant_vector8_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "constantlong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "constantulong8restrictp", + NULL + }, + { + "global_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long8*", "globallong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong8*", "globalulong8p", + NULL + }, + { + "global_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "globallong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "globalulong8restrictp", + NULL + }, + { + "global_const_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long8*", "globalconstlong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong8*", "globalconstulong8p", + NULL + }, + { + "global_const_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "globalconstlong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "globalconstulong8restrictp", + NULL + }, + { + "global_volatile_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long8*", "globalvolatilelong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong8*", "globalvolatileulong8p", + NULL + }, + { + "global_volatile_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "globalvolatilelong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "globalvolatileulong8restrictp", + NULL + }, + { + "global_const_volatile_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long8*", "globalconstvolatilelong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong8*", "globalconstvolatileulong8p", + NULL + }, + { + "global_const_volatile_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "globalconstvolatilelong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "globalconstvolatileulong8restrictp", + NULL + }, + { + "local_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long8*", "locallong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong8*", "localulong8p", + NULL + }, + { + "local_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "locallong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "localulong8restrictp", + NULL + }, + { + "local_const_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long8*", "localconstlong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong8*", "localconstulong8p", + NULL + }, + { + "local_const_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "localconstlong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "localconstulong8restrictp", + NULL + }, + { + "local_volatile_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long8*", "localvolatilelong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong8*", "localvolatileulong8p", + NULL + }, + { + "local_volatile_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "localvolatilelong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "localvolatileulong8restrictp", + NULL + }, + { + "local_const_volatile_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long8*", "localconstvolatilelong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong8*", "localconstvolatileulong8p", + NULL + }, + { + "local_const_volatile_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "localconstvolatilelong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "localconstvolatileulong8restrictp", + NULL + }, + { + "vector8_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long8", "long8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong8", "ulong8d", + NULL + }, + { + "const_vector8_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long8", "constlong8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong8", "constulong8d", + NULL + }, + { + "private_vector8_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long8", "privatelong8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong8", "privateulong8d", + NULL + }, + { + "private_const_vector8_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long8", "privateconstlong8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong8", "privateconstulong8d", + NULL + }, + { + "constant_vector16_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long16*", "constantlong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong16*", "constantulong16p", + NULL + }, + { + "constant_vector16_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "constantlong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "constantulong16restrictp", + NULL + }, + { + "global_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long16*", "globallong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong16*", "globalulong16p", + NULL + }, + { + "global_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "globallong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "globalulong16restrictp", + NULL + }, + { + "global_const_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long16*", "globalconstlong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong16*", "globalconstulong16p", + NULL + }, + { + "global_const_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "globalconstlong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "globalconstulong16restrictp", + NULL + }, + { + "global_volatile_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long16*", "globalvolatilelong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong16*", "globalvolatileulong16p", + NULL + }, + { + "global_volatile_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "globalvolatilelong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "globalvolatileulong16restrictp", + NULL + }, + { + "global_const_volatile_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long16*", "globalconstvolatilelong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong16*", "globalconstvolatileulong16p", + NULL + }, + { + "global_const_volatile_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "globalconstvolatilelong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "globalconstvolatileulong16restrictp", + NULL + }, + { + "local_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long16*", "locallong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong16*", "localulong16p", + NULL + }, + { + "local_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "locallong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "localulong16restrictp", + NULL + }, + { + "local_const_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long16*", "localconstlong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong16*", "localconstulong16p", + NULL + }, + { + "local_const_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "localconstlong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "localconstulong16restrictp", + NULL + }, + { + "local_volatile_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long16*", "localvolatilelong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong16*", "localvolatileulong16p", + NULL + }, + { + "local_volatile_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "localvolatilelong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "localvolatileulong16restrictp", + NULL + }, + { + "local_const_volatile_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long16*", "localconstvolatilelong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong16*", "localconstvolatileulong16p", + NULL + }, + { + "local_const_volatile_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "localconstvolatilelong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "localconstvolatileulong16restrictp", + NULL + }, + { + "vector16_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long16", "long16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong16", "ulong16d", + NULL + }, + { + "const_vector16_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long16", "constlong16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong16", "constulong16d", + NULL + }, + { + "private_vector16_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long16", "privatelong16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong16", "privateulong16d", + NULL + }, + { + "private_const_vector16_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long16", "privateconstlong16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong16", "privateconstulong16d", + NULL + }, +}; + +template +int test(cl_device_id deviceID, cl_context context, kernel_args_t kernel_args, cl_uint lines_count, arg_info_t arg_info, size_t total_kernels_in_program) { + + cl_program program; + cl_kernel kernel; + const size_t max_name_len = 512; + cl_char name[ max_name_len ]; + cl_uint arg_count, numArgs; + size_t i, j, size; + int error; + + program = clCreateProgramWithSource( context, lines_count, kernel_args, NULL, &error ); + if ( program == NULL || error != CL_SUCCESS ) + { + print_error( error, "Unable to create required arguments kernel program" ); + return -1; + } + + // Compile the program + log_info( "Building kernels...\n" ); + clBuildProgram( program, 1, &deviceID, "-cl-kernel-arg-info", NULL, NULL ); + + // check for build errors and exit if things didn't work + size_t size_ret; + cl_build_status build_status; + error = clGetProgramBuildInfo(program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof(build_status), &build_status, &size_ret); + test_error( error, "Unable to query build status" ); + if (build_status == CL_BUILD_ERROR) { + printf("CL_PROGRAM_BUILD_STATUS=%d\n", (int) build_status); + error = clGetProgramBuildInfo(program, deviceID, CL_PROGRAM_BUILD_LOG, 0, NULL, &size_ret); + test_error( error, "Unable to get build log size" ); + char *build_log = (char *)malloc(size_ret); + error = clGetProgramBuildInfo(program,deviceID, CL_PROGRAM_BUILD_LOG, size_ret, build_log, &size_ret); + test_error( error, "Unable to get build log" ); + printf("CL_PROGRAM_BUILD_LOG:\n%s\n", build_log); + printf("CL_BUILD_ERROR. exiting\n"); + free(build_log); + return -1; + } + + // Lookup the number of kernels in the program. + log_info( "Testing kernels...\n" ); + size_t total_kernels = 0; + error = clGetProgramInfo( program, CL_PROGRAM_NUM_KERNELS, sizeof( size_t ), &total_kernels, NULL ); + test_error( error, "Unable to get program info num kernels" ); + + if ( total_kernels != total_kernels_in_program ) + { + print_error( error, "Program did not build all kernels" ); + return -1; + } + + // Lookup the kernel names. + size_t kernel_names_len = 0; + error = clGetProgramInfo( program, CL_PROGRAM_KERNEL_NAMES, 0, NULL, &kernel_names_len ); + test_error( error, "Unable to get length of kernel names list." ); + + size_t expected_kernel_names_len = 0; + for ( i = 0; i < total_kernels; ++i ) + { + expected_kernel_names_len += 1 + strlen( arg_info[ i ][ 0 ] ); + } + if ( kernel_names_len != expected_kernel_names_len ) + { + log_error( "Kernel names string is not the right length, expected %d, got %d\n", (int) expected_kernel_names_len, (int) kernel_names_len ); + return -1; + } + + const size_t len = ( kernel_names_len + 1 ) * sizeof( char ); + char* kernel_names = (char*) malloc( len ); + error = clGetProgramInfo( program, CL_PROGRAM_KERNEL_NAMES, len, kernel_names, &kernel_names_len ); + test_error( error, "Unable to get kernel names list." ); + + // Check to see if the kernel name array is null terminated. + if ( kernel_names[ kernel_names_len - 1 ] != '\0' ) + { + free( kernel_names ); + print_error( error, "Kernel name list was not null terminated" ); + return -1; + } + + // Check to see if the correct kernel name string was returned. + // Does the string contain each expected kernel name? + for ( i = 0; i < total_kernels; ++i ) + if ( !strstr( kernel_names, arg_info[ i ][ 0 ] ) ) + break; + if ( i != total_kernels ) + { + log_error( "Kernel names string is missing \"%s\"\n", arg_info[ i ][ 0 ] ); + free( kernel_names ); + return -1; + } + + // Are the kernel names delimited by ';'? + if ( !strtok( kernel_names, ";" ) ) + { + error = -1; + } + else + { + for ( i = 1; i < total_kernels; ++i ) + { + if ( !strtok( NULL, ";" ) ) + { + error = -1; + } + } + } + if ( error ) + { + log_error( "Kernel names string was not properly delimited by ';'\n" ); + free( kernel_names ); + return -1; + } + free( kernel_names ); + + // Create kernel objects and query them. + int rc = 0; + for ( i = 0; i < total_kernels; ++i ) + { + int kernel_rc = 0; + const char* kernel_name = arg_info[ i ][ 0 ]; + kernel = clCreateKernel( program, kernel_name, &error ); + if( kernel == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Could not get kernel: %s\n", kernel_name ); + kernel_rc = -1; + } + + if(kernel_rc == 0) + { + // Determine the expected number of arguments. + arg_count = 0; + while (arg_info[ i ][ (ARG_INFO_FIELD_COUNT * arg_count) + 1 ] != NULL) + ++arg_count; + + // Try to get the number of arguments. + error = clGetKernelInfo( kernel, CL_KERNEL_NUM_ARGS, 0, NULL, &size ); + test_error( error, "Unable to get kernel arg count param size" ); + if( size != sizeof( numArgs ) ) + { + log_error( "ERROR: Kernel arg count param returns invalid size (expected %d, got %d) for kernel: %s\n", (int)sizeof( numArgs ), (int)size, kernel_name ); + kernel_rc = -1; + } + } + + + if(kernel_rc == 0) + { + error = clGetKernelInfo( kernel, CL_KERNEL_NUM_ARGS, sizeof( numArgs ), &numArgs, NULL ); + test_error( error, "Unable to get kernel arg count" ); + if( numArgs != arg_count ) + { + log_error( "ERROR: Kernel arg count returned invalid value (expected %d, got %d) for kernel: %s\n", arg_count, numArgs, kernel_name ); + kernel_rc = -1; + } + } + + if(kernel_rc == 0) + { + for ( j = 0; j < numArgs; ++j ) + { + + int arg_rc = 0; + cl_kernel_arg_address_qualifier expected_address_qualifier = (cl_kernel_arg_address_qualifier)(uintptr_t)arg_info[ i ][ (ARG_INFO_FIELD_COUNT * j) + ARG_INFO_ADDR_OFFSET ]; + cl_kernel_arg_access_qualifier expected_access_qualifier = (cl_kernel_arg_access_qualifier)(uintptr_t)arg_info[ i ][ (ARG_INFO_FIELD_COUNT * j) + ARG_INFO_ACCESS_OFFSET ]; + cl_kernel_arg_type_qualifier expected_type_qualifier = (cl_kernel_arg_type_qualifier)(uintptr_t)arg_info[ i ][ (ARG_INFO_FIELD_COUNT * j) + ARG_INFO_TYPE_QUAL_OFFSET ]; + const char* expected_type_name = arg_info[ i ][ (ARG_INFO_FIELD_COUNT * j) + ARG_INFO_TYPE_NAME_OFFSET ]; + const char* expected_arg_name = arg_info[ i ][ (ARG_INFO_FIELD_COUNT * j) + ARG_INFO_ARG_NAME_OFFSET ]; + + // Try to get the address qualifier of each argument. + cl_kernel_arg_address_qualifier address_qualifier = 0; + error = clGetKernelArgInfo( kernel, (cl_uint)j, CL_KERNEL_ARG_ADDRESS_QUALIFIER, sizeof address_qualifier, &address_qualifier, &size ); + test_error( error, "Unable to get argument address qualifier" ); + error = (address_qualifier != expected_address_qualifier); + if ( error ) + { + log_error( "ERROR: Bad address qualifier, kernel: \"%s\", argument number: %d, expected \"0x%X\", got \"0x%X\"\n", kernel_name, (unsigned int)j, (unsigned int)expected_address_qualifier, (unsigned int)address_qualifier ); + arg_rc = -1; + } + + // Try to get the access qualifier of each argument. + cl_kernel_arg_access_qualifier access_qualifier = 0; + error = clGetKernelArgInfo( kernel, (cl_uint)j, CL_KERNEL_ARG_ACCESS_QUALIFIER, sizeof access_qualifier, &access_qualifier, &size ); + test_error( error, "Unable to get argument access qualifier" ); + error = (access_qualifier != expected_access_qualifier); + if ( error ) + { + log_error( "ERROR: Bad access qualifier, kernel: \"%s\", argument number: %d, expected \"0x%X\", got \"0x%X\"\n", kernel_name, (unsigned int)j, (unsigned int)expected_access_qualifier, (unsigned int)access_qualifier ); + arg_rc = -1; + } + + // Try to get the type qualifier of each argument. + cl_kernel_arg_type_qualifier arg_type_qualifier = 0; + error = clGetKernelArgInfo( kernel, (cl_uint)j, CL_KERNEL_ARG_TYPE_QUALIFIER, sizeof arg_type_qualifier, &arg_type_qualifier, &size ); + test_error( error, "Unable to get argument type qualifier" ); + error = (arg_type_qualifier != expected_type_qualifier); + if ( error ) + { + log_error( "ERROR: Bad type qualifier, kernel: \"%s\", argument number: %d, expected \"0x%X\", got \"0x%X\"\n", kernel_name, (unsigned int)j, (unsigned int)expected_type_qualifier, (unsigned int)arg_type_qualifier ); + arg_rc = -1; + } + + // Try to get the type of each argument. + memset( name, 0, max_name_len ); + error = clGetKernelArgInfo(kernel, (cl_uint)j, CL_KERNEL_ARG_TYPE_NAME, max_name_len, name, &size ); + test_error( error, "Unable to get argument type name" ); + error = strcmp( (const char*) name, expected_type_name ); + if ( error ) + { + log_error( "ERROR: Bad argument type name, kernel: \"%s\", argument number: %d, expected \"%s\", got \"%s\"\n", kernel_name, (unsigned int)j, expected_type_name, name ); + arg_rc = -1; + } + + // Try to get the name of each argument. + memset( name, 0, max_name_len ); + error = clGetKernelArgInfo( kernel, (cl_uint)j, CL_KERNEL_ARG_NAME, max_name_len, name, &size ); + test_error( error, "Unable to get argument name" ); + error = strcmp( (const char*) name, expected_arg_name ); + if ( error ) + { + log_error( "ERROR: Bad argument name, kernel: \"%s\", argument number: %d, expected \"%s\", got \"%s\"\n", kernel_name, (unsigned int)j, expected_arg_name, name ); + arg_rc = -1; + } + + if(arg_rc != 0) { + kernel_rc = -1; + } + } + } + + //log_info( "%s ... %s\n",arg_info[i][0],kernel_rc == 0 ? "passed" : "failed" ); + if(kernel_rc != 0) { + rc = -1; + } + } + return rc; +} + + +int test_get_kernel_arg_info( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + size_t size; + int error; + + cl_bool supports_double = 0; // assume not + cl_bool supports_half = 0; // assume not + cl_bool supports_images = 0; // assume not + cl_bool supports_long = 0; // assume not + cl_bool supports_3D_images = 0; // assume not + + // Check if this device supports images + error = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE_SUPPORT, sizeof supports_images, &supports_images, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_IMAGE_SUPPORT failed"); + + if (supports_images) { + log_info(" o Device supports images\n"); + log_info(" o Expecting SUCCESS when testing image kernel arguments.\n"); + } + else { + log_info(" o Device lacks image support\n"); + log_info(" o Not testing image kernel arguments.\n"); + } + + // Get the extensions string for the device + error = clGetDeviceInfo(deviceID, CL_DEVICE_EXTENSIONS, 0, NULL, &size); + test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS size failed"); + + char *extensions = (char*)malloc(sizeof(char)*(size + 1)); + if (extensions == 0) { + log_error("Failed to allocate memory for extensions string.\n"); + return -1; + } + memset( extensions, CHAR_MIN, sizeof(char)*(size+1) ); + + error = clGetDeviceInfo(deviceID, CL_DEVICE_EXTENSIONS, sizeof(char)*size, extensions, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS failed"); + + // Check to make sure the extension string is NUL terminated. + if( extensions[size] != CHAR_MIN ) + { + test_error( -1, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS wrote past the end of the array!" ); + return -1; + } + extensions[size] = '\0'; // set last char to NUL to avoid problems with string functions later + + // test for termination with '\0' + size_t stringSize = strlen( extensions ); + if( stringSize == size ) + { + test_error( -1, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS is not NUL terminated!" ); + return -1; + } + + if (strstr(extensions, "cl_khr_fp64")) { + log_info(" o Device claims extension 'cl_khr_fp64'\n"); + log_info(" o Expecting SUCCESS when testing double kernel arguments.\n"); + supports_double = 1; + } else { + cl_device_fp_config double_fp_config; + error = clGetDeviceInfo(deviceID, CL_DEVICE_DOUBLE_FP_CONFIG, sizeof(double_fp_config), &double_fp_config, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_DOUBLE_FP_CONFIG failed"); + if (double_fp_config != 0) + supports_double = 1; + else { + log_info(" o Device lacks extension 'cl_khr_fp64'\n"); + log_info(" o Not testing double kernel arguments.\n"); + supports_double = 0; + } + } + + if (strstr(extensions, "cl_khr_fp16")) { + log_info(" o Device claims extension 'cl_khr_fp16'\n"); + log_info(" o Expecting SUCCESS when testing halfn* kernel arguments.\n"); + supports_half = 1; + } else { + log_info(" o Device lacks extension 'cl_khr_fp16'\n"); + log_info(" o Not testing halfn* kernel arguments.\n"); + supports_half = 0; + } + + if (strstr(extensions, "cl_khr_int64")) + { + log_info(" o Device claims extension 'cl_khr_int64'\n"); + log_info(" o Expecting SUCCESS when testing long kernel arguments.\n"); + supports_long = 1; + } else + { + log_info(" o Device lacks extension 'cl_khr_int64'\n"); + log_info(" o Not testing long kernel arguments.\n"); + supports_long = 0; + } + + error = checkFor3DImageSupport(deviceID); + if (error != CL_IMAGE_FORMAT_NOT_SUPPORTED) + { + log_info(" o Device supports 3D images\n"); + log_info(" o Expecting SUCCESS when testing 3D image kernel arguments.\n"); + supports_3D_images = 1; + } else + { + log_info(" o Device lacks 3D image support\n"); + log_info(" o Not testing 3D image kernel arguments.\n"); + supports_3D_images = 0; + } + + int test_failed = 0; + + // Now create a test program using required arguments + log_info("Testing required kernel arguments...\n"); + error = test(deviceID, context, required_kernel_args, sizeof(required_kernel_args)/sizeof(required_kernel_args[0]), required_arg_info, sizeof(required_arg_info)/sizeof(required_arg_info[0])); + test_failed = (error) ? -1 : test_failed; + + if ( supports_images ) + { + log_info("Testing optional image arguments...\n"); + error = test(deviceID, context, image_kernel_args, sizeof(image_kernel_args)/sizeof(image_kernel_args[0]), image_arg_info, sizeof(image_arg_info)/sizeof(image_arg_info[0])); + test_failed = (error) ? -1 : test_failed; + } + + if ( supports_double ) + { + log_info("Testing optional double arguments...\n"); + error = test(deviceID, context, double_kernel_args, sizeof(double_kernel_args)/sizeof(double_kernel_args[0]), double_arg_info, sizeof(double_arg_info)/sizeof(double_arg_info[0])); + test_failed = (error) ? -1 : test_failed; + } + + if ( supports_half ) + { + log_info("Testing optional half arguments...\n"); + error = test(deviceID, context, half_kernel_args, sizeof(half_kernel_args)/sizeof(half_kernel_args[0]), half_arg_info, sizeof(half_arg_info)/sizeof(half_arg_info[0])); + test_failed = (error) ? -1 : test_failed; + } + + if ( supports_long ) + { + log_info("Testing optional long arguments...\n"); + error = test(deviceID, context, long_kernel_args, sizeof(long_kernel_args)/sizeof(long_kernel_args[0]), long_arg_info, sizeof(long_arg_info)/sizeof(long_arg_info[0])); + test_failed = (error) ? -1 : test_failed; + } + + if ( supports_3D_images ) + { + log_info("Testing optional 3D image arguments...\n"); + error = test(deviceID, context, image_3D_kernel_args, sizeof(image_3D_kernel_args)/sizeof(image_3D_kernel_args[0]), image_3D_arg_info, sizeof(image_3D_arg_info)/sizeof(image_3D_arg_info[0])); + test_failed = (error) ? -1 : test_failed; + } + + return test_failed; +} diff --git a/test_conformance/api/test_kernel_arg_multi_setup.cpp b/test_conformance/api/test_kernel_arg_multi_setup.cpp new file mode 100644 index 00000000..89c5eeb1 --- /dev/null +++ b/test_conformance/api/test_kernel_arg_multi_setup.cpp @@ -0,0 +1,277 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/conversions.h" + +// This test is designed to stress passing multiple vector parameters to kernels and verifying access between them all + +const char *multi_arg_kernel_source_pattern = +"__kernel void sample_test(__global %s *src1, __global %s *src2, __global %s *src3, __global %s *dst1, __global %s *dst2, __global %s *dst3 )\n" +"{\n" +" int tid = get_global_id(0);\n" +" dst1[tid] = src1[tid];\n" +" dst2[tid] = src2[tid];\n" +" dst3[tid] = src3[tid];\n" +"}\n"; + +extern cl_uint gRandomSeed; + +#define MAX_ERROR_TOLERANCE 0.0005f + +int test_multi_arg_set(cl_device_id device, cl_context context, cl_command_queue queue, + ExplicitType vec1Type, int vec1Size, + ExplicitType vec2Type, int vec2Size, + ExplicitType vec3Type, int vec3Size, MTdata d) +{ + clProgramWrapper program; + clKernelWrapper kernel; + int error, i, j; + clMemWrapper streams[ 6 ]; + size_t threads[1], localThreads[1]; + char programSrc[ 10248 ], vec1Name[ 64 ], vec2Name[ 64 ], vec3Name[ 64 ]; + char sizeNames[][ 4 ] = { "", "2", "3", "4", "", "", "", "8" }; + const char *ptr; + void *initData[3], *resultData[3]; + + + // Create the program source + sprintf( vec1Name, "%s%s", get_explicit_type_name( vec1Type ), sizeNames[ vec1Size - 1 ] ); + sprintf( vec2Name, "%s%s", get_explicit_type_name( vec2Type ), sizeNames[ vec2Size - 1 ] ); + sprintf( vec3Name, "%s%s", get_explicit_type_name( vec3Type ), sizeNames[ vec3Size - 1 ] ); + + sprintf( programSrc, multi_arg_kernel_source_pattern, + vec1Name, vec2Name, vec3Name, vec1Name, vec2Name, vec3Name, + vec1Size, vec1Size, vec2Size, vec2Size, vec3Size, vec3Size ); + ptr = programSrc; + + // Create our testing kernel + error = create_single_kernel_helper( context, &program, &kernel, 1, &ptr, "sample_test" ); + test_error( error, "Unable to create testing kernel" ); + + // Get thread dimensions + threads[0] = 1024; + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size for kernel" ); + + // Create input streams + initData[ 0 ] = create_random_data( vec1Type, d, (unsigned int)threads[ 0 ] * vec1Size ); + streams[ 0 ] = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), get_explicit_type_size( vec1Type ) * threads[0] * vec1Size, initData[ 0 ], &error ); + test_error( error, "Unable to create testing stream" ); + + initData[ 1 ] = create_random_data( vec2Type, d, (unsigned int)threads[ 0 ] * vec2Size ); + streams[ 1 ] = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), get_explicit_type_size( vec2Type ) * threads[0] * vec2Size, initData[ 1 ], &error ); + test_error( error, "Unable to create testing stream" ); + + initData[ 2 ] = create_random_data( vec3Type, d, (unsigned int)threads[ 0 ] * vec3Size ); + streams[ 2 ] = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), get_explicit_type_size( vec3Type ) * threads[0] * vec3Size, initData[ 2 ], &error ); + test_error( error, "Unable to create testing stream" ); + + streams[ 3 ] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), get_explicit_type_size( vec1Type ) * threads[0] * vec1Size, NULL, &error ); + test_error( error, "Unable to create testing stream" ); + + streams[ 4 ] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), get_explicit_type_size( vec2Type ) * threads[0] * vec2Size, NULL, &error ); + test_error( error, "Unable to create testing stream" ); + + streams[ 5 ] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), get_explicit_type_size( vec3Type ) * threads[0] * vec3Size, NULL, &error ); + test_error( error, "Unable to create testing stream" ); + + // Set the arguments + error = 0; + for( i = 0; i < 6; i++ ) + error |= clSetKernelArg( kernel, i, sizeof( cl_mem ), &streams[ i ] ); + test_error( error, "Unable to set arguments for kernel" ); + + // Execute! + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute kernel" ); + + // Read results + resultData[0] = malloc( get_explicit_type_size( vec1Type ) * vec1Size * threads[0] ); + resultData[1] = malloc( get_explicit_type_size( vec2Type ) * vec2Size * threads[0] ); + resultData[2] = malloc( get_explicit_type_size( vec3Type ) * vec3Size * threads[0] ); + error = clEnqueueReadBuffer( queue, streams[ 3 ], CL_TRUE, 0, get_explicit_type_size( vec1Type ) * vec1Size * threads[ 0 ], resultData[0], 0, NULL, NULL ); + error |= clEnqueueReadBuffer( queue, streams[ 4 ], CL_TRUE, 0, get_explicit_type_size( vec2Type ) * vec2Size * threads[ 0 ], resultData[1], 0, NULL, NULL ); + error |= clEnqueueReadBuffer( queue, streams[ 5 ], CL_TRUE, 0, get_explicit_type_size( vec3Type ) * vec3Size * threads[ 0 ], resultData[2], 0, NULL, NULL ); + test_error( error, "Unable to read result stream" ); + + // Verify + char *ptr1 = (char *)initData[ 0 ], *ptr2 = (char *)resultData[ 0 ]; + size_t span = get_explicit_type_size( vec1Type ); + for( i = 0; i < (int)threads[0]; i++ ) + { + for( j = 0; j < vec1Size; j++ ) + { + if( memcmp( ptr1 + span * j , ptr2 + span * j, span ) != 0 ) + { + log_error( "ERROR: Value did not validate for component %d of item %d of stream 0!\n", j, i ); + free( initData[ 0 ] ); + free( initData[ 1 ] ); + free( initData[ 2 ] ); + free( resultData[ 0 ] ); + free( resultData[ 1 ] ); + free( resultData[ 2 ] ); + return -1; + } + } + ptr1 += span * vec1Size; + ptr2 += span * vec1Size; + } + + ptr1 = (char *)initData[ 1 ]; + ptr2 = (char *)resultData[ 1 ]; + span = get_explicit_type_size( vec2Type ); + for( i = 0; i < (int)threads[0]; i++ ) + { + for( j = 0; j < vec2Size; j++ ) + { + if( memcmp( ptr1 + span * j , ptr2 + span * j, span ) != 0 ) + { + log_error( "ERROR: Value did not validate for component %d of item %d of stream 1!\n", j, i ); + free( initData[ 0 ] ); + free( initData[ 1 ] ); + free( initData[ 2 ] ); + free( resultData[ 0 ] ); + free( resultData[ 1 ] ); + free( resultData[ 2 ] ); + return -1; + } + } + ptr1 += span * vec2Size; + ptr2 += span * vec2Size; + } + + ptr1 = (char *)initData[ 2 ]; + ptr2 = (char *)resultData[ 2 ]; + span = get_explicit_type_size( vec3Type ); + for( i = 0; i < (int)threads[0]; i++ ) + { + for( j = 0; j < vec3Size; j++ ) + { + if( memcmp( ptr1 + span * j , ptr2 + span * j, span ) != 0 ) + { + log_error( "ERROR: Value did not validate for component %d of item %d of stream 2!\n", j, i ); + free( initData[ 0 ] ); + free( initData[ 1 ] ); + free( initData[ 2 ] ); + free( resultData[ 0 ] ); + free( resultData[ 1 ] ); + free( resultData[ 2 ] ); + return -1; + } + } + ptr1 += span * vec3Size; + ptr2 += span * vec3Size; + } + + // If we got here, everything verified successfully + free( initData[ 0 ] ); + free( initData[ 1 ] ); + free( initData[ 2 ] ); + free( resultData[ 0 ] ); + free( resultData[ 1 ] ); + free( resultData[ 2 ] ); + + return 0; +} + +int test_kernel_arg_multi_setup_exhaustive(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + // Loop through every combination of input and output types + ExplicitType types[] = { kChar, kShort, kInt, kFloat, kNumExplicitTypes }; + int type1, type2, type3; + int size1, size2, size3; + RandomSeed seed( gRandomSeed ); + + log_info( "\n" ); // for formatting + + for( type1 = 0; types[ type1 ] != kNumExplicitTypes; type1++ ) + { + for( type2 = 0; types[ type2 ] != kNumExplicitTypes; type2++ ) + { + for( type3 = 0; types[ type3 ] != kNumExplicitTypes; type3++ ) + { + log_info( "\n\ttesting %s, %s, %s...", get_explicit_type_name( types[ type1 ] ), get_explicit_type_name( types[ type2 ] ), get_explicit_type_name( types[ type3 ] ) ); + + // Loop through every combination of vector size + for( size1 = 2; size1 <= 8; size1 <<= 1 ) + { + for( size2 = 2; size2 <= 8; size2 <<= 1 ) + { + for( size3 = 2; size3 <= 8; size3 <<= 1 ) + { + log_info("."); + fflush( stdout); + if( test_multi_arg_set( device, context, queue, + types[ type1 ], size1, + types[ type2 ], size2, + types[ type3 ], size3, seed ) ) + return -1; + } + } + } + } + } + } + log_info( "\n" ); + return 0; +} + +int test_kernel_arg_multi_setup_random(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + // Loop through a selection of combinations + ExplicitType types[] = { kChar, kShort, kInt, kFloat, kNumExplicitTypes }; + int type1, type2, type3; + int size1, size2, size3; + RandomSeed seed( gRandomSeed ); + + num_elements = 3*3*3*4; + log_info( "Testing %d random configurations\n", num_elements ); + + // Loop through every combination of vector size + for( size1 = 2; size1 <= 8; size1 <<= 1 ) + { + for( size2 = 2; size2 <= 8; size2 <<= 1 ) + { + for( size3 = 2; size3 <= 8; size3 <<= 1 ) + { + // Loop through 4 type combinations for each size combination + int n; + for (n=0; n<4; n++) { + type1 = (int)get_random_float(0,4, seed); + type2 = (int)get_random_float(0,4, seed); + type3 = (int)get_random_float(0,4, seed); + + + log_info( "\ttesting %s%d, %s%d, %s%d...\n", + get_explicit_type_name( types[ type1 ] ), size1, + get_explicit_type_name( types[ type2 ] ), size2, + get_explicit_type_name( types[ type3 ] ), size3 ); + + if( test_multi_arg_set( device, context, queue, + types[ type1 ], size1, + types[ type2 ], size2, + types[ type3 ], size3, seed ) ) + return -1; + } + } + } + } + return 0; +} + + + + diff --git a/test_conformance/api/test_kernels.c b/test_conformance/api/test_kernels.c new file mode 100644 index 00000000..6daaabee --- /dev/null +++ b/test_conformance/api/test_kernels.c @@ -0,0 +1,695 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" + +extern cl_uint gRandomSeed; + +const char *sample_single_test_kernel[] = { +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n" }; + +const char *sample_struct_test_kernel[] = { +"typedef struct {\n" +"__global int *A;\n" +"__global int *B;\n" +"} input_pair_t;\n" +"\n" +"__kernel void sample_test(__global input_pair_t *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = src->A[tid] + src->B[tid];\n" +"\n" +"}\n" }; + +const char *sample_struct_array_test_kernel[] = { +"typedef struct {\n" +"int A;\n" +"int B;\n" +"} input_pair_t;\n" +"\n" +"__kernel void sample_test(__global input_pair_t *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = src[tid].A + src[tid].B;\n" +"\n" +"}\n" }; + +const char *sample_const_test_kernel[] = { +"__kernel void sample_test(__constant int *src1, __constant int *src2, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = src1[tid] + src2[tid];\n" +"\n" +"}\n" }; + +const char *sample_const_global_test_kernel[] = { +"__constant int addFactor = 1024;\n" +"__kernel void sample_test(__global int *src1, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = src1[tid] + addFactor;\n" +"\n" +"}\n" }; + +const char *sample_two_kernel_program[] = { +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n", +"__kernel void sample_test2(__global int *src, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (float)src[tid];\n" +"\n" +"}\n" }; + + + + +int test_get_kernel_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program, testProgram; + cl_context testContext; + cl_kernel kernel; + cl_char name[ 512 ]; + cl_uint numArgs, numInstances; + size_t paramSize; + + + /* Create reference */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_single_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_FUNCTION_NAME, NULL, 0, ¶mSize ); + test_error( error, "Unable to get kernel function name param size" ); + if( paramSize != strlen( "sample_test" ) + 1 ) + { + log_error( "ERROR: Kernel function name param returns invalid size (expected %d, got %d)\n", (int)strlen( "sample_test" ) + 1, (int)paramSize ); + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_FUNCTION_NAME, sizeof( name ), name, NULL ); + test_error( error, "Unable to get kernel function name" ); + if( strcmp( (char *)name, "sample_test" ) != 0 ) + { + log_error( "ERROR: Kernel function name returned invalid value (expected sample_test, got %s)\n", (char *)name ); + return -1; + } + + + error = clGetKernelInfo( kernel, CL_KERNEL_NUM_ARGS, 0, NULL, ¶mSize ); + test_error( error, "Unable to get kernel arg count param size" ); + if( paramSize != sizeof( numArgs ) ) + { + log_error( "ERROR: Kernel arg count param returns invalid size (expected %d, got %d)\n", (int)sizeof( numArgs ), (int)paramSize ); + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_NUM_ARGS, sizeof( numArgs ), &numArgs, NULL ); + test_error( error, "Unable to get kernel arg count" ); + if( numArgs != 2 ) + { + log_error( "ERROR: Kernel arg count returned invalid value (expected %d, got %d)\n", 2, numArgs ); + return -1; + } + + + error = clGetKernelInfo( kernel, CL_KERNEL_REFERENCE_COUNT, 0, NULL, ¶mSize ); + test_error( error, "Unable to get kernel reference count param size" ); + if( paramSize != sizeof( numInstances ) ) + { + log_error( "ERROR: Kernel reference count param returns invalid size (expected %d, got %d)\n", (int)sizeof( numInstances ), (int)paramSize ); + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_REFERENCE_COUNT, sizeof( numInstances ), &numInstances, NULL ); + test_error( error, "Unable to get kernel reference count" ); + + + error = clGetKernelInfo( kernel, CL_KERNEL_PROGRAM, NULL, 0, ¶mSize ); + test_error( error, "Unable to get kernel program param size" ); + if( paramSize != sizeof( testProgram ) ) + { + log_error( "ERROR: Kernel program param returns invalid size (expected %d, got %d)\n", (int)sizeof( testProgram ), (int)paramSize ); + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_PROGRAM, sizeof( testProgram ), &testProgram, NULL ); + test_error( error, "Unable to get kernel program" ); + if( testProgram != program ) + { + log_error( "ERROR: Kernel program returned invalid value (expected %p, got %p)\n", program, testProgram ); + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_CONTEXT, sizeof( testContext ), &testContext, NULL ); + test_error( error, "Unable to get kernel context" ); + if( testContext != context ) + { + log_error( "ERROR: Kernel context returned invalid value (expected %p, got %p)\n", context, testContext ); + return -1; + } + + /* Release memory */ + clReleaseKernel( kernel ); + clReleaseProgram( program ); + return 0; +} + +int test_execute_kernel_local_sizes(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + size_t threads[1], localThreads[1]; + cl_float inputData[100]; + cl_int outputData[100]; + RandomSeed seed( gRandomSeed ); + int i; + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_single_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 100, NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 100, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Write some test data */ + memset( outputData, 0, sizeof( outputData ) ); + + for (i=0; i<100; i++) + inputData[i] = get_random_float(-(float) 0x7fffffff, (float) 0x7fffffff, seed); + + error = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, sizeof(cl_float)*100, (void *)inputData, 0, NULL, NULL); + test_error( error, "Unable to set testing kernel data" ); + + /* Set the arguments */ + error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set kernel arguments" ); + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)100; + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(cl_int)*100, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<100; i++) + { + if (outputData[i] != (int)inputData[i]) + { + log_error( "ERROR: Data did not verify on first pass!\n" ); + return -1; + } + } + + /* Try again */ + if( localThreads[0] > 1 ) + localThreads[0] /= 2; + while( localThreads[0] > 1 && 0 != threads[0] % localThreads[0] ) + localThreads[0]--; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(cl_int)*100, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<100; i++) + { + if (outputData[i] != (int)inputData[i]) + { + log_error( "ERROR: Data did not verify on first pass!\n" ); + return -1; + } + } + + /* And again */ + if( localThreads[0] > 1 ) + localThreads[0] /= 2; + while( localThreads[0] > 1 && 0 != threads[0] % localThreads[0] ) + localThreads[0]--; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(cl_int)*100, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<100; i++) + { + if (outputData[i] != (int)inputData[i]) + { + log_error( "ERROR: Data did not verify on first pass!\n" ); + return -1; + } + } + + /* One more time */ + localThreads[0] = (unsigned int)1; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(cl_int)*100, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<100; i++) + { + if (outputData[i] != (int)inputData[i]) + { + log_error( "ERROR: Data did not verify on first pass!\n" ); + return -1; + } + } + + return 0; +} + +int test_set_kernel_arg_by_index(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + size_t threads[1], localThreads[1]; + cl_float inputData[10]; + cl_int outputData[10]; + RandomSeed seed( gRandomSeed ); + int i; + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_single_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Write some test data */ + memset( outputData, 0, sizeof( outputData ) ); + + for (i=0; i<10; i++) + inputData[i] = get_random_float(-(float) 0x7fffffff, (float) 0x7fffffff, seed); + + error = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, sizeof(cl_float)*10, (void *)inputData, 0, NULL, NULL); + test_error( error, "Unable to set testing kernel data" ); + + /* Test setting the arguments by index manually */ + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)10; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(cl_int)*10, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<10; i++) + { + if (outputData[i] != (int)inputData[i]) + { + log_error( "ERROR: Data did not verify on first pass!\n" ); + return -1; + } + } + + return 0; +} + +int test_set_kernel_arg_struct(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + cl_kernel kernel; + void *args[2]; + cl_mem outStream; + size_t threads[1], localThreads[1]; + cl_int outputData[10]; + int i; + cl_int randomTestDataA[10], randomTestDataB[10]; + MTdata d; + + struct img_pair_t + { + cl_mem streamA; + cl_mem streamB; + } image_pair; + + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_struct_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + d = init_genrand( gRandomSeed ); + for( i = 0; i < 10; i++ ) + { + randomTestDataA[i] = (cl_int)genrand_int32(d); + randomTestDataB[i] = (cl_int)genrand_int32(d); + } + free_mtdata(d); d = NULL; + + image_pair.streamA = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_int) * 10, randomTestDataA, &error); + test_error( error, "Creating test array failed" ); + image_pair.streamB = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_int) * 10, randomTestDataB, &error); + test_error( error, "Creating test array failed" ); + outStream = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Set the arguments */ + args[0] = &image_pair; + args[1] = outStream; + + error = clSetKernelArg(kernel, 0, sizeof( image_pair ), &image_pair); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( cl_mem ), &args[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)10; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, outStream, CL_TRUE, 0, sizeof(cl_int)*10, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<10; i++) + { + if (outputData[i] != randomTestDataA[i] + randomTestDataB[i]) + { + log_error( "ERROR: Data did not verify!\n" ); + return -1; + } + } + + + clReleaseMemObject( image_pair.streamA ); + clReleaseMemObject( image_pair.streamB ); + clReleaseMemObject( outStream ); + clReleaseKernel( kernel ); + clReleaseProgram( program ); + + return 0; +} + +int test_set_kernel_arg_constant(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[3]; + size_t threads[1], localThreads[1]; + cl_int outputData[10]; + int i; + cl_int randomTestDataA[10], randomTestDataB[10]; + cl_ulong maxSize; + MTdata d; + + /* Verify our test buffer won't be bigger than allowed */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof( maxSize ), &maxSize, 0 ); + test_error( error, "Unable to get max constant buffer size" ); + if( maxSize < sizeof( cl_int ) * 10 ) + { + log_error( "ERROR: Unable to test constant argument to kernel: max size of constant buffer is reported as %d!\n", (int)maxSize ); + return -1; + } + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_const_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + d = init_genrand( gRandomSeed ); + for( i = 0; i < 10; i++ ) + { + randomTestDataA[i] = (cl_int)genrand_int32(d) & 0xffffff; /* Make sure values are positive, just so we don't have to */ + randomTestDataB[i] = (cl_int)genrand_int32(d) & 0xffffff; /* deal with overflow on the verification */ + } + free_mtdata(d); d = NULL; + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_int) * 10, randomTestDataA, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_int) * 10, randomTestDataB, &error); + test_error( error, "Creating test array failed" ); + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Set the arguments */ + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 2, sizeof( streams[2] ), &streams[2]); + test_error( error, "Unable to set indexed kernel arguments" ); + + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)10; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[2], CL_TRUE, 0, sizeof(cl_int)*10, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<10; i++) + { + if (outputData[i] != randomTestDataA[i] + randomTestDataB[i]) + { + log_error( "ERROR: Data sample %d did not verify! %d does not match %d + %d (%d)\n", i, outputData[i], randomTestDataA[i], randomTestDataB[i], ( randomTestDataA[i] + randomTestDataB[i] ) ); + return -1; + } + } + + return 0; +} + +int test_set_kernel_arg_struct_array(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + size_t threads[1], localThreads[1]; + cl_int outputData[10]; + int i; + MTdata d; + + typedef struct img_pair_type + { + int A; + int B; + } image_pair_t; + + image_pair_t image_pair[ 10 ]; + + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_struct_array_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + d = init_genrand( gRandomSeed ); + for( i = 0; i < 10; i++ ) + { + image_pair[i].A = (cl_int)genrand_int32(d); + image_pair[i].A = (cl_int)genrand_int32(d); + } + free_mtdata(d); d = NULL; + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(image_pair_t) * 10, (void *)image_pair, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Set the arguments */ + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)10; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(cl_int)*10, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<10; i++) + { + if (outputData[i] != image_pair[i].A + image_pair[i].B) + { + log_error( "ERROR: Data did not verify!\n" ); + return -1; + } + } + + return 0; +} + +int test_create_kernels_in_program(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + cl_kernel kernel[3]; + unsigned int kernelCount; + + error = create_single_kernel_helper(context, &program, NULL, 2, sample_two_kernel_program, NULL); + test_error(error, "Unable to build test program"); + + /* Try getting the kernel count */ + error = clCreateKernelsInProgram( program, 0, NULL, &kernelCount ); + test_error( error, "Unable to get kernel count for built program" ); + if( kernelCount != 2 ) + { + log_error( "ERROR: Returned kernel count from clCreateKernelsInProgram is incorrect! (got %d, expected 2)\n", kernelCount ); + return -1; + } + + /* Try actually getting the kernels */ + error = clCreateKernelsInProgram( program, 2, kernel, NULL ); + test_error( error, "Unable to get kernels for built program" ); + clReleaseKernel( kernel[0] ); + clReleaseKernel( kernel[1] ); + + clReleaseProgram( program ); + return 0; +} + +int test_kernel_global_constant(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + size_t threads[1], localThreads[1]; + cl_int outputData[10]; + int i; + cl_int randomTestDataA[10]; + MTdata d; + + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_const_global_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + d = init_genrand( gRandomSeed ); + for( i = 0; i < 10; i++ ) + { + randomTestDataA[i] = (cl_int)genrand_int32(d) & 0xffff; /* Make sure values are positive and small, just so we don't have to */ + } + free_mtdata(d); d = NULL; + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_int) * 10, randomTestDataA, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Set the arguments */ + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)10; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(cl_int)*10, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<10; i++) + { + if (outputData[i] != randomTestDataA[i] + 1024) + { + log_error( "ERROR: Data sample %d did not verify! %d does not match %d + 1024 (%d)\n", i, outputData[i], randomTestDataA[i], ( randomTestDataA[i] + 1024 ) ); + return -1; + } + } + + return 0; +} + + + diff --git a/test_conformance/api/test_mem_object_info.cpp b/test_conformance/api/test_mem_object_info.cpp new file mode 100644 index 00000000..85069a54 --- /dev/null +++ b/test_conformance/api/test_mem_object_info.cpp @@ -0,0 +1,756 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/testHarness.h" + +extern cl_uint gRandomSeed; + + +#define TEST_MEM_OBJECT_PARAM( mem, paramName, val, expected, name, type, cast ) \ +error = clGetMemObjectInfo( mem, paramName, sizeof( val ), &val, &size ); \ +test_error( error, "Unable to get mem object " name ); \ +if( val != expected ) \ +{ \ +log_error( "ERROR: Mem object " name " did not validate! (expected " type ", got " type " from %s:%d)\n", \ +expected, (cast)val, __FILE__, __LINE__ ); \ +return -1; \ +} \ +if( size != sizeof( val ) ) \ +{ \ +log_error( "ERROR: Returned size of mem object " name " does not validate! (expected %d, got %d from %s:%d)\n", \ +(int)sizeof( val ), (int)size , __FILE__, __LINE__ ); \ +return -1; \ +} + +static void CL_CALLBACK mem_obj_destructor_callback( cl_mem, void * data ) +{ + free( data ); +} + +static unsigned int +get_image_dim(MTdata *d, unsigned int mod) +{ + unsigned int val = 0; + + do + { + val = (unsigned int)genrand_int32(*d) % mod; + } while (val == 0); + + return val; +} + + +int test_get_buffer_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ) +{ + int error; + size_t size; + void * buffer = NULL; + + clMemWrapper bufferObject; + clMemWrapper subBufferObject; + + cl_mem_flags bufferFlags[] = { + CL_MEM_READ_WRITE, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_READ_ONLY, + CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_WRITE_ONLY, + CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + }; + + cl_mem_flags subBufferFlags[] = { + CL_MEM_READ_WRITE, + CL_MEM_READ_ONLY, + CL_MEM_WRITE_ONLY, + 0, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_READ_ONLY | 0, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_WRITE_ONLY | 0, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_NO_ACCESS | 0, + }; + + + // Get the address alignment, so we can make sure the sub-buffer test later works properly. + cl_uint addressAlignBits; + error = clGetDeviceInfo( deviceID, CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof(addressAlignBits), &addressAlignBits, NULL ); + + size_t addressAlign = addressAlignBits/8; + if ( addressAlign < 128 ) + { + addressAlign = 128; + } + + for ( unsigned int i = 0; i < sizeof(bufferFlags) / sizeof(cl_mem_flags); ++i ) + { + //printf("@@@ bufferFlags[%u]=0x%x\n", i, bufferFlags[ i ]); + if ( bufferFlags[ i ] & CL_MEM_USE_HOST_PTR ) + { + // Create a buffer object to test against. + buffer = malloc( addressAlign * 4 ); + bufferObject = clCreateBuffer( context, bufferFlags[ i ], addressAlign * 4, buffer, &error ); + if ( error ) + { + free( buffer ); + test_error( error, "Unable to create buffer (CL_MEM_USE_HOST_PTR) to test with" ); + } + + // Make sure buffer is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( bufferObject, mem_obj_destructor_callback, buffer ); + test_error( error, "Unable to set mem object destructor callback" ); + + void * ptr; + TEST_MEM_OBJECT_PARAM( bufferObject, CL_MEM_HOST_PTR, ptr, buffer, "host pointer", "%p", void * ) + } + else if ( (bufferFlags[ i ] & CL_MEM_ALLOC_HOST_PTR) && (bufferFlags[ i ] & CL_MEM_COPY_HOST_PTR) ) + { + // Create a buffer object to test against. + buffer = malloc( addressAlign * 4 ); + bufferObject = clCreateBuffer( context, bufferFlags[ i ], addressAlign * 4, buffer, &error ); + if ( error ) + { + free( buffer ); + test_error( error, "Unable to create buffer (CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR) to test with" ); + } + + // Make sure buffer is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( bufferObject, mem_obj_destructor_callback, buffer ); + test_error( error, "Unable to set mem object destructor callback" ); + } + else if ( bufferFlags[ i ] & CL_MEM_ALLOC_HOST_PTR ) + { + // Create a buffer object to test against. + bufferObject = clCreateBuffer( context, bufferFlags[ i ], addressAlign * 4, NULL, &error ); + test_error( error, "Unable to create buffer (CL_MEM_ALLOC_HOST_PTR) to test with" ); + } + else if ( bufferFlags[ i ] & CL_MEM_COPY_HOST_PTR ) + { + // Create a buffer object to test against. + buffer = malloc( addressAlign * 4 ); + bufferObject = clCreateBuffer( context, bufferFlags[ i ], addressAlign * 4, buffer, &error ); + if ( error ) + { + free( buffer ); + test_error( error, "Unable to create buffer (CL_MEM_COPY_HOST_PTR) to test with" ); + } + + // Make sure buffer is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( bufferObject, mem_obj_destructor_callback, buffer ); + test_error( error, "Unable to set mem object destructor callback" ); + } + else + { + // Create a buffer object to test against. + bufferObject = clCreateBuffer( context, bufferFlags[ i ], addressAlign * 4, NULL, &error ); + test_error( error, "Unable to create buffer to test with" ); + } + + // Perform buffer object queries. + cl_mem_object_type type; + TEST_MEM_OBJECT_PARAM( bufferObject, CL_MEM_TYPE, type, CL_MEM_OBJECT_BUFFER, "type", "%d", int ) + + cl_mem_flags flags; + TEST_MEM_OBJECT_PARAM( bufferObject, CL_MEM_FLAGS, flags, (unsigned int)bufferFlags[ i ], "flags", "%d", unsigned int ) + + size_t sz; + TEST_MEM_OBJECT_PARAM( bufferObject, CL_MEM_SIZE, sz, (size_t)( addressAlign * 4 ), "size", "%ld", size_t ) + + cl_uint mapCount; + error = clGetMemObjectInfo( bufferObject, CL_MEM_MAP_COUNT, sizeof( mapCount ), &mapCount, &size ); + test_error( error, "Unable to get mem object map count" ); + if( size != sizeof( mapCount ) ) + { + log_error( "ERROR: Returned size of mem object map count does not validate! (expected %d, got %d from %s:%d)\n", + (int)sizeof( mapCount ), (int)size, __FILE__, __LINE__ ); + return -1; + } + + cl_uint refCount; + error = clGetMemObjectInfo( bufferObject, CL_MEM_REFERENCE_COUNT, sizeof( refCount ), &refCount, &size ); + test_error( error, "Unable to get mem object reference count" ); + if( size != sizeof( refCount ) ) + { + log_error( "ERROR: Returned size of mem object reference count does not validate! (expected %d, got %d from %s:%d)\n", + (int)sizeof( refCount ), (int)size, __FILE__, __LINE__ ); + return -1; + } + + cl_context otherCtx; + TEST_MEM_OBJECT_PARAM( bufferObject, CL_MEM_CONTEXT, otherCtx, context, "context", "%p", cl_context ) + + cl_mem origObj; + TEST_MEM_OBJECT_PARAM( bufferObject, CL_MEM_ASSOCIATED_MEMOBJECT, origObj, (void *)NULL, "associated mem object", "%p", void * ) + + size_t offset; + TEST_MEM_OBJECT_PARAM( bufferObject, CL_MEM_OFFSET, offset, 0L, "offset", "%ld", size_t ) + + cl_buffer_region region; + region.origin = addressAlign; + region.size = addressAlign; + + // Loop over possible sub-buffer objects to create. + for ( unsigned int j = 0; j < sizeof(subBufferFlags) / sizeof(cl_mem_flags); ++j ) + { + if ( subBufferFlags[ j ] & CL_MEM_READ_WRITE ) + { + if ( !(bufferFlags[ i ] & CL_MEM_READ_WRITE) ) + continue; // Buffer must be read_write for sub-buffer to be read_write. + } + if ( subBufferFlags[ j ] & CL_MEM_READ_ONLY ) + { + if ( !(bufferFlags[ i ] & CL_MEM_READ_WRITE) && !(bufferFlags[ i ] & CL_MEM_READ_ONLY) ) + continue; // Buffer must be read_write or read_only for sub-buffer to be read_only + } + if ( subBufferFlags[ j ] & CL_MEM_WRITE_ONLY ) + { + if ( !(bufferFlags[ i ] & CL_MEM_READ_WRITE) && !(bufferFlags[ i ] & CL_MEM_WRITE_ONLY) ) + continue; // Buffer must be read_write or write_only for sub-buffer to be write_only + } + if ( subBufferFlags[ j ] & CL_MEM_HOST_READ_ONLY ) + { + if ( (bufferFlags[ i ] & CL_MEM_HOST_NO_ACCESS) || (bufferFlags[ i ] & CL_MEM_HOST_WRITE_ONLY) ) + continue; // Buffer must be host all access or host read_only for sub-buffer to be host read_only + } + if ( subBufferFlags[ j ] & CL_MEM_HOST_WRITE_ONLY ) + { + if ( (bufferFlags[ i ] & CL_MEM_HOST_NO_ACCESS) || (bufferFlags[ i ] & CL_MEM_HOST_READ_ONLY) ) + continue; // Buffer must be host all access or host write_only for sub-buffer to be host write_only + } + //printf("@@@ bufferFlags[%u]=0x%x subBufferFlags[%u]=0x%x\n", i, bufferFlags[ i ], j, subBufferFlags[ j ]); + + subBufferObject = clCreateSubBuffer( bufferObject, subBufferFlags[ j ], CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error ); + test_error( error, "Unable to create sub-buffer to test against" ); + + // Perform sub-buffer object queries. + cl_mem_object_type type; + TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_TYPE, type, CL_MEM_OBJECT_BUFFER, "type", "%d", int ) + + cl_mem_flags flags; + cl_mem_flags inheritedFlags = subBufferFlags[ j ]; + if ( (subBufferFlags[ j ] & (CL_MEM_READ_WRITE | CL_MEM_READ_ONLY | CL_MEM_WRITE_ONLY)) == 0 ) + { + inheritedFlags |= bufferFlags[ i ] & (CL_MEM_READ_WRITE | CL_MEM_READ_ONLY | CL_MEM_WRITE_ONLY); + } + inheritedFlags |= bufferFlags[ i ] & (CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR); + if ( (subBufferFlags[ j ] & (CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS)) == 0) + { + inheritedFlags |= bufferFlags[ i ] & (CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS); + } + TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_FLAGS, flags, (unsigned int)inheritedFlags, "flags", "%d", unsigned int ) + + TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_SIZE, sz, (size_t)( addressAlign ), "size", "%ld", size_t ) + + if ( bufferFlags[ i ] & CL_MEM_USE_HOST_PTR ) + { + void * ptr; + void * offsetInBuffer = (char *)buffer + addressAlign; + + TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_HOST_PTR, ptr, offsetInBuffer, "host pointer", "%p", void * ) + } + + cl_uint mapCount; + error = clGetMemObjectInfo( subBufferObject, CL_MEM_MAP_COUNT, sizeof( mapCount ), &mapCount, &size ); + test_error( error, "Unable to get mem object map count" ); + if( size != sizeof( mapCount ) ) + { + log_error( "ERROR: Returned size of mem object map count does not validate! (expected %d, got %d from %s:%d)\n", + (int)sizeof( mapCount ), (int)size, __FILE__, __LINE__ ); + return -1; + } + + cl_uint refCount; + error = clGetMemObjectInfo( subBufferObject, CL_MEM_REFERENCE_COUNT, sizeof( refCount ), &refCount, &size ); + test_error( error, "Unable to get mem object reference count" ); + if( size != sizeof( refCount ) ) + { + log_error( "ERROR: Returned size of mem object reference count does not validate! (expected %d, got %d from %s:%d)\n", + (int)sizeof( refCount ), (int)size, __FILE__, __LINE__ ); + return -1; + } + + cl_context otherCtx; + TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_CONTEXT, otherCtx, context, "context", "%p", cl_context ) + + TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_ASSOCIATED_MEMOBJECT, origObj, (cl_mem)bufferObject, "associated mem object", "%p", void * ) + + TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_OFFSET, offset, (size_t)( addressAlign ), "offset", "%ld", size_t ) + + clReleaseMemObject( subBufferObject ); + subBufferObject = NULL; + + } + + clReleaseMemObject( bufferObject ); + bufferObject = NULL; + } + + return CL_SUCCESS; +} + + +int test_get_imageObject_info( cl_mem * image, cl_mem_flags objectFlags, cl_image_desc *imageInfo, cl_image_format *imageFormat, size_t pixelSize, cl_context context ) +{ + int error; + size_t size; + cl_mem_object_type type; + cl_mem_flags flags; + cl_uint mapCount; + cl_uint refCount; + size_t rowPitchMultiplier; + size_t slicePitchMultiplier; + cl_context otherCtx; + size_t offset; + size_t sz; + + TEST_MEM_OBJECT_PARAM( *image, CL_MEM_TYPE, type, imageInfo->image_type, "type", "%d", int ) + + TEST_MEM_OBJECT_PARAM( *image, CL_MEM_FLAGS, flags, (unsigned int)objectFlags, "flags", "%d", unsigned int ) + + error = clGetMemObjectInfo( *image, CL_MEM_SIZE, sizeof( sz ), &sz, NULL ); + test_error( error, "Unable to get mem size" ); + + // The size returned is not constrained by the spec. + + error = clGetMemObjectInfo( *image, CL_MEM_MAP_COUNT, sizeof( mapCount ), &mapCount, &size ); + test_error( error, "Unable to get mem object map count" ); + if( size != sizeof( mapCount ) ) + { + log_error( "ERROR: Returned size of mem object map count does not validate! (expected %d, got %d from %s:%d)\n", + (int)sizeof( mapCount ), (int)size, __FILE__, __LINE__ ); + return -1; + } + + error = clGetMemObjectInfo( *image, CL_MEM_REFERENCE_COUNT, sizeof( refCount ), &refCount, &size ); + test_error( error, "Unable to get mem object reference count" ); + if( size != sizeof( refCount ) ) + { + log_error( "ERROR: Returned size of mem object reference count does not validate! (expected %d, got %d from %s:%d)\n", + (int)sizeof( refCount ), (int)size, __FILE__, __LINE__ ); + return -1; + } + + TEST_MEM_OBJECT_PARAM( *image, CL_MEM_CONTEXT, otherCtx, context, "context", "%p", cl_context ) + + TEST_MEM_OBJECT_PARAM( *image, CL_MEM_OFFSET, offset, 0L, "offset", "%ld", size_t ) + + return CL_SUCCESS; +} + + +int test_get_image_info( cl_device_id deviceID, cl_context context, cl_mem_object_type type ) +{ + int error; + size_t size; + void * image = NULL; + + cl_mem imageObject; + cl_image_desc imageInfo; + + cl_mem_flags imageFlags[] = { + CL_MEM_READ_WRITE, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_READ_ONLY, + CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_WRITE_ONLY, + CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + }; + MTdata d; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ) + + cl_image_format imageFormat; + size_t pixelSize = 4; + + imageFormat.image_channel_order = CL_RGBA; + imageFormat.image_channel_data_type = CL_UNORM_INT8; + + imageInfo.image_width = imageInfo.image_height = imageInfo.image_depth = 1; + imageInfo.image_array_size = 0; + imageInfo.num_mip_levels = imageInfo.num_samples = 0; + imageInfo.mem_object = NULL; + + d = init_genrand( gRandomSeed ); + + for ( unsigned int i = 0; i < sizeof(imageFlags) / sizeof(cl_mem_flags); ++i ) + { + imageInfo.image_row_pitch = 0; + imageInfo.image_slice_pitch = 0; + + switch (type) + { + case CL_MEM_OBJECT_IMAGE1D: + imageInfo.image_width = get_image_dim(&d, 1023); + imageInfo.image_type = CL_MEM_OBJECT_IMAGE1D; + break; + + case CL_MEM_OBJECT_IMAGE2D: + imageInfo.image_width = get_image_dim(&d, 1023); + imageInfo.image_height = get_image_dim(&d, 1023); + imageInfo.image_type = CL_MEM_OBJECT_IMAGE2D; + break; + + case CL_MEM_OBJECT_IMAGE3D: + error = checkFor3DImageSupport(deviceID); + if (error == CL_IMAGE_FORMAT_NOT_SUPPORTED) + { + log_info("Device doesn't support 3D images. Skipping test.\n"); + return CL_SUCCESS; + } + imageInfo.image_width = get_image_dim(&d, 127); + imageInfo.image_height = get_image_dim(&d, 127); + imageInfo.image_depth = get_image_dim(&d, 127); + imageInfo.image_type = CL_MEM_OBJECT_IMAGE3D; + break; + + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + imageInfo.image_width = get_image_dim(&d, 1023); + imageInfo.image_array_size = get_image_dim(&d, 1023); + imageInfo.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + break; + + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + imageInfo.image_width = get_image_dim(&d, 255); + imageInfo.image_height = get_image_dim(&d, 255); + imageInfo.image_array_size = get_image_dim(&d, 255); + imageInfo.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + break; + } + + if ( imageFlags[i] & CL_MEM_USE_HOST_PTR ) + { + // Create an image object to test against. + image = malloc( imageInfo.image_width * imageInfo.image_height * imageInfo.image_depth * pixelSize * + ((imageInfo.image_array_size == 0) ? 1 : imageInfo.image_array_size) ); + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, image, &error ); + if ( error ) + { + free( image ); + test_error( error, "Unable to create image with (CL_MEM_USE_HOST_PTR) to test with" ); + } + + // Make sure image is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( imageObject, mem_obj_destructor_callback, image ); + test_error( error, "Unable to set mem object destructor callback" ); + + void * ptr; + TEST_MEM_OBJECT_PARAM( imageObject, CL_MEM_HOST_PTR, ptr, image, "host pointer", "%p", void * ) + int ret = test_get_imageObject_info( &imageObject, imageFlags[i], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + // release image object + clReleaseMemObject(imageObject); + + // Try again with non-zero rowPitch. + imageInfo.image_row_pitch = imageInfo.image_width * pixelSize; + switch (type) + { + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + case CL_MEM_OBJECT_IMAGE3D: + imageInfo.image_slice_pitch = imageInfo.image_row_pitch * imageInfo.image_height; + break; + } + + image = malloc( imageInfo.image_width * imageInfo.image_height * imageInfo.image_depth * pixelSize * + ((imageInfo.image_array_size == 0) ? 1 : imageInfo.image_array_size) ); + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, image, &error ); + if ( error ) + { + free( image ); + test_error( error, "Unable to create image2d (CL_MEM_USE_HOST_PTR) to test with" ); + } + + // Make sure image2d is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( imageObject, mem_obj_destructor_callback, image ); + test_error( error, "Unable to set mem object destructor callback" ); + + TEST_MEM_OBJECT_PARAM( imageObject, CL_MEM_HOST_PTR, ptr, image, "host pointer", "%p", void * ) + ret = test_get_imageObject_info( &imageObject, imageFlags[i], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + } + else if ( (imageFlags[i] & CL_MEM_ALLOC_HOST_PTR) && (imageFlags[i] & CL_MEM_COPY_HOST_PTR) ) + { + // Create an image object to test against. + image = malloc( imageInfo.image_width * imageInfo.image_height * imageInfo.image_depth * pixelSize * + ((imageInfo.image_array_size == 0) ? 1 : imageInfo.image_array_size) ); + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, image, &error ); + if ( error ) + { + free( image ); + test_error( error, "Unable to create image with (CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR) to test with" ); + } + + // Make sure image is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( imageObject, mem_obj_destructor_callback, image ); + test_error( error, "Unable to set mem object destructor callback" ); + int ret = test_get_imageObject_info( &imageObject, imageFlags[ i ], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + // release image object + clReleaseMemObject(imageObject); + + // Try again with non-zero rowPitch. + imageInfo.image_row_pitch = imageInfo.image_width * pixelSize; + switch (type) + { + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + case CL_MEM_OBJECT_IMAGE3D: + imageInfo.image_slice_pitch = imageInfo.image_row_pitch * imageInfo.image_height; + break; + } + + image = malloc( imageInfo.image_width * imageInfo.image_height * imageInfo.image_depth * pixelSize * + ((imageInfo.image_array_size == 0) ? 1 : imageInfo.image_array_size) ); + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, image, &error ); + if ( error ) + { + free( image ); + test_error( error, "Unable to create image with (CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR) to test with" ); + } + + // Make sure image is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( imageObject, mem_obj_destructor_callback, image ); + test_error( error, "Unable to set mem object destructor callback" ); + ret = test_get_imageObject_info( &imageObject, imageFlags[i], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + } + else if ( imageFlags[i] & CL_MEM_ALLOC_HOST_PTR ) + { + // Create an image object to test against. + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, NULL, &error ); + test_error( error, "Unable to create image with (CL_MEM_ALLOC_HOST_PTR) to test with" ); + int ret = test_get_imageObject_info( &imageObject, imageFlags[i], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + } + else if ( imageFlags[i] & CL_MEM_COPY_HOST_PTR ) + { + // Create an image object to test against. + image = malloc( imageInfo.image_width * imageInfo.image_height * imageInfo.image_depth * pixelSize * + ((imageInfo.image_array_size == 0) ? 1 : imageInfo.image_array_size) ); + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, image, &error ); + if ( error ) + { + free( image ); + test_error( error, "Unable to create image with (CL_MEM_COPY_HOST_PTR) to test with" ); + } + + // Make sure image is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( imageObject, mem_obj_destructor_callback, image ); + test_error( error, "Unable to set mem object destructor callback" ); + int ret = test_get_imageObject_info( &imageObject, imageFlags[i], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + clReleaseMemObject(imageObject); + + // Try again with non-zero rowPitch. + imageInfo.image_row_pitch = imageInfo.image_width * pixelSize; + switch (type) + { + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + case CL_MEM_OBJECT_IMAGE3D: + imageInfo.image_slice_pitch = imageInfo.image_row_pitch * imageInfo.image_height; + break; + } + + image = malloc( imageInfo.image_width * imageInfo.image_height * imageInfo.image_depth * pixelSize * + ((imageInfo.image_array_size == 0) ? 1 : imageInfo.image_array_size) ); + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, image, &error ); + if ( error ) + { + free( image ); + test_error( error, "Unable to create image with (CL_MEM_COPY_HOST_PTR) to test with" ); + } + + // Make sure image is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( imageObject, mem_obj_destructor_callback, image ); + test_error( error, "Unable to set mem object destructor callback" ); + ret = test_get_imageObject_info( &imageObject, imageFlags[i], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + } + else + { + // Create an image object to test against. + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, NULL, &error ); + test_error( error, "Unable to create image to test with" ); + int ret = test_get_imageObject_info( &imageObject, imageFlags[i], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + } + + clReleaseMemObject( imageObject ); + } + + return CL_SUCCESS; +} + + +int test_get_image2d_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ) +{ + return test_get_image_info(deviceID, context, CL_MEM_OBJECT_IMAGE2D); +} + +int test_get_image3d_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ) +{ + return test_get_image_info(deviceID, context, CL_MEM_OBJECT_IMAGE3D); +} + +int test_get_image1d_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ) +{ + return test_get_image_info(deviceID, context, CL_MEM_OBJECT_IMAGE1D); +} + +int test_get_image1d_array_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ) +{ + return test_get_image_info(deviceID, context, CL_MEM_OBJECT_IMAGE1D_ARRAY); +} + +int test_get_image2d_array_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ) +{ + return test_get_image_info(deviceID, context, CL_MEM_OBJECT_IMAGE2D_ARRAY); +} + + diff --git a/test_conformance/api/test_mem_objects.cpp b/test_conformance/api/test_mem_objects.cpp new file mode 100644 index 00000000..b0dc99d4 --- /dev/null +++ b/test_conformance/api/test_mem_objects.cpp @@ -0,0 +1,108 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +static volatile cl_int sDestructorIndex; + +void CL_CALLBACK mem_destructor_callback( cl_mem memObject, void * userData ) +{ + int * userPtr = (int *)userData; + + // ordering of callbacks is guaranteed, meaning we don't need to do atomic operation here + *userPtr = ++sDestructorIndex; +} + +#ifndef ABS +#define ABS( x ) ( ( x < 0 ) ? -x : x ) +#endif + +int test_mem_object_destructor_callback_single( clMemWrapper &memObject ) +{ + cl_int error; + int i; + + // Set up some variables to catch the order in which callbacks are called + volatile int callbackOrders[ 3 ] = { 0, 0, 0 }; + sDestructorIndex = 0; + + // Set up the callbacks + error = clSetMemObjectDestructorCallback( memObject, mem_destructor_callback, (void*) &callbackOrders[ 0 ] ); + test_error( error, "Unable to set destructor callback" ); + + error = clSetMemObjectDestructorCallback( memObject, mem_destructor_callback, (void*) &callbackOrders[ 1 ] ); + test_error( error, "Unable to set destructor callback" ); + + error = clSetMemObjectDestructorCallback( memObject, mem_destructor_callback, (void*) &callbackOrders[ 2 ] ); + test_error( error, "Unable to set destructor callback" ); + + // Now release the buffer, which SHOULD call the callbacks + error = clReleaseMemObject( memObject ); + test_error( error, "Unable to release test buffer" ); + + // Note: since we manually released the mem wrapper, we need to set it to NULL to prevent a double-release + memObject = NULL; + + // At this point, all three callbacks should have already been called + int numErrors = 0; + for( i = 0; i < 3; i++ ) + { + // Spin waiting for the release to finish. If you don't call the mem_destructor_callback, you will not + // pass the test. bugzilla 6316 + while( 0 == callbackOrders[i] ) + {} + + if( ABS( callbackOrders[ i ] ) != 3-i ) + { + log_error( "\tERROR: Callback %d was called in the wrong order! (Was called order %d, should have been order %d)\n", + i+1, ABS( callbackOrders[ i ] ), i ); + numErrors++; + } + } + + return ( numErrors > 0 ) ? -1 : 0; +} + +int test_mem_object_destructor_callback(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + clMemWrapper testBuffer, testImage; + cl_int error; + + + // Create a buffer and an image to test callbacks against + testBuffer = clCreateBuffer( context, CL_MEM_READ_WRITE, 1024, NULL, &error ); + test_error( error, "Unable to create testing buffer" ); + + if( test_mem_object_destructor_callback_single( testBuffer ) != 0 ) + { + log_error( "ERROR: Destructor callbacks for buffer object FAILED\n" ); + return -1; + } + + if( checkForImageSupport( deviceID ) == 0 ) + { + cl_image_format imageFormat = { CL_RGBA, CL_SIGNED_INT8 }; + testImage = create_image_2d( context, CL_MEM_READ_ONLY, &imageFormat, 16, 16, 0, NULL, &error ); + test_error( error, "Unable to create testing image" ); + + if( test_mem_object_destructor_callback_single( testImage ) != 0 ) + { + log_error( "ERROR: Destructor callbacks for image object FAILED\n" ); + return -1; + } + } + + return 0; +} diff --git a/test_conformance/api/test_native_kernel.cpp b/test_conformance/api/test_native_kernel.cpp new file mode 100644 index 00000000..2d52134b --- /dev/null +++ b/test_conformance/api/test_native_kernel.cpp @@ -0,0 +1,121 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +#ifndef _WIN32 +#include +#endif + +#include "../../test_common/harness/conversions.h" + +extern cl_uint gRandomSeed; + +static void CL_CALLBACK test_native_kernel_fn( void *userData ) +{ + struct arg_struct { + cl_int * source; + cl_int * dest; + cl_int count; + } *args = (arg_struct *)userData; + + for( cl_int i = 0; i < args->count; i++ ) + args->dest[ i ] = args->source[ i ]; +} + +int test_native_kernel(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + int error; + RandomSeed seed( gRandomSeed ); + // Check if we support native kernels + cl_device_exec_capabilities capabilities; + error = clGetDeviceInfo(device, CL_DEVICE_EXECUTION_CAPABILITIES, sizeof(capabilities), &capabilities, NULL); + if (!(capabilities & CL_EXEC_NATIVE_KERNEL)) { + log_info("Device does not support CL_EXEC_NATIVE_KERNEL.\n"); + return 0; + } + + clMemWrapper streams[ 2 ]; +#if !(defined (_WIN32) && defined (_MSC_VER)) + cl_int inBuffer[ n_elems ], outBuffer[ n_elems ]; +#else + cl_int* inBuffer = (cl_int *)_malloca( n_elems * sizeof(cl_int) ); + cl_int* outBuffer = (cl_int *)_malloca( n_elems * sizeof(cl_int) ); +#endif + clEventWrapper finishEvent; + + struct arg_struct + { + cl_mem inputStream; + cl_mem outputStream; + cl_int count; + } args; + + + // Create some input values + generate_random_data( kInt, n_elems, seed, inBuffer ); + + + // Create I/O streams + streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, n_elems * sizeof(cl_int), inBuffer, &error ); + test_error( error, "Unable to create I/O stream" ); + streams[ 1 ] = clCreateBuffer( context, 0, n_elems * sizeof(cl_int), NULL, &error ); + test_error( error, "Unable to create I/O stream" ); + + + // Set up the arrays to call with + args.inputStream = streams[ 0 ]; + args.outputStream = streams[ 1 ]; + args.count = n_elems; + + void * memLocs[ 2 ] = { &args.inputStream, &args.outputStream }; + + + // Run the kernel + error = clEnqueueNativeKernel( queue, test_native_kernel_fn, + &args, sizeof( args ), + 2, &streams[ 0 ], + (const void **)memLocs, + 0, NULL, &finishEvent ); + test_error( error, "Unable to queue native kernel" ); + + // Finish and wait for the kernel to complete + error = clFinish( queue ); + test_error(error, "clFinish failed"); + + error = clWaitForEvents( 1, &finishEvent ); + test_error(error, "clWaitForEvents failed"); + + // Now read the results and verify + error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, n_elems * sizeof(cl_int), outBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + for( int i = 0; i < n_elems; i++ ) + { + if( inBuffer[ i ] != outBuffer[ i ] ) + { + log_error( "ERROR: Data sample %d for native kernel did not validate (expected %d, got %d)\n", + i, (int)inBuffer[ i ], (int)outBuffer[ i ] ); + return 1; + } + } + + return 0; +} + + + + + diff --git a/test_conformance/api/test_null_buffer_arg.c b/test_conformance/api/test_null_buffer_arg.c new file mode 100644 index 00000000..b845fc0b --- /dev/null +++ b/test_conformance/api/test_null_buffer_arg.c @@ -0,0 +1,206 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#if defined(__APPLE__) +#include +#include +#else +#include +#include +#endif +#include "testBase.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/testHarness.h" +#include "procs.h" + + +enum { SUCCESS, FAILURE }; +typedef enum { NON_NULL_PATH, ADDROF_NULL_PATH, NULL_PATH } test_type; + +#define NITEMS 4096 + +/* places the comparison result of value of the src ptr against 0 into each element of the output + * array, to allow testing that the kernel actually _gets_ the NULL value */ +const char *kernel_string_long = +"kernel void test_kernel(global float *src, global long *dst)\n" +"{\n" +" uint tid = get_global_id(0);\n" +" dst[tid] = (long)(src != 0);\n" +"}\n"; + +// For gIsEmbedded +const char *kernel_string = +"kernel void test_kernel(global float *src, global int *dst)\n" +"{\n" +" uint tid = get_global_id(0);\n" +" dst[tid] = (int)(src != 0);\n" +"}\n"; + + +/* + * The guts of the test: + * call setKernelArgs with a regular buffer, &NULL, or NULL depending on + * the value of 'test_type' + */ +static int test_setargs_and_execution(cl_command_queue queue, cl_kernel kernel, + cl_mem test_buf, cl_mem result_buf, test_type type) +{ + unsigned int test_success = 0; + + unsigned int i; + cl_int status; + char *typestr; + + if (type == NON_NULL_PATH) { + status = clSetKernelArg(kernel, 0, sizeof(cl_mem), &test_buf); + typestr = "non-NULL"; + } else if (type == ADDROF_NULL_PATH) { + test_buf = NULL; + status = clSetKernelArg(kernel, 0, sizeof(cl_mem), &test_buf); + typestr = "&NULL"; + } else if (type == NULL_PATH) { + status = clSetKernelArg(kernel, 0, sizeof(cl_mem), NULL); + typestr = "NULL"; + } + + log_info("Testing setKernelArgs with %s buffer.\n", typestr); + + if (status != CL_SUCCESS) { + log_error("clSetKernelArg failed with status: %d\n", status); + return FAILURE; // no point in continuing *this* test + } + + size_t global = NITEMS; + status = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global, + NULL, 0, NULL, NULL); + test_error(status, "NDRangeKernel failed."); + + if (gIsEmbedded) + { + cl_int* host_result = (cl_int*)malloc(NITEMS*sizeof(cl_int)); + status = clEnqueueReadBuffer(queue, result_buf, CL_TRUE, 0, + sizeof(cl_int)*NITEMS, host_result, 0, NULL, NULL); + test_error(status, "ReadBuffer failed."); + // in the non-null case, we expect NONZERO values: + if (type == NON_NULL_PATH) { + for (i=0; i + +#define EXTENSION_NAME_BUF_SIZE 4096 + +#define PRINT_EXTENSION_INFO 0 + +int test_platform_extensions(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements) +{ + const char * extensions[] = { + "cl_khr_byte_addressable_store", +// "cl_APPLE_SetMemObjectDestructor", + "cl_khr_global_int32_base_atomics", + "cl_khr_global_int32_extended_atomics", + "cl_khr_local_int32_base_atomics", + "cl_khr_local_int32_extended_atomics", + "cl_khr_int64_base_atomics", + "cl_khr_int64_extended_atomics", +// need to put in entires for various atomics + "cl_khr_3d_image_writes", + "cl_khr_fp16", + "cl_khr_fp64", + NULL + }; + + bool extensionsSupported[] = { + false, //"cl_khr_byte_addressable_store", + false, // need to put in entires for various atomics + false, // "cl_khr_global_int32_base_atomics", + false, // "cl_khr_global_int32_extended_atomics", + false, // "cl_khr_local_int32_base_atomics", + false, // "cl_khr_local_int32_extended_atomics", + false, // "cl_khr_int64_base_atomics", + false, // "cl_khr_int64_extended_atomics", + false, //"cl_khr_3d_image_writes", + false, //"cl_khr_fp16", + false, //"cl_khr_fp64", + false //NULL + }; + + int extensionIndex; + + cl_platform_id platformID; + cl_int err; + + char platform_extensions[EXTENSION_NAME_BUF_SIZE]; + char device_extensions[EXTENSION_NAME_BUF_SIZE]; + + // Okay, so what we're going to do is just check the device indicated by + // deviceID against the platform that includes this device + + + // pass CL_DEVICE_PLATFORM to clGetDeviceInfo + // to get a result of type cl_platform_id + + err = clGetDeviceInfo(deviceID, + CL_DEVICE_PLATFORM, + sizeof(cl_platform_id), + (void *)(&platformID), + NULL); + + if(err != CL_SUCCESS) + { + vlog_error("test_platform_extensions : could not get platformID from device\n"); + return -1; + } + + + // now we grab the set of extensions specified by the platform + err = clGetPlatformInfo(platformID, + CL_PLATFORM_EXTENSIONS, + sizeof(platform_extensions), + (void *)(&platform_extensions[0]), + NULL); + if(err != CL_SUCCESS) + { + vlog_error("test_platform_extensions : could not get extension string from platform\n"); + return -1; + } + +#if PRINT_EXTENSION_INFO + log_info("Platform extensions include \"%s\"\n\n", platform_extensions); +#endif + + // here we parse the platform extensions, to look for the "important" ones + for(extensionIndex=0; extensions[extensionIndex] != NULL; ++extensionIndex) + { + if(strstr(platform_extensions, extensions[extensionIndex]) != NULL) + { + // we found it +#if PRINT_EXTENSION_INFO + log_info("Found \"%s\" in platform extensions\n", + extensions[extensionIndex]); +#endif + extensionsSupported[extensionIndex] = true; + } + } + + // and then we grab the set of extensions specified by the device + // (this can be turned into a "loop over all devices in this platform") + err = clGetDeviceInfo(deviceID, + CL_DEVICE_EXTENSIONS, + sizeof(device_extensions), + (void *)(&device_extensions[0]), + NULL); + if(err != CL_SUCCESS) + { + vlog_error("test_platform_extensions : could not get extension string from device\n"); + return -1; + } + + +#if PRINT_EXTENSION_INFO + log_info("Device extensions include \"%s\"\n\n", device_extensions); +#endif + + for(extensionIndex=0; extensions[extensionIndex] != NULL; ++extensionIndex) + { + if(extensionsSupported[extensionIndex] == false) + { + continue; // skip this one + } + + if(strstr(device_extensions, extensions[extensionIndex]) == NULL) + { + // device does not support it + vlog_error("Platform supports extension \"%s\" but device does not\n", + extensions[extensionIndex]); + return -1; + } + } + return 0; +} + +int test_get_platform_ids(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + cl_platform_id platforms[16]; + cl_uint num_platforms; + char *string_returned; + + string_returned = (char*)malloc(8192); + + int total_errors = 0; + int err = CL_SUCCESS; + + + err = clGetPlatformIDs(16, platforms, &num_platforms); + test_error(err, "clGetPlatformIDs failed"); + + if (num_platforms <= 16) { + // Try with NULL + err = clGetPlatformIDs(num_platforms, platforms, NULL); + test_error(err, "clGetPlatformIDs failed with NULL for return size"); + } + + if (num_platforms < 1) { + log_error("Found 0 platforms.\n"); + return -1; + } + log_info("Found %d platforms.\n", num_platforms); + + + for (int p=0; p<(int)num_platforms; p++) { + cl_device_id *devices; + cl_uint num_devices; + size_t size; + + + log_info("Platform %d (%p):\n", p, platforms[p]); + + memset(string_returned, 0, 8192); + err = clGetPlatformInfo(platforms[p], CL_PLATFORM_PROFILE, 8192, string_returned, &size); + test_error(err, "clGetPlatformInfo for CL_PLATFORM_PROFILE failed"); + log_info("\tCL_PLATFORM_PROFILE: %s\n", string_returned); + if (strlen(string_returned)+1 != size) { + log_error("Returned string length %ld does not equal reported one %ld.\n", strlen(string_returned)+1, size); + total_errors++; + } + + memset(string_returned, 0, 8192); + err = clGetPlatformInfo(platforms[p], CL_PLATFORM_VERSION, 8192, string_returned, &size); + test_error(err, "clGetPlatformInfo for CL_PLATFORM_VERSION failed"); + log_info("\tCL_PLATFORM_VERSION: %s\n", string_returned); + if (strlen(string_returned)+1 != size) { + log_error("Returned string length %ld does not equal reported one %ld.\n", strlen(string_returned)+1, size); + total_errors++; + } + + memset(string_returned, 0, 8192); + err = clGetPlatformInfo(platforms[p], CL_PLATFORM_NAME, 8192, string_returned, &size); + test_error(err, "clGetPlatformInfo for CL_PLATFORM_NAME failed"); + log_info("\tCL_PLATFORM_NAME: %s\n", string_returned); + if (strlen(string_returned)+1 != size) { + log_error("Returned string length %ld does not equal reported one %ld.\n", strlen(string_returned)+1, size); + total_errors++; + } + + memset(string_returned, 0, 8192); + err = clGetPlatformInfo(platforms[p], CL_PLATFORM_VENDOR, 8192, string_returned, &size); + test_error(err, "clGetPlatformInfo for CL_PLATFORM_VENDOR failed"); + log_info("\tCL_PLATFORM_VENDOR: %s\n", string_returned); + if (strlen(string_returned)+1 != size) { + log_error("Returned string length %ld does not equal reported one %ld.\n", strlen(string_returned)+1, size); + total_errors++; + } + + memset(string_returned, 0, 8192); + err = clGetPlatformInfo(platforms[p], CL_PLATFORM_EXTENSIONS, 8192, string_returned, &size); + test_error(err, "clGetPlatformInfo for CL_PLATFORM_EXTENSIONS failed"); + log_info("\tCL_PLATFORM_EXTENSIONS: %s\n", string_returned); + if (strlen(string_returned)+1 != size) { + log_error("Returned string length %ld does not equal reported one %ld.\n", strlen(string_returned)+1, size); + total_errors++; + } + + err = clGetDeviceIDs(platforms[p], CL_DEVICE_TYPE_ALL, 0, NULL, &num_devices); + test_error(err, "clGetDeviceIDs size failed.\n"); + devices = (cl_device_id *)malloc(num_devices*sizeof(cl_device_id)); + memset(devices, 0, sizeof(cl_device_id)*num_devices); + err = clGetDeviceIDs(platforms[p], CL_DEVICE_TYPE_ALL, num_devices, devices, NULL); + test_error(err, "clGetDeviceIDs failed.\n"); + + log_info("\tPlatform has %d devices.\n", (int)num_devices); + for (int d=0; d<(int)num_devices; d++) { + size_t returned_size; + cl_platform_id returned_platform; + cl_context context; + cl_context_properties properties[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[p], 0 }; + + err = clGetDeviceInfo(devices[d], CL_DEVICE_PLATFORM, sizeof(cl_platform_id), &returned_platform, &returned_size); + test_error(err, "clGetDeviceInfo failed for CL_DEVICE_PLATFORM\n"); + if (returned_size != sizeof(cl_platform_id)) { + log_error("Reported return size (%ld) does not match expected size (%ld).\n", returned_size, sizeof(cl_platform_id)); + total_errors++; + } + + memset(string_returned, 0, 8192); + err = clGetDeviceInfo(devices[d], CL_DEVICE_NAME, 8192, string_returned, NULL); + test_error(err, "clGetDeviceInfo failed for CL_DEVICE_NAME\n"); + + log_info("\t\tPlatform for device %d (%s) is %p.\n", d, string_returned, returned_platform); + + log_info("\t\t\tTesting clCreateContext for the platform/device...\n"); + // Try creating a context for the platform + context = clCreateContext(properties, 1, &devices[d], NULL, NULL, &err); + test_error(err, "\t\tclCreateContext failed for device with platform properties\n"); + + memset(properties, 0, sizeof(cl_context_properties)*3); + + err = clGetContextInfo(context, CL_CONTEXT_PROPERTIES, sizeof(cl_context_properties)*3, properties, &returned_size); + test_error(err, "clGetContextInfo for CL_CONTEXT_PROPERTIES failed"); + if (returned_size != sizeof(cl_context_properties)*3) { + log_error("Invalid size returned from clGetContextInfo for CL_CONTEXT_PROPERTIES. Got %ld, expected %ld.\n", + returned_size, sizeof(cl_context_properties)*3); + total_errors++; + } + + if (properties[0] != (cl_context_properties)CL_CONTEXT_PLATFORM || properties[1] != (cl_context_properties)platforms[p]) { + log_error("Wrong properties returned. Expected: [%p %p], got [%p %p]\n", + (void*)CL_CONTEXT_PLATFORM, platforms[p], (void*)properties[0], (void*)properties[1]); + total_errors++; + } + + err = clReleaseContext(context); + test_error(err, "clReleaseContext failed"); + } + free(devices); + } + + free(string_returned); + + return total_errors; +} diff --git a/test_conformance/api/test_queries.cpp b/test_conformance/api/test_queries.cpp new file mode 100644 index 00000000..0d412a0d --- /dev/null +++ b/test_conformance/api/test_queries.cpp @@ -0,0 +1,643 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/imageHelpers.h" +#include +#include + +int test_get_platform_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_platform_id platform; + cl_int error; + char buffer[ 16384 ]; + size_t length; + + // Get the platform to use + error = clGetPlatformIDs(1, &platform, NULL); + test_error( error, "Unable to get platform" ); + + // Platform profile should either be FULL_PROFILE or EMBEDDED_PROFILE + error = clGetPlatformInfo(platform, CL_PLATFORM_PROFILE, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get platform profile string" ); + + log_info("Returned CL_PLATFORM_PROFILE %s.\n", buffer); + + if( strcmp( buffer, "FULL_PROFILE" ) != 0 && strcmp( buffer, "EMBEDDED_PROFILE" ) != 0 ) + { + log_error( "ERROR: Returned platform profile string is not a valid string by OpenCL 1.2! (Returned: %s)\n", buffer ); + return -1; + } + if( strlen( buffer )+1 != length ) + { + log_error( "ERROR: Returned length of profile string is incorrect (actual length: %d, returned length: %d)\n", + (int)strlen( buffer )+1, (int)length ); + return -1; + } + + // Check just length return + error = clGetPlatformInfo(platform, CL_PLATFORM_PROFILE, 0, NULL, &length ); + test_error( error, "Unable to get platform profile length" ); + if( strlen( (char *)buffer )+1 != length ) + { + log_error( "ERROR: Returned length of profile string is incorrect (actual length: %d, returned length: %d)\n", + (int)strlen( (char *)buffer )+1, (int)length ); + return -1; + } + + + // Platform version should fit the regex "OpenCL *[0-9]+\.[0-9]+" + error = clGetPlatformInfo(platform, CL_PLATFORM_VERSION, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get platform version string" ); + + log_info("Returned CL_PLATFORM_VERSION %s.\n", buffer); + + if( memcmp( buffer, "OpenCL ", strlen( "OpenCL " ) ) != 0 ) + { + log_error( "ERROR: Initial part of platform version string does not match required format! (returned: %s)\n", (char *)buffer ); + return -1; + } + char *p1 = (char *)buffer + strlen( "OpenCL " ); + while( *p1 == ' ' ) + p1++; + char *p2 = p1; + while( isdigit( *p2 ) ) + p2++; + if( *p2 != '.' ) + { + log_error( "ERROR: Numeric part of platform version string does not match required format! (returned: %s)\n", (char *)buffer ); + return -1; + } + char *p3 = p2 + 1; + while( isdigit( *p3 ) ) + p3++; + if( *p3 != ' ' ) + { + log_error( "ERROR: space expected after minor version number! (returned: %s)\n", (char *)buffer ); + return -1; + } + *p2 = ' '; // Put in a space for atoi below. + p2++; + + // make sure it is null terminated + for( ; p3 != buffer + length; p3++ ) + if( *p3 == '\0' ) + break; + if( p3 == buffer + length ) + { + log_error( "ERROR: platform version string is not NUL terminated!\n" ); + return -1; + } + + int major = atoi( p1 ); + int minor = atoi( p2 ); + int minor_revision = 2; + if( major * 10 + minor < 10 + minor_revision ) + { + log_error( "ERROR: OpenCL profile version returned is less than 1.%d!\n", minor_revision ); + return -1; + } + + // Sanity checks on the returned values + if( length != strlen( (char *)buffer ) + 1) + { + log_error( "ERROR: Returned length of version string does not match actual length (actual: %d, returned: %d)\n", (int)strlen( (char *)buffer )+1, (int)length ); + return -1; + } + + // Check just length + error = clGetPlatformInfo(platform, CL_PLATFORM_VERSION, 0, NULL, &length ); + test_error( error, "Unable to get platform version length" ); + if( length != strlen( (char *)buffer )+1 ) + { + log_error( "ERROR: Returned length of version string does not match actual length (actual: %d, returned: %d)\n", (int)strlen( buffer )+1, (int)length ); + return -1; + } + + return 0; +} + +int test_get_sampler_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t size; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ) + + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_TRUE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_CLAMP, + CL_SAMPLER_FILTER_MODE, CL_FILTER_LINEAR, + 0 }; + clSamplerWrapper sampler = clCreateSamplerWithProperties(context, properties, &error); + test_error( error, "Unable to create sampler to test with" ); + + cl_uint refCount; + error = clGetSamplerInfo( sampler, CL_SAMPLER_REFERENCE_COUNT, sizeof( refCount ), &refCount, &size ); + test_error( error, "Unable to get sampler ref count" ); + if( size != sizeof( refCount ) ) + { + log_error( "ERROR: Returned size of sampler refcount does not validate! (expected %d, got %d)\n", (int)sizeof( refCount ), (int)size ); + return -1; + } + + cl_context otherCtx; + error = clGetSamplerInfo( sampler, CL_SAMPLER_CONTEXT, sizeof( otherCtx ), &otherCtx, &size ); + test_error( error, "Unable to get sampler context" ); + if( otherCtx != context ) + { + log_error( "ERROR: Sampler context does not validate! (expected %p, got %p)\n", context, otherCtx ); + return -1; + } + if( size != sizeof( otherCtx ) ) + { + log_error( "ERROR: Returned size of sampler context does not validate! (expected %d, got %d)\n", (int)sizeof( otherCtx ), (int)size ); + return -1; + } + + cl_addressing_mode mode; + error = clGetSamplerInfo( sampler, CL_SAMPLER_ADDRESSING_MODE, sizeof( mode ), &mode, &size ); + test_error( error, "Unable to get sampler addressing mode" ); + if( mode != CL_ADDRESS_CLAMP ) + { + log_error( "ERROR: Sampler addressing mode does not validate! (expected %d, got %d)\n", (int)CL_ADDRESS_CLAMP, (int)mode ); + return -1; + } + if( size != sizeof( mode ) ) + { + log_error( "ERROR: Returned size of sampler addressing mode does not validate! (expected %d, got %d)\n", (int)sizeof( mode ), (int)size ); + return -1; + } + + cl_filter_mode fmode; + error = clGetSamplerInfo( sampler, CL_SAMPLER_FILTER_MODE, sizeof( fmode ), &fmode, &size ); + test_error( error, "Unable to get sampler filter mode" ); + if( fmode != CL_FILTER_LINEAR ) + { + log_error( "ERROR: Sampler filter mode does not validate! (expected %d, got %d)\n", (int)CL_FILTER_LINEAR, (int)fmode ); + return -1; + } + if( size != sizeof( fmode ) ) + { + log_error( "ERROR: Returned size of sampler filter mode does not validate! (expected %d, got %d)\n", (int)sizeof( fmode ), (int)size ); + return -1; + } + + cl_int norm; + error = clGetSamplerInfo( sampler, CL_SAMPLER_NORMALIZED_COORDS, sizeof( norm ), &norm, &size ); + test_error( error, "Unable to get sampler normalized flag" ); + if( norm != CL_TRUE ) + { + log_error( "ERROR: Sampler normalized flag does not validate! (expected %d, got %d)\n", (int)CL_TRUE, (int)norm ); + return -1; + } + if( size != sizeof( norm ) ) + { + log_error( "ERROR: Returned size of sampler normalized flag does not validate! (expected %d, got %d)\n", (int)sizeof( norm ), (int)size ); + return -1; + } + + return 0; +} + +#define TEST_COMMAND_QUEUE_PARAM( queue, paramName, val, expected, name, type, cast ) \ +error = clGetCommandQueueInfo( queue, paramName, sizeof( val ), &val, &size ); \ +test_error( error, "Unable to get command queue " name ); \ +if( val != expected ) \ +{ \ +log_error( "ERROR: Command queue " name " did not validate! (expected " type ", got " type ")\n", (cast)expected, (cast)val ); \ +return -1; \ +} \ +if( size != sizeof( val ) ) \ +{ \ +log_error( "ERROR: Returned size of command queue " name " does not validate! (expected %d, got %d)\n", (int)sizeof( val ), (int)size ); \ +return -1; \ +} + +int test_get_command_queue_info(cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements) +{ + int error; + size_t size; + + cl_queue_properties device_props; + cl_queue_properties queue_props[] = {CL_QUEUE_PROPERTIES,0,0}; + + clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES, sizeof(device_props), &device_props, NULL); + log_info("CL_DEVICE_QUEUE_ON_HOST_PROPERTIES is %d\n", (int)device_props); + + queue_props[1] = device_props; + clCommandQueueWrapper queue = clCreateCommandQueueWithProperties( context, deviceID, &queue_props[0], &error ); + test_error( error, "Unable to create command queue to test with" ); + + cl_uint refCount; + error = clGetCommandQueueInfo( queue, CL_QUEUE_REFERENCE_COUNT, sizeof( refCount ), &refCount, &size ); + test_error( error, "Unable to get command queue reference count" ); + if( size != sizeof( refCount ) ) + { + log_error( "ERROR: Returned size of command queue reference count does not validate! (expected %d, got %d)\n", (int)sizeof( refCount ), (int)size ); + return -1; + } + + cl_context otherCtx; + TEST_COMMAND_QUEUE_PARAM( queue, CL_QUEUE_CONTEXT, otherCtx, context, "context", "%p", cl_context ) + + cl_device_id otherDevice; + error = clGetCommandQueueInfo( queue, CL_QUEUE_DEVICE, sizeof(otherDevice), &otherDevice, &size); + test_error(error, "clGetCommandQueue failed."); + + if (size != sizeof(cl_device_id)) { + log_error( " ERROR: Returned size of command queue CL_QUEUE_DEVICE does not validate! (expected %d, got %d)\n", (int)sizeof( otherDevice ), (int)size ); + return -1; + } + + /* Since the device IDs are opaque types we check the CL_DEVICE_VENDOR_ID which is unique for identical hardware. */ + cl_uint otherDevice_vid, deviceID_vid; + error = clGetDeviceInfo(otherDevice, CL_DEVICE_VENDOR_ID, sizeof(otherDevice_vid), &otherDevice_vid, NULL ); + test_error( error, "Unable to get device CL_DEVICE_VENDOR_ID" ); + error = clGetDeviceInfo(deviceID, CL_DEVICE_VENDOR_ID, sizeof(deviceID_vid), &deviceID_vid, NULL ); + test_error( error, "Unable to get device CL_DEVICE_VENDOR_ID" ); + + if( otherDevice_vid != deviceID_vid ) + { + log_error( "ERROR: Incorrect device returned for queue! (Expected vendor ID 0x%x, got 0x%x)\n", deviceID_vid, otherDevice_vid ); + return -1; + } + + cl_command_queue_properties props; + TEST_COMMAND_QUEUE_PARAM( queue, CL_QUEUE_PROPERTIES, props, (unsigned int)( device_props ), "properties", "%d", unsigned int ) + + return 0; +} + +int test_get_context_info(cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements) +{ + int error; + size_t size; + cl_context_properties props; + + error = clGetContextInfo( context, CL_CONTEXT_PROPERTIES, sizeof( props ), &props, &size ); + test_error( error, "Unable to get context props" ); + + if (size == 0) { + // Valid size + return 0; + } else if (size == sizeof(cl_context_properties)) { + // Data must be NULL + if (props != 0) { + log_error("ERROR: Returned properties is no NULL.\n"); + return -1; + } + // Valid data and size + return 0; + } + // Size was not 0 or 1 + log_error( "ERROR: Returned size of context props is not valid! (expected 0 or %d, got %d)\n", + (int)sizeof(cl_context_properties), (int)size ); + return -1; +} + +#define TEST_MEM_OBJECT_PARAM( mem, paramName, val, expected, name, type, cast ) \ +error = clGetMemObjectInfo( mem, paramName, sizeof( val ), &val, &size ); \ +test_error( error, "Unable to get mem object " name ); \ +if( val != expected ) \ +{ \ +log_error( "ERROR: Mem object " name " did not validate! (expected " type ", got " type ")\n", (cast)(expected), (cast)val ); \ +return -1; \ +} \ +if( size != sizeof( val ) ) \ +{ \ +log_error( "ERROR: Returned size of mem object " name " does not validate! (expected %d, got %d)\n", (int)sizeof( val ), (int)size ); \ +return -1; \ +} + +void CL_CALLBACK mem_obj_destructor_callback( cl_mem, void *data ) +{ + free( data ); +} + +// All possible combinations of valid cl_mem_flags. +static cl_mem_flags all_flags[16] = { + 0, + CL_MEM_READ_WRITE, + CL_MEM_READ_ONLY, + CL_MEM_WRITE_ONLY, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, +}; + +#define TEST_DEVICE_PARAM( device, paramName, val, name, type, cast ) \ +error = clGetDeviceInfo( device, paramName, sizeof( val ), &val, &size ); \ +test_error( error, "Unable to get device " name ); \ +if( size != sizeof( val ) ) \ +{ \ +log_error( "ERROR: Returned size of device " name " does not validate! (expected %d, got %d)\n", (int)sizeof( val ), (int)size ); \ +return -1; \ +} \ +log_info( "\tReported device " name " : " type "\n", (cast)val ); + +#define TEST_DEVICE_PARAM_MEM( device, paramName, val, name, type, div ) \ +error = clGetDeviceInfo( device, paramName, sizeof( val ), &val, &size ); \ +test_error( error, "Unable to get device " name ); \ +if( size != sizeof( val ) ) \ +{ \ +log_error( "ERROR: Returned size of device " name " does not validate! (expected %d, got %d)\n", (int)sizeof( val ), (int)size ); \ +return -1; \ +} \ +log_info( "\tReported device " name " : " type "\n", (int)( val / div ) ); + +int test_get_device_info(cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements) +{ + int error; + size_t size; + + cl_uint vendorID; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_VENDOR_ID, vendorID, "vendor ID", "0x%08x", int ) + + char extensions[ 10240 ]; + error = clGetDeviceInfo( deviceID, CL_DEVICE_EXTENSIONS, sizeof( extensions ), &extensions, &size ); + test_error( error, "Unable to get device extensions" ); + if( size != strlen( extensions ) + 1 ) + { + log_error( "ERROR: Returned size of device extensions does not validate! (expected %d, got %d)\n", (int)( strlen( extensions ) + 1 ), (int)size ); + return -1; + } + log_info( "\tReported device extensions: %s \n", extensions ); + + cl_uint preferred; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, preferred, "preferred vector char width", "%d", int ) + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, preferred, "preferred vector short width", "%d", int ) + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, preferred, "preferred vector int width", "%d", int ) + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, preferred, "preferred vector long width", "%d", int ) + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, preferred, "preferred vector float width", "%d", int ) + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, preferred, "preferred vector double width", "%d", int ) + + // Note that even if cl_khr_fp64, the preferred width for double can be non-zero. For example, vendors + // extensions can support double but may not support cl_khr_fp64, which implies math library support. + + cl_uint baseAddrAlign; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_MEM_BASE_ADDR_ALIGN, baseAddrAlign, "base address alignment", "%d bytes", int ) + + cl_uint maxDataAlign; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE, maxDataAlign, "min data type alignment", "%d bytes", int ) + + cl_device_mem_cache_type cacheType; + error = clGetDeviceInfo( deviceID, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE, sizeof( cacheType ), &cacheType, &size ); + test_error( error, "Unable to get device global mem cache type" ); + if( size != sizeof( cacheType ) ) + { + log_error( "ERROR: Returned size of device global mem cache type does not validate! (expected %d, got %d)\n", (int)sizeof( cacheType ), (int)size ); + return -1; + } + const char *cacheTypeName = ( cacheType == CL_NONE ) ? "CL_NONE" : ( cacheType == CL_READ_ONLY_CACHE ) ? "CL_READ_ONLY_CACHE" : ( cacheType == CL_READ_WRITE_CACHE ) ? "CL_READ_WRITE_CACHE" : ""; + log_info( "\tReported device global mem cache type: %s \n", cacheTypeName ); + + cl_uint cachelineSize; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, cachelineSize, "global mem cacheline size", "%d bytes", int ) + + cl_ulong cacheSize; + TEST_DEVICE_PARAM_MEM( deviceID, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, cacheSize, "global mem cache size", "%d KB", 1024 ) + + cl_ulong memSize; + TEST_DEVICE_PARAM_MEM( deviceID, CL_DEVICE_GLOBAL_MEM_SIZE, memSize, "global mem size", "%d MB", ( 1024 * 1024 ) ) + + cl_device_local_mem_type localMemType; + error = clGetDeviceInfo( deviceID, CL_DEVICE_LOCAL_MEM_TYPE, sizeof( localMemType ), &localMemType, &size ); + test_error( error, "Unable to get device local mem type" ); + if( size != sizeof( cacheType ) ) + { + log_error( "ERROR: Returned size of device local mem type does not validate! (expected %d, got %d)\n", (int)sizeof( localMemType ), (int)size ); + return -1; + } + const char *localMemTypeName = ( localMemType == CL_LOCAL ) ? "CL_LOCAL" : ( cacheType == CL_GLOBAL ) ? "CL_GLOBAL" : ""; + log_info( "\tReported device local mem type: %s \n", localMemTypeName ); + + + cl_bool errSupport; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_ERROR_CORRECTION_SUPPORT, errSupport, "error correction support", "%d", int ) + + size_t timerResolution; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_PROFILING_TIMER_RESOLUTION, timerResolution, "profiling timer resolution", "%ld nanoseconds", long ) + + cl_bool endian; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_ENDIAN_LITTLE, endian, "little endian flag", "%d", int ) + + cl_bool avail; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_AVAILABLE, avail, "available flag", "%d", int ) + + cl_bool compilerAvail; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_COMPILER_AVAILABLE, compilerAvail, "compiler available flag", "%d", int ) + + char profile[ 1024 ]; + error = clGetDeviceInfo( deviceID, CL_DEVICE_PROFILE, sizeof( profile ), &profile, &size ); + test_error( error, "Unable to get device profile" ); + if( size != strlen( profile ) + 1 ) + { + log_error( "ERROR: Returned size of device profile does not validate! (expected %d, got %d)\n", (int)( strlen( profile ) + 1 ), (int)size ); + return -1; + } + if( strcmp( profile, "FULL_PROFILE" ) != 0 && strcmp( profile, "EMBEDDED_PROFILE" ) != 0 ) + { + log_error( "ERROR: Returned profile of device not FULL or EMBEDDED as required by OpenCL 1.2! (Returned %s)\n", profile ); + return -1; + } + log_info( "\tReported device profile: %s \n", profile ); + + + return 0; +} + + + + +static const char *sample_compile_size[2] = { + "__kernel void sample_test(__global int *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = src[tid];\n" + "\n" + "}\n", + "__kernel __attribute__((reqd_work_group_size(%d,%d,%d))) void sample_test(__global int *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = src[tid];\n" + "\n" + "}\n" }; + +int test_kernel_required_group_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t realSize; + size_t kernel_max_workgroup_size; + size_t global[] = {64,14,10}; + size_t local[] = {0,0,0}; + + cl_uint max_dimensions; + + error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(max_dimensions), &max_dimensions, NULL); + test_error(error, "clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS"); + log_info("Device reported CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS = %d.\n", (int)max_dimensions); + + { + clProgramWrapper program; + clKernelWrapper kernel; + + error = create_single_kernel_helper( context, &program, &kernel, 1, &sample_compile_size[ 0 ], "sample_test" ); + if( error != 0 ) + return error; + + error = clGetKernelWorkGroupInfo(kernel, deviceID, CL_KERNEL_WORK_GROUP_SIZE, sizeof(kernel_max_workgroup_size), &kernel_max_workgroup_size, NULL); + test_error( error, "clGetKernelWorkGroupInfo failed for CL_KERNEL_WORK_GROUP_SIZE"); + log_info("The CL_KERNEL_WORK_GROUP_SIZE for the kernel is %d.\n", (int)kernel_max_workgroup_size); + + size_t size[ 3 ]; + error = clGetKernelWorkGroupInfo( kernel, deviceID, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, sizeof( size ), size, &realSize ); + test_error( error, "Unable to get work group info" ); + + if( size[ 0 ] != 0 || size[ 1 ] != 0 || size[ 2 ] != 0 ) + { + log_error( "ERROR: Nonzero compile work group size returned for nonspecified size! (returned %d,%d,%d)\n", (int)size[0], (int)size[1], (int)size[2] ); + return -1; + } + + if( realSize != sizeof( size ) ) + { + log_error( "ERROR: Returned size of compile work group size not valid! (Expected %d, got %d)\n", (int)sizeof( size ), (int)realSize ); + return -1; + } + + // Determine some local dimensions to use for the test. + if (max_dimensions == 1) { + error = get_max_common_work_group_size(context, kernel, global[0], &local[0]); + test_error( error, "get_max_common_work_group_size failed"); + log_info("For global dimension %d, kernel will require local dimension %d.\n", (int)global[0], (int)local[0]); + } else if (max_dimensions == 2) { + error = get_max_common_2D_work_group_size(context, kernel, global, local); + test_error( error, "get_max_common_2D_work_group_size failed"); + log_info("For global dimension %d x %d, kernel will require local dimension %d x %d.\n", (int)global[0], (int)global[1], (int)local[0], (int)local[1]); + } else { + error = get_max_common_3D_work_group_size(context, kernel, global, local); + test_error( error, "get_max_common_3D_work_group_size failed"); + log_info("For global dimension %d x %d x %d, kernel will require local dimension %d x %d x %d.\n", + (int)global[0], (int)global[1], (int)global[2], (int)local[0], (int)local[1], (int)local[2]); + } + } + + + { + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper in, out; + //char source[1024]; + char *source = (char*)malloc(1024); + source[0] = '\0'; + + sprintf(source, sample_compile_size[1], local[0], local[1], local[2]); + + error = create_single_kernel_helper( context, &program, &kernel, 1, (const char**)&source, "sample_test" ); + if( error != 0 ) + return error; + + size_t size[ 3 ]; + error = clGetKernelWorkGroupInfo( kernel, deviceID, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, sizeof( size ), size, &realSize ); + test_error( error, "Unable to get work group info" ); + + if( size[ 0 ] != local[0] || size[ 1 ] != local[1] || size[ 2 ] != local[2] ) + { + log_error( "ERROR: Incorrect compile work group size returned for specified size! (returned %d,%d,%d, expected %d,%d,%d)\n", + (int)size[0], (int)size[1], (int)size[2], (int)local[0], (int)local[1], (int)local[2]); + return -1; + } + + // Verify that the kernel will only execute with that size. + in = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(cl_int)*global[0], NULL, &error); + test_error(error, "clCreateBuffer failed"); + out = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(cl_int)*global[0], NULL, &error); + test_error(error, "clCreateBuffer failed"); + + error = clSetKernelArg(kernel, 0, sizeof(in), &in); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 1, sizeof(out), &out); + test_error(error, "clSetKernelArg failed"); + + error = clEnqueueNDRangeKernel(queue, kernel, 3, NULL, global, local, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + error = clFinish(queue); + test_error(error, "clFinish failed"); + + log_info("kernel_required_group_size may report spurious ERRORS in the conformance log.\n"); + + local[0]++; + error = clEnqueueNDRangeKernel(queue, kernel, 3, NULL, global, local, 0, NULL, NULL); + if (error != CL_INVALID_WORK_GROUP_SIZE) { + log_error("Incorrect error returned for executing a kernel with the wrong required local work group size. (used %d,%d,%d, required %d,%d,%d)\n", + (int)local[0], (int)local[1], (int)local[2], (int)local[0]-1, (int)local[1], (int)local[2] ); + print_error(error, "Expected: CL_INVALID_WORK_GROUP_SIZE."); + return -1; + } + + error = clFinish(queue); + test_error(error, "clFinish failed"); + + if (max_dimensions == 1) { + free(source); + return 0; + } + + local[0]--; local[1]++; + error = clEnqueueNDRangeKernel(queue, kernel, 3, NULL, global, local, 0, NULL, NULL); + if (error != CL_INVALID_WORK_GROUP_SIZE) { + log_error("Incorrect error returned for executing a kernel with the wrong required local work group size. (used %d,%d,%d, required %d,%d,%d)\n", + (int)local[0], (int)local[1], (int)local[2], (int)local[0]-1, (int)local[1], (int)local[2]); + print_error(error, "Expected: CL_INVALID_WORK_GROUP_SIZE."); + return -1; + } + + error = clFinish(queue); + test_error(error, "clFinish failed"); + + if (max_dimensions == 2) { + return 0; + free(source); + } + + local[1]--; local[2]++; + error = clEnqueueNDRangeKernel(queue, kernel, 3, NULL, global, local, 0, NULL, NULL); + if (error != CL_INVALID_WORK_GROUP_SIZE) { + log_error("Incorrect error returned for executing a kernel with the wrong required local work group size. (used %d,%d,%d, required %d,%d,%d)\n", + (int)local[0], (int)local[1], (int)local[2], (int)local[0]-1, (int)local[1], (int)local[2]); + print_error(error, "Expected: CL_INVALID_WORK_GROUP_SIZE."); + return -1; + } + + error = clFinish(queue); + test_error(error, "clFinish failed"); + free(source); + } + + return 0; +} + + diff --git a/test_conformance/api/test_queue_hint.cpp b/test_conformance/api/test_queue_hint.cpp new file mode 100644 index 00000000..2634a23a --- /dev/null +++ b/test_conformance/api/test_queue_hint.cpp @@ -0,0 +1,191 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" +#include +#include + +using namespace std; +/* + +*/ + +const char *queue_hint_test_kernel[] = { +"__kernel void vec_cpy(__global int *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = src[tid];\n" +"\n" +"}\n" }; + +int test_enqueue(cl_context context, clCommandQueueWrapper& queue, clKernelWrapper& kernel, size_t num_elements) +{ + clMemWrapper streams[2]; + int error; + + int* buf = new int[num_elements]; + + for (int i = 0; i < static_cast(num_elements); ++i) + { + buf[i] = i; + } + + + streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, num_elements * sizeof(int), buf, &error); + test_error( error, "clCreateBuffer failed." ); + streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, num_elements * sizeof(int), NULL, &error); + test_error( error, "clCreateBuffer failed." ); + + error = clSetKernelArg(kernel, 0, sizeof(streams[0]), &streams[0]); + test_error( error, "clSetKernelArg failed." ); + + error = clSetKernelArg(kernel, 1, sizeof(streams[1]), &streams[1]); + test_error( error, "clSetKernelArg failed." ); + + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &num_elements, NULL, 0, NULL, NULL); + test_error( error, "clEnqueueNDRangeKernel failed." ); + + error = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, num_elements * sizeof(int), buf, 0, NULL, NULL); + test_error( error, "clEnqueueReadBuffer failed." ); + + for (int i = 0; i < static_cast(num_elements); ++i) + { + if (buf[i] != i) + { + log_error("ERROR: Incorrect vector copy result."); + return -1; + } + } + + delete [] buf; + + return 0; +} + + + + +int test_queue_hint(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + if (num_elements <= 0) + { + num_elements = 128; + } + + int err = 0; + + // Query extension + cl_platform_id platform; + clProgramWrapper program; + clKernelWrapper kernel; + char *string_returned; + + string_returned = (char*)malloc(8192); + + err = clGetDeviceInfo(deviceID, CL_DEVICE_PLATFORM, sizeof(platform), &platform, NULL); + test_error(err, "clGetDeviceInfo for CL_DEVICE_PLATFORM failed"); + + err = create_single_kernel_helper_with_build_options(context, &program, &kernel, 1, queue_hint_test_kernel, "vec_cpy", NULL); + if (err != 0) + { + return err; + } + + memset(string_returned, 0, 8192); + err = clGetPlatformInfo(platform, CL_PLATFORM_EXTENSIONS, 8192, string_returned, NULL); + test_error(err, "clGetPlatformInfo for CL_PLATFORM_EXTENSIONS failed"); + log_info("\tCL_PLATFORM_EXTENSIONS: %s\n", string_returned); + string strExt = string_returned; + if (strExt.find("cl_khr_priority_hints") != string::npos) + { + log_info("Testing cl_khr_priority_hints...\n", string_returned); + + cl_queue_properties queue_prop[][3] = + { + { + CL_QUEUE_PRIORITY_KHR, CL_QUEUE_PRIORITY_HIGH_KHR, + 0 + }, + { + CL_QUEUE_PRIORITY_KHR, CL_QUEUE_PRIORITY_MED_KHR, + 0 + }, + { + CL_QUEUE_PRIORITY_KHR, CL_QUEUE_PRIORITY_LOW_KHR, + 0 + } + }; + + for (int i = 0; i < 3; ++i) + { + clCommandQueueWrapper q = clCreateCommandQueueWithProperties(context, deviceID, queue_prop[i], &err); + test_error(err, "clCreateCommandQueueWithProperties failed"); + + err = test_enqueue(context, q, kernel, (size_t)num_elements); + if (err != 0) + { + return err; + } + } + } + else + { + log_info("cl_khr_priority_hints is not supported."); + } + + if (strExt.find("cl_khr_throttle_hints") != string::npos) + { + cl_queue_properties queue_prop[][3] = + { + { + CL_QUEUE_THROTTLE_KHR, CL_QUEUE_THROTTLE_HIGH_KHR, + 0 + }, + { + CL_QUEUE_THROTTLE_KHR, CL_QUEUE_THROTTLE_MED_KHR, + 0 + }, + { + CL_QUEUE_THROTTLE_KHR, CL_QUEUE_THROTTLE_LOW_KHR, + 0 + } + }; + + for (int i = 0; i < 3; ++i) + { + clCommandQueueWrapper q = clCreateCommandQueueWithProperties(context, deviceID, queue_prop[i], &err); + test_error(err, "clCreateCommandQueueWithProperties failed"); + + err = test_enqueue(context, q, kernel, (size_t)num_elements); + if (err != 0) + { + return err; + } + } + + } + else + { + log_info("cl_khr_throttle_hints is not supported."); + } + + free(string_returned); + + return 0; +} + diff --git a/test_conformance/api/test_retain.cpp b/test_conformance/api/test_retain.cpp new file mode 100644 index 00000000..384d280e --- /dev/null +++ b/test_conformance/api/test_retain.cpp @@ -0,0 +1,234 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#if !defined(_WIN32) +#include +#endif // !_WIN32 + +// Note: According to spec, the various functions to get instance counts should return an error when passed in an object +// that has already been released. However, the spec is out of date. If it gets re-updated to allow such action, re-enable +// this define. +//#define VERIFY_AFTER_RELEASE 1 + +#define GET_QUEUE_INSTANCE_COUNT(p) numInstances = ( (err = clGetCommandQueueInfo(p, CL_QUEUE_REFERENCE_COUNT, sizeof( numInstances ), &numInstances, NULL)) == CL_SUCCESS ? numInstances : 0 ) +#define GET_MEM_INSTANCE_COUNT(p) numInstances = ( (err = clGetMemObjectInfo(p, CL_MEM_REFERENCE_COUNT, sizeof( numInstances ), &numInstances, NULL)) == CL_SUCCESS ? numInstances : 0 ) + +#define VERIFY_INSTANCE_COUNT(c,rightValue) if( c != rightValue ) { \ +log_error( "ERROR: Instance count for test object is not valid! (should be %d, really is %d)\n", rightValue, c ); \ +return -1; } + +int test_retain_queue_single(cl_device_id deviceID, cl_context context, cl_command_queue queueNotUsed, int num_elements) +{ + cl_command_queue queue; + cl_uint numInstances; + int err; + + + /* Create a test queue */ + queue = clCreateCommandQueueWithProperties( context, deviceID, 0, &err ); + test_error( err, "Unable to create command queue to test with" ); + + /* Test the instance count */ + GET_QUEUE_INSTANCE_COUNT( queue ); + test_error( err, "Unable to get queue instance count" ); + VERIFY_INSTANCE_COUNT( numInstances, 1 ); + + /* Now release the program */ + clReleaseCommandQueue( queue ); +#ifdef VERIFY_AFTER_RELEASE + /* We're not allowed to get the instance count after the object has been completely released. But that's + exactly how we can tell the release worked--by making sure getting the instance count fails! */ + GET_QUEUE_INSTANCE_COUNT( queue ); + if( err != CL_INVALID_COMMAND_QUEUE ) + { + print_error( err, "Command queue was not properly released" ); + return -1; + } +#endif + + return 0; +} + +int test_retain_queue_multiple(cl_device_id deviceID, cl_context context, cl_command_queue queueNotUsed, int num_elements) +{ + cl_command_queue queue; + unsigned int numInstances, i; + int err; + + + /* Create a test program */ + queue = clCreateCommandQueueWithProperties( context, deviceID, 0, &err ); + test_error( err, "Unable to create command queue to test with" ); + + /* Increment 9 times, which should bring the count to 10 */ + for( i = 0; i < 9; i++ ) + { + clRetainCommandQueue( queue ); + } + + /* Test the instance count */ + GET_QUEUE_INSTANCE_COUNT( queue ); + test_error( err, "Unable to get queue instance count" ); + VERIFY_INSTANCE_COUNT( numInstances, 10 ); + + /* Now release 5 times, which should take us to 5 */ + for( i = 0; i < 5; i++ ) + { + clReleaseCommandQueue( queue ); + } + + GET_QUEUE_INSTANCE_COUNT( queue ); + test_error( err, "Unable to get queue instance count" ); + VERIFY_INSTANCE_COUNT( numInstances, 5 ); + + /* Retain again three times, which should take us to 8 */ + for( i = 0; i < 3; i++ ) + { + clRetainCommandQueue( queue ); + } + + GET_QUEUE_INSTANCE_COUNT( queue ); + test_error( err, "Unable to get queue instance count" ); + VERIFY_INSTANCE_COUNT( numInstances, 8 ); + + /* Release 7 times, which should take it to 1 */ + for( i = 0; i < 7; i++ ) + { + clReleaseCommandQueue( queue ); + } + + GET_QUEUE_INSTANCE_COUNT( queue ); + test_error( err, "Unable to get queue instance count" ); + VERIFY_INSTANCE_COUNT( numInstances, 1 ); + + /* And one last one */ + clReleaseCommandQueue( queue ); + +#ifdef VERIFY_AFTER_RELEASE + /* We're not allowed to get the instance count after the object has been completely released. But that's + exactly how we can tell the release worked--by making sure getting the instance count fails! */ + GET_QUEUE_INSTANCE_COUNT( queue ); + if( err != CL_INVALID_COMMAND_QUEUE ) + { + print_error( err, "Command queue was not properly released" ); + return -1; + } +#endif + + return 0; +} + +int test_retain_mem_object_single(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem object; + cl_uint numInstances; + int err; + + + /* Create a test object */ + object = clCreateBuffer( context, CL_MEM_READ_ONLY, 32, NULL, &err ); + test_error( err, "Unable to create buffer to test with" ); + + /* Test the instance count */ + GET_MEM_INSTANCE_COUNT( object ); + test_error( err, "Unable to get mem object count" ); + VERIFY_INSTANCE_COUNT( numInstances, 1 ); + + /* Now release the program */ + clReleaseMemObject( object ); +#ifdef VERIFY_AFTER_RELEASE + /* We're not allowed to get the instance count after the object has been completely released. But that's + exactly how we can tell the release worked--by making sure getting the instance count fails! */ + GET_MEM_INSTANCE_COUNT( object ); + if( err != CL_INVALID_MEM_OBJECT ) + { + print_error( err, "Mem object was not properly released" ); + return -1; + } +#endif + + return 0; +} + +int test_retain_mem_object_multiple(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem object; + unsigned int numInstances, i; + int err; + + + /* Create a test object */ + object = clCreateBuffer( context, CL_MEM_READ_ONLY, 32, NULL, &err ); + test_error( err, "Unable to create buffer to test with" ); + + /* Increment 9 times, which should bring the count to 10 */ + for( i = 0; i < 9; i++ ) + { + clRetainMemObject( object ); + } + + /* Test the instance count */ + GET_MEM_INSTANCE_COUNT( object ); + test_error( err, "Unable to get mem object count" ); + VERIFY_INSTANCE_COUNT( numInstances, 10 ); + + /* Now release 5 times, which should take us to 5 */ + for( i = 0; i < 5; i++ ) + { + clReleaseMemObject( object ); + } + + GET_MEM_INSTANCE_COUNT( object ); + test_error( err, "Unable to get mem object count" ); + VERIFY_INSTANCE_COUNT( numInstances, 5 ); + + /* Retain again three times, which should take us to 8 */ + for( i = 0; i < 3; i++ ) + { + clRetainMemObject( object ); + } + + GET_MEM_INSTANCE_COUNT( object ); + test_error( err, "Unable to get mem object count" ); + VERIFY_INSTANCE_COUNT( numInstances, 8 ); + + /* Release 7 times, which should take it to 1 */ + for( i = 0; i < 7; i++ ) + { + clReleaseMemObject( object ); + } + + GET_MEM_INSTANCE_COUNT( object ); + test_error( err, "Unable to get mem object count" ); + VERIFY_INSTANCE_COUNT( numInstances, 1 ); + + /* And one last one */ + clReleaseMemObject( object ); + +#ifdef VERIFY_AFTER_RELEASE + /* We're not allowed to get the instance count after the object has been completely released. But that's + exactly how we can tell the release worked--by making sure getting the instance count fails! */ + GET_MEM_INSTANCE_COUNT( object ); + if( err != CL_INVALID_MEM_OBJECT ) + { + print_error( err, "Mem object was not properly released" ); + return -1; + } +#endif + + return 0; +} + diff --git a/test_conformance/api/test_retain_program.c b/test_conformance/api/test_retain_program.c new file mode 100644 index 00000000..4930c862 --- /dev/null +++ b/test_conformance/api/test_retain_program.c @@ -0,0 +1,105 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +#if !defined(_WIN32) +#include +#endif + +#include "../../test_common/harness/compat.h" + +int test_release_kernel_order(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_program program; + cl_kernel kernel; + int error; + const char *testProgram[] = { "__kernel void sample_test(__global int *data){}" }; + + /* Create a test program */ + error = create_single_kernel_helper(context, &program, NULL, 1, testProgram, NULL); + test_error( error, "Unable to build sample program to test with" ); + + /* And create a kernel from it */ + kernel = clCreateKernel( program, "sample_test", &error ); + test_error( error, "Unable to create kernel" ); + + /* Now try freeing the program first, then the kernel. If refcounts are right, this should work just fine */ + clReleaseProgram( program ); + clReleaseKernel( kernel ); + + /* If we got here fine, we succeeded. If not, well, we won't be able to return an error :) */ + return 0; +} + +const char *sample_delay_kernel[] = { +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +" for( int i = 0; i < 1000000; i++ ); \n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n" }; + +int test_release_during_execute( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + cl_kernel kernel; + cl_mem streams[2]; + size_t threads[1] = { 10 }, localThreadSize; + + + /* We now need an event to test. So we'll execute a kernel to get one */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_delay_kernel, "sample_test" ) ) + { + return -1; + } + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Set the arguments */ + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[ 0 ]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[ 1 ]); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreadSize ); + test_error( error, "Unable to calc local thread size" ); + + + /* Execute the kernel */ + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, &localThreadSize, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* The kernel should still be executing, but we should still be able to release it. It's not terribly + useful, but we should be able to do it, if the internal refcounting is indeed correct. */ + + clReleaseMemObject( streams[ 1 ] ); + clReleaseMemObject( streams[ 0 ] ); + clReleaseKernel( kernel ); + clReleaseProgram( program ); + + /* Now make sure we're really finished before we go on. */ + error = clFinish(queue); + test_error( error, "Unable to finish context."); + + return 0; +} + + diff --git a/test_conformance/api/test_sub_group_dispatch.cpp b/test_conformance/api/test_sub_group_dispatch.cpp new file mode 100644 index 00000000..b17727c5 --- /dev/null +++ b/test_conformance/api/test_sub_group_dispatch.cpp @@ -0,0 +1,218 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" + +const char *subgroup_dispatch_kernel[] = { +"__kernel void subgroup_dispatch_kernel(__global int *output)\n" +"{\n" +" size_t size = get_num_sub_groups ();\n" +"\n" +" output[0] = size;\n" +"\n" +"}\n" }; + +size_t flatten_ndrange(size_t* ndrange, size_t dim) +{ + switch(dim) + { + case 1: + return *ndrange; + case 2: + return ndrange[0] * ndrange[1]; + case 3: + return ndrange[0] * ndrange[1] * ndrange[2]; + default: + log_error("ERROR: bad ndrange value"); + return 0; + } +} + +cl_int get_sub_group_num(cl_command_queue queue, cl_kernel kernel, clMemWrapper& out, size_t& size, size_t local_size, size_t dim) +{ + size_t ndrange[3] = {local_size, 1, 1}; + cl_int error = CL_SUCCESS; + size = 0; + error = clSetKernelArg(kernel, 0, sizeof(out), &out); + error += clEnqueueNDRangeKernel(queue, kernel, dim, NULL, ndrange, ndrange, 0, NULL, NULL); + error += clEnqueueReadBuffer(queue, out, CL_TRUE, 0, 4, &size, 0, NULL, NULL); + return error; +} + +int test_sub_group_dispatch(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + static const size_t gsize0 = 80; + int i, error; + size_t realSize; + size_t kernel_max_subgroup_size, kernel_subgroup_count; + size_t global[] = {1,1,1}; + size_t max_local; + + cl_platform_id platform; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper out; + + size_t ret_ndrange1d; + size_t ret_ndrange2d[2]; + size_t ret_ndrange3d[3]; + + size_t ret_ndrange2d_flattened; + size_t ret_ndrange3d_flattened; + + error = create_single_kernel_helper_with_build_options(context, &program, &kernel, 1, subgroup_dispatch_kernel, "subgroup_dispatch_kernel", "-cl-std=CL2.0"); + if (error != 0) + return error; + + out = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, sizeof(size_t), NULL, &error); + test_error(error, "clCreateBuffer failed"); + + error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t), &max_local, NULL); + test_error(error, "clGetDeviceInfo failed"); + + + error = clGetDeviceInfo(deviceID, CL_DEVICE_PLATFORM, sizeof(platform), (void *)&platform, NULL); + test_error(error, "clDeviceInfo failed for CL_DEVICE_PLATFORM"); + + // Get the max subgroup size + error = clGetKernelSubGroupInfo(kernel, deviceID, CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE, + sizeof(max_local), &max_local, sizeof(kernel_max_subgroup_size), (void *)&kernel_max_subgroup_size, &realSize); + test_error(error, "clGetKernelSubGroupInfo failed for CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE"); + log_info("The CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE for the kernel is %d.\n", (int)kernel_max_subgroup_size); + + if (realSize != sizeof(kernel_max_subgroup_size)) { + log_error( "ERROR: Returned size of max sub group size not valid! (Expected %d, got %d)\n", (int)sizeof(kernel_max_subgroup_size), (int)realSize ); + return -1; + } + + // Get the number of subgroup for max local size + error = clGetKernelSubGroupInfo(kernel, deviceID, CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE, + sizeof(max_local), &max_local, sizeof(kernel_subgroup_count), (void *)&kernel_subgroup_count, &realSize); + test_error(error, "clGetKernelSubGroupInfo failed for CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE"); + log_info("The CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE for the kernel is %d.\n", (int)kernel_subgroup_count); + + if (realSize != sizeof(kernel_subgroup_count)) { + log_error( "ERROR: Returned size of sub group count not valid! (Expected %d, got %d)\n", (int)sizeof(kernel_subgroup_count), (int)realSize ); + return -1; + } + + // test CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT + for (size_t i = kernel_subgroup_count; i > 0; --i) + { + // test all 3 different dimention of requested local size + size_t expect_size = kernel_max_subgroup_size * i; + size_t kernel_ret_size = 0; + error = clGetKernelSubGroupInfo(kernel, deviceID, CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT, sizeof(i), &i, sizeof(ret_ndrange1d), &ret_ndrange1d, &realSize); + test_error(error, "clGetKernelSubGroupInfo failed for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT"); + if (realSize != sizeof(ret_ndrange1d)) { + log_error( "ERROR: Returned size of sub group count not valid! (Expected %d, got %d)\n", (int)sizeof(kernel_subgroup_count), (int)realSize ); + return -1; + } + + if (ret_ndrange1d != expect_size) + { + log_error( "ERROR: Incorrect value returned for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT! (Expected %d, got %d)\n", (int)expect_size, (int)ret_ndrange1d ); + return -1; + } + + error = get_sub_group_num(queue, kernel, out, kernel_ret_size, ret_ndrange1d, 1); + test_error(error, "Failed to query number of subgroups from kernel"); + if (i != kernel_ret_size) + { + log_error( "ERROR: Mismatch between requested number of subgroups and what get_num_sub_groups() in kernel returned! (Expected %d, got %d)\n", (int)i, (int)kernel_ret_size ); + return -1; + } + + error = clGetKernelSubGroupInfo(kernel, deviceID, CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT, sizeof(i), &i, sizeof(ret_ndrange2d), ret_ndrange2d, &realSize); + test_error(error, "clGetKernelSubGroupInfo failed for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT"); + if (realSize != sizeof(ret_ndrange2d)) { + log_error( "ERROR: Returned size of sub group count not valid! (Expected %d, got %d)\n", (int)sizeof(kernel_subgroup_count), (int)realSize ); + return -1; + } + + ret_ndrange2d_flattened = flatten_ndrange(ret_ndrange2d, 2); + if (ret_ndrange2d_flattened != expect_size || + ret_ndrange2d[1] != 1) + { + log_error( "ERROR: Incorrect value returned for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT! (Expected %d, got %d)\n", (int)expect_size, (int)ret_ndrange2d_flattened ); + return -1; + } + + error = get_sub_group_num(queue, kernel, out, kernel_ret_size, ret_ndrange2d_flattened, 2); + test_error(error, "Failed to query number of subgroups from kernel"); + if (i != kernel_ret_size) + { + log_error( "ERROR: Mismatch between requested number of subgroups and what get_num_sub_groups() in kernel returned! (Expected %d, got %d)\n", (int)i, (int)kernel_ret_size ); + return -1; + } + + error = clGetKernelSubGroupInfo(kernel, deviceID, CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT, sizeof(i), &i, sizeof(ret_ndrange3d), ret_ndrange3d, &realSize); + test_error(error, "clGetKernelSubGroupInfo failed for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT"); + if (realSize != sizeof(ret_ndrange3d)) { + log_error( "ERROR: Returned size of sub group count not valid! (Expected %d, got %d)\n", (int)sizeof(kernel_subgroup_count), (int)realSize ); + return -1; + } + + ret_ndrange3d_flattened = flatten_ndrange(ret_ndrange3d, 3); + if (ret_ndrange3d_flattened != expect_size || + ret_ndrange3d[1] != 1 || + ret_ndrange3d[2] != 1) + { + log_error( "ERROR: Incorrect value returned for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT! (Expected %d, got %d)\n", (int)expect_size, (int)ret_ndrange3d_flattened ); + return -1; + } + + error = get_sub_group_num(queue, kernel, out, kernel_ret_size, ret_ndrange3d_flattened, 3); + test_error(error, "Failed to query number of subgroups from kernel"); + if (i != kernel_ret_size) + { + log_error( "ERROR: Mismatch between requested number of subgroups and what get_num_sub_groups() in kernel returned! (Expected %d, got %d)\n", (int)i, (int)kernel_ret_size ); + return -1; + } + } + + // test when input subgroup count exceeds max wg size + size_t large_sg_size = kernel_subgroup_count + 1; + error = clGetKernelSubGroupInfo(kernel, deviceID, CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT, sizeof(size_t), &large_sg_size, sizeof(ret_ndrange1d), &ret_ndrange1d, &realSize); + test_error(error, "clGetKernelSubGroupInfo failed for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT"); + if (ret_ndrange1d != 0) + { + log_error( "ERROR: Incorrect value returned for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT! (Expected %d, got %d)\n", 0, (int)ret_ndrange1d ); + return -1; + } + + error = clGetKernelSubGroupInfo(kernel, deviceID, CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT, sizeof(size_t), &large_sg_size, sizeof(ret_ndrange2d), ret_ndrange2d, &realSize); + test_error(error, "clGetKernelSubGroupInfo failed for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT"); + if (ret_ndrange2d[0] != 0 || + ret_ndrange2d[1] != 0) + { + log_error( "ERROR: Incorrect value returned for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT!" ); + return -1; + } + + error = clGetKernelSubGroupInfo(kernel, deviceID, CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT, sizeof(size_t), &large_sg_size, sizeof(ret_ndrange3d), ret_ndrange3d, &realSize); + test_error(error, "clGetKernelSubGroupInfo failed for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT"); + if (ret_ndrange3d[0] != 0 || + ret_ndrange3d[1] != 0 || + ret_ndrange3d[2] != 0) + { + log_error( "ERROR: Incorrect value returned for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT!" ); + return -1; + } + + return 0; +} diff --git a/test_conformance/api/test_zero_sized_enqueue.cpp b/test_conformance/api/test_zero_sized_enqueue.cpp new file mode 100644 index 00000000..87aa0d21 --- /dev/null +++ b/test_conformance/api/test_zero_sized_enqueue.cpp @@ -0,0 +1,209 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" + +const char *zero_sized_enqueue_test_kernel[] = { +"__kernel void foo_kernel(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n" }; + +const int bufSize = 128; + +cl_int test_zero_sized_enqueue_and_test_output_buffer(cl_command_queue queue, clKernelWrapper& kernel, clMemWrapper& buf, size_t dim, size_t ndrange[]) +{ + cl_int error = clEnqueueNDRangeKernel(queue, kernel, dim, NULL, ndrange, NULL, 0, NULL, NULL); + if (error != CL_SUCCESS) + { + return error; + } + + clFinish(queue); + + // check output buffer has not changed. + int* output = reinterpret_cast(clEnqueueMapBuffer(queue, buf, CL_TRUE, CL_MAP_READ, 0, sizeof(int) * bufSize, 0, NULL, NULL, &error)); + if (error != CL_SUCCESS) + { + return error; + } + + for (int i = 0; i < bufSize; ++i) + { + if (output[i] != 0) + { + log_error( "ERROR: output buffer value has changed.\n" ); + return CL_INVALID_OPERATION; + } + } + + return clEnqueueUnmapMemObject(queue, buf, output, 0, NULL, NULL); +} + +int test_zero_sized_enqueue_helper(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + size_t ndrange1 = 0; + size_t ndrange20[2] = {0, 0}; + size_t ndrange21[2] = {1, 0}; + size_t ndrange22[2] = {0, 1}; + + size_t ndrange30[3] = {0, 0, 0}; + size_t ndrange31[3] = {1, 0, 0}; + size_t ndrange32[3] = {0, 1, 0}; + size_t ndrange33[3] = {0, 0, 1}; + size_t ndrange34[3] = {0, 1, 1}; + size_t ndrange35[3] = {1, 0, 1}; + size_t ndrange36[3] = {1, 1, 0}; + + streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, bufSize * sizeof(int), NULL, &error); + streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, bufSize * sizeof(int), NULL, &error); + + int* buf = new int[bufSize]; + memset(buf, 0, sizeof(int) * bufSize); + + // update output buffer + error = clEnqueueWriteBuffer(queue, streams[1], CL_TRUE, 0, sizeof(int) * bufSize, buf, 0, NULL, NULL); + + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, zero_sized_enqueue_test_kernel, "foo_kernel" ) != 0 ) + { + return -1; + } + + error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &streams[0]); + test_error( error, "clSetKernelArg failed." ); + error = clSetKernelArg(kernel, 1, sizeof(cl_mem), &streams[1]); + test_error( error, "clSetKernelArg failed." ); + + // Simple API return code tests for 1D, 2D and 3D zero sized ND range. + error = test_zero_sized_enqueue_and_test_output_buffer(queue, kernel, streams[1], 1, &ndrange1); + test_error( error, "1D zero sized kernel enqueue failed." ); + + error = test_zero_sized_enqueue_and_test_output_buffer(queue, kernel, streams[1], 2, ndrange20); + test_error( error, "2D zero sized kernel enqueue failed." ); + + error = test_zero_sized_enqueue_and_test_output_buffer(queue, kernel, streams[1], 2, ndrange21); + test_error( error, "2D zero sized kernel enqueue failed." ); + + error = test_zero_sized_enqueue_and_test_output_buffer(queue, kernel, streams[1], 2, ndrange22); + test_error( error, "2D zero sized kernel enqueue failed." ); + + + error = test_zero_sized_enqueue_and_test_output_buffer(queue, kernel, streams[1], 3, ndrange30); + test_error( error, "3D zero sized kernel enqueue failed." ); + + error = test_zero_sized_enqueue_and_test_output_buffer(queue, kernel, streams[1], 3, ndrange31); + test_error( error, "3D zero sized kernel enqueue failed." ); + + error = test_zero_sized_enqueue_and_test_output_buffer(queue, kernel, streams[1], 3, ndrange32); + test_error( error, "3D zero sized kernel enqueue failed." ); + + error = test_zero_sized_enqueue_and_test_output_buffer(queue, kernel, streams[1], 3, ndrange33); + test_error( error, "3D zero sized kernel enqueue failed." ); + + error = test_zero_sized_enqueue_and_test_output_buffer(queue, kernel, streams[1], 3, ndrange34); + test_error( error, "3D zero sized kernel enqueue failed." ); + + error = test_zero_sized_enqueue_and_test_output_buffer(queue, kernel, streams[1], 3, ndrange35); + test_error( error, "3D zero sized kernel enqueue failed." ); + + error = test_zero_sized_enqueue_and_test_output_buffer(queue, kernel, streams[1], 3, ndrange36); + test_error( error, "3D zero sized kernel enqueue failed." ); + + // Verify zero-sized ND range kernel still satisfy event wait list and correct event object + // is returned + cl_event ev = NULL; + clEventWrapper user_ev = clCreateUserEvent(context, &error); + test_error( error, "user event creation failed." ); + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, ndrange30, NULL, 1, &user_ev, &ev); + test_error( error, "3D zero sized kernel enqueue failed." ); + if (ev == NULL) + { + log_error( "ERROR: failed to create an event object\n" ); + return -1; + } + + cl_int sta; + error = clGetEventInfo(ev, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(cl_int), &sta, NULL); + test_error( error, "Failed to get event status."); + + if (sta != CL_QUEUED) + { + log_error( "ERROR: incorrect zero sized kernel enqueue event status.\n" ); + return -1; + } + + // now unblock zero-sized enqueue + error = clSetUserEventStatus(user_ev, CL_COMPLETE); + test_error( error, "Failed to set user event status."); + + clFinish(queue); + + // now check zero sized enqueue event status + error = clGetEventInfo(ev, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(cl_int), &sta, NULL); + test_error( error, "Failed to get event status."); + + if (sta != CL_COMPLETE) + { + log_error( "ERROR: incorrect zero sized kernel enqueue event status.\n" ); + return -1; + } + + delete [] buf; + + return 0; +} + + +int test_zero_sized_enqueue(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int res = test_zero_sized_enqueue_helper(deviceID, context, queue, num_elements); + if (res != 0) + { + return res; + } + + // now test out of order queue + cl_command_queue_properties props; + cl_int error = clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_PROPERTIES, sizeof(cl_command_queue_properties), &props, NULL); + test_error( error, "clGetDeviceInfo failed."); + + if (props | CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE) + { + // test out of order queue + cl_queue_properties queue_prop_def[] = + { + CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, + 0 + }; + + clCommandQueueWrapper ooqueue = clCreateCommandQueueWithProperties(context, deviceID, queue_prop_def, &error); + test_error( error, "clCreateCommandQueueWithProperties failed."); + + res = test_zero_sized_enqueue_helper(deviceID, context, ooqueue, num_elements); + } + + return res; +} diff --git a/test_conformance/atomics/CMakeLists.txt b/test_conformance/atomics/CMakeLists.txt new file mode 100644 index 00000000..9dcd4bb1 --- /dev/null +++ b/test_conformance/atomics/CMakeLists.txt @@ -0,0 +1,18 @@ +set(MODULE_NAME ATOMICS) + +set(${MODULE_NAME}_SOURCES + main.c + test_atomics.cpp + test_indexed_cases.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) + diff --git a/test_conformance/atomics/Jamfile b/test_conformance/atomics/Jamfile new file mode 100644 index 00000000..8c039e1a --- /dev/null +++ b/test_conformance/atomics/Jamfile @@ -0,0 +1,17 @@ +project + : requirements + gcc:-xc++ + msvc:"/TP" + ; + +exe test_atomics + : main.c + test_atomics.c + test_indexed_cases.c + ; + +install dist + : test_atomics + : debug:$(DIST)/debug/tests/test_conformance/atomics + release:$(DIST)/release/tests/test_conformance/atomics + ; diff --git a/test_conformance/atomics/Makefile b/test_conformance/atomics/Makefile new file mode 100644 index 00000000..aa1c0147 --- /dev/null +++ b/test_conformance/atomics/Makefile @@ -0,0 +1,44 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + test_atomics.cpp \ + test_indexed_cases.c \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/conversions.c \ + ../../test_common/harness/kernelHelpers.c + +DEFINES = + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = $(SOURCES) +HEADERS = +TARGET = test_atomics +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) $(RC_CFLAGS) ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) $(RC_CFLAGS) ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/atomics/main.c b/test_conformance/atomics/main.c new file mode 100644 index 00000000..76df7946 --- /dev/null +++ b/test_conformance/atomics/main.c @@ -0,0 +1,71 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" +#include +#include +#include +#include "procs.h" +#include "../../test_common/harness/testHarness.h" + +#if !defined(_WIN32) +#include +#endif + + +basefn basefn_list[] = { + test_atomic_add, + test_atomic_sub, + test_atomic_xchg, + test_atomic_min, + test_atomic_max, + test_atomic_inc, + test_atomic_dec, + test_atomic_cmpxchg, + test_atomic_and, + test_atomic_or, + test_atomic_xor, + + test_atomic_add_index, + test_atomic_add_index_bin +}; + +const char *basefn_names[] = { + "atomic_add", + "atomic_sub", + "atomic_xchg", + "atomic_min", + "atomic_max", + "atomic_inc", + "atomic_dec", + "atomic_cmpxchg", + "atomic_and", + "atomic_or", + "atomic_xor", + + "atomic_add_index", + "atomic_add_index_bin", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + +int main(int argc, const char *argv[]) +{ + return runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false, false, 0 ); +} + + diff --git a/test_conformance/atomics/procs.h b/test_conformance/atomics/procs.h new file mode 100644 index 00000000..017e6c55 --- /dev/null +++ b/test_conformance/atomics/procs.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/threadTesting.h" +#include "../../test_common/harness/typeWrappers.h" + +extern int create_program_and_kernel(const char *source, const char *kernel_name, cl_program *program_ret, cl_kernel *kernel_ret); + +extern int test_atomic_add(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_sub(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_xchg(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_min(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_max(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_inc(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_dec(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_cmpxchg(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_and(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_or(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_xor(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_atomic_add_index(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_add_index_bin(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + + + diff --git a/test_conformance/atomics/testBase.h b/test_conformance/atomics/testBase.h new file mode 100644 index 00000000..8d58eeb6 --- /dev/null +++ b/test_conformance/atomics/testBase.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testBase_h +#define _testBase_h + +#include "../../test_common/harness/compat.h" +#include +#include +#include +#include +#include + +#include "procs.h" + +#endif // _testBase_h + + + diff --git a/test_conformance/atomics/test_atomics.cpp b/test_conformance/atomics/test_atomics.cpp new file mode 100644 index 00000000..06941e58 --- /dev/null +++ b/test_conformance/atomics/test_atomics.cpp @@ -0,0 +1,1126 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/conversions.h" +#ifndef _WIN32 +#include +#endif + +#define INT_TEST_VALUE 402258822 +#define LONG_TEST_VALUE 515154531254381446LL + + +extern cl_uint gRandomSeed; + +const char *atomic_global_pattern[] = { + "__kernel void test_atomic_fn(volatile __global %s *destMemory, __global %s *oldValues)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + , + "\n" + "}\n" }; + +const char *atomic_local_pattern[] = { + "__kernel void test_atomic_fn(__global %s *finalDest, __global %s *oldValues, volatile __local %s *destMemory, int numDestItems )\n" + "{\n" + " int tid = get_global_id(0);\n" + " int dstItemIdx;\n" + "\n" + " // Everybody does the following line(s), but it all has the same result. We still need to ensure we sync before the atomic op, though\n" + " for( dstItemIdx = 0; dstItemIdx < numDestItems; dstItemIdx++ )\n" + " destMemory[ dstItemIdx ] = finalDest[ dstItemIdx ];\n" + " barrier( CLK_LOCAL_MEM_FENCE );\n" + "\n" + , + " barrier( CLK_LOCAL_MEM_FENCE );\n" + " // Finally, write out the last value. Again, we're synced, so everyone will be writing the same value\n" + " for( dstItemIdx = 0; dstItemIdx < numDestItems; dstItemIdx++ )\n" + " finalDest[ dstItemIdx ] = destMemory[ dstItemIdx ];\n" + "}\n" }; + + +#define TEST_COUNT 128 * 1024 + + +struct TestFns +{ + cl_int mIntStartValue; + cl_long mLongStartValue; + + size_t (*NumResultsFn)( size_t threadSize, ExplicitType dataType ); + + // Integer versions + cl_int (*ExpectedValueIntFn)( size_t size, cl_int *startRefValues, size_t whichDestValue ); + void (*GenerateRefsIntFn)( size_t size, cl_int *startRefValues, MTdata d ); + bool (*VerifyRefsIntFn)( size_t size, cl_int *refValues, cl_int finalValue ); + + // Long versions + cl_long (*ExpectedValueLongFn)( size_t size, cl_long *startRefValues, size_t whichDestValue ); + void (*GenerateRefsLongFn)( size_t size, cl_long *startRefValues, MTdata d ); + bool (*VerifyRefsLongFn)( size_t size, cl_long *refValues, cl_long finalValue ); + + // Float versions + cl_float (*ExpectedValueFloatFn)( size_t size, cl_float *startRefValues, size_t whichDestValue ); + void (*GenerateRefsFloatFn)( size_t size, cl_float *startRefValues, MTdata d ); + bool (*VerifyRefsFloatFn)( size_t size, cl_float *refValues, cl_float finalValue ); +}; + +bool check_atomic_support( cl_device_id device, bool extended, bool isLocal, ExplicitType dataType ) +{ + const char *extensionNames[8] = { + "cl_khr_global_int32_base_atomics", "cl_khr_global_int32_extended_atomics", + "cl_khr_local_int32_base_atomics", "cl_khr_local_int32_extended_atomics", + "cl_khr_int64_base_atomics", "cl_khr_int64_extended_atomics", + "cl_khr_int64_base_atomics", "cl_khr_int64_extended_atomics" // this line intended to be the same as the last one + }; + + size_t index = 0; + if( extended ) + index += 1; + if( isLocal ) + index += 2; + + size_t major, minor; + + int error = get_device_version(device, &major, &minor); + test_error( error, "get_device_version" ); + + switch (dataType) + { + case kInt: + case kUInt: + if( major * 10 + minor >= 11 ) + return 1; + break; + case kLong: + case kULong: + index += 4; + break; + case kFloat: // this has to stay separate since the float atomics arent in the 1.0 extensions + return major * 10 + minor >= 11; + default: + log_error( "ERROR: Unsupported data type (%d) in check_atomic_support\n", dataType ); + return 0; + } + + return is_extension_available( device, extensionNames[index] ); +} + +int test_atomic_function(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, const char *programCore, + TestFns testFns, + bool extended, bool isLocal, ExplicitType dataType, bool matchGroupSize ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + int error; + size_t threads[1]; + clMemWrapper streams[2]; + void *refValues, *startRefValues; + size_t threadSize, groupSize; + const char *programLines[4]; + char pragma[ 512 ]; + char programHeader[ 512 ]; + MTdata d; + size_t typeSize = get_explicit_type_size( dataType ); + + + // Verify we can run first + bool isUnsigned = ( dataType == kULong ) || ( dataType == kUInt ); + if( !check_atomic_support( deviceID, extended, isLocal, dataType ) ) + { + // Only print for the signed (unsigned comes right after, and if signed isn't supported, unsigned isn't either) + if( dataType == kFloat ) + log_info( "\t%s float not supported\n", isLocal ? "Local" : "Global" ); + else if( !isUnsigned ) + log_info( "\t%s %sint%d not supported\n", isLocal ? "Local" : "Global", isUnsigned ? "u" : "", (int)typeSize * 8 ); + // Since we don't support the operation, they implicitly pass + return 0; + } + else + { + if( dataType == kFloat ) + log_info( "\t%s float%s...", isLocal ? "local" : "global", isLocal ? " " : "" ); + else + log_info( "\t%s %sint%d%s%s...", isLocal ? "local" : "global", isUnsigned ? "u" : "", + (int)typeSize * 8, isUnsigned ? "" : " ", isLocal ? " " : "" ); + } + + //// Set up the kernel code + + // Create the pragma line for this kernel + bool isLong = ( dataType == kLong || dataType == kULong ); + sprintf( pragma, "#pragma OPENCL EXTENSION cl_khr%s_int%s_%s_atomics : enable\n", + isLong ? "" : (isLocal ? "_local" : "_global"), isLong ? "64" : "32", + extended ? "extended" : "base" ); + + // Now create the program header + const char *typeName = get_explicit_type_name( dataType ); + if( isLocal ) + sprintf( programHeader, atomic_local_pattern[ 0 ], typeName, typeName, typeName ); + else + sprintf( programHeader, atomic_global_pattern[ 0 ], typeName, typeName ); + + // Set up our entire program now + programLines[ 0 ] = pragma; + programLines[ 1 ] = programHeader; + programLines[ 2 ] = programCore; + programLines[ 3 ] = ( isLocal ) ? atomic_local_pattern[ 1 ] : atomic_global_pattern[ 1 ]; + + if( create_single_kernel_helper( context, &program, &kernel, 4, programLines, "test_atomic_fn" ) ) + { + return -1; + } + + //// Set up to actually run + threadSize = num_elements; + + error = get_max_common_work_group_size( context, kernel, threadSize, &groupSize ); + test_error( error, "Unable to get thread group max size" ); + + if( matchGroupSize ) + // HACK because xchg and cmpxchg apparently are limited by hardware + threadSize = groupSize; + + if( isLocal ) + { + size_t maxSizes[3] = {0, 0, 0}; + error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WORK_ITEM_SIZES, 3*sizeof(size_t), maxSizes, 0); + test_error( error, "Unable to obtain max work item sizes for the device" ); + + size_t workSize; + error = clGetKernelWorkGroupInfo( kernel, deviceID, CL_KERNEL_WORK_GROUP_SIZE, sizeof( workSize ), &workSize, NULL ); + test_error( error, "Unable to obtain max work group size for device and kernel combo" ); + + threadSize = groupSize = workSize; + } + + + log_info( "\t(thread count %d, group size %d)\n", (int)threadSize, (int)groupSize ); + + refValues = (cl_int *)malloc( typeSize * threadSize ); + + if( testFns.GenerateRefsIntFn != NULL ) + { + // We have a ref generator provided + d = init_genrand( gRandomSeed ); + startRefValues = malloc( typeSize * threadSize ); + if( typeSize == 4 ) + testFns.GenerateRefsIntFn( threadSize, (cl_int *)startRefValues, d ); + else + testFns.GenerateRefsLongFn( threadSize, (cl_long *)startRefValues, d ); + free_mtdata(d); + d = NULL; + } + else + startRefValues = NULL; + + // If we're given a num_results function, we need to determine how many result objects we need. If + // we don't have it, we assume it's just 1 + size_t numDestItems = ( testFns.NumResultsFn != NULL ) ? testFns.NumResultsFn( threadSize, dataType ) : 1; + + char * destItems = new char[ typeSize * numDestItems ]; + if( destItems == NULL ) + { + log_error( "ERROR: Unable to allocate memory!\n" ); + return -1; + } + void * startValue = ( typeSize == 4 ) ? (void *)&testFns.mIntStartValue : (void *)&testFns.mLongStartValue; + for( size_t i = 0; i < numDestItems; i++ ) + memcpy( destItems + i * typeSize, startValue, typeSize ); + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), typeSize * numDestItems, destItems, NULL); + if (!streams[0]) + { + log_error("ERROR: Creating output array failed!\n"); + return -1; + } + streams[1] = clCreateBuffer(context, (cl_mem_flags)(( startRefValues != NULL ? CL_MEM_COPY_HOST_PTR : CL_MEM_READ_WRITE )), typeSize * threadSize, startRefValues, NULL); + if (!streams[1]) + { + log_error("ERROR: Creating reference array failed!\n"); + return -1; + } + + /* Set the arguments */ + error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + if( isLocal ) + { + error = clSetKernelArg( kernel, 2, typeSize * numDestItems, NULL ); + test_error( error, "Unable to set indexed local kernel argument" ); + + cl_int numDestItemsInt = (cl_int)numDestItems; + error = clSetKernelArg( kernel, 3, sizeof( cl_int ), &numDestItemsInt ); + test_error( error, "Unable to set indexed kernel argument" ); + } + + /* Run the kernel */ + threads[0] = threadSize; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, &groupSize, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + error = clEnqueueReadBuffer( queue, streams[0], true, 0, typeSize * numDestItems, destItems, 0, NULL, NULL ); + test_error( error, "Unable to read result value!" ); + + error = clEnqueueReadBuffer( queue, streams[1], true, 0, typeSize * threadSize, refValues, 0, NULL, NULL ); + test_error( error, "Unable to read reference values!" ); + + // If we have an expectedFn, then we need to generate a final value to compare against. If we don't + // have one, it's because we're comparing ref values only + if( testFns.ExpectedValueIntFn != NULL ) + { + for( size_t i = 0; i < numDestItems; i++ ) + { + char expected[ 8 ]; + cl_int intVal; + cl_long longVal; + if( typeSize == 4 ) + { + // Int version + intVal = testFns.ExpectedValueIntFn( threadSize, (cl_int *)startRefValues, i ); + memcpy( expected, &intVal, sizeof( intVal ) ); + } + else + { + // Long version + longVal = testFns.ExpectedValueLongFn( threadSize, (cl_long *)startRefValues, i ); + memcpy( expected, &longVal, sizeof( longVal ) ); + } + + if( memcmp( expected, destItems + i * typeSize, typeSize ) != 0 ) + { + if( typeSize == 4 ) + { + cl_int *outValue = (cl_int *)( destItems + i * typeSize ); + log_error( "ERROR: Result %ld from kernel does not validate! (should be %d, was %d)\n", i, intVal, *outValue ); + cl_int *startRefs = (cl_int *)startRefValues; + cl_int *refs = (cl_int *)refValues; + for( i = 0; i < threadSize; i++ ) + { + if( startRefs != NULL ) + log_info( " --- %ld - %d --- %d\n", i, startRefs[i], refs[i] ); + else + log_info( " --- %ld --- %d\n", i, refs[i] ); + } + } + else + { + cl_long *outValue = (cl_long *)( destItems + i * typeSize ); + log_error( "ERROR: Result %ld from kernel does not validate! (should be %lld, was %lld)\n", i, longVal, *outValue ); + cl_long *startRefs = (cl_long *)startRefValues; + cl_long *refs = (cl_long *)refValues; + for( i = 0; i < threadSize; i++ ) + { + if( startRefs != NULL ) + log_info( " --- %ld - %lld --- %lld\n", i, startRefs[i], refs[i] ); + else + log_info( " --- %ld --- %lld\n", i, refs[i] ); + } + } + return -1; + } + } + } + + if( testFns.VerifyRefsIntFn != NULL ) + { + /* Use the verify function to also check the results */ + if( dataType == kFloat ) + { + cl_float *outValue = (cl_float *)destItems; + if( !testFns.VerifyRefsFloatFn( threadSize, (cl_float *)refValues, *outValue ) != 0 ) + { + log_error( "ERROR: Reference values did not validate!\n" ); + return -1; + } + } + else if( typeSize == 4 ) + { + cl_int *outValue = (cl_int *)destItems; + if( !testFns.VerifyRefsIntFn( threadSize, (cl_int *)refValues, *outValue ) != 0 ) + { + log_error( "ERROR: Reference values did not validate!\n" ); + return -1; + } + } + else + { + cl_long *outValue = (cl_long *)destItems; + if( !testFns.VerifyRefsLongFn( threadSize, (cl_long *)refValues, *outValue ) != 0 ) + { + log_error( "ERROR: Reference values did not validate!\n" ); + return -1; + } + } + } + else if( testFns.ExpectedValueIntFn == NULL ) + { + log_error( "ERROR: Test doesn't check total or refs; no values are verified!\n" ); + return -1; + } + + + /* Re-write the starting value */ + for( size_t i = 0; i < numDestItems; i++ ) + memcpy( destItems + i * typeSize, startValue, typeSize ); + error = clEnqueueWriteBuffer( queue, streams[0], true, 0, typeSize * numDestItems, destItems, 0, NULL, NULL ); + test_error( error, "Unable to write starting values!" ); + + /* Run the kernel once for a single thread, so we can verify that the returned value is the original one */ + threads[0] = 1; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, threads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + error = clEnqueueReadBuffer( queue, streams[1], true, 0, typeSize, refValues, 0, NULL, NULL ); + test_error( error, "Unable to read reference values!" ); + + if( memcmp( refValues, destItems, typeSize ) != 0 ) + { + if( typeSize == 4 ) + { + cl_int *s = (cl_int *)destItems; + cl_int *r = (cl_int *)refValues; + log_error( "ERROR: atomic function operated correctly but did NOT return correct 'old' value " + " (should have been %d, returned %d)!\n", *s, *r ); + } + else + { + cl_long *s = (cl_long *)destItems; + cl_long *r = (cl_long *)refValues; + log_error( "ERROR: atomic function operated correctly but did NOT return correct 'old' value " + " (should have been %lld, returned %lld)!\n", *s, *r ); + } + return -1; + } + + delete [] destItems; + free( refValues ); + if( startRefValues != NULL ) + free( startRefValues ); + + return 0; +} + +int test_atomic_function_set(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, const char *programCore, + TestFns testFns, + bool extended, bool matchGroupSize, bool usingAtomicPrefix ) +{ + log_info(" Testing %s functions...\n", usingAtomicPrefix ? "atomic_" : "atom_"); + + int errors = 0; + errors |= test_atomic_function( deviceID, context, queue, num_elements, programCore, testFns, extended, false, kInt, matchGroupSize ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, programCore, testFns, extended, false, kUInt, matchGroupSize ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, programCore, testFns, extended, true, kInt, matchGroupSize ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, programCore, testFns, extended, true, kUInt, matchGroupSize ); + + // Only the 32 bit atomic functions use the "atomic" prefix in 1.1, the 64 bit functions still use the "atom" prefix. + // The argument usingAtomicPrefix is set to true if programCore was generated with the "atomic" prefix. + if (!usingAtomicPrefix) { + errors |= test_atomic_function( deviceID, context, queue, num_elements, programCore, testFns, extended, false, kLong, matchGroupSize ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, programCore, testFns, extended, false, kULong, matchGroupSize ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, programCore, testFns, extended, true, kLong, matchGroupSize ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, programCore, testFns, extended, true, kULong, matchGroupSize ); + } + + return errors; +} + +#pragma mark ---- add + +const char atom_add_core[] = +" oldValues[tid] = atom_add( &destMemory[0], tid + 3 );\n" +" atom_add( &destMemory[0], tid + 3 );\n" +" atom_add( &destMemory[0], tid + 3 );\n" +" atom_add( &destMemory[0], tid + 3 );\n"; + +const char atomic_add_core[] = +" oldValues[tid] = atomic_add( &destMemory[0], tid + 3 );\n" +" atomic_add( &destMemory[0], tid + 3 );\n" +" atomic_add( &destMemory[0], tid + 3 );\n" +" atomic_add( &destMemory[0], tid + 3 );\n"; + +cl_int test_atomic_add_result_int( size_t size, cl_int *startRefValues, size_t whichDestValue ) +{ + cl_int total = 0; + for( size_t i = 0; i < size; i++ ) + total += ( (cl_int)i + 3 ) * 4; + return total; +} + +cl_long test_atomic_add_result_long( size_t size, cl_long *startRefValues, size_t whichDestValue ) +{ + cl_long total = 0; + for( size_t i = 0; i < size; i++ ) + total += ( ( i + 3 ) * 4 ); + return total; +} + +int test_atomic_add(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + TestFns set = { 0, 0LL, NULL, test_atomic_add_result_int, NULL, NULL, test_atomic_add_result_long, NULL, NULL }; + + if( test_atomic_function_set( deviceID, context, queue, num_elements, atom_add_core, set, false, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ false ) != 0 ) + return -1; + if( test_atomic_function_set( deviceID, context, queue, num_elements, atomic_add_core, set, false, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ true ) != 0 ) + return -1; + return 0; +} + +#pragma mark ---- sub + +const char atom_sub_core[] = " oldValues[tid] = atom_sub( &destMemory[0], tid + 3 );\n"; + +const char atomic_sub_core[] = " oldValues[tid] = atomic_sub( &destMemory[0], tid + 3 );\n"; + +cl_int test_atomic_sub_result_int( size_t size, cl_int *startRefValues, size_t whichDestValue ) +{ + cl_int total = INT_TEST_VALUE; + for( size_t i = 0; i < size; i++ ) + total -= (cl_int)i + 3; + return total; +} + +cl_long test_atomic_sub_result_long( size_t size, cl_long *startRefValues, size_t whichDestValue ) +{ + cl_long total = LONG_TEST_VALUE; + for( size_t i = 0; i < size; i++ ) + total -= i + 3; + return total; +} + +int test_atomic_sub(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + TestFns set = { INT_TEST_VALUE, LONG_TEST_VALUE, NULL, test_atomic_sub_result_int, NULL, NULL, test_atomic_sub_result_long, NULL, NULL }; + + if( test_atomic_function_set( deviceID, context, queue, num_elements, atom_sub_core, set, false, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ false ) != 0 ) + return -1; + if( test_atomic_function_set( deviceID, context, queue, num_elements, atomic_sub_core, set, false, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ true ) != 0 ) + return -1; + return 0; +} + +#pragma mark ---- xchg + +const char atom_xchg_core[] = " oldValues[tid] = atom_xchg( &destMemory[0], tid );\n"; + +const char atomic_xchg_core[] = " oldValues[tid] = atomic_xchg( &destMemory[0], tid );\n"; +const char atomic_xchg_float_core[] = " oldValues[tid] = atomic_xchg( &destMemory[0], tid );\n"; + +bool test_atomic_xchg_verify_int( size_t size, cl_int *refValues, cl_int finalValue ) +{ + /* For xchg, each value from 0 to size - 1 should have an entry in the ref array, and ONLY one entry */ + char *valids; + size_t i; + char originalValidCount = 0; + + valids = (char *)malloc( sizeof( char ) * size ); + memset( valids, 0, sizeof( char ) * size ); + + for( i = 0; i < size; i++ ) + { + if( refValues[ i ] == INT_TEST_VALUE ) + { + // Special initial value + originalValidCount++; + continue; + } + if( refValues[ i ] < 0 || (size_t)refValues[ i ] >= size ) + { + log_error( "ERROR: Reference value %ld outside of valid range! (%d)\n", i, refValues[ i ] ); + return false; + } + valids[ refValues[ i ] ] ++; + } + + /* Note: ONE entry will have zero count. It'll be the last one that executed, because that value should be + the final value outputted */ + if( valids[ finalValue ] > 0 ) + { + log_error( "ERROR: Final value %d was also in ref list!\n", finalValue ); + return false; + } + else + valids[ finalValue ] = 1; // So the following loop will be okay + + /* Now check that every entry has one and only one count */ + if( originalValidCount != 1 ) + { + log_error( "ERROR: Starting reference value %d did not occur once-and-only-once (occurred %d)\n", 65191, originalValidCount ); + return false; + } + for( i = 0; i < size; i++ ) + { + if( valids[ i ] != 1 ) + { + log_error( "ERROR: Reference value %ld did not occur once-and-only-once (occurred %d)\n", i, valids[ i ] ); + for( size_t j = 0; j < size; j++ ) + log_info( "%d: %d\n", (int)j, (int)valids[ j ] ); + return false; + } + } + + free( valids ); + return true; +} + +bool test_atomic_xchg_verify_long( size_t size, cl_long *refValues, cl_long finalValue ) +{ + /* For xchg, each value from 0 to size - 1 should have an entry in the ref array, and ONLY one entry */ + char *valids; + size_t i; + char originalValidCount = 0; + + valids = (char *)malloc( sizeof( char ) * size ); + memset( valids, 0, sizeof( char ) * size ); + + for( i = 0; i < size; i++ ) + { + if( refValues[ i ] == LONG_TEST_VALUE ) + { + // Special initial value + originalValidCount++; + continue; + } + if( refValues[ i ] < 0 || (size_t)refValues[ i ] >= size ) + { + log_error( "ERROR: Reference value %ld outside of valid range! (%lld)\n", i, refValues[ i ] ); + return false; + } + valids[ refValues[ i ] ] ++; + } + + /* Note: ONE entry will have zero count. It'll be the last one that executed, because that value should be + the final value outputted */ + if( valids[ finalValue ] > 0 ) + { + log_error( "ERROR: Final value %lld was also in ref list!\n", finalValue ); + return false; + } + else + valids[ finalValue ] = 1; // So the following loop will be okay + + /* Now check that every entry has one and only one count */ + if( originalValidCount != 1 ) + { + log_error( "ERROR: Starting reference value %d did not occur once-and-only-once (occurred %d)\n", 65191, originalValidCount ); + return false; + } + for( i = 0; i < size; i++ ) + { + if( valids[ i ] != 1 ) + { + log_error( "ERROR: Reference value %ld did not occur once-and-only-once (occurred %d)\n", i, valids[ i ] ); + for( size_t j = 0; j < size; j++ ) + log_info( "%d: %d\n", (int)j, (int)valids[ j ] ); + return false; + } + } + + free( valids ); + return true; +} + +bool test_atomic_xchg_verify_float( size_t size, cl_float *refValues, cl_float finalValue ) +{ + /* For xchg, each value from 0 to size - 1 should have an entry in the ref array, and ONLY one entry */ + char *valids; + size_t i; + char originalValidCount = 0; + + valids = (char *)malloc( sizeof( char ) * size ); + memset( valids, 0, sizeof( char ) * size ); + + for( i = 0; i < size; i++ ) + { + cl_int *intRefValue = (cl_int *)( &refValues[ i ] ); + if( *intRefValue == INT_TEST_VALUE ) + { + // Special initial value + originalValidCount++; + continue; + } + if( refValues[ i ] < 0 || (size_t)refValues[ i ] >= size ) + { + log_error( "ERROR: Reference value %ld outside of valid range! (%a)\n", i, refValues[ i ] ); + return false; + } + valids[ (int)refValues[ i ] ] ++; + } + + /* Note: ONE entry will have zero count. It'll be the last one that executed, because that value should be + the final value outputted */ + if( valids[ (int)finalValue ] > 0 ) + { + log_error( "ERROR: Final value %a was also in ref list!\n", finalValue ); + return false; + } + else + valids[ (int)finalValue ] = 1; // So the following loop will be okay + + /* Now check that every entry has one and only one count */ + if( originalValidCount != 1 ) + { + log_error( "ERROR: Starting reference value %d did not occur once-and-only-once (occurred %d)\n", 65191, originalValidCount ); + return false; + } + for( i = 0; i < size; i++ ) + { + if( valids[ i ] != 1 ) + { + log_error( "ERROR: Reference value %ld did not occur once-and-only-once (occurred %d)\n", i, valids[ i ] ); + for( size_t j = 0; j < size; j++ ) + log_info( "%d: %d\n", (int)j, (int)valids[ j ] ); + return false; + } + } + + free( valids ); + return true; +} + +int test_atomic_xchg(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + TestFns set = { INT_TEST_VALUE, LONG_TEST_VALUE, NULL, NULL, NULL, test_atomic_xchg_verify_int, NULL, NULL, test_atomic_xchg_verify_long, NULL, NULL, test_atomic_xchg_verify_float }; + + int errors = test_atomic_function_set( deviceID, context, queue, num_elements, atom_xchg_core, set, false, true, /*usingAtomicPrefix*/ false ); + errors |= test_atomic_function_set( deviceID, context, queue, num_elements, atomic_xchg_core, set, false, true, /*usingAtomicPrefix*/ true ); + + errors |= test_atomic_function( deviceID, context, queue, num_elements, atomic_xchg_float_core, set, false, false, kFloat, true ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, atomic_xchg_float_core, set, false, true, kFloat, true ); + + return errors; +} + + +#pragma mark ---- min + +const char atom_min_core[] = " oldValues[tid] = atom_min( &destMemory[0], oldValues[tid] );\n"; + +const char atomic_min_core[] = " oldValues[tid] = atomic_min( &destMemory[0], oldValues[tid] );\n"; + +cl_int test_atomic_min_result_int( size_t size, cl_int *startRefValues, size_t whichDestValue ) +{ + cl_int total = 0x7fffffffL; + for( size_t i = 0; i < size; i++ ) + { + if( startRefValues[ i ] < total ) + total = startRefValues[ i ]; + } + return total; +} + +void test_atomic_min_gen_int( size_t size, cl_int *startRefValues, MTdata d ) +{ + for( size_t i = 0; i < size; i++ ) + startRefValues[i] = (cl_int)( genrand_int32(d) % 0x3fffffff ) + 0x3fffffff; +} + +cl_long test_atomic_min_result_long( size_t size, cl_long *startRefValues, size_t whichDestValue ) +{ + cl_long total = 0x7fffffffffffffffLL; + for( size_t i = 0; i < size; i++ ) + { + if( startRefValues[ i ] < total ) + total = startRefValues[ i ]; + } + return total; +} + +void test_atomic_min_gen_long( size_t size, cl_long *startRefValues, MTdata d ) +{ + for( size_t i = 0; i < size; i++ ) + startRefValues[i] = (cl_long)( genrand_int32(d) | ( ( (cl_long)genrand_int32(d) & 0x7fffffffL ) << 16 ) ); +} + +int test_atomic_min(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + TestFns set = { 0x7fffffffL, 0x7fffffffffffffffLL, NULL, test_atomic_min_result_int, test_atomic_min_gen_int, NULL, test_atomic_min_result_long, test_atomic_min_gen_long, NULL }; + + if( test_atomic_function_set( deviceID, context, queue, num_elements, atom_min_core, set, true, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ false ) != 0 ) + return -1; + if( test_atomic_function_set( deviceID, context, queue, num_elements, atomic_min_core, set, true, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ true ) != 0 ) + return -1; + return 0; +} + + +#pragma mark ---- max + +const char atom_max_core[] = " oldValues[tid] = atom_max( &destMemory[0], oldValues[tid] );\n"; + +const char atomic_max_core[] = " oldValues[tid] = atomic_max( &destMemory[0], oldValues[tid] );\n"; + +cl_int test_atomic_max_result_int( size_t size, cl_int *startRefValues, size_t whichDestValue ) +{ + cl_int total = 0; + for( size_t i = 0; i < size; i++ ) + { + if( startRefValues[ i ] > total ) + total = startRefValues[ i ]; + } + return total; +} + +void test_atomic_max_gen_int( size_t size, cl_int *startRefValues, MTdata d ) +{ + for( size_t i = 0; i < size; i++ ) + startRefValues[i] = (cl_int)( genrand_int32(d) % 0x3fffffff ) + 0x3fffffff; +} + +cl_long test_atomic_max_result_long( size_t size, cl_long *startRefValues, size_t whichDestValue ) +{ + cl_long total = 0; + for( size_t i = 0; i < size; i++ ) + { + if( startRefValues[ i ] > total ) + total = startRefValues[ i ]; + } + return total; +} + +void test_atomic_max_gen_long( size_t size, cl_long *startRefValues, MTdata d ) +{ + for( size_t i = 0; i < size; i++ ) + startRefValues[i] = (cl_long)( genrand_int32(d) | ( ( (cl_long)genrand_int32(d) & 0x7fffffffL ) << 16 ) ); +} + +int test_atomic_max(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + TestFns set = { 0, 0, NULL, test_atomic_max_result_int, test_atomic_max_gen_int, NULL, test_atomic_max_result_long, test_atomic_max_gen_long, NULL }; + + if( test_atomic_function_set( deviceID, context, queue, num_elements, atom_max_core, set, true, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ false ) != 0 ) + return -1; + if( test_atomic_function_set( deviceID, context, queue, num_elements, atomic_max_core, set, true, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ true ) != 0 ) + return -1; + return 0; +} + + +#pragma mark ---- inc + +const char atom_inc_core[] = " oldValues[tid] = atom_inc( &destMemory[0] );\n"; + +const char atomic_inc_core[] = " oldValues[tid] = atomic_inc( &destMemory[0] );\n"; + +cl_int test_atomic_inc_result_int( size_t size, cl_int *startRefValues, size_t whichDestValue ) +{ + return INT_TEST_VALUE + (cl_int)size; +} + +cl_long test_atomic_inc_result_long( size_t size, cl_long *startRefValues, size_t whichDestValue ) +{ + return LONG_TEST_VALUE + size; +} + +int test_atomic_inc(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + TestFns set = { INT_TEST_VALUE, LONG_TEST_VALUE, NULL, test_atomic_inc_result_int, NULL, NULL, test_atomic_inc_result_long, NULL, NULL }; + + if( test_atomic_function_set( deviceID, context, queue, num_elements, atom_inc_core, set, false, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ false ) != 0 ) + return -1; + if( test_atomic_function_set( deviceID, context, queue, num_elements, atomic_inc_core, set, false, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ true ) != 0 ) + return -1; + return 0; +} + + +#pragma mark ---- dec + +const char atom_dec_core[] = " oldValues[tid] = atom_dec( &destMemory[0] );\n"; + +const char atomic_dec_core[] = " oldValues[tid] = atomic_dec( &destMemory[0] );\n"; + +cl_int test_atomic_dec_result_int( size_t size, cl_int *startRefValues, size_t whichDestValue ) +{ + return INT_TEST_VALUE - (cl_int)size; +} + +cl_long test_atomic_dec_result_long( size_t size, cl_long *startRefValues, size_t whichDestValue ) +{ + return LONG_TEST_VALUE - size; +} + +int test_atomic_dec(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + TestFns set = { INT_TEST_VALUE, LONG_TEST_VALUE, NULL, test_atomic_dec_result_int, NULL, NULL, test_atomic_dec_result_long, NULL, NULL }; + + if( test_atomic_function_set( deviceID, context, queue, num_elements, atom_dec_core, set, false, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ false ) != 0 ) + return -1; + if( test_atomic_function_set( deviceID, context, queue, num_elements, atomic_dec_core, set, false, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ true ) != 0 ) + return -1; + return 0; +} + + +#pragma mark ---- cmpxchg + +/* We test cmpxchg by implementing (the long way) atom_add */ +const char atom_cmpxchg_core[] = +" int oldValue, origValue, newValue;\n" +" do { \n" +" origValue = destMemory[0];\n" +" newValue = origValue + tid + 2;\n" +" oldValue = atom_cmpxchg( &destMemory[0], origValue, newValue );\n" +" } while( oldValue != origValue );\n" +" oldValues[tid] = oldValue;\n" +; + +const char atom_cmpxchg64_core[] = +" long oldValue, origValue, newValue;\n" +" do { \n" +" origValue = destMemory[0];\n" +" newValue = origValue + tid + 2;\n" +" oldValue = atom_cmpxchg( &destMemory[0], origValue, newValue );\n" +" } while( oldValue != origValue );\n" +" oldValues[tid] = oldValue;\n" +; + +const char atomic_cmpxchg_core[] = +" int oldValue, origValue, newValue;\n" +" do { \n" +" origValue = destMemory[0];\n" +" newValue = origValue + tid + 2;\n" +" oldValue = atomic_cmpxchg( &destMemory[0], origValue, newValue );\n" +" } while( oldValue != origValue );\n" +" oldValues[tid] = oldValue;\n" +; + +cl_int test_atomic_cmpxchg_result_int( size_t size, cl_int *startRefValues, size_t whichDestValue ) +{ + cl_int total = INT_TEST_VALUE; + for( size_t i = 0; i < size; i++ ) + total += (cl_int)i + 2; + return total; +} + +cl_long test_atomic_cmpxchg_result_long( size_t size, cl_long *startRefValues, size_t whichDestValue ) +{ + cl_long total = LONG_TEST_VALUE; + for( size_t i = 0; i < size; i++ ) + total += i + 2; + return total; +} + +int test_atomic_cmpxchg(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + TestFns set = { INT_TEST_VALUE, LONG_TEST_VALUE, NULL, test_atomic_cmpxchg_result_int, NULL, NULL, test_atomic_cmpxchg_result_long, NULL, NULL }; + + int errors = 0; + + log_info(" Testing atom_ functions...\n"); + errors |= test_atomic_function( deviceID, context, queue, num_elements, atom_cmpxchg_core, set, false, false, kInt, true ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, atom_cmpxchg_core, set, false, false, kUInt, true ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, atom_cmpxchg_core, set, false, true, kInt, true ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, atom_cmpxchg_core, set, false, true, kUInt, true ); + + errors |= test_atomic_function( deviceID, context, queue, num_elements, atom_cmpxchg64_core, set, false, false, kLong, true ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, atom_cmpxchg64_core, set, false, false, kULong, true ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, atom_cmpxchg64_core, set, false, true, kLong, true ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, atom_cmpxchg64_core, set, false, true, kULong, true ); + + log_info(" Testing atomic_ functions...\n"); + errors |= test_atomic_function( deviceID, context, queue, num_elements, atomic_cmpxchg_core, set, false, false, kInt, true ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, atomic_cmpxchg_core, set, false, false, kUInt, true ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, atomic_cmpxchg_core, set, false, true, kInt, true ); + errors |= test_atomic_function( deviceID, context, queue, num_elements, atomic_cmpxchg_core, set, false, true, kUInt, true ); + + if( errors ) + return -1; + + return 0; +} + +#pragma mark -------- Bitwise functions + +size_t test_bitwise_num_results( size_t threadCount, ExplicitType dataType ) +{ + size_t numBits = get_explicit_type_size( dataType ) * 8; + + return ( threadCount + numBits - 1 ) / numBits; +} + +#pragma mark ---- and + +const char atom_and_core[] = +" size_t numBits = sizeof( destMemory[0] ) * 8;\n" +" int whichResult = tid / numBits;\n" +" int bitIndex = tid - ( whichResult * numBits );\n" +"\n" +" oldValues[tid] = atom_and( &destMemory[whichResult], ~( 1L << bitIndex ) );\n" +; + +const char atomic_and_core[] = +" size_t numBits = sizeof( destMemory[0] ) * 8;\n" +" int whichResult = tid / numBits;\n" +" int bitIndex = tid - ( whichResult * numBits );\n" +"\n" +" oldValues[tid] = atomic_and( &destMemory[whichResult], ~( 1L << bitIndex ) );\n" +; + + +cl_int test_atomic_and_result_int( size_t size, cl_int *startRefValues, size_t whichResult ) +{ + size_t numThreads = ( (size_t)size + 31 ) / 32; + if( whichResult < numThreads - 1 ) + return 0; + + // Last item doesn't get and'ed on every bit, so we have to mask away + size_t numBits = (size_t)size - whichResult * 32; + cl_int bits = (cl_int)0xffffffffL; + for( size_t i = 0; i < numBits; i++ ) + bits &= ~( 1 << i ); + + return bits; +} + +cl_long test_atomic_and_result_long( size_t size, cl_long *startRefValues, size_t whichResult ) +{ + size_t numThreads = ( (size_t)size + 63 ) / 64; + if( whichResult < numThreads - 1 ) + return 0; + + // Last item doesn't get and'ed on every bit, so we have to mask away + size_t numBits = (size_t)size - whichResult * 64; + cl_long bits = (cl_long)0xffffffffffffffffLL; + for( size_t i = 0; i < numBits; i++ ) + bits &= ~( 1 << i ); + + return bits; +} + +int test_atomic_and(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + TestFns set = { 0xffffffff, 0xffffffffffffffffLL, test_bitwise_num_results, + test_atomic_and_result_int, NULL, NULL, test_atomic_and_result_long, NULL, NULL }; + + if( test_atomic_function_set( deviceID, context, queue, num_elements, atom_and_core, set, true, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ false ) != 0 ) + return -1; + if( test_atomic_function_set( deviceID, context, queue, num_elements, atomic_and_core, set, true, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ true ) != 0 ) + return -1; + return 0; +} + + +#pragma mark ---- or + +const char atom_or_core[] = +" size_t numBits = sizeof( destMemory[0] ) * 8;\n" +" int whichResult = tid / numBits;\n" +" int bitIndex = tid - ( whichResult * numBits );\n" +"\n" +" oldValues[tid] = atom_or( &destMemory[whichResult], ( 1L << bitIndex ) );\n" +; + +const char atomic_or_core[] = +" size_t numBits = sizeof( destMemory[0] ) * 8;\n" +" int whichResult = tid / numBits;\n" +" int bitIndex = tid - ( whichResult * numBits );\n" +"\n" +" oldValues[tid] = atomic_or( &destMemory[whichResult], ( 1L << bitIndex ) );\n" +; + +cl_int test_atomic_or_result_int( size_t size, cl_int *startRefValues, size_t whichResult ) +{ + size_t numThreads = ( (size_t)size + 31 ) / 32; + if( whichResult < numThreads - 1 ) + return 0xffffffff; + + // Last item doesn't get and'ed on every bit, so we have to mask away + size_t numBits = (size_t)size - whichResult * 32; + cl_int bits = 0; + for( size_t i = 0; i < numBits; i++ ) + bits |= ( 1 << i ); + + return bits; +} + +cl_long test_atomic_or_result_long( size_t size, cl_long *startRefValues, size_t whichResult ) +{ + size_t numThreads = ( (size_t)size + 63 ) / 64; + if( whichResult < numThreads - 1 ) + return 0x0ffffffffffffffffLL; + + // Last item doesn't get and'ed on every bit, so we have to mask away + size_t numBits = (size_t)size - whichResult * 64; + cl_long bits = 0; + for( size_t i = 0; i < numBits; i++ ) + bits |= ( 1LL << i ); + + return bits; +} + +int test_atomic_or(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + TestFns set = { 0, 0LL, test_bitwise_num_results, test_atomic_or_result_int, NULL, NULL, test_atomic_or_result_long, NULL, NULL }; + + if( test_atomic_function_set( deviceID, context, queue, num_elements, atom_or_core, set, true, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ false ) != 0 ) + return -1; + if( test_atomic_function_set( deviceID, context, queue, num_elements, atomic_or_core, set, true, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ true ) != 0 ) + return -1; + return 0; +} + + +#pragma mark ---- xor + +const char atom_xor_core[] = +" size_t numBits = sizeof( destMemory[0] ) * 8;\n" +" int bitIndex = tid & ( numBits - 1 );\n" +"\n" +" oldValues[tid] = atom_xor( &destMemory[0], 1 << bitIndex );\n" +; + +const char atomic_xor_core[] = +" size_t numBits = sizeof( destMemory[0] ) * 8;\n" +" int bitIndex = tid & ( numBits - 1 );\n" +"\n" +" oldValues[tid] = atomic_xor( &destMemory[0], 1 << bitIndex );\n" +; + +cl_int test_atomic_xor_result_int( size_t size, cl_int *startRefValues, size_t whichResult ) +{ + cl_int total = 0x2f08ab41; + for( size_t i = 0; i < size; i++ ) + total ^= ( 1 << ( i & 31 ) ); + return total; +} + +cl_long test_atomic_xor_result_long( size_t size, cl_long *startRefValues, size_t whichResult ) +{ + cl_long total = 0x2f08ab418ba0541LL; + for( size_t i = 0; i < size; i++ ) + total ^= ( 1LL << ( i & 63 ) ); + return total; +} + +int test_atomic_xor(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + TestFns set = { 0x2f08ab41, 0x2f08ab418ba0541LL, NULL, test_atomic_xor_result_int, NULL, NULL, test_atomic_xor_result_long, NULL, NULL }; + + if( test_atomic_function_set( deviceID, context, queue, num_elements, atom_xor_core, set, true, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ false ) != 0 ) + return -1; + if( test_atomic_function_set( deviceID, context, queue, num_elements, atomic_xor_core, set, true, /*matchGroupSize*/ false, /*usingAtomicPrefix*/ true ) != 0 ) + return -1; + return 0; +} + + + + diff --git a/test_conformance/atomics/test_indexed_cases.c b/test_conformance/atomics/test_indexed_cases.c new file mode 100644 index 00000000..a620d6ef --- /dev/null +++ b/test_conformance/atomics/test_indexed_cases.c @@ -0,0 +1,380 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/conversions.h" + +extern cl_uint gRandomSeed; + +const char * atomic_index_source = +"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n" +"// Counter keeps track of which index in counts we are using.\n" +"// We get that value, increment it, and then set that index in counts to our thread ID.\n" +"// At the end of this we should have all thread IDs in some random location in counts\n" +"// exactly once. If atom_add failed then we will write over various thread IDs and we\n" +"// will be missing some.\n" +"\n" +"__kernel void add_index_test(__global int *counter, __global int *counts) {\n" +" int tid = get_global_id(0);\n" +" \n" +" int counter_to_use = atom_add(counter, 1);\n" +" counts[counter_to_use] = tid;\n" +"}"; + +int test_atomic_add_index(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper counter, counters; + size_t numGlobalThreads, numLocalThreads; + int fail = 0, succeed = 0, err; + + /* Check if atomics are supported. */ + if (!is_extension_available(deviceID, "cl_khr_global_int32_base_atomics")) { + log_info("Base atomics not supported (cl_khr_global_int32_base_atomics). Skipping test.\n"); + return 0; + } + + //===== add_index test + // The index test replicates what particles does. + // It uses one memory location to keep track of the current index and then each thread + // does an atomic add to it to get its new location. The threads then write to their + // assigned location. At the end we check to make sure that each thread's ID shows up + // exactly once in the output. + + numGlobalThreads = 2048; + + if( create_single_kernel_helper( context, &program, &kernel, 1, &atomic_index_source, "add_index_test" ) ) + return -1; + + if( get_max_common_work_group_size( context, kernel, numGlobalThreads, &numLocalThreads ) ) + return -1; + + log_info("Execute global_threads:%d local_threads:%d\n", + (int)numGlobalThreads, (int)numLocalThreads); + + // Create the counter that will keep track of where each thread writes. + counter = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), + sizeof(cl_int) * 1, NULL, NULL); + // Create the counters that will hold the results of each thread writing + // its ID into a (hopefully) unique location. + counters = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), + sizeof(cl_int) * numGlobalThreads, NULL, NULL); + + // Reset all those locations to -1 to indciate they have not been used. + cl_int *values = (cl_int*) malloc(sizeof(cl_int)*numGlobalThreads); + if (values == NULL) { + log_error("add_index_test FAILED to allocate memory for initial values.\n"); + fail = 1; succeed = -1; + } else { + memset(values, -1, numLocalThreads); + unsigned int i=0; + for (i=0; i= max_counts_per_bin) { + bin = random_in_range(0, number_of_bins-1, d); + } + if (bin >= number_of_bins) + log_error("add_index_bin_test internal error generating bin assignments: bin %d >= number_of_bins %d.\n", bin, number_of_bins); + if (l_bin_counts[bin]+1 > max_counts_per_bin) + log_error("add_index_bin_test internal error generating bin assignments: bin %d has more entries (%d) than max_counts_per_bin (%d).\n", bin, l_bin_counts[bin], max_counts_per_bin); + l_bin_counts[bin]++; + l_bin_assignments[i] = bin; + // log_info("item %d assigned to bin %d (%d items)\n", i, bin, l_bin_counts[bin]); + } + err = clEnqueueWriteBuffer(queue, bin_assignments, true, 0, sizeof(cl_int)*number_of_items, l_bin_assignments, 0, NULL, NULL); + if (err) { + log_error("add_index_bin_test FAILED to set initial values for bin_assignments: %d\n", err); + return -1; + } + // Setup the kernel + err = clSetKernelArg(kernel, 0, sizeof(bin_counters), &bin_counters); + err |= clSetKernelArg(kernel, 1, sizeof(bins), &bins); + err |= clSetKernelArg(kernel, 2, sizeof(bin_assignments), &bin_assignments); + err |= clSetKernelArg(kernel, 3, sizeof(max_counts_per_bin), &max_counts_per_bin); + if (err) { + log_error("add_index_bin_test FAILED to set kernel arguments: %d\n", err); + fail=1; succeed=-1; + return -1; + } + + err = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, global_threads, local_threads, 0, NULL, NULL ); + if (err) { + log_error("add_index_bin_test FAILED to execute kernel: %d\n", err); + fail=1; succeed=-1; + } + + cl_int *final_bin_assignments = (cl_int*)malloc(sizeof(cl_int)*number_of_bins*max_counts_per_bin); + if (!final_bin_assignments) { + log_error("add_index_bin_test FAILED to allocate initial values for final_bin_assignments.\n"); + return -1; + } + err = clEnqueueReadBuffer( queue, bins, true, 0, sizeof(cl_int)*number_of_bins*max_counts_per_bin, final_bin_assignments, 0, NULL, NULL ); + if (err) { + log_error("add_index_bin_test FAILED to read back bins: %d\n", err); + fail = 1; succeed=-1; + } + + cl_int *final_bin_counts = (cl_int*)malloc(sizeof(cl_int)*number_of_bins); + if (!final_bin_counts) { + log_error("add_index_bin_test FAILED to allocate initial values for final_bin_counts.\n"); + return -1; + } + err = clEnqueueReadBuffer( queue, bin_counters, true, 0, sizeof(cl_int)*number_of_bins, final_bin_counts, 0, NULL, NULL ); + if (err) { + log_error("add_index_bin_test FAILED to read back bin_counters: %d\n", err); + fail = 1; succeed=-1; + } + + // Verification. + int errors=0; + int current_bin; + int search; + // Print out all the contents of the bins. + // for (current_bin=0; current_bingcc:-xc++ + msvc:"/TP" + ; + +exe test_basic + : main.c + test_fpmath_float.c test_fpmath_float2.c test_fpmath_float4.c + test_intmath_int.c test_intmath_int2.c test_intmath_int4.c + test_intmath_long.c test_intmath_long2.c test_intmath_long4.c + test_hiloeo.c test_local.c test_pointercast.c + test_if.c test_sizeof.c test_loop.c + test_readimage.c test_readimage_int16.c test_readimage_fp32.c + test_readimage3d.c test_readimage3d_int16.c test_readimage3d_fp32.c + test_writeimage.c test_writeimage_int16.c test_writeimage_fp32.c + test_multireadimageonefmt.c test_multireadimagemultifmt.c + test_imagedim.c + test_vloadstore.c + test_int2float.c test_float2int.c + test_createkernelsinprogram.c + test_hostptr.c + test_explicit_s2v.cpp + test_constant.c + test_constant_source.cpp + test_image_multipass.c + test_imagereadwrite.c test_imagereadwrite3d.c + test_bufferreadwriterect.c + test_image_param.c + test_imagenpot.c + test_image_r8.c + test_barrier.c + test_arrayreadwrite.c + test_arraycopy.c + test_imagearraycopy.c + test_imagearraycopy3d.c + test_imagecopy.c + test_imagerandomcopy.c + test_arrayimagecopy.c + test_arrayimagecopy3d.c + test_imagecopy3d.c + test_enqueue_map.cpp + test_work_item_functions.cpp + test_astype.cpp + test_async_copy.cpp + test_async_strided_copy.cpp + test_numeric_constants.cpp + test_kernel_call_kernel_function.cpp + test_basic_parameter_types.c + test_vector_creation.cpp + test_vec_type_hint.c + test_preprocessors.cpp + test_kernel_memory_alignment.cpp + test_global_work_offsets.cpp + test_local_kernel_scope.cpp + test_get_linear_ids.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/rounding_mode.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/typeWrappers.cpp + ../../test_common/harness/imageHelpers.cpp + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + : windows:../../test_common/harness/msvc9.c + ; + +install dist + : test_basic + : debug:$(DIST)/debug/tests/test_conformance/basic + release:$(DIST)/release/tests/test_conformance/basic + ; + diff --git a/test_conformance/basic/Makefile b/test_conformance/basic/Makefile new file mode 100644 index 00000000..faac0a80 --- /dev/null +++ b/test_conformance/basic/Makefile @@ -0,0 +1,103 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + test_fpmath_float.c test_fpmath_float2.c test_fpmath_float4.c \ + test_intmath_int.c test_intmath_int2.c test_intmath_int4.c \ + test_intmath_long.c test_intmath_long2.c test_intmath_long4.c \ + test_hiloeo.c test_local.c test_local_kernel_scope.cpp test_pointercast.c \ + test_if.c test_sizeof.c test_loop.c \ + test_readimage.c test_readimage_int16.c test_readimage_fp32.c \ + test_readimage3d.c test_readimage3d_int16.c test_readimage3d_fp32.c \ + test_writeimage.c test_writeimage_int16.c test_writeimage_fp32.c \ + test_multireadimageonefmt.c test_multireadimagemultifmt.c \ + test_imagedim.c \ + test_vloadstore.c \ + test_int2float.c test_float2int.c \ + test_createkernelsinprogram.c \ + test_hostptr.c \ + test_explicit_s2v.cpp \ + test_constant.c \ + test_constant_source.cpp \ + test_image_multipass.c \ + test_imagereadwrite.c test_imagereadwrite3d.c \ + test_bufferreadwriterect.c \ + test_image_param.c \ + test_imagenpot.c \ + test_image_r8.c \ + test_barrier.c \ + test_wg_barrier.c \ + test_arrayreadwrite.c \ + test_arraycopy.c \ + test_imagearraycopy.c \ + test_imagearraycopy3d.c \ + test_imagecopy.c \ + test_imagerandomcopy.c \ + test_arrayimagecopy.c \ + test_arrayimagecopy3d.c\ + test_imagecopy3d.c \ + test_enqueue_map.cpp \ + test_work_item_functions.cpp \ + test_astype.cpp \ + test_async_copy.cpp \ + test_async_strided_copy.cpp \ + test_numeric_constants.cpp \ + test_kernel_call_kernel_function.cpp \ + test_basic_parameter_types.c \ + test_vector_creation.cpp \ + test_vec_type_hint.c \ + test_preprocessors.cpp \ + test_kernel_memory_alignment.cpp \ + test_global_work_offsets.cpp \ + test_simple_image_pitch.c \ + test_queue_priority.c \ + test_global_linear_id.c \ + test_local_linear_id.c \ + test_enqueued_local_size.c \ + test_get_linear_ids.c \ + test_progvar.cpp \ + test_rw_image_access_qualifier.c \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/rounding_mode.c \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/typeWrappers.cpp \ + ../../test_common/harness/imageHelpers.cpp \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/conversions.c + +DEFINES = + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = $(SOURCES) +HEADERS = +TARGET = test_basic +INCLUDE = +COMPILERFLAGS = -c -Wall -g -O0 -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. + + + diff --git a/test_conformance/basic/main.c b/test_conformance/basic/main.c new file mode 100644 index 00000000..893eaeb5 --- /dev/null +++ b/test_conformance/basic/main.c @@ -0,0 +1,303 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#if !defined(_WIN32) +#include +#endif + +#include +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "procs.h" + +// FIXME: To use certain functions in ../../test_common/harness/imageHelpers.h +// (for example, generate_random_image_data()), the tests are required to declare +// the following variables (): +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +bool gTestRounding = false; + +basefn basefn_list[] = { + test_hostptr, + test_fpmath_float, + test_fpmath_float2, + test_fpmath_float4, + test_intmath_int, + test_intmath_int2, + test_intmath_int4, + test_intmath_long, + test_intmath_long2, + test_intmath_long4, + test_hiloeo, + test_if, + test_sizeof, + test_loop, + test_pointer_cast, + test_local_arg_def, + test_local_kernel_def, + test_local_kernel_scope, + test_constant, + test_constant_source, + test_readimage, + test_readimage_int16, + test_readimage_fp32, + test_writeimage, + test_writeimage_int16, + test_writeimage_fp32, + test_multireadimageonefmt, + + test_multireadimagemultifmt, + test_image_r8, + test_barrier, + test_wg_barrier, + test_int2float, + test_float2int, + test_imagereadwrite, + test_imagereadwrite3d, + test_readimage3d, + test_readimage3d_int16, + test_readimage3d_fp32, + test_bufferreadwriterect, + test_arrayreadwrite, + test_arraycopy, + test_imagearraycopy, + test_imagearraycopy3d, + test_imagecopy, + test_imagecopy3d, + test_imagerandomcopy, + test_arrayimagecopy, + test_arrayimagecopy3d, + test_imagenpot, + + test_vload_global, + test_vload_local, + test_vload_constant, + test_vload_private, + test_vstore_global, + test_vstore_local, + test_vstore_private, + + test_createkernelsinprogram, + test_imagedim_pow2, + test_imagedim_non_pow2, + test_image_param, + test_image_multipass_integer_coord, + test_image_multipass_float_coord, + test_explicit_s2v_bool, + test_explicit_s2v_char, + test_explicit_s2v_uchar, + test_explicit_s2v_short, + test_explicit_s2v_ushort, + test_explicit_s2v_int, + test_explicit_s2v_uint, + test_explicit_s2v_long, + test_explicit_s2v_ulong, + test_explicit_s2v_float, + test_explicit_s2v_double, + + test_enqueue_map_buffer, + test_enqueue_map_image, + + test_work_item_functions, + + test_astype, + + test_async_copy_global_to_local, + test_async_copy_local_to_global, + test_async_strided_copy_global_to_local, + test_async_strided_copy_local_to_global, + test_prefetch, + + test_kernel_call_kernel_function, + test_host_numeric_constants, + test_kernel_numeric_constants, + test_kernel_limit_constants, + test_kernel_preprocessor_macros, + + test_basic_parameter_types, + test_vector_creation, + test_vec_type_hint, + test_kernel_memory_alignment_local, + test_kernel_memory_alignment_global, + test_kernel_memory_alignment_constant, + test_kernel_memory_alignment_private, + + test_progvar_prog_scope_misc, + test_progvar_prog_scope_uninit, + test_progvar_prog_scope_init, + test_progvar_func_scope, + + test_global_work_offsets, + test_get_global_offset, + + test_global_linear_id, + test_local_linear_id, + test_enqueued_local_size, + + test_simple_read_image_pitch, + test_simple_write_image_pitch, + +#if defined( __APPLE__ ) + test_queue_priority, +#endif + + test_get_linear_ids, + test_rw_image_access_qualifier +}; + +const char *basefn_names[] = { + "hostptr", + "fpmath_float", + "fpmath_float2", + "fpmath_float4", + "intmath_int", + "intmath_int2", + "intmath_int4", + "intmath_long", + "intmath_long2", + "intmath_long4", + "hiloeo", + "if", + "sizeof", + "loop", + "pointer_cast", + "local_arg_def", + "local_kernel_def", + "local_kernel_scope", + "constant", + "constant_source", + "readimage", + "readimage_int16", + "readimage_fp32", + "writeimage", + "writeimage_int16", + "writeimage_fp32", + "mri_one", + + "mri_multiple", + "image_r8", + "barrier", + "wg_barrier", + "int2float", + "float2int", + "imagereadwrite", + "imagereadwrite3d", + "readimage3d", + "readimage3d_int16", + "readimage3d_fp32", + "bufferreadwriterect", + "arrayreadwrite", + "arraycopy", + "imagearraycopy", + "imagearraycopy3d", + "imagecopy", + "imagecopy3d", + "imagerandomcopy", + "arrayimagecopy", + "arrayimagecopy3d", + "imagenpot", + + "vload_global", + "vload_local", + "vload_constant", + "vload_private", + "vstore_global", + "vstore_local", + "vstore_private", + + "createkernelsinprogram", + "imagedim_pow2", + "imagedim_non_pow2", + "image_param", + "image_multipass_integer_coord", + "image_multipass_float_coord", + "explicit_s2v_bool", + "explicit_s2v_char", + "explicit_s2v_uchar", + "explicit_s2v_short", + "explicit_s2v_ushort", + "explicit_s2v_int", + "explicit_s2v_uint", + "explicit_s2v_long", + "explicit_s2v_ulong", + "explicit_s2v_float", + "explicit_s2v_double", + + "enqueue_map_buffer", + "enqueue_map_image", + + "work_item_functions", + + "astype", + + "async_copy_global_to_local", + "async_copy_local_to_global", + "async_strided_copy_global_to_local", + "async_strided_copy_local_to_global", + "prefetch", + + "kernel_call_kernel_function", + "host_numeric_constants", + "kernel_numeric_constants", + "kernel_limit_constants", + "kernel_preprocessor_macros", + + "parameter_types", + + "vector_creation", + "vec_type_hint", + + "kernel_memory_alignment_local", + "kernel_memory_alignment_global", + "kernel_memory_alignment_constant", + "kernel_memory_alignment_private", + + "progvar_prog_scope_misc", + "progvar_prog_scope_uninit", + "progvar_prog_scope_init", + "progvar_func_scope", + + "global_work_offsets", + "get_global_offset", + + "global_linear_id", + "local_linear_id", + "enqueued_local_size", + + "simple_read_image_pitch", + "simple_write_image_pitch", + +#if defined( __APPLE__ ) + "queue_priority", +#endif + + "get_linear_ids", + "test_rw_image_access_qualifier", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + + +int main(int argc, const char *argv[]) +{ + return runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false, false, 0 ); +} + + + diff --git a/test_conformance/basic/procs.h b/test_conformance/basic/procs.h new file mode 100644 index 00000000..44b2dec7 --- /dev/null +++ b/test_conformance/basic/procs.h @@ -0,0 +1,160 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/rounding_mode.h" + +extern void memset_pattern4(void *dest, const void *src_pattern, size_t bytes ); + +extern int test_hostptr(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_fpmath_float(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_fpmath_float2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_fpmath_float4(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_intmath_int(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_intmath_int2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_intmath_int4(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_intmath_long(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_intmath_long2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_intmath_long4(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_hiloeo(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_if(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_sizeof(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_loop(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_pointer_cast(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_local_arg_def(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_local_kernel_def(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_local_kernel_scope(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_constant(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_constant_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_readimage(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_readimage_int16(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_readimage_fp32(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_writeimage(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_writeimage_int16(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_writeimage_fp32(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_multireadimageonefmt(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_multireadimagemultifmt(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_image_r8(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_simplebarrier(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_barrier(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_wg_barrier(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_int2float(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_float2int(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagearraycopy(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagearraycopy3d(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagereadwrite(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagereadwrite3d(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_readimage3d(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_readimage3d_int16(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_readimage3d_fp32(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_bufferreadwriterect(cl_device_id device, cl_context context, cl_command_queue queue_, int num_elements); +extern int test_imagecopy(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagecopy3d(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagerandomcopy(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_arraycopy(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems); +extern int test_arrayimagecopy(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_arrayimagecopy3d(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagenpot(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_sampler_float(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_sampler_int(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_createkernelsinprogram(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_single_large_allocation(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_multiple_max_allocation(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_arrayreadwrite(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagedim_pow2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagedim_non_pow2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_image_param(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_image_multipass_integer_coord(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_image_multipass_float_coord(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_vload_global(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vload_local(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vload_constant(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vload_private(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vstore_global(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vstore_local(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vstore_private(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_explicit_s2v_bool(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_char(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_uchar(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_short(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_ushort(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_int(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_uint(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_long(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_ulong(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_float(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_enqueue_map_buffer(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_enqueue_map_image(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_work_item_functions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_astype(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_native_kernel(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_async_copy_global_to_local(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_async_copy_local_to_global(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_async_strided_copy_global_to_local(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_async_strided_copy_local_to_global(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_prefetch(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_host_numeric_constants(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_kernel_numeric_constants(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_kernel_limit_constants(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_kernel_preprocessor_macros(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_kernel_call_kernel_function(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_basic_parameter_types(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vector_creation(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vec_type_hint(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + + +extern int test_kernel_memory_alignment_local(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); +extern int test_kernel_memory_alignment_global(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); +extern int test_kernel_memory_alignment_constant(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); +extern int test_kernel_memory_alignment_private(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); + +extern int test_progvar_prog_scope_misc(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); +extern int test_progvar_prog_scope_uninit(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); +extern int test_progvar_prog_scope_init(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); +extern int test_progvar_func_scope(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); + +extern int test_global_work_offsets(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); +extern int test_get_global_offset(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); + +extern int test_global_linear_id(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); +extern int test_local_linear_id(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); +extern int test_enqueued_local_size(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); + +extern int test_simple_read_image_pitch(cl_device_id device, cl_context cl_context_, cl_command_queue q, int num_elements); +extern int test_simple_write_image_pitch(cl_device_id device, cl_context cl_context_, cl_command_queue q, int num_elements); + +#if defined( __APPLE__ ) +extern int test_queue_priority(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); +#endif + +extern int test_get_linear_ids(cl_device_id device, cl_context cl_context_, cl_command_queue q, int num_elements); +extern int test_rw_image_access_qualifier(cl_device_id device_id, cl_context context, cl_command_queue commands, int num_elements); + diff --git a/test_conformance/basic/run_array b/test_conformance/basic/run_array new file mode 100644 index 00000000..07d67892 --- /dev/null +++ b/test_conformance/basic/run_array @@ -0,0 +1,3 @@ +#!/bin/sh +cd `dirname $0` +./test_basic arrayreadwrite arraycopy bufferreadwriterect $@ diff --git a/test_conformance/basic/run_array_image_copy b/test_conformance/basic/run_array_image_copy new file mode 100644 index 00000000..f88ec2a0 --- /dev/null +++ b/test_conformance/basic/run_array_image_copy @@ -0,0 +1,3 @@ +#!/bin/sh +cd `dirname $0` +./test_basic arrayimagecopy arrayimagecopy3d imagearraycopy diff --git a/test_conformance/basic/run_image b/test_conformance/basic/run_image new file mode 100644 index 00000000..9bb5ee1b --- /dev/null +++ b/test_conformance/basic/run_image @@ -0,0 +1,17 @@ +#!/bin/sh +cd `dirname $0` +./test_basic \ +imagecopy imagerandomcopy \ +imagearraycopy imagearraycopy3d \ +image_r8 \ +readimage readimage_int16 readimage_fp32 \ +writeimage writeimage_int16 writeimage_fp32 \ +imagenpot \ +image_param \ +image_multipass_integer_coord \ +readimage3d \ +readimage3d_int16 \ +readimage3d_fp32 \ +imagereadwrite3d \ +imagereadwrite \ +$@ diff --git a/test_conformance/basic/run_multi_read_image b/test_conformance/basic/run_multi_read_image new file mode 100644 index 00000000..aa87b1cd --- /dev/null +++ b/test_conformance/basic/run_multi_read_image @@ -0,0 +1,4 @@ +#!/bin/sh +cd `dirname $0` +./test_basic mri_one mri_multiple + diff --git a/test_conformance/basic/test_arraycopy.c b/test_conformance/basic/test_arraycopy.c new file mode 100644 index 00000000..5104c49b --- /dev/null +++ b/test_conformance/basic/test_arraycopy.c @@ -0,0 +1,201 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +const char *copy_kernel_code = +"__kernel void test_copy(__global unsigned int *src, __global unsigned int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = src[tid];\n" +"}\n"; + +int +test_arraycopy(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_uint *input_ptr, *output_ptr; + cl_mem streams[4], results; + cl_program program; + cl_kernel kernel; + unsigned num_elements = 128 * 1024; + cl_uint num_copies = 1; + size_t delta_offset; + unsigned i; + cl_int err; + MTdata d; + + int error_count = 0; + + input_ptr = (cl_uint*)malloc(sizeof(cl_uint) * num_elements); + output_ptr = (cl_uint*)malloc(sizeof(cl_uint) * num_elements); + + // results + results = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * num_elements, NULL, &err); + test_error(err, "clCreateBuffer failed"); + +/*****************************************************************************************************************************************/ +#pragma mark client backing + + log_info("Testing CL_MEM_USE_HOST_PTR buffer with clEnqueueCopyBuffer\n"); + // randomize data + d = init_genrand( gRandomSeed ); + for (i=0; i +#include +#include +#include +#include + +#include "procs.h" + +int test_arrayimagecopy_single_format(cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format) +{ + cl_uchar *bufptr, *imgptr; + clMemWrapper buffer, image; + int img_width = 512; + int img_height = 512; + size_t elem_size; + size_t buffer_size; + int i; + cl_int err; + MTdata d; + cl_event copyevent; + + log_info("Testing %s %s\n", GetChannelOrderName(format->image_channel_order), GetChannelTypeName(format->image_channel_data_type)); + + image = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), format, img_width, img_height, 0, NULL, &err); + test_error(err, "create_image_2d failed"); + + err = clGetImageInfo(image, CL_IMAGE_ELEMENT_SIZE, sizeof(size_t), &elem_size, NULL); + test_error(err, "clGetImageInfo failed"); + + buffer_size = sizeof(cl_uchar) * elem_size * img_width * img_height; + + buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), buffer_size, NULL, &err); + test_error(err, "clCreateBuffer failed"); + + d = init_genrand( gRandomSeed ); + bufptr = (cl_uchar*)malloc(buffer_size); + for (i=0; i<(int)buffer_size; i++) { + bufptr[i] = (cl_uchar)genrand_int32(d); + } + free_mtdata(d); d = NULL; + + size_t origin[3]={0,0,0}, region[3]={img_width,img_height,1}; + err = clEnqueueWriteBuffer( queue, buffer, CL_TRUE, 0, buffer_size, bufptr, 0, NULL, NULL); + test_error(err, "clEnqueueWriteBuffer failed"); + + err = clEnqueueCopyBufferToImage( queue, buffer, image, 0, origin, region, 0, NULL, ©event ); + test_error(err, "clEnqueueCopyImageToBuffer failed"); + + imgptr = (cl_uchar*)malloc(buffer_size); + + err = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, imgptr, 1, ©event, NULL ); + test_error(err, "clEnqueueReadBuffer failed"); + + if (memcmp(bufptr, imgptr, buffer_size) != 0) { + log_error( "ERROR: Results did not validate!\n" ); + unsigned char * inchar = (unsigned char*)bufptr; + unsigned char * outchar = (unsigned char*)imgptr; + int failuresPrinted = 0; + int i; + for (i=0; i< (int)buffer_size; i+=(int)elem_size) { + int failed = 0; + int j; + for (j=0; j<(int)elem_size; j++) + if (inchar[i+j] != outchar[i+j]) + failed = 1; + char values[4096]; + values[0] = 0; + if (failed) { + sprintf(values + strlen(values), "%d(0x%x) -> actual [", i, i); + int j; + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", inchar[i+j]); + sprintf(values + strlen(values), "] != expected ["); + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", outchar[i+j]); + sprintf(values + strlen(values), "]"); + log_error("%s\n", values); + failuresPrinted++; + } + if (failuresPrinted > 5) { + log_error("Not printing further failures...\n"); + break; + } + } + err = -1; + } + + free(bufptr); + free(imgptr); + + if (err) + log_error("ARRAY to IMAGE copy test failed for image_channel_order=0x%lx and image_channel_data_type=0x%lx\n", + (unsigned long)format->image_channel_order, (unsigned long)format->image_channel_data_type); + + return err; +} + +int test_arrayimagecopy(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int err; + cl_image_format *formats; + cl_uint num_formats; + cl_uint i; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE2D, 0, NULL, &num_formats); + test_error(err, "clGetSupportedImageFormats failed"); + + formats = (cl_image_format *)malloc(num_formats * sizeof(cl_image_format)); + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE2D, num_formats, formats, NULL); + test_error(err, "clGetSupportedImageFormats failed"); + + for (i = 0; i < num_formats; i++) { + err |= test_arrayimagecopy_single_format(device, context, queue, &formats[i]); + } + + free(formats); + if (err) + log_error("ARRAY to IMAGE copy test failed\n"); + else + log_info("ARRAY to IMAGE copy test passed\n"); + + return err; +} diff --git a/test_conformance/basic/test_arrayimagecopy3d.c b/test_conformance/basic/test_arrayimagecopy3d.c new file mode 100644 index 00000000..d5333777 --- /dev/null +++ b/test_conformance/basic/test_arrayimagecopy3d.c @@ -0,0 +1,144 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" + +int test_arrayimagecopy3d_single_format(cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format) +{ + cl_uchar *bufptr, *imgptr; + clMemWrapper buffer, image; + int img_width = 128; + int img_height = 128; + int img_depth = 32; + size_t elem_size; + size_t buffer_size; + int i; + cl_int err; + MTdata d; + cl_event copyevent; + + log_info("Testing %s %s\n", GetChannelOrderName(format->image_channel_order), GetChannelTypeName(format->image_channel_data_type)); + + image = create_image_3d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), format, img_width, img_height, img_depth, 0, 0, NULL, &err); + test_error(err, "create_image_3d failed"); + + err = clGetImageInfo(image, CL_IMAGE_ELEMENT_SIZE, sizeof(size_t), &elem_size, NULL); + test_error(err, "clGetImageInfo failed"); + + buffer_size = sizeof(cl_uchar) * elem_size * img_width * img_height * img_depth; + + buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), buffer_size, NULL, &err); + test_error(err, "clCreateBuffer failed"); + + d = init_genrand( gRandomSeed ); + bufptr = (cl_uchar*)malloc(buffer_size); + for (i=0; i<(int)buffer_size; i++) { + bufptr[i] = (cl_uchar)genrand_int32(d); + } + free_mtdata(d); d = NULL; + + size_t origin[3]={0,0,0}, region[3]={img_width,img_height,img_depth}; + err = clEnqueueWriteBuffer( queue, buffer, CL_TRUE, 0, buffer_size, bufptr, 0, NULL, NULL); + test_error(err, "clEnqueueWriteBuffer failed"); + + err = clEnqueueCopyBufferToImage( queue, buffer, image, 0, origin, region, 0, NULL, ©event ); + test_error(err, "clEnqueueCopyImageToBuffer failed"); + + imgptr = (cl_uchar*)malloc(buffer_size); + + err = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, imgptr, 1, ©event, NULL ); + test_error(err, "clEnqueueReadBuffer failed"); + + if (memcmp(bufptr, imgptr, buffer_size) != 0) { + log_error( "ERROR: Results did not validate!\n" ); + unsigned char * inchar = (unsigned char*)bufptr; + unsigned char * outchar = (unsigned char*)imgptr; + int failuresPrinted = 0; + int i; + for (i=0; i< (int)buffer_size; i+=(int)elem_size) { + int failed = 0; + int j; + for (j=0; j<(int)elem_size; j++) + if (inchar[i+j] != outchar[i+j]) + failed = 1; + char values[4096]; + values[0] = 0; + if (failed) { + sprintf(values + strlen(values), "%d(0x%x) -> actual [", i, i); + int j; + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", inchar[i+j]); + sprintf(values + strlen(values), "] != expected ["); + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", outchar[i+j]); + sprintf(values + strlen(values), "]"); + log_error("%s\n", values); + failuresPrinted++; + } + if (failuresPrinted > 5) { + log_error("Not printing further failures...\n"); + break; + } + } + err = -1; + } + + free(bufptr); + free(imgptr); + + if (err) + log_error("ARRAY to IMAGE3D copy test failed for image_channel_order=0x%lx and image_channel_data_type=0x%lx\n", + (unsigned long)format->image_channel_order, (unsigned long)format->image_channel_data_type); + + return err; +} + +int test_arrayimagecopy3d(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int err; + cl_image_format *formats; + cl_uint num_formats; + cl_uint i; + + PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( device ) + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE3D, 0, NULL, &num_formats); + test_error(err, "clGetSupportedImageFormats failed"); + + formats = (cl_image_format *)malloc(num_formats * sizeof(cl_image_format)); + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE3D, num_formats, formats, NULL); + test_error(err, "clGetSupportedImageFormats failed"); + + for (i = 0; i < num_formats; i++) { + err |= test_arrayimagecopy3d_single_format(device, context, queue, &formats[i]); + } + + free(formats); + if (err) + log_error("ARRAY to IMAGE3D copy test failed\n"); + else + log_info("ARRAY to IMAGE3D copy test passed\n"); + + return err; +} diff --git a/test_conformance/basic/test_arrayreadwrite.c b/test_conformance/basic/test_arrayreadwrite.c new file mode 100644 index 00000000..96942ec1 --- /dev/null +++ b/test_conformance/basic/test_arrayreadwrite.c @@ -0,0 +1,95 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + + +int +test_arrayreadwrite(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_uint *inptr, *outptr; + cl_mem streams[1]; + int num_tries = 400; + num_elements = 1024 * 1024 * 4; + int i, j, err; + MTdata d; + + inptr = (cl_uint*)malloc(num_elements*sizeof(cl_uint)); + outptr = (cl_uint*)malloc(num_elements*sizeof(cl_uint)); + + // randomize data + d = init_genrand( gRandomSeed ); + for (i=0; i 0 && offset < num_elements) + break; + } while (1); + cb = (int)(genrand_int32(d) & 0x7FFFFFFF); + if (cb > (num_elements - offset)) + cb = num_elements - offset; + + err = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, offset*sizeof(cl_uint), sizeof(cl_uint)*cb,&inptr[offset], 0, NULL, NULL); + test_error(err, "clEnqueueWriteBuffer failed"); + + err = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, offset*sizeof(cl_uint), cb*sizeof(cl_uint), &outptr[offset], 0, NULL, NULL ); + test_error(err, "clEnqueueReadBuffer failed"); + + for (j=offset; j +#include +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" + + +static const char *astype_kernel_pattern = +"%s\n" +"__kernel void test_fn( __global %s%s *src, __global %s%s *dst )\n" +"{\n" +" int tid = get_global_id( 0 );\n" +" %s%s tmp = as_%s%s( src[ tid ] );\n" +" dst[ tid ] = tmp;\n" +"}\n"; + +static const char *astype_kernel_pattern_V3srcV3dst = +"%s\n" +"__kernel void test_fn( __global %s *src, __global %s *dst )\n" +"{\n" +" int tid = get_global_id( 0 );\n" +" %s%s tmp = as_%s%s( vload3(tid,src) );\n" +" vstore3(tmp,tid,dst);\n" +"}\n"; +// in the printf, remove the third and fifth argument, each of which +// should be a "3", when copying from the printf for astype_kernel_pattern + +static const char *astype_kernel_pattern_V3dst = +"%s\n" +"__kernel void test_fn( __global %s%s *src, __global %s *dst )\n" +"{\n" +" int tid = get_global_id( 0 );\n" +" %s3 tmp = as_%s3( src[ tid ] );\n" +" vstore3(tmp,tid,dst);\n" +"}\n"; +// in the printf, remove the fifth argument, which +// should be a "3", when copying from the printf for astype_kernel_pattern + + +static const char *astype_kernel_pattern_V3src = +"%s\n" +"__kernel void test_fn( __global %s *src, __global %s%s *dst )\n" +"{\n" +" int tid = get_global_id( 0 );\n" +" %s%s tmp = as_%s%s( vload3(tid,src) );\n" +" dst[ tid ] = tmp;\n" +"}\n"; +// in the printf, remove the third argument, which +// should be a "3", when copying from the printf for astype_kernel_pattern + + +int test_astype_set( cl_device_id device, cl_context context, cl_command_queue queue, ExplicitType inVecType, ExplicitType outVecType, + unsigned int vecSize, unsigned int outVecSize, + int numElements ) +{ + int error; + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 2 ]; + + char programSrc[ 10240 ]; + size_t threads[ 1 ], localThreads[ 1 ]; + size_t typeSize = get_explicit_type_size( inVecType ); + size_t outTypeSize = get_explicit_type_size(outVecType); + char sizeNames[][ 3 ] = { "", "", "2", "3", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + MTdata d; + + + + // Create program + if(outVecSize == 3 && vecSize == 3) { + // astype_kernel_pattern_V3srcV3dst + sprintf( programSrc, astype_kernel_pattern_V3srcV3dst, + (outVecType == kDouble || inVecType == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name( inVecType ), // sizeNames[ vecSize ], + get_explicit_type_name( outVecType ), // sizeNames[ outVecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ] ); + } else if(outVecSize == 3) { + // astype_kernel_pattern_V3dst + sprintf( programSrc, astype_kernel_pattern_V3dst, + (outVecType == kDouble || inVecType == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name( inVecType ), sizeNames[ vecSize ], + get_explicit_type_name( outVecType ), + get_explicit_type_name( outVecType ), + get_explicit_type_name( outVecType )); + + } else if(vecSize == 3) { + // astype_kernel_pattern_V3src + sprintf( programSrc, astype_kernel_pattern_V3src, + (outVecType == kDouble || inVecType == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name( inVecType ),// sizeNames[ vecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ]); + } else { + sprintf( programSrc, astype_kernel_pattern, + (outVecType == kDouble || inVecType == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name( inVecType ), sizeNames[ vecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ]); + } + + const char *ptr = programSrc; + error = create_single_kernel_helper( context, &program, &kernel, 1, &ptr, "test_fn" ); + test_error( error, "Unable to create testing kernel" ); + + + // Create some input values + size_t inBufferSize = sizeof(char)* numElements * get_explicit_type_size( inVecType ) * vecSize; + char *inBuffer = (char*)malloc( inBufferSize ); + size_t outBufferSize = sizeof(char)* numElements * get_explicit_type_size( outVecType ) *outVecSize; + char *outBuffer = (char*)malloc( outBufferSize ); + + d = init_genrand( gRandomSeed ); + generate_random_data( inVecType, numElements * vecSize, + d, inBuffer ); + free_mtdata(d); d = NULL; + + // Create I/O streams and set arguments + streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, inBufferSize, inBuffer, &error ); + test_error( error, "Unable to create I/O stream" ); + streams[ 1 ] = clCreateBuffer( context, CL_MEM_READ_WRITE, outBufferSize, NULL, &error ); + test_error( error, "Unable to create I/O stream" ); + + error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[ 1 ] ), &streams[ 1 ] ); + test_error( error, "Unable to set kernel argument" ); + + + // Run the kernel + threads[ 0 ] = numElements; + error = get_max_common_work_group_size( context, kernel, threads[ 0 ], &localThreads[ 0 ] ); + test_error( error, "Unable to get group size to run with" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + + // Get the results and compare + // The beauty is that astype is supposed to return the bit pattern as a different type, which means + // the output should have the exact same bit pattern as the input. No interpretation necessary! + error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, outBufferSize, outBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + char *expected = inBuffer; + char *actual = outBuffer; + size_t compSize = typeSize*vecSize; + if(outTypeSize*outVecSize < compSize) { + compSize = outTypeSize*outVecSize; + } + + if(outVecSize == 4 && vecSize == 3) + { + // as_type4(vec3) should compile but produce undefined results?? + free(inBuffer); + free(outBuffer); + return 0; + } + + if(outVecSize != 3 && vecSize != 3 && outVecSize != vecSize) + { + // as_typen(vecm) should compile and run but produce + // implementation-defined results for m != n + // and n*sizeof(type) = sizeof(vecm) + free(inBuffer); + free(outBuffer); + return 0; + } + + for( int i = 0; i < numElements; i++ ) + { + if( memcmp( expected, actual, compSize ) != 0 ) + { + char expectedString[ 1024 ], actualString[ 1024 ]; + log_error( "ERROR: Data sample %d of %d for as_%s%d( %s%d ) did not validate (expected {%s}, got {%s})\n", + (int)i, (int)numElements, get_explicit_type_name( outVecType ), vecSize, get_explicit_type_name( inVecType ), vecSize, + GetDataVectorString( expected, typeSize, vecSize, expectedString ), + GetDataVectorString( actual, typeSize, vecSize, actualString ) ); + log_error("Src is :\n%s\n----\n%d threads %d localthreads\n", + programSrc, (int)threads[0],(int) localThreads[0]); + free(inBuffer); + free(outBuffer); + return 1; + } + expected += typeSize * vecSize; + actual += outTypeSize * outVecSize; + } + + free(inBuffer); + free(outBuffer); + return 0; +} + +int test_astype(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + // Note: although casting to different vector element sizes that match the same size (i.e. short2 -> char4) is + // legal in OpenCL 1.0, the result is dependent on the device it runs on, which means there's no actual way + // for us to verify what is "valid". So the only thing we can test are types that match in size independent + // of the element count (char -> uchar, etc) + ExplicitType vecTypes[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 }; + unsigned int inTypeIdx, outTypeIdx, sizeIdx, outSizeIdx; + size_t inTypeSize, outTypeSize; + int error = 0; + + for( inTypeIdx = 0; vecTypes[ inTypeIdx ] != kNumExplicitTypes; inTypeIdx++ ) + { + inTypeSize = get_explicit_type_size(vecTypes[inTypeIdx]); + + if( vecTypes[ inTypeIdx ] == kDouble && !is_extension_available( device, "cl_khr_fp64" ) ) + continue; + + if (( vecTypes[ inTypeIdx ] == kLong || vecTypes[ inTypeIdx ] == kULong ) && !gHasLong ) + continue; + + for( outTypeIdx = 0; vecTypes[ outTypeIdx ] != kNumExplicitTypes; outTypeIdx++ ) + { + outTypeSize = get_explicit_type_size(vecTypes[outTypeIdx]); + if( vecTypes[ outTypeIdx ] == kDouble && !is_extension_available( device, "cl_khr_fp64" ) ) { + continue; + } + + if (( vecTypes[ outTypeIdx ] == kLong || vecTypes[ outTypeIdx ] == kULong ) && !gHasLong ) + continue; + + // change this check + if( inTypeIdx == outTypeIdx ) { + continue; + } + + log_info( " (%s->%s)\n", get_explicit_type_name( vecTypes[ inTypeIdx ] ), get_explicit_type_name( vecTypes[ outTypeIdx ] ) ); + fflush( stdout ); + + for( sizeIdx = 0; vecSizes[ sizeIdx ] != 0; sizeIdx++ ) + { + + for(outSizeIdx = 0; vecSizes[outSizeIdx] != 0; outSizeIdx++) + { + if(vecSizes[sizeIdx]*inTypeSize != + vecSizes[outSizeIdx]*outTypeSize ) + { + continue; + } + error += test_astype_set( device, context, queue, vecTypes[ inTypeIdx ], vecTypes[ outTypeIdx ], vecSizes[ sizeIdx ], vecSizes[outSizeIdx], n_elems ); + + + } + + } + if(get_explicit_type_size(vecTypes[inTypeIdx]) == + get_explicit_type_size(vecTypes[outTypeIdx])) { + // as_type3(vec4) allowed, as_type4(vec3) not allowed + error += test_astype_set( device, context, queue, vecTypes[ inTypeIdx ], vecTypes[ outTypeIdx ], 3, 4, n_elems ); + error += test_astype_set( device, context, queue, vecTypes[ inTypeIdx ], vecTypes[ outTypeIdx ], 4, 3, n_elems ); + } + + } + } + return error; +} + + diff --git a/test_conformance/basic/test_async_copy.cpp b/test_conformance/basic/test_async_copy.cpp new file mode 100644 index 00000000..4d2bd9ca --- /dev/null +++ b/test_conformance/basic/test_async_copy.cpp @@ -0,0 +1,279 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" + +static const char *async_global_to_local_kernel = +"%s\n" // optional pragma string +"__kernel void test_fn( const __global %s *src, __global %s *dst, __local %s *localBuffer, int copiesPerWorkgroup, int copiesPerWorkItem )\n" +"{\n" +" int i;\n" +// Zero the local storage first +" for(i=0; i max_local_workgroup_size[0]) + max_workgroup_size = max_local_workgroup_size[0]; + + size_t numberOfCopiesPerWorkitem = 13; + elementSize = get_explicit_type_size(vecType)* ((vecSize == 3) ? 4 : vecSize); + size_t localStorageSpacePerWorkitem = numberOfCopiesPerWorkitem*elementSize; + size_t maxLocalWorkgroupSize = (((int)max_local_mem_size/2)/localStorageSpacePerWorkitem); + + // Calculation can return 0 on embedded devices due to 1KB local mem limit + if(maxLocalWorkgroupSize == 0) + { + maxLocalWorkgroupSize = 1; + } + + size_t localWorkgroupSize = maxLocalWorkgroupSize; + if (maxLocalWorkgroupSize > max_workgroup_size) + localWorkgroupSize = max_workgroup_size; + + size_t localBufferSize = localWorkgroupSize*elementSize*numberOfCopiesPerWorkitem; + size_t numberOfLocalWorkgroups = 1111; + size_t globalBufferSize = numberOfLocalWorkgroups*localBufferSize; + size_t globalWorkgroupSize = numberOfLocalWorkgroups*localWorkgroupSize; + + inBuffer = (void*)malloc(globalBufferSize); + outBuffer = (void*)malloc(globalBufferSize); + memset(outBuffer, 0, globalBufferSize); + + cl_int copiesPerWorkItemInt, copiesPerWorkgroup; + copiesPerWorkItemInt = (int)numberOfCopiesPerWorkitem; + copiesPerWorkgroup = (int)(numberOfCopiesPerWorkitem*localWorkgroupSize); + + log_info("Global: %d, local %d, local buffer %db, global buffer %db, each work group will copy %d elements and each work item item will copy %d elements.\n", + (int) globalWorkgroupSize, (int)localWorkgroupSize, (int)localBufferSize, (int)globalBufferSize, copiesPerWorkgroup, copiesPerWorkItemInt); + + threads[0] = globalWorkgroupSize; + localThreads[0] = localWorkgroupSize; + + d = init_genrand( gRandomSeed ); + generate_random_data( vecType, globalBufferSize/get_explicit_type_size(vecType), d, inBuffer ); + free_mtdata(d); d = NULL; + + streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, globalBufferSize, inBuffer, &error ); + test_error( error, "Unable to create input buffer" ); + streams[ 1 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, globalBufferSize, outBuffer, &error ); + test_error( error, "Unable to create output buffer" ); + + error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[ 1 ] ), &streams[ 1 ] ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 2, localBufferSize, NULL ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 3, sizeof(copiesPerWorkgroup), &copiesPerWorkgroup ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 4, sizeof(copiesPerWorkItemInt), &copiesPerWorkItemInt ); + test_error( error, "Unable to set kernel argument" ); + + // Enqueue + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to queue kernel" ); + + // Read + error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, globalBufferSize, outBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + // Verify + int failuresPrinted = 0; + if( memcmp( inBuffer, outBuffer, globalBufferSize ) != 0 ) + { + size_t typeSize = get_explicit_type_size(vecType)* vecSize; + unsigned char * inchar = (unsigned char*)inBuffer; + unsigned char * outchar = (unsigned char*)outBuffer; + for (int i=0; i< (int)globalBufferSize; i+=(int)elementSize) { + if (memcmp( ((char *)inchar)+i, ((char *)outchar)+i, typeSize) != 0 ) + { + char values[4096]; + values[0] = 0; + if ( failuresPrinted == 0 ) { + // Print first failure message + log_error( "ERROR: Results of copy did not validate!\n" ); + } + sprintf(values + strlen( values), "%d -> [", i); + for (int j=0; j<(int)elementSize; j++) + sprintf(values + strlen( values), "%2x ", inchar[i+j]); + sprintf(values + strlen(values), "] != ["); + for (int j=0; j<(int)elementSize; j++) + sprintf(values + strlen( values), "%2x ", outchar[i+j]); + sprintf(values + strlen(values), "]"); + log_error("%s\n", values); + failuresPrinted++; + } + + if (failuresPrinted > 5) { + log_error("Not printing further failures...\n"); + break; + } + } + } + + free(inBuffer); + free(outBuffer); + + return failuresPrinted ? -1 : 0; +} + +int test_copy_all_types(cl_device_id deviceID, cl_context context, cl_command_queue queue, const char *kernelCode) { + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 }; + unsigned int size, typeIndex; + + int errors = 0; + + for( typeIndex = 0; vecType[ typeIndex ] != kNumExplicitTypes; typeIndex++ ) + { + if( vecType[ typeIndex ] == kDouble && !is_extension_available( deviceID, "cl_khr_fp64" ) ) + continue; + + if (( vecType[ typeIndex ] == kLong || vecType[ typeIndex ] == kULong ) && !gHasLong ) + continue; + + for( size = 0; vecSizes[ size ] != 0; size++ ) + { + if (test_copy( deviceID, context, queue, kernelCode, vecType[typeIndex],vecSizes[size] )) { + errors++; + } + } + } + if (errors) + return -1; + return 0; +} + + + + +int test_async_copy_global_to_local(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_copy_all_types( deviceID, context, queue, async_global_to_local_kernel ); +} + +int test_async_copy_local_to_global(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_copy_all_types( deviceID, context, queue, async_local_to_global_kernel ); +} + +int test_prefetch(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_copy_all_types( deviceID, context, queue, prefetch_kernel ); +} + diff --git a/test_conformance/basic/test_async_strided_copy.cpp b/test_conformance/basic/test_async_strided_copy.cpp new file mode 100644 index 00000000..ec65101d --- /dev/null +++ b/test_conformance/basic/test_async_strided_copy.cpp @@ -0,0 +1,274 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" + +static const char *async_strided_global_to_local_kernel = +"%s\n" // optional pragma string +"%s__kernel void test_fn( const __global %s *src, __global %s *dst, __local %s *localBuffer, int copiesPerWorkgroup, int copiesPerWorkItem, int stride )\n" +"{\n" +" int i;\n" +// Zero the local storage first +" for(i=0; i max_local_workgroup_size[0]) + max_workgroup_size = max_local_workgroup_size[0]; + + size_t elementSize = get_explicit_type_size(vecType)* ((vecSize == 3) ? 4 : vecSize); + + cl_ulong max_global_mem_size; + error = clGetDeviceInfo(deviceID, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(max_global_mem_size), &max_global_mem_size, NULL); + test_error (error, "clGetDeviceInfo failed for CL_DEVICE_GLOBAL_MEM_SIZE"); + + if (max_global_mem_size > (cl_ulong)SIZE_MAX) { + max_global_mem_size = (cl_ulong)SIZE_MAX; + } + + cl_bool unified_mem; + error = clGetDeviceInfo(deviceID, CL_DEVICE_HOST_UNIFIED_MEMORY, sizeof(unified_mem), &unified_mem, NULL); + test_error (error, "clGetDeviceInfo failed for CL_DEVICE_HOST_UNIFIED_MEMORY"); + + int number_of_global_mem_buffers = (unified_mem) ? 4 : 2; + + size_t numberOfCopiesPerWorkitem = 3; + size_t localStorageSpacePerWorkitem = numberOfCopiesPerWorkitem*elementSize; + size_t maxLocalWorkgroupSize = (((int)max_local_mem_size/2)/localStorageSpacePerWorkitem); + + size_t localWorkgroupSize = maxLocalWorkgroupSize; + if (maxLocalWorkgroupSize > max_workgroup_size) + localWorkgroupSize = max_workgroup_size; + + size_t localBufferSize = localWorkgroupSize*elementSize*numberOfCopiesPerWorkitem; + size_t numberOfLocalWorkgroups = 579;//1111; + + // Reduce the numberOfLocalWorkgroups so that no more than 1/2 of CL_DEVICE_GLOBAL_MEM_SIZE is consumed + // by the allocated buffer. This is done to avoid resource errors resulting from address space fragmentation. + size_t numberOfLocalWorkgroupsLimit = max_global_mem_size / (2 * number_of_global_mem_buffers * localBufferSize * stride); + if (numberOfLocalWorkgroups > numberOfLocalWorkgroupsLimit) numberOfLocalWorkgroups = numberOfLocalWorkgroupsLimit; + + size_t globalBufferSize = numberOfLocalWorkgroups*localBufferSize*stride; + size_t globalWorkgroupSize = numberOfLocalWorkgroups*localWorkgroupSize; + + inBuffer = (void*)malloc(globalBufferSize); + outBuffer = (void*)malloc(globalBufferSize); + memset(outBuffer, 0, globalBufferSize); + + cl_int copiesPerWorkItemInt, copiesPerWorkgroup; + copiesPerWorkItemInt = (int)numberOfCopiesPerWorkitem; + copiesPerWorkgroup = (int)(numberOfCopiesPerWorkitem*localWorkgroupSize); + + log_info("Global: %d, local %d, local buffer %db, global buffer %db, copy stride %d, each work group will copy %d elements and each work item item will copy %d elements.\n", + (int) globalWorkgroupSize, (int)localWorkgroupSize, (int)localBufferSize, (int)globalBufferSize, (int)stride, copiesPerWorkgroup, copiesPerWorkItemInt); + + threads[0] = globalWorkgroupSize; + localThreads[0] = localWorkgroupSize; + + d = init_genrand( gRandomSeed ); + generate_random_data( vecType, globalBufferSize/get_explicit_type_size(vecType), d, inBuffer ); + free_mtdata(d); d = NULL; + + streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, globalBufferSize, inBuffer, &error ); + test_error( error, "Unable to create input buffer" ); + streams[ 1 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, globalBufferSize, outBuffer, &error ); + test_error( error, "Unable to create output buffer" ); + + error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[ 1 ] ), &streams[ 1 ] ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 2, localBufferSize, NULL ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 3, sizeof(copiesPerWorkgroup), &copiesPerWorkgroup ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 4, sizeof(copiesPerWorkItemInt), &copiesPerWorkItemInt ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 5, sizeof(stride), &stride ); + test_error( error, "Unable to set kernel argument" ); + + // Enqueue + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to queue kernel" ); + + // Read + error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, globalBufferSize, outBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + // Verify + size_t typeSize = get_explicit_type_size(vecType)* vecSize; + for (int i=0; i<(int)globalBufferSize; i+=(int)elementSize*(int)stride) + { + if (memcmp( ((char *)inBuffer)+i, ((char *)outBuffer)+i, typeSize) != 0 ) + { + unsigned char * inchar = (unsigned char*)inBuffer + i; + unsigned char * outchar = (unsigned char*)outBuffer + i; + char values[4096]; + values[0] = 0; + + log_error( "ERROR: Results of copy did not validate!\n" ); + sprintf(values + strlen( values), "%d -> [", i); + for (int j=0; j<(int)elementSize; j++) + sprintf(values + strlen( values), "%2x ", inchar[i*elementSize+j]); + sprintf(values + strlen(values), "] != ["); + for (int j=0; j<(int)elementSize; j++) + sprintf(values + strlen( values), "%2x ", outchar[i*elementSize+j]); + sprintf(values + strlen(values), "]"); + log_error("%s\n", values); + + return -1; + } + } + + free(inBuffer); + free(outBuffer); + + return 0; +} + +int test_strided_copy_all_types(cl_device_id deviceID, cl_context context, cl_command_queue queue, const char *kernelCode) +{ + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 }; + unsigned int strideSizes[] = { 1, 3, 4, 5, 0 }; + unsigned int size, typeIndex, stride; + + int errors = 0; + + for( typeIndex = 0; vecType[ typeIndex ] != kNumExplicitTypes; typeIndex++ ) + { + if( vecType[ typeIndex ] == kDouble && !is_extension_available( deviceID, "cl_khr_fp64" ) ) + continue; + + if (( vecType[ typeIndex ] == kLong || vecType[ typeIndex ] == kULong ) && !gHasLong ) + continue; + + for( size = 0; vecSizes[ size ] != 0; size++ ) + { + for( stride = 0; strideSizes[ stride ] != 0; stride++) + { + if (test_strided_copy( deviceID, context, queue, kernelCode, vecType[typeIndex], vecSizes[size], strideSizes[stride] )) + { + errors++; + } + } + } + } + if (errors) + return -1; + return 0; +} + + + + +int test_async_strided_copy_global_to_local(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_strided_copy_all_types( deviceID, context, queue, async_strided_global_to_local_kernel ); +} + +int test_async_strided_copy_local_to_global(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_strided_copy_all_types( deviceID, context, queue, async_strided_local_to_global_kernel ); +} + diff --git a/test_conformance/basic/test_barrier.c b/test_conformance/basic/test_barrier.c new file mode 100644 index 00000000..b24d771b --- /dev/null +++ b/test_conformance/basic/test_barrier.c @@ -0,0 +1,159 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +const char *barrier_kernel_code = +"__kernel void compute_sum(__global int *a, int n, __global int *tmp_sum, __global int *sum)\n" +"{\n" +" int tid = get_local_id(0);\n" +" int lsize = get_local_size(0);\n" +" int i;\n" +"\n" +" tmp_sum[tid] = 0;\n" +" for (i=tid; i1; i = hadd(i,1))\n" +" {\n" +" barrier(CLK_GLOBAL_MEM_FENCE);\n" +" if (tid + i < lsize)\n" +" tmp_sum[tid] += tmp_sum[tid + i];\n" +" lsize = i; \n" +" }\n" +"\n" +" //no barrier is required here because last person to write to tmp_sum[0] was tid 0 \n" +" if (tid == 0)\n" +" *sum = tmp_sum[0];\n" +"}\n"; + + +static int +verify_sum(int *inptr, int *outptr, int n) +{ + int r = 0; + int i; + + for (i=0; i max_local_workgroup_size[0]) + max_threadgroup_size = max_local_workgroup_size[0]; + + // work group size must divide evenly into the global size + while( num_elements % max_threadgroup_size ) + max_threadgroup_size--; + + input_ptr = (int*)malloc(sizeof(int) * num_elements); + output_ptr = (int*)malloc(sizeof(int)); + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * num_elements, NULL, &err); + test_error(err, "clCreateBuffer failed."); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int), NULL, &err); + test_error(err, "clCreateBuffer failed."); + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * max_threadgroup_size, NULL, &err); + test_error(err, "clCreateBuffer failed."); + + d = init_genrand( gRandomSeed ); + for (i=0; i +#include +#include +#include +#include + +#include "procs.h" + +const char *kernel_code = +"__kernel void test_kernel(\n" +"char%s c, uchar%s uc, short%s s, ushort%s us, int%s i, uint%s ui, float%s f,\n" +"__global float%s *result)\n" +"{\n" +" result[0] = %s(c);\n" +" result[1] = %s(uc);\n" +" result[2] = %s(s);\n" +" result[3] = %s(us);\n" +" result[4] = %s(i);\n" +" result[5] = %s(ui);\n" +" result[6] = f;\n" +"}\n"; + +const char *kernel_code_long = +"__kernel void test_kernel_long(\n" +"long%s l, ulong%s ul,\n" +"__global float%s *result)\n" +"{\n" +" result[0] = %s(l);\n" +" result[1] = %s(ul);\n" +"}\n"; + +int +test_basic_parameter_types_long(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + clMemWrapper results; + int error; + size_t global[3] = {1, 1, 1}; + float results_back[2*16]; + int count, index; + const char* types[] = { "long", "ulong" }; + char kernel_string[8192]; + int sizes[] = {1, 2, 4, 8, 16}; + const char* size_strings[] = {"", "2", "4", "8", "16"}; + float expected; + int total_errors = 0; + int size_to_test; + char *ptr; + char convert_string[1024]; + size_t max_parameter_size; + + // We don't really care about the contents since we're just testing that the types work. + cl_long l[16]={-21,-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,14,-15}; + cl_ulong ul[16]={22,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + + // Calculate how large our paramter size is to the kernel + size_t parameter_size = sizeof(cl_long) + sizeof(cl_ulong); + + // Init our strings. + kernel_string[0] = '\0'; + convert_string[0] = '\0'; + + // Get the maximum parameter size allowed + error = clGetDeviceInfo( device, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof( max_parameter_size ), &max_parameter_size, NULL ); + test_error( error, "Unable to get max parameter size from device" ); + + // Create the results buffer + results = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_float)*2*16, NULL, &error); + test_error(error, "clCreateBuffer failed"); + + // Go over all the vector sizes + for (size_to_test = 0; size_to_test < 5; size_to_test++) { + clProgramWrapper program; + clKernelWrapper kernel; + + size_t total_parameter_size = parameter_size*sizes[size_to_test] + sizeof(cl_mem); + if (total_parameter_size > max_parameter_size) { + log_info("Can not test with vector size %d because it would exceed the maximum allowed parameter size to the kernel. (%d > %d)\n", + (int)sizes[size_to_test], (int)total_parameter_size, (int)max_parameter_size); + continue; + } + + log_info("Testing vector size %d\n", sizes[size_to_test]); + + // If size is > 1, then we need a explicit convert call. + if (sizes[size_to_test] > 1) { + sprintf(convert_string, "convert_float%s", size_strings[size_to_test]); + } else { + sprintf(convert_string, " "); + } + + // Build the kernel + sprintf(kernel_string, kernel_code_long, + size_strings[size_to_test], size_strings[size_to_test], size_strings[size_to_test], + convert_string, convert_string + ); + + ptr = kernel_string; + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&ptr, "test_kernel_long"); + test_error(error, "create single kernel failed"); + + // Set the arguments + for (count = 0; count < 2; count++) { + switch (count) { + case 0: error = clSetKernelArg(kernel, count, sizeof(cl_long)*sizes[size_to_test], &l); break; + case 1: error = clSetKernelArg(kernel, count, sizeof(cl_ulong)*sizes[size_to_test], &ul); break; + default: log_error("Test error"); break; + } + if (error) + log_error("Setting kernel arg %d %s%s: ", count, types[count], size_strings[size_to_test]); + test_error(error, "clSetKernelArgs failed"); + } + error = clSetKernelArg(kernel, 2, sizeof(cl_mem), &results); + test_error(error, "clSetKernelArgs failed"); + + // Execute + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global, NULL, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + // Read back the results + error = clEnqueueReadBuffer(queue, results, CL_TRUE, 0, sizeof(cl_float)*2*16, results_back, 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + // Verify the results + for (count = 0; count < 2; count++) { + for (index=0; index < sizes[size_to_test]; index++) { + switch (count) { + case 0: expected = (float)l[index]; break; + case 1: expected = (float)ul[index]; break; + default: log_error("Test error"); break; + } + + if (results_back[count*sizes[size_to_test]+index] != expected) { + total_errors++; + log_error("Conversion from %s%s failed: index %d got %g, expected %g.\n", types[count], size_strings[size_to_test], + index, results_back[count*sizes[size_to_test]+index], expected); + } + } + } + } + + return total_errors; +} + +int +test_basic_parameter_types(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + clMemWrapper results; + int error; + size_t global[3] = {1, 1, 1}; + float results_back[7*16]; + int count, index; + const char* types[] = {"char", "uchar", "short", "ushort", "int", "uint", "float"}; + char kernel_string[8192]; + int sizes[] = {1, 2, 4, 8, 16}; + const char* size_strings[] = {"", "2", "4", "8", "16"}; + float expected; + int total_errors = 0; + int size_to_test; + char *ptr; + char convert_string[1024]; + size_t max_parameter_size; + + // We don't really care about the contents since we're just testing that the types work. + cl_char c[16]={0,-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,14,-15}; + cl_uchar uc[16]={16,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + cl_short s[16]={-17,-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,14,-15}; + cl_ushort us[16]={18,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + cl_int i[16]={-19,-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,14,-15}; + cl_uint ui[16]={20,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + cl_float f[16]={-23,-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,14,-15}; + + // Calculate how large our paramter size is to the kernel + size_t parameter_size = sizeof(cl_char) + sizeof(cl_uchar) + + sizeof(cl_short) +sizeof(cl_ushort) + + sizeof(cl_int) +sizeof(cl_uint) + + sizeof(cl_float); + + // Init our strings. + kernel_string[0] = '\0'; + convert_string[0] = '\0'; + + // Get the maximum parameter size allowed + error = clGetDeviceInfo( device, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof( max_parameter_size ), &max_parameter_size, NULL ); + test_error( error, "Unable to get max parameter size from device" ); + + // Create the results buffer + results = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_float)*7*16, NULL, &error); + test_error(error, "clCreateBuffer failed"); + + // Go over all the vector sizes + for (size_to_test = 0; size_to_test < 5; size_to_test++) { + clProgramWrapper program; + clKernelWrapper kernel; + + size_t total_parameter_size = parameter_size*sizes[size_to_test] + sizeof(cl_mem); + if (total_parameter_size > max_parameter_size) { + log_info("Can not test with vector size %d because it would exceed the maximum allowed parameter size to the kernel. (%d > %d)\n", + (int)sizes[size_to_test], (int)total_parameter_size, (int)max_parameter_size); + continue; + } + + log_info("Testing vector size %d\n", sizes[size_to_test]); + + // If size is > 1, then we need a explicit convert call. + if (sizes[size_to_test] > 1) { + sprintf(convert_string, "convert_float%s", size_strings[size_to_test]); + } else { + sprintf(convert_string, " "); + } + + // Build the kernel + sprintf(kernel_string, kernel_code, + size_strings[size_to_test], size_strings[size_to_test], size_strings[size_to_test], + size_strings[size_to_test], size_strings[size_to_test], size_strings[size_to_test], + size_strings[size_to_test], size_strings[size_to_test], + convert_string, convert_string, convert_string, + convert_string, convert_string, convert_string + ); + + ptr = kernel_string; + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&ptr, "test_kernel"); + test_error(error, "create single kernel failed"); + + // Set the arguments + for (count = 0; count < 7; count++) { + switch (count) { + case 0: error = clSetKernelArg(kernel, count, sizeof(cl_char)*sizes[size_to_test], &c); break; + case 1: error = clSetKernelArg(kernel, count, sizeof(cl_uchar)*sizes[size_to_test], &uc); break; + case 2: error = clSetKernelArg(kernel, count, sizeof(cl_short)*sizes[size_to_test], &s); break; + case 3: error = clSetKernelArg(kernel, count, sizeof(cl_ushort)*sizes[size_to_test], &us); break; + case 4: error = clSetKernelArg(kernel, count, sizeof(cl_int)*sizes[size_to_test], &i); break; + case 5: error = clSetKernelArg(kernel, count, sizeof(cl_uint)*sizes[size_to_test], &ui); break; + case 6: error = clSetKernelArg(kernel, count, sizeof(cl_float)*sizes[size_to_test], &f); break; + default: log_error("Test error"); break; + } + if (error) + log_error("Setting kernel arg %d %s%s: ", count, types[count], size_strings[size_to_test]); + test_error(error, "clSetKernelArgs failed"); + } + error = clSetKernelArg(kernel, 7, sizeof(cl_mem), &results); + test_error(error, "clSetKernelArgs failed"); + + // Execute + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global, NULL, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + // Read back the results + error = clEnqueueReadBuffer(queue, results, CL_TRUE, 0, sizeof(cl_float)*7*16, results_back, 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + // Verify the results + for (count = 0; count < 7; count++) { + for (index=0; index < sizes[size_to_test]; index++) { + switch (count) { + case 0: expected = (float)c[index]; break; + case 1: expected = (float)uc[index]; break; + case 2: expected = (float)s[index]; break; + case 3: expected = (float)us[index]; break; + case 4: expected = (float)i[index]; break; + case 5: expected = (float)ui[index]; break; + case 6: expected = (float)f[index]; break; + default: log_error("Test error"); break; + } + + if (results_back[count*sizes[size_to_test]+index] != expected) { + total_errors++; + log_error("Conversion from %s%s failed: index %d got %g, expected %g.\n", types[count], size_strings[size_to_test], + index, results_back[count*sizes[size_to_test]+index], expected); + } + } + } + } + + if (gHasLong) { + log_info("Testing long types...\n"); + total_errors += test_basic_parameter_types_long( device, context, queue, num_elements ); + } + else { + log_info("Longs unsupported, skipping."); + } + + return total_errors; +} + + + diff --git a/test_conformance/basic/test_bufferreadwriterect.c b/test_conformance/basic/test_bufferreadwriterect.c new file mode 100644 index 00000000..1631056b --- /dev/null +++ b/test_conformance/basic/test_bufferreadwriterect.c @@ -0,0 +1,564 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" + +#define CL_EXIT_ERROR(cmd,format,...) \ +{ \ +if ((cmd) != CL_SUCCESS) { \ +log_error("CL ERROR: %s %u: ", __FILE__,__LINE__); \ +log_error(format,## __VA_ARGS__ ); \ +log_error("\n"); \ +/*abort();*/ \ +} \ +} + +typedef unsigned char BufferType; + +// Globals for test +cl_command_queue queue; + +// Width and height of each pair of images. +enum { TotalImages = 8 }; +size_t width [TotalImages]; +size_t height [TotalImages]; +size_t depth [TotalImages]; + +// cl buffer and host buffer. +cl_mem buffer [TotalImages]; +BufferType* verify[TotalImages]; +BufferType* backing[TotalImages]; + +// Temporary buffer used for read and write operations. +BufferType* tmp_buffer; +size_t tmp_buffer_size; + +size_t num_tries = 50; // Number of randomly selected operations to perform. +size_t alloc_scale = 2; // Scale term applied buffer allocation size. +MTdata mt; + +// Initialize a buffer in host memory containing random values of the specified size. +static void initialize_image(BufferType* ptr, size_t w, size_t h, size_t d, MTdata mt) +{ + enum { ElementSize = sizeof(BufferType)/sizeof(unsigned char) }; + + unsigned char* buf = (unsigned char*)ptr; + size_t size = w*h*d*ElementSize; + + for (size_t i = 0; i != size; i++) { + buf[i] = (unsigned char)(genrand_int32(mt) % 0xff); + } +} + +// This function prints the contents of a buffer to standard error. +void print_buffer(BufferType* buf, size_t w, size_t h, size_t d) { + log_error("Size = %lux%lux%lu (%lu total)\n",w,h,d,w*h*d); + for (unsigned k=0; k!=d;++k) { + log_error("Slice: %u\n",k); + for (unsigned j=0; j!=h;++j) { + for (unsigned i=0;i!=w;++i) { + log_error("%02x",buf[k*(w*h)+j*w+i]); + } + log_error("\n"); + } + log_error("\n"); + } +} + +// Returns true if the two specified regions overlap. +bool check_overlap_rect(size_t src_offset[3], + size_t dst_offset[3], + size_t region[3], + size_t row_pitch, + size_t slice_pitch) +{ + const size_t src_min[] = { src_offset[0], src_offset[1], src_offset[2] }; + const size_t src_max[] = { src_offset[0] + region[0], src_offset[1] + region[1], src_offset[2] + region[2] }; + + const size_t dst_min[] = { dst_offset[0], dst_offset[1], dst_offset[2] }; + const size_t dst_max[] = { dst_offset[0] + region[0], + dst_offset[1] + region[1], + dst_offset[2] + region[2]}; +// Check for overlap + bool overlap = true; + unsigned i; + for (i = 0; i != 3; ++i) + { + overlap = overlap && (src_min[i] < dst_max[i]) && (src_max[i] > dst_min[i]); + } + + size_t dst_start = dst_offset[2] * slice_pitch + dst_offset[1] * row_pitch + dst_offset[0]; + size_t dst_end = dst_start + (region[2] * slice_pitch + + region[1] * row_pitch + region[0]); + size_t src_start = src_offset[2] * slice_pitch + src_offset[1] * row_pitch + src_offset[0]; + size_t src_end = src_start + (region[2] * slice_pitch + + region[1] * row_pitch + region[0]); + if (!overlap) { + size_t delta_src_x = (src_offset[0] + region[0] > row_pitch) ? + src_offset[0] + region[0] - row_pitch : 0; size_t delta_dst_x = (dst_offset[0] + region[0] > row_pitch) ? + dst_offset[0] + region[0] - row_pitch : 0; + if ((delta_src_x > 0 && delta_src_x > dst_offset[0]) || + (delta_dst_x > 0 && delta_dst_x > src_offset[0])) { + if ((src_start <= dst_start && dst_start < src_end) || (dst_start <= src_start && src_start < dst_end)) overlap = true; + } + if (region[2] > 1) { + size_t src_height = slice_pitch / row_pitch; size_t dst_height = slice_pitch / row_pitch; + size_t delta_src_y = (src_offset[1] + region[1] > src_height) ? src_offset[1] + region[1] - src_height : 0; + size_t delta_dst_y = (dst_offset[1] + region[1] > dst_height) ? dst_offset[1] + region[1] - dst_height : 0; + if ((delta_src_y > 0 && delta_src_y > dst_offset[1]) || + (delta_dst_y > 0 && delta_dst_y > src_offset[1])) { + if ((src_start <= dst_start && dst_start < src_end) || (dst_start <= src_start && src_start < dst_end)) + overlap = true; + } + } + } + return overlap; +} + + + +// This function invokes the CopyBufferRect CL command and then mirrors the operation on the host side verify buffers. +int copy_region(size_t src, size_t soffset[3], size_t sregion[3], size_t dst, size_t doffset[3], size_t dregion[3]) { + + // Copy between cl buffers. + size_t src_slice_pitch = (width[src]*height[src] != 1) ? width[src]*height[src] : 0; + size_t dst_slice_pitch = (width[dst]*height[dst] != 1) ? width[dst]*height[dst] : 0; + size_t src_row_pitch = width[src]; + + cl_int err; + if (check_overlap_rect(soffset,doffset,sregion,src_row_pitch, src_slice_pitch)) { + log_info( "Copy overlap reported, skipping copy buffer rect\n" ); + return CL_SUCCESS; + } else { + if ((err = clEnqueueCopyBufferRect(queue, + buffer[src],buffer[dst], + soffset, doffset, + sregion,/*dregion,*/ + width[src], src_slice_pitch, + width[dst], dst_slice_pitch, + 0, NULL, NULL)) != CL_SUCCESS) + { + CL_EXIT_ERROR(err, "clEnqueueCopyBufferRect failed between %u and %u",(unsigned)src,(unsigned)dst); + } + } + + // Copy between host buffers. + size_t total = sregion[0] * sregion[1] * sregion[2]; + + size_t spitch = width[src]; + size_t sslice = width[src]*height[src]; + + size_t dpitch = width[dst]; + size_t dslice = width[dst]*height[dst]; + + for (size_t i = 0; i != total; ++i) { + + // Compute the coordinates of the element within the source and destination regions. + size_t rslice = sregion[0]*sregion[1]; + size_t sz = i / rslice; + size_t sy = (i % rslice) / sregion[0]; + size_t sx = (i % rslice) % sregion[0]; + + size_t dz = sz; + size_t dy = sy; + size_t dx = sx; + + // Compute the offset in bytes of the source and destination. + size_t s_idx = (soffset[2]+sz)*sslice + (soffset[1]+sy)*spitch + soffset[0]+sx; + size_t d_idx = (doffset[2]+dz)*dslice + (doffset[1]+dy)*dpitch + doffset[0]+dx; + + verify[dst][d_idx] = verify[src][s_idx]; + } + + return 0; +} + +// This function compares the destination region in the buffer pointed +// to by device, to the source region of the specified verify buffer. +int verify_region(BufferType* device, size_t src, size_t soffset[3], size_t sregion[3], size_t dst, size_t doffset[3]) { + + // Copy between host buffers. + size_t spitch = width[src]; + size_t sslice = width[src]*height[src]; + + size_t dpitch = width[dst]; + size_t dslice = width[dst]*height[dst]; + + size_t total = sregion[0] * sregion[1] * sregion[2]; + for (size_t i = 0; i != total; ++i) { + + // Compute the coordinates of the element within the source and destination regions. + size_t rslice = sregion[0]*sregion[1]; + size_t sz = i / rslice; + size_t sy = (i % rslice) / sregion[0]; + size_t sx = (i % rslice) % sregion[0]; + + // Compute the offset in bytes of the source and destination. + size_t s_idx = (soffset[2]+sz)*sslice + (soffset[1]+sy)*spitch + soffset[0]+sx; + size_t d_idx = (doffset[2]+sz)*dslice + (doffset[1]+sy)*dpitch + doffset[0]+sx; + + if (device[d_idx] != verify[src][s_idx]) { + log_error("Verify failed on comparsion %lu: coordinate (%lu, %lu, %lu) of region\n",i,sx,sy,sz); + log_error("0x%02x != 0x%02x\n", device[d_idx], verify[src][s_idx]); +#if 0 + // Uncomment this section to print buffers. + log_error("Device (copy): [%lu]\n",dst); + print_buffer(device,width[dst],height[dst],depth[dst]); + log_error("\n"); + log_error("Verify: [%lu]\n",src); + print_buffer(verify[src],width[src],height[src],depth[src]); + log_error("\n"); + abort(); +#endif + return -1; + } + } + + return 0; +} + + +// This function invokes ReadBufferRect to read a region from the +// specified source buffer into a temporary destination buffer. The +// contents of the temporary buffer are then compared to the source +// region of the corresponding verify buffer. +int read_verify_region(size_t src, size_t soffset[3], size_t sregion[3], size_t dst, size_t doffset[3], size_t dregion[3]) { + + // Clear the temporary destination host buffer. + memset(tmp_buffer, 0xff, tmp_buffer_size); + + size_t src_slice_pitch = (width[src]*height[src] != 1) ? width[src]*height[src] : 0; + size_t dst_slice_pitch = (width[dst]*height[dst] != 1) ? width[dst]*height[dst] : 0; + + // Copy the source region of the cl buffer, to the destination region of the temporary buffer. + CL_EXIT_ERROR(clEnqueueReadBufferRect(queue, + buffer[src], + CL_TRUE, + soffset,doffset, + sregion, + width[src], src_slice_pitch, + width[dst], dst_slice_pitch, + tmp_buffer, + 0, NULL, NULL), "clEnqueueCopyBufferRect failed between %u and %u",(unsigned)src,(unsigned)dst); + + return verify_region(tmp_buffer,src,soffset,sregion,dst,doffset); +} + +// This function performs the same verification check as +// read_verify_region, except a MapBuffer command is used to access the +// device buffer data instead of a ReadBufferRect, and the whole +// buffer is checked. +int map_verify_region(size_t src) { + + size_t size_bytes = width[src]*height[src]*depth[src]*sizeof(BufferType); + + // Copy the source region of the cl buffer, to the destination region of the temporary buffer. + cl_int err; + BufferType* mapped = (BufferType*)clEnqueueMapBuffer(queue,buffer[src],CL_TRUE,CL_MAP_READ,0,size_bytes,0,NULL,NULL,&err); + CL_EXIT_ERROR(err, "clEnqueueMapBuffer failed for buffer %u",(unsigned)src); + + size_t soffset[] = { 0, 0, 0 }; + size_t sregion[] = { width[src], height[src], depth[src] }; + + int ret = verify_region(mapped,src,soffset,sregion,src,soffset); + + CL_EXIT_ERROR(clEnqueueUnmapMemObject(queue,buffer[src],mapped,0,NULL,NULL), + "clEnqueueUnmapMemObject failed for buffer %u",(unsigned)src); + + return ret; +} + +// This function generates a new temporary buffer and then writes a +// region of it to a region in the specified destination buffer. +int write_region(size_t src, size_t soffset[3], size_t sregion[3], size_t dst, size_t doffset[3], size_t dregion[3]) { + + initialize_image(tmp_buffer, tmp_buffer_size, 1, 1, mt); + // memset(tmp_buffer, 0xf0, tmp_buffer_size); + + size_t src_slice_pitch = (width[src]*height[src] != 1) ? width[src]*height[src] : 0; + size_t dst_slice_pitch = (width[dst]*height[dst] != 1) ? width[dst]*height[dst] : 0; + + // Copy the source region of the cl buffer, to the destination region of the temporary buffer. + CL_EXIT_ERROR(clEnqueueWriteBufferRect(queue, + buffer[dst], + CL_TRUE, + doffset,soffset, + /*sregion,*/dregion, + width[dst], dst_slice_pitch, + width[src], src_slice_pitch, + tmp_buffer, + 0, NULL, NULL), "clEnqueueWriteBufferRect failed between %u and %u",(unsigned)src,(unsigned)dst); + + // Copy from the temporary buffer to the host buffer. + size_t spitch = width[src]; + size_t sslice = width[src]*height[src]; + size_t dpitch = width[dst]; + size_t dslice = width[dst]*height[dst]; + + size_t total = sregion[0] * sregion[1] * sregion[2]; + for (size_t i = 0; i != total; ++i) { + + // Compute the coordinates of the element within the source and destination regions. + size_t rslice = sregion[0]*sregion[1]; + size_t sz = i / rslice; + size_t sy = (i % rslice) / sregion[0]; + size_t sx = (i % rslice) % sregion[0]; + + size_t dz = sz; + size_t dy = sy; + size_t dx = sx; + + // Compute the offset in bytes of the source and destination. + size_t s_idx = (soffset[2]+sz)*sslice + (soffset[1]+sy)*spitch + soffset[0]+sx; + size_t d_idx = (doffset[2]+dz)*dslice + (doffset[1]+dy)*dpitch + doffset[0]+dx; + + verify[dst][d_idx] = tmp_buffer[s_idx]; + } + return 0; +} + +void CL_CALLBACK mem_obj_destructor_callback( cl_mem, void *data ) +{ + free( data ); +} + +// This is the main test function for the conformance test. +int +test_bufferreadwriterect(cl_device_id device, cl_context context, cl_command_queue queue_, int num_elements) +{ + queue = queue_; + cl_int err; + + // Initialize the random number generator. + mt = init_genrand( gRandomSeed ); + + // Compute a maximum buffer size based on the number of test images and the device maximum. + cl_ulong max_mem_alloc_size = 0; + CL_EXIT_ERROR(clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_mem_alloc_size, NULL),"Could not get device info"); + log_info("CL_DEVICE_MAX_MEM_ALLOC_SIZE = %llu bytes.\n", max_mem_alloc_size); + + // Confirm that the maximum allocation size is not zero. + if (max_mem_alloc_size == 0) { + log_error("Error: CL_DEVICE_MAX_MEM_ALLOC_SIZE is zero bytes\n"); + return -1; + } + + // Guess at a reasonable maximum dimension. + size_t max_mem_alloc_dim = (size_t)cbrt((double)(max_mem_alloc_size/sizeof(BufferType)))/alloc_scale; + if (max_mem_alloc_dim == 0) { + max_mem_alloc_dim = max_mem_alloc_size; + } + + log_info("Using maximum dimension = %lu.\n", max_mem_alloc_dim); + + // Create pairs of cl buffers and host buffers on which operations will be mirrored. + log_info("Creating %u pairs of random sized host and cl buffers.\n", TotalImages); + + size_t max_size = 0; + size_t total_bytes = 0; + + for (unsigned i=0; i != TotalImages; ++i) { + + // Determine a width and height for this buffer. + size_t size_bytes; + size_t tries = 0; + size_t max_tries = 1048576; + do { + width[i] = get_random_size_t(1, max_mem_alloc_dim, mt); + height[i] = get_random_size_t(1, max_mem_alloc_dim, mt); + depth[i] = get_random_size_t(1, max_mem_alloc_dim, mt); + ++tries; + } while ((tries < max_tries) && (size_bytes = width[i]*height[i]*depth[i]*sizeof(BufferType)) > max_mem_alloc_size); + + // Check to see if adequately sized buffers were found. + if (tries >= max_tries) { + log_error("Error: Could not find random buffer sized less than %llu bytes in %lu tries.\n", + max_mem_alloc_size, max_tries); + return -1; + } + + // Keep track of the dimensions of the largest buffer. + max_size = (size_bytes > max_size) ? size_bytes : max_size; + total_bytes += size_bytes; + + log_info("Buffer[%u] is (%lu,%lu,%lu) = %lu MB (truncated)\n",i,width[i],height[i],depth[i],(size_bytes)/1048576); + } + + log_info( "Total size: %lu MB (truncated)\n", total_bytes/1048576 ); + + // Allocate a temporary buffer for read and write operations. + tmp_buffer_size = max_size; + tmp_buffer = (BufferType*)malloc(tmp_buffer_size); + + // Initialize cl buffers + log_info( "Initializing buffers\n" ); + for (unsigned i=0; i != TotalImages; ++i) { + + size_t size_bytes = width[i]*height[i]*depth[i]*sizeof(BufferType); + + // Allocate a host copy of the buffer for verification. + verify[i] = (BufferType*)malloc(size_bytes); + CL_EXIT_ERROR(verify[i] ? CL_SUCCESS : -1, "malloc of host buffer failed for buffer %u", i); + + // Allocate the buffer in host memory. + backing[i] = (BufferType*)malloc(size_bytes); + CL_EXIT_ERROR(backing[i] ? CL_SUCCESS : -1, "malloc of backing buffer failed for buffer %u", i); + + // Generate a random buffer. + log_info( "Initializing buffer %u\n", i ); + initialize_image(verify[i], width[i], height[i], depth[i], mt); + + // Copy the image into a buffer which will passed to CL. + memcpy(backing[i], verify[i], size_bytes); + + // Create the CL buffer. + buffer[i] = clCreateBuffer (context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, size_bytes, backing[i], &err); + CL_EXIT_ERROR(err,"clCreateBuffer failed for buffer %u", i); + + // Make sure buffer is cleaned up appropriately if we encounter an error in the rest of the calls. + err = clSetMemObjectDestructorCallback( buffer[i], mem_obj_destructor_callback, backing[i] ); + CL_EXIT_ERROR(err, "Unable to set mem object destructor callback" ); + } + + // Main test loop, run num_tries times. + log_info( "Executing %u test operations selected at random.\n", (unsigned)num_tries ); + for (size_t iter = 0; iter < num_tries; ++iter) { + + // Determine a source and a destination. + size_t src = get_random_size_t(0,TotalImages,mt); + size_t dst = get_random_size_t(0,TotalImages,mt); + + // Determine the minimum dimensions. + size_t min_width = width[src] < width[dst] ? width[src] : width[dst]; + size_t min_height = height[src] < height[dst] ? height[src] : height[dst]; + size_t min_depth = depth[src] < depth[dst] ? depth[src] : depth[dst]; + + // Generate a random source rectangle within the minimum dimensions. + size_t mx = get_random_size_t(0, min_width-1, mt); + size_t my = get_random_size_t(0, min_height-1, mt); + size_t mz = get_random_size_t(0, min_depth-1, mt); + + size_t sw = get_random_size_t(1, (min_width - mx), mt); + size_t sh = get_random_size_t(1, (min_height - my), mt); + size_t sd = get_random_size_t(1, (min_depth - mz), mt); + + size_t sx = get_random_size_t(0, width[src]-sw, mt); + size_t sy = get_random_size_t(0, height[src]-sh, mt); + size_t sz = get_random_size_t(0, depth[src]-sd, mt); + + size_t soffset[] = { sx, sy, sz }; + size_t sregion[] = { sw, sh, sd }; + + // Generate a destination rectangle of the same size. + size_t dw = sw; + size_t dh = sh; + size_t dd = sd; + + // Generate a random destination offset within the buffer. + size_t dx = get_random_size_t(0, (width[dst] - dw), mt); + size_t dy = get_random_size_t(0, (height[dst] - dh), mt); + size_t dz = get_random_size_t(0, (depth[dst] - dd), mt); + size_t doffset[] = { dx, dy, dz }; + size_t dregion[] = { dw, dh, dd }; + + // Execute one of three operations: + // - Copy: Copies between src and dst within each set of host, buffer, and images. + // - Read & verify: Reads src region from buffer and image, and compares to host. + // - Write: Generates new buffer with src dimensions, and writes to cl buffer and image. + + enum { TotalOperations = 3 }; + size_t operation = get_random_size_t(0,TotalOperations,mt); + + switch (operation) { + case 0: + log_info("%lu Copy %lu offset (%lu,%lu,%lu) -> %lu offset (%lu,%lu,%lu) region (%lux%lux%lu = %lu)\n", + iter, + src, soffset[0], soffset[1], soffset[2], + dst, doffset[0], doffset[1], doffset[2], + sregion[0], sregion[1], sregion[2], + sregion[0]*sregion[1]*sregion[2]); + if ((err = copy_region(src, soffset, sregion, dst, doffset, dregion))) + return err; + break; + case 1: + log_info("%lu Read %lu offset (%lu,%lu,%lu) -> %lu offset (%lu,%lu,%lu) region (%lux%lux%lu = %lu)\n", + iter, + src, soffset[0], soffset[1], soffset[2], + dst, doffset[0], doffset[1], doffset[2], + sregion[0], sregion[1], sregion[2], + sregion[0]*sregion[1]*sregion[2]); + if ((err = read_verify_region(src, soffset, sregion, dst, doffset, dregion))) + return err; + break; + case 2: + log_info("%lu Write %lu offset (%lu,%lu,%lu) -> %lu offset (%lu,%lu,%lu) region (%lux%lux%lu = %lu)\n", + iter, + src, soffset[0], soffset[1], soffset[2], + dst, doffset[0], doffset[1], doffset[2], + sregion[0], sregion[1], sregion[2], + sregion[0]*sregion[1]*sregion[2]); + if ((err = write_region(src, soffset, sregion, dst, doffset, dregion))) + return err; + break; + } + +#if 0 + // Uncomment this section to verify each operation. + // If commented out, verification won't occur until the end of the + // test, and it will not be possible to determine which operation failed. + log_info("Verify src %lu offset (%u,%u,%u) region (%lux%lux%lu)\n", src, 0, 0, 0, width[src], height[src], depth[src]); + if (err = map_verify_region(src)) + return err; + + log_info("Verify dst %lu offset (%u,%u,%u) region (%lux%lux%lu)\n", dst, 0, 0, 0, width[dst], height[dst], depth[dst]); + if (err = map_verify_region(dst)) + return err; + + +#endif + + } // end main for loop. + + for (unsigned i=0;i +#include +#include +#include +#include + + +#include "procs.h" + +const char *constant_kernel_code = +"__kernel void constant_kernel(__global float *out, __constant float *tmpF, __constant int *tmpI)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" float ftmp = tmpF[tid]; \n" +" float Itmp = tmpI[tid]; \n" +" out[tid] = ftmp * Itmp; \n" +"}\n"; + +const char *loop_constant_kernel_code = +"kernel void loop_constant_kernel(global float *out, constant float *i_pos, int num)\n" +"{\n" +" int tid = get_global_id(0);\n" +" float sum = 0;\n" +" for (int i = 0; i < num; i++) {\n" +" float pos = i_pos[i*3];\n" +" sum += pos;\n" +" }\n" +" out[tid] = sum;\n" +"}\n"; + + +static int +verify(cl_float *tmpF, cl_int *tmpI, cl_float *out, int n) +{ + int i; + + for (i=0; i < n; i++) + { + float f = tmpF[i] * tmpI[i]; + if( out[i] != f ) + { + log_error("CONSTANT test failed\n"); + return -1; + } + } + + log_info("CONSTANT test passed\n"); + return 0; +} + + +static int +verify_loop_constant(const cl_float *tmp, cl_float *out, cl_int l, int n) +{ + int i; + cl_int j; + for (i=0; i < n; i++) + { + float sum = 0; + for (j=0; j < l; ++j) + sum += tmp[j*3]; + + if( out[i] != sum ) + { + log_error("loop CONSTANT test failed\n"); + return -1; + } + } + + log_info("loop CONSTANT test passed\n"); + return 0; +} + +int +test_constant(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem streams[3]; + cl_int *tmpI; + cl_float *tmpF, *out; + cl_program program; + cl_kernel kernel; + size_t global_threads[3]; + int err; + unsigned int i; + cl_ulong maxSize; + size_t num_floats, num_ints, constant_values; + MTdata d; + RoundingMode oldRoundMode; + int isRTZ = 0; + + /* Verify our test buffer won't be bigger than allowed */ + err = clGetDeviceInfo( device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof( maxSize ), &maxSize, 0 ); + test_error( err, "Unable to get max constant buffer size" ); + + log_info("Device reports CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE %llu bytes.\n", maxSize); + maxSize/=4; + num_ints = (size_t)maxSize/sizeof(cl_int); + num_floats = (size_t)maxSize/sizeof(cl_float); + if (num_ints >= num_floats) { + constant_values = num_floats; + } else { + constant_values = num_ints; + } + + log_info("Test will attempt to use %lu bytes with one %lu byte constant int buffer and one %lu byte constant float buffer.\n", + constant_values*sizeof(cl_int) + constant_values*sizeof(cl_float), constant_values*sizeof(cl_int), constant_values*sizeof(cl_float)); + + tmpI = (cl_int*)malloc(sizeof(cl_int) * constant_values); + tmpF = (cl_float*)malloc(sizeof(cl_float) * constant_values); + out = (cl_float*)malloc(sizeof(cl_float) * constant_values); + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * constant_values, NULL, NULL); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * constant_values, NULL, NULL); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * constant_values, NULL, NULL); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + d = init_genrand( gRandomSeed ); + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +const char *constant_source_kernel_code[] = { +"__constant int outVal = 42;\n" +"__constant int outIndex = 7;\n" +"__constant int outValues[ 16 ] = { 17, 01, 11, 12, 1955, 11, 5, 1985, 113, 1, 24, 1984, 7, 23, 1979, 97 };\n" +"\n" +"__kernel void constant_kernel( __global int *out )\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" if( tid == 0 )\n" +" {\n" +" out[ 0 ] = outVal;\n" +" out[ 1 ] = outValues[ outIndex ];\n" +" }\n" +" else\n" +" {\n" +" out[ tid + 1 ] = outValues[ tid ];\n" +" }\n" +"}\n" }; + +int test_constant_source(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel; + + clMemWrapper outStream; + cl_int outValues[ 17 ]; + cl_int expectedValues[ 17 ] = { 42, 1985, 01, 11, 12, 1955, 11, 5, 1985, 113, 1, 24, 1984, 7, 23, 1979, 97 }; + + cl_int error; + + + // Create a kernel to test with + error = create_single_kernel_helper( context, &program, &kernel, 1, constant_source_kernel_code, "constant_kernel" ); + test_error( error, "Unable to create testing kernel" ); + + // Create our output buffer + outStream = clCreateBuffer( context, CL_MEM_WRITE_ONLY, sizeof( outValues ), NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + // Set the argument + error = clSetKernelArg( kernel, 0, sizeof( outStream ), &outStream ); + test_error( error, "Unable to set kernel argument" ); + + // Run test kernel + size_t threads[ 1 ] = { 16 }; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to enqueue kernel" ); + + // Read results + error = clEnqueueReadBuffer( queue, outStream, CL_TRUE, 0, sizeof( outValues ), outValues, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + // Verify results + for( int i = 0; i < 17; i++ ) + { + if( expectedValues[ i ] != outValues[ i ] ) + { + if( i == 0 ) + log_error( "ERROR: Output value %d from constant source global did not validate! (Expected %d, got %d)\n", i, expectedValues[ i ], outValues[ i ] ); + else if( i == 1 ) + log_error( "ERROR: Output value %d from constant-indexed constant array did not validate! (Expected %d, got %d)\n", i, expectedValues[ i ], outValues[ i ] ); + else + log_error( "ERROR: Output value %d from variable-indexed constant array did not validate! (Expected %d, got %d)\n", i, expectedValues[ i ], outValues[ i ] ); + return -1; + } + } + + return 0; +} + + + + + diff --git a/test_conformance/basic/test_createkernelsinprogram.c b/test_conformance/basic/test_createkernelsinprogram.c new file mode 100644 index 00000000..2940f298 --- /dev/null +++ b/test_conformance/basic/test_createkernelsinprogram.c @@ -0,0 +1,105 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +const char *sample_single_kernel = { +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n"}; + +const char *sample_double_kernel = { +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n" +"__kernel void sample_test2(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n"}; + + +int +test_createkernelsinprogram(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_program program; + cl_kernel kernel[2]; + unsigned int num_kernels; + int err; + + err = create_single_kernel_helper(context, &program, NULL, 1, &sample_single_kernel, NULL); + if (err != CL_SUCCESS) + { + log_error("create_single_kernel_helper failed\n"); + return -1; + } + + err = clCreateKernelsInProgram(program, 1, kernel, &num_kernels); + if ( (err != CL_SUCCESS) || (num_kernels != 1) ) + { + log_error("clCreateKernelsInProgram test failed for a single kernel\n"); + return -1; + } + + clReleaseKernel(kernel[0]); + clReleaseProgram(program); + + err = create_single_kernel_helper(context, &program, NULL, 1, &sample_double_kernel, NULL); + if (err != CL_SUCCESS) + { + log_error("create_single_kernel_helper failed\n"); + return -1; + } + + err = clCreateKernelsInProgram(program, 2, kernel, &num_kernels); + if ( (err != CL_SUCCESS) || (num_kernels != 2) ) + { + log_error("clCreateKernelsInProgram test failed for two kernels\n"); + return -1; + } + + log_info("clCreateKernelsInProgram test passed\n"); + + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseProgram(program); + + + return err; +} + + + + + diff --git a/test_conformance/basic/test_enqueue_map.cpp b/test_conformance/basic/test_enqueue_map.cpp new file mode 100644 index 00000000..d78d20e5 --- /dev/null +++ b/test_conformance/basic/test_enqueue_map.cpp @@ -0,0 +1,254 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" + +const cl_mem_flags flag_set[] = { + CL_MEM_ALLOC_HOST_PTR, + CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_USE_HOST_PTR, + CL_MEM_COPY_HOST_PTR, + 0 +}; +const char* flag_set_names[] = { + "CL_MEM_ALLOC_HOST_PTR", + "CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR", + "CL_MEM_USE_HOST_PTR", + "CL_MEM_COPY_HOST_PTR", + "0" +}; + +int test_enqueue_map_buffer(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + const size_t bufferSize = 256*256; + int src_flag_id; + MTdata d = init_genrand( gRandomSeed ); + cl_char *initialData = (cl_char*)malloc(bufferSize); + cl_char *finalData = (cl_char*)malloc(bufferSize); + + for (src_flag_id=0; src_flag_id < sizeof(flag_set)/sizeof(flag_set[0]); src_flag_id++) + { + clMemWrapper memObject; + log_info("Testing with cl_mem_flags src: %s\n", flag_set_names[src_flag_id]); + + generate_random_data( kChar, (unsigned int)bufferSize, d, initialData ); + + if ((flag_set[src_flag_id] & CL_MEM_USE_HOST_PTR) || (flag_set[src_flag_id] & CL_MEM_COPY_HOST_PTR)) + memObject = clCreateBuffer(context, flag_set[src_flag_id], bufferSize * sizeof( cl_char ), initialData, &error); + else + memObject = clCreateBuffer(context, flag_set[src_flag_id], bufferSize * sizeof( cl_char ), NULL, &error); + test_error( error, "Unable to create testing buffer" ); + + if (!(flag_set[src_flag_id] & CL_MEM_USE_HOST_PTR) && !(flag_set[src_flag_id] & CL_MEM_COPY_HOST_PTR)) + { + error = clEnqueueWriteBuffer(queue, memObject, CL_TRUE, 0, bufferSize * sizeof( cl_char ), initialData, 0, NULL, NULL); + test_error( error, "clEnqueueWriteBuffer failed"); + } + + for( int i = 0; i < 128; i++ ) + { + + size_t offset = (size_t)random_in_range( 0, (int)bufferSize - 1, d ); + size_t length = (size_t)random_in_range( 1, (int)( bufferSize - offset ), d ); + + cl_char *mappedRegion = (cl_char *)clEnqueueMapBuffer( queue, memObject, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, + offset, length, 0, NULL, NULL, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "clEnqueueMapBuffer call failed" ); + log_error( "\tOffset: %d Length: %d\n", (int)offset, (int)length ); + free( initialData ); + free( finalData ); + free_mtdata(d); + return -1; + } + + // Write into the region + for( size_t j = 0; j < length; j++ ) + { + cl_char spin = (cl_char)genrand_int32( d ); + + // Test read AND write in one swipe + cl_char value = mappedRegion[ j ]; + value = spin - value; + mappedRegion[ j ] = value; + + // Also update the initial data array + value = initialData[ offset + j ]; + value = spin - value; + initialData[ offset + j ] = value; + } + + // Unmap + error = clEnqueueUnmapMemObject( queue, memObject, mappedRegion, 0, NULL, NULL ); + test_error( error, "Unable to unmap buffer" ); + } + + // Final validation: read actual values of buffer and compare against our reference + error = clEnqueueReadBuffer( queue, memObject, CL_TRUE, 0, sizeof( cl_char ) * bufferSize, finalData, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + for( size_t q = 0; q < bufferSize; q++ ) + { + if( initialData[ q ] != finalData[ q ] ) + { + log_error( "ERROR: Sample %d did not validate! Got %d, expected %d\n", (int)q, (int)finalData[ q ], (int)initialData[ q ] ); + free( initialData ); + free( finalData ); + free_mtdata(d); + return -1; + } + } + } // cl_mem flags + + free( initialData ); + free( finalData ); + free_mtdata(d); + + return 0; +} + +int test_enqueue_map_image(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_image_format format = { CL_RGBA, CL_UNSIGNED_INT32 }; + const size_t imageSize = 256; + int src_flag_id; + cl_uint *initialData; + cl_uint *finalData; + MTdata d; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ) + + initialData = (cl_uint*)malloc(imageSize * imageSize * 4 *sizeof(cl_uint)); + finalData = (cl_uint*)malloc(imageSize * imageSize * 4 *sizeof(cl_uint)); + + if( !is_image_format_supported( context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE2D, &format ) ) + { + log_error( "ERROR: Test requires basic OpenCL 1.0 format CL_RGBA:CL_UNSIGNED_INT32, which is unsupported by this device!\n" ); + free(initialData); + free(finalData); + return -1; + } + + d = init_genrand( gRandomSeed ); + for (src_flag_id=0; src_flag_id < sizeof(flag_set)/sizeof(flag_set[0]); src_flag_id++) { + clMemWrapper memObject; + log_info("Testing with cl_mem_flags src: %s\n", flag_set_names[src_flag_id]); + + generate_random_data( kUInt, (unsigned int)( imageSize * imageSize ), d, initialData ); + + if ((flag_set[src_flag_id] & CL_MEM_USE_HOST_PTR) || (flag_set[src_flag_id] & CL_MEM_COPY_HOST_PTR)) + memObject = create_image_2d( context, CL_MEM_READ_WRITE | flag_set[src_flag_id], &format, + imageSize, imageSize, 0, initialData, &error ); + else + memObject = create_image_2d( context, CL_MEM_READ_WRITE | flag_set[src_flag_id], &format, + imageSize, imageSize, 0, NULL, &error ); + test_error( error, "Unable to create testing buffer" ); + + if (!(flag_set[src_flag_id] & CL_MEM_USE_HOST_PTR) && !(flag_set[src_flag_id] & CL_MEM_COPY_HOST_PTR)) { + size_t write_origin[3]={0,0,0}, write_region[3]={imageSize, imageSize, 1}; + error = clEnqueueWriteImage(queue, memObject, CL_TRUE, write_origin, write_region, NULL, NULL, initialData, 0, NULL, NULL); + test_error( error, "Unable to write to testing buffer" ); + } + + for( int i = 0; i < 128; i++ ) + { + + size_t offset[3], region[3]; + size_t rowPitch; + + offset[ 0 ] = (size_t)random_in_range( 0, (int)imageSize - 1, d ); + region[ 0 ] = (size_t)random_in_range( 1, (int)( imageSize - offset[ 0 ] - 1), d ); + offset[ 1 ] = (size_t)random_in_range( 0, (int)imageSize - 1, d ); + region[ 1 ] = (size_t)random_in_range( 1, (int)( imageSize - offset[ 1 ] - 1), d ); + offset[ 2 ] = 0; + region[ 2 ] = 1; + cl_uint *mappedRegion = (cl_uint *)clEnqueueMapImage( queue, memObject, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, + offset, region, &rowPitch, NULL, 0, NULL, NULL, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "clEnqueueMapImage call failed" ); + log_error( "\tOffset: %d,%d Region: %d,%d\n", (int)offset[0], (int)offset[1], (int)region[0], (int)region[1] ); + free(initialData); + free(finalData); + free_mtdata(d); + return -1; + } + + // Write into the region + cl_uint *mappedPtr = mappedRegion; + for( size_t y = 0; y < region[ 1 ]; y++ ) + { + for( size_t x = 0; x < region[ 0 ] * 4; x++ ) + { + cl_int spin = (cl_int)random_in_range( 16, 1024, d ); + + cl_int value; + // Test read AND write in one swipe + value = mappedPtr[ ( y * rowPitch/sizeof(cl_uint) ) + x ]; + value = spin - value; + mappedPtr[ ( y * rowPitch/sizeof(cl_uint) ) + x ] = value; + + // Also update the initial data array + value = initialData[ ( ( offset[ 1 ] + y ) * imageSize + offset[ 0 ] ) * 4 + x ]; + value = spin - value; + initialData[ ( ( offset[ 1 ] + y ) * imageSize + offset[ 0 ] ) * 4 + x ] = value; + } + } + + // Unmap + error = clEnqueueUnmapMemObject( queue, memObject, mappedRegion, 0, NULL, NULL ); + test_error( error, "Unable to unmap buffer" ); + } + + // Final validation: read actual values of buffer and compare against our reference + size_t finalOrigin[3] = { 0, 0, 0 }, finalRegion[3] = { imageSize, imageSize, 1 }; + error = clEnqueueReadImage( queue, memObject, CL_TRUE, finalOrigin, finalRegion, 0, 0, finalData, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + for( size_t q = 0; q < imageSize * imageSize * 4; q++ ) + { + if( initialData[ q ] != finalData[ q ] ) + { + log_error( "ERROR: Sample %d (coord %d,%d) did not validate! Got %d, expected %d\n", (int)q, (int)( ( q / 4 ) % imageSize ), (int)( ( q / 4 ) / imageSize ), + (int)finalData[ q ], (int)initialData[ q ] ); + free(initialData); + free(finalData); + free_mtdata(d); + return -1; + } + } + } // cl_mem_flags + + free(initialData); + free(finalData); + free_mtdata(d); + return 0; +} + + diff --git a/test_conformance/basic/test_enqueued_local_size.c b/test_conformance/basic/test_enqueued_local_size.c new file mode 100644 index 00000000..371f9ac6 --- /dev/null +++ b/test_conformance/basic/test_enqueued_local_size.c @@ -0,0 +1,123 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include +#include "../../test_common/harness/rounding_mode.h" + +#include "procs.h" + +static const char *enqueued_local_size_2d_code = +"__kernel void test_enqueued_local_size_2d(global int *dst)\n" +"{\n" +" if ((get_global_id(0) == 0) && (get_global_id(1) == 0))\n" +" {\n" +" dst[0] = (int)get_enqueued_local_size(0)\n;" +" dst[1] = (int)get_enqueued_local_size(1)\n;" +" }\n" +"}\n"; + +static const char *enqueued_local_size_1d_code = +"__kernel void test_enqueued_local_size_1d(global int *dst)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" if (get_global_id(0) == 0)\n" +" {\n" +" dst[tid_x] = (int)get_enqueued_local_size(0)\n;" +" }\n" +"}\n"; + + +static int +verify_enqueued_local_size(int *result, size_t *expected, int n) +{ + int i; + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" + +#define DECLARE_S2V_IDENT_KERNEL(srctype,dsttype,size) \ +"__kernel void test_conversion(__global " srctype " *sourceValues, __global " dsttype #size " *destValues )\n" \ +"{\n" \ +" int tid = get_global_id(0);\n" \ +" " srctype " src = sourceValues[tid];\n" \ +"\n" \ +" destValues[tid] = (" dsttype #size ")src;\n" \ +"\n" \ +"}\n" + +#define DECLARE_S2V_IDENT_KERNELS(srctype,dsttype) \ +{ \ +DECLARE_S2V_IDENT_KERNEL(srctype,#dsttype,2), \ +DECLARE_S2V_IDENT_KERNEL(srctype,#dsttype,4), \ +DECLARE_S2V_IDENT_KERNEL(srctype,#dsttype,8), \ +DECLARE_S2V_IDENT_KERNEL(srctype,#dsttype,16) \ +} + +#define DECLARE_EMPTY { NULL, NULL, NULL, NULL, NULL } + +/* Note: the next four arrays all must match in order and size to the ExplicitTypes enum in conversions.h!!! */ + +#define DECLARE_S2V_IDENT_KERNELS_SET(srctype) \ +{ \ +DECLARE_S2V_IDENT_KERNELS(#srctype,bool), \ + DECLARE_S2V_IDENT_KERNELS(#srctype,char), \ + DECLARE_S2V_IDENT_KERNELS(#srctype,uchar), \ + DECLARE_S2V_IDENT_KERNELS(#srctype,unsigned char), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,short), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,ushort), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,unsigned short), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,int), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,uint), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,unsigned int), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,long), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,ulong), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,unsigned long), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,float), \ +DECLARE_EMPTY \ +} + +#define DECLARE_EMPTY_SET \ +{ \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY \ +} + + +/* The overall array */ +const char * kernel_explicit_s2v_set[kNumExplicitTypes][kNumExplicitTypes][5] = { + DECLARE_S2V_IDENT_KERNELS_SET(bool), + DECLARE_S2V_IDENT_KERNELS_SET(char), + DECLARE_S2V_IDENT_KERNELS_SET(uchar), + DECLARE_S2V_IDENT_KERNELS_SET(unsigned char), + DECLARE_S2V_IDENT_KERNELS_SET(short), + DECLARE_S2V_IDENT_KERNELS_SET(ushort), + DECLARE_S2V_IDENT_KERNELS_SET(unsigned short), + DECLARE_S2V_IDENT_KERNELS_SET(int), + DECLARE_S2V_IDENT_KERNELS_SET(uint), + DECLARE_S2V_IDENT_KERNELS_SET(unsigned int), + DECLARE_S2V_IDENT_KERNELS_SET(long), + DECLARE_S2V_IDENT_KERNELS_SET(ulong), + DECLARE_S2V_IDENT_KERNELS_SET(unsigned long), + DECLARE_S2V_IDENT_KERNELS_SET(float), + DECLARE_EMPTY_SET +}; + +int test_explicit_s2v_function(cl_device_id deviceID, cl_context context, cl_command_queue queue, const char *programSrc, + ExplicitType srcType, unsigned int count, ExplicitType destType, unsigned int vecSize, void *inputData ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + int error; + clMemWrapper streams[2]; + void *outData; + unsigned char convertedData[ 8 ]; /* Max type size is 8 bytes */ + size_t threadSize[3], groupSize[3]; + unsigned int i, s; + unsigned char *inPtr, *outPtr; + size_t paramSize, destTypeSize; + + const char* finalProgramSrc[2] = { + "", // optional pragma + programSrc + }; + + if (srcType == kDouble || destType == kDouble) { + finalProgramSrc[0] = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"; + } + + + if( programSrc == NULL ) + return 0; + + paramSize = get_explicit_type_size( srcType ); + destTypeSize = get_explicit_type_size( destType ); + + size_t destStride = destTypeSize * vecSize; + + outData = malloc( destStride * count ); + + if( create_single_kernel_helper( context, &program, &kernel, 2, finalProgramSrc, "test_conversion" ) ) + { + log_info( "****** %s%s *******\n", finalProgramSrc[0], finalProgramSrc[1] ); + return -1; + } + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), paramSize * count, inputData, &error); + test_error( error, "clCreateBuffer failed"); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), destStride * count, NULL, &error); + test_error( error, "clCreateBuffer failed"); + + /* Set the arguments */ + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + /* Run the kernel */ + threadSize[0] = count; + + error = get_max_common_work_group_size( context, kernel, threadSize[0], &groupSize[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threadSize, groupSize, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* Now verify the results. Each value should have been duplicated four times, and we should be able to just + do a memcpy instead of relying on the actual type of data */ + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, destStride * count, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output values!" ); + + inPtr = (unsigned char *)inputData; + outPtr = (unsigned char *)outData; + + for( i = 0; i < count; i++ ) + { + /* Convert the input data element to our output data type to compare against */ + convert_explicit_value( (void *)inPtr, (void *)convertedData, srcType, false, kDefaultRoundingType, destType ); + + /* Now compare every element of the vector */ + for( s = 0; s < vecSize; s++ ) + { + if( memcmp( convertedData, outPtr + destTypeSize * s, destTypeSize ) != 0 ) + { + unsigned int *p = (unsigned int *)outPtr; + log_error( "ERROR: Output value %d:%d does not validate for size %d:%d!\n", i, s, vecSize, (int)destTypeSize ); + log_error( " Input: 0x%0*x\n", (int)( paramSize * 2 ), *(unsigned int *)inPtr & ( 0xffffffff >> ( 32 - paramSize * 8 ) ) ); + log_error( " Actual: 0x%08x 0x%08x 0x%08x 0x%08x\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] ); + return -1; + } + } + inPtr += paramSize; + outPtr += destStride; + } + + free( outData ); + + return 0; +} + +int test_explicit_s2v_function_set(cl_device_id deviceID, cl_context context, cl_command_queue queue, ExplicitType srcType, + unsigned int count, void *inputData ) +{ + unsigned int sizes[] = { 2, 4, 8, 16, 0 }; + int i, dstType, failed = 0; + + + for( dstType = kBool; dstType < kNumExplicitTypes; dstType++ ) + { + if( dstType == kDouble && !is_extension_available( deviceID, "cl_khr_fp64" ) ) + continue; + + if (( dstType == kLong || dstType == kULong ) && !gHasLong ) + continue; + + for( i = 0; sizes[i] != 0; i++ ) + { + if( dstType != srcType ) + continue; + if( strchr( get_explicit_type_name( (ExplicitType)srcType ), ' ' ) != NULL || + strchr( get_explicit_type_name( (ExplicitType)dstType ), ' ' ) != NULL ) + continue; + + if( test_explicit_s2v_function( deviceID, context, queue, kernel_explicit_s2v_set[ srcType ][ dstType ][ i ], + srcType, count, (ExplicitType)dstType, sizes[ i ], inputData ) != 0 ) + { + log_error( "ERROR: Explicit cast of scalar %s to vector %s%d FAILED; skipping other %s vector tests\n", + get_explicit_type_name(srcType), get_explicit_type_name((ExplicitType)dstType), sizes[i], get_explicit_type_name((ExplicitType)dstType) ); + failed = -1; + break; + } + } + } + + return failed; +} + +int test_explicit_s2v_bool(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + log_info( "NOTE: Boolean vectors not defined in OpenCL 1.0. Skipping test.\n" ); + return 0; +#if 0 + bool data[128]; + + generate_random_data( kBool, 128, data ); + + return test_explicit_s2v_function_set( deviceID, context, queue, kBool, 128, data ); +#endif +} + +int test_explicit_s2v_char(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + char data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kChar, 128, seed, data ); + + return test_explicit_s2v_function_set( deviceID, context, queue, kChar, 128, data ); +} + +int test_explicit_s2v_uchar(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + unsigned char data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kUChar, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kUChar, 128, data ) != 0 ) + return -1; + if( test_explicit_s2v_function_set( deviceID, context, queue, kUnsignedChar, 128, data ) != 0 ) + return -1; + return 0; +} + +int test_explicit_s2v_short(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + short data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kShort, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kShort, 128, data ) != 0 ) + return -1; + return 0; +} + +int test_explicit_s2v_ushort(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + unsigned short data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kUShort, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kUShort, 128, data ) != 0 ) + return -1; + if( test_explicit_s2v_function_set( deviceID, context, queue, kUnsignedShort, 128, data ) != 0 ) + return -1; + return 0; +} + +int test_explicit_s2v_int(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kInt, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kInt, 128, data ) != 0 ) + return -1; + return 0; +} + +int test_explicit_s2v_uint(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + unsigned int data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kUInt, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kUInt, 128, data ) != 0 ) + return -1; + if( test_explicit_s2v_function_set( deviceID, context, queue, kUnsignedInt, 128, data ) != 0 ) + return -1; + return 0; +} + +int test_explicit_s2v_long(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_long data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kLong, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kLong, 128, data ) != 0 ) + return -1; + return 0; +} + +int test_explicit_s2v_ulong(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_ulong data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kULong, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kULong, 128, data ) != 0 ) + return -1; + if( test_explicit_s2v_function_set( deviceID, context, queue, kUnsignedLong, 128, data ) != 0 ) + return -1; + return 0; +} + +int test_explicit_s2v_float(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + float data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kFloat, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kFloat, 128, data ) != 0 ) + return -1; + return 0; +} + + +int test_explicit_s2v_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + double data[128]; + RandomSeed seed(gRandomSeed); + + if( !is_extension_available( deviceID, "cl_khr_fp64" ) ) { + log_info("Extension cl_khr_fp64 not supported. Skipping test.\n"); + return 0; + } + + generate_random_data( kDouble, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kDouble, 128, data ) != 0 ) + return -1; + return 0; +} + + diff --git a/test_conformance/basic/test_float2int.c b/test_conformance/basic/test_float2int.c new file mode 100644 index 00000000..55411728 --- /dev/null +++ b/test_conformance/basic/test_float2int.c @@ -0,0 +1,145 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +const char *float2int_kernel_code = +"__kernel void test_float2int(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n"; + + +int +verify_float2int(cl_float *inptr, cl_int *outptr, int n) +{ + int i; + + for (i=0; i +#include +#include +#include +#include +#include "../../test_common/harness/rounding_mode.h" + +#include "procs.h" + +static const char *fpadd_kernel_code = +"__kernel void test_fpadd(__global float *srcA, __global float *srcB, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +static const char *fpsub_kernel_code = +"__kernel void test_fpsub(__global float *srcA, __global float *srcB, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +static const char *fpmul_kernel_code = +"__kernel void test_fpmul(__global float *srcA, __global float *srcB, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + + +static const float MAX_ERR = 1e-5f; + +static int +verify_fpadd(float *inptrA, float *inptrB, float *outptr, int n) +{ + float r; + int i; + + for (i=0; i +#include +#include +#include +#include +#include "../../test_common/harness/rounding_mode.h" + + +#include "procs.h" + +const char *fpadd2_kernel_code = +"__kernel void test_fpadd2(__global float2 *srcA, __global float2 *srcB, __global float2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *fpsub2_kernel_code = +"__kernel void test_fpsub2(__global float2 *srcA, __global float2 *srcB, __global float2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *fpmul2_kernel_code = +"__kernel void test_fpmul2(__global float2 *srcA, __global float2 *srcB, __global float2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + + +int +verify_fpadd2(float *inptrA, float *inptrB, float *outptr, int n) +{ + float r; + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/rounding_mode.h" + +const char *fpadd4_kernel_code = +"__kernel void test_fpadd4(__global float4 *srcA, __global float4 *srcB, __global float4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *fpsub4_kernel_code = +"__kernel void test_fpsub4(__global float4 *srcA, __global float4 *srcB, __global float4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *fpmul4_kernel_code = +"__kernel void test_fpmul4(__global float4 *srcA, __global float4 *srcB, __global float4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + + +int +verify_fpadd4(float *inptrA, float *inptrB, float *outptr, int n) +{ + float r; + int i; + + for (i=0; i + +static const char *linear_ids_source[1] = { +"__kernel void test_linear_ids(__global int2 *out)\n" +"{\n" +" size_t lid, gid;\n" +" uint d = get_work_dim();\n" +" if (d == 1U) {\n" +" gid = get_global_id(0) - get_global_offset(0);\n" +" lid = get_local_id(0);\n" +" } else if (d == 2U) {\n" +" gid = (get_global_id(1) - get_global_offset(1)) * get_global_size(0) +\n" +" (get_global_id(0) - get_global_offset(0));\n" +" lid = get_local_id(1) * get_local_size(0) + get_local_id(0);\n" +" } else {\n" +" gid = ((get_global_id(2) - get_global_offset(2)) * get_global_size(1) +\n" +" (get_global_id(1) - get_global_offset(1))) * get_global_size(0) +\n" +" (get_global_id(0) - get_global_offset(0));\n" +" lid = (get_local_id(2) * get_local_size(1) +\n" +" get_local_id(1)) * get_local_size(0) + get_local_id(0);\n" +" }\n" +" out[gid].x = gid == get_global_linear_id();\n" +" out[gid].y = lid == get_local_linear_id();\n" +"}\n" +}; + +#define NUM_ITER 12 +#define MAX_1D 4096 +#define MAX_2D 64 +#define MAX_3D 16 +#define MAX_OFFSET 100000 + +int +test_get_linear_ids(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper outbuf; + int error, iter, i, j, k; + size_t lws[3], gws[3], gwo[3]; + cl_uint dims; + cl_int outmem[2*MAX_1D], *om; + + + // Create the kernel + error = create_single_kernel_helper_with_build_options(context, &program, &kernel, 1, linear_ids_source, "test_linear_ids", "-cl-std=CL2.0"); + if (error) + return error; + + // Create the out buffer + outbuf = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(outmem), NULL, &error); + test_error(error, "failed to create result buffer\n"); + + // This will leak if there is an error, but this is what is done everywhere else + MTdata seed = init_genrand(gRandomSeed); + + // Run some tests + for (iter=0; iter +#include +#include +#include +#include +#include "../../test_common/harness/rounding_mode.h" + +#include "procs.h" + +static const char *global_linear_id_2d_code = +"__kernel void test_global_linear_id_2d(global int *dst)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +"\n" +" int linear_id = tid_y * get_global_size(0) + tid_x;\n" +" int result = (linear_id == (int)get_global_linear_id()) ? 0x1 : 0x0;\n" +" dst[linear_id] = result;\n" +"}\n"; + +static const char *global_linear_id_1d_code = +"__kernel void test_global_linear_id_1d(global int *dst)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +"\n" +" int result = (tid_x == (int)get_global_linear_id()) ? 0x1 : 0x0;\n" +" dst[tid_x] = result;\n" +"}\n"; + + +static int +verify_global_linear_id(int *result, int n) +{ + int i; + for (i=0; i + + +const char *work_offset_test[] = { + "__kernel void test( __global int * outputID_A, \n" + " __global int * outputID_B, __global int * outputID_C )\n" + "{\n" + " size_t id0 = get_local_id( 0 ) + get_group_id( 0 ) * get_local_size( 0 );\n" + " size_t id1 = get_local_id( 1 ) + get_group_id( 1 ) * get_local_size( 1 );\n" + " size_t id2 = get_local_id( 2 ) + get_group_id( 2 ) * get_local_size( 2 );\n" + " size_t id = ( id2 * get_global_size( 0 ) * get_global_size( 1 ) ) + ( id1 * get_global_size( 0 ) ) + id0;\n" + "\n" + " outputID_A[ id ] = get_global_id( 0 );\n" + " outputID_B[ id ] = get_global_id( 1 );\n" + " outputID_C[ id ] = get_global_id( 2 );\n" + "}\n" + }; + +#define MAX_TEST_ITEMS 16 * 16 * 16 +#define NUM_TESTS 16 +#define MAX_OFFSET 256 + +#define CHECK_RANGE( v, m, c ) \ + if( ( v >= (cl_int)m ) || ( v < 0 ) ) \ + { \ + log_error( "ERROR: ouputID_%c[%lu]: %d is < 0 or >= %lu\n", c, i, v, m ); \ + return -1; \ + } + +int check_results( size_t threads[], size_t offsets[], cl_int outputA[], cl_int outputB[], cl_int outputC[] ) +{ + size_t offsettedSizes[ 3 ] = { threads[ 0 ] + offsets[ 0 ], threads[ 1 ] + offsets[ 1 ], threads[ 2 ] + offsets[ 2 ] }; + size_t limit = threads[ 0 ] * threads[ 1 ] * threads[ 2 ]; + + static char counts[ MAX_OFFSET + 32 ][ MAX_OFFSET + 16 ][ MAX_OFFSET + 16 ]; + memset( counts, 0, sizeof( counts ) ); + + for( size_t i = 0; i < limit; i++ ) + { + // Check ranges first + CHECK_RANGE( outputA[ i ], offsettedSizes[ 0 ], 'A' ) + CHECK_RANGE( outputB[ i ], offsettedSizes[ 1 ], 'B' ) + CHECK_RANGE( outputC[ i ], offsettedSizes[ 2 ], 'C' ) + + // Now set the value in the map + counts[ outputA[ i ] ][ outputB[ i ] ][ outputC[ i ] ]++; + } + + // Now check the map + int missed = 0, multiple = 0, errored = 0, corrected = 0; + for( size_t x = 0; x < offsettedSizes[ 0 ]; x++ ) + { + for( size_t y = 0; y < offsettedSizes[ 1 ]; y++ ) + { + for( size_t z = 0; z < offsettedSizes[ 2 ]; z++ ) + { + const char * limitMsg = " (further errors of this type suppressed)"; + if( ( x >= offsets[ 0 ] ) && ( y >= offsets[ 1 ] ) && ( z >= offsets[ 2 ] ) ) + { + if( counts[ x ][ y ][ z ] < 1 ) + { + if( missed < 3 ) + log_error( "ERROR: Map value (%ld,%ld,%ld) was missed%s\n", x, y, z, ( missed == 2 ) ? limitMsg : "" ); + missed++; + } + else if( counts[ x ][ y ][ z ] > 1 ) + { + if( multiple < 3 ) + log_error( "ERROR: Map value (%ld,%ld,%ld) was returned multiple times%s\n", x, y, z, ( multiple == 2 ) ? limitMsg : "" ); + multiple++; + } + } + else + { + if( counts[ x ][ y ][ z ] > 0 ) + { + if( errored < 3 ) + log_error( "ERROR: Map value (%ld,%ld,%ld) was erroneously returned%s\n", x, y, z, ( errored == 2 ) ? limitMsg : "" ); + errored++; + } + } + } + } + } + + if( missed || multiple || errored ) + { + size_t diffs[3] = { ( offsets[ 0 ] > threads[ 0 ] ? 0 : threads[ 0 ] - offsets[ 0 ] ), + ( offsets[ 1 ] > threads[ 1 ] ? 0 : threads[ 1 ] - offsets[ 1 ] ), + ( offsets[ 2 ] > threads[ 2 ] ? 0 : threads[ 2 ] - offsets[ 2 ] ) }; + int diff = (int)( ( threads[ 0 ] - diffs[ 0 ] ) * ( threads[ 1 ] - diffs[ 1 ] ) * ( threads[ 2 ] - diffs[ 2 ] ) ); + + if( ( multiple == 0 ) && ( missed == diff ) && ( errored == diff ) ) + log_error( "ERROR: Global work offset values are not being respected by get_global_id()\n" ); + else + log_error( "ERROR: Global work offset values did not function as expected (%d missed, %d reported multiple times, %d erroneously hit)\n", + missed, multiple, errored ); + } + return ( missed | multiple | errored | corrected ); +} + +int test_global_work_offsets(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 7 ]; + + int error; + size_t threads[] = {1,1,1}, localThreads[] = {1,1,1}, offsets[] = {0,0,0}; + cl_int outputA[ MAX_TEST_ITEMS ], outputB[ MAX_TEST_ITEMS ], outputC[ MAX_TEST_ITEMS ]; + + + // Create the kernel + if( create_single_kernel_helper( context, &program, &kernel, 1, work_offset_test, "test" ) != 0 ) + { + return -1; + } + + //// Create some output streams + + // Use just one output array to init them all (no need to init every single stack storage here) + memset( outputA, 0xff, sizeof( outputA ) ); + for( int i = 0; i < 3; i++ ) + { + streams[ i ] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR), sizeof(outputA), outputA, &error ); + test_error( error, "Unable to create output array" ); + } + + // Run a few different times + MTdata seed = init_genrand( gRandomSeed ); + for( int test = 0; test < NUM_TESTS; test++ ) + { + // Choose a random combination of thread size, but in total less than MAX_TEST_ITEMS + threads[ 0 ] = random_in_range( 1, 32, seed ); + threads[ 1 ] = random_in_range( 1, 16, seed ); + threads[ 2 ] = random_in_range( 1, MAX_TEST_ITEMS / (int)( threads[ 0 ] * threads[ 1 ] ), seed ); + + // Make sure we get the local thread count right + error = get_max_common_3D_work_group_size( context, kernel, threads, localThreads ); + test_error( error, "Unable to determine local work group sizes" ); + + // Randomize some offsets + for( int j = 0; j < 3; j++ ) + offsets[ j ] = random_in_range( 0, MAX_OFFSET, seed ); + + log_info( "\tTesting %ld,%ld,%ld (%ld,%ld,%ld) with offsets (%ld,%ld,%ld)...\n", + threads[ 0 ], threads[ 1 ], threads[ 2 ], localThreads[ 0 ], localThreads[ 1 ], localThreads[ 2 ], + offsets[ 0 ], offsets[ 1 ], offsets[ 2 ] ); + + // Now set up and run + for( int i = 0; i < 3; i++ ) + { + error = clSetKernelArg( kernel, i, sizeof( streams[i] ), &streams[i] ); + test_error( error, "Unable to set indexed kernel arguments" ); + } + + error = clEnqueueNDRangeKernel( queue, kernel, 3, offsets, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + // Read our results back now + cl_int * resultBuffers[] = { outputA, outputB, outputC }; + for( int i = 0; i < 3; i++ ) + { + error = clEnqueueReadBuffer( queue, streams[ i ], CL_TRUE, 0, sizeof( outputA ), resultBuffers[ i ], 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + } + + // Now we need to check the results. The outputs should have one entry for each possible ID, + // but they won't be in order, so we need to construct a count map to determine what we got + if( check_results( threads, offsets, outputA, outputB, outputC ) ) + { + log_error( "\t(Test failed for global dim %ld,%ld,%ld, local dim %ld,%ld,%ld, offsets %ld,%ld,%ld)\n", + threads[ 0 ], threads[ 1 ], threads[ 2 ], localThreads[ 0 ], localThreads[ 1 ], localThreads[ 2 ], + offsets[ 0 ], offsets[ 1 ], offsets[ 2 ] ); + return -1; + } + } + + free_mtdata(seed); + + // All done! + return 0; +} + +const char *get_offset_test[] = { + "__kernel void test( __global int * outOffsets )\n" + "{\n" + " // We use local ID here so we don't have to worry about offsets\n" + " // Also note that these should be the same for ALL threads, so we won't worry about contention\n" + " outOffsets[ 0 ] = (int)get_global_offset( 0 );\n" + " outOffsets[ 1 ] = (int)get_global_offset( 1 );\n" + " outOffsets[ 2 ] = (int)get_global_offset( 2 );\n" + "}\n" +}; + +int test_get_global_offset(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 1 ]; + + int error; + size_t threads[] = {1,1,1}, localThreads[] = {1,1,1}, offsets[] = {0,0,0}; + cl_int outOffsets[ 3 ]; + + + // Create the kernel + if( create_single_kernel_helper( context, &program, &kernel, 1, get_offset_test, "test" ) != 0 ) + { + return -1; + } + + // Create some output streams, and storage for a single control ID + memset( outOffsets, 0xff, sizeof( outOffsets ) ); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR), sizeof( outOffsets ), outOffsets, &error ); + test_error( error, "Unable to create control ID buffer" ); + + // Run a few different times + MTdata seed = init_genrand( gRandomSeed ); + for( int test = 0; test < NUM_TESTS; test++ ) + { + // Choose a random combination of thread size, but in total less than MAX_TEST_ITEMS + threads[ 0 ] = random_in_range( 1, 32, seed ); + threads[ 1 ] = random_in_range( 1, 16, seed ); + threads[ 2 ] = random_in_range( 1, MAX_TEST_ITEMS / (int)( threads[ 0 ] * threads[ 1 ] ), seed ); + + // Make sure we get the local thread count right + error = get_max_common_3D_work_group_size( context, kernel, threads, localThreads ); + test_error( error, "Unable to determine local work group sizes" ); + + // Randomize some offsets + for( int j = 0; j < 3; j++ ) + offsets[ j ] = random_in_range( 0, MAX_OFFSET, seed ); + + log_info( "\tTesting %ld,%ld,%ld (%ld,%ld,%ld) with offsets (%ld,%ld,%ld)...\n", + threads[ 0 ], threads[ 1 ], threads[ 2 ], localThreads[ 0 ], localThreads[ 1 ], localThreads[ 2 ], + offsets[ 0 ], offsets[ 1 ], offsets[ 2 ] ); + + // Now set up and run + error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 3, offsets, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + // Read our results back now + error = clEnqueueReadBuffer( queue, streams[ 0 ], CL_TRUE, 0, sizeof( outOffsets ), outOffsets, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + // And check! + int errors = 0; + for( int j = 0; j < 3; j++ ) + { + if( outOffsets[ j ] != (cl_int)offsets[ j ] ) + { + log_error( "ERROR: get_global_offset( %d ) did not return expected value (expected %ld, got %d)\n", j, offsets[ j ], outOffsets[ j ] ); + errors++; + } + } + if( errors > 0 ) + return errors; + } + free_mtdata(seed); + + // All done! + return 0; +} + diff --git a/test_conformance/basic/test_hiloeo.c b/test_conformance/basic/test_hiloeo.c new file mode 100644 index 00000000..c9777ec8 --- /dev/null +++ b/test_conformance/basic/test_hiloeo.c @@ -0,0 +1,421 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +int hi_offset( int index, int vectorSize) { return index + vectorSize / 2; } +int lo_offset( int index, int vectorSize) { return index; } +int even_offset( int index, int vectorSize ) { return index * 2; } +int odd_offset( int index, int vectorSize ) { return index * 2 + 1; } + +typedef int (*OffsetFunc)( int index, int vectorSize ); +static const OffsetFunc offsetFuncs[4] = { hi_offset, lo_offset, even_offset, odd_offset }; +typedef int (*verifyFunc)( const void *, const void *, const void *, int n, const char *sizeName ); +static const char *operatorToUse_names[] = { "hi", "lo", "even", "odd" }; +static const char *test_str_names[] = { "char", "uchar", "short", "ushort", "int", "uint", "long", "ulong", "float", "double" }; + +static const unsigned int vector_sizes[] = { 1, 2, 3, 4, 8, 16}; +static const unsigned int vector_aligns[] = { 1, 2, 4, 4, 8, 16}; +static const unsigned int out_vector_idx[] = { 0, 0, 1, 1, 3, 4}; +// if input is size vector_sizes[i], output is size +// vector_sizes[out_vector_idx[i]] +// input type name is strcat(gentype, vector_size_names[i]); +// and output type name is +// strcat(gentype, vector_size_names[out_vector_idx[i]]); +static const int size_to_idx[] = {-1,0,1,2,3,-1,-1,-1,4, + -1,-1,-1,-1,-1,-1,-1,5}; +static const char *vector_size_names[] = { "", "2", "3", "4", "8", "16"}; + +static const size_t kSizes[] = { 1, 1, 2, 2, 4, 4, 8, 8, 4, 8 }; +static int CheckResults( void *in, void *out, size_t elementCount, int type, int vectorSize, int operatorToUse ); + +int test_hiloeo(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_int *input_ptr, *output_ptr, *p; + int err; + cl_uint i; + int hasDouble = is_extension_available( device, "cl_khr_fp64" ); + cl_uint vectorSize, operatorToUse; + cl_uint type; + MTdata d; + + int expressionMode; + int numExpressionModes = 2; + + size_t length = sizeof(cl_int) * 4 * n_elems; + + input_ptr = (cl_int*)malloc(length); + output_ptr = (cl_int*)malloc(length); + + p = input_ptr; + d = init_genrand( gRandomSeed ); + for (i=0; i<4 * (cl_uint) n_elems; i++) + p[i] = genrand_int32(d); + free_mtdata(d); d = NULL; + + for( type = 0; type < sizeof( test_str_names ) / sizeof( test_str_names[0] ); type++ ) + { + // Note: restrict the element count here so we don't end up overrunning the output buffer if we're compensating for 32-bit writes + size_t elementCount = length / kSizes[type]; + cl_mem streams[2]; + + // skip double if unavailable + if( !hasDouble && ( 0 == strcmp( test_str_names[type], "double" ))) + continue; + + if( !gHasLong && + (( 0 == strcmp( test_str_names[type], "long" )) || + ( 0 == strcmp( test_str_names[type], "ulong" )))) + continue; + + log_info( "%s", test_str_names[type] ); + fflush( stdout ); + + // Set up data streams for the type + streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + err = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, length, input_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + + for( operatorToUse = 0; operatorToUse < sizeof( operatorToUse_names ) / sizeof( operatorToUse_names[0] ); operatorToUse++ ) + { + log_info( " %s", operatorToUse_names[ operatorToUse ] ); + fflush( stdout ); + for( vectorSize = 1; vectorSize < sizeof( vector_size_names ) / sizeof( vector_size_names[0] ); vectorSize++ ) { + for(expressionMode = 0; expressionMode < numExpressionModes; ++expressionMode) { + + cl_program program = NULL; + cl_kernel kernel = NULL; + cl_uint outVectorSize = out_vector_idx[vectorSize]; + char expression[1024]; + + const char *source[] = { + "", // optional pragma string + "__kernel void test_", operatorToUse_names[ operatorToUse ], "_", test_str_names[type], vector_size_names[vectorSize], + "(__global ", test_str_names[type], vector_size_names[vectorSize], + " *srcA, __global ", test_str_names[type], vector_size_names[outVectorSize], + " *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " ", test_str_names[type], + vector_size_names[out_vector_idx[vectorSize]], + " tmp = ", expression, ".", operatorToUse_names[ operatorToUse ], ";\n" + " dst[tid] = tmp;\n" + "}\n" + }; + + if(expressionMode == 0) { + sprintf(expression, "srcA[tid]"); + } else if(expressionMode == 1) { + switch(vector_sizes[vectorSize]) { + case 16: + sprintf(expression, + "((%s16)(srcA[tid].s0, srcA[tid].s1, srcA[tid].s2, srcA[tid].s3, srcA[tid].s4, srcA[tid].s5, srcA[tid].s6, srcA[tid].s7, srcA[tid].s8, srcA[tid].s9, srcA[tid].sA, srcA[tid].sB, srcA[tid].sC, srcA[tid].sD, srcA[tid].sE, srcA[tid].sf))", + test_str_names[type] + ); + break; + case 8: + sprintf(expression, + "((%s8)(srcA[tid].s0, srcA[tid].s1, srcA[tid].s2, srcA[tid].s3, srcA[tid].s4, srcA[tid].s5, srcA[tid].s6, srcA[tid].s7))", + test_str_names[type] + ); + break; + case 4: + sprintf(expression, + "((%s4)(srcA[tid].s0, srcA[tid].s1, srcA[tid].s2, srcA[tid].s3))", + test_str_names[type] + ); + break; + case 3: + sprintf(expression, + "((%s3)(srcA[tid].s0, srcA[tid].s1, srcA[tid].s2))", + test_str_names[type] + ); + break; + case 2: + sprintf(expression, + "((%s2)(srcA[tid].s0, srcA[tid].s1))", + test_str_names[type] + ); + break; + default : + sprintf(expression, "srcA[tid]"); + log_info("Default\n"); + } + } else { + sprintf(expression, "srcA[tid]"); + } + + if (0 == strcmp( test_str_names[type], "double" )) + source[0] = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"; + + char kernelName[128]; + snprintf( kernelName, sizeof( kernelName ), "test_%s_%s%s", operatorToUse_names[ operatorToUse ], test_str_names[type], vector_size_names[vectorSize] ); + err = create_single_kernel_helper(context, &program, &kernel, sizeof( source ) / sizeof( source[0] ), source, kernelName ); + if (err) + return -1; + + err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]); + err |= clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + //Wipe the output buffer clean + uint32_t pattern = 0xdeadbeef; + memset_pattern4( output_ptr, &pattern, length ); + err = clEnqueueWriteBuffer(queue, streams[1], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + + size_t size = elementCount / (vector_aligns[vectorSize]); + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &size, NULL, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + err = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueReadBuffer failed\n"); + return -1; + } + + char *inP = (char *)input_ptr; + char *outP = (char *)output_ptr; + outP += kSizes[type] * ( ( vector_sizes[outVectorSize] ) - + ( vector_sizes[ out_vector_idx[vectorSize] ] ) ); + // was outP += kSizes[type] * ( ( 1 << outVectorSize ) - ( 1 << ( vectorSize - 1 ) ) ); + for( size_t e = 0; e < size; e++ ) + { + if( CheckResults( inP, outP, 1, type, vectorSize, operatorToUse ) ) { + + log_info("e is %d\n", (int)e); + fflush(stdout); + // break; + return -1; + } + inP += kSizes[type] * ( vector_aligns[vectorSize] ); + outP += kSizes[type] * ( vector_aligns[outVectorSize] ); + } + + clReleaseKernel( kernel ); + clReleaseProgram( program ); + log_info( "." ); + fflush( stdout ); + } + } + } + + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + log_info( "done\n" ); + } + + log_info("HiLoEO test passed\n"); + + free(input_ptr); + free(output_ptr); + + return err; +} + +static int CheckResults( void *in, void *out, size_t elementCount, int type, int vectorSize, int operatorToUse ) +{ + cl_ulong array[8]; + void *p = array; + size_t halfVectorSize = vector_sizes[out_vector_idx[vectorSize]]; + size_t cmpVectorSize = vector_sizes[out_vector_idx[vectorSize]]; + // was 1 << (vectorSize-1); + OffsetFunc f = offsetFuncs[ operatorToUse ]; + size_t elementSize = kSizes[type]; + + if(vector_size_names[vectorSize][0] == '3') { + if(operatorToUse_names[operatorToUse][0] == 'h' || + operatorToUse_names[operatorToUse][0] == 'o') // hi or odd + { + cmpVectorSize = 1; // special case for vec3 ignored values + } + } + + switch( elementSize ) + { + case 1: + { + char *i = (char*)in; + char *o = (char*)out; + size_t j; + cl_uint k; + OffsetFunc f = offsetFuncs[ operatorToUse ]; + + for( k = 0; k < elementCount; k++ ) + { + char *o2 = (char*)p; + for( j = 0; j < halfVectorSize; j++ ) + o2[j] = i[ f((int)j, (int)halfVectorSize*2) ]; + + if( memcmp( o, o2, elementSize * cmpVectorSize ) ) + { + log_info( "\n%d) Failure for %s%s.%s { %d", k, test_str_names[type], vector_size_names[ vectorSize ], operatorToUse_names[ operatorToUse ], i[0] ); + for( j = 1; j < halfVectorSize * 2; j++ ) + log_info( ", %d", i[j] ); + log_info( " } --> { %d", o[0] ); + for( j = 1; j < halfVectorSize; j++ ) + log_info( ", %d", o[j] ); + log_info( " }\n" ); + return -1; + } + i += 2 * halfVectorSize; + o += halfVectorSize; + } + } + break; + + case 2: + { + short *i = (short*)in; + short *o = (short*)out; + size_t j; + cl_uint k; + + for( k = 0; k < elementCount; k++ ) + { + short *o2 = (short*)p; + for( j = 0; j < halfVectorSize; j++ ) + o2[j] = i[ f((int)j, (int)halfVectorSize*2) ]; + + if( memcmp( o, o2, elementSize * cmpVectorSize ) ) + { + log_info( "\n%d) Failure for %s%s.%s { %d", k, test_str_names[type], vector_size_names[ vectorSize ], operatorToUse_names[ operatorToUse ], i[0] ); + for( j = 1; j < halfVectorSize * 2; j++ ) + log_info( ", %d", i[j] ); + log_info( " } --> { %d", o[0] ); + for( j = 1; j < halfVectorSize; j++ ) + log_info( ", %d", o[j] ); + log_info( " }\n" ); + return -1; + } + i += 2 * halfVectorSize; + o += halfVectorSize; + } + } + break; + + case 4: + { + int *i = (int*)in; + int *o = (int*)out; + size_t j; + cl_uint k; + + for( k = 0; k < elementCount; k++ ) + { + int *o2 = (int *)p; + for( j = 0; j < halfVectorSize; j++ ) + o2[j] = i[ f((int)j, (int)halfVectorSize*2) ]; + + for( j = 0; j < cmpVectorSize; j++ ) + { + /* Allow float nans to be binary different */ + if( memcmp( &o[j], &o2[j], elementSize ) && !((strcmp(test_str_names[type], "float") == 0) && isnan(((float *)o)[j]) && isnan(((float *)o2)[j]))) + { + log_info( "\n%d) Failure for %s%s.%s { 0x%8.8x", k, test_str_names[type], vector_size_names[ vectorSize ], operatorToUse_names[ operatorToUse ], i[0] ); + for( j = 1; j < halfVectorSize * 2; j++ ) + log_info( ", 0x%8.8x", i[j] ); + log_info( " } --> { 0x%8.8x", o[0] ); + for( j = 1; j < halfVectorSize; j++ ) + log_info( ", 0x%8.8x", o[j] ); + log_info( " }\n" ); + return -1; + } + } + i += 2 * halfVectorSize; + o += halfVectorSize; + } + } + break; + + case 8: + { + cl_ulong *i = (cl_ulong*)in; + cl_ulong *o = (cl_ulong*)out; + size_t j; + cl_uint k; + + for( k = 0; k < elementCount; k++ ) + { + cl_ulong *o2 = (cl_ulong*)p; + for( j = 0; j < halfVectorSize; j++ ) + o2[j] = i[ f((int)j, (int)halfVectorSize*2) ]; + + if( memcmp( o, o2, elementSize * cmpVectorSize ) ) + { + log_info( "\n%d) Failure for %s%s.%s { 0x%16.16llx", k, test_str_names[type], vector_size_names[ vectorSize ], operatorToUse_names[ operatorToUse ], i[0] ); + for( j = 1; j < halfVectorSize * 2; j++ ) + log_info( ", 0x%16.16llx", i[j] ); + log_info( " } --> { 0x%16.16llx", o[0] ); + for( j = 1; j < halfVectorSize; j++ ) + log_info( ", 0x%16.16llx", o[j] ); + log_info( " }\n" ); + return -1; + } + i += 2 * halfVectorSize; + o += halfVectorSize; + } + } + break; + + default: + log_info( "Internal error. Unknown data type\n" ); + return -2; + } + + return 0; +} + + + diff --git a/test_conformance/basic/test_hostptr.c b/test_conformance/basic/test_hostptr.c new file mode 100644 index 00000000..4990dfd2 --- /dev/null +++ b/test_conformance/basic/test_hostptr.c @@ -0,0 +1,277 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +const char *hostptr_kernel_code = +"__kernel void test_hostptr(__global float *srcA, __global float *srcB, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +static const float MAX_ERR = 1e-5f; + +static int verify_hostptr(cl_float *inptrA, cl_float *inptrB, cl_float *outptr, int n) +{ + cl_float r; + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +const char *conditional_kernel_code = +"__kernel void test_if(__global int *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" if (src[tid] == 0)\n" +" dst[tid] = 0x12345678;\n" +" else if (src[tid] == 1)\n" +" dst[tid] = 0x23456781;\n" +" else if (src[tid] == 2)\n" +" dst[tid] = 0x34567812;\n" +" else if (src[tid] == 3)\n" +" dst[tid] = 0x45678123;\n" +" else if (src[tid] == 4)\n" +" dst[tid] = 0x56781234;\n" +" else if (src[tid] == 5)\n" +" dst[tid] = 0x67812345;\n" +" else if (src[tid] == 6)\n" +" dst[tid] = 0x78123456;\n" +" else if (src[tid] == 7)\n" +" dst[tid] = 0x81234567;\n" +" else\n" +" dst[tid] = 0x7FFFFFFF;\n" +"\n" +"}\n"; + +const int results[] = { + 0x12345678, + 0x23456781, + 0x34567812, + 0x45678123, + 0x56781234, + 0x67812345, + 0x78123456, + 0x81234567, +}; + +int +verify_if(int *inptr, int *outptr, int n) +{ + int r, i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +static const char *image_to_image_kernel_integer_coord_code = +"\n" +"__kernel void image_to_image_copy(read_only image2d_t srcimg, write_only image2d_t dstimg, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y));\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + +static const char *image_to_image_kernel_float_coord_code = +"\n" +"__kernel void image_to_image_copy(read_only image2d_t srcimg, write_only image2d_t dstimg, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (float2)((float)tid_x, (float)tid_y));\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + + +static const char *image_sum_kernel_integer_coord_code = +"\n" +"__kernel void image_sum(read_only image2d_t srcimg0, read_only image2d_t srcimg1, write_only image2d_t dstimg, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 color0;\n" +" float4 color1;\n" +"\n" +" color0 = read_imagef(srcimg0, sampler, (int2)(tid_x, tid_y));\n" +" color1 = read_imagef(srcimg1, sampler, (int2)(tid_x, tid_y));\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color0 + color1);\n" +"\n" +"}\n"; + + +static const char *image_sum_kernel_float_coord_code = +"\n" +"__kernel void image_sum(read_only image2d_t srcimg0, read_only image2d_t srcimg1, write_only image2d_t dstimg, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 color0;\n" +" float4 color1;\n" +"\n" +" color0 = read_imagef(srcimg0, sampler, (float2)((float)tid_x, (float)tid_y));\n" +" color1 = read_imagef(srcimg1, sampler, (float2)((float)tid_x, (float)tid_y));\n" +" write_imagef(dstimg,(int2)(tid_x, tid_y), color0 + color1);\n" +"\n" +"}\n"; + + +static unsigned char * +generate_initial_byte_image(int w, int h, int num_elements, unsigned char value) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * num_elements); + int i; + + for (i = 0; i < w*h*num_elements; i++) + ptr[i] = value; + + return ptr; +} + +static unsigned char * +generate_expected_byte_image(unsigned char **input_data, int num_inputs, int w, int h, int num_elements) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * num_elements); + int i; + + for (i = 0; i < w*h*num_elements; i++) + { + int j; + ptr[i] = 0; + for (j = 0; j < num_inputs; j++) + { + unsigned char *input = *(input_data + j); + ptr[i] += input[i]; + } + } + + return ptr; +} + + +static unsigned char * +generate_byte_image(int w, int h, int num_elements, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * num_elements); + int i; + + for (i = 0; i < w*h*num_elements; i++) + ptr[i] = (unsigned char)genrand_int32(d) & 31; + + return ptr; +} + +static int +verify_byte_image(unsigned char *image, unsigned char *outptr, int w, int h, int num_elements) +{ + int i; + + for (i = 0; i < w*h*num_elements; i++) + { + if (outptr[i] != image[i]) + { + return -1; + } + } + return 0; +} + +int +test_image_multipass_integer_coord(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + int img_width = 512; + int img_height = 512; + cl_image_format img_format; + + int num_input_streams = 8; + cl_mem *input_streams; + cl_mem accum_streams[2]; + unsigned char *expected_output; + unsigned char *output_ptr; + cl_kernel kernel[2]; + int err; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + + expected_output = (unsigned char*)malloc(sizeof(unsigned char) * 4 * img_width * img_height); + output_ptr = (unsigned char*)malloc(sizeof(unsigned char) * 4 * img_width * img_height); + + // Create the accum images with initial data. + { + unsigned char *initial_data; + cl_mem_flags flags; + + initial_data = generate_initial_byte_image(img_width, img_height, 4, 0xF0); + flags = (cl_mem_flags)(CL_MEM_READ_WRITE); + + accum_streams[0] = create_image_2d(context, flags, &img_format, img_width, img_height, 0, NULL, NULL); + if (!accum_streams[0]) + { + log_error("create_image_2d failed\n"); + free(expected_output); + free(output_ptr); + return -1; + } + + size_t origin[3] = {0, 0, 0}, region[3] = {img_width, img_height, 1}; + err = clEnqueueWriteImage(queue, accum_streams[0], CL_TRUE, + origin, region, 0, 0, + initial_data, 0, NULL, NULL); + if (err) + { + log_error("clWriteImage failed: %d\n", err); + free(expected_output); + free(output_ptr); + return -1; + } + + accum_streams[1] = create_image_2d(context, flags, &img_format, img_width, img_height, 0, NULL, NULL); + if (!accum_streams[1]) + { + log_error("create_image_2d failed\n"); + free(expected_output); + free(output_ptr); + return -1; + } + err = clEnqueueWriteImage(queue, accum_streams[1], CL_TRUE, + origin, region, 0, 0, + initial_data, 0, NULL, NULL); + if (err) + { + log_error("clWriteImage failed: %d\n", err); + free(expected_output); + free(output_ptr); + return -1; + } + + free(initial_data); + } + + // Set up the input data. + { + cl_mem_flags flags; + unsigned char **input_data = (unsigned char **)malloc(sizeof(unsigned char*) * num_input_streams); + MTdata d; + + input_streams = (cl_mem*)malloc(sizeof(cl_mem) * num_input_streams); + flags = (cl_mem_flags)(CL_MEM_READ_WRITE); + + int i; + d = init_genrand( gRandomSeed ); + for ( i = 0; i < num_input_streams; i++) + { + input_data[i] = generate_byte_image(img_width, img_height, 4, d); + input_streams[i] = create_image_2d(context, flags, &img_format, img_width, img_height, 0, NULL, NULL); + if (!input_streams[i]) + { + log_error("create_image_2d failed\n"); + free_mtdata(d); + free(expected_output); + free(output_ptr); + return -1; + } + + size_t origin[3] = {0, 0, 0}, region[3] = {img_width, img_height, 1}; + err = clEnqueueWriteImage(queue, input_streams[i], CL_TRUE, + origin, region, 0, 0, + input_data[i], 0, NULL, NULL); + if (err) + { + log_error("clWriteImage failed: %d\n", err); + free_mtdata(d); + free(expected_output); + free(output_ptr); + free(input_streams); + return -1; + } + + + } + free_mtdata(d); d = NULL; + expected_output = generate_expected_byte_image(input_data, num_input_streams, img_width, img_height, 4); + for ( i = 0; i < num_input_streams; i++) + { + free(input_data[i]); + } + free( input_data ); + } + + // Set up the kernels. + { + cl_program program[4]; + + err = create_single_kernel_helper(context, &program[0], &kernel[0], 1, &image_to_image_kernel_integer_coord_code, "image_to_image_copy"); + if (err) + { + log_error("Failed to create kernel 0: %d\n", err); + return -1; + } + err = create_single_kernel_helper(context, &program[1], &kernel[1], 1, &image_sum_kernel_integer_coord_code, "image_sum"); + if (err) + { + log_error("Failed to create kernel 1: %d\n", err); + return -1; + } + clReleaseProgram(program[0]); + clReleaseProgram(program[1]); + } + + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_CLAMP_TO_EDGE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + cl_sampler sampler = clCreateSamplerWithProperties(context, properties, &err); + test_error(err, "clCreateSamplerWithProperties failed"); + + { + size_t threads[3] = {0, 0, 0}; + threads[0] = (size_t)img_width; + threads[1] = (size_t)img_height; + int i; + + { + cl_mem accum_input; + cl_mem accum_output; + + err = clSetKernelArg(kernel[0], 0, sizeof input_streams[0], &input_streams[0]); + err |= clSetKernelArg(kernel[0], 1, sizeof accum_streams[0], &accum_streams[0]); + err |= clSetKernelArg(kernel[0], 2, sizeof sampler, &sampler); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + err = clEnqueueNDRangeKernel( queue, kernel[0], 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + for (i = 1; i < num_input_streams; i++) + { + accum_input = accum_streams[(i-1)%2]; + accum_output = accum_streams[i%2]; + + err = clSetKernelArg(kernel[1], 0, sizeof accum_input, &accum_input); + err |= clSetKernelArg(kernel[1], 1, sizeof input_streams[i], &input_streams[i]); + err |= clSetKernelArg(kernel[1], 2, sizeof accum_output, &accum_output); + err |= clSetKernelArg(kernel[1], 3, sizeof sampler, &sampler); + + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + err = clEnqueueNDRangeKernel( queue, kernel[1], 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + } + + // Copy the last accum into the other one. + accum_input = accum_streams[(i-1)%2]; + accum_output = accum_streams[i%2]; + err = clSetKernelArg(kernel[0], 0, sizeof accum_input, &accum_input); + err |= clSetKernelArg(kernel[0], 1, sizeof accum_output, &accum_output); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + err = clEnqueueNDRangeKernel( queue, kernel[0], 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + size_t origin[3] = {0, 0, 0}, region[3] = {img_width, img_height, 1}; + err = clEnqueueReadImage(queue, accum_output, CL_TRUE, + origin, region, 0, 0, + (void *)output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clReadImage failed\n"); + return -1; + } + err = verify_byte_image(expected_output, output_ptr, img_width, img_height, 4); + if (err) + { + log_error("IMAGE_MULTIPASS test failed.\n"); + } + else + { + log_info("IMAGE_MULTIPASS test passed\n"); + } + } + + clReleaseSampler(sampler); + } + + + // cleanup + clReleaseMemObject(accum_streams[0]); + clReleaseMemObject(accum_streams[1]); + { + int i; + for (i = 0; i < num_input_streams; i++) + { + clReleaseMemObject(input_streams[i]); + } + } + free(input_streams); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + free(expected_output); + free(output_ptr); + + return err; +} + +int +test_image_multipass_float_coord(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + int img_width = 512; + int img_height = 512; + cl_image_format img_format; + + int num_input_streams = 8; + cl_mem *input_streams; + cl_mem accum_streams[2]; + unsigned char *expected_output; + unsigned char *output_ptr; + cl_kernel kernel[2]; + int err; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + + output_ptr = (unsigned char*)malloc(sizeof(unsigned char) * 4 * img_width * img_height); + + // Create the accum images with initial data. + { + unsigned char *initial_data; + cl_mem_flags flags; + + initial_data = generate_initial_byte_image(img_width, img_height, 4, 0xF0); + flags = (cl_mem_flags)(CL_MEM_READ_WRITE); + + accum_streams[0] = create_image_2d(context, flags, &img_format, img_width, img_height, 0, NULL, NULL); + if (!accum_streams[0]) + { + log_error("create_image_2d failed\n"); + return -1; + } + + size_t origin[3] = {0, 0, 0}, region[3] = {img_width, img_height, 1}; + err = clEnqueueWriteImage(queue, accum_streams[0], CL_TRUE, + origin, region, 0, 0, + initial_data, 0, NULL, NULL); + if (err) + { + log_error("clWriteImage failed: %d\n", err); + return -1; + } + + accum_streams[1] = create_image_2d(context, flags, &img_format, img_width, img_height, 0, NULL, NULL); + if (!accum_streams[1]) + { + log_error("create_image_2d failed\n"); + return -1; + } + err = clEnqueueWriteImage(queue, accum_streams[1], CL_TRUE, + origin, region, 0, 0, + initial_data, 0, NULL, NULL); + if (err) + { + log_error("clWriteImage failed: %d\n", err); + return -1; + } + + free(initial_data); + } + + // Set up the input data. + { + cl_mem_flags flags; + unsigned char **input_data = (unsigned char **)malloc(sizeof(unsigned char*) * num_input_streams); + MTdata d; + + input_streams = (cl_mem*)malloc(sizeof(cl_mem) * num_input_streams); + flags = (cl_mem_flags)(CL_MEM_READ_WRITE); + + int i; + d = init_genrand( gRandomSeed ); + for ( i = 0; i < num_input_streams; i++) + { + input_data[i] = generate_byte_image(img_width, img_height, 4, d); + input_streams[i] = create_image_2d(context, flags, &img_format, img_width, img_height, 0, NULL, NULL); + if (!input_streams[i]) + { + log_error("create_image_2d failed\n"); + free(input_data); + free(input_streams); + return -1; + } + + size_t origin[3] = {0, 0, 0}, region[3] = {img_width, img_height, 1}; + err = clEnqueueWriteImage(queue, input_streams[i], CL_TRUE, + origin, region, 0, 0, + input_data[i], 0, NULL, NULL); + if (err) + { + log_error("clWriteImage failed: %d\n", err); + free(input_data); + free(input_streams); + return -1; + } + } + free_mtdata(d); d = NULL; + expected_output = generate_expected_byte_image(input_data, num_input_streams, img_width, img_height, 4); + for ( i = 0; i < num_input_streams; i++) + { + free(input_data[i]); + } + free(input_data); + } + + // Set up the kernels. + { + cl_program program[2]; + + err = create_single_kernel_helper(context, &program[0], &kernel[0], 1, &image_to_image_kernel_float_coord_code, "image_to_image_copy"); + if (err) + { + log_error("Failed to create kernel 2: %d\n", err); + return -1; + } + err = create_single_kernel_helper(context, &program[1], &kernel[1], 1, &image_sum_kernel_float_coord_code, "image_sum"); + if (err) + { + log_error("Failed to create kernel 3: %d\n", err); + return -1; + } + + clReleaseProgram(program[0]); + clReleaseProgram(program[1]); + } + + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_CLAMP_TO_EDGE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + cl_sampler sampler = clCreateSamplerWithProperties(context, properties, &err); + test_error(err, "clCreateSamplerWithProperties failed"); + + { + size_t threads[3] = {0, 0, 0}; + threads[0] = (size_t)img_width; + threads[1] = (size_t)img_height; + int i; + + { + cl_mem accum_input; + cl_mem accum_output; + + err = clSetKernelArg(kernel[0], 0, sizeof input_streams[0], &input_streams[0]); + err |= clSetKernelArg(kernel[0], 1, sizeof accum_streams[0], &accum_streams[0]); + err |= clSetKernelArg(kernel[0], 2, sizeof sampler, &sampler); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + err = clEnqueueNDRangeKernel( queue, kernel[0], 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + for (i = 1; i < num_input_streams; i++) + { + accum_input = accum_streams[(i-1)%2]; + accum_output = accum_streams[i%2]; + + err = clSetKernelArg(kernel[1], 0, sizeof accum_input, &accum_input); + err |= clSetKernelArg(kernel[1], 1, sizeof input_streams[i], &input_streams[i]); + err |= clSetKernelArg(kernel[1], 2, sizeof accum_output, &accum_output); + err |= clSetKernelArg(kernel[1], 3, sizeof sampler, &sampler); + + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + err = clEnqueueNDRangeKernel( queue, kernel[1], 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + } + + // Copy the last accum into the other one. + accum_input = accum_streams[(i-1)%2]; + accum_output = accum_streams[i%2]; + err = clSetKernelArg(kernel[0], 0, sizeof accum_input, &accum_input); + err |= clSetKernelArg(kernel[0], 1, sizeof accum_output, &accum_output); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + err = clEnqueueNDRangeKernel( queue, kernel[0], 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + size_t origin[3] = {0, 0, 0}, region[3] = {img_width, img_height, 1}; + err = clEnqueueReadImage(queue, accum_output, CL_TRUE, + origin, region, 0, 0, + (void *)output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clReadImage failed\n"); + return -1; + } + err = verify_byte_image(expected_output, output_ptr, img_width, img_height, 4); + if (err) + { + log_error("IMAGE_MULTIPASS test failed.\n"); + } + else + { + log_info("IMAGE_MULTIPASS test passed\n"); + } + } + + } + + + // cleanup + clReleaseSampler(sampler); + clReleaseMemObject(accum_streams[0]); + clReleaseMemObject(accum_streams[1]); + { + int i; + for (i = 0; i < num_input_streams; i++) + { + clReleaseMemObject(input_streams[i]); + } + } + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + free(expected_output); + free(output_ptr); + free(input_streams); + + return err; +} + + + + + diff --git a/test_conformance/basic/test_image_param.c b/test_conformance/basic/test_image_param.c new file mode 100644 index 00000000..e9e99fea --- /dev/null +++ b/test_conformance/basic/test_image_param.c @@ -0,0 +1,290 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/imageHelpers.h" +#include "../../test_common/harness/conversions.h" + + +static const char *param_kernel[] = { +"__kernel void test_fn(read_only image2d_t srcimg, sampler_t sampler, __global float4 *results )\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" results[ tid_y * get_image_width( srcimg ) + tid_x ] = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y));\n" +"\n" +"}\n" }; + +int validate_results( size_t width, size_t height, cl_image_format &format, char *inputData, cl_float *actualResults ) +{ + for( size_t i = 0; i < width * height; i++ ) + { + cl_float expected[ 4 ], tolerance; + + switch( format.image_channel_data_type ) + { + case CL_UNORM_INT8: + { + cl_uchar *p = (cl_uchar *)inputData; + expected[ 0 ] = p[ 0 ] / 255.f; + expected[ 1 ] = p[ 1 ] / 255.f; + expected[ 2 ] = p[ 2 ] / 255.f; + expected[ 3 ] = p[ 3 ] / 255.f; + tolerance = 1.f / 255.f; + break; + } + case CL_SNORM_INT8: + { + cl_char *p = (cl_char *)inputData; + expected[ 0 ] = fmaxf( p[ 0 ] / 127.f, -1.f ); + expected[ 1 ] = fmaxf( p[ 1 ] / 127.f, -1.f ); + expected[ 2 ] = fmaxf( p[ 2 ] / 127.f, -1.f ); + expected[ 3 ] = fmaxf( p[ 3 ] / 127.f, -1.f ); + tolerance = 1.f / 127.f; + break; + } + case CL_UNSIGNED_INT8: + { + cl_uchar *p = (cl_uchar *)inputData; + expected[ 0 ] = p[ 0 ]; + expected[ 1 ] = p[ 1 ]; + expected[ 2 ] = p[ 2 ]; + expected[ 3 ] = p[ 3 ]; + tolerance = 1.f / 127.f; + break; + } + case CL_SIGNED_INT8: + { + cl_short *p = (cl_short *)inputData; + expected[ 0 ] = p[ 0 ]; + expected[ 1 ] = p[ 1 ]; + expected[ 2 ] = p[ 2 ]; + expected[ 3 ] = p[ 3 ]; + tolerance = 1.f / 127.f; + break; + } + case CL_UNORM_INT16: + { + cl_ushort *p = (cl_ushort *)inputData; + expected[ 0 ] = p[ 0 ] / 65535.f; + expected[ 1 ] = p[ 1 ] / 65535.f; + expected[ 2 ] = p[ 2 ] / 65535.f; + expected[ 3 ] = p[ 3 ] / 65535.f; + tolerance = 1.f / 65535.f; + break; + } + case CL_UNSIGNED_INT32: + { + cl_uint *p = (cl_uint *)inputData; + expected[ 0 ] = p[ 0 ]; + expected[ 1 ] = p[ 1 ]; + expected[ 2 ] = p[ 2 ]; + expected[ 3 ] = p[ 3 ]; + tolerance = 0.0001f; + break; + } + case CL_FLOAT: + { + cl_float *p = (cl_float *)inputData; + expected[ 0 ] = p[ 0 ]; + expected[ 1 ] = p[ 1 ]; + expected[ 2 ] = p[ 2 ]; + expected[ 3 ] = p[ 3 ]; + tolerance = 0.0001f; + break; + } + default: + // Should never get here + break; + } + + if( format.image_channel_order == CL_BGRA ) + { + cl_float tmp = expected[ 0 ]; + expected[ 0 ] = expected[ 2 ]; + expected[ 2 ] = tmp; + } + + // Within an error tolerance, make sure the results match + cl_float error1 = fabsf( expected[ 0 ] - actualResults[ 0 ] ); + cl_float error2 = fabsf( expected[ 1 ] - actualResults[ 1 ] ); + cl_float error3 = fabsf( expected[ 2 ] - actualResults[ 2 ] ); + cl_float error4 = fabsf( expected[ 3 ] - actualResults[ 3 ] ); + + if( error1 > tolerance || error2 > tolerance || error3 > tolerance || error4 > tolerance ) + { + log_error( "ERROR: Sample %d did not validate against expected results for %d x %d %s:%s image\n", (int)i, (int)width, (int)height, + GetChannelOrderName( format.image_channel_order ), GetChannelTypeName( format.image_channel_data_type ) ); + log_error( " Expected: %f %f %f %f\n", (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ] ); + log_error( " Actual: %f %f %f %f\n", (float)actualResults[ 0 ], (float)actualResults[ 1 ], (float)actualResults[ 2 ], (float)actualResults[ 3 ] ); + + // Check real quick a special case error here + cl_float error1 = fabsf( expected[ 3 ] - actualResults[ 0 ] ); + cl_float error2 = fabsf( expected[ 2 ] - actualResults[ 1 ] ); + cl_float error3 = fabsf( expected[ 1 ] - actualResults[ 2 ] ); + cl_float error4 = fabsf( expected[ 0 ] - actualResults[ 3 ] ); + if( error1 <= tolerance && error2 <= tolerance && error3 <= tolerance && error4 <= tolerance ) + { + log_error( "\t(Kernel did not respect change in channel order)\n" ); + } + return -1; + } + + // Increment and go + actualResults += 4; + inputData += get_format_type_size( &format ) * 4; + } + + return 0; +} + +int test_image_param(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + size_t sizes[] = { 64, 100, 128, 250, 512 }; + cl_image_format formats[] = { { CL_RGBA, CL_UNORM_INT8 }, { CL_RGBA, CL_UNORM_INT16 }, { CL_RGBA, CL_FLOAT }, { CL_BGRA, CL_UNORM_INT8 } }; + cl_image_format *supported_formats; + ExplicitType types[] = { kUChar, kUShort, kFloat, kUChar }; + int error; + size_t i, j, idx; + size_t threads[ 2 ]; + MTdata d; + int supportsBGRA = 0; + cl_uint numSupportedFormats = 0; + + const size_t numSizes = sizeof( sizes ) / sizeof( sizes[ 0 ] ); + const size_t numFormats = sizeof( formats ) / sizeof( formats[ 0 ] ); + const size_t numAttempts = numSizes * numFormats; + + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ numAttempts ][ 2 ]; + BufferOwningPtr inputs[ numAttempts ]; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + if(gIsEmbedded) + { + /* Get the supported image formats to see if BGRA is supported */ + clGetSupportedImageFormats (context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE2D, 0, NULL, &numSupportedFormats); + supported_formats = (cl_image_format *) malloc(sizeof(cl_image_format) * numSupportedFormats); + clGetSupportedImageFormats (context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE2D, numFormats, supported_formats, NULL); + + for(i = 0; i < numSupportedFormats; i++) + { + if(supported_formats[i].image_channel_order == CL_BGRA) + { + supportsBGRA = 1; + break; + } + } + } + else + { + supportsBGRA = 1; + } + + d = init_genrand( gRandomSeed ); + for( i = 0, idx = 0; i < numSizes; i++ ) + { + for( j = 0; j < numFormats; j++, idx++ ) + { + if(formats[j].image_channel_order == CL_BGRA && !supportsBGRA) + continue; + + // For each attempt, we create a pair: an input image, whose parameters keep changing, and an output buffer + // that we can read values from. The output buffer will remain consistent to ensure that any changes we + // witness are due to the image changes + inputs[ idx ].reset(create_random_data( types[ j ], d, sizes[ i ] * sizes[ i ] * 4 )); + + streams[ idx ][ 0 ] = create_image_2d( context, CL_MEM_COPY_HOST_PTR, &formats[ j ], sizes[ i ], sizes[ i ], 0, inputs[ idx ], &error ); + { + char err_str[256]; + sprintf(err_str, "Unable to create input image for format %s order %s" , + GetChannelOrderName( formats[j].image_channel_order ), + GetChannelTypeName( formats[j].image_channel_data_type )); + test_error( error, err_str); + } + + streams[ idx ][ 1 ] = clCreateBuffer( context, CL_MEM_READ_WRITE, sizes[ i ] * sizes[ i ] * 4 * sizeof( cl_float ), NULL, &error ); + test_error( error, "Unable to create output buffer" ); + } + } + free_mtdata(d); d = NULL; + + // Create a single kernel to use for all the tests + error = create_single_kernel_helper( context, &program, &kernel, 1, param_kernel, "test_fn" ); + test_error( error, "Unable to create testing kernel" ); + + // Also create a sampler to use for all the runs + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_CLAMP_TO_EDGE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + clSamplerWrapper sampler = clCreateSamplerWithProperties(context, properties, &error); + test_error(error, "clCreateSamplerWithProperties failed"); + + // Set up the arguments for each and queue + for( i = 0, idx = 0; i < numSizes; i++ ) + { + for( j = 0; j < numFormats; j++, idx++ ) + { + if(formats[j].image_channel_order == CL_BGRA && !supportsBGRA) + continue; + + error = clSetKernelArg( kernel, 0, sizeof( streams[ idx ][ 0 ] ), &streams[ idx ][ 0 ] ); + error |= clSetKernelArg( kernel, 1, sizeof( sampler ), &sampler ); + error |= clSetKernelArg( kernel, 2, sizeof( streams[ idx ][ 1 ] ), &streams[ idx ][ 1 ]); + test_error( error, "Unable to set kernel arguments" ); + + threads[ 0 ] = threads[ 1 ] = (size_t)sizes[ i ]; + + error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "clEnqueueNDRangeKernel failed" ); + } + } + + // Now go through each combo and validate the results + for( i = 0, idx = 0; i < numSizes; i++ ) + { + for( j = 0; j < numFormats; j++, idx++ ) + { + if(formats[j].image_channel_order == CL_BGRA && !supportsBGRA) + continue; + + BufferOwningPtr output(malloc(sizeof(cl_float) * sizes[ i ] * sizes[ i ] * 4 )); + + error = clEnqueueReadBuffer( queue, streams[ idx ][ 1 ], CL_TRUE, 0, sizes[ i ] * sizes[ i ] * 4 * sizeof( cl_float ), output, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + error = validate_results( sizes[ i ], sizes[ i ], formats[ j ], inputs[ idx ], output ); + if( error ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/basic/test_image_r8.c b/test_conformance/basic/test_image_r8.c new file mode 100644 index 00000000..02bb8483 --- /dev/null +++ b/test_conformance/basic/test_image_r8.c @@ -0,0 +1,183 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +static const char *r_uint8_kernel_code = +"__kernel void test_r_uint8(read_only image2d_t srcimg, __global unsigned char *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(srcimg) + tid_x;\n" +" uint4 color;\n" +"\n" +" color = read_imageui(srcimg, sampler, (int2)(tid_x, tid_y));\n" +" dst[indx] = (unsigned char)(color.x);\n" +"\n" +"}\n"; + + +static unsigned char * +generate_8bit_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * sizeof(unsigned char)); + int i; + + for (i=0; i +#include +#include +#include +#include + +#include "procs.h" + +int test_imagearraycopy_single_format(cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format) +{ + cl_uchar *imgptr, *bufptr; + clMemWrapper image, buffer; + int img_width = 512; + int img_height = 512; + size_t elem_size; + size_t buffer_size; + int i; + cl_int err; + MTdata d; + cl_event copyevent; + + log_info("Testing %s %s\n", GetChannelOrderName(format->image_channel_order), GetChannelTypeName(format->image_channel_data_type)); + + image = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), format, img_width, img_height, 0, NULL, &err); + test_error(err, "create_image_2d failed"); + + err = clGetImageInfo(image, CL_IMAGE_ELEMENT_SIZE, sizeof(size_t), &elem_size, NULL); + test_error(err, "clGetImageInfo failed"); + + buffer_size = sizeof(cl_uchar) * elem_size * img_width * img_height; + + buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), buffer_size, NULL, &err); + test_error(err, "clCreateBuffer failed"); + + d = init_genrand( gRandomSeed ); + imgptr = (cl_uchar*)malloc(buffer_size); + for (i=0; i<(int)buffer_size; i++) { + imgptr[i] = (cl_uchar)genrand_int32(d); + } + free_mtdata(d); d = NULL; + + size_t origin[3]={0,0,0}, region[3]={img_width,img_height,1}; + err = clEnqueueWriteImage( queue, image, CL_TRUE, origin, region, 0, 0, imgptr, 0, NULL, NULL ); + test_error(err, "clEnqueueWriteBuffer failed"); + + err = clEnqueueCopyImageToBuffer( queue, image, buffer, origin, region, 0, 0, NULL, ©event ); + test_error(err, "clEnqueueCopyImageToBuffer failed"); + + bufptr = (cl_uchar*)malloc(buffer_size); + + err = clEnqueueReadBuffer( queue, buffer, CL_TRUE, 0, buffer_size, bufptr, 1, ©event, NULL); + test_error(err, "clEnqueueReadBuffer failed"); + + err = clReleaseEvent(copyevent); + test_error(err, "clReleaseEvent failed"); + + if (memcmp(imgptr, bufptr, buffer_size) != 0) { + log_error( "ERROR: Results did not validate!\n" ); + unsigned char * inchar = (unsigned char*)imgptr; + unsigned char * outchar = (unsigned char*)bufptr; + int failuresPrinted = 0; + int i; + for (i=0; i< (int)buffer_size; i+=(int)elem_size) { + int failed = 0; + int j; + for (j=0; j<(int)elem_size; j++) + if (inchar[i+j] != outchar[i+j]) + failed = 1; + char values[4096]; + values[0] = 0; + if (failed) { + sprintf(values + strlen(values), "%d(0x%x) -> actual [", i, i); + int j; + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", inchar[i+j]); + sprintf(values + strlen(values), "] != expected ["); + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", outchar[i+j]); + sprintf(values + strlen(values), "]"); + log_error("%s\n", values); + failuresPrinted++; + } + if (failuresPrinted > 5) { + log_error("Not printing further failures...\n"); + break; + } + } + err = -1; + } + + free(imgptr); + free(bufptr); + + if (err) + log_error("IMAGE to ARRAY copy test failed for image_channel_order=0x%lx and image_channel_data_type=0x%lx\n", + (unsigned long)format->image_channel_order, (unsigned long)format->image_channel_data_type); + + return err; +} + +int test_imagearraycopy(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int err; + cl_image_format *formats; + cl_uint num_formats; + cl_uint i; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE2D, 0, NULL, &num_formats); + test_error(err, "clGetSupportedImageFormats failed"); + + formats = (cl_image_format *)malloc(num_formats * sizeof(cl_image_format)); + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE2D, num_formats, formats, NULL); + test_error(err, "clGetSupportedImageFormats failed"); + + for (i = 0; i < num_formats; i++) { + err |= test_imagearraycopy_single_format(device, context, queue, &formats[i]); + } + + free(formats); + if (err) + log_error("IMAGE to ARRAY copy test failed\n"); + else + log_info("IMAGE to ARRAY copy test passed\n"); + + return err; +} diff --git a/test_conformance/basic/test_imagearraycopy3d.c b/test_conformance/basic/test_imagearraycopy3d.c new file mode 100644 index 00000000..9bb595a1 --- /dev/null +++ b/test_conformance/basic/test_imagearraycopy3d.c @@ -0,0 +1,143 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" + +int test_imagearraycopy3d_single_format(cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format) +{ + cl_uchar *imgptr, *bufptr; + clMemWrapper image, buffer; + int img_width = 128; + int img_height = 128; + int img_depth = 32; + size_t elem_size; + size_t buffer_size; + int i; + cl_int err; + MTdata d; + + log_info("Testing %s %s\n", GetChannelOrderName(format->image_channel_order), GetChannelTypeName(format->image_channel_data_type)); + + image = create_image_3d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), format, img_width, img_height, img_depth, 0, 0, NULL, &err); + test_error(err, "create_image_3d failed"); + + err = clGetImageInfo(image, CL_IMAGE_ELEMENT_SIZE, sizeof(size_t), &elem_size, NULL); + test_error(err, "clGetImageInfo failed"); + + buffer_size = sizeof(cl_uchar) * elem_size * img_width * img_height * img_depth; + + buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), buffer_size, NULL, &err); + test_error(err, "clCreateBuffer failed"); + + d = init_genrand( gRandomSeed ); + imgptr = (cl_uchar*)malloc(buffer_size); + for (i=0; i<(int)buffer_size; i++) { + imgptr[i] = (cl_uchar)genrand_int32(d); + } + free_mtdata(d); d = NULL; + + size_t origin[3]={0,0,0}, region[3]={img_width,img_height,img_depth}; + err = clEnqueueWriteImage( queue, image, CL_TRUE, origin, region, 0, 0, imgptr, 0, NULL, NULL ); + test_error(err, "clEnqueueWriteBuffer failed"); + + err = clEnqueueCopyImageToBuffer( queue, image, buffer, origin, region, 0, 0, NULL, NULL ); + test_error(err, "clEnqueueCopyImageToBuffer failed"); + + bufptr = (cl_uchar*)malloc(buffer_size); + + err = clEnqueueReadBuffer( queue, buffer, CL_TRUE, 0, buffer_size, bufptr, 0, NULL, NULL); + test_error(err, "clEnqueueReadBuffer failed"); + + if (memcmp(imgptr, bufptr, buffer_size) != 0) { + log_error( "ERROR: Results did not validate!\n" ); + unsigned char * inchar = (unsigned char*)imgptr; + unsigned char * outchar = (unsigned char*)bufptr; + int failuresPrinted = 0; + int i; + for (i=0; i< (int)buffer_size; i+=(int)elem_size) { + int failed = 0; + int j; + for (j=0; j<(int)elem_size; j++) + if (inchar[i+j] != outchar[i+j]) + failed = 1; + char values[4096]; + values[0] = 0; + if (failed) { + sprintf(values + strlen(values), "%d(0x%x) -> actual [", i, i); + int j; + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", inchar[i+j]); + sprintf(values + strlen(values), "] != expected ["); + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", outchar[i+j]); + sprintf(values + strlen(values), "]"); + log_error("%s\n", values); + failuresPrinted++; + } + if (failuresPrinted > 5) { + log_error("Not printing further failures...\n"); + break; + } + } + err = -1; + } + + free(imgptr); + free(bufptr); + + if (err) + log_error("IMAGE3D to ARRAY copy test failed for image_channel_order=0x%lx and image_channel_data_type=0x%lx\n", + (unsigned long)format->image_channel_order, (unsigned long)format->image_channel_data_type); + + return err; +} + +int test_imagearraycopy3d(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int err; + cl_image_format *formats; + cl_uint num_formats; + cl_uint i; + + PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( device ) + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE3D, 0, NULL, &num_formats); + test_error(err, "clGetSupportedImageFormats failed"); + + formats = (cl_image_format *)malloc(num_formats * sizeof(cl_image_format)); + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE3D, num_formats, formats, NULL); + test_error(err, "clGetSupportedImageFormats failed"); + + for (i = 0; i < num_formats; i++) { + err |= test_imagearraycopy3d_single_format(device, context, queue, &formats[i]); + } + + free(formats); + if (err) + log_error("IMAGE3D to ARRAY copy test failed\n"); + else + log_info("IMAGE3D to ARRAY copy test passed\n"); + + return err; +} diff --git a/test_conformance/basic/test_imagecopy.c b/test_conformance/basic/test_imagecopy.c new file mode 100644 index 00000000..258fe033 --- /dev/null +++ b/test_conformance/basic/test_imagecopy.c @@ -0,0 +1,235 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +static unsigned char * +generate_rgba8_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +static unsigned char * +generate_uint8_image(unsigned num_elements, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(num_elements); + unsigned i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +static const char *image_dim_kernel_code = +"\n" +"__kernel void test_image_dim(read_only image2d_t srcimg, write_only image2d_t dstimg, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y));\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + + +static unsigned char * +generate_8888_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i (cl_ulong)SIZE_MAX) { + max_mem_size = (cl_ulong)SIZE_MAX; + } + + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_CLAMP_TO_EDGE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + cl_sampler sampler = clCreateSamplerWithProperties(context, properties, &err); + test_error(err, "clCreateSamplerWithProperties failed"); + + max_img_width = (int)max_image2d_width; + max_img_height = (int)max_image2d_height; + + // determine max image dim we can allocate - assume RGBA image, 4 bytes per pixel, + // and we want to consume 1/4 of global memory (this is the minimum required to be + // supported by the spec) + max_mem_size /= 4; // use 1/4 + max_mem_size /= 4; // 4 bytes per pixel + max_img_dim = (int)sqrt((double)max_mem_size); + // convert to a power of 2 + { + unsigned int n = (unsigned int)max_img_dim; + unsigned int m = 0x80000000; + + // round-down to the nearest power of 2 + while (m > n) + m >>= 1; + + max_img_dim = (int)m; + } + + if (max_img_width > max_img_dim) + max_img_width = max_img_dim; + if (max_img_height > max_img_dim) + max_img_height = max_img_dim; + + log_info("Adjusted maximum image size to test is %d x %d, which is a max mem size of %gMB.\n", + max_img_width, max_img_height, (max_img_width*max_img_height*4)/(1024.0*1024.0)); + + d = init_genrand( gRandomSeed ); + input_ptr = generate_8888_image(max_img_width, max_img_height, d); + output_ptr = (unsigned char*)malloc(sizeof(unsigned char) * 4 * max_img_width * max_img_height); + + // test power of 2 width, height starting at 1 to 4K + for (i=1,i2=0; i<=max_img_height; i<<=1,i2++) + { + img_height = (1 << i2); + for (j=1,j2=0; j<=max_img_width; j<<=1,j2++) + { + img_width = (1 << j2); + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + streams[0] = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[0]) + { + log_error("create_image_2d failed. width = %d, height = %d\n", img_width, img_height); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + streams[1] = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[1]) + { + log_error("create_image_2d failed. width = %d, height = %d\n", img_width, img_height); + clReleaseMemObject(streams[0]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + + size_t origin[3] = {0,0,0}; + size_t region[3] = {img_width, img_height, 1}; + err = clEnqueueWriteImage(queue, streams[0], CL_FALSE, origin, region, 0, 0, input_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clWriteImage failed\n"); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + + err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]); + err |= clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]); + err |= clSetKernelArg(kernel, 2, sizeof sampler, &sampler); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + + threads[0] = (size_t)img_width; + threads[1] = (size_t)img_height; + log_info("Testing image dimensions %d x %d with local threads NULL.\n", img_width, img_height); + err = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + log_error("Image Dimension test failed. image width = %d, image height = %d, local NULL\n", + img_width, img_height); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + err = clEnqueueReadImage(queue, streams[1], CL_TRUE, origin, region, 0, 0, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clReadImage failed\n"); + log_error("Image Dimension test failed. image width = %d, image height = %d, local NULL\n", + img_width, img_height); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + err = verify_8888_image(input_ptr, output_ptr, img_width, img_height); + if (err) + { + total_errors++; + log_error("Image Dimension test failed. image width = %d, image height = %d\n", img_width, img_height); + } + + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + } + } + + // cleanup + free(input_ptr); + free(output_ptr); + free_mtdata(d); + clReleaseSampler(sampler); + clReleaseKernel(kernel); + clReleaseProgram(program); + + return total_errors; +} + + + +int +test_imagedim_non_pow2(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[2]; + cl_image_format img_format; + unsigned char *input_ptr, *output_ptr; + cl_program program; + cl_kernel kernel; + size_t threads[2], local_threads[2]; + cl_ulong max_mem_size; + int img_width, max_img_width; + int img_height, max_img_height; + int max_img_dim; + int i, j, i2, j2, err=0; + size_t max_image2d_width, max_image2d_height; + int total_errors = 0; + size_t max_local_workgroup_size[3]; + MTdata d; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + err = create_single_kernel_helper( context, &program, &kernel, 1, &image_dim_kernel_code, "test_image_dim" ); + if (err) + { + log_error("create_program_and_kernel_with_sources failed\n"); + return -1; + } + + size_t work_group_size = 0; + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(work_group_size), &work_group_size, NULL); + test_error(err, "clGetKerenlWorkgroupInfo failed for CL_KERNEL_WORK_GROUP_SIZE"); + + err = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(max_local_workgroup_size), max_local_workgroup_size, NULL); + test_error(err, "clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_SIZES"); + + err = clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE,sizeof(max_mem_size), &max_mem_size, NULL); + if (err) + { + log_error("clGetDeviceInfo for CL_DEVICE_GLOBAL_MEM_SIZE failed (%d)\n", err); + return -1; + } + err = clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(max_image2d_width), &max_image2d_width, NULL); + if (err) + { + log_error("clGetDeviceInfo for CL_DEVICE_IMAGE2D_MAX_WIDTH failed (%d)\n", err); + return -1; + } + err = clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(max_image2d_width), &max_image2d_height, NULL); + if (err) + { + log_error("clGetDeviceInfo for CL_DEVICE_IMAGE2D_MAX_HEIGHT failed (%d)\n", err); + return -1; + } + log_info("Device reported max image sizes of %lu x %lu, and max mem size of %gMB.\n", + max_image2d_width, max_image2d_height, max_mem_size/(1024.0*1024.0)); + + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_CLAMP_TO_EDGE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + cl_sampler sampler = clCreateSamplerWithProperties(context, properties, &err); + test_error(err, "clCreateSamplerWithProperties failed"); + + max_img_width = (int)max_image2d_width; + max_img_height = (int)max_image2d_height; + + if (max_mem_size > (cl_ulong)SIZE_MAX) { + max_mem_size = (cl_ulong)SIZE_MAX; + } + + // determine max image dim we can allocate - assume RGBA image, 4 bytes per pixel, + // and we want to consume 1/4 of global memory (this is the minimum required to be + // supported by the spec) + max_mem_size /= 4; // use 1/4 + max_mem_size /= 4; // 4 bytes per pixel + max_img_dim = (int)sqrt((double)max_mem_size); + // convert to a power of 2 + { + unsigned int n = (unsigned int)max_img_dim; + unsigned int m = 0x80000000; + + // round-down to the nearest power of 2 + while (m > n) + m >>= 1; + + max_img_dim = (int)m; + } + + if (max_img_width > max_img_dim) + max_img_width = max_img_dim; + if (max_img_height > max_img_dim) + max_img_height = max_img_dim; + + log_info("Adjusted maximum image size to test is %d x %d, which is a max mem size of %gMB.\n", + max_img_width, max_img_height, (max_img_width*max_img_height*4)/(1024.0*1024.0)); + + d = init_genrand( gRandomSeed ); + input_ptr = generate_8888_image(max_img_width, max_img_height, d); + output_ptr = (unsigned char*)malloc(sizeof(unsigned char) * 4 * max_img_width * max_img_height); + + int plus_minus; + for (plus_minus=0; plus_minus < 3; plus_minus++) + { + + // test power of 2 width, height starting at 1 to 4K + for (i=2,i2=1; i<=max_img_height; i<<=1,i2++) + { + img_height = (1 << i2); + for (j=2,j2=1; j<=max_img_width; j<<=1,j2++) + { + img_width = (1 << j2); + + int effective_img_height = img_height; + int effective_img_width = img_width; + + local_threads[0] = 1; + local_threads[1] = 1; + + switch (plus_minus) { + case 0: + effective_img_height--; + local_threads[0] = work_group_size > max_local_workgroup_size[0] ? max_local_workgroup_size[0] : work_group_size; + while (img_width%local_threads[0] != 0) + local_threads[0]--; + break; + case 1: + effective_img_width--; + local_threads[1] = work_group_size > max_local_workgroup_size[1] ? max_local_workgroup_size[1] : work_group_size; + while (img_height%local_threads[1] != 0) + local_threads[1]--; + break; + case 2: + effective_img_width--; + effective_img_height--; + break; + default: + break; + } + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + streams[0] = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), &img_format, effective_img_width, effective_img_height, 0, NULL, NULL); + if (!streams[0]) + { + log_error("create_image_2d failed. width = %d, height = %d\n", effective_img_width, effective_img_height); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + streams[1] = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), &img_format, effective_img_width, effective_img_height, 0, NULL, NULL); + if (!streams[1]) + { + log_error("create_image_2d failed. width = %d, height = %d\n", effective_img_width, effective_img_height); + clReleaseMemObject(streams[0]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + + size_t origin[3] = {0,0,0}; + size_t region[3] = {effective_img_width, effective_img_height, 1}; + err = clEnqueueWriteImage(queue, streams[0], CL_FALSE, origin, region, 0, 0, input_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clWriteImage failed\n"); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + + err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]); + err |= clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]); + err |= clSetKernelArg(kernel, 2, sizeof sampler, &sampler); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + + threads[0] = (size_t)effective_img_width; + threads[1] = (size_t)effective_img_height; + log_info("Testing image dimensions %d x %d with local threads %d x %d.\n", + effective_img_width, effective_img_height, (int)local_threads[0], (int)local_threads[1]); + err = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, local_threads, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + log_error("Image Dimension test failed. image width = %d, image height = %d, local %d x %d\n", + effective_img_width, effective_img_height, (int)local_threads[0], (int)local_threads[1]); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + err = clEnqueueReadImage(queue, streams[1], CL_TRUE, origin, region, 0, 0, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clReadImage failed\n"); + log_error("Image Dimension test failed. image width = %d, image height = %d, local %d x %d\n", + effective_img_width, effective_img_height, (int)local_threads[0], (int)local_threads[1]); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + err = verify_8888_image(input_ptr, output_ptr, effective_img_width, effective_img_height); + if (err) + { + total_errors++; + log_error("Image Dimension test failed. image width = %d, image height = %d\n", effective_img_width, effective_img_height); + } + + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + } + } + + } + + // cleanup + free(input_ptr); + free(output_ptr); + free_mtdata(d); + clReleaseSampler(sampler); + clReleaseKernel(kernel); + clReleaseProgram(program); + + return total_errors; +} + + + + diff --git a/test_conformance/basic/test_imagenpot.c b/test_conformance/basic/test_imagenpot.c new file mode 100644 index 00000000..2682f626 --- /dev/null +++ b/test_conformance/basic/test_imagenpot.c @@ -0,0 +1,226 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +static const char *rgba8888_kernel_code = +"\n" +"__kernel void test_rgba8888(read_only image2d_t srcimg, write_only image2d_t dstimg, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 color;\n" +"\n" +" if ( (tid_x >= get_image_width(dstimg)) || (tid_y >= get_image_height(dstimg)) )\n" +" return;\n" +" color = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y));\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + + +static unsigned char * +generate_8888_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i max_local_workgroup_size[0]) + local_workgroup_size = max_local_workgroup_size[0]; + + global_threads[0] = ((img_width + local_workgroup_size - 1) / local_workgroup_size) * local_workgroup_size; + global_threads[1] = img_height; + local_threads[0] = local_workgroup_size; + local_threads[1] = 1; + err = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, global_threads, local_threads, 0, NULL, NULL ); + + if (err != CL_SUCCESS) + { + log_error("%s clEnqueueNDRangeKernel failed\n", __FUNCTION__); + free_mtdata(d); + return -1; + } + err = clEnqueueReadImage(queue, streams[1], CL_TRUE, + origin, region, 0, 0, + (void *)output_ptr, + 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueReadBuffer failed\n"); + return -1; + } + + err = verify_rgba8888_image(input_ptr, output_ptr, img_width, img_height); + + // cleanup + clReleaseSampler(sampler); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + free(input_ptr); + free(output_ptr); + + if (err) + break; + } + + free_mtdata(d); + + return err; +} + + + + + diff --git a/test_conformance/basic/test_imagerandomcopy.c b/test_conformance/basic/test_imagerandomcopy.c new file mode 100644 index 00000000..1de572f1 --- /dev/null +++ b/test_conformance/basic/test_imagerandomcopy.c @@ -0,0 +1,270 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +static unsigned char * +generate_rgba8_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +static unsigned char * +generate_rgba8_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +static unsigned char * +generate_rgba8_image(int w, int h, int d, MTdata mtData) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * d *4); + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +const char *int2float_kernel_code = +"__kernel void test_int2float(__global int *src, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (float)src[tid];\n" +"\n" +"}\n"; + + +int +verify_int2float(cl_int *inptr, cl_float *outptr, int n) +{ + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +const char *int_add_kernel_code = +"__kernel void test_int_add(__global int *srcA, __global int *srcB, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *int_sub_kernel_code = +"__kernel void test_int_sub(__global int *srcA, __global int *srcB, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *int_mul_kernel_code = +"__kernel void test_int_mul(__global int *srcA, __global int *srcB, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + +const char *int_mad_kernel_code = +"__kernel void test_int_mad(__global int *srcA, __global int *srcB, __global int *srcC, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid] + srcC[tid];\n" +"}\n"; + +static const float MAX_ERR = 1e-5f; + +int +verify_int_add(int *inptrA, int *inptrB, int *outptr, int n) +{ + int r; + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +const char *int_add2_kernel_code = +"__kernel void test_int_add2(__global int2 *srcA, __global int2 *srcB, __global int2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *int_sub2_kernel_code = +"__kernel void test_int_sub2(__global int2 *srcA, __global int2 *srcB, __global int2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *int_mul2_kernel_code = +"__kernel void test_int_mul2(__global int2 *srcA, __global int2 *srcB, __global int2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + +const char *int_mad2_kernel_code = +"__kernel void test_int_mad2(__global int2 *srcA, __global int2 *srcB, __global int2 *srcC, __global int2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid] + srcC[tid];\n" +"}\n"; + +int +verify_int_add2(int *inptrA, int *inptrB, int *outptr, int n) +{ + int r; + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +const char *int_add4_kernel_code = +"__kernel void test_int_add4(__global int4 *srcA, __global int4 *srcB, __global int4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *int_sub4_kernel_code = +"__kernel void test_int_sub4(__global int4 *srcA, __global int4 *srcB, __global int4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *int_mul4_kernel_code = +"__kernel void test_int_mul4(__global int4 *srcA, __global int4 *srcB, __global int4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + +const char *int_mad4_kernel_code = +"__kernel void test_int_mad4(__global int4 *srcA, __global int4 *srcB, __global int4 *srcC, __global int4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid] + srcC[tid];\n" +"}\n"; + +int +verify_int_add4(int *inptrA, int *inptrB, int *outptr, int n) +{ + int r; + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +const char *long_add_kernel_code = +"__kernel void test_long_add(__global long *srcA, __global long *srcB, __global long *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *long_sub_kernel_code = +"__kernel void test_long_sub(__global long *srcA, __global long *srcB, __global long *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *long_mul_kernel_code = +"__kernel void test_long_mul(__global long *srcA, __global long *srcB, __global long *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + +const char *long_mad_kernel_code = +"__kernel void test_long_mad(__global long *srcA, __global long *srcB, __global long *srcC, __global long *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid] + srcC[tid];\n" +"}\n"; + +static const float MAX_ERR = 1e-5f; + +int +verify_long_add(cl_long *inptrA, cl_long *inptrB, cl_long *outptr, int n) +{ + cl_long r; + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +const char *long_add2_kernel_code = +"__kernel void test_long_add2(__global long2 *srcA, __global long2 *srcB, __global long2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *long_sub2_kernel_code = +"__kernel void test_long_sub2(__global long2 *srcA, __global long2 *srcB, __global long2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *long_mul2_kernel_code = +"__kernel void test_long_mul2(__global long2 *srcA, __global long2 *srcB, __global long2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + +const char *long_mad2_kernel_code = +"__kernel void test_long_mad2(__global long2 *srcA, __global long2 *srcB, __global long2 *srcC, __global long2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid] + srcC[tid];\n" +"}\n"; + +int +verify_long_add2(cl_long *inptrA, cl_long *inptrB, cl_long *outptr, int n) +{ + cl_long r; + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +const char *long_add4_kernel_code = +"__kernel void test_long_add4(__global long4 *srcA, __global long4 *srcB, __global long4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *long_sub4_kernel_code = +"__kernel void test_long_sub4(__global long4 *srcA, __global long4 *srcB, __global long4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *long_mul4_kernel_code = +"__kernel void test_long_mul4(__global long4 *srcA, __global long4 *srcB, __global long4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + +const char *long_mad4_kernel_code = +"__kernel void test_long_mad4(__global long4 *srcA, __global long4 *srcB, __global long4 *srcC, __global long4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid] + srcC[tid];\n" +"}\n"; + +int +verify_long_add4(cl_long *inptrA, cl_long *inptrB, cl_long *outptr, int n) +{ + cl_long r; + int i; + + for (i=0; i 10) + continue; + if (errors == 10) { + log_error("Suppressing further results...\n"); + continue; + } + log_error("Results do not match: output[%d]=%d != expected[%d]=%d\n", i, output[i], i, expected[i]); + errors++; + pass = 0; + } + } + if (pass) log_info("Passed kernel calling kernel...\n"); + + + + // Test kernel calling a function + log_info("Testing kernel calling function...\n"); + // Reset the inputs + for (int i=0; i 10) + continue; + if (errors > 10) { + log_error("Suppressing further results...\n"); + continue; + } + log_error("Results do not match: output[%d]=%d != expected[%d]=%d\n", i, output[i], i, expected[i]); + errors++; + pass = 0; + } + } + if (pass) log_info("Passed kernel calling function...\n"); + + + // Test calling the kernel we called from another kernel + log_info("Testing calling the kernel we called from another kernel before...\n"); + // Reset the inputs + for (int i=0; i 10) + continue; + if (errors > 10) { + log_error("Suppressing further results...\n"); + continue; + } + log_error("Results do not match: output[%d]=%d != expected[%d]=%d\n", i, output[i], i, expected[i]); + errors++; + pass = 0; + } + } + if (pass) log_info("Passed calling the kernel we called from another kernel before...\n"); + + free( input ); + free( output ); + free( expected ); + + return errors; +} + + diff --git a/test_conformance/basic/test_kernel_memory_alignment.cpp b/test_conformance/basic/test_kernel_memory_alignment.cpp new file mode 100644 index 00000000..adcfdaa2 --- /dev/null +++ b/test_conformance/basic/test_kernel_memory_alignment.cpp @@ -0,0 +1,570 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _WIN32 +#include +#endif + +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/errorHelpers.h" + +// For global, local, and constant +const char *parameter_kernel_long = +"%s\n" // optional pragma +"kernel void test(global ulong *results, %s %s *mem0, %s %s2 *mem2, %s %s3 *mem3, %s %s4 *mem4, %s %s8 *mem8, %s %s16 *mem16)\n" +"{\n" +" results[0] = (ulong)&mem0[0];\n" +" results[1] = (ulong)&mem2[0];\n" +" results[2] = (ulong)&mem3[0];\n" +" results[3] = (ulong)&mem4[0];\n" +" results[4] = (ulong)&mem8[0];\n" +" results[5] = (ulong)&mem16[0];\n" +"}\n"; + +// For private and local +const char *local_kernel_long = +"%s\n" // optional pragma +"kernel void test(global ulong *results)\n" +"{\n" +" %s %s mem0[3];\n" +" %s %s2 mem2[3];\n" +" %s %s3 mem3[3];\n" +" %s %s4 mem4[3];\n" +" %s %s8 mem8[3];\n" +" %s %s16 mem16[3];\n" +" results[0] = (ulong)&mem0[0];\n" +" results[1] = (ulong)&mem2[0];\n" +" results[2] = (ulong)&mem3[0];\n" +" results[3] = (ulong)&mem4[0];\n" +" results[4] = (ulong)&mem8[0];\n" +" results[5] = (ulong)&mem16[0];\n" +"}\n"; + +// For constant +const char *constant_kernel_long = +"%s\n" // optional pragma +" constant %s mem0[3] = {0};\n" +" constant %s2 mem2[3] = {(%s2)(0)};\n" +" constant %s3 mem3[3] = {(%s3)(0)};\n" +" constant %s4 mem4[3] = {(%s4)(0)};\n" +" constant %s8 mem8[3] = {(%s8)(0)};\n" +" constant %s16 mem16[3] = {(%s16)(0)};\n" +"\n" +"kernel void test(global ulong *results)\n" +"{\n" +" results[0] = (ulong)&mem0;\n" +" results[1] = (ulong)&mem2;\n" +" results[2] = (ulong)&mem3;\n" +" results[3] = (ulong)&mem4;\n" +" results[4] = (ulong)&mem8;\n" +" results[5] = (ulong)&mem16;\n" +"}\n"; + + +// For global, local, and constant +const char *parameter_kernel_no_long = +"%s\n" // optional pragma +"kernel void test(global uint *results, %s %s *mem0, %s %s2 *mem2, %s %s3 *mem3, %s %s4 *mem4, %s %s8 *mem8, %s %s16 *mem16)\n" +"{\n" +" results[0] = (uint)&mem0[0];\n" +" results[1] = (uint)&mem2[0];\n" +" results[2] = (uint)&mem3[0];\n" +" results[3] = (uint)&mem4[0];\n" +" results[4] = (uint)&mem8[0];\n" +" results[5] = (uint)&mem16[0];\n" +"}\n"; + +// For private and local +const char *local_kernel_no_long = +"%s\n" // optional pragma +"kernel void test(global uint *results)\n" +"{\n" +" %s %s mem0[3];\n" +" %s %s2 mem2[3];\n" +" %s %s3 mem3[3];\n" +" %s %s4 mem4[3];\n" +" %s %s8 mem8[3];\n" +" %s %s16 mem16[3];\n" +" results[0] = (uint)&mem0[0];\n" +" results[1] = (uint)&mem2[0];\n" +" results[2] = (uint)&mem3[0];\n" +" results[3] = (uint)&mem4[0];\n" +" results[4] = (uint)&mem8[0];\n" +" results[5] = (uint)&mem16[0];\n" +"}\n"; + +// For constant +const char *constant_kernel_no_long = +"%s\n" // optional pragma +" constant %s mem0[3] = {0};\n" +" constant %s2 mem2[3] = {(%s2)(0)};\n" +" constant %s3 mem3[3] = {(%s3)(0)};\n" +" constant %s4 mem4[3] = {(%s4)(0)};\n" +" constant %s8 mem8[3] = {(%s8)(0)};\n" +" constant %s16 mem16[3] = {(%s16)(0)};\n" +"\n" +"kernel void test(global uint *results)\n" +"{\n" +" results[0] = (uint)&mem0;\n" +" results[1] = (uint)&mem2;\n" +" results[2] = (uint)&mem3;\n" +" results[3] = (uint)&mem4;\n" +" results[4] = (uint)&mem8;\n" +" results[5] = (uint)&mem16;\n" +"}\n"; + +enum AddressSpaces +{ + kGlobal = 0, + kLocal, + kConstant, + kPrivate +}; + +typedef enum AddressSpaces AddressSpaces; + +#define DEBUG 0 + +const char * get_explicit_address_name( AddressSpaces address ) +{ + /* Quick method to avoid branching: make sure the following array matches the Enum order */ + static const char *sExplicitAddressNames[] = { "global", "local", "constant", "private"}; + + return sExplicitAddressNames[ address ]; +} + + +int test_kernel_memory_alignment(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems, AddressSpaces address ) +{ + const char *constant_kernel; + const char *parameter_kernel; + const char *local_kernel; + + if ( gHasLong ) + { + constant_kernel = constant_kernel_long; + parameter_kernel = parameter_kernel_long; + local_kernel = local_kernel_long; + } + else + { + constant_kernel = constant_kernel_no_long; + parameter_kernel = parameter_kernel_no_long; + local_kernel = local_kernel_no_long; + } + + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble }; + char *kernel_code = (char*)malloc(4096); + cl_kernel kernel; + cl_program program; + int error; + int total_errors = 0; + cl_mem results; + cl_ulong *results_data; + cl_mem mem0, mem2, mem3, mem4, mem8, mem16; + + results_data = (cl_ulong*)malloc(sizeof(cl_ulong)*6); + results = clCreateBuffer(context, 0, sizeof(cl_ulong)*6, NULL, &error); + test_error(error, "clCreateBuffer failed"); + + mem0 = clCreateBuffer(context, 0, sizeof(cl_long), NULL, &error); + test_error(error, "clCreateBuffer failed"); + mem2 = clCreateBuffer(context, 0, sizeof(cl_long)*2, NULL, &error); + test_error(error, "clCreateBuffer failed"); + mem3 = clCreateBuffer(context, 0, sizeof(cl_long)*4, NULL, &error); + test_error(error, "clCreateBuffer failed"); + mem4 = clCreateBuffer(context, 0, sizeof(cl_long)*4, NULL, &error); + test_error(error, "clCreateBuffer failed"); + mem8 = clCreateBuffer(context, 0, sizeof(cl_long)*8, NULL, &error); + test_error(error, "clCreateBuffer failed"); + mem16 = clCreateBuffer(context, 0, sizeof(cl_long)*16, NULL, &error); + test_error(error, "clCreateBuffer failed"); + + + // For each type + + // Calculate alignment mask for each size + + // For global, local, constant, private + + // If global, local or constant -- do parameter_kernel + // If private or local -- do local_kernel + // If constant -- do constant kernel + + int numConstantArgs; + clGetDeviceInfo(device, CL_DEVICE_MAX_CONSTANT_ARGS, sizeof(numConstantArgs), &numConstantArgs, NULL); + + int typeIndex; + for (typeIndex = 0; typeIndex < 10; typeIndex++) { + // Skip double tests if we don't support doubles + if (vecType[typeIndex] == kDouble && !is_extension_available(device, "cl_khr_fp64")) { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + continue; + } + + if (( vecType[ typeIndex ] == kLong || vecType[ typeIndex ] == kULong ) && !gHasLong ) + continue; + + log_info("Testing %s...\n", get_explicit_type_name(vecType[typeIndex])); + + // Determine the expected alignment masks. + // E.g., if it is supposed to be 4 byte aligned, we should get 4-1=3 = ... 000011 + // We can then and the returned address with that and we should have 0. + cl_ulong alignments[6]; + alignments[0] = get_explicit_type_size(vecType[typeIndex])-1; + alignments[1] = (get_explicit_type_size(vecType[typeIndex])<<1)-1; + alignments[2] = (get_explicit_type_size(vecType[typeIndex])<<2)-1; + alignments[3] = (get_explicit_type_size(vecType[typeIndex])<<2)-1; + alignments[4] = (get_explicit_type_size(vecType[typeIndex])<<3)-1; + alignments[5] = (get_explicit_type_size(vecType[typeIndex])<<4)-1; + + // Parameter kernel + if (address == kGlobal || address == kLocal || address == kConstant) { + log_info("\tTesting parameter kernel...\n"); + + if ( (gIsEmbedded) && (address == kConstant) && (numConstantArgs < 6)) { + sprintf(kernel_code, parameter_kernel, + vecType[typeIndex] == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]) + ); + } + else { + sprintf(kernel_code, parameter_kernel, + vecType[typeIndex] == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]) + ); + } + //printf("Kernel is: \n%s\n", kernel_code); + + // Create the kernel + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&kernel_code, "test"); + test_error(error, "create_single_kernel_helper failed"); + + // Initialize the results + memset(results_data, 0, sizeof(cl_long)*5); + error = clEnqueueWriteBuffer(queue, results, CL_TRUE, 0, sizeof(cl_long)*6, results_data, 0, NULL, NULL); + test_error(error, "clEnqueueWriteBuffer failed"); + + // Set the arguments + error = clSetKernelArg(kernel, 0, sizeof(results), &results); + test_error(error, "clSetKernelArg failed"); + if (address != kLocal) { + error = clSetKernelArg(kernel, 1, sizeof(mem0), &mem0); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 2, sizeof(mem2), &mem2); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 3, sizeof(mem3), &mem3); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 4, sizeof(mem4), &mem4); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 5, sizeof(mem8), &mem8); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 6, sizeof(mem16), &mem16); + test_error(error, "clSetKernelArg failed"); + } else { + error = clSetKernelArg(kernel, 1, get_explicit_type_size(vecType[typeIndex]), NULL); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 2, get_explicit_type_size(vecType[typeIndex])*2, NULL); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 3, get_explicit_type_size(vecType[typeIndex])*4, NULL); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 4, get_explicit_type_size(vecType[typeIndex])*4, NULL); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 5, get_explicit_type_size(vecType[typeIndex])*8, NULL); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 6, get_explicit_type_size(vecType[typeIndex])*16, NULL); + test_error(error, "clSetKernelArg failed"); + } + + // Enqueue the kernel + size_t global_size = 1; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, NULL, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + // Read back the results + error = clEnqueueReadBuffer(queue, results, CL_TRUE, 0, sizeof(cl_ulong)*6, results_data, 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + // Verify the results + if (gHasLong) { + for (int i = 0; i < 6; i++) { + if ((results_data[i] & alignments[i]) != 0) { + total_errors++; + log_error("\tVector size %d failed: 0x%llx is not properly aligned.\n", 1 << i, results_data[i]); + } else { + if (DEBUG) log_info("\tVector size %d passed: 0x%llx is properly aligned.\n", 1 << i, results_data[i]); + } + } + } + // Verify the results on devices that do not support longs + else { + cl_uint *results_data_no_long = (cl_uint *)results_data; + + for (int i = 0; i < 6; i++) { + if ((results_data_no_long[i] & alignments[i]) != 0) { + total_errors++; + log_error("\tVector size %d failed: 0x%llx is not properly aligned.\n", 1 << i, results_data_no_long[i]); + } else { + if (DEBUG) log_info("\tVector size %d passed: 0x%llx is properly aligned.\n", 1 << i, results_data_no_long[i]); + } + } + } + + clReleaseKernel(kernel); + clReleaseProgram(program); + } + + + + + // Local kernel + if (address == kLocal || address == kPrivate) { + log_info("\tTesting local kernel...\n"); + sprintf(kernel_code, local_kernel, + vecType[typeIndex] == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]) + ); + //printf("Kernel is: \n%s\n", kernel_code); + + // Create the kernel + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&kernel_code, "test"); + test_error(error, "create_single_kernel_helper failed"); + + // Initialize the results + memset(results_data, 0, sizeof(cl_long)*5); + error = clEnqueueWriteBuffer(queue, results, CL_TRUE, 0, sizeof(cl_long)*5, results_data, 0, NULL, NULL); + test_error(error, "clEnqueueWriteBuffer failed"); + + // Set the arguments + error = clSetKernelArg(kernel, 0, sizeof(results), &results); + test_error(error, "clSetKernelArg failed"); + + // Enqueue the kernel + size_t global_size = 1; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, NULL, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + // Read back the results + error = clEnqueueReadBuffer(queue, results, CL_TRUE, 0, sizeof(cl_ulong)*5, results_data, 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + // Verify the results + if (gHasLong) { + for (int i = 0; i < 5; i++) { + if ((results_data[i] & alignments[i]) != 0) { + total_errors++; + log_error("\tVector size %d failed: 0x%llx is not properly aligned.\n", 1 << i, results_data[i]); + } else { + if (DEBUG) log_info("\tVector size %d passed: 0x%llx is properly aligned.\n", 1 << i, results_data[i]); + } + } + } + // Verify the results on devices that do not support longs + else { + cl_uint *results_data_no_long = (cl_uint *)results_data; + + for (int i = 0; i < 5; i++) { + if ((results_data_no_long[i] & alignments[i]) != 0) { + total_errors++; + log_error("\tVector size %d failed: 0x%llx is not properly aligned.\n", 1 << i, results_data_no_long[i]); + } else { + if (DEBUG) log_info("\tVector size %d passed: 0x%llx is properly aligned.\n", 1 << i, results_data_no_long[i]); + } + } + } + clReleaseKernel(kernel); + clReleaseProgram(program); + } + + + + // Constant kernel + if (address == kConstant) { + log_info("\tTesting constant kernel...\n"); + sprintf(kernel_code, constant_kernel, + vecType[typeIndex] == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]) + ); + //printf("Kernel is: \n%s\n", kernel_code); + + // Create the kernel + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&kernel_code, "test"); + test_error(error, "create_single_kernel_helper failed"); + + // Initialize the results + memset(results_data, 0, sizeof(cl_long)*5); + error = clEnqueueWriteBuffer(queue, results, CL_TRUE, 0, sizeof(cl_long)*5, results_data, 0, NULL, NULL); + test_error(error, "clEnqueueWriteBuffer failed"); + + // Set the arguments + error = clSetKernelArg(kernel, 0, sizeof(results), &results); + test_error(error, "clSetKernelArg failed"); + + // Enqueue the kernel + size_t global_size = 1; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, NULL, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + // Read back the results + error = clEnqueueReadBuffer(queue, results, CL_TRUE, 0, sizeof(cl_ulong)*5, results_data, 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + // Verify the results + if (gHasLong) { + for (int i = 0; i < 5; i++) { + if ((results_data[i] & alignments[i]) != 0) { + total_errors++; + log_error("\tVector size %d failed: 0x%llx is not properly aligned.\n", 1 << i, results_data[i]); + } else { + if (DEBUG) log_info("\tVector size %d passed: 0x%llx is properly aligned.\n", 1 << i, results_data[i]); + } + } + } + // Verify the results on devices that do not support longs + else { + cl_uint *results_data_no_long = (cl_uint *)results_data; + + for (int i = 0; i < 5; i++) { + if ((results_data_no_long[i] & alignments[i]) != 0) { + total_errors++; + log_error("\tVector size %d failed: 0x%llx is not properly aligned.\n", 1 << i, results_data_no_long[i]); + } else { + if (DEBUG) log_info("\tVector size %d passed: 0x%llx is properly aligned.\n", 1 << i, results_data_no_long[i]); + } + } + } + clReleaseKernel(kernel); + clReleaseProgram(program); + } + } + + clReleaseMemObject(results); + clReleaseMemObject(mem0); + clReleaseMemObject(mem2); + clReleaseMemObject(mem3); + clReleaseMemObject(mem4); + clReleaseMemObject(mem8); + clReleaseMemObject(mem16); + free( kernel_code ); + free( results_data ); + + if (total_errors != 0) + return -1; + return 0; + +} + + +int test_kernel_memory_alignment_local(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + return test_kernel_memory_alignment( device, context, queue, n_elems, kLocal ); +} + +int test_kernel_memory_alignment_global(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + return test_kernel_memory_alignment( device, context, queue, n_elems, kGlobal ); +} + +int test_kernel_memory_alignment_constant(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + // There is a class of approved OpenCL 1.0 conformant devices out there that in some circumstances + // are unable to meaningfully take (or more precisely use) the address of constant data by virtue + // of limitations in their ISA design. This feature was not tested in 1.0, so they were declared + // conformant by Khronos. The failure is however caught here. + // + // Unfortunately, determining whether or not these devices are 1.0 conformant is not the jurisdiction + // of the 1.1 tests -- We can't fail them from 1.1 conformance here because they are not 1.1 + // devices. They are merely 1.0 conformant devices that interop with 1.1 devices in a 1.1 platform. + // To add new binding tests now to conformant 1.0 devices would violate the workingroup requirement + // of no new tests for 1.0 devices. So certain allowances have to be made in intractable cases + // such as this one. + // + // There is some precedent. Similar allowances are made for other 1.0 hardware features such as + // local memory size. The minimum required local memory size grew from 16 kB to 32 kB in OpenCL 1.1. + + // Detect 1.0 devices + // Get CL_DEVICE_VERSION size + size_t string_size = 0; + int err; + if( (err = clGetDeviceInfo( device, CL_DEVICE_VERSION, 0, NULL, &string_size ) ) ) + { + log_error( "FAILURE: Unable to get size of CL_DEVICE_VERSION string!" ); + return -1; + } + + //Allocate storage to hold the version string + char *version_string = (char*) malloc(string_size); + if( NULL == version_string ) + { + log_error( "FAILURE: Unable to allocate memory to hold CL_DEVICE_VERSION string!" ); + return -1; + } + + // Get CL_DEVICE_VERSION string + if( (err = clGetDeviceInfo( device, CL_DEVICE_VERSION, string_size, version_string, NULL ) ) ) + { + log_error( "FAILURE: Unable to read CL_DEVICE_VERSION string!" ); + return -1; + } + + // easy out for 1.0 devices + const char *string_1_0 = "OpenCL 1.0 "; + if( 0 == strncmp( version_string, string_1_0, strlen(string_1_0)) ) + { + log_info( "WARNING: Allowing device to escape testing of difficult constant memory alignment case.\n\tDevice is not a OpenCL 1.1 device. CL_DEVICE_VERSION: \"%s\"\n", version_string ); + free(version_string); + return 0; + } + log_info( "Device version string: \"%s\"\n", version_string ); + free(version_string); + + // Everyone else is to be ground mercilessly under the wheels of progress + return test_kernel_memory_alignment( device, context, queue, n_elems, kConstant ); +} + +int test_kernel_memory_alignment_private(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + return test_kernel_memory_alignment( device, context, queue, n_elems, kPrivate ); +} + + diff --git a/test_conformance/basic/test_local.c b/test_conformance/basic/test_local.c new file mode 100644 index 00000000..54345ebd --- /dev/null +++ b/test_conformance/basic/test_local.c @@ -0,0 +1,368 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +const char *barrier_with_localmem_kernel_code[] = { +"__kernel void compute_sum_with_localmem(__global int *a, int n, __local int *tmp_sum, __global int *sum)\n" +"{\n" +" int tid = get_local_id(0);\n" +" int lsize = get_local_size(0);\n" +" int i;\n" +"\n" +" tmp_sum[tid] = 0;\n" +" for (i=tid; i max_local_workgroup_size[0]) + kwgsize = max_local_workgroup_size[0]; + + // err = clSetKernelArgs(context, kernel, 4, NULL, values, sizes); + err = clSetKernelArg(kernel, 0, sizeof(streams[0]), &streams[0]); + err |= clSetKernelArg(kernel, 1, sizeof num_elements, &num_elements); + err |= clSetKernelArg(kernel, 2, wgsize * sizeof(cl_int), NULL); + err |= clSetKernelArg(kernel, 3, sizeof streams[1], &streams[1]); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + global_threads[0] = wgsize; + local_threads[0] = wgsize; + + // Adjust the local thread size to fit and be a nice multiple. + if (kwgsize < wgsize) { + log_info("Adjusting wgsize down from %lu to %lu.\n", wgsize, kwgsize); + local_threads[0] = kwgsize; + } + while (global_threads[0] % local_threads[0] != 0) + local_threads[0]--; + + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global_threads, local_threads, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + err = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, out_length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueReadBuffer failed\n"); + return -1; + } + + err = verify_sum(input_ptr, output_ptr, num_elements); + + // cleanup + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + free(input_ptr); + free(output_ptr); + + return err; +} + +int test_local_kernel_def(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem streams[2]; + cl_program program; + cl_kernel kernel; + + cl_int *input_ptr, *output_ptr; + size_t global_threads[1], local_threads[1]; + size_t wgsize, kwgsize; + int err, i; + char *program_source = (char*)malloc(sizeof(char)*2048); + MTdata d = init_genrand( gRandomSeed ); + size_t max_local_workgroup_size[3]; + memset(program_source, 0, 2048); + + err = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof wgsize, &wgsize, NULL); + if (err) { + log_error("clGetDeviceInfo failed, %d\n\n", err); + return -1; + } + wgsize/=2; + if (wgsize < 1) + wgsize = 1; + + size_t in_length = sizeof(cl_int) * num_elements; + size_t out_length = sizeof(cl_int) * wgsize; + + input_ptr = (cl_int *)malloc(in_length); + output_ptr = (cl_int *)malloc(out_length); + + streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, in_length, NULL, NULL); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, out_length, NULL, NULL); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + for (i=0; i (localMemSize / (sizeof(cl_int)*sizeof(cl_int))) ) + { + wgsize = localMemSize / (sizeof(cl_int)*sizeof(cl_int)); + } + + sprintf(program_source, barrier_with_localmem_kernel_code[1], (int)(wgsize * sizeof(cl_int))); + + err = create_single_kernel_helper(context, &program, &kernel, 1, (const char**)&program_source, "compute_sum_with_localmem" ); + free(program_source); + if (err) + return -1; + + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof kwgsize, &kwgsize, NULL); + test_error(err, "clGetKernelWorkGroupInfo failed for CL_KERNEL_WORK_GROUP_SIZE"); + + err = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(max_local_workgroup_size), max_local_workgroup_size, NULL); + test_error(err, "clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_SIZES"); + + // Pick the minimum of the device and the kernel + if (kwgsize > max_local_workgroup_size[0]) + kwgsize = max_local_workgroup_size[0]; + + // err = clSetKernelArgs(context, kernel, 4, NULL, values, sizes); + err = clSetKernelArg(kernel, 0, sizeof(streams[0]), &streams[0]); + err |= clSetKernelArg(kernel, 1, sizeof num_elements, &num_elements); + err |= clSetKernelArg(kernel, 2, sizeof streams[1], &streams[1]); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + global_threads[0] = wgsize; + local_threads[0] = wgsize; + + // Adjust the local thread size to fit and be a nice multiple. + if (kwgsize < wgsize) { + log_info("Adjusting wgsize down from %lu to %lu.\n", wgsize, kwgsize); + local_threads[0] = kwgsize; + } + while (global_threads[0] % local_threads[0] != 0) + local_threads[0]--; + + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global_threads, local_threads, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + err = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, out_length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueReadBuffer failed\n"); + return -1; + } + + err = verify_sum(input_ptr, output_ptr, num_elements); + + // cleanup + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + free(input_ptr); + free(output_ptr); + + return err; +} + + + diff --git a/test_conformance/basic/test_local_kernel_scope.cpp b/test_conformance/basic/test_local_kernel_scope.cpp new file mode 100644 index 00000000..d958dc64 --- /dev/null +++ b/test_conformance/basic/test_local_kernel_scope.cpp @@ -0,0 +1,139 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +#define MAX_LOCAL_STORAGE_SIZE 256 +#define MAX_LOCAL_STORAGE_SIZE_STRING "256" + +const char *kernelSource[] = { + "__kernel void test( __global unsigned int * input, __global unsigned int *outMaxes )\n" + "{\n" + " __local unsigned int localStorage[ " MAX_LOCAL_STORAGE_SIZE_STRING " ];\n" + " unsigned int theValue = input[ get_global_id( 0 ) ];\n" + "\n" + " // If we just write linearly, there's no verification that the items in a group share local data\n" + " // So we write reverse-linearly, which requires items to read the local data written by at least one\n" + " // different item\n" + " localStorage[ get_local_size( 0 ) - get_local_id( 0 ) - 1 ] = theValue;\n" + "\n" + " // The barrier ensures that all local items have written to the local storage\n" + " barrier( CLK_LOCAL_MEM_FENCE );\n" + "\n" + " // Now we loop back through the local storage and look for the max value. We only do this if\n" + " // we're the first item in a group\n" + " unsigned int max = 0;\n" + " if( get_local_id( 0 ) == 0 )\n" + " {\n" + " for( size_t i = 0; i < get_local_size( 0 ); i++ )\n" + " {\n" + " if( localStorage[ i ] > max )\n" + " max = localStorage[ i ];\n" + " }\n" + " outMaxes[ get_group_id( 0 ) ] = max;\n" + " }\n" + "}\n" +}; + +int test_local_kernel_scope(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 2 ]; + MTdata randSeed = init_genrand( gRandomSeed ); + + // Create a test kernel + error = create_single_kernel_helper( context, &program, &kernel, 1, kernelSource, "test" ); + test_error( error, "Unable to create test kernel" ); + + + // Determine an appropriate test size + size_t workGroupSize; + error = clGetKernelWorkGroupInfo( kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof( workGroupSize ), &workGroupSize, NULL ); + test_error( error, "Unable to obtain kernel work group size" ); + + // Make sure the work group size doesn't overrun our local storage size in the kernel + while( workGroupSize > MAX_LOCAL_STORAGE_SIZE ) + workGroupSize >>= 1; + + size_t testSize = workGroupSize; + while( testSize < 1024 ) + testSize += workGroupSize; + size_t numGroups = testSize / workGroupSize; + log_info( "\tTesting with %ld groups, %ld elements per group...\n", numGroups, workGroupSize ); + + // Create two buffers for operation + cl_uint *inputData = (cl_uint*)malloc( testSize * sizeof(cl_uint) ); + generate_random_data( kUInt, testSize, randSeed, inputData ); + free_mtdata( randSeed ); + streams[ 0 ] = clCreateBuffer( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, testSize * sizeof(cl_uint), inputData, &error ); + test_error( error, "Unable to create input buffer" ); + + cl_uint *outputData = (cl_uint*)malloc( numGroups *sizeof(cl_uint) ); + streams[ 1 ] = clCreateBuffer( context, CL_MEM_WRITE_ONLY, numGroups * sizeof(cl_uint), NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + + // Set up the kernel args and run + error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] ); + test_error( error, "Unable to set kernel arg" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[ 1 ] ), &streams[ 1 ] ); + test_error( error, "Unable to set kernel arg" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, &testSize, &workGroupSize, 0, NULL, NULL ); + test_error( error, "Unable to enqueue kernel" ); + + + // Read results and verify + error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, numGroups * sizeof(cl_uint), outputData, 0, NULL, NULL ); + test_error( error, "Unable to read output data" ); + + // MingW compiler seems to have a bug that otimizes the code below incorrectly. + // adding the volatile keyword to size_t decleration to avoid aggressive optimization by the compiler. + for( volatile size_t i = 0; i < numGroups; i++ ) + { + // Determine the max in our case + cl_uint localMax = 0; + for( volatile size_t j = 0; j < workGroupSize; j++ ) + { + if( inputData[ i * workGroupSize + j ] > localMax ) + localMax = inputData[ i * workGroupSize + j ]; + } + + if( outputData[ i ] != localMax ) + { + log_error( "ERROR: Local max validation failed! (expected %u, got %u for i=%lu)\n", localMax, outputData[ i ] , i ); + free(inputData); + free(outputData); + return -1; + } + } + + free(inputData); + free(outputData); + return 0; +} + + diff --git a/test_conformance/basic/test_local_linear_id.c b/test_conformance/basic/test_local_linear_id.c new file mode 100644 index 00000000..52e4cb00 --- /dev/null +++ b/test_conformance/basic/test_local_linear_id.c @@ -0,0 +1,122 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include +#include "../../test_common/harness/rounding_mode.h" + +#include "procs.h" + +static const char *local_linear_id_1d_code = +"__kernel void test_local_linear_id_1d(global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" int linear_id = get_local_id(0);\n" +" int result = (linear_id == (int)get_local_linear_id()) ? 0x1 : 0x0;\n" +" dst[tid] = result;\n" +"}\n"; + +static const char *local_linear_id_2d_code = +"__kernel void test_local_linear_id_2d(global int *dst)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +"\n" +" int linear_id = get_local_id(1) * get_local_size(0) + get_local_id(0);\n" +" int result = (linear_id == (int)get_local_linear_id()) ? 0x1 : 0x0;\n" +" dst[tid_y * get_global_size(0) + tid_x] = result;\n" +"}\n"; + + +static int +verify_local_linear_id(int *result, int n) +{ + int i; + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +const char *loop_kernel_code = +"__kernel void test_loop(__global int *src, __global int *loopindx, __global int *loopcnt, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +" int n = get_global_size(0);\n" +" int i, j;\n" +"\n" +" dst[tid] = 0;\n" +" for (i=0,j=loopindx[tid]; i= n)\n" +" j = 0;\n" +" dst[tid] += src[j];\n" +" }\n" +"\n" +"}\n"; + + +int +verify_loop(int *inptr, int *loopindx, int *loopcnt, int *outptr, int n) +{ + int r, i, j, k; + + for (i=0; i= n) + k = 0; + r += inptr[k]; + } + + if (r != outptr[i]) + { + log_error("LOOP test failed: %d found, expected %d\n", outptr[i], r); + return -1; + } + } + + log_info("LOOP test passed\n"); + return 0; +} + +int test_loop(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem streams[4]; + cl_int *input_ptr, *loop_indx, *loop_cnt, *output_ptr; + cl_program program; + cl_kernel kernel; + size_t threads[1]; + int err, i; + + size_t length = sizeof(cl_int) * num_elements; + input_ptr = (cl_int*)malloc(length); + loop_indx = (cl_int*)malloc(length); + loop_cnt = (cl_int*)malloc(length); + output_ptr = (cl_int*)malloc(length); + + streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[3] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[3]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + MTdata d = init_genrand( gRandomSeed ); + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +static const char *multireadimage_kernel_code = +"__kernel void test_multireadimage(read_only image2d_t img0, read_only image2d_t img1, \n" +" read_only image2d_t img2, __global float4 *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int2 tid = (int2)(tid_x, tid_y);\n" +" int indx = tid_y * get_image_width(img1) + tid_x;\n" +" float4 sum;\n" +"\n" +" sum = read_imagef(img0, sampler, tid);\n" +" sum += read_imagef(img1, sampler, tid);\n" +" sum += read_imagef(img2, sampler, tid);\n" +"\n" +" dst[indx] = sum;\n" +"}\n"; + +#define MAX_ERR 1e-7f + +static unsigned char * +generate_8888_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i max_ulp) + max_ulp = ulp; + } + + if (max_ulp > max_ulp_allowed) { + log_error("READ_MULTIREADIMAGE_MULTIFORMAT test failed. Max ulp error = %g\n", max_ulp); + return -1; + } + + log_info("READ_MULTIREADIMAGE_MULTIFORMAT test passed. Max ulp error = %g\n", max_ulp); + return 0; +} + + +int +test_multireadimagemultifmt(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem streams[4]; + cl_image_format img_format; + void *input_ptr[3], *output_ptr; + cl_program program; + cl_kernel kernel; + size_t threads[2]; + int img_width = 512; + int img_height = 512; + int i, err; + MTdata d; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + d = init_genrand( gRandomSeed ); + input_ptr[0] = (void *)generate_8888_image(img_width, img_height, d); + input_ptr[1] = (void *)generate_16bit_image(img_width, img_height, d); + input_ptr[2] = (void *)generate_float_image(img_width, img_height, d); + free_mtdata(d); d = NULL; + + output_ptr = (void *)malloc(sizeof(float) * 4 * img_width * img_height); + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + streams[0] = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[0]) + { + log_error("create_image_2d failed\n"); + return -1; + } + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT16; + streams[1] = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[1]) + { + log_error("create_image_2d failed\n"); + return -1; + } + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_FLOAT; + streams[2] = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[2]) + { + log_error("create_image_2d failed\n"); + return -1; + } + + streams[3] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(float)*4 * img_width*img_height, NULL, NULL); + if (!streams[3]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + for (i=0; i<3; i++) + { + size_t origin[3] = {0,0,0}, region[3]={img_width, img_height,1}; + err = clEnqueueWriteImage(queue, streams[i], CL_TRUE, origin, region, 0, 0, input_ptr[i], 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clWriteImage failed\n"); + return -1; + } + } + + err = create_single_kernel_helper( context, &program, &kernel, 1, &multireadimage_kernel_code, "test_multireadimage"); + if (err) + return -1; + + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_CLAMP_TO_EDGE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + cl_sampler sampler = clCreateSamplerWithProperties(context, properties, &err); + test_error(err, "clCreateSamplerWithProperties failed"); + + for (i=0; i<4; i++) + err |= clSetKernelArg(kernel, i,sizeof streams[i], &streams[i]); + err |= clSetKernelArg(kernel, 4, sizeof sampler, &sampler); + + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + threads[0] = (size_t)img_width; + threads[1] = (size_t)img_height; + + err = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + err = clEnqueueReadBuffer( queue, streams[3], CL_TRUE, 0, sizeof(float)*4*img_width*img_height, (void *)output_ptr, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueReadBuffer failed\n"); + return -1; + } + + err = verify_multireadimage(input_ptr, (float*)output_ptr, img_width, img_height); + + // cleanup + clReleaseSampler(sampler); + for (i=0; i<4; i++) + clReleaseMemObject(streams[i]); + clReleaseKernel(kernel); + clReleaseProgram(program); + for (i=0; i<3; i++) + free(input_ptr[i]); + free(output_ptr); + + return err; +} + + + + + diff --git a/test_conformance/basic/test_multireadimageonefmt.c b/test_conformance/basic/test_multireadimageonefmt.c new file mode 100644 index 00000000..40fd6bf6 --- /dev/null +++ b/test_conformance/basic/test_multireadimageonefmt.c @@ -0,0 +1,204 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +static const char *multireadimage_kernel_code = +"__kernel void test_multireadimage(int n, int m, sampler_t sampler, \n" +" read_only image2d_t img0, read_only image2d_t img1, \n" +" read_only image2d_t img2, read_only image2d_t img3, \n" +" read_only image2d_t img4, read_only image2d_t img5, \n" +" read_only image2d_t img6, __global float4 *dst)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int2 tid = (int2)(tid_x, tid_y);\n" +" int indx = tid_y * get_image_width(img5) + tid_x;\n" +" float4 sum;\n" +"\n" +" sum = read_imagef(img0, sampler, tid);\n" +" sum += read_imagef(img1, sampler, tid);\n" +" sum += read_imagef(img2, sampler, tid);\n" +" sum += read_imagef(img3, sampler, tid);\n" +" sum += read_imagef(img4, sampler, tid);\n" +" sum += read_imagef(img5, sampler, tid);\n" +" sum += read_imagef(img6, sampler, tid);\n" +"\n" +" dst[indx] = sum;\n" +"}\n"; + + +static unsigned char * +generate_8888_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i max_ulp) + max_ulp = ulp; + } + + if (max_ulp > max_ulp_allowed) + { + log_error("READ_MULTIREADIMAGE_RGBA8888 test failed. Max ULP err = %g\n", max_ulp); + return -1; + } + log_info("READ_MULTIREADIMAGE_RGBA8888 test passed. Max ULP err = %g\n", max_ulp); + return 0; +} + + +int test_multireadimageonefmt(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem streams[8]; + cl_image_format img_format; + void *input_ptr[7], *output_ptr; + cl_program program; + cl_kernel kernel; + size_t threads[2]; + int img_width = 512; + int img_height = 512; + int i, err; + size_t origin[3] = {0, 0, 0}; + size_t region[3] = {img_width, img_height, 1}; + size_t length = img_width * img_height * 4 * sizeof(float); + MTdata d; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + output_ptr = malloc(length); + + d = init_genrand( gRandomSeed ); + for (i=0; i<7; i++) { + input_ptr[i] = (void *)generate_8888_image(img_width, img_height, d); + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + streams[i] = create_image_2d(context, CL_MEM_READ_WRITE, &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[i]) + { + log_error("create_image_2d failed\n"); + return -1; + } + + err = clEnqueueWriteImage(queue, streams[i], CL_TRUE, origin, region, 0, 0, input_ptr[i], 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clWriteImage failed\n"); + return -1; + } + } + free_mtdata(d); d = NULL; + + + streams[7] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[7]) + { + log_error("clCreateArray failed\n"); + return -1; + } + + err = create_single_kernel_helper(context, &program, &kernel, 1, &multireadimage_kernel_code, "test_multireadimage"); + if (err) + return -1; + + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_CLAMP_TO_EDGE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + cl_sampler sampler = clCreateSamplerWithProperties(context, properties, &err); + test_error(err, "clCreateSamplerWithProperties failed"); + + err = clSetKernelArg(kernel, 0, sizeof i, &i); + err |= clSetKernelArg(kernel, 1, sizeof err, &err); + err |= clSetKernelArg(kernel, 2, sizeof sampler, &sampler); + for (i=0; i<8; i++) + err |= clSetKernelArg(kernel, 3+i, sizeof streams[i], &streams[i]); + + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + threads[0] = (unsigned int)img_width; + threads[1] = (unsigned int)img_height; + + err = clEnqueueNDRangeKernel(queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clExecuteKernel failed\n"); + return -1; + } + err = clEnqueueReadBuffer(queue, streams[7], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clReadArray failed\n"); + return -1; + } + + err = verify_multireadimage(input_ptr, 7, (float *)output_ptr, img_width, img_height); + + // cleanup + clReleaseSampler(sampler); + for (i=0; i<8; i++) + clReleaseMemObject(streams[i]); + clReleaseKernel(kernel); + clReleaseProgram(program); + for (i=0; i<7; i++) + free(input_ptr[i]); + free(output_ptr); + + return err; +} + + + + + diff --git a/test_conformance/basic/test_numeric_constants.cpp b/test_conformance/basic/test_numeric_constants.cpp new file mode 100644 index 00000000..5aeca0ed --- /dev/null +++ b/test_conformance/basic/test_numeric_constants.cpp @@ -0,0 +1,710 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "procs.h" + +#define TEST_VALUE_POSITIVE( string_name, name, value ) \ +{ \ +if (name < value) { \ +log_error("FAILED: " string_name ": " #name " < " #value "\n"); \ +errors++;\ +} else { \ +log_info("\t" string_name ": " #name " >= " #value "\n"); \ +} \ +} + +#define TEST_VALUE_NEGATIVE( string_name, name, value ) \ +{ \ +if (name > value) { \ +log_error("FAILED: " string_name ": " #name " > " #value "\n"); \ +errors++;\ +} else { \ +log_info("\t" string_name ": " #name " <= " #value "\n"); \ +} \ +} + +#define TEST_VALUE_EQUAL_LITERAL( string_name, name, value ) \ +{ \ +if (name != value) { \ +log_error("FAILED: " string_name ": " #name " != " #value "\n"); \ +errors++;\ +} else { \ +log_info("\t" string_name ": " #name " = " #value "\n"); \ +} \ +} + +#define TEST_VALUE_EQUAL( string_name, name, value ) \ +{ \ +if (name != value) { \ +log_error("FAILED: " string_name ": " #name " != %a (%17.21g)\n", value, value); \ +errors++;\ +} else { \ +log_info("\t" string_name ": " #name " = %a (%17.21g)\n", value, value); \ +} \ +} + +int test_host_numeric_constants(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int errors = 0; + TEST_VALUE_EQUAL_LITERAL( "CL_CHAR_BIT", CL_CHAR_BIT, 8) + TEST_VALUE_EQUAL_LITERAL( "CL_SCHAR_MAX", CL_SCHAR_MAX, 127) + TEST_VALUE_EQUAL_LITERAL( "CL_SCHAR_MIN", CL_SCHAR_MIN, (-127-1)) + TEST_VALUE_EQUAL_LITERAL( "CL_CHAR_MAX", CL_CHAR_MAX, CL_SCHAR_MAX) + TEST_VALUE_EQUAL_LITERAL( "CL_CHAR_MIN", CL_CHAR_MIN, CL_SCHAR_MIN) + TEST_VALUE_EQUAL_LITERAL( "CL_UCHAR_MAX", CL_UCHAR_MAX, 255) + TEST_VALUE_EQUAL_LITERAL( "CL_SHRT_MAX", CL_SHRT_MAX, 32767) + TEST_VALUE_EQUAL_LITERAL( "CL_SHRT_MIN", CL_SHRT_MIN, (-32767-1)) + TEST_VALUE_EQUAL_LITERAL( "CL_USHRT_MAX", CL_USHRT_MAX, 65535) + TEST_VALUE_EQUAL_LITERAL( "CL_INT_MAX", CL_INT_MAX, 2147483647) + TEST_VALUE_EQUAL_LITERAL( "CL_INT_MIN", CL_INT_MIN, (-2147483647-1)) + TEST_VALUE_EQUAL_LITERAL( "CL_UINT_MAX", CL_UINT_MAX, 0xffffffffU) + TEST_VALUE_EQUAL_LITERAL( "CL_LONG_MAX", CL_LONG_MAX, ((cl_long) 0x7FFFFFFFFFFFFFFFLL)) + TEST_VALUE_EQUAL_LITERAL( "CL_LONG_MIN", CL_LONG_MIN, ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL)) + TEST_VALUE_EQUAL_LITERAL( "CL_ULONG_MAX", CL_ULONG_MAX, ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL)) + + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_DIG", CL_FLT_DIG, 6) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MANT_DIG", CL_FLT_MANT_DIG, 24) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MAX_10_EXP", CL_FLT_MAX_10_EXP, +38) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MAX_EXP", CL_FLT_MAX_EXP, +128) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MIN_10_EXP", CL_FLT_MIN_10_EXP, -37) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MIN_EXP", CL_FLT_MIN_EXP, -125) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_RADIX", CL_FLT_RADIX, 2) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MAX", CL_FLT_MAX, MAKE_HEX_FLOAT( 0x1.fffffep127f, 0x1fffffeL, 103)) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MIN", CL_FLT_MIN, MAKE_HEX_FLOAT(0x1.0p-126f, 0x1L, -126)) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_EPSILON", CL_FLT_EPSILON, MAKE_HEX_FLOAT(0x1.0p-23f, 0x1L, -23)) + + TEST_VALUE_EQUAL_LITERAL( "CL_DBL_DIG", CL_DBL_DIG, 15) + TEST_VALUE_EQUAL_LITERAL( "CL_DBL_MANT_DIG", CL_DBL_MANT_DIG, 53) + TEST_VALUE_EQUAL_LITERAL( "CL_DBL_MAX_10_EXP", CL_DBL_MAX_10_EXP, +308) + TEST_VALUE_EQUAL_LITERAL( "CL_DBL_MAX_EXP", CL_DBL_MAX_EXP, +1024) + TEST_VALUE_EQUAL_LITERAL( "CL_DBL_MIN_10_EXP", CL_DBL_MIN_10_EXP, -307) + TEST_VALUE_EQUAL_LITERAL( "CL_DBL_MIN_EXP", CL_DBL_MIN_EXP, -1021) + TEST_VALUE_EQUAL_LITERAL( "CL_DBL_RADIX", CL_DBL_RADIX, 2) + TEST_VALUE_EQUAL( "CL_DBL_MAX", CL_DBL_MAX, MAKE_HEX_DOUBLE(0x1.fffffffffffffp1023, 0x1fffffffffffffLL, 971)) + TEST_VALUE_EQUAL( "CL_DBL_MIN", CL_DBL_MIN, MAKE_HEX_DOUBLE(0x1.0p-1022, 0x1LL, -1022)) + TEST_VALUE_EQUAL( "CL_DBL_EPSILON", CL_DBL_EPSILON, MAKE_HEX_DOUBLE(0x1.0p-52, 0x1LL, -52)) + + TEST_VALUE_EQUAL( "CL_M_E", CL_M_E, MAKE_HEX_DOUBLE(0x1.5bf0a8b145769p+1, 0x15bf0a8b145769LL, -51) ); + TEST_VALUE_EQUAL( "CL_M_LOG2E", CL_M_LOG2E, MAKE_HEX_DOUBLE(0x1.71547652b82fep+0, 0x171547652b82feLL, -52) ); + TEST_VALUE_EQUAL( "CL_M_LOG10E", CL_M_LOG10E, MAKE_HEX_DOUBLE(0x1.bcb7b1526e50ep-2, 0x1bcb7b1526e50eLL, -54) ); + TEST_VALUE_EQUAL( "CL_M_LN2", CL_M_LN2, MAKE_HEX_DOUBLE(0x1.62e42fefa39efp-1, 0x162e42fefa39efLL, -53) ); + TEST_VALUE_EQUAL( "CL_M_LN10", CL_M_LN10, MAKE_HEX_DOUBLE(0x1.26bb1bbb55516p+1, 0x126bb1bbb55516LL, -51) ); + TEST_VALUE_EQUAL( "CL_M_PI", CL_M_PI, MAKE_HEX_DOUBLE(0x1.921fb54442d18p+1, 0x1921fb54442d18LL, -51) ); + TEST_VALUE_EQUAL( "CL_M_PI_2", CL_M_PI_2, MAKE_HEX_DOUBLE(0x1.921fb54442d18p+0, 0x1921fb54442d18LL, -52) ); + TEST_VALUE_EQUAL( "CL_M_PI_4", CL_M_PI_4, MAKE_HEX_DOUBLE(0x1.921fb54442d18p-1, 0x1921fb54442d18LL, -53) ); + TEST_VALUE_EQUAL( "CL_M_1_PI", CL_M_1_PI, MAKE_HEX_DOUBLE(0x1.45f306dc9c883p-2, 0x145f306dc9c883LL, -54) ); + TEST_VALUE_EQUAL( "CL_M_2_PI", CL_M_2_PI, MAKE_HEX_DOUBLE(0x1.45f306dc9c883p-1, 0x145f306dc9c883LL, -53) ); + TEST_VALUE_EQUAL( "CL_M_2_SQRTPI", CL_M_2_SQRTPI, MAKE_HEX_DOUBLE(0x1.20dd750429b6dp+0, 0x120dd750429b6dLL, -52) ); + TEST_VALUE_EQUAL( "CL_M_SQRT2", CL_M_SQRT2, MAKE_HEX_DOUBLE(0x1.6a09e667f3bcdp+0, 0x16a09e667f3bcdLL, -52) ); + TEST_VALUE_EQUAL( "CL_M_SQRT1_2", CL_M_SQRT1_2, MAKE_HEX_DOUBLE(0x1.6a09e667f3bcdp-1, 0x16a09e667f3bcdLL, -53) ); + + TEST_VALUE_EQUAL( "CL_M_E_F", CL_M_E_F, MAKE_HEX_FLOAT(0x1.5bf0a8p+1f, 0x15bf0a8L, -23)); + TEST_VALUE_EQUAL( "CL_M_LOG2E_F", CL_M_LOG2E_F, MAKE_HEX_FLOAT(0x1.715476p+0f, 0x1715476L, -24)); + TEST_VALUE_EQUAL( "CL_M_LOG10E_F", CL_M_LOG10E_F, MAKE_HEX_FLOAT(0x1.bcb7b2p-2f, 0x1bcb7b2L, -26)); + TEST_VALUE_EQUAL( "CL_M_LN2_F", CL_M_LN2_F, MAKE_HEX_FLOAT(0x1.62e43p-1f, 0x162e43L, -21) ); + TEST_VALUE_EQUAL( "CL_M_LN10_F", CL_M_LN10_F, MAKE_HEX_FLOAT(0x1.26bb1cp+1f, 0x126bb1cL, -23)); + TEST_VALUE_EQUAL( "CL_M_PI_F", CL_M_PI_F, MAKE_HEX_FLOAT(0x1.921fb6p+1f, 0x1921fb6L, -23)); + TEST_VALUE_EQUAL( "CL_M_PI_2_F", CL_M_PI_2_F, MAKE_HEX_FLOAT(0x1.921fb6p+0f, 0x1921fb6L, -24)); + TEST_VALUE_EQUAL( "CL_M_PI_4_F", CL_M_PI_4_F, MAKE_HEX_FLOAT(0x1.921fb6p-1f, 0x1921fb6L, -25)); + TEST_VALUE_EQUAL( "CL_M_1_PI_F", CL_M_1_PI_F, MAKE_HEX_FLOAT(0x1.45f306p-2f, 0x145f306L, -26)); + TEST_VALUE_EQUAL( "CL_M_2_PI_F", CL_M_2_PI_F, MAKE_HEX_FLOAT(0x1.45f306p-1f, 0x145f306L, -25)); + TEST_VALUE_EQUAL( "CL_M_2_SQRTPI_F", CL_M_2_SQRTPI_F,MAKE_HEX_FLOAT(0x1.20dd76p+0f, 0x120dd76L, -24)); + TEST_VALUE_EQUAL( "CL_M_SQRT2_F", CL_M_SQRT2_F, MAKE_HEX_FLOAT(0x1.6a09e6p+0f, 0x16a09e6L, -24)); + TEST_VALUE_EQUAL( "CL_M_SQRT1_2_F", CL_M_SQRT1_2_F, MAKE_HEX_FLOAT(0x1.6a09e6p-1f, 0x16a09e6L, -25)); + + return errors; +} + + +const char *kernel_int_float[] = { + "__kernel void test( __global float *float_out, __global int *int_out, __global uint *uint_out) \n" + "{\n" + " int_out[0] = CHAR_BIT;\n" + " int_out[1] = SCHAR_MAX;\n" + " int_out[2] = SCHAR_MIN;\n" + " int_out[3] = CHAR_MAX;\n" + " int_out[4] = CHAR_MIN;\n" + " int_out[5] = UCHAR_MAX;\n" + " int_out[6] = SHRT_MAX;\n" + " int_out[7] = SHRT_MIN;\n" + " int_out[8] = USHRT_MAX;\n" + " int_out[9] = INT_MAX;\n" + " int_out[10] = INT_MIN;\n" + " uint_out[0] = UINT_MAX;\n" + + " int_out[11] = FLT_DIG;\n" + " int_out[12] = FLT_MANT_DIG;\n" + " int_out[13] = FLT_MAX_10_EXP;\n" + " int_out[14] = FLT_MAX_EXP;\n" + " int_out[15] = FLT_MIN_10_EXP;\n" + " int_out[16] = FLT_MIN_EXP;\n" + " int_out[17] = FLT_RADIX;\n" + "#ifdef __IMAGE_SUPPORT__\n" + " int_out[18] = __IMAGE_SUPPORT__;\n" + "#else\n" + " int_out[18] = 0xf00baa;\n" + "#endif\n" + " float_out[0] = FLT_MAX;\n" + " float_out[1] = FLT_MIN;\n" + " float_out[2] = FLT_EPSILON;\n" + " float_out[3] = M_E_F;\n" + " float_out[4] = M_LOG2E_F;\n" + " float_out[5] = M_LOG10E_F;\n" + " float_out[6] = M_LN2_F;\n" + " float_out[7] = M_LN10_F;\n" + " float_out[8] = M_PI_F;\n" + " float_out[9] = M_PI_2_F;\n" + " float_out[10] = M_PI_4_F;\n" + " float_out[11] = M_1_PI_F;\n" + " float_out[12] = M_2_PI_F;\n" + " float_out[13] = M_2_SQRTPI_F;\n" + " float_out[14] = M_SQRT2_F;\n" + " float_out[15] = M_SQRT1_2_F;\n" + "}\n" +}; + +const char *kernel_long[] = { + "__kernel void test(__global long *long_out, __global ulong *ulong_out) \n" + "{\n" + " long_out[0] = LONG_MAX;\n" + " long_out[1] = LONG_MIN;\n" + " ulong_out[0] = ULONG_MAX;\n" + "}\n" +}; + +const char *kernel_double[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global double *double_out, __global long *long_out ) \n " + "{\n" + " long_out[0] = DBL_DIG;\n" + " long_out[1] = DBL_MANT_DIG;\n" + " long_out[2] = DBL_MAX_10_EXP;\n" + " long_out[3] = DBL_MAX_EXP;\n" + " long_out[4] = DBL_MIN_10_EXP;\n" + " long_out[5] = DBL_MIN_EXP;\n" + " long_out[6] = DBL_RADIX;\n" + " double_out[0] = DBL_MAX;\n" + " double_out[1] = DBL_MIN;\n" + " double_out[2] = DBL_EPSILON;\n" + " double_out[3] = M_E;\n" + " double_out[4] = M_LOG2E;\n" + " double_out[5] = M_LOG10E;\n" + " double_out[6] = M_LN2;\n" + " double_out[7] = M_LN10;\n" + " double_out[8] = M_PI;\n" + " double_out[9] = M_PI_2;\n" + " double_out[10] = M_PI_4;\n" + " double_out[11] = M_1_PI;\n" + " double_out[12] = M_2_PI;\n" + " double_out[13] = M_2_SQRTPI;\n" + " double_out[14] = M_SQRT2;\n" + " double_out[15] = M_SQRT1_2;\n" + "}\n" +}; + + +int test_kernel_numeric_constants(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error, errors = 0; + // clProgramWrapper program; + // clKernelWrapper kernel; + // clMemWrapper streams[3]; + cl_program program; + cl_kernel kernel; + cl_mem streams[3]; + + size_t threads[] = {1,1,1}; + cl_float float_out[16]; + cl_int int_out[19]; + cl_uint uint_out[1]; + cl_long long_out[7]; + cl_ulong ulong_out[1]; + cl_double double_out[16]; + + /** INTs and FLOATs **/ + + // Create the kernel + if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_int_float, "test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(float_out), NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(int_out), NULL, &error); + test_error( error, "Creating test array failed" ); + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(uint_out), NULL, &error); + test_error( error, "Creating test array failed" ); + + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 2, sizeof( streams[2] ), &streams[2]); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, sizeof(float_out), (void*)float_out, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(int_out), (void*)int_out, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, streams[2], CL_TRUE, 0, sizeof(uint_out), (void*)uint_out, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + TEST_VALUE_EQUAL_LITERAL( "CHAR_BIT", int_out[0], 8) + TEST_VALUE_EQUAL_LITERAL( "SCHAR_MAX", int_out[1], 127) + TEST_VALUE_EQUAL_LITERAL( "SCHAR_MIN", int_out[2], (-127-1)) + TEST_VALUE_EQUAL_LITERAL( "CHAR_MAX", int_out[3], CL_SCHAR_MAX) + TEST_VALUE_EQUAL_LITERAL( "CHAR_MIN", int_out[4], CL_SCHAR_MIN) + TEST_VALUE_EQUAL_LITERAL( "UCHAR_MAX", int_out[5], 255) + TEST_VALUE_EQUAL_LITERAL( "SHRT_MAX", int_out[6], 32767) + TEST_VALUE_EQUAL_LITERAL( "SHRT_MIN",int_out[7], (-32767-1)) + TEST_VALUE_EQUAL_LITERAL( "USHRT_MAX", int_out[8], 65535) + TEST_VALUE_EQUAL_LITERAL( "INT_MAX", int_out[9], 2147483647) + TEST_VALUE_EQUAL_LITERAL( "INT_MIN", int_out[10], (-2147483647-1)) + TEST_VALUE_EQUAL_LITERAL( "UINT_MAX", uint_out[0], 0xffffffffU) + + TEST_VALUE_EQUAL_LITERAL( "FLT_DIG", int_out[11], 6) + TEST_VALUE_EQUAL_LITERAL( "FLT_MANT_DIG", int_out[12], 24) + TEST_VALUE_EQUAL_LITERAL( "FLT_MAX_10_EXP", int_out[13], +38) + TEST_VALUE_EQUAL_LITERAL( "FLT_MAX_EXP", int_out[14], +128) + TEST_VALUE_EQUAL_LITERAL( "FLT_MIN_10_EXP", int_out[15], -37) + TEST_VALUE_EQUAL_LITERAL( "FLT_MIN_EXP", int_out[16], -125) + TEST_VALUE_EQUAL_LITERAL( "FLT_RADIX", int_out[17], 2) + TEST_VALUE_EQUAL( "FLT_MAX", float_out[0], MAKE_HEX_FLOAT(0x1.fffffep127f, 0x1fffffeL, 103)) + TEST_VALUE_EQUAL( "FLT_MIN", float_out[1], MAKE_HEX_FLOAT(0x1.0p-126f, 0x1L, -126)) + TEST_VALUE_EQUAL( "FLT_EPSILON", float_out[2], MAKE_HEX_FLOAT(0x1.0p-23f, 0x1L, -23)) + TEST_VALUE_EQUAL( "M_E_F", float_out[3], CL_M_E_F ) + TEST_VALUE_EQUAL( "M_LOG2E_F", float_out[4], CL_M_LOG2E_F ) + TEST_VALUE_EQUAL( "M_LOG10E_F", float_out[5], CL_M_LOG10E_F ) + TEST_VALUE_EQUAL( "M_LN2_F", float_out[6], CL_M_LN2_F ) + TEST_VALUE_EQUAL( "M_LN10_F", float_out[7], CL_M_LN10_F ) + TEST_VALUE_EQUAL( "M_PI_F", float_out[8], CL_M_PI_F ) + TEST_VALUE_EQUAL( "M_PI_2_F", float_out[9], CL_M_PI_2_F ) + TEST_VALUE_EQUAL( "M_PI_4_F", float_out[10], CL_M_PI_4_F ) + TEST_VALUE_EQUAL( "M_1_PI_F", float_out[11], CL_M_1_PI_F ) + TEST_VALUE_EQUAL( "M_2_PI_F", float_out[12], CL_M_2_PI_F ) + TEST_VALUE_EQUAL( "M_2_SQRTPI_F", float_out[13], CL_M_2_SQRTPI_F ) + TEST_VALUE_EQUAL( "M_SQRT2_F", float_out[14], CL_M_SQRT2_F ) + TEST_VALUE_EQUAL( "M_SQRT1_2_F", float_out[15], CL_M_SQRT1_2_F ) + + // We need to check these values against what we know is supported on the device + if( checkForImageSupport( deviceID ) == 0 ) + { // has images + // If images are supported, the constant should have been defined to the value 1 + if( int_out[18] == 0xf00baa ) + { + log_error( "FAILURE: __IMAGE_SUPPORT__ undefined even though images are supported\n" ); + return -1; + } + else if( int_out[18] != 1 ) + { + log_error( "FAILURE: __IMAGE_SUPPORT__ defined, but to the wrong value (defined as %d, spec states it should be 1)\n", int_out[18] ); + return -1; + } + } + else + { // no images + // If images aren't supported, the constant should be undefined + if( int_out[18] != 0xf00baa ) + { + log_error( "FAILURE: __IMAGE_SUPPORT__ defined to value %d even though images aren't supported", int_out[18] ); + return -1; + } + } + log_info( "\t__IMAGE_SUPPORT__: %d\n", int_out[18]); + + clReleaseMemObject(streams[0]); streams[0] = NULL; + clReleaseMemObject(streams[1]); streams[1] = NULL; + clReleaseMemObject(streams[2]); streams[2] = NULL; + clReleaseKernel(kernel); kernel = NULL; + clReleaseProgram(program); program = NULL; + + /** LONGs **/ + + if(!gHasLong) { + log_info("Longs not supported; skipping long tests.\n"); + } + else + { + // Create the kernel + if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_long, "test" ) != 0 ) + { + return -1; + } + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(long_out), NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(ulong_out), NULL, &error); + test_error( error, "Creating test array failed" ); + + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, sizeof(long_out), &long_out, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(ulong_out), &ulong_out, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + TEST_VALUE_EQUAL_LITERAL( "LONG_MAX", long_out[0], ((cl_long) 0x7FFFFFFFFFFFFFFFLL)) + TEST_VALUE_EQUAL_LITERAL( "LONG_MIN", long_out[1], ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL)) + TEST_VALUE_EQUAL_LITERAL( "ULONG_MAX", ulong_out[0], ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL)) + + clReleaseMemObject(streams[0]); streams[0] = NULL; + clReleaseMemObject(streams[1]); streams[1] = NULL; + clReleaseKernel(kernel); kernel = NULL; + clReleaseProgram(program); program = NULL; + } + + /** DOUBLEs **/ + + if(!is_extension_available(deviceID, "cl_khr_fp64")) { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + } + else + { + // Create the kernel + if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_double, "test" ) != 0 ) + { + return -1; + } + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(double_out), NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(long_out), NULL, &error); + test_error( error, "Creating test array failed" ); + + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, sizeof(double_out), &double_out, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(long_out), &long_out, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + TEST_VALUE_EQUAL_LITERAL( "DBL_DIG", long_out[0], 15) + TEST_VALUE_EQUAL_LITERAL( "DBL_MANT_DIG", long_out[1], 53) + TEST_VALUE_EQUAL_LITERAL( "DBL_MAX_10_EXP", long_out[2], +308) + TEST_VALUE_EQUAL_LITERAL( "DBL_MAX_EXP", long_out[3], +1024) + TEST_VALUE_EQUAL_LITERAL( "DBL_MIN_10_EXP", long_out[4], -307) + TEST_VALUE_EQUAL_LITERAL( "DBL_MIN_EXP", long_out[5], -1021) + TEST_VALUE_EQUAL_LITERAL( "DBL_RADIX", long_out[6], 2) + TEST_VALUE_EQUAL( "DBL_MAX", double_out[0], MAKE_HEX_DOUBLE(0x1.fffffffffffffp1023, 0x1fffffffffffffLL, 971)) + TEST_VALUE_EQUAL( "DBL_MIN", double_out[1], MAKE_HEX_DOUBLE(0x1.0p-1022, 0x1LL, -1022)) + TEST_VALUE_EQUAL( "DBL_EPSILON", double_out[2], MAKE_HEX_DOUBLE(0x1.0p-52, 0x1LL, -52)) + //TEST_VALUE_EQUAL( "M_E", double_out[3], CL_M_E ) + TEST_VALUE_EQUAL( "M_LOG2E", double_out[4], CL_M_LOG2E ) + TEST_VALUE_EQUAL( "M_LOG10E", double_out[5], CL_M_LOG10E ) + TEST_VALUE_EQUAL( "M_LN2", double_out[6], CL_M_LN2 ) + TEST_VALUE_EQUAL( "M_LN10", double_out[7], CL_M_LN10 ) + TEST_VALUE_EQUAL( "M_PI", double_out[8], CL_M_PI ) + TEST_VALUE_EQUAL( "M_PI_2", double_out[9], CL_M_PI_2 ) + TEST_VALUE_EQUAL( "M_PI_4", double_out[10], CL_M_PI_4 ) + TEST_VALUE_EQUAL( "M_1_PI", double_out[11], CL_M_1_PI ) + TEST_VALUE_EQUAL( "M_2_PI", double_out[12], CL_M_2_PI ) + TEST_VALUE_EQUAL( "M_2_SQRTPI", double_out[13], CL_M_2_SQRTPI ) + TEST_VALUE_EQUAL( "M_SQRT2", double_out[14], CL_M_SQRT2 ) + TEST_VALUE_EQUAL( "M_SQRT1_2", double_out[15], CL_M_SQRT1_2 ) + + clReleaseMemObject(streams[0]); streams[0] = NULL; + clReleaseMemObject(streams[1]); streams[1] = NULL; + clReleaseKernel(kernel); kernel = NULL; + clReleaseProgram(program); program = NULL; + } + + error = clFinish(queue); + test_error(error, "clFinish failed"); + + return errors; +} + + +const char *kernel_constant_limits[] = { + "__kernel void test( __global int *intOut, __global float *floatOut ) \n" + "{\n" + " intOut[0] = isinf( MAXFLOAT ) ? 1 : 0;\n" + " intOut[1] = isnormal( MAXFLOAT ) ? 1 : 0;\n" + " intOut[2] = isnan( MAXFLOAT ) ? 1 : 0;\n" + " intOut[3] = sizeof( MAXFLOAT );\n" + " intOut[4] = ( MAXFLOAT == FLT_MAX ) ? 1 : 0;\n" + // " intOut[5] = ( MAXFLOAT == CL_FLT_MAX ) ? 1 : 0;\n" + " intOut[6] = ( MAXFLOAT == MAXFLOAT ) ? 1 : 0;\n" + " intOut[7] = ( MAXFLOAT == 0x1.fffffep127f ) ? 1 : 0;\n" + " floatOut[0] = MAXFLOAT;\n" + "}\n" +}; + +const char *kernel_constant_extended_limits[] = { + "__kernel void test( __global int *intOut, __global float *floatOut ) \n" + "{\n" + " intOut[0] = ( INFINITY == HUGE_VALF ) ? 1 : 0;\n" + " intOut[1] = sizeof( INFINITY );\n" + " intOut[2] = isinf( INFINITY ) ? 1 : 0;\n" + " intOut[3] = isnormal( INFINITY ) ? 1 : 0;\n" + " intOut[4] = isnan( INFINITY ) ? 1 : 0;\n" + " intOut[5] = ( INFINITY > MAXFLOAT ) ? 1 : 0;\n" + " intOut[6] = ( -INFINITY < -MAXFLOAT ) ? 1 : 0;\n" + " intOut[7] = ( ( MAXFLOAT + MAXFLOAT ) == INFINITY ) ? 1 : 0;\n" + " intOut[8] = ( nextafter( MAXFLOAT, INFINITY ) == INFINITY ) ? 1 : 0;\n" + " intOut[9] = ( nextafter( -MAXFLOAT, -INFINITY ) == -INFINITY ) ? 1 : 0;\n" + " intOut[10] = ( INFINITY == INFINITY ) ? 1 : 0;\n" + " intOut[11] = ( as_uint( INFINITY ) == 0x7f800000 ) ? 1 : 0;\n" + " floatOut[0] = INFINITY;\n" + "\n" + " intOut[12] = sizeof( HUGE_VALF );\n" + " intOut[13] = ( HUGE_VALF == INFINITY ) ? 1 : 0;\n" + " floatOut[1] = HUGE_VALF;\n" + "\n" + " intOut[14] = ( NAN == NAN ) ? 1 : 0;\n" + " intOut[15] = ( NAN != NAN ) ? 1 : 0;\n" + " intOut[16] = isnan( NAN ) ? 1 : 0;\n" + " intOut[17] = isinf( NAN ) ? 1 : 0;\n" + " intOut[18] = isnormal( NAN ) ? 1 : 0;\n" + " intOut[19] = ( ( as_uint( NAN ) & 0x7fffffff ) > 0x7f800000 ) ? 1 : 0;\n" + " intOut[20] = sizeof( NAN );\n" + " floatOut[2] = NAN;\n" + "\n" + " intOut[21] = isnan( INFINITY / INFINITY ) ? 1 : 0;\n" + " intOut[22] = isnan( INFINITY - INFINITY ) ? 1 : 0;\n" + " intOut[23] = isnan( 0.f / 0.f ) ? 1 : 0;\n" + " intOut[24] = isnan( INFINITY * 0.f ) ? 1 : 0;\n" + " intOut[25] = ( INFINITY == NAN ); \n" + " intOut[26] = ( -INFINITY == NAN ); \n" + " intOut[27] = ( INFINITY > NAN ); \n" + " intOut[28] = ( -INFINITY < NAN ); \n" + " intOut[29] = ( INFINITY != NAN ); \n" + " intOut[30] = ( NAN > INFINITY ); \n" + " intOut[31] = ( NAN < -INFINITY ); \n" + + "}\n" +}; + +const char *kernel_constant_double_limits[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global int *intOut, __global double *doubleOut ) \n" + "{\n" + " intOut[0] = sizeof( HUGE_VAL );\n" + " intOut[1] = ( HUGE_VAL == INFINITY ) ? 1 : 0;\n" + " intOut[2] = isinf( HUGE_VAL ) ? 1 : 0;\n" + " intOut[3] = isnormal( HUGE_VAL ) ? 1 : 0;\n" + " intOut[4] = isnan( HUGE_VAL ) ? 1 : 0;\n" + " intOut[5] = ( HUGE_VAL == HUGE_VALF ) ? 1 : 0;\n" + " intOut[6] = ( as_ulong( HUGE_VAL ) == 0x7ff0000000000000UL ) ? 1 : 0;\n" + " doubleOut[0] = HUGE_VAL;\n" + "}\n" +}; + +#define TEST_FLOAT_ASSERTION( a, msg, f ) if( !( a ) ) { log_error( "ERROR: Float constant failed requirement: %s (bitwise value is 0x%8.8x)\n", msg, *( (uint32_t *)&f ) ); return -1; } +#define TEST_DOUBLE_ASSERTION( a, msg, f ) if( !( a ) ) { log_error( "ERROR: Double constant failed requirement: %s (bitwise value is 0x%16.16llx)\n", msg, *( (uint64_t *)&f ) ); return -1; } + +int test_kernel_limit_constants(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t threads[] = {1,1,1}; + clMemWrapper intStream, floatStream, doubleStream; + cl_int intOut[ 32 ]; + cl_float floatOut[ 3 ]; + cl_double doubleOut[ 1 ]; + + + /* Create some I/O streams */ + intStream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(intOut), NULL, &error ); + test_error( error, "Creating test array failed" ); + floatStream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(floatOut), NULL, &error ); + test_error( error, "Creating test array failed" ); + + // Stage 1: basic limits on MAXFLOAT + { + clProgramWrapper program; + clKernelWrapper kernel; + + if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_constant_limits, "test" ) != 0 ) + { + return -1; + } + + error = clSetKernelArg( kernel, 0, sizeof( intStream ), &intStream ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( floatStream ), &floatStream ); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, intStream, CL_TRUE, 0, sizeof(intOut), intOut, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, floatStream, CL_TRUE, 0, sizeof(floatOut), floatOut, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + // Test MAXFLOAT properties + TEST_FLOAT_ASSERTION( intOut[0] == 0, "isinf( MAXFLOAT ) = false", floatOut[0] ) + TEST_FLOAT_ASSERTION( intOut[1] == 1, "isnormal( MAXFLOAT ) = true", floatOut[0] ) + TEST_FLOAT_ASSERTION( intOut[2] == 0, "isnan( MAXFLOAT ) = false", floatOut[0] ) + TEST_FLOAT_ASSERTION( intOut[3] == 4, "sizeof( MAXFLOAT ) = 4", floatOut[0] ) + TEST_FLOAT_ASSERTION( intOut[4] == 1, "MAXFLOAT = FLT_MAX", floatOut[0] ) + TEST_FLOAT_ASSERTION( floatOut[0] == CL_FLT_MAX, "MAXFLOAT = CL_FLT_MAX", floatOut[0] ) + TEST_FLOAT_ASSERTION( intOut[6] == 1, "MAXFLOAT = MAXFLOAT", floatOut[0] ) + TEST_FLOAT_ASSERTION( floatOut[0] == MAKE_HEX_FLOAT( 0x1.fffffep127f, 0x1fffffeL, 103), "MAXFLOAT = 0x1.fffffep127f", floatOut[0] ) + } + + // Stage 2: INFINITY and NAN + char profileStr[128] = ""; + error = clGetDeviceInfo( deviceID, CL_DEVICE_PROFILE, sizeof( profileStr ), &profileStr, NULL ); + test_error( error, "Unable to run INFINITY/NAN tests (unable to get CL_DEVICE_PROFILE" ); + + bool testInfNan = true; + if( strcmp( profileStr, "EMBEDDED_PROFILE" ) == 0 ) + { + // We test if we're not an embedded profile, OR if the inf/nan flag in the config is set + cl_device_fp_config single = 0; + error = clGetDeviceInfo( deviceID, CL_DEVICE_SINGLE_FP_CONFIG, sizeof( single ), &single, NULL ); + test_error( error, "Unable to run INFINITY/NAN tests (unable to get FP_CONFIG bits)" ); + + if( ( single & CL_FP_INF_NAN ) == 0 ) + { + log_info( "Skipping INFINITY and NAN tests on embedded device (INF/NAN not supported on this device)" ); + testInfNan = false; + } + } + + if( testInfNan ) + { + clProgramWrapper program; + clKernelWrapper kernel; + + if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_constant_extended_limits, "test" ) != 0 ) + { + return -1; + } + + error = clSetKernelArg( kernel, 0, sizeof( intStream ), &intStream ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( floatStream ), &floatStream ); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, intStream, CL_TRUE, 0, sizeof(intOut), intOut, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, floatStream, CL_TRUE, 0, sizeof(floatOut), floatOut, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + TEST_FLOAT_ASSERTION( intOut[0] == 1, "INFINITY == HUGE_VALF", intOut[0] ) + TEST_FLOAT_ASSERTION( intOut[1] == 4, "sizeof( INFINITY ) == 4", intOut[1] ) + TEST_FLOAT_ASSERTION( intOut[2] == 1, "isinf( INFINITY ) == true", intOut[2] ) + TEST_FLOAT_ASSERTION( intOut[3] == 0, "isnormal( INFINITY ) == false", intOut[3] ) + TEST_FLOAT_ASSERTION( intOut[4] == 0, "isnan( INFINITY ) == false", intOut[4] ) + TEST_FLOAT_ASSERTION( intOut[5] == 1, "INFINITY > MAXFLOAT", intOut[5] ) + TEST_FLOAT_ASSERTION( intOut[6] == 1, "-INFINITY < -MAXFLOAT", intOut[6] ) + TEST_FLOAT_ASSERTION( intOut[7] == 1, "( MAXFLOAT + MAXFLOAT ) == INFINITY", intOut[7] ) + TEST_FLOAT_ASSERTION( intOut[8] == 1, "nextafter( MAXFLOAT, INFINITY ) == INFINITY", intOut[8] ) + TEST_FLOAT_ASSERTION( intOut[9] == 1, "nextafter( -MAXFLOAT, -INFINITY ) == -INFINITY", intOut[9] ) + TEST_FLOAT_ASSERTION( intOut[10] == 1, "INFINITY = INFINITY", intOut[10] ) + TEST_FLOAT_ASSERTION( intOut[11] == 1, "asuint( INFINITY ) == 0x7f800000", intOut[11] ) + TEST_FLOAT_ASSERTION( *( (uint32_t *)&floatOut[0] ) == 0x7f800000, "asuint( INFINITY ) == 0x7f800000", floatOut[0] ) + TEST_FLOAT_ASSERTION( floatOut[1] == INFINITY, "INFINITY == INFINITY", floatOut[1] ) + + TEST_FLOAT_ASSERTION( intOut[12] == 4, "sizeof( HUGE_VALF ) == 4", intOut[12] ) + TEST_FLOAT_ASSERTION( intOut[13] == 1, "HUGE_VALF == INFINITY", intOut[13] ) + TEST_FLOAT_ASSERTION( floatOut[1] == HUGE_VALF, "HUGE_VALF == HUGE_VALF", floatOut[1] ) + + TEST_FLOAT_ASSERTION( intOut[14] == 0, "(NAN == NAN) = false", intOut[14] ) + TEST_FLOAT_ASSERTION( intOut[15] == 1, "(NAN != NAN) = true", intOut[15] ) + TEST_FLOAT_ASSERTION( intOut[16] == 1, "isnan( NAN ) = true", intOut[16] ) + TEST_FLOAT_ASSERTION( intOut[17] == 0, "isinf( NAN ) = false", intOut[17] ) + TEST_FLOAT_ASSERTION( intOut[18] == 0, "isnormal( NAN ) = false", intOut[18] ) + TEST_FLOAT_ASSERTION( intOut[19] == 1, "( as_uint( NAN ) & 0x7fffffff ) > 0x7f800000", intOut[19] ) + TEST_FLOAT_ASSERTION( intOut[20] == 4, "sizeof( NAN ) = 4", intOut[20] ) + TEST_FLOAT_ASSERTION( ( *( (uint32_t *)&floatOut[2] ) & 0x7fffffff ) > 0x7f800000, "( as_uint( NAN ) & 0x7fffffff ) > 0x7f800000", floatOut[2] ) + + TEST_FLOAT_ASSERTION( intOut[ 21 ] == 1, "isnan( INFINITY / INFINITY ) = true", intOut[ 21 ] ) + TEST_FLOAT_ASSERTION( intOut[ 22 ] == 1, "isnan( INFINITY - INFINITY ) = true", intOut[ 22 ] ) + TEST_FLOAT_ASSERTION( intOut[ 23 ] == 1, "isnan( 0.f / 0.f ) = true", intOut[ 23 ] ) + TEST_FLOAT_ASSERTION( intOut[ 24 ] == 1, "isnan( INFINITY * 0.f ) = true", intOut[ 24 ] ) + TEST_FLOAT_ASSERTION( intOut[ 25 ] == 0, "( INFINITY == NAN ) = false", intOut[ 25 ] ) + TEST_FLOAT_ASSERTION( intOut[ 26 ] == 0, "(-INFINITY == NAN ) = false", intOut[ 26 ] ) + TEST_FLOAT_ASSERTION( intOut[ 27 ] == 0, "( INFINITY > NAN ) = false", intOut[ 27 ] ) + TEST_FLOAT_ASSERTION( intOut[ 28 ] == 0, "(-INFINITY < NAN ) = false", intOut[ 28 ] ) + TEST_FLOAT_ASSERTION( intOut[ 29 ] == 1, "( INFINITY != NAN ) = true", intOut[ 29 ] ) + TEST_FLOAT_ASSERTION( intOut[ 30 ] == 0, "( NAN < INFINITY ) = false", intOut[ 30 ] ) + TEST_FLOAT_ASSERTION( intOut[ 31 ] == 0, "( NAN > -INFINITY ) = false", intOut[ 31 ] ) + } + + // Stage 3: limits on HUGE_VAL (double) + if( !is_extension_available( deviceID, "cl_khr_fp64" ) ) + log_info( "Note: Skipping double HUGE_VAL tests (doubles unsupported on device)\n" ); + else + { + cl_device_fp_config config = 0; + error = clGetDeviceInfo( deviceID, CL_DEVICE_DOUBLE_FP_CONFIG, sizeof( config ), &config, NULL ); + test_error( error, "Unable to run INFINITY/NAN tests (unable to get double FP_CONFIG bits)" ); + + if( ( config & CL_FP_INF_NAN ) == 0 ) + log_info( "Skipping HUGE_VAL tests (INF/NAN not supported on this device)" ); + else + { + clProgramWrapper program; + clKernelWrapper kernel; + + if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_constant_double_limits, "test" ) != 0 ) + { + return -1; + } + + doubleStream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(doubleOut), NULL, &error ); + test_error( error, "Creating test array failed" ); + + error = clSetKernelArg( kernel, 0, sizeof( intStream ), &intStream ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( doubleStream ), &doubleStream ); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, intStream, CL_TRUE, 0, sizeof(intOut), intOut, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, doubleStream, CL_TRUE, 0, sizeof(doubleOut), doubleOut, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + TEST_DOUBLE_ASSERTION( intOut[0] == 8, "sizeof( HUGE_VAL ) = 8", intOut[0] ) + TEST_DOUBLE_ASSERTION( intOut[1] == 1, "HUGE_VAL = INFINITY", intOut[1] ) + TEST_DOUBLE_ASSERTION( intOut[2] == 1, "isinf( HUGE_VAL ) = true", intOut[2] ) + TEST_DOUBLE_ASSERTION( intOut[3] == 0, "isnormal( HUGE_VAL ) = false", intOut[3] ) + TEST_DOUBLE_ASSERTION( intOut[4] == 0, "isnan( HUGE_VAL ) = false", intOut[4] ) + TEST_DOUBLE_ASSERTION( intOut[5] == 1, "HUGE_VAL = HUGE_VAL", intOut[5] ) + TEST_DOUBLE_ASSERTION( intOut[6] == 1, "as_ulong( HUGE_VAL ) = 0x7ff0000000000000UL", intOut[6] ) + TEST_DOUBLE_ASSERTION( *( (uint64_t *)&doubleOut[0] ) == 0x7ff0000000000000ULL, "as_ulong( HUGE_VAL ) = 0x7ff0000000000000UL", doubleOut[0] ) + } + } + + return 0; +} + + diff --git a/test_conformance/basic/test_pointercast.c b/test_conformance/basic/test_pointercast.c new file mode 100644 index 00000000..0b343f95 --- /dev/null +++ b/test_conformance/basic/test_pointercast.c @@ -0,0 +1,141 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +static const char *pointer_cast_kernel_code = +"__kernel void test_pointer_cast(__global unsigned char *src, __global unsigned int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +" __global unsigned int *p = (__global unsigned int *)src;\n" +"\n" +" dst[tid] = p[tid];\n" +"\n" +"}\n"; + + +int +verify_pointer_cast(unsigned char *inptr, unsigned int *outptr, int n) +{ + unsigned int *p = (unsigned int *)inptr; + int i; + cl_uint r; + + for (i=0; i + +// Test __FILE__, __LINE__, __OPENCL_VERSION__, __OPENCL_C_VERSION__, __ENDIAN_LITTLE__, __ROUNDING_MODE__, __IMAGE_SUPPORT__, __FAST_RELAXED_MATH__ +// __kernel_exec + +const char *preprocessor_test = { + "#line 2 \"%s\"\n" + "__kernel void test( __global int *results, __global char *outFileString, __global char *outRoundingString )\n" + "{\n" + + // Integer preprocessor macros + "#ifdef __IMAGE_SUPPORT__\n" + " results[0] = __IMAGE_SUPPORT__;\n" + "#else\n" + " results[0] = 0xf00baa;\n" + "#endif\n" + + "#ifdef __ENDIAN_LITTLE__\n" + " results[1] = __ENDIAN_LITTLE__;\n" + "#else\n" + " results[1] = 0xf00baa;\n" + "#endif\n" + + "#ifdef __OPENCL_VERSION__\n" + " results[2] = __OPENCL_VERSION__;\n" + "#else\n" + " results[2] = 0xf00baa;\n" + "#endif\n" + + "#ifdef __OPENCL_C_VERSION__\n" + " results[3] = __OPENCL_C_VERSION__;\n" + "#else\n" + " results[3] = 0xf00baa;\n" + "#endif\n" + + "#ifdef __LINE__\n" + " results[4] = __LINE__;\n" + "#else\n" + " results[4] = 0xf00baa;\n" + "#endif\n" + +#if 0 // Removed by Affie's request 2/24 + "#ifdef __FAST_RELAXED_MATH__\n" + " results[5] = __FAST_RELAXED_MATH__;\n" + "#else\n" + " results[5] = 0xf00baa;\n" + "#endif\n" +#endif + + "#ifdef __kernel_exec\n" + " results[6] = 1;\n" // By spec, we can only really evaluate that it is defined, not what it expands to + "#else\n" + " results[6] = 0xf00baa;\n" + "#endif\n" + + // String preprocessor macros. Technically, there are strings in OpenCL, but not really. + "#ifdef __FILE__\n" + " int i;\n" + " constant char *f = \"\" __FILE__;\n" + " for( i = 0; f[ i ] != 0 && i < 512; i++ )\n" + " outFileString[ i ] = f[ i ];\n" + " outFileString[ i ] = 0;\n" + "#else\n" + " outFileString[ 0 ] = 0;\n" + "#endif\n" + + "}\n" + }; + +int test_kernel_preprocessor_macros(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 3 ]; + + int error; + size_t threads[] = {1,1,1}; + + cl_int results[ 7 ]; + cl_char fileString[ 512 ] = "", roundingString[ 128 ] = ""; + char programSource[4096]; + char curFileName[512]; + char *programPtr = programSource; + int i = 0; + snprintf(curFileName, 512, "%s", __FILE__); +#ifdef _WIN32 + // Replace "\" with "\\" + while(curFileName[i] != '\0') { + if (curFileName[i] == '\\') { + int j = i + 1; + char prev = '\\'; + while (curFileName[j - 1] != '\0') { + char tmp = curFileName[j]; + curFileName[j] = prev; + prev = tmp; + j++; + } + i++; + } + i++; + } +#endif + sprintf(programSource,preprocessor_test,curFileName); + + // Create the kernel + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(results), NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(fileString), NULL, &error); + test_error( error, "Creating test array failed" ); + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(roundingString), NULL, &error); + test_error( error, "Creating test array failed" ); + + // Set up and run + for( int i = 0; i < 3; i++ ) + { + error = clSetKernelArg( kernel, i, sizeof( streams[i] ), &streams[i] ); + test_error( error, "Unable to set indexed kernel arguments" ); + } + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, sizeof(results), results, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(fileString), fileString, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, streams[2], CL_TRUE, 0, sizeof(roundingString), roundingString, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + + /////// Check the integer results + + // We need to check these values against what we know is supported on the device + if( checkForImageSupport( deviceID ) == 0 ) + { + // If images are supported, the constant should have been defined to the value 1 + if( results[ 0 ] == 0xf00baa ) + { + log_error( "ERROR: __IMAGE_SUPPORT__ undefined even though images are supported\n" ); + return -1; + } + else if( results[ 0 ] != 1 ) + { + log_error( "ERROR: __IMAGE_SUPPORT__ defined, but to the wrong value (defined as %d, spec states it should be 1)\n", (int)results[ 0 ] ); + return -1; + } + } + else + { + // If images aren't supported, the constant should be undefined + if( results[ 0 ] != 0xf00baa ) + { + log_error( "ERROR: __IMAGE_SUPPORT__ defined to value %d even though images aren't supported", (int)results[ 0 ] ); + return -1; + } + } + + // __ENDIAN_LITTLE__ is similar to __IMAGE_SUPPORT__: 1 if it's true, undefined if it isn't + cl_bool deviceIsLittleEndian; + error = clGetDeviceInfo( deviceID, CL_DEVICE_ENDIAN_LITTLE, sizeof( deviceIsLittleEndian ), &deviceIsLittleEndian, NULL ); + test_error( error, "Unable to get endian property of device to validate against" ); + + if( deviceIsLittleEndian ) + { + if( results[ 1 ] == 0xf00baa ) + { + log_error( "ERROR: __ENDIAN_LITTLE__ undefined even though the device is little endian\n" ); + return -1; + } + else if( results[ 1 ] != 1 ) + { + log_error( "ERROR: __ENDIAN_LITTLE__ defined, but to the wrong value (defined as %d, spec states it should be 1)\n", (int)results[ 1 ] ); + return -1; + } + } + else + { + if( results[ 1 ] != 0xf00baa ) + { + log_error( "ERROR: __ENDIAN_LITTLE__ defined to value %d even though the device is not little endian (should be undefined per spec)", (int)results[ 1 ] ); + return -1; + } + } + + // __OPENCL_VERSION__ + if( results[ 2 ] == 0xf00baa ) + { + log_error( "ERROR: Kernel preprocessor __OPENCL_VERSION__ undefined!" ); + return -1; + } + + // The OpenCL version reported by the macro reports the feature level supported by the compiler. Since + // this doesn't directly match any property we can query, we just check to see if it's a sane value + char versionBuffer[ 128 ]; + error = clGetDeviceInfo( deviceID, CL_DEVICE_VERSION, sizeof( versionBuffer ), versionBuffer, NULL ); + test_error( error, "Unable to get device's version to validate against" ); + + // We need to parse to get the version number to compare against + char *p1, *p2, *p3; + for( p1 = versionBuffer; ( *p1 != 0 ) && !isdigit( *p1 ); p1++ ) + ; + for( p2 = p1; ( *p2 != 0 ) && ( *p2 != '.' ); p2++ ) + ; + for( p3 = p2; ( *p3 != 0 ) && ( *p3 != ' ' ); p3++ ) + ; + + if( p2 == p3 ) + { + log_error( "ERROR: Unable to verify OpenCL version string (platform string is incorrect format)\n" ); + return -1; + } + *p2 = 0; + *p3 = 0; + int major = atoi( p1 ); + int minor = atoi( p2 + 1 ); + int realVersion = ( major * 100 ) + ( minor * 10 ); + if( ( results[ 2 ] < 100 ) || ( results[ 2 ] > realVersion ) ) + { + log_error( "ERROR: Kernel preprocessor __OPENCL_VERSION__ does not make sense w.r.t. device's version string! " + "(preprocessor states %d, real version is %d (%d.%d))\n", results[ 2 ], realVersion, major, minor ); + return -1; + } + + // __OPENCL_C_VERSION__ + if( results[ 3 ] == 0xf00baa ) + { + log_error( "ERROR: Kernel preprocessor __OPENCL_C_VERSION__ undefined!\n" ); + return -1; + } + + // The OpenCL C version reported by the macro reports the OpenCL C supported by the compiler for this OpenCL device. + char cVersionBuffer[ 128 ]; + error = clGetDeviceInfo( deviceID, CL_DEVICE_OPENCL_C_VERSION, sizeof( cVersionBuffer ), cVersionBuffer, NULL ); + test_error( error, "Unable to get device's OpenCL C version to validate against" ); + + // We need to parse to get the version number to compare against + for( p1 = cVersionBuffer; ( *p1 != 0 ) && !isdigit( *p1 ); p1++ ) + ; + for( p2 = p1; ( *p2 != 0 ) && ( *p2 != '.' ); p2++ ) + ; + for( p3 = p2; ( *p3 != 0 ) && ( *p3 != ' ' ); p3++ ) + ; + + if( p2 == p3 ) + { + log_error( "ERROR: Unable to verify OpenCL C version string (platform string is incorrect format)\n" ); + return -1; + } + *p2 = 0; + *p3 = 0; + major = atoi( p1 ); + minor = atoi( p2 + 1 ); + realVersion = ( major * 100 ) + ( minor * 10 ); + if( ( results[ 3 ] < 100 ) || ( results[ 3 ] > realVersion ) ) + { + log_error( "ERROR: Kernel preprocessor __OPENCL_C_VERSION__ does not make sense w.r.t. device's version string! " + "(preprocessor states %d, real version is %d (%d.%d))\n", results[ 2 ], realVersion, major, minor ); + return -1; + } + + // __LINE__ + if( results[ 4 ] == 0xf00baa ) + { + log_error( "ERROR: Kernel preprocessor __LINE__ undefined!" ); + return -1; + } + + // This is fun--we get to search for where __LINE__ actually is so we know what line it should define to! + // Note: it shows up twice, once for the #ifdef, and the other for the actual result output + const char *linePtr = strstr( preprocessor_test, "__LINE__" ); + if( linePtr == NULL ) + { + log_error( "ERROR: Nonsensical NULL pointer encountered!" ); + return -2; + } + linePtr = strstr( linePtr + strlen( "__LINE__" ), "__LINE__" ); + if( linePtr == NULL ) + { + log_error( "ERROR: Nonsensical NULL pointer encountered!" ); + return -2; + } + + // Now count how many carriage returns are before the string + const char *retPtr = strchr( preprocessor_test, '\n' ); + int retCount = 1; + for( ; ( retPtr < linePtr ) && ( retPtr != NULL ); retPtr = strchr( retPtr + 1, '\n' ) ) + retCount++; + + if( retCount != results[ 4 ] ) + { + log_error( "ERROR: Kernel preprocessor __LINE__ does not expand to the actual line number! (expanded to %d, but was on line %d)\n", + results[ 4 ], retCount ); + return -1; + } + +#if 0 // Removed by Affie's request 2/24 + // __FAST_RELAXED_MATH__ + // Since create_single_kernel_helper does NOT define -cl-fast-relaxed-math, this should be undefined + if( results[ 5 ] != 0xf00baa ) + { + log_error( "ERROR: Kernel preprocessor __FAST_RELAXED_MATH__ defined even though build option was not used (should be undefined)\n" ); + return -1; + } +#endif + + // __kernel_exec + // We can ONLY check to verify that it is defined + if( results[ 6 ] == 0xf00baa ) + { + log_error( "ERROR: Kernel preprocessor __kernel_exec must be defined\n" ); + return -1; + } + + //// String preprocessors + + // Since we provided the program directly, __FILE__ should compile to "". + if( fileString[ 0 ] == 0 ) + { + log_error( "ERROR: Kernel preprocessor __FILE__ undefined!\n" ); + return -1; + } + else if( strncmp( (char *)fileString, __FILE__, 512 ) != 0 ) + { + log_info( "WARNING: __FILE__ defined, but to an unexpected value (%s)\n\tShould be: \"%s\"", fileString, __FILE__ ); + return -1; + } + + +#if 0 // Removed by Affie's request 2/24 + // One more try through: try with -cl-fast-relaxed-math to make sure the appropriate preprocessor gets defined + clProgramWrapper programB = clCreateProgramWithSource( context, 1, preprocessor_test, NULL, &error ); + test_error( error, "Unable to create test program" ); + + // Try compiling + error = clBuildProgram( programB, 1, &deviceID, "-cl-fast-relaxed-math", NULL, NULL ); + test_error( error, "Unable to build program" ); + + // Create a kernel again to run against + clKernelWrapper kernelB = clCreateKernel( programB, "test", &error ); + test_error( error, "Unable to create testing kernel" ); + + // Set up and run + for( int i = 0; i < 3; i++ ) + { + error = clSetKernelArg( kernelB, i, sizeof( streams[i] ), &streams[i] ); + test_error( error, "Unable to set indexed kernel arguments" ); + } + + error = clEnqueueNDRangeKernel( queue, kernelB, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + // Only need the one read + error = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, sizeof(results), results, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + // We only need to check the one result this time + if( results[ 5 ] == 0xf00baa ) + { + log_error( "ERROR: Kernel preprocessor __FAST_RELAXED_MATH__ not defined!\n" ); + return -1; + } + else if( results[ 5 ] != 1 ) + { + log_error( "ERROR: Kernel preprocessor __FAST_RELAXED_MATH__ not defined to 1 (was %d)\n", results[ 5 ] ); + return -1; + } +#endif + + return 0; +} + diff --git a/test_conformance/basic/test_progvar.cpp b/test_conformance/basic/test_progvar.cpp new file mode 100644 index 00000000..7445444e --- /dev/null +++ b/test_conformance/basic/test_progvar.cpp @@ -0,0 +1,1555 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +// Bug: Missing in spec: atomic_intptr_t is always supported if device is 32-bits. +// Bug: Missing in spec: CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE + +#define FLUSH fflush(stdout) + +#define MAX_STR 16*1024 + +#define ALIGNMENT 128 + +#define OPTIONS "-cl-std=CL2.0" + +// NUM_ROUNDS must be at least 1. +// It determines how many sets of random data we push through the global +// variables. +#define NUM_ROUNDS 1 + +// This is a shared property of the writer and reader kernels. +#define NUM_TESTED_VALUES 5 + +// TODO: pointer-to-half (and its vectors) +// TODO: union of... + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/mt19937.h" +#include "procs.h" + + +//////////////////// +// Device capabilities +static int l_has_double = 0; +static int l_has_half = 0; +static int l_64bit_device = 0; +static int l_has_int64_atomics = 0; +static int l_has_intptr_atomics = 0; +static int l_has_cles_int64 = 0; + +static int l_host_is_big_endian = 1; + +static size_t l_max_global_id0 = 0; +static cl_bool l_linker_available = false; + +#define check_error(errCode,msg,...) ((errCode != CL_SUCCESS) ? (log_error("ERROR: " msg "! (%s:%d)\n", ## __VA_ARGS__, __FILE__, __LINE__), 1) : 0) + +//////////////////// +// Info about types we can use for program scope variables. + + +class TypeInfo { + +public: + TypeInfo() : + name(""), + m_buf_elem_type(""), + m_is_vecbase(false), + m_is_atomic(false), + m_is_like_size_t(false), + m_is_bool(false), + m_elem_type(0), m_num_elem(0), + m_size(0), + m_value_size(0) + {} + TypeInfo(const char* name_arg) : + name(name_arg), + m_buf_elem_type(name_arg), + m_is_vecbase(false), + m_is_atomic(false), + m_is_like_size_t(false), + m_is_bool(false), + m_elem_type(0), m_num_elem(0), + m_size(0), + m_value_size(0) + { } + + // Vectors + TypeInfo( TypeInfo* elem_type, int num_elem ) : + m_is_vecbase(false), + m_is_atomic(false), + m_is_like_size_t(false), + m_is_bool(false), + m_elem_type(elem_type), + m_num_elem(num_elem) + { + char the_name[10]; // long enough for longest vector type name "double16" + snprintf(the_name,sizeof(the_name),"%s%d",elem_type->get_name_c_str(),m_num_elem); + this->name = std::string(the_name); + this->m_buf_elem_type = std::string(the_name); + this->m_value_size = num_elem * elem_type->get_size(); + if ( m_num_elem == 3 ) { + this->m_size = 4 * elem_type->get_size(); + } else { + this->m_size = num_elem * elem_type->get_size(); + } + } + const std::string& get_name(void) const { return name; } + const char* get_name_c_str(void) const { return name.c_str(); } + TypeInfo& set_vecbase(void) { this->m_is_vecbase = true; return *this; } + TypeInfo& set_atomic(void) { this->m_is_atomic = true; return *this; } + TypeInfo& set_like_size_t(void) { + this->m_is_like_size_t = true; + this->set_size( l_64bit_device ? 8 : 4 ); + this->m_buf_elem_type = l_64bit_device ? "ulong" : "uint"; + return *this; + } + TypeInfo& set_bool(void) { this->m_is_bool = true; return *this; } + TypeInfo& set_size(size_t n) { this->m_value_size = this->m_size = n; return *this; } + TypeInfo& set_buf_elem_type( const char* name ) { this->m_buf_elem_type = std::string(name); return *this; } + + const TypeInfo* elem_type(void) const { return m_elem_type; } + int num_elem(void) const { return m_num_elem; } + + bool is_vecbase(void) const {return m_is_vecbase;} + bool is_atomic(void) const {return m_is_atomic;} + bool is_like_size_t(void) const {return m_is_like_size_t;} + bool is_bool(void) const {return m_is_bool;} + size_t get_size(void) const {return m_size;} + size_t get_value_size(void) const {return m_value_size;} + + // When passing values of this type to a kernel, what buffer type + // should be used? + const char* get_buf_elem_type(void) const { return m_buf_elem_type.c_str(); } + + std::string as_string(const cl_uchar* value_ptr) const { + // This method would be shorter if I had a real handle to element + // vector type. + if ( this->is_bool() ) { + std::string result( name ); + result += "<"; + result += (*value_ptr ? "true" : "false"); + result += ", "; + char buf[10]; + sprintf(buf,"%02x",*value_ptr); + result += buf; + result += ">"; + return result; + } else if ( this->num_elem() ) { + std::string result( name ); + result += "<"; + for ( unsigned ielem = 0 ; ielem < this->num_elem() ; ielem++ ) { + char buf[MAX_STR]; + if ( ielem ) result += ", "; + for ( unsigned ibyte = 0; ibyte < this->m_elem_type->get_size() ; ibyte++ ) { + sprintf(buf + 2*ibyte,"%02x", value_ptr[ ielem * this->m_elem_type->get_size() + ibyte ] ); + } + result += buf; + } + result += ">"; + return result; + } else { + std::string result( name ); + result += "<"; + char buf[MAX_STR]; + for ( unsigned ibyte = 0; ibyte < this->get_size() ; ibyte++ ) { + sprintf(buf + 2*ibyte,"%02x", value_ptr[ ibyte ] ); + } + result += buf; + result += ">"; + return result; + } + } + + // Initialize the given buffer to a constant value initialized as if it + // were from the INIT_VAR macro below. + // Only needs to support values 0 and 1. + void init( cl_uchar* buf, cl_uchar val) const { + if ( this->num_elem() ) { + for ( unsigned ielem = 0 ; ielem < this->num_elem() ; ielem++ ) { + // Delegate! + this->init_elem( buf + ielem * this->get_value_size()/this->num_elem(), val ); + } + } else { + init_elem( buf, val ); + } + } + +private: + void init_elem( cl_uchar* buf, cl_uchar val ) const { + size_t elem_size = this->num_elem() ? this->get_value_size()/this->num_elem() : this->get_size(); + memset(buf,0,elem_size); + if ( val ) { + if ( strstr( name.c_str(), "float" ) ) { + *(float*)buf = (float)val; + return; + } + if ( strstr( name.c_str(), "double" ) ) { + *(double*)buf = (double)val; + return; + } + if ( this->is_bool() ) { *buf = (bool)val; return; } + + // Write a single character value to the correct spot, + // depending on host endianness. + if ( l_host_is_big_endian ) *(buf + elem_size-1) = (cl_uchar)val; + else *buf = (cl_uchar)val; + } + } +public: + + void dump(FILE* fp) const { + fprintf(fp,"Type %s : <%d,%d,%s> ", name.c_str(), + (int)m_size, + (int)m_value_size, + m_buf_elem_type.c_str() ); + if ( this->m_elem_type ) fprintf(fp, " vec(%s,%d)", this->m_elem_type->get_name_c_str(), this->num_elem() ); + if ( this->m_is_vecbase ) fprintf(fp, " vecbase"); + if ( this->m_is_bool ) fprintf(fp, " bool"); + if ( this->m_is_like_size_t ) fprintf(fp, " like-size_t"); + if ( this->m_is_atomic ) fprintf(fp, " atomic"); + fprintf(fp,"\n"); + fflush(fp); + } + +private: + std::string name; + TypeInfo* m_elem_type; + int m_num_elem; + bool m_is_vecbase; + bool m_is_atomic; + bool m_is_like_size_t; + bool m_is_bool; + size_t m_size; // Number of bytes of storage occupied by this type. + size_t m_value_size; // Number of bytes of value significant for this type. Differs for vec3. + + // When passing values of this type to a kernel, what buffer type + // should be used? + // For most types, it's just itself. + // Use a std::string so I don't have to make a copy constructor. + std::string m_buf_elem_type; +}; + + +#define NUM_SCALAR_TYPES (8+2) // signed and unsigned integral types, float and double +#define NUM_VECTOR_SIZES (5) // 2,3,4,8,16 +#define NUM_PLAIN_TYPES \ + 5 /*boolean and size_t family */ \ + + NUM_SCALAR_TYPES \ + + NUM_SCALAR_TYPES*NUM_VECTOR_SIZES \ + + 10 /* atomic types */ + +// Need room for plain, array, pointer, struct +#define MAX_TYPES (4*NUM_PLAIN_TYPES) + +static TypeInfo type_info[MAX_TYPES]; +static int num_type_info = 0; // Number of valid entries in type_info[] + + + + +// A helper class to form kernel source arguments for clCreateProgramWithSource. +class StringTable { +public: + StringTable() : m_c_strs(NULL), m_lengths(NULL), m_frozen(false), m_strings() {} + ~StringTable() { release_frozen(); } + + void add(std::string s) { release_frozen(); m_strings.push_back(s); } + + const size_t num_str() { freeze(); return m_strings.size(); } + const char** strs() { freeze(); return m_c_strs; } + const size_t* lengths() { freeze(); return m_lengths; } + +private: + void freeze(void) { + if ( !m_frozen ) { + release_frozen(); + + m_c_strs = (const char**) malloc(sizeof(const char*) * m_strings.size()); + m_lengths = (size_t*) malloc(sizeof(size_t) * m_strings.size()); + assert( m_c_strs ); + assert( m_lengths ); + + for ( size_t i = 0; i < m_strings.size() ; i++ ) { + m_c_strs[i] = m_strings[i].c_str(); + m_lengths[i] = strlen(m_c_strs[i]); + } + + m_frozen = true; + } + } + void release_frozen(void) { + if ( m_c_strs ) { free(m_c_strs); m_c_strs = 0; } + if ( m_lengths ) { free(m_lengths); m_lengths = 0; } + m_frozen = false; + } + + typedef std::vector strlist_t; + strlist_t m_strings; + const char** m_c_strs; + size_t* m_lengths; + bool m_frozen; +}; + + +//////////////////// +// File scope function declarations + +static void l_load_abilities(cl_device_id device); +static const char* l_get_fp64_pragma(void); +static const char* l_get_cles_int64_pragma(void); +static int l_build_type_table(cl_device_id device); + +static int l_get_device_info(cl_device_id device, size_t* max_size_ret, size_t* pref_size_ret); + +static void l_set_randomly( cl_uchar* buf, size_t buf_size, RandomSeed& rand_state ); +static int l_compare( const cl_uchar* expected, const cl_uchar* received, unsigned num_values, const TypeInfo&ti ); +static int l_copy( cl_uchar* dest, unsigned dest_idx, const cl_uchar* src, unsigned src_idx, const TypeInfo&ti ); + +static std::string conversion_functions(const TypeInfo& ti); +static std::string global_decls(const TypeInfo& ti, bool with_init); +static std::string writer_function(const TypeInfo& ti); +static std::string reader_function(const TypeInfo& ti); + +static int l_write_read( cl_device_id device, cl_context context, cl_command_queue queue ); +static int l_write_read_for_type( cl_device_id device, cl_context context, cl_command_queue queue, const TypeInfo& ti, RandomSeed& rand_state ); + +static int l_init_write_read( cl_device_id device, cl_context context, cl_command_queue queue ); +static int l_init_write_read_for_type( cl_device_id device, cl_context context, cl_command_queue queue, const TypeInfo& ti, RandomSeed& rand_state ); + +static int l_capacity( cl_device_id device, cl_context context, cl_command_queue queue, size_t max_size ); +static int l_user_type( cl_device_id device, cl_context context, cl_command_queue queue, size_t max_size, bool separate_compilation ); + + + +//////////////////// +// File scope function definitions + +static cl_int print_build_log(cl_program program, cl_uint num_devices, cl_device_id *device_list, cl_uint count, const char **strings, const size_t *lengths, const char* options) +{ + cl_uint i; + cl_int error; + BufferOwningPtr devices; + + if(num_devices == 0 || device_list == NULL) + { + error = clGetProgramInfo(program, CL_PROGRAM_NUM_DEVICES, sizeof(num_devices), &num_devices, NULL); + test_error(error, "clGetProgramInfo CL_PROGRAM_NUM_DEVICES failed"); + + device_list = (cl_device_id*)malloc(sizeof(cl_device_id)*num_devices); + devices.reset(device_list); + + memset(device_list, 0, sizeof(cl_device_id) * num_devices); + + error = clGetProgramInfo(program, CL_PROGRAM_DEVICES, sizeof(cl_device_id) * num_devices, device_list, NULL); + test_error(error, "clGetProgramInfo CL_PROGRAM_DEVICES failed"); + } + + cl_uint z; + bool sourcePrinted = false; + + for(z = 0; z < num_devices; z++) + { + char deviceName[4096] = ""; + error = clGetDeviceInfo(device_list[z], CL_DEVICE_NAME, sizeof(deviceName), deviceName, NULL); + check_error(error, "Device \"%d\" failed to return a name. clGetDeviceInfo CL_DEVICE_NAME failed", z); + + cl_build_status buildStatus; + error = clGetProgramBuildInfo(program, device_list[z], CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL); + check_error(error, "clGetProgramBuildInfo CL_PROGRAM_BUILD_STATUS failed"); + + if(buildStatus != CL_BUILD_SUCCESS) + { + if(!sourcePrinted) + { + log_error("Build options: %s\n", options); + if(count && strings) + { + log_error("Original source is: ------------\n"); + for(i = 0; i < count; i++) log_error("%s", strings[i]); + } + sourcePrinted = true; + } + + char statusString[64] = ""; + if (buildStatus == (cl_build_status)CL_BUILD_SUCCESS) + sprintf(statusString, "CL_BUILD_SUCCESS"); + else if (buildStatus == (cl_build_status)CL_BUILD_NONE) + sprintf(statusString, "CL_BUILD_NONE"); + else if (buildStatus == (cl_build_status)CL_BUILD_ERROR) + sprintf(statusString, "CL_BUILD_ERROR"); + else if (buildStatus == (cl_build_status)CL_BUILD_IN_PROGRESS) + sprintf(statusString, "CL_BUILD_IN_PROGRESS"); + else + sprintf(statusString, "UNKNOWN (%d)", buildStatus); + + log_error("Build not successful for device \"%s\", status: %s\n", deviceName, statusString); + + size_t paramSize = 0; + error = clGetProgramBuildInfo(program, device_list[z], CL_PROGRAM_BUILD_LOG, 0, NULL, ¶mSize); + if(check_error(error, "clGetProgramBuildInfo CL_PROGRAM_BUILD_LOG failed")) break; + + std::string log; + log.resize(paramSize/sizeof(char)); + + error = clGetProgramBuildInfo(program, device_list[z], CL_PROGRAM_BUILD_LOG, paramSize, &log[0], NULL); + if(check_error(error, "Device %d (%s) failed to return a build log", z, deviceName)) break; + if(log[0] == 0) log_error("clGetProgramBuildInfo returned an empty log.\n"); + else + { + log_error("Build log:\n", deviceName); + log_error("%s\n", log.c_str()); + } + } + } + return error; +} + +static void l_load_abilities(cl_device_id device) +{ + l_has_half = is_extension_available(device,"cl_khr_fp16"); + l_has_double = is_extension_available(device,"cl_khr_fp64"); + l_has_cles_int64 = is_extension_available(device,"cles_khr_int64"); + + l_has_int64_atomics + = is_extension_available(device,"cl_khr_int64_base_atomics") + && is_extension_available(device,"cl_khr_int64_extended_atomics"); + + { + int status = CL_SUCCESS; + cl_uint addr_bits = 32; + status = clGetDeviceInfo(device,CL_DEVICE_ADDRESS_BITS,sizeof(addr_bits),&addr_bits,0); + l_64bit_device = ( status == CL_SUCCESS && addr_bits == 64 ); + } + + // 32-bit devices always have intptr atomics. + l_has_intptr_atomics = !l_64bit_device || l_has_int64_atomics; + + union { char c[4]; int i; } probe; + probe.i = 1; + l_host_is_big_endian = !probe.c[0]; + + // Determine max global id. + { + int status = CL_SUCCESS; + cl_uint max_dim = 0; + status = clGetDeviceInfo(device,CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS,sizeof(max_dim),&max_dim,0); + assert( status == CL_SUCCESS ); + assert( max_dim > 0 ); + size_t max_id[3]; + max_id[0] = 0; + status = clGetDeviceInfo(device,CL_DEVICE_MAX_WORK_ITEM_SIZES,max_dim*sizeof(size_t),&max_id[0],0); + assert( status == CL_SUCCESS ); + l_max_global_id0 = max_id[0]; + } + + { // Is separate compilation supported? + int status = CL_SUCCESS; + l_linker_available = false; + status = clGetDeviceInfo(device,CL_DEVICE_LINKER_AVAILABLE,sizeof(l_linker_available),&l_linker_available,0); + assert( status == CL_SUCCESS ); + } +} + + +static const char* l_get_fp64_pragma(void) +{ + return l_has_double ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" : ""; +} + +static const char* l_get_cles_int64_pragma(void) +{ + return l_has_cles_int64 ? "#pragma OPENCL EXTENSION cles_khr_int64 : enable\n" : ""; +} + + +static int l_build_type_table(cl_device_id device) +{ + int status = CL_SUCCESS; + size_t iscalar = 0; + size_t ivecsize = 0; + int vecsizes[] = { 2, 3, 4, 8, 16 }; + const char* vecbase[] = { + "uchar", "char", + "ushort", "short", + "uint", "int", + "ulong", "long", + "float", + "double" + }; + int vecbase_size[] = { + 1, 1, + 2, 2, + 4, 4, + 8, 8, + 4, + 8 + }; + const char* like_size_t[] = { + "intptr_t", + "uintptr_t", + "size_t", + "ptrdiff_t" + }; + const char* atomics[] = { + "atomic_int", "atomic_uint", + "atomic_long", "atomic_ulong", + "atomic_float", + "atomic_double", + }; + int atomics_size[] = { + 4, 4, + 8, 8, + 4, + 8 + }; + const char* intptr_atomics[] = { + "atomic_intptr_t", + "atomic_uintptr_t", + "atomic_size_t", + "atomic_ptrdiff_t" + }; + + l_load_abilities(device); + num_type_info = 0; + + // Boolean. + type_info[ num_type_info++ ] = TypeInfo( "bool" ).set_bool().set_size(1).set_buf_elem_type("uchar"); + + // Vector types, and the related scalar element types. + for ( iscalar=0; iscalar < sizeof(vecbase)/sizeof(vecbase[0]) ; ++iscalar ) { + if ( !gHasLong && strstr(vecbase[iscalar],"long") ) continue; + if ( !l_has_double && strstr(vecbase[iscalar],"double") ) continue; + + // Scalar + TypeInfo* elem_type = type_info + num_type_info++; + *elem_type = TypeInfo( vecbase[iscalar] ).set_vecbase().set_size( vecbase_size[iscalar] ); + + // Vector + for ( ivecsize=0; ivecsize < sizeof(vecsizes)/sizeof(vecsizes[0]) ; ivecsize++ ) { + type_info[ num_type_info++ ] = TypeInfo( elem_type, vecsizes[ivecsize] ); + } + } + + // Size_t-like types + for ( iscalar=0; iscalar < sizeof(like_size_t)/sizeof(like_size_t[0]) ; ++iscalar ) { + type_info[ num_type_info++ ] = TypeInfo( like_size_t[iscalar] ).set_like_size_t(); + } + + // Atomic types. + for ( iscalar=0; iscalar < sizeof(atomics)/sizeof(atomics[0]) ; ++iscalar ) { + if ( !l_has_int64_atomics && strstr(atomics[iscalar],"long") ) continue; + if ( !(l_has_int64_atomics && l_has_double) && strstr(atomics[iscalar],"double") ) continue; + + // The +7 is used to skip over the "atomic_" prefix. + const char* buf_type = atomics[iscalar] + 7; + type_info[ num_type_info++ ] = TypeInfo( atomics[iscalar] ).set_atomic().set_size( atomics_size[iscalar] ).set_buf_elem_type( buf_type ); + } + if ( l_has_intptr_atomics ) { + for ( iscalar=0; iscalar < sizeof(intptr_atomics)/sizeof(intptr_atomics[0]) ; ++iscalar ) { + type_info[ num_type_info++ ] = TypeInfo( intptr_atomics[iscalar] ).set_atomic().set_like_size_t(); + } + } + + assert( num_type_info <= MAX_TYPES ); // or increase MAX_TYPES + +#if 0 + for ( size_t i = 0 ; i < num_type_info ; i++ ) { + type_info[ i ].dump(stdout); + } + exit(0); +#endif + + return status; +} + +static const TypeInfo& l_find_type( const char* name ) +{ + for ( size_t i = 0; i < num_type_info ; i++ ) { + if ( 0 == strcmp( name, type_info[i].get_name_c_str() ) ) return type_info[i]; + } + assert(0); +} + + + +// Populate return parameters for max program variable size, preferred program variable size. + +static int l_get_device_info(cl_device_id device, size_t* max_size_ret, size_t* pref_size_ret) +{ + int err = CL_SUCCESS; + size_t return_size = 0; + + err = clGetDeviceInfo(device, CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE, sizeof(*max_size_ret), max_size_ret, &return_size); + if ( err != CL_SUCCESS ) { + log_error("Error: Failed to get device info for CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE\n"); + return err; + } + if ( return_size != sizeof(size_t) ) { + log_error("Error: Invalid size %d returned for CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE\n", (int)return_size ); + return 1; + } + if ( return_size != sizeof(size_t) ) { + log_error("Error: Invalid size %d returned for CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE\n", (int)return_size ); + return 1; + } + + return_size = 0; + err = clGetDeviceInfo(device, CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE, sizeof(*pref_size_ret), pref_size_ret, &return_size); + if ( err != CL_SUCCESS ) { + log_error("Error: Failed to get device info for CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE: %d\n",err); + return err; + } + if ( return_size != sizeof(size_t) ) { + log_error("Error: Invalid size %d returned for CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE\n", (int)return_size ); + return 1; + } + + return CL_SUCCESS; +} + + +static void l_set_randomly( cl_uchar* buf, size_t buf_size, RandomSeed& rand_state ) +{ + assert( 0 == (buf_size % sizeof(cl_uint) ) ); + for ( size_t i = 0; i < buf_size ; i += sizeof(cl_uint) ) { + *( (cl_uint*)(buf + i) ) = genrand_int32( rand_state ); + } +#if 0 + for ( size_t i = 0; i < buf_size ; i++ ) { + printf("%02x",buf[i]); + } + printf("\n"); +#endif +} + +// Return num_value values of the given type. +// Returns CL_SUCCESS if they compared as equal. +static int l_compare( const char* test_name, const cl_uchar* expected, const cl_uchar* received, size_t num_values, const TypeInfo&ti ) +{ + // Compare only the valid returned bytes. + for ( unsigned value_idx = 0; value_idx < num_values; value_idx++ ) { + const cl_uchar* expv = expected + value_idx * ti.get_size(); + const cl_uchar* gotv = received + value_idx * ti.get_size(); + if ( memcmp( expv, gotv, ti.get_value_size() ) ) { + std::string exp_str = ti.as_string( expv ); + std::string got_str = ti.as_string( gotv ); + log_error("Error: %s test for type %s, at index %d: Expected %s got %s\n", + test_name, + ti.get_name_c_str(), value_idx, + exp_str.c_str(), + got_str.c_str() ); + return 1; + } + } + return CL_SUCCESS; +} + +// Copy a target value from src[idx] to dest[idx] +static int l_copy( cl_uchar* dest, unsigned dest_idx, const cl_uchar* src, unsigned src_idx, const TypeInfo&ti ) +{ + cl_uchar* raw_dest = dest + dest_idx * ti.get_size(); + const cl_uchar* raw_src = src + src_idx * ti.get_size(); + memcpy( raw_dest, raw_src, ti.get_value_size() ); + + return 0; +} + + +static std::string conversion_functions(const TypeInfo& ti) +{ + std::string result; + static char buf[MAX_STR]; + int num_printed = 0; + // The atomic types just use the base type. + if ( ti.is_atomic() || 0 == strcmp( ti.get_buf_elem_type(), ti.get_name_c_str() ) ) { + // The type is represented in a buffer by itself. + num_printed = snprintf(buf,MAX_STR, + "%s from_buf(%s a) { return a; }\n" + "%s to_buf(%s a) { return a; }\n", + ti.get_buf_elem_type(), ti.get_buf_elem_type(), + ti.get_buf_elem_type(), ti.get_buf_elem_type() ); + } else { + // Just use C-style cast. + num_printed = snprintf(buf,MAX_STR, + "%s from_buf(%s a) { return (%s)a; }\n" + "%s to_buf(%s a) { return (%s)a; }\n", + ti.get_name_c_str(), ti.get_buf_elem_type(), ti.get_name_c_str(), + ti.get_buf_elem_type(), ti.get_name_c_str(), ti.get_buf_elem_type() ); + } + // Add initializations. + if ( ti.is_atomic() ) { + num_printed += snprintf( buf + num_printed, MAX_STR-num_printed, + "#define INIT_VAR(a) ATOMIC_VAR_INIT(a)\n" ); + } else { + // This cast works even if the target type is a vector type. + num_printed += snprintf( buf + num_printed, MAX_STR-num_printed, + "#define INIT_VAR(a) ((%s)(a))\n", ti.get_name_c_str()); + } + assert( num_printed < MAX_STR ); // or increase MAX_STR + result = buf; + return result; +} + +static std::string global_decls(const TypeInfo& ti, bool with_init ) +{ + const char* tn = ti.get_name_c_str(); + const char* vol = (ti.is_atomic() ? " volatile " : " "); + static char decls[MAX_STR]; + int num_printed = 0; + if ( with_init ) { + const char *decls_template_with_init = + "%s %s var = INIT_VAR(0);\n" + "global %s %s g_var = INIT_VAR(1);\n" + "%s %s a_var[2] = { INIT_VAR(1), INIT_VAR(1) };\n" + "volatile global %s %s* p_var = &a_var[1];\n\n"; + num_printed = snprintf(decls,sizeof(decls),decls_template_with_init, + vol,tn,vol,tn,vol,tn,vol,tn); + } else { + const char *decls_template_no_init = + "%s %s var;\n" + "global %s %s g_var;\n" + "%s %s a_var[2];\n" + "global %s %s* p_var;\n\n"; + num_printed = snprintf(decls,sizeof(decls),decls_template_no_init, + vol,tn,vol,tn,vol,tn,vol,tn); + } + assert( num_printed < sizeof(decls) ); + return std::string(decls); +} + + +// Return the source text for the writer function for the given type. +// For types that can't be passed as pointer-to-type as a kernel argument, +// use a substitute base type of the same size. +static std::string writer_function(const TypeInfo& ti) +{ + static char writer_src[MAX_STR]; + int num_printed = 0; + if ( !ti.is_atomic() ) { + const char* writer_template_normal = + "kernel void writer( global %s* src, uint idx ) {\n" + " var = from_buf(src[0]);\n" + " g_var = from_buf(src[1]);\n" + " a_var[0] = from_buf(src[2]);\n" + " a_var[1] = from_buf(src[3]);\n" + " p_var = a_var + idx;\n" + "}\n\n"; + num_printed = snprintf(writer_src,sizeof(writer_src),writer_template_normal,ti.get_buf_elem_type()); + } else { + const char* writer_template_atomic = + "kernel void writer( global %s* src, uint idx ) {\n" + " atomic_store( &var, from_buf(src[0]) );\n" + " atomic_store( &g_var, from_buf(src[1]) );\n" + " atomic_store( &a_var[0], from_buf(src[2]) );\n" + " atomic_store( &a_var[1], from_buf(src[3]) );\n" + " p_var = a_var + idx;\n" + "}\n\n"; + num_printed = snprintf(writer_src,sizeof(writer_src),writer_template_atomic,ti.get_buf_elem_type()); + } + assert( num_printed < sizeof(writer_src) ); + std::string result = writer_src; + return result; +} + + +// Return source text for teh reader function for the given type. +// For types that can't be passed as pointer-to-type as a kernel argument, +// use a substitute base type of the same size. +static std::string reader_function(const TypeInfo& ti) +{ + static char reader_src[MAX_STR]; + int num_printed = 0; + if ( !ti.is_atomic() ) { + const char* reader_template_normal = + "kernel void reader( global %s* dest, %s ptr_write_val ) {\n" + " *p_var = from_buf(ptr_write_val);\n" + " dest[0] = to_buf(var);\n" + " dest[1] = to_buf(g_var);\n" + " dest[2] = to_buf(a_var[0]);\n" + " dest[3] = to_buf(a_var[1]);\n" + "}\n\n"; + num_printed = snprintf(reader_src,sizeof(reader_src),reader_template_normal,ti.get_buf_elem_type(),ti.get_buf_elem_type()); + } else { + const char* reader_template_atomic = + "kernel void reader( global %s* dest, %s ptr_write_val ) {\n" + " atomic_store( p_var, from_buf(ptr_write_val) );\n" + " dest[0] = to_buf( atomic_load( &var ) );\n" + " dest[1] = to_buf( atomic_load( &g_var ) );\n" + " dest[2] = to_buf( atomic_load( &a_var[0] ) );\n" + " dest[3] = to_buf( atomic_load( &a_var[1] ) );\n" + "}\n\n"; + num_printed = snprintf(reader_src,sizeof(reader_src),reader_template_atomic,ti.get_buf_elem_type(),ti.get_buf_elem_type()); + } + assert( num_printed < sizeof(reader_src) ); + std::string result = reader_src; + return result; +} + + +// Check write-then-read. +static int l_write_read( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + int status = CL_SUCCESS; + int itype; + + RandomSeed rand_state( gRandomSeed ); + + for ( itype = 0; itype < num_type_info ; itype++ ) { + status = status | l_write_read_for_type(device,context,queue,type_info[itype], rand_state ); + FLUSH; + } + + return status; +} +static int l_write_read_for_type( cl_device_id device, cl_context context, cl_command_queue queue, const TypeInfo& ti, RandomSeed& rand_state ) +{ + int err = CL_SUCCESS; + std::string type_name( ti.get_name() ); + const char* tn = type_name.c_str(); + log_info(" %s ",tn); + + StringTable ksrc; + ksrc.add( l_get_fp64_pragma() ); + ksrc.add( l_get_cles_int64_pragma() ); + ksrc.add( conversion_functions(ti) ); + ksrc.add( global_decls(ti,false) ); + ksrc.add( writer_function(ti) ); + ksrc.add( reader_function(ti) ); + + int status = CL_SUCCESS; + clProgramWrapper program; + clKernelWrapper writer; + + status = create_single_kernel_helper_with_build_options(context, &program, &writer, ksrc.num_str(), ksrc.strs(), "writer", OPTIONS); + test_error_ret(status,"Failed to create program for read-after-write test",status); + + clKernelWrapper reader( clCreateKernel( program, "reader", &status ) ); + test_error_ret(status,"Failed to create reader kernel for read-after-write test",status); + + // Check size query. + size_t used_bytes = 0; + status = clGetProgramBuildInfo( program, device, CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE, sizeof(used_bytes), &used_bytes, 0 ); + test_error_ret(status,"Failed to query global variable total size",status); + size_t expected_used_bytes = + (NUM_TESTED_VALUES-1)*ti.get_size() // Two regular variables and an array of 2 elements. + + ( l_64bit_device ? 8 : 4 ); // The pointer + if ( used_bytes < expected_used_bytes ) { + log_error("Error program query for global variable total size query failed: Expected at least %llu but got %llu\n", (unsigned long long)expected_used_bytes, (unsigned long long)used_bytes ); + err |= 1; + } + + // We need to create 5 random values of the given type, + // and read 4 of them back. + cl_uchar CL_ALIGNED(ALIGNMENT) write_data[NUM_TESTED_VALUES * sizeof(cl_ulong16)]; + cl_uchar CL_ALIGNED(ALIGNMENT) read_data[ (NUM_TESTED_VALUES-1) * sizeof(cl_ulong16)]; + + clMemWrapper write_mem( clCreateBuffer( context, CL_MEM_USE_HOST_PTR, sizeof(write_data), write_data, &status ) ); + test_error_ret(status,"Failed to allocate write buffer",status); + clMemWrapper read_mem( clCreateBuffer( context, CL_MEM_USE_HOST_PTR, sizeof(read_data), read_data, &status ) ); + test_error_ret(status,"Failed to allocate read buffer",status); + + status = clSetKernelArg(writer,0,sizeof(cl_mem),&write_mem); test_error_ret(status,"set arg",status); + status = clSetKernelArg(reader,0,sizeof(cl_mem),&read_mem); test_error_ret(status,"set arg",status); + + // Boolean random data needs to be massaged a bit more. + const int num_rounds = ti.is_bool() ? (1 << NUM_TESTED_VALUES ) : NUM_ROUNDS; + unsigned bool_iter = 0; + + for ( int iround = 0; iround < num_rounds ; iround++ ) { + for ( cl_uint iptr_idx = 0; iptr_idx < 2 ; iptr_idx++ ) { // Index into array, to write via pointer + // Generate new random data to push through. + // Generate 5 * 128 bytes all the time, even though the test for many types use less than all that. + + cl_uchar *write_ptr = (cl_uchar *)clEnqueueMapBuffer(queue, write_mem, CL_TRUE, CL_MAP_WRITE, 0, sizeof(write_data), 0, 0, 0, 0); + + if ( ti.is_bool() ) { + // For boolean, random data cast to bool isn't very random. + // So use the bottom bit of bool_value_iter to get true + // diversity. + for ( unsigned value_idx = 0; value_idx < NUM_TESTED_VALUES ; value_idx++ ) { + write_data[value_idx] = (1< +#include +#include +#include +#include +#include "../../test_common/harness/rounding_mode.h" + +#include "procs.h" + +static const char *fpadd_kernel_code = +"__kernel void test_fpadd(__global float *srcA, __global float *srcB, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +static const char *fpsub_kernel_code = +"__kernel void test_fpsub(__global float *srcA, __global float *srcB, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +static const char *fpmul_kernel_code = +"__kernel void test_fpmul(__global float *srcA, __global float *srcB, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + + +static const float MAX_ERR = 1e-5f; + +static int +verify_fpadd(float *inptrA, float *inptrB, float *outptr, int n, int fileNum) +{ + float r; + int i; + + float * reference_ptr = (float *)malloc(n * sizeof(float)); + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +static const char *bgra8888_kernel_code = +"\n" +"__kernel void test_bgra8888(read_only image2d_t srcimg, __global uchar4 *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y)) * 255.0f;\n" +" dst[indx] = convert_uchar4_rte(color.zyxw);\n" +"\n" +"}\n"; + + +static const char *rgba8888_kernel_code = +"\n" +"__kernel void test_rgba8888(read_only image2d_t srcimg, __global uchar4 *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y)) * 255.0f;\n" +" dst[indx] = convert_uchar4_rte(color);\n" +"\n" +"}\n"; + + +static unsigned char * +generate_8888_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i +#include +#include +#include +#include +#include + + +#include "procs.h" + +static const char *bgra8888_kernel_code = +"\n" +"__kernel void test_bgra8888(read_only image3d_t srcimg, __global float4 *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int tid_z = get_global_id(2);\n" +" int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0));\n" +" dst[indx].x = color.z;\n" +" dst[indx].y = color.y;\n" +" dst[indx].z = color.x;\n" +" dst[indx].w = color.w;\n" +"\n" +"}\n"; + + +static const char *rgba8888_kernel_code = +"\n" +"__kernel void test_rgba8888(read_only image3d_t srcimg, __global float4 *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int tid_z = get_global_id(2);\n" +" int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0));\n" +" //indx *= 4;\n" +" dst[indx].x = color.x;\n" +" dst[indx].y = color.y;\n" +" dst[indx].z = color.z;\n" +" dst[indx].w = color.w;\n" +"\n" +"}\n"; + + +static unsigned char * +generate_3d_image8(int w, int h, int d, MTdata data) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * d * 4); + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + + +static const char *rgbaFFFF_kernel_code = +"__kernel void test_rgbaFFFF(read_only image3d_t srcimg, __global float *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int tid_z = get_global_id(2);\n" +" int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0));\n" +" indx *= 4;\n" +" dst[indx+0] = color.x;\n" +" dst[indx+1] = color.y;\n" +" dst[indx+2] = color.z;\n" +" dst[indx+3] = color.w;\n" +"\n" +"}\n"; + + +static float * +generate_float_image(int w, int h, int d, MTdata data) +{ + float *ptr = (float*)malloc(w * h * d * 4 * sizeof(float)); + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +static const char *rgba16_kernel_code = +"__kernel void test_rgba16(read_only image3d_t srcimg, __global ushort4 *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int tid_z = get_global_id(2);\n" +" int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0));\n" +" ushort4 dst_write;\n" +" dst_write.x = convert_ushort_rte(color.x * 65535.0f);\n" +" dst_write.y = convert_ushort_rte(color.y * 65535.0f);\n" +" dst_write.z = convert_ushort_rte(color.z * 65535.0f);\n" +" dst_write.w = convert_ushort_rte(color.w * 65535.0f);\n" +" dst[indx] = dst_write;\n" +"\n" +"}\n"; + + +static unsigned short * +generate_16bit_image(int w, int h, int d, MTdata data) +{ + unsigned short *ptr = (cl_ushort*)malloc(w * h * d * 4 * sizeof(cl_ushort)); + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + + +static const char *rgbaFFFF_kernel_code = +"__kernel void test_rgbaFFFF(read_only image2d_t srcimg, __global float *dst, sampler_t smp)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, smp, (int2)(tid_x, tid_y));\n" +" indx *= 4;\n" +" dst[indx+0] = color.x;\n" +" dst[indx+1] = color.y;\n" +" dst[indx+2] = color.z;\n" +" dst[indx+3] = color.w;\n" +"\n" +"}\n"; + + +static float * +generate_float_image(int w, int h, MTdata d) +{ + float *ptr = (float*)malloc(w * h * 4 * sizeof(float)); + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +static const char *rgba16_kernel_code = +"__kernel void test_rgba16(read_only image2d_t srcimg, __global ushort4 *dst, sampler_t smp)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, smp, (int2)(tid_x, tid_y));\n" +" ushort4 dst_write;\n" +" dst_write.x = convert_ushort_rte(color.x * 65535.0f);\n" +" dst_write.y = convert_ushort_rte(color.y * 65535.0f);\n" +" dst_write.z = convert_ushort_rte(color.z * 65535.0f);\n" +" dst_write.w = convert_ushort_rte(color.w * 65535.0f);\n" +" dst[indx] = dst_write;\n" +"\n" +"}\n"; + + +static unsigned short * +generate_16bit_image(int w, int h, MTdata d) +{ + cl_ushort *ptr = (cl_ushort*)malloc(w * h * 4 * sizeof(cl_ushort)); + int i; + + for (i=0; i +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/clImageHelper.h" + +static const char* rw_kernel_code = +"kernel void test_rw_images(read_write image2d_t src_image) {\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +"\n" +" int2 coords = (int2)(tid_x, tid_y);\n" +"\n" +" uint4 src_val = read_imageui(src_image, coords);\n" +" src_val += 3;\n" +"\n" +" // required to ensure that following read from image at\n" +" // location coord returns the latest color value.\n" +" atomic_work_item_fence(CLK_IMAGE_MEM_FENCE,\n" +" memory_order_acq_rel,\n" +" memory_scope_work_item);\n" +"\n" +" write_imageui(src_image, coords, src_val);\n" +"}\n"; + + +int test_rw_image_access_qualifier(cl_device_id device_id, cl_context context, cl_command_queue commands, int num_elements) +{ + + unsigned int i; + + unsigned int size_x; + unsigned int size_y; + unsigned int size; + + cl_int err; + + cl_program program; + cl_kernel kernel; + + cl_mem_flags flags; + cl_image_format format; + cl_mem src_image; + + unsigned int *input; + unsigned int *output; + + /* Create test input */ + size_x = 4; + size_y = 4; + size = size_x * size_y * 4; + + input = (unsigned int *)malloc(size*sizeof(unsigned int)); + output = (unsigned int *)malloc(size*sizeof(unsigned int)); + + if (!input && !output) { + log_error("Error: memory allocation failed\n"); + return -1; + } + + /* Fill input array with random values */ + for (i = 0; i < size; i++) { + input[i] = (unsigned int)(rand()/((double)RAND_MAX + 1)*255); + } + + /* Zero out output array */ + for (i = 0; i < size; i++) { + output[i] = 0.0f; + } + + /* Build the program executable */ + err = create_single_kernel_helper_with_build_options(context,&program,&kernel,1,&rw_kernel_code,"test_rw_images", "-cl-std=CL2.0"); + if (err != CL_SUCCESS || !program) { + log_error("Error: clCreateProgramWithSource failed\n"); + return err; + } + + /* Create arrays for input and output data */ + format.image_channel_order = CL_RGBA; + format.image_channel_data_type = CL_UNSIGNED_INT32; + + /* Create input image */ + flags = (cl_mem_flags) (CL_MEM_READ_WRITE + | CL_MEM_COPY_HOST_PTR); + src_image = create_image_2d(context, flags, &format, + size_x, size_y, 0, + (void *)input, &err); + if (err != CL_SUCCESS || !src_image) { + log_error("Error: clCreateImage2D failed\n"); + return err; + } + + /* Set kernel arguments */ + err = clSetKernelArg(kernel, 0, sizeof(src_image), &src_image); + if (err != CL_SUCCESS) { + log_error("Error: clSetKernelArg failed\n"); + return err; + } + + /* Set kernel execution parameters */ + int dim_count = 2; + size_t global_dim[2]; + size_t local_dim[2]; + + global_dim[0] = size_x; + global_dim[1] = size_y; + + local_dim[0] = 1; + local_dim[1] = 1; + + /* Execute kernel */ + err = CL_SUCCESS; + unsigned int num_iter = 1; + for(i = 0; i < num_iter; i++) { + err |= clEnqueueNDRangeKernel(commands, kernel, dim_count, + NULL, global_dim, local_dim, + 0, NULL, NULL); + } + + /* Read back the results from the device to verify the output */ + const size_t origin[3] = {0, 0, 0}; + const size_t region[3] = {size_x, size_y, 1}; + err |= clEnqueueReadImage(commands, src_image, CL_TRUE, origin, region, 0, 0, + output, 0, NULL, NULL); + if (err != CL_SUCCESS) { + log_error("Error: clEnqueueReadBuffer failed\n"); + return err; + } + + /* Verify the correctness of kernel result */ + err = 0; + for (i = 0; i < size; i++) { + if (output[i] != (input[i] + 3)) { + log_error("Error: mismatch at index %d\n", i); + err++; + break; + } + } + + /* Release programs, kernel, contect, and memory objects */ + clReleaseMemObject(src_image); + clReleaseProgram(program); + clReleaseKernel(kernel); + + /* Deallocate arrays */ + free(input); + free(output); + + return err; +} diff --git a/test_conformance/basic/test_simple_image_pitch.c b/test_conformance/basic/test_simple_image_pitch.c new file mode 100644 index 00000000..392fed58 --- /dev/null +++ b/test_conformance/basic/test_simple_image_pitch.c @@ -0,0 +1,153 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" + +int test_simple_read_image_pitch(cl_device_id device, cl_context cl_context_, cl_command_queue q, int num_elements) +{ + cl_int err = CL_SUCCESS; + + size_t imageW = 143; + size_t imageH = 151; + size_t bufferW = 151*4; + size_t bufferH = 151; + + size_t pixel_bytes = 4; + size_t image_bytes = imageW * imageH * pixel_bytes; + + size_t buffer_bytes = bufferW * bufferH; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ); + + char* host_image = (char*)malloc(image_bytes); + memset(host_image,0x1,image_bytes); + + cl_image_format fmt = { 0 }; + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNORM_INT8; + + cl_image_desc desc = { 0 }; + desc.image_type = CL_MEM_OBJECT_IMAGE2D; + desc.image_width = imageW; + desc.image_height = imageH; + + cl_mem image = clCreateImage(cl_context_, CL_MEM_COPY_HOST_PTR|CL_MEM_READ_WRITE, &fmt, &desc, host_image, &err); + test_error(err,"clCreateImage"); + + char* host_buffer = (char*)malloc(buffer_bytes); + memset(host_buffer,0xa,buffer_bytes); + + // Test reading from the image + size_t origin[] = { 0, 0, 0 }; + size_t region[] = { imageW, imageH, 1 }; + + err = clEnqueueReadImage(q, image, CL_TRUE, origin, region, bufferW, 0, host_buffer, 0, NULL, NULL); + test_error(err,"clEnqueueReadImage"); + + size_t errors = 0; + for (size_t j=0;j=imageW*pixel_bytes) && (val != 0xa)) { + log_error("Bad value %x outside image at (byte: %lu, row: %lu)\n",val,i,j); + ++errors; + } + } + } + + test_error(clReleaseMemObject(image),"clReleaseMemObject"); + free(host_image); + free(host_buffer); + + return CL_SUCCESS; +} + +int test_simple_write_image_pitch(cl_device_id device, cl_context cl_context_, cl_command_queue q, int num_elements) +{ + cl_int err = CL_SUCCESS; + + size_t imageW = 143; + size_t imageH = 151; + size_t bufferW = 151*4; + size_t bufferH = 151; + + size_t pixel_bytes = 4; + size_t image_bytes = imageW * imageH * pixel_bytes; + + size_t buffer_bytes = bufferW * bufferH; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ); + + char* host_image = (char*)malloc(image_bytes); + memset(host_image,0x0,image_bytes); + + cl_image_format fmt = { 0 }; + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNORM_INT8; + + cl_image_desc desc = { 0 }; + desc.image_type = CL_MEM_OBJECT_IMAGE2D; + desc.image_width = imageW; + desc.image_height = imageH; + + cl_mem image = clCreateImage(cl_context_, CL_MEM_COPY_HOST_PTR|CL_MEM_READ_WRITE, &fmt, &desc, host_image, &err); + test_error(err,"clCreateImage"); + + char* host_buffer = (char*)malloc(buffer_bytes); + memset(host_buffer,0xa,buffer_bytes); + + // Test reading from the image + size_t origin[] = { 0, 0, 0 }; + size_t region[] = { imageW, imageH, 1 }; + + err = clEnqueueWriteImage(q, image, CL_TRUE, origin, region, bufferW, 0, host_buffer, 0, NULL, NULL); + test_error(err,"clEnqueueWriteImage"); + + size_t mapped_pitch = 0; + char* mapped_image = (char*)clEnqueueMapImage(q, image, CL_TRUE, CL_MAP_READ, origin, region, &mapped_pitch, NULL, 0, NULL, NULL, &err); + test_error(err,"clEnqueueMapImage"); + + size_t errors = 0; + for (size_t j=0;j +#include +#include +#include +#include +#include "procs.h" + + + +cl_int get_type_size( cl_context context, cl_command_queue queue, const char *type, cl_ulong *size ) +{ + const char *sizeof_kernel_code[4] = + { + "", /* optional pragma string */ + "__kernel __attribute__((reqd_work_group_size(1,1,1))) void test_sizeof(__global uint *dst) \n" + "{\n" + " dst[0] = (uint) sizeof( ", type, " );\n" + "}\n" + }; + + cl_program p; + cl_kernel k; + cl_mem m; + cl_uint temp; + + + if (!strncmp(type, "double", 6)) + { + sizeof_kernel_code[0] = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"; + } + else if (!strncmp(type, "half", 4)) + { + sizeof_kernel_code[0] = "#pragma OPENCL EXTENSION cl_khr_fp16 : enable\n"; + } + + cl_int err = create_single_kernel_helper( context, &p, &k, 4, sizeof_kernel_code, "test_sizeof" ); + if( err ) + return err; + + m = clCreateBuffer( context, CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, sizeof( cl_ulong ), size, &err ); + if( NULL == m ) + { + clReleaseProgram( p ); + clReleaseKernel( k ); + log_error("\nclCreateBuffer FAILED\n"); + return err; + } + + err = clSetKernelArg( k, 0, sizeof( cl_mem ), &m ); + if( err ) + { + clReleaseProgram( p ); + clReleaseKernel( k ); + clReleaseMemObject( m ); + log_error("\nclSetKernelArg FAILED\n"); + return err; + } + + err = clEnqueueTask( queue, k, 0, NULL, NULL ); + clReleaseProgram( p ); + clReleaseKernel( k ); + if( err ) + { + clReleaseMemObject( m ); + log_error( "\nclEnqueueTask FAILED\n" ); + return err; + } + + err = clEnqueueReadBuffer( queue, m, CL_TRUE, 0, sizeof( cl_uint ), &temp, 0, NULL, NULL ); + clReleaseMemObject( m ); + if( err ) + log_error( "\nclEnqueueReadBuffer FAILED\n" ); + + *size = (cl_ulong) temp; + + return err; +} + +typedef struct size_table +{ + const char *name; + cl_ulong size; + cl_ulong cl_size; +}size_table; + +const size_table scalar_table[] = +{ + // Fixed size entries from table 6.1 + { "char", 1, sizeof( cl_char ) }, + { "uchar", 1, sizeof( cl_uchar) }, + { "unsigned char", 1, sizeof( cl_uchar) }, + { "short", 2, sizeof( cl_short) }, + { "ushort", 2, sizeof( cl_ushort) }, + { "unsigned short", 2, sizeof( cl_ushort) }, + { "int", 4, sizeof( cl_int ) }, + { "uint", 4, sizeof( cl_uint) }, + { "unsigned int", 4, sizeof( cl_uint) }, + { "float", 4, sizeof( cl_float) }, + { "long", 8, sizeof( cl_long ) }, + { "ulong", 8, sizeof( cl_ulong) }, + { "unsigned long", 8, sizeof( cl_ulong) } +}; + +const size_table vector_table[] = +{ + // Fixed size entries from table 6.1 + { "char", 1, sizeof( cl_char ) }, + { "uchar", 1, sizeof( cl_uchar) }, + { "short", 2, sizeof( cl_short) }, + { "ushort", 2, sizeof( cl_ushort) }, + { "int", 4, sizeof( cl_int ) }, + { "uint", 4, sizeof( cl_uint) }, + { "float", 4, sizeof( cl_float) }, + { "long", 8, sizeof( cl_long ) }, + { "ulong", 8, sizeof( cl_ulong) } +}; + +const char *ptr_table[] = +{ + "void*", + "size_t", + "sizeof(int)", // check return type of sizeof + "ptrdiff_t" +}; + +const char *other_types[] = +{ + "event_t", + "image2d_t", + "image3d_t", + "sampler_t" +}; + +static int IsPowerOfTwo( cl_ulong x ){ return 0 == (x & (x-1)); } + +int test_sizeof(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + size_t i, j; + cl_ulong test; + cl_uint ptr_size = CL_UINT_MAX; + cl_int err = CL_SUCCESS; + + // Check address space size + err = clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS, sizeof(ptr_size), &ptr_size, NULL); + if( err || ptr_size > 64) + { + log_error( "FAILED: Unable to get CL_DEVICE_ADDRESS_BITS for device %p\n", device ); + return -1; + } + log_info( "\tCL_DEVICE_ADDRESS_BITS = %u\n", ptr_size ); + ptr_size /= 8; + + // Test standard scalar sizes + for( i = 0; i < sizeof( scalar_table ) / sizeof( scalar_table[0] ); i++ ) + { + if( ! gHasLong && + (0 == strcmp(scalar_table[i].name, "long") || + 0 == strcmp(scalar_table[i].name, "ulong") || + 0 == strcmp(scalar_table[i].name, "unsigned long"))) + { + log_info("\nLongs are not supported by this device. Skipping test.\t"); + continue; + } + + test = CL_ULONG_MAX; + err = get_type_size( context, queue, scalar_table[i].name, &test ); + if( err ) + return err; + if( test != scalar_table[i].size ) + { + log_error( "\nFAILED: Type %s has size %lld, but expected size %lld!\n", scalar_table[i].name, test, scalar_table[i].size ); + return -1; + } + if( test != scalar_table[i].cl_size ) + { + log_error( "\nFAILED: Type %s has size %lld, but cl_ size is %lld!\n", scalar_table[i].name, test, scalar_table[i].cl_size ); + return -2; + } + log_info( "%16s", scalar_table[i].name ); + } + log_info( "\n" ); + + // Test standard vector sizes + for( j = 2; j <= 16; j *= 2 ) + { + // For each vector size, iterate through types + for( i = 0; i < sizeof( vector_table ) / sizeof( vector_table[0] ); i++ ) + { + if( !gHasLong && + (0 == strcmp(vector_table[i].name, "long") || + 0 == strcmp(vector_table[i].name, "ulong"))) + { + log_info("\nLongs are not supported by this device. Skipping test.\t"); + continue; + } + + char name[32]; + sprintf( name, "%s%ld", vector_table[i].name, j ); + + test = CL_ULONG_MAX; + err = get_type_size( context, queue, name, &test ); + if( err ) + return err; + if( test != j * vector_table[i].size ) + { + log_error( "\nFAILED: Type %s has size %lld, but expected size %lld!\n", name, test, j * vector_table[i].size ); + return -1; + } + if( test != j * vector_table[i].cl_size ) + { + log_error( "\nFAILED: Type %s has size %lld, but cl_ size is %lld!\n", name, test, j * vector_table[i].cl_size ); + return -2; + } + log_info( "%16s", name ); + } + log_info( "\n" ); + } + + //Check that pointer sizes are correct + for( i = 0; i < sizeof( ptr_table ) / sizeof( ptr_table[0] ); i++ ) + { + test = CL_ULONG_MAX; + err = get_type_size( context, queue, ptr_table[i], &test ); + if( err ) + return err; + if( test != ptr_size ) + { + log_error( "\nFAILED: Type %s has size %lld, but expected size %u!\n", ptr_table[i], test, ptr_size ); + return -1; + } + log_info( "%16s", ptr_table[i] ); + } + + // Check that intptr_t is large enough + test = CL_ULONG_MAX; + err = get_type_size( context, queue, "intptr_t", &test ); + if( err ) + return err; + if( test < ptr_size ) + { + log_error( "\nFAILED: intptr_t has size %lld, but must be at least %u!\n", test, ptr_size ); + return -1; + } + if( ! IsPowerOfTwo( test ) ) + { + log_error( "\nFAILED: sizeof(intptr_t) is %lld, but must be a power of two!\n", test ); + return -2; + } + log_info( "%16s", "intptr_t" ); + + // Check that uintptr_t is large enough + test = CL_ULONG_MAX; + err = get_type_size( context, queue, "uintptr_t", &test ); + if( err ) + return err; + if( test < ptr_size ) + { + log_error( "\nFAILED: uintptr_t has size %lld, but must be at least %u!\n", test, ptr_size ); + return -1; + } + if( ! IsPowerOfTwo( test ) ) + { + log_error( "\nFAILED: sizeof(uintptr_t) is %lld, but must be a power of two!\n", test ); + return -2; + } + log_info( "%16s\n", "uintptr_t" ); + + //Check that other types are powers of two + for( i = 0; i < sizeof( other_types ) / sizeof( other_types[0] ); i++ ) + { + if( 0 == strcmp(other_types[i], "image2d_t") && + checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) + { + log_info("\nimages are not supported by this device. Skipping test.\t"); + continue; + } + + if( gIsEmbedded && + 0 == strcmp(other_types[i], "image3d_t") && + checkFor3DImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) + { + log_info("\n3D images are not supported by this device. Skipping test.\t"); + continue; + } + + if( 0 == strcmp(other_types[i], "sampler_t") && + checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) + { + log_info("\nimages are not supported by this device. Skipping test.\t"); + continue; + } + + test = CL_ULONG_MAX; + err = get_type_size( context, queue, other_types[i], &test ); + if( err ) + return err; + if( ! IsPowerOfTwo( test ) ) + { + log_error( "\nFAILED: Type %s has size %lld, which is not a power of two (section 6.1.5)!\n", other_types[i], test ); + return -1; + } + log_info( "%16s", other_types[i] ); + } + log_info( "\n" ); + + + //Check double + if( is_extension_available( device, "cl_khr_fp64" ) ) + { + log_info( "\tcl_khr_fp64:" ); + test = CL_ULONG_MAX; + err = get_type_size( context, queue, "double", &test ); + if( err ) + return err; + if( test != 8 ) + { + log_error( "\nFAILED: double has size %lld, but must be 8!\n", test ); + return -1; + } + log_info( "%16s", "double" ); + + // Test standard vector sizes + for( j = 2; j <= 16; j *= 2 ) + { + char name[32]; + sprintf( name, "double%ld", j ); + + test = CL_ULONG_MAX; + err = get_type_size( context, queue, name, &test ); + if( err ) + return err; + if( test != 8*j ) + { + log_error( "\nFAILED: %s has size %lld, but must be %ld!\n", name, test, 8 * j); + return -1; + } + log_info( "%16s", name ); + } + log_info( "\n" ); + } + + //Check half + if( is_extension_available( device, "cl_khr_fp16" ) ) + { + log_info( "\tcl_khr_fp16:" ); + test = CL_ULONG_MAX; + err = get_type_size( context, queue, "half", &test ); + if( err ) + return err; + if( test != 2 ) + { + log_error( "\nFAILED: half has size %lld, but must be 2!\n", test ); + return -1; + } + log_info( "%16s", "half" ); + + // Test standard vector sizes + for( j = 2; j <= 16; j *= 2 ) + { + char name[32]; + sprintf( name, "half%ld", j ); + + test = CL_ULONG_MAX; + err = get_type_size( context, queue, name, &test ); + if( err ) + return err; + if( test != 2*j ) + { + log_error( "\nFAILED: %s has size %lld, but must be %ld!\n", name, test, 2 * j); + return -1; + } + log_info( "%16s", name ); + } + log_info( "\n" ); + } + + return err; +} + + diff --git a/test_conformance/basic/test_vec_type_hint.c b/test_conformance/basic/test_vec_type_hint.c new file mode 100644 index 00000000..a35d8403 --- /dev/null +++ b/test_conformance/basic/test_vec_type_hint.c @@ -0,0 +1,107 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" + + +static const char *sample_kernel = { + "%s\n" // optional pragma string + "__kernel __attribute__((vec_type_hint(%s%s))) void sample_test(__global int *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = src[tid];\n" + "\n" + "}\n" +}; + +int test_vec_type_hint(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + int vec_type_index, vec_size_index; + + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble }; + const char *size_names[] = {"", "2", "4", "8", "16"}; + char *program_source; + + program_source = (char*)malloc(sizeof(char)*4096); + + for (vec_type_index=0; vec_type_index<10; vec_type_index++) { + if (vecType[vec_type_index] == kDouble) { + if (!is_extension_available(deviceID, "cl_khr_fp64")) { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + continue; + } + log_info("Testing doubles.\n"); + } + + if (vecType[vec_type_index] == kLong || vecType[vec_type_index] == kULong) + { + if (!gHasLong) + { + log_info("Extension cl_khr_int64 not supported; skipping long tests.\n"); + continue; + } + } + + for (vec_size_index=0; vec_size_index<5; vec_size_index++) { + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper in, out; + size_t global[] = {1,1,1}; + + log_info("Testing __attribute__((vec_type_hint(%s%s))...\n", get_explicit_type_name(vecType[vec_type_index]), size_names[vec_size_index]); + + program_source[0] = '\0'; + sprintf(program_source, sample_kernel, + (vecType[vec_type_index] == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name(vecType[vec_type_index]), size_names[vec_size_index]); + + error = create_single_kernel_helper( context, &program, &kernel, 1, (const char**)&program_source, "sample_test" ); + if( error != 0 ) + return error; + + in = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(cl_int)*10, NULL, &error); + test_error(error, "clCreateBuffer failed"); + out = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(cl_int)*10, NULL, &error); + test_error(error, "clCreateBuffer failed"); + + error = clSetKernelArg(kernel, 0, sizeof(in), &in); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 1, sizeof(out), &out); + test_error(error, "clSetKernelArg failed"); + + error = clEnqueueNDRangeKernel(queue, kernel, 3, NULL, global, NULL, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + error = clFinish(queue); + test_error(error, "clFinish failed"); + } + } + + free(program_source); + + return 0; +} diff --git a/test_conformance/basic/test_vector_creation.cpp b/test_conformance/basic/test_vector_creation.cpp new file mode 100644 index 00000000..9ab0103a --- /dev/null +++ b/test_conformance/basic/test_vector_creation.cpp @@ -0,0 +1,406 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/errorHelpers.h" + + + + +#define DEBUG 0 +#define DEPTH 16 +// Limit the maximum code size for any given kernel. +#define MAX_CODE_SIZE (1024*32) + +const int sizes[] = {1, 2, 3, 4, 8, 16, -1, -1, -1, -1}; +const char *size_names[] = {"", "2", "3", "4", "8", "16" , "!!a", "!!b", "!!c", "!!d"}; + +// Creates a kernel by enumerating all possible ways of building the vector out of vloads +// skip_to_results will skip results up to a given number. If the amount of code generated +// is greater than MAX_CODE_SIZE, this function will return the number of results used, +// which can then be used as the skip_to_result value to continue where it left off. +int create_kernel(ExplicitType type, int output_size, char *program, int *number_of_results, int skip_to_result) { + + int number_of_sizes; + + switch (output_size) { + case 1: + number_of_sizes = 1; + break; + case 2: + number_of_sizes = 2; + break; + case 3: + number_of_sizes = 3; + break; + case 4: + number_of_sizes = 4; + break; + case 8: + number_of_sizes = 5; + break; + case 16: + number_of_sizes = 6; + break; + default: + log_error("Invalid size: %d\n", output_size); + return -1; + } + + int total_results = 0; + int current_result = 0; + int total_vloads = 0; + int total_program_length = 0; + int aborted_due_to_size = 0; + + if (skip_to_result < 0) + skip_to_result = 0; + + // The line of code for the vector creation + char line[1024]; + // Keep track of what size vector we are using in each position so we can iterate through all fo them + int pos[DEPTH]; + int max_size = output_size; + if (DEBUG > 1) log_info("max_size: %d\n", max_size); + + program[0] = '\0'; + sprintf(program, "%s\n__kernel void test_vector_creation(__global %s *src, __global %s%s *result) {\n", + type == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name(type), get_explicit_type_name(type), ( number_of_sizes == 3 ) ? "" : size_names[number_of_sizes-1]); + total_program_length += (int)strlen(program); + + char storePrefix[ 128 ], storeSuffix[ 128 ]; + + // Start out trying sizes 1,1,1,1,1... + for (int i=0; i 1) { + log_info("pos size[] = ["); + for (int k=0; k 1) log_info("vloads: %d, size_so_far:%d\n", vloads, size_so_far); + + // If they did not fit the required size exactly it is too long, so there is no point in checking any other combinations + // of the sizes to the right. Prune them from the search. + if (size_so_far != max_size) { + // Zero all the sizes to the right + for (int k=vloads+1; k=0; d--) { + pos[d]++; + if (pos[d] >= number_of_sizes) { + pos[d] = 0; + if (d == 0) { + // If we rolled over then we are done + done = 1; + break; + } + } else { + break; + } + } + // Go on to the next size since this one (and all others "under" it) didn't fit + continue; + } + + + // Generate the actual load line if we are building this part + line[0]= '\0'; + if (skip_to_result == 0 || total_results >= skip_to_result) { + if( number_of_sizes == 3 ) + { + sprintf( storePrefix, "vstore3( " ); + sprintf( storeSuffix, ", %d, result )", current_result ); + } + else + { + sprintf( storePrefix, "result[%d] = ", current_result ); + storeSuffix[ 0 ] = 0; + } + + sprintf(line, "\t%s(%s%d)(", storePrefix, get_explicit_type_name(type), output_size); + current_result++; + + int offset = 0; + for (int i=0; i MAX_CODE_SIZE) { + aborted_due_to_size = 1; + done = 1; + } + + + if (DEBUG) log_info("line is: %s", line); + + // If we did not use all of them, then we ignore any changes further to the right. + // We do this by causing those loops to skip on the next iteration. + if (vloads < DEPTH) { + if (DEBUG > 1) log_info("done with this depth\n"); + for (int k=vloads; k=0; d--) { + pos[d]++; + if (pos[d] >= number_of_sizes) { + pos[d] = 0; + if (d == 0) { + // If we rolled over at the far-left then we are done + done = 1; + break; + } + } else { + break; + } + } + if (done) + break; + + // Continue until we are done. + } + strcat(program, "}\n\n"); //log_info("%s\n", program); + total_program_length += 3; + if (DEBUG) log_info("\t\t(Program for vector type %s%s contains %d vector creations, of total program length %gkB, with a total of %d vloads.)\n", + get_explicit_type_name(type), size_names[number_of_sizes-1], total_results, total_program_length/1024.0, total_vloads); + *number_of_results = current_result; + if (aborted_due_to_size) + return total_results; + return 0; +} + + + + +int test_vector_creation(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble }; + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16}; + + char *program_source; + int error; + int total_errors = 0; + + cl_int input_data_int[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + cl_double input_data_double[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + void *input_data_converted; + void *output_data; + + int number_of_results;; + + input_data_converted = malloc(sizeof(cl_double)*16); + program_source = (char*)malloc(sizeof(char)*1024*1024*4); + + // Iterate over all the types + for (int type_index=0; type_index<10; type_index++) { + if(!gHasLong && ((vecType[type_index] == kLong) || (vecType[type_index] == kULong))) + { + log_info("Long/ULong data type not supported on this device\n"); + continue; + } + + clMemWrapper input; + + if (vecType[type_index] == kDouble) { + if (!is_extension_available(deviceID, "cl_khr_fp64")) { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + continue; + } + log_info("Testing doubles.\n"); + } + + // Convert the data to the right format for the test. + memset(input_data_converted, 0xff, sizeof(cl_double)*16); + if (vecType[type_index] != kDouble) { + for (int j=0; j<16; j++) { + convert_explicit_value(&input_data_int[j], ((char*)input_data_converted)+get_explicit_type_size(vecType[type_index])*j, + kInt, 0, kRoundToEven, vecType[type_index]); + } + } else { + memcpy(input_data_converted, &input_data_double, sizeof(cl_double)*16); + } + + input = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, get_explicit_type_size(vecType[type_index])*16, + (vecType[type_index] != kDouble) ? input_data_converted : input_data_double, &error); + if (error) { + print_error(error, "clCreateBuffer failed"); + total_errors++; + continue; + } + + // Iterate over all the vector sizes. + for (int size_index=1; size_index< 5; size_index++) { + size_t global[] = {1,1,1}; + int number_generated = -1; + int previous_number_generated = 0; + + log_info("Testing %s%s...\n", get_explicit_type_name(vecType[type_index]), size_names[size_index]); + while (number_generated != 0) { + clMemWrapper output; + clKernelWrapper kernel; + clProgramWrapper program; + + number_generated = create_kernel(vecType[type_index], vecSizes[size_index], program_source, &number_of_results, number_generated); + if (number_generated != 0) { + if (previous_number_generated == 0) + log_info("Code size greater than %gkB; splitting test into multiple kernels.\n", MAX_CODE_SIZE/1024.0); + log_info("\tExecuting vector permutations %d to %d...\n", previous_number_generated, number_generated-1); + } + + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&program_source, "test_vector_creation"); + if (error) { + log_error("create_single_kernel_helper failed.\n"); + total_errors++; + break; + } + + output = clCreateBuffer(context, CL_MEM_WRITE_ONLY, + number_of_results*get_explicit_type_size(vecType[type_index])*vecSizes[size_index], + NULL, &error); + if (error) { + print_error(error, "clCreateBuffer failed"); + total_errors++; + break; + } + + error = clSetKernelArg(kernel, 0, sizeof(input), &input); + error |= clSetKernelArg(kernel, 1, sizeof(output), &output); + if (error) { + print_error(error, "clSetKernelArg failed"); + total_errors++; + break; + } + + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global, NULL, 0, NULL, NULL); + if (error) { + print_error(error, "clEnqueueNDRangeKernel failed"); + total_errors++; + break; + } + + error = clFinish(queue); + if (error) { + print_error(error, "clFinish failed"); + total_errors++; + break; + } + + output_data = malloc(number_of_results*get_explicit_type_size(vecType[type_index])*vecSizes[size_index]); + if (output_data == NULL) { + log_error("Failed to allocate memory for output data.\n"); + total_errors++; + break; + } + memset(output_data, 0xff, number_of_results*get_explicit_type_size(vecType[type_index])*vecSizes[size_index]); + error = clEnqueueReadBuffer(queue, output, CL_TRUE, 0, + number_of_results*get_explicit_type_size(vecType[type_index])*vecSizes[size_index], + output_data, 0, NULL, NULL); + if (error) { + print_error(error, "clEnqueueReadBuffer failed"); + total_errors++; + free(output_data); + break; + } + + // Check the results + char *res = (char *)output_data; + char *exp = (char *)input_data_converted; + for (int i=0; i +#include +#include +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/errorHelpers.h" + +// Outputs debug information for stores +#define DEBUG 0 +// Forces stores/loads to be done with offsets = tid +#define LINEAR_OFFSETS 0 +#define NUM_LOADS 512 + +static const char *doubleExtensionPragma = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"; + +#pragma mark -------------------- vload harness -------------------------- + +typedef void (*create_vload_program_fn)( char *destBuffer, size_t inBufferSize, ExplicitType type, size_t inVectorSize, size_t outVectorSize ); + +int test_vload( cl_device_id device, cl_context context, cl_command_queue queue, ExplicitType type, unsigned int vecSize, + create_vload_program_fn createFn, size_t bufferSize, MTdata d ) +{ + int error; + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 4 ]; + const size_t numLoads = (DEBUG) ? 16 : NUM_LOADS; + + if (DEBUG) bufferSize = (bufferSize < 128) ? bufferSize : 128; + + size_t threads[ 1 ], localThreads[ 1 ]; + clProtectedArray inBuffer( bufferSize ); + char programSrc[ 10240 ]; + cl_uint offsets[ numLoads ], alignmentOffsets[ numLoads ]; + size_t numElements, typeSize, i; + unsigned int outVectorSize; + + + typeSize = get_explicit_type_size( type ); + numElements = bufferSize / ( typeSize * vecSize ); + bufferSize = numElements * typeSize * vecSize; // To account for rounding + + if (DEBUG) log_info("Testing: numLoads: %d, typeSize: %d, vecSize: %d, numElements: %d, bufferSize: %d\n", (int)numLoads, (int)typeSize, vecSize, (int)numElements, (int)bufferSize); + + // Create some random input data and random offsets to load from + generate_random_data( type, numElements * vecSize, d, (void *)inBuffer ); + for( i = 0; i < numLoads; i++ ) + { + offsets[ i ] = (cl_uint)random_in_range( 0, (int)numElements - 1, d ); + if( offsets[ i ] < numElements - 2 ) + alignmentOffsets[ i ] = (cl_uint)random_in_range( 0, (int)vecSize - 1, d ); + else + alignmentOffsets[ i ] = 0; + if (LINEAR_OFFSETS) offsets[i] = (cl_uint)i; + } + if (LINEAR_OFFSETS) log_info("Offsets set to thread IDs to simplify output.\n"); + + // 32-bit fixup + outVectorSize = vecSize; + + // Declare output buffers now +#if !(defined(_WIN32) && defined(_MSC_VER)) + char outBuffer[ numLoads * typeSize * outVectorSize ]; + char referenceBuffer[ numLoads * typeSize * vecSize ]; +#else + char* outBuffer = (char*)_malloca(numLoads * typeSize * outVectorSize * sizeof(cl_char)); + char* referenceBuffer = (char*)_malloca(numLoads * typeSize * vecSize * sizeof(cl_char)); +#endif + + // Create the program + + + createFn( programSrc, numElements, type, vecSize, outVectorSize); + + // Create our kernel + const char *ptr = programSrc; + + error = create_single_kernel_helper( context, &program, &kernel, 1, &ptr, "test_fn" ); + test_error( error, "Unable to create testing kernel" ); + if (DEBUG) log_info("Kernel: \n%s\n", programSrc); + + // Get the number of args to differentiate the kernels with local storage. (They have 5) + cl_uint numArgs; + error = clGetKernelInfo(kernel, CL_KERNEL_NUM_ARGS, sizeof(numArgs), &numArgs, NULL); + test_error( error, "clGetKernelInfo failed"); + + // Set up parameters + streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, bufferSize, (void *)inBuffer, &error ); + test_error( error, "Unable to create kernel stream" ); + streams[ 1 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, numLoads*sizeof(offsets[0]), offsets, &error ); + test_error( error, "Unable to create kernel stream" ); + streams[ 2 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, numLoads*sizeof(alignmentOffsets[0]), alignmentOffsets, &error ); + test_error( error, "Unable to create kernel stream" ); + streams[ 3 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, numLoads*typeSize*outVectorSize, (void *)outBuffer, &error ); + test_error( error, "Unable to create kernel stream" ); + + // Set parameters and run + if (numArgs == 5) { + // We need to set the size of the local storage + error = clSetKernelArg(kernel, 0, bufferSize, NULL); + test_error( error, "clSetKernelArg for buffer failed"); + for( i = 0; i < 4; i++ ) + { + error = clSetKernelArg( kernel, (int)i+1, sizeof( streams[ i ] ), &streams[ i ] ); + test_error( error, "Unable to set kernel argument" ); + } + } else { + // No local storage + for( i = 0; i < 4; i++ ) + { + error = clSetKernelArg( kernel, (int)i, sizeof( streams[ i ] ), &streams[ i ] ); + test_error( error, "Unable to set kernel argument" ); + } + } + + threads[ 0 ] = numLoads; + error = get_max_common_work_group_size( context, kernel, threads[ 0 ], &localThreads[ 0 ] ); + test_error( error, "Unable to get local thread size" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to exec kernel" ); + + // Get the results + error = clEnqueueReadBuffer( queue, streams[ 3 ], CL_TRUE, 0, numLoads * typeSize * outVectorSize * sizeof(cl_char), (void *)outBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + + // Create the reference results + memset( referenceBuffer, 0, numLoads * typeSize * vecSize * sizeof(cl_char)); + for( i = 0; i < numLoads; i++ ) + { + memcpy( referenceBuffer + i * typeSize * vecSize, ( (char *)(void *)inBuffer ) + ( ( offsets[ i ] * vecSize ) + alignmentOffsets[ i ] ) * typeSize, + typeSize * vecSize ); + } + + // Validate the results now + char *expected = referenceBuffer; + char *actual = outBuffer; + char *in = (char *)(void *)inBuffer; + + if (DEBUG) { + log_info("Memory contents:\n"); + for (i=0; i 10240 ) + localSize = 10240; + if (localSize > 4096) + localSize -= 2048; + else + localSize /= 2; + + return test_vloadset( device, context, queue, create_local_load_code, (size_t)localSize ); +} + + +void create_constant_load_code( char *destBuffer, size_t inBufferSize, ExplicitType type, size_t inVectorSize, size_t outVectorSize ) +{ + const char *pattern = + "%s%s" + "__kernel void test_fn( __constant %s *src, __global uint *offsets, __global uint *alignmentOffsets, __global %s%d *results )\n" + "{\n" + " int tid = get_global_id( 0 );\n" + " %s%d tmp = vload%d( offsets[ tid ], ( (__constant %s *) src ) + alignmentOffsets[ tid ] );\n" + " results[ tid ] = tmp;\n" + "}\n"; + + const char *patternV3 = + "%s%s" + "__kernel void test_fn( __constant %s *src, __global uint *offsets, __global uint *alignmentOffsets, __global %s *results )\n" + "{\n" + " int tid = get_global_id( 0 );\n" + " %s3 tmp = vload3( offsets[ tid ], ( (__constant %s *) src ) + alignmentOffsets[ tid ] );\n" + " results[ 3*tid ] = tmp.s0;\n" + " results[ 3*tid+1 ] = tmp.s1;\n" + " results[ 3*tid+2 ] = tmp.s2;\n" + "}\n"; + + const char *typeName = get_explicit_type_name(type); + if(inVectorSize == 3) { + sprintf( destBuffer, patternV3, + type == kDouble ? doubleExtensionPragma : "", + "", + typeName, typeName, typeName, + typeName ); + } else { + sprintf( destBuffer, pattern, + type == kDouble ? doubleExtensionPragma : "", + "", + typeName, typeName, (int)outVectorSize, typeName, (int)inVectorSize, + (int)inVectorSize, typeName ); + } +} + +int test_vload_constant(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + // Determine the max size of a local buffer that we can test against + cl_ulong maxSize; + int error = clGetDeviceInfo( device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof( maxSize ), &maxSize, NULL ); + test_error( error, "Unable to get max size of constant memory buffer" ); + if( maxSize > 10240 ) + maxSize = 10240; + if (maxSize > 4096) + maxSize -= 2048; + else + maxSize /= 2; + + return test_vloadset( device, context, queue, create_constant_load_code, (size_t)maxSize ); +} + + +void create_private_load_code( char *destBuffer, size_t inBufferSize, ExplicitType type, size_t inVectorSize, size_t outVectorSize ) +{ + const char *pattern = + "%s%s" + // Private memory is unique per thread, unlike local storage which is unique per local work group. Which means + // for this test, we have to copy the entire test buffer into private storage ON EACH THREAD to be an effective test + "#define PRIV_TYPE %s%d\n" + "#define PRIV_SIZE %d\n" + "__kernel void test_fn( __global %s%d *src, __global uint *offsets, __global uint *alignmentOffsets, __global %s%d *results )\n" + "{\n" + " __private PRIV_TYPE sPrivateStorage[ PRIV_SIZE ];\n" + " int tid = get_global_id( 0 );\n" + "\n" + " for( int i = 0; i < %d; i++ )\n" + " sPrivateStorage[ i ] = src[ i ];\n" + // Note: unlike the local test, each thread runs the above copy loop independently, so nobody needs to wait for + // anybody else to sync up + "\n" + " %s%d tmp = vload%d( offsets[ tid ], ( (__private %s *) sPrivateStorage ) + alignmentOffsets[ tid ] );\n" + " results[ tid ] = tmp;\n" + "}\n"; + + const char *patternV3 = + "%s%s" + // Private memory is unique per thread, unlike local storage which is unique per local work group. Which means + // for this test, we have to copy the entire test buffer into private storage ON EACH THREAD to be an effective test + "#define PRIV_TYPE %s\n" + "#define PRIV_SIZE %d\n" + "__kernel void test_fn( __global %s *src, __global uint *offsets, __global uint *alignmentOffsets, __global %s *results )\n" + "{\n" + " __private PRIV_TYPE sPrivateStorage[ PRIV_SIZE ];\n" + " int tid = get_global_id( 0 );\n" + "\n" + " for( int i = 0; i < PRIV_SIZE; i++ )\n" + " {\n" + " sPrivateStorage[ i ] = src[ i ];\n" + " }\n" + // Note: unlike the local test, each thread runs the above copy loop independently, so nobody needs to wait for + // anybody else to sync up + "\n" + " %s3 tmp = vload3( offsets[ tid ], ( sPrivateStorage ) + alignmentOffsets[ tid ] );\n" + " results[ 3*tid ] = tmp.s0;\n" + " results[ 3*tid+1 ] = tmp.s1;\n" + " results[ 3*tid+2 ] = tmp.s2;\n" + "}\n"; + + const char *typeName = get_explicit_type_name(type); + if(inVectorSize ==3) { + sprintf( destBuffer, patternV3, + type == kDouble ? doubleExtensionPragma : "", + "", + typeName, 3*((int)inBufferSize), + typeName, typeName, + typeName ); + // log_info("Src is \"\n%s\n\"\n", destBuffer); + } else { + sprintf( destBuffer, pattern, + type == kDouble ? doubleExtensionPragma : "", + "", + typeName, (int)inVectorSize, (int)inBufferSize, + typeName, (int)inVectorSize, typeName, (int)outVectorSize, + (int)inBufferSize, + typeName, (int)inVectorSize, (int)inVectorSize, typeName ); + } +} + +int test_vload_private(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + // We have no idea how much actual private storage is available, so just pick a reasonable value, + // which is that we can fit at least two 16-element long, which is 2*8 bytes * 16 = 256 bytes + return test_vloadset( device, context, queue, create_private_load_code, 256 ); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark -------------------- vstore harness -------------------------- + +typedef void (*create_vstore_program_fn)( char *destBuffer, size_t inBufferSize, ExplicitType type, size_t inVectorSize ); + +int test_vstore( cl_device_id device, cl_context context, cl_command_queue queue, ExplicitType type, unsigned int vecSize, + create_vstore_program_fn createFn, size_t bufferSize, MTdata d ) +{ + int error; + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 3 ]; + + size_t threads[ 1 ], localThreads[ 1 ]; + + size_t numElements, typeSize, numStores = (DEBUG) ? 16 : NUM_LOADS; + + if (DEBUG) + bufferSize = (bufferSize < 128) ? bufferSize : 128; + + typeSize = get_explicit_type_size( type ); + numElements = bufferSize / ( typeSize * vecSize ); + bufferSize = numElements * typeSize * vecSize; // To account for rounding + if( numStores > numElements * 2 / 3 ) + { + // Note: unlike load, we have to restrict the # of stores here, since all offsets must be unique for our test + // (Plus, we leave some room for extra values to make sure didn't get written) + numStores = numElements * 2 / 3; + if( numStores < 1 ) + numStores = 1; + } + if (DEBUG) + log_info("Testing: numStores: %d, typeSize: %d, vecSize: %d, numElements: %d, bufferSize: %d\n", (int)numStores, (int)typeSize, vecSize, (int)numElements, (int)bufferSize); +#if !(defined(_WIN32) && defined(_MSC_VER)) + cl_uint offsets[ numStores ]; +#else + cl_uint* offsets = (cl_uint*)_malloca(numStores * sizeof(cl_uint)); +#endif + char programSrc[ 10240 ]; + size_t i; + +#if !(defined(_WIN32) && defined(_MSC_VER)) + char inBuffer[ numStores * typeSize * vecSize ]; +#else + char* inBuffer = (char*)_malloca( numStores * typeSize * vecSize * sizeof(cl_char)); +#endif + clProtectedArray outBuffer( numElements * typeSize * vecSize ); +#if !(defined(_WIN32) && defined(_MSC_VER)) + char referenceBuffer[ numElements * typeSize * vecSize ]; +#else + char* referenceBuffer = (char*)_malloca(numElements * typeSize * vecSize * sizeof(cl_char)); +#endif + + // Create some random input data and random offsets to load from + generate_random_data( type, numStores * vecSize, d, (void *)inBuffer ); + + // Note: make sure no two offsets are the same, otherwise the output would depend on + // the order that threads ran in, and that would be next to impossible to verify +#if !(defined(_WIN32) && defined(_MSC_VER)) + char flags[ numElements ]; +#else + char* flags = (char*)_malloca( numElements * sizeof(char)); +#endif + + memset( flags, 0, numElements * sizeof(char) ); + for( i = 0; i < numStores; i++ ) + { + do + { + offsets[ i ] = (cl_uint)random_in_range( 0, (int)numElements - 2, d ); // Note: keep it one vec below the end for offset testing + } while( flags[ offsets[ i ] ] != 0 ); + flags[ offsets[ i ] ] = -1; + if (LINEAR_OFFSETS) + offsets[i] = (int)i; + } + if (LINEAR_OFFSETS) + log_info("Offsets set to thread IDs to simplify output.\n"); + + createFn( programSrc, numElements, type, vecSize ); + + // Create our kernel + const char *ptr = programSrc; + error = create_single_kernel_helper( context, &program, &kernel, 1, &ptr, "test_fn" ); + test_error( error, "Unable to create testing kernel" ); + if (DEBUG) log_info("Kernel: \n%s\n", programSrc); + + // Get the number of args to differentiate the kernels with local storage. (They have 5) + cl_uint numArgs; + error = clGetKernelInfo(kernel, CL_KERNEL_NUM_ARGS, sizeof(numArgs), &numArgs, NULL); + test_error( error, "clGetKernelInfo failed"); + + // Set up parameters + streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, numStores * typeSize * vecSize * sizeof(cl_char), (void *)inBuffer, &error ); + test_error( error, "Unable to create kernel stream" ); + streams[ 1 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, numStores * sizeof(cl_uint), offsets, &error ); + test_error( error, "Unable to create kernel stream" ); + streams[ 2 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, numElements * typeSize * vecSize, (void *)outBuffer, &error ); + test_error( error, "Unable to create kernel stream" ); + + // Set parameters and run + if (numArgs == 5) + { + // We need to set the size of the local storage + error = clSetKernelArg(kernel, 0, bufferSize, NULL); + test_error( error, "clSetKernelArg for buffer failed"); + for( i = 0; i < 3; i++ ) + { + error = clSetKernelArg( kernel, (int)i+1, sizeof( streams[ i ] ), &streams[ i ] ); + test_error( error, "Unable to set kernel argument" ); + } + } + else + { + // No local storage + for( i = 0; i < 3; i++ ) + { + error = clSetKernelArg( kernel, (int)i, sizeof( streams[ i ] ), &streams[ i ] ); + if (error) + log_info("%s\n", programSrc); + test_error( error, "Unable to set kernel argument" ); + } + } + + threads[ 0 ] = numStores; + error = get_max_common_work_group_size( context, kernel, threads[ 0 ], &localThreads[ 0 ] ); + test_error( error, "Unable to get local thread size" ); + + // Run in a loop, changing the address offset from 0 to ( vecSize - 1 ) each time, since + // otherwise stores might overlap each other, and it'd be a nightmare to test! + for( cl_uint addressOffset = 0; addressOffset < vecSize; addressOffset++ ) + { + if (DEBUG) + log_info("\tstore addressOffset is %d, executing with threads %d\n", addressOffset, (int)threads[0]); + + // Clear the results first + memset( outBuffer, 0, numElements * typeSize * vecSize ); + error = clEnqueueWriteBuffer( queue, streams[ 2 ], CL_TRUE, 0, numElements * typeSize * vecSize, (void *)outBuffer, 0, NULL, NULL ); + test_error( error, "Unable to erase result stream" ); + + // Set up the new offset and run + if (numArgs == 5) + error = clSetKernelArg( kernel, 3+1, sizeof( cl_uint ), &addressOffset ); + else + error = clSetKernelArg( kernel, 3, sizeof( cl_uint ), &addressOffset ); + test_error( error, "Unable to set address offset argument" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to exec kernel" ); + + // Get the results + error = clEnqueueReadBuffer( queue, streams[ 2 ], CL_TRUE, 0, numElements * typeSize * vecSize, (void *)outBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + + // Create the reference results + memset( referenceBuffer, 0, numElements * typeSize * vecSize * sizeof(cl_char) ); + for( i = 0; i < numStores; i++ ) + { + memcpy( referenceBuffer + ( ( offsets[ i ] * vecSize ) + addressOffset ) * typeSize, inBuffer + i * typeSize * vecSize, typeSize * vecSize ); + } + + // Validate the results now + char *expected = referenceBuffer; + char *actual = (char *)(void *)outBuffer; + + if (DEBUG) + { + log_info("Memory contents:\n"); + for (i=0; i>2) ], offsets[ tid ], destBuffer + alignmentOffset );\n" + " } else {\n" + " vstore3( vload3(tid, (__global %s *)srcValues), offsets[ tid ], destBuffer + alignmentOffset );\n" + " }\n" + "}\n"; + + const char *typeName = get_explicit_type_name(type); + + if(inVectorSize == 3) { + sprintf( destBuffer, patternV3, + type == kDouble ? doubleExtensionPragma : "", + typeName, typeName, typeName); + + } else { + sprintf( destBuffer, pattern, + type == kDouble ? doubleExtensionPragma : "", + typeName, (int)inVectorSize, typeName, (int)inVectorSize ); + } + // if(inVectorSize == 3 || inVectorSize == 4) { + // log_info("\n----\n%s\n----\n", destBuffer); + // } +} + +int test_vstore_global(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + return test_vstoreset( device, context, queue, create_global_store_code, 10240 ); +} + + +void create_local_store_code( char *destBuffer, size_t inBufferSize, ExplicitType type, size_t inVectorSize ) +{ + const char *pattern = + "%s" + "\n" + "__kernel void test_fn(__local %s%d *sSharedStorage, __global %s%d *srcValues, __global uint *offsets, __global %s%d *destBuffer, uint alignmentOffset )\n" + "{\n" + " int tid = get_global_id( 0 );\n" + // We need to zero the shared storage since any locations we don't write to will have garbage otherwise. + " sSharedStorage[ offsets[tid] ] = (%s%d)(%s)0;\n" + " sSharedStorage[ offsets[tid] +1 ] = sSharedStorage[ offsets[tid] ];\n" + " barrier( CLK_LOCAL_MEM_FENCE );\n" + "\n" + " vstore%d( srcValues[ tid ], offsets[ tid ], ( (__local %s *)sSharedStorage ) + alignmentOffset );\n" + "\n" + // Note: Once all threads are done vstore'ing into our shared storage, we then copy into the global output + // buffer, but we have to make sure ALL threads are done vstore'ing before we do the copy + " barrier( CLK_LOCAL_MEM_FENCE );\n" + "\n" + // Note: we only copy the relevant portion of our local storage over to the dest buffer, because + // otherwise, local threads would be overwriting results from other local threads + " int i;\n" + " __local %s *sp = (__local %s*) (sSharedStorage + offsets[tid]) + alignmentOffset;\n" + " __global %s *dp = (__global %s*) (destBuffer + offsets[tid]) + alignmentOffset;\n" + " for( i = 0; (size_t)i < sizeof( sSharedStorage[0]) / sizeof( *sp ); i++ ) \n" + " dp[i] = sp[i];\n" + "}\n"; + + const char *patternV3 = + "%s" + "\n" + "__kernel void test_fn(__local %s *sSharedStorage, __global %s *srcValues, __global uint *offsets, __global %s *destBuffer, uint alignmentOffset )\n" + "{\n" + " int tid = get_global_id( 0 );\n" + // We need to zero the shared storage since any locations we don't write to will have garbage otherwise. + " sSharedStorage[ 3*offsets[tid] ] = (%s)0;\n" + " sSharedStorage[ 3*offsets[tid] +1 ] = \n" + " sSharedStorage[ 3*offsets[tid] ];\n" + " sSharedStorage[ 3*offsets[tid] +2 ] = \n" + " sSharedStorage[ 3*offsets[tid]];\n" + " sSharedStorage[ 3*offsets[tid] +3 ] = \n" + " sSharedStorage[ 3*offsets[tid]];\n" + " sSharedStorage[ 3*offsets[tid] +4 ] = \n" + " sSharedStorage[ 3*offsets[tid] ];\n" + " sSharedStorage[ 3*offsets[tid] +5 ] = \n" + " sSharedStorage[ 3*offsets[tid]];\n" + " barrier( CLK_LOCAL_MEM_FENCE );\n" + "\n" + " vstore3( vload3(tid,srcValues), offsets[ tid ], sSharedStorage + alignmentOffset );\n" + "\n" + // Note: Once all threads are done vstore'ing into our shared storage, we then copy into the global output + // buffer, but we have to make sure ALL threads are done vstore'ing before we do the copy + " barrier( CLK_LOCAL_MEM_FENCE );\n" + "\n" + // Note: we only copy the relevant portion of our local storage over to the dest buffer, because + // otherwise, local threads would be overwriting results from other local threads + " int i;\n" + " __local %s *sp = (sSharedStorage + 3*offsets[tid]) + alignmentOffset;\n" + " __global %s *dp = (destBuffer + 3*offsets[tid]) + alignmentOffset;\n" + " for( i = 0; i < 3; i++ ) \n" + " dp[i] = sp[i];\n" + "}\n"; + + const char *typeName = get_explicit_type_name(type); + if(inVectorSize == 3) { + sprintf( destBuffer, patternV3, + type == kDouble ? doubleExtensionPragma : "", + typeName, + typeName, + typeName, typeName, + typeName, typeName, typeName ); + } else { + sprintf( destBuffer, pattern, + type == kDouble ? doubleExtensionPragma : "", + typeName, (int)inVectorSize, + typeName, (int)inVectorSize, typeName, (int)inVectorSize, + typeName, (int)inVectorSize, typeName, + (int)inVectorSize, typeName, typeName, + typeName, typeName, typeName ); + } + // log_info(destBuffer); +} + +int test_vstore_local(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + // Determine the max size of a local buffer that we can test against + cl_ulong localSize; + int error = clGetDeviceInfo( device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof( localSize ), &localSize, NULL ); + test_error( error, "Unable to get max size of local memory buffer" ); + if( localSize > 10240 ) + localSize = 10240; + if (localSize > 4096) + localSize -= 2048; + else + localSize /= 2; + return test_vstoreset( device, context, queue, create_local_store_code, (size_t)localSize ); +} + + +void create_private_store_code( char *destBuffer, size_t inBufferSize, ExplicitType type, size_t inVectorSize ) +{ + const char *pattern = + "%s" + // Private memory is unique per thread, unlike local storage which is unique per local work group. Which means + // for this test, we have to copy the entire test buffer into private storage ON EACH THREAD to be an effective test + "\n" + "__kernel void test_fn( __global %s%d *srcValues, __global uint *offsets, __global %s%d *destBuffer, uint alignmentOffset )\n" + "{\n" + " __private %s%d sPrivateStorage[ %d ];\n" + " int tid = get_global_id( 0 );\n" + // We need to zero the shared storage since any locations we don't write to will have garbage otherwise. + " sPrivateStorage[tid] = (%s%d)(%s)0;\n" + "\n" + " vstore%d( srcValues[ tid ], offsets[ tid ], ( (__private %s *)sPrivateStorage ) + alignmentOffset );\n" + "\n" + // Note: we only copy the relevant portion of our local storage over to the dest buffer, because + // otherwise, local threads would be overwriting results from other local threads + " uint i;\n" + " __private %s *sp = (__private %s*) (sPrivateStorage + offsets[tid]) + alignmentOffset;\n" + " __global %s *dp = (__global %s*) (destBuffer + offsets[tid]) + alignmentOffset;\n" + " for( i = 0; i < sizeof( sPrivateStorage[0]) / sizeof( *sp ); i++ ) \n" + " dp[i] = sp[i];\n" + "}\n"; + + + const char *patternV3 = + "%s" + // Private memory is unique per thread, unlike local storage which is unique per local work group. Which means + // for this test, we have to copy the entire test buffer into private storage ON EACH THREAD to be an effective test + "\n" + "__kernel void test_fn( __global %s *srcValues, __global uint *offsets, __global %s3 *destBuffer, uint alignmentOffset )\n" + "{\n" + " __private %s3 sPrivateStorage[ %d ];\n" // keep this %d + " int tid = get_global_id( 0 );\n" + // We need to zero the shared storage since any locations we don't write to will have garbage otherwise. + " sPrivateStorage[tid] = (%s3)(%s)0;\n" + "\n" + + " vstore3( vload3(tid,srcValues), offsets[ tid ], ( (__private %s *)sPrivateStorage ) + alignmentOffset );\n" + "\n" + // Note: we only copy the relevant portion of our local storage over to the dest buffer, because + // otherwise, local threads would be overwriting results from other local threads + " uint i;\n" + " __private %s *sp = ((__private %s*) sPrivateStorage) + 3*offsets[tid] + alignmentOffset;\n" + " __global %s *dp = ((__global %s*) destBuffer) + 3*offsets[tid] + alignmentOffset;\n" + " for( i = 0; i < 3; i++ ) \n" + " dp[i] = sp[i];\n" + "}\n"; + + const char *typeName = get_explicit_type_name(type); + if(inVectorSize == 3) { + sprintf( destBuffer, patternV3, + type == kDouble ? doubleExtensionPragma : "", + typeName, typeName, + typeName, (int)inBufferSize, + typeName, typeName, + typeName, typeName, typeName, typeName, typeName ); + } else { + sprintf( destBuffer, pattern, + type == kDouble ? doubleExtensionPragma : "", + typeName, (int)inVectorSize, typeName, (int)inVectorSize, + typeName, (int)inVectorSize, (int)inBufferSize, + typeName, (int)inVectorSize, typeName, + (int)inVectorSize, typeName, typeName, typeName, typeName, typeName ); + } +} + +int test_vstore_private(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + // We have no idea how much actual private storage is available, so just pick a reasonable value, + // which is that we can fit at least two 16-element long, which is 2*8 bytes * 16 = 256 bytes + return test_vstoreset( device, context, queue, create_private_store_code, 256 ); +} + + + diff --git a/test_conformance/basic/test_wg_barrier.c b/test_conformance/basic/test_wg_barrier.c new file mode 100644 index 00000000..e23490d3 --- /dev/null +++ b/test_conformance/basic/test_wg_barrier.c @@ -0,0 +1,153 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +const char *wg_barrier_kernel_code = +"__kernel void compute_sum(__global int *a, int n, __global int *tmp_sum, __global int *sum)\n" +"{\n" +" int tid = get_local_id(0);\n" +" int lsize = get_local_size(0);\n" +" int i;\n" +"\n" +" tmp_sum[tid] = 0;\n" +" for (i=tid; i1; i = hadd(i,1))\n" +" {\n" +" work_group_barrier(CLK_GLOBAL_MEM_FENCE);\n" +" if (tid + i < lsize)\n" +" tmp_sum[tid] += tmp_sum[tid + i];\n" +" lsize = i; \n" +" }\n" +"\n" +" //no barrier is required here because last person to write to tmp_sum[0] was tid 0 \n" +" if (tid == 0)\n" +" *sum = tmp_sum[0];\n" +"}\n"; + + +static int +verify_sum(int *inptr, int *tmpptr, int *outptr, int n) +{ + int i; + int reference = 0; + + for (i=0; i max_local_workgroup_size[0]) + max_threadgroup_size = max_local_workgroup_size[0]; + + // work group size must divide evenly into the global size + while( num_elements % max_threadgroup_size ) + max_threadgroup_size--; + + input_ptr = (int*)malloc(sizeof(int) * num_elements); + output_ptr = (int*)malloc(sizeof(int)); + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * num_elements, NULL, &err); + test_error(err, "clCreateBuffer failed."); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int), NULL, &err); + test_error(err, "clCreateBuffer failed."); + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * max_threadgroup_size, NULL, &err); + test_error(err, "clCreateBuffer failed."); + + d = init_genrand( gRandomSeed ); + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" + +typedef struct work_item_data +{ + cl_uint workDim; + cl_uint globalSize[ 3 ]; + cl_uint globalID[ 3 ]; + cl_uint localSize[ 3 ]; + cl_uint localID[ 3 ]; + cl_uint numGroups[ 3 ]; + cl_uint groupID[ 3 ]; +}; + +static const char *workItemKernelCode = +"typedef struct {\n" +" uint workDim;\n" +" uint globalSize[ 3 ];\n" +" uint globalID[ 3 ];\n" +" uint localSize[ 3 ];\n" +" uint localID[ 3 ];\n" +" uint numGroups[ 3 ];\n" +" uint groupID[ 3 ];\n" +" } work_item_data;\n" +"\n" +"__kernel void sample_kernel( __global work_item_data *outData )\n" +"{\n" +" int id = get_global_id(0);\n" +" outData[ id ].workDim = (uint)get_work_dim();\n" +" for( uint i = 0; i < get_work_dim(); i++ )\n" +" {\n" +" outData[ id ].globalSize[ i ] = (uint)get_global_size( i );\n" +" outData[ id ].globalID[ i ] = (uint)get_global_id( i );\n" +" outData[ id ].localSize[ i ] = (uint)get_local_size( i );\n" +" outData[ id ].localID[ i ] = (uint)get_local_id( i );\n" +" outData[ id ].numGroups[ i ] = (uint)get_num_groups( i );\n" +" outData[ id ].groupID[ i ] = (uint)get_group_id( i );\n" +" }\n" +"}"; + +#define NUM_TESTS 1 + +int test_work_item_functions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper outData; + work_item_data testData[ 10240 ]; + size_t threads[3], localThreads[3]; + MTdata d; + + + error = create_single_kernel_helper( context, &program, &kernel, 1, &workItemKernelCode, "sample_kernel" ); + test_error( error, "Unable to create testing kernel" ); + + outData = clCreateBuffer( context, CL_MEM_READ_WRITE, sizeof( testData ), NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + error = clSetKernelArg( kernel, 0, sizeof( outData ), &outData ); + test_error( error, "Unable to set kernel arg" ); + + d = init_genrand( gRandomSeed ); + for( size_t dim = 1; dim <= 3; dim++ ) + { + for( int i = 0; i < NUM_TESTS; i++ ) + { + size_t numItems = 1; + for( size_t j = 0; j < dim; j++ ) + { + // All of our thread sizes should be within the max local sizes, since they're all <= 20 + threads[ j ] = (size_t)random_in_range( 1, 20, d ); + localThreads[ j ] = threads[ j ] / (size_t)random_in_range( 1, (int)threads[ j ], d ); + while( localThreads[ j ] > 1 && ( threads[ j ] % localThreads[ j ] != 0 ) ) + localThreads[ j ]--; + + numItems *= threads[ j ]; + + // Hack for now: localThreads > 1 are iffy + localThreads[ j ] = 1; + } + error = clEnqueueNDRangeKernel( queue, kernel, (cl_uint)dim, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + error = clEnqueueReadBuffer( queue, outData, CL_TRUE, 0, sizeof( testData ), testData, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + // Validate + for( size_t q = 0; q < threads[0]; q++ ) + { + // We can't really validate the actual value of each one, but we can validate that they're within a sane range + if( testData[ q ].workDim != (cl_uint)dim ) + { + log_error( "ERROR: get_work_dim() did not return proper value for %d dimensions (expected %d, got %d)\n", (int)dim, (int)dim, (int)testData[ q ].workDim ); + free_mtdata(d); + return -1; + } + for( size_t j = 0; j < dim; j++ ) + { + if( testData[ q ].globalSize[ j ] != (cl_uint)threads[ j ] ) + { + log_error( "ERROR: get_global_size(%d) did not return proper value for %d dimensions (expected %d, got %d)\n", + (int)j, (int)dim, (int)threads[ j ], (int)testData[ q ].globalSize[ j ] ); + free_mtdata(d); + return -1; + } + if( testData[ q ].globalID[ j ] < 0 || testData[ q ].globalID[ j ] >= (cl_uint)threads[ j ] ) + { + log_error( "ERROR: get_global_id(%d) did not return proper value for %d dimensions (max %d, got %d)\n", + (int)j, (int)dim, (int)threads[ j ], (int)testData[ q ].globalID[ j ] ); + free_mtdata(d); + return -1; + } + if( testData[ q ].localSize[ j ] != (cl_uint)localThreads[ j ] ) + { + log_error( "ERROR: get_local_size(%d) did not return proper value for %d dimensions (expected %d, got %d)\n", + (int)j, (int)dim, (int)localThreads[ j ], (int)testData[ q ].localSize[ j ] ); + free_mtdata(d); + return -1; + } + if( testData[ q ].localID[ j ] < 0 && testData[ q ].localID[ j ] >= (cl_uint)localThreads[ j ] ) + { + log_error( "ERROR: get_local_id(%d) did not return proper value for %d dimensions (max %d, got %d)\n", + (int)j, (int)dim, (int)localThreads[ j ], (int)testData[ q ].localID[ j ] ); + free_mtdata(d); + return -1; + } + size_t groupCount = ( threads[ j ] + localThreads[ j ] - 1 ) / localThreads[ j ]; + if( testData[ q ].numGroups[ j ] != (cl_uint)groupCount ) + { + log_error( "ERROR: get_num_groups(%d) did not return proper value for %d dimensions (expected %d with global dim %d and local dim %d, got %d)\n", + (int)j, (int)dim, (int)groupCount, (int)threads[ j ], (int)localThreads[ j ], (int)testData[ q ].numGroups[ j ] ); + free_mtdata(d); + return -1; + } + if( testData[ q ].groupID[ j ] < 0 || testData[ q ].groupID[ j ] >= (cl_uint)groupCount ) + { + log_error( "ERROR: get_group_id(%d) did not return proper value for %d dimensions (max %d, got %d)\n", + (int)j, (int)dim, (int)groupCount, (int)testData[ q ].groupID[ j ] ); + free_mtdata(d); + return -1; + } + } + } + } + } + + free_mtdata(d); + return 0; +} + + diff --git a/test_conformance/basic/test_writeimage.c b/test_conformance/basic/test_writeimage.c new file mode 100644 index 00000000..da4bd99d --- /dev/null +++ b/test_conformance/basic/test_writeimage.c @@ -0,0 +1,354 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +static const char *bgra8888_write_kernel_code = +"\n" +"__kernel void test_bgra8888_write(__global unsigned char *src, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(dstimg) + tid_x;\n" +" float4 color;\n" +"\n" +" indx *= 4;\n" +" color = (float4)((float)src[indx+2], (float)src[indx+1], (float)src[indx+0], (float)src[indx+3]);\n" +" color /= (float4)(255.0f, 255.0f, 255.0f, 255.0f);\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + + +static const char *rgba8888_write_kernel_code = +"\n" +"__kernel void test_rgba8888_write(__global unsigned char *src, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(dstimg) + tid_x;\n" +" float4 color;\n" +"\n" +" indx *= 4;\n" +" color = (float4)((float)src[indx+0], (float)src[indx+1], (float)src[indx+2], (float)src[indx+3]);\n" +" color /= (float4)(255.0f, 255.0f, 255.0f, 255.0f);\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + + +static unsigned char * +generate_8888_image(int w, int h, MTdata d) +{ + cl_uchar *ptr = (cl_uchar *)malloc(w * h * 4); + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + + +static const char *rgbaFFFF_write_kernel_code = +"__kernel void test_rgbaFFFF_write(__global float *src, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(dstimg) + tid_x;\n" +" float4 color;\n" +"\n" +" indx *= 4;\n" +" color = (float4)(src[indx+0], src[indx+1], src[indx+2], src[indx+3]);\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + + +static float * +generate_float_image(int w, int h, MTdata d) +{ + float *ptr = (float*)malloc(w * h * 4 * sizeof(float)); + int i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +static const char *rgba16_write_kernel_code = +"__kernel void test_rgba16_write(__global unsigned short *src, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(dstimg) + tid_x;\n" +" float4 color;\n" +"\n" +" indx *= 4;\n" +" color = (float4)((float)src[indx+0], (float)src[indx+1], (float)src[indx+2], (float)src[indx+3]);\n" +" color /= 65535.0f;\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + + +static unsigned short * +generate_16bit_image(int w, int h, MTdata d) +{ + cl_ushort *ptr = (cl_ushort*)malloc(w * h * 4 * sizeof(cl_ushort)); + int i; + + for (i=0; i MAX_ERR) + { + log_error("%s failed\n", string); + return -1; + } + } + + log_info("%s passed\n", string); + return 0; +} + +int test_writeimage_int16(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem streams[3]; + cl_program program; + cl_kernel kernel[2]; + cl_image_format img_format; + cl_ushort *input_ptr, *output_ptr; + size_t threads[2]; + int img_width = 512; + int img_height = 512; + int i, err, any_err = 0; + size_t origin[3] = {0, 0, 0}; + size_t region[3] = {img_width, img_height, 1}; + size_t length = img_width * img_height * 4 * sizeof(cl_ushort); + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + MTdata d = init_genrand( gRandomSeed ); + input_ptr = generate_16bit_image(img_width, img_height, d); + free_mtdata(d); d = NULL; + + output_ptr = (cl_ushort*)malloc(length); + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT16; + streams[0] = create_image_2d(context, CL_MEM_READ_WRITE, &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[0]) + { + log_error("create_image_2d failed\n"); + return -1; + } + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT16; + streams[1] = create_image_2d(context, CL_MEM_WRITE_ONLY, &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[1]) + { + log_error("create_image_2d failed\n"); + return -1; + } + streams[2] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[2]) + { + log_error("clCreateArray failed\n"); + return -1; + } + + err = clEnqueueWriteBuffer(queue, streams[2], CL_TRUE, 0, length, input_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + + err = create_single_kernel_helper(context, &program, &kernel[0], 1, &rgba16_write_kernel_code, "test_rgba16_write" ); + if (err) + return -1; + kernel[1] = clCreateKernel(program, "test_rgba16_write", NULL); + if (!kernel[1]) + { + log_error("clCreateKernel failed\n"); + return -1; + } + + err = clSetKernelArg(kernel[0], 0, sizeof streams[2], &streams[2]); + err |= clSetKernelArg(kernel[0], 1, sizeof streams[0], &streams[0]); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + err = clSetKernelArg(kernel[1], 0, sizeof streams[2], &streams[2]); + err |= clSetKernelArg(kernel[1], 1, sizeof streams[1], &streams[1]); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + threads[0] = (unsigned int)img_width; + threads[1] = (unsigned int)img_height; + + for (i=0; i<2; i++) + { + err = clEnqueueNDRangeKernel(queue, kernel[i], 2, NULL, threads, NULL, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clExecuteKernel failed\n"); + return -1; + } + + err = clEnqueueReadImage(queue, streams[i], CL_TRUE, origin, region, 0, 0, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clReadImage failed\n"); + return -1; + } + + err = verify_16bit_image((i == 0) ? "WRITE_IMAGE_RGBA_UNORM_INT16 test with memflags = CL_MEM_READ_WRITE" : + "WRITE_IMAGE_RGBA_UNORM_INT16 test with memflags = CL_MEM_WRITE_ONLY", + input_ptr, output_ptr, img_width, img_height); + any_err |= err; + } + + // cleanup + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + clReleaseMemObject(streams[2]); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseProgram(program); + free(input_ptr); + free(output_ptr); + + return any_err; +} + + diff --git a/test_conformance/buffers/CMakeLists.txt b/test_conformance/buffers/CMakeLists.txt new file mode 100644 index 00000000..8265eca5 --- /dev/null +++ b/test_conformance/buffers/CMakeLists.txt @@ -0,0 +1,26 @@ +set(MODULE_NAME BUFFERS) + +set(${MODULE_NAME}_SOURCES + main.c + test_buffer_copy.c + test_buffer_read.c + test_buffer_write.c + test_buffer_mem.c + array_info.c + test_buffer_map.c + test_sub_buffers.cpp + test_buffer_fill.c + test_buffer_migrate.c + test_image_migrate.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/typeWrappers.cpp + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) diff --git a/test_conformance/buffers/Jamfile b/test_conformance/buffers/Jamfile new file mode 100644 index 00000000..be1b449e --- /dev/null +++ b/test_conformance/buffers/Jamfile @@ -0,0 +1,24 @@ +project + : requirements + gcc:-xc++ + msvc:"/TP" + ; + +exe test_buffers + : array_info.c + main.c + test_buffer_copy.c + test_buffer_map.c + test_buffer_mem.c + test_buffer_read.c + test_buffer_write.c + test_buffer_fill.c + : ../..//glew + ; + +install dist + : test_buffers + : debug:$(DIST)/debug/tests/test_conformance/buffers + release:$(DIST)/release/tests/test_conformance/buffers + ; + diff --git a/test_conformance/buffers/Makefile b/test_conformance/buffers/Makefile new file mode 100644 index 00000000..50954563 --- /dev/null +++ b/test_conformance/buffers/Makefile @@ -0,0 +1,49 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c test_buffer_copy.c test_buffer_read.c test_buffer_write.c \ + test_buffer_mem.c array_info.c test_buffer_map.c \ + test_sub_buffers.cpp test_buffer_fill.c \ + test_buffer_migrate.c test_image_migrate.c \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/conversions.c \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/typeWrappers.cpp + + + +DEFINES = + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = $(SOURCES) +HEADERS = +TARGET = test_buffers +INCLUDE = +COMPILERFLAGS = -c -Wall -g -O0 -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) +LIBRARIES = -framework OpenCL -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. + diff --git a/test_conformance/buffers/array_info.c b/test_conformance/buffers/array_info.c new file mode 100644 index 00000000..0da92a02 --- /dev/null +++ b/test_conformance/buffers/array_info.c @@ -0,0 +1,63 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" + + + +int testBufferSize( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_mem memobj; + cl_int err; + size_t w = 32, h = 32, d = 32; + size_t retSize; + size_t elementSize = sizeof( cl_int ); + + memobj = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), elementSize * w*h*d, NULL, &err); + test_error(err, "clCreateBuffer failed."); + + err = clGetMemObjectInfo(memobj, CL_MEM_SIZE, sizeof( size_t ), (void *)&retSize, NULL); + if ( err ){ + log_error( "Error calling clGetMemObjectInfo(): %d\n", err ); + clReleaseMemObject(memobj); + return -1; + } + if ( (elementSize * w * h * d) != retSize ) { + log_error( "Error in clGetMemObjectInfo() check of size\n" ); + clReleaseMemObject(memobj); + return -1; + } + else{ + log_info( " CL_MEM_SIZE passed.\n" ); + } + + // cleanup + clReleaseMemObject(memobj); + + return err; + +} // end testArrayElementSize() + + +// FIXME: need to test other flags + diff --git a/test_conformance/buffers/main.c b/test_conformance/buffers/main.c new file mode 100644 index 00000000..df76a5d0 --- /dev/null +++ b/test_conformance/buffers/main.c @@ -0,0 +1,246 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include "procs.h" +#include "../../test_common/harness/testHarness.h" + +basefn bufferfn_list[] = { + test_buffer_read_async_int, + test_buffer_read_async_uint, + test_buffer_read_async_long, + test_buffer_read_async_ulong, + test_buffer_read_async_short, + test_buffer_read_async_ushort, + test_buffer_read_async_char, + test_buffer_read_async_uchar, + test_buffer_read_async_float, + test_buffer_read_array_barrier_int, + test_buffer_read_array_barrier_uint, + test_buffer_read_array_barrier_long, + test_buffer_read_array_barrier_ulong, + test_buffer_read_array_barrier_short, + test_buffer_read_array_barrier_ushort, + test_buffer_read_array_barrier_char, + test_buffer_read_array_barrier_uchar, + test_buffer_read_array_barrier_float, + test_buffer_read_int, + test_buffer_read_uint, + test_buffer_read_long, + test_buffer_read_ulong, + test_buffer_read_short, + test_buffer_read_ushort, + test_buffer_read_float, + 0, //test_buffer_read_half, + test_buffer_read_char, + test_buffer_read_uchar, + test_buffer_read_struct, + test_buffer_read_random_size, + test_buffer_map_read_int, + test_buffer_map_read_uint, + test_buffer_map_read_long, + test_buffer_map_read_ulong, + test_buffer_map_read_short, + test_buffer_map_read_ushort, + test_buffer_map_read_char, + test_buffer_map_read_uchar, + test_buffer_map_read_float, + test_buffer_map_read_struct, + + test_buffer_map_write_int, + test_buffer_map_write_uint, + test_buffer_map_write_long, + test_buffer_map_write_ulong, + test_buffer_map_write_short, + test_buffer_map_write_ushort, + test_buffer_map_write_char, + test_buffer_map_write_uchar, + test_buffer_map_write_float, + test_buffer_map_write_struct, + + test_buffer_write_int, + test_buffer_write_uint, + test_buffer_write_short, + test_buffer_write_ushort, + test_buffer_write_char, + test_buffer_write_uchar, + test_buffer_write_float, + 0, //test_buffer_write_half, + test_buffer_write_long, + test_buffer_write_ulong, + test_buffer_write_struct, + test_buffer_write_async_int, + test_buffer_write_async_uint, + test_buffer_write_async_short, + test_buffer_write_async_ushort, + test_buffer_write_async_char, + test_buffer_write_async_uchar, + test_buffer_write_async_float, + test_buffer_write_async_long, + test_buffer_write_async_ulong, + test_buffer_copy, + test_buffer_partial_copy, + test_mem_read_write_flags, + test_mem_write_flags, + test_mem_read_flags, + test_mem_copy_host_flags, + 0, //test_mem_alloc_ref_flags, + testBufferSize, + + test_sub_buffers_read_write, + test_sub_buffers_read_write_dual_devices, + test_sub_buffers_overlapping, + + test_buffer_fill_int, + test_buffer_fill_uint, + test_buffer_fill_short, + test_buffer_fill_ushort, + test_buffer_fill_char, + test_buffer_fill_uchar, + test_buffer_fill_long, + test_buffer_fill_ulong, + test_buffer_fill_float, + test_buffer_fill_struct, + + test_buffer_migrate, + test_image_migrate, +}; + +const char *bufferfn_names[] = { + "buffer_read_async_int", + "buffer_read_async_uint", + "buffer_read_async_long", + "buffer_read_async_ulong", + "buffer_read_async_short", + "buffer_read_async_ushort", + "buffer_read_async_char", + "buffer_read_async_uchar", + "buffer_read_async_float", + "buffer_read_array_barrier_int", + "buffer_read_array_barrier_uint", + "buffer_read_array_barrier_long", + "buffer_read_array_barrier_ulong", + "buffer_read_array_barrier_short", + "buffer_read_array_barrier_ushort", + "buffer_read_array_barrier_char", + "buffer_read_array_barrier_uchar", + "buffer_read_array_barrier_float", + "buffer_read_int", + "buffer_read_uint", + "buffer_read_long", + "buffer_read_ulong", + "buffer_read_short", + "buffer_read_ushort", + "buffer_read_float", + "buffer_read_half", + "buffer_read_char", + "buffer_read_uchar", + "buffer_read_struct", + "buffer_read_random_size", + "buffer_map_read_int", + "buffer_map_read_uint", + "buffer_map_read_long", + "buffer_map_read_ulong", + "buffer_map_read_short", + "buffer_map_read_ushort", + "buffer_map_read_char", + "buffer_map_read_uchar", + "buffer_map_read_float", + "buffer_map_read_struct", + + "buffer_map_write_int", + "buffer_map_write_uint", + "buffer_map_write_long", + "buffer_map_write_ulong", + "buffer_map_write_short", + "buffer_map_write_ushort", + "buffer_map_write_char", + "buffer_map_write_uchar", + "buffer_map_write_float", + "buffer_map_write_struct", + + "buffer_write_int", + "buffer_write_uint", + "buffer_write_short", + "buffer_write_ushort", + "buffer_write_char", + "buffer_write_uchar", + "buffer_write_float", + "buffer_write_half", + "buffer_write_long", + "buffer_write_ulong", + "buffer_write_struct", + "buffer_write_async_int", + "buffer_write_async_uint", + "buffer_write_async_short", + "buffer_write_async_ushort", + "buffer_write_async_char", + "buffer_write_async_uchar", + "buffer_write_async_float", + "buffer_write_async_long", + "buffer_write_async_ulong", + "buffer_copy", + "buffer_partial_copy", + "mem_read_write_flags", + "mem_write_only_flags", + "mem_read_only_flags", + "mem_copy_host_flags", + "mem_alloc_ref_flags", + "array_info_size", + "sub_buffers_read_write", + "sub_buffers_read_write_dual_devices", + "sub_buffers_overlapping", + "buffer_fill_int", + "buffer_fill_uint", + "buffer_fill_short", + "buffer_fill_ushort", + "buffer_fill_char", + "buffer_fill_uchar", + "buffer_fill_long", + "buffer_fill_ulong", + "buffer_fill_float", + "buffer_fill_struct", + "buffer_migrate", + "image_migrate", +}; + +ct_assert((sizeof(bufferfn_names) / sizeof(bufferfn_names[0])) == (sizeof(bufferfn_list) / sizeof(bufferfn_list[0]))); + +int num_bufferfns = sizeof(bufferfn_names) / sizeof(char *); + +const cl_mem_flags flag_set[] = { + CL_MEM_ALLOC_HOST_PTR, + CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_USE_HOST_PTR, + CL_MEM_COPY_HOST_PTR, + 0 +}; +const char* flag_set_names[] = { + "CL_MEM_ALLOC_HOST_PTR", + "CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR", + "CL_MEM_USE_HOST_PTR", + "CL_MEM_COPY_HOST_PTR", + "0" +}; + +int main( int argc, const char *argv[] ) +{ + return runTestHarness( argc, argv, num_bufferfns, bufferfn_list, bufferfn_names, + false, false, 0 ); +} diff --git a/test_conformance/buffers/procs.h b/test_conformance/buffers/procs.h new file mode 100644 index 00000000..ff1edbfb --- /dev/null +++ b/test_conformance/buffers/procs.h @@ -0,0 +1,132 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef __PROCS_H__ +#define __PROCS_H__ + +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/mt19937.h" +#include "../../test_common/harness/conversions.h" + +#ifndef __APPLE__ +#include +#endif + +extern const cl_mem_flags flag_set[]; +extern const char* flag_set_names[]; +#define NUM_FLAGS 5 + +extern int test_buffer_read_int( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_uint( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_long( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_ulong( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_short( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_ushort( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_float( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_half( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_char( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_uchar( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_struct( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_random_size( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_async_int( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_async_uint( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_async_long( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_async_ulong( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_async_short( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_async_ushort( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_async_char( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_async_uchar( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_async_float( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_array_barrier_int( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_array_barrier_uint( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_array_barrier_short( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_array_barrier_ushort( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_array_barrier_long( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_array_barrier_ulong( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_array_barrier_char( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_array_barrier_uchar( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_read_array_barrier_float( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_int( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_uint( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_short( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_ushort( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_char( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_uchar( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_float( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_half( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_long( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_ulong( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_struct( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_async_int( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_async_uint( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_async_short( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_async_ushort( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_async_char( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_async_uchar( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_async_float( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_async_long( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_write_async_ulong( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_copy( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_partial_copy( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int testBufferSize( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_mem_read_write_flags( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_mem_write_flags( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_mem_read_flags( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_mem_copy_host_flags( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_mem_alloc_ref_flags( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_read_int( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_read_uint( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_read_long( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_read_ulong( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_read_short( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_read_ushort( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_read_char( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_read_uchar( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_read_float( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_read_struct( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); + +extern int test_buffer_map_write_int( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_write_uint( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_write_long( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_write_ulong( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_write_short( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_write_ushort( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_write_char( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_write_uchar( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_write_float( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_map_write_struct( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); + +extern int test_sub_buffers_read_write( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_sub_buffers_read_write_dual_devices( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_sub_buffers_overlapping( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_migrate(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_image_migrate(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_buffer_fill_int( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_fill_uint( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_fill_short( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_fill_ushort( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_fill_char( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_fill_uchar( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_fill_long( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_fill_ulong( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_fill_float( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffer_fill_struct( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); + +#endif // #ifndef __PROCS_H__ + diff --git a/test_conformance/buffers/test_buffer_copy.c b/test_conformance/buffers/test_buffer_copy.c new file mode 100644 index 00000000..fa2d579d --- /dev/null +++ b/test_conformance/buffers/test_buffer_copy.c @@ -0,0 +1,295 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/errorHelpers.h" + + +static int verify_copy_buffer(int *inptr, int *outptr, int n) +{ + int i; + + for (i=0; i +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/errorHelpers.h" + +#define USE_LOCAL_WORK_GROUP 1 + +#define TEST_PRIME_CHAR 0x77 +#define TEST_PRIME_INT ((1<<16)+1) +#define TEST_PRIME_UINT ((1U<<16)+1U) +#define TEST_PRIME_LONG ((1LL<<32)+1LL) +#define TEST_PRIME_ULONG ((1ULL<<32)+1ULL) +#define TEST_PRIME_SHORT (cl_short)((1<<8)+1) +#define TEST_PRIME_USHORT (cl_ushort)((1<<8)+1) +#define TEST_PRIME_FLOAT (cl_float)3.40282346638528860e+38 +#define TEST_PRIME_HALF 119.f + +#ifndef TestStruct +typedef struct{ + cl_int a; + cl_float b; +} TestStruct; +#endif + +const char *buffer_fill_int_kernel_code[] = { + "__kernel void test_buffer_fill_int(__global int *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_int2(__global int2 *src, __global int2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_int4(__global int4 *src, __global int4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_int8(__global int8 *src, __global int8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_int16(__global int16 *src, __global int16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *int_kernel_name[] = { "test_buffer_fill_int", "test_buffer_fill_int2", "test_buffer_fill_int4", "test_buffer_fill_int8", "test_buffer_fill_int16" }; + + +const char *buffer_fill_uint_kernel_code[] = { + "__kernel void test_buffer_fill_uint(__global uint *src, __global uint *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_uint2(__global uint2 *src, __global uint2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_uint4(__global uint4 *src, __global uint4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_uint8(__global uint8 *src, __global uint8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_uint16(__global uint16 *src, __global uint16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *uint_kernel_name[] = { "test_buffer_fill_uint", "test_buffer_fill_uint2", "test_buffer_fill_uint4", "test_buffer_fill_uint8", "test_buffer_fill_uint16" }; + + +const char *buffer_fill_short_kernel_code[] = { + "__kernel void test_buffer_fill_short(__global short *src, __global short *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_short2(__global short2 *src, __global short2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_short4(__global short4 *src, __global short4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_short8(__global short8 *src, __global short8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_short16(__global short16 *src, __global short16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *short_kernel_name[] = { "test_buffer_fill_short", "test_buffer_fill_short2", "test_buffer_fill_short4", "test_buffer_fill_short8", "test_buffer_fill_short16" }; + + +const char *buffer_fill_ushort_kernel_code[] = { + "__kernel void test_buffer_fill_ushort(__global ushort *src, __global ushort *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_ushort2(__global ushort2 *src, __global ushort2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_ushort4(__global ushort4 *src, __global ushort4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_ushort8(__global ushort8 *src, __global ushort8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_ushort16(__global ushort16 *src, __global ushort16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *ushort_kernel_name[] = { "test_buffer_fill_ushort", "test_buffer_fill_ushort2", "test_buffer_fill_ushort4", "test_buffer_fill_ushort8", "test_buffer_fill_ushort16" }; + + +const char *buffer_fill_char_kernel_code[] = { + "__kernel void test_buffer_fill_char(__global char *src, __global char *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_char2(__global char2 *src, __global char2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_char4(__global char4 *src, __global char4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_char8(__global char8 *src, __global char8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_char16(__global char16 *src, __global char16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *char_kernel_name[] = { "test_buffer_fill_char", "test_buffer_fill_char2", "test_buffer_fill_char4", "test_buffer_fill_char8", "test_buffer_fill_char16" }; + + +const char *buffer_fill_uchar_kernel_code[] = { + "__kernel void test_buffer_fill_uchar(__global uchar *src, __global uchar *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_uchar2(__global uchar2 *src, __global uchar2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_uchar4(__global uchar4 *src, __global uchar4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_uchar8(__global uchar8 *src, __global uchar8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_uchar16(__global uchar16 *src, __global uchar16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *uchar_kernel_name[] = { "test_buffer_fill_uchar", "test_buffer_fill_uchar2", "test_buffer_fill_uchar4", "test_buffer_fill_uchar8", "test_buffer_fill_uchar16" }; + + +const char *buffer_fill_long_kernel_code[] = { + "__kernel void test_buffer_fill_long(__global long *src, __global long *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_long2(__global long2 *src, __global long2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_long4(__global long4 *src, __global long4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_long8(__global long8 *src, __global long8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_long16(__global long16 *src, __global long16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *long_kernel_name[] = { "test_buffer_fill_long", "test_buffer_fill_long2", "test_buffer_fill_long4", "test_buffer_fill_long8", "test_buffer_fill_long16" }; + + +const char *buffer_fill_ulong_kernel_code[] = { + "__kernel void test_buffer_fill_ulong(__global ulong *src, __global ulong *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_ulong2(__global ulong2 *src, __global ulong2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_ulong4(__global ulong4 *src, __global ulong4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_ulong8(__global ulong8 *src, __global ulong8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_ulong16(__global ulong16 *src, __global ulong16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *ulong_kernel_name[] = { "test_buffer_fill_ulong", "test_buffer_fill_ulong2", "test_buffer_fill_ulong4", "test_buffer_fill_ulong8", "test_buffer_fill_ulong16" }; + + +const char *buffer_fill_float_kernel_code[] = { + "__kernel void test_buffer_fill_float(__global float *src, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_float2(__global float2 *src, __global float2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_float4(__global float4 *src, __global float4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_float8(__global float8 *src, __global float8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_fill_float16(__global float16 *src, __global float16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *float_kernel_name[] = { "test_buffer_fill_float", "test_buffer_fill_float2", "test_buffer_fill_float4", "test_buffer_fill_float8", "test_buffer_fill_float16" }; + + +static const char *struct_kernel_code = +"typedef struct{\n" +"int a;\n" +"float b;\n" +"} TestStruct;\n" +"__kernel void read_fill_struct(__global TestStruct *src, __global TestStruct *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid].a = src[tid].a;\n" +" dst[tid].b = src[tid].b;\n" +"}\n"; + + + +static int verify_fill_int( void *ptr1, void *ptr2, int n ) +{ + int i; + cl_int *inptr = (cl_int *)ptr1; + cl_int *outptr = (cl_int *)ptr2; + + for (i=0; ia = (cl_int)genrand_int32(d); + pattern->b = (cl_float)get_random_float( -FLT_MAX, FLT_MAX, d ); + + inptr = (TestStruct *)align_malloc(ptrSize * num_elements, min_alignment); + for ( j = 0; j < offset_elements; j++ ) { + inptr[j].a = 0; + inptr[j].b =0; + } + for ( j = offset_elements; j < offset_elements + fill_elements; j++ ) { + inptr[j].a = pattern->a; + inptr[j].b = pattern->b; + } + for ( j = offset_elements + fill_elements; j < (size_t)num_elements; j++ ) { + inptr[j].a = 0; + inptr[j].b = 0; + } + + hostptr = (TestStruct *)align_malloc(ptrSize * num_elements, min_alignment); + memset(hostptr, 0, ptrSize * num_elements); + + for (src_flag_id=0; src_flag_id < NUM_FLAGS; src_flag_id++) { + log_info("Testing with cl_mem_flags: %s\n", flag_set_names[src_flag_id]); + + if ((flag_set[src_flag_id] & CL_MEM_USE_HOST_PTR) || (flag_set[src_flag_id] & CL_MEM_COPY_HOST_PTR)) + buffers[0] = clCreateBuffer(context, flag_set[src_flag_id], ptrSize * num_elements, hostptr, &err); + else + buffers[0] = clCreateBuffer(context, flag_set[src_flag_id], ptrSize * num_elements, NULL, &err); + if ( err ){ + print_error(err, " clCreateBuffer failed\n" ); + clReleaseEvent( event[0] ); + clReleaseEvent( event[1] ); + free( (void *)pattern ); + align_free( (void *)inptr ); + align_free( (void *)hostptr ); + free_mtdata(d); + return -1; + } + if (!((flag_set[src_flag_id] & CL_MEM_USE_HOST_PTR) || (flag_set[src_flag_id] & CL_MEM_COPY_HOST_PTR))) { + err = clEnqueueWriteBuffer(queue, buffers[0], CL_FALSE, 0, ptrSize * num_elements, hostptr, 0, NULL, NULL); + if ( err != CL_SUCCESS ){ + print_error(err, " clEnqueueWriteBuffer failed\n" ); + clReleaseEvent( event[0] ); + clReleaseEvent( event[1] ); + free( (void *)pattern ); + align_free( (void *)inptr ); + align_free( (void *)hostptr ); + free_mtdata(d); + return -1; + } + } + outptr = align_malloc( ptrSize * num_elements, min_alignment); + memset(outptr, 0, ptrSize * num_elements); + buffers[1] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, ptrSize * num_elements, outptr, &err); + if ( ! buffers[1] || err){ + print_error(err, " clCreateBuffer failed\n" ); + align_free( outptr ); + clReleaseMemObject(buffers[0]); + clReleaseEvent( event[0] ); + clReleaseEvent( event[1] ); + free( (void *)pattern ); + align_free( (void *)inptr ); + align_free( (void *)hostptr ); + free_mtdata(d); + return -1; + } + + err = clEnqueueFillBuffer(queue, buffers[0], pattern, ptrSize, + ptrSize * offset_elements, ptrSize * fill_elements, + 0, NULL, &(event[0])); + /* uncomment for test debugging + err = clEnqueueWriteBuffer(queue, buffers[0], CL_FALSE, 0, ptrSize * num_elements, inptr, 0, NULL, &(event[0])); + */ + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueFillBuffer failed" ); + align_free( outptr ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseEvent( event[0] ); + clReleaseEvent( event[1] ); + free( (void *)pattern ); + align_free( (void *)inptr ); + align_free( (void *)hostptr ); + free_mtdata(d); + return -1; + } + + err = create_single_kernel_helper( context, &program, &kernel, 1, &struct_kernel_code, "read_fill_struct" ); + if ( err ){ + log_error( " Error creating program for struct\n" ); + align_free( outptr ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseEvent( event[0] ); + clReleaseEvent( event[1] ); + free( (void *)pattern ); + align_free( (void *)inptr ); + align_free( (void *)hostptr ); + free_mtdata(d); + return -1; + } + +#ifdef USE_LOCAL_WORK_GROUP + err = get_max_common_work_group_size( context, kernel, global_work_size[0], &local_work_size[0] ); + test_error( err, "Unable to get work group size to use" ); +#endif + + err = clSetKernelArg( kernel, 0, sizeof( cl_mem ), (void *)&buffers[0] ); + err |= clSetKernelArg( kernel, 1, sizeof( cl_mem ), (void *)&buffers[1] ); + if ( err != CL_SUCCESS ){ + print_error( err, " clSetKernelArg failed" ); + clReleaseKernel( kernel ); + clReleaseProgram( program ); + align_free( outptr ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseEvent( event[0] ); + clReleaseEvent( event[1] ); + free( (void *)pattern ); + align_free( (void *)inptr ); + align_free( (void *)hostptr ); + free_mtdata(d); + return -1; + } + + err = clWaitForEvents( 1, &(event[0]) ); + if ( err != CL_SUCCESS ){ + print_error( err, "clWaitForEvents() failed" ); + clReleaseKernel( kernel ); + clReleaseProgram( program ); + align_free( outptr ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseEvent( event[0] ); + clReleaseEvent( event[1] ); + free( (void *)pattern ); + align_free( (void *)inptr ); + align_free( (void *)hostptr ); + free_mtdata(d); + return -1; + } + clReleaseEvent( event[0] ); + +#ifdef USE_LOCAL_WORK_GROUP + err = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, global_work_size, local_work_size, 0, NULL, NULL ); +#else + err = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, global_work_size, NULL, 0, NULL, NULL ); +#endif + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseKernel( kernel ); + clReleaseProgram( program ); + align_free( outptr ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseEvent( event[0] ); + clReleaseEvent( event[1] ); + free( (void *)pattern ); + align_free( (void *)inptr ); + align_free( (void *)hostptr ); + free_mtdata(d); + return -1; + } + + err = clEnqueueReadBuffer( queue, buffers[1], CL_FALSE, 0, ptrSize * num_elements, outptr, 0, NULL, &(event[1]) ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed" ); + clReleaseKernel( kernel ); + clReleaseProgram( program ); + align_free( outptr ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseEvent( event[0] ); + clReleaseEvent( event[1] ); + free( (void *)pattern ); + align_free( (void *)inptr ); + align_free( (void *)hostptr ); + free_mtdata(d); + return -1; + } + + err = clWaitForEvents( 1, &(event[1]) ); + if ( err != CL_SUCCESS ){ + print_error( err, "clWaitForEvents() failed" ); + } + clReleaseEvent( event[1] ); + + if ( verify_fill_struct( inptr, outptr, num_elements) ) { + log_error( " buffer_FILL async struct test failed\n" ); + total_errors++; + } + else{ + log_info( " buffer_FILL async struct test passed\n" ); + } + // cleanup + clReleaseKernel( kernel ); + clReleaseProgram( program ); + align_free( outptr ); + clReleaseMemObject( buffers[0] ); + clReleaseMemObject( buffers[1] ); + } // src cl_mem_flag + free( (void *)pattern ); + align_free( (void *)inptr ); + align_free( (void *)hostptr ); + } + + free_mtdata(d); + + return total_errors; + +} // end test_buffer_fill_struct() + + +int test_buffer_fill_int( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_int *inptr[5]; + cl_int *hostptr[5]; + cl_int *pattern[5]; + size_t ptrSizes[5]; + int n, i, err=0; + size_t j, offset_elements, fill_elements; + int (*foo)(void *,void *,int); + MTdata d = init_genrand( gRandomSeed ); + + size_t min_alignment = get_min_alignment(context); + + foo = verify_fill_int; + + ptrSizes[0] = sizeof(cl_int); + ptrSizes[1] = ptrSizes[0] << 1; + ptrSizes[2] = ptrSizes[1] << 1; + ptrSizes[3] = ptrSizes[2] << 1; + ptrSizes[4] = ptrSizes[3] << 1; + + // Test with random offsets and fill sizes + for ( n = 0; n < 8; n++ ){ + offset_elements = (size_t)get_random_float( 0.f, (float)(num_elements - 8), d ); + fill_elements = (size_t)get_random_float( 8.f, (float)(num_elements - offset_elements), d ); + log_info( "Testing random fill from offset %d for %d elements: \n", (int)offset_elements, (int)fill_elements ); + + for ( i = 0; i < 5; i++ ){ + pattern[i] = (cl_int *)malloc(ptrSizes[i]); + for ( j = 0; j < ptrSizes[i] / ptrSizes[0]; j++ ) + pattern[i][j] = TEST_PRIME_INT; + + inptr[i] = (cl_int *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + for ( j = 0; j < ptrSizes[i] * offset_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + for ( j = ptrSizes[i] * offset_elements / ptrSizes[0]; j < ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j++ ) + inptr[i][j] = TEST_PRIME_INT; + for ( j = ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j < ptrSizes[i] * num_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + + hostptr[i] = (cl_int *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + memset(hostptr[i], 0, ptrSizes[i] * num_elements); + } + + if (test_buffer_fill( deviceID, context, queue, num_elements, sizeof( cl_int ), (char*)"int", + 5, (void**)inptr, (void**)hostptr, (void**)pattern, + offset_elements, fill_elements, + buffer_fill_int_kernel_code, int_kernel_name, foo )) + err++; + + for ( i = 0; i < 5; i++ ){ + free( (void *)pattern[i] ); + align_free( (void *)inptr[i] ); + align_free( (void *)hostptr[i] ); + } + + } + + free_mtdata(d); + + return err; + +} // end test_buffer_int_fill() + + +int test_buffer_fill_uint( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_uint *inptr[5]; + cl_uint *hostptr[5]; + cl_uint *pattern[5]; + size_t ptrSizes[5]; + int n, i, err=0; + size_t j, offset_elements, fill_elements; + MTdata d = init_genrand( gRandomSeed ); + int (*foo)(void *,void *,int); + + size_t min_alignment = get_min_alignment(context); + + foo = verify_fill_uint; + + ptrSizes[0] = sizeof(cl_uint); + ptrSizes[1] = ptrSizes[0] << 1; + ptrSizes[2] = ptrSizes[1] << 1; + ptrSizes[3] = ptrSizes[2] << 1; + ptrSizes[4] = ptrSizes[3] << 1; + + // Test with random offsets and fill sizes + for ( n = 0; n < 8; n++ ){ + offset_elements = (size_t)get_random_float( 0.f, (float)(num_elements - 8), d ); + fill_elements = (size_t)get_random_float( 8.f, (float)(num_elements - offset_elements), d ); + log_info( "Testing random fill from offset %d for %d elements: \n", (int)offset_elements, (int)fill_elements ); + + for ( i = 0; i < 5; i++ ){ + pattern[i] = (cl_uint *)malloc(ptrSizes[i]); + for ( j = 0; j < ptrSizes[i] / ptrSizes[0]; j++ ) + pattern[i][j] = TEST_PRIME_UINT; + + inptr[i] = (cl_uint *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + for ( j = 0; j < ptrSizes[i] * offset_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + for ( j = ptrSizes[i] * offset_elements / ptrSizes[0]; j < ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j++ ) + inptr[i][j] = TEST_PRIME_UINT; + for ( j = ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j < ptrSizes[i] * num_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + + hostptr[i] = (cl_uint *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + memset(hostptr[i], 0, ptrSizes[i] * num_elements); + } + + if (test_buffer_fill( deviceID, context, queue, num_elements, sizeof( cl_uint ), (char*)"uint", + 5, (void**)inptr, (void**)hostptr, (void**)pattern, + offset_elements, fill_elements, + buffer_fill_uint_kernel_code, uint_kernel_name, foo )) + err++; + + for ( i = 0; i < 5; i++ ){ + free( (void *)pattern[i] ); + align_free( (void *)inptr[i] ); + align_free( (void *)hostptr[i] ); + } + + } + + free_mtdata(d); + + return err; + +} // end test_buffer_uint_fill() + + +int test_buffer_fill_short( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_short *inptr[5]; + cl_short *hostptr[5]; + cl_short *pattern[5]; + size_t ptrSizes[5]; + int n, i, err=0; + size_t j, offset_elements, fill_elements; + MTdata d = init_genrand( gRandomSeed ); + int (*foo)(void *,void *,int); + + size_t min_alignment = get_min_alignment(context); + + foo = verify_fill_short; + + ptrSizes[0] = sizeof(cl_short); + ptrSizes[1] = ptrSizes[0] << 1; + ptrSizes[2] = ptrSizes[1] << 1; + ptrSizes[3] = ptrSizes[2] << 1; + ptrSizes[4] = ptrSizes[3] << 1; + + // Test with random offsets and fill sizes + for ( n = 0; n < 8; n++ ){ + offset_elements = (size_t)get_random_float( 0.f, (float)(num_elements - 8), d ); + fill_elements = (size_t)get_random_float( 8.f, (float)(num_elements - offset_elements), d ); + log_info( "Testing random fill from offset %d for %d elements: \n", (int)offset_elements, (int)fill_elements ); + + for ( i = 0; i < 5; i++ ){ + pattern[i] = (cl_short *)malloc(ptrSizes[i]); + for ( j = 0; j < ptrSizes[i] / ptrSizes[0]; j++ ) + pattern[i][j] = TEST_PRIME_SHORT; + + inptr[i] = (cl_short *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + for ( j = 0; j < ptrSizes[i] * offset_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + for ( j = ptrSizes[i] * offset_elements / ptrSizes[0]; j < ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j++ ) + inptr[i][j] = TEST_PRIME_SHORT; + for ( j = ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j < ptrSizes[i] * num_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + + hostptr[i] = (cl_short *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + memset(hostptr[i], 0, ptrSizes[i] * num_elements); + } + + if (test_buffer_fill( deviceID, context, queue, num_elements, sizeof( cl_short ), (char*)"short", + 5, (void**)inptr, (void**)hostptr, (void**)pattern, + offset_elements, fill_elements, + buffer_fill_short_kernel_code, short_kernel_name, foo )) + err++; + + for ( i = 0; i < 5; i++ ){ + free( (void *)pattern[i] ); + align_free( (void *)inptr[i] ); + align_free( (void *)hostptr[i] ); + } + + } + + free_mtdata(d); + + return err; + +} // end test_buffer_short_fill() + + +int test_buffer_fill_ushort( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_ushort *inptr[5]; + cl_ushort *hostptr[5]; + cl_ushort *pattern[5]; + size_t ptrSizes[5]; + int n, i, err=0; + size_t j, offset_elements, fill_elements; + MTdata d = init_genrand( gRandomSeed ); + int (*foo)(void *,void *,int); + + size_t min_alignment = get_min_alignment(context); + + foo = verify_fill_ushort; + + ptrSizes[0] = sizeof(cl_ushort); + ptrSizes[1] = ptrSizes[0] << 1; + ptrSizes[2] = ptrSizes[1] << 1; + ptrSizes[3] = ptrSizes[2] << 1; + ptrSizes[4] = ptrSizes[3] << 1; + + // Test with random offsets and fill sizes + for ( n = 0; n < 8; n++ ){ + offset_elements = (size_t)get_random_float( 0.f, (float)(num_elements - 8), d ); + fill_elements = (size_t)get_random_float( 8.f, (float)(num_elements - offset_elements), d ); + log_info( "Testing random fill from offset %d for %d elements: \n", (int)offset_elements, (int)fill_elements ); + + for ( i = 0; i < 5; i++ ){ + pattern[i] = (cl_ushort *)malloc(ptrSizes[i]); + for ( j = 0; j < ptrSizes[i] / ptrSizes[0]; j++ ) + pattern[i][j] = TEST_PRIME_USHORT; + + inptr[i] = (cl_ushort *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + for ( j = 0; j < ptrSizes[i] * offset_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + for ( j = ptrSizes[i] * offset_elements / ptrSizes[0]; j < ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j++ ) + inptr[i][j] = TEST_PRIME_USHORT; + for ( j = ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j < ptrSizes[i] * num_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + + hostptr[i] = (cl_ushort *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + memset(hostptr[i], 0, ptrSizes[i] * num_elements); + } + + if (test_buffer_fill( deviceID, context, queue, num_elements, sizeof( cl_ushort ), (char*)"ushort", + 5, (void**)inptr, (void**)hostptr, (void**)pattern, + offset_elements, fill_elements, + buffer_fill_ushort_kernel_code, ushort_kernel_name, foo )) + err++; + + for ( i = 0; i < 5; i++ ){ + free( (void *)pattern[i] ); + align_free( (void *)inptr[i] ); + align_free( (void *)hostptr[i] ); + } + + } + + free_mtdata(d); + + return err; + +} // end test_buffer_ushort_fill() + + +int test_buffer_fill_char( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_char *inptr[5]; + cl_char *hostptr[5]; + cl_char *pattern[5]; + size_t ptrSizes[5]; + int n, i, err=0; + size_t j, offset_elements, fill_elements; + MTdata d = init_genrand( gRandomSeed ); + int (*foo)(void *,void *,int); + + size_t min_alignment = get_min_alignment(context); + + foo = verify_fill_char; + + ptrSizes[0] = sizeof(cl_char); + ptrSizes[1] = ptrSizes[0] << 1; + ptrSizes[2] = ptrSizes[1] << 1; + ptrSizes[3] = ptrSizes[2] << 1; + ptrSizes[4] = ptrSizes[3] << 1; + + // Test with random offsets and fill sizes + for ( n = 0; n < 8; n++ ){ + offset_elements = (size_t)get_random_float( 0.f, (float)(num_elements - 8), d ); + fill_elements = (size_t)get_random_float( 8.f, (float)(num_elements - offset_elements), d ); + log_info( "Testing random fill from offset %d for %d elements: \n", (int)offset_elements, (int)fill_elements ); + + for ( i = 0; i < 5; i++ ){ + pattern[i] = (cl_char *)malloc(ptrSizes[i]); + for ( j = 0; j < ptrSizes[i] / ptrSizes[0]; j++ ) + pattern[i][j] = TEST_PRIME_CHAR; + + inptr[i] = (cl_char *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + for ( j = 0; j < ptrSizes[i] * offset_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + for ( j = ptrSizes[i] * offset_elements / ptrSizes[0]; j < ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j++ ) + inptr[i][j] = TEST_PRIME_CHAR; + for ( j = ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j < ptrSizes[i] * num_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + + hostptr[i] = (cl_char *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + memset(hostptr[i], 0, ptrSizes[i] * num_elements); + } + + if (test_buffer_fill( deviceID, context, queue, num_elements, sizeof( cl_char ), (char*)"char", + 5, (void**)inptr, (void**)hostptr, (void**)pattern, + offset_elements, fill_elements, + buffer_fill_char_kernel_code, char_kernel_name, foo )) + err++; + + for ( i = 0; i < 5; i++ ){ + free( (void *)pattern[i] ); + align_free( (void *)inptr[i] ); + align_free( (void *)hostptr[i] ); + } + + } + + free_mtdata(d); + + return err; + +} // end test_buffer_char_fill() + + +int test_buffer_fill_uchar( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_uchar *inptr[5]; + cl_uchar *hostptr[5]; + cl_uchar *pattern[5]; + size_t ptrSizes[5]; + int n, i, err=0; + size_t j, offset_elements, fill_elements; + MTdata d = init_genrand( gRandomSeed ); + int (*foo)(void *,void *,int); + + size_t min_alignment = get_min_alignment(context); + + foo = verify_fill_uchar; + + ptrSizes[0] = sizeof(cl_uchar); + ptrSizes[1] = ptrSizes[0] << 1; + ptrSizes[2] = ptrSizes[1] << 1; + ptrSizes[3] = ptrSizes[2] << 1; + ptrSizes[4] = ptrSizes[3] << 1; + + // Test with random offsets and fill sizes + for ( n = 0; n < 8; n++ ){ + offset_elements = (size_t)get_random_float( 0.f, (float)(num_elements - 8), d ); + fill_elements = (size_t)get_random_float( 8.f, (float)(num_elements - offset_elements), d ); + log_info( "Testing random fill from offset %d for %d elements: \n", (int)offset_elements, (int)fill_elements ); + + for ( i = 0; i < 5; i++ ){ + pattern[i] = (cl_uchar *)malloc(ptrSizes[i]); + for ( j = 0; j < ptrSizes[i] / ptrSizes[0]; j++ ) + pattern[i][j] = TEST_PRIME_CHAR; + + inptr[i] = (cl_uchar *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + for ( j = 0; j < ptrSizes[i] * offset_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + for ( j = ptrSizes[i] * offset_elements / ptrSizes[0]; j < ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j++ ) + inptr[i][j] = TEST_PRIME_CHAR; + for ( j = ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j < ptrSizes[i] * num_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + + hostptr[i] = (cl_uchar *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + memset(hostptr[i], 0, ptrSizes[i] * num_elements); + } + + if (test_buffer_fill( deviceID, context, queue, num_elements, sizeof( cl_uchar ), (char*)"uchar", + 5, (void**)inptr, (void**)hostptr, (void**)pattern, + offset_elements, fill_elements, + buffer_fill_uchar_kernel_code, uchar_kernel_name, foo )) + err++; + + for ( i = 0; i < 5; i++ ){ + free( (void *)pattern[i] ); + align_free( (void *)inptr[i] ); + align_free( (void *)hostptr[i] ); + } + + } + + free_mtdata(d); + + return err; + +} // end test_buffer_uchar_fill() + + +int test_buffer_fill_long( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_long *inptr[5]; + cl_long *hostptr[5]; + cl_long *pattern[5]; + size_t ptrSizes[5]; + int n, i, err=0; + size_t j, offset_elements, fill_elements; + MTdata d = init_genrand( gRandomSeed ); + int (*foo)(void *,void *,int); + + size_t min_alignment = get_min_alignment(context); + + foo = verify_fill_long; + + ptrSizes[0] = sizeof(cl_long); + ptrSizes[1] = ptrSizes[0] << 1; + ptrSizes[2] = ptrSizes[1] << 1; + ptrSizes[3] = ptrSizes[2] << 1; + ptrSizes[4] = ptrSizes[3] << 1; + + //skip devices that don't support long + if (! gHasLong ) + { + log_info( "Device does not support 64-bit integers. Skipping test.\n" ); + return CL_SUCCESS; + } + + // Test with random offsets and fill sizes + for ( n = 0; n < 8; n++ ){ + offset_elements = (size_t)get_random_float( 0.f, (float)(num_elements - 8), d ); + fill_elements = (size_t)get_random_float( 8.f, (float)(num_elements - offset_elements), d ); + log_info( "Testing random fill from offset %d for %d elements: \n", (int)offset_elements, (int)fill_elements ); + + for ( i = 0; i < 5; i++ ){ + pattern[i] = (cl_long *)malloc(ptrSizes[i]); + for ( j = 0; j < ptrSizes[i] / ptrSizes[0]; j++ ) + pattern[i][j] = TEST_PRIME_LONG; + + inptr[i] = (cl_long *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + for ( j = 0; j < ptrSizes[i] * offset_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + for ( j = ptrSizes[i] * offset_elements / ptrSizes[0]; j < ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j++ ) + inptr[i][j] = TEST_PRIME_LONG; + for ( j = ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j < ptrSizes[i] * num_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + + hostptr[i] = (cl_long *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + memset(hostptr[i], 0, ptrSizes[i] * num_elements); + } + + if (test_buffer_fill( deviceID, context, queue, num_elements, sizeof( cl_long ), (char*)"long", + 5, (void**)inptr, (void**)hostptr, (void**)pattern, + offset_elements, fill_elements, + buffer_fill_long_kernel_code, long_kernel_name, foo )) + err++; + + for ( i = 0; i < 5; i++ ){ + free( (void *)pattern[i] ); + align_free( (void *)inptr[i] ); + align_free( (void *)hostptr[i] ); + } + + } + + free_mtdata(d); + + return err; + +} // end test_buffer_long_fill() + + +int test_buffer_fill_ulong( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_ulong *inptr[5]; + cl_ulong *hostptr[5]; + cl_ulong *pattern[5]; + size_t ptrSizes[5]; + int n, i, err=0; + size_t j, offset_elements, fill_elements; + MTdata d = init_genrand( gRandomSeed ); + int (*foo)(void *,void *,int); + + size_t min_alignment = get_min_alignment(context); + + foo = verify_fill_ulong; + + ptrSizes[0] = sizeof(cl_ulong); + ptrSizes[1] = ptrSizes[0] << 1; + ptrSizes[2] = ptrSizes[1] << 1; + ptrSizes[3] = ptrSizes[2] << 1; + ptrSizes[4] = ptrSizes[3] << 1; + + if (! gHasLong ) + { + log_info( "Device does not support 64-bit integers. Skipping test.\n" ); + return CL_SUCCESS; + } + + // Test with random offsets and fill sizes + for ( n = 0; n < 8; n++ ){ + offset_elements = (size_t)get_random_float( 0.f, (float)(num_elements - 8), d ); + fill_elements = (size_t)get_random_float( 8.f, (float)(num_elements - offset_elements), d ); + log_info( "Testing random fill from offset %d for %d elements: \n", (int)offset_elements, (int)fill_elements ); + + for ( i = 0; i < 5; i++ ){ + pattern[i] = (cl_ulong *)malloc(ptrSizes[i]); + for ( j = 0; j < ptrSizes[i] / ptrSizes[0]; j++ ) + pattern[i][j] = TEST_PRIME_ULONG; + + inptr[i] = (cl_ulong *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + for ( j = 0; j < ptrSizes[i] * offset_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + for ( j = ptrSizes[i] * offset_elements / ptrSizes[0]; j < ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j++ ) + inptr[i][j] = TEST_PRIME_ULONG; + for ( j = ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j < ptrSizes[i] * num_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + + hostptr[i] = (cl_ulong *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + memset(hostptr[i], 0, ptrSizes[i] * num_elements); + } + + if (test_buffer_fill( deviceID, context, queue, num_elements, sizeof( cl_ulong ), (char*)"ulong", + 5, (void**)inptr, (void**)hostptr, (void**)pattern, + offset_elements, fill_elements, + buffer_fill_ulong_kernel_code, ulong_kernel_name, foo )) + err++; + + for ( i = 0; i < 5; i++ ){ + free( (void *)pattern[i] ); + align_free( (void *)inptr[i] ); + align_free( (void *)hostptr[i] ); + } + + } + + free_mtdata(d); + + return err; + +} // end test_buffer_ulong_fill() + + +int test_buffer_fill_float( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_float *inptr[5]; + cl_float *hostptr[5]; + cl_float *pattern[5]; + size_t ptrSizes[5]; + int n, i, err=0; + size_t j, offset_elements, fill_elements; + MTdata d = init_genrand( gRandomSeed ); + int (*foo)(void *,void *,int); + + size_t min_alignment = get_min_alignment(context); + + foo = verify_fill_float; + + ptrSizes[0] = sizeof(cl_float); + ptrSizes[1] = ptrSizes[0] << 1; + ptrSizes[2] = ptrSizes[1] << 1; + ptrSizes[3] = ptrSizes[2] << 1; + ptrSizes[4] = ptrSizes[3] << 1; + + // Test with random offsets and fill sizes + for ( n = 0; n < 8; n++ ){ + offset_elements = (size_t)get_random_float( 0.f, (float)(num_elements - 8), d ); + fill_elements = (size_t)get_random_float( 8.f, (float)(num_elements - offset_elements), d ); + log_info( "Testing random fill from offset %d for %d elements: \n", (int)offset_elements, (int)fill_elements ); + + for ( i = 0; i < 5; i++ ){ + pattern[i] = (cl_float *)malloc(ptrSizes[i]); + for ( j = 0; j < ptrSizes[i] / ptrSizes[0]; j++ ) + pattern[i][j] = TEST_PRIME_FLOAT; + + inptr[i] = (cl_float *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + for ( j = 0; j < ptrSizes[i] * offset_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + for ( j = ptrSizes[i] * offset_elements / ptrSizes[0]; j < ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j++ ) + inptr[i][j] = TEST_PRIME_FLOAT; + for ( j = ptrSizes[i] * (offset_elements + fill_elements) / ptrSizes[0]; j < ptrSizes[i] * num_elements / ptrSizes[0]; j++ ) + inptr[i][j] = 0; + + hostptr[i] = (cl_float *)align_malloc(ptrSizes[i] * num_elements, min_alignment); + memset(hostptr[i], 0, ptrSizes[i] * num_elements); + } + + if (test_buffer_fill( deviceID, context, queue, num_elements, sizeof( cl_float ), (char*)"float", + 5, (void**)inptr, (void**)hostptr, (void**)pattern, + offset_elements, fill_elements, + buffer_fill_float_kernel_code, float_kernel_name, foo )) + err++; + + for ( i = 0; i < 5; i++ ){ + free( (void *)pattern[i] ); + align_free( (void *)inptr[i] ); + align_free( (void *)hostptr[i] ); + } + + } + + free_mtdata(d); + + return err; + +} // end test_buffer_float_fill() diff --git a/test_conformance/buffers/test_buffer_map.c b/test_conformance/buffers/test_buffer_map.c new file mode 100644 index 00000000..0f7089da --- /dev/null +++ b/test_conformance/buffers/test_buffer_map.c @@ -0,0 +1,703 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/errorHelpers.h" + + +#define TEST_PRIME_INT ((1<<16)+1) +#define TEST_PRIME_UINT ((1U<<16)+1U) +#define TEST_PRIME_LONG ((1LL<<32)+1LL) +#define TEST_PRIME_ULONG ((1ULL<<32)+1ULL) +#define TEST_PRIME_SHORT ((1S<<8)+1S) +#define TEST_PRIME_FLOAT (float)3.40282346638528860e+38 +#define TEST_PRIME_HALF 119.f +#define TEST_BOOL true +#define TEST_PRIME_CHAR 0x77 + + +#ifndef TestStruct +typedef struct{ + int a; + float b; +} TestStruct; +#endif + + +//--- the code for the kernel executables +static const char *buffer_read_int_kernel_code[] = { + "__kernel void test_buffer_read_int(__global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1<<16)+1);\n" + "}\n", + + "__kernel void test_buffer_read_int2(__global int2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1<<16)+1);\n" + "}\n", + + "__kernel void test_buffer_read_int4(__global int4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1<<16)+1);\n" + "}\n", + + "__kernel void test_buffer_read_int8(__global int8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1<<16)+1);\n" + "}\n", + + "__kernel void test_buffer_read_int16(__global int16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1<<16)+1);\n" + "}\n" }; + +static const char *int_kernel_name[] = { "test_buffer_read_int", "test_buffer_read_int2", "test_buffer_read_int4", "test_buffer_read_int8", "test_buffer_read_int16" }; + +static const char *buffer_read_uint_kernel_code[] = { + "__kernel void test_buffer_read_uint(__global uint *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1U<<16)+1U);\n" + "}\n", + + "__kernel void test_buffer_read_uint2(__global uint2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1U<<16)+1U);\n" + "}\n", + + "__kernel void test_buffer_read_uint4(__global uint4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1U<<16)+1U);\n" + "}\n", + + "__kernel void test_buffer_read_uint8(__global uint8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1U<<16)+1U);\n" + "}\n", + + "__kernel void test_buffer_read_uint16(__global uint16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1U<<16)+1U);\n" + "}\n" }; + +static const char *uint_kernel_name[] = { "test_buffer_read_uint", "test_buffer_read_uint2", "test_buffer_read_uint4", "test_buffer_read_uint8", "test_buffer_read_uint16" }; + +static const char *buffer_read_long_kernel_code[] = { + "__kernel void test_buffer_read_long(__global long *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1L<<32)+1L);\n" + "}\n", + + "__kernel void test_buffer_read_long2(__global long2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1L<<32)+1L);\n" + "}\n", + + "__kernel void test_buffer_read_long4(__global long4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1L<<32)+1L);\n" + "}\n", + + "__kernel void test_buffer_read_long8(__global long8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1L<<32)+1L);\n" + "}\n", + + "__kernel void test_buffer_read_long16(__global long16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1L<<32)+1L);\n" + "}\n" }; + +static const char *long_kernel_name[] = { "test_buffer_read_long", "test_buffer_read_long2", "test_buffer_read_long4", "test_buffer_read_long8", "test_buffer_read_long16" }; + +static const char *buffer_read_ulong_kernel_code[] = { + "__kernel void test_buffer_read_ulong(__global ulong *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1UL<<32)+1UL);\n" + "}\n", + + "__kernel void test_buffer_read_ulong2(__global ulong2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1UL<<32)+1UL);\n" + "}\n", + + "__kernel void test_buffer_read_ulong4(__global ulong4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1UL<<32)+1UL);\n" + "}\n", + + "__kernel void test_buffer_read_ulong8(__global ulong8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1UL<<32)+1UL);\n" + "}\n", + + "__kernel void test_buffer_read_ulong16(__global ulong16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1UL<<32)+1UL);\n" + "}\n" }; + +static const char *ulong_kernel_name[] = { "test_buffer_read_ulong", "test_buffer_read_ulong2", "test_buffer_read_ulong4", "test_buffer_read_ulong8", "test_buffer_read_ulong16" }; + +static const char *buffer_read_short_kernel_code[] = { + "__kernel void test_buffer_read_short(__global short *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (short)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_short2(__global short2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (short)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_short4(__global short4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (short)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_short8(__global short8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (short)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_short16(__global short16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (short)((1<<8)+1);\n" + "}\n" }; + +static const char *short_kernel_name[] = { "test_buffer_read_short", "test_buffer_read_short2", "test_buffer_read_short4", "test_buffer_read_short8", "test_buffer_read_short16" }; + + +static const char *buffer_read_ushort_kernel_code[] = { + "__kernel void test_buffer_read_ushort(__global ushort *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (ushort)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_ushort2(__global ushort2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (ushort)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_ushort4(__global ushort4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (ushort)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_ushort8(__global ushort8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (ushort)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_ushort16(__global ushort16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (ushort)((1<<8)+1);\n" + "}\n" }; + +static const char *ushort_kernel_name[] = { "test_buffer_read_ushort", "test_buffer_read_ushort2", "test_buffer_read_ushort4", "test_buffer_read_ushort8", "test_buffer_read_ushort16" }; + + +static const char *buffer_read_float_kernel_code[] = { + "__kernel void test_buffer_read_float(__global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (float)3.40282346638528860e+38;\n" + "}\n", + + "__kernel void test_buffer_read_float2(__global float2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (float)3.40282346638528860e+38;\n" + "}\n", + + "__kernel void test_buffer_read_float4(__global float4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (float)3.40282346638528860e+38;\n" + "}\n", + + "__kernel void test_buffer_read_float8(__global float8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (float)3.40282346638528860e+38;\n" + "}\n", + + "__kernel void test_buffer_read_float16(__global float16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (float)3.40282346638528860e+38;\n" + "}\n" }; + +static const char *float_kernel_name[] = { "test_buffer_read_float", "test_buffer_read_float2", "test_buffer_read_float4", "test_buffer_read_float8", "test_buffer_read_float16" }; + + +static const char *buffer_read_char_kernel_code[] = { + "__kernel void test_buffer_read_char(__global char *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (char)'w';\n" + "}\n", + + "__kernel void test_buffer_read_char2(__global char2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (char)'w';\n" + "}\n", + + "__kernel void test_buffer_read_char4(__global char4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (char)'w';\n" + "}\n", + + "__kernel void test_buffer_read_char8(__global char8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (char)'w';\n" + "}\n", + + "__kernel void test_buffer_read_char16(__global char16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (char)'w';\n" + "}\n" }; + +static const char *char_kernel_name[] = { "test_buffer_read_char", "test_buffer_read_char2", "test_buffer_read_char4", "test_buffer_read_char8", "test_buffer_read_char16" }; + + +static const char *buffer_read_uchar_kernel_code[] = { + "__kernel void test_buffer_read_uchar(__global uchar *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = 'w';\n" + "}\n", + + "__kernel void test_buffer_read_uchar2(__global uchar2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (uchar)'w';\n" + "}\n", + + "__kernel void test_buffer_read_uchar4(__global uchar4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (uchar)'w';\n" + "}\n", + + "__kernel void test_buffer_read_uchar8(__global uchar8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (uchar)'w';\n" + "}\n", + + "__kernel void test_buffer_read_uchar16(__global uchar16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (uchar)'w';\n" + "}\n" }; + +static const char *uchar_kernel_name[] = { "test_buffer_read_uchar", "test_buffer_read_uchar2", "test_buffer_read_uchar4", "test_buffer_read_uchar8", "test_buffer_read_uchar16" }; + + +static const char *buffer_read_struct_kernel_code[] = { + "typedef struct{\n" + "int a;\n" + "float b;\n" + "} TestStruct;\n" + "__kernel void test_buffer_read_struct(__global TestStruct *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid].a = ((1<<16)+1);\n" + " dst[tid].b = (float)3.40282346638528860e+38;\n" + "}\n" }; + +static const char *struct_kernel_name[] = { "test_buffer_read_struct" }; + + +//--- the verify functions +static int verify_read_int(void *ptr, int n) +{ + int i; + int *outptr = (int *)ptr; + + for (i=0; i +#include +#include +#include +#include + +#include "procs.h" + +#ifndef uchar +typedef unsigned char uchar; +#endif + +#define USE_LOCAL_WORK_GROUP 1 + + +const char *mem_read_write_kernel_code = +"__kernel void test_mem_read_write(__global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = dst[tid]+1;\n" +"}\n"; + +const char *mem_read_kernel_code = +"__kernel void test_mem_read(__global int *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = src[tid]+1;\n" +"}\n"; + +const char *mem_write_kernel_code = +"__kernel void test_mem_write(__global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = dst[tid]+1;\n" +"}\n"; + + +static int verify_mem( int *outptr, int n ) +{ + int i; + + for ( i = 0; i < n; i++ ){ + if ( outptr[i] != ( i + 1 ) ) + return -1; + } + + return 0; +} + + + +int test_mem_read_write_flags( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_mem buffers[1]; + cl_int *inptr, *outptr; + cl_program program[1]; + cl_kernel kernel[1]; + size_t global_work_size[3]; +#ifdef USE_LOCAL_WORK_GROUP + size_t local_work_size[3]; +#endif + cl_int err; + int i; + + size_t min_alignment = get_min_alignment(context); + + global_work_size[0] = (cl_uint)num_elements; + + inptr = (cl_int*)align_malloc(sizeof(cl_int) * num_elements, min_alignment); + outptr = (cl_int*)align_malloc(sizeof(cl_int) * num_elements, min_alignment); + buffers[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int) * num_elements, NULL, &err); + if (err != CL_SUCCESS) { + print_error( err, "clCreateBuffer failed"); + align_free( (void *)outptr ); + align_free( (void *)inptr ); + return -1; + } + + for (i=0; i +#include + +#include "procs.h" +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/testHarness.h" + +#define MAX_SUB_DEVICES 16 // Limit the sub-devices to ensure no out of resource errors. +#define BUFFER_SIZE 1024 + +// Kernel source code +static const char *buffer_migrate_kernel_code = +"__kernel void test_buffer_migrate(__global uint *dst, __global uint *src1, __global uint *src2, uint x)\n" +"{\n" +" int tid = get_global_id(0);\n" +" dst[tid] = src1[tid] ^ src2[tid] ^ x;\n" +"}\n"; + +enum migrations { MIGRATE_PREFERRED, // migrate to the preferred sub-device + MIGRATE_NON_PREFERRED, // migrate to a randomly chosen non-preferred sub-device + MIGRATE_RANDOM, // migrate to a randomly chosen sub-device with randomly chosen flags + NUMBER_OF_MIGRATIONS }; + +static cl_mem init_buffer(cl_command_queue cmd_q, cl_mem buffer, cl_uint *data) +{ + cl_int err; + + if (buffer) { + if ((err = clEnqueueWriteBuffer(cmd_q, buffer, CL_TRUE, 0, sizeof(cl_uint)*BUFFER_SIZE, data, 0, NULL, NULL)) != CL_SUCCESS) { + print_error(err, "Failed on enqueue write of buffer data."); + } + } + return buffer; +} + +static cl_int migrateMemObject(enum migrations migrate, cl_command_queue *queues, cl_mem *mem_objects, cl_uint num_devices, cl_mem_migration_flags *flags, MTdata d) +{ + cl_uint i, j; + cl_int err = CL_SUCCESS; + + for (i=0; i 1)) j = (j+1) % num_devices; + break; + case MIGRATE_RANDOM: + // Choose a random set of flags + flags[i] = (cl_mem_migration_flags)(genrand_int32(d) & (CL_MIGRATE_MEM_OBJECT_HOST | CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED));; + break; + } + if ((err = clEnqueueMigrateMemObjects(queues[j], 1, (const cl_mem *)(&mem_objects[i]), flags[i], 0, NULL, NULL)) != CL_SUCCESS) { + print_error(err, "Failed migrating memory object."); + } + } + return err; +} + +static cl_int restoreBuffer(cl_command_queue *queues, cl_mem *buffers, cl_uint num_devices, cl_mem_migration_flags *flags, cl_uint *buffer) +{ + cl_uint i, j; + cl_int err; + + // If the buffer was previously migrated with undefined content, reload the content. + + for (i=0; i 1) { + // Create each of the sub-devices and a corresponding context. + if ((err = clCreateSubDevices(deviceID, (const cl_device_partition_property *)property, num_devices, devices, &num_devices)) != CL_SUCCESS) { + print_error(err, "Failed creating sub devices."); + failed = 1; + goto cleanup; + } + + // Create a context containing all the sub-devices + ctx = clCreateContext(NULL, num_devices, devices, notify_callback, NULL, &err); + if (ctx == NULL) { + print_error(err, "Failed creating context containing the sub-devices."); + failed = 1; + goto cleanup; + } + + // Create a command queue for each sub-device + for (i=0; i 1) { + // Command queue cleanup + if (queues[i]) { + if ((err = clReleaseCommandQueue(queues[i])) != CL_SUCCESS) { + print_error(err, "Failed releasing command queue."); + failed = 1; + } + } + + // Sub-device cleanup + if (devices[i]) { + if ((err = clReleaseDevice(devices[i])) != CL_SUCCESS) { + print_error(err, "Failed releasing sub device."); + failed = 1; + } + } + devices[i] = 0; + } + } + + // Context, program, and kernel cleanup + if (program) { + if ((err = clReleaseProgram(program)) != CL_SUCCESS) { + print_error(err, "Failed releasing program."); + failed = 1; + } + program = NULL; + } + + if (kernel) { + if ((err = clReleaseKernel(kernel)) != CL_SUCCESS) { + print_error(err, "Failed releasing kernel."); + failed = 1; + } + kernel = NULL; + } + + if (ctx && (ctx != context)) { + if ((err = clReleaseContext(ctx)) != CL_SUCCESS) { + print_error(err, "Failed releasing context."); + failed = 1; + } + } + ctx = NULL; + + if (failed) goto cleanup_allocations; + } while (domains); + +cleanup_allocations: + if (devices) free(devices); + if (queues) free(queues); + if (flagsA) free(flagsA); + if (flagsB) free(flagsB); + if (flagsC) free(flagsC); + if (bufferA) free(bufferA); + if (bufferB) free(bufferB); + if (bufferC) free(bufferC); + + return ((failed) ? -1 : 0); +} diff --git a/test_conformance/buffers/test_buffer_read.c b/test_conformance/buffers/test_buffer_read.c new file mode 100644 index 00000000..2755afec --- /dev/null +++ b/test_conformance/buffers/test_buffer_read.c @@ -0,0 +1,1463 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include +#include + +#include "procs.h" + +//#define HK_DO_NOT_RUN_SHORT_ASYNC 1 +//#define HK_DO_NOT_RUN_USHORT_ASYNC 1 +//#define HK_DO_NOT_RUN_CHAR_ASYNC 1 +//#define HK_DO_NOT_RUN_UCHAR_ASYNC 1 + +#define TEST_PRIME_INT ((1<<16)+1) +#define TEST_PRIME_UINT ((1U<<16)+1U) +#define TEST_PRIME_LONG ((1LL<<32)+1LL) +#define TEST_PRIME_ULONG ((1ULL<<32)+1ULL) +#define TEST_PRIME_SHORT ((1S<<8)+1S) +#define TEST_PRIME_FLOAT (float)3.40282346638528860e+38 +#define TEST_PRIME_HALF 119.f +#define TEST_BOOL true +#define TEST_PRIME_CHAR 0x77 + +#ifndef ulong +typedef unsigned long ulong; +#endif + +#ifndef uchar +typedef unsigned char uchar; +#endif + +#ifndef TestStruct +typedef struct{ + int a; + float b; +} TestStruct; +#endif + +//--- the code for the kernel executables +static const char *buffer_read_int_kernel_code[] = { + "__kernel void test_buffer_read_int(__global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1<<16)+1);\n" + "}\n", + + "__kernel void test_buffer_read_int2(__global int2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1<<16)+1);\n" + "}\n", + + "__kernel void test_buffer_read_int4(__global int4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1<<16)+1);\n" + "}\n", + + "__kernel void test_buffer_read_int8(__global int8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1<<16)+1);\n" + "}\n", + + "__kernel void test_buffer_read_int16(__global int16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1<<16)+1);\n" + "}\n" }; + +static const char *int_kernel_name[] = { "test_buffer_read_int", "test_buffer_read_int2", "test_buffer_read_int4", "test_buffer_read_int8", "test_buffer_read_int16" }; + +static const char *buffer_read_uint_kernel_code[] = { + "__kernel void test_buffer_read_uint(__global uint *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1U<<16)+1U);\n" + "}\n", + + "__kernel void test_buffer_read_uint2(__global uint2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1U<<16)+1U);\n" + "}\n", + + "__kernel void test_buffer_read_uint4(__global uint4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1U<<16)+1U);\n" + "}\n", + + "__kernel void test_buffer_read_uint8(__global uint8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1U<<16)+1U);\n" + "}\n", + + "__kernel void test_buffer_read_uint16(__global uint16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1U<<16)+1U);\n" + "}\n" }; + +static const char *uint_kernel_name[] = { "test_buffer_read_uint", "test_buffer_read_uint2", "test_buffer_read_uint4", "test_buffer_read_uint8", "test_buffer_read_uint16" }; + +static const char *buffer_read_long_kernel_code[] = { + "__kernel void test_buffer_read_long(__global long *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1L<<32)+1L);\n" + "}\n", + + "__kernel void test_buffer_read_long2(__global long2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1L<<32)+1L);\n" + "}\n", + + "__kernel void test_buffer_read_long4(__global long4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1L<<32)+1L);\n" + "}\n", + + "__kernel void test_buffer_read_long8(__global long8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1L<<32)+1L);\n" + "}\n", + + "__kernel void test_buffer_read_long16(__global long16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1L<<32)+1L);\n" + "}\n" }; + +static const char *long_kernel_name[] = { "test_buffer_read_long", "test_buffer_read_long2", "test_buffer_read_long4", "test_buffer_read_long8", "test_buffer_read_long16" }; + +static const char *buffer_read_ulong_kernel_code[] = { + "__kernel void test_buffer_read_ulong(__global ulong *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1UL<<32)+1UL);\n" + "}\n", + + "__kernel void test_buffer_read_ulong2(__global ulong2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1UL<<32)+1UL);\n" + "}\n", + + "__kernel void test_buffer_read_ulong4(__global ulong4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1UL<<32)+1UL);\n" + "}\n", + + "__kernel void test_buffer_read_ulong8(__global ulong8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1UL<<32)+1UL);\n" + "}\n", + + "__kernel void test_buffer_read_ulong16(__global ulong16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = ((1UL<<32)+1UL);\n" + "}\n" }; + +static const char *ulong_kernel_name[] = { "test_buffer_read_ulong", "test_buffer_read_ulong2", "test_buffer_read_ulong4", "test_buffer_read_ulong8", "test_buffer_read_ulong16" }; + +static const char *buffer_read_short_kernel_code[] = { + "__kernel void test_buffer_read_short(__global short *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (short)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_short2(__global short2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (short)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_short4(__global short4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (short)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_short8(__global short8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (short)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_short16(__global short16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (short)((1<<8)+1);\n" + "}\n" }; + +static const char *short_kernel_name[] = { "test_buffer_read_short", "test_buffer_read_short2", "test_buffer_read_short4", "test_buffer_read_short8", "test_buffer_read_short16" }; + + +static const char *buffer_read_ushort_kernel_code[] = { + "__kernel void test_buffer_read_ushort(__global ushort *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (ushort)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_ushort2(__global ushort2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (ushort)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_ushort4(__global ushort4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (ushort)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_ushort8(__global ushort8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (ushort)((1<<8)+1);\n" + "}\n", + + "__kernel void test_buffer_read_ushort16(__global ushort16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (ushort)((1<<8)+1);\n" + "}\n" }; + +static const char *ushort_kernel_name[] = { "test_buffer_read_ushort", "test_buffer_read_ushort2", "test_buffer_read_ushort4", "test_buffer_read_ushort8", "test_buffer_read_ushort16" }; + + +static const char *buffer_read_float_kernel_code[] = { + "__kernel void test_buffer_read_float(__global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (float)3.40282346638528860e+38;\n" + "}\n", + + "__kernel void test_buffer_read_float2(__global float2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (float)3.40282346638528860e+38;\n" + "}\n", + + "__kernel void test_buffer_read_float4(__global float4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (float)3.40282346638528860e+38;\n" + "}\n", + + "__kernel void test_buffer_read_float8(__global float8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (float)3.40282346638528860e+38;\n" + "}\n", + + "__kernel void test_buffer_read_float16(__global float16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (float)3.40282346638528860e+38;\n" + "}\n" }; + +static const char *float_kernel_name[] = { "test_buffer_read_float", "test_buffer_read_float2", "test_buffer_read_float4", "test_buffer_read_float8", "test_buffer_read_float16" }; + + +static const char *buffer_read_half_kernel_code[] = { + "__kernel void test_buffer_read_half(__global half *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (half)119;\n" + "}\n", + + "__kernel void test_buffer_read_half2(__global half2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (half)119;\n" + "}\n", + + "__kernel void test_buffer_read_half4(__global half4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (half)119;\n" + "}\n", + + "__kernel void test_buffer_read_half8(__global half8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (half)119;\n" + "}\n", + + "__kernel void test_buffer_read_half16(__global half16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (half)119;\n" + "}\n" }; + +static const char *half_kernel_name[] = { "test_buffer_read_half", "test_buffer_read_half2", "test_buffer_read_half4", "test_buffer_read_half8", "test_buffer_read_half16" }; + + +static const char *buffer_read_char_kernel_code[] = { + "__kernel void test_buffer_read_char(__global char *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (char)'w';\n" + "}\n", + + "__kernel void test_buffer_read_char2(__global char2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (char)'w';\n" + "}\n", + + "__kernel void test_buffer_read_char4(__global char4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (char)'w';\n" + "}\n", + + "__kernel void test_buffer_read_char8(__global char8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (char)'w';\n" + "}\n", + + "__kernel void test_buffer_read_char16(__global char16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (char)'w';\n" + "}\n" }; + +static const char *char_kernel_name[] = { "test_buffer_read_char", "test_buffer_read_char2", "test_buffer_read_char4", "test_buffer_read_char8", "test_buffer_read_char16" }; + + +static const char *buffer_read_uchar_kernel_code[] = { + "__kernel void test_buffer_read_uchar(__global uchar *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = 'w';\n" + "}\n", + + "__kernel void test_buffer_read_uchar2(__global uchar2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (uchar)'w';\n" + "}\n", + + "__kernel void test_buffer_read_uchar4(__global uchar4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (uchar)'w';\n" + "}\n", + + "__kernel void test_buffer_read_uchar8(__global uchar8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (uchar)'w';\n" + "}\n", + + "__kernel void test_buffer_read_uchar16(__global uchar16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (uchar)'w';\n" + "}\n" }; + +static const char *uchar_kernel_name[] = { "test_buffer_read_uchar", "test_buffer_read_uchar2", "test_buffer_read_uchar4", "test_buffer_read_uchar8", "test_buffer_read_uchar16" }; + + +static const char *buffer_read_struct_kernel_code = +"typedef struct{\n" +"int a;\n" +"float b;\n" +"} TestStruct;\n" +"__kernel void test_buffer_read_struct(__global TestStruct *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid].a = ((1<<16)+1);\n" +" dst[tid].b = (float)3.40282346638528860e+38;\n" +"}\n"; + + +//--- the verify functions +static int verify_read_int(void *ptr, int n) +{ + int i; + cl_int *outptr = (cl_int *)ptr; + + for (i=0; i> 1 ) ){ + log_error( "buffer_READ half test failed\n" ); + err = -1; + } + else{ + log_info( "buffer_READ half test passed\n" ); + err = 0; + } + + // cleanup + clReleaseMemObject( buffers[0] ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + free( (void *)outptr ); + + return err; + + } // end test_buffer_half_read() + */ + +int test_buffer_read_struct(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem buffers[1]; + TestStruct *output_ptr; + cl_program program[1]; + cl_kernel kernel[1]; + size_t global_work_size[3]; +#ifdef USE_LOCAL_WORK_GROUP + size_t local_work_size[3]; +#endif + cl_int err; + size_t objSize = sizeof(TestStruct); + + size_t min_alignment = get_min_alignment(context); + + global_work_size[0] = (cl_uint)num_elements; + + output_ptr = (TestStruct*)align_malloc(objSize * num_elements, min_alignment); + if ( ! output_ptr ){ + log_error( " unable to allocate %d bytes for output_ptr\n", (int)(objSize * num_elements) ); + return -1; + } + buffers[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), objSize * num_elements, NULL , &err); + if ( err != CL_SUCCESS ){ + print_error( err, " clCreateBuffer failed\n" ); + align_free( output_ptr ); + return -1; + } + + err = create_single_kernel_helper( context, &program[0], &kernel[0], 1, &buffer_read_struct_kernel_code, "test_buffer_read_struct" ); + if ( err ){ + clReleaseProgram( program[0] ); + align_free( output_ptr ); + return -1; + } + + err = clSetKernelArg( kernel[0], 0, sizeof( cl_mem ), (void *)&buffers[0] ); + if ( err != CL_SUCCESS){ + print_error( err, "clSetKernelArg failed" ); + clReleaseMemObject( buffers[0] ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + align_free( output_ptr ); + return -1; + } + +#ifdef USE_LOCAL_WORK_GROUP + err = get_max_common_work_group_size( context, kernel[0], global_work_size[0], &local_work_size[0] ); + test_error( err, "Unable to get work group size to use" ); + + err = clEnqueueNDRangeKernel( queue, kernel[0], 1, NULL, global_work_size, local_work_size, 0, NULL, NULL ); +#else + err = clEnqueueNDRangeKernel( queue, kernel[0], 1, NULL, global_work_size, NULL, 0, NULL, NULL ); +#endif + if ( err != CL_SUCCESS ){ + print_error( err, "clEnqueueNDRangeKernel failed" ); + clReleaseMemObject( buffers[0] ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + align_free( output_ptr ); + return -1; + } + + err = clEnqueueReadBuffer( queue, buffers[0], true, 0, objSize*num_elements, (void *)output_ptr, 0, NULL, NULL ); + if ( err != CL_SUCCESS){ + print_error( err, "clEnqueueReadBuffer failed" ); + clReleaseMemObject( buffers[0] ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + align_free( output_ptr ); + return -1; + } + + if (verify_read_struct(output_ptr, num_elements)){ + log_error(" struct test failed\n"); + err = -1; + } + else{ + log_info(" struct test passed\n"); + err = 0; + } + + // cleanup + clReleaseMemObject( buffers[0] ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + align_free( output_ptr ); + + return err; +} + + +static int testRandomReadSize( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, cl_uint startOfRead, size_t sizeOfRead ) +{ + cl_mem buffers[3]; + int *outptr[3]; + cl_program program[3]; + cl_kernel kernel[3]; + size_t global_work_size[3]; +#ifdef USE_LOCAL_WORK_GROUP + size_t local_work_size[3]; +#endif + cl_int err; + int i, j; + size_t ptrSizes[3]; // sizeof(int), sizeof(int2), sizeof(int4) + int total_errors = 0; + size_t min_alignment = get_min_alignment(context); + + global_work_size[0] = (cl_uint)num_elements; + + ptrSizes[0] = sizeof(cl_int); + ptrSizes[1] = ptrSizes[0] << 1; + ptrSizes[2] = ptrSizes[1] << 1; + for ( i = 0; i < 3; i++ ){ + outptr[i] = (int *)align_malloc( ptrSizes[i] * num_elements, min_alignment); + if ( ! outptr[i] ){ + log_error( " Unable to allocate %d bytes for outptr[%d]\n", (int)(ptrSizes[i] * num_elements), i ); + for ( j = 0; j < i; j++ ){ + clReleaseMemObject( buffers[j] ); + align_free( outptr[j] ); + } + return -1; + } + buffers[i] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), ptrSizes[i] * num_elements, NULL, &err); + if ( err != CL_SUCCESS ){ + print_error(err, " clCreateBuffer failed\n" ); + for ( j = 0; j < i; j++ ){ + clReleaseMemObject( buffers[j] ); + align_free( outptr[j] ); + } + align_free( outptr[i] ); + return -1; + } + } + + err = create_single_kernel_helper( context, &program[0], &kernel[0], 1, &buffer_read_int_kernel_code[0], "test_buffer_read_int" ); + if ( err ){ + log_error( " Error creating program for int\n" ); + for ( i = 0; i < 3; i++ ){ + clReleaseMemObject( buffers[i] ); + align_free( outptr[i] ); + } + return -1; + } + + err = create_single_kernel_helper( context, &program[1], &kernel[1], 1, &buffer_read_int_kernel_code[1], "test_buffer_read_int2" ); + if ( err ){ + log_error( " Error creating program for int2\n" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + for ( i = 0; i < 3; i++ ){ + clReleaseMemObject( buffers[i] ); + align_free( outptr[i] ); + } + return -1; + } + + err = create_single_kernel_helper( context, &program[2], &kernel[2], 1, &buffer_read_int_kernel_code[2], "test_buffer_read_int4" ); + if ( err ){ + log_error( " Error creating program for int4\n" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseKernel( kernel[1] ); + clReleaseProgram( program[1] ); + for ( i = 0; i < 3; i++ ){ + clReleaseMemObject( buffers[i] ); + align_free( outptr[i] ); + } + return -1; + } + + for (i=0; i<3; i++){ + err = clSetKernelArg( kernel[i], 0, sizeof( cl_mem ), (void *)&buffers[i] ); + if ( err != CL_SUCCESS ){ + print_error( err, "clSetKernelArgs failed" ); + clReleaseMemObject( buffers[i] ); + clReleaseKernel( kernel[i] ); + clReleaseProgram( program[i] ); + align_free( outptr[i] ); + return -1; + } + +#ifdef USE_LOCAL_WORK_GROUP + err = get_max_common_work_group_size( context, kernel[i], global_work_size[0], &local_work_size[0] ); + test_error( err, "Unable to get work group size to use" ); + + err = clEnqueueNDRangeKernel( queue, kernel[i], 1, NULL, global_work_size, local_work_size, 0, NULL, NULL ); +#else + err = clEnqueueNDRangeKernel( queue, kernel[i], 1, NULL, global_work_size, NULL, 0, NULL, NULL ); +#endif + if ( err != CL_SUCCESS ){ + print_error( err, "clEnqueueNDRangeKernel failed" ); + clReleaseMemObject( buffers[i] ); + clReleaseKernel( kernel[i] ); + clReleaseProgram( program[i] ); + align_free( outptr[i] ); + return -1; + } + + err = clEnqueueReadBuffer( queue, buffers[i], true, startOfRead*ptrSizes[i], ptrSizes[i]*sizeOfRead, (void *)(outptr[i]), 0, NULL, NULL ); + if ( err != CL_SUCCESS ){ + print_error( err, "clEnqueueReadBuffer failed" ); + clReleaseMemObject( buffers[i] ); + clReleaseKernel( kernel[i] ); + clReleaseProgram( program[i] ); + align_free( outptr[i] ); + return -1; + } + + if ( verify_read_int( outptr[i], (int)sizeOfRead*(1< +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/errorHelpers.h" + +#define USE_LOCAL_WORK_GROUP 1 + +#ifndef uchar +typedef unsigned char uchar; +#endif + +#ifndef TestStruct +typedef struct{ + int a; + float b; +} TestStruct; +#endif + +// If this is set to 1 the writes are done via map/unmap +static int gTestMap = 0; + +const char *buffer_write_int_kernel_code[] = { + "__kernel void test_buffer_write_int(__global int *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_int2(__global int2 *src, __global int2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_int4(__global int4 *src, __global int4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_int8(__global int8 *src, __global int8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_int16(__global int16 *src, __global int16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *int_kernel_name[] = { "test_buffer_write_int", "test_buffer_write_int2", "test_buffer_write_int4", "test_buffer_write_int8", "test_buffer_write_int16" }; + + +const char *buffer_write_uint_kernel_code[] = { + "__kernel void test_buffer_write_uint(__global uint *src, __global uint *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_uint2(__global uint2 *src, __global uint2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_uint4(__global uint4 *src, __global uint4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_uint8(__global uint8 *src, __global uint8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_uint16(__global uint16 *src, __global uint16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *uint_kernel_name[] = { "test_buffer_write_uint", "test_buffer_write_uint2", "test_buffer_write_uint4", "test_buffer_write_uint8", "test_buffer_write_uint16" }; + + +const char *buffer_write_ushort_kernel_code[] = { + "__kernel void test_buffer_write_ushort(__global ushort *src, __global ushort *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_ushort2(__global ushort2 *src, __global ushort2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_ushort4(__global ushort4 *src, __global ushort4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_ushort8(__global ushort8 *src, __global ushort8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_ushort16(__global ushort16 *src, __global ushort16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *ushort_kernel_name[] = { "test_buffer_write_ushort", "test_buffer_write_ushort2", "test_buffer_write_ushort4", "test_buffer_write_ushort8", "test_buffer_write_ushort16" }; + + + +const char *buffer_write_short_kernel_code[] = { + "__kernel void test_buffer_write_short(__global short *src, __global short *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_short2(__global short2 *src, __global short2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_short4(__global short4 *src, __global short4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_short8(__global short8 *src, __global short8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_short16(__global short16 *src, __global short16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *short_kernel_name[] = { "test_buffer_write_short", "test_buffer_write_short2", "test_buffer_write_short4", "test_buffer_write_short8", "test_buffer_write_short16" }; + + +const char *buffer_write_char_kernel_code[] = { + "__kernel void test_buffer_write_char(__global char *src, __global char *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_char2(__global char2 *src, __global char2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_char4(__global char4 *src, __global char4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_char8(__global char8 *src, __global char8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_char16(__global char16 *src, __global char16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *char_kernel_name[] = { "test_buffer_write_char", "test_buffer_write_char2", "test_buffer_write_char4", "test_buffer_write_char8", "test_buffer_write_char16" }; + + +const char *buffer_write_uchar_kernel_code[] = { + "__kernel void test_buffer_write_uchar(__global uchar *src, __global uchar *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_uchar2(__global uchar2 *src, __global uchar2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_uchar4(__global uchar4 *src, __global uchar4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_uchar8(__global uchar8 *src, __global uchar8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_uchar16(__global uchar16 *src, __global uchar16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *uchar_kernel_name[] = { "test_buffer_write_uchar", "test_buffer_write_uchar2", "test_buffer_write_uchar4", "test_buffer_write_uchar8", "test_buffer_write_uchar16" }; + + +const char *buffer_write_float_kernel_code[] = { + "__kernel void test_buffer_write_float(__global float *src, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_float2(__global float2 *src, __global float2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_float4(__global float4 *src, __global float4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_float8(__global float8 *src, __global float8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_float16(__global float16 *src, __global float16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *float_kernel_name[] = { "test_buffer_write_float", "test_buffer_write_float2", "test_buffer_write_float4", "test_buffer_write_float8", "test_buffer_write_float16" }; + + +const char *buffer_write_half_kernel_code[] = { + "__kernel void test_buffer_write_half(__global half *src, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = vload_half( tid * 2, src );\n" + "}\n", + + "__kernel void test_buffer_write_half2(__global half2 *src, __global float2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = vload_half2( tid * 2, src );\n" + "}\n", + + "__kernel void test_buffer_write_half4(__global half4 *src, __global float4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = vload_half4( tid * 2, src );\n" + "}\n", + + "__kernel void test_buffer_write_half8(__global half8 *src, __global float8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = vload_half8( tid * 2, src );\n" + "}\n", + + "__kernel void test_buffer_write_half16(__global half16 *src, __global float16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = vload_half16( tid * 2, src );\n" + "}\n" }; + +static const char *half_kernel_name[] = { "test_buffer_write_half", "test_buffer_write_half2", "test_buffer_write_half4", "test_buffer_write_half8", "test_buffer_write_half16" }; + + +const char *buffer_write_long_kernel_code[] = { + "__kernel void test_buffer_write_long(__global long *src, __global long *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_long2(__global long2 *src, __global long2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_long4(__global long4 *src, __global long4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_long8(__global long8 *src, __global long8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_long16(__global long16 *src, __global long16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *long_kernel_name[] = { "test_buffer_write_long", "test_buffer_write_long2", "test_buffer_write_long4", "test_buffer_write_long8", "test_buffer_write_long16" }; + + +const char *buffer_write_ulong_kernel_code[] = { + "__kernel void test_buffer_write_ulong(__global ulong *src, __global ulong *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_ulong2(__global ulong2 *src, __global ulong2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_ulong4(__global ulong4 *src, __global ulong4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_ulong8(__global ulong8 *src, __global ulong8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_buffer_write_ulong16(__global ulong16 *src, __global ulong16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *ulong_kernel_name[] = { "test_buffer_write_ulong", "test_buffer_write_ulong2", "test_buffer_write_ulong4", "test_buffer_write_ulong8", "test_buffer_write_ulong16" }; + + +static const char *struct_kernel_code = +"typedef struct{\n" +"int a;\n" +"float b;\n" +"} TestStruct;\n" +"__kernel void read_write_struct(__global TestStruct *src, __global TestStruct *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid].a = src[tid].a;\n" +" dst[tid].b = src[tid].b;\n" +"}\n"; + + + +static int verify_write_int( void *ptr1, void *ptr2, int n ) +{ + int i; + int *inptr = (int *)ptr1; + int *outptr = (int *)ptr2; + + for (i=0; i +#include + +#include "procs.h" +#include "../../test_common/harness/errorHelpers.h" + +#define MAX_SUB_DEVICES 16 // Limit the sub-devices to ensure no out of resource errors. +#define MEM_OBJ_SIZE 1024 +#define IMAGE_DIM 16 + +// Kernel source code +static const char *image_migrate_kernel_code = +"__kernel void test_image_migrate(write_only image2d_t dst, read_only image2d_t src1,\n" +" read_only image2d_t src2, sampler_t sampler, uint x)\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1);\n" +" int2 coords = (int2) {tidX, tidY};\n" +" uint4 val = read_imageui(src1, sampler, coords) ^\n" +" read_imageui(src2, sampler, coords) ^\n" +" x;\n" +" write_imageui(dst, coords, val);\n" +"}\n"; + +enum migrations { MIGRATE_PREFERRED, // migrate to the preferred sub-device + MIGRATE_NON_PREFERRED, // migrate to a randomly chosen non-preferred sub-device + MIGRATE_RANDOM, // migrate to a randomly chosen sub-device with randomly chosen flags + NUMBER_OF_MIGRATIONS }; + +static cl_mem init_image(cl_command_queue cmd_q, cl_mem image, cl_uint *data) +{ + cl_int err; + + size_t origin[3] = {0, 0, 0}; + size_t region[3] = {IMAGE_DIM, IMAGE_DIM, 1}; + + if (image) { + if ((err = clEnqueueWriteImage(cmd_q, image, CL_TRUE, + origin, region, 0, 0, data, 0, NULL, NULL)) != CL_SUCCESS) { + print_error(err, "Failed on enqueue write of image data."); + } + } + + return image; +} + +static cl_int migrateMemObject(enum migrations migrate, cl_command_queue *queues, cl_mem *mem_objects, + cl_uint num_devices, cl_mem_migration_flags *flags, MTdata d) +{ + cl_uint i, j; + cl_int err = CL_SUCCESS; + + for (i=0; i 1)) j = (j+1) % num_devices; + break; + case MIGRATE_RANDOM: + // Choose a random set of flags + flags[i] = (cl_mem_migration_flags)(genrand_int32(d) & (CL_MIGRATE_MEM_OBJECT_HOST | CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED)); + break; + } + if ((err = clEnqueueMigrateMemObjects(queues[j], 1, (const cl_mem *)(&mem_objects[i]), + flags[i], 0, NULL, NULL)) != CL_SUCCESS) { + print_error(err, "Failed migrating memory object."); + } + } + return err; +} + +static cl_int restoreImage(cl_command_queue *queues, cl_mem *mem_objects, cl_uint num_devices, + cl_mem_migration_flags *flags, cl_uint *buffer) +{ + cl_uint i; + cl_int err; + + const size_t origin[3] = {0, 0, 0}; + const size_t region[3] = {IMAGE_DIM, IMAGE_DIM, 1}; + + // If the image was previously migrated with undefined content, reload the content. + + for (i=0; i 1) { + // Create each of the sub-devices and a corresponding context. + if ((err = clCreateSubDevices(deviceID, (const cl_device_partition_property *)property, num_devices, devices, &num_devices)) != CL_SUCCESS) { + print_error(err, "Failed creating sub devices."); + failed = 1; + goto cleanup; + } + + // Create a context containing all the sub-devices + ctx = clCreateContext(NULL, num_devices, devices, notify_callback, NULL, &err); + if (ctx == NULL) { + print_error(err, "Failed creating context containing the sub-devices."); + failed = 1; + goto cleanup; + } + + // Create a command queue for each sub-device + for (i=0; i 1) { + // Command queue cleanup + if (queues[i]) { + if ((err = clReleaseCommandQueue(queues[i])) != CL_SUCCESS) { + print_error(err, "Failed releasing command queue."); + failed = 1; + } + } + + // Sub-device cleanup + if (devices[i]) { + if ((err = clReleaseDevice(devices[i])) != CL_SUCCESS) { + print_error(err, "Failed releasing sub device."); + failed = 1; + } + } + devices[i] = 0; + } + } + + // Sampler cleanup + if (sampler) { + if ((err = clReleaseSampler(sampler)) != CL_SUCCESS) { + print_error(err, "Failed releasing sampler."); + failed = 1; + } + sampler = NULL; + } + + // Context, program, and kernel cleanup + if (program) { + if ((err = clReleaseProgram(program)) != CL_SUCCESS) { + print_error(err, "Failed releasing program."); + failed = 1; + } + program = NULL; + } + + if (kernel) { + if ((err = clReleaseKernel(kernel)) != CL_SUCCESS) { + print_error(err, "Failed releasing kernel."); + failed = 1; + } + kernel = NULL; + } + + if (ctx && (ctx != context)) { + if ((err = clReleaseContext(ctx)) != CL_SUCCESS) { + print_error(err, "Failed releasing context."); + failed = 1; + } + } + ctx = NULL; + + if (failed) goto cleanup_allocations; + } while (domains); + +cleanup_allocations: + if (devices) free(devices); + if (queues) free(queues); + if (flagsA) free(flagsA); + if (flagsB) free(flagsB); + if (flagsC) free(flagsC); + if (imageA) free(imageA); + if (imageB) free(imageB); + if (imageC) free(imageC); + + return ((failed) ? -1 : 0); +} diff --git a/test_conformance/buffers/test_sub_buffers.cpp b/test_conformance/buffers/test_sub_buffers.cpp new file mode 100644 index 00000000..8a8d0269 --- /dev/null +++ b/test_conformance/buffers/test_sub_buffers.cpp @@ -0,0 +1,631 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "procs.h" + +// Design: +// To test sub buffers, we first create one main buffer. We then create several sub-buffers and +// queue Actions on each one. Each Action is encapsulated in a class so it can keep track of +// what results it expects, and so we can test scaling degrees of Actions on scaling numbers of +// sub-buffers. + +class SubBufferWrapper : public clMemWrapper +{ +public: + cl_mem mParentBuffer; + size_t mOrigin; + size_t mSize; + + cl_int Allocate( cl_mem parent, cl_mem_flags flags, size_t origin, size_t size ) + { + mParentBuffer = parent; + mOrigin = origin; + mSize = size; + + cl_buffer_region region; + region.origin = mOrigin; + region.size = mSize; + + cl_int error; + mMem = clCreateSubBuffer( mParentBuffer, flags, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error ); + return error; + } +}; + +class Action +{ +public: + virtual ~Action() {} + virtual cl_int Execute( cl_context context, cl_command_queue queue, cl_char tag, SubBufferWrapper &buffer1, SubBufferWrapper &buffer2, cl_char *parentBufferState ) = 0; + virtual const char * GetName( void ) const = 0; + + static MTdata d; + static MTdata GetRandSeed( void ) + { + if ( d == 0 ) + d = init_genrand( gRandomSeed ); + return d; + } + static void FreeRandSeed() { + if ( d != 0 ) { + free_mtdata(d); + d = 0; + } + } +}; + +MTdata Action::d = 0; + +class ReadWriteAction : public Action +{ +public: + virtual ~ReadWriteAction() {} + virtual const char * GetName( void ) const { return "ReadWrite";} + + virtual cl_int Execute( cl_context context, cl_command_queue queue, cl_char tag, SubBufferWrapper &buffer1, SubBufferWrapper &buffer2, cl_char *parentBufferState ) + { + cl_char *tempBuffer = (cl_char*)malloc(buffer1.mSize); + if (!tempBuffer) { + log_error("Out of memory\n"); + return -1; + } + cl_int error = clEnqueueReadBuffer( queue, buffer1, CL_TRUE, 0, buffer1.mSize, tempBuffer, 0, NULL, NULL ); + test_error( error, "Unable to enqueue buffer read" ); + + size_t start = get_random_size_t( 0, buffer1.mSize / 2, GetRandSeed() ); + size_t end = get_random_size_t( start, buffer1.mSize, GetRandSeed() ); + + for ( size_t i = start; i < end; i++ ) + { + tempBuffer[ i ] |= tag; + parentBufferState[ i + buffer1.mOrigin ] |= tag; + } + + error = clEnqueueWriteBuffer( queue, buffer1, CL_TRUE, 0, buffer1.mSize, tempBuffer, 0, NULL, NULL ); + test_error( error, "Unable to enqueue buffer write" ); + free(tempBuffer); + return CL_SUCCESS; + } +}; + +#ifndef MAX +#define MAX( _a, _b ) ( (_a) > (_b) ? (_a) : (_b) ) +#endif +#ifndef MIN +#define MIN( _a, _b ) ( (_a) < (_b) ? (_a) : (_b) ) +#endif + +class CopyAction : public Action +{ +public: + virtual ~CopyAction() {} + virtual const char * GetName( void ) const { return "Copy";} + + virtual cl_int Execute( cl_context context, cl_command_queue queue, cl_char tag, SubBufferWrapper &buffer1, SubBufferWrapper &buffer2, cl_char *parentBufferState ) + { + // Copy from sub-buffer 1 to sub-buffer 2 + size_t size = get_random_size_t( 0, MIN( buffer1.mSize, buffer2.mSize ), GetRandSeed() ); + + size_t startOffset = get_random_size_t( 0, buffer1.mSize - size, GetRandSeed() ); + size_t endOffset = get_random_size_t( 0, buffer2.mSize - size, GetRandSeed() ); + + cl_int error = clEnqueueCopyBuffer( queue, buffer1, buffer2, startOffset, endOffset, size, 0, NULL, NULL ); + test_error( error, "Unable to enqueue buffer copy" ); + + memcpy( parentBufferState + buffer2.mOrigin + endOffset, parentBufferState + buffer1.mOrigin + startOffset, size ); + + return CL_SUCCESS; + } +}; + +class MapAction : public Action +{ +public: + virtual ~MapAction() {} + virtual const char * GetName( void ) const { return "Map";} + + virtual cl_int Execute( cl_context context, cl_command_queue queue, cl_char tag, SubBufferWrapper &buffer1, SubBufferWrapper &buffer2, cl_char *parentBufferState ) + { + size_t size = get_random_size_t( 0, buffer1.mSize, GetRandSeed() ); + size_t start = get_random_size_t( 0, buffer1.mSize - size, GetRandSeed() ); + + cl_int error; + void * mappedPtr = clEnqueueMapBuffer( queue, buffer1, CL_TRUE, (cl_map_flags)( CL_MAP_READ | CL_MAP_WRITE ), + start, size, 0, NULL, NULL, &error ); + test_error( error, "Unable to map buffer" ); + + cl_char *cPtr = (cl_char *)mappedPtr; + for ( size_t i = 0; i < size; i++ ) + { + cPtr[ i ] |= tag; + parentBufferState[ i + start + buffer1.mOrigin ] |= tag; + } + + error = clEnqueueUnmapMemObject( queue, buffer1, mappedPtr, 0, NULL, NULL ); + test_error( error, "Unable to unmap buffer" ); + + return CL_SUCCESS; + } +}; + +class KernelReadWriteAction : public Action +{ +public: + virtual ~KernelReadWriteAction() {} + virtual const char * GetName( void ) const { return "KernelReadWrite";} + + virtual cl_int Execute( cl_context context, cl_command_queue queue, cl_char tag, SubBufferWrapper &buffer1, SubBufferWrapper &buffer2, cl_char *parentBufferState ) + { + const char *kernelCode[] = { + "__kernel void readTest( __global char *inBuffer, char tag )\n" + "{\n" + " int tid = get_global_id(0);\n" + " inBuffer[ tid ] |= tag;\n" + "}\n" }; + + clProgramWrapper program; + clKernelWrapper kernel; + cl_int error; + + if ( create_single_kernel_helper( context, &program, &kernel, 1, kernelCode, "readTest" ) ) + { + return -1; + } + + size_t threads[1] = { buffer1.mSize }; + + error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &buffer1 ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 1, sizeof( tag ), &tag ); + test_error( error, "Unable to set kernel argument" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to queue kernel" ); + + for ( size_t i = 0; i < buffer1.mSize; i++ ) + parentBufferState[ i + buffer1.mOrigin ] |= tag; + + return CL_SUCCESS; + } +}; + +cl_int get_reasonable_buffer_size( cl_device_id device, size_t &outSize ) +{ + cl_ulong maxAllocSize; + cl_int error; + + // Get the largest possible buffer we could allocate + error = clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get max alloc size" ); + + // Don't create a buffer quite that big, just so we have some space left over for other work + outSize = (size_t)( maxAllocSize / 5 ); + + // Cap at 32M so tests complete in a reasonable amount of time. + if ( outSize > 32 << 20 ) + outSize = 32 << 20; + + return CL_SUCCESS; +} + +size_t find_subbuffer_by_index( SubBufferWrapper * subBuffers, size_t numSubBuffers, size_t index ) +{ + for ( size_t i = 0; i < numSubBuffers; i++ ) + { + if ( subBuffers[ i ].mOrigin > index ) + return numSubBuffers; + if ( ( subBuffers[ i ].mOrigin <= index ) && ( ( subBuffers[ i ].mOrigin + subBuffers[ i ].mSize ) > index ) ) + return i; + } + return numSubBuffers; +} + +// This tests the read/write capabilities of sub buffers (if we are read/write, the sub buffers +// can't overlap) +int test_sub_buffers_read_write_core( cl_context context, cl_command_queue queueA, cl_command_queue queueB, size_t mainSize, size_t addressAlign ) +{ + clMemWrapper mainBuffer; + SubBufferWrapper subBuffers[ 8 ]; + size_t numSubBuffers; + cl_int error; + size_t i; + MTdata m = init_genrand( 22 ); + + + cl_char * mainBufferContents = (cl_char*)calloc(1,mainSize); + cl_char * actualResults = (cl_char*)calloc(1,mainSize); + + for ( i = 0; i < mainSize / 4; i++ ) + ((cl_uint*) mainBufferContents)[i] = genrand_int32(m); + + free_mtdata( m ); + + // Create the main buffer to test against + mainBuffer = clCreateBuffer( context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, mainSize, mainBufferContents, &error ); + test_error( error, "Unable to create test main buffer" ); + + // Create some sub-buffers to use + size_t toStartFrom = 0; + for ( numSubBuffers = 0; numSubBuffers < 8; numSubBuffers++ ) + { + size_t endRange = toStartFrom + ( mainSize / 4 ); + if ( endRange > mainSize ) + endRange = mainSize; + + size_t offset = get_random_size_t( toStartFrom / addressAlign, endRange / addressAlign, Action::GetRandSeed() ) * addressAlign; + size_t size = get_random_size_t( 1, ( MIN( mainSize / 8, mainSize - offset ) ) / addressAlign, Action::GetRandSeed() ) * addressAlign; + error = subBuffers[ numSubBuffers ].Allocate( mainBuffer, CL_MEM_READ_WRITE, offset, size ); + test_error( error, "Unable to allocate sub buffer" ); + + toStartFrom = offset + size; + if ( toStartFrom > ( mainSize - ( addressAlign * 256 ) ) ) + break; + } + + ReadWriteAction rwAction; + MapAction mapAction; + CopyAction copyAction; + KernelReadWriteAction kernelAction; + + Action * actions[] = { &rwAction, &mapAction, ©Action, &kernelAction }; + int numErrors = 0; + + // Do the following steps twice, to make sure the parent gets updated *and* we can + // still work on the sub-buffers + cl_command_queue prev_queue = queueA; + for ( int time = 0; time < 2; time++ ) + { + // Randomly apply actions to the set of sub buffers + size_t i; + for ( i = 0; i < 64; i++ ) + { + int which = random_in_range( 0, 3, Action::GetRandSeed() ); + int whichQueue = random_in_range( 0, 1, Action::GetRandSeed() ); + int whichBufferA = random_in_range( 0, (int)numSubBuffers - 1, Action::GetRandSeed() ); + int whichBufferB; + do + { + whichBufferB = random_in_range( 0, (int)numSubBuffers - 1, Action::GetRandSeed() ); + } while ( whichBufferB == whichBufferA ); + + cl_command_queue queue = ( whichQueue == 1 ) ? queueB : queueA; + if (queue != prev_queue) { + error = clFinish( prev_queue ); + test_error( error, "Error finishing other queue." ); + + prev_queue = queue; + } + + error = actions[ which ]->Execute( context, queue, (cl_int)i, subBuffers[ whichBufferA ], subBuffers[ whichBufferB ], mainBufferContents ); + test_error( error, "Unable to execute action against sub buffers" ); + } + + error = clFinish( queueA ); + test_error( error, "Error finishing queueA." ); + + error = clFinish( queueB ); + test_error( error, "Error finishing queueB." ); + + // Validate by reading the final contents of the main buffer and + // validating against our ref copy we generated + error = clEnqueueReadBuffer( queueA, mainBuffer, CL_TRUE, 0, mainSize, actualResults, 0, NULL, NULL ); + test_error( error, "Unable to enqueue buffer read" ); + + for ( i = 0; i < mainSize; i += 65536 ) + { + size_t left = 65536; + if ( ( i + left ) > mainSize ) + left = mainSize - i; + + if ( memcmp( actualResults + i, mainBufferContents + i, left ) == 0 ) + continue; + + // The fast compare failed, so we need to determine where exactly the failure is + + for ( size_t j = 0; j < left; j++ ) + { + if ( actualResults[ i + j ] != mainBufferContents[ i + j ] ) + { + // Hit a failure; report the subbuffer at this address as having failed + size_t sbThatFailed = find_subbuffer_by_index( subBuffers, numSubBuffers, i + j ); + if ( sbThatFailed == numSubBuffers ) + { + log_error( "ERROR: Validation failure outside of a sub-buffer! (Shouldn't be possible, but it happened at index %ld out of %ld...)\n", i + j, mainSize ); + // Since this is a nonsensical, don't bother continuing to check + // (we will, however, print our map of sub-buffers for comparison) + for ( size_t k = 0; k < numSubBuffers; k++ ) + { + log_error( "\tBuffer %ld: %ld to %ld (length %ld)\n", k, subBuffers[ k ].mOrigin, subBuffers[ k ].mOrigin + subBuffers[ k ].mSize, subBuffers[ k ].mSize ); + } + return -1; + } + log_error( "ERROR: Validation failure on sub-buffer %ld (start: %ld, length: %ld)\n", sbThatFailed, subBuffers[ sbThatFailed ].mOrigin, subBuffers[ sbThatFailed ].mSize ); + size_t newPos = subBuffers[ sbThatFailed ].mOrigin + subBuffers[ sbThatFailed ].mSize - 1; + i = newPos & ~65535; + j = newPos - i; + numErrors++; + } + } + } + } + + free(mainBufferContents); + free(actualResults); + Action::FreeRandSeed(); + + return numErrors; +} + +int test_sub_buffers_read_write( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_int error; + size_t mainSize; + cl_uint addressAlignBits; + + // Get the size of the main buffer to use + error = get_reasonable_buffer_size( deviceID, mainSize ); + test_error( error, "Unable to get reasonable buffer size" ); + + // Determine the alignment of the device so we can make sure sub buffers are valid + error = clGetDeviceInfo( deviceID, CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof( addressAlignBits ), &addressAlignBits, NULL ); + test_error( error, "Unable to get device's address alignment" ); + + size_t addressAlign = addressAlignBits/8; + + return test_sub_buffers_read_write_core( context, queue, queue, mainSize, addressAlign ); +} + +// This test performs the same basic operations as sub_buffers_read_write, but instead of a single +// device, it creates a context and buffer shared between two devices, then executes commands +// on queues for each device to ensure that everything still operates as expected. +int test_sub_buffers_read_write_dual_devices( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_int error; + + + // First obtain the second device + cl_device_id otherDevice = GetOpposingDevice( deviceID ); + if ( otherDevice == NULL ) + { + log_error( "ERROR: Unable to obtain a second device for sub-buffer dual-device test.\n" ); + return -1; + } + if ( otherDevice == deviceID ) + { + log_info( "Note: Unable to run dual-device sub-buffer test (only one device available). Skipping test (implicitly passing).\n" ); + return 0; + } + + // Determine the device id. + size_t param_size; + error = clGetDeviceInfo(otherDevice, CL_DEVICE_NAME, 0, NULL, ¶m_size ); + test_error( error, "Error obtaining device name" ); + +#if !(defined(_WIN32) && defined(_MSC_VER)) + char device_name[param_size]; +#else + char* device_name = (char*)_malloca(param_size); +#endif + error = clGetDeviceInfo(otherDevice, CL_DEVICE_NAME, param_size, &device_name[0], NULL ); + test_error( error, "Error obtaining device name" ); + + log_info( "\tOther device obtained for dual device test is type %s\n", device_name ); + + // Create a shared context for these two devices + cl_device_id devices[ 2 ] = { deviceID, otherDevice }; + clContextWrapper testingContext = clCreateContext( NULL, 2, devices, NULL, NULL, &error ); + test_error( error, "Unable to create shared context" ); + + // Create two queues (can't use the existing one, because it's on the wrong context) + clCommandQueueWrapper queue1 = clCreateCommandQueueWithProperties( testingContext, deviceID, 0, &error ); + test_error( error, "Unable to create command queue on main device" ); + + clCommandQueueWrapper queue2 = clCreateCommandQueueWithProperties( testingContext, otherDevice, 0, &error ); + test_error( error, "Unable to create command queue on secondary device" ); + + // Determine the reasonable buffer size and address alignment that applies to BOTH devices + size_t maxBuffer1, maxBuffer2; + error = get_reasonable_buffer_size( deviceID, maxBuffer1 ); + test_error( error, "Unable to get buffer size for main device" ); + + error = get_reasonable_buffer_size( otherDevice, maxBuffer2 ); + test_error( error, "Unable to get buffer size for secondary device" ); + maxBuffer1 = MIN( maxBuffer1, maxBuffer2 ); + + cl_uint addressAlign1Bits, addressAlign2Bits; + error = clGetDeviceInfo( deviceID, CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof( addressAlign1Bits ), &addressAlign1Bits, NULL ); + test_error( error, "Unable to get main device's address alignment" ); + + error = clGetDeviceInfo( otherDevice, CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof( addressAlign2Bits ), &addressAlign2Bits, NULL ); + test_error( error, "Unable to get secondary device's address alignment" ); + + cl_uint addressAlign1 = MAX( addressAlign1Bits, addressAlign2Bits ) / 8; + + // Finally time to run! + return test_sub_buffers_read_write_core( testingContext, queue1, queue2, maxBuffer1, addressAlign1 ); +} + +cl_int read_buffer_via_kernel( cl_context context, cl_command_queue queue, cl_mem buffer, size_t length, cl_char *outResults ) +{ + const char *kernelCode[] = { + "__kernel void readTest( __global char *inBuffer, __global char *outBuffer )\n" + "{\n" + " int tid = get_global_id(0);\n" + " outBuffer[ tid ] = inBuffer[ tid ];\n" + "}\n" }; + + clProgramWrapper program; + clKernelWrapper kernel; + cl_int error; + + if ( create_single_kernel_helper( context, &program, &kernel, 1, kernelCode, "readTest" ) ) + { + return -1; + } + + size_t threads[1] = { length }; + + clMemWrapper outStream = clCreateBuffer( context, CL_MEM_READ_WRITE, length, NULL, &error ); + test_error( error, "Unable to create output stream" ); + + error = clSetKernelArg( kernel, 0, sizeof( buffer ), &buffer ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 1, sizeof( outStream ), &outStream ); + test_error( error, "Unable to set kernel argument" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to queue kernel" ); + + error = clEnqueueReadBuffer( queue, outStream, CL_TRUE, 0, length, outResults, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + + return CL_SUCCESS; +} + + +int test_sub_buffers_overlapping( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_int error; + size_t mainSize; + cl_uint addressAlign; + + clMemWrapper mainBuffer; + SubBufferWrapper subBuffers[ 16 ]; + + + // Create the main buffer to test against + error = get_reasonable_buffer_size( deviceID, mainSize ); + test_error( error, "Unable to get reasonable buffer size" ); + + mainBuffer = clCreateBuffer( context, CL_MEM_READ_WRITE, mainSize, NULL, &error ); + test_error( error, "Unable to create test main buffer" ); + + // Determine the alignment of the device so we can make sure sub buffers are valid + error = clGetDeviceInfo( deviceID, CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof( addressAlign ), &addressAlign, NULL ); + test_error( error, "Unable to get device's address alignment" ); + + // Create some sub-buffers to use. Note: they don't have to not overlap (we actually *want* them to overlap) + for ( size_t i = 0; i < 16; i++ ) + { + size_t offset = get_random_size_t( 0, mainSize / addressAlign, Action::GetRandSeed() ) * addressAlign; + size_t size = get_random_size_t( 1, ( mainSize - offset ) / addressAlign, Action::GetRandSeed() ) * addressAlign; + + error = subBuffers[ i ].Allocate( mainBuffer, CL_MEM_READ_ONLY, offset, size ); + test_error( error, "Unable to allocate sub buffer" ); + } + + /// For logging, we determine the amount of overlap we just generated + // Build a fast in-out map to help with generating the stats + int sbMap[ 32 ], mapSize = 0; + for ( int i = 0; i < 16; i++ ) + { + int j; + for ( j = 0; j < mapSize; j++ ) + { + size_t pt = ( sbMap[ j ] < 0 ) ? ( subBuffers[ -sbMap[ j ] ].mOrigin + subBuffers[ -sbMap[ j ] ].mSize ) + : subBuffers[ sbMap[ j ] ].mOrigin; + if ( subBuffers[ i ].mOrigin < pt ) + { + // Origin is before this part of the map, so move map forward so we can insert + memmove( &sbMap[ j + 1 ], &sbMap[ j ], sizeof( int ) * ( mapSize - j ) ); + sbMap[ j ] = i; + mapSize++; + break; + } + } + if ( j == mapSize ) + { + sbMap[ j ] = i; + mapSize++; + } + + size_t endPt = subBuffers[ i ].mOrigin + subBuffers[ i ].mSize; + for ( j = 0; j < mapSize; j++ ) + { + size_t pt = ( sbMap[ j ] < 0 ) ? ( subBuffers[ -sbMap[ j ] ].mOrigin + subBuffers[ -sbMap[ j ] ].mSize ) + : subBuffers[ sbMap[ j ] ].mOrigin; + if ( endPt < pt ) + { + // Origin is before this part of the map, so move map forward so we can insert + memmove( &sbMap[ j + 1 ], &sbMap[ j ], sizeof( int ) * ( mapSize - j ) ); + sbMap[ j ] = -( i + 1 ); + mapSize++; + break; + } + } + if ( j == mapSize ) + { + sbMap[ j ] = -( i + 1 ); + mapSize++; + } + } + long long delta = 0; + size_t maxOverlap = 1, overlap = 0; + for ( int i = 0; i < 32; i++ ) + { + if ( sbMap[ i ] >= 0 ) + { + overlap++; + if ( overlap > 1 ) + delta -= (long long)( subBuffers[ sbMap[ i ] ].mOrigin ); + if ( overlap > maxOverlap ) + maxOverlap = overlap; + } + else + { + if ( overlap > 1 ) + delta += (long long)( subBuffers[ -sbMap[ i ] - 1 ].mOrigin + subBuffers[ -sbMap[ i ] - 1 ].mSize ); + overlap--; + } + } + + log_info( "\tTesting %d sub-buffers with %lld overlapping Kbytes (%d%%; as many as %ld buffers overlapping at once)\n", + 16, ( delta / 1024LL ), (int)( delta * 100LL / (long long)mainSize ), maxOverlap ); + + // Write some random contents to the main buffer + cl_char * contents = new cl_char[ mainSize ]; + generate_random_data( kChar, mainSize, Action::GetRandSeed(), contents ); + + error = clEnqueueWriteBuffer( queue, mainBuffer, CL_TRUE, 0, mainSize, contents, 0, NULL, NULL ); + test_error( error, "Unable to write to main buffer" ); + + // Now read from each sub-buffer and check to make sure that they make sense w.r.t. the main contents + cl_char * tempBuffer = new cl_char[ mainSize ]; + + int numErrors = 0; + for ( size_t i = 0; i < 16; i++ ) + { + // Read from this buffer + int which = random_in_range( 0, 1, Action::GetRandSeed() ); + if ( which ) + error = clEnqueueReadBuffer( queue, subBuffers[ i ], CL_TRUE, 0, subBuffers[ i ].mSize, tempBuffer, 0, NULL, NULL ); + else + error = read_buffer_via_kernel( context, queue, subBuffers[ i ], subBuffers[ i ].mSize, tempBuffer ); + test_error( error, "Unable to read sub buffer contents" ); + + if ( memcmp( tempBuffer, contents + subBuffers[ i ].mOrigin, subBuffers[ i ].mSize ) != 0 ) + { + log_error( "ERROR: Validation for sub-buffer %ld failed!\n", i ); + numErrors++; + } + } + + delete [] contents; + delete [] tempBuffer; + Action::FreeRandSeed(); + + return numErrors; +} + diff --git a/test_conformance/c11_atomics/CMakeLists.txt b/test_conformance/c11_atomics/CMakeLists.txt new file mode 100644 index 00000000..96525406 --- /dev/null +++ b/test_conformance/c11_atomics/CMakeLists.txt @@ -0,0 +1,17 @@ +set(MODULE_NAME C11_ATOMICS) + +set(${MODULE_NAME}_SOURCES + common.cpp + host_atomics.cpp + main.cpp + test_atomics.cpp + ../../test_common/harness/ThreadPool.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) diff --git a/test_conformance/c11_atomics/Makefile b/test_conformance/c11_atomics/Makefile new file mode 100644 index 00000000..7bd23b5d --- /dev/null +++ b/test_conformance/c11_atomics/Makefile @@ -0,0 +1,46 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + test_atomics.cpp \ + host_atomics.cpp \ + common.cpp \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/typeWrappers.cpp \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/conversions.c \ + ../../test_common/harness/ThreadPool.c + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +HEADERS = +TARGET = test_atomics_c11 +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/c11_atomics/common.cpp b/test_conformance/c11_atomics/common.cpp new file mode 100644 index 00000000..1fb6b9b2 --- /dev/null +++ b/test_conformance/c11_atomics/common.cpp @@ -0,0 +1,208 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/typeWrappers.h" + +#include "common.h" + +const char *get_memory_order_type_name(TExplicitMemoryOrderType orderType) +{ + switch (orderType) + { + case MEMORY_ORDER_EMPTY: + return ""; + case MEMORY_ORDER_RELAXED: + return "memory_order_relaxed"; + case MEMORY_ORDER_ACQUIRE: + return "memory_order_acquire"; + case MEMORY_ORDER_RELEASE: + return "memory_order_release"; + case MEMORY_ORDER_ACQ_REL: + return "memory_order_acq_rel"; + case MEMORY_ORDER_SEQ_CST: + return "memory_order_seq_cst"; + default: + return 0; + } +} + +const char *get_memory_scope_type_name(TExplicitMemoryScopeType scopeType) +{ + switch (scopeType) + { + case MEMORY_SCOPE_EMPTY: + return ""; + case MEMORY_SCOPE_WORK_GROUP: + return "memory_scope_work_group"; + case MEMORY_SCOPE_DEVICE: + return "memory_scope_device"; + case MEMORY_SCOPE_ALL_SVM_DEVICES: + return "memory_scope_all_svm_devices"; + default: + return 0; + } +} + + +cl_uint AtomicTypeInfo::Size(cl_device_id device) +{ + switch(_type) + { + case TYPE_ATOMIC_INT: + case TYPE_ATOMIC_UINT: + case TYPE_ATOMIC_FLOAT: + case TYPE_ATOMIC_FLAG: + return sizeof(cl_int); + case TYPE_ATOMIC_LONG: + case TYPE_ATOMIC_ULONG: + case TYPE_ATOMIC_DOUBLE: + return sizeof(cl_long); + case TYPE_ATOMIC_INTPTR_T: + case TYPE_ATOMIC_UINTPTR_T: + case TYPE_ATOMIC_SIZE_T: + case TYPE_ATOMIC_PTRDIFF_T: + { + int error; + cl_uint addressBits = 0; + + error = clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS, sizeof(addressBits), &addressBits, 0); + test_error_ret(error, "clGetDeviceInfo", 0); + + return addressBits/8; + } + default: + return 0; + } +} + +const char *AtomicTypeInfo::AtomicTypeName() +{ + switch(_type) + { + case TYPE_ATOMIC_INT: + return "atomic_int"; + case TYPE_ATOMIC_UINT: + return "atomic_uint"; + case TYPE_ATOMIC_FLOAT: + return "atomic_float"; + case TYPE_ATOMIC_FLAG: + return "atomic_flag"; + case TYPE_ATOMIC_LONG: + return "atomic_long"; + case TYPE_ATOMIC_ULONG: + return "atomic_ulong"; + case TYPE_ATOMIC_DOUBLE: + return "atomic_double"; + case TYPE_ATOMIC_INTPTR_T: + return "atomic_intptr_t"; + case TYPE_ATOMIC_UINTPTR_T: + return "atomic_uintptr_t"; + case TYPE_ATOMIC_SIZE_T: + return "atomic_size_t"; + case TYPE_ATOMIC_PTRDIFF_T: + return "atomic_ptrdiff_t"; + default: + return 0; + } +} + +const char *AtomicTypeInfo::RegularTypeName() +{ + switch(_type) + { + case TYPE_ATOMIC_INT: + return "int"; + case TYPE_ATOMIC_UINT: + return "uint"; + case TYPE_ATOMIC_FLOAT: + return "float"; + case TYPE_ATOMIC_FLAG: + return "int"; + case TYPE_ATOMIC_LONG: + return "long"; + case TYPE_ATOMIC_ULONG: + return "ulong"; + case TYPE_ATOMIC_DOUBLE: + return "double"; + case TYPE_ATOMIC_INTPTR_T: + return "intptr_t"; + case TYPE_ATOMIC_UINTPTR_T: + return "uintptr_t"; + case TYPE_ATOMIC_SIZE_T: + return "size_t"; + case TYPE_ATOMIC_PTRDIFF_T: + return "ptrdiff_t"; + default: + return 0; + } +} + +const char *AtomicTypeInfo::AddSubOperandTypeName() +{ + switch(_type) + { + case TYPE_ATOMIC_INTPTR_T: + case TYPE_ATOMIC_UINTPTR_T: + return AtomicTypeInfo(TYPE_ATOMIC_PTRDIFF_T).RegularTypeName(); + default: + return RegularTypeName(); + } +} + +int AtomicTypeInfo::IsSupported(cl_device_id device) +{ + switch(_type) + { + case TYPE_ATOMIC_INT: + case TYPE_ATOMIC_UINT: + case TYPE_ATOMIC_FLOAT: + case TYPE_ATOMIC_FLAG: + return 1; + case TYPE_ATOMIC_LONG: + case TYPE_ATOMIC_ULONG: + return is_extension_available(device, "cl_khr_int64_base_atomics") && + is_extension_available(device, "cl_khr_int64_extended_atomics"); + case TYPE_ATOMIC_DOUBLE: + return is_extension_available(device, "cl_khr_int64_base_atomics") && + is_extension_available(device, "cl_khr_int64_extended_atomics") && + is_extension_available(device, "cl_khr_fp64"); + case TYPE_ATOMIC_INTPTR_T: + case TYPE_ATOMIC_UINTPTR_T: + case TYPE_ATOMIC_SIZE_T: + case TYPE_ATOMIC_PTRDIFF_T: + if(Size(device) == 4) + return 1; + return is_extension_available(device, "cl_khr_int64_base_atomics") && + is_extension_available(device, "cl_khr_int64_extended_atomics"); + default: + return 0; + } +} + +template<> cl_int AtomicTypeExtendedInfo::MinValue() {return CL_INT_MIN;} +template<> cl_uint AtomicTypeExtendedInfo::MinValue() {return 0;} +template<> cl_long AtomicTypeExtendedInfo::MinValue() {return CL_LONG_MIN;} +template<> cl_ulong AtomicTypeExtendedInfo::MinValue() {return 0;} +template<> cl_float AtomicTypeExtendedInfo::MinValue() {return CL_FLT_MIN;} +template<> cl_double AtomicTypeExtendedInfo::MinValue() {return CL_DBL_MIN;} + +template<> cl_int AtomicTypeExtendedInfo::MaxValue() {return CL_INT_MAX;} +template<> cl_uint AtomicTypeExtendedInfo::MaxValue() {return CL_UINT_MAX;} +template<> cl_long AtomicTypeExtendedInfo::MaxValue() {return CL_LONG_MAX;} +template<> cl_ulong AtomicTypeExtendedInfo::MaxValue() {return CL_ULONG_MAX;} +template<> cl_float AtomicTypeExtendedInfo::MaxValue() {return CL_FLT_MAX;} +template<> cl_double AtomicTypeExtendedInfo::MaxValue() {return CL_DBL_MAX;} diff --git a/test_conformance/c11_atomics/common.h b/test_conformance/c11_atomics/common.h new file mode 100644 index 00000000..afb5106f --- /dev/null +++ b/test_conformance/c11_atomics/common.h @@ -0,0 +1,1179 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/ThreadPool.h" + +#include "host_atomics.h" + +#include +#include + +#define MAX_DEVICE_THREADS (gHost ? 0U : gMaxDeviceThreads) +#define MAX_HOST_THREADS GetThreadCount() + +#define EXECUTE_TEST(error, test)\ + error |= test;\ + if(error && !gContinueOnError)\ + return error; + +enum TExplicitAtomicType +{ + TYPE_ATOMIC_INT, + TYPE_ATOMIC_UINT, + TYPE_ATOMIC_LONG, + TYPE_ATOMIC_ULONG, + TYPE_ATOMIC_FLOAT, + TYPE_ATOMIC_DOUBLE, + TYPE_ATOMIC_INTPTR_T, + TYPE_ATOMIC_UINTPTR_T, + TYPE_ATOMIC_SIZE_T, + TYPE_ATOMIC_PTRDIFF_T, + TYPE_ATOMIC_FLAG +}; + +enum TExplicitMemoryScopeType +{ + MEMORY_SCOPE_EMPTY, + MEMORY_SCOPE_WORK_GROUP, + MEMORY_SCOPE_DEVICE, + MEMORY_SCOPE_ALL_SVM_DEVICES +}; + +extern bool gHost; // temporary flag for testing native host threads (test verification) +extern bool gOldAPI; // temporary flag for testing with old API (OpenCL 1.2) +extern bool gContinueOnError; // execute all cases even when errors detected +extern bool gNoGlobalVariables; // disable cases with global atomics in program scope +extern bool gNoGenericAddressSpace; // disable cases with generic address space +extern bool gUseHostPtr; // use malloc/free instead of clSVMAlloc/clSVMFree +extern bool gDebug; // print OpenCL kernel code +extern int gInternalIterations; // internal test iterations for atomic operation, sufficient to verify atomicity +extern int gMaxDeviceThreads; // maximum number of threads executed on OCL device + +extern cl_uint gRandomSeed; + +extern const char *get_memory_order_type_name(TExplicitMemoryOrderType orderType); +extern const char *get_memory_scope_type_name(TExplicitMemoryScopeType scopeType); + +class AtomicTypeInfo +{ +public: + TExplicitAtomicType _type; + AtomicTypeInfo(TExplicitAtomicType type): _type(type) {} + cl_uint Size(cl_device_id device); + const char* AtomicTypeName(); + const char* RegularTypeName(); + const char* AddSubOperandTypeName(); + int IsSupported(cl_device_id device); +}; + +template +class AtomicTypeExtendedInfo : public AtomicTypeInfo +{ +public: + AtomicTypeExtendedInfo(TExplicitAtomicType type) : AtomicTypeInfo(type) {} + HostDataType MinValue(); + HostDataType MaxValue(); + HostDataType SpecialValue(cl_uchar x) + { + HostDataType tmp; + cl_uchar *ptr = (cl_uchar*)&tmp; + for(cl_uint i = 0; i < sizeof(HostDataType)/sizeof(cl_uchar); i++) + ptr[i] = x; + return tmp; + } + HostDataType SpecialValue(cl_ushort x) + { + HostDataType tmp; + cl_ushort *ptr = (cl_ushort*)&tmp; + for(cl_uint i = 0; i < sizeof(HostDataType)/sizeof(cl_ushort); i++) + ptr[i] = x; + return tmp; + } +}; + +class CTest { +public: + virtual int Execute(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) = 0; +}; + +template +class CBasicTest : CTest +{ +public: + typedef struct { + CBasicTest *test; + cl_uint tid; + cl_uint threadCount; + volatile HostAtomicType *destMemory; + HostDataType *oldValues; + } THostThreadContext; + static cl_int HostThreadFunction(cl_uint job_id, cl_uint thread_id, void *userInfo) + { + THostThreadContext *threadContext = ((THostThreadContext*)userInfo)+job_id; + threadContext->test->HostFunction(threadContext->tid, threadContext->threadCount, threadContext->destMemory, threadContext->oldValues); + return 0; + } + CBasicTest(TExplicitAtomicType dataType, bool useSVM) : CTest(), + _maxDeviceThreads(MAX_DEVICE_THREADS), + _dataType(dataType), _useSVM(useSVM), _startValue(255), + _localMemory(false), _declaredInProgram(false), + _usedInFunction(false), _genericAddrSpace(false), + _oldValueCheck(true), _localRefValues(false), + _maxGroupSize(0), _passCount(0), _iterations(gInternalIterations) + { + } + virtual ~CBasicTest() + { + if(_passCount) + log_info(" %u tests executed successfully for %s\n", _passCount, DataType().AtomicTypeName()); + } + virtual cl_uint NumResults(cl_uint threadCount, cl_device_id deviceID) + { + return 1; + } + virtual cl_uint NumNonAtomicVariablesPerThread() + { + return 1; + } + virtual bool ExpectedValue(HostDataType &expected, cl_uint threadCount, HostDataType *startRefValues, cl_uint whichDestValue) + { + return false; + } + virtual bool GenerateRefs(cl_uint threadCount, HostDataType *startRefValues, MTdata d) + { + return false; + } + virtual bool VerifyRefs(bool &correct, cl_uint threadCount, HostDataType *refValues, HostAtomicType *finalValues) + { + return false; + } + virtual std::string PragmaHeader(cl_device_id deviceID); + virtual std::string ProgramHeader(cl_uint maxNumDestItems); + virtual std::string FunctionCode(); + virtual std::string KernelCode(cl_uint maxNumDestItems); + virtual std::string ProgramCore() = 0; + virtual std::string SingleTestName() + { + std::string testName = LocalMemory() ? "local" : "global"; + testName += " "; + testName += DataType().AtomicTypeName(); + if(DeclaredInProgram()) + { + testName += " declared in program"; + } + if(DeclaredInProgram() && UsedInFunction()) + testName += ","; + if(UsedInFunction()) + { + testName += " used in "; + if(GenericAddrSpace()) + testName += "generic "; + testName += "function"; + } + return testName; + } + virtual int ExecuteSingleTest(cl_device_id deviceID, cl_context context, cl_command_queue queue); + int ExecuteForEachPointerType(cl_device_id deviceID, cl_context context, cl_command_queue queue) + { + int error = 0; + UsedInFunction(false); + EXECUTE_TEST(error, ExecuteSingleTest(deviceID, context, queue)); + UsedInFunction(true); + GenericAddrSpace(false); + EXECUTE_TEST(error, ExecuteSingleTest(deviceID, context, queue)); + GenericAddrSpace(true); + EXECUTE_TEST(error, ExecuteSingleTest(deviceID, context, queue)); + GenericAddrSpace(false); + return error; + } + int ExecuteForEachDeclarationType(cl_device_id deviceID, cl_context context, cl_command_queue queue) + { + int error = 0; + DeclaredInProgram(false); + EXECUTE_TEST(error, ExecuteForEachPointerType(deviceID, context, queue)); + if(!UseSVM()) + { + DeclaredInProgram(true); + EXECUTE_TEST(error, ExecuteForEachPointerType(deviceID, context, queue)); + } + return error; + } + virtual int ExecuteForEachParameterSet(cl_device_id deviceID, cl_context context, cl_command_queue queue) + { + int error = 0; + if(_maxDeviceThreads > 0 && !UseSVM()) + { + LocalMemory(true); + EXECUTE_TEST(error, ExecuteForEachDeclarationType(deviceID, context, queue)); + } + if(_maxDeviceThreads+MaxHostThreads() > 0) + { + LocalMemory(false); + EXECUTE_TEST(error, ExecuteForEachDeclarationType(deviceID, context, queue)); + } + return error; + } + virtual int Execute(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) + { + if(sizeof(HostAtomicType) != DataType().Size(deviceID)) + { + log_info("Invalid test: Host atomic type size (%u) is different than OpenCL type size (%u)\n", (cl_uint)sizeof(HostAtomicType), DataType().Size(deviceID)); + return -1; + } + if(sizeof(HostAtomicType) != sizeof(HostDataType)) + { + log_info("Invalid test: Host atomic type size (%u) is different than corresponding type size (%u)\n", (cl_uint)sizeof(HostAtomicType), (cl_uint)sizeof(HostDataType)); + return -1; + } + // Verify we can run first + if(UseSVM() && !gUseHostPtr) + { + cl_device_svm_capabilities caps; + cl_int error = clGetDeviceInfo(deviceID, CL_DEVICE_SVM_CAPABILITIES, sizeof(caps), &caps, 0); + test_error(error, "clGetDeviceInfo failed"); + if((caps & CL_DEVICE_SVM_ATOMICS) == 0) + { + log_info("\t%s - SVM_ATOMICS not supported\n", DataType().AtomicTypeName()); + // implicit pass + return 0; + } + } + if(!DataType().IsSupported(deviceID)) + { + log_info("\t%s not supported\n", DataType().AtomicTypeName()); + // implicit pass or host test (debug feature) + if(UseSVM()) + return 0; + _maxDeviceThreads = 0; + } + if(_maxDeviceThreads+MaxHostThreads() == 0) + return 0; + return ExecuteForEachParameterSet(deviceID, context, queue); + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + log_info("Empty thread function %u\n", (cl_uint)tid); + } + AtomicTypeExtendedInfo DataType() const + { + return AtomicTypeExtendedInfo(_dataType); + } + cl_uint _maxDeviceThreads; + virtual cl_uint MaxHostThreads() + { + if(UseSVM() || gHost) + return MAX_HOST_THREADS; + else + return 0; + } + virtual bool SVMDataBufferAllSVMConsistent() {return false;} + bool UseSVM() {return _useSVM;} + void StartValue(HostDataType startValue) {_startValue = startValue;} + HostDataType StartValue() {return _startValue;} + void LocalMemory(bool local) {_localMemory = local;} + bool LocalMemory() {return _localMemory;} + void DeclaredInProgram(bool declaredInProgram) {_declaredInProgram = declaredInProgram;} + bool DeclaredInProgram() {return _declaredInProgram;} + void UsedInFunction(bool local) {_usedInFunction = local;} + bool UsedInFunction() {return _usedInFunction;} + void GenericAddrSpace(bool genericAddrSpace) {_genericAddrSpace = genericAddrSpace;} + bool GenericAddrSpace() {return _genericAddrSpace;} + void OldValueCheck(bool check) {_oldValueCheck = check;} + bool OldValueCheck() {return _oldValueCheck;} + void LocalRefValues(bool localRefValues) {_localRefValues = localRefValues;} + bool LocalRefValues() {return _localRefValues;} + void MaxGroupSize(cl_uint maxGroupSize) {_maxGroupSize = maxGroupSize;} + cl_uint MaxGroupSize() {return _maxGroupSize;} + void CurrentGroupSize(cl_uint currentGroupSize) + { + if(MaxGroupSize() && MaxGroupSize() < currentGroupSize) + _currentGroupSize = MaxGroupSize(); + else + _currentGroupSize = currentGroupSize; + } + cl_uint CurrentGroupSize() {return _currentGroupSize;} + virtual cl_uint CurrentGroupNum(cl_uint threadCount) + { + if(threadCount == 0) + return 0; + if(LocalMemory()) + return 1; + return threadCount/CurrentGroupSize(); + } + cl_int Iterations() {return _iterations;} + std::string IterationsStr() {std::stringstream ss; ss << _iterations; return ss.str();} +private: + const TExplicitAtomicType _dataType; + const bool _useSVM; + HostDataType _startValue; + bool _localMemory; + bool _declaredInProgram; + bool _usedInFunction; + bool _genericAddrSpace; + bool _oldValueCheck; + bool _localRefValues; + cl_uint _maxGroupSize; + cl_uint _currentGroupSize; + cl_uint _passCount; + const cl_int _iterations; +}; + +template +class CBasicTestMemOrderScope : public CBasicTest +{ +public: + using CBasicTest::LocalMemory; + using CBasicTest::MaxGroupSize; + CBasicTestMemOrderScope(TExplicitAtomicType dataType, bool useSVM = false) : CBasicTest(dataType, useSVM) + { + } + virtual std::string ProgramHeader(cl_uint maxNumDestItems) + { + std::string header; + if(gOldAPI) + { + std::string s = MemoryScope() == MEMORY_SCOPE_EMPTY ? "" : ",s"; + header += + "#define atomic_store_explicit(x,y,o"+s+") atomic_store(x,y)\n" + "#define atomic_load_explicit(x,o"+s+") atomic_load(x)\n" + "#define atomic_exchange_explicit(x,y,o"+s+") atomic_exchange(x,y)\n" + "#define atomic_compare_exchange_strong_explicit(x,y,z,os,of"+s+") atomic_compare_exchange_strong(x,y,z)\n" + "#define atomic_compare_exchange_weak_explicit(x,y,z,os,of"+s+") atomic_compare_exchange_weak(x,y,z)\n" + "#define atomic_fetch_add_explicit(x,y,o"+s+") atomic_fetch_add(x,y)\n" + "#define atomic_fetch_sub_explicit(x,y,o"+s+") atomic_fetch_sub(x,y)\n" + "#define atomic_fetch_or_explicit(x,y,o"+s+") atomic_fetch_or(x,y)\n" + "#define atomic_fetch_xor_explicit(x,y,o"+s+") atomic_fetch_xor(x,y)\n" + "#define atomic_fetch_and_explicit(x,y,o"+s+") atomic_fetch_and(x,y)\n" + "#define atomic_fetch_min_explicit(x,y,o"+s+") atomic_fetch_min(x,y)\n" + "#define atomic_fetch_max_explicit(x,y,o"+s+") atomic_fetch_max(x,y)\n" + "#define atomic_flag_test_and_set_explicit(x,o"+s+") atomic_flag_test_and_set(x)\n" + "#define atomic_flag_clear_explicit(x,o"+s+") atomic_flag_clear(x)\n"; + } + return header+CBasicTest::ProgramHeader(maxNumDestItems); + } + virtual std::string SingleTestName() + { + std::string testName = CBasicTest::SingleTestName(); + if(MemoryOrder() != MEMORY_ORDER_EMPTY) + { + testName += std::string(", ")+std::string(get_memory_order_type_name(MemoryOrder())).substr(sizeof("memory")); + } + if(MemoryScope() != MEMORY_SCOPE_EMPTY) + { + testName += std::string(", ")+std::string(get_memory_scope_type_name(MemoryScope())).substr(sizeof("memory")); + } + return testName; + } + virtual int ExecuteSingleTest(cl_device_id deviceID, cl_context context, cl_command_queue queue) + { + if(LocalMemory() && + MemoryScope() != MEMORY_SCOPE_EMPTY && + MemoryScope() != MEMORY_SCOPE_WORK_GROUP) //memory scope should only be used for global memory + return 0; + if(MemoryScope() == MEMORY_SCOPE_DEVICE) + MaxGroupSize(16); // increase number of groups by forcing smaller group size + else + MaxGroupSize(0); // group size limited by device capabilities + return CBasicTest::ExecuteSingleTest(deviceID, context, queue); + } + virtual int ExecuteForEachParameterSet(cl_device_id deviceID, cl_context context, cl_command_queue queue) + { + // repeat test for each reasonable memory order/scope combination + std::vector memoryOrder; + std::vector memoryScope; + int error = 0; + + memoryOrder.push_back(MEMORY_ORDER_EMPTY); + memoryOrder.push_back(MEMORY_ORDER_RELAXED); + memoryOrder.push_back(MEMORY_ORDER_ACQUIRE); + memoryOrder.push_back(MEMORY_ORDER_RELEASE); + memoryOrder.push_back(MEMORY_ORDER_ACQ_REL); + memoryOrder.push_back(MEMORY_ORDER_SEQ_CST); + memoryScope.push_back(MEMORY_SCOPE_EMPTY); + memoryScope.push_back(MEMORY_SCOPE_WORK_GROUP); + memoryScope.push_back(MEMORY_SCOPE_DEVICE); + memoryScope.push_back(MEMORY_SCOPE_ALL_SVM_DEVICES); + + for(unsigned oi = 0; oi < memoryOrder.size(); oi++) + { + for(unsigned si = 0; si < memoryScope.size(); si++) + { + if(memoryOrder[oi] == MEMORY_ORDER_EMPTY && memoryScope[si] != MEMORY_SCOPE_EMPTY) + continue; + MemoryOrder(memoryOrder[oi]); + MemoryScope(memoryScope[si]); + EXECUTE_TEST(error, (CBasicTest::ExecuteForEachParameterSet(deviceID, context, queue))); + } + } + return error; + } + void MemoryOrder(TExplicitMemoryOrderType memoryOrder) {_memoryOrder = memoryOrder;} + TExplicitMemoryOrderType MemoryOrder() {return _memoryOrder;} + std::string MemoryOrderStr() + { + if(MemoryOrder() != MEMORY_ORDER_EMPTY) + return std::string(", ")+get_memory_order_type_name(MemoryOrder()); + return ""; + } + void MemoryScope(TExplicitMemoryScopeType memoryScope) {_memoryScope = memoryScope;} + TExplicitMemoryScopeType MemoryScope() {return _memoryScope;} + std::string MemoryScopeStr() + { + if(MemoryScope() != MEMORY_SCOPE_EMPTY) + return std::string(", ")+get_memory_scope_type_name(MemoryScope()); + return ""; + } + std::string MemoryOrderScopeStr() + { + return MemoryOrderStr()+MemoryScopeStr(); + } + virtual cl_uint CurrentGroupNum(cl_uint threadCount) + { + if(MemoryScope() == MEMORY_SCOPE_WORK_GROUP) + return 1; + return CBasicTest::CurrentGroupNum(threadCount); + } + virtual cl_uint MaxHostThreads() + { + // block host threads execution for memory scope different than memory_scope_all_svm_devices + if(MemoryScope() == MEMORY_SCOPE_ALL_SVM_DEVICES || gHost) + return CBasicTest::MaxHostThreads(); + else + return 0; + } +private: + TExplicitMemoryOrderType _memoryOrder; + TExplicitMemoryScopeType _memoryScope; +}; + +template +class CBasicTestMemOrder2Scope : public CBasicTestMemOrderScope +{ +public: + using CBasicTestMemOrderScope::LocalMemory; + using CBasicTestMemOrderScope::MemoryOrder; + using CBasicTestMemOrderScope::MemoryScope; + using CBasicTestMemOrderScope::MemoryOrderStr; + using CBasicTestMemOrderScope::MemoryScopeStr; + CBasicTestMemOrder2Scope(TExplicitAtomicType dataType, bool useSVM = false) : CBasicTestMemOrderScope(dataType, useSVM) + { + } + virtual std::string SingleTestName() + { + std::string testName = CBasicTest::SingleTestName(); + if(MemoryOrder() != MEMORY_ORDER_EMPTY) + testName += std::string(", ")+std::string(get_memory_order_type_name(MemoryOrder())).substr(sizeof("memory")); + if(MemoryOrder2() != MEMORY_ORDER_EMPTY) + testName += std::string(", ")+std::string(get_memory_order_type_name(MemoryOrder2())).substr(sizeof("memory")); + if(MemoryScope() != MEMORY_SCOPE_EMPTY) + testName += std::string(", ")+std::string(get_memory_scope_type_name(MemoryScope())).substr(sizeof("memory")); + return testName; + } + virtual int ExecuteForEachParameterSet(cl_device_id deviceID, cl_context context, cl_command_queue queue) + { + // repeat test for each reasonable memory order/scope combination + std::vector memoryOrder; + std::vector memoryScope; + int error = 0; + + memoryOrder.push_back(MEMORY_ORDER_EMPTY); + memoryOrder.push_back(MEMORY_ORDER_RELAXED); + memoryOrder.push_back(MEMORY_ORDER_ACQUIRE); + memoryOrder.push_back(MEMORY_ORDER_RELEASE); + memoryOrder.push_back(MEMORY_ORDER_ACQ_REL); + memoryOrder.push_back(MEMORY_ORDER_SEQ_CST); + memoryScope.push_back(MEMORY_SCOPE_EMPTY); + memoryScope.push_back(MEMORY_SCOPE_WORK_GROUP); + memoryScope.push_back(MEMORY_SCOPE_DEVICE); + memoryScope.push_back(MEMORY_SCOPE_ALL_SVM_DEVICES); + + for(unsigned oi = 0; oi < memoryOrder.size(); oi++) + { + for(unsigned o2i = 0; o2i < memoryOrder.size(); o2i++) + { + for(unsigned si = 0; si < memoryScope.size(); si++) + { + if((memoryOrder[oi] == MEMORY_ORDER_EMPTY || memoryOrder[o2i] == MEMORY_ORDER_EMPTY) + && memoryOrder[oi] != memoryOrder[o2i]) + continue; // both memory order arguments must be set (or none) + if((memoryOrder[oi] == MEMORY_ORDER_EMPTY || memoryOrder[o2i] == MEMORY_ORDER_EMPTY) + && memoryScope[si] != MEMORY_SCOPE_EMPTY) + continue; // memory scope without memory order is not allowed + MemoryOrder(memoryOrder[oi]); + MemoryOrder2(memoryOrder[o2i]); + MemoryScope(memoryScope[si]); + EXECUTE_TEST(error, (CBasicTest::ExecuteForEachParameterSet(deviceID, context, queue))); + } + } + } + return error; + } + void MemoryOrder2(TExplicitMemoryOrderType memoryOrderFail) {_memoryOrder2 = memoryOrderFail;} + TExplicitMemoryOrderType MemoryOrder2() {return _memoryOrder2;} + std::string MemoryOrderFailStr() + { + if(MemoryOrder2() != MEMORY_ORDER_EMPTY) + return std::string(", ")+get_memory_order_type_name(MemoryOrder2()); + return ""; + } + std::string MemoryOrderScope() + { + return MemoryOrderStr()+MemoryOrderFailStr()+MemoryScopeStr(); + } +private: + TExplicitMemoryOrderType _memoryOrder2; +}; + +template +std::string CBasicTest::PragmaHeader(cl_device_id deviceID) +{ + std::string pragma; + + if(gOldAPI) + { + pragma += "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"; + pragma += "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"; + pragma += "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"; + pragma += "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"; + } + // Create the pragma lines for this kernel + if(DataType().Size(deviceID) == 8) + { + pragma += "#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable\n"; + pragma += "#pragma OPENCL EXTENSION cl_khr_int64_extended_atomics : enable\n"; + } + if(_dataType == TYPE_ATOMIC_DOUBLE) + pragma += "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"; + return pragma; +} + +template +std::string CBasicTest::ProgramHeader(cl_uint maxNumDestItems) +{ + // Create the program header + std::string header; + std::string aTypeName = DataType().AtomicTypeName(); + std::string cTypeName = DataType().RegularTypeName(); + std::string argListForKernel; + std::string argListForFunction; + std::string argListNoTypes; + std::string functionPrototype; + std::string addressSpace = LocalMemory() ? "__local " : "__global "; + + if(gOldAPI) + { + header += std::string("#define ")+aTypeName+" "+cTypeName+"\n" + "#define atomic_store(x,y) (*(x) = y)\n" + "#define atomic_load(x) (*(x))\n" + "#define ATOMIC_VAR_INIT(x) (x)\n" + "#define ATOMIC_FLAG_INIT 0\n" + "#define atomic_init(x,y) atomic_store(x,y)\n"; + if(aTypeName == "atomic_float") + header += "#define atomic_exchange(x,y) atomic_xchg(x,y)\n"; + else if(aTypeName == "atomic_double") + header += "double atomic_exchange(volatile "+addressSpace+"atomic_double *x, double y)\n" + "{\n" + " long tmp = *(long*)&y, res;\n" + " volatile "+addressSpace+"long *tmpA = (volatile "+addressSpace+"long)x;\n" + " res = atom_xchg(tmpA,tmp);\n" + " return *(double*)&res;\n" + "}\n"; + else + header += "#define atomic_exchange(x,y) atom_xchg(x,y)\n"; + if(aTypeName != "atomic_float" && aTypeName != "atomic_double") + header += + "bool atomic_compare_exchange_strong(volatile "+addressSpace+" "+aTypeName+" *a, "+cTypeName+" *expected, "+cTypeName+" desired)\n" + "{\n" + " "+cTypeName+" old = atom_cmpxchg(a, *expected, desired);\n" + " if(old == *expected)\n" + " return true;\n" + " *expected = old;\n" + " return false;\n" + "}\n" + "#define atomic_compare_exchange_weak atomic_compare_exchange_strong\n"; + header += + "#define atomic_fetch_add(x,y) atom_add(x,y)\n" + "#define atomic_fetch_sub(x,y) atom_sub(x,y)\n" + "#define atomic_fetch_or(x,y) atom_or(x,y)\n" + "#define atomic_fetch_xor(x,y) atom_xor(x,y)\n" + "#define atomic_fetch_and(x,y) atom_and(x,y)\n" + "#define atomic_fetch_min(x,y) atom_min(x,y)\n" + "#define atomic_fetch_max(x,y) atom_max(x,y)\n" + "#define atomic_flag_test_and_set(x) atomic_exchange(x,1)\n" + "#define atomic_flag_clear(x) atomic_store(x,0)\n" + "\n"; + } + if(!LocalMemory() && DeclaredInProgram()) + { + // additional atomic variable for results copying (last thread will do this) + header += "__global volatile atomic_uint finishedThreads = ATOMIC_VAR_INIT(0);\n"; + // atomic variables declared in program scope - test data + std::stringstream ss; + ss << maxNumDestItems; + header += std::string("__global volatile ")+aTypeName+" destMemory["+ss.str()+"] = {\n"; + ss.str(""); + ss << _startValue; + for(cl_uint i = 0; i < maxNumDestItems; i++) + { + if(aTypeName == "atomic_flag") + header += " ATOMIC_FLAG_INIT"; + else + header += " ATOMIC_VAR_INIT("+ss.str()+")"; + if(i+1 < maxNumDestItems) + header += ","; + header += "\n"; + } + header+= + "};\n" + "\n"; + } + return header; +} + +template +std::string CBasicTest::FunctionCode() +{ + if(!UsedInFunction()) + return ""; + std::string addressSpace = LocalMemory() ? "__local " : "__global "; + std::string code = "void test_atomic_function(uint tid, uint threadCount, uint numDestItems, volatile "; + if(!GenericAddrSpace()) + code += addressSpace; + code += std::string(DataType().AtomicTypeName())+" *destMemory, __global "+DataType().RegularTypeName()+ + " *oldValues"; + if(LocalRefValues()) + code += std::string(", __local ")+DataType().RegularTypeName()+" *localValues"; + code += ")\n" + "{\n"; + code += ProgramCore(); + code += "}\n" + "\n"; + return code; +} + +template +std::string CBasicTest::KernelCode(cl_uint maxNumDestItems) +{ + std::string aTypeName = DataType().AtomicTypeName(); + std::string cTypeName = DataType().RegularTypeName(); + std::string addressSpace = LocalMemory() ? "__local " : "__global "; + std::string code = "__kernel void test_atomic_kernel(uint threadCount, uint numDestItems, "; + + // prepare list of arguments for kernel + if(LocalMemory()) + { + code += std::string("__global ")+cTypeName+" *finalDest, __global "+cTypeName+" *oldValues," + " volatile "+addressSpace+aTypeName+" *"+(DeclaredInProgram() ? "notUsed" : "")+"destMemory"; + } + else + { + code += "volatile "+addressSpace+(DeclaredInProgram() ? (cTypeName+" *finalDest") : (aTypeName+" *destMemory"))+ + ", __global "+cTypeName+" *oldValues"; + } + if(LocalRefValues()) + code += std::string(", __local ")+cTypeName+" *localValues"; + code += ")\n" + "{\n"; + if(LocalMemory() && DeclaredInProgram()) + { + // local atomics declared in kernel scope + std::stringstream ss; + ss << maxNumDestItems; + code += std::string(" __local volatile ")+aTypeName+" destMemory["+ss.str()+"];\n"; + } + code += " uint tid = get_global_id(0);\n" + "\n"; + if(LocalMemory()) + { + code += + " // initialize atomics not reachable from host (first thread is doing this, other threads are waiting on barrier)\n" + " if(get_local_id(0) == 0)\n" + " for(uint dstItemIdx = 0; dstItemIdx < numDestItems; dstItemIdx++)\n" + " {\n"; + if(aTypeName == "atomic_flag") + { + code += + " if(finalDest[dstItemIdx])\n" + " atomic_flag_test_and_set(destMemory+dstItemIdx);\n" + " else\n" + " atomic_flag_clear(destMemory+dstItemIdx);\n"; + } + else + { + code += + " atomic_store(destMemory+dstItemIdx, finalDest[dstItemIdx]);\n"; + } + code += + " }\n" + " barrier(CLK_LOCAL_MEM_FENCE);\n" + "\n"; + } + if (LocalRefValues()) + { + code += + " // Copy input reference values into local memory\n"; + if (NumNonAtomicVariablesPerThread() == 1) + code += " localValues[get_local_id(0)] = oldValues[tid];\n"; + else + { + std::stringstream ss; + ss << NumNonAtomicVariablesPerThread(); + code += + " for(uint rfId = 0; rfId < " + ss.str() + "; rfId++)\n" + " localValues[get_local_id(0)*" + ss.str() + "+rfId] = oldValues[tid*" + ss.str() + "+rfId];\n"; + } + code += + " barrier(CLK_LOCAL_MEM_FENCE);\n" + "\n"; + } + if (UsedInFunction()) + code += std::string(" test_atomic_function(tid, threadCount, numDestItems, destMemory, oldValues")+ + (LocalRefValues() ? ", localValues" : "")+");\n"; + else + code += ProgramCore(); + code += "\n"; + if (LocalRefValues()) + { + code += + " // Copy local reference values into output array\n" + " barrier(CLK_LOCAL_MEM_FENCE);\n"; + if (NumNonAtomicVariablesPerThread() == 1) + code += " oldValues[tid] = localValues[get_local_id(0)];\n"; + else + { + std::stringstream ss; + ss << NumNonAtomicVariablesPerThread(); + code += + " for(uint rfId = 0; rfId < " + ss.str() + "; rfId++)\n" + " oldValues[tid*" + ss.str() + "+rfId] = localValues[get_local_id(0)*" + ss.str() + "+rfId];\n"; + } + code += "\n"; + } + if(LocalMemory() || DeclaredInProgram()) + { + code += " // Copy final values to host reachable buffer\n"; + if(LocalMemory()) + code += + " barrier(CLK_LOCAL_MEM_FENCE);\n" + " if(get_local_id(0) == 0) // first thread in workgroup\n"; + else + // global atomics declared in program scope + code += + " if(atomic_fetch_add(&finishedThreads, 1) == get_global_size(0)-1)\n" + " // last finished thread\n"; + code += + " for(uint dstItemIdx = 0; dstItemIdx < numDestItems; dstItemIdx++)\n"; + if(aTypeName == "atomic_flag") + { + code += + " finalDest[dstItemIdx] = atomic_flag_test_and_set(destMemory+dstItemIdx);\n"; + } + else + { + code += + " finalDest[dstItemIdx] = atomic_load(destMemory+dstItemIdx);\n"; + } + } + code += "}\n" + "\n"; + return code; +} + +template +int CBasicTest::ExecuteSingleTest(cl_device_id deviceID, cl_context context, cl_command_queue queue) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + size_t threadNum[1]; + clMemWrapper streams[2]; + std::vector destItems; + HostAtomicType *svmAtomicBuffer = 0; + std::vector refValues, startRefValues; + HostDataType *svmDataBuffer = 0; + cl_uint deviceThreadCount, hostThreadCount, threadCount; + size_t groupSize = 0; + std::string programSource; + const char *programLine; + MTdata d; + size_t typeSize = DataType().Size(deviceID); + + deviceThreadCount = _maxDeviceThreads; + hostThreadCount = MaxHostThreads(); + threadCount = deviceThreadCount+hostThreadCount; + + //log_info("\t%s %s%s...\n", local ? "local" : "global", DataType().AtomicTypeName(), memoryOrderScope.c_str()); + log_info("\t%s...\n", SingleTestName().c_str()); + + if(!LocalMemory() && DeclaredInProgram() && gNoGlobalVariables) // no support for program scope global variables + { + log_info("\t\tTest disabled\n"); + return 0; + } + if(UsedInFunction() && GenericAddrSpace() && gNoGenericAddressSpace) + { + log_info("\t\tTest disabled\n"); + return 0; + } + + // set up work sizes based on device capabilities and test configuration + error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(groupSize), &groupSize, NULL); + test_error(error, "Unable to obtain max work group size for device"); + CurrentGroupSize((cl_uint)groupSize); + if(CurrentGroupSize() > deviceThreadCount) + CurrentGroupSize(deviceThreadCount); + if(CurrentGroupNum(deviceThreadCount) == 1 || gOldAPI) + deviceThreadCount = CurrentGroupSize()*CurrentGroupNum(deviceThreadCount); + threadCount = deviceThreadCount+hostThreadCount; + + // If we're given a num_results function, we need to determine how many result objects we need. + // This is the first assessment for current maximum number of threads (exact thread count is not known here) + // - needed for program source code generation (arrays of atomics declared in program) + cl_uint numDestItems = NumResults(threadCount, deviceID); + + if(deviceThreadCount > 0) + { + cl_ulong usedLocalMemory; + cl_ulong totalLocalMemory; + cl_uint maxWorkGroupSize; + + // Set up the kernel code + programSource = PragmaHeader(deviceID)+ProgramHeader(numDestItems)+FunctionCode()+KernelCode(numDestItems); + programLine = programSource.c_str(); + if(create_single_kernel_helper_with_build_options(context, &program, &kernel, 1, &programLine, "test_atomic_kernel", + gOldAPI ? "" : "-cl-std=CL2.0")) + { + return -1; + } + if(gDebug) + { + log_info("Program source:\n"); + log_info("%s\n", programLine); + } + // tune up work sizes based on kernel info + error = clGetKernelWorkGroupInfo(kernel, deviceID, CL_KERNEL_WORK_GROUP_SIZE, sizeof(groupSize), &groupSize, NULL); + test_error(error, "Unable to obtain max work group size for device and kernel combo"); + + if(LocalMemory()) + { + error = clGetKernelWorkGroupInfo (kernel, deviceID, CL_KERNEL_LOCAL_MEM_SIZE, sizeof(usedLocalMemory), &usedLocalMemory, NULL); + test_error(error, "clGetKernelWorkGroupInfo failed"); + + error = clGetDeviceInfo(deviceID, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(totalLocalMemory), &totalLocalMemory, NULL); + test_error(error, "clGetDeviceInfo failed"); + + // We know that each work-group is going to use typeSize * deviceThreadCount bytes of local memory + // so pick the maximum value for deviceThreadCount that uses all the local memory. + maxWorkGroupSize = ((totalLocalMemory - usedLocalMemory) / typeSize); + + if(maxWorkGroupSize < groupSize) + groupSize = maxWorkGroupSize; + } + + CurrentGroupSize((cl_uint)groupSize); + if(CurrentGroupSize() > deviceThreadCount) + CurrentGroupSize(deviceThreadCount); + if(CurrentGroupNum(deviceThreadCount) == 1 || gOldAPI) + deviceThreadCount = CurrentGroupSize()*CurrentGroupNum(deviceThreadCount); + threadCount = deviceThreadCount+hostThreadCount; + } + if(deviceThreadCount > 0) + log_info("\t\t(thread count %u, group size %u)\n", deviceThreadCount, CurrentGroupSize()); + if(hostThreadCount > 0) + log_info("\t\t(host threads %u)\n", hostThreadCount); + + refValues.resize(threadCount*NumNonAtomicVariablesPerThread()); + + // Generate ref data if we have a ref generator provided + d = init_genrand(gRandomSeed); + startRefValues.resize(threadCount*NumNonAtomicVariablesPerThread()); + if(GenerateRefs(threadCount, &startRefValues[0], d)) + { + //copy ref values for host threads + memcpy(&refValues[0], &startRefValues[0], sizeof(HostDataType)*threadCount*NumNonAtomicVariablesPerThread()); + } + else + { + startRefValues.resize(0); + } + free_mtdata(d); + d = NULL; + + // If we're given a num_results function, we need to determine how many result objects we need. If + // we don't have it, we assume it's just 1 + // This is final value (exact thread count is known in this place) + numDestItems = NumResults(threadCount, deviceID); + + destItems.resize(numDestItems); + for(cl_uint i = 0; i < numDestItems; i++) + destItems[i] = _startValue; + + // Create main buffer with atomic variables (array size dependent on particular test) + if(UseSVM()) + { + if(gUseHostPtr) + svmAtomicBuffer = (HostAtomicType*)malloc(typeSize * numDestItems); + else + svmAtomicBuffer = (HostAtomicType*)clSVMAlloc(context, CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS, typeSize * numDestItems, 0); + if(!svmAtomicBuffer) + { + log_error("ERROR: clSVMAlloc failed!\n"); + return -1; + } + memcpy(svmAtomicBuffer, &destItems[0], typeSize * numDestItems); + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_USE_HOST_PTR), typeSize * numDestItems, svmAtomicBuffer, NULL); + } + else + { + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), typeSize * numDestItems, &destItems[0], NULL); + } + if (!streams[0]) + { + log_error("ERROR: Creating output array failed!\n"); + return -1; + } + // Create buffer for per-thread input/output data + if(UseSVM()) + { + if(gUseHostPtr) + svmDataBuffer = (HostDataType*)malloc(typeSize*threadCount*NumNonAtomicVariablesPerThread()); + else + svmDataBuffer = (HostDataType*)clSVMAlloc(context, CL_MEM_SVM_FINE_GRAIN_BUFFER | (SVMDataBufferAllSVMConsistent() ? CL_MEM_SVM_ATOMICS : 0), typeSize*threadCount*NumNonAtomicVariablesPerThread(), 0); + if(!svmDataBuffer) + { + log_error("ERROR: clSVMAlloc failed!\n"); + return -1; + } + if(startRefValues.size()) + memcpy(svmDataBuffer, &startRefValues[0], typeSize*threadCount*NumNonAtomicVariablesPerThread()); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_USE_HOST_PTR), typeSize*threadCount*NumNonAtomicVariablesPerThread(), svmDataBuffer, NULL); + } + else + { + streams[1] = clCreateBuffer(context, (cl_mem_flags)((startRefValues.size() ? CL_MEM_COPY_HOST_PTR : CL_MEM_READ_WRITE)), + typeSize * threadCount*NumNonAtomicVariablesPerThread(), startRefValues.size() ? &startRefValues[0] : 0, NULL); + } + if (!streams[1]) + { + log_error("ERROR: Creating reference array failed!\n"); + return -1; + } + if(deviceThreadCount > 0) + { + cl_uint argInd = 0; + /* Set the arguments */ + error = clSetKernelArg(kernel, argInd++, sizeof(threadCount), &threadCount); + test_error(error, "Unable to set kernel argument"); + error = clSetKernelArg(kernel, argInd++, sizeof(numDestItems), &numDestItems); + test_error(error, "Unable to set indexed kernel argument"); + error = clSetKernelArg(kernel, argInd++, sizeof(streams[0]), &streams[0]); + test_error(error, "Unable to set indexed kernel arguments"); + error = clSetKernelArg(kernel, argInd++, sizeof(streams[1]), &streams[1]); + test_error(error, "Unable to set indexed kernel arguments"); + if(LocalMemory()) + { + error = clSetKernelArg(kernel, argInd++, typeSize * numDestItems, NULL); + test_error(error, "Unable to set indexed local kernel argument"); + } + if(LocalRefValues()) + { + error = clSetKernelArg(kernel, argInd++, LocalRefValues() ? typeSize*CurrentGroupSize()*NumNonAtomicVariablesPerThread() : 1, NULL); + test_error(error, "Unable to set indexed kernel argument"); + } + } + /* Configure host threads */ + std::vector hostThreadContexts(hostThreadCount); + for(unsigned int t = 0; t < hostThreadCount; t++) + { + hostThreadContexts[t].test = this; + hostThreadContexts[t].tid = deviceThreadCount+t; + hostThreadContexts[t].threadCount = threadCount; + hostThreadContexts[t].destMemory = UseSVM() ? svmAtomicBuffer : &destItems[0]; + hostThreadContexts[t].oldValues = UseSVM() ? svmDataBuffer : &refValues[0]; + } + + if(deviceThreadCount > 0) + { + /* Run the kernel */ + threadNum[0] = deviceThreadCount; + groupSize = CurrentGroupSize(); + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, threadNum, &groupSize, 0, NULL, NULL); + test_error(error, "Unable to execute test kernel"); + /* start device threads */ + error = clFlush(queue); + test_error(error, "clFlush failed"); + } + + /* Start host threads and wait for finish */ + if(hostThreadCount > 0) + ThreadPool_Do(HostThreadFunction, hostThreadCount, &hostThreadContexts[0]); + + if(UseSVM()) + { + error = clFinish(queue); + test_error(error, "clFinish failed"); + memcpy(&destItems[0], svmAtomicBuffer, typeSize*numDestItems); + memcpy(&refValues[0], svmDataBuffer, typeSize*threadCount*NumNonAtomicVariablesPerThread()); + } + else + { + if(deviceThreadCount > 0) + { + error = clEnqueueReadBuffer(queue, streams[0], CL_TRUE, 0, typeSize * numDestItems, &destItems[0], 0, NULL, NULL); + test_error(error, "Unable to read result value!"); + error = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, typeSize * deviceThreadCount*NumNonAtomicVariablesPerThread(), &refValues[0], 0, NULL, NULL); + test_error(error, "Unable to read reference values!"); + } + } + bool dataVerified = false; + // If we have an expectedFn, then we need to generate a final value to compare against. If we don't + // have one, it's because we're comparing ref values only + for(cl_uint i = 0; i < numDestItems; i++) + { + HostDataType expected; + + if(!ExpectedValue(expected, threadCount, startRefValues.size() ? &startRefValues[0] : 0, i)) + break; // no expected value function provided + + if(expected != destItems[i]) + { + std::stringstream logLine; + logLine << "ERROR: Result " << i << " from kernel does not validate! (should be " << expected << ", was " << destItems[i] << ")\n"; + log_error("%s", logLine.str().c_str()); + for(i = 0; i < threadCount; i++) + { + logLine.str(""); + logLine << " --- " << i << " - "; + if(startRefValues.size()) + logLine << startRefValues[i] << " -> " << refValues[i]; + else + logLine << refValues[i]; + logLine << " --- "; + if(i < numDestItems) + logLine << destItems[i]; + logLine << "\n"; + log_info("%s", logLine.str().c_str()); + } + if(!gDebug) + { + log_info("Program source:\n"); + log_info("%s\n", programLine); + } + return -1; + } + dataVerified = true; + } + + bool dataCorrect = false; + /* Use the verify function (if provided) to also check the results */ + if(VerifyRefs(dataCorrect, threadCount, &refValues[0], &destItems[0])) + { + if(!dataCorrect) + { + log_error("ERROR: Reference values did not validate!\n"); + std::stringstream logLine; + for(cl_uint i = 0; i < threadCount; i++) + for (cl_uint j = 0; j < NumNonAtomicVariablesPerThread(); j++) + { + logLine.str(""); + logLine << " --- " << i << " - " << refValues[i*NumNonAtomicVariablesPerThread()+j] << " --- "; + if(j == 0 && i < numDestItems) + logLine << destItems[i]; + logLine << "\n"; + log_info("%s", logLine.str().c_str()); + } + if(!gDebug) + { + log_info("Program source:\n"); + log_info("%s\n", programLine); + } + return -1; + } + } + else if(!dataVerified) + { + log_error("ERROR: Test doesn't check total or refs; no values are verified!\n"); + return -1; + } + + if(OldValueCheck() && + !(DeclaredInProgram() && !LocalMemory())) // don't test for programs scope global atomics + // 'old' value has been overwritten by previous clEnqueueNDRangeKernel + { + /* Re-write the starting value */ + for(size_t i = 0; i < numDestItems; i++) + destItems[i] = _startValue; + refValues[0] = 0; + if(deviceThreadCount > 0) + { + error = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, typeSize * numDestItems, &destItems[0], 0, NULL, NULL); + test_error(error, "Unable to write starting values!"); + + /* Run the kernel once for a single thread, so we can verify that the returned value is the original one */ + threadNum[0] = 1; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, threadNum, threadNum, 0, NULL, NULL); + test_error(error, "Unable to execute test kernel"); + + error = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, typeSize, &refValues[0], 0, NULL, NULL); + test_error(error, "Unable to read reference values!"); + } + else + { + /* Start host thread */ + HostFunction(0, 1, &destItems[0], &refValues[0]); + } + + if(refValues[0] != _startValue)//destItems[0]) + { + std::stringstream logLine; + logLine << "ERROR: atomic function operated correctly but did NOT return correct 'old' value " + " (should have been " << destItems[0] << ", returned " << refValues[0] << ")!\n"; + log_error("%s", logLine.str().c_str()); + if(!gDebug) + { + log_info("Program source:\n"); + log_info("%s\n", programLine); + } + return -1; + } + } + if(UseSVM()) + { + // the buffer object must first be released before the SVM buffer is freed + error = clReleaseMemObject(streams[0]); + streams[0] = 0; + test_error(error, "clReleaseMemObject failed"); + if(gUseHostPtr) + free(svmAtomicBuffer); + else + clSVMFree(context, svmAtomicBuffer); + error = clReleaseMemObject(streams[1]); + streams[1] = 0; + test_error(error, "clReleaseMemObject failed"); + if(gUseHostPtr) + free(svmDataBuffer); + else + clSVMFree(context, svmDataBuffer); + } + _passCount++; + return 0; +} + +#endif //_COMMON_H_ diff --git a/test_conformance/c11_atomics/host_atomics.cpp b/test_conformance/c11_atomics/host_atomics.cpp new file mode 100644 index 00000000..008fdd25 --- /dev/null +++ b/test_conformance/c11_atomics/host_atomics.cpp @@ -0,0 +1,66 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "host_atomics.h" + +void host_atomic_thread_fence(TExplicitMemoryOrderType order) +{ + if(order != MEMORY_ORDER_RELAXED) { +#if defined( _MSC_VER ) || (defined( __INTEL_COMPILER ) && defined(WIN32)) + MemoryBarrier(); +#elif defined(__GNUC__) + __sync_synchronize(); +#else + log_info("Host function not implemented: host_atomic_thread_fence\n"); +#endif + } +} + +template <> +HOST_FLOAT host_atomic_exchange(volatile HOST_ATOMIC_FLOAT* a, HOST_FLOAT c, TExplicitMemoryOrderType order) +{ + HOST_UINT tmp = host_atomic_exchange((volatile HOST_ATOMIC_UINT*)a, *(HOST_UINT*)&c, order); + return *(float*)&tmp; +} +template <> +HOST_DOUBLE host_atomic_exchange(volatile HOST_ATOMIC_DOUBLE* a, HOST_DOUBLE c, TExplicitMemoryOrderType order) +{ + HOST_ULONG tmp = host_atomic_exchange((volatile HOST_ATOMIC_ULONG*)a, *(HOST_ULONG*)&c, order); + return *(double*)&tmp; +} + +template <> +HOST_FLOAT host_atomic_load(volatile HOST_ATOMIC_FLOAT* a, TExplicitMemoryOrderType order) +{ + HOST_UINT tmp = host_atomic_load((volatile HOST_ATOMIC_UINT*)a, order); + return *(float*)&tmp; +} +template <> +HOST_DOUBLE host_atomic_load(volatile HOST_ATOMIC_DOUBLE* a, TExplicitMemoryOrderType order) +{ + HOST_ULONG tmp = host_atomic_load((volatile HOST_ATOMIC_ULONG*)a, order); + return *(double*)&tmp; +} + +bool host_atomic_flag_test_and_set(volatile HOST_ATOMIC_FLAG *a, TExplicitMemoryOrderType order) +{ + HOST_FLAG old = host_atomic_exchange(a, 1, order); + return old != 0; +} + +void host_atomic_flag_clear(volatile HOST_ATOMIC_FLAG *a, TExplicitMemoryOrderType order) +{ + host_atomic_store(a, 0, order); +} diff --git a/test_conformance/c11_atomics/host_atomics.h b/test_conformance/c11_atomics/host_atomics.h new file mode 100644 index 00000000..9a044ded --- /dev/null +++ b/test_conformance/c11_atomics/host_atomics.h @@ -0,0 +1,250 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _HOST_ATOMICS_H_ +#define _HOST_ATOMICS_H_ + +#include "../../test_common/harness/testHarness.h" + +#ifdef WIN32 +#include "Windows.h" +#endif + +//flag for test verification (good test should discover non-atomic functions and fail) +//#define NON_ATOMIC_FUNCTIONS + +enum TExplicitMemoryOrderType +{ + MEMORY_ORDER_EMPTY, + MEMORY_ORDER_RELAXED, + MEMORY_ORDER_ACQUIRE, + MEMORY_ORDER_RELEASE, + MEMORY_ORDER_ACQ_REL, + MEMORY_ORDER_SEQ_CST +}; + +// host atomic types (applicable for atomic functions supported on host OS) +#ifdef WIN32 +#define HOST_ATOMIC_INT unsigned long +#define HOST_ATOMIC_UINT unsigned long +#define HOST_ATOMIC_LONG unsigned long long +#define HOST_ATOMIC_ULONG unsigned long long +#define HOST_ATOMIC_FLOAT float +#define HOST_ATOMIC_DOUBLE double +#else +#define HOST_ATOMIC_INT cl_int +#define HOST_ATOMIC_UINT cl_uint +#define HOST_ATOMIC_LONG cl_long +#define HOST_ATOMIC_ULONG cl_ulong +#define HOST_ATOMIC_FLOAT cl_float +#define HOST_ATOMIC_DOUBLE cl_double +#endif + +#define HOST_ATOMIC_INTPTR_T32 HOST_ATOMIC_INT +#define HOST_ATOMIC_UINTPTR_T32 HOST_ATOMIC_INT +#define HOST_ATOMIC_SIZE_T32 HOST_ATOMIC_UINT +#define HOST_ATOMIC_PTRDIFF_T32 HOST_ATOMIC_INT + +#define HOST_ATOMIC_INTPTR_T64 HOST_ATOMIC_LONG +#define HOST_ATOMIC_UINTPTR_T64 HOST_ATOMIC_LONG +#define HOST_ATOMIC_SIZE_T64 HOST_ATOMIC_ULONG +#define HOST_ATOMIC_PTRDIFF_T64 HOST_ATOMIC_LONG + +#define HOST_ATOMIC_FLAG HOST_ATOMIC_INT + +// host regular types corresponding to atomic types +#define HOST_INT cl_int +#define HOST_UINT cl_uint +#define HOST_LONG cl_long +#define HOST_ULONG cl_ulong +#define HOST_FLOAT cl_float +#define HOST_DOUBLE cl_double + +#define HOST_INTPTR_T32 cl_int +#define HOST_UINTPTR_T32 cl_uint +#define HOST_SIZE_T32 cl_uint +#define HOST_PTRDIFF_T32 cl_int + +#define HOST_INTPTR_T64 cl_long +#define HOST_UINTPTR_T64 cl_ulong +#define HOST_SIZE_T64 cl_ulong +#define HOST_PTRDIFF_T64 cl_long + +#define HOST_FLAG cl_uint + +// host atomic functions +void host_atomic_thread_fence(TExplicitMemoryOrderType order); + +template +CorrespondingType host_atomic_fetch_add(volatile AtomicType *a, CorrespondingType c, + TExplicitMemoryOrderType order) +{ +#if defined( _MSC_VER ) || (defined( __INTEL_COMPILER ) && defined(WIN32)) + return InterlockedExchangeAdd(a, c); +#elif defined(__GNUC__) + return __sync_fetch_and_add(a, c); +#else + log_info("Host function not implemented: atomic_fetch_add\n"); + return 0; +#endif +} + +template +CorrespondingType host_atomic_fetch_sub(volatile AtomicType *a, CorrespondingType c, + TExplicitMemoryOrderType order) +{ +#if defined( _MSC_VER ) || (defined( __INTEL_COMPILER ) && defined(WIN32)) + return InterlockedExchangeSubtract(a, c); +#elif defined(__GNUC__) + return __sync_fetch_and_sub(a, c); +#else + log_info("Host function not implemented: atomic_fetch_sub\n"); + return 0; +#endif +} + +template +CorrespondingType host_atomic_exchange(volatile AtomicType *a, CorrespondingType c, + TExplicitMemoryOrderType order) +{ +#if defined( _MSC_VER ) || (defined( __INTEL_COMPILER ) && defined(WIN32)) + return InterlockedExchange(a, c); +#elif defined(__GNUC__) + return __sync_lock_test_and_set(a, c); +#else + log_info("Host function not implemented: atomic_exchange\n"); + return 0; +#endif +} +template <> HOST_FLOAT host_atomic_exchange(volatile HOST_ATOMIC_FLOAT *a, HOST_FLOAT c, + TExplicitMemoryOrderType order); +template <> HOST_DOUBLE host_atomic_exchange(volatile HOST_ATOMIC_DOUBLE *a, HOST_DOUBLE c, + TExplicitMemoryOrderType order); + +template +bool host_atomic_compare_exchange(volatile AtomicType *a, CorrespondingType *expected, CorrespondingType desired, + TExplicitMemoryOrderType order_success, + TExplicitMemoryOrderType order_failure) +{ + CorrespondingType tmp; +#if defined( _MSC_VER ) || (defined( __INTEL_COMPILER ) && defined(WIN32)) + tmp = InterlockedCompareExchange(a, desired, *expected); +#elif defined(__GNUC__) + tmp = __sync_val_compare_and_swap(a, *expected, desired); +#else + log_info("Host function not implemented: atomic_compare_exchange\n"); + tmp = 0; +#endif + if(tmp == *expected) + return true; + *expected = tmp; + return false; +} + +template +CorrespondingType host_atomic_load(volatile AtomicType *a, + TExplicitMemoryOrderType order) +{ +#if defined( _MSC_VER ) || (defined( __INTEL_COMPILER ) && defined(WIN32)) + return InterlockedExchangeAdd(a, 0); +#elif defined(__GNUC__) + return __sync_add_and_fetch(a, 0); +#else + log_info("Host function not implemented: atomic_load\n"); + return 0; +#endif +} +template <> HOST_FLOAT host_atomic_load(volatile HOST_ATOMIC_FLOAT *a, + TExplicitMemoryOrderType order); +template <> HOST_DOUBLE host_atomic_load(volatile HOST_ATOMIC_DOUBLE *a, + TExplicitMemoryOrderType order); + +template +void host_atomic_store(volatile AtomicType* a, CorrespondingType c, + TExplicitMemoryOrderType order) +{ + host_atomic_exchange(a, c, order); +} + +template +void host_atomic_init(volatile AtomicType* a, CorrespondingType c) +{ + host_atomic_exchange(a, c, MEMORY_ORDER_RELAXED); +} + +template +CorrespondingType host_atomic_fetch_or(volatile AtomicType *a, CorrespondingType c, + TExplicitMemoryOrderType order) +{ + CorrespondingType expected = host_atomic_load(a, order); + CorrespondingType desired; + do + desired = expected | c; + while(!host_atomic_compare_exchange(a, &expected, desired, order, order)); + return expected; +} + +template +CorrespondingType host_atomic_fetch_and(volatile AtomicType *a, CorrespondingType c, + TExplicitMemoryOrderType order) +{ + CorrespondingType expected = host_atomic_load(a, order); + CorrespondingType desired; + do + desired = expected & c; + while(!host_atomic_compare_exchange(a, &expected, desired, order, order)); + return expected; +} + +template +CorrespondingType host_atomic_fetch_xor(volatile AtomicType *a, CorrespondingType c, + TExplicitMemoryOrderType order) +{ + CorrespondingType expected = host_atomic_load(a, order); + CorrespondingType desired; + do + desired = expected ^ c; + while(!host_atomic_compare_exchange(a, &expected, desired, order, order)); + return expected; +} + +template +CorrespondingType host_atomic_fetch_min(volatile AtomicType *a, CorrespondingType c, + TExplicitMemoryOrderType order) +{ + CorrespondingType expected = host_atomic_load(a, order); + CorrespondingType desired; + do + desired = expected < c ? expected : c; + while(!host_atomic_compare_exchange(a, &expected, desired, order, order)); + return expected; +} + +template +CorrespondingType host_atomic_fetch_max(volatile AtomicType *a, CorrespondingType c, + TExplicitMemoryOrderType order) +{ + CorrespondingType expected = host_atomic_load(a, order); + CorrespondingType desired; + do + desired = expected > c ? expected : c; + while(!host_atomic_compare_exchange(a, &expected, desired, order, order)); + return expected; +} + +bool host_atomic_flag_test_and_set(volatile HOST_ATOMIC_FLAG *a, TExplicitMemoryOrderType order); +void host_atomic_flag_clear(volatile HOST_ATOMIC_FLAG *a, TExplicitMemoryOrderType order); + +#endif //_HOST_ATOMICS_H_ diff --git a/test_conformance/c11_atomics/main.cpp b/test_conformance/c11_atomics/main.cpp new file mode 100644 index 00000000..f40c45e6 --- /dev/null +++ b/test_conformance/c11_atomics/main.cpp @@ -0,0 +1,230 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/testHarness.h" +#include +#include + +bool gHost = false; // flag for testing native host threads (test verification) +bool gOldAPI = false; // flag for testing with old API (OpenCL 1.2) - test verification +bool gContinueOnError = false; // execute all cases even when errors detected +bool gNoGlobalVariables = false; // disable cases with global atomics in program scope +bool gNoGenericAddressSpace = false; // disable cases with generic address space +bool gUseHostPtr = false; // use malloc/free with CL_MEM_USE_HOST_PTR instead of clSVMAlloc/clSVMFree +bool gDebug = false; // always print OpenCL kernel code +int gInternalIterations = 10000; // internal test iterations for atomic operation, sufficient to verify atomicity +int gMaxDeviceThreads = 1024; // maximum number of threads executed on OCL device + +extern int test_atomic_init(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_store(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_load(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_store_load(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_exchange(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_compare_exchange_weak(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_compare_exchange_strong(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_add(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_sub(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_and(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_or(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_orand(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_xor(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_xor2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_min(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_max(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_flag(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fence(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_atomic_init_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_store_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_load_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_store_load_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_exchange_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_compare_exchange_weak_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_compare_exchange_strong_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_add_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_sub_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_and_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_or_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_orand_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_xor_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_xor2_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_min_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fetch_max_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_flag_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_atomic_fence_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +basefn basefn_list[] = { + test_atomic_init, + test_atomic_store, + test_atomic_load, + test_atomic_exchange, + test_atomic_compare_exchange_weak, + test_atomic_compare_exchange_strong, + test_atomic_fetch_add, + test_atomic_fetch_sub, + test_atomic_fetch_and, + test_atomic_fetch_or, + test_atomic_fetch_orand, + test_atomic_fetch_xor, + test_atomic_fetch_xor2, + test_atomic_fetch_min, + test_atomic_fetch_max, + test_atomic_flag, + test_atomic_fence, + + test_atomic_init_svm, + test_atomic_store_svm, + test_atomic_load_svm, + test_atomic_exchange_svm, + test_atomic_compare_exchange_weak_svm, + test_atomic_compare_exchange_strong_svm, + test_atomic_fetch_add_svm, + test_atomic_fetch_sub_svm, + test_atomic_fetch_and_svm, + test_atomic_fetch_or_svm, + test_atomic_fetch_orand_svm, + test_atomic_fetch_xor_svm, + test_atomic_fetch_xor2_svm, + test_atomic_fetch_min_svm, + test_atomic_fetch_max_svm, + test_atomic_flag_svm, + test_atomic_fence_svm +}; + +const char *basefn_names[] = { + "atomic_init", + "atomic_store", + "atomic_load", + "atomic_exchange", + "atomic_compare_exchange_weak", + "atomic_compare_exchange_strong", + "atomic_fetch_add", + "atomic_fetch_sub", + "atomic_fetch_and", + "atomic_fetch_or", + "atomic_fetch_orand", + "atomic_fetch_xor", + "atomic_fetch_xor2", + "atomic_fetch_min", + "atomic_fetch_max", + "atomic_flag", + "atomic_fence", + + "svm_atomic_init", + "svm_atomic_store", + "svm_atomic_load", + "svm_atomic_exchange", + "svm_atomic_compare_exchange_weak", + "svm_atomic_compare_exchange_strong", + "svm_atomic_fetch_add", + "svm_atomic_fetch_sub", + "svm_atomic_fetch_and", + "svm_atomic_fetch_or", + "svm_atomic_fetch_orand", + "svm_atomic_fetch_xor", + "svm_atomic_fetch_xor2", + "svm_atomic_fetch_min", + "svm_atomic_fetch_max", + "svm_atomic_flag", + "svm_atomic_fence", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + +int main(int argc, const char *argv[]) +{ + bool noCert = false; + while(true) + { + if(std::string(argv[argc-1]) == "-h") + { + log_info("Test options:\n"); + log_info(" '-host' flag for testing native host threads (test verification)\n"); + log_info(" '-oldAPI' flag for testing with old API (OpenCL 1.2) - test verification\n"); + log_info(" '-continueOnError' execute all cases even when errors detected\n"); + log_info(" '-noGlobalVariables' disable cases with global atomics in program scope\n"); + log_info(" '-noGenericAddressSpace' disable cases with generic address space\n"); + log_info(" '-useHostPtr' use malloc/free with CL_MEM_USE_HOST_PTR instead of clSVMAlloc/clSVMFree\n"); + log_info(" '-debug' always print OpenCL kernel code\n"); + log_info(" '-internalIterations ' internal test iterations for atomic operation, sufficient to verify atomicity\n"); + log_info(" '-maxDeviceThreads ' maximum number of threads executed on OCL device"); + + break; + } + if(std::string(argv[argc-1]) == "-host") // temporary option for testing native host threads + { + gHost = true; + noCert = true; + } + else if(std::string(argv[argc-1]) == "-oldAPI") // temporary flag for testing with old API (OpenCL 1.2) + { + gOldAPI = true; + gNoGlobalVariables = true; + gNoGenericAddressSpace = true; + gUseHostPtr = true; + noCert = true; + } + else if(std::string(argv[argc-1]) == "-continueOnError") // execute all cases even when errors detected + gContinueOnError = true; + else if(std::string(argv[argc-1]) == "-noGlobalVariables") // disable cases with global atomics in program scope + { + gNoGlobalVariables = true; + noCert = true; + } + else if(std::string(argv[argc-1]) == "-noGenericAddressSpace") // disable cases with generic address space + { + gNoGenericAddressSpace = true; + noCert = true; + } + else if(std::string(argv[argc-1]) == "-useHostPtr") // use malloc/free with CL_MEM_USE_HOST_PTR instead of clSVMAlloc/clSVMFree + { + gUseHostPtr = true; + noCert = true; + } + else if(std::string(argv[argc-1]) == "-debug") // print OpenCL kernel code + gDebug = true; + else if(argc > 2 && std::string(argv[argc-2]) == "-internalIterations") // internal test iterations for atomic operation, sufficient to verify atomicity + { + gInternalIterations = atoi(argv[argc-1]); + if(gInternalIterations < 1) + { + log_info("Invalid value: Number of internal iterations (%d) must be > 0\n", gInternalIterations); + return -1; + } + argc--; + noCert = true; + } + else if(argc > 2 && std::string(argv[argc-2]) == "-maxDeviceThreads") // maximum number of threads executed on OCL device + { + gMaxDeviceThreads = atoi(argv[argc-1]); + argc--; + noCert = true; + } + else + break; + argc--; + } + if(noCert) + { + log_info("\n" ); + log_info("*** ***\n"); + log_info("*** WARNING: Test execution in debug mode (forced by command-line option)! ***\n"); + log_info("*** Use of this mode is not sufficient to verify correctness. ***\n"); + log_info("*** ***\n"); + } + return runTestHarness(argc, argv, num_fns, basefn_list, basefn_names, false, false, 0); +} diff --git a/test_conformance/c11_atomics/test_atomics.cpp b/test_conformance/c11_atomics/test_atomics.cpp new file mode 100644 index 00000000..542e893f --- /dev/null +++ b/test_conformance/c11_atomics/test_atomics.cpp @@ -0,0 +1,2142 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/typeWrappers.h" + +#include "common.h" +#include "host_atomics.h" + +#include +#include + +template +class CBasicTestStore : public CBasicTestMemOrderScope +{ +public: + using CBasicTestMemOrderScope::OldValueCheck; + using CBasicTestMemOrderScope::MemoryOrder; + using CBasicTestMemOrderScope::MemoryOrderScopeStr; + CBasicTestStore(TExplicitAtomicType dataType, bool useSVM) : CBasicTestMemOrderScope(dataType, useSVM) + { + OldValueCheck(false); + } + virtual cl_uint NumResults(cl_uint threadCount, cl_device_id deviceID) + { + return threadCount; + } + virtual int ExecuteSingleTest(cl_device_id deviceID, cl_context context, cl_command_queue queue) + { + if(MemoryOrder() == MEMORY_ORDER_ACQUIRE || + MemoryOrder() == MEMORY_ORDER_ACQ_REL) + return 0; //skip test - not applicable + return CBasicTestMemOrderScope::ExecuteSingleTest(deviceID, context, queue); + } + virtual std::string ProgramCore() + { + std::string memoryOrderScope = MemoryOrderScopeStr(); + std::string postfix(memoryOrderScope.empty() ? "" : "_explicit"); + return + " atomic_store"+postfix+"(&destMemory[tid], tid"+memoryOrderScope+");\n"; + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + host_atomic_store(&destMemory[tid], (HostDataType)tid, MemoryOrder()); + } + virtual bool ExpectedValue(HostDataType &expected, cl_uint threadCount, HostDataType *startRefValues, cl_uint whichDestValue) + { + expected = (HostDataType)whichDestValue; + return true; + } +}; + +int test_atomic_store_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestStore test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestStore test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestStore test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestStore test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + CBasicTestStore test_float(TYPE_ATOMIC_FLOAT, useSVM); + EXECUTE_TEST(error, test_float.Execute(deviceID, context, queue, num_elements)); + CBasicTestStore test_double(TYPE_ATOMIC_DOUBLE, useSVM); + EXECUTE_TEST(error, test_double.Execute(deviceID, context, queue, num_elements)); + if(AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestStore test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestStore test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestStore test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestStore test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestStore test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestStore test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestStore test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestStore test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_store(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_store_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_store_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_store_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestInit : public CBasicTest +{ +public: + using CBasicTest::OldValueCheck; + CBasicTestInit(TExplicitAtomicType dataType, bool useSVM) : CBasicTest(dataType, useSVM) + { + OldValueCheck(false); + } + virtual cl_uint NumResults(cl_uint threadCount, cl_device_id deviceID) + { + return threadCount; + } + virtual std::string ProgramCore() + { + return + " atomic_init(&destMemory[tid], tid);\n"; + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + host_atomic_init(&destMemory[tid], (HostDataType)tid); + } + virtual bool ExpectedValue(HostDataType &expected, cl_uint threadCount, HostDataType *startRefValues, cl_uint whichDestValue) + { + expected = (HostDataType)whichDestValue; + return true; + } +}; + +int test_atomic_init_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestInit test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestInit test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestInit test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestInit test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + CBasicTestInit test_float(TYPE_ATOMIC_FLOAT, useSVM); + EXECUTE_TEST(error, test_float.Execute(deviceID, context, queue, num_elements)); + CBasicTestInit test_double(TYPE_ATOMIC_DOUBLE, useSVM); + EXECUTE_TEST(error, test_double.Execute(deviceID, context, queue, num_elements)); + if(AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestInit test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestInit test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestInit test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestInit test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestInit test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestInit test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestInit test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestInit test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_init(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_init_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_init_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_init_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestLoad : public CBasicTestMemOrderScope +{ +public: + using CBasicTestMemOrderScope::OldValueCheck; + using CBasicTestMemOrderScope::MemoryOrder; + using CBasicTestMemOrderScope::MemoryOrderScopeStr; + CBasicTestLoad(TExplicitAtomicType dataType, bool useSVM) : CBasicTestMemOrderScope(dataType, useSVM) + { + OldValueCheck(false); + } + virtual cl_uint NumResults(cl_uint threadCount, cl_device_id deviceID) + { + return threadCount; + } + virtual int ExecuteSingleTest(cl_device_id deviceID, cl_context context, cl_command_queue queue) + { + if(MemoryOrder() == MEMORY_ORDER_RELEASE || + MemoryOrder() == MEMORY_ORDER_ACQ_REL) + return 0; //skip test - not applicable + return CBasicTestMemOrderScope::ExecuteSingleTest(deviceID, context, queue); + } + virtual std::string ProgramCore() + { + std::string memoryOrderScope = MemoryOrderScopeStr(); + std::string postfix(memoryOrderScope.empty() ? "" : "_explicit"); + return + " atomic_store(&destMemory[tid], tid);\n" + " oldValues[tid] = atomic_load"+postfix+"(&destMemory[tid]"+memoryOrderScope+");\n"; + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + host_atomic_store(&destMemory[tid], (HostDataType)tid, MEMORY_ORDER_SEQ_CST); + oldValues[tid] = host_atomic_load(&destMemory[tid], MemoryOrder()); + } + virtual bool ExpectedValue(HostDataType &expected, cl_uint threadCount, HostDataType *startRefValues, cl_uint whichDestValue) + { + expected = (HostDataType)whichDestValue; + return true; + } + virtual bool VerifyRefs(bool &correct, cl_uint threadCount, HostDataType *refValues, HostAtomicType *finalValues) + { + correct = true; + for(cl_uint i = 0; i < threadCount; i++ ) + { + if(refValues[i] != (HostDataType)i) + { + log_error("Invalid value for thread %u\n", (cl_uint)i); + correct = false; + return true; + } + } + return true; + } +}; + +int test_atomic_load_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestLoad test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestLoad test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestLoad test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestLoad test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + CBasicTestLoad test_float(TYPE_ATOMIC_FLOAT, useSVM); + EXECUTE_TEST(error, test_float.Execute(deviceID, context, queue, num_elements)); + CBasicTestLoad test_double(TYPE_ATOMIC_DOUBLE, useSVM); + EXECUTE_TEST(error, test_double.Execute(deviceID, context, queue, num_elements)); + if(AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestLoad test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestLoad test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestLoad test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestLoad test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestLoad test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestLoad test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestLoad test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestLoad test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_load(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_load_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_load_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_load_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestExchange : public CBasicTestMemOrderScope +{ +public: + using CBasicTestMemOrderScope::OldValueCheck; + using CBasicTestMemOrderScope::StartValue; + using CBasicTestMemOrderScope::MemoryOrder; + using CBasicTestMemOrderScope::MemoryOrderScopeStr; + using CBasicTestMemOrderScope::Iterations; + using CBasicTestMemOrderScope::IterationsStr; + CBasicTestExchange(TExplicitAtomicType dataType, bool useSVM) : CBasicTestMemOrderScope(dataType, useSVM) + { + StartValue(123456); + } + virtual std::string ProgramCore() + { + std::string memoryOrderScope = MemoryOrderScopeStr(); + std::string postfix(memoryOrderScope.empty() ? "" : "_explicit"); + return + " oldValues[tid] = atomic_exchange"+postfix+"(&destMemory[0], tid"+memoryOrderScope+");\n" + " for(int i = 0; i < "+IterationsStr()+"; i++)\n" + " oldValues[tid] = atomic_exchange"+postfix+"(&destMemory[0], oldValues[tid]"+memoryOrderScope+");\n"; + } + + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + oldValues[tid] = host_atomic_exchange(&destMemory[0], (HostDataType)tid, MemoryOrder()); + for(int i = 0; i < Iterations(); i++) + oldValues[tid] = host_atomic_exchange(&destMemory[0], oldValues[tid], MemoryOrder()); + } + virtual bool VerifyRefs(bool &correct, cl_uint threadCount, HostDataType *refValues, HostAtomicType *finalValues) + { + OldValueCheck(Iterations()%2 == 0); //check is valid for even number of iterations only + correct = true; + /* We are expecting values from 0 to size-1 and initial value from atomic variable */ + /* These values must be distributed across refValues array and atomic variable finalVaue[0] */ + /* Any repeated value is treated as an error */ + std::vector tidFound(threadCount); + bool startValueFound = false; + cl_uint i; + + for(i = 0; i <= threadCount; i++) + { + cl_uint value; + if(i == threadCount) + value = (cl_uint)finalValues[0]; //additional value from atomic variable (last written) + else + value = (cl_uint)refValues[i]; + if(value == (cl_uint)StartValue()) + { + // Special initial value + if(startValueFound) + { + log_error("ERROR: Starting reference value (%u) occurred more thane once\n", (cl_uint)StartValue()); + correct = false; + return true; + } + startValueFound = true; + continue; + } + if(value >= threadCount) + { + log_error("ERROR: Reference value %u outside of valid range! (%u)\n", i, value); + correct = false; + return true; + } + if(tidFound[value]) + { + log_error("ERROR: Value (%u) occurred more thane once\n", value); + correct = false; + return true; + } + tidFound[value] = true; + } + return true; + } +}; + +int test_atomic_exchange_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestExchange test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestExchange test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestExchange test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestExchange test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + CBasicTestExchange test_float(TYPE_ATOMIC_FLOAT, useSVM); + EXECUTE_TEST(error, test_float.Execute(deviceID, context, queue, num_elements)); + CBasicTestExchange test_double(TYPE_ATOMIC_DOUBLE, useSVM); + EXECUTE_TEST(error, test_double.Execute(deviceID, context, queue, num_elements)); + if(AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestExchange test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestExchange test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestExchange test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestExchange test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestExchange test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestExchange test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestExchange test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestExchange test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_exchange(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_exchange_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_exchange_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_exchange_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestCompareStrong : public CBasicTestMemOrder2Scope +{ +public: + using CBasicTestMemOrder2Scope::StartValue; + using CBasicTestMemOrder2Scope::OldValueCheck; + using CBasicTestMemOrder2Scope::MemoryOrder; + using CBasicTestMemOrder2Scope::MemoryOrder2; + using CBasicTestMemOrder2Scope::MemoryOrderScope; + using CBasicTestMemOrder2Scope::DataType; + using CBasicTestMemOrder2Scope::Iterations; + using CBasicTestMemOrder2Scope::IterationsStr; + CBasicTestCompareStrong(TExplicitAtomicType dataType, bool useSVM) : CBasicTestMemOrder2Scope(dataType, useSVM) + { + StartValue(123456); + OldValueCheck(false); + } + virtual int ExecuteSingleTest(cl_device_id deviceID, cl_context context, cl_command_queue queue) + { + if(MemoryOrder2() == MEMORY_ORDER_RELEASE || + MemoryOrder2() == MEMORY_ORDER_ACQ_REL) + return 0; // not allowed as 'failure' argument + if((MemoryOrder() == MEMORY_ORDER_RELAXED && MemoryOrder2() != MEMORY_ORDER_RELAXED) || + (MemoryOrder() != MEMORY_ORDER_SEQ_CST && MemoryOrder2() == MEMORY_ORDER_SEQ_CST)) + return 0; // failure argument shall be no stronger than the success + return CBasicTestMemOrder2Scope::ExecuteSingleTest(deviceID, context, queue); + } + virtual std::string ProgramCore() + { + std::string memoryOrderScope = MemoryOrderScope(); + std::string postfix(memoryOrderScope.empty() ? "" : "_explicit"); + return + std::string(" ")+DataType().RegularTypeName()+" expected, previous;\n" + " int successCount = 0;\n" + " oldValues[tid] = tid;\n" + " expected = tid; // force failure at the beginning\n" + " if(atomic_compare_exchange_strong"+postfix+"(&destMemory[0], &expected, oldValues[tid]"+memoryOrderScope+") || expected == tid)\n" + " oldValues[tid] = threadCount+1; //mark unexpected success with invalid value\n" + " else\n" + " {\n" + " for(int i = 0; i < "+IterationsStr()+" || successCount == 0; i++)\n" + " {\n" + " previous = expected;\n" + " if(atomic_compare_exchange_strong"+postfix+"(&destMemory[0], &expected, oldValues[tid]"+memoryOrderScope+"))\n" + " {\n" + " oldValues[tid] = expected;\n" + " successCount++;\n" + " }\n" + " else\n" + " {\n" + " if(previous == expected) // spurious failure - shouldn't occur for 'strong'\n" + " {\n" + " oldValues[tid] = threadCount; //mark fail with invalid value\n" + " break;\n" + " }\n" + " }\n" + " }\n" + " }\n"; + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + HostDataType expected = (HostDataType)StartValue(), previous; + oldValues[tid] = (HostDataType)tid; + for(int i = 0; i < Iterations(); i++) + { + previous = expected; + if(host_atomic_compare_exchange(&destMemory[0], &expected, oldValues[tid], MemoryOrder(), MemoryOrder2())) + oldValues[tid] = expected; + else + { + if(previous == expected) // shouldn't occur for 'strong' + { + oldValues[tid] = threadCount; //mark fail with invalid value + } + } + } + } + virtual bool VerifyRefs(bool &correct, cl_uint threadCount, HostDataType *refValues, HostAtomicType *finalValues) + { + correct = true; + /* We are expecting values from 0 to size-1 and initial value from atomic variable */ + /* These values must be distributed across refValues array and atomic variable finalVaue[0] */ + /* Any repeated value is treated as an error */ + std::vector tidFound(threadCount); + bool startValueFound = false; + cl_uint i; + + for(i = 0; i <= threadCount; i++) + { + cl_uint value; + if(i == threadCount) + value = (cl_uint)finalValues[0]; //additional value from atomic variable (last written) + else + value = (cl_uint)refValues[i]; + if(value == (cl_uint)StartValue()) + { + // Special initial value + if(startValueFound) + { + log_error("ERROR: Starting reference value (%u) occurred more thane once\n", (cl_uint)StartValue()); + correct = false; + return true; + } + startValueFound = true; + continue; + } + if(value >= threadCount) + { + if(value == threadCount) + log_error("ERROR: Spurious failure detected for atomic_compare_exchange_strong\n"); + log_error("ERROR: Reference value %u outside of valid range! (%u)\n", i, value); + correct = false; + return true; + } + if(tidFound[value]) + { + log_error("ERROR: Value (%u) occurred more thane once\n", value); + correct = false; + return true; + } + tidFound[value] = true; + } + return true; + } +}; + +int test_atomic_compare_exchange_strong_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestCompareStrong test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareStrong test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareStrong test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareStrong test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + if(AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestCompareStrong test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareStrong test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareStrong test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareStrong test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestCompareStrong test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareStrong test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareStrong test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareStrong test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_compare_exchange_strong(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_compare_exchange_strong_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_compare_exchange_strong_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_compare_exchange_strong_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestCompareWeak : public CBasicTestCompareStrong +{ +public: + using CBasicTestCompareStrong::StartValue; + using CBasicTestCompareStrong::MemoryOrderScope; + using CBasicTestCompareStrong::DataType; + using CBasicTestCompareStrong::Iterations; + using CBasicTestCompareStrong::IterationsStr; + CBasicTestCompareWeak(TExplicitAtomicType dataType, bool useSVM) : CBasicTestCompareStrong(dataType, useSVM) + { + } + virtual std::string ProgramCore() + { + std::string memoryOrderScope = MemoryOrderScope(); + std::string postfix(memoryOrderScope.empty() ? "" : "_explicit"); + return + std::string(" ")+DataType().RegularTypeName()+" expected , previous;\n" + " int successCount = 0;\n" + " oldValues[tid] = tid;\n" + " expected = tid; // force failure at the beginning\n" + " if(atomic_compare_exchange_weak"+postfix+"(&destMemory[0], &expected, oldValues[tid]"+memoryOrderScope+") || expected == tid)\n" + " oldValues[tid] = threadCount+1; //mark unexpected success with invalid value\n" + " else\n" + " {\n" + " for(int i = 0; i < "+IterationsStr()+" || successCount == 0; i++)\n" + " {\n" + " previous = expected;\n" + " if(atomic_compare_exchange_weak"+postfix+"(&destMemory[0], &expected, oldValues[tid]"+memoryOrderScope+"))\n" + " {\n" + " oldValues[tid] = expected;\n" + " successCount++;\n" + " }\n" + " }\n" + " }\n"; + } +}; + +int test_atomic_compare_exchange_weak_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestCompareWeak test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareWeak test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareWeak test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareWeak test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + if(AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestCompareWeak test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareWeak test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareWeak test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareWeak test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestCompareWeak test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareWeak test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareWeak test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestCompareWeak test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_compare_exchange_weak(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_compare_exchange_weak_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_compare_exchange_weak_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_compare_exchange_weak_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestFetchAdd : public CBasicTestMemOrderScope +{ +public: + using CBasicTestMemOrderScope::MemoryOrder; + using CBasicTestMemOrderScope::MemoryOrderScopeStr; + using CBasicTestMemOrderScope::StartValue; + using CBasicTestMemOrderScope::DataType; + CBasicTestFetchAdd(TExplicitAtomicType dataType, bool useSVM) : CBasicTestMemOrderScope(dataType, useSVM) + { + } + virtual std::string ProgramCore() + { + std::string memoryOrderScope = MemoryOrderScopeStr(); + std::string postfix(memoryOrderScope.empty() ? "" : "_explicit"); + return + " oldValues[tid] = atomic_fetch_add"+postfix+"(&destMemory[0], tid + 3"+memoryOrderScope+");\n"+ + " atomic_fetch_add"+postfix+"(&destMemory[0], tid + 3"+memoryOrderScope+");\n" + " atomic_fetch_add"+postfix+"(&destMemory[0], tid + 3"+memoryOrderScope+");\n" + " atomic_fetch_add"+postfix+"(&destMemory[0], (("+DataType().AddSubOperandTypeName()+")tid + 3) << (sizeof("+DataType().AddSubOperandTypeName()+")-1)*8"+memoryOrderScope+");\n"; + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + oldValues[tid] = host_atomic_fetch_add(&destMemory[0], (HostDataType)tid + 3, MemoryOrder()); + host_atomic_fetch_add(&destMemory[0], (HostDataType)tid + 3, MemoryOrder()); + host_atomic_fetch_add(&destMemory[0], (HostDataType)tid + 3, MemoryOrder()); + host_atomic_fetch_add(&destMemory[0], ((HostDataType)tid + 3) << (sizeof(HostDataType)-1)*8, MemoryOrder()); + } + virtual bool ExpectedValue(HostDataType &expected, cl_uint threadCount, HostDataType *startRefValues, cl_uint whichDestValue) + { + expected = StartValue(); + for(cl_uint i = 0; i < threadCount; i++) + expected += ((HostDataType)i+3)*3+(((HostDataType)i + 3) << (sizeof(HostDataType)-1)*8); + return true; + } +}; + +int test_atomic_fetch_add_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestFetchAdd test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAdd test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAdd test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAdd test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + if(AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestFetchAdd test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAdd test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAdd test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAdd test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestFetchAdd test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAdd test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAdd test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAdd test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_fetch_add(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_add_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_fetch_add_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_add_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestFetchSub : public CBasicTestMemOrderScope +{ +public: + using CBasicTestMemOrderScope::MemoryOrder; + using CBasicTestMemOrderScope::MemoryOrderScopeStr; + using CBasicTestMemOrderScope::StartValue; + using CBasicTestMemOrderScope::DataType; + CBasicTestFetchSub(TExplicitAtomicType dataType, bool useSVM) : CBasicTestMemOrderScope(dataType, useSVM) + { + } + virtual std::string ProgramCore() + { + std::string memoryOrderScope = MemoryOrderScopeStr(); + std::string postfix(memoryOrderScope.empty() ? "" : "_explicit"); + return + " oldValues[tid] = atomic_fetch_sub"+postfix+"(&destMemory[0], tid + 3 +((("+DataType().AddSubOperandTypeName()+")tid + 3) << (sizeof("+DataType().AddSubOperandTypeName()+")-1)*8)"+memoryOrderScope+");\n"; + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + oldValues[tid] = host_atomic_fetch_sub(&destMemory[0], (HostDataType)tid + 3+(((HostDataType)tid + 3) << (sizeof(HostDataType)-1)*8), MemoryOrder()); + } + virtual bool ExpectedValue(HostDataType &expected, cl_uint threadCount, HostDataType *startRefValues, cl_uint whichDestValue) + { + expected = StartValue(); + for(cl_uint i = 0; i < threadCount; i++) + expected -= (HostDataType)i + 3 +(((HostDataType)i + 3) << (sizeof(HostDataType)-1)*8); + return true; + } +}; + +int test_atomic_fetch_sub_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestFetchSub test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchSub test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchSub test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchSub test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + if(AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestFetchSub test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchSub test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchSub test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchSub test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestFetchSub test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchSub test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchSub test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchSub test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_fetch_sub(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_sub_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_fetch_sub_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_sub_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestFetchOr : public CBasicTestMemOrderScope +{ +public: + using CBasicTestMemOrderScope::StartValue; + using CBasicTestMemOrderScope::DataType; + using CBasicTestMemOrderScope::MemoryOrder; + using CBasicTestMemOrderScope::MemoryOrderScopeStr; + CBasicTestFetchOr(TExplicitAtomicType dataType, bool useSVM) : CBasicTestMemOrderScope(dataType, useSVM) + { + StartValue(0); + } + virtual cl_uint NumResults(cl_uint threadCount, cl_device_id deviceID) + { + cl_uint numBits = DataType().Size(deviceID) * 8; + + return (threadCount + numBits - 1) / numBits; + } + virtual std::string ProgramCore() + { + std::string memoryOrderScope = MemoryOrderScopeStr(); + std::string postfix(memoryOrderScope.empty() ? "" : "_explicit"); + return + std::string(" size_t numBits = sizeof(")+DataType().RegularTypeName()+") * 8;\n" + " int whichResult = tid / numBits;\n" + " int bitIndex = tid - (whichResult * numBits);\n" + "\n" + " oldValues[tid] = atomic_fetch_or"+postfix+"(&destMemory[whichResult], (("+DataType().RegularTypeName()+")1 << bitIndex) "+memoryOrderScope+");\n"; + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + size_t numBits = sizeof(HostDataType) * 8; + size_t whichResult = tid / numBits; + size_t bitIndex = tid - (whichResult * numBits); + + oldValues[tid] = host_atomic_fetch_or(&destMemory[whichResult], ((HostDataType)1 << bitIndex), MemoryOrder()); + } + virtual bool ExpectedValue(HostDataType &expected, cl_uint threadCount, HostDataType *startRefValues, cl_uint whichDestValue) + { + cl_uint numValues = (threadCount + (sizeof(HostDataType)*8-1)) / (sizeof(HostDataType)*8); + if(whichDestValue < numValues - 1) + { + expected = ~(HostDataType)0; + return true; + } + // Last item doesn't get or'ed on every bit, so we have to mask away + cl_uint numBits = threadCount - whichDestValue * (sizeof(HostDataType)*8); + expected = StartValue(); + for(cl_uint i = 0; i < numBits; i++) + expected |= ((HostDataType)1 << i); + return true; + } +}; + +int test_atomic_fetch_or_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestFetchOr test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOr test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOr test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOr test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + if(AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestFetchOr test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOr test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOr test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOr test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestFetchOr test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOr test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOr test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOr test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_fetch_or(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_or_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_fetch_or_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_or_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestFetchXor : public CBasicTestMemOrderScope +{ +public: + using CBasicTestMemOrderScope::StartValue; + using CBasicTestMemOrderScope::MemoryOrder; + using CBasicTestMemOrderScope::MemoryOrderScopeStr; + using CBasicTestMemOrderScope::DataType; + CBasicTestFetchXor(TExplicitAtomicType dataType, bool useSVM) : CBasicTestMemOrderScope(dataType, useSVM) + { + StartValue((HostDataType)0x2f08ab418ba0541LL); + } + virtual std::string ProgramCore() + { + std::string memoryOrderScope = MemoryOrderScopeStr(); + std::string postfix(memoryOrderScope.empty() ? "" : "_explicit"); + return + std::string(" int numBits = sizeof(")+DataType().RegularTypeName()+") * 8;\n" + " int bitIndex = (numBits-1)*(tid+1)/threadCount;\n" + "\n" + " oldValues[tid] = atomic_fetch_xor"+postfix+"(&destMemory[0], (("+DataType().RegularTypeName()+")1 << bitIndex) "+memoryOrderScope+");\n"; + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + int numBits = sizeof(HostDataType) * 8; + int bitIndex = (numBits-1)*(tid+1)/threadCount; + + oldValues[tid] = host_atomic_fetch_xor(&destMemory[0], ((HostDataType)1 << bitIndex), MemoryOrder()); + } + virtual bool ExpectedValue(HostDataType &expected, cl_uint threadCount, HostDataType *startRefValues, cl_uint whichDestValue) + { + int numBits = sizeof(HostDataType)*8; + expected = StartValue(); + for(cl_uint i = 0; i < threadCount; i++) + { + int bitIndex = (numBits-1)*(i+1)/threadCount; + expected ^= ((HostDataType)1 << bitIndex); + } + return true; + } +}; + +int test_atomic_fetch_xor_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestFetchXor test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + if(AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestFetchXor test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestFetchXor test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_fetch_xor(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_xor_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_fetch_xor_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_xor_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestFetchAnd : public CBasicTestMemOrderScope +{ +public: + using CBasicTestMemOrderScope::StartValue; + using CBasicTestMemOrderScope::DataType; + using CBasicTestMemOrderScope::MemoryOrder; + using CBasicTestMemOrderScope::MemoryOrderScopeStr; + CBasicTestFetchAnd(TExplicitAtomicType dataType, bool useSVM) : CBasicTestMemOrderScope(dataType, useSVM) + { + StartValue(~(HostDataType)0); + } + virtual cl_uint NumResults(cl_uint threadCount, cl_device_id deviceID) + { + cl_uint numBits = DataType().Size(deviceID) * 8; + + return (threadCount + numBits - 1) / numBits; + } + virtual std::string ProgramCore() + { + std::string memoryOrderScope = MemoryOrderScopeStr(); + std::string postfix(memoryOrderScope.empty() ? "" : "_explicit"); + return + std::string(" size_t numBits = sizeof(")+DataType().RegularTypeName()+") * 8;\n" + " int whichResult = tid / numBits;\n" + " int bitIndex = tid - (whichResult * numBits);\n" + "\n" + " oldValues[tid] = atomic_fetch_and"+postfix+"(&destMemory[whichResult], ~(("+DataType().RegularTypeName()+")1 << bitIndex) "+memoryOrderScope+");\n"; + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + size_t numBits = sizeof(HostDataType) * 8; + size_t whichResult = tid / numBits; + size_t bitIndex = tid - (whichResult * numBits); + + oldValues[tid] = host_atomic_fetch_and(&destMemory[whichResult], ~((HostDataType)1 << bitIndex), MemoryOrder()); + } + virtual bool ExpectedValue(HostDataType &expected, cl_uint threadCount, HostDataType *startRefValues, cl_uint whichDestValue) + { + cl_uint numValues = (threadCount + (sizeof(HostDataType)*8-1)) / (sizeof(HostDataType)*8); + if(whichDestValue < numValues - 1) + { + expected = 0; + return true; + } + // Last item doesn't get and'ed on every bit, so we have to mask away + size_t numBits = threadCount - whichDestValue * (sizeof(HostDataType)*8); + expected = StartValue(); + for(size_t i = 0; i < numBits; i++) + expected &= ~((HostDataType)1 << i); + return true; + } +}; + +int test_atomic_fetch_and_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestFetchAnd test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAnd test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAnd test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAnd test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + if(AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestFetchAnd test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAnd test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAnd test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAnd test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestFetchAnd test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAnd test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAnd test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchAnd test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_fetch_and(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_and_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_fetch_and_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_and_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestFetchOrAnd : public CBasicTestMemOrderScope +{ +public: + using CBasicTestMemOrderScope::StartValue; + using CBasicTestMemOrderScope::DataType; + using CBasicTestMemOrderScope::MemoryOrder; + using CBasicTestMemOrderScope::MemoryOrderScopeStr; + using CBasicTestMemOrderScope::Iterations; + using CBasicTestMemOrderScope::IterationsStr; + CBasicTestFetchOrAnd(TExplicitAtomicType dataType, bool useSVM) : CBasicTestMemOrderScope(dataType, useSVM) + { + StartValue(0); + } + virtual cl_uint NumResults(cl_uint threadCount, cl_device_id deviceID) + { + return 1+(threadCount-1)/(DataType().Size(deviceID)*8); + } + // each thread modifies (with OR and AND operations) and verifies + // only one bit in atomic variable + // other bits are modified by other threads but it must not affect current thread operation + virtual std::string ProgramCore() + { + std::string memoryOrderScope = MemoryOrderScopeStr(); + std::string postfix(memoryOrderScope.empty() ? "" : "_explicit"); + return + std::string(" int bits = sizeof(")+DataType().RegularTypeName()+")*8;\n"+ + " size_t valueInd = tid/bits;\n" + " "+DataType().RegularTypeName()+" value, bitMask = ("+DataType().RegularTypeName()+")1 << tid%bits;\n" + " oldValues[tid] = 0;\n" + " for(int i = 0; i < "+IterationsStr()+"; i++)\n" + " {\n" + " value = atomic_fetch_or"+postfix+"(destMemory+valueInd, bitMask"+memoryOrderScope+");\n" + " if(value & bitMask) // bit should be set to 0\n" + " oldValues[tid]++;\n" + " value = atomic_fetch_and"+postfix+"(destMemory+valueInd, ~bitMask"+memoryOrderScope+");\n" + " if(!(value & bitMask)) // bit should be set to 1\n" + " oldValues[tid]++;\n" + " }\n"; + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + int bits = sizeof(HostDataType)*8; + size_t valueInd = tid/bits; + HostDataType value, bitMask = (HostDataType)1 << tid%bits; + oldValues[tid] = 0; + for(int i = 0; i < Iterations(); i++) + { + value = host_atomic_fetch_or(destMemory+valueInd, bitMask, MemoryOrder()); + if(value & bitMask) // bit should be set to 0 + oldValues[tid]++; + value = host_atomic_fetch_and(destMemory+valueInd, ~bitMask, MemoryOrder()); + if(!(value & bitMask)) // bit should be set to 1 + oldValues[tid]++; + } + } + virtual bool ExpectedValue(HostDataType &expected, cl_uint threadCount, HostDataType *startRefValues, cl_uint whichDestValue) + { + expected = 0; + return true; + } + virtual bool VerifyRefs(bool &correct, cl_uint threadCount, HostDataType *refValues, HostAtomicType *finalValues) + { + correct = true; + for(cl_uint i = 0; i < threadCount; i++) + { + if(refValues[i] > 0) + { + log_error("Thread %d found %d mismatch(es)\n", i, (cl_uint)refValues[i]); + correct = false; + } + } + return true; + } +}; + +int test_atomic_fetch_orand_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestFetchOrAnd test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOrAnd test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOrAnd test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOrAnd test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + if(AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestFetchOrAnd test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOrAnd test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOrAnd test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOrAnd test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestFetchOrAnd test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOrAnd test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOrAnd test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchOrAnd test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_fetch_orand(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_orand_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_fetch_orand_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_orand_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestFetchXor2 : public CBasicTestMemOrderScope +{ +public: + using CBasicTestMemOrderScope::StartValue; + using CBasicTestMemOrderScope::DataType; + using CBasicTestMemOrderScope::MemoryOrder; + using CBasicTestMemOrderScope::MemoryOrderScopeStr; + using CBasicTestMemOrderScope::Iterations; + using CBasicTestMemOrderScope::IterationsStr; + CBasicTestFetchXor2(TExplicitAtomicType dataType, bool useSVM) : CBasicTestMemOrderScope(dataType, useSVM) + { + StartValue(0); + } + virtual cl_uint NumResults(cl_uint threadCount, cl_device_id deviceID) + { + return 1+(threadCount-1)/(DataType().Size(deviceID)*8); + } + // each thread modifies (with XOR operation) and verifies + // only one bit in atomic variable + // other bits are modified by other threads but it must not affect current thread operation + virtual std::string ProgramCore() + { + std::string memoryOrderScope = MemoryOrderScopeStr(); + std::string postfix(memoryOrderScope.empty() ? "" : "_explicit"); + return + std::string(" int bits = sizeof(")+DataType().RegularTypeName()+")*8;\n"+ + " size_t valueInd = tid/bits;\n" + " "+DataType().RegularTypeName()+" value, bitMask = ("+DataType().RegularTypeName()+")1 << tid%bits;\n" + " oldValues[tid] = 0;\n" + " for(int i = 0; i < "+IterationsStr()+"; i++)\n" + " {\n" + " value = atomic_fetch_xor"+postfix+"(destMemory+valueInd, bitMask"+memoryOrderScope+");\n" + " if(value & bitMask) // bit should be set to 0\n" + " oldValues[tid]++;\n" + " value = atomic_fetch_xor"+postfix+"(destMemory+valueInd, bitMask"+memoryOrderScope+");\n" + " if(!(value & bitMask)) // bit should be set to 1\n" + " oldValues[tid]++;\n" + " }\n"; + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + int bits = sizeof(HostDataType)*8; + size_t valueInd = tid/bits; + HostDataType value, bitMask = (HostDataType)1 << tid%bits; + oldValues[tid] = 0; + for(int i = 0; i < Iterations(); i++) + { + value = host_atomic_fetch_xor(destMemory+valueInd, bitMask, MemoryOrder()); + if(value & bitMask) // bit should be set to 0 + oldValues[tid]++; + value = host_atomic_fetch_xor(destMemory+valueInd, bitMask, MemoryOrder()); + if(!(value & bitMask)) // bit should be set to 1 + oldValues[tid]++; + } + } + virtual bool ExpectedValue(HostDataType &expected, cl_uint threadCount, HostDataType *startRefValues, cl_uint whichDestValue) + { + expected = 0; + return true; + } + virtual bool VerifyRefs(bool &correct, cl_uint threadCount, HostDataType *refValues, HostAtomicType *finalValues) + { + correct = true; + for(cl_uint i = 0; i < threadCount; i++) + { + if(refValues[i] > 0) + { + log_error("Thread %d found %d mismatches\n", i, (cl_uint)refValues[i]); + correct = false; + } + } + return true; + } +}; + +int test_atomic_fetch_xor2_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestFetchXor2 test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor2 test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor2 test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor2 test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + if(AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestFetchXor2 test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor2 test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor2 test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor2 test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestFetchXor2 test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor2 test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor2 test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchXor2 test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_fetch_xor2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_xor2_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_fetch_xor2_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_xor2_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestFetchMin : public CBasicTestMemOrderScope +{ +public: + using CBasicTestMemOrderScope::StartValue; + using CBasicTestMemOrderScope::DataType; + using CBasicTestMemOrderScope::MemoryOrder; + using CBasicTestMemOrderScope::MemoryOrderScopeStr; + CBasicTestFetchMin(TExplicitAtomicType dataType, bool useSVM) : CBasicTestMemOrderScope(dataType, useSVM) + { + StartValue(DataType().MaxValue()); + } + virtual std::string ProgramCore() + { + std::string memoryOrderScope = MemoryOrderScopeStr(); + std::string postfix(memoryOrderScope.empty() ? "" : "_explicit"); + return + " oldValues[tid] = atomic_fetch_min"+postfix+"(&destMemory[0], oldValues[tid] "+memoryOrderScope+");\n"; + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + oldValues[tid] = host_atomic_fetch_min(&destMemory[0], oldValues[tid], MemoryOrder()); + } + virtual bool GenerateRefs(cl_uint threadCount, HostDataType *startRefValues, MTdata d) + { + for(cl_uint i = 0; i < threadCount; i++) + { + startRefValues[i] = genrand_int32(d); + if(sizeof(HostDataType) >= 8) + startRefValues[i] |= (HostDataType)genrand_int32(d) << 16; + } + return true; + } + virtual bool ExpectedValue(HostDataType &expected, cl_uint threadCount, HostDataType *startRefValues, cl_uint whichDestValue) + { + expected = StartValue(); + for(cl_uint i = 0; i < threadCount; i++) + { + if(startRefValues[ i ] < expected) + expected = startRefValues[ i ]; + } + return true; + } +}; + +int test_atomic_fetch_min_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestFetchMin test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMin test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMin test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMin test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + if(AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestFetchMin test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMin test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMin test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMin test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestFetchMin test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMin test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMin test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMin test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_fetch_min(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_min_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_fetch_min_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_min_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestFetchMax : public CBasicTestMemOrderScope +{ +public: + using CBasicTestMemOrderScope::StartValue; + using CBasicTestMemOrderScope::DataType; + using CBasicTestMemOrderScope::MemoryOrder; + using CBasicTestMemOrderScope::MemoryOrderScopeStr; + CBasicTestFetchMax(TExplicitAtomicType dataType, bool useSVM) : CBasicTestMemOrderScope(dataType, useSVM) + { + StartValue(DataType().MinValue()); + } + virtual std::string ProgramCore() + { + std::string memoryOrderScope = MemoryOrderScopeStr(); + std::string postfix(memoryOrderScope.empty() ? "" : "_explicit"); + return + " oldValues[tid] = atomic_fetch_max"+postfix+"(&destMemory[0], oldValues[tid] "+memoryOrderScope+");\n"; + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + oldValues[tid] = host_atomic_fetch_max(&destMemory[0], oldValues[tid], MemoryOrder()); + } + virtual bool GenerateRefs(cl_uint threadCount, HostDataType *startRefValues, MTdata d) + { + for(cl_uint i = 0; i < threadCount; i++) + { + startRefValues[i] = genrand_int32(d); + if(sizeof(HostDataType) >= 8) + startRefValues[i] |= (HostDataType)genrand_int32(d) << 16; + } + return true; + } + virtual bool ExpectedValue(HostDataType &expected, cl_uint threadCount, HostDataType *startRefValues, cl_uint whichDestValue) + { + expected = StartValue(); + for(cl_uint i = 0; i < threadCount; i++) + { + if(startRefValues[ i ] > expected) + expected = startRefValues[ i ]; + } + return true; + } +}; + +int test_atomic_fetch_max_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestFetchMax test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMax test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMax test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMax test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + if(AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestFetchMax test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMax test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMax test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMax test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestFetchMax test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMax test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMax test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFetchMax test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_fetch_max(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_max_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_fetch_max_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fetch_max_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestFlag : public CBasicTestMemOrderScope +{ + static const HostDataType CRITICAL_SECTION_NOT_VISITED = 1000000000; +public: + using CBasicTestMemOrderScope::StartValue; + using CBasicTestMemOrderScope::OldValueCheck; + using CBasicTestMemOrderScope::MemoryOrder; + using CBasicTestMemOrderScope::MemoryScopeStr; + using CBasicTestMemOrderScope::MemoryOrderScopeStr; + using CBasicTestMemOrderScope::LocalMemory; + CBasicTestFlag(TExplicitAtomicType dataType, bool useSVM) : CBasicTestMemOrderScope(dataType, useSVM) + { + StartValue(0); + OldValueCheck(false); + } + virtual cl_uint NumResults(cl_uint threadCount, cl_device_id deviceID) + { + return threadCount; + } + TExplicitMemoryOrderType MemoryOrderForClear() + { + // Memory ordering for atomic_flag_clear function + // ("shall not be memory_order_acquire nor memory_order_acq_rel") + if(MemoryOrder() == MEMORY_ORDER_ACQUIRE) + return MEMORY_ORDER_RELAXED; + if (MemoryOrder() == MEMORY_ORDER_ACQ_REL) + return MEMORY_ORDER_RELEASE; + return MemoryOrder(); + } + std::string MemoryOrderScopeStrForClear() + { + std::string orderStr; + if (MemoryOrder() != MEMORY_ORDER_EMPTY) + orderStr = std::string(", ") + get_memory_order_type_name(MemoryOrderForClear()); + return orderStr + MemoryScopeStr(); + } + virtual std::string ProgramCore() + { + std::string memoryOrderScope = MemoryOrderScopeStr(); + std::string postfix(memoryOrderScope.empty() ? "" : "_explicit"); + std::string program = + " uint cnt, stop = 0;\n" + " for(cnt = 0; !stop && cnt < threadCount; cnt++) // each thread must find critical section where it is the first visitor\n" + " {\n" + " bool set = atomic_flag_test_and_set" + postfix + "(&destMemory[cnt]" + memoryOrderScope + ");\n"; + if (MemoryOrder() == MEMORY_ORDER_RELAXED || MemoryOrder() == MEMORY_ORDER_RELEASE) + program += " atomic_work_item_fence(" + + std::string(LocalMemory() ? "CLK_LOCAL_MEM_FENCE, " : "CLK_GLOBAL_MEM_FENCE, ") + + "memory_order_acquire," + + std::string(LocalMemory() ? "memory_scope_work_group" : "memory_scope_device") + + ");\n"; + + program += + " if (!set)\n" + " {\n"; + + if (LocalMemory()) + program += " uint csIndex = get_enqueued_local_size(0)*get_group_id(0)+cnt;\n"; + else + program += " uint csIndex = cnt;\n"; + + std::ostringstream csNotVisited; + csNotVisited << CRITICAL_SECTION_NOT_VISITED; + program += + " // verify that thread is the first visitor\n" + " if(oldValues[csIndex] == "+csNotVisited.str()+")\n" + " {\n" + " oldValues[csIndex] = tid; // set the winner id for this critical section\n" + " stop = 1;\n" + " }\n"; + + if (MemoryOrder() == MEMORY_ORDER_ACQUIRE || MemoryOrder() == MEMORY_ORDER_RELAXED) + program += " atomic_work_item_fence(" + + std::string(LocalMemory() ? "CLK_LOCAL_MEM_FENCE, " : "CLK_GLOBAL_MEM_FENCE, ") + + "memory_order_release," + + std::string(LocalMemory() ? "memory_scope_work_group" : "memory_scope_device") + + ");\n"; + + program += + " atomic_flag_clear" + postfix + "(&destMemory[cnt]" + MemoryOrderScopeStrForClear() + ");\n" + " }\n" + " }\n"; + return program; + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + cl_uint cnt, stop = 0; + for (cnt = 0; !stop && cnt < threadCount; cnt++) // each thread must find critical section where it is the first visitor\n" + { + if (!host_atomic_flag_test_and_set(&destMemory[cnt], MemoryOrder())) + { + cl_uint csIndex = cnt; + // verify that thread is the first visitor\n" + if (oldValues[csIndex] == CRITICAL_SECTION_NOT_VISITED) + { + oldValues[csIndex] = tid; // set the winner id for this critical section\n" + stop = 1; + } + host_atomic_flag_clear(&destMemory[cnt], MemoryOrderForClear()); + } + } + } + virtual bool ExpectedValue(HostDataType &expected, cl_uint threadCount, HostDataType *startRefValues, cl_uint whichDestValue) + { + expected = StartValue(); + return true; + } + virtual bool GenerateRefs(cl_uint threadCount, HostDataType *startRefValues, MTdata d) + { + for(cl_uint i = 0 ; i < threadCount; i++) + startRefValues[i] = CRITICAL_SECTION_NOT_VISITED; + return true; + } + virtual bool VerifyRefs(bool &correct, cl_uint threadCount, HostDataType *refValues, HostAtomicType *finalValues) + { + correct = true; + /* We are expecting unique values from 0 to threadCount-1 (each critical section must be visited) */ + /* These values must be distributed across refValues array */ + std::vector tidFound(threadCount); + cl_uint i; + + for (i = 0; i < threadCount; i++) + { + cl_uint value = (cl_uint)refValues[i]; + if (value == CRITICAL_SECTION_NOT_VISITED) + { + // Special initial value + log_error("ERROR: Critical section %u not visited\n", i); + correct = false; + return true; + } + if (value >= threadCount) + { + log_error("ERROR: Reference value %u outside of valid range! (%u)\n", i, value); + correct = false; + return true; + } + if (tidFound[value]) + { + log_error("ERROR: Value (%u) occurred more thane once\n", value); + correct = false; + return true; + } + tidFound[value] = true; + } + return true; + } +}; + +int test_atomic_flag_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestFlag test_flag(TYPE_ATOMIC_FLAG, useSVM); + EXECUTE_TEST(error, test_flag.Execute(deviceID, context, queue, num_elements)); + return error; +} + +int test_atomic_flag(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_flag_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_flag_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_flag_generic(deviceID, context, queue, num_elements, true); +} + +template +class CBasicTestFence : public CBasicTestMemOrderScope +{ + struct TestDefinition { + bool op1IsFence; + TExplicitMemoryOrderType op1MemOrder; + bool op2IsFence; + TExplicitMemoryOrderType op2MemOrder; + }; +public: + using CBasicTestMemOrderScope::StartValue; + using CBasicTestMemOrderScope::OldValueCheck; + using CBasicTestMemOrderScope::MemoryOrder; + using CBasicTestMemOrderScope::MemoryScope; + using CBasicTestMemOrderScope::MemoryScopeStr; + using CBasicTestMemOrderScope::DeclaredInProgram; + using CBasicTestMemOrderScope::UsedInFunction; + using CBasicTestMemOrderScope::DataType; + using CBasicTestMemOrderScope::CurrentGroupSize; + using CBasicTestMemOrderScope::UseSVM; + using CBasicTestMemOrderScope::LocalMemory; + using CBasicTestMemOrderScope::LocalRefValues; + CBasicTestFence(TExplicitAtomicType dataType, bool useSVM) : CBasicTestMemOrderScope(dataType, useSVM) + { + StartValue(0); + OldValueCheck(false); + } + virtual cl_uint NumResults(cl_uint threadCount, cl_device_id deviceID) + { + return threadCount; + } + virtual cl_uint NumNonAtomicVariablesPerThread() + { + if (MemoryOrder() == MEMORY_ORDER_SEQ_CST) + return 1; + if (LocalMemory()) + return 32 * 1024 / 8 / CurrentGroupSize() - 1; //32KB of local memory required by spec + return 256; + } + virtual std::string SingleTestName() + { + std::string testName; + if (MemoryOrder() == MEMORY_ORDER_SEQ_CST) + testName += "seq_cst fence, "; + else + testName += std::string(get_memory_order_type_name(_subCase.op1MemOrder)).substr(sizeof("memory_order")) + + (_subCase.op1IsFence ? " fence" : " atomic") + " synchronizes-with " + + std::string(get_memory_order_type_name(_subCase.op2MemOrder)).substr(sizeof("memory_order")) + + (_subCase.op2IsFence ? " fence" : " atomic") + ", "; + testName += CBasicTest::SingleTestName(); + testName += std::string(", ") + std::string(get_memory_scope_type_name(MemoryScope())).substr(sizeof("memory")); + return testName; + } + virtual bool SVMDataBufferAllSVMConsistent() + { + return MemoryScope() == MEMORY_SCOPE_ALL_SVM_DEVICES; + } + virtual int ExecuteForEachParameterSet(cl_device_id deviceID, cl_context context, cl_command_queue queue) + { + int error = 0; + // execute 3 (maximum) sub cases for each memory order + for (_subCaseId = 0; _subCaseId < 3; _subCaseId++) + { + EXECUTE_TEST(error, (CBasicTestMemOrderScope::ExecuteForEachParameterSet(deviceID, context, queue))); + } + return error; + } + virtual int ExecuteSingleTest(cl_device_id deviceID, cl_context context, cl_command_queue queue) + { + if(DeclaredInProgram() || UsedInFunction()) + return 0; //skip test - not applicable - no overloaded fence functions for different address spaces + if(MemoryOrder() == MEMORY_ORDER_EMPTY || + MemoryScope() == MEMORY_SCOPE_EMPTY) // empty 'scope' not required since opencl20-openclc-rev15 + return 0; //skip test - not applicable + if((UseSVM() || gHost) + && LocalMemory()) + return 0; // skip test - not applicable for SVM and local memory + struct TestDefinition acqTests[] = { + // {op1IsFence, op1MemOrder, op2IsFence, op2MemOrder} + { false, MEMORY_ORDER_RELEASE, true, MEMORY_ORDER_ACQUIRE }, + { true, MEMORY_ORDER_RELEASE, true, MEMORY_ORDER_ACQUIRE }, + { true, MEMORY_ORDER_ACQ_REL, true, MEMORY_ORDER_ACQUIRE } + }; + struct TestDefinition relTests[] = { + { true, MEMORY_ORDER_RELEASE, false, MEMORY_ORDER_ACQUIRE }, + { true, MEMORY_ORDER_RELEASE, true, MEMORY_ORDER_ACQ_REL } + }; + struct TestDefinition arTests[] = { + { false, MEMORY_ORDER_RELEASE, true, MEMORY_ORDER_ACQ_REL }, + { true, MEMORY_ORDER_ACQ_REL, false, MEMORY_ORDER_ACQUIRE }, + { true, MEMORY_ORDER_ACQ_REL, true, MEMORY_ORDER_ACQ_REL } + }; + switch (MemoryOrder()) + { + case MEMORY_ORDER_ACQUIRE: + if (_subCaseId >= sizeof(acqTests) / sizeof(struct TestDefinition)) + return 0; + _subCase = acqTests[_subCaseId]; + break; + case MEMORY_ORDER_RELEASE: + if (_subCaseId >= sizeof(relTests) / sizeof(struct TestDefinition)) + return 0; + _subCase = relTests[_subCaseId]; + break; + case MEMORY_ORDER_ACQ_REL: + if (_subCaseId >= sizeof(arTests) / sizeof(struct TestDefinition)) + return 0; + _subCase = arTests[_subCaseId]; + break; + case MEMORY_ORDER_SEQ_CST: + if (_subCaseId != 0) // one special case only + return 0; + break; + default: + return 0; + } + LocalRefValues(LocalMemory()); + return CBasicTestMemOrderScope::ExecuteSingleTest(deviceID, context, queue); + } + virtual std::string ProgramHeader(cl_uint maxNumDestItems) + { + std::string header; + if(gOldAPI) + { + if(MemoryScope() == MEMORY_SCOPE_EMPTY) + { + header += "#define atomic_work_item_fence(x,y) mem_fence(x)\n"; + } + else + { + header += "#define atomic_work_item_fence(x,y,z) mem_fence(x)\n"; + } + } + return header+CBasicTestMemOrderScope::ProgramHeader(maxNumDestItems); + } + virtual std::string ProgramCore() + { + std::ostringstream naValues; + naValues << NumNonAtomicVariablesPerThread(); + std::string program, fenceType, nonAtomic; + if (LocalMemory()) + { + program = " size_t myId = get_local_id(0), hisId = get_local_size(0)-1-myId;\n"; + fenceType = "CLK_LOCAL_MEM_FENCE"; + nonAtomic = "localValues"; + } + else + { + program = " size_t myId = tid, hisId = threadCount-1-tid;\n"; + fenceType = "CLK_GLOBAL_MEM_FENCE"; + nonAtomic = "oldValues"; + } + if (MemoryOrder() == MEMORY_ORDER_SEQ_CST) + { + // All threads are divided into pairs. + // Each thread has its own atomic variable and performs the following actions: + // - increments its own variable + // - performs fence operation to propagate its value and to see value from other thread + // - reads value from other thread's variable + // - repeats the above steps when both values are the same (and less than 1000000) + // - stores the last value read from other thread (in additional variable) + // At the end of execution at least one thread should know the last value from other thread + program += std::string("") + + " " + DataType().RegularTypeName() + " myValue = 0, hisValue; \n" + " do {\n" + " myValue++;\n" + " atomic_store_explicit(&destMemory[myId], myValue, memory_order_relaxed" + MemoryScopeStr() + ");\n" + " atomic_work_item_fence(" + fenceType + ", memory_order_seq_cst" + MemoryScopeStr() + "); \n" + " hisValue = atomic_load_explicit(&destMemory[hisId], memory_order_relaxed" + MemoryScopeStr() + ");\n" + " } while(myValue == hisValue && myValue < 1000000);\n" + " " + nonAtomic + "[myId] = hisValue; \n"; + } + else + { + // Each thread modifies one of its non-atomic variables, increments value of its atomic variable + // and reads values from another thread in typical synchronizes-with scenario with: + // - non-atomic variable (at index A) modification (value change from 0 to A) + // - release operation (additional fence or within atomic) + atomic variable modification (value A) + // - atomic variable read (value B) + acquire operation (additional fence or within atomic) + // - non-atomic variable (at index B) read (value C) + // Each thread verifies dependency between atomic and non-atomic value read from another thread + // The following condition must be true: B == C + program += std::string("") + + " " + DataType().RegularTypeName() + " myValue = 0, hisAtomicValue, hisValue; \n" + " do {\n" + " myValue++;\n" + " " + nonAtomic + "[myId*" + naValues.str() +"+myValue] = myValue;\n"; + if (_subCase.op1IsFence) + program += std::string("") + + " atomic_work_item_fence(" + fenceType + ", " + get_memory_order_type_name(_subCase.op1MemOrder) + MemoryScopeStr() + "); \n" + " atomic_store_explicit(&destMemory[myId], myValue, memory_order_relaxed" + MemoryScopeStr() + ");\n"; + else + program += std::string("") + + " atomic_store_explicit(&destMemory[myId], myValue, " + get_memory_order_type_name(_subCase.op1MemOrder) + MemoryScopeStr() + ");\n"; + if (_subCase.op2IsFence) + program += std::string("") + + " hisAtomicValue = atomic_load_explicit(&destMemory[hisId], memory_order_relaxed" + MemoryScopeStr() + ");\n" + " atomic_work_item_fence(" + fenceType + ", " + get_memory_order_type_name(_subCase.op2MemOrder) + MemoryScopeStr() + "); \n"; + else + program += std::string("") + + " hisAtomicValue = atomic_load_explicit(&destMemory[hisId], " + get_memory_order_type_name(_subCase.op2MemOrder) + MemoryScopeStr() + ");\n"; + program += + " hisValue = " + nonAtomic + "[hisId*" + naValues.str() + "+hisAtomicValue]; \n"; + if (LocalMemory()) + program += " hisId = (hisId+1)%get_local_size(0);\n"; + else + program += " hisId = (hisId+1)%threadCount;\n"; + program += + " } while(hisAtomicValue == hisValue && myValue < "+naValues.str()+"-1);\n" + " if(hisAtomicValue != hisValue)\n" + " { // fail\n" + " atomic_store(&destMemory[myId], myValue-1);\n"; + if (LocalMemory()) + program += " hisId = (hisId+get_local_size(0)-1)%get_local_size(0);\n"; + else + program += " hisId = (hisId+threadCount-1)%threadCount;\n"; + program += + " if(myValue+1 < " + naValues.str() + ")\n" + " " + nonAtomic + "[myId*" + naValues.str() + "+myValue+1] = hisId;\n" + " if(myValue+2 < " + naValues.str() + ")\n" + " " + nonAtomic + "[myId*" + naValues.str() + "+myValue+2] = hisAtomicValue;\n" + " if(myValue+3 < " + naValues.str() + ")\n" + " " + nonAtomic + "[myId*" + naValues.str() + "+myValue+3] = hisValue;\n"; + if (gDebug) + { + program += + " printf(\"WI %d: atomic value (%d) at index %d is different than non-atomic value (%d)\\n\", tid, hisAtomicValue, hisId, hisValue);\n"; + } + program += + " }\n"; + } + return program; + } + virtual void HostFunction(cl_uint tid, cl_uint threadCount, volatile HostAtomicType *destMemory, HostDataType *oldValues) + { + size_t myId = tid, hisId = threadCount - 1 - tid; + if (MemoryOrder() == MEMORY_ORDER_SEQ_CST) + { + HostDataType myValue = 0, hisValue; + // CPU thread typically starts faster - wait for GPU thread + myValue++; + host_atomic_store(&destMemory[myId], myValue, MEMORY_ORDER_SEQ_CST); + while (host_atomic_load(&destMemory[hisId], MEMORY_ORDER_SEQ_CST) == 0); + do { + myValue++; + host_atomic_store(&destMemory[myId], myValue, MEMORY_ORDER_RELAXED); + host_atomic_thread_fence(MemoryOrder()); + hisValue = host_atomic_load(&destMemory[hisId], MEMORY_ORDER_RELAXED); + } while (myValue == hisValue && hisValue < 1000000); + oldValues[tid] = hisValue; + } + else + { + HostDataType myValue = 0, hisAtomicValue, hisValue; + do { + myValue++; + oldValues[myId*NumNonAtomicVariablesPerThread()+myValue] = myValue; + if (_subCase.op1IsFence) + { + host_atomic_thread_fence(_subCase.op1MemOrder); + host_atomic_store(&destMemory[myId], myValue, MEMORY_ORDER_RELAXED); + } + else + host_atomic_store(&destMemory[myId], myValue, _subCase.op1MemOrder); + if (_subCase.op2IsFence) + { + hisAtomicValue = host_atomic_load(&destMemory[hisId], MEMORY_ORDER_RELAXED); + host_atomic_thread_fence(_subCase.op2MemOrder); + } + else + hisAtomicValue = host_atomic_load(&destMemory[hisId], _subCase.op2MemOrder); + hisValue = oldValues[hisId*NumNonAtomicVariablesPerThread() + hisAtomicValue]; + hisId = (hisId + 1) % threadCount; + } while(hisAtomicValue == hisValue && myValue < (HostDataType)NumNonAtomicVariablesPerThread()-1); + if(hisAtomicValue != hisValue) + { // fail + host_atomic_store(&destMemory[myId], myValue-1, MEMORY_ORDER_SEQ_CST); + if (gDebug) + { + hisId = (hisId + threadCount - 1) % threadCount; + printf("WI %d: atomic value (%d) at index %d is different than non-atomic value (%d)\n", tid, hisAtomicValue, hisId, hisValue); + } + } + } + } + virtual bool GenerateRefs(cl_uint threadCount, HostDataType *startRefValues, MTdata d) + { + for(cl_uint i = 0 ; i < threadCount*NumNonAtomicVariablesPerThread(); i++) + startRefValues[i] = 0; + return true; + } + virtual bool VerifyRefs(bool &correct, cl_uint threadCount, HostDataType *refValues, HostAtomicType *finalValues) + { + correct = true; + cl_uint workSize = LocalMemory() ? CurrentGroupSize() : threadCount; + for(cl_uint workOffset = 0; workOffset < threadCount; workOffset+= workSize) + { + if(workOffset+workSize > threadCount) + // last workgroup (host threads) + workSize = threadCount-workOffset; + for(cl_uint i = 0 ; i < workSize && workOffset+i < threadCount; i++) + { + HostAtomicType myValue = finalValues[workOffset + i]; + if (MemoryOrder() == MEMORY_ORDER_SEQ_CST) + { + HostDataType hisValue = refValues[workOffset + i]; + if (myValue == hisValue) + { + // a draw - both threads should reach final value 1000000 + if (myValue != 1000000) + { + log_error("ERROR: Invalid reference value #%u (%d instead of 1000000)\n", workOffset + i, myValue); + correct = false; + return true; + } + } + else + { + //slower thread (in total order of seq_cst operations) must know last value written by faster thread + HostAtomicType hisRealValue = finalValues[workOffset + workSize - 1 - i]; + HostDataType myValueReadByHim = refValues[workOffset + workSize - 1 - i]; + + // who is the winner? - thread with lower private counter value + if (myValue == hisRealValue) // forbidden result - fence doesn't work + { + log_error("ERROR: Atomic counter values #%u and #%u are the same (%u)\n", workOffset + i, workOffset + workSize - 1 - i, myValue); + log_error("ERROR: Both threads have outdated values read from another thread (%u and %u)\n", hisValue, myValueReadByHim); + correct = false; + return true; + } + if (myValue > hisRealValue) // I'm slower + { + if (hisRealValue != hisValue) + { + log_error("ERROR: Invalid reference value #%u (%d instead of %d)\n", workOffset + i, hisValue, hisRealValue); + log_error("ERROR: Slower thread #%u should know value written by faster thread #%u\n", workOffset + i, workOffset + workSize - 1 - i); + correct = false; + return true; + } + } + else // I'm faster + { + if (myValueReadByHim != myValue) + { + log_error("ERROR: Invalid reference value #%u (%d instead of %d)\n", workOffset + workSize - 1 - i, myValueReadByHim, myValue); + log_error("ERROR: Slower thread #%u should know value written by faster thread #%u\n", workOffset + workSize - 1 - i, workOffset + i); + correct = false; + return true; + } + } + } + } + else + { + if (myValue != NumNonAtomicVariablesPerThread()-1) + { + log_error("ERROR: Invalid atomic value #%u (%d instead of %d)\n", workOffset + i, myValue, NumNonAtomicVariablesPerThread()-1); + log_error("ERROR: Thread #%u observed invalid values in other thread's variables\n", workOffset + i, myValue); + correct = false; + return true; + } + } + } + } + return true; + } +private: + int _subCaseId; + struct TestDefinition _subCase; +}; + +int test_atomic_fence_generic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, bool useSVM) +{ + int error = 0; + CBasicTestFence test_int(TYPE_ATOMIC_INT, useSVM); + EXECUTE_TEST(error, test_int.Execute(deviceID, context, queue, num_elements)); + CBasicTestFence test_uint(TYPE_ATOMIC_UINT, useSVM); + EXECUTE_TEST(error, test_uint.Execute(deviceID, context, queue, num_elements)); + CBasicTestFence test_long(TYPE_ATOMIC_LONG, useSVM); + EXECUTE_TEST(error, test_long.Execute(deviceID, context, queue, num_elements)); + CBasicTestFence test_ulong(TYPE_ATOMIC_ULONG, useSVM); + EXECUTE_TEST(error, test_ulong.Execute(deviceID, context, queue, num_elements)); + if (AtomicTypeInfo(TYPE_ATOMIC_SIZE_T).Size(deviceID) == 4) + { + CBasicTestFence test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFence test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFence test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFence test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + else + { + CBasicTestFence test_intptr_t(TYPE_ATOMIC_INTPTR_T, useSVM); + EXECUTE_TEST(error, test_intptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFence test_uintptr_t(TYPE_ATOMIC_UINTPTR_T, useSVM); + EXECUTE_TEST(error, test_uintptr_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFence test_size_t(TYPE_ATOMIC_SIZE_T, useSVM); + EXECUTE_TEST(error, test_size_t.Execute(deviceID, context, queue, num_elements)); + CBasicTestFence test_ptrdiff_t(TYPE_ATOMIC_PTRDIFF_T, useSVM); + EXECUTE_TEST(error, test_ptrdiff_t.Execute(deviceID, context, queue, num_elements)); + } + return error; +} + +int test_atomic_fence(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fence_generic(deviceID, context, queue, num_elements, false); +} + +int test_atomic_fence_svm(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_atomic_fence_generic(deviceID, context, queue, num_elements, true); +} diff --git a/test_conformance/clcpp/CMakeLists.txt b/test_conformance/clcpp/CMakeLists.txt new file mode 100644 index 00000000..04484e7a --- /dev/null +++ b/test_conformance/clcpp/CMakeLists.txt @@ -0,0 +1,21 @@ +add_subdirectory(address_spaces) +add_subdirectory(api) +add_subdirectory(atomics) +add_subdirectory(attributes) +add_subdirectory(common_funcs) +add_subdirectory(convert) +add_subdirectory(device_queue) +add_subdirectory(geometric_funcs) +add_subdirectory(images) +add_subdirectory(integer_funcs) +add_subdirectory(math_funcs) +add_subdirectory(pipes) +add_subdirectory(program_scope_ctors_dtors) +add_subdirectory(reinterpret) +add_subdirectory(relational_funcs) +add_subdirectory(spec_constants) +add_subdirectory(subgroups) +add_subdirectory(synchronization) +add_subdirectory(vload_vstore) +add_subdirectory(workgroups) +add_subdirectory(workitems) diff --git a/test_conformance/clcpp/address_spaces/CMakeLists.txt b/test_conformance/clcpp/address_spaces/CMakeLists.txt new file mode 100644 index 00000000..be369fc5 --- /dev/null +++ b/test_conformance/clcpp/address_spaces/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_ADDRESS_SPACES) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/address_spaces/common.hpp b/test_conformance/clcpp/address_spaces/common.hpp new file mode 100644 index 00000000..47b78ea9 --- /dev/null +++ b/test_conformance/clcpp/address_spaces/common.hpp @@ -0,0 +1,203 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_ADDRESS_SPACES_COMMON_HPP +#define TEST_CONFORMANCE_CLCPP_ADDRESS_SPACES_COMMON_HPP + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#define RUN_ADDRESS_SPACES_TEST_MACRO(TEST_CLASS) \ + last_error = run_address_spaces_test( \ + device, context, queue, n_elems, TEST_CLASS \ + ); \ + CHECK_ERROR(last_error) \ + error |= last_error; + +// This is a base class for address spaces tests. +template +struct address_spaces_test : public detail::base_func_type +{ + // output buffer type + typedef T type; + + virtual ~address_spaces_test() {}; + // Returns test name + virtual std::string str() = 0; + // Returns OpenCL program source + virtual std::string generate_program() = 0; + // Returns kernel names IN ORDER + virtual std::vector get_kernel_names() + { + // Typical case, that is, only one kernel + return { this->get_kernel_name() }; + } + + // Return value that is expected to be in output_buffer[i] + virtual T operator()(size_t i, size_t work_group_size) = 0; + + // If local size has to be set in clEnqueueNDRangeKernel() + // this should return true; otherwise - false; + virtual bool set_local_size() + { + return false; + } + + // Calculates maximal work-group size (one dim) + virtual size_t get_max_local_size(const std::vector& kernels, + cl_device_id device, + size_t work_group_size, // default work-group size + cl_int& error) + { + size_t wg_size = work_group_size; + for(auto&k : kernels) + { + size_t max_wg_size; + error = clGetKernelWorkGroupInfo(k, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &max_wg_size, NULL); + RETURN_ON_CL_ERROR(error, "clGetKernelWorkGroupInfo") + wg_size = (std::min)(max_wg_size, wg_size); + } + return wg_size; + } + + // This covers typical case: each kernel is executed once, every kernel + // has only one argument which is output buffer + virtual cl_int execute(const std::vector& kernels, + cl_mem& output_buffer, + cl_command_queue& queue, + size_t work_size, + size_t work_group_size) + { + cl_int err; + for(auto& k : kernels) + { + err = clSetKernelArg(k, 0, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel( + queue, k, 1, + NULL, &work_size, this->set_local_size() ? &work_group_size : NULL, + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + } + return err; + } +}; + +template +int run_address_spaces_test(cl_device_id device, cl_context context, cl_command_queue queue, size_t count, address_spaces_test op) +{ + cl_mem buffers[1]; + cl_program program; + std::vector kernels; + size_t wg_size; + size_t work_size[1]; + cl_int err; + + typedef typename address_spaces_test::type TYPE; + + // Don't run test for unsupported types + if(!(type_supported(device))) + { + return CL_SUCCESS; + } + + std::string code_str = op.generate_program(); + std::vector kernel_names = op.get_kernel_names(); + if(kernel_names.empty()) + { + RETURN_ON_ERROR_MSG(-1, "No kernel to run"); + } + kernels.resize(kernel_names.size()); +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &(kernels[0]), code_str, kernel_names[0]); + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &(kernels[0]), code_str, kernel_names[0], "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) + for(size_t i = 1; i < kernels.size(); i++) + { + kernels[i] = clCreateKernel(program, kernel_names[i].c_str(), &err); + RETURN_ON_CL_ERROR(err, "clCreateKernel"); + } +#else + err = create_opencl_kernel(context, &program, &(kernels[0]), code_str, kernel_names[0]); + RETURN_ON_ERROR(err) + for(size_t i = 1; i < kernels.size(); i++) + { + kernels[i] = clCreateKernel(program, kernel_names[i].c_str(), &err); + RETURN_ON_CL_ERROR(err, "clCreateKernel"); + } +#endif + + // Find the max possible wg size for among all the kernels + wg_size = op.get_max_local_size(kernels, device, 1024, err); + RETURN_ON_ERROR(err); + + work_size[0] = count; + if(op.set_local_size()) + { + size_t wg_number = static_cast( + std::ceil(static_cast(count) / wg_size) + ); + work_size[0] = wg_number * wg_size; + } + + // output on host + std::vector output = generate_output(work_size[0], 9999); + + // output buffer + buffers[0] = clCreateBuffer + (context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(TYPE) * output.size(), NULL, &err + ); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + // Execute test + err = op.execute(kernels, buffers[0], queue, work_size[0], wg_size); + RETURN_ON_ERROR(err) + + err = clEnqueueReadBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(TYPE) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + for(size_t i = 0; i < output.size(); i++) + { + TYPE v = op(i, wg_size); + if(!(are_equal(v, output[i], detail::make_value(0), op))) + { + RETURN_ON_ERROR_MSG(-1, + "test_%s(%s) failed. Expected: %s, got: %s", op.str().c_str(), type_name().c_str(), + format_value(v).c_str(), format_value(output[i]).c_str() + ); + } + } + log_info("test_%s(%s) passed\n", op.str().c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + for(auto& k : kernels) + clReleaseKernel(k); + clReleaseProgram(program); + return err; +} + +#endif // TEST_CONFORMANCE_CLCPP_ADDRESS_SPACES_COMMON_HPP diff --git a/test_conformance/clcpp/address_spaces/main.cpp b/test_conformance/clcpp/address_spaces/main.cpp new file mode 100644 index 00000000..88ea3930 --- /dev/null +++ b/test_conformance/clcpp/address_spaces/main.cpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "test_pointer_types.hpp" +#include "test_storage_types.hpp" + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/address_spaces/test_pointer_types.hpp b/test_conformance/clcpp/address_spaces/test_pointer_types.hpp new file mode 100644 index 00000000..edc50b6f --- /dev/null +++ b/test_conformance/clcpp/address_spaces/test_pointer_types.hpp @@ -0,0 +1,411 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_ADDRESS_SPACES_TEST_POINTER_TYPES_HPP +#define TEST_CONFORMANCE_CLCPP_ADDRESS_SPACES_TEST_POINTER_TYPES_HPP + +#include + +#include "common.hpp" + +// ---------------------------- +// ---------- PRIVATE +// ---------------------------- + +template +struct private_pointer_test : public address_spaces_test +{ + std::string str() + { + return "private_pointer"; + } + + T operator()(size_t i, size_t work_group_size) + { + typedef typename scalar_type::type SCALAR; + (void) work_group_size; + return detail::make_value(static_cast(i)); + } + + // Each work-item writes its global id to output[work-item-global-id] + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return + "__kernel void " + this->get_kernel_name() + "(global " + type_name() + " *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = (" + type_name() + ")(gid);\n" + "}\n"; + + #else + return + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void " + this->get_kernel_name() + "(global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " typedef " + type_name() + " TYPE;\n" + " TYPE v = TYPE(gid);\n" + " private_ptr v_ptr1(dynamic_asptr_cast>(&v));\n" + " private_ptr v_ptr2(v_ptr1);\n" + " TYPE a[] = { TYPE(0), TYPE(1) };\n" + " private_ptr a_ptr = dynamic_asptr_cast>(a);\n" + " a_ptr++;\n" + " TYPE * a_ptr2 = a_ptr.get();\n" + " *a_ptr2 = *v_ptr2;\n" + " output[gid] = a[1];\n" + "}\n"; + #endif + } +}; + +AUTO_TEST_CASE(test_private_pointer) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // private pointer + RUN_ADDRESS_SPACES_TEST_MACRO(private_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(private_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(private_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(private_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(private_pointer_test()); + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +// ---------------------------- +// ---------- LOCAL +// ---------------------------- + +template +struct local_pointer_test : public address_spaces_test +{ + std::string str() + { + return "local_pointer"; + } + + T operator()(size_t i, size_t work_group_size) + { + typedef typename scalar_type::type SCALAR; + size_t r = i / work_group_size; + return detail::make_value(static_cast(r)); + } + + bool set_local_size() + { + return true; + } + + size_t get_max_local_size(const std::vector& kernels, + cl_device_id device, + size_t work_group_size, // default work-group size + cl_int& error) + { + // Set size of the local memory, we need to to this to correctly calculate + // max possible work-group size. + // Additionally this already set 2nd argument of the test kernel, so we don't + // have to modify execute() method. + error = clSetKernelArg(kernels[0], 1, sizeof(cl_uint), NULL); + RETURN_ON_CL_ERROR(error, "clSetKernelArg"); + + size_t wg_size; + error = clGetKernelWorkGroupInfo( + kernels[0], device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &wg_size, NULL + ); + RETURN_ON_CL_ERROR(error, "clGetKernelWorkGroupInfo") + wg_size = wg_size <= work_group_size ? wg_size : work_group_size; + return wg_size; + } + + // Every work-item writes id of its work-group to output[work-item-global-id] + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return + "__kernel void " + this->get_kernel_name() + "(global " + type_name() + " *output, " + "local uint * local_mem_ptr)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = (" + type_name() + ")(get_group_id(0));\n" + "}\n"; + + #else + return + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void " + this->get_kernel_name() + "(global_ptr<" + type_name() + "[]> output, " + "local_ptr local_mem_ptr)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " typedef " + type_name() + " TYPE;\n" + // 1st work-item in work-group writes get_group_id() to var + " local var;\n" + " local_ptr var_ptr = var.ptr();\n" + " if(lid == 0) { *var_ptr = get_group_id(0); }\n" + " work_group_barrier(mem_fence::local);\n" + // last work-item in work-group writes var to 1st element of local_mem + " local_ptr local_mem_ptr2(local_mem_ptr);\n" + " auto local_mem_ptr3 = local_mem_ptr2.release();\n" + " if(lid == (get_local_size(0) - 1)) { *(local_mem_ptr3) = var; }\n" + " work_group_barrier(mem_fence::local);\n" + // each work-item in work-group writes local_mem_ptr[0] to output[work-item-global-id] + " output[gid] = local_mem_ptr[0];\n" + "}\n"; + #endif + } +}; + +AUTO_TEST_CASE(test_local_pointer) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // local pointer + RUN_ADDRESS_SPACES_TEST_MACRO(local_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(local_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(local_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(local_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(local_pointer_test()); + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +// ---------------------------- +// ---------- GLOBAL +// ---------------------------- + +template +struct global_pointer_test : public address_spaces_test +{ + std::string str() + { + return "global_pointer"; + } + + T operator()(size_t i, size_t work_group_size) + { + typedef typename scalar_type::type SCALAR; + (void) work_group_size; + return detail::make_value(static_cast(i)); + } + + // Each work-item writes its global id to output[work-item-global-id] + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return + "__kernel void " + this->get_kernel_name() + "(global " + type_name() + " *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = (" + type_name() + ")(gid);\n" + "}\n"; + + #else + return + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "typedef " + type_name() + " TYPE;\n" + "void set_to_gid(global_ptr ptr)\n" + "{\n" + " *ptr = TYPE(get_global_id(0));" + "}\n" + "__kernel void " + this->get_kernel_name() + "(global_ptr output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " auto ptr = output.get();\n" + " global_ptr ptr2(ptr);\n" + " ptr2 += ptrdiff_t(gid);\n" + " set_to_gid(ptr2);\n" + "}\n"; + #endif + } +}; + +AUTO_TEST_CASE(test_global_pointer) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // global pointer + RUN_ADDRESS_SPACES_TEST_MACRO(global_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(global_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(global_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(global_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(global_pointer_test()); + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +// ---------------------------- +// ---------- CONSTANT +// ---------------------------- + +template +struct constant_pointer_test : public address_spaces_test +{ + // m_test_value is just a random value we use in this test. + constant_pointer_test() : m_test_value(0xdeaddeadU) + { + + } + + std::string str() + { + return "constant_pointer"; + } + + T operator()(size_t i, size_t work_group_size) + { + typedef typename scalar_type::type SCALAR; + (void) work_group_size; + return detail::make_value(static_cast(m_test_value)); + } + + // Each work-item writes m_test_value to output[work-item-global-id] + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return + "__kernel void " + this->get_kernel_name() + "(global " + type_name() + " *output, " + "constant uint * const_ptr)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = (" + type_name() + ")(const_ptr[0]);\n" + "}\n"; + + #else + return + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "typedef " + type_name() + " TYPE;\n" + "__kernel void " + this->get_kernel_name() + "(global_ptr output, " + "constant_ptr const_ptr)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " constant_ptr const_ptr2 = const_ptr;\n" + " auto const_ptr3 = const_ptr2.get();\n" + " output[gid] = *const_ptr3;\n" + "}\n"; + #endif + } + + // execute() method needs to be modified, to create additional buffer + // and set it in 2nd arg (constant_ptr const_ptr) + cl_int execute(const std::vector& kernels, + cl_mem& output_buffer, + cl_command_queue& queue, + size_t work_size, + size_t work_group_size) + { + cl_int err; + + // Get context from queue + cl_context context; + err = clGetCommandQueueInfo(queue, CL_QUEUE_CONTEXT, sizeof(cl_context), &context, NULL); + RETURN_ON_CL_ERROR(err, "clGetCommandQueueInfo"); + + // Create constant buffer + auto const_buff = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_ONLY), sizeof(cl_uint), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + // Write m_test_value to const_buff + err = clEnqueueWriteBuffer( + queue, const_buff, CL_TRUE, 0, sizeof(cl_uint), + static_cast(&m_test_value), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernels[0], 0, sizeof(output_buffer), &output_buffer); + err |= clSetKernelArg(kernels[0], 1, sizeof(const_buff), &const_buff); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel( + queue, kernels[0], 1, NULL, &work_size, this->set_local_size() ? &work_group_size : NULL, 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clFinish(queue); + RETURN_ON_CL_ERROR(err, "clFinish"); + + err = clReleaseMemObject(const_buff); + RETURN_ON_CL_ERROR(err, "clReleaseMemObject"); + return err; + } + +private: + cl_uint m_test_value; +}; + +AUTO_TEST_CASE(test_constant_pointer) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // constant pointer + RUN_ADDRESS_SPACES_TEST_MACRO(constant_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(constant_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(constant_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(constant_pointer_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(constant_pointer_test()); + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_ADDRESS_SPACES_TEST_POINTER_TYPES_HPP diff --git a/test_conformance/clcpp/address_spaces/test_storage_types.hpp b/test_conformance/clcpp/address_spaces/test_storage_types.hpp new file mode 100644 index 00000000..e47f9523 --- /dev/null +++ b/test_conformance/clcpp/address_spaces/test_storage_types.hpp @@ -0,0 +1,418 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_ADDRESS_SPACES_TEST_STORAGE_TYPES_HPP +#define TEST_CONFORMANCE_CLCPP_ADDRESS_SPACES_TEST_STORAGE_TYPES_HPP + +#include + +#include "common.hpp" + +// ---------------------------- +// ---------- PRIVATE +// ---------------------------- + +template +struct private_storage_test : public address_spaces_test +{ + std::string str() + { + return "private_storage"; + } + + T operator()(size_t i, size_t work_group_size) + { + typedef typename scalar_type::type SCALAR; + (void) work_group_size; + return detail::make_value(static_cast(i)); + } + + // Each work-item writes its global id to output[work-item-global-id] + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return + "__kernel void " + this->get_kernel_name() + "(global " + type_name() + " *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = (" + type_name() + ")(gid);\n" + "}\n"; + + #else + return + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void " + this->get_kernel_name() + "(global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " typedef " + type_name() + " TYPE;\n" + " priv v = { TYPE(gid) };\n" + " const TYPE *v_ptr1 = &v;\n" + " private_ptr v_ptr2 = v.ptr();\n" + " TYPE v2 = *v_ptr2;\n" + " priv> a;\n" + " *(a.begin()) = v2;\n" + " output[gid] = a[0];\n" + "}\n"; + #endif + } +}; + +AUTO_TEST_CASE(test_private_storage) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // private storage + RUN_ADDRESS_SPACES_TEST_MACRO(private_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(private_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(private_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(private_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(private_storage_test()); + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +// ---------------------------- +// ---------- LOCAL +// ---------------------------- + +template +struct local_storage_test : public address_spaces_test +{ + std::string str() + { + return "local_storage"; + } + + T operator()(size_t i, size_t work_group_size) + { + typedef typename scalar_type::type SCALAR; + size_t r = i / work_group_size; + return detail::make_value(static_cast(r)); + } + + bool set_local_size() + { + return true; + } + + // Every work-item writes id of its work-group to output[work-item-global-id] + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return + "__kernel void " + this->get_kernel_name() + "(global " + type_name() + " *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = (" + type_name() + ")(get_group_id(0));\n" + "}\n"; + + #else + return + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + // Using program scope local variable + "local<" + type_name() + "> program_scope_var;" + "__kernel void " + this->get_kernel_name() + "(global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " typedef " + type_name() + " TYPE;\n" + // 1st work-item in work-group writes get_group_id() to var + " local var;\n" + " if(lid == 0) { var = TYPE(get_group_id(0)); }\n" + " work_group_barrier(mem_fence::local);\n" + // last work-item in work-group writes var to 1st element of a + " local_ptr var_ptr = var.ptr();\n" + " TYPE var2 = *var_ptr;\n" + " local> a;\n" + " if(lid == (get_local_size(0) - 1)) { *(a.begin()) = var2; }\n" + " work_group_barrier(mem_fence::local);\n" + // 1st work-item in work-group writes a[0] to program_scope_var + " if(lid == 0) { program_scope_var = a[0]; }\n" + " work_group_barrier(mem_fence::local);\n" + " const TYPE *program_scope_var_ptr = &program_scope_var;\n" + " output[gid] = *program_scope_var_ptr;\n" + "}\n"; + #endif + } +}; + +AUTO_TEST_CASE(test_local_storage) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // local storage + RUN_ADDRESS_SPACES_TEST_MACRO(local_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(local_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(local_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(local_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(local_storage_test()); + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +// ---------------------------- +// ---------- GLOBAL +// ---------------------------- + +template +struct global_storage_test : public address_spaces_test +{ + // m_test_value is just a random value we use in this test. + // m_test_value should not be zero. + global_storage_test() : m_test_value(0xdeaddeadU) + { + + } + + std::string str() + { + return "global_storage"; + } + + T operator()(size_t i, size_t work_group_size) + { + typedef typename scalar_type::type SCALAR; + return detail::make_value(static_cast(m_test_value)); + } + + std::vector get_kernel_names() + { + return + { + this->get_kernel_name() + "1", + this->get_kernel_name() + "2" + }; + } + + // Every work-item writes m_test_value to output[work-item-global-id] + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return + "__kernel void " + this->get_kernel_names()[0] + "(global " + type_name() + " *output, " + "uint test_value)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = (" + type_name() + ")(test_value);\n" + "}\n" + "__kernel void " + this->get_kernel_names()[1] + "(global " + type_name() + " *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = output[gid];\n" + "}\n"; + #else + return + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "typedef " + type_name() + " TYPE;\n" + // Using program scope global variable + "global> program_scope_global_array;" + "__kernel void " + this->get_kernel_names()[0] + "(global_ptr<" + type_name() + "[]> output, " + "uint test_value)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + // 1st work-item writes test_value to program_scope_global_array[0] + " if(gid == 0) { program_scope_global_array[0] = test_value; }\n" + "}\n" + "__kernel void " + this->get_kernel_names()[1] + "(global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " static global func_scope_global_var { 0 };\n" + // if (func_scope_global_var == 1) is true then + // each work-item saves program_scope_global_array[0] to output[work-item-global-id] + " if(func_scope_global_var == uint(1))\n" + " {\n" + " output[gid] = program_scope_global_array[0];\n" + " return;\n" + " }\n" + // 1st work-item writes 1 to func_scope_global_var + " if(gid == 0) { func_scope_global_var = uint(1); }\n" + "}\n"; + #endif + } + + // In this test execution is quite complicated. We have two kernels. + // 1st kernel tests program scope global variable, and 2nd kernel tests + // function scope global variable (that's why it is run twice). + cl_int execute(const std::vector& kernels, + cl_mem& output_buffer, + cl_command_queue& queue, + size_t work_size, + size_t wg_size) + { + cl_int err; + err = clSetKernelArg(kernels[0], 0, sizeof(output_buffer), &output_buffer); + err |= clSetKernelArg(kernels[0], 1, sizeof(cl_uint), &m_test_value); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + // Run first kernel, once. + // This kernel saves m_test_value to program scope global variable called program_scope_global_var + err = clEnqueueNDRangeKernel( + queue, kernels[0], 1, NULL, &work_size, this->set_local_size() ? &wg_size : NULL, 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + err = clFinish(queue); + RETURN_ON_CL_ERROR(err, "clFinish") + + err = clSetKernelArg(kernels[1], 0, sizeof(output_buffer), &output_buffer); + // Run 2nd kernel, twice. + // 1st run: program_scope_global_var is saved to function scope global array called func_scope_global_array + // 2nd run: each work-item saves func_scope_global_array[0] to ouput[work-item-global-id] + for(size_t i = 0; i < 2; i++) + { + err = clEnqueueNDRangeKernel( + queue, kernels[1], 1, NULL, &work_size, this->set_local_size() ? &wg_size : NULL, 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + err = clFinish(queue); + RETURN_ON_CL_ERROR(err, "clFinish") + } + return err; + } + +private: + cl_uint m_test_value; +}; + +AUTO_TEST_CASE(test_global_storage) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + RUN_ADDRESS_SPACES_TEST_MACRO(global_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(global_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(global_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(global_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(global_storage_test()); + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +// ---------------------------- +// ---------- CONSTANT +// ---------------------------- + +template +struct constant_storage_test : public address_spaces_test +{ + // m_test_value is just a random value we use in this test. + constant_storage_test() : m_test_value(0xdeaddeadU) + { + + } + + std::string str() + { + return "constant_storage"; + } + + T operator()(size_t i, size_t work_group_size) + { + typedef typename scalar_type::type SCALAR; + return detail::make_value(static_cast(m_test_value)); + } + + // Every work-item writes m_test_value to output[work-item-global-id] + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return + "__kernel void " + this->get_kernel_name() + "(global " + type_name() + " *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = (" + type_name() + ")(" + std::to_string(m_test_value) + ");\n" + "}\n"; + + #else + return + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + // Program scope constant variable, program_scope_var == (m_test_value - 1) + "constant program_scope_const{ (" + std::to_string(m_test_value) + " - 1) };" + "__kernel void " + this->get_kernel_name() + "(global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " typedef " + type_name() + " TYPE;\n" + " static constant func_scope_const{ 1 };\n" + " constant_ptr ps_const_ptr = program_scope_const.ptr();\n" + // " constant_ptr> fs_const_ptr = &func_scope_const;\n" + " output[gid] = TYPE(*ps_const_ptr + func_scope_const);\n" + "}\n"; + #endif + } +private: + cl_uint m_test_value; +}; + +AUTO_TEST_CASE(test_constant_storage) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + RUN_ADDRESS_SPACES_TEST_MACRO(constant_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(constant_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(constant_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(constant_storage_test()); + RUN_ADDRESS_SPACES_TEST_MACRO(constant_storage_test()); + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_ADDRESS_SPACES_TEST_STORAGE_TYPES_HPP diff --git a/test_conformance/clcpp/api/CMakeLists.txt b/test_conformance/clcpp/api/CMakeLists.txt new file mode 100644 index 00000000..db9ce582 --- /dev/null +++ b/test_conformance/clcpp/api/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_API) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/api/main.cpp b/test_conformance/clcpp/api/main.cpp new file mode 100644 index 00000000..bfcbdd43 --- /dev/null +++ b/test_conformance/clcpp/api/main.cpp @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "test_spec_consts.hpp" +#include "test_ctors_dtors.hpp" +#include "test_ctors.hpp" +#include "test_dtors.hpp" + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/api/test_ctors.hpp b/test_conformance/clcpp/api/test_ctors.hpp new file mode 100644 index 00000000..8cdfc6ea --- /dev/null +++ b/test_conformance/clcpp/api/test_ctors.hpp @@ -0,0 +1,481 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_API_TEST_CTORS_HPP +#define TEST_CONFORMANCE_CLCPP_API_TEST_CTORS_HPP + +#include +#include +#include +#include + +#include "../common.hpp" + +// TEST 1 +// Verify that constructors are executed before any kernel is executed. +// Verify that when present, multiple constructors are executed. The order between +// constructors is undefined, but they should all execute. + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +const char * kernel_test_ctors_executed = + "__kernel void test_ctors_executed(global uint *output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " output[gid] = 0;\n" + "}\n" +; +const char * kernel_test_ctors_executed_multiple_ctors = + "__kernel void test_ctors_executed_multiple_ctors(global uint *output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " output[gid] = 0;\n" + "}\n" +; +#else +const char * kernel_test_ctors_executed = + "#include \n" + "#include \n" + "using namespace cl;\n" + "struct ctor_test_class {\n" + // non-trivial ctor + " ctor_test_class(int y) { x = y;};\n" + " int x;\n" + "};\n" + // global scope program variable + "ctor_test_class global_var(int(0xbeefbeef));\n" + "__kernel void test_ctors_executed(global_ptr output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " int result = 0;\n" + " if(global_var.x != int(0xbeefbeef)) result = 1;\n" + " output[gid] = result;\n" + "}\n" +; +const char * kernel_test_ctors_executed_multiple_ctors = + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "template\n" + "struct ctor_test_class {\n" + // non-trivial ctor + " ctor_test_class(T y) { x = y;};\n" + " T x;\n" + "};\n" + // global scope program variables + "ctor_test_class global_var0(int(0xbeefbeef));\n" + "ctor_test_class global_var1(uint(0xbeefbeefU));\n" + "ctor_test_class global_var2(float(FLT_MAX));\n" + "__kernel void test_ctors_executed_multiple_ctors(global_ptr output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " int result = 0;\n" + " if(global_var0.x != int(0xbeefbeef)) result = 1;\n" + " if(global_var1.x != uint(0xbeefbeefU)) result = 1;\n" + " if(global_var2.x != float(FLT_MAX)) result = 1;\n" + " output[gid] = result;\n" + "}\n" +; +#endif + +int test_ctors_execution(cl_device_id device, + cl_context context, + cl_command_queue queue, + int count, + std::string kernel_name, + const char * kernel_source) +{ + int error = CL_SUCCESS; + + cl_mem output_buffer; + cl_program program; + cl_kernel kernel; + + size_t dim = 1; + size_t work_size[1]; +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel(context, &program, &kernel, kernel_source, kernel_name); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel(context, &program, &kernel, kernel_source, kernel_name, "", false); + RETURN_ON_ERROR(error) +// Normal run +#else + error = create_opencl_kernel(context, &program, &kernel, kernel_source, kernel_name); + RETURN_ON_ERROR(error) +#endif + + // host vector, size == count, output[0...count-1] == 1 + std::vector output(count, cl_uint(1)); + output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clEnqueueWriteBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_uint) * output.size(), static_cast(output.data()), 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + work_size[0] = output.size(); + error = clEnqueueNDRangeKernel(queue, kernel, dim, NULL, work_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + error = clEnqueueReadBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_uint) * output.size(), static_cast(output.data()), 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + size_t sum = std::accumulate(output.begin(), output.end(), size_t(0)); + if(sum != 0) + { + error = -1; + CHECK_ERROR_MSG(error, "Test %s failed.", kernel_name.c_str()); + } + + clReleaseMemObject(output_buffer); + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; +} + +AUTO_TEST_CASE(test_global_scope_ctors_executed) +(cl_device_id device, cl_context context, cl_command_queue queue, int count) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = test_ctors_execution( + device, context, queue, count, + "test_ctors_executed", kernel_test_ctors_executed + ); + CHECK_ERROR(local_error); + error |= local_error; + + local_error = test_ctors_execution( + device, context, queue, count, + "test_ctors_executed_multiple_ctors", kernel_test_ctors_executed_multiple_ctors + ); + CHECK_ERROR(local_error); + error |= local_error; + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +// TEST 2 +// Verify that constructors are only executed once when multiple kernels from a program are executed. + +// How: The first kernel (test_ctors_executed_once_set) is run once. It changes values of program scope +// variables, then the second kernel is run multiple times, each time verifying that global variables +// have correct values (the second kernel should observe the values assigned by the first kernel, not +// by the constructors). + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +const char * program_test_ctors_executed_once = + "__kernel void test_ctors_executed_once_set()\n" + "{\n" + "}\n" + "__kernel void test_ctors_executed_once_read(global uint *output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " output[gid] = 0;\n" + "}\n" +; +#else +const char * program_test_ctors_executed_once = + "#include \n" + "#include \n" + "using namespace cl;\n" + // struct template + "template\n" + "struct ctor_test_class {\n" + // non-trivial ctor + " ctor_test_class(T y) { x = y;};\n" + " T x;\n" + "};\n" + // global scope program variables + "ctor_test_class global_var0(int(0));\n" + "ctor_test_class global_var1(uint(0));\n" + + "__kernel void test_ctors_executed_once_set()\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " if(gid == 0) {\n" + " global_var0.x = int(0xbeefbeef);\n" + " global_var1.x = uint(0xbeefbeefU);\n" + " }\n" + "}\n\n" + + "__kernel void test_ctors_executed_once_read(global_ptr output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " int result = 0;\n" + " if(global_var0.x != int(0xbeefbeef)) result = 1;\n" + " if(global_var1.x != uint(0xbeefbeefU)) result = 1;\n" + " output[gid] = result;\n" + "}\n" +; +#endif + +AUTO_TEST_CASE(test_global_scope_ctors_executed_once) +(cl_device_id device, cl_context context, cl_command_queue queue, int count) +{ + int error = CL_SUCCESS; + + cl_mem output_buffer; + cl_program program; + cl_kernel kernel_set_global_vars; + cl_kernel kernel_read_global_vars; + + size_t dim = 1; + size_t work_size[1]; +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel_set_global_vars, + program_test_ctors_executed_once, "test_ctors_executed_once_set" + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel_set_global_vars, + program_test_ctors_executed_once, "test_ctors_executed_once_set", "", false + ); + RETURN_ON_ERROR(error) + // Get the second kernel + kernel_read_global_vars = clCreateKernel(program, "test_ctors_executed_once_read", &error); + RETURN_ON_CL_ERROR(error, "clCreateKernel"); +// Normal run +#else + error = create_opencl_kernel( + context, &program, &kernel_set_global_vars, + program_test_ctors_executed_once, "test_ctors_executed_once_set" + ); + RETURN_ON_ERROR(error) + // Get the second kernel + kernel_read_global_vars = clCreateKernel(program, "test_ctors_executed_once_read", &error); + RETURN_ON_CL_ERROR(error, "clCreateKernel"); +#endif + + // Execute kernel_set_global_vars + + work_size[0] = count; + error = clEnqueueNDRangeKernel(queue, kernel_set_global_vars, dim, NULL, work_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + // Execute kernel_read_global_vars 4 times, each time we check if + // global variables have correct values. + + // host vector, size == count, output[0...count-1] == 1 + std::vector output(count, cl_uint(1)); + output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + for(size_t i = 0; i < 4; i++) + { + std::fill(output.begin(), output.end(), cl_uint(1)); + error = clEnqueueWriteBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer") + + error = clSetKernelArg(kernel_read_global_vars, 0, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + work_size[0] = output.size(); + error = clEnqueueNDRangeKernel( + queue, kernel_read_global_vars, + dim, NULL, work_size, NULL, + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + error = clEnqueueReadBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + size_t sum = std::accumulate(output.begin(), output.end(), size_t(0)); + if(sum != 0) + { + error = -1; + CHECK_ERROR_MSG(error, "Test test_ctors_executed_onces failed."); + } + } + + clReleaseMemObject(output_buffer); + clReleaseKernel(kernel_set_global_vars); + clReleaseKernel(kernel_read_global_vars); + clReleaseProgram(program); + return error; +} + +// TEST3 +// Verify that when constructor is executed, the ND-range used is (1,1,1). + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +const char * program_test_ctors_ndrange = + "__kernel void test_ctors_ndrange(global int *output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " output[gid] = 0;\n" + "}\n" +; +#else +const char * program_test_ctors_ndrange = + "#include \n" + "#include \n" + "using namespace cl;\n" + // struct + "struct ctor_test_class {\n" + // non-trivial ctor + " ctor_test_class() {\n" + " x = get_global_size(0);\n" + " y = get_global_size(1);\n" + " z = get_global_size(2);\n" + " };\n" + " ulong x;\n" + " ulong y;\n" + " ulong z;\n" + // return true if the ND-range used when ctor was exectured was + // (1, 1, 1); otherwise - false + " bool check() { return (x == 1) && (y == 1) && (z == 1);}" + "};\n" + // global scope program variables + "ctor_test_class global_var0;\n" + "ctor_test_class global_var1;\n" + + "__kernel void test_ctors_ndrange(global_ptr output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " int result = 0;\n" + " if(!global_var0.check()) result = 1;\n" + " if(!global_var1.check()) result = 1;\n" + " output[gid] = result;\n" + "}\n" +; +#endif + +AUTO_TEST_CASE(test_global_scope_ctors_ndrange) +(cl_device_id device, cl_context context, cl_command_queue queue, int count) +{ + int error = CL_SUCCESS; + + cl_mem output_buffer; + cl_program program; + cl_kernel kernel; + + size_t dim = 1; + size_t work_size[1]; +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel, + program_test_ctors_ndrange, "test_ctors_ndrange" + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel, + program_test_ctors_ndrange, "test_ctors_ndrange", "", false + ); + RETURN_ON_ERROR(error) +// Normal run +#else + error = create_opencl_kernel( + context, &program, &kernel, + program_test_ctors_ndrange, "test_ctors_ndrange" + ); + RETURN_ON_ERROR(error) +#endif + + // host vector, size == count, output[0...count-1] == 1 + std::vector output(count, cl_uint(1)); + output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clEnqueueWriteBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + work_size[0] = output.size(); + error = clEnqueueNDRangeKernel( + queue, kernel, + dim, NULL, work_size, NULL, + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + error = clEnqueueReadBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + size_t sum = std::accumulate(output.begin(), output.end(), size_t(0)); + if(sum != 0) + { + error = -1; + CHECK_ERROR_MSG(error, "Test test_ctors_executed_ndrange failed."); + } + + clReleaseMemObject(output_buffer); + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_API_TEST_CTORS_HPP diff --git a/test_conformance/clcpp/api/test_ctors_dtors.hpp b/test_conformance/clcpp/api/test_ctors_dtors.hpp new file mode 100644 index 00000000..02838fa7 --- /dev/null +++ b/test_conformance/clcpp/api/test_ctors_dtors.hpp @@ -0,0 +1,185 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_API_TEST_CTORS_DTORS_HPP +#define TEST_CONFORMANCE_CLCPP_API_TEST_CTORS_DTORS_HPP + +#include +#include +#include + +#include "../common.hpp" + +// Verify queries clGetProgramInfo correctly return the presence of constructors and/or destructors +// in the program (using option CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT/CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT) +// (both are present, either one is present, none is present). + +std::string generate_ctor_dtor_program(const bool ctor, const bool dtor) +{ + std::string program; + if(ctor) + { + program += + "struct ctor_test_class {\n" + // non-trivial ctor + " ctor_test_class(int y) { x = y;};\n" + " int x;\n" + "};\n" + "ctor_test_class ctor = ctor_test_class(1024);\n" + ; + } + if(dtor) + { + program += + "struct dtor_test_class {\n" + // non-trivial dtor + " ~dtor_test_class() { x = -1024; };\n" + " int x;\n" + "};\n" + "dtor_test_class dtor;\n" + ; + } + program += "__kernel void test_ctor_dtor()\n {\n }\n"; + return program; +} + +int test_get_program_info_global_ctors_dtors_present(cl_device_id device, + cl_context context, + cl_command_queue queue, + const bool ctor, + const bool dtor) +{ + int error = CL_SUCCESS; + cl_program program; + + // program source and options + std::string options = ""; + std::string source = generate_ctor_dtor_program(ctor, dtor); + const char * source_ptr = source.c_str(); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + // Create program + error = create_openclcpp_program(context, &program, 1, &source_ptr, options.c_str()); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return CL_SUCCESS; +// Normal run +#else + // Create program + error = create_openclcpp_program(context, &program, 1, &source_ptr, options.c_str()); + RETURN_ON_ERROR(error) +#endif + + // CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT cl_bool + // This indicates that the program object contains non-trivial constructor(s) that will be + // executed by runtime before any kernel from the program is executed. + + // CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT cl_bool + // This indicates that the program object contains non-trivial destructor(s) that will be + // executed by runtime when program is destroyed. + + // CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT + cl_bool ctors_present; + size_t cl_bool_size; + error = clGetProgramInfo( + program, + CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT, + sizeof(cl_bool), + static_cast(&ctors_present), + &cl_bool_size + ); + RETURN_ON_CL_ERROR(error, "clGetProgramInfo") + if(cl_bool_size != sizeof(cl_bool)) + { + error = -1; + CHECK_ERROR_MSG(-1, "Test failed, param_value_size_ret != sizeof(cl_bool) (%lu != %lu).", cl_bool_size, sizeof(cl_bool)); + } + if(ctor && ctors_present != CL_TRUE) + { + error = -1; + CHECK_ERROR_MSG(-1, "Test failed, CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT: 0, should be: 1."); + } + else if(!ctor && ctors_present == CL_TRUE) + { + error = -1; + CHECK_ERROR_MSG(-1, "Test failed, CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT: 1, should be: 0."); + } + + // CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT + cl_bool dtors_present = 0; + error = clGetProgramInfo( + program, + CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT, + sizeof(cl_bool), + static_cast(&ctors_present), + &cl_bool_size + ); + RETURN_ON_CL_ERROR(error, "clGetProgramInfo") + if(cl_bool_size != sizeof(cl_bool)) + { + error = -1; + CHECK_ERROR_MSG(-1, "Test failed, param_value_size_ret != sizeof(cl_bool) (%lu != %lu).", cl_bool_size, sizeof(cl_bool)); + } + if(dtor && dtors_present != CL_TRUE) + { + error = -1; + CHECK_ERROR_MSG(-1, "Test failed, CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT: 0, should be: 1."); + } + else if(!dtor && dtors_present == CL_TRUE) + { + error = -1; + CHECK_ERROR_MSG(-1, "Test failed, CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT: 1, should be: 0."); + } + + clReleaseProgram(program); + return error; +} + +AUTO_TEST_CASE(test_global_scope_ctors_dtors_present) +(cl_device_id device, cl_context context, cl_command_queue queue, int count) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + // both present + last_error = test_get_program_info_global_ctors_dtors_present(device, context, queue, true, true); + CHECK_ERROR(last_error); + error |= last_error; + // dtor + last_error = test_get_program_info_global_ctors_dtors_present(device, context, queue, false, true); + CHECK_ERROR(last_error); + error |= last_error; + // ctor + last_error = test_get_program_info_global_ctors_dtors_present(device, context, queue, true, false); + CHECK_ERROR(last_error); + error |= last_error; + // none present + last_error = test_get_program_info_global_ctors_dtors_present(device, context, queue, false, false); + CHECK_ERROR(last_error); + error |= last_error; + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_API_TEST_CTORS_DTORS_HPP diff --git a/test_conformance/clcpp/api/test_dtors.hpp b/test_conformance/clcpp/api/test_dtors.hpp new file mode 100644 index 00000000..2f4fd0c7 --- /dev/null +++ b/test_conformance/clcpp/api/test_dtors.hpp @@ -0,0 +1,553 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_API_TEST_DTORS_HPP +#define TEST_CONFORMANCE_CLCPP_API_TEST_DTORS_HPP + +#include +#include +#include +#include + +#include "../common.hpp" + +// TEST 1 +// Verify that destructor is executed. + +// How: destructor of struct dtor_test_class has a side effect: zeroing buffer. If values +// in buffer are not zeros after releasing program, destructor was not executed. + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +const char * program_test_dtor_is_executed = + "__kernel void test_dtor_is_executed(global uint *output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " output[gid] = 0;\n" + "}\n" +; +#else +const char * program_test_dtor_is_executed = + "#include \n" + "#include \n" + "using namespace cl;\n" + // struct + "struct dtor_test_class {\n" + // non-trivial dtor + // set all values in buffer to 0 + " ~dtor_test_class() {\n" + " for(ulong i = 0; i < size; i++)\n" + " buffer[i] = 0;\n" + " };\n" + " global_ptr buffer;\n" + " ulong size;\n" + "};\n" + // global scope program variable + "dtor_test_class global_var;\n" + + // values in output __MUST BE__ greater than 0 for the test to work + // correctly + "__kernel void test_dtor_is_executed(global_ptr output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + // set buffer and size in global var + " if(gid == 0){\n" + " global_var.buffer = output;\n" + " global_var.size = get_global_size(0);\n" + " }\n" + "}\n" +; +#endif + +AUTO_TEST_CASE(test_global_scope_dtor_is_executed) +(cl_device_id device, cl_context context, cl_command_queue queue, int count) +{ + int error = CL_SUCCESS; + + cl_mem output_buffer; + cl_program program; + cl_kernel kernel; + + size_t dim = 1; + size_t work_size[1]; +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel, + program_test_dtor_is_executed, "test_dtor_is_executed" + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel, + program_test_dtor_is_executed, "test_dtor_is_executed", "", false + ); + RETURN_ON_ERROR(error) +// Normal run +#else + error = create_opencl_kernel( + context, &program, &kernel, + program_test_dtor_is_executed, "test_dtor_is_executed" + ); + RETURN_ON_ERROR(error) +#endif + + // host vector, size == count, output[0...count-1] == 0xbeefbeef (3203383023) + // values in output __MUST BE__ greater than 0 for the test to work correctly + std::vector output(count, cl_uint(0xbeefbeef)); + output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clEnqueueWriteBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + work_size[0] = output.size(); + error = clEnqueueNDRangeKernel( + queue, kernel, + dim, NULL, work_size, NULL, + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + // Release kernel and program + // Dtor should be called now + error = clReleaseKernel(kernel); + RETURN_ON_CL_ERROR(error, "clReleaseKernel") + error = clReleaseProgram(program); + RETURN_ON_CL_ERROR(error, "clReleaseProgram") + + // Finish + error = clFinish(queue); + RETURN_ON_CL_ERROR(error, "clFinish") + + // Read output buffer + error = clEnqueueReadBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + size_t sum = std::accumulate(output.begin(), output.end(), size_t(0)); + if(sum != 0) + { + error = -1; + CHECK_ERROR_MSG(error, "Test test_dtor_is_executed failed."); + } + + clReleaseMemObject(output_buffer); + return error; +} + +// TEST 2 +// Verify that multiple destructors, if present, are executed. Order between multiple +// destructors is undefined. +// Verify that each destructor is executed only once. + +// How: +// 0) dtor_test_class struct has a global pointer to a buffer, it's set by +// test_dtors_executed_once kernel. +// 1) Destructors have a side effect: each dtor writes to its part of the buffer. If all +// dtors are executed, all values in that buffer should be changed. +// 2) The first time destructors are executed, they set their parts of the buffer to zero. +// Next time to 1, next time to 2 etc. Since dtors should be executed only once, all +// values in that buffer should be equal to zero. + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +const char * program_test_dtors_executed_once = + "__kernel void test_dtors_executed_once(global uint *output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " output[gid] = 0;\n" + "}\n" +; +#else +const char * program_test_dtors_executed_once = + "#include \n" + "#include \n" + "using namespace cl;\n" + // struct + "struct dtor_test_class {\n" + // non-trivial dtor + // Set all values in range [start; end - 1] in buffer to counter. + // If dtor is executed only once (correct), all values in range + // [start; end - 1] in buffer should be equal to zero after releasing + // the program + " ~dtor_test_class() {\n" + " for(ulong i = start; i < end; i++){\n" + " buffer[i] = counter;\n" + " };\n" + " counter++;\n" + " };\n" + " global_ptr buffer;\n" + " ulong start;\n" + " ulong end;\n" + " ulong counter;\n" + "};\n" + // global scope program variables + "dtor_test_class global_var0;\n" + "dtor_test_class global_var1;\n" + "dtor_test_class global_var2;\n" + "dtor_test_class global_var3;\n" + + // values in output __MUST BE__ greater than 0 for the test to work correctly + "__kernel void test_dtors_executed_once(global_ptr output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + // set buffer and size in global var + " if(gid == 0){\n" + " ulong end = get_global_size(0) / 4;" + // global_var0 + " global_var0.buffer = output;\n" + " global_var0.start = 0;\n" + " global_var0.end = end;\n" + " global_var0.counter = 0;\n" + // global_var1 + " global_var1.buffer = output;\n" + " global_var1.start = end;\n" + " end += get_global_size(0) / 4;\n" + " global_var1.end = end;\n" + " global_var1.counter = 0;\n" + // global_var2 + " global_var2.buffer = output;\n" + " global_var2.start = end;\n" + " end += get_global_size(0) / 4;\n" + " global_var2.end = end;\n" + " global_var2.counter = 0;\n" + // global_var3 + " global_var3.buffer = output;\n" + " global_var3.start = end;\n" + " global_var3.end = get_global_size(0);\n" + " global_var3.counter = 0;\n" + " }\n" + "}\n" +; +#endif + +AUTO_TEST_CASE(test_global_scope_dtors_executed_once) +(cl_device_id device, cl_context context, cl_command_queue queue, int count) +{ + int error = CL_SUCCESS; + + cl_mem output_buffer; + cl_program program; + cl_kernel kernel; + + size_t dim = 1; + size_t work_size[1]; +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel, + program_test_dtors_executed_once, "test_dtors_executed_once" + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel, + program_test_dtors_executed_once, "test_dtors_executed_once", "", false + ); + RETURN_ON_ERROR(error) +// Normal run +#else + error = create_opencl_kernel( + context, &program, &kernel, + program_test_dtors_executed_once, "test_dtors_executed_once" + ); + RETURN_ON_ERROR(error) +#endif + + // host vector, size == count, output[0...count-1] == 0xbeefbeef (3203383023) + // values in output __MUST BE__ greater than 0 for the test to work correctly + cl_uint init_value = cl_uint(0xbeefbeef); + std::vector output(count, init_value); + output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clEnqueueWriteBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + work_size[0] = output.size(); + error = clEnqueueNDRangeKernel( + queue, kernel, + dim, NULL, work_size, NULL, + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + + // Increments the program reference count. Twice + error = clRetainProgram(program); + RETURN_ON_CL_ERROR(error, "clRetainProgram") + error = clRetainProgram(program); + RETURN_ON_CL_ERROR(error, "clRetainProgram") + + // Should just decrement the program reference count. + error = clReleaseProgram(program); + RETURN_ON_CL_ERROR(error, "clReleaseProgram") + error = clFinish(queue); + RETURN_ON_CL_ERROR(error, "clFinish") + + // Should just decrement the program reference count. + error = clReleaseProgram(program); + RETURN_ON_CL_ERROR(error, "clReleaseProgram") + error = clFinish(queue); + RETURN_ON_CL_ERROR(error, "clFinish") + +#ifndef USE_OPENCLC_KERNELS + // At this point global scope variables should not be destroyed, + // values in output buffer should not be modified. + + // Read output buffer + error = clEnqueueReadBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + for(auto& i : output) + { + if(i != init_value) + { + log_error("ERROR: Test test_global_scope_dtors_executed_once failed."); + log_error("\tDestructors were executed prematurely.\n"); + RETURN_ON_ERROR(-1) + } + } +#endif + + // Release kernel and program, destructors should be called now + error = clReleaseKernel(kernel); + RETURN_ON_CL_ERROR(error, "clReleaseKernel") + error = clReleaseProgram(program); + RETURN_ON_CL_ERROR(error, "clReleaseProgram") + + // Finish + error = clFinish(queue); + RETURN_ON_CL_ERROR(error, "clFinish") + + // Read output buffer + error = clEnqueueReadBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + size_t sum = std::accumulate(output.begin(), output.end(), size_t(0)); + if(sum != 0) + { + log_error("ERROR: Test test_global_scope_dtors_executed_once failed."); + // Maybe some dtors were not run? + for(auto& i : output) + { + if(i == init_value) + { + log_error("\tSome dtors were not executed."); + break; + } + } + log_error("\n"); + RETURN_ON_ERROR(-1) + } + + // Clean + clReleaseMemObject(output_buffer); + return error; +} + +// TEST3 +// Verify that ND-range during destructor execution is set to (1,1,1) + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +const char * program_test_dtor_ndrange = + "__kernel void test_dtor_ndrange(global uint *output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " output[gid] = 0;\n" + "}\n" +; +#else +const char * program_test_dtor_ndrange = + "#include \n" + "#include \n" + "using namespace cl;\n" + // struct + "struct dtor_test_class {\n" + // non-trivial dtor + // set all values in buffer to 0 only if ND-range is (1, 1, 1) + " ~dtor_test_class() {\n" + " if(check()){\n" + " for(ulong i = 0; i < size; i++)\n" + " buffer[i] = 0;\n" + " }\n" + " };\n" + // return true if the ND-range is (1, 1, 1); otherwise - false + " bool check() {\n" + " return (get_global_size(0) == 1)" + " && (get_global_size(1) == 1)" + " && (get_global_size(2) == 1);\n" + " }" + " ulong size;\n" + " global_ptr buffer;\n" + "};\n" + // global scope program variable + "dtor_test_class global_var;\n" + + // values in output __MUST BE__ greater than 0 for the test to work correctly + "__kernel void test_dtor_ndrange(global_ptr output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + // set buffer and size in global var + " if(gid == 0){\n" + " global_var.buffer = output;\n" + " global_var.size = get_global_size(0);\n" + " }\n" + "}\n" +; +#endif + +AUTO_TEST_CASE(test_global_scope_dtor_ndrange) +(cl_device_id device, cl_context context, cl_command_queue queue, int count) +{ + int error = CL_SUCCESS; + + cl_mem output_buffer; + cl_program program; + cl_kernel kernel; + + size_t dim = 1; + size_t work_size[1]; +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel, + program_test_dtor_ndrange, "test_dtor_ndrange" + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel, + program_test_dtor_ndrange, "test_dtor_ndrange", "", false + ); + RETURN_ON_ERROR(error) +// Normal run +#else + error = create_opencl_kernel( + context, &program, &kernel, + program_test_dtor_ndrange, "test_dtor_ndrange" + ); + RETURN_ON_ERROR(error) +#endif + + // host vector, size == count, output[0...count-1] == 0xbeefbeef (3203383023) + // values in output __MUST BE__ greater than 0 for the test to work correctly + std::vector output(count, cl_uint(0xbeefbeef)); + output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clEnqueueWriteBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + work_size[0] = output.size(); + error = clEnqueueNDRangeKernel( + queue, kernel, + dim, NULL, work_size, NULL, + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + // Release kernel and program + // Dtor should be called now + error = clReleaseKernel(kernel); + RETURN_ON_CL_ERROR(error, "clReleaseKernel") + error = clReleaseProgram(program); + RETURN_ON_CL_ERROR(error, "clReleaseProgram") + + // Finish + error = clFinish(queue); + RETURN_ON_CL_ERROR(error, "clFinish") + + // Read output buffer + error = clEnqueueReadBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + size_t sum = std::accumulate(output.begin(), output.end(), size_t(0)); + if(sum != 0) + { + error = -1; + CHECK_ERROR_MSG(error, "Test test_dtor_ndrange failed."); + } + + clReleaseMemObject(output_buffer); + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_API_TEST_DTORS_HPP diff --git a/test_conformance/clcpp/api/test_spec_consts.hpp b/test_conformance/clcpp/api/test_spec_consts.hpp new file mode 100644 index 00000000..1d061683 --- /dev/null +++ b/test_conformance/clcpp/api/test_spec_consts.hpp @@ -0,0 +1,474 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_API_TEST_SPEC_CONSTS_HPP +#define TEST_CONFORMANCE_CLCPP_API_TEST_SPEC_CONSTS_HPP + +#include +#include +#include + +#include "../common.hpp" + +// TEST 1 +// Verify that if left unset the specialization constant defaults to the default value set in SPIR-V (zero). + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +const char * kernel_test_spec_consts_defaults = + "__kernel void test_spec_consts_defaults(global int *output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " output[gid] = 0;\n" + "}\n" +; +#else +const char * kernel_test_spec_consts_defaults = + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "spec_constant spec1(0);\n" + "spec_constant spec2(0);\n" + "spec_constant spec3(0);\n" + "spec_constant spec4(0);\n" + "spec_constant spec5(0);\n" + "spec_constant spec6(0);\n" + "spec_constant spec7(0);\n" + "spec_constant spec8(0);\n" + "spec_constant spec9(0.0f);\n" + "#ifdef cl_khr_fp64\n" + "spec_constant spec10(0.0);\n" + "#endif\n" + "#ifdef cl_khr_fp16\n" + "spec_constant spec11(0.0h);\n" + "#endif\n" + "__kernel void test_spec_consts_defaults(global_ptr output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " int result = 0;\n" + " if(get(spec1) != char(0)) result = 1;\n" + " if(get(spec2) != uchar(0)) result = 1;\n" + " if(get(spec3) != short(0)) result = 1;\n" + " if(get(spec4) != ushort(0)) result = 1;\n" + " if(get(spec5) != int(0)) result = 1;\n" + " if(get(spec6) != uint(0)) result = 1;\n" + " if(get(spec7) != long(0)) result = 1;\n" + " if(get(spec8) != ulong(0)) result = 1;\n" + " if(get(spec9) != float(0)) result = 1;\n" + "#ifdef cl_khr_fp64\n" + " if(get(spec10) != double(0)) result = 1;\n" + "#endif\n" + "#ifdef cl_khr_fp16\n" + " if(get(spec11) != half(0)) result = 1;\n" + "#endif\n" + " output[gid] = result;\n" + "}\n" +; +#endif + +AUTO_TEST_CASE(test_spec_consts_defaults) +(cl_device_id device, cl_context context, cl_command_queue queue, int count) +{ + int error = CL_SUCCESS; + + cl_mem output_buffer; + cl_program program; + cl_kernel kernel; + + size_t dim = 1; + size_t work_size[1]; + + std::string options = ""; + if(is_extension_available(device, "cl_khr_fp16")) + { + options += " -cl-fp16-enable"; + } + if(is_extension_available(device, "cl_khr_fp64")) + { + options += " -cl-fp64-enable"; + } +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel(context, &program, &kernel, kernel_test_spec_consts_defaults, "test_spec_consts_defaults", options); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel(context, &program, &kernel, kernel_test_spec_consts_defaults, "test_spec_consts_defaults", "", false); + RETURN_ON_ERROR(error) +// Normal run +#else + // Spec constants are NOT set before clBuildProgram (called in create_opencl_kernel), so + // they all should default to the default value set in SPIR-V (zero). + error = create_opencl_kernel(context, &program, &kernel, kernel_test_spec_consts_defaults, "test_spec_consts_defaults", options); + RETURN_ON_ERROR(error) +#endif + + // host vector, size == 1, output[0] == 1 + std::vector output(1, cl_int(1)); + output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * output.size(), NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clEnqueueWriteBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_int) * output.size(), static_cast(output.data()), 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + work_size[0] = output.size(); + error = clEnqueueNDRangeKernel(queue, kernel, dim, NULL, work_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKerne") + + error = clEnqueueReadBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_int) * output.size(), static_cast(output.data()), 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + // if output[0] != 0, then some spec constant(s) did not default to zero. + if(output[0] != 0) + { + RETURN_ON_ERROR_MSG(-1, "Test test_spec_consts_defaults failed, output[0]: %d.", output[0]) + } + + clReleaseMemObject(output_buffer); + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; +} + +// TEST 2 +// Verify that setting an existing specialization constant affects only +// the value of that constant and not of other specialization constants. + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +const char * kernel_test_spec_consts_many_constants = + "__kernel void test_spec_consts_many_constants(global int *output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " output[gid] = 0;\n" + "}\n" +; +#else +const char * kernel_test_spec_consts_many_constants = + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "spec_constant spec1(0);\n" + "spec_constant spec2(0);\n" + "spec_constant spec3(0);\n" + "__kernel void test_spec_consts_defaults(global_ptr output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " int result = 0;\n" + " if(get(spec1) != int(-1024)) result += 1;\n" + " if(get(spec2) != int(0)) result += 2;\n" + " if(get(spec3) != int(1024)) result += 4;\n" + " output[gid] = result;\n" + "}\n" +; +#endif + +AUTO_TEST_CASE(test_spec_consts_many_constants) +(cl_device_id device, cl_context context, cl_command_queue queue, int count) +{ + int error = CL_SUCCESS; + + cl_mem output_buffer; + cl_program program; + cl_kernel kernel; + + size_t dim = 1; + size_t work_size[1]; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel, + kernel_test_spec_consts_many_constants, "test_spec_consts_many_constants" + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel, + kernel_test_spec_consts_many_constants, "test_spec_consts_many_constants", "", false + ); + RETURN_ON_ERROR(error) +// Normal run +#else + // Create program + error = create_openclcpp_program(context, &program, 1, &kernel_test_spec_consts_many_constants); + RETURN_ON_ERROR(error) + + // Set specialization constants + + // clSetProgramSpecializationConstant( + // cl_program /* program */, cl_uint /* spec_id */, size_t /* spec_size */,const void* /* spec_value */ + // ) + cl_int spec1 = -1024; + cl_int spec3 = 1024; + // Set spec1 + error = clSetProgramSpecializationConstant(program, cl_uint(1), sizeof(cl_int), static_cast(&spec1)); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + // Specialization constant spec2 should default to zero + // Set spec3 + error = clSetProgramSpecializationConstant(program, cl_uint(3), sizeof(cl_int), static_cast(&spec3)); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + + // Build program and create kernel + error = build_program_create_kernel_helper( + context, &program, &kernel, 1, &kernel_test_spec_consts_many_constants, "test_spec_consts_many_constants" + ); + RETURN_ON_ERROR(error) +#endif + + // host vector, size == 1, output[0] == 1 + std::vector output(1, cl_int(1)); + output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * output.size(), NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clEnqueueWriteBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_int) * output.size(), static_cast(output.data()), 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + work_size[0] = output.size(); + error = clEnqueueNDRangeKernel(queue, kernel, dim, NULL, work_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + error = clEnqueueReadBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_int) * output.size(), static_cast(output.data()), 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + // if output[0] != 0, then values of spec constants were incorrect + if(output[0] != 0) + { + RETURN_ON_ERROR_MSG(-1, "Test test_spec_consts_many_constants failed, output[0]: %d.", output[0]); + } + + clReleaseMemObject(output_buffer); + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; +} + +// TEST 3 +// Verify that the API correctly handles the size of a specialization constant by exercising +// the API for specialization constants of different types (int, bool, float, etc.) + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +const char * kernel_test_spec_consts_different_types = + "__kernel void test_spec_consts_different_types(global int *output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " output[gid] = 0;\n" + "}\n" +; +#else +const char * kernel_test_spec_consts_different_types = + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "spec_constant spec1(0);\n" + "spec_constant spec2(0);\n" + "spec_constant spec3(0);\n" + "spec_constant spec4(0);\n" + "spec_constant spec5(0);\n" + "spec_constant spec6(0);\n" + "spec_constant spec7(0);\n" + "spec_constant spec8(0);\n" + "spec_constant spec9(0.0f);\n" + "#ifdef cl_khr_fp64\n" + "spec_constant spec10(0.0);\n" + "#endif\n" + "#ifdef cl_khr_fp16\n" + "spec_constant spec11(0.0h);\n" + "#endif\n" + "__kernel void test_spec_consts_different_types(global_ptr output)\n" + "{\n" + " ulong gid = get_global_id(0);\n" + " int result = 0;\n" + " if(get(spec1) != char(CHAR_MAX)) result += 1;\n" + " if(get(spec2) != uchar(UCHAR_MAX)) result += 2;\n" + " if(get(spec3) != short(SHRT_MAX)) result += 4;\n" + " if(get(spec4) != ushort(USHRT_MAX)) result += 8;\n" + " if(get(spec5) != int(INT_MAX)) result += 16;\n" + " if(get(spec6) != uint(UINT_MAX)) result += 32;\n" + " if(get(spec7) != long(LONG_MAX)) result += 64;\n" + " if(get(spec8) != ulong(ULONG_MAX)) result += 128;\n" + " if(get(spec9) != float(FLT_MAX)) result += 256;\n" + "#ifdef cl_khr_fp64\n" + " if(get(spec10) != double(DBL_MAX)) result += 512;\n" + "#endif\n" + "#ifdef cl_khr_fp16\n" + " if(get(spec11) != half(HALF_MAX)) result += 1024;\n" + "#endif\n" + " output[gid] = result;\n" + "}\n" +; +#endif + + +AUTO_TEST_CASE(test_spec_consts_different_types) +(cl_device_id device, cl_context context, cl_command_queue queue, int count) +{ + int error = CL_SUCCESS; + + cl_mem output_buffer; + cl_program program; + cl_kernel kernel; + + size_t dim = 1; + size_t work_size[1]; + + std::string options = ""; + if(is_extension_available(device, "cl_khr_fp16")) + { + options += " -cl-fp16-enable"; + } + if(is_extension_available(device, "cl_khr_fp64")) + { + options += " -cl-fp64-enable"; + } +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel(context, &program, &kernel, kernel_test_spec_consts_different_types, "test_spec_consts_different_types", options); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel(context, &program, &kernel, kernel_test_spec_consts_different_types, "test_spec_consts_different_types", "", false); + RETURN_ON_ERROR(error) +// Normal run +#else + // Create program + error = create_openclcpp_program(context, &program, 1, &kernel_test_spec_consts_different_types, options.c_str()); + RETURN_ON_ERROR(error) + + // Set specialization constants + cl_uint spec_id = 1; + + cl_char spec1 = CL_CHAR_MAX; + cl_uchar spec2 = CL_UCHAR_MAX; + cl_short spec3 = CL_SHRT_MAX; + cl_ushort spec4 = CL_USHRT_MAX; + cl_int spec5 = CL_INT_MAX; + cl_uint spec6 = CL_UINT_MAX; + cl_long spec7 = CL_LONG_MAX; + cl_ulong spec8 = CL_ULONG_MAX; + cl_float spec9 = CL_FLT_MAX; + cl_double spec10 = CL_DBL_MAX; + cl_half spec11 = CL_HALF_MAX; + + // Set spec1 + error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_char), static_cast(&spec1)); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + // Set spec2 + error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_uchar), static_cast(&spec2)); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + // Set spec3 + error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_short), static_cast(&spec3)); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + // Set spec4 + error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_ushort), static_cast(&spec4)); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + // Set spec5 + error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_int), static_cast(&spec5)); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + // Set spec6 + error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_uint), static_cast(&spec6)); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + // Set spec7 + error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_long), static_cast(&spec7)); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + // Set spec8 + error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_ulong), static_cast(&spec8)); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + // Set spec9 + error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_float), static_cast(&spec9)); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + // Set spec10 + if(is_extension_available(device, "cl_khr_fp64")) + { + error = clSetProgramSpecializationConstant(program, cl_uint(10), sizeof(cl_double), static_cast(&spec10)); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + } + // Set spec11 + if(is_extension_available(device, "cl_khr_fp16")) + { + error = clSetProgramSpecializationConstant(program, cl_uint(11), sizeof(cl_half), static_cast(&spec11)); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + } + + // Build program and create kernel + error = build_program_create_kernel_helper( + context, &program, &kernel, 1, &kernel_test_spec_consts_many_constants, "test_spec_consts_many_constants" + ); + RETURN_ON_ERROR(error) +#endif + + // Copy output to output_buffer, run kernel, copy output_buffer back to output, check result + + // host vector, size == 1, output[0] == 1 + std::vector output(1, cl_int(1)); + output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * output.size(), NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clEnqueueWriteBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_int) * output.size(), static_cast(output.data()), 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + work_size[0] = output.size(); + error = clEnqueueNDRangeKernel(queue, kernel, dim, NULL, work_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + error = clEnqueueReadBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_int) * output.size(), static_cast(output.data()), 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + // if output[0] != 0, then some spec constants had incorrect values + if(output[0] != 0) + { + RETURN_ON_ERROR_MSG(-1, "Test test_spec_consts_different_types failed, output[0]: %d.", output[0]) + } + + clReleaseMemObject(output_buffer); + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_API_TEST_SPEC_CONSTS_HPP diff --git a/test_conformance/clcpp/atomics/CMakeLists.txt b/test_conformance/clcpp/atomics/CMakeLists.txt new file mode 100644 index 00000000..7f77110c --- /dev/null +++ b/test_conformance/clcpp/atomics/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_ATOMICS) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/atomics/atomic_fetch.hpp b/test_conformance/clcpp/atomics/atomic_fetch.hpp new file mode 100644 index 00000000..5618375e --- /dev/null +++ b/test_conformance/clcpp/atomics/atomic_fetch.hpp @@ -0,0 +1,306 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_ATOMICS_ATOMIC_FETCH_HPP +#define TEST_CONFORMANCE_CLCPP_ATOMICS_ATOMIC_FETCH_HPP + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + + +const size_t atomic_bucket_size = 100; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template +std::string generate_kernel_atomic_fetch(func_type func) +{ + std::string in1_value = "input[gid]"; + std::string out1_value = "output[gid / " + std::to_string(atomic_bucket_size) + "]"; + std::string function_call = "atomic_" + func.str() + "(&" + out1_value + ", " + in1_value + ")"; + return + "" + func.defs() + + "__kernel void test_" + func.str() + "(global " + type_name() + " *input, global atomic_" + type_name() + " *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " " + function_call + ";\n" + "}\n"; +} +#else +template +std::string generate_kernel_atomic_fetch(func_type func) +{ + std::string in1_value = "input[gid]"; + std::string out1_value = "output[gid / " + std::to_string(atomic_bucket_size) + "]"; + std::string function_call = func.str() + "(" + in1_value + ")"; + return + "" + func.defs() + + "" + func.headers() + + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_" + func.str() + "(global_ptr<" + type_name() + "[]> input," + "global_ptr() + ">[]> output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " " + out1_value + "." + function_call + ";\n" + "}\n"; +} +#endif + +template +bool verify_atomic_fetch(const std::vector &in, const std::vector &out, atomic_fetch op) +{ + for (size_t i = 0; i < out.size(); i++) + { + TYPE expected = op.init_out(); + for (size_t k = 0; k < atomic_bucket_size; k++) + { + const size_t in_i = i * atomic_bucket_size + k; + if (in_i >= in.size()) + break; + expected = op(expected, in[in_i]); + } + if (expected != out[i]) + { + print_error_msg(expected, out[i], i, op); + return false; + } + } + return true; +} + +template +int test_atomic_fetch_func(cl_device_id device, cl_context context, cl_command_queue queue, size_t count, atomic_fetch op) +{ + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t work_size[1]; + int err; + + typedef typename atomic_fetch::in_type TYPE; + + // Don't run test for unsupported types + if (!(type_supported(device))) + { + return CL_SUCCESS; + } + if (sizeof(TYPE) == 8 && + (!is_extension_available(device, "cl_khr_int64_base_atomics") || + !is_extension_available(device, "cl_khr_int64_extended_atomics"))) + { + return CL_SUCCESS; + } + + std::string code_str = generate_kernel_atomic_fetch(op); + std::string kernel_name("test_"); kernel_name += op.str(); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name, "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(err) +#endif + + std::vector input = generate_input(count, op.min1(), op.max1(), std::vector()); + std::vector output = generate_output((count - 1) / atomic_bucket_size + 1); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(TYPE) * input.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + buffers[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(TYPE) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(TYPE) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer") + + const TYPE pattern = op.init_out(); + err = clEnqueueFillBuffer(queue, buffers[1], &pattern, sizeof(pattern), 0, sizeof(TYPE) * output.size(), 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueFillBuffer") + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg") + err = clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg") + + work_size[0] = count; + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel") + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(TYPE) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer") + + if (!verify_atomic_fetch(input, output, op)) + { + RETURN_ON_ERROR_MSG(-1, "test_%s %s failed", op.str().c_str(), type_name().c_str()); + } + log_info("test_%s %s passed\n", op.str().c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + + +template +struct atomic_fetch +{ + typedef TYPE in_type; + + std::string decl_str() + { + return type_name(); + } + + std::string defs() + { + std::string defs; + if (sizeof(TYPE) == 8) + { + defs += "#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable\n"; + defs += "#pragma OPENCL EXTENSION cl_khr_int64_extended_atomics : enable\n"; + } + return defs; + } + + std::string headers() + { + return "#include \n"; + } + + TYPE min1() + { + return 0; + } + + TYPE max1() + { + return 1000; + } +}; + + +#define DEF_ATOMIC_FETCH_FUNC(CLASS_NAME, FUNC_NAME, HOST_FUNC_EXPRESSION, INIT_OUT) \ +template \ +struct CLASS_NAME : public atomic_fetch \ +{ \ + std::string str() \ + { \ + return #FUNC_NAME; \ + } \ + \ + TYPE init_out() \ + { \ + return INIT_OUT; \ + } \ + \ + TYPE operator()(const TYPE& x, const TYPE& y) \ + { \ + return HOST_FUNC_EXPRESSION; \ + } \ +}; + +DEF_ATOMIC_FETCH_FUNC(atomic_fetch_add, fetch_add, x + y, 0) +DEF_ATOMIC_FETCH_FUNC(atomic_fetch_sub, fetch_sub, x - y, (std::numeric_limits::max)()) + +DEF_ATOMIC_FETCH_FUNC(atomic_fetch_and, fetch_and, x & y, (std::numeric_limits::max)()) +DEF_ATOMIC_FETCH_FUNC(atomic_fetch_or, fetch_or, x | y, 0) +DEF_ATOMIC_FETCH_FUNC(atomic_fetch_xor, fetch_xor, x ^ y, 0) + +DEF_ATOMIC_FETCH_FUNC(atomic_fetch_max, fetch_max, (std::max)(x, y), 0) +DEF_ATOMIC_FETCH_FUNC(atomic_fetch_min, fetch_min, (std::min)(x, y), (std::numeric_limits::max)()) + +#undef DEF_ATOMIC_FETCH_FUNC + + +AUTO_TEST_CASE(test_atomic_fetch) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + +#define TEST_ATOMIC_MACRO(TEST_CLASS) \ + last_error = test_atomic_fetch_func( \ + device, context, queue, n_elems, TEST_CLASS \ + ); \ + CHECK_ERROR(last_error) \ + error |= last_error; + + TEST_ATOMIC_MACRO((atomic_fetch_add())) + TEST_ATOMIC_MACRO((atomic_fetch_add())) + TEST_ATOMIC_MACRO((atomic_fetch_add())) + TEST_ATOMIC_MACRO((atomic_fetch_add())) + + TEST_ATOMIC_MACRO((atomic_fetch_sub())) + TEST_ATOMIC_MACRO((atomic_fetch_sub())) + TEST_ATOMIC_MACRO((atomic_fetch_sub())) + TEST_ATOMIC_MACRO((atomic_fetch_sub())) + + TEST_ATOMIC_MACRO((atomic_fetch_and())) + TEST_ATOMIC_MACRO((atomic_fetch_and())) + TEST_ATOMIC_MACRO((atomic_fetch_and())) + TEST_ATOMIC_MACRO((atomic_fetch_and())) + + TEST_ATOMIC_MACRO((atomic_fetch_or())) + TEST_ATOMIC_MACRO((atomic_fetch_or())) + TEST_ATOMIC_MACRO((atomic_fetch_or())) + TEST_ATOMIC_MACRO((atomic_fetch_or())) + + TEST_ATOMIC_MACRO((atomic_fetch_xor())) + TEST_ATOMIC_MACRO((atomic_fetch_xor())) + TEST_ATOMIC_MACRO((atomic_fetch_xor())) + TEST_ATOMIC_MACRO((atomic_fetch_xor())) + + TEST_ATOMIC_MACRO((atomic_fetch_max())) + TEST_ATOMIC_MACRO((atomic_fetch_max())) + TEST_ATOMIC_MACRO((atomic_fetch_max())) + TEST_ATOMIC_MACRO((atomic_fetch_max())) + + TEST_ATOMIC_MACRO((atomic_fetch_min())) + TEST_ATOMIC_MACRO((atomic_fetch_min())) + TEST_ATOMIC_MACRO((atomic_fetch_min())) + TEST_ATOMIC_MACRO((atomic_fetch_min())) + +#undef TEST_ATOMIC_MACRO + + if (error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_ATOMICS_ATOMIC_FETCH_HPP diff --git a/test_conformance/clcpp/atomics/main.cpp b/test_conformance/clcpp/atomics/main.cpp new file mode 100644 index 00000000..0cf3d77d --- /dev/null +++ b/test_conformance/clcpp/atomics/main.cpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "atomic_fetch.hpp" + + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/attributes/CMakeLists.txt b/test_conformance/clcpp/attributes/CMakeLists.txt new file mode 100644 index 00000000..eee2785f --- /dev/null +++ b/test_conformance/clcpp/attributes/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_ATTRIBUTES) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/attributes/main.cpp b/test_conformance/clcpp/attributes/main.cpp new file mode 100644 index 00000000..cd834a71 --- /dev/null +++ b/test_conformance/clcpp/attributes/main.cpp @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "test_ivdep.hpp" +#include "test_max_size.hpp" +#include "test_required_num_sub_groups.hpp" + + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/attributes/test_ivdep.hpp b/test_conformance/clcpp/attributes/test_ivdep.hpp new file mode 100644 index 00000000..17b1f586 --- /dev/null +++ b/test_conformance/clcpp/attributes/test_ivdep.hpp @@ -0,0 +1,418 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_ATTRIBUTES_TEST_IVDEP_HPP +#define TEST_CONFORMANCE_CLCPP_ATTRIBUTES_TEST_IVDEP_HPP + +#include +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" + + +namespace test_ivdep { + +enum class loop_kind +{ + for_loop, + while_loop, + do_loop +}; + +struct test_options +{ + loop_kind loop; + int ivdep_length; + int offset1; + int offset2; + int iter_count; + bool offset1_param; + bool offset2_param; + bool iter_count_param; + bool cond_in_header; + bool init_in_header; + bool incr_in_header; +}; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +std::string generate_source(test_options options) +{ + std::string offset1s = options.offset1_param ? "offset1" : std::to_string(options.offset1); + std::string offset2s = options.offset2_param ? "offset2" : std::to_string(options.offset2); + + std::string init = "i = 0"; + std::string cond = std::string("i < ") + (options.iter_count_param ? "iter_count" : std::to_string(options.iter_count)); + std::string incr = "i += 2"; + + std::stringstream s; + s << R"( + kernel void test(global int *a, global int *b, global int *c, int offset1, int offset2, int iter_count) + { + int i; + )"; + + // Loop #1 + if (!options.init_in_header) s << init << ";" << std::endl; + if (options.loop == loop_kind::for_loop) + s << "for (" << + (options.init_in_header ? init : "") << ";" << + (options.cond_in_header ? cond : "") << ";" << + (options.incr_in_header ? incr : "") << ")"; + else if (options.loop == loop_kind::while_loop) + s << "while (" << (options.cond_in_header ? cond : "true") << ")"; + else if (options.loop == loop_kind::do_loop) + s << "do"; + s << "{" << std::endl; + if (!options.cond_in_header) s << "if (!(" << cond << ")) break;" << std::endl; + s << "a[i + " << offset1s << "] = b[i + " << offset1s << "] * c[i + " << offset1s << "];" << std::endl; + if (!options.incr_in_header) s << incr << ";" << std::endl; + s << "}" << std::endl; + if (options.loop == loop_kind::do_loop) + s << "while (" << (options.cond_in_header ? cond : "true") << ");" << std::endl; + + // Loop #2 + if (!options.init_in_header) s << init << ";" << std::endl; + if (options.loop == loop_kind::for_loop) + s << "for (" << + (options.init_in_header ? init : "") << ";" << + (options.cond_in_header ? cond : "") << ";" << + (options.incr_in_header ? incr : "") << ")"; + else if (options.loop == loop_kind::while_loop) + s << "while (" << (options.cond_in_header ? cond : "true") << ")"; + else if (options.loop == loop_kind::do_loop) + s << "do"; + s << "{" << std::endl; + if (!options.cond_in_header) s << "if (!(" << cond << ")) break;" << std::endl; + s << "a[i + " << offset2s << "] = a[i] + b[i];" << std::endl; + if (!options.incr_in_header) s << incr << ";" << std::endl; + s << "}" << std::endl; + if (options.loop == loop_kind::do_loop) + s << "while (" << (options.cond_in_header ? cond : "true") << ");" << std::endl; + + s << "}" << std::endl; + + return s.str(); +} +#else +std::string generate_source(test_options options) +{ + std::string offset1s = options.offset1_param ? "offset1" : std::to_string(options.offset1); + std::string offset2s = options.offset2_param ? "offset2" : std::to_string(options.offset2); + + std::string init = "i = 0"; + std::string cond = std::string("i < ") + (options.iter_count_param ? "iter_count" : std::to_string(options.iter_count)); + std::string incr = "i += 2"; + + std::stringstream s; + s << R"( + #include + #include + + using namespace cl; + )"; + s << R"( + kernel void test(global_ptr a, global_ptr b, global_ptr c, int offset1, int offset2, int iter_count) + { + int i; + )"; + + // Loop #1 + if (!options.init_in_header) s << init << ";" << std::endl; + if (options.ivdep_length > 0) s << "[[cl::ivdep]]" << std::endl; + if (options.loop == loop_kind::for_loop) + s << "for (" << + (options.init_in_header ? init : "") << ";" << + (options.cond_in_header ? cond : "") << ";" << + (options.incr_in_header ? incr : "") << ")"; + else if (options.loop == loop_kind::while_loop) + s << "while (" << (options.cond_in_header ? cond : "true") << ")"; + else if (options.loop == loop_kind::do_loop) + s << "do"; + s << "{" << std::endl; + if (!options.cond_in_header) s << "if (!(" << cond << ")) break;" << std::endl; + s << "a[i + " << offset1s << "] = b[i + " << offset1s << "] * c[i + " << offset1s << "];" << std::endl; + if (!options.incr_in_header) s << incr << ";" << std::endl; + s << "}" << std::endl; + if (options.loop == loop_kind::do_loop) + s << "while (" << (options.cond_in_header ? cond : "true") << ");" << std::endl; + + // Loop #2 + if (!options.init_in_header) s << init << ";" << std::endl; + if (options.ivdep_length > 0) s << "[[cl::ivdep(" << options.ivdep_length << ")]]" << std::endl; + if (options.loop == loop_kind::for_loop) + s << "for (" << + (options.init_in_header ? init : "") << ";" << + (options.cond_in_header ? cond : "") << ";" << + (options.incr_in_header ? incr : "") << ")"; + else if (options.loop == loop_kind::while_loop) + s << "while (" << (options.cond_in_header ? cond : "true") << ")"; + else if (options.loop == loop_kind::do_loop) + s << "do"; + s << "{" << std::endl; + if (!options.cond_in_header) s << "if (!(" << cond << ")) break;" << std::endl; + s << "a[i + " << offset2s << "] = a[i] + b[i];" << std::endl; + if (!options.incr_in_header) s << incr << ";" << std::endl; + s << "}" << std::endl; + if (options.loop == loop_kind::do_loop) + s << "while (" << (options.cond_in_header ? cond : "true") << ");" << std::endl; + + s << "}" << std::endl; + + return s.str(); +} +#endif + +int test(cl_device_id device, cl_context context, cl_command_queue queue, test_options options) +{ + int error = CL_SUCCESS; + + cl_program program; + cl_kernel kernel; + + std::string kernel_name = "test"; + std::string source = generate_source(options); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name, "", false + ); + RETURN_ON_ERROR(error) +// Normal run +#else + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) +#endif + + const size_t count = 100; + const size_t global_size = 1; + + std::vector a(count); + std::vector b(count); + std::vector c(count); + for (size_t i = 0; i < count; i++) + { + a[i] = 0; + b[i] = i; + c[i] = 1; + } + + cl_mem a_buffer; + a_buffer = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + sizeof(int) * count, static_cast(a.data()), &error + ); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + cl_mem b_buffer; + b_buffer = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + sizeof(int) * count, static_cast(b.data()), &error + ); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + cl_mem c_buffer; + c_buffer = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + sizeof(int) * count, static_cast(c.data()),&error + ); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &a_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 1, sizeof(cl_mem), &b_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 2, sizeof(cl_mem), &c_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 3, sizeof(cl_int), &options.offset1); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 4, sizeof(cl_int), &options.offset2); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 5, sizeof(cl_int), &options.iter_count); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + std::vector a_output(count); + error = clEnqueueReadBuffer( + queue, a_buffer, CL_TRUE, + 0, sizeof(int) * count, + static_cast(a_output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + for (int i = 0; i < options.iter_count; i += 2) + { + a[i + options.offset1] = b[i + options.offset1] * c[i + options.offset1]; + } + + for (int i = 0; i < options.iter_count; i += 2) + { + a[i + options.offset2] = a[i] + b[i]; + } + + for (size_t i = 0; i < count; i++) + { + const int value = a_output[i]; + const int expected = a[i]; + if (value != expected) + { + RETURN_ON_ERROR_MSG(-1, + "Test failed. Element %lu: %d should be: %d", + i, value, expected + ); + } + } + + clReleaseMemObject(a_buffer); + clReleaseMemObject(b_buffer); + clReleaseMemObject(c_buffer); + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; +} + +const std::vector> params{ + std::make_tuple( -1, 0, 0 ), + std::make_tuple( -1, 3, 4 ), + std::make_tuple( 1, 1, 1 ), + std::make_tuple( 3, 4, 2 ), + std::make_tuple( 3, 4, 3 ), + std::make_tuple( 8, 10, 7 ), + std::make_tuple( 16, 16, 16 ) +}; +const std::vector iter_counts{ { 1, 4, 12, 40 } }; + +AUTO_TEST_CASE(test_ivdep_for) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + int error = CL_SUCCESS; + + for (auto param : params) + for (auto iter_count : iter_counts) + for (bool offset1_param : { false, true }) + for (bool offset2_param : { false, true }) + for (bool iter_count_param : { false, true }) + for (bool cond_in_header : { false, true }) + for (bool init_in_header : { false, true }) + for (bool incr_in_header : { false, true }) + { + test_options options; + options.loop = loop_kind::for_loop; + options.ivdep_length = std::get<0>(param); + options.offset1 = std::get<1>(param); + options.offset2 = std::get<2>(param); + options.iter_count = iter_count; + options.offset1_param = offset1_param; + options.offset2_param = offset2_param; + options.iter_count_param = iter_count_param; + options.cond_in_header = cond_in_header; + options.init_in_header = init_in_header; + options.incr_in_header = incr_in_header; + + error = test(device, context, queue, options); + RETURN_ON_ERROR(error) + } + + return error; +} + +AUTO_TEST_CASE(test_ivdep_while) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + int error = CL_SUCCESS; + + for (auto param : params) + for (auto iter_count : iter_counts) + for (bool offset1_param : { false, true }) + for (bool offset2_param : { false, true }) + for (bool iter_count_param : { false, true }) + for (bool cond_in_header : { false, true }) + { + test_options options; + options.loop = loop_kind::while_loop; + options.ivdep_length = std::get<0>(param); + options.offset1 = std::get<1>(param); + options.offset2 = std::get<2>(param); + options.iter_count = iter_count; + options.offset1_param = offset1_param; + options.offset2_param = offset2_param; + options.iter_count_param = iter_count_param; + options.cond_in_header = cond_in_header; + options.init_in_header = false; + options.incr_in_header = false; + + error = test(device, context, queue, options); + RETURN_ON_ERROR(error) + } + + return error; +} + +AUTO_TEST_CASE(test_ivdep_do) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + int error = CL_SUCCESS; + + for (auto param : params) + for (auto iter_count : iter_counts) + for (bool offset1_param : { false, true }) + for (bool offset2_param : { false, true }) + for (bool iter_count_param : { false, true }) + for (bool cond_in_header : { false, true }) + { + test_options options; + options.loop = loop_kind::do_loop; + options.ivdep_length = std::get<0>(param); + options.offset1 = std::get<1>(param); + options.offset2 = std::get<2>(param); + options.iter_count = iter_count; + options.offset1_param = offset1_param; + options.offset2_param = offset2_param; + options.iter_count_param = iter_count_param; + options.cond_in_header = cond_in_header; + options.init_in_header = false; + options.incr_in_header = false; + + error = test(device, context, queue, options); + RETURN_ON_ERROR(error) + } + + return error; +} + +} // namespace + +#endif // TEST_CONFORMANCE_CLCPP_ATTRIBUTES_TEST_IVDEP_HPP diff --git a/test_conformance/clcpp/attributes/test_max_size.hpp b/test_conformance/clcpp/attributes/test_max_size.hpp new file mode 100644 index 00000000..15e7ead6 --- /dev/null +++ b/test_conformance/clcpp/attributes/test_max_size.hpp @@ -0,0 +1,266 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_ATTRIBUTES_TEST_MAX_SIZE_HPP +#define TEST_CONFORMANCE_CLCPP_ATTRIBUTES_TEST_MAX_SIZE_HPP + +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" + + +namespace test_max_size { + +enum class address_space +{ + constant, + local +}; + +enum class param_kind +{ + ptr_type, // constant_ptr + ptr, // constant* + ref // constant& +}; + +const param_kind param_kinds[] = +{ + param_kind::ptr_type, + param_kind::ptr, + param_kind::ref +}; + +struct test_options +{ + address_space space; + int max_size; + bool spec_const; + param_kind kind; + bool array; +}; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +std::string generate_source(test_options options) +{ + std::stringstream s; + s << "kernel void test("; + s << (options.space == address_space::constant ? "constant" : "local"); + s << " int2 *input) { }" << std::endl; + + return s.str(); +} +#else +std::string generate_source(test_options options) +{ + std::string type_str = "int2"; + if (options.array) + type_str += "[]"; + + std::stringstream s; + s << "#include " << std::endl; + + if (options.spec_const) + { + s << "#include " << std::endl; + s << "cl::spec_constant max_size_spec{ 1234567890 };" << std::endl; + } + + s << "kernel void test("; + s << "[[cl::max_size(" << (options.spec_const ? "max_size_spec" : std::to_string(options.max_size)) << ")]] "; + s << (options.space == address_space::constant ? "cl::constant" : "cl::local"); + if (options.kind == param_kind::ptr_type) + s << "_ptr<" << type_str << ">"; + else if (options.kind == param_kind::ptr) + s << "<" << type_str << ">*"; + else if (options.kind == param_kind::ref) + s << "<" << type_str << ">&"; + s << " input) { }" << std::endl; + + return s.str(); +} +#endif + +int test(cl_device_id device, cl_context context, cl_command_queue queue, test_options options) +{ + int error = CL_SUCCESS; + + cl_program program; + cl_kernel kernel; + + std::string kernel_name = "test"; + std::string source = generate_source(options); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name, "", false + ); + RETURN_ON_ERROR(error) +// Normal run +#else + const char *source_c_str = source.c_str(); + error = create_openclcpp_program(context, &program, 1, &source_c_str, ""); + RETURN_ON_ERROR(error) + + if (options.spec_const) + { + error = clSetProgramSpecializationConstant(program, 1, sizeof(cl_int), &options.max_size); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + } + + error = build_program_create_kernel_helper( + context, &program, &kernel, 1, &source_c_str, kernel_name.c_str() + ); + RETURN_ON_ERROR(error) +#endif + + const int max_size = options.max_size; + const int sizes[] = { + 1, + max_size / 2, + max_size, + max_size + 1, + max_size * 2 + }; + + for (int size : sizes) + { + cl_mem const_buffer; + if (options.space == address_space::constant) + { + const_buffer = clCreateBuffer(context, CL_MEM_READ_ONLY, size, NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &const_buffer); + // Check the status later (depending on size and max_size values) + } + else if (options.space == address_space::local) + { + error = clSetKernelArg(kernel, 0, size, NULL); + // Check the status later (depending on size and max_size values) + } + + if (size <= max_size) + { + // Correct value, must not fail + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + const size_t global_size = 123; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + error = clFinish(queue); + RETURN_ON_CL_ERROR(error, "clFinish") + } + else + { + // Incorrect value, must fail + if (error != CL_MAX_SIZE_RESTRICTION_EXCEEDED) + { + RETURN_ON_ERROR_MSG(-1, + "clSetKernelArg must fail with CL_MAX_SIZE_RESTRICTION_EXCEEDED," + " but returned %s (%d)", get_cl_error_string(error).c_str(), error + ); + } + } + + if (options.space == address_space::constant) + { + error = clReleaseMemObject(const_buffer); + RETURN_ON_CL_ERROR(error, "clReleaseMemObject") + } + } + + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; +} + +AUTO_TEST_CASE(test_max_size_constant) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + int error = CL_SUCCESS; + + cl_ulong max_size; + error = clGetDeviceInfo(device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(max_size), &max_size, NULL); + RETURN_ON_CL_ERROR(error, "clGetDeviceInfo") + + for (bool spec_const : { false, true }) + for (auto kind : param_kinds) + for (bool array : { false, true }) + { + test_options options; + options.space = address_space::constant; + options.max_size = max_size / 2; + options.spec_const = spec_const; + options.kind = kind; + options.array = array; + + error = test(device, context, queue, options); + RETURN_ON_ERROR(error) + } + + return error; +} + +AUTO_TEST_CASE(test_max_size_local) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + int error = CL_SUCCESS; + + cl_ulong max_size; + error = clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(max_size), &max_size, NULL); + RETURN_ON_CL_ERROR(error, "clGetDeviceInfo") + + for (bool spec_const : { false, true }) + for (auto kind : param_kinds) + for (bool array : { false, true }) + { + test_options options; + options.space = address_space::local; + options.max_size = max_size / 2; + options.spec_const = spec_const; + options.kind = kind; + options.array = array; + + error = test(device, context, queue, options); + RETURN_ON_ERROR(error) + } + + return error; +} + +} // namespace + +#endif // TEST_CONFORMANCE_CLCPP_ATTRIBUTES_TEST_MAX_SIZE_HPP diff --git a/test_conformance/clcpp/attributes/test_required_num_sub_groups.hpp b/test_conformance/clcpp/attributes/test_required_num_sub_groups.hpp new file mode 100644 index 00000000..2380eafe --- /dev/null +++ b/test_conformance/clcpp/attributes/test_required_num_sub_groups.hpp @@ -0,0 +1,285 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_ATTRIBUTES_TEST_REQUIRED_NUM_SUB_GROUPS_HPP +#define TEST_CONFORMANCE_CLCPP_ATTRIBUTES_TEST_REQUIRED_NUM_SUB_GROUPS_HPP + +#include +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" + + +namespace test_required_num_sub_groups { + +struct test_options +{ + size_t num_sub_groups; + bool spec_const; + size_t max_count; + size_t num_tests; +}; + +struct output_type +{ + cl_ulong num_sub_groups; + cl_ulong enqueued_num_sub_groups; +}; + +const std::string source_common = R"( +struct output_type +{ + ulong num_sub_groups; + ulong enqueued_num_sub_groups; +}; +)"; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +std::string generate_source(test_options options) +{ + std::stringstream s; + s << source_common; + s << R"( + #pragma OPENCL EXTENSION cl_khr_subgroups : enable + + kernel void test(global struct output_type *output) + { + const ulong gid = get_global_linear_id(); + output[gid].num_sub_groups = get_num_sub_groups(); + output[gid].enqueued_num_sub_groups = get_enqueued_num_sub_groups(); + } + )"; + + return s.str(); +} +#else +std::string generate_source(test_options options) +{ + std::stringstream s; + s << R"( + #include + #include + using namespace cl; + )"; + + if (options.spec_const) + { + s << "#include " << std::endl; + s << "cl::spec_constant num_sub_groups_spec{ 1234567890 };" << std::endl; + } + + s << source_common << std::endl; + s << "[[cl::required_num_sub_groups(" << (options.spec_const ? "num_sub_groups_spec" : std::to_string(options.num_sub_groups)) << ")]]"; + s << R"( + kernel void test(global_ptr output) + { + const ulong gid = get_global_linear_id(); + output[gid].num_sub_groups = get_num_sub_groups(); + output[gid].enqueued_num_sub_groups = get_enqueued_num_sub_groups(); + } + )"; + + return s.str(); +} +#endif + +int test(cl_device_id device, cl_context context, cl_command_queue queue, test_options options) +{ + int error = CL_SUCCESS; + +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + if (!is_extension_available(device, "cl_khr_subgroups")) + { + log_info("SKIPPED: Extension `cl_khr_subgroups` is not supported. Skipping tests.\n"); + return CL_SUCCESS; + } +#endif + + cl_program program; + cl_kernel kernel; + + std::string kernel_name = "test"; + std::string source = generate_source(options); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name, "-cl-std=CL2.0", false + ); + RETURN_ON_ERROR(error) +// Normal run +#else + const char *source_c_str = source.c_str(); + error = create_openclcpp_program(context, &program, 1, &source_c_str, ""); + RETURN_ON_ERROR(error) + + if (options.spec_const) + { + cl_uint spec_num_sub_groups = static_cast(options.num_sub_groups); + error = clSetProgramSpecializationConstant(program, 1, sizeof(cl_uint), &spec_num_sub_groups); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + } + + error = build_program_create_kernel_helper( + context, &program, &kernel, 1, &source_c_str, kernel_name.c_str() + ); + RETURN_ON_ERROR(error) +#endif + + size_t compile_num_sub_groups; + error = clGetKernelSubGroupInfo(kernel, device, CL_KERNEL_COMPILE_NUM_SUB_GROUPS, + 0, NULL, + sizeof(size_t), &compile_num_sub_groups, NULL); + RETURN_ON_CL_ERROR(error, "clGetKernelSubGroupInfo") + if (compile_num_sub_groups != options.num_sub_groups) + { + RETURN_ON_ERROR_MSG(-1, + "CL_KERNEL_COMPILE_NUM_SUB_GROUPS did not return correct value (expected %lu, got %lu)", + options.num_sub_groups, compile_num_sub_groups + ) + } + + cl_mem output_buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(output_type) * options.max_count, NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution count_dis(1, options.max_count); + + for (size_t test = 0; test < options.num_tests; test++) + { + for (size_t dim = 1; dim <= 3; dim++) + { + size_t global_size[3] = { 1, 1, 1 }; + size_t count = count_dis(gen); + std::uniform_int_distribution global_size_dis(1, static_cast(pow(count, 1.0 / dim))); + for (size_t d = 0; d < dim; d++) + { + global_size[d] = global_size_dis(gen); + } + count = global_size[0] * global_size[1] * global_size[2]; + + size_t local_size[3] = { 1, 1, 1 }; + error = clGetKernelSubGroupInfo(kernel, device, CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT, + sizeof(size_t), &options.num_sub_groups, + sizeof(size_t) * dim, local_size, NULL); + RETURN_ON_CL_ERROR(error, "clGetKernelSubGroupInfo") + if (local_size[0] == 0 || local_size[1] != 1 || local_size[2] != 1) + { + RETURN_ON_ERROR_MSG(-1, + "CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT did not return correct value" + ) + } + + size_t sub_group_count_for_ndrange; + error = clGetKernelSubGroupInfo(kernel, device, CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE, + sizeof(size_t) * dim, local_size, + sizeof(size_t), &sub_group_count_for_ndrange, NULL); + RETURN_ON_CL_ERROR(error, "clGetKernelSubGroupInfo") + if (sub_group_count_for_ndrange != options.num_sub_groups) + { + RETURN_ON_ERROR_MSG(-1, + "CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE did not return correct value (expected %lu, got %lu)", + options.num_sub_groups, sub_group_count_for_ndrange + ) + } + + const char pattern = 0; + error = clEnqueueFillBuffer(queue, output_buffer, &pattern, sizeof(pattern), 0, sizeof(output_type) * count, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueFillBuffer") + + error = clEnqueueNDRangeKernel(queue, kernel, dim, NULL, global_size, local_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + std::vector output(count); + error = clEnqueueReadBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(output_type) * count, + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + for (size_t gid = 0; gid < count; gid++) + { + const output_type &o = output[gid]; + + if (o.enqueued_num_sub_groups != options.num_sub_groups) + { + RETURN_ON_ERROR_MSG(-1, "get_enqueued_num_sub_groups does not equal to required_num_sub_groups") + } + if (o.num_sub_groups > options.num_sub_groups) + { + RETURN_ON_ERROR_MSG(-1, "get_num_sub_groups did not return correct value") + } + } + } + } + + clReleaseMemObject(output_buffer); + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; +} + +AUTO_TEST_CASE(test_required_num_sub_groups) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + int error = CL_SUCCESS; + + cl_uint max_num_sub_groups; + error = clGetDeviceInfo(device, CL_DEVICE_MAX_NUM_SUB_GROUPS, sizeof(max_num_sub_groups), &max_num_sub_groups, NULL); + RETURN_ON_CL_ERROR(error, "clGetDeviceInfo") + + for (bool spec_const : { false, true }) + for (size_t num_sub_groups = 1; num_sub_groups <= max_num_sub_groups; num_sub_groups++) + { + test_options options; + options.spec_const = spec_const; + options.num_sub_groups = num_sub_groups; + options.num_tests = 100; + options.max_count = num_elements; + + error = test(device, context, queue, options); + RETURN_ON_ERROR(error) + } + + return error; +} + +} // namespace + +#endif // TEST_CONFORMANCE_CLCPP_ATTRIBUTES_TEST_REQUIRED_NUM_SUB_GROUPS_HPP diff --git a/test_conformance/clcpp/common.hpp b/test_conformance/clcpp/common.hpp new file mode 100644 index 00000000..ff92f029 --- /dev/null +++ b/test_conformance/clcpp/common.hpp @@ -0,0 +1,51 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_COMMON_INC_HPP +#define TEST_CONFORMANCE_CLCPP_COMMON_INC_HPP + +#include +#include +#include +#include +#include +#include + +// harness framework +#include "../../test_common/harness/compat.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" + +// autotest +#include "../../test_common/autotest/autotest.hpp" + +// utils_common +#include "utils_common/is_vector_type.hpp" +#include "utils_common/scalar_type.hpp" +#include "utils_common/make_vector_type.hpp" +#include "utils_common/type_name.hpp" +#include "utils_common/type_supported.hpp" +#include "utils_common/vector_size.hpp" +#include "utils_common/kernel_helpers.hpp" +#include "utils_common/errors.hpp" +#include "utils_common/string.hpp" + +size_t get_uniform_global_size(size_t global_size, size_t local_size) +{ + return static_cast(std::ceil(static_cast(global_size) / local_size)) * local_size; +} + +#endif // TEST_CONFORMANCE_CLCPP_COMMON_INC_HPP diff --git a/test_conformance/clcpp/common_funcs/CMakeLists.txt b/test_conformance/clcpp/common_funcs/CMakeLists.txt new file mode 100644 index 00000000..bc192a5c --- /dev/null +++ b/test_conformance/clcpp/common_funcs/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_COMMON_FUNCS) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/common_funcs/common_funcs.hpp b/test_conformance/clcpp/common_funcs/common_funcs.hpp new file mode 100644 index 00000000..d6f8c897 --- /dev/null +++ b/test_conformance/clcpp/common_funcs/common_funcs.hpp @@ -0,0 +1,417 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_COMMON_FUNCS_COMMON_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_COMMON_FUNCS_COMMON_FUNCS_HPP + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#include +#include + +// floatn clamp(floatn x, floatn min, floatn max) (only scalars) +template +struct common_func_clamp : public ternary_func +{ + std::string str() + { + return "clamp"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& minval, const IN3& maxval) + { + static_assert( + std::is_same::value + && std::is_same::value + && std::is_same::value, + "All types must be the same" + ); + return (std::min)((std::max)(x, minval), maxval); + } + + IN2 min2() + { + return (std::numeric_limits::min)(); + } + + IN2 max2() + { + return (std::numeric_limits::max)() / IN2(4000.0f); + } + + IN3 min3() + { + return IN3(1) + ((std::numeric_limits::max)() / IN3(4000.0f)); + } + + IN3 max3() + { + return (std::numeric_limits::max)() / IN3(2000.0f); + } + + float ulp() + { + return 0.0f; + } +}; + +// floatn degrees(floatn t) +template +struct common_func_degrees : public unary_func +{ + std::string str() + { + return "degrees"; + } + + std::string headers() + { + return "#include \n"; + } + + REFERENCE operator()(const IN1& x) + { + static_assert( + std::is_same::value, + "All types must be the same" + ); + return (REFERENCE(180.0) / CL_M_PI) * static_cast(x); + } + + float ulp() + { + return 2.5f; + } +}; + +// floatn max(floatn x, floatn y) +template +struct common_func_max : public binary_func +{ + std::string str() + { + return "max"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& y) + { + static_assert( + std::is_same::value && std::is_same::value, + "All types must be the same" + ); + return (std::max)(x, y); + } + + float ulp() + { + return 0.0f; + } +}; + +// floatn min(floatn x, floatn y) +template +struct common_func_min : public binary_func +{ + std::string str() + { + return "min"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& y) + { + static_assert( + std::is_same::value && std::is_same::value, + "All types must be the same" + ); + return (std::min)(x, y); + } + + float ulp() + { + return 0.0f; + } +}; + +// floatn mix(floatn x, floatn y, floatn a); +template +struct common_func_mix : public ternary_func +{ + std::string str() + { + return "mix"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& y, const IN3& a) + { + static_assert( + std::is_same::value + && std::is_same::value + && std::is_same::value, + "All types must be the same" + ); + return static_cast(x) + ((static_cast(y) - static_cast(x)) * static_cast(a)); + } + + IN3 min3() + { + return IN3(0.0f + CL_FLT_EPSILON); + } + + IN3 max3() + { + return IN3(1.0f - CL_FLT_EPSILON); + } + + bool use_ulp() + { + return false; + } +}; + +// floatn radians(floatn t) +template +struct common_func_radians : public unary_func +{ + std::string str() + { + return "radians"; + } + + std::string headers() + { + return "#include \n"; + } + + REFERENCE operator()(const IN1& x) + { + static_assert( + std::is_same::value, + "All types must be the same" + ); + return (CL_M_PI / REFERENCE(180.0)) * static_cast(x); + } + + float ulp() + { + return 2.5f; + } +}; + +// floatn step(floatn edge, floatn x) +template +struct common_func_step : public binary_func +{ + std::string str() + { + return "step"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& edge, const IN2& x) + { + static_assert( + std::is_same::value && std::is_same::value, + "All types must be the same" + ); + if(x < edge) + return OUT1(0.0f); + return OUT1(1.0f); + } + + float ulp() + { + return 0.0f; + } +}; + +// floatn smoothstep(floatn edge0, floatn edge1, floatn x); +template +struct common_func_smoothstep : public ternary_func +{ + std::string str() + { + return "smoothstep"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& edge0, const IN2& edge1, const IN3& x) + { + static_assert( + std::is_same::value + && std::is_same::value + && std::is_same::value, + "All types must be the same" + ); + if(x <= edge0) + { + return OUT1(0.0f); + } + if(x >= edge1) + { + return OUT1(1.0f); + } + OUT1 t = (x - edge0) / (edge1 - edge0); + t = t * t * (3.0f - 2.0f * t); + return t; + } + + // edge0 must be < edge1 + IN1 min1() + { + return (std::numeric_limits::min)(); + } + + IN1 max1() + { + return (std::numeric_limits::max)() / IN1(8000.0f); + } + + IN2 min2() + { + return IN3(1) + ((std::numeric_limits::max)() / IN2(4000.0f)); + } + + IN2 max2() + { + return (std::numeric_limits::max)() / IN2(2000.0f); + } + + bool use_ulp() + { + return false; + } +}; + +// floatn sign(floatn t) +template +struct common_func_sign : public unary_func +{ + std::string str() + { + return "sign"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x) + { + static_assert( + std::is_same::value, + "All types must be the same" + ); + if(x == IN1(-0.0f)) + { + return IN1(-0.0f); + } + if(x == IN1(+0.0f)) + { + return IN1(+0.0f); + } + if(x > IN1(0.0f)) + { + return IN1(1.0f); + } + return IN1(-1.0f); + } + + bool use_ulp() + { + return false; + } + + float ulp() + { + return 0.0f; + } + + std::vector in_special_cases() + { + return { -0.0f, +0.0f }; + } +}; + +AUTO_TEST_CASE(test_common_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // floatn clamp(floatn x, floatn min, floatn max) + TEST_TERNARY_FUNC_MACRO((common_func_clamp())) + + // floatn degrees(floatn t) + TEST_UNARY_FUNC_MACRO((common_func_degrees())) + + // floatn max(floatn x, floatn y); + TEST_BINARY_FUNC_MACRO((common_func_max())) + + // floatn min(floatn x, floatn y); + TEST_BINARY_FUNC_MACRO((common_func_min())) + + // floatn mix(floatn x, floatn y, floatn a); + TEST_TERNARY_FUNC_MACRO((common_func_mix())) + + // floatn radians(floatn t) + TEST_UNARY_FUNC_MACRO((common_func_radians())) + + // floatn step(floatn edge, floatn x) + TEST_BINARY_FUNC_MACRO((common_func_step())) + + // floatn smoothstep(floatn edge0, floatn edge1, floatn x) + TEST_TERNARY_FUNC_MACRO((common_func_smoothstep())) + + // floatn sign(floatn t); + TEST_UNARY_FUNC_MACRO((common_func_sign())) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_COMMON_FUNCS_COMMON_FUNCS_HPP diff --git a/test_conformance/clcpp/common_funcs/main.cpp b/test_conformance/clcpp/common_funcs/main.cpp new file mode 100644 index 00000000..ff9443ec --- /dev/null +++ b/test_conformance/clcpp/common_funcs/main.cpp @@ -0,0 +1,48 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include + +#include "../common.hpp" + +#include "common_funcs.hpp" + +int main(int argc, const char *argv[]) +{ + // Check if cl_float (float) and cl_double (double) fulfill the requirements of + // IEC 559 (IEEE 754) standard. This is required for the tests to run correctly. + if(!std::numeric_limits::is_iec559) + { + RETURN_ON_ERROR_MSG(-1, + "cl_float (float) does not fulfill the requirements of IEC 559 (IEEE 754) standard. " + "Tests won't run correctly." + ); + } + if(!std::numeric_limits::is_iec559) + { + RETURN_ON_ERROR_MSG(-1, + "cl_double (double) does not fulfill the requirements of IEC 559 (IEEE 754) standard. " + "Tests won't run correctly." + ); + } + + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/convert/CMakeLists.txt b/test_conformance/clcpp/convert/CMakeLists.txt new file mode 100644 index 00000000..4fb956e5 --- /dev/null +++ b/test_conformance/clcpp/convert/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_CONVERT) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/convert/convert_cast.hpp b/test_conformance/clcpp/convert/convert_cast.hpp new file mode 100644 index 00000000..81fcca63 --- /dev/null +++ b/test_conformance/clcpp/convert/convert_cast.hpp @@ -0,0 +1,309 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_CONVERT_CONVERT_CAST_HPP +#define TEST_CONFORMANCE_CLCPP_CONVERT_CONVERT_CAST_HPP + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#include + + +enum class rounding_mode +{ + def, + /*rte, not implemented here */ + rtz, + rtp, + rtn +}; + +enum class saturate { def, off, on }; + +std::string rounding_mode_name(rounding_mode rmode) +{ + switch (rmode) + { + case rounding_mode::rtz: return "rtz"; + case rounding_mode::rtp: return "rtp"; + case rounding_mode::rtn: return "rtn"; + default: return ""; + } +} + +std::string saturate_name(saturate smode) +{ + switch (smode) + { + case saturate::off: return "off"; + case saturate::on: return "on"; + default: return ""; + } +} + +template +T clamp(T x, T a, T b) +{ + return (std::min)(b, (std::max)(a, x)); +} + +template +struct convert_cast : public unary_func +{ + static_assert(vector_size::value == vector_size::value, "The operand and result type must have the same number of elements"); + + typedef typename scalar_type::type in_scalar_type; + typedef typename scalar_type::type out_scalar_type; + + in_scalar_type in_min; + in_scalar_type in_max; + rounding_mode rmode; + saturate smode; + + convert_cast(in_scalar_type min, in_scalar_type max, rounding_mode rmode, saturate smode) + : in_min(min), in_max(max), rmode(rmode), smode(smode) + { + } + + std::string str() + { + return "convert_cast"; + } + + std::string headers() + { + return "#include \n"; + } + + IN1 min1() + { + return detail::def_limit(in_min); + } + + IN1 max1() + { + return detail::def_limit(in_max); + } + + OUT1 operator()(const IN1& x) + { + OUT1 y; + for (size_t i = 0; i < vector_size::value; i++) + { + in_scalar_type v; + if (smode == saturate::on) + v = clamp(x.s[i], + static_cast((std::numeric_limits::min)()), + static_cast((std::numeric_limits::max)()) + ); + else + v = x.s[i]; + + if (std::is_integral::value) + { + switch (rmode) + { + case rounding_mode::rtp: + y.s[i] = static_cast(std::ceil(v)); + break; + case rounding_mode::rtn: + y.s[i] = static_cast(std::floor(v)); + break; + default: + y.s[i] = static_cast(v); + } + } + else + { + y.s[i] = static_cast(v); + } + } + return y; + } +}; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template +std::string generate_kernel_convert_cast(func_type func) +{ + std::string in1_value = "input[gid]"; + std::string function_call = "convert_" + type_name(); + if (func.smode == saturate::on) + function_call += "_sat"; + if (func.rmode != rounding_mode::def) + function_call += "_" + rounding_mode_name(func.rmode); + function_call += "(" + in1_value + ")"; + return + "__kernel void test_" + func.str() + "(global " + type_name() + " *input, global " + type_name() + " *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = " + function_call + ";\n" + "}\n"; +} +#else +template +std::string generate_kernel_convert_cast(func_type func) +{ + std::string headers = func.headers(); + std::string in1_value = "input[gid]"; + std::string function_call = "convert_cast<" + type_name(); + if (func.rmode != rounding_mode::def) + function_call += ", rounding_mode::" + rounding_mode_name(func.rmode); + if (func.smode != saturate::def) + function_call += ", saturate::" + saturate_name(func.smode); + function_call += ">(" + in1_value + ")"; + return + "" + func.defs() + + "" + headers + + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_" + func.str() + "(global_ptr<" + type_name() + "[]> input," + "global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = " + function_call + ";\n" + "}\n"; +} +#endif + +template +int test_convert_cast_func(cl_device_id device, cl_context context, cl_command_queue queue, size_t count, convert_cast_op op) +{ + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t work_size[1]; + int error; + + typedef typename convert_cast_op::in_type INPUT; + typedef typename convert_cast_op::out_type OUTPUT; + + // Don't run test for unsupported types + if (!(type_supported(device) && type_supported(device))) + { + return CL_SUCCESS; + } + + std::string code_str = generate_kernel_convert_cast(op); + std::string kernel_name("test_"); kernel_name += op.str(); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name, "-cl-std=CL2.0", false); + RETURN_ON_ERROR(error) +#else + error = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(error) +#endif + + std::vector input = generate_input(count, op.min1(), op.max1(), op.in_special_cases()); + std::vector output = generate_output(count); + + buffers[0] = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(INPUT) * input.size(), NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + buffers[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(OUTPUT) * output.size(), NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(INPUT) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + work_size[0] = count; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + error = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(OUTPUT) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + if (!verify_unary(input, output, op)) + { + RETURN_ON_ERROR_MSG(-1, "test_%s %s(%s) failed", op.str().c_str(), type_name().c_str(), type_name().c_str()); + } + log_info("test_%s %s(%s) passed\n", op.str().c_str(), type_name().c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; +} + + +AUTO_TEST_CASE(test_convert_cast) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + +#define TEST_CONVERT_CAST_MACRO(OP) \ + last_error = test_convert_cast_func( \ + device, context, queue, n_elems, OP \ + ); \ + CHECK_ERROR(last_error) \ + error |= last_error; + + // No-op + TEST_CONVERT_CAST_MACRO((convert_cast(-100.0f, +100.0f, rounding_mode::rtn, saturate::def))) + TEST_CONVERT_CAST_MACRO((convert_cast(0, 255, rounding_mode::def, saturate::def))) + + // int to int + TEST_CONVERT_CAST_MACRO((convert_cast(40000, 40000, rounding_mode::def, saturate::on))) + TEST_CONVERT_CAST_MACRO((convert_cast(0, 127, rounding_mode::def, saturate::off))) + TEST_CONVERT_CAST_MACRO((convert_cast(-100, 100, rounding_mode::def, saturate::off))) + + // float to int + TEST_CONVERT_CAST_MACRO((convert_cast(-100.0f, +400.0f, rounding_mode::def, saturate::on))) + TEST_CONVERT_CAST_MACRO((convert_cast(-127.0, +127.0, rounding_mode::rtp, saturate::off))) + TEST_CONVERT_CAST_MACRO((convert_cast(-1000.0f, +10000.0f, rounding_mode::rtp, saturate::on))) + TEST_CONVERT_CAST_MACRO((convert_cast(-10000.0f, +70000.0f, rounding_mode::rtn, saturate::on))) + + // int to float + TEST_CONVERT_CAST_MACRO((convert_cast(0, 12345, rounding_mode::def, saturate::def))) + TEST_CONVERT_CAST_MACRO((convert_cast(-1000000, +1000000, rounding_mode::rtz, saturate::def))) + +#undef TEST_CONVERT_CAST_MACRO + + if (error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_CONVERT_CONVERT_CAST_HPP diff --git a/test_conformance/clcpp/convert/main.cpp b/test_conformance/clcpp/convert/main.cpp new file mode 100644 index 00000000..979156bd --- /dev/null +++ b/test_conformance/clcpp/convert/main.cpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "convert_cast.hpp" + + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/device_queue/CMakeLists.txt b/test_conformance/clcpp/device_queue/CMakeLists.txt new file mode 100644 index 00000000..d9260c2c --- /dev/null +++ b/test_conformance/clcpp/device_queue/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_DEVICE_QUEUE) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/device_queue/main.cpp b/test_conformance/clcpp/device_queue/main.cpp new file mode 100644 index 00000000..5d754b78 --- /dev/null +++ b/test_conformance/clcpp/device_queue/main.cpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "test_enqueue.hpp" + + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/device_queue/test_enqueue.hpp b/test_conformance/clcpp/device_queue/test_enqueue.hpp new file mode 100644 index 00000000..f5d4e6dc --- /dev/null +++ b/test_conformance/clcpp/device_queue/test_enqueue.hpp @@ -0,0 +1,699 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_DEVICE_QUEUE_TEST_ENQUEUE_HPP +#define TEST_CONFORMANCE_CLCPP_DEVICE_QUEUE_TEST_ENQUEUE_HPP + +#include +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" + + +namespace test_enqueue { + +struct test_options +{ + int test; +}; + +struct output_type +{ + cl_int enqueue_kernel1_success; + cl_int enqueue_kernel2_success; + cl_int enqueue_kernel3_success; + cl_int enqueue_marker_success; + cl_int event1_is_valid; + cl_int event2_is_valid; + cl_int event3_is_valid; + cl_int user_event1_is_valid; + cl_int user_event2_is_valid; + cl_int values[10000]; +}; + +const std::string source_common = R"( +struct output_type +{ + int enqueue_kernel1_success; + int enqueue_kernel2_success; + int enqueue_kernel3_success; + int enqueue_marker_success; + int event1_is_valid; + int event2_is_valid; + int event3_is_valid; + int user_event1_is_valid; + int user_event2_is_valid; + int values[10000]; +}; +)"; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +std::string generate_source(test_options options) +{ + std::stringstream s; + s << source_common; + if (options.test == 0) + { + s << R"( + kernel void test(queue_t queue, global struct output_type *output) + { + const ulong gid = get_global_id(0); + + if (gid != 0) + return; + + output->enqueue_kernel2_success = 1; + output->enqueue_kernel3_success = 1; + output->enqueue_marker_success = 1; + output->event2_is_valid = 1; + output->event3_is_valid = 1; + output->user_event1_is_valid = 1; + output->user_event2_is_valid = 1; + + queue_t default_queue = get_default_queue(); + + ndrange_t ndrange1 = ndrange_1D(get_global_size(0)); + clk_event_t event1; + int status1 = enqueue_kernel(default_queue, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange1, 0, NULL, &event1, + ^{ + const ulong gid = get_global_id(0); + output->values[gid] = 1; + }); + output->enqueue_kernel1_success = status1 == CLK_SUCCESS; + output->event1_is_valid = is_valid_event(event1); + + release_event(event1); + } + )"; + } + else if (options.test == 1) + { + s << R"( + kernel void test(queue_t queue, global struct output_type *output) + { + const ulong gid = get_global_id(0); + + if (gid != 0) + return; + + output->enqueue_kernel3_success = 1; + output->enqueue_marker_success = 1; + output->event3_is_valid = 1; + output->user_event1_is_valid = 1; + output->user_event2_is_valid = 1; + + queue_t default_queue = get_default_queue(); + + ndrange_t ndrange1 = ndrange_1D(get_global_size(0) / 2); + clk_event_t event1; + int status1 = enqueue_kernel(default_queue, CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP, ndrange1, 0, NULL, &event1, + ^{ + const ulong gid = get_global_id(0); + output->values[gid * 2] = 1; + }); + output->enqueue_kernel1_success = status1 == CLK_SUCCESS; + output->event1_is_valid = is_valid_event(event1); + + ndrange_t ndrange2 = ndrange_1D(1, get_global_size(0) / 2, 1); + clk_event_t event2; + int status2 = enqueue_kernel(queue, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange2, 1, &event1, &event2, + ^{ + const ulong gid = get_global_id(0); + output->values[(gid - 1) * 2 + 1] = 1; + }); + output->enqueue_kernel2_success = status2 == CLK_SUCCESS; + output->event2_is_valid = is_valid_event(event2); + + release_event(event1); + release_event(event2); + } + )"; + } + else if (options.test == 2) + { + s << R"( + kernel void test(queue_t queue, global struct output_type *output) + { + const ulong gid = get_global_id(0); + + if (gid != 0) + return; + + output->enqueue_marker_success = 1; + output->event3_is_valid = 1; + output->enqueue_kernel3_success = 1; + + queue_t default_queue = get_default_queue(); + + clk_event_t user_event1 = create_user_event(); + retain_event(user_event1); + output->user_event1_is_valid = is_valid_event(user_event1); + + ndrange_t ndrange1 = ndrange_1D(get_global_size(0) / 2); + clk_event_t event1; + int status1 = enqueue_kernel(queue, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange1, 1, &user_event1, &event1, + ^{ + const ulong gid = get_global_id(0); + output->values[gid * 2] = 1; + }); + output->enqueue_kernel1_success = status1 == CLK_SUCCESS; + output->event1_is_valid = is_valid_event(event1); + release_event(user_event1); + + clk_event_t user_event2 = create_user_event(); + output->user_event2_is_valid = is_valid_event(user_event2); + + clk_event_t events[2]; + events[0] = user_event2; + events[1] = user_event1; + + ndrange_t ndrange2 = ndrange_1D(1, get_global_size(0) / 2, get_local_size(0)); + clk_event_t event2; + int status2 = enqueue_kernel(default_queue, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange2, 2, events, &event2, + ^(local void *p0, local void *p1, local void *p2) { + const ulong gid = get_global_id(0); + const ulong lid = get_local_id(0); + local int2 *l0 = (local int2 *)p0; + local int *l1 = (local int *)p1; + local int *l2 = (local int *)p2; + l1[get_local_size(0) - lid - 1] = gid > 0 ? 1 : 0; + work_group_barrier(CLK_LOCAL_MEM_FENCE); + if (lid < 5) l0[lid] = (int2)(3, 4); + if (lid < 3) l2[lid] = 5; + work_group_barrier(CLK_LOCAL_MEM_FENCE); + output->values[(gid - 1) * 2 + 1] = min(l1[lid], min(l0[0].x, l2[0])); + }, sizeof(int2) * 5, sizeof(int) * get_local_size(0), sizeof(int) * 3); + output->enqueue_kernel2_success = status2 == CLK_SUCCESS; + output->event2_is_valid = is_valid_event(event2); + + set_user_event_status(user_event1, CL_COMPLETE); + set_user_event_status(user_event2, CL_COMPLETE); + + release_event(user_event1); + release_event(user_event2); + release_event(event1); + release_event(event2); + } + )"; + } + else if (options.test == 3) + { + s << R"( + kernel void test(queue_t queue, global struct output_type *output) + { + const ulong gid = get_global_id(0); + + if (gid != 0) + return; + + output->user_event2_is_valid = 1; + + queue_t default_queue = get_default_queue(); + + ndrange_t ndrange1 = ndrange_1D(get_global_size(0) / 2); + clk_event_t event1; + int status1 = enqueue_kernel(default_queue, CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP, ndrange1, 0, NULL, &event1, + ^{ + const ulong gid = get_global_id(0); + output->values[gid * 2] = 20; + }); + output->enqueue_kernel1_success = status1 == CLK_SUCCESS; + output->event1_is_valid = is_valid_event(event1); + + ndrange_t ndrange2 = ndrange_1D(1, get_global_size(0) / 2, 1); + clk_event_t event2; + int status2 = enqueue_kernel(queue, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange2, 0, NULL, &event2, + ^{ + const ulong gid = get_global_id(0); + output->values[(gid - 1) * 2 + 1] = 20; + }); + output->enqueue_kernel2_success = status2 == CLK_SUCCESS; + output->event2_is_valid = is_valid_event(event2); + + clk_event_t user_event1 = create_user_event(); + output->user_event1_is_valid = is_valid_event(user_event1); + + clk_event_t events[3]; + events[0] = event2; + events[1] = user_event1; + events[2] = event1; + + clk_event_t event3; + int status3 = enqueue_marker(queue, 3, events, &event3); + output->enqueue_marker_success = status3 == CLK_SUCCESS; + output->event3_is_valid = is_valid_event(event3); + + int status4 = enqueue_kernel(default_queue, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange_1D(get_global_size(0)), 1, &event3, NULL, + ^{ + const ulong gid = get_global_id(0); + output->values[gid] /= 20; + }); + output->enqueue_kernel3_success = status4 == CLK_SUCCESS; + + set_user_event_status(user_event1, CL_COMPLETE); + + release_event(user_event1); + release_event(event1); + release_event(event2); + release_event(event3); + } + )"; + } + + return s.str(); +} +#else +std::string generate_source(test_options options) +{ + std::stringstream s; + s << R"( + #include + #include + #include + #include + #include + using namespace cl; + )"; + + s << source_common; + if (options.test == 0) + { + s << R"( + kernel void test(device_queue queue, global *output) + { + const ulong gid = get_global_id(0); + + if (gid != 0) + return; + + output->enqueue_kernel2_success = 1; + output->enqueue_kernel3_success = 1; + output->enqueue_marker_success = 1; + output->event2_is_valid = 1; + output->event3_is_valid = 1; + output->user_event1_is_valid = 1; + output->user_event2_is_valid = 1; + + device_queue default_queue = get_default_device_queue(); + + ndrange ndrange1(get_global_size(0)); + event event1; + enqueue_status status1 = default_queue.enqueue_kernel(enqueue_policy::no_wait, 0, nullptr, &event1, ndrange1, + [](global *output) { + const ulong gid = get_global_id(0); + output->values[gid] = 1; + }, output); + output->enqueue_kernel1_success = status1 == enqueue_status::success; + output->event1_is_valid = event1.is_valid(); + + event1.release(); + } + )"; + } + else if (options.test == 1) + { + s << R"( + kernel void test(device_queue queue, global *output) + { + const ulong gid = get_global_id(0); + + if (gid != 0) + return; + + output->enqueue_kernel3_success = 1; + output->enqueue_marker_success = 1; + output->event3_is_valid = 1; + output->user_event1_is_valid = 1; + output->user_event2_is_valid = 1; + + device_queue default_queue = get_default_device_queue(); + + ndrange ndrange1(get_global_size(0) / 2); + event event1; + enqueue_status status1 = default_queue.enqueue_kernel(enqueue_policy::wait_work_group, 0, nullptr, &event1, ndrange1, + [](global *output) { + const ulong gid = get_global_id(0); + output->values[gid * 2] = 1; + }, output); + output->enqueue_kernel1_success = status1 == enqueue_status::success; + output->event1_is_valid = event1.is_valid(); + + ndrange ndrange2(1, get_global_size(0) / 2, 1); + event event2; + enqueue_status status2 = queue.enqueue_kernel(enqueue_policy::wait_kernel, 1, &event1, &event2, ndrange2, + [](global *output) { + const ulong gid = get_global_id(0); + output->values[(gid - 1) * 2 + 1] = 1; + }, output); + output->enqueue_kernel2_success = status2 == enqueue_status::success; + output->event2_is_valid = event2.is_valid(); + + event1.release(); + event2.release(); + } + )"; + } + else if (options.test == 2) + { + s << R"( + kernel void test(device_queue queue, global *output) + { + const ulong gid = get_global_id(0); + + if (gid != 0) + return; + + output->enqueue_marker_success = 1; + output->event3_is_valid = 1; + output->enqueue_kernel3_success = 1; + + device_queue default_queue = get_default_device_queue(); + + event user_event1 = make_user_event(); + user_event1.retain(); + output->user_event1_is_valid = user_event1.is_valid(); + + ndrange ndrange1(get_global_size(0) / 2); + event event1; + enqueue_status status1 = queue.enqueue_kernel(enqueue_policy::wait_kernel, 1, &user_event1, &event1, ndrange1, + [](global *output){ + const ulong gid = get_global_id(0); + output->values[gid * 2] = 1; + }, output); + output->enqueue_kernel1_success = status1 == enqueue_status::success; + output->event1_is_valid = event1.is_valid(); + user_event1.release(); + + event user_event2 = make_user_event(); + output->user_event2_is_valid = user_event2.is_valid(); + + event events[2]; + events[0] = user_event2; + events[1] = user_event1; + + ndrange ndrange2(1, get_global_size(0) / 2, get_local_size(0)); + event event2; + enqueue_status status2 = default_queue.enqueue_kernel(enqueue_policy::no_wait, 2, events, &event2, ndrange2, + [](global *output, local_ptr l0, local_ptr l1, local_ptr l2) { + const ulong gid = get_global_id(0); + const ulong lid = get_local_id(0); + l1[get_local_size(0) - lid - 1] = gid > 0 ? 1 : 0; + work_group_barrier(mem_fence::local); + if (lid < 5) l0[lid] = int2(3, 4); + if (lid < 3) l2[lid] = 5; + work_group_barrier(mem_fence::local); + output->values[(gid - 1) * 2 + 1] = min(l1[lid], min(l0[0].x, l2[0])); + }, output, local_ptr::size_type(5), local_ptr::size_type(get_local_size(0)), local_ptr::size_type(3)); + output->enqueue_kernel2_success = status2 == enqueue_status::success; + output->event2_is_valid = event2.is_valid(); + + user_event1.set_status(event_status::complete); + user_event2.set_status(event_status::complete); + + user_event1.release(); + user_event2.release(); + event1.release(); + event2.release(); + } + )"; + } + else if (options.test == 3) + { + s << R"( + kernel void test(device_queue queue, global *output) + { + const ulong gid = get_global_id(0); + + if (gid != 0) + return; + + output->user_event2_is_valid = 1; + + device_queue default_queue = get_default_device_queue(); + + ndrange ndrange1(get_global_size(0) / 2); + event event1; + enqueue_status status1 = default_queue.enqueue_kernel(enqueue_policy::wait_work_group, 0, nullptr, &event1, ndrange1, + [](global *output) { + const ulong gid = get_global_id(0); + output->values[gid * 2] = 20; + }, output); + output->enqueue_kernel1_success = status1 == enqueue_status::success; + output->event1_is_valid = event1.is_valid(); + + ndrange ndrange2(1, get_global_size(0) / 2, 1); + event event2; + enqueue_status status2 = queue.enqueue_kernel(enqueue_policy::wait_kernel, 0, nullptr, &event2, ndrange2, + [](global *output) { + const ulong gid = get_global_id(0); + output->values[(gid - 1) * 2 + 1] = 20; + }, output); + output->enqueue_kernel2_success = status2 == enqueue_status::success; + output->event2_is_valid = event2.is_valid(); + + event user_event1 = make_user_event(); + output->user_event1_is_valid = user_event1.is_valid(); + + event events[3]; + events[0] = event2; + events[1] = user_event1; + events[2] = event1; + + event event3; + enqueue_status status3 = queue.enqueue_marker(3, events, &event3); + output->enqueue_marker_success = status3 == enqueue_status::success; + output->event3_is_valid = event3.is_valid(); + + enqueue_status status4 = default_queue.enqueue_kernel(enqueue_policy::no_wait, 1, &event3, nullptr, ndrange(get_global_size(0)), + [](global *output) { + const ulong gid = get_global_id(0); + output->values[gid] /= 20; + }, output); + output->enqueue_kernel3_success = status4 == enqueue_status::success; + + user_event1.set_status(event_status::complete); + + user_event1.release(); + event1.release(); + event2.release(); + event3.release(); + } + )"; + } + + return s.str(); +} +#endif + +int test(cl_device_id device, cl_context context, cl_command_queue queue, test_options options) +{ + int error = CL_SUCCESS; + + cl_program program; + cl_kernel kernel; + + std::string kernel_name = "test"; + std::string source = generate_source(options); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name, "-cl-std=CL2.0", false + ); + RETURN_ON_ERROR(error) +// Normal run +#else + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) +#endif + + cl_uint max_queues; + error = clGetDeviceInfo(device, CL_DEVICE_MAX_ON_DEVICE_QUEUES, sizeof(cl_uint), &max_queues, NULL); + RETURN_ON_CL_ERROR(error, "clGetDeviceInfo") + + cl_uint max_events; + error = clGetDeviceInfo(device, CL_DEVICE_MAX_ON_DEVICE_EVENTS, sizeof(cl_uint), &max_events, NULL); + RETURN_ON_CL_ERROR(error, "clGetDeviceInfo") + + cl_command_queue device_queue1 = NULL; + cl_command_queue device_queue2 = NULL; + + cl_queue_properties queue_properties1[] = + { + CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT, + 0 + }; + device_queue1 = clCreateCommandQueueWithProperties(context, device, queue_properties1, &error); + RETURN_ON_CL_ERROR(error, "clCreateCommandQueueWithProperties") + + if (max_queues > 1) + { + cl_queue_properties queue_properties2[] = + { + CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE, + 0 + }; + device_queue2 = clCreateCommandQueueWithProperties(context, device, queue_properties2, &error); + RETURN_ON_CL_ERROR(error, "clCreateCommandQueueWithProperties") + } + + cl_mem output_buffer; + output_buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(output_type), NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(cl_command_queue), device_queue2 != NULL ? &device_queue2 : &device_queue1); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 1, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + const char pattern = 0; + error = clEnqueueFillBuffer(queue, output_buffer, &pattern, sizeof(pattern), 0, sizeof(output_type), 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueFillBuffer") + + size_t max_work_group_size; + error = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t), &max_work_group_size, NULL); + RETURN_ON_CL_ERROR(error, "clGetDeviceInfo") + + const size_t local_size = (std::min)((size_t)256, max_work_group_size); + const size_t global_size = 10000 / local_size * local_size; + const size_t count = global_size; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, &local_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + output_type output; + error = clEnqueueReadBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(output_type), + static_cast(&output), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + if (!output.enqueue_kernel1_success) + { + RETURN_ON_ERROR_MSG(-1, "enqueue_kernel did not succeed") + } + if (!output.enqueue_kernel2_success) + { + RETURN_ON_ERROR_MSG(-1, "enqueue_kernel did not succeed") + } + if (!output.enqueue_kernel3_success) + { + RETURN_ON_ERROR_MSG(-1, "enqueue_kernel did not succeed") + } + if (!output.enqueue_marker_success) + { + RETURN_ON_ERROR_MSG(-1, "enqueue_marker did not succeed") + } + if (!output.event1_is_valid) + { + RETURN_ON_ERROR_MSG(-1, "event1 is not valid") + } + if (!output.event2_is_valid) + { + RETURN_ON_ERROR_MSG(-1, "event2 is not valid") + } + if (!output.event3_is_valid) + { + RETURN_ON_ERROR_MSG(-1, "event3 is not valid") + } + if (!output.user_event1_is_valid) + { + RETURN_ON_ERROR_MSG(-1, "user_event1 is not valid") + } + if (!output.user_event2_is_valid) + { + RETURN_ON_ERROR_MSG(-1, "user_event2 is not valid") + } + + for (size_t i = 0; i < count; i++) + { + const cl_int result = output.values[i]; + const cl_int expected = 1; + + if (result != expected) + { + RETURN_ON_ERROR_MSG(-1, + "kernel did not return correct value. Expected: %s, got: %s", + format_value(expected).c_str(), format_value(result).c_str() + ) + } + } + + clReleaseMemObject(output_buffer); + clReleaseCommandQueue(device_queue1); + if (device_queue2 != NULL) + clReleaseCommandQueue(device_queue2); + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; +} + +AUTO_TEST_CASE(test_enqueue_one_kernel) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + test_options options; + options.test = 0; + return test(device, context, queue, options); +} + +AUTO_TEST_CASE(test_enqueue_two_kernels) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + test_options options; + options.test = 1; + return test(device, context, queue, options); +} + +AUTO_TEST_CASE(test_enqueue_user_events_and_locals) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + test_options options; + options.test = 2; + return test(device, context, queue, options); +} + +AUTO_TEST_CASE(test_enqueue_marker) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + test_options options; + options.test = 3; + return test(device, context, queue, options); +} + +} // namespace + +#endif // TEST_CONFORMANCE_CLCPP_DEVICE_QUEUE_TEST_ENQUEUE_HPP diff --git a/test_conformance/clcpp/funcs_test_utils.hpp b/test_conformance/clcpp/funcs_test_utils.hpp new file mode 100644 index 00000000..e839231c --- /dev/null +++ b/test_conformance/clcpp/funcs_test_utils.hpp @@ -0,0 +1,72 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_FUNCS_TEST_UTILS_HPP +#define TEST_CONFORMANCE_CLCPP_FUNCS_TEST_UTILS_HPP + +// This file contains helper classes and functions for testing various unary, binary +// and ternary OpenCL functions (for example cl::abs(x) or cl::abs_diff(x, y)), +// as well as other helper functions/classes. + +#include "common.hpp" + +#define TEST_UNARY_FUNC_MACRO(TEST_CLASS) \ + last_error = test_unary_func( \ + device, context, queue, n_elems, TEST_CLASS \ + ); \ + CHECK_ERROR(last_error) \ + error |= last_error; + +#define TEST_BINARY_FUNC_MACRO(TEST_CLASS) \ + last_error = test_binary_func( \ + device, context, queue, n_elems, TEST_CLASS \ + ); \ + CHECK_ERROR(last_error) \ + error |= last_error; + +#define TEST_TERNARY_FUNC_MACRO(TEST_CLASS) \ + last_error = test_ternary_func( \ + device, context, queue, n_elems, TEST_CLASS \ + ); \ + CHECK_ERROR(last_error) \ + error |= last_error; + +#include "utils_test/compare.hpp" +#include "utils_test/generate_inputs.hpp" + +// HOWTO: +// +// unary_func, binary_func, ternary_func - base classes wrapping OpenCL functions that +// you want to test. +// +// To create a wrapper class for given function, you need to create a class derived from correct +// base class (unary_func, binary_func, ternary_func), and define: +// +// * std::string str() method which should return class name in OpenCL ("abs", "abs_diff"), +// * operator(x), operator(x, y) or operator(x,y,z) depending on arity of the function you wish +// to test, method should work exactly as the tested function works in OpenCL +// * if it's needed you can overload min1, max1, min2, max2, min3, max3 methods with returns min +// and max values that can be generated for given input (function argument) [required for vec +// arguments], +// * if you want to use vector arguments (for example: cl_int2, cl_ulong16), you should look at +// how int_func_clamp<> is implemented in integer_funcs/numeric_funcs.hpp. +// +// To see how you should use class you've just created see AUTO_TEST_CASE(test_int_numeric_funcs) +// in integer_funcs/numeric_funcs.hpp. +#include "utils_test/unary.hpp" +#include "utils_test/binary.hpp" +#include "utils_test/ternary.hpp" + +#endif // TEST_CONFORMANCE_CLCPP_FUNCS_TEST_UTILS_HPP diff --git a/test_conformance/clcpp/geometric_funcs/CMakeLists.txt b/test_conformance/clcpp/geometric_funcs/CMakeLists.txt new file mode 100644 index 00000000..3314863e --- /dev/null +++ b/test_conformance/clcpp/geometric_funcs/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_GEOMETRIC_FUNCS) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/geometric_funcs/fast_geometric_funcs.hpp b/test_conformance/clcpp/geometric_funcs/fast_geometric_funcs.hpp new file mode 100644 index 00000000..c1797288 --- /dev/null +++ b/test_conformance/clcpp/geometric_funcs/fast_geometric_funcs.hpp @@ -0,0 +1,229 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_GEOMETRIC_FUNCS_FAST_GEOMETRIC_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_GEOMETRIC_FUNCS_FAST_GEOMETRIC_FUNCS_HPP + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#include + +// float fast_distance(float4 p0, float4 p1); +struct geometric_func_fast_distance : public binary_func +{ + + std::string str() + { + return "fast_distance"; + } + + std::string headers() + { + return "#include \n"; + } + + cl_float operator()(const cl_float4& p0, const cl_float4& p1) + { + cl_double r = 0.0f; + cl_double t; + for(size_t i = 0; i < 4; i++) + { + t = static_cast(p0.s[i]) - static_cast(p1.s[i]); + r += t * t; + } + return std::sqrt(r); + } + + cl_float4 min1() + { + return detail::def_limit(-512.0f); + } + + cl_float4 max1() + { + return detail::def_limit(512.0f); + } + + cl_float4 min2() + { + return detail::def_limit(-512.0f); + } + + cl_float4 max2() + { + return detail::def_limit(512.0f); + } + + cl_double delta(const cl_float4& p0, const cl_float4& p1, const cl_float& expected) + { + (void) p0; (void) p1; + return 0.01f * expected; + } + + float ulp() + { + return + 8192.0f + // error in sqrt + (1.5f * 4.0f) + // cumulative error for multiplications + (0.5f * 3.0f); // cumulative error for additions + } +}; + +// float fast_length(float4 p); +struct geometric_func_fast_length : public unary_func +{ + std::string str() + { + return "fast_length"; + } + + std::string headers() + { + return "#include \n"; + } + + cl_float operator()(const cl_float4& p) + { + cl_double r = 0.0f; + for(size_t i = 0; i < 4; i++) + { + r += static_cast(p.s[i]) * static_cast(p.s[i]); + } + return std::sqrt(r); + } + + cl_float4 min1() + { + return detail::def_limit(-512.0f); + } + + cl_float4 max1() + { + return detail::def_limit(512.0f); + } + + cl_double delta(const cl_float4& p, const cl_float& expected) + { + (void) p; + return 0.01f * expected; + } + + float ulp() + { + return + 8192.0f + // error in sqrt + 0.5f * // effect on e of taking sqrt( x + e ) + ((0.5f * 4.0f) + // cumulative error for multiplications + (0.5f * 3.0f)); // cumulative error for additions + } +}; + +// float4 fast_normalize(float4 p); +struct geometric_func_fast_normalize : public unary_func +{ + std::string str() + { + return "fast_normalize"; + } + + std::string headers() + { + return "#include \n"; + } + + cl_float4 operator()(const cl_float4& p) + { + cl_double t = 0.0f; + cl_float4 r; + for(size_t i = 0; i < 4; i++) + { + t += static_cast(p.s[i]) * static_cast(p.s[i]); + } + + if(t == 0.0f) + { + for(size_t i = 0; i < 4; i++) + { + r.s[i] = 0.0f; + } + return r; + } + + t = std::sqrt(t); + for(size_t i = 0; i < 4; i++) + { + r.s[i] = static_cast(p.s[i]) / t; + } + return r; + } + + cl_float4 min1() + { + return detail::def_limit(-512.0f); + } + + cl_float4 max1() + { + return detail::def_limit(512.0f); + } + + std::vector in_special_cases() + { + return { + {0.0f, 0.0f, 0.0f, 0.0f} + }; + } + + + cl_double4 delta(const cl_float4& p, const cl_float4& expected) + { + (void) p; + auto e = detail::make_value(0.01f); + return detail::multiply(e, expected); + } + + float ulp() + { + return + 8192.5f + // error in rsqrt + error in multiply + (0.5f * 4.0f) + // cumulative error for multiplications + (0.5f * 3.0f); // cumulative error for additions + } +}; + +AUTO_TEST_CASE(test_fast_geometric_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // float fast_distance(float4 p0, float4 p1) + TEST_BINARY_FUNC_MACRO((geometric_func_fast_distance())) + + // float fast_length(float4 p) + TEST_UNARY_FUNC_MACRO((geometric_func_fast_length())) + + // float4 fast_normalize(float4 p) + TEST_UNARY_FUNC_MACRO((geometric_func_fast_normalize())) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_GEOMETRIC_FUNCS_FAST_GEOMETRIC_FUNCS_HPP diff --git a/test_conformance/clcpp/geometric_funcs/geometric_funcs.hpp b/test_conformance/clcpp/geometric_funcs/geometric_funcs.hpp new file mode 100644 index 00000000..561f9e9b --- /dev/null +++ b/test_conformance/clcpp/geometric_funcs/geometric_funcs.hpp @@ -0,0 +1,389 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_GEOMETRIC_FUNCS_GEOMETRIC_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_GEOMETRIC_FUNCS_GEOMETRIC_FUNCS_HPP + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#include + +// float4 cross(float4 p0, float4 p1) +struct geometric_func_cross : public binary_func +{ + geometric_func_cross(cl_device_id device) + { + // On an embedded device w/ round-to-zero, 3 ulps is the worst-case tolerance for cross product + this->m_delta = 3.0f * CL_FLT_EPSILON; + // RTZ devices accrue approximately double the amount of error per operation. Allow for that. + if(get_default_rounding_mode(device) == CL_FP_ROUND_TO_ZERO) + { + this->m_delta *= 2.0f; + } + } + + std::string str() + { + return "cross"; + } + + std::string headers() + { + return "#include \n"; + } + + cl_float4 operator()(const cl_float4& p0, const cl_float4& p1) + { + cl_float4 r; + r.s[0] = (p0.s[1] * p1.s[2]) - (p0.s[2] * p1.s[1]); + r.s[1] = (p0.s[2] * p1.s[0]) - (p0.s[0] * p1.s[2]); + r.s[2] = (p0.s[0] * p1.s[1]) - (p0.s[1] * p1.s[0]); + r.s[3] = 0.0f; + return r; + } + + cl_float4 max1() + { + return detail::def_limit(1000.0f); + } + + cl_float4 max2() + { + return detail::def_limit(1000.0f); + } + + cl_float4 min1() + { + return detail::def_limit(-1000.0f); + } + + cl_float4 min2() + { + return detail::def_limit(-1000.0f); + } + + bool use_ulp() + { + return false; + } + + cl_double4 delta(const cl_float4& p0, const cl_float4& p1, const cl_float4& expected) + { + (void) p0; (void) p1; + auto e = detail::make_value(m_delta); + return detail::multiply(e, expected); + } + +private: + cl_double m_delta; +}; + +// float dot(float4 p0, float4 p1); +struct geometric_func_dot : public binary_func +{ + + std::string str() + { + return "dot"; + } + + std::string headers() + { + return "#include \n"; + } + + cl_float operator()(const cl_float4& p0, const cl_float4& p1) + { + cl_float r; + r = p0.s[0] * p1.s[0]; + r += p0.s[1] * p1.s[1]; + r += p0.s[2] * p1.s[2]; + r += p0.s[3] * p1.s[3]; + return r; + } + + cl_float4 max1() + { + return detail::def_limit(1000.0f); + } + + cl_float4 max2() + { + return detail::def_limit(1000.0f); + } + + cl_float4 min1() + { + return detail::def_limit(-1000.0f); + } + + cl_float4 min2() + { + return detail::def_limit(-1000.0f); + } + + bool use_ulp() + { + return false; + } + + cl_double delta(const cl_float4& p0, const cl_float4& p1, cl_float expected) + { + (void) p0; (void) p1; + return expected * ((4.0f + (4.0f - 1.0f)) * CL_FLT_EPSILON); + } +}; + +// float distance(float4 p0, float4 p1); +struct geometric_func_distance : public binary_func +{ + + std::string str() + { + return "distance"; + } + + std::string headers() + { + return "#include \n"; + } + + cl_float operator()(const cl_float4& p0, const cl_float4& p1) + { + cl_double r = 0.0f; + cl_double t; + for(size_t i = 0; i < 4; i++) + { + t = static_cast(p0.s[i]) - static_cast(p1.s[i]); + r += t * t; + } + return std::sqrt(r); + } + + cl_float4 max1() + { + return detail::def_limit(1000.0f); + } + + cl_float4 max2() + { + return detail::def_limit(1000.0f); + } + + cl_float4 min1() + { + return detail::def_limit(-1000.0f); + } + + cl_float4 min2() + { + return detail::def_limit(-1000.0f); + } + + float ulp() + { + return + 3.0f + // error in sqrt + (1.5f * 4.0f) + // cumulative error for multiplications + (0.5f * 3.0f); // cumulative error for additions + } +}; + +// float length(float4 p); +struct geometric_func_length : public unary_func +{ + + std::string str() + { + return "length"; + } + + std::string headers() + { + return "#include \n"; + } + + cl_float operator()(const cl_float4& p) + { + cl_double r = 0.0f; + for(size_t i = 0; i < 4; i++) + { + r += static_cast(p.s[i]) * static_cast(p.s[i]); + } + return std::sqrt(r); + } + + cl_float4 max1() + { + return detail::def_limit(1000.0f); + } + + cl_float4 min1() + { + return detail::def_limit(-1000.0f); + } + + float ulp() + { + return + 3.0f + // error in sqrt + 0.5f * // effect on e of taking sqrt( x + e ) + ((0.5f * 4.0f) + // cumulative error for multiplications + (0.5f * 3.0f)); // cumulative error for additions + } +}; + +// float4 normalize(float4 p); +struct geometric_func_normalize : public unary_func +{ + std::string str() + { + return "normalize"; + } + + std::string headers() + { + return "#include \n"; + } + + cl_float4 operator()(const cl_float4& p) + { + cl_double t = 0.0f; + cl_float4 r; + + // normalize( v ) returns a vector full of NaNs if any element is a NaN. + for(size_t i = 0; i < 4; i++) + { + if((std::isnan)(p.s[i])) + { + for(size_t j = 0; j < 4; j++) + { + r.s[j] = p.s[i]; + } + return r; + } + } + + // normalize( v ) for which any element in v is infinite shall proceed as + // if the elements in v were replaced as follows: + // for( i = 0; i < sizeof(v) / sizeof(v[0] ); i++ ) + // v[i] = isinf(v[i]) ? copysign(1.0, v[i]) : 0.0 * v [i]; + for(size_t i = 0; i < 4; i++) + { + if((std::isinf)(p.s[i])) + { + for(size_t j = 0; j < 4; j++) + { + r.s[j] = (std::isinf)(p.s[j]) ? (std::copysign)(1.0, p.s[j]) : 0.0 * p.s[j]; + } + r = (*this)(r); + return r; + } + } + + for(size_t i = 0; i < 4; i++) + { + t += static_cast(p.s[i]) * static_cast(p.s[i]); + } + + // normalize( v ) returns v if all elements of v are zero. + if(t == 0.0f) + { + for(size_t i = 0; i < 4; i++) + { + r.s[i] = 0.0f; + } + return r; + } + + t = std::sqrt(t); + for(size_t i = 0; i < 4; i++) + { + r.s[i] = static_cast(p.s[i]) / t; + } + + return r; + } + + cl_float4 max1() + { + return detail::def_limit(1000.0f); + } + + cl_float4 min1() + { + return detail::def_limit(-1000.0f); + } + + std::vector in_special_cases() + { + return { + {0.0f, 0.0f, 0.0f, 0.0f}, + {std::numeric_limits::infinity(), 0.0f, 0.0f, 0.0f}, + { + std::numeric_limits::infinity(), + std::numeric_limits::infinity(), + std::numeric_limits::infinity(), + std::numeric_limits::infinity() + }, + { + std::numeric_limits::infinity(), + 1.0f, + 0.0f, + std::numeric_limits::quiet_NaN() + }, + {-1.0f, -1.0f, 0.0f,-300.0f} + }; + } + + float ulp() + { + return + 2.5f + // error in rsqrt + error in multiply + (0.5f * 4.0f) + // cumulative error for multiplications + (0.5f * 3.0f); // cumulative error for additions + } +}; + +AUTO_TEST_CASE(test_geometric_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // float4 cross(float4 p0, float4 p1) + TEST_BINARY_FUNC_MACRO((geometric_func_cross(device))) + + // float dot(float4 p0, float4 p1) + TEST_BINARY_FUNC_MACRO((geometric_func_dot())) + + // float distance(float4 p0, float4 p1) + TEST_BINARY_FUNC_MACRO((geometric_func_distance())) + + // float length(float4 p) + TEST_UNARY_FUNC_MACRO((geometric_func_length())) + + // float4 normalize(float4 p) + TEST_UNARY_FUNC_MACRO((geometric_func_normalize())) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_GEOMETRIC_FUNCS_GEOMETRIC_FUNCS_HPP diff --git a/test_conformance/clcpp/geometric_funcs/main.cpp b/test_conformance/clcpp/geometric_funcs/main.cpp new file mode 100644 index 00000000..fb522af6 --- /dev/null +++ b/test_conformance/clcpp/geometric_funcs/main.cpp @@ -0,0 +1,49 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include + +#include "../common.hpp" + +#include "geometric_funcs.hpp" +#include "fast_geometric_funcs.hpp" + +int main(int argc, const char *argv[]) +{ + // Check if cl_float (float) and cl_double (double) fulfill the requirements of + // IEC 559 (IEEE 754) standard. This is required for the tests to run correctly. + if(!std::numeric_limits::is_iec559) + { + RETURN_ON_ERROR_MSG(-1, + "cl_float (float) does not fulfill the requirements of IEC 559 (IEEE 754) standard. " + "Tests won't run correctly." + ); + } + if(!std::numeric_limits::is_iec559) + { + RETURN_ON_ERROR_MSG(-1, + "cl_double (double) does not fulfill the requirements of IEC 559 (IEEE 754) standard. " + "Tests won't run correctly." + ); + } + + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/images/CMakeLists.txt b/test_conformance/clcpp/images/CMakeLists.txt new file mode 100644 index 00000000..e6b282d8 --- /dev/null +++ b/test_conformance/clcpp/images/CMakeLists.txt @@ -0,0 +1,15 @@ +set(MODULE_NAME CPP_IMAGES) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp + ../../../test_common/harness/mt19937.c + ../../../test_common/harness/conversions.c + ../../../test_common/harness/imageHelpers.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/images/common.hpp b/test_conformance/clcpp/images/common.hpp new file mode 100644 index 00000000..f975d7ed --- /dev/null +++ b/test_conformance/clcpp/images/common.hpp @@ -0,0 +1,198 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_IMAGES_COMMON_HPP +#define TEST_CONFORMANCE_CLCPP_IMAGES_COMMON_HPP + +#include + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +// This global variable is used by read_image_pixel from harness/imageHelpers +bool gTestRounding = false; + +#include "../../../test_common/harness/imageHelpers.h" + + +namespace detail +{ + +template +struct channel_info; + +template<> +struct channel_info +{ + typedef cl_char channel_type; + typedef cl_int4 element_type; + static std::string function_suffix() { return "i"; } + + channel_type channel_min() { return (std::numeric_limits::min)(); } + channel_type channel_max() { return (std::numeric_limits::max)(); } +}; + +template<> +struct channel_info +{ + typedef cl_short channel_type; + typedef cl_int4 element_type; + static std::string function_suffix() { return "i"; } + + channel_type channel_min() { return (std::numeric_limits::min)(); } + channel_type channel_max() { return (std::numeric_limits::max)(); } +}; + +template<> +struct channel_info +{ + typedef cl_int channel_type; + typedef cl_int4 element_type; + static std::string function_suffix() { return "i"; } + + channel_type channel_min() { return (std::numeric_limits::min)(); } + channel_type channel_max() { return (std::numeric_limits::max)(); } +}; + +template<> +struct channel_info +{ + typedef cl_uchar channel_type; + typedef cl_uint4 element_type; + static std::string function_suffix() { return "ui"; } + + channel_type channel_min() { return (std::numeric_limits::min)(); } + channel_type channel_max() { return (std::numeric_limits::max)(); } +}; + +template<> +struct channel_info +{ + typedef cl_ushort channel_type; + typedef cl_uint4 element_type; + static std::string function_suffix() { return "ui"; } + + channel_type channel_min() { return (std::numeric_limits::min)(); } + channel_type channel_max() { return (std::numeric_limits::max)(); } +}; + +template<> +struct channel_info +{ + typedef cl_uint channel_type; + typedef cl_uint4 element_type; + static std::string function_suffix() { return "ui"; } + + channel_type channel_min() { return (std::numeric_limits::min)(); } + channel_type channel_max() { return (std::numeric_limits::max)(); } +}; + +template<> +struct channel_info +{ + typedef cl_float channel_type; + typedef cl_float4 element_type; + static std::string function_suffix() { return "f"; } + + channel_type channel_min() { return -1e-3f; } + channel_type channel_max() { return +1e+3f; } +}; + +template +struct image_info; + +template<> +struct image_info +{ + static std::string image_type_name() { return "image1d"; } + static std::string coord_accessor() { return "x"; } +}; + +template<> +struct image_info +{ + static std::string image_type_name() { return "image2d"; } + static std::string coord_accessor() { return "xy"; } +}; + +template<> +struct image_info +{ + static std::string image_type_name() { return "image3d"; } +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + static std::string coord_accessor() { return "xyzw"; } +#else + static std::string coord_accessor() { return "xyz"; } +#endif +}; + +} // namespace + +template +struct image_test_base : + detail::channel_info, + detail::image_info +{ }; + +// Create image_descriptor (used by harness/imageHelpers functions) +image_descriptor create_image_descriptor(cl_image_desc &image_desc, cl_image_format *image_format) +{ + image_descriptor image_info; + image_info.width = image_desc.image_width; + image_info.height = image_desc.image_height; + image_info.depth = image_desc.image_depth; + image_info.arraySize = image_desc.image_array_size; + image_info.rowPitch = image_desc.image_row_pitch; + image_info.slicePitch = image_desc.image_slice_pitch; + image_info.format = image_format; + image_info.buffer = image_desc.mem_object; + image_info.type = image_desc.image_type; + image_info.num_mip_levels = image_desc.num_mip_levels; + return image_info; +} + +const std::vector get_channel_orders(cl_device_id device) +{ + // According to "Minimum List of Supported Image Formats" of OpenCL specification: + return { CL_R, CL_RG, CL_RGBA }; +} + +bool is_test_supported(cl_device_id device) +{ + // Check for image support + if (checkForImageSupport(device) == CL_IMAGE_FORMAT_NOT_SUPPORTED) + { + log_info("SKIPPED: Device does not support images. Skipping test.\n"); + return false; + } + return true; +} + +// Checks if x is equal to y. +template +inline bool are_equal(const type& x, + const type& y) +{ + for(size_t i = 0; i < vector_size::value; i++) + { + if(!(x.s[i] == y.s[i])) + { + return false; + } + } + return true; +} + +#endif // TEST_CONFORMANCE_CLCPP_IMAGES_COMMON_HPP diff --git a/test_conformance/clcpp/images/main.cpp b/test_conformance/clcpp/images/main.cpp new file mode 100644 index 00000000..5cf221c8 --- /dev/null +++ b/test_conformance/clcpp/images/main.cpp @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "test_read.hpp" +#include "test_sample.hpp" +#include "test_write.hpp" + + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/images/test_read.hpp b/test_conformance/clcpp/images/test_read.hpp new file mode 100644 index 00000000..3bc7b5ef --- /dev/null +++ b/test_conformance/clcpp/images/test_read.hpp @@ -0,0 +1,307 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_IMAGES_TEST_READ_HPP +#define TEST_CONFORMANCE_CLCPP_IMAGES_TEST_READ_HPP + +#include +#include +#include +#include + +#include "common.hpp" + + +namespace test_images_read { + +template +struct image_test : image_test_base +{ + cl_channel_order channel_order; + + image_test(cl_channel_order channel_order) : + channel_order(channel_order) + { } +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + std::string generate_source() + { + std::stringstream s; + s << R"( + typedef )" << type_name() << R"( element_type; + + kernel void test( + read_only )" << image_test::image_type_name() << R"(_t img, + const global int4 *coords, + global element_type *output + ) { + const ulong gid = get_global_linear_id(); + + output[gid] = read_image)" << image_test::function_suffix() << + "(img, coords[gid]." << image_test::coord_accessor() << R"(); + } + )"; + + return s.str(); + } +#else + std::string generate_source() + { + std::stringstream s; + s << R"( + #include + #include + #include + #include + using namespace cl; + )"; + + s << R"( + typedef )" << type_name() << R"( element_type; + + kernel void test( + const )" << image_test::image_type_name() << R"( img, + const global_ptr coords, + global_ptr output + ) { + const ulong gid = get_global_linear_id(); + + output[gid] = img.read(coords[gid].)" << image_test::coord_accessor() << R"(); + } + )"; + + return s.str(); + } +#endif + + int run(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) + { + int error = CL_SUCCESS; + + cl_program program; + cl_kernel kernel; + + std::string kernel_name = "test"; + std::string source = generate_source(); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name, "-cl-std=CL2.0", false + ); + RETURN_ON_ERROR(error) +// Normal run +#else + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) +#endif + + using element_type = typename image_test::element_type; + using coord_type = cl_int4; + using scalar_element_type = typename scalar_type::type; + using channel_type = typename image_test::channel_type; + + cl_image_format image_format; + image_format.image_channel_order = channel_order; + image_format.image_channel_data_type = ChannelType; + + const size_t pixel_size = get_pixel_size(&image_format); + const size_t channel_count = get_channel_order_channel_count(image_format.image_channel_order); + + cl_image_desc image_desc; + image_desc.image_type = ImageType; + if (ImageType == CL_MEM_OBJECT_IMAGE1D) + { + image_desc.image_width = 2048; + image_desc.image_height = 1; + image_desc.image_depth = 1; + } + else if (ImageType == CL_MEM_OBJECT_IMAGE2D) + { + image_desc.image_width = 256; + image_desc.image_height = 256; + image_desc.image_depth = 1; + } + else if (ImageType == CL_MEM_OBJECT_IMAGE3D) + { + image_desc.image_width = 64; + image_desc.image_height = 64; + image_desc.image_depth = 64; + } + image_desc.image_array_size = 0; + image_desc.image_row_pitch = image_desc.image_width * pixel_size; + image_desc.image_slice_pitch = image_desc.image_row_pitch * image_desc.image_height; + image_desc.num_mip_levels = 0; + image_desc.num_samples = 0; + image_desc.mem_object = NULL; + + image_descriptor image_info = create_image_descriptor(image_desc, &image_format); + + std::vector image_values = generate_input( + image_desc.image_width * image_desc.image_height * image_desc.image_depth * channel_count, + image_test::channel_min(), image_test::channel_max(), + std::vector() + ); + + const size_t count = num_elements; + + std::vector coords = generate_input( + count, + detail::make_value(0), + coord_type { + static_cast(image_desc.image_width - 1), + static_cast(image_desc.image_height - 1), + static_cast(image_desc.image_depth - 1), + 0 + }, + std::vector() + ); + + cl_mem img = clCreateImage(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + &image_format, &image_desc, static_cast(image_values.data()), &error); + RETURN_ON_CL_ERROR(error, "clCreateImage") + + cl_mem coords_buffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + sizeof(coord_type) * count, static_cast(coords.data()), &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + cl_mem output_buffer = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(element_type) * count, NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &img); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 1, sizeof(coords_buffer), &coords_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 2, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + const size_t global_size = count; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + std::vector output(count); + error = clEnqueueReadBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(element_type) * count, + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + for (size_t i = 0; i < count; i++) + { + const coord_type c = coords[i]; + const element_type result = output[i]; + + element_type expected; + read_image_pixel(static_cast(image_values.data()), &image_info, + c.s[0], c.s[1], c.s[2], + expected.s); + + if (!are_equal(result, expected)) + { + RETURN_ON_ERROR_MSG(-1, + "Reading from coordinates %s failed. Expected: %s, got: %s", + format_value(c).c_str(), format_value(expected).c_str(), format_value(result).c_str() + ); + } + } + + clReleaseMemObject(img); + clReleaseMemObject(coords_buffer); + clReleaseMemObject(output_buffer); + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; + } +}; + +template +int run_test_cases(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + if (!is_test_supported(device)) + return CL_SUCCESS; + + int error = CL_SUCCESS; + + for (auto channel_order : get_channel_orders(device)) + { + error = image_test(channel_order) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + error = image_test(channel_order) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + error = image_test(channel_order) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + + error = image_test(channel_order) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + error = image_test(channel_order) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + error = image_test(channel_order) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + + error = image_test(channel_order) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + } + + return error; +} + + +AUTO_TEST_CASE(test_images_read_1d) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + return run_test_cases(device, context, queue, num_elements); +} + +AUTO_TEST_CASE(test_images_read_2d) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + return run_test_cases(device, context, queue, num_elements); +} + +AUTO_TEST_CASE(test_images_read_3d) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + return run_test_cases(device, context, queue, num_elements); +} + +} // namespace + +#endif // TEST_CONFORMANCE_CLCPP_IMAGES_TEST_READ_HPP diff --git a/test_conformance/clcpp/images/test_sample.hpp b/test_conformance/clcpp/images/test_sample.hpp new file mode 100644 index 00000000..a96a563a --- /dev/null +++ b/test_conformance/clcpp/images/test_sample.hpp @@ -0,0 +1,363 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_IMAGES_TEST_SAMPLE_HPP +#define TEST_CONFORMANCE_CLCPP_IMAGES_TEST_SAMPLE_HPP + +#include +#include +#include +#include + +#include "common.hpp" + + +namespace test_images_sample { + +enum class sampler_source +{ + param, + program_scope +}; + +const sampler_source sampler_sources[] = { sampler_source::param, sampler_source::program_scope }; + +template +struct image_test : image_test_base +{ + cl_channel_order channel_order; + sampler_source source; + + image_test(cl_channel_order channel_order, sampler_source source) : + channel_order(channel_order), + source(source) + { } + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + std::string generate_source() + { + std::stringstream s; + s << R"( + typedef )" << type_name() << R"( element_type; + )"; + + std::string sampler; + if (source == sampler_source::program_scope) + { + s << R"( + constant sampler_t sampler_program_scope = CLK_FILTER_NEAREST | CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE; + )"; + sampler = "sampler_program_scope"; + } + else if (source == sampler_source::param) + { + sampler = "sampler_param"; + } + + s << R"( + kernel void test( + read_only )" << image_test::image_type_name() << R"(_t img, + const global int4 *coords, + global element_type *output, + sampler_t sampler_param + ) { + const ulong gid = get_global_linear_id(); + + output[gid] = read_image)" << image_test::function_suffix() << + "(img, " << sampler << ", coords[gid]." << image_test::coord_accessor() << R"(); + } + )"; + + return s.str(); + } +#else + std::string generate_source() + { + std::stringstream s; + s << R"( + #include + #include + #include + #include + using namespace cl; + )"; + + s << R"( + typedef )" << type_name() << R"( element_type; + )"; + + std::string sampler; + if (source == sampler_source::program_scope) + { + s << R"( + sampler sampler_program_scope = make_sampler(); + )"; + sampler = "sampler_program_scope"; + } + else if (source == sampler_source::param) + { + sampler = "sampler_param"; + } + + s << R"( + kernel void test( + const )" << image_test::image_type_name() << R"( img, + const global_ptr coords, + global_ptr output, + sampler sampler_param + ) { + const ulong gid = get_global_linear_id(); + + output[gid] = img.sample()" << sampler << ", coords[gid]." << image_test::coord_accessor() << R"(); + } + )"; + + return s.str(); + } +#endif + + int run(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) + { + int error = CL_SUCCESS; + + cl_program program; + cl_kernel kernel; + + std::string kernel_name = "test"; + std::string source = generate_source(); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name, "-cl-std=CL2.0", false + ); + RETURN_ON_ERROR(error) +// Normal run +#else + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) +#endif + + using element_type = typename image_test::element_type; + using coord_type = cl_int4; + using scalar_element_type = typename scalar_type::type; + using channel_type = typename image_test::channel_type; + + cl_image_format image_format; + image_format.image_channel_order = channel_order; + image_format.image_channel_data_type = ChannelType; + + const size_t pixel_size = get_pixel_size(&image_format); + const size_t channel_count = get_channel_order_channel_count(image_format.image_channel_order); + + cl_image_desc image_desc; + image_desc.image_type = ImageType; + if (ImageType == CL_MEM_OBJECT_IMAGE1D) + { + image_desc.image_width = 2048; + image_desc.image_height = 1; + image_desc.image_depth = 1; + } + else if (ImageType == CL_MEM_OBJECT_IMAGE2D) + { + image_desc.image_width = 256; + image_desc.image_height = 256; + image_desc.image_depth = 1; + } + else if (ImageType == CL_MEM_OBJECT_IMAGE3D) + { + image_desc.image_width = 64; + image_desc.image_height = 64; + image_desc.image_depth = 64; + } + image_desc.image_array_size = 0; + image_desc.image_row_pitch = image_desc.image_width * pixel_size; + image_desc.image_slice_pitch = image_desc.image_row_pitch * image_desc.image_height; + image_desc.num_mip_levels = 0; + image_desc.num_samples = 0; + image_desc.mem_object = NULL; + + image_descriptor image_info = create_image_descriptor(image_desc, &image_format); + + std::vector image_values = generate_input( + image_desc.image_width * image_desc.image_height * image_desc.image_depth * channel_count, + image_test::channel_min(), image_test::channel_max(), + std::vector() + ); + + const size_t count = num_elements; + + std::vector coords = generate_input( + count, + detail::make_value(0), + coord_type { + static_cast(image_desc.image_width - 1), + static_cast(image_desc.image_height - 1), + static_cast(image_desc.image_depth - 1), + 0 + }, + std::vector() + ); + + cl_mem img = clCreateImage(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + &image_format, &image_desc, static_cast(image_values.data()), &error); + RETURN_ON_CL_ERROR(error, "clCreateImage") + + cl_mem coords_buffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + sizeof(coord_type) * count, static_cast(coords.data()), &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + cl_mem output_buffer = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(element_type) * count, NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + const cl_sampler_properties sampler_properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_NONE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 + }; + cl_sampler sampler = clCreateSamplerWithProperties(context, sampler_properties, &error); + RETURN_ON_CL_ERROR(error, "clCreateSamplerWithProperties") + + error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &img); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 1, sizeof(coords_buffer), &coords_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 2, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 3, sizeof(sampler), &sampler); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + const size_t global_size = count; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + std::vector output(count); + error = clEnqueueReadBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(element_type) * count, + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + for (size_t i = 0; i < count; i++) + { + const coord_type c = coords[i]; + const element_type result = output[i]; + + element_type expected; + read_image_pixel(static_cast(image_values.data()), &image_info, + c.s[0], c.s[1], c.s[2], + expected.s); + + if (!are_equal(result, expected)) + { + RETURN_ON_ERROR_MSG(-1, + "Sampling from coordinates %s failed. Expected: %s, got: %s", + format_value(c).c_str(), format_value(expected).c_str(), format_value(result).c_str() + ); + } + } + + clReleaseMemObject(img); + clReleaseMemObject(coords_buffer); + clReleaseMemObject(output_buffer); + clReleaseSampler(sampler); + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; + } +}; + +template +int run_test_cases(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + if (!is_test_supported(device)) + return CL_SUCCESS; + + int error = CL_SUCCESS; + + for (auto channel_order : get_channel_orders(device)) + for (auto source : sampler_sources) + { + error = image_test(channel_order, source) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + error = image_test(channel_order, source) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + error = image_test(channel_order, source) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + + error = image_test(channel_order, source) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + error = image_test(channel_order, source) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + error = image_test(channel_order, source) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + + error = image_test(channel_order, source) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + } + + return error; +} + + +AUTO_TEST_CASE(test_images_sample_1d) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + return run_test_cases(device, context, queue, num_elements); +} + +AUTO_TEST_CASE(test_images_sample_2d) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + return run_test_cases(device, context, queue, num_elements); +} + +AUTO_TEST_CASE(test_images_sample_3d) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + return run_test_cases(device, context, queue, num_elements); +} + +} // namespace + +#endif // TEST_CONFORMANCE_CLCPP_IMAGES_TEST_SAMPLE_HPP diff --git a/test_conformance/clcpp/images/test_write.hpp b/test_conformance/clcpp/images/test_write.hpp new file mode 100644 index 00000000..0f544874 --- /dev/null +++ b/test_conformance/clcpp/images/test_write.hpp @@ -0,0 +1,327 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_IMAGES_TEST_WRITE_HPP +#define TEST_CONFORMANCE_CLCPP_IMAGES_TEST_WRITE_HPP + +#include +#include +#include +#include +#include + +#include "common.hpp" + + +namespace test_images_write { + +template +struct image_test : image_test_base +{ + cl_channel_order channel_order; + + image_test(cl_channel_order channel_order) : + channel_order(channel_order) + { } +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + std::string generate_source() + { + std::stringstream s; + s << R"( + typedef )" << type_name() << R"( element_type; + + kernel void test( + write_only )" << image_test::image_type_name() << R"(_t img, + const global int4 *coords, + const global element_type *input + ) { + const ulong gid = get_global_linear_id(); + + write_image)" << image_test::function_suffix() << + "(img, coords[gid]." << image_test::coord_accessor() << R"(, input[gid]); + } + )"; + + return s.str(); + } +#else + std::string generate_source() + { + std::stringstream s; + s << R"( + #include + #include + #include + #include + using namespace cl; + )"; + + s << R"( + typedef )" << type_name() << R"( element_type; + + kernel void test( + )" << image_test::image_type_name() << R"( img, + const global_ptr coords, + const global_ptr input + ) { + const ulong gid = get_global_linear_id(); + + img.write(coords[gid].)" << image_test::coord_accessor() << R"(, input[gid]); + } + )"; + + return s.str(); + } +#endif + + int run(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) + { + int error = CL_SUCCESS; + + cl_program program; + cl_kernel kernel; + + std::string kernel_name = "test"; + std::string source = generate_source(); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name, "-cl-std=CL2.0", false + ); + RETURN_ON_ERROR(error) +// Normal run +#else + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) +#endif + + using element_type = typename image_test::element_type; + using coord_type = cl_int4; + using scalar_element_type = typename scalar_type::type; + using channel_type = typename image_test::channel_type; + + cl_image_format image_format; + image_format.image_channel_order = channel_order; + image_format.image_channel_data_type = ChannelType; + + const size_t pixel_size = get_pixel_size(&image_format); + const size_t channel_count = get_channel_order_channel_count(image_format.image_channel_order); + + cl_image_desc image_desc; + image_desc.image_type = ImageType; + if (ImageType == CL_MEM_OBJECT_IMAGE1D) + { + image_desc.image_width = 2048; + image_desc.image_height = 1; + image_desc.image_depth = 1; + } + else if (ImageType == CL_MEM_OBJECT_IMAGE2D) + { + image_desc.image_width = 256; + image_desc.image_height = 256; + image_desc.image_depth = 1; + } + else if (ImageType == CL_MEM_OBJECT_IMAGE3D) + { + image_desc.image_width = 64; + image_desc.image_height = 64; + image_desc.image_depth = 64; + } + image_desc.image_array_size = 0; + image_desc.image_row_pitch = image_desc.image_width * pixel_size; + image_desc.image_slice_pitch = image_desc.image_row_pitch * image_desc.image_height; + image_desc.num_mip_levels = 0; + image_desc.num_samples = 0; + image_desc.mem_object = NULL; + + image_descriptor image_info = create_image_descriptor(image_desc, &image_format); + + std::vector random_image_values = generate_input( + image_desc.image_width * image_desc.image_height * image_desc.image_depth * channel_count, + image_test::channel_min(), image_test::channel_max(), + std::vector() + ); + + const size_t count = num_elements; + + std::vector coords = generate_input( + count, + detail::make_value(0), + coord_type { + static_cast(image_desc.image_width - 1), + static_cast(image_desc.image_height - 1), + static_cast(image_desc.image_depth - 1), + 0 + }, + std::vector() + ); + + std::vector input(count); + for (size_t i = 0; i < count; i++) + { + const coord_type c = coords[i]; + + // Use read_image_pixel from harness/imageHelpers to fill input values + // (it will deal with correct channels, orders etc.) + read_image_pixel(static_cast(random_image_values.data()), &image_info, + c.s[0], c.s[1], c.s[2], + input[i].s); + } + + // image_row_pitch and image_slice_pitch must be 0, when clCreateImage is used with host_ptr = NULL + image_desc.image_row_pitch = 0; + image_desc.image_slice_pitch = 0; + cl_mem img = clCreateImage(context, CL_MEM_WRITE_ONLY, + &image_format, &image_desc, NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateImage") + + cl_mem coords_buffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + sizeof(coord_type) * count, static_cast(coords.data()), &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + cl_mem input_buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + sizeof(element_type) * count, static_cast(input.data()), &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &img); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 1, sizeof(coords_buffer), &coords_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 2, sizeof(input_buffer), &input_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + const size_t global_size = count; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + std::vector image_values(image_desc.image_width * image_desc.image_height * image_desc.image_depth * channel_count); + + const size_t origin[3] = { 0 }; + const size_t region[3] = { image_desc.image_width, image_desc.image_height, image_desc.image_depth }; + error = clEnqueueReadImage( + queue, img, CL_TRUE, + origin, region, 0, 0, + static_cast(image_values.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + for (size_t i = 0; i < count; i++) + { + const coord_type c = coords[i]; + const element_type expected = input[i]; + + element_type result; + read_image_pixel(static_cast(image_values.data()), &image_info, + c.s[0], c.s[1], c.s[2], + result.s); + + if (!are_equal(result, expected)) + { + RETURN_ON_ERROR_MSG(-1, + "Writing to coordinates %s failed. Expected: %s, got: %s", + format_value(c).c_str(), format_value(expected).c_str(), format_value(result).c_str() + ); + } + } + + clReleaseMemObject(img); + clReleaseMemObject(coords_buffer); + clReleaseMemObject(input_buffer); + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; + } +}; + +template +int run_test_cases(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + if (!is_test_supported(device)) + return CL_SUCCESS; + + int error = CL_SUCCESS; + + for (auto channel_order : get_channel_orders(device)) + { + error = image_test(channel_order) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + error = image_test(channel_order) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + error = image_test(channel_order) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + + error = image_test(channel_order) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + error = image_test(channel_order) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + error = image_test(channel_order) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + + error = image_test(channel_order) + .run(device, context, queue, num_elements); + RETURN_ON_ERROR(error) + } + + return error; +} + + +AUTO_TEST_CASE(test_images_write_1d) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + return run_test_cases(device, context, queue, num_elements); +} + +AUTO_TEST_CASE(test_images_write_2d) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + return run_test_cases(device, context, queue, num_elements); +} + +AUTO_TEST_CASE(test_images_write_3d) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + return run_test_cases(device, context, queue, num_elements); +} + +} // namespace + +#endif // TEST_CONFORMANCE_CLCPP_IMAGES_TEST_WRITE_HPP diff --git a/test_conformance/clcpp/integer_funcs/24bit_funcs.hpp b/test_conformance/clcpp/integer_funcs/24bit_funcs.hpp new file mode 100644 index 00000000..98da450b --- /dev/null +++ b/test_conformance/clcpp/integer_funcs/24bit_funcs.hpp @@ -0,0 +1,142 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_INTEGER_FUNCS_24BIT_HPP +#define TEST_CONFORMANCE_CLCPP_INTEGER_FUNCS_24BIT_HPP + +#include "common.hpp" +#include + +template +struct int_func_mad24 : public ternary_func +{ + std::string str() + { + return "mad24"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& y, const IN3& z) + { + static_assert( + std::is_same::value + && std::is_same::value + && std::is_same::value, + "All types must be the same" + ); + static_assert( + std::is_same::value || std::is_same::value, + "Function takes only signed/unsigned integers." + ); + return (x * y) + z; + } + + IN1 min1() + { + return 0; + } + + IN1 max1() + { + return (std::numeric_limits::max)() & IN1(0x00FFFF); + } + + IN2 min2() + { + return 0; + } + + IN2 max2() + { + return (std::numeric_limits::max)() & IN2(0x00FFFF); + } +}; + +template +struct int_func_mul24 : public binary_func +{ + std::string str() + { + return "mul24"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& y) + { + static_assert( + std::is_same::value + && std::is_same::value, + "All types must be the same" + ); + static_assert( + std::is_same::value || std::is_same::value, + "Function takes only signed/unsigned integers." + ); + return x * y; + } + + IN1 min1() + { + return 0; + } + + IN1 max1() + { + return (std::numeric_limits::max)() & IN1(0x00FFFF); + } + + IN2 min2() + { + return 0; + } + + IN2 max2() + { + return (std::numeric_limits::max)() & IN2(0x00FFFF); + } +}; + +AUTO_TEST_CASE(test_int_24bit_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // intn mad24(intn x, intn y, intn z); + // uintn mad24(uintn x, uintn y, uintn z); + TEST_TERNARY_FUNC_MACRO((int_func_mad24())) + TEST_TERNARY_FUNC_MACRO((int_func_mad24())) + + // intn mul24(intn x, intn y); + // uintn mul24(uintn x, uintn y); + TEST_BINARY_FUNC_MACRO((int_func_mul24())) + TEST_BINARY_FUNC_MACRO((int_func_mul24())) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_INTEGER_FUNCS_24BIT_HPP diff --git a/test_conformance/clcpp/integer_funcs/CMakeLists.txt b/test_conformance/clcpp/integer_funcs/CMakeLists.txt new file mode 100644 index 00000000..88eb2a49 --- /dev/null +++ b/test_conformance/clcpp/integer_funcs/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_INTEGER_FUNCS) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/integer_funcs/bitwise_funcs.hpp b/test_conformance/clcpp/integer_funcs/bitwise_funcs.hpp new file mode 100644 index 00000000..13ca1563 --- /dev/null +++ b/test_conformance/clcpp/integer_funcs/bitwise_funcs.hpp @@ -0,0 +1,232 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_INTEGER_FUNCS_BITWISE_HPP +#define TEST_CONFORMANCE_CLCPP_INTEGER_FUNCS_BITWISE_HPP + +#include "common.hpp" +#include + +template +struct int_func_popcount : public unary_func +{ + std::string str() + { + return "popcount"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(IN1 x) + { + OUT1 count = 0; + for (count = 0; x != 0; count++) + { + x &= x - 1; + } + return count; + } +}; + +template +struct int_func_clz : public unary_func +{ + std::string str() + { + return "clz"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(IN1 x) + { + OUT1 count = 0; + if(std::is_unsigned::value) + { + cl_ulong value = x; + value <<= 8 * sizeof(value) - (8 * sizeof(x)); + for(count = 0; 0 == (value & (CL_LONG_MIN)); count++) + { + value <<= 1; + } + } + else + { + cl_long value = x; + value <<= 8 * sizeof(value) - (8 * sizeof(x)); + for(count = 0; 0 == (value & (CL_LONG_MIN)); count++) + { + value <<= 1; + } + } + return count; + } +}; + +template +struct int_func_ctz : public unary_func +{ + std::string str() + { + return "ctz"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(IN1 x) + { + if(x == 0) + return sizeof(x); + + OUT1 count = 0; + IN1 value = x; + for(count = 0; 0 == (value & 0x1); count++) + { + value >>= 1; + } + return count; + } +}; + +template +struct int_func_rotate : public binary_func +{ + std::string str() + { + return "rotate"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(IN1 value, IN2 shift) + { + static_assert( + std::is_unsigned::value, + "Only unsigned integers are supported" + ); + if ((shift &= sizeof(value)*8 - 1) == 0) + return value; + return (value << shift) | (value >> (sizeof(value)*8 - shift)); + } + + IN2 min2() + { + return 0; + } + + IN2 max2() + { + return sizeof(IN1) * 8; + } +}; + +template +struct int_func_upsample : public binary_func +{ + std::string str() + { + return "upsample"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(IN1 hi, IN2 lo) + { + static_assert( + sizeof(IN1) == sizeof(IN2), + "sizeof(IN1) != sizeof(IN2)" + ); + static_assert( + sizeof(OUT1) == 2 * sizeof(IN1), + "sizeof(OUT1) != 2 * sizeof(IN1)" + ); + static_assert( + std::is_unsigned::value, + "IN2 type must be unsigned" + ); + return (static_cast(hi) << (8*sizeof(IN1))) | lo; + } + + IN2 min2() + { + return 0; + } + + IN2 max2() + { + return sizeof(IN1) * 8; + } +}; + +AUTO_TEST_CASE(test_int_bitwise_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + TEST_UNARY_FUNC_MACRO((int_func_popcount())) + TEST_UNARY_FUNC_MACRO((int_func_popcount())) + TEST_UNARY_FUNC_MACRO((int_func_popcount())) + TEST_UNARY_FUNC_MACRO((int_func_popcount())) + + TEST_UNARY_FUNC_MACRO((int_func_clz())) + TEST_UNARY_FUNC_MACRO((int_func_clz())) + TEST_UNARY_FUNC_MACRO((int_func_clz())) + TEST_UNARY_FUNC_MACRO((int_func_clz())) + + TEST_UNARY_FUNC_MACRO((int_func_ctz())) + TEST_UNARY_FUNC_MACRO((int_func_ctz())) + TEST_UNARY_FUNC_MACRO((int_func_ctz())) + TEST_UNARY_FUNC_MACRO((int_func_ctz())) + + TEST_BINARY_FUNC_MACRO((int_func_rotate())) + TEST_BINARY_FUNC_MACRO((int_func_rotate())) + + // shortn upsample(charn hi, ucharn lo); + TEST_BINARY_FUNC_MACRO((int_func_upsample())) + // ushortn upsample(ucharn hi, ucharn lo); + TEST_BINARY_FUNC_MACRO((int_func_upsample())) + // intn upsample(shortn hi, ushortn lo); + TEST_BINARY_FUNC_MACRO((int_func_upsample())) + // uintn upsample(ushortn hi, ushortn lo); + TEST_BINARY_FUNC_MACRO((int_func_upsample())) + // longn upsample(intn hi, uintn lo); + TEST_BINARY_FUNC_MACRO((int_func_upsample())) + // ulongn upsample(uintn hi, uintn lo); + TEST_BINARY_FUNC_MACRO((int_func_upsample())) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_INTEGER_FUNCS_BITWISE_HPP diff --git a/test_conformance/clcpp/integer_funcs/common.hpp b/test_conformance/clcpp/integer_funcs/common.hpp new file mode 100644 index 00000000..f04811e1 --- /dev/null +++ b/test_conformance/clcpp/integer_funcs/common.hpp @@ -0,0 +1,26 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_INTEGER_FUNCS_COMMON_HPP +#define TEST_CONFORMANCE_CLCPP_INTEGER_FUNCS_COMMON_HPP + +#include +#include +#include + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#endif // TEST_CONFORMANCE_CLCPP_INTEGER_FUNCS_COMMON_HPP diff --git a/test_conformance/clcpp/integer_funcs/main.cpp b/test_conformance/clcpp/integer_funcs/main.cpp new file mode 100644 index 00000000..ca5d54a9 --- /dev/null +++ b/test_conformance/clcpp/integer_funcs/main.cpp @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "bitwise_funcs.hpp" +#include "numeric_funcs.hpp" +#include "24bit_funcs.hpp" + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/integer_funcs/numeric_funcs.hpp b/test_conformance/clcpp/integer_funcs/numeric_funcs.hpp new file mode 100644 index 00000000..21d75c5a --- /dev/null +++ b/test_conformance/clcpp/integer_funcs/numeric_funcs.hpp @@ -0,0 +1,703 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_INTEGER_FUNCS_NUMERIC_HPP +#define TEST_CONFORMANCE_CLCPP_INTEGER_FUNCS_NUMERIC_HPP + +#include "common.hpp" +#include + +template +struct int_func_abs : public unary_func +{ + std::string str() + { + return "abs"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x) + { + static_assert( + std::is_unsigned::value, + "OUT1 type must be unsigned" + ); + if(x < IN1(0)) + return static_cast(-x); + return static_cast(x); + } +}; + +template +struct int_func_abs_diff : public binary_func +{ + std::string str() + { + return "abs_diff"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& y) + { + static_assert( + std::is_same::value, + "IN1 must be IN2" + ); + static_assert( + std::is_unsigned::value, + "OUT1 type must be unsigned" + ); + if(x < y) + return static_cast(y-x); + return static_cast(x-y); + } +}; + +template +struct int_func_add_sat : public binary_func +{ + std::string str() + { + return "add_sat"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& y) + { + static_assert( + std::is_same::value, + "IN1 must be IN2" + ); + static_assert( + std::is_same::value, + "OUT1 must be IN2" + ); + // sat unsigned integers + if(std::is_unsigned::value) + { + OUT1 z = x + y; + if(z < x || z < y) + return (std::numeric_limits::max)(); + return z; + } + // sat signed integers + OUT1 z = x + y; + if(y > 0) + { + if(z < x) + return (std::numeric_limits::max)(); + } + else + { + if(z > x) + return (std::numeric_limits::min)(); + } + return z; + } +}; + +template +struct int_func_hadd : public binary_func +{ + std::string str() + { + return "hadd"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& y) + { + static_assert( + std::is_same::value, + "IN1 must be IN2" + ); + static_assert( + std::is_same::value, + "OUT1 must be IN2" + ); + return (x >> OUT1(1)) + (y >> OUT1(1)) + (x & y & OUT1(1)); + } +}; + +template +struct int_func_rhadd : public binary_func +{ + std::string str() + { + return "rhadd"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& y) + { + static_assert( + std::is_same::value, + "IN1 must be IN2" + ); + static_assert( + std::is_same::value, + "OUT1 must be IN2" + ); + return (x >> OUT1(1)) + (y >> OUT1(1)) + ((x | y) & OUT1(1)); + } +}; + +// clamp for scalars +template +struct int_func_clamp : public ternary_func +{ + std::string str() + { + return "clamp"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& minval, const IN3& maxval) + { + static_assert( + std::is_same::value, + "IN3 must be IN2" + ); + static_assert( + std::is_same::value, + "OUT1 must be IN1" + ); + return (std::min)((std::max)(x, minval), maxval); + } + + IN2 min2() + { + return (std::numeric_limits::min)(); + } + + IN2 max2() + { + return (std::numeric_limits::max)() / IN2(2); + } + + IN3 min3() + { + return IN3(1) + ((std::numeric_limits::max)() / IN3(2)); + } + + IN3 max3() + { + return (std::numeric_limits::max)(); + } +}; + +// gentype clamp(gentype x, scalar minval, scalar maxval); +template +struct int_func_clamp::value>::type> : public ternary_func +{ + std::string str() + { + return "clamp"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& minval, const IN3& maxval) + { + static_assert( + std::is_same::value, + "IN3 must be IN2" + ); + static_assert( + !is_vector_type::value && !is_vector_type::value, + "IN3 and IN2 must be scalar" + ); + static_assert( + std::is_same::value, + "OUT1 must be IN1" + ); + OUT1 result; + for(size_t i = 0; i < vector_size::value; i++) + { + result.s[i] = (std::min)((std::max)(x.s[i], minval), maxval); + } + return result; + } + + IN1 min1() + { + typedef typename scalar_type::type SCALAR1; + IN1 min1; + for(size_t i = 0; i < vector_size::value; i++) + { + min1.s[i] = (std::numeric_limits::min)(); + } + return min1; + } + + IN1 max1() + { + typedef typename scalar_type::type SCALAR1; + IN1 max1; + for(size_t i = 0; i < vector_size::value; i++) + { + max1.s[i] = (std::numeric_limits::max)(); + } + return max1; + } + + IN2 min2() + { + return (std::numeric_limits::min)(); + } + + IN2 max2() + { + return (std::numeric_limits::max)() / IN2(2); + } + + IN3 min3() + { + return IN3(1) + ((std::numeric_limits::max)() / IN3(2)); + } + + IN3 max3() + { + return (std::numeric_limits::max)(); + } +}; + +template +struct int_func_mul_hi : public binary_func +{ + std::string str() + { + return "mul_hi"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& y) + { + static_assert( + std::is_same::value + && std::is_same::value, + "Types must be the same" + ); + static_assert( + !std::is_same::value && !std::is_same::value, + "Operation unimplemented for 64-bit scalars" + ); + cl_long xl = static_cast(x); + cl_long yl = static_cast(y); + return static_cast((xl * yl) >> (8 * sizeof(OUT1))); + } +}; + +template +struct int_func_mad_hi : public ternary_func +{ + std::string str() + { + return "mad_hi"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& y, const IN3& z) + { + static_assert( + std::is_same::value + && std::is_same::value + && std::is_same::value, + "Types must be the same" + ); + return int_func_mul_hi()(x, y) + z; + } +}; + +// This test is implemented only for unsigned integers +template +struct int_func_mad_sat : public ternary_func +{ + std::string str() + { + return "mad_sat"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& y, const IN3& z) + { + static_assert( + std::is_same::value + && std::is_same::value + && std::is_same::value, + "Types must be the same" + ); + static_assert( + std::is_unsigned::value, + "Test operation is not implemented for signed integers" + ); + // mad_sat unsigned integers + OUT1 w1 = (x * y); + if (x != 0 && w1 / x != y) + return (std::numeric_limits::max)(); + OUT1 w2 = w1 + z; + if(w2 < w1) + return (std::numeric_limits::max)(); + return w2; + } +}; + +template +struct int_func_sub_sat : public binary_func +{ + std::string str() + { + return "sub_sat"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& y) + { + static_assert( + std::is_same::value && std::is_same::value, + "IN1, IN2 and OUT1 must be the same types" + ); + // sat unsigned integers + if(std::is_unsigned::value) + { + OUT1 z = x - y; + if(x < y) + return (std::numeric_limits::min)(); + return z; + } + // sat signed integers + OUT1 z = x - y; + if(y < 0) + { + if(z < x) + return (std::numeric_limits::max)(); + } + else + { + if(z > x) + return (std::numeric_limits::min)(); + } + return z; + } +}; + +template +struct int_func_max : public binary_func +{ + std::string str() + { + return "max"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& y) + { + static_assert( + std::is_same::value && std::is_same::value, + "IN1, IN2 and OUT1 must be the same types" + ); + return (std::max)(x, y); + } +}; + +template +struct int_func_max::value>::type> : public binary_func +{ + std::string str() + { + return "max"; + } + + std::string headers() + { + return "#include \n"; + } + + IN1 min1() + { + typedef typename scalar_type::type SCALAR1; + IN1 min1; + for(size_t i = 0; i < vector_size::value; i++) + { + min1.s[i] = (std::numeric_limits::min)(); + } + return min1; + } + + IN1 max1() + { + typedef typename scalar_type::type SCALAR1; + IN1 max1; + for(size_t i = 0; i < vector_size::value; i++) + { + max1.s[i] = (std::numeric_limits::max)(); + } + return max1; + } + + OUT1 operator()(const IN1& x, const IN2& y) + { + static_assert( + std::is_same::value, + "IN1 and OUT1 must be the same types" + ); + static_assert( + !is_vector_type::value, + "IN2 must be scalar" + ); + static_assert( + std::is_same::type, IN2>::value, + "IN2 must match with OUT1 and IN1" + ); + IN1 result = x; + for(size_t i = 0; i < vector_size::value; i++) + { + result.s[i] = (std::max)(x.s[i], y); + } + return result; + } +}; + +template +struct int_func_min : public binary_func +{ + std::string str() + { + return "min"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x, const IN2& y) + { + static_assert( + std::is_same::value && std::is_same::value, + "IN1, IN2 and OUT1 must be the same types" + ); + return (std::min)(x, y); + } +}; + +template +struct int_func_min::value>::type> : public binary_func +{ + std::string str() + { + return "min"; + } + + std::string headers() + { + return "#include \n"; + } + + IN1 min1() + { + typedef typename scalar_type::type SCALAR1; + IN1 min1; + for(size_t i = 0; i < vector_size::value; i++) + { + min1.s[i] = (std::numeric_limits::min)(); + } + return min1; + } + + IN1 max1() + { + typedef typename scalar_type::type SCALAR1; + IN1 max1; + for(size_t i = 0; i < vector_size::value; i++) + { + max1.s[i] = (std::numeric_limits::max)(); + } + return max1; + } + + OUT1 operator()(const IN1& x, const IN2& y) + { + static_assert( + std::is_same::value, + "IN1 and OUT1 must be the same types" + ); + static_assert( + !is_vector_type::value, + "IN2 must be scalar" + ); + static_assert( + std::is_same::type, IN2>::value, + "IN2 must match with OUT1 and IN1" + ); + IN1 result = x; + for(size_t i = 0; i < vector_size::value; i++) + { + result.s[i] = (std::min)(x.s[i], y); + } + return result; + } +}; + +AUTO_TEST_CASE(test_int_numeric_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // ugentype abs(gentype x); + TEST_UNARY_FUNC_MACRO((int_func_abs())) + TEST_UNARY_FUNC_MACRO((int_func_abs())) + TEST_UNARY_FUNC_MACRO((int_func_abs())) + TEST_UNARY_FUNC_MACRO((int_func_abs())) + + // ugentype abs_diff(gentype x, gentype y); + TEST_BINARY_FUNC_MACRO((int_func_abs_diff())) + TEST_BINARY_FUNC_MACRO((int_func_abs_diff())) + TEST_BINARY_FUNC_MACRO((int_func_abs_diff())) + TEST_BINARY_FUNC_MACRO((int_func_abs_diff())) + + // gentype add_sat(gentype x, gentype y); + TEST_BINARY_FUNC_MACRO((int_func_add_sat())) + TEST_BINARY_FUNC_MACRO((int_func_add_sat())) + TEST_BINARY_FUNC_MACRO((int_func_add_sat())) + TEST_BINARY_FUNC_MACRO((int_func_add_sat())) + + // gentype hadd(gentype x, gentype y); + TEST_BINARY_FUNC_MACRO((int_func_hadd())) + TEST_BINARY_FUNC_MACRO((int_func_hadd())) + TEST_BINARY_FUNC_MACRO((int_func_hadd())) + TEST_BINARY_FUNC_MACRO((int_func_hadd())) + + // gentype rhadd(gentype x, gentype y); + TEST_BINARY_FUNC_MACRO((int_func_rhadd())) + TEST_BINARY_FUNC_MACRO((int_func_rhadd())) + TEST_BINARY_FUNC_MACRO((int_func_rhadd())) + TEST_BINARY_FUNC_MACRO((int_func_rhadd())) + + // gentype clamp(gentype x, gentype minval, gentype maxval); + TEST_TERNARY_FUNC_MACRO((int_func_clamp())) + TEST_TERNARY_FUNC_MACRO((int_func_clamp())) + TEST_TERNARY_FUNC_MACRO((int_func_clamp())) + TEST_TERNARY_FUNC_MACRO((int_func_clamp())) + + // gentype clamp(gentype x, scalar minval, scalar maxval); + TEST_TERNARY_FUNC_MACRO((int_func_clamp())) + TEST_TERNARY_FUNC_MACRO((int_func_clamp())) + TEST_TERNARY_FUNC_MACRO((int_func_clamp())) + TEST_TERNARY_FUNC_MACRO((int_func_clamp())) + + // gentype mad_hi(gentype a, gentype b, gentype c); + TEST_TERNARY_FUNC_MACRO((int_func_mad_hi())) + TEST_TERNARY_FUNC_MACRO((int_func_mad_hi())) + TEST_TERNARY_FUNC_MACRO((int_func_mad_hi())) + TEST_TERNARY_FUNC_MACRO((int_func_mad_hi())) + + // gentype mad_sat(gentype a, gentype b, gentype c); + TEST_TERNARY_FUNC_MACRO((int_func_mad_sat())) + TEST_TERNARY_FUNC_MACRO((int_func_mad_sat())) + TEST_TERNARY_FUNC_MACRO((int_func_mad_sat())) + + // gentype max(gentype x, gentype y); + TEST_BINARY_FUNC_MACRO((int_func_max())) + TEST_BINARY_FUNC_MACRO((int_func_max())) + TEST_BINARY_FUNC_MACRO((int_func_max())) + TEST_BINARY_FUNC_MACRO((int_func_max())) + + // gentype max(gentype x, scalar y); + TEST_BINARY_FUNC_MACRO((int_func_max())) + TEST_BINARY_FUNC_MACRO((int_func_max())) + TEST_BINARY_FUNC_MACRO((int_func_max())) + TEST_BINARY_FUNC_MACRO((int_func_max())) + + // gentype min(gentype x, gentype y); + TEST_BINARY_FUNC_MACRO((int_func_min())) + TEST_BINARY_FUNC_MACRO((int_func_min())) + TEST_BINARY_FUNC_MACRO((int_func_min())) + TEST_BINARY_FUNC_MACRO((int_func_min())) + + // gentype min(gentype x, scalar y); + TEST_BINARY_FUNC_MACRO((int_func_min())) + TEST_BINARY_FUNC_MACRO((int_func_min())) + TEST_BINARY_FUNC_MACRO((int_func_min())) + TEST_BINARY_FUNC_MACRO((int_func_min())) + + // gentype mul_hi(gentype x, gentype y); + TEST_BINARY_FUNC_MACRO((int_func_mul_hi())) + TEST_BINARY_FUNC_MACRO((int_func_mul_hi())) + TEST_BINARY_FUNC_MACRO((int_func_mul_hi())) + TEST_BINARY_FUNC_MACRO((int_func_mul_hi())) + + // gentype sub_sat(gentype x, gentype y); + TEST_BINARY_FUNC_MACRO((int_func_sub_sat())) + TEST_BINARY_FUNC_MACRO((int_func_sub_sat())) + TEST_BINARY_FUNC_MACRO((int_func_sub_sat())) + TEST_BINARY_FUNC_MACRO((int_func_sub_sat())) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_INTEGER_FUNCS_NUMERIC_HPP diff --git a/test_conformance/clcpp/math_funcs/CMakeLists.txt b/test_conformance/clcpp/math_funcs/CMakeLists.txt new file mode 100644 index 00000000..8b48aac1 --- /dev/null +++ b/test_conformance/clcpp/math_funcs/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_MATH_FUNCS) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/math_funcs/common.hpp b/test_conformance/clcpp/math_funcs/common.hpp new file mode 100644 index 00000000..32249056 --- /dev/null +++ b/test_conformance/clcpp/math_funcs/common.hpp @@ -0,0 +1,347 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_COMMON_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_COMMON_FUNCS_HPP + +#include +#include + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#include "reference.hpp" + +#ifndef MATH_FUNCS_CLASS_NAME + #define MATH_FUNCS_CLASS_NAME(x, y) x ## _func_ ## y +#endif + +#define MATH_FUNCS_DEFINE_UNARY_FUNC1(GROUP_NAME, NAME, OCL_FUNC, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1) \ +struct MATH_FUNCS_CLASS_NAME(GROUP_NAME, NAME) : public unary_func \ +{ \ + MATH_FUNCS_CLASS_NAME(GROUP_NAME, NAME)(bool is_embedded) : m_is_embedded(is_embedded) \ + { \ + \ + } \ + \ + std::string str() \ + { \ + return #OCL_FUNC; \ + } \ + \ + std::string headers() \ + { \ + return "#include \n"; \ + } \ + /* Reference value type is cl_double */ \ + cl_double operator()(const cl_float& x) \ + { \ + return (HOST_FUNC)(static_cast(x)); \ + } \ + \ + cl_float min1() \ + { \ + return MIN1; \ + } \ + \ + cl_float max1() \ + { \ + return MAX1; \ + } \ + \ + std::vector in1_special_cases() \ + { \ + return { \ + cl_float(0.0f), \ + cl_float(-0.0f), \ + cl_float(1.0f), \ + cl_float(-1.0f), \ + cl_float(2.0f), \ + cl_float(-2.0f), \ + std::numeric_limits::infinity(), \ + -std::numeric_limits::infinity(), \ + std::numeric_limits::quiet_NaN() \ + }; \ + } \ + \ + bool use_ulp() \ + { \ + return USE_ULP; \ + } \ + \ + template \ + typename make_vector_type::value>::type \ + delta(const cl_float& in1, const T& expected) \ + { \ + typedef \ + typename make_vector_type::value>::type \ + delta_vector_type; \ + (void) in1; \ + auto e = detail::make_value(DELTA); \ + return detail::multiply(e, expected); \ + } \ + \ + float ulp() \ + { \ + if(m_is_embedded) \ + { \ + return ULP_EMBEDDED; \ + } \ + return ULP; \ + } \ +private: \ + bool m_is_embedded; \ +}; + +#define MATH_FUNCS_DEFINE_BINARY_FUNC1(GROUP_NAME, NAME, OCL_NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1, MIN2, MAX2) \ +struct MATH_FUNCS_CLASS_NAME(GROUP_NAME, NAME) : public binary_func \ +{ \ + MATH_FUNCS_CLASS_NAME(GROUP_NAME, NAME)(bool is_embedded) : m_is_embedded(is_embedded) \ + { \ + \ + } \ + \ + std::string str() \ + { \ + return #OCL_NAME; \ + } \ + \ + std::string headers() \ + { \ + return "#include \n"; \ + } \ + \ + cl_float operator()(const cl_float& x, const cl_float& y) \ + { \ + return (HOST_FUNC)(x, y); \ + } \ + \ + cl_float min1() \ + { \ + return MIN1; \ + } \ + \ + cl_float max1() \ + { \ + return MAX1; \ + } \ + \ + cl_float min2() \ + { \ + return MIN2; \ + } \ + \ + cl_float max2() \ + { \ + return MAX2; \ + } \ + \ + std::vector in1_special_cases() \ + { \ + return { \ + cl_float(0.0f), \ + cl_float(-0.0f), \ + cl_float(1.0f), \ + cl_float(-1.0f), \ + cl_float(2.0f), \ + cl_float(-2.0f), \ + std::numeric_limits::infinity(), \ + -std::numeric_limits::infinity(), \ + std::numeric_limits::quiet_NaN() \ + }; \ + } \ + \ + std::vector in2_special_cases() \ + { \ + return { \ + cl_float(0.0f), \ + cl_float(-0.0f), \ + cl_float(1.0f), \ + cl_float(-1.0f), \ + cl_float(2.0f), \ + cl_float(-2.0f), \ + std::numeric_limits::infinity(), \ + -std::numeric_limits::infinity(), \ + std::numeric_limits::quiet_NaN() \ + }; \ + } \ + \ + template \ + typename make_vector_type::value>::type \ + delta(const cl_float& in1, const cl_float& in2, const T& expected) \ + { \ + typedef \ + typename make_vector_type::value>::type \ + delta_vector_type; \ + (void) in1; \ + (void) in2; \ + auto e = detail::make_value(DELTA); \ + return detail::multiply(e, expected); \ + } \ + \ + bool use_ulp() \ + { \ + return USE_ULP; \ + } \ + \ + float ulp() \ + { \ + if(m_is_embedded) \ + { \ + return ULP_EMBEDDED; \ + } \ + return ULP; \ + } \ +private: \ + bool m_is_embedded; \ +}; + +#define MATH_FUNCS_DEFINE_TERNARY_FUNC1(GROUP_NAME, NAME, OCL_NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1, MIN2, MAX2, MIN3, MAX3) \ +struct MATH_FUNCS_CLASS_NAME(GROUP_NAME, NAME) : public ternary_func \ +{ \ + MATH_FUNCS_CLASS_NAME(GROUP_NAME, NAME)(bool is_embedded) : m_is_embedded(is_embedded) \ + { \ + \ + } \ + \ + std::string str() \ + { \ + return #OCL_NAME; \ + } \ + \ + std::string headers() \ + { \ + return "#include \n"; \ + } \ + \ + cl_double operator()(const cl_float& x, const cl_float& y, const cl_float& z) \ + { \ + return (HOST_FUNC)(static_cast(x), static_cast(y), static_cast(z)); \ + } \ + \ + cl_float min1() \ + { \ + return MIN1; \ + } \ + \ + cl_float max1() \ + { \ + return MAX1; \ + } \ + \ + cl_float min2() \ + { \ + return MIN2; \ + } \ + \ + cl_float max2() \ + { \ + return MAX2; \ + } \ + \ + cl_float min3() \ + { \ + return MIN3; \ + } \ + \ + cl_float max3() \ + { \ + return MAX3; \ + } \ + \ + std::vector in1_special_cases() \ + { \ + return { \ + cl_float(0.0f), \ + cl_float(-0.0f), \ + cl_float(1.0f), \ + cl_float(-1.0f), \ + cl_float(2.0f), \ + cl_float(-2.0f), \ + std::numeric_limits::infinity(), \ + -std::numeric_limits::infinity(), \ + std::numeric_limits::quiet_NaN() \ + }; \ + } \ + \ + std::vector in2_special_cases() \ + { \ + return { \ + cl_float(0.0f), \ + cl_float(-0.0f), \ + cl_float(1.0f), \ + cl_float(-1.0f), \ + cl_float(2.0f), \ + cl_float(-2.0f), \ + std::numeric_limits::infinity(), \ + -std::numeric_limits::infinity(), \ + std::numeric_limits::quiet_NaN() \ + }; \ + } \ + \ + std::vector in3_special_cases() \ + { \ + return { \ + cl_float(0.0f), \ + cl_float(-0.0f), \ + cl_float(1.0f), \ + cl_float(-1.0f), \ + cl_float(2.0f), \ + cl_float(-2.0f), \ + std::numeric_limits::infinity(), \ + -std::numeric_limits::infinity(), \ + std::numeric_limits::quiet_NaN() \ + }; \ + } \ + \ + template \ + typename make_vector_type::value>::type \ + delta(const cl_float& in1, const cl_float& in2, const cl_float& in3, const T& expected) \ + { \ + typedef \ + typename make_vector_type::value>::type \ + delta_vector_type; \ + (void) in1; \ + (void) in2; \ + (void) in3; \ + auto e = detail::make_value(DELTA); \ + return detail::multiply(e, expected); \ + } \ + \ + bool use_ulp() \ + { \ + return USE_ULP; \ + } \ + \ + float ulp() \ + { \ + if(m_is_embedded) \ + { \ + return ULP_EMBEDDED; \ + } \ + return ULP; \ + } \ +private: \ + bool m_is_embedded; \ +}; + +#define MATH_FUNCS_DEFINE_UNARY_FUNC(GROUP_NAME, NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1) \ + MATH_FUNCS_DEFINE_UNARY_FUNC1(GROUP_NAME, NAME, NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1) +#define MATH_FUNCS_DEFINE_BINARY_FUNC(GROUP_NAME, NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1, MIN2, MAX2) \ + MATH_FUNCS_DEFINE_BINARY_FUNC1(GROUP_NAME, NAME, NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1, MIN2, MAX2) +#define MATH_FUNCS_DEFINE_TERNARY_FUNC(GROUP_NAME, NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1, MIN2, MAX2, MIN3, MAX3) \ + MATH_FUNCS_DEFINE_TERNARY_FUNC1(GROUP_NAME, NAME, NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1, MIN2, MAX2, MIN3, MAX3) + +#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_COMMON_FUNCS_HPP diff --git a/test_conformance/clcpp/math_funcs/comparison_funcs.hpp b/test_conformance/clcpp/math_funcs/comparison_funcs.hpp new file mode 100644 index 00000000..0bd6ff91 --- /dev/null +++ b/test_conformance/clcpp/math_funcs/comparison_funcs.hpp @@ -0,0 +1,59 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_COMPARISON_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_COMPARISON_FUNCS_HPP + +#include +#include + +#include "common.hpp" + +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1 +MATH_FUNCS_DEFINE_BINARY_FUNC(comparison, fdim, std::fdim, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_BINARY_FUNC(comparison, fmax, std::fmax, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_BINARY_FUNC(comparison, fmin, std::fmin, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_BINARY_FUNC(comparison, maxmag, reference::maxmag, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_BINARY_FUNC(comparison, minmag, reference::minmag, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f, -1000.0f, 1000.0f) + +// comparison functions +AUTO_TEST_CASE(test_comparison_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // Check for EMBEDDED_PROFILE + bool is_embedded_profile = false; + char profile[128]; + last_error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL); + RETURN_ON_CL_ERROR(last_error, "clGetDeviceInfo") + if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0) + is_embedded_profile = true; + + TEST_BINARY_FUNC_MACRO((comparison_func_fdim(is_embedded_profile))) + TEST_BINARY_FUNC_MACRO((comparison_func_fmax(is_embedded_profile))) + TEST_BINARY_FUNC_MACRO((comparison_func_fmin(is_embedded_profile))) + TEST_BINARY_FUNC_MACRO((comparison_func_maxmag(is_embedded_profile))) + TEST_BINARY_FUNC_MACRO((comparison_func_minmag(is_embedded_profile))) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_COMPARISON_FUNCS_HPP diff --git a/test_conformance/clcpp/math_funcs/exponential_funcs.hpp b/test_conformance/clcpp/math_funcs/exponential_funcs.hpp new file mode 100644 index 00000000..82a8247a --- /dev/null +++ b/test_conformance/clcpp/math_funcs/exponential_funcs.hpp @@ -0,0 +1,139 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_EXP_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_EXP_FUNCS_HPP + +#include +#include + +#include "common.hpp" + +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1 +MATH_FUNCS_DEFINE_UNARY_FUNC(exponential, exp, std::exp, true, 3.0f, 4.0f, 0.001f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(exponential, expm1, std::expm1, true, 3.0f, 4.0f, 0.001f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(exponential, exp2, std::exp2, true, 3.0f, 4.0f, 0.001f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(exponential, exp10, reference::exp10, true, 3.0f, 4.0f, 0.001f, -1000.0f, 1000.0f) + +struct exponential_func_ldexp : public binary_func +{ + exponential_func_ldexp(bool is_embedded) : m_is_embedded(is_embedded) + { + + } + + std::string str() + { + return "ldexp"; + } + + std::string headers() + { + return "#include \n"; + } + + /* Reference value type is cl_double */ + cl_double operator()(const cl_float& x, const cl_int& y) + { + return (std::ldexp)(static_cast(x), y); + } + + cl_float min1() + { + return -1000.0f; + } + + cl_float max1() + { + return 1000.0f; + } + + cl_int min2() + { + return -8; + } + + cl_int max2() + { + return 8; + } + + std::vector in1_special_cases() + { + return { + cl_float(0.0f), + cl_float(-0.0f), + cl_float(1.0f), + cl_float(-1.0f), + cl_float(2.0f), + cl_float(-2.0f), + std::numeric_limits::infinity(), + -std::numeric_limits::infinity(), + std::numeric_limits::quiet_NaN() + }; + } + + bool use_ulp() + { + return true; + } + + float ulp() + { + if(m_is_embedded) + { + return 0.0f; + } + return 0.0f; + } +private: + bool m_is_embedded; +}; + +// exponential functions +AUTO_TEST_CASE(test_exponential_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // Check for EMBEDDED_PROFILE + bool is_embedded_profile = false; + char profile[128]; + last_error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL); + RETURN_ON_CL_ERROR(last_error, "clGetDeviceInfo") + if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0) + is_embedded_profile = true; + + // auto exp(gentype x); + // auto expm1(gentype x); + // auto exp2(gentype x); + // auto exp10(gentype x); + TEST_UNARY_FUNC_MACRO((exponential_func_exp(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((exponential_func_expm1(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((exponential_func_exp2(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((exponential_func_exp10(is_embedded_profile))) + + // auto ldexp(gentype x, intn k); + TEST_BINARY_FUNC_MACRO((exponential_func_ldexp(is_embedded_profile))) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_EXP_FUNCS_HPP diff --git a/test_conformance/clcpp/math_funcs/floating_point_funcs.hpp b/test_conformance/clcpp/math_funcs/floating_point_funcs.hpp new file mode 100644 index 00000000..63b4c230 --- /dev/null +++ b/test_conformance/clcpp/math_funcs/floating_point_funcs.hpp @@ -0,0 +1,733 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_FP_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_FP_FUNCS_HPP + +#include +#include + +#include "common.hpp" + +// -------------- UNARY FUNCTIONS + +// gentype ceil(gentype x); +// gentype floor(gentype x); +// gentype rint(gentype x); +// gentype round(gentype x); +// gentype trunc(gentype x); +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1 +MATH_FUNCS_DEFINE_UNARY_FUNC(fp, ceil, std::ceil, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(fp, floor, std::floor, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(fp, rint, std::rint, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(fp, round, std::round, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(fp, trunc, std::trunc, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f) + +// floatn nan(uintn nancode); +struct fp_func_nan : public unary_func +{ + std::string str() + { + return "nan"; + } + + std::string headers() + { + return "#include \n"; + } + + cl_float operator()(const cl_uint& x) + { + cl_uint r = x | 0x7fc00000U; + // cl_float and cl_int have the same size so that's correct + cl_float rf = *reinterpret_cast(&r); + return rf; + } + + cl_uint min1() + { + return 0; + } + + cl_uint max1() + { + return 100; + } + + std::vector in1_special_cases() + { + return { + 0, 1 + }; + } +}; + +// -------------- UNARY FUNCTIONS, 2ND ARG IS POINTER + +// gentype fract(gentype x, gentype* iptr); +// +// Fuction fract() returns additional value via pointer (2nd argument). In order to test +// if it's correct output buffer type is cl_float2. In first compontent we store what +// fract() function returns, and in the 2nd component we store what is returned via its +// 2nd argument (gentype* iptr). +struct fp_func_fract : public unary_func +{ + fp_func_fract(bool is_embedded) : m_is_embedded(is_embedded) + { + + } + + std::string str() + { + return "fract"; + } + + std::string headers() + { + return "#include \n"; + } + + cl_double2 operator()(const cl_float& x) + { + return reference::fract(static_cast(x)); + } + + cl_float min1() + { + return -1000.0f; + } + + cl_float max1() + { + return 1000.0f; + } + + std::vector in1_special_cases() + { + return { + cl_float(0.0f), + cl_float(-0.0f), + cl_float(1.0f), + cl_float(-1.0f), + cl_float(2.0f), + cl_float(-2.0f), + std::numeric_limits::infinity(), + -std::numeric_limits::infinity(), + std::numeric_limits::quiet_NaN() + }; + } + + bool use_ulp() + { + return true; + } + + float ulp() + { + if(m_is_embedded) + { + return 0.0f; + } + return 0.0f; + } +private: + bool m_is_embedded; +}; + +// We need to specialize generate_kernel_unary<>() function template for fp_func_fract. +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template <> +std::string generate_kernel_unary(fp_func_fract func) +{ + return + "__kernel void test_fract(global float *input, global float2 *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " float2 result;\n" + " float itpr = 0;\n" + " result.x = fract(input[gid], &itpr);\n" + " result.y = itpr;\n" + " output[gid] = result;\n" + "}\n"; +} +#else +template <> +std::string generate_kernel_unary(fp_func_fract func) +{ + return + "" + func.defs() + + "" + func.headers() + + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_fract(global_ptr input, global_ptr output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " float2 result;\n" + " float itpr = 0;\n" + " result.x = fract(input[gid], &itpr);\n" + " result.y = itpr;\n" + " output[gid] = result;\n" + "}\n"; +} +#endif + +// gentype modf(gentype x, gentype* iptr); +// +// Fuction modf() returns additional value via pointer (2nd argument). In order to test +// if it's correct output buffer type is cl_float2. In first compontent we store what +// modf() function returns, and in the 2nd component we store what is returned via its +// 2nd argument (gentype* iptr). +struct fp_func_modf : public unary_func +{ + fp_func_modf(bool is_embedded) : m_is_embedded(is_embedded) + { + + } + + std::string str() + { + return "modf"; + } + + std::string headers() + { + return "#include \n"; + } + + cl_double2 operator()(const cl_float& x) + { + cl_double2 r; + r.s[0] = (std::modf)(static_cast(x), &(r.s[1])); + return r; + } + + cl_float min1() + { + return -1000.0f; + } + + cl_float max1() + { + return 1000.0f; + } + + std::vector in1_special_cases() + { + return { + cl_float(0.0f), + cl_float(-0.0f), + cl_float(1.0f), + cl_float(-1.0f), + cl_float(2.0f), + cl_float(-2.0f), + std::numeric_limits::infinity(), + -std::numeric_limits::infinity(), + std::numeric_limits::quiet_NaN() + }; + } + + bool use_ulp() + { + return true; + } + + float ulp() + { + if(m_is_embedded) + { + return 0.0f; + } + return 0.0f; + } +private: + bool m_is_embedded; +}; + +// We need to specialize generate_kernel_unary<>() function template for fp_func_modf. +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template <> +std::string generate_kernel_unary(fp_func_modf func) +{ + return + "__kernel void test_modf(global float *input, global float2 *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " float2 result;\n" + " float itpr = 0;\n" + " result.x = modf(input[gid], &itpr);\n" + " result.y = itpr;\n" + " output[gid] = result;\n" + "}\n"; +} +#else +template <> +std::string generate_kernel_unary(fp_func_modf func) +{ + return + "" + func.defs() + + "" + func.headers() + + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_modf(global_ptr input, global_ptr output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " float2 result;\n" + " float itpr = 0;\n" + " result.x = modf(input[gid], &itpr);\n" + " result.y = itpr;\n" + " output[gid] = result;\n" + "}\n"; +} +#endif + +// gentype frexp(gentype x, intn* exp); +// +// Fuction frexp() returns additional value via pointer (2nd argument). In order to test +// if it's correct output buffer type is cl_float2. In first compontent we store what +// modf() function returns, and in the 2nd component we store what is returned via its +// 2nd argument (intn* exp). +struct fp_func_frexp : public unary_func +{ + fp_func_frexp(bool is_embedded) : m_is_embedded(is_embedded) + { + + } + + std::string str() + { + return "frexp"; + } + + std::string headers() + { + return "#include \n"; + } + + cl_double2 operator()(const cl_float& x) + { + cl_double2 r; + cl_int e; + r.s[0] = (std::frexp)(static_cast(x), &e); + r.s[1] = static_cast(e); + return r; + } + + cl_float min1() + { + return -1000.0f; + } + + cl_float max1() + { + return 1000.0f; + } + + std::vector in1_special_cases() + { + return { + cl_float(0.0f), + cl_float(-0.0f), + cl_float(1.0f), + cl_float(-1.0f), + cl_float(2.0f), + cl_float(-2.0f), + std::numeric_limits::infinity(), + -std::numeric_limits::infinity(), + std::numeric_limits::quiet_NaN() + }; + } + + bool use_ulp() + { + return true; + } + + float ulp() + { + if(m_is_embedded) + { + return 0.0f; + } + return 0.0f; + } +private: + bool m_is_embedded; +}; + +// We need to specialize generate_kernel_unary<>() function template for fp_func_frexp. +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template <> +std::string generate_kernel_unary(fp_func_frexp func) +{ + return + "__kernel void test_frexp(global float *input, global float2 *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " float2 result;\n" + " int itpr = 0;\n" + " result.x = frexp(input[gid], &itpr);\n" + " result.y = itpr;\n" + " output[gid] = result;\n" + "}\n"; +} +#else +template <> +std::string generate_kernel_unary(fp_func_frexp func) +{ + return + "" + func.defs() + + "" + func.headers() + + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_frexp(global_ptr input, global_ptr output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " float2 result;\n" + " int itpr = 0;\n" + " result.x = frexp(input[gid], &itpr);\n" + " result.y = itpr;\n" + " output[gid] = result;\n" + "}\n"; +} +#endif + +// -------------- BINARY FUNCTIONS + +// gentype copysign(gentype x, gentype y); +// gentype fmod(gentype x, gentype y); +// gentype remainder(gentype x, gentype y); +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2 +MATH_FUNCS_DEFINE_BINARY_FUNC(fp, copysign, std::copysign, true, 0.0f, 0.0f, 0.001f, -100.0f, 100.0f, -10.0f, 10.0f) +MATH_FUNCS_DEFINE_BINARY_FUNC(fp, fmod, std::fmod, true, 0.0f, 0.0f, 0.001f, -100.0f, 100.0f, -10.0f, 10.0f) +MATH_FUNCS_DEFINE_BINARY_FUNC(fp, remainder, std::remainder, true, 0.0f, 0.001f, 0.0f, -100.0f, 100.0f, -10.0f, 10.0f) + +// In case of function float nextafter(float, float) reference function must +// operate on floats and return float. +struct fp_func_nextafter : public binary_func +{ + fp_func_nextafter(bool is_embedded) : m_is_embedded(is_embedded) + { + + } + + std::string str() + { + return "nextafter"; + } + + std::string headers() + { + return "#include \n"; + } + + /* In this case reference value type MUST BE cl_float */ + cl_float operator()(const cl_float& x, const cl_float& y) + { + return (std::nextafter)(x, y); + } + + cl_float min1() + { + return -1000.0f; + } + + cl_float max1() + { + return 500.0f; + } + + cl_float min2() + { + return 501.0f; + } + + cl_float max2() + { + return 1000.0f; + } + + std::vector in1_special_cases() + { + return { + cl_float(0.0f), + cl_float(-0.0f), + cl_float(1.0f), + cl_float(-1.0f), + cl_float(2.0f), + cl_float(-2.0f), + std::numeric_limits::infinity(), + -std::numeric_limits::infinity(), + std::numeric_limits::quiet_NaN() + }; + } + + std::vector in2_special_cases() + { + return { + cl_float(0.0f), + cl_float(-0.0f), + cl_float(1.0f), + cl_float(-1.0f), + cl_float(2.0f), + cl_float(-2.0f), + std::numeric_limits::infinity(), + -std::numeric_limits::infinity(), + std::numeric_limits::quiet_NaN() + }; + } + + bool use_ulp() + { + return true; + } + + float ulp() + { + if(m_is_embedded) + { + return 0.0f; + } + return 0.0f; + } +private: + bool m_is_embedded; +}; + +// gentype remquo(gentype x, gentype y, intn* quo); +struct fp_func_remquo : public binary_func +{ + fp_func_remquo(bool is_embedded) : m_is_embedded(is_embedded) + { + + } + + std::string str() + { + return "remquo"; + } + + std::string headers() + { + return "#include \n"; + } + + cl_double2 operator()(const cl_float& x, const cl_float& y) + { + return reference::remquo(static_cast(x), static_cast(y)); + } + + cl_float min1() + { + return -1000.0f; + } + + cl_float max1() + { + return 1000.0f; + } + + cl_float min2() + { + return -1000.0f; + } + + cl_float max2() + { + return 1000.0f; + } + + std::vector in1_special_cases() + { + return { + cl_float(0.0f), + cl_float(-0.0f), + cl_float(1.0f), + cl_float(-1.0f), + std::numeric_limits::infinity(), + -std::numeric_limits::infinity(), + std::numeric_limits::quiet_NaN() + }; + } + + std::vector in2_special_cases() + { + return { + cl_float(0.0f), + cl_float(-0.0f), + cl_float(1.0f), + cl_float(-1.0f), + std::numeric_limits::infinity(), + -std::numeric_limits::infinity(), + std::numeric_limits::quiet_NaN() + }; + } + + bool use_ulp() + { + return true; + } + + float ulp() + { + if(m_is_embedded) + { + return 0.0f; + } + return 0.0f; + } +private: + bool m_is_embedded; +}; + + +// We need to specialize generate_kernel_binary<>() function template for fp_func_remquo. +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template <> +std::string generate_kernel_binary(fp_func_remquo func) +{ + return + "__kernel void test_remquo(global float *input1, global float *input2, global float2 *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " float2 result;\n" + " int quo = 0;\n" + " int sign = 0;\n" + " result.x = remquo(input1[gid], input2[gid], &quo);\n" + // Specification say: + // "remquo also calculates the lower seven bits of the integral quotient x/y, + // and gives that value the same sign as x/y. It stores this signed value in + // the object pointed to by quo." + // Implemenation may save into quo more than seven bits. We need to take + // care of that here. + " sign = (quo < 0) ? -1 : 1;\n" + " quo = (quo < 0) ? -quo : quo;\n" + " quo &= 0x0000007f;\n" + " result.y = (sign < 0) ? -quo : quo;\n" + " output[gid] = result;\n" + "}\n"; +} +#else +template <> +std::string generate_kernel_binary(fp_func_remquo func) +{ + return + "" + func.defs() + + "" + func.headers() + + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_remquo(global_ptr input1, global_ptr input2, global_ptr output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " float2 result;\n" + " int quo = 0;\n" + " int sign = 0;\n" + " result.x = remquo(input1[gid], input2[gid], &quo);\n" + // Specification say: + // "remquo also calculates the lower seven bits of the integral quotient x/y, + // and gives that value the same sign as x/y. It stores this signed value in + // the object pointed to by quo." + // Implemenation may save into quo more than seven bits. We need to take + // care of that here. + " sign = (quo < 0) ? -1 : 1;\n" + " quo = (quo < 0) ? -quo : quo;\n" + " quo &= 0x0000007f;\n" + " result.y = (sign < 0) ? -quo : quo;\n" + " output[gid] = result;\n" + "}\n"; +} +#endif + +// -------------- TERNARY FUNCTIONS + +// gentype fma(gentype a, gentype b, gentype c); +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2, min3, max3 +MATH_FUNCS_DEFINE_TERNARY_FUNC(fp, fma, std::fma, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f, -1000.0f, 1000.0f, -1000.0f, 1000.0f) + +// floating point functions +AUTO_TEST_CASE(test_fp_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // Check for EMBEDDED_PROFILE + bool is_embedded_profile = false; + char profile[128]; + last_error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL); + RETURN_ON_CL_ERROR(last_error, "clGetDeviceInfo") + if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0) + is_embedded_profile = true; + + // gentype ceil(gentype x); + TEST_UNARY_FUNC_MACRO((fp_func_ceil(is_embedded_profile))) + // gentype floor(gentype x); + TEST_UNARY_FUNC_MACRO((fp_func_floor(is_embedded_profile))) + // gentype rint(gentype x); + TEST_UNARY_FUNC_MACRO((fp_func_rint(is_embedded_profile))) + // gentype round(gentype x); + TEST_UNARY_FUNC_MACRO((fp_func_round(is_embedded_profile))) + // gentype trunc(gentype x); + TEST_UNARY_FUNC_MACRO((fp_func_trunc(is_embedded_profile))) + + // floatn nan(uintn nancode); + TEST_UNARY_FUNC_MACRO((fp_func_nan())) + + // gentype fract(gentype x, gentype* iptr); + TEST_UNARY_FUNC_MACRO((fp_func_fract(is_embedded_profile))) + // gentype modf(gentype x, gentype* iptr); + TEST_UNARY_FUNC_MACRO((fp_func_modf(is_embedded_profile))) + // gentype frexp(gentype x, intn* exp); + TEST_UNARY_FUNC_MACRO((fp_func_frexp(is_embedded_profile))) + + // gentype remainder(gentype x, gentype y); + TEST_BINARY_FUNC_MACRO((fp_func_remainder(is_embedded_profile))) + // gentype copysign(gentype x, gentype y); + TEST_BINARY_FUNC_MACRO((fp_func_copysign(is_embedded_profile))) + // gentype fmod(gentype x, gentype y); + TEST_BINARY_FUNC_MACRO((fp_func_fmod(is_embedded_profile))) + + // gentype nextafter(gentype x, gentype y); + TEST_BINARY_FUNC_MACRO((fp_func_nextafter(is_embedded_profile))) + + // gentype remquo(gentype x, gentype y, intn* quo); + TEST_BINARY_FUNC_MACRO((fp_func_remquo(is_embedded_profile))) + + // gentype fma(gentype a, gentype b, gentype c); + TEST_TERNARY_FUNC_MACRO((fp_func_fma(is_embedded_profile))) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_FP_FUNCS_HPP diff --git a/test_conformance/clcpp/math_funcs/half_math_funcs.hpp b/test_conformance/clcpp/math_funcs/half_math_funcs.hpp new file mode 100644 index 00000000..d72d717c --- /dev/null +++ b/test_conformance/clcpp/math_funcs/half_math_funcs.hpp @@ -0,0 +1,106 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_HALF_MATH_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_HALF_MATH_FUNCS_HPP + +#include +#include + +#include "common.hpp" + +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1 +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, cos, half_cos, std::cos, true, 8192.0f, 8192.0f, 0.1f, -CL_M_PI_F, CL_M_PI_F) +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, sin, half_sin, std::sin, true, 8192.0f, 8192.0f, 0.1f, -CL_M_PI_F, CL_M_PI_F) +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, tan, half_tan, std::tan, true, 8192.0f, 8192.0f, 0.1f, -CL_M_PI_F, CL_M_PI_F) + +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, exp, half_exp, std::exp, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, exp2, half_exp2, std::exp2, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, exp10, half_exp10, reference::exp10, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) + +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, log, half_log, std::log, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, log2, half_log2, std::log2, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, log10, half_log10, std::log10, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) + +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, rsqrt, half_rsqrt, reference::rsqrt, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, sqrt, half_sqrt, std::sqrt, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) + +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, recip, half_recip, reference::recip, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) + +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2 +MATH_FUNCS_DEFINE_BINARY_FUNC1(half_math, divide, half_divide, reference::divide, true, 8192.0f, 8192.0f, 0.1f, -1024.0f, 1024.0f, -1024.0f, 1024.0f) +MATH_FUNCS_DEFINE_BINARY_FUNC1(half_math, powr, half_powr, reference::powr, true, 8192.0f, 8192.0f, 0.1f, -1024.0f, 1024.0f, -1024.0f, 1024.0f) +#else +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1 +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, cos, half_math::cos, std::cos, true, 8192.0f, 8192.0f, 0.1f, -CL_M_PI_F, CL_M_PI_F) +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, sin, half_math::sin, std::sin, true, 8192.0f, 8192.0f, 0.1f, -CL_M_PI_F, CL_M_PI_F) +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, tan, half_math::tan, std::tan, true, 8192.0f, 8192.0f, 0.1f, -CL_M_PI_F, CL_M_PI_F) + +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, exp, half_math::exp, std::exp, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, exp2, half_math::exp2, std::exp2, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, exp10, half_math::exp10, reference::exp10, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) + +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, log, half_math::log, std::log, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, log2, half_math::log2, std::log2, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, log10, half_math::log10, std::log10, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) + +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, rsqrt, half_math::rsqrt, reference::rsqrt, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, sqrt, half_math::sqrt, std::sqrt, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) + +MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, recip, half_math::recip, reference::recip, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f) + +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2 +MATH_FUNCS_DEFINE_BINARY_FUNC1(half_math, divide, half_math::divide, reference::divide, true, 8192.0f, 8192.0f, 0.1f, -1024.0f, 1024.0f, -1024.0f, 1024.0f) +MATH_FUNCS_DEFINE_BINARY_FUNC1(half_math, powr, half_math::powr, reference::powr, true, 8192.0f, 8192.0f, 0.1f, -1024.0f, 1024.0f, -1024.0f, 1024.0f) +#endif + +// comparison functions +AUTO_TEST_CASE(test_half_math_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // Check for EMBEDDED_PROFILE + bool is_embedded_profile = false; + char profile[128]; + last_error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL); + RETURN_ON_CL_ERROR(last_error, "clGetDeviceInfo") + if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0) + is_embedded_profile = true; + + TEST_UNARY_FUNC_MACRO((half_math_func_cos(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((half_math_func_sin(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((half_math_func_tan(is_embedded_profile))) + + TEST_UNARY_FUNC_MACRO((half_math_func_exp(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((half_math_func_exp2(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((half_math_func_exp10(is_embedded_profile))) + + TEST_UNARY_FUNC_MACRO((half_math_func_log(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((half_math_func_log2(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((half_math_func_log10(is_embedded_profile))) + + TEST_BINARY_FUNC_MACRO((half_math_func_divide(is_embedded_profile))) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_HALF_MATH_FUNCS_HPP diff --git a/test_conformance/clcpp/math_funcs/logarithmic_funcs.hpp b/test_conformance/clcpp/math_funcs/logarithmic_funcs.hpp new file mode 100644 index 00000000..cd25d8e8 --- /dev/null +++ b/test_conformance/clcpp/math_funcs/logarithmic_funcs.hpp @@ -0,0 +1,260 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_LOG_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_LOG_FUNCS_HPP + +#include +#include + +#include "common.hpp" + +namespace detail +{ + +// This function reads values of FP_ILOGB0 and FP_ILOGBNAN macros defined on the device. +// OpenCL C++ Spec: +// The value of FP_ILOGB0 shall be either {INT_MIN} or {INT_MAX}. The value of FP_ILOGBNAN +// shall be either {INT_MAX} or {INT_MIN}. +int get_ilogb_nan_zero(cl_device_id device, cl_context context, cl_command_queue queue, cl_int& ilogb_nan, cl_int& ilogb_zero) +{ + cl_mem buffers[1]; + cl_program program; + cl_kernel kernel; + size_t work_size[1]; + int err; + + std::string code_str = + "__kernel void get_ilogb_nan_zero(__global int *out)\n" + "{\n" + " out[0] = FP_ILOGB0;\n" + " out[1] = FP_ILOGBNAN;\n" + "}\n"; + std::string kernel_name("get_ilogb_nan_zero"); + + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name, "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) + + std::vector output = generate_output(2); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + work_size[0] = 1; + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(cl_int) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + // Save + ilogb_zero = output[0]; + ilogb_nan = output[1]; + + clReleaseMemObject(buffers[0]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +} // namespace detail + +struct logarithmic_func_ilogb : public unary_func +{ + logarithmic_func_ilogb(cl_int ilogb_nan, cl_int ilogb_zero) + : m_ilogb_nan(ilogb_nan), m_ilogb_zero(ilogb_zero) + { + + } + + std::string str() + { + return "ilogb"; + } + + std::string headers() + { + return "#include \n"; + } + + cl_int operator()(const cl_float& x) + { + if((std::isnan)(x)) + { + return m_ilogb_nan; + } + else if(x == 0.0 || x == -0.0) + { + return m_ilogb_zero; + } + static_assert( + sizeof(cl_int) == sizeof(int), + "Tests assumes that sizeof(cl_int) == sizeof(int)" + ); + return (std::ilogb)(x); + } + + cl_float min1() + { + return -100.0f; + } + + cl_float max1() + { + return 1000.0f; + } + + std::vector in1_special_cases() + { + return { + cl_float(0.0f), + cl_float(-0.0f), + cl_float(1.0f), + cl_float(-1.0f), + cl_float(2.0f), + cl_float(-2.0f), + std::numeric_limits::infinity(), + -std::numeric_limits::infinity(), + std::numeric_limits::quiet_NaN() + }; + } +private: + cl_int m_ilogb_nan; + cl_int m_ilogb_zero; +}; + +// gentype log(gentype x); +// gentype logb(gentype x); +// gentype log2(gentype x); +// gentype log10(gentype x); +// gentype log1p(gentype x); +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1 +MATH_FUNCS_DEFINE_UNARY_FUNC(logarithmic, log, std::log, true, 3.0f, 4.0f, 0.001f, -10.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(logarithmic, logb, std::logb, true, 0.0f, 0.0f, 0.001f, -10.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(logarithmic, log2, std::log2, true, 3.0f, 4.0f, 0.001f, -10.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(logarithmic, log10, std::log10, true, 3.0f, 4.0f, 0.001f, -10.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(logarithmic, log1p, std::log1p, true, 2.0f, 4.0f, 0.001f, -10.0f, 1000.0f) + +// gentype lgamma(gentype x); +// OpenCL C++ Spec.: +// The ULP values for built-in math functions lgamma and lgamma_r is currently undefined. +// Because of that we don't check ULP and set acceptable delta to 0.2f (20%). +MATH_FUNCS_DEFINE_UNARY_FUNC(logarithmic, lgamma, std::lgamma, false, 0.0f, 0.0f, 0.2f, -10.0f, 1000.0f) + +// gentype lgamma_r(gentype x, intn* signp); +// OpenCL C++ Spec.: +// The ULP values for built-in math functions lgamma and lgamma_r is currently undefined. +// Because of that we don't check ULP and set acceptable delta to 0.2f (20%). +// +// Note: +// We DO NOT test if sign of the gamma function return by lgamma_r is correct. +MATH_FUNCS_DEFINE_UNARY_FUNC(logarithmic, lgamma_r, std::lgamma, false, 0.0f, 0.0f, 0.2f, -10.0f, 1000.0f) + +// We need to specialize generate_kernel_unary<>() function template for logarithmic_func_lgamma_r +// because it takes two arguments, but only one of it is input, the 2nd one is used to return +// the sign of the gamma function. +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template <> +std::string generate_kernel_unary(logarithmic_func_lgamma_r func) +{ + return + "__kernel void test_lgamma_r(global float *input, global float *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " int sign;\n" + " output[gid] = lgamma_r(input[gid], &sign);\n" + "}\n"; +} +#else +template <> +std::string generate_kernel_unary(logarithmic_func_lgamma_r func) +{ + return + "" + func.defs() + + "" + func.headers() + + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_lgamma_r(global_ptr input, global_ptr output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " int sign;\n" + " output[gid] = lgamma_r(input[gid], &sign);\n" + "}\n"; +} +#endif + +// logarithmic functions +AUTO_TEST_CASE(test_logarithmic_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // Check for EMBEDDED_PROFILE + bool is_embedded_profile = false; + char profile[128]; + error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL); + RETURN_ON_CL_ERROR(error, "clGetDeviceInfo") + if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0) + is_embedded_profile = true; + + // Write values of FP_ILOGB0 and FP_ILOGBNAN, which are macros defined on the device, to + // ilogb_zero and ilogb_nan. + cl_int ilogb_nan = 0; + cl_int ilogb_zero = 0; + error = detail::get_ilogb_nan_zero(device, context, queue, ilogb_nan, ilogb_zero); + RETURN_ON_ERROR_MSG(error, "detail::get_ilogb_nan_zero function failed"); + + // intn ilogb(gentype x); + TEST_UNARY_FUNC_MACRO((logarithmic_func_ilogb(ilogb_nan, ilogb_zero))) + + // gentype log(gentype x); + // gentype logb(gentype x); + // gentype log2(gentype x); + // gentype log10(gentype x); + // gentype log1p(gentype x); + TEST_UNARY_FUNC_MACRO((logarithmic_func_log(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((logarithmic_func_logb(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((logarithmic_func_log2(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((logarithmic_func_log10(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((logarithmic_func_log1p(is_embedded_profile))) + + // gentype lgamma(gentype x); + TEST_UNARY_FUNC_MACRO((logarithmic_func_lgamma(is_embedded_profile))) + + // gentype lgamma(gentype x); + // + // Note: + // We DO NOT test if sign of the gamma function return by lgamma_r is correct + TEST_UNARY_FUNC_MACRO((logarithmic_func_lgamma_r(is_embedded_profile))) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_LOG_FUNCS_HPP diff --git a/test_conformance/clcpp/math_funcs/main.cpp b/test_conformance/clcpp/math_funcs/main.cpp new file mode 100644 index 00000000..f2106253 --- /dev/null +++ b/test_conformance/clcpp/math_funcs/main.cpp @@ -0,0 +1,55 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include + +#include "../common.hpp" + +#include "comparison_funcs.hpp" +#include "exponential_funcs.hpp" +#include "floating_point_funcs.hpp" +#include "half_math_funcs.hpp" +#include "logarithmic_funcs.hpp" +#include "other_funcs.hpp" +#include "power_funcs.hpp" +#include "trigonometric_funcs.hpp" + +int main(int argc, const char *argv[]) +{ + // Check if cl_float (float) and cl_double (double) fulfill the requirements of + // IEC 559 (IEEE 754) standard. This is required for the tests to run correctly. + if(!std::numeric_limits::is_iec559) + { + RETURN_ON_ERROR_MSG(-1, + "cl_float (float) does not fulfill the requirements of IEC 559 (IEEE 754) standard. " + "Tests won't run correctly." + ); + } + if(!std::numeric_limits::is_iec559) + { + RETURN_ON_ERROR_MSG(-1, + "cl_double (double) does not fulfill the requirements of IEC 559 (IEEE 754) standard. " + "Tests won't run correctly." + ); + } + + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/math_funcs/other_funcs.hpp b/test_conformance/clcpp/math_funcs/other_funcs.hpp new file mode 100644 index 00000000..f939a567 --- /dev/null +++ b/test_conformance/clcpp/math_funcs/other_funcs.hpp @@ -0,0 +1,75 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_OTHER_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_OTHER_FUNCS_HPP + +#include +#include + +#include "common.hpp" + +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1 +MATH_FUNCS_DEFINE_UNARY_FUNC(other, erfc, std::erfc, true, 16.0f, 16.0f, 0.001f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(other, erf, std::erf, true, 16.0f, 16.0f, 0.001f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(other, fabs, std::fabs, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(other, tgamma, std::tgamma, true, 16.0f, 16.0f, 0.001f, -1000.0f, 1000.0f) + +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2 +MATH_FUNCS_DEFINE_BINARY_FUNC(other, hypot, std::hypot, true, 4.0f, 4.0f, 0.001f, -1000.0f, 1000.0f, -1000.0f, 1000.0f) + +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2, min3, max3 +MATH_FUNCS_DEFINE_TERNARY_FUNC(other, mad, reference::mad, false, 0.0f, 0.0f, 0.1f, -10.0f, 10.0f, -10.0f, 10.0f, -10.0f, 10.0f) + +// other functions +AUTO_TEST_CASE(test_other_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // Check for EMBEDDED_PROFILE + bool is_embedded_profile = false; + char profile[128]; + last_error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL); + RETURN_ON_CL_ERROR(last_error, "clGetDeviceInfo") + if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0) + is_embedded_profile = true; + + // gentype erf(gentype x); + // gentype erfc(gentype x); + TEST_UNARY_FUNC_MACRO((other_func_erfc(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((other_func_erf(is_embedded_profile))) + + // gentype fabs(gentype x); + TEST_UNARY_FUNC_MACRO((other_func_fabs(is_embedded_profile))) + + // gentype tgamma(gentype x); + TEST_UNARY_FUNC_MACRO((other_func_tgamma(is_embedded_profile))) + + // gentype hypot(gentype x, gentype y); + TEST_BINARY_FUNC_MACRO((other_func_hypot(is_embedded_profile))) + + // gentype mad(gentype a, gentype b, gentype c); + TEST_TERNARY_FUNC_MACRO((other_func_mad(is_embedded_profile))) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_OTHER_FUNCS_HPP diff --git a/test_conformance/clcpp/math_funcs/power_funcs.hpp b/test_conformance/clcpp/math_funcs/power_funcs.hpp new file mode 100644 index 00000000..2ace9b35 --- /dev/null +++ b/test_conformance/clcpp/math_funcs/power_funcs.hpp @@ -0,0 +1,153 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_POWER_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_POWER_FUNCS_HPP + +#include +#include +#include + +#include "common.hpp" + +#define DEFINE_BINARY_POWER_FUNC_INT(NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, MIN1, MAX1, MIN2, MAX2) \ +struct power_func_ ## NAME : public binary_func \ +{ \ + power_func_ ## NAME(bool is_embedded) : m_is_embedded(is_embedded) \ + { \ + \ + } \ + \ + std::string str() \ + { \ + return #NAME; \ + } \ + \ + std::string headers() \ + { \ + return "#include \n"; \ + } \ + /* Reference value type is cl_double */ \ + cl_double operator()(const cl_float& x, const cl_int& y) \ + { \ + return (HOST_FUNC)(static_cast(x), y); \ + } \ + \ + cl_float min1() \ + { \ + return MIN1; \ + } \ + \ + cl_float max1() \ + { \ + return MAX1; \ + } \ + \ + cl_int min2() \ + { \ + return MIN2; \ + } \ + \ + cl_int max2() \ + { \ + return MAX2; \ + } \ + \ + std::vector in1_special_cases() \ + { \ + return { \ + cl_float(-1.0f), \ + cl_float(0.0f), \ + cl_float(-0.0f), \ + }; \ + } \ + \ + std::vector in2_special_cases() \ + { \ + return { \ + 2, 3, -1, 1, -2, 2 \ + }; \ + } \ + \ + bool use_ulp() \ + { \ + return USE_ULP; \ + } \ + \ + float ulp() \ + { \ + if(m_is_embedded) \ + { \ + return ULP_EMBEDDED; \ + } \ + return ULP; \ + } \ +private: \ + bool m_is_embedded; \ +}; + +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1 +MATH_FUNCS_DEFINE_UNARY_FUNC(power, cbrt, std::cbrt, true, 2.0f, 4.0f, 0.001f, -1000.0f, -9.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(power, rsqrt, reference::rsqrt, true, 2.0f, 4.0f, 0.001f, 1.0f, 100.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(power, sqrt, std::sqrt, true, 3.0f, 4.0f, 0.001f, 1.0f, 100.0f) + +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2 +MATH_FUNCS_DEFINE_BINARY_FUNC(power, pow, std::pow, true, 16.0f, 16.0f, 0.001f, 1.0f, 100.0f, 1.0f, 10.0f) +MATH_FUNCS_DEFINE_BINARY_FUNC(power, powr, reference::powr, true, 16.0f, 16.0f, 0.001f, 1.0f, 100.0f, 1.0f, 10.0f) + +// func_name, reference_func, use_ulp, ulp, ulp_for_embedded, min1, max1, min2, max2 +DEFINE_BINARY_POWER_FUNC_INT(pown, std::pow, true, 16.0f, 16.0f, 1.0f, 100.0f, 1, 10) +DEFINE_BINARY_POWER_FUNC_INT(rootn, reference::rootn, true, 16.0f, 16.0f, -100.0f, 100.0f, -10, 10) + +// power functions +AUTO_TEST_CASE(test_power_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // Check for EMBEDDED_PROFILE + bool is_embedded_profile = false; + char profile[128]; + last_error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL); + RETURN_ON_CL_ERROR(last_error, "clGetDeviceInfo") + if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0) + is_embedded_profile = true; + + // gentype cbrt(gentype x); + // gentype rsqrt(gentype x); + // gentype sqrt(gentype x); + TEST_UNARY_FUNC_MACRO((power_func_cbrt(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((power_func_sqrt(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((power_func_rsqrt(is_embedded_profile))) + + // gentype pow(gentype x, gentype y); + // gentype powr(gentype x, gentype y); + TEST_BINARY_FUNC_MACRO((power_func_pow(is_embedded_profile))) + TEST_BINARY_FUNC_MACRO((power_func_powr(is_embedded_profile))) + + // gentype pown(gentype x, intn y); + // gentype rootn(gentype x, intn y); + TEST_BINARY_FUNC_MACRO((power_func_pown(is_embedded_profile))) + TEST_BINARY_FUNC_MACRO((power_func_rootn(is_embedded_profile))) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_POWER_FUNCS_HPP diff --git a/test_conformance/clcpp/math_funcs/reference.hpp b/test_conformance/clcpp/math_funcs/reference.hpp new file mode 100644 index 00000000..0f5fc2fc --- /dev/null +++ b/test_conformance/clcpp/math_funcs/reference.hpp @@ -0,0 +1,315 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_REFERENCE_HPP +#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_REFERENCE_HPP + +#include +#include +#include + +#include "../common.hpp" + +namespace reference +{ + // Reference functions for OpenCL comparison functions that + // are not already defined in STL. + cl_float maxmag(const cl_float& x, const cl_float& y) + { + if((std::abs)(x) > (std::abs)(y)) + { + return x; + } + else if((std::abs)(y) > (std::abs)(x)) + { + return y; + } + return (std::fmax)(x, y); + } + + cl_float minmag(const cl_float& x, const cl_float& y) + { + if((std::abs)(x) < (std::abs)(y)) + { + return x; + } + else if((std::abs)(y) < (std::abs)(x)) + { + return y; + } + return (std::fmin)(x, y); + } + + // Reference functions for OpenCL exp functions that + // are not already defined in STL. + cl_double exp10(const cl_double& x) + { + // 10^x = exp2( x * log2(10) ) + auto log2_10 = (std::log2)(static_cast(10.0)); + cl_double x_log2_10 = static_cast(x * log2_10); + return (std::exp2)(x_log2_10); + } + + // Reference functions for OpenCL floating point functions that + // are not already defined in STL. + cl_double2 fract(cl_double x) + { + // Copied from math_brute_force/reference_math.c + cl_double2 r; + if((std::isnan)(x)) + { + r.s[0] = std::numeric_limits::quiet_NaN(); + r.s[1] = std::numeric_limits::quiet_NaN(); + return r; + } + + r.s[0] = (std::modf)(x, &(r.s[1])); + if(r.s[0] < 0.0 ) + { + r.s[0] = 1.0f + r.s[0]; + r.s[1] -= 1.0f; + if( r.s[0] == 1.0f ) + r.s[0] = HEX_FLT(+, 1, fffffe, -, 1); + } + return r; + } + + cl_double2 remquo(cl_double x, cl_double y) + { + cl_double2 r; + // remquo return the same value that is returned by the + // remainder function + r.s[0] = (std::remainder)(x,y); + // calulcate quo + cl_double x_y = (x - r.s[0]) / y; + cl_uint quo = (std::abs)(x_y); + r.s[1] = quo & 0x0000007fU; + if(x_y < 0.0) + r.s[1] = -r.s[1]; + + // fix edge cases + if(!(std::isnan)(x) && y == 0.0) + { + r.s[1] = 0; + } + else if((std::isnan)(x) && (std::isnan)(y)) + { + r.s[1] = 0; + } + return r; + } + + // Reference functions for OpenCL half_math:: functions that + // are not already defined in STL. + cl_double divide(cl_double x, cl_double y) + { + return x / y; + } + + cl_double recip(cl_double x) + { + return 1.0 / x; + } + + // Reference functions for OpenCL other functions that + // are not already defined in STL. + cl_double mad(cl_double x, cl_double y, cl_double z) + { + return (x * y) + z; + } + + // Reference functions for OpenCL power functions that + // are not already defined in STL. + cl_double rsqrt(const cl_double& x) + { + return cl_double(1.0) / ((std::sqrt)(x)); + } + + cl_double powr(const cl_double& x, const cl_double& y) + { + //powr(x, y) returns NaN for x < 0. + if( x < 0.0 ) + return std::numeric_limits::quiet_NaN(); + + //powr ( x, NaN ) returns the NaN for x >= 0. + //powr ( NaN, y ) returns the NaN. + if((std::isnan)(x) || (std::isnan)(y) ) + return std::numeric_limits::quiet_NaN(); + + if( x == 1.0 ) + { + //powr ( +1, +-inf ) returns NaN. + if((std::abs)(y) == INFINITY ) + return std::numeric_limits::quiet_NaN(); + + //powr ( +1, y ) is 1 for finite y. (NaN handled above) + return 1.0; + } + + if( y == 0.0 ) + { + //powr ( +inf, +-0 ) returns NaN. + //powr ( +-0, +-0 ) returns NaN. + if( x == 0.0 || x == std::numeric_limits::infinity()) + return std::numeric_limits::quiet_NaN(); + + //powr ( x, +-0 ) is 1 for finite x > 0. (x <= 0, NaN, INF already handled above) + return 1.0; + } + + if( x == 0.0 ) + { + //powr ( +-0, -inf) is +inf. + //powr ( +-0, y ) is +inf for finite y < 0. + if( y < 0.0 ) + return std::numeric_limits::infinity(); + + //powr ( +-0, y ) is +0 for y > 0. (NaN, y==0 handled above) + return 0.0; + } + + // x = +inf + if( (std::isinf)(x) ) + { + if( y < 0 ) + return 0; + return std::numeric_limits::infinity(); + } + + double fabsx = (std::abs)(x); + double fabsy = (std::abs)(y); + + //y = +-inf cases + if( (std::isinf)(fabsy) ) + { + if( y < 0.0 ) + { + if( fabsx < 1.0 ) + return std::numeric_limits::infinity(); + return 0; + } + if( fabsx < 1.0 ) + return 0.0; + return std::numeric_limits::infinity(); + } + return (std::pow)(x, y); + } + + cl_double rootn(const cl_double& x, const cl_int n) + { + //rootn (x, 0) returns a NaN. + if(n == 0) + return std::numeric_limits::quiet_NaN(); + + //rootn ( x, n ) returns a NaN for x < 0 and n is even. + if(x < 0 && 0 == (n & 1)) + return std::numeric_limits::quiet_NaN(); + + if(x == 0.0) + { + if(n > 0) + { + //rootn ( +-0, n ) is +0 for even n > 0. + if(0 == (n & 1)) + { + return cl_double(0.0); + } + //rootn ( +-0, n ) is +-0 for odd n > 0. + else + { + return x; + } + } + else + { + //rootn ( +-0, n ) is +inf for even n < 0. + if(0 == ((-n) & 1)) + { + return std::numeric_limits::infinity(); + } + //rootn ( +-0, n ) is +-inf for odd n < 0. + else + { + return (std::copysign)( + std::numeric_limits::infinity(), x + ); + } + } + } + + cl_double r = (std::abs)(x); + r = (std::exp2)((std::log2)(r) / static_cast(n)); + return (std::copysign)(r, x); + } + + // Reference functions for OpenCL trigonometric functions that + // are not already defined in STL. + cl_double acospi(cl_double x) + { + return (std::acos)(x) / CL_M_PI; + } + + cl_double asinpi(cl_double x) + { + return (std::asin)(x) / CL_M_PI; + } + + cl_double atanpi(cl_double x) + { + return (std::atan)(x) / CL_M_PI; + } + + cl_double cospi(cl_double x) + { + return (std::cos)(x * CL_M_PI); + } + + cl_double sinpi(cl_double x) + { + return (std::sin)(x * CL_M_PI); + } + + cl_double tanpi(cl_double x) + { + return (std::tan)(x * CL_M_PI); + } + + cl_double atan2(cl_double x, cl_double y) + { + #if defined(WIN32) || defined(_WIN32) + // Fix edge cases for Windows + if ((std::isinf)(x) && (std::isinf)(y)) { + cl_double retval = (y > 0) ? CL_M_PI_4 : 3.f * CL_M_PI_4; + return (x > 0) ? retval : -retval; + } + #endif // defined(WIN32) || defined(_WIN32) + return (std::atan2)(x, y); + } + + cl_double atan2pi(cl_double x, cl_double y) + { + return ::reference::atan2(x, y) / CL_M_PI; + } + + cl_double2 sincos(cl_double x) + { + cl_double2 r; + r.s[0] = (std::sin)(x); + r.s[1] = (std::cos)(x); + return r; + } +} + +#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_REFERENCE_HPP diff --git a/test_conformance/clcpp/math_funcs/trigonometric_funcs.hpp b/test_conformance/clcpp/math_funcs/trigonometric_funcs.hpp new file mode 100644 index 00000000..343024a8 --- /dev/null +++ b/test_conformance/clcpp/math_funcs/trigonometric_funcs.hpp @@ -0,0 +1,222 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_TRI_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_TRI_FUNCS_HPP + +#include +#include + +#include "common.hpp" + +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1 +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, acos, std::acos, true, 4.0f, 4.0f, 0.001f, -1.0f, 1.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, acosh, std::acosh, true, 4.0f, 4.0f, 0.001f, -1.0f, 1.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, acospi, reference::acospi, true, 5.0f, 5.0f, 0.001f, -1.0f, 1.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, asin, std::asin, true, 4.0f, 4.0f, 0.001f, -1.0f, 1.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, asinh, std::asinh, true, 4.0f, 4.0f, 0.001f, -1.0f, 1.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, asinpi, reference::asinpi, true, 5.0f, 5.0f, 0.001f, -1.0f, 1.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, atan, std::atan, true, 5.0f, 5.0f, 0.001f, -1.0f, 1.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, atanh, std::atanh, true, 5.0f, 5.0f, 0.001f, -1.0f, 1.0f) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, atanpi, reference::atanpi, true, 5.0f, 5.0f, 0.001f, -1.0f, 1.0f) + +// For (sin/cos/tan)pi functions min input value is -0.24 and max input value is 0.24, +// so (CL_M_PI * x) is never greater than CL_M_PI_F. +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1 +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, cos, std::cos, true, 4.0f, 4.0f, 0.001f, -CL_M_PI_F, CL_M_PI_F) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, cosh, std::cosh, true, 4.0f, 4.0f, 0.001f, -CL_M_PI_F, CL_M_PI_F) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, cospi, reference::cospi, true, 4.0f, 4.0f, 0.001f, -0.24, -0.24f) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, sin, std::sin, true, 4.0f, 4.0f, 0.001f, -CL_M_PI_F, CL_M_PI_F) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, sinh, std::sinh, true, 4.0f, 4.0f, 0.001f, -CL_M_PI_F, CL_M_PI_F) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, sinpi, reference::sinpi, true, 4.0f, 4.0f, 0.001f, -0.24, -0.24f) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, tan, std::tan, true, 5.0f, 5.0f, 0.001f, -CL_M_PI_F, CL_M_PI_F) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, tanh, std::tanh, true, 5.0f, 5.0f, 0.001f, -CL_M_PI_F, CL_M_PI_F) +MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, tanpi, reference::tanpi, true, 6.0f, 6.0f, 0.001f, -0.24, -0.24f) + +// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2 +MATH_FUNCS_DEFINE_BINARY_FUNC(trigonometric, atan2, reference::atan2, true, 6.0f, 6.0f, 0.001f, -1.0f, 1.0f, -1.0f, 1.0f) +MATH_FUNCS_DEFINE_BINARY_FUNC(trigonometric, atan2pi, reference::atan2pi, true, 6.0f, 6.0f, 0.001f, -1.0f, 1.0f, -1.0f, 1.0f) + +// gentype sincos(gentype x, gentype * cosval); +// +// Fact that second argument is a pointer is inconvenient. +// +// We don't want to modify all helper functions defined in funcs_test_utils.hpp +// that run test kernels generated based on this class and check if results are +// correct, so instead of having two output cl_float buffers, one for sines and +// one for cosines values, we use one cl_float2 output buffer (first component is +// sine, second is cosine). +// +// Below we also define specialization of generate_kernel_unary function template +// for trigonometric_func_sincos. +struct trigonometric_func_sincos : public unary_func +{ + trigonometric_func_sincos(bool is_embedded) : m_is_embedded(is_embedded) + { + + } + + std::string str() + { + return "sincos"; + } + + std::string headers() + { + return "#include \n"; + } + + /* Reference value type is cl_double */ + cl_double2 operator()(const cl_float& x) + { + return (reference::sincos)(static_cast(x)); + } + + cl_float min1() + { + return -CL_M_PI_F; + } + + cl_float max1() + { + return CL_M_PI_F; + } + + bool use_ulp() + { + return true; + } + + float ulp() + { + if(m_is_embedded) + { + return 4.0f; + } + return 4.0f; + } +private: + bool m_is_embedded; +}; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template <> +std::string generate_kernel_unary(trigonometric_func_sincos func) +{ + return + "__kernel void test_sincos(global float *input, global float2 *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " float2 sine_cosine_of_x;\n" + " float cosine_of_x = 0;\n" + " sine_cosine_of_x.x = sincos(input[gid], &(cosine_of_x));\n" + " sine_cosine_of_x.y = cosine_of_x;\n" + " output[gid] = sine_cosine_of_x;\n" + "}\n"; +} +#else +template <> +std::string generate_kernel_unary(trigonometric_func_sincos func) +{ + return + "" + func.defs() + + "" + func.headers() + + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_sincos(global_ptr input, global_ptr output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " float2 sine_cosine_of_x;\n" + " float cosine_of_x = 0;\n" + " sine_cosine_of_x.x = sincos(input[gid], &(cosine_of_x));\n" + " sine_cosine_of_x.y = cosine_of_x;\n" + " output[gid] = sine_cosine_of_x;\n" + "}\n"; +} +#endif + +// trigonometric functions +AUTO_TEST_CASE(test_trigonometric_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + // Check for EMBEDDED_PROFILE + bool is_embedded_profile = false; + char profile[128]; + last_error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL); + RETURN_ON_CL_ERROR(last_error, "clGetDeviceInfo") + if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0) + is_embedded_profile = true; + + // gentype acos(gentype x); + // gentype acosh(gentype x); + // gentype acospi(gentype x); + // gentype asin(gentype x); + // gentype asinh(gentype x); + // gentype asinpi(gentype x); + // gentype atan(gentype x); + // gentype atanh(gentype x); + // gentype atanpi(gentype x); + TEST_UNARY_FUNC_MACRO((trigonometric_func_acos(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_acosh(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_acospi(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_asin(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_asinh(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_asinpi(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_atan(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_atanh(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_atanpi(is_embedded_profile))) + + // gentype cos(gentype x); + // gentype cosh(gentype x); + // gentype cospi(gentype x); + // gentype sin(gentype x); + // gentype sinh(gentype x); + // gentype sinpi(gentype x); + // gentype tan(gentype x); + // gentype tanh(gentype x); + // gentype tanpi(gentype x); + TEST_UNARY_FUNC_MACRO((trigonometric_func_cos(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_cosh(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_cospi(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_sin(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_sinh(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_sinpi(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_tan(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_tanh(is_embedded_profile))) + TEST_UNARY_FUNC_MACRO((trigonometric_func_tanpi(is_embedded_profile))) + + // gentype atan2(gentype y, gentype x); + // gentype atan2pi(gentype y, gentype x); + TEST_BINARY_FUNC_MACRO((trigonometric_func_atan2(is_embedded_profile))) + TEST_BINARY_FUNC_MACRO((trigonometric_func_atan2pi(is_embedded_profile))) + + // gentype sincos(gentype x, gentype * cosval); + TEST_UNARY_FUNC_MACRO((trigonometric_func_sincos(is_embedded_profile))) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_TRI_FUNCS_HPP diff --git a/test_conformance/clcpp/pipes/CMakeLists.txt b/test_conformance/clcpp/pipes/CMakeLists.txt new file mode 100644 index 00000000..037b432d --- /dev/null +++ b/test_conformance/clcpp/pipes/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_PIPES) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/pipes/main.cpp b/test_conformance/clcpp/pipes/main.cpp new file mode 100644 index 00000000..91a0ea83 --- /dev/null +++ b/test_conformance/clcpp/pipes/main.cpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "test_pipes.hpp" + + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/pipes/test_pipes.hpp b/test_conformance/clcpp/pipes/test_pipes.hpp new file mode 100644 index 00000000..3fc30dcd --- /dev/null +++ b/test_conformance/clcpp/pipes/test_pipes.hpp @@ -0,0 +1,632 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_PIPES_TEST_PIPES_HPP +#define TEST_CONFORMANCE_CLCPP_PIPES_TEST_PIPES_HPP + +#include +#include +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" + + +namespace test_pipes { + +enum class pipe_source +{ + param, + storage +}; + +enum class pipe_operation +{ + work_item, + work_item_reservation, + work_group_reservation, + sub_group_reservation +}; + +struct test_options +{ + pipe_operation operation; + pipe_source source; + int max_packets; + int num_packets; +}; + +struct output_type +{ + cl_uint write_reservation_is_valid; + cl_uint write_success; + + cl_uint num_packets; + cl_uint max_packets; + cl_uint read_reservation_is_valid; + cl_uint read_success; + + cl_uint value; +}; + +const std::string source_common = R"( +struct output_type +{ + uint write_reservation_is_valid; + uint write_success; + + uint num_packets; + uint max_packets; + uint read_reservation_is_valid; + uint read_success; + + uint value; +}; +)"; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +std::string generate_source(test_options options) +{ + std::stringstream s; + s << source_common; + if (options.operation == pipe_operation::work_item) + { + s << R"( + kernel void producer(write_only pipe uint out_pipe, global struct output_type *output) + { + const ulong gid = get_global_id(0); + + output[gid].write_reservation_is_valid = 1; + + uint value = gid; + output[gid].write_success = write_pipe(out_pipe, &value) == 0; + } + + kernel void consumer(read_only pipe uint in_pipe, global struct output_type *output) + { + const ulong gid = get_global_id(0); + + output[gid].num_packets = get_pipe_num_packets(in_pipe); + output[gid].max_packets = get_pipe_max_packets(in_pipe); + + output[gid].read_reservation_is_valid = 1; + + uint value; + output[gid].read_success = read_pipe(in_pipe, &value) == 0; + output[gid].value = value; + } + )"; + } + else if (options.operation == pipe_operation::work_item_reservation) + { + s << R"( + kernel void producer(write_only pipe uint out_pipe, global struct output_type *output) + { + const ulong gid = get_global_id(0); + if (gid % 2 == 1) return; + + reserve_id_t reservation = reserve_write_pipe(out_pipe, 2); + output[gid + 0].write_reservation_is_valid = is_valid_reserve_id(reservation); + output[gid + 1].write_reservation_is_valid = is_valid_reserve_id(reservation); + + uint value0 = gid + 0; + uint value1 = gid + 1; + output[gid + 0].write_success = write_pipe(out_pipe, reservation, 0, &value0) == 0; + output[gid + 1].write_success = write_pipe(out_pipe, reservation, 1, &value1) == 0; + commit_write_pipe(out_pipe, reservation); + } + + kernel void consumer(read_only pipe uint in_pipe, global struct output_type *output) + { + const ulong gid = get_global_id(0); + if (gid % 2 == 1) return; + + output[gid + 0].num_packets = get_pipe_num_packets(in_pipe); + output[gid + 0].max_packets = get_pipe_max_packets(in_pipe); + output[gid + 1].num_packets = get_pipe_num_packets(in_pipe); + output[gid + 1].max_packets = get_pipe_max_packets(in_pipe); + + reserve_id_t reservation = reserve_read_pipe(in_pipe, 2); + output[gid + 0].read_reservation_is_valid = is_valid_reserve_id(reservation); + output[gid + 1].read_reservation_is_valid = is_valid_reserve_id(reservation); + + uint value0; + uint value1; + output[gid + 0].read_success = read_pipe(in_pipe, reservation, 1, &value0) == 0; + output[gid + 1].read_success = read_pipe(in_pipe, reservation, 0, &value1) == 0; + commit_read_pipe(in_pipe, reservation); + output[gid + 0].value = value0; + output[gid + 1].value = value1; + } + )"; + } + else if (options.operation == pipe_operation::work_group_reservation) + { + s << R"( + kernel void producer(write_only pipe uint out_pipe, global struct output_type *output) + { + const ulong gid = get_global_id(0); + + reserve_id_t reservation = work_group_reserve_write_pipe(out_pipe, get_local_size(0)); + output[gid].write_reservation_is_valid = is_valid_reserve_id(reservation); + + uint value = gid; + output[gid].write_success = write_pipe(out_pipe, reservation, get_local_id(0), &value) == 0; + work_group_commit_write_pipe(out_pipe, reservation); + } + + kernel void consumer(read_only pipe uint in_pipe, global struct output_type *output) + { + const ulong gid = get_global_id(0); + + output[gid].num_packets = get_pipe_num_packets(in_pipe); + output[gid].max_packets = get_pipe_max_packets(in_pipe); + + reserve_id_t reservation = work_group_reserve_read_pipe(in_pipe, get_local_size(0)); + output[gid].read_reservation_is_valid = is_valid_reserve_id(reservation); + + uint value; + output[gid].read_success = read_pipe(in_pipe, reservation, get_local_size(0) - 1 - get_local_id(0), &value) == 0; + work_group_commit_read_pipe(in_pipe, reservation); + output[gid].value = value; + } + )"; + } + else if (options.operation == pipe_operation::sub_group_reservation) + { + s << R"( + #pragma OPENCL EXTENSION cl_khr_subgroups : enable + + kernel void producer(write_only pipe uint out_pipe, global struct output_type *output) + { + const ulong gid = get_global_id(0); + + reserve_id_t reservation = sub_group_reserve_write_pipe(out_pipe, get_sub_group_size()); + output[gid].write_reservation_is_valid = is_valid_reserve_id(reservation); + + uint value = gid; + output[gid].write_success = write_pipe(out_pipe, reservation, get_sub_group_local_id(), &value) == 0; + sub_group_commit_write_pipe(out_pipe, reservation); + } + + kernel void consumer(read_only pipe uint in_pipe, global struct output_type *output) + { + const ulong gid = get_global_id(0); + + output[gid].num_packets = get_pipe_num_packets(in_pipe); + output[gid].max_packets = get_pipe_max_packets(in_pipe); + + reserve_id_t reservation = sub_group_reserve_read_pipe(in_pipe, get_sub_group_size()); + output[gid].read_reservation_is_valid = is_valid_reserve_id(reservation); + + uint value; + output[gid].read_success = read_pipe(in_pipe, reservation, get_sub_group_size() - 1 - get_sub_group_local_id(), &value) == 0; + sub_group_commit_read_pipe(in_pipe, reservation); + output[gid].value = value; + } + )"; + } + + return s.str(); +} +#else +std::string generate_source(test_options options) +{ + std::stringstream s; + s << R"( + #include + #include + #include + #include + #include + using namespace cl; + )"; + + s << source_common; + + std::string init_out_pipe; + std::string init_in_pipe; + if (options.source == pipe_source::param) + { + init_out_pipe = "auto out_pipe = pipe_param;"; + init_in_pipe = "auto in_pipe = pipe_param;"; + } + else if (options.source == pipe_source::storage) + { + s << "pipe_storage storage;"; + init_out_pipe = "auto out_pipe = storage.get();"; + init_in_pipe = "auto in_pipe = make_pipe(storage);"; + } + + if (options.operation == pipe_operation::work_item) + { + s << R"( + kernel void producer(pipe pipe_param, global_ptr output) + { + )" << init_out_pipe << R"( + const ulong gid = get_global_id(0); + + output[gid].write_reservation_is_valid = 1; + + uint value = gid; + output[gid].write_success = out_pipe.write(value); + } + + kernel void consumer(pipe pipe_param, global_ptr output) + { + )" << init_in_pipe << R"( + const ulong gid = get_global_id(0); + + output[gid].num_packets = in_pipe.num_packets(); + output[gid].max_packets = in_pipe.max_packets(); + + output[gid].read_reservation_is_valid = 1; + + uint value; + output[gid].read_success = in_pipe.read(value); + output[gid].value = value; + } + )"; + } + else if (options.operation == pipe_operation::work_item_reservation) + { + s << R"( + kernel void producer(pipe pipe_param, global_ptr output) + { + )" << init_out_pipe << R"( + const ulong gid = get_global_id(0); + if (gid % 2 == 1) return; + + auto reservation = out_pipe.reserve(2); + output[gid + 0].write_reservation_is_valid = reservation.is_valid(); + output[gid + 1].write_reservation_is_valid = reservation.is_valid(); + + uint value0 = gid + 0; + uint value1 = gid + 1; + output[gid + 0].write_success = reservation.write(0, value0); + output[gid + 1].write_success = reservation.write(1, value1); + reservation.commit(); + } + + kernel void consumer(pipe pipe_param, global_ptr output) + { + )" << init_in_pipe << R"( + const ulong gid = get_global_id(0); + if (gid % 2 == 1) return; + + output[gid + 0].num_packets = in_pipe.num_packets(); + output[gid + 0].max_packets = in_pipe.max_packets(); + output[gid + 1].num_packets = in_pipe.num_packets(); + output[gid + 1].max_packets = in_pipe.max_packets(); + + auto reservation = in_pipe.reserve(2); + output[gid + 0].read_reservation_is_valid = reservation.is_valid(); + output[gid + 1].read_reservation_is_valid = reservation.is_valid(); + + uint value0; + uint value1; + output[gid + 0].read_success = reservation.read(1, value0); + output[gid + 1].read_success = reservation.read(0, value1); + reservation.commit(); + output[gid + 0].value = value0; + output[gid + 1].value = value1; + } + )"; + } + else if (options.operation == pipe_operation::work_group_reservation) + { + s << R"( + kernel void producer(pipe pipe_param, global_ptr output) + { + )" << init_out_pipe << R"( + const ulong gid = get_global_id(0); + + auto reservation = out_pipe.work_group_reserve(get_local_size(0)); + output[gid].write_reservation_is_valid = reservation.is_valid(); + + uint value = gid; + output[gid].write_success = reservation.write(get_local_id(0), value); + reservation.commit(); + } + + kernel void consumer(pipe pipe_param, global_ptr output) + { + )" << init_in_pipe << R"( + const ulong gid = get_global_id(0); + + output[gid].num_packets = in_pipe.num_packets(); + output[gid].max_packets = in_pipe.max_packets(); + + auto reservation = in_pipe.work_group_reserve(get_local_size(0)); + output[gid].read_reservation_is_valid = reservation.is_valid(); + + uint value; + output[gid].read_success = reservation.read(get_local_size(0) - 1 - get_local_id(0), value); + reservation.commit(); + output[gid].value = value; + } + )"; + } + else if (options.operation == pipe_operation::sub_group_reservation) + { + s << R"( + kernel void producer(pipe pipe_param, global_ptr output) + { + )" << init_out_pipe << R"( + const ulong gid = get_global_id(0); + + auto reservation = out_pipe.sub_group_reserve(get_sub_group_size()); + output[gid].write_reservation_is_valid = reservation.is_valid(); + + uint value = gid; + output[gid].write_success = reservation.write(get_sub_group_local_id(), value); + reservation.commit(); + } + + kernel void consumer(pipe pipe_param, global_ptr output) + { + )" << init_in_pipe << R"( + const ulong gid = get_global_id(0); + + output[gid].num_packets = in_pipe.num_packets(); + output[gid].max_packets = in_pipe.max_packets(); + + auto reservation = in_pipe.sub_group_reserve(get_sub_group_size()); + output[gid].read_reservation_is_valid = reservation.is_valid(); + + uint value; + output[gid].read_success = reservation.read(get_sub_group_size() - 1 - get_sub_group_local_id(), value); + reservation.commit(); + output[gid].value = value; + } + )"; + } + + return s.str(); +} +#endif + +int test(cl_device_id device, cl_context context, cl_command_queue queue, test_options options) +{ + int error = CL_SUCCESS; + + if (options.num_packets % 2 != 0 || options.max_packets < options.num_packets) + { + RETURN_ON_ERROR_MSG(-1, "Invalid test options") + } + +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + if (options.operation == pipe_operation::sub_group_reservation && !is_extension_available(device, "cl_khr_subgroups")) + { + log_info("SKIPPED: Extension `cl_khr_subgroups` is not supported. Skipping tests.\n"); + return CL_SUCCESS; + } +#endif + + cl_program program; + cl_kernel producer_kernel; + cl_kernel consumer_kernel; + + std::string producer_kernel_name = "producer"; + std::string consumer_kernel_name = "consumer"; + std::string source = generate_source(options); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &producer_kernel, + source, producer_kernel_name + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &producer_kernel, + source, producer_kernel_name, "-cl-std=CL2.0", false + ); + RETURN_ON_ERROR(error) + consumer_kernel = clCreateKernel(program, consumer_kernel_name.c_str(), &error); + RETURN_ON_CL_ERROR(error, "clCreateKernel") +// Normal run +#else + error = create_opencl_kernel( + context, &program, &producer_kernel, + source, producer_kernel_name + ); + RETURN_ON_ERROR(error) + consumer_kernel = clCreateKernel(program, consumer_kernel_name.c_str(), &error); + RETURN_ON_CL_ERROR(error, "clCreateKernel") +#endif + + size_t max_work_group_size; + error = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t), &max_work_group_size, NULL); + RETURN_ON_CL_ERROR(error, "clGetDeviceInfo") + + const size_t count = options.num_packets; + const size_t local_size = (std::min)((size_t)256, max_work_group_size); + const size_t global_size = count; + + const cl_uint packet_size = sizeof(cl_uint); + + cl_mem pipe = clCreatePipe(context, 0, packet_size, options.max_packets, NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreatePipe") + + cl_mem output_buffer; + output_buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(output_type) * count, NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + const char pattern = 0; + error = clEnqueueFillBuffer(queue, output_buffer, &pattern, sizeof(pattern), 0, sizeof(output_type) * count, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueFillBuffer") + + error = clSetKernelArg(producer_kernel, 0, sizeof(cl_mem), &pipe); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(producer_kernel, 1, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + error = clEnqueueNDRangeKernel(queue, producer_kernel, 1, NULL, &global_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + error = clSetKernelArg(consumer_kernel, 0, sizeof(cl_mem), &pipe); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(consumer_kernel, 1, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + error = clEnqueueNDRangeKernel(queue, consumer_kernel, 1, NULL, &global_size, &local_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + std::vector output(count); + error = clEnqueueReadBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(output_type) * count, + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + std::vector existing_values(count, false); + for (size_t gid = 0; gid < count; gid++) + { + const output_type &o = output[gid]; + + if (!o.write_reservation_is_valid) + { + RETURN_ON_ERROR_MSG(-1, "write reservation is not valid") + } + if (!o.write_success) + { + RETURN_ON_ERROR_MSG(-1, "write did not succeed") + } + + if (o.num_packets == 0 || o.num_packets > options.num_packets) + { + RETURN_ON_ERROR_MSG(-1, "num_packets did not return correct value") + } + if (o.max_packets != options.max_packets) + { + RETURN_ON_ERROR_MSG(-1, "max_packets did not return correct value") + } + if (!o.read_reservation_is_valid) + { + RETURN_ON_ERROR_MSG(-1, "read reservation is not valid") + } + if (!o.read_success) + { + RETURN_ON_ERROR_MSG(-1, "read did not succeed") + } + + // Every value must be presented once in any order + if (o.value >= count || existing_values[o.value]) + { + RETURN_ON_ERROR_MSG(-1, "kernel did not return correct value") + } + existing_values[o.value] = true; + } + + clReleaseMemObject(pipe); + clReleaseMemObject(output_buffer); + clReleaseKernel(producer_kernel); + clReleaseKernel(consumer_kernel); + clReleaseProgram(program); + return error; +} + +const pipe_operation pipe_operations[] = { + pipe_operation::work_item, + pipe_operation::work_item_reservation, + pipe_operation::work_group_reservation, + pipe_operation::sub_group_reservation +}; + +const std::tuple max_and_num_packets[] = { + std::make_tuple(2, 2), + std::make_tuple(10, 8), + std::make_tuple(256, 254), + std::make_tuple(1 << 16, 1 << 16), + std::make_tuple((1 << 16) + 5, 1 << 16), + std::make_tuple(12345, 12344), + std::make_tuple(1 << 18, 1 << 18) +}; + +AUTO_TEST_CASE(test_pipes_pipe) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + std::vector> ps; + for (auto p : max_and_num_packets) + { + if (std::get<0>(p) < num_elements) + ps.push_back(p); + } + ps.push_back(std::tuple(num_elements, num_elements)); + + int error = CL_SUCCESS; + + for (auto operation : pipe_operations) + for (auto p : ps) + { + test_options options; + options.source = pipe_source::param; + options.max_packets = std::get<0>(p); + options.num_packets = std::get<1>(p); + options.operation = operation; + + error = test(device, context, queue, options); + RETURN_ON_ERROR(error) + } + + return error; +} + +AUTO_TEST_CASE(test_pipes_pipe_storage) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + std::vector> ps; + for (auto p : max_and_num_packets) + { + if (std::get<0>(p) < num_elements) + ps.push_back(p); + } + ps.push_back(std::tuple(num_elements, num_elements)); + + int error = CL_SUCCESS; + + for (auto operation : pipe_operations) + for (auto p : ps) + { + test_options options; + options.source = pipe_source::storage; + options.max_packets = std::get<0>(p); + options.num_packets = std::get<1>(p); + options.operation = operation; + + error = test(device, context, queue, options); + RETURN_ON_ERROR(error) + } + + return error; +} + +} // namespace + +#endif // TEST_CONFORMANCE_CLCPP_PIPES_TEST_PIPES_HPP diff --git a/test_conformance/clcpp/program_scope_ctors_dtors/CMakeLists.txt b/test_conformance/clcpp/program_scope_ctors_dtors/CMakeLists.txt new file mode 100644 index 00000000..4318ca81 --- /dev/null +++ b/test_conformance/clcpp/program_scope_ctors_dtors/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_PROGRAM_SCOPE_CTORS_DTORS) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/program_scope_ctors_dtors/common.hpp b/test_conformance/clcpp/program_scope_ctors_dtors/common.hpp new file mode 100644 index 00000000..35bf81c9 --- /dev/null +++ b/test_conformance/clcpp/program_scope_ctors_dtors/common.hpp @@ -0,0 +1,284 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_PS_CTORS_DTORS_COMMON_HPP +#define TEST_CONFORMANCE_CLCPP_PS_CTORS_DTORS_COMMON_HPP + +#include + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#define RUN_PS_CTORS_DTORS_TEST_MACRO(TEST_CLASS) \ + last_error = run_ps_ctor_dtor_test( \ + device, context, queue, count, TEST_CLASS \ + ); \ + CHECK_ERROR(last_error) \ + error |= last_error; + +// Base class for all tests for kernels with program scope object with +// non-trivial ctors and/or dtors +struct ps_ctors_dtors_test_base : public detail::base_func_type +{ + // ctor is true, if and only if OpenCL program of this test contains program + // scope variable with non-trivial ctor. + // dtor is true, if and only if OpenCL program of this test contains program + // scope variable with non-trivial dtor. + ps_ctors_dtors_test_base(const bool ctor, + const bool dtor) + : m_ctor(ctor), m_dtor(dtor) + { + + } + virtual ~ps_ctors_dtors_test_base() { }; + // Returns test name + virtual std::string str() = 0; + // Returns OpenCL program source + virtual std::string generate_program() = 0; + // Returns kernel names IN ORDER + virtual std::vector get_kernel_names() + { + // Typical case, that is, only one kernel + return { this->get_kernel_name() }; + } + // Returns value that is expected to be in output_buffer[i] + virtual cl_uint operator()(size_t i) = 0; + // Executes kernels + // Typical case: execute every kernel once, every kernel has only + // one argument, that is, output buffer + virtual cl_int execute(const std::vector& kernels, + cl_mem& output_buffer, + cl_command_queue& queue, + size_t work_size) + { + cl_int err; + for(auto& k : kernels) + { + err = clSetKernelArg(k, 0, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel( + queue, k, 1, + NULL, &work_size, NULL, + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + } + return err; + } + // This method check if queries for CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT + // and CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT using clGetProgramInfo() + // return correct values + virtual cl_int ctors_dtors_present_queries(cl_program program) + { + cl_int error = CL_SUCCESS; + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return error; + #else + // CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT cl_bool + // This indicates that the program object contains non-trivial constructor(s) that will be + // executed by runtime before any kernel from the program is executed. + + // CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT cl_bool + // This indicates that the program object contains non-trivial destructor(s) that will be + // executed by runtime when program is destroyed. + + // CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT + cl_bool ctors_present; + size_t cl_bool_size; + error = clGetProgramInfo( + program, + CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT, + sizeof(cl_bool), + static_cast(&ctors_present), + &cl_bool_size + ); + RETURN_ON_CL_ERROR(error, "clGetProgramInfo") + if(cl_bool_size != sizeof(cl_bool)) + { + error = -1; + CHECK_ERROR_MSG( + error, + "Test failed, param_value_size_ret != sizeof(cl_bool) (%lu != %lu).\n", + cl_bool_size, + sizeof(cl_bool) + ); + } + + // CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT + cl_bool dtors_present = 0; + error = clGetProgramInfo( + program, + CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT, + sizeof(cl_bool), + static_cast(&ctors_present), + &cl_bool_size + ); + RETURN_ON_CL_ERROR(error, "clGetProgramInfo") + if(cl_bool_size != sizeof(cl_bool)) + { + error = -1; + CHECK_ERROR_MSG( + error, + "Test failed, param_value_size_ret != sizeof(cl_bool) (%lu != %lu).\n", + cl_bool_size, + sizeof(cl_bool) + ); + } + + // check constructors + if(m_ctor && ctors_present != CL_TRUE) + { + error = -1; + CHECK_ERROR_MSG( + error, + "Test failed, CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT: 0, should be: 1.\n" + ); + } + else if(!m_ctor && ctors_present == CL_TRUE) + { + error = -1; + CHECK_ERROR_MSG( + error, + "Test failed, CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT: 1, should be: 0.\n" + ); + } + + // check destructors + if(m_dtor && dtors_present != CL_TRUE) + { + error = -1; + CHECK_ERROR_MSG( + error, + "Test failed, CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT: 0, should be: 1.\n" + ); + } + else if(!m_dtor && dtors_present == CL_TRUE) + { + error = -1; + CHECK_ERROR_MSG( + error, + "Test failed, CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT: 1, should be: 0.\n" + ); + } + return error; + #endif + } + +private: + bool m_ctor; + bool m_dtor; +}; + +template +int run_ps_ctor_dtor_test(cl_device_id device, cl_context context, cl_command_queue queue, size_t count, ps_ctor_dtor_test op) +{ + cl_mem buffers[1]; + cl_program program; + std::vector kernels; + size_t work_size[1]; + cl_int err; + + std::string code_str = op.generate_program(); + std::vector kernel_names = op.get_kernel_names(); + if(kernel_names.empty()) + { + RETURN_ON_ERROR_MSG(-1, "No kernel to run"); + } + kernels.resize(kernel_names.size()); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &(kernels[0]), code_str, kernel_names[0]); + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &(kernels[0]), code_str, kernel_names[0], "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) + for(size_t i = 1; i < kernels.size(); i++) + { + kernels[i] = clCreateKernel(program, kernel_names[i].c_str(), &err); + RETURN_ON_CL_ERROR(err, "clCreateKernel"); + } +#else + err = create_opencl_kernel(context, &program, &(kernels[0]), code_str, kernel_names[0]); + RETURN_ON_ERROR(err) + for(size_t i = 1; i < kernels.size(); i++) + { + kernels[i] = clCreateKernel(program, kernel_names[i].c_str(), &err); + RETURN_ON_CL_ERROR(err, "clCreateKernel"); + } +#endif + + work_size[0] = count; + // host output vector + std::vector output = generate_output(work_size[0], 9999); + + // device output buffer + buffers[0] = clCreateBuffer( + context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &err + ); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + // Execute test + err = op.execute(kernels, buffers[0], queue, work_size[0]); + RETURN_ON_ERROR(err) + + // Check if queries returns correct values + err = op.ctors_dtors_present_queries(program); + RETURN_ON_ERROR(err); + + // Release kernels and program + // Destructors should be called now + for(auto& k : kernels) + { + err = clReleaseKernel(k); + RETURN_ON_CL_ERROR(err, "clReleaseKernel"); + } + err = clReleaseProgram(program); + RETURN_ON_CL_ERROR(err, "clReleaseProgram"); + + // Finish + err = clFinish(queue); + RETURN_ON_CL_ERROR(err, "clFinish"); + + err = clEnqueueReadBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + // Check output values + for(size_t i = 0; i < output.size(); i++) + { + cl_uint v = op(i); + if(!(are_equal(v, output[i], detail::make_value(0), op))) + { + RETURN_ON_ERROR_MSG(-1, + "test_%s(%s) failed. Expected: %s, got: %s", op.str().c_str(), type_name().c_str(), + format_value(v).c_str(), format_value(output[i]).c_str() + ); + } + } + log_info("test_%s(%s) passed\n", op.str().c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + return err; +} + +#endif // TEST_CONFORMANCE_CLCPP_PS_CTORS_DTORS_COMMON_HPP diff --git a/test_conformance/clcpp/program_scope_ctors_dtors/main.cpp b/test_conformance/clcpp/program_scope_ctors_dtors/main.cpp new file mode 100644 index 00000000..ef70cdd3 --- /dev/null +++ b/test_conformance/clcpp/program_scope_ctors_dtors/main.cpp @@ -0,0 +1,29 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "test_ctors_dtors.hpp" + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/program_scope_ctors_dtors/test_ctors_dtors.hpp b/test_conformance/clcpp/program_scope_ctors_dtors/test_ctors_dtors.hpp new file mode 100644 index 00000000..c9ac0821 --- /dev/null +++ b/test_conformance/clcpp/program_scope_ctors_dtors/test_ctors_dtors.hpp @@ -0,0 +1,324 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_PS_CTORS_DTORS_TEST_CTORS_DTORS_HPP +#define TEST_CONFORMANCE_CLCPP_PS_CTORS_DTORS_TEST_CTORS_DTORS_HPP + +#include "common.hpp" + +// Test for program scope variable with non-trivial ctor +struct ps_ctor_test : public ps_ctors_dtors_test_base +{ + ps_ctor_test(const cl_uint test_value) + : ps_ctors_dtors_test_base(true, false), + m_test_value(test_value) + { + + } + + std::string str() + { + return "ps_ctor_test"; + } + + std::vector get_kernel_names() + { + return { + this->str() + "_set", + this->str() + "_read" + }; + } + + // Returns value that is expected to be in output_buffer[i] + cl_uint operator()(size_t i) + { + if(i % 2 == 0) + return m_test_value; + return cl_uint(0xbeefbeef); + } + + // In 1st kernel 0th work-tem sets member m_x of program scope variable global_var to + // m_test_value and m_y to uint(0xbeefbeef), + // In 2nd kernel: + // 1) if global id is even, then work-item reads global_var.m_x and writes it to output[its-global-id]; + // 2) otherwise, work-item reads global_var.m_y and writes it to output[its-global-id]. + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return + "__kernel void " + this->get_kernel_names()[0] + "(global uint *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = 0xbeefbeef;\n" + "}\n" + "__kernel void " + this->get_kernel_names()[1] + "(global uint *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " if(gid % 2 == 0)\n" + " output[gid] = " + std::to_string(m_test_value) + ";\n" + "}\n"; + #else + return + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + // struct template + "template\n" + "struct ctor_test_class_base {\n" + // non-trivial ctor + " ctor_test_class_base(T x) { m_x = x;};\n" + " T m_x;\n" + "};\n" + // struct template + "template\n" + "struct ctor_test_class : public ctor_test_class_base {\n" + // non-trivial ctor + " ctor_test_class(T x, T y) : ctor_test_class_base(x), m_y(y) { };\n" + " T m_y;\n" + "};\n" + // global scope program variables + "ctor_test_class global_var(uint(0), uint(0));\n" + + "__kernel void " + this->get_kernel_names()[0] + "(global_ptr output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " if(gid == 0) {\n" + " global_var.m_x = " + std::to_string(m_test_value) + ";\n" + " global_var.m_y = 0xbeefbeef;\n" + " }\n" + "}\n" + + "__kernel void " + this->get_kernel_names()[1] + "(global_ptr output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " if(gid % 2 == 0)\n" + " output[gid] = global_var.m_x;\n" + " else\n" + " output[gid] = global_var.m_y;\n" + "}\n"; + #endif + } + +private: + cl_uint m_test_value; +}; + +// Test for program scope variable with non-trivial dtor +struct ps_dtor_test : public ps_ctors_dtors_test_base +{ + ps_dtor_test(const cl_uint test_value) + : ps_ctors_dtors_test_base(false, true), + m_test_value(test_value) + { + + } + + std::string str() + { + return "ps_dtor_test"; + } + + // Returns value that is expected to be in output_buffer[i] + cl_uint operator()(size_t i) + { + if(i % 2 == 0) + return m_test_value; + return 1; + } + + // In 1st kernel 0th work-item saves pointer to output buffer and its size in program scope + // variable global_var, it also sets counter to 1; + // After global_var is destroyed all even elements of output buffer should equal m_test_value, + // and all odd should equal 1. + // If odd elements of output buffer are >1 it means dtor was executed more than once. + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return + "__kernel void " + this->get_kernel_name() + "(global uint *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " if(gid % 2 == 0)\n" + " output[gid] = " + std::to_string(m_test_value) + ";\n" + " else\n" + " output[gid] = 1;\n" + "}\n"; + #else + return + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + // struct template + "template\n" + "struct dtor_test_class_base {\n" + // non-trivial dtor + // set all odd elements in buffer to counter + " ~dtor_test_class_base() {\n" + " for(size_t i = 1; i < this->size; i+=2)\n" + " {\n" + " this->buffer[i] = counter;\n" + " }\n" + " counter++;\n" + " };\n" + " global_ptr buffer;\n" + " size_t size;\n" + " T counter;\n" + "};\n" + // struct + "struct dtor_test_class : public dtor_test_class_base {\n" + // non-trivial dtor + // set all values in buffer to m_test_value + " ~dtor_test_class() {\n" + " for(size_t i = 0; i < this->size; i+=2)\n" + " this->buffer[i] = " + std::to_string(m_test_value) + ";\n" + " };\n" + "};\n" + // global scope program variable + "dtor_test_class global_var;\n" + + // When global_var is being destroyed, first dtor ~dtor_test_class is called, + // and then ~dtor_test_class_base is called. + + "__kernel void " + this->get_kernel_name() + "(global_ptr output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + // set buffer and size in global var + " if(gid == 0){\n" + " global_var.buffer = output;\n" + " global_var.size = get_global_size(0);\n" + " global_var.counter = 1;\n" + " }\n" + "}\n"; + #endif + } + +private: + cl_uint m_test_value; +}; + +// Test for program scope variable with both non-trivial ctor +// and non-trivial dtor +struct ps_ctor_dtor_test : public ps_ctors_dtors_test_base +{ + ps_ctor_dtor_test(const cl_uint test_value) + : ps_ctors_dtors_test_base(false, true), + m_test_value(test_value) + { + + } + + std::string str() + { + return "ps_ctor_dtor_test"; + } + + // Returns value that is expected to be in output_buffer[i] + cl_uint operator()(size_t i) + { + return m_test_value; + } + + // In 1st kernel 0th work-item saves pointer to output buffer and its size in program scope + // variable global_var. + // After global_var is destroyed all even elements of output buffer should equal m_test_value, + // and all odd should equal 1. + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return + "__kernel void " + this->get_kernel_name() + "(global uint *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = " + std::to_string(m_test_value) + ";\n" + "}\n"; + #else + return + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + // struct template + "template\n" + "struct ctor_test_class {\n" + // non-trivial ctor + " ctor_test_class(T value) : m_value(value) { };\n" + " T m_value;\n" + "};\n\n" + // struct + "struct ctor_dtor_test_class {\n" + // non-trivial ctor + " ctor_dtor_test_class(uint value) : ctor_test(value) { } \n" + // non-trivial dtor + // set all values in buffer to m_test_value + " ~ctor_dtor_test_class() {\n" + " for(size_t i = 0; i < this->size; i++)\n" + " {\n" + " this->buffer[i] = ctor_test.m_value;\n" + " }\n" + " };\n" + " ctor_test_class ctor_test;\n" + " global_ptr buffer;\n" + " size_t size;\n" + "};\n" + // global scope program variable + "ctor_dtor_test_class global_var(" + std::to_string(m_test_value) + ");\n" + + "__kernel void " + this->get_kernel_name() + "(global_ptr output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + // set buffer and size in global var + " if(gid == 0){\n" + " global_var.buffer = output;\n" + " global_var.size = get_global_size(0);\n" + " }\n" + "}\n"; + #endif + } + +private: + cl_uint m_test_value; +}; + +// This contains tests for program scope (global) constructors and destructors, more +// detailed tests are also in clcpp/api. +AUTO_TEST_CASE(test_program_scope_ctors_dtors) +(cl_device_id device, cl_context context, cl_command_queue queue, int count) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + RUN_PS_CTORS_DTORS_TEST_MACRO(ps_ctor_test(0xdeadbeefU)) + RUN_PS_CTORS_DTORS_TEST_MACRO(ps_dtor_test(0xbeefdeadU)) + RUN_PS_CTORS_DTORS_TEST_MACRO(ps_ctor_dtor_test(0xdeaddeadU)) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_PS_CTORS_DTORS_TEST_CTORS_DTORS_HPP diff --git a/test_conformance/clcpp/reinterpret/CMakeLists.txt b/test_conformance/clcpp/reinterpret/CMakeLists.txt new file mode 100644 index 00000000..56564476 --- /dev/null +++ b/test_conformance/clcpp/reinterpret/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_REINTERPRET) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/reinterpret/as_type.hpp b/test_conformance/clcpp/reinterpret/as_type.hpp new file mode 100644 index 00000000..da088cfa --- /dev/null +++ b/test_conformance/clcpp/reinterpret/as_type.hpp @@ -0,0 +1,223 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_REINTERPRET_AS_TYPE_HPP +#define TEST_CONFORMANCE_CLCPP_REINTERPRET_AS_TYPE_HPP + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#include + + +template +struct as_type : public unary_func +{ + static_assert(sizeof(IN1) == sizeof(OUT1), "It is an error to use the as_type operator to reinterpret data to a type of a different number of bytes"); + + std::string str() + { + return "as_type"; + } + + std::string headers() + { + return "#include \n"; + } + + OUT1 operator()(const IN1& x) + { + return *reinterpret_cast(&x); + } +}; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template +std::string generate_kernel_as_type(func_type func) +{ + std::string in1_value = "input[gid]"; + std::string function_call = "as_" + type_name() + "(" + in1_value + ");"; + return + "__kernel void test_" + func.str() + "(global " + type_name() + " *input, global " + type_name() + " *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = " + function_call + ";\n" + "}\n"; +} +#else +template +std::string generate_kernel_as_type(func_type func) +{ + std::string headers = func.headers(); + std::string in1_value = "input[gid]"; + std::string function_call = "as_type<" + type_name() + ">(" + in1_value + ")"; + return + "" + func.defs() + + "" + headers + + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_" + func.str() + "(global_ptr<" + type_name() + "[]> input," + "global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = " + function_call + ";\n" + "}\n"; +} +#endif + +template +bool verify_as_type(const std::vector &in, const std::vector &out, as_type_op op) +{ + // When the operand and result type contain a different number of elements, the result is implementation-defined, + // i.e. any result is correct + if (vector_size::value == vector_size::value) + { + for (size_t i = 0; i < in.size(); i++) + { + auto expected = op(in[i]); + if (std::memcmp(&expected, &out[i], sizeof(expected)) != 0) + { + print_error_msg(expected, out[i], i, op); + return false; + } + } + } + return true; +} + +template +int test_as_type_func(cl_device_id device, cl_context context, cl_command_queue queue, size_t count, as_type_op op) +{ + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t work_size[1]; + int error; + + typedef typename as_type_op::in_type INPUT; + typedef typename as_type_op::out_type OUTPUT; + + // Don't run test for unsupported types + if (!(type_supported(device) && type_supported(device))) + { + return CL_SUCCESS; + } + + std::string code_str = generate_kernel_as_type(op); + std::string kernel_name("test_"); kernel_name += op.str(); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name, "-cl-std=CL2.0", false); + RETURN_ON_ERROR(error) +#else + error = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(error) +#endif + + std::vector input = generate_input(count, op.min1(), op.max1(), op.in_special_cases()); + std::vector output = generate_output(count); + + buffers[0] = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(INPUT) * input.size(), NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + buffers[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(OUTPUT) * output.size(), NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(INPUT) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + work_size[0] = count; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + error = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(OUTPUT) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + if (!verify_as_type(input, output, op)) + { + RETURN_ON_ERROR_MSG(-1, "test_%s %s(%s) failed", op.str().c_str(), type_name().c_str(), type_name().c_str()); + } + log_info("test_%s %s(%s) passed\n", op.str().c_str(), type_name().c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; +} + +AUTO_TEST_CASE(test_as_type) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + +#define TEST_AS_TYPE_MACRO(TYPE1, TYPE2) \ + last_error = test_as_type_func( \ + device, context, queue, n_elems, as_type() \ + ); \ + CHECK_ERROR(last_error) \ + error |= last_error; + + TEST_AS_TYPE_MACRO(cl_int, cl_int) + TEST_AS_TYPE_MACRO(cl_uint, cl_int) + TEST_AS_TYPE_MACRO(cl_int, cl_ushort2) + TEST_AS_TYPE_MACRO(cl_uchar, cl_uchar) + TEST_AS_TYPE_MACRO(cl_char4, cl_ushort2) + TEST_AS_TYPE_MACRO(cl_uchar16, cl_char16) + TEST_AS_TYPE_MACRO(cl_short8, cl_uchar16) + TEST_AS_TYPE_MACRO(cl_float4, cl_uint4) + TEST_AS_TYPE_MACRO(cl_float16, cl_int16) + TEST_AS_TYPE_MACRO(cl_long2, cl_float4) + TEST_AS_TYPE_MACRO(cl_ulong, cl_long) + TEST_AS_TYPE_MACRO(cl_ulong16, cl_double16) + TEST_AS_TYPE_MACRO(cl_uchar16, cl_double2) + TEST_AS_TYPE_MACRO(cl_ulong4, cl_short16) + +#undef TEST_AS_TYPE_MACRO + + if (error != CL_SUCCESS) + { + return -1; + } + return error; +} + + +#endif // TEST_CONFORMANCE_CLCPP_REINTERPRET_AS_TYPE_HPP diff --git a/test_conformance/clcpp/reinterpret/main.cpp b/test_conformance/clcpp/reinterpret/main.cpp new file mode 100644 index 00000000..3b5272df --- /dev/null +++ b/test_conformance/clcpp/reinterpret/main.cpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "as_type.hpp" + + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/relational_funcs/CMakeLists.txt b/test_conformance/clcpp/relational_funcs/CMakeLists.txt new file mode 100644 index 00000000..7eca7a11 --- /dev/null +++ b/test_conformance/clcpp/relational_funcs/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_RELATIONAL_FUNCS) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/relational_funcs/common.hpp b/test_conformance/clcpp/relational_funcs/common.hpp new file mode 100644 index 00000000..a13f7bac --- /dev/null +++ b/test_conformance/clcpp/relational_funcs/common.hpp @@ -0,0 +1,112 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_COMMON_HPP +#define TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_COMMON_HPP + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#include +#include + +template +OUT1 perform_function(const IN1& in1, const IN2& in2, const IN3& in3, F func, typename std::enable_if::value>::type* = 0) +{ + OUT1 result; + for(size_t i = 0; i < vector_size::value; i++) + { + result.s[i] = func(in1.s[i], in2.s[i], in3.s[i]); + } + return result; +} + +template +OUT1 perform_function(const IN1& in1, const IN2& in2, const IN3& in3, F func, typename std::enable_if::value>::type* = 0) +{ + OUT1 result = func(in1, in2, in3); + return result; +} + + +template +OUT1 perform_function(const IN1& in1, const IN2& in2, F func, typename std::enable_if::value>::type* = 0) +{ + OUT1 result; + for(size_t i = 0; i < vector_size::value; i++) + { + result.s[i] = func(in1.s[i], in2.s[i]); + } + return result; +} + +template +OUT1 perform_function(const IN1& in1, const IN2& in2, F func, typename std::enable_if::value>::type* = 0) +{ + OUT1 result = func(in1, in2); + return result; +} + +template +OUT1 perform_function(const IN1& in1, F func, typename std::enable_if::value>::type* = 0) +{ + OUT1 result; + for(size_t i = 0; i < vector_size::value; i++) + { + result.s[i] = func(in1.s[i]); + } + return result; +} + +template +OUT1 perform_function(const IN1& in1, F func, typename std::enable_if::value>::type* = 0) +{ + OUT1 result = func(in1); + return result; +} + +template +cl_int perform_all_function(const IN1& in1, typename std::enable_if::value>::type* = 0) +{ + cl_int result = 1; + for(size_t i = 0; i < vector_size::value; i++) + { + result = (in1.s[i] != 0) ? result : cl_int(0); + } + return result; +} + +cl_int perform_all_function(const cl_int& in1, typename std::enable_if::value>::type* = 0) +{ + return (in1 != 0) ? cl_int(1) : cl_int(0); +} + +template +cl_int perform_any_function(const IN1& in1, typename std::enable_if::value>::type* = 0) +{ + cl_int result = 0; + for(size_t i = 0; i < vector_size::value; i++) + { + result = (in1.s[i] != 0) ? cl_int(1) : result; + } + return result; +} + +cl_int perform_any_function(const cl_int& in1, typename std::enable_if::value>::type* = 0) +{ + return (in1 != 0) ? cl_int(1) : cl_int(0); +} + +#endif // TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_COMMON_HPP diff --git a/test_conformance/clcpp/relational_funcs/comparison_funcs.hpp b/test_conformance/clcpp/relational_funcs/comparison_funcs.hpp new file mode 100644 index 00000000..980d67c8 --- /dev/null +++ b/test_conformance/clcpp/relational_funcs/comparison_funcs.hpp @@ -0,0 +1,150 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_COMPARISON_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_COMPARISON_FUNCS_HPP + +#include "common.hpp" + +// This marco creates a class wrapper for comparision function we want to test. +#define DEF_COMPARISION_FUNC(CLASS_NAME, FUNC_NAME, HOST_FUNC_EXPRESSION) \ +template \ +struct CLASS_NAME : public binary_func< \ + typename make_vector_type::type, /* create cl_floatN type */ \ + typename make_vector_type::type, /* create cl_floatN type */ \ + typename make_vector_type::type /* create cl_intN type */ \ + > \ +{ \ + typedef typename make_vector_type::type input_type; \ + typedef typename make_vector_type::type result_type; \ + \ + std::string str() \ + { \ + return #FUNC_NAME; \ + } \ + \ + std::string headers() \ + { \ + return "#include \n"; \ + } \ + \ + result_type operator()(const input_type& x, const input_type& y) \ + { \ + typedef typename scalar_type::type SCALAR; \ + return perform_function( \ + x, y, \ + [](const SCALAR& a, const SCALAR& b) \ + { \ + if(HOST_FUNC_EXPRESSION) \ + { \ + return cl_int(1); \ + } \ + return cl_int(0); \ + } \ + ); \ + } \ + \ + bool is_out_bool() \ + { \ + return true; \ + } \ + \ + input_type min1() \ + { \ + return detail::def_limit(-10000.0f); \ + } \ + \ + input_type max1() \ + { \ + return detail::def_limit(10000.0f); \ + } \ + \ + input_type min2() \ + { \ + return detail::def_limit(-10000.0f); \ + } \ + \ + input_type max2() \ + { \ + return detail::def_limit(10000.0f); \ + } \ + \ + std::vector in1_special_cases() \ + { \ + typedef typename scalar_type::type SCALAR; \ + return { \ + detail::make_value(std::numeric_limits::infinity()), \ + detail::make_value(-std::numeric_limits::infinity()), \ + detail::make_value(std::numeric_limits::quiet_NaN()), \ + detail::make_value(0.0f), \ + detail::make_value(-0.0f) \ + }; \ + } \ + \ + std::vector in2_special_cases() \ + { \ + typedef typename scalar_type::type SCALAR; \ + return { \ + detail::make_value(std::numeric_limits::infinity()), \ + detail::make_value(-std::numeric_limits::infinity()), \ + detail::make_value(std::numeric_limits::quiet_NaN()), \ + detail::make_value(0.0f), \ + detail::make_value(-0.0f) \ + }; \ + } \ +}; + +DEF_COMPARISION_FUNC(comparison_func_isequal, isequal, (a == b)) +DEF_COMPARISION_FUNC(comparison_func_isnotequal, isnotequal, !(a == b)) +DEF_COMPARISION_FUNC(comparison_func_isgreater, isgreater, (std::isgreater)(a, b)) +DEF_COMPARISION_FUNC(comparison_func_isgreaterequal, isgreaterequal, ((std::isgreater)(a, b) || a == b)) +DEF_COMPARISION_FUNC(comparison_func_isless, isless, (std::isless)(a, b)) +DEF_COMPARISION_FUNC(comparison_func_islessequal, islessequal, ((std::isless)(a, b) || a == b)) +DEF_COMPARISION_FUNC(comparison_func_islessgreater, islessgreater, ((a < b) || (a > b))) + +#undef DEF_COMPARISION_FUNC + +AUTO_TEST_CASE(test_relational_comparison_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + +// Helper macro, so we don't have to repreat the same code. +#define TEST_BINARY_REL_FUNC_MACRO(CLASS_NAME) \ + TEST_BINARY_FUNC_MACRO(CLASS_NAME<1>()) \ + TEST_BINARY_FUNC_MACRO(CLASS_NAME<2>()) \ + TEST_BINARY_FUNC_MACRO(CLASS_NAME<4>()) \ + TEST_BINARY_FUNC_MACRO(CLASS_NAME<8>()) \ + TEST_BINARY_FUNC_MACRO(CLASS_NAME<16>()) + + TEST_BINARY_REL_FUNC_MACRO(comparison_func_isequal) + TEST_BINARY_REL_FUNC_MACRO(comparison_func_isnotequal) + TEST_BINARY_REL_FUNC_MACRO(comparison_func_isgreater) + TEST_BINARY_REL_FUNC_MACRO(comparison_func_isgreaterequal) + TEST_BINARY_REL_FUNC_MACRO(comparison_func_isless) + TEST_BINARY_REL_FUNC_MACRO(comparison_func_islessequal) + TEST_BINARY_REL_FUNC_MACRO(comparison_func_islessgreater) + +#undef TEST_BINARY_REL_FUNC_MACRO + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_COMPARISON_FUNCS_HPP diff --git a/test_conformance/clcpp/relational_funcs/main.cpp b/test_conformance/clcpp/relational_funcs/main.cpp new file mode 100644 index 00000000..6d708920 --- /dev/null +++ b/test_conformance/clcpp/relational_funcs/main.cpp @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "comparison_funcs.hpp" +#include "select_funcs.hpp" +#include "test_funcs.hpp" + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/relational_funcs/select_funcs.hpp b/test_conformance/clcpp/relational_funcs/select_funcs.hpp new file mode 100644 index 00000000..2e6f6bdd --- /dev/null +++ b/test_conformance/clcpp/relational_funcs/select_funcs.hpp @@ -0,0 +1,158 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_SELECT_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_SELECT_FUNCS_HPP + +#include "common.hpp" + +template +struct select_func_select : public ternary_func< + typename make_vector_type::type, /* create IN1N type */ + typename make_vector_type::type, /* create IN1N type */ + typename make_vector_type::type, /* create cl_intN type */ + typename make_vector_type::type /* create IN1N type */ + > +{ + typedef typename make_vector_type::type input1_type; + typedef typename make_vector_type::type input2_type; + typedef typename make_vector_type::type input3_type; + typedef typename make_vector_type::type result_type; + + std::string str() + { + return "select"; + } + + std::string headers() + { + return "#include \n"; + } + + result_type operator()(const input1_type& x, const input2_type& y, const input3_type& z) + { + typedef typename scalar_type::type SCALAR1; + typedef typename scalar_type::type SCALAR2; + typedef typename scalar_type::type SCALAR3; + + return perform_function( + x, y, z, + [](const SCALAR1& a, const SCALAR2& b, const SCALAR3& c) + { + return (c != 0) ? b : a; + } + ); + } + + bool is_in3_bool() + { + return true; + } + + std::vector in3_special_cases() + { + return { + detail::make_value(0), + detail::make_value(1), + detail::make_value(12), + detail::make_value(-12) + }; + } +}; + +template +struct select_func_bitselect : public ternary_func< + typename make_vector_type::type, /* create IN1N type */ + typename make_vector_type::type, /* create IN1N type */ + typename make_vector_type::type, /* create cl_intN type */ + typename make_vector_type::type /* create IN1N type */ + > +{ + typedef typename make_vector_type::type input1_type; + typedef typename make_vector_type::type input2_type; + typedef typename make_vector_type::type input3_type; + typedef typename make_vector_type::type result_type; + + std::string str() + { + return "bitselect"; + } + + std::string headers() + { + return "#include \n"; + } + + result_type operator()(const input1_type& x, const input2_type& y, const input3_type& z) + { + static_assert( + std::is_integral::value, + "bitselect test is implemented only for integers." + ); + static_assert( + std::is_unsigned::value, + "IN1 type should be unsigned, bitwise operations on signed int may cause problems." + ); + typedef typename scalar_type::type SCALAR1; + typedef typename scalar_type::type SCALAR2; + typedef typename scalar_type::type SCALAR3; + + return perform_function( + x, y, z, + [](const SCALAR1& a, const SCALAR2& b, const SCALAR3& c) + { + return (~c & a) | (c & b); + } + ); + } +}; + +AUTO_TEST_CASE(test_relational_select_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + +// Tests for select(gentype a, gentype b, booln c) are not run in USE_OPENCLC_KERNELS +// mode, because this functions in OpenCL C requires different reference functions on host +// compared to their equivalent in OpenCL C++. +// (In OpenCL C the result of select(), when gentype is vector type, is based on the most +// significant bits of c components) +#ifndef USE_OPENCLC_KERNELS + // gentype select(gentype a, gentype b, booln c) + TEST_TERNARY_FUNC_MACRO((select_func_select())) + TEST_TERNARY_FUNC_MACRO((select_func_select())) + TEST_TERNARY_FUNC_MACRO((select_func_select())) + TEST_TERNARY_FUNC_MACRO((select_func_select())) + TEST_TERNARY_FUNC_MACRO((select_func_select())) +#else + log_info("WARNING:\n\tTests for select(gentype a, gentype b, booln c) are not run in USE_OPENCLC_KERNELS mode\n"); +#endif + + // gentype bitselect(gentype a, gentype b, gentype c) + TEST_TERNARY_FUNC_MACRO((select_func_bitselect())) + TEST_TERNARY_FUNC_MACRO((select_func_bitselect())) + TEST_TERNARY_FUNC_MACRO((select_func_bitselect())) + TEST_TERNARY_FUNC_MACRO((select_func_bitselect())) + TEST_TERNARY_FUNC_MACRO((select_func_bitselect())) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_SELECT_FUNCS_HPP diff --git a/test_conformance/clcpp/relational_funcs/test_funcs.hpp b/test_conformance/clcpp/relational_funcs/test_funcs.hpp new file mode 100644 index 00000000..77e3d871 --- /dev/null +++ b/test_conformance/clcpp/relational_funcs/test_funcs.hpp @@ -0,0 +1,336 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_TEST_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_TEST_FUNCS_HPP + +#include "common.hpp" + +// This marco creates a class wrapper for unary test function we want to test. +#define DEF_UNARY_TEST_FUNC(CLASS_NAME, FUNC_NAME, HOST_FUNC_EXPRESSION) \ +template \ +struct CLASS_NAME : public unary_func< \ + typename make_vector_type::type, /* create cl_floatN type */ \ + typename make_vector_type::type /* create cl_intN type */ \ + > \ +{ \ + typedef typename make_vector_type::type input_type; \ + typedef typename make_vector_type::type result_type; \ + \ + std::string str() \ + { \ + return #FUNC_NAME; \ + } \ + \ + std::string headers() \ + { \ + return "#include \n"; \ + } \ + \ + result_type operator()(const input_type& x) \ + { \ + typedef typename scalar_type::type SCALAR; \ + return perform_function( \ + x, \ + [](const SCALAR& a) \ + { \ + if(HOST_FUNC_EXPRESSION) \ + { \ + return cl_int(1); \ + } \ + return cl_int(0); \ + } \ + ); \ + } \ + \ + bool is_out_bool() \ + { \ + return true; \ + } \ + \ + input_type min1() \ + { \ + return detail::def_limit(-10000.0f); \ + } \ + \ + input_type max1() \ + { \ + return detail::def_limit(10000.0f); \ + } \ + \ + std::vector in1_special_cases() \ + { \ + typedef typename scalar_type::type SCALAR; \ + return { \ + detail::make_value(std::numeric_limits::infinity()), \ + detail::make_value(-std::numeric_limits::infinity()), \ + detail::make_value(std::numeric_limits::quiet_NaN()), \ + detail::make_value(std::numeric_limits::signaling_NaN()), \ + detail::make_value(std::numeric_limits::denorm_min()), \ + detail::make_value(0.0f), \ + detail::make_value(-0.0f) \ + }; \ + } \ +}; + +// This marco creates a class wrapper for binary test function we want to test. +#define DEF_BINARY_TEST_FUNC(CLASS_NAME, FUNC_NAME, HOST_FUNC_EXPRESSION) \ +template \ +struct CLASS_NAME : public binary_func< \ + typename make_vector_type::type, /* create cl_floatN type */ \ + typename make_vector_type::type, /* create cl_floatN type */ \ + typename make_vector_type::type /* create cl_intN type */ \ + > \ +{ \ + typedef typename make_vector_type::type input_type; \ + typedef typename make_vector_type::type result_type; \ + \ + std::string str() \ + { \ + return #FUNC_NAME; \ + } \ + \ + std::string headers() \ + { \ + return "#include \n"; \ + } \ + \ + result_type operator()(const input_type& x, const input_type& y) \ + { \ + typedef typename scalar_type::type SCALAR; \ + return perform_function( \ + x, y, \ + [](const SCALAR& a, const SCALAR& b) \ + { \ + if(HOST_FUNC_EXPRESSION) \ + { \ + return cl_int(1); \ + } \ + return cl_int(0); \ + } \ + ); \ + } \ + \ + bool is_out_bool() \ + { \ + return true; \ + } \ + \ + input_type min1() \ + { \ + return detail::def_limit(-10000.0f); \ + } \ + \ + input_type max1() \ + { \ + return detail::def_limit(10000.0f); \ + } \ + \ + input_type min2() \ + { \ + return detail::def_limit(-10000.0f); \ + } \ + \ + input_type max2() \ + { \ + return detail::def_limit(10000.0f); \ + } \ + \ + std::vector in1_special_cases() \ + { \ + typedef typename scalar_type::type SCALAR; \ + return { \ + detail::make_value(std::numeric_limits::infinity()), \ + detail::make_value(-std::numeric_limits::infinity()), \ + detail::make_value(std::numeric_limits::quiet_NaN()), \ + detail::make_value(std::numeric_limits::signaling_NaN()), \ + detail::make_value(std::numeric_limits::denorm_min()), \ + detail::make_value(0.0f), \ + detail::make_value(-0.0f) \ + }; \ + } \ + \ + std::vector in2_special_cases() \ + { \ + typedef typename scalar_type::type SCALAR; \ + return { \ + detail::make_value(std::numeric_limits::infinity()), \ + detail::make_value(-std::numeric_limits::infinity()), \ + detail::make_value(std::numeric_limits::quiet_NaN()), \ + detail::make_value(std::numeric_limits::signaling_NaN()), \ + detail::make_value(std::numeric_limits::denorm_min()), \ + detail::make_value(0.0f), \ + detail::make_value(-0.0f) \ + }; \ + } \ +}; + +DEF_UNARY_TEST_FUNC(test_func_isfinite, isfinite, (std::isfinite)(a)) +DEF_UNARY_TEST_FUNC(test_func_isinf, isinf, (std::isinf)(a)) +DEF_UNARY_TEST_FUNC(test_func_isnan, isnan, (std::isnan)(a)) +DEF_UNARY_TEST_FUNC(test_func_isnormal, isnormal, (std::isnormal)(a)) +DEF_UNARY_TEST_FUNC(test_func_signbit, signbit , (std::signbit)(a)) + +DEF_BINARY_TEST_FUNC(test_func_isordered, isordered, !(std::isunordered)(a, b)) +DEF_BINARY_TEST_FUNC(test_func_isunordered, isunordered, (std::isunordered)(a, b)) + +#undef DEF_UNARY_TEST_FUNC +#undef DEF_BINARY_TEST_FUNC + +template +struct test_func_all : public unary_func< + typename make_vector_type::type, /* create cl_intN type */ + cl_int /* create cl_intN type */ + > +{ + typedef typename make_vector_type::type input_type; + typedef cl_int result_type; + + std::string str() + { + return "all"; + } + + std::string headers() + { + return "#include \n"; + } + + result_type operator()(const input_type& x) + { + return perform_all_function(x); + } + + bool is_out_bool() + { + return true; + } + + bool is_in1_bool() + { + return true; + } + + std::vector in1_special_cases() + { + return { + detail::make_value(0), + detail::make_value(1), + detail::make_value(12), + detail::make_value(-12) + }; + } +}; + +template +struct test_func_any : public unary_func< + typename make_vector_type::type, /* create cl_intN type */ + cl_int /* create cl_intN type */ + > +{ + typedef typename make_vector_type::type input_type; + typedef cl_int result_type; + + std::string str() + { + return "any"; + } + + std::string headers() + { + return "#include \n"; + } + + result_type operator()(const input_type& x) + { + return perform_any_function(x); + } + + bool is_out_bool() + { + return true; + } + + bool is_in1_bool() + { + return true; + } + + std::vector in1_special_cases() + { + return { + detail::make_value(0), + detail::make_value(1), + detail::make_value(12), + detail::make_value(-12) + }; + } +}; + +AUTO_TEST_CASE(test_relational_test_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + +// Helper macro, so we don't have to repreat the same code. +#define TEST_UNARY_REL_FUNC_MACRO(CLASS_NAME) \ + TEST_UNARY_FUNC_MACRO(CLASS_NAME<1>()) \ + TEST_UNARY_FUNC_MACRO(CLASS_NAME<2>()) \ + TEST_UNARY_FUNC_MACRO(CLASS_NAME<4>()) \ + TEST_UNARY_FUNC_MACRO(CLASS_NAME<8>()) \ + TEST_UNARY_FUNC_MACRO(CLASS_NAME<16>()) + + TEST_UNARY_REL_FUNC_MACRO(test_func_isfinite) + TEST_UNARY_REL_FUNC_MACRO(test_func_isinf) + TEST_UNARY_REL_FUNC_MACRO(test_func_isnan) + TEST_UNARY_REL_FUNC_MACRO(test_func_isnormal) + TEST_UNARY_REL_FUNC_MACRO(test_func_signbit) + +// Tests for all(booln x) and any(booln x) are not run in USE_OPENCLC_KERNELS mode, +// because those functions in OpenCL C require different reference functions on host +// compared to their equivalents from OpenCL C++. +// (In OpenCL C those functions returns true/false based on the most significant bits +// in any/all component/s of x) +#ifndef USE_OPENCLC_KERNELS + TEST_UNARY_REL_FUNC_MACRO(test_func_all) + TEST_UNARY_REL_FUNC_MACRO(test_func_any) +#else + log_info("WARNING:\n\tTests for bool all(booln x) are not run in USE_OPENCLC_KERNELS mode\n"); + log_info("WARNING:\n\tTests for bool any(booln x) are not run in USE_OPENCLC_KERNELS mode\n"); +#endif + +#undef TEST_UNARY_REL_FUNC_MACRO + +#define TEST_BINARY_REL_FUNC_MACRO(CLASS_NAME) \ + TEST_BINARY_FUNC_MACRO(CLASS_NAME<1>()) \ + TEST_BINARY_FUNC_MACRO(CLASS_NAME<2>()) \ + TEST_BINARY_FUNC_MACRO(CLASS_NAME<4>()) \ + TEST_BINARY_FUNC_MACRO(CLASS_NAME<8>()) \ + TEST_BINARY_FUNC_MACRO(CLASS_NAME<16>()) + + TEST_BINARY_REL_FUNC_MACRO(test_func_isordered) + TEST_BINARY_REL_FUNC_MACRO(test_func_isunordered) + +#undef TEST_BINARY_REL_FUNC_MACRO + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_TEST_FUNCS_HPP diff --git a/test_conformance/clcpp/spec_constants/CMakeLists.txt b/test_conformance/clcpp/spec_constants/CMakeLists.txt new file mode 100644 index 00000000..80904bf7 --- /dev/null +++ b/test_conformance/clcpp/spec_constants/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_SPEC_CONSTANTS) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/spec_constants/common.hpp b/test_conformance/clcpp/spec_constants/common.hpp new file mode 100644 index 00000000..3846fe83 --- /dev/null +++ b/test_conformance/clcpp/spec_constants/common.hpp @@ -0,0 +1,257 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_COMMON_HPP +#define TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_COMMON_HPP + +#include + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#define RUN_SPEC_CONSTANTS_TEST_MACRO(TEST_CLASS) \ + last_error = run_spec_constants_test( \ + device, context, queue, n_elems, TEST_CLASS \ + ); \ + CHECK_ERROR(last_error) \ + error |= last_error; + +// Base class for all tests of cl::spec_contatnt +template +struct spec_constants_test : public detail::base_func_type +{ + // Output buffer type + typedef T type; + + virtual ~spec_constants_test() {}; + // Returns test name + virtual std::string str() = 0; + // Returns OpenCL program source + virtual std::string generate_program() = 0; + + // Return names of test's kernels, in order. + // Typical case: one kernel. + virtual std::vector get_kernel_names() + { + // Typical case, that is, only one kernel + return { this->get_kernel_name() }; + } + + // If local size has to be set in clEnqueueNDRangeKernel() + // this should return true; otherwise - false; + virtual bool set_local_size() + { + return false; + } + + // Calculates maximal work-group size (one dim) + virtual size_t get_max_local_size(const std::vector& kernels, + cl_device_id device, + size_t work_group_size, // default work-group size + cl_int& error) + { + size_t wg_size = work_group_size; + for(auto& k : kernels) + { + size_t max_wg_size; + error = clGetKernelWorkGroupInfo( + k, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &max_wg_size, NULL + ); + RETURN_ON_CL_ERROR(error, "clGetKernelWorkGroupInfo") + wg_size = (std::min)(wg_size, max_wg_size); + } + return wg_size; + } + + // Sets spec constants + // Typical case: no spec constants to set + virtual cl_int set_spec_constants(const cl_program& program) + { + return CL_SUCCESS; + } + + // This covers typical case: + // 1. each kernel is executed once, + // 2. the only argument in every kernel is output_buffer + virtual cl_int execute(const std::vector& kernels, + cl_mem& output_buffer, + cl_command_queue& queue, + size_t work_size, + size_t work_group_size) + { + cl_int err; + for(auto& k : kernels) + { + err = clSetKernelArg(k, 0, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel( + queue, k, 1, + NULL, &work_size, this->set_local_size() ? &work_group_size : NULL, + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + } + return err; + } + + // This is a function which performs additional queries and checks + // if the results are correct. This method is run after checking that + // test results (output values) are correct. + virtual cl_int check_queries(const std::vector& kernels, + cl_device_id device, + cl_context context, + cl_command_queue queue) + { + (void) kernels; + (void) device; + (void) context; + (void) queue; + return CL_SUCCESS; + } +}; + +template +int run_spec_constants_test(cl_device_id device, cl_context context, cl_command_queue queue, size_t count, spec_constants_test op) +{ + cl_mem buffers[1]; + cl_program program; + std::vector kernels; + size_t wg_size; + size_t work_size[1]; + cl_int err; + + typedef typename spec_constants_test::type TYPE; + + // Don't run test for unsupported types + if(!(type_supported(device))) + { + return CL_SUCCESS; + } + + std::string code_str = op.generate_program(); + std::vector kernel_names = op.get_kernel_names(); + if(kernel_names.empty()) + { + RETURN_ON_ERROR_MSG(-1, "No kernel to run"); + } + kernels.resize(kernel_names.size()); + + std::string options = ""; + if(is_extension_available(device, "cl_khr_fp16")) + { + options += " -cl-fp16-enable"; + } + if(is_extension_available(device, "cl_khr_fp64")) + { + options += " -cl-fp64-enable"; + } +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &(kernels[0]), code_str, kernel_names[0], options); + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &(kernels[0]), code_str, kernel_names[0], "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) + for(size_t i = 1; i < kernels.size(); i++) + { + kernels[i] = clCreateKernel(program, kernel_names[i].c_str(), &err); + RETURN_ON_CL_ERROR(err, "clCreateKernel"); + } +#else + const char * code_c_str = code_str.c_str(); + err = create_openclcpp_program(context, &program, 1, &(code_c_str), options.c_str()); + RETURN_ON_ERROR_MSG(err, "Creating OpenCL C++ program failed") + + // Set spec constants + err = op.set_spec_constants(program); + RETURN_ON_ERROR_MSG(err, "Setting Spec Constants failed") + + // Build program and create 1st kernel + err = build_program_create_kernel_helper( + context, &program, &(kernels[0]), 1, &(code_c_str), kernel_names[0].c_str() + ); + RETURN_ON_ERROR_MSG(err, "Unable to build program or to create kernel") + // Create other kernels + for(size_t i = 1; i < kernels.size(); i++) + { + kernels[i] = clCreateKernel(program, kernel_names[i].c_str(), &err); + RETURN_ON_CL_ERROR(err, "clCreateKernel"); + } +#endif + + // Find the max possible wg size for among all the kernels + wg_size = op.get_max_local_size(kernels, device, 1024, err); + RETURN_ON_ERROR(err); + + work_size[0] = count; + if(op.set_local_size()) + { + size_t wg_number = static_cast( + std::ceil(static_cast(count) / wg_size) + ); + work_size[0] = wg_number * wg_size; + } + + // host output vector + std::vector output = generate_output(work_size[0], 9999); + + // device output buffer + buffers[0] = clCreateBuffer( + context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(TYPE) * output.size(), NULL, &err + ); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + // Execute test + err = op.execute(kernels, buffers[0], queue, work_size[0], wg_size); + RETURN_ON_ERROR(err) + + err = clEnqueueReadBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(TYPE) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + // Check output values + for(size_t i = 0; i < output.size(); i++) + { + TYPE v = op(i, wg_size); + if(!(are_equal(v, output[i], detail::make_value(0), op))) + { + RETURN_ON_ERROR_MSG(-1, + "test_%s(%s) failed. Expected: %s, got: %s", op.str().c_str(), type_name().c_str(), + format_value(v).c_str(), format_value(output[i]).c_str() + ); + } + } + + // Check if queries returns correct values + err = op.check_queries(kernels, device, context, queue); + RETURN_ON_ERROR(err); + + log_info("test_%s(%s) passed\n", op.str().c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + for(auto& k : kernels) + clReleaseKernel(k); + clReleaseProgram(program); + return err; +} + +#endif // TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_COMMON_HPP diff --git a/test_conformance/clcpp/spec_constants/main.cpp b/test_conformance/clcpp/spec_constants/main.cpp new file mode 100644 index 00000000..ce505e8f --- /dev/null +++ b/test_conformance/clcpp/spec_constants/main.cpp @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "test_spec_consts_attributes.hpp" +#include "test_spec_consts_if.hpp" +#include "test_spec_consts_init_vars.hpp" + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/spec_constants/test_spec_consts_attributes.hpp b/test_conformance/clcpp/spec_constants/test_spec_consts_attributes.hpp new file mode 100644 index 00000000..539167fd --- /dev/null +++ b/test_conformance/clcpp/spec_constants/test_spec_consts_attributes.hpp @@ -0,0 +1,281 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_ATTRIBUTES_HPP +#define TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_ATTRIBUTES_HPP + +#include + +#include "common.hpp" + +// In this test we check if specialization constant can be successfully used +// in kernel attribute cl::required_work_group_size(X, Y, Z). +struct spec_const_required_work_group_size_test : public spec_constants_test +{ + // See generate_program() to know what set_spec_constant is for. + spec_const_required_work_group_size_test(const bool set_spec_constant, + const cl_uint work_group_size_0) + : m_set_spec_constant(set_spec_constant), + m_work_group_size_0(work_group_size_0) + { + + } + + std::string str() + { + if(m_set_spec_constant) + return "spec_const_in_required_work_group_size_" + std::to_string(m_work_group_size_0); + else + return "spec_const_in_required_work_group_size_not_set"; + } + + bool set_local_size() + { + return true; + } + + size_t get_max_local_size(const std::vector& kernels, + cl_device_id device, + size_t work_group_size, // default work-group size + cl_int& error) + { + if(m_set_spec_constant) + { + return m_work_group_size_0; + } + return size_t(1); + } + + cl_uint operator()(size_t i, size_t work_group_size) + { + (void) work_group_size; + if(m_set_spec_constant) + { + return m_work_group_size_0; + } + return cl_uint(1); + } + + // Check if query for CL_KERNEL_COMPILE_WORK_GROUP_SIZE using clGetKernelWorkGroupInfo + // return correct values. It should return the work-group size specified by the + // cl::required_work_group_size(X, Y, Z) qualifier. + cl_int check_queries(const std::vector& kernels, + cl_device_id device, + cl_context context, + cl_command_queue queue) + { + (void) device; + (void) context; + size_t compile_wg_size[] = { 1, 1, 1 }; + cl_int error = clGetKernelWorkGroupInfo( + kernels[0], device, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, + sizeof(compile_wg_size), compile_wg_size, NULL + ); + RETURN_ON_CL_ERROR(error, "clGetKernelWorkGroupInfo") + if(m_set_spec_constant) + { + if(compile_wg_size[0] != m_work_group_size_0 + || compile_wg_size[1] != 1 + || compile_wg_size[2] != 1) + { + error = -1; + } + } + else + { + if(compile_wg_size[0] != 1 + || compile_wg_size[1] != 1 + || compile_wg_size[2] != 1) + { + error = -1; + } + } + return error; + } + + // Sets spec constant + cl_int set_spec_constants(const cl_program& program) + { + cl_int error = CL_SUCCESS; + if(m_set_spec_constant) + { + error = clSetProgramSpecializationConstant( + program, cl_uint(1), sizeof(cl_uint), static_cast(&m_work_group_size_0) + ); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + } + return error; + } + + // Each work-item writes get_local_size(0) to output[work-item-global-id] + std::string generate_program(bool with_attribute) + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + std::string att = " "; + if(with_attribute) + { + std::string work_group_size_0 = "1"; + if(m_set_spec_constant) + { + work_group_size_0 = std::to_string(m_work_group_size_0); + } + att = "\n__attribute__((reqd_work_group_size(" + work_group_size_0 + ",1,1)))\n"; + } + return + "__kernel" + att + "void " + this->get_kernel_name() + "(global uint *output)\n" + "{\n" + " uint gid = get_global_id(0);\n" + " output[gid] = get_local_size(0);\n" + "}\n"; + + #else + std::string att = ""; + if(with_attribute) + { + att = "[[cl::required_work_group_size(spec1, 1, 1)]]\n"; + } + return + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "spec_constant spec1{1};\n" + + att + + "__kernel void " + this->get_kernel_name() + "(global_ptr output)\n" + "{\n" + " uint gid = get_global_id(0);\n" + " output[gid] = get_local_size(0);\n" + "}\n"; + #endif + } + + // Each work-item writes get_local_size(0) to output[work-item-global-id] + std::string generate_program() + { + return generate_program(true); + } + +private: + bool m_set_spec_constant; + cl_uint m_work_group_size_0; +}; + +// This function return max work-group size that can be used +// for kernels defined in source +size_t get_max_wg_size(const std::string& source, + const std::vector& kernel_names, + size_t work_group_size, // max wg size we want to have + cl_device_id device, + cl_context context, + cl_command_queue queue, + cl_int& err) +{ + cl_program program; + std::vector kernels; + if(kernel_names.empty()) + { + RETURN_ON_ERROR_MSG(-1, "No kernel to run"); + } + kernels.resize(kernel_names.size()); +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &(kernels[0]), source, kernel_names[0], "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) + for(size_t i = 1; i < kernels.size(); i++) + { + kernels[i] = clCreateKernel(program, kernel_names[i].c_str(), &err); + RETURN_ON_CL_ERROR(err, "clCreateKernel"); + } +#else + err = create_opencl_kernel(context, &program, &(kernels[0]), source, kernel_names[0]); + RETURN_ON_ERROR(err) + for(size_t i = 1; i < kernels.size(); i++) + { + kernels[i] = clCreateKernel(program, kernel_names[i].c_str(), &err); + RETURN_ON_CL_ERROR(err, "clCreateKernel"); + } +#endif + size_t wg_size = work_group_size; + for(auto& k : kernels) + { + size_t max_wg_size; + err = clGetKernelWorkGroupInfo( + k, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &max_wg_size, NULL + ); + RETURN_ON_CL_ERROR(err, "clGetKernelWorkGroupInfo") + wg_size = (std::min)(wg_size, max_wg_size); + } + return wg_size; +} + +AUTO_TEST_CASE(test_spec_constants_in_kernel_attributes) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// If ONLY_SPIRV_COMPILATION is defined we can't check the max work-group size for the +// kernel because OpenCL kernel object is never created in that mode. +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + const size_t max_wg_size = 16; +#else + // Get max work-group size that can be used in [[cl::required_work_group_size(X, 1, 1)]] + // We do this by building kernel without this attribute and checking what is the max + // work-group size we can use with it. + auto test = spec_const_required_work_group_size_test(true, 1); + const size_t max_wg_size = get_max_wg_size( + test.generate_program(false), test.get_kernel_names(), + 1024, // max wg size we want to test + device, context, queue, + error + ); + RETURN_ON_ERROR_MSG(error, "Can't get max work-group size"); +#endif + + // Run tests when specialization constant spec1 is set (kernel + // attribute is [[cl::required_work_group_size(spec1, 1, 1)]]). + for(size_t i = 1; i <= max_wg_size; i *=2) + { + RUN_SPEC_CONSTANTS_TEST_MACRO( + spec_const_required_work_group_size_test( + true, i + ) + ); + } + // This test does not set spec constant + RUN_SPEC_CONSTANTS_TEST_MACRO( + spec_const_required_work_group_size_test( + false, 9999999 // This value is incorrect, but won't be set and kernel + // attribute should be [[cl::required_work_group_size(1, 1, 1)]] + ) + ); + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_ATTRIBUTES_HPP diff --git a/test_conformance/clcpp/spec_constants/test_spec_consts_if.hpp b/test_conformance/clcpp/spec_constants/test_spec_consts_if.hpp new file mode 100644 index 00000000..1c7cec2a --- /dev/null +++ b/test_conformance/clcpp/spec_constants/test_spec_consts_if.hpp @@ -0,0 +1,161 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_IF_HPP +#define TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_IF_HPP + +#include + +#include "common.hpp" + +// This class tests using specialization constant in if statement +template +struct spec_const_in_if_test : public spec_constants_test +{ + // See generate_program() to know what set_spec_constant is for. + spec_const_in_if_test(const bool set_spec_constant) + : m_set_spec_constant(set_spec_constant) + { + static_assert( + is_vector_type::value == false, + "Specialization constant can be only scalar int or float type" + ); + switch (sizeof(T)) + { + case 1: + m_test_value = T(127); + break; + case 2: + m_test_value = T(0xdeadU); + break; + // 4 and 8 + default: + m_test_value = T(0xdeaddeadU); + break; + } + } + + std::string str() + { + return "spec_const_in_if_" + type_name(); + } + + cl_uint operator()(size_t i, size_t work_group_size) + { + (void) work_group_size; + if(m_set_spec_constant) + { + return m_test_value; + } + return static_cast(i); + } + + // Sets spec constant + cl_int set_spec_constants(const cl_program& program) + { + cl_int error = CL_SUCCESS; + if(m_set_spec_constant) + { + T spec1 = static_cast(m_test_value); + error = clSetProgramSpecializationConstant( + program, cl_uint(1), sizeof(T), static_cast(&spec1) + ); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + } + return error; + } + + // IF set_spec_constant == true: + // each work-item writes T(m_test_value) to output[work-item-global-id] + // Otherwise: + // each work-item writes T(get_global_id(0)) to output[work-item-global-id] + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + std::string result = "gid"; + if(m_set_spec_constant) + result = std::to_string(m_test_value); + return + "__kernel void " + this->get_kernel_name() + "(global uint *output)\n" + "{\n" + " uint gid = get_global_id(0);\n" + " output[gid] = " + result + ";\n" + "}\n"; + + #else + return + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "typedef " + type_name() + " TYPE;\n" + "spec_constant spec1{TYPE(0)};\n" + "__kernel void " + this->get_kernel_name() + "(global_ptr output)\n" + "{\n" + " uint gid = get_global_id(0);\n" + " if(get(spec1) == TYPE(" + std::to_string(m_test_value) +"))\n" + " {\n" + " output[gid] = " + std::to_string(m_test_value) +";\n" + " }\n" + " else\n" + " {\n" + " output[gid] = gid;\n" + " }\n" + "}\n"; + #endif + } + +private: + bool m_set_spec_constant; + cl_uint m_test_value; +}; + +AUTO_TEST_CASE(test_spec_constants_in_if_statement) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + const std::vector set_spec_const_options { true, false }; + for(auto option : set_spec_const_options) + { + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test(option)); + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test(option)); + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test(option)); + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test(option)); + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test(option)); + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test(option)); + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test(option)); + if(is_extension_available(device, "cl_khr_fp16")) + { + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test(option)); + } + if(is_extension_available(device, "cl_khr_fp64")) + { + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test(option)); + } + } + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_IF_HPP diff --git a/test_conformance/clcpp/spec_constants/test_spec_consts_init_vars.hpp b/test_conformance/clcpp/spec_constants/test_spec_consts_init_vars.hpp new file mode 100644 index 00000000..20bbff06 --- /dev/null +++ b/test_conformance/clcpp/spec_constants/test_spec_consts_init_vars.hpp @@ -0,0 +1,174 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_INIT_VARS_HPP +#define TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_INIT_VARS_HPP + +#include + +#include "common.hpp" + +// This class tests initializing variables with a specialization constant value. +template +struct spec_const_init_var : public spec_constants_test +{ + // See generate_program() to know what set_spec_constant is for. + spec_const_init_var(const bool set_spec_constant) + : m_set_spec_constant(set_spec_constant) + { + static_assert( + is_vector_type::value == false, + "Specialization constant can be only scalar int or float type" + ); + switch (sizeof(T)) + { + case 1: + m_test_value = T(127); + break; + case 2: + m_test_value = T(0xdeadU); + break; + // 4 and 8 + default: + m_test_value = T(0xdeaddeadU); + break; + } + } + + std::string str() + { + return "spec_const_init_var_" + type_name(); + } + + cl_uint operator()(size_t i, size_t work_group_size) + { + (void) work_group_size; + if(m_set_spec_constant) + { + return m_test_value; + } + return static_cast(i); + } + + // Sets spec constant + cl_int set_spec_constants(const cl_program& program) + { + cl_int error = CL_SUCCESS; + if(m_set_spec_constant) + { + T spec = static_cast(m_test_value); + // spec1 + error = clSetProgramSpecializationConstant( + program, cl_uint(1), sizeof(T), static_cast(&spec) + ); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + + // spec2 + error = clSetProgramSpecializationConstant( + program, cl_uint(2), sizeof(T), static_cast(&spec) + ); + RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant") + } + return error; + } + + // IF set_spec_constant == true: + // each work-item writes T(m_test_value) to output[work-item-global-id] + // Otherwise: + // each work-item writes T(get_global_id(0)) to output[work-item-global-id] + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + std::string result = "gid"; + if(m_set_spec_constant) + result = std::to_string(m_test_value); + return + "__kernel void " + this->get_kernel_name() + "(global uint *output)\n" + "{\n" + " uint gid = get_global_id(0);\n" + " output[gid] = " + result + ";\n" + "}\n"; + + #else + return + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "typedef " + type_name() + " TYPE;\n" + "spec_constant spec1{TYPE(0)};\n" + "spec_constant spec2{TYPE(0)};\n" + "__kernel void " + this->get_kernel_name() + "(global_ptr output)\n" + "{\n" + " uint gid = get_global_id(0);\n" + " TYPE var1(spec1.get());\n" + " TYPE var2(spec2);\n" + " TYPE var3; var3 = spec2;\n" + " if((var1 == TYPE(" + std::to_string(m_test_value) +")) " + "&& (var2 == TYPE(" + std::to_string(m_test_value) +"))\n" + "&& (var3 == TYPE(" + std::to_string(m_test_value) +")))\n" + " {\n" + " output[gid] = " + std::to_string(m_test_value) +";\n" + " }\n" + " else\n" + " {\n" + " output[gid] = gid;\n" + " }\n" + "}\n"; + #endif + } + +private: + bool m_set_spec_constant; + cl_uint m_test_value; +}; + +AUTO_TEST_CASE(test_spec_constants_initializing_variables) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + const std::vector set_spec_const_options { true, false }; + for(auto option : set_spec_const_options) + { + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var(option)); + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var(option)); + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var(option)); + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var(option)); + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var(option)); + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var(option)); + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var(option)); + if(is_extension_available(device, "cl_khr_fp16")) + { + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var(option)); + } + if(is_extension_available(device, "cl_khr_fp64")) + { + RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var(option)); + } + } + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_INIT_VARS_HPP diff --git a/test_conformance/clcpp/subgroups/CMakeLists.txt b/test_conformance/clcpp/subgroups/CMakeLists.txt new file mode 100644 index 00000000..1d1e1907 --- /dev/null +++ b/test_conformance/clcpp/subgroups/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_SUBGROUPS) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/subgroups/common.hpp b/test_conformance/clcpp/subgroups/common.hpp new file mode 100644 index 00000000..2b05a3cb --- /dev/null +++ b/test_conformance/clcpp/subgroups/common.hpp @@ -0,0 +1,97 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SG_COMMON_HPP +#define TEST_CONFORMANCE_CLCPP_SG_COMMON_HPP + +#include +#include +#include + +enum class work_group_op : int { + add, min, max +}; + +std::string to_string(work_group_op op) +{ + switch (op) + { + case work_group_op::add: + return "add"; + case work_group_op::min: + return "min"; + case work_group_op::max: + return "max"; + default: + break; + } + return ""; +} + +template +std::vector generate_input(size_t count, size_t wg_size) +{ + std::vector input(count, CL_INT_TYPE(1)); + switch (op) + { + case work_group_op::add: + return input; + case work_group_op::min: + { + size_t j = wg_size; + for(size_t i = 0; i < count; i++) + { + input[i] = static_cast(j); + j--; + if(j == 0) + { + j = wg_size; + } + } + } + break; + case work_group_op::max: + { + size_t j = 0; + for(size_t i = 0; i < count; i++) + { + input[i] = static_cast(j); + j++; + if(j == wg_size) + { + j = 0; + } + } + } + } + return input; +} + +template +std::vector generate_output(size_t count, size_t wg_size) +{ + switch (op) + { + case work_group_op::add: + return std::vector(count, CL_INT_TYPE(0)); + case work_group_op::min: + return std::vector(count, (std::numeric_limits::max)()); + case work_group_op::max: + return std::vector(count, (std::numeric_limits::min)()); + } + return std::vector(count, CL_INT_TYPE(0)); +} + +#endif // TEST_CONFORMANCE_CLCPP_SG_COMMON_HPP diff --git a/test_conformance/clcpp/subgroups/main.cpp b/test_conformance/clcpp/subgroups/main.cpp new file mode 100644 index 00000000..3140a124 --- /dev/null +++ b/test_conformance/clcpp/subgroups/main.cpp @@ -0,0 +1,34 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "test_sg_all.hpp" +#include "test_sg_any.hpp" +#include "test_sg_broadcast.hpp" +#include "test_sg_reduce.hpp" +#include "test_sg_scan_inclusive.hpp" +#include "test_sg_scan_exclusive.hpp" + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/subgroups/test_sg_all.hpp b/test_conformance/clcpp/subgroups/test_sg_all.hpp new file mode 100644 index 00000000..01d66386 --- /dev/null +++ b/test_conformance/clcpp/subgroups/test_sg_all.hpp @@ -0,0 +1,219 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_ALL_HPP +#define TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_ALL_HPP + +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" +// Common for tests of sub-group functions +#include "common.hpp" + +std::string generate_sg_all_kernel_code() +{ + return "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_sg_all(global_ptr input, global_ptr output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + " bool result = sub_group_all(input[tid] < input[tid+1]);\n" + " if(!result) {\n output[tid] = 0;\n return;\n }\n" + " output[tid] = 1;\n" + "}\n"; +} + +int verify_sg_all(const std::vector &in, const std::vector &out, size_t count, size_t wg_size, size_t sg_size) +{ + size_t i, j, k; + for (i = 0; i < count; i += wg_size) + { + for (j = 0; j < ((count - i) > wg_size ? wg_size : (count - i)); j+= sg_size) + { + // sub-group all + bool all = true; + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + if(!(in[i+j+k] < in[i+j+k+1])) + { + all = false; + break; + } + } + + // Convert bool to uint + cl_uint all_uint = all ? 1 : 0; + // Check if all work-items in sub-group stored correct value + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + if (all_uint != out[i + j + k]) + { + log_info( + "sub_group_all %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(all_uint), + static_cast(out[i + j + k])); + return -1; + } + } + } + } + return CL_SUCCESS; +} + +std::vector generate_input_sg_all(size_t count, size_t wg_size) +{ + std::vector input(count, cl_uint(0)); + size_t j = wg_size; + for(size_t i = 0; i < count; i++) + { + input[i] = static_cast(i); + // In one place in ~half of work-groups (input[tid] < input[tid+1]) will + // generate false, it means that for sub_group_all(input[tid] < input[tid+1]) + // should return false for all sub-groups in that work-groups + if((j == wg_size/2) && (i > count/2)) + { + input[i] = input[i - 1]; + } + j--; + if(j == 0) + { + j = wg_size; + } + } + return input; +} + +std::vector generate_output_sg_all(size_t count, size_t wg_size) +{ + (void) wg_size; + return std::vector(count, cl_uint(1)); +} + +int sub_group_all(cl_device_id device, cl_context context, cl_command_queue queue, size_t count) +{ + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t wg_size; + size_t sg_max_size; + size_t work_size[1]; + int err; + + std::string code_str = generate_sg_all_kernel_code(); +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_sg_all"); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + log_info("SKIPPED: OpenCL C kernels not provided for this test. Skipping the test.\n"); + return CL_SUCCESS; +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_sg_all"); + RETURN_ON_ERROR(err) +#endif + + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &wg_size, NULL); + RETURN_ON_CL_ERROR(err, "clGetKernelWorkGroupInfo") + + size_t param_value_size = 0; + err = clGetKernelSubGroupInfo( + kernel, device, CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE, + sizeof(size_t), static_cast(&wg_size), + sizeof(size_t), static_cast(&sg_max_size), + ¶m_value_size + ); + RETURN_ON_CL_ERROR(err, "clGetKernelSubGroupInfo") + + // Verify size of returned param + if(param_value_size != sizeof(size_t)) + { + RETURN_ON_ERROR_MSG(-1, + "Returned size of max sub group size not valid! (Expected %lu, got %lu)\n", + sizeof(size_t), + param_value_size + ) + } + + // Calculate global work size + size_t flat_work_size; + size_t wg_number = static_cast( + std::ceil(static_cast(count) / wg_size) + ); + flat_work_size = wg_number * wg_size; + work_size[0] = flat_work_size; + + std::vector input = generate_input_sg_all(flat_work_size + 1, wg_size); + std::vector output = generate_output_sg_all(flat_work_size, wg_size); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * input.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + buffers[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(cl_uint) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, &wg_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + if (verify_sg_all(input, output, flat_work_size, wg_size, sg_max_size) != CL_SUCCESS) + { + RETURN_ON_ERROR_MSG(-1, "sub_group_all failed"); + } + log_info("sub_group_all passed\n"); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +AUTO_TEST_CASE(test_sub_group_all) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int err = CL_SUCCESS; + err = sub_group_all(device, context, queue, n_elems); + CHECK_ERROR(err) + return err; +} + +#endif // TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_ALL_HPP diff --git a/test_conformance/clcpp/subgroups/test_sg_any.hpp b/test_conformance/clcpp/subgroups/test_sg_any.hpp new file mode 100644 index 00000000..769bef06 --- /dev/null +++ b/test_conformance/clcpp/subgroups/test_sg_any.hpp @@ -0,0 +1,219 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_ANY_HPP +#define TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_ANY_HPP + +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" +// Common for tests of sub-group functions +#include "common.hpp" + +std::string generate_sg_any_kernel_code() +{ + return "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_sg_any(global_ptr input, global_ptr output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + " bool result = sub_group_any(input[tid] == input[tid+1]);\n" + " if(!result) {\n output[tid] = 0;\n return;\n }\n" + " output[tid] = 1;\n" + "}\n"; +} + +int verify_sg_any(const std::vector &in, const std::vector &out, size_t count, size_t wg_size, size_t sg_size) +{ + size_t i, j, k; + for (i = 0; i < count; i += wg_size) + { + for (j = 0; j < ((count - i) > wg_size ? wg_size : (count - i)); j+= sg_size) + { + // sub-group any + bool any = false; + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + if(in[i+j+k] == in[i+j+k+1]) + { + any = true; + break; + } + } + + // Convert bool to uint + cl_uint any_uint = any ? 1 : 0; + // Check if all work-items in sub-group stored correct value + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + if (any_uint != out[i + j + k]) + { + log_info( + "sub_group_any %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(any_uint), + static_cast(out[i + j + k])); + return -1; + } + } + } + } + return CL_SUCCESS; +} + +std::vector generate_input_sg_any(size_t count, size_t wg_size) +{ + std::vector input(count, cl_uint(0)); + size_t j = wg_size; + for(size_t i = 0; i < count; i++) + { + input[i] = static_cast(i); + // In one place in ~half of work-groups (input[tid] == input[tid+1]) will + // generate true, it means that for sub_group_all(input[tid] == input[tid+1]) + // should return false for one sub-group in that work-groups + if((j == wg_size/2) && (i > count/2)) + { + input[i] = input[i - 1]; + } + j--; + if(j == 0) + { + j = wg_size; + } + } + return input; +} + +std::vector generate_output_sg_any(size_t count, size_t wg_size) +{ + (void) wg_size; + return std::vector(count, cl_uint(1)); +} + +int sub_group_any(cl_device_id device, cl_context context, cl_command_queue queue, size_t count) +{ + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t wg_size; + size_t sg_max_size; + size_t work_size[1]; + int err; + + std::string code_str = generate_sg_any_kernel_code(); +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_sg_any"); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + log_info("SKIPPED: OpenCL C kernels not provided for this test. Skipping the test.\n"); + return CL_SUCCESS; +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_sg_any"); + RETURN_ON_ERROR(err) +#endif + + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &wg_size, NULL); + RETURN_ON_CL_ERROR(err, "clGetKernelWorkGroupInfo") + + size_t param_value_size = 0; + err = clGetKernelSubGroupInfo( + kernel, device, CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE, + sizeof(size_t), static_cast(&wg_size), + sizeof(size_t), static_cast(&sg_max_size), + ¶m_value_size + ); + RETURN_ON_CL_ERROR(err, "clGetKernelSubGroupInfo") + + // Verify size of returned param + if(param_value_size != sizeof(size_t)) + { + RETURN_ON_ERROR_MSG(-1, + "Returned size of max sub group size not valid! (Expected %lu, got %lu)\n", + sizeof(size_t), + param_value_size + ) + } + + // Calculate global work size + size_t flat_work_size; + size_t wg_number = static_cast( + std::ceil(static_cast(count) / wg_size) + ); + flat_work_size = wg_number * wg_size; + work_size[0] = flat_work_size; + + std::vector input = generate_input_sg_any(flat_work_size + 1, wg_size); + std::vector output = generate_output_sg_any(flat_work_size, wg_size); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * input.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + buffers[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(cl_uint) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, &wg_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + if (verify_sg_any(input, output, flat_work_size, wg_size, sg_max_size) != CL_SUCCESS) + { + RETURN_ON_ERROR_MSG(-1, "sub_group_any failed"); + } + log_info("sub_group_any passed\n"); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +AUTO_TEST_CASE(test_sub_group_any) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int err = CL_SUCCESS; + err = sub_group_any(device, context, queue, n_elems); + CHECK_ERROR(err) + return err; +} + +#endif // TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_ANY_HPP diff --git a/test_conformance/clcpp/subgroups/test_sg_broadcast.hpp b/test_conformance/clcpp/subgroups/test_sg_broadcast.hpp new file mode 100644 index 00000000..39e420ac --- /dev/null +++ b/test_conformance/clcpp/subgroups/test_sg_broadcast.hpp @@ -0,0 +1,204 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_BROADCAST_HPP +#define TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_BROADCAST_HPP + +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" +// Common for tests of sub-group functions +#include "common.hpp" + +std::string generate_sg_broadcast_kernel_code() +{ + return + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_sg_broadcast(global_ptr input, global_ptr output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + " uint result = sub_group_broadcast(input[tid], 0);\n" + " output[tid] = result;\n" + "}\n"; +} + +int +verify_sg_broadcast(const std::vector &in, const std::vector &out, size_t count, size_t wg_size, size_t sg_size) +{ + size_t i, j, k; + for (i = 0; i < count; i += wg_size) + { + for (j = 0; j < ((count - i) > wg_size ? wg_size : (count - i)); j+= sg_size) + { + // sub-group broadcast + cl_uint broadcast_result = in[i+j]; + + // Check if all work-items in sub-group stored correct value + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + if (broadcast_result != out[i + j + k]) + { + log_info( + "sub_group_any %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(broadcast_result), + static_cast(out[i + j + k])); + return -1; + } + } + } + } + return CL_SUCCESS; +} + +std::vector generate_input_sg_broadcast(size_t count, size_t wg_size) +{ + std::vector input(count, cl_uint(0)); + size_t j = wg_size; + for(size_t i = 0; i < count; i++) + { + input[i] = static_cast(j); + j--; + if(j == 0) + { + j = wg_size; + } + } + return input; +} + +std::vector generate_output_sg_broadcast(size_t count, size_t wg_size) +{ + (void) wg_size; + return std::vector(count, cl_uint(1)); +} + +int sub_group_broadcast(cl_device_id device, cl_context context, cl_command_queue queue, size_t count) +{ + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t wg_size; + size_t sg_max_size; + size_t work_size[] = { 1 }; + int err; + + // Get kernel source code + std::string code_str = generate_sg_broadcast_kernel_code(); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_sg_broadcast"); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + log_info("SKIPPED: OpenCL C kernels not provided for this test. Skipping the test.\n"); + return CL_SUCCESS; +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_sg_broadcast"); + RETURN_ON_ERROR(err) +#endif + + // Get max flat workgroup size + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &wg_size, NULL); + RETURN_ON_CL_ERROR(err, "clGetKernelWorkGroupInfo") + + size_t param_value_size = 0; + err = clGetKernelSubGroupInfo( + kernel, device, CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE, + sizeof(size_t), static_cast(&wg_size), + sizeof(size_t), static_cast(&sg_max_size), + ¶m_value_size + ); + RETURN_ON_CL_ERROR(err, "clGetKernelSubGroupInfo") + + // Verify size of returned param + if(param_value_size != sizeof(size_t)) + { + RETURN_ON_ERROR_MSG(-1, + "Returned size of max sub group size not valid! (Expected %lu, got %lu)\n", + sizeof(size_t), + param_value_size + ) + } + + // Calculate global work size + size_t flat_work_size = count; + size_t wg_number = static_cast( + std::ceil(static_cast(count) / wg_size) + ); + flat_work_size = wg_number * wg_size; + work_size[0] = flat_work_size; + + std::vector input = generate_input_sg_broadcast(flat_work_size, wg_size); + std::vector output = generate_output_sg_broadcast(flat_work_size, wg_size); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * input.size(), NULL,&err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + buffers[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(cl_uint) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, &wg_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + int result = verify_sg_broadcast( input, output, work_size[0], wg_size, sg_max_size); + RETURN_ON_ERROR_MSG(result, "sub_group_broadcast failed") + log_info("sub_group_broadcast passed\n"); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +AUTO_TEST_CASE(test_sub_group_broadcast) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int err = CL_SUCCESS; + err = sub_group_broadcast(device, context, queue, n_elems); + CHECK_ERROR(err) + return err; +} + +#endif // TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_BROADCAST_HPP diff --git a/test_conformance/clcpp/subgroups/test_sg_reduce.hpp b/test_conformance/clcpp/subgroups/test_sg_reduce.hpp new file mode 100644 index 00000000..6b20d507 --- /dev/null +++ b/test_conformance/clcpp/subgroups/test_sg_reduce.hpp @@ -0,0 +1,345 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_REDUCE_HPP +#define TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_REDUCE_HPP + +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" +// Common for tests of sub-group functions +#include "common.hpp" + +template +std::string generate_sg_reduce_kernel_code() +{ + return "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_sg_reduce(global_ptr<" + type_name() + "[]> input, " + "global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + " " + type_name() + " result = sub_group_reduce(input[tid]);\n" + " output[tid] = result;\n" + "}\n"; +} + +template +int verify_sg_reduce_add(const std::vector &in, const std::vector &out, size_t wg_size, size_t sg_size) +{ + size_t i, j, k; + for (i = 0; i < in.size(); i += wg_size) + { + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j+= sg_size) + { + CL_INT_TYPE sum = 0; + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + sum += in[i + j + k]; + } + + // Check if all work-items in sub-group stored correct value + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + if (sum != out[i + j + k]) + { + log_info( + "sub_group_reduce_add %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(sum), + static_cast(out[i + j + k])); + return -1; + } + } + } + } + return CL_SUCCESS; +} + +template +int verify_sg_reduce_min(const std::vector &in, const std::vector &out, size_t wg_size, size_t sg_size) +{ + size_t i, j, k; + for (i = 0; i < in.size(); i += wg_size) + { + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j+= sg_size) + { + CL_INT_TYPE min = (std::numeric_limits::max)(); + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + min = std::min(min, in[i + j + k]); + } + + // Check if all work-items in sub-group stored correct value + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + if (min != out[i + j + k]) + { + log_info( + "sub_group_reduce_min %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(min), + static_cast(out[i + j + k])); + return -1; + } + } + } + } + return CL_SUCCESS; +} + +template +int verify_sg_reduce_max(const std::vector &in, const std::vector &out, size_t wg_size, size_t sg_size) +{ + size_t i, j, k; + for (i = 0; i < in.size(); i += wg_size) + { + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j+= sg_size) + { + CL_INT_TYPE max = (std::numeric_limits::min)(); + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + max = std::max(max, in[i + j + k]); + } + + // Check if all work-items in sub-group stored correct value + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + if (max != out[i + j + k]) + { + log_info( + "sub_group_reduce_max %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(max), + static_cast(out[i + j + k])); + return -1; + } + } + } + } + return CL_SUCCESS; +} + +template +int verify_sg_reduce(const std::vector &in, const std::vector &out, size_t wg_size, size_t sg_size) +{ + switch (op) + { + case work_group_op::add: + return verify_sg_reduce_add(in, out, wg_size, sg_size); + case work_group_op::min: + return verify_sg_reduce_min(in, out, wg_size, sg_size); + case work_group_op::max: + return verify_sg_reduce_max(in, out, wg_size, sg_size); + } + return -1; +} + +template +int sub_group_reduce(cl_device_id device, cl_context context, cl_command_queue queue, size_t count) +{ + // don't run test for unsupported types + if(!type_supported(device)) + { + return CL_SUCCESS; + } + + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t wg_size; + size_t sg_max_size; + size_t work_size[1]; + int err; + + std::string code_str = generate_sg_reduce_kernel_code(); +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_sg_reduce"); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + log_info("SKIPPED: OpenCL C kernels not provided for this test. Skipping the test.\n"); + return CL_SUCCESS; +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_sg_reduce"); + RETURN_ON_ERROR(err) +#endif + + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &wg_size, NULL); + RETURN_ON_CL_ERROR(err, "clGetKernelWorkGroupInfo") + + size_t param_value_size = 0; + err = clGetKernelSubGroupInfo( + kernel, device, CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE, + sizeof(size_t), static_cast(&wg_size), + sizeof(size_t), static_cast(&sg_max_size), + ¶m_value_size + ); + RETURN_ON_CL_ERROR(err, "clGetKernelSubGroupInfo") + + // Verify size of returned param + if(param_value_size != sizeof(size_t)) + { + RETURN_ON_ERROR_MSG(-1, + "Returned size of max sub group size not valid! (Expected %lu, got %lu)\n", + sizeof(size_t), + param_value_size + ) + } + + // Calculate global work size + size_t flat_work_size; + size_t wg_number = static_cast( + std::ceil(static_cast(count) / wg_size) + ); + flat_work_size = wg_number * wg_size; + work_size[0] = flat_work_size; + + std::vector input = generate_input(flat_work_size, wg_size); + std::vector output = generate_output(flat_work_size, wg_size); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(CL_INT_TYPE) * input.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + buffers[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(CL_INT_TYPE) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(CL_INT_TYPE) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, &wg_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(CL_INT_TYPE) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + if (verify_sg_reduce(input, output, wg_size, sg_max_size) != CL_SUCCESS) + { + RETURN_ON_ERROR_MSG(-1, "sub_group_reduce_%s %s failed", to_string(op).c_str(), type_name().c_str()); + } + log_info("sub_group_reduce_%s %s passed\n", to_string(op).c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +AUTO_TEST_CASE(test_sub_group_reduce_add) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = sub_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +AUTO_TEST_CASE(test_sub_group_reduce_min) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = sub_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +AUTO_TEST_CASE(test_sub_group_reduce_max) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = sub_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +#endif // TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_REDUCE_HPP diff --git a/test_conformance/clcpp/subgroups/test_sg_scan_exclusive.hpp b/test_conformance/clcpp/subgroups/test_sg_scan_exclusive.hpp new file mode 100644 index 00000000..7bb2b18b --- /dev/null +++ b/test_conformance/clcpp/subgroups/test_sg_scan_exclusive.hpp @@ -0,0 +1,325 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_SCAN_EXCLUSIVE_HPP +#define TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_SCAN_EXCLUSIVE_HPP + +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" +// Common for tests of sub-group functions +#include "common.hpp" + +template +std::string generate_sg_scan_exclusive_kernel_code() +{ + return "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_sg_scan_exclusive(global_ptr<" + type_name() + "[]> input, " + "global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + " " + type_name() + " result = sub_group_scan_exclusive(input[tid]);\n" + " output[tid] = result;\n" + "}\n"; +} + +template +int verify_sg_scan_exclusive_add(const std::vector &in, const std::vector &out, size_t wg_size, size_t sg_size) +{ + size_t i, j, k; + for (i = 0; i < in.size(); i += wg_size) + { + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j+= sg_size) + { + CL_INT_TYPE sum = 0; + // Check if all work-items in sub-group stored correct value + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + if (sum != out[i + j + k]) + { + log_info( + "sub_group_scan_exclusive_add %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(sum), + static_cast(out[i + j + k])); + return -1; + } + sum += in[i + j + k]; + } + } + } + return CL_SUCCESS; +} + +template +int verify_sg_scan_exclusive_min(const std::vector &in, const std::vector &out, size_t wg_size, size_t sg_size) +{ + size_t i, j, k; + for (i = 0; i < in.size(); i += wg_size) + { + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j+= sg_size) + { + CL_INT_TYPE min = (std::numeric_limits::max)(); + // Check if all work-items in sub-group stored correct value + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + if (min != out[i + j + k]) + { + log_info( + "sub_group_scan_exclusive_min %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(min), + static_cast(out[i + j + k])); + return -1; + } + min = std::min(min, in[i + j + k]); + } + } + } + return CL_SUCCESS; +} + +template +int verify_sg_scan_exclusive_max(const std::vector &in, const std::vector &out, size_t wg_size, size_t sg_size) +{ + size_t i, j, k; + for (i = 0; i < in.size(); i += wg_size) + { + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j+= sg_size) + { + CL_INT_TYPE max = (std::numeric_limits::min)(); + // Check if all work-items in sub-group stored correct value + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + if (max != out[i + j + k]) + { + log_info( + "sub_group_scan_exclusive_max %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(max), + static_cast(out[i + j + k])); + return -1; + } + max = std::max(max, in[i + j + k]); + } + } + } + return CL_SUCCESS; +} + +template +int verify_sg_scan_exclusive(const std::vector &in, const std::vector &out, size_t wg_size, size_t sg_size) +{ + switch (op) + { + case work_group_op::add: + return verify_sg_scan_exclusive_add(in, out, wg_size, sg_size); + case work_group_op::min: + return verify_sg_scan_exclusive_min(in, out, wg_size, sg_size); + case work_group_op::max: + return verify_sg_scan_exclusive_max(in, out, wg_size, sg_size); + } + return -1; +} + +template +int sub_group_scan_exclusive(cl_device_id device, cl_context context, cl_command_queue queue, size_t count) +{ + // don't run test for unsupported types + if(!type_supported(device)) + { + return CL_SUCCESS; + } + + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t wg_size; + size_t sg_max_size; + size_t work_size[1]; + int err; + + std::string code_str = generate_sg_scan_exclusive_kernel_code(); +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_sg_scan_exclusive"); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + log_info("SKIPPED: OpenCL C kernels not provided for this test. Skipping the test.\n"); + return CL_SUCCESS; +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_sg_scan_exclusive"); + RETURN_ON_ERROR(err) +#endif + + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &wg_size, NULL); + RETURN_ON_CL_ERROR(err, "clGetKernelWorkGroupInfo") + + size_t param_value_size = 0; + err = clGetKernelSubGroupInfo( + kernel, device, CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE, + sizeof(size_t), static_cast(&wg_size), + sizeof(size_t), static_cast(&sg_max_size), + ¶m_value_size + ); + RETURN_ON_CL_ERROR(err, "clGetKernelSubGroupInfo") + + // Verify size of returned param + if(param_value_size != sizeof(size_t)) + { + RETURN_ON_ERROR_MSG(-1, + "Returned size of max sub group size not valid! (Expected %lu, got %lu)\n", + sizeof(size_t), + param_value_size + ) + } + + // Calculate global work size + size_t flat_work_size; + size_t wg_number = static_cast( + std::ceil(static_cast(count) / wg_size) + ); + flat_work_size = wg_number * wg_size; + work_size[0] = flat_work_size; + + std::vector input = generate_input(flat_work_size, wg_size); + std::vector output = generate_output(flat_work_size, wg_size); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(CL_INT_TYPE) * input.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + buffers[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(CL_INT_TYPE) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(CL_INT_TYPE) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, &wg_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(CL_INT_TYPE) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + if (verify_sg_scan_exclusive(input, output, wg_size, sg_max_size) != CL_SUCCESS) + { + RETURN_ON_ERROR_MSG(-1, "sub_group_scan_exclusive_%s %s failed", to_string(op).c_str(), type_name().c_str()); + } + log_info("sub_group_scan_exclusive_%s %s passed\n", to_string(op).c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +AUTO_TEST_CASE(test_sub_group_scan_exclusive_add) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = sub_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +AUTO_TEST_CASE(test_sub_group_scan_exclusive_min) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = sub_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + local_error = sub_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + local_error = sub_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + local_error = sub_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +AUTO_TEST_CASE(test_sub_group_scan_exclusive_max) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = sub_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +#endif // TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_SCAN_EXCLUSIVE_HPP diff --git a/test_conformance/clcpp/subgroups/test_sg_scan_inclusive.hpp b/test_conformance/clcpp/subgroups/test_sg_scan_inclusive.hpp new file mode 100644 index 00000000..803daa00 --- /dev/null +++ b/test_conformance/clcpp/subgroups/test_sg_scan_inclusive.hpp @@ -0,0 +1,332 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_SCAN_INCLUSIVE_HPP +#define TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_SCAN_INCLUSIVE_HPP + +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" +// Common for tests of sub-group functions +#include "common.hpp" + +template +std::string generate_sg_scan_inclusive_kernel_code() +{ + return "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_sg_scan_inclusive(global_ptr<" + type_name() + "[]> input, " + "global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + " " + type_name() + " result = sub_group_scan_inclusive(input[tid]);\n" + " output[tid] = result;\n" + "}\n"; +} + +template +int verify_sg_scan_inclusive_add(const std::vector &in, const std::vector &out, size_t wg_size, size_t sg_size) +{ + size_t i, j, k; + for (i = 0; i < in.size(); i += wg_size) + { + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j+= sg_size) + { + CL_INT_TYPE sum = 0; + // Check if all work-items in sub-group stored correct value + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + sum += in[i + j + k]; + if (sum != out[i + j + k]) + { + log_info( + "sub_group_scan_exclusive_add %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(sum), + static_cast(out[i + j + k])); + return -1; + } + } + } + } + return CL_SUCCESS; +} + +template +int verify_sg_scan_inclusive_min(const std::vector &in, const std::vector &out, size_t wg_size, size_t sg_size) +{ + size_t i, j, k; + for (i = 0; i < in.size(); i += wg_size) + { + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j+= sg_size) + { + CL_INT_TYPE min = (std::numeric_limits::max)(); + // Check if all work-items in sub-group stored correct value + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + min = std::min(min, in[i + j + k]); + if (min != out[i + j + k]) + { + log_info( + "sub_group_scan_exclusive_min %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(min), + static_cast(out[i + j + k])); + return -1; + } + } + } + } + return CL_SUCCESS; +} + +template +int verify_sg_scan_inclusive_max(const std::vector &in, const std::vector &out, size_t wg_size, size_t sg_size) +{ + size_t i, j, k; + for (i = 0; i < in.size(); i += wg_size) + { + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j+= sg_size) + { + CL_INT_TYPE max = (std::numeric_limits::min)(); + // Check if all work-items in sub-group stored correct value + for (k = 0; k < ((wg_size - j) > sg_size ? sg_size : (wg_size - j)); k++) + { + max = std::max(max, in[i + j + k]); + if (max != out[i + j + k]) + { + log_info( + "sub_group_scan_exclusive_max %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(max), + static_cast(out[i + j + k])); + return -1; + } + } + } + } + return CL_SUCCESS; +} + +template +int verify_sg_scan_inclusive(const std::vector &in, const std::vector &out, size_t wg_size, size_t sg_size) +{ + switch (op) + { + case work_group_op::add: + return verify_sg_scan_inclusive_add(in, out, wg_size, sg_size); + case work_group_op::min: + return verify_sg_scan_inclusive_min(in, out, wg_size, sg_size); + case work_group_op::max: + return verify_sg_scan_inclusive_max(in, out, wg_size, sg_size); + } + return -1; +} + +template +int sub_group_scan_inclusive(cl_device_id device, cl_context context, cl_command_queue queue, size_t count) +{ + // don't run test for unsupported types + if(!type_supported(device)) + { + return CL_SUCCESS; + } + + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t wg_size; + size_t sg_max_size; + size_t work_size[1]; + int err; + + std::string code_str = generate_sg_scan_inclusive_kernel_code(); +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_sg_scan_inclusive"); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + log_info("SKIPPED: OpenCL C kernels not provided for this test. Skipping the test.\n"); + return CL_SUCCESS; +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_sg_scan_inclusive"); + RETURN_ON_ERROR(err) +#endif + + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &wg_size, NULL); + RETURN_ON_CL_ERROR(err, "clGetKernelWorkGroupInfo") + + size_t param_value_size = 0; + err = clGetKernelSubGroupInfo( + kernel, device, CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE, + sizeof(size_t), static_cast(&wg_size), + sizeof(size_t), static_cast(&sg_max_size), + ¶m_value_size + ); + RETURN_ON_CL_ERROR(err, "clGetKernelSubGroupInfo") + + // Verify size of returned param + if(param_value_size != sizeof(size_t)) + { + RETURN_ON_ERROR_MSG(-1, + "Returned size of max sub group size not valid! (Expected %lu, got %lu)\n", + sizeof(size_t), + param_value_size + ) + } + + // Calculate global work size + size_t flat_work_size; + size_t wg_number = static_cast( + std::ceil(static_cast(count) / wg_size) + ); + flat_work_size = wg_number * wg_size; + work_size[0] = flat_work_size; + + std::vector input = generate_input(flat_work_size, wg_size); + std::vector output = generate_output(flat_work_size, wg_size); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(CL_INT_TYPE) * input.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + buffers[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(CL_INT_TYPE) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(CL_INT_TYPE) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, &wg_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(CL_INT_TYPE) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + if (verify_sg_scan_inclusive(input, output, wg_size, sg_max_size) != CL_SUCCESS) + { + RETURN_ON_ERROR_MSG(-1, "sub_group_scan_inclusive_%s %s failed", to_string(op).c_str(), type_name().c_str()); + } + log_info("sub_group_scan_inclusive_%s %s passed\n", to_string(op).c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +AUTO_TEST_CASE(test_sub_group_scan_inclusive_add) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = sub_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +AUTO_TEST_CASE(test_sub_group_scan_inclusive_min) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = sub_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +AUTO_TEST_CASE(test_sub_group_scan_inclusive_max) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = sub_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = sub_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +#endif // TEST_CONFORMANCE_CLCPP_SUBGROUPS_TEST_SG_SCAN_INCLUSIVE_HPP diff --git a/test_conformance/clcpp/synchronization/CMakeLists.txt b/test_conformance/clcpp/synchronization/CMakeLists.txt new file mode 100644 index 00000000..793b7bd1 --- /dev/null +++ b/test_conformance/clcpp/synchronization/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_SYNCHRONIZATION) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/synchronization/main.cpp b/test_conformance/clcpp/synchronization/main.cpp new file mode 100644 index 00000000..e2a72b07 --- /dev/null +++ b/test_conformance/clcpp/synchronization/main.cpp @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "test_work_group_barrier.hpp" +#include "test_sub_group_barrier.hpp" +#include "named_barrier/test_spec_example.hpp" +#include "named_barrier/test_named_barrier.hpp" + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/synchronization/named_barrier/common.hpp b/test_conformance/clcpp/synchronization/named_barrier/common.hpp new file mode 100644 index 00000000..da34dceb --- /dev/null +++ b/test_conformance/clcpp/synchronization/named_barrier/common.hpp @@ -0,0 +1,171 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SYNCHRONIZATION_NAMED_BARRIER_COMMON_HPP +#define TEST_CONFORMANCE_CLCPP_SYNCHRONIZATION_NAMED_BARRIER_COMMON_HPP + +#include + +// Common for all OpenCL C++ tests +#include "../../common.hpp" +#include "../../funcs_test_utils.hpp" + +#define RUN_WG_NAMED_BARRIER_TEST_MACRO(TEST_CLASS) \ + last_error = run_work_group_named_barrier_barrier_test( \ + device, context, queue, num_elements, TEST_CLASS \ + ); \ + CHECK_ERROR(last_error) \ + error |= last_error; + +namespace named_barrier { + +struct work_group_named_barrier_test_base : public detail::base_func_type +{ + // Returns test name + virtual std::string str() = 0; + // Returns OpenCL program source + // It's assumed that this program has only one kernel. + virtual std::string generate_program() = 0; + // Return value that is expected to be in output_buffer[i] + virtual cl_uint operator()(size_t i, size_t work_group_size, size_t mas_sub_group_size) = 0; + // Kernel execution + // This covers typical case: kernel is executed once, kernel + // has only one argument which is output buffer + virtual cl_int execute(const cl_kernel kernel, + const cl_mem output_buffer, + const cl_command_queue& queue, + const size_t work_size, + const size_t work_group_size) + { + cl_int err; + err = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(err, "clSetKernelArg") + + err = clEnqueueNDRangeKernel( + queue, kernel, 1, + NULL, &work_size, &work_group_size, + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel") + return err; + } + // Calculates maximal work-group size (one dim) + virtual size_t get_max_local_size(const cl_kernel kernel, + const cl_device_id device, + const size_t work_group_size, // default work-group size + cl_int& error) + { + size_t max_wg_size; + error = clGetKernelWorkGroupInfo( + kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &max_wg_size, NULL + ); + RETURN_ON_ERROR(error) + return (std::min)(work_group_size, max_wg_size); + } + // if work-groups should be uniform + virtual bool enforce_uniform() + { + return false; + } +}; + +template +int run_work_group_named_barrier_barrier_test(cl_device_id device, cl_context context, cl_command_queue queue, + size_t count, work_group_named_barrier_test test) +{ + cl_mem buffers[1]; + cl_program program; + cl_kernel kernel; + size_t work_group_size; + size_t work_size[1]; + cl_int err; + + std::string code_str = test.generate_program(); + std::string kernel_name = test.get_kernel_name(); +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name, "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(err) +#endif + + // Find the max possible wg size for among all the kernels + work_group_size = test.get_max_local_size(kernel, device, 256, err); + RETURN_ON_ERROR(err); + if(work_group_size == 0) + { + log_info("SKIPPED: Can't produce local size with enough sub-groups. Skipping tests.\n"); + return CL_SUCCESS; + } + + work_size[0] = count; + // uniform work-group + if(test.enforce_uniform()) + { + size_t wg_number = static_cast( + std::ceil(static_cast(work_size[0]) / work_group_size) + ); + work_size[0] = wg_number * work_group_size; + } + + // host output vector + std::vector output = generate_output(work_size[0], 9999); + + // device output buffer + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + // Execute test kernels + err = test.execute(kernel, buffers[0], queue, work_size[0], work_group_size); + RETURN_ON_ERROR(err) + + err = clEnqueueReadBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer") + + // Check output values + for(size_t i = 0; i < output.size(); i++) + { + cl_uint v = test(i, work_group_size, i); + if(!(are_equal(v, output[i], ::detail::make_value(0), test))) + { + RETURN_ON_ERROR_MSG(-1, + "test_%s(%s) failed. Expected: %s, got: %s", test.str().c_str(), type_name().c_str(), + format_value(v).c_str(), format_value(output[i]).c_str() + ); + } + } + log_info("test_%s(%s) passed\n", test.str().c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +} // namespace named_barrier + +#endif // TEST_CONFORMANCE_CLCPP_SYNCHRONIZATION_NAMED_BARRIER_COMMON_HPP diff --git a/test_conformance/clcpp/synchronization/named_barrier/test_named_barrier.hpp b/test_conformance/clcpp/synchronization/named_barrier/test_named_barrier.hpp new file mode 100644 index 00000000..a4f9a04a --- /dev/null +++ b/test_conformance/clcpp/synchronization/named_barrier/test_named_barrier.hpp @@ -0,0 +1,490 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SYNCHRONIZATION_NAMED_BARRIER_TEST_NAMED_BARRIER_HPP +#define TEST_CONFORMANCE_CLCPP_SYNCHRONIZATION_NAMED_BARRIER_TEST_NAMED_BARRIER_HPP + +#include "common.hpp" + +namespace named_barrier { + +struct local_fence_named_barrier_test : public work_group_named_barrier_test_base +{ + std::string str() + { + return "local_fence"; + } + + // Return value that is expected to be in output_buffer[i] + cl_uint operator()(size_t i, size_t work_group_size, size_t max_sub_group_size) + { + return static_cast(i); + } + + // At the end every work-item writes its global id to ouput[work-item-global-id]. + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return + "__kernel void " + this->get_kernel_name() + "(global uint *output, " + "local uint * lmem)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = gid;\n" + "}\n"; + + #else + return + "#define cl_khr_subgroup_named_barrier\n" + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void " + this->get_kernel_name() + "(global_ptr output, " + "local_ptr lmem)\n" + "{\n\n" + " local a(1);\n" + " local b(2);\n" + " size_t gid = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " size_t value;\n" + " if(get_num_sub_groups() == 1)\n" + " {\n" + " size_t other_lid = (lid + 1) % get_enqueued_local_size(0);\n" + " size_t other_gid = (gid - lid) + other_lid;\n" + " lmem[other_lid] = other_gid;\n" + " a.wait(mem_fence::local);\n" + " value = lmem[lid];" // lmem[lid] shoule be equal to gid + " }\n" + " else if(get_num_sub_groups() == 2)\n" + " {\n" + " size_t other_lid = (lid + get_max_sub_group_size()) % get_enqueued_local_size(0);\n" + " size_t other_gid = (gid - lid) + other_lid;\n" + " lmem[other_lid] = other_gid;\n" + " b.wait(mem_fence::local);\n" + " value = lmem[lid];" // lmem[lid] shoule be equal to gid + " }\n" + " else if(get_num_sub_groups() > 2)\n" + " {\n" + " if(get_sub_group_id() < 2)\n" + " {\n" + " const size_t two_first_subgroups = 2 * get_max_sub_group_size();" + // local and global id of some work-item outside of work-item subgroup, + // but within subgroups 0 and 1. + " size_t other_lid = (lid + get_max_sub_group_size()) % two_first_subgroups;\n" + " size_t other_gid = (gid - lid) + other_lid;\n" + " lmem[other_lid] = other_gid;\n" + " b.wait(mem_fence::local);\n" // subgroup 0 and 1 are sync (local) + " value = lmem[lid];" // lmem[lid] shoule be equal to gid + " }\n" + " else\n" + " {\n" + " value = gid;\n" + " }\n" + " }\n" + " output[gid] = value;\n" + "}\n"; + #endif + } + + size_t get_max_local_size(const cl_kernel kernel, + const cl_device_id device, + const size_t work_group_size, // default work-group size + cl_int& error) + { + // Set size of the local memory, we need to to this to correctly calculate + // max possible work-group size. + size_t wg_size; + for(wg_size = work_group_size; wg_size > 1; wg_size /= 2) + { + error = clSetKernelArg(kernel, 1, wg_size * sizeof(cl_uint), NULL); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + size_t max_wg_size; + error = clGetKernelWorkGroupInfo( + kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &max_wg_size, NULL + ); + RETURN_ON_CL_ERROR(error, "clGetKernelWorkGroupInfo") + if(max_wg_size >= wg_size) break; + } + return wg_size; + } + + cl_int execute(const cl_kernel kernel, + const cl_mem output_buffer, + const cl_command_queue queue, + const size_t work_size, + const size_t work_group_size) + { + cl_int err; + // Get context from queue + cl_context context; + err = clGetCommandQueueInfo(queue, CL_QUEUE_CONTEXT, sizeof(cl_context), &context, NULL); + RETURN_ON_CL_ERROR(err, "clGetCommandQueueInfo") + + err = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer); + err |= clSetKernelArg(kernel, 1, work_group_size * sizeof(cl_uint), NULL); + RETURN_ON_CL_ERROR(err, "clSetKernelArg") + + err = clEnqueueNDRangeKernel( + queue, kernel, 1, + NULL, &work_size, &work_group_size, + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel") + + err = clFinish(queue); + return err; + } +}; + +struct global_fence_named_barrier_test : public work_group_named_barrier_test_base +{ + std::string str() + { + return "global_fence"; + } + + // Return value that is expected to be in output_buffer[i] + cl_uint operator()(size_t i, size_t work_group_size, size_t max_sub_group_size) + { + return static_cast(i % work_group_size); + } + + // At the end every work-item writes its local id to ouput[work-item-global-id]. + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return + "__kernel void " + this->get_kernel_name() + "(global uint * output, " + "global uint * temp)\n" + "{\n" + "size_t gid = get_global_id(0);\n" + "output[gid] = get_local_id(0);\n" + "}\n"; + + #else + return + "#define cl_khr_subgroup_named_barrier\n" + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void " + this->get_kernel_name() + "(global_ptr output, " + "global_ptr temp)\n" + "{\n\n" + " local a(1);\n" + " local b(2);\n" + " size_t gid = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " size_t value;\n" + " if(get_num_sub_groups() == 1)\n" + " {\n" + " size_t other_lid = (lid + 1) % get_enqueued_local_size(0);\n" + " size_t other_gid = (gid - lid) + other_lid;\n" + " temp[other_gid] = other_lid + 1;\n" + " a.wait(mem_fence::global);\n" + " size_t other_lid_same_subgroup = (lid + 2) % get_sub_group_size();\n" + " size_t other_gid_same_subgroup = (gid - lid) + other_lid_same_subgroup;\n" + " temp[other_gid_same_subgroup] = temp[other_gid_same_subgroup] - 1;\n" + " a.wait(mem_fence::global, memory_scope_sub_group);\n" + " value = temp[gid];" // temp[gid] shoule be equal to lid + " }\n" + " else if(get_num_sub_groups() == 2)\n" + " {\n" + " size_t other_lid = (lid + get_max_sub_group_size()) % get_enqueued_local_size(0);\n" + " size_t other_gid = (gid - lid) + other_lid;\n" + " temp[other_gid] = other_lid + 1;\n" + " b.wait(mem_fence::global);\n" // both subgroups wait, both are sync + " size_t other_lid_same_subgroup = " + "((lid + 1) % get_sub_group_size()) + (get_sub_group_id() * get_sub_group_size());\n" + " size_t other_gid_same_subgroup = (gid - lid) + other_lid_same_subgroup;\n" + " temp[other_gid_same_subgroup] = temp[other_gid_same_subgroup] - 1;\n" + " b.wait(mem_fence::global, memory_scope_sub_group);\n" // both subgroups wait, sync only within subgroup + " value = temp[gid];" // temp[gid] shoule be equal to lid + " }\n" + " else if(get_num_sub_groups() > 2)\n" + " {\n" + " if(get_sub_group_id() < 2)\n" + " {\n" + " const size_t two_first_subgroups = 2 * get_max_sub_group_size();" + // local and global id of some work-item outside of work-item subgroup, + // but within subgroups 0 and 1. + " size_t other_lid = (lid + get_max_sub_group_size()) % two_first_subgroups;\n" + " size_t other_gid = (gid - lid) + other_lid;\n" + " temp[other_gid] = other_lid + 1;\n" + " b.wait(mem_fence::global);\n" // both subgroups wait, both are sync + // local and global id of some other work-item within work-item subgroup + " size_t other_lid_same_subgroup = " + "((lid + 1) % get_sub_group_size()) + (get_sub_group_id() * get_sub_group_size());\n" + " size_t other_gid_same_subgroup = (gid - lid) + other_lid_same_subgroup;\n" + " temp[other_gid_same_subgroup] = temp[other_gid_same_subgroup] - 1;\n" + " b.wait(mem_fence::global, memory_scope_sub_group);\n" // both subgroups wait, sync only within subgroup + " value = temp[gid];" // temp[gid] shoule be equal to lid + " }\n" + " else\n" + " {\n" + " value = lid;\n" + " }\n" + " }\n" + " output[gid] = value;\n" + "}\n"; + #endif + } + + size_t get_max_local_size(const cl_kernel kernel, + const cl_device_id device, + const size_t work_group_size, // default work-group size + cl_int& error) + { + size_t max_wg_size; + error = clGetKernelWorkGroupInfo( + kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &max_wg_size, NULL + ); + RETURN_ON_CL_ERROR(error, "clGetKernelWorkGroupInfo") + return (std::min)(max_wg_size, work_group_size); + } + + cl_int execute(const cl_kernel kernel, + const cl_mem output_buffer, + const cl_command_queue queue, + const size_t work_size, + const size_t work_group_size) + { + cl_int err; + // Get context from queue + cl_context context; + err = clGetCommandQueueInfo(queue, CL_QUEUE_CONTEXT, sizeof(cl_context), &context, NULL); + RETURN_ON_CL_ERROR(err, "clGetCommandQueueInfo") + + // create temp buffer + auto temp_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * work_size, NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + err = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer); + err |= clSetKernelArg(kernel, 1, sizeof(temp_buffer), &temp_buffer); + RETURN_ON_CL_ERROR(err, "clSetKernelArg") + + err = clEnqueueNDRangeKernel( + queue, kernel, 1, + NULL, &work_size, &work_group_size, + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel") + + err = clFinish(queue); + err |= clReleaseMemObject(temp_buffer); + + return err; + } +}; + +struct global_local_fence_named_barrier_test : public work_group_named_barrier_test_base +{ + std::string str() + { + return "global_local_fence"; + } + + // Return value that is expected to be in output_buffer[i] + cl_uint operator()(size_t i, size_t work_group_size, size_t max_sub_group_size) + { + return static_cast(i % work_group_size); + } + + // At the end every work-item writes its local id to ouput[work-item-global-id]. + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return + "__kernel void " + this->get_kernel_name() + "(global uint * output, " + "global uint * temp," + "local uint * lmem)\n" + "{\n" + "size_t gid = get_global_id(0);\n" + "output[gid] = get_local_id(0);\n" + "}\n"; + + #else + return + "#define cl_khr_subgroup_named_barrier\n" + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void " + this->get_kernel_name() + "(global_ptr output, " + "global_ptr temp," + "local_ptr lmem)\n" + "{\n\n" + " local a(1);\n" + " local b(2);\n" + " size_t gid = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " size_t value = 0;\n" + " if(get_num_sub_groups() == 1)\n" + " {\n" + " size_t other_lid = (lid + 1) % get_enqueued_local_size(0);\n" + " size_t other_gid = (gid - lid) + other_lid;\n" + " lmem[other_lid] = other_gid;\n" + " temp[other_gid] = other_lid;\n" + " a.wait(mem_fence::local | mem_fence::global);\n" + " if(lmem[lid] == gid) value = temp[gid];\n" + " }\n" + " else if(get_num_sub_groups() == 2)\n" + " {\n" + " size_t other_lid = (lid + get_max_sub_group_size()) % get_enqueued_local_size(0);\n" + " size_t other_gid = (gid - lid) + other_lid;\n" + " lmem[other_lid] = other_gid;\n" + " temp[other_gid] = other_lid;\n" + " b.wait(mem_fence::local | mem_fence::global);\n" + " if(lmem[lid] == gid) value = temp[gid];\n" + " }\n" + " else if(get_num_sub_groups() > 2)\n" + " {\n" + " if(get_sub_group_id() < 2)\n" + " {\n" + " const size_t two_first_subgroups = 2 * get_max_sub_group_size();" + // local and global id of some work-item outside of work-item subgroup, + // but within subgroups 0 and 1. + " size_t other_lid = (lid + get_max_sub_group_size()) % two_first_subgroups;\n" + " size_t other_gid = (gid - lid) + other_lid;\n" + " lmem[other_lid] = other_gid;\n" + " temp[other_gid] = other_lid;\n" + " b.wait(mem_fence::local | mem_fence::global);\n" + " if(lmem[lid] == gid) value = temp[gid];\n" + " }\n" + " else\n" + " {\n" + " value = lid;\n" + " }\n" + " }\n" + " output[gid] = value;\n" + "}\n"; + #endif + } + + size_t get_max_local_size(const cl_kernel kernel, + const cl_device_id device, + const size_t work_group_size, // default work-group size + cl_int& error) + { + // Set size of the local memory, we need to to this to correctly calculate + // max possible work-group size. + size_t wg_size; + for(wg_size = work_group_size; wg_size > 1; wg_size /= 2) + { + error = clSetKernelArg(kernel, 2, wg_size * sizeof(cl_uint), NULL); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + size_t max_wg_size; + error = clGetKernelWorkGroupInfo( + kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &max_wg_size, NULL + ); + RETURN_ON_CL_ERROR(error, "clGetKernelWorkGroupInfo") + if(max_wg_size >= wg_size) break; + } + return wg_size; + } + + cl_int execute(const cl_kernel kernel, + const cl_mem output_buffer, + const cl_command_queue queue, + const size_t work_size, + const size_t work_group_size) + { + cl_int err; + // Get context from queue + cl_context context; + err = clGetCommandQueueInfo(queue, CL_QUEUE_CONTEXT, sizeof(cl_context), &context, NULL); + RETURN_ON_CL_ERROR(err, "clGetCommandQueueInfo") + + // create temp buffer + auto temp_buffer = clCreateBuffer( + context, (cl_mem_flags)(CL_MEM_READ_WRITE), + sizeof(cl_uint) * work_size, NULL, &err + ); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + err = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer); + err |= clSetKernelArg(kernel, 1, sizeof(temp_buffer), &temp_buffer); + err |= clSetKernelArg(kernel, 2, work_group_size * sizeof(cl_uint), NULL); + RETURN_ON_CL_ERROR(err, "clSetKernelArg") + + err = clEnqueueNDRangeKernel( + queue, kernel, 1, + NULL, &work_size, &work_group_size, + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel") + + err = clFinish(queue); + err |= clReleaseMemObject(temp_buffer); + + return err; + } +}; + +// ------------------------------------------------------------------------------ +// -------------------------- RUN TESTS ----------------------------------------- +// ------------------------------------------------------------------------------ +AUTO_TEST_CASE(test_work_group_named_barrier) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + +#if !(defined(DEVELOPMENT) && (defined(USE_OPENCLC_KERNELS) || defined(ONLY_SPIRV_COMPILATION))) + if(!is_extension_available(device, "cl_khr_subgroup_named_barrier")) + { + log_info("SKIPPED: Extension `cl_khr_subgroup_named_barrier` is not supported. Skipping tests.\n"); + return CL_SUCCESS; + } + + // An implementation shall support at least 8 named barriers per work-group. The exact + // maximum number can be queried using clGetDeviceInfo with CL_DEVICE_MAX_NAMED_BARRIER_COUNT_KHR + // from the OpenCL 2.2 Extension Specification. + cl_uint named_barrier_count; + error = clGetDeviceInfo(device, CL_DEVICE_MAX_NAMED_BARRIER_COUNT_KHR, sizeof(cl_uint), &named_barrier_count, NULL); + RETURN_ON_CL_ERROR(error, "clGetDeviceInfo") + + if(named_barrier_count < 8) + { + RETURN_ON_ERROR_MSG(-1, "Maximum number of named barriers must be at least 8."); + } +#endif + + RUN_WG_NAMED_BARRIER_TEST_MACRO(local_fence_named_barrier_test()) + RUN_WG_NAMED_BARRIER_TEST_MACRO(global_fence_named_barrier_test()) + RUN_WG_NAMED_BARRIER_TEST_MACRO(global_local_fence_named_barrier_test()) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +} // namespace + +#endif // TEST_CONFORMANCE_CLCPP_SYNCHRONIZATION_NAMED_BARRIER_TEST_NAMED_BARRIER_HPP diff --git a/test_conformance/clcpp/synchronization/named_barrier/test_spec_example.hpp b/test_conformance/clcpp/synchronization/named_barrier/test_spec_example.hpp new file mode 100644 index 00000000..c80ab717 --- /dev/null +++ b/test_conformance/clcpp/synchronization/named_barrier/test_spec_example.hpp @@ -0,0 +1,323 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SYNCHRONIZATION_NAMED_BARRIER_TEST_SPEC_EXAMPLE_HPP +#define TEST_CONFORMANCE_CLCPP_SYNCHRONIZATION_NAMED_BARRIER_TEST_SPEC_EXAMPLE_HPP + +#include "common.hpp" + +namespace named_barrier { + +// ------------------------------------------------------------------------------ +// ----------------------- SPECIFICATION EXAMPLE TEST---------------------------- +// ------------------------------------------------------------------------------ +// This test is based on the example in OpenCL C++ 1.0 specification (OpenCL C++ +// Standard Library > Synchronization Functions > Named barriers > wait). +struct spec_example_work_group_named_barrier_test : public work_group_named_barrier_test_base +{ + std::string str() + { + return "spec_example"; + } + + // Return value that is expected to be in output_buffer[i] + cl_uint operator()(size_t i, size_t work_group_size, size_t mas_sub_group_size) + { + return static_cast(i); + } + + // At the end every work-item writes its global id to ouput[work-item-global-id]. + std::string generate_program() + { + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + return + // In OpenCL C kernel we imitate subgroups by partitioning work-group (based on + // local ids of work-items), work_group_named_barrier.wait(..) calls are replaced + // with work_group_barriers. + "__kernel void " + this->get_kernel_name() + "(global uint *output, " + "global uint * temp, " + "local uint * lmem)\n" + "{\n" + "size_t gid = get_global_id(0);\n" + "size_t lid = get_local_id(0);\n" + + // We divide work-group into ranges: + // [0 - e_wg)[ew_g; q_wg)[q_wg; 3 * ew_g)[3 * ew_g; h_wg)[h_wg; get_local_size(0) - 1] + // to simulate 8 subgroups + "size_t h_wg = get_local_size(0) / 2;\n" // half of work-group + "size_t q_wg = get_local_size(0) / 4;\n" // quarter + "size_t e_wg = get_local_size(0) / 8;\n" // one-eighth + + "if(lid < h_wg) lmem[lid] = gid;\n" // [0; h_wg) + "else temp[gid] = gid;\n" // [h_wg; get_local_size(0) - 1) + "work_group_barrier(CLK_LOCAL_MEM_FENCE);\n" + + "size_t other_lid = (lid + q_wg) % h_wg;\n" + "size_t value = 0;\n" + "if(lmem[other_lid] == ((gid - lid) + other_lid)){\n" + " value = gid;\n" + "}\n" + "work_group_barrier(CLK_LOCAL_MEM_FENCE);\n" + + "if(lid < q_wg){\n" // [0; q_wg) + " if(lid < e_wg) lmem[lid + e_wg] = gid;\n" // [0; e_wg) + " else lmem[lid - e_wg] = gid;\n" // [e_wg; q_wg) + "}\n" + "else if(lid < h_wg) {\n" // [q_wg; h_wg) + " if(lid < (3 * e_wg)) lmem[lid + e_wg] = gid;\n" // [q_ww; q_wg + e_wg) + " else lmem[lid - e_wg] = gid;\n" // [q_wg + e_wg; h_wg) + "}\n" + "work_group_barrier(CLK_LOCAL_MEM_FENCE);\n" + + "if(lid < q_wg){\n" // [0; q_wg) + " output[gid + q_wg] = lmem[lid];\n" + "}\n" + "else if(lid < h_wg) {\n" // [q_wg; h_wg) + " output[gid - q_wg] = lmem[lid];\n" + "}\n" + "work_group_barrier(CLK_GLOBAL_MEM_FENCE);\n" + + "if(lid < q_wg){\n" // [0; q_wg) + " if(lid < e_wg) temp[gid] = output[gid + (3 * e_wg)];\n" // [0; e_wg) + " else temp[gid] = output[gid + e_wg];\n" // [e_wg; q_wg) + "}\n" + "else if(lid < h_wg) {\n" // [q_wg; h_wg) + " if(lid < (3 * e_wg)) temp[gid] = output[gid - e_wg];\n" // [q_ww; q_wg + e_wg) + " else temp[gid] = output[gid - (3 * e_wg)];\n" // [q_wg + e_wg; h_wg) + "}\n" + "work_group_barrier(CLK_GLOBAL_MEM_FENCE);\n" + + "output[gid] = temp[gid];\n" + "}\n"; + + #else + return + "#define cl_khr_subgroup_named_barrier\n" + "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + + "void b_function(work_group_named_barrier &b, size_t value, local_ptr lmem)\n" + "{\n\n" + "size_t lid = get_local_id(0);\n" + // Work-items from the 1st subgroup writes to local memory that will be + // later read byt the 0th subgroup, and the other way around - 0th subgroup + // writes what 1st subgroup will later read. + // b.wait(mem_fence::local) should provide sync between those two subgroups. + "if(get_sub_group_id() < 1) lmem[lid + get_max_sub_group_size()] = value;\n" + "else lmem[lid - get_max_sub_group_size()] = value;\n" + "b.wait(mem_fence::local);\n\n" // sync writes to lmem for 2 subgroups (ids: 0, 1) + "}\n" + + "__kernel void " + this->get_kernel_name() + "(global_ptr output, " + "global_ptr temp, " + "local_ptr lmem)\n" + "{\n\n" + "local a(4);\n" + "local b(2);\n" + "local c(2);\n" + + "size_t gid = get_global_id(0);\n" + "size_t lid = get_local_id(0);\n" + "if(get_sub_group_id() < 4)" + "{\n" + " lmem[lid] = gid;\n" + " a.wait(mem_fence::local);\n" // sync writes to lmem for 4 subgroups (ids: 0, 1, 2, 3) + // Now all four subgroups should see changes in lmem. + " size_t other_lid = (lid + (2 * get_max_sub_group_size())) % (4 * get_max_sub_group_size());\n" + " size_t value = 0;\n" + " if(lmem[other_lid] == ((gid - lid) + other_lid)){\n" + " value = gid;\n" + " }\n" + " a.wait(mem_fence::local);\n" // sync reads from lmem for 4 subgroups (ids: 0, 1, 2, 3) + + " if(get_sub_group_id() < 2)" // ids: 0, 1 + " {\n" + " b_function(b, value, lmem);\n" + " }\n" + " else" // ids: 2, 3 + " {\n" + // Work-items from the 2nd subgroup writes to local memory that will be + // later read byt the 3rd subgroup, and the other way around - 3rd subgroup + // writes what 2nd subgroup will later read. + // c.wait(mem_fence::local) should provide sync between those two subgroups. + " if(get_sub_group_id() < 3) lmem[lid + get_max_sub_group_size()] = value ;\n" + " else lmem[lid - get_max_sub_group_size()] = value;\n" + " c.wait(mem_fence::local);\n" // sync writes to lmem for 2 subgroups (3, 4) + " }\n" + + // Now (0, 1) are in sync (local mem), and (3, 4) are in sync (local mem). + // However, subgroups (0, 1) are not in sync with (3, 4). + " if(get_sub_group_id() < 4) {\n" // ids: 0, 1, 2, 3 + " if(get_sub_group_id() < 2) output[gid + (2 * get_max_sub_group_size())] = lmem[lid];\n" + " else output[gid - (2 * get_max_sub_group_size())] = lmem[lid];\n" + " a.wait(mem_fence::global);\n" // sync writes to global memory (output) + // for 4 subgroups (0, 1, 2, 3) + " }\n" + "}\n" + "else {\n" // subgroups with id > 4 + " temp[gid] = gid;\n" + "}\n" + + // Now (0, 1, 2, 3) are in sync (global mem) + "if(get_sub_group_id() < 2) {\n" + " if(get_sub_group_id() < 1) temp[gid] = output[gid + (3 * get_max_sub_group_size())];\n" + " else temp[gid] = output[gid + (get_max_sub_group_size())];\n" + "}\n" + "else if(get_sub_group_id() < 4) {\n" + " if(get_sub_group_id() < 3) temp[gid] = output[gid - (get_max_sub_group_size())];\n" + " else temp[gid] = output[gid - (3 * get_max_sub_group_size())];\n" + "}\n" + + // Synchronize the entire work-group (in terms of accesses to global memory) + "work_group_barrier(mem_fence::global);\n" + "output[gid] = temp[gid];\n\n" + "}\n"; + #endif + } + + size_t get_max_local_size(const cl_kernel kernel, + const cl_device_id device, + const size_t work_group_size, // default work-group size + cl_int& error) + { + // Set size of the local memory, we need to to this to correctly calculate + // max possible work-group size. + size_t wg_size; + for(wg_size = work_group_size; wg_size > 1; wg_size /= 2) + { + error = clSetKernelArg(kernel, 2, ((wg_size / 2) + 1) * sizeof(cl_uint), NULL); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + size_t max_wg_size; + error = clGetKernelWorkGroupInfo( + kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &max_wg_size, NULL + ); + RETURN_ON_ERROR(error) + if(max_wg_size >= wg_size) break; + } + + // ----------------------------------------------------------------------------------- + // ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ + // ----------------------------------------------------------------------------------- + #if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + // make sure wg_size is a multiple of 8 + if(wg_size % 8 > 0) wg_size -= (wg_size % 8); + return wg_size; + #else + // make sure that wg_size will produce at least min_num_sub_groups + // subgroups in each work-group + size_t local_size[3] = { 1, 1, 1 }; + size_t min_num_sub_groups = 8; + error = clGetKernelSubGroupInfo(kernel, device, CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT, + sizeof(size_t), &min_num_sub_groups, + sizeof(size_t) * 3, &local_size, NULL); + RETURN_ON_CL_ERROR(error, "clGetKernelSubGroupInfo") + if (local_size[0] == 0 || local_size[1] != 1 || local_size[2] != 1) + { + if(min_num_sub_groups == 1) + { + RETURN_ON_ERROR_MSG(-1, "Can't produce local size with one subgroup") + } + return 0; + } + local_size[0] = (std::min)(wg_size, local_size[0]); + + // double-check + size_t sub_group_count_for_ndrange; + error = clGetKernelSubGroupInfo(kernel, device, CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE, + sizeof(size_t) * 3, local_size, + sizeof(size_t), &sub_group_count_for_ndrange, NULL); + RETURN_ON_CL_ERROR(error, "clGetKernelSubGroupInfo") + if (sub_group_count_for_ndrange < min_num_sub_groups) + { + RETURN_ON_ERROR_MSG(-1, + "CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE did not return correct value (expected >=%lu, got %lu)", + min_num_sub_groups, sub_group_count_for_ndrange + ) + } + + return local_size[0]; + #endif + } + + cl_int execute(const cl_kernel kernel, + const cl_mem output_buffer, + const cl_command_queue queue, + const size_t work_size, + const size_t work_group_size) + { + cl_int err; + // Get context from queue + cl_context context; + err = clGetCommandQueueInfo(queue, CL_QUEUE_CONTEXT, sizeof(cl_context), &context, NULL); + RETURN_ON_CL_ERROR(err, "clGetCommandQueueInfo") + + // create temp buffer + auto temp_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * work_size, NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + err = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer); + err |= clSetKernelArg(kernel, 1, sizeof(temp_buffer), &temp_buffer); + err |= clSetKernelArg(kernel, 2, work_group_size * sizeof(cl_uint), NULL); + RETURN_ON_CL_ERROR(err, "clSetKernelArg") + + err = clEnqueueNDRangeKernel( + queue, kernel, 1, + NULL, &work_size, &work_group_size, + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel") + + err = clFinish(queue); + err |= clReleaseMemObject(temp_buffer); + + return err; + } +}; + +// ------------------------------------------------------------------------------ +// -------------------------- RUN TESTS ----------------------------------------- +// ------------------------------------------------------------------------------ +AUTO_TEST_CASE(test_work_group_named_barrier_spec_example) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ +#if !(defined(DEVELOPMENT) && (defined(USE_OPENCLC_KERNELS) || defined(ONLY_SPIRV_COMPILATION))) + if(!is_extension_available(device, "cl_khr_subgroup_named_barrier")) + { + log_info("SKIPPED: Extension `cl_khr_subgroup_named_barrier` is not supported. Skipping tests.\n"); + return CL_SUCCESS; + } +#endif + + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + + RUN_WG_NAMED_BARRIER_TEST_MACRO(spec_example_work_group_named_barrier_test()) + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +} // namespace + +#endif // TEST_CONFORMANCE_CLCPP_SYNCHRONIZATION_NAMED_BARRIER_TEST_SPEC_EXAMPLE_HPP diff --git a/test_conformance/clcpp/synchronization/test_sub_group_barrier.hpp b/test_conformance/clcpp/synchronization/test_sub_group_barrier.hpp new file mode 100644 index 00000000..20de1824 --- /dev/null +++ b/test_conformance/clcpp/synchronization/test_sub_group_barrier.hpp @@ -0,0 +1,342 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SYNCHRONIZATION_TEST_SUB_GROUP_BARRIER_HPP +#define TEST_CONFORMANCE_CLCPP_SYNCHRONIZATION_TEST_SUB_GROUP_BARRIER_HPP + +#include +#include +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" + + +namespace test_sub_group_barrier { + +enum class barrier_type +{ + local, + global +}; + +struct test_options +{ + barrier_type barrier; + size_t max_count; + size_t num_tests; +}; + +const std::string source_common = R"( + // Circular shift of sub-group local ids + size_t get_shifted_local_id(int sub_group_local_id_delta) + { + const int sub_group_size = (int)get_sub_group_size(); + return (get_local_id(0) - get_sub_group_local_id()) + + (((int)get_sub_group_local_id() + sub_group_local_id_delta) % sub_group_size + sub_group_size) % sub_group_size; + } + + // Get global ids from shifted local ids + size_t get_shifted_global_id(int sub_group_local_id_delta) + { + return get_group_id(0) * get_enqueued_local_size(0) + get_shifted_local_id(sub_group_local_id_delta); + } +)"; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +std::string generate_source(test_options options) +{ + std::stringstream s; + s << R"( + #pragma OPENCL EXTENSION cl_khr_subgroups : enable + )"; + s << source_common; + if (options.barrier == barrier_type::global) + { + s << R"( + kernel void test(const int iter_lo, const int iter_hi, global long *output) + { + const size_t gid = get_shifted_global_id(0); + + output[gid] = gid; + sub_group_barrier(CLK_GLOBAL_MEM_FENCE); + + for (int i = iter_lo; i < iter_hi; i++) + { + const size_t other_gid = get_shifted_global_id(i); + + output[other_gid] += other_gid; + sub_group_barrier(CLK_GLOBAL_MEM_FENCE); + + output[gid] += gid; + sub_group_barrier(CLK_GLOBAL_MEM_FENCE); + } + } + )"; + } + else if (options.barrier == barrier_type::local) + { + s << R"( + kernel void test(const int iter_lo, const int iter_hi, global long *output, local long *values) + { + const size_t gid = get_shifted_global_id(0); + const size_t lid = get_shifted_local_id(0); + + values[lid] = gid; + sub_group_barrier(CLK_LOCAL_MEM_FENCE); + + for (int i = iter_lo; i < iter_hi; i++) + { + const size_t other_lid = get_shifted_local_id(i); + const size_t other_gid = get_shifted_global_id(i); + + values[other_lid] += other_gid; + sub_group_barrier(CLK_LOCAL_MEM_FENCE); + + values[lid] += gid; + sub_group_barrier(CLK_LOCAL_MEM_FENCE); + } + + output[gid] = values[lid]; + } + )"; + } + + return s.str(); +} +#else +std::string generate_source(test_options options) +{ + std::stringstream s; + s << R"( + #include + #include + #include + + using namespace cl; + + )"; + s << source_common; + + if (options.barrier == barrier_type::global) + { + s << R"( + kernel void test(const int iter_lo, const int iter_hi, global_ptr output) + { + const size_t gid = get_shifted_global_id(0); + + output[gid] = gid; + sub_group_barrier(mem_fence::global); + + for (int i = iter_lo; i < iter_hi; i++) + { + const size_t other_gid = get_shifted_global_id(i); + + output[other_gid] += other_gid; + sub_group_barrier(mem_fence::global); + + output[gid] += gid; + sub_group_barrier(mem_fence::global); + } + } + )"; + } + else if (options.barrier == barrier_type::local) + { + s << R"( + kernel void test(const int iter_lo, const int iter_hi, global_ptr output, local_ptr values) + { + const size_t gid = get_shifted_global_id(0); + const size_t lid = get_shifted_local_id(0); + + values[lid] = gid; + sub_group_barrier(mem_fence::local); + + for (int i = iter_lo; i < iter_hi; i++) + { + const size_t other_lid = get_shifted_local_id(i); + const size_t other_gid = get_shifted_global_id(i); + + values[other_lid] += other_gid; + sub_group_barrier(mem_fence::local); + + values[lid] += gid; + sub_group_barrier(mem_fence::local); + } + + output[gid] = values[lid]; + } + )"; + } + + return s.str(); +} +#endif + +int test(cl_device_id device, cl_context context, cl_command_queue queue, test_options options) +{ + int error = CL_SUCCESS; + +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + if (!is_extension_available(device, "cl_khr_subgroups")) + { + log_info("SKIPPED: Extension `cl_khr_subgroups` is not supported. Skipping tests.\n"); + return CL_SUCCESS; + } +#endif + + cl_program program; + cl_kernel kernel; + + std::string kernel_name = "test"; + std::string source = generate_source(options); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name, "-cl-std=CL2.0", false + ); + RETURN_ON_ERROR(error) +// Normal run +#else + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) +#endif + + size_t max_work_group_size; + error = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(max_work_group_size), &max_work_group_size, NULL); + RETURN_ON_CL_ERROR(error, "clGetKernelWorkGroupInfo") + + if (options.barrier == barrier_type::local) + { + cl_ulong kernel_local_mem_size; + error = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_LOCAL_MEM_SIZE, sizeof(kernel_local_mem_size), &kernel_local_mem_size, NULL); + RETURN_ON_CL_ERROR(error, "clGetKernelWorkGroupInfo") + + cl_ulong device_local_mem_size; + error = clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(device_local_mem_size), &device_local_mem_size, NULL); + RETURN_ON_CL_ERROR(error, "clGetDeviceInfo") + + max_work_group_size = (std::min)(max_work_group_size, (device_local_mem_size - kernel_local_mem_size) / sizeof(cl_long)); + } + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution global_size_dis(1, options.max_count); + std::uniform_int_distribution local_size_dis(1, max_work_group_size); + std::uniform_int_distribution iter_dis(0, 20); + + for (size_t test = 0; test < options.num_tests; test++) + { + const size_t global_size = global_size_dis(gen); + const size_t local_size = local_size_dis(gen); + const size_t count = global_size; + + const int iter_lo = -iter_dis(gen); + const int iter_hi = +iter_dis(gen); + + cl_mem output_buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_long) * count, NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(iter_lo), &iter_lo); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 1, sizeof(iter_hi), &iter_hi); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 2, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + if (options.barrier == barrier_type::local) + { + error = clSetKernelArg(kernel, 3, sizeof(cl_long) * local_size, NULL); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + } + + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, &local_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + std::vector output(count); + error = clEnqueueReadBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(cl_long) * count, + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + error = clReleaseMemObject(output_buffer); + RETURN_ON_CL_ERROR(error, "clReleaseMemObject") + + for (size_t gid = 0; gid < count; gid++) + { + const long value = output[gid]; + const long expected = gid + 2 * gid * (iter_hi - iter_lo); + + if (value != expected) + { + RETURN_ON_ERROR_MSG(-1, + "Element %lu has incorrect value. Expected: %ld, got: %ld", + gid, expected, value + ); + } + } + } + + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; +} + +AUTO_TEST_CASE(test_sub_group_barrier_global) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + test_options options; + options.barrier = barrier_type::global; + options.num_tests = 1000; + options.max_count = num_elements; + return test(device, context, queue, options); +} + +AUTO_TEST_CASE(test_sub_group_barrier_local) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + test_options options; + options.barrier = barrier_type::local; + options.num_tests = 1000; + options.max_count = num_elements; + return test(device, context, queue, options); +} + +} // namespace + +#endif // TEST_CONFORMANCE_CLCPP_SYNCHRONIZATION_TEST_SUB_GROUP_BARRIER_HPP diff --git a/test_conformance/clcpp/synchronization/test_work_group_barrier.hpp b/test_conformance/clcpp/synchronization/test_work_group_barrier.hpp new file mode 100644 index 00000000..79451fb8 --- /dev/null +++ b/test_conformance/clcpp/synchronization/test_work_group_barrier.hpp @@ -0,0 +1,330 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_SYNCHRONIZATION_TEST_WORK_GROUP_BARRIER_HPP +#define TEST_CONFORMANCE_CLCPP_SYNCHRONIZATION_TEST_WORK_GROUP_BARRIER_HPP + +#include +#include +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" + + +namespace test_work_group_barrier { + +enum class barrier_type +{ + local, + global +}; + +struct test_options +{ + barrier_type barrier; + size_t max_count; + size_t num_tests; +}; + +const std::string source_common = R"( + // Circular shift of local ids + size_t get_shifted_local_id(int local_id_delta) + { + const int local_size = (int)get_local_size(0); + return (((int)get_local_id(0) + local_id_delta) % local_size + local_size) % local_size; + } + + // Get global ids from shifted local ids + size_t get_shifted_global_id(int local_id_delta) + { + return get_group_id(0) * get_enqueued_local_size(0) + get_shifted_local_id(local_id_delta); + } +)"; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +std::string generate_source(test_options options) +{ + std::stringstream s; + s << source_common; + if (options.barrier == barrier_type::global) + { + s << R"( + kernel void test(const int iter_lo, const int iter_hi, global long *output) + { + const size_t gid = get_shifted_global_id(0); + + output[gid] = gid; + work_group_barrier(CLK_GLOBAL_MEM_FENCE); + + for (int i = iter_lo; i < iter_hi; i++) + { + const size_t other_gid = get_shifted_global_id(i); + + output[other_gid] += other_gid; + work_group_barrier(CLK_GLOBAL_MEM_FENCE); + + output[gid] += gid; + work_group_barrier(CLK_GLOBAL_MEM_FENCE); + } + } + )"; + } + else if (options.barrier == barrier_type::local) + { + s << R"( + kernel void test(const int iter_lo, const int iter_hi, global long *output, local long *values) + { + const size_t gid = get_shifted_global_id(0); + const size_t lid = get_shifted_local_id(0); + + values[lid] = gid; + work_group_barrier(CLK_LOCAL_MEM_FENCE); + + for (int i = iter_lo; i < iter_hi; i++) + { + const size_t other_lid = get_shifted_local_id(i); + const size_t other_gid = get_shifted_global_id(i); + + values[other_lid] += other_gid; + work_group_barrier(CLK_LOCAL_MEM_FENCE); + + values[lid] += gid; + work_group_barrier(CLK_LOCAL_MEM_FENCE); + } + + output[gid] = values[lid]; + } + )"; + } + + return s.str(); +} +#else +std::string generate_source(test_options options) +{ + std::stringstream s; + s << R"( + #include + #include + #include + + using namespace cl; + + )"; + s << source_common; + + if (options.barrier == barrier_type::global) + { + s << R"( + kernel void test(const int iter_lo, const int iter_hi, global_ptr output) + { + const size_t gid = get_shifted_global_id(0); + + output[gid] = gid; + work_group_barrier(mem_fence::global); + + for (int i = iter_lo; i < iter_hi; i++) + { + const size_t other_gid = get_shifted_global_id(i); + + output[other_gid] += other_gid; + work_group_barrier(mem_fence::global); + + output[gid] += gid; + work_group_barrier(mem_fence::global); + } + } + )"; + } + else if (options.barrier == barrier_type::local) + { + s << R"( + kernel void test(const int iter_lo, const int iter_hi, global_ptr output, local_ptr values) + { + const size_t gid = get_shifted_global_id(0); + const size_t lid = get_shifted_local_id(0); + + values[lid] = gid; + work_group_barrier(mem_fence::local); + + for (int i = iter_lo; i < iter_hi; i++) + { + const size_t other_lid = get_shifted_local_id(i); + const size_t other_gid = get_shifted_global_id(i); + + values[other_lid] += other_gid; + work_group_barrier(mem_fence::local); + + values[lid] += gid; + work_group_barrier(mem_fence::local); + } + + output[gid] = values[lid]; + } + )"; + } + + return s.str(); +} +#endif + +int test(cl_device_id device, cl_context context, cl_command_queue queue, test_options options) +{ + int error = CL_SUCCESS; + + cl_program program; + cl_kernel kernel; + + std::string kernel_name = "test"; + std::string source = generate_source(options); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name, "-cl-std=CL2.0", false + ); + RETURN_ON_ERROR(error) +// Normal run +#else + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) +#endif + + size_t max_work_group_size; + error = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(max_work_group_size), &max_work_group_size, NULL); + RETURN_ON_CL_ERROR(error, "clGetKernelWorkGroupInfo") + + if (options.barrier == barrier_type::local) + { + cl_ulong kernel_local_mem_size; + error = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_LOCAL_MEM_SIZE, sizeof(kernel_local_mem_size), &kernel_local_mem_size, NULL); + RETURN_ON_CL_ERROR(error, "clGetKernelWorkGroupInfo") + + cl_ulong device_local_mem_size; + error = clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(device_local_mem_size), &device_local_mem_size, NULL); + RETURN_ON_CL_ERROR(error, "clGetDeviceInfo") + + max_work_group_size = (std::min)(max_work_group_size, (device_local_mem_size - kernel_local_mem_size) / sizeof(cl_long)); + } + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution global_size_dis(1, options.max_count); + std::uniform_int_distribution local_size_dis(1, max_work_group_size); + std::uniform_int_distribution iter_dis(0, 20); + + for (size_t test = 0; test < options.num_tests; test++) + { + const size_t global_size = global_size_dis(gen); + const size_t local_size = local_size_dis(gen); + const size_t count = global_size; + + const int iter_lo = -iter_dis(gen); + const int iter_hi = +iter_dis(gen); + + cl_mem output_buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_long) * count, NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(iter_lo), &iter_lo); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 1, sizeof(iter_hi), &iter_hi); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + error = clSetKernelArg(kernel, 2, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + if (options.barrier == barrier_type::local) + { + error = clSetKernelArg(kernel, 3, sizeof(cl_long) * local_size, NULL); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + } + + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, &local_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + std::vector output(count); + error = clEnqueueReadBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(cl_long) * count, + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + error = clReleaseMemObject(output_buffer); + RETURN_ON_CL_ERROR(error, "clReleaseMemObject") + + for (size_t gid = 0; gid < count; gid++) + { + const long value = output[gid]; + const long expected = gid + 2 * gid * (iter_hi - iter_lo); + + if (value != expected) + { + RETURN_ON_ERROR_MSG(-1, + "Element %lu has incorrect value. Expected: %ld, got: %ld", + gid, expected, value + ); + } + } + } + + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; +} + +AUTO_TEST_CASE(test_work_group_barrier_global) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + test_options options; + options.barrier = barrier_type::global; + options.num_tests = 1000; + options.max_count = num_elements; + return test(device, context, queue, options); +} + +AUTO_TEST_CASE(test_work_group_barrier_local) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + test_options options; + options.barrier = barrier_type::local; + options.num_tests = 1000; + options.max_count = num_elements; + return test(device, context, queue, options); +} + +} // namespace + +#endif // TEST_CONFORMANCE_CLCPP_SYNCHRONIZATION_TEST_WORK_GROUP_BARRIER_HPP diff --git a/test_conformance/clcpp/utils_common/errors.hpp b/test_conformance/clcpp/utils_common/errors.hpp new file mode 100644 index 00000000..e47eff3e --- /dev/null +++ b/test_conformance/clcpp/utils_common/errors.hpp @@ -0,0 +1,134 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_COMMON_ERRORS_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_COMMON_ERRORS_HPP + +#include + +#include "../../../test_common/harness/errorHelpers.h" + +// ------------- Check OpenCL error helpers (marcos) ----------------- + +std::string get_cl_error_string(cl_int error) +{ +#define CASE_CL_ERROR(x) case x: return #x; + switch (error) + { + CASE_CL_ERROR(CL_SUCCESS) + CASE_CL_ERROR(CL_DEVICE_NOT_FOUND) + CASE_CL_ERROR(CL_DEVICE_NOT_AVAILABLE) + CASE_CL_ERROR(CL_COMPILER_NOT_AVAILABLE) + CASE_CL_ERROR(CL_MEM_OBJECT_ALLOCATION_FAILURE) + CASE_CL_ERROR(CL_OUT_OF_RESOURCES) + CASE_CL_ERROR(CL_OUT_OF_HOST_MEMORY) + CASE_CL_ERROR(CL_PROFILING_INFO_NOT_AVAILABLE) + CASE_CL_ERROR(CL_MEM_COPY_OVERLAP) + CASE_CL_ERROR(CL_IMAGE_FORMAT_MISMATCH) + CASE_CL_ERROR(CL_IMAGE_FORMAT_NOT_SUPPORTED) + CASE_CL_ERROR(CL_BUILD_PROGRAM_FAILURE) + CASE_CL_ERROR(CL_MAP_FAILURE) + CASE_CL_ERROR(CL_MISALIGNED_SUB_BUFFER_OFFSET) + CASE_CL_ERROR(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST) + CASE_CL_ERROR(CL_COMPILE_PROGRAM_FAILURE) + CASE_CL_ERROR(CL_LINKER_NOT_AVAILABLE) + CASE_CL_ERROR(CL_LINK_PROGRAM_FAILURE) + CASE_CL_ERROR(CL_DEVICE_PARTITION_FAILED) + CASE_CL_ERROR(CL_KERNEL_ARG_INFO_NOT_AVAILABLE) + + CASE_CL_ERROR(CL_INVALID_VALUE) + CASE_CL_ERROR(CL_INVALID_DEVICE_TYPE) + CASE_CL_ERROR(CL_INVALID_PLATFORM) + CASE_CL_ERROR(CL_INVALID_DEVICE) + CASE_CL_ERROR(CL_INVALID_CONTEXT) + CASE_CL_ERROR(CL_INVALID_QUEUE_PROPERTIES) + CASE_CL_ERROR(CL_INVALID_COMMAND_QUEUE) + CASE_CL_ERROR(CL_INVALID_HOST_PTR) + CASE_CL_ERROR(CL_INVALID_MEM_OBJECT) + CASE_CL_ERROR(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR) + CASE_CL_ERROR(CL_INVALID_IMAGE_SIZE) + CASE_CL_ERROR(CL_INVALID_SAMPLER) + CASE_CL_ERROR(CL_INVALID_BINARY) + CASE_CL_ERROR(CL_INVALID_BUILD_OPTIONS) + CASE_CL_ERROR(CL_INVALID_PROGRAM) + CASE_CL_ERROR(CL_INVALID_PROGRAM_EXECUTABLE) + CASE_CL_ERROR(CL_INVALID_KERNEL_NAME) + CASE_CL_ERROR(CL_INVALID_KERNEL_DEFINITION) + CASE_CL_ERROR(CL_INVALID_KERNEL) + CASE_CL_ERROR(CL_INVALID_ARG_INDEX) + CASE_CL_ERROR(CL_INVALID_ARG_VALUE) + CASE_CL_ERROR(CL_INVALID_ARG_SIZE) + CASE_CL_ERROR(CL_INVALID_KERNEL_ARGS) + CASE_CL_ERROR(CL_INVALID_WORK_DIMENSION) + CASE_CL_ERROR(CL_INVALID_WORK_GROUP_SIZE) + CASE_CL_ERROR(CL_INVALID_WORK_ITEM_SIZE) + CASE_CL_ERROR(CL_INVALID_GLOBAL_OFFSET) + CASE_CL_ERROR(CL_INVALID_EVENT_WAIT_LIST) + CASE_CL_ERROR(CL_INVALID_EVENT) + CASE_CL_ERROR(CL_INVALID_OPERATION) + CASE_CL_ERROR(CL_INVALID_GL_OBJECT) + CASE_CL_ERROR(CL_INVALID_BUFFER_SIZE) + CASE_CL_ERROR(CL_INVALID_MIP_LEVEL) + CASE_CL_ERROR(CL_INVALID_GLOBAL_WORK_SIZE) + CASE_CL_ERROR(CL_INVALID_PROPERTY) + CASE_CL_ERROR(CL_INVALID_IMAGE_DESCRIPTOR) + CASE_CL_ERROR(CL_INVALID_COMPILER_OPTIONS) + CASE_CL_ERROR(CL_INVALID_LINKER_OPTIONS) + CASE_CL_ERROR(CL_INVALID_DEVICE_PARTITION_COUNT) + CASE_CL_ERROR(CL_INVALID_PIPE_SIZE) + CASE_CL_ERROR(CL_INVALID_DEVICE_QUEUE) + CASE_CL_ERROR(CL_INVALID_SPEC_ID) + CASE_CL_ERROR(CL_MAX_SIZE_RESTRICTION_EXCEEDED) + default: return "(unknown error code)"; + } +#undef CASE_CL_ERROR +} + +#define CHECK_ERROR(x) \ + if(x != CL_SUCCESS) \ + { \ + log_error("ERROR: %d, file: %s, line: %d\n", x, __FILE__, __LINE__);\ + } +#define CHECK_ERROR_MSG(x, ...) \ + if(x != CL_SUCCESS) \ + { \ + log_error("ERROR: " __VA_ARGS__);\ + log_error("\n");\ + log_error("ERROR: %d, file: %s, line: %d\n", x, __FILE__, __LINE__);\ + } +#define RETURN_ON_ERROR(x) \ + if(x != CL_SUCCESS) \ + { \ + log_error("ERROR: %d, file: %s, line: %d\n", x, __FILE__, __LINE__);\ + return x;\ + } +#define RETURN_ON_ERROR_MSG(x, ...) \ + if(x != CL_SUCCESS) \ + { \ + log_error("ERROR: " __VA_ARGS__);\ + log_error("\n");\ + log_error("ERROR: %d, file: %s, line: %d\n", x, __FILE__, __LINE__);\ + return x;\ + } + +#define RETURN_ON_CL_ERROR(x, cl_func_name) \ + if(x != CL_SUCCESS) \ + { \ + log_error("ERROR: %s failed: %s (%d)\n", cl_func_name, get_cl_error_string(x).c_str(), x);\ + log_error("ERROR: %d, file: %s, line: %d\n", x, __FILE__, __LINE__);\ + return x;\ + } + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_TEST_ERRORS_HPP diff --git a/test_conformance/clcpp/utils_common/is_vector_type.hpp b/test_conformance/clcpp/utils_common/is_vector_type.hpp new file mode 100644 index 00000000..0232e513 --- /dev/null +++ b/test_conformance/clcpp/utils_common/is_vector_type.hpp @@ -0,0 +1,60 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_COMMON_IS_VECTOR_TYPE_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_COMMON_IS_VECTOR_TYPE_HPP + +#include "../common.hpp" + +// is_vector_type::value is true if Type is an OpenCL +// vector type; otherwise - false. +// +// Examples: +// * is_vector_type::value == false +// * is_vector_type::value == true +template +struct is_vector_type +{ + const static bool value = false; +}; + +#define ADD_VECTOR_TYPE(Type, n) \ + template<> \ + struct is_vector_type \ + { \ + const static bool value = true; \ + }; + +#define ADD_VECTOR_TYPES(Type) \ + ADD_VECTOR_TYPE(Type, 2) \ + ADD_VECTOR_TYPE(Type, 4) \ + ADD_VECTOR_TYPE(Type, 8) \ + ADD_VECTOR_TYPE(Type, 16) + +ADD_VECTOR_TYPES(cl_char) +ADD_VECTOR_TYPES(cl_uchar) +ADD_VECTOR_TYPES(cl_short) +ADD_VECTOR_TYPES(cl_ushort) +ADD_VECTOR_TYPES(cl_int) +ADD_VECTOR_TYPES(cl_uint) +ADD_VECTOR_TYPES(cl_long) +ADD_VECTOR_TYPES(cl_ulong) +ADD_VECTOR_TYPES(cl_float) +ADD_VECTOR_TYPES(cl_double) + +#undef ADD_VECTOR_TYPES +#undef ADD_VECTOR_TYPE + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_COMMON_IS_VECTOR_TYPE_HPP diff --git a/test_conformance/clcpp/utils_common/kernel_helpers.hpp b/test_conformance/clcpp/utils_common/kernel_helpers.hpp new file mode 100644 index 00000000..189b8238 --- /dev/null +++ b/test_conformance/clcpp/utils_common/kernel_helpers.hpp @@ -0,0 +1,50 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_COMMON_KERNEL_HELPERS_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_COMMON_KERNEL_HELPERS_HPP + +#include "../common.hpp" + +// Creates a OpenCL C++/C program out_program and kernel out_kernel. +int create_opencl_kernel(cl_context context, + cl_program *out_program, + cl_kernel *out_kernel, + const char *source, + const std::string& kernel_name, + const std::string& build_options = "", + const bool openclCXX = true) +{ + return create_single_kernel_helper( + context, out_program, out_kernel, 1, &source, + kernel_name.c_str(), build_options.c_str(), openclCXX + ); +} + +int create_opencl_kernel(cl_context context, + cl_program *out_program, + cl_kernel *out_kernel, + const std::string& source, + const std::string& kernel_name, + const std::string& build_options = "", + const bool openclCXX = true) +{ + return create_opencl_kernel( + context, out_program, out_kernel, + source.c_str(), kernel_name, build_options, openclCXX + ); +} + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_COMMON_KERNEL_HELPERS_HPP diff --git a/test_conformance/clcpp/utils_common/make_vector_type.hpp b/test_conformance/clcpp/utils_common/make_vector_type.hpp new file mode 100644 index 00000000..11b11856 --- /dev/null +++ b/test_conformance/clcpp/utils_common/make_vector_type.hpp @@ -0,0 +1,65 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_COMMON_MAKE_VECTOR_TYPE_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_COMMON_MAKE_VECTOR_TYPE_HPP + +#include "../common.hpp" + +// Using scalar_type and i creates a type scalar_typei. +// +// Example: +// * make_vector_type::type is cl_uint8 +// * make_vector_type::type is cl_uint +template +struct make_vector_type +{ + typedef void type; +}; + +#define ADD_MAKE_VECTOR_TYPE(Type, n) \ + template<> \ + struct make_vector_type \ + { \ + typedef Type ## n type; \ + }; + +#define ADD_MAKE_VECTOR_TYPES(Type) \ + template<> \ + struct make_vector_type \ + { \ + typedef Type type; \ + }; \ + ADD_MAKE_VECTOR_TYPE(Type, 2) \ + ADD_MAKE_VECTOR_TYPE(Type, 3) \ + ADD_MAKE_VECTOR_TYPE(Type, 4) \ + ADD_MAKE_VECTOR_TYPE(Type, 8) \ + ADD_MAKE_VECTOR_TYPE(Type, 16) + +ADD_MAKE_VECTOR_TYPES(cl_char) +ADD_MAKE_VECTOR_TYPES(cl_uchar) +ADD_MAKE_VECTOR_TYPES(cl_short) +ADD_MAKE_VECTOR_TYPES(cl_ushort) +ADD_MAKE_VECTOR_TYPES(cl_int) +ADD_MAKE_VECTOR_TYPES(cl_uint) +ADD_MAKE_VECTOR_TYPES(cl_long) +ADD_MAKE_VECTOR_TYPES(cl_ulong) +ADD_MAKE_VECTOR_TYPES(cl_float) +ADD_MAKE_VECTOR_TYPES(cl_double) + +#undef ADD_MAKE_VECTOR_TYPES +#undef ADD_MAKE_VECTOR_TYPE + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_COMMON_MAKE_VECTOR_TYPE_HPP diff --git a/test_conformance/clcpp/utils_common/scalar_type.hpp b/test_conformance/clcpp/utils_common/scalar_type.hpp new file mode 100644 index 00000000..4c939bb2 --- /dev/null +++ b/test_conformance/clcpp/utils_common/scalar_type.hpp @@ -0,0 +1,64 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_COMMON_SCALAR_TYPE_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_COMMON_SCALAR_TYPE_HPP + +#include "../common.hpp" + +// scalar_type::type returns scalar type of Type. +// +// Examples: +// * scalar_type::type is cl_float +// * scalar_type::types is cl_float +template +struct scalar_type +{ + typedef void type; +}; + +#define ADD_VECTOR_TYPE(Type, n) \ + template<> \ + struct scalar_type \ + { \ + typedef Type type; \ + }; + +#define ADD_VECTOR_TYPES(Type) \ + template<> \ + struct scalar_type \ + { \ + typedef Type type; \ + }; \ + ADD_VECTOR_TYPE(Type, 2) \ + ADD_VECTOR_TYPE(Type, 4) \ + ADD_VECTOR_TYPE(Type, 8) \ + ADD_VECTOR_TYPE(Type, 16) + +ADD_VECTOR_TYPES(cl_char) +ADD_VECTOR_TYPES(cl_uchar) +ADD_VECTOR_TYPES(cl_short) +ADD_VECTOR_TYPES(cl_ushort) +ADD_VECTOR_TYPES(cl_int) +ADD_VECTOR_TYPES(cl_uint) +ADD_VECTOR_TYPES(cl_long) +ADD_VECTOR_TYPES(cl_ulong) +ADD_VECTOR_TYPES(cl_float) +ADD_VECTOR_TYPES(cl_double) + +#undef ADD_VECTOR_TYPES +#undef ADD_VECTOR_TYPE + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_COMMON_SCALAR_TYPE_HPP diff --git a/test_conformance/clcpp/utils_common/string.hpp b/test_conformance/clcpp/utils_common/string.hpp new file mode 100644 index 00000000..ad5ac9f0 --- /dev/null +++ b/test_conformance/clcpp/utils_common/string.hpp @@ -0,0 +1,70 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_COMMON_STRING_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_COMMON_STRING_HPP + + +#include +#include +#include +#include + +#include "is_vector_type.hpp" +#include "scalar_type.hpp" +#include "type_name.hpp" + +#include "../common.hpp" + + +template +std::string format_value(const type& value, + typename std::enable_if::value>::type* = 0) +{ + std::stringstream s; + s << type_name() << "{ "; + s << std::scientific << std::setprecision(6); + for (size_t j = 0; j < vector_size::value; j++) + { + if (j > 0) + s << ", "; + s << value.s[j]; + } + s << " }"; + return s.str(); +} + +template +std::string format_value(const type& value, + typename std::enable_if::value>::type* = 0) +{ + std::stringstream s; + s << type_name() << "{ "; + s << std::scientific << std::setprecision(6); + s << value; + s << " }"; + return s.str(); +} + +void replace_all(std::string& str, const std::string& from, const std::string& to) +{ + size_t start_pos = 0; + while((start_pos = str.find(from, start_pos)) != std::string::npos) { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); + } +} + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_COMMON_STRING_HPP diff --git a/test_conformance/clcpp/utils_common/type_name.hpp b/test_conformance/clcpp/utils_common/type_name.hpp new file mode 100644 index 00000000..c66f6e49 --- /dev/null +++ b/test_conformance/clcpp/utils_common/type_name.hpp @@ -0,0 +1,65 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_COMMON_TYPE_NAME_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_COMMON_TYPE_NAME_HPP + +#include "../common.hpp" + +// Returns type name (in OpenCL device). +// cl_uint - "uint", cl_float2 -> "float2" +template +std::string type_name() +{ + return "unknown"; +} + +#define ADD_TYPE_NAME(Type, str) \ + template<> \ + std::string type_name() \ + { \ + return #str; \ + } + +#define ADD_TYPE_NAME2(Type) \ + ADD_TYPE_NAME(cl_ ## Type, Type) + +#define ADD_TYPE_NAME3(Type, x) \ + ADD_TYPE_NAME2(Type ## x) + +#define ADD_TYPE_NAMES(Type) \ + ADD_TYPE_NAME2(Type) \ + ADD_TYPE_NAME3(Type, 2) \ + ADD_TYPE_NAME3(Type, 4) \ + ADD_TYPE_NAME3(Type, 8) \ + ADD_TYPE_NAME3(Type, 16) + +ADD_TYPE_NAMES(char) +ADD_TYPE_NAMES(uchar) +ADD_TYPE_NAMES(short) +ADD_TYPE_NAMES(ushort) +ADD_TYPE_NAMES(int) +ADD_TYPE_NAMES(uint) +ADD_TYPE_NAMES(long) +ADD_TYPE_NAMES(ulong) +ADD_TYPE_NAMES(float) +ADD_TYPE_NAMES(double) + +#undef ADD_TYPE_NAMES +#undef ADD_TYPE_NAME3 +#undef ADD_TYPE_NAME2 +#undef ADD_TYPE_NAME + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_COMMON_TYPE_NAME_HPP diff --git a/test_conformance/clcpp/utils_common/type_supported.hpp b/test_conformance/clcpp/utils_common/type_supported.hpp new file mode 100644 index 00000000..8d4f721b --- /dev/null +++ b/test_conformance/clcpp/utils_common/type_supported.hpp @@ -0,0 +1,106 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_COMMON_TYPE_SUPPORTED_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_COMMON_TYPE_SUPPORTED_HPP + +#include "../common.hpp" + +// Returns true if type is supported by device; otherwise - false; +template +bool type_supported(cl_device_id device) +{ + (void) device; + return false; +} + +#define ADD_SUPPORTED_TYPE(Type) \ + template<> \ + bool type_supported(cl_device_id device) \ + { \ + (void) device; \ + return true; \ + } + +ADD_SUPPORTED_TYPE(cl_char) +ADD_SUPPORTED_TYPE(cl_uchar) +ADD_SUPPORTED_TYPE(cl_short) +ADD_SUPPORTED_TYPE(cl_ushort) +ADD_SUPPORTED_TYPE(cl_int) +ADD_SUPPORTED_TYPE(cl_uint) + +// ulong +template<> +bool type_supported(cl_device_id device) +{ + // long types do not have to be supported in EMBEDDED_PROFILE. + char profile[128]; + int error; + + error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL); + if (error != CL_SUCCESS) + { + log_error("ERROR: clGetDeviceInfo failed with CL_DEVICE_PROFILE\n"); + return false; + } + + if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0) + return is_extension_available(device, "cles_khr_int64"); + + return true; +} +// long +template<> +bool type_supported(cl_device_id device) +{ + return type_supported(device); +} +ADD_SUPPORTED_TYPE(cl_float) +// double +template<> +bool type_supported(cl_device_id device) +{ + return is_extension_available(device, "cl_khr_fp64"); +} + +#define ADD_SUPPORTED_VEC_TYPE1(Type, n) \ + template<> \ + bool type_supported(cl_device_id device) \ + { \ + return type_supported(device); \ + } + +#define ADD_SUPPORTED_VEC_TYPE2(Type) \ + ADD_SUPPORTED_VEC_TYPE1(Type, 2) \ + ADD_SUPPORTED_VEC_TYPE1(Type, 4) \ + ADD_SUPPORTED_VEC_TYPE1(Type, 8) \ + ADD_SUPPORTED_VEC_TYPE1(Type, 16) + +ADD_SUPPORTED_VEC_TYPE2(cl_char) +ADD_SUPPORTED_VEC_TYPE2(cl_uchar) +ADD_SUPPORTED_VEC_TYPE2(cl_short) +ADD_SUPPORTED_VEC_TYPE2(cl_ushort) +ADD_SUPPORTED_VEC_TYPE2(cl_int) +ADD_SUPPORTED_VEC_TYPE2(cl_uint) +ADD_SUPPORTED_VEC_TYPE2(cl_long) +ADD_SUPPORTED_VEC_TYPE2(cl_ulong) +ADD_SUPPORTED_VEC_TYPE2(cl_float) +// ADD_SUPPORTED_VEC_TYPE2(cl_double) + +#undef ADD_SUPPORTED_VEC_TYPE2 +#undef ADD_SUPPORTED_VEC_TYPE1 +#undef ADD_SUPPORTED_TYPE + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_COMMON_TYPE_SUPPORTED_HPP diff --git a/test_conformance/clcpp/utils_common/vector_size.hpp b/test_conformance/clcpp/utils_common/vector_size.hpp new file mode 100644 index 00000000..4817506e --- /dev/null +++ b/test_conformance/clcpp/utils_common/vector_size.hpp @@ -0,0 +1,61 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_COMMON_VECTOR_SIZE_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_COMMON_VECTOR_SIZE_HPP + +#include "../common.hpp" + +// Returns 1 if Type is a scalar type; otherwise if it's a vector type, +// it returns number of components in that Type. +template +struct vector_size +{ + const static size_t value = 1; +}; + +#define ADD_VECTOR_SIZE_TYPE(Type, n) \ + template<> \ + struct vector_size \ + { \ + const static size_t value = n; \ + }; + +#define ADD_VECTOR_SIZE_TYPES(Type) \ + template<> \ + struct vector_size \ + { \ + const static size_t value = 1; \ + }; \ + ADD_VECTOR_SIZE_TYPE(Type, 2) \ + ADD_VECTOR_SIZE_TYPE(Type, 4) \ + ADD_VECTOR_SIZE_TYPE(Type, 8) \ + ADD_VECTOR_SIZE_TYPE(Type, 16) + +ADD_VECTOR_SIZE_TYPES(cl_char) +ADD_VECTOR_SIZE_TYPES(cl_uchar) +ADD_VECTOR_SIZE_TYPES(cl_short) +ADD_VECTOR_SIZE_TYPES(cl_ushort) +ADD_VECTOR_SIZE_TYPES(cl_int) +ADD_VECTOR_SIZE_TYPES(cl_uint) +ADD_VECTOR_SIZE_TYPES(cl_long) +ADD_VECTOR_SIZE_TYPES(cl_ulong) +ADD_VECTOR_SIZE_TYPES(cl_float) +ADD_VECTOR_SIZE_TYPES(cl_double) + +#undef ADD_VECTOR_SIZE_TYPES +#undef ADD_VECTOR_SIZE_TYPE + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_COMMON_VECTOR_SIZE_HPP diff --git a/test_conformance/clcpp/utils_test/binary.hpp b/test_conformance/clcpp/utils_test/binary.hpp new file mode 100644 index 00000000..5ff35c91 --- /dev/null +++ b/test_conformance/clcpp/utils_test/binary.hpp @@ -0,0 +1,308 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_TEST_BINARY_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_TEST_BINARY_HPP + +#include +#include +#include +#include + +#include "../common.hpp" + +#include "detail/base_func_type.hpp" +#include "generate_inputs.hpp" +#include "compare.hpp" + +template +struct binary_func : public detail::base_func_type +{ + typedef IN1 in1_type; + typedef IN2 in2_type; + typedef OUT1 out_type; + + virtual ~binary_func() {}; + virtual std::string str() = 0; + + std::string decl_str() + { + return type_name() + "(" + type_name() + ", " + type_name() + ")"; + } + + bool is_in1_bool() + { + return false; + } + + bool is_in2_bool() + { + return false; + } + + IN1 min1() + { + return detail::get_min(); + } + + IN1 max1() + { + return detail::get_max(); + } + + IN2 min2() + { + return detail::get_min(); + } + + IN2 max2() + { + return detail::get_max(); + } + + std::vector in1_special_cases() + { + return { }; + } + + std::vector in2_special_cases() + { + return { }; + } + + template + typename make_vector_type::value>::type + delta(const IN1& in1, const IN2& in2, const T& expected) + { + typedef + typename make_vector_type::value>::type + delta_vector_type; + // Take care of unused variable warning + (void) in1; + (void) in2; + auto e = detail::make_value(1e-3); + return detail::multiply(e, expected); + } +}; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template +std::string generate_kernel_binary(func_type func) +{ + std::string in1_value = "input1[gid]"; + if(func.is_in1_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + in1_value = "(input1[gid] != (int" + i + ")(0))"; + } + std::string in2_value = "input2[gid]"; + if(func.is_in2_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + in2_value = "(input2[gid] != (int" + i + ")(0))"; + } + std::string function_call = func.str() + "(" + in1_value + ", " + in2_value + ")"; + if(func.is_out_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + function_call = "convert_int" + i + "(" + func.str() + "(" + in1_value + ", " + in2_value + "))"; + } + return + "__kernel void " + func.get_kernel_name() + "(global " + type_name() + " *input1,\n" + " global " + type_name() + " *input2,\n" + " global " + type_name() + " *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = " + function_call + ";\n" + "}\n"; +} +#else +template +std::string generate_kernel_binary(func_type func) +{ + std::string headers = func.headers(); + std::string in1_value = "input1[gid]"; + if(func.is_in1_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + in1_value = "(input1[gid] != (int" + i + ")(0))"; + } + std::string in2_value = "input2[gid]"; + if(func.is_in2_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + in2_value = "(input2[gid] != (int" + i + ")(0))"; + } + std::string function_call = func.str() + "(" + in1_value + ", " + in2_value + ")"; + if(func.is_out_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + function_call = "convert_cast(" + func.str() + "(" + in1_value + ", " + in2_value + "))"; + } + if(func.is_out_bool() || func.is_in1_bool() || func.is_in2_bool()) + { + if(headers.find("#include ") == std::string::npos) + { + headers += "#include \n"; + } + } + return + "" + func.defs() + + "" + headers + + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void " + func.get_kernel_name() + "(global_ptr<" + type_name() + "[]> input1,\n" + " global_ptr<" + type_name() + "[]> input2,\n" + " global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = " + function_call + ";\n" + "}\n"; +} +#endif + +template +bool verify_binary(const std::vector &in1, + const std::vector &in2, + const std::vector &out, + binary_op op) +{ + for(size_t i = 0; i < in1.size(); i++) + { + auto expected = op(in1[i], in2[i]); + if(!are_equal(expected, out[i], op.delta(in1[i], in2[i], expected), op)) + { + print_error_msg(expected, out[i], i, op); + return false; + } + } + return true; +} + +template +int test_binary_func(cl_device_id device, cl_context context, cl_command_queue queue, size_t count, binary_op op) +{ + cl_mem buffers[3]; + cl_program program; + cl_kernel kernel; + size_t work_size[1]; + int err; + + typedef typename binary_op::in1_type INPUT1; + typedef typename binary_op::in2_type INPUT2; + typedef typename binary_op::out_type OUTPUT; + + // Don't run test for unsupported types + if(!(type_supported(device) + && type_supported(device) + && type_supported(device))) + { + return CL_SUCCESS; + } + + std::string code_str = generate_kernel_binary(op); + std::string kernel_name = op.get_kernel_name(); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name, "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(err) +#endif + + std::vector in1_spec_cases = op.in1_special_cases(); + std::vector in2_spec_cases = op.in2_special_cases(); + prepare_special_cases(in1_spec_cases, in2_spec_cases); + std::vector input1 = generate_input(count, op.min1(), op.max1(), in1_spec_cases); + std::vector input2 = generate_input(count, op.min2(), op.max2(), in2_spec_cases); + std::vector output = generate_output(count); + + buffers[0] = clCreateBuffer( + context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(INPUT1) * input1.size(), NULL, &err + ); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + buffers[1] = clCreateBuffer( + context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(INPUT2) * input2.size(), NULL, &err + ); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + buffers[2] = clCreateBuffer( + context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(OUTPUT) * output.size(), NULL, &err + ); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(INPUT1) * input1.size(), + static_cast(input1.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer") + + err = clEnqueueWriteBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(INPUT2) * input2.size(), + static_cast(input2.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer") + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + err |= clSetKernelArg(kernel, 2, sizeof(buffers[2]), &buffers[2]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + work_size[0] = count; + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[2], CL_TRUE, 0, sizeof(OUTPUT) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + if (!verify_binary(input1, input2, output, op)) + { + RETURN_ON_ERROR_MSG(-1, + "test_%s %s(%s, %s) failed", op.str().c_str(), + type_name().c_str(), type_name().c_str(), type_name().c_str() + ); + } + log_info( + "test_%s %s(%s, %s) passed\n", op.str().c_str(), + type_name().c_str(), type_name().c_str(), type_name().c_str() + ); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_TEST_BINARY_HPP diff --git a/test_conformance/clcpp/utils_test/compare.hpp b/test_conformance/clcpp/utils_test/compare.hpp new file mode 100644 index 00000000..a22b88fd --- /dev/null +++ b/test_conformance/clcpp/utils_test/compare.hpp @@ -0,0 +1,161 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_TEST_COMPARE_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_TEST_COMPARE_HPP + +#include +#include +#include +#include + +#include + +#include "../common.hpp" + +// Checks if x is equal to y. +template +inline bool are_equal(const type& x, + const type& y, + const delta_type& delta, + op_type op, + typename std::enable_if< + is_vector_type::value + && std::is_integral::type>::value + >::type* = 0) +{ + (void) delta; + for(size_t i = 0; i < vector_size::value; i++) + { + if(op.is_out_bool()) + { + if(!((x.s[i] != 0) == (y.s[i] != 0))) + { + return false; + } + } + else if(!(x.s[i] == y.s[i])) + { + return false; + } + } + return true; +} + +template +inline bool are_equal(const type& x, + const type& y, + const delta_type& delta, + op_type op, + typename std::enable_if< + !is_vector_type::value + && std::is_integral::value + >::type* = 0) +{ + (void) delta; + if(op.is_out_bool()) + { + if(!((x != 0) == (y != 0))) + { + return false; + } + } + return x == y; +} + +template +inline bool are_equal(const type& x, + const type1& y, + const type2& delta, + op_type op, + typename std::enable_if< + !is_vector_type::value + && std::is_floating_point::value + >::type* = 0) +{ + // x - expected + // y - result + + // INFO: + // Whe don't care about subnormal values in OpenCL C++ tests + if(std::fpclassify(static_cast(x)) == FP_SUBNORMAL || std::fpclassify(y) == FP_SUBNORMAL) + { + return true; + } + + // both are NaN + if((std::isnan)(static_cast(x)) && (std::isnan)(y)) + { + return true; + } + // one is NaN + else if((std::isnan)(static_cast(x)) || (std::isnan)(y)) + { + return false; + } + + // Check for perfect match, it also covers inf, -inf + if(static_cast(x) != y) + { + // Check if values are close + if(std::abs(static_cast(x) - y) > (std::max)(std::numeric_limits::epsilon(), std::abs(delta))) + { + return false; + } + // Check ulp + if(op.use_ulp()) + { + return !(std::abs(Ulp_Error(x, y)) > op.ulp()); + } + } + return true; +} + +template +inline bool are_equal(const type& x, + const type1& y, + const type2& delta, + op_type op, + typename std::enable_if< + is_vector_type::value + && std::is_floating_point::type>::value + >::type* = 0) +{ + // x - expected + // y - result + for(size_t i = 0; i < vector_size::value; i++) + { + if(!are_equal(x.s[i], y.s[i], delta.s[i], op)) + { + return false; + } + } + return true; +} + +template +inline void print_error_msg(const type& expected, const type1& result, size_t i, func op) +{ + log_error( + "ERROR: test_%s %s failed. Error at %lu: Expected: %s, got: %s\n", + op.str().c_str(), + op.decl_str().c_str(), + i, + format_value(expected).c_str(), + format_value(result).c_str() + ); +} + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_TEST_COMPARE_HPP diff --git a/test_conformance/clcpp/utils_test/detail/base_func_type.hpp b/test_conformance/clcpp/utils_test/detail/base_func_type.hpp new file mode 100644 index 00000000..92e375d0 --- /dev/null +++ b/test_conformance/clcpp/utils_test/detail/base_func_type.hpp @@ -0,0 +1,112 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_TEST_DETAIL_BASE_FUNC_TYPE_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_TEST_DETAIL_BASE_FUNC_TYPE_HPP + +#include +#include +#include +#include + +#include + +#include "../../common.hpp" + +#include "vec_helpers.hpp" + +namespace detail +{ + +template +struct base_func_type +{ + virtual ~base_func_type() {}; + + // Returns function name + virtual std::string str() = 0; + + // Returns name of the test kernel for that function + virtual std::string get_kernel_name() + { + std::string kn = this->str(); + replace_all(kn, "::", "_"); + return "test_" + kn; + } + + // Returns required defines and pragmas. + virtual std::string defs() + { + return ""; + } + + // Returns required OpenCL C++ headers. + virtual std::string headers() + { + return ""; + } + + // Return true if OUT1 type in OpenCL kernel should be treated + // as bool type; false otherwise. + bool is_out_bool() + { + return false; + } + + // Max ULP error, that is error should be raised when + // if Ulp_Error(result, expected) > ulp() + float ulp() + { + return 0.0f; + } + + // Should we check ULP error when verifing if the result is + // correct? + // + // (This effects how are_equal() function works, + // it may not have effect if verify() method in derived + // class does not use are_equal() function.) + // + // Only for FP numbers/vectors + bool use_ulp() + { + return true; + } + + // Max error. Error should be raised if + // abs(result - expected) > delta(.., expected) + // + // Default value: 0.001 * expected + // + // (This effects how are_equal() function works, + // it may not have effect if verify() method in derived + // class does not use are_equal() function.) + // + // Only for FP numbers/vectors + template + typename make_vector_type::value>::type + delta(const T& expected) + { + typedef + typename make_vector_type::value>::type + delta_vector_type; + auto e = detail::make_value(1e-3); + return detail::multiply(e, expected); + } +}; + +} // detail namespace + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_TEST_DETAIL_BASE_FUNC_TYPE_HPP diff --git a/test_conformance/clcpp/utils_test/detail/vec_helpers.hpp b/test_conformance/clcpp/utils_test/detail/vec_helpers.hpp new file mode 100644 index 00000000..05df42aa --- /dev/null +++ b/test_conformance/clcpp/utils_test/detail/vec_helpers.hpp @@ -0,0 +1,104 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_TEST_DETAIL_VEC_HELPERS_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_TEST_DETAIL_VEC_HELPERS_HPP + +#include +#include +#include +#include + +#include + +#include "../../common.hpp" + +namespace detail +{ + +template +T make_value(typename scalar_type::type x, typename std::enable_if::value>::type* = 0) +{ + T value; + for(size_t i = 0; i < vector_size::value; i++) + { + value.s[i] = x; + } + return value; +} + +template +T make_value(T x, typename std::enable_if::value>::type* = 0) +{ + return x; +} + +template +result_type multiply(const IN1& x, const IN2& y, typename std::enable_if::value>::type* = 0) +{ + static_assert( + (vector_size::value == vector_size::value) + && (vector_size::value == vector_size::value), + "Vector sizes must be the same." + ); + typedef typename scalar_type::type SCALAR; + result_type value; + for(size_t i = 0; i < vector_size::value; i++) + { + value.s[i] = static_cast(x.s[i]) * static_cast(y.s[i]); + } + return value; +} + +template +result_type multiply(const IN1& x, const IN2& y, typename std::enable_if::value>::type* = 0) +{ + static_assert( + !is_vector_type::value && !is_vector_type::value, + "IN1 and IN2 must be scalar types" + ); + return static_cast(x) * static_cast(y); +} + +template +T get_min() +{ + typedef typename scalar_type::type SCALAR; + return make_value((std::numeric_limits::min)()); +} + +template +T get_max() +{ + typedef typename scalar_type::type SCALAR; + return make_value((std::numeric_limits::max)()); +} + +template +T get_part_max(typename scalar_type::type x) +{ + typedef typename scalar_type::type SCALAR; + return make_value((std::numeric_limits::max)() / x); +} + +template +T def_limit(typename scalar_type::type x) +{ + return make_value(x); +} + +} // detail namespace + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_TEST_DETAIL_VEC_HELPERS_HPP diff --git a/test_conformance/clcpp/utils_test/generate_inputs.hpp b/test_conformance/clcpp/utils_test/generate_inputs.hpp new file mode 100644 index 00000000..bb0d7506 --- /dev/null +++ b/test_conformance/clcpp/utils_test/generate_inputs.hpp @@ -0,0 +1,331 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_TEST_GENERATE_INPUTS_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_TEST_GENERATE_INPUTS_HPP + +#include +#include +#include +#include + +#include + +#include "../common.hpp" + +template +std::vector generate_input(size_t count, + const type& min, + const type& max, + const std::vector special_cases, + typename std::enable_if< + is_vector_type::value + && std::is_integral::type>::value + // std::uniform_int_distribution<> does not work in VS2015 for cl_uchar and cl_char, + // because VS2015 thinks that use cl_int, because VS2015 thinks cl_uchar cl_char are + // not int types + && !(std::is_same::type, cl_uchar>::value + || std::is_same::type, cl_char>::value) + >::type* = 0) +{ + typedef typename scalar_type::type SCALAR; + const size_t vec_size = vector_size::value; + + std::vector input(count); + std::random_device rd; + std::mt19937 gen(rd()); + std::vector> dists(vec_size); + for(size_t i = 0; i < vec_size; i++) + { + dists[i] = std::uniform_int_distribution(min.s[i], max.s[i]); + } + for(auto& i : input) + { + for(size_t j = 0; j < vec_size; j++) + { + i.s[j] = dists[j](gen); + } + } + + input.insert(input.begin(), special_cases.begin(), special_cases.end()); + input.resize(count); + return input; +} + +template +std::vector generate_input(size_t count, + const type& min, + const type& max, + const std::vector special_cases, + typename std::enable_if< + is_vector_type::value + && std::is_integral::type>::value + // std::uniform_int_distribution<> does not work in VS2015 for cl_uchar and cl_char, + // because VS2015 thinks that use cl_int, because VS2015 thinks cl_uchar cl_char are + // not int types + && (std::is_same::type, cl_uchar>::value + || std::is_same::type, cl_char>::value) + >::type* = 0) +{ + typedef typename scalar_type::type SCALAR; + const size_t vec_size = vector_size::value; + + std::vector input(count); + std::random_device rd; + std::mt19937 gen(rd()); + std::vector> dists(vec_size); + for(size_t i = 0; i < vec_size; i++) + { + dists[i] = std::uniform_int_distribution( + static_cast(min.s[i]), + static_cast(max.s[i]) + ); + } + for(auto& i : input) + { + for(size_t j = 0; j < vec_size; j++) + { + i.s[j] = static_cast(dists[j](gen)); + } + } + + input.insert(input.begin(), special_cases.begin(), special_cases.end()); + input.resize(count); + return input; +} + + +template +std::vector generate_input(size_t count, + const type& min, + const type& max, + const std::vector special_cases, + typename std::enable_if< + !is_vector_type::value + && std::is_integral::value + // std::uniform_int_distribution<> does not work in VS2015 for cl_uchar and cl_char, + // because VS2015 thinks that use cl_int, because VS2015 thinks cl_uchar cl_char are + // not int types + && !(std::is_same::value || std::is_same::value) + >::type* = 0) +{ + std::vector input(count); + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(min, max); + for(auto& i : input) + { + i = dis(gen); + } + + input.insert(input.begin(), special_cases.begin(), special_cases.end()); + input.resize(count); + return input; +} + +template +std::vector generate_input(size_t count, + const type& min, + const type& max, + const std::vector special_cases, + typename std::enable_if< + !is_vector_type::value + && std::is_integral::value + // std::uniform_int_distribution<> does not work in VS2015 for cl_uchar and cl_char, + // because VS2015 thinks that use cl_int, because VS2015 thinks cl_uchar cl_char are + // not int types + && (std::is_same::value || std::is_same::value) + >::type* = 0) +{ + std::vector input(count); + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis( + static_cast(min), static_cast(max) + ); + for(auto& i : input) + { + i = static_cast(dis(gen)); + } + + input.insert(input.begin(), special_cases.begin(), special_cases.end()); + input.resize(count); + return input; +} + +template +std::vector generate_input(size_t count, + const type& min, + const type& max, + const std::vector special_cases, + typename std::enable_if< + is_vector_type::value + && std::is_floating_point::type>::value + >::type* = 0) +{ + typedef typename scalar_type::type SCALAR; + const size_t vec_size = vector_size::value; + + std::vector input(count); + std::random_device rd; + std::mt19937 gen(rd()); + std::vector> dists(vec_size); + for(size_t i = 0; i < vec_size; i++) + { + // Fatal error + if(std::fpclassify(max.s[i]) == FP_SUBNORMAL || std::fpclassify(min.s[i]) == FP_SUBNORMAL) + { + log_error("ERROR: min and max value for input generation CAN NOT BE subnormal\n"); + } + dists[i] = std::uniform_real_distribution(min.s[i], max.s[i]); + } + for(auto& i : input) + { + for(size_t j = 0; j < vec_size; j++) + { + SCALAR x = dists[j](gen); + while(std::fpclassify(x) == FP_SUBNORMAL) + { + x = dists[j](gen); + } + i.s[j] = x; + } + } + + input.insert(input.begin(), special_cases.begin(), special_cases.end()); + input.resize(count); + return input; +} + +template +std::vector generate_input(size_t count, + const type& min, + const type& max, + const std::vector special_cases, + typename std::enable_if< + !is_vector_type::value + && std::is_floating_point::value + >::type* = 0) +{ + // Fatal error + if(std::fpclassify(max) == FP_SUBNORMAL || std::fpclassify(min) == FP_SUBNORMAL) + { + log_error("ERROR: min and max value for input generation CAN NOT BE subnormal\n"); + } + std::vector input(count); + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(min, max); + for(auto& i : input) + { + type x = dis(gen); + while(std::fpclassify(x) == FP_SUBNORMAL) + { + x = dis(gen); + } + i = x; + } + + input.insert(input.begin(), special_cases.begin(), special_cases.end()); + input.resize(count); + return input; +} + +template +std::vector generate_output(size_t count, + typename scalar_type::type svalue = typename scalar_type::type(0), + typename std::enable_if::value>::type* = 0) +{ + type value; + for(size_t i = 0; i < vector_size::value; i++) + value.s[i] = svalue; + return std::vector(count, value); +} + +template +std::vector generate_output(size_t count, + type svalue = type(0), + typename std::enable_if::value>::type* = 0) +{ + return std::vector(count, svalue); +} + +template +void prepare_special_cases(std::vector& in1_spec_cases, std::vector& in2_spec_cases) +{ + if(in1_spec_cases.empty() || in2_spec_cases.empty()) + { + return; + } + + size_t new_size = in1_spec_cases.size() * in2_spec_cases.size(); + std::vector new_in1(new_size); + std::vector new_in2(new_size); + for(size_t i = 0; i < in1_spec_cases.size(); i++) + { + for(size_t j = 0; j < in2_spec_cases.size(); j++) + { + new_in1[(i * in2_spec_cases.size()) + j] = in1_spec_cases[i]; + new_in2[(i * in2_spec_cases.size()) + j] = in2_spec_cases[j]; + } + } + in1_spec_cases = new_in1; + in2_spec_cases = new_in2; +} + +template +void prepare_special_cases(std::vector& in1_spec_cases, + std::vector& in2_spec_cases, + std::vector& in3_spec_cases) +{ + if(in3_spec_cases.empty()) + { + return prepare_special_cases(in1_spec_cases, in2_spec_cases); + } + else if (in2_spec_cases.empty()) + { + return prepare_special_cases(in1_spec_cases, in3_spec_cases); + } + else if (in1_spec_cases.empty()) + { + return prepare_special_cases(in2_spec_cases, in3_spec_cases); + } + + size_t new_size = in1_spec_cases.size() * in2_spec_cases.size() * in3_spec_cases.size(); + std::vector new_in1(new_size); + std::vector new_in2(new_size); + std::vector new_in3(new_size); + for(size_t i = 0; i < in1_spec_cases.size(); i++) + { + for(size_t j = 0; j < in2_spec_cases.size(); j++) + { + for(size_t k = 0; k < in3_spec_cases.size(); k++) + { + size_t idx = + (i * in2_spec_cases.size() * in3_spec_cases.size()) + + (j * in3_spec_cases.size()) + + k; + new_in1[idx] = in1_spec_cases[i]; + new_in2[idx] = in2_spec_cases[j]; + new_in3[idx] = in3_spec_cases[k]; + } + } + } + in1_spec_cases = new_in1; + in2_spec_cases = new_in2; + in3_spec_cases = new_in3; +} + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_TEST_GENERATE_INPUTS_HPP diff --git a/test_conformance/clcpp/utils_test/ternary.hpp b/test_conformance/clcpp/utils_test/ternary.hpp new file mode 100644 index 00000000..342681e1 --- /dev/null +++ b/test_conformance/clcpp/utils_test/ternary.hpp @@ -0,0 +1,368 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_TEST_TERNARY_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_TEST_TERNARY_HPP + +#include +#include +#include +#include + +#include "../common.hpp" + +#include "detail/base_func_type.hpp" +#include "generate_inputs.hpp" +#include "compare.hpp" + +template +struct ternary_func : public detail::base_func_type +{ + typedef IN1 in1_type; + typedef IN2 in2_type; + typedef IN3 in3_type; + typedef OUT1 out_type; + + virtual ~ternary_func() {}; + virtual std::string str() = 0; + + std::string decl_str() + { + return type_name() + "(" + type_name() + ", " + type_name()+ ", " + type_name() + ")"; + } + + bool is_in1_bool() + { + return false; + } + + bool is_in2_bool() + { + return false; + } + + bool is_in3_bool() + { + return false; + } + + IN1 min1() + { + return detail::get_min(); + } + + IN1 max1() + { + return detail::get_max(); + } + + IN2 min2() + { + return detail::get_min(); + } + + IN2 max2() + { + return detail::get_max(); + } + + IN3 min3() + { + return detail::get_min(); + } + + IN3 max3() + { + return detail::get_max(); + } + + std::vector in1_special_cases() + { + return { }; + } + + std::vector in2_special_cases() + { + return { }; + } + + std::vector in3_special_cases() + { + return { }; + } + + template + typename make_vector_type::value>::type + delta(const IN1& in1, const IN2& in2, const IN3& in3, const T& expected) + { + typedef + typename make_vector_type::value>::type + delta_vector_type; + // Take care of unused variable warning + (void) in1; + (void) in2; + (void) in3; + auto e = detail::make_value(1e-3); + return detail::multiply(e, expected); + } +}; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template +std::string generate_kernel_ternary(func_type func) +{ + std::string in1_value = "input1[gid]"; + if(func.is_in1_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + in1_value = "(input1[gid] != (int" + i + ")(0))"; + } + std::string in2_value = "input2[gid]"; + if(func.is_in2_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + in2_value = "(input2[gid] != (int" + i + ")(0))"; + } + std::string in3_value = "input3[gid]"; + if(func.is_in3_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + in3_value = "(input3[gid] != (int" + i + ")(0))"; + } + std::string function_call = func.str() + "(" + in1_value + ", " + in2_value + ", " + in3_value + ")"; + if(func.is_out_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + function_call = "convert_int" + i + "(" + func.str() + "(" + in1_value + ", " + in2_value + ", " + in3_value + "))"; + } + return + "__kernel void " + func.get_kernel_name() + "(global " + type_name() + " *input1,\n" + " global " + type_name() + " *input2,\n" + " global " + type_name() + " *input3,\n" + " global " + type_name() + " *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = " + function_call + ";\n" + "}\n"; +} +#else +template +std::string generate_kernel_ternary(func_type func) +{ + std::string headers = func.headers(); + std::string in1_value = "input1[gid]"; + if(func.is_in1_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + in1_value = "(input1[gid] != (int" + i + ")(0))"; + } + std::string in2_value = "input2[gid]"; + if(func.is_in2_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + in2_value = "(input2[gid] != (int" + i + ")(0))"; + } + std::string in3_value = "input3[gid]"; + if(func.is_in3_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + in3_value = "(input3[gid] != (int" + i + ")(0))"; + } + std::string function_call = func.str() + "(" + in1_value + ", " + in2_value + ", " + in3_value + ")"; + if(func.is_out_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + function_call = "convert_cast(" + func.str() + "(" + in1_value + ", " + in2_value + ", " + in3_value + "))"; + } + if(func.is_out_bool() || func.is_in1_bool() || func.is_in2_bool() || func.is_in3_bool()) + { + if(headers.find("#include ") == std::string::npos) + { + headers += "#include \n"; + } + } + return + "" + func.defs() + + "" + headers + + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void " + func.get_kernel_name() + "(global_ptr<" + type_name() + "[]> input1,\n" + " global_ptr<" + type_name() + "[]> input2,\n" + " global_ptr<" + type_name() + "[]> input3,\n" + " global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = " + function_call + ";\n" + "}\n"; +} +#endif + +template +bool verify_ternary(const std::vector &in1, + const std::vector &in2, + const std::vector &in3, + const std::vector &out, + ternary_op op) +{ + for(size_t i = 0; i < in1.size(); i++) + { + auto expected = op(in1[i], in2[i], in3[i]); + if(!are_equal(expected, out[i], op.delta(in1[i], in2[i], in3[i], expected), op)) + { + print_error_msg(expected, out[i], i, op); + return false; + } + } + return true; +} + +template +int test_ternary_func(cl_device_id device, cl_context context, cl_command_queue queue, size_t count, ternary_op op) +{ + cl_mem buffers[4]; + cl_program program; + cl_kernel kernel; + size_t work_size[1]; + int err; + + typedef typename ternary_op::in1_type INPUT1; + typedef typename ternary_op::in2_type INPUT2; + typedef typename ternary_op::in3_type INPUT3; + typedef typename ternary_op::out_type OUTPUT; + + // Don't run test for unsupported types + if(!(type_supported(device) + && type_supported(device) + && type_supported(device) + && type_supported(device))) + { + return CL_SUCCESS; + } + + std::string code_str = generate_kernel_ternary(op); + std::string kernel_name = op.get_kernel_name(); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name, "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(err) +#endif + + std::vector in1_spec_cases = op.in1_special_cases(); + std::vector in2_spec_cases = op.in2_special_cases(); + std::vector in3_spec_cases = op.in3_special_cases(); + prepare_special_cases(in1_spec_cases, in2_spec_cases, in3_spec_cases); + std::vector input1 = generate_input(count, op.min1(), op.max1(), in1_spec_cases); + std::vector input2 = generate_input(count, op.min2(), op.max2(), in2_spec_cases); + std::vector input3 = generate_input(count, op.min3(), op.max3(), in3_spec_cases); + std::vector output = generate_output(count); + + buffers[0] = clCreateBuffer( + context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(INPUT1) * input1.size(), NULL, &err + ); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + buffers[1] = clCreateBuffer( + context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(INPUT2) * input2.size(), NULL, &err + ); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + buffers[2] = clCreateBuffer( + context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(INPUT3) * input3.size(), NULL, &err + ); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + buffers[3] = clCreateBuffer( + context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(OUTPUT) * output.size(), NULL, &err + ); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(INPUT1) * input1.size(), + static_cast(input1.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(INPUT2) * input2.size(), + static_cast(input2.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[2], CL_TRUE, 0, sizeof(INPUT3) * input3.size(), + static_cast(input3.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + err |= clSetKernelArg(kernel, 2, sizeof(buffers[2]), &buffers[2]); + err |= clSetKernelArg(kernel, 3, sizeof(buffers[3]), &buffers[3]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + work_size[0] = count; + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[3], CL_TRUE, 0, sizeof(OUTPUT) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + if (!verify_ternary(input1, input2, input3, output, op)) + { + RETURN_ON_ERROR_MSG(-1, + "test_%s %s(%s, %s, %s) failed", op.str().c_str(), + type_name().c_str(), + type_name().c_str(), + type_name().c_str(), + type_name().c_str() + ); + } + log_info( + "test_%s %s(%s, %s, %s) passed\n", op.str().c_str(), + type_name().c_str(), + type_name().c_str(), + type_name().c_str(), + type_name().c_str() + ); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_TEST_TERNARY_HPP diff --git a/test_conformance/clcpp/utils_test/unary.hpp b/test_conformance/clcpp/utils_test/unary.hpp new file mode 100644 index 00000000..2dbc6471 --- /dev/null +++ b/test_conformance/clcpp/utils_test/unary.hpp @@ -0,0 +1,261 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_UTILS_TEST_UNARY_HPP +#define TEST_CONFORMANCE_CLCPP_UTILS_TEST_UNARY_HPP + +#include +#include +#include +#include + +#include "../common.hpp" + +#include "detail/base_func_type.hpp" +#include "generate_inputs.hpp" +#include "compare.hpp" + +template +struct unary_func : public detail::base_func_type +{ + typedef IN1 in_type; + typedef OUT1 out_type; + + virtual ~unary_func() {}; + virtual std::string str() = 0; + + // Return string with function type, for example: int(float). + std::string decl_str() + { + return type_name() + "(" + type_name() + ")"; + } + + // Return true if IN1 type in OpenCL kernel should be treated + // as bool type; false otherwise. + bool is_in1_bool() + { + return false; + } + + // Return min value that can be used as a first argument. + IN1 min1() + { + return detail::get_min(); + } + + // Return max value that can be used as a first argument. + IN1 max1() + { + return detail::get_max(); + } + + // This returns a list of special cases input values we want to + // test. + std::vector in_special_cases() + { + return { }; + } + + // Max error. Error should be raised if + // abs(result - expected) > delta(.., expected) + // + // Default value: 0.001 * expected + // + // (This effects how are_equal() function works, + // it may not have effect if verify() method in derived + // class does not use are_equal() function.) + // + // Only for FP numbers/vectors + template + typename make_vector_type::value>::type + delta(const IN1& in1, const T& expected) + { + typedef + typename make_vector_type::value>::type + delta_vector_type; + // Take care of unused variable warning + (void) in1; + auto e = detail::make_value(1e-3); + return detail::multiply(e, expected); + } +}; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template +std::string generate_kernel_unary(func_type func) +{ + std::string in1_value = "input[gid]"; + // Convert uintN to boolN values + if(func.is_in1_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + in1_value = "(input[gid] != (int" + i + ")(0))"; + } + std::string function_call = func.str() + "(" + in1_value + ");"; + // Convert boolN result of funtion func_type to uintN + if(func.is_out_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + function_call = "convert_int" + i + "(" + func.str() + "(" + in1_value + "))"; + } + return + "__kernel void " + func.get_kernel_name() + "(global " + type_name() + " *input, global " + type_name() + " *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = " + function_call + ";\n" + "}\n"; +} +#else +template +std::string generate_kernel_unary(func_type func) +{ + std::string headers = func.headers(); + std::string in1_value = "input[gid]"; + if(func.is_in1_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + in1_value = "(input[gid] != (int" + i + ")(0))"; + } + std::string function_call = func.str() + "(" + in1_value + ")"; + if(func.is_out_bool()) + { + std::string i = vector_size::value == 1 ? "" : std::to_string(vector_size::value); + function_call = "convert_cast(" + func.str() + "(" + in1_value + "))"; + } + if(func.is_out_bool() || func.is_in1_bool()) + { + if(headers.find("#include ") == std::string::npos) + { + headers += "#include \n"; + } + } + return + "" + func.defs() + + "" + headers + + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void " + func.get_kernel_name() + "(global_ptr<" + type_name() + "[]> input," + "global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = " + function_call + ";\n" + "}\n"; +} +#endif + +template +bool verify_unary(const std::vector &in, const std::vector &out, unary_op op) +{ + for(size_t i = 0; i < in.size(); i++) + { + auto expected = op(in[i]); + if(!are_equal(expected, out[i], op.delta(in[i], expected), op)) + { + print_error_msg(expected, out[i], i, op); + return false; + } + } + return true; +} + +template +int test_unary_func(cl_device_id device, cl_context context, cl_command_queue queue, size_t count, unary_op op) +{ + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t work_size[1]; + int err; + + typedef typename unary_op::in_type INPUT; + typedef typename unary_op::out_type OUTPUT; + + // Don't run test for unsupported types + if(!(type_supported(device) && type_supported(device))) + { + return CL_SUCCESS; + } + + std::string code_str = generate_kernel_unary(op); + std::string kernel_name = op.get_kernel_name(); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name, "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(err) +#endif + + std::vector input = generate_input(count, op.min1(), op.max1(), op.in_special_cases()); + std::vector output = generate_output(count); + + buffers[0] = clCreateBuffer( + context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(INPUT) * input.size(), NULL, &err + ); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + buffers[1] = clCreateBuffer( + context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(OUTPUT) * output.size(), NULL, &err + ); + RETURN_ON_CL_ERROR(err, "clCreateBuffer") + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(INPUT) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + work_size[0] = count; + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(OUTPUT) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + if (!verify_unary(input, output, op)) + { + RETURN_ON_ERROR_MSG(-1, "test_%s %s(%s) failed", op.str().c_str(), type_name().c_str(), type_name().c_str()); + } + log_info("test_%s %s(%s) passed\n", op.str().c_str(), type_name().c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +#endif // TEST_CONFORMANCE_CLCPP_UTILS_TEST_UNARY_HPP diff --git a/test_conformance/clcpp/vload_vstore/CMakeLists.txt b/test_conformance/clcpp/vload_vstore/CMakeLists.txt new file mode 100644 index 00000000..0204dc5c --- /dev/null +++ b/test_conformance/clcpp/vload_vstore/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_VLOAD_VSTORE_FUNCS) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/vload_vstore/common.hpp b/test_conformance/clcpp/vload_vstore/common.hpp new file mode 100644 index 00000000..84cd539d --- /dev/null +++ b/test_conformance/clcpp/vload_vstore/common.hpp @@ -0,0 +1,81 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_COMMON_HPP +#define TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_COMMON_HPP + +#include +#include + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#include "half_utils.hpp" + +// Generates cl_half input +std::vector generate_half_input(size_t count, + const cl_float& min, + const cl_float& max, + const std::vector special_cases) +{ + std::vector input(count); + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(min, max); + for(auto& i : input) + { + i = float2half_rte(dis(gen)); + } + + input.insert(input.begin(), special_cases.begin(), special_cases.end()); + input.resize(count); + return input; +} + +// Generates input for vload_vstore tests, we can't just simply use function +// generate_input(...), because cl_half is typedef of cl_short (but generating +// cl_shorts and generating cl_halfs are different operations). +template +std::vector vload_vstore_generate_input(size_t count, + const type& min, + const type& max, + const std::vector special_cases, + const bool generate_half, + typename std::enable_if< + std::is_same::value + >::type* = 0) +{ + if(!generate_half) + { + return generate_input(count, min, max, special_cases); + } + return generate_half_input(count, -(CL_HALF_MAX/4.f), (CL_HALF_MAX/4.f), special_cases); +} + +// If !std::is_same::value, we can just use generate_input(...). +template +std::vector vload_vstore_generate_input(size_t count, + const type& min, + const type& max, + const std::vector special_cases, + const bool generate_half, + typename std::enable_if< + !std::is_same::value + >::type* = 0) +{ + return generate_input(count, min, max, special_cases); +} + +#endif // TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_COMMON_HPP diff --git a/test_conformance/clcpp/vload_vstore/half_utils.hpp b/test_conformance/clcpp/vload_vstore/half_utils.hpp new file mode 100644 index 00000000..5c60599d --- /dev/null +++ b/test_conformance/clcpp/vload_vstore/half_utils.hpp @@ -0,0 +1,136 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_HALF_UTILS_HPP +#define TEST_CONFORMANCE_CLCPP_HALF_UTILS_HPP + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#include + +namespace detail +{ + +template +inline int clz(INT_TYPE x) +{ + int count = 0; + if(std::is_unsigned::value) + { + cl_ulong value = x; + value <<= 8 * sizeof(value) - (8 * sizeof(x)); + for(count = 0; 0 == (value & (CL_LONG_MIN)); count++) + { + value <<= 1; + } + } + else + { + cl_long value = x; + value <<= 8 * sizeof(value) - (8 * sizeof(x)); + for(count = 0; 0 == (value & (CL_LONG_MIN)); count++) + { + value <<= 1; + } + } + return count; +} + +} // namespace detail + +inline cl_float half2float(cl_half us) +{ + uint32_t u = us; + uint32_t sign = (u << 16) & 0x80000000; + int32_t exponent = (u & 0x7c00) >> 10; + uint32_t mantissa = (u & 0x03ff) << 13; + union{ cl_uint u; cl_float f;}uu; + + if( exponent == 0 ) + { + if( mantissa == 0 ) + return sign ? -0.0f : 0.0f; + + int shift = detail::clz( mantissa ) - 8; + exponent -= shift-1; + mantissa <<= shift; + mantissa &= 0x007fffff; + } + else + if( exponent == 31) + { + uu.u = mantissa | sign; + if( mantissa ) + uu.u |= 0x7fc00000; + else + uu.u |= 0x7f800000; + + return uu.f; + } + + exponent += 127 - 15; + exponent <<= 23; + + exponent |= mantissa; + uu.u = exponent | sign; + + return uu.f; +} + +inline cl_ushort float2half_rte(cl_float f) +{ + union{ cl_float f; cl_uint u; } u = {f}; + cl_uint sign = (u.u >> 16) & 0x8000; + cl_float x = fabsf(f); + + //Nan + if( x != x ) + { + u.u >>= (24-11); + u.u &= 0x7fff; + u.u |= 0x0200; //silence the NaN + return u.u | sign; + } + + // overflow + if( x >= MAKE_HEX_FLOAT(0x1.ffep15f, 0x1ffeL, 3) ) + return 0x7c00 | sign; + + // underflow + if( x <= MAKE_HEX_FLOAT(0x1.0p-25f, 0x1L, -25) ) + return sign; // The halfway case can return 0x0001 or 0. 0 is even. + + // very small + if( x < MAKE_HEX_FLOAT(0x1.8p-24f, 0x18L, -28) ) + return sign | 1; + + // half denormal + if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) ) + { + u.f = x * MAKE_HEX_FLOAT(0x1.0p-125f, 0x1L, -125); + return sign | u.u; + } + + u.f *= MAKE_HEX_FLOAT(0x1.0p13f, 0x1L, 13); + u.u &= 0x7f800000; + x += u.f; + u.f = x - u.f; + u.f *= MAKE_HEX_FLOAT(0x1.0p-112f, 0x1L, -112); + + return (u.u >> (24-11)) | sign; +} + +#endif // TEST_CONFORMANCE_CLCPP_HALF_UTILS_HPP diff --git a/test_conformance/clcpp/vload_vstore/main.cpp b/test_conformance/clcpp/vload_vstore/main.cpp new file mode 100644 index 00000000..6e5978c0 --- /dev/null +++ b/test_conformance/clcpp/vload_vstore/main.cpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "vload_funcs.hpp" +#include "vstore_funcs.hpp" + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/vload_vstore/vload_funcs.hpp b/test_conformance/clcpp/vload_vstore/vload_funcs.hpp new file mode 100644 index 00000000..f0bbcfc5 --- /dev/null +++ b/test_conformance/clcpp/vload_vstore/vload_funcs.hpp @@ -0,0 +1,363 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_VLOAD_VSTORE_FUNCS_VLOAD_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_VLOAD_VSTORE_FUNCS_VLOAD_FUNCS_HPP + +#include + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#include "common.hpp" + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template +std::string generate_kernel_vload(func_type func) +{ + std::string input1_type_str = type_name(); + if(func.is_in1_half()) + { + input1_type_str = "half"; + } + std::string output1_type_str = type_name(); + if(N == 3) + { + output1_type_str[output1_type_str.size() - 1] = '3'; + } + return + "__kernel void test_" + func.str() + "(global " + input1_type_str + " *input, global " + output1_type_str + " *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = " + func.str() + std::to_string(N) + "(gid, input);\n" + "}\n"; +} +#else +template +std::string generate_kernel_vload(func_type func) +{ + std::string input1_type_str = type_name(); + if(func.is_in1_half()) + { + input1_type_str = "half"; + } + std::string output1_type_str = type_name(); + if(N == 3) + { + output1_type_str[output1_type_str.size() - 1] = '3'; + } + return + "" + func.defs() + + "" + func.headers() + + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_" + func.str() + "(global_ptr<" + input1_type_str + "[]> input," + "global_ptr<" + output1_type_str + "[]> output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " output[gid] = " + func.str() + "<" + std::to_string(N) + ">(gid, input.get());\n" + "}\n"; +} +#endif + +template +bool verify_vload(const std::vector &in, const std::vector &out, vload_op op) +{ + for(size_t i = 0; i < out.size(); i++) + { + auto expected = op(i, in.begin()); + for(size_t j = 0; j < vload_op::vector_size; j++) + { + size_t idx = (i * vector_size::value) + j; + if(!are_equal(expected.s[j], out[i].s[j], op.delta(in[idx], expected.s[j]), op)) + { + print_error_msg(expected, out[i], i, op); + return false; + } + } + } + return true; +} + +template +int test_vload_func(cl_device_id device, cl_context context, cl_command_queue queue, size_t count, vload_op op) +{ + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t work_size[1]; + int err; + + typedef typename vload_op::in_type INPUT; + typedef typename vload_op::out_type OUTPUT; + + // Don't run test for unsupported types + if(!(type_supported(device) && type_supported(device))) + { + return CL_SUCCESS; + } + + std::string code_str = generate_kernel_vload(op); + std::string kernel_name("test_"); kernel_name += op.str(); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name, "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(err) +#endif + + std::vector input = vload_vstore_generate_input( + count * vector_size::value, op.min1(), op.max1(), op.in_special_cases(), op.is_in1_half() + ); + std::vector output = generate_output(count); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(INPUT) * input.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + buffers[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(OUTPUT) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(INPUT) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + work_size[0] = count; + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(OUTPUT) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + if (!verify_vload(input, output, op)) + { + RETURN_ON_ERROR_MSG(-1, "test_%s %s(%s) failed", + op.str().c_str(), + type_name().c_str(), + type_name().c_str() + ); + } + log_info("test_%s %s(%s) passed\n", op.str().c_str(), type_name().c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +template +struct vload_func : public unary_func< + IN1, + typename make_vector_type::type /* create IN1N type */ + > +{ + typedef typename make_vector_type::type result_type; + const static size_t vector_size = N; + + std::string str() + { + return "vload"; + } + + std::string headers() + { + return "#include \n"; + } + + template + result_type operator()(const size_t offset, Iterator x) + { + static_assert( + !is_vector_type::value, + "IN1 must be scalar type" + ); + static_assert( + std::is_same::value_type, IN1>::value, + "std::iterator_traits::value_type must be IN1" + ); + + typedef typename std::iterator_traits::difference_type diff_type; + + result_type r; + Iterator temp = x + static_cast(offset * N); + for(size_t i = 0; i < N; i++) + { + r.s[i] = *temp; + temp++; + } + return r; + } + + bool is_in1_half() + { + return false; + } +}; + +template +struct vload_half_func : public unary_func< + cl_half, + typename make_vector_type::type /* create IN1N type */ + > +{ + typedef typename make_vector_type::type result_type; + const static size_t vector_size = N; + + std::string str() + { + return "vload_half"; + } + + std::string headers() + { + return "#include \n"; + } + + template + result_type operator()(const size_t offset, Iterator x) + { + static_assert( + std::is_same::value_type, cl_half>::value, + "std::iterator_traits::value_type must be cl_half" + ); + + typedef typename std::iterator_traits::difference_type diff_type; + + result_type r; + Iterator temp = x + static_cast(offset * N); + for(size_t i = 0; i < N; i++) + { + r.s[i] = half2float(*temp); + temp++; + } + return r; + } + + bool is_in1_half() + { + return true; + } +}; + +template +struct vloada_half_func : public unary_func< + cl_half, + typename make_vector_type::type /* create IN1N type */ + > +{ + typedef typename make_vector_type::type result_type; + const static size_t vector_size = N; + + std::string str() + { + return "vloada_half"; + } + + std::string headers() + { + return "#include \n"; + } + + template + result_type operator()(const size_t offset, Iterator x) + { + static_assert( + std::is_same::value_type, cl_half>::value, + "std::iterator_traits::value_type must be cl_half" + ); + + typedef typename std::iterator_traits::difference_type diff_type; + + result_type r; + size_t alignment = N == 3 ? 4 : N; + Iterator temp = x + static_cast(offset * alignment); + for(size_t i = 0; i < N; i++) + { + r.s[i] = half2float(*temp); + temp++; + } + return r; + } + + bool is_in1_half() + { + return true; + } +}; + +AUTO_TEST_CASE(test_vload_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + +#define TEST_VLOAD_FUNC_MACRO(CLASS) \ + last_error = test_vload_func( \ + device, context, queue, n_elems, CLASS \ + ); \ + CHECK_ERROR(last_error) \ + error |= last_error; + + TEST_VLOAD_FUNC_MACRO((vload_func())) + TEST_VLOAD_FUNC_MACRO((vload_func())) + TEST_VLOAD_FUNC_MACRO((vload_func())) + TEST_VLOAD_FUNC_MACRO((vload_func())) + + TEST_VLOAD_FUNC_MACRO((vload_half_func<2>())) + TEST_VLOAD_FUNC_MACRO((vload_half_func<3>())) + TEST_VLOAD_FUNC_MACRO((vload_half_func<4>())) + TEST_VLOAD_FUNC_MACRO((vload_half_func<8>())) + TEST_VLOAD_FUNC_MACRO((vload_half_func<16>())) + + TEST_VLOAD_FUNC_MACRO((vloada_half_func<2>())) + TEST_VLOAD_FUNC_MACRO((vloada_half_func<3>())) + TEST_VLOAD_FUNC_MACRO((vloada_half_func<4>())) + TEST_VLOAD_FUNC_MACRO((vloada_half_func<8>())) + TEST_VLOAD_FUNC_MACRO((vloada_half_func<16>())) + +#undef TEST_VLOAD_FUNC_MACRO + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_VLOAD_VSTORE_FUNCS_VLOAD_FUNCS_HPP diff --git a/test_conformance/clcpp/vload_vstore/vstore_funcs.hpp b/test_conformance/clcpp/vload_vstore/vstore_funcs.hpp new file mode 100644 index 00000000..5bf83f51 --- /dev/null +++ b/test_conformance/clcpp/vload_vstore/vstore_funcs.hpp @@ -0,0 +1,348 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_VLOAD_VSTORE_FUNCS_VSTORE_FUNCS_HPP +#define TEST_CONFORMANCE_CLCPP_VLOAD_VSTORE_FUNCS_VSTORE_FUNCS_HPP + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#include + +#include "../common.hpp" +#include "../funcs_test_utils.hpp" + +#include "common.hpp" + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template +std::string generate_kernel_vstore(func_type func) +{ + std::string input1_type_str = type_name(); + if(N == 3) + { + input1_type_str[input1_type_str.size() - 1] = '3'; + } + std::string output1_type_str = type_name(); + if(func.is_out_half()) + { + output1_type_str = "half"; + } + return + "__kernel void test_" + func.str() + "(global " + input1_type_str + " *input, global " + output1_type_str + " *output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " " + func.str() + std::to_string(N) + "(input[gid], gid, output);\n" + "}\n"; +} +#else +template +std::string generate_kernel_vstore(func_type func) +{ + std::string input1_type_str = type_name(); + if(N == 3) + { + input1_type_str[input1_type_str.size() - 1] = '3'; + } + std::string output1_type_str = type_name(); + if(func.is_out_half()) + { + output1_type_str = "half"; + } + return + "" + func.defs() + + "" + func.headers() + + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_" + func.str() + "(global_ptr<" + input1_type_str + "[]> input," + "global_ptr<" + output1_type_str + "[]> output)\n" + "{\n" + " size_t gid = get_global_id(0);\n" + " " + func.str() + "(input[gid], gid, output.get());\n" + "}\n"; +} +#endif + +template +bool verify_vstore(const std::vector &in, const std::vector &out, vload_op op) +{ + for(size_t i = 0; i < in.size(); i++) + { + auto expected = op(in[i]); + for(size_t j = 0; j < vload_op::vector_size; j++) + { + size_t idx = (i * vload_op::vec_alignment) + j; + if(!are_equal(expected.s[j], out[idx], op.delta(in[i], expected).s[j], op)) + { + print_error_msg(expected.s[j], out[idx], idx, op); + return false; + } + } + } + return true; +} + +template +int test_vstore_func(cl_device_id device, cl_context context, cl_command_queue queue, size_t count, vload_op op) +{ + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t work_size[1]; + int err; + + typedef typename vload_op::in_type INPUT; + typedef typename vload_op::out_type OUTPUT; + + // Don't run test for unsupported types + if(!(type_supported(device) && type_supported(device))) + { + return CL_SUCCESS; + } + + std::string code_str = generate_kernel_vstore(op); + std::string kernel_name("test_"); kernel_name += op.str(); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name, "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name); + RETURN_ON_ERROR(err) +#endif + + std::vector input = generate_input(count, op.min1(), op.max1(), op.in_special_cases()); + std::vector output = generate_output(count * vector_size::value); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(INPUT) * input.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + buffers[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(OUTPUT) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(INPUT) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + work_size[0] = count; + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, NULL, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(OUTPUT) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + if (!verify_vstore(input, output, op)) + { + RETURN_ON_ERROR_MSG(-1, "test_%s %s(%s) failed", op.str().c_str(), type_name().c_str(), type_name().c_str()); + } + log_info("test_%s %s(%s) passed\n", op.str().c_str(), type_name().c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +template +struct vstore_func : public unary_func< + typename make_vector_type::type, + T + > +{ + typedef typename make_vector_type::type input1_type; + typedef typename make_vector_type::type result_type; + const static size_t vector_size = N; + const static size_t vec_alignment = N; + + std::string str() + { + return "vstore"; + } + + std::string headers() + { + return "#include \n"; + } + + result_type operator()(const input1_type& in) + { + static_assert( + !is_vector_type::value, + "T must be scalar type" + ); + return in; + } + + bool is_out_half() + { + return false; + } +}; + +template +struct vstore_half_func : public unary_func< + typename make_vector_type::type, + cl_half + > +{ + typedef typename make_vector_type::type input1_type; + typedef typename make_vector_type::type result_type; + const static size_t vector_size = N; + const static size_t vec_alignment = N; + + std::string str() + { + return "vstore_half"; + } + + std::string headers() + { + return "#include \n"; + } + + result_type operator()(const input1_type& in) + { + result_type r; + for(size_t i = 0; i < N; i++) + { + r.s[i] = float2half_rte(in.s[i]); + } + return r; + } + + input1_type min1() + { + return detail::make_value(-512.f); + } + + input1_type max1() + { + return detail::make_value(512.f); + } + + bool is_out_half() + { + return true; + } +}; + +template +struct vstorea_half_func : public unary_func< + typename make_vector_type::type, + cl_half + > +{ + typedef typename make_vector_type::type input1_type; + typedef typename make_vector_type::type result_type; + const static size_t vector_size = N; + const static size_t vec_alignment = N == 3 ? 4 : N; + + std::string str() + { + return "vstorea_half"; + } + + std::string headers() + { + return "#include \n"; + } + + result_type operator()(const input1_type& in) + { + result_type r; + for(size_t i = 0; i < N; i++) + { + r.s[i] = float2half_rte(in.s[i]); + } + return r; + } + + input1_type min1() + { + return detail::make_value(-512.f); + } + + input1_type max1() + { + return detail::make_value(512.f); + } + + bool is_out_half() + { + return true; + } +}; + +AUTO_TEST_CASE(test_vstore_funcs) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int last_error = CL_SUCCESS; + +#define TEST_VSTORE_FUNC_MACRO(CLASS) \ + last_error = test_vstore_func( \ + device, context, queue, n_elems, CLASS \ + ); \ + CHECK_ERROR(last_error) \ + error |= last_error; + + TEST_VSTORE_FUNC_MACRO((vstore_func())) + TEST_VSTORE_FUNC_MACRO((vstore_func())) + TEST_VSTORE_FUNC_MACRO((vstore_func())) + TEST_VSTORE_FUNC_MACRO((vstore_func())) + TEST_VSTORE_FUNC_MACRO((vstore_func())) + + TEST_VSTORE_FUNC_MACRO((vstore_half_func<2>())) + TEST_VSTORE_FUNC_MACRO((vstore_half_func<3>())) + TEST_VSTORE_FUNC_MACRO((vstore_half_func<4>())) + TEST_VSTORE_FUNC_MACRO((vstore_half_func<8>())) + TEST_VSTORE_FUNC_MACRO((vstore_half_func<16>())) + + TEST_VSTORE_FUNC_MACRO((vstorea_half_func<2>())) + TEST_VSTORE_FUNC_MACRO((vstorea_half_func<3>())) + +#undef TEST_VSTORE_FUNC_MACRO + + if(error != CL_SUCCESS) + { + return -1; + } + return error; +} + +#endif // TEST_CONFORMANCE_CLCPP_VLOAD_VSTORE_FUNCS_VSTORE_FUNCS_HPP diff --git a/test_conformance/clcpp/workgroups/CMakeLists.txt b/test_conformance/clcpp/workgroups/CMakeLists.txt new file mode 100644 index 00000000..de99e367 --- /dev/null +++ b/test_conformance/clcpp/workgroups/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_WORKGROUPS) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/workgroups/common.hpp b/test_conformance/clcpp/workgroups/common.hpp new file mode 100644 index 00000000..ab7b100d --- /dev/null +++ b/test_conformance/clcpp/workgroups/common.hpp @@ -0,0 +1,97 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_WG_COMMON_HPP +#define TEST_CONFORMANCE_CLCPP_WG_COMMON_HPP + +#include +#include +#include + +enum class work_group_op : int { + add, min, max +}; + +std::string to_string(work_group_op op) +{ + switch (op) + { + case work_group_op::add: + return "add"; + case work_group_op::min: + return "min"; + case work_group_op::max: + return "max"; + default: + break; + } + return ""; +} + +template +std::vector generate_input(size_t count, size_t wg_size) +{ + std::vector input(count, CL_INT_TYPE(1)); + switch (op) + { + case work_group_op::add: + return input; + case work_group_op::min: + { + size_t j = wg_size; + for(size_t i = 0; i < count; i++) + { + input[i] = static_cast(j); + j--; + if(j == 0) + { + j = wg_size; + } + } + } + break; + case work_group_op::max: + { + size_t j = 0; + for(size_t i = 0; i < count; i++) + { + input[i] = static_cast(j); + j++; + if(j == wg_size) + { + j = 0; + } + } + } + } + return input; +} + +template +std::vector generate_output(size_t count, size_t wg_size) +{ + switch (op) + { + case work_group_op::add: + return std::vector(count, CL_INT_TYPE(0)); + case work_group_op::min: + return std::vector(count, (std::numeric_limits::max)()); + case work_group_op::max: + return std::vector(count, (std::numeric_limits::min)()); + } + return std::vector(count, CL_INT_TYPE(0)); +} + +#endif // TEST_CONFORMANCE_CLCPP_WG_COMMON_HPP diff --git a/test_conformance/clcpp/workgroups/main.cpp b/test_conformance/clcpp/workgroups/main.cpp new file mode 100644 index 00000000..72d83e26 --- /dev/null +++ b/test_conformance/clcpp/workgroups/main.cpp @@ -0,0 +1,34 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "test_wg_all.hpp" +#include "test_wg_any.hpp" +#include "test_wg_broadcast.hpp" +#include "test_wg_reduce.hpp" +#include "test_wg_scan_inclusive.hpp" +#include "test_wg_scan_exclusive.hpp" + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/workgroups/test_wg_all.hpp b/test_conformance/clcpp/workgroups/test_wg_all.hpp new file mode 100644 index 00000000..103ce2bf --- /dev/null +++ b/test_conformance/clcpp/workgroups/test_wg_all.hpp @@ -0,0 +1,218 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_WG_TEST_WG_ALL_HPP +#define TEST_CONFORMANCE_CLCPP_WG_TEST_WG_ALL_HPP + +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" +// Common for tests of work-group functions +#include "common.hpp" + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +std::string generate_wg_all_kernel_code() +{ + return + "__kernel void test_wg_all(global uint *input, global uint *output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + "\n" + " int result = work_group_all(input[tid] < input[tid+1]);\n" + " if(result == 0) {\n output[tid] = 0;\n return;\n }\n" + " output[tid] = 1;\n" + "}\n"; +} +#else +std::string generate_wg_all_kernel_code() +{ + return "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_wg_all(global_ptr input, global_ptr output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + " bool result = work_group_all(input[tid] < input[tid+1]);\n" + " if(!result) {\n output[tid] = 0;\n return;\n }\n" + " output[tid] = 1;\n" + "}\n"; +} +#endif + +int verify_wg_all(const std::vector &in, const std::vector &out, size_t count, size_t wg_size) +{ + size_t i, j; + for (i = 0; i < count; i += wg_size) + { + // Work-group all + bool all = true; + for (j = 0; j < ((count - i) > wg_size ? wg_size : (count - i)); j++) + { + if(!(in[i+j] < in[i+j+1])) + { + all = false; + break; + } + } + + // Convert bool to uint + cl_uint all_uint = all ? 1 : 0; + // Check if all work-items in work-group stored correct value + for (j = 0; j < ((count - i) > wg_size ? wg_size : (count - i)); j++) + { + if (all_uint != out[i + j]) + { + log_info( + "work_group_all %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(all_uint), + static_cast(out[i + j])); + return -1; + } + } + } + return CL_SUCCESS; +} + +std::vector generate_input_wg_all(size_t count, size_t wg_size) +{ + std::vector input(count, cl_uint(0)); + size_t j = wg_size; + for(size_t i = 0; i < count; i++) + { + input[i] = static_cast(i); + // In one place in ~half of workgroups input[tid] < input[tid+1] will + // generate false, that means for that workgroups work_group_all() + // should return false + if((j == wg_size/2) && (i > count/2)) + { + input[i] = input[i - 1]; + } + j--; + if(j == 0) + { + j = wg_size; + } + } + return input; +} + +std::vector generate_output_wg_all(size_t count, size_t wg_size) +{ + (void) wg_size; + return std::vector(count, cl_uint(1)); +} + +int work_group_all(cl_device_id device, cl_context context, cl_command_queue queue, size_t count) +{ + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t wg_size; + size_t work_size[1]; + int err; + + std::string code_str = generate_wg_all_kernel_code(); +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_all"); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_all", "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_all"); + RETURN_ON_ERROR(err) +#endif + + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &wg_size, NULL); + RETURN_ON_CL_ERROR(err, "clGetKernelWorkGroupInfo") + + // Calculate global work size + size_t flat_work_size; + size_t wg_number = static_cast( + std::ceil(static_cast(count) / wg_size) + ); + flat_work_size = wg_number * wg_size; + work_size[0] = flat_work_size; + + std::vector input = generate_input_wg_all(flat_work_size + 1, wg_size); + std::vector output = generate_output_wg_all(flat_work_size, wg_size); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * input.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + buffers[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(cl_uint) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, &wg_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + if (verify_wg_all(input, output, flat_work_size, wg_size) != CL_SUCCESS) + { + RETURN_ON_ERROR_MSG(-1, "work_group_all failed"); + } + log_info("work_group_all passed\n"); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +AUTO_TEST_CASE(test_work_group_all) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int err = CL_SUCCESS; + + err = work_group_all(device, context, queue, n_elems); + CHECK_ERROR(err) + + if(err != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +#endif // TEST_CONFORMANCE_CLCPP_WG_TEST_WG_ALL_HPP diff --git a/test_conformance/clcpp/workgroups/test_wg_any.hpp b/test_conformance/clcpp/workgroups/test_wg_any.hpp new file mode 100644 index 00000000..724b3ceb --- /dev/null +++ b/test_conformance/clcpp/workgroups/test_wg_any.hpp @@ -0,0 +1,218 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_WG_TEST_WG_ANY_HPP +#define TEST_CONFORMANCE_CLCPP_WG_TEST_WG_ANY_HPP + +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" +// Common for tests of work-group functions +#include "common.hpp" + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +std::string generate_wg_any_kernel_code() +{ + return + "__kernel void test_wg_any(global uint *input, global uint *output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + "\n" + " int result = work_group_any(input[tid] == input[tid+1]);\n" + " if(result == 0) {\n output[tid] = 0;\n return;\n }\n" + " output[tid] = 1;\n" + "}\n"; +} +#else +std::string generate_wg_any_kernel_code() +{ + return "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_wg_any(global_ptr input, global_ptr output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + " bool result = work_group_any(input[tid] == input[tid+1]);\n" + " if(!result) {\n output[tid] = 0;\n return;\n }\n" + " output[tid] = 1;\n" + "}\n"; +} +#endif + +int verify_wg_any(const std::vector &in, const std::vector &out, size_t count, size_t wg_size) +{ + size_t i, j; + for (i = 0; i < count; i += wg_size) + { + // Work-group any + bool any = false; + for (j = 0; j < ((count - i) > wg_size ? wg_size : (count - i)); j++) + { + if(in[i+j] == in[i+j+1]) + { + any = true; + break; + } + } + + // Convert bool to uint + cl_uint any_uint = any ? 1 : 0; + // Check if all work-items in work-group stored correct value + for (j = 0; j < ((count - i) > wg_size ? wg_size : (count - i)); j++) + { + if (any_uint != out[i + j]) + { + log_info( + "work_group_any %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(any_uint), + static_cast(out[i + j])); + return -1; + } + } + } + return CL_SUCCESS; +} + +std::vector generate_input_wg_any(size_t count, size_t wg_size) +{ + std::vector input(count, cl_uint(0)); + size_t j = wg_size; + for(size_t i = 0; i < count; i++) + { + input[i] = static_cast(i); + // In one place in ~half of workgroups input[tid] == input[tid+1] will + // generate true, that means for that workgroups work_group_any() + // should return true + if((j == wg_size/2) && (i > count/2)) + { + input[i] = input[i - 1]; + } + j--; + if(j == 0) + { + j = wg_size; + } + } + return input; +} + +std::vector generate_output_wg_any(size_t count, size_t wg_size) +{ + (void) wg_size; + return std::vector(count, cl_uint(1)); +} + +int work_group_any(cl_device_id device, cl_context context, cl_command_queue queue, size_t count) +{ + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t wg_size; + size_t work_size[1]; + int err; + + std::string code_str = generate_wg_any_kernel_code(); +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_any"); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_any", "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_any"); + RETURN_ON_ERROR(err) +#endif + + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &wg_size, NULL); + RETURN_ON_CL_ERROR(err, "clGetKernelWorkGroupInfo") + + // Calculate global work size + size_t flat_work_size; + size_t wg_number = static_cast( + std::ceil(static_cast(count) / wg_size) + ); + flat_work_size = wg_number * wg_size; + work_size[0] = flat_work_size; + + std::vector input = generate_input_wg_any(flat_work_size + 1, wg_size); + std::vector output = generate_output_wg_any(flat_work_size, wg_size); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * input.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + buffers[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(cl_uint) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, &wg_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + if (verify_wg_any(input, output, flat_work_size, wg_size) != CL_SUCCESS) + { + RETURN_ON_ERROR_MSG(-1, "work_group_any failed"); + } + log_info("work_group_any passed\n"); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +AUTO_TEST_CASE(test_work_group_any) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int err = CL_SUCCESS; + + err = work_group_any(device, context, queue, n_elems); + CHECK_ERROR(err) + + if(err != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +#endif // TEST_CONFORMANCE_CLCPP_WG_TEST_WG_ANY_HPP diff --git a/test_conformance/clcpp/workgroups/test_wg_broadcast.hpp b/test_conformance/clcpp/workgroups/test_wg_broadcast.hpp new file mode 100644 index 00000000..4dc5559e --- /dev/null +++ b/test_conformance/clcpp/workgroups/test_wg_broadcast.hpp @@ -0,0 +1,458 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_WG_TEST_WG_BROADCAST_HPP +#define TEST_CONFORMANCE_CLCPP_WG_TEST_WG_BROADCAST_HPP + +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" +// Common for tests of work-group functions +#include "common.hpp" + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +std::string generate_wg_broadcast_1D_kernel_code() +{ + return + "__kernel void test_wg_broadcast(global uint *input, global uint *output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + " uint result = work_group_broadcast(input[tid], get_group_id(0) % get_local_size(0));\n" + " output[tid] = result;\n" + "}\n"; +} +std::string generate_wg_broadcast_2D_kernel_code() +{ + return + "__kernel void test_wg_broadcast(global uint *input, global uint *output)\n" + "{\n" + " ulong tid_x = get_global_id(0);\n" + " ulong tid_y = get_global_id(1);\n" + " size_t x = get_group_id(0) % get_local_size(0);\n" + " size_t y = get_group_id(1) % get_local_size(1);\n" + " size_t idx = (tid_y * get_global_size(0)) + tid_x;\n" + " uint result = work_group_broadcast(input[idx], x, y);\n" + " output[idx] = result;\n" + "}\n"; +} +std::string generate_wg_broadcast_3D_kernel_code() +{ + return + "__kernel void test_wg_broadcast(global uint *input, global uint *output)\n" + "{\n" + " ulong tid_x = get_global_id(0);\n" + " ulong tid_y = get_global_id(1);\n" + " ulong tid_z = get_global_id(2);\n" + " size_t x = get_group_id(0) % get_local_size(0);\n" + " size_t y = get_group_id(1) % get_local_size(1);\n" + " size_t z = get_group_id(2) % get_local_size(2);\n" + " ulong idx = (tid_z * get_global_size(1) * get_global_size(0)) + (tid_y * get_global_size(0)) + tid_x;\n" + " uint result = work_group_broadcast(input[idx], x, y, z);\n" + " output[idx] = result;\n" + "}\n"; +} +#else +std::string generate_wg_broadcast_1D_kernel_code() +{ + return "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_wg_broadcast(global_ptr input, global_ptr output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + " uint result = work_group_broadcast(input[tid], get_group_id(0) % get_local_size(0));\n" + " output[tid] = result;\n" + "}\n"; +} +std::string generate_wg_broadcast_2D_kernel_code() +{ + return "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_wg_broadcast(global_ptr input, global_ptr output)\n" + "{\n" + " ulong tid_x = get_global_id(0);\n" + " ulong tid_y = get_global_id(1);\n" + " size_t x = get_group_id(0) % get_local_size(0);\n" + " size_t y = get_group_id(1) % get_local_size(1);\n" + " size_t idx = (tid_y * get_global_size(0)) + tid_x;\n" + " uint result = work_group_broadcast(input[idx], x, y);\n" + " output[idx] = result;\n" + "}\n"; +} +std::string generate_wg_broadcast_3D_kernel_code() +{ + return "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_wg_broadcast(global_ptr input, global_ptr output)\n" + "{\n" + " ulong tid_x = get_global_id(0);\n" + " ulong tid_y = get_global_id(1);\n" + " ulong tid_z = get_global_id(2);\n" + " size_t x = get_group_id(0) % get_local_size(0);\n" + " size_t y = get_group_id(1) % get_local_size(1);\n" + " size_t z = get_group_id(2) % get_local_size(2);\n" + " ulong idx = (tid_z * get_global_size(1) * get_global_size(0)) + (tid_y * get_global_size(0)) + tid_x;\n" + " uint result = work_group_broadcast(input[idx], x, y, z);\n" + " output[idx] = result;\n" + "}\n"; +} +#endif + +int +verify_wg_broadcast_1D(const std::vector &in, const std::vector &out, size_t n, size_t wg_size) +{ + size_t i, j; + size_t group_id; + + for (i=0,group_id=0; i wg_size ? wg_size : (n-i); + cl_uint broadcast_result = in[i + (group_id % local_size)]; + for (j=0; j &in, const std::vector &out, + size_t nx, size_t ny, + size_t wg_size_x, size_t wg_size_y) +{ + size_t i, j, _i, _j; + size_t group_id_x, group_id_y; + + for (i=0,group_id_y=0; i wg_size_y ? wg_size_y : (ny-i); + for (_i=0; _i < local_size_y; _i++) + { + for (j=0,group_id_x=0; j wg_size_x ? wg_size_x : (nx-j); + cl_uint broadcast_result = in[(i + y) * nx + (j + x)]; + for (_j=0; _j < local_size_x; _j++) + { + size_t indx = (i + _i) * nx + (j + _j); + if ( broadcast_result != out[indx] ) + { + log_info("%lu\n", indx); + log_info("%lu\n", ((i + y) * nx + (j + x))); + log_info("%lu\n", out.size()); + log_info("work_group_broadcast: Error at (%lu, %lu): expected = %u, got = %u\n", j+_j, i+_i, broadcast_result, out[indx]); + return -1; + } + } + } + } + } + + return CL_SUCCESS; +} + +int +verify_wg_broadcast_3D(const std::vector &in, const std::vector &out, + size_t nx, size_t ny, size_t nz, + size_t wg_size_x, size_t wg_size_y, size_t wg_size_z) +{ + size_t i, j, k, _i, _j, _k; + size_t group_id_x, group_id_y, group_id_z; + + for (i=0,group_id_z=0; i wg_size_z ? wg_size_z : (nz-i); + for (_i=0; _i < local_size_z; _i++) + { + for (j=0,group_id_y=0; j wg_size_y ? wg_size_y : (ny-j); + for (_j=0; _j < local_size_y; _j++) + { + for (k=0,group_id_x=0; k wg_size_x ? wg_size_x : (nx-k); + cl_uint broadcast_result = in[(i + z) * ny * nz + (j + y) * nx + (k + x)]; + for (_k=0; _k < local_size_x; _k++) + { + size_t indx = (i + _i) * ny * nx + (j + _j) * nx + (k + _k); + if ( broadcast_result != out[indx] ) + { + log_info( + "work_group_broadcast: Error at (%lu, %lu, %lu): expected = %u, got = %u\n", + k+_k, j+_j, i+_i, + broadcast_result, out[indx]); + return -1; + } + } + } + } + } + } + } + return CL_SUCCESS; +} + +std::vector generate_input_wg_broadcast(size_t count, size_t wg_size) +{ + std::vector input(count, cl_uint(0)); + size_t j = wg_size; + for(size_t i = 0; i < count; i++) + { + input[i] = static_cast(j); + j--; + if(j == 0) + { + j = wg_size; + } + } + return input; +} + +std::vector generate_output_wg_broadcast(size_t count, size_t wg_size) +{ + (void) wg_size; + return std::vector(count, cl_uint(1)); +} + +int work_group_broadcast(cl_device_id device, cl_context context, cl_command_queue queue, size_t count, size_t dim) +{ + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t flat_wg_size; + size_t wg_size[] = { 1, 1, 1}; + size_t work_size[] = { 1, 1, 1}; + int err; + + // Get kernel source code + std::string code_str; + if(dim > 2) code_str = generate_wg_broadcast_3D_kernel_code(); + else if(dim > 1) code_str = generate_wg_broadcast_2D_kernel_code(); + else code_str = generate_wg_broadcast_1D_kernel_code(); + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_broadcast"); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_broadcast", "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_broadcast"); + RETURN_ON_ERROR(err) +#endif + + // Get max flat workgroup size + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &flat_wg_size, NULL); + RETURN_ON_CL_ERROR(err, "clGetKernelWorkGroupInfo") + + // Set local work size + wg_size[0] = flat_wg_size; + if(dim > 2) + { + if (flat_wg_size >=512) + { + wg_size[0] = wg_size[1] = wg_size[2] = 8; + } + else if (flat_wg_size >= 64) + { + wg_size[0] = wg_size[1] = wg_size[2] = 4; + } + else if (flat_wg_size >= 8) + { + wg_size[0] = wg_size[1] = wg_size[2] = 2; + } + else + { + wg_size[0] = wg_size[1] = wg_size[2] = 1; + } + } + else if(dim > 1) + { + if (flat_wg_size >= 256) + { + wg_size[0] = wg_size[1] = 16; + } + else if (flat_wg_size >=64) + { + wg_size[0] = wg_size[1] = 8; + } + else if (flat_wg_size >= 16) + { + wg_size[0] = wg_size[1] = 4; + } + else + { + wg_size[0] = wg_size[1] = 1; + } + } + + // Calculate flat local work size + flat_wg_size = wg_size[0]; + if(dim > 1) flat_wg_size *= wg_size[1]; + if(dim > 2) flat_wg_size *= wg_size[2]; + + // Calculate global work size + size_t flat_work_size = count; + // 3D + if(dim > 2) + { + size_t wg_number = static_cast( + std::ceil(static_cast(count / 3) / (wg_size[0] * wg_size[1] * wg_size[2])) + ); + work_size[0] = wg_number * wg_size[0]; + work_size[1] = wg_number * wg_size[1]; + work_size[2] = wg_number * wg_size[2]; + flat_work_size = work_size[0] * work_size[1] * work_size[2]; + } + // 2D + else if(dim > 1) + { + size_t wg_number = static_cast( + std::ceil(static_cast(count / 2) / (wg_size[0] * wg_size[1])) + ); + work_size[0] = wg_number * wg_size[0]; + work_size[1] = wg_number * wg_size[1]; + flat_work_size = work_size[0] * work_size[1]; + } + // 1D + else + { + size_t wg_number = static_cast( + std::ceil(static_cast(count) / wg_size[0]) + ); + flat_work_size = wg_number * wg_size[0]; + work_size[0] = flat_work_size; + } + + std::vector input = generate_input_wg_broadcast(flat_work_size, flat_wg_size); + std::vector output = generate_output_wg_broadcast(flat_work_size, flat_wg_size); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * input.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + buffers[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(cl_uint) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel(queue, kernel, dim, NULL, work_size, wg_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(cl_uint) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + int result = CL_SUCCESS; + // 3D + if(dim > 2) + { + result = verify_wg_broadcast_3D( + input, output, + work_size[0], work_size[1], work_size[2], + wg_size[0], wg_size[1], wg_size[2] + ); + } + // 2D + else if(dim > 1) + { + result = verify_wg_broadcast_2D( + input, output, + work_size[0], work_size[1], + wg_size[0], wg_size[1] + ); + } + // 1D + else + { + result = verify_wg_broadcast_1D( + input, output, + work_size[0], + wg_size[0] + ); + } + + RETURN_ON_ERROR_MSG(result, "work_group_broadcast_%luD failed", dim); + log_info("work_group_broadcast_%luD passed\n", dim); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +AUTO_TEST_CASE(test_work_group_broadcast) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = work_group_broadcast(device, context, queue, n_elems, 1); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_broadcast(device, context, queue, n_elems, 2); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_broadcast(device, context, queue, n_elems, 3); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +#endif // TEST_CONFORMANCE_CLCPP_WG_TEST_WG_BROADCAST_HPP diff --git a/test_conformance/clcpp/workgroups/test_wg_reduce.hpp b/test_conformance/clcpp/workgroups/test_wg_reduce.hpp new file mode 100644 index 00000000..616cbdb0 --- /dev/null +++ b/test_conformance/clcpp/workgroups/test_wg_reduce.hpp @@ -0,0 +1,331 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_WG_TEST_WG_REDUCE_HPP +#define TEST_CONFORMANCE_CLCPP_WG_TEST_WG_REDUCE_HPP + +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" +// Common for tests of work-group functions +#include "common.hpp" + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template +std::string generate_wg_reduce_kernel_code() +{ + return + "__kernel void test_wg_reduce(global " + type_name() + " *input, global " + type_name() + " *output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + "\n" + " " + type_name() + " result = work_group_reduce_" + to_string(op) + "(input[tid]);\n" + " output[tid] = result;\n" + "}\n"; +} +#else +template +std::string generate_wg_reduce_kernel_code() +{ + return "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_wg_reduce(global_ptr<" + type_name() + "[]> input, " + "global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + " " + type_name() + " result = work_group_reduce(input[tid]);\n" + " output[tid] = result;\n" + "}\n"; +} +#endif + +template +int verify_wg_reduce_add(const std::vector &in, const std::vector &out, size_t wg_size) +{ + size_t i, j; + for (i = 0; i < in.size(); i += wg_size) + { + CL_INT_TYPE sum = 0; + // Work-group sum + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j++) + sum += in[i + j]; + + // Check if all work-items in work-group stored correct value + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j++) + { + if (sum != out[i + j]) + { + log_info( + "work_group_reduce_add %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(sum), + static_cast(out[i + j])); + return -1; + } + } + } + return 0; +} + +template +int verify_wg_reduce_min(const std::vector &in, const std::vector &out, size_t wg_size) +{ + size_t i, j; + for (i = 0; i < in.size(); i += wg_size) + { + CL_INT_TYPE min = (std::numeric_limits::max)(); + // Work-group min + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j++) + min = std::min(min, in[i + j]); + + // Check if all work-items in work-group stored correct value + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j++) + { + if (min != out[i + j]) + { + log_info( + "work_group_reduce_min %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(min), + static_cast(out[i + j])); + return -1; + } + } + } + return 0; +} + +template +int verify_wg_reduce_max(const std::vector &in, const std::vector &out, size_t wg_size) +{ + size_t i, j; + for (i = 0; i < in.size(); i += wg_size) + { + CL_INT_TYPE max = (std::numeric_limits::min)(); + // Work-group max + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j++) + max = std::max(max, in[i + j]); + + // Check if all work-items in work-group stored correct value + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j++) + { + if (max != out[i + j]) + { + log_info( + "work_group_reduce_max %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(max), + static_cast(out[i + j])); + return -1; + } + } + } + return 0; +} + +template +int verify_wg_reduce(const std::vector &in, const std::vector &out, size_t wg_size) +{ + switch (op) + { + case work_group_op::add: + return verify_wg_reduce_add(in, out, wg_size); + case work_group_op::min: + return verify_wg_reduce_min(in, out, wg_size); + case work_group_op::max: + return verify_wg_reduce_max(in, out, wg_size); + } + return -1; +} + +template +int work_group_reduce(cl_device_id device, cl_context context, cl_command_queue queue, size_t count) +{ + // don't run test for unsupported types + if(!type_supported(device)) + { + return CL_SUCCESS; + } + + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t wg_size; + size_t work_size[1]; + int err; + + std::string code_str = generate_wg_reduce_kernel_code(); +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_reduce"); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_reduce", "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_reduce"); + RETURN_ON_ERROR(err) +#endif + + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &wg_size, NULL); + RETURN_ON_CL_ERROR(err, "clGetKernelWorkGroupInfo") + + // Calculate global work size + size_t flat_work_size; + size_t wg_number = static_cast( + std::ceil(static_cast(count) / wg_size) + ); + flat_work_size = wg_number * wg_size; + work_size[0] = flat_work_size; + + std::vector input = generate_input(flat_work_size, wg_size); + std::vector output = generate_output(flat_work_size, wg_size); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(CL_INT_TYPE) * input.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + buffers[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(CL_INT_TYPE) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(CL_INT_TYPE) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, &wg_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(CL_INT_TYPE) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + if (verify_wg_reduce(input, output, wg_size) != CL_SUCCESS) + { + RETURN_ON_ERROR_MSG(-1, "work_group_reduce_%s %s failed", to_string(op).c_str(), type_name().c_str()); + } + log_info("work_group_reduce_%s %s passed\n", to_string(op).c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +AUTO_TEST_CASE(test_work_group_reduce_add) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = work_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +AUTO_TEST_CASE(test_work_group_reduce_min) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = work_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +AUTO_TEST_CASE(test_work_group_reduce_max) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = work_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_reduce(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +#endif // TEST_CONFORMANCE_CLCPP_WG_TEST_WG_REDUCE_HPP diff --git a/test_conformance/clcpp/workgroups/test_wg_scan_exclusive.hpp b/test_conformance/clcpp/workgroups/test_wg_scan_exclusive.hpp new file mode 100644 index 00000000..35ec4b13 --- /dev/null +++ b/test_conformance/clcpp/workgroups/test_wg_scan_exclusive.hpp @@ -0,0 +1,324 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_WG_TEST_WG_SCAN_EXCLUSIVE_HPP +#define TEST_CONFORMANCE_CLCPP_WG_TEST_WG_SCAN_EXCLUSIVE_HPP + +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" +// Common for tests of work-group functions +#include "common.hpp" + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template +std::string generate_wg_scan_exclusive_kernel_code() +{ + return + "__kernel void test_wg_scan_exclusive(global " + type_name() + " *input, global " + type_name() + " *output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + "\n" + " " + type_name() + " result = work_group_scan_exclusive_" + to_string(op) + "(input[tid]);\n" + " output[tid] = result;\n" + "}\n"; +} +#else +template +std::string generate_wg_scan_exclusive_kernel_code() +{ + return "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_wg_scan_exclusive(global_ptr<" + type_name() + "[]> input, " + "global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + " " + type_name() + " result = work_group_scan_exclusive(input[tid]);\n" + " output[tid] = result;\n" + "}\n"; +} +#endif + +template +int verify_wg_scan_exclusive_add(const std::vector &in, const std::vector &out, size_t wg_size) +{ + size_t i, j; + for (i = 0; i < in.size(); i += wg_size) + { + CL_INT_TYPE sum = 0; + + // Check if all work-items in work-group wrote correct value + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j++) + { + if (sum != out[i + j]) + { + log_info( + "work_group_scan_exclusive_add %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(sum), + static_cast(out[i + j])); + return -1; + } + sum += in[i + j]; + } + } + return CL_SUCCESS; +} + +template +int verify_wg_scan_exclusive_min(const std::vector &in, const std::vector &out, size_t wg_size) +{ + size_t i, j; + for (i = 0; i < in.size(); i += wg_size) + { + CL_INT_TYPE min = (std::numeric_limits::max)(); + + // Check if all work-items in work-group wrote correct value + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j++) + { + if (min != out[i + j]) + { + log_info( + "work_group_scan_exclusive_min %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(min), + static_cast(out[i + j])); + return -1; + } + min = (std::min)(min, in[i + j]); + } + } + return CL_SUCCESS; +} + +template +int verify_wg_scan_exclusive_max(const std::vector &in, const std::vector &out, size_t wg_size) +{ + size_t i, j; + for (i = 0; i < in.size(); i += wg_size) + { + CL_INT_TYPE max = (std::numeric_limits::min)(); + + // Check if all work-items in work-group wrote correct value + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j++) + { + if (max != out[i + j]) + { + log_info( + "work_group_scan_exclusive_max %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(max), + static_cast(out[i + j])); + return -1; + } + max = (std::max)(max, in[i + j]); + } + } + return CL_SUCCESS; +} + +template +int verify_wg_scan_exclusive(const std::vector &in, const std::vector &out, size_t wg_size) +{ + switch (op) + { + case work_group_op::add: + return verify_wg_scan_exclusive_add(in, out, wg_size); + case work_group_op::min: + return verify_wg_scan_exclusive_min(in, out, wg_size); + case work_group_op::max: + return verify_wg_scan_exclusive_max(in, out, wg_size); + } + return -1; +} + +template +int work_group_scan_exclusive(cl_device_id device, cl_context context, cl_command_queue queue, size_t count) +{ + // don't run test for unsupported types + if(!type_supported(device)) + { + return CL_SUCCESS; + } + + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t wg_size; + size_t work_size[1]; + int err; + + std::string code_str = generate_wg_scan_exclusive_kernel_code(); +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_scan_exclusive"); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_scan_exclusive", "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_scan_exclusive"); + RETURN_ON_ERROR(err) +#endif + + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &wg_size, NULL); + RETURN_ON_CL_ERROR(err, "clGetKernelWorkGroupInfo") + + // Calculate global work size + size_t flat_work_size; + size_t wg_number = static_cast( + std::ceil(static_cast(count) / wg_size) + ); + flat_work_size = wg_number * wg_size; + work_size[0] = flat_work_size; + + std::vector input = generate_input(flat_work_size, wg_size); + std::vector output = generate_output(flat_work_size, wg_size); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(CL_INT_TYPE) * input.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + buffers[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(CL_INT_TYPE) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(CL_INT_TYPE) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, &wg_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(CL_INT_TYPE) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + if (verify_wg_scan_exclusive(input, output, wg_size) != CL_SUCCESS) + { + RETURN_ON_ERROR_MSG(-1, "work_group_scan_exclusive_%s %s failed", to_string(op).c_str(), type_name().c_str()); + } + log_info("work_group_scan_exclusive_%s %s passed\n", to_string(op).c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +AUTO_TEST_CASE(test_work_group_scan_exclusive_add) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = work_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +AUTO_TEST_CASE(test_work_group_scan_exclusive_min) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = work_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +AUTO_TEST_CASE(test_work_group_scan_exclusive_max) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = work_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_exclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +#endif // TEST_CONFORMANCE_CLCPP_WG_TEST_WG_SCAN_EXCLUSIVE_HPP diff --git a/test_conformance/clcpp/workgroups/test_wg_scan_inclusive.hpp b/test_conformance/clcpp/workgroups/test_wg_scan_inclusive.hpp new file mode 100644 index 00000000..34096ebb --- /dev/null +++ b/test_conformance/clcpp/workgroups/test_wg_scan_inclusive.hpp @@ -0,0 +1,324 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_WG_TEST_WG_SCAN_INCLUSIVE_HPP +#define TEST_CONFORMANCE_CLCPP_WG_TEST_WG_SCAN_INCLUSIVE_HPP + +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" +// Common for tests of work-group functions +#include "common.hpp" + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +template +std::string generate_wg_scan_inclusive_kernel_code() +{ + return + "__kernel void test_wg_scan_inclusive(global " + type_name() + " *input, global " + type_name() + " *output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + "\n" + " " + type_name() + " result = work_group_scan_inclusive_" + to_string(op) + "(input[tid]);\n" + " output[tid] = result;\n" + "}\n"; +} +#else +template +std::string generate_wg_scan_inclusive_kernel_code() +{ + return "#include \n" + "#include \n" + "#include \n" + "using namespace cl;\n" + "__kernel void test_wg_scan_inclusive(global_ptr<" + type_name() + "[]> input, " + "global_ptr<" + type_name() + "[]> output)\n" + "{\n" + " ulong tid = get_global_id(0);\n" + " " + type_name() + " result = work_group_scan_inclusive(input[tid]);\n" + " output[tid] = result;\n" + "}\n"; +} +#endif + +template +int verify_wg_scan_inclusive_add(const std::vector &in, const std::vector &out, size_t wg_size) +{ + size_t i, j; + for (i = 0; i < in.size(); i += wg_size) + { + CL_INT_TYPE sum = 0; + + // Check if all work-items in work-group wrote correct value + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j++) + { + sum += in[i + j]; + if (sum != out[i + j]) + { + log_info( + "work_group_scan_inclusive_add %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(sum), + static_cast(out[i + j])); + return -1; + } + } + } + return CL_SUCCESS; +} + +template +int verify_wg_scan_inclusive_min(const std::vector &in, const std::vector &out, size_t wg_size) +{ + size_t i, j; + for (i = 0; i < in.size(); i += wg_size) + { + CL_INT_TYPE min = (std::numeric_limits::max)(); + + // Check if all work-items in work-group wrote correct value + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j++) + { + min = (std::min)(min, in[i + j]); + if (min != out[i + j]) + { + log_info( + "work_group_scan_inclusive_min %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(min), + static_cast(out[i + j])); + return -1; + } + } + } + return CL_SUCCESS; +} + +template +int verify_wg_scan_inclusive_max(const std::vector &in, const std::vector &out, size_t wg_size) +{ + size_t i, j; + for (i = 0; i < in.size(); i += wg_size) + { + CL_INT_TYPE max = (std::numeric_limits::min)(); + + // Check if all work-items in work-group wrote correct value + for (j = 0; j < ((in.size() - i) > wg_size ? wg_size : (in.size() - i)); j++) + { + max = (std::max)(max, in[i + j]); + if (max != out[i + j]) + { + log_info( + "work_group_scan_inclusive_max %s: Error at %lu: expected = %lu, got = %lu\n", + type_name().c_str(), + i + j, + static_cast(max), + static_cast(out[i + j])); + return -1; + } + } + } + return CL_SUCCESS; +} + +template +int verify_wg_scan_inclusive(const std::vector &in, const std::vector &out, size_t wg_size) +{ + switch (op) + { + case work_group_op::add: + return verify_wg_scan_inclusive_add(in, out, wg_size); + case work_group_op::min: + return verify_wg_scan_inclusive_min(in, out, wg_size); + case work_group_op::max: + return verify_wg_scan_inclusive_max(in, out, wg_size); + } + return -1; +} + +template +int work_group_scan_inclusive(cl_device_id device, cl_context context, cl_command_queue queue, size_t count) +{ + // don't run test for unsupported types + if(!type_supported(device)) + { + return CL_SUCCESS; + } + + cl_mem buffers[2]; + cl_program program; + cl_kernel kernel; + size_t wg_size; + size_t work_size[1]; + int err; + + std::string code_str = generate_wg_scan_inclusive_kernel_code(); +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_scan_inclusive"); + RETURN_ON_ERROR(err) + return err; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_scan_inclusive", "-cl-std=CL2.0", false); + RETURN_ON_ERROR(err) +#else + err = create_opencl_kernel(context, &program, &kernel, code_str, "test_wg_scan_inclusive"); + RETURN_ON_ERROR(err) +#endif + + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &wg_size, NULL); + RETURN_ON_CL_ERROR(err, "clGetKernelWorkGroupInfo") + + // Calculate global work size + size_t flat_work_size; + size_t wg_number = static_cast( + std::ceil(static_cast(count) / wg_size) + ); + flat_work_size = wg_number * wg_size; + work_size[0] = flat_work_size; + + std::vector input = generate_input(flat_work_size, wg_size); + std::vector output = generate_output(flat_work_size, wg_size); + + buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(CL_INT_TYPE) * input.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + buffers[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(CL_INT_TYPE) * output.size(), NULL, &err); + RETURN_ON_CL_ERROR(err, "clCreateBuffer"); + + err = clEnqueueWriteBuffer( + queue, buffers[0], CL_TRUE, 0, sizeof(CL_INT_TYPE) * input.size(), + static_cast(input.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueWriteBuffer"); + + err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]); + err |= clSetKernelArg(kernel, 1, sizeof(buffers[1]), &buffers[1]); + RETURN_ON_CL_ERROR(err, "clSetKernelArg"); + + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, &wg_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel"); + + err = clEnqueueReadBuffer( + queue, buffers[1], CL_TRUE, 0, sizeof(CL_INT_TYPE) * output.size(), + static_cast(output.data()), 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer"); + + if (verify_wg_scan_inclusive(input, output, wg_size) != CL_SUCCESS) + { + RETURN_ON_ERROR_MSG(-1, "work_group_scan_inclusive_%s %s failed", to_string(op).c_str(), type_name().c_str()); + } + log_info("work_group_scan_inclusive_%s %s passed\n", to_string(op).c_str(), type_name().c_str()); + + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + return err; +} + +AUTO_TEST_CASE(test_work_group_scan_inclusive_add) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = work_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +AUTO_TEST_CASE(test_work_group_scan_inclusive_min) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = work_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +AUTO_TEST_CASE(test_work_group_scan_inclusive_max) +(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int error = CL_SUCCESS; + int local_error = CL_SUCCESS; + + local_error = work_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + local_error = work_group_scan_inclusive(device, context, queue, n_elems); + CHECK_ERROR(local_error) + error |= local_error; + + if(error != CL_SUCCESS) + return -1; + return CL_SUCCESS; +} + +#endif // TEST_CONFORMANCE_CLCPP_WG_TEST_WG_SCAN_INCLUSIVE_HPP diff --git a/test_conformance/clcpp/workitems/CMakeLists.txt b/test_conformance/clcpp/workitems/CMakeLists.txt new file mode 100644 index 00000000..9aa2cdf3 --- /dev/null +++ b/test_conformance/clcpp/workitems/CMakeLists.txt @@ -0,0 +1,12 @@ +set(MODULE_NAME CPP_WORKITEMS) + +set(${MODULE_NAME}_SOURCES + main.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/clcpp/workitems/main.cpp b/test_conformance/clcpp/workitems/main.cpp new file mode 100644 index 00000000..412e4ea6 --- /dev/null +++ b/test_conformance/clcpp/workitems/main.cpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../common.hpp" + +#include "test_workitems.hpp" + + +int main(int argc, const char *argv[]) +{ + // Get list to all test functions + std::vector testfn_list = autotest::test_suite::get_test_functions(); + // Get names of all test functions + std::vector testfn_names = autotest::test_suite::get_test_names(); + // Create a vector of pointers to the names test functions + std::vector testfn_names_c_str = autotest::get_strings_ptrs(testfn_names); + return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0); +} diff --git a/test_conformance/clcpp/workitems/test_workitems.hpp b/test_conformance/clcpp/workitems/test_workitems.hpp new file mode 100644 index 00000000..eb5087c5 --- /dev/null +++ b/test_conformance/clcpp/workitems/test_workitems.hpp @@ -0,0 +1,418 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFORMANCE_CLCPP_WI_TEST_WORKITEMS_HPP +#define TEST_CONFORMANCE_CLCPP_WI_TEST_WORKITEMS_HPP + +#include +#include +#include + +// Common for all OpenCL C++ tests +#include "../common.hpp" + + +namespace test_workitems { + +struct test_options +{ + bool uniform_work_group_size; + size_t max_count; + size_t num_tests; +}; + +struct output_type +{ + cl_uint work_dim; + cl_ulong global_size[3]; + cl_ulong global_id[3]; + cl_ulong local_size[3]; + cl_ulong enqueued_local_size[3]; + cl_ulong local_id[3]; + cl_ulong num_groups[3]; + cl_ulong group_id[3]; + cl_ulong global_offset[3]; + cl_ulong global_linear_id; + cl_ulong local_linear_id; + cl_ulong sub_group_size; + cl_ulong max_sub_group_size; + cl_ulong num_sub_groups; + cl_ulong enqueued_num_sub_groups; + cl_ulong sub_group_id; + cl_ulong sub_group_local_id; +}; + +const std::string source_common = R"( +struct output_type +{ + uint work_dim; + ulong global_size[3]; + ulong global_id[3]; + ulong local_size[3]; + ulong enqueued_local_size[3]; + ulong local_id[3]; + ulong num_groups[3]; + ulong group_id[3]; + ulong global_offset[3]; + ulong global_linear_id; + ulong local_linear_id; + ulong sub_group_size; + ulong max_sub_group_size; + ulong num_sub_groups; + ulong enqueued_num_sub_groups; + ulong sub_group_id; + ulong sub_group_local_id; +}; +)"; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) +const std::string source = + source_common + + R"( + #ifdef cl_khr_subgroups + #pragma OPENCL EXTENSION cl_khr_subgroups : enable + #endif + + kernel void test(global struct output_type *output) + { + const ulong gid = get_global_linear_id(); + output[gid].work_dim = get_work_dim(); + for (uint dimindx = 0; dimindx < 3; dimindx++) + { + output[gid].global_size[dimindx] = get_global_size(dimindx); + output[gid].global_id[dimindx] = get_global_id(dimindx); + output[gid].local_size[dimindx] = get_local_size(dimindx); + output[gid].enqueued_local_size[dimindx] = get_enqueued_local_size(dimindx); + output[gid].local_id[dimindx] = get_local_id(dimindx); + output[gid].num_groups[dimindx] = get_num_groups(dimindx); + output[gid].group_id[dimindx] = get_group_id(dimindx); + output[gid].global_offset[dimindx] = get_global_offset(dimindx); + } + output[gid].global_linear_id = get_global_linear_id(); + output[gid].local_linear_id = get_local_linear_id(); + #ifdef cl_khr_subgroups + output[gid].sub_group_size = get_sub_group_size(); + output[gid].max_sub_group_size = get_max_sub_group_size(); + output[gid].num_sub_groups = get_num_sub_groups(); + output[gid].enqueued_num_sub_groups = get_enqueued_num_sub_groups(); + output[gid].sub_group_id = get_sub_group_id(); + output[gid].sub_group_local_id = get_sub_group_local_id(); + #endif + } + )"; +#else +const std::string source = + R"( + #include + #include + using namespace cl; + )" + + source_common + + R"( + + kernel void test(global_ptr output) + { + const size_t gid = get_global_linear_id(); + output[gid].work_dim = get_work_dim(); + for (uint dimindx = 0; dimindx < 3; dimindx++) + { + output[gid].global_size[dimindx] = get_global_size(dimindx); + output[gid].global_id[dimindx] = get_global_id(dimindx); + output[gid].local_size[dimindx] = get_local_size(dimindx); + output[gid].enqueued_local_size[dimindx] = get_enqueued_local_size(dimindx); + output[gid].local_id[dimindx] = get_local_id(dimindx); + output[gid].num_groups[dimindx] = get_num_groups(dimindx); + output[gid].group_id[dimindx] = get_group_id(dimindx); + output[gid].global_offset[dimindx] = get_global_offset(dimindx); + } + output[gid].global_linear_id = get_global_linear_id(); + output[gid].local_linear_id = get_local_linear_id(); + output[gid].sub_group_size = get_sub_group_size(); + output[gid].max_sub_group_size = get_max_sub_group_size(); + output[gid].num_sub_groups = get_num_sub_groups(); + output[gid].enqueued_num_sub_groups = get_enqueued_num_sub_groups(); + output[gid].sub_group_id = get_sub_group_id(); + output[gid].sub_group_local_id = get_sub_group_local_id(); + } + + )"; +#endif + +#define CHECK_EQUAL(result, expected, func_name) \ + if (result != expected) \ + { \ + RETURN_ON_ERROR_MSG(-1, \ + "Function %s failed. Expected: %s, got: %s", func_name, \ + format_value(expected).c_str(), format_value(result).c_str() \ + ); \ + } + +#define CHECK(expression, func_name) \ + if (expression) \ + { \ + RETURN_ON_ERROR_MSG(-1, \ + "Function %s returned incorrect result", func_name \ + ); \ + } + +int test_workitems(cl_device_id device, cl_context context, cl_command_queue queue, test_options options) +{ + int error = CL_SUCCESS; + + cl_program program; + cl_kernel kernel; + + std::string kernel_name = "test"; + +// ----------------------------------------------------------------------------------- +// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------ +// ----------------------------------------------------------------------------------- +// Only OpenCL C++ to SPIR-V compilation +#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) + return error; +// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code) +#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name, "-cl-std=CL2.0", false + ); + RETURN_ON_ERROR(error) +// Normal run +#else + error = create_opencl_kernel( + context, &program, &kernel, + source, kernel_name + ); + RETURN_ON_ERROR(error) +#endif + + size_t max_work_group_size; + size_t max_local_sizes[3]; + error = get_max_allowed_work_group_size(context, kernel, &max_work_group_size, max_local_sizes); + RETURN_ON_ERROR(error) + + bool check_sub_groups = true; + bool check_sub_groups_limits = true; +#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS) + check_sub_groups = false; + check_sub_groups_limits = false; + if (is_extension_available(device, "cl_khr_subgroups")) + { + size_t major, minor; + error = get_device_version(device, &major, &minor); + RETURN_ON_ERROR(error) + check_sub_groups_limits = (major > 2 || major == 2 && minor >= 1); // clGetKernelSubGroupInfo is from 2.1 + check_sub_groups = true; + } +#endif + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution count_dis(1, options.max_count); + + for (int test = 0; test < options.num_tests; test++) + { + for (size_t dim = 1; dim <= 3; dim++) + { + size_t global_size[3] = { 1, 1, 1 }; + size_t global_offset[3] = { 0, 0, 0 }; + size_t enqueued_local_size[3] = { 1, 1, 1 }; + size_t count = count_dis(gen); + std::uniform_int_distribution global_size_dis(1, static_cast(pow(count, 1.0 / dim))); + for (int d = 0; d < dim; d++) + { + std::uniform_int_distribution enqueued_local_size_dis(1, max_local_sizes[d]); + global_size[d] = global_size_dis(gen); + global_offset[d] = global_size_dis(gen); + enqueued_local_size[d] = enqueued_local_size_dis(gen); + } + // Local work size must not exceed CL_KERNEL_WORK_GROUP_SIZE for this kernel + while (enqueued_local_size[0] * enqueued_local_size[1] * enqueued_local_size[2] > max_work_group_size) + { + // otherwise decrease it until it fits + for (int d = 0; d < dim; d++) + { + enqueued_local_size[d] = (std::max)((size_t)1, enqueued_local_size[d] / 2); + } + } + if (options.uniform_work_group_size) + { + for (int d = 0; d < dim; d++) + { + global_size[d] = get_uniform_global_size(global_size[d], enqueued_local_size[d]); + } + } + count = global_size[0] * global_size[1] * global_size[2]; + + cl_mem output_buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(output_type) * count, NULL, &error); + RETURN_ON_CL_ERROR(error, "clCreateBuffer") + + const char pattern = 0; + error = clEnqueueFillBuffer(queue, output_buffer, &pattern, sizeof(pattern), 0, sizeof(output_type) * count, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueFillBuffer") + + error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer); + RETURN_ON_CL_ERROR(error, "clSetKernelArg") + + error = clEnqueueNDRangeKernel(queue, kernel, dim, global_offset, global_size, enqueued_local_size, 0, NULL, NULL); + RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel") + + std::vector output(count); + error = clEnqueueReadBuffer( + queue, output_buffer, CL_TRUE, + 0, sizeof(output_type) * count, + static_cast(output.data()), + 0, NULL, NULL + ); + RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer") + + error = clReleaseMemObject(output_buffer); + RETURN_ON_CL_ERROR(error, "clReleaseMemObject") + + size_t sub_group_count_for_ndrange = 0; + size_t max_sub_group_size_for_ndrange = 0; + if (check_sub_groups_limits) + { + error = clGetKernelSubGroupInfo(kernel, device, CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE, + sizeof(size_t) * dim, enqueued_local_size, + sizeof(size_t), &sub_group_count_for_ndrange, NULL); + RETURN_ON_CL_ERROR(error, "clGetKernelSubGroupInfo") + + error = clGetKernelSubGroupInfo(kernel, device, CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE, + sizeof(size_t) * dim, enqueued_local_size, + sizeof(size_t), &max_sub_group_size_for_ndrange, NULL); + RETURN_ON_CL_ERROR(error, "clGetKernelSubGroupInfo") + } + + size_t num_groups[3]; + for (int d = 0; d < 3; d++) + num_groups[d] = static_cast(std::ceil(static_cast(global_size[d]) / enqueued_local_size[d])); + + size_t group_id[3]; + for (group_id[0] = 0; group_id[0] < num_groups[0]; group_id[0]++) + for (group_id[1] = 0; group_id[1] < num_groups[1]; group_id[1]++) + for (group_id[2] = 0; group_id[2] < num_groups[2]; group_id[2]++) + { + size_t local_size[3]; + for (int d = 0; d < 3; d++) + { + if (group_id[d] == num_groups[d] - 1) + local_size[d] = global_size[d] - group_id[d] * enqueued_local_size[d]; + else + local_size[d] = enqueued_local_size[d]; + } + + size_t local_id[3]; + for (local_id[0] = 0; local_id[0] < local_size[0]; local_id[0]++) + for (local_id[1] = 0; local_id[1] < local_size[1]; local_id[1]++) + for (local_id[2] = 0; local_id[2] < local_size[2]; local_id[2]++) + { + size_t global_id_wo_offset[3]; + size_t global_id[3]; + for (int d = 0; d < 3; d++) + { + global_id_wo_offset[d] = group_id[d] * enqueued_local_size[d] + local_id[d]; + global_id[d] = global_id_wo_offset[d] + global_offset[d]; + } + + // Ignore if the current work-item is outside of global work size (i.e. the work-group is non-uniform) + if (global_id_wo_offset[0] >= global_size[0] || + global_id_wo_offset[1] >= global_size[1] || + global_id_wo_offset[2] >= global_size[2]) break; + + const size_t global_linear_id = + global_id_wo_offset[2] * global_size[1] * global_size[0] + + global_id_wo_offset[1] * global_size[0] + + global_id_wo_offset[0]; + const size_t local_linear_id = + local_id[2] * local_size[1] * local_size[0] + + local_id[1] * local_size[0] + + local_id[0]; + + const output_type &o = output[global_linear_id]; + + CHECK_EQUAL(o.work_dim, dim, "get_work_dim") + for (int d = 0; d < 3; d++) + { + CHECK_EQUAL(o.global_size[d], global_size[d], "get_global_size") + CHECK_EQUAL(o.global_id[d], global_id[d], "get_global_id") + CHECK_EQUAL(o.local_size[d], local_size[d], "get_local_size") + CHECK_EQUAL(o.enqueued_local_size[d], enqueued_local_size[d], "get_enqueued_local_size") + CHECK_EQUAL(o.local_id[d], local_id[d], "get_local_id") + CHECK_EQUAL(o.num_groups[d], num_groups[d], "get_num_groups") + CHECK_EQUAL(o.group_id[d], group_id[d], "get_group_id") + CHECK_EQUAL(o.global_offset[d], global_offset[d], "get_global_offset") + } + + CHECK_EQUAL(o.global_linear_id, global_linear_id, "get_global_linear_id") + CHECK_EQUAL(o.local_linear_id, local_linear_id, "get_local_linear_id") + + // A few (but not all possible) sub-groups related checks + if (check_sub_groups) + { + if (check_sub_groups_limits) + { + CHECK_EQUAL(o.max_sub_group_size, max_sub_group_size_for_ndrange, "get_max_sub_group_size") + CHECK_EQUAL(o.enqueued_num_sub_groups, sub_group_count_for_ndrange, "get_enqueued_num_sub_groups") + } + CHECK(o.sub_group_size == 0 || o.sub_group_size > o.max_sub_group_size, "get_sub_group_size or get_max_sub_group_size") + CHECK(o.num_sub_groups == 0 || o.num_sub_groups > o.enqueued_num_sub_groups, "get_enqueued_num_sub_groups") + CHECK(o.sub_group_id >= o.num_sub_groups, "get_sub_group_id or get_num_sub_groups") + CHECK(o.sub_group_local_id >= o.sub_group_size, "get_sub_group_local_id or get_sub_group_size") + } + } + } + } + } + + clReleaseKernel(kernel); + clReleaseProgram(program); + return error; +} + +#undef CHECK_EQUAL +#undef CHECK + +AUTO_TEST_CASE(test_workitems_uniform) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + test_options options; + options.uniform_work_group_size = true; + options.max_count = num_elements; + options.num_tests = 1000; + return test_workitems(device, context, queue, options); +} + +AUTO_TEST_CASE(test_workitems_non_uniform) +(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + test_options options; + options.uniform_work_group_size = false; + options.max_count = num_elements; + options.num_tests = 1000; + return test_workitems(device, context, queue, options); +} + +} // namespace + +#endif // TEST_CONFORMANCE_CLCPP_WI_TEST_WORKITEMS_HPP diff --git a/test_conformance/commonfns/CMakeLists.txt b/test_conformance/commonfns/CMakeLists.txt new file mode 100644 index 00000000..677bca15 --- /dev/null +++ b/test_conformance/commonfns/CMakeLists.txt @@ -0,0 +1,33 @@ +set(MODULE_NAME COMMONFNS) + +set(${MODULE_NAME}_SOURCES + main.c + test_clamp.c + test_degrees.c + test_max.c + test_maxf.c + test_min.c + test_minf.c + test_mix.c + test_radians.c + test_step.c + test_stepf.c + test_smoothstep.c + test_smoothstepf.c + test_sign.c + test_fmax.c + test_fmin.c + test_fmaxf.c + test_fminf.c + test_binary_fn.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) diff --git a/test_conformance/commonfns/Jamfile b/test_conformance/commonfns/Jamfile new file mode 100644 index 00000000..48bdaed3 --- /dev/null +++ b/test_conformance/commonfns/Jamfile @@ -0,0 +1,33 @@ +project + : requirements + gcc:-xc++ + msvc:"/TP" + ; + +exe test_commonfns + : main.c + test_binary_fn.c + test_clamp.c + test_degrees.c + test_fmax.c + test_fmaxf.c + test_fmin.c + test_fminf.c + test_max.c + test_maxf.c + test_min.c + test_minf.c + test_mix.c + test_radians.c + test_sign.c + test_smoothstep.c + test_smoothstepf.c + test_step.c + test_stepf.c + ; + +install dist + : test_commonfns + : debug:$(DIST)/debug/tests/test_conformance/commonfns + release:$(DIST)/release/tests/test_conformance/commonfns + ; diff --git a/test_conformance/commonfns/Makefile b/test_conformance/commonfns/Makefile new file mode 100644 index 00000000..474066f7 --- /dev/null +++ b/test_conformance/commonfns/Makefile @@ -0,0 +1,45 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c test_clamp.c test_degrees.c \ + test_max.c test_maxf.c test_min.c test_minf.c \ + test_mix.c test_radians.c test_step.c test_stepf.c\ + test_smoothstep.c test_smoothstepf.c test_sign.c \ + test_fmax.c test_fmin.c test_fmaxf.c test_fminf.c test_binary_fn.c \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/conversions.c \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/kernelHelpers.c + +SOURCES = $(abspath $(SRCS)) + +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = $(SOURCES) +HEADERS = +TARGET = test_commonfns +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${RC_CFLAGS} ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/commonfns/main.c b/test_conformance/commonfns/main.c new file mode 100644 index 00000000..44b0b510 --- /dev/null +++ b/test_conformance/commonfns/main.c @@ -0,0 +1,87 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include "procs.h" + +int g_arrVecSizes[kVectorSizeCount + kStrangeVectorSizeCount]; +int g_arrStrangeVectorSizes[kStrangeVectorSizeCount] = {3}; + +static void initVecSizes() { + int i; + for(i = 0; i < kVectorSizeCount; ++i) { + g_arrVecSizes[i] = (1< +#include +#include +#include + +#include "procs.h" + +const char *binary_fn_code_pattern = +"%s\n" /* optional pragma */ +"__kernel void test_fn(__global %s%s *x, __global %s%s *y, __global %s%s *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = %s(x[tid], y[tid]);\n" +"}\n"; + +const char *binary_fn_code_pattern_v3 = +"%s\n" /* optional pragma */ +"__kernel void test_fn(__global %s *x, __global %s *y, __global %s *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" vstore3(%s(vload3(tid,x), vload3(tid,y) ), tid, dst);\n" +"}\n"; + +const char *binary_fn_code_pattern_v3_scalar = +"%s\n" /* optional pragma */ +"__kernel void test_fn(__global %s *x, __global %s *y, __global %s *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" vstore3(%s(vload3(tid,x), y[tid] ), tid, dst);\n" +"}\n"; + +int test_binary_fn( cl_device_id device, cl_context context, cl_command_queue queue, int n_elems, + const char *fnName, bool vectorSecondParam, + binary_verify_float_fn floatVerifyFn, binary_verify_double_fn doubleVerifyFn ) +{ + cl_mem streams[6]; + cl_float *input_ptr[2], *output_ptr; + cl_double *input_ptr_double[2], *output_ptr_double=NULL; + cl_program *program; + cl_kernel *kernel; + size_t threads[1]; + int num_elements; + int err; + int i, j; + MTdata d; + + program = (cl_program*)malloc(sizeof(cl_program)*kTotalVecCount*2); + kernel = (cl_kernel*)malloc(sizeof(cl_kernel)*kTotalVecCount*2); + + num_elements = n_elems * (1 << (kTotalVecCount-1)); + + int test_double = 0; + if(is_extension_available( device, "cl_khr_fp64" )) + { + log_info("Testing doubles.\n"); + test_double = 1; + } + + for( i = 0; i < 2; i++ ) + { + input_ptr[i] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + if (test_double) input_ptr_double[i] = (cl_double*)malloc(sizeof(cl_double) * num_elements); + } + output_ptr = (cl_float*)malloc(sizeof(cl_float) * num_elements); + if (test_double) output_ptr_double = (cl_double*)malloc(sizeof(cl_double) * num_elements); + + for( i = 0; i < 3; i++ ) + { + streams[ i ] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, &err ); + test_error( err, "clCreateBuffer failed"); + } + + if (test_double) + for( i = 3; i < 6; i++ ) + { + streams[ i ] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_double) * num_elements, NULL, &err ); + test_error( err, "clCreateBuffer failed"); + } + + d = init_genrand( gRandomSeed ); + for( j = 0; j < num_elements; j++ ) + { + input_ptr[0][j] = get_random_float(-0x20000000, 0x20000000, d); + input_ptr[1][j] = get_random_float(-0x20000000, 0x20000000, d); + if (test_double) + { + input_ptr_double[0][j] = get_random_double(-0x20000000, 0x20000000, d); + input_ptr_double[1][j] = get_random_double(-0x20000000, 0x20000000, d); + } + } + free_mtdata(d); d = NULL; + + for( i = 0; i < 2; i++ ) + { + err = clEnqueueWriteBuffer( queue, streams[ i ], CL_TRUE, 0, sizeof( cl_float ) * num_elements, input_ptr[ i ], 0, NULL, NULL ); + test_error( err, "Unable to write input buffer" ); + + if (test_double) + { + err = clEnqueueWriteBuffer( queue, streams[ 3 + i ], CL_TRUE, 0, sizeof( cl_double ) * num_elements, input_ptr_double[ i ], 0, NULL, NULL ); + test_error( err, "Unable to write input buffer" ); + } + } + + for( i = 0; i < kTotalVecCount; i++ ) + { + char programSrc[ 10240 ]; + char vecSizeNames[][ 3 ] = { "", "2", "4", "8", "16", "3" }; + + if(i >= kVectorSizeCount) { + // do vec3 print + + if(vectorSecondParam) { + sprintf( programSrc,binary_fn_code_pattern_v3, "", "float", "float", "float", fnName ); + } else { + sprintf( programSrc,binary_fn_code_pattern_v3_scalar, "", "float", "float", "float", fnName ); + } + } else { + // do regular + sprintf( programSrc, binary_fn_code_pattern, "", "float", vecSizeNames[ i ], "float", vectorSecondParam ? vecSizeNames[ i ] : "", "float", vecSizeNames[ i ], fnName ); + } + const char *ptr = programSrc; + err = create_single_kernel_helper( context, &program[ i ], &kernel[ i ], 1, &ptr, "test_fn" ); + test_error( err, "Unable to create kernel" ); + + if (test_double) + { + if(i >= kVectorSizeCount) { + if(vectorSecondParam) { + sprintf( programSrc, binary_fn_code_pattern_v3, "#pragma OPENCL EXTENSION cl_khr_fp64 : enable", + "double", "double", "double", fnName ); + } else { + + sprintf( programSrc, binary_fn_code_pattern_v3_scalar, "#pragma OPENCL EXTENSION cl_khr_fp64 : enable", + "double", "double", "double", fnName ); + } + } else { + sprintf( programSrc, binary_fn_code_pattern, "#pragma OPENCL EXTENSION cl_khr_fp64 : enable", + "double", vecSizeNames[ i ], "double", vectorSecondParam ? vecSizeNames[ i ] : "", "double", vecSizeNames[ i ], fnName ); + } + ptr = programSrc; + err = create_single_kernel_helper( context, &program[ kTotalVecCount + i ], &kernel[ kTotalVecCount + i ], 1, &ptr, "test_fn" ); + test_error( err, "Unable to create kernel" ); + } + } + + for( i = 0; i < kTotalVecCount; i++ ) + { + for( j = 0; j < 3; j++ ) + { + err = clSetKernelArg( kernel[ i ], j, sizeof( streams[ j ] ), &streams[ j ] ); + test_error( err, "Unable to set kernel argument" ); + } + + threads[0] = (size_t)n_elems; + + err = clEnqueueNDRangeKernel( queue, kernel[i], 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( err, "Unable to execute kernel" ); + + err = clEnqueueReadBuffer( queue, streams[2], true, 0, sizeof(cl_float)*num_elements, (void *)output_ptr, 0, NULL, NULL ); + test_error( err, "Unable to read results" ); + + + + if( floatVerifyFn( input_ptr[0], input_ptr[1], output_ptr, n_elems, ((g_arrVecSizes[i])) ) ) + { + log_error(" float%d%s test failed\n", ((g_arrVecSizes[i])), vectorSecondParam ? "" : ", float"); + err = -1; + } + else + { + log_info(" float%d%s test passed\n", ((g_arrVecSizes[i])), vectorSecondParam ? "" : ", float"); + err = 0; + } + + if (err) + break; + } + + if (test_double) + { + for( i = 0; i < kTotalVecCount; i++ ) + { + for( j = 0; j < 3; j++ ) + { + err = clSetKernelArg( kernel[ kTotalVecCount + i ], j, sizeof( streams[ 3 + j ] ), &streams[ 3 + j ] ); + test_error( err, "Unable to set kernel argument" ); + } + + threads[0] = (size_t)n_elems; + + err = clEnqueueNDRangeKernel( queue, kernel[kTotalVecCount + i], 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( err, "Unable to execute kernel" ); + + err = clEnqueueReadBuffer( queue, streams[5], CL_TRUE, 0, sizeof(cl_double)*num_elements, (void *)output_ptr_double, 0, NULL, NULL ); + test_error( err, "Unable to read results" ); + + if( doubleVerifyFn( input_ptr_double[0], input_ptr_double[1], output_ptr_double, n_elems, ((g_arrVecSizes[i])))) + { + log_error(" double%d%s test failed\n", ((g_arrVecSizes[i])), vectorSecondParam ? "" : ", double"); + err = -1; + } + else + { + log_info(" double%d%s test passed\n", ((g_arrVecSizes[i])), vectorSecondParam ? "" : ", double"); + err = 0; + } + + if (err) + break; + } + } + + + for( i = 0; i < ((test_double) ? 6 : 3); i++ ) + { + clReleaseMemObject(streams[i]); + } + for (i=0; i < ((test_double) ? kTotalVecCount * 2 : kTotalVecCount) ; i++) + { + clReleaseKernel(kernel[i]); + clReleaseProgram(program[i]); + } + free(input_ptr[0]); + free(input_ptr[1]); + free(output_ptr); + free(program); + free(kernel); + + if (test_double) + { + free(input_ptr_double[0]); + free(input_ptr_double[1]); + free(output_ptr_double); + } + + return err; +} + + diff --git a/test_conformance/commonfns/test_clamp.c b/test_conformance/commonfns/test_clamp.c new file mode 100644 index 00000000..9fb46749 --- /dev/null +++ b/test_conformance/commonfns/test_clamp.c @@ -0,0 +1,311 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846264338327950288 +#endif + +#define CLAMP_KERNEL( type ) \ + const char *clamp_##type##_kernel_code = \ + EMIT_PRAGMA_DIRECTIVE \ + "__kernel void test_clamp(__global " #type " *x, __global " #type " *minval, __global " #type " *maxval, __global " #type " *dst)\n" \ + "{\n" \ + " int tid = get_global_id(0);\n" \ + "\n" \ + " dst[tid] = clamp(x[tid], minval[tid], maxval[tid]);\n" \ + "}\n"; + +#define CLAMP_KERNEL_V( type, size) \ + const char *clamp_##type##size##_kernel_code = \ + EMIT_PRAGMA_DIRECTIVE \ + "__kernel void test_clamp(__global " #type #size " *x, __global " #type #size " *minval, __global " #type #size " *maxval, __global " #type #size " *dst)\n" \ + "{\n" \ + " int tid = get_global_id(0);\n" \ + "\n" \ + " dst[tid] = clamp(x[tid], minval[tid], maxval[tid]);\n" \ + "}\n"; + +#define CLAMP_KERNEL_V3( type, size) \ + const char *clamp_##type##size##_kernel_code = \ + EMIT_PRAGMA_DIRECTIVE \ + "__kernel void test_clamp(__global " #type " *x, __global " #type " *minval, __global " #type " *maxval, __global " #type " *dst)\n" \ + "{\n" \ + " int tid = get_global_id(0);\n" \ + "\n" \ + " vstore3(clamp(vload3(tid, x), vload3(tid,minval), vload3(tid,maxval)), tid, dst);\n" \ + "}\n"; + +#define EMIT_PRAGMA_DIRECTIVE " " +CLAMP_KERNEL( float ) +CLAMP_KERNEL_V( float, 2 ) +CLAMP_KERNEL_V( float, 4 ) +CLAMP_KERNEL_V( float, 8 ) +CLAMP_KERNEL_V( float, 16 ) +CLAMP_KERNEL_V3( float, 3) +#undef EMIT_PRAGMA_DIRECTIVE + +#define EMIT_PRAGMA_DIRECTIVE "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" +CLAMP_KERNEL( double ) +CLAMP_KERNEL_V( double, 2 ) +CLAMP_KERNEL_V( double, 4 ) +CLAMP_KERNEL_V( double, 8 ) +CLAMP_KERNEL_V( double, 16 ) +CLAMP_KERNEL_V3( double, 3 ) +#undef EMIT_PRAGMA_DIRECTIVE + +const char *clamp_float_codes[] = { clamp_float_kernel_code, clamp_float2_kernel_code, clamp_float4_kernel_code, clamp_float8_kernel_code, clamp_float16_kernel_code, clamp_float3_kernel_code }; +const char *clamp_double_codes[] = { clamp_double_kernel_code, clamp_double2_kernel_code, clamp_double4_kernel_code, clamp_double8_kernel_code, clamp_double16_kernel_code, clamp_double3_kernel_code }; + +static int verify_clamp(float *x, float *minval, float *maxval, float *outptr, int n) +{ + float t; + int i; + + for (i=0; i +#include +#include +#include + +#include "procs.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846264338327950288 +#endif + +static int test_degrees_double(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems); + + +const char *degrees_kernel_code = +"__kernel void test_degrees(__global float *src, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = degrees(src[tid]);\n" +"}\n"; + +const char *degrees2_kernel_code = +"__kernel void test_degrees2(__global float2 *src, __global float2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = degrees(src[tid]);\n" +"}\n"; + +const char *degrees4_kernel_code = +"__kernel void test_degrees4(__global float4 *src, __global float4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = degrees(src[tid]);\n" +"}\n"; + +const char *degrees8_kernel_code = +"__kernel void test_degrees8(__global float8 *src, __global float8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = degrees(src[tid]);\n" +"}\n"; + +const char *degrees16_kernel_code = +"__kernel void test_degrees16(__global float16 *src, __global float16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = degrees(src[tid]);\n" +"}\n"; + +const char *degrees3_kernel_code = +"__kernel void test_degrees3(__global float *src, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" vstore3(degrees(vload3(tid,src)),tid,dst);\n" +"}\n"; + + +#define MAX_ERR 2.0f + +static int +verify_degrees(float *inptr, float *outptr, int n) +{ + float error, max_error = 0.0f; + double r, max_val = NAN; + int i, j, max_index = 0; + + for (i=0,j=0; i max_error) + { + max_error = error; + max_index = i; + max_val = r; + if( fabsf(error) > MAX_ERR) + { + log_error( "%d) Error @ %a: *%a vs %a (*%g vs %g) ulps: %f\n", i, inptr[i], r, outptr[i], r, outptr[i], error ); + return 1; + } + } + } + + log_info( "degrees: Max error %f ulps at %d: *%a vs %a (*%g vs %g)\n", max_error, max_index, max_val, outptr[max_index], max_val, outptr[max_index] ); + + return 0; +} + +int +test_degrees(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[2]; + cl_float *input_ptr[1], *output_ptr, *p; + cl_program *program; + cl_kernel *kernel; + void *values[2]; + size_t threads[1]; + int num_elements; + int err; + int i; + MTdata d; + + program = (cl_program*)malloc(sizeof(cl_program)*kTotalVecCount); + kernel = (cl_kernel*)malloc(sizeof(cl_kernel)*kTotalVecCount); + + num_elements = n_elems * (1 << (kTotalVecCount-1)); + + input_ptr[0] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + output_ptr = (cl_float*)malloc(sizeof(cl_float) * num_elements); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + p = input_ptr[0]; + d = init_genrand( gRandomSeed ); + for (i=0; i max_error) + { + max_error = error; + max_index = i; + max_val = r; + if( fabsf(error) > MAX_ERR) + { + log_error( "%d) Error @ %a: *%a vs %a (*%g vs %g) ulps: %f\n", i, inptr[i], r, outptr[i], r, outptr[i], error ); + return 1; + } + } + } + + log_info( "degreesd: Max error %f ulps at %d: *%a vs %a (*%g vs %g)\n", max_error, max_index, max_val, outptr[max_index], max_val, outptr[max_index] ); + + return 0; +} + +static int +test_degrees_double(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[2]; + cl_double *input_ptr[1], *output_ptr, *p; + cl_program *program; + cl_kernel *kernel; + void *values[2]; + size_t threads[1]; + int num_elements; + int err; + int i; + MTdata d; + + program = (cl_program*)malloc(sizeof(cl_program)*kTotalVecCount); + kernel = (cl_kernel*)malloc(sizeof(cl_kernel)*kTotalVecCount); + + // TODO: line below is clearly wrong + num_elements = n_elems * (1 << (kTotalVecCount-1)); + + input_ptr[0] = (cl_double*)malloc(sizeof(cl_double) * num_elements); + output_ptr = (cl_double*)malloc(sizeof(cl_double) * num_elements); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_double) * num_elements, NULL, NULL ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_double) * num_elements, NULL, NULL ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + p = input_ptr[0]; + d = init_genrand( gRandomSeed ); + for (i=0; i +#include +#include +#include + +#include "procs.h" + +static const char *fmax_kernel_code = + "__kernel void test_fmax(__global float *srcA, __global float *srcB, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = fmax(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmax2_kernel_code = + "__kernel void test_fmax2(__global float2 *srcA, __global float2 *srcB, __global float2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = fmax(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmax4_kernel_code = + "__kernel void test_fmax4(__global float4 *srcA, __global float4 *srcB, __global float4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = fmax(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmax8_kernel_code = + "__kernel void test_fmax8(__global float8 *srcA, __global float8 *srcB, __global float8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = fmax(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmax16_kernel_code = + "__kernel void test_fmax16(__global float16 *srcA, __global float16 *srcB, __global float16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = fmax(srcA[tid], srcB[tid]);\n" + "}\n"; + + +static const char *fmax3_kernel_code = + "__kernel void test_fmax3(__global float *srcA, __global float *srcB, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " vstore3(fmax(vload3(tid,srcA), vload3(tid,srcB)),tid,dst);\n" + "}\n"; + +static int +verify_fmax(float *inptrA, float *inptrB, float *outptr, int n) +{ + float r; + int i; + + for (i=0; i= inptrB[i]) ? inptrA[i] : inptrB[i]; + if (r != outptr[i]) + return -1; + } + + return 0; +} + +int +test_fmax(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[3]; + cl_float *input_ptr[2], *output_ptr, *p; + cl_program *program; + cl_kernel *kernel; + void *values[3]; + size_t threads[1]; + int num_elements; + int err; + int i; + MTdata d; + + program = (cl_program*)malloc(sizeof(cl_program)*kTotalVecCount); + kernel = (cl_kernel*)malloc(sizeof(cl_kernel)*kTotalVecCount); + + num_elements = n_elems * (1 << (kTotalVecCount-1)); + + input_ptr[0] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + input_ptr[1] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + output_ptr = (cl_float*)malloc(sizeof(cl_float) * num_elements); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + d = init_genrand( gRandomSeed ); + p = input_ptr[0]; + for (i=0; i +#include +#include +#include + +#include "procs.h" + +static const char *fmax_kernel_code = + "__kernel void test_fmax(__global float *srcA, __global float *srcB, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = fmax(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmax2_kernel_code = + "__kernel void test_fmax2(__global float2 *srcA, __global float *srcB, __global float2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = fmax(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmax4_kernel_code = + "__kernel void test_fmax4(__global float4 *srcA, __global float *srcB, __global float4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = fmax(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmax8_kernel_code = + "__kernel void test_fmax8(__global float8 *srcA, __global float *srcB, __global float8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = fmax(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmax16_kernel_code = + "__kernel void test_fmax16(__global float16 *srcA, __global float *srcB, __global float16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = fmax(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmax3_kernel_code = + "__kernel void test_fmax3(__global float *srcA, __global float *srcB, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " vstore3(fmax(vload3(tid,srcA), srcB[tid]),tid,dst);\n" + "}\n"; + +static int +verify_fmax(float *inptrA, float *inptrB, float *outptr, int n, int veclen) +{ + float r; + int i, j; + + for (i=0; i= inptrB[ii]) ? inptrA[i] : inptrB[ii]; + if (r != outptr[i]) { + log_info("Verify noted discrepancy at %d (of %d) (vec %d, pos %d)\n", + i,n,ii,j); + log_info("SHould be %f, is %f\n", r, outptr[i]); + log_info("Taking max of (%f,%f)\n", inptrA[i], inptrB[i]); + return -1; + } + } + } + + return 0; +} + +int +test_fmaxf(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[3]; + cl_float *input_ptr[2], *output_ptr, *p; + cl_program *program; + cl_kernel *kernel; + void *values[3]; + size_t threads[1]; + int num_elements; + int err; + int i; + MTdata d; + + program = (cl_program*)malloc(sizeof(cl_program)*kTotalVecCount); + kernel = (cl_kernel*)malloc(sizeof(cl_kernel)*kTotalVecCount); + + num_elements = n_elems * (1 << (kTotalVecCount-1)); + + input_ptr[0] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + input_ptr[1] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + output_ptr = (cl_float*)malloc(sizeof(cl_float) * num_elements); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + d = init_genrand( gRandomSeed ); + p = input_ptr[0]; + for (i=0; i +#include +#include +#include + +#include "procs.h" + +static const char *fmin_kernel_code = + "__kernel void test_fmin(__global float *srcA, __global float *srcB, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = fmin(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmin2_kernel_code = + "__kernel void test_fmin2(__global float2 *srcA, __global float2 *srcB, __global float2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = fmin(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmin4_kernel_code = + "__kernel void test_fmin4(__global float4 *srcA, __global float4 *srcB, __global float4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = fmin(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmin8_kernel_code = + "__kernel void test_fmin8(__global float8 *srcA, __global float8 *srcB, __global float8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = fmin(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmin16_kernel_code = + "__kernel void test_fmin16(__global float16 *srcA, __global float16 *srcB, __global float16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = fmin(srcA[tid], srcB[tid]);\n" + "}\n"; + + +static const char *fmin3_kernel_code = + "__kernel void test_fmin3(__global float *srcA, __global float *srcB, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " vstore3(fmin(vload3(tid,srcA), vload3(tid,srcB)),tid,dst);\n" + "}\n"; + +int +verify_fmin(float *inptrA, float *inptrB, float *outptr, int n) +{ + float r; + int i; + + for (i=0; i inptrB[i]) ? inptrB[i] : inptrA[i]; + if (r != outptr[i]) + return -1; + } + + return 0; +} + +int +test_fmin(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[3]; + cl_float *input_ptr[2], *output_ptr, *p; + cl_program *program; + cl_kernel *kernel; + void *values[3]; + size_t threads[1]; + int num_elements; + int err; + int i; + MTdata d; + + program = (cl_program*)malloc(sizeof(cl_program)*kTotalVecCount); + kernel = (cl_kernel*)malloc(sizeof(cl_kernel)*kTotalVecCount); + + num_elements = n_elems * (1 << (kTotalVecCount-1));; + + input_ptr[0] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + input_ptr[1] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + output_ptr = (cl_float*)malloc(sizeof(cl_float) * num_elements); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + streams[2] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + d = init_genrand( gRandomSeed ); + p = input_ptr[0]; + for (i=0; i +#include +#include +#include + +#include "procs.h" + +static const char *fmin_kernel_code = + "__kernel void test_fmin(__global float *srcA, __global float *srcB, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = fmin(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmin2_kernel_code = + "__kernel void test_fmin2(__global float2 *srcA, __global float *srcB, __global float2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = fmin(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmin4_kernel_code = + "__kernel void test_fmin4(__global float4 *srcA, __global float *srcB, __global float4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = fmin(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmin8_kernel_code = + "__kernel void test_fmin8(__global float8 *srcA, __global float *srcB, __global float8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = fmin(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmin16_kernel_code = + "__kernel void test_fmin16(__global float16 *srcA, __global float *srcB, __global float16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = fmin(srcA[tid], srcB[tid]);\n" + "}\n"; + +static const char *fmin3_kernel_code = + "__kernel void test_fmin3(__global float *srcA, __global float *srcB, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " vstore3(fmin(vload3(tid,srcA), srcB[tid]),tid,dst);\n" + "}\n"; + +static int +verify_fmin(float *inptrA, float *inptrB, float *outptr, int n, int veclen) +{ + float r; + int i, j; + + for (i=0; i inptrB[ii]) ? inptrB[ii] : inptrA[i]; + if (r != outptr[i]) + return -1; + } + } + + return 0; +} + +int +test_fminf(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[3]; + cl_float *input_ptr[2], *output_ptr, *p; + cl_program *program; + cl_kernel *kernel; + void *values[3]; + size_t threads[1]; + int num_elements; + int err; + int i; + MTdata d; + + program = (cl_program*)malloc(sizeof(cl_program)*kTotalVecCount); + kernel = (cl_kernel*)malloc(sizeof(cl_kernel)*kTotalVecCount); + + num_elements = n_elems * (1 << (kTotalVecCount-1)); + + input_ptr[0] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + input_ptr[1] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + output_ptr = (cl_float*)malloc(sizeof(cl_float) * num_elements); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + d = init_genrand( gRandomSeed ); + p = input_ptr[0]; + for (i=0; i +#include +#include +#include + +#include "procs.h" + +static int max_verify_float( float *x, float *y, float *out, int numElements, int vecSize ) +{ + for( int i = 0; i < numElements * vecSize; i++ ) + { + float v = ( x[ i ] < y[ i ] ) ? y[ i ] : x[ i ]; + if( v != out[ i ] ) + { + log_error("x[%d]=%g y[%d]=%g out[%d]=%g, expected %g. (index %d is vector %d, element %d, for vector size %d)\n", + i, x[i], i, y[i], i, out[i], v, i, i/vecSize, i%vecSize, vecSize); + return -1; + } + } + return 0; +} + +static int max_verify_double( double *x, double *y, double *out, int numElements, int vecSize ) +{ + for( int i = 0; i < numElements * vecSize; i++ ) + { + double v = ( x[ i ] < y[ i ] ) ? y[ i ] : x[ i ]; + if( v != out[ i ] ) + { + log_error("x[%d]=%g y[%d]=%g out[%d]=%g, expected %g. (index %d is vector %d, element %d, for vector size %d)\n", + i, x[i], i, y[i], i, out[i], v, i, i/vecSize, i%vecSize, vecSize); + return -1; + } + } + return 0; +} + +int test_max(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + return test_binary_fn( device, context, queue, n_elems, "max", true, max_verify_float, max_verify_double ); +} + + diff --git a/test_conformance/commonfns/test_maxf.c b/test_conformance/commonfns/test_maxf.c new file mode 100644 index 00000000..b3992e46 --- /dev/null +++ b/test_conformance/commonfns/test_maxf.c @@ -0,0 +1,64 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +static int max_verify_float( float *x, float *y, float *out, int numElements, int vecSize ) +{ + for( int i = 0; i < numElements; i++ ) + { + for( int j = 0; j < vecSize; j++ ) + { + float v = ( x[ i * vecSize + j ] < y[ i ] ) ? y[ i ] : x[ i * vecSize + j ]; + if( v != out[ i * vecSize + j ] ) + { + log_error( "Failure for vector size %d at position %d, element %d:\n\t max(%a, %a) = *%a vs %a\n", vecSize, i, j, x[ i * vecSize + j ], y[i], v, out[ i * vecSize + j ] ); + return -1; + } + } + } + return 0; +} + +static int max_verify_double( double *x, double *y, double *out, int numElements, int vecSize ) +{ + for( int i = 0; i < numElements; i++ ) + { + for( int j = 0; j < vecSize; j++ ) + { + double v = ( x[ i * vecSize + j ] < y[ i ] ) ? y[ i ] : x[ i * vecSize + j ]; + if( v != out[ i * vecSize + j ] ) + { + log_error( "Failure for vector size %d at position %d, element %d:\n\t max(%a, %a) = *%a vs %a\n", vecSize, i, j, x[ i * vecSize + j ], y[i], v, out[ i * vecSize + j ] ); + return -1; + } + } + } + return 0; +} + +int test_maxf(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + return test_binary_fn( device, context, queue, n_elems, "max", false, max_verify_float, max_verify_double ); +} + + diff --git a/test_conformance/commonfns/test_min.c b/test_conformance/commonfns/test_min.c new file mode 100644 index 00000000..e93b39f0 --- /dev/null +++ b/test_conformance/commonfns/test_min.c @@ -0,0 +1,56 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +static int min_verify_float( float *x, float *y, float *out, int numElements, int vecSize ) +{ + for( int i = 0; i < numElements * vecSize; i++ ) + { + float v = ( y[ i ] < x[ i ] ) ? y[ i ] : x[ i ]; + if( v != out[ i ] ) { + log_error("x[%d]=%g y[%d]=%g out[%d]=%g, expected %g. (index %d is vector %d, element %d, for vector size %d)\n", i, x[i], i, y[i], i, out[i], v, i, i/vecSize, i%vecSize, vecSize); + return -1; + } + } + return 0; +} + +static int min_verify_double( double *x, double *y, double *out, int numElements, int vecSize ) +{ + for( int i = 0; i < numElements * vecSize; i++ ) + { + double v = ( y[ i ] < x[ i ] ) ? y[ i ] : x[ i ]; + if( v != out[ i ] ) { + log_error("x[%d]=%g y[%d]=%g out[%d]=%g, expected %g. (index %d is vector %d, element %d, for vector size %d)\n", i, x[i], i, y[i], i, out[i], v, i, i/vecSize, i%vecSize, vecSize); + return -1; + } + } + return 0; +} + +int test_min(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + return test_binary_fn( device, context, queue, n_elems, "min", true, min_verify_float, min_verify_double ); +} + + diff --git a/test_conformance/commonfns/test_minf.c b/test_conformance/commonfns/test_minf.c new file mode 100644 index 00000000..16f38e4f --- /dev/null +++ b/test_conformance/commonfns/test_minf.c @@ -0,0 +1,70 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/errorHelpers.h" + +static int min_verify_float( float *x, float *y, float *out, int numElements, int vecSize ) +{ + for( int i = 0; i < numElements; i++ ) + { + for( int j = 0; j < vecSize; j++ ) + { + float v = ( y[ i ] < x[ i * vecSize + j ] ) ? y[ i ] : x[ i * vecSize + j ]; + if( v != out[ i * vecSize + j ] ) + { + log_error( "Failure for vector size %d at position %d, element %d:\n\t min(%a, %a) = *%a vs %a\n", vecSize, i, j, x[ i * vecSize + j ], y[i], v, out[ i * vecSize + j ] ); + return -1; + } + } + } + return 0; +} + +static int min_verify_double( double *x, double *y, double *out, int numElements, int vecSize ) +{ + int maxFail = 1; + int numFails = 0; + for( int i = 0; i < numElements; i++ ) + { + for( int j = 0; j < vecSize; j++ ) + { + double v = ( y[ i ] < x[ i * vecSize + j ] ) ? y[ i ] : x[ i * vecSize + j ]; + if( v != out[ i * vecSize + j ] ) + { + log_error( "Failure for vector size %d at position %d, element %d:\n\t min(%a, %a) = *%a vs %a\n", vecSize, i, j, x[ i * vecSize + j ], y[i], v, out[ i * vecSize + j ] ); + ++numFails; + if(numFails >= maxFail) { + return -1; + } + } + } + } + return 0; +} + +int test_minf(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + return test_binary_fn( device, context, queue, n_elems, "min", false, min_verify_float, min_verify_double ); +} + + diff --git a/test_conformance/commonfns/test_mix.c b/test_conformance/commonfns/test_mix.c new file mode 100644 index 00000000..b7beb822 --- /dev/null +++ b/test_conformance/commonfns/test_mix.c @@ -0,0 +1,195 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +const char *mix_kernel_code = +"__kernel void test_mix(__global float *srcA, __global float *srcB, __global float *srcC, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mix(srcA[tid], srcB[tid], srcC[tid]);\n" +"}\n"; + +#define MAX_ERR 1e-3 + +float +verify_mix(float *inptrA, float *inptrB, float *inptrC, float *outptr, int n) +{ + float r, delta, max_err = 0.0f; + int i; + + for (i=0; i max_err) max_err = delta; + } + return max_err; +} + +int +test_mix(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem streams[4]; + cl_float *input_ptr[3], *output_ptr, *p; + cl_program program; + cl_kernel kernel; + void *values[4]; + size_t lengths[1]; + size_t threads[1]; + float max_err; + int err; + int i; + MTdata d; + + input_ptr[0] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + input_ptr[1] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + input_ptr[2] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + output_ptr = (cl_float*)malloc(sizeof(cl_float) * num_elements); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + streams[3] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[3]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + p = input_ptr[0]; + d = init_genrand( gRandomSeed ); + for (i=0; i MAX_ERR) + { + log_error("MIX test failed %g max err\n", max_err); + err = -1; + } + else + { + log_info("MIX test passed %g max err\n", max_err); + err = 0; + } + + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + clReleaseMemObject(streams[2]); + clReleaseMemObject(streams[3]); + clReleaseKernel(kernel); + clReleaseProgram(program); + free(input_ptr[0]); + free(input_ptr[1]); + free(input_ptr[2]); + free(output_ptr); + + return err; +} + + + + + diff --git a/test_conformance/commonfns/test_radians.c b/test_conformance/commonfns/test_radians.c new file mode 100644 index 00000000..0f2dd9d5 --- /dev/null +++ b/test_conformance/commonfns/test_radians.c @@ -0,0 +1,470 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846264338327950288 +#endif + +static int test_radians_double(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems); + + +const char *radians_kernel_code = +"__kernel void test_radians(__global float *src, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = radians(src[tid]);\n" +"}\n"; + +const char *radians2_kernel_code = +"__kernel void test_radians2(__global float2 *src, __global float2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = radians(src[tid]);\n" +"}\n"; + +const char *radians4_kernel_code = +"__kernel void test_radians4(__global float4 *src, __global float4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = radians(src[tid]);\n" +"}\n"; + +const char *radians8_kernel_code = +"__kernel void test_radians8(__global float8 *src, __global float8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = radians(src[tid]);\n" +"}\n"; + +const char *radians16_kernel_code = +"__kernel void test_radians16(__global float16 *src, __global float16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = radians(src[tid]);\n" +"}\n"; + +const char *radians3_kernel_code = +"__kernel void test_radians3(__global float *src, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" vstore3(radians(vload3(tid,src)),tid,dst);\n" +"}\n"; + + +#define MAX_ERR 2.0f + +static float +verify_radians(float *inptr, float *outptr, int n) +{ + float error, max_error = 0.0f; + double r, max_val = NAN; + int i, j, max_index = 0; + + for (i=0,j=0; i max_error) + { + max_error = error; + max_index = i; + max_val = r; + if( fabsf(error) > MAX_ERR) + { + log_error( "%d) Error @ %a: *%a vs %a (*%g vs %g) ulps: %f\n", i, inptr[i], r, outptr[i], r, outptr[i], error ); + return 1; + } + } + } + + log_info( "radians: Max error %f ulps at %d: *%a vs %a (*%g vs %g)\n", max_error, max_index, max_val, outptr[max_index], max_val, outptr[max_index] ); + + return 0; +} + + +int +test_radians(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[2]; + cl_float *input_ptr[1], *output_ptr, *p; + cl_program *program; + cl_kernel *kernel; + void *values[2]; + size_t threads[1]; + int num_elements; + int err; + int i; + MTdata d; + + program = (cl_program*)malloc(sizeof(cl_program)*kTotalVecCount); + kernel = (cl_kernel*)malloc(sizeof(cl_kernel)*kTotalVecCount); + + num_elements = n_elems * (1 << (kTotalVecCount-1)); + + input_ptr[0] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + output_ptr = (cl_float*)malloc(sizeof(cl_float) * num_elements); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + p = input_ptr[0]; + d = init_genrand( gRandomSeed ); + for (i=0; i max_error) + { + max_error = error; + max_index = i; + max_val = r; + if( fabsf(error) > MAX_ERR) + { + log_error( "%d) Error @ %a: *%a vs %a (*%g vs %g) ulps: %f\n", i, inptr[i], r, outptr[i], r, outptr[i], error ); + return 1; + } + } + } + + log_info( "radiansd: Max error %f ulps at %d: *%a vs %a (*%g vs %g)\n", max_error, max_index, max_val, outptr[max_index], max_val, outptr[max_index] ); + + return 0; +} + + +int +test_radians_double(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[2]; + cl_double *input_ptr[1], *output_ptr, *p; + cl_program *program; + cl_kernel *kernel; + void *values[2]; + size_t threads[1]; + int num_elements; + int err; + int i; + MTdata d; + + + program = (cl_program*)malloc(sizeof(cl_program)*kTotalVecCount); + kernel = (cl_kernel*)malloc(sizeof(cl_kernel)*kTotalVecCount); + + //TODO: line below is clearly wrong + num_elements = n_elems * (1 << (kTotalVecCount-1)); + + input_ptr[0] = (cl_double*)malloc(sizeof(cl_double) * num_elements); + output_ptr = (cl_double*)malloc(sizeof(cl_double) * num_elements); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_double) * num_elements, NULL, NULL ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_double) * num_elements, NULL, NULL ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + p = input_ptr[0]; + d = init_genrand( gRandomSeed ); + for (i=0; i +#include +#include +#include + +#include "procs.h" + +static int +test_sign_double(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems); + + +const char *sign_kernel_code = +"__kernel void test_sign(__global float *src, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = sign(src[tid]);\n" +"}\n"; + +const char *sign2_kernel_code = +"__kernel void test_sign2(__global float2 *src, __global float2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = sign(src[tid]);\n" +"}\n"; + +const char *sign4_kernel_code = +"__kernel void test_sign4(__global float4 *src, __global float4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = sign(src[tid]);\n" +"}\n"; + +const char *sign8_kernel_code = +"__kernel void test_sign8(__global float8 *src, __global float8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = sign(src[tid]);\n" +"}\n"; + +const char *sign16_kernel_code = +"__kernel void test_sign16(__global float16 *src, __global float16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = sign(src[tid]);\n" +"}\n"; + +const char *sign3_kernel_code = +"__kernel void test_sign3(__global float *src, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" vstore3(sign(vload3(tid,src)), tid, dst);\n" +"}\n"; + + + +static int +verify_sign(float *inptr, float *outptr, int n) +{ + float r; + int i; + + for (i=0; i 0.0f) + r = 1.0f; + else if (inptr[i] < 0.0f) + r = -1.0f; + else + r = 0.0f; + if (r != outptr[i]) + return -1; + } + + return 0; +} + +static const char *fn_names[] = { "SIGN float", "SIGN float2", "SIGN float4", "SIGN float8", "SIGN float16", "SIGN float3" }; + +int +test_sign(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[2]; + cl_float *input_ptr[1], *output_ptr, *p; + cl_program program[kTotalVecCount]; + cl_kernel kernel[kTotalVecCount]; + void *values[2]; + size_t threads[1]; + int num_elements; + int err; + int i; + MTdata d; + + num_elements = n_elems * 16; + + input_ptr[0] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + output_ptr = (cl_float*)malloc(sizeof(cl_float) * num_elements); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + d = init_genrand( gRandomSeed ); + p = input_ptr[0]; + for (i=0; i 0.0) + r = 1.0; + else if (inptr[i] < 0.0) + r = -1.0; + else + r = 0.0f; + if (r != outptr[i]) + return -1; + } + + return 0; +} + +static const char *fn_names_double[] = { "SIGN double", "SIGN double2", "SIGN double4", "SIGN double8", "SIGN double16", "SIGN double3" }; + +int +test_sign_double(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[2]; + cl_double *input_ptr[1], *output_ptr, *p; + cl_program program[kTotalVecCount]; + cl_kernel kernel[kTotalVecCount]; + void *values[2]; + size_t threads[1]; + int num_elements; + int err; + int i; + MTdata d; + + num_elements = n_elems * 16; + + input_ptr[0] = (cl_double*)malloc(sizeof(cl_double) * num_elements); + output_ptr = (cl_double*)malloc(sizeof(cl_double) * num_elements); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_double) * num_elements, NULL, NULL ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_double) * num_elements, NULL, NULL ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + d = init_genrand( gRandomSeed ); + p = input_ptr[0]; + for (i=0; i +#include +#include +#include + +#include "procs.h" + +static const char *smoothstep_kernel_code = +"__kernel void test_smoothstep(__global float *edge0, __global float *edge1, __global float *x, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = smoothstep(edge0[tid], edge1[tid], x[tid]);\n" +"}\n"; + +static const char *smoothstep2_kernel_code = +"__kernel void test_smoothstep2(__global float2 *edge0, __global float2 *edge1, __global float2 *x, __global float2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = smoothstep(edge0[tid], edge1[tid], x[tid]);\n" +"}\n"; + +static const char *smoothstep4_kernel_code = +"__kernel void test_smoothstep4(__global float4 *edge0, __global float4 *edge1, __global float4 *x, __global float4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = smoothstep(edge0[tid], edge1[tid], x[tid]);\n" +"}\n"; + +static const char *smoothstep8_kernel_code = +"__kernel void test_smoothstep8(__global float8 *edge0, __global float8 *edge1, __global float8 *x, __global float8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = smoothstep(edge0[tid], edge1[tid], x[tid]);\n" +"}\n"; + +static const char *smoothstep16_kernel_code = +"__kernel void test_smoothstep16(__global float16 *edge0, __global float16 *edge1, __global float16 *x, __global float16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = smoothstep(edge0[tid], edge1[tid], x[tid]);\n" +"}\n"; + +static const char *smoothstep3_kernel_code = +"__kernel void test_smoothstep3(__global float *edge0, __global float *edge1, __global float *x, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" vstore3(smoothstep(vload3(tid,edge0),vload3(tid,edge1),vload3(tid,x)), tid, dst);\n" +"}\n"; + +#define MAX_ERR (1e-5f) + +static float +verify_smoothstep(float *edge0, float *edge1, float *x, float *outptr, int n) +{ + float r, t, delta, max_err = 0.0f; + int i; + + for (i=0; i 1.0f) + t = 1.0f; + r = t * t * (3.0f - 2.0f * t); + delta = (float)fabs(r - outptr[i]); + if (delta > max_err) + max_err = delta; + } + + return max_err; +} + +const static char *fn_names[] = { "SMOOTHSTEP float", "SMOOTHSTEP float2", "SMOOTHSTEP float4", "SMOOTHSTEP float8", "SMOOTHSTEP float16", "SMOOTHSTEP float3" }; + +int +test_smoothstep(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[4]; + cl_float *input_ptr[3], *output_ptr, *p, *p_edge0; + cl_program program[kTotalVecCount]; + cl_kernel kernel[kTotalVecCount]; + size_t threads[1]; + float max_err; + int num_elements; + int err; + int i; + MTdata d; + + num_elements = n_elems * 16; + + input_ptr[0] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + input_ptr[1] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + input_ptr[2] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + output_ptr = (cl_float*)malloc(sizeof(cl_float) * num_elements); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + streams[3] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[3]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + p = input_ptr[0]; + d = init_genrand( gRandomSeed ); + for (i=0; i MAX_ERR) + { + log_error("%s test failed %g max err\n", fn_names[i], max_err); + err = -1; + } + else + { + log_info("%s test passed %g max err\n", fn_names[i], max_err); + err = 0; + } + + if (err) + break; + } + + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + clReleaseMemObject(streams[2]); + clReleaseMemObject(streams[3]); + for (i=0; i +#include +#include +#include + +#include "procs.h" + +static const char *smoothstep_kernel_code = +"__kernel void test_smoothstep(__global float *edge0, __global float *edge1, __global float *x, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = smoothstep(edge0[tid], edge1[tid], x[tid]);\n" +"}\n"; + +static const char *smoothstep2_kernel_code = +"__kernel void test_smoothstep2f(__global float *edge0, __global float *edge1, __global float2 *x, __global float2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = smoothstep(edge0[tid], edge1[tid], x[tid]);\n" +"}\n"; + +static const char *smoothstep4_kernel_code = +"__kernel void test_smoothstep4f(__global float *edge0, __global float *edge1, __global float4 *x, __global float4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = smoothstep(edge0[tid], edge1[tid], x[tid]);\n" +"}\n"; + +#define MAX_ERR (1e-5f) + +extern "C" float +verify_smoothstep(float *edge0, float *edge1, float *x, float *outptr, int n, int veclen) +{ + float r, t, delta, max_err = 0.0f; + int i, j; + + for (i = 0; i < n; ++i) { + int vi = i * veclen; + for (j = 0; j < veclen; ++j, ++vi) { + t = (x[vi] - edge0[i]) / (edge1[i] - edge0[i]); + if (t < 0.0f) + t = 0.0f; + else if (t > 1.0f) + t = 1.0f; + r = t * t * (3.0f - 2.0f * t); + delta = (float)fabs(r - outptr[vi]); + if (delta > max_err) + max_err = delta; + } + } + return max_err; +} + +const static char *fn_names[] = { "SMOOTHSTEP float", "SMOOTHSTEP float2", "SMOOTHSTEP float4"}; + +int +test_smoothstepf(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[4]; + cl_float *input_ptr[3], *output_ptr, *p, *p_edge0; + cl_program program[3]; + cl_kernel kernel[3]; + size_t threads[1]; + float max_err = 0.0f; + int num_elements; + int err; + int i; + MTdata d; + + num_elements = n_elems * 4; + + input_ptr[0] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + input_ptr[1] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + input_ptr[2] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + output_ptr = (cl_float*)malloc(sizeof(cl_float) * num_elements); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + streams[3] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[3]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + d = init_genrand( gRandomSeed ); + p = input_ptr[0]; + for (i=0; i MAX_ERR) + { + log_error("%s test failed %g max err\n", fn_names[i], max_err); + err = -1; + } + else + { + log_info("%s test passed %g max err\n", fn_names[i], max_err); + err = 0; + } + + if (err) + break; + } + + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + clReleaseMemObject(streams[2]); + clReleaseMemObject(streams[3]); + for (i=0; i<3; i++) + { + clReleaseKernel(kernel[i]); + clReleaseProgram(program[i]); + } + free(input_ptr[0]); + free(input_ptr[1]); + free(input_ptr[2]); + free(output_ptr); + + return err; +} + + diff --git a/test_conformance/commonfns/test_step.c b/test_conformance/commonfns/test_step.c new file mode 100644 index 00000000..b81a0d95 --- /dev/null +++ b/test_conformance/commonfns/test_step.c @@ -0,0 +1,541 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +static int +test_step_double(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems); + + +const char *step_kernel_code = +"__kernel void test_step(__global float *srcA, __global float *srcB, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = step(srcA[tid], srcB[tid]);\n" +"}\n"; + +const char *step2_kernel_code = +"__kernel void test_step2(__global float2 *srcA, __global float2 *srcB, __global float2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = step(srcA[tid], srcB[tid]);\n" +"}\n"; + +const char *step4_kernel_code = +"__kernel void test_step4(__global float4 *srcA, __global float4 *srcB, __global float4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = step(srcA[tid], srcB[tid]);\n" +"}\n"; + +const char *step8_kernel_code = +"__kernel void test_step8(__global float8 *srcA, __global float8 *srcB, __global float8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = step(srcA[tid], srcB[tid]);\n" +"}\n"; + +const char *step16_kernel_code = +"__kernel void test_step16(__global float16 *srcA, __global float16 *srcB, __global float16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = step(srcA[tid], srcB[tid]);\n" +"}\n"; + +const char *step3_kernel_code = +"__kernel void test_step3(__global float *srcA, __global float *srcB, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" vstore3(step(vload3(tid,srcA), vload3(tid,srcB)),tid,dst);\n" +"}\n"; + + +int +verify_step(float *inptrA, float *inptrB, float *outptr, int n) +{ + float r; + int i; + + for (i=0; i +#include +#include +#include + +#include "procs.h" + +static int test_stepf_double(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems); + + +static const char *step_kernel_code = +"__kernel void test_step(__global float *srcA, __global float *srcB, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = step(srcA[tid], srcB[tid]);\n" +"}\n"; + +static const char *step2_kernel_code = +"__kernel void test_step2(__global float *srcA, __global float2 *srcB, __global float2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = step(srcA[tid], srcB[tid]);\n" +"}\n"; + +static const char *step4_kernel_code = +"__kernel void test_step4(__global float *srcA, __global float4 *srcB, __global float4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = step(srcA[tid], srcB[tid]);\n" +"}\n"; + +static const char *step8_kernel_code = +"__kernel void test_step8(__global float *srcA, __global float8 *srcB, __global float8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = step(srcA[tid], srcB[tid]);\n" +"}\n"; + +static const char *step16_kernel_code = +"__kernel void test_step16(__global float *srcA, __global float16 *srcB, __global float16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = step(srcA[tid], srcB[tid]);\n" +"}\n"; + +static const char *step3_kernel_code = +"__kernel void test_step3(__global float *srcA, __global float *srcB, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" vstore3(step(srcA[tid], vload3(tid,srcB)) ,tid,dst);\n" +"}\n"; + + +static int +verify_step( cl_float *inptrA, cl_float *inptrB, cl_float *outptr, int n, int veclen) +{ + float r; + int i, j; + + for (i=0; i *%a vs %a\n", ii, j, inptrA[ii], inptrB[i], r, outptr[i] ); + return -1; + } + } + } + + return 0; +} + +int test_stepf(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[3]; + cl_float *input_ptr[2], *output_ptr, *p; + cl_program program[kTotalVecCount]; + cl_kernel kernel[kTotalVecCount]; + size_t threads[1]; + int num_elements; + int err; + int i; + MTdata d; + num_elements = n_elems * 16; + + input_ptr[0] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + input_ptr[1] = (cl_float*)malloc(sizeof(cl_float) * num_elements); + output_ptr = (cl_float*)malloc(sizeof(cl_float) * num_elements); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * num_elements, NULL, NULL ); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + p = input_ptr[0]; + d = init_genrand( gRandomSeed ); + for (i=0; i *%a vs %a\n", ii, j, inptrA[ii], inptrB[i], r, outptr[i] ); + return -1; + } + } + } + + return 0; +} + +int test_stepf_double(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[3]; + cl_double *input_ptr[2], *output_ptr, *p; + cl_program program[kTotalVecCount]; + cl_kernel kernel[kTotalVecCount]; + size_t threads[1]; + int num_elements; + int err; + int i; + MTdata d; + num_elements = n_elems * 16; + + input_ptr[0] = (cl_double*)malloc(sizeof(cl_double) * num_elements); + input_ptr[1] = (cl_double*)malloc(sizeof(cl_double) * num_elements); + output_ptr = (cl_double*)malloc(sizeof(cl_double) * num_elements); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_double) * num_elements, NULL, NULL ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_double) * num_elements, NULL, NULL ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_double) * num_elements, NULL, NULL ); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + p = input_ptr[0]; + d = init_genrand( gRandomSeed ); + for (i=0; i +#if defined(CGL_VERSION_1_3) + #include + #include +#else + #include + #include +#endif + #include +#else +#ifdef _WIN32 + #include +#endif + #include + #include + #include +#ifdef _WIN32 + #include +#else + #include +#endif + +#endif + +#ifdef _WIN32 + GLboolean gluCheckExtension(const GLubyte *extName, const GLubyte *extString); + // No glutGetProcAddress in the standard glut v3.7. + #define glutGetProcAddress(procName) wglGetProcAddress(procName) +#endif + + +#endif // __gl_headers_h + diff --git a/test_conformance/compatibility/test_common/gl/helpers.cpp b/test_conformance/compatibility/test_common/gl/helpers.cpp new file mode 100644 index 00000000..1cc5bcb1 --- /dev/null +++ b/test_conformance/compatibility/test_common/gl/helpers.cpp @@ -0,0 +1,1622 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "helpers.h" + +// convert_float_to_half and convert_half_to_float may be found in test_conformance/images/image_helpers.cpp +cl_ushort convert_float_to_half( cl_float f ); +cl_float convert_half_to_float( cl_ushort h ); + +#if defined( __APPLE__ ) + #include +#else + #include +#endif + +#if defined(__linux__) +// On linux we dont link to GLU library to avoid comaptibility issues with +// libstdc++ +// FIXME: Implement this +const GLubyte* gluErrorString (GLenum error) +{ + const char* gl_Error = "OpenGL Error"; + return (const GLubyte*)gl_Error; +} +#endif + +void * CreateGLTexture1DArray(size_t width, size_t length, + GLenum target, GLenum glFormat, GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, int *outError, + bool allocateMem, MTdata d) +{ + *outError = 0; + GLenum err = 0; + + // width_in_pixels * pixel_width * number_of_images: + char* buffer = (char *)CreateRandomData(type, width * length * 4, d); + + glGenTextures( 1, outTextureID ); + glBindTexture( get_base_gl_target( target ), *outTextureID ); + err = glGetError(); + if( err != GL_NO_ERROR ) { + log_error( "ERROR: Failed to create GL texture object: %s!\n", gluErrorString( err )); + *outError = -1; + free( buffer ); + return NULL; + } + + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + // use TexImage2D to pump the 1D array fill of bits: + glTexImage2D( get_base_gl_target(target), 0, internalFormat, (GLsizei)width, + (GLsizei)length, 0, glFormat, glType, buffer ); + + err = glGetError(); + if( err != GL_NO_ERROR ) { + log_error( "ERROR: Unable to load data using glTexImage2D for " + "TEXTURE_1D_ARRAY : %s : %s : %d : %d : %s : %s : Error %s\n", + GetGLTargetName(target), + GetGLFormatName(internalFormat), + (int)(width), (int)(length), + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + + *outError = -1; + free( buffer ); + return NULL; + } + + + if( !allocateMem ) { + free( buffer ); + return NULL; + } + + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * length; i++ ) { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } + else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * length; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc1; + p[ i * 4 + 1 ] = uc2; + p[ i * 4 + 2 ] = uc3; + p[ i * 4 + 3 ] = uc0; + } + } + + + return buffer; +} + +void * CreateGLTexture2DArray(size_t width, size_t height, size_t length, + GLenum target, GLenum glFormat, GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, int *outError, + bool allocateMem, MTdata d) +{ + *outError = 0; + + char * buffer = (char *)create_random_data( type, d, width * height * length * 4 ); + + if( type == kFloat && allocateMem ) + { + // Re-fill the created buffer to just have [0-1] floats, since that's what it'd expect + cl_float *p = (cl_float *)buffer; + for( size_t i = 0; i < width * height * length * 4; i++ ) + { + p[ i ] = (float) genrand_real1( d ); + } + } + else if( !allocateMem ) + memset( buffer, 0, width * height * length * 4 * get_explicit_type_size( type ) ); + + glGenTextures( 1, outTextureID ); + + glBindTexture( target, *outTextureID ); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + glGetError(); + glTexImage3D( target, 0, internalFormat, (GLsizei)width, (GLsizei)height, + (GLsizei)length, 0, glFormat, glType, buffer ); + GLenum err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Unable to load data into GL texture (%s) format %s " + "type %s internal format %s\n", gluErrorString( err ), + GetGLFormatName( glFormat ), get_explicit_type_name( type ), + GetGLFormatName( internalFormat ) ); + *outError = -1; + delete [] buffer; + return NULL; + } + + if( !allocateMem ) + { + delete [] buffer; + return NULL; + } + + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * height * length; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } + else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * length; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc1; + p[ i * 4 + 1 ] = uc2; + p[ i * 4 + 2 ] = uc3; + p[ i * 4 + 3 ] = uc0; + } + } + + + return buffer; +} + +void * CreateGLTextureBuffer(size_t width, GLenum target, + GLenum glFormat, GLenum internalFormat, GLenum glType, ExplicitType type, + GLuint *outTex, GLuint *outBuf, int *outError, bool allocateMem, MTdata d) +{ + // First, generate a regular GL Buffer from random data. + *outError = 0; + GLenum err = 0; + + char * buffer = (char*)CreateRandomData(type, width * 4, d); + + glGenBuffers(1, outBuf); + glBindBuffer(GL_TEXTURE_BUFFER, *outBuf); + + // The buffer should be the array width * number of elements * element pitch + size_t size = width * 4; + + // Need to multiply by the type size: + size *= ( GetGLTypeSize( GetGLTypeForExplicitType(type) ) ); + + glBufferData(GL_TEXTURE_BUFFER, size, buffer, GL_DYNAMIC_DRAW); + + // Now make a Texture out of this Buffer: + + glGenTextures(1, outTex); + glBindTexture(GL_TEXTURE_BUFFER, *outTex); + glTexBuffer(GL_TEXTURE_BUFFER, internalFormat, *outBuf); + + + + if( !allocateMem ) { + free( buffer ); + return NULL; + } + + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width; i++ ) { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } + else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc1; + p[ i * 4 + 1 ] = uc2; + p[ i * 4 + 2 ] = uc3; + p[ i * 4 + 3 ] = uc0; + } + } + + + return buffer; +} + +void* CreateGLTexture1D( size_t width, GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, ExplicitType type, + GLuint *outTextureID, int *outError, bool allocateMem, MTdata d ) +{ + *outError = 0; + GLenum err = 0; + + char * buffer = (char*)CreateRandomData(type, width * 4, d); + + glGenTextures( 1, outTextureID ); + glBindTexture( get_base_gl_target( target ), *outTextureID ); + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Failed to create GL texture object: %s!\n", gluErrorString( err )); + *outError = -1; + free( buffer ); + return NULL; + } + + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + glTexImage1D( get_base_gl_target(target), 0, internalFormat, (GLsizei)width, + 0, glFormat, glType, buffer ); + + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Unable to load data into glTexImage1D : %s : %s : %d : %s : %s : Error %s\n", + GetGLTargetName(target), + GetGLFormatName(internalFormat), + (int)(width), + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + + *outError = -1; + free( buffer ); + return NULL; + } + + if( !allocateMem ) { + free( buffer ); + return NULL; + } + + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width; i++ ) { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } + else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc1; + p[ i * 4 + 1 ] = uc2; + p[ i * 4 + 2 ] = uc3; + p[ i * 4 + 3 ] = uc0; + } + } + + return buffer; +} + +void * CreateGLTexture2D( size_t width, size_t height, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, bool allocateMem, MTdata d ) +{ + *outError = 0; + GLenum err = 0; + + char * buffer = (char *)CreateRandomData(type, width * height * 4, d); + + glGenTextures( 1, outTextureID ); + glBindTexture( get_base_gl_target( target ), *outTextureID ); + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Failed to create GL texture object: %s!\n", gluErrorString( err )); + *outError = -1; + free( buffer ); + return NULL; + } + + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( get_base_gl_target( target ), GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + if( get_base_gl_target( target ) == GL_TEXTURE_CUBE_MAP ) + { + char * temp = (char *)malloc(width * height * 4 * get_explicit_type_size( type ) * sizeof(cl_char)); + if(allocateMem) + memcpy( temp, buffer, width * height * 4 * get_explicit_type_size( type ) ); + else + memset( temp, 0, width * height * 4 * get_explicit_type_size( type ) ); + + glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, temp ); + free(temp); + } + else + { +#ifdef DEBUG + log_info("- glTexImage2D : %s : %s : %d : %d : %s : %s\n", + GetGLTargetName(target), + GetGLFormatName(internalFormat), + width, height, + GetGLFormatName(glFormat), + GetGLTypeName(glType)); + + DumpGLBuffer(glType, width, height, buffer); + +#endif + glTexImage2D( get_base_gl_target(target), 0, internalFormat, (GLsizei)width, (GLsizei)height, 0, glFormat, glType, buffer ); + } + + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Unable to load data into glTexImage2D : %s : %s : %d : %d : %s : %s : Error %s\n", + GetGLTargetName(target), + GetGLFormatName(internalFormat), + (int)(width), (int)(height), + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + + *outError = -1; + free( buffer ); + return NULL; + } + +#ifdef DEBUG + memset(buffer, 0, width * height * 4 * get_explicit_type_size( type )); + + log_info("- glGetTexImage : %s : %s : %s\n", + GetGLTargetName(target), + GetGLFormatName(glFormat), + GetGLTypeName(glType)); + + glGetTexImage(target, 0, glFormat, glType, buffer); + + DumpGLBuffer(type, width, height, buffer); + + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Unable to read data from glGetTexImage : %s : %s : %s : Error %s\n", + GetGLTargetName(target), + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + return NULL; + } +#endif + + if( !allocateMem ) + { + free( buffer ); + return NULL; + } + + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * height; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } + else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * height; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc1; + p[ i * 4 + 1 ] = uc2; + p[ i * 4 + 2 ] = uc3; + p[ i * 4 + 3 ] = uc0; + } + } + + return buffer; +} + +void * CreateGLTexture3D( size_t width, size_t height, size_t depth, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, MTdata d, bool allocateMem) +{ + *outError = 0; + + char * buffer = (char *)create_random_data( type, d, width * height * depth * 4 ); + + if( type == kFloat && allocateMem ) + { + // Re-fill the created buffer to just have [0-1] floats, since that's what it'd expect + cl_float *p = (cl_float *)buffer; + for( size_t i = 0; i < width * height * depth * 4; i++ ) + { + p[ i ] = (float) genrand_real1( d ); + } + } + else if( !allocateMem ) + memset( buffer, 0, width * height * depth * 4 * get_explicit_type_size( type ) ); + + glGenTextures( 1, outTextureID ); + + glBindTexture( target, *outTextureID ); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + glGetError(); + glTexImage3D( target, 0, internalFormat, (GLsizei)width, (GLsizei)height, (GLsizei)depth, 0, glFormat, glType, buffer ); + GLenum err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Unable to load data into GL texture (%s) format %s type %s internal format %s\n", gluErrorString( err ), GetGLFormatName( glFormat ), get_explicit_type_name( type ), GetGLFormatName( internalFormat ) ); + *outError = -1; + delete [] buffer; + return NULL; + } + + if( !allocateMem ) + { + delete [] buffer; + return NULL; + } + + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * height * depth; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } + else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * height * depth; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc1; + p[ i * 4 + 1 ] = uc2; + p[ i * 4 + 2 ] = uc3; + p[ i * 4 + 3 ] = uc0; + } + } + + return buffer; +} + +void * ReadGLTexture( GLenum glTarget, GLuint glTexture, GLuint glBuf, GLint width, + GLenum glFormat, GLenum glInternalFormat, + GLenum glType, ExplicitType typeToReadAs, + size_t outWidth, size_t outHeight ) +{ + // Read results from the GL texture + glBindTexture(get_base_gl_target(glTarget), glTexture); + + GLint realWidth, realHeight, realDepth; + glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_WIDTH, &realWidth ); + glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_HEIGHT, &realHeight ); + glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_WIDTH, &realDepth ); + + realDepth = realDepth == 0 ? realDepth : 1; + + GLint realInternalFormat; + glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &realInternalFormat ); + +#ifdef DEBUG + log_info( "- Reading back from GL: %d x %d : %s : %s : %s : %s (stored as %s)\n", + realWidth, realHeight, + GetGLTargetName( glTarget), + GetGLFormatName( glInternalFormat ), + GetGLFormatName( glFormat ), + GetGLTypeName( glType ), + GetGLFormatName( realInternalFormat )); +#endif + + GLenum readBackFormat = glFormat == GL_RGBA_INTEGER_EXT ? GL_RGBA_INTEGER_EXT : GL_RGBA; + + GLenum readBackType; + switch (glType) { +#ifdef __APPLE__ + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + readBackType = GL_UNSIGNED_BYTE; + break; +#endif + case GL_HALF_FLOAT: + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT: + case GL_UNSIGNED_INT: + case GL_BYTE: + case GL_SHORT: + case GL_INT: + case GL_FLOAT: + default: + readBackType = glType; + } + + size_t outBytes; + if (get_base_gl_target(glTarget) != GL_TEXTURE_BUFFER) { + outBytes = realWidth * realHeight * realDepth * 4 + * GetGLTypeSize(readBackType); + } + else { + outBytes = width * 4; + + outBytes *= ( GetGLTypeSize( GetGLTypeForExplicitType(typeToReadAs) ) ); + } + + cl_char *outBuffer = (cl_char *)malloc( outBytes ); + memset(outBuffer, 0, outBytes); + + if (get_base_gl_target(glTarget) != GL_TEXTURE_BUFFER) { + glGetTexImage( glTarget, 0, readBackFormat, readBackType, outBuffer ); + } + else { + glBindBuffer(GL_ARRAY_BUFFER, glBuf); + glGetBufferSubData(GL_ARRAY_BUFFER, 0, outBytes, outBuffer); + } + +#ifdef DEBUG + + log_info( "- glGetTexImage: %s : %s : %s \n", + GetGLTargetName( glTarget), + GetGLFormatName(readBackFormat), + GetGLTypeName(readBackType)); + + DumpGLBuffer(readBackType, realWidth, realHeight, (void*)outBuffer); + +#endif + + return (void *)outBuffer; +} + +int CreateGLRenderbufferRaw( GLsizei width, GLsizei height, + GLenum attachment, GLenum glFormat, + GLenum internalFormat, GLenum glType, + GLuint *outFramebuffer, + GLuint *outRenderbuffer ) +{ + GLenum err = 0; + + // Generate a renderbuffer and bind + glGenRenderbuffersEXT( 1, outRenderbuffer ); + glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, *outRenderbuffer ); + + // Allocate storage to the renderbuffer + glGetError(); + glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, internalFormat, (GLsizei)width, (GLsizei)height ); + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error("Failed to allocate render buffer storage!\n"); + return 1701; + } + + GLint realInternalFormat; + glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &realInternalFormat ); + internalFormat = realInternalFormat; + +#ifdef DEBUG + GLint rsize, gsize, bsize, asize; + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_RED_SIZE_EXT,&rsize); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_GREEN_SIZE_EXT,&gsize); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_BLUE_SIZE_EXT,&bsize); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_ALPHA_SIZE_EXT,&asize); + + log_info("Renderbuffer internal format requested: %s actual: %s sizes: r=%d g=%d b=%d a=%d\n", + GetGLFormatName( internalFormat ), GetGLFormatName( realInternalFormat ), + rsize, gsize, bsize, asize ); +#endif + + // Create and bind a framebuffer to render with + glGenFramebuffersEXT( 1, outFramebuffer ); + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, *outFramebuffer ); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Unable to bind framebuffer : Error %s\n", + gluErrorString( err )); + + return -1; + } + + // Attach to the framebuffer + glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, *outRenderbuffer ); + err = glGetError(); + GLint status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ); + if( status != GL_FRAMEBUFFER_COMPLETE_EXT ) + { + log_error( "ERROR: Unable to attach renderbuffer to framebuffer (%s, status %x)\n", gluErrorString( err ), (int)status ); + return -1; + } + + return 0; +} + +void * CreateGLRenderbuffer( GLsizei width, GLsizei height, + GLenum attachment, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, + GLuint *outFramebuffer, + GLuint *outRenderbuffer, + int *outError, MTdata d, bool allocateMem ) +{ + *outError = CreateGLRenderbufferRaw( width, height, attachment, glFormat, internalFormat, + glType, outFramebuffer, outRenderbuffer ); + + if( *outError != 0 ) + return NULL; + + GLenum err = 0; + + // Generate a renderbuffer and bind + glGenRenderbuffersEXT( 1, outRenderbuffer ); + glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, *outRenderbuffer ); + + // Allocate storage to the renderbuffer + glGetError(); + glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, internalFormat, (GLsizei)width, (GLsizei)height ); + err = glGetError(); + if( err != GL_NO_ERROR ) + { + *outError = 1701; + log_error("Failed to allocate render buffer storage!\n"); + return NULL; + } + + GLint realInternalFormat; + glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &realInternalFormat ); + internalFormat = realInternalFormat; + +#ifdef DEBUG + GLint rsize, gsize, bsize, asize; + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_RED_SIZE_EXT,&rsize); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_GREEN_SIZE_EXT,&gsize); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_BLUE_SIZE_EXT,&bsize); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_ALPHA_SIZE_EXT,&asize); + + log_info("Renderbuffer internal format requested: %s actual: %s sizes: r=%d g=%d b=%d a=%d\n", + GetGLFormatName( internalFormat ), GetGLFormatName( realInternalFormat ), + rsize, gsize, bsize, asize ); +#endif + + // Create and bind a framebuffer to render with + glGenFramebuffersEXT( 1, outFramebuffer ); + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, *outFramebuffer ); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Unable to bind framebuffer : Error %s\n", + gluErrorString( err )); + + *outError = -1; + return NULL; + } + + // Attach to the framebuffer + glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, *outRenderbuffer ); + err = glGetError(); + GLint status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ); + if( status != GL_FRAMEBUFFER_COMPLETE_EXT ) + { + *outError = -1; + log_error( "ERROR: Unable to attach renderbuffer to framebuffer (%s, status %x)\n", gluErrorString( err ), (int)status ); + return NULL; + } + + void* buffer = CreateRandomData(type, width * height * 4, d); + +#ifdef DEBUG + log_info( "- Fillling renderbuffer: %d : %d : %s : %s \n", + (int)width, (int)height, + GetGLFormatName(glFormat), + GetGLTypeName(glType)); + + DumpGLBuffer(glType, (int)width, (int)height, (void*)buffer); +#endif + + // Fill a texture with our input data + glTextureWrapper texture; + glGenTextures( 1, &texture ); + glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture ); + glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, internalFormat, width, height, 0, glFormat, glType, buffer ); + glEnable( GL_TEXTURE_RECTANGLE_ARB ); + + // Render fullscreen textured quad + glDisable( GL_LIGHTING ); + glViewport(0, 0, width, height); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glMatrixMode( GL_TEXTURE ); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glClear(GL_COLOR_BUFFER_BIT); + gluOrtho2D( -1.0, 1.0, -1.0, 1.0 ); + glMatrixMode( GL_MODELVIEW ); + glBegin( GL_QUADS ); + { + glColor3f(1.0f, 1.0f, 1.0f); + glTexCoord2f( 0.0f, 0.0f ); + glVertex3f( -1.0f, -1.0f, 0.0f ); + glTexCoord2f( 0.0f, height ); + glVertex3f( -1.0f, 1.0f, 0.0f ); + glTexCoord2f( width, height ); + glVertex3f( 1.0f, 1.0f, 0.0f ); + glTexCoord2f( width, 0.0f ); + glVertex3f( 1.0f, -1.0f, 0.0f ); + } + glEnd(); + glBindTexture( GL_TEXTURE_RECTANGLE_ARB, 0 ); + glDisable( GL_TEXTURE_RECTANGLE_ARB ); + + glFlush(); + + // Read back the data in the renderbuffer + memset(buffer, 0, width * height * 4 * get_explicit_type_size( type )); + glReadBuffer( attachment ); + glReadPixels( 0, 0, (GLsizei)width, (GLsizei)height, glFormat, glType, buffer ); + + err = glGetError(); + if( err != GL_NO_ERROR ) + { + log_error( "ERROR: Unable to read data via glReadPixels : %d : %d : %s : %s : Error %s\n", + (int)width, (int)height, + GetGLFormatName(glFormat), + GetGLTypeName(glType), + gluErrorString( err )); + *outError = -1; + } + +#ifdef DEBUG + log_info( "- glReadPixels: %d : %d : %s : %s \n", + (int)width, (int)height, + GetGLFormatName(glFormat), + GetGLTypeName(glType)); + + DumpGLBuffer(glType, (int)width, (int)height, (void*)buffer); +#endif + + if( !allocateMem ) + { + free( buffer ); + return NULL; + } + + if( glType == GL_UNSIGNED_INT_8_8_8_8_REV && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < (size_t)width * height; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc2; + p[ i * 4 + 1 ] = uc1; + p[ i * 4 + 2 ] = uc0; + p[ i * 4 + 3 ] = uc3; + } + } + else if( glType == GL_UNSIGNED_INT_8_8_8_8 && glFormat == GL_BGRA && allocateMem ) + { + // Reverse and reorder to validate since in the + // kernel the read_imagef() call always returns RGBA + cl_uchar *p = (cl_uchar *)buffer; + for( size_t i = 0; i < width * height; i++ ) + { + cl_uchar uc0 = p[i * 4 + 0]; + cl_uchar uc1 = p[i * 4 + 1]; + cl_uchar uc2 = p[i * 4 + 2]; + cl_uchar uc3 = p[i * 4 + 3]; + + p[ i * 4 + 0 ] = uc1; + p[ i * 4 + 1 ] = uc2; + p[ i * 4 + 2 ] = uc3; + p[ i * 4 + 3 ] = uc0; + } + } + + return buffer; +} + +void * ReadGLRenderbuffer( GLuint glFramebuffer, GLuint glRenderbuffer, + GLenum attachment, GLenum glFormat, + GLenum glInternalFormat, GLenum glType, + ExplicitType typeToReadAs, + size_t outWidth, size_t outHeight ) +{ + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, glFramebuffer ); + glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, glRenderbuffer ); + + // Attach to the framebuffer + GLint err = glGetError(); + if( glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ) != GL_FRAMEBUFFER_COMPLETE_EXT ) + { + log_error( "ERROR: Unable to attach renderbuffer to framebuffer (%s)\n", gluErrorString( err ) ); + return NULL; + } + + // Read results from the GL renderbuffer +#ifdef DEBUG + log_info( "- Reading back from GL: %d x %d : %s : %s : %s\n", + (int)outWidth, (int)outHeight, + GetGLFormatName( glInternalFormat ), + GetGLFormatName( glFormat ), + GetGLTypeName( glType )); +#endif + + GLenum readBackFormat = glFormat == GL_RGBA_INTEGER_EXT ? GL_RGBA_INTEGER_EXT : GL_RGBA; + GLenum readBackType = glType; + + size_t outBytes = outWidth * outHeight * 4 * GetGLTypeSize(readBackType); + void *outBuffer = malloc( outBytes ); + memset(outBuffer, 0, outBytes); + + glReadPixels( 0, 0, (GLsizei)outWidth, (GLsizei)outHeight, readBackFormat, readBackType, outBuffer ); + +#ifdef DEBUG + log_info( "- glReadPixels: %d : %d : %s : %s \n", + (int)outWidth, (int)outHeight, + GetGLFormatName(readBackFormat), + GetGLTypeName(readBackType)); + + DumpGLBuffer(readBackType, outWidth, outHeight, outBuffer); +#endif + + return (void *)outBuffer; +} + +GLenum +GetGLFormat(GLenum internalFormat) +{ + GLenum glFormat; + switch (internalFormat) + { + case GL_BGRA: + case GL_RGBA8: + case GL_RGBA16: + case GL_RGBA32F_ARB: + glFormat = GL_RGBA; + break; + case GL_RGBA8I_EXT: + case GL_RGBA16I_EXT: + case GL_RGBA32I_EXT: + case GL_RGBA8UI_EXT: + case GL_RGBA16UI_EXT: + case GL_RGBA32UI_EXT: + glFormat = GL_RGBA_INTEGER_EXT; + break; + default: + glFormat = GL_RGBA; + break; + } + + return glFormat; +} + +GLenum GetGLTypeForExplicitType(ExplicitType type) +{ + switch( type ) + { + case kFloat: + return GL_FLOAT; + case kInt: + return GL_INT; + case kUInt: + return GL_UNSIGNED_INT; + case kShort: + return GL_SHORT; + case kUShort: + return GL_UNSIGNED_SHORT; + case kChar: + return GL_BYTE; + case kUChar: + return GL_UNSIGNED_BYTE; + case kHalf: +#if defined( __APPLE__ ) + return GL_HALF_FLOAT; +#else + return GL_HALF_FLOAT_ARB; +#endif + default: + return GL_INT; + }; +} + +size_t GetGLTypeSize(GLenum type) +{ + switch( type ) + { + case GL_FLOAT: + return sizeof(GLfloat); + case GL_INT: + return sizeof(GLint); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + case GL_SHORT: + return sizeof(GLshort); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_BYTE: + return sizeof(GLbyte); + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); +#if defined( __APPLE__ ) + case GL_HALF_FLOAT: +#else + case GL_HALF_FLOAT_ARB: +#endif + return sizeof(GLhalf); + default: + log_error("Unknown type 0x%x\n",type); + return 0; + }; +} + +ExplicitType GetExplicitTypeForGLType(GLenum type) +{ + switch( type ) + { + case GL_FLOAT: + return kFloat; + case GL_INT: + return kInt; + case GL_UNSIGNED_INT: + return kUInt; + case GL_SHORT: + return kShort; + case GL_UNSIGNED_SHORT: + return kUShort; + case GL_BYTE: + return kChar; + case GL_UNSIGNED_BYTE: + return kUChar; +#if defined( __APPLE__ ) + case GL_HALF_FLOAT: +#else + case GL_HALF_FLOAT_ARB: +#endif + return kHalf; + default: + return kFloat; + }; +} + +GLenum get_base_gl_target( GLenum target ) +{ + switch( target ) + { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + return GL_TEXTURE_CUBE_MAP; + default: + return target; + } +} + +const char *GetGLTypeName( GLenum type ) +{ + switch( type ) + { + case GL_BYTE: return "GL_BYTE"; + case GL_UNSIGNED_BYTE: return "GL_UNSIGNED_BYTE"; + case GL_INT: return "GL_INT"; + case GL_UNSIGNED_INT: return "GL_UNSIGNED_INT"; + case GL_SHORT: return "GL_SHORT"; + case GL_UNSIGNED_SHORT: return "GL_UNSIGNED_SHORT"; +#if defined( __APPLE__ ) + case GL_HALF_FLOAT: return "GL_HALF_FLOAT"; +#else + case GL_HALF_FLOAT_ARB: return "GL_HALF_FLOAT_ARB"; +#endif + case GL_FLOAT: return "GL_FLOAT"; + case GL_UNSIGNED_INT_8_8_8_8: return "GL_UNSIGNED_INT_8_8_8_8"; + case GL_UNSIGNED_INT_8_8_8_8_REV: return "GL_UNSIGNED_INT_8_8_8_8_REV"; + default: + { + static char foo[ 128 ]; + sprintf( foo, "(Unknown:0x%08x)", (int)type ); + return foo; + } + } +} + +const char *GetGLTargetName( GLenum tgt ) +{ + if( tgt == GL_TEXTURE_2D ) return "GL_TEXTURE_2D"; + if( tgt == GL_TEXTURE_3D ) return "GL_TEXTURE_3D"; + if( tgt == GL_TEXTURE_RECTANGLE_EXT ) return "GL_TEXTURE_RECTANGLE_EXT"; + if( tgt == GL_TEXTURE_CUBE_MAP_POSITIVE_X ) return "GL_TEXTURE_CUBE_MAP_POSITIVE_X"; + if( tgt == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ) return "GL_TEXTURE_CUBE_MAP_POSITIVE_Y"; + if( tgt == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ) return "GL_TEXTURE_CUBE_MAP_POSITIVE_Z"; + if( tgt == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ) return "GL_TEXTURE_CUBE_MAP_NEGATIVE_X"; + if( tgt == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ) return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y"; + if( tgt == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ) return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z"; + return ""; +} + +const char *GetGLAttachmentName( GLenum att ) +{ + if( att == GL_COLOR_ATTACHMENT0_EXT ) return "GL_COLOR_ATTACHMENT0_EXT"; + if( att == GL_COLOR_ATTACHMENT1_EXT ) return "GL_COLOR_ATTACHMENT1_EXT"; + if( att == GL_COLOR_ATTACHMENT2_EXT ) return "GL_COLOR_ATTACHMENT2_EXT"; + if( att == GL_COLOR_ATTACHMENT3_EXT ) return "GL_COLOR_ATTACHMENT3_EXT"; + if( att == GL_COLOR_ATTACHMENT4_EXT ) return "GL_COLOR_ATTACHMENT4_EXT"; + if( att == GL_COLOR_ATTACHMENT5_EXT ) return "GL_COLOR_ATTACHMENT5_EXT"; + if( att == GL_COLOR_ATTACHMENT6_EXT ) return "GL_COLOR_ATTACHMENT6_EXT"; + if( att == GL_COLOR_ATTACHMENT7_EXT ) return "GL_COLOR_ATTACHMENT7_EXT"; + if( att == GL_COLOR_ATTACHMENT8_EXT ) return "GL_COLOR_ATTACHMENT8_EXT"; + if( att == GL_DEPTH_ATTACHMENT_EXT ) return "GL_DEPTH_ATTACHMENT_EXT"; + return ""; +} +const char *GetGLBaseFormatName( GLenum baseformat ) +{ + switch( baseformat ) + { + case GL_RGBA8: return "GL_RGBA"; + case GL_RGBA16: return "GL_RGBA"; + case GL_RGBA: return "GL_RGBA"; + case GL_BGRA: return "GL_BGRA"; + case GL_RGBA8I_EXT: return "GL_RGBA_INTEGER_EXT"; + case GL_RGBA16I_EXT: return "GL_RGBA_INTEGER_EXT"; + case GL_RGBA32I_EXT: return "GL_RGBA_INTEGER_EXT"; + case GL_RGBA8UI_EXT: return "GL_RGBA_INTEGER_EXT"; + case GL_RGBA16UI_EXT: return "GL_RGBA_INTEGER_EXT"; + case GL_RGBA32UI_EXT: return "GL_RGBA_INTEGER_EXT"; + case GL_RGBA32F_ARB: return "GL_RGBA"; + + case GL_RGBA_INTEGER_EXT: return "GL_RGBA_INTEGER_EXT"; + + case GL_ALPHA4: return "GL_ALPHA"; + case GL_ALPHA8: return "GL_ALPHA"; + case GL_ALPHA12: return "GL_ALPHA"; + case GL_ALPHA16: return "GL_ALPHA"; + case GL_LUMINANCE4: return "GL_LUMINANCE"; + case GL_LUMINANCE8: return "GL_LUMINANCE"; + case GL_LUMINANCE12: return "GL_LUMINANCE"; + case GL_LUMINANCE16: return "GL_LUMINANCE"; + case GL_LUMINANCE4_ALPHA4: return "GL_LUMINANCE_ALPHA"; + case GL_LUMINANCE6_ALPHA2: return "GL_LUMINANCE_ALPHA"; + case GL_LUMINANCE8_ALPHA8: return "GL_LUMINANCE_ALPHA"; + case GL_LUMINANCE12_ALPHA4: return "GL_LUMINANCE_ALPHA"; + case GL_LUMINANCE12_ALPHA12: return "GL_LUMINANCE_ALPHA"; + case GL_LUMINANCE16_ALPHA16: return "GL_LUMINANCE_ALPHA"; + case GL_INTENSITY: return "GL_INTENSITY"; + case GL_INTENSITY4: return "GL_INTENSITY"; + case GL_INTENSITY8: return "GL_INTENSITY"; + case GL_INTENSITY12: return "GL_INTENSITY"; + case GL_INTENSITY16: return "GL_INTENSITY"; + case GL_R3_G3_B2: return "GL_RGB"; + case GL_RGB4: return "GL_RGB"; + case GL_RGB5: return "GL_RGB"; + case GL_RGB8: return "GL_RGB"; + case GL_RGB10: return "GL_RGB"; + case GL_RGB12: return "GL_RGB"; + case GL_RGB16: return "GL_RGB"; + case GL_RGBA2: return "GL_RGBA"; + case GL_RGBA4: return "GL_RGBA"; + case GL_RGB5_A1: return "GL_RGBA"; + case GL_RGB10_A2: return "GL_RGBA"; + case GL_RGBA12: return "GL_RGBA"; + + default: + { + static char foo[ 128 ]; + sprintf( foo, "(Unknown:0x%08x)", (int)baseformat ); + return foo; + } + } +} + +const char *GetGLFormatName( GLenum format ) +{ + switch( format ) + { + case GL_RGBA8: return "GL_RGBA8"; + case GL_RGBA16: return "GL_RGBA16"; + case GL_RGBA: return "GL_RGBA"; + case GL_BGRA: return "GL_BGRA"; + case GL_RGBA8I_EXT: return "GL_RGBA8I_EXT"; + case GL_RGBA16I_EXT: return "GL_RGBA16I_EXT"; + case GL_RGBA32I_EXT: return "GL_RGBA32I_EXT"; + case GL_RGBA8UI_EXT: return "GL_RGBA8UI_EXT"; + case GL_RGBA16UI_EXT: return "GL_RGBA16UI_EXT"; + case GL_RGBA32UI_EXT: return "GL_RGBA32UI_EXT"; + case GL_RGBA16F_ARB: return "GL_RGBA16F_ARB"; + case GL_RGBA32F_ARB: return "GL_RGBA32F_ARB"; + + case GL_RGBA_INTEGER_EXT: return "GL_RGBA_INTEGER_EXT"; + + case GL_ALPHA4: return "GL_ALPHA4"; + case GL_ALPHA8: return "GL_ALPHA8"; + case GL_ALPHA12: return "GL_ALPHA12"; + case GL_ALPHA16: return "GL_ALPHA16"; + case GL_LUMINANCE4: return "GL_LUMINANCE4"; + case GL_LUMINANCE8: return "GL_LUMINANCE8"; + case GL_LUMINANCE12: return "GL_LUMINANCE12"; + case GL_LUMINANCE16: return "GL_LUMINANCE16"; + case GL_LUMINANCE4_ALPHA4: return "GL_LUMINANCE4_ALPHA4"; + case GL_LUMINANCE6_ALPHA2: return "GL_LUMINANCE6_ALPHA2"; + case GL_LUMINANCE8_ALPHA8: return "GL_LUMINANCE8_ALPHA8"; + case GL_LUMINANCE12_ALPHA4: return "GL_LUMINANCE12_ALPHA4"; + case GL_LUMINANCE12_ALPHA12: return "GL_LUMINANCE12_ALPHA12"; + case GL_LUMINANCE16_ALPHA16: return "GL_LUMINANCE16_ALPHA16"; + case GL_INTENSITY: return "GL_INTENSITY"; + case GL_INTENSITY4: return "GL_INTENSITY4"; + case GL_INTENSITY8: return "GL_INTENSITY8"; + case GL_INTENSITY12: return "GL_INTENSITY12"; + case GL_INTENSITY16: return "GL_INTENSITY16"; + case GL_R3_G3_B2: return "GL_R3_G3_B2"; + case GL_RGB4: return "GL_RGB4"; + case GL_RGB5: return "GL_RGB5"; + case GL_RGB8: return "GL_RGB8"; + case GL_RGB10: return "GL_RGB10"; + case GL_RGB12: return "GL_RGB12"; + case GL_RGB16: return "GL_RGB16"; + case GL_RGBA2: return "GL_RGBA2"; + case GL_RGBA4: return "GL_RGBA4"; + case GL_RGB5_A1: return "GL_RGB5_A1"; + case GL_RGB10_A2: return "GL_RGB10_A2"; + case GL_RGBA12: return "GL_RGBA12"; + + case GL_INT: return "GL_INT"; + case GL_UNSIGNED_INT: return "GL_UNSIGNED_INT"; + case GL_SHORT: return "GL_SHORT"; + case GL_UNSIGNED_SHORT: return "GL_UNSIGNED_SHORT"; + case GL_BYTE: return "GL_BYTE"; + case GL_UNSIGNED_BYTE: return "GL_UNSIGNED_BYTE"; + case GL_FLOAT: return "GL_FLOAT"; +#if defined( __APPLE__ ) + case GL_HALF_FLOAT: return "GL_HALF_FLOAT"; +#else + case GL_HALF_FLOAT_ARB: return "GL_HALF_FLOAT_ARB"; +#endif + + default: + { + static char foo[ 128 ]; + sprintf( foo, "(Unknown:0x%08x)", (int)format ); + return foo; + } + } +} + +void* CreateRandomData( ExplicitType type, size_t count, MTdata d ) +{ + switch(type) + { + case (kChar): + { + cl_char *p = (cl_char *)malloc(count * sizeof(cl_char)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = (cl_char)genrand_int32(d); + } + return (void*)p; + } + case (kUChar): + { + cl_uchar *p = (cl_uchar *)malloc(count * sizeof(cl_uchar)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = (cl_uchar)genrand_int32(d); + } + + return (void*)p; + } + case (kShort): + { + cl_short *p = (cl_short *)malloc(count * sizeof(cl_short)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = (cl_short)genrand_int32(d); + } + + return (void*)p; + } + case (kUShort): + { + cl_ushort *p = (cl_ushort *)malloc(count * sizeof(cl_ushort)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = (cl_ushort)genrand_int32(d); + } + + return (void*)p; + } + case (kInt): + { + cl_int *p = (cl_int *)malloc(count * sizeof(cl_int)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = (cl_int)genrand_int32(d); + } + + return (void*)p; + } + case (kUInt): + { + cl_uint *p = (cl_uint *)malloc(count * sizeof(cl_uint)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = (cl_uint)genrand_int32(d); + } + + return (void*)p; + } + + case (kFloat): + { + cl_float *p = (cl_float *)malloc(count * sizeof(cl_float)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = get_random_float( 0.f, 1.f, d ); + } + + return (void*)p; + } + case (kHalf): + { + cl_half *p = (cl_half *)malloc(count * sizeof(cl_half)); + if(!p) return 0; + + for( size_t i = 0; i < count; i++ ) + { + p[ i ] = convert_float_to_half( get_random_float( 0.f, 1.f, d ) ); + } + + return (void*)p; + } + default: + { + log_error("Invalid explicit type specified for create random data!\n"); + return 0; + } + } + return 0; +} + +void DumpGLBuffer(GLenum type, size_t width, size_t height, void* buffer) +{ + size_t i; + size_t count = width * height; + if(type == GL_BYTE) + { + cl_char* p = (cl_char*)buffer; + for(i = 0; i < count; i++) + log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), + p[i* 4 + 0], + p[i* 4 + 1], + p[i* 4 + 2], + p[i* 4 + 3]); + } + else if(type == GL_UNSIGNED_BYTE) + { + cl_uchar* p = (cl_uchar*)buffer; + for(i = 0; i < count; i++) + log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), + p[i* 4 + 0], + p[i* 4 + 1], + p[i* 4 + 2], + p[i* 4 + 3]); + } + else if(type == GL_INT) + { + cl_int* p = (cl_int*)buffer; + for(i = 0; i < count; i++) + log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), + p[i* 4 + 0], + p[i* 4 + 1], + p[i* 4 + 2], + p[i* 4 + 3]); + } + else if(type == GL_UNSIGNED_INT) + { + cl_uint* p = (cl_uint*)buffer; + for(i = 0; i < count; i++) + log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), + p[i* 4 + 0], + p[i* 4 + 1], + p[i* 4 + 2], + p[i* 4 + 3]); + } + else if(type == GL_SHORT) + { + cl_short* p = (cl_short*)buffer; + for(i = 0; i < count; i++) + log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), + p[i* 4 + 0], + p[i* 4 + 1], + p[i* 4 + 2], + p[i* 4 + 3]); + } + else if(type == GL_UNSIGNED_SHORT) + { + cl_ushort* p = (cl_ushort*)buffer; + for(i = 0; i < count; i++) + log_info("[%4d] %3d %3d %3d %3d\n", (unsigned int)(i), + p[i* 4 + 0], + p[i* 4 + 1], + p[i* 4 + 2], + p[i* 4 + 3]); + } + else if(type == GL_FLOAT) + { + cl_float* p = (cl_float*)buffer; + for(i = 0; i < count; i++) + log_info("[%4d] %#f %#f %#f %#f\n", (unsigned int)(i), + p[i* 4 + 0], + p[i* 4 + 1], + p[i* 4 + 2], + p[i* 4 + 3]); + } +} + +#if defined(_WIN32) +#include + +GLboolean gluCheckExtension(const GLubyte *extName, const GLubyte *extString) +{ + const size_t len = strlen((const char*)extName); + const char* str = (const char*)extString; + + while (str != NULL) { + str = strstr(str, (const char*)extName); + if (str == NULL) { + break; + } + if ((str > (const char*)extString || str[-1] == ' ') + && (str[len] == ' ' || str[len] == '\0')) { + return GL_TRUE; + } + str = strchr(str + len, ' '); + } + + return GL_FALSE; +} + +#endif + +// Function pointers for the GL/CL calls +clCreateFromGLBuffer_fn clCreateFromGLBuffer_ptr; +clCreateFromGLTexture_fn clCreateFromGLTexture_ptr; +clCreateFromGLTexture2D_fn clCreateFromGLTexture2D_ptr; +clCreateFromGLTexture3D_fn clCreateFromGLTexture3D_ptr; +clCreateFromGLRenderbuffer_fn clCreateFromGLRenderbuffer_ptr; +clGetGLObjectInfo_fn clGetGLObjectInfo_ptr; +clGetGLTextureInfo_fn clGetGLTextureInfo_ptr; +clEnqueueAcquireGLObjects_fn clEnqueueAcquireGLObjects_ptr; +clEnqueueReleaseGLObjects_fn clEnqueueReleaseGLObjects_ptr; + +int init_clgl_ext() { + + // As OpenCL for the platforms. Warn if more than one platform found, + // since this might not be the platform we want. By default, we simply + // use the first returned platform. + + cl_uint nplatforms; + cl_platform_id platform; + clGetPlatformIDs(0, NULL, &nplatforms); + clGetPlatformIDs(1, &platform, NULL); + + if (nplatforms > 1) { + log_info("clGetPlatformIDs returned multiple values. This is not " + "an error, but might result in obtaining incorrect function " + "pointers if you do not want the first returned platform.\n"); + + // Show them the platform name, in case it is a problem. + + size_t size; + char *name; + + clGetPlatformInfo(platform, CL_PLATFORM_NAME, 0, NULL, &size); + name = (char*)malloc(size); + clGetPlatformInfo(platform, CL_PLATFORM_NAME, size, name, NULL); + + log_info("Using platform with name: %s \n", name); + free(name); + } + + // Create the function pointer table + clCreateFromGLBuffer_ptr = (clCreateFromGLBuffer_fn)clGetExtensionFunctionAddressForPlatform(platform,"clCreateFromGLBuffer"); + if (clCreateFromGLBuffer_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clCreateFromGLBuffer) returned NULL.\n"); + return -1; + } + clCreateFromGLTexture2D_ptr = (clCreateFromGLTexture2D_fn)clGetExtensionFunctionAddressForPlatform(platform,"clCreateFromGLTexture2D"); + if (clCreateFromGLTexture2D_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clCreateFromGLTexture2D) returned NULL.\n"); + return -1; + } + clCreateFromGLTexture3D_ptr = (clCreateFromGLTexture3D_fn)clGetExtensionFunctionAddressForPlatform(platform,"clCreateFromGLTexture3D"); + if (clCreateFromGLTexture3D_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clCreateFromGLTexture3D\") returned NULL.\n"); + return -1; + } + clCreateFromGLTexture_ptr = (clCreateFromGLTexture_fn)clGetExtensionFunctionAddressForPlatform(platform,"clCreateFromGLTexture"); + if (clCreateFromGLTexture_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,\"clCreateFromGLTexture\") returned NULL.\n"); + return -1; + } + clCreateFromGLRenderbuffer_ptr = (clCreateFromGLRenderbuffer_fn)clGetExtensionFunctionAddressForPlatform(platform,"clCreateFromGLRenderbuffer"); + if (clCreateFromGLRenderbuffer_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clCreateFromGLRenderbuffer) returned NULL.\n"); + return -1; + } + clGetGLObjectInfo_ptr = (clGetGLObjectInfo_fn)clGetExtensionFunctionAddressForPlatform(platform,"clGetGLObjectInfo"); + if (clGetGLObjectInfo_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clGetGLObjectInfo) returned NULL.\n"); + return -1; + } + clGetGLTextureInfo_ptr = (clGetGLTextureInfo_fn)clGetExtensionFunctionAddressForPlatform(platform,"clGetGLTextureInfo"); + if (clGetGLTextureInfo_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clGetGLTextureInfo) returned NULL.\n"); + return -1; + } + clEnqueueAcquireGLObjects_ptr = (clEnqueueAcquireGLObjects_fn)clGetExtensionFunctionAddressForPlatform(platform,"clEnqueueAcquireGLObjects"); + if (clEnqueueAcquireGLObjects_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clEnqueueAcquireGLObjects) returned NULL.\n"); + return -1; + } + clEnqueueReleaseGLObjects_ptr = (clEnqueueReleaseGLObjects_fn)clGetExtensionFunctionAddressForPlatform(platform,"clEnqueueReleaseGLObjects"); + if (clEnqueueReleaseGLObjects_ptr == NULL) { + log_error("clGetExtensionFunctionAddressForPlatform(platform,clEnqueueReleaseGLObjects) returned NULL.\n"); + return -1; + } + + return 0; +} + + diff --git a/test_conformance/compatibility/test_common/gl/helpers.h b/test_conformance/compatibility/test_common/gl/helpers.h new file mode 100644 index 00000000..86e7dde9 --- /dev/null +++ b/test_conformance/compatibility/test_common/gl/helpers.h @@ -0,0 +1,283 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _helpers_h +#define _helpers_h + +#include "../harness/compat.h" + +#include +#include +#include +#include + +#if !defined (__APPLE__) +#include +#include "gl_headers.h" +#include +#else +#include "gl_headers.h" +#endif + +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/threadTesting.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/mt19937.h" + +typedef cl_mem +(CL_API_CALL *clCreateFromGLBuffer_fn)(cl_context context, + cl_mem_flags flags, + GLuint bufobj, + int * errcode_ret); + +typedef cl_mem +(CL_API_CALL *clCreateFromGLTexture_fn)(cl_context context , + cl_mem_flags flags , + GLenum target , + GLint miplevel , + GLuint texture , + cl_int * errcode_ret) ; + +typedef cl_mem +(CL_API_CALL *clCreateFromGLTexture2D_fn)(cl_context context , + cl_mem_flags flags , + GLenum target , + GLint miplevel , + GLuint texture , + cl_int * errcode_ret) ; + +typedef cl_mem +(CL_API_CALL *clCreateFromGLTexture3D_fn)(cl_context context , + cl_mem_flags flags , + GLenum target , + GLint miplevel , + GLuint texture , + cl_int * errcode_ret) ; + +typedef cl_mem +(CL_API_CALL *clCreateFromGLRenderbuffer_fn)(cl_context context , + cl_mem_flags flags , + GLuint renderbuffer , + cl_int * errcode_ret) ; + +typedef cl_int +(CL_API_CALL *clGetGLObjectInfo_fn)(cl_mem memobj , + cl_gl_object_type * gl_object_type , + GLuint * gl_object_name) ; + +typedef cl_int +(CL_API_CALL *clGetGLTextureInfo_fn)(cl_mem memobj , + cl_gl_texture_info param_name , + size_t param_value_size , + void * param_value , + size_t * param_value_size_ret) ; + +typedef cl_int +(CL_API_CALL *clEnqueueAcquireGLObjects_fn)(cl_command_queue command_queue , + cl_uint num_objects , + const cl_mem * mem_objects , + cl_uint num_events_in_wait_list , + const cl_event * event_wait_list , + cl_event * event) ; + +typedef cl_int +(CL_API_CALL *clEnqueueReleaseGLObjects_fn)(cl_command_queue command_queue , + cl_uint num_objects , + const cl_mem * mem_objects , + cl_uint num_events_in_wait_list , + const cl_event * event_wait_list , + cl_event * event) ; + + +extern clCreateFromGLBuffer_fn clCreateFromGLBuffer_ptr; +extern clCreateFromGLTexture_fn clCreateFromGLTexture_ptr; +extern clCreateFromGLTexture2D_fn clCreateFromGLTexture2D_ptr; +extern clCreateFromGLTexture3D_fn clCreateFromGLTexture3D_ptr; +extern clCreateFromGLRenderbuffer_fn clCreateFromGLRenderbuffer_ptr; +extern clGetGLObjectInfo_fn clGetGLObjectInfo_ptr; +extern clGetGLTextureInfo_fn clGetGLTextureInfo_ptr; +extern clEnqueueAcquireGLObjects_fn clEnqueueAcquireGLObjects_ptr; +extern clEnqueueReleaseGLObjects_fn clEnqueueReleaseGLObjects_ptr; + + +class glBufferWrapper +{ + public: + glBufferWrapper() { mBuffer = 0; } + glBufferWrapper( GLuint b ) { mBuffer = b; } + ~glBufferWrapper() { if( mBuffer != 0 ) glDeleteBuffers( 1, &mBuffer ); } + + glBufferWrapper & operator=( const GLuint &rhs ) { mBuffer = rhs; return *this; } + operator GLuint() { return mBuffer; } + operator GLuint *() { return &mBuffer; } + + GLuint * operator&() { return &mBuffer; } + + bool operator==( GLuint rhs ) { return mBuffer == rhs; } + + protected: + + GLuint mBuffer; +}; + +class glTextureWrapper +{ + public: + glTextureWrapper() { mHandle = 0; } + glTextureWrapper( GLuint b ) { mHandle = b; } + ~glTextureWrapper() { + if( mHandle != 0 ) glDeleteTextures( 1, &mHandle ); + } + + glTextureWrapper & operator=( const GLuint &rhs ) { mHandle = rhs; return *this; } + operator GLuint() { return mHandle; } + operator GLuint *() { return &mHandle; } + + GLuint * operator&() { return &mHandle; } + + bool operator==( GLuint rhs ) { return mHandle == rhs; } + + protected: + + // The texture handle. + GLuint mHandle; +}; + +class glRenderbufferWrapper +{ + public: + glRenderbufferWrapper() { mBuffer = 0; } + glRenderbufferWrapper( GLuint b ) { mBuffer = b; } + ~glRenderbufferWrapper() { if( mBuffer != 0 ) glDeleteRenderbuffersEXT( 1, &mBuffer ); } + + glRenderbufferWrapper & operator=( const GLuint &rhs ) { mBuffer = rhs; return *this; } + operator GLuint() { return mBuffer; } + operator GLuint *() { return &mBuffer; } + + GLuint * operator&() { return &mBuffer; } + + bool operator==( GLuint rhs ) { return mBuffer == rhs; } + + protected: + + GLuint mBuffer; +}; + +class glFramebufferWrapper +{ + public: + glFramebufferWrapper() { mBuffer = 0; } + glFramebufferWrapper( GLuint b ) { mBuffer = b; } + ~glFramebufferWrapper() { if( mBuffer != 0 ) glDeleteFramebuffersEXT( 1, &mBuffer ); } + + glFramebufferWrapper & operator=( const GLuint &rhs ) { mBuffer = rhs; return *this; } + operator GLuint() { return mBuffer; } + operator GLuint *() { return &mBuffer; } + + GLuint * operator&() { return &mBuffer; } + + bool operator==( GLuint rhs ) { return mBuffer == rhs; } + + protected: + + GLuint mBuffer; +}; + + +// Helper functions (defined in helpers.cpp) + +extern void * CreateGLTexture1DArray( size_t width, size_t length, + GLenum target, GLenum glFormat, GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, int *outError, + bool allocateMem, MTdata d); + +extern void * CreateGLTexture2DArray( size_t width, size_t height, size_t length, + GLenum target, GLenum glFormat, GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, int *outError, + bool allocateMem, MTdata d); + +extern void * CreateGLTextureBuffer( size_t width, + GLenum target, GLenum glFormat, GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTex, GLuint *outBuf, int *outError, + bool allocateMem, MTdata d); + +extern void * CreateGLTexture1D(size_t width, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, bool allocateMem, MTdata d ); + +extern void * CreateGLTexture2D( size_t width, size_t height, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, bool allocateMem, MTdata d ); + + +extern void * CreateGLTexture3D( size_t width, size_t height, size_t depth, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, GLuint *outTextureID, + int *outError, MTdata d, bool allocateMem = true ); + +extern void * ReadGLTexture( GLenum glTarget, GLuint glTexture, GLuint glBuf, GLint width, + GLenum glFormat, GLenum glInternalFormat, + GLenum glType, ExplicitType typeToReadAs, + size_t outWidth, size_t outHeight ); + +extern int CreateGLRenderbufferRaw( GLsizei width, GLsizei height, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + GLuint *outFramebuffer, + GLuint *outRenderbuffer ); + +extern void * CreateGLRenderbuffer( GLsizei width, GLsizei height, + GLenum target, GLenum glFormat, + GLenum internalFormat, GLenum glType, + ExplicitType type, + GLuint *outFramebuffer, + GLuint *outRenderbuffer, + int *outError, MTdata d, bool allocateMem ); + +extern void * ReadGLRenderbuffer( GLuint glFramebuffer, GLuint glRenderbuffer, + GLenum attachment, GLenum glFormat, + GLenum glInternalFormat, GLenum glType, + ExplicitType typeToReadAs, + size_t outWidth, size_t outHeight ); + +extern void DumpGLBuffer(GLenum type, size_t width, size_t height, void* buffer); +extern const char *GetGLTypeName( GLenum type ); +extern const char *GetGLAttachmentName( GLenum att ); +extern const char *GetGLTargetName( GLenum tgt ); +extern const char *GetGLBaseFormatName( GLenum baseformat ); +extern const char *GetGLFormatName( GLenum format ); + +extern void* CreateRandomData( ExplicitType type, size_t count, MTdata d ); + +extern GLenum GetGLFormat(GLenum internalFormat); +extern GLenum GetGLTypeForExplicitType(ExplicitType type); +extern size_t GetGLTypeSize(GLenum type); +extern ExplicitType GetExplicitTypeForGLType(GLenum type); + +extern GLenum get_base_gl_target( GLenum target ); + +extern int init_clgl_ext( void ); + +#endif // _helpers_h + + + diff --git a/test_conformance/compatibility/test_common/gl/setup.h b/test_conformance/compatibility/test_common/gl/setup.h new file mode 100644 index 00000000..6ee810bb --- /dev/null +++ b/test_conformance/compatibility/test_common/gl/setup.h @@ -0,0 +1,48 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _setup_h +#define _setup_h + +#include +#include +#include +#include "gl_headers.h" +#ifdef __APPLE__ +#include +#else +#include +#endif + + +// Note: the idea here is to have every platform define their own setup.cpp file that implements a GLEnvironment +// subclass internally, then return it as a definition for GLEnvironment::Create + +class GLEnvironment +{ + public: + GLEnvironment() {} + virtual ~GLEnvironment() {} + + virtual int Init( int *argc, char **argv, int use_opengl_32 ) = 0; + virtual cl_context CreateCLContext( void ) = 0; + virtual int SupportsCLGLInterop( cl_device_type device_type) = 0; + + static GLEnvironment * Instance( void ); + + +}; + +#endif // _setup_h diff --git a/test_conformance/compatibility/test_common/gl/setup_osx.cpp b/test_conformance/compatibility/test_common/gl/setup_osx.cpp new file mode 100644 index 00000000..01641be0 --- /dev/null +++ b/test_conformance/compatibility/test_common/gl/setup_osx.cpp @@ -0,0 +1,156 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "setup.h" +#include "../../test_common/harness/errorHelpers.h" +#include + +class OSXGLEnvironment : public GLEnvironment +{ + public: + OSXGLEnvironment() + { + mCGLContext = NULL; + } + + virtual int Init( int *argc, char **argv, int use_opengl_32 ) + { + if (!use_opengl_32) { + + // Create a GLUT window to render into + glutInit( argc, argv ); + glutInitWindowSize( 512, 512 ); + glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); + glutCreateWindow( "OpenCL <-> OpenGL Test" ); + } + + else { + + CGLPixelFormatAttribute attribs[] = { + kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core, + kCGLPFAAllowOfflineRenderers, + kCGLPFANoRecovery, + kCGLPFAAccelerated, + kCGLPFADoubleBuffer, + (CGLPixelFormatAttribute)0 + }; + + CGLError err; + CGLPixelFormatObj pix; + GLint npix; + err = CGLChoosePixelFormat (attribs, &pix, &npix); + if(err != kCGLNoError) + { + log_error("Failed to choose pixel format\n"); + return -1; + } + err = CGLCreateContext(pix, NULL, &mCGLContext); + if(err != kCGLNoError) + { + log_error("Failed to create GL context\n"); + return -1; + } + CGLSetCurrentContext(mCGLContext); + } + + return 0; + } + + virtual cl_context CreateCLContext( void ) + { + int error; + + if( mCGLContext == NULL ) + mCGLContext = CGLGetCurrentContext(); + + CGLShareGroupObj share_group = CGLGetShareGroup(mCGLContext); + cl_context_properties properties[] = { CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)share_group, 0 }; + cl_context context = clCreateContext(properties, 0, 0, 0, 0, &error); + if (error) { + print_error(error, "clCreateContext failed"); + return NULL; + } + + // Verify that all devices in the context support the required extension + cl_device_id devices[64]; + size_t size_out; + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, sizeof(devices), devices, &size_out); + if (error) { + print_error(error, "clGetContextInfo failed"); + return NULL; + } + + char extensions[8192]; + for (int i=0; i<(int)(size_out/sizeof(cl_device_id)); i++) { + error = clGetDeviceInfo(devices[i], CL_DEVICE_EXTENSIONS, sizeof(extensions), extensions, NULL); + if (error) { + print_error(error, "clGetDeviceInfo failed"); + return NULL; + } + + if (strstr(extensions, "cl_APPLE_gl_sharing") == NULL) { + log_error("Device %d does not supporte required extension cl_APPLE_gl_sharing.\n", i); + return NULL; + } + } + return context; + } + + virtual int SupportsCLGLInterop( cl_device_type device_type ) + { + int found_valid_device = 0; + cl_device_id devices[64]; + cl_uint num_of_devices; + int error; + error = clGetDeviceIDs(NULL, device_type, 64, devices, &num_of_devices); + if (error) { + print_error(error, "clGetDeviceIDs failed"); + return -1; + } + + char extensions[8192]; + for (int i=0; i<(int)num_of_devices; i++) { + error = clGetDeviceInfo(devices[i], CL_DEVICE_EXTENSIONS, sizeof(extensions), extensions, NULL); + if (error) { + print_error(error, "clGetDeviceInfo failed"); + return -1; + } + + if (strstr(extensions, "cl_APPLE_gl_sharing") == NULL) { + log_info("Device %d of %d does not support required extension cl_APPLE_gl_sharing.\n", i, num_of_devices); + } else { + log_info("Device %d of %d does support required extension cl_APPLE_gl_sharing.\n", i, num_of_devices); + found_valid_device = 1; + } + } + return found_valid_device; + } + + virtual ~OSXGLEnvironment() + { + CGLDestroyContext( mCGLContext ); + } + + CGLContextObj mCGLContext; + +}; + +GLEnvironment * GLEnvironment::Instance( void ) +{ + static OSXGLEnvironment * env = NULL; + if( env == NULL ) + env = new OSXGLEnvironment(); + return env; +} diff --git a/test_conformance/compatibility/test_common/gl/setup_win32.cpp b/test_conformance/compatibility/test_common/gl/setup_win32.cpp new file mode 100644 index 00000000..ff40dc25 --- /dev/null +++ b/test_conformance/compatibility/test_common/gl/setup_win32.cpp @@ -0,0 +1,204 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#define GL_GLEXT_PROTOTYPES + +#include "setup.h" +#include "testBase.h" +#include "../../test_common/harness/errorHelpers.h" + +#include +#include +#include +#include +#include + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetGLContextInfoKHR_fn)( + const cl_context_properties *properties, + cl_gl_context_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret); + +// Rename references to this dynamically linked function to avoid +// collision with static link version +#define clGetGLContextInfoKHR clGetGLContextInfoKHR_proc +static clGetGLContextInfoKHR_fn clGetGLContextInfoKHR; + +#define MAX_DEVICES 32 + +class WGLEnvironment : public GLEnvironment +{ +private: + cl_device_id m_devices[MAX_DEVICES]; + int m_device_count; + cl_platform_id m_platform; + +public: + WGLEnvironment() + { + m_device_count = 0; + m_platform = 0; + + } + virtual int Init( int *argc, char **argv, int use_opengl_32 ) + { + // Create a GLUT window to render into + glutInit( argc, argv ); + glutInitWindowSize( 512, 512 ); + glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); + glutCreateWindow( "OpenCL <-> OpenGL Test" ); + glewInit(); + return 0; + } + + virtual cl_context CreateCLContext( void ) + { + HGLRC hGLRC = wglGetCurrentContext(); + HDC hDC = wglGetCurrentDC(); + cl_context_properties properties[] = { + CL_CONTEXT_PLATFORM, (cl_context_properties) m_platform, + CL_GL_CONTEXT_KHR, (cl_context_properties) hGLRC, + CL_WGL_HDC_KHR, (cl_context_properties) hDC, + 0 + }; + cl_device_id devices[MAX_DEVICES]; + size_t dev_size; + cl_int status; + + if (!hGLRC || !hDC) { + print_error(CL_INVALID_CONTEXT, "No GL context bound"); + return 0; + } + + if (!clGetGLContextInfoKHR) { + // As OpenCL for the platforms. Warn if more than one platform found, + // since this might not be the platform we want. By default, we simply + // use the first returned platform. + + cl_uint nplatforms; + cl_platform_id platform; + clGetPlatformIDs(0, NULL, &nplatforms); + clGetPlatformIDs(1, &platform, NULL); + + if (nplatforms > 1) { + log_info("clGetPlatformIDs returned multiple values. This is not " + "an error, but might result in obtaining incorrect function " + "pointers if you do not want the first returned platform.\n"); + + // Show them the platform name, in case it is a problem. + + size_t size; + char *name; + + clGetPlatformInfo(platform, CL_PLATFORM_NAME, 0, NULL, &size); + name = (char*)malloc(size); + clGetPlatformInfo(platform, CL_PLATFORM_NAME, size, name, NULL); + + log_info("Using platform with name: %s \n", name); + free(name); + } + + clGetGLContextInfoKHR = (clGetGLContextInfoKHR_fn) clGetExtensionFunctionAddressForPlatform(platform, "clGetGLContextInfoKHR"); + if (!clGetGLContextInfoKHR) { + print_error(CL_INVALID_PLATFORM, "Failed to query proc address for clGetGLContextInfoKHR"); + } + } + + status = clGetGLContextInfoKHR(properties, + CL_DEVICES_FOR_GL_CONTEXT_KHR, + sizeof(devices), + devices, + &dev_size); + if (status != CL_SUCCESS) { + print_error(status, "clGetGLContextInfoKHR failed"); + return 0; + } + dev_size /= sizeof(cl_device_id); + log_info("GL context supports %d compute devices\n", dev_size); + + status = clGetGLContextInfoKHR(properties, + CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR, + sizeof(devices), + devices, + &dev_size); + if (status != CL_SUCCESS) { + print_error(status, "clGetGLContextInfoKHR failed"); + return 0; + } + + cl_device_id ctxDevice = m_devices[0]; + if (dev_size > 0) { + log_info("GL context current device: 0x%x\n", devices[0]); + for (int i = 0; i < m_device_count; i++) { + if (m_devices[i] == devices[0]) { + ctxDevice = devices[0]; + break; + } + } + } else { + log_info("GL context current device is not a CL device, using device %d.\n", ctxDevice); + } + + return clCreateContext(properties, 1, &ctxDevice, NULL, NULL, &status); + } + + virtual int SupportsCLGLInterop( cl_device_type device_type ) + { + cl_device_id devices[MAX_DEVICES]; + cl_uint num_of_devices; + int error; + error = clGetPlatformIDs(1, &m_platform, NULL); + if (error) { + print_error(error, "clGetPlatformIDs failed"); + return -1; + } + error = clGetDeviceIDs(m_platform, device_type, MAX_DEVICES, devices, &num_of_devices); + if (error) { + print_error(error, "clGetDeviceIDs failed"); + return -1; + } + + // Check all devices, search for one that supports cl_khr_gl_sharing + char extensions[8192]; + for (int i=0; i<(int)num_of_devices; i++) { + error = clGetDeviceInfo(devices[i], CL_DEVICE_EXTENSIONS, sizeof(extensions), extensions, NULL); + if (error) { + print_error(error, "clGetDeviceInfo failed"); + return -1; + } + + if (strstr(extensions, "cl_khr_gl_sharing") == NULL) { + log_info("Device %d of %d does not support required extension cl_khr_gl_sharing.\n", i+1, num_of_devices); + } else { + log_info("Device %d of %d supports required extension cl_khr_gl_sharing.\n", i+1, num_of_devices); + m_devices[m_device_count++] = devices[i]; + } + } + return m_device_count > 0; + } + + virtual ~WGLEnvironment() + { + } +}; + +GLEnvironment * GLEnvironment::Instance( void ) +{ + static WGLEnvironment * env = NULL; + if( env == NULL ) + env = new WGLEnvironment(); + return env; +} diff --git a/test_conformance/compatibility/test_common/gl/setup_x11.cpp b/test_conformance/compatibility/test_common/gl/setup_x11.cpp new file mode 100644 index 00000000..22bc7eed --- /dev/null +++ b/test_conformance/compatibility/test_common/gl/setup_x11.cpp @@ -0,0 +1,122 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#define GL_GLEXT_PROTOTYPES + +#include "setup.h" +#include "testBase.h" +#include "../../test_common/harness/errorHelpers.h" + +#include +#include +#include +#include +#include +#include + +class X11GLEnvironment : public GLEnvironment +{ +private: + cl_device_id m_devices[64]; + cl_uint m_device_count; + +public: + X11GLEnvironment() + { + m_device_count = 0; + } + virtual int Init( int *argc, char **argv, int use_opencl_32 ) + { + // Create a GLUT window to render into + glutInit( argc, argv ); + glutInitWindowSize( 512, 512 ); + glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); + glutCreateWindow( "OpenCL <-> OpenGL Test" ); + glewInit(); + return 0; + } + + virtual cl_context CreateCLContext( void ) + { + GLXContext context = glXGetCurrentContext(); + Display *dpy = glXGetCurrentDisplay(); + + cl_context_properties properties[] = { + CL_GL_CONTEXT_KHR, (cl_context_properties) context, + CL_GLX_DISPLAY_KHR, (cl_context_properties) dpy, + 0 + }; + cl_int status; + + if (!context || !dpy) { + print_error(CL_INVALID_CONTEXT, "No GL context bound"); + return 0; + } + + return clCreateContext(properties, 1, m_devices, NULL, NULL, &status); + } + + virtual int SupportsCLGLInterop( cl_device_type device_type ) + { + int found_valid_device = 0; + cl_platform_id platform; + cl_device_id devices[64]; + cl_uint num_of_devices; + int error; + error = clGetPlatformIDs(1, &platform, NULL); + if (error) { + print_error(error, "clGetPlatformIDs failed"); + return -1; + } + error = clGetDeviceIDs(platform, device_type, 64, devices, &num_of_devices); + // If this platform doesn't have any of the requested device_type (namely GPUs) then return 0 + if (error == CL_DEVICE_NOT_FOUND) + return 0; + if (error) { + print_error(error, "clGetDeviceIDs failed"); + return -1; + } + + char extensions[8192]; + for (int i=0; i<(int)num_of_devices; i++) { + error = clGetDeviceInfo(devices[i], CL_DEVICE_EXTENSIONS, sizeof(extensions), extensions, NULL); + if (error) { + print_error(error, "clGetDeviceInfo failed"); + return -1; + } + + if (strstr(extensions, "cl_khr_gl_sharing ") == NULL) { + log_info("Device %d of %d does not support required extension cl_khr_gl_sharing.\n", i+1, num_of_devices); + } else { + log_info("Device %d of %d supports required extension cl_khr_gl_sharing.\n", i+1, num_of_devices); + found_valid_device = 1; + m_devices[m_device_count++] = devices[i]; + } + } + return found_valid_device; + } + + virtual ~X11GLEnvironment() + { + } +}; + +GLEnvironment * GLEnvironment::Instance( void ) +{ + static X11GLEnvironment * env = NULL; + if( env == NULL ) + env = new X11GLEnvironment(); + return env; +} diff --git a/test_conformance/compatibility/test_common/harness/Jamfile b/test_conformance/compatibility/test_common/harness/Jamfile new file mode 100644 index 00000000..21ebcc24 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/Jamfile @@ -0,0 +1,18 @@ +project + : requirements . + gcc:"-xc++" + msvc:"/TP" + off + : usage-requirements . + ; + +local harness.objs ; +for source in [ glob *.c *.cpp ] +{ + harness.objs += [ obj $(source:B).obj : $(source) ] ; +} + +alias harness : $(harness.objs) + : /Runtime//OpenCL.lib : + : /Runtime//OpenCL.lib + ; diff --git a/test_conformance/compatibility/test_common/harness/Makefile b/test_conformance/compatibility/test_common/harness/Makefile new file mode 100644 index 00000000..2ac60643 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/Makefile @@ -0,0 +1,41 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = conversions.c \ + errorHelpers.c \ + genericThread.cpp \ + imageHelpers.cpp \ + kernelHelpers.c \ + mt19937.c \ + rounding_mode.c \ + testHarness.c \ + testHarness.cpp \ + ThreadPool.c \ + threadTesting.c \ + typeWrappers.cpp + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +HEADERS = +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +all: $(OBJECTS) + +clean: + rm -f $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/compatibility/test_common/harness/ThreadPool.c b/test_conformance/compatibility/test_common/harness/ThreadPool.c new file mode 100644 index 00000000..a4598f2e --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/ThreadPool.c @@ -0,0 +1,899 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "ThreadPool.h" +#include "errorHelpers.h" +#include "fpcontrol.h" +#include +#include + +#if defined( __APPLE__ ) || defined( __linux__ ) || defined( _WIN32 ) // or any other POSIX system + +#if defined( _WIN32 ) +#include +#if defined(_MSC_VER) +#include +#endif +#include "mingw_compat.h" +#include +#else // !_WIN32 +#include +#include +#include +#endif // !_WIN32 + +// declarations +#ifdef _WIN32 +void ThreadPool_WorkerFunc( void *p ); +#else +void *ThreadPool_WorkerFunc( void *p ); +#endif +void ThreadPool_Init(void); +void ThreadPool_Exit(void); + +#if defined (__MINGW32__) + // Mutex for implementing super heavy atomic operations if you don't have GCC or MSVC + CRITICAL_SECTION gAtomicLock; +#elif defined( __GNUC__ ) || defined( _MSC_VER) +#else + pthread_mutex_t gAtomicLock; +#endif + +// Atomic add operator with mem barrier. Mem barrier needed to protect state modified by the worker functions. +cl_int ThreadPool_AtomicAdd( volatile cl_int *a, cl_int b ) +{ +#if defined (__MINGW32__) + // No atomics on Mingw32 + EnterCriticalSection(&gAtomicLock); + cl_int old = *a; + *a = old + b; + LeaveCriticalSection(&gAtomicLock); + return old; +#elif defined( __GNUC__ ) + // GCC extension: http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html#Atomic-Builtins + return __sync_fetch_and_add( a, b ); + // do we need __sync_synchronize() here, too? GCC docs are unclear whether __sync_fetch_and_add does a synchronize +#elif defined( _MSC_VER ) + return (cl_int) _InterlockedExchangeAdd( (volatile LONG*) a, (LONG) b ); +#else + #warning Please add a atomic add implementation here, with memory barrier. Fallback code is slow. + if( pthread_mutex_lock(&gAtomicLock) ) + log_error( "Atomic operation failed. pthread_mutex_lock(&gAtomicLock) returned an error\n"); + cl_int old = *a; + *a = old + b; + if( pthread_mutex_unlock(&gAtomicLock) ) + log_error( "Failed to release gAtomicLock. Further atomic operations may deadlock!\n"); + return old; +#endif +} + +#if defined( _WIN32 ) +// Uncomment the following line if Windows XP support is not required. +// #define HAS_INIT_ONCE_EXECUTE_ONCE 1 + +#if defined(HAS_INIT_ONCE_EXECUTE_ONCE) +#define _INIT_ONCE INIT_ONCE +#define _PINIT_ONCE PINIT_ONCE +#define _InitOnceExecuteOnce InitOnceExecuteOnce +#else // !HAS_INIT_ONCE_EXECUTE_ONCE + +typedef volatile LONG _INIT_ONCE; +typedef _INIT_ONCE *_PINIT_ONCE; +typedef BOOL (CALLBACK *_PINIT_ONCE_FN)(_PINIT_ONCE, PVOID, PVOID *); + +#define _INIT_ONCE_UNINITIALIZED 0 +#define _INIT_ONCE_IN_PROGRESS 1 +#define _INIT_ONCE_DONE 2 + +static BOOL _InitOnceExecuteOnce( + _PINIT_ONCE InitOnce, + _PINIT_ONCE_FN InitFn, + PVOID Parameter, + LPVOID *Context +) +{ + while ( *InitOnce != _INIT_ONCE_DONE ) + { + if (*InitOnce != _INIT_ONCE_IN_PROGRESS && _InterlockedCompareExchange( InitOnce, _INIT_ONCE_IN_PROGRESS, _INIT_ONCE_UNINITIALIZED ) == _INIT_ONCE_UNINITIALIZED ) + { + InitFn( InitOnce, Parameter, Context ); + *InitOnce = _INIT_ONCE_DONE; + return TRUE; + } + Sleep( 1 ); + } + return TRUE; +} +#endif // !HAS_INIT_ONCE_EXECUTE_ONCE + +// Uncomment the following line if Windows XP support is not required. +// #define HAS_CONDITION_VARIABLE 1 + +#if defined(HAS_CONDITION_VARIABLE) +#define _CONDITION_VARIABLE CONDITION_VARIABLE +#define _InitializeConditionVariable InitializeConditionVariable +#define _SleepConditionVariableCS SleepConditionVariableCS +#define _WakeAllConditionVariable WakeAllConditionVariable +#else // !HAS_CONDITION_VARIABLE +typedef struct +{ + HANDLE mEvent; // Used to park the thread. + CRITICAL_SECTION mLock[1]; // Used to protect mWaiters, mGeneration and mReleaseCount. + volatile cl_int mWaiters; // Number of threads waiting on this cond var. + volatile cl_int mGeneration; // Wait generation count. + volatile cl_int mReleaseCount; // Number of releases to execute before reseting the event. +} _CONDITION_VARIABLE; + +typedef _CONDITION_VARIABLE *_PCONDITION_VARIABLE; + +static void _InitializeConditionVariable( _PCONDITION_VARIABLE cond_var ) +{ + cond_var->mEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); + InitializeCriticalSection( cond_var->mLock ); + cond_var->mWaiters = 0; + cond_var->mGeneration = 0; +#if !defined ( NDEBUG ) + cond_var->mReleaseCount = 0; +#endif // !NDEBUG +} + +static void _SleepConditionVariableCS( _PCONDITION_VARIABLE cond_var, PCRITICAL_SECTION cond_lock, DWORD ignored) +{ + EnterCriticalSection( cond_var->mLock ); + cl_int generation = cond_var->mGeneration; + ++cond_var->mWaiters; + LeaveCriticalSection( cond_var->mLock ); + LeaveCriticalSection( cond_lock ); + + while ( TRUE ) + { + WaitForSingleObject( cond_var->mEvent, INFINITE ); + EnterCriticalSection( cond_var->mLock ); + BOOL done = cond_var->mReleaseCount > 0 && cond_var->mGeneration != generation; + LeaveCriticalSection( cond_var->mLock ); + if ( done ) + { + break; + } + } + + EnterCriticalSection( cond_lock ); + EnterCriticalSection( cond_var->mLock ); + if ( --cond_var->mReleaseCount == 0 ) + { + ResetEvent( cond_var->mEvent ); + } + --cond_var->mWaiters; + LeaveCriticalSection( cond_var->mLock ); +} + +static void _WakeAllConditionVariable( _PCONDITION_VARIABLE cond_var ) +{ + EnterCriticalSection( cond_var->mLock ); + if (cond_var->mWaiters > 0 ) + { + ++cond_var->mGeneration; + cond_var->mReleaseCount = cond_var->mWaiters; + SetEvent( cond_var->mEvent ); + } + LeaveCriticalSection( cond_var->mLock ); +} +#endif // !HAS_CONDITION_VARIABLE +#endif // _WIN32 + +#define MAX_COUNT (1<<29) + +// Global state to coordinate whether the threads have been launched successfully or not +#if defined( _MSC_VER ) && (_WIN32_WINNT >= 0x600) +static _INIT_ONCE threadpool_init_control; +#elif defined (_WIN32) // MingW of XP +static int threadpool_init_control; +#else // Posix platforms +pthread_once_t threadpool_init_control = PTHREAD_ONCE_INIT; +#endif +cl_int threadPoolInitErr = -1; // set to CL_SUCCESS on successful thread launch + +// critical region lock around ThreadPool_Do. We can only run one ThreadPool_Do at a time, +// because we are too lazy to set up a queue here, and don't expect to need one. +#if defined( _WIN32 ) +CRITICAL_SECTION gThreadPoolLock[1]; +#else // !_WIN32 +pthread_mutex_t gThreadPoolLock; +#endif // !_WIN32 + +// Condition variable to park ThreadPool threads when not working +#if defined( _WIN32 ) +CRITICAL_SECTION cond_lock[1]; +_CONDITION_VARIABLE cond_var[1]; +#else // !_WIN32 +pthread_mutex_t cond_lock; +pthread_cond_t cond_var; +#endif // !_WIN32 +volatile cl_int gRunCount = 0; // Condition variable state. How many iterations on the function left to run. + // set to CL_INT_MAX to cause worker threads to exit. Note: this value might go negative. + +// State that only changes when the threadpool is not working. +volatile TPFuncPtr gFunc_ptr = NULL; +volatile void *gUserInfo = NULL; +volatile cl_int gJobCount = 0; + +// State that may change while the thread pool is working +volatile cl_int jobError = CL_SUCCESS; // err code return for the job as a whole + +// Condition variable to park caller while waiting +#if defined( _WIN32 ) +HANDLE caller_event; +#else // !_WIN32 +pthread_mutex_t caller_cond_lock; +pthread_cond_t caller_cond_var; +#endif // !_WIN32 +volatile cl_int gRunning = 0; // # of threads intended to be running. Running threads will decrement this as they discover they've run out of work to do. + +// The total number of threads launched. +volatile cl_int gThreadCount = 0; +#ifdef _WIN32 +void ThreadPool_WorkerFunc( void *p ) +#else +void *ThreadPool_WorkerFunc( void *p ) +#endif +{ + cl_uint threadID = ThreadPool_AtomicAdd( (volatile cl_int *) p, 1 ); + cl_int item = ThreadPool_AtomicAdd( &gRunCount, -1 ); +// log_info( "ThreadPool_WorkerFunc start: gRunning = %d\n", gRunning ); + + while( MAX_COUNT > item ) + { + cl_int err; + + // check for more work to do + if( 0 >= item ) + { +// log_info( "Thread %d has run out of work.\n", threadID ); + + // No work to do. Attempt to block waiting for work +#if defined( _WIN32 ) + EnterCriticalSection( cond_lock ); +#else // !_WIN32 + if((err = pthread_mutex_lock( &cond_lock) )) + { + log_error("Error %d from pthread_mutex_lock. Worker %d unable to block waiting for work. ThreadPool_WorkerFunc failed.\n", err, threadID ); + goto exit; + } +#endif // !_WIN32 + + cl_int remaining = ThreadPool_AtomicAdd( &gRunning, -1 ); +// log_info( "ThreadPool_WorkerFunc: gRunning = %d\n", remaining - 1 ); + if( 1 == remaining ) + { // last thread out signal the main thread to wake up +#if defined( _WIN32 ) + SetEvent( caller_event ); +#else // !_WIN32 + if((err = pthread_mutex_lock( &caller_cond_lock) )) + { + log_error("Error %d from pthread_mutex_lock. Unable to wake caller.\n", err ); + goto exit; + } + if( (err = pthread_cond_broadcast( &caller_cond_var ))) + { + log_error("Error %d from pthread_cond_broadcast. Unable to wake up main thread. ThreadPool_WorkerFunc failed.\n", err ); + goto exit; + } + if((err = pthread_mutex_unlock( &caller_cond_lock) )) + { + log_error("Error %d from pthread_mutex_lock. Unable to wake caller.\n", err ); + goto exit; + } +#endif // !_WIN32 + } + + // loop in case we are woken only to discover that some other thread already did all the work + while( 0 >= item ) + { +#if defined( _WIN32 ) + _SleepConditionVariableCS( cond_var, cond_lock, INFINITE ); +#else // !_WIN32 + if((err = pthread_cond_wait( &cond_var, &cond_lock) )) + { + log_error("Error %d from pthread_cond_wait. Unable to block for waiting for work. ThreadPool_WorkerFunc failed.\n", err ); + pthread_mutex_unlock( &cond_lock); + goto exit; + } +#endif // !_WIN32 + + // try again to get a valid item id + item = ThreadPool_AtomicAdd( &gRunCount, -1 ); + if( MAX_COUNT <= item ) // exit if we are done + { +#if defined( _WIN32 ) + LeaveCriticalSection( cond_lock ); +#else // !_WIN32 + pthread_mutex_unlock( &cond_lock); +#endif // !_WIN32 + goto exit; + } + } + + ThreadPool_AtomicAdd( &gRunning, 1 ); +// log_info( "Thread %d has found work.\n", threadID); + +#if defined( _WIN32 ) + LeaveCriticalSection( cond_lock ); +#else // !_WIN32 + if((err = pthread_mutex_unlock( &cond_lock) )) + { + log_error("Error %d from pthread_mutex_unlock. Unable to block for waiting for work. ThreadPool_WorkerFunc failed.\n", err ); + goto exit; + } +#endif // !_WIN32 + + } + + // we have a valid item, so do the work + if( CL_SUCCESS == jobError ) // but only if we haven't already encountered an error + { +// log_info( "Thread %d doing job %d\n", threadID, item - 1); + +#if defined(__APPLE__) && defined(__arm__) + // On most platforms which support denorm, default is FTZ off. However, + // on some hardware where the reference is computed, default might be flush denorms to zero e.g. arm. + // This creates issues in result verification. Since spec allows the implementation to either flush or + // not flush denorms to zero, an implementation may choose not be flush i.e. return denorm result whereas + // reference result may be zero (flushed denorm). Hence we need to disable denorm flushing on host side + // where reference is being computed to make sure we get non-flushed reference result. If implementation + // returns flushed result, we correctly take care of that in verification code. + FPU_mode_type oldMode; + DisableFTZ( &oldMode ); +#endif + + // Call the user's function with this item ID + err = gFunc_ptr( item - 1, threadID, (void*) gUserInfo ); +#if defined(__APPLE__) && defined(__arm__) + // Restore FP state + RestoreFPState( &oldMode ); +#endif + + if( err ) + { +#if (__MINGW32__) + EnterCriticalSection(&gAtomicLock); + if( jobError == CL_SUCCESS ); + jobError = err; + gRunCount = 0; + LeaveCriticalSection(&gAtomicLock); +#elif defined( __GNUC__ ) + // GCC extension: http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html#Atomic-Builtins + // set the new error if we are the first one there. + __sync_val_compare_and_swap( &jobError, CL_SUCCESS, err ); + + // drop run count to 0 + gRunCount = 0; + __sync_synchronize(); +#elif defined( _MSC_VER ) + // set the new error if we are the first one there. + _InterlockedCompareExchange( (volatile LONG*) &jobError, err, CL_SUCCESS ); + + // drop run count to 0 + gRunCount = 0; + _mm_mfence(); +#else + if( pthread_mutex_lock(&gAtomicLock) ) + log_error( "Atomic operation failed. pthread_mutex_lock(&gAtomicLock) returned an error\n"); + if( jobError == CL_SUCCESS ); + jobError = err; + gRunCount = 0; + if( pthread_mutex_unlock(&gAtomicLock) ) + log_error( "Failed to release gAtomicLock. Further atomic operations may deadlock\n"); +#endif + } + } + + // get the next item + item = ThreadPool_AtomicAdd( &gRunCount, -1 ); + } + +exit: + log_info( "ThreadPool: thread %d exiting.\n", threadID ); + ThreadPool_AtomicAdd( &gThreadCount, -1 ); +#if !defined(_WIN32) + return NULL; +#endif +} + +// SetThreadCount() may be used to artifically set the number of worker threads +// If the value is 0 (the default) the number of threads will be determined based on +// the number of CPU cores. If it is a unicore machine, then 2 will be used, so +// that we still get some testing for thread safety. +// +// If count < 2 or the CL_TEST_SINGLE_THREADED environment variable is set then the +// code will run single threaded, but will report an error to indicate that the test +// is invalid. This option is intended for debugging purposes only. It is suggested +// as a convention that test apps set the thread count to 1 in response to the -m flag. +// +// SetThreadCount() must be called before the first call to GetThreadCount() or ThreadPool_Do(), +// otherwise the behavior is indefined. +void SetThreadCount( int count ) +{ + if( threadPoolInitErr == CL_SUCCESS ) + { + log_error( "Error: It is illegal to set the thread count after the first call to ThreadPool_Do or GetThreadCount\n" ); + abort(); + } + + gThreadCount = count; +} + +void ThreadPool_Init(void) +{ + cl_int i; + int err; + volatile cl_uint threadID = 0; + + // Check for manual override of multithreading code. We add this for better debuggability. + if( getenv( "CL_TEST_SINGLE_THREADED" ) ) + { + log_error("ERROR: CL_TEST_SINGLE_THREADED is set in the environment. Running single threaded.\n*** TEST IS INVALID! ***\n"); + gThreadCount = 1; + return; + } + + // Figure out how many threads to run -- check first for non-zero to give the implementation the chance + if( 0 == gThreadCount ) + { +#if defined(_MSC_VER) || defined (__MINGW64__) + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL; + DWORD length = 0; + + GetLogicalProcessorInformation( NULL, &length ); + buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION) malloc( length ); + if( buffer != NULL && GetLogicalProcessorInformation( buffer, &length ) == TRUE ) + { + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = buffer; + while( ptr < &buffer[ length / sizeof( SYSTEM_LOGICAL_PROCESSOR_INFORMATION ) ] ) + { + if( ptr->Relationship == RelationProcessorCore ) + { + // Count the number of bits in ProcessorMask (number of logical cores) + ULONG mask = ptr->ProcessorMask; + while( mask ) + { + ++gThreadCount; + mask &= mask - 1; // Remove 1 bit at a time + } + } + ++ptr; + } + free(buffer); + } +#elif defined (__MINGW32__) + { + #warning How about this, instead of hard coding it to 2? + SYSTEM_INFO sysinfo; + GetSystemInfo( &sysinfo ); + gThreadCount = sysinfo.dwNumberOfProcessors; + } +#else // !_WIN32 + gThreadCount = (cl_int) sysconf(_SC_NPROCESSORS_CONF); // Hopefully your system returns logical cpus here, as does MacOS X +#endif // !_WIN32 + + // Multithreaded tests are required to run multithreaded even on unicore systems so as to test thread safety + if( 1 == gThreadCount ) + gThreadCount = 2; + } + + //Allow the app to set thread count to <0 for debugging purposes. This will cause the test to run single threaded. + if( gThreadCount < 2 ) + { + log_error( "ERROR: Running single threaded because thread count < 2. \n*** TEST IS INVALID! ***\n"); + gThreadCount = 1; + return; + } + +#if defined( _WIN32 ) + InitializeCriticalSection( gThreadPoolLock ); + InitializeCriticalSection( cond_lock ); + _InitializeConditionVariable( cond_var ); + caller_event = CreateEvent( NULL, FALSE, FALSE, NULL ); +#elif defined (__GNUC__) + // Dont rely on PTHREAD_MUTEX_INITIALIZER for intialization of a mutex since it might cause problem + // with some flavors of gcc compilers. + pthread_cond_init(&cond_var, NULL); + pthread_mutex_init(&cond_lock ,NULL); + pthread_cond_init(&caller_cond_var, NULL); + pthread_mutex_init(&caller_cond_lock, NULL); + pthread_mutex_init(&gThreadPoolLock, NULL); +#endif + +#if !(defined(__GNUC__) || defined(_MSC_VER) || defined(__MINGW32__)) + pthread_mutex_initialize(gAtomicLock); +#elif defined (__MINGW32__) + InitializeCriticalSection(&gAtomicLock); +#endif + // Make sure the last thread done in the work pool doesn't signal us to wake before we get to the point where we are supposed to wait + // That would cause a deadlock. +#if !defined( _WIN32 ) + if((err = pthread_mutex_lock( &caller_cond_lock) )) + { + log_error("Error %d from pthread_mutex_lock. Unable to block for work to finish. ThreadPool_Init failed.\n", err ); + gThreadCount = 1; + return; + } +#endif // !_WIN32 + + gRunning = gThreadCount; + // init threads + for( i = 0; i < gThreadCount; i++ ) + { +#if defined( _WIN32 ) + uintptr_t handle = _beginthread(ThreadPool_WorkerFunc, 0, (void*) &threadID); + err = ( handle == 0 ); +#else // !_WIN32 + pthread_t tid = 0; + err = pthread_create( &tid, NULL, ThreadPool_WorkerFunc, (void*) &threadID ); +#endif // !_WIN32 + if( err ) + { + log_error( "Error %d launching thread %d\n", err, i ); + threadPoolInitErr = err; + gThreadCount = i; + break; + } + } + + atexit( ThreadPool_Exit ); + +// block until they are done launching. + do + { +#if defined( _WIN32 ) + WaitForSingleObject( caller_event, INFINITE ); +#else // !_WIN32 + if((err = pthread_cond_wait( &caller_cond_var, &caller_cond_lock) )) + { + log_error("Error %d from pthread_cond_wait. Unable to block for work to finish. ThreadPool_Init failed.\n", err ); + pthread_mutex_unlock( &caller_cond_lock); + return; + } +#endif // !_WIN32 + } + while( gRunCount != -gThreadCount ); +#if !defined( _WIN32 ) + if((err = pthread_mutex_unlock( &caller_cond_lock) )) + { + log_error("Error %d from pthread_mutex_unlock. Unable to block for work to finish. ThreadPool_Init failed.\n", err ); + return; + } +#endif // !_WIN32 + + threadPoolInitErr = CL_SUCCESS; +} + +#if defined(_MSC_VER) +static BOOL CALLBACK _ThreadPool_Init(_PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContex) +{ + ThreadPool_Init(); + return TRUE; +} +#endif + +void ThreadPool_Exit(void) +{ + int err, count; + gRunCount = CL_INT_MAX; + +#if defined( __GNUC__ ) + // GCC extension: http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html#Atomic-Builtins + __sync_synchronize(); +#elif defined( _MSC_VER ) + _mm_mfence(); +#else + #warning If this is a weakly ordered memory system, please add a memory barrier here to force this and everything else to memory before we proceed +#endif + + // spin waiting for threads to die + for (count = 0; 0 != gThreadCount && count < 1000; count++) + { +#if defined( _WIN32 ) + _WakeAllConditionVariable( cond_var ); + Sleep(1); +#else // !_WIN32 + if( (err = pthread_cond_broadcast( &cond_var ))) + { + log_error("Error %d from pthread_cond_broadcast. Unable to wake up work threads. ThreadPool_Exit failed.\n", err ); + break; + } + usleep(1000); +#endif // !_WIN32 + } + + if( gThreadCount ) + log_error( "Error: Thread pool timed out after 1 second with %d threads still active.\n", gThreadCount ); + else + log_info( "Thread pool exited in a orderly fashion.\n" ); +} + + +// Blocking API that farms out count jobs to a thread pool. +// It may return with some work undone if func_ptr() returns a non-zero +// result. +// +// This function obviously has its shortcommings. Only one call to ThreadPool_Do +// can be running at a time. It is not intended for general purpose use. +// If clEnqueueNativeKernelFn, out of order queues and a CL_DEVICE_TYPE_CPU were +// all available then it would make more sense to use those features. +cl_int ThreadPool_Do( TPFuncPtr func_ptr, + cl_uint count, + void *userInfo ) +{ + cl_int newErr; + cl_int err = 0; + // Lazily set up our threads +#if defined(_MSC_VER) && (_WIN32_WINNT >= 0x600) + err = !_InitOnceExecuteOnce( &threadpool_init_control, _ThreadPool_Init, NULL, NULL ); +#elif defined (_WIN32) + if (threadpool_init_control == 0) { + #warning This is buggy and race prone. Find a better way. + ThreadPool_Init(); + threadpool_init_control = 1; + } +#else //posix platform + err = pthread_once( &threadpool_init_control, ThreadPool_Init ); + if( err ) + { + log_error("Error %d from pthread_once. Unable to init threads. ThreadPool_Do failed.\n", err ); + return err; + } +#endif + // Single threaded code to handle case where threadpool wasn't allocated or was disabled by environment variable + if( threadPoolInitErr ) + { + cl_uint currentJob = 0; + cl_int result = CL_SUCCESS; + +#if defined(__APPLE__) && defined(__arm__) + // On most platforms which support denorm, default is FTZ off. However, + // on some hardware where the reference is computed, default might be flush denorms to zero e.g. arm. + // This creates issues in result verification. Since spec allows the implementation to either flush or + // not flush denorms to zero, an implementation may choose not be flush i.e. return denorm result whereas + // reference result may be zero (flushed denorm). Hence we need to disable denorm flushing on host side + // where reference is being computed to make sure we get non-flushed reference result. If implementation + // returns flushed result, we correctly take care of that in verification code. + FPU_mode_type oldMode; + DisableFTZ( &oldMode ); +#endif + for( currentJob = 0; currentJob < count; currentJob++ ) + if((result = func_ptr( currentJob, 0, userInfo ))) + { +#if defined(__APPLE__) && defined(__arm__) + // Restore FP state before leaving + RestoreFPState( &oldMode ); +#endif + return result; + } + +#if defined(__APPLE__) && defined(__arm__) + // Restore FP state before leaving + RestoreFPState( &oldMode ); +#endif + + return CL_SUCCESS; + } + + if( count >= MAX_COUNT ) + { + log_error("Error: ThreadPool_Do count %d >= max threadpool count of %d\n", count, MAX_COUNT ); + return -1; + } + + // Enter critical region +#if defined( _WIN32 ) + EnterCriticalSection( gThreadPoolLock ); +#else // !_WIN32 + if( (err = pthread_mutex_lock( &gThreadPoolLock ))) + { + switch (err) + { + case EDEADLK: + log_error("Error EDEADLK returned in ThreadPool_Do(). ThreadPool_Do is not designed to work recursively!\n" ); + break; + case EINVAL: + log_error("Error EINVAL returned in ThreadPool_Do(). How did we end up with an invalid gThreadPoolLock?\n" ); + break; + default: + break; + } + return err; + } +#endif // !_WIN32 + + // Start modifying the job state observable by worker threads +#if defined( _WIN32 ) + EnterCriticalSection( cond_lock ); +#else // !_WIN32 + if((err = pthread_mutex_lock( &cond_lock) )) + { + log_error("Error %d from pthread_mutex_lock. Unable to wake up work threads. ThreadPool_Do failed.\n", err ); + goto exit; + } +#endif // !_WIN32 + + // Make sure the last thread done in the work pool doesn't signal us to wake before we get to the point where we are supposed to wait + // That would cause a deadlock. +#if !defined( _WIN32 ) + if((err = pthread_mutex_lock( &caller_cond_lock) )) + { + log_error("Error %d from pthread_mutex_lock. Unable to block for work to finish. ThreadPool_Do failed.\n", err ); + goto exit; + } +#endif // !_WIN32 + + // Prime the worker threads to get going + jobError = CL_SUCCESS; + gRunCount = gJobCount = count; + gFunc_ptr = func_ptr; + gUserInfo = userInfo; + +#if defined( _WIN32 ) + _WakeAllConditionVariable( cond_var ); + LeaveCriticalSection( cond_lock ); +#else // !_WIN32 + if( (err = pthread_cond_broadcast( &cond_var ))) + { + log_error("Error %d from pthread_cond_broadcast. Unable to wake up work threads. ThreadPool_Do failed.\n", err ); + goto exit; + } + if((err = pthread_mutex_unlock( &cond_lock) )) + { + log_error("Error %d from pthread_mutex_unlock. Unable to wake up work threads. ThreadPool_Do failed.\n", err ); + goto exit; + } +#endif // !_WIN32 + +// block until they are done. It would be slightly more efficient to do some of the work here though. + do + { +#if defined( _WIN32 ) + WaitForSingleObject( caller_event, INFINITE ); +#else // !_WIN32 + if((err = pthread_cond_wait( &caller_cond_var, &caller_cond_lock) )) + { + log_error("Error %d from pthread_cond_wait. Unable to block for work to finish. ThreadPool_Do failed.\n", err ); + pthread_mutex_unlock( &caller_cond_lock); + goto exit; + } +#endif // !_WIN32 + } + while( gRunning ); +#if !defined(_WIN32) + if((err = pthread_mutex_unlock( &caller_cond_lock) )) + { + log_error("Error %d from pthread_mutex_unlock. Unable to block for work to finish. ThreadPool_Do failed.\n", err ); + goto exit; + } +#endif // !_WIN32 + + err = jobError; + +exit: + // exit critical region +#if defined( _WIN32 ) + LeaveCriticalSection( gThreadPoolLock ); +#else // !_WIN32 + newErr = pthread_mutex_unlock( &gThreadPoolLock ); + if( newErr) + { + log_error("Error %d from pthread_mutex_unlock. Unable to exit critical region. ThreadPool_Do failed.\n", newErr ); + return err; + } +#endif // !_WIN32 + + return err; +} + +cl_uint GetThreadCount( void ) +{ + // Lazily set up our threads +#if defined(_MSC_VER) && (_WIN32_WINNT >= 0x600) + cl_int err = !_InitOnceExecuteOnce( &threadpool_init_control, _ThreadPool_Init, NULL, NULL ); +#elif defined (_WIN32) + if (threadpool_init_control == 0) { + #warning This is buggy and race prone. Find a better way. + ThreadPool_Init(); + threadpool_init_control = 1; + } +#else + cl_int err = pthread_once( &threadpool_init_control, ThreadPool_Init ); + if( err ) + { + log_error("Error %d from pthread_once. Unable to init threads. ThreadPool_Do failed.\n", err ); + return err; + } +#endif // !_WIN32 + + if( gThreadCount < 1 ) + return 1; + + return gThreadCount; +} + +#else + +#ifndef MY_OS_REALLY_REALLY_DOESNT_SUPPORT_THREADS + #error ThreadPool implementation has not been multithreaded for this operating system. You must multithread this section. +#endif +// +// We require multithreading in parts of the test as a means of simultaneously testing reentrancy requirements +// of OpenCL API, while also checking +// +// A sample single threaded implementation follows, for documentation / bootstrapping purposes. +// It is not okay to use this for conformance testing!!! +// +// Exception: If your operating system does not support multithreaded execution of any kind, then you may use this code. +// + +cl_int ThreadPool_AtomicAdd( volatile cl_int *a, cl_int b ) +{ + cl_uint r = *a; + + // since this fallback code path is not multithreaded, we just do a regular add here + // If your operating system supports memory-barrier-atomics, use those here + *a = r + b; + + return r; +} + +// Blocking API that farms out count jobs to a thread pool. +// It may return with some work undone if func_ptr() returns a non-zero +// result. +cl_int ThreadPool_Do( TPFuncPtr func_ptr, + cl_uint count, + void *userInfo ) +{ + cl_uint currentJob = 0; + cl_int result = CL_SUCCESS; + +#ifndef MY_OS_REALLY_REALLY_DOESNT_SUPPORT_THREADS + // THIS FUNCTION IS NOT INTENDED FOR USE!! + log_error( "ERROR: Test must be multithreaded!\n" ); + exit(-1); +#else + static int spewCount = 0; + + if( 0 == spewCount ) + { + log_info( "\nWARNING: The operating system is claimed not to support threads of any sort. Running single threaded.\n" ); + spewCount = 1; + } +#endif + +// The multithreaded code should mimic this behavior: + for( currentJob = 0; currentJob < count; currentJob++ ) + if((result = func_ptr( currentJob, 0, userInfo ))) + return result; + + return CL_SUCCESS; +} + +cl_uint GetThreadCount( void ) +{ + return 1; +} + +void SetThreadCount( int count ) +{ + if( count > 1 ) + log_info( "WARNING: SetThreadCount(%d) ignored\n", count ); +} + +#endif diff --git a/test_conformance/compatibility/test_common/harness/ThreadPool.h b/test_conformance/compatibility/test_common/harness/ThreadPool.h new file mode 100644 index 00000000..7c392306 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/ThreadPool.h @@ -0,0 +1,76 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef THREAD_POOL_H +#define THREAD_POOL_H + +#if defined( __APPLE__ ) + #include +#else + #include +#endif + +#if defined(__cplusplus) + extern "C" { +#endif + +// +// An atomic add operator +cl_int ThreadPool_AtomicAdd( volatile cl_int *a, cl_int b ); // returns old value + +// Your function prototype +// +// A function pointer to the function you want to execute in a multithreaded context. No +// synchronization primitives are provided, other than the atomic add above. You may not +// call ThreadPool_Do from your function. ThreadPool_AtomicAdd() and GetThreadCount() should +// work, however. +// +// job ids and thread ids are 0 based. If number of jobs or threads was 8, they will numbered be 0 through 7. +// Note that while every job will be run, it is not guaranteed that every thread will wake up before +// the work is done. +typedef cl_int (*TPFuncPtr)( cl_uint /*job_id*/, cl_uint /* thread_id */, void *userInfo ); + +// returns first non-zero result from func_ptr, or CL_SUCCESS if all are zero. +// Some workitems may not run if a non-zero result is returned from func_ptr(). +// This function may not be called from a TPFuncPtr. +cl_int ThreadPool_Do( TPFuncPtr func_ptr, + cl_uint count, + void *userInfo ); + +// Returns the number of worker threads that underlie the threadpool. The value passed +// as the TPFuncPtrs thread_id will be between 0 and this value less one, inclusive. +// This is safe to call from a TPFuncPtr. +cl_uint GetThreadCount( void ); + +// SetThreadCount() may be used to artifically set the number of worker threads +// If the value is 0 (the default) the number of threads will be determined based on +// the number of CPU cores. If it is a unicore machine, then 2 will be used, so +// that we still get some testing for thread safety. +// +// If count < 2 or the CL_TEST_SINGLE_THREADED environment variable is set then the +// code will run single threaded, but will report an error to indicate that the test +// is invalid. This option is intended for debugging purposes only. It is suggested +// as a convention that test apps set the thread count to 1 in response to the -m flag. +// +// SetThreadCount() must be called before the first call to GetThreadCount() or ThreadPool_Do(), +// otherwise the behavior is indefined. It may not be called from a TPFuncPtr. +void SetThreadCount( int count ); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* THREAD_POOL_H */ diff --git a/test_conformance/compatibility/test_common/harness/clImageHelper.h b/test_conformance/compatibility/test_common/harness/clImageHelper.h new file mode 100644 index 00000000..8537ddcd --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/clImageHelper.h @@ -0,0 +1,253 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef test_conformance_clImageHelper_h +#define test_conformance_clImageHelper_h + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include "errorHelpers.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + // helper function to replace clCreateImage2D , to make the existing code use + // the functions of version 1.2 and veriosn 1.1 respectively + + inline cl_mem create_image_2d (cl_context context, + cl_mem_flags flags, + const cl_image_format *image_format, + size_t image_width, + size_t image_height, + size_t image_row_pitch, + void *host_ptr, + cl_int *errcode_ret) + { + cl_mem mImage = NULL; + +#ifdef CL_VERSION_1_2 + cl_image_desc image_desc_dest; + image_desc_dest.image_type = CL_MEM_OBJECT_IMAGE2D;; + image_desc_dest.image_width = image_width; + image_desc_dest.image_height = image_height; + image_desc_dest.image_depth= 0;// not usedfor 2d + image_desc_dest.image_array_size = 0;// not used for 2d + image_desc_dest.image_row_pitch = image_row_pitch; + image_desc_dest.image_slice_pitch = 0; + image_desc_dest.num_mip_levels = 0; + image_desc_dest.num_samples = 0; + image_desc_dest.buffer = NULL;// no image type of CL_MEM_OBJECT_IMAGE1D_BUFFER in CL_VERSION_1_1, so always is NULL + mImage = clCreateImage( context, flags, image_format, &image_desc_dest, host_ptr, errcode_ret ); + if (errcode_ret && (*errcode_ret)) { + // Log an info message and rely on the calling function to produce an error + // if necessary. + log_info("clCreateImage failed (%d)\n", *errcode_ret); + } + +#else + mImage = clCreateImage2D( context, flags, image_format, image_width, image_height, image_row_pitch, host_ptr, errcode_ret ); + if (errcode_ret && (*errcode_ret)) { + // Log an info message and rely on the calling function to produce an error + // if necessary. + log_info("clCreateImage2D failed (%d)\n", *errcode_ret); + } +#endif + + return mImage; + } + + inline cl_mem create_image_3d (cl_context context, + cl_mem_flags flags, + const cl_image_format *image_format, + size_t image_width, + size_t image_height, + size_t image_depth, + size_t image_row_pitch, + size_t image_slice_pitch, + void *host_ptr, + cl_int *errcode_ret) + { + cl_mem mImage; + +#ifdef CL_VERSION_1_2 + cl_image_desc image_desc; + image_desc.image_type = CL_MEM_OBJECT_IMAGE3D; + image_desc.image_width = image_width; + image_desc.image_height = image_height; + image_desc.image_depth = image_depth; + image_desc.image_array_size = 0;// not used for one image + image_desc.image_row_pitch = image_row_pitch; + image_desc.image_slice_pitch = image_slice_pitch; + image_desc.num_mip_levels = 0; + image_desc.num_samples = 0; + image_desc.buffer = NULL; // no image type of CL_MEM_OBJECT_IMAGE1D_BUFFER in CL_VERSION_1_1, so always is NULL + mImage = clCreateImage( context, + flags, + image_format, + &image_desc, + host_ptr, + errcode_ret ); + if (errcode_ret && (*errcode_ret)) { + // Log an info message and rely on the calling function to produce an error + // if necessary. + log_info("clCreateImage failed (%d)\n", *errcode_ret); + } + +#else + mImage = clCreateImage3D( context, + flags, image_format, + image_width, + image_height, + image_depth, + image_row_pitch, + image_slice_pitch, + host_ptr, + errcode_ret ); + if (errcode_ret && (*errcode_ret)) { + // Log an info message and rely on the calling function to produce an error + // if necessary. + log_info("clCreateImage3D failed (%d)\n", *errcode_ret); + } +#endif + + return mImage; + } + + inline cl_mem create_image_2d_array (cl_context context, + cl_mem_flags flags, + const cl_image_format *image_format, + size_t image_width, + size_t image_height, + size_t image_array_size, + size_t image_row_pitch, + size_t image_slice_pitch, + void *host_ptr, + cl_int *errcode_ret) + { + cl_mem mImage; + + cl_image_desc image_desc; + image_desc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + image_desc.image_width = image_width; + image_desc.image_height = image_height; + image_desc.image_depth = 1; + image_desc.image_array_size = image_array_size; + image_desc.image_row_pitch = image_row_pitch; + image_desc.image_slice_pitch = image_slice_pitch; + image_desc.num_mip_levels = 0; + image_desc.num_samples = 0; + image_desc.buffer = NULL; + mImage = clCreateImage( context, + flags, + image_format, + &image_desc, + host_ptr, + errcode_ret ); + if (errcode_ret && (*errcode_ret)) { + // Log an info message and rely on the calling function to produce an error + // if necessary. + log_info("clCreateImage failed (%d)\n", *errcode_ret); + } + + return mImage; + } + + inline cl_mem create_image_1d_array (cl_context context, + cl_mem_flags flags, + const cl_image_format *image_format, + size_t image_width, + size_t image_array_size, + size_t image_row_pitch, + size_t image_slice_pitch, + void *host_ptr, + cl_int *errcode_ret) + { + cl_mem mImage; + + cl_image_desc image_desc; + image_desc.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + image_desc.image_width = image_width; + image_desc.image_height = 1; + image_desc.image_depth = 1; + image_desc.image_array_size = image_array_size; + image_desc.image_row_pitch = image_row_pitch; + image_desc.image_slice_pitch = image_slice_pitch; + image_desc.num_mip_levels = 0; + image_desc.num_samples = 0; + image_desc.buffer = NULL; + mImage = clCreateImage( context, + flags, + image_format, + &image_desc, + host_ptr, + errcode_ret ); + if (errcode_ret && (*errcode_ret)) { + // Log an info message and rely on the calling function to produce an error + // if necessary. + log_info("clCreateImage failed (%d)\n", *errcode_ret); + } + + return mImage; + } + + inline cl_mem create_image_1d (cl_context context, + cl_mem_flags flags, + const cl_image_format *image_format, + size_t image_width, + size_t image_row_pitch, + void *host_ptr, + cl_mem buffer, + cl_int *errcode_ret) + { + cl_mem mImage; + + cl_image_desc image_desc; + image_desc.image_type = buffer ? CL_MEM_OBJECT_IMAGE1D_BUFFER: CL_MEM_OBJECT_IMAGE1D; + image_desc.image_width = image_width; + image_desc.image_height = 1; + image_desc.image_depth = 1; + image_desc.image_row_pitch = image_row_pitch; + image_desc.image_slice_pitch = 0; + image_desc.num_mip_levels = 0; + image_desc.num_samples = 0; + image_desc.buffer = buffer; + mImage = clCreateImage( context, + flags, + image_format, + &image_desc, + host_ptr, + errcode_ret ); + if (errcode_ret && (*errcode_ret)) { + // Log an info message and rely on the calling function to produce an error + // if necessary. + log_info("clCreateImage failed (%d)\n", *errcode_ret); + } + + return mImage; + } + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test_conformance/compatibility/test_common/harness/compat.h b/test_conformance/compatibility/test_common/harness/compat.h new file mode 100644 index 00000000..22119c46 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/compat.h @@ -0,0 +1,216 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _COMPAT_H_ +#define _COMPAT_H_ + +#if defined(_WIN32) && defined (_MSC_VER) + +#include +#include +#include +#include +#include +#include + +#define MAKE_HEX_FLOAT(x,y,z) ((float)ldexp( (float)(y), z)) +#define MAKE_HEX_DOUBLE(x,y,z) ldexp( (double)(y), z) +#define MAKE_HEX_LONG(x,y,z) ((long double) ldexp( (long double)(y), z)) + +#define isfinite(x) _finite(x) + +#if !defined(__cplusplus) +typedef char bool; +#define inline + +#else +extern "C" { +#endif + +typedef unsigned char uint8_t; +typedef char int8_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned long long uint64_t; +typedef long long int64_t; + +#define MAXPATHLEN MAX_PATH + +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; + + +#define INFINITY (FLT_MAX + FLT_MAX) +//#define NAN (INFINITY | 1) +//const static int PINFBITPATT_SP32 = INFINITY; + +#ifndef M_PI + #define M_PI 3.14159265358979323846264338327950288 +#endif + + +#define isnan( x ) ((x) != (x)) +#define isinf( _x) ((_x) == INFINITY || (_x) == -INFINITY) + +double rint( double x); +float rintf( float x); +long double rintl( long double x); + +float cbrtf( float ); +double cbrt( double ); + +int ilogb( double x); +int ilogbf (float x); +int ilogbl(long double x); + +double fmax(double x, double y); +double fmin(double x, double y); +float fmaxf( float x, float y ); +float fminf(float x, float y); + +double log2(double x); +long double log2l(long double x); + +double exp2(double x); +long double exp2l(long double x); + +double fdim(double x, double y); +float fdimf(float x, float y); +long double fdiml(long double x, long double y); + +double remquo( double x, double y, int *quo); +float remquof( float x, float y, int *quo); +long double remquol( long double x, long double y, int *quo); + +long double scalblnl(long double x, long n); + +inline long long +llabs(long long __x) { return __x >= 0 ? __x : -__x; } + + +// end of math functions + +uint64_t ReadTime( void ); +double SubtractTime( uint64_t endTime, uint64_t startTime ); + +#define sleep(X) Sleep(1000*X) +// snprintf added in _MSC_VER == 1900 (Visual Studio 2015) +#if _MSC_VER < 1900 + #define snprintf sprintf_s +#endif +//#define hypotl _hypot + +float make_nan(); +float nanf( const char* str); +double nan( const char* str); +long double nanl( const char* str); + +//#if defined USE_BOOST +//#include +//double hypot(double x, double y); +float hypotf(float x, float y); +long double hypotl(long double x, long double y) ; +double lgamma(double x); +float lgammaf(float x); + +double trunc(double x); +float truncf(float x); + +double log1p(double x); +float log1pf(float x); +long double log1pl(long double x); + +double copysign(double x, double y); +float copysignf(float x, float y); +long double copysignl(long double x, long double y); + +long lround(double x); +long lroundf(float x); +//long lroundl(long double x) + +double round(double x); +float roundf(float x); +long double roundl(long double x); + +// Added in _MSC_VER == 1800 (Visual Studio 2013) +#if _MSC_VER < 1800 + int signbit(double x); +#endif +int signbitf(float x); + +//bool signbitl(long double x) { return boost::math::tr1::signbit(x); } +//#endif // USE_BOOST + +long int lrint (double flt); +long int lrintf (float flt); + + +float int2float (int32_t ix); +int32_t float2int (float fx); + +/** Returns the number of leading 0-bits in x, + starting at the most significant bit position. + If x is 0, the result is undefined. +*/ +int __builtin_clz(unsigned int pattern); + + +static const double zero= 0.00000000000000000000e+00; +#define NAN (INFINITY - INFINITY) +#define HUGE_VALF (float)HUGE_VAL + +int usleep(int usec); + +// reimplement fenv.h because windows doesn't have it +#define FE_INEXACT 0x0020 +#define FE_UNDERFLOW 0x0010 +#define FE_OVERFLOW 0x0008 +#define FE_DIVBYZERO 0x0004 +#define FE_INVALID 0x0001 +#define FE_ALL_EXCEPT 0x003D + +int fetestexcept(int excepts); +int feclearexcept(int excepts); + +#ifdef __cplusplus +} +#endif + +#else // !((defined(_WIN32) && defined(_MSC_VER) +#if defined(__MINGW32__) +#include +#define sleep(X) Sleep(1000*X) + +#endif +#if defined(__linux__) || defined(__MINGW32__) || defined(__APPLE__) +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif +#include +#include +#include +#include +#endif +#define MAKE_HEX_FLOAT(x,y,z) x +#define MAKE_HEX_DOUBLE(x,y,z) x +#define MAKE_HEX_LONG(x,y,z) x + +#endif // !((defined(_WIN32) && defined(_MSC_VER) + + +#endif // _COMPAT_H_ diff --git a/test_conformance/compatibility/test_common/harness/conversions.c b/test_conformance/compatibility/test_common/harness/conversions.c new file mode 100644 index 00000000..72fd8cb3 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/conversions.c @@ -0,0 +1,1198 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "conversions.h" +#include +#include +#include +#include "mt19937.h" +#include "compat.h" + +#if defined( __SSE__ ) || defined (_MSC_VER) + #include +#endif +#if defined( __SSE2__ ) || defined (_MSC_VER) + #include +#endif + +void print_type_to_string(ExplicitType type, void *data, char* string) { + switch (type) { + case kBool: + if (*(char*)data) + sprintf(string, "true"); + else + sprintf(string, "false"); + return; + case kChar: + sprintf(string, "%d", (int)*((cl_char*)data)); + return; + case kUChar: + case kUnsignedChar: + sprintf(string, "%u", (int)*((cl_uchar*)data)); + return; + case kShort: + sprintf(string, "%d", (int)*((cl_short*)data)); + return; + case kUShort: + case kUnsignedShort: + sprintf(string, "%u", (int)*((cl_ushort*)data)); + return; + case kInt: + sprintf(string, "%d", *((cl_int*)data)); + return; + case kUInt: + case kUnsignedInt: + sprintf(string, "%u", *((cl_uint*)data)); + return; + case kLong: + sprintf(string, "%lld", *((cl_long*)data)); + return; + case kULong: + case kUnsignedLong: + sprintf(string, "%llu", *((cl_ulong*)data)); + return; + case kFloat: + sprintf(string, "%f", *((cl_float*)data)); + return; + case kHalf: + sprintf(string, "half"); + return; + case kDouble: + sprintf(string, "%g", *((cl_double*)data)); + return; + default: + sprintf(string, "INVALID"); + return; + } + +} + +size_t get_explicit_type_size( ExplicitType type ) +{ + /* Quick method to avoid branching: make sure the following array matches the Enum order */ + static size_t sExplicitTypeSizes[] = { + sizeof( cl_bool ), + sizeof( cl_char ), + sizeof( cl_uchar ), + sizeof( cl_uchar ), + sizeof( cl_short ), + sizeof( cl_ushort ), + sizeof( cl_ushort ), + sizeof( cl_int ), + sizeof( cl_uint ), + sizeof( cl_uint ), + sizeof( cl_long ), + sizeof( cl_ulong ), + sizeof( cl_ulong ), + sizeof( cl_float ), + sizeof( cl_half ), + sizeof( cl_double ) + }; + + return sExplicitTypeSizes[ type ]; +} + +const char * get_explicit_type_name( ExplicitType type ) +{ + /* Quick method to avoid branching: make sure the following array matches the Enum order */ + static const char *sExplicitTypeNames[] = { "bool", "char", "uchar", "unsigned char", "short", "ushort", "unsigned short", "int", + "uint", "unsigned int", "long", "ulong", "unsigned long", "float", "half", "double" }; + + return sExplicitTypeNames[ type ]; +} + +static long lrintf_clamped( float f ); +static long lrintf_clamped( float f ) +{ + static const float magic[2] = { MAKE_HEX_FLOAT( 0x1.0p23f, 0x1, 23), - MAKE_HEX_FLOAT( 0x1.0p23f, 0x1, 23) }; + + if( f >= -(float) LONG_MIN ) + return LONG_MAX; + + if( f <= (float) LONG_MIN ) + return LONG_MIN; + + // Round fractional values to integer in round towards nearest mode + if( fabsf(f) < MAKE_HEX_FLOAT( 0x1.0p23f, 0x1, 23 ) ) + { + volatile float x = f; + float magicVal = magic[ f < 0 ]; + +#if defined( __SSE__ ) || defined (_WIN32) + // Defeat x87 based arithmetic, which cant do FTZ, and will round this incorrectly + __m128 v = _mm_set_ss( x ); + __m128 m = _mm_set_ss( magicVal ); + v = _mm_add_ss( v, m ); + v = _mm_sub_ss( v, m ); + _mm_store_ss( (float*) &x, v ); +#else + x += magicVal; + x -= magicVal; +#endif + f = x; + } + + return (long) f; +} + +static long lrint_clamped( double f ); +static long lrint_clamped( double f ) +{ + static const double magic[2] = { MAKE_HEX_DOUBLE(0x1.0p52, 0x1LL, 52), MAKE_HEX_DOUBLE(-0x1.0p52, -0x1LL, 52) }; + + if( sizeof( long ) > 4 ) + { + if( f >= -(double) LONG_MIN ) + return LONG_MAX; + } + else + { + if( f >= LONG_MAX ) + return LONG_MAX; + } + + if( f <= (double) LONG_MIN ) + return LONG_MIN; + + // Round fractional values to integer in round towards nearest mode + if( fabs(f) < MAKE_HEX_DOUBLE(0x1.0p52, 0x1LL, 52) ) + { + volatile double x = f; + double magicVal = magic[ f < 0 ]; +#if defined( __SSE2__ ) || (defined (_MSC_VER)) + // Defeat x87 based arithmetic, which cant do FTZ, and will round this incorrectly + __m128d v = _mm_set_sd( x ); + __m128d m = _mm_set_sd( magicVal ); + v = _mm_add_sd( v, m ); + v = _mm_sub_sd( v, m ); + _mm_store_sd( (double*) &x, v ); +#else + x += magicVal; + x -= magicVal; +#endif + f = x; + } + + return (long) f; +} + + +typedef cl_long Long; +typedef cl_ulong ULong; + +static ULong sUpperLimits[ kNumExplicitTypes ] = + { + 0, + 127, 255, 255, + 32767, 65535, 65535, + 0x7fffffffLL, 0xffffffffLL, 0xffffffffLL, + 0x7fffffffffffffffLL, 0xffffffffffffffffLL, 0xffffffffffffffffLL, + 0, 0 }; // Last two values aren't stored here + +static Long sLowerLimits[ kNumExplicitTypes ] = + { + -1, + -128, 0, 0, + -32768, 0, 0, + 0xffffffff80000000LL, 0, 0, + 0x8000000000000000LL, 0, 0, + 0, 0 }; // Last two values aren't stored here + +#define BOOL_CASE(inType) \ + case kBool: \ + boolPtr = (bool *)outRaw; \ + *boolPtr = ( *inType##Ptr ) != 0 ? true : false; \ + break; + +#define SIMPLE_CAST_CASE(inType,outEnum,outType) \ + case outEnum: \ + outType##Ptr = (outType *)outRaw; \ + *outType##Ptr = (outType)(*inType##Ptr); \ + break; + +// Sadly, the ULong downcasting cases need a separate #define to get rid of signed/unsigned comparison warnings +#define DOWN_CAST_CASE(inType,outEnum,outType,sat) \ + case outEnum: \ + outType##Ptr = (outType *)outRaw; \ + if( sat ) \ + { \ + if( ( sLowerLimits[outEnum] < 0 && *inType##Ptr > (Long)sUpperLimits[outEnum] ) || ( sLowerLimits[outEnum] == 0 && (ULong)*inType##Ptr > sUpperLimits[outEnum] ) )\ + *outType##Ptr = (outType)sUpperLimits[outEnum];\ + else if( *inType##Ptr < sLowerLimits[outEnum] )\ + *outType##Ptr = (outType)sLowerLimits[outEnum]; \ + else \ + *outType##Ptr = (outType)*inType##Ptr; \ + } else { \ + *outType##Ptr = (outType)( *inType##Ptr & ( 0xffffffffffffffffLL >> ( 64 - ( sizeof( outType ) * 8 ) ) ) ); \ + } \ + break; + +#define U_DOWN_CAST_CASE(inType,outEnum,outType,sat) \ + case outEnum: \ + outType##Ptr = (outType *)outRaw; \ + if( sat ) \ + { \ + if( (ULong)*inType##Ptr > sUpperLimits[outEnum] )\ + *outType##Ptr = (outType)sUpperLimits[outEnum];\ + else \ + *outType##Ptr = (outType)*inType##Ptr; \ + } else { \ + *outType##Ptr = (outType)( *inType##Ptr & ( 0xffffffffffffffffLL >> ( 64 - ( sizeof( outType ) * 8 ) ) ) ); \ + } \ + break; + +#define TO_FLOAT_CASE(inType) \ + case kFloat: \ + floatPtr = (float *)outRaw; \ + *floatPtr = (float)(*inType##Ptr); \ + break; +#define TO_DOUBLE_CASE(inType) \ + case kDouble: \ + doublePtr = (double *)outRaw; \ + *doublePtr = (double)(*inType##Ptr); \ + break; + + +/* Note: we use lrintf here to force the rounding instead of whatever the processor's current rounding mode is */ +#define FLOAT_ROUND_TO_NEAREST_CASE(outEnum,outType) \ + case outEnum: \ + outType##Ptr = (outType *)outRaw; \ + *outType##Ptr = (outType)lrintf_clamped( *floatPtr ); \ + break; + +#define FLOAT_ROUND_CASE(outEnum,outType,rounding,sat) \ + case outEnum: \ + { \ + outType##Ptr = (outType *)outRaw; \ + /* Get the tens digit */ \ + Long wholeValue = (Long)*floatPtr;\ + float largeRemainder = ( *floatPtr - (float)wholeValue ) * 10.f; \ + /* What do we do based on that? */ \ + if( rounding == kRoundToEven ) \ + { \ + if( wholeValue & 1LL ) /*between 1 and 1.99 */ \ + wholeValue += 1LL; /* round up to even */ \ + } \ + else if( rounding == kRoundToZero ) \ + { \ + /* Nothing to do, round-to-zero is what C casting does */ \ + } \ + else if( rounding == kRoundToPosInf ) \ + { \ + /* Only positive numbers are wrong */ \ + if( largeRemainder != 0.f && wholeValue >= 0 ) \ + wholeValue++; \ + } \ + else if( rounding == kRoundToNegInf ) \ + { \ + /* Only negative numbers are off */ \ + if( largeRemainder != 0.f && wholeValue < 0 ) \ + wholeValue--; \ + } \ + else \ + { /* Default is round-to-nearest */ \ + wholeValue = (Long)lrintf_clamped( *floatPtr ); \ + } \ + /* Now apply saturation rules */ \ + if( sat ) \ + { \ + if( ( sLowerLimits[outEnum] < 0 && wholeValue > (Long)sUpperLimits[outEnum] ) || ( sLowerLimits[outEnum] == 0 && (ULong)wholeValue > sUpperLimits[outEnum] ) )\ + *outType##Ptr = (outType)sUpperLimits[outEnum];\ + else if( wholeValue < sLowerLimits[outEnum] )\ + *outType##Ptr = (outType)sLowerLimits[outEnum]; \ + else \ + *outType##Ptr = (outType)wholeValue; \ + } else { \ + *outType##Ptr = (outType)( wholeValue & ( 0xffffffffffffffffLL >> ( 64 - ( sizeof( outType ) * 8 ) ) ) ); \ + } \ + } \ + break; + +#define DOUBLE_ROUND_CASE(outEnum,outType,rounding,sat) \ + case outEnum: \ + { \ + outType##Ptr = (outType *)outRaw; \ + /* Get the tens digit */ \ + Long wholeValue = (Long)*doublePtr;\ + double largeRemainder = ( *doublePtr - (double)wholeValue ) * 10.0; \ + /* What do we do based on that? */ \ + if( rounding == kRoundToEven ) \ + { \ + if( wholeValue & 1LL ) /*between 1 and 1.99 */ \ + wholeValue += 1LL; /* round up to even */ \ + } \ + else if( rounding == kRoundToZero ) \ + { \ + /* Nothing to do, round-to-zero is what C casting does */ \ + } \ + else if( rounding == kRoundToPosInf ) \ + { \ + /* Only positive numbers are wrong */ \ + if( largeRemainder != 0.0 && wholeValue >= 0 ) \ + wholeValue++; \ + } \ + else if( rounding == kRoundToNegInf ) \ + { \ + /* Only negative numbers are off */ \ + if( largeRemainder != 0.0 && wholeValue < 0 ) \ + wholeValue--; \ + } \ + else \ + { /* Default is round-to-nearest */ \ + wholeValue = (Long)lrint_clamped( *doublePtr ); \ + } \ + /* Now apply saturation rules */ \ + if( sat ) \ + { \ + if( ( sLowerLimits[outEnum] < 0 && wholeValue > (Long)sUpperLimits[outEnum] ) || ( sLowerLimits[outEnum] == 0 && (ULong)wholeValue > sUpperLimits[outEnum] ) )\ + *outType##Ptr = (outType)sUpperLimits[outEnum];\ + else if( wholeValue < sLowerLimits[outEnum] )\ + *outType##Ptr = (outType)sLowerLimits[outEnum]; \ + else \ + *outType##Ptr = (outType)wholeValue; \ + } else { \ + *outType##Ptr = (outType)( wholeValue & ( 0xffffffffffffffffLL >> ( 64 - ( sizeof( outType ) * 8 ) ) ) ); \ + } \ + } \ + break; + +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; + +void convert_explicit_value( void *inRaw, void *outRaw, ExplicitType inType, bool saturate, RoundingType roundType, ExplicitType outType ) +{ + bool *boolPtr; + char *charPtr; + uchar *ucharPtr; + short *shortPtr; + ushort *ushortPtr; + int *intPtr; + uint *uintPtr; + Long *LongPtr; + ULong *ULongPtr; + float *floatPtr; + double *doublePtr; + + + switch( inType ) + { + case kBool: + boolPtr = (bool *)inRaw; + switch( outType ) + { + case kBool: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + case kChar: + case kUChar: + case kUnsignedChar: + case kShort: + case kUShort: + case kUnsignedShort: + case kInt: + case kUInt: + case kUnsignedInt: + case kLong: + case kULong: + case kUnsignedLong: + memset( outRaw, *boolPtr ? 0xff : 0, get_explicit_type_size( outType ) ); + break; + + case kFloat: + floatPtr = (float *)outRaw; + *floatPtr = ( *boolPtr ) ? -1.f : 0.f; + break; + case kDouble: + doublePtr = (double *)outRaw; + *doublePtr = ( *boolPtr ) ? -1.0 : 0.0; + break; + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kChar: + charPtr = (char *)inRaw; + switch( outType ) + { + BOOL_CASE(char) + + case kChar: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(char,kUChar,uchar,saturate) + SIMPLE_CAST_CASE(char,kUnsignedChar,uchar) + SIMPLE_CAST_CASE(char,kShort,short) + SIMPLE_CAST_CASE(char,kUShort,ushort) + SIMPLE_CAST_CASE(char,kUnsignedShort,ushort) + SIMPLE_CAST_CASE(char,kInt,int) + SIMPLE_CAST_CASE(char,kUInt,uint) + SIMPLE_CAST_CASE(char,kUnsignedInt,uint) + SIMPLE_CAST_CASE(char,kLong,Long) + SIMPLE_CAST_CASE(char,kULong,ULong) + SIMPLE_CAST_CASE(char,kUnsignedLong,ULong) + + TO_FLOAT_CASE(char) + TO_DOUBLE_CASE(char) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kUChar: + ucharPtr = (uchar *)inRaw; + switch( outType ) + { + BOOL_CASE(uchar) + + case kUChar: + case kUnsignedChar: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(uchar,kChar,char,saturate) + SIMPLE_CAST_CASE(uchar,kShort,short) + SIMPLE_CAST_CASE(uchar,kUShort,ushort) + SIMPLE_CAST_CASE(uchar,kUnsignedShort,ushort) + SIMPLE_CAST_CASE(uchar,kInt,int) + SIMPLE_CAST_CASE(uchar,kUInt,uint) + SIMPLE_CAST_CASE(uchar,kUnsignedInt,uint) + SIMPLE_CAST_CASE(uchar,kLong,Long) + SIMPLE_CAST_CASE(uchar,kULong,ULong) + SIMPLE_CAST_CASE(uchar,kUnsignedLong,ULong) + + TO_FLOAT_CASE(uchar) + TO_DOUBLE_CASE(uchar) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kUnsignedChar: + ucharPtr = (uchar *)inRaw; + switch( outType ) + { + BOOL_CASE(uchar) + + case kUChar: + case kUnsignedChar: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(uchar,kChar,char,saturate) + SIMPLE_CAST_CASE(uchar,kShort,short) + SIMPLE_CAST_CASE(uchar,kUShort,ushort) + SIMPLE_CAST_CASE(uchar,kUnsignedShort,ushort) + SIMPLE_CAST_CASE(uchar,kInt,int) + SIMPLE_CAST_CASE(uchar,kUInt,uint) + SIMPLE_CAST_CASE(uchar,kUnsignedInt,uint) + SIMPLE_CAST_CASE(uchar,kLong,Long) + SIMPLE_CAST_CASE(uchar,kULong,ULong) + SIMPLE_CAST_CASE(uchar,kUnsignedLong,ULong) + + TO_FLOAT_CASE(uchar) + TO_DOUBLE_CASE(uchar) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kShort: + shortPtr = (short *)inRaw; + switch( outType ) + { + BOOL_CASE(short) + + case kShort: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(short,kChar,char,saturate) + DOWN_CAST_CASE(short,kUChar,uchar,saturate) + DOWN_CAST_CASE(short,kUnsignedChar,uchar,saturate) + DOWN_CAST_CASE(short,kUShort,ushort,saturate) + DOWN_CAST_CASE(short,kUnsignedShort,ushort,saturate) + SIMPLE_CAST_CASE(short,kInt,int) + SIMPLE_CAST_CASE(short,kUInt,uint) + SIMPLE_CAST_CASE(short,kUnsignedInt,uint) + SIMPLE_CAST_CASE(short,kLong,Long) + SIMPLE_CAST_CASE(short,kULong,ULong) + SIMPLE_CAST_CASE(short,kUnsignedLong,ULong) + + TO_FLOAT_CASE(short) + TO_DOUBLE_CASE(short) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kUShort: + ushortPtr = (ushort *)inRaw; + switch( outType ) + { + BOOL_CASE(ushort) + + case kUShort: + case kUnsignedShort: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(ushort,kChar,char,saturate) + DOWN_CAST_CASE(ushort,kUChar,uchar,saturate) + DOWN_CAST_CASE(ushort,kUnsignedChar,uchar,saturate) + DOWN_CAST_CASE(ushort,kShort,short,saturate) + SIMPLE_CAST_CASE(ushort,kInt,int) + SIMPLE_CAST_CASE(ushort,kUInt,uint) + SIMPLE_CAST_CASE(ushort,kUnsignedInt,uint) + SIMPLE_CAST_CASE(ushort,kLong,Long) + SIMPLE_CAST_CASE(ushort,kULong,ULong) + SIMPLE_CAST_CASE(ushort,kUnsignedLong,ULong) + + TO_FLOAT_CASE(ushort) + TO_DOUBLE_CASE(ushort) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kUnsignedShort: + ushortPtr = (ushort *)inRaw; + switch( outType ) + { + BOOL_CASE(ushort) + + case kUShort: + case kUnsignedShort: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(ushort,kChar,char,saturate) + DOWN_CAST_CASE(ushort,kUChar,uchar,saturate) + DOWN_CAST_CASE(ushort,kUnsignedChar,uchar,saturate) + DOWN_CAST_CASE(ushort,kShort,short,saturate) + SIMPLE_CAST_CASE(ushort,kInt,int) + SIMPLE_CAST_CASE(ushort,kUInt,uint) + SIMPLE_CAST_CASE(ushort,kUnsignedInt,uint) + SIMPLE_CAST_CASE(ushort,kLong,Long) + SIMPLE_CAST_CASE(ushort,kULong,ULong) + SIMPLE_CAST_CASE(ushort,kUnsignedLong,ULong) + + TO_FLOAT_CASE(ushort) + TO_DOUBLE_CASE(ushort) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kInt: + intPtr = (int *)inRaw; + switch( outType ) + { + BOOL_CASE(int) + + case kInt: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(int,kChar,char,saturate) + DOWN_CAST_CASE(int,kUChar,uchar,saturate) + DOWN_CAST_CASE(int,kUnsignedChar,uchar,saturate) + DOWN_CAST_CASE(int,kShort,short,saturate) + DOWN_CAST_CASE(int,kUShort,ushort,saturate) + DOWN_CAST_CASE(int,kUnsignedShort,ushort,saturate) + DOWN_CAST_CASE(int,kUInt,uint,saturate) + DOWN_CAST_CASE(int,kUnsignedInt,uint,saturate) + SIMPLE_CAST_CASE(int,kLong,Long) + SIMPLE_CAST_CASE(int,kULong,ULong) + SIMPLE_CAST_CASE(int,kUnsignedLong,ULong) + + TO_FLOAT_CASE(int) + TO_DOUBLE_CASE(int) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kUInt: + uintPtr = (uint *)inRaw; + switch( outType ) + { + BOOL_CASE(uint) + + case kUInt: + case kUnsignedInt: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(uint,kChar,char,saturate) + DOWN_CAST_CASE(uint,kUChar,uchar,saturate) + DOWN_CAST_CASE(uint,kUnsignedChar,uchar,saturate) + DOWN_CAST_CASE(uint,kShort,short,saturate) + DOWN_CAST_CASE(uint,kUShort,ushort,saturate) + DOWN_CAST_CASE(uint,kUnsignedShort,ushort,saturate) + DOWN_CAST_CASE(uint,kInt,int,saturate) + SIMPLE_CAST_CASE(uint,kLong,Long) + SIMPLE_CAST_CASE(uint,kULong,ULong) + SIMPLE_CAST_CASE(uint,kUnsignedLong,ULong) + + TO_FLOAT_CASE(uint) + TO_DOUBLE_CASE(uint) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kUnsignedInt: + uintPtr = (uint *)inRaw; + switch( outType ) + { + BOOL_CASE(uint) + + case kUInt: + case kUnsignedInt: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(uint,kChar,char,saturate) + DOWN_CAST_CASE(uint,kUChar,uchar,saturate) + DOWN_CAST_CASE(uint,kUnsignedChar,uchar,saturate) + DOWN_CAST_CASE(uint,kShort,short,saturate) + DOWN_CAST_CASE(uint,kUShort,ushort,saturate) + DOWN_CAST_CASE(uint,kUnsignedShort,ushort,saturate) + DOWN_CAST_CASE(uint,kInt,int,saturate) + SIMPLE_CAST_CASE(uint,kLong,Long) + SIMPLE_CAST_CASE(uint,kULong,ULong) + SIMPLE_CAST_CASE(uint,kUnsignedLong,ULong) + + TO_FLOAT_CASE(uint) + TO_DOUBLE_CASE(uint) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kLong: + LongPtr = (Long *)inRaw; + switch( outType ) + { + BOOL_CASE(Long) + + case kLong: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + DOWN_CAST_CASE(Long,kChar,char,saturate) + DOWN_CAST_CASE(Long,kUChar,uchar,saturate) + DOWN_CAST_CASE(Long,kUnsignedChar,uchar,saturate) + DOWN_CAST_CASE(Long,kShort,short,saturate) + DOWN_CAST_CASE(Long,kUShort,ushort,saturate) + DOWN_CAST_CASE(Long,kUnsignedShort,ushort,saturate) + DOWN_CAST_CASE(Long,kInt,int,saturate) + DOWN_CAST_CASE(Long,kUInt,uint,saturate) + DOWN_CAST_CASE(Long,kUnsignedInt,uint,saturate) + DOWN_CAST_CASE(Long,kULong,ULong,saturate) + DOWN_CAST_CASE(Long,kUnsignedLong,ULong,saturate) + + TO_FLOAT_CASE(Long) + TO_DOUBLE_CASE(Long) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kULong: + ULongPtr = (ULong *)inRaw; + switch( outType ) + { + BOOL_CASE(ULong) + + case kUnsignedLong: + case kULong: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + U_DOWN_CAST_CASE(ULong,kChar,char,saturate) + U_DOWN_CAST_CASE(ULong,kUChar,uchar,saturate) + U_DOWN_CAST_CASE(ULong,kUnsignedChar,uchar,saturate) + U_DOWN_CAST_CASE(ULong,kShort,short,saturate) + U_DOWN_CAST_CASE(ULong,kUShort,ushort,saturate) + U_DOWN_CAST_CASE(ULong,kUnsignedShort,ushort,saturate) + U_DOWN_CAST_CASE(ULong,kInt,int,saturate) + U_DOWN_CAST_CASE(ULong,kUInt,uint,saturate) + U_DOWN_CAST_CASE(ULong,kUnsignedInt,uint,saturate) + U_DOWN_CAST_CASE(ULong,kLong,Long,saturate) + + TO_FLOAT_CASE(ULong) + TO_DOUBLE_CASE(ULong) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kUnsignedLong: + ULongPtr = (ULong *)inRaw; + switch( outType ) + { + BOOL_CASE(ULong) + + case kULong: + case kUnsignedLong: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + U_DOWN_CAST_CASE(ULong,kChar,char,saturate) + U_DOWN_CAST_CASE(ULong,kUChar,uchar,saturate) + U_DOWN_CAST_CASE(ULong,kUnsignedChar,uchar,saturate) + U_DOWN_CAST_CASE(ULong,kShort,short,saturate) + U_DOWN_CAST_CASE(ULong,kUShort,ushort,saturate) + U_DOWN_CAST_CASE(ULong,kUnsignedShort,ushort,saturate) + U_DOWN_CAST_CASE(ULong,kInt,int,saturate) + U_DOWN_CAST_CASE(ULong,kUInt,uint,saturate) + U_DOWN_CAST_CASE(ULong,kUnsignedInt,uint,saturate) + U_DOWN_CAST_CASE(ULong,kLong,Long,saturate) + + TO_FLOAT_CASE(ULong) + TO_DOUBLE_CASE(ULong) + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kFloat: + floatPtr = (float *)inRaw; + switch( outType ) + { + BOOL_CASE(float) + + FLOAT_ROUND_CASE(kChar,char,roundType,saturate) + FLOAT_ROUND_CASE(kUChar,uchar,roundType,saturate) + FLOAT_ROUND_CASE(kUnsignedChar,uchar,roundType,saturate) + FLOAT_ROUND_CASE(kShort,short,roundType,saturate) + FLOAT_ROUND_CASE(kUShort,ushort,roundType,saturate) + FLOAT_ROUND_CASE(kUnsignedShort,ushort,roundType,saturate) + FLOAT_ROUND_CASE(kInt,int,roundType,saturate) + FLOAT_ROUND_CASE(kUInt,uint,roundType,saturate) + FLOAT_ROUND_CASE(kUnsignedInt,uint,roundType,saturate) + FLOAT_ROUND_CASE(kLong,Long,roundType,saturate) + FLOAT_ROUND_CASE(kULong,ULong,roundType,saturate) + FLOAT_ROUND_CASE(kUnsignedLong,ULong,roundType,saturate) + + case kFloat: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + TO_DOUBLE_CASE(float); + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + case kDouble: + doublePtr = (double *)inRaw; + switch( outType ) + { + BOOL_CASE(double) + + DOUBLE_ROUND_CASE(kChar,char,roundType,saturate) + DOUBLE_ROUND_CASE(kUChar,uchar,roundType,saturate) + DOUBLE_ROUND_CASE(kUnsignedChar,uchar,roundType,saturate) + DOUBLE_ROUND_CASE(kShort,short,roundType,saturate) + DOUBLE_ROUND_CASE(kUShort,ushort,roundType,saturate) + DOUBLE_ROUND_CASE(kUnsignedShort,ushort,roundType,saturate) + DOUBLE_ROUND_CASE(kInt,int,roundType,saturate) + DOUBLE_ROUND_CASE(kUInt,uint,roundType,saturate) + DOUBLE_ROUND_CASE(kUnsignedInt,uint,roundType,saturate) + DOUBLE_ROUND_CASE(kLong,Long,roundType,saturate) + DOUBLE_ROUND_CASE(kULong,ULong,roundType,saturate) + DOUBLE_ROUND_CASE(kUnsignedLong,ULong,roundType,saturate) + + TO_FLOAT_CASE(double); + + case kDouble: + memcpy( outRaw, inRaw, get_explicit_type_size( inType ) ); + break; + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } + break; + + default: + log_error( "ERROR: Invalid type given to convert_explicit_value!!\n" ); + break; + } +} + +void generate_random_data( ExplicitType type, size_t count, MTdata d, void *outData ) +{ + bool *boolPtr; + cl_char *charPtr; + cl_uchar *ucharPtr; + cl_short *shortPtr; + cl_ushort *ushortPtr; + cl_int *intPtr; + cl_uint *uintPtr; + cl_long *longPtr; + cl_ulong *ulongPtr; + cl_float *floatPtr; + cl_double *doublePtr; + cl_ushort *halfPtr; + size_t i; + cl_uint bits = genrand_int32(d); + cl_uint bitsLeft = 32; + + switch( type ) + { + case kBool: + boolPtr = (bool *)outData; + for( i = 0; i < count; i++ ) + { + if( 0 == bitsLeft) + { + bits = genrand_int32(d); + bitsLeft = 32; + } + boolPtr[i] = ( bits & 1 ) ? true : false; + bits >>= 1; bitsLeft -= 1; + } + break; + + case kChar: + charPtr = (cl_char *)outData; + for( i = 0; i < count; i++ ) + { + if( 0 == bitsLeft) + { + bits = genrand_int32(d); + bitsLeft = 32; + } + charPtr[i] = (cl_char)( (cl_int)(bits & 255 ) - 127 ); + bits >>= 8; bitsLeft -= 8; + } + break; + + case kUChar: + case kUnsignedChar: + ucharPtr = (cl_uchar *)outData; + for( i = 0; i < count; i++ ) + { + if( 0 == bitsLeft) + { + bits = genrand_int32(d); + bitsLeft = 32; + } + ucharPtr[i] = (cl_uchar)( bits & 255 ); + bits >>= 8; bitsLeft -= 8; + } + break; + + case kShort: + shortPtr = (cl_short *)outData; + for( i = 0; i < count; i++ ) + { + if( 0 == bitsLeft) + { + bits = genrand_int32(d); + bitsLeft = 32; + } + shortPtr[i] = (cl_short)( (cl_int)( bits & 65535 ) - 32767 ); + bits >>= 16; bitsLeft -= 16; + } + break; + + case kUShort: + case kUnsignedShort: + ushortPtr = (cl_ushort *)outData; + for( i = 0; i < count; i++ ) + { + if( 0 == bitsLeft) + { + bits = genrand_int32(d); + bitsLeft = 32; + } + ushortPtr[i] = (cl_ushort)( (cl_int)( bits & 65535 ) ); + bits >>= 16; bitsLeft -= 16; + } + break; + + case kInt: + intPtr = (cl_int *)outData; + for( i = 0; i < count; i++ ) + { + intPtr[i] = (cl_int)genrand_int32(d); + } + break; + + case kUInt: + case kUnsignedInt: + uintPtr = (cl_uint *)outData; + for( i = 0; i < count; i++ ) + { + uintPtr[i] = (unsigned int)genrand_int32(d); + } + break; + + case kLong: + longPtr = (cl_long *)outData; + for( i = 0; i < count; i++ ) + { + longPtr[i] = (cl_long)genrand_int32(d) | ( (cl_long)genrand_int32(d) << 32 ); + } + break; + + case kULong: + case kUnsignedLong: + ulongPtr = (cl_ulong *)outData; + for( i = 0; i < count; i++ ) + { + ulongPtr[i] = (cl_ulong)genrand_int32(d) | ( (cl_ulong)genrand_int32(d) << 32 ); + } + break; + + case kFloat: + floatPtr = (cl_float *)outData; + for( i = 0; i < count; i++ ) + { + // [ -(double) 0x7fffffff, (double) 0x7fffffff ] + double t = genrand_real1(d); + floatPtr[i] = (float) ((1.0 - t) * -(double) 0x7fffffff + t * (double) 0x7fffffff); + } + break; + + case kDouble: + doublePtr = (cl_double *)outData; + for( i = 0; i < count; i++ ) + { + cl_long u = (cl_long)genrand_int32(d) | ( (cl_long)genrand_int32(d) << 32 ); + double t = (double) u; + t *= MAKE_HEX_DOUBLE( 0x1.0p-32, 0x1, -32 ); // scale [-2**63, 2**63] to [-2**31, 2**31] + doublePtr[i] = t; + } + break; + + case kHalf: + halfPtr = (ushort *)outData; + for( i = 0; i < count; i++ ) + { + if( 0 == bitsLeft) + { + bits = genrand_int32(d); + bitsLeft = 32; + } + halfPtr[i] = bits & 65535; /* Kindly generates random bits for us */ + bits >>= 16; bitsLeft -= 16; + } + break; + + default: + log_error( "ERROR: Invalid type passed in to generate_random_data!\n" ); + break; + } +} + +void * create_random_data( ExplicitType type, MTdata d, size_t count ) +{ + void *data = malloc( get_explicit_type_size( type ) * count ); + generate_random_data( type, count, d, data ); + return data; +} + +cl_long read_upscale_signed( void *inRaw, ExplicitType inType ) +{ + switch( inType ) + { + case kChar: + return (cl_long)( *( (cl_char *)inRaw ) ); + case kUChar: + case kUnsignedChar: + return (cl_long)( *( (cl_uchar *)inRaw ) ); + case kShort: + return (cl_long)( *( (cl_short *)inRaw ) ); + case kUShort: + case kUnsignedShort: + return (cl_long)( *( (cl_ushort *)inRaw ) ); + case kInt: + return (cl_long)( *( (cl_int *)inRaw ) ); + case kUInt: + case kUnsignedInt: + return (cl_long)( *( (cl_uint *)inRaw ) ); + case kLong: + return (cl_long)( *( (cl_long *)inRaw ) ); + case kULong: + case kUnsignedLong: + return (cl_long)( *( (cl_ulong *)inRaw ) ); + default: + return 0; + } +} + +cl_ulong read_upscale_unsigned( void *inRaw, ExplicitType inType ) +{ + switch( inType ) + { + case kChar: + return (cl_ulong)( *( (cl_char *)inRaw ) ); + case kUChar: + case kUnsignedChar: + return (cl_ulong)( *( (cl_uchar *)inRaw ) ); + case kShort: + return (cl_ulong)( *( (cl_short *)inRaw ) ); + case kUShort: + case kUnsignedShort: + return (cl_ulong)( *( (cl_ushort *)inRaw ) ); + case kInt: + return (cl_ulong)( *( (cl_int *)inRaw ) ); + case kUInt: + case kUnsignedInt: + return (cl_ulong)( *( (cl_uint *)inRaw ) ); + case kLong: + return (cl_ulong)( *( (cl_long *)inRaw ) ); + case kULong: + case kUnsignedLong: + return (cl_ulong)( *( (cl_ulong *)inRaw ) ); + default: + return 0; + } +} + +float read_as_float( void *inRaw, ExplicitType inType ) +{ + switch( inType ) + { + case kChar: + return (float)( *( (cl_char *)inRaw ) ); + case kUChar: + case kUnsignedChar: + return (float)( *( (cl_char *)inRaw ) ); + case kShort: + return (float)( *( (cl_short *)inRaw ) ); + case kUShort: + case kUnsignedShort: + return (float)( *( (cl_ushort *)inRaw ) ); + case kInt: + return (float)( *( (cl_int *)inRaw ) ); + case kUInt: + case kUnsignedInt: + return (float)( *( (cl_uint *)inRaw ) ); + case kLong: + return (float)( *( (cl_long *)inRaw ) ); + case kULong: + case kUnsignedLong: + return (float)( *( (cl_ulong *)inRaw ) ); + case kFloat: + return *( (float *)inRaw ); + case kDouble: + return (float) *( (double*)inRaw ); + default: + return 0; + } +} + +float get_random_float(float low, float high, MTdata d) +{ + float t = (float)((double)genrand_int32(d) / (double)0xFFFFFFFF); + return (1.0f - t) * low + t * high; +} + +double get_random_double(double low, double high, MTdata d) +{ + cl_ulong u = (cl_ulong) genrand_int32(d) | ((cl_ulong) genrand_int32(d) << 32 ); + double t = (double) u * MAKE_HEX_DOUBLE( 0x1.0p-64, 0x1, -64); + return (1.0f - t) * low + t * high; +} + +float any_float( MTdata d ) +{ + union + { + float f; + cl_uint u; + }u; + + u.u = genrand_int32(d); + return u.f; +} + + +double any_double( MTdata d ) +{ + union + { + double f; + cl_ulong u; + }u; + + u.u = (cl_ulong) genrand_int32(d) | ((cl_ulong) genrand_int32(d) << 32); + return u.f; +} + +int random_in_range( int minV, int maxV, MTdata d ) +{ + cl_ulong r = ((cl_ulong) genrand_int32(d) ) * (maxV - minV + 1); + return (cl_uint)(r >> 32) + minV; +} + +size_t get_random_size_t(size_t low, size_t high, MTdata d) +{ + enum { N = sizeof(size_t)/sizeof(int) }; + + union { + int word[N]; + size_t size; + } u; + + for (unsigned i=0; i != N; ++i) { + u.word[i] = genrand_int32(d); + } + + assert(low <= high && "Invalid random number range specified"); + size_t range = high - low; + + return (range) ? low + ((u.size - low) % range) : low; +} + + diff --git a/test_conformance/compatibility/test_common/harness/conversions.h b/test_conformance/compatibility/test_common/harness/conversions.h new file mode 100644 index 00000000..aa3cb6b4 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/conversions.h @@ -0,0 +1,126 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _conversions_h +#define _conversions_h + +#include "compat.h" + +#include "errorHelpers.h" +#include "mt19937.h" +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Note: the next three all have to match in size and order!! */ + +enum ExplicitTypes +{ + kBool = 0, + kChar, + kUChar, + kUnsignedChar, + kShort, + kUShort, + kUnsignedShort, + kInt, + kUInt, + kUnsignedInt, + kLong, + kULong, + kUnsignedLong, + kFloat, + kHalf, + kDouble, + kNumExplicitTypes +}; + +typedef enum ExplicitTypes ExplicitType; + +enum RoundingTypes +{ + kRoundToEven = 0, + kRoundToZero, + kRoundToPosInf, + kRoundToNegInf, + kRoundToNearest, + + kNumRoundingTypes, + + kDefaultRoundingType = kRoundToNearest +}; + +typedef enum RoundingTypes RoundingType; + +extern void print_type_to_string(ExplicitType type, void *data, char* string); +extern size_t get_explicit_type_size( ExplicitType type ); +extern const char * get_explicit_type_name( ExplicitType type ); +extern void convert_explicit_value( void *inRaw, void *outRaw, ExplicitType inType, bool saturate, RoundingType roundType, ExplicitType outType ); + +extern void generate_random_data( ExplicitType type, size_t count, MTdata d, void *outData ); +extern void * create_random_data( ExplicitType type, MTdata d, size_t count ); + +extern cl_long read_upscale_signed( void *inRaw, ExplicitType inType ); +extern cl_ulong read_upscale_unsigned( void *inRaw, ExplicitType inType ); +extern float read_as_float( void *inRaw, ExplicitType inType ); + +extern float get_random_float(float low, float high, MTdata d); +extern double get_random_double(double low, double high, MTdata d); +extern float any_float( MTdata d ); +extern double any_double( MTdata d ); + +extern int random_in_range( int minV, int maxV, MTdata d ); + +size_t get_random_size_t(size_t low, size_t high, MTdata d); + +// Note: though this takes a double, this is for use with single precision tests +static inline int IsFloatSubnormal( float x ) +{ +#if 2 == FLT_RADIX + // Do this in integer to avoid problems with FTZ behavior + union{ float d; uint32_t u;}u; + u.d = fabsf(x); + return (u.u-1) < 0x007fffffU; +#else + // rely on floating point hardware for non-radix2 non-IEEE-754 hardware -- will fail if you flush subnormals to zero + return fabs(x) < (double) FLT_MIN && x != 0.0; +#endif +} + +static inline int IsDoubleSubnormal( double x ) +{ +#if 2 == FLT_RADIX + // Do this in integer to avoid problems with FTZ behavior + union{ double d; uint64_t u;}u; + u.d = fabs( x); + return (u.u-1) < 0x000fffffffffffffULL; +#else + // rely on floating point hardware for non-radix2 non-IEEE-754 hardware -- will fail if you flush subnormals to zero + return fabs(x) < (double) DBL_MIN && x != 0.0; +#endif +} + +#if defined(__cplusplus) +} +#endif + +#endif // _conversions_h + + diff --git a/test_conformance/compatibility/test_common/harness/errorHelpers.c b/test_conformance/compatibility/test_common/harness/errorHelpers.c new file mode 100644 index 00000000..79c4ca21 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/errorHelpers.c @@ -0,0 +1,579 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "compat.h" + +#include +#include +#include + +#include "errorHelpers.h" + +const char *IGetErrorString( int clErrorCode ) +{ + switch( clErrorCode ) + { + case CL_SUCCESS: return "CL_SUCCESS"; + case CL_DEVICE_NOT_FOUND: return "CL_DEVICE_NOT_FOUND"; + case CL_DEVICE_NOT_AVAILABLE: return "CL_DEVICE_NOT_AVAILABLE"; + case CL_COMPILER_NOT_AVAILABLE: return "CL_COMPILER_NOT_AVAILABLE"; + case CL_MEM_OBJECT_ALLOCATION_FAILURE: return "CL_MEM_OBJECT_ALLOCATION_FAILURE"; + case CL_OUT_OF_RESOURCES: return "CL_OUT_OF_RESOURCES"; + case CL_OUT_OF_HOST_MEMORY: return "CL_OUT_OF_HOST_MEMORY"; + case CL_PROFILING_INFO_NOT_AVAILABLE: return "CL_PROFILING_INFO_NOT_AVAILABLE"; + case CL_MEM_COPY_OVERLAP: return "CL_MEM_COPY_OVERLAP"; + case CL_IMAGE_FORMAT_MISMATCH: return "CL_IMAGE_FORMAT_MISMATCH"; + case CL_IMAGE_FORMAT_NOT_SUPPORTED: return "CL_IMAGE_FORMAT_NOT_SUPPORTED"; + case CL_BUILD_PROGRAM_FAILURE: return "CL_BUILD_PROGRAM_FAILURE"; + case CL_MAP_FAILURE: return "CL_MAP_FAILURE"; + case CL_MISALIGNED_SUB_BUFFER_OFFSET: return "CL_MISALIGNED_SUB_BUFFER_OFFSET"; + case CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST: return "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST"; + case CL_COMPILE_PROGRAM_FAILURE: return "CL_COMPILE_PROGRAM_FAILURE"; + case CL_LINKER_NOT_AVAILABLE: return "CL_LINKER_NOT_AVAILABLE"; + case CL_LINK_PROGRAM_FAILURE: return "CL_LINK_PROGRAM_FAILURE"; + case CL_DEVICE_PARTITION_FAILED: return "CL_DEVICE_PARTITION_FAILED"; + case CL_KERNEL_ARG_INFO_NOT_AVAILABLE: return "CL_KERNEL_ARG_INFO_NOT_AVAILABLE"; + case CL_INVALID_VALUE: return "CL_INVALID_VALUE"; + case CL_INVALID_DEVICE_TYPE: return "CL_INVALID_DEVICE_TYPE"; + case CL_INVALID_DEVICE: return "CL_INVALID_DEVICE"; + case CL_INVALID_CONTEXT: return "CL_INVALID_CONTEXT"; + case CL_INVALID_QUEUE_PROPERTIES: return "CL_INVALID_QUEUE_PROPERTIES"; + case CL_INVALID_COMMAND_QUEUE: return "CL_INVALID_COMMAND_QUEUE"; + case CL_INVALID_HOST_PTR: return "CL_INVALID_HOST_PTR"; + case CL_INVALID_MEM_OBJECT: return "CL_INVALID_MEM_OBJECT"; + case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR: return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR"; + case CL_INVALID_IMAGE_SIZE: return "CL_INVALID_IMAGE_SIZE"; + case CL_INVALID_SAMPLER: return "CL_INVALID_SAMPLER"; + case CL_INVALID_BINARY: return "CL_INVALID_BINARY"; + case CL_INVALID_BUILD_OPTIONS: return "CL_INVALID_BUILD_OPTIONS"; + case CL_INVALID_PROGRAM: return "CL_INVALID_PROGRAM"; + case CL_INVALID_PROGRAM_EXECUTABLE: return "CL_INVALID_PROGRAM_EXECUTABLE"; + case CL_INVALID_KERNEL_NAME: return "CL_INVALID_KERNEL_NAME"; + case CL_INVALID_KERNEL_DEFINITION: return "CL_INVALID_KERNEL_DEFINITION"; + case CL_INVALID_KERNEL: return "CL_INVALID_KERNEL"; + case CL_INVALID_ARG_INDEX: return "CL_INVALID_ARG_INDEX"; + case CL_INVALID_ARG_VALUE: return "CL_INVALID_ARG_VALUE"; + case CL_INVALID_ARG_SIZE: return "CL_INVALID_ARG_SIZE"; + case CL_INVALID_KERNEL_ARGS: return "CL_INVALID_KERNEL_ARGS"; + case CL_INVALID_WORK_DIMENSION: return "CL_INVALID_WORK_DIMENSION"; + case CL_INVALID_WORK_GROUP_SIZE: return "CL_INVALID_WORK_GROUP_SIZE"; + case CL_INVALID_WORK_ITEM_SIZE: return "CL_INVALID_WORK_ITEM_SIZE"; + case CL_INVALID_GLOBAL_OFFSET: return "CL_INVALID_GLOBAL_OFFSET"; + case CL_INVALID_EVENT_WAIT_LIST: return "CL_INVALID_EVENT_WAIT_LIST"; + case CL_INVALID_EVENT: return "CL_INVALID_EVENT"; + case CL_INVALID_OPERATION: return "CL_INVALID_OPERATION"; + case CL_INVALID_GL_OBJECT: return "CL_INVALID_GL_OBJECT"; + case CL_INVALID_BUFFER_SIZE: return "CL_INVALID_BUFFER_SIZE"; + case CL_INVALID_MIP_LEVEL: return "CL_INVALID_MIP_LEVEL"; + case CL_INVALID_GLOBAL_WORK_SIZE: return "CL_INVALID_GLOBAL_WORK_SIZE"; + case CL_INVALID_PROPERTY: return "CL_INVALID_PROPERTY"; + case CL_INVALID_IMAGE_DESCRIPTOR: return "CL_INVALID_IMAGE_DESCRIPTOR"; + case CL_INVALID_COMPILER_OPTIONS: return "CL_INVALID_COMPILER_OPTIONS"; + case CL_INVALID_LINKER_OPTIONS: return "CL_INVALID_LINKER_OPTIONS"; + case CL_INVALID_DEVICE_PARTITION_COUNT: return "CL_INVALID_DEVICE_PARTITION_COUNT"; + default: return "(unknown)"; + } +} + +const char *GetChannelOrderName( cl_channel_order order ) +{ + switch( order ) + { + case CL_R: return "CL_R"; + case CL_A: return "CL_A"; + case CL_Rx: return "CL_Rx"; + case CL_RG: return "CL_RG"; + case CL_RA: return "CL_RA"; + case CL_RGx: return "CL_RGx"; + case CL_RGB: return "CL_RGB"; + case CL_RGBx: return "CL_RGBx"; + case CL_RGBA: return "CL_RGBA"; + case CL_ARGB: return "CL_ARGB"; + case CL_BGRA: return "CL_BGRA"; + case CL_INTENSITY: return "CL_INTENSITY"; + case CL_LUMINANCE: return "CL_LUMINANCE"; +#if defined CL_1RGB_APPLE + case CL_1RGB_APPLE: return "CL_1RGB_APPLE"; +#endif +#if defined CL_BGR1_APPLE + case CL_BGR1_APPLE: return "CL_BGR1_APPLE"; +#endif + default: return NULL; + } +} + +int IsChannelOrderSupported( cl_channel_order order ) +{ + switch( order ) + { + case CL_R: + case CL_A: + case CL_Rx: + case CL_RG: + case CL_RA: + case CL_RGx: + case CL_RGB: + case CL_RGBx: + case CL_RGBA: + case CL_ARGB: + case CL_BGRA: + case CL_INTENSITY: + case CL_LUMINANCE: + return 1; +#if defined CL_1RGB_APPLE + case CL_1RGB_APPLE: + return 1; +#endif +#if defined CL_BGR1_APPLE + case CL_BGR1_APPLE: + return 1; +#endif + default: + return 0; + } +} + +const char *GetChannelTypeName( cl_channel_type type ) +{ + switch( type ) + { + case CL_SNORM_INT8: return "CL_SNORM_INT8"; + case CL_SNORM_INT16: return "CL_SNORM_INT16"; + case CL_UNORM_INT8: return "CL_UNORM_INT8"; + case CL_UNORM_INT16: return "CL_UNORM_INT16"; + case CL_UNORM_SHORT_565: return "CL_UNORM_SHORT_565"; + case CL_UNORM_SHORT_555: return "CL_UNORM_SHORT_555"; + case CL_UNORM_INT_101010: return "CL_UNORM_INT_101010"; + case CL_SIGNED_INT8: return "CL_SIGNED_INT8"; + case CL_SIGNED_INT16: return "CL_SIGNED_INT16"; + case CL_SIGNED_INT32: return "CL_SIGNED_INT32"; + case CL_UNSIGNED_INT8: return "CL_UNSIGNED_INT8"; + case CL_UNSIGNED_INT16: return "CL_UNSIGNED_INT16"; + case CL_UNSIGNED_INT32: return "CL_UNSIGNED_INT32"; + case CL_HALF_FLOAT: return "CL_HALF_FLOAT"; + case CL_FLOAT: return "CL_FLOAT"; +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: return "CL_SFIXED14_APPLE"; +#endif + default: return NULL; + } +} + +int IsChannelTypeSupported( cl_channel_type type ) +{ + switch( type ) + { + case CL_SNORM_INT8: + case CL_SNORM_INT16: + case CL_UNORM_INT8: + case CL_UNORM_INT16: + case CL_UNORM_SHORT_565: + case CL_UNORM_SHORT_555: + case CL_UNORM_INT_101010: + case CL_SIGNED_INT8: + case CL_SIGNED_INT16: + case CL_SIGNED_INT32: + case CL_UNSIGNED_INT8: + case CL_UNSIGNED_INT16: + case CL_UNSIGNED_INT32: + case CL_HALF_FLOAT: + case CL_FLOAT: + return 1; +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: + return 1; +#endif + default: + return 0; + } +} + +const char *GetAddressModeName( cl_addressing_mode mode ) +{ + switch( mode ) + { + case CL_ADDRESS_NONE: return "CL_ADDRESS_NONE"; + case CL_ADDRESS_CLAMP_TO_EDGE: return "CL_ADDRESS_CLAMP_TO_EDGE"; + case CL_ADDRESS_CLAMP: return "CL_ADDRESS_CLAMP"; + case CL_ADDRESS_REPEAT: return "CL_ADDRESS_REPEAT"; + case CL_ADDRESS_MIRRORED_REPEAT: return "CL_ADDRESS_MIRRORED_REPEAT"; + default: return NULL; + } +} + +const char *GetDeviceTypeName( cl_device_type type ) +{ + switch( type ) + { + case CL_DEVICE_TYPE_GPU: return "CL_DEVICE_TYPE_GPU"; + case CL_DEVICE_TYPE_CPU: return "CL_DEVICE_TYPE_CPU"; + case CL_DEVICE_TYPE_ACCELERATOR: return "CL_DEVICE_TYPE_ACCELERATOR"; + case CL_DEVICE_TYPE_ALL: return "CL_DEVICE_TYPE_ALL"; + default: return NULL; + } +} + +const char *GetDataVectorString( void *dataBuffer, size_t typeSize, size_t vecSize, char *buffer ) +{ + static char scratch[ 1024 ]; + size_t i, j; + + if( buffer == NULL ) + buffer = scratch; + + unsigned char *p = (unsigned char *)dataBuffer; + char *bPtr; + + buffer[ 0 ] = 0; + bPtr = buffer; + for( i = 0; i < vecSize; i++ ) + { + if( i > 0 ) + { + bPtr[ 0 ] = ' '; + bPtr++; + } + for( j = 0; j < typeSize; j++ ) + { + sprintf( bPtr, "%02x", (unsigned int)p[ typeSize - j - 1 ] ); + bPtr += 2; + } + p += typeSize; + } + bPtr[ 0 ] = 0; + + return buffer; +} + +#ifndef MAX +#define MAX( _a, _b ) ((_a) > (_b) ? (_a) : (_b)) +#endif + +#if defined( _MSC_VER ) +#define scalbnf(_a, _i ) ldexpf( _a, _i ) +#define scalbn(_a, _i ) ldexp( _a, _i ) +#define scalbnl(_a, _i ) ldexpl( _a, _i ) +#endif + +static float Ulp_Error_Half_Float( float test, double reference ); +static inline float half2float( cl_ushort half ); + +// taken from math tests +#define HALF_MIN_EXP -13 +#define HALF_MANT_DIG 11 +static float Ulp_Error_Half_Float( float test, double reference ) +{ + union{ double d; uint64_t u; }u; u.d = reference; + + // Note: This function presumes that someone has already tested whether the result is correctly, + // rounded before calling this function. That test: + // + // if( (float) reference == test ) + // return 0.0f; + // + // would ensure that cases like fabs(reference) > FLT_MAX are weeded out before we get here. + // Otherwise, we'll return inf ulp error here, for what are otherwise correctly rounded + // results. + + double testVal = test; + if( u.u & 0x000fffffffffffffULL ) + { // Non-power of two and NaN + if( isnan( reference ) && isnan( test ) ) + return 0.0f; // if we are expecting a NaN, any NaN is fine + + // The unbiased exponent of the ulp unit place + int ulp_exp = HALF_MANT_DIG - 1 - MAX( ilogb( reference), HALF_MIN_EXP-1 ); + + // Scale the exponent of the error + return (float) scalbn( testVal - reference, ulp_exp ); + } + + if( isinf( reference ) ) + { + if( (double) test == reference ) + return 0.0f; + + return (float) (testVal - reference ); + } + + // reference is a normal power of two or a zero + int ulp_exp = HALF_MANT_DIG - 1 - MAX( ilogb( reference) - 1, HALF_MIN_EXP-1 ); + + // Scale the exponent of the error + return (float) scalbn( testVal - reference, ulp_exp ); +} + +// Taken from vLoadHalf test +static inline float half2float( cl_ushort us ) +{ + uint32_t u = us; + uint32_t sign = (u << 16) & 0x80000000; + int32_t exponent = (u & 0x7c00) >> 10; + uint32_t mantissa = (u & 0x03ff) << 13; + union{ unsigned int u; float f;}uu; + + if( exponent == 0 ) + { + if( mantissa == 0 ) + return sign ? -0.0f : 0.0f; + + int shift = __builtin_clz( mantissa ) - 8; + exponent -= shift-1; + mantissa <<= shift; + mantissa &= 0x007fffff; + } + else + if( exponent == 31) + { + uu.u = mantissa | sign; + if( mantissa ) + uu.u |= 0x7fc00000; + else + uu.u |= 0x7f800000; + + return uu.f; + } + + exponent += 127 - 15; + exponent <<= 23; + + exponent |= mantissa; + uu.u = exponent | sign; + + return uu.f; +} + +float Ulp_Error_Half( cl_ushort test, float reference ) +{ + return Ulp_Error_Half_Float( half2float(test), reference ); +} + + +float Ulp_Error( float test, double reference ) +{ + union{ double d; uint64_t u; }u; u.d = reference; + double testVal = test; + + // Note: This function presumes that someone has already tested whether the result is correctly, + // rounded before calling this function. That test: + // + // if( (float) reference == test ) + // return 0.0f; + // + // would ensure that cases like fabs(reference) > FLT_MAX are weeded out before we get here. + // Otherwise, we'll return inf ulp error here, for what are otherwise correctly rounded + // results. + + + if( isinf( reference ) ) + { + if( testVal == reference ) + return 0.0f; + + return (float) (testVal - reference ); + } + + if( isinf( testVal) ) + { // infinite test value, but finite (but possibly overflowing in float) reference. + // + // The function probably overflowed prematurely here. Formally, the spec says this is + // an infinite ulp error and should not be tolerated. Unfortunately, this would mean + // that the internal precision of some half_pow implementations would have to be 29+ bits + // at half_powr( 0x1.fffffep+31, 4) to correctly determine that 4*log2( 0x1.fffffep+31 ) + // is not exactly 128.0. You might represent this for example as 4*(32 - ~2**-24), which + // after rounding to single is 4*32 = 128, which will ultimately result in premature + // overflow, even though a good faith representation would be correct to within 2**-29 + // interally. + + // In the interest of not requiring the implementation go to extraordinary lengths to + // deliver a half precision function, we allow premature overflow within the limit + // of the allowed ulp error. Towards, that end, we "pretend" the test value is actually + // 2**128, the next value that would appear in the number line if float had sufficient range. + testVal = copysign( MAKE_HEX_DOUBLE(0x1.0p128, 0x1LL, 128), testVal ); + + // Note that the same hack may not work in long double, which is not guaranteed to have + // more range than double. It is not clear that premature overflow should be tolerated for + // double. + } + + if( u.u & 0x000fffffffffffffULL ) + { // Non-power of two and NaN + if( isnan( reference ) && isnan( test ) ) + return 0.0f; // if we are expecting a NaN, any NaN is fine + + // The unbiased exponent of the ulp unit place + int ulp_exp = FLT_MANT_DIG - 1 - MAX( ilogb( reference), FLT_MIN_EXP-1 ); + + // Scale the exponent of the error + return (float) scalbn( testVal - reference, ulp_exp ); + } + + // reference is a normal power of two or a zero + // The unbiased exponent of the ulp unit place + int ulp_exp = FLT_MANT_DIG - 1 - MAX( ilogb( reference) - 1, FLT_MIN_EXP-1 ); + + // Scale the exponent of the error + return (float) scalbn( testVal - reference, ulp_exp ); +} + +float Ulp_Error_Double( double test, long double reference ) +{ + // Deal with long double = double + // On most systems long double is a higher precision type than double. They provide either + // a 80-bit or greater floating point type, or they provide a head-tail double double format. + // That is sufficient to represent the accuracy of a floating point result to many more bits + // than double and we can calculate sub-ulp errors. This is the standard system for which this + // test suite is designed. + // + // On some systems double and long double are the same thing. Then we run into a problem, + // because our representation of the infinitely precise result (passed in as reference above) + // can be off by as much as a half double precision ulp itself. In this case, we inflate the + // reported error by half an ulp to take this into account. A more correct and permanent fix + // would be to undertake refactoring the reference code to return results in this format: + // + // typedef struct DoubleReference + // { // true value = correctlyRoundedResult + ulps * ulp(correctlyRoundedResult) (infinitely precise) + // double correctlyRoundedResult; // as best we can + // double ulps; // plus a fractional amount to account for the difference + // }DoubleReference; // between infinitely precise result and correctlyRoundedResult, in units of ulps. + // + // This would provide a useful higher-than-double precision format for everyone that we can use, + // and would solve a few problems with representing absolute errors below DBL_MIN and over DBL_MAX for systems + // that use a head to tail double double for long double. + + // Note: This function presumes that someone has already tested whether the result is correctly, + // rounded before calling this function. That test: + // + // if( (float) reference == test ) + // return 0.0f; + // + // would ensure that cases like fabs(reference) > FLT_MAX are weeded out before we get here. + // Otherwise, we'll return inf ulp error here, for what are otherwise correctly rounded + // results. + + + int x; + long double testVal = test; + if( 0.5L != frexpl( reference, &x) ) + { // Non-power of two and NaN + if( isinf( reference ) ) + { + if( testVal == reference ) + return 0.0f; + + return (float) ( testVal - reference ); + } + + if( isnan( reference ) && isnan( test ) ) + return 0.0f; // if we are expecting a NaN, any NaN is fine + + // The unbiased exponent of the ulp unit place + int ulp_exp = DBL_MANT_DIG - 1 - MAX( ilogbl( reference), DBL_MIN_EXP-1 ); + + // Scale the exponent of the error + float result = (float) scalbnl( testVal - reference, ulp_exp ); + + // account for rounding error in reference result on systems that do not have a higher precision floating point type (see above) + if( sizeof(long double) == sizeof( double ) ) + result += copysignf( 0.5f, result); + + return result; + + } + + // reference is a normal power of two or a zero + // The unbiased exponent of the ulp unit place + int ulp_exp = DBL_MANT_DIG - 1 - MAX( ilogbl( reference) - 1, DBL_MIN_EXP-1 ); + + // Scale the exponent of the error + float result = (float) scalbnl( testVal - reference, ulp_exp ); + + // account for rounding error in reference result on systems that do not have a higher precision floating point type (see above) + if( sizeof(long double) == sizeof( double ) ) + result += copysignf( 0.5f, result); + + return result; +} + +cl_int OutputBuildLogs(cl_program program, cl_uint num_devices, cl_device_id *device_list) +{ + int error; + size_t size_ret; + + // Does the program object exist? + if (program != NULL) { + + // Was the number of devices given + if (num_devices == 0) { + + // If zero devices were specified then allocate and query the device list from the context + cl_context context; + error = clGetProgramInfo(program, CL_PROGRAM_CONTEXT, sizeof(context), &context, NULL); + test_error( error, "Unable to query program's context" ); + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &size_ret); + test_error( error, "Unable to query context's device size" ); + num_devices = size_ret / sizeof(cl_device_id); + device_list = (cl_device_id *) malloc(size_ret); + if (device_list == NULL) { + print_error( error, "malloc failed" ); + return CL_OUT_OF_HOST_MEMORY; + } + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, size_ret, device_list, NULL); + test_error( error, "Unable to query context's devices" ); + + } + + // For each device in the device_list + unsigned int i; + for (i = 0; i < num_devices; i++) { + + // Get the build status + cl_build_status build_status; + error = clGetProgramBuildInfo(program, + device_list[i], + CL_PROGRAM_BUILD_STATUS, + sizeof(build_status), + &build_status, + &size_ret); + test_error( error, "Unable to query build status" ); + + // If the build failed then log the status, and allocate the build log, log it and free it + if (build_status != CL_BUILD_SUCCESS) { + + log_error("ERROR: CL_PROGRAM_BUILD_STATUS=%d\n", (int) build_status); + error = clGetProgramBuildInfo(program, device_list[i], CL_PROGRAM_BUILD_LOG, 0, NULL, &size_ret); + test_error( error, "Unable to query build log size" ); + char *build_log = (char *) malloc(size_ret); + error = clGetProgramBuildInfo(program, device_list[i], CL_PROGRAM_BUILD_LOG, size_ret, build_log, &size_ret); + test_error( error, "Unable to query build log" ); + log_error("ERROR: CL_PROGRAM_BUILD_LOG:\n%s\n", build_log); + free(build_log); + + } + + } + + // Was the number of devices given + if (num_devices == 0) { + + // If zero devices were specified then free the device list + free(device_list); + + } + + } + + return CL_SUCCESS; +} diff --git a/test_conformance/compatibility/test_common/harness/errorHelpers.h b/test_conformance/compatibility/test_common/harness/errorHelpers.h new file mode 100644 index 00000000..9b5d7097 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/errorHelpers.h @@ -0,0 +1,149 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _errorHelpers_h +#define _errorHelpers_h + +#ifdef __APPLE__ +#include +#else +#include +#endif +#include +#ifdef __cplusplus +extern "C" { +#endif + +#define LOWER_IS_BETTER 0 +#define HIGHER_IS_BETTER 1 + +// If USE_ATF is defined, all log_error and log_info calls can be routed to test library +// functions as described below. This is helpful for integration into an automated testing +// system. +#if USE_ATF +// export BUILD_WITH_ATF=1 + #include + #define test_start() ATFTestStart() + #define log_info ATFLogInfo + #define log_error ATFLogError + #define log_perf(_number, _higherBetter, _numType, _format, ...) ATFLogPerformanceNumber(_number, _higherBetter, _numType, _format, ##__VA_ARGS__) + #define test_finish() ATFTestFinish() + #define vlog_perf(_number, _higherBetter, _numType, _format, ...) ATFLogPerformanceNumber(_number, _higherBetter, _numType, _format,##__VA_ARGS__) + #define vlog ATFLogInfo + #define vlog_error ATFLogError +#else + #define test_start() + #define log_info printf + #define log_error printf + #define log_perf(_number, _higherBetter, _numType, _format, ...) printf("Performance Number " _format " (in %s, %s): %g\n",##__VA_ARGS__, _numType, \ + _higherBetter?"higher is better":"lower is better", _number ) + #define test_finish() + #define vlog_perf(_number, _higherBetter, _numType, _format, ...) printf("Performance Number " _format " (in %s, %s): %g\n",##__VA_ARGS__, _numType, \ + _higherBetter?"higher is better":"lower is better" , _number) + #ifdef _WIN32 + #ifdef __MINGW32__ + // Use __mingw_printf since it supports "%a" format specifier + #define vlog __mingw_printf + #define vlog_error __mingw_printf + #else + // Use home-baked function that treats "%a" as "%f" + static int vlog_win32(const char *format, ...); + #define vlog vlog_win32 + #define vlog_error vlog_win32 + #endif + #else + #define vlog_error printf + #define vlog printf + #endif +#endif + +#define ct_assert(b) ct_assert_i(b, __LINE__) +#define ct_assert_i(b, line) ct_assert_ii(b, line) +#define ct_assert_ii(b, line) int _compile_time_assertion_on_line_##line[b ? 1 : -1]; + +#define test_error(errCode,msg) test_error_ret(errCode,msg,errCode) +#define test_error_ret(errCode,msg,retValue) { if( errCode != CL_SUCCESS ) { print_error( errCode, msg ); return retValue ; } } +#define print_error(errCode,msg) log_error( "ERROR: %s! (%s from %s:%d)\n", msg, IGetErrorString( errCode ), __FILE__, __LINE__ ); + +// expected error code vs. what we got +#define test_failure_error(errCode, expectedErrCode, msg) test_failure_error_ret(errCode, expectedErrCode, msg, errCode != expectedErrCode) +#define test_failure_error_ret(errCode, expectedErrCode, msg, retValue) { if( errCode != expectedErrCode ) { print_failure_error( errCode, expectedErrCode, msg ); return retValue ; } } +#define print_failure_error(errCode, expectedErrCode, msg) log_error( "ERROR: %s! (Got %s, expected %s from %s:%d)\n", msg, IGetErrorString( errCode ), IGetErrorString( expectedErrCode ), __FILE__, __LINE__ ); +#define test_failure_warning(errCode, expectedErrCode, msg) test_failure_warning_ret(errCode, expectedErrCode, msg, errCode != expectedErrCode) +#define test_failure_warning_ret(errCode, expectedErrCode, msg, retValue) { if( errCode != expectedErrCode ) { print_failure_warning( errCode, expectedErrCode, msg ); warnings++ ; } } +#define print_failure_warning(errCode, expectedErrCode, msg) log_error( "WARNING: %s! (Got %s, expected %s from %s:%d)\n", msg, IGetErrorString( errCode ), IGetErrorString( expectedErrCode ), __FILE__, __LINE__ ); + +extern const char *IGetErrorString( int clErrorCode ); + +extern float Ulp_Error_Half( cl_ushort test, float reference ); +extern float Ulp_Error( float test, double reference ); +extern float Ulp_Error_Double( double test, long double reference ); + +extern const char *GetChannelTypeName( cl_channel_type type ); +extern int IsChannelTypeSupported( cl_channel_type type ); +extern const char *GetChannelOrderName( cl_channel_order order ); +extern int IsChannelOrderSupported( cl_channel_order order ); +extern const char *GetAddressModeName( cl_addressing_mode mode ); + +extern const char *GetDeviceTypeName( cl_device_type type ); + +// NON-REENTRANT UNLESS YOU PROVIDE A BUFFER PTR (pass null to use static storage, but it's not reentrant then!) +extern const char *GetDataVectorString( void *dataBuffer, size_t typeSize, size_t vecSize, char *buffer ); + +#if defined (_WIN32) && !defined(__MINGW32__) +#include +#include +#include +static int vlog_win32(const char *format, ...) +{ + const char *new_format = format; + + if (strstr(format, "%a")) { + char *temp; + if ((temp = strdup(format)) == NULL) { + printf("vlog_win32: Failed to allocate memory for strdup\n"); + return -1; + } + new_format = temp; + while (*temp) { + // replace %a with %f + if ((*temp == '%') && (*(temp+1) == 'a')) { + *(temp+1) = 'f'; + } + temp++; + } + } + + va_list args; + va_start(args, format); + vprintf(new_format, args); + va_end(args); + + if (new_format != format) { + free((void*)new_format); + } + + return 0; +} +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // _errorHelpers_h + + diff --git a/test_conformance/compatibility/test_common/harness/fpcontrol.h b/test_conformance/compatibility/test_common/harness/fpcontrol.h new file mode 100644 index 00000000..d6de0048 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/fpcontrol.h @@ -0,0 +1,104 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _fpcontrol_h +#define _fpcontrol_h + +// In order to get tests for correctly rounded operations (e.g. multiply) to work properly we need to be able to set the reference hardware +// to FTZ mode if the device hardware is running in that mode. We have explored all other options short of writing correctly rounded operations +// in integer code, and have found this is the only way to correctly verify operation. +// +// Non-Apple implementations will need to provide their own implentation for these features. If the reference hardware and device are both +// running in the same state (either FTZ or IEEE compliant modes) then these functions may be empty. If the device is running in non-default +// rounding mode (e.g. round toward zero), then these functions should also set the reference device into that rounding mode. +#if defined( __APPLE__ ) || defined( _MSC_VER ) || defined( __linux__ ) || defined (__MINGW32__) + typedef int FPU_mode_type; +#if defined( __i386__ ) || defined( __x86_64__ ) + #include +#elif defined( __PPC__ ) + #include + extern __thread fpu_control_t fpu_control; +#endif + // Set the reference hardware floating point unit to FTZ mode + static inline void ForceFTZ( FPU_mode_type *mode ) + { +#if defined( __i386__ ) || defined( __x86_64__ ) || defined( _MSC_VER ) || defined (__MINGW32__) + *mode = _mm_getcsr(); + _mm_setcsr( *mode | 0x8040); +#elif defined( __PPC__ ) + *mode = fpu_control; + fpu_control |= _FPU_MASK_NI; +#elif defined ( __arm__ ) + unsigned fpscr; + __asm__ volatile ("fmrx %0, fpscr" : "=r"(fpscr)); + *mode = fpscr; + __asm__ volatile ("fmxr fpscr, %0" :: "r"(fpscr | (1U << 24))); + // Add 64 bit support +#elif defined (__aarch64__) + unsigned fpscr; + __asm__ volatile ("mrs %0, fpcr" : "=r"(fpscr)); + *mode = fpscr; + __asm__ volatile ("msr fpcr, %0" :: "r"(fpscr | (1U << 24))); +#else + #error ForceFTZ needs an implentation +#endif + } + + // Disable the denorm flush to zero + static inline void DisableFTZ( FPU_mode_type *mode ) + { +#if defined( __i386__ ) || defined( __x86_64__ ) || defined( _MSC_VER ) || defined (__MINGW32__) + *mode = _mm_getcsr(); + _mm_setcsr( *mode & ~0x8040); +#elif defined( __PPC__ ) + *mode = fpu_control; + fpu_control &= ~_FPU_MASK_NI; +#elif defined ( __arm__ ) + unsigned fpscr; + __asm__ volatile ("fmrx %0, fpscr" : "=r"(fpscr)); + *mode = fpscr; + __asm__ volatile ("fmxr fpscr, %0" :: "r"(fpscr & ~(1U << 24))); + // Add 64 bit support +#elif defined (__aarch64__) + unsigned fpscr; + __asm__ volatile ("mrs %0, fpcr" : "=r"(fpscr)); + *mode = fpscr; + __asm__ volatile ("msr fpcr, %0" :: "r"(fpscr & ~(1U << 24))); +#else +#error DisableFTZ needs an implentation +#endif + } + + // Restore the reference hardware to floating point state indicated by *mode + static inline void RestoreFPState( FPU_mode_type *mode ) + { +#if defined( __i386__ ) || defined( __x86_64__ ) || defined( _MSC_VER ) || defined (__MINGW32__) + _mm_setcsr( *mode ); +#elif defined( __PPC__) + fpu_control = *mode; +#elif defined (__arm__) + __asm__ volatile ("fmxr fpscr, %0" :: "r"(*mode)); + // Add 64 bit support +#elif defined (__aarch64__) + __asm__ volatile ("msr fpcr, %0" :: "r"(*mode)); +#else + #error RestoreFPState needs an implementation +#endif + } +#else + #error ForceFTZ and RestoreFPState need implentations +#endif + +#endif diff --git a/test_conformance/compatibility/test_common/harness/genericThread.cpp b/test_conformance/compatibility/test_common/harness/genericThread.cpp new file mode 100644 index 00000000..2b742fa3 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/genericThread.cpp @@ -0,0 +1,53 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "genericThread.h" + +#if defined(_WIN32) +#include +#else // !_WIN32 +#include +#endif + +void * genericThread::IStaticReflector( void * data ) +{ + genericThread *t = (genericThread *)data; + return t->IRun(); +} + +bool genericThread::Start( void ) +{ +#if defined(_WIN32) + mHandle = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) IStaticReflector, this, 0, NULL ); + return ( mHandle != NULL ); +#else // !_WIN32 + int error = pthread_create( (pthread_t*)&mHandle, NULL, IStaticReflector, (void *)this ); + return ( error == 0 ); +#endif // !_WIN32 +} + +void * genericThread::Join( void ) +{ +#if defined(_WIN32) + WaitForSingleObject( (HANDLE)mHandle, INFINITE ); + return NULL; +#else // !_WIN32 + void * retVal; + int error = pthread_join( (pthread_t)mHandle, &retVal ); + if( error != 0 ) + retVal = NULL; + return retVal; +#endif // !_WIN32 +} diff --git a/test_conformance/compatibility/test_common/harness/genericThread.h b/test_conformance/compatibility/test_common/harness/genericThread.h new file mode 100644 index 00000000..168b7407 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/genericThread.h @@ -0,0 +1,42 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _genericThread_h +#define _genericThread_h + +#include + +class genericThread +{ + public: + + virtual ~genericThread() {} + + bool Start( void ); + void * Join( void ); + + protected: + + virtual void * IRun( void ) = 0; + + private: + + void* mHandle; + + static void * IStaticReflector( void * data ); +}; + +#endif // _genericThread_h + diff --git a/test_conformance/compatibility/test_common/harness/imageHelpers.cpp b/test_conformance/compatibility/test_common/harness/imageHelpers.cpp new file mode 100644 index 00000000..60f744b4 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/imageHelpers.cpp @@ -0,0 +1,249 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "imageHelpers.h" + +size_t get_format_type_size( const cl_image_format *format ) +{ + return get_channel_data_type_size( format->image_channel_data_type ); +} + +size_t get_channel_data_type_size( cl_channel_type channelType ) +{ + switch( channelType ) + { + case CL_SNORM_INT8: + case CL_UNORM_INT8: + case CL_SIGNED_INT8: + case CL_UNSIGNED_INT8: + return 1; + + case CL_SNORM_INT16: + case CL_UNORM_INT16: + case CL_SIGNED_INT16: + case CL_UNSIGNED_INT16: + case CL_HALF_FLOAT: +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: +#endif + return sizeof( cl_short ); + + case CL_SIGNED_INT32: + case CL_UNSIGNED_INT32: + return sizeof( cl_int ); + + case CL_UNORM_SHORT_565: + case CL_UNORM_SHORT_555: +#ifdef OBSOLETE_FORAMT + case CL_UNORM_SHORT_565_REV: + case CL_UNORM_SHORT_555_REV: +#endif + return 2; + +#ifdef OBSOLETE_FORAMT + case CL_UNORM_INT_8888: + case CL_UNORM_INT_8888_REV: + return 4; +#endif + + case CL_UNORM_INT_101010: +#ifdef OBSOLETE_FORAMT + case CL_UNORM_INT_101010_REV: +#endif + return 4; + + case CL_FLOAT: + return sizeof( cl_float ); + + default: + return 0; + } +} + +size_t get_format_channel_count( const cl_image_format *format ) +{ + return get_channel_order_channel_count( format->image_channel_order ); +} + +size_t get_channel_order_channel_count( cl_channel_order order ) +{ + switch( order ) + { + case CL_R: + case CL_A: + case CL_Rx: + case CL_INTENSITY: + case CL_LUMINANCE: + return 1; + + case CL_RG: + case CL_RA: + case CL_RGx: + return 2; + + case CL_RGB: + case CL_RGBx: + return 3; + + case CL_RGBA: + case CL_ARGB: + case CL_BGRA: +#ifdef CL_1RGB_APPLE + case CL_1RGB_APPLE: +#endif +#ifdef CL_BGR1_APPLE + case CL_BGR1_APPLE: +#endif + return 4; + + default: + return 0; + } +} + +int is_format_signed( const cl_image_format *format ) +{ + switch( format->image_channel_data_type ) + { + case CL_SNORM_INT8: + case CL_SIGNED_INT8: + case CL_SNORM_INT16: + case CL_SIGNED_INT16: + case CL_SIGNED_INT32: + case CL_HALF_FLOAT: + case CL_FLOAT: +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: +#endif + return 1; + + default: + return 0; + } +} + +size_t get_pixel_size( cl_image_format *format ) +{ + switch( format->image_channel_data_type ) + { + case CL_SNORM_INT8: + case CL_UNORM_INT8: + case CL_SIGNED_INT8: + case CL_UNSIGNED_INT8: + return get_format_channel_count( format ); + + case CL_SNORM_INT16: + case CL_UNORM_INT16: + case CL_SIGNED_INT16: + case CL_UNSIGNED_INT16: + case CL_HALF_FLOAT: +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: +#endif + return get_format_channel_count( format ) * sizeof( cl_ushort ); + + case CL_SIGNED_INT32: + case CL_UNSIGNED_INT32: + return get_format_channel_count( format ) * sizeof( cl_int ); + + case CL_UNORM_SHORT_565: + case CL_UNORM_SHORT_555: +#ifdef OBSOLETE_FORAMT + case CL_UNORM_SHORT_565_REV: + case CL_UNORM_SHORT_555_REV: +#endif + return 2; + +#ifdef OBSOLETE_FORAMT + case CL_UNORM_INT_8888: + case CL_UNORM_INT_8888_REV: + return 4; +#endif + + case CL_UNORM_INT_101010: +#ifdef OBSOLETE_FORAMT + case CL_UNORM_INT_101010_REV: +#endif + return 4; + + case CL_FLOAT: + return get_format_channel_count( format ) * sizeof( cl_float ); + + default: + return 0; + } +} + +int get_8_bit_image_format( cl_context context, cl_mem_object_type objType, cl_mem_flags flags, size_t channelCount, cl_image_format *outFormat ) +{ + cl_image_format formatList[ 128 ]; + unsigned int outFormatCount, i; + int error; + + + /* Make sure each image format is supported */ + if ((error = clGetSupportedImageFormats( context, flags, objType, 128, formatList, &outFormatCount ))) + return error; + + + /* Look for one that is an 8-bit format */ + for( i = 0; i < outFormatCount; i++ ) + { + if( formatList[ i ].image_channel_data_type == CL_SNORM_INT8 || + formatList[ i ].image_channel_data_type == CL_UNORM_INT8 || + formatList[ i ].image_channel_data_type == CL_SIGNED_INT8 || + formatList[ i ].image_channel_data_type == CL_UNSIGNED_INT8 ) + { + if ( !channelCount || ( channelCount && ( get_format_channel_count( &formatList[ i ] ) == channelCount ) ) ) + { + *outFormat = formatList[ i ]; + return 0; + } + } + } + + return -1; +} + +int get_32_bit_image_format( cl_context context, cl_mem_object_type objType, cl_mem_flags flags, size_t channelCount, cl_image_format *outFormat ) +{ + cl_image_format formatList[ 128 ]; + unsigned int outFormatCount, i; + int error; + + + /* Make sure each image format is supported */ + if ((error = clGetSupportedImageFormats( context, flags, objType, 128, formatList, &outFormatCount ))) + return error; + + /* Look for one that is an 8-bit format */ + for( i = 0; i < outFormatCount; i++ ) + { + if( formatList[ i ].image_channel_data_type == CL_UNORM_INT_101010 || + formatList[ i ].image_channel_data_type == CL_FLOAT || + formatList[ i ].image_channel_data_type == CL_SIGNED_INT32 || + formatList[ i ].image_channel_data_type == CL_UNSIGNED_INT32 ) + { + if ( !channelCount || ( channelCount && ( get_format_channel_count( &formatList[ i ] ) == channelCount ) ) ) + { + *outFormat = formatList[ i ]; + return 0; + } + } + } + + return -1; +} + diff --git a/test_conformance/compatibility/test_common/harness/imageHelpers.h b/test_conformance/compatibility/test_common/harness/imageHelpers.h new file mode 100644 index 00000000..05b7832f --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/imageHelpers.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _imageHelpers_h +#define _imageHelpers_h + +#include "errorHelpers.h" + + +extern size_t get_format_type_size( const cl_image_format *format ); +extern size_t get_channel_data_type_size( cl_channel_type channelType ); +extern size_t get_format_channel_count( const cl_image_format *format ); +extern size_t get_channel_order_channel_count( cl_channel_order order ); +extern int is_format_signed( const cl_image_format *format ); +extern size_t get_pixel_size( cl_image_format *format ); + +/* Helper to get any ol image format as long as it is 8-bits-per-channel */ +extern int get_8_bit_image_format( cl_context context, cl_mem_object_type objType, cl_mem_flags flags, size_t channelCount, cl_image_format *outFormat ); + +/* Helper to get any ol image format as long as it is 32-bits-per-channel */ +extern int get_32_bit_image_format( cl_context context, cl_mem_object_type objType, cl_mem_flags flags, size_t channelCount, cl_image_format *outFormat ); + + +#endif // _imageHelpers_h + diff --git a/test_conformance/compatibility/test_common/harness/kernelHelpers.c b/test_conformance/compatibility/test_common/harness/kernelHelpers.c new file mode 100644 index 00000000..3680c06e --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/kernelHelpers.c @@ -0,0 +1,684 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "kernelHelpers.h" +#include "errorHelpers.h" +#include "imageHelpers.h" + +#if defined(__MINGW32__) +#include "mingw_compat.h" +#endif + +int create_single_kernel_helper( cl_context context, cl_program *outProgram, cl_kernel *outKernel, unsigned int numKernelLines, const char **kernelProgram, const char *kernelName ) +{ + int error = CL_SUCCESS; + + /* Create the program object from source */ + *outProgram = clCreateProgramWithSource( context, numKernelLines, kernelProgram, NULL, &error ); + if( *outProgram == NULL || error != CL_SUCCESS) + { + print_error( error, "clCreateProgramWithSource failed" ); + return error; + } + + /* Compile the program */ + int buildProgramFailed = 0; + int printedSource = 0; + error = clBuildProgram( *outProgram, 0, NULL, NULL, NULL, NULL ); + if (error != CL_SUCCESS) + { + unsigned int i; + print_error(error, "clBuildProgram failed"); + buildProgramFailed = 1; + printedSource = 1; + log_error( "Original source is: ------------\n" ); + for( i = 0; i < numKernelLines; i++ ) + log_error( "%s", kernelProgram[ i ] ); + } + + // Verify the build status on all devices + cl_uint deviceCount = 0; + error = clGetProgramInfo( *outProgram, CL_PROGRAM_NUM_DEVICES, sizeof( deviceCount ), &deviceCount, NULL ); + if (error != CL_SUCCESS) { + print_error(error, "clGetProgramInfo CL_PROGRAM_NUM_DEVICES failed"); + return error; + } + + if (deviceCount == 0) { + log_error("No devices found for program.\n"); + return -1; + } + + cl_device_id *devices = (cl_device_id*) malloc( deviceCount * sizeof( cl_device_id ) ); + if( NULL == devices ) + return -1; + memset( devices, 0, deviceCount * sizeof( cl_device_id )); + error = clGetProgramInfo( *outProgram, CL_PROGRAM_DEVICES, sizeof( cl_device_id ) * deviceCount, devices, NULL ); + if (error != CL_SUCCESS) { + print_error(error, "clGetProgramInfo CL_PROGRAM_DEVICES failed"); + free( devices ); + return error; + } + + cl_uint z; + for( z = 0; z < deviceCount; z++ ) + { + char deviceName[4096] = ""; + error = clGetDeviceInfo(devices[z], CL_DEVICE_NAME, sizeof( deviceName), deviceName, NULL); + if (error != CL_SUCCESS || deviceName[0] == '\0') { + log_error("Device \"%d\" failed to return a name\n", z); + print_error(error, "clGetDeviceInfo CL_DEVICE_NAME failed"); + } + + cl_build_status buildStatus; + error = clGetProgramBuildInfo(*outProgram, devices[z], CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL); + if (error != CL_SUCCESS) { + print_error(error, "clGetProgramBuildInfo CL_PROGRAM_BUILD_STATUS failed"); + free( devices ); + return error; + } + + if (buildStatus != CL_BUILD_SUCCESS || buildProgramFailed) { + char log[10240] = ""; + if (buildStatus == CL_BUILD_SUCCESS && buildProgramFailed) log_error("clBuildProgram returned an error, but buildStatus is marked as CL_BUILD_SUCCESS.\n"); + + char statusString[64] = ""; + if (buildStatus == (cl_build_status)CL_BUILD_SUCCESS) + sprintf(statusString, "CL_BUILD_SUCCESS"); + else if (buildStatus == (cl_build_status)CL_BUILD_NONE) + sprintf(statusString, "CL_BUILD_NONE"); + else if (buildStatus == (cl_build_status)CL_BUILD_ERROR) + sprintf(statusString, "CL_BUILD_ERROR"); + else if (buildStatus == (cl_build_status)CL_BUILD_IN_PROGRESS) + sprintf(statusString, "CL_BUILD_IN_PROGRESS"); + else + sprintf(statusString, "UNKNOWN (%d)", buildStatus); + + if (buildStatus != CL_BUILD_SUCCESS) log_error("Build not successful for device \"%s\", status: %s\n", deviceName, statusString); + error = clGetProgramBuildInfo( *outProgram, devices[z], CL_PROGRAM_BUILD_LOG, sizeof(log), log, NULL ); + if (error != CL_SUCCESS || log[0]=='\0'){ + log_error("Device %d (%s) failed to return a build log\n", z, deviceName); + if (error) { + print_error(error, "clGetProgramBuildInfo CL_PROGRAM_BUILD_LOG failed"); + free( devices ); + return error; + } else { + log_error("clGetProgramBuildInfo returned an empty log.\n"); + free( devices ); + return -1; + } + } + // In this case we've already printed out the code above. + if (!printedSource) + { + unsigned int i; + log_error( "Original source is: ------------\n" ); + for( i = 0; i < numKernelLines; i++ ) + log_error( "%s", kernelProgram[ i ] ); + printedSource = 1; + } + log_error( "Build log for device \"%s\" is: ------------\n", deviceName ); + log_error( "%s\n", log ); + log_error( "\n----------\n" ); + free( devices ); + return -1; + } + } + + /* And create a kernel from it */ + *outKernel = clCreateKernel( *outProgram, kernelName, &error ); + if( *outKernel == NULL || error != CL_SUCCESS) + { + print_error( error, "Unable to create kernel" ); + free( devices ); + return error; + } + + free( devices ); + return 0; +} + +int get_device_version( cl_device_id id, size_t* major, size_t* minor) +{ + cl_char buffer[ 4098 ]; + size_t length; + + // Device version should fit the regex "OpenCL [0-9]+\.[0-9]+ *.*" + cl_int error = clGetDeviceInfo( id, CL_DEVICE_VERSION, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get device version string" ); + + char *p1 = (char *)buffer + strlen( "OpenCL " ); + char *p2; + while( *p1 == ' ' ) + p1++; + *major = strtol( p1, &p2, 10 ); + error = *p2 != '.'; + test_error(error, "ERROR: Version number must contain a decimal point!"); + *minor = strtol( ++p2, NULL, 10 ); + return error; +} + +int get_max_allowed_work_group_size( cl_context context, cl_kernel kernel, size_t *outMaxSize, size_t *outLimits ) +{ + cl_device_id *devices; + size_t size, maxCommonSize = 0; + int numDevices, i, j, error; + cl_uint numDims; + size_t outSize; + size_t sizeLimit[]={1,1,1}; + + + /* Assume fewer than 16 devices will be returned */ + error = clGetContextInfo( context, CL_CONTEXT_DEVICES, 0, NULL, &outSize ); + test_error( error, "Unable to obtain list of devices size for context" ); + devices = (cl_device_id *)malloc(outSize); + error = clGetContextInfo( context, CL_CONTEXT_DEVICES, outSize, devices, NULL ); + test_error( error, "Unable to obtain list of devices for context" ); + + numDevices = (int)( outSize / sizeof( cl_device_id ) ); + + for( i = 0; i < numDevices; i++ ) + { + error = clGetDeviceInfo( devices[i], CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof( size ), &size, NULL ); + test_error( error, "Unable to obtain max work group size for device" ); + if( size < maxCommonSize || maxCommonSize == 0) + maxCommonSize = size; + + error = clGetKernelWorkGroupInfo( kernel, devices[i], CL_KERNEL_WORK_GROUP_SIZE, sizeof( size ), &size, NULL ); + test_error( error, "Unable to obtain max work group size for device and kernel combo" ); + if( size < maxCommonSize || maxCommonSize == 0) + maxCommonSize = size; + + error= clGetDeviceInfo( devices[i], CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof( numDims ), &numDims, NULL); + test_error( error, "clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS"); + sizeLimit[0] = 1; + error= clGetDeviceInfo( devices[i], CL_DEVICE_MAX_WORK_ITEM_SIZES, numDims*sizeof(size_t), sizeLimit, NULL); + test_error( error, "clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_SIZES"); + + if (outLimits != NULL) + { + if (i == 0) { + for (j=0; j<3; j++) + outLimits[j] = sizeLimit[j]; + } else { + for (j=0; j<(int)numDims; j++) { + if (sizeLimit[j] < outLimits[j]) + outLimits[j] = sizeLimit[j]; + } + } + } + } + free(devices); + + *outMaxSize = (unsigned int)maxCommonSize; + return 0; +} + + +int get_max_common_work_group_size( cl_context context, cl_kernel kernel, + size_t globalThreadSize, size_t *outMaxSize ) +{ + size_t sizeLimit[3]; + int error = get_max_allowed_work_group_size( context, kernel, outMaxSize, sizeLimit ); + if( error != 0 ) + return error; + + /* Now find the largest factor of globalThreadSize that is <= maxCommonSize */ + /* Note for speed, we don't need to check the range of maxCommonSize, b/c once it gets to 1, + the modulo test will succeed and break the loop anyway */ + for( ; ( globalThreadSize % *outMaxSize ) != 0 || (*outMaxSize > sizeLimit[0]); (*outMaxSize)-- ) + ; + return 0; +} + +int get_max_common_2D_work_group_size( cl_context context, cl_kernel kernel, + size_t *globalThreadSizes, size_t *outMaxSizes ) +{ + size_t sizeLimit[3]; + size_t maxSize; + int error = get_max_allowed_work_group_size( context, kernel, &maxSize, sizeLimit ); + if( error != 0 ) + return error; + + /* Now find a set of factors, multiplied together less than maxSize, but each a factor of the global + sizes */ + + /* Simple case */ + if( globalThreadSizes[ 0 ] * globalThreadSizes[ 1 ] <= maxSize ) + { + if (globalThreadSizes[ 0 ] <= sizeLimit[0] && globalThreadSizes[ 1 ] <= sizeLimit[1]) { + outMaxSizes[ 0 ] = globalThreadSizes[ 0 ]; + outMaxSizes[ 1 ] = globalThreadSizes[ 1 ]; + return 0; + } + } + + size_t remainingSize, sizeForThisOne; + remainingSize = maxSize; + int i, j; + for (i=0 ; i<2; i++) { + if (globalThreadSizes[i] > remainingSize) + sizeForThisOne = remainingSize; + else + sizeForThisOne = globalThreadSizes[i]; + for (; (globalThreadSizes[i] % sizeForThisOne) != 0 || (sizeForThisOne > sizeLimit[i]); sizeForThisOne--) ; + outMaxSizes[i] = sizeForThisOne; + remainingSize = maxSize; + for (j=0; j<=i; j++) + remainingSize /=outMaxSizes[j]; + } + + return 0; +} + +int get_max_common_3D_work_group_size( cl_context context, cl_kernel kernel, + size_t *globalThreadSizes, size_t *outMaxSizes ) +{ + size_t sizeLimit[3]; + size_t maxSize; + int error = get_max_allowed_work_group_size( context, kernel, &maxSize, sizeLimit ); + if( error != 0 ) + return error; + /* Now find a set of factors, multiplied together less than maxSize, but each a factor of the global + sizes */ + + /* Simple case */ + if( globalThreadSizes[ 0 ] * globalThreadSizes[ 1 ] * globalThreadSizes[ 2 ] <= maxSize ) + { + if (globalThreadSizes[ 0 ] <= sizeLimit[0] && globalThreadSizes[ 1 ] <= sizeLimit[1] && globalThreadSizes[ 2 ] <= sizeLimit[2]) { + outMaxSizes[ 0 ] = globalThreadSizes[ 0 ]; + outMaxSizes[ 1 ] = globalThreadSizes[ 1 ]; + outMaxSizes[ 2 ] = globalThreadSizes[ 2 ]; + return 0; + } + } + + size_t remainingSize, sizeForThisOne; + remainingSize = maxSize; + int i, j; + for (i=0 ; i<3; i++) { + if (globalThreadSizes[i] > remainingSize) + sizeForThisOne = remainingSize; + else + sizeForThisOne = globalThreadSizes[i]; + for (; (globalThreadSizes[i] % sizeForThisOne) != 0 || (sizeForThisOne > sizeLimit[i]); sizeForThisOne--) ; + outMaxSizes[i] = sizeForThisOne; + remainingSize = maxSize; + for (j=0; j<=i; j++) + remainingSize /=outMaxSizes[j]; + } + + return 0; +} + +/* Helper to determine if an extension is supported by a device */ +int is_extension_available( cl_device_id device, const char *extensionName ) +{ + char *extString; + size_t size = 0; + int err; + int result = 0; + + if(( err = clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, 0, NULL, &size) )) + { + log_error( "Error: failed to determine size of device extensions string at %s:%d (err = %d)\n", __FILE__, __LINE__, err ); + return 0; + } + + if( 0 == size ) + return 0; + + extString = (char*) malloc( size ); + if( NULL == extString ) + { + log_error( "Error: unable to allocate %ld byte buffer for extension string at %s:%d (err = %d)\n", size, __FILE__, __LINE__, err ); + return 0; + } + + if(( err = clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, size, extString, NULL) )) + { + log_error( "Error: failed to obtain device extensions string at %s:%d (err = %d)\n", __FILE__, __LINE__, err ); + free( extString ); + return 0; + } + + if( strstr( extString, extensionName ) ) + result = 1; + + free( extString ); + return result; +} + +/* Helper to determine if a device supports an image format */ +int is_image_format_supported( cl_context context, cl_mem_flags flags, cl_mem_object_type image_type, const cl_image_format *fmt ) +{ + cl_image_format *list; + cl_uint count = 0; + cl_int err = clGetSupportedImageFormats( context, flags, image_type, 128, NULL, &count ); + if( count == 0 ) + return 0; + + list = (cl_image_format*) malloc( count * sizeof( cl_image_format ) ); + if( NULL == list ) + { + log_error( "Error: unable to allocate %ld byte buffer for image format list at %s:%d (err = %d)\n", count * sizeof( cl_image_format ), __FILE__, __LINE__, err ); + return 0; + } + + cl_int error = clGetSupportedImageFormats( context, flags, image_type, count, list, NULL ); + if( error ) + { + log_error( "Error: failed to obtain supported image type list at %s:%d (err = %d)\n", __FILE__, __LINE__, err ); + free( list ); + return 0; + } + + // iterate looking for a match. + cl_uint i; + for( i = 0; i < count; i++ ) + { + if( fmt->image_channel_data_type == list[ i ].image_channel_data_type && + fmt->image_channel_order == list[ i ].image_channel_order ) + break; + } + + free( list ); + return ( i < count ) ? true : false; +} + +size_t get_pixel_bytes( const cl_image_format *fmt ); +size_t get_pixel_bytes( const cl_image_format *fmt ) +{ + size_t chanCount; + switch( fmt->image_channel_order ) + { + case CL_R: + case CL_A: + case CL_Rx: + case CL_INTENSITY: + case CL_LUMINANCE: + chanCount = 1; + break; + case CL_RG: + case CL_RA: + case CL_RGx: + chanCount = 2; + break; + case CL_RGB: + case CL_RGBx: + chanCount = 3; + break; + case CL_RGBA: + case CL_ARGB: + case CL_BGRA: +#ifdef CL_1RGB_APPLE + case CL_1RGB_APPLE: +#endif +#ifdef CL_BGR1_APPLE + case CL_BGR1_APPLE: +#endif + chanCount = 4; + break; + default: + log_error("Unknown channel order at %s:%d!\n", __FILE__, __LINE__ ); + abort(); + break; + } + + switch( fmt->image_channel_data_type ) + { + case CL_UNORM_SHORT_565: + case CL_UNORM_SHORT_555: + return 2; + + case CL_UNORM_INT_101010: + return 4; + + case CL_SNORM_INT8: + case CL_UNORM_INT8: + case CL_SIGNED_INT8: + case CL_UNSIGNED_INT8: + return chanCount; + + case CL_SNORM_INT16: + case CL_UNORM_INT16: + case CL_HALF_FLOAT: + case CL_SIGNED_INT16: + case CL_UNSIGNED_INT16: +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: +#endif + return chanCount * 2; + + case CL_SIGNED_INT32: + case CL_UNSIGNED_INT32: + case CL_FLOAT: + return chanCount * 4; + + default: + log_error("Unknown channel data type at %s:%d!\n", __FILE__, __LINE__ ); + abort(); + } + + return 0; +} + +int verifyImageSupport( cl_device_id device ) +{ + if( checkForImageSupport( device ) ) + { + log_error( "ERROR: Device does not supported images as required by this test!\n" ); + return CL_IMAGE_FORMAT_NOT_SUPPORTED; + } + return 0; +} + +int checkForImageSupport( cl_device_id device ) +{ + cl_uint i; + int error; + + + /* Check the device props to see if images are supported at all first */ + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE_SUPPORT, sizeof( i ), &i, NULL ); + test_error( error, "Unable to query device for image support" ); + if( i == 0 ) + { + return CL_IMAGE_FORMAT_NOT_SUPPORTED; + } + + /* So our support is good */ + return 0; +} + +int checkFor3DImageSupport( cl_device_id device ) +{ + cl_uint i; + int error; + + /* Check the device props to see if images are supported at all first */ + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE_SUPPORT, sizeof( i ), &i, NULL ); + test_error( error, "Unable to query device for image support" ); + if( i == 0 ) + { + return CL_IMAGE_FORMAT_NOT_SUPPORTED; + } + + char profile[128]; + error = clGetDeviceInfo( device, CL_DEVICE_PROFILE, sizeof(profile ), profile, NULL ); + test_error( error, "Unable to query device for CL_DEVICE_PROFILE" ); + if( 0 == strcmp( profile, "EMBEDDED_PROFILE" ) ) + { + size_t width = -1L; + size_t height = -1L; + size_t depth = -1L; + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof(width), &width, NULL ); + test_error( error, "Unable to get CL_DEVICE_IMAGE3D_MAX_WIDTH" ); + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof(height), &height, NULL ); + test_error( error, "Unable to get CL_DEVICE_IMAGE3D_MAX_HEIGHT" ); + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(depth), &depth, NULL ); + test_error( error, "Unable to get CL_DEVICE_IMAGE3D_MAX_DEPTH" ); + + if( 0 == (height | width | depth )) + return CL_IMAGE_FORMAT_NOT_SUPPORTED; + } + + /* So our support is good */ + return 0; +} + +void * align_malloc(size_t size, size_t alignment) +{ +#if defined(_WIN32) && defined(_MSC_VER) + return _aligned_malloc(size, alignment); +#elif defined(__linux__) || defined (linux) || defined(__APPLE__) + void * ptr = NULL; + if (0 == posix_memalign(&ptr, alignment, size)) + return ptr; + return NULL; +#elif defined(__MINGW32__) + return __mingw_aligned_malloc(size, alignment); +#else + #error "Please add support OS for aligned malloc" +#endif +} + +void align_free(void * ptr) +{ +#if defined(_WIN32) && defined(_MSC_VER) + _aligned_free(ptr); +#elif defined(__linux__) || defined (linux) || defined(__APPLE__) + return free(ptr); +#elif defined(__MINGW32__) + return __mingw_aligned_free(ptr); +#else + #error "Please add support OS for aligned free" +#endif +} + +size_t get_min_alignment(cl_context context) +{ + static cl_uint align_size = 0; + + if( 0 == align_size ) + { + cl_device_id * devices; + size_t devices_size = 0; + cl_uint result = 0; + cl_int error; + int i; + + error = clGetContextInfo (context, + CL_CONTEXT_DEVICES, + 0, + NULL, + &devices_size); + test_error_ret(error, "clGetContextInfo failed", 0); + + devices = (cl_device_id*)malloc(devices_size); + if (devices == NULL) { + print_error( error, "malloc failed" ); + return 0; + } + + error = clGetContextInfo (context, + CL_CONTEXT_DEVICES, + devices_size, + (void*)devices, + NULL); + test_error_ret(error, "clGetContextInfo failed", 0); + + for (i = 0; i < (int)(devices_size/sizeof(cl_device_id)); i++) + { + cl_uint alignment = 0; + + error = clGetDeviceInfo (devices[i], + CL_DEVICE_MEM_BASE_ADDR_ALIGN, + sizeof(cl_uint), + (void*)&alignment, + NULL); + + if (error == CL_SUCCESS) + { + alignment >>= 3; // convert bits to bytes + result = (alignment > result) ? alignment : result; + } + else + print_error( error, "clGetDeviceInfo failed" ); + } + + align_size = result; + free(devices); + } + + return align_size; +} + +cl_device_fp_config get_default_rounding_mode( cl_device_id device ) +{ + char profileStr[128] = ""; + cl_device_fp_config single = 0; + int error = clGetDeviceInfo( device, CL_DEVICE_SINGLE_FP_CONFIG, sizeof( single ), &single, NULL ); + if( error ) + test_error_ret( error, "Unable to get device CL_DEVICE_SINGLE_FP_CONFIG", 0 ); + + if( single & CL_FP_ROUND_TO_NEAREST ) + return CL_FP_ROUND_TO_NEAREST; + + if( 0 == (single & CL_FP_ROUND_TO_ZERO) ) + test_error_ret( -1, "FAILURE: device must support either CL_DEVICE_SINGLE_FP_CONFIG or CL_FP_ROUND_TO_NEAREST", 0 ); + + // Make sure we are an embedded device before allowing a pass + if( (error = clGetDeviceInfo( device, CL_DEVICE_PROFILE, sizeof( profileStr ), &profileStr, NULL ) )) + test_error_ret( error, "FAILURE: Unable to get CL_DEVICE_PROFILE", 0 ); + + if( strcmp( profileStr, "EMBEDDED_PROFILE" ) ) + test_error_ret( error, "FAILURE: non-EMBEDDED_PROFILE devices must support CL_FP_ROUND_TO_NEAREST", 0 ); + + return CL_FP_ROUND_TO_ZERO; +} + +int checkDeviceForQueueSupport( cl_device_id device, cl_command_queue_properties prop ) +{ + cl_command_queue_properties realProps; + cl_int error = clGetDeviceInfo( device, CL_DEVICE_QUEUE_PROPERTIES, sizeof( realProps ), &realProps, NULL ); + test_error_ret( error, "FAILURE: Unable to get device queue properties", 0 ); + + return ( realProps & prop ) ? 1 : 0; +} + +int printDeviceHeader( cl_device_id device ) +{ + char deviceName[ 512 ], deviceVendor[ 512 ], deviceVersion[ 512 ], cLangVersion[ 512 ]; + int error; + + error = clGetDeviceInfo( device, CL_DEVICE_NAME, sizeof( deviceName ), deviceName, NULL ); + test_error( error, "Unable to get CL_DEVICE_NAME for device" ); + + error = clGetDeviceInfo( device, CL_DEVICE_VENDOR, sizeof( deviceVendor ), deviceVendor, NULL ); + test_error( error, "Unable to get CL_DEVICE_VENDOR for device" ); + + error = clGetDeviceInfo( device, CL_DEVICE_VERSION, sizeof( deviceVersion ), deviceVersion, NULL ); + test_error( error, "Unable to get CL_DEVICE_VERSION for device" ); + + error = clGetDeviceInfo( device, CL_DEVICE_OPENCL_C_VERSION, sizeof( cLangVersion ), cLangVersion, NULL ); + test_error( error, "Unable to get CL_DEVICE_OPENCL_C_VERSION for device" ); + + log_info("Compute Device Name = %s, Compute Device Vendor = %s, Compute Device Version = %s%s%s\n", + deviceName, deviceVendor, deviceVersion, ( error == CL_SUCCESS ) ? ", CL C Version = " : "", + ( error == CL_SUCCESS ) ? cLangVersion : "" ); + + return CL_SUCCESS; +} diff --git a/test_conformance/compatibility/test_common/harness/kernelHelpers.h b/test_conformance/compatibility/test_common/harness/kernelHelpers.h new file mode 100644 index 00000000..59c01b5f --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/kernelHelpers.h @@ -0,0 +1,128 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _kernelHelpers_h +#define _kernelHelpers_h + +#include "compat.h" + +#include +#include + +#if defined (__MINGW32__) +#include +#endif + +#include + +#ifdef __APPLE__ + #include +#else + #include +#endif + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/* + * The below code is intended to be used at the top of kernels that appear inline in files to set line and file info for the kernel: + * + * const char *source = { + * INIT_OPENCL_DEBUG_INFO + * "__kernel void foo( int x )\n" + * "{\n" + * " ...\n" + * "}\n" + * }; + */ +#define INIT_OPENCL_DEBUG_INFO SET_OPENCL_LINE_INFO( __LINE__, __FILE__ ) +#define SET_OPENCL_LINE_INFO(_line, _file) "#line " STRINGIFY(_line) " " STRINGIFY(_file) "\n" +#ifndef STRINGIFY_VALUE + #define STRINGIFY_VALUE(_x) STRINGIFY(_x) +#endif +#ifndef STRINGIFY + #define STRINGIFY(_x) #_x +#endif + +/* Helper that creates a single program and kernel from a single-kernel program source */ +extern int create_single_kernel_helper( cl_context context, cl_program *outProgram, cl_kernel *outKernel, unsigned int numKernelLines, const char **kernelProgram, const char *kernelName ); + +/* Helper to obtain the biggest fit work group size for all the devices in a given group and for the given global thread size */ +extern int get_max_common_work_group_size( cl_context context, cl_kernel kernel, size_t globalThreadSize, size_t *outSize ); + +/* Helper to obtain the biggest fit work group size for all the devices in a given group and for the given global thread size */ +extern int get_max_common_2D_work_group_size( cl_context context, cl_kernel kernel, size_t *globalThreadSize, size_t *outSizes ); + +/* Helper to obtain the biggest fit work group size for all the devices in a given group and for the given global thread size */ +extern int get_max_common_3D_work_group_size( cl_context context, cl_kernel kernel, size_t *globalThreadSize, size_t *outSizes ); + +/* Helper to get major/minor number for a device */ +extern int get_device_version( cl_device_id id, size_t* major, size_t* minor); + +/* Helper to obtain the biggest allowed work group size for all the devices in a given group */ +extern int get_max_allowed_work_group_size( cl_context context, cl_kernel kernel, size_t *outSize, size_t *outLimits ); + +/* Helper to determine if an extension is supported by a device */ +extern int is_extension_available( cl_device_id device, const char *extensionName ); + +/* Helper to determine if a device supports an image format */ +extern int is_image_format_supported( cl_context context, cl_mem_flags flags, cl_mem_object_type image_type, const cl_image_format *fmt ); + +/* Helper to get pixel size for a pixel format */ +size_t get_pixel_bytes( const cl_image_format *fmt ); + +/* Verify the given device supports images. 0 means you're good to go, otherwise an error */ +extern int verifyImageSupport( cl_device_id device ); + +/* Checks that the given device supports images. Same as verify, but doesn't print an error */ +extern int checkForImageSupport( cl_device_id device ); +extern int checkFor3DImageSupport( cl_device_id device ); + +/* Checks that a given queue property is supported on the specified device. Returns 1 if supported, 0 if not or an error. */ +extern int checkDeviceForQueueSupport( cl_device_id device, cl_command_queue_properties prop ); + +/* Helper for aligned memory allocation */ +void * align_malloc(size_t size, size_t alignment); +void align_free(void *); + +/* Helper to obtain the min alignment for a given context, i.e the max of all min alignments for devices attached to the context*/ +size_t get_min_alignment(cl_context context); + +/* Helper to obtain the default rounding mode for single precision computation. (Double is always CL_FP_ROUND_TO_NEAREST.) Returns 0 on error. */ +cl_device_fp_config get_default_rounding_mode( cl_device_id device ); + +#define PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) \ + if( checkForImageSupport( device ) ) \ + { \ + log_info( "\n\tNote: device does not support images. Skipping test...\n" ); \ + return 0; \ + } + +#define PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( device ) \ + if( checkFor3DImageSupport( device ) ) \ + { \ + log_info( "\n\tNote: device does not support 3D images. Skipping test...\n" ); \ + return 0; \ + } + +/* Prints out the standard device header for all tests given the device to print for */ +extern int printDeviceHeader( cl_device_id device ); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // _kernelHelpers_h diff --git a/test_conformance/compatibility/test_common/harness/mingw_compat.c b/test_conformance/compatibility/test_common/harness/mingw_compat.c new file mode 100644 index 00000000..54c44635 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/mingw_compat.c @@ -0,0 +1,59 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#if defined(__MINGW32__) + +#include "mingw_compat.h" +#include +#include + +//This function is unavailable on various mingw compilers, +//especially 64 bit so implementing it here +const char *basename_dot="."; +char* +basename(char *path) +{ + char *p = path, *b = NULL; + int len = strlen(path); + + if (path == NULL) { + return (char*)basename_dot; + } + + // Not absolute path on windows + if (path[1] != ':') { + return path; + } + + // Trim trailing path seperators + if (path[len - 1] == '\\' || + path[len - 1] == '/' ) { + len--; + path[len] = '\0'; + } + + while (len) { + while((*p != '\\' || *p != '/') && len) { + p++; + len--; + } + p++; + b = p; + } + + return b; +} + +#endif \ No newline at end of file diff --git a/test_conformance/compatibility/test_common/harness/mingw_compat.h b/test_conformance/compatibility/test_common/harness/mingw_compat.h new file mode 100644 index 00000000..ab28f398 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/mingw_compat.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MINGW_COMPAT_H +#define MINGW_COMPAT_H + +#if defined(__MINGW32__) +char *basename(char *path); +#include + +#if defined(__MINGW64__) +//mingw-w64 doesnot have __mingw_aligned_malloc, instead it has _aligned_malloc +#define __mingw_aligned_malloc _aligned_malloc +#define __mingw_aligned_free _aligned_free +#include +#endif //(__MINGW64__) + +#endif //(__MINGW32__) +#endif // MINGW_COMPAT_H diff --git a/test_conformance/compatibility/test_common/harness/msvc9.c b/test_conformance/compatibility/test_common/harness/msvc9.c new file mode 100644 index 00000000..811c6654 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/msvc9.c @@ -0,0 +1,754 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#if defined(_WIN32) && defined (_MSC_VER) + +#include "compat.h" +#include +#include +#include +#include + + + +/////////////////////////////////////////////////////////////////// +// +// rint, rintf +// +/////////////////////////////////////////////////////////////////// + +float copysignf( float x, float y ) +{ + union{ cl_uint u; float f; }ux, uy; + + ux.f = x; + uy.f = y; + + ux.u = (ux.u & 0x7fffffffU) | (uy.u & 0x80000000U); + + return ux.f; +} + +double copysign( double x, double y ) +{ + union{ cl_ulong u; double f; }ux, uy; + + ux.f = x; + uy.f = y; + + ux.u = (ux.u & 0x7fffffffffffffffULL) | (uy.u & 0x8000000000000000ULL); + + return ux.f; +} + +long double copysignl( long double x, long double y ) +{ + union + { + long double f; + struct{ cl_ulong m; cl_ushort sexp; }u; + }ux, uy; + + ux.f = x; + uy.f = y; + + ux.u.sexp = (ux.u.sexp & 0x7fff) | (uy.u.sexp & 0x8000); + + return ux.f; +} + +float rintf(float x) +{ + float absx = fabsf(x); + + if( absx < 8388608.0f /* 0x1.0p23f */ ) + { + float magic = copysignf( 8388608.0f /* 0x1.0p23f */, x ); + float rounded = x + magic; + rounded -= magic; + x = copysignf( rounded, x ); + } + + return x; +} + +double rint(double x) +{ + double absx = fabs(x); + + if( absx < 4503599627370496.0 /* 0x1.0p52f */ ) + { + double magic = copysign( 4503599627370496.0 /* 0x1.0p52 */, x ); + double rounded = x + magic; + rounded -= magic; + x = copysign( rounded, x ); + } + + return x; +} + +long double rintl(long double x) +{ + double absx = fabs(x); + + if( absx < 9223372036854775808.0L /* 0x1.0p64f */ ) + { + long double magic = copysignl( 9223372036854775808.0L /* 0x1.0p63L */, x ); + long double rounded = x + magic; + rounded -= magic; + x = copysignl( rounded, x ); + } + + return x; +} + + +/////////////////////////////////////////////////////////////////// +// +// ilogb, ilogbf, ilogbl +// +/////////////////////////////////////////////////////////////////// +#ifndef FP_ILOGB0 + #define FP_ILOGB0 INT_MIN +#endif + +#ifndef FP_ILOGBNAN + #define FP_ILOGBNAN INT_MIN +#endif + +int ilogb (double x) +{ + union{ double f; cl_ulong u;} u; + u.f = x; + + cl_ulong absx = u.u & CL_LONG_MAX; + if( absx - 0x0001000000000000ULL >= 0x7ff0000000000000ULL - 0x0001000000000000ULL) + { + switch( absx ) + { + case 0: + return FP_ILOGB0; + case 0x7ff0000000000000ULL: + return INT_MAX; + default: + if( absx > 0x7ff0000000000000ULL ) + return FP_ILOGBNAN; + + // subnormal + u.u = absx | 0x3ff0000000000000ULL; + u.f -= 1.0; + return (u.u >> 52) - (1023 + 1022); + } + } + + return (absx >> 52) - 1023; +} + + +int ilogbf (float x) +{ + union{ float f; cl_uint u;} u; + u.f = x; + + cl_uint absx = u.u & 0x7fffffff; + if( absx - 0x00800000U >= 0x7f800000U - 0x00800000U) + { + switch( absx ) + { + case 0: + return FP_ILOGB0; + case 0x7f800000U: + return INT_MAX; + default: + if( absx > 0x7f800000 ) + return FP_ILOGBNAN; + + // subnormal + u.u = absx | 0x3f800000U; + u.f -= 1.0f; + return (u.u >> 23) - (127 + 126); + } + } + + return (absx >> 23) - 127; +} + +int ilogbl (long double x) +{ + union + { + long double f; + struct{ cl_ulong m; cl_ushort sexp; }u; + } u; + u.f = x; + + int exp = u.u.sexp & 0x7fff; + if( 0 == exp ) + { + if( 0 == u.u.m ) + return FP_ILOGB0; + + //subnormal + u.u.sexp = 0x3fff; + u.f -= 1.0f; + exp = u.u.sexp & 0x7fff; + + return exp - (0x3fff + 0x3ffe); + } + else if( 0x7fff == exp ) + { + if( u.u.m & CL_LONG_MAX ) + return FP_ILOGBNAN; + + return INT_MAX; + } + + return exp - 0x3fff; +} + + + +/////////////////////////////////////////////////////////////////// +// +// fmax, fmin, fmaxf, fminf +// +/////////////////////////////////////////////////////////////////// + +static void GET_BITS_SP32(float fx, unsigned int* ux) +{ + volatile union {float f; unsigned int u;} _bitsy; + _bitsy.f = (fx); + *ux = _bitsy.u; +} +/* static void GET_BITS_SP32(float fx, unsigned int* ux) */ +/* { */ +/* volatile union {float f; unsigned int i;} _bitsy; */ +/* _bitsy.f = (fx); */ +/* *ux = _bitsy.i; */ +/* } */ +static void PUT_BITS_SP32(unsigned int ux, float* fx) +{ + volatile union {float f; unsigned int u;} _bitsy; + _bitsy.u = (ux); + *fx = _bitsy.f; +} +/* static void PUT_BITS_SP32(unsigned int ux, float* fx) */ +/* { */ +/* volatile union {float f; unsigned int i;} _bitsy; */ +/* _bitsy.i = (ux); */ +/* *fx = _bitsy.f; */ +/* } */ +static void GET_BITS_DP64(double dx, unsigned __int64* lx) +{ + volatile union {double d; unsigned __int64 l;} _bitsy; + _bitsy.d = (dx); + *lx = _bitsy.l; +} +static void PUT_BITS_DP64(unsigned __int64 lx, double* dx) +{ + volatile union {double d; unsigned __int64 l;} _bitsy; + _bitsy.l = (lx); + *dx = _bitsy.d; +} + +#if 0 +int SIGNBIT_DP64(double x ) +{ + int hx; + _GET_HIGH_WORD(hx,x); + return((hx>>31)); +} +#endif + +/* fmax(x, y) returns the larger (more positive) of x and y. + NaNs are treated as missing values: if one argument is NaN, + the other argument is returned. If both arguments are NaN, + the first argument is returned. */ + +/* This works so long as the compiler knows that (x != x) means + that x is NaN; gcc does. */ +double fmax(double x, double y) +{ + if( isnan(y) ) + return x; + + return x >= y ? x : y; +} + + +/* fmin(x, y) returns the smaller (more negative) of x and y. + NaNs are treated as missing values: if one argument is NaN, + the other argument is returned. If both arguments are NaN, + the first argument is returned. */ + +double fmin(double x, double y) +{ + if( isnan(y) ) + return x; + + return x <= y ? x : y; +} + + +float fmaxf( float x, float y ) +{ + if( isnan(y) ) + return x; + + return x >= y ? x : y; +} + +/* fminf(x, y) returns the smaller (more negative) of x and y. + NaNs are treated as missing values: if one argument is NaN, + the other argument is returned. If both arguments are NaN, + the first argument is returned. */ + +float fminf(float x, float y) +{ + if( isnan(y) ) + return x; + + return x <= y ? x : y; +} + +long double scalblnl(long double x, long n) +{ + union + { + long double d; + struct{ cl_ulong m; cl_ushort sexp;}u; + }u; + u.u.m = CL_LONG_MIN; + + if( x == 0.0L || n < -2200) + return copysignl( 0.0L, x ); + + if( n > 2200 ) + return INFINITY; + + if( n < 0 ) + { + u.u.sexp = 0x3fff - 1022; + while( n <= -1022 ) + { + x *= u.d; + n += 1022; + } + u.u.sexp = 0x3fff + n; + x *= u.d; + return x; + } + + if( n > 0 ) + { + u.u.sexp = 0x3fff + 1023; + while( n >= 1023 ) + { + x *= u.d; + n -= 1023; + } + u.u.sexp = 0x3fff + n; + x *= u.d; + return x; + } + + return x; +} + +/////////////////////////////////////////////////////////////////// +// +// log2 +// +/////////////////////////////////////////////////////////////////// +const static cl_double log_e_base2 = 1.4426950408889634074; +const static cl_double log_10_base2 = 3.3219280948873623478; + +//double log10(double x); + +double log2(double x) +{ + return 1.44269504088896340735992468100189214 * log(x); +} + +long double log2l(long double x) +{ + return 1.44269504088896340735992468100189214L * log(x); +} + +/////////////////////////////////////////////////////////////////// +// +// misc functions +// +/////////////////////////////////////////////////////////////////// + +/* +// This function is commented out because the Windows implementation should never call munmap. +// If it is calling it, we have a bug. Please file a bugzilla. +int munmap(void *addr, size_t len) +{ +// FIXME: this is not correct. munmap is like free() http://www.opengroup.org/onlinepubs/7990989775/xsh/munmap.html + + return (int)VirtualAlloc( (LPVOID)addr, len, + MEM_COMMIT|MEM_RESERVE, PAGE_NOACCESS ); +} +*/ + +uint64_t ReadTime( void ) +{ + LARGE_INTEGER current; + QueryPerformanceCounter(¤t); + return (uint64_t)current.QuadPart; +} + +double SubtractTime( uint64_t endTime, uint64_t startTime ) +{ + static double PerformanceFrequency = 0.0; + + if (PerformanceFrequency == 0.0) { + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + PerformanceFrequency = (double) frequency.QuadPart; + } + + return (double)(endTime - startTime) / PerformanceFrequency * 1e9; +} + +float make_nan() +{ +/* This is the IEEE 754 single-precision format: + unsigned int mantissa: 22; + unsigned int quiet_nan: 1; + unsigned int exponent: 8; + unsigned int negative: 1; +*/ + //const static unsigned + static const int32_t _nan = 0x7fc00000; + return *(const float*)(&_nan); +} + +float nanf( const char* str) +{ + cl_uint u = atoi( str ); + u |= 0x7fc00000U; + return *( float*)(&u); +} + + +double nan( const char* str) +{ + cl_ulong u = atoi( str ); + u |= 0x7ff8000000000000ULL; + return *( double*)(&u); +} + +// double check this implementatation +long double nanl( const char* str) +{ + union + { + long double f; + struct { cl_ulong m; cl_ushort sexp; }u; + }u; + u.u.sexp = 0x7fff; + u.u.m = 0x8000000000000000ULL | atoi( str ); + + return u.f; +} + +double trunc(double x) +{ + double absx = fabs(x); + + if( absx < 4503599627370496.0 /* 0x1.0p52f */ ) + { + cl_long rounded = x; + x = copysign( (double) rounded, x ); + } + + return x; +} + +float truncf(float x) +{ + float absx = fabsf(x); + + if( absx < 8388608.0f /* 0x1.0p23f */ ) + { + cl_int rounded = x; + x = copysignf( (float) rounded, x ); + } + + return x; +} + +long lround(double x) +{ + double absx = fabs(x); + + if( absx < 0.5 ) + return 0; + + if( absx < 4503599627370496.0 /* 0x1.0p52 */) + { + absx += 0.5; + cl_long rounded = absx; + absx = rounded; + x = copysign( absx, x ); + } + + if( x >= (double) LONG_MAX ) + return LONG_MAX; + + return (long) x; +} + +long lroundf(float x) +{ + float absx = fabsf(x); + + if( absx < 0.5f ) + return 0; + + if( absx < 8388608.0f ) + { + absx += 0.5f; + cl_int rounded = absx; + absx = rounded; + x = copysignf( absx, x ); + } + + if( x >= (float) LONG_MAX ) + return LONG_MAX; + + return (long) x; +} + +double round(double x) +{ + double absx = fabs(x); + + if( absx < 0.5 ) + return copysign( 0.0, x); + + if( absx < 4503599627370496.0 /* 0x1.0p52 */) + { + absx += 0.5; + cl_long rounded = absx; + absx = rounded; + x = copysign( absx, x ); + } + + return x; +} + +float roundf(float x) +{ + float absx = fabsf(x); + + if( absx < 0.5f ) + return copysignf( 0.0f, x); + + if( absx < 8388608.0f ) + { + absx += 0.5f; + cl_int rounded = absx; + absx = rounded; + x = copysignf( absx, x ); + } + + return x; +} + +long double roundl(long double x) +{ + long double absx = fabsl(x); + + if( absx < 0.5L ) + return copysignl( 0.0L, x); + + if( absx < 9223372036854775808.0L /*0x1.0p63L*/ ) + { + absx += 0.5L; + cl_ulong rounded = absx; + absx = rounded; + x = copysignl( absx, x ); + } + + return x; +} + +// Added in _MSC_VER == 1800 (Visual Studio 2013) +#if _MSC_VER < 1800 +int signbit(double x) +{ + union + { + double f; + cl_ulong u; + }u; + u.f = x; + return u.u >> 63; +} +#endif + +int signbitf(float x) +{ + union + { + float f; + cl_uint u; + }u; + u.f = x; + return u.u >> 31; +} + +float cbrtf( float x ) +{ + float z = pow( fabs((double) x), 1.0 / 3.0 ); + return copysignf( z, x ); +} + +double cbrt( double x ) +{ + return copysign( pow( fabs( x ), 1.0 / 3.0 ), x ); +} + +float int2float (int32_t ix) +{ + union { + float f; + int32_t i; + } u; + u.i = ix; + return u.f; +} + +int32_t float2int (float fx) +{ + union { + float f; + int32_t i; + } u; + u.f = fx; + return u.i; +} + +#if defined(_MSC_VER) && !defined(_WIN64) +/** Returns the number of leading 0-bits in x, + starting at the most significant bit position. + If x is 0, the result is undefined. +*/ +int __builtin_clz(unsigned int pattern) +{ +#if 0 + int res; + __asm { + mov eax, pattern + bsr eax, eax + mov res, eax + } + return 31 - res; +#endif + unsigned long index; + unsigned char res = _BitScanReverse( &index, pattern); + if (res) { + return 8*sizeof(int) - 1 - index; + } else { + return 8*sizeof(int); + } +} +#else +int __builtin_clz(unsigned int pattern) +{ + int count; + if (pattern == 0u) { + return 32; + } + count = 31; + if (pattern >= 1u<<16) { pattern >>= 16; count -= 16; } + if (pattern >= 1u<<8) { pattern >>= 8; count -= 8; } + if (pattern >= 1u<<4) { pattern >>= 4; count -= 4; } + if (pattern >= 1u<<2) { pattern >>= 2; count -= 2; } + if (pattern >= 1u<<1) { count -= 1; } + return count; +} + +#endif //defined(_MSC_VER) && !defined(_WIN64) + +#include +#include +long int lrint (double x) +{ + double absx = fabs(x); + + if( x >= (double) LONG_MAX ) + return LONG_MAX; + + if( absx < 4503599627370496.0 /* 0x1.0p52 */ ) + { + double magic = copysign( 4503599627370496.0 /* 0x1.0p52 */, x ); + double rounded = x + magic; + rounded -= magic; + return (long int) rounded; + } + + return (long int) x; +} + +long int lrintf (float x) +{ + float absx = fabsf(x); + + if( x >= (float) LONG_MAX ) + return LONG_MAX; + + if( absx < 8388608.0f /* 0x1.0p23f */ ) + { + float magic = copysignf( 8388608.0f /* 0x1.0p23f */, x ); + float rounded = x + magic; + rounded -= magic; + return (long int) rounded; + } + + return (long int) x; +} + +int usleep(int usec) +{ + Sleep((usec + 999) / 1000); + return 0; +} + +#if _MSC_VER < 1900 +int fetestexcept(int excepts) +{ + unsigned int status = _statusfp(); + return excepts & ( + ((status & _SW_INEXACT) ? FE_INEXACT : 0) | + ((status & _SW_UNDERFLOW) ? FE_UNDERFLOW : 0) | + ((status & _SW_OVERFLOW) ? FE_OVERFLOW : 0) | + ((status & _SW_ZERODIVIDE) ? FE_DIVBYZERO : 0) | + ((status & _SW_INVALID) ? FE_INVALID : 0) + ); +} + +int feclearexcept(int excepts) +{ + _clearfp(); + return 0; +} +#endif + +#endif //defined(_WIN32) diff --git a/test_conformance/compatibility/test_common/harness/mt19937.c b/test_conformance/compatibility/test_common/harness/mt19937.c new file mode 100644 index 00000000..75b76a74 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/mt19937.c @@ -0,0 +1,274 @@ +/* + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) + + Modifications for use in OpenCL by Ian Ollmann, Apple Inc. + +*/ + +#include +#include +#include "mt19937.h" +#include "mingw_compat.h" + +#ifdef __SSE2__ + #include +#endif + +static void * align_malloc(size_t size, size_t alignment) +{ +#if defined(_WIN32) && defined(_MSC_VER) + return _aligned_malloc(size, alignment); +#elif defined(__linux__) || defined (linux) || defined(__APPLE__) + void * ptr = NULL; + if (0 == posix_memalign(&ptr, alignment, size)) + return ptr; + return NULL; +#elif defined(__MINGW32__) + return __mingw_aligned_malloc(size, alignment); +#else + #error "Please add support OS for aligned malloc" +#endif +} + +static void align_free(void * ptr) +{ +#if defined(_WIN32) && defined(_MSC_VER) + _aligned_free(ptr); +#elif defined(__linux__) || defined (linux) || defined(__APPLE__) + return free(ptr); +#elif defined(__MINGW32__) + return __mingw_aligned_free(ptr); +#else + #error "Please add support OS for aligned free" +#endif +} + + +/* Period parameters */ +#define N 624 /* vector code requires multiple of 4 here */ +#define M 397 +#define MATRIX_A (cl_uint) 0x9908b0dfUL /* constant vector a */ +#define UPPER_MASK (cl_uint) 0x80000000UL /* most significant w-r bits */ +#define LOWER_MASK (cl_uint) 0x7fffffffUL /* least significant r bits */ + +typedef struct _MTdata +{ + cl_uint mt[N]; +#ifdef __SSE2__ + cl_uint cache[N]; +#endif + cl_int mti; +}_MTdata; + +/* initializes mt[N] with a seed */ +MTdata init_genrand(cl_uint s) +{ + MTdata r = (MTdata) align_malloc( sizeof( _MTdata ), 16 ); + if( NULL != r ) + { + cl_uint *mt = r->mt; + int mti = 0; + mt[0]= s; // & 0xffffffffUL; + for (mti=1; mti> 30)) + mti); + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array mt[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + // mt[mti] &= 0xffffffffUL; + /* for >32 bit machines */ + } + r->mti = mti; + } + + return r; +} + +void free_mtdata( MTdata d ) +{ + if(d) + align_free(d); +} + +/* generates a random number on [0,0xffffffff]-interval */ +cl_uint genrand_int32( MTdata d) +{ + /* mag01[x] = x * MATRIX_A for x=0,1 */ + static const cl_uint mag01[2]={0x0UL, MATRIX_A}; +#ifdef __SSE2__ + static volatile int init = 0; + static union{ __m128i v; cl_uint s[4]; } upper_mask, lower_mask, one, matrix_a, c0, c1; +#endif + + + cl_uint *mt = d->mt; + cl_uint y; + + if (d->mti == N) + { /* generate N words at one time */ + int kk; + +#ifdef __SSE2__ + if( 0 == init ) + { + upper_mask.s[0] = upper_mask.s[1] = upper_mask.s[2] = upper_mask.s[3] = UPPER_MASK; + lower_mask.s[0] = lower_mask.s[1] = lower_mask.s[2] = lower_mask.s[3] = LOWER_MASK; + one.s[0] = one.s[1] = one.s[2] = one.s[3] = 1; + matrix_a.s[0] = matrix_a.s[1] = matrix_a.s[2] = matrix_a.s[3] = MATRIX_A; + c0.s[0] = c0.s[1] = c0.s[2] = c0.s[3] = (cl_uint) 0x9d2c5680UL; + c1.s[0] = c1.s[1] = c1.s[2] = c1.s[3] = (cl_uint) 0xefc60000UL; + init = 1; + } +#endif + + kk = 0; +#ifdef __SSE2__ + // vector loop + for( ; kk + 4 <= N-M; kk += 4 ) + { + __m128i vy = _mm_or_si128( _mm_and_si128( _mm_load_si128( (__m128i*)(mt + kk) ), upper_mask.v ), + _mm_and_si128( _mm_loadu_si128( (__m128i*)(mt + kk + 1) ), lower_mask.v )); // ((mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK)) + + __m128i mask = _mm_cmpeq_epi32( _mm_and_si128( vy, one.v), one.v ); // y & 1 ? -1 : 0 + __m128i vmag01 = _mm_and_si128( mask, matrix_a.v ); // y & 1 ? MATRIX_A, 0 = mag01[y & (cl_uint) 0x1UL] + __m128i vr = _mm_xor_si128( _mm_loadu_si128( (__m128i*)(mt + kk + M)), (__m128i) _mm_srli_epi32( vy, 1 ) ); // mt[kk+M] ^ (y >> 1) + vr = _mm_xor_si128( vr, vmag01 ); // mt[kk+M] ^ (y >> 1) ^ mag01[y & (cl_uint) 0x1UL] + _mm_store_si128( (__m128i*) (mt + kk ), vr ); + } +#endif + for ( ;kk> 1) ^ mag01[y & (cl_uint) 0x1UL]; + } + +#ifdef __SSE2__ + // advance to next aligned location + for (;kk> 1) ^ mag01[y & (cl_uint) 0x1UL]; + } + + // vector loop + for( ; kk + 4 <= N-1; kk += 4 ) + { + __m128i vy = _mm_or_si128( _mm_and_si128( _mm_load_si128( (__m128i*)(mt + kk) ), upper_mask.v ), + _mm_and_si128( _mm_loadu_si128( (__m128i*)(mt + kk + 1) ), lower_mask.v )); // ((mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK)) + + __m128i mask = _mm_cmpeq_epi32( _mm_and_si128( vy, one.v), one.v ); // y & 1 ? -1 : 0 + __m128i vmag01 = _mm_and_si128( mask, matrix_a.v ); // y & 1 ? MATRIX_A, 0 = mag01[y & (cl_uint) 0x1UL] + __m128i vr = _mm_xor_si128( _mm_loadu_si128( (__m128i*)(mt + kk + M - N)), _mm_srli_epi32( vy, 1 ) ); // mt[kk+M-N] ^ (y >> 1) + vr = _mm_xor_si128( vr, vmag01 ); // mt[kk+M] ^ (y >> 1) ^ mag01[y & (cl_uint) 0x1UL] + _mm_store_si128( (__m128i*) (mt + kk ), vr ); + } +#endif + + for (;kk> 1) ^ mag01[y & (cl_uint) 0x1UL]; + } + y = (cl_uint)((mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK)); + mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & (cl_uint) 0x1UL]; + +#ifdef __SSE2__ + // Do the tempering ahead of time in vector code + for( kk = 0; kk + 4 <= N; kk += 4 ) + { + __m128i vy = _mm_load_si128( (__m128i*)(mt + kk ) ); // y = mt[k]; + vy = _mm_xor_si128( vy, _mm_srli_epi32( vy, 11 ) ); // y ^= (y >> 11); + vy = _mm_xor_si128( vy, _mm_and_si128( _mm_slli_epi32( vy, 7 ), c0.v) ); // y ^= (y << 7) & (cl_uint) 0x9d2c5680UL; + vy = _mm_xor_si128( vy, _mm_and_si128( _mm_slli_epi32( vy, 15 ), c1.v) ); // y ^= (y << 15) & (cl_uint) 0xefc60000UL; + vy = _mm_xor_si128( vy, _mm_srli_epi32( vy, 18 ) ); // y ^= (y >> 18); + _mm_store_si128( (__m128i*)(d->cache+kk), vy ); + } +#endif + + d->mti = 0; + } +#ifdef __SSE2__ + y = d->cache[d->mti++]; +#else + y = mt[d->mti++]; + + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & (cl_uint) 0x9d2c5680UL; + y ^= (y << 15) & (cl_uint) 0xefc60000UL; + y ^= (y >> 18); +#endif + + + return y; +} + +cl_ulong genrand_int64( MTdata d) +{ + return ((cl_ulong) genrand_int32(d) << 32) | (cl_uint) genrand_int32(d); +} + +/* generates a random number on [0,1]-real-interval */ +double genrand_real1(MTdata d) +{ + return genrand_int32(d)*(1.0/4294967295.0); + /* divided by 2^32-1 */ +} + +/* generates a random number on [0,1)-real-interval */ +double genrand_real2(MTdata d) +{ + return genrand_int32(d)*(1.0/4294967296.0); + /* divided by 2^32 */ +} + +/* generates a random number on (0,1)-real-interval */ +double genrand_real3(MTdata d) +{ + return (((double)genrand_int32(d)) + 0.5)*(1.0/4294967296.0); + /* divided by 2^32 */ +} + +/* generates a random number on [0,1) with 53-bit resolution*/ +double genrand_res53(MTdata d) +{ + unsigned long a=genrand_int32(d)>>5, b=genrand_int32(d)>>6; + return(a*67108864.0+b)*(1.0/9007199254740992.0); +} diff --git a/test_conformance/compatibility/test_common/harness/mt19937.h b/test_conformance/compatibility/test_common/harness/mt19937.h new file mode 100644 index 00000000..d05beed1 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/mt19937.h @@ -0,0 +1,99 @@ + +/* + * mt19937.h + * + * Mersenne Twister. + * + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) + */ + +#ifndef MT19937_H +#define MT19937_H 1 + +#if defined( __APPLE__ ) + #include +#else + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* + * Interfaces here have been modified from original sources so that they + * are safe to call reentrantly, so long as a different MTdata is used + * on each thread. + */ + +typedef struct _MTdata *MTdata; + +/* Create the random number generator with seed */ +MTdata init_genrand( cl_uint /*seed*/ ); + +/* release memory used by a MTdata private data */ +void free_mtdata( MTdata /*data*/ ); + +/* generates a random number on [0,0xffffffff]-interval */ +cl_uint genrand_int32( MTdata /*data*/); + +/* generates a random number on [0,0xffffffffffffffffULL]-interval */ +cl_ulong genrand_int64( MTdata /*data*/); + +/* generates a random number on [0,1]-real-interval */ +double genrand_real1( MTdata /*data*/); + +/* generates a random number on [0,1)-real-interval */ +double genrand_real2( MTdata /*data*/); + +/* generates a random number on (0,1)-real-interval */ +double genrand_real3( MTdata /*data*/); + +/* generates a random number on [0,1) with 53-bit resolution*/ +double genrand_res53( MTdata /*data*/ ); + + +#ifdef __cplusplus + } +#endif + +#endif /* MT19937_H */ diff --git a/test_conformance/compatibility/test_common/harness/ref_counting.h b/test_conformance/compatibility/test_common/harness/ref_counting.h new file mode 100644 index 00000000..1a2aceee --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/ref_counting.h @@ -0,0 +1,49 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _ref_counting_h +#define _ref_counting_h + +#define MARK_REF_COUNT_BASE( c, type, bigType ) \ + cl_uint c##_refCount; \ + error = clGet##type##Info( c, CL_##bigType##_REFERENCE_COUNT, sizeof( c##_refCount ), &c##_refCount, NULL ); \ + test_error( error, "Unable to check reference count for " #type ); + +#define TEST_REF_COUNT_BASE( c, type, bigType ) \ + cl_uint c##_refCount_new; \ + error = clGet##type##Info( c, CL_##bigType##_REFERENCE_COUNT, sizeof( c##_refCount_new ), &c##_refCount_new, NULL ); \ + test_error( error, "Unable to check reference count for " #type ); \ + if( c##_refCount != c##_refCount_new ) \ + { \ + log_error( "ERROR: Reference count for " #type " changed! (was %d, now %d)\n", c##_refCount, c##_refCount_new ); \ + return -1; \ + } + +#define MARK_REF_COUNT_CONTEXT( c ) MARK_REF_COUNT_BASE( c, Context, CONTEXT ) +#define TEST_REF_COUNT_CONTEXT( c ) TEST_REF_COUNT_BASE( c, Context, CONTEXT ) + +#define MARK_REF_COUNT_DEVICE( c ) MARK_REF_COUNT_BASE( c, Device, DEVICE ) +#define TEST_REF_COUNT_DEVICE( c ) TEST_REF_COUNT_BASE( c, Device, DEVICE ) + +#define MARK_REF_COUNT_QUEUE( c ) MARK_REF_COUNT_BASE( c, CommandQueue, QUEUE ) +#define TEST_REF_COUNT_QUEUE( c ) TEST_REF_COUNT_BASE( c, CommandQueue, QUEUE ) + +#define MARK_REF_COUNT_PROGRAM( c ) MARK_REF_COUNT_BASE( c, Program, PROGRAM ) +#define TEST_REF_COUNT_PROGRAM( c ) TEST_REF_COUNT_BASE( c, Program, PROGRAM ) + +#define MARK_REF_COUNT_MEM( c ) MARK_REF_COUNT_BASE( c, MemObject, MEM ) +#define TEST_REF_COUNT_MEM( c ) TEST_REF_COUNT_BASE( c, MemObject, MEM ) + +#endif // _ref_counting_h diff --git a/test_conformance/compatibility/test_common/harness/rounding_mode.c b/test_conformance/compatibility/test_common/harness/rounding_mode.c new file mode 100644 index 00000000..f77da958 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/rounding_mode.c @@ -0,0 +1,175 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "rounding_mode.h" + +#if !(defined(_WIN32) && defined(_MSC_VER)) +RoundingMode set_round( RoundingMode r, Type outType ) +{ + static const int flt_rounds[ kRoundingModeCount ] = { FE_TONEAREST, FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO }; + static const int int_rounds[ kRoundingModeCount ] = { FE_TOWARDZERO, FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO }; + const int *p = int_rounds; + if( outType == kfloat || outType == kdouble ) + p = flt_rounds; + int oldRound = fegetround(); + fesetround( p[r] ); + + switch( oldRound ) + { + case FE_TONEAREST: + return kRoundToNearestEven; + case FE_UPWARD: + return kRoundUp; + case FE_DOWNWARD: + return kRoundDown; + case FE_TOWARDZERO: + return kRoundTowardZero; + default: + abort(); // ??! + } + return kDefaultRoundingMode; //never happens +} + +RoundingMode get_round( void ) +{ + int oldRound = fegetround(); + + switch( oldRound ) + { + case FE_TONEAREST: + return kRoundToNearestEven; + case FE_UPWARD: + return kRoundUp; + case FE_DOWNWARD: + return kRoundDown; + case FE_TOWARDZERO: + return kRoundTowardZero; + } + + return kDefaultRoundingMode; +} + +#else +RoundingMode set_round( RoundingMode r, Type outType ) +{ + static const int flt_rounds[ kRoundingModeCount ] = { _RC_NEAR, _RC_NEAR, _RC_UP, _RC_DOWN, _RC_CHOP }; + static const int int_rounds[ kRoundingModeCount ] = { _RC_CHOP, _RC_NEAR, _RC_UP, _RC_DOWN, _RC_CHOP }; + const int *p = ( outType == kfloat || outType == kdouble )? flt_rounds : int_rounds; + unsigned int oldRound; + + int err = _controlfp_s(&oldRound, 0, 0); //get rounding mode into oldRound + if (err) { + vlog_error("\t\tERROR: -- cannot get rounding mode in %s:%d\n", __FILE__, __LINE__); + return kDefaultRoundingMode; //what else never happens + } + + oldRound &= _MCW_RC; + + RoundingMode old = + (oldRound == _RC_NEAR)? kRoundToNearestEven : + (oldRound == _RC_UP)? kRoundUp : + (oldRound == _RC_DOWN)? kRoundDown : + (oldRound == _RC_CHOP)? kRoundTowardZero: + kDefaultRoundingMode; + + _controlfp_s(&oldRound, p[r], _MCW_RC); //setting new rounding mode + return old; //returning old rounding mode +} + +RoundingMode get_round( void ) +{ + unsigned int oldRound; + + int err = _controlfp_s(&oldRound, 0, 0); //get rounding mode into oldRound + oldRound &= _MCW_RC; + return + (oldRound == _RC_NEAR)? kRoundToNearestEven : + (oldRound == _RC_UP)? kRoundUp : + (oldRound == _RC_DOWN)? kRoundDown : + (oldRound == _RC_CHOP)? kRoundTowardZero: + kDefaultRoundingMode; +} + +#endif + +// +// FlushToZero() sets the host processor into ftz mode. It is intended to have a remote effect on the behavior of the code in +// basic_test_conversions.c. Some host processors may not support this mode, which case you'll need to do some clamping in +// software by testing against FLT_MIN or DBL_MIN in that file. +// +// Note: IEEE-754 says conversions are basic operations. As such they do *NOT* have the behavior in section 7.5.3 of +// the OpenCL spec. They *ALWAYS* flush to zero for subnormal inputs or outputs when FTZ mode is on like other basic +// operators do (e.g. add, subtract, multiply, divide, etc.) +// +// Configuring hardware to FTZ mode varies by platform. +// CAUTION: Some C implementations may also fail to behave properly in this mode. +// +// On PowerPC, it is done by setting the FPSCR into non-IEEE mode. +// On Intel, you can do this by turning on the FZ and DAZ bits in the MXCSR -- provided that SSE/SSE2 +// is used for floating point computation! If your OS uses x87, you'll need to figure out how +// to turn that off for the conversions code in basic_test_conversions.c so that they flush to +// zero properly. Otherwise, you'll need to add appropriate software clamping to basic_test_conversions.c +// in which case, these function are at liberty to do nothing. +// +#if defined( __i386__ ) || defined( __x86_64__ ) || defined (_WIN32) + #include +#elif defined( __PPC__ ) + #include +#endif +void *FlushToZero( void ) +{ +#if defined( __APPLE__ ) || defined(__linux__) || defined (_WIN32) + #if defined( __i386__ ) || defined( __x86_64__ ) || defined(_MSC_VER) + union{ int i; void *p; }u = { _mm_getcsr() }; + _mm_setcsr( u.i | 0x8040 ); + return u.p; + #elif defined( __arm__ ) || defined(__aarch64__) + // processor is already in FTZ mode -- do nothing + return NULL; + #elif defined( __PPC__ ) + fpu_control_t flags = 0; + _FPU_GETCW(flags); + flags |= _FPU_MASK_NI; + _FPU_SETCW(flags); + return NULL; + #else + #error Unknown arch + #endif +#else + #error Please configure FlushToZero and UnFlushToZero to behave properly on this operating system. +#endif +} + +// Undo the effects of FlushToZero above, restoring the host to default behavior, using the information passed in p. +void UnFlushToZero( void *p) +{ +#if defined( __APPLE__ ) || defined(__linux__) || defined (_WIN32) + #if defined( __i386__ ) || defined( __x86_64__ ) || defined(_MSC_VER) + union{ void *p; int i; }u = { p }; + _mm_setcsr( u.i ); + #elif defined( __arm__ ) || defined(__aarch64__) + // processor is already in FTZ mode -- do nothing + #elif defined( __PPC__) + fpu_control_t flags = 0; + _FPU_GETCW(flags); + flags &= ~_FPU_MASK_NI; + _FPU_SETCW(flags); + #else + #error Unknown arch + #endif +#else + #error Please configure FlushToZero and UnFlushToZero to behave properly on this operating system. +#endif +} diff --git a/test_conformance/compatibility/test_common/harness/rounding_mode.h b/test_conformance/compatibility/test_common/harness/rounding_mode.h new file mode 100644 index 00000000..837ec687 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/rounding_mode.h @@ -0,0 +1,71 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef __ROUNDING_MODE_H__ +#define __ROUNDING_MODE_H__ + +#include "compat.h" + +#include + +#if (defined(_WIN32) && defined (_MSC_VER)) +#include "errorHelpers.h" +#include "testHarness.h" +#endif + +typedef enum +{ + kDefaultRoundingMode = 0, + kRoundToNearestEven, + kRoundUp, + kRoundDown, + kRoundTowardZero, + + kRoundingModeCount +}RoundingMode; + +typedef enum +{ + kuchar = 0, + kchar = 1, + kushort = 2, + kshort = 3, + kuint = 4, + kint = 5, + kfloat = 6, + kdouble = 7, + kulong = 8, + klong = 9, + + //This goes last + kTypeCount +}Type; + +#ifdef __cplusplus +extern "C" { +#endif + +extern RoundingMode set_round( RoundingMode r, Type outType ); +extern RoundingMode get_round( void ); +extern void *FlushToZero( void ); +extern void UnFlushToZero( void *p); + +#ifdef __cplusplus +} +#endif + + + +#endif /* __ROUNDING_MODE_H__ */ diff --git a/test_conformance/compatibility/test_common/harness/testHarness.c b/test_conformance/compatibility/test_common/harness/testHarness.c new file mode 100644 index 00000000..1994399d --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/testHarness.c @@ -0,0 +1,842 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testHarness.h" +#include "compat.h" +#include +#include + +#if !defined(_WIN32) +#include +#endif + +#include +#include "threadTesting.h" +#include "errorHelpers.h" +#include "kernelHelpers.h" +#include "fpcontrol.h" + +#if !defined(_WIN32) +#include +#endif + +#include + +#if !defined (__APPLE__) +#include +#endif + +int gTestsPassed = 0; +int gTestsFailed = 0; +cl_uint gRandomSeed = 0; +cl_uint gReSeed = 0; + +int gFlushDenormsToZero = 0; +int gInfNanSupport = 1; +int gIsEmbedded = 0; +int gIsOpenCL_C_1_0_Device = 0; +int gIsOpenCL_1_0_Device = 0; +int gHasLong = 1; + +#define DEFAULT_NUM_ELEMENTS 0x4000 + +int runTestHarness( int argc, const char *argv[], unsigned int num_fns, + basefn fnList[], const char *fnNames[], + int imageSupportRequired, int forceNoContextCreation, cl_command_queue_properties queueProps ) +{ + return runTestHarnessWithCheck( argc, argv, num_fns, fnList, fnNames, imageSupportRequired, forceNoContextCreation, queueProps, + ( imageSupportRequired ) ? verifyImageSupport : NULL ); +} + +int runTestHarnessWithCheck( int argc, const char *argv[], unsigned int num_fns, + basefn fnList[], const char *fnNames[], + int imageSupportRequired, int forceNoContextCreation, cl_command_queue_properties queueProps, + DeviceCheckFn deviceCheckFn ) +{ + test_start(); + log_info("*** Compatibility with Previous Versions test ***\n"); + + cl_device_type device_type = CL_DEVICE_TYPE_DEFAULT; + cl_uint num_platforms = 0; + cl_platform_id *platforms; + cl_device_id device; + int num_elements = DEFAULT_NUM_ELEMENTS; + cl_uint num_devices = 0; + cl_device_id *devices = NULL; + cl_uint choosen_device_index = 0; + cl_uint choosen_platform_index = 0; + + int err, ret; + char *endPtr; + unsigned int i; + int based_on_env_var = 0; + + + /* Check for environment variable to set device type */ + char *env_mode = getenv( "CL_DEVICE_TYPE" ); + if( env_mode != NULL ) + { + based_on_env_var = 1; + if( strcmp( env_mode, "gpu" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_GPU" ) == 0 ) + device_type = CL_DEVICE_TYPE_GPU; + else if( strcmp( env_mode, "cpu" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_CPU" ) == 0 ) + device_type = CL_DEVICE_TYPE_CPU; + else if( strcmp( env_mode, "accelerator" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + device_type = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( env_mode, "default" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + device_type = CL_DEVICE_TYPE_DEFAULT; + else + { + log_error( "Unknown CL_DEVICE_TYPE env variable setting: %s.\nAborting...\n", env_mode ); + abort(); + } + } + +#if defined( __APPLE__ ) + { + // report on any unusual library search path indirection + char *libSearchPath = getenv( "DYLD_LIBRARY_PATH"); + if( libSearchPath ) + log_info( "*** DYLD_LIBRARY_PATH = \"%s\"\n", libSearchPath ); + + // report on any unusual framework search path indirection + char *frameworkSearchPath = getenv( "DYLD_FRAMEWORK_PATH"); + if( libSearchPath ) + log_info( "*** DYLD_FRAMEWORK_PATH = \"%s\"\n", frameworkSearchPath ); + } +#endif + + env_mode = getenv( "CL_DEVICE_INDEX" ); + if( env_mode != NULL ) + { + choosen_device_index = atoi(env_mode); + } + + env_mode = getenv( "CL_PLATFORM_INDEX" ); + if( env_mode != NULL ) + { + choosen_platform_index = atoi(env_mode); + } + + /* Process the command line arguments */ + + /* Special case: just list the tests */ + if( ( argc > 1 ) && (!strcmp( argv[ 1 ], "-list" ) || !strcmp( argv[ 1 ], "-h" ) || !strcmp( argv[ 1 ], "--help" ))) + { + log_info( "Usage: %s [*] [pid] [id] []\n", argv[0] ); + log_info( "\t\tOne or more of: (wildcard character '*') (default *)\n"); + log_info( "\tpid\t\tIndicates platform at index should be used (default 0).\n" ); + log_info( "\tid\t\tIndicates device at index should be used (default 0).\n" ); + log_info( "\t\tcpu|gpu|accelerator| (default CL_DEVICE_TYPE_DEFAULT)\n" ); + + for( i = 0; i < num_fns - 1; i++ ) + { + log_info( "\t\t%s\n", fnNames[ i ] ); + } + test_finish(); + return 0; + } + + /* How are we supposed to seed the random # generators? */ + if( argc > 1 && strcmp( argv[ argc - 1 ], "randomize" ) == 0 ) + { + log_info(" Initializing random seed based on the clock.\n"); + gRandomSeed = (unsigned)clock(); + gReSeed = 1; + argc--; + } + else + { + log_info(" Initializing random seed to 0.\n"); + } + + /* Do we have an integer to specify the number of elements to pass to tests? */ + if( argc > 1 ) + { + ret = (int)strtol( argv[ argc - 1 ], &endPtr, 10 ); + if( endPtr != argv[ argc - 1 ] && *endPtr == 0 ) + { + /* By spec, this means the entire string was a valid integer, so we treat it as a num_elements spec */ + /* (hence why we stored the result in ret first) */ + num_elements = ret; + log_info( "Testing with num_elements of %d\n", num_elements ); + argc--; + } + } + + /* Do we have a CPU/GPU specification? */ + if( argc > 1 ) + { + if( strcmp( argv[ argc - 1 ], "gpu" ) == 0 || strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_GPU" ) == 0 ) + { + device_type = CL_DEVICE_TYPE_GPU; + argc--; + } + else if( strcmp( argv[ argc - 1 ], "cpu" ) == 0 || strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_CPU" ) == 0 ) + { + device_type = CL_DEVICE_TYPE_CPU; + argc--; + } + else if( strcmp( argv[ argc - 1 ], "accelerator" ) == 0 || strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + { + device_type = CL_DEVICE_TYPE_ACCELERATOR; + argc--; + } + else if( strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + { + device_type = CL_DEVICE_TYPE_DEFAULT; + argc--; + } + } + + /* Did we choose a specific device index? */ + if( argc > 1 ) + { + if( strlen( argv[ argc - 1 ] ) >= 3 && argv[ argc - 1 ][0] == 'i' && argv[ argc - 1 ][1] == 'd' ) + { + choosen_device_index = atoi( &(argv[ argc - 1 ][2]) ); + argc--; + } + } + + /* Did we choose a specific platform index? */ + if( argc > 1 ) + { + if( strlen( argv[ argc - 1 ] ) >= 3 && argv[ argc - 1 ][0] == 'p' && argv[ argc - 1 ][1] == 'i' && argv[ argc - 1 ][2] == 'd') + { + choosen_platform_index = atoi( &(argv[ argc - 1 ][3]) ); + argc--; + } + } + + switch( device_type ) + { + case CL_DEVICE_TYPE_GPU: log_info( "Requesting GPU device " ); break; + case CL_DEVICE_TYPE_CPU: log_info( "Requesting CPU device " ); break; + case CL_DEVICE_TYPE_ACCELERATOR: log_info( "Requesting Accelerator device " ); break; + case CL_DEVICE_TYPE_DEFAULT: log_info( "Requesting Default device " ); break; + default: log_error( "Requesting unknown device "); return -1; + } + log_info( based_on_env_var ? "based on environment variable " : "based on command line " ); + log_info( "for platform index %d and device index %d\n", choosen_platform_index, choosen_device_index); + +#if defined( __APPLE__ ) +#if defined( __i386__ ) || defined( __x86_64__ ) +#define kHasSSE3 0x00000008 +#define kHasSupplementalSSE3 0x00000100 +#define kHasSSE4_1 0x00000400 +#define kHasSSE4_2 0x00000800 + /* check our environment for a hint to disable SSE variants */ + { + const char *env = getenv( "CL_MAX_SSE" ); + if( env ) + { + extern int _cpu_capabilities; + int mask = 0; + if( 0 == strcasecmp( env, "SSE4.1" ) ) + mask = kHasSSE4_2; + else if( 0 == strcasecmp( env, "SSSE3" ) ) + mask = kHasSSE4_2 | kHasSSE4_1; + else if( 0 == strcasecmp( env, "SSE3" ) ) + mask = kHasSSE4_2 | kHasSSE4_1 | kHasSupplementalSSE3; + else if( 0 == strcasecmp( env, "SSE2" ) ) + mask = kHasSSE4_2 | kHasSSE4_1 | kHasSupplementalSSE3 | kHasSSE3; + else + { + log_error( "Error: Unknown CL_MAX_SSE setting: %s\n", env ); + return -2; + } + + log_info( "*** Environment: CL_MAX_SSE = %s ***\n", env ); + _cpu_capabilities &= ~mask; + } + } +#endif +#endif + + /* Get the platform */ + err = clGetPlatformIDs(0, NULL, &num_platforms); + if (err) { + print_error(err, "clGetPlatformIDs failed"); + test_finish(); + return -1; + } + + platforms = (cl_platform_id *) malloc( num_platforms * sizeof( cl_platform_id ) ); + if (!platforms || choosen_platform_index >= num_platforms) { + log_error( "platform index out of range -- choosen_platform_index (%d) >= num_platforms (%d)\n", choosen_platform_index, num_platforms ); + test_finish(); + return -1; + } + + err = clGetPlatformIDs(num_platforms, platforms, NULL); + if (err) { + print_error(err, "clGetPlatformIDs failed"); + test_finish(); + return -1; + } + + /* Get the number of requested devices */ + err = clGetDeviceIDs(platforms[choosen_platform_index], device_type, 0, NULL, &num_devices ); + if (err) { + print_error(err, "clGetDeviceIDs failed"); + test_finish(); + return -1; + } + + devices = (cl_device_id *) malloc( num_devices * sizeof( cl_device_id ) ); + if (!devices || choosen_device_index >= num_devices) { + log_error( "device index out of range -- choosen_device_index (%d) >= num_devices (%d)\n", choosen_device_index, num_devices ); + test_finish(); + return -1; + } + + /* Get the requested device */ + err = clGetDeviceIDs(platforms[choosen_platform_index], device_type, num_devices, devices, NULL ); + if (err) { + print_error(err, "clGetDeviceIDs failed"); + test_finish(); + return -1; + } + + device = devices[choosen_device_index]; + free(devices); + devices = NULL; + free(platforms); + platforms = NULL; + + if( printDeviceHeader( device ) != CL_SUCCESS ) + { + test_finish(); + return -1; + } + + cl_device_fp_config fpconfig = 0; + err = clGetDeviceInfo( device, CL_DEVICE_SINGLE_FP_CONFIG, sizeof( fpconfig ), &fpconfig, NULL ); + if (err) { + print_error(err, "clGetDeviceInfo for CL_DEVICE_SINGLE_FP_CONFIG failed"); + test_finish(); + return -1; + } + + gFlushDenormsToZero = ( 0 == (fpconfig & CL_FP_DENORM)); + log_info( "Supports single precision denormals: %s\n", gFlushDenormsToZero ? "NO" : "YES" ); + log_info( "sizeof( void*) = %d (host)\n", (int) sizeof( void* ) ); + + //detect whether profile of the device is embedded + char profile[1024] = ""; + err = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL); + if (err) + { + print_error(err, "clGetDeviceInfo for CL_DEVICE_PROFILE failed\n" ); + test_finish(); + return -1; + } + gIsEmbedded = NULL != strstr(profile, "EMBEDDED_PROFILE"); + + //detect the floating point capabilities + cl_device_fp_config floatCapabilities = 0; + err = clGetDeviceInfo(device, CL_DEVICE_SINGLE_FP_CONFIG, sizeof(floatCapabilities), &floatCapabilities, NULL); + if (err) + { + print_error(err, "clGetDeviceInfo for CL_DEVICE_SINGLE_FP_CONFIG failed\n"); + test_finish(); + return -1; + } + + // Check for problems that only embedded will have + if( gIsEmbedded ) + { + //If the device is embedded, we need to detect if the device supports Infinity and NaN + if ((floatCapabilities & CL_FP_INF_NAN) == 0) + gInfNanSupport = 0; + + // check the extensions list to see if ulong and long are supported + size_t extensionsStringSize = 0; + if( (err = clGetDeviceInfo( device, CL_DEVICE_EXTENSIONS, 0, NULL, &extensionsStringSize ) )) + { + print_error( err, "Unable to get extensions string size for embedded device" ); + test_finish(); + return -1; + } + char *extensions_string = (char*) malloc(extensionsStringSize); + if( NULL == extensions_string ) + { + print_error( CL_OUT_OF_HOST_MEMORY, "Unable to allocate storage for extensions string for embedded device" ); + test_finish(); + return -1; + } + + if( (err = clGetDeviceInfo( device, CL_DEVICE_EXTENSIONS, extensionsStringSize, extensions_string, NULL ) )) + { + print_error( err, "Unable to get extensions string for embedded device" ); + test_finish(); + return -1; + } + + if( extensions_string[extensionsStringSize-1] != '\0' ) + { + log_error( "FAILURE: extensions string for embedded device is not NUL terminated" ); + test_finish(); + return -1; + } + + if( NULL == strstr( extensions_string, "cles_khr_int64" )) + gHasLong = 0; + + free(extensions_string); + } + + if( getenv( "OPENCL_1_0_DEVICE" ) ) + { + char c_version[1024]; + gIsOpenCL_1_0_Device = 1; + memset( c_version, 0, sizeof( c_version ) ); + + if( (err = clGetDeviceInfo( device, CL_DEVICE_OPENCL_C_VERSION, sizeof(c_version), c_version, NULL )) ) + { + log_error( "FAILURE: unable to get CL_DEVICE_OPENCL_C_VERSION on 1.0 device. (%d)\n", err ); + test_finish(); + return -1; + } + + if( 0 == strncmp( c_version, "OpenCL C 1.0 ", strlen( "OpenCL C 1.0 " ) ) ) + { + gIsOpenCL_C_1_0_Device = 1; + log_info( "Device is a OpenCL C 1.0 device\n" ); + } + else + log_info( "Device is a OpenCL 1.0 device, but supports OpenCL C 1.1\n" ); + } + + cl_uint device_address_bits = 0; + if( (err = clGetDeviceInfo( device, CL_DEVICE_ADDRESS_BITS, sizeof( device_address_bits ), &device_address_bits, NULL ) )) + { + print_error( err, "Unable to obtain device address bits" ); + test_finish(); + return -1; + } + if( device_address_bits ) + log_info( "sizeof( void*) = %d (device)\n", device_address_bits/8 ); + else + { + log_error("Invalid device address bit size returned by device.\n"); + test_finish(); + return -1; + } + + + /* If we have a device checking function, run it */ + if( ( deviceCheckFn != NULL ) && deviceCheckFn( device ) != CL_SUCCESS ) + { + test_finish(); + return -1; + } + + if (num_elements <= 0) + num_elements = DEFAULT_NUM_ELEMENTS; + + // On most platforms which support denorm, default is FTZ off. However, + // on some hardware where the reference is computed, default might be flush denorms to zero e.g. arm. + // This creates issues in result verification. Since spec allows the implementation to either flush or + // not flush denorms to zero, an implementation may choose not be flush i.e. return denorm result whereas + // reference result may be zero (flushed denorm). Hence we need to disable denorm flushing on host side + // where reference is being computed to make sure we get non-flushed reference result. If implementation + // returns flushed result, we correctly take care of that in verification code. +#if defined(__APPLE__) && defined(__arm__) + FPU_mode_type oldMode; + DisableFTZ( &oldMode ); +#endif + + int error = parseAndCallCommandLineTests( argc, argv, device, num_fns, fnList, fnNames, forceNoContextCreation, queueProps, num_elements ); + + #if defined(__APPLE__) && defined(__arm__) + // Restore the old FP mode before leaving. + RestoreFPState( &oldMode ); +#endif + + return error; +} + +static int find_wildcard_matching_functions( const char *fnNames[], unsigned char fnsToCall[], unsigned int num_fns, + const char *wildcard ) +{ + int found_tests = 0; + size_t wildcard_length = strlen( wildcard ) - 1; /* -1 for the asterisk */ + + for( unsigned int fnIndex = 0; fnIndex < num_fns; fnIndex++ ) + { + if( strncmp( fnNames[ fnIndex ], wildcard, wildcard_length ) == 0 ) + { + if( fnsToCall[ fnIndex ] ) + { + log_error( "ERROR: Test '%s' has already been selected.\n", fnNames[ fnIndex ] ); + return EXIT_FAILURE; + } + + fnsToCall[ fnIndex ] = 1; + found_tests = 1; + } + } + + if( !found_tests ) + { + log_error( "ERROR: The wildcard '%s' did not match any test names.\n", wildcard ); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +static int find_argument_matching_function( const char *fnNames[], unsigned char *fnsToCall, unsigned int num_fns, + const char *argument ) +{ + unsigned int fnIndex; + + for( fnIndex = 0; fnIndex < num_fns; fnIndex++ ) + { + if( strcmp( argument, fnNames[ fnIndex ] ) == 0 ) + { + if( fnsToCall[ fnIndex ] ) + { + log_error( "ERROR: Test '%s' has already been selected.\n", fnNames[ fnIndex ] ); + return EXIT_FAILURE; + } + else + { + fnsToCall[ fnIndex ] = 1; + break; + } + } + } + + if( fnIndex == num_fns ) + { + log_error( "ERROR: The argument '%s' did not match any test names.\n", argument ); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +int parseAndCallCommandLineTests( int argc, const char *argv[], cl_device_id device, unsigned int num_fns, + basefn fnList[], const char *fnNames[], int forceNoContextCreation, + cl_command_queue_properties queueProps, int num_elements ) +{ + int ret = EXIT_SUCCESS; + + unsigned char *fnsToCall = ( unsigned char* ) calloc( num_fns, 1 ); + + if( argc == 1 ) + { + /* No actual arguments, all tests will be run. */ + memset( fnsToCall, 1, num_fns ); + } + else + { + for( int argIndex = 1; argIndex < argc; argIndex++ ) + { + if( strchr( argv[ argIndex ], '*' ) != NULL ) + { + ret = find_wildcard_matching_functions( fnNames, fnsToCall, num_fns, argv[ argIndex ] ); + } + else + { + if( strcmp( argv[ argIndex ], "all" ) == 0 ) + { + memset( fnsToCall, 1, num_fns ); + break; + } + else + { + ret = find_argument_matching_function( fnNames, fnsToCall, num_fns, argv[ argIndex ] ); + } + } + + if( ret == EXIT_FAILURE ) + { + break; + } + } + } + + if( ret == EXIT_SUCCESS ) + { + ret = callTestFunctions( fnList, fnNames, fnsToCall, num_fns, device, forceNoContextCreation, num_elements, queueProps ); + + if( gTestsFailed == 0 ) + { + if( gTestsPassed > 1 ) + { + log_info("PASSED %d of %d tests.\n", gTestsPassed, gTestsPassed); + } + else if( gTestsPassed > 0 ) + { + log_info("PASSED test.\n"); + } + } + else if( gTestsFailed > 0 ) + { + if( gTestsFailed+gTestsPassed > 1 ) + { + log_error("FAILED %d of %d tests.\n", gTestsFailed, gTestsFailed+gTestsPassed); + } + else + { + log_error("FAILED test.\n"); + } + } + } + + test_finish(); + + free( fnsToCall ); + + return ret; +} + +int callTestFunctions( basefn functionList[], const char *functionNames[], unsigned char functionsToCall[], + int numFunctions, cl_device_id deviceToUse, int forceNoContextCreation, + int numElementsToUse, cl_command_queue_properties queueProps ) +{ + int numErrors = 0; + + for( int i = 0; i < numFunctions; ++i ) + { + if( functionsToCall[ i ] ) + { + /* Skip any unimplemented tests. */ + if( functionList[ i ] != NULL ) + { + numErrors += callSingleTestFunction( functionList[ i ], functionNames[ i ], deviceToUse, + forceNoContextCreation, numElementsToUse, queueProps ); + } + else + { + log_info( "%s test currently not implemented\n", functionNames[ i ] ); + } + } + } + + return numErrors; +} + +void CL_CALLBACK notify_callback(const char *errinfo, const void *private_info, size_t cb, void *user_data) +{ + log_info( "%s\n", errinfo ); +} + +// Actual function execution +int callSingleTestFunction( basefn functionToCall, const char *functionName, + cl_device_id deviceToUse, int forceNoContextCreation, + int numElementsToUse, cl_command_queue_properties queueProps ) +{ + int numErrors = 0, ret; + cl_int error; + cl_context context = NULL; + cl_command_queue queue = NULL; + + /* Create a context to work with, unless we're told not to */ + if( !forceNoContextCreation ) + { + context = clCreateContext(NULL, 1, &deviceToUse, notify_callback, NULL, &error ); + if (!context) + { + print_error( error, "Unable to create testing context" ); + return 1; + } + + queue = clCreateCommandQueue( context, deviceToUse, queueProps, &error ); + if( queue == NULL ) + { + print_error( error, "Unable to create testing command queue" ); + return 1; + } + } + + /* Run the test and print the result */ + log_info( "%s...\n", functionName ); + fflush( stdout ); + + ret = functionToCall( deviceToUse, context, queue, numElementsToUse); //test_threaded_function( ptr_basefn_list[i], group, context, num_elements); + if( ret == TEST_NOT_IMPLEMENTED ) + { + /* Tests can also let us know they're not implemented yet */ + log_info("%s test currently not implemented\n\n", functionName); + } + else + { + /* Print result */ + if( ret == 0 ) { + log_info( "%s passed\n", functionName ); + gTestsPassed++; + } + else + { + numErrors++; + log_error( "%s FAILED\n", functionName ); + gTestsFailed++; + } + } + + /* Release the context */ + if( !forceNoContextCreation ) + { + int error = clFinish(queue); + if (error) { + log_error("clFinish failed: %d", error); + numErrors++; + } + clReleaseCommandQueue( queue ); + clReleaseContext( context ); + } + + return numErrors; +} + +void checkDeviceTypeOverride( cl_device_type *inOutType ) +{ + /* Check if we are forced to CPU mode */ + char *force_cpu = getenv( "CL_DEVICE_TYPE" ); + if( force_cpu != NULL ) + { + if( strcmp( force_cpu, "gpu" ) == 0 || strcmp( force_cpu, "CL_DEVICE_TYPE_GPU" ) == 0 ) + *inOutType = CL_DEVICE_TYPE_GPU; + else if( strcmp( force_cpu, "cpu" ) == 0 || strcmp( force_cpu, "CL_DEVICE_TYPE_CPU" ) == 0 ) + *inOutType = CL_DEVICE_TYPE_CPU; + else if( strcmp( force_cpu, "accelerator" ) == 0 || strcmp( force_cpu, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + *inOutType = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( force_cpu, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + *inOutType = CL_DEVICE_TYPE_DEFAULT; + } + + switch( *inOutType ) + { + case CL_DEVICE_TYPE_GPU: log_info( "Requesting GPU device " ); break; + case CL_DEVICE_TYPE_CPU: log_info( "Requesting CPU device " ); break; + case CL_DEVICE_TYPE_ACCELERATOR: log_info( "Requesting Accelerator device " ); break; + case CL_DEVICE_TYPE_DEFAULT: log_info( "Requesting Default device " ); break; + default: break; + } + log_info( force_cpu != NULL ? "based on environment variable\n" : "based on command line\n" ); + +#if defined( __APPLE__ ) + { + // report on any unusual library search path indirection + char *libSearchPath = getenv( "DYLD_LIBRARY_PATH"); + if( libSearchPath ) + log_info( "*** DYLD_LIBRARY_PATH = \"%s\"\n", libSearchPath ); + + // report on any unusual framework search path indirection + char *frameworkSearchPath = getenv( "DYLD_FRAMEWORK_PATH"); + if( libSearchPath ) + log_info( "*** DYLD_FRAMEWORK_PATH = \"%s\"\n", frameworkSearchPath ); + } +#endif + +} + +#if ! defined( __APPLE__ ) +void memset_pattern4(void *dest, const void *src_pattern, size_t bytes ) +{ + uint32_t pat = ((uint32_t*) src_pattern)[0]; + size_t count = bytes / 4; + size_t i; + uint32_t *d = (uint32_t*)dest; + + for( i = 0; i < count; i++ ) + d[i] = pat; + + d += i; + + bytes &= 3; + if( bytes ) + memcpy( d, src_pattern, bytes ); +} +#endif + +extern cl_device_type GetDeviceType( cl_device_id d ) +{ + cl_device_type result = -1; + cl_int err = clGetDeviceInfo( d, CL_DEVICE_TYPE, sizeof( result ), &result, NULL ); + if( CL_SUCCESS != err ) + log_error( "ERROR: Unable to get device type for device %p\n", d ); + return result; +} + + +cl_device_id GetOpposingDevice( cl_device_id device ) +{ + cl_int error; + cl_device_id *otherDevices; + cl_uint actualCount; + cl_platform_id plat; + + // Get the platform of the device to use for getting a list of devices + error = clGetDeviceInfo( device, CL_DEVICE_PLATFORM, sizeof( plat ), &plat, NULL ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to get device's platform" ); + return NULL; + } + + // Get a list of all devices + error = clGetDeviceIDs( plat, CL_DEVICE_TYPE_ALL, 0, NULL, &actualCount ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to get list of devices size" ); + return NULL; + } + otherDevices = (cl_device_id *)malloc(actualCount*sizeof(cl_device_id)); + error = clGetDeviceIDs( plat, CL_DEVICE_TYPE_ALL, actualCount, otherDevices, NULL ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to get list of devices" ); + free(otherDevices); + return NULL; + } + + if( actualCount == 1 ) + { + free(otherDevices); + return device; // NULL means error, returning self means we couldn't find another one + } + + // Loop and just find one that isn't the one we were given + cl_uint i; + for( i = 0; i < actualCount; i++ ) + { + if( otherDevices[ i ] != device ) + { + cl_device_type newType; + error = clGetDeviceInfo( otherDevices[ i ], CL_DEVICE_TYPE, sizeof( newType ), &newType, NULL ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to get device type for other device" ); + free(otherDevices); + return NULL; + } + cl_device_id result = otherDevices[ i ]; + free(otherDevices); + return result; + } + } + + // Should never get here + free(otherDevices); + return NULL; +} + + diff --git a/test_conformance/compatibility/test_common/harness/testHarness.h b/test_conformance/compatibility/test_common/harness/testHarness.h new file mode 100644 index 00000000..c2620647 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/testHarness.h @@ -0,0 +1,100 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testHarness_h +#define _testHarness_h + +#include "threadTesting.h" +#include "clImageHelper.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern cl_uint gReSeed; +extern cl_uint gRandomSeed; + +// Supply a list of functions to test here. This will allocate a CL device, create a context, all that +// setup work, and then call each function in turn as dictatated by the passed arguments. +extern int runTestHarness( int argc, const char *argv[], unsigned int num_fns, + basefn fnList[], const char *fnNames[], + int imageSupportRequired, int forceNoContextCreation, cl_command_queue_properties queueProps ); + +// Device checking function. See runTestHarnessWithCheck. If this function returns anything other than CL_SUCCESS (0), the harness exits. +typedef int (*DeviceCheckFn)( cl_device_id device ); + +// Same as runTestHarness, but also supplies a function that checks the created device for required functionality. +extern int runTestHarnessWithCheck( int argc, const char *argv[], unsigned int num_fns, + basefn fnList[], const char *fnNames[], + int imageSupportRequired, int forceNoContextCreation, cl_command_queue_properties queueProps, DeviceCheckFn deviceCheckFn ); + +// The command line parser used by runTestHarness to break up parameters into calls to callTestFunctions +extern int parseAndCallCommandLineTests( int argc, const char *argv[], cl_device_id device, unsigned int num_fns, + basefn *fnList, const char *fnNames[], + int forceNoContextCreation, cl_command_queue_properties queueProps, int num_elements ); + +// Call this function if you need to do all the setup work yourself, and just need the function list called/ +// managed. +// functionList is the actual array of functions +// functionNames is an array of strings representing the name of each function +// functionsToCall is an array of integers (treated as bools) which tell which function is to be called, +// each element at index i, corresponds to the element in functionList at index i +// numFunctions is the number of elements in the arrays +// contextProps are used to create a testing context for each test +// deviceToUse and numElementsToUse are all just passed to each test function +extern int callTestFunctions( basefn functionList[], const char *functionNames[], unsigned char functionsToCall[], + int numFunctions, cl_device_id deviceToUse, int forceNoContextCreation, + int numElementsToUse, cl_command_queue_properties queueProps ); + +// This function is called by callTestFunctions, once per function, to do setup, call, logging and cleanup +extern int callSingleTestFunction( basefn functionToCall, const char *functionName, + cl_device_id deviceToUse, int forceNoContextCreation, + int numElementsToUse, cl_command_queue_properties queueProps ); + +///// Miscellaneous steps + +// Given a pre-existing device type choice, check the environment for an override, then print what +// choice was made and how (and return the overridden choice, if there is one) +extern void checkDeviceTypeOverride( cl_device_type *inOutType ); + +// standard callback function for context pfn_notify +extern void CL_CALLBACK notify_callback(const char *errinfo, const void *private_info, size_t cb, void *user_data); + +extern cl_device_type GetDeviceType( cl_device_id ); + +// Given a device (most likely passed in by the harness, but not required), will attempt to find +// a DIFFERENT device and return it. Useful for finding another device to run multi-device tests against. +// Note that returning NULL means an error was hit, but if no error was hit and the device passed in +// is the only device available, the SAME device is returned, so check! +extern cl_device_id GetOpposingDevice( cl_device_id device ); + + +extern int gFlushDenormsToZero; // This is set to 1 if the device does not support denorms (CL_FP_DENORM) +extern int gInfNanSupport; // This is set to 1 if the device supports infinities and NaNs +extern int gIsEmbedded; // This is set to 1 if the device is an embedded device +extern int gHasLong; // This is set to 1 if the device suppots long and ulong types in OpenCL C. +extern int gIsOpenCL_C_1_0_Device; // This is set to 1 if the device supports only OpenCL C 1.0. + +#if ! defined( __APPLE__ ) + void memset_pattern4(void *, const void *, size_t); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // _testHarness_h + + diff --git a/test_conformance/compatibility/test_common/harness/test_mt19937.c b/test_conformance/compatibility/test_common/harness/test_mt19937.c new file mode 100644 index 00000000..c0498ea9 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/test_mt19937.c @@ -0,0 +1,51 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "mt19937.h" +#include + +int main( void ) +{ + MTdata d = init_genrand(42); + int i; + const cl_uint reference[16] = { 0x5fe1dc66, 0x8b255210, 0x0380b0c8, 0xc87d2ce4, + 0x55c31f24, 0x8bcd21ab, 0x14d5fef5, 0x9416d2b6, + 0xdf875de9, 0x00517d76, 0xd861c944, 0xa7676404, + 0x5491aff4, 0x67616209, 0xc368b3fb, 0x929dfc92 }; + int errcount = 0; + + for( i = 0; i < 65536; i++ ) + { + cl_uint u = genrand_int32( d ); + if( 0 == (i & 4095) ) + { + if( u != reference[i>>12] ) + { + printf("ERROR: expected *0x%8.8x at %d. Got 0x%8.8x\n", reference[i>>12], i, u ); + errcount++; + } + } + } + + free_mtdata(d); + + if( errcount ) + printf("mt19937 test failed.\n"); + else + printf("mt19937 test passed.\n"); + + + return 0; +} \ No newline at end of file diff --git a/test_conformance/compatibility/test_common/harness/threadTesting.c b/test_conformance/compatibility/test_common/harness/threadTesting.c new file mode 100644 index 00000000..2f16dcca --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/threadTesting.c @@ -0,0 +1,106 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "threadTesting.h" +#include "errorHelpers.h" +#include +#include + +#if !defined(_WIN32) +#include +#endif + +#include +#include + +#if !defined(_WIN32) +#include +#endif + +#if 0 // Disabed for now + +typedef struct +{ + basefn mFunction; + cl_device_id mDevice; + cl_context mContext; + int mNumElements; +} TestFnArgs; + +//////////////////////////////////////////////////////////////////////////////// +// Thread-based testing. Spawns a new thread to run the given test function, +// then waits for it to complete. The entire idea is that, if the thread crashes, +// we can catch it and report it as a failure instead of crashing the entire suite +//////////////////////////////////////////////////////////////////////////////// + +void *test_thread_wrapper( void *data ) +{ + TestFnArgs *args; + int retVal; + cl_context context; + + args = (TestFnArgs *)data; + + /* Create a new context to use (contexts can't cross threads) */ + context = clCreateContext(NULL, args->mDeviceGroup); + if( context == NULL ) + { + log_error("clCreateContext failed for new thread\n"); + return (void *)(-1); + } + + /* Call function */ + retVal = args->mFunction( args->mDeviceGroup, args->mDevice, context, args->mNumElements ); + + clReleaseContext( context ); + + return (void *)retVal; +} + +int test_threaded_function( basefn fnToTest, cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + int error; + pthread_t threadHdl; + void *retVal; + TestFnArgs args; + + + args.mFunction = fnToTest; + args.mDeviceGroup = deviceGroup; + args.mDevice = device; + args.mContext = context; + args.mNumElements = numElements; + + + error = pthread_create( &threadHdl, NULL, test_thread_wrapper, (void *)&args ); + if( error != 0 ) + { + log_error( "ERROR: Unable to create thread for testing!\n" ); + return -1; + } + + /* Thread has been started, now just wait for it to complete (or crash) */ + error = pthread_join( threadHdl, &retVal ); + if( error != 0 ) + { + log_error( "ERROR: Unable to join testing thread!\n" ); + return -1; + } + + return (int)((intptr_t)retVal); +} +#endif + + diff --git a/test_conformance/compatibility/test_common/harness/threadTesting.h b/test_conformance/compatibility/test_common/harness/threadTesting.h new file mode 100644 index 00000000..81a5757b --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/threadTesting.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _threadTesting_h +#define _threadTesting_h + +#ifdef __APPLE__ + #include +#else + #include +#endif + +#define TEST_NOT_IMPLEMENTED -99 + +typedef int (*basefn)(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_threaded_function( basefn fnToTest, cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); + +#endif // _threadTesting_h + + diff --git a/test_conformance/compatibility/test_common/harness/typeWrappers.cpp b/test_conformance/compatibility/test_common/harness/typeWrappers.cpp new file mode 100644 index 00000000..d4e08fb9 --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/typeWrappers.cpp @@ -0,0 +1,481 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "typeWrappers.h" +#include "kernelHelpers.h" +#include "errorHelpers.h" +#include +#include "clImageHelper.h" + +#define ROUND_SIZE_UP( _size, _align ) (((size_t)(_size) + (size_t)(_align) - 1) & -((size_t)(_align))) + +#if defined( __APPLE__ ) + #define kPageSize 4096 + #include + #include +#elif defined(__linux__) + #include + #define kPageSize (getpagesize()) +#endif + +clProtectedImage::clProtectedImage( cl_context context, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width, cl_int *errcode_ret ) +{ + cl_int err = Create( context, mem_flags, fmt, width ); + if( errcode_ret != NULL ) + *errcode_ret = err; +} + +cl_int clProtectedImage::Create( cl_context context, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width ) +{ + cl_int error; +#if defined( __APPLE__ ) + int protect_pages = 1; + cl_device_id devices[16]; + size_t number_of_devices; + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, sizeof(devices), devices, &number_of_devices); + test_error(error, "clGetContextInfo for CL_CONTEXT_DEVICES failed"); + + number_of_devices /= sizeof(cl_device_id); + for (int i=0; i<(int)number_of_devices; i++) { + cl_device_type type; + error = clGetDeviceInfo(devices[i], CL_DEVICE_TYPE, sizeof(type), &type, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_TYPE failed"); + if (type == CL_DEVICE_TYPE_GPU) { + protect_pages = 0; + break; + } + } + + if (protect_pages) { + size_t pixelBytes = get_pixel_bytes(fmt); + size_t rowBytes = ROUND_SIZE_UP( width * pixelBytes, kPageSize ); + size_t rowStride = rowBytes + kPageSize; + + // create backing store + backingStoreSize = rowStride + 8 * rowStride; + backingStore = mmap(0, backingStoreSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); + + // add guard pages + size_t row; + char *p = (char*) backingStore; + char *imagePtr = (char*) backingStore + 4 * rowStride; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + p += rowBytes; + mprotect( p, kPageSize, PROT_NONE ); p += rowStride; + p -= rowBytes; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + + if( getenv( "CL_ALIGN_RIGHT" ) ) + { + static int spewEnv = 1; + if(spewEnv) + { + log_info( "***CL_ALIGN_RIGHT is set. Aligning images at right edge of page\n" ); + spewEnv = 0; + } + imagePtr += rowBytes - pixelBytes * width; + } + + image = create_image_1d( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, rowStride, imagePtr, NULL, &error ); + } else { + backingStore = NULL; + image = create_image_1d( context, mem_flags, fmt, width, 0, NULL, NULL, &error ); + + } +#else + + backingStore = NULL; + image = create_image_1d( context, mem_flags, fmt, width, 0, NULL, NULL, &error ); + +#endif + return error; +} + + +clProtectedImage::clProtectedImage( cl_context context, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width, size_t height, cl_int *errcode_ret ) +{ + cl_int err = Create( context, mem_flags, fmt, width, height ); + if( errcode_ret != NULL ) + *errcode_ret = err; +} + +cl_int clProtectedImage::Create( cl_context context, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width, size_t height ) +{ + cl_int error; +#if defined( __APPLE__ ) + int protect_pages = 1; + cl_device_id devices[16]; + size_t number_of_devices; + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, sizeof(devices), devices, &number_of_devices); + test_error(error, "clGetContextInfo for CL_CONTEXT_DEVICES failed"); + + number_of_devices /= sizeof(cl_device_id); + for (int i=0; i<(int)number_of_devices; i++) { + cl_device_type type; + error = clGetDeviceInfo(devices[i], CL_DEVICE_TYPE, sizeof(type), &type, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_TYPE failed"); + if (type == CL_DEVICE_TYPE_GPU) { + protect_pages = 0; + break; + } + } + + if (protect_pages) { + size_t pixelBytes = get_pixel_bytes(fmt); + size_t rowBytes = ROUND_SIZE_UP( width * pixelBytes, kPageSize ); + size_t rowStride = rowBytes + kPageSize; + + // create backing store + backingStoreSize = height * rowStride + 8 * rowStride; + backingStore = mmap(0, backingStoreSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); + + // add guard pages + size_t row; + char *p = (char*) backingStore; + char *imagePtr = (char*) backingStore + 4 * rowStride; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + p += rowBytes; + for( row = 0; row < height; row++ ) + { + mprotect( p, kPageSize, PROT_NONE ); p += rowStride; + } + p -= rowBytes; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + + if( getenv( "CL_ALIGN_RIGHT" ) ) + { + static int spewEnv = 1; + if(spewEnv) + { + log_info( "***CL_ALIGN_RIGHT is set. Aligning images at right edge of page\n" ); + spewEnv = 0; + } + imagePtr += rowBytes - pixelBytes * width; + } + + image = create_image_2d( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, height, rowStride, imagePtr, &error ); + } else { + backingStore = NULL; + image = create_image_2d( context, mem_flags, fmt, width, height, 0, NULL, &error ); + + } +#else + + backingStore = NULL; + image = create_image_2d( context, mem_flags, fmt, width, height, 0, NULL, &error ); + +#endif + return error; +} + +clProtectedImage::clProtectedImage( cl_context context, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth, cl_int *errcode_ret ) +{ + cl_int err = Create( context, mem_flags, fmt, width, height, depth ); + if( errcode_ret != NULL ) + *errcode_ret = err; +} + +cl_int clProtectedImage::Create( cl_context context, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth ) +{ + cl_int error; + +#if defined( __APPLE__ ) + int protect_pages = 1; + cl_device_id devices[16]; + size_t number_of_devices; + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, sizeof(devices), devices, &number_of_devices); + test_error(error, "clGetContextInfo for CL_CONTEXT_DEVICES failed"); + + number_of_devices /= sizeof(cl_device_id); + for (int i=0; i<(int)number_of_devices; i++) { + cl_device_type type; + error = clGetDeviceInfo(devices[i], CL_DEVICE_TYPE, sizeof(type), &type, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_TYPE failed"); + if (type == CL_DEVICE_TYPE_GPU) { + protect_pages = 0; + break; + } + } + + if (protect_pages) { + size_t pixelBytes = get_pixel_bytes(fmt); + size_t rowBytes = ROUND_SIZE_UP( width * pixelBytes, kPageSize ); + size_t rowStride = rowBytes + kPageSize; + + // create backing store + backingStoreSize = height * depth * rowStride + 8 * rowStride; + backingStore = mmap(0, backingStoreSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); + + // add guard pages + size_t row; + char *p = (char*) backingStore; + char *imagePtr = (char*) backingStore + 4 * rowStride; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + p += rowBytes; + for( row = 0; row < height*depth; row++ ) + { + mprotect( p, kPageSize, PROT_NONE ); p += rowStride; + } + p -= rowBytes; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + + if( getenv( "CL_ALIGN_RIGHT" ) ) + { + static int spewEnv = 1; + if(spewEnv) + { + log_info( "***CL_ALIGN_RIGHT is set. Aligning images at right edge of page\n" ); + spewEnv = 0; + } + imagePtr += rowBytes - pixelBytes * width; + } + + image = create_image_3d( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, height, depth, rowStride, height*rowStride, imagePtr, &error ); + } else { + backingStore = NULL; + image = create_image_3d( context, mem_flags, fmt, width, height, depth, 0, 0, NULL, &error ); + } +#else + + backingStore = NULL; + image = create_image_3d( context, mem_flags, fmt, width, height, depth, 0, 0, NULL, &error ); + +#endif + + return error; +} + + +clProtectedImage::clProtectedImage( cl_context context, cl_mem_object_type imageType, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth, size_t arraySize, cl_int *errcode_ret ) +{ + cl_int err = Create( context, imageType, mem_flags, fmt, width, height, depth, arraySize ); + if( errcode_ret != NULL ) + *errcode_ret = err; +} + +cl_int clProtectedImage::Create( cl_context context, cl_mem_object_type imageType, cl_mem_flags mem_flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth, size_t arraySize ) +{ + cl_int error; +#if defined( __APPLE__ ) + int protect_pages = 1; + cl_device_id devices[16]; + size_t number_of_devices; + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, sizeof(devices), devices, &number_of_devices); + test_error(error, "clGetContextInfo for CL_CONTEXT_DEVICES failed"); + + number_of_devices /= sizeof(cl_device_id); + for (int i=0; i<(int)number_of_devices; i++) { + cl_device_type type; + error = clGetDeviceInfo(devices[i], CL_DEVICE_TYPE, sizeof(type), &type, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_TYPE failed"); + if (type == CL_DEVICE_TYPE_GPU) { + protect_pages = 0; + break; + } + } + + if (protect_pages) { + size_t pixelBytes = get_pixel_bytes(fmt); + size_t rowBytes = ROUND_SIZE_UP( width * pixelBytes, kPageSize ); + size_t rowStride = rowBytes + kPageSize; + + // create backing store + switch (imageType) + { + case CL_MEM_OBJECT_IMAGE1D: + backingStoreSize = rowStride + 8 * rowStride; + break; + case CL_MEM_OBJECT_IMAGE2D: + backingStoreSize = height * rowStride + 8 * rowStride; + break; + case CL_MEM_OBJECT_IMAGE3D: + backingStoreSize = height * depth * rowStride + 8 * rowStride; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + backingStoreSize = arraySize * rowStride + 8 * rowStride; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + backingStoreSize = height * arraySize * rowStride + 8 * rowStride; + break; + } + backingStore = mmap(0, backingStoreSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); + + // add guard pages + size_t row; + char *p = (char*) backingStore; + char *imagePtr = (char*) backingStore + 4 * rowStride; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + p += rowBytes; + size_t sz = (height > 0 ? height : 1) * (depth > 0 ? depth : 1) * (arraySize > 0 ? arraySize : 1); + for( row = 0; row < sz; row++ ) + { + mprotect( p, kPageSize, PROT_NONE ); p += rowStride; + } + p -= rowBytes; + for( row = 0; row < 4; row++ ) + { + mprotect( p, rowStride, PROT_NONE ); p += rowStride; + } + + if( getenv( "CL_ALIGN_RIGHT" ) ) + { + static int spewEnv = 1; + if(spewEnv) + { + log_info( "***CL_ALIGN_RIGHT is set. Aligning images at right edge of page\n" ); + spewEnv = 0; + } + imagePtr += rowBytes - pixelBytes * width; + } + + switch (imageType) + { + case CL_MEM_OBJECT_IMAGE1D: + image = create_image_1d( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, rowStride, imagePtr, NULL, &error ); + break; + case CL_MEM_OBJECT_IMAGE2D: + image = create_image_2d( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, height, rowStride, imagePtr, &error ); + break; + case CL_MEM_OBJECT_IMAGE3D: + image = create_image_3d( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, height, depth, rowStride, height*rowStride, imagePtr, &error ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + image = create_image_1d_array( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, arraySize, rowStride, rowStride, imagePtr, &error ); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + image = create_image_2d_array( context, mem_flags | CL_MEM_USE_HOST_PTR, fmt, width, height, arraySize, rowStride, height*rowStride, imagePtr, &error ); + break; + } + } else { + backingStore = NULL; + switch (imageType) + { + case CL_MEM_OBJECT_IMAGE1D: + image = create_image_1d( context, mem_flags, fmt, width, 0, NULL, NULL, &error ); + break; + case CL_MEM_OBJECT_IMAGE2D: + image = create_image_2d( context, mem_flags, fmt, width, height, 0, NULL, &error ); + break; + case CL_MEM_OBJECT_IMAGE3D: + image = create_image_3d( context, mem_flags, fmt, width, height, depth, 0, 0, NULL, &error );; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + image = create_image_1d_array( context, mem_flags, fmt, width, arraySize, 0, 0, NULL, &error ); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + image = create_image_2d_array( context, mem_flags, fmt, width, height, arraySize, 0, 0, NULL, &error ); + break; + } + + } +#else + + backingStore = NULL; + switch (imageType) + { + case CL_MEM_OBJECT_IMAGE1D: + image = create_image_1d( context, mem_flags, fmt, width, 0, NULL, NULL, &error ); + break; + case CL_MEM_OBJECT_IMAGE2D: + image = create_image_2d( context, mem_flags, fmt, width, height, 0, NULL, &error ); + break; + case CL_MEM_OBJECT_IMAGE3D: + image = create_image_3d( context, mem_flags, fmt, width, height, depth, 0, 0, NULL, &error );; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + image = create_image_1d_array( context, mem_flags, fmt, width, arraySize, 0, 0, NULL, &error ); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + image = create_image_2d_array( context, mem_flags, fmt, width, height, arraySize, 0, 0, NULL, &error ); + break; + } +#endif + return error; +} + + + +/******* + * clProtectedArray implementation + *******/ +clProtectedArray::clProtectedArray() +{ + mBuffer = mValidBuffer = NULL; +} + +clProtectedArray::clProtectedArray( size_t sizeInBytes ) +{ + mBuffer = mValidBuffer = NULL; + Allocate( sizeInBytes ); +} + +clProtectedArray::~clProtectedArray() +{ + if( mBuffer != NULL ) { +#if defined( __APPLE__ ) + int error = munmap( mBuffer, mRealSize ); + if (error) log_error("WARNING: munmap failed in clProtectedArray.\n"); +#else + free( mBuffer ); +#endif + } +} + +void clProtectedArray::Allocate( size_t sizeInBytes ) +{ + +#if defined( __APPLE__ ) + + // Allocate enough space to: round up our actual allocation to an even number of pages + // and allocate two pages on either side + mRoundedSize = ROUND_SIZE_UP( sizeInBytes, kPageSize ); + mRealSize = mRoundedSize + kPageSize * 2; + + // Use mmap here to ensure we start on a page boundary, so the mprotect calls will work OK + mBuffer = (char *)mmap(0, mRealSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); + + mValidBuffer = mBuffer + kPageSize; + + // Protect guard area from access + mprotect( mValidBuffer - kPageSize, kPageSize, PROT_NONE ); + mprotect( mValidBuffer + mRoundedSize, kPageSize, PROT_NONE ); +#else + mRoundedSize = mRealSize = sizeInBytes; + mBuffer = mValidBuffer = (char *)calloc(1, mRealSize); +#endif +} + + diff --git a/test_conformance/compatibility/test_common/harness/typeWrappers.h b/test_conformance/compatibility/test_common/harness/typeWrappers.h new file mode 100644 index 00000000..32f8966a --- /dev/null +++ b/test_conformance/compatibility/test_common/harness/typeWrappers.h @@ -0,0 +1,333 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _typeWrappers_h +#define _typeWrappers_h + +#include +#include + +#if !defined(_WIN32) +#include +#endif + +#include "compat.h" +#include +#include "mt19937.h" +#include "errorHelpers.h" +#include "kernelHelpers.h" + +extern "C" cl_uint gReSeed; +extern "C" cl_uint gRandomSeed; + +/* cl_context wrapper */ + +class clContextWrapper +{ + public: + clContextWrapper() { mContext = NULL; } + clContextWrapper( cl_context program ) { mContext = program; } + ~clContextWrapper() { if( mContext != NULL ) clReleaseContext( mContext ); } + + clContextWrapper & operator=( const cl_context &rhs ) { mContext = rhs; return *this; } + operator cl_context() { return mContext; } + + cl_context * operator&() { return &mContext; } + + bool operator==( const cl_context &rhs ) { return mContext == rhs; } + + protected: + + cl_context mContext; +}; + +/* cl_program wrapper */ + +class clProgramWrapper +{ + public: + clProgramWrapper() { mProgram = NULL; } + clProgramWrapper( cl_program program ) { mProgram = program; } + ~clProgramWrapper() { if( mProgram != NULL ) clReleaseProgram( mProgram ); } + + clProgramWrapper & operator=( const cl_program &rhs ) { mProgram = rhs; return *this; } + operator cl_program() { return mProgram; } + + cl_program * operator&() { return &mProgram; } + + bool operator==( const cl_program &rhs ) { return mProgram == rhs; } + + protected: + + cl_program mProgram; +}; + +/* cl_kernel wrapper */ + +class clKernelWrapper +{ + public: + clKernelWrapper() { mKernel = NULL; } + clKernelWrapper( cl_kernel kernel ) { mKernel = kernel; } + ~clKernelWrapper() { if( mKernel != NULL ) clReleaseKernel( mKernel ); } + + clKernelWrapper & operator=( const cl_kernel &rhs ) { mKernel = rhs; return *this; } + operator cl_kernel() { return mKernel; } + + cl_kernel * operator&() { return &mKernel; } + + bool operator==( const cl_kernel &rhs ) { return mKernel == rhs; } + + protected: + + cl_kernel mKernel; +}; + +/* cl_mem (stream) wrapper */ + +class clMemWrapper +{ + public: + clMemWrapper() { mMem = NULL; } + clMemWrapper( cl_mem mem ) { mMem = mem; } + ~clMemWrapper() { if( mMem != NULL ) clReleaseMemObject( mMem ); } + + clMemWrapper & operator=( const cl_mem &rhs ) { mMem = rhs; return *this; } + operator cl_mem() { return mMem; } + + cl_mem * operator&() { return &mMem; } + + bool operator==( const cl_mem &rhs ) { return mMem == rhs; } + + protected: + + cl_mem mMem; +}; + +class clProtectedImage +{ + public: + clProtectedImage() { image = NULL; backingStore = NULL; } + clProtectedImage( cl_context context, cl_mem_flags flags, const cl_image_format *fmt, size_t width, cl_int *errcode_ret ); + clProtectedImage( cl_context context, cl_mem_flags flags, const cl_image_format *fmt, size_t width, size_t height, cl_int *errcode_ret ); + clProtectedImage( cl_context context, cl_mem_flags flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth, cl_int *errcode_ret ); + clProtectedImage( cl_context context, cl_mem_object_type imageType, cl_mem_flags flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth, size_t arraySize, cl_int *errcode_ret ); + ~clProtectedImage() + { + if( image != NULL ) + clReleaseMemObject( image ); + +#if defined( __APPLE__ ) + if(backingStore) + munmap(backingStore, backingStoreSize); +#endif + } + + cl_int Create( cl_context context, cl_mem_flags flags, const cl_image_format *fmt, size_t width ); + cl_int Create( cl_context context, cl_mem_flags flags, const cl_image_format *fmt, size_t width, size_t height ); + cl_int Create( cl_context context, cl_mem_flags flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth ); + cl_int Create( cl_context context, cl_mem_object_type imageType, cl_mem_flags flags, const cl_image_format *fmt, size_t width, size_t height, size_t depth, size_t arraySize ); + + clProtectedImage & operator=( const cl_mem &rhs ) { image = rhs; backingStore = NULL; return *this; } + operator cl_mem() { return image; } + + cl_mem * operator&() { return ℑ } + + bool operator==( const cl_mem &rhs ) { return image == rhs; } + + protected: + void *backingStore; + size_t backingStoreSize; + cl_mem image; +}; + +/* cl_command_queue wrapper */ + +class clCommandQueueWrapper +{ + public: + clCommandQueueWrapper() { mMem = NULL; } + clCommandQueueWrapper( cl_command_queue mem ) { mMem = mem; } + ~clCommandQueueWrapper() { if( mMem != NULL ) {int error = clFinish(mMem); if (error) print_error(error, "clFinish failed"); clReleaseCommandQueue( mMem );} } + + clCommandQueueWrapper & operator=( const cl_command_queue &rhs ) { mMem = rhs; return *this; } + operator cl_command_queue() { return mMem; } + + cl_command_queue * operator&() { return &mMem; } + + bool operator==( const cl_command_queue &rhs ) { return mMem == rhs; } + + protected: + + cl_command_queue mMem; +}; + +/* cl_sampler wrapper */ +class clSamplerWrapper +{ + public: + clSamplerWrapper() { mMem = NULL; } + clSamplerWrapper( cl_sampler mem ) { mMem = mem; } + ~clSamplerWrapper() { if( mMem != NULL ) clReleaseSampler( mMem ); } + + clSamplerWrapper & operator=( const cl_sampler &rhs ) { mMem = rhs; return *this; } + operator cl_sampler() { return mMem; } + + cl_sampler * operator&() { return &mMem; } + + bool operator==( const cl_sampler &rhs ) { return mMem == rhs; } + + protected: + + cl_sampler mMem; +}; + +/* cl_event wrapper */ +class clEventWrapper +{ + public: + clEventWrapper() { mMem = NULL; } + clEventWrapper( cl_event mem ) { mMem = mem; } + ~clEventWrapper() { if( mMem != NULL ) clReleaseEvent( mMem ); } + + clEventWrapper & operator=( const cl_event &rhs ) { mMem = rhs; return *this; } + operator cl_event() { return mMem; } + + cl_event * operator&() { return &mMem; } + + bool operator==( const cl_event &rhs ) { return mMem == rhs; } + + protected: + + cl_event mMem; +}; + +/* Generic protected memory buffer, for verifying access within bounds */ +class clProtectedArray +{ + public: + clProtectedArray(); + clProtectedArray( size_t sizeInBytes ); + virtual ~clProtectedArray(); + + void Allocate( size_t sizeInBytes ); + + operator void *() { return (void *)mValidBuffer; } + operator const void *() const { return (const void *)mValidBuffer; } + + protected: + + char * mBuffer; + char * mValidBuffer; + size_t mRealSize, mRoundedSize; +}; + +class RandomSeed +{ + public: + RandomSeed( cl_uint seed ){ if(seed) log_info( "(seed = %10.10u) ", seed ); mtData = init_genrand(seed); } + ~RandomSeed() + { + if( gReSeed ) + gRandomSeed = genrand_int32( mtData ); + free_mtdata(mtData); + } + + operator MTdata () {return mtData;} + + protected: + MTdata mtData; +}; + +template class BufferOwningPtr +{ + BufferOwningPtr(BufferOwningPtr const &); // do not implement + void operator=(BufferOwningPtr const &); // do not implement + + void *ptr; + void *map; + size_t mapsize; // Bytes allocated total, pointed to by map. + size_t allocsize; // Bytes allocated in unprotected pages, pointed to by ptr. + bool aligned; + public: + explicit BufferOwningPtr(void *p = 0) : ptr(p), map(0), mapsize(0), allocsize(0), aligned(false) {} + explicit BufferOwningPtr(void *p, void *m, size_t s) + : ptr(p), map(m), mapsize(s), allocsize(0), aligned(false) + { +#if ! defined( __APPLE__ ) + if(m) + { + log_error( "ERROR: unhandled code path. BufferOwningPtr allocated with mapped buffer!" ); + abort(); + } +#endif + } + ~BufferOwningPtr() { + if (map) { +#if defined( __APPLE__ ) + int error = munmap(map, mapsize); + if (error) log_error("WARNING: munmap failed in BufferOwningPtr.\n"); +#endif + } else { + if ( aligned ) + { + align_free(ptr); + } + else + { + free(ptr); + } + } + } + void reset(void *p, void *m = 0, size_t mapsize_ = 0, size_t allocsize_ = 0, bool aligned_ = false) { + if (map){ +#if defined( __APPLE__ ) + int error = munmap(map, mapsize); + if (error) log_error("WARNING: munmap failed in BufferOwningPtr.\n"); +#else + log_error( "ERROR: unhandled code path. BufferOwningPtr reset with mapped buffer!" ); + abort(); +#endif + } else { + if ( aligned ) + { + align_free(ptr); + } + else + { + free(ptr); + } + } + ptr = p; + map = m; + mapsize = mapsize_; + allocsize = allocsize_; + aligned = aligned_; +#if ! defined( __APPLE__ ) + if(m) + { + log_error( "ERROR: unhandled code path. BufferOwningPtr allocated with mapped buffer!" ); + abort(); + } +#endif + } + operator T*() { return (T*)ptr; } + + size_t getSize() const { return allocsize; }; +}; + +#endif // _typeWrappers_h + + diff --git a/test_conformance/compatibility/test_conformance/CMakeLists.txt b/test_conformance/compatibility/test_conformance/CMakeLists.txt new file mode 100644 index 00000000..84858574 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(api) +add_subdirectory(basic) diff --git a/test_conformance/compatibility/test_conformance/api/CMakeLists.txt b/test_conformance/compatibility/test_conformance/api/CMakeLists.txt new file mode 100644 index 00000000..50dd64ef --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/CMakeLists.txt @@ -0,0 +1,34 @@ +set(MODULE_NAME COMPATIBILITY_API) + +set(${MODULE_NAME}_SOURCES + main.c + test_bool.c + test_retain.cpp + test_retain_program.c + test_queries.cpp + test_create_kernels.c + test_kernels.c + test_api_min_max.c + test_kernel_arg_changes.cpp + test_kernel_arg_multi_setup.cpp + test_binary.cpp + test_native_kernel.cpp + test_mem_objects.cpp + test_create_context_from_type.cpp + test_device_min_data_type_align_size_alignment.cpp + test_platform.cpp + test_mem_object_info.cpp + test_null_buffer_arg.c + test_kernel_arg_info.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/typeWrappers.cpp + ../../test_common/harness/conversions.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/imageHelpers.cpp +) + +include(../../../CMakeCommon.txt) diff --git a/test_conformance/compatibility/test_conformance/api/Jamfile b/test_conformance/compatibility/test_conformance/api/Jamfile new file mode 100644 index 00000000..704b5ce1 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/Jamfile @@ -0,0 +1,27 @@ +project + : requirements + gcc:-xc++ + msvc:"/TP" + ; + + +exe test_api + : main.c + test_api_min_max.c + test_binary.cpp + test_create_kernels.c + test_create_context_from_type.cpp + test_kernel_arg_changes.cpp + test_kernel_arg_multi_setup.cpp + test_kernels.c + test_native_kernel.cpp + test_queries.cpp + test_retain_program.c + test_platform.cpp + ; + +install dist + : test_api #test.lst + : debug:$(DIST)/debug/tests/test_conformance/api + release:$(DIST)/release/tests/test_conformance/api + ; diff --git a/test_conformance/compatibility/test_conformance/api/Makefile b/test_conformance/compatibility/test_conformance/api/Makefile new file mode 100644 index 00000000..44cfaee3 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/Makefile @@ -0,0 +1,61 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + test_retain_program.c \ + test_queries.cpp \ + test_create_kernels.c \ + test_kernels.c \ + test_kernel_arg_info.c \ + test_api_min_max.c \ + test_kernel_arg_changes.cpp \ + test_kernel_arg_multi_setup.cpp \ + test_binary.cpp \ + test_native_kernel.cpp \ + test_create_context_from_type.cpp \ + test_platform.cpp \ + test_retain.cpp \ + test_device_min_data_type_align_size_alignment.cpp \ + test_mem_objects.cpp \ + test_bool.c \ + test_null_buffer_arg.c \ + test_mem_object_info.cpp \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/imageHelpers.cpp \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/typeWrappers.cpp \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/conversions.c + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +HEADERS = +TARGET = test_api +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/compatibility/test_conformance/api/main.c b/test_conformance/compatibility/test_conformance/api/main.c new file mode 100644 index 00000000..1870bf8f --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/main.c @@ -0,0 +1,214 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include "procs.h" +#include "../../test_common/harness/testHarness.h" + +#if !defined(_WIN32) +#include +#endif + +// FIXME: To use certain functions in ../../test_common/harness/imageHelpers.h +// (for example, generate_random_image_data()), the tests are required to declare +// the following variables: +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +bool gTestRounding = false; + +basefn basefn_list[] = { + test_get_platform_info, + test_get_sampler_info, + test_get_command_queue_info, + test_get_context_info, + test_get_device_info, + test_enqueue_task, + test_binary_get, + test_program_binary_create, + test_kernel_required_group_size, + + test_release_kernel_order, + test_release_during_execute, + + test_load_single_kernel, + test_load_two_kernels, + test_load_two_kernels_in_one, + test_load_two_kernels_manually, + test_get_program_info_kernel_names, + test_get_kernel_arg_info, + test_create_kernels_in_program, + test_get_kernel_info, + test_execute_kernel_local_sizes, + test_set_kernel_arg_by_index, + test_set_kernel_arg_constant, + test_set_kernel_arg_struct_array, + test_kernel_global_constant, + + test_min_max_thread_dimensions, + test_min_max_work_items_sizes, + test_min_max_work_group_size, + test_min_max_read_image_args, + test_min_max_write_image_args, + test_min_max_mem_alloc_size, + test_min_max_image_2d_width, + test_min_max_image_2d_height, + test_min_max_image_3d_width, + test_min_max_image_3d_height, + test_min_max_image_3d_depth, + test_min_max_image_array_size, + test_min_max_image_buffer_size, + test_min_max_parameter_size, + test_min_max_samplers, + test_min_max_constant_buffer_size, + test_min_max_constant_args, + test_min_max_compute_units, + test_min_max_address_bits, + test_min_max_single_fp_config, + test_min_max_double_fp_config, + test_min_max_local_mem_size, + test_min_max_kernel_preferred_work_group_size_multiple, + test_min_max_execution_capabilities, + test_min_max_queue_properties, + test_min_max_device_version, + test_min_max_language_version, + + test_kernel_arg_changes, + test_kernel_arg_multi_setup_random, + + test_native_kernel, + + test_create_context_from_type, + + test_platform_extensions, + test_get_platform_ids, + test_for_bool_type, + + test_repeated_setup_cleanup, + + test_retain_queue_single, + test_retain_queue_multiple, + test_retain_mem_object_single, + test_retain_mem_object_multiple, + test_min_data_type_align_size_alignment, + + test_mem_object_destructor_callback, + test_null_buffer_arg, + test_get_buffer_info, + test_get_image2d_info, + test_get_image3d_info, + test_get_image1d_info, + test_get_image1d_array_info, + test_get_image2d_array_info, +}; + + +const char *basefn_names[] = { + "get_platform_info", + "get_sampler_info", + "get_command_queue_info", + "get_context_info", + "get_device_info", + "enqueue_task", + "binary_get", + "binary_create", + "kernel_required_group_size", + + "release_kernel_order", + "release_during_execute", + + "load_single_kernel", + "load_two_kernels", + "load_two_kernels_in_one", + "load_two_kernels_manually", + "get_program_info_kernel_names", + "get_kernel_arg_info", + "create_kernels_in_program", + "get_kernel_info", + "execute_kernel_local_sizes", + "set_kernel_arg_by_index", + "set_kernel_arg_constant", + "set_kernel_arg_struct_array", + "kernel_global_constant", + + "min_max_thread_dimensions", + "min_max_work_items_sizes", + "min_max_work_group_size", + "min_max_read_image_args", + "min_max_write_image_args", + "min_max_mem_alloc_size", + "min_max_image_2d_width", + "min_max_image_2d_height", + "min_max_image_3d_width", + "min_max_image_3d_height", + "min_max_image_3d_depth", + "min_max_image_array_size", + "min_max_image_buffer_size", + "min_max_parameter_size", + "min_max_samplers", + "min_max_constant_buffer_size", + "min_max_constant_args", + "min_max_compute_units", + "min_max_address_bits", + "min_max_single_fp_config", + "min_max_double_fp_config", + "min_max_local_mem_size", + "min_max_kernel_preferred_work_group_size_multiple", + "min_max_execution_capabilities", + "min_max_queue_properties", + "min_max_device_version", + "min_max_language_version", + + "kernel_arg_changes", + "kernel_arg_multi_setup_random", + + "native_kernel", + + "create_context_from_type", + "platform_extensions", + + "get_platform_ids", + "bool_type", + + "repeated_setup_cleanup", + + "retain_queue_single", + "retain_queue_multiple", + "retain_mem_object_single", + "retain_mem_object_multiple", + + "min_data_type_align_size_alignment", + + "mem_object_destructor_callback", + "null_buffer_arg", + "get_buffer_info", + "get_image2d_info", + "get_image3d_info", + "get_image1d_info", + "get_image1d_array_info", + "get_image2d_array_info", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + +int main(int argc, const char *argv[]) +{ + return runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false, false, 0 ); +} + + diff --git a/test_conformance/compatibility/test_conformance/api/procs.h b/test_conformance/compatibility/test_conformance/api/procs.h new file mode 100644 index 00000000..ff796a38 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/procs.h @@ -0,0 +1,108 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/clImageHelper.h" +#include "../../test_common/harness/imageHelpers.h" +extern float calculate_ulperror(float a, float b); + +extern int test_load_single_kernel(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_load_two_kernels(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_load_two_kernels_in_one(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_load_two_kernels_manually(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_get_program_info_kernel_names( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_create_kernels_in_program(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_enqueue_task(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_repeated_setup_cleanup(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_for_bool_type(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_platform_extensions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_get_platform_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_get_sampler_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_get_command_queue_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_get_context_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_get_device_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_kernel_required_group_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_binary_get(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_program_binary_create(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_release_kernel_order(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_release_during_execute(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_get_kernel_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_execute_kernel_local_sizes(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_set_kernel_arg_by_index(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_set_kernel_arg_struct(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_set_kernel_arg_constant(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_set_kernel_arg_struct_array(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_kernel_global_constant(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_min_max_thread_dimensions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_work_items_sizes(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_work_group_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_read_image_args(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_write_image_args(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_mem_alloc_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_image_2d_width(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_image_2d_height(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_image_3d_width(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_image_3d_height(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_image_3d_depth(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_image_array_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_image_buffer_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_parameter_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_samplers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_constant_buffer_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_constant_args(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_compute_units(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_address_bits(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_single_fp_config(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_double_fp_config(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_local_mem_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_kernel_preferred_work_group_size_multiple(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_execution_capabilities(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_queue_properties(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_device_version(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_max_language_version(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_native_kernel(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); + +extern int test_create_context_from_type(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_get_platform_ids(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_kernel_arg_changes(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_kernel_arg_multi_setup_random(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_retain_queue_single(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_retain_queue_multiple(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_retain_mem_object_single(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_retain_mem_object_multiple(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_min_data_type_align_size_alignment(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); + +extern int test_mem_object_destructor_callback(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_null_buffer_arg( cl_device_id device_id, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_get_buffer_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ); +extern int test_get_image2d_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ); +extern int test_get_image3d_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ); +extern int test_get_image1d_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ); +extern int test_get_image1d_array_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ); +extern int test_get_image2d_array_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ); +extern int test_get_kernel_arg_info( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); + diff --git a/test_conformance/compatibility/test_conformance/api/testBase.h b/test_conformance/compatibility/test_conformance/api/testBase.h new file mode 100644 index 00000000..5073b21f --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/testBase.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testBase_h +#define _testBase_h + +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +#endif // _testBase_h + + + diff --git a/test_conformance/compatibility/test_conformance/api/test_api_min_max.c b/test_conformance/compatibility/test_conformance/api/test_api_min_max.c new file mode 100644 index 00000000..61225e51 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/test_api_min_max.c @@ -0,0 +1,2059 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/testHarness.h" +#include +#include + +extern cl_uint gRandomSeed; + +const char *sample_single_param_kernel[] = { + "__kernel void sample_test(__global int *src)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + "}\n" }; + +const char *sample_single_param_write_kernel[] = { + "__kernel void sample_test(__global int *src)\n" + "{\n" + " int tid = get_global_id(0);\n" + " src[tid] = tid;\n" + "\n" + "}\n" }; + +const char *sample_read_image_kernel_pattern[] = { + "__kernel void sample_test( __global float *result, ", " )\n" + "{\n" + " sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST;\n" + " int tid = get_global_id(0);\n" + " result[0] = 0.0f;\n", + "\n" + "}\n" }; + +const char *sample_write_image_kernel_pattern[] = { + "__kernel void sample_test( ", " )\n" + "{\n" + " int tid = get_global_id(0);\n", + "\n" + "}\n" }; + + +const char *sample_large_parmam_kernel_pattern[] = { + "__kernel void sample_test(%s, __global long *result)\n" + "{\n" + "result[0] = 0;\n" + "%s" + "\n" + "}\n" }; + +const char *sample_large_int_parmam_kernel_pattern[] = { + "__kernel void sample_test(%s, __global int *result)\n" + "{\n" + "result[0] = 0;\n" + "%s" + "\n" + "}\n" }; + +const char *sample_sampler_kernel_pattern[] = { + "__kernel void sample_test( read_only image2d_t src, __global int4 *dst", ", sampler_t sampler%d", ")\n" + "{\n" + " int tid = get_global_id(0);\n", + " dst[ 0 ] = read_imagei( src, sampler%d, (int2)( 0, 0 ) );\n", + "\n" + "}\n" }; + +const char *sample_const_arg_kernel[] = { + "__kernel void sample_test(__constant int *src1, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src1[tid];\n" + "\n" + "}\n" }; + +const char *sample_local_arg_kernel[] = { + "__kernel void sample_test(__local int *src1, __global int *global_src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " src1[tid] = global_src[tid];\n" + " barrier(CLK_GLOBAL_MEM_FENCE);\n" + " dst[tid] = src1[tid];\n" + "\n" + "}\n" }; + +const char *sample_const_max_arg_kernel_pattern = +"__kernel void sample_test(__constant int *src1 %s, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = src1[tid];\n" +"%s" +"\n" +"}\n"; + +int test_min_max_thread_dimensions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error, retVal; + unsigned int maxThreadDim, threadDim, i; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[1]; + size_t *threads, *localThreads; + cl_event event; + cl_int event_status; + + + /* Get the max thread dimensions */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof( maxThreadDim ), &maxThreadDim, NULL ); + test_error( error, "Unable to get max work item dimensions from device" ); + + if( maxThreadDim < 3 ) + { + log_error( "ERROR: Reported max work item dimensions is less than required! (%d)\n", maxThreadDim ); + return -1; + } + + log_info("Reported max thread dimensions of %d.\n", maxThreadDim); + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_single_param_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 100, NULL, &error ); + if( streams[0] == NULL ) + { + log_error("ERROR: Creating test array failed!\n"); + return -1; + } + + /* Set the arguments */ + error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set kernel arguments" ); + + retVal = 0; + + /* Now try running the kernel with up to that many threads */ + for (threadDim=1; threadDim <= maxThreadDim; threadDim++) + { + threads = (size_t *)malloc( sizeof( size_t ) * maxThreadDim ); + localThreads = (size_t *)malloc( sizeof( size_t ) * maxThreadDim ); + for( i = 0; i < maxThreadDim; i++ ) + { + threads[ i ] = 1; + localThreads[i] = 1; + } + + error = clEnqueueNDRangeKernel( queue, kernel, maxThreadDim, NULL, threads, localThreads, 0, NULL, &event ); + test_error( error, "Failed clEnqueueNDRangeKernel"); + + // Verify that the event does not return an error from the execution + error = clWaitForEvents(1, &event); + test_error( error, "clWaitForEvent failed"); + error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL); + test_error( error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed"); + clReleaseEvent(event); + if (event_status < 0) + test_error(error, "Kernel execution event returned error"); + + /* All done */ + free( threads ); + free( localThreads ); + } + + return retVal; +} + + +int test_min_max_work_items_sizes(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t *deviceMaxWorkItemSize; + unsigned int maxWorkItemDim; + + /* Get the max work item dimensions */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof( maxWorkItemDim ), &maxWorkItemDim, NULL ); + test_error( error, "Unable to get max work item dimensions from device" ); + + log_info("CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS returned %d\n", maxWorkItemDim); + deviceMaxWorkItemSize = (size_t*)malloc(sizeof(size_t)*maxWorkItemDim); + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(size_t)*maxWorkItemDim, deviceMaxWorkItemSize, NULL ); + test_error( error, "clDeviceInfo for CL_DEVICE_MAX_WORK_ITEM_SIZES failed" ); + + unsigned int i; + int errors = 0; + for(i=0; i= 128 && maxParameterSize == 1024) + { + error = clGetDeviceInfo( deviceID, CL_DEVICE_TYPE, sizeof( deviceType ), &deviceType, NULL ); + test_error( error, "Unable to get device type from device" ); + + if(deviceType != CL_DEVICE_TYPE_CUSTOM) + { + maxReadImages = 127; + } + } + + // Subtract the size of the result + maxParameterSize -= sizeof(cl_mem); + + // Calculate the number we can use + if (maxParameterSize/sizeof(cl_mem) < maxReadImages) { + log_info("WARNING: Max parameter size of %d bytes limits test to %d max image arguments.\n", (int)maxParameterSize, (int)(maxParameterSize/sizeof(cl_mem))); + maxReadImages = (unsigned int)(maxParameterSize/sizeof(cl_mem)); + } + + /* Create a program with that many read args */ + programSrc = (char *)malloc( strlen( sample_read_image_kernel_pattern[ 0 ] ) + ( strlen( readArgPattern ) + 6 ) * ( maxReadImages ) + + strlen( sample_read_image_kernel_pattern[ 1 ] ) + 1 + 40240); + + strcpy( programSrc, sample_read_image_kernel_pattern[ 0 ] ); + strcat( programSrc, "read_only image2d_t srcimg0" ); + for( i = 0; i < maxReadImages-1; i++ ) + { + sprintf( readArgLine, readArgPattern, i+1 ); + strcat( programSrc, readArgLine ); + } + strcat( programSrc, sample_read_image_kernel_pattern[ 1 ] ); + for ( i = 0; i < maxReadImages; i++) { + sprintf( readArgLine, "\tresult[0] += read_imagef( srcimg%d, sampler, (int2)(0,0)).x;\n", i); + strcat( programSrc, readArgLine ); + } + strcat( programSrc, sample_read_image_kernel_pattern[ 2 ] ); + + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&programSrc, "sample_test"); + test_error( error, "Failed to create the program and kernel."); + free( programSrc ); + + result = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float), NULL, &error); + test_error( error, "clCreateBufer failed"); + + /* Create some I/O streams */ + streams = new clMemWrapper[maxReadImages + 1]; + for( i = 0; i < maxReadImages; i++ ) + { + image_data[0]=i; + image_result+= image_data[0]; + streams[i] = create_image_2d( context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, &image_format_desc, 4, 4, 0, image_data, &error ); + test_error( error, "Unable to allocate test image" ); + } + + error = clSetKernelArg( kernel, 0, sizeof( result ), &result ); + test_error( error, "Unable to set kernel arguments" ); + + /* Set the arguments */ + for( i = 1; i < maxReadImages+1; i++ ) + { + error = clSetKernelArg( kernel, i, sizeof( streams[i-1] ), &streams[i-1] ); + test_error( error, "Unable to set kernel arguments" ); + } + + /* Now try running the kernel */ + threads[0] = threads[1] = 1; + error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, &event ); + test_error( error, "clEnqueueNDRangeKernel failed"); + + // Verify that the event does not return an error from the execution + error = clWaitForEvents(1, &event); + test_error( error, "clWaitForEvent failed"); + error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL); + test_error( error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed"); + clReleaseEvent(event); + if (event_status < 0) + test_error(error, "Kernel execution event returned error"); + + error = clEnqueueReadBuffer(queue, result, CL_TRUE, 0, sizeof(cl_float), &actual_image_result, 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + delete[] streams; + + if (actual_image_result != image_result) { + log_error("Result failed to verify. Got %g, expected %g.\n", actual_image_result, image_result); + return 1; + } + + return 0; +} + +int test_min_max_write_image_args(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + unsigned int maxWriteImages, i; + clProgramWrapper program; + char writeArgLine[128], *programSrc; + const char *writeArgPattern = ", write_only image2d_t dstimg%d"; + clKernelWrapper kernel; + clMemWrapper *streams; + size_t threads[2]; + cl_image_format image_format_desc; + size_t maxParameterSize; + cl_event event; + cl_int event_status; + cl_uint minRequiredWriteImages = gIsEmbedded ? 1 : 8; + + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ) + image_format_desc.image_channel_order = CL_RGBA; + image_format_desc.image_channel_data_type = CL_UNORM_INT8; + + /* Get the max read image arg count */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, sizeof( maxWriteImages ), &maxWriteImages, NULL ); + test_error( error, "Unable to get max write image arg count from device" ); + + if( maxWriteImages == 0 ) + { + log_info( "WARNING: Device reports 0 for a max write image arg count (write image arguments unsupported). Skipping test (implicitly passes). This is only valid if the number of image formats is also 0.\n" ); + return 0; + } + + if( maxWriteImages < minRequiredWriteImages ) + { + log_error( "ERROR: Reported max write image arg count is less than required! (%d)\n", maxWriteImages ); + return -1; + } + + log_info("Reported %d max write image args.\n", maxWriteImages); + + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof( maxParameterSize ), &maxParameterSize, NULL ); + test_error( error, "Unable to get max parameter size from device" ); + + // Calculate the number we can use + if (maxParameterSize/sizeof(cl_mem) < maxWriteImages) { + log_info("WARNING: Max parameter size of %d bytes limits test to %d max image arguments.\n", (int)maxParameterSize, (int)(maxParameterSize/sizeof(cl_mem))); + maxWriteImages = (unsigned int)(maxParameterSize/sizeof(cl_mem)); + } + + /* Create a program with that many write args + 1 */ + programSrc = (char *)malloc( strlen( sample_write_image_kernel_pattern[ 0 ] ) + ( strlen( writeArgPattern ) + 6 ) * ( maxWriteImages + 1 ) + + strlen( sample_write_image_kernel_pattern[ 1 ] ) + 1 + 40240 ); + + strcpy( programSrc, sample_write_image_kernel_pattern[ 0 ] ); + strcat( programSrc, "write_only image2d_t dstimg0" ); + for( i = 1; i < maxWriteImages; i++ ) + { + sprintf( writeArgLine, writeArgPattern, i ); + strcat( programSrc, writeArgLine ); + } + strcat( programSrc, sample_write_image_kernel_pattern[ 1 ] ); + for ( i = 0; i < maxWriteImages; i++) { + sprintf( writeArgLine, "\twrite_imagef( dstimg%d, (int2)(0,0), (float4)(0,0,0,0));\n", i); + strcat( programSrc, writeArgLine ); + } + strcat( programSrc, sample_write_image_kernel_pattern[ 2 ] ); + + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&programSrc, "sample_test"); + test_error( error, "Failed to create the program and kernel."); + free( programSrc ); + + + /* Create some I/O streams */ + streams = new clMemWrapper[maxWriteImages + 1]; + for( i = 0; i < maxWriteImages; i++ ) + { + streams[i] = create_image_2d( context, CL_MEM_READ_WRITE, &image_format_desc, 16, 16, 0, NULL, &error ); + test_error( error, "Unable to allocate test image" ); + } + + /* Set the arguments */ + for( i = 0; i < maxWriteImages; i++ ) + { + error = clSetKernelArg( kernel, i, sizeof( streams[i] ), &streams[i] ); + test_error( error, "Unable to set kernel arguments" ); + } + + /* Now try running the kernel */ + threads[0] = threads[1] = 16; + error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, &event ); + test_error( error, "clEnqueueNDRangeKernel failed."); + + // Verify that the event does not return an error from the execution + error = clWaitForEvents(1, &event); + test_error( error, "clWaitForEvent failed"); + error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL); + test_error( error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed"); + clReleaseEvent(event); + if (event_status < 0) + test_error(error, "Kernel execution event returned error"); + + /* All done */ + delete[] streams; + return 0; +} + +int test_min_max_mem_alloc_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_ulong maxAllocSize, memSize, minSizeToTry; + clMemWrapper memHdl; + + cl_ulong requiredAllocSize; + + if (gIsEmbedded) + requiredAllocSize = 1 * 1024 * 1024; + else + requiredAllocSize = 128 * 1024 * 1024; + + /* Get the max mem alloc size */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get max mem alloc size from device" ); + + error = clGetDeviceInfo( deviceID, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get global memory size from device" ); + + if( maxAllocSize < requiredAllocSize) + { + log_error( "ERROR: Reported max allocation size is less than required %lldMB! (%llu or %lluMB, from a total mem size of %lldMB)\n", (requiredAllocSize / 1024) / 1024, maxAllocSize, (maxAllocSize / 1024)/1024, (memSize / 1024)/1024 ); + return -1; + } + + if( maxAllocSize < memSize / 4 ) + { + log_error( "ERROR: Reported max allocation size is less than required 1/4 of total memory! (%llu or %lluMB, from a total mem size of %lluMB)\n", maxAllocSize, (maxAllocSize / 1024)/1024, (memSize / 1024)/1024 ); + return -1; + } + + log_info("Reported max allocation size of %lld bytes (%gMB) and global mem size of %lld bytes (%gMB).\n", + maxAllocSize, maxAllocSize/(1024.0*1024.0), memSize, memSize/(1024.0*1024.0)); + + if ( memSize < maxAllocSize ) { + log_info("Global memory size is less than max allocation size, using that.\n"); + maxAllocSize = memSize; + } + + if ( maxAllocSize > (cl_ulong)4 * 1024 * 1024 * 1024) { + log_info("Limiting max allocation size to 4GB for test.\n"); + maxAllocSize = (cl_ulong)4 * 1024 * 1024 * 1024; + } + + minSizeToTry = maxAllocSize/16; + while (maxAllocSize > (maxAllocSize/4)) { + + log_info("Trying to create a buffer of size of %lld bytes (%gMB).\n", maxAllocSize, (double)maxAllocSize/(1024.0*1024.0)); + memHdl = clCreateBuffer( context, CL_MEM_READ_ONLY, (size_t)maxAllocSize, NULL, &error ); + if (error == CL_MEM_OBJECT_ALLOCATION_FAILURE || error == CL_OUT_OF_RESOURCES || error == CL_OUT_OF_HOST_MEMORY) { + log_info("\tAllocation failed at size of %lld bytes (%gMB).\n", maxAllocSize, (double)maxAllocSize/(1024.0*1024.0)); + maxAllocSize -= minSizeToTry; + continue; + } + test_error( error, "clCreateBuffer failed for maximum sized buffer."); + return 0; + } + log_error("Failed to allocate even %lld bytes (%gMB).\n", maxAllocSize, (double)maxAllocSize/(1024.0*1024.0)); + return -1; +} + +int test_min_max_image_2d_width(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t maxDimension; + clMemWrapper streams[1]; + cl_image_format image_format_desc; + cl_ulong maxAllocSize; + cl_uint minRequiredDimension; + cl_char buffer[ 4098 ]; + size_t length; + + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ) + + // Device version should fit the regex "OpenCL [0-9]+\.[0-9]+ *.*" + error = clGetDeviceInfo( deviceID, CL_DEVICE_VERSION, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get device version string" ); + if( memcmp( buffer, "OpenCL 2.0", strlen( "OpenCL 2.0" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 8192; + else if( memcmp( buffer, "OpenCL 1.2", strlen( "OpenCL 1.2" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 8192; + else if( memcmp( buffer, "OpenCL 1.1", strlen( "OpenCL 1.1" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 8192; + else if ( memcmp( buffer, "OpenCL 1.0", strlen( "OpenCL 1.0" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 4096; + else + { + log_error( "ERROR: device version string does not match required format! (returned: %s)\n", (char *)buffer ); + return -1; + } + + + /* Just get any ol format to test with */ + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE2D, CL_MEM_READ_WRITE, 0, &image_format_desc ); + test_error( error, "Unable to obtain suitable image format to test with!" ); + + /* Get the max 2d image width */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxDimension ), &maxDimension, NULL ); + test_error( error, "Unable to get max image 2d width from device" ); + + if( maxDimension < minRequiredDimension ) + { + log_error( "ERROR: Reported max image 2d width is less than required! (%d)\n", (int)maxDimension ); + return -1; + } + log_info("Max reported width is %ld.\n", maxDimension); + + /* Verify we can use the format */ + image_format_desc.image_channel_data_type = CL_UNORM_INT8; + image_format_desc.image_channel_order = CL_RGBA; + if (!is_image_format_supported( context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE2D, &image_format_desc)) { + log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test."); + return -1; + } + + /* Verify that we can actually allocate an image that large */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof ( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE." ); + if ( (cl_ulong)maxDimension*1*4 > maxAllocSize ) { + log_error("Can not allocate a large enough image (min size: %lld bytes, max allowed: %lld bytes) to test.\n", + (cl_ulong)maxDimension*1*4, maxAllocSize); + return -1; + } + + log_info("Attempting to create an image of size %d x 1 = %gMB.\n", (int)maxDimension, ((float)maxDimension*4/1024.0/1024.0)); + + /* Try to allocate a very big image */ + streams[0] = create_image_2d( context, CL_MEM_READ_ONLY, &image_format_desc, maxDimension, 1, 0, NULL, &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "Image 2D creation failed for maximum width" ); + return -1; + } + + return 0; +} + +int test_min_max_image_2d_height(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t maxDimension; + clMemWrapper streams[1]; + cl_image_format image_format_desc; + cl_ulong maxAllocSize; + cl_uint minRequiredDimension; + cl_char buffer[ 4098 ]; + size_t length; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ) + + // Device version should fit the regex "OpenCL [0-9]+\.[0-9]+ *.*" + error = clGetDeviceInfo( deviceID, CL_DEVICE_VERSION, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get device version string" ); + if( memcmp( buffer, "OpenCL 2.0", strlen( "OpenCL 2.0" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 8192; + else if( memcmp( buffer, "OpenCL 1.2", strlen( "OpenCL 1.2" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 8192; + else if( memcmp( buffer, "OpenCL 1.1", strlen( "OpenCL 1.1" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 8192; + else if ( memcmp( buffer, "OpenCL 1.0", strlen( "OpenCL 1.0" ) ) == 0 ) + minRequiredDimension = gIsEmbedded ? 2048 : 4096; + else + { + log_error( "ERROR: device version string does not match required format! (returned: %s)\n", (char *)buffer ); + return -1; + } + + /* Just get any ol format to test with */ + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE2D, CL_MEM_READ_WRITE, 0, &image_format_desc ); + test_error( error, "Unable to obtain suitable image format to test with!" ); + + /* Get the max 2d image width */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxDimension ), &maxDimension, NULL ); + test_error( error, "Unable to get max image 2d height from device" ); + + if( maxDimension < minRequiredDimension ) + { + log_error( "ERROR: Reported max image 2d height is less than required! (%d)\n", (int)maxDimension ); + return -1; + } + log_info("Max reported height is %ld.\n", maxDimension); + + /* Verify we can use the format */ + image_format_desc.image_channel_data_type = CL_UNORM_INT8; + image_format_desc.image_channel_order = CL_RGBA; + if (!is_image_format_supported( context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE2D, &image_format_desc)) { + log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test."); + return -1; + } + + /* Verify that we can actually allocate an image that large */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof ( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE." ); + if ( (cl_ulong)maxDimension*1*4 > maxAllocSize ) { + log_error("Can not allocate a large enough image (min size: %lld bytes, max allowed: %lld bytes) to test.\n", + (cl_ulong)maxDimension*1*4, maxAllocSize); + return -1; + } + + log_info("Attempting to create an image of size 1 x %d = %gMB.\n", (int)maxDimension, ((float)maxDimension*4/1024.0/1024.0)); + + /* Try to allocate a very big image */ + streams[0] = create_image_2d( context, CL_MEM_READ_ONLY, &image_format_desc, 1, maxDimension, 0, NULL, &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "Image 2D creation failed for maximum height" ); + return -1; + } + + return 0; +} + +int test_min_max_image_3d_width(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t maxDimension; + clMemWrapper streams[1]; + cl_image_format image_format_desc; + cl_ulong maxAllocSize; + + + PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( deviceID ) + + /* Just get any ol format to test with */ + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE3D, CL_MEM_READ_WRITE, 0, &image_format_desc ); + test_error( error, "Unable to obtain suitable image format to test with!" ); + + /* Get the max 2d image width */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxDimension ), &maxDimension, NULL ); + test_error( error, "Unable to get max image 3d width from device" ); + + if( maxDimension < 2048 ) + { + log_error( "ERROR: Reported max image 3d width is less than required! (%d)\n", (int)maxDimension ); + return -1; + } + log_info("Max reported width is %ld.\n", maxDimension); + + /* Verify we can use the format */ + image_format_desc.image_channel_data_type = CL_UNORM_INT8; + image_format_desc.image_channel_order = CL_RGBA; + if (!is_image_format_supported( context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE3D, &image_format_desc)) { + log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test."); + return -1; + } + + /* Verify that we can actually allocate an image that large */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof ( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE." ); + if ( (cl_ulong)maxDimension*2*4 > maxAllocSize ) { + log_error("Can not allocate a large enough image (min size: %lld bytes, max allowed: %lld bytes) to test.\n", + (cl_ulong)maxDimension*2*4, maxAllocSize); + return -1; + } + + log_info("Attempting to create an image of size %d x 1 x 2 = %gMB.\n", (int)maxDimension, (2*(float)maxDimension*4/1024.0/1024.0)); + + /* Try to allocate a very big image */ + streams[0] = create_image_3d( context, CL_MEM_READ_ONLY, &image_format_desc, maxDimension, 1, 2, 0, 0, NULL, &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "Image 3D creation failed for maximum width" ); + return -1; + } + + return 0; +} + +int test_min_max_image_3d_height(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t maxDimension; + clMemWrapper streams[1]; + cl_image_format image_format_desc; + cl_ulong maxAllocSize; + + + PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( deviceID ) + + /* Just get any ol format to test with */ + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE3D, CL_MEM_READ_WRITE, 0, &image_format_desc ); + test_error( error, "Unable to obtain suitable image format to test with!" ); + + /* Get the max 2d image width */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxDimension ), &maxDimension, NULL ); + test_error( error, "Unable to get max image 3d height from device" ); + + if( maxDimension < 2048 ) + { + log_error( "ERROR: Reported max image 3d height is less than required! (%d)\n", (int)maxDimension ); + return -1; + } + log_info("Max reported height is %ld.\n", maxDimension); + + /* Verify we can use the format */ + image_format_desc.image_channel_data_type = CL_UNORM_INT8; + image_format_desc.image_channel_order = CL_RGBA; + if (!is_image_format_supported( context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE3D, &image_format_desc)) { + log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test."); + return -1; + } + + /* Verify that we can actually allocate an image that large */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof ( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE." ); + if ( (cl_ulong)maxDimension*2*4 > maxAllocSize ) { + log_error("Can not allocate a large enough image (min size: %lld bytes, max allowed: %lld bytes) to test.\n", + (cl_ulong)maxDimension*2*4, maxAllocSize); + return -1; + } + + log_info("Attempting to create an image of size 1 x %d x 2 = %gMB.\n", (int)maxDimension, (2*(float)maxDimension*4/1024.0/1024.0)); + + /* Try to allocate a very big image */ + streams[0] = create_image_3d( context, CL_MEM_READ_ONLY, &image_format_desc, 1, maxDimension, 2, 0, 0, NULL, &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "Image 3D creation failed for maximum height" ); + return -1; + } + + return 0; +} + + +int test_min_max_image_3d_depth(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t maxDimension; + clMemWrapper streams[1]; + cl_image_format image_format_desc; + cl_ulong maxAllocSize; + + + PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( deviceID ) + + /* Just get any ol format to test with */ + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE3D, CL_MEM_READ_WRITE, 0, &image_format_desc ); + test_error( error, "Unable to obtain suitable image format to test with!" ); + + /* Get the max 2d image width */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDimension ), &maxDimension, NULL ); + test_error( error, "Unable to get max image 3d depth from device" ); + + if( maxDimension < 2048 ) + { + log_error( "ERROR: Reported max image 3d depth is less than required! (%d)\n", (int)maxDimension ); + return -1; + } + log_info("Max reported depth is %ld.\n", maxDimension); + + /* Verify we can use the format */ + image_format_desc.image_channel_data_type = CL_UNORM_INT8; + image_format_desc.image_channel_order = CL_RGBA; + if (!is_image_format_supported( context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE3D, &image_format_desc)) { + log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test."); + return -1; + } + + /* Verify that we can actually allocate an image that large */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof ( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE." ); + if ( (cl_ulong)maxDimension*1*4 > maxAllocSize ) { + log_error("Can not allocate a large enough image (min size: %lld bytes, max allowed: %lld bytes) to test.\n", + (cl_ulong)maxDimension*1*4, maxAllocSize); + return -1; + } + + log_info("Attempting to create an image of size 1 x 1 x %d = %gMB.\n", (int)maxDimension, ((float)maxDimension*4/1024.0/1024.0)); + + /* Try to allocate a very big image */ + streams[0] = create_image_3d( context, CL_MEM_READ_ONLY, &image_format_desc, 1, 1, maxDimension, 0, 0, NULL, &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "Image 3D creation failed for maximum depth" ); + return -1; + } + + return 0; +} + +int test_min_max_image_array_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t maxDimension; + clMemWrapper streams[1]; + cl_image_format image_format_desc; + cl_ulong maxAllocSize; + size_t minRequiredDimension = gIsEmbedded ? 256 : 2048; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ); + + /* Just get any ol format to test with */ + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE2D_ARRAY, CL_MEM_READ_WRITE, 0, &image_format_desc ); + test_error( error, "Unable to obtain suitable image format to test with!" ); + + /* Get the max image array width */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxDimension ), &maxDimension, NULL ); + test_error( error, "Unable to get max image array size from device" ); + + if( maxDimension < minRequiredDimension ) + { + log_error( "ERROR: Reported max image array size is less than required! (%d)\n", (int)maxDimension ); + return -1; + } + log_info("Max reported image array size is %ld.\n", maxDimension); + + /* Verify we can use the format */ + image_format_desc.image_channel_data_type = CL_UNORM_INT8; + image_format_desc.image_channel_order = CL_RGBA; + if (!is_image_format_supported( context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE2D_ARRAY, &image_format_desc)) { + log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test."); + return -1; + } + + /* Verify that we can actually allocate an image that large */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof ( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE." ); + if ( (cl_ulong)maxDimension*1*4 > maxAllocSize ) { + log_error("Can not allocate a large enough image (min size: %lld bytes, max allowed: %lld bytes) to test.\n", + (cl_ulong)maxDimension*1*4, maxAllocSize); + return -1; + } + + log_info("Attempting to create an image of size 1 x 1 x %d = %gMB.\n", (int)maxDimension, ((float)maxDimension*4/1024.0/1024.0)); + + /* Try to allocate a very big image */ + streams[0] = create_image_2d_array( context, CL_MEM_READ_ONLY, &image_format_desc, 1, 1, maxDimension, 0, 0, NULL, &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "2D Image Array creation failed for maximum array size" ); + return -1; + } + + return 0; +} + +int test_min_max_image_buffer_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t maxDimensionPixels; + clMemWrapper streams[2]; + cl_image_format image_format_desc = {0}; + cl_ulong maxAllocSize; + size_t minRequiredDimension = gIsEmbedded ? 2048 : 65536; + unsigned int i = 0; + size_t pixelBytes = 0; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ); + + /* Get the max memory allocation size */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof ( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE." ); + + /* Get the max image array width */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE_MAX_BUFFER_SIZE, sizeof( maxDimensionPixels ), &maxDimensionPixels, NULL ); + test_error( error, "Unable to get max image buffer size from device" ); + + if( maxDimensionPixels < minRequiredDimension ) + { + log_error( "ERROR: Reported max image buffer size is less than required! (%d)\n", (int)maxDimensionPixels ); + return -1; + } + log_info("Max reported image buffer size is %ld pixels.\n", maxDimensionPixels); + + pixelBytes = maxAllocSize / maxDimensionPixels; + if ( pixelBytes == 0 ) + { + log_error( "Value of CL_DEVICE_IMAGE_MAX_BUFFER_SIZE is greater than CL_MAX_MEM_ALLOC_SIZE so there is no way to allocate image of maximum size!\n" ); + return -1; + } + + error = -1; + for ( i = pixelBytes; i > 0; --i ) + { + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE1D, CL_MEM_READ_ONLY, i, &image_format_desc ); + if ( error == CL_SUCCESS ) + { + pixelBytes = i; + break; + } + } + test_error( error, "Device does not support format to be used to allocate image of CL_DEVICE_IMAGE_MAX_BUFFER_SIZE\n" ); + + log_info("Attempting to create an 1D image with channel order %s from buffer of size %d = %gMB.\n", + GetChannelOrderName( image_format_desc.image_channel_order ), (int)maxDimensionPixels, ((float)maxDimensionPixels*pixelBytes/1024.0/1024.0)); + + /* Try to allocate a buffer */ + streams[0] = clCreateBuffer( context, CL_MEM_READ_ONLY, maxDimensionPixels*pixelBytes, NULL, &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "Buffer creation failed for maximum image buffer size" ); + return -1; + } + + /* Try to allocate a 1D image array from buffer */ + streams[1] = create_image_1d( context, CL_MEM_READ_ONLY, &image_format_desc, maxDimensionPixels, 0, NULL, streams[0], &error ); + if( ( streams[0] == NULL ) || ( error != CL_SUCCESS )) + { + print_error( error, "1D Image from buffer creation failed for maximum image buffer size" ); + return -1; + } + + return 0; +} + + + +int test_min_max_parameter_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error, retVal, i; + size_t maxSize; + char *programSrc; + char *ptr; + size_t numberExpected; + long numberOfIntParametersToTry; + char *argumentLine, *codeLines; + void *data; + cl_long long_result, expectedResult; + cl_int int_result; + size_t decrement; + cl_event event; + cl_int event_status; + + + /* Get the max param size */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof( maxSize ), &maxSize, NULL ); + test_error( error, "Unable to get max parameter size from device" ); + + if( ((!gIsEmbedded) && (maxSize < 1024)) || ((gIsEmbedded) && (maxSize < 256)) ) + { + log_error( "ERROR: Reported max parameter size is less than required! (%d)\n", (int)maxSize ); + return -1; + } + + /* The embedded profile does not require longs, so use ints */ + if(gIsEmbedded) + numberOfIntParametersToTry = numberExpected = (maxSize-sizeof(cl_mem))/sizeof(cl_int); + else + numberOfIntParametersToTry = numberExpected = (maxSize-sizeof(cl_mem))/sizeof(cl_long); + + decrement = (size_t)(numberOfIntParametersToTry/8); + if (decrement < 1) + decrement = 1; + log_info("Reported max parameter size of %d bytes.\n", (int)maxSize); + + while (numberOfIntParametersToTry > 0) { + // These need to be inside to be deallocated automatically on each loop iteration. + clProgramWrapper program; + clMemWrapper mem; + clKernelWrapper kernel; + + if(gIsEmbedded) + { + log_info("Trying a kernel with %ld int arguments (%ld bytes) and one cl_mem (%ld bytes) for %ld bytes total.\n", + numberOfIntParametersToTry, sizeof(cl_int)*numberOfIntParametersToTry, sizeof(cl_mem), + sizeof(cl_mem)+numberOfIntParametersToTry*sizeof(cl_int)); + } + else + { + log_info("Trying a kernel with %ld long arguments (%ld bytes) and one cl_mem (%ld bytes) for %ld bytes total.\n", + numberOfIntParametersToTry, sizeof(cl_long)*numberOfIntParametersToTry, sizeof(cl_mem), + sizeof(cl_mem)+numberOfIntParametersToTry*sizeof(cl_long)); + } + + // Allocate memory for the program storage + data = malloc(sizeof(cl_long)*numberOfIntParametersToTry); + + argumentLine = (char*)malloc(sizeof(char)*numberOfIntParametersToTry*32); + codeLines = (char*)malloc(sizeof(char)*numberOfIntParametersToTry*32); + programSrc = (char*)malloc(sizeof(char)*(numberOfIntParametersToTry*64+1024)); + argumentLine[0] = '\0'; + codeLines[0] = '\0'; + programSrc[0] = '\0'; + + // Generate our results + expectedResult = 0; + for (i=0; i<(int)numberOfIntParametersToTry; i++) + { + if( gHasLong ) + { + ((cl_long *)data)[i] = i; + expectedResult += i; + } + else + { + ((cl_int *)data)[i] = i; + expectedResult += i; + } + } + + // Build the program + if( gHasLong) + sprintf(argumentLine, "%s", "long arg0"); + else + sprintf(argumentLine, "%s", "int arg0"); + + sprintf(codeLines, "%s", "result[0] += arg0;"); + for (i=1; i<(int)numberOfIntParametersToTry; i++) + { + if( gHasLong) + sprintf(argumentLine + strlen( argumentLine), ", long arg%d", i); + else + sprintf(argumentLine + strlen( argumentLine), ", int arg%d", i); + + sprintf(codeLines + strlen( codeLines), "\nresult[0] += arg%d;", i); + } + + /* Create a kernel to test with */ + sprintf( programSrc, gHasLong ? sample_large_parmam_kernel_pattern[0]: + sample_large_int_parmam_kernel_pattern[0], argumentLine, codeLines); + + ptr = programSrc; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&ptr, "sample_test" ) != 0 ) + { + log_info("Create program failed, decrementing number of parameters to try.\n"); + numberOfIntParametersToTry -= decrement; + continue; + } + + /* Try to set a large argument to the kernel */ + retVal = 0; + + mem = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_long), NULL, &error); + test_error(error, "clCreateBuffer failed"); + + for (i=0; i<(int)numberOfIntParametersToTry; i++) { + if(gHasLong) + error = clSetKernelArg(kernel, i, sizeof(cl_long), &(((cl_long*)data)[i])); + else + error = clSetKernelArg(kernel, i, sizeof(cl_int), &(((cl_int*)data)[i])); + + if (error != CL_SUCCESS) { + log_info( "clSetKernelArg failed (%s), decrementing number of parameters to try.\n", IGetErrorString(error)); + numberOfIntParametersToTry -= decrement; + break; + } + } + if (error != CL_SUCCESS) + continue; + + + error = clSetKernelArg(kernel, i, sizeof(cl_mem), &mem); + if (error != CL_SUCCESS) { + log_info( "clSetKernelArg failed (%s), decrementing number of parameters to try.\n", IGetErrorString(error)); + numberOfIntParametersToTry -= decrement; + continue; + } + + size_t globalDim[3]={1,1,1}, localDim[3]={1,1,1}; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, globalDim, localDim, 0, NULL, &event); + if (error != CL_SUCCESS) { + log_info( "clEnqueueNDRangeKernel failed (%s), decrementing number of parameters to try.\n", IGetErrorString(error)); + numberOfIntParametersToTry -= decrement; + continue; + } + + // Verify that the event does not return an error from the execution + error = clWaitForEvents(1, &event); + test_error( error, "clWaitForEvent failed"); + error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL); + test_error( error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed"); + clReleaseEvent(event); + if (event_status < 0) + test_error(error, "Kernel execution event returned error"); + + if(gHasLong) + error = clEnqueueReadBuffer(queue, mem, CL_TRUE, 0, sizeof(cl_long), &long_result, 0, NULL, NULL); + else + error = clEnqueueReadBuffer(queue, mem, CL_TRUE, 0, sizeof(cl_int), &int_result, 0, NULL, NULL); + + test_error(error, "clEnqueueReadBuffer failed") + + free(data); + free(argumentLine); + free(codeLines); + free(programSrc); + + if(gHasLong) + { + if (long_result != expectedResult) { + log_error("Expected result (%lld) does not equal actual result (%lld).\n", expectedResult, long_result); + numberOfIntParametersToTry -= decrement; + continue; + } else { + log_info("Results verified at %ld bytes of arguments.\n", sizeof(cl_mem)+numberOfIntParametersToTry*sizeof(cl_long)); + break; + } + } + else + { + if (int_result != expectedResult) { + log_error("Expected result (%lld) does not equal actual result (%d).\n", expectedResult, int_result); + numberOfIntParametersToTry -= decrement; + continue; + } else { + log_info("Results verified at %ld bytes of arguments.\n", sizeof(cl_mem)+numberOfIntParametersToTry*sizeof(cl_int)); + break; + } + } + } + + if (numberOfIntParametersToTry == (long)numberExpected) + return 0; + return -1; +} + +int test_min_max_samplers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_uint maxSamplers, i; + clProgramWrapper program; + clKernelWrapper kernel; + char *programSrc, samplerLine[1024]; + size_t maxParameterSize; + cl_event event; + cl_int event_status; + cl_uint minRequiredSamplers = gIsEmbedded ? 8 : 16; + + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ) + + /* Get the max value */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_SAMPLERS, sizeof( maxSamplers ), &maxSamplers, NULL ); + test_error( error, "Unable to get max sampler count from device" ); + + if( maxSamplers < minRequiredSamplers ) + { + log_error( "ERROR: Reported max sampler count is less than required! (%d)\n", (int)maxSamplers ); + return -1; + } + + log_info("Reported max %d samplers.\n", maxSamplers); + + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof( maxParameterSize ), &maxParameterSize, NULL ); + test_error( error, "Unable to get max parameter size from device" ); + + // Subtract the size of the result + maxParameterSize -= 2*sizeof(cl_mem); + + // Calculate the number we can use + if (maxParameterSize/sizeof(cl_sampler) < maxSamplers) { + log_info("WARNING: Max parameter size of %d bytes limits test to %d max sampler arguments.\n", (int)maxParameterSize, (int)(maxParameterSize/sizeof(cl_sampler))); + maxSamplers = (unsigned int)(maxParameterSize/sizeof(cl_sampler)); + } + + /* Create a kernel to test with */ + programSrc = (char *)malloc( ( strlen( sample_sampler_kernel_pattern[ 1 ] ) + 8 ) * ( maxSamplers ) + + strlen( sample_sampler_kernel_pattern[ 0 ] ) + strlen( sample_sampler_kernel_pattern[ 2 ] ) + + ( strlen( sample_sampler_kernel_pattern[ 3 ] ) + 8 ) * maxSamplers + + strlen( sample_sampler_kernel_pattern[ 4 ] ) ); + strcpy( programSrc, sample_sampler_kernel_pattern[ 0 ] ); + for( i = 0; i < maxSamplers; i++ ) + { + sprintf( samplerLine, sample_sampler_kernel_pattern[ 1 ], i ); + strcat( programSrc, samplerLine ); + } + strcat( programSrc, sample_sampler_kernel_pattern[ 2 ] ); + for( i = 0; i < maxSamplers; i++ ) + { + sprintf( samplerLine, sample_sampler_kernel_pattern[ 3 ], i ); + strcat( programSrc, samplerLine ); + } + strcat( programSrc, sample_sampler_kernel_pattern[ 4 ] ); + + + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&programSrc, "sample_test"); + test_error( error, "Failed to create the program and kernel."); + + // We have to set up some fake parameters so it'll work + clSamplerWrapper *samplers = new clSamplerWrapper[maxSamplers]; + + cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 }; + + clMemWrapper image = create_image_2d( context, CL_MEM_READ_WRITE, &format, 16, 16, 0, NULL, &error ); + test_error( error, "Unable to create a test image" ); + + clMemWrapper stream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), 16, NULL, &error ); + test_error( error, "Unable to create test buffer" ); + + error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &image ); + error |= clSetKernelArg( kernel, 1, sizeof( cl_mem ), &stream ); + test_error( error, "Unable to set kernel arguments" ); + for( i = 0; i < maxSamplers; i++ ) + { + samplers[ i ] = clCreateSampler( context, CL_FALSE, CL_ADDRESS_NONE, CL_FILTER_NEAREST, &error ); + test_error( error, "Unable to create sampler" ); + + error = clSetKernelArg( kernel, 2 + i, sizeof( cl_sampler ), &samplers[ i ] ); + test_error( error, "Unable to set sampler argument" ); + } + + size_t globalDim[3]={1,1,1}, localDim[3]={1,1,1}; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, globalDim, localDim, 0, NULL, &event); + test_error(error, "clEnqueueNDRangeKernel failed with maximum number of samplers."); + + // Verify that the event does not return an error from the execution + error = clWaitForEvents(1, &event); + test_error( error, "clWaitForEvent failed"); + error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL); + test_error( error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed"); + clReleaseEvent(event); + if (event_status < 0) + test_error(error, "Kernel execution event returned error"); + + free( programSrc ); + delete[] samplers; + return 0; +} + +#define PASSING_FRACTION 4 +int test_min_max_constant_buffer_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[3]; + size_t threads[1], localThreads[1]; + cl_int *constantData, *resultData; + cl_ulong maxSize, stepSize, currentSize; + int i; + cl_event event; + cl_int event_status; + MTdata d; + + /* Verify our test buffer won't be bigger than allowed */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof( maxSize ), &maxSize, 0 ); + test_error( error, "Unable to get max constant buffer size" ); + + if( ( 0 == gIsEmbedded && maxSize < 64L * 1024L ) || maxSize < 1L * 1024L ) + { + log_error( "ERROR: Reported max constant buffer size less than required by OpenCL 1.0 (reported %d KB)\n", (int)( maxSize / 1024L ) ); + return -1; + } + + log_info("Reported max constant buffer size of %lld bytes.\n", maxSize); + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_const_arg_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Try the returned max size and decrease it until we get one that works. */ + stepSize = maxSize/16; + currentSize = maxSize; + int allocPassed = 0; + d = init_genrand( gRandomSeed ); + while (!allocPassed && currentSize >= maxSize/PASSING_FRACTION) { + log_info("Attempting to allocate constant buffer of size %lld bytes\n", maxSize); + + /* Create some I/O streams */ + size_t sizeToAllocate = ((size_t)currentSize/sizeof( cl_int ))*sizeof(cl_int); + size_t numberOfInts = sizeToAllocate/sizeof(cl_int); + constantData = (cl_int *)malloc( sizeToAllocate); + for(i=0; i<(int)(numberOfInts); i++) + constantData[i] = (int)genrand_int32(d); + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeToAllocate, constantData, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeToAllocate, NULL, &error); + test_error( error, "Creating test array failed" ); + + + /* Set the arguments */ + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + + + /* Test running the kernel and verifying it */ + threads[0] = numberOfInts; + localThreads[0] = 1; + log_info("Filling constant buffer with %d cl_ints (%d bytes).\n", (int)threads[0], (int)(threads[0]*sizeof(cl_int))); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, &event ); + /* If we failed due to a resource issue, reduce the size and try again. */ + if ((error == CL_OUT_OF_RESOURCES) || (error == CL_MEM_OBJECT_ALLOCATION_FAILURE) || (error == CL_OUT_OF_HOST_MEMORY)) { + log_info("Kernel enqueue failed at size %lld, trying at a reduced size.\n", currentSize); + currentSize -= stepSize; + free(constantData); + continue; + } + test_error( error, "clEnqueueNDRangeKernel with maximum constant buffer size failed."); + + // Verify that the event does not return an error from the execution + error = clWaitForEvents(1, &event); + test_error( error, "clWaitForEvent failed"); + error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL); + test_error( error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed"); + clReleaseEvent(event); + if (event_status < 0) { + if ((event_status == CL_OUT_OF_RESOURCES) || (event_status == CL_MEM_OBJECT_ALLOCATION_FAILURE) || (event_status == CL_OUT_OF_HOST_MEMORY)) { + log_info("Kernel event indicates failure at size %lld, trying at a reduced size.\n", currentSize); + currentSize -= stepSize; + free(constantData); + continue; + } else { + test_error(error, "Kernel execution event returned error"); + } + } + + /* Otherwise we did not fail due to resource issues. */ + allocPassed = 1; + + resultData = (cl_int *)malloc(sizeToAllocate); + error = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, sizeToAllocate, resultData, 0, NULL, NULL); + test_error( error, "clEnqueueReadBuffer failed"); + + for(i=0; i<(int)(numberOfInts); i++) + if (constantData[i] != resultData[i]) { + log_error("Data failed to verify: constantData[%d]=%d != resultData[%d]=%d\n", + i, constantData[i], i, resultData[i]); + free( constantData ); + free(resultData); + free_mtdata(d); d = NULL; + return -1; + } + + free( constantData ); + free(resultData); + } + free_mtdata(d); d = NULL; + + if (allocPassed) { + if (currentSize < maxSize/PASSING_FRACTION) { + log_error("Failed to allocate at least 1/4 of the reported constant size.\n"); + return -1; + } else if (currentSize != maxSize) { + log_info("Passed at reduced size. (%lld of %lld bytes)\n", currentSize, maxSize); + return 0; + } + return 0; + } + return -1; +} + +int test_min_max_constant_args(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper *streams; + size_t threads[1], localThreads[1]; + cl_uint i, maxArgs; + cl_ulong maxSize; + cl_ulong maxParameterSize; + size_t individualBufferSize; + char *programSrc, *constArgs, *str2; + char str[512]; + const char *ptr; + cl_event event; + cl_int event_status; + + + /* Verify our test buffer won't be bigger than allowed */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_CONSTANT_ARGS, sizeof( maxArgs ), &maxArgs, 0 ); + test_error( error, "Unable to get max constant arg count" ); + + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof( maxParameterSize ), &maxParameterSize, NULL ); + test_error( error, "Unable to get max parameter size from device" ); + + // Subtract the size of the result + maxParameterSize -= sizeof(cl_mem); + + // Calculate the number we can use + if (maxParameterSize/sizeof(cl_mem) < maxArgs) { + log_info("WARNING: Max parameter size of %d bytes limits test to %d max image arguments.\n", (int)maxParameterSize, (int)(maxParameterSize/sizeof(cl_mem))); + maxArgs = (unsigned int)(maxParameterSize/sizeof(cl_mem)); + } + + + if( maxArgs < (gIsEmbedded ? 4 : 8) ) + { + log_error( "ERROR: Reported max constant arg count less than required by OpenCL 1.0 (reported %d)\n", (int)maxArgs ); + return -1; + } + + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof( maxSize ), &maxSize, 0 ); + test_error( error, "Unable to get max constant buffer size" ); + individualBufferSize = ((int)maxSize/2)/maxArgs; + + log_info("Reported max constant arg count of %d and max constant buffer size of %d. Test will attempt to allocate half of that, or %d buffers of size %d.\n", + (int)maxArgs, (int)maxSize, (int)maxArgs, (int)individualBufferSize); + + str2 = (char*)malloc(sizeof(char)*32*(maxArgs+2)); + constArgs = (char*)malloc(sizeof(char)*32*(maxArgs+2)); + programSrc = (char*)malloc(sizeof(char)*32*2*(maxArgs+2)+1024); + + /* Create a test program */ + constArgs[0] = 0; + str2[0] = 0; + for( i = 0; i < maxArgs-1; i++ ) + { + sprintf( str, ", __constant int *src%d", (int)( i + 2 ) ); + strcat( constArgs, str ); + sprintf( str2 + strlen( str2), "\tdst[tid] += src%d[tid];\n", (int)(i+2)); + if (strlen(str2) > (sizeof(char)*32*(maxArgs+2)-32) || strlen(constArgs) > (sizeof(char)*32*(maxArgs+2)-32)) { + log_info("Limiting number of arguments tested to %d due to test program allocation size.\n", i); + break; + } + } + sprintf( programSrc, sample_const_max_arg_kernel_pattern, constArgs, str2 ); + + /* Create a kernel to test with */ + ptr = programSrc; + if( create_single_kernel_helper( context, &program, &kernel, 1, &ptr, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + streams = new clMemWrapper[ maxArgs + 1 ]; + for( i = 0; i < maxArgs + 1; i++ ) + { + streams[i] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), individualBufferSize, NULL, &error); + test_error( error, "Creating test array failed" ); + } + + /* Set the arguments */ + for( i = 0; i < maxArgs + 1; i++ ) + { + error = clSetKernelArg(kernel, i, sizeof( streams[i] ), &streams[i]); + test_error( error, "Unable to set kernel argument" ); + } + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)10; + while (threads[0]*sizeof(cl_int) > individualBufferSize) + threads[0]--; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, &event ); + test_error( error, "clEnqueueNDRangeKernel failed"); + + // Verify that the event does not return an error from the execution + error = clWaitForEvents(1, &event); + test_error( error, "clWaitForEvent failed"); + error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL); + test_error( error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed"); + clReleaseEvent(event); + if (event_status < 0) + test_error(error, "Kernel execution event returned error"); + + error = clFinish(queue); + test_error( error, "clFinish failed."); + + delete [] streams; + free(str2); + free(constArgs); + free(programSrc); + return 0; +} + +int test_min_max_compute_units(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_uint value; + + + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof( value ), &value, 0 ); + test_error( error, "Unable to get compute unit count" ); + + if( value < 1 ) + { + log_error( "ERROR: Reported compute unit count less than required by OpenCL 1.0 (reported %d)\n", (int)value ); + return -1; + } + + log_info("Reported %d max compute units.\n", value); + + return 0; +} + +int test_min_max_address_bits(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_uint value; + + + error = clGetDeviceInfo( deviceID, CL_DEVICE_ADDRESS_BITS, sizeof( value ), &value, 0 ); + test_error( error, "Unable to get address bit count" ); + + if( value != 32 && value != 64 ) + { + log_error( "ERROR: Reported address bit count not valid by OpenCL 1.0 (reported %d)\n", (int)value ); + return -1; + } + + log_info("Reported %d device address bits.\n", value); + + return 0; +} + +int test_min_max_single_fp_config(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_device_fp_config value; + char profile[128] = ""; + + error = clGetDeviceInfo( deviceID, CL_DEVICE_SINGLE_FP_CONFIG, sizeof( value ), &value, 0 ); + test_error( error, "Unable to get device single fp config" ); + + //Check to see if we are an embedded profile device + if((error = clGetDeviceInfo( deviceID, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL ))) + { + log_error( "FAILURE: Unable to get CL_DEVICE_PROFILE: error %d\n", error ); + return error; + } + + if( 0 == strcmp( profile, "EMBEDDED_PROFILE" )) + { // embedded device + + if( 0 == (value & (CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO))) + { + log_error( "FAILURE: embedded device supports neither CL_FP_ROUND_TO_NEAREST or CL_FP_ROUND_TO_ZERO\n" ); + return -1; + } + } + else + { // Full profile + if( ( value & ( CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN )) != ( CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN ) ) + { + log_error( "ERROR: Reported single fp config doesn't meet minimum set by OpenCL 1.0 (reported 0x%08x)\n", (int)value ); + return -1; + } + } + return 0; +} + +int test_min_max_double_fp_config(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_device_fp_config value; + + error = clGetDeviceInfo( deviceID, CL_DEVICE_DOUBLE_FP_CONFIG, sizeof( value ), &value, 0 ); + test_error( error, "Unable to get device double fp config" ); + + if (value == 0) + return 0; + + if( ( value & (CL_FP_FMA | CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO | CL_FP_ROUND_TO_INF | CL_FP_INF_NAN | CL_FP_DENORM)) != ( CL_FP_FMA | CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO | CL_FP_ROUND_TO_INF | CL_FP_INF_NAN | CL_FP_DENORM) ) + { + log_error( "ERROR: Reported double fp config doesn't meet minimum set by OpenCL 1.0 (reported 0x%08x)\n", (int)value ); + return -1; + } + return 0; +} + +int test_min_max_local_mem_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[3]; + size_t threads[1], localThreads[1]; + cl_int *localData, *resultData; + cl_ulong maxSize, kernelLocalUsage, min_max_local_mem_size; + cl_char buffer[ 4098 ]; + size_t length; + int i; + int err = 0; + MTdata d; + + /* Verify our test buffer won't be bigger than allowed */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_LOCAL_MEM_SIZE, sizeof( maxSize ), &maxSize, 0 ); + test_error( error, "Unable to get max local buffer size" ); + + // Device version should fit the regex "OpenCL [0-9]+\.[0-9]+ *.*" + error = clGetDeviceInfo( deviceID, CL_DEVICE_VERSION, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get device version string" ); + if (!gIsEmbedded) + { + if( memcmp( buffer, "OpenCL 2.0", strlen( "OpenCL 2.0" ) ) == 0 ) + min_max_local_mem_size = 16L * 1024L; + else if( memcmp( buffer, "OpenCL 1.2", strlen( "OpenCL 1.2" ) ) != 0 ) + min_max_local_mem_size = 16L * 1024L; + else if( memcmp( buffer, "OpenCL 1.1", strlen( "OpenCL 1.1" ) ) != 0 ) + min_max_local_mem_size = 16L * 1024L; + else if ( memcmp( buffer, "OpenCL 1.0", strlen( "OpenCL 1.0" ) ) != 0 ) + min_max_local_mem_size = 32L * 1024L; + else + { + log_error( "ERROR: device version string does not match required format! (returned: %s)\n", (char *)buffer ); + return -1; + } + } + + if( maxSize < (gIsEmbedded ? 1L * 1024L : min_max_local_mem_size) ) + { + log_error( "ERROR: Reported local mem size less than required by OpenCL 1.1 (reported %dKb)\n", (int)( maxSize / 1024L ) ); + return -1; + } + + log_info("Reported max local buffer size for device: %lld bytes.\n", maxSize); + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_local_arg_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + error = clGetKernelWorkGroupInfo(kernel, deviceID, CL_KERNEL_LOCAL_MEM_SIZE, sizeof(kernelLocalUsage), &kernelLocalUsage, NULL); + test_error(error, "clGetKernelWorkGroupInfo for CL_KERNEL_LOCAL_MEM_SIZE failed"); + + log_info("Reported local buffer usage for kernel (CL_KERNEL_LOCAL_MEM_SIZE): %lld bytes.\n", kernelLocalUsage); + + /* Create some I/O streams */ + size_t sizeToAllocate = ((size_t)(maxSize-kernelLocalUsage)/sizeof( cl_int ))*sizeof(cl_int); + size_t numberOfInts = sizeToAllocate/sizeof(cl_int); + + log_info("Attempting to use %lld bytes of local memory.\n", (cl_ulong)sizeToAllocate); + + localData = (cl_int *)malloc( sizeToAllocate ); + d = init_genrand( gRandomSeed ); + for(i=0; i<(int)(numberOfInts); i++) + localData[i] = (int)genrand_int32(d); + free_mtdata(d); d = NULL; + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeToAllocate, localData, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeToAllocate, NULL, &error); + test_error( error, "Creating test array failed" ); + + + /* Set the arguments */ + error = clSetKernelArg(kernel, 0, sizeToAllocate, NULL); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 2, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + + + /* Test running the kernel and verifying it */ + threads[0] = numberOfInts; + localThreads[0] = 1; + log_info("Creating local buffer with %d cl_ints (%d bytes).\n", (int)numberOfInts, (int)sizeToAllocate); + + cl_event evt; + cl_int evt_err; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, &evt ); + test_error(error, "clEnqueueNDRangeKernel failed"); + + error = clFinish(queue); + test_error( error, "clFinish failed"); + + error = clGetEventInfo(evt, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof evt_err, &evt_err, NULL); + test_error( error, "clGetEventInfo with maximum local buffer size failed."); + + if (evt_err != CL_COMPLETE) { + print_error(evt_err, "Kernel event returned error"); + clReleaseEvent(evt); + return -1; + } + + resultData = (cl_int *)malloc(sizeToAllocate); + + error = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, sizeToAllocate, resultData, 0, NULL, NULL); + test_error( error, "clEnqueueReadBuffer failed"); + + for(i=0; i<(int)(numberOfInts); i++) + if (localData[i] != resultData[i]) { + clReleaseEvent(evt); + free( localData ); + free(resultData); + log_error("Results failed to verify.\n"); + return -1; + } + clReleaseEvent(evt); + free( localData ); + free(resultData); + + return err; +} + +int test_min_max_kernel_preferred_work_group_size_multiple(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int err; + clProgramWrapper program; + clKernelWrapper kernel; + + size_t max_local_workgroup_size[3]; + size_t max_workgroup_size = 0, preferred_workgroup_size = 0; + + err = create_single_kernel_helper(context, &program, &kernel, 1, sample_local_arg_kernel, "sample_test" ); + test_error(err, "Failed to build kernel/program."); + + err = clGetKernelWorkGroupInfo(kernel, deviceID, CL_KERNEL_WORK_GROUP_SIZE, + sizeof(max_workgroup_size), &max_workgroup_size, NULL); + test_error(err, "clGetKernelWorkgroupInfo failed."); + + err = clGetKernelWorkGroupInfo(kernel, deviceID, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, + sizeof(preferred_workgroup_size), &preferred_workgroup_size, NULL); + test_error(err, "clGetKernelWorkgroupInfo failed."); + + err = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(max_local_workgroup_size), max_local_workgroup_size, NULL); + test_error(err, "clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_SIZES"); + + // Since the preferred size is only a performance hint, we can only really check that we get a sane value + // back + log_info( "size: %ld preferred: %ld max: %ld\n", max_workgroup_size, preferred_workgroup_size, max_local_workgroup_size[0] ); + + if( preferred_workgroup_size > max_workgroup_size ) + { + log_error( "ERROR: Reported preferred workgroup multiple larger than max workgroup size (preferred %ld, max %ld)\n", preferred_workgroup_size, max_workgroup_size ); + return -1; + } + + return 0; +} + +int test_min_max_execution_capabilities(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_device_exec_capabilities value; + + + error = clGetDeviceInfo( deviceID, CL_DEVICE_EXECUTION_CAPABILITIES, sizeof( value ), &value, 0 ); + test_error( error, "Unable to get execution capabilities" ); + + if( ( value & CL_EXEC_KERNEL ) != CL_EXEC_KERNEL ) + { + log_error( "ERROR: Reported execution capabilities less than required by OpenCL 1.0 (reported 0x%08x)\n", (int)value ); + return -1; + } + return 0; +} + +int test_min_max_queue_properties(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_command_queue_properties value; + + + error = clGetDeviceInfo( deviceID, CL_DEVICE_QUEUE_PROPERTIES, sizeof( value ), &value, 0 ); + test_error( error, "Unable to get queue properties" ); + + if( ( value & CL_QUEUE_PROFILING_ENABLE ) != CL_QUEUE_PROFILING_ENABLE ) + { + log_error( "ERROR: Reported queue properties less than required by OpenCL 1.0 (reported 0x%08x)\n", (int)value ); + return -1; + } + return 0; +} + +int test_min_max_device_version(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int error, i; + cl_char buffer[ 4098 ]; + size_t length; + + + // Device version should fit the regex "OpenCL [0-9]+\.[0-9]+ *.*" + error = clGetDeviceInfo( deviceID, CL_DEVICE_VERSION, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get device version string" ); + if( memcmp( buffer, "OpenCL ", strlen( "OpenCL " ) ) != 0 ) + { + log_error( "ERROR: Initial part of device version string does not match required format! (returned: %s)\n", (char *)buffer ); + return -1; + } + + log_info("Returned version %s.\n", buffer); + + char *p1 = (char *)buffer + strlen( "OpenCL " ); + while( *p1 == ' ' ) + p1++; + char *p2 = p1; + if( ! isdigit(*p2) ) + { + log_error( "ERROR: Major revision number must follow space behind OpenCL! (returned %s)\n", (char*) buffer ); + return -1; + } + while( isdigit( *p2 ) ) + p2++; + if( *p2 != '.' ) + { + log_error( "ERROR: Version number must contain a decimal point! (returned: %s)\n", (char *)buffer ); + return -1; + } + char *p3 = p2 + 1; + if( ! isdigit(*p3) ) + { + log_error( "ERROR: Minor revision number is missing or does not abut the decimal point! (returned %s)\n", (char*) buffer ); + return -1; + } + while( isdigit( *p3 ) ) + p3++; + if( *p3 != ' ' ) + { + log_error( "ERROR: A space must appear after the minor version! (returned: %s)\n", (char *)buffer ); + return -1; + } + *p2 = ' '; // Put in a space for atoi below. + p2++; + + int major = atoi( p1 ); + int minor = atoi( p2 ); + int minor_revision = 2; + if( getenv("OPENCL_1_0_DEVICE")) + { + minor_revision = 0; + log_info( "WARNING: This test was run with OPENCL_1_0_DEVICE defined! This is not a OpenCL 1.1 or OpenCL 1.2 compatible device!!!\n" ); + } + else if( getenv("OPENCL_1_1_DEVICE")) + { + minor_revision = 1; + log_info( "WARNING: This test was run with OPENCL_1_1_DEVICE defined! This is not a OpenCL 1.2 compatible device!!!\n" ); + } + if( major * 10 + minor < 10 + minor_revision ) + { + log_error( "ERROR: OpenCL device version returned is less than 1.%d! (Returned: %s)\n", minor_revision, (char *)buffer ); + return -1; + } + + // Sanity checks on the returned values + if( length != (strlen( (char *)buffer ) + 1 )) + { + log_error( "ERROR: Returned length of version string does not match actual length (actual: %d, returned: %d)\n", (int)strlen( (char *)buffer ), (int)length ); + return -1; + } + + // Make sure 1.1 devices support required extensions for 1.1 + const char *requiredExtensions[] = + { + "cl_khr_global_int32_base_atomics", + "cl_khr_global_int32_extended_atomics", + "cl_khr_local_int32_base_atomics", + "cl_khr_local_int32_extended_atomics", + "cl_khr_byte_addressable_store", + NULL + }; + + if( major * 10 + minor >= 11 ) + { + char *extensions; + size_t extensions_size = 0; + + log_info( "Checking for required extensions for OpenCL 1.1 and later devices...\n" ); + + if( (error = clGetDeviceInfo(deviceID, CL_DEVICE_EXTENSIONS, 0, NULL, &extensions_size))) + { + log_error( "ERROR: could not get extensions size. Err # %d\n", error ); + return -1; + } + + if( extensions_size < 1 ) + { + log_error( "ERROR: invalid extensions size. Err # %d\n", error ); + return -1; + } + + extensions = (char*) malloc(extensions_size); + if( NULL == extensions ) + { + log_error( "ERROR: cannot allocate %ld bytes to hold extension string.\n", extensions_size ); + return -1; + } + memset( extensions, -1, extensions_size ); + + if( (error = clGetDeviceInfo(deviceID, CL_DEVICE_EXTENSIONS, extensions_size, extensions, NULL))) + { + log_error( "ERROR: could not get extensions. Err # %d\n", error ); + free( extensions ); + return -1; + } + + if( '\0' != extensions[ extensions_size - 1 ] ) + { + if( -1 == extensions[ extensions_size - 1 ] ) + log_error( "ERROR: extensions size reported incorrectly. Last byte is not NUL. Size too big. Reported: %ld. Should be: %ld\n", extensions_size, strlen(extensions) + 1 ); + else + log_error( "ERROR: extensions size reported incorrectly. Last byte is not NUL. Size too small. \n" ); + + free( extensions ); + return -1; + } + + for( i = 0; NULL != requiredExtensions[i]; i++ ) + { + if( NULL == strstr( extensions, requiredExtensions[i] ) ) + { + log_error( "ERROR: Required extension for 1.1 and greater devices is not in extension string: %s\n", requiredExtensions[i] ); + free( extensions ); + return -1; + } + else + log_info( "\t%s\n", requiredExtensions[i] ); + } + free( extensions ); + } + else + log_info( "WARNING: skipping required extension test -- OpenCL 1.0 device.\n" ); + + + return 0; +} + +int test_min_max_language_version(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int error; + cl_char buffer[ 4098 ]; + size_t length; + + // Device version should fit the regex "OpenCL [0-9]+\.[0-9]+ *.*" + error = clGetDeviceInfo( deviceID, CL_DEVICE_OPENCL_C_VERSION, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get device opencl c version string" ); + if( memcmp( buffer, "OpenCL C ", strlen( "OpenCL C " ) ) != 0 ) + { + log_error( "ERROR: Initial part of device language version string does not match required format! (returned: \"%s\")\n", (char *)buffer ); + return -1; + } + + log_info("Returned version \"%s\".\n", buffer); + + char *p1 = (char *)buffer + strlen( "OpenCL C " ); + while( *p1 == ' ' ) + p1++; + char *p2 = p1; + if( ! isdigit(*p2) ) + { + log_error( "ERROR: Major revision number must follow space behind OpenCL C! (returned %s)\n", (char*) buffer ); + return -1; + } + while( isdigit( *p2 ) ) + p2++; + if( *p2 != '.' ) + { + log_error( "ERROR: Version number must contain a decimal point! (returned: %s)\n", (char *)buffer ); + return -1; + } + char *p3 = p2 + 1; + if( ! isdigit(*p3) ) + { + log_error( "ERROR: Minor revision number is missing or does not abut the decimal point! (returned %s)\n", (char*) buffer ); + return -1; + } + while( isdigit( *p3 ) ) + p3++; + if( *p3 != ' ' ) + { + log_error( "ERROR: A space must appear after the minor version! (returned: %s)\n", (char *)buffer ); + return -1; + } + *p2 = ' '; // Put in a space for atoi below. + p2++; + + int major = atoi( p1 ); + int minor = atoi( p2 ); + int minor_revision = 2; + + if( major * 10 + minor < 10 + minor_revision ) + { + // If the language version did not match, check to see if OPENCL_1_0_DEVICE is set. + if( getenv("OPENCL_1_0_DEVICE")) + { + log_info( "WARNING: This test was run with OPENCL_1_0_DEVICE defined! This is not a OpenCL 1.1 or OpenCL 1.2 compatible device!!!\n" ); + } + else if( getenv("OPENCL_1_1_DEVICE")) + { + log_info( "WARNING: This test was run with OPENCL_1_1_DEVICE defined! This is not a OpenCL 1.2 compatible device!!!\n" ); + } + else + { + log_error( "ERROR: OpenCL device language version returned is less than 1.%d! (Returned: %s)\n", minor_revision, (char *)buffer ); + return -1; + } + } + + // Sanity checks on the returned values + if( length != (strlen( (char *)buffer ) + 1 )) + { + log_error( "ERROR: Returned length of version string does not match actual length (actual: %d, returned: %d)\n", (int)strlen( (char *)buffer ), (int)length ); + return -1; + } + + return 0; +} + diff --git a/test_conformance/compatibility/test_conformance/api/test_binary.cpp b/test_conformance/compatibility/test_conformance/api/test_binary.cpp new file mode 100644 index 00000000..02edd49d --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/test_binary.cpp @@ -0,0 +1,226 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +static const char *sample_binary_kernel_source[] = { +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid] + 1;\n" +"\n" +"}\n" }; + + +int test_binary_get(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + size_t binarySize; + + + program = clCreateProgramWithSource( context, 1, sample_binary_kernel_source, NULL, &error ); + test_error( error, "Unable to create program from source" ); + + // Build so we have a binary to get + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build test program" ); + + // Get the size of the resulting binary (only one device) + error = clGetProgramInfo( program, CL_PROGRAM_BINARY_SIZES, sizeof( binarySize ), &binarySize, NULL ); + test_error( error, "Unable to get binary size" ); + + // Sanity check + if( binarySize == 0 ) + { + log_error( "ERROR: Binary size of program is zero\n" ); + return -1; + } + + // Create a buffer and get the actual binary + unsigned char *binary; + binary = (unsigned char*)malloc(sizeof(unsigned char)*binarySize); + unsigned char *buffers[ 1 ] = { binary }; + + // Do another sanity check here first + size_t size; + error = clGetProgramInfo( program, CL_PROGRAM_BINARIES, 0, NULL, &size ); + test_error( error, "Unable to get expected size of binaries array" ); + if( size != sizeof( buffers ) ) + { + log_error( "ERROR: Expected size of binaries array in clGetProgramInfo is incorrect (should be %d, got %d)\n", (int)sizeof( buffers ), (int)size ); + free(binary); + return -1; + } + + error = clGetProgramInfo( program, CL_PROGRAM_BINARIES, sizeof( buffers ), &buffers, NULL ); + test_error( error, "Unable to get program binary" ); + + // No way to verify the binary is correct, so just be good with that + free(binary); + return 0; +} + + +int test_program_binary_create(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + /* To test this in a self-contained fashion, we have to create a program with + source, then get the binary, then use that binary to reload the program, and then verify */ + + int error; + clProgramWrapper program, program_from_binary; + size_t binarySize; + + + program = clCreateProgramWithSource( context, 1, sample_binary_kernel_source, NULL, &error ); + test_error( error, "Unable to create program from source" ); + + // Build so we have a binary to get + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build test program" ); + + // Get the size of the resulting binary (only one device) + error = clGetProgramInfo( program, CL_PROGRAM_BINARY_SIZES, sizeof( binarySize ), &binarySize, NULL ); + test_error( error, "Unable to get binary size" ); + + // Sanity check + if( binarySize == 0 ) + { + log_error( "ERROR: Binary size of program is zero\n" ); + return -1; + } + + // Create a buffer and get the actual binary + unsigned char *binary = (unsigned char*)malloc(binarySize); + const unsigned char *buffers[ 1 ] = { binary }; + + error = clGetProgramInfo( program, CL_PROGRAM_BINARIES, sizeof( buffers ), &buffers, NULL ); + test_error( error, "Unable to get program binary" ); + + cl_int loadErrors[ 1 ]; + program_from_binary = clCreateProgramWithBinary( context, 1, &deviceID, &binarySize, buffers, loadErrors, &error ); + test_error( error, "Unable to load valid program binary" ); + test_error( loadErrors[ 0 ], "Unable to load valid device binary into program" ); + + error = clBuildProgram( program_from_binary, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build binary program" ); + + // Get the size of the binary built from the first binary + size_t binary2Size; + error = clGetProgramInfo( program_from_binary, CL_PROGRAM_BINARY_SIZES, sizeof( binary2Size ), &binary2Size, NULL ); + test_error( error, "Unable to get size for the binary program" ); + + // Now get the binary one more time and verify it loaded the right binary + unsigned char *binary2 = (unsigned char*)malloc(binary2Size); + buffers[ 0 ] = binary2; + error = clGetProgramInfo( program_from_binary, CL_PROGRAM_BINARIES, sizeof( buffers ), &buffers, NULL ); + test_error( error, "Unable to get program binary second time" ); + + // Try again, this time without passing the status ptr in, to make sure we still + // get a valid binary + clProgramWrapper programWithoutStatus = clCreateProgramWithBinary( context, 1, &deviceID, &binary2Size, buffers, NULL, &error ); + test_error( error, "Unable to load valid program binary when binary_status pointer is NULL" ); + + error = clBuildProgram( programWithoutStatus, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build binary program created without binary_status" ); + + // Get the size of the binary created without passing binary_status + size_t binary3Size; + error = clGetProgramInfo( programWithoutStatus, CL_PROGRAM_BINARY_SIZES, sizeof( binary3Size ), &binary3Size, NULL ); + test_error( error, "Unable to get size for the binary program created without binary_status" ); + + // Now get the binary one more time + unsigned char *binary3 = (unsigned char*)malloc(binary3Size); + buffers[ 0 ] = binary3; + error = clGetProgramInfo( programWithoutStatus, CL_PROGRAM_BINARIES, sizeof( buffers ), &buffers, NULL ); + test_error( error, "Unable to get program binary from the program created without binary_status" ); + + // We no longer need these intermediate binaries + free(binary); + free(binary2); + free(binary3); + + // Now execute them both to see that they both do the same thing. + clMemWrapper in, out, out_binary; + clKernelWrapper kernel, kernel_binary; + cl_int *out_data, *out_data_binary; + cl_float *in_data; + size_t size_to_run = 1000; + + // Allocate some data + in_data = (cl_float*)malloc(sizeof(cl_float)*size_to_run); + out_data = (cl_int*)malloc(sizeof(cl_int)*size_to_run); + out_data_binary = (cl_int*)malloc(sizeof(cl_int)*size_to_run); + memset(out_data, 0, sizeof(cl_int)*size_to_run); + memset(out_data_binary, 0, sizeof(cl_int)*size_to_run); + for (size_t i=0; i -0.5f);\n" + " if(myBool)\n" + " {\n" + " dst[tid] = (int)src[tid];\n" + " }\n" + " else\n" + " {\n" + " dst[tid] = 0;\n" + " }\n" + "\n" + "}\n" +}; + +int test_for_bool_type(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements) +{ + + cl_program program; + cl_kernel kernel; + + int err = create_single_kernel_helper(context, + &program, + &kernel, + 1, kernel_with_bool, + "kernel_with_bool" ); + return err; +} + diff --git a/test_conformance/compatibility/test_conformance/api/test_create_context_from_type.cpp b/test_conformance/compatibility/test_conformance/api/test_create_context_from_type.cpp new file mode 100644 index 00000000..2339aad8 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/test_create_context_from_type.cpp @@ -0,0 +1,130 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +#ifndef _WIN32 +#include +#endif + +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/conversions.h" + +extern cl_uint gRandomSeed; + +int test_create_context_from_type(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + clContextWrapper context_to_test; + clCommandQueueWrapper queue_to_test; + size_t threads[1], localThreads[1]; + cl_float inputData[10]; + cl_int outputData[10]; + int i; + RandomSeed seed( gRandomSeed ); + + const char *sample_single_test_kernel[] = { + "__kernel void sample_test(__global float *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (int)src[tid];\n" + "\n" + "}\n" }; + + cl_device_type type; + error = clGetDeviceInfo(deviceID, CL_DEVICE_TYPE, sizeof(type), &type, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_TYPE failed\n"); + + cl_platform_id platform; + error = clGetDeviceInfo(deviceID, CL_DEVICE_PLATFORM, sizeof(platform), &platform, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_PLATFORM failed\n"); + + cl_context_properties properties[3] = { + (cl_context_properties)CL_CONTEXT_PLATFORM, + (cl_context_properties)platform, + NULL + }; + + context_to_test = clCreateContextFromType(properties, type, notify_callback, NULL, &error); + test_error(error, "clCreateContextFromType failed"); + if (context_to_test == NULL) { + log_error("clCreateContextFromType returned NULL, but error was CL_SUCCESS."); + return -1; + } + + queue_to_test = clCreateCommandQueue(context_to_test, deviceID, NULL, &error); + test_error(error, "clCreateCommandQueue failed"); + if (queue_to_test == NULL) { + log_error("clCreateCommandQueue returned NULL, but error was CL_SUCCESS."); + return -1; + } + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context_to_test, &program, &kernel, 1, sample_single_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + streams[0] = clCreateBuffer(context_to_test, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context_to_test, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Write some test data */ + memset( outputData, 0, sizeof( outputData ) ); + + for (i=0; i<10; i++) + inputData[i] = get_random_float(-(float) 0x7fffffff, (float) 0x7fffffff, seed); + + error = clEnqueueWriteBuffer(queue_to_test, streams[0], CL_TRUE, 0, sizeof(cl_float)*10, (void *)inputData, 0, NULL, NULL); + test_error( error, "Unable to set testing kernel data" ); + + /* Test setting the arguments by index manually */ + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)10; + + error = get_max_common_work_group_size( context_to_test, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue_to_test, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue_to_test, streams[1], CL_TRUE, 0, sizeof(cl_int)*10, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<10; i++) + { + if (outputData[i] != (int)inputData[i]) + { + log_error( "ERROR: Data did not verify on first pass!\n" ); + return -1; + } + } + + return 0; +} + + diff --git a/test_conformance/compatibility/test_conformance/api/test_create_kernels.c b/test_conformance/compatibility/test_conformance/api/test_create_kernels.c new file mode 100644 index 00000000..438300b1 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/test_create_kernels.c @@ -0,0 +1,643 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/testHarness.h" + + +const char *sample_single_kernel[] = { + "__kernel void sample_test(__global float *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (int)src[tid];\n" + "\n" + "}\n" }; + +size_t sample_single_kernel_lengths[1]; + +const char *sample_two_kernels[] = { + "__kernel void sample_test(__global float *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (int)src[tid];\n" + "\n" + "}\n", + "__kernel void sample_test2(__global int *src, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (float)src[tid];\n" + "\n" + "}\n" }; + +size_t sample_two_kernel_lengths[2]; + +const char *sample_two_kernels_in_1[] = { + "__kernel void sample_test(__global float *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (int)src[tid];\n" + "\n" + "}\n" + "__kernel void sample_test2(__global int *src, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = (float)src[tid];\n" + "\n" + "}\n" }; + +size_t sample_two_kernels_in_1_lengths[1]; + + +const char *repeate_test_kernel = +"__kernel void test_kernel(__global int *src, __global int *dst)\n" +"{\n" +" dst[get_global_id(0)] = src[get_global_id(0)]+1;\n" +"}\n"; + + + +int test_load_single_kernel(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + cl_program testProgram; + clKernelWrapper kernel; + cl_context testContext; + unsigned int numKernels; + cl_char testName[512]; + cl_uint testArgCount; + size_t realSize; + + + /* Preprocess: calc the length of each source file line */ + sample_single_kernel_lengths[ 0 ] = strlen( sample_single_kernel[ 0 ] ); + + /* Create a program */ + program = clCreateProgramWithSource( context, 1, sample_single_kernel, sample_single_kernel_lengths, &error ); + if( program == NULL || error != CL_SUCCESS ) + { + print_error( error, "Unable to create single kernel program" ); + return -1; + } + + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build single kernel program" ); + error = clCreateKernelsInProgram(program, 1, &kernel, &numKernels); + test_error( error, "Unable to create single kernel program" ); + + /* Check program and context pointers */ + error = clGetKernelInfo( kernel, CL_KERNEL_PROGRAM, sizeof( cl_program ), &testProgram, &realSize ); + test_error( error, "Unable to get kernel's program" ); + if( (cl_program)testProgram != (cl_program)program ) + { + log_error( "ERROR: Returned kernel's program does not match program used to create it! (Got %p, expected %p)\n", (cl_program)testProgram, (cl_program)program ); + return -1; + } + if( realSize != sizeof( cl_program ) ) + { + log_error( "ERROR: Returned size of kernel's program does not match expected size (expected %d, got %d)\n", (int)sizeof( cl_program ), (int)realSize ); + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_CONTEXT, sizeof( cl_context ), &testContext, &realSize ); + test_error( error, "Unable to get kernel's context" ); + if( (cl_context)testContext != (cl_context)context ) + { + log_error( "ERROR: Returned kernel's context does not match program used to create it! (Got %p, expected %p)\n", (cl_context)testContext, (cl_context)context ); + return -1; + } + if( realSize != sizeof( cl_context ) ) + { + log_error( "ERROR: Returned size of kernel's context does not match expected size (expected %d, got %d)\n", (int)sizeof( cl_context ), (int)realSize ); + return -1; + } + + /* Test arg count */ + error = clGetKernelInfo( kernel, CL_KERNEL_NUM_ARGS, 0, NULL, &realSize ); + test_error( error, "Unable to get size of arg count info from kernel" ); + + if( realSize != sizeof( testArgCount ) ) + { + log_error( "ERROR: size of arg count not valid! %d\n", (int)realSize ); + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_NUM_ARGS, sizeof( testArgCount ), &testArgCount, NULL ); + test_error( error, "Unable to get arg count from kernel" ); + + if( testArgCount != 2 ) + { + log_error( "ERROR: Kernel arg count does not match!\n" ); + return -1; + } + + + /* Test function name */ + error = clGetKernelInfo( kernel, CL_KERNEL_FUNCTION_NAME, sizeof( testName ), testName, &realSize ); + test_error( error, "Unable to get name from kernel" ); + + if( strcmp( (char *)testName, "sample_test" ) != 0 ) + { + log_error( "ERROR: Kernel names do not match!\n" ); + return -1; + } + if( realSize != strlen( (char *)testName ) + 1 ) + { + log_error( "ERROR: Length of kernel name returned does not validate (expected %d, got %d)\n", (int)strlen( (char *)testName ) + 1, (int)realSize ); + return -1; + } + + /* All done */ + + return 0; +} + +int test_load_two_kernels(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel[2]; + unsigned int numKernels; + cl_char testName[ 512 ]; + cl_uint testArgCount; + + + /* Preprocess: calc the length of each source file line */ + sample_two_kernel_lengths[ 0 ] = strlen( sample_two_kernels[ 0 ] ); + sample_two_kernel_lengths[ 1 ] = strlen( sample_two_kernels[ 1 ] ); + + /* Now create a test program */ + program = clCreateProgramWithSource( context, 2, sample_two_kernels, sample_two_kernel_lengths, &error ); + if( program == NULL || error != CL_SUCCESS ) + { + print_error( error, "Unable to create dual kernel program!" ); + return -1; + } + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build dual kernel program" ); + error = clCreateKernelsInProgram(program, 2, &kernel[0], &numKernels); + test_error( error, "Unable to create dual kernel program" ); + + if( numKernels != 2 ) + { + log_error( "ERROR: wrong # of kernels! (%d)\n", numKernels ); + return -1; + } + + /* Check first kernel */ + error = clGetKernelInfo( kernel[0], CL_KERNEL_FUNCTION_NAME, sizeof( testName ), testName, NULL ); + test_error( error, "Unable to get function name from kernel" ); + + int found_kernel1 = 0, found_kernel2 = 0; + + if( strcmp( (char *)testName, "sample_test" ) == 0 ) { + found_kernel1 = 1; + } else if( strcmp( (char *)testName, "sample_test2" ) == 0 ) { + found_kernel2 = 1; + } else { + log_error( "ERROR: Invalid kernel name returned: \"%s\" expected \"%s\" or \"%s\".\n", testName, "sample_test", "sample_test2"); + return -1; + } + + error = clGetKernelInfo( kernel[1], CL_KERNEL_FUNCTION_NAME, sizeof( testName ), testName, NULL ); + test_error( error, "Unable to get function name from second kernel" ); + + if( strcmp( (char *)testName, "sample_test" ) == 0 ) { + if (found_kernel1) { + log_error("Kernel \"%s\" returned twice.\n", (char *)testName); + return -1; + } + found_kernel1 = 1; + } else if( strcmp( (char *)testName, "sample_test2" ) == 0 ) { + if (found_kernel2) { + log_error("Kernel \"%s\" returned twice.\n", (char *)testName); + return -1; + } + found_kernel2 = 1; + } else { + log_error( "ERROR: Invalid kernel name returned: \"%s\" expected \"%s\" or \"%s\".\n", testName, "sample_test", "sample_test2"); + return -1; + } + + if( !found_kernel1 || !found_kernel2 ) + { + log_error( "ERROR: Kernel names do not match.\n" ); + if (!found_kernel1) + log_error("Kernel \"%s\" not returned.\n", "sample_test"); + if (!found_kernel2) + log_error("Kernel \"%s\" not returned.\n", "sample_test"); + return -1; + } + + error = clGetKernelInfo( kernel[0], CL_KERNEL_NUM_ARGS, sizeof( testArgCount ), &testArgCount, NULL ); + test_error( error, "Unable to get arg count from kernel" ); + + if( testArgCount != 2 ) + { + log_error( "ERROR: wrong # of args for kernel\n" ); + return -1; + } + + /* All done */ + return 0; +} + +int test_load_two_kernels_in_one(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel[2]; + unsigned int numKernels; + cl_char testName[512]; + cl_uint testArgCount; + + + /* Preprocess: calc the length of each source file line */ + sample_two_kernels_in_1_lengths[ 0 ] = strlen( sample_two_kernels_in_1[ 0 ] ); + + /* Now create a test program */ + program = clCreateProgramWithSource( context, 1, sample_two_kernels_in_1, sample_two_kernels_in_1_lengths, &error ); + if( program == NULL || error != CL_SUCCESS ) + { + print_error( error, "Unable to create dual kernel program" ); + return -1; + } + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build dual kernel program" ); + error = clCreateKernelsInProgram(program, 2, &kernel[0], &numKernels); + test_error( error, "Unable to create dual kernel program" ); + + if( numKernels != 2 ) + { + log_error( "ERROR: wrong # of kernels! (%d)\n", numKernels ); + return -1; + } + + /* Check first kernel */ + error = clGetKernelInfo( kernel[0], CL_KERNEL_FUNCTION_NAME, sizeof( testName ), testName, NULL ); + test_error( error, "Unable to get function name from kernel" ); + + int found_kernel1 = 0, found_kernel2 = 0; + + if( strcmp( (char *)testName, "sample_test" ) == 0 ) { + found_kernel1 = 1; + } else if( strcmp( (char *)testName, "sample_test2" ) == 0 ) { + found_kernel2 = 1; + } else { + log_error( "ERROR: Invalid kernel name returned: \"%s\" expected \"%s\" or \"%s\".\n", testName, "sample_test", "sample_test2"); + return -1; + } + + error = clGetKernelInfo( kernel[0], CL_KERNEL_NUM_ARGS, sizeof( testArgCount ), &testArgCount, NULL ); + test_error( error, "Unable to get arg count from kernel" ); + + if( testArgCount != 2 ) + { + log_error( "ERROR: wrong # of args for kernel\n" ); + return -1; + } + + /* Check second kernel */ + error = clGetKernelInfo( kernel[1], CL_KERNEL_FUNCTION_NAME, sizeof( testName ), testName, NULL ); + test_error( error, "Unable to get function name from kernel" ); + + if( strcmp( (char *)testName, "sample_test" ) == 0 ) { + if (found_kernel1) { + log_error("Kernel \"%s\" returned twice.\n", (char *)testName); + return -1; + } + found_kernel1 = 1; + } else if( strcmp( (char *)testName, "sample_test2" ) == 0 ) { + if (found_kernel2) { + log_error("Kernel \"%s\" returned twice.\n", (char *)testName); + return -1; + } + found_kernel2 = 1; + } else { + log_error( "ERROR: Invalid kernel name returned: \"%s\" expected \"%s\" or \"%s\".\n", testName, "sample_test", "sample_test2"); + return -1; + } + + if( !found_kernel1 || !found_kernel2 ) + { + log_error( "ERROR: Kernel names do not match.\n" ); + if (!found_kernel1) + log_error("Kernel \"%s\" not returned.\n", "sample_test"); + if (!found_kernel2) + log_error("Kernel \"%s\" not returned.\n", "sample_test"); + return -1; + } + + /* All done */ + return 0; +} + +int test_load_two_kernels_manually( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel1, kernel2; + int error; + + + /* Now create a test program */ + program = clCreateProgramWithSource( context, 1, sample_two_kernels_in_1, NULL, &error ); + if( program == NULL || error != CL_SUCCESS ) + { + print_error( error, "Unable to create dual kernel program" ); + return -1; + } + + /* Compile the program */ + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build kernel program" ); + + /* Try manually creating kernels (backwards just in case) */ + kernel1 = clCreateKernel( program, "sample_test2", &error ); + + if( kernel1 == NULL || error != CL_SUCCESS ) + { + print_error( error, "Could not get kernel 1" ); + return -1; + } + + kernel2 = clCreateKernel( program, "sample_test", &error ); + + if( kernel2 == NULL ) + { + print_error( error, "Could not get kernel 2" ); + return -1; + } + + return 0; +} + +int test_get_program_info_kernel_names( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel1, kernel2; + int error; + size_t i; + + /* Now create a test program */ + program = clCreateProgramWithSource( context, 1, sample_two_kernels_in_1, NULL, &error ); + if( program == NULL || error != CL_SUCCESS ) + { + print_error( error, "Unable to create dual kernel program" ); + return -1; + } + + /* Compile the program */ + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build kernel program" ); + + /* Lookup the number of kernels in the program. */ + size_t total_kernels = 0; + error = clGetProgramInfo(program, CL_PROGRAM_NUM_KERNELS, sizeof(size_t),&total_kernels,NULL); + test_error( error, "Unable to get program info num kernels"); + + if (total_kernels != 2) + { + print_error( error, "Program did not contain two kernels" ); + return -1; + } + + /* Lookup the kernel names. */ + const char* actual_names[] = { "sample_test;sample_test2", "sample_test2;sample_test"} ; + + size_t kernel_names_len = 0; + error = clGetProgramInfo(program,CL_PROGRAM_KERNEL_NAMES,0,NULL,&kernel_names_len); + test_error( error, "Unable to get length of kernel names list." ); + + if (kernel_names_len != (strlen(actual_names[0])+1)) + { + print_error( error, "Kernel names length did not match"); + return -1; + } + + const size_t len = (kernel_names_len+1)*sizeof(char); + char* kernel_names = (char*)malloc(len); + error = clGetProgramInfo(program,CL_PROGRAM_KERNEL_NAMES,len,kernel_names,&kernel_names_len); + test_error( error, "Unable to get kernel names list." ); + + /* Check to see if the kernel name array is null terminated. */ + if (kernel_names[kernel_names_len-1] != '\0') + { + free(kernel_names); + print_error( error, "Kernel name list was not null terminated"); + return -1; + } + + /* Check to see if the correct kernel name string was returned. */ + for( i = 0; i < sizeof( actual_names ) / sizeof( actual_names[0] ); i++ ) + if( 0 == strcmp(actual_names[i],kernel_names) ) + break; + + if (i == sizeof( actual_names ) / sizeof( actual_names[0] ) ) + { + free(kernel_names); + log_error( "Kernel names \"%s\" did not match:\n", kernel_names ); + for( i = 0; i < sizeof( actual_names ) / sizeof( actual_names[0] ); i++ ) + log_error( "\t\t\"%s\"\n", actual_names[0] ); + return -1; + } + free(kernel_names); + + /* Try manually creating kernels (backwards just in case) */ + kernel1 = clCreateKernel( program, "sample_test", &error ); + if( kernel1 == NULL || error != CL_SUCCESS ) + { + print_error( error, "Could not get kernel 1" ); + return -1; + } + + kernel2 = clCreateKernel( program, "sample_test2", &error ); + if( kernel2 == NULL ) + { + print_error( error, "Could not get kernel 2" ); + return -1; + } + + return 0; +} + +static const char *single_task_kernel[] = { + "__kernel void sample_test(__global int *dst, int count)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " for( int i = 0; i < count; i++ )\n" + " dst[i] = tid + i;\n" + "\n" + "}\n" }; + +int test_enqueue_task(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper output; + cl_int count; + + + if( create_single_kernel_helper( context, &program, &kernel, 1, single_task_kernel, "sample_test" ) ) + return -1; + + // Create args + count = 100; + output = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof( cl_int ) * count, NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &output ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 1, sizeof( cl_int ), &count ); + test_error( error, "Unable to set kernel argument" ); + + // Run task + error = clEnqueueTask( queue, kernel, 0, NULL, NULL ); + test_error( error, "Unable to run task" ); + + // Read results + cl_int *results = (cl_int*)malloc(sizeof(cl_int)*count); + error = clEnqueueReadBuffer( queue, output, CL_TRUE, 0, sizeof( cl_int ) * count, results, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + // Validate + for( cl_int i = 0; i < count; i++ ) + { + if( results[ i ] != i ) + { + log_error( "ERROR: Task result value %d did not validate! Expected %d, got %d\n", (int)i, (int)i, (int)results[ i ] ); + free(results); + return -1; + } + } + + /* All done */ + free(results); + return 0; +} + + + +#define TEST_SIZE 1000 +int test_repeated_setup_cleanup(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + + cl_context local_context; + cl_command_queue local_queue; + cl_program local_program; + cl_kernel local_kernel; + cl_mem local_mem_in, local_mem_out; + cl_event local_event; + size_t global_dim[3]; + int i, j, error; + global_dim[0] = TEST_SIZE; + global_dim[1] = 1; global_dim[2] = 1; + cl_int *inData, *outData; + cl_int status; + + inData = (cl_int*)malloc(sizeof(cl_int)*TEST_SIZE); + outData = (cl_int*)malloc(sizeof(cl_int)*TEST_SIZE); + for (i=0; i +#endif + +int IsAPowerOfTwo( unsigned long x ) +{ + return 0 == (x & (x-1)); +} + + +int test_min_data_type_align_size_alignment(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + cl_uint min_alignment; + + if (gHasLong) + min_alignment = sizeof(cl_long)*16; + else + min_alignment = sizeof(cl_int)*16; + + int error = 0; + cl_uint alignment; + + error = clGetDeviceInfo(device, CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof(alignment), &alignment, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_MEM_BASE_ADDR_ALIGN failed"); + log_info("Device reported CL_DEVICE_MEM_BASE_ADDR_ALIGN = %lu bits.\n", (unsigned long)alignment); + + // Verify the size is large enough + if (alignment < min_alignment*8) { + log_error("ERROR: alignment too small. Minimum alignment for %s16 is %lu bits, device reported %lu bits.", + (gHasLong) ? "long" : "int", + (unsigned long)(min_alignment*8), (unsigned long)alignment); + return -1; + } + + // Verify the size is a power of two + if (!IsAPowerOfTwo((unsigned long)alignment)) { + log_error("ERROR: alignment is not a power of two.\n"); + return -1; + } + + return 0; + +} diff --git a/test_conformance/compatibility/test_conformance/api/test_kernel_arg_changes.cpp b/test_conformance/compatibility/test_conformance/api/test_kernel_arg_changes.cpp new file mode 100644 index 00000000..b7aba632 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/test_kernel_arg_changes.cpp @@ -0,0 +1,141 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +extern "C" { extern cl_uint gRandomSeed;} + +// This test is designed to stress changing kernel arguments between execute calls (that are asynchronous and thus +// potentially overlapping) to make sure each kernel gets the right arguments + +// Note: put a delay loop in the kernel to make sure we have time to queue the next kernel before this one finishes +const char *inspect_image_kernel_source[] = { +"__kernel void sample_test(read_only image2d_t src, __global int *outDimensions )\n" +"{\n" +" int tid = get_global_id(0), i;\n" +" for( i = 0; i < 100000; i++ ); \n" +" outDimensions[tid * 2] = get_image_width(src) * tid;\n" +" outDimensions[tid * 2 + 1] = get_image_height(src) * tid;\n" +"\n" +"}\n" }; + +#define NUM_TRIES 100 +#define NUM_THREADS 2048 + +int test_kernel_arg_changes(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel; + int error, i; + clMemWrapper images[ NUM_TRIES ]; + size_t sizes[ NUM_TRIES ][ 2 ]; + clMemWrapper results[ NUM_TRIES ]; + cl_image_format imageFormat; + size_t maxWidth, maxHeight; + size_t threads[1], localThreads[1]; + cl_int resultArray[ NUM_THREADS * 2 ]; + char errStr[ 128 ]; + RandomSeed seed( gRandomSeed ); + + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + // Just get any ol format to test with + error = get_8_bit_image_format( context, CL_MEM_OBJECT_IMAGE2D, CL_MEM_READ_WRITE, 0, &imageFormat ); + test_error( error, "Unable to obtain suitable image format to test with!" ); + + // Create our testing kernel + error = create_single_kernel_helper( context, &program, &kernel, 1, inspect_image_kernel_source, "sample_test" ); + test_error( error, "Unable to create testing kernel" ); + + // Get max dimensions for each of our images + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + test_error( error, "Unable to get max image dimensions for device" ); + + // Get the number of threads we'll be able to run + threads[0] = NUM_THREADS; + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size for kernel" ); + + // Create a variety of images and output arrays + for( i = 0; i < NUM_TRIES; i++ ) + { + sizes[ i ][ 0 ] = genrand_int32(seed) % (maxWidth/32) + 1; + sizes[ i ][ 1 ] = genrand_int32(seed) % (maxHeight/32) + 1; + + images[ i ] = create_image_2d( context, (cl_mem_flags)(CL_MEM_READ_ONLY), + &imageFormat, sizes[ i ][ 0], sizes[ i ][ 1 ], 0, NULL, &error ); + if( images[i] == NULL ) + { + log_error("Failed to create image %d of size %d x %d (%s).\n", i, (int)sizes[i][0], (int)sizes[i][1], IGetErrorString( error )); + return -1; + } + results[ i ] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof( cl_int ) * threads[0] * 2, NULL, &error ); + if( results[i] == NULL) + { + log_error("Failed to create array %d of size %d.\n", i, (int)threads[0]*2); + return -1; + } + } + + // Start setting arguments and executing kernels + for( i = 0; i < NUM_TRIES; i++ ) + { + // Set the arguments for this try + error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &images[ i ] ); + sprintf( errStr, "Unable to set argument 0 for kernel try %d", i ); + test_error( error, errStr ); + + error = clSetKernelArg( kernel, 1, sizeof( cl_mem ), &results[ i ] ); + sprintf( errStr, "Unable to set argument 1 for kernel try %d", i ); + test_error( error, errStr ); + + // Queue up execution + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + sprintf( errStr, "Unable to execute kernel try %d", i ); + test_error( error, errStr ); + } + + // Read the results back out, one at a time, and verify + for( i = 0; i < NUM_TRIES; i++ ) + { + error = clEnqueueReadBuffer( queue, results[ i ], CL_TRUE, 0, sizeof( cl_int ) * threads[0] * 2, resultArray, 0, NULL, NULL ); + sprintf( errStr, "Unable to read results for kernel try %d", i ); + test_error( error, errStr ); + + // Verify. Each entry should be n * the (width/height) of image i + for( int j = 0; j < NUM_THREADS; j++ ) + { + if( resultArray[ j * 2 + 0 ] != (int)sizes[ i ][ 0 ] * j ) + { + log_error( "ERROR: Verficiation for kernel try %d, sample %d FAILED, expected a width of %d, got %d\n", + i, j, (int)sizes[ i ][ 0 ] * j, resultArray[ j * 2 + 0 ] ); + return -1; + } + if( resultArray[ j * 2 + 1 ] != (int)sizes[ i ][ 1 ] * j ) + { + log_error( "ERROR: Verficiation for kernel try %d, sample %d FAILED, expected a height of %d, got %d\n", + i, j, (int)sizes[ i ][ 1 ] * j, resultArray[ j * 2 + 1 ] ); + return -1; + } + } + } + + // If we got here, everything verified successfully + return 0; +} + + diff --git a/test_conformance/compatibility/test_conformance/api/test_kernel_arg_info.c b/test_conformance/compatibility/test_conformance/api/test_kernel_arg_info.c new file mode 100644 index 00000000..5b1e5e6d --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/test_kernel_arg_info.c @@ -0,0 +1,5192 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include +#include +#ifndef _WIN32 +#include +#endif + +#define ARG_INFO_FIELD_COUNT 5 + +#define ARG_INFO_ADDR_OFFSET 1 +#define ARG_INFO_ACCESS_OFFSET 2 +#define ARG_INFO_TYPE_QUAL_OFFSET 3 +#define ARG_INFO_TYPE_NAME_OFFSET 4 +#define ARG_INFO_ARG_NAME_OFFSET 5 + +typedef char const * kernel_args_t[]; + +kernel_args_t required_kernel_args = { + "typedef float4 typedef_type;\n" + "\n" + "typedef struct struct_type {\n" + " float4 float4d;\n" + " int intd;\n" + "} typedef_struct_type;\n" + "\n" + "typedef union union_type {\n" + " float4 float4d;\n" + " uint4 uint4d;\n" + "} typedef_union_type;\n" + "\n" + "typedef enum enum_type {\n" + " enum_type_zero,\n" + " enum_type_one,\n" + " enum_type_two\n" + "} typedef_enum_type;\n" + "\n" + "kernel void constant_scalar_p0(constant void*constantvoidp,\n" + " constant char *constantcharp,\n" + " constant uchar* constantucharp,\n" + " constant unsigned char * constantunsignedcharp)\n" + "{}\n", + "kernel void constant_scalar_p1(constant short*constantshortp,\n" + " constant ushort *constantushortp,\n" + " constant unsigned short* constantunsignedshortp,\n" + " constant int * constantintp)\n" + "{}\n", + "kernel void constant_scalar_p2(constant uint*constantuintp,\n" + " constant unsigned int *constantunsignedintp,\n" + " constant long* constantlongp,\n" + " constant ulong * constantulongp)\n" + "{}\n", + "kernel void constant_scalar_p3(constant unsigned long*constantunsignedlongp,\n" + " constant float *constantfloatp)\n" + "{}\n", + "\n" + "kernel void constant_scalar_restrict_p0(constant void* restrict constantvoidrestrictp,\n" + " constant char * restrict constantcharrestrictp,\n" + " constant uchar*restrict constantucharrestrictp,\n" + " constant unsigned char *restrict constantunsignedcharrestrictp)\n" + "{}\n", + "kernel void constant_scalar_restrict_p1(constant short* restrict constantshortrestrictp,\n" + " constant ushort * restrict constantushortrestrictp,\n" + " constant unsigned short*restrict constantunsignedshortrestrictp,\n" + " constant int *restrict constantintrestrictp)\n" + "{}\n", + "kernel void constant_scalar_restrict_p2(constant uint* restrict constantuintrestrictp,\n" + " constant unsigned int * restrict constantunsignedintrestrictp,\n" + " constant long*restrict constantlongrestrictp,\n" + " constant ulong *restrict constantulongrestrictp)\n" + "{}\n", + "kernel void constant_scalar_restrict_p3(constant unsigned long* restrict constantunsignedlongrestrictp,\n" + " constant float * restrict constantfloatrestrictp)\n" + "{}\n", + "\n" + "kernel void global_scalar_p(global void*globalvoidp,\n" + " global char *globalcharp,\n" + " global uchar* globalucharp,\n" + " global unsigned char * globalunsignedcharp,\n" + " global short*globalshortp,\n" + " global ushort *globalushortp,\n" + " global unsigned short* globalunsignedshortp,\n" + " global int * globalintp,\n" + " global uint*globaluintp,\n" + " global unsigned int *globalunsignedintp,\n" + " global long* globallongp,\n" + " global ulong * globalulongp,\n" + " global unsigned long*globalunsignedlongp,\n" + " global float *globalfloatp)\n" + "{}\n", + "\n" + "kernel void global_scalar_restrict_p(global void* restrict globalvoidrestrictp,\n" + " global char * restrict globalcharrestrictp,\n" + " global uchar*restrict globalucharrestrictp,\n" + " global unsigned char *restrict globalunsignedcharrestrictp,\n" + " global short* restrict globalshortrestrictp,\n" + " global ushort * restrict globalushortrestrictp,\n" + " global unsigned short*restrict globalunsignedshortrestrictp,\n" + " global int *restrict globalintrestrictp,\n" + " global uint* restrict globaluintrestrictp,\n" + " global unsigned int * restrict globalunsignedintrestrictp,\n" + " global long*restrict globallongrestrictp,\n" + " global ulong *restrict globalulongrestrictp,\n" + " global unsigned long* restrict globalunsignedlongrestrictp,\n" + " global float * restrict globalfloatrestrictp)\n" + "{}\n", + "\n" + "kernel void global_const_scalar_p(global const void*globalconstvoidp,\n" + " global const char *globalconstcharp,\n" + " global const uchar* globalconstucharp,\n" + " global const unsigned char * globalconstunsignedcharp,\n" + " global const short*globalconstshortp,\n" + " global const ushort *globalconstushortp,\n" + " global const unsigned short* globalconstunsignedshortp,\n" + " global const int * globalconstintp,\n" + " global const uint*globalconstuintp,\n" + " global const unsigned int *globalconstunsignedintp,\n" + " global const long* globalconstlongp,\n" + " global const ulong * globalconstulongp,\n" + " global const unsigned long*globalconstunsignedlongp,\n" + " global const float *globalconstfloatp)\n" + "{}\n", + "\n" + "kernel void global_const_scalar_restrict_p(global const void* restrict globalconstvoidrestrictp,\n" + " global const char * restrict globalconstcharrestrictp,\n" + " global const uchar*restrict globalconstucharrestrictp,\n" + " global const unsigned char *restrict globalconstunsignedcharrestrictp,\n" + " global const short* restrict globalconstshortrestrictp,\n" + " global const ushort * restrict globalconstushortrestrictp,\n" + " global const unsigned short*restrict globalconstunsignedshortrestrictp,\n" + " global const int *restrict globalconstintrestrictp,\n" + " global const uint* restrict globalconstuintrestrictp,\n" + " global const unsigned int * restrict globalconstunsignedintrestrictp,\n" + " global const long*restrict globalconstlongrestrictp,\n" + " global const ulong *restrict globalconstulongrestrictp,\n" + " global const unsigned long* restrict globalconstunsignedlongrestrictp,\n" + " global const float * restrict globalconstfloatrestrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_scalar_p(global volatile void*globalvolatilevoidp,\n" + " global volatile char *globalvolatilecharp,\n" + " global volatile uchar* globalvolatileucharp,\n" + " global volatile unsigned char * globalvolatileunsignedcharp,\n" + " global volatile short*globalvolatileshortp,\n" + " global volatile ushort *globalvolatileushortp,\n" + " global volatile unsigned short* globalvolatileunsignedshortp,\n" + " global volatile int * globalvolatileintp,\n" + " global volatile uint*globalvolatileuintp,\n" + " global volatile unsigned int *globalvolatileunsignedintp,\n" + " global volatile long* globalvolatilelongp,\n" + " global volatile ulong * globalvolatileulongp,\n" + " global volatile unsigned long*globalvolatileunsignedlongp,\n" + " global volatile float *globalvolatilefloatp)\n" + "{}\n", + "\n" + "kernel void global_volatile_scalar_restrict_p(global volatile void* restrict globalvolatilevoidrestrictp,\n" + " global volatile char * restrict globalvolatilecharrestrictp,\n" + " global volatile uchar*restrict globalvolatileucharrestrictp,\n" + " global volatile unsigned char *restrict globalvolatileunsignedcharrestrictp,\n" + " global volatile short* restrict globalvolatileshortrestrictp,\n" + " global volatile ushort * restrict globalvolatileushortrestrictp,\n" + " global volatile unsigned short*restrict globalvolatileunsignedshortrestrictp,\n" + " global volatile int *restrict globalvolatileintrestrictp,\n" + " global volatile uint* restrict globalvolatileuintrestrictp,\n" + " global volatile unsigned int * restrict globalvolatileunsignedintrestrictp,\n" + " global volatile long*restrict globalvolatilelongrestrictp,\n" + " global volatile ulong *restrict globalvolatileulongrestrictp,\n" + " global volatile unsigned long* restrict globalvolatileunsignedlongrestrictp,\n" + " global volatile float * restrict globalvolatilefloatrestrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_scalar_p(global const volatile void*globalconstvolatilevoidp,\n" + " global const volatile char *globalconstvolatilecharp,\n" + " global const volatile uchar* globalconstvolatileucharp,\n" + " global const volatile unsigned char * globalconstvolatileunsignedcharp,\n" + " global const volatile short*globalconstvolatileshortp,\n" + " global const volatile ushort *globalconstvolatileushortp,\n" + " global const volatile unsigned short* globalconstvolatileunsignedshortp,\n" + " global const volatile int * globalconstvolatileintp,\n" + " global const volatile uint*globalconstvolatileuintp,\n" + " global const volatile unsigned int *globalconstvolatileunsignedintp,\n" + " global const volatile long* globalconstvolatilelongp,\n" + " global const volatile ulong * globalconstvolatileulongp,\n" + " global const volatile unsigned long*globalconstvolatileunsignedlongp,\n" + " global const volatile float *globalconstvolatilefloatp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_scalar_restrict_p(global const volatile void* restrict globalconstvolatilevoidrestrictp,\n" + " global const volatile char * restrict globalconstvolatilecharrestrictp,\n" + " global const volatile uchar*restrict globalconstvolatileucharrestrictp,\n" + " global const volatile unsigned char *restrict globalconstvolatileunsignedcharrestrictp,\n" + " global const volatile short* restrict globalconstvolatileshortrestrictp,\n" + " global const volatile ushort * restrict globalconstvolatileushortrestrictp,\n" + " global const volatile unsigned short*restrict globalconstvolatileunsignedshortrestrictp,\n" + " global const volatile int *restrict globalconstvolatileintrestrictp,\n" + " global const volatile uint* restrict globalconstvolatileuintrestrictp,\n" + " global const volatile unsigned int * restrict globalconstvolatileunsignedintrestrictp,\n" + " global const volatile long*restrict globalconstvolatilelongrestrictp,\n" + " global const volatile ulong *restrict globalconstvolatileulongrestrictp,\n" + " global const volatile unsigned long* restrict globalconstvolatileunsignedlongrestrictp,\n" + " global const volatile float * restrict globalconstvolatilefloatrestrictp)\n" + "{}\n", + "\n" + "kernel void local_scalar_p(local void*localvoidp,\n" + " local char *localcharp,\n" + " local uchar* localucharp,\n" + " local unsigned char * localunsignedcharp,\n" + " local short*localshortp,\n" + " local ushort *localushortp,\n" + " local unsigned short* localunsignedshortp,\n" + " local int * localintp,\n" + " local uint*localuintp,\n" + " local unsigned int *localunsignedintp,\n" + " local long* locallongp,\n" + " local ulong * localulongp,\n" + " local unsigned long*localunsignedlongp,\n" + " local float *localfloatp)\n" + "{}\n", + "\n" + "kernel void local_scalar_restrict_p(local void* restrict localvoidrestrictp,\n" + " local char * restrict localcharrestrictp,\n" + " local uchar*restrict localucharrestrictp,\n" + " local unsigned char *restrict localunsignedcharrestrictp,\n" + " local short* restrict localshortrestrictp,\n" + " local ushort * restrict localushortrestrictp,\n" + " local unsigned short*restrict localunsignedshortrestrictp,\n" + " local int *restrict localintrestrictp,\n" + " local uint* restrict localuintrestrictp,\n" + " local unsigned int * restrict localunsignedintrestrictp,\n" + " local long*restrict locallongrestrictp,\n" + " local ulong *restrict localulongrestrictp,\n" + " local unsigned long* restrict localunsignedlongrestrictp,\n" + " local float * restrict localfloatrestrictp)\n" + "{}\n", + "\n" + "kernel void local_const_scalar_p(local const void*localconstvoidp,\n" + " local const char *localconstcharp,\n" + " local const uchar* localconstucharp,\n" + " local const unsigned char * localconstunsignedcharp,\n" + " local const short*localconstshortp,\n" + " local const ushort *localconstushortp,\n" + " local const unsigned short* localconstunsignedshortp,\n" + " local const int * localconstintp,\n" + " local const uint*localconstuintp,\n" + " local const unsigned int *localconstunsignedintp,\n" + " local const long* localconstlongp,\n" + " local const ulong * localconstulongp,\n" + " local const unsigned long*localconstunsignedlongp,\n" + " local const float *localconstfloatp)\n" + "{}\n", + "\n" + "kernel void local_const_scalar_restrict_p(local const void* restrict localconstvoidrestrictp,\n" + " local const char * restrict localconstcharrestrictp,\n" + " local const uchar*restrict localconstucharrestrictp,\n" + " local const unsigned char *restrict localconstunsignedcharrestrictp,\n" + " local const short* restrict localconstshortrestrictp,\n" + " local const ushort * restrict localconstushortrestrictp,\n" + " local const unsigned short*restrict localconstunsignedshortrestrictp,\n" + " local const int *restrict localconstintrestrictp,\n" + " local const uint* restrict localconstuintrestrictp,\n" + " local const unsigned int * restrict localconstunsignedintrestrictp,\n" + " local const long*restrict localconstlongrestrictp,\n" + " local const ulong *restrict localconstulongrestrictp,\n" + " local const unsigned long* restrict localconstunsignedlongrestrictp,\n" + " local const float * restrict localconstfloatrestrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_scalar_p(local volatile void*localvolatilevoidp,\n" + " local volatile char *localvolatilecharp,\n" + " local volatile uchar* localvolatileucharp,\n" + " local volatile unsigned char * localvolatileunsignedcharp,\n" + " local volatile short*localvolatileshortp,\n" + " local volatile ushort *localvolatileushortp,\n" + " local volatile unsigned short* localvolatileunsignedshortp,\n" + " local volatile int * localvolatileintp,\n" + " local volatile uint*localvolatileuintp,\n" + " local volatile unsigned int *localvolatileunsignedintp,\n" + " local volatile long* localvolatilelongp,\n" + " local volatile ulong * localvolatileulongp,\n" + " local volatile unsigned long*localvolatileunsignedlongp,\n" + " local volatile float *localvolatilefloatp)\n" + "{}\n", + "\n" + "kernel void local_volatile_scalar_restrict_p(local volatile void* restrict localvolatilevoidrestrictp,\n" + " local volatile char * restrict localvolatilecharrestrictp,\n" + " local volatile uchar*restrict localvolatileucharrestrictp,\n" + " local volatile unsigned char *restrict localvolatileunsignedcharrestrictp,\n" + " local volatile short* restrict localvolatileshortrestrictp,\n" + " local volatile ushort * restrict localvolatileushortrestrictp,\n" + " local volatile unsigned short*restrict localvolatileunsignedshortrestrictp,\n" + " local volatile int *restrict localvolatileintrestrictp,\n" + " local volatile uint* restrict localvolatileuintrestrictp,\n" + " local volatile unsigned int * restrict localvolatileunsignedintrestrictp,\n" + " local volatile long*restrict localvolatilelongrestrictp,\n" + " local volatile ulong *restrict localvolatileulongrestrictp,\n" + " local volatile unsigned long* restrict localvolatileunsignedlongrestrictp,\n" + " local volatile float * restrict localvolatilefloatrestrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_scalar_p(local const volatile void*localconstvolatilevoidp,\n" + " local const volatile char *localconstvolatilecharp,\n" + " local const volatile uchar* localconstvolatileucharp,\n" + " local const volatile unsigned char * localconstvolatileunsignedcharp,\n" + " local const volatile short*localconstvolatileshortp,\n" + " local const volatile ushort *localconstvolatileushortp,\n" + " local const volatile unsigned short* localconstvolatileunsignedshortp,\n" + " local const volatile int * localconstvolatileintp,\n" + " local const volatile uint*localconstvolatileuintp,\n" + " local const volatile unsigned int *localconstvolatileunsignedintp,\n" + " local const volatile long* localconstvolatilelongp,\n" + " local const volatile ulong * localconstvolatileulongp,\n" + " local const volatile unsigned long*localconstvolatileunsignedlongp,\n" + " local const volatile float *localconstvolatilefloatp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_scalar_restrict_p(local const volatile void* restrict localconstvolatilevoidrestrictp,\n" + " local const volatile char * restrict localconstvolatilecharrestrictp,\n" + " local const volatile uchar*restrict localconstvolatileucharrestrictp,\n" + " local const volatile unsigned char *restrict localconstvolatileunsignedcharrestrictp,\n" + " local const volatile short* restrict localconstvolatileshortrestrictp,\n" + " local const volatile ushort * restrict localconstvolatileushortrestrictp,\n" + " local const volatile unsigned short*restrict localconstvolatileunsignedshortrestrictp,\n" + " local const volatile int *restrict localconstvolatileintrestrictp,\n" + " local const volatile uint* restrict localconstvolatileuintrestrictp,\n" + " local const volatile unsigned int * restrict localconstvolatileunsignedintrestrictp,\n" + " local const volatile long*restrict localconstvolatilelongrestrictp,\n" + " local const volatile ulong *restrict localconstvolatileulongrestrictp,\n" + " local const volatile unsigned long* restrict localconstvolatileunsignedlongrestrictp,\n" + " local const volatile float * restrict localconstvolatilefloatrestrictp)\n" + "{}\n", + "\n" + "kernel void scalar_d(char chard,\n" + " uchar uchard,\n" + " unsigned char unsignedchard,\n" + " short shortd,\n" + " ushort ushortd,\n" + " unsigned short unsignedshortd,\n" + " int intd,\n" + " uint uintd,\n" + " unsigned int unsignedintd,\n" + " long longd,\n" + " ulong ulongd,\n" + " unsigned long unsignedlongd,\n" + " float floatd)\n" + "{}\n", + "\n" + "kernel void const_scalar_d(const char constchard,\n" + " const uchar constuchard,\n" + " const unsigned char constunsignedchard,\n" + " const short constshortd,\n" + " const ushort constushortd,\n" + " const unsigned short constunsignedshortd,\n" + " const int constintd,\n" + " const uint constuintd,\n" + " const unsigned int constunsignedintd,\n" + " const long constlongd,\n" + " const ulong constulongd,\n" + " const unsigned long constunsignedlongd,\n" + " const float constfloatd)\n" + "{}\n", + "\n" + "kernel void private_scalar_d(private char privatechard,\n" + " private uchar privateuchard,\n" + " private unsigned char privateunsignedchard,\n" + " private short privateshortd,\n" + " private ushort privateushortd,\n" + " private unsigned short privateunsignedshortd,\n" + " private int privateintd,\n" + " private uint privateuintd,\n" + " private unsigned int privateunsignedintd,\n" + " private long privatelongd,\n" + " private ulong privateulongd,\n" + " private unsigned long privateunsignedlongd,\n" + " private float privatefloatd)\n" + "{}\n", + "\n" + "kernel void private_const_scalar_d(private const char privateconstchard,\n" + " private const uchar privateconstuchard,\n" + " private const unsigned char privateconstunsignedchard,\n" + " private const short privateconstshortd,\n" + " private const ushort privateconstushortd,\n" + " private const unsigned short privateconstunsignedshortd,\n" + " private const int privateconstintd,\n" + " private const uint privateconstuintd,\n" + " private const unsigned int privateconstunsignedintd,\n" + " private const long privateconstlongd,\n" + " private const ulong privateconstulongd,\n" + " private const unsigned long privateconstunsignedlongd,\n" + " private const float privateconstfloatd)\n" + "{}\n", + "\n" + "kernel void constant_vector2_p0(constant char2*constantchar2p,\n" + " constant uchar2 *constantuchar2p,\n" + " constant short2* constantshort2p,\n" + " constant ushort2 * constantushort2p)\n" + "{}\n", + "\n" + "kernel void constant_vector2_p1(constant int2*constantint2p,\n" + " constant uint2 *constantuint2p,\n" + " constant long2* constantlong2p,\n" + " constant ulong2 * constantulong2p)\n" + "{}\n", + "\n" + "kernel void constant_vector2_p2(constant float2*constantfloat2p)\n" + "{}\n", + "\n" + "kernel void constant_vector2_restrict_p0(constant char2 *restrict constantchar2restrictp,\n" + " constant uchar2* restrict constantuchar2restrictp,\n" + " constant short2 * restrict constantshort2restrictp,\n" + " constant ushort2*restrict constantushort2restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector2_restrict_p1(constant int2 *restrict constantint2restrictp,\n" + " constant uint2* restrict constantuint2restrictp,\n" + " constant long2 * restrict constantlong2restrictp,\n" + " constant ulong2*restrict constantulong2restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector2_restrict_p2(constant float2 *restrict constantfloat2restrictp)\n" + "{}\n", + "\n" + "kernel void global_vector2_p(global char2*globalchar2p,\n" + " global uchar2 *globaluchar2p,\n" + " global short2* globalshort2p,\n" + " global ushort2 * globalushort2p,\n" + " global int2*globalint2p,\n" + " global uint2 *globaluint2p,\n" + " global long2* globallong2p,\n" + " global ulong2 * globalulong2p,\n" + " global float2*globalfloat2p)\n" + "{}\n", + "\n" + "kernel void global_vector2_restrict_p(global char2 *restrict globalchar2restrictp,\n" + " global uchar2* restrict globaluchar2restrictp,\n" + " global short2 * restrict globalshort2restrictp,\n" + " global ushort2*restrict globalushort2restrictp,\n" + " global int2 *restrict globalint2restrictp,\n" + " global uint2* restrict globaluint2restrictp,\n" + " global long2 * restrict globallong2restrictp,\n" + " global ulong2*restrict globalulong2restrictp,\n" + " global float2 *restrict globalfloat2restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_vector2_p(global const char2* globalconstchar2p,\n" + " global const uchar2 * globalconstuchar2p,\n" + " global const short2*globalconstshort2p,\n" + " global const ushort2 *globalconstushort2p,\n" + " global const int2* globalconstint2p,\n" + " global const uint2 * globalconstuint2p,\n" + " global const long2*globalconstlong2p,\n" + " global const ulong2 *globalconstulong2p,\n" + " global const float2* globalconstfloat2p)\n" + "{}\n", + "\n" + "kernel void global_const_vector2_restrict_p(global const char2 * restrict globalconstchar2restrictp,\n" + " global const uchar2*restrict globalconstuchar2restrictp,\n" + " global const short2 *restrict globalconstshort2restrictp,\n" + " global const ushort2* restrict globalconstushort2restrictp,\n" + " global const int2 * restrict globalconstint2restrictp,\n" + " global const uint2*restrict globalconstuint2restrictp,\n" + " global const long2 *restrict globalconstlong2restrictp,\n" + " global const ulong2* restrict globalconstulong2restrictp,\n" + " global const float2 * restrict globalconstfloat2restrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector2_p(global volatile char2*globalvolatilechar2p,\n" + " global volatile uchar2 *globalvolatileuchar2p,\n" + " global volatile short2* globalvolatileshort2p,\n" + " global volatile ushort2 * globalvolatileushort2p,\n" + " global volatile int2*globalvolatileint2p,\n" + " global volatile uint2 *globalvolatileuint2p,\n" + " global volatile long2* globalvolatilelong2p,\n" + " global volatile ulong2 * globalvolatileulong2p,\n" + " global volatile float2*globalvolatilefloat2p)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector2_restrict_p(global volatile char2 *restrict globalvolatilechar2restrictp,\n" + " global volatile uchar2* restrict globalvolatileuchar2restrictp,\n" + " global volatile short2 * restrict globalvolatileshort2restrictp,\n" + " global volatile ushort2*restrict globalvolatileushort2restrictp,\n" + " global volatile int2 *restrict globalvolatileint2restrictp,\n" + " global volatile uint2* restrict globalvolatileuint2restrictp,\n" + " global volatile long2 * restrict globalvolatilelong2restrictp,\n" + " global volatile ulong2*restrict globalvolatileulong2restrictp,\n" + " global volatile float2 *restrict globalvolatilefloat2restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector2_p(global const volatile char2* globalconstvolatilechar2p,\n" + " global const volatile uchar2 * globalconstvolatileuchar2p,\n" + " global const volatile short2*globalconstvolatileshort2p,\n" + " global const volatile ushort2 *globalconstvolatileushort2p,\n" + " global const volatile int2* globalconstvolatileint2p,\n" + " global const volatile uint2 * globalconstvolatileuint2p,\n" + " global const volatile long2*globalconstvolatilelong2p,\n" + " global const volatile ulong2 *globalconstvolatileulong2p,\n" + " global const volatile float2* globalconstvolatilefloat2p)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector2_restrict_p(global const volatile char2 * restrict globalconstvolatilechar2restrictp,\n" + " global const volatile uchar2*restrict globalconstvolatileuchar2restrictp,\n" + " global const volatile short2 *restrict globalconstvolatileshort2restrictp,\n" + " global const volatile ushort2* restrict globalconstvolatileushort2restrictp,\n" + " global const volatile int2 * restrict globalconstvolatileint2restrictp,\n" + " global const volatile uint2*restrict globalconstvolatileuint2restrictp,\n" + " global const volatile long2 *restrict globalconstvolatilelong2restrictp,\n" + " global const volatile ulong2* restrict globalconstvolatileulong2restrictp,\n" + " global const volatile float2 * restrict globalconstvolatilefloat2restrictp)\n" + "{}\n", + "\n" + "kernel void local_vector2_p(local char2*localchar2p,\n" + " local uchar2 *localuchar2p,\n" + " local short2* localshort2p,\n" + " local ushort2 * localushort2p,\n" + " local int2*localint2p,\n" + " local uint2 *localuint2p,\n" + " local long2* locallong2p,\n" + " local ulong2 * localulong2p,\n" + " local float2*localfloat2p)\n" + "{}\n", + "\n" + "kernel void local_vector2_restrict_p(local char2 *restrict localchar2restrictp,\n" + " local uchar2* restrict localuchar2restrictp,\n" + " local short2 * restrict localshort2restrictp,\n" + " local ushort2*restrict localushort2restrictp,\n" + " local int2 *restrict localint2restrictp,\n" + " local uint2* restrict localuint2restrictp,\n" + " local long2 * restrict locallong2restrictp,\n" + " local ulong2*restrict localulong2restrictp,\n" + " local float2 *restrict localfloat2restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_vector2_p(local const char2* localconstchar2p,\n" + " local const uchar2 * localconstuchar2p,\n" + " local const short2*localconstshort2p,\n" + " local const ushort2 *localconstushort2p,\n" + " local const int2* localconstint2p,\n" + " local const uint2 * localconstuint2p,\n" + " local const long2*localconstlong2p,\n" + " local const ulong2 *localconstulong2p,\n" + " local const float2* localconstfloat2p)\n" + "{}\n", + "\n" + "kernel void local_const_vector2_restrict_p(local const char2 * restrict localconstchar2restrictp,\n" + " local const uchar2*restrict localconstuchar2restrictp,\n" + " local const short2 *restrict localconstshort2restrictp,\n" + " local const ushort2* restrict localconstushort2restrictp,\n" + " local const int2 * restrict localconstint2restrictp,\n" + " local const uint2*restrict localconstuint2restrictp,\n" + " local const long2 *restrict localconstlong2restrictp,\n" + " local const ulong2* restrict localconstulong2restrictp,\n" + " local const float2 * restrict localconstfloat2restrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector2_p(local volatile char2*localvolatilechar2p,\n" + " local volatile uchar2 *localvolatileuchar2p,\n" + " local volatile short2* localvolatileshort2p,\n" + " local volatile ushort2 * localvolatileushort2p,\n" + " local volatile int2*localvolatileint2p,\n" + " local volatile uint2 *localvolatileuint2p,\n" + " local volatile long2* localvolatilelong2p,\n" + " local volatile ulong2 * localvolatileulong2p,\n" + " local volatile float2*localvolatilefloat2p)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector2_restrict_p(local volatile char2 *restrict localvolatilechar2restrictp,\n" + " local volatile uchar2* restrict localvolatileuchar2restrictp,\n" + " local volatile short2 * restrict localvolatileshort2restrictp,\n" + " local volatile ushort2*restrict localvolatileushort2restrictp,\n" + " local volatile int2 *restrict localvolatileint2restrictp,\n" + " local volatile uint2* restrict localvolatileuint2restrictp,\n" + " local volatile long2 * restrict localvolatilelong2restrictp,\n" + " local volatile ulong2*restrict localvolatileulong2restrictp,\n" + " local volatile float2 *restrict localvolatilefloat2restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector2_p(local const volatile char2* localconstvolatilechar2p,\n" + " local const volatile uchar2 * localconstvolatileuchar2p,\n" + " local const volatile short2*localconstvolatileshort2p,\n" + " local const volatile ushort2 *localconstvolatileushort2p,\n" + " local const volatile int2* localconstvolatileint2p,\n" + " local const volatile uint2 * localconstvolatileuint2p,\n" + " local const volatile long2*localconstvolatilelong2p,\n" + " local const volatile ulong2 *localconstvolatileulong2p,\n" + " local const volatile float2* localconstvolatilefloat2p)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector2_restrict_p(local const volatile char2 * restrict localconstvolatilechar2restrictp,\n" + " local const volatile uchar2*restrict localconstvolatileuchar2restrictp,\n" + " local const volatile short2 *restrict localconstvolatileshort2restrictp,\n" + " local const volatile ushort2* restrict localconstvolatileushort2restrictp,\n" + " local const volatile int2 * restrict localconstvolatileint2restrictp,\n" + " local const volatile uint2*restrict localconstvolatileuint2restrictp,\n" + " local const volatile long2 *restrict localconstvolatilelong2restrictp,\n" + " local const volatile ulong2* restrict localconstvolatileulong2restrictp,\n" + " local const volatile float2 * restrict localconstvolatilefloat2restrictp)\n" + "{}\n", + "\n" + "kernel void vector2_d(char2 char2d,\n" + " uchar2 uchar2d,\n" + " short2 short2d,\n" + " ushort2 ushort2d,\n" + " int2 int2d,\n" + " uint2 uint2d,\n" + " long2 long2d,\n" + " ulong2 ulong2d,\n" + " float2 float2d)\n" + "{}\n", + "\n" + "kernel void const_vector2_d(const char2 constchar2d,\n" + " const uchar2 constuchar2d,\n" + " const short2 constshort2d,\n" + " const ushort2 constushort2d,\n" + " const int2 constint2d,\n" + " const uint2 constuint2d,\n" + " const long2 constlong2d,\n" + " const ulong2 constulong2d,\n" + " const float2 constfloat2d)\n" + "{}\n", + "\n" + "kernel void private_vector2_d(private char2 privatechar2d,\n" + " private uchar2 privateuchar2d,\n" + " private short2 privateshort2d,\n" + " private ushort2 privateushort2d,\n" + " private int2 privateint2d,\n" + " private uint2 privateuint2d,\n" + " private long2 privatelong2d,\n" + " private ulong2 privateulong2d,\n" + " private float2 privatefloat2d)\n" + "{}\n", + "\n" + "kernel void private_const_vector2_d(private const char2 privateconstchar2d,\n" + " private const uchar2 privateconstuchar2d,\n" + " private const short2 privateconstshort2d,\n" + " private const ushort2 privateconstushort2d,\n" + " private const int2 privateconstint2d,\n" + " private const uint2 privateconstuint2d,\n" + " private const long2 privateconstlong2d,\n" + " private const ulong2 privateconstulong2d,\n" + " private const float2 privateconstfloat2d)\n" + "{}\n", + "\n" + "kernel void constant_vector3_p0(constant char3*constantchar3p,\n" + " constant uchar3 *constantuchar3p,\n" + " constant short3* constantshort3p,\n" + " constant ushort3 * constantushort3p)\n" + "{}\n", + "\n" + "kernel void constant_vector3_p1(constant int3*constantint3p,\n" + " constant uint3 *constantuint3p,\n" + " constant long3* constantlong3p,\n" + " constant ulong3 * constantulong3p)\n" + "{}\n", + "\n" + "kernel void constant_vector3_p2(constant float3*constantfloat3p)\n" + "{}\n", + "\n" + "kernel void constant_vector3_restrict_p0(constant char3 *restrict constantchar3restrictp,\n" + " constant uchar3* restrict constantuchar3restrictp,\n" + " constant short3 * restrict constantshort3restrictp,\n" + " constant ushort3*restrict constantushort3restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector3_restrict_p1(constant int3 *restrict constantint3restrictp,\n" + " constant uint3* restrict constantuint3restrictp,\n" + " constant long3 * restrict constantlong3restrictp,\n" + " constant ulong3*restrict constantulong3restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector3_restrict_p2(constant float3 *restrict constantfloat3restrictp)\n" + "{}\n", + "\n" + "kernel void global_vector3_p(global char3*globalchar3p,\n" + " global uchar3 *globaluchar3p,\n" + " global short3* globalshort3p,\n" + " global ushort3 * globalushort3p,\n" + " global int3*globalint3p,\n" + " global uint3 *globaluint3p,\n" + " global long3* globallong3p,\n" + " global ulong3 * globalulong3p,\n" + " global float3*globalfloat3p)\n" + "{}\n", + "\n" + "kernel void global_vector3_restrict_p(global char3 *restrict globalchar3restrictp,\n" + " global uchar3* restrict globaluchar3restrictp,\n" + " global short3 * restrict globalshort3restrictp,\n" + " global ushort3*restrict globalushort3restrictp,\n" + " global int3 *restrict globalint3restrictp,\n" + " global uint3* restrict globaluint3restrictp,\n" + " global long3 * restrict globallong3restrictp,\n" + " global ulong3*restrict globalulong3restrictp,\n" + " global float3 *restrict globalfloat3restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_vector3_p(global const char3* globalconstchar3p,\n" + " global const uchar3 * globalconstuchar3p,\n" + " global const short3*globalconstshort3p,\n" + " global const ushort3 *globalconstushort3p,\n" + " global const int3* globalconstint3p,\n" + " global const uint3 * globalconstuint3p,\n" + " global const long3*globalconstlong3p,\n" + " global const ulong3 *globalconstulong3p,\n" + " global const float3* globalconstfloat3p)\n" + "{}\n", + "\n" + "kernel void global_const_vector3_restrict_p(global const char3 * restrict globalconstchar3restrictp,\n" + " global const uchar3*restrict globalconstuchar3restrictp,\n" + " global const short3 *restrict globalconstshort3restrictp,\n" + " global const ushort3* restrict globalconstushort3restrictp,\n" + " global const int3 * restrict globalconstint3restrictp,\n" + " global const uint3*restrict globalconstuint3restrictp,\n" + " global const long3 *restrict globalconstlong3restrictp,\n" + " global const ulong3* restrict globalconstulong3restrictp,\n" + " global const float3 * restrict globalconstfloat3restrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector3_p(global volatile char3*globalvolatilechar3p,\n" + " global volatile uchar3 *globalvolatileuchar3p,\n" + " global volatile short3* globalvolatileshort3p,\n" + " global volatile ushort3 * globalvolatileushort3p,\n" + " global volatile int3*globalvolatileint3p,\n" + " global volatile uint3 *globalvolatileuint3p,\n" + " global volatile long3* globalvolatilelong3p,\n" + " global volatile ulong3 * globalvolatileulong3p,\n" + " global volatile float3*globalvolatilefloat3p)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector3_restrict_p(global volatile char3 *restrict globalvolatilechar3restrictp,\n" + " global volatile uchar3* restrict globalvolatileuchar3restrictp,\n" + " global volatile short3 * restrict globalvolatileshort3restrictp,\n" + " global volatile ushort3*restrict globalvolatileushort3restrictp,\n" + " global volatile int3 *restrict globalvolatileint3restrictp,\n" + " global volatile uint3* restrict globalvolatileuint3restrictp,\n" + " global volatile long3 * restrict globalvolatilelong3restrictp,\n" + " global volatile ulong3*restrict globalvolatileulong3restrictp,\n" + " global volatile float3 *restrict globalvolatilefloat3restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector3_p(global const volatile char3* globalconstvolatilechar3p,\n" + " global const volatile uchar3 * globalconstvolatileuchar3p,\n" + " global const volatile short3*globalconstvolatileshort3p,\n" + " global const volatile ushort3 *globalconstvolatileushort3p,\n" + " global const volatile int3* globalconstvolatileint3p,\n" + " global const volatile uint3 * globalconstvolatileuint3p,\n" + " global const volatile long3*globalconstvolatilelong3p,\n" + " global const volatile ulong3 *globalconstvolatileulong3p,\n" + " global const volatile float3* globalconstvolatilefloat3p)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector3_restrict_p(global const volatile char3 * restrict globalconstvolatilechar3restrictp,\n" + " global const volatile uchar3*restrict globalconstvolatileuchar3restrictp,\n" + " global const volatile short3 *restrict globalconstvolatileshort3restrictp,\n" + " global const volatile ushort3* restrict globalconstvolatileushort3restrictp,\n" + " global const volatile int3 * restrict globalconstvolatileint3restrictp,\n" + " global const volatile uint3*restrict globalconstvolatileuint3restrictp,\n" + " global const volatile long3 *restrict globalconstvolatilelong3restrictp,\n" + " global const volatile ulong3* restrict globalconstvolatileulong3restrictp,\n" + " global const volatile float3 * restrict globalconstvolatilefloat3restrictp)\n" + "{}\n", + "\n" + "kernel void local_vector3_p(local char3*localchar3p,\n" + " local uchar3 *localuchar3p,\n" + " local short3* localshort3p,\n" + " local ushort3 * localushort3p,\n" + " local int3*localint3p,\n" + " local uint3 *localuint3p,\n" + " local long3* locallong3p,\n" + " local ulong3 * localulong3p,\n" + " local float3*localfloat3p)\n" + "{}\n", + "\n" + "kernel void local_vector3_restrict_p(local char3 *restrict localchar3restrictp,\n" + " local uchar3* restrict localuchar3restrictp,\n" + " local short3 * restrict localshort3restrictp,\n" + " local ushort3*restrict localushort3restrictp,\n" + " local int3 *restrict localint3restrictp,\n" + " local uint3* restrict localuint3restrictp,\n" + " local long3 * restrict locallong3restrictp,\n" + " local ulong3*restrict localulong3restrictp,\n" + " local float3 *restrict localfloat3restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_vector3_p(local const char3* localconstchar3p,\n" + " local const uchar3 * localconstuchar3p,\n" + " local const short3*localconstshort3p,\n" + " local const ushort3 *localconstushort3p,\n" + " local const int3* localconstint3p,\n" + " local const uint3 * localconstuint3p,\n" + " local const long3*localconstlong3p,\n" + " local const ulong3 *localconstulong3p,\n" + " local const float3* localconstfloat3p)\n" + "{}\n", + "\n" + "kernel void local_const_vector3_restrict_p(local const char3 * restrict localconstchar3restrictp,\n" + " local const uchar3*restrict localconstuchar3restrictp,\n" + " local const short3 *restrict localconstshort3restrictp,\n" + " local const ushort3* restrict localconstushort3restrictp,\n" + " local const int3 * restrict localconstint3restrictp,\n" + " local const uint3*restrict localconstuint3restrictp,\n" + " local const long3 *restrict localconstlong3restrictp,\n" + " local const ulong3* restrict localconstulong3restrictp,\n" + " local const float3 * restrict localconstfloat3restrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector3_p(local volatile char3*localvolatilechar3p,\n" + " local volatile uchar3 *localvolatileuchar3p,\n" + " local volatile short3* localvolatileshort3p,\n" + " local volatile ushort3 * localvolatileushort3p,\n" + " local volatile int3*localvolatileint3p,\n" + " local volatile uint3 *localvolatileuint3p,\n" + " local volatile long3* localvolatilelong3p,\n" + " local volatile ulong3 * localvolatileulong3p,\n" + " local volatile float3*localvolatilefloat3p)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector3_restrict_p(local volatile char3 *restrict localvolatilechar3restrictp,\n" + " local volatile uchar3* restrict localvolatileuchar3restrictp,\n" + " local volatile short3 * restrict localvolatileshort3restrictp,\n" + " local volatile ushort3*restrict localvolatileushort3restrictp,\n" + " local volatile int3 *restrict localvolatileint3restrictp,\n" + " local volatile uint3* restrict localvolatileuint3restrictp,\n" + " local volatile long3 * restrict localvolatilelong3restrictp,\n" + " local volatile ulong3*restrict localvolatileulong3restrictp,\n" + " local volatile float3 *restrict localvolatilefloat3restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector3_p(local const volatile char3* localconstvolatilechar3p,\n" + " local const volatile uchar3 * localconstvolatileuchar3p,\n" + " local const volatile short3*localconstvolatileshort3p,\n" + " local const volatile ushort3 *localconstvolatileushort3p,\n" + " local const volatile int3* localconstvolatileint3p,\n" + " local const volatile uint3 * localconstvolatileuint3p,\n" + " local const volatile long3*localconstvolatilelong3p,\n" + " local const volatile ulong3 *localconstvolatileulong3p,\n" + " local const volatile float3* localconstvolatilefloat3p)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector3_restrict_p(local const volatile char3 * restrict localconstvolatilechar3restrictp,\n" + " local const volatile uchar3*restrict localconstvolatileuchar3restrictp,\n" + " local const volatile short3 *restrict localconstvolatileshort3restrictp,\n" + " local const volatile ushort3* restrict localconstvolatileushort3restrictp,\n" + " local const volatile int3 * restrict localconstvolatileint3restrictp,\n" + " local const volatile uint3*restrict localconstvolatileuint3restrictp,\n" + " local const volatile long3 *restrict localconstvolatilelong3restrictp,\n" + " local const volatile ulong3* restrict localconstvolatileulong3restrictp,\n" + " local const volatile float3 * restrict localconstvolatilefloat3restrictp)\n" + "{}\n", + "\n" + "kernel void vector3_d(char3 char3d,\n" + " uchar3 uchar3d,\n" + " short3 short3d,\n" + " ushort3 ushort3d,\n" + " int3 int3d,\n" + " uint3 uint3d,\n" + " long3 long3d,\n" + " ulong3 ulong3d,\n" + " float3 float3d)\n" + "{}\n", + "\n" + "kernel void const_vector3_d(const char3 constchar3d,\n" + " const uchar3 constuchar3d,\n" + " const short3 constshort3d,\n" + " const ushort3 constushort3d,\n" + " const int3 constint3d,\n" + " const uint3 constuint3d,\n" + " const long3 constlong3d,\n" + " const ulong3 constulong3d,\n" + " const float3 constfloat3d)\n" + "{}\n", + "\n" + "kernel void private_vector3_d(private char3 privatechar3d,\n" + " private uchar3 privateuchar3d,\n" + " private short3 privateshort3d,\n" + " private ushort3 privateushort3d,\n" + " private int3 privateint3d,\n" + " private uint3 privateuint3d,\n" + " private long3 privatelong3d,\n" + " private ulong3 privateulong3d,\n" + " private float3 privatefloat3d)\n" + "{}\n", + "\n" + "kernel void private_const_vector3_d(private const char3 privateconstchar3d,\n" + " private const uchar3 privateconstuchar3d,\n" + " private const short3 privateconstshort3d,\n" + " private const ushort3 privateconstushort3d,\n" + " private const int3 privateconstint3d,\n" + " private const uint3 privateconstuint3d,\n" + " private const long3 privateconstlong3d,\n" + " private const ulong3 privateconstulong3d,\n" + " private const float3 privateconstfloat3d)\n" + "{}\n", + "\n" + "kernel void constant_vector4_p0(constant char4*constantchar4p,\n" + " constant uchar4 *constantuchar4p,\n" + " constant short4* constantshort4p,\n" + " constant ushort4 * constantushort4p)\n" + "{}\n", + "\n" + "kernel void constant_vector4_p1(constant int4*constantint4p,\n" + " constant uint4 *constantuint4p,\n" + " constant long4* constantlong4p,\n" + " constant ulong4 * constantulong4p)\n" + "{}\n", + "\n" + "kernel void constant_vector4_p2(constant float4*constantfloat4p)\n" + "{}\n", + "\n" + "kernel void constant_vector4_restrict_p0(constant char4 *restrict constantchar4restrictp,\n" + " constant uchar4* restrict constantuchar4restrictp,\n" + " constant short4 * restrict constantshort4restrictp,\n" + " constant ushort4*restrict constantushort4restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector4_restrict_p1(constant int4 *restrict constantint4restrictp,\n" + " constant uint4* restrict constantuint4restrictp,\n" + " constant long4 * restrict constantlong4restrictp,\n" + " constant ulong4*restrict constantulong4restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector4_restrict_p2(constant float4 *restrict constantfloat4restrictp)\n" + "{}\n", + "\n" + "kernel void global_vector4_p(global char4*globalchar4p,\n" + " global uchar4 *globaluchar4p,\n" + " global short4* globalshort4p,\n" + " global ushort4 * globalushort4p,\n" + " global int4*globalint4p,\n" + " global uint4 *globaluint4p,\n" + " global long4* globallong4p,\n" + " global ulong4 * globalulong4p,\n" + " global float4*globalfloat4p)\n" + "{}\n", + "\n" + "kernel void global_vector4_restrict_p(global char4 *restrict globalchar4restrictp,\n" + " global uchar4* restrict globaluchar4restrictp,\n" + " global short4 * restrict globalshort4restrictp,\n" + " global ushort4*restrict globalushort4restrictp,\n" + " global int4 *restrict globalint4restrictp,\n" + " global uint4* restrict globaluint4restrictp,\n" + " global long4 * restrict globallong4restrictp,\n" + " global ulong4*restrict globalulong4restrictp,\n" + " global float4 *restrict globalfloat4restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_vector4_p(global const char4* globalconstchar4p,\n" + " global const uchar4 * globalconstuchar4p,\n" + " global const short4*globalconstshort4p,\n" + " global const ushort4 *globalconstushort4p,\n" + " global const int4* globalconstint4p,\n" + " global const uint4 * globalconstuint4p,\n" + " global const long4*globalconstlong4p,\n" + " global const ulong4 *globalconstulong4p,\n" + " global const float4* globalconstfloat4p)\n" + "{}\n", + "\n" + "kernel void global_const_vector4_restrict_p(global const char4 * restrict globalconstchar4restrictp,\n" + " global const uchar4*restrict globalconstuchar4restrictp,\n" + " global const short4 *restrict globalconstshort4restrictp,\n" + " global const ushort4* restrict globalconstushort4restrictp,\n" + " global const int4 * restrict globalconstint4restrictp,\n" + " global const uint4*restrict globalconstuint4restrictp,\n" + " global const long4 *restrict globalconstlong4restrictp,\n" + " global const ulong4* restrict globalconstulong4restrictp,\n" + " global const float4 * restrict globalconstfloat4restrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector4_p(global volatile char4*globalvolatilechar4p,\n" + " global volatile uchar4 *globalvolatileuchar4p,\n" + " global volatile short4* globalvolatileshort4p,\n" + " global volatile ushort4 * globalvolatileushort4p,\n" + " global volatile int4*globalvolatileint4p,\n" + " global volatile uint4 *globalvolatileuint4p,\n" + " global volatile long4* globalvolatilelong4p,\n" + " global volatile ulong4 * globalvolatileulong4p,\n" + " global volatile float4*globalvolatilefloat4p)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector4_restrict_p(global volatile char4 *restrict globalvolatilechar4restrictp,\n" + " global volatile uchar4* restrict globalvolatileuchar4restrictp,\n" + " global volatile short4 * restrict globalvolatileshort4restrictp,\n" + " global volatile ushort4*restrict globalvolatileushort4restrictp,\n" + " global volatile int4 *restrict globalvolatileint4restrictp,\n" + " global volatile uint4* restrict globalvolatileuint4restrictp,\n" + " global volatile long4 * restrict globalvolatilelong4restrictp,\n" + " global volatile ulong4*restrict globalvolatileulong4restrictp,\n" + " global volatile float4 *restrict globalvolatilefloat4restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector4_p(global const volatile char4* globalconstvolatilechar4p,\n" + " global const volatile uchar4 * globalconstvolatileuchar4p,\n" + " global const volatile short4*globalconstvolatileshort4p,\n" + " global const volatile ushort4 *globalconstvolatileushort4p,\n" + " global const volatile int4* globalconstvolatileint4p,\n" + " global const volatile uint4 * globalconstvolatileuint4p,\n" + " global const volatile long4*globalconstvolatilelong4p,\n" + " global const volatile ulong4 *globalconstvolatileulong4p,\n" + " global const volatile float4* globalconstvolatilefloat4p)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector4_restrict_p(global const volatile char4 * restrict globalconstvolatilechar4restrictp,\n" + " global const volatile uchar4*restrict globalconstvolatileuchar4restrictp,\n" + " global const volatile short4 *restrict globalconstvolatileshort4restrictp,\n" + " global const volatile ushort4* restrict globalconstvolatileushort4restrictp,\n" + " global const volatile int4 * restrict globalconstvolatileint4restrictp,\n" + " global const volatile uint4*restrict globalconstvolatileuint4restrictp,\n" + " global const volatile long4 *restrict globalconstvolatilelong4restrictp,\n" + " global const volatile ulong4* restrict globalconstvolatileulong4restrictp,\n" + " global const volatile float4 * restrict globalconstvolatilefloat4restrictp)\n" + "{}\n", + "\n" + "kernel void local_vector4_p(local char4*localchar4p,\n" + " local uchar4 *localuchar4p,\n" + " local short4* localshort4p,\n" + " local ushort4 * localushort4p,\n" + " local int4*localint4p,\n" + " local uint4 *localuint4p,\n" + " local long4* locallong4p,\n" + " local ulong4 * localulong4p,\n" + " local float4*localfloat4p)\n" + "{}\n", + "\n" + "kernel void local_vector4_restrict_p(local char4 *restrict localchar4restrictp,\n" + " local uchar4* restrict localuchar4restrictp,\n" + " local short4 * restrict localshort4restrictp,\n" + " local ushort4*restrict localushort4restrictp,\n" + " local int4 *restrict localint4restrictp,\n" + " local uint4* restrict localuint4restrictp,\n" + " local long4 * restrict locallong4restrictp,\n" + " local ulong4*restrict localulong4restrictp,\n" + " local float4 *restrict localfloat4restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_vector4_p(local const char4* localconstchar4p,\n" + " local const uchar4 * localconstuchar4p,\n" + " local const short4*localconstshort4p,\n" + " local const ushort4 *localconstushort4p,\n" + " local const int4* localconstint4p,\n" + " local const uint4 * localconstuint4p,\n" + " local const long4*localconstlong4p,\n" + " local const ulong4 *localconstulong4p,\n" + " local const float4* localconstfloat4p)\n" + "{}\n", + "\n" + "kernel void local_const_vector4_restrict_p(local const char4 * restrict localconstchar4restrictp,\n" + " local const uchar4*restrict localconstuchar4restrictp,\n" + " local const short4 *restrict localconstshort4restrictp,\n" + " local const ushort4* restrict localconstushort4restrictp,\n" + " local const int4 * restrict localconstint4restrictp,\n" + " local const uint4*restrict localconstuint4restrictp,\n" + " local const long4 *restrict localconstlong4restrictp,\n" + " local const ulong4* restrict localconstulong4restrictp,\n" + " local const float4 * restrict localconstfloat4restrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector4_p(local volatile char4*localvolatilechar4p,\n" + " local volatile uchar4 *localvolatileuchar4p,\n" + " local volatile short4* localvolatileshort4p,\n" + " local volatile ushort4 * localvolatileushort4p,\n" + " local volatile int4*localvolatileint4p,\n" + " local volatile uint4 *localvolatileuint4p,\n" + " local volatile long4* localvolatilelong4p,\n" + " local volatile ulong4 * localvolatileulong4p,\n" + " local volatile float4*localvolatilefloat4p)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector4_restrict_p(local volatile char4 *restrict localvolatilechar4restrictp,\n" + " local volatile uchar4* restrict localvolatileuchar4restrictp,\n" + " local volatile short4 * restrict localvolatileshort4restrictp,\n" + " local volatile ushort4*restrict localvolatileushort4restrictp,\n" + " local volatile int4 *restrict localvolatileint4restrictp,\n" + " local volatile uint4* restrict localvolatileuint4restrictp,\n" + " local volatile long4 * restrict localvolatilelong4restrictp,\n" + " local volatile ulong4*restrict localvolatileulong4restrictp,\n" + " local volatile float4 *restrict localvolatilefloat4restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector4_p(local const volatile char4* localconstvolatilechar4p,\n" + " local const volatile uchar4 * localconstvolatileuchar4p,\n" + " local const volatile short4*localconstvolatileshort4p,\n" + " local const volatile ushort4 *localconstvolatileushort4p,\n" + " local const volatile int4* localconstvolatileint4p,\n" + " local const volatile uint4 * localconstvolatileuint4p,\n" + " local const volatile long4*localconstvolatilelong4p,\n" + " local const volatile ulong4 *localconstvolatileulong4p,\n" + " local const volatile float4* localconstvolatilefloat4p)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector4_restrict_p(local const volatile char4 * restrict localconstvolatilechar4restrictp,\n" + " local const volatile uchar4*restrict localconstvolatileuchar4restrictp,\n" + " local const volatile short4 *restrict localconstvolatileshort4restrictp,\n" + " local const volatile ushort4* restrict localconstvolatileushort4restrictp,\n" + " local const volatile int4 * restrict localconstvolatileint4restrictp,\n" + " local const volatile uint4*restrict localconstvolatileuint4restrictp,\n" + " local const volatile long4 *restrict localconstvolatilelong4restrictp,\n" + " local const volatile ulong4* restrict localconstvolatileulong4restrictp,\n" + " local const volatile float4 * restrict localconstvolatilefloat4restrictp)\n" + "{}\n", + "\n" + "kernel void vector4_d(char4 char4d,\n" + " uchar4 uchar4d,\n" + " short4 short4d,\n" + " ushort4 ushort4d,\n" + " int4 int4d,\n" + " uint4 uint4d,\n" + " long4 long4d,\n" + " ulong4 ulong4d,\n" + " float4 float4d)\n" + "{}\n", + "\n" + "kernel void const_vector4_d(const char4 constchar4d,\n" + " const uchar4 constuchar4d,\n" + " const short4 constshort4d,\n" + " const ushort4 constushort4d,\n" + " const int4 constint4d,\n" + " const uint4 constuint4d,\n" + " const long4 constlong4d,\n" + " const ulong4 constulong4d,\n" + " const float4 constfloat4d)\n" + "{}\n", + "\n" + "kernel void private_vector4_d(private char4 privatechar4d,\n" + " private uchar4 privateuchar4d,\n" + " private short4 privateshort4d,\n" + " private ushort4 privateushort4d,\n" + " private int4 privateint4d,\n" + " private uint4 privateuint4d,\n" + " private long4 privatelong4d,\n" + " private ulong4 privateulong4d,\n" + " private float4 privatefloat4d)\n" + "{}\n", + "\n" + "kernel void private_const_vector4_d(private const char4 privateconstchar4d,\n" + " private const uchar4 privateconstuchar4d,\n" + " private const short4 privateconstshort4d,\n" + " private const ushort4 privateconstushort4d,\n" + " private const int4 privateconstint4d,\n" + " private const uint4 privateconstuint4d,\n" + " private const long4 privateconstlong4d,\n" + " private const ulong4 privateconstulong4d,\n" + " private const float4 privateconstfloat4d)\n" + "{}\n", + "\n" + "kernel void constant_vector8_p0(constant char8*constantchar8p,\n" + " constant uchar8 *constantuchar8p,\n" + " constant short8* constantshort8p,\n" + " constant ushort8 * constantushort8p)\n" + "{}\n", + "\n" + "kernel void constant_vector8_p1(constant int8*constantint8p,\n" + " constant uint8 *constantuint8p,\n" + " constant long8* constantlong8p,\n" + " constant ulong8 * constantulong8p)\n" + "{}\n", + "\n" + "kernel void constant_vector8_p2(constant float8*constantfloat8p)\n" + "{}\n", + "\n" + "kernel void constant_vector8_restrict_p0(constant char8 *restrict constantchar8restrictp,\n" + " constant uchar8* restrict constantuchar8restrictp,\n" + " constant short8 * restrict constantshort8restrictp,\n" + " constant ushort8*restrict constantushort8restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector8_restrict_p1(constant int8 *restrict constantint8restrictp,\n" + " constant uint8* restrict constantuint8restrictp,\n" + " constant long8 * restrict constantlong8restrictp,\n" + " constant ulong8*restrict constantulong8restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector8_restrict_p2(constant float8 *restrict constantfloat8restrictp)\n" + "{}\n", + "\n" + "kernel void global_vector8_p(global char8*globalchar8p,\n" + " global uchar8 *globaluchar8p,\n" + " global short8* globalshort8p,\n" + " global ushort8 * globalushort8p,\n" + " global int8*globalint8p,\n" + " global uint8 *globaluint8p,\n" + " global long8* globallong8p,\n" + " global ulong8 * globalulong8p,\n" + " global float8*globalfloat8p)\n" + "{}\n", + "\n" + "kernel void global_vector8_restrict_p(global char8 *restrict globalchar8restrictp,\n" + " global uchar8* restrict globaluchar8restrictp,\n" + " global short8 * restrict globalshort8restrictp,\n" + " global ushort8*restrict globalushort8restrictp,\n" + " global int8 *restrict globalint8restrictp,\n" + " global uint8* restrict globaluint8restrictp,\n" + " global long8 * restrict globallong8restrictp,\n" + " global ulong8*restrict globalulong8restrictp,\n" + " global float8 *restrict globalfloat8restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_vector8_p(global const char8* globalconstchar8p,\n" + " global const uchar8 * globalconstuchar8p,\n" + " global const short8*globalconstshort8p,\n" + " global const ushort8 *globalconstushort8p,\n" + " global const int8* globalconstint8p,\n" + " global const uint8 * globalconstuint8p,\n" + " global const long8*globalconstlong8p,\n" + " global const ulong8 *globalconstulong8p,\n" + " global const float8* globalconstfloat8p)\n" + "{}\n", + "\n" + "kernel void global_const_vector8_restrict_p(global const char8 * restrict globalconstchar8restrictp,\n" + " global const uchar8*restrict globalconstuchar8restrictp,\n" + " global const short8 *restrict globalconstshort8restrictp,\n" + " global const ushort8* restrict globalconstushort8restrictp,\n" + " global const int8 * restrict globalconstint8restrictp,\n" + " global const uint8*restrict globalconstuint8restrictp,\n" + " global const long8 *restrict globalconstlong8restrictp,\n" + " global const ulong8* restrict globalconstulong8restrictp,\n" + " global const float8 * restrict globalconstfloat8restrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector8_p(global volatile char8*globalvolatilechar8p,\n" + " global volatile uchar8 *globalvolatileuchar8p,\n" + " global volatile short8* globalvolatileshort8p,\n" + " global volatile ushort8 * globalvolatileushort8p,\n" + " global volatile int8*globalvolatileint8p,\n" + " global volatile uint8 *globalvolatileuint8p,\n" + " global volatile long8* globalvolatilelong8p,\n" + " global volatile ulong8 * globalvolatileulong8p,\n" + " global volatile float8*globalvolatilefloat8p)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector8_restrict_p(global volatile char8 *restrict globalvolatilechar8restrictp,\n" + " global volatile uchar8* restrict globalvolatileuchar8restrictp,\n" + " global volatile short8 * restrict globalvolatileshort8restrictp,\n" + " global volatile ushort8*restrict globalvolatileushort8restrictp,\n" + " global volatile int8 *restrict globalvolatileint8restrictp,\n" + " global volatile uint8* restrict globalvolatileuint8restrictp,\n" + " global volatile long8 * restrict globalvolatilelong8restrictp,\n" + " global volatile ulong8*restrict globalvolatileulong8restrictp,\n" + " global volatile float8 *restrict globalvolatilefloat8restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector8_p(global const volatile char8* globalconstvolatilechar8p,\n" + " global const volatile uchar8 * globalconstvolatileuchar8p,\n" + " global const volatile short8*globalconstvolatileshort8p,\n" + " global const volatile ushort8 *globalconstvolatileushort8p,\n" + " global const volatile int8* globalconstvolatileint8p,\n" + " global const volatile uint8 * globalconstvolatileuint8p,\n" + " global const volatile long8*globalconstvolatilelong8p,\n" + " global const volatile ulong8 *globalconstvolatileulong8p,\n" + " global const volatile float8* globalconstvolatilefloat8p)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector8_restrict_p(global const volatile char8 * restrict globalconstvolatilechar8restrictp,\n" + " global const volatile uchar8*restrict globalconstvolatileuchar8restrictp,\n" + " global const volatile short8 *restrict globalconstvolatileshort8restrictp,\n" + " global const volatile ushort8* restrict globalconstvolatileushort8restrictp,\n" + " global const volatile int8 * restrict globalconstvolatileint8restrictp,\n" + " global const volatile uint8*restrict globalconstvolatileuint8restrictp,\n" + " global const volatile long8 *restrict globalconstvolatilelong8restrictp,\n" + " global const volatile ulong8* restrict globalconstvolatileulong8restrictp,\n" + " global const volatile float8 * restrict globalconstvolatilefloat8restrictp)\n" + "{}\n", + "\n" + "kernel void local_vector8_p(local char8*localchar8p,\n" + " local uchar8 *localuchar8p,\n" + " local short8* localshort8p,\n" + " local ushort8 * localushort8p,\n" + " local int8*localint8p,\n" + " local uint8 *localuint8p,\n" + " local long8* locallong8p,\n" + " local ulong8 * localulong8p,\n" + " local float8*localfloat8p)\n" + "{}\n", + "\n" + "kernel void local_vector8_restrict_p(local char8 *restrict localchar8restrictp,\n" + " local uchar8* restrict localuchar8restrictp,\n" + " local short8 * restrict localshort8restrictp,\n" + " local ushort8*restrict localushort8restrictp,\n" + " local int8 *restrict localint8restrictp,\n" + " local uint8* restrict localuint8restrictp,\n" + " local long8 * restrict locallong8restrictp,\n" + " local ulong8*restrict localulong8restrictp,\n" + " local float8 *restrict localfloat8restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_vector8_p(local const char8* localconstchar8p,\n" + " local const uchar8 * localconstuchar8p,\n" + " local const short8*localconstshort8p,\n" + " local const ushort8 *localconstushort8p,\n" + " local const int8* localconstint8p,\n" + " local const uint8 * localconstuint8p,\n" + " local const long8*localconstlong8p,\n" + " local const ulong8 *localconstulong8p,\n" + " local const float8* localconstfloat8p)\n" + "{}\n", + "\n" + "kernel void local_const_vector8_restrict_p(local const char8 * restrict localconstchar8restrictp,\n" + " local const uchar8*restrict localconstuchar8restrictp,\n" + " local const short8 *restrict localconstshort8restrictp,\n" + " local const ushort8* restrict localconstushort8restrictp,\n" + " local const int8 * restrict localconstint8restrictp,\n" + " local const uint8*restrict localconstuint8restrictp,\n" + " local const long8 *restrict localconstlong8restrictp,\n" + " local const ulong8* restrict localconstulong8restrictp,\n" + " local const float8 * restrict localconstfloat8restrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector8_p(local volatile char8*localvolatilechar8p,\n" + " local volatile uchar8 *localvolatileuchar8p,\n" + " local volatile short8* localvolatileshort8p,\n" + " local volatile ushort8 * localvolatileushort8p,\n" + " local volatile int8*localvolatileint8p,\n" + " local volatile uint8 *localvolatileuint8p,\n" + " local volatile long8* localvolatilelong8p,\n" + " local volatile ulong8 * localvolatileulong8p,\n" + " local volatile float8*localvolatilefloat8p)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector8_restrict_p(local volatile char8 *restrict localvolatilechar8restrictp,\n" + " local volatile uchar8* restrict localvolatileuchar8restrictp,\n" + " local volatile short8 * restrict localvolatileshort8restrictp,\n" + " local volatile ushort8*restrict localvolatileushort8restrictp,\n" + " local volatile int8 *restrict localvolatileint8restrictp,\n" + " local volatile uint8* restrict localvolatileuint8restrictp,\n" + " local volatile long8 * restrict localvolatilelong8restrictp,\n" + " local volatile ulong8*restrict localvolatileulong8restrictp,\n" + " local volatile float8 *restrict localvolatilefloat8restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector8_p(local const volatile char8* localconstvolatilechar8p,\n" + " local const volatile uchar8 * localconstvolatileuchar8p,\n" + " local const volatile short8*localconstvolatileshort8p,\n" + " local const volatile ushort8 *localconstvolatileushort8p,\n" + " local const volatile int8* localconstvolatileint8p,\n" + " local const volatile uint8 * localconstvolatileuint8p,\n" + " local const volatile long8*localconstvolatilelong8p,\n" + " local const volatile ulong8 *localconstvolatileulong8p,\n" + " local const volatile float8* localconstvolatilefloat8p)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector8_restrict_p(local const volatile char8 * restrict localconstvolatilechar8restrictp,\n" + " local const volatile uchar8*restrict localconstvolatileuchar8restrictp,\n" + " local const volatile short8 *restrict localconstvolatileshort8restrictp,\n" + " local const volatile ushort8* restrict localconstvolatileushort8restrictp,\n" + " local const volatile int8 * restrict localconstvolatileint8restrictp,\n" + " local const volatile uint8*restrict localconstvolatileuint8restrictp,\n" + " local const volatile long8 *restrict localconstvolatilelong8restrictp,\n" + " local const volatile ulong8* restrict localconstvolatileulong8restrictp,\n" + " local const volatile float8 * restrict localconstvolatilefloat8restrictp)\n" + "{}\n", + "\n" + "kernel void vector8_d(char8 char8d,\n" + " uchar8 uchar8d,\n" + " short8 short8d,\n" + " ushort8 ushort8d,\n" + " int8 int8d,\n" + " uint8 uint8d,\n" + " long8 long8d,\n" + " ulong8 ulong8d,\n" + " float8 float8d)\n" + "{}\n", + "\n" + "kernel void const_vector8_d(const char8 constchar8d,\n" + " const uchar8 constuchar8d,\n" + " const short8 constshort8d,\n" + " const ushort8 constushort8d,\n" + " const int8 constint8d,\n" + " const uint8 constuint8d,\n" + " const long8 constlong8d,\n" + " const ulong8 constulong8d,\n" + " const float8 constfloat8d)\n" + "{}\n", + "\n" + "kernel void private_vector8_d(private char8 privatechar8d,\n" + " private uchar8 privateuchar8d,\n" + " private short8 privateshort8d,\n" + " private ushort8 privateushort8d,\n" + " private int8 privateint8d,\n" + " private uint8 privateuint8d,\n" + " private long8 privatelong8d,\n" + " private ulong8 privateulong8d,\n" + " private float8 privatefloat8d)\n" + "{}\n", + "\n" + "kernel void private_const_vector8_d(private const char8 privateconstchar8d,\n" + " private const uchar8 privateconstuchar8d,\n" + " private const short8 privateconstshort8d,\n" + " private const ushort8 privateconstushort8d,\n" + " private const int8 privateconstint8d,\n" + " private const uint8 privateconstuint8d,\n" + " private const long8 privateconstlong8d,\n" + " private const ulong8 privateconstulong8d,\n" + " private const float8 privateconstfloat8d)\n" + "{}\n", + "\n" + "kernel void constant_vector16_p0(constant char16*constantchar16p,\n" + " constant uchar16 *constantuchar16p,\n" + " constant short16* constantshort16p,\n" + " constant ushort16 * constantushort16p)\n" + "{}\n", + "\n" + "kernel void constant_vector16_p1(constant int16*constantint16p,\n" + " constant uint16 *constantuint16p,\n" + " constant long16* constantlong16p,\n" + " constant ulong16 * constantulong16p)\n" + "{}\n", + "\n" + "kernel void constant_vector16_p2(constant float16*constantfloat16p)\n" + "{}\n", + "\n" + "kernel void constant_vector16_restrict_p0(constant char16 *restrict constantchar16restrictp,\n" + " constant uchar16* restrict constantuchar16restrictp,\n" + " constant short16 * restrict constantshort16restrictp,\n" + " constant ushort16*restrict constantushort16restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector16_restrict_p1(constant int16 *restrict constantint16restrictp,\n" + " constant uint16* restrict constantuint16restrictp,\n" + " constant long16 * restrict constantlong16restrictp,\n" + " constant ulong16*restrict constantulong16restrictp)\n" + "{}\n", + "\n" + "kernel void constant_vector16_restrict_p2(constant float16 *restrict constantfloat16restrictp)\n" + "{}\n", + "\n" + "kernel void global_vector16_p(global char16*globalchar16p,\n" + " global uchar16 *globaluchar16p,\n" + " global short16* globalshort16p,\n" + " global ushort16 * globalushort16p,\n" + " global int16*globalint16p,\n" + " global uint16 *globaluint16p,\n" + " global long16* globallong16p,\n" + " global ulong16 * globalulong16p,\n" + " global float16*globalfloat16p)\n" + "{}\n", + "\n" + "kernel void global_vector16_restrict_p(global char16 *restrict globalchar16restrictp,\n" + " global uchar16* restrict globaluchar16restrictp,\n" + " global short16 * restrict globalshort16restrictp,\n" + " global ushort16*restrict globalushort16restrictp,\n" + " global int16 *restrict globalint16restrictp,\n" + " global uint16* restrict globaluint16restrictp,\n" + " global long16 * restrict globallong16restrictp,\n" + " global ulong16*restrict globalulong16restrictp,\n" + " global float16 *restrict globalfloat16restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_vector16_p(global const char16* globalconstchar16p,\n" + " global const uchar16 * globalconstuchar16p,\n" + " global const short16*globalconstshort16p,\n" + " global const ushort16 *globalconstushort16p,\n" + " global const int16* globalconstint16p,\n" + " global const uint16 * globalconstuint16p,\n" + " global const long16*globalconstlong16p,\n" + " global const ulong16 *globalconstulong16p,\n" + " global const float16* globalconstfloat16p)\n" + "{}\n", + "\n" + "kernel void global_const_vector16_restrict_p(global const char16 * restrict globalconstchar16restrictp,\n" + " global const uchar16*restrict globalconstuchar16restrictp,\n" + " global const short16 *restrict globalconstshort16restrictp,\n" + " global const ushort16* restrict globalconstushort16restrictp,\n" + " global const int16 * restrict globalconstint16restrictp,\n" + " global const uint16*restrict globalconstuint16restrictp,\n" + " global const long16 *restrict globalconstlong16restrictp,\n" + " global const ulong16* restrict globalconstulong16restrictp,\n" + " global const float16 * restrict globalconstfloat16restrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector16_p(global volatile char16*globalvolatilechar16p,\n" + " global volatile uchar16 *globalvolatileuchar16p,\n" + " global volatile short16* globalvolatileshort16p,\n" + " global volatile ushort16 * globalvolatileushort16p,\n" + " global volatile int16*globalvolatileint16p,\n" + " global volatile uint16 *globalvolatileuint16p,\n" + " global volatile long16* globalvolatilelong16p,\n" + " global volatile ulong16 * globalvolatileulong16p,\n" + " global volatile float16*globalvolatilefloat16p)\n" + "{}\n", + "\n" + "kernel void global_volatile_vector16_restrict_p(global volatile char16 *restrict globalvolatilechar16restrictp,\n" + " global volatile uchar16* restrict globalvolatileuchar16restrictp,\n" + " global volatile short16 * restrict globalvolatileshort16restrictp,\n" + " global volatile ushort16*restrict globalvolatileushort16restrictp,\n" + " global volatile int16 *restrict globalvolatileint16restrictp,\n" + " global volatile uint16* restrict globalvolatileuint16restrictp,\n" + " global volatile long16 * restrict globalvolatilelong16restrictp,\n" + " global volatile ulong16*restrict globalvolatileulong16restrictp,\n" + " global volatile float16 *restrict globalvolatilefloat16restrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector16_p(global const volatile char16* globalconstvolatilechar16p,\n" + " global const volatile uchar16 * globalconstvolatileuchar16p,\n" + " global const volatile short16*globalconstvolatileshort16p,\n" + " global const volatile ushort16 *globalconstvolatileushort16p,\n" + " global const volatile int16* globalconstvolatileint16p,\n" + " global const volatile uint16 * globalconstvolatileuint16p,\n" + " global const volatile long16*globalconstvolatilelong16p,\n" + " global const volatile ulong16 *globalconstvolatileulong16p,\n" + " global const volatile float16* globalconstvolatilefloat16p)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_vector16_restrict_p(global const volatile char16 * restrict globalconstvolatilechar16restrictp,\n" + " global const volatile uchar16*restrict globalconstvolatileuchar16restrictp,\n" + " global const volatile short16 *restrict globalconstvolatileshort16restrictp,\n" + " global const volatile ushort16* restrict globalconstvolatileushort16restrictp,\n" + " global const volatile int16 * restrict globalconstvolatileint16restrictp,\n" + " global const volatile uint16*restrict globalconstvolatileuint16restrictp,\n" + " global const volatile long16 *restrict globalconstvolatilelong16restrictp,\n" + " global const volatile ulong16* restrict globalconstvolatileulong16restrictp,\n" + " global const volatile float16 * restrict globalconstvolatilefloat16restrictp)\n" + "{}\n", + "\n" + "kernel void local_vector16_p(local char16*localchar16p,\n" + " local uchar16 *localuchar16p,\n" + " local short16* localshort16p,\n" + " local ushort16 * localushort16p,\n" + " local int16*localint16p,\n" + " local uint16 *localuint16p,\n" + " local long16* locallong16p,\n" + " local ulong16 * localulong16p,\n" + " local float16*localfloat16p)\n" + "{}\n", + "\n" + "kernel void local_vector16_restrict_p(local char16 *restrict localchar16restrictp,\n" + " local uchar16* restrict localuchar16restrictp,\n" + " local short16 * restrict localshort16restrictp,\n" + " local ushort16*restrict localushort16restrictp,\n" + " local int16 *restrict localint16restrictp,\n" + " local uint16* restrict localuint16restrictp,\n" + " local long16 * restrict locallong16restrictp,\n" + " local ulong16*restrict localulong16restrictp,\n" + " local float16 *restrict localfloat16restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_vector16_p(local const char16* localconstchar16p,\n" + " local const uchar16 * localconstuchar16p,\n" + " local const short16*localconstshort16p,\n" + " local const ushort16 *localconstushort16p,\n" + " local const int16* localconstint16p,\n" + " local const uint16 * localconstuint16p,\n" + " local const long16*localconstlong16p,\n" + " local const ulong16 *localconstulong16p,\n" + " local const float16* localconstfloat16p)\n" + "{}\n", + "\n" + "kernel void local_const_vector16_restrict_p(local const char16 * restrict localconstchar16restrictp,\n" + " local const uchar16*restrict localconstuchar16restrictp,\n" + " local const short16 *restrict localconstshort16restrictp,\n" + " local const ushort16* restrict localconstushort16restrictp,\n" + " local const int16 * restrict localconstint16restrictp,\n" + " local const uint16*restrict localconstuint16restrictp,\n" + " local const long16 *restrict localconstlong16restrictp,\n" + " local const ulong16* restrict localconstulong16restrictp,\n" + " local const float16 * restrict localconstfloat16restrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector16_p(local volatile char16*localvolatilechar16p,\n" + " local volatile uchar16 *localvolatileuchar16p,\n" + " local volatile short16* localvolatileshort16p,\n" + " local volatile ushort16 * localvolatileushort16p,\n" + " local volatile int16*localvolatileint16p,\n" + " local volatile uint16 *localvolatileuint16p,\n" + " local volatile long16* localvolatilelong16p,\n" + " local volatile ulong16 * localvolatileulong16p,\n" + " local volatile float16*localvolatilefloat16p)\n" + "{}\n", + "\n" + "kernel void local_volatile_vector16_restrict_p(local volatile char16 *restrict localvolatilechar16restrictp,\n" + " local volatile uchar16* restrict localvolatileuchar16restrictp,\n" + " local volatile short16 * restrict localvolatileshort16restrictp,\n" + " local volatile ushort16*restrict localvolatileushort16restrictp,\n" + " local volatile int16 *restrict localvolatileint16restrictp,\n" + " local volatile uint16* restrict localvolatileuint16restrictp,\n" + " local volatile long16 * restrict localvolatilelong16restrictp,\n" + " local volatile ulong16*restrict localvolatileulong16restrictp,\n" + " local volatile float16 *restrict localvolatilefloat16restrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector16_p(local const volatile char16* localconstvolatilechar16p,\n" + " local const volatile uchar16 * localconstvolatileuchar16p,\n" + " local const volatile short16*localconstvolatileshort16p,\n" + " local const volatile ushort16 *localconstvolatileushort16p,\n" + " local const volatile int16* localconstvolatileint16p,\n" + " local const volatile uint16 * localconstvolatileuint16p,\n" + " local const volatile long16*localconstvolatilelong16p,\n" + " local const volatile ulong16 *localconstvolatileulong16p,\n" + " local const volatile float16* localconstvolatilefloat16p)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_vector16_restrict_p(local const volatile char16 * restrict localconstvolatilechar16restrictp,\n" + " local const volatile uchar16*restrict localconstvolatileuchar16restrictp,\n" + " local const volatile short16 *restrict localconstvolatileshort16restrictp,\n" + " local const volatile ushort16* restrict localconstvolatileushort16restrictp,\n" + " local const volatile int16 * restrict localconstvolatileint16restrictp,\n" + " local const volatile uint16*restrict localconstvolatileuint16restrictp,\n" + " local const volatile long16 *restrict localconstvolatilelong16restrictp,\n" + " local const volatile ulong16* restrict localconstvolatileulong16restrictp,\n" + " local const volatile float16 * restrict localconstvolatilefloat16restrictp)\n" + "{}\n", + "\n" + "kernel void vector16_d(char16 char16d,\n" + " uchar16 uchar16d,\n" + " short16 short16d,\n" + " ushort16 ushort16d,\n" + " int16 int16d,\n" + " uint16 uint16d,\n" + " long16 long16d,\n" + " ulong16 ulong16d,\n" + " float16 float16d)\n" + "{}\n", + "\n" + "kernel void const_vector16_d(const char16 constchar16d,\n" + " const uchar16 constuchar16d,\n" + " const short16 constshort16d,\n" + " const ushort16 constushort16d,\n" + " const int16 constint16d,\n" + " const uint16 constuint16d,\n" + " const long16 constlong16d,\n" + " const ulong16 constulong16d,\n" + " const float16 constfloat16d)\n" + "{}\n", + "\n" + "kernel void private_vector16_d(private char16 privatechar16d,\n" + " private uchar16 privateuchar16d,\n" + " private short16 privateshort16d,\n" + " private ushort16 privateushort16d,\n" + " private int16 privateint16d,\n" + " private uint16 privateuint16d,\n" + " private long16 privatelong16d,\n" + " private ulong16 privateulong16d,\n" + " private float16 privatefloat16d)\n" + "{}\n", + "\n" + "kernel void private_const_vector16_d(private const char16 privateconstchar16d,\n" + " private const uchar16 privateconstuchar16d,\n" + " private const short16 privateconstshort16d,\n" + " private const ushort16 privateconstushort16d,\n" + " private const int16 privateconstint16d,\n" + " private const uint16 privateconstuint16d,\n" + " private const long16 privateconstlong16d,\n" + " private const ulong16 privateconstulong16d,\n" + " private const float16 privateconstfloat16d)\n" + "{}\n", + "\n" + "kernel void constant_derived_p0(constant typedef_type*constanttypedef_typep,\n" + " constant struct struct_type *constantstructstruct_typep,\n" + " constant typedef_struct_type* constanttypedef_struct_typep,\n" + " constant union union_type * constantunionunion_typep)\n" + "{}\n", + "\n" + "kernel void constant_derived_p1(constant typedef_union_type*constanttypedef_union_typep,\n" + " constant enum enum_type *constantenumenum_typep,\n" + " constant typedef_enum_type* constanttypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void constant_derived_restrict_p0(constant typedef_type * restrict constanttypedef_typerestrictp,\n" + " constant struct struct_type*restrict constantstructstruct_typerestrictp,\n" + " constant typedef_struct_type *restrict constanttypedef_struct_typerestrictp,\n" + " constant union union_type* restrict constantunionunion_typerestrictp)\n" + "{}\n", + "\n" + "kernel void constant_derived_restrict_p1(constant typedef_union_type * restrict constanttypedef_union_typerestrictp,\n" + " constant enum enum_type*restrict constantenumenum_typerestrictp,\n" + " constant typedef_enum_type *restrict constanttypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void global_derived_p(global typedef_type*globaltypedef_typep,\n" + " global struct struct_type *globalstructstruct_typep,\n" + " global typedef_struct_type* globaltypedef_struct_typep,\n" + " global union union_type * globalunionunion_typep,\n" + " global typedef_union_type*globaltypedef_union_typep,\n" + " global enum enum_type *globalenumenum_typep,\n" + " global typedef_enum_type* globaltypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void global_derived_restrict_p(global typedef_type * restrict globaltypedef_typerestrictp,\n" + " global struct struct_type*restrict globalstructstruct_typerestrictp,\n" + " global typedef_struct_type *restrict globaltypedef_struct_typerestrictp,\n" + " global union union_type* restrict globalunionunion_typerestrictp,\n" + " global typedef_union_type * restrict globaltypedef_union_typerestrictp,\n" + " global enum enum_type*restrict globalenumenum_typerestrictp,\n" + " global typedef_enum_type *restrict globaltypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void global_const_derived_p(global const typedef_type* globalconsttypedef_typep,\n" + " global const struct struct_type * globalconststructstruct_typep,\n" + " global const typedef_struct_type*globalconsttypedef_struct_typep,\n" + " global const union union_type *globalconstunionunion_typep,\n" + " global const typedef_union_type* globalconsttypedef_union_typep,\n" + " global const enum enum_type * globalconstenumenum_typep,\n" + " global const typedef_enum_type*globalconsttypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void global_const_derived_restrict_p(global const typedef_type *restrict globalconsttypedef_typerestrictp,\n" + " global const struct struct_type* restrict globalconststructstruct_typerestrictp,\n" + " global const typedef_struct_type * restrict globalconsttypedef_struct_typerestrictp,\n" + " global const union union_type*restrict globalconstunionunion_typerestrictp,\n" + " global const typedef_union_type *restrict globalconsttypedef_union_typerestrictp,\n" + " global const enum enum_type* restrict globalconstenumenum_typerestrictp,\n" + " global const typedef_enum_type * restrict globalconsttypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void global_volatile_derived_p(global volatile typedef_type*globalvolatiletypedef_typep,\n" + " global volatile struct struct_type *globalvolatilestructstruct_typep,\n" + " global volatile typedef_struct_type* globalvolatiletypedef_struct_typep,\n" + " global volatile union union_type * globalvolatileunionunion_typep,\n" + " global volatile typedef_union_type*globalvolatiletypedef_union_typep,\n" + " global volatile enum enum_type *globalvolatileenumenum_typep,\n" + " global volatile typedef_enum_type* globalvolatiletypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void global_volatile_derived_restrict_p(global volatile typedef_type * restrict globalvolatiletypedef_typerestrictp,\n" + " global volatile struct struct_type*restrict globalvolatilestructstruct_typerestrictp,\n" + " global volatile typedef_struct_type *restrict globalvolatiletypedef_struct_typerestrictp,\n" + " global volatile union union_type* restrict globalvolatileunionunion_typerestrictp,\n" + " global volatile typedef_union_type * restrict globalvolatiletypedef_union_typerestrictp,\n" + " global volatile enum enum_type*restrict globalvolatileenumenum_typerestrictp,\n" + " global volatile typedef_enum_type *restrict globalvolatiletypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_derived_p(global const volatile typedef_type* globalconstvolatiletypedef_typep,\n" + " global const volatile struct struct_type * globalconstvolatilestructstruct_typep,\n" + " global const volatile typedef_struct_type*globalconstvolatiletypedef_struct_typep,\n" + " global const volatile union union_type *globalconstvolatileunionunion_typep,\n" + " global const volatile typedef_union_type* globalconstvolatiletypedef_union_typep,\n" + " global const volatile enum enum_type * globalconstvolatileenumenum_typep,\n" + " global const volatile typedef_enum_type*globalconstvolatiletypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void global_const_volatile_derived_restrict_p(global const volatile typedef_type *restrict globalconstvolatiletypedef_typerestrictp,\n" + " global const volatile struct struct_type* restrict globalconstvolatilestructstruct_typerestrictp,\n" + " global const volatile typedef_struct_type * restrict globalconstvolatiletypedef_struct_typerestrictp,\n" + " global const volatile union union_type*restrict globalconstvolatileunionunion_typerestrictp,\n" + " global const volatile typedef_union_type *restrict globalconstvolatiletypedef_union_typerestrictp,\n" + " global const volatile enum enum_type* restrict globalconstvolatileenumenum_typerestrictp,\n" + " global const volatile typedef_enum_type * restrict globalconstvolatiletypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void local_derived_p(local typedef_type*localtypedef_typep,\n" + " local struct struct_type *localstructstruct_typep,\n" + " local typedef_struct_type* localtypedef_struct_typep,\n" + " local union union_type * localunionunion_typep,\n" + " local typedef_union_type*localtypedef_union_typep,\n" + " local enum enum_type *localenumenum_typep,\n" + " local typedef_enum_type* localtypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void local_derived_restrict_p(local typedef_type * restrict localtypedef_typerestrictp,\n" + " local struct struct_type*restrict localstructstruct_typerestrictp,\n" + " local typedef_struct_type *restrict localtypedef_struct_typerestrictp,\n" + " local union union_type* restrict localunionunion_typerestrictp,\n" + " local typedef_union_type * restrict localtypedef_union_typerestrictp,\n" + " local enum enum_type*restrict localenumenum_typerestrictp,\n" + " local typedef_enum_type *restrict localtypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void local_const_derived_p(local const typedef_type* localconsttypedef_typep,\n" + " local const struct struct_type * localconststructstruct_typep,\n" + " local const typedef_struct_type*localconsttypedef_struct_typep,\n" + " local const union union_type *localconstunionunion_typep,\n" + " local const typedef_union_type* localconsttypedef_union_typep,\n" + " local const enum enum_type * localconstenumenum_typep,\n" + " local const typedef_enum_type*localconsttypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void local_const_derived_restrict_p(local const typedef_type *restrict localconsttypedef_typerestrictp,\n" + " local const struct struct_type* restrict localconststructstruct_typerestrictp,\n" + " local const typedef_struct_type * restrict localconsttypedef_struct_typerestrictp,\n" + " local const union union_type*restrict localconstunionunion_typerestrictp,\n" + " local const typedef_union_type *restrict localconsttypedef_union_typerestrictp,\n" + " local const enum enum_type* restrict localconstenumenum_typerestrictp,\n" + " local const typedef_enum_type * restrict localconsttypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void local_volatile_derived_p(local volatile typedef_type*localvolatiletypedef_typep,\n" + " local volatile struct struct_type *localvolatilestructstruct_typep,\n" + " local volatile typedef_struct_type* localvolatiletypedef_struct_typep,\n" + " local volatile union union_type * localvolatileunionunion_typep,\n" + " local volatile typedef_union_type*localvolatiletypedef_union_typep,\n" + " local volatile enum enum_type *localvolatileenumenum_typep,\n" + " local volatile typedef_enum_type* localvolatiletypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void local_volatile_derived_restrict_p(local volatile typedef_type * restrict localvolatiletypedef_typerestrictp,\n" + " local volatile struct struct_type*restrict localvolatilestructstruct_typerestrictp,\n" + " local volatile typedef_struct_type *restrict localvolatiletypedef_struct_typerestrictp,\n" + " local volatile union union_type* restrict localvolatileunionunion_typerestrictp,\n" + " local volatile typedef_union_type * restrict localvolatiletypedef_union_typerestrictp,\n" + " local volatile enum enum_type*restrict localvolatileenumenum_typerestrictp,\n" + " local volatile typedef_enum_type *restrict localvolatiletypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_derived_p(local const volatile typedef_type* localconstvolatiletypedef_typep,\n" + " local const volatile struct struct_type * localconstvolatilestructstruct_typep,\n" + " local const volatile typedef_struct_type*localconstvolatiletypedef_struct_typep,\n" + " local const volatile union union_type *localconstvolatileunionunion_typep,\n" + " local const volatile typedef_union_type* localconstvolatiletypedef_union_typep,\n" + " local const volatile enum enum_type * localconstvolatileenumenum_typep,\n" + " local const volatile typedef_enum_type*localconstvolatiletypedef_enum_typep)\n" + "{}\n", + "\n" + "kernel void local_const_volatile_derived_restrict_p(local const volatile typedef_type *restrict localconstvolatiletypedef_typerestrictp,\n" + " local const volatile struct struct_type* restrict localconstvolatilestructstruct_typerestrictp,\n" + " local const volatile typedef_struct_type * restrict localconstvolatiletypedef_struct_typerestrictp,\n" + " local const volatile union union_type*restrict localconstvolatileunionunion_typerestrictp,\n" + " local const volatile typedef_union_type *restrict localconstvolatiletypedef_union_typerestrictp,\n" + " local const volatile enum enum_type* restrict localconstvolatileenumenum_typerestrictp,\n" + " local const volatile typedef_enum_type * restrict localconstvolatiletypedef_enum_typerestrictp)\n" + "{}\n", + "\n" + "kernel void derived_d(typedef_type typedef_typed,\n" + " struct struct_type structstruct_typed,\n" + " typedef_struct_type typedef_struct_typed,\n" + " union union_type unionunion_typed,\n" + " typedef_union_type typedef_union_typed,\n" + " enum enum_type enumenum_typed,\n" + " typedef_enum_type typedef_enum_typed)\n" + "{}\n", + "\n" + "kernel void const_derived_d(const typedef_type consttypedef_typed,\n" + " const struct struct_type conststructstruct_typed,\n" + " const typedef_struct_type consttypedef_struct_typed,\n" + " const union union_type constunionunion_typed,\n" + " const typedef_union_type consttypedef_union_typed,\n" + " const enum enum_type constenumenum_typed,\n" + " const typedef_enum_type consttypedef_enum_typed)\n" + "{}\n", + "\n" + "kernel void private_derived_d(private typedef_type privatetypedef_typed,\n" + " private struct struct_type privatestructstruct_typed,\n" + " private typedef_struct_type privatetypedef_struct_typed,\n" + " private union union_type privateunionunion_typed,\n" + " private typedef_union_type privatetypedef_union_typed,\n" + " private enum enum_type privateenumenum_typed,\n" + " private typedef_enum_type privatetypedef_enum_typed)\n" + "{}\n", + "\n" + "kernel void private_const_derived_d(private const typedef_type privateconsttypedef_typed,\n" + " private const struct struct_type privateconststructstruct_typed,\n" + " private const typedef_struct_type privateconsttypedef_struct_typed,\n" + " private const union union_type privateconstunionunion_typed,\n" + " private const typedef_union_type privateconsttypedef_union_typed,\n" + " private const enum enum_type privateconstenumenum_typed,\n" + " private const typedef_enum_type privateconsttypedef_enum_typed)\n" + "{}\n", + "\n" +}; + +const char * required_arg_info[][72] = { + // The minimum value of CL_DEVICE_MAX_CONSTANT_ARGS is 4 + { + "constant_scalar_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "void*", "constantvoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char*", "constantcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar*", "constantucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar*", "constantunsignedcharp", + NULL + }, + { + "constant_scalar_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short*", "constantshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort*", "constantushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort*", "constantunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int*", "constantintp", + NULL + }, + { + "constant_scalar_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint*", "constantuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint*", "constantunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long*", "constantlongp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong*", "constantulongp", + NULL + }, + { + "constant_scalar_p3", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong*", "constantunsignedlongp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float*", "constantfloatp", + NULL + }, + { + "constant_scalar_restrict_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "constantvoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "constantcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "constantucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "constantunsignedcharrestrictp", + NULL + }, + { + "constant_scalar_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "constantshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "constantushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "constantunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "constantintrestrictp", + NULL + }, + { + "constant_scalar_restrict_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "constantuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "constantunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "constantlongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "constantulongrestrictp", + NULL + }, + { + "constant_scalar_restrict_p3", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "constantunsignedlongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "constantfloatrestrictp", + NULL + }, + { + "global_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "void*", "globalvoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char*", "globalcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar*", "globalucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar*", "globalunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short*", "globalshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort*", "globalushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort*", "globalunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int*", "globalintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint*", "globaluintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint*", "globalunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long*", "globallongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong*", "globalulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong*", "globalunsignedlongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float*", "globalfloatp", + NULL + }, + { + "global_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "globalvoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "globalcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "globalshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "globalintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globaluintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globalunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "globallongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalunsignedlongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "globalfloatrestrictp", + NULL + }, + { + "global_const_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "void*", "globalconstvoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char*", "globalconstcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar*", "globalconstucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar*", "globalconstunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short*", "globalconstshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort*", "globalconstushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort*", "globalconstunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int*", "globalconstintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint*", "globalconstuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint*", "globalconstunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long*", "globalconstlongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong*", "globalconstulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong*", "globalconstunsignedlongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float*", "globalconstfloatp", + NULL + }, + { + "global_const_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "globalconstvoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "globalconstcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalconstucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalconstunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "globalconstshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalconstushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalconstunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "globalconstintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globalconstuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globalconstunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "globalconstlongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalconstulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalconstunsignedlongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "globalconstfloatrestrictp", + NULL + }, + { + "global_volatile_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "void*", "globalvolatilevoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char*", "globalvolatilecharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "globalvolatileucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "globalvolatileunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short*", "globalvolatileshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "globalvolatileushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "globalvolatileunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int*", "globalvolatileintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "globalvolatileuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "globalvolatileunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long*", "globalvolatilelongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "globalvolatileulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "globalvolatileunsignedlongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float*", "globalvolatilefloatp", + NULL + }, + { + "global_volatile_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "globalvolatilevoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "globalvolatilecharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalvolatileucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalvolatileunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "globalvolatileshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalvolatileushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalvolatileunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "globalvolatileintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globalvolatileuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globalvolatileunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "globalvolatilelongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalvolatileulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalvolatileunsignedlongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "globalvolatilefloatrestrictp", + NULL + }, + { + "global_const_volatile_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "void*", "globalconstvolatilevoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char*", "globalconstvolatilecharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "globalconstvolatileucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "globalconstvolatileunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short*", "globalconstvolatileshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "globalconstvolatileushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "globalconstvolatileunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int*", "globalconstvolatileintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "globalconstvolatileuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "globalconstvolatileunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long*", "globalconstvolatilelongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "globalconstvolatileulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "globalconstvolatileunsignedlongp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float*", "globalconstvolatilefloatp", + NULL + }, + { + "global_const_volatile_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "globalconstvolatilevoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "globalconstvolatilecharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalconstvolatileucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "globalconstvolatileunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "globalconstvolatileshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalconstvolatileushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "globalconstvolatileunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "globalconstvolatileintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globalconstvolatileuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "globalconstvolatileunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "globalconstvolatilelongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalconstvolatileulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "globalconstvolatileunsignedlongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "globalconstvolatilefloatrestrictp", + NULL + }, + { + "local_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "void*", "localvoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char*", "localcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar*", "localucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar*", "localunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short*", "localshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort*", "localushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort*", "localunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int*", "localintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint*", "localuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint*", "localunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long*", "locallongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong*", "localulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong*", "localunsignedlongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float*", "localfloatp", + NULL + }, + { + "local_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "localvoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "localcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "localshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "localintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "locallongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localunsignedlongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "localfloatrestrictp", + NULL + }, + { + "local_const_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "void*", "localconstvoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char*", "localconstcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar*", "localconstucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar*", "localconstunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short*", "localconstshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort*", "localconstushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort*", "localconstunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int*", "localconstintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint*", "localconstuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint*", "localconstunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long*", "localconstlongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong*", "localconstulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong*", "localconstunsignedlongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float*", "localconstfloatp", + NULL + }, + { + "local_const_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "localconstvoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "localconstcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localconstucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localconstunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "localconstshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localconstushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localconstunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "localconstintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localconstuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localconstunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "localconstlongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localconstulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localconstunsignedlongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "localconstfloatrestrictp", + NULL + }, + { + "local_volatile_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "void*", "localvolatilevoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char*", "localvolatilecharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "localvolatileucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "localvolatileunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short*", "localvolatileshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "localvolatileushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "localvolatileunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int*", "localvolatileintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "localvolatileuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "localvolatileunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long*", "localvolatilelongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "localvolatileulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "localvolatileunsignedlongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float*", "localvolatilefloatp", + NULL + }, + { + "local_volatile_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "localvolatilevoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "localvolatilecharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localvolatileucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localvolatileunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "localvolatileshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localvolatileushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localvolatileunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "localvolatileintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localvolatileuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localvolatileunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "localvolatilelongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localvolatileulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localvolatileunsignedlongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "localvolatilefloatrestrictp", + NULL + }, + { + "local_const_volatile_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "void*", "localconstvolatilevoidp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char*", "localconstvolatilecharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "localconstvolatileucharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar*", "localconstvolatileunsignedcharp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short*", "localconstvolatileshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "localconstvolatileushortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort*", "localconstvolatileunsignedshortp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int*", "localconstvolatileintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "localconstvolatileuintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint*", "localconstvolatileunsignedintp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long*", "localconstvolatilelongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "localconstvolatileulongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong*", "localconstvolatileunsignedlongp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float*", "localconstvolatilefloatp", + NULL + }, + { + "local_const_volatile_scalar_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "void*", "localconstvolatilevoidrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char*", "localconstvolatilecharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localconstvolatileucharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar*", "localconstvolatileunsignedcharrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short*", "localconstvolatileshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localconstvolatileushortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort*", "localconstvolatileunsignedshortrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int*", "localconstvolatileintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localconstvolatileuintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint*", "localconstvolatileunsignedintrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long*", "localconstvolatilelongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localconstvolatileulongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong*", "localconstvolatileunsignedlongrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float*", "localconstvolatilefloatrestrictp", + NULL + }, + { + "scalar_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char", "chard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "uchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "unsignedchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short", "shortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "ushortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "unsignedshortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int", "intd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "uintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "unsignedintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long", "longd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "ulongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "unsignedlongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float", "floatd", + NULL + }, + { + "const_scalar_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char", "constchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "constuchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "constunsignedchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short", "constshortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "constushortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "constunsignedshortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int", "constintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "constuintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "constunsignedintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long", "constlongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "constulongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "constunsignedlongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float", "constfloatd", + NULL + }, + { + "private_scalar_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char", "privatechard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "privateuchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "privateunsignedchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short", "privateshortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "privateushortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "privateunsignedshortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int", "privateintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "privateuintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "privateunsignedintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long", "privatelongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "privateulongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "privateunsignedlongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float", "privatefloatd", + NULL + }, + { + "private_const_scalar_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char", "privateconstchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "privateconstuchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar", "privateconstunsignedchard", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short", "privateconstshortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "privateconstushortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort", "privateconstunsignedshortd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int", "privateconstintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "privateconstuintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint", "privateconstunsignedintd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long", "privateconstlongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "privateconstulongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong", "privateconstunsignedlongd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float", "privateconstfloatd", + NULL + }, + { + "constant_vector2_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char2*", "constantchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar2*", "constantuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short2*", "constantshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort2*", "constantushort2p", + NULL + }, + { + "constant_vector2_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int2*", "constantint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint2*", "constantuint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long2*", "constantlong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong2*", "constantulong2p", + NULL + }, + { + "constant_vector2_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float2*", "constantfloat2p", + NULL + }, + { + "constant_vector2_restrict_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "constantchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "constantuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "constantshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "constantushort2restrictp", + NULL + }, + { + "constant_vector2_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "constantint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "constantuint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "constantlong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "constantulong2restrictp", + NULL + }, + { + "constant_vector2_restrict_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "constantfloat2restrictp", + NULL + }, + { + "global_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char2*", "globalchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar2*", "globaluchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short2*", "globalshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort2*", "globalushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int2*", "globalint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint2*", "globaluint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long2*", "globallong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong2*", "globalulong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float2*", "globalfloat2p", + NULL + }, + { + "global_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "globalchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "globaluchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "globalshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "globalushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "globalint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "globaluint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "globallong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "globalulong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "globalfloat2restrictp", + NULL + }, + { + "global_const_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char2*", "globalconstchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar2*", "globalconstuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short2*", "globalconstshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort2*", "globalconstushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int2*", "globalconstint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint2*", "globalconstuint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long2*", "globalconstlong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong2*", "globalconstulong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float2*", "globalconstfloat2p", + NULL + }, + { + "global_const_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "globalconstchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "globalconstuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "globalconstshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "globalconstushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "globalconstint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "globalconstuint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "globalconstlong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "globalconstulong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "globalconstfloat2restrictp", + NULL + }, + { + "global_volatile_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char2*", "globalvolatilechar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar2*", "globalvolatileuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short2*", "globalvolatileshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort2*", "globalvolatileushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int2*", "globalvolatileint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint2*", "globalvolatileuint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long2*", "globalvolatilelong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong2*", "globalvolatileulong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float2*", "globalvolatilefloat2p", + NULL + }, + { + "global_volatile_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "globalvolatilechar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "globalvolatileuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "globalvolatileshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "globalvolatileushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "globalvolatileint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "globalvolatileuint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "globalvolatilelong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "globalvolatileulong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "globalvolatilefloat2restrictp", + NULL + }, + { + "global_const_volatile_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char2*", "globalconstvolatilechar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar2*", "globalconstvolatileuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short2*", "globalconstvolatileshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort2*", "globalconstvolatileushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int2*", "globalconstvolatileint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint2*", "globalconstvolatileuint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long2*", "globalconstvolatilelong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong2*", "globalconstvolatileulong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float2*", "globalconstvolatilefloat2p", + NULL + }, + { + "global_const_volatile_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "globalconstvolatilechar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "globalconstvolatileuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "globalconstvolatileshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "globalconstvolatileushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "globalconstvolatileint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "globalconstvolatileuint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "globalconstvolatilelong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "globalconstvolatileulong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "globalconstvolatilefloat2restrictp", + NULL + }, + { + "local_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char2*", "localchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar2*", "localuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short2*", "localshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort2*", "localushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int2*", "localint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint2*", "localuint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long2*", "locallong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong2*", "localulong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float2*", "localfloat2p", + NULL + }, + { + "local_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "localchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "localuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "localshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "localushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "localint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "localuint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "locallong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "localulong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "localfloat2restrictp", + NULL + }, + { + "local_const_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char2*", "localconstchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar2*", "localconstuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short2*", "localconstshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort2*", "localconstushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int2*", "localconstint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint2*", "localconstuint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long2*", "localconstlong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong2*", "localconstulong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float2*", "localconstfloat2p", + NULL + }, + { + "local_const_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "localconstchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "localconstuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "localconstshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "localconstushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "localconstint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "localconstuint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "localconstlong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "localconstulong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "localconstfloat2restrictp", + NULL + }, + { + "local_volatile_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char2*", "localvolatilechar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar2*", "localvolatileuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short2*", "localvolatileshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort2*", "localvolatileushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int2*", "localvolatileint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint2*", "localvolatileuint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long2*", "localvolatilelong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong2*", "localvolatileulong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float2*", "localvolatilefloat2p", + NULL + }, + { + "local_volatile_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "localvolatilechar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "localvolatileuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "localvolatileshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "localvolatileushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "localvolatileint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "localvolatileuint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "localvolatilelong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "localvolatileulong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "localvolatilefloat2restrictp", + NULL + }, + { + "local_const_volatile_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char2*", "localconstvolatilechar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar2*", "localconstvolatileuchar2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short2*", "localconstvolatileshort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort2*", "localconstvolatileushort2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int2*", "localconstvolatileint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint2*", "localconstvolatileuint2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long2*", "localconstvolatilelong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong2*", "localconstvolatileulong2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float2*", "localconstvolatilefloat2p", + NULL + }, + { + "local_const_volatile_vector2_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char2*", "localconstvolatilechar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar2*", "localconstvolatileuchar2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short2*", "localconstvolatileshort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort2*", "localconstvolatileushort2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int2*", "localconstvolatileint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint2*", "localconstvolatileuint2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long2*", "localconstvolatilelong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong2*", "localconstvolatileulong2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float2*", "localconstvolatilefloat2restrictp", + NULL + }, + { + "vector2_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char2", "char2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar2", "uchar2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short2", "short2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort2", "ushort2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int2", "int2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint2", "uint2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long2", "long2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong2", "ulong2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float2", "float2d", + NULL + }, + { + "const_vector2_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char2", "constchar2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar2", "constuchar2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short2", "constshort2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort2", "constushort2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int2", "constint2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint2", "constuint2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long2", "constlong2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong2", "constulong2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float2", "constfloat2d", + NULL + }, + { + "private_vector2_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char2", "privatechar2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar2", "privateuchar2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short2", "privateshort2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort2", "privateushort2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int2", "privateint2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint2", "privateuint2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long2", "privatelong2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong2", "privateulong2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float2", "privatefloat2d", + NULL + }, + { + "private_const_vector2_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char2", "privateconstchar2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar2", "privateconstuchar2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short2", "privateconstshort2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort2", "privateconstushort2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int2", "privateconstint2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint2", "privateconstuint2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long2", "privateconstlong2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong2", "privateconstulong2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float2", "privateconstfloat2d", + NULL + }, + { + "constant_vector3_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char3*", "constantchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar3*", "constantuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short3*", "constantshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort3*", "constantushort3p", + NULL + }, + { + "constant_vector3_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int3*", "constantint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint3*", "constantuint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long3*", "constantlong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong3*", "constantulong3p", + NULL + }, + { + "constant_vector3_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float3*", "constantfloat3p", + NULL + }, + { + "constant_vector3_restrict_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "constantchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "constantuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "constantshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "constantushort3restrictp", + NULL + }, + { + "constant_vector3_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "constantint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "constantuint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "constantlong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "constantulong3restrictp", + NULL + }, + { + "constant_vector3_restrict_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "constantfloat3restrictp", + NULL + }, + { + "global_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char3*", "globalchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar3*", "globaluchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short3*", "globalshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort3*", "globalushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int3*", "globalint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint3*", "globaluint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long3*", "globallong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong3*", "globalulong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float3*", "globalfloat3p", + NULL + }, + { + "global_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "globalchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "globaluchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "globalshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "globalushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "globalint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "globaluint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "globallong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "globalulong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "globalfloat3restrictp", + NULL + }, + { + "global_const_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char3*", "globalconstchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar3*", "globalconstuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short3*", "globalconstshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort3*", "globalconstushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int3*", "globalconstint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint3*", "globalconstuint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long3*", "globalconstlong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong3*", "globalconstulong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float3*", "globalconstfloat3p", + NULL + }, + { + "global_const_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "globalconstchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "globalconstuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "globalconstshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "globalconstushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "globalconstint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "globalconstuint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "globalconstlong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "globalconstulong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "globalconstfloat3restrictp", + NULL + }, + { + "global_volatile_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char3*", "globalvolatilechar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar3*", "globalvolatileuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short3*", "globalvolatileshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort3*", "globalvolatileushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int3*", "globalvolatileint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint3*", "globalvolatileuint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long3*", "globalvolatilelong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong3*", "globalvolatileulong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float3*", "globalvolatilefloat3p", + NULL + }, + { + "global_volatile_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "globalvolatilechar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "globalvolatileuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "globalvolatileshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "globalvolatileushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "globalvolatileint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "globalvolatileuint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "globalvolatilelong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "globalvolatileulong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "globalvolatilefloat3restrictp", + NULL + }, + { + "global_const_volatile_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char3*", "globalconstvolatilechar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar3*", "globalconstvolatileuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short3*", "globalconstvolatileshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort3*", "globalconstvolatileushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int3*", "globalconstvolatileint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint3*", "globalconstvolatileuint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long3*", "globalconstvolatilelong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong3*", "globalconstvolatileulong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float3*", "globalconstvolatilefloat3p", + NULL + }, + { + "global_const_volatile_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "globalconstvolatilechar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "globalconstvolatileuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "globalconstvolatileshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "globalconstvolatileushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "globalconstvolatileint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "globalconstvolatileuint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "globalconstvolatilelong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "globalconstvolatileulong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "globalconstvolatilefloat3restrictp", + NULL + }, + { + "local_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char3*", "localchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar3*", "localuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short3*", "localshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort3*", "localushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int3*", "localint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint3*", "localuint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long3*", "locallong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong3*", "localulong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float3*", "localfloat3p", + NULL + }, + { + "local_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "localchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "localuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "localshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "localushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "localint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "localuint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "locallong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "localulong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "localfloat3restrictp", + NULL + }, + { + "local_const_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char3*", "localconstchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar3*", "localconstuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short3*", "localconstshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort3*", "localconstushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int3*", "localconstint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint3*", "localconstuint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long3*", "localconstlong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong3*", "localconstulong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float3*", "localconstfloat3p", + NULL + }, + { + "local_const_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "localconstchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "localconstuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "localconstshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "localconstushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "localconstint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "localconstuint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "localconstlong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "localconstulong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "localconstfloat3restrictp", + NULL + }, + { + "local_volatile_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char3*", "localvolatilechar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar3*", "localvolatileuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short3*", "localvolatileshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort3*", "localvolatileushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int3*", "localvolatileint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint3*", "localvolatileuint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long3*", "localvolatilelong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong3*", "localvolatileulong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float3*", "localvolatilefloat3p", + NULL + }, + { + "local_volatile_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "localvolatilechar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "localvolatileuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "localvolatileshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "localvolatileushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "localvolatileint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "localvolatileuint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "localvolatilelong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "localvolatileulong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "localvolatilefloat3restrictp", + NULL + }, + { + "local_const_volatile_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char3*", "localconstvolatilechar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar3*", "localconstvolatileuchar3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short3*", "localconstvolatileshort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort3*", "localconstvolatileushort3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int3*", "localconstvolatileint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint3*", "localconstvolatileuint3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long3*", "localconstvolatilelong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong3*", "localconstvolatileulong3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float3*", "localconstvolatilefloat3p", + NULL + }, + { + "local_const_volatile_vector3_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char3*", "localconstvolatilechar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar3*", "localconstvolatileuchar3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short3*", "localconstvolatileshort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort3*", "localconstvolatileushort3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int3*", "localconstvolatileint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint3*", "localconstvolatileuint3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long3*", "localconstvolatilelong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong3*", "localconstvolatileulong3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float3*", "localconstvolatilefloat3restrictp", + NULL + }, + { + "vector3_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char3", "char3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar3", "uchar3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short3", "short3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort3", "ushort3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int3", "int3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint3", "uint3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long3", "long3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong3", "ulong3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float3", "float3d", + NULL + }, + { + "const_vector3_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char3", "constchar3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar3", "constuchar3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short3", "constshort3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort3", "constushort3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int3", "constint3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint3", "constuint3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long3", "constlong3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong3", "constulong3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float3", "constfloat3d", + NULL + }, + { + "private_vector3_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char3", "privatechar3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar3", "privateuchar3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short3", "privateshort3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort3", "privateushort3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int3", "privateint3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint3", "privateuint3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long3", "privatelong3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong3", "privateulong3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float3", "privatefloat3d", + NULL + }, + { + "private_const_vector3_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char3", "privateconstchar3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar3", "privateconstuchar3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short3", "privateconstshort3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort3", "privateconstushort3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int3", "privateconstint3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint3", "privateconstuint3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long3", "privateconstlong3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong3", "privateconstulong3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float3", "privateconstfloat3d", + NULL + }, + { + "constant_vector4_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char4*", "constantchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar4*", "constantuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short4*", "constantshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort4*", "constantushort4p", + NULL + }, + { + "constant_vector4_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int4*", "constantint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint4*", "constantuint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long4*", "constantlong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong4*", "constantulong4p", + NULL + }, + { + "constant_vector4_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float4*", "constantfloat4p", + NULL + }, + { + "constant_vector4_restrict_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "constantchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "constantuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "constantshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "constantushort4restrictp", + NULL + }, + { + "constant_vector4_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "constantint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "constantuint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "constantlong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "constantulong4restrictp", + NULL + }, + { + "constant_vector4_restrict_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "constantfloat4restrictp", + NULL + }, + { + "global_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char4*", "globalchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar4*", "globaluchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short4*", "globalshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort4*", "globalushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int4*", "globalint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint4*", "globaluint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long4*", "globallong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong4*", "globalulong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float4*", "globalfloat4p", + NULL + }, + { + "global_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "globalchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "globaluchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "globalshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "globalushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "globalint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "globaluint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "globallong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "globalulong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "globalfloat4restrictp", + NULL + }, + { + "global_const_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char4*", "globalconstchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar4*", "globalconstuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short4*", "globalconstshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort4*", "globalconstushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int4*", "globalconstint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint4*", "globalconstuint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long4*", "globalconstlong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong4*", "globalconstulong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float4*", "globalconstfloat4p", + NULL + }, + { + "global_const_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "globalconstchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "globalconstuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "globalconstshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "globalconstushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "globalconstint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "globalconstuint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "globalconstlong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "globalconstulong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "globalconstfloat4restrictp", + NULL + }, + { + "global_volatile_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char4*", "globalvolatilechar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar4*", "globalvolatileuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short4*", "globalvolatileshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort4*", "globalvolatileushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int4*", "globalvolatileint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint4*", "globalvolatileuint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long4*", "globalvolatilelong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong4*", "globalvolatileulong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float4*", "globalvolatilefloat4p", + NULL + }, + { + "global_volatile_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "globalvolatilechar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "globalvolatileuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "globalvolatileshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "globalvolatileushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "globalvolatileint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "globalvolatileuint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "globalvolatilelong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "globalvolatileulong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "globalvolatilefloat4restrictp", + NULL + }, + { + "global_const_volatile_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char4*", "globalconstvolatilechar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar4*", "globalconstvolatileuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short4*", "globalconstvolatileshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort4*", "globalconstvolatileushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int4*", "globalconstvolatileint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint4*", "globalconstvolatileuint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long4*", "globalconstvolatilelong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong4*", "globalconstvolatileulong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float4*", "globalconstvolatilefloat4p", + NULL + }, + { + "global_const_volatile_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "globalconstvolatilechar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "globalconstvolatileuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "globalconstvolatileshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "globalconstvolatileushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "globalconstvolatileint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "globalconstvolatileuint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "globalconstvolatilelong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "globalconstvolatileulong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "globalconstvolatilefloat4restrictp", + NULL + }, + { + "local_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char4*", "localchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar4*", "localuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short4*", "localshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort4*", "localushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int4*", "localint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint4*", "localuint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long4*", "locallong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong4*", "localulong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float4*", "localfloat4p", + NULL + }, + { + "local_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "localchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "localuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "localshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "localushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "localint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "localuint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "locallong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "localulong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "localfloat4restrictp", + NULL + }, + { + "local_const_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char4*", "localconstchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar4*", "localconstuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short4*", "localconstshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort4*", "localconstushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int4*", "localconstint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint4*", "localconstuint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long4*", "localconstlong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong4*", "localconstulong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float4*", "localconstfloat4p", + NULL + }, + { + "local_const_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "localconstchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "localconstuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "localconstshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "localconstushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "localconstint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "localconstuint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "localconstlong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "localconstulong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "localconstfloat4restrictp", + NULL + }, + { + "local_volatile_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char4*", "localvolatilechar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar4*", "localvolatileuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short4*", "localvolatileshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort4*", "localvolatileushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int4*", "localvolatileint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint4*", "localvolatileuint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long4*", "localvolatilelong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong4*", "localvolatileulong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float4*", "localvolatilefloat4p", + NULL + }, + { + "local_volatile_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "localvolatilechar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "localvolatileuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "localvolatileshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "localvolatileushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "localvolatileint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "localvolatileuint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "localvolatilelong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "localvolatileulong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "localvolatilefloat4restrictp", + NULL + }, + { + "local_const_volatile_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char4*", "localconstvolatilechar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar4*", "localconstvolatileuchar4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short4*", "localconstvolatileshort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort4*", "localconstvolatileushort4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int4*", "localconstvolatileint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint4*", "localconstvolatileuint4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long4*", "localconstvolatilelong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong4*", "localconstvolatileulong4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float4*", "localconstvolatilefloat4p", + NULL + }, + { + "local_const_volatile_vector4_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char4*", "localconstvolatilechar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar4*", "localconstvolatileuchar4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short4*", "localconstvolatileshort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort4*", "localconstvolatileushort4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int4*", "localconstvolatileint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint4*", "localconstvolatileuint4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long4*", "localconstvolatilelong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong4*", "localconstvolatileulong4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float4*", "localconstvolatilefloat4restrictp", + NULL + }, + { + "vector4_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char4", "char4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar4", "uchar4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short4", "short4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort4", "ushort4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int4", "int4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint4", "uint4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long4", "long4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong4", "ulong4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float4", "float4d", + NULL + }, + { + "const_vector4_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char4", "constchar4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar4", "constuchar4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short4", "constshort4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort4", "constushort4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int4", "constint4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint4", "constuint4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long4", "constlong4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong4", "constulong4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float4", "constfloat4d", + NULL + }, + { + "private_vector4_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char4", "privatechar4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar4", "privateuchar4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short4", "privateshort4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort4", "privateushort4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int4", "privateint4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint4", "privateuint4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long4", "privatelong4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong4", "privateulong4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float4", "privatefloat4d", + NULL + }, + { + "private_const_vector4_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char4", "privateconstchar4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar4", "privateconstuchar4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short4", "privateconstshort4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort4", "privateconstushort4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int4", "privateconstint4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint4", "privateconstuint4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long4", "privateconstlong4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong4", "privateconstulong4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float4", "privateconstfloat4d", + NULL + }, + { + "constant_vector8_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char8*", "constantchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar8*", "constantuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short8*", "constantshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort8*", "constantushort8p", + NULL + }, + { + "constant_vector8_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int8*", "constantint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint8*", "constantuint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long8*", "constantlong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong8*", "constantulong8p", + NULL + }, + { + "constant_vector8_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float8*", "constantfloat8p", + NULL + }, + { + "constant_vector8_restrict_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "constantchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "constantuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "constantshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "constantushort8restrictp", + NULL + }, + { + "constant_vector8_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "constantint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "constantuint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "constantlong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "constantulong8restrictp", + NULL + }, + { + "constant_vector8_restrict_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "constantfloat8restrictp", + NULL + }, + { + "global_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char8*", "globalchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar8*", "globaluchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short8*", "globalshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort8*", "globalushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int8*", "globalint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint8*", "globaluint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long8*", "globallong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong8*", "globalulong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float8*", "globalfloat8p", + NULL + }, + { + "global_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "globalchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "globaluchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "globalshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "globalushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "globalint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "globaluint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "globallong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "globalulong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "globalfloat8restrictp", + NULL + }, + { + "global_const_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char8*", "globalconstchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar8*", "globalconstuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short8*", "globalconstshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort8*", "globalconstushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int8*", "globalconstint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint8*", "globalconstuint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long8*", "globalconstlong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong8*", "globalconstulong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float8*", "globalconstfloat8p", + NULL + }, + { + "global_const_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "globalconstchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "globalconstuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "globalconstshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "globalconstushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "globalconstint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "globalconstuint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "globalconstlong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "globalconstulong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "globalconstfloat8restrictp", + NULL + }, + { + "global_volatile_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char8*", "globalvolatilechar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar8*", "globalvolatileuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short8*", "globalvolatileshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort8*", "globalvolatileushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int8*", "globalvolatileint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint8*", "globalvolatileuint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long8*", "globalvolatilelong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong8*", "globalvolatileulong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float8*", "globalvolatilefloat8p", + NULL + }, + { + "global_volatile_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "globalvolatilechar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "globalvolatileuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "globalvolatileshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "globalvolatileushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "globalvolatileint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "globalvolatileuint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "globalvolatilelong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "globalvolatileulong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "globalvolatilefloat8restrictp", + NULL + }, + { + "global_const_volatile_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char8*", "globalconstvolatilechar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar8*", "globalconstvolatileuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short8*", "globalconstvolatileshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort8*", "globalconstvolatileushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int8*", "globalconstvolatileint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint8*", "globalconstvolatileuint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long8*", "globalconstvolatilelong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong8*", "globalconstvolatileulong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float8*", "globalconstvolatilefloat8p", + NULL + }, + { + "global_const_volatile_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "globalconstvolatilechar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "globalconstvolatileuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "globalconstvolatileshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "globalconstvolatileushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "globalconstvolatileint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "globalconstvolatileuint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "globalconstvolatilelong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "globalconstvolatileulong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "globalconstvolatilefloat8restrictp", + NULL + }, + { + "local_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char8*", "localchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar8*", "localuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short8*", "localshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort8*", "localushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int8*", "localint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint8*", "localuint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long8*", "locallong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong8*", "localulong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float8*", "localfloat8p", + NULL + }, + { + "local_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "localchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "localuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "localshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "localushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "localint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "localuint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "locallong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "localulong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "localfloat8restrictp", + NULL + }, + { + "local_const_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char8*", "localconstchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar8*", "localconstuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short8*", "localconstshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort8*", "localconstushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int8*", "localconstint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint8*", "localconstuint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long8*", "localconstlong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong8*", "localconstulong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float8*", "localconstfloat8p", + NULL + }, + { + "local_const_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "localconstchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "localconstuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "localconstshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "localconstushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "localconstint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "localconstuint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "localconstlong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "localconstulong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "localconstfloat8restrictp", + NULL + }, + { + "local_volatile_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char8*", "localvolatilechar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar8*", "localvolatileuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short8*", "localvolatileshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort8*", "localvolatileushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int8*", "localvolatileint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint8*", "localvolatileuint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long8*", "localvolatilelong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong8*", "localvolatileulong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float8*", "localvolatilefloat8p", + NULL + }, + { + "local_volatile_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "localvolatilechar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "localvolatileuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "localvolatileshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "localvolatileushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "localvolatileint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "localvolatileuint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "localvolatilelong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "localvolatileulong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "localvolatilefloat8restrictp", + NULL + }, + { + "local_const_volatile_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char8*", "localconstvolatilechar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar8*", "localconstvolatileuchar8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short8*", "localconstvolatileshort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort8*", "localconstvolatileushort8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int8*", "localconstvolatileint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint8*", "localconstvolatileuint8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long8*", "localconstvolatilelong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong8*", "localconstvolatileulong8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float8*", "localconstvolatilefloat8p", + NULL + }, + { + "local_const_volatile_vector8_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char8*", "localconstvolatilechar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar8*", "localconstvolatileuchar8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short8*", "localconstvolatileshort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort8*", "localconstvolatileushort8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int8*", "localconstvolatileint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint8*", "localconstvolatileuint8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long8*", "localconstvolatilelong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong8*", "localconstvolatileulong8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float8*", "localconstvolatilefloat8restrictp", + NULL + }, + { + "vector8_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char8", "char8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar8", "uchar8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short8", "short8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort8", "ushort8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int8", "int8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint8", "uint8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long8", "long8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong8", "ulong8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float8", "float8d", + NULL + }, + { + "const_vector8_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char8", "constchar8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar8", "constuchar8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short8", "constshort8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort8", "constushort8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int8", "constint8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint8", "constuint8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long8", "constlong8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong8", "constulong8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float8", "constfloat8d", + NULL + }, + { + "private_vector8_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char8", "privatechar8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar8", "privateuchar8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short8", "privateshort8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort8", "privateushort8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int8", "privateint8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint8", "privateuint8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long8", "privatelong8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong8", "privateulong8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float8", "privatefloat8d", + NULL + }, + { + "private_const_vector8_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char8", "privateconstchar8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar8", "privateconstuchar8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short8", "privateconstshort8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort8", "privateconstushort8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int8", "privateconstint8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint8", "privateconstuint8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long8", "privateconstlong8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong8", "privateconstulong8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float8", "privateconstfloat8d", + NULL + }, + { + "constant_vector16_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char16*", "constantchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar16*", "constantuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short16*", "constantshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort16*", "constantushort16p", + NULL + }, + { + "constant_vector16_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int16*", "constantint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint16*", "constantuint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long16*", "constantlong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong16*", "constantulong16p", + NULL + }, + { + "constant_vector16_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float16*", "constantfloat16p", + NULL + }, + { + "constant_vector16_restrict_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "constantchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "constantuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "constantshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "constantushort16restrictp", + NULL + }, + { + "constant_vector16_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "constantint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "constantuint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "constantlong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "constantulong16restrictp", + NULL + }, + { + "constant_vector16_restrict_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "constantfloat16restrictp", + NULL + }, + { + "global_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char16*", "globalchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar16*", "globaluchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short16*", "globalshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort16*", "globalushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int16*", "globalint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint16*", "globaluint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long16*", "globallong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong16*", "globalulong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float16*", "globalfloat16p", + NULL + }, + { + "global_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "globalchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "globaluchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "globalshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "globalushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "globalint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "globaluint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "globallong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "globalulong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "globalfloat16restrictp", + NULL + }, + { + "global_const_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char16*", "globalconstchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar16*", "globalconstuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short16*", "globalconstshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort16*", "globalconstushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int16*", "globalconstint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint16*", "globalconstuint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long16*", "globalconstlong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong16*", "globalconstulong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float16*", "globalconstfloat16p", + NULL + }, + { + "global_const_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "globalconstchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "globalconstuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "globalconstshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "globalconstushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "globalconstint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "globalconstuint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "globalconstlong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "globalconstulong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "globalconstfloat16restrictp", + NULL + }, + { + "global_volatile_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char16*", "globalvolatilechar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar16*", "globalvolatileuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short16*", "globalvolatileshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort16*", "globalvolatileushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int16*", "globalvolatileint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint16*", "globalvolatileuint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long16*", "globalvolatilelong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong16*", "globalvolatileulong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float16*", "globalvolatilefloat16p", + NULL + }, + { + "global_volatile_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "globalvolatilechar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "globalvolatileuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "globalvolatileshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "globalvolatileushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "globalvolatileint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "globalvolatileuint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "globalvolatilelong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "globalvolatileulong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "globalvolatilefloat16restrictp", + NULL + }, + { + "global_const_volatile_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char16*", "globalconstvolatilechar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar16*", "globalconstvolatileuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short16*", "globalconstvolatileshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort16*", "globalconstvolatileushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int16*", "globalconstvolatileint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint16*", "globalconstvolatileuint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long16*", "globalconstvolatilelong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong16*", "globalconstvolatileulong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float16*", "globalconstvolatilefloat16p", + NULL + }, + { + "global_const_volatile_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "globalconstvolatilechar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "globalconstvolatileuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "globalconstvolatileshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "globalconstvolatileushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "globalconstvolatileint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "globalconstvolatileuint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "globalconstvolatilelong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "globalconstvolatileulong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "globalconstvolatilefloat16restrictp", + NULL + }, + { + "local_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char16*", "localchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar16*", "localuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short16*", "localshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort16*", "localushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int16*", "localint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint16*", "localuint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long16*", "locallong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong16*", "localulong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float16*", "localfloat16p", + NULL + }, + { + "local_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "localchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "localuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "localshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "localushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "localint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "localuint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "locallong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "localulong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "localfloat16restrictp", + NULL + }, + { + "local_const_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "char16*", "localconstchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uchar16*", "localconstuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "short16*", "localconstshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ushort16*", "localconstushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "int16*", "localconstint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "uint16*", "localconstuint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "long16*", "localconstlong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "ulong16*", "localconstulong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "float16*", "localconstfloat16p", + NULL + }, + { + "local_const_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "localconstchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "localconstuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "localconstshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "localconstushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "localconstint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "localconstuint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "localconstlong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "localconstulong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "localconstfloat16restrictp", + NULL + }, + { + "local_volatile_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "char16*", "localvolatilechar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uchar16*", "localvolatileuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "short16*", "localvolatileshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ushort16*", "localvolatileushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "int16*", "localvolatileint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "uint16*", "localvolatileuint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "long16*", "localvolatilelong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "ulong16*", "localvolatileulong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "float16*", "localvolatilefloat16p", + NULL + }, + { + "local_volatile_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "localvolatilechar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "localvolatileuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "localvolatileshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "localvolatileushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "localvolatileint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "localvolatileuint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "localvolatilelong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "localvolatileulong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "localvolatilefloat16restrictp", + NULL + }, + { + "local_const_volatile_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "char16*", "localconstvolatilechar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uchar16*", "localconstvolatileuchar16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "short16*", "localconstvolatileshort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ushort16*", "localconstvolatileushort16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "int16*", "localconstvolatileint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "uint16*", "localconstvolatileuint16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "long16*", "localconstvolatilelong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "ulong16*", "localconstvolatileulong16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "float16*", "localconstvolatilefloat16p", + NULL + }, + { + "local_const_volatile_vector16_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "char16*", "localconstvolatilechar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uchar16*", "localconstvolatileuchar16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "short16*", "localconstvolatileshort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ushort16*", "localconstvolatileushort16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "int16*", "localconstvolatileint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "uint16*", "localconstvolatileuint16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "long16*", "localconstvolatilelong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "ulong16*", "localconstvolatileulong16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "float16*", "localconstvolatilefloat16restrictp", + NULL + }, + { + "vector16_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char16", "char16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar16", "uchar16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short16", "short16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort16", "ushort16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int16", "int16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint16", "uint16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long16", "long16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong16", "ulong16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float16", "float16d", + NULL + }, + { + "const_vector16_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char16", "constchar16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar16", "constuchar16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short16", "constshort16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort16", "constushort16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int16", "constint16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint16", "constuint16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long16", "constlong16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong16", "constulong16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float16", "constfloat16d", + NULL + }, + { + "private_vector16_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char16", "privatechar16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar16", "privateuchar16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short16", "privateshort16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort16", "privateushort16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int16", "privateint16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint16", "privateuint16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long16", "privatelong16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong16", "privateulong16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float16", "privatefloat16d", + NULL + }, + { + "private_const_vector16_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "char16", "privateconstchar16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uchar16", "privateconstuchar16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "short16", "privateconstshort16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ushort16", "privateconstushort16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "int16", "privateconstint16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "uint16", "privateconstuint16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "long16", "privateconstlong16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "ulong16", "privateconstulong16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "float16", "privateconstfloat16d", + NULL + }, + { + "constant_derived_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_type*", "constanttypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "struct struct_type*", "constantstructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_struct_type*", "constanttypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "union union_type*", "constantunionunion_typep", + NULL + }, + { + "constant_derived_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_union_type*", "constanttypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "enum enum_type*", "constantenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_enum_type*", "constanttypedef_enum_typep", + NULL + }, + { + "constant_derived_restrict_p0", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "constanttypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "constantstructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "constanttypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "constantunionunion_typerestrictp", + NULL + }, + { + "constant_derived_restrict_p1", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "constanttypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "constantenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "constanttypedef_enum_typerestrictp", + NULL + }, + { + "global_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_type*", "globaltypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "struct struct_type*", "globalstructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_struct_type*", "globaltypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "union union_type*", "globalunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_union_type*", "globaltypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "enum enum_type*", "globalenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_enum_type*", "globaltypedef_enum_typep", + NULL + }, + { + "global_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "globaltypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "globalstructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "globaltypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "globalunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "globaltypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "globalenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "globaltypedef_enum_typerestrictp", + NULL + }, + { + "global_const_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_type*", "globalconsttypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "struct struct_type*", "globalconststructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_struct_type*", "globalconsttypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "union union_type*", "globalconstunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_union_type*", "globalconsttypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "enum enum_type*", "globalconstenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_enum_type*", "globalconsttypedef_enum_typep", + NULL + }, + { + "global_const_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "globalconsttypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "globalconststructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "globalconsttypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "globalconstunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "globalconsttypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "globalconstenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "globalconsttypedef_enum_typerestrictp", + NULL + }, + { + "global_volatile_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_type*", "globalvolatiletypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "struct struct_type*", "globalvolatilestructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_struct_type*", "globalvolatiletypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "union union_type*", "globalvolatileunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_union_type*", "globalvolatiletypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "enum enum_type*", "globalvolatileenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_enum_type*", "globalvolatiletypedef_enum_typep", + NULL + }, + { + "global_volatile_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "globalvolatiletypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "globalvolatilestructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "globalvolatiletypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "globalvolatileunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "globalvolatiletypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "globalvolatileenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "globalvolatiletypedef_enum_typerestrictp", + NULL + }, + { + "global_const_volatile_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_type*", "globalconstvolatiletypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "struct struct_type*", "globalconstvolatilestructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_struct_type*", "globalconstvolatiletypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "union union_type*", "globalconstvolatileunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_union_type*", "globalconstvolatiletypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "enum enum_type*", "globalconstvolatileenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_enum_type*", "globalconstvolatiletypedef_enum_typep", + NULL + }, + { + "global_const_volatile_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "globalconstvolatiletypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "globalconstvolatilestructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "globalconstvolatiletypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "globalconstvolatileunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "globalconstvolatiletypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "globalconstvolatileenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "globalconstvolatiletypedef_enum_typerestrictp", + NULL + }, + { + "local_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_type*", "localtypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "struct struct_type*", "localstructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_struct_type*", "localtypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "union union_type*", "localunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_union_type*", "localtypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "enum enum_type*", "localenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_enum_type*", "localtypedef_enum_typep", + NULL + }, + { + "local_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "localtypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "localstructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "localtypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "localunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "localtypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "localenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "localtypedef_enum_typerestrictp", + NULL + }, + { + "local_const_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_type*", "localconsttypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "struct struct_type*", "localconststructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_struct_type*", "localconsttypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "union union_type*", "localconstunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_union_type*", "localconsttypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "enum enum_type*", "localconstenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "typedef_enum_type*", "localconsttypedef_enum_typep", + NULL + }, + { + "local_const_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "localconsttypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "localconststructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "localconsttypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "localconstunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "localconsttypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "localconstenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "localconsttypedef_enum_typerestrictp", + NULL + }, + { + "local_volatile_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_type*", "localvolatiletypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "struct struct_type*", "localvolatilestructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_struct_type*", "localvolatiletypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "union union_type*", "localvolatileunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_union_type*", "localvolatiletypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "enum enum_type*", "localvolatileenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_enum_type*", "localvolatiletypedef_enum_typep", + NULL + }, + { + "local_volatile_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "localvolatiletypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "localvolatilestructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "localvolatiletypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "localvolatileunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "localvolatiletypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "localvolatileenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "localvolatiletypedef_enum_typerestrictp", + NULL + }, + { + "local_const_volatile_derived_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_type*", "localconstvolatiletypedef_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "struct struct_type*", "localconstvolatilestructstruct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_struct_type*", "localconstvolatiletypedef_struct_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "union union_type*", "localconstvolatileunionunion_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_union_type*", "localconstvolatiletypedef_union_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "enum enum_type*", "localconstvolatileenumenum_typep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "typedef_enum_type*", "localconstvolatiletypedef_enum_typep", + NULL + }, + { + "local_const_volatile_derived_restrict_p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_type*", "localconstvolatiletypedef_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "struct struct_type*", "localconstvolatilestructstruct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_struct_type*", "localconstvolatiletypedef_struct_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "union union_type*", "localconstvolatileunionunion_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_union_type*", "localconstvolatiletypedef_union_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "enum enum_type*", "localconstvolatileenumenum_typerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "typedef_enum_type*", "localconstvolatiletypedef_enum_typerestrictp", + NULL + }, + { + "derived_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_type", "typedef_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "struct struct_type", "structstruct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_struct_type", "typedef_struct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "union union_type", "unionunion_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_union_type", "typedef_union_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "enum enum_type", "enumenum_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_enum_type", "typedef_enum_typed", + NULL + }, + { + "const_derived_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_type", "consttypedef_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "struct struct_type", "conststructstruct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_struct_type", "consttypedef_struct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "union union_type", "constunionunion_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_union_type", "consttypedef_union_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "enum enum_type", "constenumenum_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_enum_type", "consttypedef_enum_typed", + NULL + }, + { + "private_derived_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_type", "privatetypedef_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "struct struct_type", "privatestructstruct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_struct_type", "privatetypedef_struct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "union union_type", "privateunionunion_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_union_type", "privatetypedef_union_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "enum enum_type", "privateenumenum_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_enum_type", "privatetypedef_enum_typed", + NULL + }, + { + "private_const_derived_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_type", "privateconsttypedef_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "struct struct_type", "privateconststructstruct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_struct_type", "privateconsttypedef_struct_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "union union_type", "privateconstunionunion_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_union_type", "privateconsttypedef_union_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "enum enum_type", "privateconstenumenum_typed", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "typedef_enum_type", "privateconsttypedef_enum_typed", + NULL + }, +}; + +// Support for optional image data type +const char * image_kernel_args[] = { + "#pragma OPENCL EXTENSION cl_khr_3d_image_writes: enable\n" + "kernel void image_d(read_only image2d_t image2d_td0,\n" + " write_only image2d_t image2d_td1,\n" + " read_only image3d_t image3d_td2,\n" + " write_only image3d_t image3d_td3,\n" + " read_only image2d_array_t image2d_array_td4,\n" + " write_only image2d_array_t image2d_array_td5,\n" + " read_only image1d_t image1d_td6,\n" + " write_only image1d_t image1d_td7,\n" + " read_only image1d_buffer_t image1d_buffer_td8,\n" + " write_only image1d_buffer_t image1d_buffer_td9,\n" + " read_only image1d_array_t image1d_array_td10,\n" + " write_only image1d_array_t image1d_array_td11,\n" + " sampler_t sampler_td12)\n" + "{}\n", + "\n" +}; + +const char * image_arg_info[][67] = { + { + "image_d", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_READ_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image2d_t", "image2d_td0", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_WRITE_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image2d_t", "image2d_td1", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_READ_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image3d_t", "image3d_td2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_WRITE_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image3d_t", "image3d_td3", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_READ_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image2d_array_t", "image2d_array_td4", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_WRITE_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image2d_array_t", "image2d_array_td5", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_READ_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image1d_t", "image1d_td6", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_WRITE_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image1d_t", "image1d_td7", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_READ_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image1d_buffer_t", "image1d_buffer_td8", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_WRITE_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image1d_buffer_t", "image1d_buffer_td9", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_READ_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image1d_array_t", "image1d_array_td10", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_WRITE_ONLY, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "image1d_array_t", "image1d_array_td11", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "sampler_t", "sampler_td12", + NULL + }, +}; + +// Support for optional double data type +const char * double_kernel_args[] = { + "kernel void double_scalar_p(constant double*constantdoublep,\n" + " constant double *restrict constantdoublerestrictp,\n" + " global double*globaldoublep,\n" + " global double *restrict globaldoublerestrictp,\n" + " global const double* globalconstdoublep,\n" + " global const double * restrict globalconstdoublerestrictp,\n" + " global volatile double*globalvolatiledoublep,\n" + " global volatile double *restrict globalvolatiledoublerestrictp,\n" + " global const volatile double* globalconstvolatiledoublep)\n" + "{}\n", + "\n" + "kernel void double_scalar_p2(global const volatile double * restrict globalconstvolatiledoublerestrictp,\n" + " local double*localdoublep,\n" + " local double *restrict localdoublerestrictp,\n" + " local const double* localconstdoublep,\n" + " local const double * restrict localconstdoublerestrictp,\n" + " local volatile double*localvolatiledoublep,\n" + " local volatile double *restrict localvolatiledoublerestrictp,\n" + " local const volatile double* localconstvolatiledoublep,\n" + " local const volatile double * restrict localconstvolatiledoublerestrictp)\n" + "{}\n", + "\n" + "kernel void double_scalar_d(double doubled,\n" + " const double constdoubled,\n" + " private double privatedoubled,\n" + " private const double privateconstdoubled)\n" + "{}\n", + "\n" + "kernel void double_vector2_p(constant double2*constantdouble2p,\n" + " constant double2 *restrict constantdouble2restrictp,\n" + " global double2*globaldouble2p,\n" + " global double2 *restrict globaldouble2restrictp,\n" + " global const double2* globalconstdouble2p,\n" + " global const double2 * restrict globalconstdouble2restrictp,\n" + " global volatile double2*globalvolatiledouble2p,\n" + " global volatile double2 *restrict globalvolatiledouble2restrictp,\n" + " global const volatile double2* globalconstvolatiledouble2p)\n" + "{}\n", + "\n" + "kernel void double_vector2_p2(global const volatile double2 * restrict globalconstvolatiledouble2restrictp,\n" + " local double2*localdouble2p,\n" + " local double2 *restrict localdouble2restrictp,\n" + " local const double2* localconstdouble2p,\n" + " local const double2 * restrict localconstdouble2restrictp,\n" + " local volatile double2*localvolatiledouble2p,\n" + " local volatile double2 *restrict localvolatiledouble2restrictp,\n" + " local const volatile double2* localconstvolatiledouble2p,\n" + " local const volatile double2 * restrict localconstvolatiledouble2restrictp)\n" + "{}\n", + "\n" + "kernel void double_vector2_d(double2 double2d,\n" + " const double2 constdouble2d,\n" + " private double2 privatedouble2d,\n" + " private const double2 privateconstdouble2d)\n" + "{}\n", + "\n" + "kernel void double_vector3_p(constant double3*constantdouble3p,\n" + " constant double3 *restrict constantdouble3restrictp,\n" + " global double3*globaldouble3p,\n" + " global double3 *restrict globaldouble3restrictp,\n" + " global const double3* globalconstdouble3p,\n" + " global const double3 * restrict globalconstdouble3restrictp,\n" + " global volatile double3*globalvolatiledouble3p,\n" + " global volatile double3 *restrict globalvolatiledouble3restrictp,\n" + " global const volatile double3* globalconstvolatiledouble3p)\n" + "{}\n", + "\n" + "kernel void double_vector3_p2(global const volatile double3 * restrict globalconstvolatiledouble3restrictp,\n" + " local double3*localdouble3p,\n" + " local double3 *restrict localdouble3restrictp,\n" + " local const double3* localconstdouble3p,\n" + " local const double3 * restrict localconstdouble3restrictp,\n" + " local volatile double3*localvolatiledouble3p,\n" + " local volatile double3 *restrict localvolatiledouble3restrictp,\n" + " local const volatile double3* localconstvolatiledouble3p,\n" + " local const volatile double3 * restrict localconstvolatiledouble3restrictp)\n" + "{}\n", + "\n" + "kernel void double_vector3_d(double3 double3d,\n" + " const double3 constdouble3d,\n" + " private double3 privatedouble3d,\n" + " private const double3 privateconstdouble3d)\n" + "{}\n", + "\n" + "kernel void double_vector4_p(constant double4*constantdouble4p,\n" + " constant double4 *restrict constantdouble4restrictp,\n" + " global double4*globaldouble4p,\n" + " global double4 *restrict globaldouble4restrictp,\n" + " global const double4* globalconstdouble4p,\n" + " global const double4 * restrict globalconstdouble4restrictp,\n" + " global volatile double4*globalvolatiledouble4p,\n" + " global volatile double4 *restrict globalvolatiledouble4restrictp,\n" + " global const volatile double4* globalconstvolatiledouble4p)\n" + "{}\n", + "\n" + "kernel void double_vector4_p2(global const volatile double4 * restrict globalconstvolatiledouble4restrictp,\n" + " local double4*localdouble4p,\n" + " local double4 *restrict localdouble4restrictp,\n" + " local const double4* localconstdouble4p,\n" + " local const double4 * restrict localconstdouble4restrictp,\n" + " local volatile double4*localvolatiledouble4p,\n" + " local volatile double4 *restrict localvolatiledouble4restrictp,\n" + " local const volatile double4* localconstvolatiledouble4p,\n" + " local const volatile double4 * restrict localconstvolatiledouble4restrictp)\n" + "{}\n", + "\n" + "kernel void double_vector4_d(double4 double4d,\n" + " const double4 constdouble4d,\n" + " private double4 privatedouble4d,\n" + " private const double4 privateconstdouble4d)\n" + "{}\n", + "\n" + "kernel void double_vector8_p(constant double8*constantdouble8p,\n" + " constant double8 *restrict constantdouble8restrictp,\n" + " global double8*globaldouble8p,\n" + " global double8 *restrict globaldouble8restrictp,\n" + " global const double8* globalconstdouble8p,\n" + " global const double8 * restrict globalconstdouble8restrictp,\n" + " global volatile double8*globalvolatiledouble8p,\n" + " global volatile double8 *restrict globalvolatiledouble8restrictp,\n" + " global const volatile double8* globalconstvolatiledouble8p)\n" + "{}\n", + "\n" + "kernel void double_vector8_p2(global const volatile double8 * restrict globalconstvolatiledouble8restrictp,\n" + " local double8*localdouble8p,\n" + " local double8 *restrict localdouble8restrictp,\n" + " local const double8* localconstdouble8p,\n" + " local const double8 * restrict localconstdouble8restrictp,\n" + " local volatile double8*localvolatiledouble8p,\n" + " local volatile double8 *restrict localvolatiledouble8restrictp,\n" + " local const volatile double8* localconstvolatiledouble8p,\n" + " local const volatile double8 * restrict localconstvolatiledouble8restrictp)\n" + "{}\n", + "\n" + "kernel void double_vector8_d(double8 double8d,\n" + " const double8 constdouble8d,\n" + " private double8 privatedouble8d,\n" + " private const double8 privateconstdouble8d)\n" + "{}\n", + "\n" + "kernel void double_vector16_p(constant double16*constantdouble16p,\n" + " constant double16 *restrict constantdouble16restrictp,\n" + " global double16*globaldouble16p,\n" + " global double16 *restrict globaldouble16restrictp,\n" + " global const double16* globalconstdouble16p,\n" + " global const double16 * restrict globalconstdouble16restrictp,\n" + " global volatile double16*globalvolatiledouble16p,\n" + " global volatile double16 *restrict globalvolatiledouble16restrictp,\n" + " global const volatile double16* globalconstvolatiledouble16p)\n" + "{}\n", + "\n" + "kernel void double_vector16_p2(global const volatile double16 * restrict globalconstvolatiledouble16restrictp,\n" + " local double16*localdouble16p,\n" + " local double16 *restrict localdouble16restrictp,\n" + " local const double16* localconstdouble16p,\n" + " local const double16 * restrict localconstdouble16restrictp,\n" + " local volatile double16*localvolatiledouble16p,\n" + " local volatile double16 *restrict localvolatiledouble16restrictp,\n" + " local const volatile double16* localconstvolatiledouble16p,\n" + " local const volatile double16 * restrict localconstvolatiledouble16restrictp)\n" + "{}\n", + "\n" + "kernel void double_vector16_d(double16 double16d,\n" + " const double16 constdouble16d,\n" + " private double16 privatedouble16d,\n" + " private const double16 privateconstdouble16d)\n" + "{}\n", + "\n" +}; + +const char * double_arg_info[][77] = { + { + "double_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double*", "constantdoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "constantdoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double*", "globaldoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "globaldoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double*", "globalconstdoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "globalconstdoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double*", "globalvolatiledoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "globalvolatiledoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double*", "globalconstvolatiledoublep", + NULL + }, + { + "double_scalar_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "globalconstvolatiledoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double*", "localdoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "localdoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double*", "localconstdoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "localconstdoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double*", "localvolatiledoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "localvolatiledoublerestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double*", "localconstvolatiledoublep", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double*", "localconstvolatiledoublerestrictp", + NULL + }, + { + "double_scalar_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double", "doubled", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double", "constdoubled", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double", "privatedoubled", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double", "privateconstdoubled", + NULL + }, + { + "double_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double2*", "constantdouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "constantdouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double2*", "globaldouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "globaldouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double2*", "globalconstdouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "globalconstdouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double2*", "globalvolatiledouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "globalvolatiledouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double2*", "globalconstvolatiledouble2p", + NULL + }, + { + "double_vector2_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "globalconstvolatiledouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double2*", "localdouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "localdouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double2*", "localconstdouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "localconstdouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double2*", "localvolatiledouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "localvolatiledouble2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double2*", "localconstvolatiledouble2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double2*", "localconstvolatiledouble2restrictp", + NULL + }, + { + "double_vector2_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double2", "double2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double2", "constdouble2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double2", "privatedouble2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double2", "privateconstdouble2d", + NULL + }, + { + "double_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double3*", "constantdouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "constantdouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double3*", "globaldouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "globaldouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double3*", "globalconstdouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "globalconstdouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double3*", "globalvolatiledouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "globalvolatiledouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double3*", "globalconstvolatiledouble3p", + NULL + }, + { + "double_vector3_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "globalconstvolatiledouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double3*", "localdouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "localdouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double3*", "localconstdouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "localconstdouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double3*", "localvolatiledouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "localvolatiledouble3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double3*", "localconstvolatiledouble3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double3*", "localconstvolatiledouble3restrictp", + NULL + }, + { + "double_vector3_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double3", "double3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double3", "constdouble3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double3", "privatedouble3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double3", "privateconstdouble3d", + NULL + }, + { + "double_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double4*", "constantdouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "constantdouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double4*", "globaldouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "globaldouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double4*", "globalconstdouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "globalconstdouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double4*", "globalvolatiledouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "globalvolatiledouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double4*", "globalconstvolatiledouble4p", + NULL + }, + { + "double_vector4_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "globalconstvolatiledouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double4*", "localdouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "localdouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double4*", "localconstdouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "localconstdouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double4*", "localvolatiledouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "localvolatiledouble4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double4*", "localconstvolatiledouble4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double4*", "localconstvolatiledouble4restrictp", + NULL + }, + { + "double_vector4_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double4", "double4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double4", "constdouble4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double4", "privatedouble4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double4", "privateconstdouble4d", + NULL + }, + { + "double_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double8*", "constantdouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "constantdouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double8*", "globaldouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "globaldouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double8*", "globalconstdouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "globalconstdouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double8*", "globalvolatiledouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "globalvolatiledouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double8*", "globalconstvolatiledouble8p", + NULL + }, + { + "double_vector8_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "globalconstvolatiledouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double8*", "localdouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "localdouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double8*", "localconstdouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "localconstdouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double8*", "localvolatiledouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "localvolatiledouble8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double8*", "localconstvolatiledouble8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double8*", "localconstvolatiledouble8restrictp", + NULL + }, + { + "double_vector8_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double8", "double8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double8", "constdouble8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double8", "privatedouble8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double8", "privateconstdouble8d", + NULL + }, + { + "double_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double16*", "constantdouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "constantdouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double16*", "globaldouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "globaldouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double16*", "globalconstdouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "globalconstdouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double16*", "globalvolatiledouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "globalvolatiledouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double16*", "globalconstvolatiledouble16p", + NULL + }, + { + "double_vector16_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "globalconstvolatiledouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double16*", "localdouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "localdouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "double16*", "localconstdouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "localconstdouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "double16*", "localvolatiledouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "localvolatiledouble16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "double16*", "localconstvolatiledouble16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "double16*", "localconstvolatiledouble16restrictp", + NULL + }, + { + "double_vector16_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double16", "double16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double16", "constdouble16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double16", "privatedouble16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "double16", "privateconstdouble16d", + NULL + }, +}; + + +// Support for optional half data type +const char * half_kernel_args[] = { + "#pragma OPENCL EXTENSION cl_khr_fp16 : enable\n" + "\n" + "kernel void half_scalar_p(constant half*constanthalfp,\n" + " constant half *restrict constanthalfrestrictp,\n" + " global half*globalhalfp,\n" + " global half *restrict globalhalfrestrictp,\n" + " global const half* globalconsthalfp,\n" + " global const half * restrict globalconsthalfrestrictp,\n" + " global volatile half*globalvolatilehalfp,\n" + " global volatile half *restrict globalvolatilehalfrestrictp,\n" + " global const volatile half* globalconstvolatilehalfp)\n" + "{}\n", + "\n" + "kernel void half_scalar_p2(global const volatile half * restrict globalconstvolatilehalfrestrictp,\n" + " local half*localhalfp,\n" + " local half *restrict localhalfrestrictp,\n" + " local const half* localconsthalfp,\n" + " local const half * restrict localconsthalfrestrictp,\n" + " local volatile half*localvolatilehalfp,\n" + " local volatile half *restrict localvolatilehalfrestrictp,\n" + " local const volatile half* localconstvolatilehalfp,\n" + " local const volatile half * restrict localconstvolatilehalfrestrictp)\n" + "{}\n", + "\n" + "kernel void half_scalar_d(half halfd,\n" + " const half consthalfd,\n" + " private half privatehalfd,\n" + " private const half privateconsthalfd)\n" + "{}\n", + "\n" + "kernel void half_vector2_p(constant half2*constanthalf2p,\n" + " constant half2 *restrict constanthalf2restrictp,\n" + " global half2*globalhalf2p,\n" + " global half2 *restrict globalhalf2restrictp,\n" + " global const half2* globalconsthalf2p,\n" + " global const half2 * restrict globalconsthalf2restrictp,\n" + " global volatile half2*globalvolatilehalf2p,\n" + " global volatile half2 *restrict globalvolatilehalf2restrictp,\n" + " global const volatile half2* globalconstvolatilehalf2p)\n" + "{}\n", + "\n" + "kernel void half_vector2_p2(global const volatile half2 * restrict globalconstvolatilehalf2restrictp,\n" + " local half2*localhalf2p,\n" + " local half2 *restrict localhalf2restrictp,\n" + " local const half2* localconsthalf2p,\n" + " local const half2 * restrict localconsthalf2restrictp,\n" + " local volatile half2*localvolatilehalf2p,\n" + " local volatile half2 *restrict localvolatilehalf2restrictp,\n" + " local const volatile half2* localconstvolatilehalf2p,\n" + " local const volatile half2 * restrict localconstvolatilehalf2restrictp)\n" + "{}\n", + "\n" + "kernel void half_vector2_d(half2 half2d,\n" + " const half2 consthalf2d,\n" + " private half2 privatehalf2d,\n" + " private const half2 privateconsthalf2d)\n" + "{}\n", + "\n" + "kernel void half_vector3_p(constant half3*constanthalf3p,\n" + " constant half3 *restrict constanthalf3restrictp,\n" + " global half3*globalhalf3p,\n" + " global half3 *restrict globalhalf3restrictp,\n" + " global const half3* globalconsthalf3p,\n" + " global const half3 * restrict globalconsthalf3restrictp,\n" + " global volatile half3*globalvolatilehalf3p,\n" + " global volatile half3 *restrict globalvolatilehalf3restrictp,\n" + " global const volatile half3* globalconstvolatilehalf3p)\n" + "{}\n", + "\n" + "kernel void half_vector3_p2(global const volatile half3 * restrict globalconstvolatilehalf3restrictp,\n" + " local half3*localhalf3p,\n" + " local half3 *restrict localhalf3restrictp,\n" + " local const half3* localconsthalf3p,\n" + " local const half3 * restrict localconsthalf3restrictp,\n" + " local volatile half3*localvolatilehalf3p,\n" + " local volatile half3 *restrict localvolatilehalf3restrictp,\n" + " local const volatile half3* localconstvolatilehalf3p,\n" + " local const volatile half3 * restrict localconstvolatilehalf3restrictp)\n" + "{}\n", + "\n" + "kernel void half_vector3_d(half3 half3d,\n" + " const half3 consthalf3d,\n" + " private half3 privatehalf3d,\n" + " private const half3 privateconsthalf3d)\n" + "{}\n", + "\n" + "kernel void half_vector4_p(constant half4*constanthalf4p,\n" + " constant half4 *restrict constanthalf4restrictp,\n" + " global half4*globalhalf4p,\n" + " global half4 *restrict globalhalf4restrictp,\n" + " global const half4* globalconsthalf4p,\n" + " global const half4 * restrict globalconsthalf4restrictp,\n" + " global volatile half4*globalvolatilehalf4p,\n" + " global volatile half4 *restrict globalvolatilehalf4restrictp,\n" + " global const volatile half4* globalconstvolatilehalf4p)\n" + "{}\n", + "\n" + "kernel void half_vector4_p2(global const volatile half4 * restrict globalconstvolatilehalf4restrictp,\n" + " local half4*localhalf4p,\n" + " local half4 *restrict localhalf4restrictp,\n" + " local const half4* localconsthalf4p,\n" + " local const half4 * restrict localconsthalf4restrictp,\n" + " local volatile half4*localvolatilehalf4p,\n" + " local volatile half4 *restrict localvolatilehalf4restrictp,\n" + " local const volatile half4* localconstvolatilehalf4p,\n" + " local const volatile half4 * restrict localconstvolatilehalf4restrictp)\n" + "{}\n", + "\n" + "kernel void half_vector4_d(half4 half4d,\n" + " const half4 consthalf4d,\n" + " private half4 privatehalf4d,\n" + " private const half4 privateconsthalf4d)\n" + "{}\n", + "\n" + "kernel void half_vector8_p(constant half8*constanthalf8p,\n" + " constant half8 *restrict constanthalf8restrictp,\n" + " global half8*globalhalf8p,\n" + " global half8 *restrict globalhalf8restrictp,\n" + " global const half8* globalconsthalf8p,\n" + " global const half8 * restrict globalconsthalf8restrictp,\n" + " global volatile half8*globalvolatilehalf8p,\n" + " global volatile half8 *restrict globalvolatilehalf8restrictp,\n" + " global const volatile half8* globalconstvolatilehalf8p)\n" + "{}\n", + "\n" + "kernel void half_vector8_p2(global const volatile half8 * restrict globalconstvolatilehalf8restrictp,\n" + " local half8*localhalf8p,\n" + " local half8 *restrict localhalf8restrictp,\n" + " local const half8* localconsthalf8p,\n" + " local const half8 * restrict localconsthalf8restrictp,\n" + " local volatile half8*localvolatilehalf8p,\n" + " local volatile half8 *restrict localvolatilehalf8restrictp,\n" + " local const volatile half8* localconstvolatilehalf8p,\n" + " local const volatile half8 * restrict localconstvolatilehalf8restrictp)\n" + "{}\n", + "\n" + "kernel void half_vector8_d(half8 half8d,\n" + " const half8 consthalf8d,\n" + " private half8 privatehalf8d,\n" + " private const half8 privateconsthalf8d)\n" + "{}\n", + "\n" + "kernel void half_vector16_p(constant half16*constanthalf16p,\n" + " constant half16 *restrict constanthalf16restrictp,\n" + " global half16*globalhalf16p,\n" + " global half16 *restrict globalhalf16restrictp,\n" + " global const half16* globalconsthalf16p,\n" + " global const half16 * restrict globalconsthalf16restrictp,\n" + " global volatile half16*globalvolatilehalf16p,\n" + " global volatile half16 *restrict globalvolatilehalf16restrictp,\n" + " global const volatile half16* globalconstvolatilehalf16p)\n" + "{}\n", + "\n" + "kernel void half_vector16_p2(global const volatile half16 * restrict globalconstvolatilehalf16restrictp,\n" + " local half16*localhalf16p,\n" + " local half16 *restrict localhalf16restrictp,\n" + " local const half16* localconsthalf16p,\n" + " local const half16 * restrict localconsthalf16restrictp,\n" + " local volatile half16*localvolatilehalf16p,\n" + " local volatile half16 *restrict localvolatilehalf16restrictp,\n" + " local const volatile half16* localconstvolatilehalf16p,\n" + " local const volatile half16 * restrict localconstvolatilehalf16restrictp)\n" + "{}\n", + "\n" + "kernel void half_vector16_d(half16 half16d,\n" + " const half16 consthalf16d,\n" + " private half16 privatehalf16d,\n" + " private const half16 privateconsthalf16d)\n" + "{}\n", + "\n" +}; + +const char * half_arg_info[][77] = { + { + "half_scalar_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half*", "constanthalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "constanthalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half*", "globalhalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "globalhalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half*", "globalconsthalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "globalconsthalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half*", "globalvolatilehalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "globalvolatilehalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half*", "globalconstvolatilehalfp", + NULL + }, + { + "half_scalar_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "globalconstvolatilehalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half*", "localhalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "localhalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half*", "localconsthalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "localconsthalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half*", "localvolatilehalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "localvolatilehalfrestrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half*", "localconstvolatilehalfp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half*", "localconstvolatilehalfrestrictp", + NULL + }, + { + "half_scalar_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half", "halfd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half", "consthalfd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half", "privatehalfd", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half", "privateconsthalfd", + NULL + }, + { + "half_vector2_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half2*", "constanthalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "constanthalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half2*", "globalhalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "globalhalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half2*", "globalconsthalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "globalconsthalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half2*", "globalvolatilehalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "globalvolatilehalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half2*", "globalconstvolatilehalf2p", + NULL + }, + { + "half_vector2_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "globalconstvolatilehalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half2*", "localhalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "localhalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half2*", "localconsthalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "localconsthalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half2*", "localvolatilehalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "localvolatilehalf2restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half2*", "localconstvolatilehalf2p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half2*", "localconstvolatilehalf2restrictp", + NULL + }, + { + "half_vector2_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half2", "half2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half2", "consthalf2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half2", "privatehalf2d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half2", "privateconsthalf2d", + NULL + }, + { + "half_vector3_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half3*", "constanthalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "constanthalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half3*", "globalhalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "globalhalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half3*", "globalconsthalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "globalconsthalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half3*", "globalvolatilehalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "globalvolatilehalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half3*", "globalconstvolatilehalf3p", + NULL + }, + { + "half_vector3_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "globalconstvolatilehalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half3*", "localhalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "localhalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half3*", "localconsthalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "localconsthalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half3*", "localvolatilehalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "localvolatilehalf3restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half3*", "localconstvolatilehalf3p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half3*", "localconstvolatilehalf3restrictp", + NULL + }, + { + "half_vector3_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half3", "half3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half3", "consthalf3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half3", "privatehalf3d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half3", "privateconsthalf3d", + NULL + }, + { + "half_vector4_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half4*", "constanthalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "constanthalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half4*", "globalhalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "globalhalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half4*", "globalconsthalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "globalconsthalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half4*", "globalvolatilehalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "globalvolatilehalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half4*", "globalconstvolatilehalf4p", + NULL + }, + { + "half_vector4_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "globalconstvolatilehalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half4*", "localhalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "localhalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half4*", "localconsthalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "localconsthalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half4*", "localvolatilehalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "localvolatilehalf4restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half4*", "localconstvolatilehalf4p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half4*", "localconstvolatilehalf4restrictp", + NULL + }, + { + "half_vector4_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half4", "half4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half4", "consthalf4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half4", "privatehalf4d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half4", "privateconsthalf4d", + NULL + }, + { + "half_vector8_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half8*", "constanthalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "constanthalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half8*", "globalhalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "globalhalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half8*", "globalconsthalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "globalconsthalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half8*", "globalvolatilehalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "globalvolatilehalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half8*", "globalconstvolatilehalf8p", + NULL + }, + { + "half_vector8_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "globalconstvolatilehalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half8*", "localhalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "localhalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half8*", "localconsthalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "localconsthalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half8*", "localvolatilehalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "localvolatilehalf8restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half8*", "localconstvolatilehalf8p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half8*", "localconstvolatilehalf8restrictp", + NULL + }, + { + "half_vector8_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half8", "half8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half8", "consthalf8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half8", "privatehalf8d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half8", "privateconsthalf8d", + NULL + }, + { + "half_vector16_p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half16*", "constanthalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_CONSTANT, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "constanthalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half16*", "globalhalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "globalhalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half16*", "globalconsthalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "globalconsthalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half16*", "globalvolatilehalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "globalvolatilehalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half16*", "globalconstvolatilehalf16p", + NULL + }, + { + "half_vector16_p2", + (const char *)CL_KERNEL_ARG_ADDRESS_GLOBAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "globalconstvolatilehalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half16*", "localhalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "localhalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST), "half16*", "localconsthalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "localconsthalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE), "half16*", "localvolatilehalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "localvolatilehalf16restrictp", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE), "half16*", "localconstvolatilehalf16p", + (const char *)CL_KERNEL_ARG_ADDRESS_LOCAL, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_CONST|CL_KERNEL_ARG_TYPE_VOLATILE|CL_KERNEL_ARG_TYPE_RESTRICT), "half16*", "localconstvolatilehalf16restrictp", + NULL + }, + { + "half_vector16_d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half16", "half16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half16", "consthalf16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half16", "privatehalf16d", + (const char *)CL_KERNEL_ARG_ADDRESS_PRIVATE, (const char *)CL_KERNEL_ARG_ACCESS_NONE, (const char *)(CL_KERNEL_ARG_TYPE_NONE), "half16", "privateconsthalf16d", + NULL + }, +}; + + +template +int test(cl_device_id deviceID, cl_context context, kernel_args_t kernel_args, cl_uint lines_count, arg_info_t arg_info, size_t total_kernels_in_program) { + + cl_program program; + cl_kernel kernel; + const size_t max_name_len = 512; + cl_char name[ max_name_len ]; + cl_uint arg_count, numArgs; + size_t i, j, size; + int error; + + program = clCreateProgramWithSource( context, lines_count, kernel_args, NULL, &error ); + if ( program == NULL || error != CL_SUCCESS ) + { + print_error( error, "Unable to create required arguments kernel program" ); + return -1; + } + + // Compile the program + log_info( "Building kernels...\n" ); + clBuildProgram( program, 1, &deviceID, "-cl-kernel-arg-info", NULL, NULL ); + + // check for build errors and exit if things didn't work + size_t size_ret; + cl_build_status build_status; + error = clGetProgramBuildInfo(program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof(build_status), &build_status, &size_ret); + test_error( error, "Unable to query build status" ); + if (build_status == CL_BUILD_ERROR) { + printf("CL_PROGRAM_BUILD_STATUS=%d\n", (int) build_status); + error = clGetProgramBuildInfo(program, deviceID, CL_PROGRAM_BUILD_LOG, 0, NULL, &size_ret); + test_error( error, "Unable to get build log size" ); + char *build_log = (char *)malloc(size_ret); + error = clGetProgramBuildInfo(program,deviceID, CL_PROGRAM_BUILD_LOG, size_ret, build_log, &size_ret); + test_error( error, "Unable to get build log" ); + printf("CL_PROGRAM_BUILD_LOG:\n%s\n", build_log); + printf("CL_BUILD_ERROR. exiting\n"); + free(build_log); + return -1; + } + + // Lookup the number of kernels in the program. + log_info( "Testing kernels...\n" ); + size_t total_kernels = 0; + error = clGetProgramInfo( program, CL_PROGRAM_NUM_KERNELS, sizeof( size_t ), &total_kernels, NULL ); + test_error( error, "Unable to get program info num kernels" ); + + if ( total_kernels != total_kernels_in_program ) + { + print_error( error, "Program did not build all kernels" ); + return -1; + } + + // Lookup the kernel names. + size_t kernel_names_len = 0; + error = clGetProgramInfo( program, CL_PROGRAM_KERNEL_NAMES, 0, NULL, &kernel_names_len ); + test_error( error, "Unable to get length of kernel names list." ); + + size_t expected_kernel_names_len = 0; + for ( i = 0; i < total_kernels; ++i ) + { + expected_kernel_names_len += 1 + strlen( arg_info[ i ][ 0 ] ); + } + if ( kernel_names_len != expected_kernel_names_len ) + { + log_error( "Kernel names string is not the right length, expected %d, got %d\n", (int) expected_kernel_names_len, (int) kernel_names_len ); + return -1; + } + + const size_t len = ( kernel_names_len + 1 ) * sizeof( char ); + char* kernel_names = (char*) malloc( len ); + error = clGetProgramInfo( program, CL_PROGRAM_KERNEL_NAMES, len, kernel_names, &kernel_names_len ); + test_error( error, "Unable to get kernel names list." ); + + // Check to see if the kernel name array is null terminated. + if ( kernel_names[ kernel_names_len - 1 ] != '\0' ) + { + free( kernel_names ); + print_error( error, "Kernel name list was not null terminated" ); + return -1; + } + + // Check to see if the correct kernel name string was returned. + // Does the string contain each expected kernel name? + for ( i = 0; i < total_kernels; ++i ) + if ( !strstr( kernel_names, arg_info[ i ][ 0 ] ) ) + break; + if ( i != total_kernels ) + { + log_error( "Kernel names string is missing \"%s\"\n", arg_info[ i ][ 0 ] ); + free( kernel_names ); + return -1; + } + + // Are the kernel names delimited by ';'? + if ( !strtok( kernel_names, ";" ) ) + { + error = -1; + } + else + { + for ( i = 1; i < total_kernels; ++i ) + { + if ( !strtok( NULL, ";" ) ) + { + error = -1; + } + } + } + if ( error ) + { + log_error( "Kernel names string was not properly delimited by ';'\n" ); + free( kernel_names ); + return -1; + } + free( kernel_names ); + + // Create kernel objects and query them. + int rc = 0; + for ( i = 0; i < total_kernels; ++i ) + { + int kernel_rc = 0; + const char* kernel_name = arg_info[ i ][ 0 ]; + kernel = clCreateKernel( program, kernel_name, &error ); + if( kernel == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Could not get kernel: %s\n", kernel_name ); + kernel_rc = -1; + } + + if(kernel_rc == 0) + { + // Determine the expected number of arguments. + arg_count = 0; + while (arg_info[ i ][ (ARG_INFO_FIELD_COUNT * arg_count) + 1 ] != NULL) + ++arg_count; + + // Try to get the number of arguments. + error = clGetKernelInfo( kernel, CL_KERNEL_NUM_ARGS, 0, NULL, &size ); + test_error( error, "Unable to get kernel arg count param size" ); + if( size != sizeof( numArgs ) ) + { + log_error( "ERROR: Kernel arg count param returns invalid size (expected %d, got %d) for kernel: %s\n", (int)sizeof( numArgs ), (int)size, kernel_name ); + kernel_rc = -1; + } + } + + + if(kernel_rc == 0) + { + error = clGetKernelInfo( kernel, CL_KERNEL_NUM_ARGS, sizeof( numArgs ), &numArgs, NULL ); + test_error( error, "Unable to get kernel arg count" ); + if( numArgs != arg_count ) + { + log_error( "ERROR: Kernel arg count returned invalid value (expected %d, got %d) for kernel: %s\n", arg_count, numArgs, kernel_name ); + kernel_rc = -1; + } + } + + if(kernel_rc == 0) + { + for ( j = 0; j < numArgs; ++j ) + { + + int arg_rc = 0; + cl_kernel_arg_address_qualifier expected_address_qualifier = (cl_kernel_arg_address_qualifier)(uintptr_t)arg_info[ i ][ (ARG_INFO_FIELD_COUNT * j) + ARG_INFO_ADDR_OFFSET ]; + cl_kernel_arg_access_qualifier expected_access_qualifier = (cl_kernel_arg_access_qualifier)(uintptr_t)arg_info[ i ][ (ARG_INFO_FIELD_COUNT * j) + ARG_INFO_ACCESS_OFFSET ]; + cl_kernel_arg_type_qualifier expected_type_qualifier = (cl_kernel_arg_type_qualifier)(uintptr_t)arg_info[ i ][ (ARG_INFO_FIELD_COUNT * j) + ARG_INFO_TYPE_QUAL_OFFSET ]; + const char* expected_type_name = arg_info[ i ][ (ARG_INFO_FIELD_COUNT * j) + ARG_INFO_TYPE_NAME_OFFSET ]; + const char* expected_arg_name = arg_info[ i ][ (ARG_INFO_FIELD_COUNT * j) + ARG_INFO_ARG_NAME_OFFSET ]; + + // Try to get the address qualifier of each argument. + cl_kernel_arg_address_qualifier address_qualifier = 0; + error = clGetKernelArgInfo( kernel, (cl_uint)j, CL_KERNEL_ARG_ADDRESS_QUALIFIER, sizeof address_qualifier, &address_qualifier, &size ); + test_error( error, "Unable to get argument address qualifier" ); + error = (address_qualifier != expected_address_qualifier); + if ( error ) + { + log_error( "ERROR: Bad address qualifier, kernel: \"%s\", argument number: %d, expected \"0x%X\", got \"0x%X\"\n", kernel_name, (unsigned int)j, (unsigned int)expected_address_qualifier, (unsigned int)address_qualifier ); + arg_rc = -1; + } + + // Try to get the access qualifier of each argument. + cl_kernel_arg_access_qualifier access_qualifier = 0; + error = clGetKernelArgInfo( kernel, (cl_uint)j, CL_KERNEL_ARG_ACCESS_QUALIFIER, sizeof access_qualifier, &access_qualifier, &size ); + test_error( error, "Unable to get argument access qualifier" ); + error = (access_qualifier != expected_access_qualifier); + if ( error ) + { + log_error( "ERROR: Bad access qualifier, kernel: \"%s\", argument number: %d, expected \"0x%X\", got \"0x%X\"\n", kernel_name, (unsigned int)j, (unsigned int)expected_access_qualifier, (unsigned int)access_qualifier ); + arg_rc = -1; + } + + // Try to get the type qualifier of each argument. + cl_kernel_arg_type_qualifier arg_type_qualifier = 0; + error = clGetKernelArgInfo( kernel, (cl_uint)j, CL_KERNEL_ARG_TYPE_QUALIFIER, sizeof arg_type_qualifier, &arg_type_qualifier, &size ); + test_error( error, "Unable to get argument type qualifier" ); + error = (arg_type_qualifier != expected_type_qualifier); + if ( error ) + { + log_error( "ERROR: Bad type qualifier, kernel: \"%s\", argument number: %d, expected \"0x%X\", got \"0x%X\"\n", kernel_name, (unsigned int)j, (unsigned int)expected_type_qualifier, (unsigned int)arg_type_qualifier ); + arg_rc = -1; + } + + // Try to get the type of each argument. + memset( name, 0, max_name_len ); + error = clGetKernelArgInfo(kernel, (cl_uint)j, CL_KERNEL_ARG_TYPE_NAME, max_name_len, name, &size ); + test_error( error, "Unable to get argument type name" ); + error = strcmp( (const char*) name, expected_type_name ); + if ( error ) + { + log_error( "ERROR: Bad argument type name, kernel: \"%s\", argument number: %d, expected \"%s\", got \"%s\"\n", kernel_name, (unsigned int)j, expected_type_name, name ); + arg_rc = -1; + } + + // Try to get the name of each argument. + memset( name, 0, max_name_len ); + error = clGetKernelArgInfo( kernel, (cl_uint)j, CL_KERNEL_ARG_NAME, max_name_len, name, &size ); + test_error( error, "Unable to get argument name" ); + error = strcmp( (const char*) name, expected_arg_name ); + if ( error ) + { + log_error( "ERROR: Bad argument name, kernel: \"%s\", argument number: %d, expected \"%s\", got \"%s\"\n", kernel_name, (unsigned int)j, expected_arg_name, name ); + arg_rc = -1; + } + + if(arg_rc != 0) { + kernel_rc = -1; + } + } + } + + //log_info( "%s ... %s\n",arg_info[i][0],kernel_rc == 0 ? "passed" : "failed" ); + if(kernel_rc != 0) { + rc = -1; + } + } + return rc; +} + + +int test_get_kernel_arg_info( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + size_t size; + int error; + + cl_bool supports_double = 0; // assume not + cl_bool supports_half = 0; // assume not + cl_bool supports_images = 0; // assume not + + // Check if this device supports images + error = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE_SUPPORT, sizeof supports_images, &supports_images, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_IMAGE_SUPPORT failed"); + + if (supports_images) { + log_info(" o Device supports images\n"); + log_info(" o Expecting SUCCESS when testing image kernel arguments.\n"); + } + else { + log_info(" o Device lacks image support\n"); + log_info(" o Not testing image kernel arguments.\n"); + } + + // Get the extensions string for the device + error = clGetDeviceInfo(deviceID, CL_DEVICE_EXTENSIONS, 0, NULL, &size); + test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS size failed"); + + char *extensions = (char*)malloc(sizeof(char)*(size + 1)); + if (extensions == 0) { + log_error("Failed to allocate memory for extensions string.\n"); + return -1; + } + memset( extensions, CHAR_MIN, sizeof(char)*(size+1) ); + + error = clGetDeviceInfo(deviceID, CL_DEVICE_EXTENSIONS, sizeof(char)*size, extensions, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS failed"); + + // Check to make sure the extension string is NUL terminated. + if( extensions[size] != CHAR_MIN ) + { + test_error( -1, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS wrote past the end of the array!" ); + return -1; + } + extensions[size] = '\0'; // set last char to NUL to avoid problems with string functions later + + // test for termination with '\0' + size_t stringSize = strlen( extensions ); + if( stringSize == size ) + { + test_error( -1, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS is not NUL terminated!" ); + return -1; + } + + if (strstr(extensions, "cl_khr_fp64")) { + log_info(" o Device claims extension 'cl_khr_fp64'\n"); + log_info(" o Expecting SUCCESS when testing double kernel arguments.\n"); + supports_double = 1; + } else { + cl_device_fp_config double_fp_config; + error = clGetDeviceInfo(deviceID, CL_DEVICE_DOUBLE_FP_CONFIG, sizeof(double_fp_config), &double_fp_config, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_DOUBLE_FP_CONFIG failed"); + if (double_fp_config != 0) + supports_double = 1; + else { + log_info(" o Device lacks extension 'cl_khr_fp64'\n"); + log_info(" o Not testing double kernel arguments.\n"); + supports_double = 0; + } + } + + if (strstr(extensions, "cl_khr_fp16")) { + log_info(" o Device claims extension 'cl_khr_fp16'\n"); + log_info(" o Expecting SUCCESS when testing halfn* kernel arguments.\n"); + supports_half = 1; + } else { + log_info(" o Device lacks extension 'cl_khr_fp16'\n"); + log_info(" o Not testing halfn* kernel arguments.\n"); + supports_half = 0; + } + + + int test_failed = 0; + + // Now create a test program using required arguments + log_info("Testing required kernel arguments...\n"); + error = test(deviceID, context, required_kernel_args, sizeof(required_kernel_args)/sizeof(required_kernel_args[0]), required_arg_info, sizeof(required_arg_info)/sizeof(required_arg_info[0])); + test_failed = (error) ? -1 : test_failed; + + if ( supports_images ) { + log_info("Testing optional image arguments...\n"); + error = test(deviceID, context, image_kernel_args, sizeof(image_kernel_args)/sizeof(image_kernel_args[0]), image_arg_info, sizeof(image_arg_info)/sizeof(image_arg_info[0])); + test_failed = (error) ? -1 : test_failed; + } + + if ( supports_double ) { + log_info("Testing optional double arguments...\n"); + error = test(deviceID, context, double_kernel_args, sizeof(double_kernel_args)/sizeof(double_kernel_args[0]), double_arg_info, sizeof(double_arg_info)/sizeof(double_arg_info[0])); + test_failed = (error) ? -1 : test_failed; + } + + if ( supports_half ) { + log_info("Testing optional half arguments...\n"); + error = test(deviceID, context, half_kernel_args, sizeof(half_kernel_args)/sizeof(half_kernel_args[0]), half_arg_info, sizeof(half_arg_info)/sizeof(half_arg_info[0])); + test_failed = (error) ? -1 : test_failed; + } + + return test_failed; +} + + diff --git a/test_conformance/compatibility/test_conformance/api/test_kernel_arg_multi_setup.cpp b/test_conformance/compatibility/test_conformance/api/test_kernel_arg_multi_setup.cpp new file mode 100644 index 00000000..89c5eeb1 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/test_kernel_arg_multi_setup.cpp @@ -0,0 +1,277 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/conversions.h" + +// This test is designed to stress passing multiple vector parameters to kernels and verifying access between them all + +const char *multi_arg_kernel_source_pattern = +"__kernel void sample_test(__global %s *src1, __global %s *src2, __global %s *src3, __global %s *dst1, __global %s *dst2, __global %s *dst3 )\n" +"{\n" +" int tid = get_global_id(0);\n" +" dst1[tid] = src1[tid];\n" +" dst2[tid] = src2[tid];\n" +" dst3[tid] = src3[tid];\n" +"}\n"; + +extern cl_uint gRandomSeed; + +#define MAX_ERROR_TOLERANCE 0.0005f + +int test_multi_arg_set(cl_device_id device, cl_context context, cl_command_queue queue, + ExplicitType vec1Type, int vec1Size, + ExplicitType vec2Type, int vec2Size, + ExplicitType vec3Type, int vec3Size, MTdata d) +{ + clProgramWrapper program; + clKernelWrapper kernel; + int error, i, j; + clMemWrapper streams[ 6 ]; + size_t threads[1], localThreads[1]; + char programSrc[ 10248 ], vec1Name[ 64 ], vec2Name[ 64 ], vec3Name[ 64 ]; + char sizeNames[][ 4 ] = { "", "2", "3", "4", "", "", "", "8" }; + const char *ptr; + void *initData[3], *resultData[3]; + + + // Create the program source + sprintf( vec1Name, "%s%s", get_explicit_type_name( vec1Type ), sizeNames[ vec1Size - 1 ] ); + sprintf( vec2Name, "%s%s", get_explicit_type_name( vec2Type ), sizeNames[ vec2Size - 1 ] ); + sprintf( vec3Name, "%s%s", get_explicit_type_name( vec3Type ), sizeNames[ vec3Size - 1 ] ); + + sprintf( programSrc, multi_arg_kernel_source_pattern, + vec1Name, vec2Name, vec3Name, vec1Name, vec2Name, vec3Name, + vec1Size, vec1Size, vec2Size, vec2Size, vec3Size, vec3Size ); + ptr = programSrc; + + // Create our testing kernel + error = create_single_kernel_helper( context, &program, &kernel, 1, &ptr, "sample_test" ); + test_error( error, "Unable to create testing kernel" ); + + // Get thread dimensions + threads[0] = 1024; + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size for kernel" ); + + // Create input streams + initData[ 0 ] = create_random_data( vec1Type, d, (unsigned int)threads[ 0 ] * vec1Size ); + streams[ 0 ] = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), get_explicit_type_size( vec1Type ) * threads[0] * vec1Size, initData[ 0 ], &error ); + test_error( error, "Unable to create testing stream" ); + + initData[ 1 ] = create_random_data( vec2Type, d, (unsigned int)threads[ 0 ] * vec2Size ); + streams[ 1 ] = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), get_explicit_type_size( vec2Type ) * threads[0] * vec2Size, initData[ 1 ], &error ); + test_error( error, "Unable to create testing stream" ); + + initData[ 2 ] = create_random_data( vec3Type, d, (unsigned int)threads[ 0 ] * vec3Size ); + streams[ 2 ] = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), get_explicit_type_size( vec3Type ) * threads[0] * vec3Size, initData[ 2 ], &error ); + test_error( error, "Unable to create testing stream" ); + + streams[ 3 ] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), get_explicit_type_size( vec1Type ) * threads[0] * vec1Size, NULL, &error ); + test_error( error, "Unable to create testing stream" ); + + streams[ 4 ] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), get_explicit_type_size( vec2Type ) * threads[0] * vec2Size, NULL, &error ); + test_error( error, "Unable to create testing stream" ); + + streams[ 5 ] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), get_explicit_type_size( vec3Type ) * threads[0] * vec3Size, NULL, &error ); + test_error( error, "Unable to create testing stream" ); + + // Set the arguments + error = 0; + for( i = 0; i < 6; i++ ) + error |= clSetKernelArg( kernel, i, sizeof( cl_mem ), &streams[ i ] ); + test_error( error, "Unable to set arguments for kernel" ); + + // Execute! + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute kernel" ); + + // Read results + resultData[0] = malloc( get_explicit_type_size( vec1Type ) * vec1Size * threads[0] ); + resultData[1] = malloc( get_explicit_type_size( vec2Type ) * vec2Size * threads[0] ); + resultData[2] = malloc( get_explicit_type_size( vec3Type ) * vec3Size * threads[0] ); + error = clEnqueueReadBuffer( queue, streams[ 3 ], CL_TRUE, 0, get_explicit_type_size( vec1Type ) * vec1Size * threads[ 0 ], resultData[0], 0, NULL, NULL ); + error |= clEnqueueReadBuffer( queue, streams[ 4 ], CL_TRUE, 0, get_explicit_type_size( vec2Type ) * vec2Size * threads[ 0 ], resultData[1], 0, NULL, NULL ); + error |= clEnqueueReadBuffer( queue, streams[ 5 ], CL_TRUE, 0, get_explicit_type_size( vec3Type ) * vec3Size * threads[ 0 ], resultData[2], 0, NULL, NULL ); + test_error( error, "Unable to read result stream" ); + + // Verify + char *ptr1 = (char *)initData[ 0 ], *ptr2 = (char *)resultData[ 0 ]; + size_t span = get_explicit_type_size( vec1Type ); + for( i = 0; i < (int)threads[0]; i++ ) + { + for( j = 0; j < vec1Size; j++ ) + { + if( memcmp( ptr1 + span * j , ptr2 + span * j, span ) != 0 ) + { + log_error( "ERROR: Value did not validate for component %d of item %d of stream 0!\n", j, i ); + free( initData[ 0 ] ); + free( initData[ 1 ] ); + free( initData[ 2 ] ); + free( resultData[ 0 ] ); + free( resultData[ 1 ] ); + free( resultData[ 2 ] ); + return -1; + } + } + ptr1 += span * vec1Size; + ptr2 += span * vec1Size; + } + + ptr1 = (char *)initData[ 1 ]; + ptr2 = (char *)resultData[ 1 ]; + span = get_explicit_type_size( vec2Type ); + for( i = 0; i < (int)threads[0]; i++ ) + { + for( j = 0; j < vec2Size; j++ ) + { + if( memcmp( ptr1 + span * j , ptr2 + span * j, span ) != 0 ) + { + log_error( "ERROR: Value did not validate for component %d of item %d of stream 1!\n", j, i ); + free( initData[ 0 ] ); + free( initData[ 1 ] ); + free( initData[ 2 ] ); + free( resultData[ 0 ] ); + free( resultData[ 1 ] ); + free( resultData[ 2 ] ); + return -1; + } + } + ptr1 += span * vec2Size; + ptr2 += span * vec2Size; + } + + ptr1 = (char *)initData[ 2 ]; + ptr2 = (char *)resultData[ 2 ]; + span = get_explicit_type_size( vec3Type ); + for( i = 0; i < (int)threads[0]; i++ ) + { + for( j = 0; j < vec3Size; j++ ) + { + if( memcmp( ptr1 + span * j , ptr2 + span * j, span ) != 0 ) + { + log_error( "ERROR: Value did not validate for component %d of item %d of stream 2!\n", j, i ); + free( initData[ 0 ] ); + free( initData[ 1 ] ); + free( initData[ 2 ] ); + free( resultData[ 0 ] ); + free( resultData[ 1 ] ); + free( resultData[ 2 ] ); + return -1; + } + } + ptr1 += span * vec3Size; + ptr2 += span * vec3Size; + } + + // If we got here, everything verified successfully + free( initData[ 0 ] ); + free( initData[ 1 ] ); + free( initData[ 2 ] ); + free( resultData[ 0 ] ); + free( resultData[ 1 ] ); + free( resultData[ 2 ] ); + + return 0; +} + +int test_kernel_arg_multi_setup_exhaustive(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + // Loop through every combination of input and output types + ExplicitType types[] = { kChar, kShort, kInt, kFloat, kNumExplicitTypes }; + int type1, type2, type3; + int size1, size2, size3; + RandomSeed seed( gRandomSeed ); + + log_info( "\n" ); // for formatting + + for( type1 = 0; types[ type1 ] != kNumExplicitTypes; type1++ ) + { + for( type2 = 0; types[ type2 ] != kNumExplicitTypes; type2++ ) + { + for( type3 = 0; types[ type3 ] != kNumExplicitTypes; type3++ ) + { + log_info( "\n\ttesting %s, %s, %s...", get_explicit_type_name( types[ type1 ] ), get_explicit_type_name( types[ type2 ] ), get_explicit_type_name( types[ type3 ] ) ); + + // Loop through every combination of vector size + for( size1 = 2; size1 <= 8; size1 <<= 1 ) + { + for( size2 = 2; size2 <= 8; size2 <<= 1 ) + { + for( size3 = 2; size3 <= 8; size3 <<= 1 ) + { + log_info("."); + fflush( stdout); + if( test_multi_arg_set( device, context, queue, + types[ type1 ], size1, + types[ type2 ], size2, + types[ type3 ], size3, seed ) ) + return -1; + } + } + } + } + } + } + log_info( "\n" ); + return 0; +} + +int test_kernel_arg_multi_setup_random(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + // Loop through a selection of combinations + ExplicitType types[] = { kChar, kShort, kInt, kFloat, kNumExplicitTypes }; + int type1, type2, type3; + int size1, size2, size3; + RandomSeed seed( gRandomSeed ); + + num_elements = 3*3*3*4; + log_info( "Testing %d random configurations\n", num_elements ); + + // Loop through every combination of vector size + for( size1 = 2; size1 <= 8; size1 <<= 1 ) + { + for( size2 = 2; size2 <= 8; size2 <<= 1 ) + { + for( size3 = 2; size3 <= 8; size3 <<= 1 ) + { + // Loop through 4 type combinations for each size combination + int n; + for (n=0; n<4; n++) { + type1 = (int)get_random_float(0,4, seed); + type2 = (int)get_random_float(0,4, seed); + type3 = (int)get_random_float(0,4, seed); + + + log_info( "\ttesting %s%d, %s%d, %s%d...\n", + get_explicit_type_name( types[ type1 ] ), size1, + get_explicit_type_name( types[ type2 ] ), size2, + get_explicit_type_name( types[ type3 ] ), size3 ); + + if( test_multi_arg_set( device, context, queue, + types[ type1 ], size1, + types[ type2 ], size2, + types[ type3 ], size3, seed ) ) + return -1; + } + } + } + } + return 0; +} + + + + diff --git a/test_conformance/compatibility/test_conformance/api/test_kernels.c b/test_conformance/compatibility/test_conformance/api/test_kernels.c new file mode 100644 index 00000000..9cfbca27 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/test_kernels.c @@ -0,0 +1,704 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" + +extern cl_uint gRandomSeed; + +const char *sample_single_test_kernel[] = { +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n" }; + +const char *sample_struct_test_kernel[] = { +"typedef struct {\n" +"__global int *A;\n" +"__global int *B;\n" +"} input_pair_t;\n" +"\n" +"__kernel void sample_test(__global input_pair_t *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = src->A[tid] + src->B[tid];\n" +"\n" +"}\n" }; + +const char *sample_struct_array_test_kernel[] = { +"typedef struct {\n" +"int A;\n" +"int B;\n" +"} input_pair_t;\n" +"\n" +"__kernel void sample_test(__global input_pair_t *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = src[tid].A + src[tid].B;\n" +"\n" +"}\n" }; + +const char *sample_const_test_kernel[] = { +"__kernel void sample_test(__constant int *src1, __constant int *src2, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = src1[tid] + src2[tid];\n" +"\n" +"}\n" }; + +const char *sample_const_global_test_kernel[] = { +"__constant int addFactor = 1024;\n" +"__kernel void sample_test(__global int *src1, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = src1[tid] + addFactor;\n" +"\n" +"}\n" }; + +const char *sample_two_kernel_program[] = { +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n", +"__kernel void sample_test2(__global int *src, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (float)src[tid];\n" +"\n" +"}\n" }; + + + + +int test_get_kernel_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program, testProgram; + cl_context testContext; + cl_kernel kernel; + cl_char name[ 512 ]; + cl_uint numArgs, numInstances; + size_t paramSize; + + + /* Create reference */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_single_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_FUNCTION_NAME, NULL, 0, ¶mSize ); + test_error( error, "Unable to get kernel function name param size" ); + if( paramSize != strlen( "sample_test" ) + 1 ) + { + log_error( "ERROR: Kernel function name param returns invalid size (expected %d, got %d)\n", (int)strlen( "sample_test" ) + 1, (int)paramSize ); + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_FUNCTION_NAME, sizeof( name ), name, NULL ); + test_error( error, "Unable to get kernel function name" ); + if( strcmp( (char *)name, "sample_test" ) != 0 ) + { + log_error( "ERROR: Kernel function name returned invalid value (expected sample_test, got %s)\n", (char *)name ); + return -1; + } + + + error = clGetKernelInfo( kernel, CL_KERNEL_NUM_ARGS, 0, NULL, ¶mSize ); + test_error( error, "Unable to get kernel arg count param size" ); + if( paramSize != sizeof( numArgs ) ) + { + log_error( "ERROR: Kernel arg count param returns invalid size (expected %d, got %d)\n", (int)sizeof( numArgs ), (int)paramSize ); + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_NUM_ARGS, sizeof( numArgs ), &numArgs, NULL ); + test_error( error, "Unable to get kernel arg count" ); + if( numArgs != 2 ) + { + log_error( "ERROR: Kernel arg count returned invalid value (expected %d, got %d)\n", 2, numArgs ); + return -1; + } + + + error = clGetKernelInfo( kernel, CL_KERNEL_REFERENCE_COUNT, 0, NULL, ¶mSize ); + test_error( error, "Unable to get kernel reference count param size" ); + if( paramSize != sizeof( numInstances ) ) + { + log_error( "ERROR: Kernel reference count param returns invalid size (expected %d, got %d)\n", (int)sizeof( numInstances ), (int)paramSize ); + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_REFERENCE_COUNT, sizeof( numInstances ), &numInstances, NULL ); + test_error( error, "Unable to get kernel reference count" ); + + + error = clGetKernelInfo( kernel, CL_KERNEL_PROGRAM, NULL, 0, ¶mSize ); + test_error( error, "Unable to get kernel program param size" ); + if( paramSize != sizeof( testProgram ) ) + { + log_error( "ERROR: Kernel program param returns invalid size (expected %d, got %d)\n", (int)sizeof( testProgram ), (int)paramSize ); + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_PROGRAM, sizeof( testProgram ), &testProgram, NULL ); + test_error( error, "Unable to get kernel program" ); + if( testProgram != program ) + { + log_error( "ERROR: Kernel program returned invalid value (expected %p, got %p)\n", program, testProgram ); + return -1; + } + + error = clGetKernelInfo( kernel, CL_KERNEL_CONTEXT, sizeof( testContext ), &testContext, NULL ); + test_error( error, "Unable to get kernel context" ); + if( testContext != context ) + { + log_error( "ERROR: Kernel context returned invalid value (expected %p, got %p)\n", context, testContext ); + return -1; + } + + /* Release memory */ + clReleaseKernel( kernel ); + clReleaseProgram( program ); + return 0; +} + +int test_execute_kernel_local_sizes(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + size_t threads[1], localThreads[1]; + cl_float inputData[100]; + cl_int outputData[100]; + RandomSeed seed( gRandomSeed ); + int i; + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_single_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 100, NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 100, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Write some test data */ + memset( outputData, 0, sizeof( outputData ) ); + + for (i=0; i<100; i++) + inputData[i] = get_random_float(-(float) 0x7fffffff, (float) 0x7fffffff, seed); + + error = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, sizeof(cl_float)*100, (void *)inputData, 0, NULL, NULL); + test_error( error, "Unable to set testing kernel data" ); + + /* Set the arguments */ + error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set kernel arguments" ); + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)100; + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(cl_int)*100, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<100; i++) + { + if (outputData[i] != (int)inputData[i]) + { + log_error( "ERROR: Data did not verify on first pass!\n" ); + return -1; + } + } + + /* Try again */ + if( localThreads[0] > 1 ) + localThreads[0] /= 2; + while( localThreads[0] > 1 && 0 != threads[0] % localThreads[0] ) + localThreads[0]--; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(cl_int)*100, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<100; i++) + { + if (outputData[i] != (int)inputData[i]) + { + log_error( "ERROR: Data did not verify on first pass!\n" ); + return -1; + } + } + + /* And again */ + if( localThreads[0] > 1 ) + localThreads[0] /= 2; + while( localThreads[0] > 1 && 0 != threads[0] % localThreads[0] ) + localThreads[0]--; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(cl_int)*100, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<100; i++) + { + if (outputData[i] != (int)inputData[i]) + { + log_error( "ERROR: Data did not verify on first pass!\n" ); + return -1; + } + } + + /* One more time */ + localThreads[0] = (unsigned int)1; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(cl_int)*100, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<100; i++) + { + if (outputData[i] != (int)inputData[i]) + { + log_error( "ERROR: Data did not verify on first pass!\n" ); + return -1; + } + } + + return 0; +} + +int test_set_kernel_arg_by_index(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + size_t threads[1], localThreads[1]; + cl_float inputData[10]; + cl_int outputData[10]; + RandomSeed seed( gRandomSeed ); + int i; + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_single_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Write some test data */ + memset( outputData, 0, sizeof( outputData ) ); + + for (i=0; i<10; i++) + inputData[i] = get_random_float(-(float) 0x7fffffff, (float) 0x7fffffff, seed); + + error = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, sizeof(cl_float)*10, (void *)inputData, 0, NULL, NULL); + test_error( error, "Unable to set testing kernel data" ); + + /* Test setting the arguments by index manually */ + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)10; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(cl_int)*10, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<10; i++) + { + if (outputData[i] != (int)inputData[i]) + { + log_error( "ERROR: Data did not verify on first pass!\n" ); + return -1; + } + } + + return 0; +} + +int test_set_kernel_arg_struct(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + cl_kernel kernel; + void *args[2]; + cl_mem outStream; + size_t threads[1], localThreads[1]; + cl_int outputData[10]; + int i; + cl_int randomTestDataA[10], randomTestDataB[10]; + MTdata d; + + struct img_pair_t + { + cl_mem streamA; + cl_mem streamB; + } image_pair; + + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_struct_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + d = init_genrand( gRandomSeed ); + for( i = 0; i < 10; i++ ) + { + randomTestDataA[i] = (cl_int)genrand_int32(d); + randomTestDataB[i] = (cl_int)genrand_int32(d); + } + free_mtdata(d); d = NULL; + + image_pair.streamA = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_int) * 10, randomTestDataA, &error); + test_error( error, "Creating test array failed" ); + image_pair.streamB = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_int) * 10, randomTestDataB, &error); + test_error( error, "Creating test array failed" ); + outStream = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Set the arguments */ + args[0] = &image_pair; + args[1] = outStream; + + error = clSetKernelArg(kernel, 0, sizeof( image_pair ), &image_pair); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( cl_mem ), &args[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)10; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, outStream, CL_TRUE, 0, sizeof(cl_int)*10, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<10; i++) + { + if (outputData[i] != randomTestDataA[i] + randomTestDataB[i]) + { + log_error( "ERROR: Data did not verify!\n" ); + return -1; + } + } + + + clReleaseMemObject( image_pair.streamA ); + clReleaseMemObject( image_pair.streamB ); + clReleaseMemObject( outStream ); + clReleaseKernel( kernel ); + clReleaseProgram( program ); + + return 0; +} + +int test_set_kernel_arg_constant(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[3]; + size_t threads[1], localThreads[1]; + cl_int outputData[10]; + int i; + cl_int randomTestDataA[10], randomTestDataB[10]; + cl_ulong maxSize; + MTdata d; + + /* Verify our test buffer won't be bigger than allowed */ + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof( maxSize ), &maxSize, 0 ); + test_error( error, "Unable to get max constant buffer size" ); + if( maxSize < sizeof( cl_int ) * 10 ) + { + log_error( "ERROR: Unable to test constant argument to kernel: max size of constant buffer is reported as %d!\n", (int)maxSize ); + return -1; + } + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_const_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + d = init_genrand( gRandomSeed ); + for( i = 0; i < 10; i++ ) + { + randomTestDataA[i] = (cl_int)genrand_int32(d) & 0xffffff; /* Make sure values are positive, just so we don't have to */ + randomTestDataB[i] = (cl_int)genrand_int32(d) & 0xffffff; /* deal with overflow on the verification */ + } + free_mtdata(d); d = NULL; + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_int) * 10, randomTestDataA, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_int) * 10, randomTestDataB, &error); + test_error( error, "Creating test array failed" ); + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Set the arguments */ + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 2, sizeof( streams[2] ), &streams[2]); + test_error( error, "Unable to set indexed kernel arguments" ); + + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)10; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[2], CL_TRUE, 0, sizeof(cl_int)*10, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<10; i++) + { + if (outputData[i] != randomTestDataA[i] + randomTestDataB[i]) + { + log_error( "ERROR: Data sample %d did not verify! %d does not match %d + %d (%d)\n", i, outputData[i], randomTestDataA[i], randomTestDataB[i], ( randomTestDataA[i] + randomTestDataB[i] ) ); + return -1; + } + } + + return 0; +} + +int test_set_kernel_arg_struct_array(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + size_t threads[1], localThreads[1]; + cl_int outputData[10]; + int i; + MTdata d; + + typedef struct img_pair_type + { + int A; + int B; + } image_pair_t; + + image_pair_t image_pair[ 10 ]; + + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_struct_array_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + d = init_genrand( gRandomSeed ); + for( i = 0; i < 10; i++ ) + { + image_pair[i].A = (cl_int)genrand_int32(d); + image_pair[i].A = (cl_int)genrand_int32(d); + } + free_mtdata(d); d = NULL; + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(image_pair_t) * 10, (void *)image_pair, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Set the arguments */ + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)10; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(cl_int)*10, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<10; i++) + { + if (outputData[i] != image_pair[i].A + image_pair[i].B) + { + log_error( "ERROR: Data did not verify!\n" ); + return -1; + } + } + + return 0; +} + +int test_create_kernels_in_program(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + cl_kernel kernel[3]; + unsigned int kernelCount; + + /* Create a test program */ + program = clCreateProgramWithSource( context, 2, sample_two_kernel_program, NULL, &error); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create test program!\n" ); + return -1; + } + + /* Build */ + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build test program" ); + + /* Try getting the kernel count */ + error = clCreateKernelsInProgram( program, 0, NULL, &kernelCount ); + test_error( error, "Unable to get kernel count for built program" ); + if( kernelCount != 2 ) + { + log_error( "ERROR: Returned kernel count from clCreateKernelsInProgram is incorrect! (got %d, expected 2)\n", kernelCount ); + return -1; + } + + /* Try actually getting the kernels */ + error = clCreateKernelsInProgram( program, 2, kernel, NULL ); + test_error( error, "Unable to get kernels for built program" ); + clReleaseKernel( kernel[0] ); + clReleaseKernel( kernel[1] ); + + clReleaseProgram( program ); + return 0; +} + +int test_kernel_global_constant(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + size_t threads[1], localThreads[1]; + cl_int outputData[10]; + int i; + cl_int randomTestDataA[10]; + MTdata d; + + + /* Create a kernel to test with */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_const_global_test_kernel, "sample_test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + d = init_genrand( gRandomSeed ); + for( i = 0; i < 10; i++ ) + { + randomTestDataA[i] = (cl_int)genrand_int32(d) & 0xffff; /* Make sure values are positive and small, just so we don't have to */ + } + free_mtdata(d); d = NULL; + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_int) * 10, randomTestDataA, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Set the arguments */ + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + + + /* Test running the kernel and verifying it */ + threads[0] = (size_t)10; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(cl_int)*10, (void *)outputData, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + for (i=0; i<10; i++) + { + if (outputData[i] != randomTestDataA[i] + 1024) + { + log_error( "ERROR: Data sample %d did not verify! %d does not match %d + 1024 (%d)\n", i, outputData[i], randomTestDataA[i], ( randomTestDataA[i] + 1024 ) ); + return -1; + } + } + + return 0; +} + + + diff --git a/test_conformance/compatibility/test_conformance/api/test_mem_object_info.cpp b/test_conformance/compatibility/test_conformance/api/test_mem_object_info.cpp new file mode 100644 index 00000000..b4e14569 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/test_mem_object_info.cpp @@ -0,0 +1,750 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/testHarness.h" + +extern cl_uint gRandomSeed; + + +#define TEST_MEM_OBJECT_PARAM( mem, paramName, val, expected, name, type, cast ) \ +error = clGetMemObjectInfo( mem, paramName, sizeof( val ), &val, &size ); \ +test_error( error, "Unable to get mem object " name ); \ +if( val != expected ) \ +{ \ +log_error( "ERROR: Mem object " name " did not validate! (expected " type ", got " type " from %s:%d)\n", \ +expected, (cast)val, __FILE__, __LINE__ ); \ +return -1; \ +} \ +if( size != sizeof( val ) ) \ +{ \ +log_error( "ERROR: Returned size of mem object " name " does not validate! (expected %d, got %d from %s:%d)\n", \ +(int)sizeof( val ), (int)size , __FILE__, __LINE__ ); \ +return -1; \ +} + +static void CL_CALLBACK mem_obj_destructor_callback( cl_mem, void * data ) +{ + free( data ); +} + +static unsigned int +get_image_dim(MTdata *d, unsigned int mod) +{ + unsigned int val = 0; + + do + { + val = (unsigned int)genrand_int32(*d) % mod; + } while (val == 0); + + return val; +} + + +int test_get_buffer_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ) +{ + int error; + size_t size; + void * buffer = NULL; + + clMemWrapper bufferObject; + clMemWrapper subBufferObject; + + cl_mem_flags bufferFlags[] = { + CL_MEM_READ_WRITE, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_READ_ONLY, + CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_WRITE_ONLY, + CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + }; + + cl_mem_flags subBufferFlags[] = { + CL_MEM_READ_WRITE, + CL_MEM_READ_ONLY, + CL_MEM_WRITE_ONLY, + 0, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_READ_ONLY | 0, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_WRITE_ONLY | 0, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_NO_ACCESS | 0, + }; + + + // Get the address alignment, so we can make sure the sub-buffer test later works properly. + cl_uint addressAlignBits; + error = clGetDeviceInfo( deviceID, CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof(addressAlignBits), &addressAlignBits, NULL ); + + size_t addressAlign = addressAlignBits/8; + if ( addressAlign < 128 ) + { + addressAlign = 128; + } + + for ( unsigned int i = 0; i < sizeof(bufferFlags) / sizeof(cl_mem_flags); ++i ) + { + //printf("@@@ bufferFlags[%u]=0x%x\n", i, bufferFlags[ i ]); + if ( bufferFlags[ i ] & CL_MEM_USE_HOST_PTR ) + { + // Create a buffer object to test against. + buffer = malloc( addressAlign * 4 ); + bufferObject = clCreateBuffer( context, bufferFlags[ i ], addressAlign * 4, buffer, &error ); + if ( error ) + { + free( buffer ); + test_error( error, "Unable to create buffer (CL_MEM_USE_HOST_PTR) to test with" ); + } + + // Make sure buffer is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( bufferObject, mem_obj_destructor_callback, buffer ); + test_error( error, "Unable to set mem object destructor callback" ); + + void * ptr; + TEST_MEM_OBJECT_PARAM( bufferObject, CL_MEM_HOST_PTR, ptr, buffer, "host pointer", "%p", void * ) + } + else if ( (bufferFlags[ i ] & CL_MEM_ALLOC_HOST_PTR) && (bufferFlags[ i ] & CL_MEM_COPY_HOST_PTR) ) + { + // Create a buffer object to test against. + buffer = malloc( addressAlign * 4 ); + bufferObject = clCreateBuffer( context, bufferFlags[ i ], addressAlign * 4, buffer, &error ); + if ( error ) + { + free( buffer ); + test_error( error, "Unable to create buffer (CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR) to test with" ); + } + + // Make sure buffer is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( bufferObject, mem_obj_destructor_callback, buffer ); + test_error( error, "Unable to set mem object destructor callback" ); + } + else if ( bufferFlags[ i ] & CL_MEM_ALLOC_HOST_PTR ) + { + // Create a buffer object to test against. + bufferObject = clCreateBuffer( context, bufferFlags[ i ], addressAlign * 4, NULL, &error ); + test_error( error, "Unable to create buffer (CL_MEM_ALLOC_HOST_PTR) to test with" ); + } + else if ( bufferFlags[ i ] & CL_MEM_COPY_HOST_PTR ) + { + // Create a buffer object to test against. + buffer = malloc( addressAlign * 4 ); + bufferObject = clCreateBuffer( context, bufferFlags[ i ], addressAlign * 4, buffer, &error ); + if ( error ) + { + free( buffer ); + test_error( error, "Unable to create buffer (CL_MEM_COPY_HOST_PTR) to test with" ); + } + + // Make sure buffer is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( bufferObject, mem_obj_destructor_callback, buffer ); + test_error( error, "Unable to set mem object destructor callback" ); + } + else + { + // Create a buffer object to test against. + bufferObject = clCreateBuffer( context, bufferFlags[ i ], addressAlign * 4, NULL, &error ); + test_error( error, "Unable to create buffer to test with" ); + } + + // Perform buffer object queries. + cl_mem_object_type type; + TEST_MEM_OBJECT_PARAM( bufferObject, CL_MEM_TYPE, type, CL_MEM_OBJECT_BUFFER, "type", "%d", int ) + + cl_mem_flags flags; + TEST_MEM_OBJECT_PARAM( bufferObject, CL_MEM_FLAGS, flags, (unsigned int)bufferFlags[ i ], "flags", "%d", unsigned int ) + + size_t sz; + TEST_MEM_OBJECT_PARAM( bufferObject, CL_MEM_SIZE, sz, (size_t)( addressAlign * 4 ), "size", "%ld", size_t ) + + cl_uint mapCount; + error = clGetMemObjectInfo( bufferObject, CL_MEM_MAP_COUNT, sizeof( mapCount ), &mapCount, &size ); + test_error( error, "Unable to get mem object map count" ); + if( size != sizeof( mapCount ) ) + { + log_error( "ERROR: Returned size of mem object map count does not validate! (expected %d, got %d from %s:%d)\n", + (int)sizeof( mapCount ), (int)size, __FILE__, __LINE__ ); + return -1; + } + + cl_uint refCount; + error = clGetMemObjectInfo( bufferObject, CL_MEM_REFERENCE_COUNT, sizeof( refCount ), &refCount, &size ); + test_error( error, "Unable to get mem object reference count" ); + if( size != sizeof( refCount ) ) + { + log_error( "ERROR: Returned size of mem object reference count does not validate! (expected %d, got %d from %s:%d)\n", + (int)sizeof( refCount ), (int)size, __FILE__, __LINE__ ); + return -1; + } + + cl_context otherCtx; + TEST_MEM_OBJECT_PARAM( bufferObject, CL_MEM_CONTEXT, otherCtx, context, "context", "%p", cl_context ) + + cl_mem origObj; + TEST_MEM_OBJECT_PARAM( bufferObject, CL_MEM_ASSOCIATED_MEMOBJECT, origObj, (void *)NULL, "associated mem object", "%p", void * ) + + size_t offset; + TEST_MEM_OBJECT_PARAM( bufferObject, CL_MEM_OFFSET, offset, 0L, "offset", "%ld", size_t ) + + cl_buffer_region region; + region.origin = addressAlign; + region.size = addressAlign; + + // Loop over possible sub-buffer objects to create. + for ( unsigned int j = 0; j < sizeof(subBufferFlags) / sizeof(cl_mem_flags); ++j ) + { + if ( subBufferFlags[ j ] & CL_MEM_READ_WRITE ) + { + if ( !(bufferFlags[ i ] & CL_MEM_READ_WRITE) ) + continue; // Buffer must be read_write for sub-buffer to be read_write. + } + if ( subBufferFlags[ j ] & CL_MEM_READ_ONLY ) + { + if ( !(bufferFlags[ i ] & CL_MEM_READ_WRITE) && !(bufferFlags[ i ] & CL_MEM_READ_ONLY) ) + continue; // Buffer must be read_write or read_only for sub-buffer to be read_only + } + if ( subBufferFlags[ j ] & CL_MEM_WRITE_ONLY ) + { + if ( !(bufferFlags[ i ] & CL_MEM_READ_WRITE) && !(bufferFlags[ i ] & CL_MEM_WRITE_ONLY) ) + continue; // Buffer must be read_write or write_only for sub-buffer to be write_only + } + if ( subBufferFlags[ j ] & CL_MEM_HOST_READ_ONLY ) + { + if ( (bufferFlags[ i ] & CL_MEM_HOST_NO_ACCESS) || (bufferFlags[ i ] & CL_MEM_HOST_WRITE_ONLY) ) + continue; // Buffer must be host all access or host read_only for sub-buffer to be host read_only + } + if ( subBufferFlags[ j ] & CL_MEM_HOST_WRITE_ONLY ) + { + if ( (bufferFlags[ i ] & CL_MEM_HOST_NO_ACCESS) || (bufferFlags[ i ] & CL_MEM_HOST_READ_ONLY) ) + continue; // Buffer must be host all access or host write_only for sub-buffer to be host write_only + } + //printf("@@@ bufferFlags[%u]=0x%x subBufferFlags[%u]=0x%x\n", i, bufferFlags[ i ], j, subBufferFlags[ j ]); + + subBufferObject = clCreateSubBuffer( bufferObject, subBufferFlags[ j ], CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error ); + test_error( error, "Unable to create sub-buffer to test against" ); + + // Perform sub-buffer object queries. + cl_mem_object_type type; + TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_TYPE, type, CL_MEM_OBJECT_BUFFER, "type", "%d", int ) + + cl_mem_flags flags; + cl_mem_flags inheritedFlags = subBufferFlags[ j ]; + if ( (subBufferFlags[ j ] & (CL_MEM_READ_WRITE | CL_MEM_READ_ONLY | CL_MEM_WRITE_ONLY)) == 0 ) + { + inheritedFlags |= bufferFlags[ i ] & (CL_MEM_READ_WRITE | CL_MEM_READ_ONLY | CL_MEM_WRITE_ONLY); + } + inheritedFlags |= bufferFlags[ i ] & (CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR); + if ( (subBufferFlags[ j ] & (CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS)) == 0) + { + inheritedFlags |= bufferFlags[ i ] & (CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS); + } + TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_FLAGS, flags, (unsigned int)inheritedFlags, "flags", "%d", unsigned int ) + + TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_SIZE, sz, (size_t)( addressAlign ), "size", "%ld", size_t ) + + if ( bufferFlags[ i ] & CL_MEM_USE_HOST_PTR ) + { + void * ptr; + void * offsetInBuffer = (char *)buffer + addressAlign; + + TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_HOST_PTR, ptr, offsetInBuffer, "host pointer", "%p", void * ) + } + + cl_uint mapCount; + error = clGetMemObjectInfo( subBufferObject, CL_MEM_MAP_COUNT, sizeof( mapCount ), &mapCount, &size ); + test_error( error, "Unable to get mem object map count" ); + if( size != sizeof( mapCount ) ) + { + log_error( "ERROR: Returned size of mem object map count does not validate! (expected %d, got %d from %s:%d)\n", + (int)sizeof( mapCount ), (int)size, __FILE__, __LINE__ ); + return -1; + } + + cl_uint refCount; + error = clGetMemObjectInfo( subBufferObject, CL_MEM_REFERENCE_COUNT, sizeof( refCount ), &refCount, &size ); + test_error( error, "Unable to get mem object reference count" ); + if( size != sizeof( refCount ) ) + { + log_error( "ERROR: Returned size of mem object reference count does not validate! (expected %d, got %d from %s:%d)\n", + (int)sizeof( refCount ), (int)size, __FILE__, __LINE__ ); + return -1; + } + + cl_context otherCtx; + TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_CONTEXT, otherCtx, context, "context", "%p", cl_context ) + + TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_ASSOCIATED_MEMOBJECT, origObj, (cl_mem)bufferObject, "associated mem object", "%p", void * ) + + TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_OFFSET, offset, (size_t)( addressAlign ), "offset", "%ld", size_t ) + + clReleaseMemObject( subBufferObject ); + subBufferObject = NULL; + + } + + clReleaseMemObject( bufferObject ); + bufferObject = NULL; + } + + return CL_SUCCESS; +} + + +int test_get_imageObject_info( cl_mem * image, cl_mem_flags objectFlags, cl_image_desc *imageInfo, cl_image_format *imageFormat, size_t pixelSize, cl_context context ) +{ + int error; + size_t size; + cl_mem_object_type type; + cl_mem_flags flags; + cl_uint mapCount; + cl_uint refCount; + size_t rowPitchMultiplier; + size_t slicePitchMultiplier; + cl_context otherCtx; + size_t offset; + size_t sz; + + TEST_MEM_OBJECT_PARAM( *image, CL_MEM_TYPE, type, imageInfo->image_type, "type", "%d", int ) + + TEST_MEM_OBJECT_PARAM( *image, CL_MEM_FLAGS, flags, (unsigned int)objectFlags, "flags", "%d", unsigned int ) + + error = clGetMemObjectInfo( *image, CL_MEM_SIZE, sizeof( sz ), &sz, NULL ); + test_error( error, "Unable to get mem size" ); + + // The size returned is not constrained by the spec. + + error = clGetMemObjectInfo( *image, CL_MEM_MAP_COUNT, sizeof( mapCount ), &mapCount, &size ); + test_error( error, "Unable to get mem object map count" ); + if( size != sizeof( mapCount ) ) + { + log_error( "ERROR: Returned size of mem object map count does not validate! (expected %d, got %d from %s:%d)\n", + (int)sizeof( mapCount ), (int)size, __FILE__, __LINE__ ); + return -1; + } + + error = clGetMemObjectInfo( *image, CL_MEM_REFERENCE_COUNT, sizeof( refCount ), &refCount, &size ); + test_error( error, "Unable to get mem object reference count" ); + if( size != sizeof( refCount ) ) + { + log_error( "ERROR: Returned size of mem object reference count does not validate! (expected %d, got %d from %s:%d)\n", + (int)sizeof( refCount ), (int)size, __FILE__, __LINE__ ); + return -1; + } + + TEST_MEM_OBJECT_PARAM( *image, CL_MEM_CONTEXT, otherCtx, context, "context", "%p", cl_context ) + + TEST_MEM_OBJECT_PARAM( *image, CL_MEM_OFFSET, offset, 0L, "offset", "%ld", size_t ) + + return CL_SUCCESS; +} + + +int test_get_image_info( cl_device_id deviceID, cl_context context, cl_mem_object_type type ) +{ + int error; + size_t size; + void * image = NULL; + + cl_mem imageObject; + cl_image_desc imageInfo; + + cl_mem_flags imageFlags[] = { + CL_MEM_READ_WRITE, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_READ_ONLY, + CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_WRITE_ONLY, + CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + }; + MTdata d; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ) + + cl_image_format imageFormat; + size_t pixelSize = 4; + + imageFormat.image_channel_order = CL_RGBA; + imageFormat.image_channel_data_type = CL_UNORM_INT8; + + imageInfo.image_width = imageInfo.image_height = imageInfo.image_depth = 1; + imageInfo.image_array_size = 0; + imageInfo.num_mip_levels = imageInfo.num_samples = 0; + imageInfo.buffer = NULL; + + d = init_genrand( gRandomSeed ); + + for ( unsigned int i = 0; i < sizeof(imageFlags) / sizeof(cl_mem_flags); ++i ) + { + imageInfo.image_row_pitch = 0; + imageInfo.image_slice_pitch = 0; + + switch (type) + { + case CL_MEM_OBJECT_IMAGE1D: + imageInfo.image_width = get_image_dim(&d, 1023); + imageInfo.image_type = CL_MEM_OBJECT_IMAGE1D; + break; + + case CL_MEM_OBJECT_IMAGE2D: + imageInfo.image_width = get_image_dim(&d, 1023); + imageInfo.image_height = get_image_dim(&d, 1023); + imageInfo.image_type = CL_MEM_OBJECT_IMAGE2D; + break; + + case CL_MEM_OBJECT_IMAGE3D: + imageInfo.image_width = get_image_dim(&d, 127); + imageInfo.image_height = get_image_dim(&d, 127); + imageInfo.image_depth = get_image_dim(&d, 127); + imageInfo.image_type = CL_MEM_OBJECT_IMAGE3D; + break; + + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + imageInfo.image_width = get_image_dim(&d, 1023); + imageInfo.image_array_size = get_image_dim(&d, 1023); + imageInfo.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + break; + + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + imageInfo.image_width = get_image_dim(&d, 255); + imageInfo.image_height = get_image_dim(&d, 255); + imageInfo.image_array_size = get_image_dim(&d, 255); + imageInfo.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + break; + } + + if ( imageFlags[i] & CL_MEM_USE_HOST_PTR ) + { + // Create an image object to test against. + image = malloc( imageInfo.image_width * imageInfo.image_height * imageInfo.image_depth * pixelSize * + ((imageInfo.image_array_size == 0) ? 1 : imageInfo.image_array_size) ); + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, image, &error ); + if ( error ) + { + free( image ); + test_error( error, "Unable to create image with (CL_MEM_USE_HOST_PTR) to test with" ); + } + + // Make sure image is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( imageObject, mem_obj_destructor_callback, image ); + test_error( error, "Unable to set mem object destructor callback" ); + + void * ptr; + TEST_MEM_OBJECT_PARAM( imageObject, CL_MEM_HOST_PTR, ptr, image, "host pointer", "%p", void * ) + int ret = test_get_imageObject_info( &imageObject, imageFlags[i], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + // release image object + clReleaseMemObject(imageObject); + + // Try again with non-zero rowPitch. + imageInfo.image_row_pitch = imageInfo.image_width * pixelSize; + switch (type) + { + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + case CL_MEM_OBJECT_IMAGE3D: + imageInfo.image_slice_pitch = imageInfo.image_row_pitch * imageInfo.image_height; + break; + } + + image = malloc( imageInfo.image_width * imageInfo.image_height * imageInfo.image_depth * pixelSize * + ((imageInfo.image_array_size == 0) ? 1 : imageInfo.image_array_size) ); + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, image, &error ); + if ( error ) + { + free( image ); + test_error( error, "Unable to create image2d (CL_MEM_USE_HOST_PTR) to test with" ); + } + + // Make sure image2d is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( imageObject, mem_obj_destructor_callback, image ); + test_error( error, "Unable to set mem object destructor callback" ); + + TEST_MEM_OBJECT_PARAM( imageObject, CL_MEM_HOST_PTR, ptr, image, "host pointer", "%p", void * ) + ret = test_get_imageObject_info( &imageObject, imageFlags[i], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + } + else if ( (imageFlags[i] & CL_MEM_ALLOC_HOST_PTR) && (imageFlags[i] & CL_MEM_COPY_HOST_PTR) ) + { + // Create an image object to test against. + image = malloc( imageInfo.image_width * imageInfo.image_height * imageInfo.image_depth * pixelSize * + ((imageInfo.image_array_size == 0) ? 1 : imageInfo.image_array_size) ); + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, image, &error ); + if ( error ) + { + free( image ); + test_error( error, "Unable to create image with (CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR) to test with" ); + } + + // Make sure image is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( imageObject, mem_obj_destructor_callback, image ); + test_error( error, "Unable to set mem object destructor callback" ); + int ret = test_get_imageObject_info( &imageObject, imageFlags[ i ], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + // release image object + clReleaseMemObject(imageObject); + + // Try again with non-zero rowPitch. + imageInfo.image_row_pitch = imageInfo.image_width * pixelSize; + switch (type) + { + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + case CL_MEM_OBJECT_IMAGE3D: + imageInfo.image_slice_pitch = imageInfo.image_row_pitch * imageInfo.image_height; + break; + } + + image = malloc( imageInfo.image_width * imageInfo.image_height * imageInfo.image_depth * pixelSize * + ((imageInfo.image_array_size == 0) ? 1 : imageInfo.image_array_size) ); + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, image, &error ); + if ( error ) + { + free( image ); + test_error( error, "Unable to create image with (CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR) to test with" ); + } + + // Make sure image is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( imageObject, mem_obj_destructor_callback, image ); + test_error( error, "Unable to set mem object destructor callback" ); + ret = test_get_imageObject_info( &imageObject, imageFlags[i], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + } + else if ( imageFlags[i] & CL_MEM_ALLOC_HOST_PTR ) + { + // Create an image object to test against. + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, NULL, &error ); + test_error( error, "Unable to create image with (CL_MEM_ALLOC_HOST_PTR) to test with" ); + int ret = test_get_imageObject_info( &imageObject, imageFlags[i], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + } + else if ( imageFlags[i] & CL_MEM_COPY_HOST_PTR ) + { + // Create an image object to test against. + image = malloc( imageInfo.image_width * imageInfo.image_height * imageInfo.image_depth * pixelSize * + ((imageInfo.image_array_size == 0) ? 1 : imageInfo.image_array_size) ); + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, image, &error ); + if ( error ) + { + free( image ); + test_error( error, "Unable to create image with (CL_MEM_COPY_HOST_PTR) to test with" ); + } + + // Make sure image is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( imageObject, mem_obj_destructor_callback, image ); + test_error( error, "Unable to set mem object destructor callback" ); + int ret = test_get_imageObject_info( &imageObject, imageFlags[i], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + clReleaseMemObject(imageObject); + + // Try again with non-zero rowPitch. + imageInfo.image_row_pitch = imageInfo.image_width * pixelSize; + switch (type) + { + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + case CL_MEM_OBJECT_IMAGE3D: + imageInfo.image_slice_pitch = imageInfo.image_row_pitch * imageInfo.image_height; + break; + } + + image = malloc( imageInfo.image_width * imageInfo.image_height * imageInfo.image_depth * pixelSize * + ((imageInfo.image_array_size == 0) ? 1 : imageInfo.image_array_size) ); + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, image, &error ); + if ( error ) + { + free( image ); + test_error( error, "Unable to create image with (CL_MEM_COPY_HOST_PTR) to test with" ); + } + + // Make sure image is cleaned up appropriately if we encounter an error in the rest of the calls. + error = clSetMemObjectDestructorCallback( imageObject, mem_obj_destructor_callback, image ); + test_error( error, "Unable to set mem object destructor callback" ); + ret = test_get_imageObject_info( &imageObject, imageFlags[i], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + } + else + { + // Create an image object to test against. + imageObject = clCreateImage( context, imageFlags[i], &imageFormat, &imageInfo, NULL, &error ); + test_error( error, "Unable to create image to test with" ); + int ret = test_get_imageObject_info( &imageObject, imageFlags[i], &imageInfo, &imageFormat, pixelSize, context ); + if (ret) + return ret; + + } + + clReleaseMemObject( imageObject ); + } + + return CL_SUCCESS; +} + + +int test_get_image2d_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ) +{ + return test_get_image_info(deviceID, context, CL_MEM_OBJECT_IMAGE2D); +} + +int test_get_image3d_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ) +{ + return test_get_image_info(deviceID, context, CL_MEM_OBJECT_IMAGE3D); +} + +int test_get_image1d_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ) +{ + return test_get_image_info(deviceID, context, CL_MEM_OBJECT_IMAGE1D); +} + +int test_get_image1d_array_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ) +{ + return test_get_image_info(deviceID, context, CL_MEM_OBJECT_IMAGE1D_ARRAY); +} + +int test_get_image2d_array_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ) +{ + return test_get_image_info(deviceID, context, CL_MEM_OBJECT_IMAGE2D_ARRAY); +} + + diff --git a/test_conformance/compatibility/test_conformance/api/test_mem_objects.cpp b/test_conformance/compatibility/test_conformance/api/test_mem_objects.cpp new file mode 100644 index 00000000..b0dc99d4 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/test_mem_objects.cpp @@ -0,0 +1,108 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +static volatile cl_int sDestructorIndex; + +void CL_CALLBACK mem_destructor_callback( cl_mem memObject, void * userData ) +{ + int * userPtr = (int *)userData; + + // ordering of callbacks is guaranteed, meaning we don't need to do atomic operation here + *userPtr = ++sDestructorIndex; +} + +#ifndef ABS +#define ABS( x ) ( ( x < 0 ) ? -x : x ) +#endif + +int test_mem_object_destructor_callback_single( clMemWrapper &memObject ) +{ + cl_int error; + int i; + + // Set up some variables to catch the order in which callbacks are called + volatile int callbackOrders[ 3 ] = { 0, 0, 0 }; + sDestructorIndex = 0; + + // Set up the callbacks + error = clSetMemObjectDestructorCallback( memObject, mem_destructor_callback, (void*) &callbackOrders[ 0 ] ); + test_error( error, "Unable to set destructor callback" ); + + error = clSetMemObjectDestructorCallback( memObject, mem_destructor_callback, (void*) &callbackOrders[ 1 ] ); + test_error( error, "Unable to set destructor callback" ); + + error = clSetMemObjectDestructorCallback( memObject, mem_destructor_callback, (void*) &callbackOrders[ 2 ] ); + test_error( error, "Unable to set destructor callback" ); + + // Now release the buffer, which SHOULD call the callbacks + error = clReleaseMemObject( memObject ); + test_error( error, "Unable to release test buffer" ); + + // Note: since we manually released the mem wrapper, we need to set it to NULL to prevent a double-release + memObject = NULL; + + // At this point, all three callbacks should have already been called + int numErrors = 0; + for( i = 0; i < 3; i++ ) + { + // Spin waiting for the release to finish. If you don't call the mem_destructor_callback, you will not + // pass the test. bugzilla 6316 + while( 0 == callbackOrders[i] ) + {} + + if( ABS( callbackOrders[ i ] ) != 3-i ) + { + log_error( "\tERROR: Callback %d was called in the wrong order! (Was called order %d, should have been order %d)\n", + i+1, ABS( callbackOrders[ i ] ), i ); + numErrors++; + } + } + + return ( numErrors > 0 ) ? -1 : 0; +} + +int test_mem_object_destructor_callback(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + clMemWrapper testBuffer, testImage; + cl_int error; + + + // Create a buffer and an image to test callbacks against + testBuffer = clCreateBuffer( context, CL_MEM_READ_WRITE, 1024, NULL, &error ); + test_error( error, "Unable to create testing buffer" ); + + if( test_mem_object_destructor_callback_single( testBuffer ) != 0 ) + { + log_error( "ERROR: Destructor callbacks for buffer object FAILED\n" ); + return -1; + } + + if( checkForImageSupport( deviceID ) == 0 ) + { + cl_image_format imageFormat = { CL_RGBA, CL_SIGNED_INT8 }; + testImage = create_image_2d( context, CL_MEM_READ_ONLY, &imageFormat, 16, 16, 0, NULL, &error ); + test_error( error, "Unable to create testing image" ); + + if( test_mem_object_destructor_callback_single( testImage ) != 0 ) + { + log_error( "ERROR: Destructor callbacks for image object FAILED\n" ); + return -1; + } + } + + return 0; +} diff --git a/test_conformance/compatibility/test_conformance/api/test_native_kernel.cpp b/test_conformance/compatibility/test_conformance/api/test_native_kernel.cpp new file mode 100644 index 00000000..2d52134b --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/test_native_kernel.cpp @@ -0,0 +1,121 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +#ifndef _WIN32 +#include +#endif + +#include "../../test_common/harness/conversions.h" + +extern cl_uint gRandomSeed; + +static void CL_CALLBACK test_native_kernel_fn( void *userData ) +{ + struct arg_struct { + cl_int * source; + cl_int * dest; + cl_int count; + } *args = (arg_struct *)userData; + + for( cl_int i = 0; i < args->count; i++ ) + args->dest[ i ] = args->source[ i ]; +} + +int test_native_kernel(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + int error; + RandomSeed seed( gRandomSeed ); + // Check if we support native kernels + cl_device_exec_capabilities capabilities; + error = clGetDeviceInfo(device, CL_DEVICE_EXECUTION_CAPABILITIES, sizeof(capabilities), &capabilities, NULL); + if (!(capabilities & CL_EXEC_NATIVE_KERNEL)) { + log_info("Device does not support CL_EXEC_NATIVE_KERNEL.\n"); + return 0; + } + + clMemWrapper streams[ 2 ]; +#if !(defined (_WIN32) && defined (_MSC_VER)) + cl_int inBuffer[ n_elems ], outBuffer[ n_elems ]; +#else + cl_int* inBuffer = (cl_int *)_malloca( n_elems * sizeof(cl_int) ); + cl_int* outBuffer = (cl_int *)_malloca( n_elems * sizeof(cl_int) ); +#endif + clEventWrapper finishEvent; + + struct arg_struct + { + cl_mem inputStream; + cl_mem outputStream; + cl_int count; + } args; + + + // Create some input values + generate_random_data( kInt, n_elems, seed, inBuffer ); + + + // Create I/O streams + streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, n_elems * sizeof(cl_int), inBuffer, &error ); + test_error( error, "Unable to create I/O stream" ); + streams[ 1 ] = clCreateBuffer( context, 0, n_elems * sizeof(cl_int), NULL, &error ); + test_error( error, "Unable to create I/O stream" ); + + + // Set up the arrays to call with + args.inputStream = streams[ 0 ]; + args.outputStream = streams[ 1 ]; + args.count = n_elems; + + void * memLocs[ 2 ] = { &args.inputStream, &args.outputStream }; + + + // Run the kernel + error = clEnqueueNativeKernel( queue, test_native_kernel_fn, + &args, sizeof( args ), + 2, &streams[ 0 ], + (const void **)memLocs, + 0, NULL, &finishEvent ); + test_error( error, "Unable to queue native kernel" ); + + // Finish and wait for the kernel to complete + error = clFinish( queue ); + test_error(error, "clFinish failed"); + + error = clWaitForEvents( 1, &finishEvent ); + test_error(error, "clWaitForEvents failed"); + + // Now read the results and verify + error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, n_elems * sizeof(cl_int), outBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + for( int i = 0; i < n_elems; i++ ) + { + if( inBuffer[ i ] != outBuffer[ i ] ) + { + log_error( "ERROR: Data sample %d for native kernel did not validate (expected %d, got %d)\n", + i, (int)inBuffer[ i ], (int)outBuffer[ i ] ); + return 1; + } + } + + return 0; +} + + + + + diff --git a/test_conformance/compatibility/test_conformance/api/test_null_buffer_arg.c b/test_conformance/compatibility/test_conformance/api/test_null_buffer_arg.c new file mode 100644 index 00000000..0d792136 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/test_null_buffer_arg.c @@ -0,0 +1,162 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#if defined(__APPLE__) +#include +#include +#else +#include +#include +#endif +#include "procs.h" + + +enum { SUCCESS, FAILURE }; +typedef enum { NON_NULL_PATH, ADDROF_NULL_PATH, NULL_PATH } test_type; + +#define NITEMS 4096 + +/* places the casted long value of the src ptr into each element of the output + * array, to allow testing that the kernel actually _gets_ the NULL value */ +const char *kernel_string = +"kernel void test_kernel(global float *src, global long *dst)\n" +"{\n" +" uint tid = get_global_id(0);\n" +" dst[tid] = (long)src;\n" +"}\n"; + +/* + * The guts of the test: + * call setKernelArgs with a regular buffer, &NULL, or NULL depending on + * the value of 'test_type' + */ +static int test_setargs_and_execution(cl_command_queue queue, cl_kernel kernel, + cl_mem test_buf, cl_mem result_buf, test_type type) +{ + unsigned int test_success = 0; + + unsigned int i; + cl_int status; + char *typestr; + + if (type == NON_NULL_PATH) { + status = clSetKernelArg(kernel, 0, sizeof(cl_mem), &test_buf); + typestr = "non-NULL"; + } else if (type == ADDROF_NULL_PATH) { + test_buf = NULL; + status = clSetKernelArg(kernel, 0, sizeof(cl_mem), &test_buf); + typestr = "&NULL"; + } else if (type == NULL_PATH) { + status = clSetKernelArg(kernel, 0, sizeof(cl_mem), NULL); + typestr = "NULL"; + } + + log_info("Testing setKernelArgs with %s buffer.\n", typestr); + + if (status != CL_SUCCESS) { + log_error("clSetKernelArg failed with status: %d\n", status); + return FAILURE; // no point in continuing *this* test + } + + size_t global = NITEMS; + status = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global, + NULL, 0, NULL, NULL); + test_error(status, "NDRangeKernel failed."); + + cl_long* host_result = (cl_long*)malloc(NITEMS*sizeof(cl_long)); + status = clEnqueueReadBuffer(queue, result_buf, CL_TRUE, 0, + sizeof(cl_long)*NITEMS, host_result, 0, NULL, NULL); + test_error(status, "ReadBuffer failed."); + + // in the non-null case, we expect NONZERO values: + if (type == NON_NULL_PATH) { + for (i=0; i + +#define EXTENSION_NAME_BUF_SIZE 4096 + +#define PRINT_EXTENSION_INFO 0 + +int test_platform_extensions(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements) +{ + const char * extensions[] = { + "cl_khr_byte_addressable_store", +// "cl_APPLE_SetMemObjectDestructor", + "cl_khr_global_int32_base_atomics", + "cl_khr_global_int32_extended_atomics", + "cl_khr_local_int32_base_atomics", + "cl_khr_local_int32_extended_atomics", + "cl_khr_int64_base_atomics", + "cl_khr_int64_extended_atomics", +// need to put in entires for various atomics + "cl_khr_3d_image_writes", + "cl_khr_fp16", + "cl_khr_fp64", + NULL + }; + + bool extensionsSupported[] = { + false, //"cl_khr_byte_addressable_store", + false, // need to put in entires for various atomics + false, // "cl_khr_global_int32_base_atomics", + false, // "cl_khr_global_int32_extended_atomics", + false, // "cl_khr_local_int32_base_atomics", + false, // "cl_khr_local_int32_extended_atomics", + false, // "cl_khr_int64_base_atomics", + false, // "cl_khr_int64_extended_atomics", + false, //"cl_khr_3d_image_writes", + false, //"cl_khr_fp16", + false, //"cl_khr_fp64", + false //NULL + }; + + int extensionIndex; + + cl_platform_id platformID; + cl_int err; + + char platform_extensions[EXTENSION_NAME_BUF_SIZE]; + char device_extensions[EXTENSION_NAME_BUF_SIZE]; + + // Okay, so what we're going to do is just check the device indicated by + // deviceID against the platform that includes this device + + + // pass CL_DEVICE_PLATFORM to clGetDeviceInfo + // to get a result of type cl_platform_id + + err = clGetDeviceInfo(deviceID, + CL_DEVICE_PLATFORM, + sizeof(cl_platform_id), + (void *)(&platformID), + NULL); + + if(err != CL_SUCCESS) + { + vlog_error("test_platform_extensions : could not get platformID from device\n"); + return -1; + } + + + // now we grab the set of extensions specified by the platform + err = clGetPlatformInfo(platformID, + CL_PLATFORM_EXTENSIONS, + sizeof(platform_extensions), + (void *)(&platform_extensions[0]), + NULL); + if(err != CL_SUCCESS) + { + vlog_error("test_platform_extensions : could not get extension string from platform\n"); + return -1; + } + +#if PRINT_EXTENSION_INFO + log_info("Platform extensions include \"%s\"\n\n", platform_extensions); +#endif + + // here we parse the platform extensions, to look for the "important" ones + for(extensionIndex=0; extensions[extensionIndex] != NULL; ++extensionIndex) + { + if(strstr(platform_extensions, extensions[extensionIndex]) != NULL) + { + // we found it +#if PRINT_EXTENSION_INFO + log_info("Found \"%s\" in platform extensions\n", + extensions[extensionIndex]); +#endif + extensionsSupported[extensionIndex] = true; + } + } + + // and then we grab the set of extensions specified by the device + // (this can be turned into a "loop over all devices in this platform") + err = clGetDeviceInfo(deviceID, + CL_DEVICE_EXTENSIONS, + sizeof(device_extensions), + (void *)(&device_extensions[0]), + NULL); + if(err != CL_SUCCESS) + { + vlog_error("test_platform_extensions : could not get extension string from device\n"); + return -1; + } + + +#if PRINT_EXTENSION_INFO + log_info("Device extensions include \"%s\"\n\n", device_extensions); +#endif + + for(extensionIndex=0; extensions[extensionIndex] != NULL; ++extensionIndex) + { + if(extensionsSupported[extensionIndex] == false) + { + continue; // skip this one + } + + if(strstr(device_extensions, extensions[extensionIndex]) == NULL) + { + // device does not support it + vlog_error("Platform supports extension \"%s\" but device does not\n", + extensions[extensionIndex]); + return -1; + } + } + return 0; +} + +int test_get_platform_ids(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + cl_platform_id platforms[16]; + cl_uint num_platforms; + char *string_returned; + + string_returned = (char*)malloc(8192); + + int total_errors = 0; + int err = CL_SUCCESS; + + + err = clGetPlatformIDs(16, platforms, &num_platforms); + test_error(err, "clGetPlatformIDs failed"); + + if (num_platforms <= 16) { + // Try with NULL + err = clGetPlatformIDs(num_platforms, platforms, NULL); + test_error(err, "clGetPlatformIDs failed with NULL for return size"); + } + + if (num_platforms < 1) { + log_error("Found 0 platforms.\n"); + return -1; + } + log_info("Found %d platforms.\n", num_platforms); + + + for (int p=0; p<(int)num_platforms; p++) { + cl_device_id *devices; + cl_uint num_devices; + size_t size; + + + log_info("Platform %d (%p):\n", p, platforms[p]); + + memset(string_returned, 0, 8192); + err = clGetPlatformInfo(platforms[p], CL_PLATFORM_PROFILE, 8192, string_returned, &size); + test_error(err, "clGetPlatformInfo for CL_PLATFORM_PROFILE failed"); + log_info("\tCL_PLATFORM_PROFILE: %s\n", string_returned); + if (strlen(string_returned)+1 != size) { + log_error("Returned string length %ld does not equal reported one %ld.\n", strlen(string_returned)+1, size); + total_errors++; + } + + memset(string_returned, 0, 8192); + err = clGetPlatformInfo(platforms[p], CL_PLATFORM_VERSION, 8192, string_returned, &size); + test_error(err, "clGetPlatformInfo for CL_PLATFORM_VERSION failed"); + log_info("\tCL_PLATFORM_VERSION: %s\n", string_returned); + if (strlen(string_returned)+1 != size) { + log_error("Returned string length %ld does not equal reported one %ld.\n", strlen(string_returned)+1, size); + total_errors++; + } + + memset(string_returned, 0, 8192); + err = clGetPlatformInfo(platforms[p], CL_PLATFORM_NAME, 8192, string_returned, &size); + test_error(err, "clGetPlatformInfo for CL_PLATFORM_NAME failed"); + log_info("\tCL_PLATFORM_NAME: %s\n", string_returned); + if (strlen(string_returned)+1 != size) { + log_error("Returned string length %ld does not equal reported one %ld.\n", strlen(string_returned)+1, size); + total_errors++; + } + + memset(string_returned, 0, 8192); + err = clGetPlatformInfo(platforms[p], CL_PLATFORM_VENDOR, 8192, string_returned, &size); + test_error(err, "clGetPlatformInfo for CL_PLATFORM_VENDOR failed"); + log_info("\tCL_PLATFORM_VENDOR: %s\n", string_returned); + if (strlen(string_returned)+1 != size) { + log_error("Returned string length %ld does not equal reported one %ld.\n", strlen(string_returned)+1, size); + total_errors++; + } + + memset(string_returned, 0, 8192); + err = clGetPlatformInfo(platforms[p], CL_PLATFORM_EXTENSIONS, 8192, string_returned, &size); + test_error(err, "clGetPlatformInfo for CL_PLATFORM_EXTENSIONS failed"); + log_info("\tCL_PLATFORM_EXTENSIONS: %s\n", string_returned); + if (strlen(string_returned)+1 != size) { + log_error("Returned string length %ld does not equal reported one %ld.\n", strlen(string_returned)+1, size); + total_errors++; + } + + err = clGetDeviceIDs(platforms[p], CL_DEVICE_TYPE_ALL, 0, NULL, &num_devices); + test_error(err, "clGetDeviceIDs size failed.\n"); + devices = (cl_device_id *)malloc(num_devices*sizeof(cl_device_id)); + memset(devices, 0, sizeof(cl_device_id)*num_devices); + err = clGetDeviceIDs(platforms[p], CL_DEVICE_TYPE_ALL, num_devices, devices, NULL); + test_error(err, "clGetDeviceIDs failed.\n"); + + log_info("\tPlatform has %d devices.\n", (int)num_devices); + for (int d=0; d<(int)num_devices; d++) { + size_t returned_size; + cl_platform_id returned_platform; + cl_context context; + cl_context_properties properties[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[p], 0 }; + + err = clGetDeviceInfo(devices[d], CL_DEVICE_PLATFORM, sizeof(cl_platform_id), &returned_platform, &returned_size); + test_error(err, "clGetDeviceInfo failed for CL_DEVICE_PLATFORM\n"); + if (returned_size != sizeof(cl_platform_id)) { + log_error("Reported return size (%ld) does not match expected size (%ld).\n", returned_size, sizeof(cl_platform_id)); + total_errors++; + } + + memset(string_returned, 0, 8192); + err = clGetDeviceInfo(devices[d], CL_DEVICE_NAME, 8192, string_returned, NULL); + test_error(err, "clGetDeviceInfo failed for CL_DEVICE_NAME\n"); + + log_info("\t\tPlatform for device %d (%s) is %p.\n", d, string_returned, returned_platform); + + log_info("\t\t\tTesting clCreateContext for the platform/device...\n"); + // Try creating a context for the platform + context = clCreateContext(properties, 1, &devices[d], NULL, NULL, &err); + test_error(err, "\t\tclCreateContext failed for device with platform properties\n"); + + memset(properties, 0, sizeof(cl_context_properties)*3); + + err = clGetContextInfo(context, CL_CONTEXT_PROPERTIES, sizeof(cl_context_properties)*3, properties, &returned_size); + test_error(err, "clGetContextInfo for CL_CONTEXT_PROPERTIES failed"); + if (returned_size != sizeof(cl_context_properties)*3) { + log_error("Invalid size returned from clGetContextInfo for CL_CONTEXT_PROPERTIES. Got %ld, expected %ld.\n", + returned_size, sizeof(cl_context_properties)*3); + total_errors++; + } + + if (properties[0] != (cl_context_properties)CL_CONTEXT_PLATFORM || properties[1] != (cl_context_properties)platforms[p]) { + log_error("Wrong properties returned. Expected: [%p %p], got [%p %p]\n", + (void*)CL_CONTEXT_PLATFORM, platforms[p], (void*)properties[0], (void*)properties[1]); + total_errors++; + } + + err = clReleaseContext(context); + test_error(err, "clReleaseContext failed"); + } + free(devices); + } + + free(string_returned); + + return total_errors; +} diff --git a/test_conformance/compatibility/test_conformance/api/test_queries.cpp b/test_conformance/compatibility/test_conformance/api/test_queries.cpp new file mode 100644 index 00000000..8e34f97d --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/test_queries.cpp @@ -0,0 +1,635 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/imageHelpers.h" +#include +#include + +int test_get_platform_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_platform_id platform; + cl_int error; + char buffer[ 4098 ]; + size_t length; + + // Get the platform to use + error = clGetPlatformIDs(1, &platform, NULL); + test_error( error, "Unable to get platform" ); + + // Platform profile should either be FULL_PROFILE or EMBEDDED_PROFILE + error = clGetPlatformInfo(platform, CL_PLATFORM_PROFILE, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get platform profile string" ); + + log_info("Returned CL_PLATFORM_PROFILE %s.\n", buffer); + + if( strcmp( buffer, "FULL_PROFILE" ) != 0 && strcmp( buffer, "EMBEDDED_PROFILE" ) != 0 ) + { + log_error( "ERROR: Returned platform profile string is not a valid string by OpenCL 1.2! (Returned: %s)\n", buffer ); + return -1; + } + if( strlen( buffer )+1 != length ) + { + log_error( "ERROR: Returned length of profile string is incorrect (actual length: %d, returned length: %d)\n", + (int)strlen( buffer )+1, (int)length ); + return -1; + } + + // Check just length return + error = clGetPlatformInfo(platform, CL_PLATFORM_PROFILE, 0, NULL, &length ); + test_error( error, "Unable to get platform profile length" ); + if( strlen( (char *)buffer )+1 != length ) + { + log_error( "ERROR: Returned length of profile string is incorrect (actual length: %d, returned length: %d)\n", + (int)strlen( (char *)buffer )+1, (int)length ); + return -1; + } + + + // Platform version should fit the regex "OpenCL *[0-9]+\.[0-9]+" + error = clGetPlatformInfo(platform, CL_PLATFORM_VERSION, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get platform version string" ); + + log_info("Returned CL_PLATFORM_VERSION %s.\n", buffer); + + if( memcmp( buffer, "OpenCL ", strlen( "OpenCL " ) ) != 0 ) + { + log_error( "ERROR: Initial part of platform version string does not match required format! (returned: %s)\n", (char *)buffer ); + return -1; + } + char *p1 = (char *)buffer + strlen( "OpenCL " ); + while( *p1 == ' ' ) + p1++; + char *p2 = p1; + while( isdigit( *p2 ) ) + p2++; + if( *p2 != '.' ) + { + log_error( "ERROR: Numeric part of platform version string does not match required format! (returned: %s)\n", (char *)buffer ); + return -1; + } + char *p3 = p2 + 1; + while( isdigit( *p3 ) ) + p3++; + if( *p3 != ' ' ) + { + log_error( "ERROR: space expected after minor version number! (returned: %s)\n", (char *)buffer ); + return -1; + } + *p2 = ' '; // Put in a space for atoi below. + p2++; + + // make sure it is null terminated + for( ; p3 != buffer + length; p3++ ) + if( *p3 == '\0' ) + break; + if( p3 == buffer + length ) + { + log_error( "ERROR: platform version string is not NUL terminated!\n" ); + return -1; + } + + int major = atoi( p1 ); + int minor = atoi( p2 ); + int minor_revision = 2; + if( major * 10 + minor < 10 + minor_revision ) + { + log_error( "ERROR: OpenCL profile version returned is less than 1.%d!\n", minor_revision ); + return -1; + } + + // Sanity checks on the returned values + if( length != strlen( (char *)buffer ) + 1) + { + log_error( "ERROR: Returned length of version string does not match actual length (actual: %d, returned: %d)\n", (int)strlen( (char *)buffer )+1, (int)length ); + return -1; + } + + // Check just length + error = clGetPlatformInfo(platform, CL_PLATFORM_VERSION, 0, NULL, &length ); + test_error( error, "Unable to get platform version length" ); + if( length != strlen( (char *)buffer )+1 ) + { + log_error( "ERROR: Returned length of version string does not match actual length (actual: %d, returned: %d)\n", (int)strlen( buffer )+1, (int)length ); + return -1; + } + + return 0; +} + +int test_get_sampler_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t size; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ) + + clSamplerWrapper sampler = clCreateSampler( context, CL_TRUE, CL_ADDRESS_CLAMP, CL_FILTER_LINEAR, &error ); + test_error( error, "Unable to create sampler to test with" ); + + cl_uint refCount; + error = clGetSamplerInfo( sampler, CL_SAMPLER_REFERENCE_COUNT, sizeof( refCount ), &refCount, &size ); + test_error( error, "Unable to get sampler ref count" ); + if( size != sizeof( refCount ) ) + { + log_error( "ERROR: Returned size of sampler refcount does not validate! (expected %d, got %d)\n", (int)sizeof( refCount ), (int)size ); + return -1; + } + + cl_context otherCtx; + error = clGetSamplerInfo( sampler, CL_SAMPLER_CONTEXT, sizeof( otherCtx ), &otherCtx, &size ); + test_error( error, "Unable to get sampler context" ); + if( otherCtx != context ) + { + log_error( "ERROR: Sampler context does not validate! (expected %p, got %p)\n", context, otherCtx ); + return -1; + } + if( size != sizeof( otherCtx ) ) + { + log_error( "ERROR: Returned size of sampler context does not validate! (expected %d, got %d)\n", (int)sizeof( otherCtx ), (int)size ); + return -1; + } + + cl_addressing_mode mode; + error = clGetSamplerInfo( sampler, CL_SAMPLER_ADDRESSING_MODE, sizeof( mode ), &mode, &size ); + test_error( error, "Unable to get sampler addressing mode" ); + if( mode != CL_ADDRESS_CLAMP ) + { + log_error( "ERROR: Sampler addressing mode does not validate! (expected %d, got %d)\n", (int)CL_ADDRESS_CLAMP, (int)mode ); + return -1; + } + if( size != sizeof( mode ) ) + { + log_error( "ERROR: Returned size of sampler addressing mode does not validate! (expected %d, got %d)\n", (int)sizeof( mode ), (int)size ); + return -1; + } + + cl_filter_mode fmode; + error = clGetSamplerInfo( sampler, CL_SAMPLER_FILTER_MODE, sizeof( fmode ), &fmode, &size ); + test_error( error, "Unable to get sampler filter mode" ); + if( fmode != CL_FILTER_LINEAR ) + { + log_error( "ERROR: Sampler filter mode does not validate! (expected %d, got %d)\n", (int)CL_FILTER_LINEAR, (int)fmode ); + return -1; + } + if( size != sizeof( fmode ) ) + { + log_error( "ERROR: Returned size of sampler filter mode does not validate! (expected %d, got %d)\n", (int)sizeof( fmode ), (int)size ); + return -1; + } + + cl_int norm; + error = clGetSamplerInfo( sampler, CL_SAMPLER_NORMALIZED_COORDS, sizeof( norm ), &norm, &size ); + test_error( error, "Unable to get sampler normalized flag" ); + if( norm != CL_TRUE ) + { + log_error( "ERROR: Sampler normalized flag does not validate! (expected %d, got %d)\n", (int)CL_TRUE, (int)norm ); + return -1; + } + if( size != sizeof( norm ) ) + { + log_error( "ERROR: Returned size of sampler normalized flag does not validate! (expected %d, got %d)\n", (int)sizeof( norm ), (int)size ); + return -1; + } + + return 0; +} + +#define TEST_COMMAND_QUEUE_PARAM( queue, paramName, val, expected, name, type, cast ) \ +error = clGetCommandQueueInfo( queue, paramName, sizeof( val ), &val, &size ); \ +test_error( error, "Unable to get command queue " name ); \ +if( val != expected ) \ +{ \ +log_error( "ERROR: Command queue " name " did not validate! (expected " type ", got " type ")\n", (cast)expected, (cast)val ); \ +return -1; \ +} \ +if( size != sizeof( val ) ) \ +{ \ +log_error( "ERROR: Returned size of command queue " name " does not validate! (expected %d, got %d)\n", (int)sizeof( val ), (int)size ); \ +return -1; \ +} + +int test_get_command_queue_info(cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements) +{ + int error; + size_t size; + + cl_command_queue_properties device_props; + clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_PROPERTIES, sizeof(device_props), &device_props, NULL); + log_info("CL_DEVICE_QUEUE_PROPERTIES is %d\n", (int)device_props); + + clCommandQueueWrapper queue = clCreateCommandQueue( context, deviceID, device_props, &error ); + test_error( error, "Unable to create command queue to test with" ); + + cl_uint refCount; + error = clGetCommandQueueInfo( queue, CL_QUEUE_REFERENCE_COUNT, sizeof( refCount ), &refCount, &size ); + test_error( error, "Unable to get command queue reference count" ); + if( size != sizeof( refCount ) ) + { + log_error( "ERROR: Returned size of command queue reference count does not validate! (expected %d, got %d)\n", (int)sizeof( refCount ), (int)size ); + return -1; + } + + cl_context otherCtx; + TEST_COMMAND_QUEUE_PARAM( queue, CL_QUEUE_CONTEXT, otherCtx, context, "context", "%p", cl_context ) + + cl_device_id otherDevice; + error = clGetCommandQueueInfo( queue, CL_QUEUE_DEVICE, sizeof(otherDevice), &otherDevice, &size); + test_error(error, "clGetCommandQueue failed."); + + if (size != sizeof(cl_device_id)) { + log_error( " ERROR: Returned size of command queue CL_QUEUE_DEVICE does not validate! (expected %d, got %d)\n", (int)sizeof( otherDevice ), (int)size ); + return -1; + } + + /* Since the device IDs are opaque types we check the CL_DEVICE_VENDOR_ID which is unique for identical hardware. */ + cl_uint otherDevice_vid, deviceID_vid; + error = clGetDeviceInfo(otherDevice, CL_DEVICE_VENDOR_ID, sizeof(otherDevice_vid), &otherDevice_vid, NULL ); + test_error( error, "Unable to get device CL_DEVICE_VENDOR_ID" ); + error = clGetDeviceInfo(deviceID, CL_DEVICE_VENDOR_ID, sizeof(deviceID_vid), &deviceID_vid, NULL ); + test_error( error, "Unable to get device CL_DEVICE_VENDOR_ID" ); + + if( otherDevice_vid != deviceID_vid ) + { + log_error( "ERROR: Incorrect device returned for queue! (Expected vendor ID 0x%x, got 0x%x)\n", deviceID_vid, otherDevice_vid ); + return -1; + } + + cl_command_queue_properties props; + TEST_COMMAND_QUEUE_PARAM( queue, CL_QUEUE_PROPERTIES, props, (unsigned int)( device_props ), "properties", "%d", unsigned int ) + + return 0; +} + +int test_get_context_info(cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements) +{ + int error; + size_t size; + cl_context_properties props; + + error = clGetContextInfo( context, CL_CONTEXT_PROPERTIES, sizeof( props ), &props, &size ); + test_error( error, "Unable to get context props" ); + + if (size == 0) { + // Valid size + return 0; + } else if (size == sizeof(cl_context_properties)) { + // Data must be NULL + if (props != 0) { + log_error("ERROR: Returned properties is no NULL.\n"); + return -1; + } + // Valid data and size + return 0; + } + // Size was not 0 or 1 + log_error( "ERROR: Returned size of context props is not valid! (expected 0 or %d, got %d)\n", + (int)sizeof(cl_context_properties), (int)size ); + return -1; +} + +#define TEST_MEM_OBJECT_PARAM( mem, paramName, val, expected, name, type, cast ) \ +error = clGetMemObjectInfo( mem, paramName, sizeof( val ), &val, &size ); \ +test_error( error, "Unable to get mem object " name ); \ +if( val != expected ) \ +{ \ +log_error( "ERROR: Mem object " name " did not validate! (expected " type ", got " type ")\n", (cast)(expected), (cast)val ); \ +return -1; \ +} \ +if( size != sizeof( val ) ) \ +{ \ +log_error( "ERROR: Returned size of mem object " name " does not validate! (expected %d, got %d)\n", (int)sizeof( val ), (int)size ); \ +return -1; \ +} + +void CL_CALLBACK mem_obj_destructor_callback( cl_mem, void *data ) +{ + free( data ); +} + +// All possible combinations of valid cl_mem_flags. +static cl_mem_flags all_flags[16] = { + 0, + CL_MEM_READ_WRITE, + CL_MEM_READ_ONLY, + CL_MEM_WRITE_ONLY, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, +}; + +#define TEST_DEVICE_PARAM( device, paramName, val, name, type, cast ) \ +error = clGetDeviceInfo( device, paramName, sizeof( val ), &val, &size ); \ +test_error( error, "Unable to get device " name ); \ +if( size != sizeof( val ) ) \ +{ \ +log_error( "ERROR: Returned size of device " name " does not validate! (expected %d, got %d)\n", (int)sizeof( val ), (int)size ); \ +return -1; \ +} \ +log_info( "\tReported device " name " : " type "\n", (cast)val ); + +#define TEST_DEVICE_PARAM_MEM( device, paramName, val, name, type, div ) \ +error = clGetDeviceInfo( device, paramName, sizeof( val ), &val, &size ); \ +test_error( error, "Unable to get device " name ); \ +if( size != sizeof( val ) ) \ +{ \ +log_error( "ERROR: Returned size of device " name " does not validate! (expected %d, got %d)\n", (int)sizeof( val ), (int)size ); \ +return -1; \ +} \ +log_info( "\tReported device " name " : " type "\n", (int)( val / div ) ); + +int test_get_device_info(cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements) +{ + int error; + size_t size; + + cl_uint vendorID; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_VENDOR_ID, vendorID, "vendor ID", "0x%08x", int ) + + char extensions[ 10240 ]; + error = clGetDeviceInfo( deviceID, CL_DEVICE_EXTENSIONS, sizeof( extensions ), &extensions, &size ); + test_error( error, "Unable to get device extensions" ); + if( size != strlen( extensions ) + 1 ) + { + log_error( "ERROR: Returned size of device extensions does not validate! (expected %d, got %d)\n", (int)( strlen( extensions ) + 1 ), (int)size ); + return -1; + } + log_info( "\tReported device extensions: %s \n", extensions ); + + cl_uint preferred; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, preferred, "preferred vector char width", "%d", int ) + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, preferred, "preferred vector short width", "%d", int ) + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, preferred, "preferred vector int width", "%d", int ) + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, preferred, "preferred vector long width", "%d", int ) + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, preferred, "preferred vector float width", "%d", int ) + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, preferred, "preferred vector double width", "%d", int ) + + // Note that even if cl_khr_fp64, the preferred width for double can be non-zero. For example, vendors + // extensions can support double but may not support cl_khr_fp64, which implies math library support. + + cl_uint baseAddrAlign; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_MEM_BASE_ADDR_ALIGN, baseAddrAlign, "base address alignment", "%d bytes", int ) + + cl_uint maxDataAlign; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE, maxDataAlign, "min data type alignment", "%d bytes", int ) + + cl_device_mem_cache_type cacheType; + error = clGetDeviceInfo( deviceID, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE, sizeof( cacheType ), &cacheType, &size ); + test_error( error, "Unable to get device global mem cache type" ); + if( size != sizeof( cacheType ) ) + { + log_error( "ERROR: Returned size of device global mem cache type does not validate! (expected %d, got %d)\n", (int)sizeof( cacheType ), (int)size ); + return -1; + } + const char *cacheTypeName = ( cacheType == CL_NONE ) ? "CL_NONE" : ( cacheType == CL_READ_ONLY_CACHE ) ? "CL_READ_ONLY_CACHE" : ( cacheType == CL_READ_WRITE_CACHE ) ? "CL_READ_WRITE_CACHE" : ""; + log_info( "\tReported device global mem cache type: %s \n", cacheTypeName ); + + cl_uint cachelineSize; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, cachelineSize, "global mem cacheline size", "%d bytes", int ) + + cl_ulong cacheSize; + TEST_DEVICE_PARAM_MEM( deviceID, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, cacheSize, "global mem cache size", "%d KB", 1024 ) + + cl_ulong memSize; + TEST_DEVICE_PARAM_MEM( deviceID, CL_DEVICE_GLOBAL_MEM_SIZE, memSize, "global mem size", "%d MB", ( 1024 * 1024 ) ) + + cl_device_local_mem_type localMemType; + error = clGetDeviceInfo( deviceID, CL_DEVICE_LOCAL_MEM_TYPE, sizeof( localMemType ), &localMemType, &size ); + test_error( error, "Unable to get device local mem type" ); + if( size != sizeof( cacheType ) ) + { + log_error( "ERROR: Returned size of device local mem type does not validate! (expected %d, got %d)\n", (int)sizeof( localMemType ), (int)size ); + return -1; + } + const char *localMemTypeName = ( localMemType == CL_LOCAL ) ? "CL_LOCAL" : ( cacheType == CL_GLOBAL ) ? "CL_GLOBAL" : ""; + log_info( "\tReported device local mem type: %s \n", localMemTypeName ); + + + cl_bool errSupport; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_ERROR_CORRECTION_SUPPORT, errSupport, "error correction support", "%d", int ) + + size_t timerResolution; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_PROFILING_TIMER_RESOLUTION, timerResolution, "profiling timer resolution", "%ld nanoseconds", long ) + + cl_bool endian; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_ENDIAN_LITTLE, endian, "little endian flag", "%d", int ) + + cl_bool avail; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_AVAILABLE, avail, "available flag", "%d", int ) + + cl_bool compilerAvail; + TEST_DEVICE_PARAM( deviceID, CL_DEVICE_COMPILER_AVAILABLE, compilerAvail, "compiler available flag", "%d", int ) + + char profile[ 1024 ]; + error = clGetDeviceInfo( deviceID, CL_DEVICE_PROFILE, sizeof( profile ), &profile, &size ); + test_error( error, "Unable to get device profile" ); + if( size != strlen( profile ) + 1 ) + { + log_error( "ERROR: Returned size of device profile does not validate! (expected %d, got %d)\n", (int)( strlen( profile ) + 1 ), (int)size ); + return -1; + } + if( strcmp( profile, "FULL_PROFILE" ) != 0 && strcmp( profile, "EMBEDDED_PROFILE" ) != 0 ) + { + log_error( "ERROR: Returned profile of device not FULL or EMBEDDED as required by OpenCL 1.2! (Returned %s)\n", profile ); + return -1; + } + log_info( "\tReported device profile: %s \n", profile ); + + + return 0; +} + + + + +static const char *sample_compile_size[2] = { + "__kernel void sample_test(__global int *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = src[tid];\n" + "\n" + "}\n", + "__kernel __attribute__((reqd_work_group_size(%d,%d,%d))) void sample_test(__global int *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = src[tid];\n" + "\n" + "}\n" }; + +int test_kernel_required_group_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t realSize; + size_t kernel_max_workgroup_size; + size_t global[] = {64,14,10}; + size_t local[] = {0,0,0}; + + cl_uint max_dimensions; + + error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(max_dimensions), &max_dimensions, NULL); + test_error(error, "clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS"); + log_info("Device reported CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS = %d.\n", (int)max_dimensions); + + { + clProgramWrapper program; + clKernelWrapper kernel; + + error = create_single_kernel_helper( context, &program, &kernel, 1, &sample_compile_size[ 0 ], "sample_test" ); + if( error != 0 ) + return error; + + error = clGetKernelWorkGroupInfo(kernel, deviceID, CL_KERNEL_WORK_GROUP_SIZE, sizeof(kernel_max_workgroup_size), &kernel_max_workgroup_size, NULL); + test_error( error, "clGetKernelWorkGroupInfo failed for CL_KERNEL_WORK_GROUP_SIZE"); + log_info("The CL_KERNEL_WORK_GROUP_SIZE for the kernel is %d.\n", (int)kernel_max_workgroup_size); + + size_t size[ 3 ]; + error = clGetKernelWorkGroupInfo( kernel, deviceID, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, sizeof( size ), size, &realSize ); + test_error( error, "Unable to get work group info" ); + + if( size[ 0 ] != 0 || size[ 1 ] != 0 || size[ 2 ] != 0 ) + { + log_error( "ERROR: Nonzero compile work group size returned for nonspecified size! (returned %d,%d,%d)\n", (int)size[0], (int)size[1], (int)size[2] ); + return -1; + } + + if( realSize != sizeof( size ) ) + { + log_error( "ERROR: Returned size of compile work group size not valid! (Expected %d, got %d)\n", (int)sizeof( size ), (int)realSize ); + return -1; + } + + // Determine some local dimensions to use for the test. + if (max_dimensions == 1) { + error = get_max_common_work_group_size(context, kernel, global[0], &local[0]); + test_error( error, "get_max_common_work_group_size failed"); + log_info("For global dimension %d, kernel will require local dimension %d.\n", (int)global[0], (int)local[0]); + } else if (max_dimensions == 2) { + error = get_max_common_2D_work_group_size(context, kernel, global, local); + test_error( error, "get_max_common_2D_work_group_size failed"); + log_info("For global dimension %d x %d, kernel will require local dimension %d x %d.\n", (int)global[0], (int)global[1], (int)local[0], (int)local[1]); + } else { + error = get_max_common_3D_work_group_size(context, kernel, global, local); + test_error( error, "get_max_common_3D_work_group_size failed"); + log_info("For global dimension %d x %d x %d, kernel will require local dimension %d x %d x %d.\n", + (int)global[0], (int)global[1], (int)global[2], (int)local[0], (int)local[1], (int)local[2]); + } + } + + + { + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper in, out; + //char source[1024]; + char *source = (char*)malloc(1024); + source[0] = '\0'; + + sprintf(source, sample_compile_size[1], local[0], local[1], local[2]); + + error = create_single_kernel_helper( context, &program, &kernel, 1, (const char**)&source, "sample_test" ); + if( error != 0 ) + return error; + + size_t size[ 3 ]; + error = clGetKernelWorkGroupInfo( kernel, deviceID, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, sizeof( size ), size, &realSize ); + test_error( error, "Unable to get work group info" ); + + if( size[ 0 ] != local[0] || size[ 1 ] != local[1] || size[ 2 ] != local[2] ) + { + log_error( "ERROR: Incorrect compile work group size returned for specified size! (returned %d,%d,%d, expected %d,%d,%d)\n", + (int)size[0], (int)size[1], (int)size[2], (int)local[0], (int)local[1], (int)local[2]); + return -1; + } + + // Verify that the kernel will only execute with that size. + in = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(cl_int)*global[0], NULL, &error); + test_error(error, "clCreateBuffer failed"); + out = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(cl_int)*global[0], NULL, &error); + test_error(error, "clCreateBuffer failed"); + + error = clSetKernelArg(kernel, 0, sizeof(in), &in); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 1, sizeof(out), &out); + test_error(error, "clSetKernelArg failed"); + + error = clEnqueueNDRangeKernel(queue, kernel, 3, NULL, global, local, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + error = clFinish(queue); + test_error(error, "clFinish failed"); + + log_info("kernel_required_group_size may report spurious ERRORS in the conformance log.\n"); + + local[0]++; + error = clEnqueueNDRangeKernel(queue, kernel, 3, NULL, global, local, 0, NULL, NULL); + if (error != CL_INVALID_WORK_GROUP_SIZE) { + log_error("Incorrect error returned for executing a kernel with the wrong required local work group size. (used %d,%d,%d, required %d,%d,%d)\n", + (int)local[0], (int)local[1], (int)local[2], (int)local[0]-1, (int)local[1], (int)local[2] ); + print_error(error, "Expected: CL_INVALID_WORK_GROUP_SIZE."); + return -1; + } + + error = clFinish(queue); + test_error(error, "clFinish failed"); + + if (max_dimensions == 1) { + free(source); + return 0; + } + + local[0]--; local[1]++; + error = clEnqueueNDRangeKernel(queue, kernel, 3, NULL, global, local, 0, NULL, NULL); + if (error != CL_INVALID_WORK_GROUP_SIZE) { + log_error("Incorrect error returned for executing a kernel with the wrong required local work group size. (used %d,%d,%d, required %d,%d,%d)\n", + (int)local[0], (int)local[1], (int)local[2], (int)local[0]-1, (int)local[1], (int)local[2]); + print_error(error, "Expected: CL_INVALID_WORK_GROUP_SIZE."); + return -1; + } + + error = clFinish(queue); + test_error(error, "clFinish failed"); + + if (max_dimensions == 2) { + return 0; + free(source); + } + + local[1]--; local[2]++; + error = clEnqueueNDRangeKernel(queue, kernel, 3, NULL, global, local, 0, NULL, NULL); + if (error != CL_INVALID_WORK_GROUP_SIZE) { + log_error("Incorrect error returned for executing a kernel with the wrong required local work group size. (used %d,%d,%d, required %d,%d,%d)\n", + (int)local[0], (int)local[1], (int)local[2], (int)local[0]-1, (int)local[1], (int)local[2]); + print_error(error, "Expected: CL_INVALID_WORK_GROUP_SIZE."); + return -1; + } + + error = clFinish(queue); + test_error(error, "clFinish failed"); + free(source); + } + + return 0; +} + + diff --git a/test_conformance/compatibility/test_conformance/api/test_retain.cpp b/test_conformance/compatibility/test_conformance/api/test_retain.cpp new file mode 100644 index 00000000..0fa0ac6b --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/test_retain.cpp @@ -0,0 +1,234 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#if !defined(_WIN32) +#include +#endif // !_WIN32 + +// Note: According to spec, the various functions to get instance counts should return an error when passed in an object +// that has already been released. However, the spec is out of date. If it gets re-updated to allow such action, re-enable +// this define. +//#define VERIFY_AFTER_RELEASE 1 + +#define GET_QUEUE_INSTANCE_COUNT(p) numInstances = ( (err = clGetCommandQueueInfo(p, CL_QUEUE_REFERENCE_COUNT, sizeof( numInstances ), &numInstances, NULL)) == CL_SUCCESS ? numInstances : 0 ) +#define GET_MEM_INSTANCE_COUNT(p) numInstances = ( (err = clGetMemObjectInfo(p, CL_MEM_REFERENCE_COUNT, sizeof( numInstances ), &numInstances, NULL)) == CL_SUCCESS ? numInstances : 0 ) + +#define VERIFY_INSTANCE_COUNT(c,rightValue) if( c != rightValue ) { \ +log_error( "ERROR: Instance count for test object is not valid! (should be %d, really is %d)\n", rightValue, c ); \ +return -1; } + +int test_retain_queue_single(cl_device_id deviceID, cl_context context, cl_command_queue queueNotUsed, int num_elements) +{ + cl_command_queue queue; + cl_uint numInstances; + int err; + + + /* Create a test queue */ + queue = clCreateCommandQueue( context, deviceID, 0, &err ); + test_error( err, "Unable to create command queue to test with" ); + + /* Test the instance count */ + GET_QUEUE_INSTANCE_COUNT( queue ); + test_error( err, "Unable to get queue instance count" ); + VERIFY_INSTANCE_COUNT( numInstances, 1 ); + + /* Now release the program */ + clReleaseCommandQueue( queue ); +#ifdef VERIFY_AFTER_RELEASE + /* We're not allowed to get the instance count after the object has been completely released. But that's + exactly how we can tell the release worked--by making sure getting the instance count fails! */ + GET_QUEUE_INSTANCE_COUNT( queue ); + if( err != CL_INVALID_COMMAND_QUEUE ) + { + print_error( err, "Command queue was not properly released" ); + return -1; + } +#endif + + return 0; +} + +int test_retain_queue_multiple(cl_device_id deviceID, cl_context context, cl_command_queue queueNotUsed, int num_elements) +{ + cl_command_queue queue; + unsigned int numInstances, i; + int err; + + + /* Create a test program */ + queue = clCreateCommandQueue( context, deviceID, 0, &err ); + test_error( err, "Unable to create command queue to test with" ); + + /* Increment 9 times, which should bring the count to 10 */ + for( i = 0; i < 9; i++ ) + { + clRetainCommandQueue( queue ); + } + + /* Test the instance count */ + GET_QUEUE_INSTANCE_COUNT( queue ); + test_error( err, "Unable to get queue instance count" ); + VERIFY_INSTANCE_COUNT( numInstances, 10 ); + + /* Now release 5 times, which should take us to 5 */ + for( i = 0; i < 5; i++ ) + { + clReleaseCommandQueue( queue ); + } + + GET_QUEUE_INSTANCE_COUNT( queue ); + test_error( err, "Unable to get queue instance count" ); + VERIFY_INSTANCE_COUNT( numInstances, 5 ); + + /* Retain again three times, which should take us to 8 */ + for( i = 0; i < 3; i++ ) + { + clRetainCommandQueue( queue ); + } + + GET_QUEUE_INSTANCE_COUNT( queue ); + test_error( err, "Unable to get queue instance count" ); + VERIFY_INSTANCE_COUNT( numInstances, 8 ); + + /* Release 7 times, which should take it to 1 */ + for( i = 0; i < 7; i++ ) + { + clReleaseCommandQueue( queue ); + } + + GET_QUEUE_INSTANCE_COUNT( queue ); + test_error( err, "Unable to get queue instance count" ); + VERIFY_INSTANCE_COUNT( numInstances, 1 ); + + /* And one last one */ + clReleaseCommandQueue( queue ); + +#ifdef VERIFY_AFTER_RELEASE + /* We're not allowed to get the instance count after the object has been completely released. But that's + exactly how we can tell the release worked--by making sure getting the instance count fails! */ + GET_QUEUE_INSTANCE_COUNT( queue ); + if( err != CL_INVALID_COMMAND_QUEUE ) + { + print_error( err, "Command queue was not properly released" ); + return -1; + } +#endif + + return 0; +} + +int test_retain_mem_object_single(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem object; + cl_uint numInstances; + int err; + + + /* Create a test object */ + object = clCreateBuffer( context, CL_MEM_READ_ONLY, 32, NULL, &err ); + test_error( err, "Unable to create buffer to test with" ); + + /* Test the instance count */ + GET_MEM_INSTANCE_COUNT( object ); + test_error( err, "Unable to get mem object count" ); + VERIFY_INSTANCE_COUNT( numInstances, 1 ); + + /* Now release the program */ + clReleaseMemObject( object ); +#ifdef VERIFY_AFTER_RELEASE + /* We're not allowed to get the instance count after the object has been completely released. But that's + exactly how we can tell the release worked--by making sure getting the instance count fails! */ + GET_MEM_INSTANCE_COUNT( object ); + if( err != CL_INVALID_MEM_OBJECT ) + { + print_error( err, "Mem object was not properly released" ); + return -1; + } +#endif + + return 0; +} + +int test_retain_mem_object_multiple(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem object; + unsigned int numInstances, i; + int err; + + + /* Create a test object */ + object = clCreateBuffer( context, CL_MEM_READ_ONLY, 32, NULL, &err ); + test_error( err, "Unable to create buffer to test with" ); + + /* Increment 9 times, which should bring the count to 10 */ + for( i = 0; i < 9; i++ ) + { + clRetainMemObject( object ); + } + + /* Test the instance count */ + GET_MEM_INSTANCE_COUNT( object ); + test_error( err, "Unable to get mem object count" ); + VERIFY_INSTANCE_COUNT( numInstances, 10 ); + + /* Now release 5 times, which should take us to 5 */ + for( i = 0; i < 5; i++ ) + { + clReleaseMemObject( object ); + } + + GET_MEM_INSTANCE_COUNT( object ); + test_error( err, "Unable to get mem object count" ); + VERIFY_INSTANCE_COUNT( numInstances, 5 ); + + /* Retain again three times, which should take us to 8 */ + for( i = 0; i < 3; i++ ) + { + clRetainMemObject( object ); + } + + GET_MEM_INSTANCE_COUNT( object ); + test_error( err, "Unable to get mem object count" ); + VERIFY_INSTANCE_COUNT( numInstances, 8 ); + + /* Release 7 times, which should take it to 1 */ + for( i = 0; i < 7; i++ ) + { + clReleaseMemObject( object ); + } + + GET_MEM_INSTANCE_COUNT( object ); + test_error( err, "Unable to get mem object count" ); + VERIFY_INSTANCE_COUNT( numInstances, 1 ); + + /* And one last one */ + clReleaseMemObject( object ); + +#ifdef VERIFY_AFTER_RELEASE + /* We're not allowed to get the instance count after the object has been completely released. But that's + exactly how we can tell the release worked--by making sure getting the instance count fails! */ + GET_MEM_INSTANCE_COUNT( object ); + if( err != CL_INVALID_MEM_OBJECT ) + { + print_error( err, "Mem object was not properly released" ); + return -1; + } +#endif + + return 0; +} + diff --git a/test_conformance/compatibility/test_conformance/api/test_retain_program.c b/test_conformance/compatibility/test_conformance/api/test_retain_program.c new file mode 100644 index 00000000..7fe22f0c --- /dev/null +++ b/test_conformance/compatibility/test_conformance/api/test_retain_program.c @@ -0,0 +1,109 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +#if !defined(_WIN32) +#include +#endif + +#include "../../test_common/harness/compat.h" + +int test_release_kernel_order(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_program program; + cl_kernel kernel; + int error; + const char *testProgram[] = { "__kernel void sample_test(__global int *data){}" }; + + /* Create a test program */ + program = clCreateProgramWithSource( context, 1, testProgram, NULL, &error); + test_error( error, "Unable to create program to test with" ); + + /* Compile the program */ + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build sample program to test with" ); + + /* And create a kernel from it */ + kernel = clCreateKernel( program, "sample_test", &error ); + test_error( error, "Unable to create kernel" ); + + /* Now try freeing the program first, then the kernel. If refcounts are right, this should work just fine */ + clReleaseProgram( program ); + clReleaseKernel( kernel ); + + /* If we got here fine, we succeeded. If not, well, we won't be able to return an error :) */ + return 0; +} + +const char *sample_delay_kernel[] = { +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +" for( int i = 0; i < 1000000; i++ ); \n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n" }; + +int test_release_during_execute( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + cl_kernel kernel; + cl_mem streams[2]; + size_t threads[1] = { 10 }, localThreadSize; + + + /* We now need an event to test. So we'll execute a kernel to get one */ + if( create_single_kernel_helper( context, &program, &kernel, 1, sample_delay_kernel, "sample_test" ) ) + { + return -1; + } + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 10, NULL, &error); + test_error( error, "Creating test array failed" ); + + /* Set the arguments */ + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[ 0 ]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[ 1 ]); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreadSize ); + test_error( error, "Unable to calc local thread size" ); + + + /* Execute the kernel */ + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, &localThreadSize, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* The kernel should still be executing, but we should still be able to release it. It's not terribly + useful, but we should be able to do it, if the internal refcounting is indeed correct. */ + + clReleaseMemObject( streams[ 1 ] ); + clReleaseMemObject( streams[ 0 ] ); + clReleaseKernel( kernel ); + clReleaseProgram( program ); + + /* Now make sure we're really finished before we go on. */ + error = clFinish(queue); + test_error( error, "Unable to finish context."); + + return 0; +} + + diff --git a/test_conformance/compatibility/test_conformance/basic/CMakeLists.txt b/test_conformance/compatibility/test_conformance/basic/CMakeLists.txt new file mode 100644 index 00000000..d6a5fe65 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/CMakeLists.txt @@ -0,0 +1,65 @@ +set(MODULE_NAME COMPATIBILITY_BASIC) + +set(${MODULE_NAME}_SOURCES + main.c + test_fpmath_float.c test_fpmath_float2.c test_fpmath_float4.c + test_intmath_int.c test_intmath_int2.c test_intmath_int4.c + test_intmath_long.c test_intmath_long2.c test_intmath_long4.c + test_hiloeo.c test_local.c test_pointercast.c + test_if.c test_loop.c + test_readimage.c test_readimage_int16.c test_readimage_fp32.c + test_readimage3d.c test_readimage3d_int16.c test_readimage3d_fp32.c + test_writeimage.c test_writeimage_int16.c test_writeimage_fp32.c + test_multireadimageonefmt.c test_multireadimagemultifmt.c + test_imagedim.c + test_vloadstore.c + test_int2float.c test_float2int.c + test_createkernelsinprogram.c + test_hostptr.c + test_explicit_s2v.cpp + test_constant.c + test_image_multipass.c + test_imagereadwrite.c test_imagereadwrite3d.c + test_image_param.c + test_imagenpot.c + test_image_r8.c + test_barrier.c + test_basic_parameter_types.c + test_arrayreadwrite.c + test_arraycopy.c + test_imagearraycopy.c + test_imagearraycopy3d.c + test_imagecopy.c + test_imagerandomcopy.c + test_arrayimagecopy.c + test_arrayimagecopy3d.c + test_imagecopy3d.c + test_enqueue_map.cpp + test_work_item_functions.cpp + test_astype.cpp + test_async_copy.cpp + test_sizeof.c + test_vector_creation.cpp + test_vec_type_hint.c + test_numeric_constants.cpp + test_constant_source.cpp + test_bufferreadwriterect.c + test_async_strided_copy.cpp + test_preprocessors.cpp + test_kernel_memory_alignment.cpp + test_global_work_offsets.cpp + test_kernel_call_kernel_function.cpp + test_local_kernel_scope.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/typeWrappers.cpp + ../../test_common/harness/imageHelpers.cpp + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/rounding_mode.c + ../../test_common/harness/msvc9.c +) + +include(../../../CMakeCommon.txt) diff --git a/test_conformance/compatibility/test_conformance/basic/Jamfile b/test_conformance/compatibility/test_conformance/basic/Jamfile new file mode 100644 index 00000000..02c3fca9 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/Jamfile @@ -0,0 +1,75 @@ +project + : requirements + gcc:-xc++ + msvc:"/TP" + ; + +exe test_basic + : main.c + test_arraycopy.c + test_arrayimagecopy3d.c + test_arrayimagecopy.c + test_arrayreadwrite.c + test_astype.cpp + test_async_copy.cpp + test_barrier.c + test_basic_parameter_types.c + test_constant.c + test_createkernelsinprogram.c + test_enqueue_map.cpp + test_explicit_s2v.cpp + test_float2int.c + test_fpmath_float2.c + test_fpmath_float4.c + test_fpmath_float.c + test_hiloeo.c + test_hostptr.c + test_if.c + test_imagearraycopy3d.c + test_imagearraycopy.c + test_imagecopy3d.c + test_imagecopy.c + test_imagedim.c + test_image_multipass.c + test_imagenpot.c + test_image_param.c + test_image_r8.c + test_imagerandomcopy.c + test_imagereadwrite3d.c + test_imagereadwrite.c + test_int2float.c + test_intmath_int2.c + test_intmath_int4.c + test_intmath_int.c + test_intmath_long2.c + test_intmath_long4.c + test_intmath_long.c + test_local.c + test_loop.c + test_multireadimagemultifmt.c + test_multireadimageonefmt.c + test_pointercast.c + test_readimage3d.c + test_readimage3d_fp32.c + test_readimage3d_int16.c + test_readimage.c + test_readimage_fp32.c + test_readimage_int16.c + test_sizeof.c + test_vec_type_hint.c + test_vector_creation.cpp + test_vloadstore.c + test_work_item_functions.cpp + test_writeimage.c + test_writeimage_fp32.c + test_writeimage_int16.c + test_numeric_constants.cpp + test_kernel_call_kernel_function.cpp + ; + +install dist + : test_basic + : debug:$(DIST)/debug/tests/test_conformance/basic + release:$(DIST)/release/tests/test_conformance/basic + ; + \ No newline at end of file diff --git a/test_conformance/compatibility/test_conformance/basic/Makefile b/test_conformance/compatibility/test_conformance/basic/Makefile new file mode 100644 index 00000000..eaa45ce2 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/Makefile @@ -0,0 +1,94 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + test_fpmath_float.c test_fpmath_float2.c test_fpmath_float4.c \ + test_intmath_int.c test_intmath_int2.c test_intmath_int4.c \ + test_intmath_long.c test_intmath_long2.c test_intmath_long4.c \ + test_hiloeo.c test_local.c test_local_kernel_scope.cpp test_pointercast.c \ + test_if.c test_sizeof.c test_loop.c \ + test_readimage.c test_readimage_int16.c test_readimage_fp32.c \ + test_readimage3d.c test_readimage3d_int16.c test_readimage3d_fp32.c \ + test_writeimage.c test_writeimage_int16.c test_writeimage_fp32.c \ + test_multireadimageonefmt.c test_multireadimagemultifmt.c \ + test_imagedim.c \ + test_vloadstore.c \ + test_int2float.c test_float2int.c \ + test_createkernelsinprogram.c \ + test_hostptr.c \ + test_explicit_s2v.cpp \ + test_constant.c \ + test_constant_source.cpp \ + test_image_multipass.c \ + test_imagereadwrite.c test_imagereadwrite3d.c \ + test_bufferreadwriterect.c \ + test_image_param.c \ + test_imagenpot.c \ + test_image_r8.c \ + test_barrier.c \ + test_arrayreadwrite.c \ + test_arraycopy.c \ + test_imagearraycopy.c \ + test_imagearraycopy3d.c \ + test_imagecopy.c \ + test_imagerandomcopy.c \ + test_arrayimagecopy.c \ + test_arrayimagecopy3d.c\ + test_imagecopy3d.c \ + test_enqueue_map.cpp \ + test_work_item_functions.cpp \ + test_astype.cpp \ + test_async_copy.cpp \ + test_async_strided_copy.cpp \ + test_numeric_constants.cpp \ + test_kernel_call_kernel_function.cpp \ + test_basic_parameter_types.c \ + test_vector_creation.cpp \ + test_vec_type_hint.c \ + test_preprocessors.cpp \ + test_kernel_memory_alignment.cpp \ + test_global_work_offsets.cpp \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/rounding_mode.c \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/typeWrappers.cpp \ + ../../test_common/harness/imageHelpers.cpp \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/conversions.c + +DEFINES = + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = $(SOURCES) +HEADERS = +TARGET = test_basic +INCLUDE = +COMPILERFLAGS = -c -Wall -g -O0 -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. + + + diff --git a/test_conformance/compatibility/test_conformance/basic/main.c b/test_conformance/compatibility/test_conformance/basic/main.c new file mode 100644 index 00000000..fd6ae953 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/main.c @@ -0,0 +1,263 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#if !defined(_WIN32) +#include +#endif + +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "procs.h" + +// FIXME: To use certain functions in ../../test_common/harness/imageHelpers.h +// (for example, generate_random_image_data()), the tests are required to declare +// the following variables: +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +bool gTestRounding = false; + +basefn basefn_list[] = { + test_hostptr, + test_fpmath_float, + test_fpmath_float2, + test_fpmath_float4, + test_intmath_int, + test_intmath_int2, + test_intmath_int4, + test_intmath_long, + test_intmath_long2, + test_intmath_long4, + test_hiloeo, + test_if, + test_sizeof, + test_loop, + test_pointer_cast, + test_local_arg_def, + test_local_kernel_def, + test_local_kernel_scope, + test_constant, + test_constant_source, + test_readimage, + test_readimage_int16, + test_readimage_fp32, + test_writeimage, + test_writeimage_int16, + test_writeimage_fp32, + test_multireadimageonefmt, + + test_multireadimagemultifmt, + test_image_r8, + test_barrier, + test_int2float, + test_float2int, + test_imagereadwrite, + test_imagereadwrite3d, + test_readimage3d, + test_readimage3d_int16, + test_readimage3d_fp32, + test_bufferreadwriterect, + test_arrayreadwrite, + test_arraycopy, + test_imagearraycopy, + test_imagearraycopy3d, + test_imagecopy, + test_imagecopy3d, + test_imagerandomcopy, + test_arrayimagecopy, + test_arrayimagecopy3d, + test_imagenpot, + + test_vload_global, + test_vload_local, + test_vload_constant, + test_vload_private, + test_vstore_global, + test_vstore_local, + test_vstore_private, + + test_createkernelsinprogram, + test_imagedim_pow2, + test_imagedim_non_pow2, + test_image_param, + test_image_multipass_integer_coord, + test_image_multipass_float_coord, + test_explicit_s2v_bool, + test_explicit_s2v_char, + test_explicit_s2v_uchar, + test_explicit_s2v_short, + test_explicit_s2v_ushort, + test_explicit_s2v_int, + test_explicit_s2v_uint, + test_explicit_s2v_long, + test_explicit_s2v_ulong, + test_explicit_s2v_float, + test_explicit_s2v_double, + + test_enqueue_map_buffer, + test_enqueue_map_image, + + test_work_item_functions, + + test_astype, + + test_async_copy_global_to_local, + test_async_copy_local_to_global, + test_async_strided_copy_global_to_local, + test_async_strided_copy_local_to_global, + test_prefetch, + + test_kernel_call_kernel_function, + test_host_numeric_constants, + test_kernel_numeric_constants, + test_kernel_limit_constants, + test_kernel_preprocessor_macros, + + test_basic_parameter_types, + test_vector_creation, + test_vec_type_hint, + test_kernel_memory_alignment_local, + test_kernel_memory_alignment_global, + test_kernel_memory_alignment_constant, + test_kernel_memory_alignment_private, + + test_global_work_offsets, + test_get_global_offset +}; + +const char *basefn_names[] = { + "hostptr", + "fpmath_float", + "fpmath_float2", + "fpmath_float4", + "intmath_int", + "intmath_int2", + "intmath_int4", + "intmath_long", + "intmath_long2", + "intmath_long4", + "hiloeo", + "if", + "sizeof", + "loop", + "pointer_cast", + "local_arg_def", + "local_kernel_def", + "local_kernel_scope", + "constant", + "constant_source", + "readimage", + "readimage_int16", + "readimage_fp32", + "writeimage", + "writeimage_int16", + "writeimage_fp32", + "mri_one", + + "mri_multiple", + "image_r8", + "barrier", + "int2float", + "float2int", + "imagereadwrite", + "imagereadwrite3d", + "readimage3d", + "readimage3d_int16", + "readimage3d_fp32", + "bufferreadwriterect", + "arrayreadwrite", + "arraycopy", + "imagearraycopy", + "imagearraycopy3d", + "imagecopy", + "imagecopy3d", + "imagerandomcopy", + "arrayimagecopy", + "arrayimagecopy3d", + "imagenpot", + + "vload_global", + "vload_local", + "vload_constant", + "vload_private", + "vstore_global", + "vstore_local", + "vstore_private", + + "createkernelsinprogram", + "imagedim_pow2", + "imagedim_non_pow2", + "image_param", + "image_multipass_integer_coord", + "image_multipass_float_coord", + "explicit_s2v_bool", + "explicit_s2v_char", + "explicit_s2v_uchar", + "explicit_s2v_short", + "explicit_s2v_ushort", + "explicit_s2v_int", + "explicit_s2v_uint", + "explicit_s2v_long", + "explicit_s2v_ulong", + "explicit_s2v_float", + "explicit_s2v_double", + + "enqueue_map_buffer", + "enqueue_map_image", + + "work_item_functions", + + "astype", + + "async_copy_global_to_local", + "async_copy_local_to_global", + "async_strided_copy_global_to_local", + "async_strided_copy_local_to_global", + "prefetch", + + "kernel_call_kernel_function", + "host_numeric_constants", + "kernel_numeric_constants", + "kernel_limit_constants", + "kernel_preprocessor_macros", + + "parameter_types", + + "vector_creation", + "vec_type_hint", + + "kernel_memory_alignment_local", + "kernel_memory_alignment_global", + "kernel_memory_alignment_constant", + "kernel_memory_alignment_private", + + "global_work_offsets", + "get_global_offset", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + + +int main(int argc, const char *argv[]) +{ + int err = runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false, false, 0 ); + return err; +} + + + diff --git a/test_conformance/compatibility/test_conformance/basic/procs.h b/test_conformance/compatibility/test_conformance/basic/procs.h new file mode 100644 index 00000000..b5b5ce6f --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/procs.h @@ -0,0 +1,142 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/rounding_mode.h" + +extern void memset_pattern4(void *dest, const void *src_pattern, size_t bytes ); + +extern int test_hostptr(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_fpmath_float(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_fpmath_float2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_fpmath_float4(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_intmath_int(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_intmath_int2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_intmath_int4(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_intmath_long(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_intmath_long2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_intmath_long4(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_hiloeo(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_if(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_sizeof(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_loop(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_pointer_cast(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_local_arg_def(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_local_kernel_def(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_local_kernel_scope(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_constant(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_constant_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_readimage(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_readimage_int16(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_readimage_fp32(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_writeimage(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_writeimage_int16(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_writeimage_fp32(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_multireadimageonefmt(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_multireadimagemultifmt(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_image_r8(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_simplebarrier(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_barrier(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_int2float(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_float2int(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagearraycopy(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagearraycopy3d(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagereadwrite(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagereadwrite3d(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_readimage3d(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_readimage3d_int16(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_readimage3d_fp32(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_bufferreadwriterect(cl_device_id device, cl_context context, cl_command_queue queue_, int num_elements); +extern int test_imagecopy(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagecopy3d(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagerandomcopy(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_arraycopy(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems); +extern int test_arrayimagecopy(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_arrayimagecopy3d(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagenpot(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_sampler_float(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_sampler_int(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_createkernelsinprogram(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_single_large_allocation(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_multiple_max_allocation(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_arrayreadwrite(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagedim_pow2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_imagedim_non_pow2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_image_param(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_image_multipass_integer_coord(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_image_multipass_float_coord(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_vload_global(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vload_local(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vload_constant(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vload_private(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vstore_global(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vstore_local(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vstore_private(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_explicit_s2v_bool(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_char(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_uchar(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_short(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_ushort(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_int(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_uint(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_long(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_ulong(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_float(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_explicit_s2v_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_enqueue_map_buffer(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_enqueue_map_image(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_work_item_functions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_astype(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_native_kernel(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_async_copy_global_to_local(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_async_copy_local_to_global(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_async_strided_copy_global_to_local(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_async_strided_copy_local_to_global(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_prefetch(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_host_numeric_constants(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_kernel_numeric_constants(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_kernel_limit_constants(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_kernel_preprocessor_macros(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_kernel_call_kernel_function(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_basic_parameter_types(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vector_creation(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_vec_type_hint(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + + +extern int test_kernel_memory_alignment_local(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); +extern int test_kernel_memory_alignment_global(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); +extern int test_kernel_memory_alignment_constant(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); +extern int test_kernel_memory_alignment_private(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); + +extern int test_global_work_offsets(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); +extern int test_get_global_offset(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); + + + diff --git a/test_conformance/compatibility/test_conformance/basic/run_array b/test_conformance/compatibility/test_conformance/basic/run_array new file mode 100644 index 00000000..07d67892 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/run_array @@ -0,0 +1,3 @@ +#!/bin/sh +cd `dirname $0` +./test_basic arrayreadwrite arraycopy bufferreadwriterect $@ diff --git a/test_conformance/compatibility/test_conformance/basic/run_array_image_copy b/test_conformance/compatibility/test_conformance/basic/run_array_image_copy new file mode 100644 index 00000000..f88ec2a0 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/run_array_image_copy @@ -0,0 +1,3 @@ +#!/bin/sh +cd `dirname $0` +./test_basic arrayimagecopy arrayimagecopy3d imagearraycopy diff --git a/test_conformance/compatibility/test_conformance/basic/run_image b/test_conformance/compatibility/test_conformance/basic/run_image new file mode 100644 index 00000000..9bb5ee1b --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/run_image @@ -0,0 +1,17 @@ +#!/bin/sh +cd `dirname $0` +./test_basic \ +imagecopy imagerandomcopy \ +imagearraycopy imagearraycopy3d \ +image_r8 \ +readimage readimage_int16 readimage_fp32 \ +writeimage writeimage_int16 writeimage_fp32 \ +imagenpot \ +image_param \ +image_multipass_integer_coord \ +readimage3d \ +readimage3d_int16 \ +readimage3d_fp32 \ +imagereadwrite3d \ +imagereadwrite \ +$@ diff --git a/test_conformance/compatibility/test_conformance/basic/run_multi_read_image b/test_conformance/compatibility/test_conformance/basic/run_multi_read_image new file mode 100644 index 00000000..aa87b1cd --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/run_multi_read_image @@ -0,0 +1,4 @@ +#!/bin/sh +cd `dirname $0` +./test_basic mri_one mri_multiple + diff --git a/test_conformance/compatibility/test_conformance/basic/test_arraycopy.c b/test_conformance/compatibility/test_conformance/basic/test_arraycopy.c new file mode 100644 index 00000000..5104c49b --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_arraycopy.c @@ -0,0 +1,201 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +const char *copy_kernel_code = +"__kernel void test_copy(__global unsigned int *src, __global unsigned int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = src[tid];\n" +"}\n"; + +int +test_arraycopy(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_uint *input_ptr, *output_ptr; + cl_mem streams[4], results; + cl_program program; + cl_kernel kernel; + unsigned num_elements = 128 * 1024; + cl_uint num_copies = 1; + size_t delta_offset; + unsigned i; + cl_int err; + MTdata d; + + int error_count = 0; + + input_ptr = (cl_uint*)malloc(sizeof(cl_uint) * num_elements); + output_ptr = (cl_uint*)malloc(sizeof(cl_uint) * num_elements); + + // results + results = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * num_elements, NULL, &err); + test_error(err, "clCreateBuffer failed"); + +/*****************************************************************************************************************************************/ +#pragma mark client backing + + log_info("Testing CL_MEM_USE_HOST_PTR buffer with clEnqueueCopyBuffer\n"); + // randomize data + d = init_genrand( gRandomSeed ); + for (i=0; i +#include +#include +#include + +#include "procs.h" + +int test_arrayimagecopy_single_format(cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format) +{ + cl_uchar *bufptr, *imgptr; + clMemWrapper buffer, image; + int img_width = 512; + int img_height = 512; + size_t elem_size; + size_t buffer_size; + int i; + cl_int err; + MTdata d; + cl_event copyevent; + + log_info("Testing %s %s\n", GetChannelOrderName(format->image_channel_order), GetChannelTypeName(format->image_channel_data_type)); + + image = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), format, img_width, img_height, 0, NULL, &err); + test_error(err, "create_image_2d failed"); + + err = clGetImageInfo(image, CL_IMAGE_ELEMENT_SIZE, sizeof(size_t), &elem_size, NULL); + test_error(err, "clGetImageInfo failed"); + + buffer_size = sizeof(cl_uchar) * elem_size * img_width * img_height; + + buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), buffer_size, NULL, &err); + test_error(err, "clCreateBuffer failed"); + + bufptr = (cl_uchar*)malloc(buffer_size); + + d = init_genrand( gRandomSeed ); + bufptr = (cl_uchar*)malloc(buffer_size); + for (i=0; i<(int)buffer_size; i++) { + bufptr[i] = (cl_uchar)genrand_int32(d); + } + free_mtdata(d); d = NULL; + + size_t origin[3]={0,0,0}, region[3]={img_width,img_height,1}; + err = clEnqueueWriteBuffer( queue, buffer, CL_TRUE, 0, buffer_size, bufptr, 0, NULL, NULL); + test_error(err, "clEnqueueWriteBuffer failed"); + + err = clEnqueueCopyBufferToImage( queue, buffer, image, 0, origin, region, 0, NULL, ©event ); + test_error(err, "clEnqueueCopyImageToBuffer failed"); + + imgptr = (cl_uchar*)malloc(buffer_size); + + err = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, imgptr, 1, ©event, NULL ); + test_error(err, "clEnqueueReadBuffer failed"); + + if (memcmp(bufptr, imgptr, buffer_size) != 0) { + log_error( "ERROR: Results did not validate!\n" ); + unsigned char * inchar = (unsigned char*)bufptr; + unsigned char * outchar = (unsigned char*)imgptr; + int failuresPrinted = 0; + int i; + for (i=0; i< (int)buffer_size; i+=(int)elem_size) { + int failed = 0; + int j; + for (j=0; j<(int)elem_size; j++) + if (inchar[i+j] != outchar[i+j]) + failed = 1; + char values[4096]; + values[0] = 0; + if (failed) { + sprintf(values + strlen(values), "%d(0x%x) -> actual [", i, i); + int j; + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", inchar[i+j]); + sprintf(values + strlen(values), "] != expected ["); + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", outchar[i+j]); + sprintf(values + strlen(values), "]"); + log_error("%s\n", values); + failuresPrinted++; + } + if (failuresPrinted > 5) { + log_error("Not printing further failures...\n"); + break; + } + } + err = -1; + } + + free(bufptr); + free(imgptr); + + if (err) + log_error("ARRAY to IMAGE copy test failed for image_channel_order=0x%lx and image_channel_data_type=0x%lx\n", + (unsigned long)format->image_channel_order, (unsigned long)format->image_channel_data_type); + + return err; +} + +int test_arrayimagecopy(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int err; + cl_image_format *formats; + cl_uint num_formats; + cl_uint i; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE2D, 0, NULL, &num_formats); + test_error(err, "clGetSupportedImageFormats failed"); + + formats = (cl_image_format *)malloc(num_formats * sizeof(cl_image_format)); + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE2D, num_formats, formats, NULL); + test_error(err, "clGetSupportedImageFormats failed"); + + for (i = 0; i < num_formats; i++) { + err |= test_arrayimagecopy_single_format(device, context, queue, &formats[i]); + } + + if (err) + log_error("ARRAY to IMAGE copy test failed\n"); + else + log_info("ARRAY to IMAGE copy test passed\n"); + + return err; +} diff --git a/test_conformance/compatibility/test_conformance/basic/test_arrayimagecopy3d.c b/test_conformance/compatibility/test_conformance/basic/test_arrayimagecopy3d.c new file mode 100644 index 00000000..5b7ed5a7 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_arrayimagecopy3d.c @@ -0,0 +1,144 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +int test_arrayimagecopy3d_single_format(cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format) +{ + cl_uchar *bufptr, *imgptr; + clMemWrapper buffer, image; + int img_width = 128; + int img_height = 128; + int img_depth = 32; + size_t elem_size; + size_t buffer_size; + int i; + cl_int err; + MTdata d; + cl_event copyevent; + + log_info("Testing %s %s\n", GetChannelOrderName(format->image_channel_order), GetChannelTypeName(format->image_channel_data_type)); + + image = create_image_3d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), format, img_width, img_height, img_depth, 0, 0, NULL, &err); + test_error(err, "create_image_3d failed"); + + err = clGetImageInfo(image, CL_IMAGE_ELEMENT_SIZE, sizeof(size_t), &elem_size, NULL); + test_error(err, "clGetImageInfo failed"); + + buffer_size = sizeof(cl_uchar) * elem_size * img_width * img_height * img_depth; + + buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), buffer_size, NULL, &err); + test_error(err, "clCreateBuffer failed"); + + bufptr = (cl_uchar*)malloc(buffer_size); + + d = init_genrand( gRandomSeed ); + bufptr = (cl_uchar*)malloc(buffer_size); + for (i=0; i<(int)buffer_size; i++) { + bufptr[i] = (cl_uchar)genrand_int32(d); + } + free_mtdata(d); d = NULL; + + size_t origin[3]={0,0,0}, region[3]={img_width,img_height,img_depth}; + err = clEnqueueWriteBuffer( queue, buffer, CL_TRUE, 0, buffer_size, bufptr, 0, NULL, NULL); + test_error(err, "clEnqueueWriteBuffer failed"); + + err = clEnqueueCopyBufferToImage( queue, buffer, image, 0, origin, region, 0, NULL, ©event ); + test_error(err, "clEnqueueCopyImageToBuffer failed"); + + imgptr = (cl_uchar*)malloc(buffer_size); + + err = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, imgptr, 1, ©event, NULL ); + test_error(err, "clEnqueueReadBuffer failed"); + + if (memcmp(bufptr, imgptr, buffer_size) != 0) { + log_error( "ERROR: Results did not validate!\n" ); + unsigned char * inchar = (unsigned char*)bufptr; + unsigned char * outchar = (unsigned char*)imgptr; + int failuresPrinted = 0; + int i; + for (i=0; i< (int)buffer_size; i+=(int)elem_size) { + int failed = 0; + int j; + for (j=0; j<(int)elem_size; j++) + if (inchar[i+j] != outchar[i+j]) + failed = 1; + char values[4096]; + values[0] = 0; + if (failed) { + sprintf(values + strlen(values), "%d(0x%x) -> actual [", i, i); + int j; + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", inchar[i+j]); + sprintf(values + strlen(values), "] != expected ["); + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", outchar[i+j]); + sprintf(values + strlen(values), "]"); + log_error("%s\n", values); + failuresPrinted++; + } + if (failuresPrinted > 5) { + log_error("Not printing further failures...\n"); + break; + } + } + err = -1; + } + + free(bufptr); + free(imgptr); + + if (err) + log_error("ARRAY to IMAGE3D copy test failed for image_channel_order=0x%lx and image_channel_data_type=0x%lx\n", + (unsigned long)format->image_channel_order, (unsigned long)format->image_channel_data_type); + + return err; +} + +int test_arrayimagecopy3d(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int err; + cl_image_format *formats; + cl_uint num_formats; + cl_uint i; + + PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( device ) + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE3D, 0, NULL, &num_formats); + test_error(err, "clGetSupportedImageFormats failed"); + + formats = (cl_image_format *)malloc(num_formats * sizeof(cl_image_format)); + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE3D, num_formats, formats, NULL); + test_error(err, "clGetSupportedImageFormats failed"); + + for (i = 0; i < num_formats; i++) { + err |= test_arrayimagecopy3d_single_format(device, context, queue, &formats[i]); + } + + if (err) + log_error("ARRAY to IMAGE3D copy test failed\n"); + else + log_info("ARRAY to IMAGE3D copy test passed\n"); + + return err; +} diff --git a/test_conformance/compatibility/test_conformance/basic/test_arrayreadwrite.c b/test_conformance/compatibility/test_conformance/basic/test_arrayreadwrite.c new file mode 100644 index 00000000..3a58c6aa --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_arrayreadwrite.c @@ -0,0 +1,94 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + + +int +test_arrayreadwrite(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_uint *inptr, *outptr; + cl_mem streams[1]; + int num_tries = 400; + num_elements = 1024 * 1024 * 4; + int i, j, err; + MTdata d; + + inptr = (cl_uint*)malloc(num_elements*sizeof(cl_uint)); + outptr = (cl_uint*)malloc(num_elements*sizeof(cl_uint)); + + // randomize data + d = init_genrand( gRandomSeed ); + for (i=0; i 0 && offset < num_elements) + break; + } while (1); + cb = (int)(genrand_int32(d) & 0x7FFFFFFF); + if (cb > (num_elements - offset)) + cb = num_elements - offset; + + err = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, offset*sizeof(cl_uint), sizeof(cl_uint)*cb,&inptr[offset], 0, NULL, NULL); + test_error(err, "clEnqueueWriteBuffer failed"); + + err = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, offset*sizeof(cl_uint), cb*sizeof(cl_uint), &outptr[offset], 0, NULL, NULL ); + test_error(err, "clEnqueueReadBuffer failed"); + + for (j=offset; j +#include +#include +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" + + +static const char *astype_kernel_pattern = +"%s\n" +"__kernel void test_fn( __global %s%s *src, __global %s%s *dst )\n" +"{\n" +" int tid = get_global_id( 0 );\n" +" %s%s tmp = as_%s%s( src[ tid ] );\n" +" dst[ tid ] = tmp;\n" +"}\n"; + +static const char *astype_kernel_pattern_V3srcV3dst = +"%s\n" +"__kernel void test_fn( __global %s *src, __global %s *dst )\n" +"{\n" +" int tid = get_global_id( 0 );\n" +" %s%s tmp = as_%s%s( vload3(tid,src) );\n" +" vstore3(tmp,tid,dst);\n" +"}\n"; +// in the printf, remove the third and fifth argument, each of which +// should be a "3", when copying from the printf for astype_kernel_pattern + +static const char *astype_kernel_pattern_V3dst = +"%s\n" +"__kernel void test_fn( __global %s%s *src, __global %s *dst )\n" +"{\n" +" int tid = get_global_id( 0 );\n" +" %s3 tmp = as_%s3( src[ tid ] );\n" +" vstore3(tmp,tid,dst);\n" +"}\n"; +// in the printf, remove the fifth argument, which +// should be a "3", when copying from the printf for astype_kernel_pattern + + +static const char *astype_kernel_pattern_V3src = +"%s\n" +"__kernel void test_fn( __global %s *src, __global %s%s *dst )\n" +"{\n" +" int tid = get_global_id( 0 );\n" +" %s%s tmp = as_%s%s( vload3(tid,src) );\n" +" dst[ tid ] = tmp;\n" +"}\n"; +// in the printf, remove the third argument, which +// should be a "3", when copying from the printf for astype_kernel_pattern + + +int test_astype_set( cl_device_id device, cl_context context, cl_command_queue queue, ExplicitType inVecType, ExplicitType outVecType, + unsigned int vecSize, unsigned int outVecSize, + int numElements ) +{ + int error; + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 2 ]; + + char programSrc[ 10240 ]; + size_t threads[ 1 ], localThreads[ 1 ]; + size_t typeSize = get_explicit_type_size( inVecType ); + size_t outTypeSize = get_explicit_type_size(outVecType); + char sizeNames[][ 3 ] = { "", "", "2", "3", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + MTdata d; + + + + // Create program + if(outVecSize == 3 && vecSize == 3) { + // astype_kernel_pattern_V3srcV3dst + sprintf( programSrc, astype_kernel_pattern_V3srcV3dst, + (outVecType == kDouble || inVecType == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name( inVecType ), // sizeNames[ vecSize ], + get_explicit_type_name( outVecType ), // sizeNames[ outVecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ] ); + } else if(outVecSize == 3) { + // astype_kernel_pattern_V3dst + sprintf( programSrc, astype_kernel_pattern_V3dst, + (outVecType == kDouble || inVecType == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name( inVecType ), sizeNames[ vecSize ], + get_explicit_type_name( outVecType ), + get_explicit_type_name( outVecType ), + get_explicit_type_name( outVecType )); + + } else if(vecSize == 3) { + // astype_kernel_pattern_V3src + sprintf( programSrc, astype_kernel_pattern_V3src, + (outVecType == kDouble || inVecType == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name( inVecType ),// sizeNames[ vecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ]); + } else { + sprintf( programSrc, astype_kernel_pattern, + (outVecType == kDouble || inVecType == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name( inVecType ), sizeNames[ vecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ], + get_explicit_type_name( outVecType ), sizeNames[ outVecSize ]); + } + + const char *ptr = programSrc; + error = create_single_kernel_helper( context, &program, &kernel, 1, &ptr, "test_fn" ); + test_error( error, "Unable to create testing kernel" ); + + + // Create some input values + size_t inBufferSize = sizeof(char)* numElements * get_explicit_type_size( inVecType ) * vecSize; + char *inBuffer = (char*)malloc( inBufferSize ); + size_t outBufferSize = sizeof(char)* numElements * get_explicit_type_size( outVecType ) *outVecSize; + char *outBuffer = (char*)malloc( outBufferSize ); + + d = init_genrand( gRandomSeed ); + generate_random_data( inVecType, numElements * vecSize, + d, inBuffer ); + free_mtdata(d); d = NULL; + + // Create I/O streams and set arguments + streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, inBufferSize, inBuffer, &error ); + test_error( error, "Unable to create I/O stream" ); + streams[ 1 ] = clCreateBuffer( context, CL_MEM_READ_WRITE, outBufferSize, NULL, &error ); + test_error( error, "Unable to create I/O stream" ); + + error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[ 1 ] ), &streams[ 1 ] ); + test_error( error, "Unable to set kernel argument" ); + + + // Run the kernel + threads[ 0 ] = numElements; + error = get_max_common_work_group_size( context, kernel, threads[ 0 ], &localThreads[ 0 ] ); + test_error( error, "Unable to get group size to run with" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + + // Get the results and compare + // The beauty is that astype is supposed to return the bit pattern as a different type, which means + // the output should have the exact same bit pattern as the input. No interpretation necessary! + error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, outBufferSize, outBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + char *expected = inBuffer; + char *actual = outBuffer; + size_t compSize = typeSize*vecSize; + if(outTypeSize*outVecSize < compSize) { + compSize = outTypeSize*outVecSize; + } + + if(outVecSize == 4 && vecSize == 3) + { + // as_type4(vec3) should compile but produce undefined results?? + free(inBuffer); + free(outBuffer); + return 0; + } + + if(outVecSize != 3 && vecSize != 3 && outVecSize != vecSize) + { + // as_typen(vecm) should compile and run but produce + // implementation-defined results for m != n + // and n*sizeof(type) = sizeof(vecm) + free(inBuffer); + free(outBuffer); + return 0; + } + + for( int i = 0; i < numElements; i++ ) + { + if( memcmp( expected, actual, compSize ) != 0 ) + { + char expectedString[ 1024 ], actualString[ 1024 ]; + log_error( "ERROR: Data sample %d of %d for as_%s%d( %s%d ) did not validate (expected {%s}, got {%s})\n", + (int)i, (int)numElements, get_explicit_type_name( outVecType ), vecSize, get_explicit_type_name( inVecType ), vecSize, + GetDataVectorString( expected, typeSize, vecSize, expectedString ), + GetDataVectorString( actual, typeSize, vecSize, actualString ) ); + log_error("Src is :\n%s\n----\n%d threads %d localthreads\n", + programSrc, (int)threads[0],(int) localThreads[0]); + free(inBuffer); + free(outBuffer); + return 1; + } + expected += typeSize * vecSize; + actual += outTypeSize * outVecSize; + } + + free(inBuffer); + free(outBuffer); + return 0; +} + +int test_astype(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + // Note: although casting to different vector element sizes that match the same size (i.e. short2 -> char4) is + // legal in OpenCL 1.0, the result is dependent on the device it runs on, which means there's no actual way + // for us to verify what is "valid". So the only thing we can test are types that match in size independent + // of the element count (char -> uchar, etc) + ExplicitType vecTypes[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 }; + unsigned int inTypeIdx, outTypeIdx, sizeIdx, outSizeIdx; + size_t inTypeSize, outTypeSize; + int error = 0; + + for( inTypeIdx = 0; vecTypes[ inTypeIdx ] != kNumExplicitTypes; inTypeIdx++ ) + { + inTypeSize = get_explicit_type_size(vecTypes[inTypeIdx]); + + if( vecTypes[ inTypeIdx ] == kDouble && !is_extension_available( device, "cl_khr_fp64" ) ) + continue; + + if (( vecTypes[ inTypeIdx ] == kLong || vecTypes[ inTypeIdx ] == kULong ) && !gHasLong ) + continue; + + for( outTypeIdx = 0; vecTypes[ outTypeIdx ] != kNumExplicitTypes; outTypeIdx++ ) + { + outTypeSize = get_explicit_type_size(vecTypes[outTypeIdx]); + if( vecTypes[ outTypeIdx ] == kDouble && !is_extension_available( device, "cl_khr_fp64" ) ) { + continue; + } + + if (( vecTypes[ outTypeIdx ] == kLong || vecTypes[ outTypeIdx ] == kULong ) && !gHasLong ) + continue; + + // change this check + if( inTypeIdx == outTypeIdx ) { + continue; + } + + log_info( " (%s->%s)\n", get_explicit_type_name( vecTypes[ inTypeIdx ] ), get_explicit_type_name( vecTypes[ outTypeIdx ] ) ); + fflush( stdout ); + + for( sizeIdx = 0; vecSizes[ sizeIdx ] != 0; sizeIdx++ ) + { + + for(outSizeIdx = 0; vecSizes[outSizeIdx] != 0; outSizeIdx++) + { + if(vecSizes[sizeIdx]*inTypeSize != + vecSizes[outSizeIdx]*outTypeSize ) + { + continue; + } + error += test_astype_set( device, context, queue, vecTypes[ inTypeIdx ], vecTypes[ outTypeIdx ], vecSizes[ sizeIdx ], vecSizes[outSizeIdx], n_elems ); + + + } + + } + if(get_explicit_type_size(vecTypes[inTypeIdx]) == + get_explicit_type_size(vecTypes[outTypeIdx])) { + // as_type3(vec4) allowed, as_type4(vec3) not allowed + error += test_astype_set( device, context, queue, vecTypes[ inTypeIdx ], vecTypes[ outTypeIdx ], 3, 4, n_elems ); + error += test_astype_set( device, context, queue, vecTypes[ inTypeIdx ], vecTypes[ outTypeIdx ], 4, 3, n_elems ); + } + + } + } + return error; +} + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_async_copy.cpp b/test_conformance/compatibility/test_conformance/basic/test_async_copy.cpp new file mode 100644 index 00000000..234ed698 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_async_copy.cpp @@ -0,0 +1,276 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" + +static const char *async_global_to_local_kernel = +"%s\n" // optional pragma string +"__kernel void test_fn( const __global %s *src, __global %s *dst, __local %s *localBuffer, int copiesPerWorkgroup, int copiesPerWorkItem )\n" +"{\n" +" int i;\n" +// Zero the local storage first +" for(i=0; i max_local_workgroup_size[0]) + max_workgroup_size = max_local_workgroup_size[0]; + + size_t numberOfCopiesPerWorkitem = 13; + size_t localStorageSpacePerWorkitem = numberOfCopiesPerWorkitem*elementSize; + size_t maxLocalWorkgroupSize = (((int)max_local_mem_size/2)/localStorageSpacePerWorkitem); + + // Calculation can return 0 on embedded devices due to 1KB local mem limit + if(maxLocalWorkgroupSize == 0) + { + maxLocalWorkgroupSize = 1; + } + + size_t localWorkgroupSize = maxLocalWorkgroupSize; + if (maxLocalWorkgroupSize > max_workgroup_size) + localWorkgroupSize = max_workgroup_size; + + size_t localBufferSize = localWorkgroupSize*elementSize*numberOfCopiesPerWorkitem; + size_t numberOfLocalWorkgroups = 1111; + size_t globalBufferSize = numberOfLocalWorkgroups*localBufferSize; + size_t globalWorkgroupSize = numberOfLocalWorkgroups*localWorkgroupSize; + + inBuffer = (void*)malloc(globalBufferSize); + outBuffer = (void*)malloc(globalBufferSize); + memset(outBuffer, 0, globalBufferSize); + + cl_int copiesPerWorkItemInt, copiesPerWorkgroup; + copiesPerWorkItemInt = (int)numberOfCopiesPerWorkitem; + copiesPerWorkgroup = (int)(numberOfCopiesPerWorkitem*localWorkgroupSize); + + log_info("Global: %d, local %d, local buffer %db, global buffer %db, each work group will copy %d elements and each work item item will copy %d elements.\n", + (int) globalWorkgroupSize, (int)localWorkgroupSize, (int)localBufferSize, (int)globalBufferSize, copiesPerWorkgroup, copiesPerWorkItemInt); + + threads[0] = globalWorkgroupSize; + localThreads[0] = localWorkgroupSize; + + d = init_genrand( gRandomSeed ); + generate_random_data( vecType, globalBufferSize/get_explicit_type_size(vecType), d, inBuffer ); + free_mtdata(d); d = NULL; + + streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, globalBufferSize, inBuffer, &error ); + test_error( error, "Unable to create input buffer" ); + streams[ 1 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, globalBufferSize, outBuffer, &error ); + test_error( error, "Unable to create output buffer" ); + + error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[ 1 ] ), &streams[ 1 ] ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 2, localBufferSize, NULL ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 3, sizeof(copiesPerWorkgroup), &copiesPerWorkgroup ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 4, sizeof(copiesPerWorkItemInt), &copiesPerWorkItemInt ); + test_error( error, "Unable to set kernel argument" ); + + // Enqueue + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to queue kernel" ); + + // Read + error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, globalBufferSize, outBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + // Verify + if( memcmp( inBuffer, outBuffer, globalBufferSize ) != 0 ) + { + log_error( "ERROR: Results of copy did not validate!\n" ); + unsigned char * inchar = (unsigned char*)inBuffer; + unsigned char * outchar = (unsigned char*)outBuffer; + int failuresPrinted = 0; + for (int i=0; i< (int)globalBufferSize; i+=(int)elementSize) { + int failed = 0; + for (int j=0; j<(int)elementSize; j++) + if (inchar[i+j] != outchar[i+j]) + failed = 1; + char values[4096]; + values[0] = 0; + if (failed) { + sprintf(values + strlen( values), "%d -> [", i); + for (int j=0; j<(int)elementSize; j++) + sprintf(values + strlen( values), "%2x ", inchar[i+j]); + sprintf(values + strlen(values), "] != ["); + for (int j=0; j<(int)elementSize; j++) + sprintf(values + strlen( values), "%2x ", outchar[i+j]); + sprintf(values + strlen(values), "]"); + log_error("%s\n", values); + failuresPrinted++; + } + if (failuresPrinted > 5) { + log_error("Not printing further failures...\n"); + break; + } + } + return -1; + } + + free(inBuffer); + free(outBuffer); + + return 0; +} + +int test_copy_all_types(cl_device_id deviceID, cl_context context, cl_command_queue queue, const char *kernelCode) { + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 4, 8, 16, 0 }; + unsigned int size, typeIndex; + + int errors = 0; + + for( typeIndex = 0; vecType[ typeIndex ] != kNumExplicitTypes; typeIndex++ ) + { + if( vecType[ typeIndex ] == kDouble && !is_extension_available( deviceID, "cl_khr_fp64" ) ) + continue; + + if (( vecType[ typeIndex ] == kLong || vecType[ typeIndex ] == kULong ) && !gHasLong ) + continue; + + for( size = 0; vecSizes[ size ] != 0; size++ ) + { + if (test_copy( deviceID, context, queue, kernelCode, vecType[typeIndex],vecSizes[size] )) { + errors++; + } + } + } + if (errors) + return -1; + return 0; +} + + + + +int test_async_copy_global_to_local(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_copy_all_types( deviceID, context, queue, async_global_to_local_kernel ); +} + +int test_async_copy_local_to_global(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_copy_all_types( deviceID, context, queue, async_local_to_global_kernel ); +} + +int test_prefetch(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_copy_all_types( deviceID, context, queue, prefetch_kernel ); +} + diff --git a/test_conformance/compatibility/test_conformance/basic/test_async_strided_copy.cpp b/test_conformance/compatibility/test_conformance/basic/test_async_strided_copy.cpp new file mode 100644 index 00000000..6db06398 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_async_strided_copy.cpp @@ -0,0 +1,267 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" + +static const char *async_strided_global_to_local_kernel = +"%s\n" // optional pragma string +"%s__kernel void test_fn( const __global %s *src, __global %s *dst, __local %s *localBuffer, int copiesPerWorkgroup, int copiesPerWorkItem, int stride )\n" +"{\n" +" int i;\n" +// Zero the local storage first +" for(i=0; i max_local_workgroup_size[0]) + max_workgroup_size = max_local_workgroup_size[0]; + + cl_ulong max_global_mem_size; + error = clGetDeviceInfo(deviceID, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(max_global_mem_size), &max_global_mem_size, NULL); + test_error (error, "clGetDeviceInfo failed for CL_DEVICE_GLOBAL_MEM_SIZE"); + + cl_bool unified_mem; + error = clGetDeviceInfo(deviceID, CL_DEVICE_HOST_UNIFIED_MEMORY, sizeof(unified_mem), &unified_mem, NULL); + test_error (error, "clGetDeviceInfo failed for CL_DEVICE_HOST_UNIFIED_MEMORY"); + + int number_of_global_mem_buffers = (unified_mem) ? 4 : 2; + + size_t numberOfCopiesPerWorkitem = 3; + size_t localStorageSpacePerWorkitem = numberOfCopiesPerWorkitem*elementSize; + size_t maxLocalWorkgroupSize = (((int)max_local_mem_size/2)/localStorageSpacePerWorkitem); + + size_t localWorkgroupSize = maxLocalWorkgroupSize; + if (maxLocalWorkgroupSize > max_workgroup_size) + localWorkgroupSize = max_workgroup_size; + + size_t localBufferSize = localWorkgroupSize*elementSize*numberOfCopiesPerWorkitem; + size_t numberOfLocalWorkgroups = 579;//1111; + + // Reduce the numberOfLocalWorkgroups so that no more than 1/2 of CL_DEVICE_GLOBAL_MEM_SIZE is consumed + // by the allocated buffer. This is done to avoid resource errors resulting from address space fragmentation. + size_t numberOfLocalWorkgroupsLimit = max_global_mem_size / (2 * number_of_global_mem_buffers * localBufferSize * stride); + if (numberOfLocalWorkgroups > numberOfLocalWorkgroupsLimit) numberOfLocalWorkgroups = numberOfLocalWorkgroupsLimit; + + size_t globalBufferSize = numberOfLocalWorkgroups*localBufferSize*stride; + size_t globalWorkgroupSize = numberOfLocalWorkgroups*localWorkgroupSize; + + inBuffer = (void*)malloc(globalBufferSize); + outBuffer = (void*)malloc(globalBufferSize); + memset(outBuffer, 0, globalBufferSize); + + cl_int copiesPerWorkItemInt, copiesPerWorkgroup; + copiesPerWorkItemInt = (int)numberOfCopiesPerWorkitem; + copiesPerWorkgroup = (int)(numberOfCopiesPerWorkitem*localWorkgroupSize); + + log_info("Global: %d, local %d, local buffer %db, global buffer %db, copy stride %d, each work group will copy %d elements and each work item item will copy %d elements.\n", + (int) globalWorkgroupSize, (int)localWorkgroupSize, (int)localBufferSize, (int)globalBufferSize, (int)stride, copiesPerWorkgroup, copiesPerWorkItemInt); + + threads[0] = globalWorkgroupSize; + localThreads[0] = localWorkgroupSize; + + d = init_genrand( gRandomSeed ); + generate_random_data( vecType, globalBufferSize/get_explicit_type_size(vecType), d, inBuffer ); + free_mtdata(d); d = NULL; + + streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, globalBufferSize, inBuffer, &error ); + test_error( error, "Unable to create input buffer" ); + streams[ 1 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, globalBufferSize, outBuffer, &error ); + test_error( error, "Unable to create output buffer" ); + + error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[ 1 ] ), &streams[ 1 ] ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 2, localBufferSize, NULL ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 3, sizeof(copiesPerWorkgroup), &copiesPerWorkgroup ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 4, sizeof(copiesPerWorkItemInt), &copiesPerWorkItemInt ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 5, sizeof(stride), &stride ); + test_error( error, "Unable to set kernel argument" ); + + // Enqueue + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to queue kernel" ); + + // Read + error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, globalBufferSize, outBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + // Verify + for (int i=0; i<(int)globalBufferSize; i+=(int)elementSize*(int)stride) + { + if (memcmp( ((char *)inBuffer)+i, ((char *)outBuffer)+i, elementSize) != 0 ) + { + unsigned char * inchar = (unsigned char*)inBuffer + i; + unsigned char * outchar = (unsigned char*)outBuffer + i; + char values[4096]; + values[0] = 0; + + log_error( "ERROR: Results of copy did not validate!\n" ); + sprintf(values + strlen( values), "%d -> [", i); + for (int j=0; j<(int)elementSize; j++) + sprintf(values + strlen( values), "%2x ", inchar[i*elementSize+j]); + sprintf(values + strlen(values), "] != ["); + for (int j=0; j<(int)elementSize; j++) + sprintf(values + strlen( values), "%2x ", outchar[i*elementSize+j]); + sprintf(values + strlen(values), "]"); + log_error("%s\n", values); + + return -1; + } + } + + free(inBuffer); + free(outBuffer); + + return 0; +} + +int test_strided_copy_all_types(cl_device_id deviceID, cl_context context, cl_command_queue queue, const char *kernelCode) +{ + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 4, 8, 16, 0 }; + unsigned int strideSizes[] = { 1, 3, 4, 5, 0 }; + unsigned int size, typeIndex, stride; + + int errors = 0; + + for( typeIndex = 0; vecType[ typeIndex ] != kNumExplicitTypes; typeIndex++ ) + { + if( vecType[ typeIndex ] == kDouble && !is_extension_available( deviceID, "cl_khr_fp64" ) ) + continue; + + if (( vecType[ typeIndex ] == kLong || vecType[ typeIndex ] == kULong ) && !gHasLong ) + continue; + + for( size = 0; vecSizes[ size ] != 0; size++ ) + { + for( stride = 0; strideSizes[ stride ] != 0; stride++) + { + if (test_strided_copy( deviceID, context, queue, kernelCode, vecType[typeIndex], vecSizes[size], strideSizes[stride] )) + { + errors++; + } + } + } + } + if (errors) + return -1; + return 0; +} + + + + +int test_async_strided_copy_global_to_local(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_strided_copy_all_types( deviceID, context, queue, async_strided_global_to_local_kernel ); +} + +int test_async_strided_copy_local_to_global(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_strided_copy_all_types( deviceID, context, queue, async_strided_local_to_global_kernel ); +} + diff --git a/test_conformance/compatibility/test_conformance/basic/test_barrier.c b/test_conformance/compatibility/test_conformance/basic/test_barrier.c new file mode 100644 index 00000000..87d106d3 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_barrier.c @@ -0,0 +1,158 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +const char *barrier_kernel_code = +"__kernel void compute_sum(__global int *a, int n, __global int *tmp_sum, __global int *sum)\n" +"{\n" +" int tid = get_local_id(0);\n" +" int lsize = get_local_size(0);\n" +" int i;\n" +"\n" +" tmp_sum[tid] = 0;\n" +" for (i=tid; i1; i = hadd(i,1))\n" +" {\n" +" barrier(CLK_GLOBAL_MEM_FENCE);\n" +" if (tid + i < lsize)\n" +" tmp_sum[tid] += tmp_sum[tid + i];\n" +" lsize = i; \n" +" }\n" +"\n" +" //no barrier is required here because last person to write to tmp_sum[0] was tid 0 \n" +" if (tid == 0)\n" +" *sum = tmp_sum[0];\n" +"}\n"; + + +static int +verify_sum(int *inptr, int *tmpptr, int *outptr, int n) +{ + int r = 0; + int i; + + for (i=0; i max_local_workgroup_size[0]) + max_threadgroup_size = max_local_workgroup_size[0]; + + // work group size must divide evenly into the global size + while( num_elements % max_threadgroup_size ) + max_threadgroup_size--; + + input_ptr = (int*)malloc(sizeof(int) * num_elements); + output_ptr = (int*)malloc(sizeof(int)); + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * num_elements, NULL, &err); + test_error(err, "clCreateBuffer failed."); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int), NULL, &err); + test_error(err, "clCreateBuffer failed."); + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * max_threadgroup_size, NULL, &err); + test_error(err, "clCreateBuffer failed."); + + d = init_genrand( gRandomSeed ); + for (i=0; i +#include +#include +#include + +#include "procs.h" + +const char *kernel_code = +"__kernel void test_kernel(\n" +"char%s c, uchar%s uc, short%s s, ushort%s us, int%s i, uint%s ui, float%s f,\n" +"__global float%s *result)\n" +"{\n" +" result[0] = %s(c);\n" +" result[1] = %s(uc);\n" +" result[2] = %s(s);\n" +" result[3] = %s(us);\n" +" result[4] = %s(i);\n" +" result[5] = %s(ui);\n" +" result[6] = f;\n" +"}\n"; + +const char *kernel_code_long = +"__kernel void test_kernel_long(\n" +"long%s l, ulong%s ul,\n" +"__global float%s *result)\n" +"{\n" +" result[0] = %s(l);\n" +" result[1] = %s(ul);\n" +"}\n"; + +int +test_basic_parameter_types_long(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + clMemWrapper results; + int error; + size_t global[3] = {1, 1, 1}; + float results_back[2*16]; + int count, index; + const char* types[] = { "long", "ulong" }; + char kernel_string[8192]; + int sizes[] = {1, 2, 4, 8, 16}; + const char* size_strings[] = {"", "2", "4", "8", "16"}; + float expected; + int total_errors = 0; + int size_to_test; + char *ptr; + char convert_string[1024]; + size_t max_parameter_size; + + // We don't really care about the contents since we're just testing that the types work. + cl_long l[16]={-21,-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,14,-15}; + cl_ulong ul[16]={22,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + + // Calculate how large our paramter size is to the kernel + size_t parameter_size = sizeof(cl_long) + sizeof(cl_ulong); + + // Init our strings. + kernel_string[0] = '\0'; + convert_string[0] = '\0'; + + // Get the maximum parameter size allowed + error = clGetDeviceInfo( device, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof( max_parameter_size ), &max_parameter_size, NULL ); + test_error( error, "Unable to get max parameter size from device" ); + + // Create the results buffer + results = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_float)*2*16, NULL, &error); + test_error(error, "clCreateBuffer failed"); + + // Go over all the vector sizes + for (size_to_test = 0; size_to_test < 5; size_to_test++) { + clProgramWrapper program; + clKernelWrapper kernel; + + size_t total_parameter_size = parameter_size*sizes[size_to_test] + sizeof(cl_mem); + if (total_parameter_size > max_parameter_size) { + log_info("Can not test with vector size %d because it would exceed the maximum allowed parameter size to the kernel. (%d > %d)\n", + (int)sizes[size_to_test], (int)total_parameter_size, (int)max_parameter_size); + continue; + } + + log_info("Testing vector size %d\n", sizes[size_to_test]); + + // If size is > 1, then we need a explicit convert call. + if (sizes[size_to_test] > 1) { + sprintf(convert_string, "convert_float%s", size_strings[size_to_test]); + } else { + sprintf(convert_string, " "); + } + + // Build the kernel + sprintf(kernel_string, kernel_code_long, + size_strings[size_to_test], size_strings[size_to_test], size_strings[size_to_test], + convert_string, convert_string + ); + + ptr = kernel_string; + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&ptr, "test_kernel_long"); + test_error(error, "create single kernel failed"); + + // Set the arguments + for (count = 0; count < 2; count++) { + switch (count) { + case 0: error = clSetKernelArg(kernel, count, sizeof(cl_long)*sizes[size_to_test], &l); break; + case 1: error = clSetKernelArg(kernel, count, sizeof(cl_ulong)*sizes[size_to_test], &ul); break; + default: log_error("Test error"); break; + } + if (error) + log_error("Setting kernel arg %d %s%s: ", count, types[count], size_strings[size_to_test]); + test_error(error, "clSetKernelArgs failed"); + } + error = clSetKernelArg(kernel, 2, sizeof(cl_mem), &results); + test_error(error, "clSetKernelArgs failed"); + + // Execute + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global, NULL, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + // Read back the results + error = clEnqueueReadBuffer(queue, results, CL_TRUE, 0, sizeof(cl_float)*2*16, results_back, 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + // Verify the results + for (count = 0; count < 2; count++) { + for (index=0; index < sizes[size_to_test]; index++) { + switch (count) { + case 0: expected = (float)l[index]; break; + case 1: expected = (float)ul[index]; break; + default: log_error("Test error"); break; + } + + if (results_back[count*sizes[size_to_test]+index] != expected) { + total_errors++; + log_error("Conversion from %s%s failed: index %d got %g, expected %g.\n", types[count], size_strings[size_to_test], + index, results_back[count*sizes[size_to_test]+index], expected); + } + } + } + } + + return total_errors; +} + +int +test_basic_parameter_types(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + clMemWrapper results; + int error; + size_t global[3] = {1, 1, 1}; + float results_back[7*16]; + int count, index; + const char* types[] = {"char", "uchar", "short", "ushort", "int", "uint", "float"}; + char kernel_string[8192]; + int sizes[] = {1, 2, 4, 8, 16}; + const char* size_strings[] = {"", "2", "4", "8", "16"}; + float expected; + int total_errors = 0; + int size_to_test; + char *ptr; + char convert_string[1024]; + size_t max_parameter_size; + + // We don't really care about the contents since we're just testing that the types work. + cl_char c[16]={0,-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,14,-15}; + cl_uchar uc[16]={16,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + cl_short s[16]={-17,-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,14,-15}; + cl_ushort us[16]={18,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + cl_int i[16]={-19,-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,14,-15}; + cl_uint ui[16]={20,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + cl_float f[16]={-23,-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,14,-15}; + + // Calculate how large our paramter size is to the kernel + size_t parameter_size = sizeof(cl_char) + sizeof(cl_uchar) + + sizeof(cl_short) +sizeof(cl_ushort) + + sizeof(cl_int) +sizeof(cl_uint) + + sizeof(cl_float); + + // Init our strings. + kernel_string[0] = '\0'; + convert_string[0] = '\0'; + + // Get the maximum parameter size allowed + error = clGetDeviceInfo( device, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof( max_parameter_size ), &max_parameter_size, NULL ); + test_error( error, "Unable to get max parameter size from device" ); + + // Create the results buffer + results = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_float)*7*16, NULL, &error); + test_error(error, "clCreateBuffer failed"); + + // Go over all the vector sizes + for (size_to_test = 0; size_to_test < 5; size_to_test++) { + clProgramWrapper program; + clKernelWrapper kernel; + + size_t total_parameter_size = parameter_size*sizes[size_to_test] + sizeof(cl_mem); + if (total_parameter_size > max_parameter_size) { + log_info("Can not test with vector size %d because it would exceed the maximum allowed parameter size to the kernel. (%d > %d)\n", + (int)sizes[size_to_test], (int)total_parameter_size, (int)max_parameter_size); + continue; + } + + log_info("Testing vector size %d\n", sizes[size_to_test]); + + // If size is > 1, then we need a explicit convert call. + if (sizes[size_to_test] > 1) { + sprintf(convert_string, "convert_float%s", size_strings[size_to_test]); + } else { + sprintf(convert_string, " "); + } + + // Build the kernel + sprintf(kernel_string, kernel_code, + size_strings[size_to_test], size_strings[size_to_test], size_strings[size_to_test], + size_strings[size_to_test], size_strings[size_to_test], size_strings[size_to_test], + size_strings[size_to_test], size_strings[size_to_test], + convert_string, convert_string, convert_string, + convert_string, convert_string, convert_string + ); + + ptr = kernel_string; + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&ptr, "test_kernel"); + test_error(error, "create single kernel failed"); + + // Set the arguments + for (count = 0; count < 7; count++) { + switch (count) { + case 0: error = clSetKernelArg(kernel, count, sizeof(cl_char)*sizes[size_to_test], &c); break; + case 1: error = clSetKernelArg(kernel, count, sizeof(cl_uchar)*sizes[size_to_test], &uc); break; + case 2: error = clSetKernelArg(kernel, count, sizeof(cl_short)*sizes[size_to_test], &s); break; + case 3: error = clSetKernelArg(kernel, count, sizeof(cl_ushort)*sizes[size_to_test], &us); break; + case 4: error = clSetKernelArg(kernel, count, sizeof(cl_int)*sizes[size_to_test], &i); break; + case 5: error = clSetKernelArg(kernel, count, sizeof(cl_uint)*sizes[size_to_test], &ui); break; + case 6: error = clSetKernelArg(kernel, count, sizeof(cl_float)*sizes[size_to_test], &f); break; + default: log_error("Test error"); break; + } + if (error) + log_error("Setting kernel arg %d %s%s: ", count, types[count], size_strings[size_to_test]); + test_error(error, "clSetKernelArgs failed"); + } + error = clSetKernelArg(kernel, 7, sizeof(cl_mem), &results); + test_error(error, "clSetKernelArgs failed"); + + // Execute + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global, NULL, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + // Read back the results + error = clEnqueueReadBuffer(queue, results, CL_TRUE, 0, sizeof(cl_float)*7*16, results_back, 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + // Verify the results + for (count = 0; count < 7; count++) { + for (index=0; index < sizes[size_to_test]; index++) { + switch (count) { + case 0: expected = (float)c[index]; break; + case 1: expected = (float)uc[index]; break; + case 2: expected = (float)s[index]; break; + case 3: expected = (float)us[index]; break; + case 4: expected = (float)i[index]; break; + case 5: expected = (float)ui[index]; break; + case 6: expected = (float)f[index]; break; + default: log_error("Test error"); break; + } + + if (results_back[count*sizes[size_to_test]+index] != expected) { + total_errors++; + log_error("Conversion from %s%s failed: index %d got %g, expected %g.\n", types[count], size_strings[size_to_test], + index, results_back[count*sizes[size_to_test]+index], expected); + } + } + } + } + + if (gHasLong) { + log_info("Testing long types...\n"); + total_errors += test_basic_parameter_types_long( device, context, queue, num_elements ); + } + else { + log_info("Longs unsupported, skipping."); + } + + return total_errors; +} + + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_bufferreadwriterect.c b/test_conformance/compatibility/test_conformance/basic/test_bufferreadwriterect.c new file mode 100644 index 00000000..e72ae708 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_bufferreadwriterect.c @@ -0,0 +1,529 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +#define CL_EXIT_ERROR(cmd,format,...) \ +{ \ +if ((cmd) != CL_SUCCESS) { \ +log_error("CL ERROR: %s %u: ", __FILE__,__LINE__); \ +log_error(format,## __VA_ARGS__ ); \ +log_error("\n"); \ +/*abort();*/ \ +} \ +} + +typedef unsigned char BufferType; + +// Globals for test +cl_command_queue queue; + +// Width and height of each pair of images. +enum { TotalImages = 8 }; +size_t width [TotalImages]; +size_t height [TotalImages]; +size_t depth [TotalImages]; + +// cl buffer and host buffer. +cl_mem buffer [TotalImages]; +BufferType* verify[TotalImages]; +BufferType* backing[TotalImages]; + +// Temporary buffer used for read and write operations. +BufferType* tmp_buffer; +size_t tmp_buffer_size; + +size_t num_tries = 50; // Number of randomly selected operations to perform. +size_t alloc_scale = 2; // Scale term applied buffer allocation size. +MTdata mt; + +// Initialize a buffer in host memory containing random values of the specified size. +static void initialize_image(BufferType* ptr, size_t w, size_t h, size_t d, MTdata mt) +{ + enum { ElementSize = sizeof(BufferType)/sizeof(unsigned char) }; + + unsigned char* buf = (unsigned char*)ptr; + size_t size = w*h*d*ElementSize; + + for (size_t i = 0; i != size; i++) { + buf[i] = (unsigned char)(genrand_int32(mt) % 0xff); + } +} + +// This function prints the contents of a buffer to standard error. +void print_buffer(BufferType* buf, size_t w, size_t h, size_t d) { + log_error("Size = %lux%lux%lu (%lu total)\n",w,h,d,w*h*d); + for (unsigned k=0; k!=d;++k) { + log_error("Slice: %u\n",k); + for (unsigned j=0; j!=h;++j) { + for (unsigned i=0;i!=w;++i) { + log_error("%02x",buf[k*(w*h)+j*w+i]); + } + log_error("\n"); + } + log_error("\n"); + } +} + +// Returns true if the two specified regions overlap. +bool check_overlap(const size_t src_offset[3], const size_t dst_offset[3], const size_t region[3]) { + + const size_t src_min[] = {src_offset[0], src_offset[1], src_offset[2]}; + const size_t src_max[] = {src_offset[0]+region[0], src_offset[1]+region[1], src_offset[2]+region[2]}; + + const size_t dst_min[] = {dst_offset[0], dst_offset[1], dst_offset[2]}; + const size_t dst_max[] = {dst_offset[0]+region[0], dst_offset[1]+region[1], dst_offset[2]+region[2]}; + + // Check for overlap, using the span space formulation. + bool overlap = true; + unsigned i; + for (i=0; i != 3; ++i) { + overlap = overlap && (src_min[i] < dst_max[i]) && (src_max[i] > dst_min[i]); + } + + return overlap; +} + +// This function invokes the CopyBufferRect CL command and then mirrors the operation on the host side verify buffers. +int copy_region(size_t src, size_t soffset[3], size_t sregion[3], size_t dst, size_t doffset[3], size_t dregion[3]) { + + // Copy between cl buffers. + size_t src_slice_pitch = (width[src]*height[src] != 1) ? width[src]*height[src] : 0; + size_t dst_slice_pitch = (width[dst]*height[dst] != 1) ? width[dst]*height[dst] : 0; + + cl_int err; + if (check_overlap(soffset,doffset,sregion)) { + log_info( "Copy overlap reported, skipping copy buffer rect\n" ); + return CL_SUCCESS; + } else { + if ((err = clEnqueueCopyBufferRect(queue, + buffer[src],buffer[dst], + soffset, doffset, + sregion,/*dregion,*/ + width[src], src_slice_pitch, + width[dst], dst_slice_pitch, + 0, NULL, NULL)) != CL_SUCCESS) + { + CL_EXIT_ERROR(err, "clEnqueueCopyBufferRect failed between %u and %u",(unsigned)src,(unsigned)dst); + } + } + + // Copy between host buffers. + size_t total = sregion[0] * sregion[1] * sregion[2]; + + size_t spitch = width[src]; + size_t sslice = width[src]*height[src]; + + size_t dpitch = width[dst]; + size_t dslice = width[dst]*height[dst]; + + for (size_t i = 0; i != total; ++i) { + + // Compute the coordinates of the element within the source and destination regions. + size_t rslice = sregion[0]*sregion[1]; + size_t sz = i / rslice; + size_t sy = (i % rslice) / sregion[0]; + size_t sx = (i % rslice) % sregion[0]; + + size_t dz = sz; + size_t dy = sy; + size_t dx = sx; + + // Compute the offset in bytes of the source and destination. + size_t s_idx = (soffset[2]+sz)*sslice + (soffset[1]+sy)*spitch + soffset[0]+sx; + size_t d_idx = (doffset[2]+dz)*dslice + (doffset[1]+dy)*dpitch + doffset[0]+dx; + + verify[dst][d_idx] = verify[src][s_idx]; + } + + return 0; +} + +// This function compares the destination region in the buffer pointed +// to by device, to the source region of the specified verify buffer. +int verify_region(BufferType* device, size_t src, size_t soffset[3], size_t sregion[3], size_t dst, size_t doffset[3]) { + + // Copy between host buffers. + size_t spitch = width[src]; + size_t sslice = width[src]*height[src]; + + size_t dpitch = width[dst]; + size_t dslice = width[dst]*height[dst]; + + size_t total = sregion[0] * sregion[1] * sregion[2]; + for (size_t i = 0; i != total; ++i) { + + // Compute the coordinates of the element within the source and destination regions. + size_t rslice = sregion[0]*sregion[1]; + size_t sz = i / rslice; + size_t sy = (i % rslice) / sregion[0]; + size_t sx = (i % rslice) % sregion[0]; + + // Compute the offset in bytes of the source and destination. + size_t s_idx = (soffset[2]+sz)*sslice + (soffset[1]+sy)*spitch + soffset[0]+sx; + size_t d_idx = (doffset[2]+sz)*dslice + (doffset[1]+sy)*dpitch + doffset[0]+sx; + + if (device[d_idx] != verify[src][s_idx]) { + log_error("Verify failed on comparsion %lu: coordinate (%lu, %lu, %lu) of region\n",i,sx,sy,sz); + log_error("0x%02x != 0x%02x\n", device[d_idx], verify[src][s_idx]); +#if 0 + // Uncomment this section to print buffers. + log_error("Device (copy): [%lu]\n",dst); + print_buffer(device,width[dst],height[dst],depth[dst]); + log_error("\n"); + log_error("Verify: [%lu]\n",src); + print_buffer(verify[src],width[src],height[src],depth[src]); + log_error("\n"); + abort(); +#endif + return -1; + } + } + + return 0; +} + + +// This function invokes ReadBufferRect to read a region from the +// specified source buffer into a temporary destination buffer. The +// contents of the temporary buffer are then compared to the source +// region of the corresponding verify buffer. +int read_verify_region(size_t src, size_t soffset[3], size_t sregion[3], size_t dst, size_t doffset[3], size_t dregion[3]) { + + // Clear the temporary destination host buffer. + memset(tmp_buffer, 0xff, tmp_buffer_size); + + size_t src_slice_pitch = (width[src]*height[src] != 1) ? width[src]*height[src] : 0; + size_t dst_slice_pitch = (width[dst]*height[dst] != 1) ? width[dst]*height[dst] : 0; + + // Copy the source region of the cl buffer, to the destination region of the temporary buffer. + CL_EXIT_ERROR(clEnqueueReadBufferRect(queue, + buffer[src], + CL_TRUE, + soffset,doffset, + sregion, + width[src], src_slice_pitch, + width[dst], dst_slice_pitch, + tmp_buffer, + 0, NULL, NULL), "clEnqueueCopyBufferRect failed between %u and %u",(unsigned)src,(unsigned)dst); + + return verify_region(tmp_buffer,src,soffset,sregion,dst,doffset); +} + +// This function performs the same verification check as +// read_verify_region, except a MapBuffer command is used to access the +// device buffer data instead of a ReadBufferRect, and the whole +// buffer is checked. +int map_verify_region(size_t src) { + + size_t size_bytes = width[src]*height[src]*depth[src]*sizeof(BufferType); + + // Copy the source region of the cl buffer, to the destination region of the temporary buffer. + cl_int err; + BufferType* mapped = (BufferType*)clEnqueueMapBuffer(queue,buffer[src],CL_TRUE,CL_MAP_READ,0,size_bytes,0,NULL,NULL,&err); + CL_EXIT_ERROR(err, "clEnqueueMapBuffer failed for buffer %u",(unsigned)src); + + size_t soffset[] = { 0, 0, 0 }; + size_t sregion[] = { width[src], height[src], depth[src] }; + + int ret = verify_region(mapped,src,soffset,sregion,src,soffset); + + CL_EXIT_ERROR(clEnqueueUnmapMemObject(queue,buffer[src],mapped,0,NULL,NULL), + "clEnqueueUnmapMemObject failed for buffer %u",(unsigned)src); + + return ret; +} + +// This function generates a new temporary buffer and then writes a +// region of it to a region in the specified destination buffer. +int write_region(size_t src, size_t soffset[3], size_t sregion[3], size_t dst, size_t doffset[3], size_t dregion[3]) { + + initialize_image(tmp_buffer, tmp_buffer_size, 1, 1, mt); + // memset(tmp_buffer, 0xf0, tmp_buffer_size); + + size_t src_slice_pitch = (width[src]*height[src] != 1) ? width[src]*height[src] : 0; + size_t dst_slice_pitch = (width[dst]*height[dst] != 1) ? width[dst]*height[dst] : 0; + + // Copy the source region of the cl buffer, to the destination region of the temporary buffer. + CL_EXIT_ERROR(clEnqueueWriteBufferRect(queue, + buffer[dst], + CL_TRUE, + doffset,soffset, + /*sregion,*/dregion, + width[dst], dst_slice_pitch, + width[src], src_slice_pitch, + tmp_buffer, + 0, NULL, NULL), "clEnqueueWriteBufferRect failed between %u and %u",(unsigned)src,(unsigned)dst); + + // Copy from the temporary buffer to the host buffer. + size_t spitch = width[src]; + size_t sslice = width[src]*height[src]; + size_t dpitch = width[dst]; + size_t dslice = width[dst]*height[dst]; + + size_t total = sregion[0] * sregion[1] * sregion[2]; + for (size_t i = 0; i != total; ++i) { + + // Compute the coordinates of the element within the source and destination regions. + size_t rslice = sregion[0]*sregion[1]; + size_t sz = i / rslice; + size_t sy = (i % rslice) / sregion[0]; + size_t sx = (i % rslice) % sregion[0]; + + size_t dz = sz; + size_t dy = sy; + size_t dx = sx; + + // Compute the offset in bytes of the source and destination. + size_t s_idx = (soffset[2]+sz)*sslice + (soffset[1]+sy)*spitch + soffset[0]+sx; + size_t d_idx = (doffset[2]+dz)*dslice + (doffset[1]+dy)*dpitch + doffset[0]+dx; + + verify[dst][d_idx] = tmp_buffer[s_idx]; + } + return 0; +} + +void CL_CALLBACK mem_obj_destructor_callback( cl_mem, void *data ) +{ + free( data ); +} + +// This is the main test function for the conformance test. +int +test_bufferreadwriterect(cl_device_id device, cl_context context, cl_command_queue queue_, int num_elements) +{ + queue = queue_; + cl_int err; + + // Initialize the random number generator. + mt = init_genrand( gRandomSeed ); + + // Compute a maximum buffer size based on the number of test images and the device maximum. + cl_ulong max_mem_alloc_size = 0; + CL_EXIT_ERROR(clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_mem_alloc_size, NULL),"Could not get device info"); + log_info("CL_DEVICE_MAX_MEM_ALLOC_SIZE = %llu bytes.\n", max_mem_alloc_size); + + // Confirm that the maximum allocation size is not zero. + if (max_mem_alloc_size == 0) { + log_error("Error: CL_DEVICE_MAX_MEM_ALLOC_SIZE is zero bytes\n"); + return -1; + } + + // Guess at a reasonable maximum dimension. + size_t max_mem_alloc_dim = (size_t)cbrt((double)(max_mem_alloc_size/sizeof(BufferType)))/alloc_scale; + if (max_mem_alloc_dim == 0) { + max_mem_alloc_dim = max_mem_alloc_size; + } + + log_info("Using maximum dimension = %lu.\n", max_mem_alloc_dim); + + // Create pairs of cl buffers and host buffers on which operations will be mirrored. + log_info("Creating %u pairs of random sized host and cl buffers.\n", TotalImages); + + size_t max_size = 0; + size_t total_bytes = 0; + + for (unsigned i=0; i != TotalImages; ++i) { + + // Determine a width and height for this buffer. + size_t size_bytes; + size_t tries = 0; + size_t max_tries = 1048576; + do { + width[i] = get_random_size_t(1, max_mem_alloc_dim, mt); + height[i] = get_random_size_t(1, max_mem_alloc_dim, mt); + depth[i] = get_random_size_t(1, max_mem_alloc_dim, mt); + ++tries; + } while ((tries < max_tries) && (size_bytes = width[i]*height[i]*depth[i]*sizeof(BufferType)) > max_mem_alloc_size); + + // Check to see if adequately sized buffers were found. + if (tries >= max_tries) { + log_error("Error: Could not find random buffer sized less than %llu bytes in %lu tries.\n", + max_mem_alloc_size, max_tries); + return -1; + } + + // Keep track of the dimensions of the largest buffer. + max_size = (size_bytes > max_size) ? size_bytes : max_size; + total_bytes += size_bytes; + + log_info("Buffer[%u] is (%lu,%lu,%lu) = %lu MB (truncated)\n",i,width[i],height[i],depth[i],(size_bytes)/1048576); + } + + log_info( "Total size: %lu MB (truncated)\n", total_bytes/1048576 ); + + // Allocate a temporary buffer for read and write operations. + tmp_buffer_size = max_size; + tmp_buffer = (BufferType*)malloc(tmp_buffer_size); + + // Initialize cl buffers + log_info( "Initializing buffers\n" ); + for (unsigned i=0; i != TotalImages; ++i) { + + size_t size_bytes = width[i]*height[i]*depth[i]*sizeof(BufferType); + + // Allocate a host copy of the buffer for verification. + verify[i] = (BufferType*)malloc(size_bytes); + CL_EXIT_ERROR(verify[i] ? CL_SUCCESS : -1, "malloc of host buffer failed for buffer %u", i); + + // Allocate the buffer in host memory. + backing[i] = (BufferType*)malloc(size_bytes); + CL_EXIT_ERROR(backing[i] ? CL_SUCCESS : -1, "malloc of backing buffer failed for buffer %u", i); + + // Generate a random buffer. + log_info( "Initializing buffer %u\n", i ); + initialize_image(verify[i], width[i], height[i], depth[i], mt); + + // Copy the image into a buffer which will passed to CL. + memcpy(backing[i], verify[i], size_bytes); + + // Create the CL buffer. + buffer[i] = clCreateBuffer (context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, size_bytes, backing[i], &err); + CL_EXIT_ERROR(err,"clCreateBuffer failed for buffer %u", i); + + // Make sure buffer is cleaned up appropriately if we encounter an error in the rest of the calls. + err = clSetMemObjectDestructorCallback( buffer[i], mem_obj_destructor_callback, backing[i] ); + CL_EXIT_ERROR(err, "Unable to set mem object destructor callback" ); + } + + // Main test loop, run num_tries times. + log_info( "Executing %u test operations selected at random.\n", (unsigned)num_tries ); + for (size_t iter = 0; iter < num_tries; ++iter) { + + // Determine a source and a destination. + size_t src = get_random_size_t(0,TotalImages,mt); + size_t dst = get_random_size_t(0,TotalImages,mt); + + // Determine the minimum dimensions. + size_t min_width = width[src] < width[dst] ? width[src] : width[dst]; + size_t min_height = height[src] < height[dst] ? height[src] : height[dst]; + size_t min_depth = depth[src] < depth[dst] ? depth[src] : depth[dst]; + + // Generate a random source rectangle within the minimum dimensions. + size_t mx = get_random_size_t(0, min_width-1, mt); + size_t my = get_random_size_t(0, min_height-1, mt); + size_t mz = get_random_size_t(0, min_depth-1, mt); + + size_t sw = get_random_size_t(1, (min_width - mx), mt); + size_t sh = get_random_size_t(1, (min_height - my), mt); + size_t sd = get_random_size_t(1, (min_depth - mz), mt); + + size_t sx = get_random_size_t(0, width[src]-sw, mt); + size_t sy = get_random_size_t(0, height[src]-sh, mt); + size_t sz = get_random_size_t(0, depth[src]-sd, mt); + + size_t soffset[] = { sx, sy, sz }; + size_t sregion[] = { sw, sh, sd }; + + // Generate a destination rectangle of the same size. + size_t dw = sw; + size_t dh = sh; + size_t dd = sd; + + // Generate a random destination offset within the buffer. + size_t dx = get_random_size_t(0, (width[dst] - dw), mt); + size_t dy = get_random_size_t(0, (height[dst] - dh), mt); + size_t dz = get_random_size_t(0, (depth[dst] - dd), mt); + size_t doffset[] = { dx, dy, dz }; + size_t dregion[] = { dw, dh, dd }; + + // Execute one of three operations: + // - Copy: Copies between src and dst within each set of host, buffer, and images. + // - Read & verify: Reads src region from buffer and image, and compares to host. + // - Write: Generates new buffer with src dimensions, and writes to cl buffer and image. + + enum { TotalOperations = 3 }; + size_t operation = get_random_size_t(0,TotalOperations,mt); + + switch (operation) { + case 0: + log_info("%lu Copy %lu offset (%lu,%lu,%lu) -> %lu offset (%lu,%lu,%lu) region (%lux%lux%lu = %lu)\n", + iter, + src, soffset[0], soffset[1], soffset[2], + dst, doffset[0], doffset[1], doffset[2], + sregion[0], sregion[1], sregion[2], + sregion[0]*sregion[1]*sregion[2]); + if ((err = copy_region(src, soffset, sregion, dst, doffset, dregion))) + return err; + break; + case 1: + log_info("%lu Read %lu offset (%lu,%lu,%lu) -> %lu offset (%lu,%lu,%lu) region (%lux%lux%lu = %lu)\n", + iter, + src, soffset[0], soffset[1], soffset[2], + dst, doffset[0], doffset[1], doffset[2], + sregion[0], sregion[1], sregion[2], + sregion[0]*sregion[1]*sregion[2]); + if ((err = read_verify_region(src, soffset, sregion, dst, doffset, dregion))) + return err; + break; + case 2: + log_info("%lu Write %lu offset (%lu,%lu,%lu) -> %lu offset (%lu,%lu,%lu) region (%lux%lux%lu = %lu)\n", + iter, + src, soffset[0], soffset[1], soffset[2], + dst, doffset[0], doffset[1], doffset[2], + sregion[0], sregion[1], sregion[2], + sregion[0]*sregion[1]*sregion[2]); + if ((err = write_region(src, soffset, sregion, dst, doffset, dregion))) + return err; + break; + } + +#if 0 + // Uncomment this section to verify each operation. + // If commented out, verification won't occur until the end of the + // test, and it will not be possible to determine which operation failed. + log_info("Verify src %lu offset (%u,%u,%u) region (%lux%lux%lu)\n", src, 0, 0, 0, width[src], height[src], depth[src]); + if (err = map_verify_region(src)) + return err; + + log_info("Verify dst %lu offset (%u,%u,%u) region (%lux%lux%lu)\n", dst, 0, 0, 0, width[dst], height[dst], depth[dst]); + if (err = map_verify_region(dst)) + return err; + + +#endif + + } // end main for loop. + + for (unsigned i=0;i +#include +#include +#include + + +#include "procs.h" + +const char *constant_kernel_code = +"__kernel void constant_kernel(__global float *out, __constant float *tmpF, __constant int *tmpI)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" float ftmp = tmpF[tid]; \n" +" float Itmp = tmpI[tid]; \n" +" out[tid] = ftmp * Itmp; \n" +"}\n"; + +const char *loop_constant_kernel_code = +"kernel void loop_constant_kernel(global float *out, constant float *i_pos, int num)\n" +"{\n" +" int tid = get_global_id(0);\n" +" float sum = 0;\n" +" for (int i = 0; i < num; i++) {\n" +" float pos = i_pos[i*3];\n" +" sum += pos;\n" +" }\n" +" out[tid] = sum;\n" +"}\n"; + + +static int +verify(cl_float *tmpF, cl_int *tmpI, cl_float *out, int n) +{ + int i; + + for (i=0; i < n; i++) + { + float f = tmpF[i] * tmpI[i]; + if( out[i] != f ) + { + log_error("CONSTANT test failed\n"); + return -1; + } + } + + log_info("CONSTANT test passed\n"); + return 0; +} + + +static int +verify_loop_constant(const cl_float *tmp, cl_float *out, cl_int l, int n) +{ + int i; + cl_int j; + for (i=0; i < n; i++) + { + float sum = 0; + for (j=0; j < l; ++j) + sum += tmp[j*3]; + + if( out[i] != sum ) + { + log_error("loop CONSTANT test failed\n"); + return -1; + } + } + + log_info("loop CONSTANT test passed\n"); + return 0; +} + +int +test_constant(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem streams[3]; + cl_int *tmpI; + cl_float *tmpF, *out; + cl_program program; + cl_kernel kernel; + size_t global_threads[3]; + int err; + unsigned int i; + cl_ulong maxSize; + size_t num_floats, num_ints, constant_values; + MTdata d; + RoundingMode oldRoundMode; + int isRTZ = 0; + + /* Verify our test buffer won't be bigger than allowed */ + err = clGetDeviceInfo( device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof( maxSize ), &maxSize, 0 ); + test_error( err, "Unable to get max constant buffer size" ); + + log_info("Device reports CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE %llu bytes.\n", maxSize); + maxSize/=4; + num_ints = (size_t)maxSize/sizeof(cl_int); + num_floats = (size_t)maxSize/sizeof(cl_float); + if (num_ints >= num_floats) { + constant_values = num_floats; + } else { + constant_values = num_ints; + } + + log_info("Test will attempt to use %lu bytes with one %lu byte constant int buffer and one %lu byte constant float buffer.\n", + constant_values*sizeof(cl_int) + constant_values*sizeof(cl_float), constant_values*sizeof(cl_int), constant_values*sizeof(cl_float)); + + tmpI = (cl_int*)malloc(sizeof(cl_int) * constant_values); + tmpF = (cl_float*)malloc(sizeof(cl_float) * constant_values); + out = (cl_float*)malloc(sizeof(cl_float) * constant_values); + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * constant_values, NULL, NULL); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * constant_values, NULL, NULL); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * constant_values, NULL, NULL); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + d = init_genrand( gRandomSeed ); + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +const char *constant_source_kernel_code[] = { +"__constant int outVal = 42;\n" +"__constant int outIndex = 7;\n" +"__constant int outValues[ 16 ] = { 17, 01, 11, 12, 1955, 11, 5, 1985, 113, 1, 24, 1984, 7, 23, 1979, 97 };\n" +"\n" +"__kernel void constant_kernel( __global int *out )\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" if( tid == 0 )\n" +" {\n" +" out[ 0 ] = outVal;\n" +" out[ 1 ] = outValues[ outIndex ];\n" +" }\n" +" else\n" +" {\n" +" out[ tid + 1 ] = outValues[ tid ];\n" +" }\n" +"}\n" }; + +int test_constant_source(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel; + + clMemWrapper outStream; + cl_int outValues[ 17 ]; + cl_int expectedValues[ 17 ] = { 42, 1985, 01, 11, 12, 1955, 11, 5, 1985, 113, 1, 24, 1984, 7, 23, 1979, 97 }; + + cl_int error; + + + // Create a kernel to test with + error = create_single_kernel_helper( context, &program, &kernel, 1, constant_source_kernel_code, "constant_kernel" ); + test_error( error, "Unable to create testing kernel" ); + + // Create our output buffer + outStream = clCreateBuffer( context, CL_MEM_WRITE_ONLY, sizeof( outValues ), NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + // Set the argument + error = clSetKernelArg( kernel, 0, sizeof( outStream ), &outStream ); + test_error( error, "Unable to set kernel argument" ); + + // Run test kernel + size_t threads[ 1 ] = { 16 }; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to enqueue kernel" ); + + // Read results + error = clEnqueueReadBuffer( queue, outStream, CL_TRUE, 0, sizeof( outValues ), outValues, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + // Verify results + for( int i = 0; i < 17; i++ ) + { + if( expectedValues[ i ] != outValues[ i ] ) + { + if( i == 0 ) + log_error( "ERROR: Output value %d from constant source global did not validate! (Expected %d, got %d)\n", i, expectedValues[ i ], outValues[ i ] ); + else if( i == 1 ) + log_error( "ERROR: Output value %d from constant-indexed constant array did not validate! (Expected %d, got %d)\n", i, expectedValues[ i ], outValues[ i ] ); + else + log_error( "ERROR: Output value %d from variable-indexed constant array did not validate! (Expected %d, got %d)\n", i, expectedValues[ i ], outValues[ i ] ); + return -1; + } + } + + return 0; +} + + + + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_createkernelsinprogram.c b/test_conformance/compatibility/test_conformance/basic/test_createkernelsinprogram.c new file mode 100644 index 00000000..58bcc810 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_createkernelsinprogram.c @@ -0,0 +1,121 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +const char *sample_single_kernel = { +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n"}; + +const char *sample_double_kernel = { +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n" +"__kernel void sample_test2(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n"}; + + +int +test_createkernelsinprogram(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_program program; + cl_kernel kernel[2]; + unsigned int num_kernels; + size_t lengths[2]; + int err; + + lengths[0] = strlen(sample_single_kernel); + program = clCreateProgramWithSource(context, 1, &sample_single_kernel, lengths, NULL); + if (!program) + { + log_error("clCreateProgramWithSource failed\n"); + return -1; + } + + err = clBuildProgram(program, 0, NULL, NULL, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clBuildProgramExecutable failed\n"); + return -1; + } + + err = clCreateKernelsInProgram(program, 1, kernel, &num_kernels); + if ( (err != CL_SUCCESS) || (num_kernels != 1) ) + { + log_error("clCreateKernelsInProgram test failed for a single kernel\n"); + return -1; + } + + clReleaseKernel(kernel[0]); + clReleaseProgram(program); + + lengths[0] = strlen(sample_double_kernel); + program = clCreateProgramWithSource(context, 1, &sample_double_kernel, lengths, NULL); + if (!program) + { + log_error("clCreateProgramWithSource failed\n"); + return -1; + } + + err = clBuildProgram(program, 0, NULL, NULL, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clBuildProgramExecutable failed\n"); + return -1; + } + + err = clCreateKernelsInProgram(program, 2, kernel, &num_kernels); + if ( (err != CL_SUCCESS) || (num_kernels != 2) ) + { + log_error("clCreateKernelsInProgram test failed for two kernels\n"); + return -1; + } + + log_info("clCreateKernelsInProgram test passed\n"); + + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseProgram(program); + + + return err; +} + + + + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_enqueue_map.cpp b/test_conformance/compatibility/test_conformance/basic/test_enqueue_map.cpp new file mode 100644 index 00000000..3bf7be58 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_enqueue_map.cpp @@ -0,0 +1,253 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" + +const cl_mem_flags flag_set[] = { + CL_MEM_ALLOC_HOST_PTR, + CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, + CL_MEM_USE_HOST_PTR, + CL_MEM_COPY_HOST_PTR, + 0 +}; +const char* flag_set_names[] = { + "CL_MEM_ALLOC_HOST_PTR", + "CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR", + "CL_MEM_USE_HOST_PTR", + "CL_MEM_COPY_HOST_PTR", + "0" +}; + +int test_enqueue_map_buffer(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + const size_t bufferSize = 256*256; + int src_flag_id; + MTdata d = init_genrand( gRandomSeed ); + cl_char *initialData = (cl_char*)malloc(bufferSize); + cl_char *finalData = (cl_char*)malloc(bufferSize); + + for (src_flag_id=0; src_flag_id < 5; src_flag_id++) + { + clMemWrapper memObject; + log_info("Testing with cl_mem_flags src: %s\n", flag_set_names[src_flag_id]); + + generate_random_data( kChar, (unsigned int)bufferSize, d, initialData ); + + if ((flag_set[src_flag_id] & CL_MEM_USE_HOST_PTR) || (flag_set[src_flag_id] & CL_MEM_COPY_HOST_PTR)) + memObject = clCreateBuffer(context, flag_set[src_flag_id], bufferSize * sizeof( cl_char ), initialData, &error); + else + memObject = clCreateBuffer(context, flag_set[src_flag_id], bufferSize * sizeof( cl_char ), NULL, &error); + test_error( error, "Unable to create testing buffer" ); + + if (!(flag_set[src_flag_id] & CL_MEM_USE_HOST_PTR) && !(flag_set[src_flag_id] & CL_MEM_COPY_HOST_PTR)) + { + error = clEnqueueWriteBuffer(queue, memObject, CL_TRUE, 0, bufferSize * sizeof( cl_char ), initialData, 0, NULL, NULL); + test_error( error, "clEnqueueWriteBuffer failed"); + } + + for( int i = 0; i < 128; i++ ) + { + + size_t offset = (size_t)random_in_range( 0, (int)bufferSize - 1, d ); + size_t length = (size_t)random_in_range( 1, (int)( bufferSize - offset ), d ); + + cl_char *mappedRegion = (cl_char *)clEnqueueMapBuffer( queue, memObject, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, + offset, length, 0, NULL, NULL, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "clEnqueueMapBuffer call failed" ); + log_error( "\tOffset: %d Length: %d\n", (int)offset, (int)length ); + free( initialData ); + free( finalData ); + free_mtdata(d); + return -1; + } + + // Write into the region + for( size_t j = 0; j < length; j++ ) + { + cl_char spin = (cl_char)genrand_int32( d ); + + // Test read AND write in one swipe + cl_char value = mappedRegion[ j ]; + value = spin - value; + mappedRegion[ j ] = value; + + // Also update the initial data array + value = initialData[ offset + j ]; + value = spin - value; + initialData[ offset + j ] = value; + } + + // Unmap + error = clEnqueueUnmapMemObject( queue, memObject, mappedRegion, 0, NULL, NULL ); + test_error( error, "Unable to unmap buffer" ); + } + + // Final validation: read actual values of buffer and compare against our reference + error = clEnqueueReadBuffer( queue, memObject, CL_TRUE, 0, sizeof( cl_char ) * bufferSize, finalData, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + for( size_t q = 0; q < bufferSize; q++ ) + { + if( initialData[ q ] != finalData[ q ] ) + { + log_error( "ERROR: Sample %d did not validate! Got %d, expected %d\n", (int)q, (int)finalData[ q ], (int)initialData[ q ] ); + free( initialData ); + free( finalData ); + free_mtdata(d); + return -1; + } + } + } // cl_mem flags + + free( initialData ); + free( finalData ); + free_mtdata(d); + + return 0; +} + +int test_enqueue_map_image(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_image_format format = { CL_RGBA, CL_UNSIGNED_INT32 }; + const size_t imageSize = 256; + int src_flag_id; + cl_uint *initialData; + cl_uint *finalData; + MTdata d; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID ) + + initialData = (cl_uint*)malloc(imageSize * imageSize * 4 *sizeof(cl_uint)); + finalData = (cl_uint*)malloc(imageSize * imageSize * 4 *sizeof(cl_uint)); + + if( !is_image_format_supported( context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE2D, &format ) ) + { + log_error( "ERROR: Test requires basic OpenCL 1.0 format CL_RGBA:CL_UNSIGNED_INT32, which is unsupported by this device!\n" ); + free(initialData); + free(finalData); + return -1; + } + + d = init_genrand( gRandomSeed ); + for (src_flag_id=0; src_flag_id < 5; src_flag_id++) { + clMemWrapper memObject; + log_info("Testing with cl_mem_flags src: %s\n", flag_set_names[src_flag_id]); + + generate_random_data( kUInt, (unsigned int)( imageSize * imageSize ), d, initialData ); + + if ((flag_set[src_flag_id] & CL_MEM_USE_HOST_PTR) || (flag_set[src_flag_id] & CL_MEM_COPY_HOST_PTR)) + memObject = create_image_2d( context, CL_MEM_READ_WRITE | flag_set[src_flag_id], &format, + imageSize, imageSize, 0, initialData, &error ); + else + memObject = create_image_2d( context, CL_MEM_READ_WRITE | flag_set[src_flag_id], &format, + imageSize, imageSize, 0, NULL, &error ); + test_error( error, "Unable to create testing buffer" ); + + if (!(flag_set[src_flag_id] & CL_MEM_USE_HOST_PTR) && !(flag_set[src_flag_id] & CL_MEM_COPY_HOST_PTR)) { + size_t write_origin[3]={0,0,0}, write_region[3]={imageSize, imageSize, 1}; + error = clEnqueueWriteImage(queue, memObject, CL_TRUE, write_origin, write_region, NULL, NULL, initialData, 0, NULL, NULL); + test_error( error, "Unable to write to testing buffer" ); + } + + for( int i = 0; i < 128; i++ ) + { + + size_t offset[3], region[3]; + size_t rowPitch; + + offset[ 0 ] = (size_t)random_in_range( 0, (int)imageSize - 1, d ); + region[ 0 ] = (size_t)random_in_range( 1, (int)( imageSize - offset[ 0 ] - 1), d ); + offset[ 1 ] = (size_t)random_in_range( 0, (int)imageSize - 1, d ); + region[ 1 ] = (size_t)random_in_range( 1, (int)( imageSize - offset[ 1 ] - 1), d ); + offset[ 2 ] = 0; + region[ 2 ] = 1; + cl_uint *mappedRegion = (cl_uint *)clEnqueueMapImage( queue, memObject, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, + offset, region, &rowPitch, NULL, 0, NULL, NULL, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "clEnqueueMapImage call failed" ); + log_error( "\tOffset: %d,%d Region: %d,%d\n", (int)offset[0], (int)offset[1], (int)region[0], (int)region[1] ); + free(initialData); + free(finalData); + free_mtdata(d); + return -1; + } + + // Write into the region + cl_uint *mappedPtr = mappedRegion; + for( size_t y = 0; y < region[ 1 ]; y++ ) + { + for( size_t x = 0; x < region[ 0 ] * 4; x++ ) + { + cl_int spin = (cl_int)random_in_range( 16, 1024, d ); + + cl_int value; + // Test read AND write in one swipe + value = mappedPtr[ ( y * rowPitch/sizeof(cl_uint) ) + x ]; + value = spin - value; + mappedPtr[ ( y * rowPitch/sizeof(cl_uint) ) + x ] = value; + + // Also update the initial data array + value = initialData[ ( ( offset[ 1 ] + y ) * imageSize + offset[ 0 ] ) * 4 + x ]; + value = spin - value; + initialData[ ( ( offset[ 1 ] + y ) * imageSize + offset[ 0 ] ) * 4 + x ] = value; + } + } + + // Unmap + error = clEnqueueUnmapMemObject( queue, memObject, mappedRegion, 0, NULL, NULL ); + test_error( error, "Unable to unmap buffer" ); + } + + // Final validation: read actual values of buffer and compare against our reference + size_t finalOrigin[3] = { 0, 0, 0 }, finalRegion[3] = { imageSize, imageSize, 1 }; + error = clEnqueueReadImage( queue, memObject, CL_TRUE, finalOrigin, finalRegion, 0, 0, finalData, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + for( size_t q = 0; q < imageSize * imageSize * 4; q++ ) + { + if( initialData[ q ] != finalData[ q ] ) + { + log_error( "ERROR: Sample %d (coord %d,%d) did not validate! Got %d, expected %d\n", (int)q, (int)( ( q / 4 ) % imageSize ), (int)( ( q / 4 ) / imageSize ), + (int)finalData[ q ], (int)initialData[ q ] ); + free(initialData); + free(finalData); + free_mtdata(d); + return -1; + } + } + } // cl_mem_flags + + free(initialData); + free(finalData); + free_mtdata(d); + return 0; +} + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_explicit_s2v.cpp b/test_conformance/compatibility/test_conformance/basic/test_explicit_s2v.cpp new file mode 100644 index 00000000..205e7bbd --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_explicit_s2v.cpp @@ -0,0 +1,384 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" + +#define DECLARE_S2V_IDENT_KERNEL(srctype,dsttype,size) \ +"__kernel void test_conversion(__global " srctype " *sourceValues, __global " dsttype #size " *destValues )\n" \ +"{\n" \ +" int tid = get_global_id(0);\n" \ +" " srctype " src = sourceValues[tid];\n" \ +"\n" \ +" destValues[tid] = (" dsttype #size ")src;\n" \ +"\n" \ +"}\n" + +#define DECLARE_S2V_IDENT_KERNELS(srctype,dsttype) \ +{ \ +DECLARE_S2V_IDENT_KERNEL(srctype,#dsttype,2), \ +DECLARE_S2V_IDENT_KERNEL(srctype,#dsttype,4), \ +DECLARE_S2V_IDENT_KERNEL(srctype,#dsttype,8), \ +DECLARE_S2V_IDENT_KERNEL(srctype,#dsttype,16) \ +} + +#define DECLARE_EMPTY { NULL, NULL, NULL, NULL, NULL } + +/* Note: the next four arrays all must match in order and size to the ExplicitTypes enum in conversions.h!!! */ + +#define DECLARE_S2V_IDENT_KERNELS_SET(srctype) \ +{ \ +DECLARE_S2V_IDENT_KERNELS(#srctype,bool), \ + DECLARE_S2V_IDENT_KERNELS(#srctype,char), \ + DECLARE_S2V_IDENT_KERNELS(#srctype,uchar), \ + DECLARE_S2V_IDENT_KERNELS(#srctype,unsigned char), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,short), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,ushort), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,unsigned short), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,int), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,uint), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,unsigned int), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,long), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,ulong), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,unsigned long), \ +DECLARE_S2V_IDENT_KERNELS(#srctype,float), \ +DECLARE_EMPTY \ +} + +#define DECLARE_EMPTY_SET \ +{ \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY, \ +DECLARE_EMPTY \ +} + + +/* The overall array */ +const char * kernel_explicit_s2v_set[kNumExplicitTypes][kNumExplicitTypes][5] = { + DECLARE_S2V_IDENT_KERNELS_SET(bool), + DECLARE_S2V_IDENT_KERNELS_SET(char), + DECLARE_S2V_IDENT_KERNELS_SET(uchar), + DECLARE_S2V_IDENT_KERNELS_SET(unsigned char), + DECLARE_S2V_IDENT_KERNELS_SET(short), + DECLARE_S2V_IDENT_KERNELS_SET(ushort), + DECLARE_S2V_IDENT_KERNELS_SET(unsigned short), + DECLARE_S2V_IDENT_KERNELS_SET(int), + DECLARE_S2V_IDENT_KERNELS_SET(uint), + DECLARE_S2V_IDENT_KERNELS_SET(unsigned int), + DECLARE_S2V_IDENT_KERNELS_SET(long), + DECLARE_S2V_IDENT_KERNELS_SET(ulong), + DECLARE_S2V_IDENT_KERNELS_SET(unsigned long), + DECLARE_S2V_IDENT_KERNELS_SET(float), + DECLARE_EMPTY_SET +}; + +int test_explicit_s2v_function(cl_device_id deviceID, cl_context context, cl_command_queue queue, const char *programSrc, + ExplicitType srcType, unsigned int count, ExplicitType destType, unsigned int vecSize, void *inputData ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + int error; + clMemWrapper streams[2]; + void *outData; + unsigned char convertedData[ 8 ]; /* Max type size is 8 bytes */ + size_t threadSize[3], groupSize[3]; + unsigned int i, s; + unsigned char *inPtr, *outPtr; + size_t paramSize, destTypeSize; + + const char* finalProgramSrc[2] = { + "", // optional pragma + programSrc + }; + + if (srcType == kDouble || destType == kDouble) { + finalProgramSrc[0] = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"; + } + + + if( programSrc == NULL ) + return 0; + + paramSize = get_explicit_type_size( srcType ); + destTypeSize = get_explicit_type_size( destType ); + + size_t destStride = destTypeSize * vecSize; + + outData = malloc( destStride * count ); + + if( create_single_kernel_helper( context, &program, &kernel, 2, finalProgramSrc, "test_conversion" ) ) + { + log_info( "****** %s%s *******\n", finalProgramSrc[0], finalProgramSrc[1] ); + return -1; + } + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), paramSize * count, inputData, &error); + test_error( error, "clCreateBuffer failed"); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), destStride * count, NULL, &error); + test_error( error, "clCreateBuffer failed"); + + /* Set the arguments */ + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + /* Run the kernel */ + threadSize[0] = count; + + error = get_max_common_work_group_size( context, kernel, threadSize[0], &groupSize[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threadSize, groupSize, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* Now verify the results. Each value should have been duplicated four times, and we should be able to just + do a memcpy instead of relying on the actual type of data */ + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, destStride * count, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output values!" ); + + inPtr = (unsigned char *)inputData; + outPtr = (unsigned char *)outData; + + for( i = 0; i < count; i++ ) + { + /* Convert the input data element to our output data type to compare against */ + convert_explicit_value( (void *)inPtr, (void *)convertedData, srcType, false, kDefaultRoundingType, destType ); + + /* Now compare every element of the vector */ + for( s = 0; s < vecSize; s++ ) + { + if( memcmp( convertedData, outPtr + destTypeSize * s, destTypeSize ) != 0 ) + { + unsigned int *p = (unsigned int *)outPtr; + log_error( "ERROR: Output value %d:%d does not validate for size %d:%d!\n", i, s, vecSize, (int)destTypeSize ); + log_error( " Input: 0x%0*x\n", (int)( paramSize * 2 ), *(unsigned int *)inPtr & ( 0xffffffff >> ( 32 - paramSize * 8 ) ) ); + log_error( " Actual: 0x%08x 0x%08x 0x%08x 0x%08x\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] ); + return -1; + } + } + inPtr += paramSize; + outPtr += destStride; + } + + free( outData ); + + return 0; +} + +int test_explicit_s2v_function_set(cl_device_id deviceID, cl_context context, cl_command_queue queue, ExplicitType srcType, + unsigned int count, void *inputData ) +{ + unsigned int sizes[] = { 2, 4, 8, 16, 0 }; + int i, dstType, failed = 0; + + + for( dstType = kBool; dstType < kNumExplicitTypes; dstType++ ) + { + if( dstType == kDouble && !is_extension_available( deviceID, "cl_khr_fp64" ) ) + continue; + + if (( dstType == kLong || dstType == kULong ) && !gHasLong ) + continue; + + for( i = 0; sizes[i] != 0; i++ ) + { + if( dstType != srcType ) + continue; + if( strchr( get_explicit_type_name( (ExplicitType)srcType ), ' ' ) != NULL || + strchr( get_explicit_type_name( (ExplicitType)dstType ), ' ' ) != NULL ) + continue; + + if( test_explicit_s2v_function( deviceID, context, queue, kernel_explicit_s2v_set[ srcType ][ dstType ][ i ], + srcType, count, (ExplicitType)dstType, sizes[ i ], inputData ) != 0 ) + { + log_error( "ERROR: Explicit cast of scalar %s to vector %s%d FAILED; skipping other %s vector tests\n", + get_explicit_type_name(srcType), get_explicit_type_name((ExplicitType)dstType), sizes[i], get_explicit_type_name((ExplicitType)dstType) ); + failed = -1; + break; + } + } + } + + return failed; +} + +int test_explicit_s2v_bool(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + log_info( "NOTE: Boolean vectors not defined in OpenCL 1.0. Skipping test.\n" ); + return 0; +#if 0 + bool data[128]; + + generate_random_data( kBool, 128, data ); + + return test_explicit_s2v_function_set( deviceID, context, queue, kBool, 128, data ); +#endif +} + +int test_explicit_s2v_char(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + char data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kChar, 128, seed, data ); + + return test_explicit_s2v_function_set( deviceID, context, queue, kChar, 128, data ); +} + +int test_explicit_s2v_uchar(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + unsigned char data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kUChar, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kUChar, 128, data ) != 0 ) + return -1; + if( test_explicit_s2v_function_set( deviceID, context, queue, kUnsignedChar, 128, data ) != 0 ) + return -1; + return 0; +} + +int test_explicit_s2v_short(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + short data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kShort, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kShort, 128, data ) != 0 ) + return -1; + return 0; +} + +int test_explicit_s2v_ushort(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + unsigned short data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kUShort, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kUShort, 128, data ) != 0 ) + return -1; + if( test_explicit_s2v_function_set( deviceID, context, queue, kUnsignedShort, 128, data ) != 0 ) + return -1; + return 0; +} + +int test_explicit_s2v_int(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kInt, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kInt, 128, data ) != 0 ) + return -1; + return 0; +} + +int test_explicit_s2v_uint(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + unsigned int data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kUInt, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kUInt, 128, data ) != 0 ) + return -1; + if( test_explicit_s2v_function_set( deviceID, context, queue, kUnsignedInt, 128, data ) != 0 ) + return -1; + return 0; +} + +int test_explicit_s2v_long(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_long data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kLong, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kLong, 128, data ) != 0 ) + return -1; + return 0; +} + +int test_explicit_s2v_ulong(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_ulong data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kULong, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kULong, 128, data ) != 0 ) + return -1; + if( test_explicit_s2v_function_set( deviceID, context, queue, kUnsignedLong, 128, data ) != 0 ) + return -1; + return 0; +} + +int test_explicit_s2v_float(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + float data[128]; + RandomSeed seed(gRandomSeed); + + generate_random_data( kFloat, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kFloat, 128, data ) != 0 ) + return -1; + return 0; +} + + +int test_explicit_s2v_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + double data[128]; + RandomSeed seed(gRandomSeed); + + if( !is_extension_available( deviceID, "cl_khr_fp64" ) ) { + log_info("Extension cl_khr_fp64 not supported. Skipping test.\n"); + return 0; + } + + generate_random_data( kDouble, 128, seed, data ); + + if( test_explicit_s2v_function_set( deviceID, context, queue, kDouble, 128, data ) != 0 ) + return -1; + return 0; +} + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_float2int.c b/test_conformance/compatibility/test_conformance/basic/test_float2int.c new file mode 100644 index 00000000..0191ceec --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_float2int.c @@ -0,0 +1,160 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +const char *float2int_kernel_code = +"__kernel void test_float2int(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n"; + + +int +verify_float2int(cl_float *inptr, cl_int *outptr, int n) +{ + int i; + + for (i=0; i +#include +#include +#include +#include "../../test_common/harness/rounding_mode.h" + +#include "procs.h" + +const char *fpadd_kernel_code = +"__kernel void test_fpadd(__global float *srcA, __global float *srcB, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *fpsub_kernel_code = +"__kernel void test_fpsub(__global float *srcA, __global float *srcB, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *fpmul_kernel_code = +"__kernel void test_fpmul(__global float *srcA, __global float *srcB, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + + +static const float MAX_ERR = 1e-5f; + +int +verify_fpadd(float *inptrA, float *inptrB, float *outptr, int n) +{ + float r; + int i; + + for (i=0; i +#include +#include +#include +#include "../../test_common/harness/rounding_mode.h" + + +#include "procs.h" + +const char *fpadd2_kernel_code = +"__kernel void test_fpadd2(__global float2 *srcA, __global float2 *srcB, __global float2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *fpsub2_kernel_code = +"__kernel void test_fpsub2(__global float2 *srcA, __global float2 *srcB, __global float2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *fpmul2_kernel_code = +"__kernel void test_fpmul2(__global float2 *srcA, __global float2 *srcB, __global float2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + + +int +verify_fpadd2(float *inptrA, float *inptrB, float *outptr, int n) +{ + float r; + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/rounding_mode.h" + +const char *fpadd4_kernel_code = +"__kernel void test_fpadd4(__global float4 *srcA, __global float4 *srcB, __global float4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *fpsub4_kernel_code = +"__kernel void test_fpsub4(__global float4 *srcA, __global float4 *srcB, __global float4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *fpmul4_kernel_code = +"__kernel void test_fpmul4(__global float4 *srcA, __global float4 *srcB, __global float4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + + +int +verify_fpadd4(float *inptrA, float *inptrB, float *outptr, int n) +{ + float r; + int i; + + for (i=0; i + + +const char *work_offset_test[] = { + "__kernel void test( __global int * outputID_A, \n" + " __global int * outputID_B, __global int * outputID_C )\n" + "{\n" + " size_t id0 = get_local_id( 0 ) + get_group_id( 0 ) * get_local_size( 0 );\n" + " size_t id1 = get_local_id( 1 ) + get_group_id( 1 ) * get_local_size( 1 );\n" + " size_t id2 = get_local_id( 2 ) + get_group_id( 2 ) * get_local_size( 2 );\n" + " size_t id = ( id2 * get_global_size( 0 ) * get_global_size( 1 ) ) + ( id1 * get_global_size( 0 ) ) + id0;\n" + "\n" + " outputID_A[ id ] = get_global_id( 0 );\n" + " outputID_B[ id ] = get_global_id( 1 );\n" + " outputID_C[ id ] = get_global_id( 2 );\n" + "}\n" + }; + +#define MAX_TEST_ITEMS 16 * 16 * 16 +#define NUM_TESTS 16 +#define MAX_OFFSET 256 + +#define CHECK_RANGE( v, m, c ) \ + if( ( v >= (cl_int)m ) || ( v < 0 ) ) \ + { \ + log_error( "ERROR: ouputID_%c[%lu]: %d is < 0 or >= %lu\n", c, i, v, m ); \ + return -1; \ + } + +int check_results( size_t threads[], size_t offsets[], cl_int outputA[], cl_int outputB[], cl_int outputC[] ) +{ + size_t offsettedSizes[ 3 ] = { threads[ 0 ] + offsets[ 0 ], threads[ 1 ] + offsets[ 1 ], threads[ 2 ] + offsets[ 2 ] }; + size_t limit = threads[ 0 ] * threads[ 1 ] * threads[ 2 ]; + + static char counts[ MAX_OFFSET + 32 ][ MAX_OFFSET + 16 ][ MAX_OFFSET + 16 ]; + memset( counts, 0, sizeof( counts ) ); + + for( size_t i = 0; i < limit; i++ ) + { + // Check ranges first + CHECK_RANGE( outputA[ i ], offsettedSizes[ 0 ], 'A' ) + CHECK_RANGE( outputB[ i ], offsettedSizes[ 1 ], 'B' ) + CHECK_RANGE( outputC[ i ], offsettedSizes[ 2 ], 'C' ) + + // Now set the value in the map + counts[ outputA[ i ] ][ outputB[ i ] ][ outputC[ i ] ]++; + } + + // Now check the map + int missed = 0, multiple = 0, errored = 0, corrected = 0; + for( size_t x = 0; x < offsettedSizes[ 0 ]; x++ ) + { + for( size_t y = 0; y < offsettedSizes[ 1 ]; y++ ) + { + for( size_t z = 0; z < offsettedSizes[ 2 ]; z++ ) + { + const char * limitMsg = " (further errors of this type suppressed)"; + if( ( x >= offsets[ 0 ] ) && ( y >= offsets[ 1 ] ) && ( z >= offsets[ 2 ] ) ) + { + if( counts[ x ][ y ][ z ] < 1 ) + { + if( missed < 3 ) + log_error( "ERROR: Map value (%ld,%ld,%ld) was missed%s\n", x, y, z, ( missed == 2 ) ? limitMsg : "" ); + missed++; + } + else if( counts[ x ][ y ][ z ] > 1 ) + { + if( multiple < 3 ) + log_error( "ERROR: Map value (%ld,%ld,%ld) was returned multiple times%s\n", x, y, z, ( multiple == 2 ) ? limitMsg : "" ); + multiple++; + } + } + else + { + if( counts[ x ][ y ][ z ] > 0 ) + { + if( errored < 3 ) + log_error( "ERROR: Map value (%ld,%ld,%ld) was erroneously returned%s\n", x, y, z, ( errored == 2 ) ? limitMsg : "" ); + errored++; + } + } + } + } + } + + if( missed || multiple || errored ) + { + size_t diffs[3] = { ( offsets[ 0 ] > threads[ 0 ] ? 0 : threads[ 0 ] - offsets[ 0 ] ), + ( offsets[ 1 ] > threads[ 1 ] ? 0 : threads[ 1 ] - offsets[ 1 ] ), + ( offsets[ 2 ] > threads[ 2 ] ? 0 : threads[ 2 ] - offsets[ 2 ] ) }; + int diff = (int)( ( threads[ 0 ] - diffs[ 0 ] ) * ( threads[ 1 ] - diffs[ 1 ] ) * ( threads[ 2 ] - diffs[ 2 ] ) ); + + if( ( multiple == 0 ) && ( missed == diff ) && ( errored == diff ) ) + log_error( "ERROR: Global work offset values are not being respected by get_global_id()\n" ); + else + log_error( "ERROR: Global work offset values did not function as expected (%d missed, %d reported multiple times, %d erroneously hit)\n", + missed, multiple, errored ); + } + return ( missed | multiple | errored | corrected ); +} + +int test_global_work_offsets(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 7 ]; + + int error; + size_t threads[] = {1,1,1}, localThreads[] = {1,1,1}, offsets[] = {0,0,0}; + cl_int outputA[ MAX_TEST_ITEMS ], outputB[ MAX_TEST_ITEMS ], outputC[ MAX_TEST_ITEMS ]; + + + // Create the kernel + if( create_single_kernel_helper( context, &program, &kernel, 1, work_offset_test, "test" ) != 0 ) + { + return -1; + } + + //// Create some output streams + + // Use just one output array to init them all (no need to init every single stack storage here) + memset( outputA, 0xff, sizeof( outputA ) ); + for( int i = 0; i < 3; i++ ) + { + streams[ i ] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR), sizeof(outputA), outputA, &error ); + test_error( error, "Unable to create output array" ); + } + + // Run a few different times + MTdata seed = init_genrand( gRandomSeed ); + for( int test = 0; test < NUM_TESTS; test++ ) + { + // Choose a random combination of thread size, but in total less than MAX_TEST_ITEMS + threads[ 0 ] = random_in_range( 1, 32, seed ); + threads[ 1 ] = random_in_range( 1, 16, seed ); + threads[ 2 ] = random_in_range( 1, MAX_TEST_ITEMS / (int)( threads[ 0 ] * threads[ 1 ] ), seed ); + + // Make sure we get the local thread count right + error = get_max_common_3D_work_group_size( context, kernel, threads, localThreads ); + test_error( error, "Unable to determine local work group sizes" ); + + // Randomize some offsets + for( int j = 0; j < 3; j++ ) + offsets[ j ] = random_in_range( 0, MAX_OFFSET, seed ); + + log_info( "\tTesting %ld,%ld,%ld (%ld,%ld,%ld) with offsets (%ld,%ld,%ld)...\n", + threads[ 0 ], threads[ 1 ], threads[ 2 ], localThreads[ 0 ], localThreads[ 1 ], localThreads[ 2 ], + offsets[ 0 ], offsets[ 1 ], offsets[ 2 ] ); + + // Now set up and run + for( int i = 0; i < 3; i++ ) + { + error = clSetKernelArg( kernel, i, sizeof( streams[i] ), &streams[i] ); + test_error( error, "Unable to set indexed kernel arguments" ); + } + + error = clEnqueueNDRangeKernel( queue, kernel, 3, offsets, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + // Read our results back now + cl_int * resultBuffers[] = { outputA, outputB, outputC }; + for( int i = 0; i < 3; i++ ) + { + error = clEnqueueReadBuffer( queue, streams[ i ], CL_TRUE, 0, sizeof( outputA ), resultBuffers[ i ], 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + } + + // Now we need to check the results. The outputs should have one entry for each possible ID, + // but they won't be in order, so we need to construct a count map to determine what we got + if( check_results( threads, offsets, outputA, outputB, outputC ) ) + { + log_error( "\t(Test failed for global dim %ld,%ld,%ld, local dim %ld,%ld,%ld, offsets %ld,%ld,%ld)\n", + threads[ 0 ], threads[ 1 ], threads[ 2 ], localThreads[ 0 ], localThreads[ 1 ], localThreads[ 2 ], + offsets[ 0 ], offsets[ 1 ], offsets[ 2 ] ); + return -1; + } + } + + free_mtdata(seed); + + // All done! + return 0; +} + +const char *get_offset_test[] = { + "__kernel void test( __global int * outOffsets )\n" + "{\n" + " // We use local ID here so we don't have to worry about offsets\n" + " // Also note that these should be the same for ALL threads, so we won't worry about contention\n" + " outOffsets[ 0 ] = (int)get_global_offset( 0 );\n" + " outOffsets[ 1 ] = (int)get_global_offset( 1 );\n" + " outOffsets[ 2 ] = (int)get_global_offset( 2 );\n" + "}\n" +}; + +int test_get_global_offset(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 1 ]; + + int error; + size_t threads[] = {1,1,1}, localThreads[] = {1,1,1}, offsets[] = {0,0,0}; + cl_int outOffsets[ 3 ]; + + + // Create the kernel + if( create_single_kernel_helper( context, &program, &kernel, 1, get_offset_test, "test" ) != 0 ) + { + return -1; + } + + // Create some output streams, and storage for a single control ID + memset( outOffsets, 0xff, sizeof( outOffsets ) ); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR), sizeof( outOffsets ), outOffsets, &error ); + test_error( error, "Unable to create control ID buffer" ); + + // Run a few different times + MTdata seed = init_genrand( gRandomSeed ); + for( int test = 0; test < NUM_TESTS; test++ ) + { + // Choose a random combination of thread size, but in total less than MAX_TEST_ITEMS + threads[ 0 ] = random_in_range( 1, 32, seed ); + threads[ 1 ] = random_in_range( 1, 16, seed ); + threads[ 2 ] = random_in_range( 1, MAX_TEST_ITEMS / (int)( threads[ 0 ] * threads[ 1 ] ), seed ); + + // Make sure we get the local thread count right + error = get_max_common_3D_work_group_size( context, kernel, threads, localThreads ); + test_error( error, "Unable to determine local work group sizes" ); + + // Randomize some offsets + for( int j = 0; j < 3; j++ ) + offsets[ j ] = random_in_range( 0, MAX_OFFSET, seed ); + + log_info( "\tTesting %ld,%ld,%ld (%ld,%ld,%ld) with offsets (%ld,%ld,%ld)...\n", + threads[ 0 ], threads[ 1 ], threads[ 2 ], localThreads[ 0 ], localThreads[ 1 ], localThreads[ 2 ], + offsets[ 0 ], offsets[ 1 ], offsets[ 2 ] ); + + // Now set up and run + error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 3, offsets, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + // Read our results back now + error = clEnqueueReadBuffer( queue, streams[ 0 ], CL_TRUE, 0, sizeof( outOffsets ), outOffsets, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + // And check! + int errors = 0; + for( int j = 0; j < 3; j++ ) + { + if( outOffsets[ j ] != (cl_int)offsets[ j ] ) + { + log_error( "ERROR: get_global_offset( %d ) did not return expected value (expected %ld, got %d)\n", j, offsets[ j ], outOffsets[ j ] ); + errors++; + } + } + if( errors > 0 ) + return errors; + } + free_mtdata(seed); + + // All done! + return 0; +} + diff --git a/test_conformance/compatibility/test_conformance/basic/test_hiloeo.c b/test_conformance/compatibility/test_conformance/basic/test_hiloeo.c new file mode 100644 index 00000000..72e97cee --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_hiloeo.c @@ -0,0 +1,421 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + + +#include "procs.h" + +int hi_offset( int index, int vectorSize) { return index + vectorSize / 2; } +int lo_offset( int index, int vectorSize) { return index; } +int even_offset( int index, int vectorSize ) { return index * 2; } +int odd_offset( int index, int vectorSize ) { return index * 2 + 1; } + +typedef int (*OffsetFunc)( int index, int vectorSize ); +static const OffsetFunc offsetFuncs[4] = { hi_offset, lo_offset, even_offset, odd_offset }; +typedef int (*verifyFunc)( const void *, const void *, const void *, int n, const char *sizeName ); +static const char *operatorToUse_names[] = { "hi", "lo", "even", "odd" }; +static const char *test_str_names[] = { "char", "uchar", "short", "ushort", "int", "uint", "long", "ulong", "float", "double" }; + +static const unsigned int vector_sizes[] = { 1, 2, 3, 4, 8, 16}; +static const unsigned int vector_aligns[] = { 1, 2, 4, 4, 8, 16}; +static const unsigned int out_vector_idx[] = { 0, 0, 1, 1, 3, 4}; +// if input is size vector_sizes[i], output is size +// vector_sizes[out_vector_idx[i]] +// input type name is strcat(gentype, vector_size_names[i]); +// and output type name is +// strcat(gentype, vector_size_names[out_vector_idx[i]]); +static const int size_to_idx[] = {-1,0,1,2,3,-1,-1,-1,4, + -1,-1,-1,-1,-1,-1,-1,5}; +static const char *vector_size_names[] = { "", "2", "3", "4", "8", "16"}; + +static const size_t kSizes[] = { 1, 1, 2, 2, 4, 4, 8, 8, 4, 8 }; +static int CheckResults( void *in, void *out, size_t elementCount, int type, int vectorSize, int operatorToUse ); + +int test_hiloeo(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_int *input_ptr, *output_ptr, *p; + int err; + cl_uint i; + int hasDouble = is_extension_available( device, "cl_khr_fp64" ); + cl_uint vectorSize, operatorToUse; + cl_uint type; + MTdata d; + + int expressionMode; + int numExpressionModes = 2; + + size_t length = sizeof(cl_int) * 4 * n_elems; + + input_ptr = (cl_int*)malloc(length); + output_ptr = (cl_int*)malloc(length); + + p = input_ptr; + d = init_genrand( gRandomSeed ); + for (i=0; i<4 * (cl_uint) n_elems; i++) + p[i] = genrand_int32(d); + free_mtdata(d); d = NULL; + + for( type = 0; type < sizeof( test_str_names ) / sizeof( test_str_names[0] ); type++ ) + { + // Note: restrict the element count here so we don't end up overrunning the output buffer if we're compensating for 32-bit writes + size_t elementCount = length / kSizes[type]; + cl_mem streams[2]; + + // skip double if unavailable + if( !hasDouble && ( 0 == strcmp( test_str_names[type], "double" ))) + continue; + + if( !gHasLong && + ( 0 == strcmp( test_str_names[type], "long" )) && + ( 0 == strcmp( test_str_names[type], "ulong" ))) + continue; + + log_info( "%s", test_str_names[type] ); + fflush( stdout ); + + // Set up data streams for the type + streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + err = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, length, input_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + + for( operatorToUse = 0; operatorToUse < sizeof( operatorToUse_names ) / sizeof( operatorToUse_names[0] ); operatorToUse++ ) + { + log_info( " %s", operatorToUse_names[ operatorToUse ] ); + fflush( stdout ); + for( vectorSize = 1; vectorSize < sizeof( vector_size_names ) / sizeof( vector_size_names[0] ); vectorSize++ ) { + for(expressionMode = 0; expressionMode < numExpressionModes; ++expressionMode) { + + cl_program program = NULL; + cl_kernel kernel = NULL; + cl_uint outVectorSize = out_vector_idx[vectorSize]; + char expression[1024]; + + const char *source[] = { + "", // optional pragma string + "__kernel void test_", operatorToUse_names[ operatorToUse ], "_", test_str_names[type], vector_size_names[vectorSize], + "(__global ", test_str_names[type], vector_size_names[vectorSize], + " *srcA, __global ", test_str_names[type], vector_size_names[outVectorSize], + " *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " ", test_str_names[type], + vector_size_names[out_vector_idx[vectorSize]], + " tmp = ", expression, ".", operatorToUse_names[ operatorToUse ], ";\n" + " dst[tid] = tmp;\n" + "}\n" + }; + + if(expressionMode == 0) { + sprintf(expression, "srcA[tid]"); + } else if(expressionMode == 1) { + switch(vector_sizes[vectorSize]) { + case 16: + sprintf(expression, + "((%s16)(srcA[tid].s0, srcA[tid].s1, srcA[tid].s2, srcA[tid].s3, srcA[tid].s4, srcA[tid].s5, srcA[tid].s6, srcA[tid].s7, srcA[tid].s8, srcA[tid].s9, srcA[tid].sA, srcA[tid].sB, srcA[tid].sC, srcA[tid].sD, srcA[tid].sE, srcA[tid].sf))", + test_str_names[type] + ); + break; + case 8: + sprintf(expression, + "((%s8)(srcA[tid].s0, srcA[tid].s1, srcA[tid].s2, srcA[tid].s3, srcA[tid].s4, srcA[tid].s5, srcA[tid].s6, srcA[tid].s7))", + test_str_names[type] + ); + break; + case 4: + sprintf(expression, + "((%s4)(srcA[tid].s0, srcA[tid].s1, srcA[tid].s2, srcA[tid].s3))", + test_str_names[type] + ); + break; + case 3: + sprintf(expression, + "((%s3)(srcA[tid].s0, srcA[tid].s1, srcA[tid].s2))", + test_str_names[type] + ); + break; + case 2: + sprintf(expression, + "((%s2)(srcA[tid].s0, srcA[tid].s1))", + test_str_names[type] + ); + break; + default : + sprintf(expression, "srcA[tid]"); + log_info("Default\n"); + } + } else { + sprintf(expression, "srcA[tid]"); + } + + if (0 == strcmp( test_str_names[type], "double" )) + source[0] = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"; + + char kernelName[128]; + snprintf( kernelName, sizeof( kernelName ), "test_%s_%s%s", operatorToUse_names[ operatorToUse ], test_str_names[type], vector_size_names[vectorSize] ); + err = create_single_kernel_helper(context, &program, &kernel, sizeof( source ) / sizeof( source[0] ), source, kernelName ); + if (err) + return -1; + + err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]); + err |= clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + //Wipe the output buffer clean + uint32_t pattern = 0xdeadbeef; + memset_pattern4( output_ptr, &pattern, length ); + err = clEnqueueWriteBuffer(queue, streams[1], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + + size_t size = elementCount / (vector_aligns[vectorSize]); + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &size, NULL, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + err = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueReadBuffer failed\n"); + return -1; + } + + char *inP = (char *)input_ptr; + char *outP = (char *)output_ptr; + outP += kSizes[type] * ( ( vector_sizes[outVectorSize] ) - + ( vector_sizes[ out_vector_idx[vectorSize] ] ) ); + // was outP += kSizes[type] * ( ( 1 << outVectorSize ) - ( 1 << ( vectorSize - 1 ) ) ); + for( size_t e = 0; e < size; e++ ) + { + if( CheckResults( inP, outP, 1, type, vectorSize, operatorToUse ) ) { + + log_info("e is %d\n", (int)e); + fflush(stdout); + // break; + return -1; + } + inP += kSizes[type] * ( vector_aligns[vectorSize] ); + outP += kSizes[type] * ( vector_aligns[outVectorSize] ); + } + + clReleaseKernel( kernel ); + clReleaseProgram( program ); + log_info( "." ); + fflush( stdout ); + } + } + } + + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + log_info( "done\n" ); + } + + log_info("HiLoEO test passed\n"); + + free(input_ptr); + free(output_ptr); + + return err; +} + +static int CheckResults( void *in, void *out, size_t elementCount, int type, int vectorSize, int operatorToUse ) +{ + cl_ulong array[8]; + void *p = array; + size_t halfVectorSize = vector_sizes[out_vector_idx[vectorSize]]; + size_t cmpVectorSize = vector_sizes[out_vector_idx[vectorSize]]; + // was 1 << (vectorSize-1); + OffsetFunc f = offsetFuncs[ operatorToUse ]; + size_t elementSize = kSizes[type]; + + if(vector_size_names[vectorSize][0] == '3') { + if(operatorToUse_names[operatorToUse][0] == 'h' || + operatorToUse_names[operatorToUse][0] == 'o') // hi or odd + { + cmpVectorSize = 1; // special case for vec3 ignored values + } + } + + switch( elementSize ) + { + case 1: + { + char *i = (char*)in; + char *o = (char*)out; + size_t j; + cl_uint k; + OffsetFunc f = offsetFuncs[ operatorToUse ]; + + for( k = 0; k < elementCount; k++ ) + { + char *o2 = (char*)p; + for( j = 0; j < halfVectorSize; j++ ) + o2[j] = i[ f((int)j, (int)halfVectorSize*2) ]; + + if( memcmp( o, o2, elementSize * cmpVectorSize ) ) + { + log_info( "\n%d) Failure for %s%s.%s { %d", k, test_str_names[type], vector_size_names[ vectorSize ], operatorToUse_names[ operatorToUse ], i[0] ); + for( j = 1; j < halfVectorSize * 2; j++ ) + log_info( ", %d", i[j] ); + log_info( " } --> { %d", o[0] ); + for( j = 1; j < halfVectorSize; j++ ) + log_info( ", %d", o[j] ); + log_info( " }\n" ); + return -1; + } + i += 2 * halfVectorSize; + o += halfVectorSize; + } + } + break; + + case 2: + { + short *i = (short*)in; + short *o = (short*)out; + size_t j; + cl_uint k; + + for( k = 0; k < elementCount; k++ ) + { + short *o2 = (short*)p; + for( j = 0; j < halfVectorSize; j++ ) + o2[j] = i[ f((int)j, (int)halfVectorSize*2) ]; + + if( memcmp( o, o2, elementSize * cmpVectorSize ) ) + { + log_info( "\n%d) Failure for %s%s.%s { %d", k, test_str_names[type], vector_size_names[ vectorSize ], operatorToUse_names[ operatorToUse ], i[0] ); + for( j = 1; j < halfVectorSize * 2; j++ ) + log_info( ", %d", i[j] ); + log_info( " } --> { %d", o[0] ); + for( j = 1; j < halfVectorSize; j++ ) + log_info( ", %d", o[j] ); + log_info( " }\n" ); + return -1; + } + i += 2 * halfVectorSize; + o += halfVectorSize; + } + } + break; + + case 4: + { + int *i = (int*)in; + int *o = (int*)out; + size_t j; + cl_uint k; + + for( k = 0; k < elementCount; k++ ) + { + int *o2 = (int *)p; + for( j = 0; j < halfVectorSize; j++ ) + o2[j] = i[ f((int)j, (int)halfVectorSize*2) ]; + + for( j = 0; j < cmpVectorSize; j++ ) + { + /* Allow float nans to be binary different */ + if( memcmp( &o[j], &o2[j], elementSize ) && !((strcmp(test_str_names[type], "float") == 0) && isnan(((float *)o)[j]) && isnan(((float *)o2)[j]))) + { + log_info( "\n%d) Failure for %s%s.%s { 0x%8.8x", k, test_str_names[type], vector_size_names[ vectorSize ], operatorToUse_names[ operatorToUse ], i[0] ); + for( j = 1; j < halfVectorSize * 2; j++ ) + log_info( ", 0x%8.8x", i[j] ); + log_info( " } --> { 0x%8.8x", o[0] ); + for( j = 1; j < halfVectorSize; j++ ) + log_info( ", 0x%8.8x", o[j] ); + log_info( " }\n" ); + return -1; + } + } + i += 2 * halfVectorSize; + o += halfVectorSize; + } + } + break; + + case 8: + { + cl_ulong *i = (cl_ulong*)in; + cl_ulong *o = (cl_ulong*)out; + size_t j; + cl_uint k; + + for( k = 0; k < elementCount; k++ ) + { + cl_ulong *o2 = (cl_ulong*)p; + for( j = 0; j < halfVectorSize; j++ ) + o2[j] = i[ f((int)j, (int)halfVectorSize*2) ]; + + if( memcmp( o, o2, elementSize * cmpVectorSize ) ) + { + log_info( "\n%d) Failure for %s%s.%s { 0x%16.16llx", k, test_str_names[type], vector_size_names[ vectorSize ], operatorToUse_names[ operatorToUse ], i[0] ); + for( j = 1; j < halfVectorSize * 2; j++ ) + log_info( ", 0x%16.16llx", i[j] ); + log_info( " } --> { 0x%16.16llx", o[0] ); + for( j = 1; j < halfVectorSize; j++ ) + log_info( ", 0x%16.16llx", o[j] ); + log_info( " }\n" ); + return -1; + } + i += 2 * halfVectorSize; + o += halfVectorSize; + } + } + break; + + default: + log_info( "Internal error. Unknown data type\n" ); + return -2; + } + + return 0; +} + + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_hostptr.c b/test_conformance/compatibility/test_conformance/basic/test_hostptr.c new file mode 100644 index 00000000..fed42ff0 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_hostptr.c @@ -0,0 +1,276 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +const char *hostptr_kernel_code = +"__kernel void test_hostptr(__global float *srcA, __global float *srcB, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +static const float MAX_ERR = 1e-5f; + +static int verify_hostptr(cl_float *inptrA, cl_float *inptrB, cl_float *outptr, int n) +{ + cl_float r; + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +const char *conditional_kernel_code = +"__kernel void test_if(__global int *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" if (src[tid] == 0)\n" +" dst[tid] = 0x12345678;\n" +" else if (src[tid] == 1)\n" +" dst[tid] = 0x23456781;\n" +" else if (src[tid] == 2)\n" +" dst[tid] = 0x34567812;\n" +" else if (src[tid] == 3)\n" +" dst[tid] = 0x45678123;\n" +" else if (src[tid] == 4)\n" +" dst[tid] = 0x56781234;\n" +" else if (src[tid] == 5)\n" +" dst[tid] = 0x67812345;\n" +" else if (src[tid] == 6)\n" +" dst[tid] = 0x78123456;\n" +" else if (src[tid] == 7)\n" +" dst[tid] = 0x81234567;\n" +" else\n" +" dst[tid] = 0x7FFFFFFF;\n" +"\n" +"}\n"; + +const int results[] = { + 0x12345678, + 0x23456781, + 0x34567812, + 0x45678123, + 0x56781234, + 0x67812345, + 0x78123456, + 0x81234567, +}; + +int +verify_if(int *inptr, int *outptr, int n) +{ + int r, i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +static const char *image_to_image_kernel_integer_coord_code = +"\n" +"__kernel void image_to_image_copy(read_only image2d_t srcimg, write_only image2d_t dstimg, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y));\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + +static const char *image_to_image_kernel_float_coord_code = +"\n" +"__kernel void image_to_image_copy(read_only image2d_t srcimg, write_only image2d_t dstimg, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (float2)((float)tid_x, (float)tid_y));\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + + +static const char *image_sum_kernel_integer_coord_code = +"\n" +"__kernel void image_sum(read_only image2d_t srcimg0, read_only image2d_t srcimg1, write_only image2d_t dstimg, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 color0;\n" +" float4 color1;\n" +"\n" +" color0 = read_imagef(srcimg0, sampler, (int2)(tid_x, tid_y));\n" +" color1 = read_imagef(srcimg1, sampler, (int2)(tid_x, tid_y));\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color0 + color1);\n" +"\n" +"}\n"; + + +static const char *image_sum_kernel_float_coord_code = +"\n" +"__kernel void image_sum(read_only image2d_t srcimg0, read_only image2d_t srcimg1, write_only image2d_t dstimg, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 color0;\n" +" float4 color1;\n" +"\n" +" color0 = read_imagef(srcimg0, sampler, (float2)((float)tid_x, (float)tid_y));\n" +" color1 = read_imagef(srcimg1, sampler, (float2)((float)tid_x, (float)tid_y));\n" +" write_imagef(dstimg,(int2)(tid_x, tid_y), color0 + color1);\n" +"\n" +"}\n"; + + +static unsigned char * +generate_initial_byte_image(int w, int h, int num_elements, unsigned char value) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * num_elements); + int i; + + for (i = 0; i < w*h*num_elements; i++) + ptr[i] = value; + + return ptr; +} + +static unsigned char * +generate_expected_byte_image(unsigned char **input_data, int num_inputs, int w, int h, int num_elements) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * num_elements); + int i; + + for (i = 0; i < w*h*num_elements; i++) + { + int j; + ptr[i] = 0; + for (j = 0; j < num_inputs; j++) + { + unsigned char *input = *(input_data + j); + ptr[i] += input[i]; + } + } + + return ptr; +} + + +static unsigned char * +generate_byte_image(int w, int h, int num_elements, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * num_elements); + int i; + + for (i = 0; i < w*h*num_elements; i++) + ptr[i] = (unsigned char)genrand_int32(d) & 31; + + return ptr; +} + +static int +verify_byte_image(unsigned char *image, unsigned char *outptr, int w, int h, int num_elements) +{ + int i; + + for (i = 0; i < w*h*num_elements; i++) + { + if (outptr[i] != image[i]) + { + return -1; + } + } + return 0; +} + +int +test_image_multipass_integer_coord(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + int img_width = 512; + int img_height = 512; + cl_image_format img_format; + + int num_input_streams = 8; + cl_mem *input_streams; + cl_mem accum_streams[2]; + unsigned char *expected_output; + unsigned char *output_ptr; + cl_kernel kernel[2]; + int err; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + + expected_output = (unsigned char*)malloc(sizeof(unsigned char) * 4 * img_width * img_height); + output_ptr = (unsigned char*)malloc(sizeof(unsigned char) * 4 * img_width * img_height); + + // Create the accum images with initial data. + { + unsigned char *initial_data; + cl_mem_flags flags; + + initial_data = generate_initial_byte_image(img_width, img_height, 4, 0xF0); + flags = (cl_mem_flags)(CL_MEM_READ_WRITE); + + accum_streams[0] = create_image_2d(context, flags, &img_format, img_width, img_height, 0, NULL, NULL); + if (!accum_streams[0]) + { + log_error("create_image_2d failed\n"); + free(expected_output); + free(output_ptr); + return -1; + } + + size_t origin[3] = {0, 0, 0}, region[3] = {img_width, img_height, 1}; + err = clEnqueueWriteImage(queue, accum_streams[0], CL_TRUE, + origin, region, 0, 0, + initial_data, 0, NULL, NULL); + if (err) + { + log_error("clWriteImage failed: %d\n", err); + free(expected_output); + free(output_ptr); + return -1; + } + + accum_streams[1] = create_image_2d(context, flags, &img_format, img_width, img_height, 0, NULL, NULL); + if (!accum_streams[1]) + { + log_error("create_image_2d failed\n"); + free(expected_output); + free(output_ptr); + return -1; + } + err = clEnqueueWriteImage(queue, accum_streams[1], CL_TRUE, + origin, region, 0, 0, + initial_data, 0, NULL, NULL); + if (err) + { + log_error("clWriteImage failed: %d\n", err); + free(expected_output); + free(output_ptr); + return -1; + } + + free(initial_data); + } + + // Set up the input data. + { + cl_mem_flags flags; + unsigned char **input_data = (unsigned char **)malloc(sizeof(unsigned char*) * num_input_streams); + MTdata d; + + input_streams = (cl_mem*)malloc(sizeof(cl_mem) * num_input_streams); + flags = (cl_mem_flags)(CL_MEM_READ_WRITE); + + int i; + d = init_genrand( gRandomSeed ); + for ( i = 0; i < num_input_streams; i++) + { + input_data[i] = generate_byte_image(img_width, img_height, 4, d); + input_streams[i] = create_image_2d(context, flags, &img_format, img_width, img_height, 0, NULL, NULL); + if (!input_streams[i]) + { + log_error("create_image_2d failed\n"); + free_mtdata(d); + free(expected_output); + free(output_ptr); + return -1; + } + + size_t origin[3] = {0, 0, 0}, region[3] = {img_width, img_height, 1}; + err = clEnqueueWriteImage(queue, input_streams[i], CL_TRUE, + origin, region, 0, 0, + input_data[i], 0, NULL, NULL); + if (err) + { + log_error("clWriteImage failed: %d\n", err); + free_mtdata(d); + free(expected_output); + free(output_ptr); + free(input_streams); + return -1; + } + + + } + free_mtdata(d); d = NULL; + expected_output = generate_expected_byte_image(input_data, num_input_streams, img_width, img_height, 4); + for ( i = 0; i < num_input_streams; i++) + { + free(input_data[i]); + } + free( input_data ); + } + + // Set up the kernels. + { + cl_program program[4]; + + err = create_single_kernel_helper(context, &program[0], &kernel[0], 1, &image_to_image_kernel_integer_coord_code, "image_to_image_copy"); + if (err) + { + log_error("Failed to create kernel 0: %d\n", err); + return -1; + } + err = create_single_kernel_helper(context, &program[1], &kernel[1], 1, &image_sum_kernel_integer_coord_code, "image_sum"); + if (err) + { + log_error("Failed to create kernel 1: %d\n", err); + return -1; + } + clReleaseProgram(program[0]); + clReleaseProgram(program[1]); + } + + cl_sampler sampler = clCreateSampler(context, CL_FALSE, CL_ADDRESS_CLAMP_TO_EDGE, CL_FILTER_NEAREST, &err); + test_error(err, "clCreateSampler failed"); + + { + size_t threads[3] = {0, 0, 0}; + threads[0] = (size_t)img_width; + threads[1] = (size_t)img_height; + int i; + + { + cl_mem accum_input; + cl_mem accum_output; + + err = clSetKernelArg(kernel[0], 0, sizeof input_streams[0], &input_streams[0]); + err |= clSetKernelArg(kernel[0], 1, sizeof accum_streams[0], &accum_streams[0]); + err |= clSetKernelArg(kernel[0], 2, sizeof sampler, &sampler); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + err = clEnqueueNDRangeKernel( queue, kernel[0], 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + for (i = 1; i < num_input_streams; i++) + { + accum_input = accum_streams[(i-1)%2]; + accum_output = accum_streams[i%2]; + + err = clSetKernelArg(kernel[1], 0, sizeof accum_input, &accum_input); + err |= clSetKernelArg(kernel[1], 1, sizeof input_streams[i], &input_streams[i]); + err |= clSetKernelArg(kernel[1], 2, sizeof accum_output, &accum_output); + err |= clSetKernelArg(kernel[1], 3, sizeof sampler, &sampler); + + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + err = clEnqueueNDRangeKernel( queue, kernel[1], 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + } + + // Copy the last accum into the other one. + accum_input = accum_streams[(i-1)%2]; + accum_output = accum_streams[i%2]; + err = clSetKernelArg(kernel[0], 0, sizeof accum_input, &accum_input); + err |= clSetKernelArg(kernel[0], 1, sizeof accum_output, &accum_output); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + err = clEnqueueNDRangeKernel( queue, kernel[0], 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + size_t origin[3] = {0, 0, 0}, region[3] = {img_width, img_height, 1}; + err = clEnqueueReadImage(queue, accum_output, CL_TRUE, + origin, region, 0, 0, + (void *)output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clReadImage failed\n"); + return -1; + } + err = verify_byte_image(expected_output, output_ptr, img_width, img_height, 4); + if (err) + { + log_error("IMAGE_MULTIPASS test failed.\n"); + } + else + { + log_info("IMAGE_MULTIPASS test passed\n"); + } + } + + clReleaseSampler(sampler); + } + + + // cleanup + clReleaseMemObject(accum_streams[0]); + clReleaseMemObject(accum_streams[1]); + { + int i; + for (i = 0; i < num_input_streams; i++) + { + clReleaseMemObject(input_streams[i]); + } + } + free(input_streams); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + free(expected_output); + free(output_ptr); + + return err; +} + +int +test_image_multipass_float_coord(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + int img_width = 512; + int img_height = 512; + cl_image_format img_format; + + int num_input_streams = 8; + cl_mem *input_streams; + cl_mem accum_streams[2]; + unsigned char *expected_output; + unsigned char *output_ptr; + cl_kernel kernel[2]; + int err; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + + output_ptr = (unsigned char*)malloc(sizeof(unsigned char) * 4 * img_width * img_height); + + // Create the accum images with initial data. + { + unsigned char *initial_data; + cl_mem_flags flags; + + initial_data = generate_initial_byte_image(img_width, img_height, 4, 0xF0); + flags = (cl_mem_flags)(CL_MEM_READ_WRITE); + + accum_streams[0] = create_image_2d(context, flags, &img_format, img_width, img_height, 0, NULL, NULL); + if (!accum_streams[0]) + { + log_error("create_image_2d failed\n"); + return -1; + } + + size_t origin[3] = {0, 0, 0}, region[3] = {img_width, img_height, 1}; + err = clEnqueueWriteImage(queue, accum_streams[0], CL_TRUE, + origin, region, 0, 0, + initial_data, 0, NULL, NULL); + if (err) + { + log_error("clWriteImage failed: %d\n", err); + return -1; + } + + accum_streams[1] = create_image_2d(context, flags, &img_format, img_width, img_height, 0, NULL, NULL); + if (!accum_streams[1]) + { + log_error("create_image_2d failed\n"); + return -1; + } + err = clEnqueueWriteImage(queue, accum_streams[1], CL_TRUE, + origin, region, 0, 0, + initial_data, 0, NULL, NULL); + if (err) + { + log_error("clWriteImage failed: %d\n", err); + return -1; + } + + free(initial_data); + } + + // Set up the input data. + { + cl_mem_flags flags; + unsigned char **input_data = (unsigned char **)malloc(sizeof(unsigned char*) * num_input_streams); + MTdata d; + + input_streams = (cl_mem*)malloc(sizeof(cl_mem) * num_input_streams); + flags = (cl_mem_flags)(CL_MEM_READ_WRITE); + + int i; + d = init_genrand( gRandomSeed ); + for ( i = 0; i < num_input_streams; i++) + { + input_data[i] = generate_byte_image(img_width, img_height, 4, d); + input_streams[i] = create_image_2d(context, flags, &img_format, img_width, img_height, 0, NULL, NULL); + if (!input_streams[i]) + { + log_error("create_image_2d failed\n"); + free(input_data); + free(input_streams); + return -1; + } + + size_t origin[3] = {0, 0, 0}, region[3] = {img_width, img_height, 1}; + err = clEnqueueWriteImage(queue, input_streams[i], CL_TRUE, + origin, region, 0, 0, + input_data[i], 0, NULL, NULL); + if (err) + { + log_error("clWriteImage failed: %d\n", err); + free(input_data); + free(input_streams); + return -1; + } + } + free_mtdata(d); d = NULL; + expected_output = generate_expected_byte_image(input_data, num_input_streams, img_width, img_height, 4); + for ( i = 0; i < num_input_streams; i++) + { + free(input_data[i]); + } + free(input_data); + } + + // Set up the kernels. + { + cl_program program[2]; + + err = create_single_kernel_helper(context, &program[0], &kernel[0], 1, &image_to_image_kernel_float_coord_code, "image_to_image_copy"); + if (err) + { + log_error("Failed to create kernel 2: %d\n", err); + return -1; + } + err = create_single_kernel_helper(context, &program[1], &kernel[1], 1, &image_sum_kernel_float_coord_code, "image_sum"); + if (err) + { + log_error("Failed to create kernel 3: %d\n", err); + return -1; + } + + clReleaseProgram(program[0]); + clReleaseProgram(program[1]); + } + + cl_sampler sampler = clCreateSampler(context, CL_FALSE, CL_ADDRESS_CLAMP_TO_EDGE, CL_FILTER_NEAREST, &err); + test_error(err, "clCreateSampler failed"); + + { + size_t threads[3] = {0, 0, 0}; + threads[0] = (size_t)img_width; + threads[1] = (size_t)img_height; + int i; + + { + cl_mem accum_input; + cl_mem accum_output; + + err = clSetKernelArg(kernel[0], 0, sizeof input_streams[0], &input_streams[0]); + err |= clSetKernelArg(kernel[0], 1, sizeof accum_streams[0], &accum_streams[0]); + err |= clSetKernelArg(kernel[0], 2, sizeof sampler, &sampler); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + err = clEnqueueNDRangeKernel( queue, kernel[0], 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + for (i = 1; i < num_input_streams; i++) + { + accum_input = accum_streams[(i-1)%2]; + accum_output = accum_streams[i%2]; + + err = clSetKernelArg(kernel[1], 0, sizeof accum_input, &accum_input); + err |= clSetKernelArg(kernel[1], 1, sizeof input_streams[i], &input_streams[i]); + err |= clSetKernelArg(kernel[1], 2, sizeof accum_output, &accum_output); + err |= clSetKernelArg(kernel[1], 3, sizeof sampler, &sampler); + + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + err = clEnqueueNDRangeKernel( queue, kernel[1], 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + } + + // Copy the last accum into the other one. + accum_input = accum_streams[(i-1)%2]; + accum_output = accum_streams[i%2]; + err = clSetKernelArg(kernel[0], 0, sizeof accum_input, &accum_input); + err |= clSetKernelArg(kernel[0], 1, sizeof accum_output, &accum_output); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + err = clEnqueueNDRangeKernel( queue, kernel[0], 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + size_t origin[3] = {0, 0, 0}, region[3] = {img_width, img_height, 1}; + err = clEnqueueReadImage(queue, accum_output, CL_TRUE, + origin, region, 0, 0, + (void *)output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clReadImage failed\n"); + return -1; + } + err = verify_byte_image(expected_output, output_ptr, img_width, img_height, 4); + if (err) + { + log_error("IMAGE_MULTIPASS test failed.\n"); + } + else + { + log_info("IMAGE_MULTIPASS test passed\n"); + } + } + + } + + + // cleanup + clReleaseSampler(sampler); + clReleaseMemObject(accum_streams[0]); + clReleaseMemObject(accum_streams[1]); + { + int i; + for (i = 0; i < num_input_streams; i++) + { + clReleaseMemObject(input_streams[i]); + } + } + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + free(expected_output); + free(output_ptr); + free(input_streams); + + return err; +} + + + + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_image_param.c b/test_conformance/compatibility/test_conformance/basic/test_image_param.c new file mode 100644 index 00000000..567af7f2 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_image_param.c @@ -0,0 +1,251 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/imageHelpers.h" +#include "../../test_common/harness/conversions.h" + + +static const char *param_kernel[] = { +"__kernel void test_fn(read_only image2d_t srcimg, sampler_t sampler, __global float4 *results )\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" results[ tid_y * get_image_width( srcimg ) + tid_x ] = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y));\n" +"\n" +"}\n" }; + +int validate_results( size_t width, size_t height, cl_image_format &format, char *inputData, cl_float *actualResults ) +{ + for( size_t i = 0; i < width * height; i++ ) + { + cl_float expected[ 4 ], tolerance; + + switch( format.image_channel_data_type ) + { + case CL_UNORM_INT8: + { + cl_uchar *p = (cl_uchar *)inputData; + expected[ 0 ] = p[ 0 ] / 255.f; + expected[ 1 ] = p[ 1 ] / 255.f; + expected[ 2 ] = p[ 2 ] / 255.f; + expected[ 3 ] = p[ 3 ] / 255.f; + tolerance = 1.f / 255.f; + break; + } + case CL_SNORM_INT8: + { + cl_char *p = (cl_char *)inputData; + expected[ 0 ] = fmaxf( p[ 0 ] / 127.f, -1.f ); + expected[ 1 ] = fmaxf( p[ 1 ] / 127.f, -1.f ); + expected[ 2 ] = fmaxf( p[ 2 ] / 127.f, -1.f ); + expected[ 3 ] = fmaxf( p[ 3 ] / 127.f, -1.f ); + tolerance = 1.f / 127.f; + break; + } + case CL_UNSIGNED_INT8: + { + cl_uchar *p = (cl_uchar *)inputData; + expected[ 0 ] = p[ 0 ]; + expected[ 1 ] = p[ 1 ]; + expected[ 2 ] = p[ 2 ]; + expected[ 3 ] = p[ 3 ]; + tolerance = 1.f / 127.f; + break; + } + case CL_SIGNED_INT8: + { + cl_short *p = (cl_short *)inputData; + expected[ 0 ] = p[ 0 ]; + expected[ 1 ] = p[ 1 ]; + expected[ 2 ] = p[ 2 ]; + expected[ 3 ] = p[ 3 ]; + tolerance = 1.f / 127.f; + break; + } + case CL_UNORM_INT16: + { + cl_ushort *p = (cl_ushort *)inputData; + expected[ 0 ] = p[ 0 ] / 65535.f; + expected[ 1 ] = p[ 1 ] / 65535.f; + expected[ 2 ] = p[ 2 ] / 65535.f; + expected[ 3 ] = p[ 3 ] / 65535.f; + tolerance = 1.f / 65535.f; + break; + } + case CL_UNSIGNED_INT32: + { + cl_uint *p = (cl_uint *)inputData; + expected[ 0 ] = p[ 0 ]; + expected[ 1 ] = p[ 1 ]; + expected[ 2 ] = p[ 2 ]; + expected[ 3 ] = p[ 3 ]; + tolerance = 0.0001f; + break; + } + case CL_FLOAT: + { + cl_float *p = (cl_float *)inputData; + expected[ 0 ] = p[ 0 ]; + expected[ 1 ] = p[ 1 ]; + expected[ 2 ] = p[ 2 ]; + expected[ 3 ] = p[ 3 ]; + tolerance = 0.0001f; + break; + } + default: + // Should never get here + break; + } + + if( format.image_channel_order == CL_BGRA ) + { + cl_float tmp = expected[ 0 ]; + expected[ 0 ] = expected[ 2 ]; + expected[ 2 ] = tmp; + } + + // Within an error tolerance, make sure the results match + cl_float error1 = fabsf( expected[ 0 ] - actualResults[ 0 ] ); + cl_float error2 = fabsf( expected[ 1 ] - actualResults[ 1 ] ); + cl_float error3 = fabsf( expected[ 2 ] - actualResults[ 2 ] ); + cl_float error4 = fabsf( expected[ 3 ] - actualResults[ 3 ] ); + + if( error1 > tolerance || error2 > tolerance || error3 > tolerance || error4 > tolerance ) + { + log_error( "ERROR: Sample %d did not validate against expected results for %d x %d %s:%s image\n", (int)i, (int)width, (int)height, + GetChannelOrderName( format.image_channel_order ), GetChannelTypeName( format.image_channel_data_type ) ); + log_error( " Expected: %f %f %f %f\n", (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ] ); + log_error( " Actual: %f %f %f %f\n", (float)actualResults[ 0 ], (float)actualResults[ 1 ], (float)actualResults[ 2 ], (float)actualResults[ 3 ] ); + + // Check real quick a special case error here + cl_float error1 = fabsf( expected[ 3 ] - actualResults[ 0 ] ); + cl_float error2 = fabsf( expected[ 2 ] - actualResults[ 1 ] ); + cl_float error3 = fabsf( expected[ 1 ] - actualResults[ 2 ] ); + cl_float error4 = fabsf( expected[ 0 ] - actualResults[ 3 ] ); + if( error1 <= tolerance && error2 <= tolerance && error3 <= tolerance && error4 <= tolerance ) + { + log_error( "\t(Kernel did not respect change in channel order)\n" ); + } + return -1; + } + + // Increment and go + actualResults += 4; + inputData += get_format_type_size( &format ) * 4; + } + + return 0; +} + +int test_image_param(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + size_t sizes[] = { 64, 100, 128, 250, 512 }; + cl_image_format formats[] = { { CL_RGBA, CL_UNORM_INT8 }, { CL_RGBA, CL_UNORM_INT16 }, { CL_RGBA, CL_FLOAT }, { CL_BGRA, CL_UNORM_INT8 } }; + ExplicitType types[] = { kUChar, kUShort, kFloat, kUChar }; + int error; + size_t i, j, idx; + size_t threads[ 2 ]; + MTdata d; + + const size_t numSizes = sizeof( sizes ) / sizeof( sizes[ 0 ] ); + const size_t numFormats = sizeof( formats ) / sizeof( formats[ 0 ] ); + const size_t numAttempts = numSizes * numFormats; + + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ numAttempts ][ 2 ]; + BufferOwningPtr inputs[ numAttempts ]; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + d = init_genrand( gRandomSeed ); + for( i = 0, idx = 0; i < numSizes; i++ ) + { + for( j = 0; j < numFormats; j++, idx++ ) + { + // For each attempt, we create a pair: an input image, whose parameters keep changing, and an output buffer + // that we can read values from. The output buffer will remain consistent to ensure that any changes we + // witness are due to the image changes + inputs[ idx ].reset(create_random_data( types[ j ], d, sizes[ i ] * sizes[ i ] * 4 )); + + streams[ idx ][ 0 ] = create_image_2d( context, CL_MEM_COPY_HOST_PTR, &formats[ j ], sizes[ i ], sizes[ i ], 0, inputs[ idx ], &error ); + { + char err_str[256]; + sprintf(err_str, "Unable to create input image for format %s order %s" , + GetChannelOrderName( formats[j].image_channel_order ), + GetChannelTypeName( formats[j].image_channel_data_type )); + test_error( error, err_str); + } + + streams[ idx ][ 1 ] = clCreateBuffer( context, CL_MEM_READ_WRITE, sizes[ i ] * sizes[ i ] * 4 * sizeof( cl_float ), NULL, &error ); + test_error( error, "Unable to create output buffer" ); + } + } + free_mtdata(d); d = NULL; + + // Create a single kernel to use for all the tests + error = create_single_kernel_helper( context, &program, &kernel, 1, param_kernel, "test_fn" ); + test_error( error, "Unable to create testing kernel" ); + + // Also create a sampler to use for all the runs + clSamplerWrapper sampler = clCreateSampler(context, CL_FALSE, CL_ADDRESS_CLAMP_TO_EDGE, CL_FILTER_NEAREST, &error ); + test_error( error, "clCreateSampler failed" ); + + // Set up the arguments for each and queue + for( i = 0, idx = 0; i < numSizes; i++ ) + { + for( j = 0; j < numFormats; j++, idx++ ) + { + error = clSetKernelArg( kernel, 0, sizeof( streams[ idx ][ 0 ] ), &streams[ idx ][ 0 ] ); + error |= clSetKernelArg( kernel, 1, sizeof( sampler ), &sampler ); + error |= clSetKernelArg( kernel, 2, sizeof( streams[ idx ][ 1 ] ), &streams[ idx ][ 1 ]); + test_error( error, "Unable to set kernel arguments" ); + + threads[ 0 ] = threads[ 1 ] = (size_t)sizes[ i ]; + + error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "clEnqueueNDRangeKernel failed" ); + } + } + + // Now go through each combo and validate the results + for( i = 0, idx = 0; i < numSizes; i++ ) + { + for( j = 0; j < numFormats; j++, idx++ ) + { + BufferOwningPtr output(malloc(sizeof(cl_float) * sizes[ i ] * sizes[ i ] * 4 )); + + error = clEnqueueReadBuffer( queue, streams[ idx ][ 1 ], CL_TRUE, 0, sizes[ i ] * sizes[ i ] * 4 * sizeof( cl_float ), output, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + error = validate_results( sizes[ i ], sizes[ i ], formats[ j ], inputs[ idx ], output ); + if( error ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/compatibility/test_conformance/basic/test_image_r8.c b/test_conformance/compatibility/test_conformance/basic/test_image_r8.c new file mode 100644 index 00000000..2f9976f0 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_image_r8.c @@ -0,0 +1,176 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +static const char *r_uint8_kernel_code = +"__kernel void test_r_uint8(read_only image2d_t srcimg, __global unsigned char *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(srcimg) + tid_x;\n" +" uint4 color;\n" +"\n" +" color = read_imageui(srcimg, sampler, (int2)(tid_x, tid_y));\n" +" dst[indx] = (unsigned char)(color.x);\n" +"\n" +"}\n"; + + +static unsigned char * +generate_8bit_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * sizeof(unsigned char)); + int i; + + for (i=0; i +#include +#include +#include +#include + +#include "procs.h" + +int test_imagearraycopy_single_format(cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format) +{ + cl_uchar *imgptr, *bufptr; + clMemWrapper image, buffer; + int img_width = 512; + int img_height = 512; + size_t elem_size; + size_t buffer_size; + int i; + cl_int err; + MTdata d; + cl_event copyevent; + + log_info("Testing %s %s\n", GetChannelOrderName(format->image_channel_order), GetChannelTypeName(format->image_channel_data_type)); + + image = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), format, img_width, img_height, 0, NULL, &err); + test_error(err, "create_image_2d failed"); + + err = clGetImageInfo(image, CL_IMAGE_ELEMENT_SIZE, sizeof(size_t), &elem_size, NULL); + test_error(err, "clGetImageInfo failed"); + + buffer_size = sizeof(cl_uchar) * elem_size * img_width * img_height; + + buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), buffer_size, NULL, &err); + test_error(err, "clCreateBuffer failed"); + + d = init_genrand( gRandomSeed ); + imgptr = (cl_uchar*)malloc(buffer_size); + for (i=0; i<(int)buffer_size; i++) { + imgptr[i] = (cl_uchar)genrand_int32(d); + } + free_mtdata(d); d = NULL; + + size_t origin[3]={0,0,0}, region[3]={img_width,img_height,1}; + err = clEnqueueWriteImage( queue, image, CL_TRUE, origin, region, 0, 0, imgptr, 0, NULL, NULL ); + test_error(err, "clEnqueueWriteBuffer failed"); + + err = clEnqueueCopyImageToBuffer( queue, image, buffer, origin, region, 0, 0, NULL, ©event ); + test_error(err, "clEnqueueCopyImageToBuffer failed"); + + bufptr = (cl_uchar*)malloc(buffer_size); + + err = clEnqueueReadBuffer( queue, buffer, CL_TRUE, 0, buffer_size, bufptr, 1, ©event, NULL); + test_error(err, "clEnqueueReadBuffer failed"); + + err = clReleaseEvent(copyevent); + test_error(err, "clReleaseEvent failed"); + + if (memcmp(imgptr, bufptr, buffer_size) != 0) { + log_error( "ERROR: Results did not validate!\n" ); + unsigned char * inchar = (unsigned char*)imgptr; + unsigned char * outchar = (unsigned char*)bufptr; + int failuresPrinted = 0; + int i; + for (i=0; i< (int)buffer_size; i+=(int)elem_size) { + int failed = 0; + int j; + for (j=0; j<(int)elem_size; j++) + if (inchar[i+j] != outchar[i+j]) + failed = 1; + char values[4096]; + values[0] = 0; + if (failed) { + sprintf(values + strlen(values), "%d(0x%x) -> actual [", i, i); + int j; + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", inchar[i+j]); + sprintf(values + strlen(values), "] != expected ["); + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", outchar[i+j]); + sprintf(values + strlen(values), "]"); + log_error("%s\n", values); + failuresPrinted++; + } + if (failuresPrinted > 5) { + log_error("Not printing further failures...\n"); + break; + } + } + err = -1; + } + + free(imgptr); + free(bufptr); + + if (err) + log_error("IMAGE to ARRAY copy test failed for image_channel_order=0x%lx and image_channel_data_type=0x%lx\n", + (unsigned long)format->image_channel_order, (unsigned long)format->image_channel_data_type); + + return err; +} + +int test_imagearraycopy(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int err; + cl_image_format *formats; + cl_uint num_formats; + cl_uint i; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE2D, 0, NULL, &num_formats); + test_error(err, "clGetSupportedImageFormats failed"); + + formats = (cl_image_format *)malloc(num_formats * sizeof(cl_image_format)); + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE2D, num_formats, formats, NULL); + test_error(err, "clGetSupportedImageFormats failed"); + + for (i = 0; i < num_formats; i++) { + err |= test_imagearraycopy_single_format(device, context, queue, &formats[i]); + } + + free(formats); + if (err) + log_error("IMAGE to ARRAY copy test failed\n"); + else + log_info("IMAGE to ARRAY copy test passed\n"); + + return err; +} diff --git a/test_conformance/compatibility/test_conformance/basic/test_imagearraycopy3d.c b/test_conformance/compatibility/test_conformance/basic/test_imagearraycopy3d.c new file mode 100644 index 00000000..d0fc05a3 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_imagearraycopy3d.c @@ -0,0 +1,144 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +int test_imagearraycopy3d_single_format(cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format) +{ + cl_uchar *imgptr, *bufptr; + clMemWrapper image, buffer; + int img_width = 128; + int img_height = 128; + int img_depth = 32; + size_t elem_size; + size_t buffer_size; + int i; + cl_int err; + MTdata d; + cl_event copyevent; + + log_info("Testing %s %s\n", GetChannelOrderName(format->image_channel_order), GetChannelTypeName(format->image_channel_data_type)); + + image = create_image_3d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), format, img_width, img_height, img_depth, 0, 0, NULL, &err); + test_error(err, "create_image_3d failed"); + + err = clGetImageInfo(image, CL_IMAGE_ELEMENT_SIZE, sizeof(size_t), &elem_size, NULL); + test_error(err, "clGetImageInfo failed"); + + buffer_size = sizeof(cl_uchar) * elem_size * img_width * img_height * img_depth; + + buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), buffer_size, NULL, &err); + test_error(err, "clCreateBuffer failed"); + + imgptr = (cl_uchar*)malloc(buffer_size); + + d = init_genrand( gRandomSeed ); + imgptr = (cl_uchar*)malloc(buffer_size); + for (i=0; i<(int)buffer_size; i++) { + imgptr[i] = (cl_uchar)genrand_int32(d); + } + free_mtdata(d); d = NULL; + + size_t origin[3]={0,0,0}, region[3]={img_width,img_height,img_depth}; + err = clEnqueueWriteImage( queue, image, CL_TRUE, origin, region, 0, 0, imgptr, 0, NULL, NULL ); + test_error(err, "clEnqueueWriteBuffer failed"); + + err = clEnqueueCopyImageToBuffer( queue, image, buffer, origin, region, 0, 0, NULL, ©event ); + test_error(err, "clEnqueueCopyImageToBuffer failed"); + + bufptr = (cl_uchar*)malloc(buffer_size); + + err = clEnqueueReadBuffer( queue, buffer, CL_TRUE, 0, buffer_size, bufptr, 1, ©event, NULL); + test_error(err, "clEnqueueReadBuffer failed"); + + if (memcmp(imgptr, bufptr, buffer_size) != 0) { + log_error( "ERROR: Results did not validate!\n" ); + unsigned char * inchar = (unsigned char*)imgptr; + unsigned char * outchar = (unsigned char*)bufptr; + int failuresPrinted = 0; + int i; + for (i=0; i< (int)buffer_size; i+=(int)elem_size) { + int failed = 0; + int j; + for (j=0; j<(int)elem_size; j++) + if (inchar[i+j] != outchar[i+j]) + failed = 1; + char values[4096]; + values[0] = 0; + if (failed) { + sprintf(values + strlen(values), "%d(0x%x) -> actual [", i, i); + int j; + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", inchar[i+j]); + sprintf(values + strlen(values), "] != expected ["); + for (j=0; j<(int)elem_size; j++) + sprintf(values + strlen( values), "0x%02x ", outchar[i+j]); + sprintf(values + strlen(values), "]"); + log_error("%s\n", values); + failuresPrinted++; + } + if (failuresPrinted > 5) { + log_error("Not printing further failures...\n"); + break; + } + } + err = -1; + } + + free(imgptr); + free(bufptr); + + if (err) + log_error("IMAGE3D to ARRAY copy test failed for image_channel_order=0x%lx and image_channel_data_type=0x%lx\n", + (unsigned long)format->image_channel_order, (unsigned long)format->image_channel_data_type); + + return err; +} + +int test_imagearraycopy3d(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int err; + cl_image_format *formats; + cl_uint num_formats; + cl_uint i; + + PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( device ) + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE3D, 0, NULL, &num_formats); + test_error(err, "clGetSupportedImageFormats failed"); + + formats = (cl_image_format *)malloc(num_formats * sizeof(cl_image_format)); + + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE3D, num_formats, formats, NULL); + test_error(err, "clGetSupportedImageFormats failed"); + + for (i = 0; i < num_formats; i++) { + err |= test_imagearraycopy3d_single_format(device, context, queue, &formats[i]); + } + + if (err) + log_error("IMAGE3D to ARRAY copy test failed\n"); + else + log_info("IMAGE3D to ARRAY copy test passed\n"); + + return err; +} diff --git a/test_conformance/compatibility/test_conformance/basic/test_imagecopy.c b/test_conformance/compatibility/test_conformance/basic/test_imagecopy.c new file mode 100644 index 00000000..d01ff5ff --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_imagecopy.c @@ -0,0 +1,234 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +static unsigned char * +generate_rgba8_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +static unsigned char * +generate_uint8_image(unsigned num_elements, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(num_elements); + unsigned i; + + for (i=0; i +#include +#include +#include +#include + + +#include "procs.h" + +static const char *image_dim_kernel_code = +"\n" +"__kernel void test_image_dim(read_only image2d_t srcimg, write_only image2d_t dstimg, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y));\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + + +static unsigned char * +generate_8888_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i (cl_ulong)SIZE_MAX) { + max_mem_size = (cl_ulong)SIZE_MAX; + } + + cl_sampler sampler = clCreateSampler(context, CL_FALSE, CL_ADDRESS_CLAMP_TO_EDGE, CL_FILTER_NEAREST, &err); + test_error(err, "clCreateSampler failed"); + + max_img_width = (int)max_image2d_width; + max_img_height = (int)max_image2d_height; + + // determine max image dim we can allocate - assume RGBA image, 4 bytes per pixel, + // and we want to consume 1/4 of global memory (this is the minimum required to be + // supported by the spec) + max_mem_size /= 4; // use 1/4 + max_mem_size /= 4; // 4 bytes per pixel + max_img_dim = (int)sqrt((double)max_mem_size); + // convert to a power of 2 + { + unsigned int n = (unsigned int)max_img_dim; + unsigned int m = 0x80000000; + + // round-down to the nearest power of 2 + while (m > n) + m >>= 1; + + max_img_dim = (int)m; + } + + if (max_img_width > max_img_dim) + max_img_width = max_img_dim; + if (max_img_height > max_img_dim) + max_img_height = max_img_dim; + + log_info("Adjusted maximum image size to test is %d x %d, which is a max mem size of %gMB.\n", + max_img_width, max_img_height, (max_img_width*max_img_height*4)/(1024.0*1024.0)); + + d = init_genrand( gRandomSeed ); + input_ptr = generate_8888_image(max_img_width, max_img_height, d); + output_ptr = (unsigned char*)malloc(sizeof(unsigned char) * 4 * max_img_width * max_img_height); + + // test power of 2 width, height starting at 1 to 4K + for (i=1,i2=0; i<=max_img_height; i<<=1,i2++) + { + img_height = (1 << i2); + for (j=1,j2=0; j<=max_img_width; j<<=1,j2++) + { + img_width = (1 << j2); + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + streams[0] = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[0]) + { + log_error("create_image_2d failed. width = %d, height = %d\n", img_width, img_height); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + streams[1] = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[1]) + { + log_error("create_image_2d failed. width = %d, height = %d\n", img_width, img_height); + clReleaseMemObject(streams[0]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + + size_t origin[3] = {0,0,0}; + size_t region[3] = {img_width, img_height, 1}; + err = clEnqueueWriteImage(queue, streams[0], CL_FALSE, origin, region, 0, 0, input_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clWriteImage failed\n"); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + + err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]); + err |= clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]); + err |= clSetKernelArg(kernel, 2, sizeof sampler, &sampler); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + + threads[0] = (size_t)img_width; + threads[1] = (size_t)img_height; + log_info("Testing image dimensions %d x %d with local threads NULL.\n", img_width, img_height); + err = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + log_error("Image Dimension test failed. image width = %d, image height = %d, local NULL\n", + img_width, img_height); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + err = clEnqueueReadImage(queue, streams[1], CL_TRUE, origin, region, 0, 0, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clReadImage failed\n"); + log_error("Image Dimension test failed. image width = %d, image height = %d, local NULL\n", + img_width, img_height); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + err = verify_8888_image(input_ptr, output_ptr, img_width, img_height); + if (err) + { + total_errors++; + log_error("Image Dimension test failed. image width = %d, image height = %d\n", img_width, img_height); + } + + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + } + } + + // cleanup + free(input_ptr); + free(output_ptr); + free_mtdata(d); + clReleaseSampler(sampler); + clReleaseKernel(kernel); + clReleaseProgram(program); + + return total_errors; +} + + + +int +test_imagedim_non_pow2(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[2]; + cl_image_format img_format; + unsigned char *input_ptr, *output_ptr; + cl_program program; + cl_kernel kernel; + size_t threads[2], local_threads[2]; + cl_ulong max_mem_size; + int img_width, max_img_width; + int img_height, max_img_height; + int max_img_dim; + int i, j, i2, j2, err=0; + size_t max_image2d_width, max_image2d_height; + int total_errors = 0; + size_t max_local_workgroup_size[3]; + MTdata d; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + err = create_single_kernel_helper( context, &program, &kernel, 1, &image_dim_kernel_code, "test_image_dim" ); + if (err) + { + log_error("create_program_and_kernel_with_sources failed\n"); + return -1; + } + + size_t work_group_size = 0; + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(work_group_size), &work_group_size, NULL); + test_error(err, "clGetKerenlWorkgroupInfo failed for CL_KERNEL_WORK_GROUP_SIZE"); + + err = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(max_local_workgroup_size), max_local_workgroup_size, NULL); + test_error(err, "clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_SIZES"); + + err = clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE,sizeof(max_mem_size), &max_mem_size, NULL); + if (err) + { + log_error("clGetDeviceInfo for CL_DEVICE_GLOBAL_MEM_SIZE failed (%d)\n", err); + return -1; + } + err = clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(max_image2d_width), &max_image2d_width, NULL); + if (err) + { + log_error("clGetDeviceInfo for CL_DEVICE_IMAGE2D_MAX_WIDTH failed (%d)\n", err); + return -1; + } + err = clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(max_image2d_width), &max_image2d_height, NULL); + if (err) + { + log_error("clGetDeviceInfo for CL_DEVICE_IMAGE2D_MAX_HEIGHT failed (%d)\n", err); + return -1; + } + log_info("Device reported max image sizes of %lu x %lu, and max mem size of %gMB.\n", + max_image2d_width, max_image2d_height, max_mem_size/(1024.0*1024.0)); + + cl_sampler sampler = clCreateSampler(context, CL_FALSE, CL_ADDRESS_CLAMP_TO_EDGE, CL_FILTER_NEAREST, &err); + test_error(err, "clCreateSampler failed"); + + max_img_width = (int)max_image2d_width; + max_img_height = (int)max_image2d_height; + + if (max_mem_size > (cl_ulong)SIZE_MAX) { + max_mem_size = (cl_ulong)SIZE_MAX; + } + + // determine max image dim we can allocate - assume RGBA image, 4 bytes per pixel, + // and we want to consume 1/4 of global memory (this is the minimum required to be + // supported by the spec) + max_mem_size /= 4; // use 1/4 + max_mem_size /= 4; // 4 bytes per pixel + max_img_dim = (int)sqrt((double)max_mem_size); + // convert to a power of 2 + { + unsigned int n = (unsigned int)max_img_dim; + unsigned int m = 0x80000000; + + // round-down to the nearest power of 2 + while (m > n) + m >>= 1; + + max_img_dim = (int)m; + } + + if (max_img_width > max_img_dim) + max_img_width = max_img_dim; + if (max_img_height > max_img_dim) + max_img_height = max_img_dim; + + log_info("Adjusted maximum image size to test is %d x %d, which is a max mem size of %gMB.\n", + max_img_width, max_img_height, (max_img_width*max_img_height*4)/(1024.0*1024.0)); + + d = init_genrand( gRandomSeed ); + input_ptr = generate_8888_image(max_img_width, max_img_height, d); + output_ptr = (unsigned char*)malloc(sizeof(unsigned char) * 4 * max_img_width * max_img_height); + + int plus_minus; + for (plus_minus=0; plus_minus < 3; plus_minus++) + { + + // test power of 2 width, height starting at 1 to 4K + for (i=2,i2=1; i<=max_img_height; i<<=1,i2++) + { + img_height = (1 << i2); + for (j=2,j2=1; j<=max_img_width; j<<=1,j2++) + { + img_width = (1 << j2); + + int effective_img_height = img_height; + int effective_img_width = img_width; + + local_threads[0] = 1; + local_threads[1] = 1; + + switch (plus_minus) { + case 0: + effective_img_height--; + local_threads[0] = work_group_size > max_local_workgroup_size[0] ? max_local_workgroup_size[0] : work_group_size; + while (img_width%local_threads[0] != 0) + local_threads[0]--; + break; + case 1: + effective_img_width--; + local_threads[1] = work_group_size > max_local_workgroup_size[1] ? max_local_workgroup_size[1] : work_group_size; + while (img_height%local_threads[1] != 0) + local_threads[1]--; + break; + case 2: + effective_img_width--; + effective_img_height--; + break; + default: + break; + } + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + streams[0] = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), &img_format, effective_img_width, effective_img_height, 0, NULL, NULL); + if (!streams[0]) + { + log_error("create_image_2d failed. width = %d, height = %d\n", effective_img_width, effective_img_height); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + streams[1] = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), &img_format, effective_img_width, effective_img_height, 0, NULL, NULL); + if (!streams[1]) + { + log_error("create_image_2d failed. width = %d, height = %d\n", effective_img_width, effective_img_height); + clReleaseMemObject(streams[0]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + + size_t origin[3] = {0,0,0}; + size_t region[3] = {effective_img_width, effective_img_height, 1}; + err = clEnqueueWriteImage(queue, streams[0], CL_FALSE, origin, region, 0, 0, input_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clWriteImage failed\n"); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + + err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]); + err |= clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]); + err |= clSetKernelArg(kernel, 2, sizeof sampler, &sampler); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + + threads[0] = (size_t)effective_img_width; + threads[1] = (size_t)effective_img_height; + log_info("Testing image dimensions %d x %d with local threads %d x %d.\n", + effective_img_width, effective_img_height, (int)local_threads[0], (int)local_threads[1]); + err = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, local_threads, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + log_error("Image Dimension test failed. image width = %d, image height = %d, local %d x %d\n", + effective_img_width, effective_img_height, (int)local_threads[0], (int)local_threads[1]); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + err = clEnqueueReadImage(queue, streams[1], CL_TRUE, origin, region, 0, 0, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clReadImage failed\n"); + log_error("Image Dimension test failed. image width = %d, image height = %d, local %d x %d\n", + effective_img_width, effective_img_height, (int)local_threads[0], (int)local_threads[1]); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + free(input_ptr); + free(output_ptr); + free_mtdata(d); + return -1; + } + err = verify_8888_image(input_ptr, output_ptr, effective_img_width, effective_img_height); + if (err) + { + total_errors++; + log_error("Image Dimension test failed. image width = %d, image height = %d\n", effective_img_width, effective_img_height); + } + + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + } + } + + } + + // cleanup + free(input_ptr); + free(output_ptr); + free_mtdata(d); + clReleaseSampler(sampler); + clReleaseKernel(kernel); + clReleaseProgram(program); + + return total_errors; +} + + + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_imagenpot.c b/test_conformance/compatibility/test_conformance/basic/test_imagenpot.c new file mode 100644 index 00000000..acea61dc --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_imagenpot.c @@ -0,0 +1,220 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +static const char *rgba8888_kernel_code = +"\n" +"__kernel void test_rgba8888(read_only image2d_t srcimg, write_only image2d_t dstimg, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 color;\n" +"\n" +" if ( (tid_x >= get_image_width(dstimg)) || (tid_y >= get_image_height(dstimg)) )\n" +" return;\n" +" color = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y));\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + + +static unsigned char * +generate_8888_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i max_local_workgroup_size[0]) + local_workgroup_size = max_local_workgroup_size[0]; + + global_threads[0] = ((img_width + local_workgroup_size - 1) / local_workgroup_size) * local_workgroup_size; + global_threads[1] = img_height; + local_threads[0] = local_workgroup_size; + local_threads[1] = 1; + err = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, global_threads, local_threads, 0, NULL, NULL ); + + if (err != CL_SUCCESS) + { + log_error("%s clEnqueueNDRangeKernel failed\n", __FUNCTION__); + free_mtdata(d); + return -1; + } + err = clEnqueueReadImage(queue, streams[1], CL_TRUE, + origin, region, 0, 0, + (void *)output_ptr, + 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueReadBuffer failed\n"); + return -1; + } + + err = verify_rgba8888_image(input_ptr, output_ptr, img_width, img_height); + + // cleanup + clReleaseSampler(sampler); + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + free(input_ptr); + free(output_ptr); + + if (err) + break; + } + + free_mtdata(d); + + return err; +} + + + + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_imagerandomcopy.c b/test_conformance/compatibility/test_conformance/basic/test_imagerandomcopy.c new file mode 100644 index 00000000..1b95f6a8 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_imagerandomcopy.c @@ -0,0 +1,269 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +static unsigned char * +generate_rgba8_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +static unsigned char * +generate_rgba8_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +static unsigned char * +generate_rgba8_image(int w, int h, int d, MTdata mtData) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * d *4); + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +const char *int2float_kernel_code = +"__kernel void test_int2float(__global int *src, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (float)src[tid];\n" +"\n" +"}\n"; + + +int +verify_int2float(cl_int *inptr, cl_float *outptr, int n) +{ + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +const char *int_add_kernel_code = +"__kernel void test_int_add(__global int *srcA, __global int *srcB, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *int_sub_kernel_code = +"__kernel void test_int_sub(__global int *srcA, __global int *srcB, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *int_mul_kernel_code = +"__kernel void test_int_mul(__global int *srcA, __global int *srcB, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + +const char *int_mad_kernel_code = +"__kernel void test_int_mad(__global int *srcA, __global int *srcB, __global int *srcC, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid] + srcC[tid];\n" +"}\n"; + +static const float MAX_ERR = 1e-5f; + +int +verify_int_add(int *inptrA, int *inptrB, int *outptr, int n) +{ + int r; + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +const char *int_add2_kernel_code = +"__kernel void test_int_add2(__global int2 *srcA, __global int2 *srcB, __global int2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *int_sub2_kernel_code = +"__kernel void test_int_sub2(__global int2 *srcA, __global int2 *srcB, __global int2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *int_mul2_kernel_code = +"__kernel void test_int_mul2(__global int2 *srcA, __global int2 *srcB, __global int2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + +const char *int_mad2_kernel_code = +"__kernel void test_int_mad2(__global int2 *srcA, __global int2 *srcB, __global int2 *srcC, __global int2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid] + srcC[tid];\n" +"}\n"; + +int +verify_int_add2(int *inptrA, int *inptrB, int *outptr, int n) +{ + int r; + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +const char *int_add4_kernel_code = +"__kernel void test_int_add4(__global int4 *srcA, __global int4 *srcB, __global int4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *int_sub4_kernel_code = +"__kernel void test_int_sub4(__global int4 *srcA, __global int4 *srcB, __global int4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *int_mul4_kernel_code = +"__kernel void test_int_mul4(__global int4 *srcA, __global int4 *srcB, __global int4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + +const char *int_mad4_kernel_code = +"__kernel void test_int_mad4(__global int4 *srcA, __global int4 *srcB, __global int4 *srcC, __global int4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid] + srcC[tid];\n" +"}\n"; + +int +verify_int_add4(int *inptrA, int *inptrB, int *outptr, int n) +{ + int r; + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +const char *long_add_kernel_code = +"__kernel void test_long_add(__global long *srcA, __global long *srcB, __global long *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *long_sub_kernel_code = +"__kernel void test_long_sub(__global long *srcA, __global long *srcB, __global long *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *long_mul_kernel_code = +"__kernel void test_long_mul(__global long *srcA, __global long *srcB, __global long *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + +const char *long_mad_kernel_code = +"__kernel void test_long_mad(__global long *srcA, __global long *srcB, __global long *srcC, __global long *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid] + srcC[tid];\n" +"}\n"; + +static const float MAX_ERR = 1e-5f; + +int +verify_long_add(cl_long *inptrA, cl_long *inptrB, cl_long *outptr, int n) +{ + cl_long r; + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +const char *long_add2_kernel_code = +"__kernel void test_long_add2(__global long2 *srcA, __global long2 *srcB, __global long2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *long_sub2_kernel_code = +"__kernel void test_long_sub2(__global long2 *srcA, __global long2 *srcB, __global long2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *long_mul2_kernel_code = +"__kernel void test_long_mul2(__global long2 *srcA, __global long2 *srcB, __global long2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + +const char *long_mad2_kernel_code = +"__kernel void test_long_mad2(__global long2 *srcA, __global long2 *srcB, __global long2 *srcC, __global long2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid] + srcC[tid];\n" +"}\n"; + +int +verify_long_add2(cl_long *inptrA, cl_long *inptrB, cl_long *outptr, int n) +{ + cl_long r; + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +const char *long_add4_kernel_code = +"__kernel void test_long_add4(__global long4 *srcA, __global long4 *srcB, __global long4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] + srcB[tid];\n" +"}\n"; + +const char *long_sub4_kernel_code = +"__kernel void test_long_sub4(__global long4 *srcA, __global long4 *srcB, __global long4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] - srcB[tid];\n" +"}\n"; + +const char *long_mul4_kernel_code = +"__kernel void test_long_mul4(__global long4 *srcA, __global long4 *srcB, __global long4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid];\n" +"}\n"; + +const char *long_mad4_kernel_code = +"__kernel void test_long_mad4(__global long4 *srcA, __global long4 *srcB, __global long4 *srcC, __global long4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] * srcB[tid] + srcC[tid];\n" +"}\n"; + +int +verify_long_add4(cl_long *inptrA, cl_long *inptrB, cl_long *outptr, int n) +{ + cl_long r; + int i; + + for (i=0; i 10) + continue; + if (errors == 10) { + log_error("Suppressing further results...\n"); + continue; + } + log_error("Results do not match: output[%d]=%d != expected[%d]=%d\n", i, output[i], i, expected[i]); + errors++; + pass = 0; + } + } + if (pass) log_info("Passed kernel calling kernel...\n"); + + + + // Test kernel calling a function + log_info("Testing kernel calling function...\n"); + // Reset the inputs + for (int i=0; i 10) + continue; + if (errors > 10) { + log_error("Suppressing further results...\n"); + continue; + } + log_error("Results do not match: output[%d]=%d != expected[%d]=%d\n", i, output[i], i, expected[i]); + errors++; + pass = 0; + } + } + if (pass) log_info("Passed kernel calling function...\n"); + + + // Test calling the kernel we called from another kernel + log_info("Testing calling the kernel we called from another kernel before...\n"); + // Reset the inputs + for (int i=0; i 10) + continue; + if (errors > 10) { + log_error("Suppressing further results...\n"); + continue; + } + log_error("Results do not match: output[%d]=%d != expected[%d]=%d\n", i, output[i], i, expected[i]); + errors++; + pass = 0; + } + } + if (pass) log_info("Passed calling the kernel we called from another kernel before...\n"); + + free( input ); + free( output ); + free( expected ); + + return errors; +} + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_kernel_memory_alignment.cpp b/test_conformance/compatibility/test_conformance/basic/test_kernel_memory_alignment.cpp new file mode 100644 index 00000000..1352e46a --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_kernel_memory_alignment.cpp @@ -0,0 +1,572 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _WIN32 +#include +#endif + +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/errorHelpers.h" + +// For global, local, and constant +const char *parameter_kernel_long = +"%s\n" // optional pragma +"kernel void test(global ulong *results, %s %s *mem0, %s %s2 *mem2, %s %s3 *mem3, %s %s4 *mem4, %s %s8 *mem8, %s %s16 *mem16)\n" +"{\n" +" results[0] = (ulong)&mem0[0];\n" +" results[1] = (ulong)&mem2[0];\n" +" results[2] = (ulong)&mem3[0];\n" +" results[3] = (ulong)&mem4[0];\n" +" results[4] = (ulong)&mem8[0];\n" +" results[5] = (ulong)&mem16[0];\n" +"}\n"; + +// For private and local +const char *local_kernel_long = +"%s\n" // optional pragma +"kernel void test(global ulong *results)\n" +"{\n" +" %s %s mem0[3];\n" +" %s %s2 mem2[3];\n" +" %s %s3 mem3[3];\n" +" %s %s4 mem4[3];\n" +" %s %s8 mem8[3];\n" +" %s %s16 mem16[3];\n" +" results[0] = (ulong)&mem0[0];\n" +" results[1] = (ulong)&mem2[0];\n" +" results[2] = (ulong)&mem3[0];\n" +" results[3] = (ulong)&mem4[0];\n" +" results[4] = (ulong)&mem8[0];\n" +" results[5] = (ulong)&mem16[0];\n" +"}\n"; + +// For constant +const char *constant_kernel_long = +"%s\n" // optional pragma +" constant %s mem0[3] = {0};\n" +" constant %s2 mem2[3] = {(%s2)(0)};\n" +" constant %s3 mem3[3] = {(%s3)(0)};\n" +" constant %s4 mem4[3] = {(%s4)(0)};\n" +" constant %s8 mem8[3] = {(%s8)(0)};\n" +" constant %s16 mem16[3] = {(%s16)(0)};\n" +"\n" +"kernel void test(global ulong *results)\n" +"{\n" +" results[0] = (ulong)&mem0;\n" +" results[1] = (ulong)&mem2;\n" +" results[2] = (ulong)&mem3;\n" +" results[3] = (ulong)&mem4;\n" +" results[4] = (ulong)&mem8;\n" +" results[5] = (ulong)&mem16;\n" +"}\n"; + + +// For global, local, and constant +const char *parameter_kernel_no_long = +"%s\n" // optional pragma +"kernel void test(global uint *results, %s %s *mem0, %s %s2 *mem2, %s %s3 *mem3, %s %s4 *mem4, %s %s8 *mem8, %s %s16 *mem16)\n" +"{\n" +" results[0] = (uint)&mem0[0];\n" +" results[1] = (uint)&mem2[0];\n" +" results[2] = (uint)&mem3[0];\n" +" results[3] = (uint)&mem4[0];\n" +" results[4] = (uint)&mem8[0];\n" +" results[5] = (uint)&mem16[0];\n" +"}\n"; + +// For private and local +const char *local_kernel_no_long = +"%s\n" // optional pragma +"kernel void test(global uint *results)\n" +"{\n" +" %s %s mem0[3];\n" +" %s %s2 mem2[3];\n" +" %s %s3 mem3[3];\n" +" %s %s4 mem4[3];\n" +" %s %s8 mem8[3];\n" +" %s %s16 mem16[3];\n" +" results[0] = (uint)&mem0[0];\n" +" results[1] = (uint)&mem2[0];\n" +" results[2] = (uint)&mem3[0];\n" +" results[3] = (uint)&mem4[0];\n" +" results[4] = (uint)&mem8[0];\n" +" results[5] = (uint)&mem16[0];\n" +"}\n"; + +// For constant +const char *constant_kernel_no_long = +"%s\n" // optional pragma +" constant %s mem0[3] = {0};\n" +" constant %s2 mem2[3] = {(%s2)(0)};\n" +" constant %s3 mem3[3] = {(%s3)(0)};\n" +" constant %s4 mem4[3] = {(%s4)(0)};\n" +" constant %s8 mem8[3] = {(%s8)(0)};\n" +" constant %s16 mem16[3] = {(%s16)(0)};\n" +"\n" +"kernel void test(global uint *results)\n" +"{\n" +" results[0] = (uint)&mem0;\n" +" results[1] = (uint)&mem2;\n" +" results[2] = (uint)&mem3;\n" +" results[3] = (uint)&mem4;\n" +" results[4] = (uint)&mem8;\n" +" results[5] = (uint)&mem16;\n" +"}\n"; + +enum AddressSpaces +{ + kGlobal = 0, + kLocal, + kConstant, + kPrivate +}; + +typedef enum AddressSpaces AddressSpaces; + +#define DEBUG 0 + +const char * get_explicit_address_name( AddressSpaces address ) +{ + /* Quick method to avoid branching: make sure the following array matches the Enum order */ + static const char *sExplicitAddressNames[] = { "global", "local", "constant", "private"}; + + return sExplicitAddressNames[ address ]; +} + + +int test_kernel_memory_alignment(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems, AddressSpaces address ) +{ + const char *constant_kernel; + const char *parameter_kernel; + const char *local_kernel; + + if ( gHasLong ) + { + constant_kernel = constant_kernel_long; + parameter_kernel = parameter_kernel_long; + local_kernel = local_kernel_long; + } + else + { + constant_kernel = constant_kernel_no_long; + parameter_kernel = parameter_kernel_no_long; + local_kernel = local_kernel_no_long; + } + + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble }; + char *kernel_code = (char*)malloc(4096); + cl_kernel kernel; + cl_program program; + int error; + int total_errors = 0; + cl_mem results; + cl_ulong *results_data; + cl_mem mem0, mem2, mem3, mem4, mem8, mem16; + + results_data = (cl_ulong*)malloc(sizeof(cl_ulong)*6); + results = clCreateBuffer(context, 0, sizeof(cl_ulong)*6, NULL, &error); + test_error(error, "clCreateBuffer failed"); + + mem0 = clCreateBuffer(context, 0, sizeof(cl_long), NULL, &error); + test_error(error, "clCreateBuffer failed"); + mem2 = clCreateBuffer(context, 0, sizeof(cl_long)*2, NULL, &error); + test_error(error, "clCreateBuffer failed"); + mem3 = clCreateBuffer(context, 0, sizeof(cl_long)*4, NULL, &error); + test_error(error, "clCreateBuffer failed"); + mem4 = clCreateBuffer(context, 0, sizeof(cl_long)*4, NULL, &error); + test_error(error, "clCreateBuffer failed"); + mem8 = clCreateBuffer(context, 0, sizeof(cl_long)*8, NULL, &error); + test_error(error, "clCreateBuffer failed"); + mem16 = clCreateBuffer(context, 0, sizeof(cl_long)*16, NULL, &error); + test_error(error, "clCreateBuffer failed"); + + + // For each type + + // Calculate alignment mask for each size + + // For global, local, constant, private + + // If global, local or constant -- do parameter_kernel + // If private or local -- do local_kernel + // If constant -- do constant kernel + + int numConstantArgs; + clGetDeviceInfo(device, CL_DEVICE_MAX_CONSTANT_ARGS, sizeof(numConstantArgs), &numConstantArgs, NULL); + + int typeIndex; + for (typeIndex = 0; typeIndex < 10; typeIndex++) { + // Skip double tests if we don't support doubles + if (vecType[typeIndex] == kDouble && !is_extension_available(device, "cl_khr_fp64")) { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + continue; + } + + if (( vecType[ typeIndex ] == kLong || vecType[ typeIndex ] == kULong ) && !gHasLong ) + continue; + + log_info("Testing %s...\n", get_explicit_type_name(vecType[typeIndex])); + + // Determine the expected alignment masks. + // E.g., if it is supposed to be 4 byte aligned, we should get 4-1=3 = ... 000011 + // We can then and the returned address with that and we should have 0. + cl_ulong alignments[6]; + alignments[0] = get_explicit_type_size(vecType[typeIndex])-1; + alignments[1] = (get_explicit_type_size(vecType[typeIndex])<<1)-1; + alignments[2] = (get_explicit_type_size(vecType[typeIndex])<<2)-1; + alignments[3] = (get_explicit_type_size(vecType[typeIndex])<<2)-1; + alignments[4] = (get_explicit_type_size(vecType[typeIndex])<<3)-1; + alignments[5] = (get_explicit_type_size(vecType[typeIndex])<<4)-1; + + // Parameter kernel + if (address == kGlobal || address == kLocal || address == kConstant) { + log_info("\tTesting parameter kernel...\n"); + + if ( (gIsEmbedded) && (address == kConstant) && (numConstantArgs < 6)) { + sprintf(kernel_code, parameter_kernel, + vecType[typeIndex] == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]) + ); + } + else { + sprintf(kernel_code, parameter_kernel, + vecType[typeIndex] == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]) + ); + } + //printf("Kernel is: \n%s\n", kernel_code); + + // Create the kernel + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&kernel_code, "test"); + test_error(error, "create_single_kernel_helper failed"); + + // Initialize the results + memset(results_data, 0, sizeof(cl_long)*5); + error = clEnqueueWriteBuffer(queue, results, CL_TRUE, 0, sizeof(cl_long)*6, results_data, 0, NULL, NULL); + test_error(error, "clEnqueueWriteBuffer failed"); + + // Set the arguments + error = clSetKernelArg(kernel, 0, sizeof(results), &results); + test_error(error, "clSetKernelArg failed"); + if (address != kLocal) { + error = clSetKernelArg(kernel, 1, sizeof(mem0), &mem0); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 2, sizeof(mem2), &mem2); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 3, sizeof(mem3), &mem3); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 4, sizeof(mem4), &mem4); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 5, sizeof(mem8), &mem8); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 6, sizeof(mem16), &mem16); + test_error(error, "clSetKernelArg failed"); + } else { + error = clSetKernelArg(kernel, 1, get_explicit_type_size(vecType[typeIndex]), NULL); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 2, get_explicit_type_size(vecType[typeIndex])*2, NULL); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 3, get_explicit_type_size(vecType[typeIndex])*4, NULL); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 4, get_explicit_type_size(vecType[typeIndex])*4, NULL); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 5, get_explicit_type_size(vecType[typeIndex])*8, NULL); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 6, get_explicit_type_size(vecType[typeIndex])*16, NULL); + test_error(error, "clSetKernelArg failed"); + } + + // Enqueue the kernel + size_t global_size = 1; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, NULL, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + // Read back the results + error = clEnqueueReadBuffer(queue, results, CL_TRUE, 0, sizeof(cl_ulong)*6, results_data, 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + // Verify the results + if (gHasLong) { + for (int i = 0; i < 6; i++) { + if ((results_data[i] & alignments[i]) != 0) { + total_errors++; + log_error("\tVector size %d failed: 0x%llx is not properly aligned.\n", 1 << i, results_data[i]); + } else { + if (DEBUG) log_info("\tVector size %d passed: 0x%llx is properly aligned.\n", 1 << i, results_data[i]); + } + } + } + // Verify the results on devices that do not support longs + else { + cl_uint *results_data_no_long = (cl_uint *)results_data; + + for (int i = 0; i < 6; i++) { + if ((results_data_no_long[i] & alignments[i]) != 0) { + total_errors++; + log_error("\tVector size %d failed: 0x%llx is not properly aligned.\n", 1 << i, results_data_no_long[i]); + } else { + if (DEBUG) log_info("\tVector size %d passed: 0x%llx is properly aligned.\n", 1 << i, results_data_no_long[i]); + } + } + } + + clReleaseKernel(kernel); + clReleaseProgram(program); + } + + + + + // Local kernel + if (address == kLocal || address == kPrivate) { + log_info("\tTesting local kernel...\n"); + sprintf(kernel_code, local_kernel, + vecType[typeIndex] == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]), + get_explicit_address_name(address), get_explicit_type_name(vecType[typeIndex]) + ); + //printf("Kernel is: \n%s\n", kernel_code); + + // Create the kernel + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&kernel_code, "test"); + test_error(error, "create_single_kernel_helper failed"); + + // Initialize the results + memset(results_data, 0, sizeof(cl_long)*5); + error = clEnqueueWriteBuffer(queue, results, CL_TRUE, 0, sizeof(cl_long)*5, results_data, 0, NULL, NULL); + test_error(error, "clEnqueueWriteBuffer failed"); + + // Set the arguments + error = clSetKernelArg(kernel, 0, sizeof(results), &results); + test_error(error, "clSetKernelArg failed"); + + // Enqueue the kernel + size_t global_size = 1; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, NULL, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + // Read back the results + error = clEnqueueReadBuffer(queue, results, CL_TRUE, 0, sizeof(cl_ulong)*5, results_data, 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + // Verify the results + if (gHasLong) { + for (int i = 0; i < 5; i++) { + if ((results_data[i] & alignments[i]) != 0) { + total_errors++; + log_error("\tVector size %d failed: 0x%llx is not properly aligned.\n", 1 << i, results_data[i]); + } else { + if (DEBUG) log_info("\tVector size %d passed: 0x%llx is properly aligned.\n", 1 << i, results_data[i]); + } + } + } + // Verify the results on devices that do not support longs + else { + cl_uint *results_data_no_long = (cl_uint *)results_data; + + for (int i = 0; i < 5; i++) { + if ((results_data_no_long[i] & alignments[i]) != 0) { + total_errors++; + log_error("\tVector size %d failed: 0x%llx is not properly aligned.\n", 1 << i, results_data_no_long[i]); + } else { + if (DEBUG) log_info("\tVector size %d passed: 0x%llx is properly aligned.\n", 1 << i, results_data_no_long[i]); + } + } + } + clReleaseKernel(kernel); + clReleaseProgram(program); + } + + + + // Constant kernel + if (address == kConstant) { + log_info("\tTesting constant kernel...\n"); + sprintf(kernel_code, constant_kernel, + vecType[typeIndex] == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]), + get_explicit_type_name(vecType[typeIndex]) + ); + //printf("Kernel is: \n%s\n", kernel_code); + + // Create the kernel + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&kernel_code, "test"); + test_error(error, "create_single_kernel_helper failed"); + + // Initialize the results + memset(results_data, 0, sizeof(cl_long)*5); + error = clEnqueueWriteBuffer(queue, results, CL_TRUE, 0, sizeof(cl_long)*5, results_data, 0, NULL, NULL); + test_error(error, "clEnqueueWriteBuffer failed"); + + // Set the arguments + error = clSetKernelArg(kernel, 0, sizeof(results), &results); + test_error(error, "clSetKernelArg failed"); + + // Enqueue the kernel + size_t global_size = 1; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, NULL, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + // Read back the results + error = clEnqueueReadBuffer(queue, results, CL_TRUE, 0, sizeof(cl_ulong)*5, results_data, 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + // Verify the results + if (gHasLong) { + for (int i = 0; i < 5; i++) { + if ((results_data[i] & alignments[i]) != 0) { + total_errors++; + log_error("\tVector size %d failed: 0x%llx is not properly aligned.\n", 1 << i, results_data[i]); + } else { + if (DEBUG) log_info("\tVector size %d passed: 0x%llx is properly aligned.\n", 1 << i, results_data[i]); + } + } + } + // Verify the results on devices that do not support longs + else { + cl_uint *results_data_no_long = (cl_uint *)results_data; + + for (int i = 0; i < 5; i++) { + if ((results_data_no_long[i] & alignments[i]) != 0) { + total_errors++; + log_error("\tVector size %d failed: 0x%llx is not properly aligned.\n", 1 << i, results_data_no_long[i]); + } else { + if (DEBUG) log_info("\tVector size %d passed: 0x%llx is properly aligned.\n", 1 << i, results_data_no_long[i]); + } + } + } + clReleaseKernel(kernel); + clReleaseProgram(program); + } + + + } + + clReleaseMemObject(results); + clReleaseMemObject(mem0); + clReleaseMemObject(mem2); + clReleaseMemObject(mem3); + clReleaseMemObject(mem4); + clReleaseMemObject(mem8); + clReleaseMemObject(mem16); + free( kernel_code ); + free( results_data ); + + if (total_errors != 0) + return -1; + return 0; + +} + + +int test_kernel_memory_alignment_local(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + return test_kernel_memory_alignment( device, context, queue, n_elems, kLocal ); +} + +int test_kernel_memory_alignment_global(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + return test_kernel_memory_alignment( device, context, queue, n_elems, kGlobal ); +} + +int test_kernel_memory_alignment_constant(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + // There is a class of approved OpenCL 1.0 conformant devices out there that in some circumstances + // are unable to meaningfully take (or more precisely use) the address of constant data by virtue + // of limitations in their ISA design. This feature was not tested in 1.0, so they were declared + // conformant by Khronos. The failure is however caught here. + // + // Unfortunately, determining whether or not these devices are 1.0 conformant is not the jurisdiction + // of the 1.1 tests -- We can't fail them from 1.1 conformance here because they are not 1.1 + // devices. They are merely 1.0 conformant devices that interop with 1.1 devices in a 1.1 platform. + // To add new binding tests now to conformant 1.0 devices would violate the workingroup requirement + // of no new tests for 1.0 devices. So certain allowances have to be made in intractable cases + // such as this one. + // + // There is some precedent. Similar allowances are made for other 1.0 hardware features such as + // local memory size. The minimum required local memory size grew from 16 kB to 32 kB in OpenCL 1.1. + + // Detect 1.0 devices + // Get CL_DEVICE_VERSION size + size_t string_size = 0; + int err; + if( (err = clGetDeviceInfo( device, CL_DEVICE_VERSION, 0, NULL, &string_size ) ) ) + { + log_error( "FAILURE: Unable to get size of CL_DEVICE_VERSION string!" ); + return -1; + } + + //Allocate storage to hold the version string + char *version_string = (char*) malloc(string_size); + if( NULL == version_string ) + { + log_error( "FAILURE: Unable to allocate memory to hold CL_DEVICE_VERSION string!" ); + return -1; + } + + // Get CL_DEVICE_VERSION string + if( (err = clGetDeviceInfo( device, CL_DEVICE_VERSION, string_size, version_string, NULL ) ) ) + { + log_error( "FAILURE: Unable to read CL_DEVICE_VERSION string!" ); + return -1; + } + + // easy out for 1.0 devices + const char *string_1_0 = "OpenCL 1.0 "; + if( 0 == strncmp( version_string, string_1_0, strlen(string_1_0)) ) + { + log_info( "WARNING: Allowing device to escape testing of difficult constant memory alignment case.\n\tDevice is not a OpenCL 1.1 device. CL_DEVICE_VERSION: \"%s\"\n", version_string ); + free(version_string); + return 0; + } + log_info( "Device version string: \"%s\"\n", version_string ); + free(version_string); + + // Everyone else is to be ground mercilessly under the wheels of progress + return test_kernel_memory_alignment( device, context, queue, n_elems, kConstant ); +} + +int test_kernel_memory_alignment_private(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + return test_kernel_memory_alignment( device, context, queue, n_elems, kPrivate ); +} + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_local.c b/test_conformance/compatibility/test_conformance/basic/test_local.c new file mode 100644 index 00000000..1be5926a --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_local.c @@ -0,0 +1,372 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +const char *barrier_with_localmem_kernel_code[] = { +"__kernel void compute_sum_with_localmem(__global int *a, int n, __local int *tmp_sum, __global int *sum)\n" +"{\n" +" int tid = get_local_id(0);\n" +" int lsize = get_local_size(0);\n" +" int i;\n" +"\n" +" tmp_sum[tid] = 0;\n" +" for (i=tid; i max_local_workgroup_size[0]) + kwgsize = max_local_workgroup_size[0]; + + // err = clSetKernelArgs(context, kernel, 4, NULL, values, sizes); + err = clSetKernelArg(kernel, 0, sizeof(streams[0]), &streams[0]); + err |= clSetKernelArg(kernel, 1, sizeof num_elements, &num_elements); + err |= clSetKernelArg(kernel, 2, wgsize * sizeof(cl_int), NULL); + err |= clSetKernelArg(kernel, 3, sizeof streams[1], &streams[1]); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + global_threads[0] = wgsize; + local_threads[0] = wgsize; + + // Adjust the local thread size to fit and be a nice multiple. + if (kwgsize < wgsize) { + log_info("Adjusting wgsize down from %lu to %lu.\n", wgsize, kwgsize); + local_threads[0] = kwgsize; + } + while (global_threads[0] % local_threads[0] != 0) + local_threads[0]--; + + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global_threads, local_threads, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + err = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, out_length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueReadBuffer failed\n"); + return -1; + } + + err = verify_sum(input_ptr, tmp_ptr, output_ptr, num_elements); + + // cleanup + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + free(input_ptr); + free(tmp_ptr); + free(output_ptr); + + return err; +} + +int test_local_kernel_def(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem streams[2]; + cl_program program; + cl_kernel kernel; + + cl_int *input_ptr, *output_ptr, *tmp_ptr; + size_t global_threads[1], local_threads[1]; + size_t wgsize, kwgsize; + int err, i; + char *program_source = (char*)malloc(sizeof(char)*2048); + MTdata d = init_genrand( gRandomSeed ); + size_t max_local_workgroup_size[3]; + memset(program_source, 0, 2048); + + err = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof wgsize, &wgsize, NULL); + if (err) { + log_error("clGetDeviceInfo failed, %d\n\n", err); + return -1; + } + wgsize/=2; + if (wgsize < 1) + wgsize = 1; + + size_t in_length = sizeof(cl_int) * num_elements; + size_t out_length = sizeof(cl_int) * wgsize; + + input_ptr = (cl_int *)malloc(in_length); + output_ptr = (cl_int *)malloc(out_length); + tmp_ptr = (cl_int *)malloc(out_length); + + streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, in_length, NULL, NULL); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, out_length, NULL, NULL); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + for (i=0; i (localMemSize / (sizeof(cl_int)*sizeof(cl_int))) ) + { + wgsize = localMemSize / (sizeof(cl_int)*sizeof(cl_int)); + } + + sprintf(program_source, barrier_with_localmem_kernel_code[1], (int)(wgsize * sizeof(cl_int))); + + err = create_single_kernel_helper(context, &program, &kernel, 1, (const char**)&program_source, "compute_sum_with_localmem" ); + free(program_source); + if (err) + return -1; + + err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof kwgsize, &kwgsize, NULL); + test_error(err, "clGetKernelWorkGroupInfo failed for CL_KERNEL_WORK_GROUP_SIZE"); + + err = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(max_local_workgroup_size), max_local_workgroup_size, NULL); + test_error(err, "clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_SIZES"); + + // Pick the minimum of the device and the kernel + if (kwgsize > max_local_workgroup_size[0]) + kwgsize = max_local_workgroup_size[0]; + + // err = clSetKernelArgs(context, kernel, 4, NULL, values, sizes); + err = clSetKernelArg(kernel, 0, sizeof(streams[0]), &streams[0]); + err |= clSetKernelArg(kernel, 1, sizeof num_elements, &num_elements); + err |= clSetKernelArg(kernel, 2, sizeof streams[1], &streams[1]); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + global_threads[0] = wgsize; + local_threads[0] = wgsize; + + // Adjust the local thread size to fit and be a nice multiple. + if (kwgsize < wgsize) { + log_info("Adjusting wgsize down from %lu to %lu.\n", wgsize, kwgsize); + local_threads[0] = kwgsize; + } + while (global_threads[0] % local_threads[0] != 0) + local_threads[0]--; + + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global_threads, local_threads, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + err = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, out_length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueReadBuffer failed\n"); + return -1; + } + + err = verify_sum(input_ptr, tmp_ptr, output_ptr, num_elements); + + // cleanup + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + clReleaseKernel(kernel); + clReleaseProgram(program); + free(input_ptr); + free(tmp_ptr); + free(output_ptr); + + return err; +} + + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_local_kernel_scope.cpp b/test_conformance/compatibility/test_conformance/basic/test_local_kernel_scope.cpp new file mode 100644 index 00000000..a469751d --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_local_kernel_scope.cpp @@ -0,0 +1,138 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +#define MAX_LOCAL_STORAGE_SIZE 256 +#define MAX_LOCAL_STORAGE_SIZE_STRING "256" + +const char *kernelSource[] = { + "__kernel void test( __global unsigned int * input, __global unsigned int *outMaxes )\n" + "{\n" + " __local unsigned int localStorage[ " MAX_LOCAL_STORAGE_SIZE_STRING " ];\n" + " unsigned int theValue = input[ get_global_id( 0 ) ];\n" + "\n" + " // If we just write linearly, there's no verification that the items in a group share local data\n" + " // So we write reverse-linearly, which requires items to read the local data written by at least one\n" + " // different item\n" + " localStorage[ get_local_size( 0 ) - get_local_id( 0 ) - 1 ] = theValue;\n" + "\n" + " // The barrier ensures that all local items have written to the local storage\n" + " barrier( CLK_LOCAL_MEM_FENCE );\n" + "\n" + " // Now we loop back through the local storage and look for the max value. We only do this if\n" + " // we're the first item in a group\n" + " unsigned int max = 0;\n" + " if( get_local_id( 0 ) == 0 )\n" + " {\n" + " for( size_t i = 0; i < get_local_size( 0 ); i++ )\n" + " {\n" + " if( localStorage[ i ] > max )\n" + " max = localStorage[ i ];\n" + " }\n" + " outMaxes[ get_group_id( 0 ) ] = max;\n" + " }\n" + "}\n" +}; + +int test_local_kernel_scope(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int error; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 2 ]; + MTdata randSeed = init_genrand( gRandomSeed ); + + // Create a test kernel + error = create_single_kernel_helper( context, &program, &kernel, 1, kernelSource, "test" ); + test_error( error, "Unable to create test kernel" ); + + + // Determine an appropriate test size + size_t workGroupSize; + error = clGetKernelWorkGroupInfo( kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof( workGroupSize ), &workGroupSize, NULL ); + test_error( error, "Unable to obtain kernel work group size" ); + + // Make sure the work group size doesn't overrun our local storage size in the kernel + while( workGroupSize > MAX_LOCAL_STORAGE_SIZE ) + workGroupSize >>= 1; + + size_t testSize = workGroupSize; + while( testSize < 1024 ) + testSize += workGroupSize; + size_t numGroups = testSize / workGroupSize; + log_info( "\tTesting with %ld groups, %ld elements per group...\n", numGroups, workGroupSize ); + + // Create two buffers for operation + cl_uint *inputData = (cl_uint*)malloc( testSize * sizeof(cl_uint) ); + generate_random_data( kUInt, testSize, randSeed, inputData ); + free_mtdata( randSeed ); + streams[ 0 ] = clCreateBuffer( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, testSize * sizeof(cl_uint), inputData, &error ); + test_error( error, "Unable to create input buffer" ); + + cl_uint *outputData = (cl_uint*)malloc( numGroups *sizeof(cl_uint) ); + streams[ 1 ] = clCreateBuffer( context, CL_MEM_WRITE_ONLY, numGroups * sizeof(cl_uint), NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + + // Set up the kernel args and run + error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] ); + test_error( error, "Unable to set kernel arg" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[ 1 ] ), &streams[ 1 ] ); + test_error( error, "Unable to set kernel arg" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, &testSize, &workGroupSize, 0, NULL, NULL ); + test_error( error, "Unable to enqueue kernel" ); + + + // Read results and verify + error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, numGroups * sizeof(cl_uint), outputData, 0, NULL, NULL ); + test_error( error, "Unable to read output data" ); + + // MingW compiler seems to have a bug that otimizes the code below incorrectly. + // adding the volatile keyword to size_t decleration to avoid aggressive optimization by the compiler. + for( volatile size_t i = 0; i < numGroups; i++ ) + { + // Determine the max in our case + cl_uint localMax = 0; + for( volatile size_t j = 0; j < workGroupSize; j++ ) + { + if( inputData[ i * workGroupSize + j ] > localMax ) + localMax = inputData[ i * workGroupSize + j ]; + } + + if( outputData[ i ] != localMax ) + { + log_error( "ERROR: Local max validation failed! (expected %u, got %u for i=%lu)\n", localMax, outputData[ i ] , i ); + free(inputData); + free(outputData); + return -1; + } + } + + free(inputData); + free(outputData); + return 0; +} + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_loop.c b/test_conformance/compatibility/test_conformance/basic/test_loop.c new file mode 100644 index 00000000..a4f043b4 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_loop.c @@ -0,0 +1,184 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +const char *loop_kernel_code = +"__kernel void test_loop(__global int *src, __global int *loopindx, __global int *loopcnt, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +" int n = get_global_size(0);\n" +" int i, j;\n" +"\n" +" dst[tid] = 0;\n" +" for (i=0,j=loopindx[tid]; i= n)\n" +" j = 0;\n" +" dst[tid] += src[j];\n" +" }\n" +"\n" +"}\n"; + + +int +verify_loop(int *inptr, int *loopindx, int *loopcnt, int *outptr, int n) +{ + int r, i, j, k; + + for (i=0; i= n) + k = 0; + r += inptr[k]; + } + + if (r != outptr[i]) + { + log_error("LOOP test failed: %d found, expected %d\n", outptr[i], r); + return -1; + } + } + + log_info("LOOP test passed\n"); + return 0; +} + +int test_loop(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem streams[4]; + cl_int *input_ptr, *loop_indx, *loop_cnt, *output_ptr; + cl_program program; + cl_kernel kernel; + size_t threads[1]; + int err, i; + + size_t length = sizeof(cl_int) * num_elements; + input_ptr = (cl_int*)malloc(length); + loop_indx = (cl_int*)malloc(length); + loop_cnt = (cl_int*)malloc(length); + output_ptr = (cl_int*)malloc(length); + + streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[3] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[3]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + MTdata d = init_genrand( gRandomSeed ); + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +static const char *multireadimage_kernel_code = +"__kernel void test_multireadimage(read_only image2d_t img0, read_only image2d_t img1, \n" +" read_only image2d_t img2, __global float4 *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int2 tid = (int2)(tid_x, tid_y);\n" +" int indx = tid_y * get_image_width(img1) + tid_x;\n" +" float4 sum;\n" +"\n" +" sum = read_imagef(img0, sampler, tid);\n" +" sum += read_imagef(img1, sampler, tid);\n" +" sum += read_imagef(img2, sampler, tid);\n" +"\n" +" dst[indx] = sum;\n" +"}\n"; + +#define MAX_ERR 1e-7f + +static unsigned char * +generate_8888_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i max_ulp) + max_ulp = ulp; + } + + if (max_ulp > max_ulp_allowed) { + log_error("READ_MULTIREADIMAGE_MULTIFORMAT test failed. Max ulp error = %g\n", max_ulp); + return -1; + } + + log_info("READ_MULTIREADIMAGE_MULTIFORMAT test passed. Max ulp error = %g\n", max_ulp); + return 0; +} + + +int +test_multireadimagemultifmt(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem streams[4]; + cl_image_format img_format; + void *input_ptr[3], *output_ptr; + cl_program program; + cl_kernel kernel; + size_t threads[2]; + int img_width = 512; + int img_height = 512; + int i, err; + MTdata d; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + d = init_genrand( gRandomSeed ); + input_ptr[0] = (void *)generate_8888_image(img_width, img_height, d); + input_ptr[1] = (void *)generate_16bit_image(img_width, img_height, d); + input_ptr[2] = (void *)generate_float_image(img_width, img_height, d); + free_mtdata(d); d = NULL; + + output_ptr = (void *)malloc(sizeof(float) * 4 * img_width * img_height); + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + streams[0] = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[0]) + { + log_error("create_image_2d failed\n"); + return -1; + } + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT16; + streams[1] = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[1]) + { + log_error("create_image_2d failed\n"); + return -1; + } + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_FLOAT; + streams[2] = create_image_2d(context, (cl_mem_flags)(CL_MEM_READ_WRITE), &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[2]) + { + log_error("create_image_2d failed\n"); + return -1; + } + + streams[3] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(float)*4 * img_width*img_height, NULL, NULL); + if (!streams[3]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + for (i=0; i<3; i++) + { + size_t origin[3] = {0,0,0}, region[3]={img_width, img_height,1}; + err = clEnqueueWriteImage(queue, streams[i], CL_TRUE, origin, region, 0, 0, input_ptr[i], 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clWriteImage failed\n"); + return -1; + } + } + + err = create_single_kernel_helper( context, &program, &kernel, 1, &multireadimage_kernel_code, "test_multireadimage"); + if (err) + return -1; + + cl_sampler sampler = clCreateSampler(context, CL_FALSE, CL_ADDRESS_CLAMP_TO_EDGE, CL_FILTER_NEAREST, &err); + test_error(err, "clCreateSampler failed"); + + for (i=0; i<4; i++) + err |= clSetKernelArg(kernel, i,sizeof streams[i], &streams[i]); + err |= clSetKernelArg(kernel, 4, sizeof sampler, &sampler); + + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + threads[0] = (size_t)img_width; + threads[1] = (size_t)img_height; + + err = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + err = clEnqueueReadBuffer( queue, streams[3], CL_TRUE, 0, sizeof(float)*4*img_width*img_height, (void *)output_ptr, 0, NULL, NULL ); + if (err != CL_SUCCESS) + { + log_error("clEnqueueReadBuffer failed\n"); + return -1; + } + + err = verify_multireadimage(input_ptr, (float*)output_ptr, img_width, img_height); + + // cleanup + clReleaseSampler(sampler); + for (i=0; i<4; i++) + clReleaseMemObject(streams[i]); + clReleaseKernel(kernel); + clReleaseProgram(program); + for (i=0; i<3; i++) + free(input_ptr[i]); + free(output_ptr); + + return err; +} + + + + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_multireadimageonefmt.c b/test_conformance/compatibility/test_conformance/basic/test_multireadimageonefmt.c new file mode 100644 index 00000000..e561176d --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_multireadimageonefmt.c @@ -0,0 +1,198 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +static const char *multireadimage_kernel_code = +"__kernel void test_multireadimage(int n, int m, sampler_t sampler, \n" +" read_only image2d_t img0, read_only image2d_t img1, \n" +" read_only image2d_t img2, read_only image2d_t img3, \n" +" read_only image2d_t img4, read_only image2d_t img5, \n" +" read_only image2d_t img6, __global float4 *dst)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int2 tid = (int2)(tid_x, tid_y);\n" +" int indx = tid_y * get_image_width(img5) + tid_x;\n" +" float4 sum;\n" +"\n" +" sum = read_imagef(img0, sampler, tid);\n" +" sum += read_imagef(img1, sampler, tid);\n" +" sum += read_imagef(img2, sampler, tid);\n" +" sum += read_imagef(img3, sampler, tid);\n" +" sum += read_imagef(img4, sampler, tid);\n" +" sum += read_imagef(img5, sampler, tid);\n" +" sum += read_imagef(img6, sampler, tid);\n" +"\n" +" dst[indx] = sum;\n" +"}\n"; + + +static unsigned char * +generate_8888_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i max_ulp) + max_ulp = ulp; + } + + if (max_ulp > max_ulp_allowed) + { + log_error("READ_MULTIREADIMAGE_RGBA8888 test failed. Max ULP err = %g\n", max_ulp); + return -1; + } + log_info("READ_MULTIREADIMAGE_RGBA8888 test passed. Max ULP err = %g\n", max_ulp); + return 0; +} + + +int test_multireadimageonefmt(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem streams[8]; + cl_image_format img_format; + void *input_ptr[7], *output_ptr; + cl_program program; + cl_kernel kernel; + size_t threads[2]; + int img_width = 512; + int img_height = 512; + int i, err; + size_t origin[3] = {0, 0, 0}; + size_t region[3] = {img_width, img_height, 1}; + size_t length = img_width * img_height * 4 * sizeof(float); + MTdata d; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + output_ptr = malloc(length); + + d = init_genrand( gRandomSeed ); + for (i=0; i<7; i++) { + input_ptr[i] = (void *)generate_8888_image(img_width, img_height, d); + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT8; + streams[i] = create_image_2d(context, CL_MEM_READ_WRITE, &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[i]) + { + log_error("create_image_2d failed\n"); + return -1; + } + + err = clEnqueueWriteImage(queue, streams[i], CL_TRUE, origin, region, 0, 0, input_ptr[i], 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clWriteImage failed\n"); + return -1; + } + } + free_mtdata(d); d = NULL; + + + streams[7] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[7]) + { + log_error("clCreateArray failed\n"); + return -1; + } + + err = create_single_kernel_helper(context, &program, &kernel, 1, &multireadimage_kernel_code, "test_multireadimage"); + if (err) + return -1; + + cl_sampler sampler = clCreateSampler(context, CL_FALSE, CL_ADDRESS_CLAMP_TO_EDGE, CL_FILTER_NEAREST, &err); + test_error(err, "clCreateSampler failed"); + + err = clSetKernelArg(kernel, 0, sizeof i, &i); + err |= clSetKernelArg(kernel, 1, sizeof err, &err); + err |= clSetKernelArg(kernel, 2, sizeof sampler, &sampler); + for (i=0; i<8; i++) + err |= clSetKernelArg(kernel, 3+i, sizeof streams[i], &streams[i]); + + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + threads[0] = (unsigned int)img_width; + threads[1] = (unsigned int)img_height; + + err = clEnqueueNDRangeKernel(queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clExecuteKernel failed\n"); + return -1; + } + err = clEnqueueReadBuffer(queue, streams[7], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clReadArray failed\n"); + return -1; + } + + err = verify_multireadimage(input_ptr, 7, (float *)output_ptr, img_width, img_height); + + // cleanup + clReleaseSampler(sampler); + for (i=0; i<8; i++) + clReleaseMemObject(streams[i]); + clReleaseKernel(kernel); + clReleaseProgram(program); + for (i=0; i<7; i++) + free(input_ptr[i]); + free(output_ptr); + + return err; +} + + + + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_numeric_constants.cpp b/test_conformance/compatibility/test_conformance/basic/test_numeric_constants.cpp new file mode 100644 index 00000000..5aeca0ed --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_numeric_constants.cpp @@ -0,0 +1,710 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "procs.h" + +#define TEST_VALUE_POSITIVE( string_name, name, value ) \ +{ \ +if (name < value) { \ +log_error("FAILED: " string_name ": " #name " < " #value "\n"); \ +errors++;\ +} else { \ +log_info("\t" string_name ": " #name " >= " #value "\n"); \ +} \ +} + +#define TEST_VALUE_NEGATIVE( string_name, name, value ) \ +{ \ +if (name > value) { \ +log_error("FAILED: " string_name ": " #name " > " #value "\n"); \ +errors++;\ +} else { \ +log_info("\t" string_name ": " #name " <= " #value "\n"); \ +} \ +} + +#define TEST_VALUE_EQUAL_LITERAL( string_name, name, value ) \ +{ \ +if (name != value) { \ +log_error("FAILED: " string_name ": " #name " != " #value "\n"); \ +errors++;\ +} else { \ +log_info("\t" string_name ": " #name " = " #value "\n"); \ +} \ +} + +#define TEST_VALUE_EQUAL( string_name, name, value ) \ +{ \ +if (name != value) { \ +log_error("FAILED: " string_name ": " #name " != %a (%17.21g)\n", value, value); \ +errors++;\ +} else { \ +log_info("\t" string_name ": " #name " = %a (%17.21g)\n", value, value); \ +} \ +} + +int test_host_numeric_constants(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int errors = 0; + TEST_VALUE_EQUAL_LITERAL( "CL_CHAR_BIT", CL_CHAR_BIT, 8) + TEST_VALUE_EQUAL_LITERAL( "CL_SCHAR_MAX", CL_SCHAR_MAX, 127) + TEST_VALUE_EQUAL_LITERAL( "CL_SCHAR_MIN", CL_SCHAR_MIN, (-127-1)) + TEST_VALUE_EQUAL_LITERAL( "CL_CHAR_MAX", CL_CHAR_MAX, CL_SCHAR_MAX) + TEST_VALUE_EQUAL_LITERAL( "CL_CHAR_MIN", CL_CHAR_MIN, CL_SCHAR_MIN) + TEST_VALUE_EQUAL_LITERAL( "CL_UCHAR_MAX", CL_UCHAR_MAX, 255) + TEST_VALUE_EQUAL_LITERAL( "CL_SHRT_MAX", CL_SHRT_MAX, 32767) + TEST_VALUE_EQUAL_LITERAL( "CL_SHRT_MIN", CL_SHRT_MIN, (-32767-1)) + TEST_VALUE_EQUAL_LITERAL( "CL_USHRT_MAX", CL_USHRT_MAX, 65535) + TEST_VALUE_EQUAL_LITERAL( "CL_INT_MAX", CL_INT_MAX, 2147483647) + TEST_VALUE_EQUAL_LITERAL( "CL_INT_MIN", CL_INT_MIN, (-2147483647-1)) + TEST_VALUE_EQUAL_LITERAL( "CL_UINT_MAX", CL_UINT_MAX, 0xffffffffU) + TEST_VALUE_EQUAL_LITERAL( "CL_LONG_MAX", CL_LONG_MAX, ((cl_long) 0x7FFFFFFFFFFFFFFFLL)) + TEST_VALUE_EQUAL_LITERAL( "CL_LONG_MIN", CL_LONG_MIN, ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL)) + TEST_VALUE_EQUAL_LITERAL( "CL_ULONG_MAX", CL_ULONG_MAX, ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL)) + + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_DIG", CL_FLT_DIG, 6) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MANT_DIG", CL_FLT_MANT_DIG, 24) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MAX_10_EXP", CL_FLT_MAX_10_EXP, +38) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MAX_EXP", CL_FLT_MAX_EXP, +128) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MIN_10_EXP", CL_FLT_MIN_10_EXP, -37) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MIN_EXP", CL_FLT_MIN_EXP, -125) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_RADIX", CL_FLT_RADIX, 2) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MAX", CL_FLT_MAX, MAKE_HEX_FLOAT( 0x1.fffffep127f, 0x1fffffeL, 103)) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MIN", CL_FLT_MIN, MAKE_HEX_FLOAT(0x1.0p-126f, 0x1L, -126)) + TEST_VALUE_EQUAL_LITERAL( "CL_FLT_EPSILON", CL_FLT_EPSILON, MAKE_HEX_FLOAT(0x1.0p-23f, 0x1L, -23)) + + TEST_VALUE_EQUAL_LITERAL( "CL_DBL_DIG", CL_DBL_DIG, 15) + TEST_VALUE_EQUAL_LITERAL( "CL_DBL_MANT_DIG", CL_DBL_MANT_DIG, 53) + TEST_VALUE_EQUAL_LITERAL( "CL_DBL_MAX_10_EXP", CL_DBL_MAX_10_EXP, +308) + TEST_VALUE_EQUAL_LITERAL( "CL_DBL_MAX_EXP", CL_DBL_MAX_EXP, +1024) + TEST_VALUE_EQUAL_LITERAL( "CL_DBL_MIN_10_EXP", CL_DBL_MIN_10_EXP, -307) + TEST_VALUE_EQUAL_LITERAL( "CL_DBL_MIN_EXP", CL_DBL_MIN_EXP, -1021) + TEST_VALUE_EQUAL_LITERAL( "CL_DBL_RADIX", CL_DBL_RADIX, 2) + TEST_VALUE_EQUAL( "CL_DBL_MAX", CL_DBL_MAX, MAKE_HEX_DOUBLE(0x1.fffffffffffffp1023, 0x1fffffffffffffLL, 971)) + TEST_VALUE_EQUAL( "CL_DBL_MIN", CL_DBL_MIN, MAKE_HEX_DOUBLE(0x1.0p-1022, 0x1LL, -1022)) + TEST_VALUE_EQUAL( "CL_DBL_EPSILON", CL_DBL_EPSILON, MAKE_HEX_DOUBLE(0x1.0p-52, 0x1LL, -52)) + + TEST_VALUE_EQUAL( "CL_M_E", CL_M_E, MAKE_HEX_DOUBLE(0x1.5bf0a8b145769p+1, 0x15bf0a8b145769LL, -51) ); + TEST_VALUE_EQUAL( "CL_M_LOG2E", CL_M_LOG2E, MAKE_HEX_DOUBLE(0x1.71547652b82fep+0, 0x171547652b82feLL, -52) ); + TEST_VALUE_EQUAL( "CL_M_LOG10E", CL_M_LOG10E, MAKE_HEX_DOUBLE(0x1.bcb7b1526e50ep-2, 0x1bcb7b1526e50eLL, -54) ); + TEST_VALUE_EQUAL( "CL_M_LN2", CL_M_LN2, MAKE_HEX_DOUBLE(0x1.62e42fefa39efp-1, 0x162e42fefa39efLL, -53) ); + TEST_VALUE_EQUAL( "CL_M_LN10", CL_M_LN10, MAKE_HEX_DOUBLE(0x1.26bb1bbb55516p+1, 0x126bb1bbb55516LL, -51) ); + TEST_VALUE_EQUAL( "CL_M_PI", CL_M_PI, MAKE_HEX_DOUBLE(0x1.921fb54442d18p+1, 0x1921fb54442d18LL, -51) ); + TEST_VALUE_EQUAL( "CL_M_PI_2", CL_M_PI_2, MAKE_HEX_DOUBLE(0x1.921fb54442d18p+0, 0x1921fb54442d18LL, -52) ); + TEST_VALUE_EQUAL( "CL_M_PI_4", CL_M_PI_4, MAKE_HEX_DOUBLE(0x1.921fb54442d18p-1, 0x1921fb54442d18LL, -53) ); + TEST_VALUE_EQUAL( "CL_M_1_PI", CL_M_1_PI, MAKE_HEX_DOUBLE(0x1.45f306dc9c883p-2, 0x145f306dc9c883LL, -54) ); + TEST_VALUE_EQUAL( "CL_M_2_PI", CL_M_2_PI, MAKE_HEX_DOUBLE(0x1.45f306dc9c883p-1, 0x145f306dc9c883LL, -53) ); + TEST_VALUE_EQUAL( "CL_M_2_SQRTPI", CL_M_2_SQRTPI, MAKE_HEX_DOUBLE(0x1.20dd750429b6dp+0, 0x120dd750429b6dLL, -52) ); + TEST_VALUE_EQUAL( "CL_M_SQRT2", CL_M_SQRT2, MAKE_HEX_DOUBLE(0x1.6a09e667f3bcdp+0, 0x16a09e667f3bcdLL, -52) ); + TEST_VALUE_EQUAL( "CL_M_SQRT1_2", CL_M_SQRT1_2, MAKE_HEX_DOUBLE(0x1.6a09e667f3bcdp-1, 0x16a09e667f3bcdLL, -53) ); + + TEST_VALUE_EQUAL( "CL_M_E_F", CL_M_E_F, MAKE_HEX_FLOAT(0x1.5bf0a8p+1f, 0x15bf0a8L, -23)); + TEST_VALUE_EQUAL( "CL_M_LOG2E_F", CL_M_LOG2E_F, MAKE_HEX_FLOAT(0x1.715476p+0f, 0x1715476L, -24)); + TEST_VALUE_EQUAL( "CL_M_LOG10E_F", CL_M_LOG10E_F, MAKE_HEX_FLOAT(0x1.bcb7b2p-2f, 0x1bcb7b2L, -26)); + TEST_VALUE_EQUAL( "CL_M_LN2_F", CL_M_LN2_F, MAKE_HEX_FLOAT(0x1.62e43p-1f, 0x162e43L, -21) ); + TEST_VALUE_EQUAL( "CL_M_LN10_F", CL_M_LN10_F, MAKE_HEX_FLOAT(0x1.26bb1cp+1f, 0x126bb1cL, -23)); + TEST_VALUE_EQUAL( "CL_M_PI_F", CL_M_PI_F, MAKE_HEX_FLOAT(0x1.921fb6p+1f, 0x1921fb6L, -23)); + TEST_VALUE_EQUAL( "CL_M_PI_2_F", CL_M_PI_2_F, MAKE_HEX_FLOAT(0x1.921fb6p+0f, 0x1921fb6L, -24)); + TEST_VALUE_EQUAL( "CL_M_PI_4_F", CL_M_PI_4_F, MAKE_HEX_FLOAT(0x1.921fb6p-1f, 0x1921fb6L, -25)); + TEST_VALUE_EQUAL( "CL_M_1_PI_F", CL_M_1_PI_F, MAKE_HEX_FLOAT(0x1.45f306p-2f, 0x145f306L, -26)); + TEST_VALUE_EQUAL( "CL_M_2_PI_F", CL_M_2_PI_F, MAKE_HEX_FLOAT(0x1.45f306p-1f, 0x145f306L, -25)); + TEST_VALUE_EQUAL( "CL_M_2_SQRTPI_F", CL_M_2_SQRTPI_F,MAKE_HEX_FLOAT(0x1.20dd76p+0f, 0x120dd76L, -24)); + TEST_VALUE_EQUAL( "CL_M_SQRT2_F", CL_M_SQRT2_F, MAKE_HEX_FLOAT(0x1.6a09e6p+0f, 0x16a09e6L, -24)); + TEST_VALUE_EQUAL( "CL_M_SQRT1_2_F", CL_M_SQRT1_2_F, MAKE_HEX_FLOAT(0x1.6a09e6p-1f, 0x16a09e6L, -25)); + + return errors; +} + + +const char *kernel_int_float[] = { + "__kernel void test( __global float *float_out, __global int *int_out, __global uint *uint_out) \n" + "{\n" + " int_out[0] = CHAR_BIT;\n" + " int_out[1] = SCHAR_MAX;\n" + " int_out[2] = SCHAR_MIN;\n" + " int_out[3] = CHAR_MAX;\n" + " int_out[4] = CHAR_MIN;\n" + " int_out[5] = UCHAR_MAX;\n" + " int_out[6] = SHRT_MAX;\n" + " int_out[7] = SHRT_MIN;\n" + " int_out[8] = USHRT_MAX;\n" + " int_out[9] = INT_MAX;\n" + " int_out[10] = INT_MIN;\n" + " uint_out[0] = UINT_MAX;\n" + + " int_out[11] = FLT_DIG;\n" + " int_out[12] = FLT_MANT_DIG;\n" + " int_out[13] = FLT_MAX_10_EXP;\n" + " int_out[14] = FLT_MAX_EXP;\n" + " int_out[15] = FLT_MIN_10_EXP;\n" + " int_out[16] = FLT_MIN_EXP;\n" + " int_out[17] = FLT_RADIX;\n" + "#ifdef __IMAGE_SUPPORT__\n" + " int_out[18] = __IMAGE_SUPPORT__;\n" + "#else\n" + " int_out[18] = 0xf00baa;\n" + "#endif\n" + " float_out[0] = FLT_MAX;\n" + " float_out[1] = FLT_MIN;\n" + " float_out[2] = FLT_EPSILON;\n" + " float_out[3] = M_E_F;\n" + " float_out[4] = M_LOG2E_F;\n" + " float_out[5] = M_LOG10E_F;\n" + " float_out[6] = M_LN2_F;\n" + " float_out[7] = M_LN10_F;\n" + " float_out[8] = M_PI_F;\n" + " float_out[9] = M_PI_2_F;\n" + " float_out[10] = M_PI_4_F;\n" + " float_out[11] = M_1_PI_F;\n" + " float_out[12] = M_2_PI_F;\n" + " float_out[13] = M_2_SQRTPI_F;\n" + " float_out[14] = M_SQRT2_F;\n" + " float_out[15] = M_SQRT1_2_F;\n" + "}\n" +}; + +const char *kernel_long[] = { + "__kernel void test(__global long *long_out, __global ulong *ulong_out) \n" + "{\n" + " long_out[0] = LONG_MAX;\n" + " long_out[1] = LONG_MIN;\n" + " ulong_out[0] = ULONG_MAX;\n" + "}\n" +}; + +const char *kernel_double[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global double *double_out, __global long *long_out ) \n " + "{\n" + " long_out[0] = DBL_DIG;\n" + " long_out[1] = DBL_MANT_DIG;\n" + " long_out[2] = DBL_MAX_10_EXP;\n" + " long_out[3] = DBL_MAX_EXP;\n" + " long_out[4] = DBL_MIN_10_EXP;\n" + " long_out[5] = DBL_MIN_EXP;\n" + " long_out[6] = DBL_RADIX;\n" + " double_out[0] = DBL_MAX;\n" + " double_out[1] = DBL_MIN;\n" + " double_out[2] = DBL_EPSILON;\n" + " double_out[3] = M_E;\n" + " double_out[4] = M_LOG2E;\n" + " double_out[5] = M_LOG10E;\n" + " double_out[6] = M_LN2;\n" + " double_out[7] = M_LN10;\n" + " double_out[8] = M_PI;\n" + " double_out[9] = M_PI_2;\n" + " double_out[10] = M_PI_4;\n" + " double_out[11] = M_1_PI;\n" + " double_out[12] = M_2_PI;\n" + " double_out[13] = M_2_SQRTPI;\n" + " double_out[14] = M_SQRT2;\n" + " double_out[15] = M_SQRT1_2;\n" + "}\n" +}; + + +int test_kernel_numeric_constants(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error, errors = 0; + // clProgramWrapper program; + // clKernelWrapper kernel; + // clMemWrapper streams[3]; + cl_program program; + cl_kernel kernel; + cl_mem streams[3]; + + size_t threads[] = {1,1,1}; + cl_float float_out[16]; + cl_int int_out[19]; + cl_uint uint_out[1]; + cl_long long_out[7]; + cl_ulong ulong_out[1]; + cl_double double_out[16]; + + /** INTs and FLOATs **/ + + // Create the kernel + if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_int_float, "test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(float_out), NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(int_out), NULL, &error); + test_error( error, "Creating test array failed" ); + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(uint_out), NULL, &error); + test_error( error, "Creating test array failed" ); + + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 2, sizeof( streams[2] ), &streams[2]); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, sizeof(float_out), (void*)float_out, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(int_out), (void*)int_out, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, streams[2], CL_TRUE, 0, sizeof(uint_out), (void*)uint_out, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + TEST_VALUE_EQUAL_LITERAL( "CHAR_BIT", int_out[0], 8) + TEST_VALUE_EQUAL_LITERAL( "SCHAR_MAX", int_out[1], 127) + TEST_VALUE_EQUAL_LITERAL( "SCHAR_MIN", int_out[2], (-127-1)) + TEST_VALUE_EQUAL_LITERAL( "CHAR_MAX", int_out[3], CL_SCHAR_MAX) + TEST_VALUE_EQUAL_LITERAL( "CHAR_MIN", int_out[4], CL_SCHAR_MIN) + TEST_VALUE_EQUAL_LITERAL( "UCHAR_MAX", int_out[5], 255) + TEST_VALUE_EQUAL_LITERAL( "SHRT_MAX", int_out[6], 32767) + TEST_VALUE_EQUAL_LITERAL( "SHRT_MIN",int_out[7], (-32767-1)) + TEST_VALUE_EQUAL_LITERAL( "USHRT_MAX", int_out[8], 65535) + TEST_VALUE_EQUAL_LITERAL( "INT_MAX", int_out[9], 2147483647) + TEST_VALUE_EQUAL_LITERAL( "INT_MIN", int_out[10], (-2147483647-1)) + TEST_VALUE_EQUAL_LITERAL( "UINT_MAX", uint_out[0], 0xffffffffU) + + TEST_VALUE_EQUAL_LITERAL( "FLT_DIG", int_out[11], 6) + TEST_VALUE_EQUAL_LITERAL( "FLT_MANT_DIG", int_out[12], 24) + TEST_VALUE_EQUAL_LITERAL( "FLT_MAX_10_EXP", int_out[13], +38) + TEST_VALUE_EQUAL_LITERAL( "FLT_MAX_EXP", int_out[14], +128) + TEST_VALUE_EQUAL_LITERAL( "FLT_MIN_10_EXP", int_out[15], -37) + TEST_VALUE_EQUAL_LITERAL( "FLT_MIN_EXP", int_out[16], -125) + TEST_VALUE_EQUAL_LITERAL( "FLT_RADIX", int_out[17], 2) + TEST_VALUE_EQUAL( "FLT_MAX", float_out[0], MAKE_HEX_FLOAT(0x1.fffffep127f, 0x1fffffeL, 103)) + TEST_VALUE_EQUAL( "FLT_MIN", float_out[1], MAKE_HEX_FLOAT(0x1.0p-126f, 0x1L, -126)) + TEST_VALUE_EQUAL( "FLT_EPSILON", float_out[2], MAKE_HEX_FLOAT(0x1.0p-23f, 0x1L, -23)) + TEST_VALUE_EQUAL( "M_E_F", float_out[3], CL_M_E_F ) + TEST_VALUE_EQUAL( "M_LOG2E_F", float_out[4], CL_M_LOG2E_F ) + TEST_VALUE_EQUAL( "M_LOG10E_F", float_out[5], CL_M_LOG10E_F ) + TEST_VALUE_EQUAL( "M_LN2_F", float_out[6], CL_M_LN2_F ) + TEST_VALUE_EQUAL( "M_LN10_F", float_out[7], CL_M_LN10_F ) + TEST_VALUE_EQUAL( "M_PI_F", float_out[8], CL_M_PI_F ) + TEST_VALUE_EQUAL( "M_PI_2_F", float_out[9], CL_M_PI_2_F ) + TEST_VALUE_EQUAL( "M_PI_4_F", float_out[10], CL_M_PI_4_F ) + TEST_VALUE_EQUAL( "M_1_PI_F", float_out[11], CL_M_1_PI_F ) + TEST_VALUE_EQUAL( "M_2_PI_F", float_out[12], CL_M_2_PI_F ) + TEST_VALUE_EQUAL( "M_2_SQRTPI_F", float_out[13], CL_M_2_SQRTPI_F ) + TEST_VALUE_EQUAL( "M_SQRT2_F", float_out[14], CL_M_SQRT2_F ) + TEST_VALUE_EQUAL( "M_SQRT1_2_F", float_out[15], CL_M_SQRT1_2_F ) + + // We need to check these values against what we know is supported on the device + if( checkForImageSupport( deviceID ) == 0 ) + { // has images + // If images are supported, the constant should have been defined to the value 1 + if( int_out[18] == 0xf00baa ) + { + log_error( "FAILURE: __IMAGE_SUPPORT__ undefined even though images are supported\n" ); + return -1; + } + else if( int_out[18] != 1 ) + { + log_error( "FAILURE: __IMAGE_SUPPORT__ defined, but to the wrong value (defined as %d, spec states it should be 1)\n", int_out[18] ); + return -1; + } + } + else + { // no images + // If images aren't supported, the constant should be undefined + if( int_out[18] != 0xf00baa ) + { + log_error( "FAILURE: __IMAGE_SUPPORT__ defined to value %d even though images aren't supported", int_out[18] ); + return -1; + } + } + log_info( "\t__IMAGE_SUPPORT__: %d\n", int_out[18]); + + clReleaseMemObject(streams[0]); streams[0] = NULL; + clReleaseMemObject(streams[1]); streams[1] = NULL; + clReleaseMemObject(streams[2]); streams[2] = NULL; + clReleaseKernel(kernel); kernel = NULL; + clReleaseProgram(program); program = NULL; + + /** LONGs **/ + + if(!gHasLong) { + log_info("Longs not supported; skipping long tests.\n"); + } + else + { + // Create the kernel + if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_long, "test" ) != 0 ) + { + return -1; + } + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(long_out), NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(ulong_out), NULL, &error); + test_error( error, "Creating test array failed" ); + + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, sizeof(long_out), &long_out, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(ulong_out), &ulong_out, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + TEST_VALUE_EQUAL_LITERAL( "LONG_MAX", long_out[0], ((cl_long) 0x7FFFFFFFFFFFFFFFLL)) + TEST_VALUE_EQUAL_LITERAL( "LONG_MIN", long_out[1], ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL)) + TEST_VALUE_EQUAL_LITERAL( "ULONG_MAX", ulong_out[0], ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL)) + + clReleaseMemObject(streams[0]); streams[0] = NULL; + clReleaseMemObject(streams[1]); streams[1] = NULL; + clReleaseKernel(kernel); kernel = NULL; + clReleaseProgram(program); program = NULL; + } + + /** DOUBLEs **/ + + if(!is_extension_available(deviceID, "cl_khr_fp64")) { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + } + else + { + // Create the kernel + if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_double, "test" ) != 0 ) + { + return -1; + } + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(double_out), NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(long_out), NULL, &error); + test_error( error, "Creating test array failed" ); + + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, sizeof(double_out), &double_out, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(long_out), &long_out, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + TEST_VALUE_EQUAL_LITERAL( "DBL_DIG", long_out[0], 15) + TEST_VALUE_EQUAL_LITERAL( "DBL_MANT_DIG", long_out[1], 53) + TEST_VALUE_EQUAL_LITERAL( "DBL_MAX_10_EXP", long_out[2], +308) + TEST_VALUE_EQUAL_LITERAL( "DBL_MAX_EXP", long_out[3], +1024) + TEST_VALUE_EQUAL_LITERAL( "DBL_MIN_10_EXP", long_out[4], -307) + TEST_VALUE_EQUAL_LITERAL( "DBL_MIN_EXP", long_out[5], -1021) + TEST_VALUE_EQUAL_LITERAL( "DBL_RADIX", long_out[6], 2) + TEST_VALUE_EQUAL( "DBL_MAX", double_out[0], MAKE_HEX_DOUBLE(0x1.fffffffffffffp1023, 0x1fffffffffffffLL, 971)) + TEST_VALUE_EQUAL( "DBL_MIN", double_out[1], MAKE_HEX_DOUBLE(0x1.0p-1022, 0x1LL, -1022)) + TEST_VALUE_EQUAL( "DBL_EPSILON", double_out[2], MAKE_HEX_DOUBLE(0x1.0p-52, 0x1LL, -52)) + //TEST_VALUE_EQUAL( "M_E", double_out[3], CL_M_E ) + TEST_VALUE_EQUAL( "M_LOG2E", double_out[4], CL_M_LOG2E ) + TEST_VALUE_EQUAL( "M_LOG10E", double_out[5], CL_M_LOG10E ) + TEST_VALUE_EQUAL( "M_LN2", double_out[6], CL_M_LN2 ) + TEST_VALUE_EQUAL( "M_LN10", double_out[7], CL_M_LN10 ) + TEST_VALUE_EQUAL( "M_PI", double_out[8], CL_M_PI ) + TEST_VALUE_EQUAL( "M_PI_2", double_out[9], CL_M_PI_2 ) + TEST_VALUE_EQUAL( "M_PI_4", double_out[10], CL_M_PI_4 ) + TEST_VALUE_EQUAL( "M_1_PI", double_out[11], CL_M_1_PI ) + TEST_VALUE_EQUAL( "M_2_PI", double_out[12], CL_M_2_PI ) + TEST_VALUE_EQUAL( "M_2_SQRTPI", double_out[13], CL_M_2_SQRTPI ) + TEST_VALUE_EQUAL( "M_SQRT2", double_out[14], CL_M_SQRT2 ) + TEST_VALUE_EQUAL( "M_SQRT1_2", double_out[15], CL_M_SQRT1_2 ) + + clReleaseMemObject(streams[0]); streams[0] = NULL; + clReleaseMemObject(streams[1]); streams[1] = NULL; + clReleaseKernel(kernel); kernel = NULL; + clReleaseProgram(program); program = NULL; + } + + error = clFinish(queue); + test_error(error, "clFinish failed"); + + return errors; +} + + +const char *kernel_constant_limits[] = { + "__kernel void test( __global int *intOut, __global float *floatOut ) \n" + "{\n" + " intOut[0] = isinf( MAXFLOAT ) ? 1 : 0;\n" + " intOut[1] = isnormal( MAXFLOAT ) ? 1 : 0;\n" + " intOut[2] = isnan( MAXFLOAT ) ? 1 : 0;\n" + " intOut[3] = sizeof( MAXFLOAT );\n" + " intOut[4] = ( MAXFLOAT == FLT_MAX ) ? 1 : 0;\n" + // " intOut[5] = ( MAXFLOAT == CL_FLT_MAX ) ? 1 : 0;\n" + " intOut[6] = ( MAXFLOAT == MAXFLOAT ) ? 1 : 0;\n" + " intOut[7] = ( MAXFLOAT == 0x1.fffffep127f ) ? 1 : 0;\n" + " floatOut[0] = MAXFLOAT;\n" + "}\n" +}; + +const char *kernel_constant_extended_limits[] = { + "__kernel void test( __global int *intOut, __global float *floatOut ) \n" + "{\n" + " intOut[0] = ( INFINITY == HUGE_VALF ) ? 1 : 0;\n" + " intOut[1] = sizeof( INFINITY );\n" + " intOut[2] = isinf( INFINITY ) ? 1 : 0;\n" + " intOut[3] = isnormal( INFINITY ) ? 1 : 0;\n" + " intOut[4] = isnan( INFINITY ) ? 1 : 0;\n" + " intOut[5] = ( INFINITY > MAXFLOAT ) ? 1 : 0;\n" + " intOut[6] = ( -INFINITY < -MAXFLOAT ) ? 1 : 0;\n" + " intOut[7] = ( ( MAXFLOAT + MAXFLOAT ) == INFINITY ) ? 1 : 0;\n" + " intOut[8] = ( nextafter( MAXFLOAT, INFINITY ) == INFINITY ) ? 1 : 0;\n" + " intOut[9] = ( nextafter( -MAXFLOAT, -INFINITY ) == -INFINITY ) ? 1 : 0;\n" + " intOut[10] = ( INFINITY == INFINITY ) ? 1 : 0;\n" + " intOut[11] = ( as_uint( INFINITY ) == 0x7f800000 ) ? 1 : 0;\n" + " floatOut[0] = INFINITY;\n" + "\n" + " intOut[12] = sizeof( HUGE_VALF );\n" + " intOut[13] = ( HUGE_VALF == INFINITY ) ? 1 : 0;\n" + " floatOut[1] = HUGE_VALF;\n" + "\n" + " intOut[14] = ( NAN == NAN ) ? 1 : 0;\n" + " intOut[15] = ( NAN != NAN ) ? 1 : 0;\n" + " intOut[16] = isnan( NAN ) ? 1 : 0;\n" + " intOut[17] = isinf( NAN ) ? 1 : 0;\n" + " intOut[18] = isnormal( NAN ) ? 1 : 0;\n" + " intOut[19] = ( ( as_uint( NAN ) & 0x7fffffff ) > 0x7f800000 ) ? 1 : 0;\n" + " intOut[20] = sizeof( NAN );\n" + " floatOut[2] = NAN;\n" + "\n" + " intOut[21] = isnan( INFINITY / INFINITY ) ? 1 : 0;\n" + " intOut[22] = isnan( INFINITY - INFINITY ) ? 1 : 0;\n" + " intOut[23] = isnan( 0.f / 0.f ) ? 1 : 0;\n" + " intOut[24] = isnan( INFINITY * 0.f ) ? 1 : 0;\n" + " intOut[25] = ( INFINITY == NAN ); \n" + " intOut[26] = ( -INFINITY == NAN ); \n" + " intOut[27] = ( INFINITY > NAN ); \n" + " intOut[28] = ( -INFINITY < NAN ); \n" + " intOut[29] = ( INFINITY != NAN ); \n" + " intOut[30] = ( NAN > INFINITY ); \n" + " intOut[31] = ( NAN < -INFINITY ); \n" + + "}\n" +}; + +const char *kernel_constant_double_limits[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global int *intOut, __global double *doubleOut ) \n" + "{\n" + " intOut[0] = sizeof( HUGE_VAL );\n" + " intOut[1] = ( HUGE_VAL == INFINITY ) ? 1 : 0;\n" + " intOut[2] = isinf( HUGE_VAL ) ? 1 : 0;\n" + " intOut[3] = isnormal( HUGE_VAL ) ? 1 : 0;\n" + " intOut[4] = isnan( HUGE_VAL ) ? 1 : 0;\n" + " intOut[5] = ( HUGE_VAL == HUGE_VALF ) ? 1 : 0;\n" + " intOut[6] = ( as_ulong( HUGE_VAL ) == 0x7ff0000000000000UL ) ? 1 : 0;\n" + " doubleOut[0] = HUGE_VAL;\n" + "}\n" +}; + +#define TEST_FLOAT_ASSERTION( a, msg, f ) if( !( a ) ) { log_error( "ERROR: Float constant failed requirement: %s (bitwise value is 0x%8.8x)\n", msg, *( (uint32_t *)&f ) ); return -1; } +#define TEST_DOUBLE_ASSERTION( a, msg, f ) if( !( a ) ) { log_error( "ERROR: Double constant failed requirement: %s (bitwise value is 0x%16.16llx)\n", msg, *( (uint64_t *)&f ) ); return -1; } + +int test_kernel_limit_constants(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + size_t threads[] = {1,1,1}; + clMemWrapper intStream, floatStream, doubleStream; + cl_int intOut[ 32 ]; + cl_float floatOut[ 3 ]; + cl_double doubleOut[ 1 ]; + + + /* Create some I/O streams */ + intStream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(intOut), NULL, &error ); + test_error( error, "Creating test array failed" ); + floatStream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(floatOut), NULL, &error ); + test_error( error, "Creating test array failed" ); + + // Stage 1: basic limits on MAXFLOAT + { + clProgramWrapper program; + clKernelWrapper kernel; + + if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_constant_limits, "test" ) != 0 ) + { + return -1; + } + + error = clSetKernelArg( kernel, 0, sizeof( intStream ), &intStream ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( floatStream ), &floatStream ); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, intStream, CL_TRUE, 0, sizeof(intOut), intOut, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, floatStream, CL_TRUE, 0, sizeof(floatOut), floatOut, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + // Test MAXFLOAT properties + TEST_FLOAT_ASSERTION( intOut[0] == 0, "isinf( MAXFLOAT ) = false", floatOut[0] ) + TEST_FLOAT_ASSERTION( intOut[1] == 1, "isnormal( MAXFLOAT ) = true", floatOut[0] ) + TEST_FLOAT_ASSERTION( intOut[2] == 0, "isnan( MAXFLOAT ) = false", floatOut[0] ) + TEST_FLOAT_ASSERTION( intOut[3] == 4, "sizeof( MAXFLOAT ) = 4", floatOut[0] ) + TEST_FLOAT_ASSERTION( intOut[4] == 1, "MAXFLOAT = FLT_MAX", floatOut[0] ) + TEST_FLOAT_ASSERTION( floatOut[0] == CL_FLT_MAX, "MAXFLOAT = CL_FLT_MAX", floatOut[0] ) + TEST_FLOAT_ASSERTION( intOut[6] == 1, "MAXFLOAT = MAXFLOAT", floatOut[0] ) + TEST_FLOAT_ASSERTION( floatOut[0] == MAKE_HEX_FLOAT( 0x1.fffffep127f, 0x1fffffeL, 103), "MAXFLOAT = 0x1.fffffep127f", floatOut[0] ) + } + + // Stage 2: INFINITY and NAN + char profileStr[128] = ""; + error = clGetDeviceInfo( deviceID, CL_DEVICE_PROFILE, sizeof( profileStr ), &profileStr, NULL ); + test_error( error, "Unable to run INFINITY/NAN tests (unable to get CL_DEVICE_PROFILE" ); + + bool testInfNan = true; + if( strcmp( profileStr, "EMBEDDED_PROFILE" ) == 0 ) + { + // We test if we're not an embedded profile, OR if the inf/nan flag in the config is set + cl_device_fp_config single = 0; + error = clGetDeviceInfo( deviceID, CL_DEVICE_SINGLE_FP_CONFIG, sizeof( single ), &single, NULL ); + test_error( error, "Unable to run INFINITY/NAN tests (unable to get FP_CONFIG bits)" ); + + if( ( single & CL_FP_INF_NAN ) == 0 ) + { + log_info( "Skipping INFINITY and NAN tests on embedded device (INF/NAN not supported on this device)" ); + testInfNan = false; + } + } + + if( testInfNan ) + { + clProgramWrapper program; + clKernelWrapper kernel; + + if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_constant_extended_limits, "test" ) != 0 ) + { + return -1; + } + + error = clSetKernelArg( kernel, 0, sizeof( intStream ), &intStream ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( floatStream ), &floatStream ); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, intStream, CL_TRUE, 0, sizeof(intOut), intOut, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, floatStream, CL_TRUE, 0, sizeof(floatOut), floatOut, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + TEST_FLOAT_ASSERTION( intOut[0] == 1, "INFINITY == HUGE_VALF", intOut[0] ) + TEST_FLOAT_ASSERTION( intOut[1] == 4, "sizeof( INFINITY ) == 4", intOut[1] ) + TEST_FLOAT_ASSERTION( intOut[2] == 1, "isinf( INFINITY ) == true", intOut[2] ) + TEST_FLOAT_ASSERTION( intOut[3] == 0, "isnormal( INFINITY ) == false", intOut[3] ) + TEST_FLOAT_ASSERTION( intOut[4] == 0, "isnan( INFINITY ) == false", intOut[4] ) + TEST_FLOAT_ASSERTION( intOut[5] == 1, "INFINITY > MAXFLOAT", intOut[5] ) + TEST_FLOAT_ASSERTION( intOut[6] == 1, "-INFINITY < -MAXFLOAT", intOut[6] ) + TEST_FLOAT_ASSERTION( intOut[7] == 1, "( MAXFLOAT + MAXFLOAT ) == INFINITY", intOut[7] ) + TEST_FLOAT_ASSERTION( intOut[8] == 1, "nextafter( MAXFLOAT, INFINITY ) == INFINITY", intOut[8] ) + TEST_FLOAT_ASSERTION( intOut[9] == 1, "nextafter( -MAXFLOAT, -INFINITY ) == -INFINITY", intOut[9] ) + TEST_FLOAT_ASSERTION( intOut[10] == 1, "INFINITY = INFINITY", intOut[10] ) + TEST_FLOAT_ASSERTION( intOut[11] == 1, "asuint( INFINITY ) == 0x7f800000", intOut[11] ) + TEST_FLOAT_ASSERTION( *( (uint32_t *)&floatOut[0] ) == 0x7f800000, "asuint( INFINITY ) == 0x7f800000", floatOut[0] ) + TEST_FLOAT_ASSERTION( floatOut[1] == INFINITY, "INFINITY == INFINITY", floatOut[1] ) + + TEST_FLOAT_ASSERTION( intOut[12] == 4, "sizeof( HUGE_VALF ) == 4", intOut[12] ) + TEST_FLOAT_ASSERTION( intOut[13] == 1, "HUGE_VALF == INFINITY", intOut[13] ) + TEST_FLOAT_ASSERTION( floatOut[1] == HUGE_VALF, "HUGE_VALF == HUGE_VALF", floatOut[1] ) + + TEST_FLOAT_ASSERTION( intOut[14] == 0, "(NAN == NAN) = false", intOut[14] ) + TEST_FLOAT_ASSERTION( intOut[15] == 1, "(NAN != NAN) = true", intOut[15] ) + TEST_FLOAT_ASSERTION( intOut[16] == 1, "isnan( NAN ) = true", intOut[16] ) + TEST_FLOAT_ASSERTION( intOut[17] == 0, "isinf( NAN ) = false", intOut[17] ) + TEST_FLOAT_ASSERTION( intOut[18] == 0, "isnormal( NAN ) = false", intOut[18] ) + TEST_FLOAT_ASSERTION( intOut[19] == 1, "( as_uint( NAN ) & 0x7fffffff ) > 0x7f800000", intOut[19] ) + TEST_FLOAT_ASSERTION( intOut[20] == 4, "sizeof( NAN ) = 4", intOut[20] ) + TEST_FLOAT_ASSERTION( ( *( (uint32_t *)&floatOut[2] ) & 0x7fffffff ) > 0x7f800000, "( as_uint( NAN ) & 0x7fffffff ) > 0x7f800000", floatOut[2] ) + + TEST_FLOAT_ASSERTION( intOut[ 21 ] == 1, "isnan( INFINITY / INFINITY ) = true", intOut[ 21 ] ) + TEST_FLOAT_ASSERTION( intOut[ 22 ] == 1, "isnan( INFINITY - INFINITY ) = true", intOut[ 22 ] ) + TEST_FLOAT_ASSERTION( intOut[ 23 ] == 1, "isnan( 0.f / 0.f ) = true", intOut[ 23 ] ) + TEST_FLOAT_ASSERTION( intOut[ 24 ] == 1, "isnan( INFINITY * 0.f ) = true", intOut[ 24 ] ) + TEST_FLOAT_ASSERTION( intOut[ 25 ] == 0, "( INFINITY == NAN ) = false", intOut[ 25 ] ) + TEST_FLOAT_ASSERTION( intOut[ 26 ] == 0, "(-INFINITY == NAN ) = false", intOut[ 26 ] ) + TEST_FLOAT_ASSERTION( intOut[ 27 ] == 0, "( INFINITY > NAN ) = false", intOut[ 27 ] ) + TEST_FLOAT_ASSERTION( intOut[ 28 ] == 0, "(-INFINITY < NAN ) = false", intOut[ 28 ] ) + TEST_FLOAT_ASSERTION( intOut[ 29 ] == 1, "( INFINITY != NAN ) = true", intOut[ 29 ] ) + TEST_FLOAT_ASSERTION( intOut[ 30 ] == 0, "( NAN < INFINITY ) = false", intOut[ 30 ] ) + TEST_FLOAT_ASSERTION( intOut[ 31 ] == 0, "( NAN > -INFINITY ) = false", intOut[ 31 ] ) + } + + // Stage 3: limits on HUGE_VAL (double) + if( !is_extension_available( deviceID, "cl_khr_fp64" ) ) + log_info( "Note: Skipping double HUGE_VAL tests (doubles unsupported on device)\n" ); + else + { + cl_device_fp_config config = 0; + error = clGetDeviceInfo( deviceID, CL_DEVICE_DOUBLE_FP_CONFIG, sizeof( config ), &config, NULL ); + test_error( error, "Unable to run INFINITY/NAN tests (unable to get double FP_CONFIG bits)" ); + + if( ( config & CL_FP_INF_NAN ) == 0 ) + log_info( "Skipping HUGE_VAL tests (INF/NAN not supported on this device)" ); + else + { + clProgramWrapper program; + clKernelWrapper kernel; + + if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_constant_double_limits, "test" ) != 0 ) + { + return -1; + } + + doubleStream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(doubleOut), NULL, &error ); + test_error( error, "Creating test array failed" ); + + error = clSetKernelArg( kernel, 0, sizeof( intStream ), &intStream ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( doubleStream ), &doubleStream ); + test_error( error, "Unable to set indexed kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, intStream, CL_TRUE, 0, sizeof(intOut), intOut, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, doubleStream, CL_TRUE, 0, sizeof(doubleOut), doubleOut, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + TEST_DOUBLE_ASSERTION( intOut[0] == 8, "sizeof( HUGE_VAL ) = 8", intOut[0] ) + TEST_DOUBLE_ASSERTION( intOut[1] == 1, "HUGE_VAL = INFINITY", intOut[1] ) + TEST_DOUBLE_ASSERTION( intOut[2] == 1, "isinf( HUGE_VAL ) = true", intOut[2] ) + TEST_DOUBLE_ASSERTION( intOut[3] == 0, "isnormal( HUGE_VAL ) = false", intOut[3] ) + TEST_DOUBLE_ASSERTION( intOut[4] == 0, "isnan( HUGE_VAL ) = false", intOut[4] ) + TEST_DOUBLE_ASSERTION( intOut[5] == 1, "HUGE_VAL = HUGE_VAL", intOut[5] ) + TEST_DOUBLE_ASSERTION( intOut[6] == 1, "as_ulong( HUGE_VAL ) = 0x7ff0000000000000UL", intOut[6] ) + TEST_DOUBLE_ASSERTION( *( (uint64_t *)&doubleOut[0] ) == 0x7ff0000000000000ULL, "as_ulong( HUGE_VAL ) = 0x7ff0000000000000UL", doubleOut[0] ) + } + } + + return 0; +} + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_pointercast.c b/test_conformance/compatibility/test_conformance/basic/test_pointercast.c new file mode 100644 index 00000000..88a19aad --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_pointercast.c @@ -0,0 +1,140 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +static const char *pointer_cast_kernel_code = +"__kernel void test_pointer_cast(__global unsigned char *src, __global unsigned int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +" __global unsigned int *p = (__global unsigned int *)src;\n" +"\n" +" dst[tid] = p[tid];\n" +"\n" +"}\n"; + + +int +verify_pointer_cast(unsigned char *inptr, unsigned int *outptr, int n) +{ + unsigned int *p = (unsigned int *)inptr; + int i; + cl_uint r; + + for (i=0; i + +// Test __FILE__, __LINE__, __OPENCL_VERSION__, __OPENCL_C_VERSION__, __ENDIAN_LITTLE__, __ROUNDING_MODE__, __IMAGE_SUPPORT__, __FAST_RELAXED_MATH__ +// __kernel_exec + +const char *preprocessor_test = { + "#line 2 \"%s\"\n" + "__kernel void test( __global int *results, __global char *outFileString, __global char *outRoundingString )\n" + "{\n" + + // Integer preprocessor macros + "#ifdef __IMAGE_SUPPORT__\n" + " results[0] = __IMAGE_SUPPORT__;\n" + "#else\n" + " results[0] = 0xf00baa;\n" + "#endif\n" + + "#ifdef __ENDIAN_LITTLE__\n" + " results[1] = __ENDIAN_LITTLE__;\n" + "#else\n" + " results[1] = 0xf00baa;\n" + "#endif\n" + + "#ifdef __OPENCL_VERSION__\n" + " results[2] = __OPENCL_VERSION__;\n" + "#else\n" + " results[2] = 0xf00baa;\n" + "#endif\n" + + "#ifdef __OPENCL_C_VERSION__\n" + " results[3] = __OPENCL_C_VERSION__;\n" + "#else\n" + " results[3] = 0xf00baa;\n" + "#endif\n" + + "#ifdef __LINE__\n" + " results[4] = __LINE__;\n" + "#else\n" + " results[4] = 0xf00baa;\n" + "#endif\n" + +#if 0 // Removed by Affie's request 2/24 + "#ifdef __FAST_RELAXED_MATH__\n" + " results[5] = __FAST_RELAXED_MATH__;\n" + "#else\n" + " results[5] = 0xf00baa;\n" + "#endif\n" +#endif + + "#ifdef __kernel_exec\n" + " results[6] = 1;\n" // By spec, we can only really evaluate that it is defined, not what it expands to + "#else\n" + " results[6] = 0xf00baa;\n" + "#endif\n" + + // String preprocessor macros. Technically, there are strings in OpenCL, but not really. + "#ifdef __FILE__\n" + " int i;\n" + " constant char *f = \"\" __FILE__;\n" + " for( i = 0; f[ i ] != 0 && i < 512; i++ )\n" + " outFileString[ i ] = f[ i ];\n" + " outFileString[ i ] = 0;\n" + "#else\n" + " outFileString[ 0 ] = 0;\n" + "#endif\n" + + "}\n" + }; + +int test_kernel_preprocessor_macros(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 3 ]; + + int error; + size_t threads[] = {1,1,1}; + + cl_int results[ 7 ]; + cl_char fileString[ 512 ] = "", roundingString[ 128 ] = ""; + char programSource[4096]; + char curFileName[512]; + char *programPtr = programSource; + int i = 0; + snprintf(curFileName, 512, "%s", __FILE__); +#ifdef _WIN32 + // Replace "\" with "\\" + while(curFileName[i] != '\0') { + if (curFileName[i] == '\\') { + int j = i + 1; + char prev = '\\'; + while (curFileName[j - 1] != '\0') { + char tmp = curFileName[j]; + curFileName[j] = prev; + prev = tmp; + j++; + } + i++; + } + i++; + } +#endif + sprintf(programSource,preprocessor_test,curFileName); + + // Create the kernel + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "test" ) != 0 ) + { + return -1; + } + + /* Create some I/O streams */ + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(results), NULL, &error); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(fileString), NULL, &error); + test_error( error, "Creating test array failed" ); + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(roundingString), NULL, &error); + test_error( error, "Creating test array failed" ); + + // Set up and run + for( int i = 0; i < 3; i++ ) + { + error = clSetKernelArg( kernel, i, sizeof( streams[i] ), &streams[i] ); + test_error( error, "Unable to set indexed kernel arguments" ); + } + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + error = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, sizeof(results), results, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(fileString), fileString, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + error = clEnqueueReadBuffer( queue, streams[2], CL_TRUE, 0, sizeof(roundingString), roundingString, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + + /////// Check the integer results + + // We need to check these values against what we know is supported on the device + if( checkForImageSupport( deviceID ) == 0 ) + { + // If images are supported, the constant should have been defined to the value 1 + if( results[ 0 ] == 0xf00baa ) + { + log_error( "ERROR: __IMAGE_SUPPORT__ undefined even though images are supported\n" ); + return -1; + } + else if( results[ 0 ] != 1 ) + { + log_error( "ERROR: __IMAGE_SUPPORT__ defined, but to the wrong value (defined as %d, spec states it should be 1)\n", (int)results[ 0 ] ); + return -1; + } + } + else + { + // If images aren't supported, the constant should be undefined + if( results[ 0 ] != 0xf00baa ) + { + log_error( "ERROR: __IMAGE_SUPPORT__ defined to value %d even though images aren't supported", (int)results[ 0 ] ); + return -1; + } + } + + // __ENDIAN_LITTLE__ is similar to __IMAGE_SUPPORT__: 1 if it's true, undefined if it isn't + cl_bool deviceIsLittleEndian; + error = clGetDeviceInfo( deviceID, CL_DEVICE_ENDIAN_LITTLE, sizeof( deviceIsLittleEndian ), &deviceIsLittleEndian, NULL ); + test_error( error, "Unable to get endian property of device to validate against" ); + + if( deviceIsLittleEndian ) + { + if( results[ 1 ] == 0xf00baa ) + { + log_error( "ERROR: __ENDIAN_LITTLE__ undefined even though the device is little endian\n" ); + return -1; + } + else if( results[ 1 ] != 1 ) + { + log_error( "ERROR: __ENDIAN_LITTLE__ defined, but to the wrong value (defined as %d, spec states it should be 1)\n", (int)results[ 1 ] ); + return -1; + } + } + else + { + if( results[ 1 ] != 0xf00baa ) + { + log_error( "ERROR: __ENDIAN_LITTLE__ defined to value %d even though the device is not little endian (should be undefined per spec)", (int)results[ 1 ] ); + return -1; + } + } + + // __OPENCL_VERSION__ + if( results[ 2 ] == 0xf00baa ) + { + log_error( "ERROR: Kernel preprocessor __OPENCL_VERSION__ undefined!" ); + return -1; + } + + // The OpenCL version reported by the macro reports the feature level supported by the compiler. Since + // this doesn't directly match any property we can query, we just check to see if it's a sane value + char versionBuffer[ 128 ]; + error = clGetDeviceInfo( deviceID, CL_DEVICE_VERSION, sizeof( versionBuffer ), versionBuffer, NULL ); + test_error( error, "Unable to get device's version to validate against" ); + + // We need to parse to get the version number to compare against + char *p1, *p2, *p3; + for( p1 = versionBuffer; ( *p1 != 0 ) && !isdigit( *p1 ); p1++ ) + ; + for( p2 = p1; ( *p2 != 0 ) && ( *p2 != '.' ); p2++ ) + ; + for( p3 = p2; ( *p3 != 0 ) && ( *p3 != ' ' ); p3++ ) + ; + + if( p2 == p3 ) + { + log_error( "ERROR: Unable to verify OpenCL version string (platform string is incorrect format)\n" ); + return -1; + } + *p2 = 0; + *p3 = 0; + int major = atoi( p1 ); + int minor = atoi( p2 + 1 ); + int realVersion = ( major * 100 ) + ( minor * 10 ); + if( ( results[ 2 ] < 100 ) || ( results[ 2 ] > realVersion ) ) + { + log_error( "ERROR: Kernel preprocessor __OPENCL_VERSION__ does not make sense w.r.t. device's version string! " + "(preprocessor states %d, real version is %d (%d.%d))\n", results[ 2 ], realVersion, major, minor ); + return -1; + } + + // __OPENCL_C_VERSION__ + if( results[ 3 ] == 0xf00baa ) + { + log_error( "ERROR: Kernel preprocessor __OPENCL_C_VERSION__ undefined!\n" ); + return -1; + } + + // The OpenCL C version reported by the macro reports the OpenCL C supported by the compiler for this OpenCL device. + char cVersionBuffer[ 128 ]; + error = clGetDeviceInfo( deviceID, CL_DEVICE_OPENCL_C_VERSION, sizeof( cVersionBuffer ), cVersionBuffer, NULL ); + test_error( error, "Unable to get device's OpenCL C version to validate against" ); + + // We need to parse to get the version number to compare against + for( p1 = cVersionBuffer; ( *p1 != 0 ) && !isdigit( *p1 ); p1++ ) + ; + for( p2 = p1; ( *p2 != 0 ) && ( *p2 != '.' ); p2++ ) + ; + for( p3 = p2; ( *p3 != 0 ) && ( *p3 != ' ' ); p3++ ) + ; + + if( p2 == p3 ) + { + log_error( "ERROR: Unable to verify OpenCL C version string (platform string is incorrect format)\n" ); + return -1; + } + *p2 = 0; + *p3 = 0; + major = atoi( p1 ); + minor = atoi( p2 + 1 ); + realVersion = ( major * 100 ) + ( minor * 10 ); + if( ( results[ 3 ] < 100 ) || ( results[ 3 ] > realVersion ) ) + { + log_error( "ERROR: Kernel preprocessor __OPENCL_C_VERSION__ does not make sense w.r.t. device's version string! " + "(preprocessor states %d, real version is %d (%d.%d))\n", results[ 2 ], realVersion, major, minor ); + return -1; + } + + // __LINE__ + if( results[ 4 ] == 0xf00baa ) + { + log_error( "ERROR: Kernel preprocessor __LINE__ undefined!" ); + return -1; + } + + // This is fun--we get to search for where __LINE__ actually is so we know what line it should define to! + // Note: it shows up twice, once for the #ifdef, and the other for the actual result output + const char *linePtr = strstr( preprocessor_test, "__LINE__" ); + if( linePtr == NULL ) + { + log_error( "ERROR: Nonsensical NULL pointer encountered!" ); + return -2; + } + linePtr = strstr( linePtr + strlen( "__LINE__" ), "__LINE__" ); + if( linePtr == NULL ) + { + log_error( "ERROR: Nonsensical NULL pointer encountered!" ); + return -2; + } + + // Now count how many carriage returns are before the string + const char *retPtr = strchr( preprocessor_test, '\n' ); + int retCount = 1; + for( ; ( retPtr < linePtr ) && ( retPtr != NULL ); retPtr = strchr( retPtr + 1, '\n' ) ) + retCount++; + + if( retCount != results[ 4 ] ) + { + log_error( "ERROR: Kernel preprocessor __LINE__ does not expand to the actual line number! (expanded to %d, but was on line %d)\n", + results[ 4 ], retCount ); + return -1; + } + +#if 0 // Removed by Affie's request 2/24 + // __FAST_RELAXED_MATH__ + // Since create_single_kernel_helper does NOT define -cl-fast-relaxed-math, this should be undefined + if( results[ 5 ] != 0xf00baa ) + { + log_error( "ERROR: Kernel preprocessor __FAST_RELAXED_MATH__ defined even though build option was not used (should be undefined)\n" ); + return -1; + } +#endif + + // __kernel_exec + // We can ONLY check to verify that it is defined + if( results[ 6 ] == 0xf00baa ) + { + log_error( "ERROR: Kernel preprocessor __kernel_exec must be defined\n" ); + return -1; + } + + //// String preprocessors + + // Since we provided the program directly, __FILE__ should compile to "". + if( fileString[ 0 ] == 0 ) + { + log_error( "ERROR: Kernel preprocessor __FILE__ undefined!\n" ); + return -1; + } + else if( strncmp( (char *)fileString, __FILE__, 512 ) != 0 ) + { + log_info( "WARNING: __FILE__ defined, but to an unexpected value (%s)\n\tShould be: \"%s\"", fileString, __FILE__ ); + return -1; + } + + +#if 0 // Removed by Affie's request 2/24 + // One more try through: try with -cl-fast-relaxed-math to make sure the appropriate preprocessor gets defined + clProgramWrapper programB = clCreateProgramWithSource( context, 1, preprocessor_test, NULL, &error ); + test_error( error, "Unable to create test program" ); + + // Try compiling + error = clBuildProgram( programB, 1, &deviceID, "-cl-fast-relaxed-math", NULL, NULL ); + test_error( error, "Unable to build program" ); + + // Create a kernel again to run against + clKernelWrapper kernelB = clCreateKernel( programB, "test", &error ); + test_error( error, "Unable to create testing kernel" ); + + // Set up and run + for( int i = 0; i < 3; i++ ) + { + error = clSetKernelArg( kernelB, i, sizeof( streams[i] ), &streams[i] ); + test_error( error, "Unable to set indexed kernel arguments" ); + } + + error = clEnqueueNDRangeKernel( queue, kernelB, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Kernel execution failed" ); + + // Only need the one read + error = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, sizeof(results), results, 0, NULL, NULL ); + test_error( error, "Unable to get result data" ); + + // We only need to check the one result this time + if( results[ 5 ] == 0xf00baa ) + { + log_error( "ERROR: Kernel preprocessor __FAST_RELAXED_MATH__ not defined!\n" ); + return -1; + } + else if( results[ 5 ] != 1 ) + { + log_error( "ERROR: Kernel preprocessor __FAST_RELAXED_MATH__ not defined to 1 (was %d)\n", results[ 5 ] ); + return -1; + } +#endif + + return 0; +} + diff --git a/test_conformance/compatibility/test_conformance/basic/test_readimage.c b/test_conformance/compatibility/test_conformance/basic/test_readimage.c new file mode 100644 index 00000000..e9de33c7 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_readimage.c @@ -0,0 +1,244 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +static const char *bgra8888_kernel_code = +"\n" +"__kernel void test_bgra8888(read_only image2d_t srcimg, __global uchar4 *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y)) * 255.0f;\n" +" dst[indx] = convert_uchar4_rte(color.zyxw);\n" +"\n" +"}\n"; + + +static const char *rgba8888_kernel_code = +"\n" +"__kernel void test_rgba8888(read_only image2d_t srcimg, __global uchar4 *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y)) * 255.0f;\n" +" dst[indx] = convert_uchar4_rte(color);\n" +"\n" +"}\n"; + + +static unsigned char * +generate_8888_image(int w, int h, MTdata d) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * 4); + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +static const char *bgra8888_kernel_code = +"\n" +"__kernel void test_bgra8888(read_only image3d_t srcimg, __global float4 *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int tid_z = get_global_id(2);\n" +" int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0));\n" +" dst[indx].x = color.z;\n" +" dst[indx].y = color.y;\n" +" dst[indx].z = color.x;\n" +" dst[indx].w = color.w;\n" +"\n" +"}\n"; + + +static const char *rgba8888_kernel_code = +"\n" +"__kernel void test_rgba8888(read_only image3d_t srcimg, __global float4 *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int tid_z = get_global_id(2);\n" +" int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0));\n" +" //indx *= 4;\n" +" dst[indx].x = color.x;\n" +" dst[indx].y = color.y;\n" +" dst[indx].z = color.z;\n" +" dst[indx].w = color.w;\n" +"\n" +"}\n"; + + +static unsigned char * +generate_3d_image8(int w, int h, int d, MTdata data) +{ + unsigned char *ptr = (unsigned char*)malloc(w * h * d * 4); + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + + +static const char *rgbaFFFF_kernel_code = +"__kernel void test_rgbaFFFF(read_only image3d_t srcimg, __global float *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int tid_z = get_global_id(2);\n" +" int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0));\n" +" indx *= 4;\n" +" dst[indx+0] = color.x;\n" +" dst[indx+1] = color.y;\n" +" dst[indx+2] = color.z;\n" +" dst[indx+3] = color.w;\n" +"\n" +"}\n"; + + +static float * +generate_float_image(int w, int h, int d, MTdata data) +{ + float *ptr = (float*)malloc(w * h * d * 4 * sizeof(float)); + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +static const char *rgba16_kernel_code = +"__kernel void test_rgba16(read_only image3d_t srcimg, __global ushort4 *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int tid_z = get_global_id(2);\n" +" int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0));\n" +" ushort4 dst_write;\n" +" dst_write.x = convert_ushort_rte(color.x * 65535.0f);\n" +" dst_write.y = convert_ushort_rte(color.y * 65535.0f);\n" +" dst_write.z = convert_ushort_rte(color.z * 65535.0f);\n" +" dst_write.w = convert_ushort_rte(color.w * 65535.0f);\n" +" dst[indx] = dst_write;\n" +"\n" +"}\n"; + + +static unsigned short * +generate_16bit_image(int w, int h, int d, MTdata data) +{ + unsigned short *ptr = (cl_ushort*)malloc(w * h * d * 4 * sizeof(cl_ushort)); + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + + +static const char *rgbaFFFF_kernel_code = +"__kernel void test_rgbaFFFF(read_only image2d_t srcimg, __global float *dst, sampler_t smp)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, smp, (int2)(tid_x, tid_y));\n" +" indx *= 4;\n" +" dst[indx+0] = color.x;\n" +" dst[indx+1] = color.y;\n" +" dst[indx+2] = color.z;\n" +" dst[indx+3] = color.w;\n" +"\n" +"}\n"; + + +static float * +generate_float_image(int w, int h, MTdata d) +{ + float *ptr = (float*)malloc(w * h * 4 * sizeof(float)); + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +static const char *rgba16_kernel_code = +"__kernel void test_rgba16(read_only image2d_t srcimg, __global ushort4 *dst, sampler_t smp)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, smp, (int2)(tid_x, tid_y));\n" +" ushort4 dst_write;\n" +" dst_write.x = convert_ushort_rte(color.x * 65535.0f);\n" +" dst_write.y = convert_ushort_rte(color.y * 65535.0f);\n" +" dst_write.z = convert_ushort_rte(color.z * 65535.0f);\n" +" dst_write.w = convert_ushort_rte(color.w * 65535.0f);\n" +" dst[indx] = dst_write;\n" +"\n" +"}\n"; + + +static unsigned short * +generate_16bit_image(int w, int h, MTdata d) +{ + cl_ushort *ptr = (cl_ushort*)malloc(w * h * 4 * sizeof(cl_ushort)); + int i; + + for (i=0; i +#include +#include +#include +#include "procs.h" + + + +cl_int get_type_size( cl_context context, cl_command_queue queue, const char *type, cl_ulong *size ) +{ + const char *sizeof_kernel_code[4] = + { + "", /* optional pragma string */ + "__kernel __attribute__((reqd_work_group_size(1,1,1))) void test_sizeof(__global uint *dst) \n" + "{\n" + " dst[0] = (uint) sizeof( ", type, " );\n" + "}\n" + }; + + cl_program p; + cl_kernel k; + cl_mem m; + cl_uint temp; + + + if (!strncmp(type, "double", 6)) + { + sizeof_kernel_code[0] = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"; + } + else if (!strncmp(type, "half", 4)) + { + sizeof_kernel_code[0] = "#pragma OPENCL EXTENSION cl_khr_fp16 : enable\n"; + } + + cl_int err = create_single_kernel_helper( context, &p, &k, 4, sizeof_kernel_code, "test_sizeof" ); + if( err ) + return err; + + m = clCreateBuffer( context, CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, sizeof( cl_ulong ), size, &err ); + if( NULL == m ) + { + clReleaseProgram( p ); + clReleaseKernel( k ); + log_error("\nclCreateBuffer FAILED\n"); + return err; + } + + err = clSetKernelArg( k, 0, sizeof( cl_mem ), &m ); + if( err ) + { + clReleaseProgram( p ); + clReleaseKernel( k ); + clReleaseMemObject( m ); + log_error("\nclSetKernelArg FAILED\n"); + return err; + } + + err = clEnqueueTask( queue, k, 0, NULL, NULL ); + clReleaseProgram( p ); + clReleaseKernel( k ); + if( err ) + { + clReleaseMemObject( m ); + log_error( "\nclEnqueueTask FAILED\n" ); + return err; + } + + err = clEnqueueReadBuffer( queue, m, CL_TRUE, 0, sizeof( cl_uint ), &temp, 0, NULL, NULL ); + clReleaseMemObject( m ); + if( err ) + log_error( "\nclEnqueueReadBuffer FAILED\n" ); + + *size = (cl_ulong) temp; + + return err; +} + +typedef struct size_table +{ + const char *name; + cl_ulong size; + cl_ulong cl_size; +}size_table; + +const size_table scalar_table[] = +{ + // Fixed size entries from table 6.1 + { "char", 1, sizeof( cl_char ) }, + { "uchar", 1, sizeof( cl_uchar) }, + { "unsigned char", 1, sizeof( cl_uchar) }, + { "short", 2, sizeof( cl_short) }, + { "ushort", 2, sizeof( cl_ushort) }, + { "unsigned short", 2, sizeof( cl_ushort) }, + { "int", 4, sizeof( cl_int ) }, + { "uint", 4, sizeof( cl_uint) }, + { "unsigned int", 4, sizeof( cl_uint) }, + { "float", 4, sizeof( cl_float) }, + { "long", 8, sizeof( cl_long ) }, + { "ulong", 8, sizeof( cl_ulong) }, + { "unsigned long", 8, sizeof( cl_ulong) } +}; + +const size_table vector_table[] = +{ + // Fixed size entries from table 6.1 + { "char", 1, sizeof( cl_char ) }, + { "uchar", 1, sizeof( cl_uchar) }, + { "short", 2, sizeof( cl_short) }, + { "ushort", 2, sizeof( cl_ushort) }, + { "int", 4, sizeof( cl_int ) }, + { "uint", 4, sizeof( cl_uint) }, + { "float", 4, sizeof( cl_float) }, + { "long", 8, sizeof( cl_long ) }, + { "ulong", 8, sizeof( cl_ulong) } +}; + +const char *ptr_table[] = +{ + "void*", + "size_t", + "sizeof(int)", // check return type of sizeof + "ptrdiff_t" +}; + +const char *other_types[] = +{ + "event_t", + "image2d_t", + "image3d_t", + "sampler_t" +}; + +static int IsPowerOfTwo( cl_ulong x ){ return 0 == (x & (x-1)); } + +int test_sizeof(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + size_t i, j; + cl_ulong test; + cl_uint ptr_size = CL_UINT_MAX; + cl_int err = CL_SUCCESS; + + // Check address space size + err = clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS, sizeof(ptr_size), &ptr_size, NULL); + if( err || ptr_size > 64) + { + log_error( "FAILED: Unable to get CL_DEVICE_ADDRESS_BITS for device %p\n", device ); + return -1; + } + log_info( "\tCL_DEVICE_ADDRESS_BITS = %u\n", ptr_size ); + ptr_size /= 8; + + // Test standard scalar sizes + for( i = 0; i < sizeof( scalar_table ) / sizeof( scalar_table[0] ); i++ ) + { + if( ! gHasLong && + (0 == strcmp(scalar_table[i].name, "long") || + 0 == strcmp(scalar_table[i].name, "ulong") || + 0 == strcmp(scalar_table[i].name, "unsigned long"))) + { + log_info("\nLongs are not supported by this device. Skipping test.\t"); + continue; + } + + test = CL_ULONG_MAX; + err = get_type_size( context, queue, scalar_table[i].name, &test ); + if( err ) + return err; + if( test != scalar_table[i].size ) + { + log_error( "\nFAILED: Type %s has size %lld, but expected size %lld!\n", scalar_table[i].name, test, scalar_table[i].size ); + return -1; + } + if( test != scalar_table[i].cl_size ) + { + log_error( "\nFAILED: Type %s has size %lld, but cl_ size is %lld!\n", scalar_table[i].name, test, scalar_table[i].cl_size ); + return -2; + } + log_info( "%16s", scalar_table[i].name ); + } + log_info( "\n" ); + + // Test standard vector sizes + for( j = 2; j <= 16; j *= 2 ) + { + // For each vector size, iterate through types + for( i = 0; i < sizeof( vector_table ) / sizeof( vector_table[0] ); i++ ) + { + if( !gHasLong && + (0 == strcmp(vector_table[i].name, "long") || + 0 == strcmp(vector_table[i].name, "ulong"))) + { + log_info("\nLongs are not supported by this device. Skipping test.\t"); + continue; + } + + char name[32]; + sprintf( name, "%s%ld", vector_table[i].name, j ); + + test = CL_ULONG_MAX; + err = get_type_size( context, queue, name, &test ); + if( err ) + return err; + if( test != j * vector_table[i].size ) + { + log_error( "\nFAILED: Type %s has size %lld, but expected size %lld!\n", name, test, j * vector_table[i].size ); + return -1; + } + if( test != j * vector_table[i].cl_size ) + { + log_error( "\nFAILED: Type %s has size %lld, but cl_ size is %lld!\n", name, test, j * vector_table[i].cl_size ); + return -2; + } + log_info( "%16s", name ); + } + log_info( "\n" ); + } + + //Check that pointer sizes are correct + for( i = 0; i < sizeof( ptr_table ) / sizeof( ptr_table[0] ); i++ ) + { + test = CL_ULONG_MAX; + err = get_type_size( context, queue, ptr_table[i], &test ); + if( err ) + return err; + if( test != ptr_size ) + { + log_error( "\nFAILED: Type %s has size %lld, but expected size %u!\n", ptr_table[i], test, ptr_size ); + return -1; + } + log_info( "%16s", ptr_table[i] ); + } + + // Check that intptr_t is large enough + test = CL_ULONG_MAX; + err = get_type_size( context, queue, "intptr_t", &test ); + if( err ) + return err; + if( test < ptr_size ) + { + log_error( "\nFAILED: intptr_t has size %lld, but must be at least %u!\n", test, ptr_size ); + return -1; + } + if( ! IsPowerOfTwo( test ) ) + { + log_error( "\nFAILED: sizeof(intptr_t) is %lld, but must be a power of two!\n", test ); + return -2; + } + log_info( "%16s", "intptr_t" ); + + // Check that uintptr_t is large enough + test = CL_ULONG_MAX; + err = get_type_size( context, queue, "uintptr_t", &test ); + if( err ) + return err; + if( test < ptr_size ) + { + log_error( "\nFAILED: uintptr_t has size %lld, but must be at least %u!\n", test, ptr_size ); + return -1; + } + if( ! IsPowerOfTwo( test ) ) + { + log_error( "\nFAILED: sizeof(uintptr_t) is %lld, but must be a power of two!\n", test ); + return -2; + } + log_info( "%16s\n", "uintptr_t" ); + + //Check that other types are powers of two + for( i = 0; i < sizeof( other_types ) / sizeof( other_types[0] ); i++ ) + { + if( 0 == strcmp(other_types[i], "image2d_t") && + checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) + { + log_info("\nimages are not supported by this device. Skipping test.\t"); + continue; + } + + if( gIsEmbedded && + 0 == strcmp(other_types[i], "image3d_t") && + checkFor3DImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) + { + log_info("\n3D images are not supported by this device. Skipping test.\t"); + continue; + } + + if( 0 == strcmp(other_types[i], "sampler_t") && + checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) + { + log_info("\nimages are not supported by this device. Skipping test.\t"); + continue; + } + + test = CL_ULONG_MAX; + err = get_type_size( context, queue, other_types[i], &test ); + if( err ) + return err; + if( ! IsPowerOfTwo( test ) ) + { + log_error( "\nFAILED: Type %s has size %lld, which is not a power of two (section 6.1.5)!\n", other_types[i], test ); + return -1; + } + log_info( "%16s", other_types[i] ); + } + log_info( "\n" ); + + + //Check double + if( is_extension_available( device, "cl_khr_fp64" ) ) + { + log_info( "\tcl_khr_fp64:" ); + test = CL_ULONG_MAX; + err = get_type_size( context, queue, "double", &test ); + if( err ) + return err; + if( test != 8 ) + { + log_error( "\nFAILED: double has size %lld, but must be 8!\n", test ); + return -1; + } + log_info( "%16s", "double" ); + + // Test standard vector sizes + for( j = 2; j <= 16; j *= 2 ) + { + char name[32]; + sprintf( name, "double%ld", j ); + + test = CL_ULONG_MAX; + err = get_type_size( context, queue, name, &test ); + if( err ) + return err; + if( test != 8*j ) + { + log_error( "\nFAILED: %s has size %lld, but must be %ld!\n", name, test, 8 * j); + return -1; + } + log_info( "%16s", name ); + } + log_info( "\n" ); + } + + //Check half + if( is_extension_available( device, "cl_khr_fp16" ) ) + { + log_info( "\tcl_khr_fp16:" ); + test = CL_ULONG_MAX; + err = get_type_size( context, queue, "half", &test ); + if( err ) + return err; + if( test != 2 ) + { + log_error( "\nFAILED: half has size %lld, but must be 2!\n", test ); + return -1; + } + log_info( "%16s", "half" ); + + // Test standard vector sizes + for( j = 2; j <= 16; j *= 2 ) + { + char name[32]; + sprintf( name, "half%ld", j ); + + test = CL_ULONG_MAX; + err = get_type_size( context, queue, name, &test ); + if( err ) + return err; + if( test != 2*j ) + { + log_error( "\nFAILED: %s has size %lld, but must be %ld!\n", name, test, 2 * j); + return -1; + } + log_info( "%16s", name ); + } + log_info( "\n" ); + } + + return err; +} + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_vec_type_hint.c b/test_conformance/compatibility/test_conformance/basic/test_vec_type_hint.c new file mode 100644 index 00000000..d3b5fa76 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_vec_type_hint.c @@ -0,0 +1,97 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" + + +static const char *sample_kernel = { + "%s\n" // optional pragma string + "__kernel __attribute__((vec_type_hint(%s%s))) void sample_test(__global int *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = src[tid];\n" + "\n" + "}\n" +}; + +int test_vec_type_hint(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + int vec_type_index, vec_size_index; + + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble }; + const char *size_names[] = {"", "2", "4", "8", "16"}; + char *program_source; + + program_source = (char*)malloc(sizeof(char)*4096); + + for (vec_type_index=0; vec_type_index<10; vec_type_index++) { + if (vecType[vec_type_index] == kDouble) { + if (!is_extension_available(deviceID, "cl_khr_fp64")) { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + continue; + } + log_info("Testing doubles.\n"); + } + + for (vec_size_index=0; vec_size_index<5; vec_size_index++) { + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper in, out; + size_t global[] = {1,1,1}; + + log_info("Testing __attribute__((vec_type_hint(%s%s))...\n", get_explicit_type_name(vecType[vec_type_index]), size_names[vec_size_index]); + + program_source[0] = '\0'; + sprintf(program_source, sample_kernel, + (vecType[vec_type_index] == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name(vecType[vec_type_index]), size_names[vec_size_index]); + + error = create_single_kernel_helper( context, &program, &kernel, 1, (const char**)&program_source, "sample_test" ); + if( error != 0 ) + return error; + + in = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(cl_int)*10, NULL, &error); + test_error(error, "clCreateBuffer failed"); + out = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(cl_int)*10, NULL, &error); + test_error(error, "clCreateBuffer failed"); + + error = clSetKernelArg(kernel, 0, sizeof(in), &in); + test_error(error, "clSetKernelArg failed"); + error = clSetKernelArg(kernel, 1, sizeof(out), &out); + test_error(error, "clSetKernelArg failed"); + + error = clEnqueueNDRangeKernel(queue, kernel, 3, NULL, global, NULL, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + error = clFinish(queue); + test_error(error, "clFinish failed"); + } + } + + free(program_source); + + return 0; +} diff --git a/test_conformance/compatibility/test_conformance/basic/test_vector_creation.cpp b/test_conformance/compatibility/test_conformance/basic/test_vector_creation.cpp new file mode 100644 index 00000000..9ab0103a --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_vector_creation.cpp @@ -0,0 +1,406 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/errorHelpers.h" + + + + +#define DEBUG 0 +#define DEPTH 16 +// Limit the maximum code size for any given kernel. +#define MAX_CODE_SIZE (1024*32) + +const int sizes[] = {1, 2, 3, 4, 8, 16, -1, -1, -1, -1}; +const char *size_names[] = {"", "2", "3", "4", "8", "16" , "!!a", "!!b", "!!c", "!!d"}; + +// Creates a kernel by enumerating all possible ways of building the vector out of vloads +// skip_to_results will skip results up to a given number. If the amount of code generated +// is greater than MAX_CODE_SIZE, this function will return the number of results used, +// which can then be used as the skip_to_result value to continue where it left off. +int create_kernel(ExplicitType type, int output_size, char *program, int *number_of_results, int skip_to_result) { + + int number_of_sizes; + + switch (output_size) { + case 1: + number_of_sizes = 1; + break; + case 2: + number_of_sizes = 2; + break; + case 3: + number_of_sizes = 3; + break; + case 4: + number_of_sizes = 4; + break; + case 8: + number_of_sizes = 5; + break; + case 16: + number_of_sizes = 6; + break; + default: + log_error("Invalid size: %d\n", output_size); + return -1; + } + + int total_results = 0; + int current_result = 0; + int total_vloads = 0; + int total_program_length = 0; + int aborted_due_to_size = 0; + + if (skip_to_result < 0) + skip_to_result = 0; + + // The line of code for the vector creation + char line[1024]; + // Keep track of what size vector we are using in each position so we can iterate through all fo them + int pos[DEPTH]; + int max_size = output_size; + if (DEBUG > 1) log_info("max_size: %d\n", max_size); + + program[0] = '\0'; + sprintf(program, "%s\n__kernel void test_vector_creation(__global %s *src, __global %s%s *result) {\n", + type == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name(type), get_explicit_type_name(type), ( number_of_sizes == 3 ) ? "" : size_names[number_of_sizes-1]); + total_program_length += (int)strlen(program); + + char storePrefix[ 128 ], storeSuffix[ 128 ]; + + // Start out trying sizes 1,1,1,1,1... + for (int i=0; i 1) { + log_info("pos size[] = ["); + for (int k=0; k 1) log_info("vloads: %d, size_so_far:%d\n", vloads, size_so_far); + + // If they did not fit the required size exactly it is too long, so there is no point in checking any other combinations + // of the sizes to the right. Prune them from the search. + if (size_so_far != max_size) { + // Zero all the sizes to the right + for (int k=vloads+1; k=0; d--) { + pos[d]++; + if (pos[d] >= number_of_sizes) { + pos[d] = 0; + if (d == 0) { + // If we rolled over then we are done + done = 1; + break; + } + } else { + break; + } + } + // Go on to the next size since this one (and all others "under" it) didn't fit + continue; + } + + + // Generate the actual load line if we are building this part + line[0]= '\0'; + if (skip_to_result == 0 || total_results >= skip_to_result) { + if( number_of_sizes == 3 ) + { + sprintf( storePrefix, "vstore3( " ); + sprintf( storeSuffix, ", %d, result )", current_result ); + } + else + { + sprintf( storePrefix, "result[%d] = ", current_result ); + storeSuffix[ 0 ] = 0; + } + + sprintf(line, "\t%s(%s%d)(", storePrefix, get_explicit_type_name(type), output_size); + current_result++; + + int offset = 0; + for (int i=0; i MAX_CODE_SIZE) { + aborted_due_to_size = 1; + done = 1; + } + + + if (DEBUG) log_info("line is: %s", line); + + // If we did not use all of them, then we ignore any changes further to the right. + // We do this by causing those loops to skip on the next iteration. + if (vloads < DEPTH) { + if (DEBUG > 1) log_info("done with this depth\n"); + for (int k=vloads; k=0; d--) { + pos[d]++; + if (pos[d] >= number_of_sizes) { + pos[d] = 0; + if (d == 0) { + // If we rolled over at the far-left then we are done + done = 1; + break; + } + } else { + break; + } + } + if (done) + break; + + // Continue until we are done. + } + strcat(program, "}\n\n"); //log_info("%s\n", program); + total_program_length += 3; + if (DEBUG) log_info("\t\t(Program for vector type %s%s contains %d vector creations, of total program length %gkB, with a total of %d vloads.)\n", + get_explicit_type_name(type), size_names[number_of_sizes-1], total_results, total_program_length/1024.0, total_vloads); + *number_of_results = current_result; + if (aborted_due_to_size) + return total_results; + return 0; +} + + + + +int test_vector_creation(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble }; + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16}; + + char *program_source; + int error; + int total_errors = 0; + + cl_int input_data_int[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + cl_double input_data_double[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + void *input_data_converted; + void *output_data; + + int number_of_results;; + + input_data_converted = malloc(sizeof(cl_double)*16); + program_source = (char*)malloc(sizeof(char)*1024*1024*4); + + // Iterate over all the types + for (int type_index=0; type_index<10; type_index++) { + if(!gHasLong && ((vecType[type_index] == kLong) || (vecType[type_index] == kULong))) + { + log_info("Long/ULong data type not supported on this device\n"); + continue; + } + + clMemWrapper input; + + if (vecType[type_index] == kDouble) { + if (!is_extension_available(deviceID, "cl_khr_fp64")) { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + continue; + } + log_info("Testing doubles.\n"); + } + + // Convert the data to the right format for the test. + memset(input_data_converted, 0xff, sizeof(cl_double)*16); + if (vecType[type_index] != kDouble) { + for (int j=0; j<16; j++) { + convert_explicit_value(&input_data_int[j], ((char*)input_data_converted)+get_explicit_type_size(vecType[type_index])*j, + kInt, 0, kRoundToEven, vecType[type_index]); + } + } else { + memcpy(input_data_converted, &input_data_double, sizeof(cl_double)*16); + } + + input = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, get_explicit_type_size(vecType[type_index])*16, + (vecType[type_index] != kDouble) ? input_data_converted : input_data_double, &error); + if (error) { + print_error(error, "clCreateBuffer failed"); + total_errors++; + continue; + } + + // Iterate over all the vector sizes. + for (int size_index=1; size_index< 5; size_index++) { + size_t global[] = {1,1,1}; + int number_generated = -1; + int previous_number_generated = 0; + + log_info("Testing %s%s...\n", get_explicit_type_name(vecType[type_index]), size_names[size_index]); + while (number_generated != 0) { + clMemWrapper output; + clKernelWrapper kernel; + clProgramWrapper program; + + number_generated = create_kernel(vecType[type_index], vecSizes[size_index], program_source, &number_of_results, number_generated); + if (number_generated != 0) { + if (previous_number_generated == 0) + log_info("Code size greater than %gkB; splitting test into multiple kernels.\n", MAX_CODE_SIZE/1024.0); + log_info("\tExecuting vector permutations %d to %d...\n", previous_number_generated, number_generated-1); + } + + error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&program_source, "test_vector_creation"); + if (error) { + log_error("create_single_kernel_helper failed.\n"); + total_errors++; + break; + } + + output = clCreateBuffer(context, CL_MEM_WRITE_ONLY, + number_of_results*get_explicit_type_size(vecType[type_index])*vecSizes[size_index], + NULL, &error); + if (error) { + print_error(error, "clCreateBuffer failed"); + total_errors++; + break; + } + + error = clSetKernelArg(kernel, 0, sizeof(input), &input); + error |= clSetKernelArg(kernel, 1, sizeof(output), &output); + if (error) { + print_error(error, "clSetKernelArg failed"); + total_errors++; + break; + } + + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global, NULL, 0, NULL, NULL); + if (error) { + print_error(error, "clEnqueueNDRangeKernel failed"); + total_errors++; + break; + } + + error = clFinish(queue); + if (error) { + print_error(error, "clFinish failed"); + total_errors++; + break; + } + + output_data = malloc(number_of_results*get_explicit_type_size(vecType[type_index])*vecSizes[size_index]); + if (output_data == NULL) { + log_error("Failed to allocate memory for output data.\n"); + total_errors++; + break; + } + memset(output_data, 0xff, number_of_results*get_explicit_type_size(vecType[type_index])*vecSizes[size_index]); + error = clEnqueueReadBuffer(queue, output, CL_TRUE, 0, + number_of_results*get_explicit_type_size(vecType[type_index])*vecSizes[size_index], + output_data, 0, NULL, NULL); + if (error) { + print_error(error, "clEnqueueReadBuffer failed"); + total_errors++; + free(output_data); + break; + } + + // Check the results + char *res = (char *)output_data; + char *exp = (char *)input_data_converted; + for (int i=0; i +#include +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/errorHelpers.h" + +// Outputs debug information for stores +#define DEBUG 0 +// Forces stores/loads to be done with offsets = tid +#define LINEAR_OFFSETS 0 +#define NUM_LOADS 512 + +static const char *doubleExtensionPragma = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"; + +#pragma mark -------------------- vload harness -------------------------- + +typedef void (*create_vload_program_fn)( char *destBuffer, size_t inBufferSize, ExplicitType type, size_t inVectorSize, size_t outVectorSize ); + +int test_vload( cl_device_id device, cl_context context, cl_command_queue queue, ExplicitType type, unsigned int vecSize, + create_vload_program_fn createFn, size_t bufferSize, MTdata d ) +{ + int error; + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 4 ]; + const size_t numLoads = (DEBUG) ? 16 : NUM_LOADS; + + if (DEBUG) bufferSize = (bufferSize < 128) ? bufferSize : 128; + + size_t threads[ 1 ], localThreads[ 1 ]; + clProtectedArray inBuffer( bufferSize ); + char programSrc[ 10240 ]; + cl_uint offsets[ numLoads ], alignmentOffsets[ numLoads ]; + size_t numElements, typeSize, i; + unsigned int outVectorSize; + + + typeSize = get_explicit_type_size( type ); + numElements = bufferSize / ( typeSize * vecSize ); + bufferSize = numElements * typeSize * vecSize; // To account for rounding + + if (DEBUG) log_info("Testing: numLoads: %d, typeSize: %d, vecSize: %d, numElements: %d, bufferSize: %d\n", (int)numLoads, (int)typeSize, vecSize, (int)numElements, (int)bufferSize); + + // Create some random input data and random offsets to load from + generate_random_data( type, numElements * vecSize, d, (void *)inBuffer ); + for( i = 0; i < numLoads; i++ ) + { + offsets[ i ] = (cl_uint)random_in_range( 0, (int)numElements - 1, d ); + if( offsets[ i ] < numElements - 2 ) + alignmentOffsets[ i ] = (cl_uint)random_in_range( 0, (int)vecSize - 1, d ); + else + alignmentOffsets[ i ] = 0; + if (LINEAR_OFFSETS) offsets[i] = (cl_uint)i; + } + if (LINEAR_OFFSETS) log_info("Offsets set to thread IDs to simplify output.\n"); + + // 32-bit fixup + outVectorSize = vecSize; + + // Declare output buffers now +#if !(defined(_WIN32) && defined(_MSC_VER)) + char outBuffer[ numLoads * typeSize * outVectorSize ]; + char referenceBuffer[ numLoads * typeSize * vecSize ]; +#else + char* outBuffer = (char*)_malloca(numLoads * typeSize * outVectorSize * sizeof(cl_char)); + char* referenceBuffer = (char*)_malloca(numLoads * typeSize * vecSize * sizeof(cl_char)); +#endif + + // Create the program + + + createFn( programSrc, numElements, type, vecSize, outVectorSize); + + // Create our kernel + const char *ptr = programSrc; + + error = create_single_kernel_helper( context, &program, &kernel, 1, &ptr, "test_fn" ); + test_error( error, "Unable to create testing kernel" ); + if (DEBUG) log_info("Kernel: \n%s\n", programSrc); + + // Get the number of args to differentiate the kernels with local storage. (They have 5) + cl_uint numArgs; + error = clGetKernelInfo(kernel, CL_KERNEL_NUM_ARGS, sizeof(numArgs), &numArgs, NULL); + test_error( error, "clGetKernelInfo failed"); + + // Set up parameters + streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, bufferSize, (void *)inBuffer, &error ); + test_error( error, "Unable to create kernel stream" ); + streams[ 1 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, numLoads*sizeof(offsets[0]), offsets, &error ); + test_error( error, "Unable to create kernel stream" ); + streams[ 2 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, numLoads*sizeof(alignmentOffsets[0]), alignmentOffsets, &error ); + test_error( error, "Unable to create kernel stream" ); + streams[ 3 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, numLoads*typeSize*outVectorSize, (void *)outBuffer, &error ); + test_error( error, "Unable to create kernel stream" ); + + // Set parameters and run + if (numArgs == 5) { + // We need to set the size of the local storage + error = clSetKernelArg(kernel, 0, bufferSize, NULL); + test_error( error, "clSetKernelArg for buffer failed"); + for( i = 0; i < 4; i++ ) + { + error = clSetKernelArg( kernel, (int)i+1, sizeof( streams[ i ] ), &streams[ i ] ); + test_error( error, "Unable to set kernel argument" ); + } + } else { + // No local storage + for( i = 0; i < 4; i++ ) + { + error = clSetKernelArg( kernel, (int)i, sizeof( streams[ i ] ), &streams[ i ] ); + test_error( error, "Unable to set kernel argument" ); + } + } + + threads[ 0 ] = numLoads; + error = get_max_common_work_group_size( context, kernel, threads[ 0 ], &localThreads[ 0 ] ); + test_error( error, "Unable to get local thread size" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to exec kernel" ); + + // Get the results + error = clEnqueueReadBuffer( queue, streams[ 3 ], CL_TRUE, 0, numLoads * typeSize * outVectorSize * sizeof(cl_char), (void *)outBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + + // Create the reference results + memset( referenceBuffer, 0, numLoads * typeSize * vecSize * sizeof(cl_char)); + for( i = 0; i < numLoads; i++ ) + { + memcpy( referenceBuffer + i * typeSize * vecSize, ( (char *)(void *)inBuffer ) + ( ( offsets[ i ] * vecSize ) + alignmentOffsets[ i ] ) * typeSize, + typeSize * vecSize ); + } + + // Validate the results now + char *expected = referenceBuffer; + char *actual = outBuffer; + char *in = (char *)(void *)inBuffer; + + if (DEBUG) { + log_info("Memory contents:\n"); + for (i=0; i 10240 ) + localSize = 10240; + if (localSize > 4096) + localSize -= 2048; + else + localSize /= 2; + + return test_vloadset( device, context, queue, create_local_load_code, (size_t)localSize ); +} + + +void create_constant_load_code( char *destBuffer, size_t inBufferSize, ExplicitType type, size_t inVectorSize, size_t outVectorSize ) +{ + const char *pattern = + "%s%s" + "__kernel void test_fn( __constant %s *src, __global uint *offsets, __global uint *alignmentOffsets, __global %s%d *results )\n" + "{\n" + " int tid = get_global_id( 0 );\n" + " %s%d tmp = vload%d( offsets[ tid ], ( (__constant %s *) src ) + alignmentOffsets[ tid ] );\n" + " results[ tid ] = tmp;\n" + "}\n"; + + const char *patternV3 = + "%s%s" + "__kernel void test_fn( __constant %s *src, __global uint *offsets, __global uint *alignmentOffsets, __global %s *results )\n" + "{\n" + " int tid = get_global_id( 0 );\n" + " %s3 tmp = vload3( offsets[ tid ], ( (__constant %s *) src ) + alignmentOffsets[ tid ] );\n" + " results[ 3*tid ] = tmp.s0;\n" + " results[ 3*tid+1 ] = tmp.s1;\n" + " results[ 3*tid+2 ] = tmp.s2;\n" + "}\n"; + + const char *typeName = get_explicit_type_name(type); + if(inVectorSize == 3) { + sprintf( destBuffer, patternV3, + type == kDouble ? doubleExtensionPragma : "", + "", + typeName, typeName, typeName, + typeName ); + } else { + sprintf( destBuffer, pattern, + type == kDouble ? doubleExtensionPragma : "", + "", + typeName, typeName, (int)outVectorSize, typeName, (int)inVectorSize, + (int)inVectorSize, typeName ); + } +} + +int test_vload_constant(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + // Determine the max size of a local buffer that we can test against + cl_ulong maxSize; + int error = clGetDeviceInfo( device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof( maxSize ), &maxSize, NULL ); + test_error( error, "Unable to get max size of constant memory buffer" ); + if( maxSize > 10240 ) + maxSize = 10240; + if (maxSize > 4096) + maxSize -= 2048; + else + maxSize /= 2; + + return test_vloadset( device, context, queue, create_constant_load_code, (size_t)maxSize ); +} + + +void create_private_load_code( char *destBuffer, size_t inBufferSize, ExplicitType type, size_t inVectorSize, size_t outVectorSize ) +{ + const char *pattern = + "%s%s" + // Private memory is unique per thread, unlike local storage which is unique per local work group. Which means + // for this test, we have to copy the entire test buffer into private storage ON EACH THREAD to be an effective test + "#define PRIV_TYPE %s%d\n" + "#define PRIV_SIZE %d\n" + "__kernel void test_fn( __global %s%d *src, __global uint *offsets, __global uint *alignmentOffsets, __global %s%d *results )\n" + "{\n" + " __private PRIV_TYPE sPrivateStorage[ PRIV_SIZE ];\n" + " int tid = get_global_id( 0 );\n" + "\n" + " for( int i = 0; i < %d; i++ )\n" + " sPrivateStorage[ i ] = src[ i ];\n" + // Note: unlike the local test, each thread runs the above copy loop independently, so nobody needs to wait for + // anybody else to sync up + "\n" + " %s%d tmp = vload%d( offsets[ tid ], ( (__private %s *) sPrivateStorage ) + alignmentOffsets[ tid ] );\n" + " results[ tid ] = tmp;\n" + "}\n"; + + const char *patternV3 = + "%s%s" + // Private memory is unique per thread, unlike local storage which is unique per local work group. Which means + // for this test, we have to copy the entire test buffer into private storage ON EACH THREAD to be an effective test + "#define PRIV_TYPE %s\n" + "#define PRIV_SIZE %d\n" + "__kernel void test_fn( __global %s *src, __global uint *offsets, __global uint *alignmentOffsets, __global %s *results )\n" + "{\n" + " __private PRIV_TYPE sPrivateStorage[ PRIV_SIZE ];\n" + " int tid = get_global_id( 0 );\n" + "\n" + " for( int i = 0; i < PRIV_SIZE; i++ )\n" + " {\n" + " sPrivateStorage[ i ] = src[ i ];\n" + " }\n" + // Note: unlike the local test, each thread runs the above copy loop independently, so nobody needs to wait for + // anybody else to sync up + "\n" + " %s3 tmp = vload3( offsets[ tid ], ( sPrivateStorage ) + alignmentOffsets[ tid ] );\n" + " results[ 3*tid ] = tmp.s0;\n" + " results[ 3*tid+1 ] = tmp.s1;\n" + " results[ 3*tid+2 ] = tmp.s2;\n" + "}\n"; + + const char *typeName = get_explicit_type_name(type); + if(inVectorSize ==3) { + sprintf( destBuffer, patternV3, + type == kDouble ? doubleExtensionPragma : "", + "", + typeName, 3*((int)inBufferSize), + typeName, typeName, + typeName ); + // log_info("Src is \"\n%s\n\"\n", destBuffer); + } else { + sprintf( destBuffer, pattern, + type == kDouble ? doubleExtensionPragma : "", + "", + typeName, (int)inVectorSize, (int)inBufferSize, + typeName, (int)inVectorSize, typeName, (int)outVectorSize, + (int)inBufferSize, + typeName, (int)inVectorSize, (int)inVectorSize, typeName ); + } +} + +int test_vload_private(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + // We have no idea how much actual private storage is available, so just pick a reasonable value, + // which is that we can fit at least two 16-element long, which is 2*8 bytes * 16 = 256 bytes + return test_vloadset( device, context, queue, create_private_load_code, 256 ); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark -------------------- vstore harness -------------------------- + +typedef void (*create_vstore_program_fn)( char *destBuffer, size_t inBufferSize, ExplicitType type, size_t inVectorSize ); + +int test_vstore( cl_device_id device, cl_context context, cl_command_queue queue, ExplicitType type, unsigned int vecSize, + create_vstore_program_fn createFn, size_t bufferSize, MTdata d ) +{ + int error; + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 3 ]; + + size_t threads[ 1 ], localThreads[ 1 ]; + + size_t numElements, typeSize, numStores = (DEBUG) ? 16 : NUM_LOADS; + + if (DEBUG) + bufferSize = (bufferSize < 128) ? bufferSize : 128; + + typeSize = get_explicit_type_size( type ); + numElements = bufferSize / ( typeSize * vecSize ); + bufferSize = numElements * typeSize * vecSize; // To account for rounding + if( numStores > numElements * 2 / 3 ) + { + // Note: unlike load, we have to restrict the # of stores here, since all offsets must be unique for our test + // (Plus, we leave some room for extra values to make sure didn't get written) + numStores = numElements * 2 / 3; + if( numStores < 1 ) + numStores = 1; + } + if (DEBUG) + log_info("Testing: numStores: %d, typeSize: %d, vecSize: %d, numElements: %d, bufferSize: %d\n", (int)numStores, (int)typeSize, vecSize, (int)numElements, (int)bufferSize); +#if !(defined(_WIN32) && defined(_MSC_VER)) + cl_uint offsets[ numStores ]; +#else + cl_uint* offsets = (cl_uint*)_malloca(numStores * sizeof(cl_uint)); +#endif + char programSrc[ 10240 ]; + size_t i; + +#if !(defined(_WIN32) && defined(_MSC_VER)) + char inBuffer[ numStores * typeSize * vecSize ]; +#else + char* inBuffer = (char*)_malloca( numStores * typeSize * vecSize * sizeof(cl_char)); +#endif + clProtectedArray outBuffer( numElements * typeSize * vecSize ); +#if !(defined(_WIN32) && defined(_MSC_VER)) + char referenceBuffer[ numElements * typeSize * vecSize ]; +#else + char* referenceBuffer = (char*)_malloca(numElements * typeSize * vecSize * sizeof(cl_char)); +#endif + + // Create some random input data and random offsets to load from + generate_random_data( type, numStores * vecSize, d, (void *)inBuffer ); + + // Note: make sure no two offsets are the same, otherwise the output would depend on + // the order that threads ran in, and that would be next to impossible to verify +#if !(defined(_WIN32) && defined(_MSC_VER)) + char flags[ numElements ]; +#else + char* flags = (char*)_malloca( numElements * sizeof(char)); +#endif + + memset( flags, 0, numElements * sizeof(char) ); + for( i = 0; i < numStores; i++ ) + { + do + { + offsets[ i ] = (cl_uint)random_in_range( 0, (int)numElements - 2, d ); // Note: keep it one vec below the end for offset testing + } while( flags[ offsets[ i ] ] != 0 ); + flags[ offsets[ i ] ] = -1; + if (LINEAR_OFFSETS) + offsets[i] = (int)i; + } + if (LINEAR_OFFSETS) + log_info("Offsets set to thread IDs to simplify output.\n"); + + createFn( programSrc, numElements, type, vecSize ); + + // Create our kernel + const char *ptr = programSrc; + error = create_single_kernel_helper( context, &program, &kernel, 1, &ptr, "test_fn" ); + test_error( error, "Unable to create testing kernel" ); + if (DEBUG) log_info("Kernel: \n%s\n", programSrc); + + // Get the number of args to differentiate the kernels with local storage. (They have 5) + cl_uint numArgs; + error = clGetKernelInfo(kernel, CL_KERNEL_NUM_ARGS, sizeof(numArgs), &numArgs, NULL); + test_error( error, "clGetKernelInfo failed"); + + // Set up parameters + streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, numStores * typeSize * vecSize * sizeof(cl_char), (void *)inBuffer, &error ); + test_error( error, "Unable to create kernel stream" ); + streams[ 1 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, numStores * sizeof(cl_uint), offsets, &error ); + test_error( error, "Unable to create kernel stream" ); + streams[ 2 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, numElements * typeSize * vecSize, (void *)outBuffer, &error ); + test_error( error, "Unable to create kernel stream" ); + + // Set parameters and run + if (numArgs == 5) + { + // We need to set the size of the local storage + error = clSetKernelArg(kernel, 0, bufferSize, NULL); + test_error( error, "clSetKernelArg for buffer failed"); + for( i = 0; i < 3; i++ ) + { + error = clSetKernelArg( kernel, (int)i+1, sizeof( streams[ i ] ), &streams[ i ] ); + test_error( error, "Unable to set kernel argument" ); + } + } + else + { + // No local storage + for( i = 0; i < 3; i++ ) + { + error = clSetKernelArg( kernel, (int)i, sizeof( streams[ i ] ), &streams[ i ] ); + if (error) + log_info("%s\n", programSrc); + test_error( error, "Unable to set kernel argument" ); + } + } + + threads[ 0 ] = numStores; + error = get_max_common_work_group_size( context, kernel, threads[ 0 ], &localThreads[ 0 ] ); + test_error( error, "Unable to get local thread size" ); + + // Run in a loop, changing the address offset from 0 to ( vecSize - 1 ) each time, since + // otherwise stores might overlap each other, and it'd be a nightmare to test! + for( cl_uint addressOffset = 0; addressOffset < vecSize; addressOffset++ ) + { + if (DEBUG) + log_info("\tstore addressOffset is %d, executing with threads %d\n", addressOffset, (int)threads[0]); + + // Clear the results first + memset( outBuffer, 0, numElements * typeSize * vecSize ); + error = clEnqueueWriteBuffer( queue, streams[ 2 ], CL_TRUE, 0, numElements * typeSize * vecSize, (void *)outBuffer, 0, NULL, NULL ); + test_error( error, "Unable to erase result stream" ); + + // Set up the new offset and run + if (numArgs == 5) + error = clSetKernelArg( kernel, 3+1, sizeof( cl_uint ), &addressOffset ); + else + error = clSetKernelArg( kernel, 3, sizeof( cl_uint ), &addressOffset ); + test_error( error, "Unable to set address offset argument" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to exec kernel" ); + + // Get the results + error = clEnqueueReadBuffer( queue, streams[ 2 ], CL_TRUE, 0, numElements * typeSize * vecSize, (void *)outBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + + // Create the reference results + memset( referenceBuffer, 0, numElements * typeSize * vecSize * sizeof(cl_char) ); + for( i = 0; i < numStores; i++ ) + { + memcpy( referenceBuffer + ( ( offsets[ i ] * vecSize ) + addressOffset ) * typeSize, inBuffer + i * typeSize * vecSize, typeSize * vecSize ); + } + + // Validate the results now + char *expected = referenceBuffer; + char *actual = (char *)(void *)outBuffer; + + if (DEBUG) + { + log_info("Memory contents:\n"); + for (i=0; i>2) ], offsets[ tid ], destBuffer + alignmentOffset );\n" + " } else {\n" + " vstore3( vload3(tid, (__global %s *)srcValues), offsets[ tid ], destBuffer + alignmentOffset );\n" + " }\n" + "}\n"; + + const char *typeName = get_explicit_type_name(type); + + if(inVectorSize == 3) { + sprintf( destBuffer, patternV3, + type == kDouble ? doubleExtensionPragma : "", + typeName, typeName, typeName); + + } else { + sprintf( destBuffer, pattern, + type == kDouble ? doubleExtensionPragma : "", + typeName, (int)inVectorSize, typeName, (int)inVectorSize ); + } + // if(inVectorSize == 3 || inVectorSize == 4) { + // log_info("\n----\n%s\n----\n", destBuffer); + // } +} + +int test_vstore_global(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + return test_vstoreset( device, context, queue, create_global_store_code, 10240 ); +} + + +void create_local_store_code( char *destBuffer, size_t inBufferSize, ExplicitType type, size_t inVectorSize ) +{ + const char *pattern = + "%s" + "\n" + "__kernel void test_fn(__local %s%d *sSharedStorage, __global %s%d *srcValues, __global uint *offsets, __global %s%d *destBuffer, uint alignmentOffset )\n" + "{\n" + " int tid = get_global_id( 0 );\n" + // We need to zero the shared storage since any locations we don't write to will have garbage otherwise. + " sSharedStorage[ offsets[tid] ] = (%s%d)(%s)0;\n" + " sSharedStorage[ offsets[tid] +1 ] = sSharedStorage[ offsets[tid] ];\n" + " barrier( CLK_LOCAL_MEM_FENCE );\n" + "\n" + " vstore%d( srcValues[ tid ], offsets[ tid ], ( (__local %s *)sSharedStorage ) + alignmentOffset );\n" + "\n" + // Note: Once all threads are done vstore'ing into our shared storage, we then copy into the global output + // buffer, but we have to make sure ALL threads are done vstore'ing before we do the copy + " barrier( CLK_LOCAL_MEM_FENCE );\n" + "\n" + // Note: we only copy the relevant portion of our local storage over to the dest buffer, because + // otherwise, local threads would be overwriting results from other local threads + " int i;\n" + " __local %s *sp = (__local %s*) (sSharedStorage + offsets[tid]) + alignmentOffset;\n" + " __global %s *dp = (__global %s*) (destBuffer + offsets[tid]) + alignmentOffset;\n" + " for( i = 0; (size_t)i < sizeof( sSharedStorage[0]) / sizeof( *sp ); i++ ) \n" + " dp[i] = sp[i];\n" + "}\n"; + + const char *patternV3 = + "%s" + "\n" + "__kernel void test_fn(__local %s *sSharedStorage, __global %s *srcValues, __global uint *offsets, __global %s *destBuffer, uint alignmentOffset )\n" + "{\n" + " int tid = get_global_id( 0 );\n" + // We need to zero the shared storage since any locations we don't write to will have garbage otherwise. + " sSharedStorage[ 3*offsets[tid] ] = (%s)0;\n" + " sSharedStorage[ 3*offsets[tid] +1 ] = \n" + " sSharedStorage[ 3*offsets[tid] ];\n" + " sSharedStorage[ 3*offsets[tid] +2 ] = \n" + " sSharedStorage[ 3*offsets[tid]];\n" + " sSharedStorage[ 3*offsets[tid] +3 ] = \n" + " sSharedStorage[ 3*offsets[tid]];\n" + " sSharedStorage[ 3*offsets[tid] +4 ] = \n" + " sSharedStorage[ 3*offsets[tid] ];\n" + " sSharedStorage[ 3*offsets[tid] +5 ] = \n" + " sSharedStorage[ 3*offsets[tid]];\n" + " barrier( CLK_LOCAL_MEM_FENCE );\n" + "\n" + " vstore3( vload3(tid,srcValues), offsets[ tid ], sSharedStorage + alignmentOffset );\n" + "\n" + // Note: Once all threads are done vstore'ing into our shared storage, we then copy into the global output + // buffer, but we have to make sure ALL threads are done vstore'ing before we do the copy + " barrier( CLK_LOCAL_MEM_FENCE );\n" + "\n" + // Note: we only copy the relevant portion of our local storage over to the dest buffer, because + // otherwise, local threads would be overwriting results from other local threads + " int i;\n" + " __local %s *sp = (sSharedStorage + 3*offsets[tid]) + alignmentOffset;\n" + " __global %s *dp = (destBuffer + 3*offsets[tid]) + alignmentOffset;\n" + " for( i = 0; i < 3; i++ ) \n" + " dp[i] = sp[i];\n" + "}\n"; + + const char *typeName = get_explicit_type_name(type); + if(inVectorSize == 3) { + sprintf( destBuffer, patternV3, + type == kDouble ? doubleExtensionPragma : "", + typeName, + typeName, + typeName, typeName, + typeName, typeName, typeName ); + } else { + sprintf( destBuffer, pattern, + type == kDouble ? doubleExtensionPragma : "", + typeName, (int)inVectorSize, + typeName, (int)inVectorSize, typeName, (int)inVectorSize, + typeName, (int)inVectorSize, typeName, + (int)inVectorSize, typeName, typeName, + typeName, typeName, typeName ); + } + // log_info(destBuffer); +} + +int test_vstore_local(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + // Determine the max size of a local buffer that we can test against + cl_ulong localSize; + int error = clGetDeviceInfo( device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof( localSize ), &localSize, NULL ); + test_error( error, "Unable to get max size of local memory buffer" ); + if( localSize > 10240 ) + localSize = 10240; + if (localSize > 4096) + localSize -= 2048; + else + localSize /= 2; + return test_vstoreset( device, context, queue, create_local_store_code, (size_t)localSize ); +} + + +void create_private_store_code( char *destBuffer, size_t inBufferSize, ExplicitType type, size_t inVectorSize ) +{ + const char *pattern = + "%s" + // Private memory is unique per thread, unlike local storage which is unique per local work group. Which means + // for this test, we have to copy the entire test buffer into private storage ON EACH THREAD to be an effective test + "\n" + "__kernel void test_fn( __global %s%d *srcValues, __global uint *offsets, __global %s%d *destBuffer, uint alignmentOffset )\n" + "{\n" + " __private %s%d sPrivateStorage[ %d ];\n" + " int tid = get_global_id( 0 );\n" + // We need to zero the shared storage since any locations we don't write to will have garbage otherwise. + " sPrivateStorage[tid] = (%s%d)(%s)0;\n" + "\n" + " vstore%d( srcValues[ tid ], offsets[ tid ], ( (__private %s *)sPrivateStorage ) + alignmentOffset );\n" + "\n" + // Note: we only copy the relevant portion of our local storage over to the dest buffer, because + // otherwise, local threads would be overwriting results from other local threads + " uint i;\n" + " __private %s *sp = (__private %s*) (sPrivateStorage + offsets[tid]) + alignmentOffset;\n" + " __global %s *dp = (__global %s*) (destBuffer + offsets[tid]) + alignmentOffset;\n" + " for( i = 0; i < sizeof( sPrivateStorage[0]) / sizeof( *sp ); i++ ) \n" + " dp[i] = sp[i];\n" + "}\n"; + + + const char *patternV3 = + "%s" + // Private memory is unique per thread, unlike local storage which is unique per local work group. Which means + // for this test, we have to copy the entire test buffer into private storage ON EACH THREAD to be an effective test + "\n" + "__kernel void test_fn( __global %s *srcValues, __global uint *offsets, __global %s3 *destBuffer, uint alignmentOffset )\n" + "{\n" + " __private %s3 sPrivateStorage[ %d ];\n" // keep this %d + " int tid = get_global_id( 0 );\n" + // We need to zero the shared storage since any locations we don't write to will have garbage otherwise. + " sPrivateStorage[tid] = (%s3)(%s)0;\n" + "\n" + + " vstore3( vload3(tid,srcValues), offsets[ tid ], ( (__private %s *)sPrivateStorage ) + alignmentOffset );\n" + "\n" + // Note: we only copy the relevant portion of our local storage over to the dest buffer, because + // otherwise, local threads would be overwriting results from other local threads + " uint i;\n" + " __private %s *sp = ((__private %s*) sPrivateStorage) + 3*offsets[tid] + alignmentOffset;\n" + " __global %s *dp = ((__global %s*) destBuffer) + 3*offsets[tid] + alignmentOffset;\n" + " for( i = 0; i < 3; i++ ) \n" + " dp[i] = sp[i];\n" + "}\n"; + + const char *typeName = get_explicit_type_name(type); + if(inVectorSize == 3) { + sprintf( destBuffer, patternV3, + type == kDouble ? doubleExtensionPragma : "", + typeName, typeName, + typeName, (int)inBufferSize, + typeName, typeName, + typeName, typeName, typeName, typeName, typeName ); + } else { + sprintf( destBuffer, pattern, + type == kDouble ? doubleExtensionPragma : "", + typeName, (int)inVectorSize, typeName, (int)inVectorSize, + typeName, (int)inVectorSize, (int)inBufferSize, + typeName, (int)inVectorSize, typeName, + (int)inVectorSize, typeName, typeName, typeName, typeName, typeName ); + } +} + +int test_vstore_private(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + // We have no idea how much actual private storage is available, so just pick a reasonable value, + // which is that we can fit at least two 16-element long, which is 2*8 bytes * 16 = 256 bytes + return test_vstoreset( device, context, queue, create_private_store_code, 256 ); +} + + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_work_item_functions.cpp b/test_conformance/compatibility/test_conformance/basic/test_work_item_functions.cpp new file mode 100644 index 00000000..04de4e39 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_work_item_functions.cpp @@ -0,0 +1,177 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" + +typedef struct work_item_data +{ + cl_uint workDim; + cl_uint globalSize[ 3 ]; + cl_uint globalID[ 3 ]; + cl_uint localSize[ 3 ]; + cl_uint localID[ 3 ]; + cl_uint numGroups[ 3 ]; + cl_uint groupID[ 3 ]; +}; + +static const char *workItemKernelCode = +"typedef struct {\n" +" uint workDim;\n" +" uint globalSize[ 3 ];\n" +" uint globalID[ 3 ];\n" +" uint localSize[ 3 ];\n" +" uint localID[ 3 ];\n" +" uint numGroups[ 3 ];\n" +" uint groupID[ 3 ];\n" +" } work_item_data;\n" +"\n" +"__kernel void sample_kernel( __global work_item_data *outData )\n" +"{\n" +" int id = get_global_id(0);\n" +" outData[ id ].workDim = (uint)get_work_dim();\n" +" for( uint i = 0; i < get_work_dim(); i++ )\n" +" {\n" +" outData[ id ].globalSize[ i ] = (uint)get_global_size( i );\n" +" outData[ id ].globalID[ i ] = (uint)get_global_id( i );\n" +" outData[ id ].localSize[ i ] = (uint)get_local_size( i );\n" +" outData[ id ].localID[ i ] = (uint)get_local_id( i );\n" +" outData[ id ].numGroups[ i ] = (uint)get_num_groups( i );\n" +" outData[ id ].groupID[ i ] = (uint)get_group_id( i );\n" +" }\n" +"}"; + +#define NUM_TESTS 1 + +int test_work_item_functions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper outData; + work_item_data testData[ 10240 ]; + size_t threads[3], localThreads[3]; + MTdata d; + + + error = create_single_kernel_helper( context, &program, &kernel, 1, &workItemKernelCode, "sample_kernel" ); + test_error( error, "Unable to create testing kernel" ); + + outData = clCreateBuffer( context, CL_MEM_READ_WRITE, sizeof( testData ), NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + error = clSetKernelArg( kernel, 0, sizeof( outData ), &outData ); + test_error( error, "Unable to set kernel arg" ); + + d = init_genrand( gRandomSeed ); + for( size_t dim = 1; dim <= 3; dim++ ) + { + for( int i = 0; i < NUM_TESTS; i++ ) + { + size_t numItems = 1; + for( size_t j = 0; j < dim; j++ ) + { + // All of our thread sizes should be within the max local sizes, since they're all <= 20 + threads[ j ] = (size_t)random_in_range( 1, 20, d ); + localThreads[ j ] = threads[ j ] / (size_t)random_in_range( 1, (int)threads[ j ], d ); + while( localThreads[ j ] > 1 && ( threads[ j ] % localThreads[ j ] != 0 ) ) + localThreads[ j ]--; + + numItems *= threads[ j ]; + + // Hack for now: localThreads > 1 are iffy + localThreads[ j ] = 1; + } + error = clEnqueueNDRangeKernel( queue, kernel, (cl_uint)dim, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + error = clEnqueueReadBuffer( queue, outData, CL_TRUE, 0, sizeof( testData ), testData, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + // Validate + for( size_t q = 0; q < threads[0]; q++ ) + { + // We can't really validate the actual value of each one, but we can validate that they're within a sane range + if( testData[ q ].workDim != (cl_uint)dim ) + { + log_error( "ERROR: get_work_dim() did not return proper value for %d dimensions (expected %d, got %d)\n", (int)dim, (int)dim, (int)testData[ q ].workDim ); + free_mtdata(d); + return -1; + } + for( size_t j = 0; j < dim; j++ ) + { + if( testData[ q ].globalSize[ j ] != (cl_uint)threads[ j ] ) + { + log_error( "ERROR: get_global_size(%d) did not return proper value for %d dimensions (expected %d, got %d)\n", + (int)j, (int)dim, (int)threads[ j ], (int)testData[ q ].globalSize[ j ] ); + free_mtdata(d); + return -1; + } + if( testData[ q ].globalID[ j ] < 0 || testData[ q ].globalID[ j ] >= (cl_uint)threads[ j ] ) + { + log_error( "ERROR: get_global_id(%d) did not return proper value for %d dimensions (max %d, got %d)\n", + (int)j, (int)dim, (int)threads[ j ], (int)testData[ q ].globalID[ j ] ); + free_mtdata(d); + return -1; + } + if( testData[ q ].localSize[ j ] != (cl_uint)localThreads[ j ] ) + { + log_error( "ERROR: get_local_size(%d) did not return proper value for %d dimensions (expected %d, got %d)\n", + (int)j, (int)dim, (int)localThreads[ j ], (int)testData[ q ].localSize[ j ] ); + free_mtdata(d); + return -1; + } + if( testData[ q ].localID[ j ] < 0 && testData[ q ].localID[ j ] >= (cl_uint)localThreads[ j ] ) + { + log_error( "ERROR: get_local_id(%d) did not return proper value for %d dimensions (max %d, got %d)\n", + (int)j, (int)dim, (int)localThreads[ j ], (int)testData[ q ].localID[ j ] ); + free_mtdata(d); + return -1; + } + size_t groupCount = ( threads[ j ] + localThreads[ j ] - 1 ) / localThreads[ j ]; + if( testData[ q ].numGroups[ j ] != (cl_uint)groupCount ) + { + log_error( "ERROR: get_num_groups(%d) did not return proper value for %d dimensions (expected %d with global dim %d and local dim %d, got %d)\n", + (int)j, (int)dim, (int)groupCount, (int)threads[ j ], (int)localThreads[ j ], (int)testData[ q ].numGroups[ j ] ); + free_mtdata(d); + return -1; + } + if( testData[ q ].groupID[ j ] < 0 || testData[ q ].groupID[ j ] >= (cl_uint)groupCount ) + { + log_error( "ERROR: get_group_id(%d) did not return proper value for %d dimensions (max %d, got %d)\n", + (int)j, (int)dim, (int)groupCount, (int)testData[ q ].groupID[ j ] ); + free_mtdata(d); + return -1; + } + } + } + } + } + + free_mtdata(d); + return 0; +} + + diff --git a/test_conformance/compatibility/test_conformance/basic/test_writeimage.c b/test_conformance/compatibility/test_conformance/basic/test_writeimage.c new file mode 100644 index 00000000..26489a26 --- /dev/null +++ b/test_conformance/compatibility/test_conformance/basic/test_writeimage.c @@ -0,0 +1,300 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + + +#include "procs.h" + +static const char *bgra8888_write_kernel_code = +"\n" +"__kernel void test_bgra8888_write(__global unsigned char *src, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(dstimg) + tid_x;\n" +" float4 color;\n" +"\n" +" indx *= 4;\n" +" color = (float4)((float)src[indx+2], (float)src[indx+1], (float)src[indx+0], (float)src[indx+3]);\n" +" color /= (float4)(255.0f, 255.0f, 255.0f, 255.0f);\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + + +static const char *rgba8888_write_kernel_code = +"\n" +"__kernel void test_rgba8888_write(__global unsigned char *src, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(dstimg) + tid_x;\n" +" float4 color;\n" +"\n" +" indx *= 4;\n" +" color = (float4)((float)src[indx+0], (float)src[indx+1], (float)src[indx+2], (float)src[indx+3]);\n" +" color /= (float4)(255.0f, 255.0f, 255.0f, 255.0f);\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + + +static unsigned char * +generate_8888_image(int w, int h, MTdata d) +{ + cl_uchar *ptr = (cl_uchar *)malloc(w * h * 4); + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + + +static const char *rgbaFFFF_write_kernel_code = +"__kernel void test_rgbaFFFF_write(__global float *src, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(dstimg) + tid_x;\n" +" float4 color;\n" +"\n" +" indx *= 4;\n" +" color = (float4)(src[indx+0], src[indx+1], src[indx+2], src[indx+3]);\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + + +static float * +generate_float_image(int w, int h, MTdata d) +{ + float *ptr = (float*)malloc(w * h * 4 * sizeof(float)); + int i; + + for (i=0; i +#include +#include +#include + + +#include "procs.h" + +static const char *rgba16_write_kernel_code = +"__kernel void test_rgba16_write(__global unsigned short *src, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(dstimg) + tid_x;\n" +" float4 color;\n" +"\n" +" indx *= 4;\n" +" color = (float4)((float)src[indx+0], (float)src[indx+1], (float)src[indx+2], (float)src[indx+3]);\n" +" color /= 65535.0f;\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + + +static unsigned short * +generate_16bit_image(int w, int h, MTdata d) +{ + cl_ushort *ptr = (cl_ushort*)malloc(w * h * 4 * sizeof(cl_ushort)); + int i; + + for (i=0; i MAX_ERR) + { + log_error("%s failed\n", string); + return -1; + } + } + + log_info("%s passed\n", string); + return 0; +} + +int test_writeimage_int16(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem streams[3]; + cl_program program; + cl_kernel kernel[2]; + cl_image_format img_format; + cl_ushort *input_ptr, *output_ptr; + size_t threads[2]; + int img_width = 512; + int img_height = 512; + int i, err, any_err = 0; + size_t origin[3] = {0, 0, 0}; + size_t region[3] = {img_width, img_height, 1}; + size_t length = img_width * img_height * 4 * sizeof(cl_ushort); + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + MTdata d = init_genrand( gRandomSeed ); + input_ptr = generate_16bit_image(img_width, img_height, d); + free_mtdata(d); d = NULL; + + output_ptr = (cl_ushort*)malloc(length); + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT16; + streams[0] = create_image_2d(context, CL_MEM_READ_WRITE, &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[0]) + { + log_error("create_image_2d failed\n"); + return -1; + } + + img_format.image_channel_order = CL_RGBA; + img_format.image_channel_data_type = CL_UNORM_INT16; + streams[1] = create_image_2d(context, CL_MEM_WRITE_ONLY, &img_format, img_width, img_height, 0, NULL, NULL); + if (!streams[1]) + { + log_error("create_image_2d failed\n"); + return -1; + } + streams[2] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL); + if (!streams[2]) + { + log_error("clCreateArray failed\n"); + return -1; + } + + err = clEnqueueWriteBuffer(queue, streams[2], CL_TRUE, 0, length, input_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + + err = create_single_kernel_helper(context, &program, &kernel[0], 1, &rgba16_write_kernel_code, "test_rgba16_write" ); + if (err) + return -1; + kernel[1] = clCreateKernel(program, "test_rgba16_write", NULL); + if (!kernel[1]) + { + log_error("clCreateKernel failed\n"); + return -1; + } + + err = clSetKernelArg(kernel[0], 0, sizeof streams[2], &streams[2]); + err |= clSetKernelArg(kernel[0], 1, sizeof streams[0], &streams[0]); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + err = clSetKernelArg(kernel[1], 0, sizeof streams[2], &streams[2]); + err |= clSetKernelArg(kernel[1], 1, sizeof streams[1], &streams[1]); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + threads[0] = (unsigned int)img_width; + threads[1] = (unsigned int)img_height; + + for (i=0; i<2; i++) + { + err = clEnqueueNDRangeKernel(queue, kernel[i], 2, NULL, threads, NULL, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clExecuteKernel failed\n"); + return -1; + } + + err = clEnqueueReadImage(queue, streams[i], CL_TRUE, origin, region, 0, 0, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clReadImage failed\n"); + return -1; + } + + err = verify_16bit_image((i == 0) ? "WRITE_IMAGE_RGBA_UNORM_INT16 test with memflags = CL_MEM_READ_WRITE" : + "WRITE_IMAGE_RGBA_UNORM_INT16 test with memflags = CL_MEM_WRITE_ONLY", + input_ptr, output_ptr, img_width, img_height); + any_err |= err; + } + + // cleanup + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + clReleaseMemObject(streams[2]); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseProgram(program); + free(input_ptr); + free(output_ptr); + + return any_err; +} + + diff --git a/test_conformance/compatibility/test_conformance/images/image_helpers.h b/test_conformance/compatibility/test_conformance/images/image_helpers.h new file mode 100644 index 00000000..d2132c7e --- /dev/null +++ b/test_conformance/compatibility/test_conformance/images/image_helpers.h @@ -0,0 +1,534 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _image_helpers_h +#define _image_helpers_h + +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/imageHelpers.h" +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/mt19937.h" +#include "../../test_common/harness/rounding_mode.h" +#include "../../test_common/harness/clImageHelper.h" + +extern int gTestCount; +extern int gTestFailure; +extern cl_device_type gDeviceType; + +// Number of iterations per image format to test if not testing max images, rounding, or small images +#define NUM_IMAGE_ITERATIONS 3 + +// Definition for our own sampler type, to mirror the cl_sampler internals +typedef struct { + cl_addressing_mode addressing_mode; + cl_filter_mode filter_mode; + bool normalized_coords; +} image_sampler_data; + +extern void print_read_header( cl_image_format *format, image_sampler_data *sampler, bool err = false, int t = 0 ); +extern void print_write_header( cl_image_format *format, bool err); +extern void print_header( cl_image_format *format, bool err ); +extern bool find_format( cl_image_format *formatList, unsigned int numFormats, cl_image_format *formatToFind ); +extern bool check_minimum_supported( cl_image_format *formatList, unsigned int numFormats, cl_mem_flags flags ); + +cl_channel_type get_channel_type_from_name( const char *name ); +cl_channel_order get_channel_order_from_name( const char *name ); +int random_in_range( int minV, int maxV, MTdata d ); +int random_log_in_range( int minV, int maxV, MTdata d ); + +typedef struct +{ + size_t width; + size_t height; + size_t depth; + size_t rowPitch; + size_t slicePitch; + size_t arraySize; + cl_image_format *format; + cl_mem buffer; + cl_mem_object_type type; +} image_descriptor; + +typedef struct +{ + float p[4]; +}FloatPixel; + +void get_max_sizes(size_t *numberOfSizes, const int maxNumberOfSizes, + size_t sizes[][3], size_t maxWidth, size_t maxHeight, size_t maxDepth, size_t maxArraySize, + const cl_ulong maxIndividualAllocSize, const cl_ulong maxTotalAllocSize, cl_mem_object_type image_type, cl_image_format *format); +extern size_t get_format_max_int( cl_image_format *format ); + +extern char * generate_random_image_data( image_descriptor *imageInfo, BufferOwningPtr &Owner, MTdata d ); + +extern int debug_find_vector_in_image( void *imagePtr, image_descriptor *imageInfo, + void *vectorToFind, size_t vectorSize, int *outX, int *outY, int *outZ ); + +extern int debug_find_pixel_in_image( void *imagePtr, image_descriptor *imageInfo, + unsigned int *valuesToFind, int *outX, int *outY, int *outZ ); +extern int debug_find_pixel_in_image( void *imagePtr, image_descriptor *imageInfo, + int *valuesToFind, int *outX, int *outY, int *outZ ); +extern int debug_find_pixel_in_image( void *imagePtr, image_descriptor *imageInfo, + float *valuesToFind, int *outX, int *outY, int *outZ ); + +extern void copy_image_data( image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, void *imageValues, void *destImageValues, + const size_t sourcePos[], const size_t destPos[], const size_t regionSize[] ); + +int has_alpha(cl_image_format *format); + +inline float calculate_array_index( float coord, float extent ); + +template void read_image_pixel( void *imageData, image_descriptor *imageInfo, + int x, int y, int z, T *outData ) +{ + float convert_half_to_float( unsigned short halfValue ); + + if ( x < 0 || x >= (int)imageInfo->width + || ( imageInfo->height != 0 && ( y < 0 || y >= (int)imageInfo->height ) ) + || ( imageInfo->depth != 0 && ( z < 0 || z >= (int)imageInfo->depth ) ) + || ( imageInfo->arraySize != 0 && ( z < 0 || z >= (int)imageInfo->arraySize ) ) ) + { + // Border color + outData[ 0 ] = outData[ 1 ] = outData[ 2 ] = outData[ 3 ] = 0; + if (!has_alpha(imageInfo->format)) + outData[3] = 1; + return; + } + + cl_image_format *format = imageInfo->format; + + unsigned int i; + T tempData[ 4 ]; + + // Advance to the right spot + char *ptr = (char *)imageData; + size_t pixelSize = get_pixel_size( format ); + + ptr += z * imageInfo->slicePitch + y * imageInfo->rowPitch + x * pixelSize; + + // OpenCL only supports reading floats from certain formats + switch( format->image_channel_data_type ) + { + case CL_SNORM_INT8: + { + cl_char *dPtr = (cl_char *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_UNORM_INT8: + { + cl_uchar *dPtr = (cl_uchar *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_SIGNED_INT8: + { + cl_char *dPtr = (cl_char *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_UNSIGNED_INT8: + { + cl_uchar *dPtr = (cl_uchar*)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_SNORM_INT16: + { + cl_short *dPtr = (cl_short *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_UNORM_INT16: + { + cl_ushort *dPtr = (cl_ushort *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_SIGNED_INT16: + { + cl_short *dPtr = (cl_short *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_UNSIGNED_INT16: + { + cl_ushort *dPtr = (cl_ushort *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_HALF_FLOAT: + { + cl_ushort *dPtr = (cl_ushort *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)convert_half_to_float( dPtr[ i ] ); + break; + } + + case CL_SIGNED_INT32: + { + cl_int *dPtr = (cl_int *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_UNSIGNED_INT32: + { + cl_uint *dPtr = (cl_uint *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } + + case CL_UNORM_SHORT_565: + { + cl_ushort *dPtr = (cl_ushort*)ptr; + tempData[ 0 ] = (T)( dPtr[ 0 ] >> 11 ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 5 ) & 63 ); + tempData[ 2 ] = (T)( dPtr[ 0 ] & 31 ); + break; + } + +#ifdef OBSOLETE_FORMAT + case CL_UNORM_SHORT_565_REV: + { + unsigned short *dPtr = (unsigned short *)ptr; + tempData[ 2 ] = (T)( dPtr[ 0 ] >> 11 ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 5 ) & 63 ); + tempData[ 0 ] = (T)( dPtr[ 0 ] & 31 ); + break; + } + + case CL_UNORM_SHORT_555_REV: + { + unsigned short *dPtr = (unsigned short *)ptr; + tempData[ 2 ] = (T)( ( dPtr[ 0 ] >> 10 ) & 31 ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 5 ) & 31 ); + tempData[ 0 ] = (T)( dPtr[ 0 ] & 31 ); + break; + } + + case CL_UNORM_INT_8888: + { + unsigned int *dPtr = (unsigned int *)ptr; + tempData[ 3 ] = (T)( dPtr[ 0 ] >> 24 ); + tempData[ 2 ] = (T)( ( dPtr[ 0 ] >> 16 ) & 0xff ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 8 ) & 0xff ); + tempData[ 0 ] = (T)( dPtr[ 0 ] & 0xff ); + break; + } + case CL_UNORM_INT_8888_REV: + { + unsigned int *dPtr = (unsigned int *)ptr; + tempData[ 0 ] = (T)( dPtr[ 0 ] >> 24 ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 16 ) & 0xff ); + tempData[ 2 ] = (T)( ( dPtr[ 0 ] >> 8 ) & 0xff ); + tempData[ 3 ] = (T)( dPtr[ 0 ] & 0xff ); + break; + } + + case CL_UNORM_INT_101010_REV: + { + unsigned int *dPtr = (unsigned int *)ptr; + tempData[ 2 ] = (T)( ( dPtr[ 0 ] >> 20 ) & 0x3ff ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 10 ) & 0x3ff ); + tempData[ 0 ] = (T)( dPtr[ 0 ] & 0x3ff ); + break; + } +#endif + case CL_UNORM_SHORT_555: + { + cl_ushort *dPtr = (cl_ushort *)ptr; + tempData[ 0 ] = (T)( ( dPtr[ 0 ] >> 10 ) & 31 ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 5 ) & 31 ); + tempData[ 2 ] = (T)( dPtr[ 0 ] & 31 ); + break; + } + + case CL_UNORM_INT_101010: + { + cl_uint *dPtr = (cl_uint *)ptr; + tempData[ 0 ] = (T)( ( dPtr[ 0 ] >> 20 ) & 0x3ff ); + tempData[ 1 ] = (T)( ( dPtr[ 0 ] >> 10 ) & 0x3ff ); + tempData[ 2 ] = (T)( dPtr[ 0 ] & 0x3ff ); + break; + } + + case CL_FLOAT: + { + cl_float *dPtr = (cl_float *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ]; + break; + } +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: + { + cl_float *dPtr = (cl_float *)ptr; + for( i = 0; i < get_format_channel_count( format ); i++ ) + tempData[ i ] = (T)dPtr[ i ] + 0x4000; + break; + } +#endif + } + + + outData[ 0 ] = outData[ 1 ] = outData[ 2 ] = 0; + outData[ 3 ] = 1; + + if( format->image_channel_order == CL_A ) + { + outData[ 3 ] = tempData[ 0 ]; + } + else if( format->image_channel_order == CL_R ) + { + outData[ 0 ] = tempData[ 0 ]; + } + else if( format->image_channel_order == CL_Rx ) + { + outData[ 0 ] = tempData[ 0 ]; + } + else if( format->image_channel_order == CL_RA ) + { + outData[ 0 ] = tempData[ 0 ]; + outData[ 3 ] = tempData[ 1 ]; + } + else if( format->image_channel_order == CL_RG ) + { + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 1 ]; + } + else if( format->image_channel_order == CL_RGx ) + { + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 1 ]; + } + else if( format->image_channel_order == CL_RGB ) + { + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 1 ]; + outData[ 2 ] = tempData[ 2 ]; + } + else if( format->image_channel_order == CL_RGBx ) + { + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 1 ]; + outData[ 2 ] = tempData[ 2 ]; + } + else if( format->image_channel_order == CL_RGBA ) + { + outData[ 0 ] = tempData[ 0 ]; + outData[ 1 ] = tempData[ 1 ]; + outData[ 2 ] = tempData[ 2 ]; + outData[ 3 ] = tempData[ 3 ]; + } + else if( format->image_channel_order == CL_ARGB ) + { + outData[ 0 ] = tempData[ 1 ]; + outData[ 1 ] = tempData[ 2 ]; + outData[ 2 ] = tempData[ 3 ]; + outData[ 3 ] = tempData[ 0 ]; + } + else if( format->image_channel_order == CL_BGRA ) + { + outData[ 0 ] = tempData[ 2 ]; + outData[ 1 ] = tempData[ 1 ]; + outData[ 2 ] = tempData[ 0 ]; + outData[ 3 ] = tempData[ 3 ]; + } + else if( format->image_channel_order == CL_INTENSITY ) + { + outData[ 1 ] = tempData[ 0 ]; + outData[ 2 ] = tempData[ 0 ]; + outData[ 3 ] = tempData[ 0 ]; + } + else if( format->image_channel_order == CL_LUMINANCE ) + { + outData[ 1 ] = tempData[ 0 ]; + outData[ 2 ] = tempData[ 0 ]; + } +#ifdef CL_1RGB_APPLE + else if( format->image_channel_order == CL_1RGB_APPLE ) + { + outData[ 0 ] = tempData[ 1 ]; + outData[ 1 ] = tempData[ 2 ]; + outData[ 2 ] = tempData[ 3 ]; + outData[ 3 ] = 0xff; + } +#endif +#ifdef CL_BGR1_APPLE + else if( format->image_channel_order == CL_BGR1_APPLE ) + { + outData[ 0 ] = tempData[ 2 ]; + outData[ 1 ] = tempData[ 1 ]; + outData[ 2 ] = tempData[ 0 ]; + outData[ 3 ] = 0xff; + } +#endif + else + { + log_error("Invalid format:"); + print_header(format, true); + } +} + +// Stupid template rules +bool get_integer_coords( float x, float y, float z, + size_t width, size_t height, size_t depth, + image_sampler_data *imageSampler, image_descriptor *imageInfo, + int &outX, int &outY, int &outZ ); +bool get_integer_coords_offset( float x, float y, float z, + float xAddressOffset, float yAddressOffset, float zAddressOffset, + size_t width, size_t height, size_t depth, + image_sampler_data *imageSampler, image_descriptor *imageInfo, + int &outX, int &outY, int &outZ ); + + +template void sample_image_pixel_offset( void *imageData, image_descriptor *imageInfo, + float x, float y, float z, float xAddressOffset, float yAddressOffset, float zAddressOffset, + image_sampler_data *imageSampler, T *outData ) +{ + int iX, iY, iZ; + + float max_w = imageInfo->width; + float max_h; + float max_d; + + switch (imageInfo->type) { + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + max_h = imageInfo->arraySize; + max_d = 0; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + max_h = imageInfo->height; + max_d = imageInfo->arraySize; + break; + default: + max_h = imageInfo->height; + max_d = imageInfo->depth; + break; + } + + get_integer_coords_offset( x, y, z, xAddressOffset, yAddressOffset, zAddressOffset, max_w, max_h, max_d, imageSampler, imageInfo, iX, iY, iZ ); + + read_image_pixel( imageData, imageInfo, iX, iY, iZ, outData ); +} + + +template void sample_image_pixel( void *imageData, image_descriptor *imageInfo, + float x, float y, float z, image_sampler_data *imageSampler, T *outData ) +{ + return sample_image_pixel_offset(imageData, imageInfo, x, y, z, 0.0f, 0.0f, 0.0f, imageSampler, outData); +} + +FloatPixel sample_image_pixel_float( void *imageData, image_descriptor *imageInfo, + float x, float y, float z, image_sampler_data *imageSampler, float *outData, int verbose, int *containsDenorms ); + +FloatPixel sample_image_pixel_float_offset( void *imageData, image_descriptor *imageInfo, + float x, float y, float z, float xAddressOffset, float yAddressOffset, float zAddressOffset, + image_sampler_data *imageSampler, float *outData, int verbose, int *containsDenorms ); + + +extern void pack_image_pixel( unsigned int *srcVector, const cl_image_format *imageFormat, void *outData ); +extern void pack_image_pixel( int *srcVector, const cl_image_format *imageFormat, void *outData ); +extern void pack_image_pixel( float *srcVector, const cl_image_format *imageFormat, void *outData ); +extern void pack_image_pixel_error( const float *srcVector, const cl_image_format *imageFormat, const void *results, float *errors ); + +extern char *create_random_image_data( ExplicitType dataType, image_descriptor *imageInfo, BufferOwningPtr &P, MTdata d ); + +// deprecated +// extern bool clamp_image_coord( image_sampler_data *imageSampler, float value, size_t max, int &outValue ); + +extern void get_sampler_kernel_code( image_sampler_data *imageSampler, char *outLine ); +extern float get_max_absolute_error( cl_image_format *format, image_sampler_data *sampler); +extern float get_max_relative_error( cl_image_format *format, image_sampler_data *sampler, int is3D, int isLinearFilter ); +extern int issubnormal(float); + + +#define errMax( _x , _y ) ( (_x) != (_x) ? (_x) : (_x) > (_y) ? (_x) : (_y) ) + +static inline cl_uint abs_diff_uint( cl_uint x, cl_uint y ) +{ + return y > x ? y - x : x - y; +} + +static inline cl_uint abs_diff_int( cl_int x, cl_int y ) +{ + return (cl_uint) (y > x ? y - x : x - y); +} + +static inline cl_float relative_error( float test, float expected ) +{ + // 0-0/0 is 0 in this case, not NaN + if( test == 0.0f && expected == 0.0f ) + return 0.0f; + + return (test - expected) / expected; +} + +extern float random_float(float low, float high); + +class CoordWalker +{ +public: + CoordWalker( void * coords, bool useFloats, size_t vecSize ); + ~CoordWalker(); + + cl_float Get( size_t idx, size_t el ); + +protected: + cl_float * mFloatCoords; + cl_int * mIntCoords; + size_t mVecSize; +}; + +extern int DetectFloatToHalfRoundingMode( cl_command_queue ); // Returns CL_SUCCESS on success + +int inline is_half_nan( cl_ushort half ){ return (half & 0x7fff) > 0x7c00; } + +cl_ushort convert_float_to_half( cl_float f ); +cl_float convert_half_to_float( cl_ushort h ); + + +#endif // _image_helpers_h + + diff --git a/test_conformance/compiler/CMakeLists.txt b/test_conformance/compiler/CMakeLists.txt new file mode 100644 index 00000000..861ae083 --- /dev/null +++ b/test_conformance/compiler/CMakeLists.txt @@ -0,0 +1,25 @@ +set(MODULE_NAME COMPILER) + +set(${MODULE_NAME}_SOURCES + main.c + test_build_helpers.c + test_compile.c + test_async_build.c + test_build_options.cpp + test_preprocessor.c + test_image_macro.c + test_compiler_defines_for_extensions.cpp + test_pragma_unroll.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/typeWrappers.cpp + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/os_helpers.cpp + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) diff --git a/test_conformance/compiler/Jamfile b/test_conformance/compiler/Jamfile new file mode 100644 index 00000000..d1324298 --- /dev/null +++ b/test_conformance/compiler/Jamfile @@ -0,0 +1,27 @@ +project + : requirements + gcc:-xc++ + msvc:"/TP" + ; + +exe test_compiler + : main.c + test_async_build.c + test_build_helpers.c + test_build_options.cpp + test_compile.c + test_preprocessor.c + test_pragma_unroll.c + ; + +install dist + : test_compiler + : debug:$(DIST)/debug/tests/test_conformance/compiler + release:$(DIST)/release/tests/test_conformance/compiler + ; + +install data + : includeTestDirectory/testIncludeFile.h + : debug:$(DIST)/debug/tests/test_conformance/compiler/includeTestDirectory + release:$(DIST)/release/tests/test_conformance/compiler/includeTestDirectory + ; diff --git a/test_conformance/compiler/Makefile b/test_conformance/compiler/Makefile new file mode 100644 index 00000000..aab43bf8 --- /dev/null +++ b/test_conformance/compiler/Makefile @@ -0,0 +1,51 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + test_build_helpers.c \ + test_compile.c \ + test_compiler_defines_for_extensions.cpp \ + test_async_build.c \ + test_build_options.cpp \ + test_preprocessor.c \ + test_image_macro.c \ + test_pragma_unroll.c \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/typeWrappers.cpp \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/os_helpers.cpp \ + ../../test_common/harness/conversions.c + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +HEADERS = +TARGET = test_compiler +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/compiler/includeTestDirectory/testIncludeFile.h b/test_conformance/compiler/includeTestDirectory/testIncludeFile.h new file mode 100644 index 00000000..d8684fb4 --- /dev/null +++ b/test_conformance/compiler/includeTestDirectory/testIncludeFile.h @@ -0,0 +1,16 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#define HEADER_FOUND 12 diff --git a/test_conformance/compiler/main.c b/test_conformance/compiler/main.c new file mode 100644 index 00000000..a97b5829 --- /dev/null +++ b/test_conformance/compiler/main.c @@ -0,0 +1,168 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include "procs.h" +#include "../../test_common/harness/testHarness.h" + +#if !defined(_WIN32) +#include +#endif + +basefn basefn_list[] = { + test_load_program_source, + test_load_multistring_source, + test_load_two_kernel_source, + test_load_null_terminated_source, + test_load_null_terminated_multi_line_source, + test_load_null_terminated_partial_multi_line_source, + test_load_discreet_length_source, + test_get_program_source, + test_get_program_build_info, + test_get_program_info, + + test_large_compile, + test_async_build_pieces, + + test_options_optimizations, + test_options_build_macro, + test_options_build_macro_existence, + test_options_include_directory, + test_options_denorm_cache, + + test_preprocessor_define_udef, + test_preprocessor_include, + test_preprocessor_line_error, + test_preprocessor_pragma, + + test_compiler_defines_for_extensions, + test_image_macro, + + test_simple_compile_only, + test_simple_static_compile_only, + test_simple_extern_compile_only, + test_simple_compile_with_callback, + test_simple_embedded_header_compile, + test_simple_link_only, + test_two_file_regular_variable_access, + test_two_file_regular_struct_access, + test_two_file_regular_function_access, + test_simple_link_with_callback, + test_simple_embedded_header_link, + test_execute_after_simple_compile_and_link, + test_execute_after_simple_compile_and_link_no_device_info, + test_execute_after_simple_compile_and_link_with_defines, + test_execute_after_simple_compile_and_link_with_callbacks, + test_execute_after_simple_library_with_link, + test_execute_after_two_file_link, + test_execute_after_embedded_header_link, + test_execute_after_included_header_link, + test_execute_after_serialize_reload_object, + test_execute_after_serialize_reload_library, + test_simple_library_only, + test_simple_library_with_callback, + test_simple_library_with_link, + test_two_file_link, + test_multi_file_libraries, + test_multiple_files, + test_multiple_libraries, + test_multiple_files_multiple_libraries, + test_multiple_embedded_headers, + + test_program_binary_type, + test_compile_and_link_status_options_log, + + test_pragma_unroll +}; + + +const char *basefn_names[] = { + "load_program_source", + "load_multistring_source", + "load_two_kernel_source", + "load_null_terminated_source", + "load_null_terminated_multi_line_source", + "load_null_terminated_partial_multi_line_source", + "load_discreet_length_source", + "get_program_source", + "get_program_build_info", + "get_program_info", + + "large_compile", + "async_build", + + "options_build_optimizations", + "options_build_macro", + "options_build_macro_existence", + "options_include_directory", + "options_denorm_cache", + + "preprocessor_define_udef", + "preprocessor_include", + "preprocessor_line_error", + "preprocessor_pragma", + + "compiler_defines_for_extensions", + "image_macro", + + "simple_compile_only", + "simple_static_compile_only", + "simple_extern_compile_only", + "simple_compile_with_callback", + "simple_embedded_header_compile", + "simple_link_only", + "two_file_regular_variable_access", + "two_file_regular_struct_access", + "two_file_regular_function_access", + "simple_link_with_callback", + "simple_embedded_header_link", + "execute_after_simple_compile_and_link", + "execute_after_simple_compile_and_link_no_device_info", + "execute_after_simple_compile_and_link_with_defines", + "execute_after_simple_compile_and_link_with_callbacks", + "execute_after_simple_library_with_link", + "execute_after_two_file_link", + "execute_after_embedded_header_link", + "execute_after_included_header_link", + "execute_after_serialize_reload_object", + "execute_after_serialize_reload_library", + "simple_library_only", + "simple_library_with_callback", + "simple_library_with_link", + "two_file_link", + "multi_file_libraries", + "multiple_files", + "multiple_libraries", + "multiple_files_multiple_libraries", + "multiple_embedded_headers", + "program_binary_type", + "compile_and_link_status_options_log", + + "pragma_unroll", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + +int main(int argc, const char *argv[]) +{ + return runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false, false, 0 ); +} + + diff --git a/test_conformance/compiler/procs.h b/test_conformance/compiler/procs.h new file mode 100644 index 00000000..54a93db3 --- /dev/null +++ b/test_conformance/compiler/procs.h @@ -0,0 +1,88 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/mt19937.h" + +extern int test_load_program_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_load_multistring_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_load_two_kernel_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_load_null_terminated_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_load_null_terminated_multi_line_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_load_null_terminated_partial_multi_line_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_load_discreet_length_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_get_program_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_get_program_build_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_get_program_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_large_compile(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_async_build_pieces(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_options_optimizations(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_options_build_macro(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_options_build_macro_existence(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_options_include_directory(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_options_denorm_cache(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_preprocessor_define_udef(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_preprocessor_include(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_preprocessor_line_error(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_preprocessor_pragma(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_compiler_defines_for_extensions(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); +extern int test_image_macro(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_simple_compile_only(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_simple_static_compile_only(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_simple_extern_compile_only(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_simple_compile_with_callback(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_simple_embedded_header_compile(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_simple_link_only(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_two_file_regular_variable_access(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_two_file_regular_struct_access(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_two_file_regular_function_access(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_simple_link_with_callback(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_simple_embedded_header_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_execute_after_simple_compile_and_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_execute_after_simple_compile_and_link_no_device_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_execute_after_simple_compile_and_link_with_defines(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_execute_after_simple_compile_and_link_with_callbacks(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_execute_after_simple_library_with_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_execute_after_two_file_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_execute_after_embedded_header_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_execute_after_included_header_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_execute_after_serialize_reload_object(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_execute_after_serialize_reload_library(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_simple_library_only(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_simple_library_with_callback(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_simple_library_with_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_two_file_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_multi_file_libraries(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_multiple_libraries(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_multiple_files(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_multiple_files_multiple_libraries(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_multiple_embedded_headers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_program_binary_type(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_compile_and_link_status_options_log(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_pragma_unroll(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); \ No newline at end of file diff --git a/test_conformance/compiler/secondIncludeTestDirectory/testIncludeFile.h b/test_conformance/compiler/secondIncludeTestDirectory/testIncludeFile.h new file mode 100644 index 00000000..ef795d67 --- /dev/null +++ b/test_conformance/compiler/secondIncludeTestDirectory/testIncludeFile.h @@ -0,0 +1,16 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#define HEADER_FOUND 42 diff --git a/test_conformance/compiler/testBase.h b/test_conformance/compiler/testBase.h new file mode 100644 index 00000000..5073b21f --- /dev/null +++ b/test_conformance/compiler/testBase.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testBase_h +#define _testBase_h + +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +#endif // _testBase_h + + + diff --git a/test_conformance/compiler/test_async_build.c b/test_conformance/compiler/test_async_build.c new file mode 100644 index 00000000..e32c64ab --- /dev/null +++ b/test_conformance/compiler/test_async_build.c @@ -0,0 +1,94 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +#if !defined(_WIN32) +#include +#endif + + +const char *sample_async_kernel[] = { +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n" }; + +volatile int buildNotificationSent; + +void CL_CALLBACK test_notify_build_complete( cl_program program, void *userData ) +{ + if( userData == NULL || strcmp( (char *)userData, "userData" ) != 0 ) + { + log_error( "ERROR: User data passed in to build notify function was not correct!\n" ); + buildNotificationSent = -1; + } + else + buildNotificationSent = 1; + log_info( "\n <-- program successfully built\n" ); +} + +int test_async_build_pieces(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + cl_build_status status; + + + buildNotificationSent = 0; + + /* First, test by doing the slow method of the individual calls */ + error = create_single_kernel_helper_create_program(context, &program, 1, sample_async_kernel); + test_error(error, "Unable to create program from source"); + + /* Compile the program */ + error = clBuildProgram( program, 1, &deviceID, NULL, test_notify_build_complete, (void *)"userData" ); + test_error( error, "Unable to build program source" ); + + /* Wait for build to complete (just keep polling, since we're just a test */ + if( ( error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL ) ) != CL_SUCCESS ) + { + print_error( error, "Unable to get program build status" ); + return -1; + } + while( (int)status == CL_BUILD_IN_PROGRESS ) + { + log_info( "\n -- still waiting for build... (status is %d)", status ); + sleep( 1 ); + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Unable to get program build status" ); + } + + if( status != CL_BUILD_SUCCESS ) + { + log_error( "ERROR: build failed! (status: %d)\n", (int)status ); + return -1; + } + + if( buildNotificationSent == 0 ) + { + log_error( "ERROR: Async build completed, but build notification was not sent!\n" ); + return -1; + } + + clReleaseProgram( program ); + + return 0; +} + + diff --git a/test_conformance/compiler/test_build_helpers.c b/test_conformance/compiler/test_build_helpers.c new file mode 100644 index 00000000..0fcb7103 --- /dev/null +++ b/test_conformance/compiler/test_build_helpers.c @@ -0,0 +1,571 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/parseParameters.h" + +const char *sample_kernel_code_single_line[] = { +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n" }; + +size_t sample_single_line_lengths[1]; + +const char *sample_kernel_code_multi_line[] = { +"__kernel void sample_test(__global float *src, __global int *dst)", +"{", +" int tid = get_global_id(0);", +"", +" dst[tid] = (int)src[tid];", +"", +"}" }; + +size_t sample_multi_line_lengths[ 7 ]; + +const char *sample_kernel_code_two_line[] = { +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (int)src[tid];\n" +"\n" +"}\n", +"__kernel void sample_test2(__global int *src, __global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (float)src[tid];\n" +"\n" +"}\n" }; + +size_t sample_two_line_lengths[1]; + +const char *sample_kernel_code_bad_multi_line[] = { +"__kernel void sample_test(__global float *src, __global int *dst)", +"{", +" int tid = get_global_id(0);thisisanerror", +"", +" dst[tid] = (int)src[tid];", +"", +"}" }; + +size_t sample_bad_multi_line_lengths[ 7 ]; + + +int test_load_program_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + size_t length; + char *buffer; + + /* Preprocess: calc the length of each source file line */ + sample_single_line_lengths[ 0 ] = strlen( sample_kernel_code_single_line[ 0 ] ); + + /* New OpenCL API only has one entry point, so go ahead and just try it */ + program = clCreateProgramWithSource( context, 1, sample_kernel_code_single_line, sample_single_line_lengths, &error); + test_error( error, "Unable to create reference program" ); + + /* Now get the source and compare against our original */ + error = clGetProgramInfo( program, CL_PROGRAM_SOURCE, NULL, NULL, &length ); + test_error( error, "Unable to get length of first program source" ); + + // Note: according to spec section 5.4.5, the length returned should include the null terminator + if( length != sample_single_line_lengths[0] + 1 ) + { + log_error( "ERROR: Length of program (%ld) does not match reference length (%ld)!\n", length, sample_single_line_lengths[0] + 1 ); + return -1; + } + + buffer = (char *)malloc( length ); + error = clGetProgramInfo( program, CL_PROGRAM_SOURCE, length, buffer, NULL ); + test_error( error, "Unable to get buffer of first program source" ); + + if( strcmp( (char *)buffer, sample_kernel_code_single_line[ 0 ] ) != 0 ) + { + log_error( "ERROR: Program sources do not match!\n" ); + return -1; + } + + /* All done */ + free( buffer ); + + return 0; +} + +int test_load_multistring_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + + int i; + + + /* Preprocess: calc the length of each source file line */ + for( i = 0; i < 7; i++ ) + { + sample_multi_line_lengths[ i ] = strlen( sample_kernel_code_multi_line[ i ] ); + } + + /* Create another program using the macro function */ + program = clCreateProgramWithSource( context, 7, sample_kernel_code_multi_line, sample_multi_line_lengths, &error ); + if( program == NULL ) + { + log_error( "ERROR: Unable to create reference program!\n" ); + return -1; + } + + /* Try compiling */ + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build multi-line program source" ); + + /* Should probably check binary here to verify the same results... */ + + /* All done! */ + + return 0; +} + +int test_load_two_kernel_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + + int i; + + + /* Preprocess: calc the length of each source file line */ + for( i = 0; i < 2; i++ ) + { + sample_two_line_lengths[ i ] = strlen( sample_kernel_code_two_line[ i ] ); + } + + /* Now create a program using the macro function */ + program = clCreateProgramWithSource( context, 2, sample_kernel_code_two_line, sample_two_line_lengths, &error ); + if( program == NULL ) + { + log_error( "ERROR: Unable to create two-kernel program!\n" ); + return -1; + } + + /* Try compiling */ + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build two-kernel program source" ); + + /* Should probably check binary here to verify the same results... */ + + /* All done! */ + clReleaseProgram( program ); + + return 0; +} + +int test_load_null_terminated_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + + + /* Now create a program using the macro function */ + program = clCreateProgramWithSource( context, 1, sample_kernel_code_single_line, NULL, &error ); + if( program == NULL ) + { + log_error( "ERROR: Unable to create null-terminated program!" ); + return -1; + } + + /* Try compiling */ + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build null-terminated program source" ); + + /* Should probably check binary here to verify the same results... */ + + /* All done! */ + clReleaseProgram( program ); + + return 0; +} + +int test_load_null_terminated_multi_line_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + + + /* Now create a program using the macro function */ + program = clCreateProgramWithSource( context, 7, sample_kernel_code_multi_line, NULL, &error ); + if( program == NULL ) + { + log_error( "ERROR: Unable to create null-terminated program!" ); + return -1; + } + + /* Try compiling */ + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build null-terminated program source" ); + + /* Should probably check binary here to verify the same results... */ + + /* All done! */ + clReleaseProgram( program ); + + return 0; +} + + +int test_load_discreet_length_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + + int i; + + + /* Preprocess: calc the length of each source file line */ + for( i = 0; i < 7; i++ ) + { + sample_bad_multi_line_lengths[ i ] = strlen( sample_kernel_code_bad_multi_line[ i ] ); + } + + /* Now force the length of the third line to skip the actual error */ + sample_bad_multi_line_lengths[2] -= strlen("thisisanerror"); + + /* Now create a program using the macro function */ + program = clCreateProgramWithSource( context, 7, sample_kernel_code_bad_multi_line, sample_bad_multi_line_lengths, &error ); + if( program == NULL ) + { + log_error( "ERROR: Unable to create null-terminated program!" ); + return -1; + } + + /* Try compiling */ + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build null-terminated program source" ); + + /* Should probably check binary here to verify the same results... */ + + /* All done! */ + clReleaseProgram( program ); + + return 0; +} + +int test_load_null_terminated_partial_multi_line_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + int i; + + /* Preprocess: calc the length of each source file line */ + for( i = 0; i < 7; i++ ) + { + if( i & 0x01 ) + sample_multi_line_lengths[ i ] = 0; /* Should force for null-termination on this line only */ + else + sample_multi_line_lengths[ i ] = strlen( sample_kernel_code_multi_line[ i ] ); + } + + /* Now create a program using the macro function */ + program = clCreateProgramWithSource( context, 7, sample_kernel_code_multi_line, sample_multi_line_lengths, &error ); + if( program == NULL ) + { + log_error( "ERROR: Unable to create null-terminated program!" ); + return -1; + } + + /* Try compiling */ + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build null-terminated program source" ); + + /* Should probably check binary here to verify the same results... */ + + /* All done! */ + clReleaseProgram( program ); + + return 0; +} + +int test_get_program_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + cl_device_id device1; + cl_context context1; + size_t paramSize; + cl_uint numInstances; + + + error = create_single_kernel_helper_create_program(context, &program, 1, sample_kernel_code_single_line); + if( program == NULL ) + { + log_error( "ERROR: Unable to create reference program!\n" ); + return -1; + } + + /* Test that getting the device works. */ + device1 = (cl_device_id)0xbaadfeed; + error = clGetProgramInfo( program, CL_PROGRAM_DEVICES, sizeof( device1 ), &device1, NULL ); + test_error( error, "Unable to get device of program" ); + + /* Since the device IDs are opaque types we check the CL_DEVICE_VENDOR_ID which is unique for identical hardware. */ + cl_uint device1_vid, deviceID_vid; + error = clGetDeviceInfo(device1, CL_DEVICE_VENDOR_ID, sizeof(device1_vid), &device1_vid, NULL ); + test_error( error, "Unable to get device CL_DEVICE_VENDOR_ID" ); + error = clGetDeviceInfo(deviceID, CL_DEVICE_VENDOR_ID, sizeof(deviceID_vid), &deviceID_vid, NULL ); + test_error( error, "Unable to get device CL_DEVICE_VENDOR_ID" ); + + if( device1_vid != deviceID_vid ) + { + log_error( "ERROR: Incorrect device returned for program! (Expected vendor ID 0x%x, got 0x%x)\n", deviceID_vid, device1_vid ); + return -1; + } + + cl_uint devCount; + error = clGetProgramInfo( program, CL_PROGRAM_NUM_DEVICES, sizeof( devCount ), &devCount, NULL ); + test_error( error, "Unable to get device count of program" ); + + if( devCount != 1 ) + { + log_error( "ERROR: Invalid device count returned for program! (Expected 1, got %d)\n", (int)devCount ); + return -1; + } + + context1 = (cl_context)0xbaadfeed; + error = clGetProgramInfo( program, CL_PROGRAM_CONTEXT, sizeof( context1 ), &context1, NULL ); + test_error( error, "Unable to get device of program" ); + + if( context1 != context ) + { + log_error( "ERROR: Invalid context returned for program! (Expected %p, got %p)\n", context, context1 ); + return -1; + } + + error = clGetProgramInfo( program, CL_PROGRAM_REFERENCE_COUNT, sizeof( numInstances ), &numInstances, NULL ); + test_error( error, "Unable to get instance count" ); + + /* While we're at it, test the sizes of programInfo too */ + error = clGetProgramInfo( program, CL_PROGRAM_DEVICES, NULL, NULL, ¶mSize ); + test_error( error, "Unable to get device param size" ); + if( paramSize != sizeof( cl_device_id ) ) + { + log_error( "ERROR: Size returned for device is wrong!\n" ); + return -1; + } + + error = clGetProgramInfo( program, CL_PROGRAM_CONTEXT, NULL, NULL, ¶mSize ); + test_error( error, "Unable to get context param size" ); + if( paramSize != sizeof( cl_context ) ) + { + log_error( "ERROR: Size returned for context is wrong!\n" ); + return -1; + } + + error = clGetProgramInfo( program, CL_PROGRAM_REFERENCE_COUNT, NULL, NULL, ¶mSize ); + test_error( error, "Unable to get instance param size" ); + if( paramSize != sizeof( cl_uint ) ) + { + log_error( "ERROR: Size returned for num instances is wrong!\n" ); + return -1; + } + + error = clGetProgramInfo( program, CL_PROGRAM_NUM_DEVICES, NULL, NULL, ¶mSize ); + test_error( error, "Unable to get device count param size" ); + if( paramSize != sizeof( cl_uint ) ) + { + log_error( "ERROR: Size returned for device count is wrong!\n" ); + return -1; + } + + clReleaseProgram( program ); + + return 0; +} + +int test_get_program_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_program program; + int error; + char buffer[10240]; + size_t length; + + + error = create_single_kernel_helper_create_program(context, &program, 1, sample_kernel_code_single_line); + if( program == NULL ) + { + log_error( "ERROR: Unable to create test program!\n" ); + return -1; + } + + /* Try getting the length */ + error = clGetProgramInfo( program, CL_PROGRAM_SOURCE, NULL, NULL, &length ); + test_error( error, "Unable to get program source length" ); + if (length != strlen(sample_kernel_code_single_line[0]) + 1 && !(gOfflineCompiler && gOfflineCompilerOutputType != kSource)) + { + log_error( "ERROR: Length returned for program source is incorrect!\n" ); + return -1; + } + + /* Try normal source */ + error = clGetProgramInfo( program, CL_PROGRAM_SOURCE, sizeof( buffer ), buffer, NULL ); + test_error( error, "Unable to get program source" ); + if (strlen(buffer) != strlen(sample_kernel_code_single_line[0]) && !(gOfflineCompiler && gOfflineCompilerOutputType != kSource)) + { + log_error( "ERROR: Length of program source is incorrect!\n" ); + return -1; + } + + /* Try both at once */ + error = clGetProgramInfo( program, CL_PROGRAM_SOURCE, sizeof( buffer ), buffer, &length ); + test_error( error, "Unable to get program source" ); + if (strlen(buffer) != strlen(sample_kernel_code_single_line[0]) && !(gOfflineCompiler && gOfflineCompilerOutputType != kSource)) + { + log_error( "ERROR: Length of program source is incorrect!\n" ); + return -1; + } + if (length != strlen(sample_kernel_code_single_line[0]) + 1 && !(gOfflineCompiler && gOfflineCompilerOutputType != kSource)) + { + log_error( "ERROR: Returned length of program source is incorrect!\n" ); + return -1; + } + + /* if we got here, everything passed */ + clReleaseProgram( program ); + return 0; +} + +int test_get_program_build_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_program program; + int error; + char *buffer; + size_t length, newLength; + cl_build_status status; + + + error = create_single_kernel_helper_create_program(context, &program, 1, sample_kernel_code_single_line); + if( program == NULL ) + { + log_error( "ERROR: Unable to create test program!\n" ); + return -1; + } + + /* Make sure getting the length works */ + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, 0, NULL, &length ); + test_error( error, "Unable to get program build status length" ); + if( length != sizeof( status ) ) + { + log_error( "ERROR: Returned length of program build status is invalid! (Expected %d, got %d)\n", (int)sizeof( status ), (int)length ); + return -1; + } + + /* Now actually build it and verify the status */ + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build program source" ); + + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Unable to get program build status" ); + if( status != CL_BUILD_SUCCESS ) + { + log_error( "ERROR: Getting built program build status did not return CL_BUILD_SUCCESS! (%d)\n", (int)status ); + return -1; + } + + /***** Build log *****/ + + /* Try getting the length */ + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_LOG, 0, NULL, &length ); + test_error( error, "Unable to get program build log length" ); + + log_info("Build log is %ld long.\n", length); + + buffer = (char*)malloc(length); + + /* Try normal source */ + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_LOG, length, buffer, NULL ); + test_error( error, "Unable to get program build log" ); + + if( buffer[length-1] != '\0' ) + { + log_error( "clGetProgramBuildInfo overwrote allocated space for build log! '%c'\n", buffer[length-1] ); + return -1; + } + + /* Try both at once */ + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_LOG, length, buffer, &newLength ); + test_error( error, "Unable to get program build log" ); + + free(buffer); + + + /***** Build options *****/ + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_OPTIONS, 0, NULL, &length ); + test_error( error, "Unable to get program build options length" ); + + buffer = (char*)malloc(length); + + /* Try normal source */ + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_OPTIONS, length, buffer, NULL ); + test_error( error, "Unable to get program build options" ); + + /* Try both at once */ + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_OPTIONS, length, buffer, &newLength ); + test_error( error, "Unable to get program build options" ); + + free(buffer); + + /* Try with a valid option */ + clReleaseProgram( program ); + program = clCreateProgramWithSource( context, 1, sample_kernel_code_single_line, NULL, &error ); + if( program == NULL ) + { + log_error( "ERROR: Unable to create test program!\n" ); + return -1; + } + + error = clBuildProgram( program, 1, &deviceID, "-cl-opt-disable", NULL, NULL ); + if( error != CL_SUCCESS ) + { + print_error( error, "Building with valid options failed!" ); + return -1; + } + + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_OPTIONS, NULL, NULL, &length ); + test_error( error, "Unable to get program build options" ); + + buffer = (char*)malloc(length); + + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_OPTIONS, length, buffer, NULL ); + test_error( error, "Unable to get program build options" ); + if( strcmp( (char *)buffer, "-cl-opt-disable" ) != 0 ) + { + log_error( "ERROR: Getting program build options for program with -cl-opt-disable build options did not return expected value (got %s)\n", buffer ); + return -1; + } + + free(buffer); + + /* if we got here, everything passed */ + clReleaseProgram( program ); + return 0; +} + + + + diff --git a/test_conformance/compiler/test_build_options.cpp b/test_conformance/compiler/test_build_options.cpp new file mode 100644 index 00000000..791eafd9 --- /dev/null +++ b/test_conformance/compiler/test_build_options.cpp @@ -0,0 +1,410 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/os_helpers.h" + +const char *preprocessor_test_kernel[] = { +"__kernel void sample_test(__global int *dst)\n" +"{\n" +" dst[0] = TEST_MACRO;\n" +"\n" +"}\n" }; + +const char *preprocessor_existence_test_kernel[] = { + "__kernel void sample_test(__global int *dst)\n" + "{\n" + "#ifdef TEST_MACRO\n" + " dst[0] = 42;\n" + "#else\n" + " dst[0] = 24;\n" + "#endif\n" + "\n" + "}\n" }; + +const char *include_test_kernel[] = { +"#include \"./testIncludeFile.h\"\n" +"__kernel void sample_test(__global int *dst)\n" +"{\n" +" dst[0] = HEADER_FOUND;\n" +"\n" +"}\n" }; + +const char *options_test_kernel[] = { +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" dst[tid] = src[tid];\n" +"}\n" }; + +const char *optimization_options[] = { + "-cl-single-precision-constant", + "-cl-denorms-are-zero", + "-cl-opt-disable", + "-cl-mad-enable", + "-cl-no-signed-zeros", + "-cl-unsafe-math-optimizations", + "-cl-finite-math-only", + "-cl-fast-relaxed-math", + "-w", + "-Werror", +#if defined( __APPLE__ ) + "-cl-opt-enable", + "-cl-auto-vectorize-enable" +#endif + }; + +cl_int get_result_from_program( cl_context context, cl_command_queue queue, cl_program program, cl_int *outValue ) +{ + cl_int error; + clKernelWrapper kernel = clCreateKernel( program, "sample_test", &error ); + test_error( error, "Unable to create kernel from program" ); + + clMemWrapper outStream; + outStream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int), NULL, &error ); + test_error( error, "Unable to create test buffer" ); + + error = clSetKernelArg( kernel, 0, sizeof( outStream ), &outStream ); + test_error( error, "Unable to set kernel argument" ); + + size_t threads[1] = { 1 }; + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + error = clEnqueueReadBuffer( queue, outStream, true, 0, sizeof( cl_int ), outValue, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + return CL_SUCCESS; +} + +int test_options_optimizations(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_build_status status; + + for(size_t i = 0; i < sizeof(optimization_options) / (sizeof(char*)); i++) { + + clProgramWrapper program; + error = create_single_kernel_helper_create_program(context, &program, 1, options_test_kernel, optimization_options[i]); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create reference program!\n" ); + return -1; + } + + /* Build with the macro defined */ + log_info("Testing optimization option '%s'\n", optimization_options[i]); + error = clBuildProgram( program, 1, &deviceID, optimization_options[i], NULL, NULL ); + test_error( error, "Test program did not properly build" ); + + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Unable to get program build status" ); + + if( (int)status != CL_BUILD_SUCCESS ) + { + log_info("Building with optimization option '%s' failed to compile!\n", optimization_options[i]); + print_error( error, "Failed to build with optimization defined") + return -1; + } + } + return 0; +} + +int test_options_build_macro(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + cl_build_status status; + + + program = clCreateProgramWithSource( context, 1, preprocessor_test_kernel, NULL, &error ); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create reference program!\n" ); + return -1; + } + + /* Build with the macro defined */ + error = clBuildProgram( program, 1, &deviceID, "-DTEST_MACRO=1 ", NULL, NULL ); + test_error( error, "Test program did not properly build" ); + + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Unable to get program build status" ); + + if( (int)status != CL_BUILD_SUCCESS ) + { + print_error( error, "Failed to build with macro defined" ); + return -1; + } + + + // Go ahead and run the program to verify results + cl_int firstResult, secondResult; + + error = get_result_from_program( context, queue, program, &firstResult ); + test_error( error, "Unable to get result from first program" ); + + if( firstResult != 1 ) + { + log_error( "ERROR: Result from first program did not validate! (Expected 1, got %d)\n", firstResult ); + return -1; + } + + // Rebuild with a different value for the define macro, to make sure caching behaves properly + error = clBuildProgram( program, 1, &deviceID, "-DTEST_MACRO=5 ", NULL, NULL ); + test_error( error, "Test program did not properly rebuild" ); + + error = get_result_from_program( context, queue, program, &secondResult ); + test_error( error, "Unable to get result from second program" ); + + if( secondResult != 5 ) + { + if( secondResult == firstResult ) + log_error( "ERROR: Program result did not change with device macro change (program was not recompiled)!\n" ); + else + log_error( "ERROR: Result from second program did not validate! (Expected 5, got %d)\n", secondResult ); + return -1; + } + + return 0; +} + +int test_options_build_macro_existence(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + clProgramWrapper program; + + + // In this case, the program should still run without the macro, but it should give a different result + program = clCreateProgramWithSource( context, 1, preprocessor_existence_test_kernel, NULL, &error ); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create reference program!\n" ); + return -1; + } + + /* Build without the macro defined */ + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Test program did not properly build" ); + + // Go ahead and run the program to verify results + cl_int firstResult, secondResult; + + error = get_result_from_program( context, queue, program, &firstResult ); + test_error( error, "Unable to get result from first program" ); + + if( firstResult != 24 ) + { + log_error( "ERROR: Result from first program did not validate! (Expected 24, got %d)\n", firstResult ); + return -1; + } + + // Now compile again with the macro defined and verify a change in results + error = clBuildProgram( program, 1, &deviceID, "-DTEST_MACRO", NULL, NULL ); + test_error( error, "Test program did not properly build" ); + + error = get_result_from_program( context, queue, program, &secondResult ); + test_error( error, "Unable to get result from second program" ); + + if( secondResult != 42 ) + { + if( secondResult == firstResult ) + log_error( "ERROR: Program result did not change with device macro addition (program was not recompiled)!\n" ); + else + log_error( "ERROR: Result from second program did not validate! (Expected 42, got %d)\n", secondResult ); + return -1; + } + + return 0; +} + +int test_options_include_directory(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + + std::string sep = dir_sep(); + std::string path = exe_dir(); // Directory where test executable is located. + std::string include_dir; + + clProgramWrapper program; + cl_build_status status; + + /* Try compiling the program first without the directory included Should fail. */ + program = clCreateProgramWithSource( context, 1, include_test_kernel, NULL, &error ); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create reference program!\n" ); + return -1; + } + + /* Build with the include directory defined */ + include_dir = "-I " + path + sep + "includeTestDirectory"; + +// log_info("%s\n", include_dir); + error = clBuildProgram( program, 1, &deviceID, include_dir.c_str(), NULL, NULL ); + test_error( error, "Test program did not properly build" ); + + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Unable to get program build status" ); + + if( (int)status != CL_BUILD_SUCCESS ) + { + print_error( error, "Failed to build with include directory" ); + return -1; + } + + // Go ahead and run the program to verify results + cl_int firstResult, secondResult; + + error = get_result_from_program( context, queue, program, &firstResult ); + test_error( error, "Unable to get result from first program" ); + + if( firstResult != 12 ) + { + log_error( "ERROR: Result from first program did not validate! (Expected 12, got %d)\n", firstResult ); + return -1; + } + + // Rebuild with a different include directory + include_dir = "-I " + path + sep + "secondIncludeTestDirectory"; + error = clBuildProgram( program, 1, &deviceID, include_dir.c_str(), NULL, NULL ); + test_error( error, "Test program did not properly rebuild" ); + + error = get_result_from_program( context, queue, program, &secondResult ); + test_error( error, "Unable to get result from second program" ); + + if( secondResult != 42 ) + { + if( secondResult == firstResult ) + log_error( "ERROR: Program result did not change with include path change (program was not recompiled)!\n" ); + else + log_error( "ERROR: Result from second program did not validate! (Expected 42, got %d)\n", secondResult ); + return -1; + } + + return 0; +} + +const char *denorm_test_kernel[] = { + "__kernel void sample_test( float src1, float src2, __global float *dst)\n" + "{\n" + " dst[ 0 ] = src1 + src2;\n" + "\n" + "}\n" }; + +cl_int get_float_result_from_program( cl_context context, cl_command_queue queue, cl_program program, cl_float inA, cl_float inB, cl_float *outValue ) +{ + cl_int error; + + clKernelWrapper kernel = clCreateKernel( program, "sample_test", &error ); + test_error( error, "Unable to create kernel from program" ); + + clMemWrapper outStream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float), NULL, &error ); + test_error( error, "Unable to create test buffer" ); + + error = clSetKernelArg( kernel, 0, sizeof( cl_float ), &inA ); + test_error( error, "Unable to set kernel argument" ); + + error = clSetKernelArg( kernel, 1, sizeof( cl_float ), &inB ); + test_error( error, "Unable to set kernel argument" ); + + error = clSetKernelArg( kernel, 2, sizeof( outStream ), &outStream ); + test_error( error, "Unable to set kernel argument" ); + + size_t threads[1] = { 1 }; + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + error = clEnqueueReadBuffer( queue, outStream, true, 0, sizeof( cl_float ), outValue, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + return CL_SUCCESS; +} + +int test_options_denorm_cache(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + + clProgramWrapper program; + cl_build_status status; + + + // If denorms aren't even supported, testing this flag is pointless + cl_device_fp_config floatCaps = 0; + error = clGetDeviceInfo( deviceID, CL_DEVICE_SINGLE_FP_CONFIG, sizeof(floatCaps), &floatCaps, NULL); + test_error( error, "Unable to get device FP config" ); + if( ( floatCaps & CL_FP_DENORM ) == 0 ) + { + log_info( "Device does not support denormalized single-precision floats; skipping test.\n" ); + return 0; + } + + program = clCreateProgramWithSource( context, 1, denorm_test_kernel, NULL, &error ); + test_error( error, "Unable to create test program" ); + + // Build first WITH the denorm flush flag + error = clBuildProgram( program, 1, &deviceID, "-cl-denorms-are-zero", NULL, NULL ); + test_error( error, "Test program did not properly build" ); + + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Unable to get program build status" ); + + if( (int)status != CL_BUILD_SUCCESS ) + { + print_error( error, "Failed to build with include directory" ); + return -1; + } + + // Note: the following in floating point is a subnormal number, thus adding two of them together + // should give us a subnormalized result. If denormals are flushed to zero, however, it'll give us zero instead + uint32_t intSubnormal = 0x00000001; + cl_float *input = (cl_float *)&intSubnormal; + cl_float firstResult, secondResult; + + error = get_float_result_from_program( context, queue, program, *input, *input, &firstResult ); + test_error( error, "Unable to get result from first program" ); + + // Note: since -cl-denorms-are-zero is a HINT, not a requirement, the result we got could + // either be subnormal (hint ignored) or zero (hint respected). Since either is technically + // valid, there isn't anything we can to do validate results for now + + // Rebuild without flushing flag set + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Test program did not properly rebuild" ); + + error = get_float_result_from_program( context, queue, program, *input, *input, &secondResult ); + test_error( error, "Unable to get result from second program" ); + + // Now, there are three possiblities here: + // 1. The denorms-are-zero hint is not respected, in which case the first and second result will be identical + // 2. The hint is respected, and the program was properly rebuilt, in which case the first result will be zero and the second non-zero + // 3. The hint is respected, but the program was not properly rebuilt, in which case both results will be zero + // 3 is the only error condition we need to look for + uint32_t *fPtr = (uint32_t *)&firstResult; + uint32_t *sPtr = (uint32_t *)&secondResult; + + if( ( *fPtr == 0 ) && ( *sPtr == 0 ) ) + { + log_error( "ERROR: Program result didn't change when -cl-denorms-are-zero flag was removed.\n" + "First result (should be zero): 0x%08x, Second result (should be non-zero): 0x%08x\n", + *fPtr, *sPtr ); + return -1; + } + + return 0; +} + diff --git a/test_conformance/compiler/test_compile.c b/test_conformance/compiler/test_compile.c new file mode 100644 index 00000000..926d69bd --- /dev/null +++ b/test_conformance/compiler/test_compile.c @@ -0,0 +1,3170 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#if defined(_WIN32) +#include +#elif defined(__linux__) || defined(__APPLE__) +#include +#include +#endif +#include "../../test_common/harness/conversions.h" + +extern cl_uint gRandomSeed; + +#define MAX_LINE_SIZE_IN_PROGRAM 1024 +#define MAX_LOG_SIZE_IN_PROGRAM 2048 + +const char *sample_kernel_start = +"__kernel void sample_test(__global float *src, __global int *dst)\n" +"{\n" +" float temp;\n" +" int tid = get_global_id(0);\n"; + +const char *sample_kernel_end = "}\n"; + +const char *sample_kernel_lines[] = { +"dst[tid] = src[tid];\n", +"dst[tid] = src[tid] * 3.f;\n", +"temp = src[tid] / 4.f;\n", +"dst[tid] = dot(temp,src[tid]);\n", +"dst[tid] = dst[tid] + temp;\n" }; + +/* I compile and link therefore I am. Robert Ioffe */ +/* The following kernels are used in testing Improved Compilation and Linking feature */ + +const char *simple_kernel = +"__kernel void\n" +"CopyBuffer(\n" +" __global float* src,\n" +" __global float* dst )\n" +"{\n" +" int id = (int)get_global_id(0);\n" +" dst[id] = src[id];\n" +"}\n"; + +const char *simple_kernel_with_defines = +"__kernel void\n" +"CopyBuffer(\n" +" __global float* src,\n" +" __global float* dst )\n" +"{\n" +" int id = (int)get_global_id(0);\n" +" float temp = src[id] - 42;\n" +" dst[id] = FIRST + temp + SECOND;\n" +"}\n"; + +const char *simple_kernel_template = +"__kernel void\n" +"CopyBuffer%d(\n" +" __global float* src,\n" +" __global float* dst )\n" +"{\n" +" int id = (int)get_global_id(0);\n" +" dst[id] = src[id];\n" +"}\n"; + +const char *composite_kernel_start = +"__kernel void\n" +"CompositeKernel(\n" +" __global float* src,\n" +" __global float* dst )\n" +"{\n"; + +const char *composite_kernel_end = "}\n"; + +const char *composite_kernel_template = +" CopyBuffer%d(src, dst);\n"; + +const char *composite_kernel_extern_template = +"extern __kernel void\n" +"CopyBuffer%d(\n" +" __global float* src,\n" +" __global float* dst );\n"; + +const char *another_simple_kernel = +"extern __kernel void\n" +"CopyBuffer(\n" +" __global float* src,\n" +" __global float* dst );\n" +"__kernel void\n" +"AnotherCopyBuffer(\n" +" __global float* src,\n" +" __global float* dst )\n" +"{\n" +" CopyBuffer(src, dst);\n" +"}\n"; + +const char* simple_header = +"extern __kernel void\n" +"CopyBuffer(\n" +" __global float* src,\n" +" __global float* dst );\n"; + +const char* simple_header_name = "simple_header.h"; + +const char* another_simple_kernel_with_header = +"#include \"simple_header.h\"\n" +"__kernel void\n" +"AnotherCopyBuffer(\n" +" __global float* src,\n" +" __global float* dst )\n" +"{\n" +" CopyBuffer(src, dst);\n" +"}\n"; + +const char* header_name_templates[4] = { "simple_header%d.h", + "foo/simple_header%d.h", + "foo/bar/simple_header%d.h", + "foo/bar/baz/simple_header%d.h"}; + +const char* include_header_name_templates[4] = { "#include \"simple_header%d.h\"\n", + "#include \"foo/simple_header%d.h\"\n", + "#include \"foo/bar/simple_header%d.h\"\n", + "#include \"foo/bar/baz/simple_header%d.h\"\n"}; + +const char* compile_extern_var = "extern constant float foo;\n"; +const char* compile_extern_struct = "extern constant struct bar bart;\n"; +const char* compile_extern_function = "extern int baz(int, int);\n"; + +const char* compile_static_var = "static constant float foo = 2.78;\n"; +const char* compile_static_struct = "static constant struct bar {float x, y, z, r; int color; } foo = {3.14159};\n"; +const char* compile_static_function = "static int foo(int x, int y) { return x*x + y*y; }\n"; + +const char* compile_regular_var = "constant float foo = 4.0f;\n"; +const char* compile_regular_struct = "constant struct bar {float x, y, z, r; int color; } foo = {0.f, 0.f, 0.f, 0.f, 0};\n"; +const char* compile_regular_function = "int foo(int x, int y) { return x*x + y*y; }\n"; + +const char* link_static_var_access = // use with compile_static_var +"extern constant float foo;\n" +"float access_foo() { return foo; }\n"; + +const char* link_static_struct_access = // use with compile_static_struct +"extern constant struct bar{float x, y, z, r; int color; } foo;\n" +"struct bar access_foo() {return foo; }\n"; + +const char* link_static_function_access = // use with compile_static_function +"extern int foo(int, int);\n" +"int access_foo() { int blah = foo(3, 4); return blah + 5; }\n"; + +int test_large_single_compile(cl_context context, cl_device_id deviceID, unsigned int numLines) +{ + int error; + cl_program program; + const char **lines; + unsigned int numChoices, i; + MTdata d; + + /* First, allocate the array for our line pointers */ + lines = (const char **)malloc( numLines * sizeof( const char * ) ); + if (lines == NULL) { + log_error( "ERROR: Unable to allocate lines array with %d lines! (in %s:%d)\n", numLines, __FILE__, __LINE__); + return -1; + } + + /* First and last lines are easy */ + lines[ 0 ] = sample_kernel_start; + lines[ numLines - 1 ] = sample_kernel_end; + + numChoices = sizeof( sample_kernel_lines ) / sizeof( sample_kernel_lines[ 0 ] ); + + /* Fill the rest with random lines to hopefully prevent much optimization */ + d = init_genrand( gRandomSeed ); + for( i = 1; i < numLines - 1; i++ ) + { + lines[ i ] = sample_kernel_lines[ genrand_int32(d) % numChoices ]; + } + free_mtdata(d); d = NULL; + + /* Try to create a program with these lines */ + error = create_single_kernel_helper_create_program(context, &program, numLines, lines); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create long test program with %d lines! (%s in %s:%d)", numLines, IGetErrorString( error ), __FILE__, __LINE__ ); + free( lines ); + if (program != NULL) + { + error = clReleaseProgram( program ); + test_error( error, "Unable to release a program object" ); + } + return -1; + } + + /* Build it */ + error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + test_error( error, "Unable to build a long program" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release a program object" ); + + free( lines ); + + return 0; +} + +int test_large_compile(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + unsigned int toTest[] = { 64, 128, 256, 512, 1024, 2048, 4096, 0 }; //8192, 16384, 32768, 0 }; + unsigned int i; + + log_info( "Testing large compiles...this might take awhile...\n" ); + + for( i = 0; toTest[ i ] != 0; i++ ) + { + log_info( " %d...\n", toTest[ i ] ); + +#if defined(_WIN32) + clock_t start = clock(); +#elif defined(__linux__) || defined(__APPLE__) + timeval time1, time2; + gettimeofday(&time1, NULL); +#endif + + if( test_large_single_compile( context, deviceID, toTest[ i ] ) != 0 ) + { + log_error( "ERROR: long program test failed for %d lines! (in %s:%d)\n", toTest[ i ], __FILE__, __LINE__); + return -1; + } + +#if defined(_WIN32) + clock_t end = clock(); + log_perf( (float)( end - start ) / (float)CLOCKS_PER_SEC, false, "clock() time in secs", "%d lines", toTest[i] ); +#elif defined(__linux__) || defined(__APPLE__) + gettimeofday(&time2, NULL); + log_perf( (float)(float)(time2.tv_sec - time1.tv_sec) + 1.0e-6 * (time2.tv_usec - time1.tv_usec) , false, "wall time in secs", "%d lines", toTest[i] ); +#endif + } + + return 0; +} + +static int verifyCopyBuffer(cl_context context, cl_command_queue queue, cl_kernel kernel); + +#if defined(__APPLE__) || defined(__linux) +#define _strdup strdup +#endif + +int test_large_multi_file_library(cl_context context, cl_device_id deviceID, cl_command_queue queue, unsigned int numLines) +{ + int error; + cl_program program; + cl_program *simple_kernels; + const char **lines; + unsigned int i; + char buffer[MAX_LINE_SIZE_IN_PROGRAM]; + + simple_kernels = (cl_program*)malloc(numLines*sizeof(cl_program)); + if (simple_kernels == NULL) { + log_error( "ERROR: Unable to allocate kernels array with %d kernels! (in %s:%d)\n", numLines, __FILE__, __LINE__); + return -1; + } + /* First, allocate the array for our line pointers */ + lines = (const char **)malloc( (2*numLines + 2) * sizeof( const char * ) ); + if (lines == NULL) { + free(simple_kernels); + log_error( "ERROR: Unable to allocate lines array with %d lines! (in %s:%d)\n", (2*numLines + 2), __FILE__, __LINE__ ); + return -1; + } + + for( i = 0; i < numLines; i++) + { + sprintf(buffer, composite_kernel_extern_template, i); + lines[i] = _strdup(buffer); + } + /* First and last lines are easy */ + lines[ numLines ] = composite_kernel_start; + lines[ 2* numLines + 1] = composite_kernel_end; + + /* Fill the rest with templated kernels */ + for( i = numLines + 1; i < 2* numLines + 1; i++ ) + { + sprintf(buffer, composite_kernel_template, i - numLines - 1); + lines[ i ] = _strdup(buffer); + } + + /* Try to create a program with these lines */ + error = create_single_kernel_helper_create_program(context, &program, 2 * numLines + 2, lines); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create long test program with %d lines! (%s) (in %s:%d)\n", numLines, IGetErrorString( error ), __FILE__, __LINE__ ); + free( simple_kernels ); + for( i = 0; i < numLines; i++) + { + free( (void*)lines[i] ); + free( (void*)lines[i+numLines+1] ); + } + free( lines ); + if (program != NULL) + { + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + } + + return -1; + } + + /* Compile it */ + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + /* Create and compile templated kernels */ + for( i = 0; i < numLines; i++) + { + sprintf(buffer, simple_kernel_template, i); + const char* kernel_source = _strdup(buffer); + simple_kernels[i] = clCreateProgramWithSource( context, 1, &kernel_source, NULL, &error ); + if( simple_kernels[i] == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create long test program with %d lines! (%s) (in %s:%d)\n", numLines, IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + /* Compile it */ + error = clCompileProgram(simple_kernels[i], 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + free((void*)kernel_source); + } + + /* Create library out of compiled templated kernels */ + cl_program my_newly_minted_library = clLinkProgram(context, 1, &deviceID, "-create-library", numLines, simple_kernels, NULL, NULL, &error); + test_error( error, "Unable to create a multi-line library" ); + + /* Link the program that calls the kernels and the library that contains them */ + cl_program programs[2] = { program, my_newly_minted_library }; + cl_program my_newly_linked_program = clLinkProgram(context, 1, &deviceID, NULL, 2, programs, NULL, NULL, &error); + test_error( error, "Unable to link a program with a library" ); + + // Create the composite kernel + cl_kernel kernel = clCreateKernel(my_newly_linked_program, "CompositeKernel", &error); + test_error( error, "Unable to create a composite kernel" ); + + // Run the composite kernel and verify the results + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + for( i = 0; i < numLines; i++) + { + free( (void*)lines[i] ); + free( (void*)lines[i+numLines+1] ); + } + free( lines ); + + for(i = 0; i < numLines; i++) + { + error = clReleaseProgram( simple_kernels[i] ); + test_error( error, "Unable to release program object" ); + } + free( simple_kernels ); + + error = clReleaseKernel( kernel ); + test_error( error, "Unable to release kernel object" ); + + error = clReleaseProgram( my_newly_minted_library ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_multi_file_libraries(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + unsigned int toTest[] = { 2, 4, 8, 16, 32, 64, 128, 256, 0 }; // 512, 1024, 2048, 4096, 8192, 16384, 32768, 0 }; + unsigned int i; + + log_info( "Testing multi-file libraries ...this might take awhile...\n" ); + + for( i = 0; toTest[ i ] != 0; i++ ) + { + log_info( " %d...\n", toTest[ i ] ); + +#if defined(_WIN32) + clock_t start = clock(); +#elif defined(__linux__) || defined(__APPLE__) + timeval time1, time2; + gettimeofday(&time1, NULL); +#endif + + if( test_large_multi_file_library( context, deviceID, queue, toTest[ i ] ) != 0 ) + { + log_error( "ERROR: multi-file library program test failed for %d lines! (in %s:%d)\n\n", toTest[ i ], __FILE__, __LINE__ ); + return -1; + } + +#if defined(_WIN32) + clock_t end = clock(); + log_perf( (float)( end - start ) / (float)CLOCKS_PER_SEC, false, "clock() time in secs", "%d lines", toTest[i] ); +#elif defined(__linux__) || defined(__APPLE__) + gettimeofday(&time2, NULL); + log_perf( (float)(float)(time2.tv_sec - time1.tv_sec) + 1.0e-6 * (time2.tv_usec - time1.tv_usec) , false, "wall time in secs", "%d lines", toTest[i] ); +#endif + } + + return 0; +} + +int test_large_multiple_embedded_headers(cl_context context, cl_device_id deviceID, cl_command_queue queue, unsigned int numLines) +{ + int error; + cl_program program; + cl_program *simple_kernels; + cl_program *headers; + const char **header_names; + const char **lines; + unsigned int i; + char buffer[MAX_LINE_SIZE_IN_PROGRAM]; + + simple_kernels = (cl_program*)malloc(numLines*sizeof(cl_program)); + if (simple_kernels == NULL) { + log_error( "ERROR: Unable to allocate simple_kernels array with %d lines! (in %s:%d)\n", numLines, __FILE__, __LINE__ ); + return -1; + } + headers = (cl_program*)malloc(numLines*sizeof(cl_program)); + if (headers == NULL) { + log_error( "ERROR: Unable to allocate headers array with %d lines! (in %s:%d)\n", numLines, __FILE__, __LINE__ ); + return -1; + } + /* First, allocate the array for our line pointers */ + header_names = (const char**)malloc( numLines*sizeof( const char * ) ); + if (header_names == NULL) { + log_error( "ERROR: Unable to allocate header_names array with %d lines! (in %s:%d)\n", numLines, __FILE__, __LINE__ ); + return -1; + } + lines = (const char **)malloc( (2*numLines + 2)*sizeof( const char * ) ); + if (lines == NULL) { + log_error( "ERROR: Unable to allocate lines array with %d lines! (in %s:%d)\n", (2*numLines + 2), __FILE__, __LINE__ ); + return -1; + } + + for( i = 0; i < numLines; i++) + { + sprintf(buffer, include_header_name_templates[i % 4], i); + lines[i] = _strdup(buffer); + sprintf(buffer, header_name_templates[i % 4], i); + header_names[i] = _strdup(buffer); + + sprintf(buffer, composite_kernel_extern_template, i); + const char* line = _strdup(buffer); + error = create_single_kernel_helper_create_program(context, &headers[i], 1, &line); + if( headers[i] == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple header program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__); + return -1; + } + } + /* First and last lines are easy */ + lines[ numLines ] = composite_kernel_start; + lines[ 2* numLines + 1 ] = composite_kernel_end; + + /* Fill the rest with templated kernels */ + for( i = numLines + 1; i < 2* numLines + 1; i++ ) + { + sprintf(buffer, composite_kernel_template, i - numLines - 1); + lines[ i ] = _strdup(buffer); + } + + /* Try to create a program with these lines */ + error = create_single_kernel_helper_create_program(context, &program, 2 * numLines + 2, lines); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create long test program with %d lines! (%s) (in %s:%d)\n", numLines, IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + /* Compile it */ + error = clCompileProgram(program, 1, &deviceID, NULL, numLines, headers, header_names, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + /* Create and compile templated kernels */ + for( i = 0; i < numLines; i++) + { + sprintf(buffer, simple_kernel_template, i); + const char* kernel_source = _strdup(buffer); + error = create_single_kernel_helper_create_program(context, &simple_kernels[i], 1, &kernel_source); + if( simple_kernels[i] == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create long test program with %d lines! (%s) (in %s:%d)\n", numLines, IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + /* Compile it */ + error = clCompileProgram(simple_kernels[i], 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + free((void*)kernel_source); + } + + /* Create library out of compiled templated kernels */ + cl_program my_newly_minted_library = clLinkProgram(context, 1, &deviceID, "-create-library", numLines, simple_kernels, NULL, NULL, &error); + test_error( error, "Unable to create a multi-line library" ); + + /* Link the program that calls the kernels and the library that contains them */ + cl_program programs[2] = { program, my_newly_minted_library }; + cl_program my_newly_linked_program = clLinkProgram(context, 1, &deviceID, NULL, 2, programs, NULL, NULL, &error); + test_error( error, "Unable to link a program with a library" ); + + // Create the composite kernel + cl_kernel kernel = clCreateKernel(my_newly_linked_program, "CompositeKernel", &error); + test_error( error, "Unable to create a composite kernel" ); + + // Run the composite kernel and verify the results + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + for( i = 0; i < numLines; i++) + { + free( (void*)lines[i] ); + free( (void*)header_names[i] ); + } + for( i = numLines + 1; i < 2* numLines + 1; i++ ) + { + free( (void*)lines[i] ); + } + free( lines ); + free( header_names ); + + for(i = 0; i < numLines; i++) + { + error = clReleaseProgram( simple_kernels[i] ); + test_error( error, "Unable to release program object" ); + error = clReleaseProgram( headers[i] ); + test_error( error, "Unable to release header program object" ); + } + free( simple_kernels ); + free( headers ); + + error = clReleaseProgram( my_newly_minted_library ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_multiple_embedded_headers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + unsigned int toTest[] = { 2, 4, 8, 16, 32, 64, 128, 256, 0 }; // 512, 1024, 2048, 4096, 8192, 16384, 32768, 0 }; + unsigned int i; + + log_info( "Testing multiple embedded headers ...this might take awhile...\n" ); + + for( i = 0; toTest[ i ] != 0; i++ ) + { + log_info( " %d...\n", toTest[ i ] ); + +#if defined(_WIN32) + clock_t start = clock(); +#elif defined(__linux__) || defined(__APPLE__) + timeval time1, time2; + gettimeofday(&time1, NULL); +#endif + + if( test_large_multiple_embedded_headers( context, deviceID, queue, toTest[ i ] ) != 0 ) + { + log_error( "ERROR: multiple embedded headers program test failed for %d lines! (in %s:%d)\n", toTest[ i ], __FILE__, __LINE__ ); + return -1; + } + +#if defined(_WIN32) + clock_t end = clock(); + log_perf( (float)( end - start ) / (float)CLOCKS_PER_SEC, false, "clock() time in secs", "%d lines", toTest[i] ); +#elif defined(__linux__) || defined(__APPLE__) + gettimeofday(&time2, NULL); + log_perf( (float)(float)(time2.tv_sec - time1.tv_sec) + 1.0e-6 * (time2.tv_usec - time1.tv_usec) , false, "wall time in secs", "%d lines", toTest[i] ); +#endif + } + + return 0; +} + +double logbase(double a, double base) +{ + return log(a) / log(base); +} + +int test_large_multiple_libraries(cl_context context, cl_device_id deviceID, cl_command_queue queue, unsigned int numLines) +{ + int error; + cl_program *simple_kernels; + const char **lines; + unsigned int i; + char buffer[MAX_LINE_SIZE_IN_PROGRAM]; + /* I want to create (log2(N)+1)/2 libraries */ + unsigned int level = (unsigned int)(logbase(numLines, 2.0) + 1.000001)/2; + unsigned int numLibraries = (unsigned int)pow(2.0, level - 1.0); + unsigned int numFilesInLib = numLines/numLibraries; + cl_program *my_program_and_libraries = (cl_program*)malloc((1+numLibraries)*sizeof(cl_program)); + if (my_program_and_libraries == NULL) { + log_error( "ERROR: Unable to allocate program array with %d programs! (in %s:%d)\n", (1+numLibraries), __FILE__, __LINE__); + return -1; + } + + log_info("level - %d, numLibraries - %d, numFilesInLib - %d\n", level, numLibraries, numFilesInLib); + + simple_kernels = (cl_program*)malloc(numLines*sizeof(cl_program)); + if (simple_kernels == NULL) { + log_error( "ERROR: Unable to allocate kernels array with %d kernels! (in %s:%d)\n", numLines, __FILE__, __LINE__); + return -1; + } + /* First, allocate the array for our line pointers */ + lines = (const char **)malloc( (2*numLines + 2) * sizeof( const char * ) ); + if (lines == NULL) { + log_error( "ERROR: Unable to allocate lines array with %d lines! (in %s:%d)\n", (2*numLines + 2), __FILE__, __LINE__); + return -1; + } + + for(i = 0; i < numLines; i++) + { + sprintf(buffer, composite_kernel_extern_template, i); + lines[i] = _strdup(buffer); + } + /* First and last lines are easy */ + lines[ numLines ] = composite_kernel_start; + lines[ 2*numLines + 1] = composite_kernel_end; + + /* Fill the rest with templated kernels */ + for(i = numLines + 1; i < 2*numLines + 1; i++ ) + { + sprintf(buffer, composite_kernel_template, i - numLines - 1); + lines[ i ] = _strdup(buffer); + } + + /* Try to create a program with these lines */ + error = create_single_kernel_helper_create_program(context, &my_program_and_libraries[0], 2 * numLines + 2, lines); + if( my_program_and_libraries[0] == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create long test program with %d lines! (%s in %s:%d)\n", numLines, IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + /* Compile it */ + error = clCompileProgram(my_program_and_libraries[0], 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + /* Create and compile templated kernels */ + for(i = 0; i < numLines; i++) + { + sprintf(buffer, simple_kernel_template, i); + const char* kernel_source = _strdup(buffer); + error = create_single_kernel_helper_create_program(context, &simple_kernels[i], 1, &kernel_source); + if( simple_kernels[i] == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create long test program with %d lines! (%s in %s:%d)\n", numLines, IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + /* Compile it */ + error = clCompileProgram(simple_kernels[i], 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + free((void*)kernel_source); + } + + /* Create library out of compiled templated kernels */ + for(i = 0; i < numLibraries; i++) { + my_program_and_libraries[i+1] = clLinkProgram(context, 1, &deviceID, "-create-library", numFilesInLib, simple_kernels+i*numFilesInLib, NULL, NULL, &error); + test_error( error, "Unable to create a multi-line library" ); + } + + /* Link the program that calls the kernels and the library that contains them */ + cl_program my_newly_linked_program = clLinkProgram(context, 1, &deviceID, NULL, numLibraries+1, my_program_and_libraries, NULL, NULL, &error); + test_error( error, "Unable to link a program with a library" ); + + // Create the composite kernel + cl_kernel kernel = clCreateKernel(my_newly_linked_program, "CompositeKernel", &error); + test_error( error, "Unable to create a composite kernel" ); + + // Run the composite kernel and verify the results + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + for(i = 0; i <= numLibraries; i++) { + error = clReleaseProgram( my_program_and_libraries[i] ); + test_error( error, "Unable to release program object" ); + } + free( my_program_and_libraries ); + for(i = 0; i < numLines; i++) + { + free( (void*)lines[i] ); + } + for(i = numLines + 1; i < 2*numLines + 1; i++ ) + { + free( (void*)lines[i] ); + } + free( lines ); + + for(i = 0; i < numLines; i++) + { + error = clReleaseProgram( simple_kernels[i] ); + test_error( error, "Unable to release program object" ); + } + free( simple_kernels ); + + error = clReleaseProgram( my_newly_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_multiple_libraries(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + unsigned int toTest[] = { 2, 8, 32, 128, 256, 0 }; // 512, 2048, 8192, 32768, 0 }; + unsigned int i; + + log_info( "Testing multiple libraries ...this might take awhile...\n" ); + + for( i = 0; toTest[ i ] != 0; i++ ) + { + log_info( " %d...\n", toTest[ i ] ); + +#if defined(_WIN32) + clock_t start = clock(); +#elif defined(__linux__) || defined(__APPLE__) + timeval time1, time2; + gettimeofday(&time1, NULL); +#endif + + if( test_large_multiple_libraries( context, deviceID, queue, toTest[ i ] ) != 0 ) + { + log_error( "ERROR: multiple library program test failed for %d lines! (in %s:%d)\n\n", toTest[ i ], __FILE__, __LINE__ ); + return -1; + } + +#if defined(_WIN32) + clock_t end = clock(); + log_perf( (float)( end - start ) / (float)CLOCKS_PER_SEC, false, "clock() time in secs", "%d lines", toTest[i] ); +#elif defined(__linux__) || defined(__APPLE__) + gettimeofday(&time2, NULL); + log_perf( (float)(float)(time2.tv_sec - time1.tv_sec) + 1.0e-6 * (time2.tv_usec - time1.tv_usec) , false, "wall time in secs", "%d lines", toTest[i] ); +#endif + } + + return 0; +} + +int test_large_multiple_files_multiple_libraries(cl_context context, cl_device_id deviceID, cl_command_queue queue, unsigned int numLines) +{ + int error; + cl_program *simple_kernels; + const char **lines; + unsigned int i; + char buffer[MAX_LINE_SIZE_IN_PROGRAM]; + /* I want to create (log2(N)+1)/4 libraries */ + unsigned int level = (unsigned int)(logbase(numLines, 2.0) + 1.000001)/2; + unsigned int numLibraries = (unsigned int)pow(2.0, level - 2.0); + unsigned int numFilesInLib = numLines/(2*numLibraries); + cl_program *my_programs_and_libraries = (cl_program*)malloc((1+numLibraries+numLibraries*numFilesInLib)*sizeof(cl_program)); + if (my_programs_and_libraries == NULL) { + log_error( "ERROR: Unable to allocate program array with %d programs! (in %s:%d)\n", (1+numLibraries+numLibraries*numFilesInLib), __FILE__, __LINE__ ); + return -1; + } + log_info("level - %d, numLibraries - %d, numFilesInLib - %d\n", level, numLibraries, numFilesInLib); + + simple_kernels = (cl_program*)malloc(numLines*sizeof(cl_program)); + if (simple_kernels == NULL) { + log_error( "ERROR: Unable to allocate kernels array with %d kernels! (in %s:%d)\n", numLines, __FILE__, __LINE__ ); + return -1; + } + /* First, allocate the array for our line pointers */ + lines = (const char **)malloc( (2*numLines + 2) * sizeof( const char * ) ); + if (lines == NULL) { + log_error( "ERROR: Unable to allocate lines array with %d lines! (in %s:%d)\n", (2*numLines + 2), __FILE__, __LINE__ ); + return -1; + } + + for(i = 0; i < numLines; i++) + { + sprintf(buffer, composite_kernel_extern_template, i); + lines[i] = _strdup(buffer); + } + /* First and last lines are easy */ + lines[ numLines ] = composite_kernel_start; + lines[ 2*numLines + 1] = composite_kernel_end; + + /* Fill the rest with templated kernels */ + for(i = numLines + 1; i < 2*numLines + 1; i++ ) + { + sprintf(buffer, composite_kernel_template, i - numLines - 1); + lines[ i ] = _strdup(buffer); + } + + /* Try to create a program with these lines */ + error = create_single_kernel_helper_create_program(context, &my_programs_and_libraries[0], 2 * numLines + 2, lines); + if( my_programs_and_libraries[0] == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create long test program with %d lines! (%s in %s:%d)\n", numLines, IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + /* Compile it */ + error = clCompileProgram(my_programs_and_libraries[0], 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + /* Create and compile templated kernels */ + for(i = 0; i < numLines; i++) + { + sprintf(buffer, simple_kernel_template, i); + const char* kernel_source = _strdup(buffer); + error = create_single_kernel_helper_create_program(context, &simple_kernels[i], 1, &kernel_source); + if( simple_kernels[i] == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create long test program with %d lines! (%s in %s:%d)\n", numLines, IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + /* Compile it */ + error = clCompileProgram(simple_kernels[i], 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + free((void*)kernel_source); + } + + /* Copy already compiled kernels */ + for( i = 0; i < numLibraries*numFilesInLib; i++) { + my_programs_and_libraries[i+1] = simple_kernels[i]; + } + + /* Create library out of compiled templated kernels */ + for( i = 0; i < numLibraries; i++) { + my_programs_and_libraries[i+1+numLibraries*numFilesInLib] = clLinkProgram(context, 1, &deviceID, "-create-library", numFilesInLib, simple_kernels+(i*numFilesInLib+numLibraries*numFilesInLib), NULL, NULL, &error); + test_error( error, "Unable to create a multi-line library" ); + } + + /* Link the program that calls the kernels and the library that contains them */ + cl_program my_newly_linked_program = clLinkProgram(context, 1, &deviceID, NULL, numLibraries+1+numLibraries*numFilesInLib, my_programs_and_libraries, NULL, NULL, &error); + test_error( error, "Unable to link a program with a library" ); + + // Create the composite kernel + cl_kernel kernel = clCreateKernel(my_newly_linked_program, "CompositeKernel", &error); + test_error( error, "Unable to create a composite kernel" ); + + // Run the composite kernel and verify the results + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + for(i = 0; i < numLibraries+1+numLibraries*numFilesInLib; i++) { + error = clReleaseProgram( my_programs_and_libraries[i] ); + test_error( error, "Unable to release program object" ); + } + free( my_programs_and_libraries ); + + for(i = 0; i < numLines; i++) + { + free( (void*)lines[i] ); + } + for(i = numLines + 1; i < 2*numLines + 1; i++ ) + { + free( (void*)lines[i] ); + } + free( lines ); + + for(i = numLibraries*numFilesInLib; i < numLines; i++) + { + error = clReleaseProgram( simple_kernels[i] ); + test_error( error, "Unable to release program object" ); + } + free( simple_kernels ); + + error = clReleaseProgram( my_newly_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_multiple_files_multiple_libraries(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + unsigned int toTest[] = { 8, 32, 128, 256, 0 }; // 512, 2048, 8192, 32768, 0 }; + unsigned int i; + + log_info( "Testing multiple files and multiple libraries ...this might take awhile...\n" ); + + for( i = 0; toTest[ i ] != 0; i++ ) + { + log_info( " %d...\n", toTest[ i ] ); + +#if defined(_WIN32) + clock_t start = clock(); +#elif defined(__linux__) || defined(__APPLE__) + timeval time1, time2; + gettimeofday(&time1, NULL); +#endif + + if( test_large_multiple_files_multiple_libraries( context, deviceID, queue, toTest[ i ] ) != 0 ) + { + log_error( "ERROR: multiple files, multiple libraries program test failed for %d lines! (in %s:%d)\n\n", toTest[ i ], __FILE__, __LINE__ ); + return -1; + } + +#if defined(_WIN32) + clock_t end = clock(); + log_perf( (float)( end - start ) / (float)CLOCKS_PER_SEC, false, "clock() time in secs", "%d lines", toTest[i] ); +#elif defined(__linux__) || defined(__APPLE__) + gettimeofday(&time2, NULL); + log_perf( (float)(float)(time2.tv_sec - time1.tv_sec) + 1.0e-6 * (time2.tv_usec - time1.tv_usec) , false, "wall time in secs", "%d lines", toTest[i] ); +#endif + } + + return 0; +} + +int test_large_multiple_files(cl_context context, cl_device_id deviceID, cl_command_queue queue, unsigned int numLines) +{ + int error; + const char **lines; + unsigned int i; + char buffer[MAX_LINE_SIZE_IN_PROGRAM]; + cl_program *my_programs = (cl_program*)malloc((1+numLines)*sizeof(cl_program)); + + if (my_programs == NULL) { + log_error( "ERROR: Unable to allocate my_programs array with %d programs! (in %s:%d)\n", (1+numLines), __FILE__, __LINE__); + return -1; + } + /* First, allocate the array for our line pointers */ + lines = (const char **)malloc( (2*numLines + 2) * sizeof( const char * ) ); + if (lines == NULL) { + log_error( "ERROR: Unable to allocate lines array with %d lines! (in %s:%d)\n", (2*numLines + 2), __FILE__, __LINE__); + return -1; + } + + for(i = 0; i < numLines; i++) + { + sprintf(buffer, composite_kernel_extern_template, i); + lines[i] = _strdup(buffer); + } + /* First and last lines are easy */ + lines[ numLines ] = composite_kernel_start; + lines[ 2* numLines + 1] = composite_kernel_end; + + /* Fill the rest with templated kernels */ + for(i = numLines + 1; i < 2*numLines + 1; i++ ) + { + sprintf(buffer, composite_kernel_template, i - numLines - 1); + lines[ i ] = _strdup(buffer); + } + + /* Try to create a program with these lines */ + error = create_single_kernel_helper_create_program(context, &my_programs[0], 2 * numLines + 2, lines); + if( my_programs[0] == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create long test program with %d lines! (%s in %s:%d)\n", numLines, IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + /* Compile it */ + error = clCompileProgram(my_programs[0], 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + /* Create and compile templated kernels */ + for( i = 0; i < numLines; i++) + { + sprintf(buffer, simple_kernel_template, i); + const char* kernel_source = _strdup(buffer); + error = create_single_kernel_helper_create_program(context, &my_programs[i + 1], 1, &kernel_source); + if( my_programs[i+1] == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create long test program with %d lines! (%s in %s:%d)\n", numLines, IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + /* Compile it */ + error = clCompileProgram(my_programs[i+1], 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + free((void*)kernel_source); + } + + /* Link the program that calls the kernels and the library that contains them */ + cl_program my_newly_linked_program = clLinkProgram(context, 1, &deviceID, NULL, 1+numLines, my_programs, NULL, NULL, &error); + test_error( error, "Unable to link a program with a library" ); + + // Create the composite kernel + cl_kernel kernel = clCreateKernel(my_newly_linked_program, "CompositeKernel", &error); + test_error( error, "Unable to create a composite kernel" ); + + // Run the composite kernel and verify the results + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + for(i = 0; i < 1+numLines; i++) { + error = clReleaseProgram( my_programs[i] ); + test_error( error, "Unable to release program object" ); + } + free( my_programs ); + for(i = 0; i < numLines; i++) + { + free( (void*)lines[i] ); + } + for(i = numLines + 1; i < 2*numLines + 1; i++ ) + { + free( (void*)lines[i] ); + } + free( lines ); + + error = clReleaseProgram( my_newly_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_multiple_files(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + unsigned int toTest[] = { 8, 32, 128, 256, 0 }; // 512, 2048, 8192, 32768, 0 }; + unsigned int i; + + log_info( "Testing multiple files compilation and linking into a single executable ...this might take awhile...\n" ); + + for( i = 0; toTest[ i ] != 0; i++ ) + { + log_info( " %d...\n", toTest[ i ] ); + +#if defined(_WIN32) + clock_t start = clock(); +#elif defined(__linux__) || defined(__APPLE__) + timeval time1, time2; + gettimeofday(&time1, NULL); +#endif + + if( test_large_multiple_files( context, deviceID, queue, toTest[ i ] ) != 0 ) + { + log_error( "ERROR: multiple files program test failed for %d lines! (in %s:%d)\n\n", toTest[ i ], __FILE__, __LINE__ ); + return -1; + } + +#if defined(_WIN32) + clock_t end = clock(); + log_perf( (float)( end - start ) / (float)CLOCKS_PER_SEC, false, "clock() time in secs", "%d lines", toTest[i] ); +#elif defined(__linux__) || defined(__APPLE__) + gettimeofday(&time2, NULL); + log_perf( (float)(float)(time2.tv_sec - time1.tv_sec) + 1.0e-6 * (time2.tv_usec - time1.tv_usec) , false, "wall time in secs", "%d lines", toTest[i] ); +#endif + } + + return 0; +} + +int test_simple_compile_only(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + + log_info("Testing a simple compilation only...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_simple_static_compile_only(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + + log_info("Testing a simple static compilations only...\n"); + + error = create_single_kernel_helper_create_program(context, &program, 1, &compile_static_var); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple static variable test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + log_info("Compiling a static variable...\n"); + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple static variable program" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = create_single_kernel_helper_create_program(context, &program, 1, &compile_static_struct); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple static struct test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + log_info("Compiling a static struct...\n"); + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple static variable program" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = create_single_kernel_helper_create_program(context, &program, 1, &compile_static_function); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple static function test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + log_info("Compiling a static function...\n"); + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple static function program" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_simple_extern_compile_only(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + + log_info("Testing a simple extern compilations only...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_header); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple extern kernel test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + log_info("Compiling an extern kernel...\n"); + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple extern kernel program" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = create_single_kernel_helper_create_program(context, &program, 1, &compile_extern_var); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple extern variable test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + log_info("Compiling an extern variable...\n"); + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple extern variable program" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = create_single_kernel_helper_create_program(context, &program, 1, &compile_extern_struct); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple extern struct test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + log_info("Compiling an extern struct...\n"); + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple extern variable program" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = create_single_kernel_helper_create_program(context, &program, 1, &compile_extern_function); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple extern function test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + log_info("Compiling an extern function...\n"); + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple extern function program" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +struct simple_user_data { + const char* m_message; + cl_event m_event; +}; + +const char* once_upon_a_midnight_dreary = "Once upon a midnight dreary!"; + +static void CL_CALLBACK simple_compile_callback(cl_program program, void* user_data) +{ + simple_user_data* simple_compile_user_data = (simple_user_data*)user_data; + log_info("in the simple_compile_callback: program %p just completed compiling with '%s'\n", program, simple_compile_user_data->m_message); + if (strcmp(once_upon_a_midnight_dreary, simple_compile_user_data->m_message) != 0) + { + log_error("ERROR: in the simple_compile_callback: Expected '%s' and got %s (in %s:%d)!\n", once_upon_a_midnight_dreary, simple_compile_user_data->m_message, __FILE__, __LINE__); + } + + int error; + log_info("in the simple_compile_callback: program %p just completed compiling with '%p'\n", program, simple_compile_user_data->m_event); + + error = clSetUserEventStatus(simple_compile_user_data->m_event, CL_COMPLETE); + if (error != CL_SUCCESS) + { + log_error( "ERROR: in the simple_compile_callback: Unable to set user event status to CL_COMPLETE! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + exit(-1); + } + log_info("in the simple_compile_callback: Successfully signaled compile_program_completion_event!\n"); +} + +int test_simple_compile_with_callback(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + cl_event compile_program_completion_event; + + log_info("Testing a simple compilation with callback...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + compile_program_completion_event = clCreateUserEvent(context, &error); + test_error( error, "Unable to create a user event"); + + simple_user_data simple_compile_user_data = {once_upon_a_midnight_dreary, compile_program_completion_event}; + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, simple_compile_callback, (void*)&simple_compile_user_data); + test_error( error, "Unable to compile a simple program with a callback" ); + + error = clWaitForEvents(1, &compile_program_completion_event); + test_error( error, "clWaitForEvents failed when waiting on compile_program_completion_event"); + + /* All done! */ + error = clReleaseEvent(compile_program_completion_event); + test_error( error, "Unable to release event object" ); + + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_simple_embedded_header_compile(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program, header; + + log_info("Testing a simple embedded header compile only...\n"); + program = clCreateProgramWithSource(context, 1, &another_simple_kernel_with_header, NULL, &error); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + header = clCreateProgramWithSource(context, 1, &simple_header, NULL, &error); + if( header == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple header program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 1, &header, &simple_header_name, NULL, NULL); + test_error( error, "Unable to compile a simple program with embedded header" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_simple_link_only(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + + log_info("Testing a simple linking only...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program my_newly_linked_program = clLinkProgram(context, 1, &deviceID, NULL, 1, &program, NULL, NULL, &error); + test_error( error, "Unable to link a simple program" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_two_file_regular_variable_access(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program, second_program, my_newly_linked_program; + + const char* sources[2] = {simple_kernel, compile_regular_var}; // here we want to avoid linking error due to lack of kernels + log_info("Compiling and linking two program objects, where one tries to access regular variable from another...\n"); + error = create_single_kernel_helper_create_program(context, &program, 2, sources); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a test program with regular variable! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program with regular function" ); + + error = create_single_kernel_helper_create_program(context, &second_program, 1, &link_static_var_access); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a test program that tries to access a regular variable! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(second_program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a program that tries to access a regular variable" ); + + cl_program two_programs[2] = { program, second_program }; + my_newly_linked_program = clLinkProgram(context, 1, &deviceID, NULL, 2, two_programs, NULL, NULL, &error); + test_error( error, "clLinkProgram: Expected a different error code while linking a program that tries to access a regular variable" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( second_program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_two_file_regular_struct_access(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program, second_program, my_newly_linked_program; + + const char* sources[2] = {simple_kernel, compile_regular_struct}; // here we want to avoid linking error due to lack of kernels + log_info("Compiling and linking two program objects, where one tries to access regular struct from another...\n"); + error = create_single_kernel_helper_create_program(context, &program, 2, sources); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a test program with regular struct! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program with regular struct" ); + + error = create_single_kernel_helper_create_program(context, &second_program, 1, &link_static_struct_access); + if( second_program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a test program that tries to access a regular struct! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(second_program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a program that tries to access a regular struct" ); + + cl_program two_programs[2] = { program, second_program }; + my_newly_linked_program = clLinkProgram(context, 1, &deviceID, NULL, 2, two_programs, NULL, NULL, &error); + test_error( error, "clLinkProgram: Expected a different error code while linking a program that tries to access a regular struct" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( second_program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + + +int test_two_file_regular_function_access(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program, second_program, my_newly_linked_program; + + const char* sources[2] = {simple_kernel, compile_regular_function}; // here we want to avoid linking error due to lack of kernels + log_info("Compiling and linking two program objects, where one tries to access regular function from another...\n"); + error = create_single_kernel_helper_create_program(context, &program, 2, sources); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a test program with regular function! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program with regular function" ); + + error = create_single_kernel_helper_create_program(context, &second_program, 1, &link_static_function_access); + if( second_program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a test program that tries to access a regular function! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(second_program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a program that tries to access a regular function" ); + + cl_program two_programs[2] = { program, second_program }; + my_newly_linked_program = clLinkProgram(context, 1, &deviceID, NULL, 2, two_programs, NULL, NULL, &error); + test_error( error, "clLinkProgram: Expected a different error code while linking a program that tries to access a regular function" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( second_program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_simple_embedded_header_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program, header, simple_program; + + log_info("Testing a simple embedded header link...\n"); + program = clCreateProgramWithSource(context, 1, &another_simple_kernel_with_header, NULL, &error); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + header = clCreateProgramWithSource(context, 1, &simple_header, NULL, &error); + if( header == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple header program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 1, &header, &simple_header_name, NULL, NULL); + test_error( error, "Unable to compile a simple program with embedded header" ); + + error = create_single_kernel_helper_create_program(context, &simple_program, 1, &simple_kernel); + if( simple_program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(simple_program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program two_programs[2] = { program, simple_program }; + cl_program fully_linked_program = clLinkProgram(context, 1, &deviceID, "", 2, two_programs, NULL, NULL, &error); + test_error( error, "Unable to create an executable from two binaries, one compiled with embedded header" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( simple_program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( fully_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +const char* when_i_pondered_weak_and_weary = "When I pondered weak and weary!"; + +static void CL_CALLBACK simple_link_callback(cl_program program, void* user_data) +{ + simple_user_data* simple_link_user_data = (simple_user_data*)user_data; + log_info("in the simple_link_callback: program %p just completed linking with '%s'\n", program, (const char*)simple_link_user_data->m_message); + if (strcmp(when_i_pondered_weak_and_weary, simple_link_user_data->m_message) != 0) + { + log_error("ERROR: in the simple_compile_callback: Expected '%s' and got %s! (in %s:%d)\n", when_i_pondered_weak_and_weary, simple_link_user_data->m_message, __FILE__, __LINE__); + } + + int error; + log_info("in the simple_link_callback: program %p just completed linking with '%p'\n", program, simple_link_user_data->m_event); + + error = clSetUserEventStatus(simple_link_user_data->m_event, CL_COMPLETE); + if (error != CL_SUCCESS) + { + log_error( "ERROR: simple_link_callback: Unable to set user event status to CL_COMPLETE! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + exit(-1); + } + log_info("in the simple_link_callback: Successfully signaled link_program_completion_event event!\n"); +} + +int test_simple_link_with_callback(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + cl_event link_program_completion_event; + + log_info("Testing a simple linking with callback...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + link_program_completion_event = clCreateUserEvent(context, &error); + test_error( error, "Unable to create a user event"); + + simple_user_data simple_link_user_data = {when_i_pondered_weak_and_weary, link_program_completion_event}; + + clLinkProgram(context, 1, &deviceID, NULL, 1, &program, simple_link_callback, (void*)&simple_link_user_data, &error); + test_error( error, "Unable to link a simple program" ); + + error = clWaitForEvents(1, &link_program_completion_event); + test_error( error, "clWaitForEvents failed when waiting on link_program_completion_event"); + + /* All done! */ + error = clReleaseEvent(link_program_completion_event); + test_error( error, "Unable to release event object" ); + + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +static void initBuffer(float* & srcBuffer, unsigned int cnDimension) +{ + float num = 0.0f; + + for( unsigned int i = 0; i < cnDimension; i++ ) + { + if( ( i % 10 ) == 0 ) + { + num = 0.0f; + } + + srcBuffer[ i ] = num; + num = num + 1.0f; + } +} + +static int verifyCopyBuffer(cl_context context, cl_command_queue queue, cl_kernel kernel) +{ + int error, result = CL_SUCCESS; + const size_t cnDimension = 32; + + // Allocate source buffer + float * srcBuffer = (float*)malloc(cnDimension * sizeof(float)); + float * dstBuffer = (float*)malloc(cnDimension * sizeof(float)); + + if (srcBuffer == NULL) { + log_error( "ERROR: Unable to allocate srcBuffer float array with %lu floats! (in %s:%d)\n", cnDimension, __FILE__, __LINE__); + return -1; + } + if (dstBuffer == NULL) { + log_error( "ERROR: Unable to allocate dstBuffer float array with %lu floats! (in %s:%d)\n", cnDimension, __FILE__, __LINE__); + return -1; + } + + if( srcBuffer && dstBuffer ) + { + // initialize host memory + initBuffer(srcBuffer, cnDimension ); + + // Allocate device memory + cl_mem deviceMemSrc = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + cnDimension * sizeof( cl_float ), srcBuffer, &error); + test_error( error, "Unable to create a source memory buffer" ); + + cl_mem deviceMemDst = clCreateBuffer(context, CL_MEM_WRITE_ONLY, + cnDimension * sizeof( cl_float ), 0, &error); + test_error( error, "Unable to create a destination memory buffer" ); + + // Set kernel args + // Set parameter 0 to be the source buffer + error = clSetKernelArg(kernel, 0, sizeof( cl_mem ), ( void * )&deviceMemSrc ); + test_error( error, "Unable to set the first kernel argument" ); + + // Set parameter 1 to be the destination buffer + error = clSetKernelArg(kernel, 1, sizeof( cl_mem ), ( void * )&deviceMemDst ); + test_error( error, "Unable to set the second kernel argument" ); + + // Execute kernel + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, + &cnDimension, 0, 0, NULL, NULL ); + test_error( error, "Unable to enqueue kernel" ); + + error = clFlush( queue ); + test_error( error, "Unable to flush the queue" ); + + // copy results from device back to host + error = clEnqueueReadBuffer(queue, deviceMemDst, CL_TRUE, 0, cnDimension * sizeof( cl_float ), + dstBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read the destination buffer" ); + + error = clFlush( queue ); + test_error( error, "Unable to flush the queue" ); + + // Compare the source and destination buffers + const int* pSrc = (int*)srcBuffer; + const int* pDst = (int*)dstBuffer; + int mismatch = 0; + + for( size_t i = 0; i < cnDimension; i++ ) + { + if( pSrc[i] != pDst[i] ) + { + if( mismatch < 4 ) + { + log_info("Offset %08lX: Expected %08X, Got %08X\n", i * 4, pSrc[i], pDst[i] ); + } + else + { + log_info("."); + } + mismatch++; + } + } + + if( mismatch ) + { + log_info("*** %d mismatches found, TEST FAILS! ***\n", mismatch ); + result = -1; + } + else + { + log_info("Buffers match, test passes.\n"); + } + + free( srcBuffer ); + srcBuffer = NULL; + free( dstBuffer ); + dstBuffer = NULL; + + if( deviceMemSrc ) + { + error = clReleaseMemObject( deviceMemSrc ); + test_error( error, "Unable to release memory object" ); + } + + if( deviceMemDst ) + { + error = clReleaseMemObject( deviceMemDst ); + test_error( error, "Unable to release memory object" ); + } + } + return result; +} + +int test_execute_after_simple_compile_and_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + + log_info("Testing execution after a simple compile and link...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program my_newly_linked_program = clLinkProgram(context, 1, &deviceID, NULL, 1, &program, NULL, NULL, &error); + test_error( error, "Unable to link a simple program" ); + + cl_kernel kernel = clCreateKernel(my_newly_linked_program, "CopyBuffer", &error); + test_error( error, "Unable to create a simple kernel" ); + + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_execute_after_simple_compile_and_link_no_device_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + + log_info("Testing execution after a simple compile and link with no device information provided...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 0, NULL, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program my_newly_linked_program = clLinkProgram(context, 0, NULL, NULL, 1, &program, NULL, NULL, &error); + test_error( error, "Unable to link a simple program" ); + + cl_kernel kernel = clCreateKernel(my_newly_linked_program, "CopyBuffer", &error); + test_error( error, "Unable to create a simple kernel" ); + + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_execute_after_simple_compile_and_link_with_defines(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + + log_info("Testing execution after a simple compile and link with defines...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel_with_defines, "-DFIRST=5 -DSECOND=37"); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, "-DFIRST=5 -DSECOND=37", 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program my_newly_linked_program = clLinkProgram(context, 1, &deviceID, NULL, 1, &program, NULL, NULL, &error); + test_error( error, "Unable to link a simple program" ); + + cl_kernel kernel = clCreateKernel(my_newly_linked_program, "CopyBuffer", &error); + test_error( error, "Unable to create a simple kernel" ); + + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_execute_after_serialize_reload_object(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + size_t binarySize; + unsigned char *binary; + + log_info("Testing execution after serialization and reloading of the object...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + // Get the size of the resulting binary (only one device) + error = clGetProgramInfo( program, CL_PROGRAM_BINARY_SIZES, sizeof( binarySize ), &binarySize, NULL ); + test_error( error, "Unable to get binary size" ); + + // Sanity check + if( binarySize == 0 ) + { + log_error( "ERROR: Binary size of program is zero (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + + // Create a buffer and get the actual binary + binary = (unsigned char*)malloc(sizeof(unsigned char)*binarySize); + if (binary == NULL) { + log_error( "ERROR: Unable to allocate binary character array with %lu characters! (in %s:%d)\n", binarySize, __FILE__, __LINE__ ); + return -1; + } + + unsigned char *buffers[ 1 ] = { binary }; + cl_int loadErrors[ 1 ]; + + // Do another sanity check here first + size_t size; + error = clGetProgramInfo( program, CL_PROGRAM_BINARIES, 0, NULL, &size ); + test_error( error, "Unable to get expected size of binaries array" ); + if( size != sizeof( buffers ) ) + { + log_error( "ERROR: Expected size of binaries array in clGetProgramInfo is incorrect (should be %d, got %d) (in %s:%d)\n", (int)sizeof( buffers ), (int)size, __FILE__, __LINE__ ); + free(binary); + return -1; + } + + error = clGetProgramInfo( program, CL_PROGRAM_BINARIES, sizeof( buffers ), &buffers, NULL ); + test_error( error, "Unable to get program binary" ); + + // use clCreateProgramWithBinary + cl_program program_with_binary = clCreateProgramWithBinary(context, 1, &deviceID, &binarySize, (const unsigned char**)buffers, loadErrors, &error); + test_error( error, "Unable to create program with binary" ); + + cl_program my_newly_linked_program = clLinkProgram(context, 1, &deviceID, NULL, 1, &program_with_binary, NULL, NULL, &error); + test_error( error, "Unable to link a simple program" ); + + cl_kernel kernel = clCreateKernel(my_newly_linked_program, "CopyBuffer", &error); + test_error( error, "Unable to create a simple kernel" ); + + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_linked_program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( program_with_binary ); + test_error( error, "Unable to release program object" ); + + free(binary); + + return 0; +} + +int test_execute_after_serialize_reload_library(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program, another_program; + size_t binarySize; + unsigned char *binary; + + log_info("Testing execution after linking a binary with a simple library...\n"); + // we will test creation of a simple library from one file + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program my_newly_minted_library = clLinkProgram(context, 1, &deviceID, "-create-library", 1, &program, NULL, NULL, &error); + test_error( error, "Unable to create a simple library" ); + + + // Get the size of the resulting library (only one device) + error = clGetProgramInfo( my_newly_minted_library, CL_PROGRAM_BINARY_SIZES, sizeof( binarySize ), &binarySize, NULL ); + test_error( error, "Unable to get binary size" ); + + // Sanity check + if( binarySize == 0 ) + { + log_error( "ERROR: Binary size of program is zero (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + + // Create a buffer and get the actual binary + binary = (unsigned char*)malloc(sizeof(unsigned char)*binarySize); + if (binary == NULL) { + log_error( "ERROR: Unable to allocate binary character array with %lu characters (in %s:%d)!", binarySize, __FILE__, __LINE__); + return -1; + } + unsigned char *buffers[ 1 ] = { binary }; + cl_int loadErrors[ 1 ]; + + // Do another sanity check here first + size_t size; + error = clGetProgramInfo( my_newly_minted_library, CL_PROGRAM_BINARIES, 0, NULL, &size ); + test_error( error, "Unable to get expected size of binaries array" ); + if( size != sizeof( buffers ) ) + { + log_error( "ERROR: Expected size of binaries array in clGetProgramInfo is incorrect (should be %d, got %d) (in %s:%d)\n", (int)sizeof( buffers ), (int)size, __FILE__, __LINE__ ); + free(binary); + return -1; + } + + error = clGetProgramInfo( my_newly_minted_library, CL_PROGRAM_BINARIES, sizeof( buffers ), &buffers, NULL ); + test_error( error, "Unable to get program binary" ); + + // use clCreateProgramWithBinary + cl_program library_with_binary = clCreateProgramWithBinary(context, 1, &deviceID, &binarySize, (const unsigned char**)buffers, loadErrors, &error); + test_error( error, "Unable to create program with binary" ); + + error = create_single_kernel_helper_create_program(context, &another_program, 1, &another_simple_kernel); + if( another_program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(another_program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program program_and_archive[2] = { another_program, library_with_binary }; + cl_program fully_linked_program = clLinkProgram(context, 1, &deviceID, "", 2, program_and_archive, NULL, NULL, &error); + test_error( error, "Unable to create an executable from a binary and a library" ); + + cl_kernel kernel = clCreateKernel(fully_linked_program, "CopyBuffer", &error); + test_error( error, "Unable to create a simple kernel" ); + + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + cl_kernel another_kernel = clCreateKernel(fully_linked_program, "AnotherCopyBuffer", &error); + test_error( error, "Unable to create another simple kernel" ); + + error = verifyCopyBuffer(context, queue, another_kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( another_program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_minted_library ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( library_with_binary ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( fully_linked_program ); + test_error( error, "Unable to release program object" ); + + free(binary); + + return 0; +} + +static void CL_CALLBACK program_compile_completion_callback(cl_program program, void* user_data) +{ + int error; + cl_event compile_program_completion_event = (cl_event)user_data; + log_info("in the program_compile_completion_callback: program %p just completed compiling with '%p'\n", program, compile_program_completion_event); + + error = clSetUserEventStatus(compile_program_completion_event, CL_COMPLETE); + if (error != CL_SUCCESS) + { + log_error( "ERROR: in the program_compile_completion_callback: Unable to set user event status to CL_COMPLETE! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + exit(-1); + } + log_info("in the program_compile_completion_callback: Successfully signaled compile_program_completion_event event!\n"); +} + +static void CL_CALLBACK program_link_completion_callback(cl_program program, void* user_data) +{ + int error; + cl_event link_program_completion_event = (cl_event)user_data; + log_info("in the program_link_completion_callback: program %p just completed linking with '%p'\n", program, link_program_completion_event); + + error = clSetUserEventStatus(link_program_completion_event, CL_COMPLETE); + if (error != CL_SUCCESS) + { + log_error( "ERROR: in the program_link_completion_callback: Unable to set user event status to CL_COMPLETE! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + exit(-1); + } + log_info("in the program_link_completion_callback: Successfully signaled link_program_completion_event event!\n"); +} + +int test_execute_after_simple_compile_and_link_with_callbacks(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + cl_event compile_program_completion_event, link_program_completion_event; + + log_info("Testing execution after a simple compile and link with callbacks...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + compile_program_completion_event = clCreateUserEvent(context, &error); + test_error( error, "Unable to create a user event"); + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, + program_compile_completion_callback, (void*)compile_program_completion_event); + test_error( error, "Unable to compile a simple program" ); + + error = clWaitForEvents(1, &compile_program_completion_event); + test_error( error, "clWaitForEvents failed when waiting on compile_program_completion_event"); + + clReleaseEvent(compile_program_completion_event); + + link_program_completion_event = clCreateUserEvent(context, &error); + test_error( error, "Unable to create a user event"); + + cl_program my_newly_linked_program = clLinkProgram(context, 1, &deviceID, NULL, 1, &program, + program_link_completion_callback, (void*)link_program_completion_event, &error); + test_error( error, "Unable to link a simple program" ); + + error = clWaitForEvents(1, &link_program_completion_event); + test_error( error, "clWaitForEvents failed when waiting on link_program_completion_event"); + + clReleaseEvent(link_program_completion_event); + + cl_kernel kernel = clCreateKernel(my_newly_linked_program, "CopyBuffer", &error); + test_error( error, "Unable to create a simple kernel" ); + + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_simple_library_only(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + + log_info("Testing creation of a simple library...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program my_newly_minted_library = clLinkProgram(context, 1, &deviceID, "-create-library", 1, &program, NULL, NULL, &error); + test_error( error, "Unable to create a simple library" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_minted_library ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_simple_library_with_callback(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program; + cl_event link_program_completion_event; + + log_info("Testing creation of a simple library with a callback...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + link_program_completion_event = clCreateUserEvent(context, &error); + test_error( error, "Unable to create a user event"); + + simple_user_data simple_link_user_data = {when_i_pondered_weak_and_weary, link_program_completion_event}; + + cl_program my_newly_minted_library = clLinkProgram(context, 1, &deviceID, "-create-library", 1, &program, + simple_link_callback, (void*)&simple_link_user_data, &error); + test_error( error, "Unable to create a simple library" ); + + error = clWaitForEvents(1, &link_program_completion_event); + test_error( error, "clWaitForEvents failed when waiting on link_program_completion_event"); + + /* All done! */ + error = clReleaseEvent(link_program_completion_event); + test_error( error, "Unable to release event object" ); + + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_minted_library ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_simple_library_with_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program, another_program; + + log_info("Testing creation and linking with a simple library...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program my_newly_minted_library = clLinkProgram(context, 1, &deviceID, "-create-library", 1, &program, NULL, NULL, &error); + test_error( error, "Unable to create a simple library" ); + + error = create_single_kernel_helper_create_program(context, &another_program, 1, &another_simple_kernel); + if( another_program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(another_program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program program_and_archive[2] = { another_program, my_newly_minted_library }; + cl_program fully_linked_program = clLinkProgram(context, 1, &deviceID, "", 2, program_and_archive, NULL, NULL, &error); + test_error( error, "Unable to create an executable from a binary and a library" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( another_program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_minted_library ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( fully_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_execute_after_simple_library_with_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program, another_program; + + log_info("Testing execution after linking a binary with a simple library...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program my_newly_minted_library = clLinkProgram(context, 1, &deviceID, "-create-library", 1, &program, NULL, NULL, &error); + test_error( error, "Unable to create a simple library" ); + + error = create_single_kernel_helper_create_program(context, &another_program, 1, &another_simple_kernel); + if( another_program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(another_program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program program_and_archive[2] = { another_program, my_newly_minted_library }; + cl_program fully_linked_program = clLinkProgram(context, 1, &deviceID, "", 2, program_and_archive, NULL, NULL, &error); + test_error( error, "Unable to create an executable from a binary and a library" ); + + cl_kernel kernel = clCreateKernel(fully_linked_program, "CopyBuffer", &error); + test_error( error, "Unable to create a simple kernel" ); + + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + cl_kernel another_kernel = clCreateKernel(fully_linked_program, "AnotherCopyBuffer", &error); + test_error( error, "Unable to create another simple kernel" ); + + error = verifyCopyBuffer(context, queue, another_kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( another_program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_minted_library ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( fully_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_two_file_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program, another_program; + + log_info("Testing two file compiling and linking...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + + error = create_single_kernel_helper_create_program(context, &another_program, 1, &another_simple_kernel); + if( another_program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(another_program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program two_programs[2] = { program, another_program }; + cl_program fully_linked_program = clLinkProgram(context, 1, &deviceID, "", 2, two_programs, NULL, NULL, &error); + test_error( error, "Unable to create an executable from two binaries" ); + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( another_program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( fully_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_execute_after_two_file_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program, another_program; + + log_info("Testing two file compiling and linking and execution of two kernels afterwards ...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + error = create_single_kernel_helper_create_program(context, &another_program, 1, &another_simple_kernel); + if( another_program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(another_program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program two_programs[2] = { program, another_program }; + cl_program fully_linked_program = clLinkProgram(context, 1, &deviceID, "", 2, two_programs, NULL, NULL, &error); + test_error( error, "Unable to create an executable from two binaries" ); + + cl_kernel kernel = clCreateKernel(fully_linked_program, "CopyBuffer", &error); + test_error( error, "Unable to create a simple kernel" ); + + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + cl_kernel another_kernel = clCreateKernel(fully_linked_program, "AnotherCopyBuffer", &error); + test_error( error, "Unable to create another simple kernel" ); + + error = verifyCopyBuffer(context, queue, another_kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( another_program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( fully_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_execute_after_embedded_header_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program, header, simple_program; + + log_info("Testing execution after embedded header link...\n"); + // we will test execution after compiling and linking with embedded headers + program = clCreateProgramWithSource(context, 1, &another_simple_kernel_with_header, NULL, &error); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + header = clCreateProgramWithSource(context, 1, &simple_header, NULL, &error); + if( header == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple header program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 1, &header, &simple_header_name, NULL, NULL); + test_error( error, "Unable to compile a simple program with embedded header" ); + + simple_program = clCreateProgramWithSource(context, 1, &simple_kernel, NULL, &error); + if( simple_program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(simple_program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program two_programs[2] = { program, simple_program }; + cl_program fully_linked_program = clLinkProgram(context, 1, &deviceID, "", 2, two_programs, NULL, NULL, &error); + test_error( error, "Unable to create an executable from two binaries, one compiled with embedded header" ); + + cl_kernel kernel = clCreateKernel(fully_linked_program, "CopyBuffer", &error); + test_error( error, "Unable to create a simple kernel" ); + + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + cl_kernel another_kernel = clCreateKernel(fully_linked_program, "AnotherCopyBuffer", &error); + test_error( error, "Unable to create another simple kernel" ); + + error = verifyCopyBuffer(context, queue, another_kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( simple_program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( fully_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +#if defined(__APPLE__) || defined(__linux) +#define _mkdir(x) mkdir(x,S_IRWXU) +#define _chdir chdir +#define _rmdir rmdir +#define _unlink unlink +#else +#include +#endif + +int test_execute_after_included_header_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program, simple_program; + + log_info("Testing execution after included header link...\n"); + // we will test execution after compiling and linking with included headers + program = clCreateProgramWithSource(context, 1, &another_simple_kernel_with_header, NULL, &error); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + /* setup */ +#if (defined(__linux__) || defined(__APPLE__)) && (!defined( __ANDROID__ )) + /* Some tests systems doesn't allow one to write in the test directory */ + if (_chdir("/tmp") != 0) { + log_error( "ERROR: Unable to remove directory foo/bar! (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } +#endif + if (_mkdir("foo") != 0) { + log_error( "ERROR: Unable to create directory foo! (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + if (_mkdir("foo/bar") != 0) { + log_error( "ERROR: Unable to create directory foo/bar! (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + if (_chdir("foo/bar") != 0) { + log_error( "ERROR: Unable to change to directory foo/bar! (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + FILE* simple_header_file = fopen(simple_header_name, "w"); + if (simple_header_file == NULL) { + log_error( "ERROR: Unable to create simple header file %s! (in %s:%d)\n", simple_header_name, __FILE__, __LINE__ ); + return -1; + } + if (fprintf(simple_header_file, "%s", simple_header) < 0) { + log_error( "ERROR: Unable to write to simple header file %s! (in %s:%d)\n", simple_header_name, __FILE__, __LINE__); + return -1; + } + if (fclose(simple_header_file) != 0) { + log_error( "ERROR: Unable to close simple header file %s! (in %s:%d)\n", simple_header_name, __FILE__, __LINE__); + return -1; + } + if (_chdir("../..") != 0) { + log_error( "ERROR: Unable to change to original working directory! (in %s:%d)\n", __FILE__, __LINE__); + return -1; + } +#if (defined(__linux__) || defined(__APPLE__)) && (!defined( __ANDROID__ )) + error = clCompileProgram(program, 1, &deviceID, "-I/tmp/foo/bar", 0, NULL, NULL, NULL, NULL); +#else + error = clCompileProgram(program, 1, &deviceID, "-Ifoo/bar", 0, NULL, NULL, NULL, NULL); +#endif + test_error( error, "Unable to compile a simple program with included header" ); + + /* cleanup */ + if (_chdir("foo/bar") != 0) { + log_error( "ERROR: Unable to change to directory foo/bar! (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + if (_unlink(simple_header_name) != 0) { + log_error( "ERROR: Unable to remove simple header file %s! (in %s:%d)\n", simple_header_name, __FILE__, __LINE__ ); + return -1; + } + if (_chdir("../..") != 0) { + log_error( "ERROR: Unable to change to original working directory! (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + if (_rmdir("foo/bar") != 0) { + log_error( "ERROR: Unable to remove directory foo/bar! (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + if (_rmdir("foo") != 0) { + log_error( "ERROR: Unable to remove directory foo! (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + + simple_program = clCreateProgramWithSource(context, 1, &simple_kernel, NULL, &error); + if( simple_program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(simple_program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program two_programs[2] = { program, simple_program }; + cl_program fully_linked_program = clLinkProgram(context, 1, &deviceID, "", 2, two_programs, NULL, NULL, &error); + test_error( error, "Unable to create an executable from two binaries, one compiled with embedded header" ); + + cl_kernel kernel = clCreateKernel(fully_linked_program, "CopyBuffer", &error); + test_error( error, "Unable to create a simple kernel" ); + + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + cl_kernel another_kernel = clCreateKernel(fully_linked_program, "AnotherCopyBuffer", &error); + test_error( error, "Unable to create another simple kernel" ); + + error = verifyCopyBuffer(context, queue, another_kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( simple_program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( fully_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_program_binary_type(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int error; + cl_program program, another_program, program_with_binary, fully_linked_program_with_binary; + cl_program_binary_type program_type = -1; + size_t size; + size_t binarySize; + unsigned char *binary; + + log_info("Testing querying of program binary type...\n"); + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + error = clGetProgramBuildInfo (program, deviceID, CL_PROGRAM_BINARY_TYPE, sizeof(cl_program_binary_type), &program_type, NULL); + test_error( error, "Unable to get program binary type" ); + if (program_type != CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT) + { + log_error( "ERROR: Expected program type of a just compiled program to be CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + program_type = -1; + + // Get the size of the resulting binary (only one device) + error = clGetProgramInfo( program, CL_PROGRAM_BINARY_SIZES, sizeof( binarySize ), &binarySize, NULL ); + test_error( error, "Unable to get binary size" ); + + // Sanity check + if( binarySize == 0 ) + { + log_error( "ERROR: Binary size of program is zero (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + + // Create a buffer and get the actual binary + { + binary = (unsigned char*)malloc(sizeof(unsigned char)*binarySize); + if (binary == NULL) { + log_error( "ERROR: Unable to allocate binary character array with %lu characters! (in %s:%d)\n", binarySize, __FILE__, __LINE__ ); + return -1; + } + unsigned char *buffers[ 1 ] = { binary }; + cl_int loadErrors[ 1 ]; + + // Do another sanity check here first + size_t size; + error = clGetProgramInfo( program, CL_PROGRAM_BINARIES, 0, NULL, &size ); + test_error( error, "Unable to get expected size of binaries array" ); + if( size != sizeof( buffers ) ) + { + log_error( "ERROR: Expected size of binaries array in clGetProgramInfo is incorrect (should be %d, got %d) (in %s:%d)\n", (int)sizeof( buffers ), (int)size, __FILE__, __LINE__ ); + free(binary); + return -1; + } + + error = clGetProgramInfo( program, CL_PROGRAM_BINARIES, sizeof( buffers ), &buffers, NULL ); + test_error( error, "Unable to get program binary" ); + + // use clCreateProgramWithBinary + program_with_binary = clCreateProgramWithBinary(context, 1, &deviceID, &binarySize, (const unsigned char**)buffers, loadErrors, &error); + test_error( error, "Unable to create program with binary" ); + + error = clGetProgramBuildInfo (program_with_binary, deviceID, CL_PROGRAM_BINARY_TYPE, sizeof(cl_program_binary_type), &program_type, NULL); + test_error( error, "Unable to get program binary type" ); + if (program_type != CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT) + { + log_error( "ERROR: Expected program type of a program created from compiled object to be CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + program_type = -1; + free(binary); + } + + cl_program my_newly_minted_library = clLinkProgram(context, 1, &deviceID, "-create-library", 1, &program_with_binary, NULL, NULL, &error); + test_error( error, "Unable to create a simple library" ); + error = clGetProgramBuildInfo (my_newly_minted_library, deviceID, CL_PROGRAM_BINARY_TYPE, sizeof(cl_program_binary_type), &program_type, NULL); + test_error( error, "Unable to get program binary type" ); + if (program_type != CL_PROGRAM_BINARY_TYPE_LIBRARY) + { + log_error( "ERROR: Expected program type of a just linked library to be CL_PROGRAM_BINARY_TYPE_LIBRARY (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + program_type = -1; + + // Get the size of the resulting library (only one device) + error = clGetProgramInfo( my_newly_minted_library, CL_PROGRAM_BINARY_SIZES, sizeof( binarySize ), &binarySize, NULL ); + test_error( error, "Unable to get binary size" ); + + // Sanity check + if( binarySize == 0 ) + { + log_error( "ERROR: Binary size of program is zero (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + + // Create a buffer and get the actual binary + binary = (unsigned char*)malloc(sizeof(unsigned char)*binarySize); + if (binary == NULL) { + log_error( "ERROR: Unable to allocate binary character array with %lu characters! (in %s:%d)\n", binarySize, __FILE__, __LINE__); + return -1; + } + + unsigned char *buffers[ 1 ] = { binary }; + cl_int loadErrors[ 1 ]; + + // Do another sanity check here first + error = clGetProgramInfo( my_newly_minted_library, CL_PROGRAM_BINARIES, 0, NULL, &size ); + test_error( error, "Unable to get expected size of binaries array" ); + if( size != sizeof( buffers ) ) + { + log_error( "ERROR: Expected size of binaries array in clGetProgramInfo is incorrect (should be %d, got %d) (in %s:%d)\n", (int)sizeof( buffers ), (int)size, __FILE__, __LINE__ ); + free(binary); + return -1; + } + + error = clGetProgramInfo( my_newly_minted_library, CL_PROGRAM_BINARIES, sizeof( buffers ), &buffers, NULL ); + test_error( error, "Unable to get program binary" ); + + // use clCreateProgramWithBinary + cl_program library_with_binary = clCreateProgramWithBinary(context, 1, &deviceID, &binarySize, (const unsigned char**)buffers, loadErrors, &error); + test_error( error, "Unable to create program with binary" ); + error = clGetProgramBuildInfo (library_with_binary, deviceID, CL_PROGRAM_BINARY_TYPE, sizeof(cl_program_binary_type), &program_type, NULL); + test_error( error, "Unable to get program binary type" ); + if (program_type != CL_PROGRAM_BINARY_TYPE_LIBRARY) + { + log_error( "ERROR: Expected program type of a library loaded with binary to be CL_PROGRAM_BINARY_TYPE_LIBRARY (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + program_type = -1; + free(binary); + + error = create_single_kernel_helper_create_program(context, &another_program, 1, &another_simple_kernel); + if( another_program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clCompileProgram(another_program, 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + cl_program program_and_archive[2] = { another_program, library_with_binary }; + cl_program fully_linked_program = clLinkProgram(context, 1, &deviceID, "", 2, program_and_archive, NULL, NULL, &error); + test_error( error, "Unable to create an executable from a binary and a library" ); + + error = clGetProgramBuildInfo (fully_linked_program, deviceID, CL_PROGRAM_BINARY_TYPE, sizeof(cl_program_binary_type), &program_type, NULL); + test_error( error, "Unable to get program binary type" ); + if (program_type != CL_PROGRAM_BINARY_TYPE_EXECUTABLE) + { + log_error( "ERROR: Expected program type of a newly build executable to be CL_PROGRAM_BINARY_TYPE_EXECUTABLE (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + program_type = -1; + + // Get the size of the resulting binary (only one device) + error = clGetProgramInfo( fully_linked_program, CL_PROGRAM_BINARY_SIZES, sizeof( binarySize ), &binarySize, NULL ); + test_error( error, "Unable to get binary size" ); + + // Sanity check + if( binarySize == 0 ) + { + log_error( "ERROR: Binary size of program is zero (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + + // Create a buffer and get the actual binary + { + binary = (unsigned char*)malloc(sizeof(unsigned char)*binarySize); + if (binary == NULL) { + log_error( "ERROR: Unable to allocate binary character array with %lu characters! (in %s:%d)\n", binarySize, __FILE__, __LINE__ ); + return -1; + } + unsigned char *buffers[ 1 ] = { binary }; + cl_int loadErrors[ 1 ]; + + // Do another sanity check here first + size_t size; + error = clGetProgramInfo( fully_linked_program, CL_PROGRAM_BINARIES, 0, NULL, &size ); + test_error( error, "Unable to get expected size of binaries array" ); + if( size != sizeof( buffers ) ) + { + log_error( "ERROR: Expected size of binaries array in clGetProgramInfo is incorrect (should be %d, got %d) (in %s:%d)\n", (int)sizeof( buffers ), (int)size, __FILE__, __LINE__ ); + free(binary); + return -1; + } + + error = clGetProgramInfo( fully_linked_program, CL_PROGRAM_BINARIES, sizeof( buffers ), &buffers, NULL ); + test_error( error, "Unable to get program binary" ); + + // use clCreateProgramWithBinary + fully_linked_program_with_binary = clCreateProgramWithBinary(context, 1, &deviceID, &binarySize, (const unsigned char**)buffers, loadErrors, &error); + test_error( error, "Unable to create program with binary" ); + + error = clGetProgramBuildInfo (fully_linked_program_with_binary, deviceID, CL_PROGRAM_BINARY_TYPE, sizeof(cl_program_binary_type), &program_type, NULL); + test_error( error, "Unable to get program binary type" ); + if (program_type != CL_PROGRAM_BINARY_TYPE_EXECUTABLE) + { + log_error( "ERROR: Expected program type of a program created from a fully linked executable binary to be CL_PROGRAM_BINARY_TYPE_EXECUTABLE (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + program_type = -1; + free(binary); + } + + error = clBuildProgram(fully_linked_program_with_binary, 1, &deviceID, NULL, NULL, NULL); + test_error( error, "Unable to build a simple program" ); + + cl_kernel kernel = clCreateKernel(fully_linked_program_with_binary, "CopyBuffer", &error); + test_error( error, "Unable to create a simple kernel" ); + + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + cl_kernel another_kernel = clCreateKernel(fully_linked_program_with_binary, "AnotherCopyBuffer", &error); + test_error( error, "Unable to create another simple kernel" ); + + error = verifyCopyBuffer(context, queue, another_kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + /* Oh, one more thing. Steve Jobs and apparently Herb Sutter. The question is "Who is copying whom?" */ + error = create_single_kernel_helper_create_program(context, &program, 1, &simple_kernel); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create a simple test program! (%s in %s:%d)\n", IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + error = clBuildProgram(program, 1, &deviceID, NULL, NULL, NULL); + test_error( error, "Unable to build a simple program" ); + error = clGetProgramBuildInfo (program, deviceID, CL_PROGRAM_BINARY_TYPE, sizeof(cl_program_binary_type), &program_type, NULL); + test_error( error, "Unable to get program binary type" ); + if (program_type != CL_PROGRAM_BINARY_TYPE_EXECUTABLE) + { + log_error( "ERROR: Expected program type of a program created from compiled object to be CL_PROGRAM_BINARY_TYPE_EXECUTABLE (in %s:%d)\n", __FILE__, __LINE__ ); + return -1; + } + program_type = -1; + + /* All's well that ends well. William Shakespeare */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( another_program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_minted_library ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( library_with_binary ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( fully_linked_program ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( fully_linked_program_with_binary ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( program_with_binary ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +volatile int compileNotificationSent; + +void CL_CALLBACK test_notify_compile_complete( cl_program program, void *userData ) +{ + if( userData == NULL || strcmp( (char *)userData, "compilation" ) != 0 ) + { + log_error( "ERROR: User data passed in to compile notify function was not correct! (in %s:%d)\n", __FILE__, __LINE__ ); + compileNotificationSent = -1; + } + else + compileNotificationSent = 1; + log_info( "\n <-- program successfully compiled\n" ); +} + +volatile int libraryCreationNotificationSent; + +void CL_CALLBACK test_notify_create_library_complete( cl_program program, void *userData ) +{ + if( userData == NULL || strcmp( (char *)userData, "create library" ) != 0 ) + { + log_error( "ERROR: User data passed in to library creation notify function was not correct! (in %s:%d)\n", __FILE__, __LINE__ ); + libraryCreationNotificationSent = -1; + } + else + libraryCreationNotificationSent = 1; + log_info( "\n <-- library successfully created\n" ); +} + +volatile int linkNotificationSent; + +void CL_CALLBACK test_notify_link_complete( cl_program program, void *userData ) +{ + if( userData == NULL || strcmp( (char *)userData, "linking" ) != 0 ) + { + log_error( "ERROR: User data passed in to link notify function was not correct! (in %s:%d)\n", __FILE__, __LINE__ ); + linkNotificationSent = -1; + } + else + linkNotificationSent = 1; + log_info( "\n <-- program successfully linked\n" ); +} + +int test_large_compile_and_link_status_options_log(cl_context context, cl_device_id deviceID, cl_command_queue queue, unsigned int numLines) +{ + int error; + cl_program program; + cl_program * simple_kernels; + const char **lines; + unsigned int i; + char buffer[MAX_LINE_SIZE_IN_PROGRAM]; + char *compile_log; + char *compile_options; + char *library_log; + char *library_options; + char *linking_log; + char *linking_options; + cl_build_status status; + size_t size_ret; + + compileNotificationSent = libraryCreationNotificationSent = linkNotificationSent = 0; + + simple_kernels = (cl_program*)malloc(numLines*sizeof(cl_program)); + if (simple_kernels == NULL) { + log_error( "ERROR: Unable to allocate kernels array with %d kernels! (in %s:%d)\n", numLines, __FILE__, __LINE__); + return -1; + } + /* First, allocate the array for our line pointers */ + lines = (const char **)malloc( (2*numLines + 2) * sizeof( const char * ) ); + if (lines == NULL) { + log_error( "ERROR: Unable to allocate lines array with %d lines! (in %s:%d)\n", (2*numLines + 2), __FILE__, __LINE__); + return -1; + } + + for(i = 0; i < numLines; i++) + { + sprintf(buffer, composite_kernel_extern_template, i); + lines[i] = _strdup(buffer); + } + /* First and last lines are easy */ + lines[ numLines ] = composite_kernel_start; + lines[ 2*numLines + 1] = composite_kernel_end; + + /* Fill the rest with templated kernels */ + for(i = numLines + 1; i < 2*numLines + 1; i++ ) + { + sprintf(buffer, composite_kernel_template, i - numLines - 1); + lines[ i ] = _strdup(buffer); + } + + /* Try to create a program with these lines */ + error = create_single_kernel_helper_create_program(context, &program, 2 * numLines + 2, lines); + if( program == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create long test program with %d lines! (%s) (in %s:%d)\n", numLines, IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + /* Lets check that the compilation status is CL_BUILD_NONE */ + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Unable to get program compile status" ); + if (status != CL_BUILD_NONE) + { + log_error( "ERROR: Expected compile status to be CL_BUILD_NONE prior to the beginning of the compilation! (status: %d in %s:%d)\n", (int)status, __FILE__, __LINE__ ); + return -1; + } + + /* Compile it */ + error = clCompileProgram(program, 1, &deviceID, NULL, 0, NULL, NULL, test_notify_compile_complete, (void *)"compilation"); + test_error( error, "Unable to compile a simple program" ); + + /* Wait for compile to complete (just keep polling, since we're just a test */ + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Unable to get program compile status" ); + + while( (int)status == CL_BUILD_IN_PROGRESS ) + { + log_info( "\n -- still waiting for compile... (status is %d)", status ); + sleep( 1 ); + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Unable to get program compile status" ); + } + if( status != CL_BUILD_SUCCESS ) + { + log_error( "ERROR: compile failed! (status: %d in %s:%d)\n", (int)status, __FILE__, __LINE__ ); + return -1; + } + + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_LOG, 0, NULL, &size_ret ); + test_error( error, "Device failed to return compile log size" ); + compile_log = (char *)malloc(size_ret); + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_LOG, size_ret, compile_log, NULL ); + if (error != CL_SUCCESS){ + log_error("Device failed to return a compile log (in %s:%d)\n", __FILE__, __LINE__); + test_error(error, "clGetProgramBuildInfo CL_PROGRAM_BUILD_LOG failed"); + } + log_info("BUILD LOG: %s\n", compile_log); + free(compile_log); + + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_OPTIONS, 0, NULL, &size_ret ); + test_error(error, "Device failed to return compile options size"); + compile_options = (char *)malloc(size_ret); + error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_OPTIONS, size_ret, compile_options, NULL ); + test_error(error, "Device failed to return compile options.\nclGetProgramBuildInfo CL_PROGRAM_BUILD_OPTIONS failed"); + + log_info("BUILD OPTIONS: %s\n", compile_options); + free(compile_options); + + /* Create and compile templated kernels */ + for( i = 0; i < numLines; i++) + { + sprintf(buffer, simple_kernel_template, i); + const char* kernel_source = _strdup(buffer); + error = create_single_kernel_helper_create_program(context, &simple_kernels[i], 1, &kernel_source); + if( simple_kernels[i] == NULL || error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create long test program with %d lines! (%s in %s:%d)", numLines, IGetErrorString( error ), __FILE__, __LINE__ ); + return -1; + } + + /* Compile it */ + error = clCompileProgram(simple_kernels[i], 1, &deviceID, NULL, 0, NULL, NULL, NULL, NULL); + test_error( error, "Unable to compile a simple program" ); + + free((void*)kernel_source); + } + + /* Create library out of compiled templated kernels */ + cl_program my_newly_minted_library = clLinkProgram(context, 1, &deviceID, "-create-library", numLines, simple_kernels, test_notify_create_library_complete, (void *)"create library", &error); + test_error( error, "Unable to create a multi-line library" ); + + /* Wait for library creation to complete (just keep polling, since we're just a test */ + error = clGetProgramBuildInfo( my_newly_minted_library, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Unable to get library creation link status" ); + + while( (int)status == CL_BUILD_IN_PROGRESS ) + { + log_info( "\n -- still waiting for library creation... (status is %d)", status ); + sleep( 1 ); + error = clGetProgramBuildInfo( my_newly_minted_library, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Unable to get library creation link status" ); + } + if( status != CL_BUILD_SUCCESS ) + { + log_error( "ERROR: library creation failed! (status: %d in %s:%d)\n", (int)status, __FILE__, __LINE__ ); + return -1; + } + error = clGetProgramBuildInfo( my_newly_minted_library, deviceID, CL_PROGRAM_BUILD_LOG, 0, NULL, &size_ret ); + test_error( error, "Device failed to return a library creation log size" ); + library_log = (char *)malloc(size_ret); + error = clGetProgramBuildInfo( my_newly_minted_library, deviceID, CL_PROGRAM_BUILD_LOG, size_ret, library_log, NULL ); + if (error != CL_SUCCESS) { + log_error("Device failed to return a library creation log (in %s:%d)\n", __FILE__, __LINE__); + test_error(error, "clGetProgramBuildInfo CL_PROGRAM_BUILD_LOG failed"); + } + log_info("CREATE LIBRARY LOG: %s\n", library_log); + free(library_log); + + error = clGetProgramBuildInfo( my_newly_minted_library, deviceID, CL_PROGRAM_BUILD_OPTIONS, 0, NULL, &size_ret ); + test_error(error, "Device failed to return library creation options size"); + library_options = (char *)malloc(size_ret); + error = clGetProgramBuildInfo( my_newly_minted_library, deviceID, CL_PROGRAM_BUILD_OPTIONS, size_ret, library_options, NULL ); + test_error(error, "Device failed to return library creation options.\nclGetProgramBuildInfo CL_PROGRAM_BUILD_OPTIONS failed"); + + log_info("CREATE LIBRARY OPTIONS: %s\n", library_options); + free(library_options); + + /* Link the program that calls the kernels and the library that contains them */ + cl_program programs[2] = { program, my_newly_minted_library }; + cl_program my_newly_linked_program = clLinkProgram(context, 1, &deviceID, NULL, 2, programs, test_notify_link_complete, (void *)"linking", &error); + test_error( error, "Unable to link a program with a library" ); + + /* Wait for linking to complete (just keep polling, since we're just a test */ + error = clGetProgramBuildInfo( my_newly_linked_program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Unable to get program link status" ); + + while( (int)status == CL_BUILD_IN_PROGRESS ) + { + log_info( "\n -- still waiting for program linking... (status is %d)", status ); + sleep( 1 ); + error = clGetProgramBuildInfo( my_newly_linked_program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Unable to get program link status" ); + } + if( status != CL_BUILD_SUCCESS ) + { + log_error( "ERROR: program linking failed! (status: %d in %s:%d)\n", (int)status, __FILE__, __LINE__ ); + return -1; + } + error = clGetProgramBuildInfo( my_newly_linked_program, deviceID, CL_PROGRAM_BUILD_LOG, 0, NULL, &size_ret ); + test_error( error, "Device failed to return a linking log size" ); + linking_log = (char *)malloc(size_ret); + error = clGetProgramBuildInfo( my_newly_linked_program, deviceID, CL_PROGRAM_BUILD_LOG, size_ret, linking_log, NULL ); + if (error != CL_SUCCESS){ + log_error("Device failed to return a linking log (in %s:%d).\n", __FILE__, __LINE__); + test_error(error, "clGetProgramBuildInfo CL_PROGRAM_BUILD_LOG failed"); + } + log_info("BUILDING LOG: %s\n", linking_log); + free(linking_log); + + error = clGetProgramBuildInfo( my_newly_linked_program, deviceID, CL_PROGRAM_BUILD_OPTIONS, 0, NULL, &size_ret ); + test_error(error, "Device failed to return linking options size"); + linking_options = (char *)malloc(size_ret); + error = clGetProgramBuildInfo( my_newly_linked_program, deviceID, CL_PROGRAM_BUILD_OPTIONS, size_ret, linking_options, NULL ); + test_error(error, "Device failed to return linking options.\nclGetProgramBuildInfo CL_PROGRAM_BUILD_OPTIONS failed"); + + log_info("BUILDING OPTIONS: %s\n", linking_options); + free(linking_options); + + // Create the composite kernel + cl_kernel kernel = clCreateKernel(my_newly_linked_program, "CompositeKernel", &error); + test_error( error, "Unable to create a composite kernel" ); + + // Run the composite kernel and verify the results + error = verifyCopyBuffer(context, queue, kernel); + if (error != CL_SUCCESS) + return error; + + /* All done! */ + error = clReleaseProgram( program ); + test_error( error, "Unable to release program object" ); + + for(i = 0; i < numLines; i++) + { + free( (void*)lines[i] ); + free( (void*)lines[i+numLines+1] ); + } + free( lines ); + + for(i = 0; i < numLines; i++) + { + error = clReleaseProgram( simple_kernels[i] ); + test_error( error, "Unable to release program object" ); + } + free( simple_kernels ); + + error = clReleaseProgram( my_newly_minted_library ); + test_error( error, "Unable to release program object" ); + + error = clReleaseProgram( my_newly_linked_program ); + test_error( error, "Unable to release program object" ); + + return 0; +} + +int test_compile_and_link_status_options_log(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + unsigned int toTest[] = { 256, 0 }; //512, 1024, 8192, 16384, 32768, 0 }; + unsigned int i; + + log_info( "Testing Compile and Link Status, Options and Logging ...this might take awhile...\n" ); + + for( i = 0; toTest[ i ] != 0; i++ ) + { + log_info( " %d...\n", toTest[ i ] ); + +#if defined(_WIN32) + clock_t start = clock(); +#elif defined(__linux__) || defined(__APPLE__) + timeval time1, time2; + gettimeofday(&time1, NULL); +#endif + + if( test_large_compile_and_link_status_options_log( context, deviceID, queue, toTest[ i ] ) != 0 ) + { + log_error( "ERROR: large program compilation, linking, status, options and logging test failed for %d lines! (in %s:%d)\n", toTest[ i ], __FILE__, __LINE__ ); + return -1; + } + +#if defined(_WIN32) + clock_t end = clock(); + log_perf( (float)( end - start ) / (float)CLOCKS_PER_SEC, false, "clock() time in secs", "%d lines", toTest[i] ); +#elif defined(__linux__) || defined(__APPLE__) + gettimeofday(&time2, NULL); + log_perf( (float)(float)(time2.tv_sec - time1.tv_sec) + 1.0e-6 * (time2.tv_usec - time1.tv_usec) , false, "wall time in secs", "%d lines", toTest[i] ); +#endif + } + + return 0; +} diff --git a/test_conformance/compiler/test_compiler_defines_for_extensions.cpp b/test_conformance/compiler/test_compiler_defines_for_extensions.cpp new file mode 100644 index 00000000..a262d019 --- /dev/null +++ b/test_conformance/compiler/test_compiler_defines_for_extensions.cpp @@ -0,0 +1,420 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include +#include +#ifndef _WIN32 +#include +#endif + + + + +const char *known_extensions[] = { + "cl_khr_fp64", + "cl_khr_global_int32_base_atomics", + "cl_khr_global_int32_extended_atomics", + "cl_khr_local_int32_base_atomics", + "cl_khr_local_int32_extended_atomics", + "cl_khr_int64_base_atomics", + "cl_khr_int64_extended_atomics", + "cl_khr_3d_image_writes", + "cl_khr_byte_addressable_store", + "cl_khr_fp16", + "cl_khr_gl_sharing", + "cl_khr_gl_event", + "cl_khr_d3d10_sharing", + "cl_khr_d3d11_sharing", + "cl_khr_icd", + "cl_khr_dx9_media_sharing", + "cl_khr_depth_images", + "cl_khr_gl_depth_images", + "cl_khr_gl_msaa_sharing", + "cl_khr_image2d_from_buffer", + "cl_khr_initialize_memory", + "cl_khr_terminate_context", + "cl_khr_spir", + "cl_khr_srgb_image_writes", + "cl_khr_subgroups", + "cl_khr_mipmap_image", + "cl_khr_mipmap_image_writes", + "cl_khr_egl_image", + "cl_khr_egl_event", + "cl_khr_throttle_hints", + "cl_khr_priority_hints", +}; + +size_t num_known_extensions = sizeof(known_extensions)/sizeof(char*); +size_t first_API_extension = 10; + +const char *known_embedded_extensions[] = { + "cles_khr_int64", + NULL +}; + +typedef enum +{ + kUnsupported_extension = -1, + kVendor_extension = 0, + kLanguage_extension = 1, + kAPI_extension = 2 +}Extension_Type; + +const char *kernel_strings[] = { + "kernel void test(global int *defines)\n{\n", + "#pragma OPENCL EXTENSION %s : enable\n", + "#ifdef %s\n" + " defines[%d] = 1;\n" + "#else\n" + " defines[%d] = 0;\n" + "#endif\n", + "#pragma OPENCL EXTENSION %s : disable\n\n", + "}\n" +}; + +int test_compiler_defines_for_extensions(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ) +{ + + int error; + int total_errors = 0; + + + // Get the extensions string for the device + size_t size; + error = clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, 0, NULL, &size); + test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS size failed"); + + char *extensions = (char*)malloc(sizeof(char)*(size + 1)); + if (extensions == 0) { + log_error("Failed to allocate memory for extensions string.\n"); + return -1; + } + memset( extensions, CHAR_MIN, sizeof(char)*(size+1) ); + + error = clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, sizeof(char)*size, extensions, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS failed"); + + // Check to make sure the extension string is NUL terminated. + if( extensions[size] != CHAR_MIN ) + { + test_error( -1, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS wrote past the end of the array!" ); + return -1; + } + extensions[size] = '\0'; // set last char to NUL to avoid problems with string functions later + + // test for termination with '\0' + size_t stringSize = strlen( extensions ); + if( stringSize == size ) + { + test_error( -1, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS is not NUL terminated!" ); + return -1; + } + + // Break up the extensions + log_info("Device reports the following extensions:\n"); + char *extensions_supported[1024]; + Extension_Type extension_type[1024]; + int num_of_supported_extensions = 0; + char *currentP = extensions; + + memset( extension_type, 0, sizeof( extension_type) ); + + // loop over extension string + while (currentP != extensions + stringSize) + { + // skip leading white space + while( *currentP == ' ' ) + currentP++; + + // Exit if end of string + if( *currentP == '\0' ) + { + if( currentP != extensions + stringSize) + { + test_error( -1, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS contains a NUL in the middle of the string!" ); + return -1; + } + break; + } + + // Not space, not end of string, so extension + char *start = currentP; // start of extension name + + // loop looking for the end + while (*currentP != ' ' && currentP != extensions + stringSize) + { + // check for non-space white space in the extension name + if( isspace(*currentP) ) + { + test_error( -1, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS contains a non-space whitespace in an extension name!" ); + return -1; + } + currentP++; + } + + // record the extension name + uintptr_t extension_length = (uintptr_t) currentP - (uintptr_t) start; + extensions_supported[ num_of_supported_extensions ] = (char*) malloc( (extension_length + 1) * sizeof( char ) ); + if( NULL == extensions_supported[ num_of_supported_extensions ] ) + { + log_error( "Error: unable to allocate memory to hold extension name: %ld chars\n", extension_length ); + return -1; + } + memcpy( extensions_supported[ num_of_supported_extensions ], start, extension_length * sizeof( char ) ); + extensions_supported[ num_of_supported_extensions ][extension_length] = '\0'; + + // If the extension is a cl_khr extension, make sure it is an approved cl_khr extension -- looking for misspellings here + if( extensions_supported[ num_of_supported_extensions ][0] == 'c' && + extensions_supported[ num_of_supported_extensions ][1] == 'l' && + extensions_supported[ num_of_supported_extensions ][2] == '_' && + extensions_supported[ num_of_supported_extensions ][3] == 'k' && + extensions_supported[ num_of_supported_extensions ][4] == 'h' && + extensions_supported[ num_of_supported_extensions ][5] == 'r' && + extensions_supported[ num_of_supported_extensions ][6] == '_' ) + { + size_t ii; + for( ii = 0; ii < num_known_extensions; ii++ ) + { + if( 0 == strcmp( known_extensions[ii], extensions_supported[ num_of_supported_extensions ] ) ) + break; + } + if( ii == num_known_extensions ) + { + log_error( "FAIL: Extension %s is not in the list of approved Khronos extensions!", extensions_supported[ num_of_supported_extensions ] ); + return -1; + } + } + // Is it an embedded extension? + else if( memcmp( extensions_supported[ num_of_supported_extensions ], "cles_khr_", 9 ) == 0 ) + { + // Yes, but is it a known one? + size_t ii; + for( ii = 0; known_embedded_extensions[ ii ] != NULL; ii++ ) + { + if( strcmp( known_embedded_extensions[ ii ], extensions_supported[ num_of_supported_extensions ] ) == 0 ) + break; + } + if( known_embedded_extensions[ ii ] == NULL ) + { + log_error( "FAIL: Extension %s is not in the list of approved Khronos embedded extensions!", extensions_supported[ num_of_supported_extensions ] ); + return -1; + } + + // It's approved, but are we even an embedded system? + char profileStr[128] = ""; + error = clGetDeviceInfo( device, CL_DEVICE_PROFILE, sizeof( profileStr ), &profileStr, NULL ); + test_error( error, "Unable to get CL_DEVICE_PROFILE to validate embedded extension name" ); + + if( strcmp( profileStr, "EMBEDDED_PROFILE" ) != 0 ) + { + log_error( "FAIL: Extension %s is an approved embedded extension, but on a non-embedded profile!", extensions_supported[ num_of_supported_extensions ] ); + return -1; + } + } + else + { // All other extensions must be of the form cl__ + if( extensions_supported[ num_of_supported_extensions ][0] != 'c' || + extensions_supported[ num_of_supported_extensions ][1] != 'l' || + extensions_supported[ num_of_supported_extensions ][2] != '_' ) + { + log_error( "FAIL: Extension %s doesn't start with \"cl_\"!", extensions_supported[ num_of_supported_extensions ] ); + return -1; + } + + if( extensions_supported[ num_of_supported_extensions ][3] == '_' || extensions_supported[ num_of_supported_extensions ][3] == '\0' ) + { + log_error( "FAIL: Vendor name is missing in extension %s!", extensions_supported[ num_of_supported_extensions ] ); + return -1; + } + + // look for the second underscore for name + char *p = extensions_supported[ num_of_supported_extensions ] + 4; + while( *p != '\0' && *p != '_' ) + p++; + + if( *p != '_' || p[1] == '\0') + { + log_error( "FAIL: extension name is missing in extension %s!", extensions_supported[ num_of_supported_extensions ] ); + return -1; + } + } + + + num_of_supported_extensions++; + } + + // Build a list of the known extensions that are not supported by the device + char *extensions_not_supported[1024]; + int num_not_supported_extensions = 0; + for( int i = 0; i < num_of_supported_extensions; i++ ) + { + int is_supported = 0; + for( size_t j = 0; j < num_known_extensions; j++ ) + { + if( strcmp( extensions_supported[ i ], known_extensions[ j ] ) == 0 ) + { + extension_type[ i ] = ( j < first_API_extension ) ? kLanguage_extension : kAPI_extension; + is_supported = 1; + break; + } + } + if( !is_supported ) + { + for( int j = 0; known_embedded_extensions[ j ] != NULL; j++ ) + { + if( strcmp( extensions_supported[ i ], known_embedded_extensions[ j ] ) == 0 ) + { + extension_type[ i ] = kLanguage_extension; + is_supported = 1; + break; + } + } + } + if (!is_supported) { + extensions_not_supported[num_not_supported_extensions] = (char*)malloc(strlen(extensions_supported[i])+1); + strcpy(extensions_not_supported[num_not_supported_extensions], extensions_supported[i]); + num_not_supported_extensions++; + } + } + + for (int i=0; i +#endif + +const char * image_supported_source = "kernel void enabled(global int * buf) { \r\n" \ +"int n = get_global_id(0); \r\n"\ +"buf[n] = 0; \r\n "\ +"#ifndef __IMAGE_SUPPORT__ \r\n" \ +"ERROR; \r\n"\ +"#endif \r\n"\ +"\r\n } \r\n"; + + +const char * image_not_supported_source = "kernel void not_enabled(global int * buf) { \r\n" \ +"int n = get_global_id(0); \r\n"\ +"buf[n] = 0; \r\n "\ +"#ifdef __IMAGE_SUPPORT__ \r\n" \ +"ERROR; \r\n"\ +"#endif \r\n"\ +"\r\n } \r\n"; + + +int test_image_macro(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_bool image_support; + char buf[256]; + int status; + cl_program program; + + status = clGetDeviceInfo( deviceID, CL_DEVICE_NAME, sizeof( buf ), buf, NULL ); + if( status ) + { + log_error( "getting device info (name): %d\n", status ); + exit(-1); + } + + status = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE_SUPPORT, sizeof( image_support ), &image_support, NULL ); + if( status ) + { + log_error( "getting device info (image support): %d\n", status ); + return status; + } + + if( (image_support == CL_TRUE) ) + { + status = create_single_kernel_helper_create_program(context, &program, 1, (const char**)&image_supported_source); + + if( status ) + { + log_error ("Failure creating program, [%d] \n", status ); + return status; + } + + status = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + if( status ) + log_error("CL_DEVICE_IMAGE_SUPPORT is set, __IMAGE_SUPPORT__ macro not set \n"); + else + log_info("CL_DEVICE_IMAGE_SUPPORT is set, __IMAGE_SUPPORT__ macro is set \n"); + } + else + { + status = create_single_kernel_helper_create_program(context, &program, 1, (const char**)&image_not_supported_source); + if( status ) + { + log_error ("Failure creating program, [%d] \n", status ); + return status; + } + + status = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL ); + if( status ) + log_error("CL_DEVICE_IMAGE_SUPPORT not set, __IMAGE_SUPPORT__ macro is set \n"); + else + log_info("CL_DEVICE_IMAGE_SUPPORT not set, __IMAGE_SUPPORT__ macro not set \n"); + } + + clReleaseProgram( program ); + return status; +} + diff --git a/test_conformance/compiler/test_pragma_unroll.c b/test_conformance/compiler/test_pragma_unroll.c new file mode 100644 index 00000000..3a5cbf90 --- /dev/null +++ b/test_conformance/compiler/test_pragma_unroll.c @@ -0,0 +1,290 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +#include + +const char *pragma_unroll_kernels[] = { +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" __attribute__((opencl_unroll_hint))\n" +" for(size_t i = 0; i < 100; ++i)\n" +" dst[i] = i;\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" __attribute__((opencl_unroll_hint(1)))\n" +" for(size_t i = 0; i < 100; ++i)\n" +" dst[i] = i;\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" __attribute__((opencl_unroll_hint(10)))\n" +" for(size_t i = 0; i < 100; ++i)\n" +" dst[i] = i;\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" __attribute__((opencl_unroll_hint(100)))\n" +" for(size_t i = 0; i < 100; ++i)\n" +" dst[i] = i;\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t n = (tid + 1) * 100;\n" +" __attribute__((opencl_unroll_hint))\n" +" for(size_t i = 0; i < n; ++i)\n" +" dst[i] = i;\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t n = (tid + 1) * 100;\n" +" __attribute__((opencl_unroll_hint(1)))\n" +" for(size_t i = 0; i < n; ++i)\n" +" dst[i] = i;\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t n = (tid + 1) * 100;\n" +" __attribute__((opencl_unroll_hint(10)))\n" +" for(size_t i = 0; i < n; ++i)\n" +" dst[i] = i;\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t n = (tid + 1) * 100;\n" +" __attribute__((opencl_unroll_hint(100)))\n" +" for(size_t i = 0; i < n; ++i)\n" +" dst[i] = i;\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint))\n" +" while(i < 100) {\n" +" dst[i] = i;\n" +" ++i;\n" +" }\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint(1)))\n" +" while(i < 100) {\n" +" dst[i] = i;\n" +" ++i;\n" +" }\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint(10)))\n" +" while(i < 100) {\n" +" dst[i] = i;\n" +" ++i;\n" +" }\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint(100)))\n" +" while(i < 100) {\n" +" dst[i] = i;\n" +" ++i;\n" +" }\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t n = (tid + 1) * 100;\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint))\n" +" while(i < n) {\n" +" dst[i] = i;\n" +" ++i;\n" +" }\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t n = (tid + 1) * 100;\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint(1)))\n" +" while(i < n) {\n" +" dst[i] = i;\n" +" ++i;\n" +" }\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t n = (tid + 1) * 100;\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint(10)))\n" +" while(i < n) {\n" +" dst[i] = i;\n" +" ++i;\n" +" }\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t n = (tid + 1) * 100;\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint(100)))\n" +" while(i < n) {\n" +" dst[i] = i;\n" +" ++i;\n" +" }\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint))\n" +" do {\n" +" dst[i] = i;\n" +" ++i;\n" +" } while(i < 100);\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint(1)))\n" +" do {\n" +" dst[i] = i;\n" +" ++i;\n" +" } while(i < 100);\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint(10)))\n" +" do {\n" +" dst[i] = i;\n" +" ++i;\n" +" } while(i < 100);\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint(100)))\n" +" do {\n" +" dst[i] = i;\n" +" ++i;\n" +" } while(i < 100);\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t n = (tid + 1) * 100;\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint))\n" +" do {\n" +" dst[i] = i;\n" +" ++i;\n" +" } while(i < n);\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t n = (tid + 1) * 100;\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint(1)))\n" +" do {\n" +" dst[i] = i;\n" +" ++i;\n" +" } while(i < n);\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t n = (tid + 1) * 100;\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint(10)))\n" +" do {\n" +" dst[i] = i;\n" +" ++i;\n" +" } while(i < n);\n" +"}\n", +"__kernel void pragma_unroll(__global uint *dst)\n" +"{\n" +" size_t tid = get_global_id(0);\n" +" size_t n = (tid + 1) * 100;\n" +" size_t i = 0;\n" +" __attribute__((opencl_unroll_hint(100)))\n" +" do {\n" +" dst[i] = i;\n" +" ++i;\n" +" } while(i < n);\n" +"}\n", +}; + +int test_pragma_unroll(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + const size_t ELEMENT_NUM = 100; + const size_t KERNEL_NUM = 24; + + cl_int error; + + //execute all kernels and check if the results are as expected + for (size_t kernelIdx = 0; kernelIdx < KERNEL_NUM; ++kernelIdx) { + clProgramWrapper program; + clKernelWrapper kernel; + if( create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, (const char **)&pragma_unroll_kernels[kernelIdx], "pragma_unroll", "-cl-std=CL2.0" ) ) { + log_error("The program we attempted to compile was: \n%s\n", pragma_unroll_kernels[kernelIdx]); + return -1; + } + + clMemWrapper buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, ELEMENT_NUM * sizeof(cl_uint), NULL, &error); + test_error(error, "clCreateBuffer failed"); + + error = clSetKernelArg(kernel, 0, sizeof(buffer), &buffer); + test_error(error, "clSetKernelArg failed"); + + //only one thread should be enough to verify if kernel is fully functional + size_t workSize = 1; + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &workSize, NULL, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + std::vector results(ELEMENT_NUM, 0); + error = clEnqueueReadBuffer(queue, buffer, CL_TRUE, 0, ELEMENT_NUM * sizeof(cl_uint), &results[0], 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + for (size_t i = 0; i < ELEMENT_NUM; ++i) { + if (results[i] != i) { + log_error("Kernel %d returned invalid result. Test: %d, expected: %d\n", kernelIdx + 1, results[i], i); + return -1; + } + } + } + + return 0; +} diff --git a/test_conformance/compiler/test_preprocessor.c b/test_conformance/compiler/test_preprocessor.c new file mode 100644 index 00000000..4f3277c6 --- /dev/null +++ b/test_conformance/compiler/test_preprocessor.c @@ -0,0 +1,342 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/os_helpers.h" + +extern cl_uint gRandomSeed; + +const char *define_kernel_code[] = { +" #define VALUE\n" +"__kernel void define_test(__global int *src, __global int *dstA, __global int *dstB)\n" +"{\n" +" int tid = get_global_id(0);\n" +"#ifdef VALUE\n" +" dstA[tid] = src[tid] * 2;\n" +"#else\n" +" dstA[tid] = src[tid] * 4;\n" +"#endif\n" +"\n" +"#undef VALUE\n" +"#ifdef VALUE\n" +" dstB[tid] = src[tid] * 2;\n" +"#else\n" +" dstB[tid] = src[tid] * 4;\n" +"#endif\n" +"\n" +"}\n"}; + + + + +int test_preprocessor_define_udef(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + + cl_int error; + clKernelWrapper kernel; + clProgramWrapper program; + clMemWrapper buffer[3]; + cl_int *srcData, *resultData; + int i; + MTdata d; + + error = create_single_kernel_helper(context, &program, &kernel, 1, define_kernel_code, "define_test"); + if (error) + return -1; + + buffer[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, num_elements*sizeof(cl_int), NULL, &error); + test_error( error, "clCreateBuffer failed"); + buffer[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, num_elements*sizeof(cl_int), NULL, &error); + test_error( error, "clCreateBuffer failed"); + buffer[2] = clCreateBuffer(context, CL_MEM_READ_WRITE, num_elements*sizeof(cl_int), NULL, &error); + test_error( error, "clCreateBuffer failed"); + + srcData = (cl_int*)malloc(sizeof(cl_int)*num_elements); + if (srcData == NULL) { + log_error("Failed to allocate storage for source data (%d cl_ints).\n", num_elements); + return -1; + } + + d = init_genrand( gRandomSeed ); + for (i=0; igcc:-xc++ + msvc:"/TP" + ; + +exe computeinfo : main.c ; + +install dist + : computeinfo + : debug:$(DIST)/debug/tests/test_conformance/computeinfo + release:$(DIST)/release/tests/test_conformance/computeinfo + ; diff --git a/test_conformance/computeinfo/Makefile b/test_conformance/computeinfo/Makefile new file mode 100644 index 00000000..f9ff3d38 --- /dev/null +++ b/test_conformance/computeinfo/Makefile @@ -0,0 +1,32 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = main.c ../../test_common/harness/errorHelpers.c ../../test_common/harness/kernelHelpers.c +HEADERS = +TARGET = computeinfo +INCLUDE = -I./../../OpenCL/cl_headers/public +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${RC_CFLAGS} ${ATF} + +OBJECTS = main.o errorHelpers.o kernelHelpers.o + +TARGETOBJECT = +all: $(TARGET) + +$(OBJECTS): $(FRAMEWORK) $(HEADERS) + $(CC) $(CFLAGS) $(INCLUDE) $(FRAMEWORK) + +$(TARGET): $(OBJECTS) + $(CC) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/computeinfo/main.c b/test_conformance/computeinfo/main.c new file mode 100644 index 00000000..8126c95a --- /dev/null +++ b/test_conformance/computeinfo/main.c @@ -0,0 +1,873 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" + +static int dump_supported_formats; + +typedef struct +{ + cl_device_type device_type; + const char* device_type_name; + unsigned num_devices; + cl_device_id* devices; + // more infos here +} device_info; + +device_info device_infos[] = +{ + {CL_DEVICE_TYPE_DEFAULT, "CL_DEVICE_TYPE_DEFAULT", -1, NULL}, + {CL_DEVICE_TYPE_CPU, "CL_DEVICE_TYPE_CPU", -1, NULL}, + {CL_DEVICE_TYPE_GPU, "CL_DEVICE_TYPE_GPU", -1, NULL}, + {CL_DEVICE_TYPE_ACCELERATOR, "CL_DEVICE_TYPE_ACCELERATOR", -1, NULL}, + {CL_DEVICE_TYPE_ALL, "CL_DEVICE_TYPE_ALL", -1, NULL}, +}; + +// config types +enum +{ + type_cl_device_type, + type_cl_device_fp_config, + type_cl_device_mem_cache_type, + type_cl_local_mem_type, + type_cl_device_exec_capabilities, + type_cl_command_queue_properties, + type_cl_device_id, + type_cl_device_affinity_domain, + type_cl_uint, + type_size_t, + type_size_t_arr, + type_cl_ulong, + type_string, + type_cl_device_svm_capabilities, +}; + +typedef union +{ + cl_device_type type; + cl_device_fp_config fp_config; + cl_device_mem_cache_type mem_cache_type; + cl_device_local_mem_type local_mem_type; + cl_device_exec_capabilities exec_capabilities; + cl_command_queue_properties queue_properties; + cl_device_id device_id; + cl_device_affinity_domain affinity_domain; + cl_int uint; + size_t sizet; + size_t sizet_arr[3]; + cl_ulong ull; + char string[1024]; + cl_device_svm_capabilities svmCapabilities; +} config_data; + +struct _version { + int major; + int minor; +}; +typedef struct _version version_t; + +struct _extensions { + int cl_khr_fp64; + int cl_khr_fp16; +}; +typedef struct _extensions extensions_t; + +// Compare two versions, return -1 (the first is lesser), 0 (equal), 1 (the first is greater). +int vercmp( version_t a, version_t b ) { + if ( a.major < b.major || a.major == b.major && a.minor < b.minor ) { + return -1; + } else if ( a.major == b.major && a.minor == b.minor ) { + return 0; + } else { + return 1; + } +} + +typedef struct +{ + version_t version; // Opcode is introduced in this version of OpenCL spec. + cl_device_info opcode; + const char* opcode_name; + int config_type; + config_data config; +} config_info; + +#define CONFIG_INFO( major, minor, opcode, type ) { { major, minor }, opcode, #opcode, type_ ## type, { 0 } } + +config_info image_buffer_config_infos[] = +{ +#ifdef CL_DEVICE_IMAGE_PITCH_ALIGNMENT + CONFIG_INFO( 1, 2, CL_DEVICE_IMAGE_PITCH_ALIGNMENT, cl_uint), + CONFIG_INFO( 1, 2, CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT, cl_uint), +#endif +}; + +config_info config_infos[] = +{ + // `CL_DEVICE_VERSION' must be the first item in the list! It's version must be 0, 0. + CONFIG_INFO( 0, 0, CL_DEVICE_VERSION, string), + // `CL_DEVICE_EXTENSIONS' must be the second! + CONFIG_INFO( 1, 1, CL_DEVICE_EXTENSIONS, string), + + CONFIG_INFO( 1, 1, CL_DEVICE_TYPE, cl_device_type), + CONFIG_INFO( 1, 1, CL_DEVICE_VENDOR_ID, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_MAX_COMPUTE_UNITS, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_MAX_WORK_ITEM_SIZES, size_t_arr), + CONFIG_INFO( 1, 1, CL_DEVICE_MAX_WORK_GROUP_SIZE, size_t), + CONFIG_INFO( 1, 1, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_NATIVE_VECTOR_WIDTH_INT, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF, cl_uint), + + CONFIG_INFO( 1, 1, CL_DEVICE_MAX_CLOCK_FREQUENCY, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_ADDRESS_BITS, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_MAX_READ_IMAGE_ARGS, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, cl_uint), + CONFIG_INFO( 2, 0, CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_MAX_MEM_ALLOC_SIZE, cl_ulong), + CONFIG_INFO( 1, 1, CL_DEVICE_IMAGE2D_MAX_WIDTH, size_t), + CONFIG_INFO( 1, 1, CL_DEVICE_IMAGE2D_MAX_HEIGHT, size_t), + CONFIG_INFO( 1, 1, CL_DEVICE_IMAGE3D_MAX_WIDTH, size_t), + CONFIG_INFO( 1, 1, CL_DEVICE_IMAGE3D_MAX_HEIGHT, size_t), + CONFIG_INFO( 1, 1, CL_DEVICE_IMAGE3D_MAX_DEPTH, size_t), + CONFIG_INFO( 1, 2, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, size_t), + CONFIG_INFO( 1, 2, CL_DEVICE_IMAGE_MAX_BUFFER_SIZE, size_t), + CONFIG_INFO( 1, 1, CL_DEVICE_IMAGE_SUPPORT, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_MAX_PARAMETER_SIZE, size_t), + CONFIG_INFO( 1, 1, CL_DEVICE_MAX_SAMPLERS, cl_uint), + CONFIG_INFO( 2, 0, CL_DEVICE_IMAGE_PITCH_ALIGNMENT, cl_uint), + CONFIG_INFO( 2, 0, CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT, cl_uint), + + CONFIG_INFO( 1, 1, CL_DEVICE_MEM_BASE_ADDR_ALIGN, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_SINGLE_FP_CONFIG, cl_device_fp_config), + CONFIG_INFO( 1, 1, CL_DEVICE_DOUBLE_FP_CONFIG, cl_device_fp_config), + CONFIG_INFO( 1, 1, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE, cl_device_mem_cache_type), + CONFIG_INFO( 1, 1, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, cl_ulong), + CONFIG_INFO( 1, 1, CL_DEVICE_GLOBAL_MEM_SIZE, cl_ulong), + + CONFIG_INFO( 1, 1, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, cl_ulong), + CONFIG_INFO( 1, 1, CL_DEVICE_MAX_CONSTANT_ARGS, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_LOCAL_MEM_TYPE, cl_local_mem_type), + CONFIG_INFO( 1, 1, CL_DEVICE_LOCAL_MEM_SIZE, cl_ulong), + CONFIG_INFO( 1, 1, CL_DEVICE_ERROR_CORRECTION_SUPPORT, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_HOST_UNIFIED_MEMORY, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_PROFILING_TIMER_RESOLUTION, size_t), + CONFIG_INFO( 1, 1, CL_DEVICE_ENDIAN_LITTLE, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_AVAILABLE, cl_uint), + CONFIG_INFO( 1, 1, CL_DEVICE_COMPILER_AVAILABLE, cl_uint), + CONFIG_INFO( 1, 2, CL_DEVICE_LINKER_AVAILABLE, cl_uint), + + CONFIG_INFO( 1, 2, CL_DEVICE_BUILT_IN_KERNELS, string), + + CONFIG_INFO( 1, 2, CL_DEVICE_PRINTF_BUFFER_SIZE, size_t), + CONFIG_INFO( 1, 2, CL_DEVICE_PREFERRED_INTEROP_USER_SYNC, cl_uint), + + CONFIG_INFO( 1, 2, CL_DEVICE_PARENT_DEVICE, cl_device_id), + CONFIG_INFO( 1, 2, CL_DEVICE_PARTITION_MAX_SUB_DEVICES, cl_uint), + CONFIG_INFO( 1, 2, CL_DEVICE_PARTITION_AFFINITY_DOMAIN, cl_device_affinity_domain), + CONFIG_INFO( 1, 2, CL_DEVICE_REFERENCE_COUNT, cl_uint), + + CONFIG_INFO( 1, 1, CL_DEVICE_EXECUTION_CAPABILITIES, cl_device_exec_capabilities), + CONFIG_INFO( 1, 1, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES, cl_command_queue_properties), + CONFIG_INFO( 1, 1, CL_DEVICE_NAME, string), + CONFIG_INFO( 1, 1, CL_DEVICE_VENDOR, string), + CONFIG_INFO( 1, 1, CL_DRIVER_VERSION, string), + CONFIG_INFO( 1, 1, CL_DEVICE_PROFILE, string), + CONFIG_INFO( 1, 1, CL_DEVICE_VERSION, string), + CONFIG_INFO( 1, 1, CL_DEVICE_OPENCL_C_VERSION, string), + CONFIG_INFO( 1, 1, CL_DEVICE_EXTENSIONS, string), + + CONFIG_INFO( 2, 0, CL_DEVICE_MAX_PIPE_ARGS, cl_uint), + CONFIG_INFO( 2, 0, CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS, cl_uint), + CONFIG_INFO( 2, 0, CL_DEVICE_PIPE_MAX_PACKET_SIZE, cl_uint), + + CONFIG_INFO( 2, 0, CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE, size_t), + CONFIG_INFO( 2, 0, CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE, size_t), + + CONFIG_INFO( 2, 0, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES, cl_command_queue_properties), + CONFIG_INFO( 2, 0, CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES, cl_command_queue_properties), + CONFIG_INFO( 2, 0, CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE, cl_uint), + CONFIG_INFO( 2, 0, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, cl_uint), + CONFIG_INFO( 2, 0, CL_DEVICE_MAX_ON_DEVICE_QUEUES, cl_uint), + CONFIG_INFO( 2, 0, CL_DEVICE_MAX_ON_DEVICE_EVENTS, cl_uint), + + CONFIG_INFO( 2, 0, CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT, cl_uint), + CONFIG_INFO( 2, 0, CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT, cl_uint), + CONFIG_INFO( 2, 0, CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT , cl_uint), + + CONFIG_INFO( 2, 0, CL_DEVICE_SVM_CAPABILITIES, cl_device_svm_capabilities), +}; + +#define ENTRY(T) { T, #T } +struct image_type_entry { + cl_mem_object_type val; + const char *str; +}; +static const struct image_type_entry image_types[] = { + ENTRY(CL_MEM_OBJECT_IMAGE1D), ENTRY(CL_MEM_OBJECT_IMAGE1D_BUFFER), + ENTRY(CL_MEM_OBJECT_IMAGE2D), ENTRY(CL_MEM_OBJECT_IMAGE3D), + ENTRY(CL_MEM_OBJECT_IMAGE1D_ARRAY), ENTRY(CL_MEM_OBJECT_IMAGE2D_ARRAY) +}; + +struct supported_flags_entry { + cl_mem_flags val; + const char *str; +}; + +static const struct supported_flags_entry supported_flags[] = { + ENTRY(CL_MEM_READ_ONLY), ENTRY(CL_MEM_WRITE_ONLY), + ENTRY(CL_MEM_READ_WRITE), ENTRY(CL_MEM_KERNEL_READ_AND_WRITE) +}; + +int getImageInfo(cl_device_id device) +{ + cl_context ctx; + cl_int err; + cl_uint i, num_supported; + cl_image_format *formats; + int num_errors; + int ii, ni = sizeof(image_types)/sizeof(image_types[0]); + int fi, nf = sizeof(supported_flags)/sizeof(supported_flags[0]); + + ctx = clCreateContext(NULL, 1, &device, notify_callback, NULL, &err); + if (!ctx) { + print_error(err, "Unable to create context from device"); + return 1; + } + + num_errors = 0; + for (ii=0; iiconfig_type) + { + case type_cl_device_type: + err = clGetDeviceInfo(device, info->opcode, sizeof(info->config.type), &info->config.type, &config_size_ret); + size_err = config_size_ret != sizeof(info->config.type); + break; + case type_cl_device_fp_config: + err = clGetDeviceInfo(device, info->opcode, sizeof(info->config.fp_config), &info->config.fp_config, &config_size_ret); + size_err = config_size_ret != sizeof(info->config.fp_config); + break; + case type_cl_device_mem_cache_type: + err = clGetDeviceInfo(device, info->opcode, sizeof(info->config.mem_cache_type), &info->config.mem_cache_type, &config_size_ret); + size_err = config_size_ret != sizeof(info->config.mem_cache_type); + break; + case type_cl_local_mem_type: + err = clGetDeviceInfo(device, info->opcode, sizeof(info->config.local_mem_type), &info->config.local_mem_type, &config_size_ret); + size_err = config_size_ret != sizeof(info->config.local_mem_type); + break; + case type_cl_device_exec_capabilities: + err = clGetDeviceInfo(device, info->opcode, sizeof(info->config.exec_capabilities), &info->config.exec_capabilities, &config_size_ret); + size_err = config_size_ret != sizeof(info->config.exec_capabilities); + break; + case type_cl_command_queue_properties: + err = clGetDeviceInfo(device, info->opcode, sizeof(info->config.queue_properties), &info->config.queue_properties, &config_size_ret); + size_err = config_size_ret != sizeof(info->config.queue_properties); + break; + case type_cl_device_id: + err = clGetDeviceInfo(device, info->opcode, sizeof(info->config.device_id), &info->config.device_id, &config_size_ret); + size_err = config_size_ret != sizeof(info->config.device_id); + break; + case type_cl_device_affinity_domain: + err = clGetDeviceInfo(device, info->opcode, sizeof(info->config.affinity_domain), &info->config.affinity_domain, &config_size_ret); + size_err = config_size_ret != sizeof(info->config.affinity_domain); + break; + case type_cl_uint: + err = clGetDeviceInfo(device, info->opcode, sizeof(info->config.uint), &info->config.uint, &config_size_ret); + size_err = config_size_ret != sizeof(info->config.uint); + break; + case type_size_t_arr: + err = clGetDeviceInfo(device, info->opcode, sizeof(info->config.sizet_arr), &info->config.sizet_arr, &config_size_ret); + size_err = config_size_ret != sizeof(info->config.sizet_arr); + break; + case type_size_t: + err = clGetDeviceInfo(device, info->opcode, sizeof(info->config.sizet), &info->config.sizet, &config_size_ret); + size_err = config_size_ret != sizeof(info->config.sizet); + break; + case type_cl_ulong: + err = clGetDeviceInfo(device, info->opcode, sizeof(info->config.ull), &info->config.ull, &config_size_ret); + size_err = config_size_ret != sizeof(info->config.ull); + break; + case type_string: + err = clGetDeviceInfo(device, info->opcode, sizeof(info->config.string), &info->config.string, &config_size_ret); + break; + case type_cl_device_svm_capabilities: + err = clGetDeviceInfo(device, info->opcode, sizeof(info->config.svmCapabilities), &info->config.svmCapabilities, &config_size_ret); + break; + default: + log_error("Unknown config type: %d\n", info->config_type); + break; + } + if (err || size_err) + log_error("\tFailed clGetDeviceInfo for %s.\n", info->opcode_name); + if(err) + print_error(err, "\t\tclGetDeviceInfo failed."); + if (size_err) + log_error("\t\tWrong size return from clGetDeviceInfo.\n"); + return err || size_err; +} + +void dumpConfigInfo(cl_device_id device, config_info* info) +{ + // We should not error if we find an unknown configuration since vendors + // may specify their own options beyond the list in the specification. + switch(info->config_type) + { + case type_cl_device_type: + log_info("\t%s == %s|%s|%s|%s\n", info->opcode_name, + (info->config.fp_config & CL_DEVICE_TYPE_CPU) ? "CL_DEVICE_TYPE_CPU":"", + (info->config.fp_config & CL_DEVICE_TYPE_GPU) ? "CL_DEVICE_TYPE_GPU":"", + (info->config.fp_config & CL_DEVICE_TYPE_ACCELERATOR) ? "CL_DEVICE_TYPE_ACCELERATOR":"", + (info->config.fp_config & CL_DEVICE_TYPE_DEFAULT) ? "CL_DEVICE_TYPE_DEFAULT":"" + ); + { + cl_device_type all_device_types = CL_DEVICE_TYPE_CPU | CL_DEVICE_TYPE_GPU | CL_DEVICE_TYPE_ACCELERATOR | CL_DEVICE_TYPE_DEFAULT; + if(info->config.fp_config & ~all_device_types) + { + log_info("WARNING: %s unknown bits found 0x%08llX", info->opcode_name, (info->config.fp_config & ~all_device_types)); + } + } + break; + case type_cl_device_fp_config: + log_info("\t%s == %s|%s|%s|%s|%s|%s|%s\n", info->opcode_name, + (info->config.fp_config & CL_FP_DENORM) ? "CL_FP_DENORM":"", + (info->config.fp_config & CL_FP_INF_NAN) ? "CL_FP_INF_NAN":"", + (info->config.fp_config & CL_FP_ROUND_TO_NEAREST) ? "CL_FP_ROUND_TO_NEAREST":"", + (info->config.fp_config & CL_FP_ROUND_TO_ZERO) ? "CL_FP_ROUND_TO_ZERO":"", + (info->config.fp_config & CL_FP_ROUND_TO_INF) ? "CL_FP_ROUND_TO_INF":"", + (info->config.fp_config & CL_FP_FMA) ? "CL_FP_FMA":"", + (info->config.fp_config & CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT) ? "CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT":"" + ); + { + cl_device_fp_config all_fp_config = CL_FP_DENORM | CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST | + CL_FP_ROUND_TO_ZERO | CL_FP_ROUND_TO_INF | CL_FP_FMA | + CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT; + if(info->config.fp_config & ~all_fp_config) + log_info("WARNING: %s unknown bits found 0x%08llX", info->opcode_name, (info->config.fp_config & ~all_fp_config)); + } + break; + case type_cl_device_mem_cache_type: + switch(info->config.mem_cache_type) + { + case CL_NONE: + log_info("\t%s == CL_NONE\n", info->opcode_name); + break; + case CL_READ_ONLY_CACHE: + log_info("\t%s == CL_READ_ONLY_CACHE\n", info->opcode_name); + break; + case CL_READ_WRITE_CACHE: + log_info("\t%s == CL_READ_WRITE_CACHE\n", info->opcode_name); + break; + default: + log_error("ERROR: %s out of range, %d\n", info->opcode_name, info->config.mem_cache_type); + break; + } + break; + case type_cl_local_mem_type: + switch(info->config.local_mem_type) + { + case CL_NONE: + log_info("\t%s == CL_NONE\n", info->opcode_name); + break; + case CL_LOCAL: + log_info("\t%s == CL_LOCAL\n", info->opcode_name); + break; + case CL_GLOBAL: + log_info("\t%s == CL_GLOBAL\n", info->opcode_name); + break; + default: + log_info("WARNING: %s out of range, %d\n", info->opcode_name, info->config.local_mem_type); + break; + } + break; + case type_cl_device_exec_capabilities: + log_info("\t%s == %s|%s\n", info->opcode_name, + (info->config.exec_capabilities & CL_EXEC_KERNEL) ? "CL_EXEC_KERNEL":"", + (info->config.exec_capabilities & CL_EXEC_NATIVE_KERNEL) ? "CL_EXEC_NATIVE_KERNEL":"" ); + { + cl_device_exec_capabilities all_exec_cap = CL_EXEC_KERNEL | CL_EXEC_NATIVE_KERNEL; + if(info->config.exec_capabilities & ~all_exec_cap) + log_info("WARNING: %s unknown bits found 0x%08llX", info->opcode_name, (info->config.exec_capabilities & ~all_exec_cap)); + } + break; + case type_cl_command_queue_properties: + log_info("\t%s == %s|%s\n", info->opcode_name, + (info->config.queue_properties & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE) ? "CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE":"", + (info->config.queue_properties & CL_QUEUE_PROFILING_ENABLE) ? "CL_QUEUE_PROFILING_ENABLE":""); + { + cl_command_queue_properties all_queue_properties = CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_PROFILING_ENABLE; + if(info->config.queue_properties & ~all_queue_properties) + log_info("WARNING: %s unknown bits found 0x%08llX", info->opcode_name, (info->config.exec_capabilities & ~all_queue_properties)); + } + break; + case type_cl_device_id: + log_info("\t%s == %ld\n", info->opcode_name, (intptr_t)info->config.device_id); + break; + case type_cl_device_affinity_domain: + log_info("\t%s == %s|%s|%s|%s|%s|%s\n", info->opcode_name, + (info->config.affinity_domain & CL_DEVICE_AFFINITY_DOMAIN_NUMA) ? "CL_DEVICE_AFFINITY_DOMAIN_NUMA":"", + (info->config.affinity_domain & CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE) ? "CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE":"", + (info->config.affinity_domain & CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE) ? "CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE":"", + (info->config.affinity_domain & CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE) ? "CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE":"", + (info->config.affinity_domain & CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE) ? "CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE":"", + (info->config.affinity_domain & CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE) ? "CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE":"" + ); + { + cl_device_affinity_domain all_affinity_domain = CL_DEVICE_AFFINITY_DOMAIN_NUMA | + CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE | + CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE | + CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE | + CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE | + CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE; + if(info->config.affinity_domain & ~all_affinity_domain) + log_error("ERROR: %s unknown bits found 0x%08llX", info->opcode_name, (info->config.affinity_domain & ~all_affinity_domain)); + } + break; + case type_cl_uint: + log_info("\t%s == %u\n", info->opcode_name, info->config.uint); + break; + case type_size_t_arr: + log_info("\t%s == %d %d %d\n", info->opcode_name, info->config.sizet_arr[0], + info->config.sizet_arr[1], info->config.sizet_arr[2]); + break; + case type_size_t: + log_info("\t%s == %ld\n", info->opcode_name, info->config.sizet); + break; + case type_cl_ulong: + log_info("\t%s == %lld\n", info->opcode_name, info->config.ull); + break; + case type_string: + log_info("\t%s == \"%s\"\n", info->opcode_name, info->config.string); + break; + case type_cl_device_svm_capabilities: + log_info("\t%s == %s|%s|%s|%s\n", info->opcode_name, + (info->config.svmCapabilities & CL_DEVICE_SVM_COARSE_GRAIN_BUFFER) ? "CL_DEVICE_SVM_COARSE_GRAIN_BUFFER":"", + (info->config.svmCapabilities & CL_DEVICE_SVM_FINE_GRAIN_BUFFER) ? "CL_DEVICE_SVM_FINE_GRAIN_BUFFER":"", + (info->config.svmCapabilities & CL_DEVICE_SVM_FINE_GRAIN_SYSTEM) ? "CL_DEVICE_SVM_FINE_GRAIN_SYSTEM":"", + (info->config.svmCapabilities & CL_DEVICE_SVM_ATOMICS) ? "CL_DEVICE_SVM_ATOMICS":""); + { + cl_device_svm_capabilities all_svm_capabilities = CL_DEVICE_SVM_COARSE_GRAIN_BUFFER | + CL_DEVICE_SVM_FINE_GRAIN_BUFFER | + CL_DEVICE_SVM_FINE_GRAIN_SYSTEM | + CL_DEVICE_SVM_ATOMICS; + if(info->config.svmCapabilities & ~all_svm_capabilities) + log_info("WARNING: %s unknown bits found 0x%08llX", info->opcode_name, (info->config.svmCapabilities & ~all_svm_capabilities)); + } + break; + } +} + +void print_platform_string_selector( cl_platform_id platform, const char *selector_name, cl_platform_info selector ) +{ + // Currently all the selectors are strings + size_t size = 0; + char *value; + int err; + + if(( err = clGetPlatformInfo( platform, selector, 0, NULL, &size ))) + { + log_error( "FAILURE: Unable to get platform info size for %s.\n", selector_name ); + exit( -1 ); + } + + if( size == 0 ) + { + log_error( "FAILURE: The size of %s was returned to be zero.\n", selector_name ); + exit( -1 ); + } + + value = (char*) malloc( size ); + if( NULL == value ) + { + log_error( "Internal test failure: Unable to allocate %ld bytes\n", size ); + exit(-1); + } + + memset( value, -1, size ); + if(( err = clGetPlatformInfo( platform, selector, size, value, NULL ))) + { + log_error( "FAILURE: Unable to get platform info for %s.\n", selector_name ); + free( value ); + exit( -1 ); + } + + if( value[size-1] != '\0' ) + { + log_error( "FAILURE: platform info for %s is either not NUL terminated, or the size is wrong.\n", selector_name ); + free( value ); + exit( -1 ); + } + + log_info( "\t%s: %s\n", selector_name, value ); + free( value ); +} + +int parseVersion( char const * str, version_t * version ) +{ + int rc = -1; + version->major = 0; + version->minor = 0; + if ( strncmp( str, "OpenCL 1.2", 10 ) == 0 && ( str[ 10 ] == 0 || str[ 10 ] == ' ' ) ) { + version->major = 1; + version->minor = 2; + rc = 0; + } else if ( strncmp( str, "OpenCL 1.1", 10 ) == 0 && ( str[ 10 ] == 0 || str[ 10 ] == ' ' ) ) { + version->major = 1; + version->minor = 1; + rc = 0; + } else if ( strncmp( str, "OpenCL 2.0", 10 ) == 0 && ( str[ 10 ] == 0 || str[ 10 ] == ' ' ) ) { + version->major = 2; + version->minor = 0; + rc = 0; + } else if ( strncmp( str, "OpenCL 2.1", 10 ) == 0 && ( str[ 10 ] == 0 || str[ 10 ] == ' ' ) ) { + version->major = 2; + version->minor = 1; + rc = 0; + } else { + log_error( "ERROR: Unexpected version string: `%s'.\n", str ); + }; + return rc; +} + +int parseExtensions( char const * str, extensions_t * extensions ) +{ + char const * begin = NULL; + char const * space = NULL; + size_t length = 0; + + memset( extensions, 0, sizeof ( extensions_t ) ); + + begin = str; + while ( begin[ 0 ] != 0 ) { + space = strchr( begin, ' ' ); // Find space position. + if ( space != NULL ) { // Calculate length of word. + length = space - begin; + } else { + length = strlen( begin ); + } + if ( strncmp( begin, "cl_khr_fp64", length ) == 0 ) { + extensions->cl_khr_fp64 = 1; + } + if ( strncmp( begin, "cl_khr_fp16", length ) == 0 ) { + extensions->cl_khr_fp16 = 1; + } + begin += length; // Skip word. + if ( begin[ 0 ] == ' ' ) { // Skip space, if any. + begin += 1; + } + } + + return 0; +} + +int getConfigInfos( cl_device_id device ) +{ + int total_errors = 0; + unsigned onConfigInfo; + version_t version = { 0, 0 }; // Version of the device. Will get real value on the first loop iteration. + version_t const ver11 = { 1, 1 }; // Version 1.1. + extensions_t extensions = { 0 }; + int get; // Boolean flag: true = get property, false = skip it. + int err; + for ( onConfigInfo = 0; onConfigInfo < sizeof(config_infos) / sizeof(config_infos[0]); onConfigInfo++) { + config_info info = config_infos[ onConfigInfo ]; + // Get a property only if device version is equal or greater than property version. + get = ( vercmp( version, info.version ) >= 0 ); + if ( info.opcode == CL_DEVICE_DOUBLE_FP_CONFIG && vercmp( version, ver11 ) <= 0 ) { + // CL_DEVICE_DOUBLE_FP_CONFIG is a special case. It was introduced in OpenCL 1.1, but + // device is required to report it only if doubles are supported. So, before querying + // it on device version 1.1, we have to check doubles are sopported. + // In OpenCL 1.2 CL_DEVICE_DOUBLE_FP_CONFIG should be reported unconditionally. + get = extensions.cl_khr_fp64; + }; + if ( info.opcode == CL_DEVICE_HALF_FP_CONFIG ) { + // CL_DEVICE_HALF_FP_CONFIG should be reported only when cl_khr_fp16 extension is available + get = extensions.cl_khr_fp16; + }; + if ( get ) { + err = getConfigInfo(device, & info); + if ( ! err ) { + dumpConfigInfo(device, & info); + if ( info.opcode == CL_DEVICE_VERSION ) { + err = parseVersion( info.config.string, & version ); + if ( err ) { + total_errors++; + break; + } + } else if ( info.opcode == CL_DEVICE_EXTENSIONS ) { + err = parseExtensions( info.config.string, & extensions ); + if ( err ) { + total_errors++; + break; + } + } + } else { + total_errors++; + } + } else { + log_info( "\tSkipped: %s.\n", info.opcode_name ); + } + } + + if (is_extension_available(device, "cl_khr_image2d_from_buffer")){ + for ( onConfigInfo = 0; onConfigInfo < sizeof(image_buffer_config_infos) / sizeof(image_buffer_config_infos[0]); onConfigInfo++) { + config_info info = image_buffer_config_infos[ onConfigInfo ]; + get = ( vercmp( version, info.version ) >= 0 ); + if ( get ) { + err = getConfigInfo(device, & info); + if ( ! err ) { + dumpConfigInfo(device, & info); + } + else { + total_errors++; + } + } + } + } + + total_errors += getImageInfo(device); + + return total_errors; +} + + +int main(int argc, const char** argv) +{ + cl_platform_id platform; + test_start(); + + if (argc == 2) { + if (!strcmp(argv[1], "-v")) + dump_supported_formats = 1; + else { + log_info("Use option \"-v\" for verbose output\n"); + return 0; + } + } + + int err; + int total_errors = 0; + + err = clGetPlatformIDs(1, &platform, NULL); + test_error(err, "clGetPlatformIDs failed"); + if (err != CL_SUCCESS) { + total_errors++; + } + + // print platform info + log_info( "\nclGetPlatformInfo:\n------------------\n" ); + print_platform_string_selector( platform, "CL_PLATFORM_PROFILE", CL_PLATFORM_PROFILE ); + print_platform_string_selector( platform, "CL_PLATFORM_VERSION", CL_PLATFORM_VERSION ); + print_platform_string_selector( platform, "CL_PLATFORM_NAME", CL_PLATFORM_NAME ); + print_platform_string_selector( platform, "CL_PLATFORM_VENDOR", CL_PLATFORM_VENDOR ); + print_platform_string_selector( platform, "CL_PLATFORM_EXTENSIONS", CL_PLATFORM_EXTENSIONS ); + log_info( "\n" ); + + // Check to see if this test is being run on a specific device + char* device_type_env = getenv("CL_DEVICE_TYPE"); + char* device_index_env = getenv("CL_DEVICE_INDEX"); + + if (device_type_env || device_index_env) { + + cl_device_type device_type = CL_DEVICE_TYPE_DEFAULT; + size_t device_type_idx = 0; + size_t device_index = 0; + + // Check to see if a device type was specified. + if (device_type_env) { + if (!strcmp(device_type_env,"default") || !strcmp(device_type_env,"CL_DEVICE_TYPE_DEFAULT")) { + device_type = CL_DEVICE_TYPE_DEFAULT; + device_type_idx = 0; + } + else if (!strcmp(device_type_env,"cpu") || !strcmp(device_type_env,"CL_DEVICE_TYPE_CPU")) { + device_type = CL_DEVICE_TYPE_CPU; + device_type_idx = 1; + } + else if (!strcmp(device_type_env,"gpu") || !strcmp(device_type_env,"CL_DEVICE_TYPE_GPU")) { + device_type = CL_DEVICE_TYPE_GPU; + device_type_idx = 2; + } + else if (!strcmp(device_type_env,"accelerator") || !strcmp(device_type_env,"CL_DEVICE_TYPE_ACCELERATOR")) { + device_type = CL_DEVICE_TYPE_ACCELERATOR; + device_type_idx = 3; + } + else { + log_error("CL_DEVICE_TYPE=\"%s\" is invalid\n",device_type_env); + return -1; + } + } + + // Check to see if a device index was specified + if (device_index_env) + device_index = atoi(device_index_env); + + // Look up the device + cl_uint num_devices; + err = clGetDeviceIDs(platform, device_type, 0, NULL, &num_devices); + if (err) + { + log_error("No devices of type %s found.\n", device_type_env); + return -1; + } + + if (device_index >= num_devices) { + log_error("CL_DEVICE_INDEX=%d is greater than the number of matching devices %d\n",(unsigned)device_index,num_devices); + return -1; + } + + if (num_devices == 0) + { + log_error("No devices of type %s found.\n", device_type_env); + return -1; + } + + cl_device_id *devices = (cl_device_id *) malloc( num_devices * sizeof( cl_device_id ) ); + err = clGetDeviceIDs(platform, device_type, num_devices, devices, NULL); + if (err) + { + log_error("No devices of type %s found.\n", device_type_env); + free(devices); + return -1; + } + + cl_device_id device = devices[device_index]; + free(devices); + + log_info("%s Device %d of %d Info:\n", device_infos[device_type_idx].device_type_name, (unsigned)device_index+1, num_devices); + total_errors += getConfigInfos( device ); + log_info("\n"); + + } + + // Otherwise iterate over all of the devices in the platform + else { + //print device info + int onInfo; + for(onInfo = 0; onInfo < sizeof(device_infos) / sizeof(device_infos[0]); onInfo++) + { + log_info("Getting device IDs for %s devices\n", device_infos[onInfo].device_type_name); + err = clGetDeviceIDs(platform, device_infos[onInfo].device_type, 0, NULL, &device_infos[onInfo].num_devices); + if (err == CL_DEVICE_NOT_FOUND) + { + log_info("No devices of type %s found.\n", device_infos[onInfo].device_type_name); + continue; + } + test_error(err, "clGetDeviceIDs failed"); + + log_info("Found %d %s devices:\n", device_infos[onInfo].num_devices, device_infos[onInfo].device_type_name); + if(device_infos[onInfo].num_devices) + { + device_infos[onInfo].devices = (cl_device_id *)malloc(sizeof(cl_device_id) * device_infos[onInfo].num_devices); + err = clGetDeviceIDs(platform, device_infos[onInfo].device_type, device_infos[onInfo].num_devices, device_infos[onInfo].devices, NULL); + test_error(err, "clGetDeviceIDs failed"); + } + + int onDevice; + for(onDevice = 0; onDevice < device_infos[onInfo].num_devices; onDevice++) + { + log_info("%s Device %d of %d Info:\n", device_infos[onInfo].device_type_name, onDevice+1, device_infos[onInfo].num_devices); + total_errors += getConfigInfos( device_infos[onInfo].devices[onDevice] ); + log_info("\n"); + } + + if(device_infos[onInfo].num_devices) + { + free(device_infos[onInfo].devices); + } + } + } + + if (total_errors) + log_error("FAILED computeinfo.\n"); + else + log_info("PASSED computeinfo.\n"); + + test_finish(); + if (total_errors) + return -1; + return 0; +} + diff --git a/test_conformance/contractions/CMakeLists.txt b/test_conformance/contractions/CMakeLists.txt new file mode 100644 index 00000000..ac407682 --- /dev/null +++ b/test_conformance/contractions/CMakeLists.txt @@ -0,0 +1,15 @@ +set(MODULE_NAME CONTRACTIONS) + +set(${MODULE_NAME}_SOURCES + contractions.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/mingw_compat.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/rounding_mode.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) diff --git a/test_conformance/contractions/Jamfile b/test_conformance/contractions/Jamfile new file mode 100644 index 00000000..a5bd7f19 --- /dev/null +++ b/test_conformance/contractions/Jamfile @@ -0,0 +1,13 @@ +project + : requirements +# gcc:-xc++ + msvc:"/TP" + ; + +exe contractions : contractions.c ; + +install dist + : contractions + : debug:$(DIST)/debug/tests/test_conformance/contractions + release:$(DIST)/release/tests/test_conformance/contractions + ; diff --git a/test_conformance/contractions/Makefile b/test_conformance/contractions/Makefile new file mode 100644 index 00000000..14e283dc --- /dev/null +++ b/test_conformance/contractions/Makefile @@ -0,0 +1,32 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +CC = c++ +CFLAGS = -g -arch i386 -arch x86_64 -Wall $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} -I ../../test_common/harness +LIBRARIES = -framework OpenCL -framework ApplicationServices -framework IOKit -I/System/Library/Frameworks/OpenCL.framework/Headers ${RC_CFLAGS} ${ATF} + +release: + echo "Build Release" + $(CC) *.c ../../test_common/harness/rounding_mode.c ../../test_common/harness/kernelHelpers.c ../../test_common/harness/errorHelpers.c ../../test_common/harness/mt19937.c -Os $(CFLAGS) -o contractions $(LIBRARIES) + +debug: + echo "Build Debug" + $(CC) *.c ../../test_common/harness/rounding_mode.c ../../test_common/harness/kernelHelpers.c ../../test_common/harness/errorHelpers.c ../../test_common/harness/mt19937.c -O0 $(CFLAGS) -D_DEBUG=1 -o contractions_debug $(LIBRARIES) + +test: release + arch -i386 ./contractions -c > cpu.log; + arch -i386 ./contractions -g > gpu.log; + +test64: release + arch -x86_64 ./contractions_debug -c > cpu64.log; + arch -x86_64 ./contractions_debug -g > gpu64.log; + echo "Testing 64-bit mode in progress. This may take up to 1 day to complete. See cpu64.log and gpu64.log for results." + + +clean: + rm -f ./contractions + rm -f ./contractions_debug + +all: release diff --git a/test_conformance/contractions/contractions.c b/test_conformance/contractions/contractions.c new file mode 100644 index 00000000..164fde6c --- /dev/null +++ b/test_conformance/contractions/contractions.c @@ -0,0 +1,1217 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include + +#if !defined(_WIN32) +#include +#include +#endif + +#include "mingw_compat.h" +#if defined (__MINGW32__) +#include +#endif + +#include +#include "errorHelpers.h" +#include "../../test_common/harness/compat.h" +#include "../../test_common/harness/mt19937.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/rounding_mode.h" +#include "../../test_common/harness/fpcontrol.h" +#include "../../test_common/harness/parseParameters.h" +#if defined( __APPLE__ ) +#include +#endif +#if defined( __linux__ ) +#include +#include +#include +#endif + +#if defined (_WIN32) +#include +#endif + +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) +#include +#endif + +#if defined(__PPC__) +// Global varaiable used to hold the FPU control register state. The FPSCR register can not +// be used because not all Power implementations retain or observed the NI (non-IEEE +// mode) bit. +__thread fpu_control_t fpu_control = 0; +#endif + +#ifndef MAXPATHLEN +#define MAXPATHLEN 2048 +#endif + +char appName[ MAXPATHLEN ] = ""; +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +cl_device_id gDevice = NULL; +cl_context gContext = NULL; +cl_command_queue gQueue = NULL; +cl_program gProgram[5] = { NULL, NULL, NULL, NULL, NULL }; +cl_program gProgram_double[5] = { NULL, NULL, NULL, NULL, NULL }; +int gForceFTZ = 0; +int gSeed = 0; +int gSeedSpecified = 0; +int gHasDouble = 0; +MTdata gMTdata = NULL; +int gSkipNanInf = 0; +int gIgnoreZeroSign = 0; + +cl_mem bufA = NULL; +cl_mem bufB = NULL; +cl_mem bufC = NULL; +cl_mem bufD = NULL; +cl_mem bufE = NULL; +cl_mem bufC_double = NULL; +cl_mem bufD_double = NULL; +float *buf1, *buf2, *buf3, *buf4, *buf5, *buf6; +float *correct[8]; +int *skipTest[8]; + +double *buf3_double, *buf4_double, *buf5_double, *buf6_double; +double *correct_double[8]; + +#define BUFFER_SIZE (1024*1024) + + +static int ParseArgs( int argc, const char **argv ); +static void PrintArch( void ); +static void PrintUsage( void ); +static int InitCL( void ); +static void ReleaseCL( void ); +static int RunTest( int testNumber ); +static int RunTest_Double( int testNumber ); + +#if defined(__ANDROID__) +#define nanf( X ) strtof( "NAN", ( char ** ) NULL ) +#define nan( X ) strtod( "NAN", ( char ** ) NULL ) +#endif + +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) +// defeat x87 on MSVC +float sse_add(float x, float y) +{ + volatile float a = x; + volatile float b = y; + + // defeat x87 + __m128 va = _mm_set_ss( (float) a ); + __m128 vb = _mm_set_ss( (float) b ); + va = _mm_add_ss( va, vb ); + _mm_store_ss( (float*) &a, va ); + return a; +} + +double sse_add_sd(double x, double y) +{ + volatile double a = x; + volatile double b = y; + + // defeat x87 + __m128d va = _mm_set_sd( (double) a ); + __m128d vb = _mm_set_sd( (double) b ); + va = _mm_add_sd( va, vb ); + _mm_store_sd( (double*) &a, va ); + return a; +} + +float sse_sub(float x, float y) +{ + volatile float a = x; + volatile float b = y; + + // defeat x87 + __m128 va = _mm_set_ss( (float) a ); + __m128 vb = _mm_set_ss( (float) b ); + va = _mm_sub_ss( va, vb ); + _mm_store_ss( (float*) &a, va ); + return a; +} + +double sse_sub_sd(double x, double y) +{ + volatile double a = x; + volatile double b = y; + + // defeat x87 + __m128d va = _mm_set_sd( (double) a ); + __m128d vb = _mm_set_sd( (double) b ); + va = _mm_sub_sd( va, vb ); + _mm_store_sd( (double*) &a, va ); + return a; +} + +float sse_mul(float x, float y) +{ + volatile float a = x; + volatile float b = y; + + // defeat x87 + __m128 va = _mm_set_ss( (float) a ); + __m128 vb = _mm_set_ss( (float) b ); + va = _mm_mul_ss( va, vb ); + _mm_store_ss( (float*) &a, va ); + return a; +} + +double sse_mul_sd(double x, double y) +{ + volatile double a = x; + volatile double b = y; + + // defeat x87 + __m128d va = _mm_set_sd( (double) a ); + __m128d vb = _mm_set_sd( (double) b ); + va = _mm_mul_sd( va, vb ); + _mm_store_sd( (double*) &a, va ); + return a; +} +#endif + +#ifdef __PPC__ +float ppc_mul(float a, float b) +{ + float p; + + if (gForceFTZ) { + // Flush input a to zero if it is sub-normal + if (fabsf(a) < FLT_MIN) { + a = copysignf(0.0, a); + } + // Flush input b to zero if it is sub-normal + if (fabsf(b) < FLT_MIN) { + b = copysignf(0.0, b); + } + // Perform multiply + p = a * b; + // Flush the product if it is a sub-normal + if (fabs((double)a * (double)b) < FLT_MIN) { + p = copysignf(0.0, p); + } + } else { + p = a * b; + } + return p; +} +#endif + +int main( int argc, const char **argv ) +{ + int error = 0; + int i; + + test_start(); + argc = parseCustomParam(argc, argv); + if (argc == -1) + { + test_finish(); + return -1; + } + + error = ParseArgs( argc, argv ); + if( error ) + return error; + + // Init OpenCL + error = InitCL(); + if( error ) + return error; + + // run the tests + log_info( "Testing floats...\n" ); + for( i = 0; i < 8; i++ ) + error |= RunTest( i ); + + if( gHasDouble ) + { + log_info( "Testing doubles...\n" ); + for( i = 0; i < 8; i++ ) + error |= RunTest_Double( i ); + } + + + int flush_error = clFinish(gQueue); + if (flush_error) + log_error("clFinish failed: %d\n", flush_error); + + if( error ) + vlog_error( "Contractions test FAILED.\n" ); + else + vlog( "Contractions test PASSED.\n" ); + + ReleaseCL(); + test_finish(); + + return error; +} + + + +static int ParseArgs( int argc, const char **argv ) +{ + int i; + int length_of_seed = 0; + + { // Extract the app name + strncpy( appName, argv[0], MAXPATHLEN ); + +#if (defined( __APPLE__ ) || defined(__linux__) || defined(__MINGW32__)) + char baseName[MAXPATHLEN]; + char *base = NULL; + strncpy( baseName, argv[0], MAXPATHLEN ); + base = basename( baseName ); + if( NULL != base ) + { + strncpy( appName, base, sizeof( appName ) ); + appName[ sizeof( appName ) -1 ] = '\0'; + } +#elif defined (_WIN32) + char fname[_MAX_FNAME + _MAX_EXT + 1]; + char ext[_MAX_EXT]; + + errno_t err = _splitpath_s( argv[0], NULL, 0, NULL, 0, + fname, _MAX_FNAME, ext, _MAX_EXT ); + if (err == 0) { // no error + strcat (fname, ext); //just cat them, size of frame can keep both + strncpy (appName, fname, sizeof(appName)); + appName[ sizeof( appName ) -1 ] = '\0'; + } +#endif + } + + /* Check if we are forced to CPU mode */ + char *env_mode = getenv( "CL_DEVICE_TYPE" ); + if( env_mode != NULL ) + { + if( strcmp( env_mode, "gpu" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_GPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_GPU; + else if( strcmp( env_mode, "cpu" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_CPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_CPU; + else if( strcmp( env_mode, "accelerator" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( env_mode, "default" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_DEFAULT; + else + { + vlog_error( "Unknown CL_DEVICE_TYPE env variable setting: %s.\nAborting...\n", env_mode ); + abort(); + } + } + + vlog( "\n%s\t", appName ); + for( i = 1; i < argc; i++ ) + { + const char *arg = argv[i]; + if( NULL == arg ) + break; + + vlog( "\t%s", arg ); + int optionFound = 0; + if( arg[0] == '-' ) + { + while( arg[1] != '\0' ) + { + arg++; + optionFound = 1; + switch( *arg ) + { + case 'h': + PrintUsage(); + return -1; + + case 's': + arg++; + gSeed = atoi( arg ); + while (arg[length_of_seed] >='0' && arg[length_of_seed]<='9') + length_of_seed++; + gSeedSpecified = 1; + arg+=length_of_seed-1; + break; + + case 'z': + gForceFTZ ^= 1; + break; + + case ' ': + break; + + default: + vlog( " <-- unknown flag: %c (0x%2.2x)\n)", *arg, *arg ); + PrintUsage(); + return -1; + } + } + } + else if( 0 == strcmp( arg, "CL_DEVICE_TYPE_CPU" ) ) + gDeviceType = CL_DEVICE_TYPE_CPU; + else if( 0 == strcmp( arg, "CL_DEVICE_TYPE_GPU" ) ) + gDeviceType = CL_DEVICE_TYPE_GPU; + else if( 0 == strcmp( arg, "CL_DEVICE_TYPE_ACCELERATOR" ) ) + gDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + else if( 0 == strcmp( arg, "CL_DEVICE_TYPE_DEFAULT" ) ) + gDeviceType = CL_DEVICE_TYPE_DEFAULT; + else + { + vlog( "ERROR -- unknown argument: %s\n", arg ); + abort(); + } + } + vlog( "\n\nTest binary built %s %s\n", __DATE__, __TIME__ ); + + PrintArch(); + + return 0; +} + +static void PrintArch( void ) +{ + vlog( "\nHost info:\n" ); + vlog( "\tsizeof( void*) = %ld\n", sizeof( void *) ); +#if defined( __ppc__ ) + vlog( "\tARCH:\tppc\n" ); +#elif defined( __ppc64__ ) + vlog( "\tARCH:\tppc64\n" ); +#elif defined( __PPC__ ) + vlog( "ARCH:\tppc\n" ); +#elif defined( __i386__ ) + vlog( "\tARCH:\ti386\n" ); +#elif defined( __x86_64__ ) + vlog( "\tARCH:\tx86_64\n" ); +#elif defined( __arm__ ) + vlog( "\tARCH:\tarm\n" ); +#else + vlog( "\tARCH:\tunknown\n" ); +#endif + +#if defined( __APPLE__ ) + int type = 0; + size_t typeSize = sizeof( type ); + sysctlbyname( "hw.cputype", &type, &typeSize, NULL, 0 ); + vlog( "\tcpu type:\t%d\n", type ); + typeSize = sizeof( type ); + sysctlbyname( "hw.cpusubtype", &type, &typeSize, NULL, 0 ); + vlog( "\tcpu subtype:\t%d\n", type ); + +#elif defined( __linux__ ) && !defined(__aarch64__) + int _sysctl(struct __sysctl_args *args ); +#define OSNAMESZ 100 + + struct __sysctl_args args; + char osname[OSNAMESZ]; + size_t osnamelth; + int name[] = { CTL_KERN, KERN_OSTYPE }; + memset(&args, 0, sizeof(struct __sysctl_args)); + args.name = name; + args.nlen = sizeof(name)/sizeof(name[0]); + args.oldval = osname; + args.oldlenp = &osnamelth; + + osnamelth = sizeof(osname); + + if (syscall(SYS__sysctl, &args) == -1) { + vlog( "_sysctl error\n" ); + } + else { + vlog("this machine is running %*s\n", osnamelth, osname); + } + +#endif +} + +static void PrintUsage( void ) +{ + vlog( "%s [-z]: \n", appName ); + vlog( "\toptions:\n" ); + vlog( "\t\t-z\tToggle FTZ mode (Section 6.5.3) for all functions. (Set by device capabilities by default.)\n" ); + vlog( "\t\t-sNUMBER set random seed.\n"); + vlog( "\n" ); +} + +const char *sizeNames[] = { "float", "float2", "float4", "float8", "float16" }; +const char *sizeNames_double[] = { "double", "double2", "double4", "double8", "double16" }; + +static void CL_CALLBACK notify_callback(const char *errinfo, const void *private_info, size_t cb, void *user_data) +{ + vlog( "%s\n", errinfo ); +} + +static int InitCL( void ) +{ + cl_platform_id platform = NULL; + int error; + uint32_t i, j; + int *bufSkip = NULL; + int isRTZ = 0; + int isEmbedded = 0; + RoundingMode oldRoundMode = kDefaultRoundingMode; + + if( (error = clGetPlatformIDs(1, &platform, NULL) ) ) + return error; + + if( (error = clGetDeviceIDs(platform, gDeviceType, 1, &gDevice, NULL )) ) + return error; + + cl_device_fp_config floatCapabilities = 0; + if( (error = clGetDeviceInfo(gDevice, CL_DEVICE_SINGLE_FP_CONFIG, sizeof(floatCapabilities), &floatCapabilities, NULL))) + floatCapabilities = 0; + if(0 == (CL_FP_DENORM & floatCapabilities) ) + gForceFTZ ^= 1; + + // check for cl_khr_fp64 + size_t extensions_size = 0; + if( (error = clGetDeviceInfo( gDevice, CL_DEVICE_EXTENSIONS, 0, NULL, &extensions_size ))) + { + vlog_error( "clGetDeviceInfo(CL_DEVICE_EXTENSIONS) failed. %d\n", error ); + return -1; + } + if( extensions_size ) + { + char *extensions = (char*)malloc(extensions_size); + if( NULL == extensions ) + { + vlog_error( "ERROR: Unable to allocate %ld bytes to hold extensions string\n", extensions_size ); + return -1; + } + + if( (error = clGetDeviceInfo( gDevice, CL_DEVICE_EXTENSIONS, extensions_size, extensions, NULL ))) + { + vlog_error( "clGetDeviceInfo(CL_DEVICE_EXTENSIONS) failed 2. %d\n", error ); + return -1; + } + + gHasDouble = NULL != strstr( extensions, "cl_khr_fp64" ); + free( extensions ); + } + + if(0 == (CL_FP_INF_NAN & floatCapabilities) ) + gSkipNanInf = 1; + + char profile[1024] = ""; + if ( (error = clGetDeviceInfo(gDevice, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL ) ) ) {} + else if (strstr(profile, "EMBEDDED_PROFILE")) + isEmbedded = 1; + + // Embedded devices that flush to zero are allowed to have an undefined sign. + if (isEmbedded && gForceFTZ) + gIgnoreZeroSign = 1; + + gContext = clCreateContext( NULL, 1, &gDevice, notify_callback, NULL, &error ); + if( NULL == gContext || error ) + { + vlog_error( "clCreateDeviceGroup failed. %d\n", error ); + return -1; + } + + gQueue = clCreateCommandQueueWithProperties( gContext, gDevice, 0, &error ); + if( NULL == gQueue || error ) + { + vlog_error( "clCreateContext failed. %d\n", error ); + return -2; + } + + // setup input buffers + bufA = clCreateBuffer( gContext, CL_MEM_READ_WRITE, BUFFER_SIZE, NULL, NULL ); + bufB = clCreateBuffer( gContext, CL_MEM_READ_WRITE, BUFFER_SIZE, NULL, NULL ); + bufC = clCreateBuffer( gContext, CL_MEM_READ_WRITE, BUFFER_SIZE, NULL, NULL ); + bufD = clCreateBuffer( gContext, CL_MEM_READ_WRITE, BUFFER_SIZE, NULL, NULL ); + bufE = clCreateBuffer( gContext, CL_MEM_READ_WRITE, BUFFER_SIZE, NULL, NULL ); + + if( bufA == NULL || + bufB == NULL || + bufC == NULL || + bufD == NULL || + bufE == NULL ) + { + vlog_error( "clCreateArray failed for input\n" ); + return -4; + } + + if( gHasDouble ) + { + bufC_double = clCreateBuffer( gContext, CL_MEM_READ_WRITE, BUFFER_SIZE, NULL, NULL ); + bufD_double = clCreateBuffer( gContext, CL_MEM_READ_WRITE, BUFFER_SIZE, NULL, NULL ); + if( bufC_double == NULL || + bufD_double == NULL ) + { + vlog_error( "clCreateArray failed for input DP\n" ); + return -4; + } + } + + const char *kernels[] = { + "", "#pragma OPENCL FP_CONTRACT OFF\n" + "__kernel void kernel1( __global ", NULL, " *out, const __global ", NULL, " *a, const __global ", NULL, " *b, const __global ", NULL, " *c )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = a[i] * b[i] + c[i];\n" + "}\n" + "\n" + "__kernel void kernel2( __global ", NULL, " *out, const __global ", NULL, " *a, const __global ", NULL, " *b, const __global ", NULL, " *c )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = a[i] * b[i] - c[i];\n" + "}\n" + "\n" + "__kernel void kernel3( __global ", NULL, " *out, const __global ", NULL, " *a, const __global ", NULL, " *b, const __global ", NULL, " *c )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = c[i] + a[i] * b[i];\n" + "}\n" + "\n" + "__kernel void kernel4( __global ", NULL, " *out, const __global ", NULL, " *a, const __global ", NULL, " *b, const __global ", NULL, " *c )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = c[i] - a[i] * b[i];\n" + "}\n" + "\n" + "__kernel void kernel5( __global ", NULL, " *out, const __global ", NULL, " *a, const __global ", NULL, " *b, const __global ", NULL, " *c )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = -(a[i] * b[i] + c[i]);\n" + "}\n" + "\n" + "__kernel void kernel6( __global ", NULL, " *out, const __global ", NULL, " *a, const __global ", NULL, " *b, const __global ", NULL, " *c )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = -(a[i] * b[i] - c[i]);\n" + "}\n" + "\n" + "__kernel void kernel7( __global ", NULL, " *out, const __global ", NULL, " *a, const __global ", NULL, " *b, const __global ", NULL, " *c )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = -(c[i] + a[i] * b[i]);\n" + "}\n" + "\n" + "__kernel void kernel8( __global ", NULL, " *out, const __global ", NULL, " *a, const __global ", NULL, " *b, const __global ", NULL, " *c )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = -(c[i] - a[i] * b[i]);\n" + "}\n" + "\n" }; + + for( i = 0; i < sizeof( sizeNames ) / sizeof( sizeNames[0] ); i++ ) + { + size_t strCount = sizeof( kernels ) / sizeof( kernels[0] ); + kernels[0] = ""; + + for( j = 2; j < strCount; j += 2 ) + kernels[j] = sizeNames[i]; + + error = create_single_kernel_helper_create_program(gContext, &gProgram[i], strCount, kernels); + if( NULL == gProgram[i] ) + { + vlog_error( "clCreateProgramWithSource failed\n" ); + return -5; + } + + if(( error = clBuildProgram(gProgram[i], 1, &gDevice, NULL, NULL, NULL) )) + { + vlog_error( "clBuildProgramExecutable failed\n" ); + char build_log[2048] = ""; + + clGetProgramBuildInfo(gProgram[i], gDevice, CL_PROGRAM_BUILD_LOG, sizeof(build_log), build_log, NULL); + vlog_error( "Log:\n%s\n", build_log ); + return -5; + } + } + + if( gHasDouble ) + { + kernels[0] = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"; + for( i = 0; i < sizeof( sizeNames_double ) / sizeof( sizeNames_double[0] ); i++ ) + { + size_t strCount = sizeof( kernels ) / sizeof( kernels[0] ); + + for( j = 2; j < strCount; j += 2 ) + kernels[j] = sizeNames_double[i]; + + error = create_single_kernel_helper_create_program(gContext, &gProgram_double[i], strCount, kernels); + if( NULL == gProgram_double[i] ) + { + vlog_error( "clCreateProgramWithSource failed\n" ); + return -5; + } + + if(( error = clBuildProgram(gProgram_double[i], 1, &gDevice, NULL, NULL, NULL) )) + { + vlog_error( "clBuildProgramExecutable failed\n" ); + char build_log[2048] = ""; + + clGetProgramBuildInfo(gProgram_double[i], gDevice, CL_PROGRAM_BUILD_LOG, sizeof(build_log), build_log, NULL); + vlog_error( "Log:\n%s\n", build_log ); + return -5; + } + } + } + + if( 0 == gSeedSpecified ) + { + time_t currentTime = time( NULL ); + struct tm *t = localtime(¤tTime); + gSeed = t->tm_sec + 60 * ( t->tm_min + 60 * (t->tm_hour + 24 * (t->tm_yday + 365 * t->tm_year))); + gSeed = (uint32_t) (((uint64_t) gSeed * (uint64_t) gSeed ) >> 16); + } + gMTdata = init_genrand( gSeed ); + + + // Init bufA and bufB + { + buf1 = (float *)malloc( BUFFER_SIZE ); + buf2 = (float *)malloc( BUFFER_SIZE ); + buf3 = (float *)malloc( BUFFER_SIZE ); + buf4 = (float *)malloc( BUFFER_SIZE ); + buf5 = (float *)malloc( BUFFER_SIZE ); + buf6 = (float *)malloc( BUFFER_SIZE ); + + bufSkip = (int *)malloc( BUFFER_SIZE ); + + if( NULL == buf1 || NULL == buf2 || NULL == buf3 || NULL == buf4 || NULL == buf5 || NULL == buf6 || NULL == bufSkip) + { + vlog_error( "Out of memory initializing buffers\n" ); + return -15; + } + for( i = 0; i < sizeof( correct ) / sizeof( correct[0] ); i++ ) + { + correct[i] = (float *)malloc( BUFFER_SIZE ); + skipTest[i] = (int *)malloc( BUFFER_SIZE ); + if(( NULL == correct[i] ) || ( NULL == skipTest[i])) + { + vlog_error( "Out of memory initializing buffers 2\n" ); + return -15; + } + } + + for( i = 0; i < BUFFER_SIZE / sizeof(float); i++ ) + ((uint32_t*) buf1)[i] = genrand_int32( gMTdata ); + + if( (error = clEnqueueWriteBuffer(gQueue, bufA, CL_FALSE, 0, BUFFER_SIZE, buf1, 0, NULL, NULL) )) + { + vlog_error( "Failure %d at clEnqueueWriteBuffer1\n", error ); + return error; + } + + for( i = 0; i < BUFFER_SIZE / sizeof(float); i++ ) + ((uint32_t*) buf2)[i] = genrand_int32( gMTdata ); + + if( (error = clEnqueueWriteBuffer(gQueue, bufB, CL_FALSE, 0, BUFFER_SIZE, buf2, 0, NULL, NULL) )) + { + vlog_error( "Failure %d at clEnqueueWriteBuffer2\n", error ); + return error; + } + + void *ftzInfo = NULL; + if( gForceFTZ ) + ftzInfo = FlushToZero(); + if ((CL_FP_ROUND_TO_ZERO == get_default_rounding_mode(gDevice)) && isEmbedded) { + oldRoundMode = set_round(kRoundTowardZero, kfloat); + isRTZ = 1; + } + float *f = (float*) buf1; + float *f2 = (float*) buf2; + float *f3 = (float*) buf3; + float *f4 = (float*) buf4; + for( i = 0; i < BUFFER_SIZE / sizeof(float); i++ ) + { + float q = f[i]; + float q2 = f2[i]; + + feclearexcept(FE_OVERFLOW); +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) + // VS2005 might use x87 for straight multiplies, and we can't + // turn that off + f3[i] = sse_mul(q, q2); + f4[i] = sse_mul(-q, q2); +#elif defined(__PPC__) + // None of the current generation PPC processors support HW + // FTZ, emulate it in sw. + f3[i] = ppc_mul(q, q2); + f4[i] = ppc_mul(-q, q2); +#else + f3[i] = q * q2; + f4[i] = -q * q2; +#endif + // Skip test if the device doesn't support infinities and NaN AND the result overflows + // or either input is an infinity of NaN + bufSkip[i] = (gSkipNanInf && ((FE_OVERFLOW == (FE_OVERFLOW & fetestexcept(FE_OVERFLOW))) || + (fabsf(q) == FLT_MAX) || (q != q) || + (fabsf(q2) == FLT_MAX) || (q2 != q2))); + } + + if( gForceFTZ ) + UnFlushToZero(ftzInfo); + + if (isRTZ) + (void)set_round(oldRoundMode, kfloat); + + + if( (error = clEnqueueWriteBuffer(gQueue, bufC, CL_FALSE, 0, BUFFER_SIZE, buf3, 0, NULL, NULL) )) + { + vlog_error( "Failure %d at clEnqueueWriteBuffer3\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, bufD, CL_FALSE, 0, BUFFER_SIZE, buf4, 0, NULL, NULL) )) + { + vlog_error( "Failure %d at clEnqueueWriteBuffer4\n", error ); + return error; + } + + // Fill the buffers with NaN + float *f5 = (float*) buf5; + float nan_val = nanf(""); + for( i = 0; i < BUFFER_SIZE / sizeof( float ); i++ ) + f5[i] = nan_val; + + // calculate reference results + for( i = 0; i < BUFFER_SIZE / sizeof( float ); i++ ) + { + for ( j=0; j<8; j++) + { + feclearexcept(FE_OVERFLOW); + switch (j) + { +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) + // VS2005 might use x87 for straight add/sub, and we can't + // turn that off + case 0: + correct[0][i] = sse_add(buf3[i],buf4[i]); break; + case 1: + correct[1][i] = sse_sub(buf3[i],buf3[i]); break; + case 2: + correct[2][i] = sse_add(buf4[i],buf3[i]); break; + case 3: + correct[3][i] = sse_sub(buf3[i],buf3[i]); break; + case 4: + correct[4][i] = -sse_add(buf3[i],buf4[i]); break; + case 5: + correct[5][i] = -sse_sub(buf3[i],buf3[i]); break; + case 6: + correct[6][i] = -sse_add(buf4[i],buf3[i]); break; + case 7: + correct[7][i] = -sse_sub(buf3[i],buf3[i]); break; +#else + case 0: + correct[0][i] = buf3[i] + buf4[i]; break; + case 1: + correct[1][i] = buf3[i] - buf3[i]; break; + case 2: + correct[2][i] = buf4[i] + buf3[i]; break; + case 3: + correct[3][i] = buf3[i] - buf3[i]; break; + case 4: + correct[4][i] = -(buf3[i] + buf4[i]); break; + case 5: + correct[5][i] = -(buf3[i] - buf3[i]); break; + case 6: + correct[6][i] = -(buf4[i] + buf3[i]); break; + case 7: + correct[7][i] = -(buf3[i] - buf3[i]); break; +#endif + } + // Further skip test inputs if the device doesn support infinities AND NaNs + // resulting sum overflows + skipTest[j][i] = (bufSkip[i] || + (gSkipNanInf && (FE_OVERFLOW == (FE_OVERFLOW & fetestexcept(FE_OVERFLOW))))); + +#if defined(__PPC__) + // Since the current Power processors don't emulate flush to zero in HW, + // it must be emulated in SW instead. + if (gForceFTZ) + { + if ((fabsf(correct[j][i]) < FLT_MIN) && (correct[j][i] != 0.0f)) + correct[j][i] = copysignf(0.0f, correct[j][i]); + } +#endif + } + } + if( gHasDouble ) + { + // Spec requires correct non-flushed results + // for doubles. We disable FTZ if this is default on + // the platform (like ARM) for reference result computation + // It is no-op if platform default is not FTZ (e.g. x86) + FPU_mode_type oldMode; + DisableFTZ( &oldMode ); + + buf3_double = (double *)malloc( BUFFER_SIZE ); + buf4_double = (double *)malloc( BUFFER_SIZE ); + buf5_double = (double *)malloc( BUFFER_SIZE ); + buf6_double = (double *)malloc( BUFFER_SIZE ); + if( NULL == buf3_double || NULL == buf4_double || NULL == buf5_double || NULL == buf6_double ) + { + vlog_error( "Out of memory initializing DP buffers\n" ); + return -15; + } + for( i = 0; i < sizeof( correct_double ) / sizeof( correct_double[0] ); i++ ) + { + correct_double[i] = (double *)malloc( BUFFER_SIZE ); + if( NULL == correct_double[i] ) + { + vlog_error( "Out of memory initializing DP buffers 2\n" ); + return -15; + } + } + + + double *f = (double*) buf1; + double *f2 = (double*) buf2; + double *f3 = (double*) buf3_double; + double *f4 = (double*) buf4_double; + for( i = 0; i < BUFFER_SIZE / sizeof(double); i++ ) + { + double q = f[i]; + double q2 = f2[i]; +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) + // VS2005 might use x87 for straight multiplies, and we can't + // turn that off + f3[i] = sse_mul_sd(q, q2); + f4[i] = sse_mul_sd(-q, q2); +#else + f3[i] = q * q2; + f4[i] = -q * q2; +#endif + } + + if( (error = clEnqueueWriteBuffer(gQueue, bufC_double, CL_FALSE, 0, BUFFER_SIZE, buf3_double, 0, NULL, NULL) )) + { + vlog_error( "Failure %d at clEnqueueWriteBuffer3\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, bufD_double, CL_FALSE, 0, BUFFER_SIZE, buf4_double, 0, NULL, NULL) )) + { + vlog_error( "Failure %d at clEnqueueWriteBuffer4\n", error ); + return error; + } + + // Fill the buffers with NaN + double *f5 = (double*) buf5_double; + double nan_val = nanf(""); + for( i = 0; i < BUFFER_SIZE / sizeof( double ); i++ ) + f5[i] = nan_val; + + // calculate reference results + for( i = 0; i < BUFFER_SIZE / sizeof( double ); i++ ) + { +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) + // VS2005 might use x87 for straight add/sub, and we can't + // turn that off + correct_double[0][i] = sse_add_sd(buf3_double[i],buf4_double[i]); + correct_double[1][i] = sse_sub_sd(buf3_double[i],buf3_double[i]); + correct_double[2][i] = sse_add_sd(buf4_double[i],buf3_double[i]); + correct_double[3][i] = sse_sub_sd(buf3_double[i],buf3_double[i]); + correct_double[4][i] = -sse_add_sd(buf3_double[i],buf4_double[i]); + correct_double[5][i] = -sse_sub_sd(buf3_double[i],buf3_double[i]); + correct_double[6][i] = -sse_add_sd(buf4_double[i],buf3_double[i]); + correct_double[7][i] = -sse_sub_sd(buf3_double[i],buf3_double[i]); +#else + correct_double[0][i] = buf3_double[i] + buf4_double[i]; + correct_double[1][i] = buf3_double[i] - buf3_double[i]; + correct_double[2][i] = buf4_double[i] + buf3_double[i]; + correct_double[3][i] = buf3_double[i] - buf3_double[i]; + correct_double[4][i] = -(buf3_double[i] + buf4_double[i]); + correct_double[5][i] = -(buf3_double[i] - buf3_double[i]); + correct_double[6][i] = -(buf4_double[i] + buf3_double[i]); + correct_double[7][i] = -(buf3_double[i] - buf3_double[i]); +#endif + } + + // Restore previous FP state since we modified it for + // reference result computation (see DisableFTZ call above) + RestoreFPState(&oldMode); + } + } + + char c[1000]; + static const char *no_yes[] = { "NO", "YES" }; + vlog( "\nCompute Device info:\n" ); + clGetDeviceInfo( gDevice, CL_DEVICE_NAME, sizeof(c), (void *)&c, NULL); + vlog( "\tDevice Name: %s\n", c ); + clGetDeviceInfo( gDevice, CL_DEVICE_VENDOR, sizeof(c), (void *)&c, NULL); + vlog( "\tVendor: %s\n", c ); + clGetDeviceInfo( gDevice, CL_DEVICE_VERSION, sizeof(c), (void *)&c, NULL); + vlog( "\tDevice Version: %s\n", c ); + clGetDeviceInfo( gDevice, CL_DEVICE_OPENCL_C_VERSION, sizeof(c), &c, NULL); + vlog( "\tCL C Version: %s\n", c ); + clGetDeviceInfo( gDevice, CL_DRIVER_VERSION, sizeof(c), (void *)&c, NULL); + vlog( "\tDriver Version: %s\n", c ); + vlog( "\tSubnormal values supported? %s\n", no_yes[0 != (CL_FP_DENORM & floatCapabilities)] ); + vlog( "\tTesting with FTZ mode ON? %s\n", no_yes[0 != gForceFTZ] ); + vlog( "\tTesting Doubles? %s\n", no_yes[0 != gHasDouble] ); + vlog( "\tRandom Number seed: 0x%8.8x\n", gSeed ); + vlog( "\n\n" ); + + return 0; +} + +static void ReleaseCL( void ) +{ + clReleaseMemObject(bufA); + clReleaseMemObject(bufB); + clReleaseMemObject(bufC); + clReleaseMemObject(bufD); + clReleaseMemObject(bufE); + clReleaseProgram(gProgram[0]); + clReleaseProgram(gProgram[1]); + clReleaseProgram(gProgram[2]); + clReleaseProgram(gProgram[3]); + clReleaseProgram(gProgram[4]); + if( gHasDouble ) + { + clReleaseMemObject(bufC_double); + clReleaseMemObject(bufD_double); + clReleaseProgram(gProgram_double[0]); + clReleaseProgram(gProgram_double[1]); + clReleaseProgram(gProgram_double[2]); + clReleaseProgram(gProgram_double[3]); + clReleaseProgram(gProgram_double[4]); + } + clReleaseCommandQueue(gQueue); + clReleaseContext(gContext); +} + + +static int RunTest( int testNumber ) +{ + size_t i; + int error = 0; + cl_mem args[4]; + float *c; + const char *kernelName[] = { "kernel1", "kernel2", "kernel3", "kernel4", + "kernel5", "kernel6", "kernel7", "kernel8" }; + switch( testNumber ) + { + case 0: args[0] = bufE; args[1] = bufA; args[2] = bufB; args[3] = bufD; c = buf4; break; // a * b + c + case 1: args[0] = bufE; args[1] = bufA; args[2] = bufB; args[3] = bufC; c = buf3; break; + case 2: args[0] = bufE; args[1] = bufA; args[2] = bufB; args[3] = bufD; c = buf4; break; + case 3: args[0] = bufE; args[1] = bufA; args[2] = bufB; args[3] = bufC; c = buf3; break; + case 4: args[0] = bufE; args[1] = bufA; args[2] = bufB; args[3] = bufD; c = buf4; break; + case 5: args[0] = bufE; args[1] = bufA; args[2] = bufB; args[3] = bufC; c = buf3; break; + case 6: args[0] = bufE; args[1] = bufA; args[2] = bufB; args[3] = bufD; c = buf4; break; + case 7: args[0] = bufE; args[1] = bufA; args[2] = bufB; args[3] = bufC; c = buf3; break; + default: + vlog_error( "Unknown test case %d passed to RunTest\n", testNumber ); + return -1; + } + + + int vectorSize; + for( vectorSize = 0; vectorSize < 5; vectorSize++ ) + { + cl_kernel k = clCreateKernel( gProgram[ vectorSize ], kernelName[ testNumber ], &error ); + if( NULL == k || error ) + { + vlog_error( "%d) Unable to find kernel \"%s\" for vector size: %d\n", error, kernelName[ testNumber ], 1 << vectorSize ); + return -2; + } + + // set the kernel args + for( i = 0; i < sizeof(args ) / sizeof( args[0]); i++ ) + if( (error = clSetKernelArg(k, i, sizeof( cl_mem ), args + i) )) + { + vlog_error( "Error %d setting kernel arg # %ld\n", error, i ); + return error; + } + + // write NaNs to the result array + if( (error = clEnqueueWriteBuffer(gQueue, bufE, CL_TRUE, 0, BUFFER_SIZE, buf5, 0, NULL, NULL) )) + { + vlog_error( "Failure %d at clWriteArray %d\n", error, testNumber ); + return error; + } + + // execute the kernel + size_t gDim[3] = { BUFFER_SIZE / (sizeof( cl_float ) * (1<gcc:-xc++ + msvc:"/TP" + ; + +exe test_conversions + : basic_test_conversions.c + Sleep.c + test_conversions.c + ; + +install dist + : test_conversions + : debug:$(DIST)/debug/tests/test_conformance/conversions + release:$(DIST)/release/tests/test_conformance/conversions + ; diff --git a/test_conformance/conversions/Makefile b/test_conformance/conversions/Makefile new file mode 100644 index 00000000..370224e3 --- /dev/null +++ b/test_conformance/conversions/Makefile @@ -0,0 +1,50 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +# We do not use dependencies in this Makefile + +SRCFILES = Sleep.c test_conversions.c ../../test_common/harness/mt19937.c ../../test_common/harness/ThreadPool.c ../../test_common/harness/rounding_mode.c + +CC = c++ + +CFLAGS = -g -Wall -Wshorten-64-to-32 $(COMPILERFLAGS) \ + ${RC_CFLAGS} ${USE_ATF} + +INCLUDES = -I../../test_common/harness \ + ${RC_CFLAGS} ${ATF} + +LIBRARIES = -framework OpenCL -framework CoreFoundation -framework IOKit + +release: + echo "Build Release" + $(CC) -c basic_test_conversions.c -Os $(CFLAGS) -o basic_test_conversions.o + $(CC) $(SRCFILES) -Os $(CFLAGS) basic_test_conversions.o -o test_conversions $(INCLUDES) $(LIBRARIES) + +debug: + echo "Build Debug" + $(CC) -c basic_test_conversions.c -O0 $(CFLAGS) -o basic_test_conversions.o + $(CC) test_conversions.c -c -O0 -g $(CFLAGS) $(INCLUDES) -o test_conversions.o + $(CC) Sleep.c -c -O0 -g $(CFLAGS) $(INCLUDES) -o Sleep.o + $(CC) ../../test_common/harness/mt19937.c -c -O0 -g $(INCLUDES) $(CFLAGS) -o mt19937.o + $(CC) ../../test_common/harness/ThreadPool.c -c -O0 -g $(INCLUDES) $(CFLAGS) -o ThreadPool.o + $(CC) ../../test_common/harness/rounding_mode.c -c -O0 -g $(INCLUDES) $(CFLAGS) -o rounding_mode.o + $(CC) *.o -g -O0 -o test_conversions_debug $(LIBRARIES) -arch i386 -arch x86_64 + +clean: + rm -f test_conversions + rm -f *.o + rm -f test_conversions_debug + +test: release + arch -i386 ./test_conversions -c > cpu.out & + arch -i386 ./test_conversions -g > gpu.out & + echo "Testing 32-bit mode conversions for CPU and GPU, which takes a day or three. Results may be found in cpu.out and gpu.out\n" + +test64: release + arch -x86_64 ./test_conversions_64 -c > cpu64.out & + arch -x86_64 ./test_conversions_64 -g > gpu64.out & + echo "Testing 64-bit mode conversions for CPU and GPU, which takes a day or three. Results may be found in cpu64.out and gpu64.out\n" + +all: release diff --git a/test_conformance/conversions/Sleep.c b/test_conformance/conversions/Sleep.c new file mode 100644 index 00000000..8ed6ef34 --- /dev/null +++ b/test_conformance/conversions/Sleep.c @@ -0,0 +1,120 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#if defined( __APPLE__ ) + + #include "Sleep.h" + #include + #include + #include "basic_test_conversions.h" + + #define UNUSED __attribute__((unused)) + + struct + { + io_connect_t connection; + IONotificationPortRef port; + io_object_t iterator; + }sleepInfo; + + void sleepCallback( void * refcon, + io_service_t service, + natural_t messageType, + void * messageArgument ); + + void sleepCallback( void * refcon UNUSED, + io_service_t service UNUSED, + natural_t messageType, + void * messageArgument ) + { + + IOReturn result; + /* + service -- The IOService whose state has changed. + messageType -- A messageType enum, defined by IOKit/IOMessage.h or by the IOService's family. + messageArgument -- An argument for the message, dependent on the messageType. + */ + switch ( messageType ) + { + case kIOMessageSystemWillSleep: + // Handle demand sleep (such as sleep caused by running out of + // batteries, closing the lid of a laptop, or selecting + // sleep from the Apple menu. + IOAllowPowerChange(sleepInfo.connection,(long)messageArgument); + vlog( "Hard sleep occurred.\n" ); + break; + case kIOMessageCanSystemSleep: + // In this case, the computer has been idle for several minutes + // and will sleep soon so you must either allow or cancel + // this notification. Important: if you don’t respond, there will + // be a 30-second timeout before the computer sleeps. + // IOCancelPowerChange(root_port,(long)messageArgument); + result = IOCancelPowerChange(sleepInfo.connection,(long)messageArgument); + if( kIOReturnSuccess != result ) + vlog( "sleep prevention failed. (%d)\n", result); + break; + case kIOMessageSystemHasPoweredOn: + // Handle wakeup. + break; + } + } + + void PreventSleep( void ) + { + vlog( "Disabling sleep... " ); + sleepInfo.iterator = (io_object_t) 0; + sleepInfo.port = NULL; + sleepInfo.connection = IORegisterForSystemPower + ( + &sleepInfo, //void * refcon, + &sleepInfo.port, //IONotificationPortRef * thePortRef, + sleepCallback, //IOServiceInterestCallback callback, + &sleepInfo.iterator //io_object_t * notifier + ); + + if( (io_connect_t) 0 == sleepInfo.connection ) + vlog( "failed.\n" ); + else + vlog( "done.\n" ); + + CFRunLoopAddSource(CFRunLoopGetCurrent(), + IONotificationPortGetRunLoopSource(sleepInfo.port), + kCFRunLoopDefaultMode); + } + + void ResumeSleep( void ) + { + IOReturn result = IODeregisterForSystemPower ( &sleepInfo.iterator ); + if( 0 != result ) + vlog( "Got error %d restoring sleep \n", result ); + else + vlog( "Sleep restored.\n" ); + } + +#else /* not __APPLE__ */ +#if defined(__cplusplus) +extern "C" { +#endif + + void PreventSleep( void ) {} + void ResumeSleep( void ) {} + +#if defined(__cplusplus) +} +#endif //__cplusplus + +#endif + + diff --git a/test_conformance/conversions/Sleep.h b/test_conformance/conversions/Sleep.h new file mode 100644 index 00000000..195e886f --- /dev/null +++ b/test_conformance/conversions/Sleep.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef SLEEP_H +#define SLEEP_H + +#if defined(__cplusplus) +extern "C" { +#endif + +void PreventSleep( void ); +void ResumeSleep( void ); + +#if defined(__cplusplus) +} +#endif //__cplusplus + +#endif /* SLEEP_H */ + + diff --git a/test_conformance/conversions/basic_test_conversions.c b/test_conformance/conversions/basic_test_conversions.c new file mode 100644 index 00000000..73f38633 --- /dev/null +++ b/test_conformance/conversions/basic_test_conversions.c @@ -0,0 +1,2246 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include "basic_test_conversions.h" +#include +#include + +#include "../../test_common/harness/mt19937.h" + +#if defined( __arm__ ) && defined( __GNUC__ ) +#include "fplib.h" +#endif + +#if defined( __arm__ ) && defined( __GNUC__ ) +/* Rounding modes and saturation for use with qcom 64 bit to float conversion library */ + bool qcom_sat; + roundingMode qcom_rm; +#endif + +static inline cl_ulong random64( MTdata d ); + +#if defined (_WIN32) + #include + #include +#else // !_WIN32 +#if defined (__SSE__ ) + #include +#endif +#if defined (__SSE2__ ) + #include +#endif +#endif // _WIN32 + +const char *gTypeNames[ kTypeCount ] = { + "uchar", "char", + "ushort", "short", + "uint", "int", + "float", "double", + "ulong", "long" + }; + +const char *gRoundingModeNames[ kRoundingModeCount ] = { + "", + "_rte", + "_rtp", + "_rtn", + "_rtz" + }; + +const char *gSaturationNames[ 2 ] = { "", "_sat" }; + +size_t gTypeSizes[ kTypeCount ] = { + sizeof( cl_uchar ), sizeof( cl_char ), + sizeof( cl_ushort ), sizeof( cl_short ), + sizeof( cl_uint ), sizeof( cl_int ), + sizeof( cl_float ), sizeof( cl_double ), + sizeof( cl_ulong ), sizeof( cl_long ), + }; + +long lrintf_clamped( float f ); +long lrintf_clamped( float f ) +{ + static const float magic[2] = { MAKE_HEX_FLOAT( 0x1.0p23f, 0x1, 23), - MAKE_HEX_FLOAT( 0x1.0p23f, 0x1, 23) }; + + if( f >= -(float) LONG_MIN ) + return LONG_MAX; + + if( f <= (float) LONG_MIN ) + return LONG_MIN; + + // Round fractional values to integer in round towards nearest mode + if( fabsf(f) < MAKE_HEX_FLOAT( 0x1.0p23f, 0x1, 23 ) ) + { + volatile float x = f; + float magicVal = magic[ f < 0 ]; + +#if defined( __SSE__ ) || defined (_WIN32) + // Defeat x87 based arithmetic, which cant do FTZ, and will round this incorrectly + __m128 v = _mm_set_ss( x ); + __m128 m = _mm_set_ss( magicVal ); + v = _mm_add_ss( v, m ); + v = _mm_sub_ss( v, m ); + _mm_store_ss( (float*) &x, v ); +#else + x += magicVal; + x -= magicVal; +#endif + f = x; + } + + return (long) f; +} + +long long llrintf_clamped( float f ); +long long llrintf_clamped( float f ) +{ + static const float magic[2] = { MAKE_HEX_FLOAT( 0x1.0p23f, 0x1, 23), - MAKE_HEX_FLOAT( 0x1.0p23f, 0x1, 23) }; + + if( f >= -(float) LLONG_MIN ) + return LLONG_MAX; + + if( f <= (float) LLONG_MIN ) + return LLONG_MIN; + + // Round fractional values to integer in round towards nearest mode + if( fabsf(f) < MAKE_HEX_FLOAT(0x1.0p23f, 0x1L, 23) ) + { + volatile float x = f; + float magicVal = magic[ f < 0 ]; +#if defined( __SSE__ ) || defined (_WIN32) + // Defeat x87 based arithmetic, which cant do FTZ, and will round this incorrectly + __m128 v = _mm_set_ss( x ); + __m128 m = _mm_set_ss( magicVal ); + v = _mm_add_ss( v, m ); + v = _mm_sub_ss( v, m ); + _mm_store_ss( (float*) &x, v ); +#else + x += magicVal; + x -= magicVal; +#endif + f = x; + } + + return (long long) f; +} + +long lrint_clamped( double f ); +long lrint_clamped( double f ) +{ + static const double magic[2] = { MAKE_HEX_DOUBLE(0x1.0p52, 0x1LL, 52), MAKE_HEX_DOUBLE(-0x1.0p52, -0x1LL, 52) }; + + if( sizeof( long ) > 4 ) + { + if( f >= -(double) LONG_MIN ) + return LONG_MAX; + } + else + { + if( f >= LONG_MAX ) + return LONG_MAX; + } + + if( f <= (double) LONG_MIN ) + return LONG_MIN; + + // Round fractional values to integer in round towards nearest mode + if( fabs(f) < MAKE_HEX_DOUBLE(0x1.0p52, 0x1LL, 52) ) + { + volatile double x = f; + double magicVal = magic[ f < 0 ]; +#if defined( __SSE2__ ) || defined (_MSC_VER) + // Defeat x87 based arithmetic, which cant do FTZ, and will round this incorrectly + __m128d v = _mm_set_sd( x ); + __m128d m = _mm_set_sd( magicVal ); + v = _mm_add_sd( v, m ); + v = _mm_sub_sd( v, m ); + _mm_store_sd( (double*) &x, v ); +#else + x += magicVal; + x -= magicVal; +#endif + f = x; + } + + return (long) f; +} + +long long llrint_clamped( double f ); +long long llrint_clamped( double f ) +{ + static const double magic[2] = { MAKE_HEX_DOUBLE(0x1.0p52, 0x1LL, 52), MAKE_HEX_DOUBLE(-0x1.0p52, -0x1LL, 52) }; + + if( f >= -(double) LLONG_MIN ) + return LLONG_MAX; + + if( f <= (double) LLONG_MIN ) + return LLONG_MIN; + + // Round fractional values to integer in round towards nearest mode + if( fabs(f) < MAKE_HEX_DOUBLE(0x1.0p52, 0x1LL, 52) ) + { + volatile double x = f; + double magicVal = magic[ f < 0 ]; +#if defined( __SSE2__ ) || defined (_MSC_VER) + // Defeat x87 based arithmetic, which cant do FTZ, and will round this incorrectly + __m128d v = _mm_set_sd( x ); + __m128d m = _mm_set_sd( magicVal ); + v = _mm_add_sd( v, m ); + v = _mm_sub_sd( v, m ); + _mm_store_sd( (double*) &x, v ); +#else + x += magicVal; + x -= magicVal; +#endif + f = x; + } + + return (long long) f; +} + + +/* + Names created as: + + #include + + const char *names[] = { "uchar", "char", "ushort", "short", "uint", "int", "float", "double", "ulong", "long" }; + + int main( void ) + { + + int i,j; + + for( i = 0; i < sizeof( names ) / sizeof( names[0] ); i++ ) + for( j = 0; j < sizeof( names ) / sizeof( names[0] ); j++ ) + { + if( j == i ) + continue; + + vlog( "void %s2%s( void *, void *);\n", names[i], names[j] ); + } + + + return 0; + } +*/ + +static float my_fabsf( float x ); +static double my_fabs( double x ); + + + +static void uchar2char( void *, void *); +static void uchar2ushort( void *, void *); +static void uchar2short( void *, void *); +static void uchar2uint( void *, void *); +static void uchar2int( void *, void *); +static void uchar2float( void *, void *); +static void uchar2double( void *, void *); +static void uchar2ulong( void *, void *); +static void uchar2long( void *, void *); +static void char2uchar( void *, void *); +static void char2ushort( void *, void *); +static void char2short( void *, void *); +static void char2uint( void *, void *); +static void char2int( void *, void *); +static void char2float( void *, void *); +static void char2double( void *, void *); +static void char2ulong( void *, void *); +static void char2long( void *, void *); +static void ushort2uchar( void *, void *); +static void ushort2char( void *, void *); +static void ushort2short( void *, void *); +static void ushort2uint( void *, void *); +static void ushort2int( void *, void *); +static void ushort2float( void *, void *); +static void ushort2double( void *, void *); +static void ushort2ulong( void *, void *); +static void ushort2long( void *, void *); +static void short2uchar( void *, void *); +static void short2char( void *, void *); +static void short2ushort( void *, void *); +static void short2uint( void *, void *); +static void short2int( void *, void *); +static void short2float( void *, void *); +static void short2double( void *, void *); +static void short2ulong( void *, void *); +static void short2long( void *, void *); +static void uint2uchar( void *, void *); +static void uint2char( void *, void *); +static void uint2ushort( void *, void *); +static void uint2short( void *, void *); +static void uint2int( void *, void *); +static void uint2float( void *, void *); +static void uint2double( void *, void *); +static void uint2ulong( void *, void *); +static void uint2long( void *, void *); +static void int2uchar( void *, void *); +static void int2char( void *, void *); +static void int2ushort( void *, void *); +static void int2short( void *, void *); +static void int2uint( void *, void *); +static void int2float( void *, void *); +static void int2double( void *, void *); +static void int2ulong( void *, void *); +static void int2long( void *, void *); +static void float2uchar( void *, void *); +static void float2char( void *, void *); +static void float2ushort( void *, void *); +static void float2short( void *, void *); +static void float2uint( void *, void *); +static void float2int( void *, void *); +static void float2double( void *, void *); +static void float2ulong( void *, void *); +static void float2long( void *, void *); +static void double2uchar( void *, void *); +static void double2char( void *, void *); +static void double2ushort( void *, void *); +static void double2short( void *, void *); +static void double2uint( void *, void *); +static void double2int( void *, void *); +static void double2float( void *, void *); +static void double2ulong( void *, void *); +static void double2long( void *, void *); +static void ulong2uchar( void *, void *); +static void ulong2char( void *, void *); +static void ulong2ushort( void *, void *); +static void ulong2short( void *, void *); +static void ulong2uint( void *, void *); +static void ulong2int( void *, void *); +static void ulong2float( void *, void *); +static void ulong2double( void *, void *); +static void ulong2long( void *, void *); +static void long2uchar( void *, void *); +static void long2char( void *, void *); +static void long2ushort( void *, void *); +static void long2short( void *, void *); +static void long2uint( void *, void *); +static void long2int( void *, void *); +static void long2float( void *, void *); +static void long2double( void *, void *); +static void long2ulong( void *, void *); + +/* + Conversion list created as + + #include + + const char *names[] = { "uchar", "char", "ushort", "short", "uint", "int", "float", "double", "ulong", "long" }; + + int main( void ) + { + + int i,j; + + for( i = 0; i < sizeof( names ) / sizeof( names[0] ); i++ ) + { + vlog( "{ " ); + for( j = 0; j < sizeof( names ) / sizeof( names[0] ); j++ ) + { + if( j == i ) + vlog( " NULL, " ); + else + { + char s[64]; + sprintf( s, "%s2%s,", names[j], names[i] ); + vlog( "%15s ", s ); + } + } + vlog( "},\n" ); + } + + return 0; + } + + */ +/* +Convert gConversions[kTypeCount][kTypeCount] = { +{ NULL, char2uchar, ushort2uchar, short2uchar, uint2uchar, int2uchar, float2uchar, double2uchar, ulong2uchar, long2uchar, }, +{ uchar2char, NULL, ushort2char, short2char, uint2char, int2char, float2char, double2char, ulong2char, long2char, }, +{ uchar2ushort, char2ushort, NULL, short2ushort, uint2ushort, int2ushort, float2ushort, double2ushort, ulong2ushort, long2ushort, }, +{ uchar2short, char2short, ushort2short, NULL, uint2short, int2short, float2short, double2short, ulong2short, long2short, }, +{ uchar2uint, char2uint, ushort2uint, short2uint, NULL, int2uint, float2uint, double2uint, ulong2uint, long2uint, }, +{ uchar2int, char2int, ushort2int, short2int, uint2int, NULL, float2int, double2int, ulong2int, long2int, }, +{ uchar2float, char2float, ushort2float, short2float, uint2float, int2float, NULL, double2float, ulong2float, long2float, }, +{ uchar2double, char2double, ushort2double, short2double, uint2double, int2double, float2double, NULL, ulong2double, long2double, }, +{ uchar2ulong, char2ulong, ushort2ulong, short2ulong, uint2ulong, int2ulong, float2ulong, double2ulong, NULL, long2ulong, }, +{ uchar2long, char2long, ushort2long, short2long, uint2long, int2long, float2long, double2long, ulong2long, NULL, } }; +*/ + +static void uchar2char_sat( void *, void *); +static void uchar2ushort_sat( void *, void *); +static void uchar2short_sat( void *, void *); +static void uchar2uint_sat( void *, void *); +static void uchar2int_sat( void *, void *); +static void uchar2float_sat( void *, void *); +static void uchar2double_sat( void *, void *); +static void uchar2ulong_sat( void *, void *); +static void uchar2long_sat( void *, void *); +static void char2uchar_sat( void *, void *); +static void char2ushort_sat( void *, void *); +static void char2short_sat( void *, void *); +static void char2uint_sat( void *, void *); +static void char2int_sat( void *, void *); +static void char2float_sat( void *, void *); +static void char2double_sat( void *, void *); +static void char2ulong_sat( void *, void *); +static void char2long_sat( void *, void *); +static void ushort2uchar_sat( void *, void *); +static void ushort2char_sat( void *, void *); +static void ushort2short_sat( void *, void *); +static void ushort2uint_sat( void *, void *); +static void ushort2int_sat( void *, void *); +static void ushort2float_sat( void *, void *); +static void ushort2double_sat( void *, void *); +static void ushort2ulong_sat( void *, void *); +static void ushort2long_sat( void *, void *); +static void short2uchar_sat( void *, void *); +static void short2char_sat( void *, void *); +static void short2ushort_sat( void *, void *); +static void short2uint_sat( void *, void *); +static void short2int_sat( void *, void *); +static void short2float_sat( void *, void *); +static void short2double_sat( void *, void *); +static void short2ulong_sat( void *, void *); +static void short2long_sat( void *, void *); +static void uint2uchar_sat( void *, void *); +static void uint2char_sat( void *, void *); +static void uint2ushort_sat( void *, void *); +static void uint2short_sat( void *, void *); +static void uint2int_sat( void *, void *); +static void uint2float_sat( void *, void *); +static void uint2double_sat( void *, void *); +static void uint2ulong_sat( void *, void *); +static void uint2long_sat( void *, void *); +static void int2uchar_sat( void *, void *); +static void int2char_sat( void *, void *); +static void int2ushort_sat( void *, void *); +static void int2short_sat( void *, void *); +static void int2uint_sat( void *, void *); +static void int2float_sat( void *, void *); +static void int2double_sat( void *, void *); +static void int2ulong_sat( void *, void *); +static void int2long_sat( void *, void *); +static void float2uchar_sat( void *, void *); +static void float2char_sat( void *, void *); +static void float2ushort_sat( void *, void *); +static void float2short_sat( void *, void *); +static void float2uint_sat( void *, void *); +static void float2int_sat( void *, void *); +static void float2double_sat( void *, void *); +static void float2ulong_sat( void *, void *); +static void float2long_sat( void *, void *); +static void double2uchar_sat( void *, void *); +static void double2char_sat( void *, void *); +static void double2ushort_sat( void *, void *); +static void double2short_sat( void *, void *); +static void double2uint_sat( void *, void *); +static void double2int_sat( void *, void *); +static void double2float_sat( void *, void *); +static void double2ulong_sat( void *, void *); +static void double2long_sat( void *, void *); +static void ulong2uchar_sat( void *, void *); +static void ulong2char_sat( void *, void *); +static void ulong2ushort_sat( void *, void *); +static void ulong2short_sat( void *, void *); +static void ulong2uint_sat( void *, void *); +static void ulong2int_sat( void *, void *); +static void ulong2float_sat( void *, void *); +static void ulong2double_sat( void *, void *); +static void ulong2long_sat( void *, void *); +static void long2uchar_sat( void *, void *); +static void long2char_sat( void *, void *); +static void long2ushort_sat( void *, void *); +static void long2short_sat( void *, void *); +static void long2uint_sat( void *, void *); +static void long2int_sat( void *, void *); +static void long2float_sat( void *, void *); +static void long2double_sat( void *, void *); +static void long2ulong_sat( void *, void *); +/* + #include + + const char *names[] = { "uchar", "char", "ushort", "short", "uint", "int", "float", "double", "ulong", "long" }; + + int main( void ) + { + + int i,j; + + for( i = 0; i < sizeof( names ) / sizeof( names[0] ); i++ ) + { + vlog( "{ " ); + for( j = 0; j < sizeof( names ) / sizeof( names[0] ); j++ ) + { + if( j == i ) + vlog( " NULL, " ); + else + { + char s[64]; + sprintf( s, "%s2%s_sat,", names[j], names[i] ); + vlog( "%18s ", s ); + } + } + vlog( "},\n" ); + } + + return 0; + } + +Convert gSaturatedConversions[kTypeCount][kTypeCount] = { +{ NULL, char2uchar_sat, ushort2uchar_sat, short2uchar_sat, uint2uchar_sat, int2uchar_sat, float2uchar_sat, double2uchar_sat, ulong2uchar_sat, long2uchar_sat, }, +{ uchar2char_sat, NULL, ushort2char_sat, short2char_sat, uint2char_sat, int2char_sat, float2char_sat, double2char_sat, ulong2char_sat, long2char_sat, }, +{ uchar2ushort_sat, char2ushort_sat, NULL, short2ushort_sat, uint2ushort_sat, int2ushort_sat, float2ushort_sat, double2ushort_sat, ulong2ushort_sat, long2ushort_sat, }, +{ uchar2short_sat, char2short_sat, ushort2short_sat, NULL, uint2short_sat, int2short_sat, float2short_sat, double2short_sat, ulong2short_sat, long2short_sat, }, +{ uchar2uint_sat, char2uint_sat, ushort2uint_sat, short2uint_sat, NULL, int2uint_sat, float2uint_sat, double2uint_sat, ulong2uint_sat, long2uint_sat, }, +{ uchar2int_sat, char2int_sat, ushort2int_sat, short2int_sat, uint2int_sat, NULL, float2int_sat, double2int_sat, ulong2int_sat, long2int_sat, }, +{ uchar2float_sat, char2float_sat, ushort2float_sat, short2float_sat, uint2float_sat, int2float_sat, NULL, double2float_sat, ulong2float_sat, long2float_sat, }, +{ uchar2double_sat, char2double_sat, ushort2double_sat, short2double_sat, uint2double_sat, int2double_sat, float2double_sat, NULL, ulong2double_sat, long2double_sat, }, +{ uchar2ulong_sat, char2ulong_sat, ushort2ulong_sat, short2ulong_sat, uint2ulong_sat, int2ulong_sat, float2ulong_sat, double2ulong_sat, NULL, long2ulong_sat, }, +{ uchar2long_sat, char2long_sat, ushort2long_sat, short2long_sat, uint2long_sat, int2long_sat, float2long_sat, double2long_sat, ulong2long_sat, NULL, } +}; +*/ + +/* + #include + + const char *names[] = { "uchar", "char", "ushort", "short", "uint", "int", "float", "double", "ulong", "long" }; + const char *types[] = { "uchar", "char", "ushort", "short", "uint", "int", "float", "double", "ulong", "llong" }; + + int main( void ) + { + + int i,j; + + for( i = 0; i < sizeof( names ) / sizeof( names[0] ); i++ ) + for( j = 0; j < sizeof( names ) / sizeof( names[0] ); j++ ) + { + if( j == i ) + continue; + + switch( i ) + { + case 6: //float + if( j == 7 ) + vlog( "void %s2%s( void *out, void *in){ ((%s*) out)[0] = (%s) ((%s*) in)[0]; }\n", names[i], names[i], names[j], types[j], types[i] ); + else + vlog( "void %s2%s( void *out, void *in){ ((%s*) out)[0] = (%s) my_rintf(((%s*) in)[0]); }\n", names[i], names[i], names[j], types[j], types[i] ); + break; + case 7: //double + if( j == 6 ) + vlog( "void %s2%s( void *out, void *in){ ((%s*) out)[0] = (%s) ((%s*) in)[0]; }\n", names[i], names[i], names[j], types[j], types[i] ); + else + vlog( "void %s2%s( void *out, void *in){ ((%s*) out)[0] = (%s) rint(((%s*) in)[0]); }\n", names[i], names[i], names[j], types[j], types[i] ); + break; + default: + vlog( "void %s2%s( void *out, void *in){ ((%s*) out)[0] = (%s) + ((%s*) in)[0]; }\n", names[i], names[i], names[j], types[j], types[i] ); + break; + } + } + + + return 0; + } +*/ + +float my_fabsf( float x ) +{ + union{ cl_uint u; float f; }u; + u.f = x; + u.u &= 0x7fffffff; + return u.f; +} + +double my_fabs( double x ) +{ + union{ cl_ulong u; double f; }u; + u.f = x; + u.u &= 0x7fffffffffffffffULL; + return u.f; +} + +static float my_rintf( float f ); +static float my_rintf( float f ) +{ + static const float magic[2] = { MAKE_HEX_FLOAT( 0x1.0p23f, 0x1, 23), - MAKE_HEX_FLOAT( 0x1.0p23f, 0x1, 23) }; + + // Round fractional values to integer in round towards nearest mode + if( fabsf(f) < MAKE_HEX_FLOAT( 0x1.0p23f, 0x1, 23 ) ) + { + volatile float x = f; + float magicVal = magic[ f < 0 ]; + +#if defined( __SSE__ ) + // Defeat x87 based arithmetic, which cant do FTZ, and will round this incorrectly + __m128 v = _mm_set_ss( x ); + __m128 m = _mm_set_ss( magicVal ); + v = _mm_add_ss( v, m ); + v = _mm_sub_ss( v, m ); + _mm_store_ss( (float*) &x, v ); +#else + x += magicVal; + x -= magicVal; +#endif + f = x; + } + + return f; +} + +static void uchar2char( void *out, void *in){ ((char*) out)[0] = ((cl_uchar*) in)[0]; } +static void uchar2ushort( void *out, void *in){ ((cl_ushort*) out)[0] = ((cl_uchar*) in)[0]; } +static void uchar2short( void *out, void *in){ ((short*) out)[0] = ((cl_uchar*) in)[0]; } +static void uchar2uint( void *out, void *in){ ((cl_uint*) out)[0] = ((cl_uchar*) in)[0]; } +static void uchar2int( void *out, void *in){ ((int*) out)[0] = ((cl_uchar*) in)[0]; } +static void uchar2float( void *out, void *in) +{ + cl_uchar l = ((cl_uchar*) in)[0]; + ((float*) out)[0] = (l == 0 ? 0.0f : (float) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +} +static void uchar2double( void *out, void *in) +{ + cl_uchar l = ((cl_uchar*) in)[0]; + ((double*) out)[0] = (l == 0 ? 0.0 : (double) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +} +static void uchar2ulong( void *out, void *in){ ((cl_ulong*) out)[0] = ((cl_uchar*) in)[0]; } +static void uchar2long( void *out, void *in){ ((cl_long*) out)[0] = ((cl_uchar*) in)[0]; } +static void char2uchar( void *out, void *in){ ((cl_uchar*) out)[0] = ((cl_char*) in)[0]; } +static void char2ushort( void *out, void *in){ ((cl_ushort*) out)[0] = ((cl_char*) in)[0]; } +static void char2short( void *out, void *in){ ((short*) out)[0] = ((cl_char*) in)[0]; } +static void char2uint( void *out, void *in){ ((cl_uint*) out)[0] = ((cl_char*) in)[0]; } +static void char2int( void *out, void *in){ ((int*) out)[0] = ((cl_char*) in)[0]; } +static void char2float( void *out, void *in) +{ + cl_char l = ((cl_char*) in)[0]; + ((float*) out)[0] = (l == 0 ? 0.0f : (float) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +} +static void char2double( void *out, void *in) +{ + cl_char l = ((cl_char*) in)[0]; + ((double*) out)[0] = (l == 0 ? 0.0 : (double) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +} +static void char2ulong( void *out, void *in){ ((cl_ulong*) out)[0] = ((cl_char*) in)[0]; } +static void char2long( void *out, void *in){ ((cl_long*) out)[0] = ((cl_char*) in)[0]; } +static void ushort2uchar( void *out, void *in){ ((cl_uchar*) out)[0] = ((cl_ushort*) in)[0]; } +static void ushort2char( void *out, void *in){ ((char*) out)[0] = ((cl_ushort*) in)[0]; } +static void ushort2short( void *out, void *in){ ((short*) out)[0] = ((cl_ushort*) in)[0]; } +static void ushort2uint( void *out, void *in){ ((cl_uint*) out)[0] = ((cl_ushort*) in)[0]; } +static void ushort2int( void *out, void *in){ ((int*) out)[0] = ((cl_ushort*) in)[0]; } +static void ushort2float( void *out, void *in) +{ + cl_ushort l = ((cl_ushort*) in)[0]; + ((float*) out)[0] = (l == 0 ? 0.0f : (float) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +} +static void ushort2double( void *out, void *in) +{ + cl_ushort l = ((cl_ushort*) in)[0]; + ((double*) out)[0] = (l == 0 ? 0.0 : (double) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +} +static void ushort2ulong( void *out, void *in){ ((cl_ulong*) out)[0] = ((cl_ushort*) in)[0]; } +static void ushort2long( void *out, void *in){ ((cl_long*) out)[0] = ((cl_ushort*) in)[0]; } +static void short2uchar( void *out, void *in){ ((cl_uchar*) out)[0] = ((cl_short*) in)[0]; } +static void short2char( void *out, void *in){ ((cl_char*) out)[0] = ((cl_short*) in)[0]; } +static void short2ushort( void *out, void *in){ ((cl_ushort*) out)[0] = ((cl_short*) in)[0]; } +static void short2uint( void *out, void *in){ ((cl_uint*) out)[0] = ((cl_short*) in)[0]; } +static void short2int( void *out, void *in){ ((cl_int*) out)[0] = ((cl_short*) in)[0]; } +static void short2float( void *out, void *in) +{ + cl_short l = ((cl_short*) in)[0]; + ((float*) out)[0] = (l == 0 ? 0.0f : (float) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +} +static void short2double( void *out, void *in) +{ + cl_short l = ((cl_short*) in)[0]; + ((double*) out)[0] = (l == 0 ? 0.0 : (double) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +} +static void short2ulong( void *out, void *in){ ((cl_ulong*) out)[0] = ((cl_short*) in)[0]; } +static void short2long( void *out, void *in){ ((cl_long*) out)[0] = ((cl_short*) in)[0]; } +static void uint2uchar( void *out, void *in){ ((cl_uchar*) out)[0] = ((cl_uint*) in)[0]; } +static void uint2char( void *out, void *in){ ((cl_char*) out)[0] = ((cl_uint*) in)[0]; } +static void uint2ushort( void *out, void *in){ ((cl_ushort*) out)[0] = ((cl_uint*) in)[0]; } +static void uint2short( void *out, void *in){ ((short*) out)[0] = ((cl_uint*) in)[0]; } +static void uint2int( void *out, void *in){ ((cl_int*) out)[0] = ((cl_uint*) in)[0]; } +static void uint2float( void *out, void *in) +{ + cl_uint l = ((cl_uint*) in)[0]; + ((float*) out)[0] = (l == 0 ? 0.0f : (float) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +} +static void uint2double( void *out, void *in) +{ + cl_uint l = ((cl_uint*) in)[0]; + ((double*) out)[0] = (l == 0 ? 0.0 : (double) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +} +static void uint2ulong( void *out, void *in){ ((cl_ulong*) out)[0] = ((cl_uint*) in)[0]; } +static void uint2long( void *out, void *in){ ((cl_long*) out)[0] = ((cl_uint*) in)[0]; } +static void int2uchar( void *out, void *in){ ((cl_uchar*) out)[0] = ((cl_int*) in)[0]; } +static void int2char( void *out, void *in){ ((cl_char*) out)[0] = ((cl_int*) in)[0]; } +static void int2ushort( void *out, void *in){ ((cl_ushort*) out)[0] = ((cl_int*) in)[0]; } +static void int2short( void *out, void *in){ ((cl_short*) out)[0] = ((cl_int*) in)[0]; } +static void int2uint( void *out, void *in){ ((cl_uint*) out)[0] = ((cl_int*) in)[0]; } +static void int2float( void *out, void *in) +{ + cl_int l = ((cl_int*) in)[0]; + ((float*) out)[0] = (l == 0 ? 0.0f : (float) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +} +static void int2double( void *out, void *in) +{ + cl_int l = ((cl_int*) in)[0]; + ((double*) out)[0] = (l == 0 ? 0.0 : (double) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +} +static void int2ulong( void *out, void *in){ ((cl_ulong*) out)[0] = ((cl_int*) in)[0]; } +static void int2long( void *out, void *in){ ((cl_long*) out)[0] = ((cl_int*) in)[0]; } +static void float2uchar( void *out, void *in){ ((cl_uchar*) out)[0] = my_rintf(((cl_float*) in)[0]); } +static void float2char( void *out, void *in){ ((cl_char*) out)[0] = my_rintf(((cl_float*) in)[0]); } +static void float2ushort( void *out, void *in){ ((cl_ushort*) out)[0] = my_rintf(((cl_float*) in)[0]); } +static void float2short( void *out, void *in){ ((cl_short*) out)[0] = my_rintf(((cl_float*) in)[0]); } +static void float2uint( void *out, void *in){ ((cl_uint*) out)[0] = my_rintf(((cl_float*) in)[0]); } +static void float2int( void *out, void *in){ ((cl_int*) out)[0] = my_rintf(((cl_float*) in)[0]); } +static void float2double( void *out, void *in){ ((cl_double*) out)[0] = ((cl_float*) in)[0]; } +static void float2ulong( void *out, void *in) +{ +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) + // VS2005 (at least) on x86 uses fistp to store the float as a 64-bit int. + // However, fistp stores it as a signed int, and some of the test values won't + // fit into a signed int. (These test values are >= 2^63.) The result on VS2005 + // is that these end up silently (at least by default settings) clamped to + // the max lowest ulong. + cl_float x = my_rintf(((cl_float *)in)[0]); + if (x >= 9223372036854775808.0f) { + x -= 9223372036854775808.0f; + ((cl_ulong*) out)[0] = x; + ((cl_ulong*) out)[0] += 9223372036854775808ULL; + } else { + ((cl_ulong*) out)[0] = x; + } +#else + ((cl_ulong*) out)[0] = my_rintf(((cl_float*) in)[0]); +#endif +} + +static void float2long( void *out, void *in){ ((cl_long*) out)[0] = llrint_clamped( ((cl_float*) in)[0] ); } +static void double2uchar( void *out, void *in){ ((cl_uchar*) out)[0] = rint(((cl_double*) in)[0]); } +static void double2char( void *out, void *in){ ((cl_char*) out)[0] = rint(((cl_double*) in)[0]); } +static void double2ushort( void *out, void *in){ ((cl_ushort*) out)[0] = rint(((cl_double*) in)[0]); } +static void double2short( void *out, void *in){ ((cl_short*) out)[0] = rint(((cl_double*) in)[0]); } +static void double2uint( void *out, void *in){ ((cl_uint*) out)[0] = (cl_uint) rint(((cl_double*) in)[0]); } +static void double2int( void *out, void *in){ ((cl_int*) out)[0] = (int) rint(((cl_double*) in)[0]); } +static void double2float( void *out, void *in){ ((cl_float*) out)[0] = (float) ((cl_double*) in)[0]; } +static void double2ulong( void *out, void *in){ ((cl_ulong*) out)[0] = (cl_ulong) rint(((cl_double*) in)[0]); } +static void double2long( void *out, void *in){ ((cl_long*) out)[0] = (cl_long) rint(((cl_double*) in)[0]); } +static void ulong2uchar( void *out, void *in){ ((cl_uchar*) out)[0] = (cl_uchar) ((cl_ulong*) in)[0]; } +static void ulong2char( void *out, void *in){ ((cl_char*) out)[0] = (cl_char) ((cl_ulong*) in)[0]; } +static void ulong2ushort( void *out, void *in){ ((cl_ushort*) out)[0] = (cl_ushort) ((cl_ulong*) in)[0]; } +static void ulong2short( void *out, void *in){ ((cl_short*) out)[0] = (cl_short)((cl_ulong*) in)[0]; } +static void ulong2uint( void *out, void *in){ ((cl_uint*) out)[0] = (cl_uint) ((cl_ulong*) in)[0]; } +static void ulong2int( void *out, void *in){ ((cl_int*) out)[0] = (cl_int) ((cl_ulong*) in)[0]; } +static void ulong2float( void *out, void *in) +{ +#if defined(_MSC_VER) + cl_ulong l = ((cl_ulong*) in)[0]; + float result; + + cl_long sl = ((cl_long)l < 0) ? (cl_long)((l >> 1) | (l & 1)) : (cl_long)l; +#if defined(_M_X64) + _mm_store_ss(&result, _mm_cvtsi64_ss(_mm_setzero_ps(), sl)); +#else + result = sl; +#endif + ((float*) out)[0] = (l == 0 ? 0.0f : (((cl_long)l < 0) ? result * 2.0f : result)); +#else + cl_ulong l = ((cl_ulong*) in)[0]; +#if defined( __arm__ ) && defined( __GNUC__ ) + /* ARM VFP doesn't have hardware instruction for converting from 64-bit integer to float types, hence GCC ARM uses the floating-point emulation code + * despite which -mfloat-abi setting it is. But the emulation code in libgcc.a has only one rounding mode (round to nearest even in this case) + * and ignores the user rounding mode setting in hardware. + * As a result setting rounding modes in hardware won't give correct rounding results for type covert from 64-bit integer to float using GCC for ARM compiler + * so for testing different rounding modes, we need to use alternative reference function */ + ((float*) out)[0] = qcom_u64_2_f32(l, qcom_sat, qcom_rm); +#else + ((float*) out)[0] = (l == 0 ? 0.0f : (float) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +#endif +#endif +} +static void ulong2double( void *out, void *in) +{ +#if defined(_MSC_VER) + cl_ulong l = ((cl_ulong*) in)[0]; + double result; + + cl_long sl = ((cl_long)l < 0) ? (cl_long)((l >> 1) | (l & 1)) : (cl_long)l; +#if defined(_M_X64) + _mm_store_sd(&result, _mm_cvtsi64_sd(_mm_setzero_pd(), sl)); +#else + result = sl; +#endif + ((double*) out)[0] = (l == 0 ? 0.0 : (((cl_long)l < 0) ? result * 2.0 : result)); +#else + cl_ulong l = ((cl_ulong*) in)[0]; + ((double*) out)[0] = (l == 0 ? 0.0 : (double) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +#endif +} +static void ulong2long( void *out, void *in){ ((cl_long*) out)[0] = ((cl_ulong*) in)[0]; } +static void long2uchar( void *out, void *in){ ((cl_uchar*) out)[0] = (cl_uchar) ((cl_long*) in)[0]; } +static void long2char( void *out, void *in){ ((cl_char*) out)[0] = (cl_char) ((cl_long*) in)[0]; } +static void long2ushort( void *out, void *in){ ((cl_ushort*) out)[0] = (cl_ushort) ((cl_long*) in)[0]; } +static void long2short( void *out, void *in){ ((cl_short*) out)[0] = (cl_short) ((cl_long*) in)[0]; } +static void long2uint( void *out, void *in){ ((cl_uint*) out)[0] = (cl_uint) ((cl_long*) in)[0]; } +static void long2int( void *out, void *in){ ((cl_int*) out)[0] = (cl_int) ((cl_long*) in)[0]; } +static void long2float( void *out, void *in) +{ +#if defined(_MSC_VER) && defined(_M_X64) + cl_long l = ((cl_long*) in)[0]; + float result; + + _mm_store_ss(&result, _mm_cvtsi64_ss(_mm_setzero_ps(), l)); + ((float*) out)[0] = (l == 0 ? 0.0f : result); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +#else + cl_long l = ((cl_long*) in)[0]; +#if defined( __arm__ ) && defined( __GNUC__ ) + /* ARM VFP doesn't have hardware instruction for converting from 64-bit integer to float types, hence GCC ARM uses the floating-point emulation code + * despite which -mfloat-abi setting it is. But the emulation code in libgcc.a has only one rounding mode (round to nearest even in this case) + * and ignores the user rounding mode setting in hardware. + * As a result setting rounding modes in hardware won't give correct rounding results for type covert from 64-bit integer to float using GCC for ARM compiler + * so for testing different rounding modes, we need to use alternative reference function */ + ((float*) out)[0] = (l == 0 ? 0.0f : qcom_s64_2_f32(l, qcom_sat, qcom_rm)); +#else + ((float*) out)[0] = (l == 0 ? 0.0f : (float) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +#endif +#endif +} +static void long2double( void *out, void *in) +{ +#if defined(_MSC_VER) && defined(_M_X64) + cl_long l = ((cl_long*) in)[0]; + double result; + + _mm_store_sd(&result, _mm_cvtsi64_sd(_mm_setzero_pd(), l)); + ((double*) out)[0] = (l == 0 ? 0.0 : result); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +#else + cl_long l = ((cl_long*) in)[0]; + ((double*) out)[0] = (l == 0 ? 0.0 : (double) l); // Per IEEE-754-2008 5.4.1, 0's always convert to +0.0 +#endif +} +static void long2ulong( void *out, void *in){ ((cl_ulong*) out)[0] = ((cl_long*) in)[0]; } + +#define CLAMP( _lo, _x, _hi ) ( (_x) < (_lo) ? (_lo) : ((_x) > (_hi) ? (_hi) : (_x))) + +// Done by hand +static void uchar2char_sat( void *out, void *in){ cl_uchar c = ((cl_uchar*) in)[0]; ((cl_char*) out)[0] = c > 0x7f ? 0x7f : c; } +static void uchar2ushort_sat( void *out, void *in){ ((cl_ushort*) out)[0] = ((cl_uchar*) in)[0]; } +static void uchar2short_sat( void *out, void *in){ ((cl_short*) out)[0] = ((cl_uchar*) in)[0]; } +static void uchar2uint_sat( void *out, void *in){ ((cl_uint*) out)[0] = ((cl_uchar*) in)[0]; } +static void uchar2int_sat( void *out, void *in){ ((cl_int*) out)[0] = ((cl_uchar*) in)[0]; } +static void uchar2float_sat( void *out, void *in){ ((cl_float*) out)[0] = my_fabsf( (cl_float) ((cl_uchar*) in)[0]); } // my_fabs workaround for +static void uchar2double_sat( void *out, void *in){ ((cl_double*) out)[0] = my_fabs( (cl_double) ((cl_uchar*) in)[0]); } // my_fabs workaround for +static void uchar2ulong_sat( void *out, void *in){ ((cl_ulong*) out)[0] = ((cl_uchar*) in)[0]; } +static void uchar2long_sat( void *out, void *in){ ((cl_long*) out)[0] = ((cl_uchar*) in)[0]; } +static void char2uchar_sat( void *out, void *in){ cl_char c = ((cl_char*) in)[0]; ((cl_uchar*) out)[0] = c < 0 ? 0 : c; } +static void char2ushort_sat( void *out, void *in){ cl_char c = ((cl_char*) in)[0]; ((cl_ushort*) out)[0] = c < 0 ? 0 : c; } +static void char2short_sat( void *out, void *in){ ((cl_short*) out)[0] = ((cl_char*) in)[0]; } +static void char2uint_sat( void *out, void *in){ cl_char c = ((cl_char*) in)[0]; ((cl_uint*) out)[0] = c < 0 ? 0 : c; } +static void char2int_sat( void *out, void *in){ ((cl_int*) out)[0] = ((cl_char*) in)[0]; } +static void char2float_sat( void *out, void *in){ ((cl_float*) out)[0] = ((cl_char*) in)[0]; } +static void char2double_sat( void *out, void *in){ ((cl_double*) out)[0] = ((cl_char*) in)[0]; } +static void char2ulong_sat( void *out, void *in){ cl_char c = ((cl_char*) in)[0]; ((cl_ulong*) out)[0] = c < 0 ? 0 : c; } +static void char2long_sat( void *out, void *in){ ((cl_long*) out)[0] = ((cl_char*) in)[0]; } +static void ushort2uchar_sat( void *out, void *in){ cl_ushort u = ((cl_ushort*) in)[0]; ((cl_uchar*) out)[0] = u > 0xff ? 0xFF : u; } +static void ushort2char_sat( void *out, void *in){ cl_ushort u = ((cl_ushort*) in)[0]; ((cl_char*) out)[0] = u > 0x7f ? 0x7F : u; } +static void ushort2short_sat( void *out, void *in){ cl_ushort u = ((cl_ushort*) in)[0]; ((cl_short*) out)[0] = u > 0x7fff ? 0x7fFF : u; } +static void ushort2uint_sat( void *out, void *in){ ((cl_uint*) out)[0] = ((cl_ushort*) in)[0]; } +static void ushort2int_sat( void *out, void *in){ ((cl_int*) out)[0] = ((cl_ushort*) in)[0]; } +static void ushort2float_sat( void *out, void *in){ ((cl_float*) out)[0] = my_fabsf((cl_float)((cl_ushort*) in)[0]); } // my_fabs workaround for +static void ushort2double_sat( void *out, void *in){ ((cl_double*) out)[0] = my_fabs( (cl_double) ((cl_ushort*) in)[0]); } // my_fabs workaround for +static void ushort2ulong_sat( void *out, void *in){ ((cl_ulong*) out)[0] = ((cl_ushort*) in)[0]; } +static void ushort2long_sat( void *out, void *in){ ((cl_long*) out)[0] = ((cl_ushort*) in)[0]; } +static void short2uchar_sat( void *out, void *in){ cl_short s = ((cl_short*) in)[0]; ((cl_uchar*) out)[0] = CLAMP( 0, s, CL_UCHAR_MAX ); } +static void short2char_sat( void *out, void *in){ cl_short s = ((cl_short*) in)[0]; ((cl_char*) out)[0] = CLAMP( CL_CHAR_MIN, s, CL_CHAR_MAX ); } +static void short2ushort_sat( void *out, void *in){ cl_short s = ((cl_short*) in)[0]; ((cl_ushort*) out)[0] = s < 0 ? 0 : s; } +static void short2uint_sat( void *out, void *in){ cl_short s = ((cl_short*) in)[0]; ((cl_uint*) out)[0] = s < 0 ? 0 : s; } +static void short2int_sat( void *out, void *in){ ((cl_int*) out)[0] = ((cl_short*) in)[0]; } +static void short2float_sat( void *out, void *in){ ((cl_float*) out)[0] = ((cl_short*) in)[0]; } +static void short2double_sat( void *out, void *in){ ((cl_double*) out)[0] = ((cl_short*) in)[0]; } +static void short2ulong_sat( void *out, void *in){ cl_short s = ((cl_short*) in)[0]; ((cl_ulong*) out)[0] = s < 0 ? 0 : s; } +static void short2long_sat( void *out, void *in){ ((cl_long*) out)[0] = ((cl_short*) in)[0]; } +static void uint2uchar_sat( void *out, void *in){ cl_uint u = ((cl_uint*) in)[0]; ((cl_uchar*) out)[0] = CLAMP( 0, u, CL_UCHAR_MAX); } +static void uint2char_sat( void *out, void *in){ cl_uint u = ((cl_uint*) in)[0]; ((cl_char*) out)[0] = CLAMP( 0, u, CL_CHAR_MAX ); } +static void uint2ushort_sat( void *out, void *in){ cl_uint u = ((cl_uint*) in)[0]; ((cl_ushort*) out)[0] = CLAMP( 0, u, CL_USHRT_MAX); } +static void uint2short_sat( void *out, void *in){ cl_uint u = ((cl_uint*) in)[0]; ((cl_short*) out)[0] = CLAMP( 0, u, CL_SHRT_MAX); } +static void uint2int_sat( void *out, void *in){ cl_uint u = ((cl_uint*) in)[0]; ((cl_int*) out)[0] = CLAMP( 0, u, CL_INT_MAX); } +static void uint2float_sat( void *out, void *in){ ((cl_float*) out)[0] = my_fabsf( (cl_float) ((cl_uint*) in)[0] ); } // my_fabs workaround for +static void uint2double_sat( void *out, void *in){ ((cl_double*) out)[0] = my_fabs( (cl_double) ((cl_uint*) in)[0]); } // my_fabs workaround for +static void uint2ulong_sat( void *out, void *in){ ((cl_ulong*) out)[0] = ((cl_uint*) in)[0]; } +static void uint2long_sat( void *out, void *in){ ((cl_long*) out)[0] = ((cl_uint*) in)[0]; } +static void int2uchar_sat( void *out, void *in){ cl_int i = ((cl_int*) in)[0]; ((cl_uchar*) out)[0] = CLAMP( 0, i, CL_UCHAR_MAX); } +static void int2char_sat( void *out, void *in){ cl_int i = ((cl_int*) in)[0]; ((cl_char*) out)[0] = CLAMP( CL_CHAR_MIN, i, CL_CHAR_MAX); } +static void int2ushort_sat( void *out, void *in){ cl_int i = ((cl_int*) in)[0]; ((cl_ushort*) out)[0] = CLAMP( 0, i, CL_USHRT_MAX); } +static void int2short_sat( void *out, void *in){ cl_int i = ((cl_int*) in)[0]; ((cl_short*) out)[0] = CLAMP( CL_SHRT_MIN, i, CL_SHRT_MAX); } +static void int2uint_sat( void *out, void *in){ cl_int i = ((cl_int*) in)[0]; ((cl_uint*) out)[0] = CLAMP( 0, i, CL_INT_MAX); } +static void int2float_sat( void *out, void *in){ ((cl_float*) out)[0] = ((cl_int*) in)[0]; } +static void int2double_sat( void *out, void *in){ ((cl_double*) out)[0] = ((cl_int*) in)[0]; } +static void int2ulong_sat( void *out, void *in){ cl_int i = ((cl_int*) in)[0]; ((cl_ulong*) out)[0] = i < 0 ? 0 : i; } +static void int2long_sat( void *out, void *in){ ((cl_long*) out)[0] = ((cl_int*) in)[0]; } +static void float2uchar_sat( void *out, void *in){ ((cl_uchar*) out)[0] = CLAMP( 0, lrintf_clamped(((cl_float*) in)[0]), CL_UCHAR_MAX ); } +static void float2char_sat( void *out, void *in){ ((cl_char*) out)[0] = CLAMP( CL_CHAR_MIN, lrintf_clamped(((cl_float*) in)[0]), CL_CHAR_MAX); } +static void float2ushort_sat( void *out, void *in){ ((cl_ushort*) out)[0] = CLAMP( 0, lrintf_clamped(((cl_float*) in)[0]), CL_USHRT_MAX ); } +static void float2short_sat( void *out, void *in){ ((cl_short*) out)[0] = CLAMP( CL_SHRT_MIN, lrintf_clamped(((cl_float*) in)[0]), CL_SHRT_MAX ); } +static void float2uint_sat( void *out, void *in){ ((cl_uint*) out)[0] = (cl_uint) CLAMP( 0, llrintf_clamped(((cl_float*) in)[0]), CL_UINT_MAX ); } +static void float2int_sat( void *out, void *in){ ((cl_int*) out)[0] = (cl_int) CLAMP( CL_INT_MIN, lrintf_clamped(((cl_float*) in)[0]), CL_INT_MAX ); } +static void float2double_sat( void *out, void *in){ ((cl_double*) out)[0] = ((cl_float*) in)[0]; } +static void float2ulong_sat( void *out, void *in) +{ +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) + // VS2005 (at least) on x86 uses fistp to store the float as a 64-bit int. + // However, fistp stores it as a signed int, and some of the test values won't + // fit into a signed int. (These test values are >= 2^63.) The result on VS2005 + // is that these end up silently (at least by default settings) clamped to + // the max lowest ulong. + cl_float x = my_rintf(((cl_float *)in)[0]); + if (x >= 18446744073709551616.0f) { // 2^64 + ((cl_ulong*) out)[0] = 0xFFFFFFFFFFFFFFFFULL; + } else if (x < 0) { + ((cl_ulong*) out)[0] = 0; + } else if (x >= 9223372036854775808.0f) { // 2^63 + x -= 9223372036854775808.0f; + ((cl_ulong*) out)[0] = x; + ((cl_ulong*) out)[0] += 9223372036854775808ULL; + } else { + ((cl_ulong*) out)[0] = x; + } +#else + float f = my_rintf(((float*) in)[0]); ((cl_ulong*) out)[0] = f >= MAKE_HEX_DOUBLE(0x1.0p64, 0x1LL, 64) ? 0xFFFFFFFFFFFFFFFFULL : f < 0 ? 0 : (cl_ulong) f; +#endif +} +// The final cast used to be (cl_ulong) f, but on Linux (RHEL5 at least) +// if f = -1.0f, then (cl_ulong) f = 0xffffffff, which clearly isn't right. +// Switching it to (cl_long) f seems to fix that. +static void float2long_sat( void *out, void *in){ float f = my_rintf(((float*) in)[0]); ((cl_long*) out)[0] = f >= MAKE_HEX_DOUBLE(0x1.0p63, 0x1LL, 63) ? 0x7FFFFFFFFFFFFFFFULL : f < MAKE_HEX_DOUBLE(-0x1.0p63, -0x1LL, 63) ? 0x8000000000000000LL : (cl_long) f; } +static void double2uchar_sat( void *out, void *in){ ((cl_uchar*) out)[0] = CLAMP( 0, lrint_clamped(((cl_double*) in)[0]), CL_UCHAR_MAX ); } +static void double2char_sat( void *out, void *in){ ((cl_char*) out)[0] = CLAMP( CL_CHAR_MIN, lrint_clamped(((cl_double*) in)[0]), CL_CHAR_MAX); } +static void double2ushort_sat( void *out, void *in){ ((cl_ushort*) out)[0] = CLAMP( 0, lrint_clamped(((cl_double*) in)[0]), CL_USHRT_MAX ); } +static void double2short_sat( void *out, void *in){ ((cl_short*) out)[0] = CLAMP( CL_SHRT_MIN, lrint_clamped(((cl_double*) in)[0]), CL_SHRT_MAX ); } +static void double2uint_sat( void *out, void *in){ ((cl_uint*) out)[0] = (cl_uint) CLAMP( 0, llrint_clamped(((cl_double*) in)[0]), CL_UINT_MAX ); } +static void double2int_sat( void *out, void *in){ ((cl_int*) out)[0] = (cl_int) CLAMP( CL_INT_MIN, lrint_clamped(((cl_double*) in)[0]), CL_INT_MAX ); } +static void double2float_sat( void *out, void *in){ ((cl_float*) out)[0] = (cl_float) ((double*) in)[0]; } +static void double2ulong_sat( void *out, void *in){ double f = rint(((double*) in)[0]); ((cl_ulong*) out)[0] = f >= MAKE_HEX_DOUBLE(0x1.0p64, 0x1LL, 64) ? 0xFFFFFFFFFFFFFFFFULL : f < 0 ? 0 : (cl_ulong) f; } +static void double2long_sat( void *out, void *in){ double f = rint(((double*) in)[0]); ((cl_long*) out)[0] = f >= MAKE_HEX_DOUBLE(0x1.0p63, 0x1LL, 63) ? 0x7FFFFFFFFFFFFFFFULL : f < MAKE_HEX_DOUBLE(-0x1.0p63, -0x1LL, 63) ? 0x8000000000000000LL : (cl_long) f; } +static void ulong2uchar_sat( void *out, void *in){ cl_ulong u = ((cl_ulong*) in)[0]; ((cl_uchar*) out)[0] = CLAMP( 0, u, CL_UCHAR_MAX ); } +static void ulong2char_sat( void *out, void *in){ cl_ulong u = ((cl_ulong*) in)[0]; ((cl_char*) out)[0] = CLAMP( 0, u, CL_CHAR_MAX ); } +static void ulong2ushort_sat( void *out, void *in){ cl_ulong u = ((cl_ulong*) in)[0]; ((cl_ushort*) out)[0] = CLAMP( 0, u, CL_USHRT_MAX ); } +static void ulong2short_sat( void *out, void *in){ cl_ulong u = ((cl_ulong*) in)[0]; ((cl_short*) out)[0] = CLAMP( 0, u, CL_SHRT_MAX ); } +static void ulong2uint_sat( void *out, void *in){ cl_ulong u = ((cl_ulong*) in)[0]; ((cl_uint*) out)[0] = (cl_uint) CLAMP( 0, u, CL_UINT_MAX ); } +static void ulong2int_sat( void *out, void *in){ cl_ulong u = ((cl_ulong*) in)[0]; ((cl_int*) out)[0] = (cl_int) CLAMP( 0, u, CL_INT_MAX ); } +static void ulong2float_sat( void *out, void *in){ ((float*) out)[0] = my_fabsf((float) ((cl_ulong*) in)[0]); } // my_fabs workaround for +static void ulong2double_sat( void *out, void *in){ ((double*) out)[0] = my_fabs( ((cl_ulong*) in)[0]); } // my_fabs workaround for +static void ulong2long_sat( void *out, void *in){ cl_ulong u = ((cl_ulong*) in)[0]; ((cl_long*) out)[0] = CLAMP( 0, u, CL_LONG_MAX ); } +static void long2uchar_sat( void *out, void *in){ cl_long u = ((cl_long*) in)[0]; ((cl_uchar*) out)[0] = CLAMP( 0, u, CL_UCHAR_MAX ); } +static void long2char_sat( void *out, void *in){ cl_long u = ((cl_long*) in)[0]; ((cl_char*) out)[0] = CLAMP( CL_CHAR_MIN, u, CL_CHAR_MAX ); } +static void long2ushort_sat( void *out, void *in){ cl_long u = ((cl_long*) in)[0]; ((cl_ushort*) out)[0] = CLAMP( 0, u, CL_USHRT_MAX ); } +static void long2short_sat( void *out, void *in){ cl_long u = ((cl_long*) in)[0]; ((cl_short*) out)[0] = CLAMP( CL_SHRT_MIN, u, CL_SHRT_MAX ); } +static void long2uint_sat( void *out, void *in){ cl_long u = ((cl_long*) in)[0]; ((cl_uint*) out)[0] = (cl_uint) CLAMP( 0, u, CL_UINT_MAX ); } +static void long2int_sat( void *out, void *in){ cl_long u = ((cl_long*) in)[0]; ((cl_int*) out)[0] = (int) CLAMP( CL_INT_MIN, u, CL_INT_MAX ); } +static void long2float_sat( void *out, void *in){ ((float*) out)[0] = (float) ((cl_long*) in)[0]; } +static void long2double_sat( void *out, void *in){ ((double*) out)[0] = ((cl_long*) in)[0]; } +static void long2ulong_sat( void *out, void *in){ cl_long u = ((cl_long*) in)[0]; ((cl_ulong*) out)[0] = CLAMP( 0, u, CL_LONG_MAX ); } + +/* +#include + +char *ground[] = { "", + "_rte", + "_rtp", + "_rtn", + "_rtz" + }; + +const char *gTypeNames[ ] = { + "uchar", "char", + "ushort", "short", + "uint", "int", + "float", "double", + "ulong", "long" + }; + + +int main( void ) +{ + int i, j; + + for( i = 0; i < sizeof( gTypeNames ) / sizeof( gTypeNames[0] ); i++ ) + for( j = 0; j < sizeof( ground ) / sizeof( ground[0] ); j++ ) + { + vlog( "float clampf_%s%s( float );\n", gTypeNames[i], ground[j] ); + vlog( "double clampd_%s%s( double );\n", gTypeNames[i], ground[j] ); + } + + return 0; + +} +*/ + + +float clampf_uchar( float ); +double clampd_uchar( double ); +float clampf_uchar_rte( float ); +double clampd_uchar_rte( double ); +float clampf_uchar_rtp( float ); +double clampd_uchar_rtp( double ); +float clampf_uchar_rtn( float ); +double clampd_uchar_rtn( double ); +float clampf_uchar_rtz( float ); +double clampd_uchar_rtz( double ); +float clampf_char( float ); +double clampd_char( double ); +float clampf_char_rte( float ); +double clampd_char_rte( double ); +float clampf_char_rtp( float ); +double clampd_char_rtp( double ); +float clampf_char_rtn( float ); +double clampd_char_rtn( double ); +float clampf_char_rtz( float ); +double clampd_char_rtz( double ); +float clampf_ushort( float ); +double clampd_ushort( double ); +float clampf_ushort_rte( float ); +double clampd_ushort_rte( double ); +float clampf_ushort_rtp( float ); +double clampd_ushort_rtp( double ); +float clampf_ushort_rtn( float ); +double clampd_ushort_rtn( double ); +float clampf_ushort_rtz( float ); +double clampd_ushort_rtz( double ); +float clampf_short( float ); +double clampd_short( double ); +float clampf_short_rte( float ); +double clampd_short_rte( double ); +float clampf_short_rtp( float ); +double clampd_short_rtp( double ); +float clampf_short_rtn( float ); +double clampd_short_rtn( double ); +float clampf_short_rtz( float ); +double clampd_short_rtz( double ); +float clampf_uint( float ); +double clampd_uint( double ); +float clampf_uint_rte( float ); +double clampd_uint_rte( double ); +float clampf_uint_rtp( float ); +double clampd_uint_rtp( double ); +float clampf_uint_rtn( float ); +double clampd_uint_rtn( double ); +float clampf_uint_rtz( float ); +double clampd_uint_rtz( double ); +float clampf_int( float ); +double clampd_int( double ); +float clampf_int_rte( float ); +double clampd_int_rte( double ); +float clampf_int_rtp( float ); +double clampd_int_rtp( double ); +float clampf_int_rtn( float ); +double clampd_int_rtn( double ); +float clampf_int_rtz( float ); +double clampd_int_rtz( double ); +float clampf_float( float ); +double clampd_float( double ); +float clampf_float_rte( float ); +double clampd_float_rte( double ); +float clampf_float_rtp( float ); +double clampd_float_rtp( double ); +float clampf_float_rtn( float ); +double clampd_float_rtn( double ); +float clampf_float_rtz( float ); +double clampd_float_rtz( double ); +float clampf_double( float ); +double clampd_double( double ); +float clampf_double_rte( float ); +double clampd_double_rte( double ); +float clampf_double_rtp( float ); +double clampd_double_rtp( double ); +float clampf_double_rtn( float ); +double clampd_double_rtn( double ); +float clampf_double_rtz( float ); +double clampd_double_rtz( double ); +float clampf_ulong( float ); +double clampd_ulong( double ); +float clampf_ulong_rte( float ); +double clampd_ulong_rte( double ); +float clampf_ulong_rtp( float ); +double clampd_ulong_rtp( double ); +float clampf_ulong_rtn( float ); +double clampd_ulong_rtn( double ); +float clampf_ulong_rtz( float ); +double clampd_ulong_rtz( double ); +float clampf_long( float ); +double clampd_long( double ); +float clampf_long_rte( float ); +double clampd_long_rte( double ); +float clampf_long_rtp( float ); +double clampd_long_rtp( double ); +float clampf_long_rtn( float ); +double clampd_long_rtn( double ); +float clampf_long_rtz( float ); +double clampd_long_rtz( double ); + +/* +#include + +char *ground[] = { "", + "_rte", + "_rtp", + "_rtn", + "_rtz" + }; + +const char *gTypeNames[ ] = { + "uchar", "char", + "ushort", "short", + "uint", "int", + "float", "double", + "ulong", "long" + }; + + +int main( void ) +{ + int i, j; + + for( i = 0; i < sizeof( gTypeNames ) / sizeof( gTypeNames[0] ); i++ ) + { + vlog( "{\t" ); + for( j = 0; j < sizeof( ground ) / sizeof( ground[0] ); j++ ) + vlog( "clampf_%s%s,\t", gTypeNames[i], ground[j] ); + + vlog( "\t},\n" ); + } + + return 0; + +} +*/ +clampf gClampFloat[ kTypeCount ][kRoundingModeCount] = { + { clampf_uchar, clampf_uchar_rte, clampf_uchar_rtp, clampf_uchar_rtn, clampf_uchar_rtz, }, + { clampf_char, clampf_char_rte, clampf_char_rtp, clampf_char_rtn, clampf_char_rtz, }, + { clampf_ushort, clampf_ushort_rte, clampf_ushort_rtp, clampf_ushort_rtn, clampf_ushort_rtz, }, + { clampf_short, clampf_short_rte, clampf_short_rtp, clampf_short_rtn, clampf_short_rtz, }, + { clampf_uint, clampf_uint_rte, clampf_uint_rtp, clampf_uint_rtn, clampf_uint_rtz, }, + { clampf_int, clampf_int_rte, clampf_int_rtp, clampf_int_rtn, clampf_int_rtz, }, + { clampf_float, clampf_float_rte, clampf_float_rtp, clampf_float_rtn, clampf_float_rtz, }, + { clampf_double, clampf_double_rte, clampf_double_rtp, clampf_double_rtn, clampf_double_rtz, }, + { clampf_ulong, clampf_ulong_rte, clampf_ulong_rtp, clampf_ulong_rtn, clampf_ulong_rtz, }, + { clampf_long, clampf_long_rte, clampf_long_rtp, clampf_long_rtn, clampf_long_rtz, } +}; + +clampd gClampDouble[ kTypeCount ][kRoundingModeCount] = { + { clampd_uchar, clampd_uchar_rte, clampd_uchar_rtp, clampd_uchar_rtn, clampd_uchar_rtz, }, + { clampd_char, clampd_char_rte, clampd_char_rtp, clampd_char_rtn, clampd_char_rtz, }, + { clampd_ushort, clampd_ushort_rte, clampd_ushort_rtp, clampd_ushort_rtn, clampd_ushort_rtz, }, + { clampd_short, clampd_short_rte, clampd_short_rtp, clampd_short_rtn, clampd_short_rtz, }, + { clampd_uint, clampd_uint_rte, clampd_uint_rtp, clampd_uint_rtn, clampd_uint_rtz, }, + { clampd_int, clampd_int_rte, clampd_int_rtp, clampd_int_rtn, clampd_int_rtz, }, + { clampd_float, clampd_float_rte, clampd_float_rtp, clampd_float_rtn, clampd_float_rtz, }, + { clampd_double, clampd_double_rte, clampd_double_rtp, clampd_double_rtn, clampd_double_rtz, }, + { clampd_ulong, clampd_ulong_rte, clampd_ulong_rtp, clampd_ulong_rtn, clampd_ulong_rtz, }, + { clampd_long, clampd_long_rte, clampd_long_rtp, clampd_long_rtn, clampd_long_rtz, } +}; + +#if defined (_WIN32) +#define __attribute__(X) +#endif + +static inline float fclamp( float lo, float v, float hi ) __attribute__ ((always_inline)); +static inline double dclamp( double lo, double v, double hi ) __attribute__ ((always_inline)); + +static inline float fclamp( float lo, float v, float hi ){ v = v < lo ? lo : v; return v < hi ? v : hi; } +static inline double dclamp( double lo, double v, double hi ){ v = v < lo ? lo : v; return v < hi ? v : hi; } + +// Clamp unsaturated inputs into range so we don't get test errors: +float clampf_uchar( float f ) { return fclamp( -0.5f, f, 255.5f - 128.0f * FLT_EPSILON ); } +double clampd_uchar( double f ) { return dclamp( -0.5, f, 255.5 - 128.0 * DBL_EPSILON ); } +float clampf_uchar_rte( float f ) { return fclamp( -0.5f, f, 255.5f - 128.0f * FLT_EPSILON ); } +double clampd_uchar_rte( double f ) { return dclamp( -0.5, f, 255.5 - 128.0 * DBL_EPSILON ); } +float clampf_uchar_rtp( float f ) { return fclamp( -1.0f + FLT_EPSILON/2.0f, f, 255.0f ); } +double clampd_uchar_rtp( double f ) { return dclamp( -1.0 + DBL_EPSILON/2.0, f, 255.0 ); } +float clampf_uchar_rtn( float f ) { return fclamp( -0.0f, f, 256.0f - 128.0f * FLT_EPSILON); } +double clampd_uchar_rtn( double f ) { return dclamp( -0.0, f, 256.0 - 128.0 * DBL_EPSILON); } +float clampf_uchar_rtz( float f ) { return fclamp( -1.0f + FLT_EPSILON/2.0f, f, 256.0f - 128.0f * FLT_EPSILON); } +double clampd_uchar_rtz( double f ) { return dclamp( -1.0 + DBL_EPSILON/2.0, f, 256.0 - 128.0f * DBL_EPSILON); } + +float clampf_char( float f ) { return fclamp( -128.5f, f, 127.5f - 64.f * FLT_EPSILON ); } +double clampd_char( double f ) { return dclamp( -128.5, f, 127.5 - 64. * DBL_EPSILON ); } +float clampf_char_rte( float f ) { return fclamp( -128.5f, f, 127.5f - 64.f * FLT_EPSILON ); } +double clampd_char_rte( double f ) { return dclamp( -128.5, f, 127.5 - 64. * DBL_EPSILON ); } +float clampf_char_rtp( float f ) { return fclamp( -129.0f + 128.f*FLT_EPSILON, f, 127.f ); } +double clampd_char_rtp( double f ) { return dclamp( -129.0 + 128.*DBL_EPSILON, f, 127. ); } +float clampf_char_rtn( float f ) { return fclamp( -128.0f, f, 128.f - 64.0f*FLT_EPSILON ); } +double clampd_char_rtn( double f ) { return dclamp( -128.0, f, 128. - 64.0*DBL_EPSILON ); } +float clampf_char_rtz( float f ) { return fclamp( -129.0f + 128.f*FLT_EPSILON, f, 128.f - 64.0f*FLT_EPSILON ); } +double clampd_char_rtz( double f ) { return dclamp( -129.0 + 128.*DBL_EPSILON, f, 128. - 64.0*DBL_EPSILON ); } + +float clampf_ushort( float f ) { return fclamp( -0.5f, f, 65535.5f - 32768.0f * FLT_EPSILON ); } +double clampd_ushort( double f ) { return dclamp( -0.5, f, 65535.5 - 32768.0 * DBL_EPSILON ); } +float clampf_ushort_rte( float f ) { return fclamp( -0.5f, f, 65535.5f - 32768.0f * FLT_EPSILON ); } +double clampd_ushort_rte( double f ) { return dclamp( -0.5, f, 65535.5 - 32768.0 * DBL_EPSILON ); } +float clampf_ushort_rtp( float f ) { return fclamp( -1.0f + FLT_EPSILON/2.0f, f, 65535.0f ); } +double clampd_ushort_rtp( double f ) { return dclamp( -1.0 + DBL_EPSILON/2.0, f, 65535.0 ); } +float clampf_ushort_rtn( float f ) { return fclamp( -0.0f, f, 65536.0f - 32768.0f * FLT_EPSILON); } +double clampd_ushort_rtn( double f ) { return dclamp( -0.0, f, 65536.0 - 32768.0 * DBL_EPSILON); } +float clampf_ushort_rtz( float f ) { return fclamp( -1.0f + FLT_EPSILON/2.0f, f, 65536.0f - 32768.0f * FLT_EPSILON); } +double clampd_ushort_rtz( double f ) { return dclamp( -1.0 + DBL_EPSILON/2.0, f, 65536.0 - 32768.0f * DBL_EPSILON); } + +float clampf_short( float f ) { return fclamp( -32768.5f, f, 32767.5f - 16384.f * FLT_EPSILON ); } +double clampd_short( double f ) { return dclamp( -32768.5, f, 32767.5 - 16384. * DBL_EPSILON ); } +float clampf_short_rte( float f ) { return fclamp( -32768.5f, f, 32767.5f - 16384.f * FLT_EPSILON ); } +double clampd_short_rte( double f ) { return dclamp( -32768.5, f, 32767.5 - 16384. * DBL_EPSILON ); } +float clampf_short_rtp( float f ) { return fclamp( -32769.0f + 32768.f*FLT_EPSILON, f, 32767.f ); } +double clampd_short_rtp( double f ) { return dclamp( -32769.0 + 32768.*DBL_EPSILON, f, 32767. ); } +float clampf_short_rtn( float f ) { return fclamp( -32768.0f, f, 32768.f - 16384.0f*FLT_EPSILON ); } +double clampd_short_rtn( double f ) { return dclamp( -32768.0, f, 32768. - 16384.0*DBL_EPSILON ); } +float clampf_short_rtz( float f ) { return fclamp( -32769.0f + 32768.f*FLT_EPSILON, f, 32768.f - 16384.0f*FLT_EPSILON ); } +double clampd_short_rtz( double f ) { return dclamp( -32769.0 + 32768.*DBL_EPSILON, f, 32768. - 16384.0*DBL_EPSILON ); } + +float clampf_uint( float f ) { return fclamp( -0.5f, f, MAKE_HEX_FLOAT(0x1.fffffep31f, 0x1fffffeL, 7) ); } +double clampd_uint( double f ) { return dclamp( -0.5, f, CL_UINT_MAX + 0.5 - MAKE_HEX_DOUBLE(0x1.0p31, 0x1LL, 31) * DBL_EPSILON ); } +float clampf_uint_rte( float f ) { return fclamp( -0.5f, f, MAKE_HEX_FLOAT(0x1.fffffep31f, 0x1fffffeL, 7) ); } +double clampd_uint_rte( double f ) { return dclamp( -0.5, f, CL_UINT_MAX + 0.5 - MAKE_HEX_DOUBLE(0x1.0p31, 0x1LL, 31) * DBL_EPSILON ); } +float clampf_uint_rtp( float f ) { return fclamp( -1.0f + FLT_EPSILON/2.0f, f, MAKE_HEX_FLOAT(0x1.fffffep31f, 0x1fffffeL, 7) ); } +double clampd_uint_rtp( double f ) { return dclamp( -1.0 + DBL_EPSILON/2.0, f, CL_UINT_MAX ); } +float clampf_uint_rtn( float f ) { return fclamp( -0.0f, f, MAKE_HEX_FLOAT(0x1.fffffep31f, 0x1fffffeL, 7)); } +double clampd_uint_rtn( double f ) { return dclamp( -0.0, f, MAKE_HEX_DOUBLE(0x1.fffffffffffffp31, 0x1fffffffffffffLL, -21) ); } +float clampf_uint_rtz( float f ) { return fclamp( -1.0f + FLT_EPSILON/2.0f, f, MAKE_HEX_FLOAT(0x1.fffffep31f, 0x1fffffeL, 7)); } +double clampd_uint_rtz( double f ) { return dclamp( -1.0 + DBL_EPSILON/2.0, f, MAKE_HEX_DOUBLE(0x1.fffffffffffffp31, 0x1fffffffffffffLL, -21)); } + +float clampf_int( float f ) { return fclamp( INT_MIN, f, MAKE_HEX_FLOAT(0x1.fffffep30f, 0x1fffffeL, 6) ); } +double clampd_int( double f ) { return dclamp( INT_MIN - 0.5, f, CL_INT_MAX + 0.5 - MAKE_HEX_DOUBLE(0x1.0p30, 0x1LL, 30) * DBL_EPSILON ); } +float clampf_int_rte( float f ) { return fclamp( INT_MIN, f, MAKE_HEX_FLOAT(0x1.fffffep30f, 0x1fffffeL, 6) ); } +double clampd_int_rte( double f ) { return dclamp( INT_MIN - 0.5, f, CL_INT_MAX + 0.5 - MAKE_HEX_DOUBLE(0x1.0p30, 0x1LL, 30) * DBL_EPSILON ); } +float clampf_int_rtp( float f ) { return fclamp( INT_MIN, f, MAKE_HEX_FLOAT(0x1.fffffep30f, 0x1fffffeL, 6) ); } +double clampd_int_rtp( double f ) { return dclamp( INT_MIN - 1.0 + DBL_EPSILON * MAKE_HEX_DOUBLE(0x1.0p31, 0x1LL, 31), f, CL_INT_MAX ); } +float clampf_int_rtn( float f ) { return fclamp( INT_MIN, f, MAKE_HEX_FLOAT(0x1.fffffep30f, 0x1fffffeL, 6) ); } +double clampd_int_rtn( double f ) { return dclamp( INT_MIN, f, CL_INT_MAX + 1.0 - MAKE_HEX_DOUBLE(0x1.0p30, 0x1LL, 30) * DBL_EPSILON ); } +float clampf_int_rtz( float f ) { return fclamp( INT_MIN, f, MAKE_HEX_FLOAT(0x1.fffffep30f, 0x1fffffeL, 6) ); } +double clampd_int_rtz( double f ) { return dclamp( INT_MIN - 1.0 + DBL_EPSILON * MAKE_HEX_DOUBLE(0x1.0p31, 0x1LL, 31), f, CL_INT_MAX + 1.0 - MAKE_HEX_DOUBLE(0x1.0p30, 0x1LL, 30) * DBL_EPSILON ); } + +float clampf_float( float f ){ return f; } +double clampd_float( double f ){ return f; } +float clampf_float_rte( float f ){ return f; } +double clampd_float_rte( double f ){ return f; } +float clampf_float_rtp( float f ){ return f; } +double clampd_float_rtp( double f ){ return f; } +float clampf_float_rtn( float f ){ return f; } +double clampd_float_rtn( double f ){ return f; } +float clampf_float_rtz( float f ){ return f; } +double clampd_float_rtz( double f ){ return f; } + +float clampf_double( float f ){ return f; } +double clampd_double( double f ){ return f; } +float clampf_double_rte( float f ){ return f; } +double clampd_double_rte( double f ){ return f; } +float clampf_double_rtp( float f ){ return f; } +double clampd_double_rtp( double f ){ return f; } +float clampf_double_rtn( float f ){ return f; } +double clampd_double_rtn( double f ){ return f; } +float clampf_double_rtz( float f ){ return f; } +double clampd_double_rtz( double f ){ return f; } + +float clampf_ulong( float f ) { return fclamp( -0.5f, f, MAKE_HEX_FLOAT(0x1.fffffep63f, 0x1fffffeL, 39) ); } +double clampd_ulong( double f ) { return dclamp( -0.5, f, MAKE_HEX_DOUBLE(0x1.fffffffffffffp63, 0x1fffffffffffffLL, 11) ); } +float clampf_ulong_rte( float f ) { return fclamp( -0.5f, f, MAKE_HEX_FLOAT(0x1.fffffep63f, 0x1fffffeL, 39) ); } +double clampd_ulong_rte( double f ) { return dclamp( -0.5, f, MAKE_HEX_DOUBLE(0x1.fffffffffffffp63, 0x1fffffffffffffLL, 11) ); } +float clampf_ulong_rtp( float f ) { return fclamp( -1.0f + FLT_EPSILON/2.0f, f, MAKE_HEX_FLOAT(0x1.fffffep63f, 0x1fffffeL, 39) ); } +double clampd_ulong_rtp( double f ) { return dclamp( -1.0 + DBL_EPSILON/2.0, f, MAKE_HEX_DOUBLE(0x1.fffffffffffffp63, 0x1fffffffffffffLL, 11) ); } +float clampf_ulong_rtn( float f ) { return fclamp( -0.0f, f, MAKE_HEX_FLOAT(0x1.fffffep63f, 0x1fffffeL, 39) ); } +double clampd_ulong_rtn( double f ) { return dclamp( -0.0, f, MAKE_HEX_DOUBLE(0x1.fffffffffffffp63, 0x1fffffffffffffLL, 11) ); } +float clampf_ulong_rtz( float f ) { return fclamp( -1.0f + FLT_EPSILON/2.0f, f, MAKE_HEX_FLOAT(0x1.fffffep63f, 0x1fffffeL, 39) ); } +double clampd_ulong_rtz( double f ) { return dclamp( -1.0 + DBL_EPSILON/2.0, f, MAKE_HEX_DOUBLE(0x1.fffffffffffffp63, 0x1fffffffffffffLL, 11) ); } + +float clampf_long( float f ) { return fclamp( MAKE_HEX_FLOAT(-0x1.0p63f, -0x1L, 63), f, MAKE_HEX_FLOAT(0x1.fffffep62f, 0x1fffffeL, 38) ); } +double clampd_long( double f ) { return dclamp( MAKE_HEX_DOUBLE(-0x1.0p63, -0x1LL, 63), f, MAKE_HEX_DOUBLE(0x1.fffffffffffffp62, 0x1fffffffffffffLL, 10) ); } +float clampf_long_rte( float f ) { return fclamp( MAKE_HEX_FLOAT(-0x1.0p63f, -0x1L, 63), f, MAKE_HEX_FLOAT(0x1.fffffep62f, 0x1fffffeL, 38) ); } +double clampd_long_rte( double f ) { return dclamp( MAKE_HEX_DOUBLE(-0x1.0p63, -0x1LL, 63), f, MAKE_HEX_DOUBLE(0x1.fffffffffffffp62, 0x1fffffffffffffLL, 10) ); } +float clampf_long_rtp( float f ) { return fclamp( MAKE_HEX_FLOAT(-0x1.0p63f, -0x1L, 63), f, MAKE_HEX_FLOAT(0x1.fffffep62f, 0x1fffffeL, 38) ); } +double clampd_long_rtp( double f ) { return dclamp( MAKE_HEX_DOUBLE(-0x1.0p63, -0x1LL, 63), f, MAKE_HEX_DOUBLE(0x1.fffffffffffffp62, 0x1fffffffffffffLL, 10) ); } +float clampf_long_rtn( float f ) { return fclamp( MAKE_HEX_FLOAT(-0x1.0p63f, -0x1L, 63), f, MAKE_HEX_FLOAT(0x1.fffffep62f, 0x1fffffeL, 38) ); } +double clampd_long_rtn( double f ) { return dclamp( MAKE_HEX_DOUBLE(-0x1.0p63, -0x1LL, 63), f, MAKE_HEX_DOUBLE(0x1.fffffffffffffp62, 0x1fffffffffffffLL, 10) ); } +float clampf_long_rtz( float f ) { return fclamp( MAKE_HEX_FLOAT(-0x1.0p63f, -0x1L, 63), f, MAKE_HEX_FLOAT(0x1.fffffep62f, 0x1fffffeL, 38) ); } +double clampd_long_rtz( double f ) { return dclamp( MAKE_HEX_DOUBLE(-0x1.0p63, -0x1LL, 63), f, MAKE_HEX_DOUBLE(0x1.fffffffffffffp62, 0x1fffffffffffffLL, 10) ); } + +#pragma mark - + +int alwaysPass( void *out1, void *out2, void *allowZ, uint32_t count, int vectorSize ); +int alwaysFail( void *out1, void *out2, void *allowZ, uint32_t count, int vectorSize ); +int check_uchar( void *out1, void *out2, void *allowZ, uint32_t count, int vectorSize ); +int check_char( void *out1, void *out2, void *allowZ, uint32_t count, int vectorSize ); +int check_ushort( void *out1, void *out2, void *allowZ, uint32_t count, int vectorSize ); +int check_short( void *out1, void *out2, void *allowZ, uint32_t count, int vectorSize ); +int check_uint( void *out1, void *out2, void *allowZ, uint32_t count, int vectorSize ); +int check_int( void *out1, void *out2, void *allowZ, uint32_t count, int vectorSize ); +int check_ulong( void *out1, void *out2, void *allowZ, uint32_t count, int vectorSize ); +int check_long( void *out1, void *out2, void *allowZ, uint32_t count, int vectorSize ); +int check_float( void *out1, void *out2, void *allowZ, uint32_t count, int vectorSize ); +int check_double( void *out1, void *out2, void *allowZ, uint32_t count, int vectorSize ); + +void init_uchar( void *dest, SaturationMode, RoundingMode, Type destType, uint64_t start, int count, MTdata d ); +void init_char( void *dest, SaturationMode, RoundingMode, Type destType, uint64_t start, int count, MTdata d ); +void init_ushort( void *dest, SaturationMode, RoundingMode, Type destType, uint64_t start, int count, MTdata d ); +void init_short( void *dest, SaturationMode, RoundingMode, Type destType, uint64_t start, int count, MTdata d ); +void init_uint( void *dest, SaturationMode, RoundingMode, Type destType, uint64_t start, int count, MTdata d ); +void init_int( void *dest, SaturationMode, RoundingMode, Type destType, uint64_t start, int count, MTdata d ); +void init_float( void *dest, SaturationMode, RoundingMode, Type destType, uint64_t start, int count, MTdata d ); +void init_double( void *dest, SaturationMode, RoundingMode, Type destType, uint64_t start, int count, MTdata d ); +void init_ulong( void *dest, SaturationMode, RoundingMode, Type destType, uint64_t start, int count, MTdata d ); +void init_long( void *dest, SaturationMode, RoundingMode, Type destType, uint64_t start, int count, MTdata d ); + +InitDataFunc gInitFunctions[ kTypeCount ] = { + init_uchar, init_char, + init_ushort, init_short, + init_uint, init_int, + init_float, init_double, + init_ulong, init_long + }; + + +CheckResults gCheckResults[ kTypeCount ] = { + check_uchar, check_char, check_ushort, check_short, check_uint, + check_int, check_float, check_double, check_ulong, check_long + }; +#if !defined (__APPLE__) +#define UNUSED +#else +#define UNUSED __attribute__((unused)) +#endif + +int alwaysPass( void UNUSED *out1, void UNUSED *out2, void UNUSED *allowZ, uint32_t UNUSED count, int UNUSED vectorSize){ return 0; } +int alwaysFail( void UNUSED *out1, void UNUSED *out2, void UNUSED *allowZ, uint32_t UNUSED count, int UNUSED vectorSize ){ return -1; } + +int check_uchar( void *test, void *correct, void *allowZ, uint32_t count, int vectorSize ) +{ + const cl_uchar *t = (const cl_uchar*)test; + const cl_uchar *c = (const cl_uchar*)correct; + const cl_uchar *a = (const cl_uchar*)allowZ; + uint32_t i; + + for( i = 0; i < count; i++ ) + if( t[i] != c[i] && !(a[i] != (cl_uchar)0 && t[i] == (cl_uchar)0)) + { + vlog( "\nError for vector size %d found at 0x%8.8x: *0x%2.2x vs 0x%2.2x\n", vectorSize, i, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +int check_char( void *test, void *correct, void *allowZ, uint32_t count, int vectorSize ) +{ + const cl_char *t = (const cl_char*)test; + const cl_char *c = (const cl_char*)correct; + const cl_uchar *a = (const cl_uchar*)allowZ; + uint32_t i; + + for( i = 0; i < count; i++ ) + if( t[i] != c[i] && !(a[i] != (cl_uchar)0 && t[i] == (cl_char)0)) + { + vlog( "\nError for vector size %d found at 0x%8.8x: *0x%2.2x vs 0x%2.2x\n", vectorSize, i, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +int check_ushort( void *test, void *correct, void *allowZ, uint32_t count, int vectorSize ) +{ + const cl_ushort *t = (const cl_ushort*)test; + const cl_ushort *c = (const cl_ushort*)correct; + const cl_uchar *a = (const cl_uchar*)allowZ; + uint32_t i; + + for( i = 0; i < count; i++ ) + if( t[i] != c[i] && !(a[i] != (cl_uchar)0 && t[i] == (cl_ushort)0)) + { + vlog( "\nError for vector size %d found at 0x%8.8x: *0x%4.4x vs 0x%4.4x\n", vectorSize, i, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +int check_short( void *test, void *correct, void *allowZ, uint32_t count, int vectorSize ) +{ + const cl_short *t = (const cl_short*)test; + const cl_short *c = (const cl_short*)correct; + const cl_uchar *a = (const cl_uchar*)allowZ; + uint32_t i; + + for( i = 0; i < count; i++ ) + if( t[i] != c[i] && !(a[i] != (cl_uchar)0 && t[i] == (cl_short)0)) + { + vlog( "\nError for vector size %d found at 0x%8.8x: *0x%4.4x vs 0x%4.4x\n", vectorSize, i, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +int check_uint( void *test, void *correct, void *allowZ, uint32_t count, int vectorSize ) +{ + const cl_uint *t = (const cl_uint*)test; + const cl_uint *c = (const cl_uint*)correct; + const cl_uchar *a = (const cl_uchar*)allowZ; + uint32_t i; + + for( i = 0; i < count; i++ ) + if( t[i] != c[i] && !(a[i] != (cl_uchar)0 && t[i] == (cl_uint)0)) + { + vlog( "\nError for vector size %d found at 0x%8.8x: *0x%8.8x vs 0x%8.8x\n", vectorSize, i, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +int check_int( void *test, void *correct, void *allowZ, uint32_t count, int vectorSize ) +{ + const cl_int *t = (const cl_int*)test; + const cl_int *c = (const cl_int*)correct; + const cl_uchar *a = (const cl_uchar*)allowZ; + uint32_t i; + + for( i = 0; i < count; i++ ) + if( t[i] != c[i] && !(a[i] != (cl_uchar)0 && t[i] == (cl_int)0)) + { + vlog( "\nError for vector size %d found at 0x%8.8x: *0x%8.8x vs 0x%8.8x\n", vectorSize, i, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +int check_ulong( void *test, void *correct, void *allowZ, uint32_t count, int vectorSize ) +{ + const cl_ulong *t = (const cl_ulong*)test; + const cl_ulong *c = (const cl_ulong*)correct; + const cl_uchar *a = (const cl_uchar*)allowZ; + uint32_t i; + + for( i = 0; i < count; i++ ) + if( t[i] != c[i] && !(a[i] != (cl_uchar)0 && t[i] == (cl_ulong)0)) + { + vlog( "\nError for vector size %d found at 0x%8.8x: *0x%16.16llx vs 0x%16.16llx\n", vectorSize, i, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +int check_long( void *test, void *correct, void *allowZ, uint32_t count, int vectorSize ) +{ + const cl_long *t = (const cl_long*)test; + const cl_long *c = (const cl_long*)correct; + const cl_uchar *a = (const cl_uchar*)allowZ; + uint32_t i; + + for( i = 0; i < count; i++ ) + if( t[i] != c[i] && !(a[i] != (cl_uchar)0 && t[i] == (cl_long)0)) + { + vlog( "\nError for vector size %d found at 0x%8.8x: *0x%16.16llx vs 0x%16.16llx\n", vectorSize, i, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +int check_float( void *test, void *correct, void *allowZ, uint32_t count, int vectorSize ) +{ + const cl_uint *t = (const cl_uint*)test; + const cl_uint *c = (const cl_uint*)correct; + const cl_uchar *a = (const cl_uchar*)allowZ; + uint32_t i; + + for( i = 0; i < count; i++ ) + if (t[i] != c[i] && + // Allow nan's to be binary different + !((t[i] & 0x7fffffffU) > 0x7f800000U && + (c[i] & 0x7fffffffU) > 0x7f800000U) && + !(a[i] != (cl_uchar)0 && + t[i] == (c[i] & 0x80000000U))) { + vlog( "\nError for vector size %d found at 0x%8.8x: *%a vs %a\n", + vectorSize, i, ((float*)correct)[i], ((float*)test)[i] ); + return i + 1; + } + + return 0; +} + +int check_double( void *test, void *correct, void *allowZ, uint32_t count, int vectorSize ) +{ + const cl_ulong *t = (const cl_ulong*)test; + const cl_ulong *c = (const cl_ulong*)correct; + const cl_uchar *a = (const cl_uchar*)allowZ; + uint32_t i; + + for( i = 0; i < count; i++ ) + if (t[i] != c[i] && + // Allow nan's to be binary different + !((t[i] & 0x7fffffffffffffffULL) > 0x7ff0000000000000ULL && + (c[i] & 0x7fffffffffffffffULL) > 0x7f80000000000000ULL) && + !(a[i] != (cl_uchar)0 && + t[i] == (c[i] & 0x8000000000000000ULL))) { + vlog( "\nError for vector size %d found at 0x%8.8x: *%a vs %a\n", + vectorSize, i, ((double*)correct)[i], ((double*)test)[i] ); + return i + 1; + } + + return 0; +} + + +void init_uchar( void *out, SaturationMode UNUSED sat, RoundingMode UNUSED round, Type UNUSED destType, uint64_t start, int count, MTdata UNUSED d ) +{ + cl_uchar *o = (cl_uchar *)out; + int i; + + for( i = 0; i < count; i++ ) + o[i] = start++; +} + +void init_char( void *out, SaturationMode UNUSED sat, RoundingMode UNUSED round, Type UNUSED destType, uint64_t start, int count, MTdata UNUSED d ) +{ + char *o = (char *)out; + int i; + + for( i = 0; i < count; i++ ) + o[i] = start++; +} + +void init_ushort( void *out, SaturationMode UNUSED sat, RoundingMode UNUSED round, Type UNUSED destType, uint64_t start, int count, MTdata UNUSED d ) +{ + cl_ushort *o = (cl_ushort *)out; + int i; + + for( i = 0; i < count; i++ ) + o[i] = start++; +} + +void init_short( void *out, SaturationMode UNUSED sat, RoundingMode UNUSED round, UNUSED Type destType, uint64_t start, int count, MTdata UNUSED d ) +{ + short *o = (short *)out; + int i; + + for( i = 0; i < count; i++ ) + o[i] = start++; +} + +void init_uint( void *out, SaturationMode UNUSED sat, RoundingMode UNUSED round, Type UNUSED destType, uint64_t start, int count, MTdata d ) +{ + static const unsigned int specialValuesUInt[] = { + INT_MIN, INT_MIN + 1, INT_MIN + 2, + -(1<<30)-3,-(1<<30)-2,-(1<<30)-1, -(1<<30), -(1<<30)+1, -(1<<30)+2, -(1<<30)+3, + -(1<<24)-3,-(1<<24)-2,-(1<<24)-1, -(1<<24), -(1<<24)+1, -(1<<24)+2, -(1<<24)+3, + -(1<<23)-3,-(1<<23)-2,-(1<<23)-1, -(1<<23), -(1<<23)+1, -(1<<23)+2, -(1<<23)+3, + -(1<<22)-3,-(1<<22)-2,-(1<<22)-1, -(1<<22), -(1<<22)+1, -(1<<22)+2, -(1<<22)+3, + -(1<<21)-3,-(1<<21)-2,-(1<<21)-1, -(1<<21), -(1<<21)+1, -(1<<21)+2, -(1<<21)+3, + -(1<<16)-3,-(1<<16)-2,-(1<<16)-1, -(1<<16), -(1<<16)+1, -(1<<16)+2, -(1<<16)+3, + -(1<<15)-3,-(1<<15)-2,-(1<<15)-1, -(1<<15), -(1<<15)+1, -(1<<15)+2, -(1<<15)+3, + -(1<<8)-3,-(1<<8)-2,-(1<<8)-1, -(1<<8), -(1<<8)+1, -(1<<8)+2, -(1<<8)+3, + -(1<<7)-3,-(1<<7)-2,-(1<<7)-1, -(1<<7), -(1<<7)+1, -(1<<7)+2, -(1<<7)+3, + -4, -3, -2, -1, 0, 1, 2, 3, 4, + (1<<7)-3,(1<<7)-2,(1<<7)-1, (1<<7), (1<<7)+1, (1<<7)+2, (1<<7)+3, + (1<<8)-3,(1<<8)-2,(1<<8)-1, (1<<8), (1<<8)+1, (1<<8)+2, (1<<8)+3, + (1<<15)-3,(1<<15)-2,(1<<15)-1, (1<<15), (1<<15)+1, (1<<15)+2, (1<<15)+3, + (1<<16)-3,(1<<16)-2,(1<<16)-1, (1<<16), (1<<16)+1, (1<<16)+2, (1<<16)+3, + (1<<21)-3,(1<<21)-2,(1<<21)-1, (1<<21), (1<<21)+1, (1<<21)+2, (1<<21)+3, + (1<<22)-3,(1<<22)-2,(1<<22)-1, (1<<22), (1<<22)+1, (1<<22)+2, (1<<22)+3, + (1<<23)-3,(1<<23)-2,(1<<23)-1, (1<<23), (1<<23)+1, (1<<23)+2, (1<<23)+3, + (1<<24)-3,(1<<24)-2,(1<<24)-1, (1<<24), (1<<24)+1, (1<<24)+2, (1<<24)+3, + (1<<30)-3,(1<<30)-2,(1<<30)-1, (1<<30), (1<<30)+1, (1<<30)+2, (1<<30)+3, + INT_MAX-3, INT_MAX-2, INT_MAX-1, INT_MAX, // 0x80000000, 0x80000001 0x80000002 already covered above + UINT_MAX-3, UINT_MAX-2, UINT_MAX-1, UINT_MAX + }; + + cl_uint *o = (cl_uint *)out; + int i; + + for( i = 0; i < count; i++) { + if( gIsEmbedded ) + o[i] = (cl_uint) genrand_int32(d); + else + o[i] = (cl_uint)i + start; + } + + if( 0 == start ) + { + size_t tableSize = sizeof( specialValuesUInt ); + if( sizeof( cl_uint) * count < tableSize ) + tableSize = sizeof( cl_uint) * count; + memcpy( (char*)(o + i) - tableSize, specialValuesUInt, tableSize ); + } +} + +void init_int( void *out, SaturationMode UNUSED sat, RoundingMode UNUSED round, Type UNUSED destType, uint64_t start, int count, MTdata d ) +{ + static const unsigned int specialValuesInt[] = { + INT_MIN, INT_MIN + 1, INT_MIN + 2, + -(1<<30)-3,-(1<<30)-2,-(1<<30)-1, -(1<<30), -(1<<30)+1, -(1<<30)+2, -(1<<30)+3, + -(1<<24)-3,-(1<<24)-2,-(1<<24)-1, -(1<<24), -(1<<24)+1, -(1<<24)+2, -(1<<24)+3, + -(1<<23)-3,-(1<<23)-2,-(1<<23)-1, -(1<<23), -(1<<23)+1, -(1<<23)+2, -(1<<23)+3, + -(1<<22)-3,-(1<<22)-2,-(1<<22)-1, -(1<<22), -(1<<22)+1, -(1<<22)+2, -(1<<22)+3, + -(1<<21)-3,-(1<<21)-2,-(1<<21)-1, -(1<<21), -(1<<21)+1, -(1<<21)+2, -(1<<21)+3, + -(1<<16)-3,-(1<<16)-2,-(1<<16)-1, -(1<<16), -(1<<16)+1, -(1<<16)+2, -(1<<16)+3, + -(1<<15)-3,-(1<<15)-2,-(1<<15)-1, -(1<<15), -(1<<15)+1, -(1<<15)+2, -(1<<15)+3, + -(1<<8)-3,-(1<<8)-2,-(1<<8)-1, -(1<<8), -(1<<8)+1, -(1<<8)+2, -(1<<8)+3, + -(1<<7)-3,-(1<<7)-2,-(1<<7)-1, -(1<<7), -(1<<7)+1, -(1<<7)+2, -(1<<7)+3, + -4, -3, -2, -1, 0, 1, 2, 3, 4, + (1<<7)-3,(1<<7)-2,(1<<7)-1, (1<<7), (1<<7)+1, (1<<7)+2, (1<<7)+3, + (1<<8)-3,(1<<8)-2,(1<<8)-1, (1<<8), (1<<8)+1, (1<<8)+2, (1<<8)+3, + (1<<15)-3,(1<<15)-2,(1<<15)-1, (1<<15), (1<<15)+1, (1<<15)+2, (1<<15)+3, + (1<<16)-3,(1<<16)-2,(1<<16)-1, (1<<16), (1<<16)+1, (1<<16)+2, (1<<16)+3, + (1<<21)-3,(1<<21)-2,(1<<21)-1, (1<<21), (1<<21)+1, (1<<21)+2, (1<<21)+3, + (1<<22)-3,(1<<22)-2,(1<<22)-1, (1<<22), (1<<22)+1, (1<<22)+2, (1<<22)+3, + (1<<23)-3,(1<<23)-2,(1<<23)-1, (1<<23), (1<<23)+1, (1<<23)+2, (1<<23)+3, + (1<<24)-3,(1<<24)-2,(1<<24)-1, (1<<24), (1<<24)+1, (1<<24)+2, (1<<24)+3, + (1<<30)-3,(1<<30)-2,(1<<30)-1, (1<<30), (1<<30)+1, (1<<30)+2, (1<<30)+3, + INT_MAX-3, INT_MAX-2, INT_MAX-1, INT_MAX, // 0x80000000, 0x80000001 0x80000002 already covered above + UINT_MAX-3, UINT_MAX-2, UINT_MAX-1, UINT_MAX + }; + + int *o = (int *)out; + int i; + + for( i = 0; i < count; i++ ) { + if( gIsEmbedded ) { + o[i] = (int) genrand_int32(d); + } + else { + o[i] = (int) i + start; + } + } + + if( 0 == start ) + { + size_t tableSize = sizeof( specialValuesInt ); + if( sizeof( int) * count < tableSize ) + tableSize = sizeof( int) * count; + memcpy( (char*)(o + i) - tableSize, specialValuesInt, tableSize ); + } +} + +void init_float( void *out, SaturationMode sat, RoundingMode round, Type destType, uint64_t start, int count, MTdata d ) +{ + static const float specialValuesFloat[] = { + -NAN, -INFINITY, -FLT_MAX, MAKE_HEX_FLOAT(-0x1.000002p64f, -0x1000002L, 40), MAKE_HEX_FLOAT(-0x1.0p64f, -0x1L, 64), MAKE_HEX_FLOAT(-0x1.fffffep63f, -0x1fffffeL, 39), MAKE_HEX_FLOAT(-0x1.000002p63f, -0x1000002L, 39), MAKE_HEX_FLOAT(-0x1.0p63f, -0x1L, 63), MAKE_HEX_FLOAT(-0x1.fffffep62f, -0x1fffffeL, 38), + MAKE_HEX_FLOAT(-0x1.000002p32f, -0x1000002L, 8), MAKE_HEX_FLOAT(-0x1.0p32f, -0x1L, 32), MAKE_HEX_FLOAT(-0x1.fffffep31f, -0x1fffffeL, 7), MAKE_HEX_FLOAT(-0x1.000002p31f, -0x1000002L, 7), MAKE_HEX_FLOAT(-0x1.0p31f, -0x1L, 31), MAKE_HEX_FLOAT(-0x1.fffffep30f, -0x1fffffeL, 6), -1000.f, -100.f, -4.0f, -3.5f, + -3.0f, MAKE_HEX_FLOAT(-0x1.800002p1f, -0x1800002L, -23), -2.5f, MAKE_HEX_FLOAT(-0x1.7ffffep1f, -0x17ffffeL, -23), -2.0f, MAKE_HEX_FLOAT(-0x1.800002p0f, -0x1800002L, -24), -1.5f, MAKE_HEX_FLOAT(-0x1.7ffffep0f, -0x17ffffeL, -24),MAKE_HEX_FLOAT(-0x1.000002p0f, -0x1000002L, -24), -1.0f, MAKE_HEX_FLOAT(-0x1.fffffep-1f, -0x1fffffeL, -25), + MAKE_HEX_FLOAT(-0x1.000002p-1f, -0x1000002L, -25), -0.5f, MAKE_HEX_FLOAT(-0x1.fffffep-2f, -0x1fffffeL, -26), MAKE_HEX_FLOAT(-0x1.000002p-2f, -0x1000002L, -26), -0.25f, MAKE_HEX_FLOAT(-0x1.fffffep-3f, -0x1fffffeL, -27), + MAKE_HEX_FLOAT(-0x1.000002p-126f, -0x1000002L, -150), -FLT_MIN, MAKE_HEX_FLOAT(-0x0.fffffep-126f, -0x0fffffeL, -150), MAKE_HEX_FLOAT(-0x0.000ffep-126f, -0x0000ffeL, -150), MAKE_HEX_FLOAT(-0x0.0000fep-126f, -0x00000feL, -150), MAKE_HEX_FLOAT(-0x0.00000ep-126f, -0x000000eL, -150), MAKE_HEX_FLOAT(-0x0.00000cp-126f, -0x000000cL, -150), MAKE_HEX_FLOAT(-0x0.00000ap-126f, -0x000000aL, -150), + MAKE_HEX_FLOAT(-0x0.000008p-126f, -0x0000008L, -150), MAKE_HEX_FLOAT(-0x0.000006p-126f, -0x0000006L, -150), MAKE_HEX_FLOAT(-0x0.000004p-126f, -0x0000004L, -150), MAKE_HEX_FLOAT(-0x0.000002p-126f, -0x0000002L, -150), -0.0f, + +NAN, +INFINITY, +FLT_MAX, MAKE_HEX_FLOAT(+0x1.000002p64f, +0x1000002L, 40), MAKE_HEX_FLOAT(+0x1.0p64f, +0x1L, 64), MAKE_HEX_FLOAT(+0x1.fffffep63f, +0x1fffffeL, 39), MAKE_HEX_FLOAT(+0x1.000002p63f, +0x1000002L, 39), MAKE_HEX_FLOAT(+0x1.0p63f, +0x1L, 63), MAKE_HEX_FLOAT(+0x1.fffffep62f, +0x1fffffeL, 38), + MAKE_HEX_FLOAT(+0x1.000002p32f, +0x1000002L, 8), MAKE_HEX_FLOAT(+0x1.0p32f, +0x1L, 32), MAKE_HEX_FLOAT(+0x1.fffffep31f, +0x1fffffeL, 7), MAKE_HEX_FLOAT(+0x1.000002p31f, +0x1000002L, 7), MAKE_HEX_FLOAT(+0x1.0p31f, +0x1L, 31), MAKE_HEX_FLOAT(+0x1.fffffep30f, +0x1fffffeL, 6), +1000.f, +100.f, +4.0f, +3.5f, + +3.0f, MAKE_HEX_FLOAT(+0x1.800002p1f, +0x1800002L, -23), 2.5f, MAKE_HEX_FLOAT(+0x1.7ffffep1f, +0x17ffffeL, -23),+2.0f, MAKE_HEX_FLOAT(+0x1.800002p0f, +0x1800002L, -24), 1.5f, MAKE_HEX_FLOAT(+0x1.7ffffep0f, +0x17ffffeL, -24), MAKE_HEX_FLOAT(+0x1.000002p0f, +0x1000002L, -24), +1.0f, MAKE_HEX_FLOAT(+0x1.fffffep-1f, +0x1fffffeL, -25), + MAKE_HEX_FLOAT(+0x1.000002p-1f, +0x1000002L, -25), +0.5f, MAKE_HEX_FLOAT(+0x1.fffffep-2f, +0x1fffffeL, -26), MAKE_HEX_FLOAT(+0x1.000002p-2f, +0x1000002L, -26), +0.25f, MAKE_HEX_FLOAT(+0x1.fffffep-3f, +0x1fffffeL, -27), + MAKE_HEX_FLOAT(0x1.000002p-126f, 0x1000002L, -150), +FLT_MIN, MAKE_HEX_FLOAT(+0x0.fffffep-126f, +0x0fffffeL, -150), MAKE_HEX_FLOAT(+0x0.000ffep-126f, +0x0000ffeL, -150), MAKE_HEX_FLOAT(+0x0.0000fep-126f, +0x00000feL, -150), MAKE_HEX_FLOAT(+0x0.00000ep-126f, +0x000000eL, -150), MAKE_HEX_FLOAT(+0x0.00000cp-126f, +0x000000cL, -150), MAKE_HEX_FLOAT(+0x0.00000ap-126f, +0x000000aL, -150), + MAKE_HEX_FLOAT(+0x0.000008p-126f, +0x0000008L, -150), MAKE_HEX_FLOAT(+0x0.000006p-126f, +0x0000006L, -150), MAKE_HEX_FLOAT(+0x0.000004p-126f, +0x0000004L, -150), MAKE_HEX_FLOAT(+0x0.000002p-126f, +0x0000002L, -150), +0.0f + }; + + cl_uint *o = (cl_uint *)out; + int i; + + for( i = 0; i < count; i++ ) { + if( gIsEmbedded ) + o[i] = (cl_uint) genrand_int32(d); + else + o[i] = (cl_uint) i + start; + } + + if( 0 == start ) + { + size_t tableSize = sizeof( specialValuesFloat ); + if( sizeof( float) * count < tableSize ) + tableSize = sizeof( float) * count; + memcpy( (char*)(o + i) - tableSize, specialValuesFloat, tableSize ); + } + + if( kUnsaturated == sat ) + { + clampf func = gClampFloat[ destType ][round]; + float *f = (float *)out; + + for( i = 0; i < count; i++ ) + f[i] = func( f[i] ); + } +} + +// used to convert a bucket of bits into a search pattern through double +static inline double DoubleFromUInt32( uint32_t bits ); +static inline double DoubleFromUInt32( uint32_t bits ) +{ + union{ uint64_t u; double d;} u; + + // split 0x89abcdef to 0x89abc00000000def + u.u = bits & 0xfffU; + u.u |= (uint64_t) (bits & ~0xfffU) << 32; + + // sign extend the leading bit of def segment as sign bit so that the middle region consists of either all 1s or 0s + u.u -= (bits & 0x800U) << 1; + + // return result + return u.d; +} + +// A table of more difficult cases to get right +static const double specialValuesDouble[] = { + -NAN, -INFINITY, -DBL_MAX, MAKE_HEX_DOUBLE(-0x1.0000000000001p64, -0x10000000000001LL, 12), MAKE_HEX_DOUBLE(-0x1.0p64, -0x1LL, 64), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp63, -0x1fffffffffffffLL, 11), MAKE_HEX_DOUBLE(-0x1.80000000000001p64, -0x180000000000001LL, 8), + MAKE_HEX_DOUBLE(-0x1.8p64, -0x18LL, 60), MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp64, -0x17ffffffffffffLL, 12), MAKE_HEX_DOUBLE(-0x1.80000000000001p63, -0x180000000000001LL, 7), MAKE_HEX_DOUBLE(-0x1.8p63, -0x18LL, 59), MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp63, -0x17ffffffffffffLL, 11), + MAKE_HEX_DOUBLE(-0x1.0000000000001p63, -0x10000000000001LL, 11), MAKE_HEX_DOUBLE(-0x1.0p63, -0x1LL, 63), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp62, -0x1fffffffffffffLL, 10), MAKE_HEX_DOUBLE(-0x1.80000000000001p32, -0x180000000000001LL, -24), MAKE_HEX_DOUBLE(-0x1.8p32, -0x18LL, 28), MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp32, -0x17ffffffffffffLL, -20), + MAKE_HEX_DOUBLE(-0x1.000002p32, -0x1000002LL, 8), MAKE_HEX_DOUBLE(-0x1.0p32, -0x1LL, 32), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp31, -0x1fffffffffffffLL, -21), MAKE_HEX_DOUBLE(-0x1.80000000000001p31, -0x180000000000001LL, -25), MAKE_HEX_DOUBLE(-0x1.8p31, -0x18LL, 27), MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp31, -0x17ffffffffffffLL, -21), MAKE_HEX_DOUBLE(-0x1.0000000000001p31, -0x10000000000001LL, -21), MAKE_HEX_DOUBLE(-0x1.0p31, -0x1LL, 31), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp30, -0x1fffffffffffffLL, -22), -1000., -100., -4.0, -3.5, + -3.0, MAKE_HEX_DOUBLE(-0x1.8000000000001p1, -0x18000000000001LL, -51), -2.5, MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp1, -0x17ffffffffffffLL, -51), -2.0, MAKE_HEX_DOUBLE(-0x1.8000000000001p0, -0x18000000000001LL, -52), -1.5, MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp0, -0x17ffffffffffffLL, -52),MAKE_HEX_DOUBLE(-0x1.0000000000001p0, -0x10000000000001LL, -52), -1.0, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-1, -0x1fffffffffffffLL, -53), + MAKE_HEX_DOUBLE(-0x1.0000000000001p-1, -0x10000000000001LL, -53), -0.5, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-2, -0x1fffffffffffffLL, -54), MAKE_HEX_DOUBLE(-0x1.0000000000001p-2, -0x10000000000001LL, -54), -0.25, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-3, -0x1fffffffffffffLL, -55), + MAKE_HEX_DOUBLE(-0x1.0000000000001p-1022, -0x10000000000001LL, -1074), -DBL_MIN, MAKE_HEX_DOUBLE(-0x0.fffffffffffffp-1022, -0x0fffffffffffffLL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000fffp-1022, -0x00000000000fffLL, -1074), MAKE_HEX_DOUBLE(-0x0.00000000000fep-1022, -0x000000000000feLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000ep-1022, -0x0000000000000eLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000cp-1022, -0x0000000000000cLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000ap-1022, -0x0000000000000aLL, -1074), + MAKE_HEX_DOUBLE(-0x0.0000000000008p-1022, -0x00000000000008LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000007p-1022, -0x00000000000007LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000006p-1022, -0x00000000000006LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000005p-1022, -0x00000000000005LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000004p-1022, -0x00000000000004LL, -1074), + MAKE_HEX_DOUBLE(-0x0.0000000000003p-1022, -0x00000000000003LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000002p-1022, -0x00000000000002LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000001p-1022, -0x00000000000001LL, -1074), -0.0, + + MAKE_HEX_DOUBLE(+0x1.fffffffffffffp63, +0x1fffffffffffffLL, 11), MAKE_HEX_DOUBLE(0x1.80000000000001p63, 0x180000000000001LL, 7), MAKE_HEX_DOUBLE(0x1.8p63, 0x18LL, 59), MAKE_HEX_DOUBLE(0x1.7ffffffffffffp63, 0x17ffffffffffffLL, 11), MAKE_HEX_DOUBLE(+0x1.0000000000001p63, +0x10000000000001LL, 11), MAKE_HEX_DOUBLE(+0x1.0p63, +0x1LL, 63), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp62, +0x1fffffffffffffLL, 10), + MAKE_HEX_DOUBLE(+0x1.80000000000001p32, +0x180000000000001LL, -24), MAKE_HEX_DOUBLE(+0x1.8p32, +0x18LL, 28), MAKE_HEX_DOUBLE(+0x1.7ffffffffffffp32, +0x17ffffffffffffLL, -20), + MAKE_HEX_DOUBLE(+0x1.000002p32, +0x1000002LL, 8), MAKE_HEX_DOUBLE(+0x1.0p32, +0x1LL, 32), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp31, +0x1fffffffffffffLL, -21), MAKE_HEX_DOUBLE(+0x1.80000000000001p31, +0x180000000000001LL, -25), MAKE_HEX_DOUBLE(+0x1.8p31, +0x18LL, 27), MAKE_HEX_DOUBLE(+0x1.7ffffffffffffp31, +0x17ffffffffffffLL, -21), MAKE_HEX_DOUBLE(+0x1.0000000000001p31, +0x10000000000001LL, -21), MAKE_HEX_DOUBLE(+0x1.0p31, +0x1LL, 31), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp30, +0x1fffffffffffffLL, -22), +1000., +100., +4.0, +3.5, + +3.0, MAKE_HEX_DOUBLE(+0x1.8000000000001p1, +0x18000000000001LL, -51), +2.5, MAKE_HEX_DOUBLE(+0x1.7ffffffffffffp1, +0x17ffffffffffffLL, -51), +2.0, MAKE_HEX_DOUBLE(+0x1.8000000000001p0, +0x18000000000001LL, -52), +1.5, MAKE_HEX_DOUBLE(+0x1.7ffffffffffffp0, +0x17ffffffffffffLL, -52),MAKE_HEX_DOUBLE(-0x1.0000000000001p0, -0x10000000000001LL, -52), +1.0, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-1, +0x1fffffffffffffLL, -53), + MAKE_HEX_DOUBLE(+0x1.0000000000001p-1, +0x10000000000001LL, -53), +0.5, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-2, +0x1fffffffffffffLL, -54), MAKE_HEX_DOUBLE(+0x1.0000000000001p-2, +0x10000000000001LL, -54), +0.25, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-3, +0x1fffffffffffffLL, -55), + MAKE_HEX_DOUBLE(+0x1.0000000000001p-1022, +0x10000000000001LL, -1074), +DBL_MIN, MAKE_HEX_DOUBLE(+0x0.fffffffffffffp-1022, +0x0fffffffffffffLL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000fffp-1022, +0x00000000000fffLL, -1074), MAKE_HEX_DOUBLE(+0x0.00000000000fep-1022, +0x000000000000feLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000ep-1022, +0x0000000000000eLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000cp-1022, +0x0000000000000cLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000ap-1022, +0x0000000000000aLL, -1074), + MAKE_HEX_DOUBLE(+0x0.0000000000008p-1022, +0x00000000000008LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000007p-1022, +0x00000000000007LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000006p-1022, +0x00000000000006LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000005p-1022, +0x00000000000005LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000004p-1022, +0x00000000000004LL, -1074), + MAKE_HEX_DOUBLE(+0x0.0000000000003p-1022, +0x00000000000003LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000002p-1022, +0x00000000000002LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000001p-1022, +0x00000000000001LL, -1074), +0.0, + + MAKE_HEX_DOUBLE(-0x1.ffffffffffffep62, -0x1ffffffffffffeLL, 10), MAKE_HEX_DOUBLE(-0x1.ffffffffffffcp62, -0x1ffffffffffffcLL, 10), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp62, -0x1fffffffffffffLL, 10), MAKE_HEX_DOUBLE(+0x1.ffffffffffffep62, +0x1ffffffffffffeLL, 10), MAKE_HEX_DOUBLE(+0x1.ffffffffffffcp62, +0x1ffffffffffffcLL, 10), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp62, +0x1fffffffffffffLL, 10), + MAKE_HEX_DOUBLE(-0x1.ffffffffffffep51, -0x1ffffffffffffeLL, -1), MAKE_HEX_DOUBLE(-0x1.ffffffffffffcp51, -0x1ffffffffffffcLL, -1), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp51, -0x1fffffffffffffLL, -1), MAKE_HEX_DOUBLE(+0x1.ffffffffffffep51, +0x1ffffffffffffeLL, -1), MAKE_HEX_DOUBLE(+0x1.ffffffffffffcp51, +0x1ffffffffffffcLL, -1), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp51, +0x1fffffffffffffLL, -1), + MAKE_HEX_DOUBLE(-0x1.ffffffffffffep52, -0x1ffffffffffffeLL, 0), MAKE_HEX_DOUBLE(-0x1.ffffffffffffcp52, -0x1ffffffffffffcLL, 0), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp52, -0x1fffffffffffffLL, 0), MAKE_HEX_DOUBLE(+0x1.ffffffffffffep52, +0x1ffffffffffffeLL, 0), MAKE_HEX_DOUBLE(+0x1.ffffffffffffcp52, +0x1ffffffffffffcLL, 0), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp52, +0x1fffffffffffffLL, 0), + MAKE_HEX_DOUBLE(-0x1.ffffffffffffep53, -0x1ffffffffffffeLL, 1), MAKE_HEX_DOUBLE(-0x1.ffffffffffffcp53, -0x1ffffffffffffcLL, 1), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp53, -0x1fffffffffffffLL, 1), MAKE_HEX_DOUBLE(+0x1.ffffffffffffep53, +0x1ffffffffffffeLL, 1), MAKE_HEX_DOUBLE(+0x1.ffffffffffffcp53, +0x1ffffffffffffcLL, 1), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp53, +0x1fffffffffffffLL, 1), + MAKE_HEX_DOUBLE(-0x1.0000000000002p52, -0x10000000000002LL, 0), MAKE_HEX_DOUBLE(-0x1.0000000000001p52, -0x10000000000001LL, 0), MAKE_HEX_DOUBLE(-0x1.0p52, -0x1LL, 52), MAKE_HEX_DOUBLE(+0x1.0000000000002p52, +0x10000000000002LL, 0), MAKE_HEX_DOUBLE(+0x1.0000000000001p52, +0x10000000000001LL, 0), MAKE_HEX_DOUBLE(+0x1.0p52, +0x1LL, 52), + MAKE_HEX_DOUBLE(-0x1.0000000000002p53, -0x10000000000002LL, 1), MAKE_HEX_DOUBLE(-0x1.0000000000001p53, -0x10000000000001LL, 1), MAKE_HEX_DOUBLE(-0x1.0p53, -0x1LL, 53), MAKE_HEX_DOUBLE(+0x1.0000000000002p53, +0x10000000000002LL, 1), MAKE_HEX_DOUBLE(+0x1.0000000000001p53, +0x10000000000001LL, 1), MAKE_HEX_DOUBLE(+0x1.0p53, +0x1LL, 53), + MAKE_HEX_DOUBLE(-0x1.0000000000002p54, -0x10000000000002LL, 2), MAKE_HEX_DOUBLE(-0x1.0000000000001p54, -0x10000000000001LL, 2), MAKE_HEX_DOUBLE(-0x1.0p54, -0x1LL, 54), MAKE_HEX_DOUBLE(+0x1.0000000000002p54, +0x10000000000002LL, 2), MAKE_HEX_DOUBLE(+0x1.0000000000001p54, +0x10000000000001LL, 2), MAKE_HEX_DOUBLE(+0x1.0p54, +0x1LL, 54), + MAKE_HEX_DOUBLE(-0x1.fffffffefffffp62, -0x1fffffffefffffLL, 10), MAKE_HEX_DOUBLE(-0x1.ffffffffp62, -0x1ffffffffLL, 30), MAKE_HEX_DOUBLE(-0x1.ffffffff00001p62, -0x1ffffffff00001LL, 10), MAKE_HEX_DOUBLE(0x1.fffffffefffffp62, 0x1fffffffefffffLL, 10), MAKE_HEX_DOUBLE(0x1.ffffffffp62, 0x1ffffffffLL, 30), MAKE_HEX_DOUBLE(0x1.ffffffff00001p62, 0x1ffffffff00001LL, 10), +}; + + +void init_double( void *out, SaturationMode sat, RoundingMode round, Type destType, uint64_t start, int count, MTdata UNUSED d ) +{ + double *o = (double*)out; + int i; + + for( i = 0; i < count; i++ ) + { + uint64_t z = i + start; + o[i] = DoubleFromUInt32( (uint32_t) z ^ (uint32_t) (z >> 32)); + } + + if( 0 == start ) + { + size_t tableSize = sizeof( specialValuesDouble ); + if( sizeof( cl_double) * count < tableSize ) + tableSize = sizeof( cl_double) * count; + memcpy( (char*)(o + i) - tableSize, specialValuesDouble, tableSize ); + } + + if( 0 == sat ) + { + clampd func = gClampDouble[ destType ][round]; + + for( i = 0; i < count; i++ ) + o[i] = func( o[i] ); + } +} + +cl_ulong random64( MTdata d ) +{ + return (cl_ulong) genrand_int32(d) | ((cl_ulong) genrand_int32(d) << 32); +} + +void init_ulong( void *out, SaturationMode UNUSED sat, RoundingMode UNUSED round, Type UNUSED destType, uint64_t start, int count, MTdata d ) +{ + cl_ulong *o = (cl_ulong *)out; + cl_ulong i, j, k; + + i = 0; + if( start == 0 ) + { + //Try various powers of two + for( j = 0; j < (cl_ulong) count && j < 8 * sizeof(cl_ulong); j++ ) + o[j] = (cl_ulong) 1 << j; + i = j; + + // try the complement of those + for( j = 0; i < (cl_ulong) count && j < 8 * sizeof(cl_ulong); j++ ) + o[i++] = ~((cl_ulong) 1 << j); + + //Try various negative powers of two + for( j = 0; i < (cl_ulong) count && j < 8 * sizeof(cl_ulong); j++ ) + o[i++] = (cl_ulong) 0xFFFFFFFFFFFFFFFEULL << j; + + //try various powers of two plus 1, shifted by various amounts + for( j = 0; i < (cl_ulong)count && j < 8 * sizeof(cl_ulong); j++ ) + for( k = 0; i < (cl_ulong)count && k < 8 * sizeof(cl_ulong) - j; k++ ) + o[i++] = (((cl_ulong) 1 << j) + 1) << k; + + //try various powers of two minus 1 + for( j = 0; i < (cl_ulong)count && j < 8 * sizeof(cl_ulong); j++ ) + for( k = 0; i < (cl_ulong)count && k < 8 * sizeof(cl_ulong) - j; k++ ) + o[i++] = (((cl_ulong) 1 << j) - 1) << k; + + // Other patterns + cl_ulong pattern[] = { 0x3333333333333333ULL, 0x5555555555555555ULL, 0x9999999999999999ULL, 0x6666666666666666ULL, 0xccccccccccccccccULL, 0xaaaaaaaaaaaaaaaaULL }; + cl_ulong mask[] = { 0xffffffffffffffffULL, 0xff00ff00ff00ff00ULL, 0xffff0000ffff0000ULL, 0xffffffff00000000ULL }; + for( j = 0; i < (cl_ulong) count && j < sizeof(pattern) / sizeof( pattern[0]); j++ ) + for( k = 0; i + 2 <= (cl_ulong) count && k < sizeof(mask) / sizeof( mask[0]); k++ ) + { + o[i++] = pattern[j] & mask[k]; + o[i++] = pattern[j] & ~mask[k]; + } + } + + for( ; i < (cl_ulong) count; i++ ) + o[i] = random64(d); +} + +void init_long( void *out, SaturationMode sat, RoundingMode round, Type destType, uint64_t start, int count, MTdata d ) +{ + init_ulong( out, sat, round, destType, start, count, d ); +} + +// ====== + +void uchar2uchar_many( void *out, void *in, size_t n); +void uchar2uchar_sat_many( void *out, void *in, size_t n); +void char2uchar_many( void *out, void *in, size_t n); +void char2uchar_sat_many( void *out, void *in, size_t n); +void ushort2uchar_many( void *out, void *in, size_t n); +void ushort2uchar_sat_many( void *out, void *in, size_t n); +void short2uchar_many( void *out, void *in, size_t n); +void short2uchar_sat_many( void *out, void *in, size_t n); +void uint2uchar_many( void *out, void *in, size_t n); +void uint2uchar_sat_many( void *out, void *in, size_t n); +void int2uchar_many( void *out, void *in, size_t n); +void int2uchar_sat_many( void *out, void *in, size_t n); +void float2uchar_many( void *out, void *in, size_t n); +void float2uchar_sat_many( void *out, void *in, size_t n); +void double2uchar_many( void *out, void *in, size_t n); +void double2uchar_sat_many( void *out, void *in, size_t n); +void ulong2uchar_many( void *out, void *in, size_t n); +void ulong2uchar_sat_many( void *out, void *in, size_t n); +void long2uchar_many( void *out, void *in, size_t n); +void long2uchar_sat_many( void *out, void *in, size_t n); +void uchar2char_many( void *out, void *in, size_t n); +void uchar2char_sat_many( void *out, void *in, size_t n); +void char2char_many( void *out, void *in, size_t n); +void char2char_sat_many( void *out, void *in, size_t n); +void ushort2char_many( void *out, void *in, size_t n); +void ushort2char_sat_many( void *out, void *in, size_t n); +void short2char_many( void *out, void *in, size_t n); +void short2char_sat_many( void *out, void *in, size_t n); +void uint2char_many( void *out, void *in, size_t n); +void uint2char_sat_many( void *out, void *in, size_t n); +void int2char_many( void *out, void *in, size_t n); +void int2char_sat_many( void *out, void *in, size_t n); +void float2char_many( void *out, void *in, size_t n); +void float2char_sat_many( void *out, void *in, size_t n); +void double2char_many( void *out, void *in, size_t n); +void double2char_sat_many( void *out, void *in, size_t n); +void ulong2char_many( void *out, void *in, size_t n); +void ulong2char_sat_many( void *out, void *in, size_t n); +void long2char_many( void *out, void *in, size_t n); +void long2char_sat_many( void *out, void *in, size_t n); +void uchar2ushort_many( void *out, void *in, size_t n); +void uchar2ushort_sat_many( void *out, void *in, size_t n); +void char2ushort_many( void *out, void *in, size_t n); +void char2ushort_sat_many( void *out, void *in, size_t n); +void ushort2ushort_many( void *out, void *in, size_t n); +void ushort2ushort_sat_many( void *out, void *in, size_t n); +void short2ushort_many( void *out, void *in, size_t n); +void short2ushort_sat_many( void *out, void *in, size_t n); +void uint2ushort_many( void *out, void *in, size_t n); +void uint2ushort_sat_many( void *out, void *in, size_t n); +void int2ushort_many( void *out, void *in, size_t n); +void int2ushort_sat_many( void *out, void *in, size_t n); +void float2ushort_many( void *out, void *in, size_t n); +void float2ushort_sat_many( void *out, void *in, size_t n); +void double2ushort_many( void *out, void *in, size_t n); +void double2ushort_sat_many( void *out, void *in, size_t n); +void ulong2ushort_many( void *out, void *in, size_t n); +void ulong2ushort_sat_many( void *out, void *in, size_t n); +void long2ushort_many( void *out, void *in, size_t n); +void long2ushort_sat_many( void *out, void *in, size_t n); +void uchar2short_many( void *out, void *in, size_t n); +void uchar2short_sat_many( void *out, void *in, size_t n); +void char2short_many( void *out, void *in, size_t n); +void char2short_sat_many( void *out, void *in, size_t n); +void ushort2short_many( void *out, void *in, size_t n); +void ushort2short_sat_many( void *out, void *in, size_t n); +void short2short_many( void *out, void *in, size_t n); +void short2short_sat_many( void *out, void *in, size_t n); +void uint2short_many( void *out, void *in, size_t n); +void uint2short_sat_many( void *out, void *in, size_t n); +void int2short_many( void *out, void *in, size_t n); +void int2short_sat_many( void *out, void *in, size_t n); +void float2short_many( void *out, void *in, size_t n); +void float2short_sat_many( void *out, void *in, size_t n); +void double2short_many( void *out, void *in, size_t n); +void double2short_sat_many( void *out, void *in, size_t n); +void ulong2short_many( void *out, void *in, size_t n); +void ulong2short_sat_many( void *out, void *in, size_t n); +void long2short_many( void *out, void *in, size_t n); +void long2short_sat_many( void *out, void *in, size_t n); +void uchar2uint_many( void *out, void *in, size_t n); +void uchar2uint_sat_many( void *out, void *in, size_t n); +void char2uint_many( void *out, void *in, size_t n); +void char2uint_sat_many( void *out, void *in, size_t n); +void ushort2uint_many( void *out, void *in, size_t n); +void ushort2uint_sat_many( void *out, void *in, size_t n); +void short2uint_many( void *out, void *in, size_t n); +void short2uint_sat_many( void *out, void *in, size_t n); +void uint2uint_many( void *out, void *in, size_t n); +void uint2uint_sat_many( void *out, void *in, size_t n); +void int2uint_many( void *out, void *in, size_t n); +void int2uint_sat_many( void *out, void *in, size_t n); +void float2uint_many( void *out, void *in, size_t n); +void float2uint_sat_many( void *out, void *in, size_t n); +void double2uint_many( void *out, void *in, size_t n); +void double2uint_sat_many( void *out, void *in, size_t n); +void ulong2uint_many( void *out, void *in, size_t n); +void ulong2uint_sat_many( void *out, void *in, size_t n); +void long2uint_many( void *out, void *in, size_t n); +void long2uint_sat_many( void *out, void *in, size_t n); +void uchar2int_many( void *out, void *in, size_t n); +void uchar2int_sat_many( void *out, void *in, size_t n); +void char2int_many( void *out, void *in, size_t n); +void char2int_sat_many( void *out, void *in, size_t n); +void ushort2int_many( void *out, void *in, size_t n); +void ushort2int_sat_many( void *out, void *in, size_t n); +void short2int_many( void *out, void *in, size_t n); +void short2int_sat_many( void *out, void *in, size_t n); +void uint2int_many( void *out, void *in, size_t n); +void uint2int_sat_many( void *out, void *in, size_t n); +void int2int_many( void *out, void *in, size_t n); +void int2int_sat_many( void *out, void *in, size_t n); +void float2int_many( void *out, void *in, size_t n); +void float2int_sat_many( void *out, void *in, size_t n); +void double2int_many( void *out, void *in, size_t n); +void double2int_sat_many( void *out, void *in, size_t n); +void ulong2int_many( void *out, void *in, size_t n); +void ulong2int_sat_many( void *out, void *in, size_t n); +void long2int_many( void *out, void *in, size_t n); +void long2int_sat_many( void *out, void *in, size_t n); +void uchar2float_many( void *out, void *in, size_t n); +void uchar2float_sat_many( void *out, void *in, size_t n); +void char2float_many( void *out, void *in, size_t n); +void char2float_sat_many( void *out, void *in, size_t n); +void ushort2float_many( void *out, void *in, size_t n); +void ushort2float_sat_many( void *out, void *in, size_t n); +void short2float_many( void *out, void *in, size_t n); +void short2float_sat_many( void *out, void *in, size_t n); +void uint2float_many( void *out, void *in, size_t n); +void uint2float_sat_many( void *out, void *in, size_t n); +void int2float_many( void *out, void *in, size_t n); +void int2float_sat_many( void *out, void *in, size_t n); +void float2float_many( void *out, void *in, size_t n); +void float2float_sat_many( void *out, void *in, size_t n); +void double2float_many( void *out, void *in, size_t n); +void double2float_sat_many( void *out, void *in, size_t n); +void ulong2float_many( void *out, void *in, size_t n); +void ulong2float_sat_many( void *out, void *in, size_t n); +void long2float_many( void *out, void *in, size_t n); +void long2float_sat_many( void *out, void *in, size_t n); +void uchar2double_many( void *out, void *in, size_t n); +void uchar2double_sat_many( void *out, void *in, size_t n); +void char2double_many( void *out, void *in, size_t n); +void char2double_sat_many( void *out, void *in, size_t n); +void ushort2double_many( void *out, void *in, size_t n); +void ushort2double_sat_many( void *out, void *in, size_t n); +void short2double_many( void *out, void *in, size_t n); +void short2double_sat_many( void *out, void *in, size_t n); +void uint2double_many( void *out, void *in, size_t n); +void uint2double_sat_many( void *out, void *in, size_t n); +void int2double_many( void *out, void *in, size_t n); +void int2double_sat_many( void *out, void *in, size_t n); +void float2double_many( void *out, void *in, size_t n); +void float2double_sat_many( void *out, void *in, size_t n); +void double2double_many( void *out, void *in, size_t n); +void double2double_sat_many( void *out, void *in, size_t n); +void ulong2double_many( void *out, void *in, size_t n); +void ulong2double_sat_many( void *out, void *in, size_t n); +void long2double_many( void *out, void *in, size_t n); +void long2double_sat_many( void *out, void *in, size_t n); +void uchar2ulong_many( void *out, void *in, size_t n); +void uchar2ulong_sat_many( void *out, void *in, size_t n); +void char2ulong_many( void *out, void *in, size_t n); +void char2ulong_sat_many( void *out, void *in, size_t n); +void ushort2ulong_many( void *out, void *in, size_t n); +void ushort2ulong_sat_many( void *out, void *in, size_t n); +void short2ulong_many( void *out, void *in, size_t n); +void short2ulong_sat_many( void *out, void *in, size_t n); +void uint2ulong_many( void *out, void *in, size_t n); +void uint2ulong_sat_many( void *out, void *in, size_t n); +void int2ulong_many( void *out, void *in, size_t n); +void int2ulong_sat_many( void *out, void *in, size_t n); +void float2ulong_many( void *out, void *in, size_t n); +void float2ulong_sat_many( void *out, void *in, size_t n); +void double2ulong_many( void *out, void *in, size_t n); +void double2ulong_sat_many( void *out, void *in, size_t n); +void ulong2ulong_many( void *out, void *in, size_t n); +void ulong2ulong_sat_many( void *out, void *in, size_t n); +void long2ulong_many( void *out, void *in, size_t n); +void long2ulong_sat_many( void *out, void *in, size_t n); +void uchar2long_many( void *out, void *in, size_t n); +void uchar2long_sat_many( void *out, void *in, size_t n); +void char2long_many( void *out, void *in, size_t n); +void char2long_sat_many( void *out, void *in, size_t n); +void ushort2long_many( void *out, void *in, size_t n); +void ushort2long_sat_many( void *out, void *in, size_t n); +void short2long_many( void *out, void *in, size_t n); +void short2long_sat_many( void *out, void *in, size_t n); +void uint2long_many( void *out, void *in, size_t n); +void uint2long_sat_many( void *out, void *in, size_t n); +void int2long_many( void *out, void *in, size_t n); +void int2long_sat_many( void *out, void *in, size_t n); +void float2long_many( void *out, void *in, size_t n); +void float2long_sat_many( void *out, void *in, size_t n); +void double2long_many( void *out, void *in, size_t n); +void double2long_sat_many( void *out, void *in, size_t n); +void ulong2long_many( void *out, void *in, size_t n); +void ulong2long_sat_many( void *out, void *in, size_t n); +void long2long_many( void *out, void *in, size_t n); +void long2long_sat_many( void *out, void *in, size_t n); + +void uchar2uchar_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_uchar )); } +void uchar2uchar_sat_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_uchar )); } +void char2uchar_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2uchar( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_char)); }} +void char2uchar_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2uchar_sat( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_char)); }} +void ushort2uchar_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2uchar( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_ushort)); }} +void ushort2uchar_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2uchar_sat( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_ushort)); }} +void short2uchar_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2uchar( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_short)); }} +void short2uchar_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2uchar_sat( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_short)); }} +void uint2uchar_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2uchar( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_uint)); }} +void uint2uchar_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2uchar_sat( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_uint)); }} +void int2uchar_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2uchar( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_int)); }} +void int2uchar_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2uchar_sat( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_int)); }} +void float2uchar_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2uchar( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_float)); }} +void float2uchar_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2uchar_sat( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_float)); }} +void double2uchar_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2uchar( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_double)); }} +void double2uchar_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2uchar_sat( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_double)); }} +void ulong2uchar_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2uchar( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_ulong)); }} +void ulong2uchar_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2uchar_sat( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_ulong)); }} +void long2uchar_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2uchar( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_long)); }} +void long2uchar_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2uchar_sat( (char*) out + i * sizeof(cl_uchar), (char*) in + i * sizeof(cl_long)); }} +void uchar2char_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2char( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_uchar)); }} +void uchar2char_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2char_sat( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_uchar)); }} +void char2char_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_char )); } +void char2char_sat_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_char )); } +void ushort2char_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2char( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_ushort)); }} +void ushort2char_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2char_sat( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_ushort)); }} +void short2char_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2char( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_short)); }} +void short2char_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2char_sat( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_short)); }} +void uint2char_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2char( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_uint)); }} +void uint2char_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2char_sat( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_uint)); }} +void int2char_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2char( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_int)); }} +void int2char_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2char_sat( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_int)); }} +void float2char_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2char( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_float)); }} +void float2char_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2char_sat( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_float)); }} +void double2char_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2char( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_double)); }} +void double2char_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2char_sat( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_double)); }} +void ulong2char_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2char( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_ulong)); }} +void ulong2char_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2char_sat( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_ulong)); }} +void long2char_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2char( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_long)); }} +void long2char_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2char_sat( (char*) out + i * sizeof(cl_char), (char*) in + i * sizeof(cl_long)); }} +void uchar2ushort_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2ushort( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_uchar)); }} +void uchar2ushort_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2ushort_sat( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_uchar)); }} +void char2ushort_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2ushort( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_char)); }} +void char2ushort_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2ushort_sat( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_char)); }} +void ushort2ushort_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_ushort )); } +void ushort2ushort_sat_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_ushort )); } +void short2ushort_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2ushort( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_short)); }} +void short2ushort_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2ushort_sat( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_short)); }} +void uint2ushort_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2ushort( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_uint)); }} +void uint2ushort_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2ushort_sat( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_uint)); }} +void int2ushort_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2ushort( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_int)); }} +void int2ushort_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2ushort_sat( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_int)); }} +void float2ushort_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2ushort( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_float)); }} +void float2ushort_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2ushort_sat( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_float)); }} +void double2ushort_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2ushort( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_double)); }} +void double2ushort_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2ushort_sat( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_double)); }} +void ulong2ushort_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2ushort( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_ulong)); }} +void ulong2ushort_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2ushort_sat( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_ulong)); }} +void long2ushort_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2ushort( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_long)); }} +void long2ushort_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2ushort_sat( (char*) out + i * sizeof(cl_ushort), (char*) in + i * sizeof(cl_long)); }} +void uchar2short_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2short( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_uchar)); }} +void uchar2short_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2short_sat( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_uchar)); }} +void char2short_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2short( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_char)); }} +void char2short_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2short_sat( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_char)); }} +void ushort2short_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2short( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_ushort)); }} +void ushort2short_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2short_sat( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_ushort)); }} +void short2short_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_short )); } +void short2short_sat_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_short )); } +void uint2short_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2short( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_uint)); }} +void uint2short_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2short_sat( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_uint)); }} +void int2short_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2short( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_int)); }} +void int2short_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2short_sat( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_int)); }} +void float2short_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2short( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_float)); }} +void float2short_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2short_sat( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_float)); }} +void double2short_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2short( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_double)); }} +void double2short_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2short_sat( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_double)); }} +void ulong2short_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2short( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_ulong)); }} +void ulong2short_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2short_sat( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_ulong)); }} +void long2short_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2short( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_long)); }} +void long2short_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2short_sat( (char*) out + i * sizeof(cl_short), (char*) in + i * sizeof(cl_long)); }} +void uchar2uint_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2uint( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_uchar)); }} +void uchar2uint_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2uint_sat( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_uchar)); }} +void char2uint_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2uint( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_char)); }} +void char2uint_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2uint_sat( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_char)); }} +void ushort2uint_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2uint( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_ushort)); }} +void ushort2uint_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2uint_sat( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_ushort)); }} +void short2uint_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2uint( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_short)); }} +void short2uint_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2uint_sat( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_short)); }} +void uint2uint_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_uint )); } +void uint2uint_sat_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_uint )); } +void int2uint_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2uint( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_int)); }} +void int2uint_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2uint_sat( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_int)); }} +void float2uint_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2uint( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_float)); }} +void float2uint_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2uint_sat( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_float)); }} +void double2uint_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2uint( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_double)); }} +void double2uint_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2uint_sat( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_double)); }} +void ulong2uint_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2uint( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_ulong)); }} +void ulong2uint_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2uint_sat( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_ulong)); }} +void long2uint_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2uint( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_long)); }} +void long2uint_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2uint_sat( (char*) out + i * sizeof(cl_uint), (char*) in + i * sizeof(cl_long)); }} +void uchar2int_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2int( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_uchar)); }} +void uchar2int_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2int_sat( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_uchar)); }} +void char2int_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2int( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_char)); }} +void char2int_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2int_sat( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_char)); }} +void ushort2int_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2int( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_ushort)); }} +void ushort2int_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2int_sat( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_ushort)); }} +void short2int_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2int( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_short)); }} +void short2int_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2int_sat( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_short)); }} +void uint2int_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2int( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_uint)); }} +void uint2int_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2int_sat( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_uint)); }} +void int2int_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_int )); } +void int2int_sat_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_int )); } +void float2int_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2int( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_float)); }} +void float2int_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2int_sat( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_float)); }} +void double2int_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2int( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_double)); }} +void double2int_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2int_sat( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_double)); }} +void ulong2int_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2int( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_ulong)); }} +void ulong2int_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2int_sat( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_ulong)); }} +void long2int_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2int( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_long)); }} +void long2int_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2int_sat( (char*) out + i * sizeof(cl_int), (char*) in + i * sizeof(cl_long)); }} +void uchar2float_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2float( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_uchar)); }} +void uchar2float_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2float_sat( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_uchar)); }} +void char2float_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2float( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_char)); }} +void char2float_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2float_sat( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_char)); }} +void ushort2float_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2float( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_ushort)); }} +void ushort2float_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2float_sat( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_ushort)); }} +void short2float_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2float( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_short)); }} +void short2float_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2float_sat( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_short)); }} +void uint2float_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2float( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_uint)); }} +void uint2float_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2float_sat( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_uint)); }} +void int2float_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2float( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_int)); }} +void int2float_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2float_sat( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_int)); }} +void float2float_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_float )); } +void float2float_sat_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_float )); } +void double2float_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2float( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_double)); }} +void double2float_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2float_sat( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_double)); }} +void ulong2float_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2float( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_ulong)); }} +void ulong2float_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2float_sat( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_ulong)); }} +void long2float_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2float( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_long)); }} +void long2float_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2float_sat( (char*) out + i * sizeof(cl_float), (char*) in + i * sizeof(cl_long)); }} +void uchar2double_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2double( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_uchar)); }} +void uchar2double_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2double_sat( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_uchar)); }} +void char2double_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2double( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_char)); }} +void char2double_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2double_sat( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_char)); }} +void ushort2double_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2double( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_ushort)); }} +void ushort2double_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2double_sat( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_ushort)); }} +void short2double_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2double( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_short)); }} +void short2double_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2double_sat( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_short)); }} +void uint2double_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2double( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_uint)); }} +void uint2double_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2double_sat( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_uint)); }} +void int2double_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2double( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_int)); }} +void int2double_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2double_sat( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_int)); }} +void float2double_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2double( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_float)); }} +void float2double_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2double_sat( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_float)); }} +void double2double_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_double )); } +void double2double_sat_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_double )); } +void ulong2double_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2double( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_ulong)); }} +void ulong2double_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2double_sat( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_ulong)); }} +void long2double_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2double( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_long)); }} +void long2double_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2double_sat( (char*) out + i * sizeof(cl_double), (char*) in + i * sizeof(cl_long)); }} +void uchar2ulong_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2ulong( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_uchar)); }} +void uchar2ulong_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2ulong_sat( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_uchar)); }} +void char2ulong_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2ulong( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_char)); }} +void char2ulong_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2ulong_sat( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_char)); }} +void ushort2ulong_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2ulong( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_ushort)); }} +void ushort2ulong_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2ulong_sat( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_ushort)); }} +void short2ulong_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2ulong( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_short)); }} +void short2ulong_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2ulong_sat( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_short)); }} +void uint2ulong_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2ulong( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_uint)); }} +void uint2ulong_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2ulong_sat( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_uint)); }} +void int2ulong_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2ulong( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_int)); }} +void int2ulong_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2ulong_sat( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_int)); }} +void float2ulong_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2ulong( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_float)); }} +void float2ulong_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2ulong_sat( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_float)); }} +void double2ulong_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2ulong( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_double)); }} +void double2ulong_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2ulong_sat( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_double)); }} +void ulong2ulong_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_ulong )); } +void ulong2ulong_sat_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_ulong )); } +void long2ulong_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2ulong( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_long)); }} +void long2ulong_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ long2ulong_sat( (char*) out + i * sizeof(cl_ulong), (char*) in + i * sizeof(cl_long)); }} +void uchar2long_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2long( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_uchar)); }} +void uchar2long_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uchar2long_sat( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_uchar)); }} +void char2long_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2long( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_char)); }} +void char2long_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ char2long_sat( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_char)); }} +void ushort2long_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2long( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_ushort)); }} +void ushort2long_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ushort2long_sat( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_ushort)); }} +void short2long_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2long( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_short)); }} +void short2long_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ short2long_sat( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_short)); }} +void uint2long_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2long( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_uint)); }} +void uint2long_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ uint2long_sat( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_uint)); }} +void int2long_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2long( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_int)); }} +void int2long_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ int2long_sat( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_int)); }} +void float2long_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2long( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_float)); }} +void float2long_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ float2long_sat( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_float)); }} +void double2long_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2long( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_double)); }} +void double2long_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ double2long_sat( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_double)); }} +void ulong2long_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2long( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_ulong)); }} +void ulong2long_sat_many( void *out, void *in, size_t n){size_t i; for( i = 0; i < n; i++){ ulong2long_sat( (char*) out + i * sizeof(cl_long), (char*) in + i * sizeof(cl_ulong)); }} +void long2long_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_long )); } +void long2long_sat_many( void *out, void *in, size_t n){ memcpy( out, in, n * sizeof( cl_long )); } + +Convert gSaturatedConversions[kTypeCount][kTypeCount] = { + { uchar2uchar_sat_many, char2uchar_sat_many, ushort2uchar_sat_many, short2uchar_sat_many, uint2uchar_sat_many, int2uchar_sat_many, float2uchar_sat_many, double2uchar_sat_many, ulong2uchar_sat_many, long2uchar_sat_many, }, + { uchar2char_sat_many, char2char_sat_many, ushort2char_sat_many, short2char_sat_many, uint2char_sat_many, int2char_sat_many, float2char_sat_many, double2char_sat_many, ulong2char_sat_many, long2char_sat_many, }, + { uchar2ushort_sat_many, char2ushort_sat_many, ushort2ushort_sat_many, short2ushort_sat_many, uint2ushort_sat_many, int2ushort_sat_many, float2ushort_sat_many, double2ushort_sat_many, ulong2ushort_sat_many, long2ushort_sat_many, }, + { uchar2short_sat_many, char2short_sat_many, ushort2short_sat_many, short2short_sat_many, uint2short_sat_many, int2short_sat_many, float2short_sat_many, double2short_sat_many, ulong2short_sat_many, long2short_sat_many, }, + { uchar2uint_sat_many, char2uint_sat_many, ushort2uint_sat_many, short2uint_sat_many, uint2uint_sat_many, int2uint_sat_many, float2uint_sat_many, double2uint_sat_many, ulong2uint_sat_many, long2uint_sat_many, }, + { uchar2int_sat_many, char2int_sat_many, ushort2int_sat_many, short2int_sat_many, uint2int_sat_many, int2int_sat_many, float2int_sat_many, double2int_sat_many, ulong2int_sat_many,long2int_sat_many, }, + { uchar2float_sat_many, char2float_sat_many, ushort2float_sat_many, short2float_sat_many, uint2float_sat_many, int2float_sat_many, float2float_sat_many, double2float_sat_many, ulong2float_sat_many, long2float_sat_many, }, + { uchar2double_sat_many, char2double_sat_many, ushort2double_sat_many, short2double_sat_many, uint2double_sat_many, int2double_sat_many, float2double_sat_many, double2double_sat_many, ulong2double_sat_many, long2double_sat_many, }, + { uchar2ulong_sat_many, char2ulong_sat_many, ushort2ulong_sat_many, short2ulong_sat_many, uint2ulong_sat_many, int2ulong_sat_many, float2ulong_sat_many, double2ulong_sat_many, ulong2ulong_sat_many, long2ulong_sat_many, }, + { uchar2long_sat_many, char2long_sat_many, ushort2long_sat_many, short2long_sat_many, uint2long_sat_many, int2long_sat_many, float2long_sat_many, double2long_sat_many, ulong2long_sat_many, long2long_sat_many, }, +}; + +Convert gConversions[kTypeCount][kTypeCount] = { + { uchar2uchar_many, char2uchar_many, ushort2uchar_many, short2uchar_many, uint2uchar_many, int2uchar_many, float2uchar_many, double2uchar_many, ulong2uchar_many, long2uchar_many, }, + { uchar2char_many, char2char_many, ushort2char_many, short2char_many, uint2char_many, int2char_many, float2char_many, double2char_many, ulong2char_many, long2char_many, }, + { uchar2ushort_many, char2ushort_many, ushort2ushort_many, short2ushort_many, uint2ushort_many, int2ushort_many, float2ushort_many, double2ushort_many, ulong2ushort_many, long2ushort_many, }, + { uchar2short_many, char2short_many, ushort2short_many, short2short_many, uint2short_many, int2short_many, float2short_many, double2short_many, ulong2short_many, long2short_many, }, + { uchar2uint_many, char2uint_many, ushort2uint_many, short2uint_many, uint2uint_many, int2uint_many, float2uint_many, double2uint_many, ulong2uint_many, long2uint_many, }, + { uchar2int_many, char2int_many, ushort2int_many, short2int_many, uint2int_many, int2int_many, float2int_many, double2int_many, ulong2int_many, long2int_many, }, + { uchar2float_many, char2float_many, ushort2float_many, short2float_many, uint2float_many, int2float_many, float2float_many, double2float_many, ulong2float_many, long2float_many, }, + { uchar2double_many, char2double_many, ushort2double_many, short2double_many, uint2double_many, int2double_many, float2double_many, double2double_many, ulong2double_many, long2double_many, }, + { uchar2ulong_many, char2ulong_many, ushort2ulong_many, short2ulong_many, uint2ulong_many, int2ulong_many, float2ulong_many, double2ulong_many, ulong2ulong_many, long2ulong_many, }, + { uchar2long_many, char2long_many, ushort2long_many, short2long_many, uint2long_many, int2long_many, float2long_many, double2long_many, ulong2long_many, long2long_many, }, +}; diff --git a/test_conformance/conversions/basic_test_conversions.h b/test_conformance/conversions/basic_test_conversions.h new file mode 100644 index 00000000..ab8c68cd --- /dev/null +++ b/test_conformance/conversions/basic_test_conversions.h @@ -0,0 +1,73 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef BASIC_TEST_CONVERSIONS_H +#define BASIC_TEST_CONVERSIONS_H + +#include "../../test_common/harness/compat.h" + +#if !defined(_WIN32) +#include +#endif + +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/rounding_mode.h" + +#include +#if defined( __APPLE__ ) + #include +#else + #include +#endif + +#include "../../test_common/harness/mt19937.h" + +typedef void (*Convert)( void *dest, void *src, size_t ); + +#define kVectorSizeCount 6 +#define kMaxVectorSize 16 + +typedef enum +{ + kUnsaturated = 0, + kSaturated, + + kSaturationModeCount +}SaturationMode; + +extern Convert gConversions[kTypeCount][kTypeCount]; // [dest format][source format] +extern Convert gSaturatedConversions[kTypeCount][kTypeCount]; // [dest format][source format] +extern const char *gTypeNames[ kTypeCount ]; +extern const char *gRoundingModeNames[ kRoundingModeCount ]; // { "", "_rte", "_rtp", "_rtn", "_rtz" } +extern const char *gSaturationNames[ kSaturationModeCount ]; // { "", "_sat" } +extern const char *gVectorSizeNames[kVectorSizeCount]; // { "", "2", "4", "8", "16" } +extern size_t gTypeSizes[ kTypeCount ]; +extern int gIsEmbedded; + +//Functions for clamping floating point numbers into the representable range for the type +typedef float (*clampf)( float ); +typedef double (*clampd)( double ); + +extern clampf gClampFloat[ kTypeCount ][kRoundingModeCount]; +extern clampd gClampDouble[ kTypeCount ][kRoundingModeCount]; + +typedef void (*InitDataFunc)( void *dest, SaturationMode, RoundingMode, Type destType, uint64_t start, int count, MTdata d ); +extern InitDataFunc gInitFunctions[ kTypeCount ]; + +typedef int (*CheckResults)( void *out1, void *out2, void *allowZ, uint32_t count, int vectorSize ); +extern CheckResults gCheckResults[ kTypeCount ]; + +#endif /* BASIC_TEST_CONVERSIONS_H */ + diff --git a/test_conformance/conversions/fplib.c b/test_conformance/conversions/fplib.c new file mode 100644 index 00000000..a18b919c --- /dev/null +++ b/test_conformance/conversions/fplib.c @@ -0,0 +1,221 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include "fplib.h" + +#define FLT_MANT_DIG 24 +#define as_float(x) (*((float *)(&x))) +#define as_long(x) (*((int64_t *)(&x))) + +static uint32_t clz(uint64_t value) +{ + uint32_t num_zeros; + + for( num_zeros = 0; num_zeros < (sizeof(uint64_t)*8); num_zeros++) + { + if(0x8000000000000000 & (value << num_zeros)) + break; + } + return num_zeros; +} + +float qcom_s64_2_f32(int64_t data, bool sat, roundingMode rnd) +{ + switch (rnd) { + case qcomRTZ: { + int sign = 0; + if (!data) + return 0.0f; + if (data < 0){ + data = - data; + sign = 1; + } + uint32_t exponent = (127 + 64 - clz(data) - 1) << (FLT_MANT_DIG - 1); //add 1 for the implied 1.0 in normalized fp32 numbers + int mantShift = 40 - clz(data); + uint32_t mantissa; + if (mantShift >= 0) + mantissa = (uint32_t)((uint64_t)data >> mantShift); + else + mantissa = (uint32_t)((uint64_t)data << -mantShift); + mantissa &= 0x7fffff;//mask off the leading 1 + + uint32_t result = exponent | mantissa; + if (sign) + result |= 0x80000000; + return as_float(result); + break; + } + case qcomRTE: return (float)(data); break; + case qcomRTP: { + int sign = 0; + int inExact = 0; + uint32_t f = 0xdf000000; + if (!data) + return 0.0f; + if (data == 0x8000000000000000) + return as_float(f); + if (data < 0){ + data = - data; + sign = 1; + } + uint32_t exponent = (127 + 64 - clz(data) - 1) << (FLT_MANT_DIG - 1); //add 1 for the implied 1.0 in normalized fp32 numbers + int mantShift = 40 - clz(data); + uint32_t mantissa; + if (mantShift >= 0){ + uint64_t temp = (uint64_t)data >> mantShift; + uint64_t mask = (1 << mantShift) - 1; + if ((temp << mantShift) != data) + inExact = 1; + mantissa = (uint32_t)temp; + } + else + { + mantissa = (uint32_t)((uint64_t)data << -mantShift); + } + mantissa &= 0x7fffff;//mask off the leading 1 + + uint32_t result = exponent | mantissa; + if (sign) + result |= 0x80000000; + if (sign) + return as_float(result); // for negative inputs return rtz results + else + { + if(inExact) + { // for positive inputs return higher next fp + uint32_t high_float = 0x7f7fffff; + return nextafterf(as_float(result), as_float(high_float)); // could be simplified with some inc and carry operation + } + else + return as_float(result); + } + } + break; + case qcomRTN: { + int sign = 0; + int inExact = 0; + uint32_t f = 0xdf000000; + if (!data) + return 0.0f; + if (data == 0x8000000000000000) + return as_float(f); + if (data < 0){ + data = - data; + sign = 1; + } + uint32_t exponent = (127 + 64 - clz(data) - 1) << (FLT_MANT_DIG - 1); //add 1 for the implied 1.0 in normalized fp32 numbers + int mantShift = 40 - clz(data); + uint32_t mantissa; + if (mantShift >= 0){ + uint64_t temp = (uint64_t)data >> mantShift; + uint64_t mask = (1 << mantShift) - 1; + if (temp << mantShift != data) + inExact = 1; + mantissa = (uint32_t)temp; + } + else + mantissa = (uint32_t)((uint64_t)data << -mantShift); + mantissa &= 0x7fffff;//mask off the leading 1 + + uint32_t result = exponent | mantissa; + if (sign) + result |= 0x80000000; + if (!sign) + return as_float(result); // for positive inputs return RTZ result + else{ + if(inExact){ // for negative inputs find the lower next fp number + uint32_t low_float = 0xff7fffff; + return nextafterf(as_float(result), as_float(low_float)); // could be simplified with some inc and carry operation + } + else + return as_float(result); + } + } + } + return 0.0f; +} + +float qcom_u64_2_f32(uint64_t data, bool sat, roundingMode rnd) +{ + switch (rnd) { + case qcomRTZ: { + if (!data) + return 0.0f; + uint32_t exponent = (127 + 64 - clz(data) - 1) << (FLT_MANT_DIG - 1); //add 1 for the implied 1.0 in normalized fp32 numbers + int mantShift = 40 - clz(data); + uint32_t mantissa; + if (mantShift >= 0) + mantissa = (uint32_t)(data >> mantShift); + else + mantissa = (uint32_t)(data << -mantShift); + mantissa &= 0x7fffff;//mask off the leading 1 + + uint32_t result = exponent | mantissa; + return as_float(result); + break; + } + case qcomRTE: return (float)(data); break; + case qcomRTP: { + int inExact = 0; + if (!data) + return 0.0f; + uint32_t exponent = (127 + 64 - clz(data) - 1) << (FLT_MANT_DIG - 1); //add 1 for the implied 1.0 in normalized fp32 numbers + int mantShift = 40 - clz(data); + uint32_t mantissa; + if (mantShift >= 0){ + uint64_t temp = data >> mantShift; + uint64_t mask = (1 << mantShift) - 1; + if (temp << mantShift != data) + inExact = 1; + mantissa = (uint32_t)temp; + } + else + mantissa = (uint32_t)(data << -mantShift); + mantissa &= 0x7fffff;//mask off the leading 1 + + uint32_t result = exponent | mantissa; + if(inExact){ // for positive inputs return higher next fp + uint32_t high_float = 0x7f7fffff; + return nextafterf(as_float(result), as_float(high_float)); // could be simplified with some inc and carry operation + } + else + return as_float(result); + } + case qcomRTN: { + int inExact = 0; + if (!data) + return 0.0f; + uint32_t exponent = (127 + 64 - clz(data) - 1) << (FLT_MANT_DIG - 1); //add 1 for the implied 1.0 in normalized fp32 numbers + int mantShift = 40 - clz(data); + uint32_t mantissa; + if (mantShift >= 0){ + uint64_t temp = (uint64_t)data >> mantShift; + uint64_t mask = (1 << mantShift) - 1; + if (temp << mantShift != data) + inExact = 1; + mantissa = (uint32_t)temp; + } + else + mantissa = (uint32_t)((uint64_t)data << -mantShift); + mantissa &= 0x7fffff;//mask off the leading 1 + + uint32_t result = exponent | mantissa; + return as_float(result); // for positive inputs return RTZ result + } + } + return 0.0f; +} diff --git a/test_conformance/conversions/fplib.h b/test_conformance/conversions/fplib.h new file mode 100644 index 00000000..576e4afe --- /dev/null +++ b/test_conformance/conversions/fplib.h @@ -0,0 +1,29 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include + +typedef enum +{ + qcomRTZ = 0, + qcomRTE, + qcomRTP, + qcomRTN, + + qcomRoundingModeCount +}roundingMode; + +float qcom_u64_2_f32(uint64_t data, bool sat, roundingMode rnd); +float qcom_s64_2_f32(int64_t data, bool sat, roundingMode rnd); diff --git a/test_conformance/conversions/run_batch b/test_conformance/conversions/run_batch new file mode 100644 index 00000000..a99abeee --- /dev/null +++ b/test_conformance/conversions/run_batch @@ -0,0 +1,16 @@ +#!/usr/bin/csh +# +# This runs the conversions in 32- and 64-bit modes, split into 9 processes for better throughput. +# It is intended to allow for quicker debugging turnaround for code development purposes +# + +/usr/bin/arch -i386 ./test_conversions CL_DEVICE_TYPE_CPU 0 100 > 0_32.txt; /usr/bin/arch -x86_64 ./test_conversions CL_DEVICE_TYPE_CPU 0 100 > 0_64.txt & +/usr/bin/arch -i386 ./test_conversions CL_DEVICE_TYPE_CPU 100 100 > 1_32.txt; /usr/bin/arch -x86_64 ./test_conversions CL_DEVICE_TYPE_CPU 100 100 > 1_64.txt & +/usr/bin/arch -i386 ./test_conversions CL_DEVICE_TYPE_CPU 200 100 > 2_32.txt; /usr/bin/arch -x86_64 ./test_conversions CL_DEVICE_TYPE_CPU 200 100 > 2_64.txt & +/usr/bin/arch -i386 ./test_conversions CL_DEVICE_TYPE_CPU 300 100 > 3_32.txt; /usr/bin/arch -x86_64 ./test_conversions CL_DEVICE_TYPE_CPU 300 100 > 3_64.txt & +/usr/bin/arch -i386 ./test_conversions CL_DEVICE_TYPE_CPU 400 100 > 4_32.txt; /usr/bin/arch -x86_64 ./test_conversions CL_DEVICE_TYPE_CPU 400 100 > 4_64.txt & +/usr/bin/arch -i386 ./test_conversions CL_DEVICE_TYPE_CPU 500 100 > 5_32.txt; /usr/bin/arch -x86_64 ./test_conversions CL_DEVICE_TYPE_CPU 500 100 > 5_64.txt & +/usr/bin/arch -i386 ./test_conversions CL_DEVICE_TYPE_CPU 600 100 > 6_32.txt; /usr/bin/arch -x86_64 ./test_conversions CL_DEVICE_TYPE_CPU 600 100 > 6_64.txt & +/usr/bin/arch -i386 ./test_conversions CL_DEVICE_TYPE_CPU 700 100 > 7_32.txt; /usr/bin/arch -x86_64 ./test_conversions CL_DEVICE_TYPE_CPU 700 100 > 7_64.txt & +/usr/bin/arch -i386 ./test_conversions CL_DEVICE_TYPE_CPU 800 100 > 8_32.txt; /usr/bin/arch -x86_64 ./test_conversions CL_DEVICE_TYPE_CPU 800 100 > 8_64.txt & + diff --git a/test_conformance/conversions/test_conversions.c b/test_conformance/conversions/test_conversions.c new file mode 100644 index 00000000..fc6f6315 --- /dev/null +++ b/test_conformance/conversions/test_conversions.c @@ -0,0 +1,1865 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" +#include "../../test_common/harness/rounding_mode.h" +#include "../../test_common/harness/ThreadPool.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/parseParameters.h" +#if !defined(_WIN32) && !defined(__ANDROID__) +#include +#endif + +#if defined( __linux__ ) +#include +#include +#include +#endif +#if defined(__linux__) +#include +#include +#endif + +#include "mingw_compat.h" +#if defined(__MINGW32__) +#include +#endif + +#include +#include +#include +#if !defined(_WIN32) +#include +#include +#endif +#include + +#include "Sleep.h" +#include "basic_test_conversions.h" + +#pragma STDC FENV_ACCESS ON + +#if (defined(_WIN32) && defined (_MSC_VER)) +// need for _controlfp_s and rouinding modes in RoundingMode +#include "../../test_common/harness/testHarness.h" +#endif + +#pragma mark - +#pragma mark globals + +#define BUFFER_SIZE (1024*1024) +#define kPageSize 4096 +#define EMBEDDED_REDUCTION_FACTOR 16 +#define PERF_LOOP_COUNT 100 + +#define kCallStyleCount (kVectorSizeCount + 1 /* for implicit scalar */) + +#if defined( __arm__ ) && defined( __GNUC__ ) +#include "fplib.h" + extern bool qcom_sat; + extern roundingMode qcom_rm; +#endif + +const char ** argList = NULL; +int argCount = 0; +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +cl_device_id gDevice = NULL; +cl_context gContext = NULL; +cl_command_queue gQueue = NULL; +char appName[64] = "ctest"; +int gTestCount = 0; +int gFailCount = 0; +int gStartTestNumber = -1; +int gEndTestNumber = 0; +#if defined( __APPLE__ ) +int gTimeResults = 1; +#else +int gTimeResults = 0; +#endif +int gReportAverageTimes = 0; +void *gIn = NULL; +void *gRef = NULL; +void *gAllowZ = NULL; +void *gOut[ kCallStyleCount ] = { NULL }; +cl_mem gInBuffer; +cl_mem gOutBuffers[ kCallStyleCount ]; +size_t gComputeDevices = 0; +uint32_t gDeviceFrequency = 0; +int gWimpyMode = 0; +int gSkipTesting = 0; +int gForceFTZ = 0; +int gMultithread = 1; +int gIsRTZ = 0; +uint32_t gSimdSize = 1; +int gHasDouble = 0; +int gIsEmbedded = 0; +int gHasLong = 1; +int gTestDouble = 1; +cl_uint choosen_device_index = 0; +const char * sizeNames[] = { "", "", "2", "3", "4", "8", "16" }; +const int vectorSizes[] = { 1, 1, 2, 3, 4, 8, 16 }; +int gMinVectorSize = 0; +int gMaxVectorSize = sizeof(vectorSizes) / sizeof( vectorSizes[0] ); + +#pragma mark - +#pragma mark Declarations + +static int ParseArgs( int argc, const char **argv ); +static void PrintUsage( void ); +static void PrintArch(void); +static int InitCL( void ); +static int GetTestCase( const char *name, Type *outType, Type *inType, SaturationMode *sat, RoundingMode *round ); +static int DoTest( Type outType, Type inType, SaturationMode sat, RoundingMode round, MTdata d ); +static cl_program MakeProgram( Type outType, Type inType, SaturationMode sat, RoundingMode round, int vectorSize, cl_kernel *outKernel ); +static int RunKernel( cl_kernel kernel, void *inBuf, void *outBuf, size_t blockCount ); + +void *FlushToZero( void ); +void UnFlushToZero( void *); + +static cl_program CreateImplicitConvertProgram( Type outType, Type inType, SaturationMode sat, RoundingMode round, int vectorSize, char testName[256], cl_int *error ); +static cl_program CreateStandardProgram( Type outType, Type inType, SaturationMode sat, RoundingMode round, int vectorSize, char testName[256], cl_int *error ); + + +// Windows (since long double got deprecated) sets the x87 to 53-bit precision +// (that's x87 default state). This causes problems with the tests that +// convert long and ulong to float and double or otherwise deal with values +// that need more precision than 53-bit. So, set the x87 to 64-bit precision. +static inline void Force64BitFPUPrecision(void) +{ +#if __MINGW32__ + // The usual method is to use _controlfp as follows: + // #include + // _controlfp(_PC_64, _MCW_PC); + // + // _controlfp is available on MinGW32 but not on MinGW64. Instead of having + // divergent code just use inline assembly which works for both. + unsigned short int orig_cw = 0; + unsigned short int new_cw = 0; + __asm__ __volatile__ ("fstcw %0":"=m" (orig_cw)); + new_cw = orig_cw | 0x0300; // set precision to 64-bit + __asm__ __volatile__ ("fldcw %0"::"m" (new_cw)); +#else + /* Implement for other platforms if needed */ +#endif +} + + +#pragma mark - + +int main (int argc, const char **argv ) +{ + int error, i, testNumber = -1; + Type inType, outType; + RoundingMode round; + SaturationMode sat; + MTdata d = NULL; + cl_uint seed = (cl_uint) time( NULL ); + + test_start(); + argc = parseCustomParam(argc, argv); + if (argc == -1) + { + test_finish(); + return -1; + } + + if( (error = ParseArgs( argc, argv )) ) + return error; + + //Turn off sleep so our tests run to completion + PreventSleep(); + atexit( ResumeSleep ); + + // Init CL data structures + if( (error = InitCL()) ) + return error; + + if(!gMultithread) + SetThreadCount(1); + +#if defined(_MSC_VER) && defined(_M_IX86) + // VS2005 (and probably others, since long double got deprecated) sets + // the x87 to 53-bit precision. This causes problems with the tests + // that convert long and ulong to float and double, since they deal + // with values that need more precision than that. So, set the x87 + // to 64-bit precision. + unsigned int ignored; + _controlfp_s(&ignored, _PC_64, _MCW_PC); +#endif + + vlog( "===========================================================\n" ); + vlog( "Random seed: %u\n", seed ); + d = init_genrand( seed ); + int startMinVectorSize = gMinVectorSize; + if( argCount ) + { + for( i = 0; i < argCount; i++ ) + { + if( GetTestCase( argList[i], &outType, &inType, &sat, &round ) ) + { + vlog_error( "\n\t\t**** ERROR: Unable to parse function name %s. Skipping.... *****\n\n", argList[i] ); + continue; + } + + // skip double if we don't have it + if( !gTestDouble && (inType == kdouble || outType == kdouble ) ) + { + if( gHasDouble ) + { + vlog_error( "\t *** convert_%sn%s%s( %sn ) FAILED ** \n", gTypeNames[ outType ], gSaturationNames[ sat ], gRoundingModeNames[round], gTypeNames[inType] ); + vlog( "\t\tcl_khr_fp64 enabled, but double testing turned off.\n" ); + } + + continue; + } + + // skip longs on embedded + if( ! gHasLong && + (inType == klong || outType == klong || inType == kulong || outType == kulong)) + continue; + + // Skip the implicit converts if the rounding mode is not default or test is saturated + if( 0 == startMinVectorSize ) + { + if( sat || round != kDefaultRoundingMode ) + gMinVectorSize = 1; + else + gMinVectorSize = 0; + } + + if( (error = DoTest( outType, inType, sat, round, d )) ) + vlog_error( "\t *** convert_%sn%s%s( %sn ) FAILED ** \n", gTypeNames[ outType ], gSaturationNames[ sat ], gRoundingModeNames[round], gTypeNames[inType] ); + } + } + else + { + + for( outType = (Type)0; outType < kTypeCount; outType = (Type)(outType+1) ) + { + for( inType = (Type)0; inType < kTypeCount; inType = (Type)(inType+1) ) + { + // skip longs on embedded + if( ! gHasLong && + (inType == klong || outType == klong || inType == kulong || outType == kulong)) + continue; + + for( sat = (SaturationMode)0; sat < kSaturationModeCount; sat = (SaturationMode)(sat+1) ) + { + //skip illegal saturated conversions to float type + if( kSaturated == sat && ( outType == kfloat || outType == kdouble ) ) + continue; + + for( round = (RoundingMode)0; round < kRoundingModeCount; round = (RoundingMode)(round+1) ) + { + if( ++testNumber < gStartTestNumber ) + { + // vlog( "%d) skipping convert_%sn%s%s( %sn )\n", testNumber, gTypeNames[ outType ], gSaturationNames[ sat ], gRoundingModeNames[round], gTypeNames[inType] ); + continue; + } + else + if( gEndTestNumber > 0 && testNumber >= gEndTestNumber ) + goto exit; + + vlog( "%d) Testing convert_%sn%s%s( %sn ):\n", testNumber, gTypeNames[ outType ], gSaturationNames[ sat ], gRoundingModeNames[round], gTypeNames[inType] ); + + // skip double if we don't have it + if( ! gTestDouble && (inType == kdouble || outType == kdouble ) ) + { + if( gHasDouble ) + { + vlog_error( "\t *** %d) convert_%sn%s%s( %sn ) FAILED ** \n", testNumber, gTypeNames[ outType ], gSaturationNames[ sat ], gRoundingModeNames[round], gTypeNames[inType] ); + vlog( "\t\tcl_khr_fp64 enabled, but double testing turned off.\n" ); + } + continue; + } + + // Skip the implicit converts if the rounding mode is not default or test is saturated + if( 0 == startMinVectorSize ) + { + if( sat || round != kDefaultRoundingMode ) + gMinVectorSize = 1; + else + gMinVectorSize = 0; + } + + if( (error = DoTest( outType, inType, sat, round, d) ) ) + vlog_error( "\t *** %d) convert_%sn%s%s( %sn ) FAILED ** \n", testNumber, gTypeNames[ outType ], gSaturationNames[ sat ], gRoundingModeNames[round], gTypeNames[inType] ); + } + } + } + } + } + +exit: + free_mtdata(d); + vlog( "\n\n" ); + vlog( "Tests completed: %d\n", gTestCount ); + + error = clFinish(gQueue); + if (error) + vlog_error("clFinish failed: %d\n", error); + + if (gFailCount == 0 && gTestCount >= 0) { + vlog("PASSED %d of %d tests.\n", gTestCount, gTestCount); + } else if (gFailCount > 0) { + vlog_error("FAILED %d of %d tests.\n", gFailCount, gTestCount); + } + + clReleaseMemObject(gInBuffer); + + for( i = 0; i < kCallStyleCount; i++ ) { + clReleaseMemObject(gOutBuffers[i]); + } + clReleaseCommandQueue(gQueue); + clReleaseContext(gContext); + + test_finish(); + if (gFailCount > 0) + return -1; + + return 0; +} + +#pragma mark - +#pragma mark setup + +static int ParseArgs( int argc, const char **argv ) +{ + int i; + argList = (const char **)calloc( argc - 1, sizeof( char*) ); + argCount = 0; + + if( NULL == argList && argc > 1 ) + return -1; + +#if (defined( __APPLE__ ) || defined(__linux__) || defined (__MINGW32__)) + { // Extract the app name + char baseName[ MAXPATHLEN ]; + strncpy( baseName, argv[0], MAXPATHLEN ); + char *base = basename( baseName ); + if( NULL != base ) + { + strncpy( appName, base, sizeof( appName ) ); + appName[ sizeof( appName ) -1 ] = '\0'; + } + } +#elif defined (_WIN32) + { + char fname[_MAX_FNAME + _MAX_EXT + 1]; + char ext[_MAX_EXT]; + + errno_t err = _splitpath_s( argv[0], NULL, 0, NULL, 0, + fname, _MAX_FNAME, ext, _MAX_EXT ); + if (err == 0) { // no error + strcat (fname, ext); //just cat them, size of frame can keep both + strncpy (appName, fname, sizeof(appName)); + appName[ sizeof( appName ) -1 ] = '\0'; + } + } +#endif + + /* Check for environment variable to set device type */ + char *env_mode = getenv( "CL_DEVICE_TYPE" ); + if( env_mode != NULL ) + { + vlog( "CL_DEVICE_TYPE: %s\n", env_mode ); + if( strcmp( env_mode, "gpu" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_GPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_GPU; + else if( strcmp( env_mode, "cpu" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_CPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_CPU; + else if( strcmp( env_mode, "accelerator" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( env_mode, "default" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_DEFAULT; + else + { + vlog_error( "Unknown CL_DEVICE_TYPE env variable setting: %s.\nAborting...\n", env_mode ); + abort(); + } + } + + + vlog( "\n%s", appName ); + for( i = 1; i < argc; i++ ) + { + const char *arg = argv[i]; + if( NULL == arg ) + break; + + vlog( "\t%s", arg ); + if( arg[0] == '-' ) + { + arg++; + while( *arg != '\0' ) + { + switch( *arg ) + { + case 'd': + gTestDouble ^= 1; + break; + case 'l': + gSkipTesting ^= 1; + break; + case 'm': + gMultithread ^= 1; + break; + case 'w': + gWimpyMode ^= 1; + break; + case 'z': + gForceFTZ ^= 1; + break; + case 't': + gTimeResults ^= 1; + break; + case 'a': + gReportAverageTimes ^= 1; + break; + case '1': + if( arg[1] == '6' ) + { + gMinVectorSize = 6; + gMaxVectorSize = 7; + arg++; + } + else + { + gMinVectorSize = 0; + gMaxVectorSize = 2; + } + break; + + case '2': + gMinVectorSize = 2; + gMaxVectorSize = 3; + break; + + case '3': + gMinVectorSize = 3; + gMaxVectorSize = 4; + break; + + case '4': + gMinVectorSize = 4; + gMaxVectorSize = 5; + break; + + case '8': + gMinVectorSize = 5; + gMaxVectorSize = 6; + break; + + default: + vlog( " <-- unknown flag: %c (0x%2.2x)\n)", *arg, *arg ); + PrintUsage(); + return -1; + } + arg++; + } + } + // Check if a particular device id was requested + else if (strlen(argv[i]) >= 3 && argv[i][0] == 'i' && argv[i][1] =='d') + { + choosen_device_index = atoi(&(argv[i][2])); + } + else + { + char *t = NULL; + long number = strtol( arg, &t, 0 ); + if( t != arg ) + { + if( gStartTestNumber != -1 ) + gEndTestNumber = gStartTestNumber + (int) number; + else + gStartTestNumber = (int) number; + } + else if( 0 == strcmp( arg, "CL_DEVICE_TYPE_CPU")) + gDeviceType = CL_DEVICE_TYPE_CPU; + else if( 0 == strcmp( arg, "CL_DEVICE_TYPE_GPU")) + gDeviceType = CL_DEVICE_TYPE_GPU; + else if( 0 == strcmp( arg, "CL_DEVICE_TYPE_ACCELERATOR")) + gDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + else if( 0 == strcmp( arg, "CL_DEVICE_TYPE_DEFAULT")) + gDeviceType = CL_DEVICE_TYPE_DEFAULT; + else + { + argList[ argCount ] = arg; + argCount++; + } + } + } + + // Check for the wimpy mode environment variable + if (getenv("CL_WIMPY_MODE")) { + vlog( "\n" ); + vlog( "*** Detected CL_WIMPY_MODE env ***\n" ); + gWimpyMode = 1; + } + + vlog( "\n" ); + + vlog( "Test binary built %s %s\n", __DATE__, __TIME__ ); + + PrintArch(); + + if( gWimpyMode ) + { + vlog( "\n" ); + vlog( "*** WARNING: Testing in Wimpy mode! ***\n" ); + vlog( "*** Wimpy mode is not sufficient to verify correctness. ***\n" ); + vlog( "*** It gives warm fuzzy feelings and then nevers calls. ***\n\n" ); + } + + return 0; +} + +static void PrintUsage( void ) +{ + int i; + vlog( "%s [-wz#]: \n", appName ); + vlog( "\ttest names:\n" ); + vlog( "\t\tdestFormat<_sat><_round>_sourceFormat\n" ); + vlog( "\t\t\tPossible format types are:\n\t\t\t\t" ); + for( i = 0; i < kTypeCount; i++ ) + vlog( "%s, ", gTypeNames[i] ); + vlog( "\n\n\t\t\tPossible saturation values are: (empty) and _sat\n" ); + vlog( "\t\t\tPossible rounding values are:\n\t\t\t\t(empty), " ); + for( i = 1; i < kRoundingModeCount; i++ ) + vlog( "%s, ", gRoundingModeNames[i] ); + vlog( "\n\t\t\tExamples:\n" ); + vlog( "\t\t\t\tulong_short converts short to ulong\n" ); + vlog( "\t\t\t\tchar_sat_rte_float converts float to char with saturated clipping in round to nearest rounding mode\n\n" ); + vlog( "\toptions:\n" ); + vlog( "\t\t-d\tToggle testing of double precision. On by default if cl_khr_fp64 is enabled, ignored otherwise.\n" ); + vlog( "\t\t-l\tToggle link check mode. When on, testing is skipped, and we just check to see that the kernels build. (Off by default.)\n" ); + vlog( "\t\t-m\tToggle Multithreading. (On by default.)\n" ); + vlog( "\t\t-w\tToggle wimpy mode. When wimpy mode is on, we run a very small subset of the tests for each fn. NOT A VALID TEST! (Off by default.)\n" ); + vlog( "\t\t-z\tToggle flush to zero mode (Default: per device)\n" ); + vlog( "\t\t-#\tTest just vector size given by #, where # is an element of the set {1,2,3,4,8,16}\n" ); + vlog( "\n" ); + vlog( "You may also pass the number of the test on which to start.\nA second number can be then passed to indicate how many tests to run\n\n" ); +} + +static void PrintArch( void ) +{ + vlog( "sizeof( void*) = %ld\n", sizeof( void *) ); +#if defined( __ppc__ ) + vlog( "ARCH:\tppc\n" ); +#elif defined( __ppc64__ ) + vlog( "ARCH:\tppc64\n" ); +#elif defined( __PPC__ ) + vlog( "ARCH:\tppc\n" ); +#elif defined( __i386__ ) + vlog( "ARCH:\ti386\n" ); +#elif defined( __x86_64__ ) + vlog( "ARCH:\tx86_64\n" ); +#elif defined( __arm__ ) + vlog( "ARCH:\tarm\n" ); +// Add 64 bit support +#elif defined(__aarch64__) + vlog( "ARCH:\taarch64\n" ); +#elif defined (_WIN32) + vlog( "ARCH:\tWindows\n" ); +#else +#error unknown arch +#endif + +#if defined( __APPLE__ ) + + int type = 0; + size_t typeSize = sizeof( type ); + sysctlbyname( "hw.cputype", &type, &typeSize, NULL, 0 ); + vlog( "cpu type:\t%d\n", type ); + typeSize = sizeof( type ); + sysctlbyname( "hw.cpusubtype", &type, &typeSize, NULL, 0 ); + vlog( "cpu subtype:\t%d\n", type ); + +#elif defined( __linux__ ) && !defined(__aarch64__) +#define OSNAMESZ 100 + int _sysctl(struct __sysctl_args *args ); + + struct __sysctl_args args; + char osname[OSNAMESZ]; + size_t osnamelth; + int name[] = { CTL_KERN, KERN_OSTYPE }; + memset(&args, 0, sizeof(struct __sysctl_args)); + args.name = name; + args.nlen = sizeof(name)/sizeof(name[0]); + args.oldval = osname; + args.oldlenp = &osnamelth; + + osnamelth = sizeof(osname); + + if (syscall(SYS__sysctl, &args) == -1) { + vlog( "_sysctl error\n" ); + } + else { + vlog("this machine is running %*s\n", osnamelth, osname); + } + +#endif +} + + + + + +static int GetTestCase( const char *name, Type *outType, Type *inType, SaturationMode *sat, RoundingMode *round ) +{ + int i; + + //Find the return type + for( i = 0; i < kTypeCount; i++ ) + if( name == strstr( name, gTypeNames[i] ) ) + { + *outType = (Type)i; + name += strlen( gTypeNames[i] ); + + break; + } + + if( i == kTypeCount ) + return -1; + + // Check to see if _sat appears next + *sat = (SaturationMode)0; + for( i = 1; i < kSaturationModeCount; i++ ) + if( name == strstr( name, gSaturationNames[i] ) ) + { + *sat = (SaturationMode)i; + name += strlen( gSaturationNames[i] ); + break; + } + + *round = (RoundingMode)0; + for( i = 1; i < kRoundingModeCount; i++ ) + if( name == strstr( name, gRoundingModeNames[i] ) ) + { + *round = (RoundingMode)i; + name += strlen( gRoundingModeNames[i] ); + break; + } + + if( *name != '_' ) + return -2; + name++; + + for( i = 0; i < kTypeCount; i++ ) + if( name == strstr( name, gTypeNames[i] ) ) + { + *inType = (Type)i; + name += strlen( gTypeNames[i] ); + + break; + } + + if( i == kTypeCount ) + return -3; + + if( *name != '\0' ) + return -4; + + return 0; +} + +#pragma mark - +#pragma mark OpenCL + +static void CL_CALLBACK notify_callback(const char *errinfo, const void *private_info, size_t cb, void *user_data) +{ + vlog( "%s\n", errinfo ); +} + +static int InitCL( void ) +{ + int error, i; + size_t configSize = sizeof( gComputeDevices ); + + cl_platform_id platform = NULL; + cl_uint num_devices = 0; + cl_device_id *devices = NULL; + + /* Get the platform */ + error = clGetPlatformIDs(1, &platform, NULL); + if (error) { + vlog_error( "clGetPlatformIDs failed: %d\n", error ); + return error; + } + + /* Get the number of requested devices */ + error = clGetDeviceIDs(platform, gDeviceType, 0, NULL, &num_devices ); + if (error) { + vlog_error( "clGetDeviceIDs failed: %d\n", error ); + return error; + } + + devices = (cl_device_id *) malloc( num_devices * sizeof( cl_device_id ) ); + if (!devices || choosen_device_index >= num_devices) { + vlog_error( "device index out of range -- choosen_device_index (%d) >= num_devices (%d)\n", choosen_device_index, num_devices ); + return -1; + } + + /* Get the requested device */ + error = clGetDeviceIDs(platform, gDeviceType, num_devices, devices, NULL ); + if (error) { + vlog_error( "clGetDeviceIDs failed: %d\n", error ); + return error; + } + + gDevice = devices[choosen_device_index]; + free(devices); + devices = NULL; + + if( (error = clGetDeviceInfo( gDevice, CL_DEVICE_MAX_COMPUTE_UNITS, configSize, &gComputeDevices, NULL )) ) + gComputeDevices = 1; + + configSize = sizeof( gDeviceFrequency ); + if( (error = clGetDeviceInfo( gDevice, CL_DEVICE_MAX_CLOCK_FREQUENCY, configSize, &gDeviceFrequency, NULL )) ) + gDeviceFrequency = 0; + + cl_device_fp_config floatCapabilities = 0; + if( (error = clGetDeviceInfo(gDevice, CL_DEVICE_SINGLE_FP_CONFIG, sizeof(floatCapabilities), &floatCapabilities, NULL))) + floatCapabilities = 0; + if(0 == (CL_FP_DENORM & floatCapabilities) ) + gForceFTZ ^= 1; + + if( 0 == (floatCapabilities & CL_FP_ROUND_TO_NEAREST ) ) + { + char profileStr[128] = ""; + // Verify that we are an embedded profile device + if( (error = clGetDeviceInfo( gDevice, CL_DEVICE_PROFILE, sizeof( profileStr ), profileStr, NULL ) ) ) + { + vlog_error( "FAILURE: Could not get device profile: error %d\n", error ); + return -1; + } + + if( strcmp( profileStr, "EMBEDDED_PROFILE" ) ) + { + vlog_error( "FAILURE: non-embedded profile device does not support CL_FP_ROUND_TO_NEAREST\n" ); + return -1; + } + + if( 0 == (floatCapabilities & CL_FP_ROUND_TO_ZERO ) ) + { + vlog_error( "FAILURE: embedded profile device supports neither CL_FP_ROUND_TO_NEAREST or CL_FP_ROUND_TO_ZERO\n" ); + return -1; + } + + gIsRTZ = 1; + } + + char extensions[2048] = ""; + if( (error = clGetDeviceInfo( gDevice, CL_DEVICE_EXTENSIONS, sizeof( extensions ), extensions, NULL ) ) ) + { + vlog_error( "FAILURE: unable to get device info for CL_DEVICE_EXTENSIONS!" ); + return -1; + } + else if( strstr( extensions, "cl_khr_fp64" ) ) + { + gHasDouble = 1; + } + gTestDouble &= gHasDouble; + + //detect whether profile of the device is embedded + char profile[1024] = ""; + if( (error = clGetDeviceInfo( gDevice, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL ) ) ){} + else if( strstr(profile, "EMBEDDED_PROFILE" ) ) + { + gIsEmbedded = 1; + if( !strstr( extensions, "cles_khr_int64" ) ) + gHasLong = 0; + } + + + gContext = clCreateContext( NULL, 1, &gDevice, notify_callback, NULL, &error ); + if( NULL == gDevice || error ) + { + vlog_error( "clCreateContext failed. (%d)\n", error ); + return error; + } + + gQueue = clCreateCommandQueueWithProperties(gContext, gDevice, 0, &error); + if( NULL == gQueue || error ) + { + vlog_error( "clCreateCommandQueue failed. (%d)\n", error ); + return error; + } + + //Allocate buffers + //FIXME: use clProtectedArray for guarded allocations? + gIn = malloc( BUFFER_SIZE + 2 * kPageSize ); + gAllowZ = malloc( BUFFER_SIZE + 2 * kPageSize ); + gRef = malloc( BUFFER_SIZE + 2 * kPageSize ); + for( i = 0; i < kCallStyleCount; i++ ) + { + gOut[i] = malloc( BUFFER_SIZE + 2 * kPageSize ); + if( NULL == gOut[i] ) + return -3; + } + + // setup input buffers + gInBuffer = clCreateBuffer(gContext, CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, BUFFER_SIZE, NULL, &error); + if( gInBuffer == NULL || error) + { + vlog_error( "clCreateBuffer failed for input (%d)\n", error ); + return error; + } + + // setup output buffers + for( i = 0; i < kCallStyleCount; i++ ) + { + gOutBuffers[i] = clCreateBuffer( gContext, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, BUFFER_SIZE, NULL, &error ); + if( gOutBuffers[i] == NULL || error ) + { + vlog_error( "clCreateArray failed for output (%d)\n", error ); + return error; + } + } + +#if defined( __APPLE__ ) + +#if defined( __i386__ ) || defined( __x86_64__ ) +#define kHasSSE3 0x00000008 +#define kHasSupplementalSSE3 0x00000100 +#define kHasSSE4_1 0x00000400 +#define kHasSSE4_2 0x00000800 + /* check our environment for a hint to disable SSE variants */ + { + const char *env = getenv( "CL_MAX_SSE" ); + if( env ) + { + extern int _cpu_capabilities; + int mask = 0; + if( 0 == strcasecmp( env, "SSE4.1" ) ) + mask = kHasSSE4_2; + else if( 0 == strcasecmp( env, "SSSE3" ) ) + mask = kHasSSE4_2 | kHasSSE4_1; + else if( 0 == strcasecmp( env, "SSE3" ) ) + mask = kHasSSE4_2 | kHasSSE4_1 | kHasSupplementalSSE3; + else if( 0 == strcasecmp( env, "SSE2" ) ) + mask = kHasSSE4_2 | kHasSSE4_1 | kHasSupplementalSSE3 | kHasSSE3; + else + { + vlog_error( "Error: Unknown CL_MAX_SSE setting: %s\n", env ); + return -2; + } + + vlog( "*** Environment: CL_MAX_SSE = %s ***\n", env ); + _cpu_capabilities &= ~mask; + } + } +#endif +#endif + + + char c[1024]; + static const char *no_yes[] = { "NO", "YES" }; + vlog( "\nCompute Device info:\n" ); + clGetDeviceInfo(gDevice, CL_DEVICE_NAME, sizeof(c), c, NULL); + vlog( "\tDevice Name: %s\n", c ); + clGetDeviceInfo(gDevice, CL_DEVICE_VENDOR, sizeof(c), c, NULL); + vlog( "\tVendor: %s\n", c ); + clGetDeviceInfo(gDevice, CL_DEVICE_VERSION, sizeof(c), c, NULL); + vlog( "\tDevice Version: %s\n", c ); + clGetDeviceInfo(gDevice, CL_DEVICE_OPENCL_C_VERSION, sizeof(c), &c, NULL); + vlog( "\tCL C Version: %s\n", c ); + clGetDeviceInfo(gDevice, CL_DRIVER_VERSION, sizeof(c), c, NULL); + vlog( "\tDriver Version: %s\n", c ); + vlog( "\tProcessing with %ld devices\n", gComputeDevices ); + vlog( "\tDevice Frequency: %d MHz\n", gDeviceFrequency ); + vlog( "\tSubnormal values supported for floats? %s\n", no_yes[0 != (CL_FP_DENORM & floatCapabilities)] ); + vlog( "\tTesting with FTZ mode ON for floats? %s\n", no_yes[0 != gForceFTZ] ); + vlog( "\tTesting with default RTZ mode for floats? %s\n", no_yes[0 != gIsRTZ] ); + vlog( "\tHas Double? %s\n", no_yes[0 != gHasDouble] ); + if( gHasDouble ) + vlog( "\tTest Double? %s\n", no_yes[0 != gTestDouble] ); + vlog( "\tHas Long? %s\n", no_yes[0 != gHasLong] ); + vlog( "\tTesting vector sizes: " ); + for( i = gMinVectorSize; i < gMaxVectorSize; i++ ) + vlog("\t%d", vectorSizes[i]); + vlog( "\n" ); + return 0; +} + +static int RunKernel( cl_kernel kernel, void *inBuf, void *outBuf, size_t blockCount ) +{ + // The global dimensions are just the blockCount to execute since we haven't set up multiple queues for multiple devices. + int error; + + error = clSetKernelArg(kernel, 0, sizeof( inBuf ), &inBuf); + error |= clSetKernelArg(kernel, 1, sizeof(outBuf), &outBuf); + + if( error ) + { + vlog_error( "FAILED -- could not set kernel args (%d)\n", error ); + return error; + } + + if( (error = clEnqueueNDRangeKernel(gQueue, kernel, 1, NULL, &blockCount, NULL, 0, NULL, NULL))) + { + vlog_error( "FAILED -- could not execute kernel (%d)\n", error ); + return error; + } + + return 0; +} + +#if ! defined( __APPLE__ ) +static void memset_pattern4(void *dest, const void *src_pattern, size_t bytes ); +static void memset_pattern4(void *dest, const void *src_pattern, size_t bytes ) +{ + uint32_t pat = ((uint32_t*) src_pattern)[0]; + size_t count = bytes / 4; + size_t i; + uint32_t *d = (uint32_t *)dest; + + for( i = 0; i < count; i++ ) + d[i] = pat; + + d += i; + + bytes &= 3; + if( bytes ) + memcpy( d, src_pattern, bytes ); +} + +#endif + +#if defined( __APPLE__ ) +#include +#endif + +uint64_t GetTime( void ); +uint64_t GetTime( void ) +{ +#if defined( __APPLE__ ) + return mach_absolute_time(); +#elif defined(_MSC_VER) + return ReadTime(); +#else + //mach_absolute_time is a high precision timer with precision < 1 microsecond. +#warning need accurate clock here. Times are invalid. + return 0; +#endif +} + + +#if defined (_MSC_VER) +/* function is defined in "compat.h" */ +#else +double SubtractTime( uint64_t endTime, uint64_t startTime ); +double SubtractTime( uint64_t endTime, uint64_t startTime ) +{ + uint64_t diff = endTime - startTime; + static double conversion = 0.0; + + if( 0.0 == conversion ) + { +#if defined( __APPLE__ ) + mach_timebase_info_data_t info = {0,0}; + kern_return_t err = mach_timebase_info( &info ); + if( 0 == err ) + conversion = 1e-9 * (double) info.numer / (double) info.denom; +#else + // This function consumes output from GetTime() above, and converts the time to secionds. +#warning need accurate ticks to seconds conversion factor here. Times are invalid. +#endif + } + + // strictly speaking we should also be subtracting out timer latency here + return conversion * (double) diff; +} +#endif + +typedef struct CalcReferenceValuesInfo +{ + struct WriteInputBufferInfo *parent; // pointer back to the parent WriteInputBufferInfo struct + cl_kernel kernel; // the kernel for this vector size + cl_program program; // the program for this vector size + cl_uint vectorSize; // the vector size for this callback chain + void *p; // the pointer to mapped result data for this vector size + cl_int result; +}CalcReferenceValuesInfo; + +typedef struct WriteInputBufferInfo +{ + volatile cl_event calcReferenceValues; // user event which signals when main thread is done calculating reference values + volatile cl_event doneBarrier; // user event which signals when worker threads are done + cl_uint count; // the number of elements in the array + Type outType; // the data type of the conversion result + Type inType; // the data type of the conversion input + volatile int barrierCount; + CalcReferenceValuesInfo calcInfo[kCallStyleCount]; +}WriteInputBufferInfo; + +cl_uint RoundUpToNextPowerOfTwo( cl_uint x ); +cl_uint RoundUpToNextPowerOfTwo( cl_uint x ) +{ + if( 0 == (x & (x-1))) + return x; + + while( x & (x-1) ) + x &= x-1; + + return x + x; +} + +void CL_CALLBACK WriteInputBufferComplete( cl_event, cl_int, void * ); + +typedef struct DataInitInfo +{ + cl_ulong start; + cl_uint size; + Type outType; + Type inType; + SaturationMode sat; + RoundingMode round; + MTdata *d; +}DataInitInfo; + +cl_int InitData( cl_uint job_id, cl_uint thread_id, void *p ); +cl_int InitData( cl_uint job_id, cl_uint thread_id, void *p ) +{ + DataInitInfo *info = (DataInitInfo*) p; + + gInitFunctions[ info->inType ]( (char*)gIn + job_id * info->size * gTypeSizes[info->inType], info->sat, info->round, + info->outType, info->start + job_id * info->size, info->size, info->d[thread_id] ); + return CL_SUCCESS; +} + +static void setAllowZ(uint8_t *allow, uint32_t *x, cl_uint count) +{ + cl_uint i; + for (i = 0; i < count; ++i) + allow[i] |= (uint8_t)((x[i] & 0x7f800000U) == 0); +} + +cl_int PrepareReference( cl_uint job_id, cl_uint thread_id, void *p ); +cl_int PrepareReference( cl_uint job_id, cl_uint thread_id, void *p ) +{ + DataInitInfo *info = (DataInitInfo*) p; + cl_uint count = info->size; + Type inType = info->inType; + Type outType = info->outType; + RoundingMode round = info->round; + size_t j; + + Force64BitFPUPrecision(); + + void *s = (cl_uchar*) gIn + job_id * count * gTypeSizes[info->inType]; + void *a = (cl_uchar*) gAllowZ + job_id * count; + void *d = (cl_uchar*) gRef + job_id * count * gTypeSizes[info->outType]; + + if (outType != inType) + { + //create the reference while we wait + Convert f = gConversions[ outType ][ inType ]; + if( info->sat ) + f = gSaturatedConversions[ outType ][ inType ]; + +#if defined( __arm__ ) && defined( __GNUC__ ) + /* ARM VFP doesn't have hardware instruction for converting from 64-bit integer to float types, hence GCC ARM uses the floating-point emulation code + * despite which -mfloat-abi setting it is. But the emulation code in libgcc.a has only one rounding mode (round to nearest even in this case) + * and ignores the user rounding mode setting in hardware. + * As a result setting rounding modes in hardware won't give correct rounding results for type covert from 64-bit integer to float using GCC for ARM compiler + * so for testing different rounding modes, we need to use alternative reference function */ + switch (round) + { + /* conversions to floating-point type use the current rounding mode. + * The only default floating-point rounding mode supported is round to nearest even + * i.e the current rounding mode will be _rte for floating-point types. */ + case kDefaultRoundingMode: + qcom_rm = qcomRTE; + break; + case kRoundToNearestEven: + qcom_rm = qcomRTE; + break; + case kRoundUp: + qcom_rm = qcomRTP; + break; + case kRoundDown: + qcom_rm = qcomRTN; + break; + case kRoundTowardZero: + qcom_rm = qcomRTZ; + break; + default: + vlog_error("ERROR: undefined rounding mode %d\n", round); + break; + } + qcom_sat = info->sat; +#endif + + RoundingMode oldRound = set_round( round, outType ); + f( d, s, count ); + set_round( oldRound, outType ); + + // Decide if we allow a zero result in addition to the correctly rounded one + memset(a, 0, count); + if (gForceFTZ) { + if (inType == kfloat) + setAllowZ((uint8_t*)a, (uint32_t*)s, count); + if (outType == kfloat) + setAllowZ((uint8_t*)a, (uint32_t*)d, count); + } + } + else + { + // Copy the input to the reference + memcpy(d, s, info->size * gTypeSizes[inType]); + } + + //Patch up NaNs conversions to integer to zero -- these can be converted to any integer + if( info->outType != kfloat && info->outType != kdouble ) + { + if( inType == kfloat ) + { + float *inp = (float*) s; + for( j = 0; j < count; j++ ) + { + if( isnan( inp[j] ) ) + memset( (char*) d + j * gTypeSizes[ outType ], 0, gTypeSizes[ outType ] ); + } + } + if( inType == kdouble ) + { + double *inp = (double*) s; + for( j = 0; j < count; j++ ) + { + if( isnan( inp[j] ) ) + memset( (char*) d + j * gTypeSizes[ outType ], 0, gTypeSizes[ outType ] ); + } + } + } + else if( inType == kfloat || inType == kdouble ) + { // outtype and intype is float or double. NaN conversions for float <-> double can be any NaN + if( inType == kfloat && outType == kdouble ) + { + float *inp = (float*) s; + for( j = 0; j < count; j++ ) + { + if( isnan( inp[j] ) ) + ((double*) d)[j] = NAN; + } + } + if( inType == kdouble && outType == kfloat ) + { + double *inp = (double*) s; + for( j = 0; j < count; j++ ) + { + if( isnan( inp[j] ) ) + ((float*) d)[j] = NAN; + } + } + } + + return CL_SUCCESS; +} + +static int DoTest( Type outType, Type inType, SaturationMode sat, RoundingMode round, MTdata d ) +{ +#ifdef __APPLE__ + cl_ulong wall_start = mach_absolute_time(); +#endif + + DataInitInfo init_info = { 0, 0, outType, inType, sat, round, NULL }; + WriteInputBufferInfo writeInputBufferInfo; + int vectorSize; + int error = 0; + cl_uint threads = GetThreadCount(); + uint64_t i; + + gTestCount++; + size_t blockCount = BUFFER_SIZE / MAX( gTypeSizes[ inType ], gTypeSizes[ outType ] ); + size_t step = blockCount; + uint64_t lastCase = 1ULL << (8*gTypeSizes[ inType ]); + cl_event writeInputBuffer = NULL; + + memset( &writeInputBufferInfo, 0, sizeof( writeInputBufferInfo ) ); + init_info.d = (MTdata*)malloc( threads * sizeof( MTdata ) ); + if( NULL == init_info.d ) + { + vlog_error( "ERROR: Unable to allocate storage for random number generator!\n" ); + return -1; + } + for( i = 0; i < threads; i++ ) + { + init_info.d[i] = init_genrand( genrand_int32( d ) ); + if( NULL == init_info.d[i] ) + { + vlog_error( "ERROR: Unable to allocate storage for random number generator!\n" ); + return -1; + } + } + + writeInputBufferInfo.outType = outType; + writeInputBufferInfo.inType = inType; + + for( vectorSize = gMinVectorSize; vectorSize < gMaxVectorSize; vectorSize++) + { + writeInputBufferInfo.calcInfo[vectorSize].program = MakeProgram( outType, inType, sat, round, vectorSize, + &writeInputBufferInfo.calcInfo[vectorSize].kernel ); + if( NULL == writeInputBufferInfo.calcInfo[vectorSize].program ) + { + gFailCount++; + return -1; + } + if( NULL == writeInputBufferInfo.calcInfo[vectorSize].kernel ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create kernel.\n" ); + return -2; + } + + writeInputBufferInfo.calcInfo[vectorSize].parent = &writeInputBufferInfo; + writeInputBufferInfo.calcInfo[vectorSize].vectorSize = vectorSize; + writeInputBufferInfo.calcInfo[vectorSize].result = -1; + } + + if( gSkipTesting ) + goto exit; + + // Patch up rounding mode if default is RTZ + // We leave the part above in default rounding mode so that the right kernel is compiled. + if( round == kDefaultRoundingMode && gIsRTZ && (outType == kfloat) ) + init_info.round = round = kRoundTowardZero; + + // Figure out how many elements are in a work block + + // we handle 64-bit types a bit differently. + if( 8*gTypeSizes[ inType ] > 32 ) + lastCase = 0x100000000ULL; + + if ( !gWimpyMode && gIsEmbedded ) + step = blockCount * EMBEDDED_REDUCTION_FACTOR; + + vlog( "Testing... " ); + fflush(stdout); + for( i = 0; i < (uint64_t)lastCase; i += step ) + { + if (gWimpyMode) { + uint64_t blockIndex = (i / blockCount) & 0xFF; + if (blockIndex != 0 && blockIndex != 0xFF) + continue; + } + + if( 0 == ( i & ((lastCase >> 3) -1))) { + vlog("."); + fflush(stdout); + } + + cl_uint count = (uint32_t) MIN( blockCount, lastCase - i ); + writeInputBufferInfo.count = count; + + // Crate a user event to represent the status of the reference value computation completion + writeInputBufferInfo.calcReferenceValues = clCreateUserEvent( gContext, &error); + if( error || NULL == writeInputBufferInfo.calcReferenceValues ) + { + vlog_error( "ERROR: Unable to create user event. (%d)\n", error ); + gFailCount++; + goto exit; + } + + // retain for consumption by MapOutputBufferComplete + for( vectorSize = gMinVectorSize; vectorSize < gMaxVectorSize; vectorSize++) + { + if( (error = clRetainEvent(writeInputBufferInfo.calcReferenceValues) )) + { + vlog_error( "ERROR: Unable to retain user event. (%d)\n", error ); + gFailCount++; + goto exit; + } + } + + // Crate a user event to represent when the callbacks are done verifying correctness + writeInputBufferInfo.doneBarrier = clCreateUserEvent( gContext, &error); + if( error || NULL == writeInputBufferInfo.calcReferenceValues ) + { + vlog_error( "ERROR: Unable to create user event for barrier. (%d)\n", error ); + gFailCount++; + goto exit; + } + + // retain for use by the callback that calls this + if( (error = clRetainEvent(writeInputBufferInfo.doneBarrier) )) + { + vlog_error( "ERROR: Unable to retain user event doneBarrier. (%d)\n", error ); + gFailCount++; + goto exit; + } + + // Call this in a multithreaded manner + // gInitFunctions[ inType ]( gIn, sat, round, outType, i, count, d ); + cl_uint chunks = RoundUpToNextPowerOfTwo(threads) * 2; + init_info.start = i; + init_info.size = count / chunks; + if( init_info.size < 16384 ) + { + chunks = RoundUpToNextPowerOfTwo(threads); + init_info.size = count / chunks; + if( init_info.size < 16384 ) + { + init_info.size = count; + chunks = 1; + } + } + ThreadPool_Do(InitData, chunks, &init_info); + + // Copy the results to the device + writeInputBuffer = NULL; + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, count * gTypeSizes[inType], gIn, 0, NULL, &writeInputBuffer ))) + { + vlog_error( "ERROR: clEnqueueWriteBuffer failed. (%d)\n", error ); + gFailCount++; + goto exit; + } + + // Setup completion callback for the write, which will enqueue the rest of the work + // This is somewhat gratuitous. Because this is an in order queue, we didn't really need to + // do this work in a callback. We could have done it from the main thread. Here we are + // verifying that the implementation can enqueue work from a callback, while at the same time + // also checking to make sure that the conversions work. + // + // Because the verification code is also moved to a callback, it is hoped that implementations will + // achieve a test performance improvement because they can verify the results in parallel. If the + // implementation serializes callbacks however, that won't happen. Consider it some motivation + // to do the right thing! :-) + if( (error = clSetEventCallback( writeInputBuffer, CL_COMPLETE, WriteInputBufferComplete, &writeInputBufferInfo)) ) + { + vlog_error( "ERROR: clSetEventCallback failed. (%d)\n", error ); + gFailCount++; + goto exit; + } + + // The event can't be destroyed until the callback is called, so we can release it now. + if( (error = clReleaseEvent(writeInputBuffer) )) + { + vlog_error( "ERROR: clReleaseEvent failed. (%d)\n", error ); + gFailCount++; + goto exit; + } + + // Make sure the work is actually running, so we don't deadlock + if( (error = clFlush( gQueue ) ) ) + { + vlog_error( "clFlush failed with error %d\n", error ); + gFailCount++; + goto exit; + } + + ThreadPool_Do(PrepareReference, chunks, &init_info); + + // signal we are done calculating the reference results + if( (error = clSetUserEventStatus( writeInputBufferInfo.calcReferenceValues, CL_COMPLETE ) ) ) + { + vlog_error( "Error: Failed to set user event status to CL_COMPLETE: %d\n", error ); + gFailCount++; + goto exit; + } + + // Wait for the event callbacks to finish verifying correctness. + if( (error = clWaitForEvents( 1, (cl_event*) &writeInputBufferInfo.doneBarrier ) )) + { + vlog_error( "Error: Failed to wait for barrier: %d\n", error ); + gFailCount++; + goto exit; + } + + if( (error = clReleaseEvent(writeInputBufferInfo.calcReferenceValues ) )) + { + vlog_error( "Error: Failed to release calcReferenceValues: %d\n", error ); + gFailCount++; + goto exit; + } + + if( (error = clReleaseEvent(writeInputBufferInfo.doneBarrier ) )) + { + vlog_error( "Error: Failed to release done barrier: %d\n", error ); + gFailCount++; + goto exit; + } + + + for( vectorSize = gMinVectorSize; vectorSize < gMaxVectorSize; vectorSize++) + { + if( ( error = writeInputBufferInfo.calcInfo[ vectorSize ].result )) + { + switch( inType ) + { + case kuchar: + case kchar: + vlog( "Input value: 0x%2.2x ", ((unsigned char*)gIn)[error - 1] ); + break; + case kushort: + case kshort: + vlog( "Input value: 0x%4.4x ", ((unsigned short*)gIn)[error - 1] ); + break; + case kuint: + case kint: + vlog( "Input value: 0x%8.8x ", ((unsigned int*)gIn)[error - 1] ); + break; + case kfloat: + vlog( "Input value: %a ", ((float*)gIn)[error - 1] ); + break; + break; + case kulong: + case klong: + vlog( "Input value: 0x%16.16llx ", ((unsigned long long*)gIn)[error - 1] ); + break; + case kdouble: + vlog( "Input value: %a ", ((double*)gIn)[error - 1]); + break; + default: + vlog_error( "Internal error at %s: %d\n", __FILE__, __LINE__ ); + abort(); + break; + } + + // tell the user which conversion it was. + if( 0 == vectorSize ) + vlog( " (implicit scalar conversion from %s to %s)\n", gTypeNames[ inType ], gTypeNames[ outType ] ); + else + vlog( " (convert_%s%s%s%s( %s%s ))\n", gTypeNames[outType], sizeNames[vectorSize], gSaturationNames[ sat ], + gRoundingModeNames[ round ], gTypeNames[inType], sizeNames[vectorSize] ); + + gFailCount++; + goto exit; + } + } + } + + log_info( "done.\n" ); + + if( gTimeResults ) + { + //Kick off tests for the various vector lengths + for( vectorSize = gMinVectorSize; vectorSize < gMaxVectorSize; vectorSize++) + { + size_t workItemCount = blockCount / vectorSizes[vectorSize]; + if( vectorSizes[vectorSize] * gTypeSizes[outType] < 4 ) + workItemCount /= 4 / (vectorSizes[vectorSize] * gTypeSizes[outType]); + + double sum = 0.0; + double bestTime = INFINITY; + cl_uint k; + for( k = 0; k < PERF_LOOP_COUNT; k++ ) + { + uint64_t startTime = GetTime(); + if( (error = RunKernel( writeInputBufferInfo.calcInfo[vectorSize].kernel, gInBuffer, gOutBuffers[ vectorSize ], workItemCount )) ) + { + gFailCount++; + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (workItemCount * vectorSizes[vectorSize]); + if( 0 == vectorSize ) + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "implicit convert %s -> %s", gTypeNames[ inType ], gTypeNames[ outType ] ); + else + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "convert_%s%s%s%s( %s%s )", gTypeNames[ outType ], sizeNames[vectorSize], gSaturationNames[ sat ], gRoundingModeNames[round], gTypeNames[inType], sizeNames[vectorSize] ); + } + } + + if( gWimpyMode ) + vlog( "\tWimp pass" ); + else + vlog( "\tpassed" ); + +#ifdef __APPLE__ + // record the run time + vlog( "\t(%f s)", 1e-9 * ( mach_absolute_time() - wall_start ) ); +#endif + vlog( "\n\n" ); + fflush( stdout ); + + +exit: + //clean up + for( vectorSize = gMinVectorSize; vectorSize < gMaxVectorSize; vectorSize++) + { + clReleaseProgram( writeInputBufferInfo.calcInfo[vectorSize].program ); + clReleaseKernel( writeInputBufferInfo.calcInfo[vectorSize].kernel ); + } + + if( init_info.d ) + { + for( i = 0; i < threads; i++ ) + free_mtdata(init_info.d[i]); + free(init_info.d); + } + + return error; +} + +void CL_CALLBACK MapResultValuesComplete( cl_event e, cl_int status, void *data ); + +// Note: not called reentrantly +void CL_CALLBACK WriteInputBufferComplete( cl_event e, cl_int status, void *data ) +{ + WriteInputBufferInfo *info = (WriteInputBufferInfo*) data; + cl_uint count = info->count; + int vectorSize; + + if( CL_SUCCESS != status ) + { + vlog_error( "ERROR: WriteInputBufferComplete calback failed with status: %d\n", status ); + gFailCount++; + return; + } + + info->barrierCount = gMaxVectorSize - gMinVectorSize; + + // now that we know that the write buffer is complete, enqueue callbacks to wait for the main thread to + // finish calculating the reference results. + for( vectorSize = gMinVectorSize; vectorSize < gMaxVectorSize; vectorSize++) + { + size_t workItemCount = (count + vectorSizes[vectorSize] - 1) / ( vectorSizes[vectorSize]); + cl_event mapComplete = NULL; + + if( (status = RunKernel( info->calcInfo[ vectorSize ].kernel, gInBuffer, gOutBuffers[ vectorSize ], workItemCount )) ) + { + gFailCount++; + return; + } + + info->calcInfo[vectorSize].p = clEnqueueMapBuffer( gQueue, gOutBuffers[ vectorSize ], CL_FALSE, CL_MAP_READ | CL_MAP_WRITE, + 0, count * gTypeSizes[ info->outType ], 0, NULL, &mapComplete, &status); + { + if( status ) + { + vlog_error( "ERROR: WriteInputBufferComplete calback failed with status: %d\n", status ); + gFailCount++; + return; + } + } + + if( (status = clSetEventCallback( mapComplete, CL_COMPLETE, MapResultValuesComplete, info->calcInfo + vectorSize))) + { + vlog_error( "ERROR: WriteInputBufferComplete calback failed with status: %d\n", status ); + gFailCount++; + return; + } + + if( (status = clReleaseEvent(mapComplete))) + { + vlog_error( "ERROR: clReleaseEvent calback failed in WriteInputBufferComplete for vector size %d with status: %d\n", vectorSize, status ); + gFailCount++; + return; + } + } + + // Make sure the work starts moving -- otherwise we may deadlock + if( (status = clFlush(gQueue))) + { + vlog_error( "ERROR: WriteInputBufferComplete calback failed with status: %d\n", status ); + gFailCount++; + return; + } + + // e was already released by the main thread. It should be destroyed automatically soon after we exit. +} + +void CL_CALLBACK CalcReferenceValuesComplete( cl_event e, cl_int status, void *data ); + +// Note: May be called reentrantly +void CL_CALLBACK MapResultValuesComplete( cl_event e, cl_int status, void *data ) +{ + CalcReferenceValuesInfo *info = (CalcReferenceValuesInfo*) data; + cl_event calcReferenceValues = info->parent->calcReferenceValues; + + if( CL_SUCCESS != status ) + { + vlog_error( "ERROR: MapResultValuesComplete calback failed with status: %d\n", status ); + gFailCount++; // not thread safe -- being lazy here + clReleaseEvent(calcReferenceValues); + return; + } + + // we know that the map is done, wait for the main thread to finish calculating the reference values + if( (status = clSetEventCallback( calcReferenceValues, CL_COMPLETE, CalcReferenceValuesComplete, data ))) + { + vlog_error( "ERROR: clSetEventCallback failed in MapResultValuesComplete with status: %d\n", status ); + gFailCount++; // not thread safe -- being lazy here + } + + // this thread no longer needs its reference to info->calcReferenceValues, so release it + if( (status = clReleaseEvent(calcReferenceValues) )) + { + vlog_error( "ERROR: clReleaseEvent(info->calcReferenceValues) failed with status: %d\n", status ); + gFailCount++; // not thread safe -- being lazy here + } + + // no need to flush since we didn't enqueue anything + + // e was already released by WriteInputBufferComplete. It should be destroyed automatically soon after we exit. +} + + +void CL_CALLBACK CalcReferenceValuesComplete( cl_event e, cl_int status, void *data ) +{ + CalcReferenceValuesInfo *info = (CalcReferenceValuesInfo*) data; + cl_uint vectorSize = info->vectorSize; + cl_uint count = info->parent->count; + Type outType = info->parent->outType; // the data type of the conversion result + Type inType = info->parent->inType; // the data type of the conversion input + size_t j; + cl_int error; + cl_event doneBarrier = info->parent->doneBarrier; + + // report spurious error condition + if( CL_SUCCESS != status ) + { + vlog_error( "ERROR: CalcReferenceValuesComplete did not succeed! (%d)\n", status ); + gFailCount++; // lazy about thread safety here + return; + } + + // Now we know that both results have been mapped back from the device, and the + // main thread is done calculating the reference results. It is now time to check + // the results. + + // verify results + void *mapped = info->p; + + //Patch up NaNs conversions to integer to zero -- these can be converted to any integer + if( outType != kfloat && outType != kdouble ) + { + if( inType == kfloat ) + { + float *inp = (float*) gIn; + for( j = 0; j < count; j++ ) + { + if( isnan( inp[j] ) ) + memset( (char*) mapped + j * gTypeSizes[ outType ], 0, gTypeSizes[ outType ] ); + } + } + if( inType == kdouble ) + { + double *inp = (double*) gIn; + for( j = 0; j < count; j++ ) + { + if( isnan( inp[j] ) ) + memset( (char*) mapped + j * gTypeSizes[ outType ], 0, gTypeSizes[ outType ] ); + } + } + } + else if( inType == kfloat || inType == kdouble ) + { // outtype and intype is float or double. NaN conversions for float <-> double can be any NaN + if( inType == kfloat && outType == kdouble ) + { + float *inp = (float*) gIn; + double *outp = (double*) mapped; + for( j = 0; j < count; j++ ) + { + if( isnan( inp[j] ) && isnan(outp[j]) ) + outp[j] = NAN; + } + } + if( inType == kdouble && outType == kfloat ) + { + double *inp = (double*) gIn; + float *outp = (float*) mapped; + for( j = 0; j < count; j++ ) + { + if( isnan( inp[j] ) && isnan(outp[j]) ) + outp[j] = NAN; + } + } + } + + if( memcmp( mapped, gRef, count * gTypeSizes[ outType ] ) ) + info->result = gCheckResults[outType]( mapped, gRef, gAllowZ, count, vectorSizes[vectorSize] ); + else + info->result = 0; + + // Fill the output buffer with junk and release it + { + cl_uint pattern = 0xffffdead; + memset_pattern4(mapped, &pattern, count * gTypeSizes[outType]); + if((error = clEnqueueUnmapMemObject(gQueue, gOutBuffers[ vectorSize ], mapped, 0, NULL, NULL))) + { + vlog_error( "ERROR: clEnqueueUnmapMemObject failed in CalcReferenceValuesComplete (%d)\n", error ); + gFailCount++; + } + } + + if( 1 == ThreadPool_AtomicAdd( &info->parent->barrierCount, -1) ) + { + if( (status = clSetUserEventStatus( doneBarrier, CL_COMPLETE) )) + { + vlog_error( "ERROR: clSetUserEventStatus failed in CalcReferenceValuesComplete (err: %d). We're probably going to deadlock.\n", status ); + gFailCount++; + return; + } + + if( (status = clReleaseEvent( doneBarrier ) ) ) + { + vlog_error( "ERROR: clReleaseEvent failed in CalcReferenceValuesComplete (err: %d).\n", status ); + gFailCount++; + return; + } + } + + + // e was already released by WriteInputBufferComplete. It should be destroyed automatically soon after + // all the calls to CalcReferenceValuesComplete exit. +} + +static cl_program MakeProgram( Type outType, Type inType, SaturationMode sat, RoundingMode round, int vectorSize, cl_kernel *outKernel ) +{ + cl_program program; + char testName[256]; + int error = 0; + const char **strings; + size_t stringCount = 0; + + // Create the program. This is a bit complicated because we are trying to avoid byte and short stores. + if (0 == vectorSize) + { + char inName[32]; + char outName[32]; + const char *programSource[] = + { + "", // optional pragma + "__kernel void ", testName, "( __global ", inName, " *src, __global ", outName, " *dest )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " dest[i] = src[i];\n" + "}\n" + }; + stringCount = sizeof(programSource) / sizeof(programSource[0]); + strings = programSource; + + if (outType == kdouble || inType == kdouble) + programSource[0] = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"; + + //create the type name + strncpy(inName, gTypeNames[inType], sizeof(inName)); + strncpy(outName, gTypeNames[outType], sizeof(outName)); + sprintf(testName, "test_implicit_%s_%s", outName, inName); + vlog("Building implicit %s -> %s conversion test\n", gTypeNames[inType], gTypeNames[outType]); + fflush(stdout); + } + else + { + int vectorSizetmp = vectorSizes[vectorSize]; + + char convertString[128]; + char inName[32]; + char outName[32]; + const char *programSource[] = + { + "", // optional pragma + "__kernel void ", testName, "( __global ", inName, " *src, __global ", outName, " *dest )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " dest[i] = ", convertString, "( src[i] );\n" + "}\n" + }; + const char *programSourceV3[] = + { + "", // optional pragma + "__kernel void ", testName, "( __global ", inName, " *src, __global ", outName, " *dest )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0))\n" + " vstore3( ", convertString, "( vload3( i, src)), i, dest );\n" + " else\n" + " {\n" + " ", inName, "3 in;\n" + " ", outName, "3 out;\n" + " if( 0 == (i & 1) )\n" + " in.y = src[3*i+1];\n" + " in.x = src[3*i];\n" + " out = ", convertString, "( in ); \n" + " dest[3*i] = out.x;\n" + " if( 0 == (i & 1) )\n" + " dest[3*i+1] = out.y;\n" + " }\n" + "}\n" + }; + stringCount = 3 == vectorSizetmp ? sizeof(programSourceV3) / sizeof(programSourceV3[0]) : + sizeof(programSource) / sizeof(programSource[0]); + strings = 3 == vectorSizetmp ? programSourceV3 : programSource; + + if (outType == kdouble || inType == kdouble) { + programSource[0] = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"; + programSourceV3[0] = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"; + } + + //create the type name + switch (vectorSizetmp) + { + case 1: + strncpy(inName, gTypeNames[inType], sizeof(inName)); + strncpy(outName, gTypeNames[outType], sizeof(outName)); + snprintf(convertString, sizeof(convertString), "convert_%s%s%s", outName, gSaturationNames[sat], gRoundingModeNames[round]); + snprintf(testName, 256, "test_%s_%s", convertString, inName); + vlog("Building %s( %s ) test\n", convertString, inName); + break; + case 3: + strncpy(inName, gTypeNames[inType], sizeof(inName)); + strncpy(outName, gTypeNames[outType], sizeof(outName)); + snprintf(convertString, sizeof(convertString), "convert_%s3%s%s", outName, gSaturationNames[sat], gRoundingModeNames[round]); + snprintf(testName, 256, "test_%s_%s3", convertString, inName); + vlog("Building %s( %s3 ) test\n", convertString, inName); + break; + default: + snprintf(inName, sizeof(inName), "%s%d", gTypeNames[inType], vectorSizetmp); + snprintf(outName, sizeof(outName), "%s%d", gTypeNames[outType], vectorSizetmp); + snprintf(convertString, sizeof(convertString), "convert_%s%s%s", outName, gSaturationNames[sat], gRoundingModeNames[round]); + snprintf(testName, 256, "test_%s_%s", convertString, inName); + vlog("Building %s( %s ) test\n", convertString, inName); + break; + } + + fflush(stdout); + } + *outKernel = NULL; + + const char *flags = NULL; + if( gForceFTZ ) + flags = "-cl-denorms-are-zero"; + + // build it + error = create_single_kernel_helper(gContext, &program, outKernel, (cl_uint)stringCount, strings, testName, flags); + if (error) + { + char buffer[2048] = ""; + + vlog_error("Failed to build kernel/program.\n", error); + clReleaseProgram(program); + return NULL; + } + + return program; +} + diff --git a/test_conformance/d3d10/CMakeLists.txt b/test_conformance/d3d10/CMakeLists.txt new file mode 100644 index 00000000..dbe39f0e --- /dev/null +++ b/test_conformance/d3d10/CMakeLists.txt @@ -0,0 +1,47 @@ +if(WIN32) + +set(D3D10_INCLUDE_DIR $ENV{NV_TOOLS}/sdk/DirectX_Aug2009/Include) + +if(${ARCH} STREQUAL "i686") +set(D3D10_LIB_DIR $ENV{NV_TOOLS}/sdk/DirectX_Aug2009/Lib/x86) +endif(${ARCH} STREQUAL "i686") + +if(${ARCH} STREQUAL "x86_64") +set(D3D10_LIB_DIR $ENV{NV_TOOLS}/sdk/DirectX_Aug2009/Lib/x64) +endif(${ARCH} STREQUAL "x86_64") + +list(APPEND CLConform_INCLUDE_DIR ${D3D10_INCLUDE_DIR}) +include_directories (${CLConform_SOURCE_DIR}/test_common/harness + ${CLConform_INCLUDE_DIR} ) +link_directories(${CL_LIB_DIR}, ${D3D10_LIB_DIR}) + +list(APPEND CLConform_LIBRARIES d3d10 dxgi) + + +set(D3D10_SOURCES + buffer.cpp + texture2d.cpp + texture3d.cpp + misc.cpp + main.cpp + harness.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp) + +add_executable(conformance_test_d3d10 + ${D3D10_SOURCES}) + +set_source_files_properties( + ${D3D10_SOURCES} + PROPERTIES LANGUAGE CXX) + +TARGET_LINK_LIBRARIES(conformance_test_d3d10 + ${CLConform_LIBRARIES}) + +endif(WIN32) diff --git a/test_conformance/d3d10/buffer.cpp b/test_conformance/d3d10/buffer.cpp new file mode 100644 index 00000000..ed411db0 --- /dev/null +++ b/test_conformance/d3d10/buffer.cpp @@ -0,0 +1,310 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "harness.h" + +#define ADD_BUFFER_PROPERTIES(w, x, y, z) \ + { w, x, y, z, #x, #y, #z, } + +BufferProperties bufferProperties[] = +{ + ADD_BUFFER_PROPERTIES( 0x100, D3D10_BIND_CONSTANT_BUFFER, D3D10_USAGE_DYNAMIC, D3D10_CPU_ACCESS_WRITE), + ADD_BUFFER_PROPERTIES( 0x1000, D3D10_BIND_CONSTANT_BUFFER, D3D10_USAGE_DYNAMIC, D3D10_CPU_ACCESS_WRITE), + ADD_BUFFER_PROPERTIES( 0x8000, D3D10_BIND_CONSTANT_BUFFER, D3D10_USAGE_DYNAMIC, D3D10_CPU_ACCESS_WRITE), + + ADD_BUFFER_PROPERTIES( 0x7FFFF, D3D10_BIND_SHADER_RESOURCE, D3D10_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x100000, D3D10_BIND_SHADER_RESOURCE, D3D10_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x100000, D3D10_BIND_STREAM_OUTPUT, D3D10_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x100001, D3D10_BIND_STREAM_OUTPUT, D3D10_USAGE_DEFAULT, 0), + + ADD_BUFFER_PROPERTIES( 0x10, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x11, D3D10_BIND_INDEX_BUFFER, D3D10_USAGE_DYNAMIC, D3D10_CPU_ACCESS_WRITE), + ADD_BUFFER_PROPERTIES( 0x121, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x1234, D3D10_BIND_INDEX_BUFFER, D3D10_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x12345, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DYNAMIC, D3D10_CPU_ACCESS_WRITE), + ADD_BUFFER_PROPERTIES( 0x123456, D3D10_BIND_INDEX_BUFFER, D3D10_USAGE_DEFAULT, 0), +#if 0 // avoid large sizes on automation + ADD_BUFFER_PROPERTIES( 0x1234567, D3D10_BIND_INDEX_BUFFER, D3D10_USAGE_DYNAMIC, D3D10_CPU_ACCESS_WRITE), + + ADD_BUFFER_PROPERTIES( 0x4000000, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x4000004, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x4000008, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x4000010, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x4000014, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DEFAULT, 0), +#endif +}; +UINT bufferPropertyCount = sizeof(bufferProperties)/sizeof(bufferProperties[0]); + +void SubTestBuffer( + cl_context context, + cl_command_queue command_queue, + ID3D10Device* pDevice, + const BufferProperties* props) +{ + ID3D10Buffer* pBuffer = NULL; + HRESULT hr = S_OK; + cl_mem mem = NULL; + cl_int result = CL_SUCCESS; + + HarnessD3D10_TestBegin("Buffer: Size=%d, BindFlags=%s, Usage=%s, CPUAccess=%s", + props->ByteWidth, + props->name_BindFlags, + props->name_Usage, + props->name_CPUAccess); + + // create the D3D10 resource + { + D3D10_BUFFER_DESC desc = {0}; + desc.ByteWidth = props->ByteWidth; + desc.Usage = props->Usage; + desc.CPUAccessFlags = props->CPUAccess; + desc.BindFlags = props->BindFlags; + desc.MiscFlags = 0; + hr = pDevice->CreateBuffer(&desc, NULL, &pBuffer); + TestRequire(SUCCEEDED(hr), "Creating vertex buffer failed!"); + } + + // populate the D3D10 resource with data + { + ID3D10Buffer* pStagingBuffer = NULL; + char *pStagingData = NULL; + + // create a staging buffer to use to copy data to the D3D buffer + D3D10_BUFFER_DESC desc = {0}; + desc.ByteWidth = 16; + desc.Usage = D3D10_USAGE_STAGING; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE|D3D10_CPU_ACCESS_READ; + desc.BindFlags = 0; + desc.MiscFlags = 0; + hr = pDevice->CreateBuffer(&desc, NULL, &pStagingBuffer); + TestRequire(SUCCEEDED(hr), "Creating staging vertex buffer failed!"); + + // populate the staging buffer + hr = pStagingBuffer->Map( + D3D10_MAP_READ_WRITE, + 0, + (void **)&pStagingData); + TestRequire(SUCCEEDED(hr), "Map failed!"); + memcpy(pStagingData, "abcdXXXXxxxx1234", 16); + pStagingBuffer->Unmap(); + TestRequire(SUCCEEDED(hr), "Unmap failed!"); + + // copy 'abcdXXXX' to the front of the buffer and 'xxxx1234' to the back + D3D10_BOX box = {0}; + box.front = 0; + box.back = 1; + box.top = 0; + box.bottom = 1; + + box.left = 0; + box.right = 8; + pDevice->CopySubresourceRegion( + pBuffer, + 0, + 0, + 0, + 0, + pStagingBuffer, + 0, + &box); + box.left = 8; + box.right = 16; + pDevice->CopySubresourceRegion( + pBuffer, + 0, + props->ByteWidth-8, + 0, + 0, + pStagingBuffer, + 0, + &box); + pStagingBuffer->Release(); + } + + // share the resource with OpenCL + { + mem = clCreateFromD3D10BufferKHR( + context, + 0, + pBuffer, + &result); + TestRequire(CL_SUCCESS == result, "clCreateFromD3D10BufferKHR failed"); + } + + // validate the OpenCL mem obj's properties + { + ID3D10Resource* clResource = NULL; + result = clGetMemObjectInfo( + mem, + CL_MEM_D3D10_RESOURCE_KHR, + sizeof(clResource), + &clResource, + NULL); + TestRequire(result == CL_SUCCESS, "clGetMemObjectInfo for CL_MEM_D3D10_RESOURCE_KHR failed."); + TestRequire(clResource == pBuffer, "clGetMemObjectInfo for CL_MEM_D3D10_RESOURCE_KHR returned incorrect value."); + } + + // acquire the resource from OpenCL + { + result = clEnqueueAcquireD3D10ObjectsKHR( + command_queue, + 1, + &mem, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueAcquireD3D10ObjectsKHR failed."); + } + + // read+write data from the buffer in OpenCL + { + // overwrite the 'XXXX' with '1234' and the 'xxxx' with 'abcd' so we now have + // 'abcd1234' at the beginning and end of the buffer + result = clEnqueueCopyBuffer( + command_queue, + mem, + mem, + 0, + props->ByteWidth-8, + 4, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueCopyBuffer failed."); + + result = clEnqueueCopyBuffer( + command_queue, + mem, + mem, + props->ByteWidth-4, + 4, + 4, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueCopyBuffer failed."); + } + + // release the resource from OpenCL + { + result = clEnqueueReleaseD3D10ObjectsKHR( + command_queue, + 1, + &mem, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueReleaseD3D10ObjectsKHR failed."); + } + + // read data in D3D + { + ID3D10Buffer* pStagingBuffer = NULL; + char *pStagingData = NULL; + + // create a staging buffer to read the data back + D3D10_BUFFER_DESC desc = {0}; + desc.ByteWidth = 16; + desc.Usage = D3D10_USAGE_STAGING; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE|D3D10_CPU_ACCESS_READ; + desc.BindFlags = 0; + desc.MiscFlags = 0; + hr = pDevice->CreateBuffer(&desc, NULL, &pStagingBuffer); + TestRequire(SUCCEEDED(hr), "Creating staging vertex buffer failed!"); + + // make sure the staging buffer doesn't get stale data + hr = pStagingBuffer->Map( + D3D10_MAP_READ_WRITE, + 0, + (void **)&pStagingData); + TestRequire(SUCCEEDED(hr), "Map failed!"); + memset(pStagingData, 0, 16); + pStagingBuffer->Unmap(); + + + // copy the 'abcd1234' from the front and back of the buffer to the staging buffer + D3D10_BOX box = {0}; + box.front = 0; + box.back = 1; + box.top = 0; + box.bottom = 1; + + box.left = 0; + box.right = 8; + pDevice->CopySubresourceRegion( + pStagingBuffer, + 0, + 0, + 0, + 0, + pBuffer, + 0, + &box); + box.left = props->ByteWidth-8; + box.right = props->ByteWidth; + pDevice->CopySubresourceRegion( + pStagingBuffer, + 0, + 8, + 0, + 0, + pBuffer, + 0, + &box); + TestRequire(SUCCEEDED(hr), "CopySubresourceRegion failed!"); + + // verify that we got the 'abcd1234' + hr = pStagingBuffer->Map( + D3D10_MAP_READ_WRITE, + 0, + (void **)&pStagingData); + TestRequire(SUCCEEDED(hr), "Map failed!"); + TestRequire(!memcmp(pStagingData, "abcd1234abcd1234", 16), "Data was not accurately"); + pStagingBuffer->Unmap(); + TestRequire(SUCCEEDED(hr), "Unmap failed!"); + + pStagingBuffer->Release(); + } + +Cleanup: + + if (pBuffer) + { + pBuffer->Release(); + } + if (mem) + { + clReleaseMemObject(mem); + } + + HarnessD3D10_TestEnd(); +} + + +void TestDeviceBuffer( + cl_context context, + cl_command_queue command_queue, + ID3D10Device* pDevice) +{ + for (UINT i = 0; i < bufferPropertyCount; ++i) + { + SubTestBuffer( + context, + command_queue, + pDevice, + &bufferProperties[i]); + } +} + diff --git a/test_conformance/d3d10/harness.cpp b/test_conformance/d3d10/harness.cpp new file mode 100644 index 00000000..e93cee94 --- /dev/null +++ b/test_conformance/d3d10/harness.cpp @@ -0,0 +1,413 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#define INITGUID +#include "harness.h" +#include + +#include + +/* + * OpenCL state + */ + +clGetDeviceIDsFromD3D10KHR_fn clGetDeviceIDsFromD3D10KHR = NULL; +clCreateFromD3D10BufferKHR_fn clCreateFromD3D10BufferKHR = NULL; +clCreateFromD3D10Texture2DKHR_fn clCreateFromD3D10Texture2DKHR = NULL; +clCreateFromD3D10Texture3DKHR_fn clCreateFromD3D10Texture3DKHR = NULL; +clEnqueueAcquireD3D10ObjectsKHR_fn clEnqueueAcquireD3D10ObjectsKHR = NULL; +clEnqueueReleaseD3D10ObjectsKHR_fn clEnqueueReleaseD3D10ObjectsKHR = NULL; + +#define INITPFN(x) \ + x = (x ## _fn)clGetExtensionFunctionAddressForPlatform(platform, #x); NonTestRequire(x, "Failed to get function pointer for %s", #x); + +void +HarnessD3D10_ExtensionCheck() +{ + bool extensionPresent = false; + cl_int result = CL_SUCCESS; + cl_platform_id platform = NULL; + char extensions[1024]; + + HarnessD3D10_TestBegin("Extension query"); + + result = clGetPlatformIDs(1, &platform, NULL); + NonTestRequire(result == CL_SUCCESS, "Failed to get any platforms."); + result = clGetPlatformInfo(platform, CL_PLATFORM_EXTENSIONS, sizeof(extensions), extensions, NULL); + NonTestRequire(result == CL_SUCCESS, "Failed to list extensions."); + extensionPresent = strstr(extensions, "cl_khr_d3d10_sharing") ? true : false; + + if (!extensionPresent) { + // platform is required to report the extension only if all devices support it + cl_uint devicesCount; + result = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0, NULL, &devicesCount); + NonTestRequire(result == CL_SUCCESS, "Failed to get devices count."); + std::vector devices(devicesCount); + result = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, devicesCount, &devices[0], NULL); + NonTestRequire(result == CL_SUCCESS, "Failed to get devices count."); + + for (cl_uint i = 0; i < devicesCount; i++) { + clGetDeviceInfo(devices[i], CL_DEVICE_EXTENSIONS, sizeof(extensions), extensions, NULL); + NonTestRequire(result == CL_SUCCESS, "Failed to list extensions."); + extensionPresent = strstr(extensions, "cl_khr_d3d10_sharing") ? true : false; + if (extensionPresent) + break; + } + } + + OSVERSIONINFO osvi; + osvi.dwOSVersionInfoSize = sizeof(osvi); + GetVersionEx(&osvi); + if (osvi.dwMajorVersion <= 5) + { + TestRequire(!extensionPresent, "Extension should not be exported on Windows < 6"); + } + else + { + TestRequire(extensionPresent, "Extension should be exported on Windows >= 6"); + } + +Cleanup: + HarnessD3D10_TestEnd(); + + // early-out of the extension is not present + if (!extensionPresent) + { + HarnessD3D10_TestStats(); + } +} + +void +HarnessD3D10_Initialize(cl_platform_id platform) +{ + HarnessD3D10_ExtensionCheck(); + + // extract function pointers for exported functions + INITPFN(clGetDeviceIDsFromD3D10KHR); + INITPFN(clCreateFromD3D10BufferKHR); + INITPFN(clCreateFromD3D10Texture2DKHR); + INITPFN(clCreateFromD3D10Texture3DKHR); + INITPFN(clEnqueueAcquireD3D10ObjectsKHR); + INITPFN(clEnqueueReleaseD3D10ObjectsKHR); +} + +/* + * Window management + */ + +static IDXGISwapChain* HarnessD3D10_pSwapChain = NULL; +static ID3D10Device* HarnessD3D10_pDevice = NULL; +static HWND HarnessD3D10_hWnd = NULL; + +static LRESULT WINAPI HarnessD3D10_Proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_KEYDOWN: + return 0; + break; + case WM_DESTROY: + HarnessD3D10_hWnd = NULL; + PostQuitMessage(0); + return 0; + case WM_PAINT: + ValidateRect(hWnd, NULL); + return 0; + } + return DefWindowProc(hWnd, msg, wParam, lParam); +} + +static void HarnessD3D10_InteractiveLoop() +{ + MSG msg; + while(PeekMessage(&msg,HarnessD3D10_hWnd,0,0,PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +cl_int HarnessD3D10_CreateDevice(IDXGIAdapter* pAdapter, ID3D10Device **ppDevice) +{ + HRESULT hr = S_OK; + unsigned int cuStatus = 1; + + *ppDevice = NULL; + + // create window + static WNDCLASSEX wc = + { + sizeof(WNDCLASSEX), + CS_CLASSDC, + HarnessD3D10_Proc, + 0L, + 0L, + GetModuleHandle(NULL), + NULL, + NULL, + NULL, + NULL, + _T( "cl_khr_d3d10_sharing_conformance" ), + NULL + }; + RegisterClassEx(&wc); + HarnessD3D10_hWnd = CreateWindow( + _T( "cl_khr_d3d10_sharing_conformance" ), + _T( "cl_khr_d3d10_sharing_conformance" ), + WS_OVERLAPPEDWINDOW, + 0, 0, 256, 256, + NULL, + NULL, + wc.hInstance, + NULL); + NonTestRequire(0 != HarnessD3D10_hWnd, "Failed to create window"); + + ShowWindow(HarnessD3D10_hWnd,SW_SHOWDEFAULT); + UpdateWindow(HarnessD3D10_hWnd); + + RECT rc; + GetClientRect(HarnessD3D10_hWnd, &rc); + UINT width = rc.right - rc.left; + UINT height = rc.bottom - rc.top; + + // Create device and swapchain + DXGI_SWAP_CHAIN_DESC sd; + ZeroMemory(&sd, sizeof(sd)); + sd.BufferCount = 1; + sd.BufferDesc.Width = width; + sd.BufferDesc.Height = height; + sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + sd.BufferDesc.RefreshRate.Numerator = 60; + sd.BufferDesc.RefreshRate.Denominator = 1; + sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sd.OutputWindow = HarnessD3D10_hWnd; + sd.SampleDesc.Count = 1; + sd.SampleDesc.Quality = 0; + sd.Windowed = TRUE; + hr = D3D10CreateDeviceAndSwapChain( + pAdapter, + D3D10_DRIVER_TYPE_HARDWARE, + NULL, + D3D10_CREATE_DEVICE_DEBUG, + D3D10_SDK_VERSION, + &sd, + &HarnessD3D10_pSwapChain, + &HarnessD3D10_pDevice); + + if (FAILED(hr) ) { + return CL_DEVICE_NOT_FOUND; + } + + *ppDevice = HarnessD3D10_pDevice; + return CL_SUCCESS; +} + +void HarnessD3D10_DestroyDevice() +{ + HarnessD3D10_pSwapChain->Release(); + HarnessD3D10_pDevice->Release(); + + if (HarnessD3D10_hWnd) DestroyWindow(HarnessD3D10_hWnd); + HarnessD3D10_hWnd = 0; +} + +/* + * + * texture formats + * + */ + +#define ADD_TEXTURE_FORMAT(x,y,z,a,b,g) { x, y, z, a*b/8, g, #x, #y, #z, } +TextureFormat formats[] = +{ + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32B32A32_FLOAT , CL_RGBA , CL_FLOAT , 32, 4, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32B32A32_UINT , CL_RGBA , CL_UNSIGNED_INT32 , 32, 4, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32B32A32_SINT , CL_RGBA , CL_SIGNED_INT32 , 32, 4, TextureFormat::GENERIC_SINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_FLOAT , CL_RGBA , CL_HALF_FLOAT , 16, 4, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_UNORM , CL_RGBA , CL_UNORM_INT16 , 16, 4, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_UINT , CL_RGBA , CL_UNSIGNED_INT16 , 16, 4, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_SNORM , CL_RGBA , CL_SNORM_INT16 , 16, 4, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_SINT , CL_RGBA , CL_SIGNED_INT16 , 16, 4, TextureFormat::GENERIC_SINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_UNORM , CL_RGBA , CL_UNORM_INT8 , 8, 4, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_UINT , CL_RGBA , CL_UNSIGNED_INT8 , 8, 4, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_SNORM , CL_RGBA , CL_SNORM_INT8 , 8, 4, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_SINT , CL_RGBA , CL_SIGNED_INT8 , 8, 4, TextureFormat::GENERIC_SINT ), + + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32_FLOAT , CL_RG , CL_FLOAT , 32, 2, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32_UINT , CL_RG , CL_UNSIGNED_INT32 , 32, 2, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32_SINT , CL_RG , CL_SIGNED_INT32 , 32, 2, TextureFormat::GENERIC_SINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_FLOAT , CL_RG , CL_HALF_FLOAT , 16, 2, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_UNORM , CL_RG , CL_UNORM_INT16 , 16, 2, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_UINT , CL_RG , CL_UNSIGNED_INT16 , 16, 2, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_SNORM , CL_RG , CL_SNORM_INT16 , 16, 2, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_SINT , CL_RG , CL_SIGNED_INT16 , 16, 2, TextureFormat::GENERIC_SINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_UNORM , CL_RG , CL_UNORM_INT8 , 8, 2, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_UINT , CL_RG , CL_UNSIGNED_INT8 , 8, 2, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_SNORM , CL_RG , CL_SNORM_INT8 , 8, 2, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_SINT , CL_RG , CL_SIGNED_INT8 , 8, 2, TextureFormat::GENERIC_SINT ), + + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32_FLOAT , CL_R , CL_FLOAT , 32, 1, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32_UINT , CL_R , CL_UNSIGNED_INT32 , 32, 1, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32_SINT , CL_R , CL_SIGNED_INT32 , 32, 1, TextureFormat::GENERIC_SINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_FLOAT , CL_R , CL_HALF_FLOAT , 16, 1, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_UNORM , CL_R , CL_UNORM_INT16 , 16, 1, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_UINT , CL_R , CL_UNSIGNED_INT16 , 16, 1, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_SNORM , CL_R , CL_SNORM_INT16 , 16, 1, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_SINT , CL_R , CL_SIGNED_INT16 , 16, 1, TextureFormat::GENERIC_SINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_UNORM , CL_R , CL_UNORM_INT8 , 8, 1, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_UINT , CL_R , CL_UNSIGNED_INT8 , 8, 1, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_SNORM , CL_R , CL_SNORM_INT8 , 8, 1, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_SINT , CL_R , CL_SIGNED_INT8 , 8, 1, TextureFormat::GENERIC_SINT ), +}; +UINT formatCount = sizeof(formats)/sizeof(formats[0]); + +/* + * + * Logging and error reporting + * + */ + +static struct +{ + cl_int testCount; + cl_int passCount; + + cl_int nonTestFailures; + cl_int inTest; + cl_int currentTestPass; + + char currentTestName[1024]; +} HarnessD3D10_testStats = {0}; + +void HarnessD3D10_TestBegin(const char* fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsprintf(HarnessD3D10_testStats.currentTestName, fmt, ap); + va_end(ap); + + TestPrint("[%s] ... ", HarnessD3D10_testStats.currentTestName); + + HarnessD3D10_testStats.inTest = 1; + HarnessD3D10_testStats.currentTestPass = 1; +} + +void HarnessD3D10_TestFail() +{ + if (HarnessD3D10_testStats.inTest) + { + HarnessD3D10_testStats.currentTestPass = 0; + } + else + { + ++HarnessD3D10_testStats.nonTestFailures; + } +} + +void HarnessD3D10_TestEnd() +{ + HarnessD3D10_testStats.inTest = 0; + + HarnessD3D10_testStats.testCount += 1; + HarnessD3D10_testStats.passCount += HarnessD3D10_testStats.currentTestPass; + + TestPrint("%s\n", + HarnessD3D10_testStats.currentTestPass ? "PASSED" : "FAILED"); +} + +void HarnessD3D10_TestStats() +{ + TestPrint("PASSED %d of %d tests.\n", HarnessD3D10_testStats.passCount, HarnessD3D10_testStats.testCount); + if (HarnessD3D10_testStats.testCount > HarnessD3D10_testStats.passCount) + { + TestPrint("***FAILED***\n"); + exit(1); + } + else + { + TestPrint("&&&& cl_khr_d3d10_sharing test PASSED\n"); + } + exit(0); +} + +/* + * + * Helper function + * + */ + +cl_int HarnessD3D10_CreateKernelFromSource( + cl_kernel *outKernel, + cl_device_id device, + cl_context context, + const char *source, + const char *entrypoint) +{ + cl_int status; + cl_program program = NULL; + cl_kernel kernel = NULL; + + // compile program + { + const char *sourceTexts[] = {source}; + size_t sourceLengths[] = {strlen(source) }; + + status = create_single_kernel_helper_create_program(context, &program, 1, &sourceTexts[0]); + TestRequire( + CL_SUCCESS == status, + "clCreateProgramWithSource failed"); + } + status = clBuildProgram( + program, + 0, + NULL, + NULL, + NULL, + NULL); + if (CL_SUCCESS != status) + { + char log[2048] = {0}; + status = clGetProgramBuildInfo( + program, + device, + CL_PROGRAM_BUILD_LOG, + sizeof(log), + log, + NULL); + TestPrint("error: %s\n", log); + TestRequire( + CL_SUCCESS == status, + "Compilation error log:\n%s\n", log); + } + + kernel = clCreateKernel( + program, + entrypoint, + &status); + TestRequire( + CL_SUCCESS == status, + "clCreateKernel failed"); + + clReleaseProgram(program); + *outKernel = kernel; + +Cleanup: + + return CL_SUCCESS; +} + + + diff --git a/test_conformance/d3d10/harness.h b/test_conformance/d3d10/harness.h new file mode 100644 index 00000000..a17839b2 --- /dev/null +++ b/test_conformance/d3d10/harness.h @@ -0,0 +1,213 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _HARNESS_H_ +#define _HARNESS_H_ + +#define _CRT_SECURE_NO_WARNINGS + +#if defined (__MINGW32__) +#include +typedef unsigned char UINT8; +#define __out +#define __in +#define __inout +#define __out_bcount_opt(size) +#define __in_opt +#define __in_ecount(size) +#define __in_ecount_opt(size) +#define __out_opt +#define __out_ecount(size) +#define __out_ecount_opt(size) +#define __in_bcount_opt(size) +#define __inout_opt +#endif + +#include +#include +#include +#include +#include "errorHelpers.h" +#include "../test_common/harness/kernelHelpers.h" + +// #define log_info(...) printf(__VA_ARGS__) +// #define log_error(...) printf(__VA_ARGS__) + +#define NonTestRequire(x, ...) \ +do \ +{ \ + if (!(x) ) \ + { \ + log_info("\n[assertion failed: %s at %s:%d]\n", #x, __FILE__, __LINE__); \ + log_info("CATASTROPHIC NON-TEST ERROR: "); \ + log_error(__VA_ARGS__); \ + log_info("\n"); \ + log_info("***FAILED***\n"); \ + exit(1); \ + } \ +} while (0) + +#define TestRequire(x, ...) \ + do \ + { \ + if (!(x) ) \ + { \ + log_info("\n[assertion failed: %s at %s:%d]\n", #x, __FILE__, __LINE__); \ + log_info("ERROR: "); \ + log_error(__VA_ARGS__); \ + log_info("\n"); \ + HarnessD3D10_TestFail(); \ + goto Cleanup; \ + } \ + } while (0) + +#define TestPrint(...) \ + do \ + { \ + log_error(__VA_ARGS__); \ + } while (0) + +struct TextureFormat +{ + DXGI_FORMAT format; + cl_channel_order channel_order; + cl_channel_type channel_type; + UINT bytesPerPixel; + enum + { + GENERIC_FLOAT = 0, + GENERIC_UINT = 1, + GENERIC_SINT = 2, + } generic; + + const char *name_format; + const char *name_channel_order; + const char *name_channel_type; +}; +extern TextureFormat formats[]; +extern UINT formatCount; + + +#define MAX_REGISTERED_SUBRESOURCES 4 // limit to just make life easier + +struct BufferProperties +{ + UINT ByteWidth; + UINT BindFlags; + D3D10_USAGE Usage; + UINT CPUAccess; + const char* name_BindFlags; + const char* name_Usage; + const char* name_CPUAccess; +}; + +struct Texture2DSize +{ + UINT Width; + UINT Height; + UINT MipLevels; + UINT ArraySize; + UINT SubResourceCount; + struct + { + UINT MipLevel; + UINT ArraySlice; + } subResources[MAX_REGISTERED_SUBRESOURCES]; + UINT MiscFlags; +}; +struct Texture3DSize +{ + UINT Width; + UINT Height; + UINT Depth; + UINT MipLevels; + UINT SubResourceCount; + struct + { + UINT MipLevel; + } subResources[MAX_REGISTERED_SUBRESOURCES]; + UINT MiscFlags; +}; + +void HarnessD3D10_Initialize(cl_platform_id platform); +cl_int HarnessD3D10_CreateDevice(IDXGIAdapter* pAdapter, ID3D10Device **ppDevice); +void HarnessD3D10_DestroyDevice(); + +void HarnessD3D10_TestBegin(const char* fmt, ...); +void HarnessD3D10_TestFail(); +void HarnessD3D10_TestEnd(); +void HarnessD3D10_TestStats(); + + +void TestAdapterEnumeration( + cl_platform_id platform, + IDXGIAdapter* pAdapter, + ID3D10Device* pDevice, + cl_uint* num_devices); + +void TestAdapterDevices( + cl_platform_id platform, + IDXGIAdapter* pAdapter, + ID3D10Device* pDevice, + cl_uint num_devices); + +void TestDevice( + cl_device_id device, + ID3D10Device* pDevice); + +bool TestDeviceContextCreate( + cl_device_id device, + ID3D10Device* pDevice, + cl_context* out_context, + cl_command_queue* out_command_queue); + +void TestDeviceBuffer( + cl_context context, + cl_command_queue command_queue, + ID3D10Device* pDevice); + +void TestDeviceTexture2D( + cl_device_id device, + cl_context context, + cl_command_queue command_queue, + ID3D10Device* pDevice); + +void TestDeviceTexture3D( + cl_device_id device, + cl_context context, + cl_command_queue command_queue, + ID3D10Device* pDevice); + +void TestDeviceMisc( + cl_device_id device, + cl_context context, + cl_command_queue command_queue, + ID3D10Device* pDevice); + +cl_int HarnessD3D10_CreateKernelFromSource( + cl_kernel *outKernel, + cl_device_id device, + cl_context context, + const char *source, + const char *entrypoint); + +extern clGetDeviceIDsFromD3D10KHR_fn clGetDeviceIDsFromD3D10KHR; +extern clCreateFromD3D10BufferKHR_fn clCreateFromD3D10BufferKHR; +extern clCreateFromD3D10Texture2DKHR_fn clCreateFromD3D10Texture2DKHR; +extern clCreateFromD3D10Texture3DKHR_fn clCreateFromD3D10Texture3DKHR; +extern clEnqueueAcquireD3D10ObjectsKHR_fn clEnqueueAcquireD3D10ObjectsKHR; +extern clEnqueueReleaseD3D10ObjectsKHR_fn clEnqueueReleaseD3D10ObjectsKHR; + +#endif diff --git a/test_conformance/d3d10/main.cpp b/test_conformance/d3d10/main.cpp new file mode 100644 index 00000000..7c862e81 --- /dev/null +++ b/test_conformance/d3d10/main.cpp @@ -0,0 +1,433 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#if defined( _WIN32 ) + +#define _CRT_SECURE_NO_WARNINGS +#include "harness.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/parseParameters.h" + +int main(int argc, const char* argv[]) +{ + cl_int result; + cl_platform_id platform = NULL; + cl_uint num_devices_tested = 0; + + argc = parseCustomParam(argc, argv); + + // get the platform to test + result = clGetPlatformIDs(1, &platform, NULL); NonTestRequire(result == CL_SUCCESS, "Failed to get any platforms."); + + HarnessD3D10_Initialize(platform); + + // for each adapter... + IDXGIFactory* pFactory = NULL; + HRESULT hr = CreateDXGIFactory(IID_IDXGIFactory, (void**)(&pFactory) ); + NonTestRequire(SUCCEEDED(hr), "Failed to create DXGI factory."); + for (UINT adapter = 0;; ++adapter) + { + IDXGIAdapter* pAdapter = NULL; + ID3D10Device* pDevice = NULL; + HRESULT hr = pFactory->EnumAdapters(adapter, &pAdapter); + if (FAILED(hr)) + { + break; + } + + // print data about the adapter + DXGI_ADAPTER_DESC desc; + hr = pAdapter->GetDesc(&desc); + NonTestRequire(SUCCEEDED(hr), "IDXGIAdapter::GetDesc failed."); + + TestPrint("=====================================\n"); + TestPrint("Testing DXGI Adapter and D3D10 Device\n"); + TestPrint("Description=%ls, VendorID=%x, DeviceID=%x\n", desc.Description, desc.VendorId, desc.DeviceId); + TestPrint("=====================================\n"); + + // run the test on the adapter + HarnessD3D10_CreateDevice(pAdapter, &pDevice); + + cl_uint num_devices = 0; + + // test adapter and device enumeration + TestAdapterEnumeration(platform, pAdapter, pDevice, &num_devices); + + // if there were any devices found in enumeration, run the tests on them + if (num_devices) + { + TestAdapterDevices(platform, pAdapter, pDevice, num_devices); + } + num_devices_tested += num_devices; + + // destroy the D3D10 device + if (pDevice) + { + HarnessD3D10_DestroyDevice(); + } + + pAdapter->Release(); + } + pFactory->Release(); + + NonTestRequire(num_devices_tested, "No D3D10 compatible cl_device_ids were found."); + + HarnessD3D10_TestStats(); +} + +void TestAdapterEnumeration(cl_platform_id platform, IDXGIAdapter* pAdapter, ID3D10Device* pDevice, cl_uint* num_devices) +{ + cl_uint num_adapter_devices = 0; + cl_device_id* adapter_devices = NULL; + + cl_uint num_device_devices = 0; + cl_device_id* device_devices = NULL; + + cl_int result; + + HarnessD3D10_TestBegin("cl_device_id Enumeration"); + + // get the cl_device_ids for the adapter + { + result = clGetDeviceIDsFromD3D10KHR( + platform, + CL_D3D10_DXGI_ADAPTER_KHR, + pAdapter, + CL_ALL_DEVICES_FOR_D3D10_KHR, + 0, + NULL, + &num_adapter_devices); + TestRequire( + (result == CL_SUCCESS || result == CL_DEVICE_NOT_FOUND), + "clGetDeviceIDsFromD3D10KHR failed."); + + if (result == CL_DEVICE_NOT_FOUND) + { + TestPrint("No devices found for adapter.\n"); + } + else + { + // if there were devices, query them + adapter_devices = new cl_device_id[num_adapter_devices]; + result = clGetDeviceIDsFromD3D10KHR( + platform, + CL_D3D10_DXGI_ADAPTER_KHR, + pAdapter, + CL_ALL_DEVICES_FOR_D3D10_KHR, + num_adapter_devices, + adapter_devices, + NULL); + TestRequire( + (result == CL_SUCCESS), + "clGetDeviceIDsFromD3D10KHR failed."); + } + } + + // get the cl_device_ids for the device (if it was successfully created) + if (pDevice) + { + result = clGetDeviceIDsFromD3D10KHR( + platform, + CL_D3D10_DEVICE_KHR, + pDevice, + CL_ALL_DEVICES_FOR_D3D10_KHR, + 0, + NULL, + &num_device_devices); + TestRequire( + (result == CL_SUCCESS || result == CL_DEVICE_NOT_FOUND), + "clGetDeviceIDsFromD3D10KHR failed."); + + if (result == CL_DEVICE_NOT_FOUND) + { + TestPrint("No devices found for D3D device.\n"); + } + else + { + // if there were devices, query them + device_devices = new cl_device_id[num_device_devices]; + result = clGetDeviceIDsFromD3D10KHR( + platform, + CL_D3D10_DEVICE_KHR, + pDevice, + CL_ALL_DEVICES_FOR_D3D10_KHR, + num_device_devices, + device_devices, + NULL); + TestRequire( + (result == CL_SUCCESS), + "clGetDeviceIDsFromD3D10KHR failed."); + } + + // require that each cl_device_id returned for the ID3D10Device was among the devices listed for the adapter + for (cl_uint device_device = 0; device_device < num_device_devices; ++device_device) + { + cl_uint adapter_device; + for (adapter_device = 0; adapter_device < num_adapter_devices; ++adapter_device) + { + if (device_devices[device_device] == adapter_devices[adapter_device]) + { + break; + } + } + TestRequire( + (adapter_device != num_adapter_devices), + "CL_D3D10_DEVICE_KHR devices not a subset of CL_D3D10_DXGI_ADAPTER_KHR devices"); + } + } + +Cleanup: + + if (adapter_devices) + { + delete[] adapter_devices; + } + if (device_devices) + { + delete[] device_devices; + } + + *num_devices = num_device_devices; + + HarnessD3D10_TestEnd(); +} + +void TestAdapterDevices(cl_platform_id platform, IDXGIAdapter* pAdapter, ID3D10Device* pDevice, cl_uint num_devices_expected) +{ + cl_int result; + cl_uint num_devices = 0; + cl_device_id* devices = NULL; + char extensions[8192]; + + devices = new cl_device_id[num_devices_expected]; + NonTestRequire( + devices, + "Memory allocation failure."); + + result = clGetDeviceIDsFromD3D10KHR( + platform, + CL_D3D10_DEVICE_KHR, + pDevice, + CL_ALL_DEVICES_FOR_D3D10_KHR, + num_devices_expected, + devices, + &num_devices); + NonTestRequire( + (result == CL_SUCCESS), + "clGetDeviceIDsFromD3D10KHR failed."); + NonTestRequire( + (num_devices == num_devices_expected), + "clGetDeviceIDsFromD3D10KHR returned an unexpected number of devices."); + + for (cl_uint i = 0; i < num_devices; ++i) + { + // make sure the device supports the extension + result = clGetDeviceInfo(devices[i], CL_DEVICE_EXTENSIONS, sizeof(extensions), extensions, NULL); NonTestRequire(result == CL_SUCCESS, "Failed to get extensions."); + if (strstr(extensions, "cl_khr_d3d10_sharing") == NULL) { + TestPrint("Device does not support cl_khr_d3d10_sharing extension\n"); + continue; + } + + TestDevice(devices[i], pDevice); + } +} + +void TestDevice(cl_device_id device, ID3D10Device* pDevice) +{ + char device_name[1024]; + cl_int result = CL_SUCCESS; + cl_context context = NULL; + cl_command_queue command_queue = NULL; + cl_bool prefer_shared_resources = CL_FALSE; + ID3D10Device* clDevice = NULL; + + result = clGetDeviceInfo( + device, + CL_DEVICE_NAME, + sizeof(device_name), + device_name, + NULL); + NonTestRequire(CL_SUCCESS == result, "clGetDeviceInfo with CL_DEVICE_NAME failed"); + TestPrint("--------------------\n"); + TestPrint("Testing cl_device_id\n"); + TestPrint("Name=%s\n", device_name); + TestPrint("--------------------\n"); + + if (!TestDeviceContextCreate(device, pDevice, &context, &command_queue) ) + { + return; + } + + // make sure that we can query the shared resource preference + result = clGetContextInfo( + context, + CL_CONTEXT_D3D10_PREFER_SHARED_RESOURCES_KHR, + sizeof(prefer_shared_resources), + &prefer_shared_resources, + NULL); + NonTestRequire(CL_SUCCESS == result, "clGetContextInfo with CL_CONTEXT_D3D10_PREFER_SHARED_RESOURCES_KHR failed"); + + // run buffer tests + TestDeviceBuffer( + context, + command_queue, + pDevice); + + // run 2D texture tests + TestDeviceTexture2D( + device, + context, + command_queue, + pDevice); + + // run 3D texture tests + TestDeviceTexture3D( + device, + context, + command_queue, + pDevice); + + // run misc tests + TestDeviceMisc( + device, + context, + command_queue, + pDevice); + + clReleaseContext(context); + clReleaseCommandQueue(command_queue); +} + +bool TestDeviceContextCreate( + cl_device_id device, + ID3D10Device* pDevice, + cl_context* out_context, + cl_command_queue* out_command_queue) +{ + cl_int result = CL_SUCCESS; + cl_context context = NULL; + cl_command_queue command_queue = NULL; + + ID3D10Device* clDevice = NULL; + + bool succeeded = false; + + HarnessD3D10_TestBegin("Context creation"); + + cl_context_properties properties[5]; + + // create the context + properties[0] = (cl_context_properties)CL_CONTEXT_D3D10_DEVICE_KHR; + properties[1] = (cl_context_properties)pDevice; + properties[2] = (cl_context_properties)CL_CONTEXT_INTEROP_USER_SYNC; + properties[3] = (cl_context_properties)CL_TRUE; + properties[4] = (cl_context_properties)0; + context = clCreateContext( + properties, + 1, + &device, + NULL, + NULL, + &result); + TestRequire( + (result == CL_SUCCESS), + "clCreateContext with CL_CONTEXT_D3D10_DEVICE_KHR failed"); + result = clReleaseContext(context); + TestRequire( + (result == CL_SUCCESS), + "clReleaseContext with CL_CONTEXT_D3D10_DEVICE_KHR failed"); + + // create the context + properties[0] = (cl_context_properties)CL_CONTEXT_D3D10_DEVICE_KHR; + properties[1] = (cl_context_properties)pDevice; + properties[2] = (cl_context_properties)CL_CONTEXT_INTEROP_USER_SYNC; + properties[3] = (cl_context_properties)CL_FALSE; + properties[4] = (cl_context_properties)0; + context = clCreateContext( + properties, + 1, + &device, + NULL, + NULL, + &result); + TestRequire( + (result == CL_SUCCESS), + "clCreateContext with CL_CONTEXT_D3D10_DEVICE_KHR failed"); + result = clReleaseContext(context); + TestRequire( + (result == CL_SUCCESS), + "clReleaseContext with CL_CONTEXT_D3D10_DEVICE_KHR failed"); + + // create the context + properties[0] = (cl_context_properties)CL_CONTEXT_D3D10_DEVICE_KHR; + properties[1] = (cl_context_properties)pDevice; + properties[2] = (cl_context_properties)0; + context = clCreateContext( + properties, + 1, + &device, + NULL, + NULL, + &result); + TestRequire( + (result == CL_SUCCESS), + "clCreateContext with CL_CONTEXT_D3D10_DEVICE_KHR failed"); + + // create the command queue + TestPrint("Creating a command queue.\n"); + command_queue = clCreateCommandQueueWithProperties( + context, + device, + NULL, + &result); + TestRequire( + (result == CL_SUCCESS), + "clCreateContext with CL_CONTEXT_D3D10_DEVICE_KHR failed"); + + succeeded = true; + +Cleanup: + + if (succeeded) + { + *out_context = context; + *out_command_queue = command_queue; + } + else + { + if (context) + { + clReleaseContext(context); + } + if (command_queue) + { + clReleaseCommandQueue(command_queue); + } + } + HarnessD3D10_TestEnd(); + return succeeded; +} + +#else + +#include "errorHelpers.h" + +int main(int argc, char* argv[]) +{ + log_info( "Windows-specific test skipped.\n" ); + return 0; +} + +#endif diff --git a/test_conformance/d3d10/misc.cpp b/test_conformance/d3d10/misc.cpp new file mode 100644 index 00000000..4ccd492e --- /dev/null +++ b/test_conformance/d3d10/misc.cpp @@ -0,0 +1,259 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "harness.h" + +void SubTestMiscMultipleCreates( + cl_context context, + cl_command_queue command_queue, + ID3D10Device* pDevice) +{ + ID3D10Buffer* pBuffer = NULL; + ID3D10Texture2D* pTexture = NULL; + HRESULT hr = S_OK; + cl_mem mem[5] = {NULL, NULL, NULL, NULL, NULL}; + cl_int result = CL_SUCCESS; + + HarnessD3D10_TestBegin("Misc: Multiple Creates"); + + // create the D3D10 resources + { + D3D10_TEXTURE2D_DESC desc; + memset(&desc, 0, sizeof(desc) ); + desc.Width = 256; + desc.Height = 256; + desc.MipLevels = 4; + desc.ArraySize = 4; + desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + hr = pDevice->CreateTexture2D(&desc, NULL, &pTexture); + TestRequire(SUCCEEDED(hr), "Failed to create texture."); + } + + // create the D3D10 buffer + { + D3D10_BUFFER_DESC desc = {0}; + desc.ByteWidth = 1024; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.CPUAccessFlags = 0; + desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; + desc.MiscFlags = 0; + hr = pDevice->CreateBuffer(&desc, NULL, &pBuffer); + TestRequire(SUCCEEDED(hr), "Creating vertex buffer failed!"); + } + + mem[0] = clCreateFromD3D10BufferKHR( + context, + 0, + pBuffer, + &result); + TestRequire(result == CL_SUCCESS, "clCreateFromD3D10BufferKHR"); + + mem[1] = clCreateFromD3D10BufferKHR( + context, + 0, + pBuffer, + &result); + TestRequire(result == CL_INVALID_D3D10_RESOURCE_KHR, "clCreateFromD3D10BufferKHR succeeded when it shouldn't"); + + mem[2] = clCreateFromD3D10Texture2DKHR( + context, + 0, + pTexture, + 1, + &result); + TestRequire(result == CL_SUCCESS, "clCreateFromD3D10Texture2DKHR failed"); + + mem[3] = clCreateFromD3D10Texture2DKHR( + context, + 0, + pTexture, + 1, + &result); + TestRequire(result == CL_INVALID_D3D10_RESOURCE_KHR, "clCreateFromD3D10Texture2DKHR succeeded when it shouldn't"); + + mem[4] = clCreateFromD3D10Texture2DKHR( + context, + 0, + pTexture, + 16, + &result); + TestRequire(result == CL_INVALID_VALUE, "clCreateFromD3D10Texture2DKHR succeeded when it shouldn't"); + + +Cleanup: + + for (UINT i = 0; i < 4; ++i) + { + if (mem[i]) + { + clReleaseMemObject(mem[i]); + } + } + if (pBuffer) + { + pBuffer->Release(); + } + if (pTexture) + { + pTexture->Release(); + } + + HarnessD3D10_TestEnd(); +} + +void SubTestMiscAcquireRelease( + cl_context context, + cl_command_queue command_queue, + ID3D10Device* pDevice) +{ + ID3D10Buffer* pBuffer = NULL; + ID3D10Texture2D* pTexture = NULL; + HRESULT hr = S_OK; + + cl_int result = CL_SUCCESS; + cl_mem mem[2] = {NULL, NULL}; + + HarnessD3D10_TestBegin("Misc: Acquire Release"); + + // create the D3D10 resources + { + D3D10_TEXTURE2D_DESC desc; + memset(&desc, 0, sizeof(desc) ); + desc.Width = 256; + desc.Height = 256; + desc.MipLevels = 4; + desc.ArraySize = 4; + desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + hr = pDevice->CreateTexture2D(&desc, NULL, &pTexture); + TestRequire(SUCCEEDED(hr), "Failed to create texture."); + } + + // create the D3D10 buffer + { + D3D10_BUFFER_DESC desc = {0}; + desc.ByteWidth = 1024; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.CPUAccessFlags = 0; + desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; + desc.MiscFlags = 0; + hr = pDevice->CreateBuffer(&desc, NULL, &pBuffer); + TestRequire(SUCCEEDED(hr), "Creating vertex buffer failed!"); + } + + // create cl_mem objects for the resources + mem[0] = clCreateFromD3D10BufferKHR( + context, + 0, + pBuffer, + &result); + TestRequire(result == CL_SUCCESS, "clCreateFromD3D10BufferKHR"); + mem[1] = clCreateFromD3D10Texture2DKHR( + context, + 0, + pTexture, + 1, + &result); + TestRequire(result == CL_SUCCESS, "clCreateFromD3D10Texture2DKHR failed"); + + // test some acquire/release patterns + result = clEnqueueAcquireD3D10ObjectsKHR( + command_queue, + 1, + &mem[1], + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueAcquireD3D10ObjectsKHR failed."); + + result = clEnqueueAcquireD3D10ObjectsKHR( + command_queue, + 1, + &mem[0], + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueAcquireD3D10ObjectsKHR failed."); + + result = clEnqueueReleaseD3D10ObjectsKHR( + command_queue, + 1, + &mem[1], + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueReleaseD3D10ObjectsKHR failed."); + + + result = clEnqueueReleaseD3D10ObjectsKHR( + command_queue, + 1, + &mem[0], + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueReleaseD3D10ObjectsKHR failed."); + +Cleanup: + + for (UINT i = 0; i < 2; ++i) + { + if (mem[i]) + { + clReleaseMemObject(mem[i]); + } + } + if (pBuffer) + { + pBuffer->Release(); + } + if (pTexture) + { + pTexture->Release(); + } + + HarnessD3D10_TestEnd(); +} + +void TestDeviceMisc( + cl_device_id device, + cl_context context, + cl_command_queue command_queue, + ID3D10Device* pDevice) +{ + SubTestMiscMultipleCreates( + context, + command_queue, + pDevice); + + SubTestMiscAcquireRelease( + context, + command_queue, + pDevice); +} + diff --git a/test_conformance/d3d10/texture2d.cpp b/test_conformance/d3d10/texture2d.cpp new file mode 100644 index 00000000..123ba3f8 --- /dev/null +++ b/test_conformance/d3d10/texture2d.cpp @@ -0,0 +1,694 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#define _CRT_SECURE_NO_WARNINGS +#include "harness.h" + +Texture2DSize texture2DSizes[] = +{ + { + 4, // Width + 4, // Height + 1, // MipLevels + 1, // ArraySize + 1, // SubResourceCount + { // SubResources + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, + { + 15, // Width + 37, // Height + 2, // MipLevels + 1, // ArraySize + 2, // SubResourceCount + { // SubResources + {0, 0}, // MipLevel, ArraySlice + {1, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, + { + 65, // Width + 17, // Height + 1, // MipLevels + 1, // ArraySize + 1, // SubResourceCount + { // SubResources + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + }, + D3D10_RESOURCE_MISC_SHARED, // MiscFlags + }, + + { + 127, // Width + 125, // Height + 4, // MipLevels + 1, // ArraySize + 4, // SubResourceCount + { // SubResources + {3, 0}, // MipLevel, ArraySlice + {2, 0}, // MipLevel, ArraySlice + {1, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, + { + 128, // Width + 128, // Height + 4, // MipLevels + 6, // ArraySize + 4, // SubResourceCount + { // SubResources + {0, 1}, // MipLevel, ArraySlice + {1, 0}, // MipLevel, ArraySlice + {0, 2}, // MipLevel, ArraySlice + {3, 5}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, + { + 256, // Width + 256, // Height + 0, // MipLevels + 256, // ArraySize + 4, // SubResourceCount + { // SubResources + {0, 0}, // MipLevel, ArraySlice + {1, 255}, // MipLevel, ArraySlice + {2, 127}, // MipLevel, ArraySlice + {3, 128}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, + { + 258, // Width + 511, // Height + 1, // MipLevels + 1, // ArraySize + 1, // SubResourceCount + { // SubResources + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, + { + 767, // Width + 1025, // Height + 4, // MipLevels + 1, // ArraySize + 1, // SubResourceCount + { // SubResources + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, + { + 2048, // Width + 2048, // Height + 1, // MipLevels + 1, // ArraySize + 1, // SubResourceCount + { // SubResources + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, +}; +UINT texture2DSizeCount = sizeof(texture2DSizes)/sizeof(texture2DSizes[0]); + +const char * +texture2DPatterns[2][2] = +{ + {"aAbBcCdDeEfFgGhHiIjJ", "AaBbCcDdEeFfGgHhIiJj"}, + {"zZyYxXwWvVuUtTsSrRqQ", "ZzYyXxWwVvUuTtSsRrQq"}, +}; + +void SubTestTexture2D( + cl_context context, + cl_command_queue command_queue, + cl_kernel kernel, + ID3D10Device* pDevice, + const TextureFormat* format, + const Texture2DSize* size) +{ + ID3D10Texture2D* pTexture = NULL; + HRESULT hr = S_OK; + + cl_int result = CL_SUCCESS; + + HarnessD3D10_TestBegin("2D Texture: Format=%s, Width=%d, Height=%d, MipLevels=%d, ArraySize=%d", + format->name_format, + size->Width, + size->Height, + size->MipLevels, + size->ArraySize); + + struct + { + cl_mem mem; + UINT subResource; + UINT width; + UINT height; + } + subResourceInfo[4]; + + cl_event events[4] = {NULL, NULL, NULL, NULL}; + + // create the D3D10 resources + { + D3D10_TEXTURE2D_DESC desc; + memset(&desc, 0, sizeof(desc) ); + desc.Width = size->Width; + desc.Height = size->Height; + desc.MipLevels = size->MipLevels; + desc.ArraySize = size->ArraySize; + desc.Format = format->format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + hr = pDevice->CreateTexture2D(&desc, NULL, &pTexture); + TestRequire(SUCCEEDED(hr), "ID3D10Device::CreateTexture2D failed (non-OpenCL D3D error, but test is invalid)."); + } + + // initialize some useful variables + for (UINT i = 0; i < size->SubResourceCount; ++i) + { + // compute the expected values for the subresource + subResourceInfo[i].subResource = D3D10CalcSubresource( + size->subResources[i].MipLevel, + size->subResources[i].ArraySlice, + size->MipLevels); + subResourceInfo[i].width = size->Width; + subResourceInfo[i].height = size->Height; + for (UINT j = 0; j < size->subResources[i].MipLevel; ++j) { + subResourceInfo[i].width /= 2; + subResourceInfo[i].height /= 2; + } + } + + // copy a pattern into the corners of the image, coordinates + // (0,0), (w,0-1), (0,h-1), (w-1,h-1) + for (UINT i = 0; i < size->SubResourceCount; ++i) + for (UINT x = 0; x < 2; ++x) + for (UINT y = 0; y < 2; ++y) + { + // create the staging buffer + ID3D10Texture2D* pStagingBuffer = NULL; + { + D3D10_TEXTURE2D_DESC desc = {0}; + desc.Width = 1; + desc.Height = 1; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = format->format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D10_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + hr = pDevice->CreateTexture2D(&desc, NULL, &pStagingBuffer); + TestRequire(SUCCEEDED(hr), "ID3D10Device::CreateTexture2D failed (non-OpenCL D3D error, but test is invalid)."); + } + + // write the data to the staging buffer + { + D3D10_MAPPED_TEXTURE2D mappedTexture; + hr = pStagingBuffer->Map( + 0, + D3D10_MAP_READ_WRITE, + 0, + &mappedTexture); + memcpy(mappedTexture.pData, texture2DPatterns[x][y], format->bytesPerPixel); + pStagingBuffer->Unmap(0); + } + + // copy the data to to the texture + { + D3D10_BOX box = {0}; + box.front = 0; box.back = 1; + box.top = 0; box.bottom = 1; + box.left = 0; box.right = 1; + pDevice->CopySubresourceRegion( + pTexture, + subResourceInfo[i].subResource, + x ? subResourceInfo[i].width - 1 : 0, + y ? subResourceInfo[i].height - 1 : 0, + 0, + pStagingBuffer, + 0, + &box); + } + + pStagingBuffer->Release(); + } + + // create the cl_mem objects for the resources and verify its sanity + for (UINT i = 0; i < size->SubResourceCount; ++i) + { + // create a cl_mem for the resource + subResourceInfo[i].mem = clCreateFromD3D10Texture2DKHR( + context, + 0, + pTexture, + subResourceInfo[i].subResource, + &result); + TestRequire(result == CL_SUCCESS, "clCreateFromD3D10Texture2DKHR failed"); + + // query resource pointer and verify + ID3D10Resource* clResource = NULL; + result = clGetMemObjectInfo( + subResourceInfo[i].mem, + CL_MEM_D3D10_RESOURCE_KHR, + sizeof(clResource), + &clResource, + NULL); + TestRequire(result == CL_SUCCESS, "clGetMemObjectInfo for CL_MEM_D3D10_RESOURCE_KHR failed."); + TestRequire(clResource == pTexture, "clGetMemObjectInfo for CL_MEM_D3D10_RESOURCE_KHR returned incorrect value."); + + // query subresource and verify + UINT clSubResource; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_D3D10_SUBRESOURCE_KHR, + sizeof(clSubResource), + &clSubResource, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_D3D10_SUBRESOURCE_KHR failed"); + TestRequire(clSubResource == subResourceInfo[i].subResource, "clGetImageInfo for CL_IMAGE_D3D10_SUBRESOURCE_KHR returned incorrect value."); + + // query format and verify + cl_image_format clFormat; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_FORMAT, + sizeof(clFormat), + &clFormat, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_FORMAT failed"); + TestRequire(clFormat.image_channel_order == format->channel_order, "clGetImageInfo for CL_IMAGE_FORMAT returned incorrect channel order."); + TestRequire(clFormat.image_channel_data_type == format->channel_type, "clGetImageInfo for CL_IMAGE_FORMAT returned incorrect channel data type."); + + // query width + size_t width; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_WIDTH, + sizeof(width), + &width, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_WIDTH failed"); + TestRequire(width == subResourceInfo[i].width, "clGetImageInfo for CL_IMAGE_HEIGHT returned incorrect value."); + + // query height + size_t height; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_HEIGHT, + sizeof(height), + &height, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_HEIGHT failed"); + TestRequire(height == subResourceInfo[i].height, "clGetImageInfo for CL_IMAGE_HEIGHT returned incorrect value."); + + } + + // acquire the resources for OpenCL + for (UINT i = 0; i < 2; ++i) + { + cl_uint memCount = 0; + cl_mem memToAcquire[MAX_REGISTERED_SUBRESOURCES]; + + // cut the registered sub-resources into two sets and send the acquire calls for them separately + if (i == 0) + { + for(UINT j = 0; j < size->SubResourceCount/2; ++j) + { + memToAcquire[memCount++] = subResourceInfo[j].mem; + } + } + else + { + for(UINT j = size->SubResourceCount/2; j < size->SubResourceCount; ++j) + { + memToAcquire[memCount++] = subResourceInfo[j].mem; + } + } + if (!memCount) continue; + + // do the acquire + result = clEnqueueAcquireD3D10ObjectsKHR( + command_queue, + memCount, + memToAcquire, + 0, + NULL, + &events[0+i]); + TestRequire(result == CL_SUCCESS, "clEnqueueAcquireD3D10ObjectsKHR failed."); + TestRequire(events[0+i], "clEnqueueAcquireD3D10ObjectsKHR did not return an event."); + + // make sure the event type is correct + cl_uint eventType = 0; + result = clGetEventInfo( + events[0+i], + CL_EVENT_COMMAND_TYPE, + sizeof(eventType), + &eventType, + NULL); + TestRequire(result == CL_SUCCESS, "clGetEventInfo for event created by clEnqueueAcquireD3D10ObjectsKHR failed."); + TestRequire(eventType == CL_COMMAND_ACQUIRE_D3D10_OBJECTS_KHR, "clGetEventInfo for CL_EVENT_COMMAND_TYPE was not CL_COMMAND_ACQUIRE_D3D10_OBJECTS_KHR."); + } + + // download the data using OpenCL & compare with the expected results + for (UINT i = 0; i < size->SubResourceCount; ++i) + { + // copy (0,0) to (1,1) and (w-1,h-1) to (w-2,h-2) using a kernel + { + result = clSetKernelArg( + kernel, + 0, + sizeof(cl_mem), + (void *)&subResourceInfo[i].mem); + result = clSetKernelArg( + kernel, + 1, + sizeof(cl_mem), + (void *)&subResourceInfo[i].mem); + + TestRequire(CL_SUCCESS == result, "clSetKernelArg failed"); + + size_t localWorkSize[] = {1}; + size_t globalWorkSize[] = {1}; + result = clEnqueueNDRangeKernel( + command_queue, + kernel, + 1, + NULL, + globalWorkSize, + localWorkSize, + 0, + NULL, + NULL); + TestRequire(CL_SUCCESS == result, "clEnqueueNDRangeKernel failed"); + } + // copy (w-1,0) to (w-2,1) and (0,h) to (1,h-2) using a memcpy + for (UINT x = 0; x < 2; ++x) + for (UINT y = 0; y < 2; ++y) + { + if (x == y) + { + continue; + } + + size_t src[3] = + { + x ? subResourceInfo[i].width - 1 : 0, + y ? subResourceInfo[i].height - 1 : 0, + 0, + }; + size_t dst[3] = + { + x ? subResourceInfo[i].width - 2 : 1, + y ? subResourceInfo[i].height - 2 : 1, + 0, + }; + size_t region[3] = + { + 1, + 1, + 1, + }; + result = clEnqueueCopyImage( + command_queue, + subResourceInfo[i].mem, + subResourceInfo[i].mem, + src, + dst, + region, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueCopyImage failed."); + } + } + + // release the resource from OpenCL + for (UINT i = 0; i < 2; ++i) + { + cl_uint memCount = 0; + cl_mem memToAcquire[MAX_REGISTERED_SUBRESOURCES]; + + // cut the registered sub-resources into two sets and send the release calls for them separately + if (i == 0) + { + for(UINT j = size->SubResourceCount/4; j < size->SubResourceCount; ++j) + { + memToAcquire[memCount++] = subResourceInfo[j].mem; + } + } + else + { + for(UINT j = 0; j < size->SubResourceCount/4; ++j) + { + memToAcquire[memCount++] = subResourceInfo[j].mem; + } + } + if (!memCount) continue; + + // do the release + result = clEnqueueReleaseD3D10ObjectsKHR( + command_queue, + memCount, + memToAcquire, + 0, + NULL, + &events[2+i]); + TestRequire(result == CL_SUCCESS, "clEnqueueReleaseD3D10ObjectsKHR failed."); + TestRequire(events[2+i], "clEnqueueReleaseD3D10ObjectsKHR did not return an event."); + + // make sure the event type is correct + cl_uint eventType = 0; + result = clGetEventInfo( + events[2+i], + CL_EVENT_COMMAND_TYPE, + sizeof(eventType), + &eventType, + NULL); + TestRequire(result == CL_SUCCESS, "clGetEventInfo for event created by clEnqueueReleaseD3D10ObjectsKHR failed."); + TestRequire(eventType == CL_COMMAND_RELEASE_D3D10_OBJECTS_KHR, "clGetEventInfo for CL_EVENT_COMMAND_TYPE was not CL_COMMAND_RELEASE_D3D10_OBJECTS_KHR."); + } + + for (UINT i = 0; i < size->SubResourceCount; ++i) + for (UINT x = 0; x < 2; ++x) + for (UINT y = 0; y < 2; ++y) + { + // create the staging buffer + ID3D10Texture2D* pStagingBuffer = NULL; + { + D3D10_TEXTURE2D_DESC desc = {0}; + desc.Width = 1; + desc.Height = 1; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = format->format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D10_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + hr = pDevice->CreateTexture2D(&desc, NULL, &pStagingBuffer); + TestRequire(SUCCEEDED(hr), "Failed to create staging buffer."); + } + + // wipe out the staging buffer to make sure we don't get stale values + { + D3D10_MAPPED_TEXTURE2D mappedTexture; + hr = pStagingBuffer->Map( + 0, + D3D10_MAP_READ_WRITE, + 0, + &mappedTexture); + TestRequire(SUCCEEDED(hr), "Failed to map staging buffer"); + memset(mappedTexture.pData, 0, format->bytesPerPixel); + pStagingBuffer->Unmap(0); + } + + // copy the pixel to the staging buffer + { + D3D10_BOX box = {0}; + box.left = x ? subResourceInfo[i].width - 2 : 1; box.right = box.left + 1; + box.top = y ? subResourceInfo[i].height - 2 : 1; box.bottom = box.top + 1; + box.front = 0; box.back = 1; + pDevice->CopySubresourceRegion( + pStagingBuffer, + 0, + 0, + 0, + 0, + pTexture, + subResourceInfo[i].subResource, + &box); + } + + // make sure we read back what was written next door + { + D3D10_MAPPED_TEXTURE2D mappedTexture; + hr = pStagingBuffer->Map( + 0, + D3D10_MAP_READ_WRITE, + 0, + &mappedTexture); + TestRequire(SUCCEEDED(hr), "Failed to map staging buffer"); + + /* + // This can be helpful in debugging... + printf("\n"); + for (UINT k = 0; k < format->bytesPerPixel; ++k) + { + printf("[%c %c]\n", + texture2DPatterns[x][y][k], + ( (char *)mappedTexture.pData )[k]); + } + */ + + TestRequire( + !memcmp(mappedTexture.pData, texture2DPatterns[x][y], format->bytesPerPixel), + "Failed to map staging buffer"); + + pStagingBuffer->Unmap(0); + } + + pStagingBuffer->Release(); + } + + +Cleanup: + + if (pTexture) + { + pTexture->Release(); + } + for (UINT i = 0; i < size->SubResourceCount; ++i) + { + clReleaseMemObject(subResourceInfo[i].mem); + } + for (UINT i = 0; i < 4; ++i) + { + if (events[i]) + { + result = clReleaseEvent(events[i]); + TestRequire(result == CL_SUCCESS, "clReleaseEvent for event failed."); + } + } + + HarnessD3D10_TestEnd(); +} + +void TestDeviceTexture2D( + cl_device_id device, + cl_context context, + cl_command_queue command_queue, + ID3D10Device* pDevice) +{ + cl_int result = CL_SUCCESS; + cl_kernel kernels[3] = {NULL, NULL, NULL}; + + const char *sourceRaw = + " \ + __kernel void texture2D\n\ + ( \n\ + __read_only image2d_t texIn, \n\ + __write_only image2d_t texOut \n\ + ) \n\ + { \n\ + const sampler_t smp = CLK_FILTER_NEAREST; \n\ + %s value; \n\ + int2 coordIn; \n\ + int2 coordOut; \n\ + int w = get_image_width(texIn); \n\ + int h = get_image_height(texIn); \n\ + \n\ + coordIn = (int2)(0, 0); \n\ + coordOut = (int2)(1, 1); \n\ + value = read_image%s(texIn, smp, coordIn); \n\ + write_image%s(texOut, coordOut, value); \n\ + \n\ + coordIn = (int2)(w-1, h-1); \n\ + coordOut = (int2)(w-2, h-2); \n\ + value = read_image%s(texIn, smp, coordIn); \n\ + write_image%s(texOut, coordOut, value); \n\ + } \n\ + "; + + char source[2048]; + sprintf(source, sourceRaw, "float4", "f", "f", "f", "f"); + result = HarnessD3D10_CreateKernelFromSource(&kernels[0], device, context, source, "texture2D"); + TestRequire(CL_SUCCESS == result, "HarnessD3D10_CreateKernelFromSource failed."); + + sprintf(source, sourceRaw, "uint4", "ui", "ui", "ui", "ui"); + result = HarnessD3D10_CreateKernelFromSource(&kernels[1], device, context, source, "texture2D"); + TestRequire(CL_SUCCESS == result, "HarnessD3D10_CreateKernelFromSource failed."); + + sprintf(source, sourceRaw, "int4", "i", "i", "i", "i"); + result = HarnessD3D10_CreateKernelFromSource(&kernels[2], device, context, source, "texture2D"); + TestRequire(CL_SUCCESS == result, "HarnessD3D10_CreateKernelFromSource failed."); + + for (UINT format = 0, size = 0; format < formatCount; ++size, ++format) + { + SubTestTexture2D( + context, + command_queue, + kernels[formats[format].generic], + pDevice, + &formats[format], + &texture2DSizes[size % texture2DSizeCount]); + } + +Cleanup: + + for (UINT i = 0; i < 3; ++i) + { + if (kernels[i]) + { + clReleaseKernel(kernels[i]); + } + } +} + diff --git a/test_conformance/d3d10/texture3d.cpp b/test_conformance/d3d10/texture3d.cpp new file mode 100644 index 00000000..39bcff47 --- /dev/null +++ b/test_conformance/d3d10/texture3d.cpp @@ -0,0 +1,491 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#define _CRT_SECURE_NO_WARNINGS +#include "harness.h" + +Texture3DSize texture3DSizes[] = +{ + { + 4, // Width + 4, // Height + 4, // Depth + 1, // MipLevels + 1, // SubResourceCount + { // SubResources + { 0 }, // MipLevel + { 0 }, // MipLevel + { 0 }, // MipLevel + { 0 }, // MipLevel + }, + 0, // MiscFlags + }, + { + 127, // Width + 25, // Height + 33, // Depth + 1, // MipLevels + 1, // SubResourceCount + { // SubResources + { 0 }, // MipLevel + { 0 }, // MipLevel + { 0 }, // MipLevel + { 0 }, // MipLevel + }, + 0, // MiscFlags + }, + { + 128, // Width + 256, // Height + 64, // Depth + 4, // MipLevels + 3, // SubResourceCount + { // SubResources + { 2 }, // MipLevel + { 1 }, // MipLevel + { 0 }, // MipLevel + { 0 }, // MipLevel + }, + 0, // MiscFlags + }, + { + 512, // Width + 64, // Height + 32, // Depth + 3, // MipLevels + 1, // SubResourceCount + { // SubResources + { 2 }, // MipLevel + { 0 }, // MipLevel + { 0 }, // MipLevel + { 0 }, // MipLevel + }, + 0, // MiscFlags + }, +}; +UINT texture3DSizeCount = sizeof(texture3DSizes)/sizeof(texture3DSizes[0]); + +const char * +texture3DPatterns[2][2][2] = +{ + { + {"PlaceTheCasseroleDis", "hInAColdOvenPlaceACh"}, + {"airFacingTheOvenAndS", "itInItForeverThinkAb"}, + }, + { + {"outHowHungryYouAreWh", "enNightFallsDoNotTur"}, + {"nOnTheLightMyEyeBeca", "meInflamedIHateCamus"}, + }, +}; + +void SubTestTexture3D( + cl_context context, + cl_command_queue command_queue, + ID3D10Device* pDevice, + const TextureFormat* format, + const Texture3DSize* size) +{ + ID3D10Texture3D* pTexture = NULL; + HRESULT hr = S_OK; + + cl_int result = CL_SUCCESS; + + HarnessD3D10_TestBegin("3D Texture: Format=%s, Width=%d, Height=%d, Depth=%d, MipLevels=%d", + format->name_format, + size->Width, + size->Height, + size->Depth, + size->MipLevels); + + struct + { + cl_mem mem; + UINT subResource; + UINT width; + UINT height; + UINT depth; + } + subResourceInfo[4]; + + // create the D3D10 resources + { + D3D10_TEXTURE3D_DESC desc; + memset(&desc, 0, sizeof(desc) ); + desc.Width = size->Width; + desc.Height = size->Height; + desc.Depth = size->Depth; + desc.MipLevels = size->MipLevels; + desc.Format = format->format; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + hr = pDevice->CreateTexture3D(&desc, NULL, &pTexture); + TestRequire(SUCCEEDED(hr), "CreateTexture3D failed."); + } + + // initialize some useful variables + for (UINT i = 0; i < size->SubResourceCount; ++i) + { + // compute the expected values for the subresource + subResourceInfo[i].subResource = size->subResources[i].MipLevel; + subResourceInfo[i].width = size->Width; + subResourceInfo[i].height = size->Height; + subResourceInfo[i].depth = size->Depth; + for (UINT j = 0; j < size->subResources[i].MipLevel; ++j) { + subResourceInfo[i].width /= 2; + subResourceInfo[i].height /= 2; + subResourceInfo[i].depth /= 2; + } + } + + // copy a pattern into the corners of the image, coordinates + for (UINT i = 0; i < size->SubResourceCount; ++i) + for (UINT x = 0; x < 2; ++x) + for (UINT y = 0; y < 2; ++y) + for (UINT z = 0; z < 2; ++z) + { + // create the staging buffer + ID3D10Texture3D* pStagingBuffer = NULL; + { + D3D10_TEXTURE3D_DESC desc = {0}; + desc.Width = 1; + desc.Height = 1; + desc.Depth = 1; + desc.MipLevels = 1; + desc.Format = format->format; + desc.Usage = D3D10_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + hr = pDevice->CreateTexture3D(&desc, NULL, &pStagingBuffer); + TestRequire(SUCCEEDED(hr), "CreateTexture3D failed."); + } + + // write the data to the staging buffer + { + D3D10_MAPPED_TEXTURE3D mappedTexture; + hr = pStagingBuffer->Map( + 0, + D3D10_MAP_READ_WRITE, + 0, + &mappedTexture); + memcpy(mappedTexture.pData, texture3DPatterns[x][y][z], format->bytesPerPixel); + pStagingBuffer->Unmap(0); + } + + // copy the data to to the texture + { + D3D10_BOX box = {0}; + box.front = 0; box.back = 1; + box.top = 0; box.bottom = 1; + box.left = 0; box.right = 1; + pDevice->CopySubresourceRegion( + pTexture, + subResourceInfo[i].subResource, + x ? subResourceInfo[i].width - 1 : 0, + y ? subResourceInfo[i].height - 1 : 0, + z ? subResourceInfo[i].depth - 1 : 0, + pStagingBuffer, + 0, + &box); + } + + pStagingBuffer->Release(); + } + + // create the cl_mem objects for the resources and verify its sanity + for (UINT i = 0; i < size->SubResourceCount; ++i) + { + // create a cl_mem for the resource + subResourceInfo[i].mem = clCreateFromD3D10Texture3DKHR( + context, + 0, + pTexture, + subResourceInfo[i].subResource, + &result); + TestRequire(result == CL_SUCCESS, "clCreateFromD3D10Texture3DKHR failed"); + + // query resource pointer and verify + ID3D10Resource* clResource = NULL; + result = clGetMemObjectInfo( + subResourceInfo[i].mem, + CL_MEM_D3D10_RESOURCE_KHR, + sizeof(clResource), + &clResource, + NULL); + TestRequire(result == CL_SUCCESS, "clGetMemObjectInfo for CL_MEM_D3D10_RESOURCE_KHR failed."); + TestRequire(clResource == pTexture, "clGetMemObjectInfo for CL_MEM_D3D10_RESOURCE_KHR returned incorrect value."); + + // query subresource and verify + UINT clSubResource; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_D3D10_SUBRESOURCE_KHR, + sizeof(clSubResource), + &clSubResource, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_D3D10_SUBRESOURCE_KHR failed"); + TestRequire(clSubResource == subResourceInfo[i].subResource, "clGetImageInfo for CL_IMAGE_D3D10_SUBRESOURCE_KHR returned incorrect value."); + + // query format and verify + cl_image_format clFormat; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_FORMAT, + sizeof(clFormat), + &clFormat, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_FORMAT failed"); + TestRequire(clFormat.image_channel_order == format->channel_order, "clGetImageInfo for CL_IMAGE_FORMAT returned incorrect channel order."); + TestRequire(clFormat.image_channel_data_type == format->channel_type, "clGetImageInfo for CL_IMAGE_FORMAT returned incorrect channel data type."); + + // query width + size_t width; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_WIDTH, + sizeof(width), + &width, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_WIDTH failed"); + TestRequire(width == subResourceInfo[i].width, "clGetImageInfo for CL_IMAGE_HEIGHT returned incorrect value."); + + // query height + size_t height; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_HEIGHT, + sizeof(height), + &height, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_HEIGHT failed"); + TestRequire(height == subResourceInfo[i].height, "clGetImageInfo for CL_IMAGE_HEIGHT returned incorrect value."); + + // query depth + size_t depth; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_DEPTH, + sizeof(depth), + &depth, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_DEPTH failed"); + TestRequire(depth == subResourceInfo[i].depth, "clGetImageInfo for CL_IMAGE_DEPTH returned incorrect value."); + + } + + // acquire the resources for OpenCL + { + cl_mem memToAcquire[MAX_REGISTERED_SUBRESOURCES]; + + // cut the registered sub-resources into two sets and send the acquire calls for them separately + for(UINT i = 0; i < size->SubResourceCount; ++i) + { + memToAcquire[i] = subResourceInfo[i].mem; + } + + // do the acquire + result = clEnqueueAcquireD3D10ObjectsKHR( + command_queue, + size->SubResourceCount, + memToAcquire, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueAcquireD3D10ObjectsKHR failed."); + } + + // download the data using OpenCL & compare with the expected results + // copy the corners of the image into the image + for (UINT i = 0; i < size->SubResourceCount; ++i) + for (UINT x = 0; x < 2; ++x) + for (UINT y = 0; y < 2; ++y) + for (UINT z = 0; z < 2; ++z) + { + if (x == y && y == z && 0) + { + continue; + } + size_t src[3] = + { + x ? subResourceInfo[i].width - 1 : 0, + y ? subResourceInfo[i].height - 1 : 0, + z ? subResourceInfo[i].depth - 1 : 0, + }; + size_t dst[3] = + { + x ? subResourceInfo[i].width - 2 : 1, + y ? subResourceInfo[i].height - 2 : 1, + z ? subResourceInfo[i].depth - 2 : 1, + }; + size_t region[3] = + { + 1, + 1, + 1, + }; + result = clEnqueueCopyImage( + command_queue, + subResourceInfo[i].mem, + subResourceInfo[i].mem, + src, + dst, + region, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueCopyImage failed."); + } + + // release the resource from OpenCL + { + cl_mem memToAcquire[MAX_REGISTERED_SUBRESOURCES]; + for(UINT i = 0; i < size->SubResourceCount; ++i) + { + memToAcquire[i] = subResourceInfo[i].mem; + } + + // do the release + result = clEnqueueReleaseD3D10ObjectsKHR( + command_queue, + size->SubResourceCount, + memToAcquire, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueReleaseD3D10ObjectsKHR failed."); + } + + for (UINT i = 0; i < size->SubResourceCount; ++i) + for (UINT x = 0; x < 2; ++x) + for (UINT y = 0; y < 2; ++y) + for (UINT z = 0; z < 2; ++z) + { + // create the staging buffer + ID3D10Texture3D* pStagingBuffer = NULL; + { + D3D10_TEXTURE3D_DESC desc = {0}; + desc.Width = 1; + desc.Height = 1; + desc.Depth = 1; + desc.MipLevels = 1; + desc.Format = format->format; + desc.Usage = D3D10_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + hr = pDevice->CreateTexture3D(&desc, NULL, &pStagingBuffer); + TestRequire(SUCCEEDED(hr), "Failed to create staging buffer."); + } + + // wipe out the staging buffer to make sure we don't get stale values + { + D3D10_MAPPED_TEXTURE3D mappedTexture; + hr = pStagingBuffer->Map( + 0, + D3D10_MAP_READ_WRITE, + 0, + &mappedTexture); + TestRequire(SUCCEEDED(hr), "Failed to map staging buffer"); + memset(mappedTexture.pData, 0, format->bytesPerPixel); + pStagingBuffer->Unmap(0); + } + + // copy the pixel to the staging buffer + { + D3D10_BOX box = {0}; + box.left = x ? subResourceInfo[i].width - 2 : 1; box.right = box.left + 1; + box.top = y ? subResourceInfo[i].height - 2 : 1; box.bottom = box.top + 1; + box.front = z ? subResourceInfo[i].depth - 2 : 1; box.back = box.front + 1; + pDevice->CopySubresourceRegion( + pStagingBuffer, + 0, + 0, + 0, + 0, + pTexture, + subResourceInfo[i].subResource, + &box); + } + + // make sure we read back what was written next door + { + D3D10_MAPPED_TEXTURE3D mappedTexture; + hr = pStagingBuffer->Map( + 0, + D3D10_MAP_READ_WRITE, + 0, + &mappedTexture); + TestRequire(SUCCEEDED(hr), "Failed to map staging buffer"); + + /* + // This can be helpful in debugging... + printf("\n"); + for (UINT k = 0; k < format->bytesPerPixel; ++k) + { + printf("[%c %c]\n", + texture2DPatterns[x][y][k], + ( (char *)mappedTexture.pData )[k]); + } + */ + + TestRequire( + !memcmp(mappedTexture.pData, texture3DPatterns[x][y][z], format->bytesPerPixel), + "Failed to map staging buffer"); + + pStagingBuffer->Unmap(0); + } + + pStagingBuffer->Release(); + } + + +Cleanup: + + if (pTexture) + { + pTexture->Release(); + } + for (UINT i = 0; i < size->SubResourceCount; ++i) + { + clReleaseMemObject(subResourceInfo[i].mem); + } + + HarnessD3D10_TestEnd(); +} + + +void TestDeviceTexture3D( + cl_device_id device, + cl_context context, + cl_command_queue command_queue, + ID3D10Device* pDevice) +{ + cl_int result = CL_SUCCESS; + + + for (UINT format = 0, size = 0; format < formatCount; ++size, ++format) + { + SubTestTexture3D( + context, + command_queue, + pDevice, + &formats[format], + &texture3DSizes[size % texture3DSizeCount]); + } +} + diff --git a/test_conformance/d3d11/CMakeLists.txt b/test_conformance/d3d11/CMakeLists.txt new file mode 100644 index 00000000..21a035ed --- /dev/null +++ b/test_conformance/d3d11/CMakeLists.txt @@ -0,0 +1,47 @@ +if(WIN32) + +set(D3D11_INCLUDE_DIR $ENV{NV_TOOLS}/sdk/DirectX_Aug2009/Include) + +if(${ARCH} STREQUAL "i686") +set(D3D11_LIB_DIR $ENV{NV_TOOLS}/sdk/DirectX_Aug2009/Lib/x86) +endif(${ARCH} STREQUAL "i686") + +if(${ARCH} STREQUAL "x86_64") +set(D3D11_LIB_DIR $ENV{NV_TOOLS}/sdk/DirectX_Aug2009/Lib/x64) +endif(${ARCH} STREQUAL "x86_64") + +list(APPEND CLConform_INCLUDE_DIR ${D3D11_INCLUDE_DIR}) +include_directories (${CLConform_SOURCE_DIR}/test_common/harness + ${CLConform_INCLUDE_DIR} ) +link_directories(${CL_LIB_DIR}, ${D3D11_LIB_DIR}) + +list(APPEND CLConform_LIBRARIES d3d11 dxgi) + + +set(D3D11_SOURCES + buffer.cpp + texture2d.cpp + texture3d.cpp + misc.cpp + main.cpp + harness.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp) + +add_executable(conformance_test_d3d11 + ${D3D11_SOURCES}) + +set_source_files_properties( + ${D3D11_SOURCES} + PROPERTIES LANGUAGE CXX) + +TARGET_LINK_LIBRARIES(conformance_test_d3d11 + ${CLConform_LIBRARIES}) + +endif(WIN32) diff --git a/test_conformance/d3d11/buffer.cpp b/test_conformance/d3d11/buffer.cpp new file mode 100644 index 00000000..e10e45ca --- /dev/null +++ b/test_conformance/d3d11/buffer.cpp @@ -0,0 +1,321 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "harness.h" + +#define ADD_BUFFER_PROPERTIES(w, x, y, z) \ + { w, x, y, z, #x, #y, #z, } + +BufferProperties bufferProperties[] = +{ + ADD_BUFFER_PROPERTIES( 0x110, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE), + ADD_BUFFER_PROPERTIES( 0x1100, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE), + ADD_BUFFER_PROPERTIES( 0x8000, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE), + + ADD_BUFFER_PROPERTIES( 0x7FFFF, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x110000, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x110000, D3D11_BIND_STREAM_OUTPUT, D3D11_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x110001, D3D11_BIND_STREAM_OUTPUT, D3D11_USAGE_DEFAULT, 0), + + ADD_BUFFER_PROPERTIES( 0x11, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x11, D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE), + ADD_BUFFER_PROPERTIES( 0x121, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x1234, D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x12345, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE), + ADD_BUFFER_PROPERTIES( 0x123456, D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DEFAULT, 0), +#if 0 // avoid large sizes on automation + ADD_BUFFER_PROPERTIES( 0x1234567, D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE), + + ADD_BUFFER_PROPERTIES( 0x4000000, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x4000004, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x4000008, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x4000011, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0), + ADD_BUFFER_PROPERTIES( 0x4000014, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0), +#endif +}; +UINT bufferPropertyCount = sizeof(bufferProperties)/sizeof(bufferProperties[0]); + +void SubTestBuffer( + cl_context context, + cl_command_queue command_queue, + ID3D11Device* pDevice, + ID3D11DeviceContext* pDC, + const BufferProperties* props) +{ + ID3D11Buffer* pBuffer = NULL; + HRESULT hr = S_OK; + cl_mem mem = NULL; + cl_int result = CL_SUCCESS; + + HarnessD3D11_TestBegin("Buffer: Size=%d, BindFlags=%s, Usage=%s, CPUAccess=%s", + props->ByteWidth, + props->name_BindFlags, + props->name_Usage, + props->name_CPUAccess); + + // create the D3D11 resource + { + D3D11_BUFFER_DESC desc = {0}; + desc.ByteWidth = props->ByteWidth; + desc.Usage = props->Usage; + desc.CPUAccessFlags = props->CPUAccess; + desc.BindFlags = props->BindFlags; + desc.MiscFlags = 0; + hr = pDevice->CreateBuffer(&desc, NULL, &pBuffer); + TestRequire(SUCCEEDED(hr), "Creating vertex buffer failed!"); + } + + // populate the D3D11 resource with data + { + ID3D11Buffer* pStagingBuffer = NULL; + char *pStagingData = NULL; + D3D11_MAPPED_SUBRESOURCE map = {0}; + + // create a staging buffer to use to copy data to the D3D buffer + D3D11_BUFFER_DESC desc = {0}; + desc.ByteWidth = 16; + desc.Usage = D3D11_USAGE_STAGING; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE|D3D11_CPU_ACCESS_READ; + desc.BindFlags = 0; + desc.MiscFlags = 0; + hr = pDevice->CreateBuffer(&desc, NULL, &pStagingBuffer); + TestRequire(SUCCEEDED(hr), "Creating staging vertex buffer failed!"); + + // populate the staging buffer + hr = pDC->Map( + pStagingBuffer, + 0, + D3D11_MAP_READ_WRITE, + 0, + &map); + TestRequire(SUCCEEDED(hr), "Map failed!"); + memcpy(map.pData, "abcdXXXXxxxx1234", 16); + pDC->Unmap(pStagingBuffer, 0); + TestRequire(SUCCEEDED(hr), "Unmap failed!"); + + // copy 'abcdXXXX' to the front of the buffer and 'xxxx1234' to the back + D3D11_BOX box = {0}; + box.front = 0; + box.back = 1; + box.top = 0; + box.bottom = 1; + + box.left = 0; + box.right = 8; + pDC->CopySubresourceRegion( + pBuffer, + 0, + 0, + 0, + 0, + pStagingBuffer, + 0, + &box); + box.left = 8; + box.right = 16; + pDC->CopySubresourceRegion( + pBuffer, + 0, + props->ByteWidth-8, + 0, + 0, + pStagingBuffer, + 0, + &box); + pStagingBuffer->Release(); + } + + // share the resource with OpenCL + { + mem = clCreateFromD3D11BufferKHR( + context, + 0, + pBuffer, + &result); + TestRequire(CL_SUCCESS == result, "clCreateFromD3D11BufferKHR failed"); + } + + // validate the OpenCL mem obj's properties + { + ID3D11Resource* clResource = NULL; + result = clGetMemObjectInfo( + mem, + CL_MEM_D3D11_RESOURCE_KHR, + sizeof(clResource), + &clResource, + NULL); + TestRequire(result == CL_SUCCESS, "clGetMemObjectInfo for CL_MEM_D3D11_RESOURCE_KHR failed."); + TestRequire(clResource == pBuffer, "clGetMemObjectInfo for CL_MEM_D3D11_RESOURCE_KHR returned incorrect value."); + } + + // acquire the resource from OpenCL + { + result = clEnqueueAcquireD3D11ObjectsKHR( + command_queue, + 1, + &mem, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueAcquireD3D11ObjectsKHR failed."); + } + + // read+write data from the buffer in OpenCL + { + // overwrite the 'XXXX' with '1234' and the 'xxxx' with 'abcd' so we now have + // 'abcd1234' at the beginning and end of the buffer + result = clEnqueueCopyBuffer( + command_queue, + mem, + mem, + 0, + props->ByteWidth-8, + 4, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueCopyBuffer failed."); + + result = clEnqueueCopyBuffer( + command_queue, + mem, + mem, + props->ByteWidth-4, + 4, + 4, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueCopyBuffer failed."); + } + + // release the resource from OpenCL + { + result = clEnqueueReleaseD3D11ObjectsKHR( + command_queue, + 1, + &mem, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueReleaseD3D11ObjectsKHR failed."); + } + + // read data in D3D + { + ID3D11Buffer* pStagingBuffer = NULL; + char *pStagingData = NULL; + D3D11_MAPPED_SUBRESOURCE map = {0}; + + // create a staging buffer to read the data back + D3D11_BUFFER_DESC desc = {0}; + desc.ByteWidth = 16; + desc.Usage = D3D11_USAGE_STAGING; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE|D3D11_CPU_ACCESS_READ; + desc.BindFlags = 0; + desc.MiscFlags = 0; + hr = pDevice->CreateBuffer(&desc, NULL, &pStagingBuffer); + TestRequire(SUCCEEDED(hr), "Creating staging vertex buffer failed!"); + + // make sure the staging buffer doesn't get stale data + hr = pDC->Map( + pStagingBuffer, + 0, + D3D11_MAP_READ_WRITE, + 0, + &map); + TestRequire(SUCCEEDED(hr), "Map failed!"); + memset(map.pData, 0, 16); + pDC->Unmap(pStagingBuffer, 0); + TestRequire(SUCCEEDED(hr), "Unmap failed!"); + + // copy the 'abcd1234' from the front and back of the buffer to the staging buffer + D3D11_BOX box = {0}; + box.front = 0; + box.back = 1; + box.top = 0; + box.bottom = 1; + + box.left = 0; + box.right = 8; + pDC->CopySubresourceRegion( + pStagingBuffer, + 0, + 0, + 0, + 0, + pBuffer, + 0, + &box); + box.left = props->ByteWidth-8; + box.right = props->ByteWidth; + pDC->CopySubresourceRegion( + pStagingBuffer, + 0, + 8, + 0, + 0, + pBuffer, + 0, + &box); + TestRequire(SUCCEEDED(hr), "CopySubresourceRegion failed!"); + + // verify that we got the 'abcd1234' + hr = pDC->Map( + pStagingBuffer, + 0, + D3D11_MAP_READ_WRITE, + 0, + &map); + TestRequire(SUCCEEDED(hr), "Map failed!"); + TestRequire(!memcmp(map.pData, "abcd1234abcd1234", 16), "Data was not accurately"); + pDC->Unmap(pStagingBuffer, 0); + TestRequire(SUCCEEDED(hr), "Unmap failed!"); + + pStagingBuffer->Release(); + } + +Cleanup: + + if (pBuffer) + { + pBuffer->Release(); + } + if (mem) + { + clReleaseMemObject(mem); + } + + HarnessD3D11_TestEnd(); +} + + +void TestDeviceBuffer( + cl_context context, + cl_command_queue command_queue, + ID3D11Device* pDevice, + ID3D11DeviceContext* pDC) +{ + for (UINT i = 0; i < bufferPropertyCount; ++i) + { + SubTestBuffer( + context, + command_queue, + pDevice, + pDC, + &bufferProperties[i]); + } +} + diff --git a/test_conformance/d3d11/harness.cpp b/test_conformance/d3d11/harness.cpp new file mode 100644 index 00000000..7d33b7f0 --- /dev/null +++ b/test_conformance/d3d11/harness.cpp @@ -0,0 +1,456 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#define INITGUID +#include "harness.h" + +#include +#include +#include + +/* + * OpenCL state + */ + +clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR = NULL; +clCreateFromD3D11BufferKHR_fn clCreateFromD3D11BufferKHR = NULL; +clCreateFromD3D11Texture2DKHR_fn clCreateFromD3D11Texture2DKHR = NULL; +clCreateFromD3D11Texture3DKHR_fn clCreateFromD3D11Texture3DKHR = NULL; +clEnqueueAcquireD3D11ObjectsKHR_fn clEnqueueAcquireD3D11ObjectsKHR = NULL; +clEnqueueReleaseD3D11ObjectsKHR_fn clEnqueueReleaseD3D11ObjectsKHR = NULL; + +#define INITPFN(x) \ + x = (x ## _fn)clGetExtensionFunctionAddressForPlatform(platform, #x); NonTestRequire(x, "Failed to get function pointer for %s", #x); + +void +HarnessD3D11_ExtensionCheck() +{ + cl_int result = CL_SUCCESS; + cl_platform_id platform = NULL; + + HarnessD3D11_TestBegin("Extension query"); + + bool platform_d3d11 = false; // Does platform support the extension? + { + std::vector< char > buffer; + size_t size = 0; + result = clGetPlatformIDs( 1, &platform, NULL ); + NonTestRequire( result == CL_SUCCESS, "Failed to get any platforms." ); + result = clGetPlatformInfo( platform, CL_PLATFORM_EXTENSIONS, 0, NULL, & size ); + NonTestRequire( result == CL_SUCCESS, "Failed to get size of extension string." ); + buffer.resize( size ); + result = clGetPlatformInfo( platform, CL_PLATFORM_EXTENSIONS, buffer.size(), & buffer.front(), & size ); + NonTestRequire( result == CL_SUCCESS, "Failed to get extension string." ); + std::string extensions = std::string( " " ) + & buffer.front() + " "; + platform_d3d11 = ( extensions.find( " cl_khr_d3d11_sharing " ) != std::string::npos ); + } + + // Platform is required to report the extension only if all devices support it, + // so let us iterate through all the devices and count devices supporting the extension. + + // Get list of all devices. + std::vector< cl_device_id > devices; + cl_uint num_devices = 0; + result = clGetDeviceIDs( platform, CL_DEVICE_TYPE_ALL, 0, NULL, & num_devices ); + NonTestRequire( result == CL_SUCCESS, "Failed to get number of devices." ); + devices.resize( num_devices ); + result = clGetDeviceIDs( platform, CL_DEVICE_TYPE_ALL, devices.size(), & devices.front(), & num_devices ); + NonTestRequire( result == CL_SUCCESS, "Failed to get list of device ids." ); + NonTestRequire( num_devices == devices.size(), "Failed to get list of device ids." ); + + // Iterate through the devices and count devices supporting the extension. + cl_uint num_devices_d3d11 = 0; // Number of devices supporting cl_khr_d3d11_sharing. + for ( cl_uint i = 0; i < devices.size(); ++ i ) + { + std::vector< char > buffer; + size_t size = 0; + result = clGetDeviceInfo( devices[ i ], CL_DEVICE_EXTENSIONS, 0, NULL, & size ); + NonTestRequire( result == CL_SUCCESS, "Failed to get size of extension string." ); + buffer.resize( size ); + result = clGetDeviceInfo( devices[ i ], CL_DEVICE_EXTENSIONS, buffer.size(), & buffer.front(), & size ); + NonTestRequire( result == CL_SUCCESS, "Failed to get extension string." ); + std::string extensions = std::string( " " ) + & buffer.front() + " "; + if ( extensions.find( " cl_khr_d3d11_sharing " ) != std::string::npos ) + { + ++ num_devices_d3d11; + } + } + + OSVERSIONINFO osvi; + osvi.dwOSVersionInfoSize = sizeof(osvi); + GetVersionEx(&osvi); + if (osvi.dwMajorVersion <= 5) + { + // Neither platform nor devices should declare support. + TestRequire( ! platform_d3d11, "Platform should not declare extension on Windows < 6" ); + TestRequire( num_devices_d3d11 == 0, "Devices should not declare extension on Windows < 6" ); + } + else + { + if ( num_devices_d3d11 == num_devices ) + { + // All the devices declare support, so platform must declare support as well. + TestRequire( platform_d3d11, "Extension should be exported on Windows >= 6" ); + } + else + { + // Not all the devices support th eextension => platform should not declare it. + TestRequire( ! platform_d3d11, "Extension should not be exported on Windows >= 6" ); + } + } + +Cleanup: + HarnessD3D11_TestEnd(); + + // early-out of the extension is not present + if ( num_devices_d3d11 == 0 ) + { + HarnessD3D11_TestStats(); + } +} + +void +HarnessD3D11_Initialize(cl_platform_id platform) +{ + HarnessD3D11_ExtensionCheck(); + + // extract function pointers for exported functions + INITPFN(clGetDeviceIDsFromD3D11KHR); + INITPFN(clCreateFromD3D11BufferKHR); + INITPFN(clCreateFromD3D11Texture2DKHR); + INITPFN(clCreateFromD3D11Texture3DKHR); + INITPFN(clEnqueueAcquireD3D11ObjectsKHR); + INITPFN(clEnqueueReleaseD3D11ObjectsKHR); +} + +/* + * Window management + */ + +static IDXGISwapChain* HarnessD3D11_pSwapChain = NULL; +static ID3D11Device* HarnessD3D11_pDevice = NULL; +static ID3D11DeviceContext* HarnessD3D11_pDC = NULL; +static HWND HarnessD3D11_hWnd = NULL; + +static LRESULT WINAPI HarnessD3D11_Proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_KEYDOWN: + return 0; + break; + case WM_DESTROY: + HarnessD3D11_hWnd = NULL; + PostQuitMessage(0); + return 0; + case WM_PAINT: + ValidateRect(hWnd, NULL); + return 0; + } + return DefWindowProc(hWnd, msg, wParam, lParam); +} + +static void HarnessD3D11_InteractiveLoop() +{ + MSG msg; + while(PeekMessage(&msg,HarnessD3D11_hWnd,0,0,PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +cl_int HarnessD3D11_CreateDevice( + IDXGIAdapter* pAdapter, + ID3D11Device **ppDevice, + ID3D11DeviceContext** ppDC) +{ + HRESULT hr = S_OK; + unsigned int cuStatus = 1; + + *ppDevice = NULL; + + // create window + static WNDCLASSEX wc = + { + sizeof(WNDCLASSEX), + CS_CLASSDC, + HarnessD3D11_Proc, + 0L, + 0L, + GetModuleHandle(NULL), + NULL, + NULL, + NULL, + NULL, + _T( "cl_khr_d3d11_sharing_conformance" ), + NULL + }; + RegisterClassEx(&wc); + HarnessD3D11_hWnd = CreateWindow( + _T( "cl_khr_d3d11_sharing_conformance" ), + _T( "cl_khr_d3d11_sharing_conformance" ), + WS_OVERLAPPEDWINDOW, + 0, 0, 256, 256, + NULL, + NULL, + wc.hInstance, + NULL); + NonTestRequire(0 != HarnessD3D11_hWnd, "Failed to create window"); + + ShowWindow(HarnessD3D11_hWnd,SW_SHOWDEFAULT); + UpdateWindow(HarnessD3D11_hWnd); + + RECT rc; + GetClientRect(HarnessD3D11_hWnd, &rc); + UINT width = rc.right - rc.left; + UINT height = rc.bottom - rc.top; + + // Create device and swapchain + DXGI_SWAP_CHAIN_DESC sd; + ZeroMemory( &sd, sizeof(sd) ); + sd.BufferCount = 1; + sd.BufferDesc.Width = width; + sd.BufferDesc.Height = height; + sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + sd.BufferDesc.RefreshRate.Numerator = 60; + sd.BufferDesc.RefreshRate.Denominator = 1; + sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sd.OutputWindow = HarnessD3D11_hWnd; + sd.SampleDesc.Count = 1; + sd.SampleDesc.Quality = 0; + sd.Windowed = TRUE; + D3D_FEATURE_LEVEL requestedFeatureLevels[] = {D3D_FEATURE_LEVEL_10_0}; + D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0; + hr = D3D11CreateDeviceAndSwapChain( + NULL, // pAdapter, + D3D_DRIVER_TYPE_HARDWARE, + NULL, + 0, + requestedFeatureLevels, + 1, + D3D11_SDK_VERSION, + &sd, + &HarnessD3D11_pSwapChain, + &HarnessD3D11_pDevice, + &featureLevel, + &HarnessD3D11_pDC); + if (FAILED(hr) ) { + return CL_DEVICE_NOT_FOUND; + } + + *ppDevice = HarnessD3D11_pDevice; + *ppDC = HarnessD3D11_pDC; + return CL_SUCCESS; +} + +void HarnessD3D11_DestroyDevice() +{ + HarnessD3D11_pSwapChain->Release(); + HarnessD3D11_pDevice->Release(); + HarnessD3D11_pDC->Release(); + + if (HarnessD3D11_hWnd) DestroyWindow(HarnessD3D11_hWnd); + HarnessD3D11_hWnd = 0; +} + +/* + * + * texture formats + * + */ + +#define ADD_TEXTURE_FORMAT(x,y,z,a,b,g) { x, y, z, a*b/8, g, #x, #y, #z, } +TextureFormat formats[] = +{ + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32B32A32_FLOAT , CL_RGBA , CL_FLOAT , 32, 4, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32B32A32_UINT , CL_RGBA , CL_UNSIGNED_INT32 , 32, 4, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32B32A32_SINT , CL_RGBA , CL_SIGNED_INT32 , 32, 4, TextureFormat::GENERIC_SINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_FLOAT , CL_RGBA , CL_HALF_FLOAT , 16, 4, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_UNORM , CL_RGBA , CL_UNORM_INT16 , 16, 4, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_UINT , CL_RGBA , CL_UNSIGNED_INT16 , 16, 4, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_SNORM , CL_RGBA , CL_SNORM_INT16 , 16, 4, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_SINT , CL_RGBA , CL_SIGNED_INT16 , 16, 4, TextureFormat::GENERIC_SINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_UNORM , CL_RGBA , CL_UNORM_INT8 , 8, 4, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_UINT , CL_RGBA , CL_UNSIGNED_INT8 , 8, 4, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_SNORM , CL_RGBA , CL_SNORM_INT8 , 8, 4, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_SINT , CL_RGBA , CL_SIGNED_INT8 , 8, 4, TextureFormat::GENERIC_SINT ), + + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32_FLOAT , CL_RG , CL_FLOAT , 32, 2, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32_UINT , CL_RG , CL_UNSIGNED_INT32 , 32, 2, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32_SINT , CL_RG , CL_SIGNED_INT32 , 32, 2, TextureFormat::GENERIC_SINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_FLOAT , CL_RG , CL_HALF_FLOAT , 16, 2, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_UNORM , CL_RG , CL_UNORM_INT16 , 16, 2, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_UINT , CL_RG , CL_UNSIGNED_INT16 , 16, 2, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_SNORM , CL_RG , CL_SNORM_INT16 , 16, 2, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_SINT , CL_RG , CL_SIGNED_INT16 , 16, 2, TextureFormat::GENERIC_SINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_UNORM , CL_RG , CL_UNORM_INT8 , 8, 2, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_UINT , CL_RG , CL_UNSIGNED_INT8 , 8, 2, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_SNORM , CL_RG , CL_SNORM_INT8 , 8, 2, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_SINT , CL_RG , CL_SIGNED_INT8 , 8, 2, TextureFormat::GENERIC_SINT ), + + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32_FLOAT , CL_R , CL_FLOAT , 32, 1, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32_UINT , CL_R , CL_UNSIGNED_INT32 , 32, 1, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32_SINT , CL_R , CL_SIGNED_INT32 , 32, 1, TextureFormat::GENERIC_SINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_FLOAT , CL_R , CL_HALF_FLOAT , 16, 1, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_UNORM , CL_R , CL_UNORM_INT16 , 16, 1, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_UINT , CL_R , CL_UNSIGNED_INT16 , 16, 1, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_SNORM , CL_R , CL_SNORM_INT16 , 16, 1, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_SINT , CL_R , CL_SIGNED_INT16 , 16, 1, TextureFormat::GENERIC_SINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_UNORM , CL_R , CL_UNORM_INT8 , 8, 1, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_UINT , CL_R , CL_UNSIGNED_INT8 , 8, 1, TextureFormat::GENERIC_UINT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_SNORM , CL_R , CL_SNORM_INT8 , 8, 1, TextureFormat::GENERIC_FLOAT ), + ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_SINT , CL_R , CL_SIGNED_INT8 , 8, 1, TextureFormat::GENERIC_SINT ), +}; +UINT formatCount = sizeof(formats)/sizeof(formats[0]); + +/* + * + * Logging and error reporting + * + */ + +static struct +{ + cl_int testCount; + cl_int passCount; + + cl_int nonTestFailures; + cl_int inTest; + cl_int currentTestPass; + + char currentTestName[1024]; +} HarnessD3D11_testStats = {0}; + +void HarnessD3D11_TestBegin(const char* fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsprintf(HarnessD3D11_testStats.currentTestName, fmt, ap); + va_end(ap); + + printf("[%s] ... ", HarnessD3D11_testStats.currentTestName); + + HarnessD3D11_testStats.inTest = 1; + HarnessD3D11_testStats.currentTestPass = 1; +} + +void HarnessD3D11_TestFail() +{ + if (HarnessD3D11_testStats.inTest) + { + HarnessD3D11_testStats.currentTestPass = 0; + } + else + { + ++HarnessD3D11_testStats.nonTestFailures; + } +} + +void HarnessD3D11_TestEnd() +{ + HarnessD3D11_testStats.inTest = 0; + + HarnessD3D11_testStats.testCount += 1; + HarnessD3D11_testStats.passCount += HarnessD3D11_testStats.currentTestPass; + + TestPrint("%s\n", + HarnessD3D11_testStats.currentTestPass ? "PASSED" : "FAILED"); +} + +void HarnessD3D11_TestStats() +{ + TestPrint("PASSED %d of %d tests.\n", HarnessD3D11_testStats.passCount, HarnessD3D11_testStats.testCount); + if (HarnessD3D11_testStats.testCount > HarnessD3D11_testStats.passCount) + { + TestPrint("***FAILED***\n"); + exit(1); + } + else + { + TestPrint("&&&& cl_khr_d3d11_sharing test PASSED\n"); + } + exit(0); +} + +/* + * + * Helper function + * + */ + +cl_int HarnessD3D11_CreateKernelFromSource( + cl_kernel *outKernel, + cl_device_id device, + cl_context context, + const char *source, + const char *entrypoint) +{ + cl_int status; + cl_kernel kernel = NULL; + + // compile program + cl_program program = NULL; + { + const char *sourceTexts[] = {source}; + size_t sourceLengths[] = {strlen(source) }; + + status = create_single_kernel_helper_create_program(context, &program, 1, &sourceTexts[0]); + TestRequire( + CL_SUCCESS == status, + "clCreateProgramWithSource failed"); + } + status = clBuildProgram( + program, + 0, + NULL, + NULL, + NULL, + NULL); + if (CL_SUCCESS != status) + { + char log[2048] = {0}; + status = clGetProgramBuildInfo( + program, + device, + CL_PROGRAM_BUILD_LOG, + sizeof(log), + log, + NULL); + TestPrint("error: %s\n", log); + TestRequire( + CL_SUCCESS == status, + "Compilation error log:\n%s\n", log); + } + + kernel = clCreateKernel( + program, + entrypoint, + &status); + TestRequire( + CL_SUCCESS == status, + "clCreateKernel failed"); + + clReleaseProgram(program); + *outKernel = kernel; + +Cleanup: + + return CL_SUCCESS; +} + + + diff --git a/test_conformance/d3d11/harness.h b/test_conformance/d3d11/harness.h new file mode 100644 index 00000000..c1b66100 --- /dev/null +++ b/test_conformance/d3d11/harness.h @@ -0,0 +1,221 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _HARNESS_H_ +#define _HARNESS_H_ + +#define _CRT_SECURE_NO_WARNINGS + +#if defined (__MINGW32__) +#include +typedef unsigned char UINT8; +#define __out +#define __in +#define __inout +#define __out_bcount(size) +#define __out_bcount_opt(size) +#define __in_opt +#define __in_ecount(size) +#define __in_ecount_opt(size) +#define __out_opt +#define __out_ecount(size) +#define __out_ecount_opt(size) +#define __in_bcount_opt(size) +#define __inout_opt +#endif + +#include +#include +#include +#include +#include "errorHelpers.h" +#include "../test_common/harness/kernelHelpers.h" + +// #define log_info(...) printf(__VA_ARGS__) +// #define log_error(...) printf(__VA_ARGS__) + +#define NonTestRequire(x, ...) \ +do \ +{ \ + if (!(x) ) \ + { \ + log_info("\n[assertion failed: %s at %s:%d]\n", #x, __FILE__, __LINE__); \ + log_info("CATASTROPHIC NON-TEST ERROR: "); \ + log_error(__VA_ARGS__); \ + log_info("\n"); \ + log_info("***FAILED***\n"); \ + exit(1); \ + } \ +} while (0) + +#define TestRequire(x, ...) \ + do \ + { \ + if (!(x) ) \ + { \ + log_info("\n[assertion failed: %s at %s:%d]\n", #x, __FILE__, __LINE__); \ + log_info("ERROR: "); \ + log_error(__VA_ARGS__); \ + log_info("\n"); \ + HarnessD3D11_TestFail(); \ + goto Cleanup; \ + } \ + } while (0) + +#define TestPrint(...) \ + do \ + { \ + log_error(__VA_ARGS__); \ + } while (0) + +struct TextureFormat +{ + DXGI_FORMAT format; + cl_channel_order channel_order; + cl_channel_type channel_type; + UINT bytesPerPixel; + enum + { + GENERIC_FLOAT = 0, + GENERIC_UINT = 1, + GENERIC_SINT = 2, + } generic; + + const char *name_format; + const char *name_channel_order; + const char *name_channel_type; +}; +extern TextureFormat formats[]; +extern UINT formatCount; + + +#define MAX_REGISTERED_SUBRESOURCES 4 // limit to just make life easier + +struct BufferProperties +{ + UINT ByteWidth; + UINT BindFlags; + D3D11_USAGE Usage; + UINT CPUAccess; + const char* name_BindFlags; + const char* name_Usage; + const char* name_CPUAccess; +}; + +struct Texture2DSize +{ + UINT Width; + UINT Height; + UINT MipLevels; + UINT ArraySize; + UINT SubResourceCount; + struct + { + UINT MipLevel; + UINT ArraySlice; + } subResources[MAX_REGISTERED_SUBRESOURCES]; + UINT MiscFlags; +}; +struct Texture3DSize +{ + UINT Width; + UINT Height; + UINT Depth; + UINT MipLevels; + UINT SubResourceCount; + struct + { + UINT MipLevel; + } subResources[MAX_REGISTERED_SUBRESOURCES]; + UINT MiscFlags; +}; + +void HarnessD3D11_Initialize(cl_platform_id platform); +cl_int HarnessD3D11_CreateDevice( + IDXGIAdapter* pAdapter, + ID3D11Device **ppDevice, + ID3D11DeviceContext** ppDC); +void HarnessD3D11_DestroyDevice(); + +void HarnessD3D11_TestBegin(const char* fmt, ...); +void HarnessD3D11_TestFail(); +void HarnessD3D11_TestEnd(); +void HarnessD3D11_TestStats(); + +void TestAdapterEnumeration( + cl_platform_id platform, + IDXGIAdapter* pAdapter, + ID3D11Device* pDevice, + cl_uint* num_devices); + +void TestAdapterDevices( + cl_platform_id platform, + IDXGIAdapter* pAdapter, + ID3D11Device* pDevice, + ID3D11DeviceContext* pDC, + cl_uint num_devices); + +void TestDevice( + cl_device_id device, + ID3D11Device* pDevice, + ID3D11DeviceContext* pDC); + +bool TestDeviceContextCreate( + cl_device_id device, + ID3D11Device* pDevice, + cl_context* out_context, + cl_command_queue* out_command_queue); + +void TestDeviceBuffer( + cl_context context, + cl_command_queue command_queue, + ID3D11Device* pDevice, + ID3D11DeviceContext* pDC); + +void TestDeviceTexture2D( + cl_device_id device, + cl_context context, + cl_command_queue command_queue, + ID3D11Device* pDevice, + ID3D11DeviceContext* pDC); + +void TestDeviceTexture3D( + cl_device_id device, + cl_context context, + cl_command_queue command_queue, + ID3D11Device* pDevice, + ID3D11DeviceContext* pDC); + +void TestDeviceMisc( + cl_device_id device, + cl_context context, + cl_command_queue command_queue, + ID3D11Device* pDevice); + +cl_int HarnessD3D11_CreateKernelFromSource( + cl_kernel *outKernel, + cl_device_id device, + cl_context context, + const char *source, + const char *entrypoint); + +extern clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR; +extern clCreateFromD3D11BufferKHR_fn clCreateFromD3D11BufferKHR; +extern clCreateFromD3D11Texture2DKHR_fn clCreateFromD3D11Texture2DKHR; +extern clCreateFromD3D11Texture3DKHR_fn clCreateFromD3D11Texture3DKHR; +extern clEnqueueAcquireD3D11ObjectsKHR_fn clEnqueueAcquireD3D11ObjectsKHR; +extern clEnqueueReleaseD3D11ObjectsKHR_fn clEnqueueReleaseD3D11ObjectsKHR; + +#endif diff --git a/test_conformance/d3d11/main.cpp b/test_conformance/d3d11/main.cpp new file mode 100644 index 00000000..f477d7bb --- /dev/null +++ b/test_conformance/d3d11/main.cpp @@ -0,0 +1,464 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#if defined( _WIN32 ) + +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include "harness.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/parseParameters.h" + +int main(int argc, const char* argv[]) +{ + cl_int result; + cl_platform_id platform = NULL; + cl_uint num_devices_tested = 0; + + argc = parseCustomParam(argc, argv); + + // get the platforms to test + result = clGetPlatformIDs(1, &platform, NULL); NonTestRequire(result == CL_SUCCESS, "Failed to get any platforms."); + + HarnessD3D11_Initialize(platform); + + // for each adapter... + IDXGIFactory* pFactory = NULL; + HRESULT hr = CreateDXGIFactory(IID_IDXGIFactory, (void**)(&pFactory) ); + NonTestRequire(SUCCEEDED(hr), "Failed to create DXGI factory."); + for (UINT adapter = 0;; ++adapter) + { + IDXGIAdapter* pAdapter = NULL; + ID3D11Device* pDevice = NULL; + ID3D11DeviceContext* pDC = NULL; + HRESULT hr = pFactory->EnumAdapters(adapter, &pAdapter); + if (FAILED(hr)) + { + break; + } + + // print data about the adapter + DXGI_ADAPTER_DESC desc; + hr = pAdapter->GetDesc(&desc); + NonTestRequire(SUCCEEDED(hr), "IDXGIAdapter::GetDesc failed."); + + TestPrint("=====================================\n"); + TestPrint("Testing DXGI Adapter and D3D11 Device\n"); + TestPrint("Description=%ls, VendorID=%x, DeviceID=%x\n", desc.Description, desc.VendorId, desc.DeviceId); + TestPrint("=====================================\n"); + + // run the test on the adapter + HarnessD3D11_CreateDevice(pAdapter, &pDevice, &pDC); + + cl_uint num_devices = 0; + + // test adapter and device enumeration + TestAdapterEnumeration(platform, pAdapter, pDevice, &num_devices); + + // if there were any devices found in enumeration, run the tests on them + if (num_devices) + { + TestAdapterDevices(platform, pAdapter, pDevice, pDC, num_devices); + } + num_devices_tested += num_devices; + + // destroy the D3D11 device + if (pDevice) + { + HarnessD3D11_DestroyDevice(); + } + + pAdapter->Release(); + } + pFactory->Release(); + + // allow the test to be waived in automation + // NonTestRequire(num_devices_tested, "No D3D11 compatible cl_device_ids were found."); + + HarnessD3D11_TestStats(); +} + +void TestAdapterEnumeration( + cl_platform_id platform, + IDXGIAdapter* pAdapter, + ID3D11Device* pDevice, + cl_uint* num_devices) +{ + cl_uint num_adapter_devices = 0; + cl_device_id* adapter_devices = NULL; + + cl_uint num_device_devices = 0; + cl_device_id* device_devices = NULL; + + cl_int result; + + HarnessD3D11_TestBegin("cl_device_id Enumeration"); + + // get the cl_device_ids for the adapter + { + result = clGetDeviceIDsFromD3D11KHR( + platform, + CL_D3D11_DXGI_ADAPTER_KHR, + pAdapter, + CL_ALL_DEVICES_FOR_D3D11_KHR, + 0, + NULL, + &num_adapter_devices); + TestRequire( + (result == CL_SUCCESS || result == CL_DEVICE_NOT_FOUND), + "clGetDeviceIDsFromD3D11KHR failed."); + + if (result == CL_DEVICE_NOT_FOUND) + { + TestPrint("No devices found for adapter.\n"); + } + else + { + // if there were devices, query them + adapter_devices = new cl_device_id[num_adapter_devices]; + result = clGetDeviceIDsFromD3D11KHR( + platform, + CL_D3D11_DXGI_ADAPTER_KHR, + pAdapter, + CL_ALL_DEVICES_FOR_D3D11_KHR, + num_adapter_devices, + adapter_devices, + NULL); + TestRequire( + (result == CL_SUCCESS), + "clGetDeviceIDsFromD3D11KHR failed."); + } + } + + // get the cl_device_ids for the device (if it was successfully created) + if (pDevice) + { + result = clGetDeviceIDsFromD3D11KHR( + platform, + CL_D3D11_DEVICE_KHR, + pDevice, + CL_ALL_DEVICES_FOR_D3D11_KHR, + 0, + NULL, + &num_device_devices); + TestRequire( + (result == CL_SUCCESS || result == CL_DEVICE_NOT_FOUND), + "clGetDeviceIDsFromD3D11KHR failed."); + + if (result == CL_DEVICE_NOT_FOUND) + { + TestPrint("No devices found for D3D device.\n"); + } + else + { + // if there were devices, query them + device_devices = new cl_device_id[num_device_devices]; + result = clGetDeviceIDsFromD3D11KHR( + platform, + CL_D3D11_DEVICE_KHR, + pDevice, + CL_ALL_DEVICES_FOR_D3D11_KHR, + num_device_devices, + device_devices, + NULL); + TestRequire( + (result == CL_SUCCESS), + "clGetDeviceIDsFromD3D11KHR failed."); + } + + } + +Cleanup: + + if (adapter_devices) + { + delete[] adapter_devices; + } + if (device_devices) + { + delete[] device_devices; + } + + *num_devices = num_device_devices; + + HarnessD3D11_TestEnd(); +} + +void TestAdapterDevices( + cl_platform_id platform, + IDXGIAdapter* pAdapter, + ID3D11Device* pDevice, + ID3D11DeviceContext* pDC, + cl_uint num_devices_expected) +{ + cl_int result; + cl_uint num_devices = 0; + cl_device_id* devices = NULL; + + devices = new cl_device_id[num_devices_expected]; + NonTestRequire( + devices, + "Memory allocation failure."); + + result = clGetDeviceIDsFromD3D11KHR( + platform, + CL_D3D11_DEVICE_KHR, + pDevice, + CL_ALL_DEVICES_FOR_D3D11_KHR, + num_devices_expected, + devices, + &num_devices); + NonTestRequire( + (result == CL_SUCCESS), + "clGetDeviceIDsFromD3D11KHR failed."); + NonTestRequire( + (num_devices == num_devices_expected), + "clGetDeviceIDsFromD3D11KHR returned an unexpected number of devices."); + + for (cl_uint i = 0; i < num_devices; ++i) + { + TestDevice(devices[i], pDevice, pDC); + } +} + +void TestDevice( + cl_device_id device, + ID3D11Device* pDevice, + ID3D11DeviceContext* pDC) +{ + char device_name[1024]; + cl_int result = CL_SUCCESS; + cl_context context = NULL; + cl_command_queue command_queue = NULL; + ID3D11Device* clDevice = NULL; + cl_uint prefer_shared_resources; + + result = clGetDeviceInfo( + device, + CL_DEVICE_NAME, + sizeof(device_name), + device_name, + NULL); + NonTestRequire(CL_SUCCESS == result, "clGetDeviceInfo with CL_DEVICE_NAME failed"); + TestPrint("--------------------\n"); + TestPrint("Testing cl_device_id\n"); + TestPrint("Name=%s\n", device_name); + TestPrint("--------------------\n"); + + if (!TestDeviceContextCreate(device, pDevice, &context, &command_queue) ) + { + return; + } + + // make sure that we can query the shared resource preference + result = clGetContextInfo( + context, + CL_CONTEXT_D3D11_PREFER_SHARED_RESOURCES_KHR, + sizeof(prefer_shared_resources), + &prefer_shared_resources, + NULL); + NonTestRequire(CL_SUCCESS == result, "clGetContextInfo with CL_CONTEXT_D3D10_PREFER_SHARED_RESOURCES_KHR failed"); + + // run buffer tests + TestDeviceBuffer( + context, + command_queue, + pDevice, + pDC); + + // run 2D texture tests + TestDeviceTexture2D( + device, + context, + command_queue, + pDevice, + pDC); + + // run 3D texture tests + TestDeviceTexture3D( + device, + context, + command_queue, + pDevice, + pDC); + + // run misc tests + TestDeviceMisc( + device, + context, + command_queue, + pDevice); + + clReleaseContext(context); + clReleaseCommandQueue(command_queue); +} + +bool TestDeviceContextCreate( + cl_device_id device, + ID3D11Device* pDevice, + cl_context* out_context, + cl_command_queue* out_command_queue) +{ + cl_int result = CL_SUCCESS; + cl_context context = NULL; + cl_command_queue command_queue = NULL; + + ID3D11Device* clDevice = NULL; + + bool succeeded = false; + + HarnessD3D11_TestBegin("Context creation"); + + cl_context_properties properties[5]; + + // create the context + properties[0] = (cl_context_properties)CL_CONTEXT_D3D11_DEVICE_KHR; + properties[1] = (cl_context_properties)pDevice; + properties[2] = (cl_context_properties)CL_CONTEXT_INTEROP_USER_SYNC; + properties[3] = (cl_context_properties)CL_TRUE; + properties[4] = (cl_context_properties)0; + context = clCreateContext( + properties, + 1, + &device, + NULL, + NULL, + &result); + TestRequire( + (result == CL_SUCCESS), + "clCreateContext with CL_CONTEXT_D3D11_DEVICE_KHR failed"); + result = clReleaseContext(context); + TestRequire( + (result == CL_SUCCESS), + "clReleaseContext with CL_CONTEXT_D3D11_DEVICE_KHR failed"); + + // create the context + properties[0] = (cl_context_properties)CL_CONTEXT_D3D11_DEVICE_KHR; + properties[1] = (cl_context_properties)pDevice; + properties[2] = (cl_context_properties)CL_CONTEXT_INTEROP_USER_SYNC; + properties[3] = (cl_context_properties)CL_FALSE; + properties[4] = (cl_context_properties)0; + context = clCreateContext( + properties, + 1, + &device, + NULL, + NULL, + &result); + TestRequire( + (result == CL_SUCCESS), + "clCreateContext with CL_CONTEXT_D3D11_DEVICE_KHR failed"); + result = clReleaseContext(context); + TestRequire( + (result == CL_SUCCESS), + "clReleaseContext with CL_CONTEXT_D3D11_DEVICE_KHR failed"); + + // create the context + properties[0] = (cl_context_properties)CL_CONTEXT_D3D11_DEVICE_KHR; + properties[1] = (cl_context_properties)pDevice; + properties[2] = (cl_context_properties)0; + context = clCreateContext( + properties, + 1, + &device, + NULL, + NULL, + &result); + TestRequire( + (result == CL_SUCCESS), + "clCreateContext with CL_CONTEXT_D3D11_DEVICE_KHR failed"); + + // check CL_CONTEXT_D3D11_DEVICE_KHR + { + size_t param_value_size_ret; + result = clGetContextInfo(context, CL_CONTEXT_PROPERTIES, 0, NULL, ¶m_value_size_ret); + TestRequire( + (result == CL_SUCCESS), + "clGetContextInfo with CL_CONTEXT_PROPERTIES failed"); + + TestRequire( + ((param_value_size_ret % sizeof(cl_context_properties)) == 0), + "param_value_size_ret is not a multiple of sizeof(cl_context_properties)"); + + std::vector contextProperties(param_value_size_ret / sizeof(cl_context_properties)); + result = clGetContextInfo(context, CL_CONTEXT_PROPERTIES, param_value_size_ret, &contextProperties[0], NULL); + TestRequire( + (result == CL_SUCCESS), + "clGetContextInfo with CL_CONTEXT_PROPERTIES failed"); + + TestRequire(contextProperties.size() % 2 == 1, "Property list size is not odd."); + TestRequire(contextProperties[contextProperties.size() - 1] == 0, "last property is not zero"); + + std::vector::const_iterator iter; + for (iter = contextProperties.begin(); *iter != 0; iter+=2) + { + if (CL_CONTEXT_D3D11_DEVICE_KHR == *iter) + { + TestRequire((ID3D11Device*)*(iter+1) == pDevice, "CL_CONTEXT_D3D11_DEVICE_KHR returned invalid value"); + break; + } + } + + TestRequire((iter != contextProperties.end()), "CL_CONTEXT_PROPERTIES doesn't include CL_CONTEXT_D3D11_DEVICE_KHR"); + } + + + // create the command queue + TestPrint("Creating a command queue.\n"); + command_queue = clCreateCommandQueueWithProperties( + context, + device, + NULL, + &result); + TestRequire( + (result == CL_SUCCESS), + "clCreateContext with CL_CONTEXT_D3D11_DEVICE_KHR failed"); + + succeeded = true; + +Cleanup: + + if (succeeded) + { + *out_context = context; + *out_command_queue = command_queue; + } + else + { + if (context) + { + clReleaseContext(context); + } + if (command_queue) + { + clReleaseCommandQueue(command_queue); + } + } + HarnessD3D11_TestEnd(); + return succeeded; +} + +#else + +#include "errorHelpers.h" + +int main(int argc, char* argv[]) +{ + log_info( "Windows-specific test skipped.\n" ); + return 0; +} + +#endif diff --git a/test_conformance/d3d11/misc.cpp b/test_conformance/d3d11/misc.cpp new file mode 100644 index 00000000..1eba7e2d --- /dev/null +++ b/test_conformance/d3d11/misc.cpp @@ -0,0 +1,224 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#define _CRT_SECURE_NO_WARNINGS +#include "harness.h" + +void SubTestMiscMultipleCreates( + cl_context context, + cl_command_queue command_queue, + ID3D11Device* pDevice) +{ + cl_mem mem[5] = {NULL, NULL, NULL, NULL, NULL}; + ID3D11Buffer* pBuffer = NULL; + ID3D11Texture2D* pTexture = NULL; + HRESULT hr = S_OK; + + cl_int result = CL_SUCCESS; + + HarnessD3D11_TestBegin("Misc: Multiple Creates"); + + // create the D3D11 resources + { + D3D11_TEXTURE2D_DESC desc; + memset(&desc, 0, sizeof(desc) ); + desc.Width = 256; + desc.Height = 256; + desc.MipLevels = 4; + desc.ArraySize = 4; + desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + hr = pDevice->CreateTexture2D(&desc, NULL, &pTexture); + TestRequire(SUCCEEDED(hr), "Failed to create texture."); + } + + // create the D3D11 buffer + { + D3D11_BUFFER_DESC desc = {0}; + desc.ByteWidth = 1124; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.CPUAccessFlags = 0; + desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + desc.MiscFlags = 0; + hr = pDevice->CreateBuffer(&desc, NULL, &pBuffer); + TestRequire(SUCCEEDED(hr), "Creating vertex buffer failed!"); + } + + mem[0] = clCreateFromD3D11BufferKHR( + context, + 0, + pBuffer, + &result); + TestRequire(result == CL_SUCCESS, "clCreateFromD3D11BufferKHR"); + + mem[1] = clCreateFromD3D11BufferKHR( + context, + 0, + pBuffer, + &result); + TestRequire(result == CL_INVALID_D3D11_RESOURCE_KHR, "clCreateFromD3D11BufferKHR succeeded when it shouldn't"); + + mem[2] = clCreateFromD3D11Texture2DKHR( + context, + 0, + pTexture, + 1, + &result); + TestRequire(result == CL_SUCCESS, "clCreateFromD3D11Texture2DKHR failed"); + + mem[3] = clCreateFromD3D11Texture2DKHR( + context, + 0, + pTexture, + 1, + &result); + TestRequire(result == CL_INVALID_D3D11_RESOURCE_KHR, "clCreateFromD3D11Texture2DKHR succeeded when it shouldn't"); + + mem[4] = clCreateFromD3D11Texture2DKHR( + context, + 0, + pTexture, + 16, + &result); + TestRequire(result == CL_INVALID_VALUE, "clCreateFromD3D11Texture2DKHR succeeded when it shouldn't"); + + +Cleanup: + + for (UINT i = 0; i < 4; ++i) + { + if (mem[i]) + { + clReleaseMemObject(mem[i]); + } + } + if (pBuffer) + { + pBuffer->Release(); + } + if (pTexture) + { + pTexture->Release(); + } + + HarnessD3D11_TestEnd(); +} + +void SubTestMiscAcquireRelease( + cl_device_id device, + cl_context context, + ID3D11Device* pDevice) +{ + ID3D11Buffer* pBuffer = NULL; + ID3D11Texture2D* pTexture = NULL; + HRESULT hr = S_OK; + + cl_int result = CL_SUCCESS; + cl_mem mem[2] = {NULL, NULL}; + + HarnessD3D11_TestBegin("Misc: Acquire Release"); + + + // create the D3D11 resources + { + D3D11_TEXTURE2D_DESC desc; + memset(&desc, 0, sizeof(desc) ); + desc.Width = 256; + desc.Height = 256; + desc.MipLevels = 4; + desc.ArraySize = 4; + desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + hr = pDevice->CreateTexture2D(&desc, NULL, &pTexture); + TestRequire(SUCCEEDED(hr), "Failed to create texture."); + } + + // create the D3D11 buffer + { + D3D11_BUFFER_DESC desc = {0}; + desc.ByteWidth = 1124; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.CPUAccessFlags = 0; + desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + desc.MiscFlags = 0; + hr = pDevice->CreateBuffer(&desc, NULL, &pBuffer); + TestRequire(SUCCEEDED(hr), "Creating vertex buffer failed!"); + } + + // create cl_mem objects for the resources + mem[0] = clCreateFromD3D11BufferKHR( + context, + 0, + pBuffer, + &result); + TestRequire(result == CL_SUCCESS, "clCreateFromD3D11BufferKHR"); + mem[1] = clCreateFromD3D11Texture2DKHR( + context, + 0, + pTexture, + 1, + &result); + TestRequire(result == CL_SUCCESS, "clCreateFromD3D11Texture2DKHR failed"); + +Cleanup: + for (UINT i = 0; i < 2; ++i) + { + if (mem[i]) + { + clReleaseMemObject(mem[i]); + } + } + if (pBuffer) + { + pBuffer->Release(); + } + if (pTexture) + { + pTexture->Release(); + } + + HarnessD3D11_TestEnd(); +} + +void TestDeviceMisc( + cl_device_id device, + cl_context context, + cl_command_queue command_queue, + ID3D11Device* pDevice) +{ + SubTestMiscMultipleCreates( + context, + command_queue, + pDevice); + + SubTestMiscAcquireRelease( + device, + context, + pDevice); +} + + diff --git a/test_conformance/d3d11/texture2d.cpp b/test_conformance/d3d11/texture2d.cpp new file mode 100644 index 00000000..abfdbf06 --- /dev/null +++ b/test_conformance/d3d11/texture2d.cpp @@ -0,0 +1,749 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#define _CRT_SECURE_NO_WARNINGS +#include "harness.h" +#include + +Texture2DSize texture2DSizes[] = +{ + { + 4, // Width + 4, // Height + 1, // MipLevels + 1, // ArraySize + 1, // SubResourceCount + { // SubResources + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, + { + 15, // Width + 37, // Height + 2, // MipLevels + 1, // ArraySize + 2, // SubResourceCount + { // SubResources + {0, 0}, // MipLevel, ArraySlice + {1, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, + { + 65, // Width + 17, // Height + 1, // MipLevels + 1, // ArraySize + 1, // SubResourceCount + { // SubResources + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + }, + D3D11_RESOURCE_MISC_SHARED, // MiscFlags + }, + + { + 127, // Width + 125, // Height + 4, // MipLevels + 1, // ArraySize + 4, // SubResourceCount + { // SubResources + {3, 0}, // MipLevel, ArraySlice + {2, 0}, // MipLevel, ArraySlice + {1, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, + { + 128, // Width + 128, // Height + 4, // MipLevels + 6, // ArraySize + 4, // SubResourceCount + { // SubResources + {0, 1}, // MipLevel, ArraySlice + {1, 0}, // MipLevel, ArraySlice + {0, 2}, // MipLevel, ArraySlice + {3, 5}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, + { + 256, // Width + 256, // Height + 0, // MipLevels + 256, // ArraySize + 4, // SubResourceCount + { // SubResources + {0, 0}, // MipLevel, ArraySlice + {1, 255}, // MipLevel, ArraySlice + {2, 127}, // MipLevel, ArraySlice + {3, 128}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, + { + 258, // Width + 511, // Height + 1, // MipLevels + 1, // ArraySize + 1, // SubResourceCount + { // SubResources + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, + { + 767, // Width + 1025, // Height + 4, // MipLevels + 1, // ArraySize + 1, // SubResourceCount + { // SubResources + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, + { + 2048, // Width + 2048, // Height + 1, // MipLevels + 1, // ArraySize + 1, // SubResourceCount + { // SubResources + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + {0, 0}, // MipLevel, ArraySlice + }, + 0, // MiscFlags + }, +}; +UINT texture2DSizeCount = sizeof(texture2DSizes)/sizeof(texture2DSizes[0]); + +const char * +texture2DPatterns[2][2] = +{ + {"aAbBcCdDeEfFgGhHiIjJ", "AaBbCcDdEeFfGgHhIiJj"}, + {"zZyYxXwWvVuUtTsSrRqQ", "ZzYyXxWwVvUuTtSsRrQq"}, +}; + +void SubTestTexture2D( + cl_context context, + cl_command_queue command_queue, + cl_kernel kernel, + ID3D11Device* pDevice, + ID3D11DeviceContext* pDC, + const TextureFormat* format, + const Texture2DSize* size) +{ + ID3D11Texture2D* pTexture = NULL; + HRESULT hr = S_OK; + cl_image_format clFormat; + cl_int result = CL_SUCCESS; + + HarnessD3D11_TestBegin("2D Texture: Format=%s, Width=%d, Height=%d, MipLevels=%d, ArraySize=%d", + format->name_format, + size->Width, + size->Height, + size->MipLevels, + size->ArraySize); + + struct + { + cl_mem mem; + UINT subResource; + UINT width; + UINT height; + } + subResourceInfo[4]; + + cl_event events[4] = {NULL, NULL, NULL, NULL}; + + // create the D3D11 resources + { + D3D11_TEXTURE2D_DESC desc; + memset(&desc, 0, sizeof(desc) ); + desc.Width = size->Width; + desc.Height = size->Height; + desc.MipLevels = size->MipLevels; + desc.ArraySize = size->ArraySize; + desc.Format = format->format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + hr = pDevice->CreateTexture2D(&desc, NULL, &pTexture); + TestRequire(SUCCEEDED(hr), "ID3D11Device::CreateTexture2D failed (non-OpenCL D3D error, but test is invalid)."); + } + + // initialize some useful variables + for (UINT i = 0; i < size->SubResourceCount; ++i) + { + // compute the expected values for the subresource + subResourceInfo[i].subResource = D3D11CalcSubresource( + size->subResources[i].MipLevel, + size->subResources[i].ArraySlice, + size->MipLevels); + subResourceInfo[i].width = size->Width; + subResourceInfo[i].height = size->Height; + for (UINT j = 0; j < size->subResources[i].MipLevel; ++j) { + subResourceInfo[i].width /= 2; + subResourceInfo[i].height /= 2; + } + subResourceInfo[i].mem = NULL; + } + + // copy a pattern into the corners of the image, coordinates + // (0,0), (w,0-1), (0,h-1), (w-1,h-1) + for (UINT i = 0; i < size->SubResourceCount; ++i) + for (UINT x = 0; x < 2; ++x) + for (UINT y = 0; y < 2; ++y) + { + // create the staging buffer + ID3D11Texture2D* pStagingBuffer = NULL; + { + D3D11_TEXTURE2D_DESC desc = {0}; + desc.Width = 1; + desc.Height = 1; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = format->format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + hr = pDevice->CreateTexture2D(&desc, NULL, &pStagingBuffer); + TestRequire(SUCCEEDED(hr), "ID3D11Device::CreateTexture2D failed (non-OpenCL D3D error, but test is invalid)."); + } + + // write the data to the staging buffer + { + D3D11_MAPPED_SUBRESOURCE mappedTexture; + hr = pDC->Map( + pStagingBuffer, + 0, + D3D11_MAP_READ_WRITE, + 0, + &mappedTexture); + memcpy(mappedTexture.pData, texture2DPatterns[x][y], format->bytesPerPixel); + pDC->Unmap(pStagingBuffer, 0); + } + + // copy the data to to the texture + { + D3D11_BOX box = {0}; + box.front = 0; box.back = 1; + box.top = 0; box.bottom = 1; + box.left = 0; box.right = 1; + pDC->CopySubresourceRegion( + pTexture, + subResourceInfo[i].subResource, + x ? subResourceInfo[i].width - 1 : 0, + y ? subResourceInfo[i].height - 1 : 0, + 0, + pStagingBuffer, + 0, + &box); + } + + pStagingBuffer->Release(); + } + + // create the cl_mem objects for the resources and verify its sanity + for (UINT i = 0; i < size->SubResourceCount; ++i) + { + // create a cl_mem for the resource + subResourceInfo[i].mem = clCreateFromD3D11Texture2DKHR( + context, + 0, + pTexture, + subResourceInfo[i].subResource, + &result); + if (CL_IMAGE_FORMAT_NOT_SUPPORTED == result) + { + goto Cleanup; + } + TestRequire(result == CL_SUCCESS, "clCreateFromD3D11Texture2DKHR failed"); + + // query resource pointer and verify + ID3D11Resource* clResource = NULL; + result = clGetMemObjectInfo( + subResourceInfo[i].mem, + CL_MEM_D3D11_RESOURCE_KHR, + sizeof(clResource), + &clResource, + NULL); + TestRequire(result == CL_SUCCESS, "clGetMemObjectInfo for CL_MEM_D3D11_RESOURCE_KHR failed."); + TestRequire(clResource == pTexture, "clGetMemObjectInfo for CL_MEM_D3D11_RESOURCE_KHR returned incorrect value."); + + // query subresource and verify + UINT clSubResource; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_D3D11_SUBRESOURCE_KHR, + sizeof(clSubResource), + &clSubResource, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_D3D11_SUBRESOURCE_KHR failed"); + TestRequire(clSubResource == subResourceInfo[i].subResource, "clGetImageInfo for CL_IMAGE_D3D11_SUBRESOURCE_KHR returned incorrect value."); + + // query format and verify + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_FORMAT, + sizeof(clFormat), + &clFormat, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_FORMAT failed"); + TestRequire(clFormat.image_channel_order == format->channel_order, "clGetImageInfo for CL_IMAGE_FORMAT returned incorrect channel order."); + TestRequire(clFormat.image_channel_data_type == format->channel_type, "clGetImageInfo for CL_IMAGE_FORMAT returned incorrect channel data type."); + + // query width + size_t width; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_WIDTH, + sizeof(width), + &width, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_WIDTH failed"); + TestRequire(width == subResourceInfo[i].width, "clGetImageInfo for CL_IMAGE_HEIGHT returned incorrect value."); + + // query height + size_t height; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_HEIGHT, + sizeof(height), + &height, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_HEIGHT failed"); + TestRequire(height == subResourceInfo[i].height, "clGetImageInfo for CL_IMAGE_HEIGHT returned incorrect value."); + + } + + // acquire the resources for OpenCL + for (UINT i = 0; i < 2; ++i) + { + cl_uint memCount = 0; + cl_mem memToAcquire[MAX_REGISTERED_SUBRESOURCES]; + + // cut the registered sub-resources into two sets and send the acquire calls for them separately + if (i == 0) + { + for(UINT j = 0; j < size->SubResourceCount/2; ++j) + { + memToAcquire[memCount++] = subResourceInfo[j].mem; + } + } + else + { + for(UINT j = size->SubResourceCount/2; j < size->SubResourceCount; ++j) + { + memToAcquire[memCount++] = subResourceInfo[j].mem; + } + } + if (!memCount) continue; + + // do the acquire + result = clEnqueueAcquireD3D11ObjectsKHR( + command_queue, + memCount, + memToAcquire, + 0, + NULL, + &events[0+i]); + TestRequire(result == CL_SUCCESS, "clEnqueueAcquireD3D11ObjectsKHR failed."); + TestRequire(events[0+i], "clEnqueueAcquireD3D11ObjectsKHR did not return an event."); + + // make sure the event type is correct + cl_uint eventType = 0; + result = clGetEventInfo( + events[0+i], + CL_EVENT_COMMAND_TYPE, + sizeof(eventType), + &eventType, + NULL); + TestRequire(result == CL_SUCCESS, "clGetEventInfo for event created by clEnqueueAcquireD3D11ObjectsKHR failed."); + TestRequire(eventType == CL_COMMAND_ACQUIRE_D3D11_OBJECTS_KHR, "clGetEventInfo for CL_EVENT_COMMAND_TYPE was not CL_COMMAND_ACQUIRE_D3D11_OBJECTS_KHR."); + } + + // download the data using OpenCL & compare with the expected results + for (UINT i = 0; i < size->SubResourceCount; ++i) + { + size_t origin[3] = {0,0,0}; + size_t region[3] = {subResourceInfo[i].width, subResourceInfo[i].height, 1}; + cl_mem tempImage; + cl_image_desc image_desc = { 0 }; + image_desc.image_depth = 1; + image_desc.image_height = subResourceInfo[i].height; + image_desc.image_width = subResourceInfo[i].width; + image_desc.image_type = CL_MEM_OBJECT_IMAGE2D; + + tempImage = clCreateImage(context, 0, &clFormat, &image_desc, NULL, &result); + TestRequire(result == CL_SUCCESS, "clCreateImage failed"); + + result = clEnqueueCopyImage(command_queue, subResourceInfo[i].mem, tempImage, + origin, origin, region, 0, NULL, NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueCopyImage failed"); + + // copy (0,0) to (1,1) and (w-1,h-1) to (w-2,h-2) using a kernel + { + result = clSetKernelArg( + kernel, + 0, + sizeof(cl_mem), + (void *)&tempImage); + result = clSetKernelArg( + kernel, + 1, + sizeof(cl_mem), + (void *)&subResourceInfo[i].mem); + + TestRequire(CL_SUCCESS == result, "clSetKernelArg failed"); + + size_t localWorkSize[] = {1}; + size_t globalWorkSize[] = {1}; + result = clEnqueueNDRangeKernel( + command_queue, + kernel, + 1, + NULL, + globalWorkSize, + localWorkSize, + 0, + NULL, + NULL); + TestRequire(CL_SUCCESS == result, "clEnqueueNDRangeKernel failed"); + } + // copy (w-1,0) to (w-2,1) and (0,h) to (1,h-2) using a memcpy + for (UINT x = 0; x < 2; ++x) + for (UINT y = 0; y < 2; ++y) + { + if (x == y) + { + continue; + } + + size_t src[3] = + { + x ? subResourceInfo[i].width - 1 : 0, + y ? subResourceInfo[i].height - 1 : 0, + 0, + }; + size_t dst[3] = + { + x ? subResourceInfo[i].width - 2 : 1, + y ? subResourceInfo[i].height - 2 : 1, + 0, + }; + size_t region[3] = + { + 1, + 1, + 1, + }; + result = clEnqueueCopyImage( + command_queue, + subResourceInfo[i].mem, + subResourceInfo[i].mem, + src, + dst, + region, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueCopyImage failed."); + } + clReleaseMemObject(tempImage); + } + + // release the resource from OpenCL + for (UINT i = 0; i < 2; ++i) + { + cl_uint memCount = 0; + cl_mem memToAcquire[MAX_REGISTERED_SUBRESOURCES]; + + // cut the registered sub-resources into two sets and send the release calls for them separately + if (i == 0) + { + for(UINT j = size->SubResourceCount/4; j < size->SubResourceCount; ++j) + { + memToAcquire[memCount++] = subResourceInfo[j].mem; + } + } + else + { + for(UINT j = 0; j < size->SubResourceCount/4; ++j) + { + memToAcquire[memCount++] = subResourceInfo[j].mem; + } + } + if (!memCount) continue; + + // do the release + result = clEnqueueReleaseD3D11ObjectsKHR( + command_queue, + memCount, + memToAcquire, + 0, + NULL, + &events[2+i]); + TestRequire(result == CL_SUCCESS, "clEnqueueReleaseD3D11ObjectsKHR failed."); + TestRequire(events[2+i], "clEnqueueReleaseD3D11ObjectsKHR did not return an event."); + + // make sure the event type is correct + cl_uint eventType = 0; + result = clGetEventInfo( + events[2+i], + CL_EVENT_COMMAND_TYPE, + sizeof(eventType), + &eventType, + NULL); + TestRequire(result == CL_SUCCESS, "clGetEventInfo for event created by clEnqueueReleaseD3D11ObjectsKHR failed."); + TestRequire(eventType == CL_COMMAND_RELEASE_D3D11_OBJECTS_KHR, "clGetEventInfo for CL_EVENT_COMMAND_TYPE was not CL_COMMAND_RELEASE_D3D11_OBJECTS_KHR."); + } + + for (UINT i = 0; i < size->SubResourceCount; ++i) + for (UINT x = 0; x < 2; ++x) + for (UINT y = 0; y < 2; ++y) + { + // create the staging buffer + ID3D11Texture2D* pStagingBuffer = NULL; + { + D3D11_TEXTURE2D_DESC desc = {0}; + desc.Width = 1; + desc.Height = 1; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = format->format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + hr = pDevice->CreateTexture2D(&desc, NULL, &pStagingBuffer); + TestRequire(SUCCEEDED(hr), "Failed to create staging buffer."); + } + + // wipe out the staging buffer to make sure we don't get stale values + { + D3D11_MAPPED_SUBRESOURCE mappedTexture; + hr = pDC->Map( + pStagingBuffer, + 0, + D3D11_MAP_READ_WRITE, + 0, + &mappedTexture); + TestRequire(SUCCEEDED(hr), "Failed to map staging buffer"); + memset(mappedTexture.pData, 0, format->bytesPerPixel); + pDC->Unmap(pStagingBuffer, 0); + } + + // copy the pixel to the staging buffer + { + D3D11_BOX box = {0}; + box.left = x ? subResourceInfo[i].width - 2 : 1; box.right = box.left + 1; + box.top = y ? subResourceInfo[i].height - 2 : 1; box.bottom = box.top + 1; + box.front = 0; box.back = 1; + pDC->CopySubresourceRegion( + pStagingBuffer, + 0, + 0, + 0, + 0, + pTexture, + subResourceInfo[i].subResource, + &box); + } + + // make sure we read back what was written next door + { + D3D11_MAPPED_SUBRESOURCE mappedTexture; + hr = pDC->Map( + pStagingBuffer, + 0, + D3D11_MAP_READ_WRITE, + 0, + &mappedTexture); + TestRequire(SUCCEEDED(hr), "Failed to map staging buffer"); + TestRequire( + !memcmp(mappedTexture.pData, texture2DPatterns[x][y], format->bytesPerPixel), + "Failed to map staging buffer"); + pDC->Unmap(pStagingBuffer, 0); + } + + pStagingBuffer->Release(); + } + + +Cleanup: + + if (pTexture) + { + pTexture->Release(); + } + for (UINT i = 0; i < size->SubResourceCount; ++i) + { + clReleaseMemObject(subResourceInfo[i].mem); + } + for (UINT i = 0; i < 4; ++i) + { + if (events[i]) + { + result = clReleaseEvent(events[i]); + TestRequire(result == CL_SUCCESS, "clReleaseEvent for event failed."); + } + } + + + HarnessD3D11_TestEnd(); +} + +bool is_format_supported( + cl_channel_order channel_order, + cl_channel_type channel_type, + const std::vector &supported_image_formats) +{ + for (std::vector::const_iterator it = supported_image_formats.begin(); it != supported_image_formats.end(); ++it) + if (it->image_channel_data_type == channel_type && it->image_channel_order == channel_order) + return true; + + return false; +} + +void TestDeviceTexture2D( + cl_device_id device, + cl_context context, + cl_command_queue command_queue, + ID3D11Device* pDevice, + ID3D11DeviceContext* pDC) +{ + cl_int result = CL_SUCCESS; + cl_kernel kernels[3] = {NULL, NULL, NULL}; + + const char *sourceRaw = + " \ + __kernel void texture2D\n\ + ( \n\ + __read_only image2d_t texIn, \n\ + __write_only image2d_t texOut \n\ + ) \n\ + { \n\ + const sampler_t smp = CLK_FILTER_NEAREST; \n\ + CLK_NORMALIZED_COORDS_FALSE |\n\ + CLK_ADDRESS_CLAMP_TO_EDGE; \n\ + %s value; \n\ + int2 coordIn; \n\ + int2 coordOut; \n\ + int w = get_image_width(texIn); \n\ + int h = get_image_height(texIn); \n\ + \n\ + coordIn = (int2)(0, 0); \n\ + coordOut = (int2)(1, 1); \n\ + value = read_image%s(texIn, smp, coordIn); \n\ + write_image%s(texOut, coordOut, value); \n\ + \n\ + coordIn = (int2)(w-1, h-1); \n\ + coordOut = (int2)(w-2, h-2); \n\ + value = read_image%s(texIn, smp, coordIn); \n\ + write_image%s(texOut, coordOut, value); \n\ + } \n\ + "; + + cl_uint supported_formats_count; + std::vector supported_image_formats; + result = clGetSupportedImageFormats(context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE2D, 0, NULL, &supported_formats_count); + TestRequire(CL_SUCCESS == result, "clGetSupportedImageFormats failed."); + + supported_image_formats.resize(supported_formats_count); + result = clGetSupportedImageFormats(context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE2D, supported_formats_count, &supported_image_formats[0], NULL); + TestRequire(CL_SUCCESS == result, "clGetSupportedImageFormats failed."); + + char source[2048]; + sprintf(source, sourceRaw, "float4", "f", "f", "f", "f"); + result = HarnessD3D11_CreateKernelFromSource(&kernels[0], device, context, source, "texture2D"); + TestRequire(CL_SUCCESS == result, "HarnessD3D11_CreateKernelFromSource failed."); + + sprintf(source, sourceRaw, "uint4", "ui", "ui", "ui", "ui"); + result = HarnessD3D11_CreateKernelFromSource(&kernels[1], device, context, source, "texture2D"); + TestRequire(CL_SUCCESS == result, "HarnessD3D11_CreateKernelFromSource failed."); + + sprintf(source, sourceRaw, "int4", "i", "i", "i", "i"); + result = HarnessD3D11_CreateKernelFromSource(&kernels[2], device, context, source, "texture2D"); + TestRequire(CL_SUCCESS == result, "HarnessD3D11_CreateKernelFromSource failed."); + + for (UINT format = 0, size = 0; format < formatCount; ++size, ++format) + { + if (!is_format_supported(formats[format].channel_order, formats[format].channel_type, supported_image_formats)) + { + HarnessD3D11_TestBegin("2D_texture: Format=%s, Width=%d, Height=%d, MipLevels=%d, ArraySize=%d\n", + formats[format].name_format, + texture2DSizes[size % texture2DSizeCount].Width, + texture2DSizes[size % texture2DSizeCount].Height, + texture2DSizes[size % texture2DSizeCount].MipLevels, + texture2DSizes[size % texture2DSizeCount].ArraySize); + log_info("\tFormat not supported, skipping test!\n"); + HarnessD3D11_TestEnd(); + + continue; + } + + SubTestTexture2D( + context, + command_queue, + kernels[formats[format].generic], + pDevice, + pDC, + &formats[format], + &texture2DSizes[size % texture2DSizeCount]); + } + +Cleanup: + + + for (UINT i = 0; i < 3; ++i) + { + if (kernels[i]) + { + clReleaseKernel(kernels[i]); + } + } +} + + diff --git a/test_conformance/d3d11/texture3d.cpp b/test_conformance/d3d11/texture3d.cpp new file mode 100644 index 00000000..05f53b74 --- /dev/null +++ b/test_conformance/d3d11/texture3d.cpp @@ -0,0 +1,489 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#define _CRT_SECURE_NO_WARNINGS +#include "harness.h" + +Texture3DSize texture3DSizes[] = +{ + { + 4, // Width + 4, // Height + 4, // Depth + 1, // MipLevels + 1, // SubResourceCount + { // SubResources + { 0 }, // MipLevel + { 0 }, // MipLevel + { 0 }, // MipLevel + { 0 }, // MipLevel + }, + 0, // MiscFlags + }, + { + 127, // Width + 55, // Height + 33, // Depth + 1, // MipLevels + 1, // SubResourceCount + { // SubResources + { 0 }, // MipLevel + { 0 }, // MipLevel + { 0 }, // MipLevel + { 0 }, // MipLevel + }, + 0, // MiscFlags + }, + { + 128, // Width + 256, // Height + 64, // Depth + 4, // MipLevels + 3, // SubResourceCount + { // SubResources + { 2 }, // MipLevel + { 1 }, // MipLevel + { 0 }, // MipLevel + { 0 }, // MipLevel + }, + 0, // MiscFlags + }, + { + 512, // Width + 64, // Height + 32, // Depth + 3, // MipLevels + 1, // SubResourceCount + { // SubResources + { 2 }, // MipLevel + { 0 }, // MipLevel + { 0 }, // MipLevel + { 0 }, // MipLevel + }, + 0, // MiscFlags + }, +}; +UINT texture3DSizeCount = sizeof(texture3DSizes)/sizeof(texture3DSizes[0]); + +const char * +texture3DPatterns[2][2][2] = +{ + { + {"PlaceTheCasseroleDis", "hInAColdOvenPlaceACh"}, + {"airFacingTheOvenAndS", "itInItForeverThinkAb"}, + }, + { + {"outHowHungryYouAreWh", "enNightFallsDoNotTur"}, + {"nOnTheLightMyEyeBeca", "meInflamedIHateCamus"}, + }, +}; + +void SubTestTexture3D( + cl_context context, + cl_command_queue command_queue, + ID3D11Device* pDevice, + ID3D11DeviceContext* pDC, + const TextureFormat* format, + const Texture3DSize* size) +{ + ID3D11Texture3D* pTexture = NULL; + HRESULT hr = S_OK; + + cl_int result = CL_SUCCESS; + + HarnessD3D11_TestBegin("3D Texture: Format=%s, Width=%d, Height=%d, Depth=%d, MipLevels=%d", + format->name_format, + size->Width, + size->Height, + size->Depth, + size->MipLevels); + + struct + { + cl_mem mem; + UINT subResource; + UINT width; + UINT height; + UINT depth; + } + subResourceInfo[4]; + + // create the D3D11 resources + { + D3D11_TEXTURE3D_DESC desc; + memset(&desc, 0, sizeof(desc) ); + desc.Width = size->Width; + desc.Height = size->Height; + desc.Depth = size->Depth; + desc.MipLevels = size->MipLevels; + desc.Format = format->format; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + hr = pDevice->CreateTexture3D(&desc, NULL, &pTexture); + TestRequire(SUCCEEDED(hr), "CreateTexture3D failed."); + } + + // initialize some useful variables + for (UINT i = 0; i < size->SubResourceCount; ++i) + { + // compute the expected values for the subresource + subResourceInfo[i].subResource = size->subResources[i].MipLevel; + subResourceInfo[i].width = size->Width; + subResourceInfo[i].height = size->Height; + subResourceInfo[i].depth = size->Depth; + for (UINT j = 0; j < size->subResources[i].MipLevel; ++j) { + subResourceInfo[i].width /= 2; + subResourceInfo[i].height /= 2; + subResourceInfo[i].depth /= 2; + } + subResourceInfo[i].mem = NULL; + } + + // copy a pattern into the corners of the image, coordinates + for (UINT i = 0; i < size->SubResourceCount; ++i) + for (UINT x = 0; x < 2; ++x) + for (UINT y = 0; y < 2; ++y) + for (UINT z = 0; z < 2; ++z) + { + // create the staging buffer + ID3D11Texture3D* pStagingBuffer = NULL; + { + D3D11_TEXTURE3D_DESC desc = {0}; + desc.Width = 1; + desc.Height = 1; + desc.Depth = 1; + desc.MipLevels = 1; + desc.Format = format->format; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + hr = pDevice->CreateTexture3D(&desc, NULL, &pStagingBuffer); + TestRequire(SUCCEEDED(hr), "CreateTexture3D failed."); + } + + // write the data to the staging buffer + { + D3D11_MAPPED_SUBRESOURCE mappedTexture; + hr = pDC->Map( + pStagingBuffer, + 0, + D3D11_MAP_READ_WRITE, + 0, + &mappedTexture); + memcpy(mappedTexture.pData, texture3DPatterns[x][y][z], format->bytesPerPixel); + pDC->Unmap(pStagingBuffer, 0); + } + + // copy the data to to the texture + { + D3D11_BOX box = {0}; + box.front = 0; box.back = 1; + box.top = 0; box.bottom = 1; + box.left = 0; box.right = 1; + pDC->CopySubresourceRegion( + pTexture, + subResourceInfo[i].subResource, + x ? subResourceInfo[i].width - 1 : 0, + y ? subResourceInfo[i].height - 1 : 0, + z ? subResourceInfo[i].depth - 1 : 0, + pStagingBuffer, + 0, + &box); + } + + pStagingBuffer->Release(); + } + + // create the cl_mem objects for the resources and verify its sanity + for (UINT i = 0; i < size->SubResourceCount; ++i) + { + // create a cl_mem for the resource + subResourceInfo[i].mem = clCreateFromD3D11Texture3DKHR( + context, + 0, + pTexture, + subResourceInfo[i].subResource, + &result); + if (CL_IMAGE_FORMAT_NOT_SUPPORTED == result) + { + goto Cleanup; + } + TestRequire(result == CL_SUCCESS, "clCreateFromD3D11Texture3DKHR failed"); + + // query resource pointer and verify + ID3D11Resource* clResource = NULL; + result = clGetMemObjectInfo( + subResourceInfo[i].mem, + CL_MEM_D3D11_RESOURCE_KHR, + sizeof(clResource), + &clResource, + NULL); + TestRequire(result == CL_SUCCESS, "clGetMemObjectInfo for CL_MEM_D3D11_RESOURCE_KHR failed."); + TestRequire(clResource == pTexture, "clGetMemObjectInfo for CL_MEM_D3D11_RESOURCE_KHR returned incorrect value."); + + // query subresource and verify + UINT clSubResource; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_D3D11_SUBRESOURCE_KHR, + sizeof(clSubResource), + &clSubResource, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_D3D11_SUBRESOURCE_KHR failed"); + TestRequire(clSubResource == subResourceInfo[i].subResource, "clGetImageInfo for CL_IMAGE_D3D11_SUBRESOURCE_KHR returned incorrect value."); + + // query format and verify + cl_image_format clFormat; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_FORMAT, + sizeof(clFormat), + &clFormat, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_FORMAT failed"); + TestRequire(clFormat.image_channel_order == format->channel_order, "clGetImageInfo for CL_IMAGE_FORMAT returned incorrect channel order."); + TestRequire(clFormat.image_channel_data_type == format->channel_type, "clGetImageInfo for CL_IMAGE_FORMAT returned incorrect channel data type."); + + // query width + size_t width; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_WIDTH, + sizeof(width), + &width, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_WIDTH failed"); + TestRequire(width == subResourceInfo[i].width, "clGetImageInfo for CL_IMAGE_HEIGHT returned incorrect value."); + + // query height + size_t height; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_HEIGHT, + sizeof(height), + &height, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_HEIGHT failed"); + TestRequire(height == subResourceInfo[i].height, "clGetImageInfo for CL_IMAGE_HEIGHT returned incorrect value."); + + // query depth + size_t depth; + result = clGetImageInfo( + subResourceInfo[i].mem, + CL_IMAGE_DEPTH, + sizeof(depth), + &depth, + NULL); + TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_DEPTH failed"); + TestRequire(depth == subResourceInfo[i].depth, "clGetImageInfo for CL_IMAGE_DEPTH returned incorrect value."); + + } + + // acquire the resources for OpenCL + { + cl_mem memToAcquire[MAX_REGISTERED_SUBRESOURCES]; + + // cut the registered sub-resources into two sets and send the acquire calls for them separately + for(UINT i = 0; i < size->SubResourceCount; ++i) + { + memToAcquire[i] = subResourceInfo[i].mem; + } + + // do the acquire + result = clEnqueueAcquireD3D11ObjectsKHR( + command_queue, + size->SubResourceCount, + memToAcquire, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueAcquireD3D11ObjectsKHR failed."); + } + + // download the data using OpenCL & compare with the expected results + // copy the corners of the image into the image + for (UINT i = 0; i < size->SubResourceCount; ++i) + for (UINT x = 0; x < 2; ++x) + for (UINT y = 0; y < 2; ++y) + for (UINT z = 0; z < 2; ++z) + { + if (x == y && y == z && 0) + { + continue; + } + size_t src[3] = + { + x ? subResourceInfo[i].width - 1 : 0, + y ? subResourceInfo[i].height - 1 : 0, + z ? subResourceInfo[i].depth - 1 : 0, + }; + size_t dst[3] = + { + x ? subResourceInfo[i].width - 2 : 1, + y ? subResourceInfo[i].height - 2 : 1, + z ? subResourceInfo[i].depth - 2 : 1, + }; + size_t region[3] = + { + 1, + 1, + 1, + }; + result = clEnqueueCopyImage( + command_queue, + subResourceInfo[i].mem, + subResourceInfo[i].mem, + src, + dst, + region, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueCopyImage failed."); + } + + // release the resource from OpenCL + { + cl_mem memToAcquire[MAX_REGISTERED_SUBRESOURCES]; + for(UINT i = 0; i < size->SubResourceCount; ++i) + { + memToAcquire[i] = subResourceInfo[i].mem; + } + + // do the release + result = clEnqueueReleaseD3D11ObjectsKHR( + command_queue, + size->SubResourceCount, + memToAcquire, + 0, + NULL, + NULL); + TestRequire(result == CL_SUCCESS, "clEnqueueReleaseD3D11ObjectsKHR failed."); + } + + for (UINT i = 0; i < size->SubResourceCount; ++i) + for (UINT x = 0; x < 2; ++x) + for (UINT y = 0; y < 2; ++y) + for (UINT z = 0; z < 2; ++z) + { + // create the staging buffer + ID3D11Texture3D* pStagingBuffer = NULL; + { + D3D11_TEXTURE3D_DESC desc = {0}; + desc.Width = 1; + desc.Height = 1; + desc.Depth = 1; + desc.MipLevels = 1; + desc.Format = format->format; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + hr = pDevice->CreateTexture3D(&desc, NULL, &pStagingBuffer); + TestRequire(SUCCEEDED(hr), "Failed to create staging buffer."); + } + + // wipe out the staging buffer to make sure we don't get stale values + { + D3D11_MAPPED_SUBRESOURCE mappedTexture; + hr = pDC->Map( + pStagingBuffer, + 0, + D3D11_MAP_READ_WRITE, + 0, + &mappedTexture); + TestRequire(SUCCEEDED(hr), "Failed to map staging buffer"); + memset(mappedTexture.pData, 0, format->bytesPerPixel); + pDC->Unmap(pStagingBuffer, 0); + } + + // copy the pixel to the staging buffer + { + D3D11_BOX box = {0}; + box.left = x ? subResourceInfo[i].width - 2 : 1; box.right = box.left + 1; + box.top = y ? subResourceInfo[i].height - 2 : 1; box.bottom = box.top + 1; + box.front = z ? subResourceInfo[i].depth - 2 : 1; box.back = box.front + 1; + pDC->CopySubresourceRegion( + pStagingBuffer, + 0, + 0, + 0, + 0, + pTexture, + subResourceInfo[i].subResource, + &box); + } + + // make sure we read back what was written next door + { + D3D11_MAPPED_SUBRESOURCE mappedTexture; + hr = pDC->Map( + pStagingBuffer, + 0, + D3D11_MAP_READ_WRITE, + 0, + &mappedTexture); + TestRequire(SUCCEEDED(hr), "Failed to map staging buffer"); + TestRequire( + !memcmp(mappedTexture.pData, texture3DPatterns[x][y][z], format->bytesPerPixel), + "Failed to map staging buffer"); + pDC->Unmap(pStagingBuffer, 0); + } + + pStagingBuffer->Release(); + } + + +Cleanup: + + if (pTexture) + { + pTexture->Release(); + } + for (UINT i = 0; i < size->SubResourceCount; ++i) + { + clReleaseMemObject(subResourceInfo[i].mem); + } + + HarnessD3D11_TestEnd(); +} + + +void TestDeviceTexture3D( + cl_device_id device, + cl_context context, + cl_command_queue command_queue, + ID3D11Device* pDevice, + ID3D11DeviceContext* pDC) +{ + cl_int result = CL_SUCCESS; + + + for (UINT format = 0, size = 0; format < formatCount; ++size, ++format) + { + SubTestTexture3D( + context, + command_queue, + pDevice, + pDC, + &formats[format], + &texture3DSizes[size % texture3DSizeCount]); + } +} + diff --git a/test_conformance/device_execution/CMakeLists.txt b/test_conformance/device_execution/CMakeLists.txt new file mode 100644 index 00000000..450db838 --- /dev/null +++ b/test_conformance/device_execution/CMakeLists.txt @@ -0,0 +1,27 @@ +set(MODULE_NAME DEVICE_EXECUTION) + +set(DEVICE_EXECUTION_SOURCES + device_info.cpp + device_queue.cpp + enqueue_block.cpp + enqueue_flags.cpp + enqueue_multi_queue.cpp + enqueue_ndrange.cpp + enqueue_wg_size.cpp + execute_block.cpp + host_multi_queue.cpp + host_queue_order.cpp + main.c + nested_blocks.cpp + utils.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) + +# end of file # diff --git a/test_conformance/device_execution/Makefile b/test_conformance/device_execution/Makefile new file mode 100644 index 00000000..59271df0 --- /dev/null +++ b/test_conformance/device_execution/Makefile @@ -0,0 +1,52 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + device_info.cpp \ + device_queue.cpp \ + enqueue_block.cpp \ + enqueue_flags.cpp \ + enqueue_multi_queue.cpp \ + enqueue_ndrange.cpp \ + enqueue_wg_size.cpp \ + execute_block.cpp \ + host_multi_queue.cpp \ + host_queue_order.cpp \ + nested_blocks.cpp \ + utils.cpp \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/typeWrappers.cpp \ + ../../test_common/harness/mt19937.c \ + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +HEADERS = +TARGET = test_device_execution +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/device_execution/device_info.cpp b/test_conformance/device_execution/device_info.cpp new file mode 100644 index 00000000..fa37fe6b --- /dev/null +++ b/test_conformance/device_execution/device_info.cpp @@ -0,0 +1,106 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" + +#include "procs.h" +#include "utils.h" + +static const cl_uint MIN_DEVICE_PREFFERED_QUEUE_SIZE = 16 * 1024; +static const cl_uint MAX_DEVICE_QUEUE_SIZE = 256 * 1024; +static const cl_uint MAX_DEVICE_EMBEDDED_QUEUE_SIZE = 64 * 1024; + +#ifdef CL_VERSION_2_0 + +int test_device_info(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int err_ret; + int embedded = 0; + size_t ret_len; + char profile[32] = {0}; + cl_command_queue_properties properties; + cl_uint size; + + err_ret = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), profile, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_PROFILE) failed"); + if(ret_len < sizeof(profile) && strcmp(profile, "FULL_PROFILE") == 0) embedded = 0; + else if(ret_len < sizeof(profile) && strcmp(profile, "EMBEDDED_PROFILE") == 0) embedded = 1; + else + { + log_error("Unknown device profile: %s\n", profile); + return -1; + } + + err_ret = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES, sizeof(properties), &properties, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_QUEUE_ON_HOST_PROPERTIES) failed"); + if(!(properties&CL_QUEUE_PROFILING_ENABLE)) + { + log_error("Host command-queue does not support mandated minimum capability: CL_QUEUE_PROFILING_ENABLE\n"); + return -1; + } + + err_ret = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES, sizeof(properties), &properties, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES) failed"); + if(!(properties&CL_QUEUE_PROFILING_ENABLE)) + { + log_error("Device command-queue does not support mandated minimum capability: CL_QUEUE_PROFILING_ENABLE\n"); + return -1; + } + if(!(properties&CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE)) + { + log_error("Device command-queue does not support mandated minimum capability: CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE\n"); + return -1; + } + + err_ret = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE, sizeof(size), &size, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE) failed"); + if(size < MIN_DEVICE_PREFFERED_QUEUE_SIZE) + { + log_error("Device command-queue preferred size is less than minimum %dK: %dK\n", MIN_DEVICE_PREFFERED_QUEUE_SIZE/1024, size/1024); + return -1; + } + + err_ret = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, sizeof(size), &size, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE) failed"); + if(size < (embedded ? MAX_DEVICE_EMBEDDED_QUEUE_SIZE : MAX_DEVICE_QUEUE_SIZE)) + { + log_error("Device command-queue maximum size is less than minimum %dK: %dK\n", (embedded ? MAX_DEVICE_EMBEDDED_QUEUE_SIZE : MAX_DEVICE_QUEUE_SIZE)/1024, size/1024); + return -1; + } + + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_ON_DEVICE_QUEUES, sizeof(size), &size, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_ON_DEVICE_QUEUES) failed"); + if(size < 1) + { + log_error("Maximum number of device queues is less than minimum 1: %d\n", size); + return -1; + } + + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_ON_DEVICE_EVENTS, sizeof(size), &size, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_ON_DEVICE_EVENTS) failed"); + if(size < 1024) + { + log_error("Maximum number of events in use by a device queue is less than minimum 1024: %d\n", size); + return -1; + } + + return 0; +} + +#endif + diff --git a/test_conformance/device_execution/device_queue.cpp b/test_conformance/device_execution/device_queue.cpp new file mode 100644 index 00000000..2a0e3961 --- /dev/null +++ b/test_conformance/device_execution/device_queue.cpp @@ -0,0 +1,188 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" + +#include + +#include "procs.h" +#include "utils.h" + +static int check_device_queue(cl_device_id device, cl_context context, cl_command_queue queue, cl_uint size) +{ + cl_int err_ret; + cl_context q_context; + cl_device_id q_device; + cl_command_queue_properties q_properties; + cl_uint q_size; + size_t size_ret; + + err_ret = clRetainCommandQueue(queue); + test_error(err_ret, "clRetainCommandQueue() failed"); + + err_ret = clGetCommandQueueInfo(queue, CL_QUEUE_CONTEXT, sizeof(q_context), &q_context, &size_ret); + test_error(err_ret, "clGetCommandQueueInfo(CL_QUEUE_CONTEXT) failed"); + if(size_ret != sizeof(q_context) || q_context != context) + { + log_error("clGetCommandQueueInfo(CL_QUEUE_CONTEXT) returned invalid context\n"); + return -1; + } + + err_ret = clGetCommandQueueInfo(queue, CL_QUEUE_DEVICE, sizeof(q_device), &q_device, &size_ret); + test_error(err_ret, "clGetCommandQueueInfo(CL_QUEUE_DEVICE) failed"); + if(size_ret != sizeof(q_device) || q_device != device) + { + log_error("clGetCommandQueueInfo(CL_QUEUE_DEVICE) returned invalid device\n"); + return -1; + } + + err_ret = clGetCommandQueueInfo(queue, CL_QUEUE_PROPERTIES, sizeof(q_properties), &q_properties, &size_ret); + test_error(err_ret, "clGetCommandQueueInfo(CL_QUEUE_PROPERTIES) failed"); + if(size_ret != sizeof(q_properties) || !(q_properties & (CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE|CL_QUEUE_ON_DEVICE))) + { + log_error("clGetCommandQueueInfo(CL_QUEUE_PROPERTIES) returned invalid properties\n"); + return -1; + } + + err_ret = clGetCommandQueueInfo(queue, CL_QUEUE_SIZE, sizeof(q_size), &q_size, &size_ret); + test_error(err_ret, "clGetCommandQueueInfo(CL_QUEUE_SIZE) failed"); + if(size_ret != sizeof(q_size) || q_size < 1) + { + log_error("clGetCommandQueueInfo(CL_QUEUE_SIZE) returned invalid queue size\n"); + return -1; + } + + err_ret = clReleaseCommandQueue(queue); + test_error(err_ret, "clReleaseCommandQueue() failed"); + + + return 0; +} + +static int check_device_queues(cl_device_id device, cl_context context, cl_uint num_queues, cl_queue_properties *properties, cl_uint size) +{ + cl_int err_ret, res = 0; + cl_uint i; + std::vector queue(num_queues); + + // Create all queues + for(i = 0; i < num_queues; ++i) + { + queue[i] = clCreateCommandQueueWithProperties(context, device, properties, &err_ret); + test_error(err_ret, "clCreateCommandQueueWithProperties(CL_QUEUE_DEVICE) failed"); + } + + // Validate all queues + for(i = 0; i < num_queues; ++i) + { + err_ret = check_device_queue(device, context, queue[i], size); + if(check_error(err_ret, "Device queue[%d] validation failed", i)) res = -1; + + } + return res; +} + +int test_device_queue(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int err_ret, res = 0; + size_t ret_len; + clCommandQueueWrapper dev_queue; + cl_uint preffered_size, max_size, max_queues; + + cl_queue_properties queue_prop_def[] = + { + CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE|CL_QUEUE_ON_DEVICE|CL_QUEUE_ON_DEVICE_DEFAULT, + 0 + }; + + cl_queue_properties queue_prop[] = + { + CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE|CL_QUEUE_ON_DEVICE, + 0 + }; + + err_ret = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE, sizeof(preffered_size), &preffered_size, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE) failed"); + + err_ret = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, sizeof(max_size), &max_size, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE) failed"); + + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_ON_DEVICE_QUEUES, sizeof(max_queues), &max_queues, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_ON_DEVICE_QUEUES) failed"); + + if(max_queues > MAX_QUEUES) max_queues = MAX_QUEUES; + + dev_queue = clCreateCommandQueueWithProperties(context, device, queue_prop_def, &err_ret); + test_error(err_ret, "clCreateCommandQueueWithProperties(CL_QUEUE_DEVICE|CL_QUEUE_DEFAULT) failed"); + + err_ret = check_device_queue(device, context, dev_queue, preffered_size); + if(check_error(err_ret, "Default device queue validation failed")) res = -1; + + log_info("Default device queue is OK.\n"); + + if(max_queues > 1) // Check more queues if supported. + { + cl_uint q_size = preffered_size-1024; + cl_queue_properties queue_prop_size[] = + { + CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE|CL_QUEUE_ON_DEVICE, + CL_QUEUE_SIZE, q_size, + 0 + }; + + cl_queue_properties queue_prop_max[] = + { + CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE|CL_QUEUE_ON_DEVICE, + CL_QUEUE_SIZE, max_size, + 0 + }; + { + err_ret = check_device_queues(device, context, 1, queue_prop, preffered_size); + if(check_error(err_ret, "Second device queue validation failed")) res = -1; + else log_info("Second device queue is OK.\n"); + } + { + err_ret = check_device_queues(device, context, 1, queue_prop_size, q_size); + if(check_error(err_ret, "Device queue with size validation failed")) res = -1; + else log_info("Device queue with size is OK.\n"); + } + { + err_ret = check_device_queues(device, context, 1, queue_prop_max, max_size); + if(check_error(err_ret, "Device queue max size validation failed")) res = -1; + else log_info("Device queue max size is OK.\n"); + } + { + err_ret = check_device_queues(device, context, max_queues, queue_prop, preffered_size); + if(check_error(err_ret, "Max number device queue validation failed")) res = -1; + else log_info("Max number device queue is OK.\n"); + } + { + err_ret = check_device_queues(device, context, max_queues, queue_prop_size, q_size); + if(check_error(err_ret, "Max number device queue with size validation failed")) res = -1; + else log_info("Max number device queue with size is OK.\n"); + } + { + err_ret = check_device_queues(device, context, max_queues, queue_prop_max, max_size); + if(check_error(err_ret, "Max number device queue with max size validation failed")) res = -1; + else log_info("Max number device queue with max size is OK.\n"); + } + } + + return res; +} + diff --git a/test_conformance/device_execution/enqueue_block.cpp b/test_conformance/device_execution/enqueue_block.cpp new file mode 100644 index 00000000..b3966e57 --- /dev/null +++ b/test_conformance/device_execution/enqueue_block.cpp @@ -0,0 +1,684 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" + +#include + +#include "procs.h" +#include "utils.h" +#include + + +#ifdef CL_VERSION_2_0 +extern int gWimpyMode; +static const char* enqueue_simple_block[] = +{ + NL, "void block_fn(size_t tid, int mul, __global int* res)" + NL, "{" + NL, " res[tid] = mul * 7 - 21;" + NL, "}" + NL, "" + NL, "kernel void enqueue_simple_block(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(tid, multiplier, res); };" + NL, "" + NL, " res[tid] = -1;" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "}" + NL +}; + +static const char* enqueue_block_with_local_arg1[] = +{ + NL, "#define LOCAL_MEM_SIZE 10" + NL, "" + NL, "void block_fn_local_arg1(size_t tid, int mul, __global int* res, __local int* tmp)" + NL, "{" + NL, " for(int i = 0; i < LOCAL_MEM_SIZE; i++)" + NL, " {" + NL, " tmp[i] = mul * 7 - 21;" + NL, " res[tid] += tmp[i];" + NL, " }" + NL, " res[tid] += 2;" + NL, "}" + NL, "" + NL, "kernel void enqueue_block_with_local_arg1(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " void (^kernelBlock)(__local void*) = ^(__local void* buf){ block_fn_local_arg1(tid, multiplier, res, (local int*)buf); };" + NL, "" + NL, " res[tid] = -2;" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock, (uint)(LOCAL_MEM_SIZE*sizeof(int)));" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "}" + NL +}; + +static const char* enqueue_block_with_local_arg2[] = +{ + NL, "#define LOCAL_MEM_SIZE 10" + NL, "" + NL, "void block_fn_local_arg1(size_t tid, int mul, __global int* res, __local int* tmp1, __local float4* tmp2)" + NL, "{" + NL, " for(int i = 0; i < LOCAL_MEM_SIZE; i++)" + NL, " {" + NL, " tmp1[i] = mul * 7 - 21;" + NL, " tmp2[i].x = (float)(mul * 7 - 21);" + NL, " tmp2[i].y = (float)(mul * 7 - 21);" + NL, " tmp2[i].z = (float)(mul * 7 - 21);" + NL, " tmp2[i].w = (float)(mul * 7 - 21);" + NL, "" + NL, " res[tid] += tmp1[i];" + NL, " res[tid] += (int)(tmp2[i].x+tmp2[i].y+tmp2[i].z+tmp2[i].w);" + NL, " }" + NL, " res[tid] += 2;" + NL, "}" + NL, "" + NL, "kernel void enqueue_block_with_local_arg2(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " void (^kernelBlock)(__local void*, __local void*) = ^(__local void* buf1, __local void* buf2)" + NL, " { block_fn_local_arg1(tid, multiplier, res, (local int*)buf1, (local float4*)buf2); };" + NL, "" + NL, " res[tid] = -2;" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock, (uint)(LOCAL_MEM_SIZE*sizeof(int)), (uint)(LOCAL_MEM_SIZE*sizeof(float4)));" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "}" + NL +}; + +static const char* enqueue_block_with_wait_list[] = +{ + NL, "#define BLOCK_SUBMITTED 1" + NL, "#define BLOCK_COMPLETED 2" + NL, "#define CHECK_SUCCESS 0" + NL, "" + NL, "kernel void enqueue_block_with_wait_list(__global int* res)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " clk_event_t user_evt = create_user_event();" + NL, "" + NL, " res[tid] = BLOCK_SUBMITTED;" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, " clk_event_t block_evt;" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, 1, &user_evt, &block_evt," + NL, " ^{" + NL, " res[tid] = BLOCK_COMPLETED;" + NL, " });" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "" + NL, " retain_event(block_evt);" + NL, " release_event(block_evt);" + NL, "" + NL, " //check block is not started" + NL, " if(res[tid] == BLOCK_SUBMITTED)" + NL, " {" + NL, " clk_event_t my_evt;" + NL, " enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, 1, &block_evt, &my_evt, " + NL, " ^{" + NL, " //check block is completed" + NL, " if(res[tid] == BLOCK_COMPLETED) res[tid] = CHECK_SUCCESS;" + NL, " });" + NL, " release_event(my_evt);" + NL, " }" + NL, "" + NL, " set_user_event_status(user_evt, CL_COMPLETE);" + NL, "" + NL, " release_event(user_evt);" + NL, " release_event(block_evt);" + NL, "}" + NL +}; + +static const char* enqueue_block_with_wait_list_and_local_arg[] = +{ + NL, "#define LOCAL_MEM_SIZE 10" + NL, "#define BLOCK_COMPLETED 1" + NL, "#define BLOCK_SUBMITTED 2" + NL, "#define BLOCK_STARTED 3" + NL, "#define CHECK_SUCCESS 0" + NL, "" + NL, "void block_fn_local_arg(size_t tid, int mul, __global int* res, __local int* tmp)" + NL, "{" + NL, " res[tid] = BLOCK_STARTED;" + NL, " for(int i = 0; i < LOCAL_MEM_SIZE; i++)" + NL, " {" + NL, " tmp[i] = mul * 7 - 21;" + NL, " res[tid] += tmp[i];" + NL, " }" + NL, " if(res[tid] == BLOCK_STARTED) res[tid] = BLOCK_COMPLETED;" + NL, "}" + NL, "" + NL, "kernel void enqueue_block_with_wait_list_and_local_arg(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " size_t tid = get_global_id(0);" + NL, " clk_event_t user_evt = create_user_event();" + NL, "" + NL, " res[tid] = BLOCK_SUBMITTED;" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, " clk_event_t block_evt;" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, 1, &user_evt, &block_evt, " + NL, " ^(__local void* buf) {" + NL, " block_fn_local_arg(tid, multiplier, res, (__local int*)buf);" + NL, " }, LOCAL_MEM_SIZE*sizeof(int));" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "" + NL, " retain_event(block_evt);" + NL, " release_event(block_evt);" + NL, "" + NL, " //check block is not started" + NL, " if(res[tid] == BLOCK_SUBMITTED)" + NL, " {" + NL, " clk_event_t my_evt;" + NL, " enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, 1, &block_evt, &my_evt, " + NL, " ^{" + NL, " //check block is completed" + NL, " if(res[tid] == BLOCK_COMPLETED) res[tid] = CHECK_SUCCESS;" + NL, " });" + NL, " release_event(my_evt);" + NL, " }" + NL, "" + NL, " set_user_event_status(user_evt, CL_COMPLETE);" + NL, "" + NL, " release_event(user_evt);" + NL, " release_event(block_evt);" + NL, "}" + NL +}; + +static const char* enqueue_block_get_kernel_work_group_size[] = +{ + NL, "void block_fn(size_t tid, int mul, __global int* res)" + NL, "{" + NL, " res[tid] = mul * 7 - 21;" + NL, "}" + NL, "" + NL, "kernel void enqueue_block_get_kernel_work_group_size(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(tid, multiplier, res); };" + NL, "" + NL, " size_t local_work_size = get_kernel_work_group_size(kernelBlock);" + NL, " if (local_work_size <= 0){ res[tid] = -1; return; }" + NL, " size_t global_work_size = local_work_size * 4;" + NL, "" + NL, " res[tid] = -1;" + NL, " queue_t q1 = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(global_work_size, local_work_size);" + NL, "" + NL, " int enq_res = enqueue_kernel(q1, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "}" +}; + +static const char* enqueue_block_get_kernel_preferred_work_group_size_multiple[] = +{ + NL, "void block_fn(size_t tid, int mul, __global int* res)" + NL, "{" + NL, " res[tid] = mul * 7 - 21;" + NL, "}" + NL, "" + NL, "kernel void enqueue_block_get_kernel_preferred_work_group_size_multiple(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(tid, multiplier, res); };" + NL, "" + NL, " size_t local_work_size = get_kernel_preferred_work_group_size_multiple(kernelBlock);" + NL, " if (local_work_size <= 0){ res[tid] = -1; return; }" + NL, " size_t global_work_size = local_work_size * 4;" + NL, "" + NL, " res[tid] = -1;" + NL, " queue_t q1 = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(global_work_size, local_work_size);" + NL, "" + NL, " int enq_res = enqueue_kernel(q1, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "}" +}; + +static const char* enqueue_block_capture_event_profiling_info_after_execution[] = +{ + NL, "#define MAX_GWS " STRINGIFY_VALUE(MAX_GWS) + NL, "" + NL, "__global ulong value[MAX_GWS*2] = {0};" + NL, "" + NL, "void block_fn(size_t tid, __global int* res)" + NL, "{" + NL, " res[tid] = -2;" + NL, "}" + NL, "" + NL, "void check_res(size_t tid, const clk_event_t evt, __global int* res)" + NL, "{" + NL, " capture_event_profiling_info (evt, CLK_PROFILING_COMMAND_EXEC_TIME, &value[tid*2]);" + NL, "" + NL, " if (value[tid*2] > 0 && value[tid*2+1] > 0) res[tid] = 0;" + NL, " else res[tid] = -4;" + NL, " release_event(evt);" + NL, "}" + NL, "" + NL, "kernel void enqueue_block_capture_event_profiling_info_after_execution(__global int* res)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " res[tid] = -1;" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, " clk_event_t block_evt1;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn (tid, res); };" + NL, "" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, 0, NULL, &block_evt1, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "" + NL, " void (^checkBlock) (void) = ^{ check_res(tid, block_evt1, res); };" + NL, "" + NL, " enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, 1, &block_evt1, NULL, checkBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -3; return; }" + NL, "}" + NL +}; + +static const char* enqueue_block_capture_event_profiling_info_before_execution[] = +{ + NL, "#define MAX_GWS " STRINGIFY_VALUE(MAX_GWS) + NL, "" + NL, "__global ulong value[MAX_GWS*2] = {0};" + NL, "" + NL, "void block_fn(size_t tid, __global int* res)" + NL, "{" + NL, " res[tid] = -2;" + NL, "}" + NL, "" + NL, "void check_res(size_t tid, const ulong *value, __global int* res)" + NL, "{" + NL, " if (value[tid*2] > 0 && value[tid*2+1] > 0) res[tid] = 0;" + NL, " else res[tid] = -4;" + NL, "}" + NL, "" + NL, "kernel void enqueue_block_capture_event_profiling_info_before_execution(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " size_t tid = get_global_id(0);" + NL, " clk_event_t user_evt = create_user_event();" + NL, "" + NL, " res[tid] = -1;" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, " clk_event_t block_evt1;" + NL, " clk_event_t block_evt2;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn (tid, res); };" + NL, "" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, 1, &user_evt, &block_evt1, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "" + NL, " capture_event_profiling_info (block_evt1, CLK_PROFILING_COMMAND_EXEC_TIME, &value[tid*2]);" + NL, "" + NL, " set_user_event_status(user_evt, CL_COMPLETE);" + NL, "" + NL, " void (^checkBlock) (void) = ^{ check_res(tid, &value, res); };" + NL, "" + NL, " enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, 1, &block_evt1, &block_evt2, checkBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -3; return; }" + NL, "" + NL, " release_event(user_evt);" + NL, " release_event(block_evt1);" + NL, " release_event(block_evt2);" + NL, "}" + NL +}; + +static const char* enqueue_block_with_barrier[] = +{ + NL, "void block_fn(size_t tid, int mul, __global int* res)" + NL, "{" + NL, " if(mul > 0) barrier(CLK_GLOBAL_MEM_FENCE);" + NL, " res[tid] = mul * 7 -21;" + NL, "}" + NL, "" + NL, "void loop_fn(size_t tid, int n, __global int* res)" + NL, "{" + NL, " while(n > 0)" + NL, " {" + NL, " barrier(CLK_GLOBAL_MEM_FENCE);" + NL, " res[tid] = 0;" + NL, " --n;" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_block_with_barrier(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " size_t tid = get_global_id(0);" + NL, " queue_t def_q = get_default_queue();" + NL, " res[tid] = -1;" + NL, " size_t n = 256;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(tid, multiplier, res); };" + NL, "" + NL, " ndrange_t ndrange = ndrange_1D(n);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "" + NL, " void (^loopBlock)(void) = ^{ loop_fn(tid, n, res); };" + NL, "" + NL, " enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, loopBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "}" + NL +}; + +static const char* enqueue_marker_with_block_event[] = +{ + NL, "#define BLOCK_COMPLETED 1" + NL, "#define BLOCK_SUBMITTED 2" + NL, "#define CHECK_SUCCESS 0" + NL, "" + NL, "kernel void enqueue_marker_with_block_event(__global int* res)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " clk_event_t user_evt = create_user_event();" + NL, "" + NL, " res[tid] = BLOCK_SUBMITTED;" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, "" + NL, " clk_event_t block_evt1;" + NL, " clk_event_t marker_evt;" + NL, "" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, 1, &user_evt, &block_evt1," + NL, " ^{" + NL, " res[tid] = BLOCK_COMPLETED;" + NL, " });" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -2; return; }" + NL, "" + NL, " enq_res = enqueue_marker(def_q, 1, &block_evt1, &marker_evt);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -3; return; }" + NL, "" + NL, " retain_event(marker_evt);" + NL, " release_event(marker_evt);" + NL, "" + NL, " //check block is not started" + NL, " if(res[tid] == BLOCK_SUBMITTED)" + NL, " {" + NL, " clk_event_t my_evt;" + NL, " enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, 1, &marker_evt, &my_evt, " + NL, " ^{" + NL, " //check block is completed" + NL, " if(res[tid] == BLOCK_COMPLETED) res[tid] = CHECK_SUCCESS;" + NL, " });" + NL, " release_event(my_evt);" + NL, " }" + NL, "" + NL, " set_user_event_status(user_evt, CL_COMPLETE);" + NL, "" + NL, " release_event(block_evt1);" + NL, " release_event(marker_evt);" + NL, " release_event(user_evt);" + NL, "}" + NL +}; + +static const char* enqueue_marker_with_user_event[] = +{ + NL, "#define BLOCK_COMPLETED 1" + NL, "#define BLOCK_SUBMITTED 2" + NL, "#define CHECK_SUCCESS 0" + NL, "" + NL, "kernel void enqueue_marker_with_user_event(__global int* res)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " uint multiplier = 7;" + NL, "" + NL, " clk_event_t user_evt = create_user_event();" + NL, "" + NL, " res[tid] = BLOCK_SUBMITTED;" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, "" + NL, " clk_event_t marker_evt;" + NL, " clk_event_t block_evt;" + NL, "" + NL, " int enq_res = enqueue_marker(def_q, 1, &user_evt, &marker_evt);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "" + NL, " retain_event(marker_evt);" + NL, " release_event(marker_evt);" + NL, "" + NL, " enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, 1, &marker_evt, &block_evt, " + NL, " ^{" + NL, " if(res[tid] == BLOCK_SUBMITTED) res[tid] = CHECK_SUCCESS;" + NL, " });" + NL, "" + NL, " //check block is not started" + NL, " if(res[tid] != BLOCK_SUBMITTED) { res[tid] = -2; return; }" + NL, "" + NL, " set_user_event_status(user_evt, CL_COMPLETE);" + NL, "" + NL, " release_event(block_evt);" + NL, " release_event(marker_evt);" + NL, " release_event(user_evt);" + NL, "}" + NL +}; + +static const char* enqueue_marker_with_mixed_events[] = +{ + NL, "#define BLOCK_COMPLETED 1" + NL, "#define BLOCK_SUBMITTED 2" + NL, "#define CHECK_SUCCESS 0" + NL, "" + NL, "kernel void enqueue_marker_with_mixed_events(__global int* res)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " clk_event_t mix_ev[2];" + NL, " mix_ev[0] = create_user_event();" + NL, "" + NL, " res[tid] = BLOCK_SUBMITTED;" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, "" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, 1, &mix_ev[0], &mix_ev[1]," + NL, " ^{" + NL, " res[tid] = BLOCK_COMPLETED;" + NL, " });" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -2; return; }" + NL, "" + NL, " clk_event_t marker_evt;" + NL, "" + NL, " enq_res = enqueue_marker(def_q, 2, mix_ev, &marker_evt);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -3; return; }" + NL, "" + NL, " retain_event(marker_evt);" + NL, " release_event(marker_evt);" + NL, "" + NL, " //check block is not started" + NL, " if(res[tid] == BLOCK_SUBMITTED)" + NL, " {" + NL, " clk_event_t my_evt;" + NL, " enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, 1, &marker_evt, &my_evt, " + NL, " ^{" + NL, " //check block is completed" + NL, " if(res[tid] == BLOCK_COMPLETED) res[tid] = CHECK_SUCCESS;" + NL, " });" + NL, " release_event(my_evt);" + NL, " }" + NL, "" + NL, " set_user_event_status(mix_ev[0], CL_COMPLETE);" + NL, "" + NL, " release_event(mix_ev[1]);" + NL, " release_event(marker_evt);" + NL, " release_event(mix_ev[0]);" + NL, "}" + NL +}; + +static const char* enqueue_block_with_mixed_events[] = +{ + NL, "kernel void enqueue_block_with_mixed_events(__global int* res)" + NL, "{" + NL, " int enq_res;" + NL, " size_t tid = get_global_id(0);" + NL, " clk_event_t mix_ev[3];" + NL, " mix_ev[0] = create_user_event();" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, " res[tid] = -2;" + NL, "" + NL, " enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, 1, &mix_ev[0], &mix_ev[1], ^{ res[tid]++; });" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "" + NL, " enq_res = enqueue_marker(def_q, 1, &mix_ev[1], &mix_ev[2]);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -3; return; }" + NL, "" + NL, " enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, sizeof(mix_ev)/sizeof(mix_ev[0]), mix_ev, NULL, ^{ res[tid]++; });" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -4; return; }" + NL, "" + NL, " set_user_event_status(mix_ev[0], CL_COMPLETE);" + NL, "" + NL, " release_event(mix_ev[0]);" + NL, " release_event(mix_ev[1]);" + NL, " release_event(mix_ev[2]);" + NL, "}" + NL +}; + +static const kernel_src sources_enqueue_block[] = +{ + KERNEL(enqueue_simple_block), + // Block with local mem + KERNEL(enqueue_block_with_local_arg1), + KERNEL(enqueue_block_with_local_arg2), + KERNEL(enqueue_block_with_wait_list), + KERNEL(enqueue_block_with_wait_list_and_local_arg), + // WG size built-ins + KERNEL(enqueue_block_get_kernel_work_group_size), + KERNEL(enqueue_block_get_kernel_preferred_work_group_size_multiple), + // Event profiling info + KERNEL(enqueue_block_capture_event_profiling_info_after_execution), + KERNEL(enqueue_block_capture_event_profiling_info_before_execution), + // Marker + KERNEL(enqueue_marker_with_block_event), + KERNEL(enqueue_marker_with_user_event), + // Mixed events + KERNEL(enqueue_marker_with_mixed_events), + KERNEL(enqueue_block_with_mixed_events), + // Barrier + KERNEL(enqueue_block_with_barrier), + +}; +static const size_t num_kernels_enqueue_block = arr_size(sources_enqueue_block); + +static int check_kernel_results(cl_int* results, cl_int len) +{ + for(cl_int i = 0; i < len; ++i) + { + if(results[i] != 0) return i; + } + return -1; +} + +int test_enqueue_block(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_uint i; + cl_int n, err_ret, res = 0; + clCommandQueueWrapper dev_queue; + cl_int kernel_results[MAX_GWS] = {0}; + + size_t ret_len; + cl_uint max_queues = 1; + cl_uint maxQueueSize = 0; + err_ret = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, sizeof(maxQueueSize), &maxQueueSize, 0); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE) failed"); + + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_ON_DEVICE_QUEUES, sizeof(max_queues), &max_queues, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_ON_DEVICE_QUEUES) failed"); + + size_t max_local_size = 1; + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(max_local_size), &max_local_size, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_WORK_GROUP_SIZE) failed"); + + cl_queue_properties queue_prop_def[] = + { + CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE|CL_QUEUE_ON_DEVICE|CL_QUEUE_ON_DEVICE_DEFAULT|CL_QUEUE_PROFILING_ENABLE, + CL_QUEUE_SIZE, maxQueueSize, + 0 + }; + + dev_queue = clCreateCommandQueueWithProperties(context, device, queue_prop_def, &err_ret); + test_error(err_ret, "clCreateCommandQueueWithProperties(CL_QUEUE_DEVICE|CL_QUEUE_DEFAULT) failed"); + + size_t global_size = MAX_GWS; + size_t local_size = (max_local_size > global_size/16) ? global_size/16 : max_local_size; + if(gWimpyMode) + { + global_size = 4; + local_size = 2; + } + + size_t failCnt = 0; + for(i = 0; i < num_kernels_enqueue_block; ++i) + { + if (!gKernelName.empty() && gKernelName != sources_enqueue_block[i].kernel_name) + continue; + + log_info("Running '%s' kernel (%d of %d) ...\n", sources_enqueue_block[i].kernel_name, i + 1, num_kernels_enqueue_block); + err_ret = run_n_kernel_args(context, queue, sources_enqueue_block[i].lines, sources_enqueue_block[i].num_lines, sources_enqueue_block[i].kernel_name, local_size, global_size, kernel_results, sizeof(kernel_results), 0, NULL); + if(check_error(err_ret, "'%s' kernel execution failed", sources_enqueue_block[i].kernel_name)) { ++failCnt; res = -1; } + else if((n = check_kernel_results(kernel_results, arr_size(kernel_results))) >= 0 && check_error(-1, "'%s' kernel results validation failed: [%d] returned %d expected 0", sources_enqueue_block[i].kernel_name, n, kernel_results[n])) res = -1; + else log_info("'%s' kernel is OK.\n", sources_enqueue_block[i].kernel_name); + } + + if (failCnt > 0) + { + log_error("ERROR: %d of %d kernels failed.\n", failCnt, num_kernels_enqueue_block); + } + + return res; +} + + + +#endif + + diff --git a/test_conformance/device_execution/enqueue_flags.cpp b/test_conformance/device_execution/enqueue_flags.cpp new file mode 100644 index 00000000..d3858c66 --- /dev/null +++ b/test_conformance/device_execution/enqueue_flags.cpp @@ -0,0 +1,756 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" + +#include + +#include "procs.h" +#include "utils.h" +#include + + +#ifdef CL_VERSION_2_0 +extern int gWimpyMode; +#define BITS_DEPTH 28 + +static const char* enqueue_flags_wait_kernel_simple[] = +{ + NL, "#define BITS_DEPTH " STRINGIFY_VALUE(BITS_DEPTH) + NL, "" + NL, "void block_fn(__global int* array, int index, size_t ls, size_t gs, __global int* res)" + NL, "{" + NL, " int val = 0;" + NL, " size_t lid = get_local_id(0);" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " array[index * gs + tid] = array[(index - 1) * gs + tid] + 1;" + NL, "" + NL, " if(tid == 0)" + NL, " {" + NL, " if((index + 1) < BITS_DEPTH)" + NL, " {" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange_1D(gs, ls), " + NL, " ^{" + NL, " block_fn(array, index + 1, ls, gs, res);" + NL, " });" + NL, " }" + NL, " }" + NL, "" + NL, " if((index + 1) == BITS_DEPTH)" + NL, " {" + NL, " barrier(CLK_LOCAL_MEM_FENCE);" + NL, "" + NL, " if(lid == 0)" + NL, " {" + NL, " size_t gid = get_group_id(0);" + NL, " res[gid] = 1;" + NL, "" + NL, " for(int j = 0; j < BITS_DEPTH; j++)" + NL, " {" + NL, " for(int i = 0; i < ls; i++)" + NL, " {" + NL, " if(array[j * gs + ls * gid + i] != ((ls * gid + i) + j))" + NL, " {" + NL, " res[gid] = 2;" + NL, " break;" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_flags_wait_kernel_simple(__global int* res, __global int* array)" + NL, "{" + NL, " size_t ls = get_local_size(0);" + NL, " size_t gs = get_global_size(0);" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " res[tid] = 0;" + NL, " array[tid] = tid;" + NL, "" + NL, " if(tid == 0)" + NL, " {" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange_1D(gs, ls), " + NL, " ^{" + NL, " block_fn(array, 1, ls, gs, res);" + NL, " });" + NL, " }" + NL, "}" + NL +}; + +static const char* enqueue_flags_wait_kernel_event[] = +{ + NL, "#define BITS_DEPTH " STRINGIFY_VALUE(BITS_DEPTH) + NL, "" + NL, "void block_fn(__global int* array, int index, size_t ls, size_t gs, __global int* res)" + NL, "{" + NL, " int val = 0;" + NL, " size_t lid = get_local_id(0);" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " array[index * gs + tid] = array[(index - 1) * gs + tid] + 1;" + NL, "" + NL, " if(tid == 0)" + NL, " {" + NL, " if((index + 1) < BITS_DEPTH)" + NL, " {" + NL, " clk_event_t block_evt;" + NL, " clk_event_t user_evt = create_user_event();" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange_1D(gs, ls), 1, &user_evt, &block_evt, " + NL, " ^{" + NL, " block_fn(array, index + 1, ls, gs, res);" + NL, " });" + NL, " set_user_event_status(user_evt, CL_COMPLETE);" + NL, " release_event(user_evt);" + NL, " release_event(block_evt);" + NL, " }" + NL, " }" + NL, "" + NL, " if((index + 1) == BITS_DEPTH)" + NL, " {" + NL, " barrier(CLK_LOCAL_MEM_FENCE);" + NL, "" + NL, " if(lid == 0)" + NL, " {" + NL, " size_t gid = get_group_id(0);" + NL, " res[gid] = 1;" + NL, "" + NL, " for(int j = 0; j < BITS_DEPTH; j++)" + NL, " {" + NL, " for(int i = 0; i < ls; i++)" + NL, " {" + NL, " if(array[j * gs + ls * gid + i] != ((ls * gid + i) + j))" + NL, " {" + NL, " res[gid] = 2;" + NL, " break;" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_flags_wait_kernel_event(__global int* res, __global int* array)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " size_t gs = get_global_size(0);" + NL, " size_t ls = get_local_size(0);" + NL, "" + NL, " res[tid] = 0;" + NL, " array[tid] = tid;" + NL, "" + NL, " if(tid == 0)" + NL, " {" + NL, " clk_event_t block_evt;" + NL, " clk_event_t user_evt = create_user_event();" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange_1D(gs, ls), 1, &user_evt, &block_evt, " + NL, " ^{" + NL, " block_fn(array, 1, ls, gs, res);" + NL, " });" + NL, " set_user_event_status(user_evt, CL_COMPLETE);" + NL, " release_event(user_evt);" + NL, " release_event(block_evt);" + NL, " }" + NL, "}" + NL +}; + +static const char* enqueue_flags_wait_kernel_local[] = +{ + NL, "#define BITS_DEPTH " STRINGIFY_VALUE(BITS_DEPTH) + NL, "" + NL, "void block_fn(__global int* array, int index, size_t ls, size_t gs, __global int* res, __local int* sub_array)" + NL, "{" + NL, " int val = 0;" + NL, " size_t gid = get_group_id(0);" + NL, " size_t lid = get_local_id(0);" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " sub_array[lid] = array[(index - 1) * gs + tid];" + NL, " barrier(CLK_LOCAL_MEM_FENCE);" + NL, "" + NL, " for(int i = 0; i < ls; i++)" + NL, " {" + NL, " int id = gid * ls + i;" + NL, " val += sub_array[i];" + NL, " val -= (tid == id)? 0: (id + index - 1);" + NL, " }" + NL, " array[index * gs + tid] = val + 1;" + NL, "" + NL, " if(tid == 0)" + NL, " {" + NL, " if((index + 1) < BITS_DEPTH)" + NL, " {" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange_1D(gs, ls), " + NL, " ^(__local void* sub_array){" + NL, " block_fn(array, index + 1, ls, gs, res, sub_array);" + NL, " }, ls * sizeof(int));" + NL, " }" + NL, " }" + NL, "" + NL, " if((index + 1) == BITS_DEPTH)" + NL, " {" + NL, " barrier(CLK_LOCAL_MEM_FENCE);" + NL, "" + NL, " if(lid == 0)" + NL, " {" + NL, " res[gid] = 1;" + NL, "" + NL, " for(int j = 0; j < BITS_DEPTH; j++)" + NL, " {" + NL, " for(int i = 0; i < ls; i++)" + NL, " {" + NL, " if(array[j * gs + ls * gid + i] != ((ls * gid + i) + j))" + NL, " {" + NL, " res[gid] = 2;" + NL, " break;" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_flags_wait_kernel_local(__global int* res, __global int* array)" + NL, "{" + NL, " size_t ls = get_local_size(0);" + NL, " size_t gs = get_global_size(0);" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " res[tid] = 0;" + NL, " array[tid] = tid;" + NL, "" + NL, " if(tid == 0)" + NL, " {" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange_1D(gs, ls), " + NL, " ^(__local void* sub_array){" + NL, " block_fn(array, 1, ls, gs, res, sub_array);" + NL, " }, ls * sizeof(int));" + NL, " }" + NL, "}" + NL +}; + +static const char* enqueue_flags_wait_kernel_event_local[] = +{ + NL, "#define BITS_DEPTH " STRINGIFY_VALUE(BITS_DEPTH) + NL, "" + NL, "void block_fn(__global int* array, int index, size_t ls, size_t gs, __global int* res, __local int* sub_array)" + NL, "{" + NL, " int val = 0;" + NL, " size_t gid = get_group_id(0);" + NL, " size_t lid = get_local_id(0);" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " sub_array[lid] = array[(index - 1) * gs + tid];" + NL, " barrier(CLK_LOCAL_MEM_FENCE);" + NL, "" + NL, " for(int i = 0; i < ls; i++)" + NL, " {" + NL, " int id = gid * ls + i;" + NL, " val += sub_array[i];" + NL, " val -= (tid == id)? 0: (id + index - 1);" + NL, " }" + NL, " array[index * gs + tid] = val + 1;" + NL, "" + NL, " if(tid == 0)" + NL, " {" + NL, " if((index + 1) < BITS_DEPTH)" + NL, " {" + NL, " clk_event_t block_evt;" + NL, " clk_event_t user_evt = create_user_event();" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange_1D(gs, ls), 1, &user_evt, &block_evt, " + NL, " ^(__local void* sub_array){" + NL, " block_fn(array, index + 1, ls, gs, res, sub_array);" + NL, " }, ls * sizeof(int));" + NL, " set_user_event_status(user_evt, CL_COMPLETE);" + NL, " release_event(user_evt);" + NL, " release_event(block_evt);" + NL, " }" + NL, " }" + NL, "" + NL, " if((index + 1) == BITS_DEPTH)" + NL, " {" + NL, " barrier(CLK_LOCAL_MEM_FENCE);" + NL, "" + NL, " if(lid == 0)" + NL, " {" + NL, " res[gid] = 1;" + NL, "" + NL, " for(int j = 0; j < BITS_DEPTH; j++)" + NL, " {" + NL, " for(int i = 0; i < ls; i++)" + NL, " {" + NL, " if(array[j * gs + ls * gid + i] != ((ls * gid + i) + j))" + NL, " {" + NL, " res[gid] = 2;" + NL, " break;" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_flags_wait_kernel_event_local(__global int* res, __global int* array)" + NL, "{" + NL, " size_t ls = get_local_size(0);" + NL, " size_t gs = get_global_size(0);" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " res[tid] = 0;" + NL, " array[tid] = tid;" + NL, "" + NL, " if(tid == 0)" + NL, " {" + NL, " clk_event_t block_evt;" + NL, " clk_event_t user_evt = create_user_event();" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange_1D(gs, ls), 1, &user_evt, &block_evt, " + NL, " ^(__local void* sub_array){" + NL, " block_fn(array, 1, ls, gs, res, sub_array);" + NL, " }, ls * sizeof(int));" + NL, " set_user_event_status(user_evt, CL_COMPLETE);" + NL, " release_event(user_evt);" + NL, " release_event(block_evt);" + NL, " }" + NL, "}" + NL +}; + +static const char* enqueue_flags_wait_work_group_simple[] = +{ + NL, "#define BITS_DEPTH " STRINGIFY_VALUE(BITS_DEPTH) + NL, "" + NL, "void block_fn(__global int* array, int index, size_t ls, __global int* res, int group_id)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " size_t lid = get_local_id(0);" + NL, " size_t gs = get_global_size(0);" + NL, " size_t gid = get_group_id(0);" + NL, " " + NL, " if(gid == group_id)" + NL, " {" + NL, " array[index * gs + tid] = array[(index - 1) * gs + tid] + 1;" + NL, " " + NL, " if((index + 1) < BITS_DEPTH && lid == 0)" + NL, " {" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP, ndrange_1D(gs, ls), " + NL, " ^{" + NL, " block_fn(array, index + 1, ls, res, gid);" + NL, " });" + NL, " }" + NL, " }" + NL, "" + NL, " if((index + 1) == BITS_DEPTH)" + NL, " {" + NL, " barrier(CLK_LOCAL_MEM_FENCE);" + NL, "" + NL, " if(lid == 0)" + NL, " {" + NL, " res[gid] = 1;" + NL, "" + NL, " for(int j = 0; j < BITS_DEPTH; j++)" + NL, " {" + NL, " for(int i = 0; i < ls; i++)" + NL, " {" + NL, " if(array[j * gs + ls * gid + i] != ((ls * gid + i) + j))" + NL, " {" + NL, " res[gid] = 2;" + NL, " break;" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_flags_wait_work_group_simple(__global int* res, __global int* array)" + NL, "{" + NL, " size_t ls = get_local_size(0);" + NL, " size_t gs = get_global_size(0);" + NL, " size_t tid = get_global_id(0);" + NL, " size_t gid = get_group_id(0);" + NL, " size_t lid = get_local_id(0);" + NL, "" + NL, " res[tid] = 0;" + NL, " array[tid] = tid;" + NL, "" + NL, " if(lid == 0)" + NL, " {" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP, ndrange_1D(gs, ls), " + NL, " ^{" + NL, " block_fn(array, 1, ls, res, gid);" + NL, " });" + NL, " }" + NL, "}" + NL +}; + +static const char* enqueue_flags_wait_work_group_event[] = +{ + NL, "#define BITS_DEPTH " STRINGIFY_VALUE(BITS_DEPTH) + NL, "" + NL, "void block_fn(__global int* array, int index, size_t ls, __global int* res, int group_id)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " size_t lid = get_local_id(0);" + NL, " size_t gs = get_global_size(0);" + NL, " size_t gid = get_group_id(0);" + NL, " " + NL, " if(gid == group_id)" + NL, " {" + NL, " array[index * gs + tid] = array[(index - 1) * gs + tid] + 1;" + NL, " " + NL, " if((index + 1) < BITS_DEPTH && lid == 0)" + NL, " {" + NL, " clk_event_t block_evt;" + NL, " clk_event_t user_evt = create_user_event();" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP, ndrange_1D(gs, ls), 1, &user_evt, &block_evt, " + NL, " ^{" + NL, " block_fn(array, index + 1, ls, res, gid);" + NL, " });" + NL, " set_user_event_status(user_evt, CL_COMPLETE);" + NL, " release_event(user_evt);" + NL, " release_event(block_evt);" + NL, " }" + NL, " }" + NL, "" + NL, "" + NL, " if((index + 1) == BITS_DEPTH)" + NL, " {" + NL, " barrier(CLK_LOCAL_MEM_FENCE);" + NL, "" + NL, " if(lid == 0)" + NL, " {" + NL, " res[gid] = 1;" + NL, "" + NL, " for(int j = 0; j < BITS_DEPTH; j++)" + NL, " {" + NL, " for(int i = 0; i < ls; i++)" + NL, " {" + NL, " if(array[j * gs + ls * gid + i] != ((ls * gid + i) + j))" + NL, " {" + NL, " res[gid] = 2;" + NL, " break;" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_flags_wait_work_group_event(__global int* res, __global int* array)" + NL, "{" + NL, " size_t ls = get_local_size(0);" + NL, " size_t gs = get_global_size(0);" + NL, " size_t tid = get_global_id(0);" + NL, " size_t gid = get_group_id(0);" + NL, " size_t lid = get_local_id(0);" + NL, "" + NL, " res[tid] = 0;" + NL, " array[tid] = tid;" + NL, "" + NL, " if(lid == 0)" + NL, " {" + NL, " clk_event_t block_evt;" + NL, " clk_event_t user_evt = create_user_event();" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP, ndrange_1D(gs, ls), 1, &user_evt, &block_evt, " + NL, " ^{" + NL, " block_fn(array, 1, ls, res, gid);" + NL, " });" + NL, " set_user_event_status(user_evt, CL_COMPLETE);" + NL, " release_event(user_evt);" + NL, " release_event(block_evt);" + NL, " }" + NL, "}" + NL +}; + +static const char* enqueue_flags_wait_work_group_local[] = +{ + NL, "#define BITS_DEPTH " STRINGIFY_VALUE(BITS_DEPTH) + NL, "" + NL, "void block_fn(__global int* array, int index, size_t ls, __global int* res, __local int* sub_array, int group_id)" + NL, "{" + NL, " int val = 0;" + NL, " size_t gid = get_group_id(0);" + NL, " size_t lid = get_local_id(0);" + NL, " size_t tid = get_global_id(0);" + NL, " size_t gs = get_global_size(0);" + NL, "" + NL, " sub_array[lid] = array[(index - 1) * gs + tid];" + NL, " barrier(CLK_LOCAL_MEM_FENCE);" + NL, "" + NL, " for(int i = 0; i < ls; i++)" + NL, " {" + NL, " int id = gid * ls + i;" + NL, " val += sub_array[i];" + NL, " val -= (tid == id)? 0: (id + index - 1);" + NL, " }" + NL, " " + NL, " if(gid == group_id)" + NL, " {" + NL, " array[index * gs + tid] = val + 1;" + NL, " " + NL, " if((index + 1) < BITS_DEPTH && lid == 0)" + NL, " {" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP, ndrange_1D(gs, ls), " + NL, " ^(__local void* sub_array){" + NL, " block_fn(array, index + 1, ls, res, sub_array, gid);" + NL, " }, ls * sizeof(int));" + NL, " }" + NL, " }" + NL, "" + NL, "" + NL, " if((index + 1) == BITS_DEPTH)" + NL, " {" + NL, " barrier(CLK_LOCAL_MEM_FENCE);" + NL, "" + NL, " if(lid == 0)" + NL, " {" + NL, " res[gid] = 1;" + NL, "" + NL, " for(int j = 0; j < BITS_DEPTH; j++)" + NL, " {" + NL, " for(int i = 0; i < ls; i++)" + NL, " {" + NL, " if(array[j * gs + ls * gid + i] != ((ls * gid + i) + j))" + NL, " {" + NL, " res[gid] = 2;" + NL, " break;" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_flags_wait_work_group_local(__global int* res, __global int* array)" + NL, "{" + NL, " size_t ls = get_local_size(0);" + NL, " size_t gs = get_global_size(0);" + NL, " size_t tid = get_global_id(0);" + NL, " size_t gid = get_group_id(0);" + NL, " size_t lid = get_local_id(0);" + NL, "" + NL, " res[tid] = 0;" + NL, " array[tid] = tid;" + NL, "" + NL, " if(lid == 0)" + NL, " {" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP, ndrange_1D(gs, ls), " + NL, " ^(__local void* sub_array){" + NL, " block_fn(array, 1, ls, res, sub_array, gid);" + NL, " }, ls * sizeof(int));" + NL, " }" + NL, "}" + NL +}; + +static const char* enqueue_flags_wait_work_group_event_local[] = +{ + NL, "#define BITS_DEPTH " STRINGIFY_VALUE(BITS_DEPTH) + NL, "" + NL, "void block_fn(__global int* array, int index, size_t ls, __global int* res, __local int* sub_array, int group_id)" + NL, "{" + NL, " int val = 0;" + NL, " size_t gid = get_group_id(0);" + NL, " size_t lid = get_local_id(0);" + NL, " size_t tid = get_global_id(0);" + NL, " size_t gs = get_global_size(0);" + NL, "" + NL, " sub_array[lid] = array[(index - 1) * gs + tid];" + NL, " barrier(CLK_LOCAL_MEM_FENCE);" + NL, "" + NL, " for(int i = 0; i < ls; i++)" + NL, " {" + NL, " int id = gid * ls + i;" + NL, " val += sub_array[i];" + NL, " val -= (tid == id)? 0: (id + index - 1);" + NL, " }" + NL, "" + NL, " if(gid == group_id)" + NL, " {" + NL, " array[index * gs + tid] = val + 1;" + NL, " " + NL, " if((index + 1) < BITS_DEPTH && lid == 0)" + NL, " {" + NL, " clk_event_t block_evt;" + NL, " clk_event_t user_evt = create_user_event();" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP, ndrange_1D(gs, ls), 1, &user_evt, &block_evt, " + NL, " ^(__local void* sub_array){" + NL, " block_fn(array, index + 1, ls, res, sub_array, gid);" + NL, " }, ls * sizeof(int));" + NL, " set_user_event_status(user_evt, CL_COMPLETE);" + NL, " release_event(user_evt);" + NL, " release_event(block_evt);" + NL, " }" + NL, " }" + NL, "" + NL, " if((index + 1) == BITS_DEPTH)" + NL, " {" + NL, " barrier(CLK_LOCAL_MEM_FENCE);" + NL, "" + NL, " if(lid == 0)" + NL, " {" + NL, " res[gid] = 1;" + NL, "" + NL, " for(int j = 0; j < BITS_DEPTH; j++)" + NL, " {" + NL, " for(int i = 0; i < ls; i++)" + NL, " {" + NL, " if(array[j * gs + ls * gid + i] != ((ls * gid + i) + j))" + NL, " {" + NL, " res[gid] = 2;" + NL, " break;" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_flags_wait_work_group_event_local(__global int* res, __global int* array)" + NL, "{" + NL, " size_t ls = get_local_size(0);" + NL, " size_t gs = get_global_size(0);" + NL, " size_t tid = get_global_id(0);" + NL, " size_t gid = get_group_id(0);" + NL, " size_t lid = get_local_id(0);" + NL, "" + NL, " res[tid] = 0;" + NL, " array[tid] = tid;" + NL, "" + NL, " if(lid == 0)" + NL, " {" + NL, " clk_event_t block_evt;" + NL, " clk_event_t user_evt = create_user_event();" + NL, " enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP, ndrange_1D(gs, ls), 1, &user_evt, &block_evt, " + NL, " ^(__local void* sub_array){" + NL, " block_fn(array, 1, ls, res, sub_array, gid);" + NL, " }, ls * sizeof(int));" + NL, " set_user_event_status(user_evt, CL_COMPLETE);" + NL, " release_event(user_evt);" + NL, " release_event(block_evt);" + NL, " }" + NL, "}" + NL +}; + +static const kernel_src sources_enqueue_block_flags[] = +{ + KERNEL(enqueue_flags_wait_kernel_simple), + KERNEL(enqueue_flags_wait_kernel_event), + KERNEL(enqueue_flags_wait_kernel_local), + KERNEL(enqueue_flags_wait_kernel_event_local), + KERNEL(enqueue_flags_wait_work_group_simple), + KERNEL(enqueue_flags_wait_work_group_event), + KERNEL(enqueue_flags_wait_work_group_local), + KERNEL(enqueue_flags_wait_work_group_event_local) +}; +static const size_t num_enqueue_block_flags = arr_size(sources_enqueue_block_flags); + + +int test_enqueue_flags(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_uint i; + cl_int err_ret, res = 0; + clCommandQueueWrapper dev_queue; + cl_int kernel_results[MAX_GWS] = { -1 }; + int buff[MAX_GWS * BITS_DEPTH] = { 0 }; + + size_t ret_len; + size_t max_local_size = 1; + cl_uint maxQueueSize = 0; + err_ret = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, sizeof(maxQueueSize), &maxQueueSize, 0); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE) failed"); + + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(max_local_size), &max_local_size, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_WORK_GROUP_SIZE) failed"); + + cl_queue_properties queue_prop_def[] = + { + CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE|CL_QUEUE_ON_DEVICE|CL_QUEUE_ON_DEVICE_DEFAULT, + CL_QUEUE_SIZE, maxQueueSize, + 0 + }; + + dev_queue = clCreateCommandQueueWithProperties(context, device, queue_prop_def, &err_ret); + test_error(err_ret, "clCreateCommandQueueWithProperties(CL_QUEUE_DEVICE|CL_QUEUE_DEFAULT) failed"); + + size_t global_size = MAX_GWS; + size_t local_size = (max_local_size > global_size/16) ? global_size/16 : max_local_size; + if(gWimpyMode) + { + global_size = 4; + local_size = 2; + } + + size_t failCnt = 0; + for(i = 0; i < num_enqueue_block_flags; ++i) + { + if (!gKernelName.empty() && gKernelName != sources_enqueue_block_flags[i].kernel_name) + continue; + + log_info("Running '%s' kernel (%d of %d) ...\n", sources_enqueue_block_flags[i].kernel_name, i + 1, num_enqueue_block_flags); + + clMemWrapper mem = clCreateBuffer(context, CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR, global_size * BITS_DEPTH * sizeof(cl_int), buff, &err_ret); + test_error(err_ret, "clCreateBuffer() failed"); + + kernel_arg args[] = + { + { sizeof(cl_mem), &mem } + }; + + err_ret = run_n_kernel_args(context, queue, sources_enqueue_block_flags[i].lines, sources_enqueue_block_flags[i].num_lines, sources_enqueue_block_flags[i].kernel_name, local_size, global_size, kernel_results, sizeof(kernel_results), arr_size(args), args); + if(check_error(err_ret, "'%s' kernel execution failed", sources_enqueue_block_flags[i].kernel_name)) { ++failCnt; res = -1; } + else + { + int r = 0; + for (int j=0; j= (global_size / local_size) && check_error(-1, "'%s' kernel result[idx: %d] validation failed (test) %d != (expected) 0", sources_enqueue_block_flags[i].kernel_name, j, kernel_results[j])) + { + r = -1; + break; + } + } + if(r == 0) log_info("'%s' kernel is OK.\n", sources_enqueue_block_flags[i].kernel_name); + else res = -1; + } + } + + if (failCnt > 0) + { + log_error("ERROR: %d of %d kernels failed.\n", failCnt, num_enqueue_block_flags); + } + + return res; +} + + + +#endif diff --git a/test_conformance/device_execution/enqueue_multi_queue.cpp b/test_conformance/device_execution/enqueue_multi_queue.cpp new file mode 100644 index 00000000..76d69168 --- /dev/null +++ b/test_conformance/device_execution/enqueue_multi_queue.cpp @@ -0,0 +1,198 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" + +#include + +#include "procs.h" +#include "utils.h" +#include + + + + +#ifdef CL_VERSION_2_0 +extern int gWimpyMode; +static const char enqueue_block_multi_queue[] = + NL "#define BLOCK_COMPLETED 0" + NL "#define BLOCK_SUBMITTED 1" + NL "" + NL "kernel void enqueue_block_multi_queue(__global int* res, __global int* buff %s)" + NL "{" + NL " uint i, n = %d;" + NL " clk_event_t block_evt[%d];" + NL " queue_t q[] = { %s };" + NL " queue_t *queue = q;" + NL "" + NL " clk_event_t user_evt = create_user_event();" + NL " queue_t def_q = get_default_queue();" + NL " size_t tid = get_global_id(0);" + NL " res[tid] = -1;" + NL " __global int* b = buff + tid*n;" + NL " for(i=0; i 1) + { + n = (max_queues > MAX_QUEUES) ? MAX_QUEUES : max_queues-1; + clMemWrapper mem, buff, evt; + std::vector queues(n); + std::vector q(n); + cl_queue_properties queue_prop[] = + { + CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE|CL_QUEUE_ON_DEVICE, + CL_QUEUE_SIZE, maxQueueSize, + 0 + }; + + for(i = 0; i < n; ++i) + { + queues[i] = clCreateCommandQueueWithProperties(context, device, queue_prop, &err_ret); + test_error(err_ret, "clCreateCommandQueueWithProperties(CL_QUEUE_DEVICE) failed"); + q[i] = queues[i]; + } + + size_t global_size = MAX_GWS; + size_t local_size = (max_local_size > global_size/16) ? global_size/16 : max_local_size; + if(gWimpyMode) + { + global_size = 4; + local_size = 2; + } + + evt = clCreateBuffer(context, CL_MEM_READ_WRITE, n * sizeof(cl_event), NULL, &err_ret); + test_error(err_ret, "clCreateBuffer() failed"); + + mem = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, n * sizeof(cl_command_queue), &q[0], &err_ret); + test_error(err_ret, "clCreateBuffer() failed"); + + buff = clCreateBuffer(context, CL_MEM_READ_WRITE, global_size * n * sizeof(cl_int), NULL, &err_ret); + test_error(err_ret, "clCreateBuffer() failed"); + + // Prepare CL source + char cl[65536] = { 0 }; + char q_args[16384] = { 0 }; + char q_list[8192] = { 0 }; + + kernel_arg arg_res = { sizeof(cl_mem), &buff }; + + std::vector args(n+1); + args[0] = arg_res; + + for(i = 0; i < n; ++i) + { + snprintf(q_args+strlen(q_args), sizeof(q_args)-strlen(q_args)-1, ", queue_t q%d", i); + snprintf(q_list+strlen(q_list), sizeof(q_list)-strlen(q_list)-1, "q%d, ", i); + kernel_arg arg_q = { sizeof(cl_command_queue), &q[i] }; + args[i+1] = arg_q; + } + + snprintf(cl, sizeof(cl)-1, enqueue_block_multi_queue, q_args, n, n, q_list); + const char *source = cl; + + err_ret = run_n_kernel_args(context, queue, &source, 1, "enqueue_block_multi_queue", local_size, global_size, kernel_results, sizeof(kernel_results), args.size(), &args[0]); + if(check_error(err_ret, "'%s' kernel execution failed", "enqueue_block_multi_queue")) res = -1; + else if((k = check_kernel_results(kernel_results, arr_size(kernel_results))) >= 0 && check_error(-1, "'%s' kernel results validation failed: [%d] returned %d expected 0", "enqueue_block_multi_queue", k, kernel_results[k])) res = -1; + else log_info("'%s' kernel is OK.\n", "enqueue_block_multi_queue"); + } + return res; +} + + + +#endif + + diff --git a/test_conformance/device_execution/enqueue_ndrange.cpp b/test_conformance/device_execution/enqueue_ndrange.cpp new file mode 100644 index 00000000..0055b618 --- /dev/null +++ b/test_conformance/device_execution/enqueue_ndrange.cpp @@ -0,0 +1,681 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" + +#include + +#include "procs.h" +#include "utils.h" +#include + + +#ifdef CL_VERSION_2_0 +extern int gWimpyMode; +static const char* helper_ndrange_1d_glo[] = +{ + NL, "void block_fn(int len, __global atomic_uint* val)" + NL, "{" + NL, " atomic_fetch_add_explicit(&val[get_global_linear_id() % len], 1, memory_order_relaxed, memory_scope_device);" + NL, "}" + NL, "" + NL, "kernel void helper_ndrange_1d_glo(__global int* res, uint n, uint len, __global uint* glob_size_arr, __global uint* loc_size_arr, __global atomic_uint* val, __global uint* ofs_arr)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " void (^kernelBlock)(void) = ^{ block_fn(len, val); };" + NL, "" + NL, " for(int i = 0; i < n; i++)" + NL, " {" + NL, " ndrange_t ndrange = ndrange_1D(glob_size_arr[i]);" + NL, " int enq_res = enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, " }" + NL, "}" + NL +}; + +static const char* helper_ndrange_1d_loc[] = +{ + NL, "void block_fn(int len, __global atomic_uint* val)" + NL, "{" + NL, " atomic_fetch_add_explicit(&val[get_global_linear_id() % len], 1, memory_order_relaxed, memory_scope_device);" + NL, "}" + NL, "" + NL, "kernel void helper_ndrange_1d_loc(__global int* res, uint n, uint len, __global uint* glob_size_arr, __global uint* loc_size_arr, __global atomic_uint* val, __global uint* ofs_arr)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " void (^kernelBlock)(void) = ^{ block_fn(len, val); };" + NL, "" + NL, " for(int k = 0; k < n; k++)" + NL, " {" + NL, " for(int i = 0; i < n; i++)" + NL, " {" + NL, " if (glob_size_arr[i] >= loc_size_arr[k])" + NL, " {" + NL, " ndrange_t ndrange = ndrange_1D(glob_size_arr[i], loc_size_arr[k]);" + NL, " int enq_res = enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, " }" + NL, " }" + NL, " }" + NL, "}" + NL +}; + +static const char* helper_ndrange_1d_ofs[] = +{ + NL, "void block_fn(int len, __global atomic_uint* val)" + NL, "{" + NL, " atomic_fetch_add_explicit(&val[(get_global_offset(0) + get_global_linear_id()) % len], 1, memory_order_relaxed, memory_scope_device);" + NL, "}" + NL, "" + NL, "kernel void helper_ndrange_1d_ofs(__global int* res, uint n, uint len, __global uint* glob_size_arr, __global uint* loc_size_arr, __global atomic_uint* val, __global uint* ofs_arr)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " void (^kernelBlock)(void) = ^{ block_fn(len, val); };" + NL, "" + NL, " for(int l = 0; l < n; l++)" + NL, " {" + NL, " for(int k = 0; k < n; k++)" + NL, " {" + NL, " for(int i = 0; i < n; i++)" + NL, " {" + NL, " if (glob_size_arr[i] >= loc_size_arr[k])" + NL, " {" + NL, " ndrange_t ndrange = ndrange_1D(ofs_arr[l], glob_size_arr[i], loc_size_arr[k]);" + NL, " int enq_res = enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, "}" + NL +}; + +static const char* helper_ndrange_2d_glo[] = +{ + NL, "void block_fn(int len, __global atomic_uint* val)" + NL, "{" + NL, " atomic_fetch_add_explicit(&val[get_global_linear_id() % len], 1, memory_order_relaxed, memory_scope_device);" + NL, "}" + NL, "" + NL, "kernel void helper_ndrange_2d_glo(__global int* res, uint n, uint len, __global uint* glob_size_arr, __global uint* loc_size_arr, __global int* val, __global uint* ofs_arr)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " void (^kernelBlock)(void) = ^{ block_fn(len, val); };" + NL, "" + NL, " for(int i = 0; i < n; i++)" + NL, " {" + NL, " size_t glob_size[2] = { glob_size_arr[i], glob_size_arr[(i + 1) % n] };" + NL, " ndrange_t ndrange = ndrange_2D(glob_size);" + NL, " int enq_res = enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, " }" + NL, "}" + NL +}; + +static const char* helper_ndrange_2d_loc[] = +{ + NL, "void block_fn(int len, __global atomic_uint* val)" + NL, "{" + NL, " atomic_fetch_add_explicit(&val[get_global_linear_id() % len], 1, memory_order_relaxed, memory_scope_device);" + NL, "}" + NL, "" + NL, "kernel void helper_ndrange_2d_loc(__global int* res, uint n, uint len, __global uint* glob_size_arr, __global uint* loc_size_arr, __global int* val, __global uint* ofs_arr)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " void (^kernelBlock)(void) = ^{ block_fn(len, val); };" + NL, "" + NL, " for(int k = 0; k < n; k++)" + NL, " {" + NL, " for(int i = 0; i < n; i++)" + NL, " {" + NL, " if (glob_size_arr[(i + 1) % n] >= loc_size_arr[k])" + NL, " {" + NL, " size_t glob_size[] = { glob_size_arr[i], glob_size_arr[(i + 1) % n] };" + NL, " size_t loc_size[] = { 1, loc_size_arr[k] };" + NL, "" + NL, " ndrange_t ndrange = ndrange_2D(glob_size, loc_size);" + NL, " int enq_res = enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, " }" + NL, " }" + NL, " }" + NL, "}" + NL +}; + + +static const char* helper_ndrange_2d_ofs[] = +{ + NL, "void block_fn(int len, __global atomic_uint* val)" + NL, "{" + NL, " atomic_fetch_add_explicit(&val[(get_global_offset(1) * get_global_size(0) + get_global_offset(0) + get_global_linear_id()) % len], 1, memory_order_relaxed, memory_scope_device);" + NL, "}" + NL, "" + NL, "kernel void helper_ndrange_2d_ofs(__global int* res, uint n, uint len, __global uint* glob_size_arr, __global uint* loc_size_arr, __global int* val, __global uint* ofs_arr)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " void (^kernelBlock)(void) = ^{ block_fn(len, val); };" + NL, "" + NL, " for(int l = 0; l < n; l++)" + NL, " {" + NL, " for(int k = 0; k < n; k++)" + NL, " {" + NL, " for(int i = 0; i < n; i++)" + NL, " {" + NL, " if (glob_size_arr[(i + 1) % n] >= loc_size_arr[k])" + NL, " {" + NL, " size_t glob_size[] = { glob_size_arr[i], glob_size_arr[(i + 1) % n]};" + NL, " size_t loc_size[] = { 1, loc_size_arr[k] };" + NL, " size_t ofs[] = { ofs_arr[l], ofs_arr[(l + 1) % n] };" + NL, "" + NL, " ndrange_t ndrange = ndrange_2D(ofs,glob_size,loc_size);" + NL, " int enq_res = enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, "}" + NL +}; + + +static const char* helper_ndrange_3d_glo[] = +{ + NL, "void block_fn(int len, __global atomic_uint* val)" + NL, "{" + NL, " atomic_fetch_add_explicit(&val[get_global_linear_id() % len], 1, memory_order_relaxed, memory_scope_device);" + NL, "}" + NL, "" + NL, "kernel void helper_ndrange_3d_glo(__global int* res, uint n, uint len, __global uint* glob_size_arr, __global uint* loc_size_arr, __global int* val, __global uint* ofs_arr)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " void (^kernelBlock)(void) = ^{ block_fn(len, val); };" + NL, "" + NL, " for(int i = 0; i < n; i++)" + NL, " {" + NL, " uint global_work_size = glob_size_arr[i] * glob_size_arr[(i + 1) % n] * glob_size_arr[(i + 2) % n];" + NL, " if (global_work_size <= (len * len))" + NL, " {" + NL, " size_t glob_size[3] = { glob_size_arr[i], glob_size_arr[(i + 1) % n], glob_size_arr[(i + 2) % n] };" + NL, " ndrange_t ndrange = ndrange_3D(glob_size);" + NL, " int enq_res = enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, " }" + NL, " }" + NL, "}" + NL +}; + + +static const char* helper_ndrange_3d_loc[] = +{ + NL, "void block_fn(int len, __global atomic_uint* val)" + NL, "{" + NL, " atomic_fetch_add_explicit(&val[get_global_linear_id() % len], 1, memory_order_relaxed, memory_scope_device);" + NL, "}" + NL, "" + NL, "kernel void helper_ndrange_3d_loc(__global int* res, uint n, uint len, __global uint* glob_size_arr, __global uint* loc_size_arr, __global int* val, __global uint* ofs_arr)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " void (^kernelBlock)(void) = ^{ block_fn(len, val); };" + NL, "" + NL, " for(int k = 0; k < n; k++)" + NL, " {" + NL, " for(int i = 0; i < n; i++)" + NL, " {" + NL, " uint global_work_size = glob_size_arr[i] * glob_size_arr[(i + 1) % n] * glob_size_arr[(i + 2) % n];" + NL, " if (glob_size_arr[(i + 2) % n] >= loc_size_arr[k] && global_work_size <= (len * len))" + NL, " {" + NL, " size_t glob_size[] = { glob_size_arr[i], glob_size_arr[(i + 1) % n], glob_size_arr[(i + 2) % n] };" + NL, " size_t loc_size[] = { 1, 1, loc_size_arr[k] };" + NL, " ndrange_t ndrange = ndrange_3D(glob_size,loc_size);" + NL, " int enq_res = enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " " + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, " }" + NL, " }" + NL, " }" + NL, "}" + NL +}; + +static const char* helper_ndrange_3d_ofs[] = +{ + NL, "void block_fn(int len, __global atomic_uint* val)" + NL, "{" + NL, " atomic_fetch_add_explicit(&val[(get_global_offset(2) * get_global_size(0) * get_global_size(1) + get_global_offset(1) * get_global_size(0) + get_global_offset(0) + get_global_linear_id()) % len], 1, memory_order_relaxed, memory_scope_device);" + NL, "}" + NL, "" + NL, "kernel void helper_ndrange_3d_ofs(__global int* res, uint n, uint len, __global uint* glob_size_arr, __global uint* loc_size_arr, __global int* val, __global uint* ofs_arr)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " void (^kernelBlock)(void) = ^{ block_fn(len, val); };" + NL, "" + NL, " for(int l = 0; l < n; l++)" + NL, " {" + NL, " for(int k = 0; k < n; k++)" + NL, " {" + NL, " for(int i = 0; i < n; i++)" + NL, " {" + NL, " uint global_work_size = glob_size_arr[i] * glob_size_arr[(i + 1) % n] * glob_size_arr[(i + 2) % n];" + NL, " if (glob_size_arr[(i + 2) % n] >= loc_size_arr[k] && global_work_size <= (len * len))" + NL, " {" + NL, " size_t glob_size[3] = { glob_size_arr[i], glob_size_arr[(i + 1) % n], glob_size_arr[(i + 2) % n]};" + NL, " size_t loc_size[3] = { 1, 1, loc_size_arr[k] };" + NL, " size_t ofs[3] = { ofs_arr[l], ofs_arr[(l + 1) % n], ofs_arr[(l + 2) % n] };" + NL, " ndrange_t ndrange = ndrange_3D(ofs,glob_size,loc_size);" + NL, " int enq_res = enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, " }" + NL, " }" + NL, " }" + NL, " }" + NL, "}" + NL +}; + +static const kernel_src_dim_check sources_ndrange_Xd[] = +{ + { KERNEL(helper_ndrange_1d_glo), 1, CL_FALSE, CL_FALSE}, + { KERNEL(helper_ndrange_1d_loc), 1, CL_TRUE, CL_FALSE}, + { KERNEL(helper_ndrange_1d_ofs), 1, CL_TRUE, CL_TRUE}, + { KERNEL(helper_ndrange_2d_glo), 2, CL_FALSE, CL_FALSE}, + { KERNEL(helper_ndrange_2d_loc), 2, CL_TRUE, CL_FALSE}, + { KERNEL(helper_ndrange_2d_ofs), 2, CL_TRUE, CL_TRUE}, + { KERNEL(helper_ndrange_3d_glo), 3, CL_FALSE, CL_FALSE}, + { KERNEL(helper_ndrange_3d_loc), 3, CL_TRUE, CL_FALSE}, + { KERNEL(helper_ndrange_3d_ofs), 3, CL_TRUE, CL_TRUE}, +}; +static const size_t num_kernels_ndrange_Xd = arr_size(sources_ndrange_Xd); + +static int check_kernel_results(cl_int* results, cl_int len) +{ + for(cl_int i = 0; i < len; ++i) + { + if(results[i] != 0) return i; + } + return -1; +} + +void generate_reference_1D(std::vector &reference_results, std::vector &glob_size_arr) +{ + for (size_t g = 0; g < glob_size_arr.size(); ++g) + { + for (size_t w = 0; w < glob_size_arr[g]; ++w) + { + ++reference_results[w]; + } + } +} + +void generate_reference_1D_local(std::vector &reference_results, std::vector &glob_size_arr, std::vector &loc_size_arr) +{ + for (size_t g = 0; g < glob_size_arr.size(); ++g) + { + for (size_t l = 0; l < loc_size_arr.size(); ++l) + { + if (glob_size_arr[g] >= loc_size_arr[l]) + { + for (size_t w = 0; w < glob_size_arr[g]; ++w) + { + ++reference_results[w]; + } + } + } + } +} + +void generate_reference_1D_offset(std::vector &reference_results, std::vector &glob_size_arr, std::vector &loc_size_arr, std::vector &offset, cl_uint len) +{ + for (size_t g = 0; g < glob_size_arr.size(); ++g) + { + for (size_t l = 0; l < loc_size_arr.size(); ++l) + { + if (glob_size_arr[g] >= loc_size_arr[l]) + { + for (size_t o = 0; o < offset.size(); ++o) + { + for (size_t w = 0; w < glob_size_arr[g]; ++w) + { + ++reference_results[(offset[o] + w) % len]; + } + } + } + } + } +} + +void generate_reference_2D(std::vector &reference_results, std::vector &glob_size_arr, cl_uint len) +{ + for (size_t g = 0; g < glob_size_arr.size(); ++g) + { + for (size_t h = 0; h < glob_size_arr[(g + 1) % glob_size_arr.size()]; ++h) + { + for (size_t w = 0; w < glob_size_arr[g]; ++w) + { + ++reference_results[(h * glob_size_arr[g] + w) % len]; + } + } + } +} + +void generate_reference_2D_local(std::vector &reference_results, std::vector &glob_size_arr, std::vector &loc_size_arr, cl_uint len) +{ + size_t n = glob_size_arr.size(); + for (size_t g = 0; g < glob_size_arr.size(); ++g) + { + for (size_t l = 0; l < loc_size_arr.size(); ++l) + { + if (glob_size_arr[(g + 1) % n] >= loc_size_arr[l]) + { + for (size_t h = 0; h < glob_size_arr[(g + 1) % n]; ++h) + { + for (size_t w = 0; w < glob_size_arr[g]; ++w) + { + ++reference_results[(h * glob_size_arr[g] + w) % len]; + } + } + } + } + } +} + +void generate_reference_2D_offset(std::vector &reference_results, std::vector &glob_size_arr, std::vector &loc_size_arr, std::vector &offset, cl_uint len) +{ + size_t n = glob_size_arr.size(); + for (size_t g = 0; g < glob_size_arr.size(); ++g) + { + for (size_t l = 0; l < loc_size_arr.size(); ++l) + { + if (glob_size_arr[(g + 1) % n] >= loc_size_arr[l]) + { + for (size_t o = 0; o < offset.size(); ++o) + { + for (size_t h = 0; h < glob_size_arr[(g + 1) % n]; ++h) + { + for (size_t w = 0; w < glob_size_arr[g]; ++w) + { + ++reference_results[(glob_size_arr[g] * offset[(o + 1) % n] + offset[o] + h * glob_size_arr[g] + w) % len]; + } + } + } + } + } + } +} + +void generate_reference_3D(std::vector &reference_results, std::vector &glob_size_arr, cl_uint len) +{ + size_t n = glob_size_arr.size(); + for (size_t g = 0; g < glob_size_arr.size(); ++g) + { + size_t global_work_size = glob_size_arr[(g + 2) % n] * glob_size_arr[(g + 1) % n] * glob_size_arr[g]; + if(global_work_size <= (len * len)) + { + for (size_t d = 0; d < glob_size_arr[(g + 2) % n]; ++d) + { + for (size_t h = 0; h < glob_size_arr[(g + 1) % n]; ++h) + { + for (size_t w = 0; w < glob_size_arr[g]; ++w) + { + ++reference_results[(d * glob_size_arr[(g + 1) % n] * glob_size_arr[g] + h * glob_size_arr[g] + w) % len]; + } + } + } + } + } +} + +void generate_reference_3D_local(std::vector &reference_results, std::vector &glob_size_arr, std::vector &loc_size_arr, cl_uint len) +{ + size_t n = glob_size_arr.size(); + for (size_t g = 0; g < glob_size_arr.size(); ++g) + { + for (size_t l = 0; l < loc_size_arr.size(); ++l) + { + size_t global_work_size = glob_size_arr[(g + 2) % n] * glob_size_arr[(g + 1) % n] * glob_size_arr[g]; + if (glob_size_arr[(g + 2) % n] >= loc_size_arr[l] && global_work_size <= (len * len)) + { + for (size_t d = 0; d < glob_size_arr[(g + 2) % n]; ++d) + { + for (size_t h = 0; h < glob_size_arr[(g + 1) % n]; ++h) + { + for (size_t w = 0; w < glob_size_arr[g]; ++w) + { + ++reference_results[(d * glob_size_arr[(g + 1) % n] * glob_size_arr[g] + h * glob_size_arr[g] + w) % len]; + } + } + } + } + } + } +} + +void generate_reference_3D_offset(std::vector &reference_results, std::vector &glob_size_arr, std::vector &loc_size_arr, std::vector &offset, cl_uint len) +{ + size_t n = glob_size_arr.size(); + for (size_t g = 0; g < glob_size_arr.size(); ++g) + { + for (size_t l = 0; l < loc_size_arr.size(); ++l) + { + size_t global_work_size = glob_size_arr[(g + 2) % n] * glob_size_arr[(g + 1) % n] * glob_size_arr[g]; + if (glob_size_arr[(g + 2) % n] >= loc_size_arr[l] && global_work_size <= (len * len)) + { + for (size_t o = 0; o < offset.size(); ++o) + { + for (size_t d = 0; d < glob_size_arr[(g + 2) % n]; ++d) + { + for (size_t h = 0; h < glob_size_arr[(g + 1) % n]; ++h) + { + for (size_t w = 0; w < glob_size_arr[g]; ++w) + { + ++reference_results[(glob_size_arr[g] * glob_size_arr[(g + 1) % n] * offset[(o + 2) % n] + glob_size_arr[g] * offset[(o + 1) % n] + offset[o] + d * glob_size_arr[(g + 1) % n] * glob_size_arr[g] + h * glob_size_arr[g] + w) % len]; + } + } + } + } + } + } + } +} + +static int check_kernel_results(cl_int* results, cl_int len, std::vector &glob_size_arr, std::vector &loc_size_arr, std::vector &offset, cl_int dim, cl_bool use_local, cl_bool use_offset) +{ + std::vector reference_results(len, 0); + switch (dim) + { + case 1: + if (use_local == CL_FALSE) + { + generate_reference_1D(reference_results, glob_size_arr); + } + else if(use_local == CL_TRUE && use_offset == CL_FALSE) + { + generate_reference_1D_local(reference_results, glob_size_arr, loc_size_arr); + } + else + { + generate_reference_1D_offset(reference_results, glob_size_arr, loc_size_arr, offset, len); + } + break; + case 2: + if (use_local == CL_FALSE) + { + generate_reference_2D(reference_results, glob_size_arr, len); + } + else if (use_local == CL_TRUE && use_offset == CL_FALSE) + { + generate_reference_2D_local(reference_results, glob_size_arr, loc_size_arr, len); + } + else + { + generate_reference_2D_offset(reference_results, glob_size_arr, loc_size_arr, offset, len); + } + break; + case 3: + if (use_local == CL_FALSE) + { + generate_reference_3D(reference_results, glob_size_arr, len); + } + else if (use_local == CL_TRUE && use_offset == CL_FALSE) + { + generate_reference_3D_local(reference_results, glob_size_arr, loc_size_arr, len); + } + else + { + generate_reference_3D_offset(reference_results, glob_size_arr, loc_size_arr, offset, len); + } + break; + default: + return 0; + break; + } + + for (cl_int i = 0; i < len; ++i) + { + if (results[i] != reference_results[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d\n", results[i], reference_results[i]); + return i; + } + } + + return -1; +} + +int test_enqueue_ndrange(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + MTdata d; + cl_uint i; + cl_int err_ret, res = 0; + clCommandQueueWrapper dev_queue; + cl_int k, kernel_results[MAX_GWS] = { 0 }; + + size_t ret_len; + cl_uint max_queues = 1; + cl_uint maxQueueSize = 0; + + d = init_genrand(gRandomSeed); + + err_ret = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, sizeof(maxQueueSize), &maxQueueSize, 0); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE) failed"); + + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_ON_DEVICE_QUEUES, sizeof(max_queues), &max_queues, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_ON_DEVICE_QUEUES) failed"); + + size_t max_local_size = 1; + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(max_local_size), &max_local_size, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_WORK_GROUP_SIZE) failed"); + + cl_queue_properties queue_prop_def[] = + { + CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE|CL_QUEUE_ON_DEVICE|CL_QUEUE_ON_DEVICE_DEFAULT, + CL_QUEUE_SIZE, maxQueueSize, + 0 + }; + + dev_queue = clCreateCommandQueueWithProperties(context, device, queue_prop_def, &err_ret); + test_error(err_ret, "clCreateCommandQueueWithProperties(CL_QUEUE_DEVICE|CL_QUEUE_DEFAULT) failed"); + + max_local_size = (max_local_size > MAX_GWS)? MAX_GWS: max_local_size; + if(gWimpyMode) + { + max_local_size = MIN(8, max_local_size); + } + + cl_uint num = 10; + cl_uint global_work_size = max_local_size * 2; + std::vector glob_size_arr(num); + std::vector loc_size_arr(num); + std::vector ofs_arr(num); + std::vector glob_results(global_work_size, 0); + + glob_size_arr[0] = 1; + glob_size_arr[1] = global_work_size; + loc_size_arr[0] = 1; + loc_size_arr[1] = max_local_size; + ofs_arr[0] = 0; + ofs_arr[1] = 1; + + for(i = 2; i < num; ++i) + { + glob_size_arr[i] = genrand_int32(d) % global_work_size; + glob_size_arr[i] = glob_size_arr[i] ? glob_size_arr[i]: 1; + loc_size_arr[i] = genrand_int32(d) % max_local_size; + loc_size_arr[i] = loc_size_arr[i] ? loc_size_arr[i]: 1; + ofs_arr[i] = genrand_int32(d) % global_work_size; + } + + // check ndrange_dX functions + size_t failCnt = 0; + for(i = 0; i < num_kernels_ndrange_Xd; ++i) + { + if (!gKernelName.empty() && gKernelName != sources_ndrange_Xd[i].src.kernel_name) + continue; + + clMemWrapper mem1 = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, glob_size_arr.size() * sizeof(cl_uint), &glob_size_arr[0], &err_ret); + test_error(err_ret, "clCreateBuffer() failed"); + clMemWrapper mem2 = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, loc_size_arr.size() * sizeof(cl_uint), &loc_size_arr[0], &err_ret); + test_error(err_ret, "clCreateBuffer() failed"); + clMemWrapper mem3 = clCreateBuffer(context, CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR, glob_results.size() * sizeof(cl_int), &glob_results[0], &err_ret); + test_error(err_ret, "clCreateBuffer() failed"); + clMemWrapper mem4 = clCreateBuffer(context, CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR, ofs_arr.size() * sizeof(cl_uint), &ofs_arr[0], &err_ret); + test_error(err_ret, "clCreateBuffer() failed"); + + kernel_arg args[] = + { + { sizeof(cl_uint), &num }, + { sizeof(cl_uint), &global_work_size }, + { sizeof(cl_mem), &mem1 }, + { sizeof(cl_mem), &mem2 }, + { sizeof(cl_mem), &mem3 }, + { sizeof(cl_mem), &mem4 }, + }; + + log_info("Running '%s' kernel (%d of %d) ...\n", sources_ndrange_Xd[i].src.kernel_name, i + 1, num_kernels_ndrange_Xd); + err_ret = run_single_kernel_args(context, queue, sources_ndrange_Xd[i].src.lines, sources_ndrange_Xd[i].src.num_lines, sources_ndrange_Xd[i].src.kernel_name, kernel_results, sizeof(kernel_results), arr_size(args), args); + + cl_int *ptr = (cl_int *)clEnqueueMapBuffer(queue, mem3, CL_TRUE, CL_MAP_READ, 0, glob_results.size() * sizeof(cl_int), 0, 0, 0, &err_ret); + test_error(err_ret, "clEnqueueMapBuffer() failed"); + + if(check_error(err_ret, "'%s' kernel execution failed", sources_ndrange_Xd[i].src.kernel_name)) { ++failCnt; res = -1; } + else if((k = check_kernel_results(kernel_results, arr_size(kernel_results))) >= 0 && check_error(-1, "'%s' kernel results validation failed: [%d] returned %d expected 0", sources_ndrange_Xd[i].src.kernel_name, k, kernel_results[k])) res = -1; + else if((k = check_kernel_results(ptr, global_work_size, glob_size_arr, loc_size_arr, ofs_arr, sources_ndrange_Xd[i].dim, sources_ndrange_Xd[i].localSize, sources_ndrange_Xd[i].offset)) >= 0 && check_error(-1, "'%s' global kernel results validation failed: [%d] returned %d expected 0", sources_ndrange_Xd[i].src.kernel_name, k, glob_results[k])) res = -1; + else log_info("'%s' kernel is OK.\n", sources_ndrange_Xd[i].src.kernel_name); + + err_ret = clEnqueueUnmapMemObject(queue, mem3, ptr, 0, 0, 0); + test_error(err_ret, "clEnqueueUnmapMemObject() failed"); + + } + + if (failCnt > 0) + { + log_error("ERROR: %d of %d kernels failed.\n", failCnt, num_kernels_ndrange_Xd); + } + + return res; +} + + +#endif + diff --git a/test_conformance/device_execution/enqueue_wg_size.cpp b/test_conformance/device_execution/enqueue_wg_size.cpp new file mode 100644 index 00000000..e1da04ce --- /dev/null +++ b/test_conformance/device_execution/enqueue_wg_size.cpp @@ -0,0 +1,1724 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" + +#include + +#include "procs.h" +#include "utils.h" +#include + + +#ifdef CL_VERSION_2_0 +extern int gWimpyMode; +static int nestingLevel = 3; + +static const char* enqueue_1D_wg_size_single[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " queue_t def_q = get_default_queue();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " const size_t gs = 64 * 64 * 64;" + NL, " size_t ls = rnd[tidX % maxGlobalWorkSize] % wg % gs;" + NL, " ls = ls? ls: 1;" + NL, "" + NL, " ndrange_t ndrange = ndrange_1D(gs, ls);" + NL, "" + NL, " // Only 1 work-item enqueues block" + NL, " if(tidX == 0)" + NL, " {" + NL, " atomic_inc(&res[tidX % maxGlobalWorkSize]);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tidX % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_1D_wg_size_single(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +static int check_single(cl_int* results, cl_int len, cl_int nesting_level) +{ + for(size_t i = 0; i < len; ++i) + { + if(i == 0 && results[i] != nestingLevel) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], nestingLevel, i); + return (int)i; + } + + if(i > 0 && results[i] != 0) + { + log_error("ERROR: Kernel returned %d vs. expected 0, index: %d\n", results[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_1D_wg_size_some_eq[] = +{ + NL, "void block_fn(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " queue_t def_q = get_default_queue();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(res, level, maxGlobalWorkSize, rnd); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " const size_t gs = 8 * 8 * 2;" + NL, " size_t ls = rnd[tidX % maxGlobalWorkSize] % wg % gs;" + NL, " ls = ls? ls: 1;" + NL, "" + NL, " ndrange_t ndrange = ndrange_1D(gs, ls);" + NL, "" + NL, " // Some work-items enqueues nested blocks with the same level" + NL, " if((tidX % (maxGlobalWorkSize / 8)) == 0)" + NL, " {" + NL, " atomic_inc(&res[tidX % maxGlobalWorkSize]);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tidX % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_1D_wg_size_some_eq(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(res, level, maxGlobalWorkSize, rnd);" + NL, "}" + NL +}; + +void generate_reference_results_some_eq_1D(std::vector &referenceResults, cl_int maxGlobalWorkSize, cl_int level) +{ + size_t globalSize = (level == nestingLevel) ? maxGlobalWorkSize: (8 * 8 * 2); + if(--level < 0) + { + return; + } + + for (size_t tidX = 0; tidX < globalSize; ++tidX) + { + if ((tidX % (maxGlobalWorkSize / 8)) == 0) + { + ++referenceResults[tidX % maxGlobalWorkSize]; + generate_reference_results_some_eq_1D(referenceResults, maxGlobalWorkSize, level); + } + } +} + +static int check_some_eq_1D(cl_int* results, cl_int len, cl_int nesting_level) +{ + std::vector referenceResults(len, 0); + generate_reference_results_some_eq_1D(referenceResults, len, nesting_level); + + for(size_t i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_1D_wg_size_some_diff[] = +{ + NL, "void block_fn(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " queue_t def_q = get_default_queue();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(res, level, maxGlobalWorkSize, rnd); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " const size_t gs = 8 * 8 * 8;" + NL, " size_t ls = rnd[tidX % maxGlobalWorkSize] % wg % gs;" + NL, " ls = ls? ls: 1;" + NL, "" + NL, " ndrange_t ndrange = ndrange_1D(gs, ls);" + NL, "" + NL, " // Some work-items enqueues nested blocks with different levels" + NL, " if((tidX % 2) == 0)" + NL, " {" + NL, " atomic_inc(&res[tidX % maxGlobalWorkSize]);" + NL, " if(level >= tidX)" + NL, " {" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tidX % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_1D_wg_size_some_diff(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(res, level, maxGlobalWorkSize, rnd);" + NL, "}" + NL +}; + +void generate_reference_results_some_diff_1D(std::vector &referenceResults, cl_int maxGlobalWorkSize, cl_int level) +{ + size_t globalSize = (level == nestingLevel) ? maxGlobalWorkSize: (8 * 8 * 8); + if(--level < 0) + { + return; + } + + for (size_t tidX = 0; tidX < globalSize; ++tidX) + { + if ((tidX % 2) == 0) + { + ++referenceResults[tidX % maxGlobalWorkSize]; + if (level >= tidX) + { + generate_reference_results_some_diff_1D(referenceResults, maxGlobalWorkSize, level); + } + } + } +} + +static int check_some_diff_1D(cl_int* results, cl_int maxGlobalWorkSize, cl_int nesting_level) +{ + std::vector referenceResults(maxGlobalWorkSize, 0); + generate_reference_results_some_diff_1D(referenceResults, maxGlobalWorkSize, nesting_level); + + for(size_t i = 0; i < maxGlobalWorkSize; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_1D_wg_size_all_eq[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " queue_t def_q = get_default_queue();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " const size_t gs = 8;" + NL, " size_t ls = rnd[tidX % maxGlobalWorkSize] % wg % gs;" + NL, " ls = ls? ls: 1;" + NL, "" + NL, " ndrange_t ndrange = ndrange_1D(gs, ls);" + NL, "" + NL, " // All work-items enqueues nested blocks with the same level" + NL, " atomic_inc(&res[tidX % maxGlobalWorkSize]);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tidX % maxGlobalWorkSize] = -1; return; }" + NL, "}" + NL, "" + NL, "kernel void enqueue_1D_wg_size_all_eq(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +void generate_reference_results_all_eq_1D(std::vector &referenceResults, cl_int len, cl_int level) +{ + size_t globalSize = (level == nestingLevel) ? len: 8; + if(--level < 0) + { + return; + } + + for (size_t tidX = 0; tidX < globalSize; ++tidX) + { + ++referenceResults[tidX % len]; + generate_reference_results_all_eq_1D(referenceResults, len, level); + } +} + +static int check_all_eq_1D(cl_int* results, cl_int len, cl_int nesting_level) +{ + std::vector referenceResults(len, 0); + generate_reference_results_all_eq_1D(referenceResults, len, nesting_level); + + for(size_t i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_1D_wg_size_all_diff[] = +{ + NL, "void block_fn(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " queue_t def_q = get_default_queue();" + NL, " if((--level) < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(res, level, maxGlobalWorkSize, rnd); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " const size_t gs = 8 * 8 * 8;" + NL, " size_t ls = rnd[tidX % maxGlobalWorkSize] % wg % gs;" + NL, " ls = ls? ls: 1;" + NL, "" + NL, " ndrange_t ndrange = ndrange_1D(gs, ls);" + NL, "" + NL, " // All work-items enqueues nested blocks with different levels" + NL, " atomic_inc(&res[tidX % maxGlobalWorkSize]);" + NL, " if(level >= tidX)" + NL, " {" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tidX % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_1D_wg_size_all_diff(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(res, level, maxGlobalWorkSize, rnd);" + NL, "}" + NL +}; + +void generate_reference_results_all_diff_1D(std::vector &referenceResults, cl_int len, cl_int level) +{ + size_t globalSize = (level == nestingLevel) ? len: (8 * 8 * 8); + if((--level) < 0) + { + return; + } + + for (size_t threadIdx = 0; threadIdx < globalSize; ++threadIdx) + { + ++referenceResults[threadIdx % len]; + if (level >= threadIdx) + { + generate_reference_results_all_diff_1D(referenceResults, len, level); + } + } +} + +static int check_all_diff_1D(cl_int* results, cl_int len, cl_int nesting_level) +{ + std::vector referenceResults(len, 0); + generate_reference_results_all_diff_1D(referenceResults, len, nesting_level); + + for(size_t i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_2D_wg_size_single[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " size_t tidY = get_global_id(1);" + NL, " size_t linearId = get_global_linear_id();" + NL, " queue_t def_q = get_default_queue();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " const size_t gs[] = { 64, 64 * 64 };" + NL, " size_t ls[] = { 1, rnd[tidY % maxGlobalWorkSize] % wg % gs[1] };" + NL, " ls[1] = ls[1]? ls[1]: 1;" + NL, " " + NL, " ndrange_t ndrange = ndrange_2D(gs, ls);" + NL, "" + NL, " // Only 1 work-item enqueues block" + NL, " if(tidX == 0 && tidY == 0)" + NL, " {" + NL, " atomic_inc(&res[linearId % maxGlobalWorkSize]);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[linearId % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_2D_wg_size_single(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +static const char* enqueue_2D_wg_size_some_eq[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " size_t tidY = get_global_id(1);" + NL, " size_t linearId = get_global_linear_id();" + NL, " queue_t def_q = get_default_queue();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " const size_t gs[] = { 4, 4 };" + NL, " size_t ls[] = { 1, rnd[tidY % maxGlobalWorkSize] % wg % gs[1] };" + NL, " ls[1] = ls[1]? ls[1]: 1;" + NL, " " + NL, " ndrange_t ndrange = ndrange_2D(gs, ls);" + NL, "" + NL, " // Some work-items enqueues nested blocks with the same level" + NL, " if((tidX < (get_global_size(0) >> 1)) && ((tidY < (get_global_size(1) >> 1)) || get_global_size(1) == 1))" + NL, " {" + NL, " atomic_inc(&res[linearId % maxGlobalWorkSize]);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[linearId % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_2D_wg_size_some_eq(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +void generate_reference_results_some_eq_2D(std::vector &referenceResults, cl_int len, cl_int level) +{ + size_t globalSizeX = (level == nestingLevel) ? len: 4; + size_t globalSizeY = (level == nestingLevel) ? 1: 4; + if(--level < 0) + { + return; + } + + for (size_t tidY = 0; tidY < globalSizeY; ++tidY) + { + for (size_t tidX = 0; tidX < globalSizeX; ++tidX) + { + if ((tidX < (globalSizeX >> 1)) && ((tidY < (globalSizeY >> 1)) || globalSizeY == 1)) + { + ++referenceResults[(globalSizeX * tidY + tidX) % len]; + generate_reference_results_some_eq_2D(referenceResults, len, level); + } + } + } +} + +static int check_some_eq_2D(cl_int* results, cl_int len, cl_int nesting_level) +{ + std::vector referenceResults(len, 0); + generate_reference_results_some_eq_2D(referenceResults, len, nesting_level); + + for(size_t i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_2D_wg_size_some_diff[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " size_t tidY = get_global_id(1);" + NL, " size_t linearId = get_global_linear_id();" + NL, " queue_t def_q = get_default_queue();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " const size_t gs[] = { 8, 8 };" + NL, " size_t ls[] = { 1, rnd[tidY % maxGlobalWorkSize] % wg % gs[1] };" + NL, " ls[1] = ls[1]? ls[1]: 1;" + NL, " " + NL, " ndrange_t ndrange = ndrange_2D(gs, ls);" + NL, "" + NL, " // Some work-items enqueues nested blocks with different levels" + NL, " if((tidX % 2) == 0 && (tidY % 2) == 0)" + NL, " {" + NL, " atomic_inc(&res[linearId % maxGlobalWorkSize]);" + NL, " if(level >= tidX && level >= tidY)" + NL, " {" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[linearId % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_2D_wg_size_some_diff(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +void generate_reference_results_some_diff_2D(std::vector &referenceResults, cl_int len, cl_int level) +{ + size_t globalSizeX = (level == nestingLevel) ? len: 8; + size_t globalSizeY = (level == nestingLevel) ? 1: 8; + if(--level < 0) + { + return; + } + + for (size_t tidY = 0; tidY < globalSizeY; ++tidY) + { + for (size_t tidX = 0; tidX < globalSizeX; ++tidX) + { + if ((tidX % 2) == 0 && (tidY % 2) == 0) + { + ++referenceResults[(globalSizeX * tidY + tidX) % len]; + if (level >= tidX && level >= tidY) + { + generate_reference_results_some_diff_2D(referenceResults, len, level); + } + } + } + } +} + +static int check_some_diff_2D(cl_int* results, cl_int len, cl_int nesting_level) +{ + std::vector referenceResults(len, 0); + generate_reference_results_some_diff_2D(referenceResults, len, nesting_level); + + for(size_t i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_2D_wg_size_all_eq[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " size_t tidY = get_global_id(1);" + NL, " size_t linearId = get_global_linear_id();" + NL, " queue_t def_q = get_default_queue();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " const size_t gs[] = { 2, 2 };" + NL, " size_t ls[] = { 1, rnd[tidY % maxGlobalWorkSize] % wg % gs[1] };" + NL, " ls[1] = ls[1]? ls[1]: 1;" + NL, " " + NL, " ndrange_t ndrange = ndrange_2D(gs, ls);" + NL, "" + NL, " // All work-items enqueues nested blocks with the same level" + NL, " atomic_inc(&res[linearId % maxGlobalWorkSize]);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[linearId % maxGlobalWorkSize] = -1; return; }" + NL, "}" + NL, "" + NL, "kernel void enqueue_2D_wg_size_all_eq(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +void generate_reference_results_all_eq_2D(std::vector &referenceResults, cl_int len, cl_int level) +{ + size_t globalSizeX = (level == nestingLevel) ? len: 2; + size_t globalSizeY = (level == nestingLevel) ? 1: 2; + if(--level < 0) + { + return; + } + + for (size_t tidY = 0; tidY < globalSizeY; ++tidY) + { + for (size_t tidX = 0; tidX < globalSizeX; ++tidX) + { + ++referenceResults[(globalSizeX * tidY + tidX) % len]; + generate_reference_results_all_eq_2D(referenceResults, len, level); + } + } +} + +static int check_all_eq_2D(cl_int* results, cl_int len, cl_int nesting_level) +{ + std::vector referenceResults(len, 0); + generate_reference_results_all_eq_2D(referenceResults, len, nesting_level); + + for(size_t i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_2D_wg_size_all_diff[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " size_t tidY = get_global_id(1);" + NL, " size_t linearId = get_global_linear_id();" + NL, " queue_t def_q = get_default_queue();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " size_t gs[] = { 8, 8 * 8 };" + NL, " size_t ls[] = { 1, rnd[tidY % maxGlobalWorkSize] % wg % gs[1] };" + NL, " ls[1] = ls[1]? ls[1]: 1;" + NL, " " + NL, " ndrange_t ndrange = ndrange_2D(gs, ls);" + NL, "" + NL, " // All work-items enqueues nested blocks with different levels" + NL, " atomic_inc(&res[linearId % maxGlobalWorkSize]);" + NL, " if(level >= tidX && level >= tidY)" + NL, " {" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[linearId % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_2D_wg_size_all_diff(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +void generate_reference_results_all_diff_2D(std::vector &referenceResults, cl_int len, cl_int level) +{ + size_t globalSizeX = (level == nestingLevel) ? len: 8; + size_t globalSizeY = (level == nestingLevel) ? 1: (8 * 8); + if(--level < 0) + { + return; + } + + for (size_t tidY = 0; tidY < globalSizeY; ++tidY) + { + for (size_t tidX = 0; tidX < globalSizeX; ++tidX) + { + ++referenceResults[(globalSizeX * tidY + tidX) % len]; + if (level >= tidX && level >= tidY) + { + generate_reference_results_all_diff_2D(referenceResults, len, level); + } + } + } +} + +static int check_all_diff_2D(cl_int* results, cl_int len, cl_int nesting_level) +{ + std::vector referenceResults(len, 0); + generate_reference_results_all_diff_2D(referenceResults, len, nesting_level); + + for(size_t i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_3D_wg_size_single[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " size_t tidY = get_global_id(1);" + NL, " size_t tidZ = get_global_id(2);" + NL, " size_t linearId = get_global_linear_id();" + NL, " queue_t def_q = get_default_queue();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " const size_t gs[] = { 64, 64, 64 };" + NL, " size_t ls[] = { 1, 1, rnd[tidZ % maxGlobalWorkSize] % wg % gs[2] };" + NL, " ls[2] = ls[2]? ls[2]: 1;" + NL, " " + NL, " ndrange_t ndrange = ndrange_3D(gs, ls);" + NL, "" + NL, " // Only 1 work-item enqueues block" + NL, " if(tidX == 0 && tidY == 0 && tidZ == 0)" + NL, " {" + NL, " atomic_inc(&res[linearId % maxGlobalWorkSize]);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[linearId % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_3D_wg_size_single(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +static const char* enqueue_3D_wg_size_some_eq[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " size_t tidY = get_global_id(1);" + NL, " size_t tidZ = get_global_id(2);" + NL, " size_t linearId = get_global_linear_id();" + NL, " queue_t def_q = get_default_queue();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " const size_t gs[] = { 4, 4, 4 };" + NL, " size_t ls[] = { 1, 1, rnd[tidZ % maxGlobalWorkSize] % wg % gs[2] };" + NL, " ls[2] = ls[2]? ls[2]: 1;" + NL, " " + NL, " ndrange_t ndrange = ndrange_3D(gs, ls);" + NL, "" + NL, " // Some work-items enqueues nested blocks with the same level" + NL, " if((tidX < (get_global_size(0) >> 1)) && " + NL, " ((tidY < (get_global_size(1) >> 1)) || get_global_size(1) == 1) &&" + NL, " ((tidZ < (get_global_size(2) >> 1)) || get_global_size(2) == 1))" + NL, " {" + NL, " atomic_inc(&res[linearId % maxGlobalWorkSize]);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[linearId % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_3D_wg_size_some_eq(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +void generate_reference_results_some_eq_3D(std::vector &referenceResults, cl_int len, cl_int level) +{ + size_t globalSizeX = (level == nestingLevel) ? len: 4; + size_t globalSizeY = (level == nestingLevel) ? 1: 4; + size_t globalSizeZ = (level == nestingLevel) ? 1: 4; + if(--level < 0) + { + return; + } + + for (size_t tidZ = 0; tidZ < globalSizeZ; ++tidZ) + { + for (size_t tidY = 0; tidY < globalSizeY; ++tidY) + { + for (size_t tidX = 0; tidX < globalSizeX; ++tidX) + { + if ((tidX < (globalSizeX >> 1)) && ((tidY < (globalSizeY >> 1)) || globalSizeY == 1) && ((tidZ < (globalSizeZ >> 1)) || globalSizeZ == 1)) + { + ++referenceResults[(globalSizeX * globalSizeY * tidZ + globalSizeX * tidY + tidX) % len]; + generate_reference_results_some_eq_3D(referenceResults, len, level); + } + } + } + } +} + +static int check_some_eq_3D(cl_int* results, cl_int len, cl_int nesting_level) +{ + std::vector referenceResults(len, 0); + generate_reference_results_some_eq_3D(referenceResults, len, nesting_level); + + for(size_t i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_3D_wg_size_some_diff[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " size_t tidY = get_global_id(1);" + NL, " size_t tidZ = get_global_id(2);" + NL, " size_t linearId = get_global_linear_id();" + NL, " queue_t def_q = get_default_queue();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " const size_t gs[] = { 8, 8, 8 };" + NL, " size_t ls[] = { 1, 1, rnd[tidZ % maxGlobalWorkSize] % wg % gs[2] };" + NL, " ls[2] = ls[2]? ls[2]: 1;" + NL, " " + NL, " ndrange_t ndrange = ndrange_3D(gs, ls);" + NL, "" + NL, " // Some work-items enqueues nested blocks with different levels" + NL, " if((tidX % 2) == 0 && (tidY % 2) == 0 && (tidZ % 2) == 0)" + NL, " {" + NL, " atomic_inc(&res[linearId % maxGlobalWorkSize]);" + NL, " if(level >= tidX && level >= tidY && level >= tidZ)" + NL, " {" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[linearId % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_3D_wg_size_some_diff(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +void generate_reference_results_some_diff_3D(std::vector &referenceResults, cl_int len, cl_int level) +{ + size_t globalSizeX = (level == nestingLevel) ? len: 8; + size_t globalSizeY = (level == nestingLevel) ? 1: 8; + size_t globalSizeZ = (level == nestingLevel) ? 1: 8; + if(--level < 0) + { + return; + } + + for (size_t tidZ = 0; tidZ < globalSizeZ; ++tidZ) + { + for (size_t tidY = 0; tidY < globalSizeY; ++tidY) + { + for (size_t tidX = 0; tidX < globalSizeX; ++tidX) + { + if ((tidX % 2) == 0 && (tidY % 2) == 0 && (tidZ % 2) == 0) + { + ++referenceResults[(globalSizeX * globalSizeY * tidZ + globalSizeX * tidY + tidX) % len]; + if (level >= tidX && level >= tidY && level >= tidZ) + { + generate_reference_results_some_diff_3D(referenceResults, len, level); + } + } + } + } + } +} + +static int check_some_diff_3D(cl_int* results, cl_int len, cl_int nesting_level) +{ + std::vector referenceResults(len, 0); + generate_reference_results_some_diff_3D(referenceResults, len, nesting_level); + + for(size_t i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_3D_wg_size_all_eq[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " size_t tidY = get_global_id(1);" + NL, " size_t tidZ = get_global_id(2);" + NL, " size_t linearId = get_global_linear_id();" + NL, " queue_t def_q = get_default_queue();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " const size_t gs[] = { 2, 2, 2 };" + NL, " size_t ls[] = { 1, 1, rnd[tidZ % maxGlobalWorkSize] % wg % gs[2] };" + NL, " ls[2] = ls[2]? ls[2]: 1;" + NL, " " + NL, " ndrange_t ndrange = ndrange_3D(gs, ls);" + NL, "" + NL, " // All work-items enqueues nested blocks with the same level" + NL, " atomic_inc(&res[linearId % maxGlobalWorkSize]);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[linearId % maxGlobalWorkSize] = -1; return; }" + NL, "}" + NL, "" + NL, "kernel void enqueue_3D_wg_size_all_eq(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +void generate_reference_results_all_eq_3D(std::vector &referenceResults, cl_int len, cl_int level) +{ + size_t globalSizeX = (level == nestingLevel) ? len: 2; + size_t globalSizeY = (level == nestingLevel) ? 1: 2; + size_t globalSizeZ = (level == nestingLevel) ? 1: 2; + if(--level < 0) + { + return; + } + + for (size_t tidZ = 0; tidZ < globalSizeZ; ++tidZ) + { + for (size_t tidY = 0; tidY < globalSizeY; ++tidY) + { + for (size_t tidX = 0; tidX < globalSizeX; ++tidX) + { + ++referenceResults[(globalSizeX * globalSizeY * tidZ + globalSizeX * tidY + tidX) % len]; + generate_reference_results_all_eq_3D(referenceResults, len, level); + } + } + } +} + +static int check_all_eq_3D(cl_int* results, cl_int len, cl_int nesting_level) +{ + std::vector referenceResults(len, 0); + generate_reference_results_all_eq_3D(referenceResults, len, nesting_level); + + for(size_t i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_3D_wg_size_all_diff[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " size_t tidY = get_global_id(1);" + NL, " size_t tidZ = get_global_id(2);" + NL, " size_t linearId = get_global_linear_id();" + NL, " queue_t def_q = get_default_queue();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " const size_t gs[] = { 8, 8, 8 };" + NL, " size_t ls[] = { 1, 1, rnd[tidZ % maxGlobalWorkSize] % wg % gs[2] };" + NL, " ls[2] = ls[2]? ls[2]: 1;" + NL, " " + NL, " ndrange_t ndrange = ndrange_3D(gs, ls);" + NL, "" + NL, " // All work-items enqueues nested blocks with different levels" + NL, " atomic_inc(&res[linearId % maxGlobalWorkSize]);" + NL, " if(level >= tidX && level >= tidY && level >= tidZ)" + NL, " {" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[linearId % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_3D_wg_size_all_diff(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +void generate_reference_results_all_diff_3D(std::vector &referenceResults, cl_int len, cl_int level) +{ + size_t globalSizeX = (level == nestingLevel) ? len: 8; + size_t globalSizeY = (level == nestingLevel) ? 1: 8; + size_t globalSizeZ = (level == nestingLevel) ? 1: 8; + if(--level < 0) + { + return; + } + + for (size_t tidZ = 0; tidZ < globalSizeZ; ++tidZ) + { + for (size_t tidY = 0; tidY < globalSizeY; ++tidY) + { + for (size_t tidX = 0; tidX < globalSizeX; ++tidX) + { + ++referenceResults[(globalSizeX * globalSizeY * tidZ + globalSizeX * tidY + tidX) % len]; + if (level >= tidX && level >= tidY && level >= tidZ) + { + generate_reference_results_all_diff_3D(referenceResults, len, level); + } + } + } + } +} + +static int check_all_diff_3D(cl_int* results, cl_int len, cl_int nesting_level) +{ + std::vector referenceResults(len, 0); + generate_reference_results_all_diff_3D(referenceResults, len, nesting_level); + + for(size_t i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_mix_wg_size_single[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " size_t tidX = get_global_id(0);" + NL, " size_t tidY = get_global_id(1);" + NL, " size_t tidZ = get_global_id(2);" + NL, " size_t linearId = get_global_linear_id();" + NL, " queue_t def_q = get_default_queue();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " ndrange_t ndrange;" + NL, " switch((linearId + level) % 3)" + NL, " {" + NL, " case 0:" + NL, " {" + NL, " const size_t gs = 64 * 64 * 64;" + NL, " size_t ls = rnd[tidX % maxGlobalWorkSize] % wg % gs;" + NL, " ls = ls? ls: 1;" + NL, " ndrange = ndrange_1D(gs, ls);" + NL, " }" + NL, " break;" + NL, " case 1:" + NL, " {" + NL, " const size_t gs[] = { 64, 64 * 64 };" + NL, " size_t ls[] = { 1, rnd[tidY % maxGlobalWorkSize] % wg % gs[1] };" + NL, " ls[1] = ls[1]? ls[1]: 1;" + NL, " ndrange = ndrange_2D(gs, ls);" + NL, " }" + NL, " break;" + NL, " case 2:" + NL, " {" + NL, " const size_t gs[] = { 64, 64, 64 };" + NL, " size_t ls[] = { 1, 1, rnd[tidZ % maxGlobalWorkSize] % wg % gs[2] };" + NL, " ls[2] = ls[2]? ls[2]: 1;" + NL, " ndrange = ndrange_3D(gs, ls);" + NL, " }" + NL, " break;" + NL, " default:" + NL, " break;" + NL, " }" + NL, "" + NL, " // Only 1 work-item enqueues block" + NL, " if(tidX == 0 && (tidY == 0 || get_global_size(1) == 1) && (tidZ == 0 || get_global_size(2) == 1))" + NL, " {" + NL, " atomic_inc(&res[linearId % maxGlobalWorkSize]);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[linearId % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_mix_wg_size_single(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +static const char* enqueue_mix_wg_size_some_eq[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " queue_t def_q = get_default_queue();" + NL, " size_t tidX = get_global_id(0);" + NL, " size_t tidY = get_global_id(1);" + NL, " size_t tidZ = get_global_id(2);" + NL, " size_t linearId = get_global_linear_id();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " ndrange_t ndrange;" + NL, " switch((linearId + level) % 3)" + NL, " {" + NL, " case 0:" + NL, " {" + NL, " const size_t gs = 2 * 4 * 4;" + NL, " size_t ls = rnd[tidX % maxGlobalWorkSize] % wg % gs;" + NL, " ls = ls? ls: 1;" + NL, " ndrange = ndrange_1D(gs, ls);" + NL, " }" + NL, " break;" + NL, " case 1:" + NL, " {" + NL, " const size_t gs[] = { 2, 4 * 4 };" + NL, " size_t ls[] = { 1, rnd[tidY % maxGlobalWorkSize] % wg % gs[1] };" + NL, " ls[1] = ls[1]? ls[1]: 1;" + NL, " ndrange = ndrange_2D(gs, ls);" + NL, " }" + NL, " break;" + NL, " case 2:" + NL, " {" + NL, " const size_t gs[] = { 2, 4, 4 };" + NL, " size_t ls[] = { 1, 1, rnd[tidZ % maxGlobalWorkSize] % wg % gs[2] };" + NL, " ls[2] = ls[2]? ls[2]: 1;" + NL, " ndrange = ndrange_3D(gs, ls);" + NL, " }" + NL, " break;" + NL, " default:" + NL, " break;" + NL, " }" + NL, "" + NL, " // Some work-items enqueues nested blocks with the same level" + NL, " size_t globalSizeX = get_global_size(0);" + NL, " size_t globalSizeY = get_global_size(1);" + NL, " size_t globalSizeZ = get_global_size(2);" + NL, " if((tidX < (globalSizeX >> 1)) && ((tidY < (globalSizeY >> 1)) || globalSizeY == 1) && ((tidZ < (globalSizeZ >> 1)) || globalSizeZ == 1))" + NL, " {" + NL, " atomic_inc(&res[linearId % maxGlobalWorkSize]);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[linearId % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_mix_wg_size_some_eq(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +void generate_reference_results_some_eq_mix(std::vector &referenceResults, cl_int len, cl_int level, cl_int dim) +{ + size_t globalSizeX = 1, globalSizeY = 1, globalSizeZ = 1; + switch (dim) + { + case 0: + globalSizeX = (level == nestingLevel) ? len: (2 * 4 * 4); + break; + case 1: + globalSizeX = 2; + globalSizeY = 4 * 4; + break; + case 2: + globalSizeX = 2; + globalSizeY = 4; + globalSizeZ = 4; + break; + default: + break; + } + + if(--level < 0) + { + return; + } + + for (size_t tidZ = 0; tidZ < globalSizeZ; ++tidZ) + { + for (size_t tidY = 0; tidY < globalSizeY; ++tidY) + { + for (size_t tidX = 0; tidX < globalSizeX; ++tidX) + { + size_t linearID = globalSizeX * globalSizeY * tidZ + globalSizeX * tidY + tidX; + cl_int nextDim = (linearID + level) % 3; + if ((tidX < (globalSizeX >> 1)) && ((tidY < (globalSizeY >> 1)) || globalSizeY == 1) && ((tidZ < (globalSizeZ >> 1)) || globalSizeZ == 1)) + { + ++referenceResults[linearID % len]; + generate_reference_results_some_eq_mix(referenceResults, len, level, nextDim); + } + } + } + } +} + +static int check_some_eq_mix(cl_int* results, cl_int len, cl_int nesting_level) +{ + std::vector referenceResults(len, 0); + generate_reference_results_some_eq_mix(referenceResults, len, nesting_level, 0); + + for(size_t i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_mix_wg_size_some_diff[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " queue_t def_q = get_default_queue();" + NL, " size_t tidX = get_global_id(0);" + NL, " size_t tidY = get_global_id(1);" + NL, " size_t tidZ = get_global_id(2);" + NL, " size_t linearId = get_global_linear_id();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " ndrange_t ndrange;" + NL, " switch((linearId + level) % 3)" + NL, " {" + NL, " case 0:" + NL, " {" + NL, " const size_t gs = 8 * 8 * 8;" + NL, " size_t ls = rnd[tidX % maxGlobalWorkSize] % wg % gs;" + NL, " ls = ls? ls: 1;" + NL, " ndrange = ndrange_1D(gs, ls);" + NL, " }" + NL, " break;" + NL, " case 1:" + NL, " {" + NL, " const size_t gs[] = { 8, 8 * 8 };" + NL, " size_t ls[] = { 1, rnd[tidY % maxGlobalWorkSize] % wg % gs[1] };" + NL, " ls[1] = ls[1]? ls[1]: 1;" + NL, " ndrange = ndrange_2D(gs, ls);" + NL, " }" + NL, " break;" + NL, " case 2:" + NL, " {" + NL, " const size_t gs[] = { 8, 8, 8 };" + NL, " size_t ls[] = { 1, 1, rnd[tidZ % maxGlobalWorkSize] % wg % gs[2] };" + NL, " ls[2] = ls[2]? ls[2]: 1;" + NL, " ndrange = ndrange_3D(gs, ls);" + NL, " }" + NL, " break;" + NL, " default:" + NL, " break;" + NL, " }" + NL, "" + NL, " // Some work-items enqueues nested blocks with different levels" + NL, " if((tidX % 2) == 0 && (tidY % 2) == 0 && (tidZ % 2) == 0)" + NL, " {" + NL, " atomic_inc(&res[linearId % maxGlobalWorkSize]);" + NL, " if(level >= tidX && level >= tidY && level >= tidZ)" + NL, " {" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[linearId % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_mix_wg_size_some_diff(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +void generate_reference_results_some_diff_mix(std::vector &referenceResults, cl_int len, cl_int level, cl_int dim) +{ + size_t globalSizeX = 1, globalSizeY = 1, globalSizeZ = 1; + switch (dim) + { + case 0: + globalSizeX = (level == nestingLevel) ? len: (8 * 8 * 8); + break; + case 1: + globalSizeX = 8; + globalSizeY = 8 * 8; + break; + case 2: + globalSizeX = 8; + globalSizeY = 8; + globalSizeZ = 8; + break; + default: + return; + break; + } + + if(--level < 0) + { + return; + } + + for (size_t tidZ = 0; tidZ < globalSizeZ; ++tidZ) + { + for (size_t tidY = 0; tidY < globalSizeY; ++tidY) + { + for (size_t tidX = 0; tidX < globalSizeX; ++tidX) + { + size_t linearID = globalSizeX * globalSizeY * tidZ + globalSizeX * tidY + tidX; + cl_int nextDim = (linearID + level) % 3; + if ((tidX % 2) == 0 && (tidY % 2) == 0 && (tidZ % 2) == 0) + { + ++referenceResults[linearID % len]; + if (level >= tidX && level >= tidY && level >= tidZ) + { + generate_reference_results_some_diff_mix(referenceResults, len, level, nextDim); + } + } + } + } + } +} + +static int check_some_diff_mix(cl_int* results, cl_int len, cl_int nesting_level) +{ + std::vector referenceResults(len, 0); + generate_reference_results_some_diff_mix(referenceResults, len, nesting_level, 0); + + for(size_t i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_mix_wg_size_all_eq[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " queue_t def_q = get_default_queue();" + NL, " size_t tidX = get_global_id(0);" + NL, " size_t tidY = get_global_id(1);" + NL, " size_t tidZ = get_global_id(2);" + NL, " size_t linearId = get_global_linear_id();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " ndrange_t ndrange;" + NL, " switch((linearId + level) % 3)" + NL, " {" + NL, " case 0:" + NL, " {" + NL, " const size_t gs = 2 * 2 * 2;" + NL, " size_t ls = rnd[tidX % maxGlobalWorkSize] % wg % gs;" + NL, " ls = ls? ls: 1;" + NL, " ndrange = ndrange_1D(gs, ls);" + NL, " }" + NL, " break;" + NL, " case 1:" + NL, " {" + NL, " const size_t gs[] = { 2, 2 * 2 };" + NL, " size_t ls[] = { 1, rnd[tidY % maxGlobalWorkSize] % wg % gs[1] };" + NL, " ls[1] = ls[1]? ls[1]: 1;" + NL, " ndrange = ndrange_2D(gs, ls);" + NL, " }" + NL, " break;" + NL, " case 2:" + NL, " {" + NL, " const size_t gs[] = { 2, 2, 2 };" + NL, " size_t ls[] = { 1, 1, rnd[tidZ % maxGlobalWorkSize] % wg % gs[2] };" + NL, " ls[2] = ls[2]? ls[2]: 1;" + NL, " ndrange = ndrange_3D(gs, ls);" + NL, " }" + NL, " break;" + NL, " default:" + NL, " break;" + NL, " }" + NL, "" + NL, " // All work-items enqueues nested blocks with the same level" + NL, " atomic_inc(&res[linearId % maxGlobalWorkSize]);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[linearId % maxGlobalWorkSize] = -1; return; }" + NL, "}" + NL, "" + NL, "kernel void enqueue_mix_wg_size_all_eq(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +void generate_reference_results_all_eq_mix(std::vector &referenceResults, cl_int len, cl_int level, cl_int dim) +{ + size_t globalSizeX = 1, globalSizeY = 1, globalSizeZ = 1; + switch (dim) + { + case 0: + globalSizeX = (level == nestingLevel) ? len: (2 * 2 * 2); + break; + case 1: + globalSizeX = 2; + globalSizeY = 2 * 2; + break; + case 2: + globalSizeX = 2; + globalSizeY = 2; + globalSizeZ = 2; + break; + default: + break; + } + + if(--level < 0) + { + return; + } + + for (size_t tidZ = 0; tidZ < globalSizeZ; ++tidZ) + { + for (size_t tidY = 0; tidY < globalSizeY; ++tidY) + { + for (size_t tidX = 0; tidX < globalSizeX; ++tidX) + { + size_t linearID = globalSizeX * globalSizeY * tidZ + globalSizeX * tidY + tidX; + cl_int nextDim = (linearID + level) % 3; + ++referenceResults[linearID % len]; + generate_reference_results_all_eq_mix(referenceResults, len, level, nextDim); + } + } + } +} + +static int check_all_eq_mix(cl_int* results, cl_int len, cl_int nesting_level) +{ + std::vector referenceResults(len, 0); + generate_reference_results_all_eq_mix(referenceResults, len, nesting_level, 0); + + for(size_t i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const char* enqueue_mix_wg_size_all_diff[] = +{ + NL, "void block_fn(int level, int maxGlobalWorkSize, __global int* rnd, __global int* res)" + NL, "{" + NL, " queue_t def_q = get_default_queue();" + NL, " size_t tidX = get_global_id(0);" + NL, " size_t tidY = get_global_id(1);" + NL, " size_t tidZ = get_global_id(2);" + NL, " size_t linearId = get_global_linear_id();" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, maxGlobalWorkSize, rnd, res); };" + NL, " uint wg = get_kernel_work_group_size(kernelBlock);" + NL, "" + NL, " ndrange_t ndrange;" + NL, " switch((linearId + level) % 3)" + NL, " {" + NL, " case 0:" + NL, " {" + NL, " const size_t gs = 8 * 8 * 8;" + NL, " size_t ls = rnd[tidX % maxGlobalWorkSize] % wg % gs;" + NL, " ls = ls? ls: 1;" + NL, " ndrange = ndrange_1D(gs, ls);" + NL, " }" + NL, " break;" + NL, " case 1:" + NL, " {" + NL, " const size_t gs[] = { 8, 8 * 8 };" + NL, " size_t ls[] = { 1, rnd[tidY % maxGlobalWorkSize] % wg % gs[1] };" + NL, " ls[1] = ls[1]? ls[1]: 1;" + NL, " ndrange = ndrange_2D(gs, ls);" + NL, " }" + NL, " break;" + NL, " case 2:" + NL, " {" + NL, " const size_t gs[] = { 8, 8, 8 };" + NL, " size_t ls[] = { 1, 1, rnd[tidZ % maxGlobalWorkSize] % wg % gs[2] };" + NL, " ls[2] = ls[2]? ls[2]: 1;" + NL, " ndrange = ndrange_3D(gs, ls);" + NL, " }" + NL, " break;" + NL, " default:" + NL, " break;" + NL, " }" + NL, "" + NL, " // All work-items enqueues nested blocks with different levels" + NL, " atomic_inc(&res[linearId % maxGlobalWorkSize]);" + NL, " if(level >= tidX && level >= tidY && level >= tidZ)" + NL, " {" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[linearId % maxGlobalWorkSize] = -1; return; }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_mix_wg_size_all_diff(__global int* res, int level, int maxGlobalWorkSize, __global int* rnd)" + NL, "{" + NL, " block_fn(level, maxGlobalWorkSize, rnd, res);" + NL, "}" + NL +}; + +void generate_reference_results_all_diff_mix(std::vector &referenceResults, cl_int len, cl_int level, cl_int dim) +{ + size_t globalSizeX = 1, globalSizeY = 1, globalSizeZ = 1; + switch (dim) + { + case 0: + globalSizeX = (level == nestingLevel) ? len: (8 * 8 * 8); + break; + case 1: + globalSizeX = 8; + globalSizeY = 8 * 8; + break; + case 2: + globalSizeX = 8; + globalSizeY = 8; + globalSizeZ = 8; + break; + default: + break; + } + + if(--level < 0) + { + return; + } + + for (size_t tidZ = 0; tidZ < globalSizeZ; ++tidZ) + { + for (size_t tidY = 0; tidY < globalSizeY; ++tidY) + { + for (size_t tidX = 0; tidX < globalSizeX; ++tidX) + { + size_t linearID = globalSizeX * globalSizeY * tidZ + globalSizeX * tidY + tidX; + cl_int nextDim = (linearID + level) % 3; + ++referenceResults[linearID % len]; + if (level >= tidX && level >= tidY && level >= tidZ) + { + generate_reference_results_all_diff_mix(referenceResults, len, level, nextDim); + } + } + } + } +} + +static int check_all_diff_mix(cl_int* results, cl_int len, cl_int nesting_level) +{ + std::vector referenceResults(len, 0); + generate_reference_results_all_diff_mix(referenceResults, len, nesting_level, 0); + + for(size_t i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) + { + log_error("ERROR: Kernel returned %d vs. expected %d, index: %d\n", results[i], referenceResults[i], i); + return (int)i; + } + } + + return -1; +} + +static const kernel_src_check sources_enqueue_wg_size[] = +{ + { KERNEL(enqueue_1D_wg_size_single), check_single }, + { KERNEL(enqueue_1D_wg_size_some_eq), check_some_eq_1D }, + { KERNEL(enqueue_1D_wg_size_some_diff), check_some_diff_1D }, + { KERNEL(enqueue_1D_wg_size_all_eq), check_all_eq_1D }, + { KERNEL(enqueue_1D_wg_size_all_diff), check_all_diff_1D }, + + { KERNEL(enqueue_2D_wg_size_single), check_single }, + { KERNEL(enqueue_2D_wg_size_some_eq), check_some_eq_2D }, + { KERNEL(enqueue_2D_wg_size_some_diff), check_some_diff_2D }, + { KERNEL(enqueue_2D_wg_size_all_eq), check_all_eq_2D }, + { KERNEL(enqueue_2D_wg_size_all_diff), check_all_diff_2D }, + + { KERNEL(enqueue_3D_wg_size_single), check_single }, + { KERNEL(enqueue_3D_wg_size_some_eq), check_some_eq_3D }, + { KERNEL(enqueue_3D_wg_size_some_diff), check_some_diff_3D }, + { KERNEL(enqueue_3D_wg_size_all_eq), check_all_eq_3D }, + { KERNEL(enqueue_3D_wg_size_all_diff), check_all_diff_3D }, + + { KERNEL(enqueue_mix_wg_size_single), check_single }, + { KERNEL(enqueue_mix_wg_size_some_eq), check_some_eq_mix }, + { KERNEL(enqueue_mix_wg_size_some_diff), check_some_diff_mix }, + { KERNEL(enqueue_mix_wg_size_all_eq), check_all_eq_mix }, + { KERNEL(enqueue_mix_wg_size_all_diff), check_all_diff_mix } +}; + +int test_enqueue_wg_size(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + MTdata d; + cl_uint i, k; + cl_int err_ret, res = 0; + clCommandQueueWrapper dev_queue; + const cl_int MAX_GLOBAL_WORK_SIZE = MAX_GWS / 4; + cl_int kernel_results[MAX_GLOBAL_WORK_SIZE] = { 0 }; + cl_uint vrnd[MAX_GLOBAL_WORK_SIZE] = { 0 }; + + size_t ret_len; + cl_uint max_queues = 1; + cl_uint maxQueueSize = 0; + d = init_genrand(gRandomSeed); + + if(gWimpyMode) + { + nestingLevel = 2; + vlog( "*** WARNING: Testing in Wimpy mode! ***\n" ); + vlog( "*** Wimpy mode is not sufficient to verify correctness. ***\n" ); + } + + err_ret = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, sizeof(maxQueueSize), &maxQueueSize, 0); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE) failed"); + + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_ON_DEVICE_QUEUES, sizeof(max_queues), &max_queues, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_ON_DEVICE_QUEUES) failed"); + + size_t max_local_size = 1; + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(max_local_size), &max_local_size, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_WORK_GROUP_SIZE) failed"); + + cl_queue_properties queue_prop_def[] = + { + CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE|CL_QUEUE_ON_DEVICE|CL_QUEUE_ON_DEVICE_DEFAULT, + CL_QUEUE_SIZE, maxQueueSize, + 0 + }; + + dev_queue = clCreateCommandQueueWithProperties(context, device, queue_prop_def, &err_ret); + test_error(err_ret, "clCreateCommandQueueWithProperties(CL_QUEUE_DEVICE|CL_QUEUE_DEFAULT) failed"); + + + size_t failCnt = 0; + for(k = 0; k < arr_size(sources_enqueue_wg_size); ++k) + { + if (!gKernelName.empty() && gKernelName != sources_enqueue_wg_size[k].src.kernel_name) + continue; + + log_info("Running '%s' kernel (%d of %d) ...\n", sources_enqueue_wg_size[k].src.kernel_name, k + 1, arr_size(sources_enqueue_wg_size)); + for(i = 0; i < MAX_GLOBAL_WORK_SIZE; ++i) + { + kernel_results[i] = 0; + vrnd[i] = genrand_int32(d); + } + + // Fill some elements with prime numbers + cl_uint prime[] = { 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127 }; + + for(i = 0; i < arr_size(prime); ++i) + { + vrnd[genrand_int32(d) % MAX_GLOBAL_WORK_SIZE] = prime[i]; + } + + clMemWrapper mem; + mem = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, sizeof(vrnd), vrnd, &err_ret); + test_error(err_ret, "clCreateBuffer() failed"); + + kernel_arg args[] = + { + { sizeof(cl_uint), &nestingLevel }, + { sizeof(cl_uint), &MAX_GLOBAL_WORK_SIZE }, + { sizeof(cl_mem), &mem } + }; + + size_t global_size = MAX_GLOBAL_WORK_SIZE; + size_t local_size = (max_local_size > global_size) ? global_size : max_local_size; + + err_ret = run_n_kernel_args(context, queue, sources_enqueue_wg_size[k].src.lines, sources_enqueue_wg_size[k].src.num_lines, sources_enqueue_wg_size[k].src.kernel_name, local_size, global_size, kernel_results, sizeof(kernel_results), arr_size(args), args); + + //check results + int fail = sources_enqueue_wg_size[k].check(kernel_results, global_size, nestingLevel); + + if(check_error(err_ret, "'%s' kernel execution failed", sources_enqueue_wg_size[k].src.kernel_name)) { ++failCnt; res = -1; continue; } + else if(fail >= 0 && check_error(-1, "'%s' kernel results validation failed: [%d]", sources_enqueue_wg_size[k].src.kernel_name, fail)) { ++failCnt; res = -1; continue; } + else log_info("'%s' kernel is OK.\n", sources_enqueue_wg_size[k].src.kernel_name); + } + + if (failCnt > 0) + { + log_error("ERROR: %d of %d kernels failed.\n", failCnt, arr_size(sources_enqueue_wg_size)); + } + + free_mtdata(d); + + return res; +} + +#endif + diff --git a/test_conformance/device_execution/execute_block.cpp b/test_conformance/device_execution/execute_block.cpp new file mode 100644 index 00000000..e10b7c6e --- /dev/null +++ b/test_conformance/device_execution/execute_block.cpp @@ -0,0 +1,1050 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" + +#include + +#include "procs.h" +#include "utils.h" +#include + + +#ifdef CL_VERSION_2_0 + +static const char* block_global_scope[] = +{ + NL, "int __constant globalVar = 7;" + NL, "int (^__constant globalBlock)(int) = ^int(int num)" + NL, "{" + NL, " return globalVar * num * (1+ get_global_id(0));" + NL, "};" + NL, "kernel void block_global_scope(__global int* res)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = -1;" + NL, " res[tid] = globalBlock(3) - 21*(tid + 1);" + NL, "}" + NL +}; + +static const char* block_kernel_scope[] = +{ + NL, "kernel void block_kernel_scope(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " int (^kernelBlock)(int) = ^(int num)" + NL, " {" + NL, " return num * multiplier;" + NL, " };" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = -1;" + NL, " multiplier = 8;" + NL, " res[tid] = kernelBlock(7) - 21;" + NL, "}" + NL +}; + +static const char* block_statement_scope[] = +{ + NL, "kernel void block_statement_scope(__global int* res)" + NL, "{" + NL, " int multiplier = 0;" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = -1;" + NL, " multiplier = 9;" + NL, " res[tid] = ^int(int num) { return multiplier * num; } (11) - 99;" + NL, "}" + NL +}; + +static const char* block_function_scope[] = +{ + NL, "int fnTest(int a)" + NL, "{" + NL, " int localVar = 17;" + NL, " int (^functionBlock)(int) = ^(int num)" + NL, " {" + NL, " return localVar * num;" + NL, " };" + NL, " return 111 - functionBlock(a+1);" + NL, "}" + NL, "kernel void block_function_scope(__global int* res)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = -1;" + NL, " res[tid] = fnTest(5) - 9;" + NL, "}" + NL +}; + +static const char* block_nested_scope[] = +{ + NL, "kernel void block_nested_scope(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " int (^kernelBlock)(int) = ^(int num)" + NL, " {" + NL, " int (^innerBlock)(int) = ^(int n)" + NL, " {" + NL, " return multiplier * n;" + NL, " };" + NL, " return num * innerBlock(23);" + NL, " };" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = -1;" + NL, " multiplier = 8;" + NL, " res[tid] = kernelBlock(13) - 897;" + NL, "}" + NL +}; + +static const char* block_arg_struct[] = +{ + NL, "struct two_ints {" + NL, " short x;" + NL, " long y;" + NL, "};" + NL, "struct two_structs {" + NL, " struct two_ints a;" + NL, " struct two_ints b;" + NL, "};" + NL, "kernel void block_arg_struct(__global int* res)" + NL, "{" + NL, " int (^kernelBlock)(struct two_ints, struct two_structs) = ^int(struct two_ints ti, struct two_structs ts)" + NL, " {" + NL, " return ti.x * ti.y * ts.a.x * ts.a.y * ts.b.x * ts.b.y;" + NL, " };" + NL, " struct two_ints i;" + NL, " i.x = 2;" + NL, " i.y = 3;" + NL, " struct two_structs s;" + NL, " s.a.x = 4;" + NL, " s.a.y = 5;" + NL, " s.b.x = 6;" + NL, " s.b.y = 7;" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = -1;" + NL, " res[tid] = kernelBlock(i,s) - 5040;" + NL, "}" + NL +}; + +static const char* block_arg_types_mix[] = +{ + NL, "union number {" + NL, " long l;" + NL, " float f;" + NL, "};" + NL, "enum color {" + NL, " RED = 0," + NL, " GREEN," + NL, " BLUE" // Using this value - it is actualy "2" + NL, "};" + NL, "typedef int _INT ;" + NL, "typedef char _ACHAR[3] ;" + NL, "kernel void block_arg_types_mix(__global int* res)" + NL, "{" + NL, " int (^kernelBlock)(_INT, _ACHAR, union number, enum color, int, int, int, int, int, int, int, int, int, int, int, int, int) =" + NL, " ^int(_INT bi, _ACHAR bch, union number bn, enum color bc, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8," + NL, " int i9, int i10, int i11, int i12, int i13)" + NL, " {" + NL, " return bi * bch[0] * bch[1] * bch[2] * bn.l * bc - i1 - i2 - i3 - i4 - i5 - i6 - i7 - i8 - i9 - i10 - i11 - i12 - i13;" + NL, " };" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = -1;" + NL, " _INT x = -5;" + NL, " _ACHAR char_arr = { 1, 2, 3 };" + NL, " union number n;" + NL, " n.l = 4;" + NL, " enum color c = BLUE;" + NL, " res[tid] = kernelBlock(x,char_arr,n,c,1,2,3,4,5,6,7,8,9,10,11,12,13) + 331;" + NL, "}" + NL +}; + +static const char* block_arg_pointer[] = +{ + NL, "struct two_ints {" + NL, " short x;" + NL, " long y;" + NL, "};" + NL, "kernel void block_arg_pointer(__global int* res)" + NL, "{" + NL, " int (^kernelBlock)(struct two_ints*, struct two_ints*, int*, int*) = " + NL, " ^int(struct two_ints* bs1, struct two_ints* bs2, int* bi1, int* bi2)" + NL, " {" + NL, " return (*bs1).x * (*bs1).y * (*bs2).x * (*bs2).y * (*bi1) * (*bi2);" + NL, " };" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = -1;" + NL, " struct two_ints s[2];" + NL, " s[0].x = 4;" + NL, " s[0].y = 5;" + NL, " struct two_ints* ps = s + 1;" + NL, " (*ps).x = 6;" + NL, " (*ps).y = 7;" + NL, " int i = 2;" + NL, " int * pi = &i;" + NL, " res[tid] = kernelBlock(s,ps,&i,pi) - 3360;" + NL, "}" + NL +}; + +static const char* block_arg_global_p[] = +{ + NL, "kernel void block_arg_global_p(__global int* res)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = -1;" + NL, " typedef __global int* int_ptr_to_global_t;" + NL, " int_ptr_to_global_t (^kernelBlock)(__global int*, int) =^ int_ptr_to_global_t (__global int* bres, int btid)" + NL, " {" + NL, " bres[tid] = 5;" + NL, " return bres;" + NL, " };" + NL, " res = kernelBlock(res, tid);" + NL, " res[tid] -= 5;" + NL, "}" + NL +}; + +static const char* block_arg_const_p[] = +{ + NL, "constant int ci = 8;" + NL, "kernel void block_arg_const_p(__global int* res)" + NL, "{" + NL, " __constant int* (^kernelBlock)(__constant int*) = ^(__constant int* bpci)" + NL, " {" + NL, " return bpci;" + NL, " };" + NL, " constant int* pci = &ci;" + NL, " constant int* pci_check;" + NL, " pci_check = kernelBlock(pci);" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = pci == pci_check ? 0 : -1;" + NL, "}" + NL +}; + +static const char* block_ret_struct[] = +{ + NL, "kernel void block_ret_struct(__global int* res)" + NL, "{" + NL, " struct A {" + NL, " int a;" + NL, " }; " + NL, " struct A (^kernelBlock)(struct A) = ^struct A(struct A a)" + NL, " { " + NL, " a.a = 6;" + NL, " return a;" + NL, " };" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = -1;" + NL, " struct A aa;" + NL, " aa.a = 5;" + NL, " res[tid] = kernelBlock(aa).a - 6;" + NL, "}" + NL +}; + +static const char* block_arg_global_var[] = +{ + NL, "constant int gi = 8;" + NL, "kernel void block_arg_global_var(__global int* res)" + NL, "{" + NL, " int (^kernelBlock)(int) = ^(int bgi)" + NL, " {" + NL, " return bgi - 8;" + NL, " };" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = kernelBlock(gi);" + NL, "}" + NL +}; + +static const char* block_in_for_init[] = +{ + NL, "kernel void block_in_for_init(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " int (^kernelBlock)(int) = ^(int num)" + NL, " {" + NL, " return num * multiplier;" + NL, " };" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = 27;" + NL, " for(int i=kernelBlock(9); i>0; i--)" + NL, " {" + NL, " res[tid]--;" + NL, " }" + NL, "}" + NL +}; + +static const char* block_in_for_cond[] = +{ + NL, "kernel void block_in_for_cond(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " int (^kernelBlock)(int) = ^(int num)" + NL, " {" + NL, " return num * multiplier;" + NL, " };" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = 39;" + NL, " for(int i=0; i 0)" + NL, " {" + NL, " typedef uint (^block_t)(uint);" + NL, " const block_t nestedBlock = ^(uint bi) { return (uint)(bi + 4); };" + NL, " a = nestedBlock(1) + nestedBlock(2);" + NL, " break;" + NL, " }" + NL, " } while(1); " + NL, " res[tid] = a - 11;" + NL, "}" + NL +}; + +static const char* block_typedef_mltpl_g[] = +{ + NL, "typedef int (^block1_t)(float, int); " + NL, "constant block1_t b1 = ^(float fi, int ii) { return (int)(ii + fi); };" + NL, "typedef int (^block2_t)(float, int);" + NL, "constant block2_t b2 = ^(float fi, int ii) { return (int)(ii + fi); };" + NL, "typedef float (^block3_t)(int, int);" + NL, "constant block3_t b3 = ^(int i1, int i2) { return (float)(i1 + i2); };" + NL, "typedef int (^block4_t)(float, float);" + NL, "kernel void block_typedef_mltpl_g(__global int* res)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = -1;" + NL, " block4_t b4 = ^(float f1, float f2) { return (int)(f1 + f2); };" + NL, " res[tid] = b1(1.1, b2(1.1, 1)) - b4(b3(1,1), 1.1);" + NL, "}" + NL +}; + +static const char* block_literal[] = +{ + NL, "int func()" + NL, "{" + NL, " return ^(int i) {" + NL, " return ^(ushort us)" + NL, " {" + NL, " return (int)us + i;" + NL, " }(3);" + NL, " }(7) - 10;" + NL, "}" + NL, "kernel void block_literal(__global int* res)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = -1;" + NL, " res[tid] = func();" + NL, "}" + NL +}; + +static const char* block_complex[] = +{ + NL, "kernel void block_complex(__global int* res)" + NL, "{" + NL, " int (^kernelBlock)(int) = ^(int num)" + NL, " {" + NL, " int result = 1;" + NL, " for (int i = 0; i < num; i++)" + NL, " {" + NL, " switch(i)" + NL, " {" + NL, " case 0:" + NL, " case 1:" + NL, " case 2:" + NL, " result += i;" + NL, " break;" + NL, " case 3:" + NL, " if (result < num)" + NL, " result += i;" + NL, " else" + NL, " result += i * 2;" + NL, " break;" + NL, " case 4:" + NL, " while (1)" + NL, " {" + NL, " result++;" + NL, " if (result)" + NL, " goto ret;" + NL, " }" + NL, " break;" + NL, " default:" + NL, " return 777;" + NL, " }" + NL, " }" + NL, " ret: ;" + NL, " while (num) {" + NL, " num--;" + NL, " if (num % 2 == 0)" + NL, " continue;" + NL, " result++;" + NL, " }" + NL, " return result;" + NL, " };" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = -1;" + NL, " res[tid] = kernelBlock(7) - 11;" + NL, "}" + NL +}; + +static const char* block_empty[] = +{ + NL, "kernel void block_empty(__global int* res)" + NL, "{" + NL, " void (^kernelBlock)(void) = ^(){};" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = -1;" + NL, " kernelBlock();" + NL, " res[tid] = 0;" + NL, "}" + NL +}; + +static const char* block_builtin[] = +{ + NL, "kernel void block_builtin(__global int* res)" + NL, "{" + NL, " int b = 3;" + NL, " int (^kernelBlock)(int) = ^(int a)" + NL, " {" + NL, " return (int)abs(a - b);" + NL, " };" + NL, " size_t tid = get_global_id(0);" + NL, " res[tid] = -1;" + NL, " res[tid] = kernelBlock(2) - 1;" + NL, "}" + NL +}; + +static const char* block_barrier[] = +{ + NL, "kernel void block_barrier(__global int* res)" + NL, "{" + NL, " int b = 3;" + NL, " size_t tid = get_global_id(0);" + NL, " size_t lsz = get_local_size(0);" + NL, " size_t gid = get_group_id(0);" + NL, " size_t idx = gid*lsz;" + NL, "" + NL, " int (^kernelBlock)(int) = ^(int a)" + NL, " {" + NL, " atomic_inc(res+idx);" + NL, " barrier(CLK_GLOBAL_MEM_FENCE);" + NL, " return (int)abs(a - b) - (res[idx] != lsz ? 0 : 1);" + NL, " };" + NL, "" + NL, " int d = kernelBlock(2);" + NL, " barrier(CLK_GLOBAL_MEM_FENCE);" + NL, " res[tid] = d;" + NL, "}" + NL +}; + + + +static const kernel_src sources_execute_block[] = +{ + // Simple blocks + KERNEL(block_global_scope), + KERNEL(block_kernel_scope), + KERNEL(block_statement_scope), + KERNEL(block_function_scope), + KERNEL(block_nested_scope), + + // Kernels with Block in for/while/if/switch + KERNEL(block_in_for_init), + KERNEL(block_in_for_cond), + KERNEL(block_in_for_iter), + KERNEL(block_in_while_cond), + KERNEL(block_in_while_body), + KERNEL(block_in_do_while_body), + KERNEL(block_cond_statement), + KERNEL(block_in_if_cond), + KERNEL(block_in_if_branch), + KERNEL(block_switch_cond), + KERNEL(block_switch_case), + KERNEL(block_literal), + + // Accessing data from block + KERNEL(block_access_program_data), + KERNEL(block_access_kernel_data), + KERNEL(block_access_chained_data), + KERNEL(block_access_volatile_data), + + // Block args + KERNEL(block_arg_struct), + KERNEL(block_arg_types_mix), + KERNEL(block_arg_pointer), + KERNEL(block_arg_global_p), + KERNEL(block_arg_const_p), + KERNEL(block_ret_struct), + KERNEL(block_arg_global_var), + + // Block in typedef + KERNEL(block_typedef_kernel), + KERNEL(block_typedef_func), + KERNEL(block_typedef_stmnt_if), + KERNEL(block_typedef_loop), + KERNEL(block_typedef_mltpl_func), + KERNEL(block_typedef_mltpl_stmnt), + KERNEL(block_typedef_mltpl_g), + + // Non - trivial blocks + KERNEL(block_complex), + KERNEL(block_empty), + KERNEL(block_builtin), + KERNEL(block_barrier), + +}; +static const size_t num_kernels_execute_block = arr_size(sources_execute_block); + +static int check_kernel_results(cl_int* results, cl_int len) +{ + for(cl_int i = 0; i < len; ++i) + { + if(results[i] != 0) return i; + } + return -1; +} + +int test_execute_block(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + size_t i; + size_t ret_len; + cl_int n, err_ret, res = 0; + clCommandQueueWrapper dev_queue; + cl_int kernel_results[MAX_GWS] = {0xDEADBEEF}; + + size_t max_local_size = 1; + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(max_local_size), &max_local_size, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_WORK_GROUP_SIZE) failed"); + + size_t global_size = MAX_GWS; + size_t local_size = (max_local_size > global_size/16) ? global_size/16 : max_local_size; + + size_t failCnt = 0; + for(i = 0; i < num_kernels_execute_block; ++i) + { + if (!gKernelName.empty() && gKernelName != sources_execute_block[i].kernel_name) + continue; + + log_info("Running '%s' kernel (%d of %d) ...\n", sources_execute_block[i].kernel_name, i + 1, num_kernels_execute_block); + err_ret = run_n_kernel_args(context, queue, sources_execute_block[i].lines, sources_execute_block[i].num_lines, sources_execute_block[i].kernel_name, local_size, global_size, kernel_results, sizeof(kernel_results), 0, NULL); + if(check_error(err_ret, "'%s' kernel execution failed", sources_execute_block[i].kernel_name)) { ++failCnt; res = -1; } + else if((n = check_kernel_results(kernel_results, arr_size(kernel_results))) >= 0 && check_error(-1, "'%s' kernel results validation failed: [%d] returned %d expected 0", sources_execute_block[i].kernel_name, n, kernel_results[n])) { ++failCnt; res = -1; } + else log_info("'%s' kernel is OK.\n", sources_execute_block[i].kernel_name); + } + + if (failCnt > 0) + { + log_error("ERROR: %d of %d kernels failed.\n", failCnt, num_kernels_execute_block); + } + + return res; +} + + +#endif + diff --git a/test_conformance/device_execution/host_multi_queue.cpp b/test_conformance/device_execution/host_multi_queue.cpp new file mode 100644 index 00000000..5b572d72 --- /dev/null +++ b/test_conformance/device_execution/host_multi_queue.cpp @@ -0,0 +1,228 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" + +#include + +#include "procs.h" +#include "utils.h" +#include + + +#ifdef CL_VERSION_2_0 +extern int gWimpyMode; +static const char* multi_queue_simple_block1[] = +{ + NL, "void block_fn(size_t tid, int mul, __global int* res)" + NL, "{" + NL, " res[tid] = mul * 7 - 21;" + NL, "}" + NL, "" + NL, "kernel void multi_queue_simple_block1(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(tid, multiplier, res); };" + NL, "" + NL, " res[tid] = -1;" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "}" + NL +}; + +static const char* multi_queue_simple_block2[] = +{ + NL, "void block_fn(size_t tid, int mul, __global int* res)" + NL, "{" + NL, " res[tid] = mul * 7 - 21;" + NL, "}" + NL, "" + NL, "kernel void multi_queue_simple_block2(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(tid, multiplier, res); };" + NL, "" + NL, " res[tid] = -1;" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "}" + NL +}; + +static const char* multi_queue_simple_block3[] = +{ + NL, "void block_fn(size_t tid, int mul, __global int* res)" + NL, "{" + NL, " res[tid] = mul * 7 - 21;" + NL, "}" + NL, "" + NL, "kernel void multi_queue_simple_block3(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(tid, multiplier, res); };" + NL, "" + NL, " res[tid] = -1;" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "}" + NL +}; + +static const char* multi_queue_simple_block4[] = +{ + NL, "void block_fn(size_t tid, int mul, __global int* res)" + NL, "{" + NL, " res[tid] = mul * 7 - 21;" + NL, "}" + NL, "" + NL, "kernel void multi_queue_simple_block4(__global int* res)" + NL, "{" + NL, " int multiplier = 3;" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(tid, multiplier, res); };" + NL, "" + NL, " res[tid] = -1;" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "}" + NL +}; + +static const kernel_src sources_multi_queue_block[] = +{ + KERNEL(multi_queue_simple_block1), + KERNEL(multi_queue_simple_block2), + KERNEL(multi_queue_simple_block3), + KERNEL(multi_queue_simple_block4), +}; +static const size_t num_kernels_multi_queue_block = arr_size(sources_multi_queue_block); + + +int test_host_multi_queue(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_uint i; + cl_int err_ret, res = 0; + clCommandQueueWrapper dev_queue; + cl_int kernel_results[MAX_GWS] = {0}; + + size_t ret_len; + cl_uint max_queues = 1; + cl_uint maxQueueSize = 0; + err_ret = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, sizeof(maxQueueSize), &maxQueueSize, 0); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE) failed"); + + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_ON_DEVICE_QUEUES, sizeof(max_queues), &max_queues, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_ON_DEVICE_QUEUES) failed"); + + size_t max_local_size = 1; + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(max_local_size), &max_local_size, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_WORK_GROUP_SIZE) failed"); + + cl_queue_properties queue_prop_def[] = + { + CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE|CL_QUEUE_ON_DEVICE|CL_QUEUE_ON_DEVICE_DEFAULT, + CL_QUEUE_SIZE, maxQueueSize, + 0 + }; + + dev_queue = clCreateCommandQueueWithProperties(context, device, queue_prop_def, &err_ret); + test_error(err_ret, "clCreateCommandQueueWithProperties(CL_QUEUE_DEVICE|CL_QUEUE_DEFAULT) failed"); + + cl_uint n = num_kernels_multi_queue_block; // Number of host queues + std::vector queues(n); + std::vector q(n); + std::vector program(n); + std::vector kernel(n); + std::vector mem(n); + std::vector event(n); + + for(i = 0; i < n; ++i) + { + queues[i] = clCreateCommandQueueWithProperties(context, device, NULL, &err_ret); + if(check_error(err_ret, "clCreateCommandQueueWithProperties() failed")) { res = -1; break; } + q[i] = queues[i]; + } + + if(err_ret == CL_SUCCESS) + { + for(i = 0; i < n; ++i) + { + size_t global = MAX_GWS; + if(gWimpyMode) + { + global = 16; + } + + err_ret |= create_single_kernel_helper_with_build_options(context, &program[i], &kernel[i], sources_multi_queue_block[i].num_lines, sources_multi_queue_block[i].lines, sources_multi_queue_block[i].kernel_name, "-cl-std=CL2.0"); + if(check_error(err_ret, "Create single kernel failed")) { res = -1; break; } + + mem[i] = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(kernel_results), kernel_results, &err_ret); + if(check_error(err_ret, "clCreateBuffer() failed")) { res = -1; break; } + + err_ret |= clSetKernelArg(kernel[i], 0, sizeof(cl_mem), &mem[i]); + if(check_error(err_ret, "clSetKernelArg(0) failed")) { res = -1; break; } + + err_ret |= clEnqueueNDRangeKernel(q[i], kernel[i], 1, NULL, &global, 0, 0, NULL, &event[i]); + if(check_error(err_ret, "clEnqueueNDRangeKernel() failed")) { res = -1; break; } + } + } + + if(err_ret == CL_SUCCESS) + { + for(i = 0; i < n; ++i) + { + cl_int status; + err_ret = clEnqueueReadBuffer(q[i], mem[i], CL_TRUE, 0, sizeof(kernel_results), kernel_results, 0, NULL, NULL); + if(check_error(err_ret, "clEnqueueReadBuffer() failed")) { res = -1; break; } + + err_ret = clGetEventInfo(event[i], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(status), &status, &ret_len); + if(check_error(err_ret, "clGetEventInfo() failed")) { res = -1; break; } + +#if CL_COMPLETE != CL_SUCCESS +#error Fix me! +#endif + // This hack is possible because both CL_COMPLETE and CL_SUCCESS defined as 0x00 + if(check_error(status, "Kernel execution status %d", status)) { err_ret = status; res = -1; break; } + else if(kernel_results[0] != 0 && check_error(-1, "'%s' kernel results validation failed = %d", sources_multi_queue_block[i].kernel_name, kernel_results[0])) { res = -1; break; } + } + } + + return res; +} + + + + +#endif + diff --git a/test_conformance/device_execution/host_queue_order.cpp b/test_conformance/device_execution/host_queue_order.cpp new file mode 100644 index 00000000..51a7b718 --- /dev/null +++ b/test_conformance/device_execution/host_queue_order.cpp @@ -0,0 +1,185 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" + +#include + +#include "procs.h" +#include "utils.h" +#include + +extern int gWimpyMode; + +#ifdef CL_VERSION_2_0 + +static const char* enqueue_block_first_kernel[] = +{ + NL, "void block_fn(uint num, __global int* res)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, "" + NL, " for(int i = 1 ; i < tid ; i++)" + NL, " {" + NL, " for(int j = 0 ; j < num ; j++)" + NL, " atomic_add(res+tid, (int)sqrt((float)i*i) / i);" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_block_first_kernel(uint num, __global int* res)" + NL, "{" + NL, " void (^kernelBlock)(void) = ^{ block_fn(num, res); };" + NL, "" + NL, " ndrange_t ndrange = ndrange_1D(num, 1);" + NL, "" + NL, " int enq_res = enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[0] = -1; return; }" + NL, "" + NL, "}" + NL +}; + +static const char* enqueue_block_second_kernel[] = +{ + NL, "void block_fn(uint num, __global int* res)" + NL, "{" + NL, " for(int i = 2 ; i < num ; i++)" + NL, " {" + NL, " res[i] = res[i]/num - (i-1);" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_block_second_kernel(uint num, __global int* res)" + NL, "{" + NL, " void (^kernelBlock)(void) = ^{ block_fn(num, res); };" + NL, "" + NL, " ndrange_t ndrange = ndrange_1D(1);" + NL, "" + NL, " int enq_res = enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[0] = -1; return; }" + NL, "" + NL, "}" + NL +}; + +static int check_kernel_results(cl_int* results, cl_int len) +{ + for(cl_int i = 0; i < len; ++i) + { + if(results[i] != 0) return i; + } + return -1; +} + +/* + Test checks kernel block execution order in case of two different kernels with enqueue block submitted to one ordered host queue. +*/ +int test_host_queue_order(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int k, err_ret, res = 0; + clCommandQueueWrapper dev_queue; + cl_int kernel_results[MAX_GWS] = {0}; + + size_t ret_len; + cl_uint max_queues = 1; + cl_uint maxQueueSize = 0; + err_ret = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, sizeof(maxQueueSize), &maxQueueSize, 0); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE) failed"); + + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_ON_DEVICE_QUEUES, sizeof(max_queues), &max_queues, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_ON_DEVICE_QUEUES) failed"); + + size_t max_local_size = 1; + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(max_local_size), &max_local_size, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_WORK_GROUP_SIZE) failed"); + + cl_queue_properties queue_prop_def[] = + { + CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE|CL_QUEUE_ON_DEVICE|CL_QUEUE_ON_DEVICE_DEFAULT, + CL_QUEUE_SIZE, maxQueueSize, + 0 + }; + + dev_queue = clCreateCommandQueueWithProperties(context, device, queue_prop_def, &err_ret); + test_error(err_ret, "clCreateCommandQueueWithProperties(CL_QUEUE_DEVICE|CL_QUEUE_DEFAULT) failed"); + + cl_int status; + size_t size = 1; + cl_int result[MAX_GWS] = { 0 }; + cl_uint num = arr_size(result); + if( gWimpyMode ) + { + num = MAX(num / 16, 4); + } + + clMemWrapper res_mem; + clProgramWrapper program1, program2; + clKernelWrapper kernel1, kernel2; + + cl_event kernel_event; + + err_ret = create_single_kernel_helper_with_build_options(context, &program1, &kernel1, arr_size(enqueue_block_first_kernel), enqueue_block_first_kernel, "enqueue_block_first_kernel", "-cl-std=CL2.0"); + if(check_error(err_ret, "Create single kernel failed")) return -1; + + err_ret = create_single_kernel_helper_with_build_options(context, &program2, &kernel2, arr_size(enqueue_block_second_kernel), enqueue_block_second_kernel, "enqueue_block_second_kernel", "-cl-std=CL2.0"); + if(check_error(err_ret, "Create single kernel failed")) return -1; + + res_mem = clCreateBuffer(context, CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR, sizeof(kernel_results), kernel_results, &err_ret); + test_error(err_ret, "clCreateBuffer() failed"); + + // Enqueue first kernel + err_ret = clSetKernelArg(kernel1, 0, sizeof(num), &num); + test_error(err_ret, "clSetKernelArg(0) failed"); + err_ret = clSetKernelArg(kernel1, 1, sizeof(cl_mem), &res_mem); + test_error(err_ret, "clSetKernelArg(1) failed"); + + cl_event event1 = clCreateUserEvent(context, &err_ret); + if(check_error(err_ret, "Create user event failed")) return -1; + + err_ret = clEnqueueNDRangeKernel(queue, kernel1, 1, NULL, &size, &size, 1, &event1, NULL); + test_error(err_ret, "clEnqueueNDRangeKernel('enqueue_block_first_kernel') failed"); + + // Enqueue second kernel + err_ret = clSetKernelArg(kernel2, 0, sizeof(num), &num); + test_error(err_ret, "clSetKernelArg(0) failed"); + err_ret = clSetKernelArg(kernel2, 1, sizeof(cl_mem), &res_mem); + test_error(err_ret, "clSetKernelArg(1) failed"); + + err_ret = clEnqueueNDRangeKernel(queue, kernel2, 1, NULL, &size, &size, 0, NULL, &kernel_event); + test_error(err_ret, "clEnqueueNDRangeKernel('enqueue_block_second_kernel') failed"); + + //Triger execution of first kernel + err_ret = clSetUserEventStatus(event1, CL_COMPLETE); + test_error(err_ret, "clSetUserEventStatus() failed"); + + // Collect resulsts + err_ret = clEnqueueReadBuffer(queue, res_mem, CL_TRUE, 0, sizeof(result), result, 0, NULL, NULL); + test_error(err_ret, "clEnqueueReadBuffer() failed"); + + err_ret = clGetEventInfo(kernel_event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(status), &status, &ret_len); + test_error(err_ret, "clGetEventInfo() failed"); + + if(check_error(status, "Kernel execution status %d", status)) return status; + + if((k = check_kernel_results(result, num)) >= 0 && check_error(-1, "'%s' results validation failed: [%d] returned %d expected 0", "test_host_queue_order", k, result[k])) res = -1; + + return res; +} + +#endif + diff --git a/test_conformance/device_execution/main.c b/test_conformance/device_execution/main.c new file mode 100644 index 00000000..da2cdc42 --- /dev/null +++ b/test_conformance/device_execution/main.c @@ -0,0 +1,101 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include + +#if !defined(_WIN32) +#include +#endif + +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/parseParameters.h" +#include "utils.h" +#include "procs.h" + +std::string gKernelName; +int gWimpyMode = 0; + +basefn basefn_list[] = +{ +#ifdef CL_VERSION_2_0 + test_device_info, + test_device_queue, + test_execute_block, + test_enqueue_block, + test_enqueue_nested_blocks, + test_enqueue_wg_size, + test_enqueue_flags, + test_enqueue_multi_queue, + test_host_multi_queue, + test_enqueue_ndrange, + test_host_queue_order, +#endif +}; + +const char *commonfn_names[] = +{ +#ifdef CL_VERSION_2_0 + "test_device_info", + "test_device_queue", + "test_execute_block", + "test_enqueue_block", + "test_enqueue_nested_blocks", + "test_enqueue_wg_size", + "test_enqueue_flags", + "test_enqueue_multi_queue", + "test_host_multi_queue", + "test_enqueue_ndrange", + "test_host_queue_order", +#endif +}; + +ct_assert(arr_size(commonfn_names) == arr_size(basefn_list)) + +static const int num_commonfns = arr_size(commonfn_names); + +int +main(int argc, const char *argv[]) +{ + argc = parseCustomParam(argc, argv); + + for (int i = 0; i < argc; ++i) { + int argsRemoveNum = 0; + if ( strcmp(argv[i], "-kernelName") == 0 ) { + if((i + 1) > argc && argv[i + 1] == NULL) { + vlog( "Missing value for -kernelName argument\n"); + return -1; + } + + gKernelName = std::string(argv[i + 1]); + argsRemoveNum += 2; + } + if (strcmp(argv[i], "-w") == 0 ){ + gWimpyMode = 1; + argsRemoveNum += 1; + } + + + if (argsRemoveNum > 0) { + for (int j = i; j < (argc - argsRemoveNum); ++j) + argv[j] = argv[j + argsRemoveNum]; + + argc -= argsRemoveNum; + --i; + } + } + + return runTestHarness(argc, argv, num_commonfns, basefn_list, commonfn_names, false, false, 0); +} diff --git a/test_conformance/device_execution/nested_blocks.cpp b/test_conformance/device_execution/nested_blocks.cpp new file mode 100644 index 00000000..fd075527 --- /dev/null +++ b/test_conformance/device_execution/nested_blocks.cpp @@ -0,0 +1,374 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" + +#include + +#include "procs.h" +#include "utils.h" +#include + + +#ifdef CL_VERSION_2_0 + +static int gNestingLevel = 4; +extern int gWimpyMode; + +static const char* enqueue_nested_blocks_single[] = +{ + NL, "void block_fn(__global int* res, int level)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(3);" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(res, level); };" + NL, "" + NL, " // Only 1 work-item enqueues block" + NL, " if(tid == 1)" + NL, " {" + NL, " res[tid]++;" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_nested_blocks_single(__global int* res, int level)" + NL, "{" + NL, " block_fn(res, level);" + NL, "}" + NL +}; + +static const char* enqueue_nested_blocks_some_eq[] = +{ + NL, "void block_fn(int level, __global int* res)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(10);" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, res); };" + NL, "" + NL, " // Some work-items enqueues nested blocks with the same level" + NL, " if(tid < (get_global_size(0) >> 1))" + NL, " {" + NL, " atomic_inc(&res[tid]);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_nested_blocks_some_eq(__global int* res, int level)" + NL, "{" + NL, " block_fn(level, res);" + NL, "}" + NL +}; + +static const char* enqueue_nested_blocks_some_diff[] = +{ + NL, "void block_fn(int level, __global int* res)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(10);" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, res); };" + NL, "" + NL, " // Some work-items enqueues nested blocks with different levels" + NL, " if(tid % 2)" + NL, " {" + NL, " atomic_inc(&res[tid]);" + NL, " if(level >= tid)" + NL, " {" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, " }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_nested_blocks_some_diff(__global int* res, int level)" + NL, "{" + NL, " block_fn(level, res);" + NL, "}" + NL +}; + +static const char* enqueue_nested_blocks_all_eq[] = +{ + NL, "void block_fn(int level, __global int* res)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(4);" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, res); };" + NL, "" + NL, " // All work-items enqueues nested blocks with the same level" + NL, " atomic_inc(&res[tid]);" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, "}" + NL, "" + NL, "kernel void enqueue_nested_blocks_all_eq(__global int* res, int level)" + NL, "{" + NL, " block_fn(level, res);" + NL, "}" + NL +}; + +static const char* enqueue_nested_blocks_all_diff[] = +{ + NL, "void block_fn(int level, __global int* res)" + NL, "{" + NL, " size_t tid = get_global_id(0);" + NL, " queue_t def_q = get_default_queue();" + NL, " ndrange_t ndrange = ndrange_1D(10);" + NL, " if(--level < 0) return;" + NL, "" + NL, " void (^kernelBlock)(void) = ^{ block_fn(level, res); };" + NL, "" + NL, " // All work-items enqueues nested blocks with different levels" + NL, " atomic_inc(&res[tid]);" + NL, " if(level >= tid)" + NL, " {" + NL, " int enq_res = enqueue_kernel(def_q, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);" + NL, " if(enq_res != CLK_SUCCESS) { res[tid] = -1; return; }" + NL, " }" + NL, "}" + NL, "" + NL, "kernel void enqueue_nested_blocks_all_diff(__global int* res, int level)" + NL, "{" + NL, " block_fn(level, res);" + NL, "}" + NL +}; + +static int check_single(cl_int* results, cl_int len, cl_int nesting_level) +{ + int i, fail = -1; + const cl_uint tid = 1; + + for(i = 0; i < len; ++i) + { + if(i != tid && results[i] != 0) { fail = i; break; } + if(i == tid && results[i] != nesting_level) { fail = i; break; } + } + return fail; +} + +void generate_reference_some_eq(std::vector &referenceResults, cl_int len, cl_int nesting_level) +{ + size_t globalWorkSize = (nesting_level == gNestingLevel)? len: 10; + if(--nesting_level < 0) return; + + for (size_t tid = 0; tid < globalWorkSize; ++tid) + { + if (tid < (globalWorkSize >> 1)) + { + ++referenceResults[tid]; + generate_reference_some_eq(referenceResults, len, nesting_level); + } + } +} + +static int check_some_eq(cl_int* results, cl_int len, cl_int nesting_level) +{ + int i, fail = -1; + std::vector referenceResults(len, 0); + generate_reference_some_eq(referenceResults, len, nesting_level); + + for(i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) { fail = i; break; } + } + + return fail; +} + +void generate_reference_some_diff(std::vector &referenceResults, cl_int len, cl_int nesting_level) +{ + size_t globalWorkSize = (nesting_level == gNestingLevel)? len: 10; + if(--nesting_level < 0) return; + + for (size_t tid = 0; tid < globalWorkSize; ++tid) + { + if (tid % 2) + { + ++referenceResults[tid]; + if (nesting_level >= tid) + { + generate_reference_some_diff(referenceResults, len, nesting_level); + } + } + } +} + +static int check_some_diff(cl_int* results, cl_int len, cl_int nesting_level) +{ + int i, fail = -1; + std::vector referenceResults(len, 0); + generate_reference_some_diff(referenceResults, len, nesting_level); + + for(i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) { fail = i; break; } + } + + return fail; +} + +void generate_reference_all_eq(std::vector &referenceResults, cl_int len, cl_int nesting_level) +{ + size_t globalWorkSize = (nesting_level == gNestingLevel)? len: 4; + if(--nesting_level < 0) return; + + for (size_t tid = 0; tid < globalWorkSize; ++tid) + { + ++referenceResults[tid]; + generate_reference_all_eq(referenceResults, len, nesting_level); + } +} + +static int check_all_eq(cl_int* results, cl_int len, cl_int nesting_level) +{ + int i, fail = -1; + std::vector referenceResults(len, 0); + generate_reference_all_eq(referenceResults, len, nesting_level); + + for(i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) { fail = i; break; } + } + + return fail; +} + +void generate_reference_all_diff(std::vector &referenceResults, cl_int len, cl_int nesting_level) +{ + size_t globalWorkSize = (nesting_level == gNestingLevel)? len: 10; + if(--nesting_level < 0) return; + + for (size_t tid = 0; tid < globalWorkSize; ++tid) + { + ++referenceResults[tid]; + if (nesting_level >= tid) + { + generate_reference_all_diff(referenceResults, len, nesting_level); + } + } +} + +static int check_all_diff(cl_int* results, cl_int len, cl_int nesting_level) +{ + int i, fail = -1; + std::vector referenceResults(len, 0); + generate_reference_all_diff(referenceResults, len, nesting_level); + + for(i = 0; i < len; ++i) + { + if (results[i] != referenceResults[i]) { fail = i; break; } + } + + return fail; +} + +static const kernel_src_check sources_nested_blocks[] = +{ + { KERNEL(enqueue_nested_blocks_single), check_single }, + { KERNEL(enqueue_nested_blocks_some_eq), check_some_eq }, + { KERNEL(enqueue_nested_blocks_some_diff), check_some_diff }, + { KERNEL(enqueue_nested_blocks_all_eq), check_all_eq }, + { KERNEL(enqueue_nested_blocks_all_diff), check_all_diff } +}; + +int test_enqueue_nested_blocks(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_uint i, k; + cl_int err_ret, res = 0; + clCommandQueueWrapper dev_queue; + const size_t MAX_GLOBAL_WORK_SIZE = MAX_GWS / 4; + cl_int kernel_results[MAX_GLOBAL_WORK_SIZE] = {0}; + + if(gWimpyMode) + { + gNestingLevel = 2; + vlog( "*** WARNING: Testing in Wimpy mode! ***\n" ); + vlog( "*** Wimpy mode is not sufficient to verify correctness. ***\n" ); + } + + size_t ret_len; + cl_uint max_queues = 1; + cl_uint maxQueueSize = 0; + err_ret = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, sizeof(maxQueueSize), &maxQueueSize, 0); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE) failed"); + + err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_ON_DEVICE_QUEUES, sizeof(max_queues), &max_queues, &ret_len); + test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_ON_DEVICE_QUEUES) failed"); + + cl_queue_properties queue_prop_def[] = + { + CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE|CL_QUEUE_ON_DEVICE|CL_QUEUE_ON_DEVICE_DEFAULT, + CL_QUEUE_SIZE, maxQueueSize, + 0 + }; + + dev_queue = clCreateCommandQueueWithProperties(context, device, queue_prop_def, &err_ret); + test_error(err_ret, "clCreateCommandQueueWithProperties(CL_QUEUE_DEVICE|CL_QUEUE_DEFAULT) failed"); + + kernel_arg args[] = + { + { sizeof(cl_int), &gNestingLevel } + }; + + size_t failCnt = 0; + for(k = 0; k < arr_size(sources_nested_blocks); ++k) + { + if (!gKernelName.empty() && gKernelName != sources_nested_blocks[k].src.kernel_name) + continue; + + log_info("Running '%s' kernel (%d of %d) ...\n", sources_nested_blocks[k].src.kernel_name, k + 1, arr_size(sources_nested_blocks)); + for(i = 0; i < MAX_GLOBAL_WORK_SIZE; ++i) kernel_results[i] = 0; + + err_ret = run_n_kernel_args(context, queue, sources_nested_blocks[k].src.lines, sources_nested_blocks[k].src.num_lines, sources_nested_blocks[k].src.kernel_name, 0, MAX_GLOBAL_WORK_SIZE, kernel_results, sizeof(kernel_results), arr_size(args), args); + if(check_error(err_ret, "'%s' kernel execution failed", sources_nested_blocks[k].src.kernel_name)) { res = -1; continue ; } + + //check results + int fail = sources_nested_blocks[k].check(kernel_results, MAX_GLOBAL_WORK_SIZE, gNestingLevel); + + if(check_error(err_ret, "'%s' kernel execution failed", sources_nested_blocks[k].src.kernel_name)) { ++failCnt; res = -1; continue; } + else if(fail >= 0 && check_error(-1, "'%s' kernel results validation failed: [%d] returned %d expected 0", sources_nested_blocks[k].src.kernel_name, fail, kernel_results[fail])) { ++failCnt; res = -1; continue; } + else log_info("'%s' kernel is OK.\n", sources_nested_blocks[k].src.kernel_name); + } + + if (failCnt > 0) + { + log_error("ERROR: %d of %d kernels failed.\n", failCnt, arr_size(sources_nested_blocks)); + } + + return res; +} + +#endif + diff --git a/test_conformance/device_execution/procs.h b/test_conformance/device_execution/procs.h new file mode 100644 index 00000000..53b6be41 --- /dev/null +++ b/test_conformance/device_execution/procs.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/testHarness.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern int test_device_info(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); +extern int test_device_queue(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); +extern int test_execute_block(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); +extern int test_enqueue_block(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); +extern int test_enqueue_nested_blocks(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); +extern int test_enqueue_wg_size(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); +extern int test_enqueue_flags(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); +extern int test_enqueue_multi_queue(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); +extern int test_host_multi_queue(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); +extern int test_enqueue_ndrange(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); +extern int test_host_queue_order(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_execution_stress(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); + +#ifdef __cplusplus +} +#endif + + diff --git a/test_conformance/device_execution/utils.cpp b/test_conformance/device_execution/utils.cpp new file mode 100644 index 00000000..b349b2d6 --- /dev/null +++ b/test_conformance/device_execution/utils.cpp @@ -0,0 +1,76 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" + +#include "utils.h" + +int run_single_kernel(cl_context context, cl_command_queue queue, const char** source, unsigned int num_lines, const char* kernel_name, void* results, size_t res_size) +{ + return run_single_kernel_args(context, queue, source, num_lines, kernel_name, results, res_size, 0, NULL); +} + +int run_single_kernel_args(cl_context context, cl_command_queue queue, const char** source, unsigned int num_lines, const char* kernel_name, void* results, size_t res_size, cl_uint num_args, kernel_arg* args) +{ + return run_n_kernel_args(context, queue, source, num_lines, kernel_name, 1, 1, results, res_size, num_args, args); +} + +int run_n_kernel_args(cl_context context, cl_command_queue queue, const char** source, unsigned int num_lines, const char* kernel_name, size_t local, size_t global, void* results, size_t res_size, cl_uint num_args, kernel_arg* args) +{ + cl_int err_ret, status; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper mem; + clEventWrapper event; + cl_uint i; + size_t ret_len; + + err_ret = create_single_kernel_helper_with_build_options(context, &program, &kernel, num_lines, source, kernel_name, "-cl-std=CL2.0"); + if(check_error(err_ret, "Create single kernel failed")) return -1; + + mem = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, res_size, results, &err_ret); + test_error(err_ret, "clCreateBuffer() failed"); + + err_ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), &mem); + if(check_error(err_ret, "clSetKernelArg(%d, %d, %p) for kernel: '%s' failed: %d", 0, (int)sizeof(cl_mem), &mem, kernel_name, err_ret)) return err_ret; + + for(i = 0; i < num_args; ++i) + { + err_ret = clSetKernelArg(kernel, i+1, args[i].size, args[i].ptr); + if(check_error(err_ret, "clSetKernelArg(%d, %d, %p) for kernel: '%s' failed: %d", (int)(i+1), (int)args[i].size, args[i].ptr, kernel_name, err_ret)) return err_ret; + } + + err_ret = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global, (local ? &local : NULL), 0, NULL, &event); + if(check_error(err_ret, "clEnqueueNDRangeKernel('%s', gws=%d, lws=%d) failed", kernel_name, (int)global, (int)local)) return err_ret; + + err_ret = clEnqueueReadBuffer(queue, mem, CL_TRUE, 0, res_size, results, 0, NULL, NULL); + test_error(err_ret, "clEnqueueReadBuffer() failed"); + + err_ret = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(status), &status, &ret_len); + test_error(err_ret, "clGetEventInfo() failed"); + +#if CL_COMPLETE != CL_SUCCESS +#error Fix me! +#endif + + // This hack is possible because CL_COMPLETE and CL_SUCCESS defined as 0x0 + if(check_error(status, "Kernel execution status %d", status)) return status; + + return 0; +} + diff --git a/test_conformance/device_execution/utils.h b/test_conformance/device_execution/utils.h new file mode 100644 index 00000000..02d7b6c7 --- /dev/null +++ b/test_conformance/device_execution/utils.h @@ -0,0 +1,73 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _utils_h_ +#define _utils_h_ + +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/mt19937.h" + +#include + +#ifndef CL_VERSION_2_0 +#define CL_VERSION_2_0 +#endif + +#define MAX_QUEUES 1000 // Max number of queues to test +#define MAX_GWS 256 // Global Work Size (must be multiple of 16) + + +#define NL "\n" +#define arr_size(a) (sizeof(a)/sizeof(a[0])) +#define check_error(errCode,msg,...) ((errCode != CL_SUCCESS) ? (log_error("ERROR: " msg "! (%s:%d)\n", ## __VA_ARGS__, __FILE__, __LINE__), 1) : 0) + +#define KERNEL(name) { arr_size(name), name, #name } + +extern std::string gKernelName; + +typedef struct +{ + unsigned int num_lines; + const char** lines; + const char* kernel_name; +} kernel_src; + +typedef int (*fn_check)(cl_int*, cl_int, cl_int); + +typedef struct +{ + kernel_src src; + fn_check check; +} kernel_src_check; + +typedef struct +{ + size_t size; + const void* ptr; +} kernel_arg; + +typedef struct +{ + kernel_src src; + cl_int dim; + cl_bool localSize; + cl_bool offset; +} kernel_src_dim_check; + +int run_single_kernel(cl_context context, cl_command_queue queue, const char** source, unsigned int num_lines, const char* kernel_name, void* results, size_t res_size); +int run_single_kernel_args(cl_context context, cl_command_queue queue, const char** source, unsigned int num_lines, const char* kernel_name, void* results, size_t res_size, cl_uint num_args, kernel_arg* args); +int run_n_kernel_args(cl_context context, cl_command_queue queue, const char** source, unsigned int num_lines, const char* kernel_name, size_t local, size_t global, void* results, size_t res_size, cl_uint num_args, kernel_arg* args); + +#endif diff --git a/test_conformance/device_partition/CMakeLists.txt b/test_conformance/device_partition/CMakeLists.txt new file mode 100644 index 00000000..c391e4c0 --- /dev/null +++ b/test_conformance/device_partition/CMakeLists.txt @@ -0,0 +1,17 @@ +set(MODULE_NAME DEVICE_PARTITION) + +set(${MODULE_NAME}_SOURCES + main.c + test_device_partition.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/genericThread.cpp + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/typeWrappers.cpp + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) +include(../CMakeCommon.txt) diff --git a/test_conformance/device_partition/Jamfile b/test_conformance/device_partition/Jamfile new file mode 100644 index 00000000..0e1d4d6a --- /dev/null +++ b/test_conformance/device_partition/Jamfile @@ -0,0 +1,32 @@ +project + : requirements + gcc:-xc++ + msvc:"/TP" + ; + +exe test_device_partition + : main.c + test_device_partition.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/genericThread.cpp + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/typeWrappers.cpp + : windows:../../test_common/harness/msvc9.c + ; + +install dist + : test_device_partition + : debug:$(DIST)/debug/tests/conformance/1.2/x86/device_partition + release:$(DIST)/release/tests/conformance/1.2/x86/device_partition + ; + +install dist + : test_device_partition + : debug:$(DIST)/debug/tests/conformance/1.2/x86_64/device_partition + release:$(DIST)/release/tests/conformance/1.2/x86_64/device_partition + 64 + ; diff --git a/test_conformance/device_partition/Makefile b/test_conformance/device_partition/Makefile new file mode 100644 index 00000000..493b0609 --- /dev/null +++ b/test_conformance/device_partition/Makefile @@ -0,0 +1,45 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + test_device_partition.cpp \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/genericThread.cpp \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/conversions.c \ + ../../test_common/harness/typeWrappers.cpp \ + ../../test_common/harness/msvc9.c +DEFINES = + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = $(abspath $(SRCS)) +HEADERS = procs.h testBase.h +TARGET = test_device_partition +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Os -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${RC_CFLAGS} ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/device_partition/main.c b/test_conformance/device_partition/main.c new file mode 100644 index 00000000..cb4173ec --- /dev/null +++ b/test_conformance/device_partition/main.c @@ -0,0 +1,60 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include "procs.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/mt19937.h" + +#if !defined(_WIN32) +#include +#endif + +basefn basefn_list[] = { + test_partition_equally, + test_partition_by_counts, + test_partition_by_affinity_domain_numa, + test_partition_by_affinity_domain_l4_cache, + test_partition_by_affinity_domain_l3_cache, + test_partition_by_affinity_domain_l2_cache, + test_partition_by_affinity_domain_l1_cache, + test_partition_by_affinity_domain_next_partitionable, + test_partition +}; + + +const char *basefn_names[] = { + "device_partition_equally", + "device_partition_by_counts", + "device_partition_by_affinity_domain_numa", + "device_partition_by_affinity_domain_l4_cache", + "device_partition_by_affinity_domain_l3_cache", + "device_partition_by_affinity_domain_l2_cache", + "device_partition_by_affinity_domain_l1_cache", + "device_partition_by_affinity_domain_next_partitionable", + "device_partition_all", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + +int main(int argc, const char *argv[]) +{ + return runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false, true, 0 ); +} diff --git a/test_conformance/device_partition/procs.h b/test_conformance/device_partition/procs.h new file mode 100644 index 00000000..0f9718f7 --- /dev/null +++ b/test_conformance/device_partition/procs.h @@ -0,0 +1,29 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/mt19937.h" + +extern int test_partition(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_partition_equally(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_partition_by_counts(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_partition_by_affinity_domain_numa(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_partition_by_affinity_domain_l4_cache(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_partition_by_affinity_domain_l3_cache(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_partition_by_affinity_domain_l2_cache(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_partition_by_affinity_domain_l1_cache(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_partition_by_affinity_domain_next_partitionable(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); diff --git a/test_conformance/device_partition/testBase.h b/test_conformance/device_partition/testBase.h new file mode 100644 index 00000000..5073b21f --- /dev/null +++ b/test_conformance/device_partition/testBase.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testBase_h +#define _testBase_h + +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +#endif // _testBase_h + + + diff --git a/test_conformance/device_partition/test_device_partition.cpp b/test_conformance/device_partition/test_device_partition.cpp new file mode 100644 index 00000000..bd012522 --- /dev/null +++ b/test_conformance/device_partition/test_device_partition.cpp @@ -0,0 +1,589 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/conversions.h" + +#include + +typedef long long int lld; +typedef long long unsigned llu; + +const char *test_kernels[] = { +"__kernel void kernelA(__global int *dst)\n" +"{\n" +"\n" +" dst[get_global_id(0)]*=3;\n" +"\n" +"}\n" +"__kernel void kernelB(__global int *dst)\n" +"{\n" +"\n" +" dst[get_global_id(0)]++;\n" +"\n" +"}\n" +}; + +#define TEST_SIZE 512 +#define MAX_QUEUES 1000 + +const char *printPartition(cl_device_partition_property partition) +{ + switch (partition) { + case (0): return ""; + case (CL_DEVICE_PARTITION_EQUALLY): return "CL_DEVICE_PARTITION_EQUALLY"; + case (CL_DEVICE_PARTITION_BY_COUNTS): return "CL_DEVICE_PARTITION_BY_COUNTS"; + case (CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN): return "CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN"; + default: return ""; + } // switch +} + +const char *printAffinity(cl_device_affinity_domain affinity) +{ + switch (affinity) { + case (0): return ""; + case (CL_DEVICE_AFFINITY_DOMAIN_NUMA): return "CL_DEVICE_AFFINITY_DOMAIN_NUMA"; + case (CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE): return "CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE"; + case (CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE): return "CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE"; + case (CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE): return "CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE"; + case (CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE): return "CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE"; + case (CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE): return "CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE"; + default: return ""; + } // switch +} +int create_single_kernel_helper( cl_context context, cl_program *outProgram, cl_kernel *outKernel, unsigned int numKernelLines, const char **kernelProgram, const char *kernelName, const cl_device_id *parentDevice ) +{ + int error = CL_SUCCESS; + + /* Create the program object from source */ + error = create_single_kernel_helper_create_program(context, outProgram, numKernelLines, kernelProgram); + if( *outProgram == NULL || error != CL_SUCCESS) + { + print_error( error, "clCreateProgramWithSource failed" ); + return error; + } + + /* Compile the program */ + int buildProgramFailed = 0; + int printedSource = 0; + error = clBuildProgram( *outProgram, ((parentDevice == NULL) ? 0 : 1), parentDevice, NULL, NULL, NULL ); + if (error != CL_SUCCESS) + { + unsigned int i; + print_error(error, "clBuildProgram failed"); + buildProgramFailed = 1; + printedSource = 1; + log_error( "Original source is: ------------\n" ); + for( i = 0; i < numKernelLines; i++ ) + log_error( "%s", kernelProgram[ i ] ); + } + + // Verify the build status on all devices + cl_uint deviceCount = 0; + error = clGetProgramInfo( *outProgram, CL_PROGRAM_NUM_DEVICES, sizeof( deviceCount ), &deviceCount, NULL ); + if (error != CL_SUCCESS) { + print_error(error, "clGetProgramInfo CL_PROGRAM_NUM_DEVICES failed"); + return error; + } + + if (deviceCount == 0) { + log_error("No devices found for program.\n"); + return -1; + } + + cl_device_id *devices = (cl_device_id*) malloc( deviceCount * sizeof( cl_device_id ) ); + if( NULL == devices ) + return -1; + memset( devices, 0, deviceCount * sizeof( cl_device_id )); + error = clGetProgramInfo( *outProgram, CL_PROGRAM_DEVICES, sizeof( cl_device_id ) * deviceCount, devices, NULL ); + if (error != CL_SUCCESS) { + print_error(error, "clGetProgramInfo CL_PROGRAM_DEVICES failed"); + free( devices ); + return error; + } + + cl_uint z; + for( z = 0; z < deviceCount; z++ ) + { + char deviceName[4096] = ""; + error = clGetDeviceInfo(devices[z], CL_DEVICE_NAME, sizeof( deviceName), deviceName, NULL); + if (error != CL_SUCCESS || deviceName[0] == '\0') { + log_error("Device \"%d\" failed to return a name\n", z); + print_error(error, "clGetDeviceInfo CL_DEVICE_NAME failed"); + } + + cl_build_status buildStatus; + error = clGetProgramBuildInfo(*outProgram, devices[z], CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL); + if (error != CL_SUCCESS) { + print_error(error, "clGetProgramBuildInfo CL_PROGRAM_BUILD_STATUS failed"); + free( devices ); + return error; + } + + if (buildStatus != CL_BUILD_SUCCESS || buildProgramFailed) { + char log[10240] = ""; + if (buildStatus == CL_BUILD_SUCCESS && buildProgramFailed) log_error("clBuildProgram returned an error, but buildStatus is marked as CL_BUILD_SUCCESS.\n"); + + char statusString[64] = ""; + if (buildStatus == (cl_build_status)CL_BUILD_SUCCESS) + sprintf(statusString, "CL_BUILD_SUCCESS"); + else if (buildStatus == (cl_build_status)CL_BUILD_NONE) + sprintf(statusString, "CL_BUILD_NONE"); + else if (buildStatus == (cl_build_status)CL_BUILD_ERROR) + sprintf(statusString, "CL_BUILD_ERROR"); + else if (buildStatus == (cl_build_status)CL_BUILD_IN_PROGRESS) + sprintf(statusString, "CL_BUILD_IN_PROGRESS"); + else + sprintf(statusString, "UNKNOWN (%d)", buildStatus); + + if (buildStatus != CL_BUILD_SUCCESS) log_error("Build not successful for device \"%s\", status: %s\n", deviceName, statusString); + error = clGetProgramBuildInfo( *outProgram, devices[z], CL_PROGRAM_BUILD_LOG, sizeof(log), log, NULL ); + if (error != CL_SUCCESS || log[0]=='\0'){ + log_error("Device %d (%s) failed to return a build log\n", z, deviceName); + if (error) { + print_error(error, "clGetProgramBuildInfo CL_PROGRAM_BUILD_LOG failed"); + free( devices ); + return error; + } else { + log_error("clGetProgramBuildInfo returned an empty log.\n"); + free( devices ); + return -1; + } + } + // In this case we've already printed out the code above. + if (!printedSource) + { + unsigned int i; + log_error( "Original source is: ------------\n" ); + for( i = 0; i < numKernelLines; i++ ) + log_error( "%s", kernelProgram[ i ] ); + printedSource = 1; + } + log_error( "Build log for device \"%s\" is: ------------\n", deviceName ); + log_error( "%s\n", log ); + log_error( "\n----------\n" ); + free( devices ); + return -1; + } + } + + /* And create a kernel from it */ + *outKernel = clCreateKernel( *outProgram, kernelName, &error ); + if( *outKernel == NULL || error != CL_SUCCESS) + { + print_error( error, "Unable to create kernel" ); + free( devices ); + return error; + } + + free( devices ); + return 0; +} + +template +class AutoDestructArray +{ +public: + AutoDestructArray(T* arr) : m_arr(arr) {} + ~AutoDestructArray() { if (m_arr) delete [] m_arr; } + +private: + T* m_arr; +}; + +int test_device_set(size_t deviceCount, size_t queueCount, cl_device_id *devices, int num_elements, cl_device_id *parentDevice = NULL) +{ + int error; + clContextWrapper context; + clProgramWrapper program; + clKernelWrapper kernels[2]; + clMemWrapper stream; + clCommandQueueWrapper queues[MAX_QUEUES]; + size_t threads[1], localThreads[1]; + int data[TEST_SIZE]; + int outputData[TEST_SIZE]; + int expectedResults[TEST_SIZE]; + int *expectedResultsOneDeviceArray = new int[deviceCount * TEST_SIZE]; + int **expectedResultsOneDevice = (int**)alloca(sizeof(int**) * deviceCount); + size_t i; + AutoDestructArray autoDestruct(expectedResultsOneDeviceArray); + + for (i=0; i MAX_QUEUES) { + log_error("Number of queues (%ld) is greater than the number for which the test was written (%d).", queueCount, MAX_QUEUES); + return -1; + } + + log_info("Testing with %ld queues on %ld devices, %ld kernel executions.\n", queueCount, deviceCount, queueCount*num_elements/TEST_SIZE); + + for (i=0; i properties_t; + properties_t supportedProps( 3 ); // only 3 types defined in the spec (but implementation can define more) + size_t const propSize = sizeof( cl_device_partition_property ); // Size of one property in bytes. + size_t size; // size of all properties in bytes. + cl_int err; + size = 0; + err = clGetDeviceInfo( parentDevice, CL_DEVICE_PARTITION_PROPERTIES, 0, NULL, & size ); + if ( err == CL_SUCCESS ) { + if ( size % propSize != 0 ) { + log_error( "ERROR: clGetDeviceInfo: Bad size of returned partition properties (%llu), it must me a multiply of partition property size (%llu)\n", llu( size ), llu( propSize ) ); + return -1; + } + supportedProps.resize( size / propSize ); + size = 0; + err = clGetDeviceInfo( parentDevice, CL_DEVICE_PARTITION_PROPERTIES, supportedProps.size() * propSize, & supportedProps.front(), & size ); + test_error_ret( err, "Unable to get device partition properties (2)", -1 ); + } else if ( err == CL_INVALID_VALUE ) { + log_error( "ERROR: clGetDeviceInfo: CL_DEVICE_PARTITION_PROPERTIES is not supported.\n" ); + return -1; + } else { + test_error_ret( err, "Unable to get device partition properties (1)", -1 ); + }; + for ( int i = 0; i < supportedProps.size(); i++) + { + if (supportedProps[i] == partitionType) + { + if (partitionType == CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN) + { + cl_device_affinity_domain supportedAffinityDomain; + err = clGetDeviceInfo(parentDevice, CL_DEVICE_PARTITION_AFFINITY_DOMAIN, sizeof(supportedAffinityDomain), &supportedAffinityDomain, NULL); + test_error( err, "Unable to get supported affinity domains" ); + if (supportedAffinityDomain & affinityDomain) + return 0; + } + else + return 0; + } + } + + return -1; +} + +int test_partition_of_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, cl_device_partition_property *partition_type, + cl_uint starting_property, cl_uint ending_property) +{ + cl_uint maxComputeUnits; + cl_uint maxSubDevices; // maximal number of sub-devices that can be created in one call to clCreateSubDevices + int err = 0; + + if (init_device_partition_test(deviceID, maxComputeUnits, maxSubDevices) != 0) + return -1; + + if (maxComputeUnits <= 1) + return 0; + // confirm that this devices reports how it was partitioned + if (partition_type != NULL) + { // if we're not the root device + size_t psize; + err = clGetDeviceInfo(deviceID, CL_DEVICE_PARTITION_TYPE, 0, NULL, &psize); + test_error( err, "Unable to get CL_DEVICE_PARTITION_TYPE" ); + cl_device_partition_property *properties_returned = (cl_device_partition_property *)alloca(psize); + err = clGetDeviceInfo(deviceID, CL_DEVICE_PARTITION_TYPE, psize, (void *) properties_returned, NULL); + test_error( err, "Unable to get CL_DEVICE_PARTITION_TYPE" ); + + // test returned type + for (cl_uint i = 0;i < psize / sizeof(cl_device_partition_property);i++) { + if (properties_returned[i] != partition_type[i]) { + if (!(partition_type[0] == CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN && + i == 1 && partition_type[1] == CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE && + (properties_returned[1] == CL_DEVICE_AFFINITY_DOMAIN_NUMA || + properties_returned[1] == CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE || + properties_returned[1] == CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE || + properties_returned[1] == CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE || + properties_returned[1] == CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE))) { + log_error("properties_returned[%d] 0x%x != 0x%x partition_type[%d].", i, properties_returned[i], partition_type[i], i); + return -1; + } + } + } // for + } + +#define PROPERTY_TYPES 8 + cl_device_partition_property partitionProp[PROPERTY_TYPES][5] = { + { CL_DEVICE_PARTITION_EQUALLY, maxComputeUnits / 2, 0, 0, 0 } , + { CL_DEVICE_PARTITION_BY_COUNTS, 1, maxComputeUnits - 1, CL_DEVICE_PARTITION_BY_COUNTS_LIST_END, 0 } , + { CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN, CL_DEVICE_AFFINITY_DOMAIN_NUMA, 0, 0, 0 } , + { CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN, CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE, 0, 0, 0 } , + { CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN, CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE, 0, 0, 0 } , + { CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN, CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE, 0, 0, 0 } , + { CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN, CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE, 0, 0, 0 } , + { CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN, CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE, 0, 0, 0 } + }; + + // loop thru each type, creating sub-devices for each type + for (cl_uint i = starting_property;i < ending_property;i++) { + + if (test_device_partition_type_support(deviceID, partitionProp[i][0], partitionProp[i][1]) != 0) + { + if (partitionProp[i][0] == CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN) + { + log_info( "Device partition type \"%s\" \"%s\" is not supported on device %p. Skipping test...\n", + printPartition(partitionProp[i][0]), + printAffinity(partitionProp[i][1]), deviceID); + } + else + { + log_info( "Device partition type \"%s\" is not supported on device %p. Skipping test...\n", + printPartition(partitionProp[i][0]), deviceID); + } + continue; + } + + if (partitionProp[i][0] == CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN) + { + log_info("Testing on device %p partition type \"%s\" \"%s\"\n", deviceID, printPartition(partitionProp[i][0]), + printAffinity(partitionProp[i][1])); + } + else + { + log_info("Testing on device %p partition type \"%s\" (%d,%d)\n", deviceID, printPartition(partitionProp[i][0]), + partitionProp[i][1], partitionProp[i][2]); + } + + cl_uint deviceCount; + + // how many sub-devices can we create? + err = clCreateSubDevices(deviceID, partitionProp[i], 0, NULL, &deviceCount); + if ( err == CL_DEVICE_PARTITION_FAILED ) { + log_info( "The device %p could not be further partitioned.\n", deviceID ); + continue; + } + test_error( err, "Failed to get number of sub-devices" ); + + // get the list of subDevices + // create room for 1 more device_id, so that we can put the parent device in there. + cl_device_id *subDevices = (cl_device_id*)alloca(sizeof(cl_device_id) * (deviceCount + 1)); + err = clCreateSubDevices(deviceID, partitionProp[i], deviceCount, subDevices, &deviceCount); + test_error( err, "Actual creation of sub-devices failed" ); + + log_info("Testing on all devices in context\n"); + err = test_device_set(deviceCount, deviceCount, subDevices, num_elements); + if (err == 0) + { + log_info("Testing on a parent device for context\n"); + + // add the parent device + subDevices[deviceCount] = deviceID; + err = test_device_set(deviceCount + 1, deviceCount, subDevices, num_elements, &deviceID); + } + if (err != 0) + { + printf("error! returning %d\n",err); + return err; + } + + // now, recurse and test the FIRST of these sub-devices, to make sure it can be further partitioned + err = test_partition_of_device(subDevices[0], context, queue, num_elements, partitionProp[i], starting_property, ending_property); + if (err != 0) + { + printf("error! returning %d\n",err); + return err; + } + + for (cl_uint j=0;j < deviceCount;j++) + { + err = clReleaseDevice(subDevices[j]); + test_error( err, "\n Releasing sub-device failed \n" ); + } + + } // for + + log_info("Testing on all device %p finished\n", deviceID); + return 0; +} + + +int test_partition_equally(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_partition_of_device(deviceID, context, queue, num_elements, NULL, 0, 1); +} + +int test_partition_by_counts(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_partition_of_device(deviceID, context, queue, num_elements, NULL, 1, 2); +} + +int test_partition_by_affinity_domain_numa(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_partition_of_device(deviceID, context, queue, num_elements, NULL, 2, 3); +} + +int test_partition_by_affinity_domain_l4_cache(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_partition_of_device(deviceID, context, queue, num_elements, NULL, 3, 4); +} + +int test_partition_by_affinity_domain_l3_cache(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_partition_of_device(deviceID, context, queue, num_elements, NULL, 4, 5); +} + +int test_partition_by_affinity_domain_l2_cache(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_partition_of_device(deviceID, context, queue, num_elements, NULL, 5, 6); +} + +int test_partition_by_affinity_domain_l1_cache(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_partition_of_device(deviceID, context, queue, num_elements, NULL, 6, 7); +} + +int test_partition_by_affinity_domain_next_partitionable(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_partition_of_device(deviceID, context, queue, num_elements, NULL, 7, 8); +} + +int test_partition(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_partition_of_device(deviceID, context, queue, num_elements, NULL, 0, 8); +} diff --git a/test_conformance/device_timer/CMakeLists.txt b/test_conformance/device_timer/CMakeLists.txt new file mode 100644 index 00000000..b37f6382 --- /dev/null +++ b/test_conformance/device_timer/CMakeLists.txt @@ -0,0 +1,13 @@ +set(MODULE_NAME DEVICE_TIMER) + +set(${MODULE_NAME}_SOURCES + main.c + test_device_timer.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/parseParameters.cpp + ../../test_common/harness/msvc9.c +) + +include(../CMakeCommon.txt) diff --git a/test_conformance/device_timer/main.c b/test_conformance/device_timer/main.c new file mode 100644 index 00000000..c3cb2611 --- /dev/null +++ b/test_conformance/device_timer/main.c @@ -0,0 +1,45 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" +#include +#include +#include +#include "../../test_common/harness/testHarness.h" + +#if !defined(_WIN32) +#include +#endif + +#include "procs.h" + +basefn basefn_list[] = { + test_timer_resolution_queries, + test_device_and_host_timers +}; + +const char *basefn_names[] = { + "test_timer_resolution_queries", + "test_device_and_host_timers", + "all" +}; + +size_t num_fns = sizeof(basefn_names)/sizeof(basefn_names[0]); + +int main(int argc, const char *argv[]) +{ + return runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false, false, 0 ); +} + diff --git a/test_conformance/device_timer/procs.h b/test_conformance/device_timer/procs.h new file mode 100644 index 00000000..8157ec7f --- /dev/null +++ b/test_conformance/device_timer/procs.h @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef __PROCS_H__ +#define __PROCS_H__ + +extern int test_device_and_host_timers(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements); + +extern int test_timer_resolution_queries(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements); +#endif // #ifndef __PROCS_H__ diff --git a/test_conformance/device_timer/test_device_timer.c b/test_conformance/device_timer/test_device_timer.c new file mode 100644 index 00000000..7b171c02 --- /dev/null +++ b/test_conformance/device_timer/test_device_timer.c @@ -0,0 +1,165 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/compat.h" + +#if !defined(_WIN32) + #include "unistd.h" // For "sleep" +#endif + +#define ALLOWED_ERROR 0.005f + +int test_device_and_host_timers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int errors = 0; + cl_int result = CL_SUCCESS; + cl_ulong deviceStartTime, deviceEndTime, deviceTimeDiff; + cl_ulong hostStartTime, hostEndTime, hostTimeDiff; + cl_ulong hostOnlyStartTime, hostOnlyEndTime, hostOnlyTimeDiff; + cl_ulong observedDiff; + cl_ulong allowedDiff; + + result = clGetDeviceAndHostTimer(deviceID, &deviceStartTime, &hostStartTime); + if (result != CL_SUCCESS) { + log_error("clGetDeviceAndHostTimer failed with error %s\n", IGetErrorString(result)); + errors++; + goto End; + } + + result = clGetHostTimer(deviceID, &hostOnlyStartTime); + if (result != CL_SUCCESS) { + log_error("clGetHostTimer failed with error %s\n", IGetErrorString(result)); + errors++; + goto End; + } + + // Wait for a while to allow the timers to increment substantially. + sleep(5); + + result = clGetDeviceAndHostTimer(deviceID, &deviceEndTime, &hostEndTime); + if (result != CL_SUCCESS) { + log_error("clGetDeviceAndHostTimer failed with error %s\n", IGetErrorString(result)); + errors++; + goto End; + } + + result = clGetHostTimer(deviceID, &hostOnlyEndTime); + if (result != CL_SUCCESS) { + log_error("clGetHostTimer failed with error %s\n", IGetErrorString(result)); + errors++; + goto End; + } + + deviceTimeDiff = deviceEndTime - deviceStartTime ; + hostTimeDiff = hostEndTime - hostStartTime ; + hostOnlyTimeDiff = hostOnlyEndTime - hostOnlyStartTime; + + log_info("Checking results from clGetDeviceAndHostTimer ...\n"); + + if (deviceEndTime <= deviceStartTime) { + log_error("Device timer is not monotonically increasing.\n"); + log_error(" deviceStartTime: %lu, deviceEndTime: %lu\n", deviceStartTime, deviceEndTime); + errors++; + } + + if (hostEndTime <= hostStartTime) { + log_error("Error: Host timer is not monotonically increasing.\n"); + log_error(" hostStartTime: %lu, hostEndTime: %lu\n", hostStartTime, hostEndTime); + errors++; + } + + if (deviceTimeDiff > hostTimeDiff) { + observedDiff = deviceTimeDiff - hostTimeDiff; + allowedDiff = (cl_ulong)(hostTimeDiff * ALLOWED_ERROR); + } + else { + observedDiff = hostTimeDiff - deviceTimeDiff; + allowedDiff = (cl_ulong)(deviceTimeDiff * ALLOWED_ERROR); + } + + if (observedDiff > allowedDiff) { + log_error("Error: Device and host timers did not increase by same amount\n"); + log_error(" Observed difference between timers %lu (max allowed %lu).\n", observedDiff, allowedDiff); + errors++; + } + + log_info("Cross-checking results with clGetHostTimer ...\n"); + + if (hostOnlyEndTime <= hostOnlyStartTime) { + log_error("Error: Host timer is not monotonically increasing.\n"); + log_error(" hostStartTime: %lu, hostEndTime: %lu\n", hostOnlyStartTime, hostOnlyEndTime); + errors++; + } + + if (hostOnlyStartTime < hostStartTime) { + log_error("Error: Host start times do not correlate.\n"); + log_error("clGetDeviceAndHostTimer was called before clGetHostTimer but timers are not in that order.\n"); + log_error(" clGetDeviceAndHostTimer: %lu, clGetHostTimer: %lu\n", hostStartTime, hostOnlyStartTime); + errors++; + } + + if (hostOnlyEndTime < hostEndTime) { + log_error("Error: Host end times do not correlate.\n"); + log_error("clGetDeviceAndHostTimer was called before clGetHostTimer but timers are not in that order.\n"); + log_error(" clGetDeviceAndHostTimer: %lu, clGetHostTimer: %lu\n", hostEndTime, hostOnlyEndTime); + errors++; + } + +End: + return errors; +} + +int test_timer_resolution_queries(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int errors = 0; + cl_int result = CL_SUCCESS; + cl_platform_id platform = 0; + cl_ulong deviceTimerResolution = 0; + cl_ulong hostTimerResolution = 0; + + result = clGetDeviceInfo(deviceID, CL_DEVICE_PLATFORM, sizeof(platform), &platform, NULL); + if (result != CL_SUCCESS) { + log_error("clGetDeviceInfo(CL_DEVICE_PLATFORM) failed with error %s.\n", IGetErrorString(result)); + errors++; + } + + result = clGetDeviceInfo(deviceID, CL_DEVICE_PROFILING_TIMER_RESOLUTION, sizeof(deviceTimerResolution), &deviceTimerResolution, NULL); + if (result != CL_SUCCESS) { + log_error("clGetDeviceInfo(CL_DEVICE_PROFILING_TIMER_RESOLUTION) failed with error %s.\n", IGetErrorString(result)); + errors++; + } + else { + log_info("CL_DEVICE_PROFILING_TIMER_RESOLUTION == %lu nanoseconds\n", deviceTimerResolution); + } + + if (platform) { + result = clGetPlatformInfo(platform, CL_PLATFORM_HOST_TIMER_RESOLUTION, sizeof(hostTimerResolution), &hostTimerResolution, NULL); + if (result != CL_SUCCESS) { + log_error("clGetPlatformInfo(CL_PLATFORM_HOST_TIMER_RESOLUTION) failed with error %s.\n", IGetErrorString(result)); + errors++; + } + else { + log_info("CL_PLATFORM_HOST_TIMER_RESOLUTION == %lu nanoseconds\n", hostTimerResolution); + } + } + else { + log_error("Could not find platform ID to query CL_PLATFORM_HOST_TIMER_RESOLUTION\n"); + } + + return errors; +} diff --git a/test_conformance/events/CMakeLists.txt b/test_conformance/events/CMakeLists.txt new file mode 100644 index 00000000..88f7d319 --- /dev/null +++ b/test_conformance/events/CMakeLists.txt @@ -0,0 +1,25 @@ +set(MODULE_NAME EVENTS) + +set(${MODULE_NAME}_SOURCES + main.c + test_events.cpp + test_event_dependencies.cpp + test_waitlists.cpp + test_userevents.cpp + test_userevents_multithreaded.cpp + action_classes.cpp + test_callbacks.cpp + ../../test_common/harness/genericThread.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/typeWrappers.cpp + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/ThreadPool.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) diff --git a/test_conformance/events/Jamfile b/test_conformance/events/Jamfile new file mode 100644 index 00000000..45979f76 --- /dev/null +++ b/test_conformance/events/Jamfile @@ -0,0 +1,18 @@ +project + : requirements + gcc:-xc++ + msvc:"/TP" + ; + +exe test_events + : main.c + test_event_dependencies.cpp + test_events.cpp + test_waitlists.cpp + ; + +install dist + : test_events + : debug:$(DIST)/debug/tests/test_conformance/events + release:$(DIST)/release/tests/test_conformance/events + ; diff --git a/test_conformance/events/Makefile b/test_conformance/events/Makefile new file mode 100644 index 00000000..c2025261 --- /dev/null +++ b/test_conformance/events/Makefile @@ -0,0 +1,51 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + test_events.cpp \ + test_event_dependencies.cpp \ + test_userevents.cpp \ + test_waitlists.cpp \ + test_callbacks.cpp \ + action_classes.cpp \ + test_userevents_multithreaded.cpp \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/genericThread.cpp \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/typeWrappers.cpp \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/conversions.c \ + ../../test_common/harness/ThreadPool.c \ + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +HEADERS = +TARGET = test_events +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/events/action_classes.cpp b/test_conformance/events/action_classes.cpp new file mode 100644 index 00000000..122c21ff --- /dev/null +++ b/test_conformance/events/action_classes.cpp @@ -0,0 +1,658 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "action_classes.h" + +#pragma mark -------------------- Base Action Class ------------------------- + +const cl_uint BufferSizeReductionFactor = 20; + +cl_int Action::IGetPreferredImageSize2D( cl_device_id device, size_t &outWidth, size_t &outHeight ) +{ + cl_ulong maxAllocSize; + size_t maxWidth, maxHeight; + cl_int error; + + + // Get the largest possible buffer we could allocate + error = clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + test_error( error, "Unable to get device config" ); + + // Create something of a decent size + if( maxWidth * maxHeight * 4 > maxAllocSize / BufferSizeReductionFactor ) + { + float rootSize = sqrtf( (float)( maxAllocSize / ( BufferSizeReductionFactor * 4 ) ) ); + + if( (size_t)rootSize > maxWidth ) + outWidth = maxWidth; + else + outWidth = (size_t)rootSize; + outHeight = (size_t)( ( maxAllocSize / ( BufferSizeReductionFactor * 4 ) ) / outWidth ); + if( outHeight > maxHeight ) + outHeight = maxHeight; + } + else + { + outWidth = maxWidth; + outHeight = maxHeight; + } + + outWidth /=2; + outHeight /=2; + + if (outWidth > 2048) + outWidth = 2048; + if (outHeight > 2048) + outHeight = 2048; + log_info("\tImage size: %d x %d (%gMB)\n", (int)outWidth, (int)outHeight, + (double)((int)outWidth*(int)outHeight*4)/(1024.0*1024.0)); + return CL_SUCCESS; +} + +cl_int Action::IGetPreferredImageSize3D( cl_device_id device, size_t &outWidth, size_t &outHeight, size_t &outDepth ) +{ + cl_ulong maxAllocSize; + size_t maxWidth, maxHeight, maxDepth; + cl_int error; + + + // Get the largest possible buffer we could allocate + error = clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL ); + test_error( error, "Unable to get device config" ); + + // Create something of a decent size + if( (cl_ulong)maxWidth * maxHeight * maxDepth > maxAllocSize / ( BufferSizeReductionFactor * 4 ) ) + { + float rootSize = cbrtf( (float)( maxAllocSize / ( BufferSizeReductionFactor * 4 ) ) ); + + if( (size_t)rootSize > maxWidth ) + outWidth = maxWidth; + else + outWidth = (size_t)rootSize; + if( (size_t)rootSize > maxHeight ) + outHeight = maxHeight; + else + outHeight = (size_t)rootSize; + outDepth = (size_t)( ( maxAllocSize / ( BufferSizeReductionFactor * 4 ) ) / ( outWidth * outHeight ) ); + if( outDepth > maxDepth ) + outDepth = maxDepth; + } + else + { + outWidth = maxWidth; + outHeight = maxHeight; + outDepth = maxDepth; + } + + outWidth /=2; + outHeight /=2; + outDepth /=2; + + if (outWidth > 512) + outWidth = 512; + if (outHeight > 512) + outHeight = 512; + if (outDepth > 512) + outDepth = 512; + log_info("\tImage size: %d x %d x %d (%gMB)\n", (int)outWidth, (int)outHeight, (int)outDepth, + (double)((int)outWidth*(int)outHeight*(int)outDepth*4)/(1024.0*1024.0)); + + return CL_SUCCESS; +} + +#pragma mark -------------------- Execution Sub-Classes ------------------------- + +cl_int NDRangeKernelAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + const char *long_kernel[] = { + "__kernel void sample_test(__global float *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " int i;\n" + "\n" + " for( i = 0; i < 100000; i++ )\n" + " {\n" + " dst[tid] = (int)src[tid] * 3;\n" + " }\n" + "\n" + "}\n" }; + + size_t threads[1] = { 1000 }; + int error; + + if( create_single_kernel_helper( context, &mProgram, &mKernel, 1, long_kernel, "sample_test" ) ) + { + return -1; + } + + error = get_max_common_work_group_size( context, mKernel, threads[0], &mLocalThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + mStreams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 1000, NULL, &error ); + test_error( error, "Creating test array failed" ); + mStreams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 1000, NULL, &error ); + test_error( error, "Creating test array failed" ); + + /* Set the arguments */ + error = clSetKernelArg( mKernel, 0, sizeof( mStreams[0] ), &mStreams[0] ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( mKernel, 1, sizeof( mStreams[1] ), &mStreams[1] ); + test_error( error, "Unable to set kernel arguments" ); + + return CL_SUCCESS; +} + +cl_int NDRangeKernelAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) +{ + size_t threads[1] = { 1000 }; + cl_int error = clEnqueueNDRangeKernel( queue, mKernel, 1, NULL, threads, mLocalThreads, numWaits, waits, outEvent ); + test_error( error, "Unable to execute kernel" ); + + return CL_SUCCESS; +} + +#pragma mark -------------------- Buffer Sub-Classes ------------------------- + +cl_int BufferAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue, bool allocate ) +{ + cl_int error; + cl_ulong maxAllocSize; + + + // Get the largest possible buffer we could allocate + error = clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + + // Don't create a buffer quite that big, just so we have some space left over for other work + mSize = (size_t)( maxAllocSize / BufferSizeReductionFactor ); + + // Cap at 128M so tests complete in a reasonable amount of time. + if (mSize > 128 << 20) + mSize = 128 << 20; + + mSize /=2; + + log_info("\tBuffer size: %gMB\n", (double)mSize/(1024.0*1024.0)); + + mBuffer = clCreateBuffer( context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, mSize, NULL, &error ); + test_error( error, "Unable to create buffer to test against" ); + + mOutBuffer = malloc( mSize ); + if( mOutBuffer == NULL ) + { + log_error( "ERROR: Unable to allocate temp buffer (out of memory)\n" ); + return CL_OUT_OF_RESOURCES; + } + + return CL_SUCCESS; +} + +cl_int ReadBufferAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + return BufferAction::Setup( device, context, queue, true ); +} + +cl_int ReadBufferAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) +{ + cl_int error = clEnqueueReadBuffer( queue, mBuffer, CL_FALSE, 0, mSize, mOutBuffer, numWaits, waits, outEvent ); + test_error( error, "Unable to enqueue buffer read" ); + + return CL_SUCCESS; +} + +cl_int WriteBufferAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + return BufferAction::Setup( device, context, queue, true ); +} + +cl_int WriteBufferAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) +{ + cl_int error = clEnqueueWriteBuffer( queue, mBuffer, CL_FALSE, 0, mSize, mOutBuffer, numWaits, waits, outEvent ); + test_error( error, "Unable to enqueue buffer write" ); + + return CL_SUCCESS; +} + +MapBufferAction::~MapBufferAction() +{ + if (mQueue) + clEnqueueUnmapMemObject( mQueue, mBuffer, mMappedPtr, 0, NULL, NULL ); +} + +cl_int MapBufferAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + return BufferAction::Setup( device, context, queue, false ); +} + +cl_int MapBufferAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) +{ + cl_int error; + mQueue = queue; + mMappedPtr = clEnqueueMapBuffer( queue, mBuffer, CL_FALSE, CL_MAP_READ, 0, mSize, numWaits, waits, outEvent, &error ); + test_error( error, "Unable to enqueue buffer map" ); + + return CL_SUCCESS; +} + +cl_int UnmapBufferAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + cl_int error = BufferAction::Setup( device, context, queue, false ); + if( error != CL_SUCCESS ) + return error; + + mMappedPtr = clEnqueueMapBuffer( queue, mBuffer, CL_TRUE, CL_MAP_READ, 0, mSize, 0, NULL, NULL, &error ); + test_error( error, "Unable to enqueue buffer map" ); + + return CL_SUCCESS; +} + +cl_int UnmapBufferAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) +{ + cl_int error = clEnqueueUnmapMemObject( queue, mBuffer, mMappedPtr, numWaits, waits, outEvent ); + test_error( error, "Unable to enqueue buffer unmap" ); + + return CL_SUCCESS; +} + + +#pragma mark -------------------- Read/Write Image Classes ------------------------- + +cl_int ReadImage2DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + cl_int error; + + + if( ( error = IGetPreferredImageSize2D( device, mWidth, mHeight ) ) ) + return error; + + cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 }; + mImage = create_image_2d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, 0, NULL, &error ); + + test_error( error, "Unable to create image to test against" ); + + mOutput = malloc( mWidth * mHeight * 4 ); + if( mOutput == NULL ) + { + log_error( "ERROR: Unable to allocate buffer: out of memory\n" ); + return CL_OUT_OF_RESOURCES; + } + + return CL_SUCCESS; +} + +cl_int ReadImage2DAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) +{ + size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, 1 }; + + cl_int error = clEnqueueReadImage( queue, mImage, CL_FALSE, origin, region, 0, 0, mOutput, numWaits, waits, outEvent ); + test_error( error, "Unable to enqueue image read" ); + + return CL_SUCCESS; +} + +cl_int ReadImage3DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + cl_int error; + + + if( ( error = IGetPreferredImageSize3D( device, mWidth, mHeight, mDepth ) ) ) + return error; + + cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 }; + mImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + mOutput = malloc( mWidth * mHeight * mDepth * 4 ); + if( mOutput == NULL ) + { + log_error( "ERROR: Unable to allocate buffer: out of memory\n" ); + return CL_OUT_OF_RESOURCES; + } + + return CL_SUCCESS; +} + +cl_int ReadImage3DAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) +{ + size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, mDepth }; + + cl_int error = clEnqueueReadImage( queue, mImage, CL_FALSE, origin, region, 0, 0, mOutput, numWaits, waits, outEvent ); + test_error( error, "Unable to enqueue image read" ); + + return CL_SUCCESS; +} + +cl_int WriteImage2DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + cl_int error; + + + if( ( error = IGetPreferredImageSize2D( device, mWidth, mHeight ) ) ) + return error; + + cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 }; + mImage = create_image_2d( context, CL_MEM_WRITE_ONLY, &format, mWidth, mHeight, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + mOutput = malloc( mWidth * mHeight * 4 ); + if( mOutput == NULL ) + { + log_error( "ERROR: Unable to allocate buffer: out of memory\n" ); + return CL_OUT_OF_RESOURCES; + } + + return CL_SUCCESS; +} + +cl_int WriteImage2DAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) +{ + size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, 1 }; + + cl_int error = clEnqueueWriteImage( queue, mImage, CL_FALSE, origin, region, 0, 0, mOutput, numWaits, waits, outEvent ); + test_error( error, "Unable to enqueue image write" ); + + return CL_SUCCESS; +} + +cl_int WriteImage3DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + cl_int error; + + + if( ( error = IGetPreferredImageSize3D( device, mWidth, mHeight, mDepth ) ) ) + return error; + + cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 }; + mImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + mOutput = malloc( mWidth * mHeight * mDepth * 4 ); + if( mOutput == NULL ) + { + log_error( "ERROR: Unable to allocate buffer: out of memory\n" ); + return CL_OUT_OF_RESOURCES; + } + + return CL_SUCCESS; +} + +cl_int WriteImage3DAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) +{ + size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, mDepth }; + + cl_int error = clEnqueueWriteImage( queue, mImage, CL_FALSE, origin, region, 0, 0, mOutput, numWaits, waits, outEvent ); + test_error( error, "Unable to enqueue image write" ); + + return CL_SUCCESS; +} + +#pragma mark -------------------- Copy Image Classes ------------------------- + +cl_int CopyImageAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) +{ + size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, mDepth }; + + cl_int error = clEnqueueCopyImage( queue, mSrcImage, mDstImage, origin, origin, region, numWaits, waits, outEvent ); + test_error( error, "Unable to enqueue image copy" ); + + return CL_SUCCESS; +} + +cl_int CopyImage2Dto2DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + cl_int error; + + + if( ( error = IGetPreferredImageSize2D( device, mWidth, mHeight ) ) ) + return error; + + mWidth /= 2; + + cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 }; + mSrcImage = create_image_2d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + mDstImage = create_image_2d( context, CL_MEM_WRITE_ONLY, &format, mWidth, mHeight, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + mDepth = 1; + return CL_SUCCESS; +} + +cl_int CopyImage2Dto3DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + cl_int error; + + + if( ( error = IGetPreferredImageSize3D( device, mWidth, mHeight, mDepth ) ) ) + return error; + + mDepth /= 2; + + cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 }; + mSrcImage = create_image_2d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + mDstImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + mDepth = 1; + return CL_SUCCESS; +} + +cl_int CopyImage3Dto2DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + cl_int error; + + + if( ( error = IGetPreferredImageSize3D( device, mWidth, mHeight, mDepth ) ) ) + return error; + + mDepth /= 2; + + cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 }; + mSrcImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + mDstImage = create_image_2d( context, CL_MEM_WRITE_ONLY, &format, mWidth, mHeight, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + mDepth = 1; + return CL_SUCCESS; +} + +cl_int CopyImage3Dto3DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + cl_int error; + + + if( ( error = IGetPreferredImageSize3D( device, mWidth, mHeight, mDepth ) ) ) + return error; + + mDepth /= 2; + + cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 }; + mSrcImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + mDstImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + return CL_SUCCESS; +} + +#pragma mark -------------------- Copy Image/Buffer Classes ------------------------- + +cl_int Copy2DImageToBufferAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + cl_int error; + + + if( ( error = IGetPreferredImageSize2D( device, mWidth, mHeight ) ) ) + return error; + + mWidth /= 2; + + cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 }; + mSrcImage = create_image_2d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + mDstBuffer = clCreateBuffer( context, CL_MEM_WRITE_ONLY, mWidth * mHeight * 4, NULL, &error ); + test_error( error, "Unable to create buffer to test against" ); + + return CL_SUCCESS; +} + +cl_int Copy2DImageToBufferAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) +{ + size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, 1 }; + + cl_int error = clEnqueueCopyImageToBuffer( queue, mSrcImage, mDstBuffer, origin, region, 0, numWaits, waits, outEvent ); + test_error( error, "Unable to enqueue image to buffer copy" ); + + return CL_SUCCESS; +} + +cl_int Copy3DImageToBufferAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + cl_int error; + + + if( ( error = IGetPreferredImageSize3D( device, mWidth, mHeight, mDepth ) ) ) + return error; + + mDepth /= 2; + + cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 }; + mSrcImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + mDstBuffer = clCreateBuffer( context, CL_MEM_WRITE_ONLY, mWidth * mHeight * mDepth * 4, NULL, &error ); + test_error( error, "Unable to create buffer to test against" ); + + return CL_SUCCESS; +} + +cl_int Copy3DImageToBufferAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) +{ + size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, mDepth }; + + cl_int error = clEnqueueCopyImageToBuffer( queue, mSrcImage, mDstBuffer, origin, region, 0, numWaits, waits, outEvent ); + test_error( error, "Unable to enqueue image to buffer copy" ); + + return CL_SUCCESS; +} + +cl_int CopyBufferTo2DImageAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + cl_int error; + + + if( ( error = IGetPreferredImageSize2D( device, mWidth, mHeight ) ) ) + return error; + + mWidth /= 2; + + cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 }; + + mSrcBuffer = clCreateBuffer( context, CL_MEM_READ_ONLY, mWidth * mHeight * 4, NULL, &error ); + test_error( error, "Unable to create buffer to test against" ); + + mDstImage = create_image_2d( context, CL_MEM_WRITE_ONLY, &format, mWidth, mHeight, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + return CL_SUCCESS; +} + +cl_int CopyBufferTo2DImageAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) +{ + size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, 1 }; + + cl_int error = clEnqueueCopyBufferToImage( queue, mSrcBuffer, mDstImage, 0, origin, region, numWaits, waits, outEvent ); + test_error( error, "Unable to enqueue buffer to image copy" ); + + return CL_SUCCESS; +} + +cl_int CopyBufferTo3DImageAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + cl_int error; + + + if( ( error = IGetPreferredImageSize3D( device, mWidth, mHeight, mDepth ) ) ) + return error; + + mDepth /= 2; + + mSrcBuffer = clCreateBuffer( context, CL_MEM_READ_ONLY, mWidth * mHeight * mDepth * 4, NULL, &error ); + test_error( error, "Unable to create buffer to test against" ); + + cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 }; + mDstImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + return CL_SUCCESS; +} + +cl_int CopyBufferTo3DImageAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) +{ + size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, mDepth }; + + cl_int error = clEnqueueCopyBufferToImage( queue, mSrcBuffer, mDstImage, 0, origin, region, numWaits, waits, outEvent ); + test_error( error, "Unable to enqueue buffer to image copy" ); + + return CL_SUCCESS; +} + +#pragma mark -------------------- Map Image Class ------------------------- + +MapImageAction::~MapImageAction() +{ + if (mQueue) + clEnqueueUnmapMemObject( mQueue, mImage, mMappedPtr, 0, NULL, NULL ); +} + +cl_int MapImageAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue ) +{ + cl_int error; + + + if( ( error = IGetPreferredImageSize2D( device, mWidth, mHeight ) ) ) + return error; + + cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 }; + mImage = create_image_2d( context, CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, &format, mWidth, mHeight, 0, NULL, &error ); + test_error( error, "Unable to create image to test against" ); + + return CL_SUCCESS; +} + +cl_int MapImageAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) +{ + cl_int error; + + size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, 1 }; + size_t outPitch; + + mQueue = queue; + mMappedPtr = clEnqueueMapImage( queue, mImage, CL_FALSE, CL_MAP_READ, origin, region, &outPitch, NULL, numWaits, waits, outEvent, &error ); + test_error( error, "Unable to enqueue image map" ); + + return CL_SUCCESS; +} diff --git a/test_conformance/events/action_classes.h b/test_conformance/events/action_classes.h new file mode 100644 index 00000000..069ed346 --- /dev/null +++ b/test_conformance/events/action_classes.h @@ -0,0 +1,326 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _action_classes_h +#define _action_classes_h + +#include "testBase.h" + +// This is a base class from which all actions are born +// Note: No actions should actually feed I/O to each other, because then +// it would potentially be possible for an implementation to make actions +// wait on one another based on their shared I/O, not because of their +// wait lists! +class Action +{ + public: + Action() {} + virtual ~Action() {} + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ) = 0; + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) = 0; + + virtual const char * GetName( void ) const = 0; + + protected: + + cl_int IGetPreferredImageSize2D( cl_device_id device, size_t &outWidth, size_t &outHeight ); + cl_int IGetPreferredImageSize3D( cl_device_id device, size_t &outWidth, size_t &outHeight, size_t &outDepth ); +}; + +// Simple NDRangeKernel execution that takes a noticable amount of time +class NDRangeKernelAction : public Action +{ + public: + NDRangeKernelAction() {} + virtual ~NDRangeKernelAction() {} + + size_t mLocalThreads[ 1 ]; + clMemWrapper mStreams[ 2 ]; + clProgramWrapper mProgram; + clKernelWrapper mKernel; + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ); + + virtual const char * GetName( void ) const { return "NDRangeKernel"; } +}; + +// Base action for buffer actions +class BufferAction : public Action +{ + public: + clMemWrapper mBuffer; + size_t mSize; + void *mOutBuffer; + + BufferAction() { mOutBuffer = NULL; } + virtual ~BufferAction() { free( mOutBuffer ); } + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue, bool allocate ); +}; + +class ReadBufferAction : public BufferAction +{ + public: + ReadBufferAction() {} + virtual ~ReadBufferAction() {} + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ); + + virtual const char * GetName( void ) const { return "ReadBuffer"; } +}; + +class WriteBufferAction : public BufferAction +{ + public: + WriteBufferAction() {} + virtual ~WriteBufferAction() {} + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ); + + virtual const char * GetName( void ) const { return "WriteBuffer"; } +}; + +class MapBufferAction : public BufferAction +{ + public: + MapBufferAction() : mQueue(0) {} + + cl_command_queue mQueue; + void *mMappedPtr; + + virtual ~MapBufferAction(); + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ); + + virtual const char * GetName( void ) const { return "MapBuffer"; } +}; + +class UnmapBufferAction : public BufferAction +{ + public: + UnmapBufferAction() {} + virtual ~UnmapBufferAction() {} + + void *mMappedPtr; + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ); + + virtual const char * GetName( void ) const { return "UnmapBuffer"; } +}; + +class ReadImage2DAction : public Action +{ + public: + ReadImage2DAction() { mOutput = NULL; } + virtual ~ReadImage2DAction() { free( mOutput ); } + + clMemWrapper mImage; + size_t mWidth, mHeight; + void *mOutput; + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ); + + virtual const char * GetName( void ) const { return "ReadImage2D"; } +}; + +class ReadImage3DAction : public Action +{ + public: + ReadImage3DAction() { mOutput = NULL; } + virtual ~ReadImage3DAction() { free( mOutput ); } + + clMemWrapper mImage; + size_t mWidth, mHeight, mDepth; + void *mOutput; + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ); + + virtual const char * GetName( void ) const { return "ReadImage3D"; } +}; + +class WriteImage2DAction : public Action +{ + public: + clMemWrapper mImage; + size_t mWidth, mHeight; + void *mOutput; + + WriteImage2DAction() { mOutput = NULL; } + virtual ~WriteImage2DAction() { free( mOutput ); } + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ); + + virtual const char * GetName( void ) const { return "WriteImage2D"; } +}; + +class WriteImage3DAction : public Action +{ + public: + clMemWrapper mImage; + size_t mWidth, mHeight, mDepth; + void *mOutput; + + WriteImage3DAction() { mOutput = NULL; } + virtual ~WriteImage3DAction() { free( mOutput ); } + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ); + + virtual const char * GetName( void ) const { return "WriteImage3D"; } +}; + +class CopyImageAction : public Action +{ + public: + CopyImageAction() {} + virtual ~CopyImageAction() {} + + clMemWrapper mSrcImage, mDstImage; + size_t mWidth, mHeight, mDepth; + + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ); +}; + +class CopyImage2Dto2DAction : public CopyImageAction +{ + public: + CopyImage2Dto2DAction() {} + virtual ~CopyImage2Dto2DAction() {} + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + + virtual const char * GetName( void ) const { return "CopyImage2Dto2D"; } +}; + +class CopyImage2Dto3DAction : public CopyImageAction +{ + public: + CopyImage2Dto3DAction() {} + virtual ~CopyImage2Dto3DAction() {} + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + + virtual const char * GetName( void ) const { return "CopyImage2Dto3D"; } +}; + +class CopyImage3Dto2DAction : public CopyImageAction +{ + public: + CopyImage3Dto2DAction() {} + virtual ~CopyImage3Dto2DAction() {} + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + + virtual const char * GetName( void ) const { return "CopyImage3Dto2D"; } +}; + +class CopyImage3Dto3DAction : public CopyImageAction +{ + public: + CopyImage3Dto3DAction() {} + virtual ~CopyImage3Dto3DAction() {} + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + + virtual const char * GetName( void ) const { return "CopyImage3Dto3D"; } +}; + +class Copy2DImageToBufferAction : public Action +{ + public: + Copy2DImageToBufferAction() {} + virtual ~Copy2DImageToBufferAction() {} + + clMemWrapper mSrcImage, mDstBuffer; + size_t mWidth, mHeight; + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ); + + virtual const char * GetName( void ) const { return "Copy2DImageToBuffer"; } +}; + +class Copy3DImageToBufferAction : public Action +{ + public: + Copy3DImageToBufferAction() {} + virtual ~Copy3DImageToBufferAction() {} + + clMemWrapper mSrcImage, mDstBuffer; + size_t mWidth, mHeight, mDepth; + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ); + + virtual const char * GetName( void ) const { return "Copy3DImageToBuffer"; } +}; + +class CopyBufferTo2DImageAction : public Action +{ + public: + CopyBufferTo2DImageAction() {} + virtual ~CopyBufferTo2DImageAction() {} + + clMemWrapper mSrcBuffer, mDstImage; + size_t mWidth, mHeight; + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ); + + virtual const char * GetName( void ) const { return "CopyBufferTo2D"; } +}; + +class CopyBufferTo3DImageAction : public Action +{ + public: + CopyBufferTo3DImageAction() {} + virtual ~CopyBufferTo3DImageAction() {} + + clMemWrapper mSrcBuffer, mDstImage; + size_t mWidth, mHeight, mDepth; + + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ); + + virtual const char * GetName( void ) const { return "CopyBufferTo3D"; } +}; + +class MapImageAction : public Action +{ + public: + MapImageAction() : mQueue(0) {} + + clMemWrapper mImage; + size_t mWidth, mHeight; + void *mMappedPtr; + cl_command_queue mQueue; + + virtual ~MapImageAction(); + virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ); + virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ); + + virtual const char * GetName( void ) const { return "MapImage"; } +}; + + +#endif // _action_classes_h diff --git a/test_conformance/events/main.c b/test_conformance/events/main.c new file mode 100644 index 00000000..5a6600c7 --- /dev/null +++ b/test_conformance/events/main.c @@ -0,0 +1,108 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include "procs.h" +#include "../../test_common/harness/testHarness.h" +#if !defined(_WIN32) +#include +#endif + +basefn basefn_list[] = { + test_event_get_execute_status, + test_event_get_write_array_status, + test_event_get_read_array_status, + test_event_get_info, + test_event_wait_for_execute, + test_event_wait_for_array, + test_event_flush, + test_event_finish_execute, + test_event_finish_array, + test_event_release_before_done, + test_event_enqueue_marker, + #ifdef CL_VERSION_1_2 + test_event_enqueue_marker_with_list, + test_event_enqueue_barrier_with_list, + #endif + + + test_event_waitlist_single_queue, + test_event_waitlist_multi_queue, + test_event_waitlist_multi_queue_multi_device, + test_event_enqueue_wait_for_events_single_queue, + test_event_enqueue_wait_for_events_multi_queue, + test_event_enqueue_wait_for_events_multi_queue_multi_device, + test_event_enqueue_marker_single_queue, + test_event_enqueue_marker_multi_queue, + test_event_enqueue_marker_multi_queue_multi_device, + test_event_enqueue_barrier_single_queue, + + test_waitlists, + test_userevents, + test_callbacks, + test_callbacks_simultaneous, + test_userevents_multithreaded, +}; + +const char *basefn_names[] = { + "event_get_execute_status", + "event_get_write_array_status", + "event_get_read_array_status", + "event_get_info", + "event_wait_for_execute", + "event_wait_for_array", + "event_flush", + "event_finish_execute", + "event_finish_array", + "event_release_before_done", + "event_enqueue_marker", +#ifdef CL_VERSION_1_2 + "event_enqueue_marker_with_event_list", + "event_enqueue_barrier_with_event_list", +#endif + + "out_of_order_event_waitlist_single_queue", + "out_of_order_event_waitlist_multi_queue", + "out_of_order_event_waitlist_multi_queue_multi_device", + "out_of_order_event_enqueue_wait_for_events_single_queue", + "out_of_order_event_enqueue_wait_for_events_multi_queue", + "out_of_order_event_enqueue_wait_for_events_multi_queue_multi_device", + "out_of_order_event_enqueue_marker_single_queue", + "out_of_order_event_enqueue_marker_multi_queue", + "out_of_order_event_enqueue_marker_multi_queue_multi_device", + "out_of_order_event_enqueue_barrier_single_queue", + + "waitlists", + "test_userevents", + + "callbacks", + "callbacks_simultaneous", + + "userevents_multithreaded", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + +int main(int argc, const char *argv[]) +{ + return runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false, false, 0 ); +} + + diff --git a/test_conformance/events/procs.h b/test_conformance/events/procs.h new file mode 100644 index 00000000..4dcf7509 --- /dev/null +++ b/test_conformance/events/procs.h @@ -0,0 +1,61 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/clImageHelper.h" + +extern float random_float(float low, float high); +extern float calculate_ulperror(float a, float b); + + +extern int test_event_get_execute_status(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_get_write_array_status(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_get_read_array_status(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_get_info( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_wait_for_execute(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_wait_for_array(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_flush(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_finish_execute(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_finish_array(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_release_before_done(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_enqueue_marker(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +#ifdef CL_VERSION_1_2 +extern int test_event_enqueue_marker_with_list(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_enqueue_barrier_with_list(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +#endif + +extern int test_event_waitlist_single_queue(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_waitlist_multi_queue( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_waitlist_multi_queue_multi_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_event_enqueue_wait_for_events_single_queue(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_enqueue_wait_for_events_multi_queue( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_enqueue_wait_for_events_multi_queue_multi_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_event_enqueue_barrier_single_queue(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_event_enqueue_marker_single_queue(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_enqueue_marker_multi_queue( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_event_enqueue_marker_multi_queue_multi_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_waitlists( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_userevents( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_callbacks( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_callbacks_simultaneous( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_userevents_multithreaded( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); + + diff --git a/test_conformance/events/testBase.h b/test_conformance/events/testBase.h new file mode 100644 index 00000000..5073b21f --- /dev/null +++ b/test_conformance/events/testBase.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testBase_h +#define _testBase_h + +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +#endif // _testBase_h + + + diff --git a/test_conformance/events/test_callbacks.cpp b/test_conformance/events/test_callbacks.cpp new file mode 100644 index 00000000..3286fd6e --- /dev/null +++ b/test_conformance/events/test_callbacks.cpp @@ -0,0 +1,341 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "action_classes.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/ThreadPool.h" + +#if !defined (_MSC_VER) +#include +#endif // !_MSC_VER + +extern const char *IGetStatusString( cl_int status ); + +#define PRINT_OPS 0 + +// Yes, this is somewhat nasty, in that we're relying on the CPU (the real CPU, not the OpenCL device) +// to be atomic w.r.t. boolean values. Although if it isn't, we'll just miss the check on this bool +// until the next time around, so it's not that big of a deal. Ideally, we'd be using a semaphore with +// a trywait on it, but then that introduces the fun issue of what to do on Win32, etc. This way is +// far more portable, and worst case of failure is a slightly longer test run. +static bool sCallbackTriggered = false; + + +#define EVENT_CALLBACK_TYPE_TOTAL 3 +static bool sCallbackTriggered_flag[ EVENT_CALLBACK_TYPE_TOTAL ] ={ false,false, false }; +cl_int event_callback_types[EVENT_CALLBACK_TYPE_TOTAL] ={ CL_SUBMITTED, CL_RUNNING, CL_COMPLETE}; + +// Our callback function +/*void CL_CALLBACK single_event_callback_function( cl_event event, cl_int commandStatus, void * userData ) +{ + int i=*static_cast(userData); + log_info( "\tEvent callback %d triggered\n", i); + sCallbackTriggered_flag [ i ] = true; +}*/ + +/* use struct as call back para */ +typedef struct { cl_int enevt_type; int index; } CALL_BACK_USER_DATA; + +void CL_CALLBACK single_event_callback_function_flags( cl_event event, cl_int commandStatus, void * userData ) +{ + // int i=*static_cast(userData); + CALL_BACK_USER_DATA *pdata= static_cast(userData); + + log_info( "\tEvent callback %d of type %d triggered\n", pdata->index, pdata->enevt_type); + sCallbackTriggered_flag [pdata->index ] = true; +} + +int test_callback_event_single( cl_device_id device, cl_context context, cl_command_queue queue, Action *actionToTest ) +{ + // Note: we don't use the waiting feature here. We just want to verify that we get a callback called + // when the given event finishes + + cl_int error = actionToTest->Setup( device, context, queue ); + test_error( error, "Unable to set up test action" ); + + // Set up a user event, which we use as a gate for the second event + clEventWrapper gateEvent = clCreateUserEvent( context, &error ); + test_error( error, "Unable to set up user gate event" ); + + // Set up the execution of the action with its actual event + clEventWrapper actualEvent; + error = actionToTest->Execute( queue, 1, &gateEvent, &actualEvent ); + test_error( error, "Unable to set up action execution" ); + + // Set up the callback on the actual event + + /* use struct as call back para */ + CALL_BACK_USER_DATA user_data[EVENT_CALLBACK_TYPE_TOTAL]; + int index [EVENT_CALLBACK_TYPE_TOTAL]={ 0,1,2}; + for( int i=0;i< EVENT_CALLBACK_TYPE_TOTAL; i++) + { + user_data[i].enevt_type=event_callback_types[i]; + user_data[i].index =i; + error = clSetEventCallback( actualEvent, event_callback_types[i], single_event_callback_function_flags, user_data+i ); + + } + + // Now release the user event, which will allow our actual action to run + error = clSetUserEventStatus( gateEvent, CL_COMPLETE ); + test_error( error, "Unable to trigger gate event" ); + + // Now we wait for completion. Note that we can actually wait on the event itself, at least at first + error = clWaitForEvents( 1, &actualEvent ); + test_error( error, "Unable to wait for actual test event" ); + + // Note: we can check our callback now, and it MIGHT have been triggered, but that's not guaranteed + if( sCallbackTriggered ) + { + // We're all good, so return success + return 0; + } + + // The callback has not yet been called, but that doesn't mean it won't be. So wait for it + log_info( "\tWaiting for callback..." ); + fflush( stdout ); + for( int i = 0; i < 10 * 10; i++ ) + { + usleep( 100000 ); // 1/10th second + + int cc=0; + for( int k=0;k< EVENT_CALLBACK_TYPE_TOTAL;k++) + if (sCallbackTriggered_flag[k]) { + cc++; + } + + if (cc== EVENT_CALLBACK_TYPE_TOTAL ) + { + log_info( "\n" ); + return 0; + } + log_info( "." ); + fflush( stdout ); + } + + // If we got here, we never got the callback + log_error( "\nCallback not called within 10 seconds! (assuming failure)\n" ); + return -1; +} + +#define TEST_ACTION( name ) \ +{ \ + name##Action action; \ + log_info( "-- Testing " #name "...\n" ); \ + if( ( error = test_callback_event_single( deviceID, context, queue, &action ) ) != CL_SUCCESS ) \ + retVal++; \ + clFinish( queue ); \ +} + +int test_callbacks( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_int error; + int retVal = 0; + + log_info( "\n" ); + + TEST_ACTION( NDRangeKernel ) + + TEST_ACTION( ReadBuffer ) + TEST_ACTION( WriteBuffer ) + TEST_ACTION( MapBuffer ) + TEST_ACTION( UnmapBuffer ) + + if( checkForImageSupport( deviceID ) == CL_IMAGE_FORMAT_NOT_SUPPORTED ) + { + log_info( "\nNote: device does not support images. Skipping remainder of callback tests...\n" ); + } + else + { + TEST_ACTION( ReadImage2D ) + TEST_ACTION( WriteImage2D ) + TEST_ACTION( CopyImage2Dto2D ) + TEST_ACTION( Copy2DImageToBuffer ) + TEST_ACTION( CopyBufferTo2DImage ) + TEST_ACTION( MapImage ) + + if( checkFor3DImageSupport( deviceID ) == CL_IMAGE_FORMAT_NOT_SUPPORTED ) + log_info( "\nNote: device does not support 3D images. Skipping remainder of waitlist tests...\n" ); + else + { + TEST_ACTION( ReadImage3D ) + TEST_ACTION( WriteImage3D ) + TEST_ACTION( CopyImage2Dto3D ) + TEST_ACTION( CopyImage3Dto2D ) + TEST_ACTION( CopyImage3Dto3D ) + TEST_ACTION( Copy3DImageToBuffer ) + TEST_ACTION( CopyBufferTo3DImage ) + } + } + + return retVal; +} + +#define SIMUTANEOUS_ACTION_TOTAL 18 +static bool sSimultaneousFlags[ 54 ];// for 18 actions with 3 callback status +static volatile int sSimultaneousCount; + +Action * actions[ 19 ] = { 0 }; + +// Callback for the simultaneous tests +void CL_CALLBACK simultaneous_event_callback_function( cl_event event, cl_int commandStatus, void * userData ) +{ + int eventIndex = (int)(size_t)userData; + int actionIndex = eventIndex/EVENT_CALLBACK_TYPE_TOTAL; + int statusIndex = eventIndex%EVENT_CALLBACK_TYPE_TOTAL; + log_info( "\tEvent callback triggered for action %s callback type %s \n", actions[actionIndex]->GetName(), IGetStatusString(statusIndex) ); + sSimultaneousFlags[ actionIndex ] = true; + ThreadPool_AtomicAdd(&sSimultaneousCount,1); +} + +int test_callbacks_simultaneous( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_int error; + + // Unlike the singles test, in this one, we run a bunch of events all at once, to verify that + // the callbacks do get called once-and-only-once for each event, even if the run out of order or + // are dependent on each other + + // First, the list of actions to run + int actionCount = 0, index = 0; + + actions[ index++ ] = new NDRangeKernelAction(); + actions[ index++ ] = new ReadBufferAction(); + actions[ index++ ] = new WriteBufferAction(); + actions[ index++ ] = new MapBufferAction(); + actions[ index++ ] = new UnmapBufferAction(); + + if( checkForImageSupport( deviceID ) != CL_IMAGE_FORMAT_NOT_SUPPORTED ) + { + actions[ index++ ] = new ReadImage2DAction(); + actions[ index++ ] = new WriteImage2DAction(); + actions[ index++ ] = new CopyImage2Dto2DAction(); + actions[ index++ ] = new Copy2DImageToBufferAction(); + actions[ index++ ] = new CopyBufferTo2DImageAction(); + actions[ index++ ] = new MapImageAction(); + + if( checkFor3DImageSupport( deviceID ) != CL_IMAGE_FORMAT_NOT_SUPPORTED ) + { + actions[ index++ ] = new ReadImage3DAction(); + actions[ index++ ] = new WriteImage3DAction(); + actions[ index++ ] = new CopyImage2Dto3DAction(); + actions[ index++ ] = new CopyImage3Dto2DAction(); + actions[ index++ ] = new CopyImage3Dto3DAction(); + actions[ index++ ] = new Copy3DImageToBufferAction(); + actions[ index++ ] = new CopyBufferTo3DImageAction(); + } + } + actionCount = index; + actions[ index++ ] = NULL; + + // Now set them all up + log_info( "\tSetting up test events...\n" ); + for( index = 0; actions[ index ] != NULL; index++ ) + { + error = actions[ index ]->Setup( deviceID, context, queue ); + test_error( error, "Unable to set up test action" ); + sSimultaneousFlags[ index ] = false; + } + sSimultaneousCount = 0; + + // Set up the user event to start them all + clEventWrapper gateEvent = clCreateUserEvent( context, &error ); + test_error( error, "Unable to set up user gate event" ); + + // Start executing, all tied to the gate event + //clEventWrapper actionEvents[ 18 ];// current actionCount is 18 + clEventWrapper *actionEvents= new clEventWrapper[actionCount]; + if (actionEvents == NULL) + { + log_error(" memory error in test_callbacks_simultaneous \n"); + for (size_t i=0;i<(sizeof(actions)/sizeof(actions[0]));++i) + if (actions[i]) delete actions[i]; + return -1; + } + + RandomSeed seed( gRandomSeed ); + for( index = 0; actions[ index ] != NULL; index++ ) + { + // Randomly choose to wait on the gate, or wait on the previous event + cl_event * eventPtr = &gateEvent; + if( ( index > 0 ) && ( random_in_range( 0, 255, seed ) & 1 ) ) + eventPtr = &actionEvents[ index - 1 ]; + + error = actions[ index ]->Execute( queue, 1, eventPtr, &actionEvents[ index ] ); + test_error( error, "Unable to execute test action" ); + + + for( int k=0; k< EVENT_CALLBACK_TYPE_TOTAL; k++) + { + error = clSetEventCallback( actionEvents[index], event_callback_types[k], simultaneous_event_callback_function, (void *)(size_t)(index*EVENT_CALLBACK_TYPE_TOTAL+k ) ); + test_error( error, "Unable to set event callback function" ); + + } + } + + int total_callbacks= actionCount * EVENT_CALLBACK_TYPE_TOTAL; + + // Now release the user event, which will allow our actual action to run + error = clSetUserEventStatus( gateEvent, CL_COMPLETE ); + test_error( error, "Unable to trigger gate event" ); + + // Wait on the actual action events now + log_info( "\tWaiting for test completions...\n" ); + error = clWaitForEvents( actionCount, &actionEvents[ 0 ] ); + test_error( error, "Unable to wait for actual test events" ); + + // Note: we can check our callback now, and it MIGHT have been triggered, but that's not guaranteed + int last_count = 0; + if( ((last_count = sSimultaneousCount)) == total_callbacks) + { + // We're all good, so return success + log_info( "\t%d of %d callbacks received\n", sSimultaneousCount, total_callbacks ); + + if (actionEvents) delete [] actionEvents; + for (size_t i=0;i<(sizeof(actions)/sizeof(actions[0]));++i) + if (actions[i]) delete actions[i]; + return 0; + } + + // We haven't gotten (all) of the callbacks, so wait for them + log_info( "\tWe've only received %d of the %d callbacks we expected; waiting for more...\n", last_count, total_callbacks ); + + for( int i = 0; i < 10 * 10; i++ ) + { + usleep( 100000 ); // 1/10th second + if( ((last_count = sSimultaneousCount)) == total_callbacks ) + { + // All of the callbacks were executed + if (actionEvents) delete [] actionEvents; + for (size_t i=0;i<(sizeof(actions)/sizeof(actions[0]));++i) + if (actions[i]) delete actions[i]; + return 0; + } + } + + // If we got here, some of the callbacks did not occur in time + log_error( "\nError: We only ever received %d of our %d callbacks!\n", last_count, total_callbacks ); + log_error( "Events that did not receive callbacks:\n" ); + for( index = 0; actions[ index ] != NULL; index++ ) + { + if( !sSimultaneousFlags[ index ] ) + log_error( "\t%s\n", actions[ index ]->GetName() ); + } + + if (actionEvents) delete [] actionEvents; + return -1; + +} + diff --git a/test_conformance/events/test_event_dependencies.cpp b/test_conformance/events/test_event_dependencies.cpp new file mode 100644 index 00000000..6665d8d5 --- /dev/null +++ b/test_conformance/events/test_event_dependencies.cpp @@ -0,0 +1,509 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/testHarness.h" + +const char *write_kernels[] = { + "__kernel void write_up(__global int *dst, int length)\n" + "{\n" + "\n" + " dst[get_global_id(0)] *= 2;\n" + "\n" + "}\n" + "__kernel void write_down(__global int *dst, int length)\n" + "{\n" + "\n" + " dst[get_global_id(0)]--;\n" + "\n" + "}\n" +}; + +#define TEST_SIZE 10000 +#define TEST_COUNT 100 +#define RANDOMIZE 1 +#define DEBUG_OUT 0 + +/* + Tests event dependencies by running two kernels that use the same buffer. + If two_queues is set they are run in separate queues. + If test_enqueue_wait_for_events is set then clEnqueueWaitForEvent is called between them. + If test_barrier is set then clEnqueueBarrier is called between them (only for single queue). + If neither are set, nothing is done to prevent them from executing in the wrong order. This can be used for verification. + */ +int test_event_enqueue_wait_for_events_run_test( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, int two_queues, int two_devices, + int test_enqueue_wait_for_events, int test_barrier, int use_waitlist, int use_marker) +{ + cl_int error = CL_SUCCESS; + size_t threads[3] = {TEST_SIZE,0,0}; + int i, loop_count, event_count, expected_value, failed; + int expected_if_only_queue[2]; + int max_count = TEST_SIZE; + + cl_platform_id platform; + cl_command_queue queues[2]; // Not a wrapper so we don't autorelease if they are the same + clCommandQueueWrapper queueWrappers[2]; // If they are different, we use the wrapper so it will auto release + clContextWrapper context_to_use; + clMemWrapper data; + clProgramWrapper program; + clKernelWrapper kernel1[TEST_COUNT], kernel2[TEST_COUNT]; + clEventWrapper event[TEST_COUNT*4+2]; // If we usemarkers we get 2 more events per iteration + + if (test_enqueue_wait_for_events) + log_info("\tTesting with clEnqueueBarrierWithWaitList as barrier function.\n"); + if (test_barrier) + log_info("\tTesting with clEnqueueBarrierWithWaitList as barrier function.\n"); + if (use_waitlist) + log_info("\tTesting with waitlist-based depenednecies between kernels.\n"); + if (use_marker) + log_info("\tTesting with clEnqueueMarker as a barrier function.\n"); + if (test_barrier && (two_queues || two_devices)) { + log_error("\tTest requested with clEnqueueBarrier across two queues. This is not a valid combination.\n"); + return -1; + } + + error = clGetPlatformIDs(1, &platform, NULL); + test_error(error, "clGetPlatformIDs failed."); + + // If we are to use two devices, then get them and create a context with both. + cl_device_id *two_device_ids; + if (two_devices) { + two_device_ids = (cl_device_id*)malloc(sizeof(cl_device_id)*2); + cl_uint number_returned; + error = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 2, two_device_ids, &number_returned); + test_error( error, "clGetDeviceIDs for CL_DEVICE_TYPE_ALL failed."); + if (number_returned != 2) { + log_info("Failed to obtain two devices. Test can not run.\n"); + free(two_device_ids); + return 0; + } + + for (i=0; i<2; i++) { + cl_device_type type; + error = clGetDeviceInfo(two_device_ids[i], CL_DEVICE_TYPE, sizeof(cl_device_type), &type, NULL); + test_error( error, "clGetDeviceInfo failed."); + if (type & CL_DEVICE_TYPE_CPU) + log_info("\tDevice %d is CL_DEVICE_TYPE_CPU.\n", i); + if (type & CL_DEVICE_TYPE_GPU) + log_info("\tDevice %d is CL_DEVICE_TYPE_GPU.\n", i); + if (type & CL_DEVICE_TYPE_ACCELERATOR) + log_info("\tDevice %d is CL_DEVICE_TYPE_ACCELERATOR.\n", i); + if (type & CL_DEVICE_TYPE_DEFAULT) + log_info("\tDevice %d is CL_DEVICE_TYPE_DEFAULT.\n", i); + } + + context_to_use = clCreateContext(NULL, 2, two_device_ids, notify_callback, NULL, &error); + test_error(error, "clCreateContext failed for two devices."); + + log_info("\tTesting with two devices.\n"); + } else { + context_to_use = clCreateContext(NULL, 1, &deviceID, NULL, NULL, &error); + test_error(error, "clCreateContext failed for one device."); + + log_info("\tTesting with one device.\n"); + } + + // If we are using two queues then create them + cl_queue_properties props[] = {CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, 0}; + if (two_queues) { + // Get a second queue + if (two_devices) + { + if( !checkDeviceForQueueSupport( two_device_ids[ 0 ], props[1] ) || + !checkDeviceForQueueSupport( two_device_ids[ 1 ], props[1] ) ) + { + log_info( "WARNING: One or more device for multi-device test does not support out-of-order exec mode; skipping test.\n" ); + return -1942; + } + + queueWrappers[0] = clCreateCommandQueueWithProperties(context_to_use, two_device_ids[0], &props[0], &error); + test_error(error, "clCreateCommandQueue for first queue on first device failed."); + queueWrappers[1] = clCreateCommandQueueWithProperties(context_to_use, two_device_ids[1], &props[0], &error); + test_error(error, "clCreateCommandQueue for second queue on second device failed."); + + } + else + { + // Single device has already been checked for out-of-order exec support + queueWrappers[0] = clCreateCommandQueueWithProperties(context_to_use, deviceID, &props[0], &error); + test_error(error, "clCreateCommandQueue for first queue failed."); + queueWrappers[1] = clCreateCommandQueueWithProperties(context_to_use, deviceID, &props[0], &error); + test_error(error, "clCreateCommandQueue for second queue failed."); + } + // Ugly hack to make sure we only have the wrapper auto-release if they are different queues + queues[0] = queueWrappers[0]; + queues[1] = queueWrappers[1]; + log_info("\tTesting with two queues.\n"); + } + else + { + // (Note: single device has already been checked for out-of-order exec support) + // Otherwise create one queue and have the second one be the same + queueWrappers[0] = clCreateCommandQueueWithProperties(context_to_use, deviceID, &props[0], &error); + test_error(error, "clCreateCommandQueue for first queue failed."); + queues[0] = queueWrappers[0]; + queues[1] = (cl_command_queue)queues[0]; + log_info("\tTesting with one queue.\n"); + } + + + // Setup - create a buffer and the two kernels + data = clCreateBuffer(context_to_use, CL_MEM_READ_WRITE, TEST_SIZE*sizeof(cl_int), NULL, &error); + test_error( error, "clCreateBuffer failed"); + + + // Initialize the values to zero + cl_int *values = (cl_int*)malloc(TEST_SIZE*sizeof(cl_int)); + for (i=0; i<(int)TEST_SIZE; i++) + values[i] = 0; + error = clEnqueueWriteBuffer(queues[0], data, CL_TRUE, 0, TEST_SIZE*sizeof(cl_int), values, 0, NULL, NULL); + test_error( error, "clEnqueueWriteBuffer failed"); + expected_value = 0; + + // Build the kernels + if (create_single_kernel_helper( context_to_use, &program, &kernel1[0], 1, write_kernels, "write_up" )) + return -1; + + error = clSetKernelArg(kernel1[0], 0, sizeof(data), &data); + error |= clSetKernelArg(kernel1[0], 1, sizeof(max_count), &max_count); + test_error( error, "clSetKernelArg 1 failed"); + + for (i=1; i", (int)status ); + return tempString; + } +} + +/* Note: tests clGetEventStatus and clReleaseEvent (implicitly) */ +int test_event_get_execute_status( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int status; + SETUP_EVENT( context, queue ); + + /* Now wait for it to be done */ + error = clWaitForEvents( 1, &event ); + test_error( error, "Unable to wait for event" ); + + error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventStatus to wait for event completion failed" ); + if( status != CL_COMPLETE ) + { + log_error( "ERROR: Incorrect status returned from clGetErrorStatus after event complete (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + FINISH_EVENT(queue); + return 0; +} + +int test_event_get_info( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + SETUP_EVENT( context, queue ); + + /* Verify parameters of clGetEventInfo not already tested by other tests */ + cl_command_queue otherQueue; + size_t size; + + error = clGetEventInfo( event, CL_EVENT_COMMAND_QUEUE, sizeof( otherQueue ), &otherQueue, &size ); + test_error( error, "Unable to get event info!" ); + // We can not check if this is the right queue because this is an opaque object. + if( size != sizeof( queue ) ) + { + log_error( "ERROR: Returned command queue size does not validate (expected %d, got %d)\n", (int)sizeof( queue ), (int)size ); + return -1; + } + + cl_command_type type; + error = clGetEventInfo( event, CL_EVENT_COMMAND_TYPE, sizeof( type ), &type, &size ); + test_error( error, "Unable to get event info!" ); + if( type != CL_COMMAND_NDRANGE_KERNEL ) + { + log_error( "ERROR: Returned command type does not validate (expected %d, got %d)\n", (int)CL_COMMAND_NDRANGE_KERNEL, (int)type ); + return -1; + } + if( size != sizeof( type ) ) + { + log_error( "ERROR: Returned command type size does not validate (expected %d, got %d)\n", (int)sizeof( type ), (int)size ); + return -1; + } + + cl_uint count; + error = clGetEventInfo( event, CL_EVENT_REFERENCE_COUNT, sizeof( count ), &count, &size ); + test_error( error, "Unable to get event info for CL_EVENT_REFERENCE_COUNT!" ); + if( size != sizeof( count ) ) + { + log_error( "ERROR: Returned command type size does not validate (expected %d, got %d)\n", (int)sizeof( type ), (int)size ); + return -1; + } + + cl_context testCtx; + error = clGetEventInfo( event, CL_EVENT_CONTEXT, sizeof( testCtx ), &testCtx, &size ); + test_error( error, "Unable to get event context info!" ); + if( size != sizeof( context ) ) + { + log_error( "ERROR: Returned context size does not validate (expected %d, got %d)\n", (int)sizeof( context ), (int)size ); + return -1; + } + if( testCtx != context ) + { + log_error( "ERROR: Returned context does not match (expected %p, got %p)\n", (void *)context, (void *)testCtx ); + return -1; + } + + FINISH_EVENT(queue); + return 0; +} + +int test_event_get_write_array_status( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem stream; + cl_float testArray[ 1024 * 32 ]; + cl_event event; + int error; + cl_int status; + + + stream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 1024 * 32, NULL, &error ); + test_error( error, "Creating test array failed" ); + + error = clEnqueueWriteBuffer(queue, stream, CL_FALSE, 0, sizeof(cl_float)*1024*32, (void *)testArray, 0, NULL, &event); + test_error( error, "Unable to set testing kernel data" ); + + /* Now wait for it to be done */ + error = clWaitForEvents( 1, &event ); + test_error( error, "Unable to wait for event" ); + + error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventStatus to wait for event completion failed" ); + if( status != CL_COMPLETE ) + { + log_error( "ERROR: Incorrect status returned from clGetErrorStatus after array write complete (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + + clReleaseMemObject( stream ); + clReleaseEvent( event ); + + return 0; +} + +int test_event_get_read_array_status( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem stream; + cl_float testArray[ 1024 * 32 ]; + cl_event event; + int error; + cl_int status; + + + stream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 1024 * 32, NULL, &error ); + test_error( error, "Creating test array failed" ); + + error = clEnqueueReadBuffer(queue, stream, CL_FALSE, 0, sizeof(cl_float)*1024*32, (void *)testArray, 0, NULL, &event); + test_error( error, "Unable to get testing kernel data" ); + + + /* It should still be running... */ + error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventStatus didn't work!" ); + + if( status != CL_RUNNING && status != CL_QUEUED && status != CL_SUBMITTED && status != CL_COMPLETE) + { + log_error( "ERROR: Incorrect status returned from clGetErrorStatus during array read (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + /* Now wait for it to be done */ + error = clWaitForEvents( 1, &event ); + test_error( error, "Unable to wait for event" ); + + error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventStatus to wait for event completion failed" ); + if( status != CL_COMPLETE ) + { + log_error( "ERROR: Incorrect status returned from clGetErrorStatus after array read complete (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + + clReleaseMemObject( stream ); + clReleaseEvent( event ); + + return 0; +} + +/* clGetEventStatus not implemented yet */ + +int test_event_wait_for_execute( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int status; + SETUP_EVENT( context, queue ); + + /* Now we wait for it to be done, then test the status again */ + error = clWaitForEvents( 1, &event ); + test_error( error, "Unable to wait for execute event" ); + + /* Make sure it worked */ + error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventStatus didn't work!" ); + if( status != CL_COMPLETE ) + { + log_error( "ERROR: Incorrect status returned from clGetErrorStatus after event complete (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + FINISH_EVENT(queue); + return 0; +} + +int test_event_wait_for_array( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem streams[2]; + cl_float readArray[ 1024 * 32 ]; + cl_float writeArray[ 1024 * 32 ]; + cl_event events[2]; + int error; + cl_int status; + + + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 1024 * 32, NULL, &error ); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 1024 * 32, NULL, &error ); + test_error( error, "Creating test array failed" ); + + error = clEnqueueReadBuffer(queue, streams[0], CL_FALSE, 0, sizeof(cl_float)*1024*32, (void *)readArray, 0, NULL, &events[0]); + test_error( error, "Unable to read testing kernel data" ); + + error = clEnqueueWriteBuffer(queue, streams[1], CL_FALSE, 0, sizeof(cl_float)*1024*32, (void *)writeArray, 0, NULL, &events[1]); + test_error( error, "Unable to write testing kernel data" ); + + /* Both should still be running */ + error = clGetEventInfo( events[0], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventStatus didn't work!" ); + if( status != CL_RUNNING && status != CL_QUEUED && status != CL_SUBMITTED && status != CL_COMPLETE) + { + log_error( "ERROR: Incorrect status returned from clGetErrorStatus during array read (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + error = clGetEventInfo( events[1], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventStatus didn't work!" ); + if( status != CL_RUNNING && status != CL_QUEUED && status != CL_SUBMITTED && status != CL_COMPLETE) + { + log_error( "ERROR: Incorrect status returned from clGetErrorStatus during array write (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + /* Now try waiting for both */ + error = clWaitForEvents( 2, events ); + test_error( error, "Unable to wait for array events" ); + + /* Double check status on both */ + error = clGetEventInfo( events[0], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventStatus didn't work!" ); + if( status != CL_COMPLETE ) + { + log_error( "ERROR: Incorrect status returned from clGetErrorStatus after array read complete (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + error = clGetEventInfo( events[1], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventStatus didn't work!" ); + if( status != CL_COMPLETE ) + { + log_error( "ERROR: Incorrect status returned from clGetErrorStatus after array write complete (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + clReleaseEvent( events[0] ); + clReleaseEvent( events[1] ); + + return 0; +} + +int test_event_flush( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int loopCount = 0; + cl_int status; + SETUP_EVENT( context, queue ); + + /* Now flush. Note that we can't guarantee this actually lets the op finish, but we can guarantee it's no longer queued */ + error = clFlush( queue ); + test_error( error, "Unable to flush events" ); + + /* Make sure it worked */ + while (1) { + error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS, + sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventStatus didn't work!" ); + + if( status != CL_QUEUED ) + break; + +#if ! defined( _WIN32 ) + sleep(1); // give it some time here. +#else // _WIN32 + Sleep(1000); +#endif + ++loopCount; + } + +/* +CL_QUEUED (command has been enqueued in the command-queue), +CL_SUBMITTED (enqueued command has been submitted by the host to the device associated with the command-queue), +CL_RUNNING (device is currently executing this command), +CL_COMPLETE (the command has completed), or +Error code given by a negative integer value. (command was abnormally terminated – this may be caused by a bad memory access etc.). +*/ + if(status != CL_COMPLETE && status != CL_SUBMITTED && + status != CL_RUNNING && status != CL_COMPLETE) + { + log_error( "ERROR: Incorrect status returned from clGetErrorStatus after event flush (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + /* Now wait */ + error = clFinish( queue ); + test_error( error, "Unable to finish events" ); + + FINISH_EVENT(queue); + return 0; +} + + +int test_event_finish_execute( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int status; + SETUP_EVENT( context, queue ); + + /* Now flush and finish all ops */ + error = clFinish( queue ); + test_error( error, "Unable to finish all events" ); + + /* Make sure it worked */ + error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventStatus didn't work!" ); + if( status != CL_COMPLETE ) + { + log_error( "ERROR: Incorrect status returned from clGetErrorStatus after event complete (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + FINISH_EVENT(queue); + return 0; +} + +int test_event_finish_array( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem streams[2]; + cl_float readArray[ 1024 * 32 ]; + cl_float writeArray[ 1024 * 32 ]; + cl_event events[2]; + int error; + cl_int status; + + + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 1024 * 32, NULL, &error ); + test_error( error, "Creating test array failed" ); + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 1024 * 32, NULL, &error ); + test_error( error, "Creating test array failed" ); + + error = clEnqueueReadBuffer(queue, streams[0], CL_FALSE, 0, sizeof(cl_float)*1024*32, (void *)readArray, 0, NULL, &events[0]); + test_error( error, "Unable to read testing kernel data" ); + + error = clEnqueueWriteBuffer(queue, streams[1], CL_FALSE, 0, sizeof(cl_float)*1024*32, (void *)writeArray, 0, NULL, &events[1]); + test_error( error, "Unable to write testing kernel data" ); + + /* Both should still be running */ + error = clGetEventInfo( events[0], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventStatus didn't work!" ); + if( status != CL_RUNNING && status != CL_QUEUED && status != CL_SUBMITTED && status != CL_COMPLETE) + { + log_error( "ERROR: Incorrect status returned from clGetErrorStatus during array read (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + error = clGetEventInfo( events[1], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventStatus didn't work!" ); + if( status != CL_RUNNING && status != CL_QUEUED && status != CL_SUBMITTED && status != CL_COMPLETE) + { + log_error( "ERROR: Incorrect status returned from clGetErrorStatus during array write (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + /* Now try finishing all ops */ + error = clFinish( queue ); + test_error( error, "Unable to finish all events" ); + + /* Double check status on both */ + error = clGetEventInfo( events[0], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventStatus didn't work!" ); + if( status != CL_COMPLETE ) + { + log_error( "ERROR: Incorrect status returned from clGetErrorStatus after array read complete (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + error = clGetEventInfo( events[1], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventStatus didn't work!" ); + if( status != CL_COMPLETE ) + { + log_error( "ERROR: Incorrect status returned from clGetErrorStatus after array write complete (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + clReleaseEvent( events[0] ); + clReleaseEvent( events[1] ); + + return 0; +} + + +#define NUM_EVENT_RUNS 100 + +int test_event_release_before_done( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + // Create a kernel to run + clProgramWrapper program; + clKernelWrapper kernel[NUM_EVENT_RUNS]; + size_t threads[1] = { 1000 }; + cl_event events[NUM_EVENT_RUNS]; + cl_int status; + clMemWrapper streams[NUM_EVENT_RUNS][2]; + int error, i; + + // Create a kernel + if( create_single_kernel_helper( context, &program, &kernel[0], 1, sample_long_test_kernel, "sample_test" ) ) + { + return -1; + } + + for( i = 1; i < NUM_EVENT_RUNS; i++ ) { + kernel[i] = clCreateKernel(program, "sample_test", &error); + test_error(error, "Unable to create kernel"); + } + + error = get_max_common_work_group_size( context, kernel[0], 1024, &threads[0] ); + test_error( error, "Unable to get work group size to use" ); + + // Create a set of streams to use as arguments + for( i = 0; i < NUM_EVENT_RUNS; i++ ) + { + streams[i][0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * threads[0], NULL, &error ); + streams[i][1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * threads[0], NULL, &error ); + if( ( streams[i][0] == NULL ) || ( streams[i][1] == NULL ) ) + { + log_error( "ERROR: Unable to allocate testing streams" ); + return -1; + } + } + + // Execute the kernels one by one, hopefully making sure they won't be done by the time we get to the end + for( i = 0; i < NUM_EVENT_RUNS; i++ ) + { + error = clSetKernelArg( kernel[i], 0, sizeof( cl_mem ), &streams[i][0] ); + error |= clSetKernelArg( kernel[i], 1, sizeof( cl_mem ), &streams[i][1] ); + test_error( error, "Unable to set kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel[i], 1, NULL, threads, threads, 0, NULL, &events[i]); + test_error( error, "Unable to execute test kernel" ); + } + + // Free all but the last event + for( i = 0; i < NUM_EVENT_RUNS - 1; i++ ) + { + clReleaseEvent( events[ i ] ); + } + + // Get status on the last one, then free it + error = clGetEventInfo( events[ NUM_EVENT_RUNS - 1 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Unable to get event status" ); + + clReleaseEvent( events[ NUM_EVENT_RUNS - 1 ] ); + + // Was the status still-running? + if( status == CL_COMPLETE ) + { + log_info( "WARNING: Events completed before they could be released, so test is a null-op. Increase workload and try again." ); + } + else if( status == CL_RUNNING || status == CL_QUEUED || status == CL_SUBMITTED ) + { + log_info( "Note: Event status was running or queued when released, so test was good.\n" ); + } + + // If we didn't crash by now, the test succeeded + clFinish( queue ); + + return 0; +} + +int test_event_enqueue_marker( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_int status; + SETUP_EVENT( context, queue ); + + /* Now we queue a marker and wait for that, which--since it queues afterwards--should guarantee the execute finishes too */ + clEventWrapper markerEvent; + //error = clEnqueueMarker( queue, &markerEvent ); + +#ifdef CL_VERSION_1_2 + error = clEnqueueMarkerWithWaitList(queue, 0, NULL, &markerEvent ); +#else + error = clEnqueueMarker( queue, &markerEvent ); +#endif + test_error( error, "Unable to queue marker" ); + /* Now we wait for it to be done, then test the status again */ + error = clWaitForEvents( 1, &markerEvent ); + test_error( error, "Unable to wait for marker event" ); + + /* Check the status of the first event */ + error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL ); + test_error( error, "Calling clGetEventInfo didn't work!" ); + if( status != CL_COMPLETE ) + { + log_error( "ERROR: Incorrect status returned from clGetEventInfo after event complete (%d:%s)\n", status, IGetStatusString( status ) ); + return -1; + } + + FINISH_EVENT(queue); + return 0; +} + +#ifdef CL_VERSION_1_2 +int test_event_enqueue_marker_with_list( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + + cl_int status; + SETUP_EVENT( context, queue ); + cl_event event_list[3]={ NULL, NULL, NULL}; + + size_t threads[1] = { 10 }, localThreads[1]={1}; + cl_uint event_count=2; + error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[0]); + test_error( error, " clEnqueueMarkerWithWaitList 1 " ); + + error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[1]); + test_error( error, " clEnqueueMarkerWithWaitList 2" ); + + error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, NULL); + test_error( error, " clEnqueueMarkerWithWaitList 3" ); + + // test the case event returned + error =clEnqueueMarkerWithWaitList(queue, event_count, event_list, &event_list[2]); + test_error( error, " clEnqueueMarkerWithWaitList " ); + + error = clReleaseEvent(event_list[0]); + error |= clReleaseEvent(event_list[1]); + test_error( error, "clReleaseEvent" ); + + error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[0]); + test_error( error, " clEnqueueMarkerWithWaitList 1 -1 " ); + + error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[1]); + test_error( error, " clEnqueueMarkerWithWaitList 2-2" ); + + // test the case event =NULL, caused [CL_INVALID_VALUE] : OpenCL Error : clEnqueueMarkerWithWaitList failed: event is a NULL value + error =clEnqueueMarkerWithWaitList(queue, event_count, event_list, NULL); + test_error( error, " clEnqueueMarkerWithWaitList " ); + + error = clReleaseEvent(event_list[0]); + error |= clReleaseEvent(event_list[1]); + error |= clReleaseEvent(event_list[2]); + test_error( error, "clReleaseEvent" ); + + FINISH_EVENT(queue); + return 0; +} +#endif + +#ifdef CL_VERSION_1_2 +int test_event_enqueue_barrier_with_list( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + + cl_int status; + SETUP_EVENT( context, queue ); + cl_event event_list[3]={ NULL, NULL, NULL}; + + size_t threads[1] = { 10 }, localThreads[1]={1}; + cl_uint event_count=2; + error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[0]); + test_error( error, " clEnqueueBarrierWithWaitList 1 " ); + + error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[1]); + test_error( error, " clEnqueueBarrierWithWaitList 2" ); + + error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, NULL); + test_error( error, " clEnqueueBarrierWithWaitList 20" ); + + // test the case event returned + error =clEnqueueBarrierWithWaitList(queue, event_count, event_list, &event_list[2]); + test_error( error, " clEnqueueBarrierWithWaitList " ); + + clReleaseEvent(event_list[0]); + clReleaseEvent(event_list[1]); + + error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[0]); + test_error( error, " clEnqueueBarrierWithWaitList 1 " ); + + error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[1]); + test_error( error, " clEnqueueBarrierWithWaitList 2" ); + + // test the case event =NULL, caused [CL_INVALID_VALUE] : OpenCL Error : clEnqueueMarkerWithWaitList failed: event is a NULL value + error = clEnqueueBarrierWithWaitList(queue, event_count, event_list, NULL); + test_error( error, " clEnqueueBarrierWithWaitList " ); + + clReleaseEvent(event_list[0]); + clReleaseEvent(event_list[1]); + clReleaseEvent(event_list[2]); + + FINISH_EVENT(queue); + return 0; +} +#endif diff --git a/test_conformance/events/test_userevents.cpp b/test_conformance/events/test_userevents.cpp new file mode 100644 index 00000000..39dea376 --- /dev/null +++ b/test_conformance/events/test_userevents.cpp @@ -0,0 +1,293 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#if defined(__APPLE__) + #include + #include +#else + #include + #include +#endif +#include +#include +#include +#include "../../test_common/harness/kernelHelpers.h" + +/////////////////////////////////////////////////////////////////////////////// +// ATF performance framework. + +#if USE_ATF +#include +#define test_start() ATFTestStart() +#define log_perf(_number, _higherBetter, _numType, _format, ...) ATFLogPerformanceNumber(_number, _higherBetter, _numType, _format,##__VA_ARGS__) +#define log_info ATFLogInfo +#define log_error ATFLogError +#define log_no_atf +#define test_finish() ATFTestFinish() +#else +#define test_start() +#define log_perf(_number, _higherBetter, _numType, _format, ...) printf("Performance Number " _format " (in %s, %s): %g\n",##__VA_ARGS__, _numType, _higherBetter?"higher is better":"lower is better" , _number) +#define log_info(...) fprintf(stdout, ## __VA_ARGS__ ) +#define log_error(...) fprintf(stderr, ## __VA_ARGS__ ) +#define log_info_no_atf(...) log_info(## __VA_ARGS__ ) +#define test_finish() +#endif + +/////////////////////////////////////////////////////////////////////////////// +// CL error checking. + +#define CL_DEVICE_TYPE_ENV_MUST_BE( bitfield_ )\ +{\ +cl_device_type device_type = CL_DEVICE_TYPE_DEFAULT;\ +const char* device_env = getenv("CL_DEVICE_TYPE");\ +if (device_env != NULL) {\ +if (!strcmp( device_env, "gpu" ) || !strcmp( device_env, "CL_DEVICE_TYPE_GPU" ))\ +device_type = CL_DEVICE_TYPE_GPU;\ +else if(!strcmp( device_env, "cpu" ) || !strcmp( device_env, "CL_DEVICE_TYPE_CPU" ))\ +device_type = CL_DEVICE_TYPE_CPU;\ +else if(!strcmp( device_env, "default" ) || !strcmp( device_env, "CL_DEVICE_TYPE_DEFAULT" ))\ +device_type = CL_DEVICE_TYPE_DEFAULT;\ +if (!(device_type & bitfield_)) {\ +log_error( "CL_DEVICE_TYPE environment variable \"%s\" must be \"%s\".", device_env, #bitfield_ );\ +abort();\ +}\ +}\ +}\ + +#define CL_DEVICE_TYPE_ENV( device_type_ )\ +{\ +const char* device_env = getenv("CL_DEVICE_TYPE");\ +if (device_env != NULL) {\ +if (!strcmp( device_env, "gpu" ) || !strcmp( device_env, "CL_DEVICE_TYPE_GPU" ))\ +device_type_ = CL_DEVICE_TYPE_GPU;\ +else if(!strcmp( device_env, "cpu" ) || !strcmp( device_env, "CL_DEVICE_TYPE_CPU" ))\ +device_type_ = CL_DEVICE_TYPE_CPU;\ +else if(!strcmp( device_env, "default" ) || !strcmp( device_env, "CL_DEVICE_TYPE_DEFAULT" ))\ +device_type_ = CL_DEVICE_TYPE_DEFAULT;\ +}\ +} + +#if defined(_MSC_VER) +#define CL_EXIT_ERROR(cmd,...) \ +{ \ +if ((cmd) != CL_SUCCESS) { \ +log_error("CL ERROR: %s %u: ", __FILE__,__LINE__);\ +log_error(## __VA_ARGS__ );\ +log_error("\n");\ +return -1;\ +}\ +} +#else +#define CL_EXIT_ERROR(cmd,format,...) \ +{ \ +if ((cmd) != CL_SUCCESS) { \ +log_error("CL ERROR: %s %u: ", __FILE__,__LINE__);\ +log_error(format,## __VA_ARGS__ );\ +log_error("\n");\ +return -1;\ +}\ +} +#endif + +#define CL_EXIT_BUILD_ERROR(cmd,program,format,...) \ +{ \ +if ((cmd) != CL_SUCCESS) { \ +cl_uint num_devices_;\ +clGetProgramInfo(program,CL_PROGRAM_NUM_DEVICES,sizeof(num_devices_),&num_devices_,NULL);\ +cl_device_id *device_list;\ +device_list=(cl_device_id *)malloc(num_devices_*sizeof(cl_device_id));\ +clGetProgramInfo(program,CL_PROGRAM_DEVICES,num_devices_*sizeof(cl_device_id),device_list,NULL);\ +for (unsigned i=0;i= CL_SUBMITTED) ? CL_SUCCESS : -1,"clGetEventInfo %u returned wrong status before user event",i); + } + + log_info("Setting user event status to complete\n"); + CL_EXIT_ERROR(clSetUserEventStatus(u1,CL_COMPLETE),"clSetUserEventStatus failed"); + + log_info("Waiting for tasks to finish executing\n"); + CL_EXIT_ERROR(clWaitForEvents( 1, &e[N-1] ),"clWaitForEvent failed"); + + log_info("Checking task status after setting user event status\n"); + for (cl_uint i = 0; i != N; ++i) { + CL_EXIT_ERROR(clGetEventInfo(e[i],CL_EVENT_COMMAND_EXECUTION_STATUS,sizeof s,&s,0),"clGetEventInfo failed"); + CL_EXIT_ERROR((s != CL_QUEUED) ? CL_SUCCESS : -1,"clGetEventInfo %u returned wrong status %04x after successful user event",i,s); + } + + CL_EXIT_ERROR(clReleaseEvent(u1),"clReleaseEvent failed"); + + for (cl_uint i = 0; i != N; ++i) + CL_EXIT_ERROR(clReleaseEvent(e[i]),"clReleaseEvent failed"); + + log_info("Successful user event case passed.\n"); + + } + + // Test unsuccessful user event case. /////////////////////////////////////////////////////////////////// + { + cl_event u2 = clCreateUserEvent( context, &err ); + CL_EXIT_ERROR(err,"clCreateUserEvent failed"); + + cl_event e[4]; + cl_uint N = sizeof e / sizeof(cl_event); + + log_info("Enqueuing tasks\n"); + for (cl_uint i = 0; i != N; ++i) + CL_EXIT_ERROR(clEnqueueTask(queue,k0,1,&u2,&e[i]),"clEnqueueTaskFailed"); + + log_info("Checking task status before setting user event status\n"); + for (cl_uint i = 0; i != N; ++i) { + CL_EXIT_ERROR(clGetEventInfo(e[i],CL_EVENT_COMMAND_EXECUTION_STATUS,sizeof s,&s,0),"clGetEventInfo failed"); + CL_EXIT_ERROR((s == CL_QUEUED || s == CL_SUBMITTED) ? CL_SUCCESS : -1,"clGetEventInfo %u returned wrong status %d before user event",i, (int) s); + } + + log_info("Setting user event status to unsuccessful result\n"); + CL_EXIT_ERROR(clSetUserEventStatus(u2,-1),"clSetUserEventStatus failed"); + + log_info("Waiting for tasks to finish executing\n"); + CL_EXIT_ERROR((clWaitForEvents( N, &e[0] )!=CL_SUCCESS) ? CL_SUCCESS : -1,"clWaitForEvent succeeded when it should have failed"); + + log_info("Checking task status after setting user event status\n"); + for (cl_uint i = 0; i != N; ++i) { + CL_EXIT_ERROR(clGetEventInfo(e[i],CL_EVENT_COMMAND_EXECUTION_STATUS,sizeof s,&s,0),"clGetEventInfo failed"); + CL_EXIT_ERROR((s != CL_QUEUED) ? CL_SUCCESS : -1,"clGetEventInfo %u returned wrong status %04x after unsuccessful user event",i,s); + } + + CL_EXIT_ERROR(clReleaseEvent(u2),"clReleaseEvent failed"); + + for (cl_uint i = 0; i != N; ++i) + CL_EXIT_ERROR(clReleaseEvent(e[i]),"clReleaseEvent failed"); + + log_info("Unsuccessful user event case passed.\n"); + } + + return 0; + +} + +#if 0 +int main(int argc, char** argv) +{ + + cl_int err; + + test_start(); + + cl_device_type device_type; + CL_DEVICE_TYPE_ENV( device_type ); + + cl_device_id device_id; + CL_EXIT_ERROR(clGetDeviceIDs(NULL, device_type, 1, &device_id, NULL),"GetDeviceIDs"); + + // Create a context. + cl_context context = clCreateContext(0, 1, &device_id, NULL, NULL, &err); + CL_EXIT_ERROR(err,"CreateContext"); + + // Create a command queue. + q = clCreateCommandQueueWithProperties(context,device_id,0,&err); + CL_EXIT_ERROR(err,"clCreateCommandQueue failed"); + + int ret = test_userevents( device_type, context, queue, 0 ); + + test_finish(); + + return ret; +} +#endif diff --git a/test_conformance/events/test_userevents_multithreaded.cpp b/test_conformance/events/test_userevents_multithreaded.cpp new file mode 100644 index 00000000..6c54e780 --- /dev/null +++ b/test_conformance/events/test_userevents_multithreaded.cpp @@ -0,0 +1,82 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "action_classes.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/genericThread.h" + +#if !defined (_MSC_VER) + #include +#endif // !_MSC_VER + +class releaseEvent_thread : public genericThread +{ + public: + releaseEvent_thread( cl_event *event ) : mEvent( event ) {} + + cl_event * mEvent; + + protected: + virtual void * IRun( void ) + { + usleep( 1000000 ); + log_info( "\tTriggering gate from separate thread...\n" ); + clSetUserEventStatus( *mEvent, CL_COMPLETE ); + return NULL; + } +}; + +int test_userevents_multithreaded( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_int error; + + + // Set up a user event to act as a gate + clEventWrapper gateEvent = clCreateUserEvent( context, &error ); + test_error( error, "Unable to create user gate event" ); + + // Set up a few actions gated on the user event + NDRangeKernelAction action1; + ReadBufferAction action2; + WriteBufferAction action3; + + clEventWrapper actionEvents[ 3 ]; + Action * actions[] = { &action1, &action2, &action3, NULL }; + + for( int i = 0; actions[ i ] != NULL; i++ ) + { + error = actions[ i ]->Setup( deviceID, context, queue ); + test_error( error, "Unable to set up test action" ); + + error = actions[ i ]->Execute( queue, 1, &gateEvent, &actionEvents[ i ] ); + test_error( error, "Unable to execute test action" ); + } + + // Now, instead of releasing the gate, we spawn a separate thread to do so + releaseEvent_thread thread( &gateEvent ); + log_info( "\tStarting trigger thread...\n" ); + thread.Start(); + + log_info( "\tWaiting for actions...\n" ); + error = clWaitForEvents( 3, &actionEvents[ 0 ] ); + test_error( error, "Unable to wait for action events" ); + + log_info( "\tActions completed.\n" ); + + // If we got here without error, we're good + return 0; +} + diff --git a/test_conformance/events/test_waitlists.cpp b/test_conformance/events/test_waitlists.cpp new file mode 100644 index 00000000..fa5db3f2 --- /dev/null +++ b/test_conformance/events/test_waitlists.cpp @@ -0,0 +1,322 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "action_classes.h" + + +extern const char *IGetStatusString( cl_int status ); + +#define PRINT_OPS 0 + +int test_waitlist( cl_device_id device, cl_context context, cl_command_queue queue, Action *actionToTest, bool multiple ) +{ + NDRangeKernelAction actions[ 2 ]; + clEventWrapper events[ 3 ]; + cl_int status[ 3 ]; + cl_int error; + + if (multiple) + log_info("\tExecuting reference event 0, then reference event 1 with reference event 0 in its waitlist, then test event 2 with reference events 0 and 1 in its waitlist.\n"); + else + log_info("\tExecuting reference event 0, then test event 2 with reference event 0 in its waitlist.\n"); + + // Set up the first base action to wait against + error = actions[ 0 ].Setup( device, context, queue ); + test_error( error, "Unable to setup base event to wait against" ); + + if( multiple ) + { + // Set up a second event to wait against + error = actions[ 1 ].Setup( device, context, queue ); + test_error( error, "Unable to setup second base event to wait against" ); + } + + // Now set up the actual action to test + error = actionToTest->Setup( device, context, queue ); + test_error( error, "Unable to set up test event" ); + + // Execute all events now + if (PRINT_OPS) log_info("\tExecuting action 0...\n"); + error = actions[ 0 ].Execute( queue, 0, NULL, &events[ 0 ] ); + test_error( error, "Unable to execute first event" ); + + if( multiple ) + { + if (PRINT_OPS) log_info("\tExecuting action 1...\n"); + error = actions[ 1 ].Execute( queue, 1, &events[0], &events[ 1 ] ); + test_error( error, "Unable to execute second event" ); + } + + // Sanity check + if( multiple ) { + if (PRINT_OPS) log_info("\tChecking status of action 1...\n"); + error = clGetEventInfo( events[ 1 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 1 ] ), &status[ 1 ], NULL ); + test_error( error, "Unable to get event status" ); + } + if (PRINT_OPS) log_info("\tChecking status of action 0...\n"); + error = clGetEventInfo( events[ 0 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 0 ] ), &status[ 0 ], NULL ); + test_error( error, "Unable to get event status" ); + + log_info("\t\tEvent status after starting reference events: reference event 0: %s, reference event 1: %s, test event 2: %s.\n", + IGetStatusString( status[ 0 ] ), (multiple ? IGetStatusString( status[ 1 ] ) : "N/A"), "N/A"); + + if( ( status[ 0 ] == CL_COMPLETE ) || ( multiple && status[ 1 ] == CL_COMPLETE ) ) + { + log_info( "WARNING: Reference event(s) already completed before we could execute test event! Possible that the reference event blocked (implicitly passing)\n" ); + return 0; + } + + if (PRINT_OPS) log_info("\tExecuting action to test...\n"); + error = actionToTest->Execute( queue, ( multiple ) ? 2 : 1, &events[ 0 ], &events[ 2 ] ); + test_error( error, "Unable to execute test event" ); + + // Hopefully, the first event is still running + if (PRINT_OPS) log_info("\tChecking status of action to test 2...\n"); + error = clGetEventInfo( events[ 2 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 2 ] ), &status[ 2 ], NULL ); + test_error( error, "Unable to get event status" ); + if( multiple ) { + if (PRINT_OPS) log_info("\tChecking status of action 1...\n"); + error = clGetEventInfo( events[ 1 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 1 ] ), &status[ 1 ], NULL ); + test_error( error, "Unable to get event status" ); + } + if (PRINT_OPS) log_info("\tChecking status of action 0...\n"); + error = clGetEventInfo( events[ 0 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 0 ] ), &status[ 0 ], NULL ); + test_error( error, "Unable to get event status" ); + + log_info("\t\tEvent status after starting test event: reference event 0: %s, reference event 1: %s, test event 2: %s.\n", + IGetStatusString( status[ 0 ] ), (multiple ? IGetStatusString( status[ 1 ] ) : "N/A"), IGetStatusString( status[ 2 ] )); + + if( multiple ) + { + if( status[ 0 ] == CL_COMPLETE && status[ 1 ] == CL_COMPLETE ) + { + log_info( "WARNING: Both events completed, so unable to test further (implicitly passing).\n" ); + clFinish( queue ); + return 0; + } + + if(status[1] == CL_COMPLETE && status[0] != CL_COMPLETE) + { + log_error("ERROR: Test failed because the second wait event is complete and the first is not.(status: 0: %s and 1: %s)\n", IGetStatusString( status[ 0 ] ), IGetStatusString( status[ 1 ] ) ); + clFinish( queue ); + return -1; + } + } + else + { + if( status[ 0 ] == CL_COMPLETE ) + { + log_info( "WARNING: Reference event completed, so unable to test further (implicitly passing).\n" ); + clFinish( queue ); + return 0; + } + if( status[ 0 ] != CL_RUNNING && status[ 0 ] != CL_QUEUED && status[ 0 ] != CL_SUBMITTED ) + { + log_error( "ERROR: Test failed because first wait event is not currently running, queued, or submitted! (status: 0: %s)\n", IGetStatusString( status[ 0 ] ) ); + clFinish( queue ); + return -1; + } + } + + if( status[ 2 ] != CL_QUEUED && status[ 2 ] != CL_SUBMITTED ) + { + log_error( "ERROR: Test event is not waiting to run! (status: 2: %s)\n", IGetStatusString( status[ 2 ] ) ); + clFinish( queue ); + return -1; + } + + // Now wait for the first reference event + if (PRINT_OPS) log_info("\tWaiting for action 1 to finish...\n"); + error = clWaitForEvents( 1, &events[ 0 ] ); + test_error( error, "Unable to wait for reference event" ); + + // Grab statuses again + if (PRINT_OPS) log_info("\tChecking status of action to test 2...\n"); + error = clGetEventInfo( events[ 2 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 2 ] ), &status[ 2 ], NULL ); + test_error( error, "Unable to get event status" ); + if( multiple ) { + if (PRINT_OPS) log_info("\tChecking status of action 1...\n"); + error = clGetEventInfo( events[ 1 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 1 ] ), &status[ 1 ], NULL ); + test_error( error, "Unable to get event status" ); + } + if (PRINT_OPS) log_info("\tChecking status of action 0...\n"); + error = clGetEventInfo( events[ 0 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 0 ] ), &status[ 0 ], NULL ); + test_error( error, "Unable to get event status" ); + + log_info("\t\tEvent status after waiting for reference event 0: reference event 0: %s, reference event 1: %s, test event 2: %s.\n", + IGetStatusString( status[ 0 ] ), (multiple ? IGetStatusString( status[ 1 ] ) : "N/A"), IGetStatusString( status[ 2 ] )); + + // Sanity + if( status[ 0 ] != CL_COMPLETE ) + { + log_error( "ERROR: Waited for first event but it's not complete (status: 0: %s)\n", IGetStatusString( status[ 0 ] ) ); + clFinish( queue ); + return -1; + } + + // If we're multiple, and the second event isn't complete, then our test event should still be queued + if( multiple && status[ 1 ] != CL_COMPLETE ) + { + if( status[ 1 ] == CL_RUNNING && status[ 2 ] == CL_RUNNING ) { + log_error("ERROR: Test event and second event are both running.\n"); + clFinish( queue ); + return -1; + } + if( status[ 2 ] != CL_QUEUED && status[ 2 ] != CL_SUBMITTED ) + { + log_error( "ERROR: Test event did not wait for second event before starting! (status of ref: 1: %s, of test: 2: %s)\n", IGetStatusString( status[ 1 ] ), IGetStatusString( status[ 2 ] ) ); + clFinish( queue ); + return -1; + } + + // Now wait for second event to complete, too + if (PRINT_OPS) log_info("\tWaiting for action 1 to finish...\n"); + error = clWaitForEvents( 1, &events[ 1 ] ); + test_error( error, "Unable to wait for second reference event" ); + + // Grab statuses again + if (PRINT_OPS) log_info("\tChecking status of action to test 2...\n"); + error = clGetEventInfo( events[ 2 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 2 ] ), &status[ 2 ], NULL ); + test_error( error, "Unable to get event status" ); + if( multiple ) { + if (PRINT_OPS) log_info("\tChecking status of action 1...\n"); + error = clGetEventInfo( events[ 1 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 1 ] ), &status[ 1 ], NULL ); + test_error( error, "Unable to get event status" ); + } + if (PRINT_OPS) log_info("\tChecking status of action 0...\n"); + error = clGetEventInfo( events[ 0 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 0 ] ), &status[ 0 ], NULL ); + test_error( error, "Unable to get event status" ); + + log_info("\t\tEvent status after waiting for reference event 1: reference event 0: %s, reference event 1: %s, test event 2: %s.\n", + IGetStatusString( status[ 0 ] ), (multiple ? IGetStatusString( status[ 1 ] ) : "N/A"), IGetStatusString( status[ 2 ] )); + + // Sanity + if( status[ 1 ] != CL_COMPLETE ) + { + log_error( "ERROR: Waited for second reference event but it didn't complete (status: 1: %s)\n", IGetStatusString( status[ 1 ] ) ); + clFinish( queue ); + return -1; + } + } + + // At this point, the test event SHOULD be running, but if it completed, we consider it a pass + if( status[ 2 ] == CL_COMPLETE ) + { + log_info( "WARNING: Test event already completed. Assumed valid.\n" ); + clFinish( queue ); + return 0; + } + if( status[ 2 ] != CL_RUNNING && status[ 2 ] != CL_SUBMITTED && status[ 2 ] != CL_QUEUED) + { + log_error( "ERROR: Second event did not start running after reference event(s) completed! (status: 2: %s)\n", IGetStatusString( status[ 2 ] ) ); + clFinish( queue ); + return -1; + } + + // Wait for the test event, then return + if (PRINT_OPS) log_info("\tWaiting for action 2 to test to finish...\n"); + error = clWaitForEvents( 1, &events[ 2 ] ); + test_error( error, "Unable to wait for test event" ); + + error |= clGetEventInfo( events[ 2 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 2 ] ), &status[ 2 ], NULL ); + test_error( error, "Unable to get event status" ); + + log_info("\t\tEvent status after waiting for test event: reference event 0: %s, reference event 1: %s, test event 2: %s.\n", + IGetStatusString( status[ 0 ] ), (multiple ? IGetStatusString( status[ 1 ] ) : "N/A"), IGetStatusString( status[ 2 ] )); + + // Sanity + if( status[ 2 ] != CL_COMPLETE ) + { + log_error( "ERROR: Test event didn't complete (status: 2: %s)\n", IGetStatusString( status[ 2 ] ) ); + clFinish( queue ); + return -1; + } + + clFinish(queue); + return 0; +} + +#define TEST_ACTION( name ) \ + { \ + name##Action action; \ + log_info( "-- Testing " #name " (waiting on 1 event)...\n" ); \ + if( ( error = test_waitlist( deviceID, context, queue, &action, false ) ) != CL_SUCCESS ) \ + retVal++; \ + clFinish( queue ); \ + } \ + if( error == CL_SUCCESS ) /* Only run multiples test if single test passed */ \ + { \ + name##Action action; \ + log_info( "-- Testing " #name " (waiting on 2 events)...\n" ); \ + if( ( error = test_waitlist( deviceID, context, queue, &action, true ) ) != CL_SUCCESS ) \ + retVal++; \ + clFinish( queue ); \ + } + +int test_waitlists( cl_device_id deviceID, cl_context context, cl_command_queue oldQueue, int num_elements ) +{ + cl_int error; + int retVal = 0; + cl_queue_properties props[] = {CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, 0}; + + if( !checkDeviceForQueueSupport( deviceID, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE ) ) + { + log_info( "WARNING: Device does not support out-of-order exec mode; skipping test.\n" ); + return 0; + } + + clCommandQueueWrapper queue = clCreateCommandQueueWithProperties( context, deviceID, &props[0], &error ); + test_error(error, "Unable to create out-of-order queue"); + + log_info( "\n" ); + + TEST_ACTION( NDRangeKernel ) + + TEST_ACTION( ReadBuffer ) + TEST_ACTION( WriteBuffer ) + TEST_ACTION( MapBuffer ) + TEST_ACTION( UnmapBuffer ) + + if( checkForImageSupport( deviceID ) == CL_IMAGE_FORMAT_NOT_SUPPORTED ) + { + log_info( "\nNote: device does not support images. Skipping remainder of waitlist tests...\n" ); + } + else + { + TEST_ACTION( ReadImage2D ) + TEST_ACTION( WriteImage2D ) + TEST_ACTION( CopyImage2Dto2D ) + TEST_ACTION( Copy2DImageToBuffer ) + TEST_ACTION( CopyBufferTo2DImage ) + TEST_ACTION( MapImage ) + + if( checkFor3DImageSupport( deviceID ) == CL_IMAGE_FORMAT_NOT_SUPPORTED ) + log_info("Device does not support 3D images. Skipping remainder of waitlist tests...\n"); + else + { + TEST_ACTION( ReadImage3D ) + TEST_ACTION( WriteImage3D ) + TEST_ACTION( CopyImage2Dto3D ) + TEST_ACTION( CopyImage3Dto2D ) + TEST_ACTION( CopyImage3Dto3D ) + TEST_ACTION( Copy3DImageToBuffer ) + TEST_ACTION( CopyBufferTo3DImage ) + } + } + + return retVal; +} + diff --git a/test_conformance/generic_address_space/CMakeLists.txt b/test_conformance/generic_address_space/CMakeLists.txt new file mode 100644 index 00000000..da347abc --- /dev/null +++ b/test_conformance/generic_address_space/CMakeLists.txt @@ -0,0 +1,18 @@ +set(MODULE_NAME GENERIC_ADDRESS_SPACE) + +set(${MODULE_NAME}_SOURCES + advanced_tests.cpp + basic_tests.cpp + main.cpp + stress_tests.cpp + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) + +# end of file # diff --git a/test_conformance/generic_address_space/Makefile b/test_conformance/generic_address_space/Makefile new file mode 100644 index 00000000..b59fe4c6 --- /dev/null +++ b/test_conformance/generic_address_space/Makefile @@ -0,0 +1,44 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + basic_tests.cpp \ + advanced_tests.cpp \ + stress_tests.cpp \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/typeWrappers.cpp \ + ../../test_common/harness/mt19937.c \ + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +HEADERS = +TARGET = test_uniform_address_space +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/generic_address_space/advanced_tests.cpp b/test_conformance/generic_address_space/advanced_tests.cpp new file mode 100644 index 00000000..05bd7ae9 --- /dev/null +++ b/test_conformance/generic_address_space/advanced_tests.cpp @@ -0,0 +1,1031 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" +#include "base.h" + +#include +#include +#include +#include + +typedef enum { + ARG_TYPE_NONE, + + ARG_TYPE_HOST_PTR, + ARG_TYPE_HOST_LOCAL, + + ARG_TYPE_COARSE_GRAINED_SVM, + ARG_TYPE_FINE_GRAINED_BUFFER_SVM, + ARG_TYPE_FINE_GRAINED_SYSTEM_SVM, + ARG_TYPE_ATOMICS_SVM +} ExtraKernelArgMemType; + +class CSVMWrapper { +public: + CSVMWrapper() : ptr_(NULL), context_(NULL) { } + + void Attach(cl_context context, void *ptr) { + context_ = context; + ptr_ = ptr; + } + + ~CSVMWrapper() { + if (ptr_) + clSVMFree(context_, ptr_); + } + + operator void *() { + return ptr_; + } + +private: + void *ptr_; + cl_context context_; +}; + +class CAdvancedTest : public CTest { +public: + CAdvancedTest(const std::vector& kernel) : CTest(), _kernels(kernel), _extraKernelArgMemType(ARG_TYPE_NONE) { + + } + + CAdvancedTest(const std::string& library, const std::vector& kernel) : CTest(), _libraryCode(library), _kernels(kernel), _extraKernelArgMemType(ARG_TYPE_NONE) { + + } + + CAdvancedTest(const std::string& kernel, ExtraKernelArgMemType argType = ARG_TYPE_NONE) : CTest(), _kernels(1, kernel), _extraKernelArgMemType(argType) { + + } + + CAdvancedTest(const std::string& library, const std::string& kernel) : CTest(), _libraryCode(library), _kernels(1, kernel), _extraKernelArgMemType(ARG_TYPE_NONE) { + + } + + int PrintCompilationLog(cl_program program, cl_device_id device) { + cl_int error; + size_t buildLogSize = 0; + + error = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &buildLogSize); + test_error(error, "clGetProgramBuildInfo failed"); + + std::string log; + log.resize(buildLogSize); + + error = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, buildLogSize, &log[0], NULL); + test_error(error, "clGetProgramBuildInfo failed"); + + log_error("Build log for device is:\n------------\n"); + log_error("%s\n", log.c_str() ); + log_error( "\n----------\n" ); + + return CL_SUCCESS; + } + + int ExecuteSubcase(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, const std::string& src) { + cl_int error; + + clProgramWrapper program, preCompiledLibrary, library, finalProgram; + clKernelWrapper kernel; + + const char *srcPtr = src.c_str(); + + if (!_libraryCode.empty()) { + program = clCreateProgramWithSource(context, 1, &srcPtr, NULL, &error); + test_error(error, "clCreateProgramWithSource failed"); + + error = clCompileProgram(program, 1, &deviceID, "-cl-std=CL2.0", 0, NULL, NULL, NULL, NULL); + + if (error != CL_SUCCESS) + PrintCompilationLog(program, deviceID); + test_error(error, "clCompileProgram failed"); + + const char *srcPtrLibrary = _libraryCode.c_str(); + + preCompiledLibrary = clCreateProgramWithSource(context, 1, &srcPtrLibrary, NULL, &error); + test_error(error, "clCreateProgramWithSource failed"); + + error = clCompileProgram(preCompiledLibrary, 1, &deviceID, "-cl-std=CL2.0", 0, NULL, NULL, NULL, NULL); + + if (error != CL_SUCCESS) + PrintCompilationLog(preCompiledLibrary, deviceID); + test_error(error, "clCompileProgram failed"); + + library = clLinkProgram(context, 1, &deviceID, "-create-library", 1, &preCompiledLibrary, NULL, NULL, &error); + test_error(error, "clLinkProgram failed"); + + cl_program objects[] = { program, library }; + finalProgram = clLinkProgram(context, 1, &deviceID, "", 2, objects, NULL, NULL, &error); + test_error(error, "clLinkProgram failed"); + + kernel = clCreateKernel(finalProgram, "testKernel", &error); + test_error(error, "clCreateKernel failed"); + } + + else { + if (create_single_kernel_helper_with_build_options(context, &program, &kernel, 1, &srcPtr, "testKernel", "-cl-std=CL2.0")) { + log_error("create_single_kernel_helper failed\n"); + return -1; + } + } + + size_t bufferSize = num_elements * sizeof(cl_uint); + clMemWrapper buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY, bufferSize, NULL, &error); + test_error(error, "clCreateBuffer failed"); + + error = clSetKernelArg(kernel, 0, sizeof(buffer), &buffer); + test_error(error, "clSetKernelArg(0) failed"); + + // Warning: the order below is very important as SVM buffer cannot be free'd before corresponding mem_object + CSVMWrapper svmWrapper; + clMemWrapper extraArg; + std::vector extraArgData(num_elements); + for (cl_uint i = 0; i < (cl_uint)num_elements; i++) + extraArgData[i] = i; + + if (_extraKernelArgMemType != ARG_TYPE_NONE) { + if (_extraKernelArgMemType == ARG_TYPE_HOST_PTR) { + extraArg = clCreateBuffer(context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, bufferSize, &extraArgData[0], &error); + test_error(error, "clCreateBuffer failed"); + } + + else { + void *ptr = NULL; + + switch (_extraKernelArgMemType) { + case ARG_TYPE_COARSE_GRAINED_SVM: + ptr = clSVMAlloc(context, CL_MEM_READ_WRITE, bufferSize, 0); + break; + case ARG_TYPE_FINE_GRAINED_BUFFER_SVM: + ptr = clSVMAlloc(context, CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_READ_WRITE, bufferSize, 0); + break; + case ARG_TYPE_FINE_GRAINED_SYSTEM_SVM: + ptr = &extraArgData[0]; + break; + case ARG_TYPE_ATOMICS_SVM: + ptr = clSVMAlloc(context, CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS | CL_MEM_READ_WRITE, bufferSize, 0); + break; + default: + break; + } + + if(_extraKernelArgMemType != ARG_TYPE_HOST_LOCAL) { + if (!ptr) { + log_error("Allocation failed\n"); + return -1; + } + + if (_extraKernelArgMemType != ARG_TYPE_FINE_GRAINED_SYSTEM_SVM) { + svmWrapper.Attach(context, ptr); + } + + if (_extraKernelArgMemType == ARG_TYPE_COARSE_GRAINED_SVM) { + error = clEnqueueSVMMap(queue, CL_TRUE, CL_MAP_WRITE, ptr, bufferSize, 0, NULL, NULL); + test_error(error, "clEnqueueSVMMap failed"); + } + + memcpy(ptr, &extraArgData[0], bufferSize); + + if (_extraKernelArgMemType == ARG_TYPE_COARSE_GRAINED_SVM) { + error = clEnqueueSVMUnmap(queue, ptr, 0, NULL, NULL); + test_error(error, "clEnqueueSVMUnmap failed"); + clFinish(queue); + } + + extraArg = clCreateBuffer(context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, bufferSize, ptr, &error); + test_error(error, "clCreateBuffer from SVM buffer failed"); + } + } + + if(_extraKernelArgMemType == ARG_TYPE_HOST_LOCAL) + error = clSetKernelArg(kernel, 1, bufferSize, NULL); + else + error = clSetKernelArg(kernel, 1, sizeof(extraArg), &extraArg); + + + test_error(error, "clSetKernelArg(1) failed"); + } + + size_t globalWorkGroupSize = num_elements; + size_t localWorkGroupSize = 0; + error = get_max_common_work_group_size(context, kernel, globalWorkGroupSize, &localWorkGroupSize); + test_error(error, "Unable to get common work group size"); + + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &globalWorkGroupSize, &localWorkGroupSize, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + // verify results + std::vector results(num_elements); + + error = clEnqueueReadBuffer(queue, buffer, CL_TRUE, 0, bufferSize, &results[0], 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + size_t passCount = std::count(results.begin(), results.end(), 1); + if (passCount != results.size()) { + std::vector::iterator iter = std::find(results.begin(), results.end(), 0); + log_error("Verification on device failed at index %ld\n", std::distance(results.begin(), iter)); + log_error("%ld out of %ld failed\n", (results.size()-passCount), results.size()); + return -1; + } + + return CL_SUCCESS; + } + + int Execute(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + cl_int result = CL_SUCCESS; + + for (std::vector::const_iterator it = _kernels.begin(); it != _kernels.end(); ++it) { + log_info("Executing subcase #%ld out of %ld\n", (it - _kernels.begin() + 1), _kernels.size()); + + result |= ExecuteSubcase(deviceID, context, queue, num_elements, *it); + } + + return result; + } + +private: + const std::string _libraryCode; + const std::vector _kernels; + const ExtraKernelArgMemType _extraKernelArgMemType; +}; + +int test_library_function(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + const std::string LIBRARY_FUNCTION = common::CONFORMANCE_VERIFY_FENCE + + NL + NL "bool helperFunction(float *floatp, float val) {" + NL " if (!isFenceValid(get_fence(floatp)))" + NL " return false;" + NL + NL " if (*floatp != val)" + NL " return false;" + NL + NL " return true;" + NL "}" + NL; + + const std::string KERNEL_FUNCTION = + NL + NL "extern bool helperFunction(float *floatp, float val);" + NL + NL "__global float gfloat = 1.0f;" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " __global float *gfloatp = &gfloat;" + NL " __local float lfloat;" + NL " lfloat = 2.0f;" + NL " __local float *lfloatp = &lfloat;" + NL " float pfloat = 3.0f;" + NL " __private float *pfloatp = &pfloat;" + NL + NL " uint failures = 0;" + NL + NL " failures += helperFunction(gfloatp, gfloat) ? 0 : 1;" + NL " failures += helperFunction(lfloatp, lfloat) ? 0 : 1;" + NL " failures += helperFunction(pfloatp, pfloat) ? 0 : 1;" + NL + NL " results[tid] = failures == 0;" + NL "}" + NL; + + CAdvancedTest test(LIBRARY_FUNCTION, KERNEL_FUNCTION); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_generic_variable_volatile(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + std::vector KERNEL_FUNCTIONS; + + KERNEL_FUNCTIONS.push_back(common::CONFORMANCE_VERIFY_FENCE + + NL + NL "bool helperFunction(float *floatp, float val) {" + NL " if (!isFenceValid(get_fence(floatp)))" + NL " return false;" + NL + NL " if (*floatp != val)" + NL " return false;" + NL + NL " return true;" + NL "}" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " static __global float val;" + NL " val = 0.1f;" + NL " float * volatile ptr = &val;" + NL + NL " results[tid] = helperFunction(ptr, val);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back(common::CONFORMANCE_VERIFY_FENCE + + NL + NL "bool helperFunction(float *floatp, float val) {" + NL " if (!isFenceValid(get_fence(floatp)))" + NL " return false;" + NL + NL " if (*floatp != val)" + NL " return false;" + NL + NL " return true;" + NL "}" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " __local float val;" + NL " val = 0.1f;" + NL " float * ptr = &val;" + NL + NL " results[tid] = helperFunction(ptr, val);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back(common::CONFORMANCE_VERIFY_FENCE + + NL + NL "bool helperFunction(float *floatp, float val) {" + NL " if (!isFenceValid(get_fence(floatp)))" + NL " return false;" + NL + NL " if (*floatp != val)" + NL " return false;" + NL + NL " return true;" + NL "}" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " __private float val;" + NL " val = 0.1f;" + NL " float * volatile ptr = &val;" + NL + NL " results[tid] = helperFunction(ptr, val);" + NL "}" + NL + ); + + CAdvancedTest test(KERNEL_FUNCTIONS); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_generic_variable_const(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + std::vector KERNEL_FUNCTIONS; + + KERNEL_FUNCTIONS.push_back(common::CONFORMANCE_VERIFY_FENCE + + NL + NL "bool helperFunction(const float *floatp, float val) {" + NL " if (!isFenceValid(get_fence(floatp)))" + NL " return false;" + NL + NL " if (*floatp != val)" + NL " return false;" + NL + NL " return true;" + NL "}" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " const __private float val = 0.1f;" + NL " const float * ptr = &val;" + NL + NL " results[tid] = helperFunction(ptr, val);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back(common::CONFORMANCE_VERIFY_FENCE + + NL + NL "bool helperFunction(const float *floatp, float val) {" + NL " if (!isFenceValid(get_fence(floatp)))" + NL " return false;" + NL + NL " if (*floatp != val)" + NL " return false;" + NL + NL " return true;" + NL "}" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " const static __global float val = 0.1f;" + NL " const float * ptr = &val;" + NL + NL " results[tid] = helperFunction(ptr, val);" + NL "}" + NL + ); + + CAdvancedTest test(KERNEL_FUNCTIONS); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_generic_variable_gentype(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + const std::string KERNEL_FUNCTION_TEMPLATE = common::CONFORMANCE_VERIFY_FENCE + + NL + NL "%s" + NL + NL "bool helperFunction(const %s *%sp, %s val) {" + NL " if (!isFenceValid(get_fence(%sp)))" + NL " return false;" + NL + NL " return %s(*%sp == val);" + NL "}" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " %s %s val = (%s)1;" + NL " %s * ptr = &val;" + NL + NL " results[tid] = helperFunction(ptr, val);" + NL "}" + NL; +/* Qualcomm fix: 12502 Gen Addr Space - Fix kernel for generic variable gentype (half) test + const std::string KERNEL_FUNCTION_TEMPLATE_HALF = common::CONFORMANCE_VERIFY_FENCE */ + const std::string vector_sizes[] = { "", "2", "3", "4", "8", "16" }; + const std::string gentype_base[] = { "float", "char", "uchar", "short", "ushort", "int", "uint", "long", "ulong" }; + const std::string gentype_others[] = { "bool", "size_t", "ptrdiff_t", "intptr_t", "uintptr_t" }; + + const std::string address_spaces[] = { "static __global", "__private" }; + + const std::string vector_cmp = "all"; + + std::vector KERNEL_FUNCTIONS; + + // Add base types plus theirs vector variants + for (size_t i = 0; i < sizeof(gentype_base) / sizeof(gentype_base[0]); i++) { + for (size_t j = 0; j < sizeof(vector_sizes) / sizeof(vector_sizes[0]); j++) { + for (size_t k = 0; k < sizeof(address_spaces) / sizeof(address_spaces[0]); k++) { + char temp_kernel[1024]; + const std::string fulltype = gentype_base[i] + vector_sizes[j]; + sprintf(temp_kernel, KERNEL_FUNCTION_TEMPLATE.c_str(), + "", + fulltype.c_str(), fulltype.c_str(), fulltype.c_str(), fulltype.c_str(), + (j > 0 ? vector_cmp.c_str() : ""), + fulltype.c_str(), address_spaces[k].c_str(), fulltype.c_str(), fulltype.c_str(), + fulltype.c_str()); + + KERNEL_FUNCTIONS.push_back(temp_kernel); + } + } + } + + const std::string cl_khr_fp64_pragma = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable"; + + // Add double floating types if they are supported + if (is_extension_available(deviceID, "cl_khr_fp64")) { + for (size_t j = 0; j < sizeof(vector_sizes) / sizeof(vector_sizes[0]); j++) { + for (size_t k = 0; k < sizeof(address_spaces) / sizeof(address_spaces[0]); k++) { + char temp_kernel[1024]; + const std::string fulltype = std::string("double") + vector_sizes[j]; + sprintf(temp_kernel, KERNEL_FUNCTION_TEMPLATE.c_str(), + cl_khr_fp64_pragma.c_str(), + fulltype.c_str(), fulltype.c_str(), fulltype.c_str(), fulltype.c_str(), + (j > 0 ? vector_cmp.c_str() : ""), + fulltype.c_str(), address_spaces[k].c_str(), fulltype.c_str(), fulltype.c_str(), + fulltype.c_str()); + + KERNEL_FUNCTIONS.push_back(temp_kernel); + } + } + } +/* Qualcomm fix: 12502 Gen Addr Space - Fix kernel for generic variable gentype (half) test */ + const std::string cl_khr_fp16_pragma = "#pragma OPENCL EXTENSION cl_khr_fp16 : enable"; + + // Add half floating types if they are supported + if (is_extension_available(deviceID, "cl_khr_fp16")) { + for (size_t j = 0; j < sizeof(vector_sizes) / sizeof(vector_sizes[0]); j++) { + for (size_t k = 0; k < sizeof(address_spaces) / sizeof(address_spaces[0]); k++) { + char temp_kernel[1024]; + const std::string fulltype = std::string("half") + vector_sizes[j]; + sprintf(temp_kernel, KERNEL_FUNCTION_TEMPLATE.c_str(), + cl_khr_fp16_pragma.c_str(), + fulltype.c_str(), fulltype.c_str(), fulltype.c_str(), fulltype.c_str(), + (j > 0 ? vector_cmp.c_str() : ""), + fulltype.c_str(), address_spaces[k].c_str(), fulltype.c_str(), fulltype.c_str(), + fulltype.c_str()); +/* Qualcomm fix: end */ + KERNEL_FUNCTIONS.push_back(temp_kernel); + } + } + } + + // Add other types that do not have vector variants + for (size_t i = 0; i < sizeof(gentype_others) / sizeof(gentype_others[0]); i++) { + for (size_t k = 0; k < sizeof(address_spaces) / sizeof(address_spaces[0]); k++) { + char temp_kernel[1024]; + const std::string fulltype = gentype_others[i]; + sprintf(temp_kernel, KERNEL_FUNCTION_TEMPLATE.c_str(), + "", + fulltype.c_str(), fulltype.c_str(), fulltype.c_str(), fulltype.c_str(), + "", + fulltype.c_str(), address_spaces[k].c_str(), fulltype.c_str(), fulltype.c_str(), + fulltype.c_str()); + + KERNEL_FUNCTIONS.push_back(temp_kernel); + } + } + + CAdvancedTest test(KERNEL_FUNCTIONS); + + return test.Execute(deviceID, context, queue, num_elements); +} + +void create_math_kernels(std::vector& KERNEL_FUNCTIONS) { + const std::string KERNEL_FUNCTION_TEMPLATE = + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " const %s param1 = %s;" + NL " %s param2_generic;" + NL " %s param2_reference;" + NL " %s * ptr = ¶m2_generic;" + NL " %s return_value_generic;" + NL " %s return_value_reference;" + NL + NL " return_value_generic = %s(param1, ptr);" + NL " return_value_reference = %s(param1, ¶m2_reference);" + NL + NL " results[tid] = (%s(*ptr == param2_reference) && %s(return_value_generic == return_value_reference));" + NL "}" + NL; + + typedef struct { + std::string bulitin_name; + std::string base_gentype; + std::string pointer_gentype; + std::string first_param_value; + std::string compare_fn; + } BuiltinDescriptor; + + BuiltinDescriptor builtins[] = { + { "fract", "float", "float", "133.55f", "" }, + { "frexp", "float2", "int2", "(float2)(24.12f, 99999.7f)", "all" }, + { "frexp", "float", "int", "1234.5f", "" }, + { "lgamma_r", "float2", "int2", "(float2)(1000.0f, 9999.5f)", "all" }, + { "lgamma_r", "float", "int", "1000.0f", "" }, + { "modf", "float", "float", "1234.56789f", "" }, + { "sincos", "float", "float", "3.141592f", "" } + }; + + for (size_t i = 0; i < sizeof(builtins) / sizeof(builtins[0]); i++) { + char temp_kernel[1024]; + sprintf(temp_kernel, KERNEL_FUNCTION_TEMPLATE.c_str(), builtins[i].base_gentype.c_str(), builtins[i].first_param_value.c_str(), + builtins[i].pointer_gentype.c_str(), builtins[i].pointer_gentype.c_str(), builtins[i].pointer_gentype.c_str(), builtins[i].base_gentype.c_str(), + builtins[i].base_gentype.c_str(), builtins[i].bulitin_name.c_str(), builtins[i].bulitin_name.c_str(), + builtins[i].compare_fn.c_str(), builtins[i].compare_fn.c_str()); + + KERNEL_FUNCTIONS.push_back(temp_kernel); + } + + // add special case for remquo (3 params) + KERNEL_FUNCTIONS.push_back( + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " const float param1 = 1234.56789f;" + NL " const float param2 = 123.456789f;" + NL " int param3_generic;" + NL " int param3_reference;" + NL " int * ptr = ¶m3_generic;" + NL " float return_value_generic;" + NL " float return_value_reference;" + NL + NL " return_value_generic = remquo(param1, param2, ptr);" + NL " return_value_reference = remquo(param1, param2, ¶m3_reference);" + NL + NL " results[tid] = (*ptr == param3_reference && return_value_generic == return_value_reference);" + NL "}" + NL + ); +} + +std::string get_default_data_for_type(const std::string& type) { + std::string result; + + if (type == "float") { + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + char temp[10]; + sprintf(temp, "%d.%df, ", i, j); + result += std::string(temp); + } + } + } + + else if (type == "double") { + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + char temp[10]; + sprintf(temp, "%d.%d, ", i, j); + result += std::string(temp); + } + } + } + + else { + for (int i = 0; i < 100; i++) { + char temp[10]; + sprintf(temp, "%d, ", i); + result += std::string(temp); + } + } + + return result; +} + +void create_vload_kernels(std::vector& KERNEL_FUNCTIONS, cl_device_id deviceID) { + const std::string KERNEL_FUNCTION_TEMPLATE_GLOBAL = + NL + NL "%s" + NL "__global %s data[] = { %s };" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " // Testing: %s" + NL " const %s * ptr = data;" + NL " %s%s result_generic = vload%s(2, ptr);" + NL " %s%s result_reference = vload%s(2, data);" + NL + NL " results[tid] = all(result_generic == result_reference);" + NL "}" + NL; + + const std::string KERNEL_FUNCTION_TEMPLATE_LOCAL = + NL + NL "%s" + NL "__constant %s to_copy_from[] = { %s };" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " __local %s data[100];" + NL " for (int i = 0; i < sizeof(to_copy_from) / sizeof(to_copy_from[0]); i++)" + NL " data[i] = to_copy_from[i];" + NL + NL " const %s * ptr = data;" + NL " %s%s result_generic = vload%s(2, ptr);" + NL " %s%s result_reference = vload%s(2, data);" + NL + NL " results[tid] = all(result_generic == result_reference);" + NL "}" + NL; + + const std::string KERNEL_FUNCTION_TEMPLATE_PRIVATE = + NL + NL "%s" + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " %s data[] = { %s };" + NL " // Testing: %s" + NL " const %s * ptr = data;" + NL " %s%s result_generic = vload%s(2, ptr);" + NL " %s%s result_reference = vload%s(2, data);" + NL + NL " results[tid] = all(result_generic == result_reference);" + NL "}" + NL; + + const std::string vector_sizes[] = { "2", "3", "4", "8", "16" }; + const std::string gentype_base[] = { "double", "float", "char", "uchar", "short", "ushort", "int", "uint", "long", "ulong" }; + const std::string kernel_variants[] = { KERNEL_FUNCTION_TEMPLATE_GLOBAL, KERNEL_FUNCTION_TEMPLATE_LOCAL, KERNEL_FUNCTION_TEMPLATE_PRIVATE }; + + const std::string cl_khr_fp64_pragma = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable"; + + for (size_t i = 0; i < sizeof(gentype_base) / sizeof(gentype_base[0]); i++) { + const char *pragma_str = ""; + + if (i == 0) { + if (!is_extension_available(deviceID, "cl_khr_fp64")) + continue; + else + pragma_str = cl_khr_fp64_pragma.c_str(); + } + + for (size_t j = 0; j < sizeof(vector_sizes) / sizeof(vector_sizes[0]); j++) { + for (size_t k = 0; k < sizeof(kernel_variants) / sizeof(kernel_variants[0]); k++) { + char temp_kernel[4098]; + sprintf(temp_kernel, kernel_variants[k].c_str(), + pragma_str, + gentype_base[i].c_str(), + get_default_data_for_type(gentype_base[i]).c_str(), + gentype_base[i].c_str(), + gentype_base[i].c_str(), + gentype_base[i].c_str(), vector_sizes[j].c_str(), vector_sizes[j].c_str(), + gentype_base[i].c_str(), vector_sizes[j].c_str(), vector_sizes[j].c_str() + ); + + KERNEL_FUNCTIONS.push_back(temp_kernel); + } + } + } +} + +void create_vstore_kernels(std::vector& KERNEL_FUNCTIONS, cl_device_id deviceID) { + const std::string KERNEL_FUNCTION_TEMPLATE_GLOBAL = + NL + NL "%s" + NL "__global %s data_generic[] = { %s };" + NL "__global %s data_reference[] = { %s };" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " %s%s input = (%s%s)(1);" + NL " %s * ptr = data_generic;" + NL + NL " vstore%s(input, 2, ptr);" + NL " vstore%s(input, 2, data_reference);" + NL + NL " bool result = true;" + NL " for (int i = 0; i < sizeof(data_generic) / sizeof(data_generic[0]); i++)" + NL " if (data_generic[i] != data_reference[i])" + NL " result = false;" + NL + NL " results[tid] = result;" + NL "}" + NL; + + const std::string KERNEL_FUNCTION_TEMPLATE_LOCAL = + NL + NL "%s" + NL "__constant %s to_copy_from[] = { %s };" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " __local %s data_generic[100];" + NL " for (int i = 0; i < sizeof(to_copy_from) / sizeof(to_copy_from[0]); i++)" + NL " data_generic[i] = to_copy_from[i];" + NL + NL " __local %s data_reference[100];" + NL " for (int i = 0; i < sizeof(to_copy_from) / sizeof(to_copy_from[0]); i++)" + NL " data_reference[i] = to_copy_from[i];" + NL + NL " %s%s input = (%s%s)(1);" + NL " %s * ptr = data_generic;" + NL + NL " vstore%s(input, 2, ptr);" + NL " vstore%s(input, 2, data_reference);" + NL + NL " work_group_barrier(CLK_LOCAL_MEM_FENCE);" + NL + NL " bool result = true;" + NL " for (int i = 0; i < sizeof(data_generic) / sizeof(data_generic[0]); i++)" + NL " if (data_generic[i] != data_reference[i])" + NL " result = false;" + NL + NL " results[tid] = result;" + NL "}" + NL; + + const std::string KERNEL_FUNCTION_TEMPLATE_PRIVATE = + NL + NL "%s" + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " __private %s data_generic[] = { %s };" + NL " __private %s data_reference[] = { %s };" + NL + NL " %s%s input = (%s%s)(1);" + NL " %s * ptr = data_generic;" + NL + NL " vstore%s(input, 2, ptr);" + NL " vstore%s(input, 2, data_reference);" + NL + NL " bool result = true;" + NL " for (int i = 0; i < sizeof(data_generic) / sizeof(data_generic[0]); i++)" + NL " if (data_generic[i] != data_reference[i])" + NL " result = false;" + NL + NL " results[tid] = result;" + NL "}" + NL; + + const std::string vector_sizes[] = { "2", "3", "4", "8", "16" }; + const std::string gentype_base[] = { "double", "float", "char", "uchar", "short", "ushort", "int", "uint", "long", "ulong" }; + const std::string kernel_variants[] = { KERNEL_FUNCTION_TEMPLATE_GLOBAL, KERNEL_FUNCTION_TEMPLATE_LOCAL, KERNEL_FUNCTION_TEMPLATE_PRIVATE }; + + const std::string cl_khr_fp64_pragma = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable"; + + for (size_t i = 0; i < sizeof(gentype_base) / sizeof(gentype_base[0]); i++) { + const char *pragma_str = ""; + if (i == 0) { + if (!is_extension_available(deviceID, "cl_khr_fp64")) + continue; + else + pragma_str = cl_khr_fp64_pragma.c_str(); + } + + + for (size_t j = 0; j < sizeof(vector_sizes) / sizeof(vector_sizes[0]); j++) { + for (size_t k = 0; k < sizeof(kernel_variants) / sizeof(kernel_variants[0]); k++) { + char temp_kernel[4098]; + + switch (k) { + case 0: // global template + case 2: // private template + sprintf(temp_kernel, kernel_variants[k].c_str(), + pragma_str, + gentype_base[i].c_str(), get_default_data_for_type(gentype_base[i]).c_str(), + gentype_base[i].c_str(), get_default_data_for_type(gentype_base[i]).c_str(), + gentype_base[i].c_str(), vector_sizes[j].c_str(), gentype_base[i].c_str(), vector_sizes[j].c_str(), + gentype_base[i].c_str(), + vector_sizes[j].c_str(), + vector_sizes[j].c_str() + ); + break; + + case 1: // local template + sprintf(temp_kernel, kernel_variants[k].c_str(), + pragma_str, + gentype_base[i].c_str(), get_default_data_for_type(gentype_base[i]).c_str(), + gentype_base[i].c_str(), + gentype_base[i].c_str(), + gentype_base[i].c_str(), vector_sizes[j].c_str(), gentype_base[i].c_str(), vector_sizes[j].c_str(), + gentype_base[i].c_str(), + vector_sizes[j].c_str(), + vector_sizes[j].c_str() + ); + break; + } + + KERNEL_FUNCTIONS.push_back(temp_kernel); + } + } + } +} + +int test_builtin_functions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + std::vector KERNEL_FUNCTIONS; + + create_math_kernels(KERNEL_FUNCTIONS); + create_vload_kernels(KERNEL_FUNCTIONS, deviceID); + create_vstore_kernels(KERNEL_FUNCTIONS, deviceID); + + CAdvancedTest test(KERNEL_FUNCTIONS); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_generic_advanced_casting(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + std::vector KERNEL_FUNCTIONS; + + KERNEL_FUNCTIONS.push_back( + NL + NL "__global char arr[16] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 };" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " const int * volatile ptr = (const int *)arr;" + NL + NL " results[tid] = (ptr[0] == 0x00000000) && (ptr[1] == 0x01010101) && (ptr[2] == 0x02020202) && (ptr[3] == 0x03030303);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back( + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " __local int i;" + NL " i = 0x11112222;" + NL " short *ptr = (short *)&i;" + NL " local int *lptr = (local int *)ptr;" + NL + NL " results[tid] = (lptr == &i) && (*lptr == i);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back( + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " int i = 0x11112222;" + NL + NL " void *ptr = &i;" + NL " int copy = *((int *)ptr);" + NL + NL " results[tid] = (copy == i);" + NL "}" + NL + ); + + CAdvancedTest test(KERNEL_FUNCTIONS); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_generic_ptr_to_host_mem(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + cl_int result = CL_SUCCESS; + + const std::string GLOBAL_KERNEL_FUNCTION = common::CONFORMANCE_VERIFY_FENCE + + NL + NL "bool helperFunction(uint *ptr, uint tid) {" + NL " if (!isFenceValid(get_fence(ptr)))" + NL " return false;" + NL + NL " if (*ptr != tid)" + NL " return false;" + NL + NL " return true;" + NL "}" + NL + NL "__kernel void testKernel(__global uint *results, __global uint *buf) {" + NL " uint tid = get_global_id(0);" + NL + NL " results[tid] = helperFunction(&buf[tid], tid);" + NL "}" + NL; + + const std::string LOCAL_KERNEL_FUNCTION = common::CONFORMANCE_VERIFY_FENCE + + NL + NL "bool helperFunction(uint *ptr, uint tid) {" + NL " if (!isFenceValid(get_fence(ptr)))" + NL " return false;" + NL + NL " if (*ptr != tid)" + NL " return false;" + NL + NL " return true;" + NL "}" + NL + NL "__kernel void testKernel(__global uint *results, __local uint *buf) {" + NL " uint tid = get_global_id(0);" + NL " if (get_local_id(0) == 0) {" + NL " for (uint i = 0; i < get_local_size(0); ++i) {" + NL " uint idx = get_local_size(0) * get_group_id(0) + i;" + NL " buf[idx] = idx;" + NL " }" + NL " }" + NL + NL " work_group_barrier(CLK_LOCAL_MEM_FENCE);" + NL " results[tid] = helperFunction(&buf[tid], tid);" + NL "}" + NL; + + CAdvancedTest test_global_ptr(GLOBAL_KERNEL_FUNCTION, ARG_TYPE_HOST_PTR); + result |= test_global_ptr.Execute(deviceID, context, queue, num_elements); + + CAdvancedTest test_local_ptr(LOCAL_KERNEL_FUNCTION, ARG_TYPE_HOST_LOCAL); + result |= test_local_ptr.Execute(deviceID, context, queue, num_elements / 64); + + /* Test SVM capabilities and select matching tests */ + cl_device_svm_capabilities caps; + + cl_int error = clGetDeviceInfo(deviceID, CL_DEVICE_SVM_CAPABILITIES, sizeof(caps), &caps, NULL); + test_error(error, "clGetDeviceInfo(CL_DEVICE_SVM_CAPABILITIES) failed"); + + if (caps & CL_DEVICE_SVM_COARSE_GRAIN_BUFFER) { + CAdvancedTest test_global_svm_ptr(GLOBAL_KERNEL_FUNCTION, ARG_TYPE_COARSE_GRAINED_SVM); + result |= test_global_svm_ptr.Execute(deviceID, context, queue, num_elements); + } + + if (caps & CL_DEVICE_SVM_FINE_GRAIN_BUFFER) { + CAdvancedTest test_global_svm_ptr(GLOBAL_KERNEL_FUNCTION, ARG_TYPE_FINE_GRAINED_BUFFER_SVM); + result |= test_global_svm_ptr.Execute(deviceID, context, queue, num_elements); + } + + if (caps & CL_DEVICE_SVM_FINE_GRAIN_SYSTEM) { + CAdvancedTest test_global_svm_ptr(GLOBAL_KERNEL_FUNCTION, ARG_TYPE_FINE_GRAINED_SYSTEM_SVM); + result |= test_global_svm_ptr.Execute(deviceID, context, queue, num_elements); + } + + if (caps & CL_DEVICE_SVM_ATOMICS) { + CAdvancedTest test_global_svm_ptr(GLOBAL_KERNEL_FUNCTION, ARG_TYPE_ATOMICS_SVM); + result |= test_global_svm_ptr.Execute(deviceID, context, queue, num_elements); + } + + return result; +} diff --git a/test_conformance/generic_address_space/base.h b/test_conformance/generic_address_space/base.h new file mode 100644 index 00000000..5ea71055 --- /dev/null +++ b/test_conformance/generic_address_space/base.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/testHarness.h" + +#include + +class CTest { +public: + virtual int Execute(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) = 0; +}; + +#define NL "\n" + +namespace common { + static const std::string CONFORMANCE_VERIFY_FENCE = + NL + NL "// current spec says get_fence can return any valid fence" + NL "bool isFenceValid(cl_mem_fence_flags fence) {" + NL " if ((fence == 0) || (fence == CLK_GLOBAL_MEM_FENCE) || (fence == CLK_LOCAL_MEM_FENCE) " + NL " || (fence == (CLK_GLOBAL_MEM_FENCE | CLK_LOCAL_MEM_FENCE)))" + NL " return true;" + NL " else" + NL " return false;" + NL "}" + NL; +} diff --git a/test_conformance/generic_address_space/basic_tests.cpp b/test_conformance/generic_address_space/basic_tests.cpp new file mode 100644 index 00000000..ff42edd9 --- /dev/null +++ b/test_conformance/generic_address_space/basic_tests.cpp @@ -0,0 +1,877 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" +#include "base.h" + +#include +#include +#include + +class CBasicTest : CTest { +public: + CBasicTest(const std::vector& kernel) : CTest(), _kernels(kernel) { + + } + + CBasicTest(const std::string& kernel) : CTest(), _kernels(1, kernel) { + + } + + int ExecuteSubcase(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, const std::string& src) { + cl_int error; + + clProgramWrapper program; + clKernelWrapper kernel; + + const char *srcPtr = src.c_str(); + + if (create_single_kernel_helper_with_build_options(context, &program, &kernel, 1, &srcPtr, "testKernel", "-cl-std=CL2.0")) { + log_error("create_single_kernel_helper failed"); + return -1; + } + + size_t bufferSize = num_elements * sizeof(cl_uint); + clMemWrapper buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY, bufferSize, NULL, &error); + test_error(error, "clCreateBuffer failed"); + + error = clSetKernelArg(kernel, 0, sizeof(buffer), &buffer); + test_error(error, "clSetKernelArg failed"); + + size_t globalWorkGroupSize = num_elements; + size_t localWorkGroupSize = 0; + error = get_max_common_work_group_size(context, kernel, globalWorkGroupSize, &localWorkGroupSize); + test_error(error, "Unable to get common work group size"); + + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &globalWorkGroupSize, &localWorkGroupSize, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + // verify results + std::vector results(num_elements); + + error = clEnqueueReadBuffer(queue, buffer, CL_TRUE, 0, bufferSize, &results[0], 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + size_t passCount = std::count(results.begin(), results.end(), 1); + if (passCount != results.size()) { + std::vector::iterator iter = std::find(results.begin(), results.end(), 0); + log_error("Verification on device failed at index %ld\n", std::distance(results.begin(), iter)); + log_error("%ld out of %ld failed\n", (results.size()-passCount), results.size()); + return -1; + } + + return CL_SUCCESS; + } + + int Execute(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + cl_int result = CL_SUCCESS; + + for (std::vector::const_iterator it = _kernels.begin(); it != _kernels.end(); ++it) { + log_info("Executing subcase #%ld out of %ld\n", (it - _kernels.begin() + 1), _kernels.size()); + + result |= ExecuteSubcase(deviceID, context, queue, num_elements, *it); + } + + return result; + } + +private: + const std::vector _kernels; +}; + +int test_function_params_get_fence(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + const std::string KERNEL_FUNCTION = common::CONFORMANCE_VERIFY_FENCE + + NL + NL "__global int gint = 1;" + NL "__global uchar guchar = 3;" + NL + NL "bool helperFunction(int *intp, float *floatp, uchar *ucharp, ushort *ushortp, long *longp) {" + NL " if (!isFenceValid(get_fence(intp)))" + NL " return false;" + NL " if (!isFenceValid(get_fence(floatp)))" + NL " return false;" + NL " if (!isFenceValid(get_fence(ucharp)))" + NL " return false;" + NL " if (!isFenceValid(get_fence(ushortp)))" + NL " return false;" + NL " if (!isFenceValid(get_fence(longp)))" + NL " return false;" + NL + NL " if (*intp != 1 || *floatp != 2.0f || *ucharp != 3 || *ushortp != 4 || *longp != 5)" + NL " return false;" + NL + NL " return true;" + NL "}" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " __local float lfloat;" + NL " lfloat = 2.0f;" + NL " __local ushort lushort;" + NL " lushort = 4;" + NL " long plong = 5;" + NL + NL " __global int *gintp = &gint;" + NL " __local float *lfloatp = &lfloat;" + NL " __global uchar *gucharp = &guchar;" + NL " __local ushort *lushortp = &lushort;" + NL " __private long *plongp = &plong;" + NL + NL " results[tid] = helperFunction(gintp, lfloatp, gucharp, lushortp, plongp);" + NL "}" + NL; + + CBasicTest test(KERNEL_FUNCTION); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_function_params_to_address_space(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + const std::string KERNEL_FUNCTION = + NL + NL "__global int gint = 1;" + NL "__global uchar guchar = 3;" + NL + NL "bool helperFunction(int *gintp, float *lfloatp, uchar *gucharp, ushort *lushortp, long *plongp) {" + NL " if (to_global(gintp) == NULL)" + NL " return false;" + NL " if (to_local(lfloatp) == NULL)" + NL " return false;" + NL " if (to_global(gucharp) == NULL)" + NL " return false;" + NL " if (to_local(lushortp) == NULL)" + NL " return false;" + NL " if (to_private(plongp) == NULL)" + NL " return false;" + NL + NL " if (*gintp != 1 || *lfloatp != 2.0f || *gucharp != 3 || *lushortp != 4 || *plongp != 5)" + NL " return false;" + NL + NL " return true;" + NL "}" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " __local float lfloat;" + NL " lfloat = 2.0f;" + NL " __local ushort lushort;" + NL " lushort = 4;" + NL " long plong = 5;" + NL + NL " __global int *gintp = &gint;" + NL " __local float *lfloatp = &lfloat;" + NL " __global uchar *gucharp = &guchar;" + NL " __local ushort *lushortp = &lushort;" + NL " __private long *plongp = &plong;" + NL + NL " results[tid] = helperFunction(gintp, lfloatp, gucharp, lushortp, plongp);" + NL "}" + NL; + + CBasicTest test(KERNEL_FUNCTION); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_variable_get_fence(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + const std::string KERNEL_FUNCTION = common::CONFORMANCE_VERIFY_FENCE + + NL + NL "__global int gint = 1;" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " __local ushort lushort;" + NL " lushort = 2;" + NL " float pfloat = 3.0f;" + NL + NL " // tested pointers" + NL " __global int *gintp = &gint;" + NL " __local ushort *lushortp = &lushort;" + NL " __private float *pfloatp = &pfloat;" + NL + NL " int failures = 0;" + NL " if (!isFenceValid(get_fence(gintp)))" + NL " failures++;" + NL " if (!isFenceValid(get_fence(lushortp)))" + NL " failures++;" + NL " if (!isFenceValid(get_fence(pfloatp)))" + NL " failures++;" + NL " results[tid] = (failures == 0);" + NL "}" + NL; + + CBasicTest test(KERNEL_FUNCTION); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_variable_to_address_space(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + const std::string KERNEL_FUNCTION = + NL + NL "__global int gint = 1;" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " __local ushort lushort;" + NL " lushort = 2;" + NL " float pfloat = 3.0f;" + NL + NL " // tested pointers" + NL " __global int * gintp = &gint;" + NL " __local ushort *lushortp = &lushort;" + NL " __private float *pfloatp = &pfloat;" + NL + NL " int failures = 0;" + NL " if (to_global(gintp) == NULL)" + NL " failures++;" + NL " if (to_local(lushortp) == NULL)" + NL " failures++;" + NL " if (to_private(pfloatp) == NULL)" + NL " failures++;" + NL " results[tid] = (failures == 0);" + NL "}" + NL; + + CBasicTest test(KERNEL_FUNCTION); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_casting(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + std::vector KERNEL_FUNCTIONS; + + // pointers to global, local or private are implicitly convertible to generic + KERNEL_FUNCTIONS.push_back(common::CONFORMANCE_VERIFY_FENCE + + NL + NL "__global int gint = 1;" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " __local int lint;" + NL " lint = 2;" + NL " int pint = 3;" + NL + NL " // count mismatches with expected fence types" + NL " int failures = 0;" + NL + NL " // tested pointer" + NL " // generic can be reassigned to different named address spaces" + NL " int * intp;" + NL + NL " intp = &gint;" + NL " failures += !(isFenceValid(get_fence(intp)));" + NL " failures += !(to_global(intp));" + NL " failures += (*intp != 1);" + NL + NL " intp = &lint;" + NL " failures += !(isFenceValid(get_fence(intp)));" + NL " failures += !(to_local(intp));" + NL " failures += (*intp != 2);" + NL + NL " intp = &pint;" + NL " failures += !(isFenceValid(get_fence(intp)));" + NL " failures += !(to_private(intp));" + NL " failures += (*intp != 3);" + NL + NL " results[tid] = (failures == 0);" + NL "}" + NL + ); + + // converting from a generic pointer to a named address space is legal only with explicit casting + KERNEL_FUNCTIONS.push_back(common::CONFORMANCE_VERIFY_FENCE + + NL + NL "__global int gint = 1;" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " __local int lint;" + NL " lint = 2;" + NL " int pint = 3;" + NL + NL " // count mismatches with expected fence types" + NL " int failures = 0;" + NL + NL " // tested pointer" + NL " // generic can be reassigned to different named address spaces" + NL " int * intp;" + NL + NL " intp = &gint;" + NL " global int * gintp = (global int *)intp;" + NL " failures += !(isFenceValid(get_fence(gintp)));" + NL " failures += !(to_global(gintp));" + NL " failures += (*gintp != 1);" + NL + NL " intp = &lint;" + NL " local int * lintp = (local int *)intp;" + NL " failures += !(isFenceValid(get_fence(lintp)));" + NL " failures += !(to_local(lintp));" + NL " failures += (*lintp != 2);" + NL + NL " intp = &pint;" + NL " private int * pintp = (private int *)intp;" + NL " failures += !(isFenceValid(get_fence(pintp)));" + NL " failures += !(to_private(pintp));" + NL " failures += (*pintp != 3);" + NL + NL " results[tid] = (failures == 0);" + NL "}" + NL + ); + + CBasicTest test(KERNEL_FUNCTIONS); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_conditional_casting(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + const std::string KERNEL_FUNCTION = common::CONFORMANCE_VERIFY_FENCE + + NL + NL "__global int gint = 1;" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " int *ptr;" + NL " __local int lint;" + NL " lint = 2;" + NL + NL " if (tid % 2)" + NL " ptr = &gint;" + NL " else" + NL " ptr = &lint;" + NL + NL " barrier(CLK_GLOBAL_MEM_FENCE);" + NL + NL " if (tid % 2)" + NL " results[tid] = (isFenceValid(get_fence(ptr)) && to_global(ptr) && *ptr == 1);" + NL " else" + NL " results[tid] = (isFenceValid(get_fence(ptr)) && to_local(ptr) && *ptr == 2);" + NL "}" + NL; + + CBasicTest test(KERNEL_FUNCTION); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_chain_casting(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + const std::string KERNEL_FUNCTION = common::CONFORMANCE_VERIFY_FENCE + + NL + NL "__global int gint = 1;" + NL + NL "int f4(int val, int *ptr) { return (isFenceValid(get_fence(ptr)) && val == *ptr) ? 0 : 1; }" + NL "int f3(int val, int *ptr) { return f4(val, ptr); }" + NL "int f2(int *ptr, int val) { return f3(val, ptr); }" + NL "int f1(int *ptr, int val) { return f2(ptr, val); }" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " int *ptr;" + NL " __local int lint;" + NL " lint = 2;" + NL " __private int pint = 3;" + NL + NL " int failures = 0;" + NL " failures += f1(&gint, gint);" + NL " failures += f1(&lint, lint);" + NL " failures += f1(&pint, pint);" + NL + NL " results[tid] = (failures == 0);" + NL "}" + NL; + CBasicTest test(KERNEL_FUNCTION); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_ternary_operator_casting(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + const std::string KERNEL_FUNCTION = common::CONFORMANCE_VERIFY_FENCE + + NL + NL "__global int gint = 1;" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " int *ptr;" + NL " __local int lint;" + NL " lint = 2;" + NL + NL " ptr = (tid % 2) ? &gint : (int *)&lint; // assuming there is an implicit conversion from named address space to generic" + NL + NL " barrier(CLK_GLOBAL_MEM_FENCE);" + NL + NL " if (tid % 2)" + NL " results[tid] = (isFenceValid(get_fence(ptr)) && to_global(ptr) && *ptr == gint);" + NL " else" + NL " results[tid] = (isFenceValid(get_fence(ptr)) && to_local(ptr) && *ptr == lint);" + NL "}" + NL; + + CBasicTest test(KERNEL_FUNCTION); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_language_struct(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + std::vector KERNEL_FUNCTIONS; + + // implicit private struct + KERNEL_FUNCTIONS.push_back(common::CONFORMANCE_VERIFY_FENCE + + NL + NL "__global int gint = 1;" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL " int failures = 0;" + NL + NL " __local int lint;" + NL " lint = 2;" + NL " __private int pint = 3;" + NL + NL " struct {" + NL " __global int *gintp;" + NL " __local int *lintp;" + NL " __private int *pintp;" + NL " } structWithPointers;" + NL + NL " structWithPointers.gintp = &gint;" + NL " structWithPointers.lintp = &lint;" + NL " structWithPointers.pintp = &pint;" + NL + NL " failures += !(isFenceValid(get_fence(structWithPointers.gintp)));" + NL " failures += !(isFenceValid(get_fence(structWithPointers.lintp)));" + NL " failures += !(isFenceValid(get_fence(structWithPointers.pintp)));" + NL + NL " failures += !(to_global(structWithPointers.gintp));" + NL " failures += !(to_local(structWithPointers.lintp));" + NL " failures += !(to_private(structWithPointers.pintp));" + NL + NL " results[tid] = (failures == 0);" + NL "}" + NL + ); + + // explicit __private struct + KERNEL_FUNCTIONS.push_back(common::CONFORMANCE_VERIFY_FENCE + + NL + NL "__global int gint = 1;" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL " int failures = 0;" + NL + NL " __local int lint;" + NL " lint = 2;" + NL " __private int pint = 3;" + NL + NL " typedef struct {" + NL " __global int * gintp;" + NL " __local int * lintp;" + NL " __private int * pintp;" + NL " } S;" + NL + NL " __private S structWithPointers;" + NL " structWithPointers.gintp = &gint;" + NL " structWithPointers.lintp = &lint;" + NL " structWithPointers.pintp = &pint;" + NL + NL " failures += !(isFenceValid(get_fence(structWithPointers.gintp)));" + NL " failures += !(isFenceValid(get_fence(structWithPointers.lintp)));" + NL " failures += !(isFenceValid(get_fence(structWithPointers.pintp)));" + NL + NL " failures += !(to_global(structWithPointers.gintp));" + NL " failures += !(to_local(structWithPointers.lintp));" + NL " failures += !(to_private(structWithPointers.pintp));" + NL + NL " results[tid] = (failures == 0);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back(common::CONFORMANCE_VERIFY_FENCE + + NL + NL "__global int gint = 1;" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL " int failures = 0;" + NL + NL " __local int lint;" + NL " lint = 2;" + NL " __private int pint = 3;" + NL + NL " typedef struct {" + NL " __global int * gintp;" + NL " __local int * lintp;" + NL " __private int * pintp;" + NL " } S;" + NL + NL " __local S structWithPointers;" + NL " structWithPointers.gintp = &gint;" + NL " structWithPointers.lintp = &lint;" + NL " structWithPointers.pintp = &pint;" + NL + NL " failures += !(isFenceValid(get_fence(structWithPointers.gintp)));" + NL " failures += !(isFenceValid(get_fence(structWithPointers.lintp)));" + NL " failures += !(isFenceValid(get_fence(structWithPointers.pintp)));" + NL + NL " failures += !(to_global(structWithPointers.gintp));" + NL " failures += !(to_local(structWithPointers.lintp));" + NL " failures += !(to_private(structWithPointers.pintp));" + NL + NL " results[tid] = (failures == 0);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back(common::CONFORMANCE_VERIFY_FENCE + + NL + NL "typedef struct {" + NL " __global int *gintp;" + NL " __local int *lintp;" + NL " __private int *pintp;" + NL "} S;" + NL + NL "__global S structWithPointers;" + NL "__global int gint = 1;" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL " int failures = 0;" + NL + NL " __local int lint;" + NL " lint = 2;" + NL " __private int pint = 3;" + NL + NL " structWithPointers.gintp = &gint;" + NL " structWithPointers.lintp = &lint;" + NL " structWithPointers.pintp = &pint;" + NL + NL " failures += !(isFenceValid(get_fence(structWithPointers.gintp)));" + NL " failures += !(isFenceValid(get_fence(structWithPointers.lintp)));" + NL " failures += !(isFenceValid(get_fence(structWithPointers.pintp)));" + NL + NL " failures += !(to_global(structWithPointers.gintp));" + NL " failures += !(to_local(structWithPointers.lintp));" + NL " failures += !(to_private(structWithPointers.pintp));" + NL + NL " results[tid] = (failures == 0);" + NL "}" + NL + ); + + CBasicTest test(KERNEL_FUNCTIONS); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_language_union(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + std::vector KERNEL_FUNCTIONS; + + KERNEL_FUNCTIONS.push_back(common::CONFORMANCE_VERIFY_FENCE + + NL + NL "__global int g = 1;" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL " int failures = 0;" + NL + NL " __local int l;" + NL " l = 2;" + NL " int p = 3;" + NL + NL " union {" + NL " __global int *gintp;" + NL " __local int *lintp;" + NL " __private int *pintp;" + NL " } u;" + NL + NL " u.gintp = &g;" + NL " failures += !(isFenceValid(get_fence(u.gintp)));" + NL " failures += !to_global(u.gintp);" + NL " failures += (*(u.gintp) != 1);" + NL + NL " u.lintp = &l;" + NL " failures += !(isFenceValid(get_fence(u.lintp)));" + NL " failures += !to_local(u.lintp);" + NL " failures += (*(u.lintp) != 2);" + NL + NL " u.pintp = &p;" + NL " failures += !(isFenceValid(get_fence(u.pintp)));" + NL " failures += !to_private(u.pintp);" + NL " failures += (*(u.pintp) != 3);" + NL + NL " results[tid] = (failures == 0);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back(common::CONFORMANCE_VERIFY_FENCE + + NL + NL "__global int g = 1;" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL " int failures = 0;" + NL + NL " __local int l;" + NL " l = 2;" + NL " int p = 3;" + NL + NL " typedef union {" + NL " __global int * gintp;" + NL " __local int * lintp;" + NL " __private int * pintp;" + NL " } U;" + NL + NL " __local U u;" + NL + NL " u.gintp = &g;" + NL " failures += !(isFenceValid(get_fence(u.gintp)));" + NL " failures += !to_global(u.gintp);" + NL " failures += (*(u.gintp) != 1);" + NL + NL " u.lintp = &l;" + NL " failures += !(isFenceValid(get_fence(u.lintp)));" + NL " failures += !to_local(u.lintp);" + NL " failures += (*(u.lintp) != 2);" + NL + NL " u.pintp = &p;" + NL " failures += !(isFenceValid(get_fence(u.pintp)));" + NL " failures += !to_private(u.pintp);" + NL " failures += (*(u.pintp) != 3);" + NL + NL " results[tid] = (failures == 0);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back(common::CONFORMANCE_VERIFY_FENCE + + NL + NL "typedef union {" + NL " __global int * gintp;" + NL " __local int * lintp;" + NL " __private int * pintp;" + NL "} U;" + NL + NL "__global U u;" + NL "__global int g = 1;" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " // for global unions only one thread should modify union's content" + NL " if (tid != 0) {" + NL " results[tid] = 1;" + NL " return;" + NL " }" + NL + NL " int failures = 0;" + NL + NL " __local int l;" + NL " l = 2;" + NL " int p = 3;" + NL + NL " u.gintp = &g;" + NL " failures += !(isFenceValid(get_fence(u.gintp)));" + NL " failures += !to_global(u.gintp);" + NL " failures += (*(u.gintp) != 1);" + NL + NL " u.lintp = &l;" + NL " failures += !(isFenceValid(get_fence(u.lintp)));" + NL " failures += !to_local(u.lintp);" + NL " failures += (*(u.lintp) != 2);" + NL + NL " u.pintp = &p;" + NL " failures += !(isFenceValid(get_fence(u.pintp)));" + NL " failures += !to_private(u.pintp);" + NL " failures += (*(u.pintp) != 3);" + NL + NL " results[tid] = (failures == 0);" + NL "}" + NL + ); + + CBasicTest test(KERNEL_FUNCTIONS); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_multiple_calls_same_function(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + const std::string KERNEL_FUNCTION = + NL + NL "int shift2(const int *ptr, int arg) {" + NL " return *ptr << arg;" + NL "}" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL " int failures = 0;" + NL + NL " __local int val;" + NL " val = get_group_id(0);" + NL + NL " for (int i = 0; i < 5; i++) {" + NL " if (shift2(&val, i) != (val << i))" + NL " failures++;" + NL " }" + NL + NL " for (int i = 10; i > 5; i--) {" + NL " if (shift2(&val, i) != (val << i))" + NL " failures++;" + NL " }" + NL + NL " results[tid] = (failures == 0);" + NL "}" + NL; + + CBasicTest test(KERNEL_FUNCTION); + + return test.Execute(deviceID, context, queue, num_elements); +} + +int test_compare_pointers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + std::vector KERNEL_FUNCTIONS; + + KERNEL_FUNCTIONS.push_back( + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " int *ptr = NULL;" + NL + NL " results[tid] = (ptr == NULL);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back( + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " int *ptr = NULL;" + NL " __global int *gptr = NULL;" + NL + NL " results[tid] = (ptr == gptr);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back( + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " int *ptr = NULL;" + NL " __local int *lptr = NULL;" + NL + NL " results[tid] = (ptr == lptr);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back( + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " int *ptr = NULL;" + NL " __private int *pptr = NULL;" + NL + NL " results[tid] = (ptr == pptr);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back( + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " int *ptr = NULL;" + NL " __local int *lptr = NULL;" + NL " __global int *gptr = NULL;" + NL + NL " ptr = lptr;" + NL + NL " results[tid] = (gptr == ptr) && (lptr == ptr);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back( + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " int some_value = 7;" + NL " int *ptr = NULL;" + NL " __private int *pptr = &some_value;" + NL + NL " results[tid] = (ptr != pptr);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back( + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " __local int some_value;" + NL " some_value = 7;" + NL " int *ptr = NULL;" + NL " __local int *lptr = &some_value;" + NL + NL " results[tid] = (ptr != lptr);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back( + NL "__global int some_value = 7;" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " int *ptr = NULL;" + NL " __global int *gptr = &some_value;" + NL + NL " results[tid] = (ptr != gptr);" + NL "}" + NL + ); + + KERNEL_FUNCTIONS.push_back( + NL "__global int arr[5] = { 0, 1, 2, 3, 4 };" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " int *ptr = &arr[1];" + NL " __global int *gptr = &arr[3];" + NL + NL " results[tid] = (gptr >= ptr);" + NL "}" + NL + ); + + CBasicTest test(KERNEL_FUNCTIONS); + + return test.Execute(deviceID, context, queue, num_elements); +} diff --git a/test_conformance/generic_address_space/main.cpp b/test_conformance/generic_address_space/main.cpp new file mode 100644 index 00000000..e59fd49e --- /dev/null +++ b/test_conformance/generic_address_space/main.cpp @@ -0,0 +1,106 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/testHarness.h" + +#include + +// basic tests +extern int test_function_params_get_fence(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_function_params_to_address_space(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_variable_get_fence(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_variable_to_address_space(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_casting(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_conditional_casting(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_chain_casting(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_ternary_operator_casting(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_language_struct(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_language_union(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_multiple_calls_same_function(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_compare_pointers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +// advanced tests +extern int test_library_function(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_generic_variable_volatile(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_generic_variable_const(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_generic_variable_gentype(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_builtin_functions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_generic_advanced_casting(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_generic_ptr_to_host_mem(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_max_number_of_params(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +basefn basefn_list[] = { + // basic tests + test_function_params_get_fence, + test_function_params_to_address_space, + test_variable_get_fence, + test_variable_to_address_space, + test_casting, + test_conditional_casting, + test_chain_casting, + test_ternary_operator_casting, + test_language_struct, + test_language_union, + test_multiple_calls_same_function, + test_compare_pointers, + // advanced tests + test_library_function, + test_generic_variable_volatile, + test_generic_variable_const, + test_generic_variable_gentype, + test_builtin_functions, + test_generic_advanced_casting, + test_generic_ptr_to_host_mem, + test_max_number_of_params, +}; + +const char *basefn_names[] = { + //basic tests + "function_get_fence", + "function_to_address_space", + "variable_get_fence", + "variable_to_address_space", + "casting", + "conditional_casting", + "chain_casting", + "ternary_operator_casting", + "language_struct", + "language_union", + "multiple_calls_same_function", + "compare_pointers", + // advanced tests + "library_function", + "generic_variable_volatile", + "generic_variable_const", + "generic_variable_gentype", + "builtin_functions", + "generic_advanced_casting", + "generic_ptr_to_host_mem", + "max_number_of_params", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + +/* + Generic Address Space + Tests for unnamed generic address space. This feature allows developers to create single generic functions + that are able to operate on pointers from various address spaces instead of writing separate instances for every combination. +*/ + +int main(int argc, const char *argv[]) +{ + return runTestHarness(argc, argv, num_fns, basefn_list, basefn_names, false, false, NULL); +} diff --git a/test_conformance/generic_address_space/stress_tests.cpp b/test_conformance/generic_address_space/stress_tests.cpp new file mode 100644 index 00000000..58ceb514 --- /dev/null +++ b/test_conformance/generic_address_space/stress_tests.cpp @@ -0,0 +1,173 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/mt19937.h" +#include "base.h" + +#include +#include +#include +#include + +class CStressTest : public CTest { +public: + CStressTest(const std::vector& kernel) : CTest(), _kernels(kernel) { + + } + + CStressTest(const std::string& kernel) : CTest(), _kernels(1, kernel) { + + } + + int ExecuteSubcase(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, const std::string& src) { + cl_int error; + + clProgramWrapper program; + clKernelWrapper kernel; + + const char *srcPtr = src.c_str(); + + if (create_single_kernel_helper_with_build_options(context, &program, &kernel, 1, &srcPtr, "testKernel", "-cl-std=CL2.0")) { + log_error("create_single_kernel_helper failed"); + return -1; + } + + size_t bufferSize = num_elements * sizeof(cl_uint); + clMemWrapper buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY, bufferSize, NULL, &error); + test_error(error, "clCreateBuffer failed"); + + error = clSetKernelArg(kernel, 0, sizeof(buffer), &buffer); + test_error(error, "clSetKernelArg failed"); + + size_t globalWorkGroupSize = num_elements; + size_t localWorkGroupSize = 0; + error = get_max_common_work_group_size(context, kernel, globalWorkGroupSize, &localWorkGroupSize); + test_error(error, "Unable to get common work group size"); + + error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &globalWorkGroupSize, &localWorkGroupSize, 0, NULL, NULL); + test_error(error, "clEnqueueNDRangeKernel failed"); + + // verify results + std::vector results(num_elements); + + error = clEnqueueReadBuffer(queue, buffer, CL_TRUE, 0, bufferSize, &results[0], 0, NULL, NULL); + test_error(error, "clEnqueueReadBuffer failed"); + + size_t passCount = std::count(results.begin(), results.end(), 1); + if (passCount != results.size()) { + std::vector::iterator iter = std::find(results.begin(), results.end(), 0); + log_error("Verification on device failed at index %ld\n", std::distance(results.begin(), iter)); + log_error("%ld out of %ld failed\n", (results.size()-passCount), results.size()); + return -1; + } + + return CL_SUCCESS; + } + + int Execute(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + cl_int result = CL_SUCCESS; + + for (std::vector::const_iterator it = _kernels.begin(); it != _kernels.end(); ++it) { + log_info("Executing subcase #%ld out of %ld\n", (it - _kernels.begin() + 1), _kernels.size()); + + result |= ExecuteSubcase(deviceID, context, queue, num_elements, *it); + } + + return result; + } + +private: + const std::vector _kernels; +}; + +int test_max_number_of_params(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) { + cl_int error; + + size_t deviceMaxParameterSize; + error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof(deviceMaxParameterSize), &deviceMaxParameterSize, NULL); + test_error(error, "clGetDeviceInfo failed"); + + size_t deviceAddressBits; + error = clGetDeviceInfo(deviceID, CL_DEVICE_ADDRESS_BITS, sizeof(deviceAddressBits), &deviceAddressBits, NULL); + test_error(error, "clGetDeviceInfo failed"); + + size_t maxParams = deviceMaxParameterSize / (deviceAddressBits / 8); + + const std::string KERNEL_FUNCTION_TEMPLATE[] = { + common::CONFORMANCE_VERIFY_FENCE + + NL + NL "bool helperFunction(int *ptr0 ", + // the rest of arguments goes here + ") {" + NL " // check first pointer only" + NL " if (!isFenceValid(get_fence(ptr0)))" + NL " return false;" + NL + NL " return true;" + NL "}" + NL + NL "__kernel void testKernel(__global uint *results) {" + NL " uint tid = get_global_id(0);" + NL + NL " __global int * gptr;" + NL " __local int * lptr;" + NL " __private int * pptr;" + NL + NL " size_t failures = 0;" + NL + NL, + // the function body goes here + NL + NL " results[tid] = (failures == 0);" + NL "}" + NL + }; + + std::ostringstream type_params; + std::ostringstream function_calls; + + for (size_t i = 0; i < maxParams; i++) { + type_params << ", int *ptr" << i+1; + } + + // use pseudo random generator to shuffle params + MTdata d = init_genrand(gRandomSeed); + if (!d) + return -1; + + std::string pointers[] = { "gptr", "lptr", "pptr" }; + + size_t totalCalls = maxParams / 2; + for (size_t i = 0; i < totalCalls; i++) { + function_calls << "\tif (!helperFunction(gptr"; + + for (size_t j = 0; j < maxParams; j++) { + function_calls << ", " << pointers[genrand_int32(d)%3]; + } + + function_calls << ")) failures++;" << NL; + } + + free_mtdata(d); + d = NULL; + + const std::string KERNEL_FUNCTION = KERNEL_FUNCTION_TEMPLATE[0] + type_params.str() + KERNEL_FUNCTION_TEMPLATE[1] + function_calls.str() + KERNEL_FUNCTION_TEMPLATE[2]; + + CStressTest test(KERNEL_FUNCTION); + + return test.Execute(deviceID, context, queue, num_elements); +} diff --git a/test_conformance/geometrics/CMakeLists.txt b/test_conformance/geometrics/CMakeLists.txt new file mode 100644 index 00000000..f88f0364 --- /dev/null +++ b/test_conformance/geometrics/CMakeLists.txt @@ -0,0 +1,24 @@ +set(MODULE_NAME GEOMETRICS) + +set(${MODULE_NAME}_SOURCES + main.c + test_geometrics_double.cpp + test_geometrics.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + +# VS2005 optimization WAR for geom_length) +if(MSVC) +set(CMAKE_C_FLAGS_RELEASE "/Od /Ob0") +set(CMAKE_CXX_FLAGS_RELEASE "/Od /Ob0") +endif(MSVC) + +include(../CMakeCommon.txt) + diff --git a/test_conformance/geometrics/Jamfile b/test_conformance/geometrics/Jamfile new file mode 100644 index 00000000..3a9f200b --- /dev/null +++ b/test_conformance/geometrics/Jamfile @@ -0,0 +1,17 @@ +project + : requirements + gcc:-xc++ + msvc:"/TP" + ; + +exe test_geometrics + : main.c + test_geometrics.cpp + test_geometrics_double.cpp + ; + +install dist + : test_geometrics + : debug:$(DIST)/debug/tests/test_conformance/geometrics + release:$(DIST)/release/tests/test_conformance/geometrics + ; diff --git a/test_conformance/geometrics/Makefile b/test_conformance/geometrics/Makefile new file mode 100644 index 00000000..e35c93e0 --- /dev/null +++ b/test_conformance/geometrics/Makefile @@ -0,0 +1,44 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + test_geometrics.c \ + test_geometrics_double.c \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/conversions.c \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/kernelHelpers.c + +DEFINES = + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = $(SOURCES) +HEADERS = +TARGET = test_geometrics +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/geometrics/main.c b/test_conformance/geometrics/main.c new file mode 100644 index 00000000..0a99f8ee --- /dev/null +++ b/test_conformance/geometrics/main.c @@ -0,0 +1,61 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include "procs.h" +#include "../../test_common/harness/testHarness.h" +#if !defined(_WIN32) +#include +#endif + +basefn basefn_list[] = { + test_geom_cross, + test_geom_dot, + test_geom_distance, + test_geom_fast_distance, + test_geom_length, + test_geom_fast_length, + test_geom_normalize, + test_geom_fast_normalize +}; + + +const char *basefn_names[] = { + "geom_cross", + "geom_dot", + "geom_distance", + "geom_fast_distance", + "geom_length", + "geom_fast_length", + "geom_normalize", + "geom_fast_normalize", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + +const unsigned int g_vecSizeof[] = {0,1,2,4,4,0,0,0,8, + 0,0,0,0,0,0,0,16}; + +int main(int argc, const char *argv[]) +{ + return runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false, false, 0 ); +} + + diff --git a/test_conformance/geometrics/procs.h b/test_conformance/geometrics/procs.h new file mode 100644 index 00000000..25af3e38 --- /dev/null +++ b/test_conformance/geometrics/procs.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/threadTesting.h" +#include "../../test_common/harness/typeWrappers.h" + +extern const unsigned int g_vecSizeof[]; + +extern int create_program_and_kernel(const char *source, const char *kernel_name, cl_program *program_ret, cl_kernel *kernel_ret); + +extern int test_geom_cross(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_geom_dot(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_geom_distance(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_geom_fast_distance(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_geom_length(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_geom_fast_length(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_geom_normalize(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_geom_fast_normalize(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_geom_cross_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, MTdata d); +extern int test_geom_dot_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, MTdata d); +extern int test_geom_distance_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, MTdata d); +extern int test_geom_length_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, MTdata d); +extern int test_geom_normalize_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, MTdata d); diff --git a/test_conformance/geometrics/testBase.h b/test_conformance/geometrics/testBase.h new file mode 100644 index 00000000..5073b21f --- /dev/null +++ b/test_conformance/geometrics/testBase.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testBase_h +#define _testBase_h + +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +#endif // _testBase_h + + + diff --git a/test_conformance/geometrics/test_geometrics.cpp b/test_conformance/geometrics/test_geometrics.cpp new file mode 100644 index 00000000..ac16b2a4 --- /dev/null +++ b/test_conformance/geometrics/test_geometrics.cpp @@ -0,0 +1,1109 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include "testBase.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/errorHelpers.h" +#include + +const char *crossKernelSource = +"__kernel void sample_test(__global float4 *sourceA, __global float4 *sourceB, __global float4 *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = cross( sourceA[tid], sourceB[tid] );\n" +"\n" +"}\n" ; + +const char *crossKernelSourceV3 = +"__kernel void sample_test(__global float *sourceA, __global float *sourceB, __global float *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" vstore3( cross( vload3( tid, sourceA), vload3( tid, sourceB) ), tid, destValues );\n" +"\n" +"}\n"; + +const char *twoToFloatKernelPattern = +"__kernel void sample_test(__global float%s *sourceA, __global float%s *sourceB, __global float *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( sourceA[tid], sourceB[tid] );\n" +"\n" +"}\n"; + +const char *twoToFloatKernelPatternV3 = +"__kernel void sample_test(__global float%s *sourceA, __global float%s *sourceB, __global float *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( vload3( tid, (__global float*) sourceA), vload3( tid, (__global float*) sourceB) );\n" +"\n" +"}\n"; + +const char *oneToFloatKernelPattern = +"__kernel void sample_test(__global float%s *sourceA, __global float *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( sourceA[tid] );\n" +"\n" +"}\n"; + +const char *oneToFloatKernelPatternV3 = +"__kernel void sample_test(__global float%s *sourceA, __global float *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( vload3( tid, (__global float*) sourceA) );\n" +"\n" +"}\n"; + +const char *oneToOneKernelPattern = +"__kernel void sample_test(__global float%s *sourceA, __global float%s *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( sourceA[tid] );\n" +"\n" +"}\n"; + +const char *oneToOneKernelPatternV3 = +"__kernel void sample_test(__global float%s *sourceA, __global float%s *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" vstore3( %s( vload3( tid, (__global float*) sourceA) ), tid, (__global float*) destValues );\n" +"\n" +"}\n"; + +#define TEST_SIZE (1 << 20) + +double verifyFastDistance( float *srcA, float *srcB, size_t vecSize ); +double verifyFastLength( float *srcA, size_t vecSize ); + + + +void vector2string( char *string, float *vector, size_t elements ) +{ + *string++ = '{'; + *string++ = ' '; + string += sprintf( string, "%a", vector[0] ); + size_t i; + for( i = 1; i < elements; i++ ) + string += sprintf( string, ", %a", vector[i] ); + *string++ = ' '; + *string++ = '}'; + *string = '\0'; +} + +void fillWithTrickyNumbers( float *aVectors, float *bVectors, size_t vecSize ) +{ + static const cl_float trickyValues[] = { -FLT_EPSILON, FLT_EPSILON, + MAKE_HEX_FLOAT(0x1.0p63f, 0x1L, 63), MAKE_HEX_FLOAT(0x1.8p63f, 0x18L, 59), MAKE_HEX_FLOAT(0x1.0p64f, 0x1L, 64), MAKE_HEX_FLOAT(-0x1.0p63f, -0x1L, 63), MAKE_HEX_FLOAT(-0x1.8p-63f, -0x18L, -67), MAKE_HEX_FLOAT(-0x1.0p64f, -0x1L, 64), + MAKE_HEX_FLOAT(0x1.0p-63f, 0x1L, -63), MAKE_HEX_FLOAT(0x1.8p-63f, 0x18L, -67), MAKE_HEX_FLOAT(0x1.0p-64f, 0x1L, -64), MAKE_HEX_FLOAT(-0x1.0p-63f, -0x1L, -63), MAKE_HEX_FLOAT(-0x1.8p-63f, -0x18L, -67), MAKE_HEX_FLOAT(-0x1.0p-64f, -0x1L, -64), + FLT_MAX / 2.f, -FLT_MAX / 2.f, INFINITY, -INFINITY, 0.f, -0.f }; + static const size_t trickyCount = sizeof( trickyValues ) / sizeof( trickyValues[0] ); + static const size_t stride[4] = {1, trickyCount, trickyCount*trickyCount, trickyCount*trickyCount*trickyCount }; + size_t i, j, k; + + for( j = 0; j < vecSize; j++ ) + for( k = 0; k < vecSize; k++ ) + for( i = 0; i < trickyCount; i++ ) + aVectors[ j + stride[j] * (i + k*trickyCount)*vecSize] = trickyValues[i]; + + if( bVectors ) + { + size_t copySize = vecSize * vecSize * trickyCount; + memset( bVectors, 0, sizeof(float) * copySize ); + memset( aVectors + copySize, 0, sizeof(float) * copySize ); + memcpy( bVectors + copySize, aVectors, sizeof(float) * copySize ); + } +} + + +void cross_product( const float *vecA, const float *vecB, float *outVector, float *errorTolerances, float ulpTolerance ) +{ + outVector[ 0 ] = ( vecA[ 1 ] * vecB[ 2 ] ) - ( vecA[ 2 ] * vecB[ 1 ] ); + outVector[ 1 ] = ( vecA[ 2 ] * vecB[ 0 ] ) - ( vecA[ 0 ] * vecB[ 2 ] ); + outVector[ 2 ] = ( vecA[ 0 ] * vecB[ 1 ] ) - ( vecA[ 1 ] * vecB[ 0 ] ); + outVector[ 3 ] = 0.0f; + + errorTolerances[ 0 ] = fmaxf( fabsf( vecA[ 1 ] ), fmaxf( fabsf( vecB[ 2 ] ), fmaxf( fabsf( vecA[ 2 ] ), fabsf( vecB[ 1 ] ) ) ) ); + errorTolerances[ 1 ] = fmaxf( fabsf( vecA[ 2 ] ), fmaxf( fabsf( vecB[ 0 ] ), fmaxf( fabsf( vecA[ 0 ] ), fabsf( vecB[ 2 ] ) ) ) ); + errorTolerances[ 2 ] = fmaxf( fabsf( vecA[ 0 ] ), fmaxf( fabsf( vecB[ 1 ] ), fmaxf( fabsf( vecA[ 1 ] ), fabsf( vecB[ 0 ] ) ) ) ); + + errorTolerances[ 0 ] = errorTolerances[ 0 ] * errorTolerances[ 0 ] * ( ulpTolerance * FLT_EPSILON ); // This gives us max squared times ulp tolerance, i.e. the worst-case expected variance we could expect from this result + errorTolerances[ 1 ] = errorTolerances[ 1 ] * errorTolerances[ 1 ] * ( ulpTolerance * FLT_EPSILON ); + errorTolerances[ 2 ] = errorTolerances[ 2 ] * errorTolerances[ 2 ] * ( ulpTolerance * FLT_EPSILON ); +} + + + + +int test_geom_cross(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + int vecsize; + RandomSeed seed(gRandomSeed); + + /* Get the default rounding mode */ + cl_device_fp_config defaultRoundingMode = get_default_rounding_mode(deviceID); + if( 0 == defaultRoundingMode ) + return -1; + + + for(vecsize = 3; vecsize <= 4; ++vecsize) + { + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[3]; + BufferOwningPtr A(malloc(sizeof(cl_float) * TEST_SIZE * vecsize)); + BufferOwningPtr B(malloc(sizeof(cl_float) * TEST_SIZE * vecsize)); + BufferOwningPtr C(malloc(sizeof(cl_float) * TEST_SIZE * vecsize)); + cl_float testVector[4]; + int error, i; + cl_float *inDataA = A; + cl_float *inDataB = B; + cl_float *outData = C; + size_t threads[1], localThreads[1]; + + /* Create kernels */ + if( create_single_kernel_helper( context, &program, &kernel, 1, vecsize == 3 ? &crossKernelSourceV3 : &crossKernelSource, "sample_test" ) ) + return -1; + + /* Generate some streams. Note: deliberately do some random data in w to verify that it gets ignored */ + for( i = 0; i < TEST_SIZE * vecsize; i++ ) + { + inDataA[ i ] = get_random_float( -512.f, 512.f, seed ); + inDataB[ i ] = get_random_float( -512.f, 512.f, seed ); + } + fillWithTrickyNumbers( inDataA, inDataB, vecsize ); + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_float) * vecsize * TEST_SIZE, inDataA, NULL); + if( streams[0] == NULL ) + { + log_error("ERROR: Creating input array A failed!\n"); + return -1; + } + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_float) * vecsize * TEST_SIZE, inDataB, NULL); + if( streams[1] == NULL ) + { + log_error("ERROR: Creating input array B failed!\n"); + return -1; + } + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * vecsize * TEST_SIZE, NULL, NULL); + if( streams[2] == NULL ) + { + log_error("ERROR: Creating output array failed!\n"); + return -1; + } + + /* Assign streams and execute */ + for( i = 0; i < 3; i++ ) + { + error = clSetKernelArg(kernel, i, sizeof( streams[i] ), &streams[i]); + test_error( error, "Unable to set indexed kernel arguments" ); + } + + /* Run the kernel */ + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[2], true, 0, sizeof( cl_float ) * TEST_SIZE * vecsize, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + /* And verify! */ + for( i = 0; i < TEST_SIZE; i++ ) + { + float errorTolerances[ 4 ]; + // On an embedded device w/ round-to-zero, 3 ulps is the worst-case tolerance for cross product + cross_product( inDataA + i * vecsize, inDataB + i * vecsize, testVector, errorTolerances, 3.f ); + + // RTZ devices accrue approximately double the amount of error per operation. Allow for that. + if( defaultRoundingMode == CL_FP_ROUND_TO_ZERO ) + { + errorTolerances[0] *= 2.0f; + errorTolerances[1] *= 2.0f; + errorTolerances[2] *= 2.0f; + errorTolerances[3] *= 2.0f; + } + + float errs[] = { fabsf( testVector[ 0 ] - outData[ i * vecsize + 0 ] ), + fabsf( testVector[ 1 ] - outData[ i * vecsize + 1 ] ), + fabsf( testVector[ 2 ] - outData[ i * vecsize + 2 ] ) }; + + if( errs[ 0 ] > errorTolerances[ 0 ] || errs[ 1 ] > errorTolerances[ 1 ] || errs[ 2 ] > errorTolerances[ 2 ] ) + { + log_error( "ERROR: Data sample %d does not validate! Expected (%a,%a,%a,%a), got (%a,%a,%a,%a)\n", + i, testVector[0], testVector[1], testVector[2], testVector[3], + outData[i*vecsize], outData[i*vecsize+1], outData[i*vecsize+2], outData[i*vecsize+3] ); + log_error( " Input: (%a %a %a) and (%a %a %a)\n", + inDataA[ i * vecsize + 0 ], inDataA[ i * vecsize + 1 ], inDataA[ i * vecsize + 2 ], + inDataB[ i * vecsize + 0 ], inDataB[ i * vecsize + 1 ], inDataB[ i * vecsize + 2 ] ); + log_error( " Errors: (%a out of %a), (%a out of %a), (%a out of %a)\n", + errs[ 0 ], errorTolerances[ 0 ], errs[ 1 ], errorTolerances[ 1 ], errs[ 2 ], errorTolerances[ 2 ] ); + log_error(" ulp %f\n", Ulp_Error( outData[ i * vecsize + 1 ], testVector[ 1 ] ) ); + return -1; + } + } + } // for(vecsize=... + + if(!is_extension_available(deviceID, "cl_khr_fp64")) { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + return 0; + } else { + log_info("Testing doubles...\n"); + return test_geom_cross_double( deviceID, context, queue, num_elements, seed); + } +} + +float getMaxValue( float vecA[], float vecB[], size_t vecSize ) +{ + float a = fmaxf( fabsf( vecA[ 0 ] ), fabsf( vecB[ 0 ] ) ); + for( size_t i = 1; i < vecSize; i++ ) + a = fmaxf( fabsf( vecA[ i ] ), fmaxf( fabsf( vecB[ i ] ), a ) ); + return a; +} + +typedef double (*twoToFloatVerifyFn)( float *srcA, float *srcB, size_t vecSize ); + +int test_twoToFloat_kernel(cl_command_queue queue, cl_context context, const char *fnName, + size_t vecSize, twoToFloatVerifyFn verifyFn, float ulpLimit, MTdata d ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[3]; + int error; + size_t i, threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + char sizeNames[][4] = { "", "2", "3", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + int hasInfNan = 1; + cl_device_id device = NULL; + + error = clGetCommandQueueInfo( queue, CL_QUEUE_DEVICE, sizeof( device ), &device, NULL ); + test_error( error, "Unable to get command queue device" ); + + /* Check for embedded devices doing nutty stuff */ + error = clGetDeviceInfo( device, CL_DEVICE_PROFILE, sizeof( kernelSource ), kernelSource, NULL ); + test_error( error, "Unable to get device profile" ); + if( 0 == strcmp( kernelSource, "EMBEDDED_PROFILE" ) ) + { + cl_device_fp_config config = 0; + error = clGetDeviceInfo( device, CL_DEVICE_SINGLE_FP_CONFIG, sizeof( config ), &config, NULL ); + test_error( error, "Unable to get CL_DEVICE_SINGLE_FP_CONFIG" ); + + if( CL_FP_ROUND_TO_ZERO == (config & (CL_FP_ROUND_TO_NEAREST|CL_FP_ROUND_TO_ZERO))) + ulpLimit *= 2.0f; // rtz operations average twice the accrued error of rte operations + + if( 0 == (config & CL_FP_INF_NAN) ) + hasInfNan = 0; + } + + BufferOwningPtr A(malloc(sizeof(cl_float) * TEST_SIZE * 4)); + BufferOwningPtr B(malloc(sizeof(cl_float) * TEST_SIZE * 4)); + BufferOwningPtr C(malloc(sizeof(cl_float) * TEST_SIZE)); + + cl_float *inDataA = A; + cl_float *inDataB = B; + cl_float *outData = C; + + /* Create the source */ + sprintf( kernelSource, vecSize == 3 ? twoToFloatKernelPatternV3 : twoToFloatKernelPattern, sizeNames[vecSize-1], sizeNames[vecSize-1], fnName ); + + /* Create kernels */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + { + return -1; + } + /* Generate some streams */ + for( i = 0; i < TEST_SIZE * vecSize; i++ ) + { + inDataA[ i ] = get_random_float( -512.f, 512.f, d ); + inDataB[ i ] = get_random_float( -512.f, 512.f, d ); + } + fillWithTrickyNumbers( inDataA, inDataB, vecSize ); + + /* Clamp values to be in range for fast_ functions */ + if( verifyFn == verifyFastDistance ) + { + for( i = 0; i < TEST_SIZE * vecSize; i++ ) + { + if( fabsf( inDataA[i] ) > MAKE_HEX_FLOAT(0x1.0p62f, 0x1L, 62) || fabsf( inDataA[i] ) < MAKE_HEX_FLOAT(0x1.0p-62f, 0x1L, -62) ) + inDataA[ i ] = get_random_float( -512.f, 512.f, d ); + if( fabsf( inDataB[i] ) > MAKE_HEX_FLOAT(0x1.0p62f, 0x1L, 62) || fabsf( inDataB[i] ) < MAKE_HEX_FLOAT(0x1.0p-62f, 0x1L, -62) ) + inDataB[ i ] = get_random_float( -512.f, 512.f, d ); + } + } + + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_float) * vecSize * TEST_SIZE, inDataA, NULL); + if( streams[0] == NULL ) + { + log_error("ERROR: Creating input array A failed!\n"); + return -1; + } + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_float) * vecSize * TEST_SIZE, inDataB, NULL); + if( streams[1] == NULL ) + { + log_error("ERROR: Creating input array B failed!\n"); + return -1; + } + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * TEST_SIZE, NULL, NULL); + if( streams[2] == NULL ) + { + log_error("ERROR: Creating output array failed!\n"); + return -1; + } + + /* Assign streams and execute */ + for( i = 0; i < 3; i++ ) + { + error = clSetKernelArg(kernel, (int)i, sizeof( streams[i] ), &streams[i]); + test_error( error, "Unable to set indexed kernel arguments" ); + } + + /* Run the kernel */ + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[2], true, 0, sizeof( cl_float ) * TEST_SIZE, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + + /* And verify! */ + int skipCount = 0; + for( i = 0; i < TEST_SIZE; i++ ) + { + cl_float *src1 = inDataA + i * vecSize; + cl_float *src2 = inDataB + i * vecSize; + double expected = verifyFn( src1, src2, vecSize ); + if( (float) expected != outData[ i ] ) + { + if( isnan(expected) && isnan( outData[i] ) ) + continue; + + if( ! hasInfNan ) + { + size_t ii; + for( ii = 0; ii < vecSize; ii++ ) + { + if( ! isfinite( src1[ii] ) || ! isfinite( src2[ii] ) ) + { + skipCount++; + continue; + } + } + if( ! isfinite( (cl_float) expected ) ) + { + skipCount++; + continue; + } + } + + if( ulpLimit < 0 ) + { + // Limit below zero means we need to test via a computed error (like cross product does) + float maxValue = + getMaxValue( inDataA + i * vecSize, inDataB + i * vecSize,vecSize ); + // In this case (dot is the only one that gets here), the ulp is 2*vecSize - 1 (n + n-1 max # of errors) + float errorTolerance = maxValue * maxValue * ( 2.f * (float)vecSize - 1.f ) * FLT_EPSILON; + + // Limit below zero means test via epsilon instead + double error = + fabs( (double)expected - (double)outData[ i ] ); + if( error > errorTolerance ) + { + + log_error( "ERROR: Data sample %d at size %d does not validate! Expected (%a), got (%a), sources (%a and %a) error of %g against tolerance %g\n", + (int)i, (int)vecSize, expected, + outData[ i ], + inDataA[i*vecSize], + inDataB[i*vecSize], + (float)error, + (float)errorTolerance ); + + char vecA[1000], vecB[1000]; + vector2string( vecA, inDataA +i * vecSize, vecSize ); + vector2string( vecB, inDataB + i * vecSize, vecSize ); + log_error( "\tvector A: %s, vector B: %s\n", vecA, vecB ); + return -1; + } + } + else + { + float error = Ulp_Error( outData[ i ], expected ); + if( fabsf(error) > ulpLimit ) + { + log_error( "ERROR: Data sample %d at size %d does not validate! Expected (%a), got (%a), sources (%a and %a) ulp of %f\n", + (int)i, (int)vecSize, expected, outData[ i ], inDataA[i*vecSize], inDataB[i*vecSize], error ); + + char vecA[1000], vecB[1000]; + vector2string( vecA, inDataA + i * vecSize, vecSize ); + vector2string( vecB, inDataB + i * vecSize, vecSize ); + log_error( "\tvector A: %s, vector B: %s\n", vecA, vecB ); + return -1; + } + } + } + } + + if( skipCount ) + log_info( "Skipped %d tests out of %d because they contained Infs or NaNs\n\tEMBEDDED_PROFILE Device does not support CL_FP_INF_NAN\n", skipCount, TEST_SIZE ); + + return 0; +} + +double verifyDot( float *srcA, float *srcB, size_t vecSize ) +{ + double total = 0.f; + + for( unsigned int i = 0; i < vecSize; i++ ) + total += (double)srcA[ i ] * (double)srcB[ i ]; + + return total; +} + +int test_geom_dot(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + size_t sizes[] = { 1, 2, 3, 4, 0 }; + unsigned int size; + int retVal = 0; + RandomSeed seed(gRandomSeed); + + for( size = 0; sizes[ size ] != 0 ; size++ ) + { + if( test_twoToFloat_kernel( queue, context, "dot", sizes[size], verifyDot, -1.0f /*magic value*/, seed ) != 0 ) + { + log_error( " dot vector size %d FAILED\n", (int)sizes[ size ] ); + retVal = -1; + } + } + + if (retVal) + return retVal; + + if(!is_extension_available(deviceID, "cl_khr_fp64")) + { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + return 0; + } + + log_info("Testing doubles...\n"); + return test_geom_dot_double( deviceID, context, queue, num_elements, seed); +} + +double verifyFastDistance( float *srcA, float *srcB, size_t vecSize ) +{ + double total = 0, value; + unsigned int i; + + // We calculate the distance as a double, to try and make up for the fact that + // the GPU has better precision distance since it's a single op + for( i = 0; i < vecSize; i++ ) + { + value = (double)srcA[i] - (double)srcB[i]; + total += value * value; + } + + return sqrt( total ); +} + +int test_geom_fast_distance(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + size_t sizes[] = { 1, 2, 3, 4, 0 }; + unsigned int size; + int retVal = 0; + RandomSeed seed(gRandomSeed); + + for( size = 0; sizes[ size ] != 0 ; size++ ) + { + float maxUlps = 8192.0f + // error in sqrt + ( 1.5f * (float) sizes[size] + // cumulative error for multiplications (a-b+0.5ulp)**2 = (a-b)**2 + a*0.5ulp + b*0.5 ulp + 0.5 ulp for multiplication + 0.5f * (float) (sizes[size]-1)); // cumulative error for additions + + if( test_twoToFloat_kernel( queue, context, "fast_distance", + sizes[ size ], verifyFastDistance, + maxUlps, seed ) != 0 ) + { + log_error( " fast_distance vector size %d FAILED\n", + (int)sizes[ size ] ); + retVal = -1; + } + else + { + log_info( " fast_distance vector size %d passed\n", + (int)sizes[ size ] ); + } + } + return retVal; +} + + +double verifyDistance( float *srcA, float *srcB, size_t vecSize ) +{ + double total = 0, value; + unsigned int i; + + // We calculate the distance as a double, to try and make up for the fact that + // the GPU has better precision distance since it's a single op + for( i = 0; i < vecSize; i++ ) + { + value = (double)srcA[i] - (double)srcB[i]; + total += value * value; + } + + return sqrt( total ); +} + +int test_geom_distance(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + size_t sizes[] = { 1, 2, 3, 4, 0 }; + unsigned int size; + int retVal = 0; + RandomSeed seed(gRandomSeed ); + + for( size = 0; sizes[ size ] != 0 ; size++ ) + { + float maxUlps = 3.0f + // error in sqrt + ( 1.5f * (float) sizes[size] + // cumulative error for multiplications (a-b+0.5ulp)**2 = (a-b)**2 + a*0.5ulp + b*0.5 ulp + 0.5 ulp for multiplication + 0.5f * (float) (sizes[size]-1)); // cumulative error for additions + + if( test_twoToFloat_kernel( queue, context, "distance", sizes[ size ], verifyDistance, maxUlps, seed ) != 0 ) + { + log_error( " distance vector size %d FAILED\n", + (int)sizes[ size ] ); + retVal = -1; + } + else + { + log_info( " distance vector size %d passed\n", (int)sizes[ size ] ); + } + } + if (retVal) + return retVal; + + if(!is_extension_available(deviceID, "cl_khr_fp64")) + { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + return 0; + } else { + log_info("Testing doubles...\n"); + return test_geom_distance_double( deviceID, context, queue, num_elements, seed); + } +} + +typedef double (*oneToFloatVerifyFn)( float *srcA, size_t vecSize ); + +int test_oneToFloat_kernel(cl_command_queue queue, cl_context context, const char *fnName, + size_t vecSize, oneToFloatVerifyFn verifyFn, float ulpLimit, MTdata d ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + BufferOwningPtr A(malloc(sizeof(cl_float) * TEST_SIZE * 4)); + BufferOwningPtr B(malloc(sizeof(cl_float) * TEST_SIZE)); + int error; + size_t i, threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + char sizeNames[][4] = { "", "2", "3", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + cl_float *inDataA = A; + cl_float *outData = B; + + /* Create the source */ + sprintf( kernelSource, vecSize == 3? oneToFloatKernelPatternV3 : oneToFloatKernelPattern, sizeNames[vecSize-1], fnName ); + + /* Create kernels */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + { + return -1; + } + + /* Generate some streams */ + for( i = 0; i < TEST_SIZE * vecSize; i++ ) + { + inDataA[ i ] = get_random_float( -512.f, 512.f, d ); + } + fillWithTrickyNumbers( inDataA, NULL, vecSize ); + + /* Clamp values to be in range for fast_ functions */ + if( verifyFn == verifyFastLength ) + { + for( i = 0; i < TEST_SIZE * vecSize; i++ ) + { + if( fabsf( inDataA[i] ) > MAKE_HEX_FLOAT(0x1.0p62f, 0x1L, 62) || fabsf( inDataA[i] ) < MAKE_HEX_FLOAT(0x1.0p-62f, 0x1L, -62) ) + inDataA[ i ] = get_random_float( -512.f, 512.f, d ); + } + } + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), + sizeof(cl_float) * vecSize * TEST_SIZE, inDataA, NULL); + if( streams[0] == NULL ) + { + log_error("ERROR: Creating input array A failed!\n"); + return -1; + } + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), + sizeof(cl_float) * TEST_SIZE, NULL, NULL); + if( streams[1] == NULL ) + { + log_error("ERROR: Creating output array failed!\n"); + return -1; + } + + /* Assign streams and execute */ + error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[ 1 ] ), &streams[1] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + /* Run the kernel */ + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], + &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, + localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[1], true, 0, + sizeof( cl_float ) * TEST_SIZE, outData, + 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + /* And verify! */ + for( i = 0; i < TEST_SIZE; i++ ) + { + double expected = verifyFn( inDataA + i * vecSize, vecSize ); + if( (float) expected != outData[ i ] ) + { + float ulps = Ulp_Error( outData[i], expected ); + if( fabsf( ulps ) <= ulpLimit ) + continue; + + // We have to special case NAN + if( isnan( outData[ i ] ) && isnan( expected ) ) + continue; + + if(! (fabsf(ulps) < ulpLimit) ) + { + log_error( "ERROR: Data sample %d at size %d does not validate! Expected (%a), got (%a), source (%a), ulp %f\n", + (int)i, (int)vecSize, expected, outData[ i ], inDataA[i*vecSize], ulps ); + char vecA[1000]; + vector2string( vecA, inDataA + i *vecSize, vecSize ); + log_error( "\tvector: %s", vecA ); + return -1; + } + } + } + + return 0; +} + +double verifyLength( float *srcA, size_t vecSize ) +{ + double total = 0; + unsigned int i; + + // We calculate the distance as a double, to try and make up for the fact that + // the GPU has better precision distance since it's a single op + for( i = 0; i < vecSize; i++ ) + { + total += (double)srcA[i] * (double)srcA[i]; + } + + return sqrt( total ); +} + +int test_geom_length(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + size_t sizes[] = { 1, 2, 3, 4, 0 }; + unsigned int size; + int retVal = 0; + RandomSeed seed( gRandomSeed ); + + for( size = 0; sizes[ size ] != 0 ; size++ ) + { + float maxUlps = 3.0f + // error in sqrt + 0.5f * // effect on e of taking sqrt( x + e ) + ( 0.5f * (float) sizes[size] + // cumulative error for multiplications + 0.5f * (float) (sizes[size]-1)); // cumulative error for additions + + if( test_oneToFloat_kernel( queue, context, "length", sizes[ size ], verifyLength, maxUlps, seed ) != 0 ) + { + log_error( " length vector size %d FAILED\n", (int)sizes[ size ] ); + retVal = -1; + } + else + { + log_info( " length vector vector size %d passed\n", (int)sizes[ size ] ); + } + } + if (retVal) + return retVal; + + if(!is_extension_available(deviceID, "cl_khr_fp64")) + { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + return 0; + } + else + { + log_info("Testing doubles...\n"); + return test_geom_length_double( deviceID, context, queue, num_elements, seed); + } +} + + +double verifyFastLength( float *srcA, size_t vecSize ) +{ + double total = 0; + unsigned int i; + + // We calculate the distance as a double, to try and make up for the fact that + // the GPU has better precision distance since it's a single op + for( i = 0; i < vecSize; i++ ) + { + total += (double)srcA[i] * (double)srcA[i]; + } + + return sqrt( total ); +} + +int test_geom_fast_length(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + size_t sizes[] = { 1, 2, 3, 4, 0 }; + unsigned int size; + int retVal = 0; + RandomSeed seed(gRandomSeed); + + for( size = 0; sizes[ size ] != 0 ; size++ ) + { + float maxUlps = 8192.0f + // error in half_sqrt + ( 0.5f * (float) sizes[size] + // cumulative error for multiplications + 0.5f * (float) (sizes[size]-1)); // cumulative error for additions + + if( test_oneToFloat_kernel( queue, context, "fast_length", sizes[ size ], verifyFastLength, maxUlps, seed ) != 0 ) + { + log_error( " fast_length vector size %d FAILED\n", (int)sizes[ size ] ); + retVal = -1; + } + else + { + log_info( " fast_length vector size %d passed\n", (int)sizes[ size ] ); + } + } + return retVal; +} + + +typedef void (*oneToOneVerifyFn)( float *srcA, float *dstA, size_t vecSize ); + + +int test_oneToOne_kernel(cl_command_queue queue, cl_context context, const char *fnName, + size_t vecSize, oneToOneVerifyFn verifyFn, float ulpLimit, int softball, MTdata d ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + BufferOwningPtr A(malloc(sizeof(cl_float) * TEST_SIZE + * vecSize)); + BufferOwningPtr B(malloc(sizeof(cl_float) * TEST_SIZE + * vecSize)); + int error; + size_t i, j, threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + char sizeNames[][4] = { "", "2", "3", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + cl_float *inDataA = A; + cl_float *outData = B; + float ulp_error = 0; + + /* Create the source */ + sprintf( kernelSource, vecSize == 3 ? oneToOneKernelPatternV3: oneToOneKernelPattern, sizeNames[vecSize-1], sizeNames[vecSize-1], fnName ); + + /* Create kernels */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + return -1; + + /* Initialize data. First element always 0. */ + memset( inDataA, 0, sizeof(cl_float) * vecSize ); + if( 0 == strcmp( fnName, "fast_normalize" )) + { // keep problematic cases out of the fast function + for( i = vecSize; i < TEST_SIZE * vecSize; i++ ) + { + cl_float z = get_random_float( -MAKE_HEX_FLOAT( 0x1.0p60f, 1, 60), MAKE_HEX_FLOAT( 0x1.0p60f, 1, 60), d); + if( fabsf(z) < MAKE_HEX_FLOAT( 0x1.0p-60f, 1, -60) ) + z = copysignf( 0.0f, z ); + inDataA[i] = z; + } + } + else + { + for( i = vecSize; i < TEST_SIZE * vecSize; i++ ) + inDataA[i] = any_float(d); + } + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_float) * vecSize* TEST_SIZE, inDataA, NULL); + if( streams[0] == NULL ) + { + log_error("ERROR: Creating input array A failed!\n"); + return -1; + } + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * vecSize * TEST_SIZE, NULL, NULL); + if( streams[1] == NULL ) + { + log_error("ERROR: Creating output array failed!\n"); + return -1; + } + + /* Assign streams and execute */ + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + /* Run the kernel */ + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[1], true, 0, sizeof( cl_float ) * TEST_SIZE * vecSize, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + /* And verify! */ + for( i = 0; i < TEST_SIZE; i++ ) + { + float expected[4]; + int fail = 0; + verifyFn( inDataA + i * vecSize, expected, vecSize ); + for( j = 0; j < vecSize; j++ ) + { + // We have to special case NAN + if( isnan( outData[ i * vecSize + j ] ) + && isnan( expected[ j ] ) ) + continue; + + if( expected[j] != outData[ i * vecSize + j ] ) { + ulp_error = Ulp_Error( outData[i*vecSize+j], expected[ j ] ); + + if( fabsf(ulp_error) > ulpLimit ) { + fail = 1; + break; + } + } + + } + + // try again with subnormals flushed to zero if the platform flushes + if( fail && gFlushDenormsToZero ) + { + float temp[4], expected2[4]; + for( j = 0; j < vecSize; j++ ) + { + if( IsFloatSubnormal(inDataA[i*vecSize+j] ) ) + temp[j] = copysignf( 0.0f, inDataA[i*vecSize+j] ); + else + temp[j] = inDataA[ i*vecSize +j]; + } + + verifyFn( temp, expected2, vecSize ); + fail = 0; + + for( j = 0; j < vecSize; j++ ) + { + // We have to special case NAN + if( isnan( outData[ i * vecSize + j ] ) && isnan( expected[ j ] ) ) + continue; + + if( expected2[j] != outData[ i * vecSize + j ] ) + { + ulp_error = Ulp_Error(outData[i*vecSize + j ], expected[ j ] ); + + if( fabsf(ulp_error) > ulpLimit ) + { + if( IsFloatSubnormal(expected2[j]) ) + { + expected2[j] = 0.0f; + if( expected2[j] != outData[i*vecSize + j ] ) + { + ulp_error = Ulp_Error( outData[ i * vecSize + j ], expected[ j ] ); + if( fabsf(ulp_error) > ulpLimit ) { + fail = 1; + break; + } + } + } + } + } + } + } + + if( fail ) + { + log_error( "ERROR: Data sample {%d,%d} at size %d does not validate! Expected %12.24f (%a), got %12.24f (%a), ulp %f\n", + (int)i, (int)j, (int)vecSize, expected[j], expected[j], outData[ i*vecSize+j], outData[ i*vecSize+j], ulp_error ); + log_error( " Source: " ); + for( size_t q = 0; q < vecSize; q++ ) + log_error( "%g ", inDataA[ i * vecSize+q]); + log_error( "\n : " ); + for( size_t q = 0; q < vecSize; q++ ) + log_error( "%a ", inDataA[i*vecSize +q] ); + log_error( "\n" ); + log_error( " Result: " ); + for( size_t q = 0; q < vecSize; q++ ) + log_error( "%g ", outData[ i *vecSize + q ] ); + log_error( "\n : " ); + for( size_t q = 0; q < vecSize; q++ ) + log_error( "%a ", outData[ i * vecSize + q ] ); + log_error( "\n" ); + log_error( " Expected: " ); + for( size_t q = 0; q < vecSize; q++ ) + log_error( "%g ", expected[ q ] ); + log_error( "\n : " ); + for( size_t q = 0; q < vecSize; q++ ) + log_error( "%a ", expected[ q ] ); + log_error( "\n" ); + return -1; + } + } + + return 0; +} + +void verifyNormalize( float *srcA, float *dst, size_t vecSize ) +{ + double total = 0, value; + unsigned int i; + + // We calculate everything as a double, to try and make up for the fact that + // the GPU has better precision distance since it's a single op + for( i = 0; i < vecSize; i++ ) + total += (double)srcA[i] * (double)srcA[i]; + + if( total == 0.f ) + { + // Special edge case: copy vector over without change + for( i = 0; i < vecSize; i++ ) + dst[i] = srcA[i]; + return; + } + + // Deal with infinities + if( total == INFINITY ) + { + total = 0.0f; + for( i = 0; i < vecSize; i++ ) + { + if( fabsf( srcA[i]) == INFINITY ) + dst[i] = copysignf( 1.0f, srcA[i] ); + else + dst[i] = copysignf( 0.0f, srcA[i] ); + total += (double)dst[i] * (double)dst[i]; + } + + srcA = dst; + } + + value = sqrt( total ); + for( i = 0; i < vecSize; i++ ) + dst[i] = (float)( (double)srcA[i] / value ); +} + +int test_geom_normalize(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + size_t sizes[] = { 1, 2, 3, 4, 0 }; + unsigned int size; + int retVal = 0; + RandomSeed seed(gRandomSeed); + + for( size = 0; sizes[ size ] != 0 ; size++ ) + { + float maxUlps = 2.5f + // error in rsqrt + error in multiply + ( 0.5f * (float) sizes[size] + // cumulative error for multiplications + 0.5f * (float) (sizes[size]-1)); // cumulative error for additions + if( test_oneToOne_kernel( queue, context, "normalize", sizes[ size ], verifyNormalize, maxUlps, 0, seed ) != 0 ) + { + log_error( " normalized vector size %d FAILED\n", (int)sizes[ size ] ); + retVal = -1; + } + else + { + log_info( " normalized vector size %d passed\n", (int)sizes[ size ] ); + } + } + if (retVal) + return retVal; + + if(!is_extension_available(deviceID, "cl_khr_fp64")) + { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + return 0; + } else { + log_info("Testing doubles...\n"); + return test_geom_normalize_double( deviceID, context, queue, num_elements, seed); + } +} + + +int test_geom_fast_normalize(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + size_t sizes[] = { 1, 2, 3, 4, 0 }; + unsigned int size; + int retVal = 0; + RandomSeed seed( gRandomSeed ); + + for( size = 0; sizes[ size ] != 0 ; size++ ) + { + float maxUlps = 8192.5f + // error in rsqrt + error in multiply + ( 0.5f * (float) sizes[size] + // cumulative error for multiplications + 0.5f * (float) (sizes[size]-1)); // cumulative error for additions + + if( test_oneToOne_kernel( queue, context, "fast_normalize", sizes[ size ], verifyNormalize, maxUlps, 1, seed ) != 0 ) + { + log_error( " fast_normalize vector size %d FAILED\n", (int)sizes[ size ] ); + retVal = -1; + } + else + { + log_info( " fast_normalize vector size %d passed\n", (int)sizes[ size ] ); + } + } + return retVal; +} + + + diff --git a/test_conformance/geometrics/test_geometrics_double.cpp b/test_conformance/geometrics/test_geometrics_double.cpp new file mode 100644 index 00000000..2d258d5d --- /dev/null +++ b/test_conformance/geometrics/test_geometrics_double.cpp @@ -0,0 +1,941 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/errorHelpers.h" + +const char *crossKernelSource_double = +"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" +"__kernel void sample_test(__global double4 *sourceA, __global double4 *sourceB, __global double4 *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = cross( sourceA[tid], sourceB[tid] );\n" +"\n" +"}\n"; + +const char *crossKernelSource_doubleV3 = +"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" +"__kernel void sample_test(__global double *sourceA, __global double *sourceB, __global double *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" vstore3( cross( vload3( tid, sourceA), vload3( tid, sourceB) ), tid, destValues);\n" +"\n" +"}\n"; + +const char *twoToFloatKernelPattern_double = +"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" +"__kernel void sample_test(__global double%s *sourceA, __global double%s *sourceB, __global double *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( sourceA[tid], sourceB[tid] );\n" +"\n" +"}\n"; + +const char *twoToFloatKernelPattern_doubleV3 = +"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" +"__kernel void sample_test(__global double%s *sourceA, __global double%s *sourceB, __global double *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( vload3( tid, (__global double*) sourceA), vload3( tid, (__global double*) sourceB ) );\n" +"\n" +"}\n"; + +const char *oneToFloatKernelPattern_double = +"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" +"__kernel void sample_test(__global double%s *sourceA, __global double *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( sourceA[tid] );\n" +"\n" +"}\n"; + +const char *oneToFloatKernelPattern_doubleV3 = +"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" +"__kernel void sample_test(__global double%s *sourceA, __global double *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( vload3( tid, (__global double*) sourceA) );\n" +"\n" +"}\n"; + +const char *oneToOneKernelPattern_double = +"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" +"__kernel void sample_test(__global double%s *sourceA, __global double%s *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( sourceA[tid] );\n" +"\n" +"}\n"; + +const char *oneToOneKernelPattern_doubleV3 = +"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" +"__kernel void sample_test(__global double%s *sourceA, __global double%s *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" vstore3( %s( vload3( tid, (__global double*) sourceA) ), tid, (__global double*) destValues );\n" +"\n" +"}\n"; + +#define TEST_SIZE (1 << 20) + +double verifyLength_double( double *srcA, size_t vecSize ); +double verifyDistance_double( double *srcA, double *srcB, size_t vecSize ); + + + +void vector2string_double( char *string, double *vector, size_t elements ) +{ + *string++ = '{'; + *string++ = ' '; + string += sprintf( string, "%a", vector[0] ); + size_t i; + for( i = 1; i < elements; i++ ) + string += sprintf( string, ", %a", vector[i] ); + *string++ = ' '; + *string++ = '}'; + *string = '\0'; +} + +void fillWithTrickyNumbers_double( double *aVectors, double *bVectors, size_t vecSize ) +{ + static const cl_double trickyValues[] = { -FLT_EPSILON, FLT_EPSILON, + MAKE_HEX_DOUBLE(0x1.0p511, 0x1L, 511), MAKE_HEX_DOUBLE(0x1.8p511, 0x18L, 507), MAKE_HEX_DOUBLE(0x1.0p512, 0x1L, 512), MAKE_HEX_DOUBLE(-0x1.0p511, -0x1L, 511), MAKE_HEX_DOUBLE(-0x1.8p-511, -0x18L, -515), MAKE_HEX_DOUBLE(-0x1.0p512, -0x1L, 512), + MAKE_HEX_DOUBLE(0x1.0p-511, 0x1L, -511), MAKE_HEX_DOUBLE(0x1.8p-511, 0x18L, -515), MAKE_HEX_DOUBLE(0x1.0p-512, 0x1L, -512), MAKE_HEX_DOUBLE(-0x1.0p-511, -0x1L, -511), MAKE_HEX_DOUBLE(-0x1.8p-511, -0x18L, -515), MAKE_HEX_DOUBLE(-0x1.0p-512, -0x1L, -512), + DBL_MAX / 2., -DBL_MAX / 2., INFINITY, -INFINITY, 0., -0. }; + static const size_t trickyCount = sizeof( trickyValues ) / sizeof( trickyValues[0] ); + static const size_t stride[4] = {1, trickyCount, trickyCount*trickyCount, trickyCount*trickyCount*trickyCount }; + size_t i, j, k; + + for( j = 0; j < vecSize; j++ ) + for( k = 0; k < vecSize; k++ ) + for( i = 0; i < trickyCount; i++ ) + aVectors[ j + stride[j] * (i + k*trickyCount)*vecSize] = trickyValues[i]; + + if( bVectors ) + { + size_t copySize = vecSize * vecSize * trickyCount; + memset( bVectors, 0, sizeof(double) * copySize ); + memset( aVectors + copySize, 0, sizeof(double) * copySize ); + memcpy( bVectors + copySize, aVectors, sizeof(double) * copySize ); + } +} + + +void cross_product_double( const double *vecA, const double *vecB, double *outVector, double *errorTolerances, double ulpTolerance ) +{ + outVector[ 0 ] = ( vecA[ 1 ] * vecB[ 2 ] ) - ( vecA[ 2 ] * vecB[ 1 ] ); + outVector[ 1 ] = ( vecA[ 2 ] * vecB[ 0 ] ) - ( vecA[ 0 ] * vecB[ 2 ] ); + outVector[ 2 ] = ( vecA[ 0 ] * vecB[ 1 ] ) - ( vecA[ 1 ] * vecB[ 0 ] ); + outVector[ 3 ] = 0.0f; + + errorTolerances[ 0 ] = fmax( fabs( vecA[ 1 ] ), fmax( fabs( vecB[ 2 ] ), fmax( fabs( vecA[ 2 ] ), fabs( vecB[ 1 ] ) ) ) ); + errorTolerances[ 1 ] = fmax( fabs( vecA[ 2 ] ), fmax( fabs( vecB[ 0 ] ), fmax( fabs( vecA[ 0 ] ), fabs( vecB[ 2 ] ) ) ) ); + errorTolerances[ 2 ] = fmax( fabs( vecA[ 0 ] ), fmax( fabs( vecB[ 1 ] ), fmax( fabs( vecA[ 1 ] ), fabs( vecB[ 0 ] ) ) ) ); + + errorTolerances[ 0 ] = errorTolerances[ 0 ] * errorTolerances[ 0 ] * ( ulpTolerance * FLT_EPSILON ); // This gives us max squared times ulp tolerance, i.e. the worst-case expected variance we could expect from this result + errorTolerances[ 1 ] = errorTolerances[ 1 ] * errorTolerances[ 1 ] * ( ulpTolerance * FLT_EPSILON ); + errorTolerances[ 2 ] = errorTolerances[ 2 ] * errorTolerances[ 2 ] * ( ulpTolerance * FLT_EPSILON ); +} + +int test_geom_cross_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, MTdata d) +{ + cl_int error; + cl_ulong maxAllocSize, maxGlobalMemSize; + + error = clGetDeviceInfo( deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( deviceID, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( maxGlobalMemSize ), &maxGlobalMemSize, NULL ); + test_error( error, "Unable to get device config" ); + + log_info("Device supports:\nCL_DEVICE_MAX_MEM_ALLOC_SIZE: %gMB\nCL_DEVICE_GLOBAL_MEM_SIZE: %gMB\n", + maxGlobalMemSize/(1024.0*1024.0), maxAllocSize/(1024.0*1024.0)); + + if (maxGlobalMemSize > (cl_ulong)SIZE_MAX) { + maxGlobalMemSize = (cl_ulong)SIZE_MAX; + } + + unsigned int size; + unsigned int bufSize; + unsigned int adjustment; + int vecsize; + + adjustment = 32*1024*1024; /* Try to allocate a bit less than the limits */ + for(vecsize = 3; vecsize <= 4; ++vecsize) + { + /* Make sure we adhere to the maximum individual allocation size and global memory size limits. */ + size = TEST_SIZE; + bufSize = sizeof(cl_double) * TEST_SIZE * vecsize; + + while ((bufSize > (maxAllocSize - adjustment)) || (3*bufSize > (maxGlobalMemSize - adjustment))) { + size /= 2; + bufSize = sizeof(cl_double) * size * vecsize; + } + + /* Perform the test */ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[3]; + cl_double testVector[4]; + int error, i; + size_t threads[1], localThreads[1]; + BufferOwningPtr A(malloc(bufSize)); + BufferOwningPtr B(malloc(bufSize)); + BufferOwningPtr C(malloc(bufSize)); + cl_double *inDataA = A; + cl_double *inDataB = B; + cl_double *outData = C; + + /* Create kernels */ + if( create_single_kernel_helper( context, &program, &kernel, 1, vecsize == 3 ? &crossKernelSource_doubleV3 : &crossKernelSource_double, "sample_test" ) ) + return -1; + + /* Generate some streams. Note: deliberately do some random data in w to verify that it gets ignored */ + for( i = 0; i < TEST_SIZE * vecsize; i++ ) + { + inDataA[ i ] = get_random_double( -512.f, 512.f, d ); + inDataB[ i ] = get_random_double( -512.f, 512.f, d ); + } + fillWithTrickyNumbers_double( inDataA, inDataB, vecsize ); + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), bufSize, inDataA, NULL); + if( streams[0] == NULL ) + { + log_error("ERROR: Creating input array A failed!\n"); + return -1; + } + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), bufSize, inDataB, NULL); + if( streams[1] == NULL ) + { + log_error("ERROR: Creating input array B failed!\n"); + return -1; + } + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), bufSize, NULL, NULL); + if( streams[2] == NULL ) + { + log_error("ERROR: Creating output array failed!\n"); + return -1; + } + + /* Assign streams and execute */ + for( i = 0; i < 3; i++ ) + { + error = clSetKernelArg(kernel, i, sizeof( streams[i] ), &streams[i]); + test_error( error, "Unable to set indexed kernel arguments" ); + } + + /* Run the kernel */ + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[2], true, 0, bufSize, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + /* And verify! */ + for( i = 0; i < size; i++ ) + { + double errorTolerances[ 4 ]; + // On an embedded device w/ round-to-zero, 3 ulps is the worst-case tolerance for cross product + cross_product_double( inDataA + i * vecsize, inDataB + i * vecsize, testVector, errorTolerances, 3.f ); + + double errs[] = { fabs( testVector[ 0 ] - outData[ i * vecsize + 0 ] ), + fabs( testVector[ 1 ] - outData[ i * vecsize + 1 ] ), + fabs( testVector[ 2 ] - outData[ i * vecsize + 2 ] ) }; + + if( errs[ 0 ] > errorTolerances[ 0 ] || errs[ 1 ] > errorTolerances[ 1 ] || errs[ 2 ] > errorTolerances[ 2 ] ) + { + log_error( "ERROR: Data sample %d does not validate! Expected (%a,%a,%a,%a), got (%a,%a,%a,%a)\n", + i, testVector[0], testVector[1], testVector[2], testVector[3], + outData[i*vecsize], outData[i*vecsize+1], outData[i*vecsize+2], outData[i*vecsize+3] ); + log_error( " Input: (%a %a %a) and (%a %a %a)\n", + inDataA[ i * vecsize + 0 ], inDataA[ i * vecsize + 1 ], inDataA[ i * vecsize + 2 ], + inDataB[ i * vecsize + 0 ], inDataB[ i * vecsize + 1 ], inDataB[ i * vecsize + 2 ] ); + log_error( " Errors: (%a out of %a), (%a out of %a), (%a out of %a)\n", + errs[ 0 ], errorTolerances[ 0 ], errs[ 1 ], errorTolerances[ 1 ], errs[ 2 ], errorTolerances[ 2 ] ); + log_error(" ulp %g\n", Ulp_Error_Double( outData[ i * vecsize + 1 ], testVector[ 1 ] ) ); + return -1; + } + } + } + return 0; +} + +double getMaxValue_double( double vecA[], double vecB[], size_t vecSize ) +{ + double a = fmax( fabs( vecA[ 0 ] ), fabs( vecB[ 0 ] ) ); + for( size_t i = 1; i < vecSize; i++ ) + a = fmax( fabs( vecA[ i ] ), fmax( fabs( vecB[ i ] ), a ) ); + return a; +} + +typedef double (*twoToFloatVerifyFn_double)( double *srcA, double *srcB, size_t vecSize ); + +int test_twoToFloat_kernel_double(cl_command_queue queue, cl_context context, const char *fnName, + size_t vecSize, twoToFloatVerifyFn_double verifyFn, double ulpLimit, MTdata d ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[3]; + int error; + size_t i, threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + char sizeNames[][4] = { "", "2", "3", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + BufferOwningPtr A(malloc(sizeof(cl_double) * TEST_SIZE * vecSize)); + BufferOwningPtr B(malloc(sizeof(cl_double) * TEST_SIZE * vecSize)); + BufferOwningPtr C(malloc(sizeof(cl_double) * TEST_SIZE)); + + cl_double *inDataA = A; + cl_double *inDataB = B; + cl_double *outData = C; + + /* Create the source */ + sprintf( kernelSource, vecSize == 3 ? twoToFloatKernelPattern_doubleV3 : twoToFloatKernelPattern_double, sizeNames[vecSize-1], sizeNames[vecSize-1], fnName ); + + /* Create kernels */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + return -1; + + /* Generate some streams */ + for( i = 0; i < TEST_SIZE * vecSize; i++ ) + { + inDataA[ i ] = any_double(d); + inDataB[ i ] = any_double(d); + } + fillWithTrickyNumbers_double( inDataA, inDataB, vecSize ); + + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_double) * vecSize * TEST_SIZE, inDataA, NULL); + if( streams[0] == NULL ) + { + log_error("ERROR: Creating input array A failed!\n"); + return -1; + } + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_double) * vecSize * TEST_SIZE, inDataB, NULL); + if( streams[1] == NULL ) + { + log_error("ERROR: Creating input array B failed!\n"); + return -1; + } + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_double) * TEST_SIZE, NULL, NULL); + if( streams[2] == NULL ) + { + log_error("ERROR: Creating output array failed!\n"); + return -1; + } + + /* Assign streams and execute */ + for( i = 0; i < 3; i++ ) + { + error = clSetKernelArg(kernel, (int)i, sizeof( streams[i] ), &streams[i]); + test_error( error, "Unable to set indexed kernel arguments" ); + } + + /* Run the kernel */ + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[2], true, 0, sizeof( cl_double ) * TEST_SIZE, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + /* And verify! */ + for( i = 0; i < TEST_SIZE; i++ ) + { + double expected = verifyFn( inDataA + i * vecSize, inDataB + i * vecSize, vecSize ); + if( (double) expected != outData[ i ] ) + { + if( isnan(expected) && isnan( outData[i] ) ) + continue; + + if( ulpLimit < 0 ) + { + // Limit below zero means we need to test via a computed error (like cross product does) + double maxValue = + getMaxValue_double( inDataA + i * vecSize, inDataB + i * vecSize, vecSize ); + + // In this case (dot is the only one that gets here), the ulp is 2*vecSize - 1 (n + n-1 max # of errors) + double errorTolerance = maxValue * maxValue * ( 2.f * (double)vecSize - 1.f ) * FLT_EPSILON; + + // Limit below zero means test via epsilon instead + double error = fabs( (double)expected - (double)outData[ i ] ); + if( error > errorTolerance ) + { + + log_error( "ERROR: Data sample %d at size %d does not validate! Expected (%a), got (%a), sources (%a and %a) error of %g against tolerance %g\n", + (int)i, (int)vecSize, expected, + outData[ i ], + inDataA[i*vecSize], + inDataB[i*vecSize], + (double)error, + (double)errorTolerance ); + + char vecA[1000], vecB[1000]; + vector2string_double( vecA, inDataA + i * vecSize, vecSize ); + vector2string_double( vecB, inDataB + i * vecSize, vecSize ); + log_error( "\tvector A: %s\n\tvector B: %s\n", vecA, vecB ); + return -1; + } + } + else + { + double error = Ulp_Error_Double( outData[ i ], + expected ); + if( fabs(error) > ulpLimit ) + { + log_error( "ERROR: Data sample %d at size %d does not validate! Expected (%a), got (%a), sources (%a and %a) ulp of %f\n", + (int)i, (int)vecSize, expected, + outData[ i ], + inDataA[i*vecSize], + inDataB[i*vecSize], + error ); + + char vecA[1000], vecB[1000]; + vector2string_double( vecA, inDataA + i * vecSize, vecSize ); + vector2string_double( vecB, inDataB + i * vecSize, vecSize ); + log_error( "\tvector A: %s\n\tvector B: %s\n", vecA, vecB ); + return -1; + } + } + } + } + return 0; +} + +double verifyDot_double( double *srcA, double *srcB, size_t vecSize ) +{ + double total = 0.f; + + for( unsigned int i = 0; i < vecSize; i++ ) + total += (double)srcA[ i ] * (double)srcB[ i ]; + + return total; +} + +int test_geom_dot_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, MTdata d) +{ + size_t sizes[] = { 1, 2, 3, 4, 0 }; + unsigned int size; + int retVal = 0; + + + for( size = 0; sizes[ size ] != 0 ; size++ ) + { + if( test_twoToFloat_kernel_double( queue, context, "dot", sizes[ size ], verifyDot_double, -1.0f /*magic value*/, d ) != 0 ) + { + log_error( " dot double vector size %d FAILED\n", (int)sizes[ size ] ); + retVal = -1; + } + } + return retVal; +} + + +int test_geom_fast_distance_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, MTdata d) +{ + size_t sizes[] = { 1, 2, 3, 4, 0 }; + unsigned int size; + int retVal = 0; + + abort(); //there is no double precision fast_distance + + for( size = 0; sizes[ size ] != 0 ; size++ ) + { + double maxUlps = 8192.0f + // error in sqrt + 0.5f * // effect on e of taking sqrt( x + e ) + ( 1.5f * (double) sizes[size] + // cumulative error for multiplications (a-b+0.5ulp)**2 = (a-b)**2 + a*0.5ulp + b*0.5 ulp + 0.5 ulp for multiplication + 0.5f * (double) (sizes[size]-1)); // cumulative error for additions + + if( test_twoToFloat_kernel_double( queue, context, "fast_distance", sizes[ size ], verifyDistance_double, maxUlps, d ) != 0 ) + { + log_error( " fast_distance double vector size %d FAILED\n", (int)sizes[ size ] ); + retVal = -1; + } + else + { + log_info( " fast_distance double vector size %d passed\n", (int)sizes[ size ] ); + } + } + return retVal; +} + + +double verifyDistance_double( double *srcA, double *srcB, size_t vecSize ) +{ + unsigned int i; + double diff[4]; + + for( i = 0; i < vecSize; i++ ) + diff[i] = srcA[i] - srcB[i]; + + return verifyLength_double( diff, vecSize ); +} + +int test_geom_distance_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, MTdata d) +{ + size_t sizes[] = { 1, 2, 3, 4, 0 }; + unsigned int size; + int retVal = 0; + + for( size = 0; sizes[ size ] != 0 ; size++ ) + { + double maxUlps = 3.0f + // error in sqrt + 0.5f * // effect on e of taking sqrt( x + e ) + ( 1.5f * (double) sizes[size] + // cumulative error for multiplications (a-b+0.5ulp)**2 = (a-b)**2 + a*0.5ulp + b*0.5 ulp + 0.5 ulp for multiplication + 0.5f * (double) (sizes[size]-1)); // cumulative error for additions + + maxUlps *= 2.0; // our reference code may be in error too + + if( test_twoToFloat_kernel_double( queue, context, "distance", sizes[ size ], verifyDistance_double, maxUlps, d ) != 0 ) + { + log_error( " distance double vector size %d FAILED\n", (int)sizes[ size ] ); + retVal = -1; + } + else + { + log_info( " distance double vector size %d passed\n", (int)sizes[ size ] ); + } + } + return retVal; +} + +typedef double (*oneToFloatVerifyFn_double)( double *srcA, size_t vecSize ); + +int test_oneToFloat_kernel_double(cl_command_queue queue, cl_context context, const char *fnName, + size_t vecSize, oneToFloatVerifyFn_double verifyFn, double ulpLimit, MTdata d ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + BufferOwningPtr A(malloc(sizeof(cl_double) * TEST_SIZE * vecSize)); + BufferOwningPtr B(malloc(sizeof(cl_double) * TEST_SIZE)); + int error; + size_t i, threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + char sizeNames[][4] = { "", "2", "3", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + cl_double *inDataA = A; + cl_double *outData = B; + + /* Create the source */ + sprintf( kernelSource, vecSize == 3 ? oneToFloatKernelPattern_doubleV3 : oneToFloatKernelPattern_double, sizeNames[vecSize-1], fnName ); + + /* Create kernels */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + return -1; + + /* Generate some streams */ + for( i = 0; i < TEST_SIZE * vecSize; i++ ) + inDataA[ i ] = any_double(d); + + fillWithTrickyNumbers_double( inDataA, NULL, vecSize ); + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_double) * vecSize * TEST_SIZE, inDataA, NULL); + if( streams[0] == NULL ) + { + log_error("ERROR: Creating input array A failed!\n"); + return -1; + } + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_double) * TEST_SIZE, NULL, NULL); + if( streams[1] == NULL ) + { + log_error("ERROR: Creating output array failed!\n"); + return -1; + } + + /* Assign streams and execute */ + error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[ 1 ] ), &streams[1] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + /* Run the kernel */ + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[1], true, 0, sizeof( cl_double ) * TEST_SIZE, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + /* And verify! */ + for( i = 0; i < TEST_SIZE; i++ ) + { + double expected = verifyFn( inDataA + i * vecSize, vecSize ); + if( (double) expected != outData[ i ] ) + { + double ulps = Ulp_Error_Double( outData[i], expected ); + if( fabs( ulps ) <= ulpLimit ) + continue; + + // We have to special case NAN + if( isnan( outData[ i ] ) && isnan( expected ) ) + continue; + + if(! (fabs(ulps) < ulpLimit) ) + { + log_error( "ERROR: Data sample %d at size %d does not validate! Expected (%a), got (%a), source (%a), ulp %f\n", + (int)i, (int)vecSize, expected, outData[ i ], inDataA[i*vecSize], ulps ); + char vecA[1000]; + vector2string_double( vecA, inDataA + i * vecSize, vecSize ); + log_error( "\tvector: %s", vecA ); + return -1; + } + } + } + + return 0; +} + +double verifyLength_double( double *srcA, size_t vecSize ) +{ + double total = 0; + unsigned int i; + + // We calculate the distance as a double, to try and make up for the fact that + // the GPU has better precision distance since it's a single op + for( i = 0; i < vecSize; i++ ) + total += srcA[i] * srcA[i]; + + // Deal with spurious overflow + if( total == INFINITY ) + { + total = 0.0; + for( i = 0; i < vecSize; i++ ) + { + double f = srcA[i] * MAKE_HEX_DOUBLE(0x1.0p-600, 0x1LL, -600); + total += f * f; + } + + return sqrt( total ) * MAKE_HEX_DOUBLE(0x1.0p600, 0x1LL, 600); + } + + // Deal with spurious underflow + if( total < 4 /*max vector length*/ * DBL_MIN / DBL_EPSILON ) + { + total = 0.0; + for( i = 0; i < vecSize; i++ ) + { + double f = srcA[i] * MAKE_HEX_DOUBLE(0x1.0p700, 0x1LL, 700); + total += f * f; + } + + return sqrt( total ) * MAKE_HEX_DOUBLE(0x1.0p-700, 0x1LL, -700); + } + + return sqrt( total ); +} + +int test_geom_length_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, MTdata d) +{ + size_t sizes[] = { 1, 2, 3, 4, 0 }; + unsigned int size; + int retVal = 0; + + for( size = 0; sizes[ size ] != 0 ; size++ ) + { + double maxUlps = 3.0f + // error in sqrt + 0.5f * // effect on e of taking sqrt( x + e ) + ( 0.5f * (double) sizes[size] + // cumulative error for multiplications + 0.5f * (double) (sizes[size]-1)); // cumulative error for additions + + maxUlps *= 2.0; // our reference code may be in error too + if( test_oneToFloat_kernel_double( queue, context, "length", sizes[ size ], verifyLength_double, maxUlps, d ) != 0 ) + { + log_error( " length double vector size %d FAILED\n", (int)sizes[ size ] ); + retVal = -1; + } + else + { + log_info( " length double vector size %d passed\n", (int)sizes[ size ] ); + } + } + return retVal; +} + + +double verifyFastLength_double( double *srcA, size_t vecSize ) +{ + double total = 0; + unsigned int i; + + // We calculate the distance as a double, to try and make up for the fact that + // the GPU has better precision distance since it's a single op + for( i = 0; i < vecSize; i++ ) + { + total += (double)srcA[i] * (double)srcA[i]; + } + + return sqrt( total ); +} + +int test_geom_fast_length_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, MTdata d) +{ + size_t sizes[] = { 1, 2, 3, 4, 0 }; + unsigned int size; + int retVal = 0; + + abort(); //there is no double precision fast_length + + for( size = 0; sizes[ size ] != 0 ; size++ ) + { + double maxUlps = 8192.0f + // error in half_sqrt + 0.5f * // effect on e of taking sqrt( x + e ) + ( 0.5f * (double) sizes[size] + // cumulative error for multiplications + 0.5f * (double) (sizes[size]-1)); // cumulative error for additions + + if( test_oneToFloat_kernel_double( queue, context, "fast_length", sizes[ size ], verifyFastLength_double, maxUlps, d ) != 0 ) + { + log_error( " fast_length double vector size %d FAILED\n", (int)sizes[ size ] ); + retVal = -1; + } + else + { + log_info( " fast_length double vector size %d passed\n", (int)sizes[ size ] ); + } + } + return retVal; +} + + +typedef void (*oneToOneVerifyFn_double)( double *srcA, double *dstA, size_t vecSize ); + +int test_oneToOne_kernel_double(cl_command_queue queue, cl_context context, const char *fnName, + size_t vecSize, oneToOneVerifyFn_double verifyFn, double ulpLimit, MTdata d ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + BufferOwningPtr A(malloc(sizeof(cl_double) * TEST_SIZE * vecSize)); + BufferOwningPtr B(malloc(sizeof(cl_double) * TEST_SIZE * vecSize)); + int error; + size_t i, j, threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + char sizeNames[][4] = { "", "2", "3", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + cl_double *inDataA = A; + cl_double *outData = B; + + /* Create the source */ + sprintf( kernelSource, vecSize == 3 ? oneToOneKernelPattern_doubleV3 : oneToOneKernelPattern_double, sizeNames[vecSize-1], sizeNames[vecSize-1], fnName ); + + /* Create kernels */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + return -1; + + /* initialize data */ + memset( inDataA, 0, vecSize * sizeof( cl_double ) ); + for( i = vecSize; i < TEST_SIZE * vecSize; i++ ) + inDataA[ i ] = any_double(d); + + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_double) * vecSize * TEST_SIZE, inDataA, NULL); + if( streams[0] == NULL ) + { + log_error("ERROR: Creating input array A failed!\n"); + return -1; + } + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_double) * vecSize * TEST_SIZE, NULL, NULL); + if( streams[1] == NULL ) + { + log_error("ERROR: Creating output array failed!\n"); + return -1; + } + + /* Assign streams and execute */ + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + /* Run the kernel */ + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[1], true, 0, sizeof( cl_double ) * TEST_SIZE * vecSize, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + /* And verify! */ + for( i = 0; i < TEST_SIZE; i++ ) + { + double expected[4]; + verifyFn( inDataA + i * vecSize, expected, vecSize ); + for( j = 0; j < vecSize; j++ ) + { + // We have to special case NAN + if( isnan( outData[ i * vecSize + j ] ) && isnan( expected[ j ] ) ) + continue; + + if( expected[j] != outData[ i *vecSize+j ] ) + { + double error = + Ulp_Error_Double( outData[i*vecSize + j ], expected[ j ] ); + if( fabs(error) > ulpLimit ) + { + log_error( "ERROR: Data sample {%d,%d} at size %d does not validate! Expected %12.24f (%a), got %12.24f (%a), ulp %f\n", + (int)i, (int)j, (int)vecSize, + expected[j], expected[j], + outData[i*vecSize +j], + outData[i*vecSize +j], error ); + log_error( " Source: " ); + for( size_t q = 0; q < vecSize; q++ ) + log_error( "%g ", inDataA[ i * vecSize + q ] ); + log_error( "\n : " ); + for( size_t q = 0; q < vecSize; q++ ) + log_error( "%a ", inDataA[ i * vecSize + q ] ); + log_error( "\n" ); + log_error( " Result: " ); + for( size_t q = 0; q < vecSize; q++ ) + log_error( "%g ", outData[i * vecSize + q ] ); + log_error( "\n : " ); + for( size_t q = 0; q < vecSize; q++ ) + log_error( "%a ", outData[i * vecSize + q ] ); + log_error( "\n" ); + log_error( " Expected: " ); + for( size_t q = 0; q < vecSize; q++ ) + log_error( "%g ", expected[ q ] ); + log_error( "\n : " ); + for( size_t q = 0; q < vecSize; q++ ) + log_error( "%a ", expected[ q ] ); + log_error( "\n" ); + return -1; + } + } + } + } + + return 0; +} + +void verifyNormalize_double( double *srcA, double *dst, size_t vecSize ) +{ + double total = 0, value; + unsigned int i; + + // We calculate everything as a double, to try and make up for the fact that + // the GPU has better precision distance since it's a single op + for( i = 0; i < vecSize; i++ ) + total += (double)srcA[i] * (double)srcA[i]; + + if( total < vecSize * DBL_MIN / DBL_EPSILON ) + { //we may have incurred denormalization loss -- rescale + total = 0; + for( i = 0; i < vecSize; i++ ) + { + dst[i] = srcA[i] * MAKE_HEX_DOUBLE(0x1.0p700, 0x1LL, 700); //exact + total += dst[i] * dst[i]; + } + + //If still zero + if( total == 0.0 ) + { + // Special edge case: copy vector over without change + for( i = 0; i < vecSize; i++ ) + dst[i] = srcA[i]; + return; + } + + srcA = dst; + } + else if( total == INFINITY ) + { //we may have incurred spurious overflow + double scale = MAKE_HEX_DOUBLE(0x1.0p-512, 0x1LL, -512) / vecSize; + total = 0; + for( i = 0; i < vecSize; i++ ) + { + dst[i] = srcA[i] * scale; //exact + total += dst[i] * dst[i]; + } + + // If there are infinities here, handle those + if( total == INFINITY ) + { + total = 0; + for( i = 0; i < vecSize; i++ ) + { + if( isinf(dst[i]) ) + { + dst[i] = copysign( 1.0, srcA[i] ); + total += 1.0; + } + else + dst[i] = copysign( 0.0, srcA[i] ); + } + } + + srcA = dst; + } + + value = sqrt( total ); + + for( i = 0; i < vecSize; i++ ) + dst[i] = srcA[i] / value; +} + +int test_geom_normalize_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, MTdata d) +{ + size_t sizes[] = { 1, 2, 3, 4, 0 }; + unsigned int size; + int retVal = 0; + + for( size = 0; sizes[ size ] != 0 ; size++ ) + { + double maxUlps = 2.5f + // error in rsqrt + error in multiply + 0.5f * // effect on e of taking sqrt( x + e ) + ( 0.5f * (double) sizes[size] + // cumulative error for multiplications + 0.5f * (double) (sizes[size]-1)); // cumulative error for additions + + maxUlps *= 2.0; //our reference code is not infinitely precise and may have error of its own + if( test_oneToOne_kernel_double( queue, context, "normalize", sizes[ size ], verifyNormalize_double, maxUlps, d ) != 0 ) + { + log_error( " normalize double vector size %d FAILED\n", (int)sizes[ size ] ); + retVal = -1; + } + else + { + log_info( " normalize double vector size %d passed\n", (int)sizes[ size ] ); + } + } + return retVal; +} + + + + + diff --git a/test_conformance/gl/CMakeLists.txt b/test_conformance/gl/CMakeLists.txt new file mode 100644 index 00000000..3ebdf6c7 --- /dev/null +++ b/test_conformance/gl/CMakeLists.txt @@ -0,0 +1,63 @@ +if(WIN32) +list(APPEND CLConform_LIBRARIES glut32 opengl32 glu32 ) +else(WIN32) +list(APPEND CLConform_LIBRARIES GL glut GLEW GLU) +endif(WIN32) + +set (GL_SOURCES + main.cpp + test_buffers.cpp + test_images_2D.cpp + test_images_3D.cpp + test_renderbuffer.cpp + test_images_2D_info.cpp + test_images_3D_info.cpp + test_renderbuffer_info.cpp + test_fence_sync.cpp + helpers.cpp + ../../test_common/gl/helpers.cpp + ../../test_common/harness/genericThread.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp + ) + +if (WIN32) + list (APPEND GL_SOURCES ../../test_common/gl/setup_win32.cpp) +else(WIN32) + list (APPEND GL_SOURCES ../../test_common/gl/setup_x11.cpp) +endif(WIN32) + +# Compiling GLEW along with the project if the compiler is MINGW. +# The mingw linker was giving weird errors while linking to glew32.lib generated by +# MSVC. +if(MINGW) + list (APPEND GL_SOURCES GLEW/glew.c) + set_source_files_properties( + ${GL_SOURCES} + COMPILE_FLAGS -DGLEW_STATIC) + include_directories("./GLEW/") +endif(MINGW) + +if (MSVC) + if(CMAKE_CL_64) + list(APPEND CLConform_LIBRARIES glew64) + else(CMAKE_CL_64) + list(APPEND CLConform_LIBRARIES glew32) + endif(CMAKE_CL_64) +endif(MSVC) + +add_executable(conformance_test_gl + ${GL_SOURCES} ${GLUT_SOURCES}) + +set_source_files_properties( + ${GL_SOURCES} + PROPERTIES LANGUAGE CXX) + +TARGET_LINK_LIBRARIES(conformance_test_gl + ${CLConform_LIBRARIES}) diff --git a/test_conformance/gl/GLEW/GL/glew.h b/test_conformance/gl/GLEW/GL/glew.h new file mode 100644 index 00000000..13723b4e --- /dev/null +++ b/test_conformance/gl/GLEW/GL/glew.h @@ -0,0 +1,12262 @@ +/* +** The OpenGL Extension Wrangler Library +** Copyright (C) 2002-2008, Milan Ikits +** Copyright (C) 2002-2008, Marcelo E. Magallon +** Copyright (C) 2002, Lev Povalahev +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** * The name of the author may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +** THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * Mesa 3-D graphics library + * Version: 7.0 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* +** Copyright (c) 2007 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#ifndef __glew_h__ +#define __glew_h__ +#define __GLEW_H__ + +#if defined(__gl_h_) || defined(__GL_H__) +#error gl.h included before glew.h +#endif +#if defined(__glext_h_) || defined(__GLEXT_H_) +#error glext.h included before glew.h +#endif +#if defined(__gl_ATI_h_) +#error glATI.h included before glew.h +#endif + +#define __gl_h_ +#define __GL_H__ +#define __glext_h_ +#define __GLEXT_H_ +#define __gl_ATI_h_ + +#if defined(_WIN32) + +/* + * GLEW does not include to avoid name space pollution. + * GL needs GLAPI and GLAPIENTRY, GLU needs APIENTRY, CALLBACK, and wchar_t + * defined properly. + */ +/* */ +#ifndef APIENTRY +#define GLEW_APIENTRY_DEFINED +# if defined(__MINGW32__) +# define APIENTRY __stdcall +# elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__) +# define APIENTRY __stdcall +# else +# define APIENTRY +# endif +#endif +#ifndef GLAPI +# if defined(__MINGW32__) +# define GLAPI extern +# endif +#endif +/* */ +#ifndef CALLBACK +#define GLEW_CALLBACK_DEFINED +# if defined(__MINGW32__) +# define CALLBACK __attribute__ ((__stdcall__)) +# elif (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) +# define CALLBACK __stdcall +# else +# define CALLBACK +# endif +#endif +/* and */ +#ifndef WINGDIAPI +#define GLEW_WINGDIAPI_DEFINED +#define WINGDIAPI __declspec(dllimport) +#endif +/* */ +#if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(_WCHAR_T_DEFINED) +typedef unsigned short wchar_t; +# define _WCHAR_T_DEFINED +#endif +/* */ +#if !defined(_W64) +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && defined(_MSC_VER) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif +#if !defined(_PTRDIFF_T_DEFINED) && !defined(_PTRDIFF_T_) +# ifdef _WIN64 +typedef __int64 ptrdiff_t; +# else +typedef _W64 int ptrdiff_t; +# endif +# define _PTRDIFF_T_DEFINED +# define _PTRDIFF_T_ +#endif + +#ifndef GLAPI +# if defined(__MINGW32__) +# define GLAPI extern +# else +# define GLAPI WINGDIAPI +# endif +#endif + +#ifndef GLAPIENTRY +#define GLAPIENTRY APIENTRY +#endif + +/* + * GLEW_STATIC needs to be set when using the static version. + * GLEW_BUILD is set when building the DLL version. + */ +#ifdef GLEW_STATIC +# define GLEWAPI extern +#else +# ifdef GLEW_BUILD +# define GLEWAPI extern __declspec(dllexport) +# else +# define GLEWAPI extern __declspec(dllimport) +# endif +#endif + +#else /* _UNIX */ + +/* + * Needed for ptrdiff_t in turn needed by VBO. This is defined by ISO + * C. On my system, this amounts to _3 lines_ of included code, all of + * them pretty much harmless. If you know of a way of detecting 32 vs + * 64 _targets_ at compile time you are free to replace this with + * something that's portable. For now, _this_ is the portable solution. + * (mem, 2004-01-04) + */ + +#include +#include + +#define GLEW_APIENTRY_DEFINED +#define APIENTRY +#define GLEWAPI extern + +/* */ +#ifndef GLAPI +#define GLAPI extern +#endif +#ifndef GLAPIENTRY +#define GLAPIENTRY +#endif + +#endif /* _WIN32 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----------------------------- GL_VERSION_1_1 ---------------------------- */ + +#ifndef GL_VERSION_1_1 +#define GL_VERSION_1_1 1 + +typedef unsigned int GLenum; +typedef unsigned int GLbitfield; +typedef unsigned int GLuint; +typedef int GLint; +typedef int GLsizei; +typedef unsigned char GLboolean; +typedef signed char GLbyte; +typedef short GLshort; +typedef unsigned char GLubyte; +typedef unsigned short GLushort; +typedef unsigned long GLulong; +typedef float GLfloat; +typedef float GLclampf; +typedef double GLdouble; +typedef double GLclampd; +typedef void GLvoid; +#if defined(_MSC_VER) +# if _MSC_VER < 1400 +typedef __int64 GLint64EXT; +typedef unsigned __int64 GLuint64EXT; +# else +typedef signed long long GLint64EXT; +typedef unsigned long long GLuint64EXT; +# endif +#else +# if defined(__MINGW32__) +#include +# endif +typedef int64_t GLint64EXT; +typedef uint64_t GLuint64EXT; +#endif + +#define GL_ACCUM 0x0100 +#define GL_LOAD 0x0101 +#define GL_RETURN 0x0102 +#define GL_MULT 0x0103 +#define GL_ADD 0x0104 +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_CURRENT_BIT 0x00000001 +#define GL_POINT_BIT 0x00000002 +#define GL_LINE_BIT 0x00000004 +#define GL_POLYGON_BIT 0x00000008 +#define GL_POLYGON_STIPPLE_BIT 0x00000010 +#define GL_PIXEL_MODE_BIT 0x00000020 +#define GL_LIGHTING_BIT 0x00000040 +#define GL_FOG_BIT 0x00000080 +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_ACCUM_BUFFER_BIT 0x00000200 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_VIEWPORT_BIT 0x00000800 +#define GL_TRANSFORM_BIT 0x00001000 +#define GL_ENABLE_BIT 0x00002000 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_HINT_BIT 0x00008000 +#define GL_EVAL_BIT 0x00010000 +#define GL_LIST_BIT 0x00020000 +#define GL_TEXTURE_BIT 0x00040000 +#define GL_SCISSOR_BIT 0x00080000 +#define GL_ALL_ATTRIB_BITS 0x000fffff +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_QUADS 0x0007 +#define GL_QUAD_STRIP 0x0008 +#define GL_POLYGON 0x0009 +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_TRUE 1 +#define GL_FALSE 0 +#define GL_CLIP_PLANE0 0x3000 +#define GL_CLIP_PLANE1 0x3001 +#define GL_CLIP_PLANE2 0x3002 +#define GL_CLIP_PLANE3 0x3003 +#define GL_CLIP_PLANE4 0x3004 +#define GL_CLIP_PLANE5 0x3005 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_2_BYTES 0x1407 +#define GL_3_BYTES 0x1408 +#define GL_4_BYTES 0x1409 +#define GL_DOUBLE 0x140A +#define GL_NONE 0 +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_RIGHT 0x0403 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_LEFT 0x0406 +#define GL_RIGHT 0x0407 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_AUX0 0x0409 +#define GL_AUX1 0x040A +#define GL_AUX2 0x040B +#define GL_AUX3 0x040C +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_2D 0x0600 +#define GL_3D 0x0601 +#define GL_3D_COLOR 0x0602 +#define GL_3D_COLOR_TEXTURE 0x0603 +#define GL_4D_COLOR_TEXTURE 0x0604 +#define GL_PASS_THROUGH_TOKEN 0x0700 +#define GL_POINT_TOKEN 0x0701 +#define GL_LINE_TOKEN 0x0702 +#define GL_POLYGON_TOKEN 0x0703 +#define GL_BITMAP_TOKEN 0x0704 +#define GL_DRAW_PIXEL_TOKEN 0x0705 +#define GL_COPY_PIXEL_TOKEN 0x0706 +#define GL_LINE_RESET_TOKEN 0x0707 +#define GL_EXP 0x0800 +#define GL_EXP2 0x0801 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_COEFF 0x0A00 +#define GL_ORDER 0x0A01 +#define GL_DOMAIN 0x0A02 +#define GL_CURRENT_COLOR 0x0B00 +#define GL_CURRENT_INDEX 0x0B01 +#define GL_CURRENT_NORMAL 0x0B02 +#define GL_CURRENT_TEXTURE_COORDS 0x0B03 +#define GL_CURRENT_RASTER_COLOR 0x0B04 +#define GL_CURRENT_RASTER_INDEX 0x0B05 +#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06 +#define GL_CURRENT_RASTER_POSITION 0x0B07 +#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08 +#define GL_CURRENT_RASTER_DISTANCE 0x0B09 +#define GL_POINT_SMOOTH 0x0B10 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_LINE_STIPPLE 0x0B24 +#define GL_LINE_STIPPLE_PATTERN 0x0B25 +#define GL_LINE_STIPPLE_REPEAT 0x0B26 +#define GL_LIST_MODE 0x0B30 +#define GL_MAX_LIST_NESTING 0x0B31 +#define GL_LIST_BASE 0x0B32 +#define GL_LIST_INDEX 0x0B33 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_POLYGON_STIPPLE 0x0B42 +#define GL_EDGE_FLAG 0x0B43 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_LIGHTING 0x0B50 +#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 +#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 +#define GL_LIGHT_MODEL_AMBIENT 0x0B53 +#define GL_SHADE_MODEL 0x0B54 +#define GL_COLOR_MATERIAL_FACE 0x0B55 +#define GL_COLOR_MATERIAL_PARAMETER 0x0B56 +#define GL_COLOR_MATERIAL 0x0B57 +#define GL_FOG 0x0B60 +#define GL_FOG_INDEX 0x0B61 +#define GL_FOG_DENSITY 0x0B62 +#define GL_FOG_START 0x0B63 +#define GL_FOG_END 0x0B64 +#define GL_FOG_MODE 0x0B65 +#define GL_FOG_COLOR 0x0B66 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_ACCUM_CLEAR_VALUE 0x0B80 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_MATRIX_MODE 0x0BA0 +#define GL_NORMALIZE 0x0BA1 +#define GL_VIEWPORT 0x0BA2 +#define GL_MODELVIEW_STACK_DEPTH 0x0BA3 +#define GL_PROJECTION_STACK_DEPTH 0x0BA4 +#define GL_TEXTURE_STACK_DEPTH 0x0BA5 +#define GL_MODELVIEW_MATRIX 0x0BA6 +#define GL_PROJECTION_MATRIX 0x0BA7 +#define GL_TEXTURE_MATRIX 0x0BA8 +#define GL_ATTRIB_STACK_DEPTH 0x0BB0 +#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1 +#define GL_ALPHA_TEST 0x0BC0 +#define GL_ALPHA_TEST_FUNC 0x0BC1 +#define GL_ALPHA_TEST_REF 0x0BC2 +#define GL_DITHER 0x0BD0 +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLEND 0x0BE2 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_INDEX_LOGIC_OP 0x0BF1 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_AUX_BUFFERS 0x0C00 +#define GL_DRAW_BUFFER 0x0C01 +#define GL_READ_BUFFER 0x0C02 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_INDEX_CLEAR_VALUE 0x0C20 +#define GL_INDEX_WRITEMASK 0x0C21 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_INDEX_MODE 0x0C30 +#define GL_RGBA_MODE 0x0C31 +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_STEREO 0x0C33 +#define GL_RENDER_MODE 0x0C40 +#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 +#define GL_POINT_SMOOTH_HINT 0x0C51 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_FOG_HINT 0x0C54 +#define GL_TEXTURE_GEN_S 0x0C60 +#define GL_TEXTURE_GEN_T 0x0C61 +#define GL_TEXTURE_GEN_R 0x0C62 +#define GL_TEXTURE_GEN_Q 0x0C63 +#define GL_PIXEL_MAP_I_TO_I 0x0C70 +#define GL_PIXEL_MAP_S_TO_S 0x0C71 +#define GL_PIXEL_MAP_I_TO_R 0x0C72 +#define GL_PIXEL_MAP_I_TO_G 0x0C73 +#define GL_PIXEL_MAP_I_TO_B 0x0C74 +#define GL_PIXEL_MAP_I_TO_A 0x0C75 +#define GL_PIXEL_MAP_R_TO_R 0x0C76 +#define GL_PIXEL_MAP_G_TO_G 0x0C77 +#define GL_PIXEL_MAP_B_TO_B 0x0C78 +#define GL_PIXEL_MAP_A_TO_A 0x0C79 +#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0 +#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1 +#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2 +#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3 +#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4 +#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5 +#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6 +#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7 +#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8 +#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAP_COLOR 0x0D10 +#define GL_MAP_STENCIL 0x0D11 +#define GL_INDEX_SHIFT 0x0D12 +#define GL_INDEX_OFFSET 0x0D13 +#define GL_RED_SCALE 0x0D14 +#define GL_RED_BIAS 0x0D15 +#define GL_ZOOM_X 0x0D16 +#define GL_ZOOM_Y 0x0D17 +#define GL_GREEN_SCALE 0x0D18 +#define GL_GREEN_BIAS 0x0D19 +#define GL_BLUE_SCALE 0x0D1A +#define GL_BLUE_BIAS 0x0D1B +#define GL_ALPHA_SCALE 0x0D1C +#define GL_ALPHA_BIAS 0x0D1D +#define GL_DEPTH_SCALE 0x0D1E +#define GL_DEPTH_BIAS 0x0D1F +#define GL_MAX_EVAL_ORDER 0x0D30 +#define GL_MAX_LIGHTS 0x0D31 +#define GL_MAX_CLIP_PLANES 0x0D32 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_PIXEL_MAP_TABLE 0x0D34 +#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35 +#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 +#define GL_MAX_NAME_STACK_DEPTH 0x0D37 +#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 +#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_INDEX_BITS 0x0D51 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_ACCUM_RED_BITS 0x0D58 +#define GL_ACCUM_GREEN_BITS 0x0D59 +#define GL_ACCUM_BLUE_BITS 0x0D5A +#define GL_ACCUM_ALPHA_BITS 0x0D5B +#define GL_NAME_STACK_DEPTH 0x0D70 +#define GL_AUTO_NORMAL 0x0D80 +#define GL_MAP1_COLOR_4 0x0D90 +#define GL_MAP1_INDEX 0x0D91 +#define GL_MAP1_NORMAL 0x0D92 +#define GL_MAP1_TEXTURE_COORD_1 0x0D93 +#define GL_MAP1_TEXTURE_COORD_2 0x0D94 +#define GL_MAP1_TEXTURE_COORD_3 0x0D95 +#define GL_MAP1_TEXTURE_COORD_4 0x0D96 +#define GL_MAP1_VERTEX_3 0x0D97 +#define GL_MAP1_VERTEX_4 0x0D98 +#define GL_MAP2_COLOR_4 0x0DB0 +#define GL_MAP2_INDEX 0x0DB1 +#define GL_MAP2_NORMAL 0x0DB2 +#define GL_MAP2_TEXTURE_COORD_1 0x0DB3 +#define GL_MAP2_TEXTURE_COORD_2 0x0DB4 +#define GL_MAP2_TEXTURE_COORD_3 0x0DB5 +#define GL_MAP2_TEXTURE_COORD_4 0x0DB6 +#define GL_MAP2_VERTEX_3 0x0DB7 +#define GL_MAP2_VERTEX_4 0x0DB8 +#define GL_MAP1_GRID_DOMAIN 0x0DD0 +#define GL_MAP1_GRID_SEGMENTS 0x0DD1 +#define GL_MAP2_GRID_DOMAIN 0x0DD2 +#define GL_MAP2_GRID_SEGMENTS 0x0DD3 +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0 +#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1 +#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2 +#define GL_SELECTION_BUFFER_POINTER 0x0DF3 +#define GL_SELECTION_BUFFER_SIZE 0x0DF4 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_BORDER 0x1005 +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_LIGHT0 0x4000 +#define GL_LIGHT1 0x4001 +#define GL_LIGHT2 0x4002 +#define GL_LIGHT3 0x4003 +#define GL_LIGHT4 0x4004 +#define GL_LIGHT5 0x4005 +#define GL_LIGHT6 0x4006 +#define GL_LIGHT7 0x4007 +#define GL_AMBIENT 0x1200 +#define GL_DIFFUSE 0x1201 +#define GL_SPECULAR 0x1202 +#define GL_POSITION 0x1203 +#define GL_SPOT_DIRECTION 0x1204 +#define GL_SPOT_EXPONENT 0x1205 +#define GL_SPOT_CUTOFF 0x1206 +#define GL_CONSTANT_ATTENUATION 0x1207 +#define GL_LINEAR_ATTENUATION 0x1208 +#define GL_QUADRATIC_ATTENUATION 0x1209 +#define GL_COMPILE 0x1300 +#define GL_COMPILE_AND_EXECUTE 0x1301 +#define GL_CLEAR 0x1500 +#define GL_AND 0x1501 +#define GL_AND_REVERSE 0x1502 +#define GL_COPY 0x1503 +#define GL_AND_INVERTED 0x1504 +#define GL_NOOP 0x1505 +#define GL_XOR 0x1506 +#define GL_OR 0x1507 +#define GL_NOR 0x1508 +#define GL_EQUIV 0x1509 +#define GL_INVERT 0x150A +#define GL_OR_REVERSE 0x150B +#define GL_COPY_INVERTED 0x150C +#define GL_OR_INVERTED 0x150D +#define GL_NAND 0x150E +#define GL_SET 0x150F +#define GL_EMISSION 0x1600 +#define GL_SHININESS 0x1601 +#define GL_AMBIENT_AND_DIFFUSE 0x1602 +#define GL_COLOR_INDEXES 0x1603 +#define GL_MODELVIEW 0x1700 +#define GL_PROJECTION 0x1701 +#define GL_TEXTURE 0x1702 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_COLOR_INDEX 0x1900 +#define GL_STENCIL_INDEX 0x1901 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_BITMAP 0x1A00 +#define GL_POINT 0x1B00 +#define GL_LINE 0x1B01 +#define GL_FILL 0x1B02 +#define GL_RENDER 0x1C00 +#define GL_FEEDBACK 0x1C01 +#define GL_SELECT 0x1C02 +#define GL_FLAT 0x1D00 +#define GL_SMOOTH 0x1D01 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_S 0x2000 +#define GL_T 0x2001 +#define GL_R 0x2002 +#define GL_Q 0x2003 +#define GL_MODULATE 0x2100 +#define GL_DECAL 0x2101 +#define GL_TEXTURE_ENV_MODE 0x2200 +#define GL_TEXTURE_ENV_COLOR 0x2201 +#define GL_TEXTURE_ENV 0x2300 +#define GL_EYE_LINEAR 0x2400 +#define GL_OBJECT_LINEAR 0x2401 +#define GL_SPHERE_MAP 0x2402 +#define GL_TEXTURE_GEN_MODE 0x2500 +#define GL_OBJECT_PLANE 0x2501 +#define GL_EYE_PLANE 0x2502 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_CLAMP 0x2900 +#define GL_REPEAT 0x2901 +#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001 +#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002 +#define GL_CLIENT_ALL_ATTRIB_BITS 0xffffffff +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_ALPHA4 0x803B +#define GL_ALPHA8 0x803C +#define GL_ALPHA12 0x803D +#define GL_ALPHA16 0x803E +#define GL_LUMINANCE4 0x803F +#define GL_LUMINANCE8 0x8040 +#define GL_LUMINANCE12 0x8041 +#define GL_LUMINANCE16 0x8042 +#define GL_LUMINANCE4_ALPHA4 0x8043 +#define GL_LUMINANCE6_ALPHA2 0x8044 +#define GL_LUMINANCE8_ALPHA8 0x8045 +#define GL_LUMINANCE12_ALPHA4 0x8046 +#define GL_LUMINANCE12_ALPHA12 0x8047 +#define GL_LUMINANCE16_ALPHA16 0x8048 +#define GL_INTENSITY 0x8049 +#define GL_INTENSITY4 0x804A +#define GL_INTENSITY8 0x804B +#define GL_INTENSITY12 0x804C +#define GL_INTENSITY16 0x804D +#define GL_R3_G3_B2 0x2A10 +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB8 0x8051 +#define GL_RGB10 0x8052 +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGBA2 0x8055 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE 0x8061 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_TEXTURE_PRIORITY 0x8066 +#define GL_TEXTURE_RESIDENT 0x8067 +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_VERTEX_ARRAY 0x8074 +#define GL_NORMAL_ARRAY 0x8075 +#define GL_COLOR_ARRAY 0x8076 +#define GL_INDEX_ARRAY 0x8077 +#define GL_TEXTURE_COORD_ARRAY 0x8078 +#define GL_EDGE_FLAG_ARRAY 0x8079 +#define GL_VERTEX_ARRAY_SIZE 0x807A +#define GL_VERTEX_ARRAY_TYPE 0x807B +#define GL_VERTEX_ARRAY_STRIDE 0x807C +#define GL_NORMAL_ARRAY_TYPE 0x807E +#define GL_NORMAL_ARRAY_STRIDE 0x807F +#define GL_COLOR_ARRAY_SIZE 0x8081 +#define GL_COLOR_ARRAY_TYPE 0x8082 +#define GL_COLOR_ARRAY_STRIDE 0x8083 +#define GL_INDEX_ARRAY_TYPE 0x8085 +#define GL_INDEX_ARRAY_STRIDE 0x8086 +#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A +#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C +#define GL_VERTEX_ARRAY_POINTER 0x808E +#define GL_NORMAL_ARRAY_POINTER 0x808F +#define GL_COLOR_ARRAY_POINTER 0x8090 +#define GL_INDEX_ARRAY_POINTER 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093 +#define GL_V2F 0x2A20 +#define GL_V3F 0x2A21 +#define GL_C4UB_V2F 0x2A22 +#define GL_C4UB_V3F 0x2A23 +#define GL_C3F_V3F 0x2A24 +#define GL_N3F_V3F 0x2A25 +#define GL_C4F_N3F_V3F 0x2A26 +#define GL_T2F_V3F 0x2A27 +#define GL_T4F_V4F 0x2A28 +#define GL_T2F_C4UB_V3F 0x2A29 +#define GL_T2F_C3F_V3F 0x2A2A +#define GL_T2F_N3F_V3F 0x2A2B +#define GL_T2F_C4F_N3F_V3F 0x2A2C +#define GL_T4F_C4F_N3F_V4F 0x2A2D +#define GL_LOGIC_OP GL_INDEX_LOGIC_OP +#define GL_TEXTURE_COMPONENTS GL_TEXTURE_INTERNAL_FORMAT +#define GL_COLOR_INDEX1_EXT 0x80E2 +#define GL_COLOR_INDEX2_EXT 0x80E3 +#define GL_COLOR_INDEX4_EXT 0x80E4 +#define GL_COLOR_INDEX8_EXT 0x80E5 +#define GL_COLOR_INDEX12_EXT 0x80E6 +#define GL_COLOR_INDEX16_EXT 0x80E7 + +GLAPI void GLAPIENTRY glAccum (GLenum op, GLfloat value); +GLAPI void GLAPIENTRY glAlphaFunc (GLenum func, GLclampf ref); +GLAPI GLboolean GLAPIENTRY glAreTexturesResident (GLsizei n, const GLuint *textures, GLboolean *residences); +GLAPI void GLAPIENTRY glArrayElement (GLint i); +GLAPI void GLAPIENTRY glBegin (GLenum mode); +GLAPI void GLAPIENTRY glBindTexture (GLenum target, GLuint texture); +GLAPI void GLAPIENTRY glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); +GLAPI void GLAPIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GLAPI void GLAPIENTRY glCallList (GLuint list); +GLAPI void GLAPIENTRY glCallLists (GLsizei n, GLenum type, const GLvoid *lists); +GLAPI void GLAPIENTRY glClear (GLbitfield mask); +GLAPI void GLAPIENTRY glClearAccum (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI void GLAPIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +GLAPI void GLAPIENTRY glClearDepth (GLclampd depth); +GLAPI void GLAPIENTRY glClearIndex (GLfloat c); +GLAPI void GLAPIENTRY glClearStencil (GLint s); +GLAPI void GLAPIENTRY glClipPlane (GLenum plane, const GLdouble *equation); +GLAPI void GLAPIENTRY glColor3b (GLbyte red, GLbyte green, GLbyte blue); +GLAPI void GLAPIENTRY glColor3bv (const GLbyte *v); +GLAPI void GLAPIENTRY glColor3d (GLdouble red, GLdouble green, GLdouble blue); +GLAPI void GLAPIENTRY glColor3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glColor3f (GLfloat red, GLfloat green, GLfloat blue); +GLAPI void GLAPIENTRY glColor3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glColor3i (GLint red, GLint green, GLint blue); +GLAPI void GLAPIENTRY glColor3iv (const GLint *v); +GLAPI void GLAPIENTRY glColor3s (GLshort red, GLshort green, GLshort blue); +GLAPI void GLAPIENTRY glColor3sv (const GLshort *v); +GLAPI void GLAPIENTRY glColor3ub (GLubyte red, GLubyte green, GLubyte blue); +GLAPI void GLAPIENTRY glColor3ubv (const GLubyte *v); +GLAPI void GLAPIENTRY glColor3ui (GLuint red, GLuint green, GLuint blue); +GLAPI void GLAPIENTRY glColor3uiv (const GLuint *v); +GLAPI void GLAPIENTRY glColor3us (GLushort red, GLushort green, GLushort blue); +GLAPI void GLAPIENTRY glColor3usv (const GLushort *v); +GLAPI void GLAPIENTRY glColor4b (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); +GLAPI void GLAPIENTRY glColor4bv (const GLbyte *v); +GLAPI void GLAPIENTRY glColor4d (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); +GLAPI void GLAPIENTRY glColor4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI void GLAPIENTRY glColor4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glColor4i (GLint red, GLint green, GLint blue, GLint alpha); +GLAPI void GLAPIENTRY glColor4iv (const GLint *v); +GLAPI void GLAPIENTRY glColor4s (GLshort red, GLshort green, GLshort blue, GLshort alpha); +GLAPI void GLAPIENTRY glColor4sv (const GLshort *v); +GLAPI void GLAPIENTRY glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +GLAPI void GLAPIENTRY glColor4ubv (const GLubyte *v); +GLAPI void GLAPIENTRY glColor4ui (GLuint red, GLuint green, GLuint blue, GLuint alpha); +GLAPI void GLAPIENTRY glColor4uiv (const GLuint *v); +GLAPI void GLAPIENTRY glColor4us (GLushort red, GLushort green, GLushort blue, GLushort alpha); +GLAPI void GLAPIENTRY glColor4usv (const GLushort *v); +GLAPI void GLAPIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GLAPI void GLAPIENTRY glColorMaterial (GLenum face, GLenum mode); +GLAPI void GLAPIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); +GLAPI void GLAPIENTRY glCopyTexImage1D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); +GLAPI void GLAPIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI void GLAPIENTRY glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI void GLAPIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void GLAPIENTRY glCullFace (GLenum mode); +GLAPI void GLAPIENTRY glDeleteLists (GLuint list, GLsizei range); +GLAPI void GLAPIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); +GLAPI void GLAPIENTRY glDepthFunc (GLenum func); +GLAPI void GLAPIENTRY glDepthMask (GLboolean flag); +GLAPI void GLAPIENTRY glDepthRange (GLclampd zNear, GLclampd zFar); +GLAPI void GLAPIENTRY glDisable (GLenum cap); +GLAPI void GLAPIENTRY glDisableClientState (GLenum array); +GLAPI void GLAPIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GLAPI void GLAPIENTRY glDrawBuffer (GLenum mode); +GLAPI void GLAPIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +GLAPI void GLAPIENTRY glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glEdgeFlag (GLboolean flag); +GLAPI void GLAPIENTRY glEdgeFlagPointer (GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glEdgeFlagv (const GLboolean *flag); +GLAPI void GLAPIENTRY glEnable (GLenum cap); +GLAPI void GLAPIENTRY glEnableClientState (GLenum array); +GLAPI void GLAPIENTRY glEnd (void); +GLAPI void GLAPIENTRY glEndList (void); +GLAPI void GLAPIENTRY glEvalCoord1d (GLdouble u); +GLAPI void GLAPIENTRY glEvalCoord1dv (const GLdouble *u); +GLAPI void GLAPIENTRY glEvalCoord1f (GLfloat u); +GLAPI void GLAPIENTRY glEvalCoord1fv (const GLfloat *u); +GLAPI void GLAPIENTRY glEvalCoord2d (GLdouble u, GLdouble v); +GLAPI void GLAPIENTRY glEvalCoord2dv (const GLdouble *u); +GLAPI void GLAPIENTRY glEvalCoord2f (GLfloat u, GLfloat v); +GLAPI void GLAPIENTRY glEvalCoord2fv (const GLfloat *u); +GLAPI void GLAPIENTRY glEvalMesh1 (GLenum mode, GLint i1, GLint i2); +GLAPI void GLAPIENTRY glEvalMesh2 (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); +GLAPI void GLAPIENTRY glEvalPoint1 (GLint i); +GLAPI void GLAPIENTRY glEvalPoint2 (GLint i, GLint j); +GLAPI void GLAPIENTRY glFeedbackBuffer (GLsizei size, GLenum type, GLfloat *buffer); +GLAPI void GLAPIENTRY glFinish (void); +GLAPI void GLAPIENTRY glFlush (void); +GLAPI void GLAPIENTRY glFogf (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glFogfv (GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glFogi (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glFogiv (GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glFrontFace (GLenum mode); +GLAPI void GLAPIENTRY glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLAPI GLuint GLAPIENTRY glGenLists (GLsizei range); +GLAPI void GLAPIENTRY glGenTextures (GLsizei n, GLuint *textures); +GLAPI void GLAPIENTRY glGetBooleanv (GLenum pname, GLboolean *params); +GLAPI void GLAPIENTRY glGetClipPlane (GLenum plane, GLdouble *equation); +GLAPI void GLAPIENTRY glGetDoublev (GLenum pname, GLdouble *params); +GLAPI GLenum GLAPIENTRY glGetError (void); +GLAPI void GLAPIENTRY glGetFloatv (GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetIntegerv (GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetLightfv (GLenum light, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetLightiv (GLenum light, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetMapdv (GLenum target, GLenum query, GLdouble *v); +GLAPI void GLAPIENTRY glGetMapfv (GLenum target, GLenum query, GLfloat *v); +GLAPI void GLAPIENTRY glGetMapiv (GLenum target, GLenum query, GLint *v); +GLAPI void GLAPIENTRY glGetMaterialfv (GLenum face, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetMaterialiv (GLenum face, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetPixelMapfv (GLenum map, GLfloat *values); +GLAPI void GLAPIENTRY glGetPixelMapuiv (GLenum map, GLuint *values); +GLAPI void GLAPIENTRY glGetPixelMapusv (GLenum map, GLushort *values); +GLAPI void GLAPIENTRY glGetPointerv (GLenum pname, GLvoid* *params); +GLAPI void GLAPIENTRY glGetPolygonStipple (GLubyte *mask); +GLAPI const GLubyte * GLAPIENTRY glGetString (GLenum name); +GLAPI void GLAPIENTRY glGetTexEnvfv (GLenum target, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexEnviv (GLenum target, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetTexGendv (GLenum coord, GLenum pname, GLdouble *params); +GLAPI void GLAPIENTRY glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexGeniv (GLenum coord, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +GLAPI void GLAPIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glHint (GLenum target, GLenum mode); +GLAPI void GLAPIENTRY glIndexMask (GLuint mask); +GLAPI void GLAPIENTRY glIndexPointer (GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glIndexd (GLdouble c); +GLAPI void GLAPIENTRY glIndexdv (const GLdouble *c); +GLAPI void GLAPIENTRY glIndexf (GLfloat c); +GLAPI void GLAPIENTRY glIndexfv (const GLfloat *c); +GLAPI void GLAPIENTRY glIndexi (GLint c); +GLAPI void GLAPIENTRY glIndexiv (const GLint *c); +GLAPI void GLAPIENTRY glIndexs (GLshort c); +GLAPI void GLAPIENTRY glIndexsv (const GLshort *c); +GLAPI void GLAPIENTRY glIndexub (GLubyte c); +GLAPI void GLAPIENTRY glIndexubv (const GLubyte *c); +GLAPI void GLAPIENTRY glInitNames (void); +GLAPI void GLAPIENTRY glInterleavedArrays (GLenum format, GLsizei stride, const GLvoid *pointer); +GLAPI GLboolean GLAPIENTRY glIsEnabled (GLenum cap); +GLAPI GLboolean GLAPIENTRY glIsList (GLuint list); +GLAPI GLboolean GLAPIENTRY glIsTexture (GLuint texture); +GLAPI void GLAPIENTRY glLightModelf (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glLightModelfv (GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glLightModeli (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glLightModeliv (GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glLightf (GLenum light, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glLighti (GLenum light, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glLightiv (GLenum light, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glLineStipple (GLint factor, GLushort pattern); +GLAPI void GLAPIENTRY glLineWidth (GLfloat width); +GLAPI void GLAPIENTRY glListBase (GLuint base); +GLAPI void GLAPIENTRY glLoadIdentity (void); +GLAPI void GLAPIENTRY glLoadMatrixd (const GLdouble *m); +GLAPI void GLAPIENTRY glLoadMatrixf (const GLfloat *m); +GLAPI void GLAPIENTRY glLoadName (GLuint name); +GLAPI void GLAPIENTRY glLogicOp (GLenum opcode); +GLAPI void GLAPIENTRY glMap1d (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); +GLAPI void GLAPIENTRY glMap1f (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); +GLAPI void GLAPIENTRY glMap2d (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); +GLAPI void GLAPIENTRY glMap2f (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); +GLAPI void GLAPIENTRY glMapGrid1d (GLint un, GLdouble u1, GLdouble u2); +GLAPI void GLAPIENTRY glMapGrid1f (GLint un, GLfloat u1, GLfloat u2); +GLAPI void GLAPIENTRY glMapGrid2d (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); +GLAPI void GLAPIENTRY glMapGrid2f (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); +GLAPI void GLAPIENTRY glMaterialf (GLenum face, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glMateriali (GLenum face, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glMaterialiv (GLenum face, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glMatrixMode (GLenum mode); +GLAPI void GLAPIENTRY glMultMatrixd (const GLdouble *m); +GLAPI void GLAPIENTRY glMultMatrixf (const GLfloat *m); +GLAPI void GLAPIENTRY glNewList (GLuint list, GLenum mode); +GLAPI void GLAPIENTRY glNormal3b (GLbyte nx, GLbyte ny, GLbyte nz); +GLAPI void GLAPIENTRY glNormal3bv (const GLbyte *v); +GLAPI void GLAPIENTRY glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz); +GLAPI void GLAPIENTRY glNormal3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz); +GLAPI void GLAPIENTRY glNormal3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glNormal3i (GLint nx, GLint ny, GLint nz); +GLAPI void GLAPIENTRY glNormal3iv (const GLint *v); +GLAPI void GLAPIENTRY glNormal3s (GLshort nx, GLshort ny, GLshort nz); +GLAPI void GLAPIENTRY glNormal3sv (const GLshort *v); +GLAPI void GLAPIENTRY glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLAPI void GLAPIENTRY glPassThrough (GLfloat token); +GLAPI void GLAPIENTRY glPixelMapfv (GLenum map, GLsizei mapsize, const GLfloat *values); +GLAPI void GLAPIENTRY glPixelMapuiv (GLenum map, GLsizei mapsize, const GLuint *values); +GLAPI void GLAPIENTRY glPixelMapusv (GLenum map, GLsizei mapsize, const GLushort *values); +GLAPI void GLAPIENTRY glPixelStoref (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glPixelStorei (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glPixelTransferf (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glPixelTransferi (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glPixelZoom (GLfloat xfactor, GLfloat yfactor); +GLAPI void GLAPIENTRY glPointSize (GLfloat size); +GLAPI void GLAPIENTRY glPolygonMode (GLenum face, GLenum mode); +GLAPI void GLAPIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GLAPI void GLAPIENTRY glPolygonStipple (const GLubyte *mask); +GLAPI void GLAPIENTRY glPopAttrib (void); +GLAPI void GLAPIENTRY glPopClientAttrib (void); +GLAPI void GLAPIENTRY glPopMatrix (void); +GLAPI void GLAPIENTRY glPopName (void); +GLAPI void GLAPIENTRY glPrioritizeTextures (GLsizei n, const GLuint *textures, const GLclampf *priorities); +GLAPI void GLAPIENTRY glPushAttrib (GLbitfield mask); +GLAPI void GLAPIENTRY glPushClientAttrib (GLbitfield mask); +GLAPI void GLAPIENTRY glPushMatrix (void); +GLAPI void GLAPIENTRY glPushName (GLuint name); +GLAPI void GLAPIENTRY glRasterPos2d (GLdouble x, GLdouble y); +GLAPI void GLAPIENTRY glRasterPos2dv (const GLdouble *v); +GLAPI void GLAPIENTRY glRasterPos2f (GLfloat x, GLfloat y); +GLAPI void GLAPIENTRY glRasterPos2fv (const GLfloat *v); +GLAPI void GLAPIENTRY glRasterPos2i (GLint x, GLint y); +GLAPI void GLAPIENTRY glRasterPos2iv (const GLint *v); +GLAPI void GLAPIENTRY glRasterPos2s (GLshort x, GLshort y); +GLAPI void GLAPIENTRY glRasterPos2sv (const GLshort *v); +GLAPI void GLAPIENTRY glRasterPos3d (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glRasterPos3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glRasterPos3f (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glRasterPos3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glRasterPos3i (GLint x, GLint y, GLint z); +GLAPI void GLAPIENTRY glRasterPos3iv (const GLint *v); +GLAPI void GLAPIENTRY glRasterPos3s (GLshort x, GLshort y, GLshort z); +GLAPI void GLAPIENTRY glRasterPos3sv (const GLshort *v); +GLAPI void GLAPIENTRY glRasterPos4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void GLAPIENTRY glRasterPos4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glRasterPos4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void GLAPIENTRY glRasterPos4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glRasterPos4i (GLint x, GLint y, GLint z, GLint w); +GLAPI void GLAPIENTRY glRasterPos4iv (const GLint *v); +GLAPI void GLAPIENTRY glRasterPos4s (GLshort x, GLshort y, GLshort z, GLshort w); +GLAPI void GLAPIENTRY glRasterPos4sv (const GLshort *v); +GLAPI void GLAPIENTRY glReadBuffer (GLenum mode); +GLAPI void GLAPIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +GLAPI void GLAPIENTRY glRectd (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); +GLAPI void GLAPIENTRY glRectdv (const GLdouble *v1, const GLdouble *v2); +GLAPI void GLAPIENTRY glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); +GLAPI void GLAPIENTRY glRectfv (const GLfloat *v1, const GLfloat *v2); +GLAPI void GLAPIENTRY glRecti (GLint x1, GLint y1, GLint x2, GLint y2); +GLAPI void GLAPIENTRY glRectiv (const GLint *v1, const GLint *v2); +GLAPI void GLAPIENTRY glRects (GLshort x1, GLshort y1, GLshort x2, GLshort y2); +GLAPI void GLAPIENTRY glRectsv (const GLshort *v1, const GLshort *v2); +GLAPI GLint GLAPIENTRY glRenderMode (GLenum mode); +GLAPI void GLAPIENTRY glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glScaled (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void GLAPIENTRY glSelectBuffer (GLsizei size, GLuint *buffer); +GLAPI void GLAPIENTRY glShadeModel (GLenum mode); +GLAPI void GLAPIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GLAPI void GLAPIENTRY glStencilMask (GLuint mask); +GLAPI void GLAPIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GLAPI void GLAPIENTRY glTexCoord1d (GLdouble s); +GLAPI void GLAPIENTRY glTexCoord1dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord1f (GLfloat s); +GLAPI void GLAPIENTRY glTexCoord1fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord1i (GLint s); +GLAPI void GLAPIENTRY glTexCoord1iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord1s (GLshort s); +GLAPI void GLAPIENTRY glTexCoord1sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoord2d (GLdouble s, GLdouble t); +GLAPI void GLAPIENTRY glTexCoord2dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord2f (GLfloat s, GLfloat t); +GLAPI void GLAPIENTRY glTexCoord2fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord2i (GLint s, GLint t); +GLAPI void GLAPIENTRY glTexCoord2iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord2s (GLshort s, GLshort t); +GLAPI void GLAPIENTRY glTexCoord2sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoord3d (GLdouble s, GLdouble t, GLdouble r); +GLAPI void GLAPIENTRY glTexCoord3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord3f (GLfloat s, GLfloat t, GLfloat r); +GLAPI void GLAPIENTRY glTexCoord3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord3i (GLint s, GLint t, GLint r); +GLAPI void GLAPIENTRY glTexCoord3iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord3s (GLshort s, GLshort t, GLshort r); +GLAPI void GLAPIENTRY glTexCoord3sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoord4d (GLdouble s, GLdouble t, GLdouble r, GLdouble q); +GLAPI void GLAPIENTRY glTexCoord4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q); +GLAPI void GLAPIENTRY glTexCoord4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord4i (GLint s, GLint t, GLint r, GLint q); +GLAPI void GLAPIENTRY glTexCoord4iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord4s (GLshort s, GLshort t, GLshort r, GLshort q); +GLAPI void GLAPIENTRY glTexCoord4sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glTexEnvf (GLenum target, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glTexEnvi (GLenum target, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glTexEnviv (GLenum target, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glTexGend (GLenum coord, GLenum pname, GLdouble param); +GLAPI void GLAPIENTRY glTexGendv (GLenum coord, GLenum pname, const GLdouble *params); +GLAPI void GLAPIENTRY glTexGenf (GLenum coord, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glTexGeni (GLenum coord, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glTexGeniv (GLenum coord, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTranslated (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glVertex2d (GLdouble x, GLdouble y); +GLAPI void GLAPIENTRY glVertex2dv (const GLdouble *v); +GLAPI void GLAPIENTRY glVertex2f (GLfloat x, GLfloat y); +GLAPI void GLAPIENTRY glVertex2fv (const GLfloat *v); +GLAPI void GLAPIENTRY glVertex2i (GLint x, GLint y); +GLAPI void GLAPIENTRY glVertex2iv (const GLint *v); +GLAPI void GLAPIENTRY glVertex2s (GLshort x, GLshort y); +GLAPI void GLAPIENTRY glVertex2sv (const GLshort *v); +GLAPI void GLAPIENTRY glVertex3d (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glVertex3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glVertex3f (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glVertex3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glVertex3i (GLint x, GLint y, GLint z); +GLAPI void GLAPIENTRY glVertex3iv (const GLint *v); +GLAPI void GLAPIENTRY glVertex3s (GLshort x, GLshort y, GLshort z); +GLAPI void GLAPIENTRY glVertex3sv (const GLshort *v); +GLAPI void GLAPIENTRY glVertex4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void GLAPIENTRY glVertex4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void GLAPIENTRY glVertex4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glVertex4i (GLint x, GLint y, GLint z, GLint w); +GLAPI void GLAPIENTRY glVertex4iv (const GLint *v); +GLAPI void GLAPIENTRY glVertex4s (GLshort x, GLshort y, GLshort z, GLshort w); +GLAPI void GLAPIENTRY glVertex4sv (const GLshort *v); +GLAPI void GLAPIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); + +#define GLEW_VERSION_1_1 GLEW_GET_VAR(__GLEW_VERSION_1_1) + +#endif /* GL_VERSION_1_1 */ + +/* ---------------------------------- GLU ---------------------------------- */ + +/* this is where we can safely include GLU */ +#if defined(__APPLE__) && defined(__MACH__) +#include +#else +#include +#endif + +/* ----------------------------- GL_VERSION_1_2 ---------------------------- */ + +#ifndef GL_VERSION_1_2 +#define GL_VERSION_1_2 1 + +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_RESCALE_NORMAL 0x803A +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 +#define GL_SINGLE_COLOR 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR 0x81FA +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E + +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); + +#define glCopyTexSubImage3D GLEW_GET_FUN(__glewCopyTexSubImage3D) +#define glDrawRangeElements GLEW_GET_FUN(__glewDrawRangeElements) +#define glTexImage3D GLEW_GET_FUN(__glewTexImage3D) +#define glTexSubImage3D GLEW_GET_FUN(__glewTexSubImage3D) + +#define GLEW_VERSION_1_2 GLEW_GET_VAR(__GLEW_VERSION_1_2) + +#endif /* GL_VERSION_1_2 */ + +/* ----------------------------- GL_VERSION_1_3 ---------------------------- */ + +#ifndef GL_VERSION_1_3 +#define GL_VERSION_1_3 1 + +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 +#define GL_MAX_TEXTURE_UNITS 0x84E2 +#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 +#define GL_SUBTRACT 0x84E7 +#define GL_COMPRESSED_ALPHA 0x84E9 +#define GL_COMPRESSED_LUMINANCE 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB +#define GL_COMPRESSED_INTENSITY 0x84EC +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_NORMAL_MAP 0x8511 +#define GL_REFLECTION_MAP 0x8512 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_COMBINE 0x8570 +#define GL_COMBINE_RGB 0x8571 +#define GL_COMBINE_ALPHA 0x8572 +#define GL_RGB_SCALE 0x8573 +#define GL_ADD_SIGNED 0x8574 +#define GL_INTERPOLATE 0x8575 +#define GL_CONSTANT 0x8576 +#define GL_PRIMARY_COLOR 0x8577 +#define GL_PREVIOUS 0x8578 +#define GL_SOURCE0_RGB 0x8580 +#define GL_SOURCE1_RGB 0x8581 +#define GL_SOURCE2_RGB 0x8582 +#define GL_SOURCE0_ALPHA 0x8588 +#define GL_SOURCE1_ALPHA 0x8589 +#define GL_SOURCE2_ALPHA 0x858A +#define GL_OPERAND0_RGB 0x8590 +#define GL_OPERAND1_RGB 0x8591 +#define GL_OPERAND2_RGB 0x8592 +#define GL_OPERAND0_ALPHA 0x8598 +#define GL_OPERAND1_ALPHA 0x8599 +#define GL_OPERAND2_ALPHA 0x859A +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_DOT3_RGB 0x86AE +#define GL_DOT3_RGBA 0x86AF +#define GL_MULTISAMPLE_BIT 0x20000000 + +typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint lod, GLvoid *img); +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat m[16]); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert); + +#define glActiveTexture GLEW_GET_FUN(__glewActiveTexture) +#define glClientActiveTexture GLEW_GET_FUN(__glewClientActiveTexture) +#define glCompressedTexImage1D GLEW_GET_FUN(__glewCompressedTexImage1D) +#define glCompressedTexImage2D GLEW_GET_FUN(__glewCompressedTexImage2D) +#define glCompressedTexImage3D GLEW_GET_FUN(__glewCompressedTexImage3D) +#define glCompressedTexSubImage1D GLEW_GET_FUN(__glewCompressedTexSubImage1D) +#define glCompressedTexSubImage2D GLEW_GET_FUN(__glewCompressedTexSubImage2D) +#define glCompressedTexSubImage3D GLEW_GET_FUN(__glewCompressedTexSubImage3D) +#define glGetCompressedTexImage GLEW_GET_FUN(__glewGetCompressedTexImage) +#define glLoadTransposeMatrixd GLEW_GET_FUN(__glewLoadTransposeMatrixd) +#define glLoadTransposeMatrixf GLEW_GET_FUN(__glewLoadTransposeMatrixf) +#define glMultTransposeMatrixd GLEW_GET_FUN(__glewMultTransposeMatrixd) +#define glMultTransposeMatrixf GLEW_GET_FUN(__glewMultTransposeMatrixf) +#define glMultiTexCoord1d GLEW_GET_FUN(__glewMultiTexCoord1d) +#define glMultiTexCoord1dv GLEW_GET_FUN(__glewMultiTexCoord1dv) +#define glMultiTexCoord1f GLEW_GET_FUN(__glewMultiTexCoord1f) +#define glMultiTexCoord1fv GLEW_GET_FUN(__glewMultiTexCoord1fv) +#define glMultiTexCoord1i GLEW_GET_FUN(__glewMultiTexCoord1i) +#define glMultiTexCoord1iv GLEW_GET_FUN(__glewMultiTexCoord1iv) +#define glMultiTexCoord1s GLEW_GET_FUN(__glewMultiTexCoord1s) +#define glMultiTexCoord1sv GLEW_GET_FUN(__glewMultiTexCoord1sv) +#define glMultiTexCoord2d GLEW_GET_FUN(__glewMultiTexCoord2d) +#define glMultiTexCoord2dv GLEW_GET_FUN(__glewMultiTexCoord2dv) +#define glMultiTexCoord2f GLEW_GET_FUN(__glewMultiTexCoord2f) +#define glMultiTexCoord2fv GLEW_GET_FUN(__glewMultiTexCoord2fv) +#define glMultiTexCoord2i GLEW_GET_FUN(__glewMultiTexCoord2i) +#define glMultiTexCoord2iv GLEW_GET_FUN(__glewMultiTexCoord2iv) +#define glMultiTexCoord2s GLEW_GET_FUN(__glewMultiTexCoord2s) +#define glMultiTexCoord2sv GLEW_GET_FUN(__glewMultiTexCoord2sv) +#define glMultiTexCoord3d GLEW_GET_FUN(__glewMultiTexCoord3d) +#define glMultiTexCoord3dv GLEW_GET_FUN(__glewMultiTexCoord3dv) +#define glMultiTexCoord3f GLEW_GET_FUN(__glewMultiTexCoord3f) +#define glMultiTexCoord3fv GLEW_GET_FUN(__glewMultiTexCoord3fv) +#define glMultiTexCoord3i GLEW_GET_FUN(__glewMultiTexCoord3i) +#define glMultiTexCoord3iv GLEW_GET_FUN(__glewMultiTexCoord3iv) +#define glMultiTexCoord3s GLEW_GET_FUN(__glewMultiTexCoord3s) +#define glMultiTexCoord3sv GLEW_GET_FUN(__glewMultiTexCoord3sv) +#define glMultiTexCoord4d GLEW_GET_FUN(__glewMultiTexCoord4d) +#define glMultiTexCoord4dv GLEW_GET_FUN(__glewMultiTexCoord4dv) +#define glMultiTexCoord4f GLEW_GET_FUN(__glewMultiTexCoord4f) +#define glMultiTexCoord4fv GLEW_GET_FUN(__glewMultiTexCoord4fv) +#define glMultiTexCoord4i GLEW_GET_FUN(__glewMultiTexCoord4i) +#define glMultiTexCoord4iv GLEW_GET_FUN(__glewMultiTexCoord4iv) +#define glMultiTexCoord4s GLEW_GET_FUN(__glewMultiTexCoord4s) +#define glMultiTexCoord4sv GLEW_GET_FUN(__glewMultiTexCoord4sv) +#define glSampleCoverage GLEW_GET_FUN(__glewSampleCoverage) + +#define GLEW_VERSION_1_3 GLEW_GET_VAR(__GLEW_VERSION_1_3) + +#endif /* GL_VERSION_1_3 */ + +/* ----------------------------- GL_VERSION_1_4 ---------------------------- */ + +#ifndef GL_VERSION_1_4 +#define GL_VERSION_1_4 1 + +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_POINT_SIZE_MIN 0x8126 +#define GL_POINT_SIZE_MAX 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION 0x8129 +#define GL_GENERATE_MIPMAP 0x8191 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_FOG_COORDINATE_SOURCE 0x8450 +#define GL_FOG_COORDINATE 0x8451 +#define GL_FRAGMENT_DEPTH 0x8452 +#define GL_CURRENT_FOG_COORDINATE 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 +#define GL_FOG_COORDINATE_ARRAY 0x8457 +#define GL_COLOR_SUM 0x8458 +#define GL_CURRENT_SECONDARY_COLOR 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D +#define GL_SECONDARY_COLOR_ARRAY 0x845E +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_FILTER_CONTROL 0x8500 +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_DEPTH_TEXTURE_MODE 0x884B +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_COMPARE_R_TO_TEXTURE 0x884E + +typedef void (GLAPIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDPROC) (GLdouble coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDVPROC) (const GLdouble *coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFPROC) (GLfloat coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFVPROC) (const GLfloat *coord); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVPROC) (GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVPROC) (GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVPROC) (const GLdouble *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVPROC) (const GLfloat *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IPROC) (GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVPROC) (const GLint *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVPROC) (const GLshort *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVPROC) (const GLdouble *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVPROC) (const GLfloat *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVPROC) (const GLint *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVPROC) (const GLshort *p); + +#define glBlendColor GLEW_GET_FUN(__glewBlendColor) +#define glBlendEquation GLEW_GET_FUN(__glewBlendEquation) +#define glBlendFuncSeparate GLEW_GET_FUN(__glewBlendFuncSeparate) +#define glFogCoordPointer GLEW_GET_FUN(__glewFogCoordPointer) +#define glFogCoordd GLEW_GET_FUN(__glewFogCoordd) +#define glFogCoorddv GLEW_GET_FUN(__glewFogCoorddv) +#define glFogCoordf GLEW_GET_FUN(__glewFogCoordf) +#define glFogCoordfv GLEW_GET_FUN(__glewFogCoordfv) +#define glMultiDrawArrays GLEW_GET_FUN(__glewMultiDrawArrays) +#define glMultiDrawElements GLEW_GET_FUN(__glewMultiDrawElements) +#define glPointParameterf GLEW_GET_FUN(__glewPointParameterf) +#define glPointParameterfv GLEW_GET_FUN(__glewPointParameterfv) +#define glPointParameteri GLEW_GET_FUN(__glewPointParameteri) +#define glPointParameteriv GLEW_GET_FUN(__glewPointParameteriv) +#define glSecondaryColor3b GLEW_GET_FUN(__glewSecondaryColor3b) +#define glSecondaryColor3bv GLEW_GET_FUN(__glewSecondaryColor3bv) +#define glSecondaryColor3d GLEW_GET_FUN(__glewSecondaryColor3d) +#define glSecondaryColor3dv GLEW_GET_FUN(__glewSecondaryColor3dv) +#define glSecondaryColor3f GLEW_GET_FUN(__glewSecondaryColor3f) +#define glSecondaryColor3fv GLEW_GET_FUN(__glewSecondaryColor3fv) +#define glSecondaryColor3i GLEW_GET_FUN(__glewSecondaryColor3i) +#define glSecondaryColor3iv GLEW_GET_FUN(__glewSecondaryColor3iv) +#define glSecondaryColor3s GLEW_GET_FUN(__glewSecondaryColor3s) +#define glSecondaryColor3sv GLEW_GET_FUN(__glewSecondaryColor3sv) +#define glSecondaryColor3ub GLEW_GET_FUN(__glewSecondaryColor3ub) +#define glSecondaryColor3ubv GLEW_GET_FUN(__glewSecondaryColor3ubv) +#define glSecondaryColor3ui GLEW_GET_FUN(__glewSecondaryColor3ui) +#define glSecondaryColor3uiv GLEW_GET_FUN(__glewSecondaryColor3uiv) +#define glSecondaryColor3us GLEW_GET_FUN(__glewSecondaryColor3us) +#define glSecondaryColor3usv GLEW_GET_FUN(__glewSecondaryColor3usv) +#define glSecondaryColorPointer GLEW_GET_FUN(__glewSecondaryColorPointer) +#define glWindowPos2d GLEW_GET_FUN(__glewWindowPos2d) +#define glWindowPos2dv GLEW_GET_FUN(__glewWindowPos2dv) +#define glWindowPos2f GLEW_GET_FUN(__glewWindowPos2f) +#define glWindowPos2fv GLEW_GET_FUN(__glewWindowPos2fv) +#define glWindowPos2i GLEW_GET_FUN(__glewWindowPos2i) +#define glWindowPos2iv GLEW_GET_FUN(__glewWindowPos2iv) +#define glWindowPos2s GLEW_GET_FUN(__glewWindowPos2s) +#define glWindowPos2sv GLEW_GET_FUN(__glewWindowPos2sv) +#define glWindowPos3d GLEW_GET_FUN(__glewWindowPos3d) +#define glWindowPos3dv GLEW_GET_FUN(__glewWindowPos3dv) +#define glWindowPos3f GLEW_GET_FUN(__glewWindowPos3f) +#define glWindowPos3fv GLEW_GET_FUN(__glewWindowPos3fv) +#define glWindowPos3i GLEW_GET_FUN(__glewWindowPos3i) +#define glWindowPos3iv GLEW_GET_FUN(__glewWindowPos3iv) +#define glWindowPos3s GLEW_GET_FUN(__glewWindowPos3s) +#define glWindowPos3sv GLEW_GET_FUN(__glewWindowPos3sv) + +#define GLEW_VERSION_1_4 GLEW_GET_VAR(__GLEW_VERSION_1_4) + +#endif /* GL_VERSION_1_4 */ + +/* ----------------------------- GL_VERSION_1_5 ---------------------------- */ + +#ifndef GL_VERSION_1_5 +#define GL_VERSION_1_5 1 + +#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE +#define GL_FOG_COORD GL_FOG_COORDINATE +#define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY +#define GL_SRC0_RGB GL_SOURCE0_RGB +#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER +#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE +#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA +#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE +#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE +#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA +#define GL_SRC1_RGB GL_SOURCE1_RGB +#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING +#define GL_SRC2_ALPHA GL_SOURCE2_ALPHA +#define GL_SRC2_RGB GL_SOURCE2_RGB +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_SAMPLES_PASSED 0x8914 + +typedef ptrdiff_t GLsizeiptr; +typedef ptrdiff_t GLintptr; + +typedef void (GLAPIENTRY * PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLENDQUERYPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLGENQUERIESPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid** params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERPROC) (GLuint buffer); +typedef GLboolean (GLAPIENTRY * PFNGLISQUERYPROC) (GLuint id); +typedef GLvoid* (GLAPIENTRY * PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); +typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERPROC) (GLenum target); + +#define glBeginQuery GLEW_GET_FUN(__glewBeginQuery) +#define glBindBuffer GLEW_GET_FUN(__glewBindBuffer) +#define glBufferData GLEW_GET_FUN(__glewBufferData) +#define glBufferSubData GLEW_GET_FUN(__glewBufferSubData) +#define glDeleteBuffers GLEW_GET_FUN(__glewDeleteBuffers) +#define glDeleteQueries GLEW_GET_FUN(__glewDeleteQueries) +#define glEndQuery GLEW_GET_FUN(__glewEndQuery) +#define glGenBuffers GLEW_GET_FUN(__glewGenBuffers) +#define glGenQueries GLEW_GET_FUN(__glewGenQueries) +#define glGetBufferParameteriv GLEW_GET_FUN(__glewGetBufferParameteriv) +#define glGetBufferPointerv GLEW_GET_FUN(__glewGetBufferPointerv) +#define glGetBufferSubData GLEW_GET_FUN(__glewGetBufferSubData) +#define glGetQueryObjectiv GLEW_GET_FUN(__glewGetQueryObjectiv) +#define glGetQueryObjectuiv GLEW_GET_FUN(__glewGetQueryObjectuiv) +#define glGetQueryiv GLEW_GET_FUN(__glewGetQueryiv) +#define glIsBuffer GLEW_GET_FUN(__glewIsBuffer) +#define glIsQuery GLEW_GET_FUN(__glewIsQuery) +#define glMapBuffer GLEW_GET_FUN(__glewMapBuffer) +#define glUnmapBuffer GLEW_GET_FUN(__glewUnmapBuffer) + +#define GLEW_VERSION_1_5 GLEW_GET_VAR(__GLEW_VERSION_1_5) + +#endif /* GL_VERSION_1_5 */ + +/* ----------------------------- GL_VERSION_2_0 ---------------------------- */ + +#ifndef GL_VERSION_2_0 +#define GL_VERSION_2_0 1 + +#define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_POINT_SPRITE 0x8861 +#define GL_COORD_REPLACE 0x8862 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_MAX_TEXTURE_COORDS 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_SHADER_TYPE 0x8B4F +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_DELETE_STATUS 0x8B80 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 + +typedef char GLchar; + +typedef void (GLAPIENTRY * PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar* name); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum, GLenum); +typedef void (GLAPIENTRY * PFNGLCOMPILESHADERPROC) (GLuint shader); +typedef GLuint (GLAPIENTRY * PFNGLCREATEPROGRAMPROC) (void); +typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROC) (GLenum type); +typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLDELETESHADERPROC) (GLuint shader); +typedef void (GLAPIENTRY * PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint); +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum* bufs); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint); +typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders); +typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint* param); +typedef void (GLAPIENTRY * PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog); +typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEPROC) (GLint obj, GLsizei maxLength, GLsizei* length, GLchar* source); +typedef void (GLAPIENTRY * PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint* param); +typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint, GLenum, GLvoid*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVPROC) (GLuint, GLenum, GLdouble*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVPROC) (GLuint, GLenum, GLfloat*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVPROC) (GLuint, GLenum, GLint*); +typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPROC) (GLuint program); +typedef GLboolean (GLAPIENTRY * PFNGLISSHADERPROC) (GLuint shader); +typedef void (GLAPIENTRY * PFNGLLINKPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar** strings, const GLint* lengths); +typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); +typedef void (GLAPIENTRY * PFNGLSTENCILMASKSEPARATEPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IPROC) (GLint location, GLint v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUSEPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer); + +#define glAttachShader GLEW_GET_FUN(__glewAttachShader) +#define glBindAttribLocation GLEW_GET_FUN(__glewBindAttribLocation) +#define glBlendEquationSeparate GLEW_GET_FUN(__glewBlendEquationSeparate) +#define glCompileShader GLEW_GET_FUN(__glewCompileShader) +#define glCreateProgram GLEW_GET_FUN(__glewCreateProgram) +#define glCreateShader GLEW_GET_FUN(__glewCreateShader) +#define glDeleteProgram GLEW_GET_FUN(__glewDeleteProgram) +#define glDeleteShader GLEW_GET_FUN(__glewDeleteShader) +#define glDetachShader GLEW_GET_FUN(__glewDetachShader) +#define glDisableVertexAttribArray GLEW_GET_FUN(__glewDisableVertexAttribArray) +#define glDrawBuffers GLEW_GET_FUN(__glewDrawBuffers) +#define glEnableVertexAttribArray GLEW_GET_FUN(__glewEnableVertexAttribArray) +#define glGetActiveAttrib GLEW_GET_FUN(__glewGetActiveAttrib) +#define glGetActiveUniform GLEW_GET_FUN(__glewGetActiveUniform) +#define glGetAttachedShaders GLEW_GET_FUN(__glewGetAttachedShaders) +#define glGetAttribLocation GLEW_GET_FUN(__glewGetAttribLocation) +#define glGetProgramInfoLog GLEW_GET_FUN(__glewGetProgramInfoLog) +#define glGetProgramiv GLEW_GET_FUN(__glewGetProgramiv) +#define glGetShaderInfoLog GLEW_GET_FUN(__glewGetShaderInfoLog) +#define glGetShaderSource GLEW_GET_FUN(__glewGetShaderSource) +#define glGetShaderiv GLEW_GET_FUN(__glewGetShaderiv) +#define glGetUniformLocation GLEW_GET_FUN(__glewGetUniformLocation) +#define glGetUniformfv GLEW_GET_FUN(__glewGetUniformfv) +#define glGetUniformiv GLEW_GET_FUN(__glewGetUniformiv) +#define glGetVertexAttribPointerv GLEW_GET_FUN(__glewGetVertexAttribPointerv) +#define glGetVertexAttribdv GLEW_GET_FUN(__glewGetVertexAttribdv) +#define glGetVertexAttribfv GLEW_GET_FUN(__glewGetVertexAttribfv) +#define glGetVertexAttribiv GLEW_GET_FUN(__glewGetVertexAttribiv) +#define glIsProgram GLEW_GET_FUN(__glewIsProgram) +#define glIsShader GLEW_GET_FUN(__glewIsShader) +#define glLinkProgram GLEW_GET_FUN(__glewLinkProgram) +#define glShaderSource GLEW_GET_FUN(__glewShaderSource) +#define glStencilFuncSeparate GLEW_GET_FUN(__glewStencilFuncSeparate) +#define glStencilMaskSeparate GLEW_GET_FUN(__glewStencilMaskSeparate) +#define glStencilOpSeparate GLEW_GET_FUN(__glewStencilOpSeparate) +#define glUniform1f GLEW_GET_FUN(__glewUniform1f) +#define glUniform1fv GLEW_GET_FUN(__glewUniform1fv) +#define glUniform1i GLEW_GET_FUN(__glewUniform1i) +#define glUniform1iv GLEW_GET_FUN(__glewUniform1iv) +#define glUniform2f GLEW_GET_FUN(__glewUniform2f) +#define glUniform2fv GLEW_GET_FUN(__glewUniform2fv) +#define glUniform2i GLEW_GET_FUN(__glewUniform2i) +#define glUniform2iv GLEW_GET_FUN(__glewUniform2iv) +#define glUniform3f GLEW_GET_FUN(__glewUniform3f) +#define glUniform3fv GLEW_GET_FUN(__glewUniform3fv) +#define glUniform3i GLEW_GET_FUN(__glewUniform3i) +#define glUniform3iv GLEW_GET_FUN(__glewUniform3iv) +#define glUniform4f GLEW_GET_FUN(__glewUniform4f) +#define glUniform4fv GLEW_GET_FUN(__glewUniform4fv) +#define glUniform4i GLEW_GET_FUN(__glewUniform4i) +#define glUniform4iv GLEW_GET_FUN(__glewUniform4iv) +#define glUniformMatrix2fv GLEW_GET_FUN(__glewUniformMatrix2fv) +#define glUniformMatrix3fv GLEW_GET_FUN(__glewUniformMatrix3fv) +#define glUniformMatrix4fv GLEW_GET_FUN(__glewUniformMatrix4fv) +#define glUseProgram GLEW_GET_FUN(__glewUseProgram) +#define glValidateProgram GLEW_GET_FUN(__glewValidateProgram) +#define glVertexAttrib1d GLEW_GET_FUN(__glewVertexAttrib1d) +#define glVertexAttrib1dv GLEW_GET_FUN(__glewVertexAttrib1dv) +#define glVertexAttrib1f GLEW_GET_FUN(__glewVertexAttrib1f) +#define glVertexAttrib1fv GLEW_GET_FUN(__glewVertexAttrib1fv) +#define glVertexAttrib1s GLEW_GET_FUN(__glewVertexAttrib1s) +#define glVertexAttrib1sv GLEW_GET_FUN(__glewVertexAttrib1sv) +#define glVertexAttrib2d GLEW_GET_FUN(__glewVertexAttrib2d) +#define glVertexAttrib2dv GLEW_GET_FUN(__glewVertexAttrib2dv) +#define glVertexAttrib2f GLEW_GET_FUN(__glewVertexAttrib2f) +#define glVertexAttrib2fv GLEW_GET_FUN(__glewVertexAttrib2fv) +#define glVertexAttrib2s GLEW_GET_FUN(__glewVertexAttrib2s) +#define glVertexAttrib2sv GLEW_GET_FUN(__glewVertexAttrib2sv) +#define glVertexAttrib3d GLEW_GET_FUN(__glewVertexAttrib3d) +#define glVertexAttrib3dv GLEW_GET_FUN(__glewVertexAttrib3dv) +#define glVertexAttrib3f GLEW_GET_FUN(__glewVertexAttrib3f) +#define glVertexAttrib3fv GLEW_GET_FUN(__glewVertexAttrib3fv) +#define glVertexAttrib3s GLEW_GET_FUN(__glewVertexAttrib3s) +#define glVertexAttrib3sv GLEW_GET_FUN(__glewVertexAttrib3sv) +#define glVertexAttrib4Nbv GLEW_GET_FUN(__glewVertexAttrib4Nbv) +#define glVertexAttrib4Niv GLEW_GET_FUN(__glewVertexAttrib4Niv) +#define glVertexAttrib4Nsv GLEW_GET_FUN(__glewVertexAttrib4Nsv) +#define glVertexAttrib4Nub GLEW_GET_FUN(__glewVertexAttrib4Nub) +#define glVertexAttrib4Nubv GLEW_GET_FUN(__glewVertexAttrib4Nubv) +#define glVertexAttrib4Nuiv GLEW_GET_FUN(__glewVertexAttrib4Nuiv) +#define glVertexAttrib4Nusv GLEW_GET_FUN(__glewVertexAttrib4Nusv) +#define glVertexAttrib4bv GLEW_GET_FUN(__glewVertexAttrib4bv) +#define glVertexAttrib4d GLEW_GET_FUN(__glewVertexAttrib4d) +#define glVertexAttrib4dv GLEW_GET_FUN(__glewVertexAttrib4dv) +#define glVertexAttrib4f GLEW_GET_FUN(__glewVertexAttrib4f) +#define glVertexAttrib4fv GLEW_GET_FUN(__glewVertexAttrib4fv) +#define glVertexAttrib4iv GLEW_GET_FUN(__glewVertexAttrib4iv) +#define glVertexAttrib4s GLEW_GET_FUN(__glewVertexAttrib4s) +#define glVertexAttrib4sv GLEW_GET_FUN(__glewVertexAttrib4sv) +#define glVertexAttrib4ubv GLEW_GET_FUN(__glewVertexAttrib4ubv) +#define glVertexAttrib4uiv GLEW_GET_FUN(__glewVertexAttrib4uiv) +#define glVertexAttrib4usv GLEW_GET_FUN(__glewVertexAttrib4usv) +#define glVertexAttribPointer GLEW_GET_FUN(__glewVertexAttribPointer) + +#define GLEW_VERSION_2_0 GLEW_GET_VAR(__GLEW_VERSION_2_0) + +#endif /* GL_VERSION_2_0 */ + +/* ----------------------------- GL_VERSION_2_1 ---------------------------- */ + +#ifndef GL_VERSION_2_1 +#define GL_VERSION_2_1 1 + +#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB_ALPHA 0x8C42 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_SLUMINANCE_ALPHA 0x8C44 +#define GL_SLUMINANCE8_ALPHA8 0x8C45 +#define GL_SLUMINANCE 0x8C46 +#define GL_SLUMINANCE8 0x8C47 +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 +#define GL_COMPRESSED_SLUMINANCE 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B + +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + +#define glUniformMatrix2x3fv GLEW_GET_FUN(__glewUniformMatrix2x3fv) +#define glUniformMatrix2x4fv GLEW_GET_FUN(__glewUniformMatrix2x4fv) +#define glUniformMatrix3x2fv GLEW_GET_FUN(__glewUniformMatrix3x2fv) +#define glUniformMatrix3x4fv GLEW_GET_FUN(__glewUniformMatrix3x4fv) +#define glUniformMatrix4x2fv GLEW_GET_FUN(__glewUniformMatrix4x2fv) +#define glUniformMatrix4x3fv GLEW_GET_FUN(__glewUniformMatrix4x3fv) + +#define GLEW_VERSION_2_1 GLEW_GET_VAR(__GLEW_VERSION_2_1) + +#endif /* GL_VERSION_2_1 */ + +/* ----------------------------- GL_VERSION_3_0 ---------------------------- */ + +#ifndef GL_VERSION_3_0 +#define GL_VERSION_3_0 1 + +#define GL_MAX_CLIP_DISTANCES GL_MAX_CLIP_PLANES +#define GL_CLIP_DISTANCE5 GL_CLIP_PLANE5 +#define GL_CLIP_DISTANCE1 GL_CLIP_PLANE1 +#define GL_CLIP_DISTANCE3 GL_CLIP_PLANE3 +#define GL_COMPARE_REF_TO_TEXTURE GL_COMPARE_R_TO_TEXTURE_ARB +#define GL_CLIP_DISTANCE0 GL_CLIP_PLANE0 +#define GL_CLIP_DISTANCE4 GL_CLIP_PLANE4 +#define GL_CLIP_DISTANCE2 GL_CLIP_PLANE2 +#define GL_MAX_VARYING_COMPONENTS GL_MAX_VARYING_FLOATS +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001 +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_CONTEXT_FLAGS 0x821E +#define GL_DEPTH_BUFFER 0x8223 +#define GL_STENCIL_BUFFER 0x8224 +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RG 0x8226 +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_CLAMP_VERTEX_COLOR 0x891A +#define GL_CLAMP_FRAGMENT_COLOR 0x891B +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_FIXED_ONLY 0x891D +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE 0x8C15 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_GREEN_INTEGER 0x8D95 +#define GL_BLUE_INTEGER 0x8D96 +#define GL_ALPHA_INTEGER 0x8D97 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_BGR_INTEGER 0x8D9A +#define GL_BGRA_INTEGER 0x8D9B +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_QUERY_WAIT 0x8E13 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 + +typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERPROC) (GLuint, GLenum); +typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEPROC) (GLenum, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEPROC) (GLenum, GLuint, GLuint, GLintptr, GLsizeiptr); +typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONPROC) (GLuint, GLuint, const GLchar*); +typedef void (GLAPIENTRY * PFNGLCLAMPCOLORPROC) (GLenum, GLenum); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFIPROC) (GLenum, GLint, GLfloat, GLint); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFVPROC) (GLenum, GLint, const GLfloat*); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERIVPROC) (GLenum, GLint, const GLint*); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERUIVPROC) (GLenum, GLint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLCOLORMASKIPROC) (GLuint, GLboolean, GLboolean, GLboolean, GLboolean); +typedef void (GLAPIENTRY * PFNGLDISABLEIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLENABLEIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERPROC) (void); +typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKPROC) (void); +typedef void (GLAPIENTRY * PFNGLGETBOOLEANI_VPROC) (GLenum, GLuint, GLboolean*); +typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONPROC) (GLuint, const GLchar*); +typedef void (GLAPIENTRY * PFNGLGETINTEGERI_VPROC) (GLenum, GLuint, GLint*); +typedef const GLubyte* (GLAPIENTRY * PFNGLGETSTRINGIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIIVPROC) (GLenum, GLenum, GLint*); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIUIVPROC) (GLenum, GLenum, GLuint*); +typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint, GLuint, GLint*); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVPROC) (GLuint, GLint, GLuint*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVPROC) (GLuint, GLenum, GLint*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint, GLenum, GLuint*); +typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVPROC) (GLenum, GLenum, const GLint*); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVPROC) (GLenum, GLenum, const GLuint*); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint, GLsizei, const GLint*, GLenum); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIPROC) (GLint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIPROC) (GLint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIPROC) (GLint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIPROC) (GLint, GLuint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IPROC) (GLuint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIPROC) (GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IPROC) (GLuint, GLint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIPROC) (GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IPROC) (GLuint, GLint, GLint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIPROC) (GLuint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4BVPROC) (GLuint, const GLbyte*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IPROC) (GLuint, GLint, GLint, GLint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4SVPROC) (GLuint, const GLshort*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVPROC) (GLuint, const GLubyte*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIPROC) (GLuint, GLuint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVPROC) (GLuint, const GLushort*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint, GLint, GLenum, GLsizei, const GLvoid*); + +#define glBeginConditionalRender GLEW_GET_FUN(__glewBeginConditionalRender) +#define glBeginTransformFeedback GLEW_GET_FUN(__glewBeginTransformFeedback) +#define glBindBufferBase GLEW_GET_FUN(__glewBindBufferBase) +#define glBindBufferRange GLEW_GET_FUN(__glewBindBufferRange) +#define glBindFragDataLocation GLEW_GET_FUN(__glewBindFragDataLocation) +#define glClampColor GLEW_GET_FUN(__glewClampColor) +#define glClearBufferfi GLEW_GET_FUN(__glewClearBufferfi) +#define glClearBufferfv GLEW_GET_FUN(__glewClearBufferfv) +#define glClearBufferiv GLEW_GET_FUN(__glewClearBufferiv) +#define glClearBufferuiv GLEW_GET_FUN(__glewClearBufferuiv) +#define glColorMaski GLEW_GET_FUN(__glewColorMaski) +#define glDisablei GLEW_GET_FUN(__glewDisablei) +#define glEnablei GLEW_GET_FUN(__glewEnablei) +#define glEndConditionalRender GLEW_GET_FUN(__glewEndConditionalRender) +#define glEndTransformFeedback GLEW_GET_FUN(__glewEndTransformFeedback) +#define glGetBooleani_v GLEW_GET_FUN(__glewGetBooleani_v) +#define glGetFragDataLocation GLEW_GET_FUN(__glewGetFragDataLocation) +#define glGetIntegeri_v GLEW_GET_FUN(__glewGetIntegeri_v) +#define glGetStringi GLEW_GET_FUN(__glewGetStringi) +#define glGetTexParameterIiv GLEW_GET_FUN(__glewGetTexParameterIiv) +#define glGetTexParameterIuiv GLEW_GET_FUN(__glewGetTexParameterIuiv) +#define glGetTransformFeedbackVarying GLEW_GET_FUN(__glewGetTransformFeedbackVarying) +#define glGetUniformuiv GLEW_GET_FUN(__glewGetUniformuiv) +#define glGetVertexAttribIiv GLEW_GET_FUN(__glewGetVertexAttribIiv) +#define glGetVertexAttribIuiv GLEW_GET_FUN(__glewGetVertexAttribIuiv) +#define glIsEnabledi GLEW_GET_FUN(__glewIsEnabledi) +#define glTexParameterIiv GLEW_GET_FUN(__glewTexParameterIiv) +#define glTexParameterIuiv GLEW_GET_FUN(__glewTexParameterIuiv) +#define glTransformFeedbackVaryings GLEW_GET_FUN(__glewTransformFeedbackVaryings) +#define glUniform1ui GLEW_GET_FUN(__glewUniform1ui) +#define glUniform1uiv GLEW_GET_FUN(__glewUniform1uiv) +#define glUniform2ui GLEW_GET_FUN(__glewUniform2ui) +#define glUniform2uiv GLEW_GET_FUN(__glewUniform2uiv) +#define glUniform3ui GLEW_GET_FUN(__glewUniform3ui) +#define glUniform3uiv GLEW_GET_FUN(__glewUniform3uiv) +#define glUniform4ui GLEW_GET_FUN(__glewUniform4ui) +#define glUniform4uiv GLEW_GET_FUN(__glewUniform4uiv) +#define glVertexAttribI1i GLEW_GET_FUN(__glewVertexAttribI1i) +#define glVertexAttribI1iv GLEW_GET_FUN(__glewVertexAttribI1iv) +#define glVertexAttribI1ui GLEW_GET_FUN(__glewVertexAttribI1ui) +#define glVertexAttribI1uiv GLEW_GET_FUN(__glewVertexAttribI1uiv) +#define glVertexAttribI2i GLEW_GET_FUN(__glewVertexAttribI2i) +#define glVertexAttribI2iv GLEW_GET_FUN(__glewVertexAttribI2iv) +#define glVertexAttribI2ui GLEW_GET_FUN(__glewVertexAttribI2ui) +#define glVertexAttribI2uiv GLEW_GET_FUN(__glewVertexAttribI2uiv) +#define glVertexAttribI3i GLEW_GET_FUN(__glewVertexAttribI3i) +#define glVertexAttribI3iv GLEW_GET_FUN(__glewVertexAttribI3iv) +#define glVertexAttribI3ui GLEW_GET_FUN(__glewVertexAttribI3ui) +#define glVertexAttribI3uiv GLEW_GET_FUN(__glewVertexAttribI3uiv) +#define glVertexAttribI4bv GLEW_GET_FUN(__glewVertexAttribI4bv) +#define glVertexAttribI4i GLEW_GET_FUN(__glewVertexAttribI4i) +#define glVertexAttribI4iv GLEW_GET_FUN(__glewVertexAttribI4iv) +#define glVertexAttribI4sv GLEW_GET_FUN(__glewVertexAttribI4sv) +#define glVertexAttribI4ubv GLEW_GET_FUN(__glewVertexAttribI4ubv) +#define glVertexAttribI4ui GLEW_GET_FUN(__glewVertexAttribI4ui) +#define glVertexAttribI4uiv GLEW_GET_FUN(__glewVertexAttribI4uiv) +#define glVertexAttribI4usv GLEW_GET_FUN(__glewVertexAttribI4usv) +#define glVertexAttribIPointer GLEW_GET_FUN(__glewVertexAttribIPointer) + +#define GLEW_VERSION_3_0 GLEW_GET_VAR(__GLEW_VERSION_3_0) + +#endif /* GL_VERSION_3_0 */ + +/* -------------------------- GL_3DFX_multisample -------------------------- */ + +#ifndef GL_3DFX_multisample +#define GL_3DFX_multisample 1 + +#define GL_MULTISAMPLE_3DFX 0x86B2 +#define GL_SAMPLE_BUFFERS_3DFX 0x86B3 +#define GL_SAMPLES_3DFX 0x86B4 +#define GL_MULTISAMPLE_BIT_3DFX 0x20000000 + +#define GLEW_3DFX_multisample GLEW_GET_VAR(__GLEW_3DFX_multisample) + +#endif /* GL_3DFX_multisample */ + +/* ---------------------------- GL_3DFX_tbuffer ---------------------------- */ + +#ifndef GL_3DFX_tbuffer +#define GL_3DFX_tbuffer 1 + +typedef void (GLAPIENTRY * PFNGLTBUFFERMASK3DFXPROC) (GLuint mask); + +#define glTbufferMask3DFX GLEW_GET_FUN(__glewTbufferMask3DFX) + +#define GLEW_3DFX_tbuffer GLEW_GET_VAR(__GLEW_3DFX_tbuffer) + +#endif /* GL_3DFX_tbuffer */ + +/* -------------------- GL_3DFX_texture_compression_FXT1 ------------------- */ + +#ifndef GL_3DFX_texture_compression_FXT1 +#define GL_3DFX_texture_compression_FXT1 1 + +#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0 +#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1 + +#define GLEW_3DFX_texture_compression_FXT1 GLEW_GET_VAR(__GLEW_3DFX_texture_compression_FXT1) + +#endif /* GL_3DFX_texture_compression_FXT1 */ + +/* ------------------------ GL_APPLE_client_storage ------------------------ */ + +#ifndef GL_APPLE_client_storage +#define GL_APPLE_client_storage 1 + +#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2 + +#define GLEW_APPLE_client_storage GLEW_GET_VAR(__GLEW_APPLE_client_storage) + +#endif /* GL_APPLE_client_storage */ + +/* ------------------------- GL_APPLE_element_array ------------------------ */ + +#ifndef GL_APPLE_element_array +#define GL_APPLE_element_array 1 + +#define GL_ELEMENT_ARRAY_APPLE 0x8768 +#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8769 +#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x876A + +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void* pointer); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint* first, const GLsizei *count, GLsizei primcount); + +#define glDrawElementArrayAPPLE GLEW_GET_FUN(__glewDrawElementArrayAPPLE) +#define glDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewDrawRangeElementArrayAPPLE) +#define glElementPointerAPPLE GLEW_GET_FUN(__glewElementPointerAPPLE) +#define glMultiDrawElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawElementArrayAPPLE) +#define glMultiDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawRangeElementArrayAPPLE) + +#define GLEW_APPLE_element_array GLEW_GET_VAR(__GLEW_APPLE_element_array) + +#endif /* GL_APPLE_element_array */ + +/* ----------------------------- GL_APPLE_fence ---------------------------- */ + +#ifndef GL_APPLE_fence +#define GL_APPLE_fence 1 + +#define GL_DRAW_PIXELS_APPLE 0x8A0A +#define GL_FENCE_APPLE 0x8A0B + +typedef void (GLAPIENTRY * PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint* fences); +typedef void (GLAPIENTRY * PFNGLFINISHFENCEAPPLEPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name); +typedef void (GLAPIENTRY * PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint* fences); +typedef GLboolean (GLAPIENTRY * PFNGLISFENCEAPPLEPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLSETFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (GLAPIENTRY * PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name); + +#define glDeleteFencesAPPLE GLEW_GET_FUN(__glewDeleteFencesAPPLE) +#define glFinishFenceAPPLE GLEW_GET_FUN(__glewFinishFenceAPPLE) +#define glFinishObjectAPPLE GLEW_GET_FUN(__glewFinishObjectAPPLE) +#define glGenFencesAPPLE GLEW_GET_FUN(__glewGenFencesAPPLE) +#define glIsFenceAPPLE GLEW_GET_FUN(__glewIsFenceAPPLE) +#define glSetFenceAPPLE GLEW_GET_FUN(__glewSetFenceAPPLE) +#define glTestFenceAPPLE GLEW_GET_FUN(__glewTestFenceAPPLE) +#define glTestObjectAPPLE GLEW_GET_FUN(__glewTestObjectAPPLE) + +#define GLEW_APPLE_fence GLEW_GET_VAR(__GLEW_APPLE_fence) + +#endif /* GL_APPLE_fence */ + +/* ------------------------- GL_APPLE_float_pixels ------------------------- */ + +#ifndef GL_APPLE_float_pixels +#define GL_APPLE_float_pixels 1 + +#define GL_HALF_APPLE 0x140B +#define GL_RGBA_FLOAT32_APPLE 0x8814 +#define GL_RGB_FLOAT32_APPLE 0x8815 +#define GL_ALPHA_FLOAT32_APPLE 0x8816 +#define GL_INTENSITY_FLOAT32_APPLE 0x8817 +#define GL_LUMINANCE_FLOAT32_APPLE 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819 +#define GL_RGBA_FLOAT16_APPLE 0x881A +#define GL_RGB_FLOAT16_APPLE 0x881B +#define GL_ALPHA_FLOAT16_APPLE 0x881C +#define GL_INTENSITY_FLOAT16_APPLE 0x881D +#define GL_LUMINANCE_FLOAT16_APPLE 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F +#define GL_COLOR_FLOAT_APPLE 0x8A0F + +#define GLEW_APPLE_float_pixels GLEW_GET_VAR(__GLEW_APPLE_float_pixels) + +#endif /* GL_APPLE_float_pixels */ + +/* ---------------------- GL_APPLE_flush_buffer_range ---------------------- */ + +#ifndef GL_APPLE_flush_buffer_range +#define GL_APPLE_flush_buffer_range 1 + +#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12 +#define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13 + +typedef void (GLAPIENTRY * PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size); + +#define glBufferParameteriAPPLE GLEW_GET_FUN(__glewBufferParameteriAPPLE) +#define glFlushMappedBufferRangeAPPLE GLEW_GET_FUN(__glewFlushMappedBufferRangeAPPLE) + +#define GLEW_APPLE_flush_buffer_range GLEW_GET_VAR(__GLEW_APPLE_flush_buffer_range) + +#endif /* GL_APPLE_flush_buffer_range */ + +/* ------------------------- GL_APPLE_pixel_buffer ------------------------- */ + +#ifndef GL_APPLE_pixel_buffer +#define GL_APPLE_pixel_buffer 1 + +#define GL_MIN_PBUFFER_VIEWPORT_DIMS_APPLE 0x8A10 + +#define GLEW_APPLE_pixel_buffer GLEW_GET_VAR(__GLEW_APPLE_pixel_buffer) + +#endif /* GL_APPLE_pixel_buffer */ + +/* ------------------------ GL_APPLE_specular_vector ----------------------- */ + +#ifndef GL_APPLE_specular_vector +#define GL_APPLE_specular_vector 1 + +#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0 + +#define GLEW_APPLE_specular_vector GLEW_GET_VAR(__GLEW_APPLE_specular_vector) + +#endif /* GL_APPLE_specular_vector */ + +/* ------------------------- GL_APPLE_texture_range ------------------------ */ + +#ifndef GL_APPLE_texture_range +#define GL_APPLE_texture_range 1 + +#define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7 +#define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8 +#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC +#define GL_STORAGE_PRIVATE_APPLE 0x85BD +#define GL_STORAGE_CACHED_APPLE 0x85BE +#define GL_STORAGE_SHARED_APPLE 0x85BF + +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, GLvoid **params); +typedef void (GLAPIENTRY * PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, GLvoid *pointer); + +#define glGetTexParameterPointervAPPLE GLEW_GET_FUN(__glewGetTexParameterPointervAPPLE) +#define glTextureRangeAPPLE GLEW_GET_FUN(__glewTextureRangeAPPLE) + +#define GLEW_APPLE_texture_range GLEW_GET_VAR(__GLEW_APPLE_texture_range) + +#endif /* GL_APPLE_texture_range */ + +/* ------------------------ GL_APPLE_transform_hint ------------------------ */ + +#ifndef GL_APPLE_transform_hint +#define GL_APPLE_transform_hint 1 + +#define GL_TRANSFORM_HINT_APPLE 0x85B1 + +#define GLEW_APPLE_transform_hint GLEW_GET_VAR(__GLEW_APPLE_transform_hint) + +#endif /* GL_APPLE_transform_hint */ + +/* ---------------------- GL_APPLE_vertex_array_object --------------------- */ + +#ifndef GL_APPLE_vertex_array_object +#define GL_APPLE_vertex_array_object 1 + +#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5 + +typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array); +typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays); +typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays); +typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array); + +#define glBindVertexArrayAPPLE GLEW_GET_FUN(__glewBindVertexArrayAPPLE) +#define glDeleteVertexArraysAPPLE GLEW_GET_FUN(__glewDeleteVertexArraysAPPLE) +#define glGenVertexArraysAPPLE GLEW_GET_FUN(__glewGenVertexArraysAPPLE) +#define glIsVertexArrayAPPLE GLEW_GET_FUN(__glewIsVertexArrayAPPLE) + +#define GLEW_APPLE_vertex_array_object GLEW_GET_VAR(__GLEW_APPLE_vertex_array_object) + +#endif /* GL_APPLE_vertex_array_object */ + +/* ---------------------- GL_APPLE_vertex_array_range ---------------------- */ + +#ifndef GL_APPLE_vertex_array_range +#define GL_APPLE_vertex_array_range 1 + +#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E +#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F +#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE 0x8520 +#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521 +#define GL_STORAGE_CACHED_APPLE 0x85BE +#define GL_STORAGE_SHARED_APPLE 0x85BF + +typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer); + +#define glFlushVertexArrayRangeAPPLE GLEW_GET_FUN(__glewFlushVertexArrayRangeAPPLE) +#define glVertexArrayParameteriAPPLE GLEW_GET_FUN(__glewVertexArrayParameteriAPPLE) +#define glVertexArrayRangeAPPLE GLEW_GET_FUN(__glewVertexArrayRangeAPPLE) + +#define GLEW_APPLE_vertex_array_range GLEW_GET_VAR(__GLEW_APPLE_vertex_array_range) + +#endif /* GL_APPLE_vertex_array_range */ + +/* --------------------------- GL_APPLE_ycbcr_422 -------------------------- */ + +#ifndef GL_APPLE_ycbcr_422 +#define GL_APPLE_ycbcr_422 1 + +#define GL_YCBCR_422_APPLE 0x85B9 +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB + +#define GLEW_APPLE_ycbcr_422 GLEW_GET_VAR(__GLEW_APPLE_ycbcr_422) + +#endif /* GL_APPLE_ycbcr_422 */ + +/* ----------------------- GL_ARB_color_buffer_float ----------------------- */ + +#ifndef GL_ARB_color_buffer_float +#define GL_ARB_color_buffer_float 1 + +#define GL_RGBA_FLOAT_MODE_ARB 0x8820 +#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A +#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B +#define GL_CLAMP_READ_COLOR_ARB 0x891C +#define GL_FIXED_ONLY_ARB 0x891D + +typedef void (GLAPIENTRY * PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp); + +#define glClampColorARB GLEW_GET_FUN(__glewClampColorARB) + +#define GLEW_ARB_color_buffer_float GLEW_GET_VAR(__GLEW_ARB_color_buffer_float) + +#endif /* GL_ARB_color_buffer_float */ + +/* ----------------------- GL_ARB_depth_buffer_float ----------------------- */ + +#ifndef GL_ARB_depth_buffer_float +#define GL_ARB_depth_buffer_float 1 + +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD + +#define GLEW_ARB_depth_buffer_float GLEW_GET_VAR(__GLEW_ARB_depth_buffer_float) + +#endif /* GL_ARB_depth_buffer_float */ + +/* -------------------------- GL_ARB_depth_texture ------------------------- */ + +#ifndef GL_ARB_depth_texture +#define GL_ARB_depth_texture 1 + +#define GL_DEPTH_COMPONENT16_ARB 0x81A5 +#define GL_DEPTH_COMPONENT24_ARB 0x81A6 +#define GL_DEPTH_COMPONENT32_ARB 0x81A7 +#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A +#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B + +#define GLEW_ARB_depth_texture GLEW_GET_VAR(__GLEW_ARB_depth_texture) + +#endif /* GL_ARB_depth_texture */ + +/* -------------------------- GL_ARB_draw_buffers -------------------------- */ + +#ifndef GL_ARB_draw_buffers +#define GL_ARB_draw_buffers 1 + +#define GL_MAX_DRAW_BUFFERS_ARB 0x8824 +#define GL_DRAW_BUFFER0_ARB 0x8825 +#define GL_DRAW_BUFFER1_ARB 0x8826 +#define GL_DRAW_BUFFER2_ARB 0x8827 +#define GL_DRAW_BUFFER3_ARB 0x8828 +#define GL_DRAW_BUFFER4_ARB 0x8829 +#define GL_DRAW_BUFFER5_ARB 0x882A +#define GL_DRAW_BUFFER6_ARB 0x882B +#define GL_DRAW_BUFFER7_ARB 0x882C +#define GL_DRAW_BUFFER8_ARB 0x882D +#define GL_DRAW_BUFFER9_ARB 0x882E +#define GL_DRAW_BUFFER10_ARB 0x882F +#define GL_DRAW_BUFFER11_ARB 0x8830 +#define GL_DRAW_BUFFER12_ARB 0x8831 +#define GL_DRAW_BUFFER13_ARB 0x8832 +#define GL_DRAW_BUFFER14_ARB 0x8833 +#define GL_DRAW_BUFFER15_ARB 0x8834 + +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum* bufs); + +#define glDrawBuffersARB GLEW_GET_FUN(__glewDrawBuffersARB) + +#define GLEW_ARB_draw_buffers GLEW_GET_VAR(__GLEW_ARB_draw_buffers) + +#endif /* GL_ARB_draw_buffers */ + +/* ------------------------- GL_ARB_draw_instanced ------------------------- */ + +#ifndef GL_ARB_draw_instanced +#define GL_ARB_draw_instanced 1 + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount); + +#define glDrawArraysInstancedARB GLEW_GET_FUN(__glewDrawArraysInstancedARB) +#define glDrawElementsInstancedARB GLEW_GET_FUN(__glewDrawElementsInstancedARB) + +#define GLEW_ARB_draw_instanced GLEW_GET_VAR(__GLEW_ARB_draw_instanced) + +#endif /* GL_ARB_draw_instanced */ + +/* ------------------------ GL_ARB_fragment_program ------------------------ */ + +#ifndef GL_ARB_fragment_program +#define GL_ARB_fragment_program 1 + +#define GL_FRAGMENT_PROGRAM_ARB 0x8804 +#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805 +#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806 +#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807 +#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808 +#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809 +#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A +#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B +#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C +#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D +#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E +#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F +#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810 +#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 + +#define GLEW_ARB_fragment_program GLEW_GET_VAR(__GLEW_ARB_fragment_program) + +#endif /* GL_ARB_fragment_program */ + +/* --------------------- GL_ARB_fragment_program_shadow -------------------- */ + +#ifndef GL_ARB_fragment_program_shadow +#define GL_ARB_fragment_program_shadow 1 + +#define GLEW_ARB_fragment_program_shadow GLEW_GET_VAR(__GLEW_ARB_fragment_program_shadow) + +#endif /* GL_ARB_fragment_program_shadow */ + +/* ------------------------- GL_ARB_fragment_shader ------------------------ */ + +#ifndef GL_ARB_fragment_shader +#define GL_ARB_fragment_shader 1 + +#define GL_FRAGMENT_SHADER_ARB 0x8B30 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B + +#define GLEW_ARB_fragment_shader GLEW_GET_VAR(__GLEW_ARB_fragment_shader) + +#endif /* GL_ARB_fragment_shader */ + +/* ----------------------- GL_ARB_framebuffer_object ----------------------- */ + +#ifndef GL_ARB_framebuffer_object +#define GL_ARB_framebuffer_object 1 + +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_INDEX 0x8222 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_SRGB 0x8C40 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_STENCIL_INDEX1 0x8D46 +#define GL_STENCIL_INDEX4 0x8D47 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_INDEX16 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 + +typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer); +typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURLAYERPROC) (GLenum target,GLenum attachment, GLuint texture,GLint level,GLint layer); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer); +typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer); +typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + +#define glBindFramebuffer GLEW_GET_FUN(__glewBindFramebuffer) +#define glBindRenderbuffer GLEW_GET_FUN(__glewBindRenderbuffer) +#define glBlitFramebuffer GLEW_GET_FUN(__glewBlitFramebuffer) +#define glCheckFramebufferStatus GLEW_GET_FUN(__glewCheckFramebufferStatus) +#define glDeleteFramebuffers GLEW_GET_FUN(__glewDeleteFramebuffers) +#define glDeleteRenderbuffers GLEW_GET_FUN(__glewDeleteRenderbuffers) +#define glFramebufferRenderbuffer GLEW_GET_FUN(__glewFramebufferRenderbuffer) +#define glFramebufferTexturLayer GLEW_GET_FUN(__glewFramebufferTexturLayer) +#define glFramebufferTexture1D GLEW_GET_FUN(__glewFramebufferTexture1D) +#define glFramebufferTexture2D GLEW_GET_FUN(__glewFramebufferTexture2D) +#define glFramebufferTexture3D GLEW_GET_FUN(__glewFramebufferTexture3D) +#define glGenFramebuffers GLEW_GET_FUN(__glewGenFramebuffers) +#define glGenRenderbuffers GLEW_GET_FUN(__glewGenRenderbuffers) +#define glGenerateMipmap GLEW_GET_FUN(__glewGenerateMipmap) +#define glGetFramebufferAttachmentParameteriv GLEW_GET_FUN(__glewGetFramebufferAttachmentParameteriv) +#define glGetRenderbufferParameteriv GLEW_GET_FUN(__glewGetRenderbufferParameteriv) +#define glIsFramebuffer GLEW_GET_FUN(__glewIsFramebuffer) +#define glIsRenderbuffer GLEW_GET_FUN(__glewIsRenderbuffer) +#define glRenderbufferStorage GLEW_GET_FUN(__glewRenderbufferStorage) +#define glRenderbufferStorageMultisample GLEW_GET_FUN(__glewRenderbufferStorageMultisample) + +#define GLEW_ARB_framebuffer_object GLEW_GET_VAR(__GLEW_ARB_framebuffer_object) + +#endif /* GL_ARB_framebuffer_object */ + +/* ------------------------ GL_ARB_framebuffer_sRGB ------------------------ */ + +#ifndef GL_ARB_framebuffer_sRGB +#define GL_ARB_framebuffer_sRGB 1 + +#define GL_FRAMEBUFFER_SRGB 0x8DB9 + +#define GLEW_ARB_framebuffer_sRGB GLEW_GET_VAR(__GLEW_ARB_framebuffer_sRGB) + +#endif /* GL_ARB_framebuffer_sRGB */ + +/* ------------------------ GL_ARB_geometry_shader4 ------------------------ */ + +#ifndef GL_ARB_geometry_shader4 +#define GL_ARB_geometry_shader4 1 + +#define GL_LINES_ADJACENCY_ARB 0xA +#define GL_LINE_STRIP_ADJACENCY_ARB 0xB +#define GL_TRIANGLES_ADJACENCY_ARB 0xC +#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0xD +#define GL_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9 +#define GL_GEOMETRY_SHADER_ARB 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD +#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1 + +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value); + +#define glFramebufferTextureARB GLEW_GET_FUN(__glewFramebufferTextureARB) +#define glFramebufferTextureFaceARB GLEW_GET_FUN(__glewFramebufferTextureFaceARB) +#define glFramebufferTextureLayerARB GLEW_GET_FUN(__glewFramebufferTextureLayerARB) +#define glProgramParameteriARB GLEW_GET_FUN(__glewProgramParameteriARB) + +#define GLEW_ARB_geometry_shader4 GLEW_GET_VAR(__GLEW_ARB_geometry_shader4) + +#endif /* GL_ARB_geometry_shader4 */ + +/* ------------------------ GL_ARB_half_float_pixel ------------------------ */ + +#ifndef GL_ARB_half_float_pixel +#define GL_ARB_half_float_pixel 1 + +#define GL_HALF_FLOAT_ARB 0x140B + +#define GLEW_ARB_half_float_pixel GLEW_GET_VAR(__GLEW_ARB_half_float_pixel) + +#endif /* GL_ARB_half_float_pixel */ + +/* ------------------------ GL_ARB_half_float_vertex ----------------------- */ + +#ifndef GL_ARB_half_float_vertex +#define GL_ARB_half_float_vertex 1 + +#define GL_HALF_FLOAT 0x140B + +#define GLEW_ARB_half_float_vertex GLEW_GET_VAR(__GLEW_ARB_half_float_vertex) + +#endif /* GL_ARB_half_float_vertex */ + +/* ----------------------------- GL_ARB_imaging ---------------------------- */ + +#ifndef GL_ARB_imaging +#define GL_ARB_imaging 1 + +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 +#define GL_FUNC_ADD 0x8006 +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_BLEND_EQUATION 0x8009 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_CONVOLUTION_1D 0x8010 +#define GL_CONVOLUTION_2D 0x8011 +#define GL_SEPARABLE_2D 0x8012 +#define GL_CONVOLUTION_BORDER_MODE 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS 0x8015 +#define GL_REDUCE 0x8016 +#define GL_CONVOLUTION_FORMAT 0x8017 +#define GL_CONVOLUTION_WIDTH 0x8018 +#define GL_CONVOLUTION_HEIGHT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 +#define GL_HISTOGRAM 0x8024 +#define GL_PROXY_HISTOGRAM 0x8025 +#define GL_HISTOGRAM_WIDTH 0x8026 +#define GL_HISTOGRAM_FORMAT 0x8027 +#define GL_HISTOGRAM_RED_SIZE 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C +#define GL_HISTOGRAM_SINK 0x802D +#define GL_MINMAX 0x802E +#define GL_MINMAX_FORMAT 0x802F +#define GL_MINMAX_SINK 0x8030 +#define GL_TABLE_TOO_LARGE 0x8031 +#define GL_COLOR_MATRIX 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB +#define GL_COLOR_TABLE 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 +#define GL_PROXY_COLOR_TABLE 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 +#define GL_COLOR_TABLE_SCALE 0x80D6 +#define GL_COLOR_TABLE_BIAS 0x80D7 +#define GL_COLOR_TABLE_FORMAT 0x80D8 +#define GL_COLOR_TABLE_WIDTH 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF +#define GL_IGNORE_BORDER 0x8150 +#define GL_CONSTANT_BORDER 0x8151 +#define GL_WRAP_BORDER 0x8152 +#define GL_REPLICATE_BORDER 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR 0x8154 + +typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum types, GLvoid *values); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +typedef void (GLAPIENTRY * PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLRESETMINMAXPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); + +#define glColorSubTable GLEW_GET_FUN(__glewColorSubTable) +#define glColorTable GLEW_GET_FUN(__glewColorTable) +#define glColorTableParameterfv GLEW_GET_FUN(__glewColorTableParameterfv) +#define glColorTableParameteriv GLEW_GET_FUN(__glewColorTableParameteriv) +#define glConvolutionFilter1D GLEW_GET_FUN(__glewConvolutionFilter1D) +#define glConvolutionFilter2D GLEW_GET_FUN(__glewConvolutionFilter2D) +#define glConvolutionParameterf GLEW_GET_FUN(__glewConvolutionParameterf) +#define glConvolutionParameterfv GLEW_GET_FUN(__glewConvolutionParameterfv) +#define glConvolutionParameteri GLEW_GET_FUN(__glewConvolutionParameteri) +#define glConvolutionParameteriv GLEW_GET_FUN(__glewConvolutionParameteriv) +#define glCopyColorSubTable GLEW_GET_FUN(__glewCopyColorSubTable) +#define glCopyColorTable GLEW_GET_FUN(__glewCopyColorTable) +#define glCopyConvolutionFilter1D GLEW_GET_FUN(__glewCopyConvolutionFilter1D) +#define glCopyConvolutionFilter2D GLEW_GET_FUN(__glewCopyConvolutionFilter2D) +#define glGetColorTable GLEW_GET_FUN(__glewGetColorTable) +#define glGetColorTableParameterfv GLEW_GET_FUN(__glewGetColorTableParameterfv) +#define glGetColorTableParameteriv GLEW_GET_FUN(__glewGetColorTableParameteriv) +#define glGetConvolutionFilter GLEW_GET_FUN(__glewGetConvolutionFilter) +#define glGetConvolutionParameterfv GLEW_GET_FUN(__glewGetConvolutionParameterfv) +#define glGetConvolutionParameteriv GLEW_GET_FUN(__glewGetConvolutionParameteriv) +#define glGetHistogram GLEW_GET_FUN(__glewGetHistogram) +#define glGetHistogramParameterfv GLEW_GET_FUN(__glewGetHistogramParameterfv) +#define glGetHistogramParameteriv GLEW_GET_FUN(__glewGetHistogramParameteriv) +#define glGetMinmax GLEW_GET_FUN(__glewGetMinmax) +#define glGetMinmaxParameterfv GLEW_GET_FUN(__glewGetMinmaxParameterfv) +#define glGetMinmaxParameteriv GLEW_GET_FUN(__glewGetMinmaxParameteriv) +#define glGetSeparableFilter GLEW_GET_FUN(__glewGetSeparableFilter) +#define glHistogram GLEW_GET_FUN(__glewHistogram) +#define glMinmax GLEW_GET_FUN(__glewMinmax) +#define glResetHistogram GLEW_GET_FUN(__glewResetHistogram) +#define glResetMinmax GLEW_GET_FUN(__glewResetMinmax) +#define glSeparableFilter2D GLEW_GET_FUN(__glewSeparableFilter2D) + +#define GLEW_ARB_imaging GLEW_GET_VAR(__GLEW_ARB_imaging) + +#endif /* GL_ARB_imaging */ + +/* ------------------------ GL_ARB_instanced_arrays ------------------------ */ + +#ifndef GL_ARB_instanced_arrays +#define GL_ARB_instanced_arrays 1 + +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE + +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor); + +#define glVertexAttribDivisorARB GLEW_GET_FUN(__glewVertexAttribDivisorARB) + +#define GLEW_ARB_instanced_arrays GLEW_GET_VAR(__GLEW_ARB_instanced_arrays) + +#endif /* GL_ARB_instanced_arrays */ + +/* ------------------------ GL_ARB_map_buffer_range ------------------------ */ + +#ifndef GL_ARB_map_buffer_range +#define GL_ARB_map_buffer_range 1 + +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 + +typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); + +#define glFlushMappedBufferRange GLEW_GET_FUN(__glewFlushMappedBufferRange) +#define glMapBufferRange GLEW_GET_FUN(__glewMapBufferRange) + +#define GLEW_ARB_map_buffer_range GLEW_GET_VAR(__GLEW_ARB_map_buffer_range) + +#endif /* GL_ARB_map_buffer_range */ + +/* ------------------------- GL_ARB_matrix_palette ------------------------- */ + +#ifndef GL_ARB_matrix_palette +#define GL_ARB_matrix_palette 1 + +#define GL_MATRIX_PALETTE_ARB 0x8840 +#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841 +#define GL_MAX_PALETTE_MATRICES_ARB 0x8842 +#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843 +#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844 +#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845 +#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846 +#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847 +#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848 +#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849 + +typedef void (GLAPIENTRY * PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUBVARBPROC) (GLint size, GLubyte *indices); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUIVARBPROC) (GLint size, GLuint *indices); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUSVARBPROC) (GLint size, GLushort *indices); + +#define glCurrentPaletteMatrixARB GLEW_GET_FUN(__glewCurrentPaletteMatrixARB) +#define glMatrixIndexPointerARB GLEW_GET_FUN(__glewMatrixIndexPointerARB) +#define glMatrixIndexubvARB GLEW_GET_FUN(__glewMatrixIndexubvARB) +#define glMatrixIndexuivARB GLEW_GET_FUN(__glewMatrixIndexuivARB) +#define glMatrixIndexusvARB GLEW_GET_FUN(__glewMatrixIndexusvARB) + +#define GLEW_ARB_matrix_palette GLEW_GET_VAR(__GLEW_ARB_matrix_palette) + +#endif /* GL_ARB_matrix_palette */ + +/* --------------------------- GL_ARB_multisample -------------------------- */ + +#ifndef GL_ARB_multisample +#define GL_ARB_multisample 1 + +#define GL_MULTISAMPLE_ARB 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F +#define GL_SAMPLE_COVERAGE_ARB 0x80A0 +#define GL_SAMPLE_BUFFERS_ARB 0x80A8 +#define GL_SAMPLES_ARB 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB +#define GL_MULTISAMPLE_BIT_ARB 0x20000000 + +typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert); + +#define glSampleCoverageARB GLEW_GET_FUN(__glewSampleCoverageARB) + +#define GLEW_ARB_multisample GLEW_GET_VAR(__GLEW_ARB_multisample) + +#endif /* GL_ARB_multisample */ + +/* -------------------------- GL_ARB_multitexture -------------------------- */ + +#ifndef GL_ARB_multitexture +#define GL_ARB_multitexture 1 + +#define GL_TEXTURE0_ARB 0x84C0 +#define GL_TEXTURE1_ARB 0x84C1 +#define GL_TEXTURE2_ARB 0x84C2 +#define GL_TEXTURE3_ARB 0x84C3 +#define GL_TEXTURE4_ARB 0x84C4 +#define GL_TEXTURE5_ARB 0x84C5 +#define GL_TEXTURE6_ARB 0x84C6 +#define GL_TEXTURE7_ARB 0x84C7 +#define GL_TEXTURE8_ARB 0x84C8 +#define GL_TEXTURE9_ARB 0x84C9 +#define GL_TEXTURE10_ARB 0x84CA +#define GL_TEXTURE11_ARB 0x84CB +#define GL_TEXTURE12_ARB 0x84CC +#define GL_TEXTURE13_ARB 0x84CD +#define GL_TEXTURE14_ARB 0x84CE +#define GL_TEXTURE15_ARB 0x84CF +#define GL_TEXTURE16_ARB 0x84D0 +#define GL_TEXTURE17_ARB 0x84D1 +#define GL_TEXTURE18_ARB 0x84D2 +#define GL_TEXTURE19_ARB 0x84D3 +#define GL_TEXTURE20_ARB 0x84D4 +#define GL_TEXTURE21_ARB 0x84D5 +#define GL_TEXTURE22_ARB 0x84D6 +#define GL_TEXTURE23_ARB 0x84D7 +#define GL_TEXTURE24_ARB 0x84D8 +#define GL_TEXTURE25_ARB 0x84D9 +#define GL_TEXTURE26_ARB 0x84DA +#define GL_TEXTURE27_ARB 0x84DB +#define GL_TEXTURE28_ARB 0x84DC +#define GL_TEXTURE29_ARB 0x84DD +#define GL_TEXTURE30_ARB 0x84DE +#define GL_TEXTURE31_ARB 0x84DF +#define GL_ACTIVE_TEXTURE_ARB 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 +#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 + +typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); + +#define glActiveTextureARB GLEW_GET_FUN(__glewActiveTextureARB) +#define glClientActiveTextureARB GLEW_GET_FUN(__glewClientActiveTextureARB) +#define glMultiTexCoord1dARB GLEW_GET_FUN(__glewMultiTexCoord1dARB) +#define glMultiTexCoord1dvARB GLEW_GET_FUN(__glewMultiTexCoord1dvARB) +#define glMultiTexCoord1fARB GLEW_GET_FUN(__glewMultiTexCoord1fARB) +#define glMultiTexCoord1fvARB GLEW_GET_FUN(__glewMultiTexCoord1fvARB) +#define glMultiTexCoord1iARB GLEW_GET_FUN(__glewMultiTexCoord1iARB) +#define glMultiTexCoord1ivARB GLEW_GET_FUN(__glewMultiTexCoord1ivARB) +#define glMultiTexCoord1sARB GLEW_GET_FUN(__glewMultiTexCoord1sARB) +#define glMultiTexCoord1svARB GLEW_GET_FUN(__glewMultiTexCoord1svARB) +#define glMultiTexCoord2dARB GLEW_GET_FUN(__glewMultiTexCoord2dARB) +#define glMultiTexCoord2dvARB GLEW_GET_FUN(__glewMultiTexCoord2dvARB) +#define glMultiTexCoord2fARB GLEW_GET_FUN(__glewMultiTexCoord2fARB) +#define glMultiTexCoord2fvARB GLEW_GET_FUN(__glewMultiTexCoord2fvARB) +#define glMultiTexCoord2iARB GLEW_GET_FUN(__glewMultiTexCoord2iARB) +#define glMultiTexCoord2ivARB GLEW_GET_FUN(__glewMultiTexCoord2ivARB) +#define glMultiTexCoord2sARB GLEW_GET_FUN(__glewMultiTexCoord2sARB) +#define glMultiTexCoord2svARB GLEW_GET_FUN(__glewMultiTexCoord2svARB) +#define glMultiTexCoord3dARB GLEW_GET_FUN(__glewMultiTexCoord3dARB) +#define glMultiTexCoord3dvARB GLEW_GET_FUN(__glewMultiTexCoord3dvARB) +#define glMultiTexCoord3fARB GLEW_GET_FUN(__glewMultiTexCoord3fARB) +#define glMultiTexCoord3fvARB GLEW_GET_FUN(__glewMultiTexCoord3fvARB) +#define glMultiTexCoord3iARB GLEW_GET_FUN(__glewMultiTexCoord3iARB) +#define glMultiTexCoord3ivARB GLEW_GET_FUN(__glewMultiTexCoord3ivARB) +#define glMultiTexCoord3sARB GLEW_GET_FUN(__glewMultiTexCoord3sARB) +#define glMultiTexCoord3svARB GLEW_GET_FUN(__glewMultiTexCoord3svARB) +#define glMultiTexCoord4dARB GLEW_GET_FUN(__glewMultiTexCoord4dARB) +#define glMultiTexCoord4dvARB GLEW_GET_FUN(__glewMultiTexCoord4dvARB) +#define glMultiTexCoord4fARB GLEW_GET_FUN(__glewMultiTexCoord4fARB) +#define glMultiTexCoord4fvARB GLEW_GET_FUN(__glewMultiTexCoord4fvARB) +#define glMultiTexCoord4iARB GLEW_GET_FUN(__glewMultiTexCoord4iARB) +#define glMultiTexCoord4ivARB GLEW_GET_FUN(__glewMultiTexCoord4ivARB) +#define glMultiTexCoord4sARB GLEW_GET_FUN(__glewMultiTexCoord4sARB) +#define glMultiTexCoord4svARB GLEW_GET_FUN(__glewMultiTexCoord4svARB) + +#define GLEW_ARB_multitexture GLEW_GET_VAR(__GLEW_ARB_multitexture) + +#endif /* GL_ARB_multitexture */ + +/* ------------------------- GL_ARB_occlusion_query ------------------------ */ + +#ifndef GL_ARB_occlusion_query +#define GL_ARB_occlusion_query 1 + +#define GL_QUERY_COUNTER_BITS_ARB 0x8864 +#define GL_CURRENT_QUERY_ARB 0x8865 +#define GL_QUERY_RESULT_ARB 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 +#define GL_SAMPLES_PASSED_ARB 0x8914 + +typedef void (GLAPIENTRY * PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLENDQUERYARBPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISQUERYARBPROC) (GLuint id); + +#define glBeginQueryARB GLEW_GET_FUN(__glewBeginQueryARB) +#define glDeleteQueriesARB GLEW_GET_FUN(__glewDeleteQueriesARB) +#define glEndQueryARB GLEW_GET_FUN(__glewEndQueryARB) +#define glGenQueriesARB GLEW_GET_FUN(__glewGenQueriesARB) +#define glGetQueryObjectivARB GLEW_GET_FUN(__glewGetQueryObjectivARB) +#define glGetQueryObjectuivARB GLEW_GET_FUN(__glewGetQueryObjectuivARB) +#define glGetQueryivARB GLEW_GET_FUN(__glewGetQueryivARB) +#define glIsQueryARB GLEW_GET_FUN(__glewIsQueryARB) + +#define GLEW_ARB_occlusion_query GLEW_GET_VAR(__GLEW_ARB_occlusion_query) + +#endif /* GL_ARB_occlusion_query */ + +/* ----------------------- GL_ARB_pixel_buffer_object ---------------------- */ + +#ifndef GL_ARB_pixel_buffer_object +#define GL_ARB_pixel_buffer_object 1 + +#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF + +#define GLEW_ARB_pixel_buffer_object GLEW_GET_VAR(__GLEW_ARB_pixel_buffer_object) + +#endif /* GL_ARB_pixel_buffer_object */ + +/* ------------------------ GL_ARB_point_parameters ------------------------ */ + +#ifndef GL_ARB_point_parameters +#define GL_ARB_point_parameters 1 + +#define GL_POINT_SIZE_MIN_ARB 0x8126 +#define GL_POINT_SIZE_MAX_ARB 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129 + +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, GLfloat* params); + +#define glPointParameterfARB GLEW_GET_FUN(__glewPointParameterfARB) +#define glPointParameterfvARB GLEW_GET_FUN(__glewPointParameterfvARB) + +#define GLEW_ARB_point_parameters GLEW_GET_VAR(__GLEW_ARB_point_parameters) + +#endif /* GL_ARB_point_parameters */ + +/* -------------------------- GL_ARB_point_sprite -------------------------- */ + +#ifndef GL_ARB_point_sprite +#define GL_ARB_point_sprite 1 + +#define GL_POINT_SPRITE_ARB 0x8861 +#define GL_COORD_REPLACE_ARB 0x8862 + +#define GLEW_ARB_point_sprite GLEW_GET_VAR(__GLEW_ARB_point_sprite) + +#endif /* GL_ARB_point_sprite */ + +/* ------------------------- GL_ARB_shader_objects ------------------------- */ + +#ifndef GL_ARB_shader_objects +#define GL_ARB_shader_objects 1 + +#define GL_PROGRAM_OBJECT_ARB 0x8B40 +#define GL_SHADER_OBJECT_ARB 0x8B48 +#define GL_OBJECT_TYPE_ARB 0x8B4E +#define GL_OBJECT_SUBTYPE_ARB 0x8B4F +#define GL_FLOAT_VEC2_ARB 0x8B50 +#define GL_FLOAT_VEC3_ARB 0x8B51 +#define GL_FLOAT_VEC4_ARB 0x8B52 +#define GL_INT_VEC2_ARB 0x8B53 +#define GL_INT_VEC3_ARB 0x8B54 +#define GL_INT_VEC4_ARB 0x8B55 +#define GL_BOOL_ARB 0x8B56 +#define GL_BOOL_VEC2_ARB 0x8B57 +#define GL_BOOL_VEC3_ARB 0x8B58 +#define GL_BOOL_VEC4_ARB 0x8B59 +#define GL_FLOAT_MAT2_ARB 0x8B5A +#define GL_FLOAT_MAT3_ARB 0x8B5B +#define GL_FLOAT_MAT4_ARB 0x8B5C +#define GL_SAMPLER_1D_ARB 0x8B5D +#define GL_SAMPLER_2D_ARB 0x8B5E +#define GL_SAMPLER_3D_ARB 0x8B5F +#define GL_SAMPLER_CUBE_ARB 0x8B60 +#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 +#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 +#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 +#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 +#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 +#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 +#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 +#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 +#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 +#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 +#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 + +typedef char GLcharARB; +typedef unsigned int GLhandleARB; + +typedef void (GLAPIENTRY * PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj); +typedef void (GLAPIENTRY * PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj); +typedef GLhandleARB (GLAPIENTRY * PFNGLCREATEPROGRAMOBJECTARBPROC) (void); +typedef GLhandleARB (GLAPIENTRY * PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType); +typedef void (GLAPIENTRY * PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj); +typedef void (GLAPIENTRY * PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name); +typedef void (GLAPIENTRY * PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei* count, GLhandleARB *obj); +typedef GLhandleARB (GLAPIENTRY * PFNGLGETHANDLEARBPROC) (GLenum pname); +typedef void (GLAPIENTRY * PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *infoLog); +typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *source); +typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint* params); +typedef void (GLAPIENTRY * PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj); +typedef void (GLAPIENTRY * PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB ** string, const GLint *length); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj); +typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj); + +#define glAttachObjectARB GLEW_GET_FUN(__glewAttachObjectARB) +#define glCompileShaderARB GLEW_GET_FUN(__glewCompileShaderARB) +#define glCreateProgramObjectARB GLEW_GET_FUN(__glewCreateProgramObjectARB) +#define glCreateShaderObjectARB GLEW_GET_FUN(__glewCreateShaderObjectARB) +#define glDeleteObjectARB GLEW_GET_FUN(__glewDeleteObjectARB) +#define glDetachObjectARB GLEW_GET_FUN(__glewDetachObjectARB) +#define glGetActiveUniformARB GLEW_GET_FUN(__glewGetActiveUniformARB) +#define glGetAttachedObjectsARB GLEW_GET_FUN(__glewGetAttachedObjectsARB) +#define glGetHandleARB GLEW_GET_FUN(__glewGetHandleARB) +#define glGetInfoLogARB GLEW_GET_FUN(__glewGetInfoLogARB) +#define glGetObjectParameterfvARB GLEW_GET_FUN(__glewGetObjectParameterfvARB) +#define glGetObjectParameterivARB GLEW_GET_FUN(__glewGetObjectParameterivARB) +#define glGetShaderSourceARB GLEW_GET_FUN(__glewGetShaderSourceARB) +#define glGetUniformLocationARB GLEW_GET_FUN(__glewGetUniformLocationARB) +#define glGetUniformfvARB GLEW_GET_FUN(__glewGetUniformfvARB) +#define glGetUniformivARB GLEW_GET_FUN(__glewGetUniformivARB) +#define glLinkProgramARB GLEW_GET_FUN(__glewLinkProgramARB) +#define glShaderSourceARB GLEW_GET_FUN(__glewShaderSourceARB) +#define glUniform1fARB GLEW_GET_FUN(__glewUniform1fARB) +#define glUniform1fvARB GLEW_GET_FUN(__glewUniform1fvARB) +#define glUniform1iARB GLEW_GET_FUN(__glewUniform1iARB) +#define glUniform1ivARB GLEW_GET_FUN(__glewUniform1ivARB) +#define glUniform2fARB GLEW_GET_FUN(__glewUniform2fARB) +#define glUniform2fvARB GLEW_GET_FUN(__glewUniform2fvARB) +#define glUniform2iARB GLEW_GET_FUN(__glewUniform2iARB) +#define glUniform2ivARB GLEW_GET_FUN(__glewUniform2ivARB) +#define glUniform3fARB GLEW_GET_FUN(__glewUniform3fARB) +#define glUniform3fvARB GLEW_GET_FUN(__glewUniform3fvARB) +#define glUniform3iARB GLEW_GET_FUN(__glewUniform3iARB) +#define glUniform3ivARB GLEW_GET_FUN(__glewUniform3ivARB) +#define glUniform4fARB GLEW_GET_FUN(__glewUniform4fARB) +#define glUniform4fvARB GLEW_GET_FUN(__glewUniform4fvARB) +#define glUniform4iARB GLEW_GET_FUN(__glewUniform4iARB) +#define glUniform4ivARB GLEW_GET_FUN(__glewUniform4ivARB) +#define glUniformMatrix2fvARB GLEW_GET_FUN(__glewUniformMatrix2fvARB) +#define glUniformMatrix3fvARB GLEW_GET_FUN(__glewUniformMatrix3fvARB) +#define glUniformMatrix4fvARB GLEW_GET_FUN(__glewUniformMatrix4fvARB) +#define glUseProgramObjectARB GLEW_GET_FUN(__glewUseProgramObjectARB) +#define glValidateProgramARB GLEW_GET_FUN(__glewValidateProgramARB) + +#define GLEW_ARB_shader_objects GLEW_GET_VAR(__GLEW_ARB_shader_objects) + +#endif /* GL_ARB_shader_objects */ + +/* ---------------------- GL_ARB_shading_language_100 ---------------------- */ + +#ifndef GL_ARB_shading_language_100 +#define GL_ARB_shading_language_100 1 + +#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C + +#define GLEW_ARB_shading_language_100 GLEW_GET_VAR(__GLEW_ARB_shading_language_100) + +#endif /* GL_ARB_shading_language_100 */ + +/* ----------------------------- GL_ARB_shadow ----------------------------- */ + +#ifndef GL_ARB_shadow +#define GL_ARB_shadow 1 + +#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C +#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D +#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E + +#define GLEW_ARB_shadow GLEW_GET_VAR(__GLEW_ARB_shadow) + +#endif /* GL_ARB_shadow */ + +/* ------------------------- GL_ARB_shadow_ambient ------------------------- */ + +#ifndef GL_ARB_shadow_ambient +#define GL_ARB_shadow_ambient 1 + +#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF + +#define GLEW_ARB_shadow_ambient GLEW_GET_VAR(__GLEW_ARB_shadow_ambient) + +#endif /* GL_ARB_shadow_ambient */ + +/* ---------------------- GL_ARB_texture_border_clamp ---------------------- */ + +#ifndef GL_ARB_texture_border_clamp +#define GL_ARB_texture_border_clamp 1 + +#define GL_CLAMP_TO_BORDER_ARB 0x812D + +#define GLEW_ARB_texture_border_clamp GLEW_GET_VAR(__GLEW_ARB_texture_border_clamp) + +#endif /* GL_ARB_texture_border_clamp */ + +/* ---------------------- GL_ARB_texture_buffer_object --------------------- */ + +#ifndef GL_ARB_texture_buffer_object +#define GL_ARB_texture_buffer_object 1 + +#define GL_TEXTURE_BUFFER_ARB 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E + +typedef void (GLAPIENTRY * PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer); + +#define glTexBufferARB GLEW_GET_FUN(__glewTexBufferARB) + +#define GLEW_ARB_texture_buffer_object GLEW_GET_VAR(__GLEW_ARB_texture_buffer_object) + +#endif /* GL_ARB_texture_buffer_object */ + +/* ----------------------- GL_ARB_texture_compression ---------------------- */ + +#ifndef GL_ARB_texture_compression +#define GL_ARB_texture_compression 1 + +#define GL_COMPRESSED_ALPHA_ARB 0x84E9 +#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB +#define GL_COMPRESSED_INTENSITY_ARB 0x84EC +#define GL_COMPRESSED_RGB_ARB 0x84ED +#define GL_COMPRESSED_RGBA_ARB 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 +#define GL_TEXTURE_COMPRESSED_ARB 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 + +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, void* img); + +#define glCompressedTexImage1DARB GLEW_GET_FUN(__glewCompressedTexImage1DARB) +#define glCompressedTexImage2DARB GLEW_GET_FUN(__glewCompressedTexImage2DARB) +#define glCompressedTexImage3DARB GLEW_GET_FUN(__glewCompressedTexImage3DARB) +#define glCompressedTexSubImage1DARB GLEW_GET_FUN(__glewCompressedTexSubImage1DARB) +#define glCompressedTexSubImage2DARB GLEW_GET_FUN(__glewCompressedTexSubImage2DARB) +#define glCompressedTexSubImage3DARB GLEW_GET_FUN(__glewCompressedTexSubImage3DARB) +#define glGetCompressedTexImageARB GLEW_GET_FUN(__glewGetCompressedTexImageARB) + +#define GLEW_ARB_texture_compression GLEW_GET_VAR(__GLEW_ARB_texture_compression) + +#endif /* GL_ARB_texture_compression */ + +/* -------------------- GL_ARB_texture_compression_rgtc -------------------- */ + +#ifndef GL_ARB_texture_compression_rgtc +#define GL_ARB_texture_compression_rgtc 1 + +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE + +#define GLEW_ARB_texture_compression_rgtc GLEW_GET_VAR(__GLEW_ARB_texture_compression_rgtc) + +#endif /* GL_ARB_texture_compression_rgtc */ + +/* ------------------------ GL_ARB_texture_cube_map ------------------------ */ + +#ifndef GL_ARB_texture_cube_map +#define GL_ARB_texture_cube_map 1 + +#define GL_NORMAL_MAP_ARB 0x8511 +#define GL_REFLECTION_MAP_ARB 0x8512 +#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C + +#define GLEW_ARB_texture_cube_map GLEW_GET_VAR(__GLEW_ARB_texture_cube_map) + +#endif /* GL_ARB_texture_cube_map */ + +/* ------------------------- GL_ARB_texture_env_add ------------------------ */ + +#ifndef GL_ARB_texture_env_add +#define GL_ARB_texture_env_add 1 + +#define GLEW_ARB_texture_env_add GLEW_GET_VAR(__GLEW_ARB_texture_env_add) + +#endif /* GL_ARB_texture_env_add */ + +/* ----------------------- GL_ARB_texture_env_combine ---------------------- */ + +#ifndef GL_ARB_texture_env_combine +#define GL_ARB_texture_env_combine 1 + +#define GL_SUBTRACT_ARB 0x84E7 +#define GL_COMBINE_ARB 0x8570 +#define GL_COMBINE_RGB_ARB 0x8571 +#define GL_COMBINE_ALPHA_ARB 0x8572 +#define GL_RGB_SCALE_ARB 0x8573 +#define GL_ADD_SIGNED_ARB 0x8574 +#define GL_INTERPOLATE_ARB 0x8575 +#define GL_CONSTANT_ARB 0x8576 +#define GL_PRIMARY_COLOR_ARB 0x8577 +#define GL_PREVIOUS_ARB 0x8578 +#define GL_SOURCE0_RGB_ARB 0x8580 +#define GL_SOURCE1_RGB_ARB 0x8581 +#define GL_SOURCE2_RGB_ARB 0x8582 +#define GL_SOURCE0_ALPHA_ARB 0x8588 +#define GL_SOURCE1_ALPHA_ARB 0x8589 +#define GL_SOURCE2_ALPHA_ARB 0x858A +#define GL_OPERAND0_RGB_ARB 0x8590 +#define GL_OPERAND1_RGB_ARB 0x8591 +#define GL_OPERAND2_RGB_ARB 0x8592 +#define GL_OPERAND0_ALPHA_ARB 0x8598 +#define GL_OPERAND1_ALPHA_ARB 0x8599 +#define GL_OPERAND2_ALPHA_ARB 0x859A + +#define GLEW_ARB_texture_env_combine GLEW_GET_VAR(__GLEW_ARB_texture_env_combine) + +#endif /* GL_ARB_texture_env_combine */ + +/* ---------------------- GL_ARB_texture_env_crossbar ---------------------- */ + +#ifndef GL_ARB_texture_env_crossbar +#define GL_ARB_texture_env_crossbar 1 + +#define GLEW_ARB_texture_env_crossbar GLEW_GET_VAR(__GLEW_ARB_texture_env_crossbar) + +#endif /* GL_ARB_texture_env_crossbar */ + +/* ------------------------ GL_ARB_texture_env_dot3 ------------------------ */ + +#ifndef GL_ARB_texture_env_dot3 +#define GL_ARB_texture_env_dot3 1 + +#define GL_DOT3_RGB_ARB 0x86AE +#define GL_DOT3_RGBA_ARB 0x86AF + +#define GLEW_ARB_texture_env_dot3 GLEW_GET_VAR(__GLEW_ARB_texture_env_dot3) + +#endif /* GL_ARB_texture_env_dot3 */ + +/* -------------------------- GL_ARB_texture_float ------------------------- */ + +#ifndef GL_ARB_texture_float +#define GL_ARB_texture_float 1 + +#define GL_RGBA32F_ARB 0x8814 +#define GL_RGB32F_ARB 0x8815 +#define GL_ALPHA32F_ARB 0x8816 +#define GL_INTENSITY32F_ARB 0x8817 +#define GL_LUMINANCE32F_ARB 0x8818 +#define GL_LUMINANCE_ALPHA32F_ARB 0x8819 +#define GL_RGBA16F_ARB 0x881A +#define GL_RGB16F_ARB 0x881B +#define GL_ALPHA16F_ARB 0x881C +#define GL_INTENSITY16F_ARB 0x881D +#define GL_LUMINANCE16F_ARB 0x881E +#define GL_LUMINANCE_ALPHA16F_ARB 0x881F +#define GL_TEXTURE_RED_TYPE_ARB 0x8C10 +#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11 +#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13 +#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15 +#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16 +#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17 + +#define GLEW_ARB_texture_float GLEW_GET_VAR(__GLEW_ARB_texture_float) + +#endif /* GL_ARB_texture_float */ + +/* --------------------- GL_ARB_texture_mirrored_repeat -------------------- */ + +#ifndef GL_ARB_texture_mirrored_repeat +#define GL_ARB_texture_mirrored_repeat 1 + +#define GL_MIRRORED_REPEAT_ARB 0x8370 + +#define GLEW_ARB_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_ARB_texture_mirrored_repeat) + +#endif /* GL_ARB_texture_mirrored_repeat */ + +/* -------------------- GL_ARB_texture_non_power_of_two -------------------- */ + +#ifndef GL_ARB_texture_non_power_of_two +#define GL_ARB_texture_non_power_of_two 1 + +#define GLEW_ARB_texture_non_power_of_two GLEW_GET_VAR(__GLEW_ARB_texture_non_power_of_two) + +#endif /* GL_ARB_texture_non_power_of_two */ + +/* ------------------------ GL_ARB_texture_rectangle ----------------------- */ + +#ifndef GL_ARB_texture_rectangle +#define GL_ARB_texture_rectangle 1 + +#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 + +#define GLEW_ARB_texture_rectangle GLEW_GET_VAR(__GLEW_ARB_texture_rectangle) + +#endif /* GL_ARB_texture_rectangle */ + +/* --------------------------- GL_ARB_texture_rg --------------------------- */ + +#ifndef GL_ARB_texture_rg +#define GL_ARB_texture_rg 1 + +#define GL_RED 0x1903 +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_R16 0x822A +#define GL_RG8 0x822B +#define GL_RG16 0x822C +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C + +#define GLEW_ARB_texture_rg GLEW_GET_VAR(__GLEW_ARB_texture_rg) + +#endif /* GL_ARB_texture_rg */ + +/* ------------------------ GL_ARB_transpose_matrix ------------------------ */ + +#ifndef GL_ARB_transpose_matrix +#define GL_ARB_transpose_matrix 1 + +#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 + +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDARBPROC) (GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDARBPROC) (GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]); + +#define glLoadTransposeMatrixdARB GLEW_GET_FUN(__glewLoadTransposeMatrixdARB) +#define glLoadTransposeMatrixfARB GLEW_GET_FUN(__glewLoadTransposeMatrixfARB) +#define glMultTransposeMatrixdARB GLEW_GET_FUN(__glewMultTransposeMatrixdARB) +#define glMultTransposeMatrixfARB GLEW_GET_FUN(__glewMultTransposeMatrixfARB) + +#define GLEW_ARB_transpose_matrix GLEW_GET_VAR(__GLEW_ARB_transpose_matrix) + +#endif /* GL_ARB_transpose_matrix */ + +/* ----------------------- GL_ARB_vertex_array_object ---------------------- */ + +#ifndef GL_ARB_vertex_array_object +#define GL_ARB_vertex_array_object 1 + +#define GL_VERTEX_ARRAY_BINDING 0x85B5 + +typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYPROC) (GLuint array); +typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays); +typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays); +typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYPROC) (GLuint array); + +#define glBindVertexArray GLEW_GET_FUN(__glewBindVertexArray) +#define glDeleteVertexArrays GLEW_GET_FUN(__glewDeleteVertexArrays) +#define glGenVertexArrays GLEW_GET_FUN(__glewGenVertexArrays) +#define glIsVertexArray GLEW_GET_FUN(__glewIsVertexArray) + +#define GLEW_ARB_vertex_array_object GLEW_GET_VAR(__GLEW_ARB_vertex_array_object) + +#endif /* GL_ARB_vertex_array_object */ + +/* -------------------------- GL_ARB_vertex_blend -------------------------- */ + +#ifndef GL_ARB_vertex_blend +#define GL_ARB_vertex_blend 1 + +#define GL_MODELVIEW0_ARB 0x1700 +#define GL_MODELVIEW1_ARB 0x850A +#define GL_MAX_VERTEX_UNITS_ARB 0x86A4 +#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5 +#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6 +#define GL_VERTEX_BLEND_ARB 0x86A7 +#define GL_CURRENT_WEIGHT_ARB 0x86A8 +#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9 +#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA +#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB +#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC +#define GL_WEIGHT_ARRAY_ARB 0x86AD +#define GL_MODELVIEW2_ARB 0x8722 +#define GL_MODELVIEW3_ARB 0x8723 +#define GL_MODELVIEW4_ARB 0x8724 +#define GL_MODELVIEW5_ARB 0x8725 +#define GL_MODELVIEW6_ARB 0x8726 +#define GL_MODELVIEW7_ARB 0x8727 +#define GL_MODELVIEW8_ARB 0x8728 +#define GL_MODELVIEW9_ARB 0x8729 +#define GL_MODELVIEW10_ARB 0x872A +#define GL_MODELVIEW11_ARB 0x872B +#define GL_MODELVIEW12_ARB 0x872C +#define GL_MODELVIEW13_ARB 0x872D +#define GL_MODELVIEW14_ARB 0x872E +#define GL_MODELVIEW15_ARB 0x872F +#define GL_MODELVIEW16_ARB 0x8730 +#define GL_MODELVIEW17_ARB 0x8731 +#define GL_MODELVIEW18_ARB 0x8732 +#define GL_MODELVIEW19_ARB 0x8733 +#define GL_MODELVIEW20_ARB 0x8734 +#define GL_MODELVIEW21_ARB 0x8735 +#define GL_MODELVIEW22_ARB 0x8736 +#define GL_MODELVIEW23_ARB 0x8737 +#define GL_MODELVIEW24_ARB 0x8738 +#define GL_MODELVIEW25_ARB 0x8739 +#define GL_MODELVIEW26_ARB 0x873A +#define GL_MODELVIEW27_ARB 0x873B +#define GL_MODELVIEW28_ARB 0x873C +#define GL_MODELVIEW29_ARB 0x873D +#define GL_MODELVIEW30_ARB 0x873E +#define GL_MODELVIEW31_ARB 0x873F + +typedef void (GLAPIENTRY * PFNGLVERTEXBLENDARBPROC) (GLint count); +typedef void (GLAPIENTRY * PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLWEIGHTBVARBPROC) (GLint size, GLbyte *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTDVARBPROC) (GLint size, GLdouble *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTFVARBPROC) (GLint size, GLfloat *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTIVARBPROC) (GLint size, GLint *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTSVARBPROC) (GLint size, GLshort *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTUBVARBPROC) (GLint size, GLubyte *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTUIVARBPROC) (GLint size, GLuint *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTUSVARBPROC) (GLint size, GLushort *weights); + +#define glVertexBlendARB GLEW_GET_FUN(__glewVertexBlendARB) +#define glWeightPointerARB GLEW_GET_FUN(__glewWeightPointerARB) +#define glWeightbvARB GLEW_GET_FUN(__glewWeightbvARB) +#define glWeightdvARB GLEW_GET_FUN(__glewWeightdvARB) +#define glWeightfvARB GLEW_GET_FUN(__glewWeightfvARB) +#define glWeightivARB GLEW_GET_FUN(__glewWeightivARB) +#define glWeightsvARB GLEW_GET_FUN(__glewWeightsvARB) +#define glWeightubvARB GLEW_GET_FUN(__glewWeightubvARB) +#define glWeightuivARB GLEW_GET_FUN(__glewWeightuivARB) +#define glWeightusvARB GLEW_GET_FUN(__glewWeightusvARB) + +#define GLEW_ARB_vertex_blend GLEW_GET_VAR(__GLEW_ARB_vertex_blend) + +#endif /* GL_ARB_vertex_blend */ + +/* ---------------------- GL_ARB_vertex_buffer_object ---------------------- */ + +#ifndef GL_ARB_vertex_buffer_object +#define GL_ARB_vertex_buffer_object 1 + +#define GL_BUFFER_SIZE_ARB 0x8764 +#define GL_BUFFER_USAGE_ARB 0x8765 +#define GL_ARRAY_BUFFER_ARB 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 +#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F +#define GL_READ_ONLY_ARB 0x88B8 +#define GL_WRITE_ONLY_ARB 0x88B9 +#define GL_READ_WRITE_ARB 0x88BA +#define GL_BUFFER_ACCESS_ARB 0x88BB +#define GL_BUFFER_MAPPED_ARB 0x88BC +#define GL_BUFFER_MAP_POINTER_ARB 0x88BD +#define GL_STREAM_DRAW_ARB 0x88E0 +#define GL_STREAM_READ_ARB 0x88E1 +#define GL_STREAM_COPY_ARB 0x88E2 +#define GL_STATIC_DRAW_ARB 0x88E4 +#define GL_STATIC_READ_ARB 0x88E5 +#define GL_STATIC_COPY_ARB 0x88E6 +#define GL_DYNAMIC_DRAW_ARB 0x88E8 +#define GL_DYNAMIC_READ_ARB 0x88E9 +#define GL_DYNAMIC_COPY_ARB 0x88EA + +typedef ptrdiff_t GLsizeiptrARB; +typedef ptrdiff_t GLintptrARB; + +typedef void (GLAPIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid* data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid** params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid* data); +typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERARBPROC) (GLuint buffer); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access); +typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERARBPROC) (GLenum target); + +#define glBindBufferARB GLEW_GET_FUN(__glewBindBufferARB) +#define glBufferDataARB GLEW_GET_FUN(__glewBufferDataARB) +#define glBufferSubDataARB GLEW_GET_FUN(__glewBufferSubDataARB) +#define glDeleteBuffersARB GLEW_GET_FUN(__glewDeleteBuffersARB) +#define glGenBuffersARB GLEW_GET_FUN(__glewGenBuffersARB) +#define glGetBufferParameterivARB GLEW_GET_FUN(__glewGetBufferParameterivARB) +#define glGetBufferPointervARB GLEW_GET_FUN(__glewGetBufferPointervARB) +#define glGetBufferSubDataARB GLEW_GET_FUN(__glewGetBufferSubDataARB) +#define glIsBufferARB GLEW_GET_FUN(__glewIsBufferARB) +#define glMapBufferARB GLEW_GET_FUN(__glewMapBufferARB) +#define glUnmapBufferARB GLEW_GET_FUN(__glewUnmapBufferARB) + +#define GLEW_ARB_vertex_buffer_object GLEW_GET_VAR(__GLEW_ARB_vertex_buffer_object) + +#endif /* GL_ARB_vertex_buffer_object */ + +/* ------------------------- GL_ARB_vertex_program ------------------------- */ + +#ifndef GL_ARB_vertex_program +#define GL_ARB_vertex_program 1 + +#define GL_COLOR_SUM_ARB 0x8458 +#define GL_VERTEX_PROGRAM_ARB 0x8620 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 +#define GL_PROGRAM_LENGTH_ARB 0x8627 +#define GL_PROGRAM_STRING_ARB 0x8628 +#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E +#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F +#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 +#define GL_CURRENT_MATRIX_ARB 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 +#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B +#define GL_PROGRAM_BINDING_ARB 0x8677 +#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A +#define GL_PROGRAM_ERROR_STRING_ARB 0x8874 +#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 +#define GL_PROGRAM_FORMAT_ARB 0x8876 +#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 +#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 +#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 +#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 +#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 +#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 +#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 +#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 +#define GL_PROGRAM_PARAMETERS_ARB 0x88A8 +#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 +#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA +#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB +#define GL_PROGRAM_ATTRIBS_ARB 0x88AC +#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD +#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE +#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF +#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 +#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 +#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 +#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 +#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 +#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 +#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 +#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 +#define GL_MATRIX0_ARB 0x88C0 +#define GL_MATRIX1_ARB 0x88C1 +#define GL_MATRIX2_ARB 0x88C2 +#define GL_MATRIX3_ARB 0x88C3 +#define GL_MATRIX4_ARB 0x88C4 +#define GL_MATRIX5_ARB 0x88C5 +#define GL_MATRIX6_ARB 0x88C6 +#define GL_MATRIX7_ARB 0x88C7 +#define GL_MATRIX8_ARB 0x88C8 +#define GL_MATRIX9_ARB 0x88C9 +#define GL_MATRIX10_ARB 0x88CA +#define GL_MATRIX11_ARB 0x88CB +#define GL_MATRIX12_ARB 0x88CC +#define GL_MATRIX13_ARB 0x88CD +#define GL_MATRIX14_ARB 0x88CE +#define GL_MATRIX15_ARB 0x88CF +#define GL_MATRIX16_ARB 0x88D0 +#define GL_MATRIX17_ARB 0x88D1 +#define GL_MATRIX18_ARB 0x88D2 +#define GL_MATRIX19_ARB 0x88D3 +#define GL_MATRIX20_ARB 0x88D4 +#define GL_MATRIX21_ARB 0x88D5 +#define GL_MATRIX22_ARB 0x88D6 +#define GL_MATRIX23_ARB 0x88D7 +#define GL_MATRIX24_ARB 0x88D8 +#define GL_MATRIX25_ARB 0x88D9 +#define GL_MATRIX26_ARB 0x88DA +#define GL_MATRIX27_ARB 0x88DB +#define GL_MATRIX28_ARB 0x88DC +#define GL_MATRIX29_ARB 0x88DD +#define GL_MATRIX30_ARB 0x88DE +#define GL_MATRIX31_ARB 0x88DF + +typedef void (GLAPIENTRY * PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program); +typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint* programs); +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (GLAPIENTRY * PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint* programs); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void* string); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid** pointer); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMARBPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void* string); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer); + +#define glBindProgramARB GLEW_GET_FUN(__glewBindProgramARB) +#define glDeleteProgramsARB GLEW_GET_FUN(__glewDeleteProgramsARB) +#define glDisableVertexAttribArrayARB GLEW_GET_FUN(__glewDisableVertexAttribArrayARB) +#define glEnableVertexAttribArrayARB GLEW_GET_FUN(__glewEnableVertexAttribArrayARB) +#define glGenProgramsARB GLEW_GET_FUN(__glewGenProgramsARB) +#define glGetProgramEnvParameterdvARB GLEW_GET_FUN(__glewGetProgramEnvParameterdvARB) +#define glGetProgramEnvParameterfvARB GLEW_GET_FUN(__glewGetProgramEnvParameterfvARB) +#define glGetProgramLocalParameterdvARB GLEW_GET_FUN(__glewGetProgramLocalParameterdvARB) +#define glGetProgramLocalParameterfvARB GLEW_GET_FUN(__glewGetProgramLocalParameterfvARB) +#define glGetProgramStringARB GLEW_GET_FUN(__glewGetProgramStringARB) +#define glGetProgramivARB GLEW_GET_FUN(__glewGetProgramivARB) +#define glGetVertexAttribPointervARB GLEW_GET_FUN(__glewGetVertexAttribPointervARB) +#define glGetVertexAttribdvARB GLEW_GET_FUN(__glewGetVertexAttribdvARB) +#define glGetVertexAttribfvARB GLEW_GET_FUN(__glewGetVertexAttribfvARB) +#define glGetVertexAttribivARB GLEW_GET_FUN(__glewGetVertexAttribivARB) +#define glIsProgramARB GLEW_GET_FUN(__glewIsProgramARB) +#define glProgramEnvParameter4dARB GLEW_GET_FUN(__glewProgramEnvParameter4dARB) +#define glProgramEnvParameter4dvARB GLEW_GET_FUN(__glewProgramEnvParameter4dvARB) +#define glProgramEnvParameter4fARB GLEW_GET_FUN(__glewProgramEnvParameter4fARB) +#define glProgramEnvParameter4fvARB GLEW_GET_FUN(__glewProgramEnvParameter4fvARB) +#define glProgramLocalParameter4dARB GLEW_GET_FUN(__glewProgramLocalParameter4dARB) +#define glProgramLocalParameter4dvARB GLEW_GET_FUN(__glewProgramLocalParameter4dvARB) +#define glProgramLocalParameter4fARB GLEW_GET_FUN(__glewProgramLocalParameter4fARB) +#define glProgramLocalParameter4fvARB GLEW_GET_FUN(__glewProgramLocalParameter4fvARB) +#define glProgramStringARB GLEW_GET_FUN(__glewProgramStringARB) +#define glVertexAttrib1dARB GLEW_GET_FUN(__glewVertexAttrib1dARB) +#define glVertexAttrib1dvARB GLEW_GET_FUN(__glewVertexAttrib1dvARB) +#define glVertexAttrib1fARB GLEW_GET_FUN(__glewVertexAttrib1fARB) +#define glVertexAttrib1fvARB GLEW_GET_FUN(__glewVertexAttrib1fvARB) +#define glVertexAttrib1sARB GLEW_GET_FUN(__glewVertexAttrib1sARB) +#define glVertexAttrib1svARB GLEW_GET_FUN(__glewVertexAttrib1svARB) +#define glVertexAttrib2dARB GLEW_GET_FUN(__glewVertexAttrib2dARB) +#define glVertexAttrib2dvARB GLEW_GET_FUN(__glewVertexAttrib2dvARB) +#define glVertexAttrib2fARB GLEW_GET_FUN(__glewVertexAttrib2fARB) +#define glVertexAttrib2fvARB GLEW_GET_FUN(__glewVertexAttrib2fvARB) +#define glVertexAttrib2sARB GLEW_GET_FUN(__glewVertexAttrib2sARB) +#define glVertexAttrib2svARB GLEW_GET_FUN(__glewVertexAttrib2svARB) +#define glVertexAttrib3dARB GLEW_GET_FUN(__glewVertexAttrib3dARB) +#define glVertexAttrib3dvARB GLEW_GET_FUN(__glewVertexAttrib3dvARB) +#define glVertexAttrib3fARB GLEW_GET_FUN(__glewVertexAttrib3fARB) +#define glVertexAttrib3fvARB GLEW_GET_FUN(__glewVertexAttrib3fvARB) +#define glVertexAttrib3sARB GLEW_GET_FUN(__glewVertexAttrib3sARB) +#define glVertexAttrib3svARB GLEW_GET_FUN(__glewVertexAttrib3svARB) +#define glVertexAttrib4NbvARB GLEW_GET_FUN(__glewVertexAttrib4NbvARB) +#define glVertexAttrib4NivARB GLEW_GET_FUN(__glewVertexAttrib4NivARB) +#define glVertexAttrib4NsvARB GLEW_GET_FUN(__glewVertexAttrib4NsvARB) +#define glVertexAttrib4NubARB GLEW_GET_FUN(__glewVertexAttrib4NubARB) +#define glVertexAttrib4NubvARB GLEW_GET_FUN(__glewVertexAttrib4NubvARB) +#define glVertexAttrib4NuivARB GLEW_GET_FUN(__glewVertexAttrib4NuivARB) +#define glVertexAttrib4NusvARB GLEW_GET_FUN(__glewVertexAttrib4NusvARB) +#define glVertexAttrib4bvARB GLEW_GET_FUN(__glewVertexAttrib4bvARB) +#define glVertexAttrib4dARB GLEW_GET_FUN(__glewVertexAttrib4dARB) +#define glVertexAttrib4dvARB GLEW_GET_FUN(__glewVertexAttrib4dvARB) +#define glVertexAttrib4fARB GLEW_GET_FUN(__glewVertexAttrib4fARB) +#define glVertexAttrib4fvARB GLEW_GET_FUN(__glewVertexAttrib4fvARB) +#define glVertexAttrib4ivARB GLEW_GET_FUN(__glewVertexAttrib4ivARB) +#define glVertexAttrib4sARB GLEW_GET_FUN(__glewVertexAttrib4sARB) +#define glVertexAttrib4svARB GLEW_GET_FUN(__glewVertexAttrib4svARB) +#define glVertexAttrib4ubvARB GLEW_GET_FUN(__glewVertexAttrib4ubvARB) +#define glVertexAttrib4uivARB GLEW_GET_FUN(__glewVertexAttrib4uivARB) +#define glVertexAttrib4usvARB GLEW_GET_FUN(__glewVertexAttrib4usvARB) +#define glVertexAttribPointerARB GLEW_GET_FUN(__glewVertexAttribPointerARB) + +#define GLEW_ARB_vertex_program GLEW_GET_VAR(__GLEW_ARB_vertex_program) + +#endif /* GL_ARB_vertex_program */ + +/* -------------------------- GL_ARB_vertex_shader ------------------------- */ + +#ifndef GL_ARB_vertex_shader +#define GL_ARB_vertex_shader 1 + +#define GL_VERTEX_SHADER_ARB 0x8B31 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A +#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D +#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 +#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A + +typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB* name); +typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name); +typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name); + +#define glBindAttribLocationARB GLEW_GET_FUN(__glewBindAttribLocationARB) +#define glGetActiveAttribARB GLEW_GET_FUN(__glewGetActiveAttribARB) +#define glGetAttribLocationARB GLEW_GET_FUN(__glewGetAttribLocationARB) + +#define GLEW_ARB_vertex_shader GLEW_GET_VAR(__GLEW_ARB_vertex_shader) + +#endif /* GL_ARB_vertex_shader */ + +/* --------------------------- GL_ARB_window_pos --------------------------- */ + +#ifndef GL_ARB_window_pos +#define GL_ARB_window_pos 1 + +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVARBPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVARBPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVARBPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVARBPROC) (const GLshort* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVARBPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVARBPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVARBPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVARBPROC) (const GLshort* p); + +#define glWindowPos2dARB GLEW_GET_FUN(__glewWindowPos2dARB) +#define glWindowPos2dvARB GLEW_GET_FUN(__glewWindowPos2dvARB) +#define glWindowPos2fARB GLEW_GET_FUN(__glewWindowPos2fARB) +#define glWindowPos2fvARB GLEW_GET_FUN(__glewWindowPos2fvARB) +#define glWindowPos2iARB GLEW_GET_FUN(__glewWindowPos2iARB) +#define glWindowPos2ivARB GLEW_GET_FUN(__glewWindowPos2ivARB) +#define glWindowPos2sARB GLEW_GET_FUN(__glewWindowPos2sARB) +#define glWindowPos2svARB GLEW_GET_FUN(__glewWindowPos2svARB) +#define glWindowPos3dARB GLEW_GET_FUN(__glewWindowPos3dARB) +#define glWindowPos3dvARB GLEW_GET_FUN(__glewWindowPos3dvARB) +#define glWindowPos3fARB GLEW_GET_FUN(__glewWindowPos3fARB) +#define glWindowPos3fvARB GLEW_GET_FUN(__glewWindowPos3fvARB) +#define glWindowPos3iARB GLEW_GET_FUN(__glewWindowPos3iARB) +#define glWindowPos3ivARB GLEW_GET_FUN(__glewWindowPos3ivARB) +#define glWindowPos3sARB GLEW_GET_FUN(__glewWindowPos3sARB) +#define glWindowPos3svARB GLEW_GET_FUN(__glewWindowPos3svARB) + +#define GLEW_ARB_window_pos GLEW_GET_VAR(__GLEW_ARB_window_pos) + +#endif /* GL_ARB_window_pos */ + +/* ------------------------- GL_ATIX_point_sprites ------------------------- */ + +#ifndef GL_ATIX_point_sprites +#define GL_ATIX_point_sprites 1 + +#define GL_TEXTURE_POINT_MODE_ATIX 0x60B0 +#define GL_TEXTURE_POINT_ONE_COORD_ATIX 0x60B1 +#define GL_TEXTURE_POINT_SPRITE_ATIX 0x60B2 +#define GL_POINT_SPRITE_CULL_MODE_ATIX 0x60B3 +#define GL_POINT_SPRITE_CULL_CENTER_ATIX 0x60B4 +#define GL_POINT_SPRITE_CULL_CLIP_ATIX 0x60B5 + +#define GLEW_ATIX_point_sprites GLEW_GET_VAR(__GLEW_ATIX_point_sprites) + +#endif /* GL_ATIX_point_sprites */ + +/* ---------------------- GL_ATIX_texture_env_combine3 --------------------- */ + +#ifndef GL_ATIX_texture_env_combine3 +#define GL_ATIX_texture_env_combine3 1 + +#define GL_MODULATE_ADD_ATIX 0x8744 +#define GL_MODULATE_SIGNED_ADD_ATIX 0x8745 +#define GL_MODULATE_SUBTRACT_ATIX 0x8746 + +#define GLEW_ATIX_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATIX_texture_env_combine3) + +#endif /* GL_ATIX_texture_env_combine3 */ + +/* ----------------------- GL_ATIX_texture_env_route ----------------------- */ + +#ifndef GL_ATIX_texture_env_route +#define GL_ATIX_texture_env_route 1 + +#define GL_SECONDARY_COLOR_ATIX 0x8747 +#define GL_TEXTURE_OUTPUT_RGB_ATIX 0x8748 +#define GL_TEXTURE_OUTPUT_ALPHA_ATIX 0x8749 + +#define GLEW_ATIX_texture_env_route GLEW_GET_VAR(__GLEW_ATIX_texture_env_route) + +#endif /* GL_ATIX_texture_env_route */ + +/* ---------------- GL_ATIX_vertex_shader_output_point_size ---------------- */ + +#ifndef GL_ATIX_vertex_shader_output_point_size +#define GL_ATIX_vertex_shader_output_point_size 1 + +#define GL_OUTPUT_POINT_SIZE_ATIX 0x610E + +#define GLEW_ATIX_vertex_shader_output_point_size GLEW_GET_VAR(__GLEW_ATIX_vertex_shader_output_point_size) + +#endif /* GL_ATIX_vertex_shader_output_point_size */ + +/* -------------------------- GL_ATI_draw_buffers -------------------------- */ + +#ifndef GL_ATI_draw_buffers +#define GL_ATI_draw_buffers 1 + +#define GL_MAX_DRAW_BUFFERS_ATI 0x8824 +#define GL_DRAW_BUFFER0_ATI 0x8825 +#define GL_DRAW_BUFFER1_ATI 0x8826 +#define GL_DRAW_BUFFER2_ATI 0x8827 +#define GL_DRAW_BUFFER3_ATI 0x8828 +#define GL_DRAW_BUFFER4_ATI 0x8829 +#define GL_DRAW_BUFFER5_ATI 0x882A +#define GL_DRAW_BUFFER6_ATI 0x882B +#define GL_DRAW_BUFFER7_ATI 0x882C +#define GL_DRAW_BUFFER8_ATI 0x882D +#define GL_DRAW_BUFFER9_ATI 0x882E +#define GL_DRAW_BUFFER10_ATI 0x882F +#define GL_DRAW_BUFFER11_ATI 0x8830 +#define GL_DRAW_BUFFER12_ATI 0x8831 +#define GL_DRAW_BUFFER13_ATI 0x8832 +#define GL_DRAW_BUFFER14_ATI 0x8833 +#define GL_DRAW_BUFFER15_ATI 0x8834 + +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum* bufs); + +#define glDrawBuffersATI GLEW_GET_FUN(__glewDrawBuffersATI) + +#define GLEW_ATI_draw_buffers GLEW_GET_VAR(__GLEW_ATI_draw_buffers) + +#endif /* GL_ATI_draw_buffers */ + +/* -------------------------- GL_ATI_element_array ------------------------- */ + +#ifndef GL_ATI_element_array +#define GL_ATI_element_array 1 + +#define GL_ELEMENT_ARRAY_ATI 0x8768 +#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769 +#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A + +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count); +typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERATIPROC) (GLenum type, const void* pointer); + +#define glDrawElementArrayATI GLEW_GET_FUN(__glewDrawElementArrayATI) +#define glDrawRangeElementArrayATI GLEW_GET_FUN(__glewDrawRangeElementArrayATI) +#define glElementPointerATI GLEW_GET_FUN(__glewElementPointerATI) + +#define GLEW_ATI_element_array GLEW_GET_VAR(__GLEW_ATI_element_array) + +#endif /* GL_ATI_element_array */ + +/* ------------------------- GL_ATI_envmap_bumpmap ------------------------- */ + +#ifndef GL_ATI_envmap_bumpmap +#define GL_ATI_envmap_bumpmap 1 + +#define GL_BUMP_ROT_MATRIX_ATI 0x8775 +#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776 +#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777 +#define GL_BUMP_TEX_UNITS_ATI 0x8778 +#define GL_DUDV_ATI 0x8779 +#define GL_DU8DV8_ATI 0x877A +#define GL_BUMP_ENVMAP_ATI 0x877B +#define GL_BUMP_TARGET_ATI 0x877C + +typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param); +typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param); +typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param); +typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param); + +#define glGetTexBumpParameterfvATI GLEW_GET_FUN(__glewGetTexBumpParameterfvATI) +#define glGetTexBumpParameterivATI GLEW_GET_FUN(__glewGetTexBumpParameterivATI) +#define glTexBumpParameterfvATI GLEW_GET_FUN(__glewTexBumpParameterfvATI) +#define glTexBumpParameterivATI GLEW_GET_FUN(__glewTexBumpParameterivATI) + +#define GLEW_ATI_envmap_bumpmap GLEW_GET_VAR(__GLEW_ATI_envmap_bumpmap) + +#endif /* GL_ATI_envmap_bumpmap */ + +/* ------------------------- GL_ATI_fragment_shader ------------------------ */ + +#ifndef GL_ATI_fragment_shader +#define GL_ATI_fragment_shader 1 + +#define GL_RED_BIT_ATI 0x00000001 +#define GL_2X_BIT_ATI 0x00000001 +#define GL_4X_BIT_ATI 0x00000002 +#define GL_GREEN_BIT_ATI 0x00000002 +#define GL_COMP_BIT_ATI 0x00000002 +#define GL_BLUE_BIT_ATI 0x00000004 +#define GL_8X_BIT_ATI 0x00000004 +#define GL_NEGATE_BIT_ATI 0x00000004 +#define GL_BIAS_BIT_ATI 0x00000008 +#define GL_HALF_BIT_ATI 0x00000008 +#define GL_QUARTER_BIT_ATI 0x00000010 +#define GL_EIGHTH_BIT_ATI 0x00000020 +#define GL_SATURATE_BIT_ATI 0x00000040 +#define GL_FRAGMENT_SHADER_ATI 0x8920 +#define GL_REG_0_ATI 0x8921 +#define GL_REG_1_ATI 0x8922 +#define GL_REG_2_ATI 0x8923 +#define GL_REG_3_ATI 0x8924 +#define GL_REG_4_ATI 0x8925 +#define GL_REG_5_ATI 0x8926 +#define GL_CON_0_ATI 0x8941 +#define GL_CON_1_ATI 0x8942 +#define GL_CON_2_ATI 0x8943 +#define GL_CON_3_ATI 0x8944 +#define GL_CON_4_ATI 0x8945 +#define GL_CON_5_ATI 0x8946 +#define GL_CON_6_ATI 0x8947 +#define GL_CON_7_ATI 0x8948 +#define GL_MOV_ATI 0x8961 +#define GL_ADD_ATI 0x8963 +#define GL_MUL_ATI 0x8964 +#define GL_SUB_ATI 0x8965 +#define GL_DOT3_ATI 0x8966 +#define GL_DOT4_ATI 0x8967 +#define GL_MAD_ATI 0x8968 +#define GL_LERP_ATI 0x8969 +#define GL_CND_ATI 0x896A +#define GL_CND0_ATI 0x896B +#define GL_DOT2_ADD_ATI 0x896C +#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D +#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E +#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F +#define GL_NUM_PASSES_ATI 0x8970 +#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971 +#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972 +#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973 +#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974 +#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975 +#define GL_SWIZZLE_STR_ATI 0x8976 +#define GL_SWIZZLE_STQ_ATI 0x8977 +#define GL_SWIZZLE_STR_DR_ATI 0x8978 +#define GL_SWIZZLE_STQ_DQ_ATI 0x8979 +#define GL_SWIZZLE_STRQ_ATI 0x897A +#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B + +typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +typedef void (GLAPIENTRY * PFNGLBEGINFRAGMENTSHADERATIPROC) (void); +typedef void (GLAPIENTRY * PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +typedef void (GLAPIENTRY * PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLENDFRAGMENTSHADERATIPROC) (void); +typedef GLuint (GLAPIENTRY * PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range); +typedef void (GLAPIENTRY * PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle); +typedef void (GLAPIENTRY * PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle); +typedef void (GLAPIENTRY * PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat* value); + +#define glAlphaFragmentOp1ATI GLEW_GET_FUN(__glewAlphaFragmentOp1ATI) +#define glAlphaFragmentOp2ATI GLEW_GET_FUN(__glewAlphaFragmentOp2ATI) +#define glAlphaFragmentOp3ATI GLEW_GET_FUN(__glewAlphaFragmentOp3ATI) +#define glBeginFragmentShaderATI GLEW_GET_FUN(__glewBeginFragmentShaderATI) +#define glBindFragmentShaderATI GLEW_GET_FUN(__glewBindFragmentShaderATI) +#define glColorFragmentOp1ATI GLEW_GET_FUN(__glewColorFragmentOp1ATI) +#define glColorFragmentOp2ATI GLEW_GET_FUN(__glewColorFragmentOp2ATI) +#define glColorFragmentOp3ATI GLEW_GET_FUN(__glewColorFragmentOp3ATI) +#define glDeleteFragmentShaderATI GLEW_GET_FUN(__glewDeleteFragmentShaderATI) +#define glEndFragmentShaderATI GLEW_GET_FUN(__glewEndFragmentShaderATI) +#define glGenFragmentShadersATI GLEW_GET_FUN(__glewGenFragmentShadersATI) +#define glPassTexCoordATI GLEW_GET_FUN(__glewPassTexCoordATI) +#define glSampleMapATI GLEW_GET_FUN(__glewSampleMapATI) +#define glSetFragmentShaderConstantATI GLEW_GET_FUN(__glewSetFragmentShaderConstantATI) + +#define GLEW_ATI_fragment_shader GLEW_GET_VAR(__GLEW_ATI_fragment_shader) + +#endif /* GL_ATI_fragment_shader */ + +/* ------------------------ GL_ATI_map_object_buffer ----------------------- */ + +#ifndef GL_ATI_map_object_buffer +#define GL_ATI_map_object_buffer 1 + +typedef void* (GLAPIENTRY * PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer); + +#define glMapObjectBufferATI GLEW_GET_FUN(__glewMapObjectBufferATI) +#define glUnmapObjectBufferATI GLEW_GET_FUN(__glewUnmapObjectBufferATI) + +#define GLEW_ATI_map_object_buffer GLEW_GET_VAR(__GLEW_ATI_map_object_buffer) + +#endif /* GL_ATI_map_object_buffer */ + +/* -------------------------- GL_ATI_pn_triangles -------------------------- */ + +#ifndef GL_ATI_pn_triangles +#define GL_ATI_pn_triangles 1 + +#define GL_PN_TRIANGLES_ATI 0x87F0 +#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1 +#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2 +#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3 +#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4 +#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5 +#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6 +#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7 +#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8 + +typedef void (GLAPIENTRY * PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param); + +#define glPNTrianglesfATI GLEW_GET_FUN(__glPNTrianglewesfATI) +#define glPNTrianglesiATI GLEW_GET_FUN(__glPNTrianglewesiATI) + +#define GLEW_ATI_pn_triangles GLEW_GET_VAR(__GLEW_ATI_pn_triangles) + +#endif /* GL_ATI_pn_triangles */ + +/* ------------------------ GL_ATI_separate_stencil ------------------------ */ + +#ifndef GL_ATI_separate_stencil +#define GL_ATI_separate_stencil 1 + +#define GL_STENCIL_BACK_FUNC_ATI 0x8800 +#define GL_STENCIL_BACK_FAIL_ATI 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803 + +typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); +typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); + +#define glStencilFuncSeparateATI GLEW_GET_FUN(__glewStencilFuncSeparateATI) +#define glStencilOpSeparateATI GLEW_GET_FUN(__glewStencilOpSeparateATI) + +#define GLEW_ATI_separate_stencil GLEW_GET_VAR(__GLEW_ATI_separate_stencil) + +#endif /* GL_ATI_separate_stencil */ + +/* ----------------------- GL_ATI_shader_texture_lod ----------------------- */ + +#ifndef GL_ATI_shader_texture_lod +#define GL_ATI_shader_texture_lod 1 + +#define GLEW_ATI_shader_texture_lod GLEW_GET_VAR(__GLEW_ATI_shader_texture_lod) + +#endif /* GL_ATI_shader_texture_lod */ + +/* ---------------------- GL_ATI_text_fragment_shader ---------------------- */ + +#ifndef GL_ATI_text_fragment_shader +#define GL_ATI_text_fragment_shader 1 + +#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200 + +#define GLEW_ATI_text_fragment_shader GLEW_GET_VAR(__GLEW_ATI_text_fragment_shader) + +#endif /* GL_ATI_text_fragment_shader */ + +/* --------------------- GL_ATI_texture_compression_3dc -------------------- */ + +#ifndef GL_ATI_texture_compression_3dc +#define GL_ATI_texture_compression_3dc 1 + +#define GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI 0x8837 + +#define GLEW_ATI_texture_compression_3dc GLEW_GET_VAR(__GLEW_ATI_texture_compression_3dc) + +#endif /* GL_ATI_texture_compression_3dc */ + +/* ---------------------- GL_ATI_texture_env_combine3 ---------------------- */ + +#ifndef GL_ATI_texture_env_combine3 +#define GL_ATI_texture_env_combine3 1 + +#define GL_MODULATE_ADD_ATI 0x8744 +#define GL_MODULATE_SIGNED_ADD_ATI 0x8745 +#define GL_MODULATE_SUBTRACT_ATI 0x8746 + +#define GLEW_ATI_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATI_texture_env_combine3) + +#endif /* GL_ATI_texture_env_combine3 */ + +/* -------------------------- GL_ATI_texture_float ------------------------- */ + +#ifndef GL_ATI_texture_float +#define GL_ATI_texture_float 1 + +#define GL_RGBA_FLOAT32_ATI 0x8814 +#define GL_RGB_FLOAT32_ATI 0x8815 +#define GL_ALPHA_FLOAT32_ATI 0x8816 +#define GL_INTENSITY_FLOAT32_ATI 0x8817 +#define GL_LUMINANCE_FLOAT32_ATI 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819 +#define GL_RGBA_FLOAT16_ATI 0x881A +#define GL_RGB_FLOAT16_ATI 0x881B +#define GL_ALPHA_FLOAT16_ATI 0x881C +#define GL_INTENSITY_FLOAT16_ATI 0x881D +#define GL_LUMINANCE_FLOAT16_ATI 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F + +#define GLEW_ATI_texture_float GLEW_GET_VAR(__GLEW_ATI_texture_float) + +#endif /* GL_ATI_texture_float */ + +/* ----------------------- GL_ATI_texture_mirror_once ---------------------- */ + +#ifndef GL_ATI_texture_mirror_once +#define GL_ATI_texture_mirror_once 1 + +#define GL_MIRROR_CLAMP_ATI 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743 + +#define GLEW_ATI_texture_mirror_once GLEW_GET_VAR(__GLEW_ATI_texture_mirror_once) + +#endif /* GL_ATI_texture_mirror_once */ + +/* ----------------------- GL_ATI_vertex_array_object ---------------------- */ + +#ifndef GL_ATI_vertex_array_object +#define GL_ATI_vertex_array_object 1 + +#define GL_STATIC_ATI 0x8760 +#define GL_DYNAMIC_ATI 0x8761 +#define GL_PRESERVE_ATI 0x8762 +#define GL_DISCARD_ATI 0x8763 +#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764 +#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765 +#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766 +#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767 + +typedef void (GLAPIENTRY * PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); +typedef void (GLAPIENTRY * PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer); +typedef GLuint (GLAPIENTRY * PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const void* pointer, GLenum usage); +typedef void (GLAPIENTRY * PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const void* pointer, GLenum preserve); +typedef void (GLAPIENTRY * PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); + +#define glArrayObjectATI GLEW_GET_FUN(__glewArrayObjectATI) +#define glFreeObjectBufferATI GLEW_GET_FUN(__glewFreeObjectBufferATI) +#define glGetArrayObjectfvATI GLEW_GET_FUN(__glewGetArrayObjectfvATI) +#define glGetArrayObjectivATI GLEW_GET_FUN(__glewGetArrayObjectivATI) +#define glGetObjectBufferfvATI GLEW_GET_FUN(__glewGetObjectBufferfvATI) +#define glGetObjectBufferivATI GLEW_GET_FUN(__glewGetObjectBufferivATI) +#define glGetVariantArrayObjectfvATI GLEW_GET_FUN(__glewGetVariantArrayObjectfvATI) +#define glGetVariantArrayObjectivATI GLEW_GET_FUN(__glewGetVariantArrayObjectivATI) +#define glIsObjectBufferATI GLEW_GET_FUN(__glewIsObjectBufferATI) +#define glNewObjectBufferATI GLEW_GET_FUN(__glewNewObjectBufferATI) +#define glUpdateObjectBufferATI GLEW_GET_FUN(__glewUpdateObjectBufferATI) +#define glVariantArrayObjectATI GLEW_GET_FUN(__glewVariantArrayObjectATI) + +#define GLEW_ATI_vertex_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_array_object) + +#endif /* GL_ATI_vertex_array_object */ + +/* ------------------- GL_ATI_vertex_attrib_array_object ------------------- */ + +#ifndef GL_ATI_vertex_attrib_array_object +#define GL_ATI_vertex_attrib_array_object 1 + +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); + +#define glGetVertexAttribArrayObjectfvATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectfvATI) +#define glGetVertexAttribArrayObjectivATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectivATI) +#define glVertexAttribArrayObjectATI GLEW_GET_FUN(__glewVertexAttribArrayObjectATI) + +#define GLEW_ATI_vertex_attrib_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_attrib_array_object) + +#endif /* GL_ATI_vertex_attrib_array_object */ + +/* ------------------------- GL_ATI_vertex_streams ------------------------- */ + +#ifndef GL_ATI_vertex_streams +#define GL_ATI_vertex_streams 1 + +#define GL_MAX_VERTEX_STREAMS_ATI 0x876B +#define GL_VERTEX_SOURCE_ATI 0x876C +#define GL_VERTEX_STREAM0_ATI 0x876D +#define GL_VERTEX_STREAM1_ATI 0x876E +#define GL_VERTEX_STREAM2_ATI 0x876F +#define GL_VERTEX_STREAM3_ATI 0x8770 +#define GL_VERTEX_STREAM4_ATI 0x8771 +#define GL_VERTEX_STREAM5_ATI 0x8772 +#define GL_VERTEX_STREAM6_ATI 0x8773 +#define GL_VERTEX_STREAM7_ATI 0x8774 + +typedef void (GLAPIENTRY * PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte x, GLbyte y, GLbyte z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *v); + +#define glClientActiveVertexStreamATI GLEW_GET_FUN(__glewClientActiveVertexStreamATI) +#define glNormalStream3bATI GLEW_GET_FUN(__glewNormalStream3bATI) +#define glNormalStream3bvATI GLEW_GET_FUN(__glewNormalStream3bvATI) +#define glNormalStream3dATI GLEW_GET_FUN(__glewNormalStream3dATI) +#define glNormalStream3dvATI GLEW_GET_FUN(__glewNormalStream3dvATI) +#define glNormalStream3fATI GLEW_GET_FUN(__glewNormalStream3fATI) +#define glNormalStream3fvATI GLEW_GET_FUN(__glewNormalStream3fvATI) +#define glNormalStream3iATI GLEW_GET_FUN(__glewNormalStream3iATI) +#define glNormalStream3ivATI GLEW_GET_FUN(__glewNormalStream3ivATI) +#define glNormalStream3sATI GLEW_GET_FUN(__glewNormalStream3sATI) +#define glNormalStream3svATI GLEW_GET_FUN(__glewNormalStream3svATI) +#define glVertexBlendEnvfATI GLEW_GET_FUN(__glewVertexBlendEnvfATI) +#define glVertexBlendEnviATI GLEW_GET_FUN(__glewVertexBlendEnviATI) +#define glVertexStream2dATI GLEW_GET_FUN(__glewVertexStream2dATI) +#define glVertexStream2dvATI GLEW_GET_FUN(__glewVertexStream2dvATI) +#define glVertexStream2fATI GLEW_GET_FUN(__glewVertexStream2fATI) +#define glVertexStream2fvATI GLEW_GET_FUN(__glewVertexStream2fvATI) +#define glVertexStream2iATI GLEW_GET_FUN(__glewVertexStream2iATI) +#define glVertexStream2ivATI GLEW_GET_FUN(__glewVertexStream2ivATI) +#define glVertexStream2sATI GLEW_GET_FUN(__glewVertexStream2sATI) +#define glVertexStream2svATI GLEW_GET_FUN(__glewVertexStream2svATI) +#define glVertexStream3dATI GLEW_GET_FUN(__glewVertexStream3dATI) +#define glVertexStream3dvATI GLEW_GET_FUN(__glewVertexStream3dvATI) +#define glVertexStream3fATI GLEW_GET_FUN(__glewVertexStream3fATI) +#define glVertexStream3fvATI GLEW_GET_FUN(__glewVertexStream3fvATI) +#define glVertexStream3iATI GLEW_GET_FUN(__glewVertexStream3iATI) +#define glVertexStream3ivATI GLEW_GET_FUN(__glewVertexStream3ivATI) +#define glVertexStream3sATI GLEW_GET_FUN(__glewVertexStream3sATI) +#define glVertexStream3svATI GLEW_GET_FUN(__glewVertexStream3svATI) +#define glVertexStream4dATI GLEW_GET_FUN(__glewVertexStream4dATI) +#define glVertexStream4dvATI GLEW_GET_FUN(__glewVertexStream4dvATI) +#define glVertexStream4fATI GLEW_GET_FUN(__glewVertexStream4fATI) +#define glVertexStream4fvATI GLEW_GET_FUN(__glewVertexStream4fvATI) +#define glVertexStream4iATI GLEW_GET_FUN(__glewVertexStream4iATI) +#define glVertexStream4ivATI GLEW_GET_FUN(__glewVertexStream4ivATI) +#define glVertexStream4sATI GLEW_GET_FUN(__glewVertexStream4sATI) +#define glVertexStream4svATI GLEW_GET_FUN(__glewVertexStream4svATI) + +#define GLEW_ATI_vertex_streams GLEW_GET_VAR(__GLEW_ATI_vertex_streams) + +#endif /* GL_ATI_vertex_streams */ + +/* --------------------------- GL_EXT_422_pixels --------------------------- */ + +#ifndef GL_EXT_422_pixels +#define GL_EXT_422_pixels 1 + +#define GL_422_EXT 0x80CC +#define GL_422_REV_EXT 0x80CD +#define GL_422_AVERAGE_EXT 0x80CE +#define GL_422_REV_AVERAGE_EXT 0x80CF + +#define GLEW_EXT_422_pixels GLEW_GET_VAR(__GLEW_EXT_422_pixels) + +#endif /* GL_EXT_422_pixels */ + +/* ---------------------------- GL_EXT_Cg_shader --------------------------- */ + +#ifndef GL_EXT_Cg_shader +#define GL_EXT_Cg_shader 1 + +#define GL_CG_VERTEX_SHADER_EXT 0x890E +#define GL_CG_FRAGMENT_SHADER_EXT 0x890F + +#define GLEW_EXT_Cg_shader GLEW_GET_VAR(__GLEW_EXT_Cg_shader) + +#endif /* GL_EXT_Cg_shader */ + +/* ------------------------------ GL_EXT_abgr ------------------------------ */ + +#ifndef GL_EXT_abgr +#define GL_EXT_abgr 1 + +#define GL_ABGR_EXT 0x8000 + +#define GLEW_EXT_abgr GLEW_GET_VAR(__GLEW_EXT_abgr) + +#endif /* GL_EXT_abgr */ + +/* ------------------------------ GL_EXT_bgra ------------------------------ */ + +#ifndef GL_EXT_bgra +#define GL_EXT_bgra 1 + +#define GL_BGR_EXT 0x80E0 +#define GL_BGRA_EXT 0x80E1 + +#define GLEW_EXT_bgra GLEW_GET_VAR(__GLEW_EXT_bgra) + +#endif /* GL_EXT_bgra */ + +/* ------------------------ GL_EXT_bindable_uniform ------------------------ */ + +#ifndef GL_EXT_bindable_uniform +#define GL_EXT_bindable_uniform 1 + +#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2 +#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3 +#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4 +#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED +#define GL_UNIFORM_BUFFER_EXT 0x8DEE +#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF + +typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location); +typedef GLintptr (GLAPIENTRY * PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location); +typedef void (GLAPIENTRY * PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer); + +#define glGetUniformBufferSizeEXT GLEW_GET_FUN(__glewGetUniformBufferSizeEXT) +#define glGetUniformOffsetEXT GLEW_GET_FUN(__glewGetUniformOffsetEXT) +#define glUniformBufferEXT GLEW_GET_FUN(__glewUniformBufferEXT) + +#define GLEW_EXT_bindable_uniform GLEW_GET_VAR(__GLEW_EXT_bindable_uniform) + +#endif /* GL_EXT_bindable_uniform */ + +/* --------------------------- GL_EXT_blend_color -------------------------- */ + +#ifndef GL_EXT_blend_color +#define GL_EXT_blend_color 1 + +#define GL_CONSTANT_COLOR_EXT 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 +#define GL_CONSTANT_ALPHA_EXT 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 +#define GL_BLEND_COLOR_EXT 0x8005 + +typedef void (GLAPIENTRY * PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + +#define glBlendColorEXT GLEW_GET_FUN(__glewBlendColorEXT) + +#define GLEW_EXT_blend_color GLEW_GET_VAR(__GLEW_EXT_blend_color) + +#endif /* GL_EXT_blend_color */ + +/* --------------------- GL_EXT_blend_equation_separate -------------------- */ + +#ifndef GL_EXT_blend_equation_separate +#define GL_EXT_blend_equation_separate 1 + +#define GL_BLEND_EQUATION_RGB_EXT 0x8009 +#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha); + +#define glBlendEquationSeparateEXT GLEW_GET_FUN(__glewBlendEquationSeparateEXT) + +#define GLEW_EXT_blend_equation_separate GLEW_GET_VAR(__GLEW_EXT_blend_equation_separate) + +#endif /* GL_EXT_blend_equation_separate */ + +/* ----------------------- GL_EXT_blend_func_separate ---------------------- */ + +#ifndef GL_EXT_blend_func_separate +#define GL_EXT_blend_func_separate 1 + +#define GL_BLEND_DST_RGB_EXT 0x80C8 +#define GL_BLEND_SRC_RGB_EXT 0x80C9 +#define GL_BLEND_DST_ALPHA_EXT 0x80CA +#define GL_BLEND_SRC_ALPHA_EXT 0x80CB + +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + +#define glBlendFuncSeparateEXT GLEW_GET_FUN(__glewBlendFuncSeparateEXT) + +#define GLEW_EXT_blend_func_separate GLEW_GET_VAR(__GLEW_EXT_blend_func_separate) + +#endif /* GL_EXT_blend_func_separate */ + +/* ------------------------- GL_EXT_blend_logic_op ------------------------- */ + +#ifndef GL_EXT_blend_logic_op +#define GL_EXT_blend_logic_op 1 + +#define GLEW_EXT_blend_logic_op GLEW_GET_VAR(__GLEW_EXT_blend_logic_op) + +#endif /* GL_EXT_blend_logic_op */ + +/* -------------------------- GL_EXT_blend_minmax -------------------------- */ + +#ifndef GL_EXT_blend_minmax +#define GL_EXT_blend_minmax 1 + +#define GL_FUNC_ADD_EXT 0x8006 +#define GL_MIN_EXT 0x8007 +#define GL_MAX_EXT 0x8008 +#define GL_BLEND_EQUATION_EXT 0x8009 + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode); + +#define glBlendEquationEXT GLEW_GET_FUN(__glewBlendEquationEXT) + +#define GLEW_EXT_blend_minmax GLEW_GET_VAR(__GLEW_EXT_blend_minmax) + +#endif /* GL_EXT_blend_minmax */ + +/* ------------------------- GL_EXT_blend_subtract ------------------------- */ + +#ifndef GL_EXT_blend_subtract +#define GL_EXT_blend_subtract 1 + +#define GL_FUNC_SUBTRACT_EXT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B + +#define GLEW_EXT_blend_subtract GLEW_GET_VAR(__GLEW_EXT_blend_subtract) + +#endif /* GL_EXT_blend_subtract */ + +/* ------------------------ GL_EXT_clip_volume_hint ------------------------ */ + +#ifndef GL_EXT_clip_volume_hint +#define GL_EXT_clip_volume_hint 1 + +#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0 + +#define GLEW_EXT_clip_volume_hint GLEW_GET_VAR(__GLEW_EXT_clip_volume_hint) + +#endif /* GL_EXT_clip_volume_hint */ + +/* ------------------------------ GL_EXT_cmyka ----------------------------- */ + +#ifndef GL_EXT_cmyka +#define GL_EXT_cmyka 1 + +#define GL_CMYK_EXT 0x800C +#define GL_CMYKA_EXT 0x800D +#define GL_PACK_CMYK_HINT_EXT 0x800E +#define GL_UNPACK_CMYK_HINT_EXT 0x800F + +#define GLEW_EXT_cmyka GLEW_GET_VAR(__GLEW_EXT_cmyka) + +#endif /* GL_EXT_cmyka */ + +/* ------------------------- GL_EXT_color_subtable ------------------------- */ + +#ifndef GL_EXT_color_subtable +#define GL_EXT_color_subtable 1 + +typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void* data); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); + +#define glColorSubTableEXT GLEW_GET_FUN(__glewColorSubTableEXT) +#define glCopyColorSubTableEXT GLEW_GET_FUN(__glewCopyColorSubTableEXT) + +#define GLEW_EXT_color_subtable GLEW_GET_VAR(__GLEW_EXT_color_subtable) + +#endif /* GL_EXT_color_subtable */ + +/* ---------------------- GL_EXT_compiled_vertex_array --------------------- */ + +#ifndef GL_EXT_compiled_vertex_array +#define GL_EXT_compiled_vertex_array 1 + +#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8 +#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9 + +typedef void (GLAPIENTRY * PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void); + +#define glLockArraysEXT GLEW_GET_FUN(__glewLockArraysEXT) +#define glUnlockArraysEXT GLEW_GET_FUN(__glewUnlockArraysEXT) + +#define GLEW_EXT_compiled_vertex_array GLEW_GET_VAR(__GLEW_EXT_compiled_vertex_array) + +#endif /* GL_EXT_compiled_vertex_array */ + +/* --------------------------- GL_EXT_convolution -------------------------- */ + +#ifndef GL_EXT_convolution +#define GL_EXT_convolution 1 + +#define GL_CONVOLUTION_1D_EXT 0x8010 +#define GL_CONVOLUTION_2D_EXT 0x8011 +#define GL_SEPARABLE_2D_EXT 0x8012 +#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015 +#define GL_REDUCE_EXT 0x8016 +#define GL_CONVOLUTION_FORMAT_EXT 0x8017 +#define GL_CONVOLUTION_WIDTH_EXT 0x8018 +#define GL_CONVOLUTION_HEIGHT_EXT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 + +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* image); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* row, void* column, void* span); +typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* row, const void* column); + +#define glConvolutionFilter1DEXT GLEW_GET_FUN(__glewConvolutionFilter1DEXT) +#define glConvolutionFilter2DEXT GLEW_GET_FUN(__glewConvolutionFilter2DEXT) +#define glConvolutionParameterfEXT GLEW_GET_FUN(__glewConvolutionParameterfEXT) +#define glConvolutionParameterfvEXT GLEW_GET_FUN(__glewConvolutionParameterfvEXT) +#define glConvolutionParameteriEXT GLEW_GET_FUN(__glewConvolutionParameteriEXT) +#define glConvolutionParameterivEXT GLEW_GET_FUN(__glewConvolutionParameterivEXT) +#define glCopyConvolutionFilter1DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter1DEXT) +#define glCopyConvolutionFilter2DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter2DEXT) +#define glGetConvolutionFilterEXT GLEW_GET_FUN(__glewGetConvolutionFilterEXT) +#define glGetConvolutionParameterfvEXT GLEW_GET_FUN(__glewGetConvolutionParameterfvEXT) +#define glGetConvolutionParameterivEXT GLEW_GET_FUN(__glewGetConvolutionParameterivEXT) +#define glGetSeparableFilterEXT GLEW_GET_FUN(__glewGetSeparableFilterEXT) +#define glSeparableFilter2DEXT GLEW_GET_FUN(__glewSeparableFilter2DEXT) + +#define GLEW_EXT_convolution GLEW_GET_VAR(__GLEW_EXT_convolution) + +#endif /* GL_EXT_convolution */ + +/* ------------------------ GL_EXT_coordinate_frame ------------------------ */ + +#ifndef GL_EXT_coordinate_frame +#define GL_EXT_coordinate_frame 1 + +#define GL_TANGENT_ARRAY_EXT 0x8439 +#define GL_BINORMAL_ARRAY_EXT 0x843A +#define GL_CURRENT_TANGENT_EXT 0x843B +#define GL_CURRENT_BINORMAL_EXT 0x843C +#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E +#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F +#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440 +#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441 +#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442 +#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443 +#define GL_MAP1_TANGENT_EXT 0x8444 +#define GL_MAP2_TANGENT_EXT 0x8445 +#define GL_MAP1_BINORMAL_EXT 0x8446 +#define GL_MAP2_BINORMAL_EXT 0x8447 + +typedef void (GLAPIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer); +typedef void (GLAPIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer); + +#define glBinormalPointerEXT GLEW_GET_FUN(__glewBinormalPointerEXT) +#define glTangentPointerEXT GLEW_GET_FUN(__glewTangentPointerEXT) + +#define GLEW_EXT_coordinate_frame GLEW_GET_VAR(__GLEW_EXT_coordinate_frame) + +#endif /* GL_EXT_coordinate_frame */ + +/* -------------------------- GL_EXT_copy_texture -------------------------- */ + +#ifndef GL_EXT_copy_texture +#define GL_EXT_copy_texture 1 + +typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + +#define glCopyTexImage1DEXT GLEW_GET_FUN(__glewCopyTexImage1DEXT) +#define glCopyTexImage2DEXT GLEW_GET_FUN(__glewCopyTexImage2DEXT) +#define glCopyTexSubImage1DEXT GLEW_GET_FUN(__glewCopyTexSubImage1DEXT) +#define glCopyTexSubImage2DEXT GLEW_GET_FUN(__glewCopyTexSubImage2DEXT) +#define glCopyTexSubImage3DEXT GLEW_GET_FUN(__glewCopyTexSubImage3DEXT) + +#define GLEW_EXT_copy_texture GLEW_GET_VAR(__GLEW_EXT_copy_texture) + +#endif /* GL_EXT_copy_texture */ + +/* --------------------------- GL_EXT_cull_vertex -------------------------- */ + +#ifndef GL_EXT_cull_vertex +#define GL_EXT_cull_vertex 1 + +typedef void (GLAPIENTRY * PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat* params); + +#define glCullParameterdvEXT GLEW_GET_FUN(__glewCullParameterdvEXT) +#define glCullParameterfvEXT GLEW_GET_FUN(__glewCullParameterfvEXT) + +#define GLEW_EXT_cull_vertex GLEW_GET_VAR(__GLEW_EXT_cull_vertex) + +#endif /* GL_EXT_cull_vertex */ + +/* ------------------------ GL_EXT_depth_bounds_test ----------------------- */ + +#ifndef GL_EXT_depth_bounds_test +#define GL_EXT_depth_bounds_test 1 + +#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890 +#define GL_DEPTH_BOUNDS_EXT 0x8891 + +typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax); + +#define glDepthBoundsEXT GLEW_GET_FUN(__glewDepthBoundsEXT) + +#define GLEW_EXT_depth_bounds_test GLEW_GET_VAR(__GLEW_EXT_depth_bounds_test) + +#endif /* GL_EXT_depth_bounds_test */ + +/* ----------------------- GL_EXT_direct_state_access ---------------------- */ + +#ifndef GL_EXT_direct_state_access +#define GL_EXT_direct_state_access 1 + +#define GL_PROGRAM_MATRIX_EXT 0x8E2D +#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E +#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F + +typedef void (GLAPIENTRY * PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture); +typedef GLenum (GLAPIENTRY * PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target); +typedef void (GLAPIENTRY * PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuffer, GLsizei n, const GLenum* bufs); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); +typedef void (GLAPIENTRY * PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target); +typedef void (GLAPIENTRY * PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, void* img); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, void* img); +typedef void (GLAPIENTRY * PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum pname, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum pname, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint* param); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void* pixels); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, void** params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void* data); +typedef void (GLAPIENTRY * PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, void* string); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum pname, GLuint index, GLvoid** params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void* pixels); +typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access); +typedef void (GLAPIENTRY * PFNGLMATRIXFRUSTUMEXTPROC) (GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum matrixMode); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXORTHOEXTPROC) (GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f); +typedef void (GLAPIENTRY * PFNGLMATRIXPOPEXTPROC) (GLenum matrixMode); +typedef void (GLAPIENTRY * PFNGLMATRIXPUSHEXTPROC) (GLenum matrixMode); +typedef void (GLAPIENTRY * PFNGLMATRIXROTATEDEXTPROC) (GLenum matrixMode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLMATRIXROTATEFEXTPROC) (GLenum matrixMode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLMATRIXSCALEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLMATRIXSCALEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENDEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble param); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* param); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* param); +typedef void (GLAPIENTRY * PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const void* data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void* data); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const void* string); +typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); +typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLfloat* param); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* param); +typedef void (GLAPIENTRY * PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); +typedef GLboolean (GLAPIENTRY * PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer); + +#define glBindMultiTextureEXT GLEW_GET_FUN(__glewBindMultiTextureEXT) +#define glCheckNamedFramebufferStatusEXT GLEW_GET_FUN(__glewCheckNamedFramebufferStatusEXT) +#define glClientAttribDefaultEXT GLEW_GET_FUN(__glewClientAttribDefaultEXT) +#define glCompressedMultiTexImage1DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage1DEXT) +#define glCompressedMultiTexImage2DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage2DEXT) +#define glCompressedMultiTexImage3DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage3DEXT) +#define glCompressedMultiTexSubImage1DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage1DEXT) +#define glCompressedMultiTexSubImage2DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage2DEXT) +#define glCompressedMultiTexSubImage3DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage3DEXT) +#define glCompressedTextureImage1DEXT GLEW_GET_FUN(__glewCompressedTextureImage1DEXT) +#define glCompressedTextureImage2DEXT GLEW_GET_FUN(__glewCompressedTextureImage2DEXT) +#define glCompressedTextureImage3DEXT GLEW_GET_FUN(__glewCompressedTextureImage3DEXT) +#define glCompressedTextureSubImage1DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage1DEXT) +#define glCompressedTextureSubImage2DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage2DEXT) +#define glCompressedTextureSubImage3DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage3DEXT) +#define glCopyMultiTexImage1DEXT GLEW_GET_FUN(__glewCopyMultiTexImage1DEXT) +#define glCopyMultiTexImage2DEXT GLEW_GET_FUN(__glewCopyMultiTexImage2DEXT) +#define glCopyMultiTexSubImage1DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage1DEXT) +#define glCopyMultiTexSubImage2DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage2DEXT) +#define glCopyMultiTexSubImage3DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage3DEXT) +#define glCopyTextureImage1DEXT GLEW_GET_FUN(__glewCopyTextureImage1DEXT) +#define glCopyTextureImage2DEXT GLEW_GET_FUN(__glewCopyTextureImage2DEXT) +#define glCopyTextureSubImage1DEXT GLEW_GET_FUN(__glewCopyTextureSubImage1DEXT) +#define glCopyTextureSubImage2DEXT GLEW_GET_FUN(__glewCopyTextureSubImage2DEXT) +#define glCopyTextureSubImage3DEXT GLEW_GET_FUN(__glewCopyTextureSubImage3DEXT) +#define glDisableClientStateIndexedEXT GLEW_GET_FUN(__glewDisableClientStateIndexedEXT) +#define glEnableClientStateIndexedEXT GLEW_GET_FUN(__glewEnableClientStateIndexedEXT) +#define glFramebufferDrawBufferEXT GLEW_GET_FUN(__glewFramebufferDrawBufferEXT) +#define glFramebufferDrawBuffersEXT GLEW_GET_FUN(__glewFramebufferDrawBuffersEXT) +#define glFramebufferReadBufferEXT GLEW_GET_FUN(__glewFramebufferReadBufferEXT) +#define glGenerateMultiTexMipmapEXT GLEW_GET_FUN(__glewGenerateMultiTexMipmapEXT) +#define glGenerateTextureMipmapEXT GLEW_GET_FUN(__glewGenerateTextureMipmapEXT) +#define glGetCompressedMultiTexImageEXT GLEW_GET_FUN(__glewGetCompressedMultiTexImageEXT) +#define glGetCompressedTextureImageEXT GLEW_GET_FUN(__glewGetCompressedTextureImageEXT) +#define glGetDoubleIndexedvEXT GLEW_GET_FUN(__glewGetDoubleIndexedvEXT) +#define glGetFloatIndexedvEXT GLEW_GET_FUN(__glewGetFloatIndexedvEXT) +#define glGetFramebufferParameterivEXT GLEW_GET_FUN(__glewGetFramebufferParameterivEXT) +#define glGetMultiTexEnvfvEXT GLEW_GET_FUN(__glewGetMultiTexEnvfvEXT) +#define glGetMultiTexEnvivEXT GLEW_GET_FUN(__glewGetMultiTexEnvivEXT) +#define glGetMultiTexGendvEXT GLEW_GET_FUN(__glewGetMultiTexGendvEXT) +#define glGetMultiTexGenfvEXT GLEW_GET_FUN(__glewGetMultiTexGenfvEXT) +#define glGetMultiTexGenivEXT GLEW_GET_FUN(__glewGetMultiTexGenivEXT) +#define glGetMultiTexImageEXT GLEW_GET_FUN(__glewGetMultiTexImageEXT) +#define glGetMultiTexLevelParameterfvEXT GLEW_GET_FUN(__glewGetMultiTexLevelParameterfvEXT) +#define glGetMultiTexLevelParameterivEXT GLEW_GET_FUN(__glewGetMultiTexLevelParameterivEXT) +#define glGetMultiTexParameterIivEXT GLEW_GET_FUN(__glewGetMultiTexParameterIivEXT) +#define glGetMultiTexParameterIuivEXT GLEW_GET_FUN(__glewGetMultiTexParameterIuivEXT) +#define glGetMultiTexParameterfvEXT GLEW_GET_FUN(__glewGetMultiTexParameterfvEXT) +#define glGetMultiTexParameterivEXT GLEW_GET_FUN(__glewGetMultiTexParameterivEXT) +#define glGetNamedBufferParameterivEXT GLEW_GET_FUN(__glewGetNamedBufferParameterivEXT) +#define glGetNamedBufferPointervEXT GLEW_GET_FUN(__glewGetNamedBufferPointervEXT) +#define glGetNamedBufferSubDataEXT GLEW_GET_FUN(__glewGetNamedBufferSubDataEXT) +#define glGetNamedFramebufferAttachmentParameterivEXT GLEW_GET_FUN(__glewGetNamedFramebufferAttachmentParameterivEXT) +#define glGetNamedProgramLocalParameterIivEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterIivEXT) +#define glGetNamedProgramLocalParameterIuivEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterIuivEXT) +#define glGetNamedProgramLocalParameterdvEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterdvEXT) +#define glGetNamedProgramLocalParameterfvEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterfvEXT) +#define glGetNamedProgramStringEXT GLEW_GET_FUN(__glewGetNamedProgramStringEXT) +#define glGetNamedProgramivEXT GLEW_GET_FUN(__glewGetNamedProgramivEXT) +#define glGetNamedRenderbufferParameterivEXT GLEW_GET_FUN(__glewGetNamedRenderbufferParameterivEXT) +#define glGetPointerIndexedvEXT GLEW_GET_FUN(__glewGetPointerIndexedvEXT) +#define glGetTextureImageEXT GLEW_GET_FUN(__glewGetTextureImageEXT) +#define glGetTextureLevelParameterfvEXT GLEW_GET_FUN(__glewGetTextureLevelParameterfvEXT) +#define glGetTextureLevelParameterivEXT GLEW_GET_FUN(__glewGetTextureLevelParameterivEXT) +#define glGetTextureParameterIivEXT GLEW_GET_FUN(__glewGetTextureParameterIivEXT) +#define glGetTextureParameterIuivEXT GLEW_GET_FUN(__glewGetTextureParameterIuivEXT) +#define glGetTextureParameterfvEXT GLEW_GET_FUN(__glewGetTextureParameterfvEXT) +#define glGetTextureParameterivEXT GLEW_GET_FUN(__glewGetTextureParameterivEXT) +#define glMapNamedBufferEXT GLEW_GET_FUN(__glewMapNamedBufferEXT) +#define glMatrixFrustumEXT GLEW_GET_FUN(__glewMatrixFrustumEXT) +#define glMatrixLoadIdentityEXT GLEW_GET_FUN(__glewMatrixLoadIdentityEXT) +#define glMatrixLoadTransposedEXT GLEW_GET_FUN(__glewMatrixLoadTransposedEXT) +#define glMatrixLoadTransposefEXT GLEW_GET_FUN(__glewMatrixLoadTransposefEXT) +#define glMatrixLoaddEXT GLEW_GET_FUN(__glewMatrixLoaddEXT) +#define glMatrixLoadfEXT GLEW_GET_FUN(__glewMatrixLoadfEXT) +#define glMatrixMultTransposedEXT GLEW_GET_FUN(__glewMatrixMultTransposedEXT) +#define glMatrixMultTransposefEXT GLEW_GET_FUN(__glewMatrixMultTransposefEXT) +#define glMatrixMultdEXT GLEW_GET_FUN(__glewMatrixMultdEXT) +#define glMatrixMultfEXT GLEW_GET_FUN(__glewMatrixMultfEXT) +#define glMatrixOrthoEXT GLEW_GET_FUN(__glewMatrixOrthoEXT) +#define glMatrixPopEXT GLEW_GET_FUN(__glewMatrixPopEXT) +#define glMatrixPushEXT GLEW_GET_FUN(__glewMatrixPushEXT) +#define glMatrixRotatedEXT GLEW_GET_FUN(__glewMatrixRotatedEXT) +#define glMatrixRotatefEXT GLEW_GET_FUN(__glewMatrixRotatefEXT) +#define glMatrixScaledEXT GLEW_GET_FUN(__glewMatrixScaledEXT) +#define glMatrixScalefEXT GLEW_GET_FUN(__glewMatrixScalefEXT) +#define glMatrixTranslatedEXT GLEW_GET_FUN(__glewMatrixTranslatedEXT) +#define glMatrixTranslatefEXT GLEW_GET_FUN(__glewMatrixTranslatefEXT) +#define glMultiTexBufferEXT GLEW_GET_FUN(__glewMultiTexBufferEXT) +#define glMultiTexCoordPointerEXT GLEW_GET_FUN(__glewMultiTexCoordPointerEXT) +#define glMultiTexEnvfEXT GLEW_GET_FUN(__glewMultiTexEnvfEXT) +#define glMultiTexEnvfvEXT GLEW_GET_FUN(__glewMultiTexEnvfvEXT) +#define glMultiTexEnviEXT GLEW_GET_FUN(__glewMultiTexEnviEXT) +#define glMultiTexEnvivEXT GLEW_GET_FUN(__glewMultiTexEnvivEXT) +#define glMultiTexGendEXT GLEW_GET_FUN(__glewMultiTexGendEXT) +#define glMultiTexGendvEXT GLEW_GET_FUN(__glewMultiTexGendvEXT) +#define glMultiTexGenfEXT GLEW_GET_FUN(__glewMultiTexGenfEXT) +#define glMultiTexGenfvEXT GLEW_GET_FUN(__glewMultiTexGenfvEXT) +#define glMultiTexGeniEXT GLEW_GET_FUN(__glewMultiTexGeniEXT) +#define glMultiTexGenivEXT GLEW_GET_FUN(__glewMultiTexGenivEXT) +#define glMultiTexImage1DEXT GLEW_GET_FUN(__glewMultiTexImage1DEXT) +#define glMultiTexImage2DEXT GLEW_GET_FUN(__glewMultiTexImage2DEXT) +#define glMultiTexImage3DEXT GLEW_GET_FUN(__glewMultiTexImage3DEXT) +#define glMultiTexParameterIivEXT GLEW_GET_FUN(__glewMultiTexParameterIivEXT) +#define glMultiTexParameterIuivEXT GLEW_GET_FUN(__glewMultiTexParameterIuivEXT) +#define glMultiTexParameterfEXT GLEW_GET_FUN(__glewMultiTexParameterfEXT) +#define glMultiTexParameterfvEXT GLEW_GET_FUN(__glewMultiTexParameterfvEXT) +#define glMultiTexParameteriEXT GLEW_GET_FUN(__glewMultiTexParameteriEXT) +#define glMultiTexParameterivEXT GLEW_GET_FUN(__glewMultiTexParameterivEXT) +#define glMultiTexRenderbufferEXT GLEW_GET_FUN(__glewMultiTexRenderbufferEXT) +#define glMultiTexSubImage1DEXT GLEW_GET_FUN(__glewMultiTexSubImage1DEXT) +#define glMultiTexSubImage2DEXT GLEW_GET_FUN(__glewMultiTexSubImage2DEXT) +#define glMultiTexSubImage3DEXT GLEW_GET_FUN(__glewMultiTexSubImage3DEXT) +#define glNamedBufferDataEXT GLEW_GET_FUN(__glewNamedBufferDataEXT) +#define glNamedBufferSubDataEXT GLEW_GET_FUN(__glewNamedBufferSubDataEXT) +#define glNamedFramebufferRenderbufferEXT GLEW_GET_FUN(__glewNamedFramebufferRenderbufferEXT) +#define glNamedFramebufferTexture1DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture1DEXT) +#define glNamedFramebufferTexture2DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture2DEXT) +#define glNamedFramebufferTexture3DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture3DEXT) +#define glNamedFramebufferTextureEXT GLEW_GET_FUN(__glewNamedFramebufferTextureEXT) +#define glNamedFramebufferTextureFaceEXT GLEW_GET_FUN(__glewNamedFramebufferTextureFaceEXT) +#define glNamedFramebufferTextureLayerEXT GLEW_GET_FUN(__glewNamedFramebufferTextureLayerEXT) +#define glNamedProgramLocalParameter4dEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4dEXT) +#define glNamedProgramLocalParameter4dvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4dvEXT) +#define glNamedProgramLocalParameter4fEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4fEXT) +#define glNamedProgramLocalParameter4fvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4fvEXT) +#define glNamedProgramLocalParameterI4iEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4iEXT) +#define glNamedProgramLocalParameterI4ivEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4ivEXT) +#define glNamedProgramLocalParameterI4uiEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4uiEXT) +#define glNamedProgramLocalParameterI4uivEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4uivEXT) +#define glNamedProgramLocalParameters4fvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameters4fvEXT) +#define glNamedProgramLocalParametersI4ivEXT GLEW_GET_FUN(__glewNamedProgramLocalParametersI4ivEXT) +#define glNamedProgramLocalParametersI4uivEXT GLEW_GET_FUN(__glewNamedProgramLocalParametersI4uivEXT) +#define glNamedProgramStringEXT GLEW_GET_FUN(__glewNamedProgramStringEXT) +#define glNamedRenderbufferStorageEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageEXT) +#define glNamedRenderbufferStorageMultisampleCoverageEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageMultisampleCoverageEXT) +#define glNamedRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageMultisampleEXT) +#define glProgramUniform1fEXT GLEW_GET_FUN(__glewProgramUniform1fEXT) +#define glProgramUniform1fvEXT GLEW_GET_FUN(__glewProgramUniform1fvEXT) +#define glProgramUniform1iEXT GLEW_GET_FUN(__glewProgramUniform1iEXT) +#define glProgramUniform1ivEXT GLEW_GET_FUN(__glewProgramUniform1ivEXT) +#define glProgramUniform1uiEXT GLEW_GET_FUN(__glewProgramUniform1uiEXT) +#define glProgramUniform1uivEXT GLEW_GET_FUN(__glewProgramUniform1uivEXT) +#define glProgramUniform2fEXT GLEW_GET_FUN(__glewProgramUniform2fEXT) +#define glProgramUniform2fvEXT GLEW_GET_FUN(__glewProgramUniform2fvEXT) +#define glProgramUniform2iEXT GLEW_GET_FUN(__glewProgramUniform2iEXT) +#define glProgramUniform2ivEXT GLEW_GET_FUN(__glewProgramUniform2ivEXT) +#define glProgramUniform2uiEXT GLEW_GET_FUN(__glewProgramUniform2uiEXT) +#define glProgramUniform2uivEXT GLEW_GET_FUN(__glewProgramUniform2uivEXT) +#define glProgramUniform3fEXT GLEW_GET_FUN(__glewProgramUniform3fEXT) +#define glProgramUniform3fvEXT GLEW_GET_FUN(__glewProgramUniform3fvEXT) +#define glProgramUniform3iEXT GLEW_GET_FUN(__glewProgramUniform3iEXT) +#define glProgramUniform3ivEXT GLEW_GET_FUN(__glewProgramUniform3ivEXT) +#define glProgramUniform3uiEXT GLEW_GET_FUN(__glewProgramUniform3uiEXT) +#define glProgramUniform3uivEXT GLEW_GET_FUN(__glewProgramUniform3uivEXT) +#define glProgramUniform4fEXT GLEW_GET_FUN(__glewProgramUniform4fEXT) +#define glProgramUniform4fvEXT GLEW_GET_FUN(__glewProgramUniform4fvEXT) +#define glProgramUniform4iEXT GLEW_GET_FUN(__glewProgramUniform4iEXT) +#define glProgramUniform4ivEXT GLEW_GET_FUN(__glewProgramUniform4ivEXT) +#define glProgramUniform4uiEXT GLEW_GET_FUN(__glewProgramUniform4uiEXT) +#define glProgramUniform4uivEXT GLEW_GET_FUN(__glewProgramUniform4uivEXT) +#define glProgramUniformMatrix2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2fvEXT) +#define glProgramUniformMatrix2x3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x3fvEXT) +#define glProgramUniformMatrix2x4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x4fvEXT) +#define glProgramUniformMatrix3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3fvEXT) +#define glProgramUniformMatrix3x2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x2fvEXT) +#define glProgramUniformMatrix3x4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x4fvEXT) +#define glProgramUniformMatrix4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4fvEXT) +#define glProgramUniformMatrix4x2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x2fvEXT) +#define glProgramUniformMatrix4x3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x3fvEXT) +#define glPushClientAttribDefaultEXT GLEW_GET_FUN(__glewPushClientAttribDefaultEXT) +#define glTextureBufferEXT GLEW_GET_FUN(__glewTextureBufferEXT) +#define glTextureImage1DEXT GLEW_GET_FUN(__glewTextureImage1DEXT) +#define glTextureImage2DEXT GLEW_GET_FUN(__glewTextureImage2DEXT) +#define glTextureImage3DEXT GLEW_GET_FUN(__glewTextureImage3DEXT) +#define glTextureParameterIivEXT GLEW_GET_FUN(__glewTextureParameterIivEXT) +#define glTextureParameterIuivEXT GLEW_GET_FUN(__glewTextureParameterIuivEXT) +#define glTextureParameterfEXT GLEW_GET_FUN(__glewTextureParameterfEXT) +#define glTextureParameterfvEXT GLEW_GET_FUN(__glewTextureParameterfvEXT) +#define glTextureParameteriEXT GLEW_GET_FUN(__glewTextureParameteriEXT) +#define glTextureParameterivEXT GLEW_GET_FUN(__glewTextureParameterivEXT) +#define glTextureRenderbufferEXT GLEW_GET_FUN(__glewTextureRenderbufferEXT) +#define glTextureSubImage1DEXT GLEW_GET_FUN(__glewTextureSubImage1DEXT) +#define glTextureSubImage2DEXT GLEW_GET_FUN(__glewTextureSubImage2DEXT) +#define glTextureSubImage3DEXT GLEW_GET_FUN(__glewTextureSubImage3DEXT) +#define glUnmapNamedBufferEXT GLEW_GET_FUN(__glewUnmapNamedBufferEXT) + +#define GLEW_EXT_direct_state_access GLEW_GET_VAR(__GLEW_EXT_direct_state_access) + +#endif /* GL_EXT_direct_state_access */ + +/* -------------------------- GL_EXT_draw_buffers2 ------------------------- */ + +#ifndef GL_EXT_draw_buffers2 +#define GL_EXT_draw_buffers2 1 + +typedef void (GLAPIENTRY * PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint buf, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef void (GLAPIENTRY * PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef void (GLAPIENTRY * PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum value, GLuint index, GLboolean* data); +typedef void (GLAPIENTRY * PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum value, GLuint index, GLint* data); +typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index); + +#define glColorMaskIndexedEXT GLEW_GET_FUN(__glewColorMaskIndexedEXT) +#define glDisableIndexedEXT GLEW_GET_FUN(__glewDisableIndexedEXT) +#define glEnableIndexedEXT GLEW_GET_FUN(__glewEnableIndexedEXT) +#define glGetBooleanIndexedvEXT GLEW_GET_FUN(__glewGetBooleanIndexedvEXT) +#define glGetIntegerIndexedvEXT GLEW_GET_FUN(__glewGetIntegerIndexedvEXT) +#define glIsEnabledIndexedEXT GLEW_GET_FUN(__glewIsEnabledIndexedEXT) + +#define GLEW_EXT_draw_buffers2 GLEW_GET_VAR(__GLEW_EXT_draw_buffers2) + +#endif /* GL_EXT_draw_buffers2 */ + +/* ------------------------- GL_EXT_draw_instanced ------------------------- */ + +#ifndef GL_EXT_draw_instanced +#define GL_EXT_draw_instanced 1 + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); + +#define glDrawArraysInstancedEXT GLEW_GET_FUN(__glewDrawArraysInstancedEXT) +#define glDrawElementsInstancedEXT GLEW_GET_FUN(__glewDrawElementsInstancedEXT) + +#define GLEW_EXT_draw_instanced GLEW_GET_VAR(__GLEW_EXT_draw_instanced) + +#endif /* GL_EXT_draw_instanced */ + +/* ----------------------- GL_EXT_draw_range_elements ---------------------- */ + +#ifndef GL_EXT_draw_range_elements +#define GL_EXT_draw_range_elements 1 + +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 + +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); + +#define glDrawRangeElementsEXT GLEW_GET_FUN(__glewDrawRangeElementsEXT) + +#define GLEW_EXT_draw_range_elements GLEW_GET_VAR(__GLEW_EXT_draw_range_elements) + +#endif /* GL_EXT_draw_range_elements */ + +/* ---------------------------- GL_EXT_fog_coord --------------------------- */ + +#ifndef GL_EXT_fog_coord +#define GL_EXT_fog_coord 1 + +#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 +#define GL_FOG_COORDINATE_EXT 0x8451 +#define GL_FRAGMENT_DEPTH_EXT 0x8452 +#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 +#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 + +typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDEXTPROC) (GLdouble coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFEXTPROC) (GLfloat coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord); + +#define glFogCoordPointerEXT GLEW_GET_FUN(__glewFogCoordPointerEXT) +#define glFogCoorddEXT GLEW_GET_FUN(__glewFogCoorddEXT) +#define glFogCoorddvEXT GLEW_GET_FUN(__glewFogCoorddvEXT) +#define glFogCoordfEXT GLEW_GET_FUN(__glewFogCoordfEXT) +#define glFogCoordfvEXT GLEW_GET_FUN(__glewFogCoordfvEXT) + +#define GLEW_EXT_fog_coord GLEW_GET_VAR(__GLEW_EXT_fog_coord) + +#endif /* GL_EXT_fog_coord */ + +/* ------------------------ GL_EXT_fragment_lighting ----------------------- */ + +#ifndef GL_EXT_fragment_lighting +#define GL_EXT_fragment_lighting 1 + +#define GL_FRAGMENT_LIGHTING_EXT 0x8400 +#define GL_FRAGMENT_COLOR_MATERIAL_EXT 0x8401 +#define GL_FRAGMENT_COLOR_MATERIAL_FACE_EXT 0x8402 +#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_EXT 0x8403 +#define GL_MAX_FRAGMENT_LIGHTS_EXT 0x8404 +#define GL_MAX_ACTIVE_LIGHTS_EXT 0x8405 +#define GL_CURRENT_RASTER_NORMAL_EXT 0x8406 +#define GL_LIGHT_ENV_MODE_EXT 0x8407 +#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_EXT 0x8408 +#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_EXT 0x8409 +#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_EXT 0x840A +#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_EXT 0x840B +#define GL_FRAGMENT_LIGHT0_EXT 0x840C +#define GL_FRAGMENT_LIGHT7_EXT 0x8413 + +typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALEXTPROC) (GLenum face, GLenum mode); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFEXTPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVEXTPROC) (GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIEXTPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVEXTPROC) (GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFEXTPROC) (GLenum light, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIEXTPROC) (GLenum light, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFEXTPROC) (GLenum face, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIEXTPROC) (GLenum face, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLLIGHTENVIEXTPROC) (GLenum pname, GLint param); + +#define glFragmentColorMaterialEXT GLEW_GET_FUN(__glewFragmentColorMaterialEXT) +#define glFragmentLightModelfEXT GLEW_GET_FUN(__glewFragmentLightModelfEXT) +#define glFragmentLightModelfvEXT GLEW_GET_FUN(__glewFragmentLightModelfvEXT) +#define glFragmentLightModeliEXT GLEW_GET_FUN(__glewFragmentLightModeliEXT) +#define glFragmentLightModelivEXT GLEW_GET_FUN(__glewFragmentLightModelivEXT) +#define glFragmentLightfEXT GLEW_GET_FUN(__glewFragmentLightfEXT) +#define glFragmentLightfvEXT GLEW_GET_FUN(__glewFragmentLightfvEXT) +#define glFragmentLightiEXT GLEW_GET_FUN(__glewFragmentLightiEXT) +#define glFragmentLightivEXT GLEW_GET_FUN(__glewFragmentLightivEXT) +#define glFragmentMaterialfEXT GLEW_GET_FUN(__glewFragmentMaterialfEXT) +#define glFragmentMaterialfvEXT GLEW_GET_FUN(__glewFragmentMaterialfvEXT) +#define glFragmentMaterialiEXT GLEW_GET_FUN(__glewFragmentMaterialiEXT) +#define glFragmentMaterialivEXT GLEW_GET_FUN(__glewFragmentMaterialivEXT) +#define glGetFragmentLightfvEXT GLEW_GET_FUN(__glewGetFragmentLightfvEXT) +#define glGetFragmentLightivEXT GLEW_GET_FUN(__glewGetFragmentLightivEXT) +#define glGetFragmentMaterialfvEXT GLEW_GET_FUN(__glewGetFragmentMaterialfvEXT) +#define glGetFragmentMaterialivEXT GLEW_GET_FUN(__glewGetFragmentMaterialivEXT) +#define glLightEnviEXT GLEW_GET_FUN(__glewLightEnviEXT) + +#define GLEW_EXT_fragment_lighting GLEW_GET_VAR(__GLEW_EXT_fragment_lighting) + +#endif /* GL_EXT_fragment_lighting */ + +/* ------------------------ GL_EXT_framebuffer_blit ------------------------ */ + +#ifndef GL_EXT_framebuffer_blit +#define GL_EXT_framebuffer_blit 1 + +#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_READ_FRAMEBUFFER_EXT 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA + +typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + +#define glBlitFramebufferEXT GLEW_GET_FUN(__glewBlitFramebufferEXT) + +#define GLEW_EXT_framebuffer_blit GLEW_GET_VAR(__GLEW_EXT_framebuffer_blit) + +#endif /* GL_EXT_framebuffer_blit */ + +/* --------------------- GL_EXT_framebuffer_multisample -------------------- */ + +#ifndef GL_EXT_framebuffer_multisample +#define GL_EXT_framebuffer_multisample 1 + +#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 +#define GL_MAX_SAMPLES_EXT 0x8D57 + +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + +#define glRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewRenderbufferStorageMultisampleEXT) + +#define GLEW_EXT_framebuffer_multisample GLEW_GET_VAR(__GLEW_EXT_framebuffer_multisample) + +#endif /* GL_EXT_framebuffer_multisample */ + +/* ----------------------- GL_EXT_framebuffer_object ----------------------- */ + +#ifndef GL_EXT_framebuffer_object +#define GL_EXT_framebuffer_object 1 + +#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 +#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 +#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 +#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#define GL_STENCIL_ATTACHMENT_EXT 0x8D20 +#define GL_FRAMEBUFFER_EXT 0x8D40 +#define GL_RENDERBUFFER_EXT 0x8D41 +#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 +#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 +#define GL_STENCIL_INDEX1_EXT 0x8D46 +#define GL_STENCIL_INDEX4_EXT 0x8D47 +#define GL_STENCIL_INDEX8_EXT 0x8D48 +#define GL_STENCIL_INDEX16_EXT 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 + +typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer); +typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer); +typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPEXTPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer); +typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + +#define glBindFramebufferEXT GLEW_GET_FUN(__glewBindFramebufferEXT) +#define glBindRenderbufferEXT GLEW_GET_FUN(__glewBindRenderbufferEXT) +#define glCheckFramebufferStatusEXT GLEW_GET_FUN(__glewCheckFramebufferStatusEXT) +#define glDeleteFramebuffersEXT GLEW_GET_FUN(__glewDeleteFramebuffersEXT) +#define glDeleteRenderbuffersEXT GLEW_GET_FUN(__glewDeleteRenderbuffersEXT) +#define glFramebufferRenderbufferEXT GLEW_GET_FUN(__glewFramebufferRenderbufferEXT) +#define glFramebufferTexture1DEXT GLEW_GET_FUN(__glewFramebufferTexture1DEXT) +#define glFramebufferTexture2DEXT GLEW_GET_FUN(__glewFramebufferTexture2DEXT) +#define glFramebufferTexture3DEXT GLEW_GET_FUN(__glewFramebufferTexture3DEXT) +#define glGenFramebuffersEXT GLEW_GET_FUN(__glewGenFramebuffersEXT) +#define glGenRenderbuffersEXT GLEW_GET_FUN(__glewGenRenderbuffersEXT) +#define glGenerateMipmapEXT GLEW_GET_FUN(__glewGenerateMipmapEXT) +#define glGetFramebufferAttachmentParameterivEXT GLEW_GET_FUN(__glewGetFramebufferAttachmentParameterivEXT) +#define glGetRenderbufferParameterivEXT GLEW_GET_FUN(__glewGetRenderbufferParameterivEXT) +#define glIsFramebufferEXT GLEW_GET_FUN(__glewIsFramebufferEXT) +#define glIsRenderbufferEXT GLEW_GET_FUN(__glewIsRenderbufferEXT) +#define glRenderbufferStorageEXT GLEW_GET_FUN(__glewRenderbufferStorageEXT) + +#define GLEW_EXT_framebuffer_object GLEW_GET_VAR(__GLEW_EXT_framebuffer_object) + +#endif /* GL_EXT_framebuffer_object */ + +/* ------------------------ GL_EXT_framebuffer_sRGB ------------------------ */ + +#ifndef GL_EXT_framebuffer_sRGB +#define GL_EXT_framebuffer_sRGB 1 + +#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 +#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA + +#define GLEW_EXT_framebuffer_sRGB GLEW_GET_VAR(__GLEW_EXT_framebuffer_sRGB) + +#endif /* GL_EXT_framebuffer_sRGB */ + +/* ------------------------ GL_EXT_geometry_shader4 ------------------------ */ + +#ifndef GL_EXT_geometry_shader4 +#define GL_EXT_geometry_shader4 1 + +#define GL_LINES_ADJACENCY_EXT 0xA +#define GL_LINE_STRIP_ADJACENCY_EXT 0xB +#define GL_TRIANGLES_ADJACENCY_EXT 0xC +#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD +#define GL_PROGRAM_POINT_SIZE_EXT 0x8642 +#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 +#define GL_GEOMETRY_SHADER_EXT 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD +#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 + +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); + +#define glFramebufferTextureEXT GLEW_GET_FUN(__glewFramebufferTextureEXT) +#define glFramebufferTextureFaceEXT GLEW_GET_FUN(__glewFramebufferTextureFaceEXT) +#define glFramebufferTextureLayerEXT GLEW_GET_FUN(__glewFramebufferTextureLayerEXT) +#define glProgramParameteriEXT GLEW_GET_FUN(__glewProgramParameteriEXT) + +#define GLEW_EXT_geometry_shader4 GLEW_GET_VAR(__GLEW_EXT_geometry_shader4) + +#endif /* GL_EXT_geometry_shader4 */ + +/* --------------------- GL_EXT_gpu_program_parameters --------------------- */ + +#ifndef GL_EXT_gpu_program_parameters +#define GL_EXT_gpu_program_parameters 1 + +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat* params); + +#define glProgramEnvParameters4fvEXT GLEW_GET_FUN(__glewProgramEnvParameters4fvEXT) +#define glProgramLocalParameters4fvEXT GLEW_GET_FUN(__glewProgramLocalParameters4fvEXT) + +#define GLEW_EXT_gpu_program_parameters GLEW_GET_VAR(__GLEW_EXT_gpu_program_parameters) + +#endif /* GL_EXT_gpu_program_parameters */ + +/* --------------------------- GL_EXT_gpu_shader4 -------------------------- */ + +#ifndef GL_EXT_gpu_shader4 +#define GL_EXT_gpu_shader4 1 + +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD +#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0 +#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1 +#define GL_SAMPLER_BUFFER_EXT 0x8DC2 +#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5 +#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6 +#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7 +#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8 +#define GL_INT_SAMPLER_1D_EXT 0x8DC9 +#define GL_INT_SAMPLER_2D_EXT 0x8DCA +#define GL_INT_SAMPLER_3D_EXT 0x8DCB +#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC +#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD +#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF +#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 + +typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name); +typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + +#define glBindFragDataLocationEXT GLEW_GET_FUN(__glewBindFragDataLocationEXT) +#define glGetFragDataLocationEXT GLEW_GET_FUN(__glewGetFragDataLocationEXT) +#define glGetUniformuivEXT GLEW_GET_FUN(__glewGetUniformuivEXT) +#define glGetVertexAttribIivEXT GLEW_GET_FUN(__glewGetVertexAttribIivEXT) +#define glGetVertexAttribIuivEXT GLEW_GET_FUN(__glewGetVertexAttribIuivEXT) +#define glUniform1uiEXT GLEW_GET_FUN(__glewUniform1uiEXT) +#define glUniform1uivEXT GLEW_GET_FUN(__glewUniform1uivEXT) +#define glUniform2uiEXT GLEW_GET_FUN(__glewUniform2uiEXT) +#define glUniform2uivEXT GLEW_GET_FUN(__glewUniform2uivEXT) +#define glUniform3uiEXT GLEW_GET_FUN(__glewUniform3uiEXT) +#define glUniform3uivEXT GLEW_GET_FUN(__glewUniform3uivEXT) +#define glUniform4uiEXT GLEW_GET_FUN(__glewUniform4uiEXT) +#define glUniform4uivEXT GLEW_GET_FUN(__glewUniform4uivEXT) +#define glVertexAttribI1iEXT GLEW_GET_FUN(__glewVertexAttribI1iEXT) +#define glVertexAttribI1ivEXT GLEW_GET_FUN(__glewVertexAttribI1ivEXT) +#define glVertexAttribI1uiEXT GLEW_GET_FUN(__glewVertexAttribI1uiEXT) +#define glVertexAttribI1uivEXT GLEW_GET_FUN(__glewVertexAttribI1uivEXT) +#define glVertexAttribI2iEXT GLEW_GET_FUN(__glewVertexAttribI2iEXT) +#define glVertexAttribI2ivEXT GLEW_GET_FUN(__glewVertexAttribI2ivEXT) +#define glVertexAttribI2uiEXT GLEW_GET_FUN(__glewVertexAttribI2uiEXT) +#define glVertexAttribI2uivEXT GLEW_GET_FUN(__glewVertexAttribI2uivEXT) +#define glVertexAttribI3iEXT GLEW_GET_FUN(__glewVertexAttribI3iEXT) +#define glVertexAttribI3ivEXT GLEW_GET_FUN(__glewVertexAttribI3ivEXT) +#define glVertexAttribI3uiEXT GLEW_GET_FUN(__glewVertexAttribI3uiEXT) +#define glVertexAttribI3uivEXT GLEW_GET_FUN(__glewVertexAttribI3uivEXT) +#define glVertexAttribI4bvEXT GLEW_GET_FUN(__glewVertexAttribI4bvEXT) +#define glVertexAttribI4iEXT GLEW_GET_FUN(__glewVertexAttribI4iEXT) +#define glVertexAttribI4ivEXT GLEW_GET_FUN(__glewVertexAttribI4ivEXT) +#define glVertexAttribI4svEXT GLEW_GET_FUN(__glewVertexAttribI4svEXT) +#define glVertexAttribI4ubvEXT GLEW_GET_FUN(__glewVertexAttribI4ubvEXT) +#define glVertexAttribI4uiEXT GLEW_GET_FUN(__glewVertexAttribI4uiEXT) +#define glVertexAttribI4uivEXT GLEW_GET_FUN(__glewVertexAttribI4uivEXT) +#define glVertexAttribI4usvEXT GLEW_GET_FUN(__glewVertexAttribI4usvEXT) +#define glVertexAttribIPointerEXT GLEW_GET_FUN(__glewVertexAttribIPointerEXT) + +#define GLEW_EXT_gpu_shader4 GLEW_GET_VAR(__GLEW_EXT_gpu_shader4) + +#endif /* GL_EXT_gpu_shader4 */ + +/* ---------------------------- GL_EXT_histogram --------------------------- */ + +#ifndef GL_EXT_histogram +#define GL_EXT_histogram 1 + +#define GL_HISTOGRAM_EXT 0x8024 +#define GL_PROXY_HISTOGRAM_EXT 0x8025 +#define GL_HISTOGRAM_WIDTH_EXT 0x8026 +#define GL_HISTOGRAM_FORMAT_EXT 0x8027 +#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C +#define GL_HISTOGRAM_SINK_EXT 0x802D +#define GL_MINMAX_EXT 0x802E +#define GL_MINMAX_FORMAT_EXT 0x802F +#define GL_MINMAX_SINK_EXT 0x8030 + +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMEXTPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLRESETMINMAXEXTPROC) (GLenum target); + +#define glGetHistogramEXT GLEW_GET_FUN(__glewGetHistogramEXT) +#define glGetHistogramParameterfvEXT GLEW_GET_FUN(__glewGetHistogramParameterfvEXT) +#define glGetHistogramParameterivEXT GLEW_GET_FUN(__glewGetHistogramParameterivEXT) +#define glGetMinmaxEXT GLEW_GET_FUN(__glewGetMinmaxEXT) +#define glGetMinmaxParameterfvEXT GLEW_GET_FUN(__glewGetMinmaxParameterfvEXT) +#define glGetMinmaxParameterivEXT GLEW_GET_FUN(__glewGetMinmaxParameterivEXT) +#define glHistogramEXT GLEW_GET_FUN(__glewHistogramEXT) +#define glMinmaxEXT GLEW_GET_FUN(__glewMinmaxEXT) +#define glResetHistogramEXT GLEW_GET_FUN(__glewResetHistogramEXT) +#define glResetMinmaxEXT GLEW_GET_FUN(__glewResetMinmaxEXT) + +#define GLEW_EXT_histogram GLEW_GET_VAR(__GLEW_EXT_histogram) + +#endif /* GL_EXT_histogram */ + +/* ----------------------- GL_EXT_index_array_formats ---------------------- */ + +#ifndef GL_EXT_index_array_formats +#define GL_EXT_index_array_formats 1 + +#define GLEW_EXT_index_array_formats GLEW_GET_VAR(__GLEW_EXT_index_array_formats) + +#endif /* GL_EXT_index_array_formats */ + +/* --------------------------- GL_EXT_index_func --------------------------- */ + +#ifndef GL_EXT_index_func +#define GL_EXT_index_func 1 + +typedef void (GLAPIENTRY * PFNGLINDEXFUNCEXTPROC) (GLenum func, GLfloat ref); + +#define glIndexFuncEXT GLEW_GET_FUN(__glewIndexFuncEXT) + +#define GLEW_EXT_index_func GLEW_GET_VAR(__GLEW_EXT_index_func) + +#endif /* GL_EXT_index_func */ + +/* ------------------------- GL_EXT_index_material ------------------------- */ + +#ifndef GL_EXT_index_material +#define GL_EXT_index_material 1 + +typedef void (GLAPIENTRY * PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode); + +#define glIndexMaterialEXT GLEW_GET_FUN(__glewIndexMaterialEXT) + +#define GLEW_EXT_index_material GLEW_GET_VAR(__GLEW_EXT_index_material) + +#endif /* GL_EXT_index_material */ + +/* -------------------------- GL_EXT_index_texture ------------------------- */ + +#ifndef GL_EXT_index_texture +#define GL_EXT_index_texture 1 + +#define GLEW_EXT_index_texture GLEW_GET_VAR(__GLEW_EXT_index_texture) + +#endif /* GL_EXT_index_texture */ + +/* -------------------------- GL_EXT_light_texture ------------------------- */ + +#ifndef GL_EXT_light_texture +#define GL_EXT_light_texture 1 + +#define GL_FRAGMENT_MATERIAL_EXT 0x8349 +#define GL_FRAGMENT_NORMAL_EXT 0x834A +#define GL_FRAGMENT_COLOR_EXT 0x834C +#define GL_ATTENUATION_EXT 0x834D +#define GL_SHADOW_ATTENUATION_EXT 0x834E +#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F +#define GL_TEXTURE_LIGHT_EXT 0x8350 +#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 +#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 +#define GL_FRAGMENT_DEPTH_EXT 0x8452 + +typedef void (GLAPIENTRY * PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode); +typedef void (GLAPIENTRY * PFNGLTEXTURELIGHTEXTPROC) (GLenum pname); +typedef void (GLAPIENTRY * PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode); + +#define glApplyTextureEXT GLEW_GET_FUN(__glewApplyTextureEXT) +#define glTextureLightEXT GLEW_GET_FUN(__glewTextureLightEXT) +#define glTextureMaterialEXT GLEW_GET_FUN(__glewTextureMaterialEXT) + +#define GLEW_EXT_light_texture GLEW_GET_VAR(__GLEW_EXT_light_texture) + +#endif /* GL_EXT_light_texture */ + +/* ------------------------- GL_EXT_misc_attribute ------------------------- */ + +#ifndef GL_EXT_misc_attribute +#define GL_EXT_misc_attribute 1 + +#define GLEW_EXT_misc_attribute GLEW_GET_VAR(__GLEW_EXT_misc_attribute) + +#endif /* GL_EXT_misc_attribute */ + +/* ------------------------ GL_EXT_multi_draw_arrays ----------------------- */ + +#ifndef GL_EXT_multi_draw_arrays +#define GL_EXT_multi_draw_arrays 1 + +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint* first, GLsizei *count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid **indices, GLsizei primcount); + +#define glMultiDrawArraysEXT GLEW_GET_FUN(__glewMultiDrawArraysEXT) +#define glMultiDrawElementsEXT GLEW_GET_FUN(__glewMultiDrawElementsEXT) + +#define GLEW_EXT_multi_draw_arrays GLEW_GET_VAR(__GLEW_EXT_multi_draw_arrays) + +#endif /* GL_EXT_multi_draw_arrays */ + +/* --------------------------- GL_EXT_multisample -------------------------- */ + +#ifndef GL_EXT_multisample +#define GL_EXT_multisample 1 + +#define GL_MULTISAMPLE_EXT 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F +#define GL_SAMPLE_MASK_EXT 0x80A0 +#define GL_1PASS_EXT 0x80A1 +#define GL_2PASS_0_EXT 0x80A2 +#define GL_2PASS_1_EXT 0x80A3 +#define GL_4PASS_0_EXT 0x80A4 +#define GL_4PASS_1_EXT 0x80A5 +#define GL_4PASS_2_EXT 0x80A6 +#define GL_4PASS_3_EXT 0x80A7 +#define GL_SAMPLE_BUFFERS_EXT 0x80A8 +#define GL_SAMPLES_EXT 0x80A9 +#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA +#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB +#define GL_SAMPLE_PATTERN_EXT 0x80AC +#define GL_MULTISAMPLE_BIT_EXT 0x20000000 + +typedef void (GLAPIENTRY * PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert); +typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); + +#define glSampleMaskEXT GLEW_GET_FUN(__glewSampleMaskEXT) +#define glSamplePatternEXT GLEW_GET_FUN(__glewSamplePatternEXT) + +#define GLEW_EXT_multisample GLEW_GET_VAR(__GLEW_EXT_multisample) + +#endif /* GL_EXT_multisample */ + +/* ---------------------- GL_EXT_packed_depth_stencil ---------------------- */ + +#ifndef GL_EXT_packed_depth_stencil +#define GL_EXT_packed_depth_stencil 1 + +#define GL_DEPTH_STENCIL_EXT 0x84F9 +#define GL_UNSIGNED_INT_24_8_EXT 0x84FA +#define GL_DEPTH24_STENCIL8_EXT 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1 + +#define GLEW_EXT_packed_depth_stencil GLEW_GET_VAR(__GLEW_EXT_packed_depth_stencil) + +#endif /* GL_EXT_packed_depth_stencil */ + +/* -------------------------- GL_EXT_packed_float -------------------------- */ + +#ifndef GL_EXT_packed_float +#define GL_EXT_packed_float 1 + +#define GL_R11F_G11F_B10F_EXT 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B +#define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C + +#define GLEW_EXT_packed_float GLEW_GET_VAR(__GLEW_EXT_packed_float) + +#endif /* GL_EXT_packed_float */ + +/* -------------------------- GL_EXT_packed_pixels ------------------------- */ + +#ifndef GL_EXT_packed_pixels +#define GL_EXT_packed_pixels 1 + +#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036 + +#define GLEW_EXT_packed_pixels GLEW_GET_VAR(__GLEW_EXT_packed_pixels) + +#endif /* GL_EXT_packed_pixels */ + +/* ------------------------ GL_EXT_paletted_texture ------------------------ */ + +#ifndef GL_EXT_paletted_texture +#define GL_EXT_paletted_texture 1 + +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_TEXTURE_3D_EXT 0x806F +#define GL_PROXY_TEXTURE_3D_EXT 0x8070 +#define GL_COLOR_TABLE_FORMAT_EXT 0x80D8 +#define GL_COLOR_TABLE_WIDTH_EXT 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE_EXT 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE_EXT 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE_EXT 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE_EXT 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE_EXT 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE_EXT 0x80DF +#define GL_COLOR_INDEX1_EXT 0x80E2 +#define GL_COLOR_INDEX2_EXT 0x80E3 +#define GL_COLOR_INDEX4_EXT 0x80E4 +#define GL_COLOR_INDEX8_EXT 0x80E5 +#define GL_COLOR_INDEX12_EXT 0x80E6 +#define GL_COLOR_INDEX16_EXT 0x80E7 +#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED +#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 +#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B + +typedef void (GLAPIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void* data); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, void* data); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); + +#define glColorTableEXT GLEW_GET_FUN(__glewColorTableEXT) +#define glGetColorTableEXT GLEW_GET_FUN(__glewGetColorTableEXT) +#define glGetColorTableParameterfvEXT GLEW_GET_FUN(__glewGetColorTableParameterfvEXT) +#define glGetColorTableParameterivEXT GLEW_GET_FUN(__glewGetColorTableParameterivEXT) + +#define GLEW_EXT_paletted_texture GLEW_GET_VAR(__GLEW_EXT_paletted_texture) + +#endif /* GL_EXT_paletted_texture */ + +/* ----------------------- GL_EXT_pixel_buffer_object ---------------------- */ + +#ifndef GL_EXT_pixel_buffer_object +#define GL_EXT_pixel_buffer_object 1 + +#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF + +#define GLEW_EXT_pixel_buffer_object GLEW_GET_VAR(__GLEW_EXT_pixel_buffer_object) + +#endif /* GL_EXT_pixel_buffer_object */ + +/* ------------------------- GL_EXT_pixel_transform ------------------------ */ + +#ifndef GL_EXT_pixel_transform +#define GL_EXT_pixel_transform 1 + +#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330 +#define GL_PIXEL_MAG_FILTER_EXT 0x8331 +#define GL_PIXEL_MIN_FILTER_EXT 0x8332 +#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333 +#define GL_CUBIC_EXT 0x8334 +#define GL_AVERAGE_EXT 0x8335 +#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336 +#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337 +#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338 + +typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); + +#define glGetPixelTransformParameterfvEXT GLEW_GET_FUN(__glewGetPixelTransformParameterfvEXT) +#define glGetPixelTransformParameterivEXT GLEW_GET_FUN(__glewGetPixelTransformParameterivEXT) +#define glPixelTransformParameterfEXT GLEW_GET_FUN(__glewPixelTransformParameterfEXT) +#define glPixelTransformParameterfvEXT GLEW_GET_FUN(__glewPixelTransformParameterfvEXT) +#define glPixelTransformParameteriEXT GLEW_GET_FUN(__glewPixelTransformParameteriEXT) +#define glPixelTransformParameterivEXT GLEW_GET_FUN(__glewPixelTransformParameterivEXT) + +#define GLEW_EXT_pixel_transform GLEW_GET_VAR(__GLEW_EXT_pixel_transform) + +#endif /* GL_EXT_pixel_transform */ + +/* ------------------- GL_EXT_pixel_transform_color_table ------------------ */ + +#ifndef GL_EXT_pixel_transform_color_table +#define GL_EXT_pixel_transform_color_table 1 + +#define GLEW_EXT_pixel_transform_color_table GLEW_GET_VAR(__GLEW_EXT_pixel_transform_color_table) + +#endif /* GL_EXT_pixel_transform_color_table */ + +/* ------------------------ GL_EXT_point_parameters ------------------------ */ + +#ifndef GL_EXT_point_parameters +#define GL_EXT_point_parameters 1 + +#define GL_POINT_SIZE_MIN_EXT 0x8126 +#define GL_POINT_SIZE_MAX_EXT 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 +#define GL_DISTANCE_ATTENUATION_EXT 0x8129 + +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, GLfloat* params); + +#define glPointParameterfEXT GLEW_GET_FUN(__glewPointParameterfEXT) +#define glPointParameterfvEXT GLEW_GET_FUN(__glewPointParameterfvEXT) + +#define GLEW_EXT_point_parameters GLEW_GET_VAR(__GLEW_EXT_point_parameters) + +#endif /* GL_EXT_point_parameters */ + +/* ------------------------- GL_EXT_polygon_offset ------------------------- */ + +#ifndef GL_EXT_polygon_offset +#define GL_EXT_polygon_offset 1 + +#define GL_POLYGON_OFFSET_EXT 0x8037 +#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038 +#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039 + +typedef void (GLAPIENTRY * PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias); + +#define glPolygonOffsetEXT GLEW_GET_FUN(__glewPolygonOffsetEXT) + +#define GLEW_EXT_polygon_offset GLEW_GET_VAR(__GLEW_EXT_polygon_offset) + +#endif /* GL_EXT_polygon_offset */ + +/* ------------------------- GL_EXT_rescale_normal ------------------------- */ + +#ifndef GL_EXT_rescale_normal +#define GL_EXT_rescale_normal 1 + +#define GL_RESCALE_NORMAL_EXT 0x803A + +#define GLEW_EXT_rescale_normal GLEW_GET_VAR(__GLEW_EXT_rescale_normal) + +#endif /* GL_EXT_rescale_normal */ + +/* -------------------------- GL_EXT_scene_marker -------------------------- */ + +#ifndef GL_EXT_scene_marker +#define GL_EXT_scene_marker 1 + +typedef void (GLAPIENTRY * PFNGLBEGINSCENEEXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLENDSCENEEXTPROC) (void); + +#define glBeginSceneEXT GLEW_GET_FUN(__glewBeginSceneEXT) +#define glEndSceneEXT GLEW_GET_FUN(__glewEndSceneEXT) + +#define GLEW_EXT_scene_marker GLEW_GET_VAR(__GLEW_EXT_scene_marker) + +#endif /* GL_EXT_scene_marker */ + +/* ------------------------- GL_EXT_secondary_color ------------------------ */ + +#ifndef GL_EXT_secondary_color +#define GL_EXT_secondary_color 1 + +#define GL_COLOR_SUM_EXT 0x8458 +#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D +#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E + +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); + +#define glSecondaryColor3bEXT GLEW_GET_FUN(__glewSecondaryColor3bEXT) +#define glSecondaryColor3bvEXT GLEW_GET_FUN(__glewSecondaryColor3bvEXT) +#define glSecondaryColor3dEXT GLEW_GET_FUN(__glewSecondaryColor3dEXT) +#define glSecondaryColor3dvEXT GLEW_GET_FUN(__glewSecondaryColor3dvEXT) +#define glSecondaryColor3fEXT GLEW_GET_FUN(__glewSecondaryColor3fEXT) +#define glSecondaryColor3fvEXT GLEW_GET_FUN(__glewSecondaryColor3fvEXT) +#define glSecondaryColor3iEXT GLEW_GET_FUN(__glewSecondaryColor3iEXT) +#define glSecondaryColor3ivEXT GLEW_GET_FUN(__glewSecondaryColor3ivEXT) +#define glSecondaryColor3sEXT GLEW_GET_FUN(__glewSecondaryColor3sEXT) +#define glSecondaryColor3svEXT GLEW_GET_FUN(__glewSecondaryColor3svEXT) +#define glSecondaryColor3ubEXT GLEW_GET_FUN(__glewSecondaryColor3ubEXT) +#define glSecondaryColor3ubvEXT GLEW_GET_FUN(__glewSecondaryColor3ubvEXT) +#define glSecondaryColor3uiEXT GLEW_GET_FUN(__glewSecondaryColor3uiEXT) +#define glSecondaryColor3uivEXT GLEW_GET_FUN(__glewSecondaryColor3uivEXT) +#define glSecondaryColor3usEXT GLEW_GET_FUN(__glewSecondaryColor3usEXT) +#define glSecondaryColor3usvEXT GLEW_GET_FUN(__glewSecondaryColor3usvEXT) +#define glSecondaryColorPointerEXT GLEW_GET_FUN(__glewSecondaryColorPointerEXT) + +#define GLEW_EXT_secondary_color GLEW_GET_VAR(__GLEW_EXT_secondary_color) + +#endif /* GL_EXT_secondary_color */ + +/* --------------------- GL_EXT_separate_specular_color -------------------- */ + +#ifndef GL_EXT_separate_specular_color +#define GL_EXT_separate_specular_color 1 + +#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 +#define GL_SINGLE_COLOR_EXT 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA + +#define GLEW_EXT_separate_specular_color GLEW_GET_VAR(__GLEW_EXT_separate_specular_color) + +#endif /* GL_EXT_separate_specular_color */ + +/* -------------------------- GL_EXT_shadow_funcs -------------------------- */ + +#ifndef GL_EXT_shadow_funcs +#define GL_EXT_shadow_funcs 1 + +#define GLEW_EXT_shadow_funcs GLEW_GET_VAR(__GLEW_EXT_shadow_funcs) + +#endif /* GL_EXT_shadow_funcs */ + +/* --------------------- GL_EXT_shared_texture_palette --------------------- */ + +#ifndef GL_EXT_shared_texture_palette +#define GL_EXT_shared_texture_palette 1 + +#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB + +#define GLEW_EXT_shared_texture_palette GLEW_GET_VAR(__GLEW_EXT_shared_texture_palette) + +#endif /* GL_EXT_shared_texture_palette */ + +/* ------------------------ GL_EXT_stencil_clear_tag ----------------------- */ + +#ifndef GL_EXT_stencil_clear_tag +#define GL_EXT_stencil_clear_tag 1 + +#define GL_STENCIL_TAG_BITS_EXT 0x88F2 +#define GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3 + +#define GLEW_EXT_stencil_clear_tag GLEW_GET_VAR(__GLEW_EXT_stencil_clear_tag) + +#endif /* GL_EXT_stencil_clear_tag */ + +/* ------------------------ GL_EXT_stencil_two_side ------------------------ */ + +#ifndef GL_EXT_stencil_two_side +#define GL_EXT_stencil_two_side 1 + +#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 +#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911 + +typedef void (GLAPIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face); + +#define glActiveStencilFaceEXT GLEW_GET_FUN(__glewActiveStencilFaceEXT) + +#define GLEW_EXT_stencil_two_side GLEW_GET_VAR(__GLEW_EXT_stencil_two_side) + +#endif /* GL_EXT_stencil_two_side */ + +/* -------------------------- GL_EXT_stencil_wrap -------------------------- */ + +#ifndef GL_EXT_stencil_wrap +#define GL_EXT_stencil_wrap 1 + +#define GL_INCR_WRAP_EXT 0x8507 +#define GL_DECR_WRAP_EXT 0x8508 + +#define GLEW_EXT_stencil_wrap GLEW_GET_VAR(__GLEW_EXT_stencil_wrap) + +#endif /* GL_EXT_stencil_wrap */ + +/* --------------------------- GL_EXT_subtexture --------------------------- */ + +#ifndef GL_EXT_subtexture +#define GL_EXT_subtexture 1 + +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); + +#define glTexSubImage1DEXT GLEW_GET_FUN(__glewTexSubImage1DEXT) +#define glTexSubImage2DEXT GLEW_GET_FUN(__glewTexSubImage2DEXT) +#define glTexSubImage3DEXT GLEW_GET_FUN(__glewTexSubImage3DEXT) + +#define GLEW_EXT_subtexture GLEW_GET_VAR(__GLEW_EXT_subtexture) + +#endif /* GL_EXT_subtexture */ + +/* ----------------------------- GL_EXT_texture ---------------------------- */ + +#ifndef GL_EXT_texture +#define GL_EXT_texture 1 + +#define GL_ALPHA4_EXT 0x803B +#define GL_ALPHA8_EXT 0x803C +#define GL_ALPHA12_EXT 0x803D +#define GL_ALPHA16_EXT 0x803E +#define GL_LUMINANCE4_EXT 0x803F +#define GL_LUMINANCE8_EXT 0x8040 +#define GL_LUMINANCE12_EXT 0x8041 +#define GL_LUMINANCE16_EXT 0x8042 +#define GL_LUMINANCE4_ALPHA4_EXT 0x8043 +#define GL_LUMINANCE6_ALPHA2_EXT 0x8044 +#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +#define GL_LUMINANCE12_ALPHA4_EXT 0x8046 +#define GL_LUMINANCE12_ALPHA12_EXT 0x8047 +#define GL_LUMINANCE16_ALPHA16_EXT 0x8048 +#define GL_INTENSITY_EXT 0x8049 +#define GL_INTENSITY4_EXT 0x804A +#define GL_INTENSITY8_EXT 0x804B +#define GL_INTENSITY12_EXT 0x804C +#define GL_INTENSITY16_EXT 0x804D +#define GL_RGB2_EXT 0x804E +#define GL_RGB4_EXT 0x804F +#define GL_RGB5_EXT 0x8050 +#define GL_RGB8_EXT 0x8051 +#define GL_RGB10_EXT 0x8052 +#define GL_RGB12_EXT 0x8053 +#define GL_RGB16_EXT 0x8054 +#define GL_RGBA2_EXT 0x8055 +#define GL_RGBA4_EXT 0x8056 +#define GL_RGB5_A1_EXT 0x8057 +#define GL_RGBA8_EXT 0x8058 +#define GL_RGB10_A2_EXT 0x8059 +#define GL_RGBA12_EXT 0x805A +#define GL_RGBA16_EXT 0x805B +#define GL_TEXTURE_RED_SIZE_EXT 0x805C +#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D +#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E +#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061 +#define GL_REPLACE_EXT 0x8062 +#define GL_PROXY_TEXTURE_1D_EXT 0x8063 +#define GL_PROXY_TEXTURE_2D_EXT 0x8064 + +#define GLEW_EXT_texture GLEW_GET_VAR(__GLEW_EXT_texture) + +#endif /* GL_EXT_texture */ + +/* ---------------------------- GL_EXT_texture3D --------------------------- */ + +#ifndef GL_EXT_texture3D +#define GL_EXT_texture3D 1 + +#define GL_PACK_SKIP_IMAGES_EXT 0x806B +#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C +#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D +#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E +#define GL_TEXTURE_3D_EXT 0x806F +#define GL_PROXY_TEXTURE_3D_EXT 0x8070 +#define GL_TEXTURE_DEPTH_EXT 0x8071 +#define GL_TEXTURE_WRAP_R_EXT 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 + +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); + +#define glTexImage3DEXT GLEW_GET_FUN(__glewTexImage3DEXT) + +#define GLEW_EXT_texture3D GLEW_GET_VAR(__GLEW_EXT_texture3D) + +#endif /* GL_EXT_texture3D */ + +/* -------------------------- GL_EXT_texture_array ------------------------- */ + +#ifndef GL_EXT_texture_array +#define GL_EXT_texture_array 1 + +#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E +#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF +#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19 +#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D + +#define GLEW_EXT_texture_array GLEW_GET_VAR(__GLEW_EXT_texture_array) + +#endif /* GL_EXT_texture_array */ + +/* ---------------------- GL_EXT_texture_buffer_object --------------------- */ + +#ifndef GL_EXT_texture_buffer_object +#define GL_EXT_texture_buffer_object 1 + +#define GL_TEXTURE_BUFFER_EXT 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E + +typedef void (GLAPIENTRY * PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer); + +#define glTexBufferEXT GLEW_GET_FUN(__glewTexBufferEXT) + +#define GLEW_EXT_texture_buffer_object GLEW_GET_VAR(__GLEW_EXT_texture_buffer_object) + +#endif /* GL_EXT_texture_buffer_object */ + +/* -------------------- GL_EXT_texture_compression_dxt1 -------------------- */ + +#ifndef GL_EXT_texture_compression_dxt1 +#define GL_EXT_texture_compression_dxt1 1 + +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 + +#define GLEW_EXT_texture_compression_dxt1 GLEW_GET_VAR(__GLEW_EXT_texture_compression_dxt1) + +#endif /* GL_EXT_texture_compression_dxt1 */ + +/* -------------------- GL_EXT_texture_compression_latc -------------------- */ + +#ifndef GL_EXT_texture_compression_latc +#define GL_EXT_texture_compression_latc 1 + +#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 +#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71 +#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 +#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73 + +#define GLEW_EXT_texture_compression_latc GLEW_GET_VAR(__GLEW_EXT_texture_compression_latc) + +#endif /* GL_EXT_texture_compression_latc */ + +/* -------------------- GL_EXT_texture_compression_rgtc -------------------- */ + +#ifndef GL_EXT_texture_compression_rgtc +#define GL_EXT_texture_compression_rgtc 1 + +#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC +#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD +#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE + +#define GLEW_EXT_texture_compression_rgtc GLEW_GET_VAR(__GLEW_EXT_texture_compression_rgtc) + +#endif /* GL_EXT_texture_compression_rgtc */ + +/* -------------------- GL_EXT_texture_compression_s3tc -------------------- */ + +#ifndef GL_EXT_texture_compression_s3tc +#define GL_EXT_texture_compression_s3tc 1 + +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 + +#define GLEW_EXT_texture_compression_s3tc GLEW_GET_VAR(__GLEW_EXT_texture_compression_s3tc) + +#endif /* GL_EXT_texture_compression_s3tc */ + +/* ------------------------ GL_EXT_texture_cube_map ------------------------ */ + +#ifndef GL_EXT_texture_cube_map +#define GL_EXT_texture_cube_map 1 + +#define GL_NORMAL_MAP_EXT 0x8511 +#define GL_REFLECTION_MAP_EXT 0x8512 +#define GL_TEXTURE_CUBE_MAP_EXT 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C + +#define GLEW_EXT_texture_cube_map GLEW_GET_VAR(__GLEW_EXT_texture_cube_map) + +#endif /* GL_EXT_texture_cube_map */ + +/* ----------------------- GL_EXT_texture_edge_clamp ----------------------- */ + +#ifndef GL_EXT_texture_edge_clamp +#define GL_EXT_texture_edge_clamp 1 + +#define GL_CLAMP_TO_EDGE_EXT 0x812F + +#define GLEW_EXT_texture_edge_clamp GLEW_GET_VAR(__GLEW_EXT_texture_edge_clamp) + +#endif /* GL_EXT_texture_edge_clamp */ + +/* --------------------------- GL_EXT_texture_env -------------------------- */ + +#ifndef GL_EXT_texture_env +#define GL_EXT_texture_env 1 + +#define GL_TEXTURE_ENV0_EXT 0 +#define GL_ENV_BLEND_EXT 0 +#define GL_TEXTURE_ENV_SHIFT_EXT 0 +#define GL_ENV_REPLACE_EXT 0 +#define GL_ENV_ADD_EXT 0 +#define GL_ENV_SUBTRACT_EXT 0 +#define GL_TEXTURE_ENV_MODE_ALPHA_EXT 0 +#define GL_ENV_REVERSE_SUBTRACT_EXT 0 +#define GL_ENV_REVERSE_BLEND_EXT 0 +#define GL_ENV_COPY_EXT 0 +#define GL_ENV_MODULATE_EXT 0 + +#define GLEW_EXT_texture_env GLEW_GET_VAR(__GLEW_EXT_texture_env) + +#endif /* GL_EXT_texture_env */ + +/* ------------------------- GL_EXT_texture_env_add ------------------------ */ + +#ifndef GL_EXT_texture_env_add +#define GL_EXT_texture_env_add 1 + +#define GLEW_EXT_texture_env_add GLEW_GET_VAR(__GLEW_EXT_texture_env_add) + +#endif /* GL_EXT_texture_env_add */ + +/* ----------------------- GL_EXT_texture_env_combine ---------------------- */ + +#ifndef GL_EXT_texture_env_combine +#define GL_EXT_texture_env_combine 1 + +#define GL_COMBINE_EXT 0x8570 +#define GL_COMBINE_RGB_EXT 0x8571 +#define GL_COMBINE_ALPHA_EXT 0x8572 +#define GL_RGB_SCALE_EXT 0x8573 +#define GL_ADD_SIGNED_EXT 0x8574 +#define GL_INTERPOLATE_EXT 0x8575 +#define GL_CONSTANT_EXT 0x8576 +#define GL_PRIMARY_COLOR_EXT 0x8577 +#define GL_PREVIOUS_EXT 0x8578 +#define GL_SOURCE0_RGB_EXT 0x8580 +#define GL_SOURCE1_RGB_EXT 0x8581 +#define GL_SOURCE2_RGB_EXT 0x8582 +#define GL_SOURCE0_ALPHA_EXT 0x8588 +#define GL_SOURCE1_ALPHA_EXT 0x8589 +#define GL_SOURCE2_ALPHA_EXT 0x858A +#define GL_OPERAND0_RGB_EXT 0x8590 +#define GL_OPERAND1_RGB_EXT 0x8591 +#define GL_OPERAND2_RGB_EXT 0x8592 +#define GL_OPERAND0_ALPHA_EXT 0x8598 +#define GL_OPERAND1_ALPHA_EXT 0x8599 +#define GL_OPERAND2_ALPHA_EXT 0x859A + +#define GLEW_EXT_texture_env_combine GLEW_GET_VAR(__GLEW_EXT_texture_env_combine) + +#endif /* GL_EXT_texture_env_combine */ + +/* ------------------------ GL_EXT_texture_env_dot3 ------------------------ */ + +#ifndef GL_EXT_texture_env_dot3 +#define GL_EXT_texture_env_dot3 1 + +#define GL_DOT3_RGB_EXT 0x8740 +#define GL_DOT3_RGBA_EXT 0x8741 + +#define GLEW_EXT_texture_env_dot3 GLEW_GET_VAR(__GLEW_EXT_texture_env_dot3) + +#endif /* GL_EXT_texture_env_dot3 */ + +/* ------------------- GL_EXT_texture_filter_anisotropic ------------------- */ + +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_EXT_texture_filter_anisotropic 1 + +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF + +#define GLEW_EXT_texture_filter_anisotropic GLEW_GET_VAR(__GLEW_EXT_texture_filter_anisotropic) + +#endif /* GL_EXT_texture_filter_anisotropic */ + +/* ------------------------- GL_EXT_texture_integer ------------------------ */ + +#ifndef GL_EXT_texture_integer +#define GL_EXT_texture_integer 1 + +#define GL_RGBA32UI_EXT 0x8D70 +#define GL_RGB32UI_EXT 0x8D71 +#define GL_ALPHA32UI_EXT 0x8D72 +#define GL_INTENSITY32UI_EXT 0x8D73 +#define GL_LUMINANCE32UI_EXT 0x8D74 +#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75 +#define GL_RGBA16UI_EXT 0x8D76 +#define GL_RGB16UI_EXT 0x8D77 +#define GL_ALPHA16UI_EXT 0x8D78 +#define GL_INTENSITY16UI_EXT 0x8D79 +#define GL_LUMINANCE16UI_EXT 0x8D7A +#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B +#define GL_RGBA8UI_EXT 0x8D7C +#define GL_RGB8UI_EXT 0x8D7D +#define GL_ALPHA8UI_EXT 0x8D7E +#define GL_INTENSITY8UI_EXT 0x8D7F +#define GL_LUMINANCE8UI_EXT 0x8D80 +#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81 +#define GL_RGBA32I_EXT 0x8D82 +#define GL_RGB32I_EXT 0x8D83 +#define GL_ALPHA32I_EXT 0x8D84 +#define GL_INTENSITY32I_EXT 0x8D85 +#define GL_LUMINANCE32I_EXT 0x8D86 +#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87 +#define GL_RGBA16I_EXT 0x8D88 +#define GL_RGB16I_EXT 0x8D89 +#define GL_ALPHA16I_EXT 0x8D8A +#define GL_INTENSITY16I_EXT 0x8D8B +#define GL_LUMINANCE16I_EXT 0x8D8C +#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D +#define GL_RGBA8I_EXT 0x8D8E +#define GL_RGB8I_EXT 0x8D8F +#define GL_ALPHA8I_EXT 0x8D90 +#define GL_INTENSITY8I_EXT 0x8D91 +#define GL_LUMINANCE8I_EXT 0x8D92 +#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93 +#define GL_RED_INTEGER_EXT 0x8D94 +#define GL_GREEN_INTEGER_EXT 0x8D95 +#define GL_BLUE_INTEGER_EXT 0x8D96 +#define GL_ALPHA_INTEGER_EXT 0x8D97 +#define GL_RGB_INTEGER_EXT 0x8D98 +#define GL_RGBA_INTEGER_EXT 0x8D99 +#define GL_BGR_INTEGER_EXT 0x8D9A +#define GL_BGRA_INTEGER_EXT 0x8D9B +#define GL_LUMINANCE_INTEGER_EXT 0x8D9C +#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D +#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E + +typedef void (GLAPIENTRY * PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha); +typedef void (GLAPIENTRY * PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params); + +#define glClearColorIiEXT GLEW_GET_FUN(__glewClearColorIiEXT) +#define glClearColorIuiEXT GLEW_GET_FUN(__glewClearColorIuiEXT) +#define glGetTexParameterIivEXT GLEW_GET_FUN(__glewGetTexParameterIivEXT) +#define glGetTexParameterIuivEXT GLEW_GET_FUN(__glewGetTexParameterIuivEXT) +#define glTexParameterIivEXT GLEW_GET_FUN(__glewTexParameterIivEXT) +#define glTexParameterIuivEXT GLEW_GET_FUN(__glewTexParameterIuivEXT) + +#define GLEW_EXT_texture_integer GLEW_GET_VAR(__GLEW_EXT_texture_integer) + +#endif /* GL_EXT_texture_integer */ + +/* ------------------------ GL_EXT_texture_lod_bias ------------------------ */ + +#ifndef GL_EXT_texture_lod_bias +#define GL_EXT_texture_lod_bias 1 + +#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD +#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 +#define GL_TEXTURE_LOD_BIAS_EXT 0x8501 + +#define GLEW_EXT_texture_lod_bias GLEW_GET_VAR(__GLEW_EXT_texture_lod_bias) + +#endif /* GL_EXT_texture_lod_bias */ + +/* ---------------------- GL_EXT_texture_mirror_clamp ---------------------- */ + +#ifndef GL_EXT_texture_mirror_clamp +#define GL_EXT_texture_mirror_clamp 1 + +#define GL_MIRROR_CLAMP_EXT 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743 +#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912 + +#define GLEW_EXT_texture_mirror_clamp GLEW_GET_VAR(__GLEW_EXT_texture_mirror_clamp) + +#endif /* GL_EXT_texture_mirror_clamp */ + +/* ------------------------- GL_EXT_texture_object ------------------------- */ + +#ifndef GL_EXT_texture_object +#define GL_EXT_texture_object 1 + +#define GL_TEXTURE_PRIORITY_EXT 0x8066 +#define GL_TEXTURE_RESIDENT_EXT 0x8067 +#define GL_TEXTURE_1D_BINDING_EXT 0x8068 +#define GL_TEXTURE_2D_BINDING_EXT 0x8069 +#define GL_TEXTURE_3D_BINDING_EXT 0x806A + +typedef GLboolean (GLAPIENTRY * PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint* textures, GLboolean* residences); +typedef void (GLAPIENTRY * PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture); +typedef void (GLAPIENTRY * PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint* textures); +typedef void (GLAPIENTRY * PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint* textures); +typedef GLboolean (GLAPIENTRY * PFNGLISTEXTUREEXTPROC) (GLuint texture); +typedef void (GLAPIENTRY * PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint* textures, const GLclampf* priorities); + +#define glAreTexturesResidentEXT GLEW_GET_FUN(__glewAreTexturesResidentEXT) +#define glBindTextureEXT GLEW_GET_FUN(__glewBindTextureEXT) +#define glDeleteTexturesEXT GLEW_GET_FUN(__glewDeleteTexturesEXT) +#define glGenTexturesEXT GLEW_GET_FUN(__glewGenTexturesEXT) +#define glIsTextureEXT GLEW_GET_FUN(__glewIsTextureEXT) +#define glPrioritizeTexturesEXT GLEW_GET_FUN(__glewPrioritizeTexturesEXT) + +#define GLEW_EXT_texture_object GLEW_GET_VAR(__GLEW_EXT_texture_object) + +#endif /* GL_EXT_texture_object */ + +/* --------------------- GL_EXT_texture_perturb_normal --------------------- */ + +#ifndef GL_EXT_texture_perturb_normal +#define GL_EXT_texture_perturb_normal 1 + +#define GL_PERTURB_EXT 0x85AE +#define GL_TEXTURE_NORMAL_EXT 0x85AF + +typedef void (GLAPIENTRY * PFNGLTEXTURENORMALEXTPROC) (GLenum mode); + +#define glTextureNormalEXT GLEW_GET_FUN(__glewTextureNormalEXT) + +#define GLEW_EXT_texture_perturb_normal GLEW_GET_VAR(__GLEW_EXT_texture_perturb_normal) + +#endif /* GL_EXT_texture_perturb_normal */ + +/* ------------------------ GL_EXT_texture_rectangle ----------------------- */ + +#ifndef GL_EXT_texture_rectangle +#define GL_EXT_texture_rectangle 1 + +#define GL_TEXTURE_RECTANGLE_EXT 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_EXT 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_EXT 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT 0x84F8 + +#define GLEW_EXT_texture_rectangle GLEW_GET_VAR(__GLEW_EXT_texture_rectangle) + +#endif /* GL_EXT_texture_rectangle */ + +/* -------------------------- GL_EXT_texture_sRGB -------------------------- */ + +#ifndef GL_EXT_texture_sRGB +#define GL_EXT_texture_sRGB 1 + +#define GL_SRGB_EXT 0x8C40 +#define GL_SRGB8_EXT 0x8C41 +#define GL_SRGB_ALPHA_EXT 0x8C42 +#define GL_SRGB8_ALPHA8_EXT 0x8C43 +#define GL_SLUMINANCE_ALPHA_EXT 0x8C44 +#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45 +#define GL_SLUMINANCE_EXT 0x8C46 +#define GL_SLUMINANCE8_EXT 0x8C47 +#define GL_COMPRESSED_SRGB_EXT 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49 +#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B +#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F + +#define GLEW_EXT_texture_sRGB GLEW_GET_VAR(__GLEW_EXT_texture_sRGB) + +#endif /* GL_EXT_texture_sRGB */ + +/* --------------------- GL_EXT_texture_shared_exponent -------------------- */ + +#ifndef GL_EXT_texture_shared_exponent +#define GL_EXT_texture_shared_exponent 1 + +#define GL_RGB9_E5_EXT 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E +#define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F + +#define GLEW_EXT_texture_shared_exponent GLEW_GET_VAR(__GLEW_EXT_texture_shared_exponent) + +#endif /* GL_EXT_texture_shared_exponent */ + +/* ------------------------- GL_EXT_texture_swizzle ------------------------ */ + +#ifndef GL_EXT_texture_swizzle +#define GL_EXT_texture_swizzle 1 + +#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42 +#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43 +#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44 +#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46 + +#define GLEW_EXT_texture_swizzle GLEW_GET_VAR(__GLEW_EXT_texture_swizzle) + +#endif /* GL_EXT_texture_swizzle */ + +/* --------------------------- GL_EXT_timer_query -------------------------- */ + +#ifndef GL_EXT_timer_query +#define GL_EXT_timer_query 1 + +#define GL_TIME_ELAPSED_EXT 0x88BF + +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64EXT *params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64EXT *params); + +#define glGetQueryObjecti64vEXT GLEW_GET_FUN(__glewGetQueryObjecti64vEXT) +#define glGetQueryObjectui64vEXT GLEW_GET_FUN(__glewGetQueryObjectui64vEXT) + +#define GLEW_EXT_timer_query GLEW_GET_VAR(__GLEW_EXT_timer_query) + +#endif /* GL_EXT_timer_query */ + +/* ----------------------- GL_EXT_transform_feedback ----------------------- */ + +#ifndef GL_EXT_transform_feedback +#define GL_EXT_transform_feedback 1 + +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85 +#define GL_PRIMITIVES_GENERATED_EXT 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88 +#define GL_RASTERIZER_DISCARD_EXT 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B +#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C +#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F + +typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) (GLenum primitiveMode); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei *size, GLenum *type, char *name); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const char ** varyings, GLenum bufferMode); + +#define glBeginTransformFeedbackEXT GLEW_GET_FUN(__glewBeginTransformFeedbackEXT) +#define glBindBufferBaseEXT GLEW_GET_FUN(__glewBindBufferBaseEXT) +#define glBindBufferOffsetEXT GLEW_GET_FUN(__glewBindBufferOffsetEXT) +#define glBindBufferRangeEXT GLEW_GET_FUN(__glewBindBufferRangeEXT) +#define glEndTransformFeedbackEXT GLEW_GET_FUN(__glewEndTransformFeedbackEXT) +#define glGetTransformFeedbackVaryingEXT GLEW_GET_FUN(__glewGetTransformFeedbackVaryingEXT) +#define glTransformFeedbackVaryingsEXT GLEW_GET_FUN(__glewTransformFeedbackVaryingsEXT) + +#define GLEW_EXT_transform_feedback GLEW_GET_VAR(__GLEW_EXT_transform_feedback) + +#endif /* GL_EXT_transform_feedback */ + +/* -------------------------- GL_EXT_vertex_array -------------------------- */ + +#ifndef GL_EXT_vertex_array +#define GL_EXT_vertex_array 1 + +#define GL_DOUBLE_EXT 0x140A +#define GL_VERTEX_ARRAY_EXT 0x8074 +#define GL_NORMAL_ARRAY_EXT 0x8075 +#define GL_COLOR_ARRAY_EXT 0x8076 +#define GL_INDEX_ARRAY_EXT 0x8077 +#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 +#define GL_EDGE_FLAG_ARRAY_EXT 0x8079 +#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A +#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B +#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C +#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D +#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E +#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F +#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 +#define GL_COLOR_ARRAY_SIZE_EXT 0x8081 +#define GL_COLOR_ARRAY_TYPE_EXT 0x8082 +#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 +#define GL_COLOR_ARRAY_COUNT_EXT 0x8084 +#define GL_INDEX_ARRAY_TYPE_EXT 0x8085 +#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 +#define GL_INDEX_ARRAY_COUNT_EXT 0x8087 +#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A +#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B +#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C +#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D +#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E +#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F +#define GL_COLOR_ARRAY_POINTER_EXT 0x8090 +#define GL_INDEX_ARRAY_POINTER_EXT 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 + +typedef void (GLAPIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i); +typedef void (GLAPIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean* pointer); +typedef void (GLAPIENTRY * PFNGLGETPOINTERVEXTPROC) (GLenum pname, void** params); +typedef void (GLAPIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); + +#define glArrayElementEXT GLEW_GET_FUN(__glewArrayElementEXT) +#define glColorPointerEXT GLEW_GET_FUN(__glewColorPointerEXT) +#define glDrawArraysEXT GLEW_GET_FUN(__glewDrawArraysEXT) +#define glEdgeFlagPointerEXT GLEW_GET_FUN(__glewEdgeFlagPointerEXT) +#define glGetPointervEXT GLEW_GET_FUN(__glewGetPointervEXT) +#define glIndexPointerEXT GLEW_GET_FUN(__glewIndexPointerEXT) +#define glNormalPointerEXT GLEW_GET_FUN(__glewNormalPointerEXT) +#define glTexCoordPointerEXT GLEW_GET_FUN(__glewTexCoordPointerEXT) +#define glVertexPointerEXT GLEW_GET_FUN(__glewVertexPointerEXT) + +#define GLEW_EXT_vertex_array GLEW_GET_VAR(__GLEW_EXT_vertex_array) + +#endif /* GL_EXT_vertex_array */ + +/* ------------------------ GL_EXT_vertex_array_bgra ----------------------- */ + +#ifndef GL_EXT_vertex_array_bgra +#define GL_EXT_vertex_array_bgra 1 + +#define GL_BGRA 0x80E1 + +#define GLEW_EXT_vertex_array_bgra GLEW_GET_VAR(__GLEW_EXT_vertex_array_bgra) + +#endif /* GL_EXT_vertex_array_bgra */ + +/* -------------------------- GL_EXT_vertex_shader ------------------------- */ + +#ifndef GL_EXT_vertex_shader +#define GL_EXT_vertex_shader 1 + +#define GL_VERTEX_SHADER_EXT 0x8780 +#define GL_VERTEX_SHADER_BINDING_EXT 0x8781 +#define GL_OP_INDEX_EXT 0x8782 +#define GL_OP_NEGATE_EXT 0x8783 +#define GL_OP_DOT3_EXT 0x8784 +#define GL_OP_DOT4_EXT 0x8785 +#define GL_OP_MUL_EXT 0x8786 +#define GL_OP_ADD_EXT 0x8787 +#define GL_OP_MADD_EXT 0x8788 +#define GL_OP_FRAC_EXT 0x8789 +#define GL_OP_MAX_EXT 0x878A +#define GL_OP_MIN_EXT 0x878B +#define GL_OP_SET_GE_EXT 0x878C +#define GL_OP_SET_LT_EXT 0x878D +#define GL_OP_CLAMP_EXT 0x878E +#define GL_OP_FLOOR_EXT 0x878F +#define GL_OP_ROUND_EXT 0x8790 +#define GL_OP_EXP_BASE_2_EXT 0x8791 +#define GL_OP_LOG_BASE_2_EXT 0x8792 +#define GL_OP_POWER_EXT 0x8793 +#define GL_OP_RECIP_EXT 0x8794 +#define GL_OP_RECIP_SQRT_EXT 0x8795 +#define GL_OP_SUB_EXT 0x8796 +#define GL_OP_CROSS_PRODUCT_EXT 0x8797 +#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798 +#define GL_OP_MOV_EXT 0x8799 +#define GL_OUTPUT_VERTEX_EXT 0x879A +#define GL_OUTPUT_COLOR0_EXT 0x879B +#define GL_OUTPUT_COLOR1_EXT 0x879C +#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D +#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E +#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F +#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0 +#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1 +#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2 +#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3 +#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4 +#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5 +#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6 +#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7 +#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8 +#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9 +#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA +#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB +#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC +#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD +#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE +#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF +#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0 +#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1 +#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2 +#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3 +#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4 +#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5 +#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6 +#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7 +#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8 +#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9 +#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA +#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB +#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC +#define GL_OUTPUT_FOG_EXT 0x87BD +#define GL_SCALAR_EXT 0x87BE +#define GL_VECTOR_EXT 0x87BF +#define GL_MATRIX_EXT 0x87C0 +#define GL_VARIANT_EXT 0x87C1 +#define GL_INVARIANT_EXT 0x87C2 +#define GL_LOCAL_CONSTANT_EXT 0x87C3 +#define GL_LOCAL_EXT 0x87C4 +#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5 +#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6 +#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7 +#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8 +#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9 +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CC +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CD +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE +#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF +#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0 +#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1 +#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2 +#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3 +#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4 +#define GL_X_EXT 0x87D5 +#define GL_Y_EXT 0x87D6 +#define GL_Z_EXT 0x87D7 +#define GL_W_EXT 0x87D8 +#define GL_NEGATIVE_X_EXT 0x87D9 +#define GL_NEGATIVE_Y_EXT 0x87DA +#define GL_NEGATIVE_Z_EXT 0x87DB +#define GL_NEGATIVE_W_EXT 0x87DC +#define GL_ZERO_EXT 0x87DD +#define GL_ONE_EXT 0x87DE +#define GL_NEGATIVE_ONE_EXT 0x87DF +#define GL_NORMALIZED_RANGE_EXT 0x87E0 +#define GL_FULL_RANGE_EXT 0x87E1 +#define GL_CURRENT_VERTEX_EXT 0x87E2 +#define GL_MVP_MATRIX_EXT 0x87E3 +#define GL_VARIANT_VALUE_EXT 0x87E4 +#define GL_VARIANT_DATATYPE_EXT 0x87E5 +#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6 +#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7 +#define GL_VARIANT_ARRAY_EXT 0x87E8 +#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9 +#define GL_INVARIANT_VALUE_EXT 0x87EA +#define GL_INVARIANT_DATATYPE_EXT 0x87EB +#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC +#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED + +typedef void (GLAPIENTRY * PFNGLBEGINVERTEXSHADEREXTPROC) (void); +typedef GLuint (GLAPIENTRY * PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDPARAMETEREXTPROC) (GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value); +typedef void (GLAPIENTRY * PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLENDVERTEXSHADEREXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); +typedef GLuint (GLAPIENTRY * PFNGLGENSYMBOLSEXTPROC) (GLenum dataType, GLenum storageType, GLenum range, GLuint components); +typedef GLuint (GLAPIENTRY * PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range); +typedef void (GLAPIENTRY * PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (GLAPIENTRY * PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (GLAPIENTRY * PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid **data); +typedef void (GLAPIENTRY * PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); +typedef GLboolean (GLAPIENTRY * PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap); +typedef void (GLAPIENTRY * PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr); +typedef void (GLAPIENTRY * PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr); +typedef void (GLAPIENTRY * PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1); +typedef void (GLAPIENTRY * PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2); +typedef void (GLAPIENTRY * PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); +typedef void (GLAPIENTRY * PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); +typedef void (GLAPIENTRY * PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, GLvoid *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTBVEXTPROC) (GLuint id, GLbyte *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTDVEXTPROC) (GLuint id, GLdouble *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTFVEXTPROC) (GLuint id, GLfloat *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTIVEXTPROC) (GLuint id, GLint *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTSVEXTPROC) (GLuint id, GLshort *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTUBVEXTPROC) (GLuint id, GLubyte *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTUIVEXTPROC) (GLuint id, GLuint *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTUSVEXTPROC) (GLuint id, GLushort *addr); +typedef void (GLAPIENTRY * PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); + +#define glBeginVertexShaderEXT GLEW_GET_FUN(__glewBeginVertexShaderEXT) +#define glBindLightParameterEXT GLEW_GET_FUN(__glewBindLightParameterEXT) +#define glBindMaterialParameterEXT GLEW_GET_FUN(__glewBindMaterialParameterEXT) +#define glBindParameterEXT GLEW_GET_FUN(__glewBindParameterEXT) +#define glBindTexGenParameterEXT GLEW_GET_FUN(__glewBindTexGenParameterEXT) +#define glBindTextureUnitParameterEXT GLEW_GET_FUN(__glewBindTextureUnitParameterEXT) +#define glBindVertexShaderEXT GLEW_GET_FUN(__glewBindVertexShaderEXT) +#define glDeleteVertexShaderEXT GLEW_GET_FUN(__glewDeleteVertexShaderEXT) +#define glDisableVariantClientStateEXT GLEW_GET_FUN(__glewDisableVariantClientStateEXT) +#define glEnableVariantClientStateEXT GLEW_GET_FUN(__glewEnableVariantClientStateEXT) +#define glEndVertexShaderEXT GLEW_GET_FUN(__glewEndVertexShaderEXT) +#define glExtractComponentEXT GLEW_GET_FUN(__glewExtractComponentEXT) +#define glGenSymbolsEXT GLEW_GET_FUN(__glewGenSymbolsEXT) +#define glGenVertexShadersEXT GLEW_GET_FUN(__glewGenVertexShadersEXT) +#define glGetInvariantBooleanvEXT GLEW_GET_FUN(__glewGetInvariantBooleanvEXT) +#define glGetInvariantFloatvEXT GLEW_GET_FUN(__glewGetInvariantFloatvEXT) +#define glGetInvariantIntegervEXT GLEW_GET_FUN(__glewGetInvariantIntegervEXT) +#define glGetLocalConstantBooleanvEXT GLEW_GET_FUN(__glewGetLocalConstantBooleanvEXT) +#define glGetLocalConstantFloatvEXT GLEW_GET_FUN(__glewGetLocalConstantFloatvEXT) +#define glGetLocalConstantIntegervEXT GLEW_GET_FUN(__glewGetLocalConstantIntegervEXT) +#define glGetVariantBooleanvEXT GLEW_GET_FUN(__glewGetVariantBooleanvEXT) +#define glGetVariantFloatvEXT GLEW_GET_FUN(__glewGetVariantFloatvEXT) +#define glGetVariantIntegervEXT GLEW_GET_FUN(__glewGetVariantIntegervEXT) +#define glGetVariantPointervEXT GLEW_GET_FUN(__glewGetVariantPointervEXT) +#define glInsertComponentEXT GLEW_GET_FUN(__glewInsertComponentEXT) +#define glIsVariantEnabledEXT GLEW_GET_FUN(__glewIsVariantEnabledEXT) +#define glSetInvariantEXT GLEW_GET_FUN(__glewSetInvariantEXT) +#define glSetLocalConstantEXT GLEW_GET_FUN(__glewSetLocalConstantEXT) +#define glShaderOp1EXT GLEW_GET_FUN(__glewShaderOp1EXT) +#define glShaderOp2EXT GLEW_GET_FUN(__glewShaderOp2EXT) +#define glShaderOp3EXT GLEW_GET_FUN(__glewShaderOp3EXT) +#define glSwizzleEXT GLEW_GET_FUN(__glewSwizzleEXT) +#define glVariantPointerEXT GLEW_GET_FUN(__glewVariantPointerEXT) +#define glVariantbvEXT GLEW_GET_FUN(__glewVariantbvEXT) +#define glVariantdvEXT GLEW_GET_FUN(__glewVariantdvEXT) +#define glVariantfvEXT GLEW_GET_FUN(__glewVariantfvEXT) +#define glVariantivEXT GLEW_GET_FUN(__glewVariantivEXT) +#define glVariantsvEXT GLEW_GET_FUN(__glewVariantsvEXT) +#define glVariantubvEXT GLEW_GET_FUN(__glewVariantubvEXT) +#define glVariantuivEXT GLEW_GET_FUN(__glewVariantuivEXT) +#define glVariantusvEXT GLEW_GET_FUN(__glewVariantusvEXT) +#define glWriteMaskEXT GLEW_GET_FUN(__glewWriteMaskEXT) + +#define GLEW_EXT_vertex_shader GLEW_GET_VAR(__GLEW_EXT_vertex_shader) + +#endif /* GL_EXT_vertex_shader */ + +/* ------------------------ GL_EXT_vertex_weighting ------------------------ */ + +#ifndef GL_EXT_vertex_weighting +#define GL_EXT_vertex_weighting 1 + +#define GL_MODELVIEW0_STACK_DEPTH_EXT 0x0BA3 +#define GL_MODELVIEW0_MATRIX_EXT 0x0BA6 +#define GL_MODELVIEW0_EXT 0x1700 +#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 +#define GL_MODELVIEW1_MATRIX_EXT 0x8506 +#define GL_VERTEX_WEIGHTING_EXT 0x8509 +#define GL_MODELVIEW1_EXT 0x850A +#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B +#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C +#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D +#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E +#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F +#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 + +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFVEXTPROC) (GLfloat* weight); + +#define glVertexWeightPointerEXT GLEW_GET_FUN(__glewVertexWeightPointerEXT) +#define glVertexWeightfEXT GLEW_GET_FUN(__glewVertexWeightfEXT) +#define glVertexWeightfvEXT GLEW_GET_FUN(__glewVertexWeightfvEXT) + +#define GLEW_EXT_vertex_weighting GLEW_GET_VAR(__GLEW_EXT_vertex_weighting) + +#endif /* GL_EXT_vertex_weighting */ + +/* ---------------------- GL_GREMEDY_frame_terminator ---------------------- */ + +#ifndef GL_GREMEDY_frame_terminator +#define GL_GREMEDY_frame_terminator 1 + +typedef void (GLAPIENTRY * PFNGLFRAMETERMINATORGREMEDYPROC) (void); + +#define glFrameTerminatorGREMEDY GLEW_GET_FUN(__glewFrameTerminatorGREMEDY) + +#define GLEW_GREMEDY_frame_terminator GLEW_GET_VAR(__GLEW_GREMEDY_frame_terminator) + +#endif /* GL_GREMEDY_frame_terminator */ + +/* ------------------------ GL_GREMEDY_string_marker ----------------------- */ + +#ifndef GL_GREMEDY_string_marker +#define GL_GREMEDY_string_marker 1 + +typedef void (GLAPIENTRY * PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const void* string); + +#define glStringMarkerGREMEDY GLEW_GET_FUN(__glewStringMarkerGREMEDY) + +#define GLEW_GREMEDY_string_marker GLEW_GET_VAR(__GLEW_GREMEDY_string_marker) + +#endif /* GL_GREMEDY_string_marker */ + +/* --------------------- GL_HP_convolution_border_modes -------------------- */ + +#ifndef GL_HP_convolution_border_modes +#define GL_HP_convolution_border_modes 1 + +#define GLEW_HP_convolution_border_modes GLEW_GET_VAR(__GLEW_HP_convolution_border_modes) + +#endif /* GL_HP_convolution_border_modes */ + +/* ------------------------- GL_HP_image_transform ------------------------- */ + +#ifndef GL_HP_image_transform +#define GL_HP_image_transform 1 + +typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params); + +#define glGetImageTransformParameterfvHP GLEW_GET_FUN(__glewGetImageTransformParameterfvHP) +#define glGetImageTransformParameterivHP GLEW_GET_FUN(__glewGetImageTransformParameterivHP) +#define glImageTransformParameterfHP GLEW_GET_FUN(__glewImageTransformParameterfHP) +#define glImageTransformParameterfvHP GLEW_GET_FUN(__glewImageTransformParameterfvHP) +#define glImageTransformParameteriHP GLEW_GET_FUN(__glewImageTransformParameteriHP) +#define glImageTransformParameterivHP GLEW_GET_FUN(__glewImageTransformParameterivHP) + +#define GLEW_HP_image_transform GLEW_GET_VAR(__GLEW_HP_image_transform) + +#endif /* GL_HP_image_transform */ + +/* -------------------------- GL_HP_occlusion_test ------------------------- */ + +#ifndef GL_HP_occlusion_test +#define GL_HP_occlusion_test 1 + +#define GL_OCCLUSION_TEST_HP 0x8165 +#define GL_OCCLUSION_TEST_RESULT_HP 0x8166 + +#define GLEW_HP_occlusion_test GLEW_GET_VAR(__GLEW_HP_occlusion_test) + +#endif /* GL_HP_occlusion_test */ + +/* ------------------------- GL_HP_texture_lighting ------------------------ */ + +#ifndef GL_HP_texture_lighting +#define GL_HP_texture_lighting 1 + +#define GLEW_HP_texture_lighting GLEW_GET_VAR(__GLEW_HP_texture_lighting) + +#endif /* GL_HP_texture_lighting */ + +/* --------------------------- GL_IBM_cull_vertex -------------------------- */ + +#ifndef GL_IBM_cull_vertex +#define GL_IBM_cull_vertex 1 + +#define GL_CULL_VERTEX_IBM 103050 + +#define GLEW_IBM_cull_vertex GLEW_GET_VAR(__GLEW_IBM_cull_vertex) + +#endif /* GL_IBM_cull_vertex */ + +/* ---------------------- GL_IBM_multimode_draw_arrays --------------------- */ + +#ifndef GL_IBM_multimode_draw_arrays +#define GL_IBM_multimode_draw_arrays 1 + +typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum* mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); +typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum* mode, const GLsizei *count, GLenum type, const GLvoid * const *indices, GLsizei primcount, GLint modestride); + +#define glMultiModeDrawArraysIBM GLEW_GET_FUN(__glewMultiModeDrawArraysIBM) +#define glMultiModeDrawElementsIBM GLEW_GET_FUN(__glewMultiModeDrawElementsIBM) + +#define GLEW_IBM_multimode_draw_arrays GLEW_GET_VAR(__GLEW_IBM_multimode_draw_arrays) + +#endif /* GL_IBM_multimode_draw_arrays */ + +/* ------------------------- GL_IBM_rasterpos_clip ------------------------- */ + +#ifndef GL_IBM_rasterpos_clip +#define GL_IBM_rasterpos_clip 1 + +#define GL_RASTER_POSITION_UNCLIPPED_IBM 103010 + +#define GLEW_IBM_rasterpos_clip GLEW_GET_VAR(__GLEW_IBM_rasterpos_clip) + +#endif /* GL_IBM_rasterpos_clip */ + +/* --------------------------- GL_IBM_static_data -------------------------- */ + +#ifndef GL_IBM_static_data +#define GL_IBM_static_data 1 + +#define GL_ALL_STATIC_DATA_IBM 103060 +#define GL_STATIC_VERTEX_ARRAY_IBM 103061 + +#define GLEW_IBM_static_data GLEW_GET_VAR(__GLEW_IBM_static_data) + +#endif /* GL_IBM_static_data */ + +/* --------------------- GL_IBM_texture_mirrored_repeat -------------------- */ + +#ifndef GL_IBM_texture_mirrored_repeat +#define GL_IBM_texture_mirrored_repeat 1 + +#define GL_MIRRORED_REPEAT_IBM 0x8370 + +#define GLEW_IBM_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_IBM_texture_mirrored_repeat) + +#endif /* GL_IBM_texture_mirrored_repeat */ + +/* ----------------------- GL_IBM_vertex_array_lists ----------------------- */ + +#ifndef GL_IBM_vertex_array_lists +#define GL_IBM_vertex_array_lists 1 + +#define GL_VERTEX_ARRAY_LIST_IBM 103070 +#define GL_NORMAL_ARRAY_LIST_IBM 103071 +#define GL_COLOR_ARRAY_LIST_IBM 103072 +#define GL_INDEX_ARRAY_LIST_IBM 103073 +#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074 +#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075 +#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076 +#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077 +#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080 +#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081 +#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082 +#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083 +#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084 +#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085 +#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 +#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 + +typedef void (GLAPIENTRY * PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); + +#define glColorPointerListIBM GLEW_GET_FUN(__glewColorPointerListIBM) +#define glEdgeFlagPointerListIBM GLEW_GET_FUN(__glewEdgeFlagPointerListIBM) +#define glFogCoordPointerListIBM GLEW_GET_FUN(__glewFogCoordPointerListIBM) +#define glIndexPointerListIBM GLEW_GET_FUN(__glewIndexPointerListIBM) +#define glNormalPointerListIBM GLEW_GET_FUN(__glewNormalPointerListIBM) +#define glSecondaryColorPointerListIBM GLEW_GET_FUN(__glewSecondaryColorPointerListIBM) +#define glTexCoordPointerListIBM GLEW_GET_FUN(__glewTexCoordPointerListIBM) +#define glVertexPointerListIBM GLEW_GET_FUN(__glewVertexPointerListIBM) + +#define GLEW_IBM_vertex_array_lists GLEW_GET_VAR(__GLEW_IBM_vertex_array_lists) + +#endif /* GL_IBM_vertex_array_lists */ + +/* -------------------------- GL_INGR_color_clamp -------------------------- */ + +#ifndef GL_INGR_color_clamp +#define GL_INGR_color_clamp 1 + +#define GL_RED_MIN_CLAMP_INGR 0x8560 +#define GL_GREEN_MIN_CLAMP_INGR 0x8561 +#define GL_BLUE_MIN_CLAMP_INGR 0x8562 +#define GL_ALPHA_MIN_CLAMP_INGR 0x8563 +#define GL_RED_MAX_CLAMP_INGR 0x8564 +#define GL_GREEN_MAX_CLAMP_INGR 0x8565 +#define GL_BLUE_MAX_CLAMP_INGR 0x8566 +#define GL_ALPHA_MAX_CLAMP_INGR 0x8567 + +#define GLEW_INGR_color_clamp GLEW_GET_VAR(__GLEW_INGR_color_clamp) + +#endif /* GL_INGR_color_clamp */ + +/* ------------------------- GL_INGR_interlace_read ------------------------ */ + +#ifndef GL_INGR_interlace_read +#define GL_INGR_interlace_read 1 + +#define GL_INTERLACE_READ_INGR 0x8568 + +#define GLEW_INGR_interlace_read GLEW_GET_VAR(__GLEW_INGR_interlace_read) + +#endif /* GL_INGR_interlace_read */ + +/* ------------------------ GL_INTEL_parallel_arrays ----------------------- */ + +#ifndef GL_INTEL_parallel_arrays +#define GL_INTEL_parallel_arrays 1 + +#define GL_PARALLEL_ARRAYS_INTEL 0x83F4 +#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5 +#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6 +#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7 +#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8 + +typedef void (GLAPIENTRY * PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer); +typedef void (GLAPIENTRY * PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const void** pointer); +typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer); + +#define glColorPointervINTEL GLEW_GET_FUN(__glewColorPointervINTEL) +#define glNormalPointervINTEL GLEW_GET_FUN(__glewNormalPointervINTEL) +#define glTexCoordPointervINTEL GLEW_GET_FUN(__glewTexCoordPointervINTEL) +#define glVertexPointervINTEL GLEW_GET_FUN(__glewVertexPointervINTEL) + +#define GLEW_INTEL_parallel_arrays GLEW_GET_VAR(__GLEW_INTEL_parallel_arrays) + +#endif /* GL_INTEL_parallel_arrays */ + +/* ------------------------ GL_INTEL_texture_scissor ----------------------- */ + +#ifndef GL_INTEL_texture_scissor +#define GL_INTEL_texture_scissor 1 + +typedef void (GLAPIENTRY * PFNGLTEXSCISSORFUNCINTELPROC) (GLenum target, GLenum lfunc, GLenum hfunc); +typedef void (GLAPIENTRY * PFNGLTEXSCISSORINTELPROC) (GLenum target, GLclampf tlow, GLclampf thigh); + +#define glTexScissorFuncINTEL GLEW_GET_FUN(__glewTexScissorFuncINTEL) +#define glTexScissorINTEL GLEW_GET_FUN(__glewTexScissorINTEL) + +#define GLEW_INTEL_texture_scissor GLEW_GET_VAR(__GLEW_INTEL_texture_scissor) + +#endif /* GL_INTEL_texture_scissor */ + +/* -------------------------- GL_KTX_buffer_region ------------------------- */ + +#ifndef GL_KTX_buffer_region +#define GL_KTX_buffer_region 1 + +#define GL_KTX_FRONT_REGION 0x0 +#define GL_KTX_BACK_REGION 0x1 +#define GL_KTX_Z_REGION 0x2 +#define GL_KTX_STENCIL_REGION 0x3 + +typedef GLuint (GLAPIENTRY * PFNGLBUFFERREGIONENABLEDEXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLDELETEBUFFERREGIONEXTPROC) (GLenum region); +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERREGIONEXTPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height, GLint xDest, GLint yDest); +typedef GLuint (GLAPIENTRY * PFNGLNEWBUFFERREGIONEXTPROC) (GLenum region); +typedef void (GLAPIENTRY * PFNGLREADBUFFERREGIONEXTPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height); + +#define glBufferRegionEnabledEXT GLEW_GET_FUN(__glewBufferRegionEnabledEXT) +#define glDeleteBufferRegionEXT GLEW_GET_FUN(__glewDeleteBufferRegionEXT) +#define glDrawBufferRegionEXT GLEW_GET_FUN(__glewDrawBufferRegionEXT) +#define glNewBufferRegionEXT GLEW_GET_FUN(__glewNewBufferRegionEXT) +#define glReadBufferRegionEXT GLEW_GET_FUN(__glewReadBufferRegionEXT) + +#define GLEW_KTX_buffer_region GLEW_GET_VAR(__GLEW_KTX_buffer_region) + +#endif /* GL_KTX_buffer_region */ + +/* ------------------------- GL_MESAX_texture_stack ------------------------ */ + +#ifndef GL_MESAX_texture_stack +#define GL_MESAX_texture_stack 1 + +#define GL_TEXTURE_1D_STACK_MESAX 0x8759 +#define GL_TEXTURE_2D_STACK_MESAX 0x875A +#define GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B +#define GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C +#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D +#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E + +#define GLEW_MESAX_texture_stack GLEW_GET_VAR(__GLEW_MESAX_texture_stack) + +#endif /* GL_MESAX_texture_stack */ + +/* -------------------------- GL_MESA_pack_invert -------------------------- */ + +#ifndef GL_MESA_pack_invert +#define GL_MESA_pack_invert 1 + +#define GL_PACK_INVERT_MESA 0x8758 + +#define GLEW_MESA_pack_invert GLEW_GET_VAR(__GLEW_MESA_pack_invert) + +#endif /* GL_MESA_pack_invert */ + +/* ------------------------- GL_MESA_resize_buffers ------------------------ */ + +#ifndef GL_MESA_resize_buffers +#define GL_MESA_resize_buffers 1 + +typedef void (GLAPIENTRY * PFNGLRESIZEBUFFERSMESAPROC) (void); + +#define glResizeBuffersMESA GLEW_GET_FUN(__glewResizeBuffersMESA) + +#define GLEW_MESA_resize_buffers GLEW_GET_VAR(__GLEW_MESA_resize_buffers) + +#endif /* GL_MESA_resize_buffers */ + +/* --------------------------- GL_MESA_window_pos -------------------------- */ + +#ifndef GL_MESA_window_pos +#define GL_MESA_window_pos 1 + +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVMESAPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVMESAPROC) (const GLshort* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVMESAPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVMESAPROC) (const GLshort* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IVMESAPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort* p); + +#define glWindowPos2dMESA GLEW_GET_FUN(__glewWindowPos2dMESA) +#define glWindowPos2dvMESA GLEW_GET_FUN(__glewWindowPos2dvMESA) +#define glWindowPos2fMESA GLEW_GET_FUN(__glewWindowPos2fMESA) +#define glWindowPos2fvMESA GLEW_GET_FUN(__glewWindowPos2fvMESA) +#define glWindowPos2iMESA GLEW_GET_FUN(__glewWindowPos2iMESA) +#define glWindowPos2ivMESA GLEW_GET_FUN(__glewWindowPos2ivMESA) +#define glWindowPos2sMESA GLEW_GET_FUN(__glewWindowPos2sMESA) +#define glWindowPos2svMESA GLEW_GET_FUN(__glewWindowPos2svMESA) +#define glWindowPos3dMESA GLEW_GET_FUN(__glewWindowPos3dMESA) +#define glWindowPos3dvMESA GLEW_GET_FUN(__glewWindowPos3dvMESA) +#define glWindowPos3fMESA GLEW_GET_FUN(__glewWindowPos3fMESA) +#define glWindowPos3fvMESA GLEW_GET_FUN(__glewWindowPos3fvMESA) +#define glWindowPos3iMESA GLEW_GET_FUN(__glewWindowPos3iMESA) +#define glWindowPos3ivMESA GLEW_GET_FUN(__glewWindowPos3ivMESA) +#define glWindowPos3sMESA GLEW_GET_FUN(__glewWindowPos3sMESA) +#define glWindowPos3svMESA GLEW_GET_FUN(__glewWindowPos3svMESA) +#define glWindowPos4dMESA GLEW_GET_FUN(__glewWindowPos4dMESA) +#define glWindowPos4dvMESA GLEW_GET_FUN(__glewWindowPos4dvMESA) +#define glWindowPos4fMESA GLEW_GET_FUN(__glewWindowPos4fMESA) +#define glWindowPos4fvMESA GLEW_GET_FUN(__glewWindowPos4fvMESA) +#define glWindowPos4iMESA GLEW_GET_FUN(__glewWindowPos4iMESA) +#define glWindowPos4ivMESA GLEW_GET_FUN(__glewWindowPos4ivMESA) +#define glWindowPos4sMESA GLEW_GET_FUN(__glewWindowPos4sMESA) +#define glWindowPos4svMESA GLEW_GET_FUN(__glewWindowPos4svMESA) + +#define GLEW_MESA_window_pos GLEW_GET_VAR(__GLEW_MESA_window_pos) + +#endif /* GL_MESA_window_pos */ + +/* ------------------------- GL_MESA_ycbcr_texture ------------------------- */ + +#ifndef GL_MESA_ycbcr_texture +#define GL_MESA_ycbcr_texture 1 + +#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB +#define GL_YCBCR_MESA 0x8757 + +#define GLEW_MESA_ycbcr_texture GLEW_GET_VAR(__GLEW_MESA_ycbcr_texture) + +#endif /* GL_MESA_ycbcr_texture */ + +/* --------------------------- GL_NV_blend_square -------------------------- */ + +#ifndef GL_NV_blend_square +#define GL_NV_blend_square 1 + +#define GLEW_NV_blend_square GLEW_GET_VAR(__GLEW_NV_blend_square) + +#endif /* GL_NV_blend_square */ + +/* ------------------------ GL_NV_conditional_render ----------------------- */ + +#ifndef GL_NV_conditional_render +#define GL_NV_conditional_render 1 + +#define GL_QUERY_WAIT_NV 0x8E13 +#define GL_QUERY_NO_WAIT_NV 0x8E14 +#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16 + +typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode); +typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERNVPROC) (void); + +#define glBeginConditionalRenderNV GLEW_GET_FUN(__glewBeginConditionalRenderNV) +#define glEndConditionalRenderNV GLEW_GET_FUN(__glewEndConditionalRenderNV) + +#define GLEW_NV_conditional_render GLEW_GET_VAR(__GLEW_NV_conditional_render) + +#endif /* GL_NV_conditional_render */ + +/* ----------------------- GL_NV_copy_depth_to_color ----------------------- */ + +#ifndef GL_NV_copy_depth_to_color +#define GL_NV_copy_depth_to_color 1 + +#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E +#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F + +#define GLEW_NV_copy_depth_to_color GLEW_GET_VAR(__GLEW_NV_copy_depth_to_color) + +#endif /* GL_NV_copy_depth_to_color */ + +/* ------------------------ GL_NV_depth_buffer_float ----------------------- */ + +#ifndef GL_NV_depth_buffer_float +#define GL_NV_depth_buffer_float 1 + +#define GL_DEPTH_COMPONENT32F_NV 0x8DAB +#define GL_DEPTH32F_STENCIL8_NV 0x8DAC +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD +#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF + +typedef void (GLAPIENTRY * PFNGLCLEARDEPTHDNVPROC) (GLdouble depth); +typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax); +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar); + +#define glClearDepthdNV GLEW_GET_FUN(__glewClearDepthdNV) +#define glDepthBoundsdNV GLEW_GET_FUN(__glewDepthBoundsdNV) +#define glDepthRangedNV GLEW_GET_FUN(__glewDepthRangedNV) + +#define GLEW_NV_depth_buffer_float GLEW_GET_VAR(__GLEW_NV_depth_buffer_float) + +#endif /* GL_NV_depth_buffer_float */ + +/* --------------------------- GL_NV_depth_clamp --------------------------- */ + +#ifndef GL_NV_depth_clamp +#define GL_NV_depth_clamp 1 + +#define GL_DEPTH_CLAMP_NV 0x864F + +#define GLEW_NV_depth_clamp GLEW_GET_VAR(__GLEW_NV_depth_clamp) + +#endif /* GL_NV_depth_clamp */ + +/* ---------------------- GL_NV_depth_range_unclamped ---------------------- */ + +#ifndef GL_NV_depth_range_unclamped +#define GL_NV_depth_range_unclamped 1 + +#define GL_SAMPLE_COUNT_BITS_NV 0x8864 +#define GL_CURRENT_SAMPLE_COUNT_QUERY_NV 0x8865 +#define GL_QUERY_RESULT_NV 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_NV 0x8867 +#define GL_SAMPLE_COUNT_NV 0x8914 + +#define GLEW_NV_depth_range_unclamped GLEW_GET_VAR(__GLEW_NV_depth_range_unclamped) + +#endif /* GL_NV_depth_range_unclamped */ + +/* ---------------------------- GL_NV_evaluators --------------------------- */ + +#ifndef GL_NV_evaluators +#define GL_NV_evaluators 1 + +#define GL_EVAL_2D_NV 0x86C0 +#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1 +#define GL_MAP_TESSELLATION_NV 0x86C2 +#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3 +#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4 +#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5 +#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6 +#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7 +#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8 +#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9 +#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA +#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB +#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC +#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD +#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE +#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF +#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0 +#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1 +#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2 +#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3 +#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4 +#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5 +#define GL_MAX_MAP_TESSELLATION_NV 0x86D6 +#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7 + +typedef void (GLAPIENTRY * PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); +typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void* points); +typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void* points); +typedef void (GLAPIENTRY * PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint* params); + +#define glEvalMapsNV GLEW_GET_FUN(__glewEvalMapsNV) +#define glGetMapAttribParameterfvNV GLEW_GET_FUN(__glewGetMapAttribParameterfvNV) +#define glGetMapAttribParameterivNV GLEW_GET_FUN(__glewGetMapAttribParameterivNV) +#define glGetMapControlPointsNV GLEW_GET_FUN(__glewGetMapControlPointsNV) +#define glGetMapParameterfvNV GLEW_GET_FUN(__glewGetMapParameterfvNV) +#define glGetMapParameterivNV GLEW_GET_FUN(__glewGetMapParameterivNV) +#define glMapControlPointsNV GLEW_GET_FUN(__glewMapControlPointsNV) +#define glMapParameterfvNV GLEW_GET_FUN(__glewMapParameterfvNV) +#define glMapParameterivNV GLEW_GET_FUN(__glewMapParameterivNV) + +#define GLEW_NV_evaluators GLEW_GET_VAR(__GLEW_NV_evaluators) + +#endif /* GL_NV_evaluators */ + +/* ----------------------- GL_NV_explicit_multisample ---------------------- */ + +#ifndef GL_NV_explicit_multisample +#define GL_NV_explicit_multisample 1 + +#define GL_SAMPLE_POSITION_NV 0x8E50 +#define GL_SAMPLE_MASK_NV 0x8E51 +#define GL_SAMPLE_MASK_VALUE_NV 0x8E52 +#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53 +#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54 +#define GL_TEXTURE_RENDERBUFFER_NV 0x8E55 +#define GL_SAMPLER_RENDERBUFFER_NV 0x8E56 +#define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57 +#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58 +#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59 + +typedef void (GLAPIENTRY * PFNGLGETMULTISAMPLEFVNVPROC) (GLenum pname, GLuint index, GLfloat* val); +typedef void (GLAPIENTRY * PFNGLSAMPLEMASKINDEXEDNVPROC) (GLuint index, GLbitfield mask); +typedef void (GLAPIENTRY * PFNGLTEXRENDERBUFFERNVPROC) (GLenum target, GLuint renderbuffer); + +#define glGetMultisamplefvNV GLEW_GET_FUN(__glewGetMultisamplefvNV) +#define glSampleMaskIndexedNV GLEW_GET_FUN(__glewSampleMaskIndexedNV) +#define glTexRenderbufferNV GLEW_GET_FUN(__glewTexRenderbufferNV) + +#define GLEW_NV_explicit_multisample GLEW_GET_VAR(__GLEW_NV_explicit_multisample) + +#endif /* GL_NV_explicit_multisample */ + +/* ------------------------------ GL_NV_fence ------------------------------ */ + +#ifndef GL_NV_fence +#define GL_NV_fence 1 + +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 + +typedef void (GLAPIENTRY * PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint* fences); +typedef void (GLAPIENTRY * PFNGLFINISHFENCENVPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLGENFENCESNVPROC) (GLsizei n, GLuint* fences); +typedef void (GLAPIENTRY * PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISFENCENVPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); +typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCENVPROC) (GLuint fence); + +#define glDeleteFencesNV GLEW_GET_FUN(__glewDeleteFencesNV) +#define glFinishFenceNV GLEW_GET_FUN(__glewFinishFenceNV) +#define glGenFencesNV GLEW_GET_FUN(__glewGenFencesNV) +#define glGetFenceivNV GLEW_GET_FUN(__glewGetFenceivNV) +#define glIsFenceNV GLEW_GET_FUN(__glewIsFenceNV) +#define glSetFenceNV GLEW_GET_FUN(__glewSetFenceNV) +#define glTestFenceNV GLEW_GET_FUN(__glewTestFenceNV) + +#define GLEW_NV_fence GLEW_GET_VAR(__GLEW_NV_fence) + +#endif /* GL_NV_fence */ + +/* --------------------------- GL_NV_float_buffer -------------------------- */ + +#ifndef GL_NV_float_buffer +#define GL_NV_float_buffer 1 + +#define GL_FLOAT_R_NV 0x8880 +#define GL_FLOAT_RG_NV 0x8881 +#define GL_FLOAT_RGB_NV 0x8882 +#define GL_FLOAT_RGBA_NV 0x8883 +#define GL_FLOAT_R16_NV 0x8884 +#define GL_FLOAT_R32_NV 0x8885 +#define GL_FLOAT_RG16_NV 0x8886 +#define GL_FLOAT_RG32_NV 0x8887 +#define GL_FLOAT_RGB16_NV 0x8888 +#define GL_FLOAT_RGB32_NV 0x8889 +#define GL_FLOAT_RGBA16_NV 0x888A +#define GL_FLOAT_RGBA32_NV 0x888B +#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C +#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D +#define GL_FLOAT_RGBA_MODE_NV 0x888E + +#define GLEW_NV_float_buffer GLEW_GET_VAR(__GLEW_NV_float_buffer) + +#endif /* GL_NV_float_buffer */ + +/* --------------------------- GL_NV_fog_distance -------------------------- */ + +#ifndef GL_NV_fog_distance +#define GL_NV_fog_distance 1 + +#define GL_FOG_DISTANCE_MODE_NV 0x855A +#define GL_EYE_RADIAL_NV 0x855B +#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C + +#define GLEW_NV_fog_distance GLEW_GET_VAR(__GLEW_NV_fog_distance) + +#endif /* GL_NV_fog_distance */ + +/* ------------------------- GL_NV_fragment_program ------------------------ */ + +#ifndef GL_NV_fragment_program +#define GL_NV_fragment_program 1 + +#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868 +#define GL_FRAGMENT_PROGRAM_NV 0x8870 +#define GL_MAX_TEXTURE_COORDS_NV 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872 +#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873 +#define GL_PROGRAM_ERROR_STRING_NV 0x8874 + +typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble *params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLdouble v[]); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLfloat v[]); + +#define glGetProgramNamedParameterdvNV GLEW_GET_FUN(__glewGetProgramNamedParameterdvNV) +#define glGetProgramNamedParameterfvNV GLEW_GET_FUN(__glewGetProgramNamedParameterfvNV) +#define glProgramNamedParameter4dNV GLEW_GET_FUN(__glewProgramNamedParameter4dNV) +#define glProgramNamedParameter4dvNV GLEW_GET_FUN(__glewProgramNamedParameter4dvNV) +#define glProgramNamedParameter4fNV GLEW_GET_FUN(__glewProgramNamedParameter4fNV) +#define glProgramNamedParameter4fvNV GLEW_GET_FUN(__glewProgramNamedParameter4fvNV) + +#define GLEW_NV_fragment_program GLEW_GET_VAR(__GLEW_NV_fragment_program) + +#endif /* GL_NV_fragment_program */ + +/* ------------------------ GL_NV_fragment_program2 ------------------------ */ + +#ifndef GL_NV_fragment_program2 +#define GL_NV_fragment_program2 1 + +#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 +#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 +#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6 +#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7 +#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8 + +#define GLEW_NV_fragment_program2 GLEW_GET_VAR(__GLEW_NV_fragment_program2) + +#endif /* GL_NV_fragment_program2 */ + +/* ------------------------ GL_NV_fragment_program4 ------------------------ */ + +#ifndef GL_NV_fragment_program4 +#define GL_NV_fragment_program4 1 + +#define GLEW_NV_fragment_program4 GLEW_GET_VAR(__GLEW_NV_fragment_program4) + +#endif /* GL_NV_fragment_program4 */ + +/* --------------------- GL_NV_fragment_program_option --------------------- */ + +#ifndef GL_NV_fragment_program_option +#define GL_NV_fragment_program_option 1 + +#define GLEW_NV_fragment_program_option GLEW_GET_VAR(__GLEW_NV_fragment_program_option) + +#endif /* GL_NV_fragment_program_option */ + +/* ----------------- GL_NV_framebuffer_multisample_coverage ---------------- */ + +#ifndef GL_NV_framebuffer_multisample_coverage +#define GL_NV_framebuffer_multisample_coverage 1 + +#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB +#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10 +#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11 +#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12 + +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); + +#define glRenderbufferStorageMultisampleCoverageNV GLEW_GET_FUN(__glewRenderbufferStorageMultisampleCoverageNV) + +#define GLEW_NV_framebuffer_multisample_coverage GLEW_GET_VAR(__GLEW_NV_framebuffer_multisample_coverage) + +#endif /* GL_NV_framebuffer_multisample_coverage */ + +/* ------------------------ GL_NV_geometry_program4 ------------------------ */ + +#ifndef GL_NV_geometry_program4 +#define GL_NV_geometry_program4 1 + +#define GL_GEOMETRY_PROGRAM_NV 0x8C26 +#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27 +#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28 + +typedef void (GLAPIENTRY * PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit); + +#define glProgramVertexLimitNV GLEW_GET_FUN(__glewProgramVertexLimitNV) + +#define GLEW_NV_geometry_program4 GLEW_GET_VAR(__GLEW_NV_geometry_program4) + +#endif /* GL_NV_geometry_program4 */ + +/* ------------------------- GL_NV_geometry_shader4 ------------------------ */ + +#ifndef GL_NV_geometry_shader4 +#define GL_NV_geometry_shader4 1 + +#define GLEW_NV_geometry_shader4 GLEW_GET_VAR(__GLEW_NV_geometry_shader4) + +#endif /* GL_NV_geometry_shader4 */ + +/* --------------------------- GL_NV_gpu_program4 -------------------------- */ + +#ifndef GL_NV_gpu_program4 +#define GL_NV_gpu_program4 1 + +#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV 0x8905 +#define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906 +#define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907 +#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908 +#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909 +#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5 +#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6 + +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); + +#define glProgramEnvParameterI4iNV GLEW_GET_FUN(__glewProgramEnvParameterI4iNV) +#define glProgramEnvParameterI4ivNV GLEW_GET_FUN(__glewProgramEnvParameterI4ivNV) +#define glProgramEnvParameterI4uiNV GLEW_GET_FUN(__glewProgramEnvParameterI4uiNV) +#define glProgramEnvParameterI4uivNV GLEW_GET_FUN(__glewProgramEnvParameterI4uivNV) +#define glProgramEnvParametersI4ivNV GLEW_GET_FUN(__glewProgramEnvParametersI4ivNV) +#define glProgramEnvParametersI4uivNV GLEW_GET_FUN(__glewProgramEnvParametersI4uivNV) +#define glProgramLocalParameterI4iNV GLEW_GET_FUN(__glewProgramLocalParameterI4iNV) +#define glProgramLocalParameterI4ivNV GLEW_GET_FUN(__glewProgramLocalParameterI4ivNV) +#define glProgramLocalParameterI4uiNV GLEW_GET_FUN(__glewProgramLocalParameterI4uiNV) +#define glProgramLocalParameterI4uivNV GLEW_GET_FUN(__glewProgramLocalParameterI4uivNV) +#define glProgramLocalParametersI4ivNV GLEW_GET_FUN(__glewProgramLocalParametersI4ivNV) +#define glProgramLocalParametersI4uivNV GLEW_GET_FUN(__glewProgramLocalParametersI4uivNV) + +#define GLEW_NV_gpu_program4 GLEW_GET_VAR(__GLEW_NV_gpu_program4) + +#endif /* GL_NV_gpu_program4 */ + +/* ---------------------------- GL_NV_half_float --------------------------- */ + +#ifndef GL_NV_half_float +#define GL_NV_half_float 1 + +#define GL_HALF_FLOAT_NV 0x140B + +typedef unsigned short GLhalf; + +typedef void (GLAPIENTRY * PFNGLCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue); +typedef void (GLAPIENTRY * PFNGLCOLOR3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLCOLOR4HNVPROC) (GLhalf red, GLhalf green, GLhalf blue, GLhalf alpha); +typedef void (GLAPIENTRY * PFNGLCOLOR4HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLFOGCOORDHNVPROC) (GLhalf fog); +typedef void (GLAPIENTRY * PFNGLFOGCOORDHVNVPROC) (const GLhalf* fog); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalf s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalf s, GLhalf t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r, GLhalf q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLNORMAL3HNVPROC) (GLhalf nx, GLhalf ny, GLhalf nz); +typedef void (GLAPIENTRY * PFNGLNORMAL3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD1HNVPROC) (GLhalf s); +typedef void (GLAPIENTRY * PFNGLTEXCOORD1HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2HNVPROC) (GLhalf s, GLhalf t); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD3HNVPROC) (GLhalf s, GLhalf t, GLhalf r); +typedef void (GLAPIENTRY * PFNGLTEXCOORD3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4HNVPROC) (GLhalf s, GLhalf t, GLhalf r, GLhalf q); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEX2HNVPROC) (GLhalf x, GLhalf y); +typedef void (GLAPIENTRY * PFNGLVERTEX2HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEX3HNVPROC) (GLhalf x, GLhalf y, GLhalf z); +typedef void (GLAPIENTRY * PFNGLVERTEX3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEX4HNVPROC) (GLhalf x, GLhalf y, GLhalf z, GLhalf w); +typedef void (GLAPIENTRY * PFNGLVERTEX4HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalf x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalf x, GLhalf y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z, GLhalf w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHNVPROC) (GLhalf weight); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalf* weight); + +#define glColor3hNV GLEW_GET_FUN(__glewColor3hNV) +#define glColor3hvNV GLEW_GET_FUN(__glewColor3hvNV) +#define glColor4hNV GLEW_GET_FUN(__glewColor4hNV) +#define glColor4hvNV GLEW_GET_FUN(__glewColor4hvNV) +#define glFogCoordhNV GLEW_GET_FUN(__glewFogCoordhNV) +#define glFogCoordhvNV GLEW_GET_FUN(__glewFogCoordhvNV) +#define glMultiTexCoord1hNV GLEW_GET_FUN(__glewMultiTexCoord1hNV) +#define glMultiTexCoord1hvNV GLEW_GET_FUN(__glewMultiTexCoord1hvNV) +#define glMultiTexCoord2hNV GLEW_GET_FUN(__glewMultiTexCoord2hNV) +#define glMultiTexCoord2hvNV GLEW_GET_FUN(__glewMultiTexCoord2hvNV) +#define glMultiTexCoord3hNV GLEW_GET_FUN(__glewMultiTexCoord3hNV) +#define glMultiTexCoord3hvNV GLEW_GET_FUN(__glewMultiTexCoord3hvNV) +#define glMultiTexCoord4hNV GLEW_GET_FUN(__glewMultiTexCoord4hNV) +#define glMultiTexCoord4hvNV GLEW_GET_FUN(__glewMultiTexCoord4hvNV) +#define glNormal3hNV GLEW_GET_FUN(__glewNormal3hNV) +#define glNormal3hvNV GLEW_GET_FUN(__glewNormal3hvNV) +#define glSecondaryColor3hNV GLEW_GET_FUN(__glewSecondaryColor3hNV) +#define glSecondaryColor3hvNV GLEW_GET_FUN(__glewSecondaryColor3hvNV) +#define glTexCoord1hNV GLEW_GET_FUN(__glewTexCoord1hNV) +#define glTexCoord1hvNV GLEW_GET_FUN(__glewTexCoord1hvNV) +#define glTexCoord2hNV GLEW_GET_FUN(__glewTexCoord2hNV) +#define glTexCoord2hvNV GLEW_GET_FUN(__glewTexCoord2hvNV) +#define glTexCoord3hNV GLEW_GET_FUN(__glewTexCoord3hNV) +#define glTexCoord3hvNV GLEW_GET_FUN(__glewTexCoord3hvNV) +#define glTexCoord4hNV GLEW_GET_FUN(__glewTexCoord4hNV) +#define glTexCoord4hvNV GLEW_GET_FUN(__glewTexCoord4hvNV) +#define glVertex2hNV GLEW_GET_FUN(__glewVertex2hNV) +#define glVertex2hvNV GLEW_GET_FUN(__glewVertex2hvNV) +#define glVertex3hNV GLEW_GET_FUN(__glewVertex3hNV) +#define glVertex3hvNV GLEW_GET_FUN(__glewVertex3hvNV) +#define glVertex4hNV GLEW_GET_FUN(__glewVertex4hNV) +#define glVertex4hvNV GLEW_GET_FUN(__glewVertex4hvNV) +#define glVertexAttrib1hNV GLEW_GET_FUN(__glewVertexAttrib1hNV) +#define glVertexAttrib1hvNV GLEW_GET_FUN(__glewVertexAttrib1hvNV) +#define glVertexAttrib2hNV GLEW_GET_FUN(__glewVertexAttrib2hNV) +#define glVertexAttrib2hvNV GLEW_GET_FUN(__glewVertexAttrib2hvNV) +#define glVertexAttrib3hNV GLEW_GET_FUN(__glewVertexAttrib3hNV) +#define glVertexAttrib3hvNV GLEW_GET_FUN(__glewVertexAttrib3hvNV) +#define glVertexAttrib4hNV GLEW_GET_FUN(__glewVertexAttrib4hNV) +#define glVertexAttrib4hvNV GLEW_GET_FUN(__glewVertexAttrib4hvNV) +#define glVertexAttribs1hvNV GLEW_GET_FUN(__glewVertexAttribs1hvNV) +#define glVertexAttribs2hvNV GLEW_GET_FUN(__glewVertexAttribs2hvNV) +#define glVertexAttribs3hvNV GLEW_GET_FUN(__glewVertexAttribs3hvNV) +#define glVertexAttribs4hvNV GLEW_GET_FUN(__glewVertexAttribs4hvNV) +#define glVertexWeighthNV GLEW_GET_FUN(__glewVertexWeighthNV) +#define glVertexWeighthvNV GLEW_GET_FUN(__glewVertexWeighthvNV) + +#define GLEW_NV_half_float GLEW_GET_VAR(__GLEW_NV_half_float) + +#endif /* GL_NV_half_float */ + +/* ------------------------ GL_NV_light_max_exponent ----------------------- */ + +#ifndef GL_NV_light_max_exponent +#define GL_NV_light_max_exponent 1 + +#define GL_MAX_SHININESS_NV 0x8504 +#define GL_MAX_SPOT_EXPONENT_NV 0x8505 + +#define GLEW_NV_light_max_exponent GLEW_GET_VAR(__GLEW_NV_light_max_exponent) + +#endif /* GL_NV_light_max_exponent */ + +/* --------------------- GL_NV_multisample_filter_hint --------------------- */ + +#ifndef GL_NV_multisample_filter_hint +#define GL_NV_multisample_filter_hint 1 + +#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 + +#define GLEW_NV_multisample_filter_hint GLEW_GET_VAR(__GLEW_NV_multisample_filter_hint) + +#endif /* GL_NV_multisample_filter_hint */ + +/* ------------------------- GL_NV_occlusion_query ------------------------- */ + +#ifndef GL_NV_occlusion_query +#define GL_NV_occlusion_query 1 + +#define GL_PIXEL_COUNTER_BITS_NV 0x8864 +#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865 +#define GL_PIXEL_COUNT_NV 0x8866 +#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867 + +typedef void (GLAPIENTRY * PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLENDOCCLUSIONQUERYNVPROC) (void); +typedef void (GLAPIENTRY * PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id); + +#define glBeginOcclusionQueryNV GLEW_GET_FUN(__glewBeginOcclusionQueryNV) +#define glDeleteOcclusionQueriesNV GLEW_GET_FUN(__glewDeleteOcclusionQueriesNV) +#define glEndOcclusionQueryNV GLEW_GET_FUN(__glewEndOcclusionQueryNV) +#define glGenOcclusionQueriesNV GLEW_GET_FUN(__glewGenOcclusionQueriesNV) +#define glGetOcclusionQueryivNV GLEW_GET_FUN(__glewGetOcclusionQueryivNV) +#define glGetOcclusionQueryuivNV GLEW_GET_FUN(__glewGetOcclusionQueryuivNV) +#define glIsOcclusionQueryNV GLEW_GET_FUN(__glewIsOcclusionQueryNV) + +#define GLEW_NV_occlusion_query GLEW_GET_VAR(__GLEW_NV_occlusion_query) + +#endif /* GL_NV_occlusion_query */ + +/* ----------------------- GL_NV_packed_depth_stencil ---------------------- */ + +#ifndef GL_NV_packed_depth_stencil +#define GL_NV_packed_depth_stencil 1 + +#define GL_DEPTH_STENCIL_NV 0x84F9 +#define GL_UNSIGNED_INT_24_8_NV 0x84FA + +#define GLEW_NV_packed_depth_stencil GLEW_GET_VAR(__GLEW_NV_packed_depth_stencil) + +#endif /* GL_NV_packed_depth_stencil */ + +/* --------------------- GL_NV_parameter_buffer_object --------------------- */ + +#ifndef GL_NV_parameter_buffer_object +#define GL_NV_parameter_buffer_object 1 + +#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0 +#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1 +#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2 +#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3 +#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4 + +typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat *params); + +#define glProgramBufferParametersIivNV GLEW_GET_FUN(__glewProgramBufferParametersIivNV) +#define glProgramBufferParametersIuivNV GLEW_GET_FUN(__glewProgramBufferParametersIuivNV) +#define glProgramBufferParametersfvNV GLEW_GET_FUN(__glewProgramBufferParametersfvNV) + +#define GLEW_NV_parameter_buffer_object GLEW_GET_VAR(__GLEW_NV_parameter_buffer_object) + +#endif /* GL_NV_parameter_buffer_object */ + +/* ------------------------- GL_NV_pixel_data_range ------------------------ */ + +#ifndef GL_NV_pixel_data_range +#define GL_NV_pixel_data_range 1 + +#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 +#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879 +#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A +#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B +#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C +#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D + +typedef void (GLAPIENTRY * PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, void* pointer); + +#define glFlushPixelDataRangeNV GLEW_GET_FUN(__glewFlushPixelDataRangeNV) +#define glPixelDataRangeNV GLEW_GET_FUN(__glewPixelDataRangeNV) + +#define GLEW_NV_pixel_data_range GLEW_GET_VAR(__GLEW_NV_pixel_data_range) + +#endif /* GL_NV_pixel_data_range */ + +/* --------------------------- GL_NV_point_sprite -------------------------- */ + +#ifndef GL_NV_point_sprite +#define GL_NV_point_sprite 1 + +#define GL_POINT_SPRITE_NV 0x8861 +#define GL_COORD_REPLACE_NV 0x8862 +#define GL_POINT_SPRITE_R_MODE_NV 0x8863 + +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint* params); + +#define glPointParameteriNV GLEW_GET_FUN(__glewPointParameteriNV) +#define glPointParameterivNV GLEW_GET_FUN(__glewPointParameterivNV) + +#define GLEW_NV_point_sprite GLEW_GET_VAR(__GLEW_NV_point_sprite) + +#endif /* GL_NV_point_sprite */ + +/* -------------------------- GL_NV_present_video -------------------------- */ + +#ifndef GL_NV_present_video +#define GL_NV_present_video 1 + +#define GL_FRAME_NV 0x8E26 +#define GL_FIELDS_NV 0x8E27 +#define GL_CURRENT_TIME_NV 0x8E28 +#define GL_NUM_FILL_STREAMS_NV 0x8E29 +#define GL_PRESENT_TIME_NV 0x8E2A +#define GL_PRESENT_DURATION_NV 0x8E2B + +typedef void (GLAPIENTRY * PFNGLGETVIDEOI64VNVPROC) (GLuint video_slot, GLenum pname, GLint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOIVNVPROC) (GLuint video_slot, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOUI64VNVPROC) (GLuint video_slot, GLenum pname, GLuint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOUIVNVPROC) (GLuint video_slot, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLPRESENTFRAMEDUALFILLNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3); +typedef void (GLAPIENTRY * PFNGLPRESENTFRAMEKEYEDNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1); +typedef void (GLAPIENTRY * PFNGLVIDEOPARAMETERIVNVPROC) (GLuint video_slot, GLenum pname, const GLint* params); + +#define glGetVideoi64vNV GLEW_GET_FUN(__glewGetVideoi64vNV) +#define glGetVideoivNV GLEW_GET_FUN(__glewGetVideoivNV) +#define glGetVideoui64vNV GLEW_GET_FUN(__glewGetVideoui64vNV) +#define glGetVideouivNV GLEW_GET_FUN(__glewGetVideouivNV) +#define glPresentFrameDualFillNV GLEW_GET_FUN(__glewPresentFrameDualFillNV) +#define glPresentFrameKeyedNV GLEW_GET_FUN(__glewPresentFrameKeyedNV) +#define glVideoParameterivNV GLEW_GET_FUN(__glewVideoParameterivNV) + +#define GLEW_NV_present_video GLEW_GET_VAR(__GLEW_NV_present_video) + +#endif /* GL_NV_present_video */ + +/* ------------------------ GL_NV_primitive_restart ------------------------ */ + +#ifndef GL_NV_primitive_restart +#define GL_NV_primitive_restart 1 + +#define GL_PRIMITIVE_RESTART_NV 0x8558 +#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559 + +typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index); +typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTNVPROC) (void); + +#define glPrimitiveRestartIndexNV GLEW_GET_FUN(__glewPrimitiveRestartIndexNV) +#define glPrimitiveRestartNV GLEW_GET_FUN(__glewPrimitiveRestartNV) + +#define GLEW_NV_primitive_restart GLEW_GET_VAR(__GLEW_NV_primitive_restart) + +#endif /* GL_NV_primitive_restart */ + +/* ------------------------ GL_NV_register_combiners ----------------------- */ + +#ifndef GL_NV_register_combiners +#define GL_NV_register_combiners 1 + +#define GL_REGISTER_COMBINERS_NV 0x8522 +#define GL_VARIABLE_A_NV 0x8523 +#define GL_VARIABLE_B_NV 0x8524 +#define GL_VARIABLE_C_NV 0x8525 +#define GL_VARIABLE_D_NV 0x8526 +#define GL_VARIABLE_E_NV 0x8527 +#define GL_VARIABLE_F_NV 0x8528 +#define GL_VARIABLE_G_NV 0x8529 +#define GL_CONSTANT_COLOR0_NV 0x852A +#define GL_CONSTANT_COLOR1_NV 0x852B +#define GL_PRIMARY_COLOR_NV 0x852C +#define GL_SECONDARY_COLOR_NV 0x852D +#define GL_SPARE0_NV 0x852E +#define GL_SPARE1_NV 0x852F +#define GL_DISCARD_NV 0x8530 +#define GL_E_TIMES_F_NV 0x8531 +#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 +#define GL_UNSIGNED_IDENTITY_NV 0x8536 +#define GL_UNSIGNED_INVERT_NV 0x8537 +#define GL_EXPAND_NORMAL_NV 0x8538 +#define GL_EXPAND_NEGATE_NV 0x8539 +#define GL_HALF_BIAS_NORMAL_NV 0x853A +#define GL_HALF_BIAS_NEGATE_NV 0x853B +#define GL_SIGNED_IDENTITY_NV 0x853C +#define GL_SIGNED_NEGATE_NV 0x853D +#define GL_SCALE_BY_TWO_NV 0x853E +#define GL_SCALE_BY_FOUR_NV 0x853F +#define GL_SCALE_BY_ONE_HALF_NV 0x8540 +#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 +#define GL_COMBINER_INPUT_NV 0x8542 +#define GL_COMBINER_MAPPING_NV 0x8543 +#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 +#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 +#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 +#define GL_COMBINER_MUX_SUM_NV 0x8547 +#define GL_COMBINER_SCALE_NV 0x8548 +#define GL_COMBINER_BIAS_NV 0x8549 +#define GL_COMBINER_AB_OUTPUT_NV 0x854A +#define GL_COMBINER_CD_OUTPUT_NV 0x854B +#define GL_COMBINER_SUM_OUTPUT_NV 0x854C +#define GL_MAX_GENERAL_COMBINERS_NV 0x854D +#define GL_NUM_GENERAL_COMBINERS_NV 0x854E +#define GL_COLOR_SUM_CLAMP_NV 0x854F +#define GL_COMBINER0_NV 0x8550 +#define GL_COMBINER1_NV 0x8551 +#define GL_COMBINER2_NV 0x8552 +#define GL_COMBINER3_NV 0x8553 +#define GL_COMBINER4_NV 0x8554 +#define GL_COMBINER5_NV 0x8555 +#define GL_COMBINER6_NV 0x8556 +#define GL_COMBINER7_NV 0x8557 + +typedef void (GLAPIENTRY * PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (GLAPIENTRY * PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint* params); + +#define glCombinerInputNV GLEW_GET_FUN(__glewCombinerInputNV) +#define glCombinerOutputNV GLEW_GET_FUN(__glewCombinerOutputNV) +#define glCombinerParameterfNV GLEW_GET_FUN(__glewCombinerParameterfNV) +#define glCombinerParameterfvNV GLEW_GET_FUN(__glewCombinerParameterfvNV) +#define glCombinerParameteriNV GLEW_GET_FUN(__glewCombinerParameteriNV) +#define glCombinerParameterivNV GLEW_GET_FUN(__glewCombinerParameterivNV) +#define glFinalCombinerInputNV GLEW_GET_FUN(__glewFinalCombinerInputNV) +#define glGetCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetCombinerInputParameterfvNV) +#define glGetCombinerInputParameterivNV GLEW_GET_FUN(__glewGetCombinerInputParameterivNV) +#define glGetCombinerOutputParameterfvNV GLEW_GET_FUN(__glewGetCombinerOutputParameterfvNV) +#define glGetCombinerOutputParameterivNV GLEW_GET_FUN(__glewGetCombinerOutputParameterivNV) +#define glGetFinalCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterfvNV) +#define glGetFinalCombinerInputParameterivNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterivNV) + +#define GLEW_NV_register_combiners GLEW_GET_VAR(__GLEW_NV_register_combiners) + +#endif /* GL_NV_register_combiners */ + +/* ----------------------- GL_NV_register_combiners2 ----------------------- */ + +#ifndef GL_NV_register_combiners2 +#define GL_NV_register_combiners2 1 + +#define GL_PER_STAGE_CONSTANTS_NV 0x8535 + +typedef void (GLAPIENTRY * PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat* params); + +#define glCombinerStageParameterfvNV GLEW_GET_FUN(__glewCombinerStageParameterfvNV) +#define glGetCombinerStageParameterfvNV GLEW_GET_FUN(__glewGetCombinerStageParameterfvNV) + +#define GLEW_NV_register_combiners2 GLEW_GET_VAR(__GLEW_NV_register_combiners2) + +#endif /* GL_NV_register_combiners2 */ + +/* -------------------------- GL_NV_texgen_emboss -------------------------- */ + +#ifndef GL_NV_texgen_emboss +#define GL_NV_texgen_emboss 1 + +#define GL_EMBOSS_LIGHT_NV 0x855D +#define GL_EMBOSS_CONSTANT_NV 0x855E +#define GL_EMBOSS_MAP_NV 0x855F + +#define GLEW_NV_texgen_emboss GLEW_GET_VAR(__GLEW_NV_texgen_emboss) + +#endif /* GL_NV_texgen_emboss */ + +/* ------------------------ GL_NV_texgen_reflection ------------------------ */ + +#ifndef GL_NV_texgen_reflection +#define GL_NV_texgen_reflection 1 + +#define GL_NORMAL_MAP_NV 0x8511 +#define GL_REFLECTION_MAP_NV 0x8512 + +#define GLEW_NV_texgen_reflection GLEW_GET_VAR(__GLEW_NV_texgen_reflection) + +#endif /* GL_NV_texgen_reflection */ + +/* --------------------- GL_NV_texture_compression_vtc --------------------- */ + +#ifndef GL_NV_texture_compression_vtc +#define GL_NV_texture_compression_vtc 1 + +#define GLEW_NV_texture_compression_vtc GLEW_GET_VAR(__GLEW_NV_texture_compression_vtc) + +#endif /* GL_NV_texture_compression_vtc */ + +/* ----------------------- GL_NV_texture_env_combine4 ---------------------- */ + +#ifndef GL_NV_texture_env_combine4 +#define GL_NV_texture_env_combine4 1 + +#define GL_COMBINE4_NV 0x8503 +#define GL_SOURCE3_RGB_NV 0x8583 +#define GL_SOURCE3_ALPHA_NV 0x858B +#define GL_OPERAND3_RGB_NV 0x8593 +#define GL_OPERAND3_ALPHA_NV 0x859B + +#define GLEW_NV_texture_env_combine4 GLEW_GET_VAR(__GLEW_NV_texture_env_combine4) + +#endif /* GL_NV_texture_env_combine4 */ + +/* ---------------------- GL_NV_texture_expand_normal ---------------------- */ + +#ifndef GL_NV_texture_expand_normal +#define GL_NV_texture_expand_normal 1 + +#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F + +#define GLEW_NV_texture_expand_normal GLEW_GET_VAR(__GLEW_NV_texture_expand_normal) + +#endif /* GL_NV_texture_expand_normal */ + +/* ------------------------ GL_NV_texture_rectangle ------------------------ */ + +#ifndef GL_NV_texture_rectangle +#define GL_NV_texture_rectangle 1 + +#define GL_TEXTURE_RECTANGLE_NV 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 + +#define GLEW_NV_texture_rectangle GLEW_GET_VAR(__GLEW_NV_texture_rectangle) + +#endif /* GL_NV_texture_rectangle */ + +/* -------------------------- GL_NV_texture_shader ------------------------- */ + +#ifndef GL_NV_texture_shader +#define GL_NV_texture_shader 1 + +#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C +#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D +#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E +#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9 +#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA +#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB +#define GL_DSDT_MAG_INTENSITY_NV 0x86DC +#define GL_SHADER_CONSISTENT_NV 0x86DD +#define GL_TEXTURE_SHADER_NV 0x86DE +#define GL_SHADER_OPERATION_NV 0x86DF +#define GL_CULL_MODES_NV 0x86E0 +#define GL_OFFSET_TEXTURE_2D_MATRIX_NV 0x86E1 +#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 +#define GL_OFFSET_TEXTURE_2D_SCALE_NV 0x86E2 +#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 +#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 +#define GL_OFFSET_TEXTURE_2D_BIAS_NV 0x86E3 +#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 +#define GL_CONST_EYE_NV 0x86E5 +#define GL_PASS_THROUGH_NV 0x86E6 +#define GL_CULL_FRAGMENT_NV 0x86E7 +#define GL_OFFSET_TEXTURE_2D_NV 0x86E8 +#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9 +#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA +#define GL_DOT_PRODUCT_NV 0x86EC +#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED +#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE +#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0 +#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1 +#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2 +#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3 +#define GL_HILO_NV 0x86F4 +#define GL_DSDT_NV 0x86F5 +#define GL_DSDT_MAG_NV 0x86F6 +#define GL_DSDT_MAG_VIB_NV 0x86F7 +#define GL_HILO16_NV 0x86F8 +#define GL_SIGNED_HILO_NV 0x86F9 +#define GL_SIGNED_HILO16_NV 0x86FA +#define GL_SIGNED_RGBA_NV 0x86FB +#define GL_SIGNED_RGBA8_NV 0x86FC +#define GL_SIGNED_RGB_NV 0x86FE +#define GL_SIGNED_RGB8_NV 0x86FF +#define GL_SIGNED_LUMINANCE_NV 0x8701 +#define GL_SIGNED_LUMINANCE8_NV 0x8702 +#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 +#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 +#define GL_SIGNED_ALPHA_NV 0x8705 +#define GL_SIGNED_ALPHA8_NV 0x8706 +#define GL_SIGNED_INTENSITY_NV 0x8707 +#define GL_SIGNED_INTENSITY8_NV 0x8708 +#define GL_DSDT8_NV 0x8709 +#define GL_DSDT8_MAG8_NV 0x870A +#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B +#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C +#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D +#define GL_HI_SCALE_NV 0x870E +#define GL_LO_SCALE_NV 0x870F +#define GL_DS_SCALE_NV 0x8710 +#define GL_DT_SCALE_NV 0x8711 +#define GL_MAGNITUDE_SCALE_NV 0x8712 +#define GL_VIBRANCE_SCALE_NV 0x8713 +#define GL_HI_BIAS_NV 0x8714 +#define GL_LO_BIAS_NV 0x8715 +#define GL_DS_BIAS_NV 0x8716 +#define GL_DT_BIAS_NV 0x8717 +#define GL_MAGNITUDE_BIAS_NV 0x8718 +#define GL_VIBRANCE_BIAS_NV 0x8719 +#define GL_TEXTURE_BORDER_VALUES_NV 0x871A +#define GL_TEXTURE_HI_SIZE_NV 0x871B +#define GL_TEXTURE_LO_SIZE_NV 0x871C +#define GL_TEXTURE_DS_SIZE_NV 0x871D +#define GL_TEXTURE_DT_SIZE_NV 0x871E +#define GL_TEXTURE_MAG_SIZE_NV 0x871F + +#define GLEW_NV_texture_shader GLEW_GET_VAR(__GLEW_NV_texture_shader) + +#endif /* GL_NV_texture_shader */ + +/* ------------------------- GL_NV_texture_shader2 ------------------------- */ + +#ifndef GL_NV_texture_shader2 +#define GL_NV_texture_shader2 1 + +#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA +#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB +#define GL_DSDT_MAG_INTENSITY_NV 0x86DC +#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF +#define GL_HILO_NV 0x86F4 +#define GL_DSDT_NV 0x86F5 +#define GL_DSDT_MAG_NV 0x86F6 +#define GL_DSDT_MAG_VIB_NV 0x86F7 +#define GL_HILO16_NV 0x86F8 +#define GL_SIGNED_HILO_NV 0x86F9 +#define GL_SIGNED_HILO16_NV 0x86FA +#define GL_SIGNED_RGBA_NV 0x86FB +#define GL_SIGNED_RGBA8_NV 0x86FC +#define GL_SIGNED_RGB_NV 0x86FE +#define GL_SIGNED_RGB8_NV 0x86FF +#define GL_SIGNED_LUMINANCE_NV 0x8701 +#define GL_SIGNED_LUMINANCE8_NV 0x8702 +#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 +#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 +#define GL_SIGNED_ALPHA_NV 0x8705 +#define GL_SIGNED_ALPHA8_NV 0x8706 +#define GL_SIGNED_INTENSITY_NV 0x8707 +#define GL_SIGNED_INTENSITY8_NV 0x8708 +#define GL_DSDT8_NV 0x8709 +#define GL_DSDT8_MAG8_NV 0x870A +#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B +#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C +#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D + +#define GLEW_NV_texture_shader2 GLEW_GET_VAR(__GLEW_NV_texture_shader2) + +#endif /* GL_NV_texture_shader2 */ + +/* ------------------------- GL_NV_texture_shader3 ------------------------- */ + +#ifndef GL_NV_texture_shader3 +#define GL_NV_texture_shader3 1 + +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850 +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853 +#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854 +#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857 +#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858 +#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859 +#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A +#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B +#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C +#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D +#define GL_HILO8_NV 0x885E +#define GL_SIGNED_HILO8_NV 0x885F +#define GL_FORCE_BLUE_TO_ONE_NV 0x8860 + +#define GLEW_NV_texture_shader3 GLEW_GET_VAR(__GLEW_NV_texture_shader3) + +#endif /* GL_NV_texture_shader3 */ + +/* ------------------------ GL_NV_transform_feedback ----------------------- */ + +#ifndef GL_NV_transform_feedback +#define GL_NV_transform_feedback 1 + +#define GL_BACK_PRIMARY_COLOR_NV 0x8C77 +#define GL_BACK_SECONDARY_COLOR_NV 0x8C78 +#define GL_TEXTURE_COORD_NV 0x8C79 +#define GL_CLIP_DISTANCE_NV 0x8C7A +#define GL_VERTEX_ID_NV 0x8C7B +#define GL_PRIMITIVE_ID_NV 0x8C7C +#define GL_GENERIC_ATTRIB_NV 0x8C7D +#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80 +#define GL_ACTIVE_VARYINGS_NV 0x8C81 +#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85 +#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86 +#define GL_PRIMITIVES_GENERATED_NV 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88 +#define GL_RASTERIZER_DISCARD_NV 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B +#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C +#define GL_SEPARATE_ATTRIBS_NV 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F + +typedef void (GLAPIENTRY * PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKNVPROC) (void); +typedef void (GLAPIENTRY * PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location); +typedef GLint (GLAPIENTRY * PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode); + +#define glActiveVaryingNV GLEW_GET_FUN(__glewActiveVaryingNV) +#define glBeginTransformFeedbackNV GLEW_GET_FUN(__glewBeginTransformFeedbackNV) +#define glBindBufferBaseNV GLEW_GET_FUN(__glewBindBufferBaseNV) +#define glBindBufferOffsetNV GLEW_GET_FUN(__glewBindBufferOffsetNV) +#define glBindBufferRangeNV GLEW_GET_FUN(__glewBindBufferRangeNV) +#define glEndTransformFeedbackNV GLEW_GET_FUN(__glewEndTransformFeedbackNV) +#define glGetActiveVaryingNV GLEW_GET_FUN(__glewGetActiveVaryingNV) +#define glGetTransformFeedbackVaryingNV GLEW_GET_FUN(__glewGetTransformFeedbackVaryingNV) +#define glGetVaryingLocationNV GLEW_GET_FUN(__glewGetVaryingLocationNV) +#define glTransformFeedbackAttribsNV GLEW_GET_FUN(__glewTransformFeedbackAttribsNV) +#define glTransformFeedbackVaryingsNV GLEW_GET_FUN(__glewTransformFeedbackVaryingsNV) + +#define GLEW_NV_transform_feedback GLEW_GET_VAR(__GLEW_NV_transform_feedback) + +#endif /* GL_NV_transform_feedback */ + +/* ------------------------ GL_NV_vertex_array_range ----------------------- */ + +#ifndef GL_NV_vertex_array_range +#define GL_NV_vertex_array_range 1 + +#define GL_VERTEX_ARRAY_RANGE_NV 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E +#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F +#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 +#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 + +typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, void* pointer); + +#define glFlushVertexArrayRangeNV GLEW_GET_FUN(__glewFlushVertexArrayRangeNV) +#define glVertexArrayRangeNV GLEW_GET_FUN(__glewVertexArrayRangeNV) + +#define GLEW_NV_vertex_array_range GLEW_GET_VAR(__GLEW_NV_vertex_array_range) + +#endif /* GL_NV_vertex_array_range */ + +/* ----------------------- GL_NV_vertex_array_range2 ----------------------- */ + +#ifndef GL_NV_vertex_array_range2 +#define GL_NV_vertex_array_range2 1 + +#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 + +#define GLEW_NV_vertex_array_range2 GLEW_GET_VAR(__GLEW_NV_vertex_array_range2) + +#endif /* GL_NV_vertex_array_range2 */ + +/* -------------------------- GL_NV_vertex_program ------------------------- */ + +#ifndef GL_NV_vertex_program +#define GL_NV_vertex_program 1 + +#define GL_VERTEX_PROGRAM_NV 0x8620 +#define GL_VERTEX_STATE_PROGRAM_NV 0x8621 +#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 +#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 +#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 +#define GL_CURRENT_ATTRIB_NV 0x8626 +#define GL_PROGRAM_LENGTH_NV 0x8627 +#define GL_PROGRAM_STRING_NV 0x8628 +#define GL_MODELVIEW_PROJECTION_NV 0x8629 +#define GL_IDENTITY_NV 0x862A +#define GL_INVERSE_NV 0x862B +#define GL_TRANSPOSE_NV 0x862C +#define GL_INVERSE_TRANSPOSE_NV 0x862D +#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E +#define GL_MAX_TRACK_MATRICES_NV 0x862F +#define GL_MATRIX0_NV 0x8630 +#define GL_MATRIX1_NV 0x8631 +#define GL_MATRIX2_NV 0x8632 +#define GL_MATRIX3_NV 0x8633 +#define GL_MATRIX4_NV 0x8634 +#define GL_MATRIX5_NV 0x8635 +#define GL_MATRIX6_NV 0x8636 +#define GL_MATRIX7_NV 0x8637 +#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 +#define GL_CURRENT_MATRIX_NV 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 +#define GL_PROGRAM_PARAMETER_NV 0x8644 +#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 +#define GL_PROGRAM_TARGET_NV 0x8646 +#define GL_PROGRAM_RESIDENT_NV 0x8647 +#define GL_TRACK_MATRIX_NV 0x8648 +#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 +#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A +#define GL_PROGRAM_ERROR_POSITION_NV 0x864B +#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 +#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 +#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 +#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 +#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 +#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 +#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 +#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 +#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 +#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 +#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A +#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B +#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C +#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D +#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E +#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F +#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 +#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 +#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 +#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 +#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 +#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 +#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 +#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 +#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 +#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 +#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A +#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B +#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C +#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D +#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E +#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F +#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 +#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 +#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 +#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 +#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 +#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 +#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 +#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 +#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 +#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 +#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A +#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B +#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C +#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D +#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E +#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F + +typedef GLboolean (GLAPIENTRY * PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint* ids, GLboolean *residences); +typedef void (GLAPIENTRY * PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte* program); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid** pointer); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMNVPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte* program); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLuint num, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLuint num, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei n, const GLubyte* v); + +#define glAreProgramsResidentNV GLEW_GET_FUN(__glewAreProgramsResidentNV) +#define glBindProgramNV GLEW_GET_FUN(__glewBindProgramNV) +#define glDeleteProgramsNV GLEW_GET_FUN(__glewDeleteProgramsNV) +#define glExecuteProgramNV GLEW_GET_FUN(__glewExecuteProgramNV) +#define glGenProgramsNV GLEW_GET_FUN(__glewGenProgramsNV) +#define glGetProgramParameterdvNV GLEW_GET_FUN(__glewGetProgramParameterdvNV) +#define glGetProgramParameterfvNV GLEW_GET_FUN(__glewGetProgramParameterfvNV) +#define glGetProgramStringNV GLEW_GET_FUN(__glewGetProgramStringNV) +#define glGetProgramivNV GLEW_GET_FUN(__glewGetProgramivNV) +#define glGetTrackMatrixivNV GLEW_GET_FUN(__glewGetTrackMatrixivNV) +#define glGetVertexAttribPointervNV GLEW_GET_FUN(__glewGetVertexAttribPointervNV) +#define glGetVertexAttribdvNV GLEW_GET_FUN(__glewGetVertexAttribdvNV) +#define glGetVertexAttribfvNV GLEW_GET_FUN(__glewGetVertexAttribfvNV) +#define glGetVertexAttribivNV GLEW_GET_FUN(__glewGetVertexAttribivNV) +#define glIsProgramNV GLEW_GET_FUN(__glewIsProgramNV) +#define glLoadProgramNV GLEW_GET_FUN(__glewLoadProgramNV) +#define glProgramParameter4dNV GLEW_GET_FUN(__glewProgramParameter4dNV) +#define glProgramParameter4dvNV GLEW_GET_FUN(__glewProgramParameter4dvNV) +#define glProgramParameter4fNV GLEW_GET_FUN(__glewProgramParameter4fNV) +#define glProgramParameter4fvNV GLEW_GET_FUN(__glewProgramParameter4fvNV) +#define glProgramParameters4dvNV GLEW_GET_FUN(__glewProgramParameters4dvNV) +#define glProgramParameters4fvNV GLEW_GET_FUN(__glewProgramParameters4fvNV) +#define glRequestResidentProgramsNV GLEW_GET_FUN(__glewRequestResidentProgramsNV) +#define glTrackMatrixNV GLEW_GET_FUN(__glewTrackMatrixNV) +#define glVertexAttrib1dNV GLEW_GET_FUN(__glewVertexAttrib1dNV) +#define glVertexAttrib1dvNV GLEW_GET_FUN(__glewVertexAttrib1dvNV) +#define glVertexAttrib1fNV GLEW_GET_FUN(__glewVertexAttrib1fNV) +#define glVertexAttrib1fvNV GLEW_GET_FUN(__glewVertexAttrib1fvNV) +#define glVertexAttrib1sNV GLEW_GET_FUN(__glewVertexAttrib1sNV) +#define glVertexAttrib1svNV GLEW_GET_FUN(__glewVertexAttrib1svNV) +#define glVertexAttrib2dNV GLEW_GET_FUN(__glewVertexAttrib2dNV) +#define glVertexAttrib2dvNV GLEW_GET_FUN(__glewVertexAttrib2dvNV) +#define glVertexAttrib2fNV GLEW_GET_FUN(__glewVertexAttrib2fNV) +#define glVertexAttrib2fvNV GLEW_GET_FUN(__glewVertexAttrib2fvNV) +#define glVertexAttrib2sNV GLEW_GET_FUN(__glewVertexAttrib2sNV) +#define glVertexAttrib2svNV GLEW_GET_FUN(__glewVertexAttrib2svNV) +#define glVertexAttrib3dNV GLEW_GET_FUN(__glewVertexAttrib3dNV) +#define glVertexAttrib3dvNV GLEW_GET_FUN(__glewVertexAttrib3dvNV) +#define glVertexAttrib3fNV GLEW_GET_FUN(__glewVertexAttrib3fNV) +#define glVertexAttrib3fvNV GLEW_GET_FUN(__glewVertexAttrib3fvNV) +#define glVertexAttrib3sNV GLEW_GET_FUN(__glewVertexAttrib3sNV) +#define glVertexAttrib3svNV GLEW_GET_FUN(__glewVertexAttrib3svNV) +#define glVertexAttrib4dNV GLEW_GET_FUN(__glewVertexAttrib4dNV) +#define glVertexAttrib4dvNV GLEW_GET_FUN(__glewVertexAttrib4dvNV) +#define glVertexAttrib4fNV GLEW_GET_FUN(__glewVertexAttrib4fNV) +#define glVertexAttrib4fvNV GLEW_GET_FUN(__glewVertexAttrib4fvNV) +#define glVertexAttrib4sNV GLEW_GET_FUN(__glewVertexAttrib4sNV) +#define glVertexAttrib4svNV GLEW_GET_FUN(__glewVertexAttrib4svNV) +#define glVertexAttrib4ubNV GLEW_GET_FUN(__glewVertexAttrib4ubNV) +#define glVertexAttrib4ubvNV GLEW_GET_FUN(__glewVertexAttrib4ubvNV) +#define glVertexAttribPointerNV GLEW_GET_FUN(__glewVertexAttribPointerNV) +#define glVertexAttribs1dvNV GLEW_GET_FUN(__glewVertexAttribs1dvNV) +#define glVertexAttribs1fvNV GLEW_GET_FUN(__glewVertexAttribs1fvNV) +#define glVertexAttribs1svNV GLEW_GET_FUN(__glewVertexAttribs1svNV) +#define glVertexAttribs2dvNV GLEW_GET_FUN(__glewVertexAttribs2dvNV) +#define glVertexAttribs2fvNV GLEW_GET_FUN(__glewVertexAttribs2fvNV) +#define glVertexAttribs2svNV GLEW_GET_FUN(__glewVertexAttribs2svNV) +#define glVertexAttribs3dvNV GLEW_GET_FUN(__glewVertexAttribs3dvNV) +#define glVertexAttribs3fvNV GLEW_GET_FUN(__glewVertexAttribs3fvNV) +#define glVertexAttribs3svNV GLEW_GET_FUN(__glewVertexAttribs3svNV) +#define glVertexAttribs4dvNV GLEW_GET_FUN(__glewVertexAttribs4dvNV) +#define glVertexAttribs4fvNV GLEW_GET_FUN(__glewVertexAttribs4fvNV) +#define glVertexAttribs4svNV GLEW_GET_FUN(__glewVertexAttribs4svNV) +#define glVertexAttribs4ubvNV GLEW_GET_FUN(__glewVertexAttribs4ubvNV) + +#define GLEW_NV_vertex_program GLEW_GET_VAR(__GLEW_NV_vertex_program) + +#endif /* GL_NV_vertex_program */ + +/* ------------------------ GL_NV_vertex_program1_1 ------------------------ */ + +#ifndef GL_NV_vertex_program1_1 +#define GL_NV_vertex_program1_1 1 + +#define GLEW_NV_vertex_program1_1 GLEW_GET_VAR(__GLEW_NV_vertex_program1_1) + +#endif /* GL_NV_vertex_program1_1 */ + +/* ------------------------- GL_NV_vertex_program2 ------------------------- */ + +#ifndef GL_NV_vertex_program2 +#define GL_NV_vertex_program2 1 + +#define GLEW_NV_vertex_program2 GLEW_GET_VAR(__GLEW_NV_vertex_program2) + +#endif /* GL_NV_vertex_program2 */ + +/* ---------------------- GL_NV_vertex_program2_option --------------------- */ + +#ifndef GL_NV_vertex_program2_option +#define GL_NV_vertex_program2_option 1 + +#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 +#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 + +#define GLEW_NV_vertex_program2_option GLEW_GET_VAR(__GLEW_NV_vertex_program2_option) + +#endif /* GL_NV_vertex_program2_option */ + +/* ------------------------- GL_NV_vertex_program3 ------------------------- */ + +#ifndef GL_NV_vertex_program3 +#define GL_NV_vertex_program3 1 + +#define MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C + +#define GLEW_NV_vertex_program3 GLEW_GET_VAR(__GLEW_NV_vertex_program3) + +#endif /* GL_NV_vertex_program3 */ + +/* ------------------------- GL_NV_vertex_program4 ------------------------- */ + +#ifndef GL_NV_vertex_program4 +#define GL_NV_vertex_program4 1 + +#define GLEW_NV_vertex_program4 GLEW_GET_VAR(__GLEW_NV_vertex_program4) + +#endif /* GL_NV_vertex_program4 */ + +/* ------------------------ GL_OES_byte_coordinates ------------------------ */ + +#ifndef GL_OES_byte_coordinates +#define GL_OES_byte_coordinates 1 + +#define GL_BYTE 0x1400 + +#define GLEW_OES_byte_coordinates GLEW_GET_VAR(__GLEW_OES_byte_coordinates) + +#endif /* GL_OES_byte_coordinates */ + +/* ------------------- GL_OES_compressed_paletted_texture ------------------ */ + +#ifndef GL_OES_compressed_paletted_texture +#define GL_OES_compressed_paletted_texture 1 + +#define GL_PALETTE4_RGB8_OES 0x8B90 +#define GL_PALETTE4_RGBA8_OES 0x8B91 +#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 +#define GL_PALETTE4_RGBA4_OES 0x8B93 +#define GL_PALETTE4_RGB5_A1_OES 0x8B94 +#define GL_PALETTE8_RGB8_OES 0x8B95 +#define GL_PALETTE8_RGBA8_OES 0x8B96 +#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 +#define GL_PALETTE8_RGBA4_OES 0x8B98 +#define GL_PALETTE8_RGB5_A1_OES 0x8B99 + +#define GLEW_OES_compressed_paletted_texture GLEW_GET_VAR(__GLEW_OES_compressed_paletted_texture) + +#endif /* GL_OES_compressed_paletted_texture */ + +/* --------------------------- GL_OES_read_format -------------------------- */ + +#ifndef GL_OES_read_format +#define GL_OES_read_format 1 + +#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B + +#define GLEW_OES_read_format GLEW_GET_VAR(__GLEW_OES_read_format) + +#endif /* GL_OES_read_format */ + +/* ------------------------ GL_OES_single_precision ------------------------ */ + +#ifndef GL_OES_single_precision +#define GL_OES_single_precision 1 + +typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFOESPROC) (GLclampd depth); +typedef void (GLAPIENTRY * PFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat* equation); +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFOESPROC) (GLclampf n, GLclampf f); +typedef void (GLAPIENTRY * PFNGLFRUSTUMFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); +typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEFOESPROC) (GLenum plane, GLfloat* equation); +typedef void (GLAPIENTRY * PFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); + +#define glClearDepthfOES GLEW_GET_FUN(__glewClearDepthfOES) +#define glClipPlanefOES GLEW_GET_FUN(__glewClipPlanefOES) +#define glDepthRangefOES GLEW_GET_FUN(__glewDepthRangefOES) +#define glFrustumfOES GLEW_GET_FUN(__glewFrustumfOES) +#define glGetClipPlanefOES GLEW_GET_FUN(__glewGetClipPlanefOES) +#define glOrthofOES GLEW_GET_FUN(__glewOrthofOES) + +#define GLEW_OES_single_precision GLEW_GET_VAR(__GLEW_OES_single_precision) + +#endif /* GL_OES_single_precision */ + +/* ---------------------------- GL_OML_interlace --------------------------- */ + +#ifndef GL_OML_interlace +#define GL_OML_interlace 1 + +#define GL_INTERLACE_OML 0x8980 +#define GL_INTERLACE_READ_OML 0x8981 + +#define GLEW_OML_interlace GLEW_GET_VAR(__GLEW_OML_interlace) + +#endif /* GL_OML_interlace */ + +/* ---------------------------- GL_OML_resample ---------------------------- */ + +#ifndef GL_OML_resample +#define GL_OML_resample 1 + +#define GL_PACK_RESAMPLE_OML 0x8984 +#define GL_UNPACK_RESAMPLE_OML 0x8985 +#define GL_RESAMPLE_REPLICATE_OML 0x8986 +#define GL_RESAMPLE_ZERO_FILL_OML 0x8987 +#define GL_RESAMPLE_AVERAGE_OML 0x8988 +#define GL_RESAMPLE_DECIMATE_OML 0x8989 + +#define GLEW_OML_resample GLEW_GET_VAR(__GLEW_OML_resample) + +#endif /* GL_OML_resample */ + +/* ---------------------------- GL_OML_subsample --------------------------- */ + +#ifndef GL_OML_subsample +#define GL_OML_subsample 1 + +#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982 +#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983 + +#define GLEW_OML_subsample GLEW_GET_VAR(__GLEW_OML_subsample) + +#endif /* GL_OML_subsample */ + +/* --------------------------- GL_PGI_misc_hints --------------------------- */ + +#ifndef GL_PGI_misc_hints +#define GL_PGI_misc_hints 1 + +#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 107000 +#define GL_CONSERVE_MEMORY_HINT_PGI 107005 +#define GL_RECLAIM_MEMORY_HINT_PGI 107006 +#define GL_NATIVE_GRAPHICS_HANDLE_PGI 107010 +#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 107011 +#define GL_NATIVE_GRAPHICS_END_HINT_PGI 107012 +#define GL_ALWAYS_FAST_HINT_PGI 107020 +#define GL_ALWAYS_SOFT_HINT_PGI 107021 +#define GL_ALLOW_DRAW_OBJ_HINT_PGI 107022 +#define GL_ALLOW_DRAW_WIN_HINT_PGI 107023 +#define GL_ALLOW_DRAW_FRG_HINT_PGI 107024 +#define GL_ALLOW_DRAW_MEM_HINT_PGI 107025 +#define GL_STRICT_DEPTHFUNC_HINT_PGI 107030 +#define GL_STRICT_LIGHTING_HINT_PGI 107031 +#define GL_STRICT_SCISSOR_HINT_PGI 107032 +#define GL_FULL_STIPPLE_HINT_PGI 107033 +#define GL_CLIP_NEAR_HINT_PGI 107040 +#define GL_CLIP_FAR_HINT_PGI 107041 +#define GL_WIDE_LINE_HINT_PGI 107042 +#define GL_BACK_NORMALS_HINT_PGI 107043 + +#define GLEW_PGI_misc_hints GLEW_GET_VAR(__GLEW_PGI_misc_hints) + +#endif /* GL_PGI_misc_hints */ + +/* -------------------------- GL_PGI_vertex_hints -------------------------- */ + +#ifndef GL_PGI_vertex_hints +#define GL_PGI_vertex_hints 1 + +#define GL_VERTEX23_BIT_PGI 0x00000004 +#define GL_VERTEX4_BIT_PGI 0x00000008 +#define GL_COLOR3_BIT_PGI 0x00010000 +#define GL_COLOR4_BIT_PGI 0x00020000 +#define GL_EDGEFLAG_BIT_PGI 0x00040000 +#define GL_INDEX_BIT_PGI 0x00080000 +#define GL_MAT_AMBIENT_BIT_PGI 0x00100000 +#define GL_VERTEX_DATA_HINT_PGI 107050 +#define GL_VERTEX_CONSISTENT_HINT_PGI 107051 +#define GL_MATERIAL_SIDE_HINT_PGI 107052 +#define GL_MAX_VERTEX_HINT_PGI 107053 +#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000 +#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000 +#define GL_MAT_EMISSION_BIT_PGI 0x00800000 +#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000 +#define GL_MAT_SHININESS_BIT_PGI 0x02000000 +#define GL_MAT_SPECULAR_BIT_PGI 0x04000000 +#define GL_NORMAL_BIT_PGI 0x08000000 +#define GL_TEXCOORD1_BIT_PGI 0x10000000 +#define GL_TEXCOORD2_BIT_PGI 0x20000000 +#define GL_TEXCOORD3_BIT_PGI 0x40000000 +#define GL_TEXCOORD4_BIT_PGI 0x80000000 + +#define GLEW_PGI_vertex_hints GLEW_GET_VAR(__GLEW_PGI_vertex_hints) + +#endif /* GL_PGI_vertex_hints */ + +/* ----------------------- GL_REND_screen_coordinates ---------------------- */ + +#ifndef GL_REND_screen_coordinates +#define GL_REND_screen_coordinates 1 + +#define GL_SCREEN_COORDINATES_REND 0x8490 +#define GL_INVERTED_SCREEN_W_REND 0x8491 + +#define GLEW_REND_screen_coordinates GLEW_GET_VAR(__GLEW_REND_screen_coordinates) + +#endif /* GL_REND_screen_coordinates */ + +/* ------------------------------- GL_S3_s3tc ------------------------------ */ + +#ifndef GL_S3_s3tc +#define GL_S3_s3tc 1 + +#define GL_RGB_S3TC 0x83A0 +#define GL_RGB4_S3TC 0x83A1 +#define GL_RGBA_S3TC 0x83A2 +#define GL_RGBA4_S3TC 0x83A3 +#define GL_RGBA_DXT5_S3TC 0x83A4 +#define GL_RGBA4_DXT5_S3TC 0x83A5 + +#define GLEW_S3_s3tc GLEW_GET_VAR(__GLEW_S3_s3tc) + +#endif /* GL_S3_s3tc */ + +/* -------------------------- GL_SGIS_color_range -------------------------- */ + +#ifndef GL_SGIS_color_range +#define GL_SGIS_color_range 1 + +#define GL_EXTENDED_RANGE_SGIS 0x85A5 +#define GL_MIN_RED_SGIS 0x85A6 +#define GL_MAX_RED_SGIS 0x85A7 +#define GL_MIN_GREEN_SGIS 0x85A8 +#define GL_MAX_GREEN_SGIS 0x85A9 +#define GL_MIN_BLUE_SGIS 0x85AA +#define GL_MAX_BLUE_SGIS 0x85AB +#define GL_MIN_ALPHA_SGIS 0x85AC +#define GL_MAX_ALPHA_SGIS 0x85AD + +#define GLEW_SGIS_color_range GLEW_GET_VAR(__GLEW_SGIS_color_range) + +#endif /* GL_SGIS_color_range */ + +/* ------------------------- GL_SGIS_detail_texture ------------------------ */ + +#ifndef GL_SGIS_detail_texture +#define GL_SGIS_detail_texture 1 + +typedef void (GLAPIENTRY * PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points); +typedef void (GLAPIENTRY * PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat* points); + +#define glDetailTexFuncSGIS GLEW_GET_FUN(__glewDetailTexFuncSGIS) +#define glGetDetailTexFuncSGIS GLEW_GET_FUN(__glewGetDetailTexFuncSGIS) + +#define GLEW_SGIS_detail_texture GLEW_GET_VAR(__GLEW_SGIS_detail_texture) + +#endif /* GL_SGIS_detail_texture */ + +/* -------------------------- GL_SGIS_fog_function ------------------------- */ + +#ifndef GL_SGIS_fog_function +#define GL_SGIS_fog_function 1 + +typedef void (GLAPIENTRY * PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat* points); +typedef void (GLAPIENTRY * PFNGLGETFOGFUNCSGISPROC) (GLfloat* points); + +#define glFogFuncSGIS GLEW_GET_FUN(__glewFogFuncSGIS) +#define glGetFogFuncSGIS GLEW_GET_FUN(__glewGetFogFuncSGIS) + +#define GLEW_SGIS_fog_function GLEW_GET_VAR(__GLEW_SGIS_fog_function) + +#endif /* GL_SGIS_fog_function */ + +/* ------------------------ GL_SGIS_generate_mipmap ------------------------ */ + +#ifndef GL_SGIS_generate_mipmap +#define GL_SGIS_generate_mipmap 1 + +#define GL_GENERATE_MIPMAP_SGIS 0x8191 +#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 + +#define GLEW_SGIS_generate_mipmap GLEW_GET_VAR(__GLEW_SGIS_generate_mipmap) + +#endif /* GL_SGIS_generate_mipmap */ + +/* -------------------------- GL_SGIS_multisample -------------------------- */ + +#ifndef GL_SGIS_multisample +#define GL_SGIS_multisample 1 + +#define GL_MULTISAMPLE_SGIS 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F +#define GL_SAMPLE_MASK_SGIS 0x80A0 +#define GL_1PASS_SGIS 0x80A1 +#define GL_2PASS_0_SGIS 0x80A2 +#define GL_2PASS_1_SGIS 0x80A3 +#define GL_4PASS_0_SGIS 0x80A4 +#define GL_4PASS_1_SGIS 0x80A5 +#define GL_4PASS_2_SGIS 0x80A6 +#define GL_4PASS_3_SGIS 0x80A7 +#define GL_SAMPLE_BUFFERS_SGIS 0x80A8 +#define GL_SAMPLES_SGIS 0x80A9 +#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA +#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB +#define GL_SAMPLE_PATTERN_SGIS 0x80AC +#define GL_MULTISAMPLE_BIT_EXT 0x20000000 + +typedef void (GLAPIENTRY * PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert); +typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern); + +#define glSampleMaskSGIS GLEW_GET_FUN(__glewSampleMaskSGIS) +#define glSamplePatternSGIS GLEW_GET_FUN(__glewSamplePatternSGIS) + +#define GLEW_SGIS_multisample GLEW_GET_VAR(__GLEW_SGIS_multisample) + +#endif /* GL_SGIS_multisample */ + +/* ------------------------- GL_SGIS_pixel_texture ------------------------- */ + +#ifndef GL_SGIS_pixel_texture +#define GL_SGIS_pixel_texture 1 + +#define GLEW_SGIS_pixel_texture GLEW_GET_VAR(__GLEW_SGIS_pixel_texture) + +#endif /* GL_SGIS_pixel_texture */ + +/* ----------------------- GL_SGIS_point_line_texgen ----------------------- */ + +#ifndef GL_SGIS_point_line_texgen +#define GL_SGIS_point_line_texgen 1 + +#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0 +#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1 +#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2 +#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3 +#define GL_EYE_POINT_SGIS 0x81F4 +#define GL_OBJECT_POINT_SGIS 0x81F5 +#define GL_EYE_LINE_SGIS 0x81F6 +#define GL_OBJECT_LINE_SGIS 0x81F7 + +#define GLEW_SGIS_point_line_texgen GLEW_GET_VAR(__GLEW_SGIS_point_line_texgen) + +#endif /* GL_SGIS_point_line_texgen */ + +/* ------------------------ GL_SGIS_sharpen_texture ------------------------ */ + +#ifndef GL_SGIS_sharpen_texture +#define GL_SGIS_sharpen_texture 1 + +typedef void (GLAPIENTRY * PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat* points); +typedef void (GLAPIENTRY * PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points); + +#define glGetSharpenTexFuncSGIS GLEW_GET_FUN(__glewGetSharpenTexFuncSGIS) +#define glSharpenTexFuncSGIS GLEW_GET_FUN(__glewSharpenTexFuncSGIS) + +#define GLEW_SGIS_sharpen_texture GLEW_GET_VAR(__GLEW_SGIS_sharpen_texture) + +#endif /* GL_SGIS_sharpen_texture */ + +/* --------------------------- GL_SGIS_texture4D --------------------------- */ + +#ifndef GL_SGIS_texture4D +#define GL_SGIS_texture4D 1 + +typedef void (GLAPIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLenum format, GLenum type, const void* pixels); + +#define glTexImage4DSGIS GLEW_GET_FUN(__glewTexImage4DSGIS) +#define glTexSubImage4DSGIS GLEW_GET_FUN(__glewTexSubImage4DSGIS) + +#define GLEW_SGIS_texture4D GLEW_GET_VAR(__GLEW_SGIS_texture4D) + +#endif /* GL_SGIS_texture4D */ + +/* ---------------------- GL_SGIS_texture_border_clamp --------------------- */ + +#ifndef GL_SGIS_texture_border_clamp +#define GL_SGIS_texture_border_clamp 1 + +#define GL_CLAMP_TO_BORDER_SGIS 0x812D + +#define GLEW_SGIS_texture_border_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_border_clamp) + +#endif /* GL_SGIS_texture_border_clamp */ + +/* ----------------------- GL_SGIS_texture_edge_clamp ---------------------- */ + +#ifndef GL_SGIS_texture_edge_clamp +#define GL_SGIS_texture_edge_clamp 1 + +#define GL_CLAMP_TO_EDGE_SGIS 0x812F + +#define GLEW_SGIS_texture_edge_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_edge_clamp) + +#endif /* GL_SGIS_texture_edge_clamp */ + +/* ------------------------ GL_SGIS_texture_filter4 ------------------------ */ + +#ifndef GL_SGIS_texture_filter4 +#define GL_SGIS_texture_filter4 1 + +typedef void (GLAPIENTRY * PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat* weights); +typedef void (GLAPIENTRY * PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat* weights); + +#define glGetTexFilterFuncSGIS GLEW_GET_FUN(__glewGetTexFilterFuncSGIS) +#define glTexFilterFuncSGIS GLEW_GET_FUN(__glewTexFilterFuncSGIS) + +#define GLEW_SGIS_texture_filter4 GLEW_GET_VAR(__GLEW_SGIS_texture_filter4) + +#endif /* GL_SGIS_texture_filter4 */ + +/* -------------------------- GL_SGIS_texture_lod -------------------------- */ + +#ifndef GL_SGIS_texture_lod +#define GL_SGIS_texture_lod 1 + +#define GL_TEXTURE_MIN_LOD_SGIS 0x813A +#define GL_TEXTURE_MAX_LOD_SGIS 0x813B +#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C +#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D + +#define GLEW_SGIS_texture_lod GLEW_GET_VAR(__GLEW_SGIS_texture_lod) + +#endif /* GL_SGIS_texture_lod */ + +/* ------------------------- GL_SGIS_texture_select ------------------------ */ + +#ifndef GL_SGIS_texture_select +#define GL_SGIS_texture_select 1 + +#define GLEW_SGIS_texture_select GLEW_GET_VAR(__GLEW_SGIS_texture_select) + +#endif /* GL_SGIS_texture_select */ + +/* ----------------------------- GL_SGIX_async ----------------------------- */ + +#ifndef GL_SGIX_async +#define GL_SGIX_async 1 + +#define GL_ASYNC_MARKER_SGIX 0x8329 + +typedef void (GLAPIENTRY * PFNGLASYNCMARKERSGIXPROC) (GLuint marker); +typedef void (GLAPIENTRY * PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range); +typedef GLint (GLAPIENTRY * PFNGLFINISHASYNCSGIXPROC) (GLuint* markerp); +typedef GLuint (GLAPIENTRY * PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range); +typedef GLboolean (GLAPIENTRY * PFNGLISASYNCMARKERSGIXPROC) (GLuint marker); +typedef GLint (GLAPIENTRY * PFNGLPOLLASYNCSGIXPROC) (GLuint* markerp); + +#define glAsyncMarkerSGIX GLEW_GET_FUN(__glewAsyncMarkerSGIX) +#define glDeleteAsyncMarkersSGIX GLEW_GET_FUN(__glewDeleteAsyncMarkersSGIX) +#define glFinishAsyncSGIX GLEW_GET_FUN(__glewFinishAsyncSGIX) +#define glGenAsyncMarkersSGIX GLEW_GET_FUN(__glewGenAsyncMarkersSGIX) +#define glIsAsyncMarkerSGIX GLEW_GET_FUN(__glewIsAsyncMarkerSGIX) +#define glPollAsyncSGIX GLEW_GET_FUN(__glewPollAsyncSGIX) + +#define GLEW_SGIX_async GLEW_GET_VAR(__GLEW_SGIX_async) + +#endif /* GL_SGIX_async */ + +/* ------------------------ GL_SGIX_async_histogram ------------------------ */ + +#ifndef GL_SGIX_async_histogram +#define GL_SGIX_async_histogram 1 + +#define GL_ASYNC_HISTOGRAM_SGIX 0x832C +#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D + +#define GLEW_SGIX_async_histogram GLEW_GET_VAR(__GLEW_SGIX_async_histogram) + +#endif /* GL_SGIX_async_histogram */ + +/* -------------------------- GL_SGIX_async_pixel -------------------------- */ + +#ifndef GL_SGIX_async_pixel +#define GL_SGIX_async_pixel 1 + +#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C +#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D +#define GL_ASYNC_READ_PIXELS_SGIX 0x835E +#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F +#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360 +#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361 + +#define GLEW_SGIX_async_pixel GLEW_GET_VAR(__GLEW_SGIX_async_pixel) + +#endif /* GL_SGIX_async_pixel */ + +/* ----------------------- GL_SGIX_blend_alpha_minmax ---------------------- */ + +#ifndef GL_SGIX_blend_alpha_minmax +#define GL_SGIX_blend_alpha_minmax 1 + +#define GL_ALPHA_MIN_SGIX 0x8320 +#define GL_ALPHA_MAX_SGIX 0x8321 + +#define GLEW_SGIX_blend_alpha_minmax GLEW_GET_VAR(__GLEW_SGIX_blend_alpha_minmax) + +#endif /* GL_SGIX_blend_alpha_minmax */ + +/* ---------------------------- GL_SGIX_clipmap ---------------------------- */ + +#ifndef GL_SGIX_clipmap +#define GL_SGIX_clipmap 1 + +#define GLEW_SGIX_clipmap GLEW_GET_VAR(__GLEW_SGIX_clipmap) + +#endif /* GL_SGIX_clipmap */ + +/* ---------------------- GL_SGIX_convolution_accuracy --------------------- */ + +#ifndef GL_SGIX_convolution_accuracy +#define GL_SGIX_convolution_accuracy 1 + +#define GL_CONVOLUTION_HINT_SGIX 0x8316 + +#define GLEW_SGIX_convolution_accuracy GLEW_GET_VAR(__GLEW_SGIX_convolution_accuracy) + +#endif /* GL_SGIX_convolution_accuracy */ + +/* ------------------------- GL_SGIX_depth_texture ------------------------- */ + +#ifndef GL_SGIX_depth_texture +#define GL_SGIX_depth_texture 1 + +#define GL_DEPTH_COMPONENT16_SGIX 0x81A5 +#define GL_DEPTH_COMPONENT24_SGIX 0x81A6 +#define GL_DEPTH_COMPONENT32_SGIX 0x81A7 + +#define GLEW_SGIX_depth_texture GLEW_GET_VAR(__GLEW_SGIX_depth_texture) + +#endif /* GL_SGIX_depth_texture */ + +/* -------------------------- GL_SGIX_flush_raster ------------------------- */ + +#ifndef GL_SGIX_flush_raster +#define GL_SGIX_flush_raster 1 + +typedef void (GLAPIENTRY * PFNGLFLUSHRASTERSGIXPROC) (void); + +#define glFlushRasterSGIX GLEW_GET_FUN(__glewFlushRasterSGIX) + +#define GLEW_SGIX_flush_raster GLEW_GET_VAR(__GLEW_SGIX_flush_raster) + +#endif /* GL_SGIX_flush_raster */ + +/* --------------------------- GL_SGIX_fog_offset -------------------------- */ + +#ifndef GL_SGIX_fog_offset +#define GL_SGIX_fog_offset 1 + +#define GL_FOG_OFFSET_SGIX 0x8198 +#define GL_FOG_OFFSET_VALUE_SGIX 0x8199 + +#define GLEW_SGIX_fog_offset GLEW_GET_VAR(__GLEW_SGIX_fog_offset) + +#endif /* GL_SGIX_fog_offset */ + +/* -------------------------- GL_SGIX_fog_texture -------------------------- */ + +#ifndef GL_SGIX_fog_texture +#define GL_SGIX_fog_texture 1 + +#define GL_TEXTURE_FOG_SGIX 0 +#define GL_FOG_PATCHY_FACTOR_SGIX 0 +#define GL_FRAGMENT_FOG_SGIX 0 + +typedef void (GLAPIENTRY * PFNGLTEXTUREFOGSGIXPROC) (GLenum pname); + +#define glTextureFogSGIX GLEW_GET_FUN(__glewTextureFogSGIX) + +#define GLEW_SGIX_fog_texture GLEW_GET_VAR(__GLEW_SGIX_fog_texture) + +#endif /* GL_SGIX_fog_texture */ + +/* ------------------- GL_SGIX_fragment_specular_lighting ------------------ */ + +#ifndef GL_SGIX_fragment_specular_lighting +#define GL_SGIX_fragment_specular_lighting 1 + +typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum value, GLfloat* data); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum value, GLint* data); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* data); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* data); + +#define glFragmentColorMaterialSGIX GLEW_GET_FUN(__glewFragmentColorMaterialSGIX) +#define glFragmentLightModelfSGIX GLEW_GET_FUN(__glewFragmentLightModelfSGIX) +#define glFragmentLightModelfvSGIX GLEW_GET_FUN(__glewFragmentLightModelfvSGIX) +#define glFragmentLightModeliSGIX GLEW_GET_FUN(__glewFragmentLightModeliSGIX) +#define glFragmentLightModelivSGIX GLEW_GET_FUN(__glewFragmentLightModelivSGIX) +#define glFragmentLightfSGIX GLEW_GET_FUN(__glewFragmentLightfSGIX) +#define glFragmentLightfvSGIX GLEW_GET_FUN(__glewFragmentLightfvSGIX) +#define glFragmentLightiSGIX GLEW_GET_FUN(__glewFragmentLightiSGIX) +#define glFragmentLightivSGIX GLEW_GET_FUN(__glewFragmentLightivSGIX) +#define glFragmentMaterialfSGIX GLEW_GET_FUN(__glewFragmentMaterialfSGIX) +#define glFragmentMaterialfvSGIX GLEW_GET_FUN(__glewFragmentMaterialfvSGIX) +#define glFragmentMaterialiSGIX GLEW_GET_FUN(__glewFragmentMaterialiSGIX) +#define glFragmentMaterialivSGIX GLEW_GET_FUN(__glewFragmentMaterialivSGIX) +#define glGetFragmentLightfvSGIX GLEW_GET_FUN(__glewGetFragmentLightfvSGIX) +#define glGetFragmentLightivSGIX GLEW_GET_FUN(__glewGetFragmentLightivSGIX) +#define glGetFragmentMaterialfvSGIX GLEW_GET_FUN(__glewGetFragmentMaterialfvSGIX) +#define glGetFragmentMaterialivSGIX GLEW_GET_FUN(__glewGetFragmentMaterialivSGIX) + +#define GLEW_SGIX_fragment_specular_lighting GLEW_GET_VAR(__GLEW_SGIX_fragment_specular_lighting) + +#endif /* GL_SGIX_fragment_specular_lighting */ + +/* --------------------------- GL_SGIX_framezoom --------------------------- */ + +#ifndef GL_SGIX_framezoom +#define GL_SGIX_framezoom 1 + +typedef void (GLAPIENTRY * PFNGLFRAMEZOOMSGIXPROC) (GLint factor); + +#define glFrameZoomSGIX GLEW_GET_FUN(__glewFrameZoomSGIX) + +#define GLEW_SGIX_framezoom GLEW_GET_VAR(__GLEW_SGIX_framezoom) + +#endif /* GL_SGIX_framezoom */ + +/* --------------------------- GL_SGIX_interlace --------------------------- */ + +#ifndef GL_SGIX_interlace +#define GL_SGIX_interlace 1 + +#define GL_INTERLACE_SGIX 0x8094 + +#define GLEW_SGIX_interlace GLEW_GET_VAR(__GLEW_SGIX_interlace) + +#endif /* GL_SGIX_interlace */ + +/* ------------------------- GL_SGIX_ir_instrument1 ------------------------ */ + +#ifndef GL_SGIX_ir_instrument1 +#define GL_SGIX_ir_instrument1 1 + +#define GLEW_SGIX_ir_instrument1 GLEW_GET_VAR(__GLEW_SGIX_ir_instrument1) + +#endif /* GL_SGIX_ir_instrument1 */ + +/* ------------------------- GL_SGIX_list_priority ------------------------- */ + +#ifndef GL_SGIX_list_priority +#define GL_SGIX_list_priority 1 + +#define GLEW_SGIX_list_priority GLEW_GET_VAR(__GLEW_SGIX_list_priority) + +#endif /* GL_SGIX_list_priority */ + +/* ------------------------- GL_SGIX_pixel_texture ------------------------- */ + +#ifndef GL_SGIX_pixel_texture +#define GL_SGIX_pixel_texture 1 + +typedef void (GLAPIENTRY * PFNGLPIXELTEXGENSGIXPROC) (GLenum mode); + +#define glPixelTexGenSGIX GLEW_GET_FUN(__glewPixelTexGenSGIX) + +#define GLEW_SGIX_pixel_texture GLEW_GET_VAR(__GLEW_SGIX_pixel_texture) + +#endif /* GL_SGIX_pixel_texture */ + +/* ----------------------- GL_SGIX_pixel_texture_bits ---------------------- */ + +#ifndef GL_SGIX_pixel_texture_bits +#define GL_SGIX_pixel_texture_bits 1 + +#define GLEW_SGIX_pixel_texture_bits GLEW_GET_VAR(__GLEW_SGIX_pixel_texture_bits) + +#endif /* GL_SGIX_pixel_texture_bits */ + +/* ------------------------ GL_SGIX_reference_plane ------------------------ */ + +#ifndef GL_SGIX_reference_plane +#define GL_SGIX_reference_plane 1 + +typedef void (GLAPIENTRY * PFNGLREFERENCEPLANESGIXPROC) (const GLdouble* equation); + +#define glReferencePlaneSGIX GLEW_GET_FUN(__glewReferencePlaneSGIX) + +#define GLEW_SGIX_reference_plane GLEW_GET_VAR(__GLEW_SGIX_reference_plane) + +#endif /* GL_SGIX_reference_plane */ + +/* ---------------------------- GL_SGIX_resample --------------------------- */ + +#ifndef GL_SGIX_resample +#define GL_SGIX_resample 1 + +#define GL_PACK_RESAMPLE_SGIX 0x842E +#define GL_UNPACK_RESAMPLE_SGIX 0x842F +#define GL_RESAMPLE_DECIMATE_SGIX 0x8430 +#define GL_RESAMPLE_REPLICATE_SGIX 0x8433 +#define GL_RESAMPLE_ZERO_FILL_SGIX 0x8434 + +#define GLEW_SGIX_resample GLEW_GET_VAR(__GLEW_SGIX_resample) + +#endif /* GL_SGIX_resample */ + +/* ----------------------------- GL_SGIX_shadow ---------------------------- */ + +#ifndef GL_SGIX_shadow +#define GL_SGIX_shadow 1 + +#define GL_TEXTURE_COMPARE_SGIX 0x819A +#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B +#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C +#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D + +#define GLEW_SGIX_shadow GLEW_GET_VAR(__GLEW_SGIX_shadow) + +#endif /* GL_SGIX_shadow */ + +/* ------------------------- GL_SGIX_shadow_ambient ------------------------ */ + +#ifndef GL_SGIX_shadow_ambient +#define GL_SGIX_shadow_ambient 1 + +#define GL_SHADOW_AMBIENT_SGIX 0x80BF + +#define GLEW_SGIX_shadow_ambient GLEW_GET_VAR(__GLEW_SGIX_shadow_ambient) + +#endif /* GL_SGIX_shadow_ambient */ + +/* ----------------------------- GL_SGIX_sprite ---------------------------- */ + +#ifndef GL_SGIX_sprite +#define GL_SGIX_sprite 1 + +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, GLint* params); + +#define glSpriteParameterfSGIX GLEW_GET_FUN(__glewSpriteParameterfSGIX) +#define glSpriteParameterfvSGIX GLEW_GET_FUN(__glewSpriteParameterfvSGIX) +#define glSpriteParameteriSGIX GLEW_GET_FUN(__glewSpriteParameteriSGIX) +#define glSpriteParameterivSGIX GLEW_GET_FUN(__glewSpriteParameterivSGIX) + +#define GLEW_SGIX_sprite GLEW_GET_VAR(__GLEW_SGIX_sprite) + +#endif /* GL_SGIX_sprite */ + +/* ----------------------- GL_SGIX_tag_sample_buffer ----------------------- */ + +#ifndef GL_SGIX_tag_sample_buffer +#define GL_SGIX_tag_sample_buffer 1 + +typedef void (GLAPIENTRY * PFNGLTAGSAMPLEBUFFERSGIXPROC) (void); + +#define glTagSampleBufferSGIX GLEW_GET_FUN(__glewTagSampleBufferSGIX) + +#define GLEW_SGIX_tag_sample_buffer GLEW_GET_VAR(__GLEW_SGIX_tag_sample_buffer) + +#endif /* GL_SGIX_tag_sample_buffer */ + +/* ------------------------ GL_SGIX_texture_add_env ------------------------ */ + +#ifndef GL_SGIX_texture_add_env +#define GL_SGIX_texture_add_env 1 + +#define GLEW_SGIX_texture_add_env GLEW_GET_VAR(__GLEW_SGIX_texture_add_env) + +#endif /* GL_SGIX_texture_add_env */ + +/* -------------------- GL_SGIX_texture_coordinate_clamp ------------------- */ + +#ifndef GL_SGIX_texture_coordinate_clamp +#define GL_SGIX_texture_coordinate_clamp 1 + +#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369 +#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A +#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B + +#define GLEW_SGIX_texture_coordinate_clamp GLEW_GET_VAR(__GLEW_SGIX_texture_coordinate_clamp) + +#endif /* GL_SGIX_texture_coordinate_clamp */ + +/* ------------------------ GL_SGIX_texture_lod_bias ----------------------- */ + +#ifndef GL_SGIX_texture_lod_bias +#define GL_SGIX_texture_lod_bias 1 + +#define GLEW_SGIX_texture_lod_bias GLEW_GET_VAR(__GLEW_SGIX_texture_lod_bias) + +#endif /* GL_SGIX_texture_lod_bias */ + +/* ---------------------- GL_SGIX_texture_multi_buffer --------------------- */ + +#ifndef GL_SGIX_texture_multi_buffer +#define GL_SGIX_texture_multi_buffer 1 + +#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E + +#define GLEW_SGIX_texture_multi_buffer GLEW_GET_VAR(__GLEW_SGIX_texture_multi_buffer) + +#endif /* GL_SGIX_texture_multi_buffer */ + +/* ------------------------- GL_SGIX_texture_range ------------------------- */ + +#ifndef GL_SGIX_texture_range +#define GL_SGIX_texture_range 1 + +#define GL_RGB_SIGNED_SGIX 0x85E0 +#define GL_RGBA_SIGNED_SGIX 0x85E1 +#define GL_ALPHA_SIGNED_SGIX 0x85E2 +#define GL_LUMINANCE_SIGNED_SGIX 0x85E3 +#define GL_INTENSITY_SIGNED_SGIX 0x85E4 +#define GL_LUMINANCE_ALPHA_SIGNED_SGIX 0x85E5 +#define GL_RGB16_SIGNED_SGIX 0x85E6 +#define GL_RGBA16_SIGNED_SGIX 0x85E7 +#define GL_ALPHA16_SIGNED_SGIX 0x85E8 +#define GL_LUMINANCE16_SIGNED_SGIX 0x85E9 +#define GL_INTENSITY16_SIGNED_SGIX 0x85EA +#define GL_LUMINANCE16_ALPHA16_SIGNED_SGIX 0x85EB +#define GL_RGB_EXTENDED_RANGE_SGIX 0x85EC +#define GL_RGBA_EXTENDED_RANGE_SGIX 0x85ED +#define GL_ALPHA_EXTENDED_RANGE_SGIX 0x85EE +#define GL_LUMINANCE_EXTENDED_RANGE_SGIX 0x85EF +#define GL_INTENSITY_EXTENDED_RANGE_SGIX 0x85F0 +#define GL_LUMINANCE_ALPHA_EXTENDED_RANGE_SGIX 0x85F1 +#define GL_RGB16_EXTENDED_RANGE_SGIX 0x85F2 +#define GL_RGBA16_EXTENDED_RANGE_SGIX 0x85F3 +#define GL_ALPHA16_EXTENDED_RANGE_SGIX 0x85F4 +#define GL_LUMINANCE16_EXTENDED_RANGE_SGIX 0x85F5 +#define GL_INTENSITY16_EXTENDED_RANGE_SGIX 0x85F6 +#define GL_LUMINANCE16_ALPHA16_EXTENDED_RANGE_SGIX 0x85F7 +#define GL_MIN_LUMINANCE_SGIS 0x85F8 +#define GL_MAX_LUMINANCE_SGIS 0x85F9 +#define GL_MIN_INTENSITY_SGIS 0x85FA +#define GL_MAX_INTENSITY_SGIS 0x85FB + +#define GLEW_SGIX_texture_range GLEW_GET_VAR(__GLEW_SGIX_texture_range) + +#endif /* GL_SGIX_texture_range */ + +/* ----------------------- GL_SGIX_texture_scale_bias ---------------------- */ + +#ifndef GL_SGIX_texture_scale_bias +#define GL_SGIX_texture_scale_bias 1 + +#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179 +#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A +#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B +#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C + +#define GLEW_SGIX_texture_scale_bias GLEW_GET_VAR(__GLEW_SGIX_texture_scale_bias) + +#endif /* GL_SGIX_texture_scale_bias */ + +/* ------------------------- GL_SGIX_vertex_preclip ------------------------ */ + +#ifndef GL_SGIX_vertex_preclip +#define GL_SGIX_vertex_preclip 1 + +#define GL_VERTEX_PRECLIP_SGIX 0x83EE +#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF + +#define GLEW_SGIX_vertex_preclip GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip) + +#endif /* GL_SGIX_vertex_preclip */ + +/* ---------------------- GL_SGIX_vertex_preclip_hint ---------------------- */ + +#ifndef GL_SGIX_vertex_preclip_hint +#define GL_SGIX_vertex_preclip_hint 1 + +#define GL_VERTEX_PRECLIP_SGIX 0x83EE +#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF + +#define GLEW_SGIX_vertex_preclip_hint GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip_hint) + +#endif /* GL_SGIX_vertex_preclip_hint */ + +/* ----------------------------- GL_SGIX_ycrcb ----------------------------- */ + +#ifndef GL_SGIX_ycrcb +#define GL_SGIX_ycrcb 1 + +#define GLEW_SGIX_ycrcb GLEW_GET_VAR(__GLEW_SGIX_ycrcb) + +#endif /* GL_SGIX_ycrcb */ + +/* -------------------------- GL_SGI_color_matrix -------------------------- */ + +#ifndef GL_SGI_color_matrix +#define GL_SGI_color_matrix 1 + +#define GL_COLOR_MATRIX_SGI 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB + +#define GLEW_SGI_color_matrix GLEW_GET_VAR(__GLEW_SGI_color_matrix) + +#endif /* GL_SGI_color_matrix */ + +/* --------------------------- GL_SGI_color_table -------------------------- */ + +#ifndef GL_SGI_color_table +#define GL_SGI_color_table 1 + +#define GL_COLOR_TABLE_SGI 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2 +#define GL_PROXY_COLOR_TABLE_SGI 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5 +#define GL_COLOR_TABLE_SCALE_SGI 0x80D6 +#define GL_COLOR_TABLE_BIAS_SGI 0x80D7 +#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8 +#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF + +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* table); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, void* table); + +#define glColorTableParameterfvSGI GLEW_GET_FUN(__glewColorTableParameterfvSGI) +#define glColorTableParameterivSGI GLEW_GET_FUN(__glewColorTableParameterivSGI) +#define glColorTableSGI GLEW_GET_FUN(__glewColorTableSGI) +#define glCopyColorTableSGI GLEW_GET_FUN(__glewCopyColorTableSGI) +#define glGetColorTableParameterfvSGI GLEW_GET_FUN(__glewGetColorTableParameterfvSGI) +#define glGetColorTableParameterivSGI GLEW_GET_FUN(__glewGetColorTableParameterivSGI) +#define glGetColorTableSGI GLEW_GET_FUN(__glewGetColorTableSGI) + +#define GLEW_SGI_color_table GLEW_GET_VAR(__GLEW_SGI_color_table) + +#endif /* GL_SGI_color_table */ + +/* ----------------------- GL_SGI_texture_color_table ---------------------- */ + +#ifndef GL_SGI_texture_color_table +#define GL_SGI_texture_color_table 1 + +#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC +#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD + +#define GLEW_SGI_texture_color_table GLEW_GET_VAR(__GLEW_SGI_texture_color_table) + +#endif /* GL_SGI_texture_color_table */ + +/* ------------------------- GL_SUNX_constant_data ------------------------- */ + +#ifndef GL_SUNX_constant_data +#define GL_SUNX_constant_data 1 + +#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 +#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6 + +typedef void (GLAPIENTRY * PFNGLFINISHTEXTURESUNXPROC) (void); + +#define glFinishTextureSUNX GLEW_GET_FUN(__glewFinishTextureSUNX) + +#define GLEW_SUNX_constant_data GLEW_GET_VAR(__GLEW_SUNX_constant_data) + +#endif /* GL_SUNX_constant_data */ + +/* -------------------- GL_SUN_convolution_border_modes -------------------- */ + +#ifndef GL_SUN_convolution_border_modes +#define GL_SUN_convolution_border_modes 1 + +#define GL_WRAP_BORDER_SUN 0x81D4 + +#define GLEW_SUN_convolution_border_modes GLEW_GET_VAR(__GLEW_SUN_convolution_border_modes) + +#endif /* GL_SUN_convolution_border_modes */ + +/* -------------------------- GL_SUN_global_alpha -------------------------- */ + +#ifndef GL_SUN_global_alpha +#define GL_SUN_global_alpha 1 + +#define GL_GLOBAL_ALPHA_SUN 0x81D9 +#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA + +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor); + +#define glGlobalAlphaFactorbSUN GLEW_GET_FUN(__glewGlobalAlphaFactorbSUN) +#define glGlobalAlphaFactordSUN GLEW_GET_FUN(__glewGlobalAlphaFactordSUN) +#define glGlobalAlphaFactorfSUN GLEW_GET_FUN(__glewGlobalAlphaFactorfSUN) +#define glGlobalAlphaFactoriSUN GLEW_GET_FUN(__glewGlobalAlphaFactoriSUN) +#define glGlobalAlphaFactorsSUN GLEW_GET_FUN(__glewGlobalAlphaFactorsSUN) +#define glGlobalAlphaFactorubSUN GLEW_GET_FUN(__glewGlobalAlphaFactorubSUN) +#define glGlobalAlphaFactoruiSUN GLEW_GET_FUN(__glewGlobalAlphaFactoruiSUN) +#define glGlobalAlphaFactorusSUN GLEW_GET_FUN(__glewGlobalAlphaFactorusSUN) + +#define GLEW_SUN_global_alpha GLEW_GET_VAR(__GLEW_SUN_global_alpha) + +#endif /* GL_SUN_global_alpha */ + +/* --------------------------- GL_SUN_mesh_array --------------------------- */ + +#ifndef GL_SUN_mesh_array +#define GL_SUN_mesh_array 1 + +#define GL_QUAD_MESH_SUN 0x8614 +#define GL_TRIANGLE_MESH_SUN 0x8615 + +#define GLEW_SUN_mesh_array GLEW_GET_VAR(__GLEW_SUN_mesh_array) + +#endif /* GL_SUN_mesh_array */ + +/* ------------------------ GL_SUN_read_video_pixels ----------------------- */ + +#ifndef GL_SUN_read_video_pixels +#define GL_SUN_read_video_pixels 1 + +typedef void (GLAPIENTRY * PFNGLREADVIDEOPIXELSSUNPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); + +#define glReadVideoPixelsSUN GLEW_GET_FUN(__glewReadVideoPixelsSUN) + +#define GLEW_SUN_read_video_pixels GLEW_GET_VAR(__GLEW_SUN_read_video_pixels) + +#endif /* GL_SUN_read_video_pixels */ + +/* --------------------------- GL_SUN_slice_accum -------------------------- */ + +#ifndef GL_SUN_slice_accum +#define GL_SUN_slice_accum 1 + +#define GL_SLICE_ACCUM_SUN 0x85CC + +#define GLEW_SUN_slice_accum GLEW_GET_VAR(__GLEW_SUN_slice_accum) + +#endif /* GL_SUN_slice_accum */ + +/* -------------------------- GL_SUN_triangle_list ------------------------- */ + +#ifndef GL_SUN_triangle_list +#define GL_SUN_triangle_list 1 + +#define GL_RESTART_SUN 0x01 +#define GL_REPLACE_MIDDLE_SUN 0x02 +#define GL_REPLACE_OLDEST_SUN 0x03 +#define GL_TRIANGLE_LIST_SUN 0x81D7 +#define GL_REPLACEMENT_CODE_SUN 0x81D8 +#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0 +#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 +#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 +#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 +#define GL_R1UI_V3F_SUN 0x85C4 +#define GL_R1UI_C4UB_V3F_SUN 0x85C5 +#define GL_R1UI_C3F_V3F_SUN 0x85C6 +#define GL_R1UI_N3F_V3F_SUN 0x85C7 +#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8 +#define GL_R1UI_T2F_V3F_SUN 0x85C9 +#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA +#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB + +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte* code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint* code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort* code); + +#define glReplacementCodePointerSUN GLEW_GET_FUN(__glewReplacementCodePointerSUN) +#define glReplacementCodeubSUN GLEW_GET_FUN(__glewReplacementCodeubSUN) +#define glReplacementCodeubvSUN GLEW_GET_FUN(__glewReplacementCodeubvSUN) +#define glReplacementCodeuiSUN GLEW_GET_FUN(__glewReplacementCodeuiSUN) +#define glReplacementCodeuivSUN GLEW_GET_FUN(__glewReplacementCodeuivSUN) +#define glReplacementCodeusSUN GLEW_GET_FUN(__glewReplacementCodeusSUN) +#define glReplacementCodeusvSUN GLEW_GET_FUN(__glewReplacementCodeusvSUN) + +#define GLEW_SUN_triangle_list GLEW_GET_VAR(__GLEW_SUN_triangle_list) + +#endif /* GL_SUN_triangle_list */ + +/* ----------------------------- GL_SUN_vertex ----------------------------- */ + +#ifndef GL_SUN_vertex +#define GL_SUN_vertex 1 + +typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte* c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte* c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint* rc, const GLubyte *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat* tc, const GLubyte *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *v); + +#define glColor3fVertex3fSUN GLEW_GET_FUN(__glewColor3fVertex3fSUN) +#define glColor3fVertex3fvSUN GLEW_GET_FUN(__glewColor3fVertex3fvSUN) +#define glColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fSUN) +#define glColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fvSUN) +#define glColor4ubVertex2fSUN GLEW_GET_FUN(__glewColor4ubVertex2fSUN) +#define glColor4ubVertex2fvSUN GLEW_GET_FUN(__glewColor4ubVertex2fvSUN) +#define glColor4ubVertex3fSUN GLEW_GET_FUN(__glewColor4ubVertex3fSUN) +#define glColor4ubVertex3fvSUN GLEW_GET_FUN(__glewColor4ubVertex3fvSUN) +#define glNormal3fVertex3fSUN GLEW_GET_FUN(__glewNormal3fVertex3fSUN) +#define glNormal3fVertex3fvSUN GLEW_GET_FUN(__glewNormal3fVertex3fvSUN) +#define glReplacementCodeuiColor3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fSUN) +#define glReplacementCodeuiColor3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fvSUN) +#define glReplacementCodeuiColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fSUN) +#define glReplacementCodeuiColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fvSUN) +#define glReplacementCodeuiColor4ubVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fSUN) +#define glReplacementCodeuiColor4ubVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fvSUN) +#define glReplacementCodeuiNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fSUN) +#define glReplacementCodeuiNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fvSUN) +#define glReplacementCodeuiVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fSUN) +#define glReplacementCodeuiVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fvSUN) +#define glTexCoord2fColor3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fSUN) +#define glTexCoord2fColor3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fvSUN) +#define glTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fSUN) +#define glTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fvSUN) +#define glTexCoord2fColor4ubVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fSUN) +#define glTexCoord2fColor4ubVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fvSUN) +#define glTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fSUN) +#define glTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fvSUN) +#define glTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fSUN) +#define glTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fvSUN) +#define glTexCoord4fColor4fNormal3fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fSUN) +#define glTexCoord4fColor4fNormal3fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fvSUN) +#define glTexCoord4fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fSUN) +#define glTexCoord4fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fvSUN) + +#define GLEW_SUN_vertex GLEW_GET_VAR(__GLEW_SUN_vertex) + +#endif /* GL_SUN_vertex */ + +/* -------------------------- GL_WIN_phong_shading ------------------------- */ + +#ifndef GL_WIN_phong_shading +#define GL_WIN_phong_shading 1 + +#define GL_PHONG_WIN 0x80EA +#define GL_PHONG_HINT_WIN 0x80EB + +#define GLEW_WIN_phong_shading GLEW_GET_VAR(__GLEW_WIN_phong_shading) + +#endif /* GL_WIN_phong_shading */ + +/* -------------------------- GL_WIN_specular_fog -------------------------- */ + +#ifndef GL_WIN_specular_fog +#define GL_WIN_specular_fog 1 + +#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC + +#define GLEW_WIN_specular_fog GLEW_GET_VAR(__GLEW_WIN_specular_fog) + +#endif /* GL_WIN_specular_fog */ + +/* ---------------------------- GL_WIN_swap_hint --------------------------- */ + +#ifndef GL_WIN_swap_hint +#define GL_WIN_swap_hint 1 + +typedef void (GLAPIENTRY * PFNGLADDSWAPHINTRECTWINPROC) (GLint x, GLint y, GLsizei width, GLsizei height); + +#define glAddSwapHintRectWIN GLEW_GET_FUN(__glewAddSwapHintRectWIN) + +#define GLEW_WIN_swap_hint GLEW_GET_VAR(__GLEW_WIN_swap_hint) + +#endif /* GL_WIN_swap_hint */ + +/* ------------------------------------------------------------------------- */ + +#if defined(GLEW_MX) && defined(_WIN32) +#define GLEW_FUN_EXPORT +#else +#define GLEW_FUN_EXPORT GLEWAPI +#endif /* GLEW_MX */ + +#if defined(GLEW_MX) +#define GLEW_VAR_EXPORT +#else +#define GLEW_VAR_EXPORT GLEWAPI +#endif /* GLEW_MX */ + +#if defined(GLEW_MX) && defined(_WIN32) +struct GLEWContextStruct +{ +#endif /* GLEW_MX */ + +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DPROC __glewCopyTexSubImage3D; +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSPROC __glewDrawRangeElements; +GLEW_FUN_EXPORT PFNGLTEXIMAGE3DPROC __glewTexImage3D; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DPROC __glewTexSubImage3D; + +GLEW_FUN_EXPORT PFNGLACTIVETEXTUREPROC __glewActiveTexture; +GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREPROC __glewClientActiveTexture; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DPROC __glewCompressedTexImage1D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DPROC __glewCompressedTexImage2D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DPROC __glewCompressedTexImage3D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC __glewCompressedTexSubImage1D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC __glewCompressedTexSubImage2D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC __glewCompressedTexSubImage3D; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEPROC __glewGetCompressedTexImage; +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDPROC __glewLoadTransposeMatrixd; +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFPROC __glewLoadTransposeMatrixf; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDPROC __glewMultTransposeMatrixd; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXFPROC __glewMultTransposeMatrixf; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DPROC __glewMultiTexCoord1d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVPROC __glewMultiTexCoord1dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FPROC __glewMultiTexCoord1f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVPROC __glewMultiTexCoord1fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IPROC __glewMultiTexCoord1i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVPROC __glewMultiTexCoord1iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SPROC __glewMultiTexCoord1s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVPROC __glewMultiTexCoord1sv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DPROC __glewMultiTexCoord2d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVPROC __glewMultiTexCoord2dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FPROC __glewMultiTexCoord2f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVPROC __glewMultiTexCoord2fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IPROC __glewMultiTexCoord2i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVPROC __glewMultiTexCoord2iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SPROC __glewMultiTexCoord2s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVPROC __glewMultiTexCoord2sv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DPROC __glewMultiTexCoord3d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVPROC __glewMultiTexCoord3dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FPROC __glewMultiTexCoord3f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVPROC __glewMultiTexCoord3fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IPROC __glewMultiTexCoord3i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVPROC __glewMultiTexCoord3iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SPROC __glewMultiTexCoord3s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVPROC __glewMultiTexCoord3sv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DPROC __glewMultiTexCoord4d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVPROC __glewMultiTexCoord4dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FPROC __glewMultiTexCoord4f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVPROC __glewMultiTexCoord4fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IPROC __glewMultiTexCoord4i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVPROC __glewMultiTexCoord4iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SPROC __glewMultiTexCoord4s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVPROC __glewMultiTexCoord4sv; +GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEPROC __glewSampleCoverage; + +GLEW_FUN_EXPORT PFNGLBLENDCOLORPROC __glewBlendColor; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONPROC __glewBlendEquation; +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEPROC __glewBlendFuncSeparate; +GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERPROC __glewFogCoordPointer; +GLEW_FUN_EXPORT PFNGLFOGCOORDDPROC __glewFogCoordd; +GLEW_FUN_EXPORT PFNGLFOGCOORDDVPROC __glewFogCoorddv; +GLEW_FUN_EXPORT PFNGLFOGCOORDFPROC __glewFogCoordf; +GLEW_FUN_EXPORT PFNGLFOGCOORDFVPROC __glewFogCoordfv; +GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSPROC __glewMultiDrawArrays; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSPROC __glewMultiDrawElements; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFPROC __glewPointParameterf; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVPROC __glewPointParameterfv; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIPROC __glewPointParameteri; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIVPROC __glewPointParameteriv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BPROC __glewSecondaryColor3b; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVPROC __glewSecondaryColor3bv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DPROC __glewSecondaryColor3d; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVPROC __glewSecondaryColor3dv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FPROC __glewSecondaryColor3f; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVPROC __glewSecondaryColor3fv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IPROC __glewSecondaryColor3i; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVPROC __glewSecondaryColor3iv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SPROC __glewSecondaryColor3s; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVPROC __glewSecondaryColor3sv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBPROC __glewSecondaryColor3ub; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVPROC __glewSecondaryColor3ubv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIPROC __glewSecondaryColor3ui; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVPROC __glewSecondaryColor3uiv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USPROC __glewSecondaryColor3us; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVPROC __glewSecondaryColor3usv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERPROC __glewSecondaryColorPointer; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DPROC __glewWindowPos2d; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVPROC __glewWindowPos2dv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FPROC __glewWindowPos2f; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVPROC __glewWindowPos2fv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IPROC __glewWindowPos2i; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVPROC __glewWindowPos2iv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SPROC __glewWindowPos2s; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVPROC __glewWindowPos2sv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DPROC __glewWindowPos3d; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVPROC __glewWindowPos3dv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FPROC __glewWindowPos3f; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVPROC __glewWindowPos3fv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IPROC __glewWindowPos3i; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVPROC __glewWindowPos3iv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SPROC __glewWindowPos3s; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVPROC __glewWindowPos3sv; + +GLEW_FUN_EXPORT PFNGLBEGINQUERYPROC __glewBeginQuery; +GLEW_FUN_EXPORT PFNGLBINDBUFFERPROC __glewBindBuffer; +GLEW_FUN_EXPORT PFNGLBUFFERDATAPROC __glewBufferData; +GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAPROC __glewBufferSubData; +GLEW_FUN_EXPORT PFNGLDELETEBUFFERSPROC __glewDeleteBuffers; +GLEW_FUN_EXPORT PFNGLDELETEQUERIESPROC __glewDeleteQueries; +GLEW_FUN_EXPORT PFNGLENDQUERYPROC __glewEndQuery; +GLEW_FUN_EXPORT PFNGLGENBUFFERSPROC __glewGenBuffers; +GLEW_FUN_EXPORT PFNGLGENQUERIESPROC __glewGenQueries; +GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVPROC __glewGetBufferParameteriv; +GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVPROC __glewGetBufferPointerv; +GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAPROC __glewGetBufferSubData; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVPROC __glewGetQueryObjectiv; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVPROC __glewGetQueryObjectuiv; +GLEW_FUN_EXPORT PFNGLGETQUERYIVPROC __glewGetQueryiv; +GLEW_FUN_EXPORT PFNGLISBUFFERPROC __glewIsBuffer; +GLEW_FUN_EXPORT PFNGLISQUERYPROC __glewIsQuery; +GLEW_FUN_EXPORT PFNGLMAPBUFFERPROC __glewMapBuffer; +GLEW_FUN_EXPORT PFNGLUNMAPBUFFERPROC __glewUnmapBuffer; + +GLEW_FUN_EXPORT PFNGLATTACHSHADERPROC __glewAttachShader; +GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONPROC __glewBindAttribLocation; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEPROC __glewBlendEquationSeparate; +GLEW_FUN_EXPORT PFNGLCOMPILESHADERPROC __glewCompileShader; +GLEW_FUN_EXPORT PFNGLCREATEPROGRAMPROC __glewCreateProgram; +GLEW_FUN_EXPORT PFNGLCREATESHADERPROC __glewCreateShader; +GLEW_FUN_EXPORT PFNGLDELETEPROGRAMPROC __glewDeleteProgram; +GLEW_FUN_EXPORT PFNGLDELETESHADERPROC __glewDeleteShader; +GLEW_FUN_EXPORT PFNGLDETACHSHADERPROC __glewDetachShader; +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYPROC __glewDisableVertexAttribArray; +GLEW_FUN_EXPORT PFNGLDRAWBUFFERSPROC __glewDrawBuffers; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYPROC __glewEnableVertexAttribArray; +GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBPROC __glewGetActiveAttrib; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMPROC __glewGetActiveUniform; +GLEW_FUN_EXPORT PFNGLGETATTACHEDSHADERSPROC __glewGetAttachedShaders; +GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONPROC __glewGetAttribLocation; +GLEW_FUN_EXPORT PFNGLGETPROGRAMINFOLOGPROC __glewGetProgramInfoLog; +GLEW_FUN_EXPORT PFNGLGETPROGRAMIVPROC __glewGetProgramiv; +GLEW_FUN_EXPORT PFNGLGETSHADERINFOLOGPROC __glewGetShaderInfoLog; +GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEPROC __glewGetShaderSource; +GLEW_FUN_EXPORT PFNGLGETSHADERIVPROC __glewGetShaderiv; +GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONPROC __glewGetUniformLocation; +GLEW_FUN_EXPORT PFNGLGETUNIFORMFVPROC __glewGetUniformfv; +GLEW_FUN_EXPORT PFNGLGETUNIFORMIVPROC __glewGetUniformiv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVPROC __glewGetVertexAttribPointerv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVPROC __glewGetVertexAttribdv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVPROC __glewGetVertexAttribfv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVPROC __glewGetVertexAttribiv; +GLEW_FUN_EXPORT PFNGLISPROGRAMPROC __glewIsProgram; +GLEW_FUN_EXPORT PFNGLISSHADERPROC __glewIsShader; +GLEW_FUN_EXPORT PFNGLLINKPROGRAMPROC __glewLinkProgram; +GLEW_FUN_EXPORT PFNGLSHADERSOURCEPROC __glewShaderSource; +GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEPROC __glewStencilFuncSeparate; +GLEW_FUN_EXPORT PFNGLSTENCILMASKSEPARATEPROC __glewStencilMaskSeparate; +GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEPROC __glewStencilOpSeparate; +GLEW_FUN_EXPORT PFNGLUNIFORM1FPROC __glewUniform1f; +GLEW_FUN_EXPORT PFNGLUNIFORM1FVPROC __glewUniform1fv; +GLEW_FUN_EXPORT PFNGLUNIFORM1IPROC __glewUniform1i; +GLEW_FUN_EXPORT PFNGLUNIFORM1IVPROC __glewUniform1iv; +GLEW_FUN_EXPORT PFNGLUNIFORM2FPROC __glewUniform2f; +GLEW_FUN_EXPORT PFNGLUNIFORM2FVPROC __glewUniform2fv; +GLEW_FUN_EXPORT PFNGLUNIFORM2IPROC __glewUniform2i; +GLEW_FUN_EXPORT PFNGLUNIFORM2IVPROC __glewUniform2iv; +GLEW_FUN_EXPORT PFNGLUNIFORM3FPROC __glewUniform3f; +GLEW_FUN_EXPORT PFNGLUNIFORM3FVPROC __glewUniform3fv; +GLEW_FUN_EXPORT PFNGLUNIFORM3IPROC __glewUniform3i; +GLEW_FUN_EXPORT PFNGLUNIFORM3IVPROC __glewUniform3iv; +GLEW_FUN_EXPORT PFNGLUNIFORM4FPROC __glewUniform4f; +GLEW_FUN_EXPORT PFNGLUNIFORM4FVPROC __glewUniform4fv; +GLEW_FUN_EXPORT PFNGLUNIFORM4IPROC __glewUniform4i; +GLEW_FUN_EXPORT PFNGLUNIFORM4IVPROC __glewUniform4iv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVPROC __glewUniformMatrix2fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVPROC __glewUniformMatrix3fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVPROC __glewUniformMatrix4fv; +GLEW_FUN_EXPORT PFNGLUSEPROGRAMPROC __glewUseProgram; +GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPROC __glewValidateProgram; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DPROC __glewVertexAttrib1d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVPROC __glewVertexAttrib1dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FPROC __glewVertexAttrib1f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVPROC __glewVertexAttrib1fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SPROC __glewVertexAttrib1s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVPROC __glewVertexAttrib1sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DPROC __glewVertexAttrib2d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVPROC __glewVertexAttrib2dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FPROC __glewVertexAttrib2f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVPROC __glewVertexAttrib2fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SPROC __glewVertexAttrib2s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVPROC __glewVertexAttrib2sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DPROC __glewVertexAttrib3d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVPROC __glewVertexAttrib3dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FPROC __glewVertexAttrib3f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVPROC __glewVertexAttrib3fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SPROC __glewVertexAttrib3s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVPROC __glewVertexAttrib3sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NBVPROC __glewVertexAttrib4Nbv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NIVPROC __glewVertexAttrib4Niv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NSVPROC __glewVertexAttrib4Nsv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBPROC __glewVertexAttrib4Nub; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBVPROC __glewVertexAttrib4Nubv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUIVPROC __glewVertexAttrib4Nuiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUSVPROC __glewVertexAttrib4Nusv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4BVPROC __glewVertexAttrib4bv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DPROC __glewVertexAttrib4d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVPROC __glewVertexAttrib4dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FPROC __glewVertexAttrib4f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVPROC __glewVertexAttrib4fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4IVPROC __glewVertexAttrib4iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SPROC __glewVertexAttrib4s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVPROC __glewVertexAttrib4sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVPROC __glewVertexAttrib4ubv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UIVPROC __glewVertexAttrib4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4USVPROC __glewVertexAttrib4usv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERPROC __glewVertexAttribPointer; + +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X3FVPROC __glewUniformMatrix2x3fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X4FVPROC __glewUniformMatrix2x4fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X2FVPROC __glewUniformMatrix3x2fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X4FVPROC __glewUniformMatrix3x4fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X2FVPROC __glewUniformMatrix4x2fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X3FVPROC __glewUniformMatrix4x3fv; + +GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERPROC __glewBeginConditionalRender; +GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKPROC __glewBeginTransformFeedback; +GLEW_FUN_EXPORT PFNGLBINDBUFFERBASEPROC __glewBindBufferBase; +GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGEPROC __glewBindBufferRange; +GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONPROC __glewBindFragDataLocation; +GLEW_FUN_EXPORT PFNGLCLAMPCOLORPROC __glewClampColor; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERFIPROC __glewClearBufferfi; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERFVPROC __glewClearBufferfv; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERIVPROC __glewClearBufferiv; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERUIVPROC __glewClearBufferuiv; +GLEW_FUN_EXPORT PFNGLCOLORMASKIPROC __glewColorMaski; +GLEW_FUN_EXPORT PFNGLDISABLEIPROC __glewDisablei; +GLEW_FUN_EXPORT PFNGLENABLEIPROC __glewEnablei; +GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERPROC __glewEndConditionalRender; +GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKPROC __glewEndTransformFeedback; +GLEW_FUN_EXPORT PFNGLGETBOOLEANI_VPROC __glewGetBooleani_v; +GLEW_FUN_EXPORT PFNGLGETFRAGDATALOCATIONPROC __glewGetFragDataLocation; +GLEW_FUN_EXPORT PFNGLGETINTEGERI_VPROC __glewGetIntegeri_v; +GLEW_FUN_EXPORT PFNGLGETSTRINGIPROC __glewGetStringi; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIIVPROC __glewGetTexParameterIiv; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIUIVPROC __glewGetTexParameterIuiv; +GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGPROC __glewGetTransformFeedbackVarying; +GLEW_FUN_EXPORT PFNGLGETUNIFORMUIVPROC __glewGetUniformuiv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIIVPROC __glewGetVertexAttribIiv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIUIVPROC __glewGetVertexAttribIuiv; +GLEW_FUN_EXPORT PFNGLISENABLEDIPROC __glewIsEnabledi; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIIVPROC __glewTexParameterIiv; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIUIVPROC __glewTexParameterIuiv; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSPROC __glewTransformFeedbackVaryings; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIPROC __glewUniform1ui; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIVPROC __glewUniform1uiv; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIPROC __glewUniform2ui; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIVPROC __glewUniform2uiv; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIPROC __glewUniform3ui; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIVPROC __glewUniform3uiv; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIPROC __glewUniform4ui; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIVPROC __glewUniform4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IPROC __glewVertexAttribI1i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IVPROC __glewVertexAttribI1iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIPROC __glewVertexAttribI1ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIVPROC __glewVertexAttribI1uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IPROC __glewVertexAttribI2i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IVPROC __glewVertexAttribI2iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIPROC __glewVertexAttribI2ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIVPROC __glewVertexAttribI2uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IPROC __glewVertexAttribI3i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IVPROC __glewVertexAttribI3iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIPROC __glewVertexAttribI3ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIVPROC __glewVertexAttribI3uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4BVPROC __glewVertexAttribI4bv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IPROC __glewVertexAttribI4i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IVPROC __glewVertexAttribI4iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4SVPROC __glewVertexAttribI4sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UBVPROC __glewVertexAttribI4ubv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIPROC __glewVertexAttribI4ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIVPROC __glewVertexAttribI4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4USVPROC __glewVertexAttribI4usv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIPOINTERPROC __glewVertexAttribIPointer; + +GLEW_FUN_EXPORT PFNGLTBUFFERMASK3DFXPROC __glewTbufferMask3DFX; + +GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE; +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE; +GLEW_FUN_EXPORT PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC __glewMultiDrawElementArrayAPPLE; +GLEW_FUN_EXPORT PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC __glewMultiDrawRangeElementArrayAPPLE; + +GLEW_FUN_EXPORT PFNGLDELETEFENCESAPPLEPROC __glewDeleteFencesAPPLE; +GLEW_FUN_EXPORT PFNGLFINISHFENCEAPPLEPROC __glewFinishFenceAPPLE; +GLEW_FUN_EXPORT PFNGLFINISHOBJECTAPPLEPROC __glewFinishObjectAPPLE; +GLEW_FUN_EXPORT PFNGLGENFENCESAPPLEPROC __glewGenFencesAPPLE; +GLEW_FUN_EXPORT PFNGLISFENCEAPPLEPROC __glewIsFenceAPPLE; +GLEW_FUN_EXPORT PFNGLSETFENCEAPPLEPROC __glewSetFenceAPPLE; +GLEW_FUN_EXPORT PFNGLTESTFENCEAPPLEPROC __glewTestFenceAPPLE; +GLEW_FUN_EXPORT PFNGLTESTOBJECTAPPLEPROC __glewTestObjectAPPLE; + +GLEW_FUN_EXPORT PFNGLBUFFERPARAMETERIAPPLEPROC __glewBufferParameteriAPPLE; +GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC __glewFlushMappedBufferRangeAPPLE; + +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC __glewGetTexParameterPointervAPPLE; +GLEW_FUN_EXPORT PFNGLTEXTURERANGEAPPLEPROC __glewTextureRangeAPPLE; + +GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYAPPLEPROC __glewBindVertexArrayAPPLE; +GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSAPPLEPROC __glewDeleteVertexArraysAPPLE; +GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSAPPLEPROC __glewGenVertexArraysAPPLE; +GLEW_FUN_EXPORT PFNGLISVERTEXARRAYAPPLEPROC __glewIsVertexArrayAPPLE; + +GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC __glewFlushVertexArrayRangeAPPLE; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYPARAMETERIAPPLEPROC __glewVertexArrayParameteriAPPLE; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGEAPPLEPROC __glewVertexArrayRangeAPPLE; + +GLEW_FUN_EXPORT PFNGLCLAMPCOLORARBPROC __glewClampColorARB; + +GLEW_FUN_EXPORT PFNGLDRAWBUFFERSARBPROC __glewDrawBuffersARB; + +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDARBPROC __glewDrawArraysInstancedARB; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDARBPROC __glewDrawElementsInstancedARB; + +GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer; +GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer; +GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFERPROC __glewBlitFramebuffer; +GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSPROC __glewCheckFramebufferStatus; +GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSPROC __glewDeleteFramebuffers; +GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSPROC __glewDeleteRenderbuffers; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFERPROC __glewFramebufferRenderbuffer; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURLAYERPROC __glewFramebufferTexturLayer; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE1DPROC __glewFramebufferTexture1D; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DPROC __glewFramebufferTexture2D; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DPROC __glewFramebufferTexture3D; +GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSPROC __glewGenFramebuffers; +GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSPROC __glewGenRenderbuffers; +GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPPROC __glewGenerateMipmap; +GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC __glewGetFramebufferAttachmentParameteriv; +GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVPROC __glewGetRenderbufferParameteriv; +GLEW_FUN_EXPORT PFNGLISFRAMEBUFFERPROC __glewIsFramebuffer; +GLEW_FUN_EXPORT PFNGLISRENDERBUFFERPROC __glewIsRenderbuffer; +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEPROC __glewRenderbufferStorage; +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC __glewRenderbufferStorageMultisample; + +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREARBPROC __glewFramebufferTextureARB; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREFACEARBPROC __glewFramebufferTextureFaceARB; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYERARBPROC __glewFramebufferTextureLayerARB; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIARBPROC __glewProgramParameteriARB; + +GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEPROC __glewColorSubTable; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPROC __glewColorTable; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVPROC __glewColorTableParameterfv; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVPROC __glewColorTableParameteriv; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DPROC __glewConvolutionFilter1D; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DPROC __glewConvolutionFilter2D; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFPROC __glewConvolutionParameterf; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVPROC __glewConvolutionParameterfv; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIPROC __glewConvolutionParameteri; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVPROC __glewConvolutionParameteriv; +GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEPROC __glewCopyColorSubTable; +GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLEPROC __glewCopyColorTable; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DPROC __glewCopyConvolutionFilter1D; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DPROC __glewCopyConvolutionFilter2D; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPROC __glewGetColorTable; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVPROC __glewGetColorTableParameterfv; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVPROC __glewGetColorTableParameteriv; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTERPROC __glewGetConvolutionFilter; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVPROC __glewGetConvolutionParameterfv; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVPROC __glewGetConvolutionParameteriv; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPROC __glewGetHistogram; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVPROC __glewGetHistogramParameterfv; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVPROC __glewGetHistogramParameteriv; +GLEW_FUN_EXPORT PFNGLGETMINMAXPROC __glewGetMinmax; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVPROC __glewGetMinmaxParameterfv; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVPROC __glewGetMinmaxParameteriv; +GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTERPROC __glewGetSeparableFilter; +GLEW_FUN_EXPORT PFNGLHISTOGRAMPROC __glewHistogram; +GLEW_FUN_EXPORT PFNGLMINMAXPROC __glewMinmax; +GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMPROC __glewResetHistogram; +GLEW_FUN_EXPORT PFNGLRESETMINMAXPROC __glewResetMinmax; +GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D; + +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORARBPROC __glewVertexAttribDivisorARB; + +GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEPROC __glewFlushMappedBufferRange; +GLEW_FUN_EXPORT PFNGLMAPBUFFERRANGEPROC __glewMapBufferRange; + +GLEW_FUN_EXPORT PFNGLCURRENTPALETTEMATRIXARBPROC __glewCurrentPaletteMatrixARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXPOINTERARBPROC __glewMatrixIndexPointerARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB; + +GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB; + +GLEW_FUN_EXPORT PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB; +GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREARBPROC __glewClientActiveTextureARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DARBPROC __glewMultiTexCoord1dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVARBPROC __glewMultiTexCoord1dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FARBPROC __glewMultiTexCoord1fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVARBPROC __glewMultiTexCoord1fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IARBPROC __glewMultiTexCoord1iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVARBPROC __glewMultiTexCoord1ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SARBPROC __glewMultiTexCoord1sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVARBPROC __glewMultiTexCoord1svARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DARBPROC __glewMultiTexCoord2dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVARBPROC __glewMultiTexCoord2dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FARBPROC __glewMultiTexCoord2fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVARBPROC __glewMultiTexCoord2fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IARBPROC __glewMultiTexCoord2iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVARBPROC __glewMultiTexCoord2ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SARBPROC __glewMultiTexCoord2sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVARBPROC __glewMultiTexCoord2svARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DARBPROC __glewMultiTexCoord3dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVARBPROC __glewMultiTexCoord3dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FARBPROC __glewMultiTexCoord3fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVARBPROC __glewMultiTexCoord3fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IARBPROC __glewMultiTexCoord3iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVARBPROC __glewMultiTexCoord3ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SARBPROC __glewMultiTexCoord3sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVARBPROC __glewMultiTexCoord3svARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DARBPROC __glewMultiTexCoord4dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVARBPROC __glewMultiTexCoord4dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FARBPROC __glewMultiTexCoord4fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVARBPROC __glewMultiTexCoord4fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IARBPROC __glewMultiTexCoord4iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVARBPROC __glewMultiTexCoord4ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SARBPROC __glewMultiTexCoord4sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVARBPROC __glewMultiTexCoord4svARB; + +GLEW_FUN_EXPORT PFNGLBEGINQUERYARBPROC __glewBeginQueryARB; +GLEW_FUN_EXPORT PFNGLDELETEQUERIESARBPROC __glewDeleteQueriesARB; +GLEW_FUN_EXPORT PFNGLENDQUERYARBPROC __glewEndQueryARB; +GLEW_FUN_EXPORT PFNGLGENQUERIESARBPROC __glewGenQueriesARB; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVARBPROC __glewGetQueryObjectivARB; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVARBPROC __glewGetQueryObjectuivARB; +GLEW_FUN_EXPORT PFNGLGETQUERYIVARBPROC __glewGetQueryivARB; +GLEW_FUN_EXPORT PFNGLISQUERYARBPROC __glewIsQueryARB; + +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB; + +GLEW_FUN_EXPORT PFNGLATTACHOBJECTARBPROC __glewAttachObjectARB; +GLEW_FUN_EXPORT PFNGLCOMPILESHADERARBPROC __glewCompileShaderARB; +GLEW_FUN_EXPORT PFNGLCREATEPROGRAMOBJECTARBPROC __glewCreateProgramObjectARB; +GLEW_FUN_EXPORT PFNGLCREATESHADEROBJECTARBPROC __glewCreateShaderObjectARB; +GLEW_FUN_EXPORT PFNGLDELETEOBJECTARBPROC __glewDeleteObjectARB; +GLEW_FUN_EXPORT PFNGLDETACHOBJECTARBPROC __glewDetachObjectARB; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMARBPROC __glewGetActiveUniformARB; +GLEW_FUN_EXPORT PFNGLGETATTACHEDOBJECTSARBPROC __glewGetAttachedObjectsARB; +GLEW_FUN_EXPORT PFNGLGETHANDLEARBPROC __glewGetHandleARB; +GLEW_FUN_EXPORT PFNGLGETINFOLOGARBPROC __glewGetInfoLogARB; +GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERFVARBPROC __glewGetObjectParameterfvARB; +GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERIVARBPROC __glewGetObjectParameterivARB; +GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEARBPROC __glewGetShaderSourceARB; +GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONARBPROC __glewGetUniformLocationARB; +GLEW_FUN_EXPORT PFNGLGETUNIFORMFVARBPROC __glewGetUniformfvARB; +GLEW_FUN_EXPORT PFNGLGETUNIFORMIVARBPROC __glewGetUniformivARB; +GLEW_FUN_EXPORT PFNGLLINKPROGRAMARBPROC __glewLinkProgramARB; +GLEW_FUN_EXPORT PFNGLSHADERSOURCEARBPROC __glewShaderSourceARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1FARBPROC __glewUniform1fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1FVARBPROC __glewUniform1fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1IARBPROC __glewUniform1iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1IVARBPROC __glewUniform1ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2FARBPROC __glewUniform2fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2FVARBPROC __glewUniform2fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2IARBPROC __glewUniform2iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2IVARBPROC __glewUniform2ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3FARBPROC __glewUniform3fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3FVARBPROC __glewUniform3fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3IARBPROC __glewUniform3iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3IVARBPROC __glewUniform3ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4FARBPROC __glewUniform4fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4FVARBPROC __glewUniform4fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4IARBPROC __glewUniform4iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4IVARBPROC __glewUniform4ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVARBPROC __glewUniformMatrix2fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVARBPROC __glewUniformMatrix3fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB; +GLEW_FUN_EXPORT PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB; +GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB; + +GLEW_FUN_EXPORT PFNGLTEXBUFFERARBPROC __glewTexBufferARB; + +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC __glewCompressedTexSubImage1DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC __glewCompressedTexSubImage2DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC __glewCompressedTexSubImage3DARB; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEARBPROC __glewGetCompressedTexImageARB; + +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDARBPROC __glewLoadTransposeMatrixdARB; +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFARBPROC __glewLoadTransposeMatrixfARB; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDARBPROC __glewMultTransposeMatrixdARB; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXFARBPROC __glewMultTransposeMatrixfARB; + +GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYPROC __glewBindVertexArray; +GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSPROC __glewDeleteVertexArrays; +GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSPROC __glewGenVertexArrays; +GLEW_FUN_EXPORT PFNGLISVERTEXARRAYPROC __glewIsVertexArray; + +GLEW_FUN_EXPORT PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB; +GLEW_FUN_EXPORT PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB; +GLEW_FUN_EXPORT PFNGLWEIGHTBVARBPROC __glewWeightbvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTDVARBPROC __glewWeightdvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTFVARBPROC __glewWeightfvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTIVARBPROC __glewWeightivARB; +GLEW_FUN_EXPORT PFNGLWEIGHTSVARBPROC __glewWeightsvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTUBVARBPROC __glewWeightubvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTUIVARBPROC __glewWeightuivARB; +GLEW_FUN_EXPORT PFNGLWEIGHTUSVARBPROC __glewWeightusvARB; + +GLEW_FUN_EXPORT PFNGLBINDBUFFERARBPROC __glewBindBufferARB; +GLEW_FUN_EXPORT PFNGLBUFFERDATAARBPROC __glewBufferDataARB; +GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAARBPROC __glewBufferSubDataARB; +GLEW_FUN_EXPORT PFNGLDELETEBUFFERSARBPROC __glewDeleteBuffersARB; +GLEW_FUN_EXPORT PFNGLGENBUFFERSARBPROC __glewGenBuffersARB; +GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVARBPROC __glewGetBufferParameterivARB; +GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVARBPROC __glewGetBufferPointervARB; +GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAARBPROC __glewGetBufferSubDataARB; +GLEW_FUN_EXPORT PFNGLISBUFFERARBPROC __glewIsBufferARB; +GLEW_FUN_EXPORT PFNGLMAPBUFFERARBPROC __glewMapBufferARB; +GLEW_FUN_EXPORT PFNGLUNMAPBUFFERARBPROC __glewUnmapBufferARB; + +GLEW_FUN_EXPORT PFNGLBINDPROGRAMARBPROC __glewBindProgramARB; +GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSARBPROC __glewDeleteProgramsARB; +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYARBPROC __glewDisableVertexAttribArrayARB; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYARBPROC __glewEnableVertexAttribArrayARB; +GLEW_FUN_EXPORT PFNGLGENPROGRAMSARBPROC __glewGenProgramsARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERDVARBPROC __glewGetProgramEnvParameterdvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERFVARBPROC __glewGetProgramEnvParameterfvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC __glewGetProgramLocalParameterdvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC __glewGetProgramLocalParameterfvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGARBPROC __glewGetProgramStringARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMIVARBPROC __glewGetProgramivARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVARBPROC __glewGetVertexAttribPointervARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVARBPROC __glewGetVertexAttribdvARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVARBPROC __glewGetVertexAttribfvARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVARBPROC __glewGetVertexAttribivARB; +GLEW_FUN_EXPORT PFNGLISPROGRAMARBPROC __glewIsProgramARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DARBPROC __glewProgramEnvParameter4dARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DVARBPROC __glewProgramEnvParameter4dvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FARBPROC __glewProgramEnvParameter4fARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FVARBPROC __glewProgramEnvParameter4fvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DARBPROC __glewProgramLocalParameter4dARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DVARBPROC __glewProgramLocalParameter4dvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FARBPROC __glewProgramLocalParameter4fARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FVARBPROC __glewProgramLocalParameter4fvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMSTRINGARBPROC __glewProgramStringARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DARBPROC __glewVertexAttrib1dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVARBPROC __glewVertexAttrib1dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FARBPROC __glewVertexAttrib1fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVARBPROC __glewVertexAttrib1fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SARBPROC __glewVertexAttrib1sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVARBPROC __glewVertexAttrib1svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DARBPROC __glewVertexAttrib2dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVARBPROC __glewVertexAttrib2dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FARBPROC __glewVertexAttrib2fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVARBPROC __glewVertexAttrib2fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SARBPROC __glewVertexAttrib2sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVARBPROC __glewVertexAttrib2svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DARBPROC __glewVertexAttrib3dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVARBPROC __glewVertexAttrib3dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FARBPROC __glewVertexAttrib3fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVARBPROC __glewVertexAttrib3fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SARBPROC __glewVertexAttrib3sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVARBPROC __glewVertexAttrib3svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NBVARBPROC __glewVertexAttrib4NbvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NIVARBPROC __glewVertexAttrib4NivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NSVARBPROC __glewVertexAttrib4NsvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBARBPROC __glewVertexAttrib4NubARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBVARBPROC __glewVertexAttrib4NubvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUIVARBPROC __glewVertexAttrib4NuivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUSVARBPROC __glewVertexAttrib4NusvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4BVARBPROC __glewVertexAttrib4bvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DARBPROC __glewVertexAttrib4dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVARBPROC __glewVertexAttrib4dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FARBPROC __glewVertexAttrib4fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVARBPROC __glewVertexAttrib4fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4IVARBPROC __glewVertexAttrib4ivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SARBPROC __glewVertexAttrib4sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVARBPROC __glewVertexAttrib4svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVARBPROC __glewVertexAttrib4ubvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UIVARBPROC __glewVertexAttrib4uivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4USVARBPROC __glewVertexAttrib4usvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERARBPROC __glewVertexAttribPointerARB; + +GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONARBPROC __glewBindAttribLocationARB; +GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBARBPROC __glewGetActiveAttribARB; +GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONARBPROC __glewGetAttribLocationARB; + +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DARBPROC __glewWindowPos2dARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVARBPROC __glewWindowPos2dvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FARBPROC __glewWindowPos2fARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVARBPROC __glewWindowPos2fvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IARBPROC __glewWindowPos2iARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVARBPROC __glewWindowPos2ivARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SARBPROC __glewWindowPos2sARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVARBPROC __glewWindowPos2svARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DARBPROC __glewWindowPos3dARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVARBPROC __glewWindowPos3dvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FARBPROC __glewWindowPos3fARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVARBPROC __glewWindowPos3fvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IARBPROC __glewWindowPos3iARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVARBPROC __glewWindowPos3ivARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SARBPROC __glewWindowPos3sARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVARBPROC __glewWindowPos3svARB; + +GLEW_FUN_EXPORT PFNGLDRAWBUFFERSATIPROC __glewDrawBuffersATI; + +GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYATIPROC __glewDrawElementArrayATI; +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYATIPROC __glewDrawRangeElementArrayATI; +GLEW_FUN_EXPORT PFNGLELEMENTPOINTERATIPROC __glewElementPointerATI; + +GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERFVATIPROC __glewGetTexBumpParameterfvATI; +GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERIVATIPROC __glewGetTexBumpParameterivATI; +GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERFVATIPROC __glewTexBumpParameterfvATI; +GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERIVATIPROC __glewTexBumpParameterivATI; + +GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP1ATIPROC __glewAlphaFragmentOp1ATI; +GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP2ATIPROC __glewAlphaFragmentOp2ATI; +GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP3ATIPROC __glewAlphaFragmentOp3ATI; +GLEW_FUN_EXPORT PFNGLBEGINFRAGMENTSHADERATIPROC __glewBeginFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLBINDFRAGMENTSHADERATIPROC __glewBindFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP1ATIPROC __glewColorFragmentOp1ATI; +GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP2ATIPROC __glewColorFragmentOp2ATI; +GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP3ATIPROC __glewColorFragmentOp3ATI; +GLEW_FUN_EXPORT PFNGLDELETEFRAGMENTSHADERATIPROC __glewDeleteFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLENDFRAGMENTSHADERATIPROC __glewEndFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLGENFRAGMENTSHADERSATIPROC __glewGenFragmentShadersATI; +GLEW_FUN_EXPORT PFNGLPASSTEXCOORDATIPROC __glewPassTexCoordATI; +GLEW_FUN_EXPORT PFNGLSAMPLEMAPATIPROC __glewSampleMapATI; +GLEW_FUN_EXPORT PFNGLSETFRAGMENTSHADERCONSTANTATIPROC __glewSetFragmentShaderConstantATI; + +GLEW_FUN_EXPORT PFNGLMAPOBJECTBUFFERATIPROC __glewMapObjectBufferATI; +GLEW_FUN_EXPORT PFNGLUNMAPOBJECTBUFFERATIPROC __glewUnmapObjectBufferATI; + +GLEW_FUN_EXPORT PFNGLPNTRIANGLESFATIPROC __glPNTrianglewesfATI; +GLEW_FUN_EXPORT PFNGLPNTRIANGLESIATIPROC __glPNTrianglewesiATI; + +GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEATIPROC __glewStencilFuncSeparateATI; +GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEATIPROC __glewStencilOpSeparateATI; + +GLEW_FUN_EXPORT PFNGLARRAYOBJECTATIPROC __glewArrayObjectATI; +GLEW_FUN_EXPORT PFNGLFREEOBJECTBUFFERATIPROC __glewFreeObjectBufferATI; +GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTFVATIPROC __glewGetArrayObjectfvATI; +GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTIVATIPROC __glewGetArrayObjectivATI; +GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERFVATIPROC __glewGetObjectBufferfvATI; +GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERIVATIPROC __glewGetObjectBufferivATI; +GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTFVATIPROC __glewGetVariantArrayObjectfvATI; +GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTIVATIPROC __glewGetVariantArrayObjectivATI; +GLEW_FUN_EXPORT PFNGLISOBJECTBUFFERATIPROC __glewIsObjectBufferATI; +GLEW_FUN_EXPORT PFNGLNEWOBJECTBUFFERATIPROC __glewNewObjectBufferATI; +GLEW_FUN_EXPORT PFNGLUPDATEOBJECTBUFFERATIPROC __glewUpdateObjectBufferATI; +GLEW_FUN_EXPORT PFNGLVARIANTARRAYOBJECTATIPROC __glewVariantArrayObjectATI; + +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC __glewGetVertexAttribArrayObjectfvATI; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC __glewGetVertexAttribArrayObjectivATI; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBARRAYOBJECTATIPROC __glewVertexAttribArrayObjectATI; + +GLEW_FUN_EXPORT PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC __glewClientActiveVertexStreamATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BATIPROC __glewNormalStream3bATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BVATIPROC __glewNormalStream3bvATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DATIPROC __glewNormalStream3dATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DVATIPROC __glewNormalStream3dvATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FATIPROC __glewNormalStream3fATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FVATIPROC __glewNormalStream3fvATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IATIPROC __glewNormalStream3iATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IVATIPROC __glewNormalStream3ivATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI; +GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI; +GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FVATIPROC __glewVertexStream2fvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IATIPROC __glewVertexStream2iATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IVATIPROC __glewVertexStream2ivATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SATIPROC __glewVertexStream2sATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SVATIPROC __glewVertexStream2svATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DATIPROC __glewVertexStream3dATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DVATIPROC __glewVertexStream3dvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FATIPROC __glewVertexStream3fATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FVATIPROC __glewVertexStream3fvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IATIPROC __glewVertexStream3iATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IVATIPROC __glewVertexStream3ivATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SATIPROC __glewVertexStream3sATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SVATIPROC __glewVertexStream3svATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DATIPROC __glewVertexStream4dATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DVATIPROC __glewVertexStream4dvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FATIPROC __glewVertexStream4fATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FVATIPROC __glewVertexStream4fvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IATIPROC __glewVertexStream4iATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IVATIPROC __glewVertexStream4ivATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SATIPROC __glewVertexStream4sATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SVATIPROC __glewVertexStream4svATI; + +GLEW_FUN_EXPORT PFNGLGETUNIFORMBUFFERSIZEEXTPROC __glewGetUniformBufferSizeEXT; +GLEW_FUN_EXPORT PFNGLGETUNIFORMOFFSETEXTPROC __glewGetUniformOffsetEXT; +GLEW_FUN_EXPORT PFNGLUNIFORMBUFFEREXTPROC __glewUniformBufferEXT; + +GLEW_FUN_EXPORT PFNGLBLENDCOLOREXTPROC __glewBlendColorEXT; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEEXTPROC __glewBlendEquationSeparateEXT; + +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEEXTPROC __glewBlendFuncSeparateEXT; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONEXTPROC __glewBlendEquationEXT; + +GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEEXTPROC __glewColorSubTableEXT; +GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEEXTPROC __glewCopyColorSubTableEXT; + +GLEW_FUN_EXPORT PFNGLLOCKARRAYSEXTPROC __glewLockArraysEXT; +GLEW_FUN_EXPORT PFNGLUNLOCKARRAYSEXTPROC __glewUnlockArraysEXT; + +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DEXTPROC __glewConvolutionFilter1DEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DEXTPROC __glewConvolutionFilter2DEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFEXTPROC __glewConvolutionParameterfEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVEXTPROC __glewConvolutionParameterfvEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIEXTPROC __glewConvolutionParameteriEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVEXTPROC __glewConvolutionParameterivEXT; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC __glewCopyConvolutionFilter1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC __glewCopyConvolutionFilter2DEXT; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTEREXTPROC __glewGetConvolutionFilterEXT; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC __glewGetConvolutionParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC __glewGetConvolutionParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTEREXTPROC __glewGetSeparableFilterEXT; +GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DEXTPROC __glewSeparableFilter2DEXT; + +GLEW_FUN_EXPORT PFNGLBINORMALPOINTEREXTPROC __glewBinormalPointerEXT; +GLEW_FUN_EXPORT PFNGLTANGENTPOINTEREXTPROC __glewTangentPointerEXT; + +GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE1DEXTPROC __glewCopyTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE2DEXTPROC __glewCopyTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE1DEXTPROC __glewCopyTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE2DEXTPROC __glewCopyTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT; + +GLEW_FUN_EXPORT PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT; +GLEW_FUN_EXPORT PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT; + +GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT; + +GLEW_FUN_EXPORT PFNGLBINDMULTITEXTUREEXTPROC __glewBindMultiTextureEXT; +GLEW_FUN_EXPORT PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC __glewCheckNamedFramebufferStatusEXT; +GLEW_FUN_EXPORT PFNGLCLIENTATTRIBDEFAULTEXTPROC __glewClientAttribDefaultEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC __glewCompressedMultiTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC __glewCompressedMultiTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC __glewCompressedMultiTexImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC __glewCompressedMultiTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC __glewCompressedMultiTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC __glewCompressedMultiTexSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC __glewCompressedTextureImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC __glewCompressedTextureImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC __glewCompressedTextureImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC __glewCompressedTextureSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC __glewCompressedTextureSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC __glewCompressedTextureSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXIMAGE1DEXTPROC __glewCopyMultiTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXIMAGE2DEXTPROC __glewCopyMultiTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC __glewCopyMultiTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC __glewCopyMultiTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC __glewCopyMultiTexSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTUREIMAGE1DEXTPROC __glewCopyTextureImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTUREIMAGE2DEXTPROC __glewCopyTextureImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC __glewCopyTextureSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC __glewCopyTextureSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC __glewCopyTextureSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC __glewDisableClientStateIndexedEXT; +GLEW_FUN_EXPORT PFNGLENABLECLIENTSTATEINDEXEDEXTPROC __glewEnableClientStateIndexedEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC __glewFramebufferDrawBufferEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC __glewFramebufferDrawBuffersEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERREADBUFFEREXTPROC __glewFramebufferReadBufferEXT; +GLEW_FUN_EXPORT PFNGLGENERATEMULTITEXMIPMAPEXTPROC __glewGenerateMultiTexMipmapEXT; +GLEW_FUN_EXPORT PFNGLGENERATETEXTUREMIPMAPEXTPROC __glewGenerateTextureMipmapEXT; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC __glewGetCompressedMultiTexImageEXT; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC __glewGetCompressedTextureImageEXT; +GLEW_FUN_EXPORT PFNGLGETDOUBLEINDEXEDVEXTPROC __glewGetDoubleIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETFLOATINDEXEDVEXTPROC __glewGetFloatIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC __glewGetFramebufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXENVFVEXTPROC __glewGetMultiTexEnvfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXENVIVEXTPROC __glewGetMultiTexEnvivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXGENDVEXTPROC __glewGetMultiTexGendvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXGENFVEXTPROC __glewGetMultiTexGenfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXGENIVEXTPROC __glewGetMultiTexGenivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXIMAGEEXTPROC __glewGetMultiTexImageEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC __glewGetMultiTexLevelParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC __glewGetMultiTexLevelParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIIVEXTPROC __glewGetMultiTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIUIVEXTPROC __glewGetMultiTexParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERFVEXTPROC __glewGetMultiTexParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIVEXTPROC __glewGetMultiTexParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC __glewGetNamedBufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPOINTERVEXTPROC __glewGetNamedBufferPointervEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERSUBDATAEXTPROC __glewGetNamedBufferSubDataEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetNamedFramebufferAttachmentParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC __glewGetNamedProgramLocalParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC __glewGetNamedProgramLocalParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC __glewGetNamedProgramLocalParameterdvEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC __glewGetNamedProgramLocalParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMSTRINGEXTPROC __glewGetNamedProgramStringEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMIVEXTPROC __glewGetNamedProgramivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC __glewGetNamedRenderbufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETPOINTERINDEXEDVEXTPROC __glewGetPointerIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREIMAGEEXTPROC __glewGetTextureImageEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC __glewGetTextureLevelParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC __glewGetTextureLevelParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIIVEXTPROC __glewGetTextureParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIUIVEXTPROC __glewGetTextureParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERFVEXTPROC __glewGetTextureParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIVEXTPROC __glewGetTextureParameterivEXT; +GLEW_FUN_EXPORT PFNGLMAPNAMEDBUFFEREXTPROC __glewMapNamedBufferEXT; +GLEW_FUN_EXPORT PFNGLMATRIXFRUSTUMEXTPROC __glewMatrixFrustumEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADIDENTITYEXTPROC __glewMatrixLoadIdentityEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADTRANSPOSEDEXTPROC __glewMatrixLoadTransposedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADTRANSPOSEFEXTPROC __glewMatrixLoadTransposefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADDEXTPROC __glewMatrixLoaddEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADFEXTPROC __glewMatrixLoadfEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTTRANSPOSEDEXTPROC __glewMatrixMultTransposedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTTRANSPOSEFEXTPROC __glewMatrixMultTransposefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTDEXTPROC __glewMatrixMultdEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTFEXTPROC __glewMatrixMultfEXT; +GLEW_FUN_EXPORT PFNGLMATRIXORTHOEXTPROC __glewMatrixOrthoEXT; +GLEW_FUN_EXPORT PFNGLMATRIXPOPEXTPROC __glewMatrixPopEXT; +GLEW_FUN_EXPORT PFNGLMATRIXPUSHEXTPROC __glewMatrixPushEXT; +GLEW_FUN_EXPORT PFNGLMATRIXROTATEDEXTPROC __glewMatrixRotatedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXROTATEFEXTPROC __glewMatrixRotatefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXSCALEDEXTPROC __glewMatrixScaledEXT; +GLEW_FUN_EXPORT PFNGLMATRIXSCALEFEXTPROC __glewMatrixScalefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXTRANSLATEDEXTPROC __glewMatrixTranslatedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXTRANSLATEFEXTPROC __glewMatrixTranslatefEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXBUFFEREXTPROC __glewMultiTexBufferEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDPOINTEREXTPROC __glewMultiTexCoordPointerEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVFEXTPROC __glewMultiTexEnvfEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVFVEXTPROC __glewMultiTexEnvfvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVIEXTPROC __glewMultiTexEnviEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVIVEXTPROC __glewMultiTexEnvivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENDEXTPROC __glewMultiTexGendEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENDVEXTPROC __glewMultiTexGendvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENFEXTPROC __glewMultiTexGenfEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENFVEXTPROC __glewMultiTexGenfvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENIEXTPROC __glewMultiTexGeniEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENIVEXTPROC __glewMultiTexGenivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE1DEXTPROC __glewMultiTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE2DEXTPROC __glewMultiTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE3DEXTPROC __glewMultiTexImage3DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIIVEXTPROC __glewMultiTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIUIVEXTPROC __glewMultiTexParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERFEXTPROC __glewMultiTexParameterfEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERFVEXTPROC __glewMultiTexParameterfvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIEXTPROC __glewMultiTexParameteriEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIVEXTPROC __glewMultiTexParameterivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXRENDERBUFFEREXTPROC __glewMultiTexRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE1DEXTPROC __glewMultiTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE2DEXTPROC __glewMultiTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE3DEXTPROC __glewMultiTexSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDBUFFERDATAEXTPROC __glewNamedBufferDataEXT; +GLEW_FUN_EXPORT PFNGLNAMEDBUFFERSUBDATAEXTPROC __glewNamedBufferSubDataEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC __glewNamedFramebufferRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC __glewNamedFramebufferTexture1DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC __glewNamedFramebufferTexture2DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC __glewNamedFramebufferTexture3DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC __glewNamedFramebufferTextureEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC __glewNamedFramebufferTextureFaceEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC __glewNamedFramebufferTextureLayerEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC __glewNamedProgramLocalParameter4dEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC __glewNamedProgramLocalParameter4dvEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC __glewNamedProgramLocalParameter4fEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC __glewNamedProgramLocalParameter4fvEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC __glewNamedProgramLocalParameterI4iEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC __glewNamedProgramLocalParameterI4ivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC __glewNamedProgramLocalParameterI4uiEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC __glewNamedProgramLocalParameterI4uivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC __glewNamedProgramLocalParameters4fvEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC __glewNamedProgramLocalParametersI4ivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC __glewNamedProgramLocalParametersI4uivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMSTRINGEXTPROC __glewNamedProgramStringEXT; +GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC __glewNamedRenderbufferStorageEXT; +GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC __glewNamedRenderbufferStorageMultisampleCoverageEXT; +GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewNamedRenderbufferStorageMultisampleEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FEXTPROC __glewProgramUniform1fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FVEXTPROC __glewProgramUniform1fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IEXTPROC __glewProgramUniform1iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IVEXTPROC __glewProgramUniform1ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIEXTPROC __glewProgramUniform1uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIVEXTPROC __glewProgramUniform1uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FEXTPROC __glewProgramUniform2fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FVEXTPROC __glewProgramUniform2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IEXTPROC __glewProgramUniform2iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IVEXTPROC __glewProgramUniform2ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIEXTPROC __glewProgramUniform2uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIVEXTPROC __glewProgramUniform2uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FEXTPROC __glewProgramUniform3fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FVEXTPROC __glewProgramUniform3fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IEXTPROC __glewProgramUniform3iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IVEXTPROC __glewProgramUniform3ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIEXTPROC __glewProgramUniform3uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIVEXTPROC __glewProgramUniform3uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FEXTPROC __glewProgramUniform4fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FVEXTPROC __glewProgramUniform4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IEXTPROC __glewProgramUniform4iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IVEXTPROC __glewProgramUniform4ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIEXTPROC __glewProgramUniform4uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIVEXTPROC __glewProgramUniform4uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC __glewProgramUniformMatrix2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC __glewProgramUniformMatrix2x3fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC __glewProgramUniformMatrix2x4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC __glewProgramUniformMatrix3fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC __glewProgramUniformMatrix3x2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC __glewProgramUniformMatrix3x4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC __glewProgramUniformMatrix4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC __glewProgramUniformMatrix4x2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC __glewProgramUniformMatrix4x3fvEXT; +GLEW_FUN_EXPORT PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC __glewPushClientAttribDefaultEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREBUFFEREXTPROC __glewTextureBufferEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE1DEXTPROC __glewTextureImage1DEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DEXTPROC __glewTextureImage2DEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DEXTPROC __glewTextureImage3DEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIIVEXTPROC __glewTextureParameterIivEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIUIVEXTPROC __glewTextureParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERFEXTPROC __glewTextureParameterfEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERFVEXTPROC __glewTextureParameterfvEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIEXTPROC __glewTextureParameteriEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIVEXTPROC __glewTextureParameterivEXT; +GLEW_FUN_EXPORT PFNGLTEXTURERENDERBUFFEREXTPROC __glewTextureRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE1DEXTPROC __glewTextureSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE2DEXTPROC __glewTextureSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE3DEXTPROC __glewTextureSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLUNMAPNAMEDBUFFEREXTPROC __glewUnmapNamedBufferEXT; + +GLEW_FUN_EXPORT PFNGLCOLORMASKINDEXEDEXTPROC __glewColorMaskIndexedEXT; +GLEW_FUN_EXPORT PFNGLDISABLEINDEXEDEXTPROC __glewDisableIndexedEXT; +GLEW_FUN_EXPORT PFNGLENABLEINDEXEDEXTPROC __glewEnableIndexedEXT; +GLEW_FUN_EXPORT PFNGLGETBOOLEANINDEXEDVEXTPROC __glewGetBooleanIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETINTEGERINDEXEDVEXTPROC __glewGetIntegerIndexedvEXT; +GLEW_FUN_EXPORT PFNGLISENABLEDINDEXEDEXTPROC __glewIsEnabledIndexedEXT; + +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDEXTPROC __glewDrawArraysInstancedEXT; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDEXTPROC __glewDrawElementsInstancedEXT; + +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSEXTPROC __glewDrawRangeElementsEXT; + +GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTEREXTPROC __glewFogCoordPointerEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDDEXTPROC __glewFogCoorddEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDDVEXTPROC __glewFogCoorddvEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDFEXTPROC __glewFogCoordfEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDFVEXTPROC __glewFogCoordfvEXT; + +GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALEXTPROC __glewFragmentColorMaterialEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFEXTPROC __glewFragmentLightModelfEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVEXTPROC __glewFragmentLightModelfvEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIEXTPROC __glewFragmentLightModeliEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVEXTPROC __glewFragmentLightModelivEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFEXTPROC __glewFragmentLightfEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVEXTPROC __glewFragmentLightfvEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIEXTPROC __glewFragmentLightiEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVEXTPROC __glewFragmentLightivEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFEXTPROC __glewFragmentMaterialfEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVEXTPROC __glewFragmentMaterialfvEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIEXTPROC __glewFragmentMaterialiEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVEXTPROC __glewFragmentMaterialivEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVEXTPROC __glewGetFragmentLightfvEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVEXTPROC __glewGetFragmentLightivEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVEXTPROC __glewGetFragmentMaterialfvEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVEXTPROC __glewGetFragmentMaterialivEXT; +GLEW_FUN_EXPORT PFNGLLIGHTENVIEXTPROC __glewLightEnviEXT; + +GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFEREXTPROC __glewBlitFramebufferEXT; + +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewRenderbufferStorageMultisampleEXT; + +GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFEREXTPROC __glewBindFramebufferEXT; +GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFEREXTPROC __glewBindRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC __glewCheckFramebufferStatusEXT; +GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSEXTPROC __glewDeleteFramebuffersEXT; +GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSEXTPROC __glewDeleteRenderbuffersEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC __glewFramebufferRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE1DEXTPROC __glewFramebufferTexture1DEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DEXTPROC __glewFramebufferTexture2DEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DEXTPROC __glewFramebufferTexture3DEXT; +GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSEXTPROC __glewGenFramebuffersEXT; +GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSEXTPROC __glewGenRenderbuffersEXT; +GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPEXTPROC __glewGenerateMipmapEXT; +GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetFramebufferAttachmentParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC __glewGetRenderbufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLISFRAMEBUFFEREXTPROC __glewIsFramebufferEXT; +GLEW_FUN_EXPORT PFNGLISRENDERBUFFEREXTPROC __glewIsRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEEXTPROC __glewRenderbufferStorageEXT; + +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREEXTPROC __glewFramebufferTextureEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC __glewFramebufferTextureFaceEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC __glewFramebufferTextureLayerEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIEXTPROC __glewProgramParameteriEXT; + +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERS4FVEXTPROC __glewProgramEnvParameters4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC __glewProgramLocalParameters4fvEXT; + +GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONEXTPROC __glewBindFragDataLocationEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGDATALOCATIONEXTPROC __glewGetFragDataLocationEXT; +GLEW_FUN_EXPORT PFNGLGETUNIFORMUIVEXTPROC __glewGetUniformuivEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIIVEXTPROC __glewGetVertexAttribIivEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIUIVEXTPROC __glewGetVertexAttribIuivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIEXTPROC __glewUniform1uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIVEXTPROC __glewUniform1uivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIEXTPROC __glewUniform2uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIVEXTPROC __glewUniform2uivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIEXTPROC __glewUniform3uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIVEXTPROC __glewUniform3uivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIEXTPROC __glewUniform4uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIVEXTPROC __glewUniform4uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IEXTPROC __glewVertexAttribI1iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IVEXTPROC __glewVertexAttribI1ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIEXTPROC __glewVertexAttribI1uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIVEXTPROC __glewVertexAttribI1uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IEXTPROC __glewVertexAttribI2iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IVEXTPROC __glewVertexAttribI2ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIEXTPROC __glewVertexAttribI2uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIVEXTPROC __glewVertexAttribI2uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IEXTPROC __glewVertexAttribI3iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IVEXTPROC __glewVertexAttribI3ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIEXTPROC __glewVertexAttribI3uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIVEXTPROC __glewVertexAttribI3uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4BVEXTPROC __glewVertexAttribI4bvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IEXTPROC __glewVertexAttribI4iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IVEXTPROC __glewVertexAttribI4ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4SVEXTPROC __glewVertexAttribI4svEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UBVEXTPROC __glewVertexAttribI4ubvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIEXTPROC __glewVertexAttribI4uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIVEXTPROC __glewVertexAttribI4uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4USVEXTPROC __glewVertexAttribI4usvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIPOINTEREXTPROC __glewVertexAttribIPointerEXT; + +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMEXTPROC __glewGetHistogramEXT; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVEXTPROC __glewGetHistogramParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVEXTPROC __glewGetHistogramParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETMINMAXEXTPROC __glewGetMinmaxEXT; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVEXTPROC __glewGetMinmaxParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVEXTPROC __glewGetMinmaxParameterivEXT; +GLEW_FUN_EXPORT PFNGLHISTOGRAMEXTPROC __glewHistogramEXT; +GLEW_FUN_EXPORT PFNGLMINMAXEXTPROC __glewMinmaxEXT; +GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMEXTPROC __glewResetHistogramEXT; +GLEW_FUN_EXPORT PFNGLRESETMINMAXEXTPROC __glewResetMinmaxEXT; + +GLEW_FUN_EXPORT PFNGLINDEXFUNCEXTPROC __glewIndexFuncEXT; + +GLEW_FUN_EXPORT PFNGLINDEXMATERIALEXTPROC __glewIndexMaterialEXT; + +GLEW_FUN_EXPORT PFNGLAPPLYTEXTUREEXTPROC __glewApplyTextureEXT; +GLEW_FUN_EXPORT PFNGLTEXTURELIGHTEXTPROC __glewTextureLightEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREMATERIALEXTPROC __glewTextureMaterialEXT; + +GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSEXTPROC __glewMultiDrawArraysEXT; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSEXTPROC __glewMultiDrawElementsEXT; + +GLEW_FUN_EXPORT PFNGLSAMPLEMASKEXTPROC __glewSampleMaskEXT; +GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNEXTPROC __glewSamplePatternEXT; + +GLEW_FUN_EXPORT PFNGLCOLORTABLEEXTPROC __glewColorTableEXT; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEEXTPROC __glewGetColorTableEXT; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVEXTPROC __glewGetColorTableParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVEXTPROC __glewGetColorTableParameterivEXT; + +GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC __glewGetPixelTransformParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC __glewGetPixelTransformParameterivEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFEXTPROC __glewPixelTransformParameterfEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC __glewPixelTransformParameterfvEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIEXTPROC __glewPixelTransformParameteriEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC __glewPixelTransformParameterivEXT; + +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFEXTPROC __glewPointParameterfEXT; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVEXTPROC __glewPointParameterfvEXT; + +GLEW_FUN_EXPORT PFNGLPOLYGONOFFSETEXTPROC __glewPolygonOffsetEXT; + +GLEW_FUN_EXPORT PFNGLBEGINSCENEEXTPROC __glewBeginSceneEXT; +GLEW_FUN_EXPORT PFNGLENDSCENEEXTPROC __glewEndSceneEXT; + +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BEXTPROC __glewSecondaryColor3bEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVEXTPROC __glewSecondaryColor3bvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DEXTPROC __glewSecondaryColor3dEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVEXTPROC __glewSecondaryColor3dvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FEXTPROC __glewSecondaryColor3fEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVEXTPROC __glewSecondaryColor3fvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IEXTPROC __glewSecondaryColor3iEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVEXTPROC __glewSecondaryColor3ivEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SEXTPROC __glewSecondaryColor3sEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVEXTPROC __glewSecondaryColor3svEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBEXTPROC __glewSecondaryColor3ubEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVEXTPROC __glewSecondaryColor3ubvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIEXTPROC __glewSecondaryColor3uiEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVEXTPROC __glewSecondaryColor3uivEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USEXTPROC __glewSecondaryColor3usEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVEXTPROC __glewSecondaryColor3usvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTEREXTPROC __glewSecondaryColorPointerEXT; + +GLEW_FUN_EXPORT PFNGLACTIVESTENCILFACEEXTPROC __glewActiveStencilFaceEXT; + +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE1DEXTPROC __glewTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE2DEXTPROC __glewTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DEXTPROC __glewTexSubImage3DEXT; + +GLEW_FUN_EXPORT PFNGLTEXIMAGE3DEXTPROC __glewTexImage3DEXT; + +GLEW_FUN_EXPORT PFNGLTEXBUFFEREXTPROC __glewTexBufferEXT; + +GLEW_FUN_EXPORT PFNGLCLEARCOLORIIEXTPROC __glewClearColorIiEXT; +GLEW_FUN_EXPORT PFNGLCLEARCOLORIUIEXTPROC __glewClearColorIuiEXT; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIIVEXTPROC __glewGetTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIUIVEXTPROC __glewGetTexParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIIVEXTPROC __glewTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIUIVEXTPROC __glewTexParameterIuivEXT; + +GLEW_FUN_EXPORT PFNGLARETEXTURESRESIDENTEXTPROC __glewAreTexturesResidentEXT; +GLEW_FUN_EXPORT PFNGLBINDTEXTUREEXTPROC __glewBindTextureEXT; +GLEW_FUN_EXPORT PFNGLDELETETEXTURESEXTPROC __glewDeleteTexturesEXT; +GLEW_FUN_EXPORT PFNGLGENTEXTURESEXTPROC __glewGenTexturesEXT; +GLEW_FUN_EXPORT PFNGLISTEXTUREEXTPROC __glewIsTextureEXT; +GLEW_FUN_EXPORT PFNGLPRIORITIZETEXTURESEXTPROC __glewPrioritizeTexturesEXT; + +GLEW_FUN_EXPORT PFNGLTEXTURENORMALEXTPROC __glewTextureNormalEXT; + +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VEXTPROC __glewGetQueryObjecti64vEXT; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VEXTPROC __glewGetQueryObjectui64vEXT; + +GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKEXTPROC __glewBeginTransformFeedbackEXT; +GLEW_FUN_EXPORT PFNGLBINDBUFFERBASEEXTPROC __glewBindBufferBaseEXT; +GLEW_FUN_EXPORT PFNGLBINDBUFFEROFFSETEXTPROC __glewBindBufferOffsetEXT; +GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGEEXTPROC __glewBindBufferRangeEXT; +GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKEXTPROC __glewEndTransformFeedbackEXT; +GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC __glewGetTransformFeedbackVaryingEXT; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC __glewTransformFeedbackVaryingsEXT; + +GLEW_FUN_EXPORT PFNGLARRAYELEMENTEXTPROC __glewArrayElementEXT; +GLEW_FUN_EXPORT PFNGLCOLORPOINTEREXTPROC __glewColorPointerEXT; +GLEW_FUN_EXPORT PFNGLDRAWARRAYSEXTPROC __glewDrawArraysEXT; +GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTEREXTPROC __glewEdgeFlagPointerEXT; +GLEW_FUN_EXPORT PFNGLGETPOINTERVEXTPROC __glewGetPointervEXT; +GLEW_FUN_EXPORT PFNGLINDEXPOINTEREXTPROC __glewIndexPointerEXT; +GLEW_FUN_EXPORT PFNGLNORMALPOINTEREXTPROC __glewNormalPointerEXT; +GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTEREXTPROC __glewTexCoordPointerEXT; +GLEW_FUN_EXPORT PFNGLVERTEXPOINTEREXTPROC __glewVertexPointerEXT; + +GLEW_FUN_EXPORT PFNGLBEGINVERTEXSHADEREXTPROC __glewBeginVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLBINDLIGHTPARAMETEREXTPROC __glewBindLightParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDMATERIALPARAMETEREXTPROC __glewBindMaterialParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDPARAMETEREXTPROC __glewBindParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDTEXGENPARAMETEREXTPROC __glewBindTexGenParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDTEXTUREUNITPARAMETEREXTPROC __glewBindTextureUnitParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDVERTEXSHADEREXTPROC __glewBindVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLDELETEVERTEXSHADEREXTPROC __glewDeleteVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC __glewDisableVariantClientStateEXT; +GLEW_FUN_EXPORT PFNGLENABLEVARIANTCLIENTSTATEEXTPROC __glewEnableVariantClientStateEXT; +GLEW_FUN_EXPORT PFNGLENDVERTEXSHADEREXTPROC __glewEndVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLEXTRACTCOMPONENTEXTPROC __glewExtractComponentEXT; +GLEW_FUN_EXPORT PFNGLGENSYMBOLSEXTPROC __glewGenSymbolsEXT; +GLEW_FUN_EXPORT PFNGLGENVERTEXSHADERSEXTPROC __glewGenVertexShadersEXT; +GLEW_FUN_EXPORT PFNGLGETINVARIANTBOOLEANVEXTPROC __glewGetInvariantBooleanvEXT; +GLEW_FUN_EXPORT PFNGLGETINVARIANTFLOATVEXTPROC __glewGetInvariantFloatvEXT; +GLEW_FUN_EXPORT PFNGLGETINVARIANTINTEGERVEXTPROC __glewGetInvariantIntegervEXT; +GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC __glewGetLocalConstantBooleanvEXT; +GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTFLOATVEXTPROC __glewGetLocalConstantFloatvEXT; +GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTINTEGERVEXTPROC __glewGetLocalConstantIntegervEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTBOOLEANVEXTPROC __glewGetVariantBooleanvEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTFLOATVEXTPROC __glewGetVariantFloatvEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTINTEGERVEXTPROC __glewGetVariantIntegervEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTPOINTERVEXTPROC __glewGetVariantPointervEXT; +GLEW_FUN_EXPORT PFNGLINSERTCOMPONENTEXTPROC __glewInsertComponentEXT; +GLEW_FUN_EXPORT PFNGLISVARIANTENABLEDEXTPROC __glewIsVariantEnabledEXT; +GLEW_FUN_EXPORT PFNGLSETINVARIANTEXTPROC __glewSetInvariantEXT; +GLEW_FUN_EXPORT PFNGLSETLOCALCONSTANTEXTPROC __glewSetLocalConstantEXT; +GLEW_FUN_EXPORT PFNGLSHADEROP1EXTPROC __glewShaderOp1EXT; +GLEW_FUN_EXPORT PFNGLSHADEROP2EXTPROC __glewShaderOp2EXT; +GLEW_FUN_EXPORT PFNGLSHADEROP3EXTPROC __glewShaderOp3EXT; +GLEW_FUN_EXPORT PFNGLSWIZZLEEXTPROC __glewSwizzleEXT; +GLEW_FUN_EXPORT PFNGLVARIANTPOINTEREXTPROC __glewVariantPointerEXT; +GLEW_FUN_EXPORT PFNGLVARIANTBVEXTPROC __glewVariantbvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTDVEXTPROC __glewVariantdvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTFVEXTPROC __glewVariantfvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTIVEXTPROC __glewVariantivEXT; +GLEW_FUN_EXPORT PFNGLVARIANTSVEXTPROC __glewVariantsvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTUBVEXTPROC __glewVariantubvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTUIVEXTPROC __glewVariantuivEXT; +GLEW_FUN_EXPORT PFNGLVARIANTUSVEXTPROC __glewVariantusvEXT; +GLEW_FUN_EXPORT PFNGLWRITEMASKEXTPROC __glewWriteMaskEXT; + +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTPOINTEREXTPROC __glewVertexWeightPointerEXT; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFEXTPROC __glewVertexWeightfEXT; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFVEXTPROC __glewVertexWeightfvEXT; + +GLEW_FUN_EXPORT PFNGLFRAMETERMINATORGREMEDYPROC __glewFrameTerminatorGREMEDY; + +GLEW_FUN_EXPORT PFNGLSTRINGMARKERGREMEDYPROC __glewStringMarkerGREMEDY; + +GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC __glewGetImageTransformParameterfvHP; +GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC __glewGetImageTransformParameterivHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFHPPROC __glewImageTransformParameterfHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFVHPPROC __glewImageTransformParameterfvHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIHPPROC __glewImageTransformParameteriHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIVHPPROC __glewImageTransformParameterivHP; + +GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWARRAYSIBMPROC __glewMultiModeDrawArraysIBM; +GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWELEMENTSIBMPROC __glewMultiModeDrawElementsIBM; + +GLEW_FUN_EXPORT PFNGLCOLORPOINTERLISTIBMPROC __glewColorPointerListIBM; +GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTERLISTIBMPROC __glewEdgeFlagPointerListIBM; +GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERLISTIBMPROC __glewFogCoordPointerListIBM; +GLEW_FUN_EXPORT PFNGLINDEXPOINTERLISTIBMPROC __glewIndexPointerListIBM; +GLEW_FUN_EXPORT PFNGLNORMALPOINTERLISTIBMPROC __glewNormalPointerListIBM; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointerListIBM; +GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM; +GLEW_FUN_EXPORT PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM; + +GLEW_FUN_EXPORT PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL; +GLEW_FUN_EXPORT PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL; +GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL; +GLEW_FUN_EXPORT PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL; + +GLEW_FUN_EXPORT PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL; +GLEW_FUN_EXPORT PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL; + +GLEW_FUN_EXPORT PFNGLBUFFERREGIONENABLEDEXTPROC __glewBufferRegionEnabledEXT; +GLEW_FUN_EXPORT PFNGLDELETEBUFFERREGIONEXTPROC __glewDeleteBufferRegionEXT; +GLEW_FUN_EXPORT PFNGLDRAWBUFFERREGIONEXTPROC __glewDrawBufferRegionEXT; +GLEW_FUN_EXPORT PFNGLNEWBUFFERREGIONEXTPROC __glewNewBufferRegionEXT; +GLEW_FUN_EXPORT PFNGLREADBUFFERREGIONEXTPROC __glewReadBufferRegionEXT; + +GLEW_FUN_EXPORT PFNGLRESIZEBUFFERSMESAPROC __glewResizeBuffersMESA; + +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DMESAPROC __glewWindowPos2dMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVMESAPROC __glewWindowPos2dvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FMESAPROC __glewWindowPos2fMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVMESAPROC __glewWindowPos2fvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IMESAPROC __glewWindowPos2iMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVMESAPROC __glewWindowPos2ivMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SMESAPROC __glewWindowPos2sMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVMESAPROC __glewWindowPos2svMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DMESAPROC __glewWindowPos3dMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVMESAPROC __glewWindowPos3dvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FMESAPROC __glewWindowPos3fMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVMESAPROC __glewWindowPos3fvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IMESAPROC __glewWindowPos3iMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVMESAPROC __glewWindowPos3ivMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SMESAPROC __glewWindowPos3sMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVMESAPROC __glewWindowPos3svMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4DMESAPROC __glewWindowPos4dMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4DVMESAPROC __glewWindowPos4dvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4FMESAPROC __glewWindowPos4fMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4FVMESAPROC __glewWindowPos4fvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4IMESAPROC __glewWindowPos4iMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA; + +GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERNVPROC __glewBeginConditionalRenderNV; +GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERNVPROC __glewEndConditionalRenderNV; + +GLEW_FUN_EXPORT PFNGLCLEARDEPTHDNVPROC __glewClearDepthdNV; +GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSDNVPROC __glewDepthBoundsdNV; +GLEW_FUN_EXPORT PFNGLDEPTHRANGEDNVPROC __glewDepthRangedNV; + +GLEW_FUN_EXPORT PFNGLEVALMAPSNVPROC __glewEvalMapsNV; +GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV; +GLEW_FUN_EXPORT PFNGLGETMAPCONTROLPOINTSNVPROC __glewGetMapControlPointsNV; +GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERFVNVPROC __glewGetMapParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERIVNVPROC __glewGetMapParameterivNV; +GLEW_FUN_EXPORT PFNGLMAPCONTROLPOINTSNVPROC __glewMapControlPointsNV; +GLEW_FUN_EXPORT PFNGLMAPPARAMETERFVNVPROC __glewMapParameterfvNV; +GLEW_FUN_EXPORT PFNGLMAPPARAMETERIVNVPROC __glewMapParameterivNV; + +GLEW_FUN_EXPORT PFNGLGETMULTISAMPLEFVNVPROC __glewGetMultisamplefvNV; +GLEW_FUN_EXPORT PFNGLSAMPLEMASKINDEXEDNVPROC __glewSampleMaskIndexedNV; +GLEW_FUN_EXPORT PFNGLTEXRENDERBUFFERNVPROC __glewTexRenderbufferNV; + +GLEW_FUN_EXPORT PFNGLDELETEFENCESNVPROC __glewDeleteFencesNV; +GLEW_FUN_EXPORT PFNGLFINISHFENCENVPROC __glewFinishFenceNV; +GLEW_FUN_EXPORT PFNGLGENFENCESNVPROC __glewGenFencesNV; +GLEW_FUN_EXPORT PFNGLGETFENCEIVNVPROC __glewGetFenceivNV; +GLEW_FUN_EXPORT PFNGLISFENCENVPROC __glewIsFenceNV; +GLEW_FUN_EXPORT PFNGLSETFENCENVPROC __glewSetFenceNV; +GLEW_FUN_EXPORT PFNGLTESTFENCENVPROC __glewTestFenceNV; + +GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC __glewGetProgramNamedParameterdvNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC __glewGetProgramNamedParameterfvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DNVPROC __glewProgramNamedParameter4dNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC __glewProgramNamedParameter4dvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FNVPROC __glewProgramNamedParameter4fNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC __glewProgramNamedParameter4fvNV; + +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC __glewRenderbufferStorageMultisampleCoverageNV; + +GLEW_FUN_EXPORT PFNGLPROGRAMVERTEXLIMITNVPROC __glewProgramVertexLimitNV; + +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4INVPROC __glewProgramEnvParameterI4iNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4IVNVPROC __glewProgramEnvParameterI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4UINVPROC __glewProgramEnvParameterI4uiNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4UIVNVPROC __glewProgramEnvParameterI4uivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERSI4IVNVPROC __glewProgramEnvParametersI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC __glewProgramEnvParametersI4uivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4INVPROC __glewProgramLocalParameterI4iNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC __glewProgramLocalParameterI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4UINVPROC __glewProgramLocalParameterI4uiNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC __glewProgramLocalParameterI4uivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC __glewProgramLocalParametersI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC __glewProgramLocalParametersI4uivNV; + +GLEW_FUN_EXPORT PFNGLCOLOR3HNVPROC __glewColor3hNV; +GLEW_FUN_EXPORT PFNGLCOLOR3HVNVPROC __glewColor3hvNV; +GLEW_FUN_EXPORT PFNGLCOLOR4HNVPROC __glewColor4hNV; +GLEW_FUN_EXPORT PFNGLCOLOR4HVNVPROC __glewColor4hvNV; +GLEW_FUN_EXPORT PFNGLFOGCOORDHNVPROC __glewFogCoordhNV; +GLEW_FUN_EXPORT PFNGLFOGCOORDHVNVPROC __glewFogCoordhvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HNVPROC __glewMultiTexCoord1hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HVNVPROC __glewMultiTexCoord1hvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HNVPROC __glewMultiTexCoord2hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HVNVPROC __glewMultiTexCoord2hvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HNVPROC __glewMultiTexCoord3hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HVNVPROC __glewMultiTexCoord3hvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HNVPROC __glewMultiTexCoord4hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HVNVPROC __glewMultiTexCoord4hvNV; +GLEW_FUN_EXPORT PFNGLNORMAL3HNVPROC __glewNormal3hNV; +GLEW_FUN_EXPORT PFNGLNORMAL3HVNVPROC __glewNormal3hvNV; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HNVPROC __glewSecondaryColor3hNV; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HVNVPROC __glewSecondaryColor3hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD1HNVPROC __glewTexCoord1hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD1HVNVPROC __glewTexCoord1hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD2HNVPROC __glewTexCoord2hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD2HVNVPROC __glewTexCoord2hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD3HNVPROC __glewTexCoord3hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD3HVNVPROC __glewTexCoord3hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD4HNVPROC __glewTexCoord4hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD4HVNVPROC __glewTexCoord4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEX2HNVPROC __glewVertex2hNV; +GLEW_FUN_EXPORT PFNGLVERTEX2HVNVPROC __glewVertex2hvNV; +GLEW_FUN_EXPORT PFNGLVERTEX3HNVPROC __glewVertex3hNV; +GLEW_FUN_EXPORT PFNGLVERTEX3HVNVPROC __glewVertex3hvNV; +GLEW_FUN_EXPORT PFNGLVERTEX4HNVPROC __glewVertex4hNV; +GLEW_FUN_EXPORT PFNGLVERTEX4HVNVPROC __glewVertex4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HNVPROC __glewVertexAttrib1hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HVNVPROC __glewVertexAttrib1hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HNVPROC __glewVertexAttrib2hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HVNVPROC __glewVertexAttrib2hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HNVPROC __glewVertexAttrib3hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HVNVPROC __glewVertexAttrib3hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HNVPROC __glewVertexAttrib4hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HVNVPROC __glewVertexAttrib4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1HVNVPROC __glewVertexAttribs1hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2HVNVPROC __glewVertexAttribs2hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3HVNVPROC __glewVertexAttribs3hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4HVNVPROC __glewVertexAttribs4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHNVPROC __glewVertexWeighthNV; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHVNVPROC __glewVertexWeighthvNV; + +GLEW_FUN_EXPORT PFNGLBEGINOCCLUSIONQUERYNVPROC __glewBeginOcclusionQueryNV; +GLEW_FUN_EXPORT PFNGLDELETEOCCLUSIONQUERIESNVPROC __glewDeleteOcclusionQueriesNV; +GLEW_FUN_EXPORT PFNGLENDOCCLUSIONQUERYNVPROC __glewEndOcclusionQueryNV; +GLEW_FUN_EXPORT PFNGLGENOCCLUSIONQUERIESNVPROC __glewGenOcclusionQueriesNV; +GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYIVNVPROC __glewGetOcclusionQueryivNV; +GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYUIVNVPROC __glewGetOcclusionQueryuivNV; +GLEW_FUN_EXPORT PFNGLISOCCLUSIONQUERYNVPROC __glewIsOcclusionQueryNV; + +GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC __glewProgramBufferParametersIivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC __glewProgramBufferParametersIuivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC __glewProgramBufferParametersfvNV; + +GLEW_FUN_EXPORT PFNGLFLUSHPIXELDATARANGENVPROC __glewFlushPixelDataRangeNV; +GLEW_FUN_EXPORT PFNGLPIXELDATARANGENVPROC __glewPixelDataRangeNV; + +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERINVPROC __glewPointParameteriNV; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIVNVPROC __glewPointParameterivNV; + +GLEW_FUN_EXPORT PFNGLGETVIDEOI64VNVPROC __glewGetVideoi64vNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOIVNVPROC __glewGetVideoivNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOUI64VNVPROC __glewGetVideoui64vNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOUIVNVPROC __glewGetVideouivNV; +GLEW_FUN_EXPORT PFNGLPRESENTFRAMEDUALFILLNVPROC __glewPresentFrameDualFillNV; +GLEW_FUN_EXPORT PFNGLPRESENTFRAMEKEYEDNVPROC __glewPresentFrameKeyedNV; +GLEW_FUN_EXPORT PFNGLVIDEOPARAMETERIVNVPROC __glewVideoParameterivNV; + +GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTINDEXNVPROC __glewPrimitiveRestartIndexNV; +GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTNVPROC __glewPrimitiveRestartNV; + +GLEW_FUN_EXPORT PFNGLCOMBINERINPUTNVPROC __glewCombinerInputNV; +GLEW_FUN_EXPORT PFNGLCOMBINEROUTPUTNVPROC __glewCombinerOutputNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFNVPROC __glewCombinerParameterfNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFVNVPROC __glewCombinerParameterfvNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERINVPROC __glewCombinerParameteriNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERIVNVPROC __glewCombinerParameterivNV; +GLEW_FUN_EXPORT PFNGLFINALCOMBINERINPUTNVPROC __glewFinalCombinerInputNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC __glewGetCombinerInputParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC __glewGetCombinerInputParameterivNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC __glewGetCombinerOutputParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC __glewGetCombinerOutputParameterivNV; +GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC __glewGetFinalCombinerInputParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC __glewGetFinalCombinerInputParameterivNV; + +GLEW_FUN_EXPORT PFNGLCOMBINERSTAGEPARAMETERFVNVPROC __glewCombinerStageParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC __glewGetCombinerStageParameterfvNV; + +GLEW_FUN_EXPORT PFNGLACTIVEVARYINGNVPROC __glewActiveVaryingNV; +GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKNVPROC __glewBeginTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLBINDBUFFERBASENVPROC __glewBindBufferBaseNV; +GLEW_FUN_EXPORT PFNGLBINDBUFFEROFFSETNVPROC __glewBindBufferOffsetNV; +GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGENVPROC __glewBindBufferRangeNV; +GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKNVPROC __glewEndTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLGETACTIVEVARYINGNVPROC __glewGetActiveVaryingNV; +GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC __glewGetTransformFeedbackVaryingNV; +GLEW_FUN_EXPORT PFNGLGETVARYINGLOCATIONNVPROC __glewGetVaryingLocationNV; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC __glewTransformFeedbackAttribsNV; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC __glewTransformFeedbackVaryingsNV; + +GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGENVPROC __glewFlushVertexArrayRangeNV; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGENVPROC __glewVertexArrayRangeNV; + +GLEW_FUN_EXPORT PFNGLAREPROGRAMSRESIDENTNVPROC __glewAreProgramsResidentNV; +GLEW_FUN_EXPORT PFNGLBINDPROGRAMNVPROC __glewBindProgramNV; +GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSNVPROC __glewDeleteProgramsNV; +GLEW_FUN_EXPORT PFNGLEXECUTEPROGRAMNVPROC __glewExecuteProgramNV; +GLEW_FUN_EXPORT PFNGLGENPROGRAMSNVPROC __glewGenProgramsNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERDVNVPROC __glewGetProgramParameterdvNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERFVNVPROC __glewGetProgramParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGNVPROC __glewGetProgramStringNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMIVNVPROC __glewGetProgramivNV; +GLEW_FUN_EXPORT PFNGLGETTRACKMATRIXIVNVPROC __glewGetTrackMatrixivNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVNVPROC __glewGetVertexAttribPointervNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVNVPROC __glewGetVertexAttribdvNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVNVPROC __glewGetVertexAttribfvNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVNVPROC __glewGetVertexAttribivNV; +GLEW_FUN_EXPORT PFNGLISPROGRAMNVPROC __glewIsProgramNV; +GLEW_FUN_EXPORT PFNGLLOADPROGRAMNVPROC __glewLoadProgramNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DNVPROC __glewProgramParameter4dNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DVNVPROC __glewProgramParameter4dvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FNVPROC __glewProgramParameter4fNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FVNVPROC __glewProgramParameter4fvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4DVNVPROC __glewProgramParameters4dvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4FVNVPROC __glewProgramParameters4fvNV; +GLEW_FUN_EXPORT PFNGLREQUESTRESIDENTPROGRAMSNVPROC __glewRequestResidentProgramsNV; +GLEW_FUN_EXPORT PFNGLTRACKMATRIXNVPROC __glewTrackMatrixNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DNVPROC __glewVertexAttrib1dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVNVPROC __glewVertexAttrib1dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FNVPROC __glewVertexAttrib1fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVNVPROC __glewVertexAttrib1fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SNVPROC __glewVertexAttrib1sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVNVPROC __glewVertexAttrib1svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DNVPROC __glewVertexAttrib2dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVNVPROC __glewVertexAttrib2dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FNVPROC __glewVertexAttrib2fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVNVPROC __glewVertexAttrib2fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SNVPROC __glewVertexAttrib2sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVNVPROC __glewVertexAttrib2svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DNVPROC __glewVertexAttrib3dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVNVPROC __glewVertexAttrib3dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FNVPROC __glewVertexAttrib3fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVNVPROC __glewVertexAttrib3fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SNVPROC __glewVertexAttrib3sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVNVPROC __glewVertexAttrib3svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DNVPROC __glewVertexAttrib4dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVNVPROC __glewVertexAttrib4dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FNVPROC __glewVertexAttrib4fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVNVPROC __glewVertexAttrib4fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SNVPROC __glewVertexAttrib4sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVNVPROC __glewVertexAttrib4svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBNVPROC __glewVertexAttrib4ubNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVNVPROC __glewVertexAttrib4ubvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERNVPROC __glewVertexAttribPointerNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1DVNVPROC __glewVertexAttribs1dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1FVNVPROC __glewVertexAttribs1fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1SVNVPROC __glewVertexAttribs1svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2DVNVPROC __glewVertexAttribs2dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2FVNVPROC __glewVertexAttribs2fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2SVNVPROC __glewVertexAttribs2svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3DVNVPROC __glewVertexAttribs3dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3FVNVPROC __glewVertexAttribs3fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3SVNVPROC __glewVertexAttribs3svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4DVNVPROC __glewVertexAttribs4dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4FVNVPROC __glewVertexAttribs4fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4SVNVPROC __glewVertexAttribs4svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4UBVNVPROC __glewVertexAttribs4ubvNV; + +GLEW_FUN_EXPORT PFNGLCLEARDEPTHFOESPROC __glewClearDepthfOES; +GLEW_FUN_EXPORT PFNGLCLIPPLANEFOESPROC __glewClipPlanefOES; +GLEW_FUN_EXPORT PFNGLDEPTHRANGEFOESPROC __glewDepthRangefOES; +GLEW_FUN_EXPORT PFNGLFRUSTUMFOESPROC __glewFrustumfOES; +GLEW_FUN_EXPORT PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES; +GLEW_FUN_EXPORT PFNGLORTHOFOESPROC __glewOrthofOES; + +GLEW_FUN_EXPORT PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS; +GLEW_FUN_EXPORT PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS; + +GLEW_FUN_EXPORT PFNGLFOGFUNCSGISPROC __glewFogFuncSGIS; +GLEW_FUN_EXPORT PFNGLGETFOGFUNCSGISPROC __glewGetFogFuncSGIS; + +GLEW_FUN_EXPORT PFNGLSAMPLEMASKSGISPROC __glewSampleMaskSGIS; +GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNSGISPROC __glewSamplePatternSGIS; + +GLEW_FUN_EXPORT PFNGLGETSHARPENTEXFUNCSGISPROC __glewGetSharpenTexFuncSGIS; +GLEW_FUN_EXPORT PFNGLSHARPENTEXFUNCSGISPROC __glewSharpenTexFuncSGIS; + +GLEW_FUN_EXPORT PFNGLTEXIMAGE4DSGISPROC __glewTexImage4DSGIS; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE4DSGISPROC __glewTexSubImage4DSGIS; + +GLEW_FUN_EXPORT PFNGLGETTEXFILTERFUNCSGISPROC __glewGetTexFilterFuncSGIS; +GLEW_FUN_EXPORT PFNGLTEXFILTERFUNCSGISPROC __glewTexFilterFuncSGIS; + +GLEW_FUN_EXPORT PFNGLASYNCMARKERSGIXPROC __glewAsyncMarkerSGIX; +GLEW_FUN_EXPORT PFNGLDELETEASYNCMARKERSSGIXPROC __glewDeleteAsyncMarkersSGIX; +GLEW_FUN_EXPORT PFNGLFINISHASYNCSGIXPROC __glewFinishAsyncSGIX; +GLEW_FUN_EXPORT PFNGLGENASYNCMARKERSSGIXPROC __glewGenAsyncMarkersSGIX; +GLEW_FUN_EXPORT PFNGLISASYNCMARKERSGIXPROC __glewIsAsyncMarkerSGIX; +GLEW_FUN_EXPORT PFNGLPOLLASYNCSGIXPROC __glewPollAsyncSGIX; + +GLEW_FUN_EXPORT PFNGLFLUSHRASTERSGIXPROC __glewFlushRasterSGIX; + +GLEW_FUN_EXPORT PFNGLTEXTUREFOGSGIXPROC __glewTextureFogSGIX; + +GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALSGIXPROC __glewFragmentColorMaterialSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFSGIXPROC __glewFragmentLightModelfSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVSGIXPROC __glewFragmentLightModelfvSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELISGIXPROC __glewFragmentLightModeliSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVSGIXPROC __glewFragmentLightModelivSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFSGIXPROC __glewFragmentLightfSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVSGIXPROC __glewFragmentLightfvSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTISGIXPROC __glewFragmentLightiSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVSGIXPROC __glewFragmentLightivSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFSGIXPROC __glewFragmentMaterialfSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVSGIXPROC __glewFragmentMaterialfvSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALISGIXPROC __glewFragmentMaterialiSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVSGIXPROC __glewFragmentMaterialivSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVSGIXPROC __glewGetFragmentLightfvSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVSGIXPROC __glewGetFragmentLightivSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVSGIXPROC __glewGetFragmentMaterialfvSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVSGIXPROC __glewGetFragmentMaterialivSGIX; + +GLEW_FUN_EXPORT PFNGLFRAMEZOOMSGIXPROC __glewFrameZoomSGIX; + +GLEW_FUN_EXPORT PFNGLPIXELTEXGENSGIXPROC __glewPixelTexGenSGIX; + +GLEW_FUN_EXPORT PFNGLREFERENCEPLANESGIXPROC __glewReferencePlaneSGIX; + +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFSGIXPROC __glewSpriteParameterfSGIX; +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFVSGIXPROC __glewSpriteParameterfvSGIX; +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERISGIXPROC __glewSpriteParameteriSGIX; +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERIVSGIXPROC __glewSpriteParameterivSGIX; + +GLEW_FUN_EXPORT PFNGLTAGSAMPLEBUFFERSGIXPROC __glewTagSampleBufferSGIX; + +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVSGIPROC __glewColorTableParameterfvSGI; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVSGIPROC __glewColorTableParameterivSGI; +GLEW_FUN_EXPORT PFNGLCOLORTABLESGIPROC __glewColorTableSGI; +GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLESGIPROC __glewCopyColorTableSGI; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVSGIPROC __glewGetColorTableParameterfvSGI; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVSGIPROC __glewGetColorTableParameterivSGI; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLESGIPROC __glewGetColorTableSGI; + +GLEW_FUN_EXPORT PFNGLFINISHTEXTURESUNXPROC __glewFinishTextureSUNX; + +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORBSUNPROC __glewGlobalAlphaFactorbSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORDSUNPROC __glewGlobalAlphaFactordSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORFSUNPROC __glewGlobalAlphaFactorfSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORISUNPROC __glewGlobalAlphaFactoriSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORSSUNPROC __glewGlobalAlphaFactorsSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUBSUNPROC __glewGlobalAlphaFactorubSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUISUNPROC __glewGlobalAlphaFactoruiSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUSSUNPROC __glewGlobalAlphaFactorusSUN; + +GLEW_FUN_EXPORT PFNGLREADVIDEOPIXELSSUNPROC __glewReadVideoPixelsSUN; + +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEPOINTERSUNPROC __glewReplacementCodePointerSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBSUNPROC __glewReplacementCodeubSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBVSUNPROC __glewReplacementCodeubvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUISUNPROC __glewReplacementCodeuiSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVSUNPROC __glewReplacementCodeuivSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSSUNPROC __glewReplacementCodeusSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSVSUNPROC __glewReplacementCodeusvSUN; + +GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FSUNPROC __glewColor3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FVSUNPROC __glewColor3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FSUNPROC __glewColor4ubVertex2fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FVSUNPROC __glewColor4ubVertex2fvSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FSUNPROC __glewColor4ubVertex3fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FVSUNPROC __glewColor4ubVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FSUNPROC __glewNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FVSUNPROC __glewNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC __glewReplacementCodeuiColor3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC __glewReplacementCodeuiColor4ubVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC __glewReplacementCodeuiColor4ubVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC __glewReplacementCodeuiVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC __glewReplacementCodeuiVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC __glewTexCoord2fColor3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC __glewTexCoord2fColor3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC __glewTexCoord2fColor4ubVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC __glewTexCoord2fColor4ubVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FSUNPROC __glewTexCoord2fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FVSUNPROC __glewTexCoord2fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FSUNPROC __glewTexCoord4fVertex4fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FVSUNPROC __glewTexCoord4fVertex4fvSUN; + +GLEW_FUN_EXPORT PFNGLADDSWAPHINTRECTWINPROC __glewAddSwapHintRectWIN; + +#if defined(GLEW_MX) && !defined(_WIN32) +struct GLEWContextStruct +{ +#endif /* GLEW_MX */ + +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_1; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_3; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_4; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_5; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_2_0; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_2_1; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_0; +GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_tbuffer; +GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_texture_compression_FXT1; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_client_storage; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_element_array; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_fence; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_float_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_flush_buffer_range; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_pixel_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_specular_vector; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_texture_range; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_transform_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_range; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_ycbcr_422; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_color_buffer_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_buffer_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_instanced; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program_shadow; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_sRGB; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_geometry_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_pixel; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_imaging; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_instanced_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_map_buffer_range; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_matrix_palette; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multitexture; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_pixel_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_parameters; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_sprite; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_objects; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_100; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow_ambient; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_border_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_rgtc; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_cube_map; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_add; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_combine; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_crossbar; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_dot3; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_mirrored_repeat; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_non_power_of_two; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rectangle; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rg; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transpose_matrix; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_blend; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_program; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_window_pos; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_point_sprites; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_combine3; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_route; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_vertex_shader_output_point_size; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_draw_buffers; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_element_array; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_envmap_bumpmap; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_fragment_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_map_object_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_pn_triangles; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_separate_stencil; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_shader_texture_lod; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_text_fragment_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_compression_3dc; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_env_combine3; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_mirror_once; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_attrib_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_streams; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_422_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_Cg_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_abgr; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_bgra; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_bindable_uniform; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_color; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_equation_separate; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_func_separate; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_logic_op; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_minmax; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_subtract; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_clip_volume_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cmyka; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_color_subtable; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_compiled_vertex_array; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_convolution; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_coordinate_frame; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_copy_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cull_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_depth_bounds_test; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_direct_state_access; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_buffers2; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_instanced; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_range_elements; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fog_coord; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fragment_lighting; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_blit; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_sRGB; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_geometry_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_gpu_program_parameters; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_gpu_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_histogram; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_array_formats; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_func; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_material; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_light_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_misc_attribute; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multi_draw_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_depth_stencil; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_float; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_paletted_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform_color_table; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_point_parameters; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_polygon_offset; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_rescale_normal; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_scene_marker; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_secondary_color; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_specular_color; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shadow_funcs; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shared_texture_palette; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_clear_tag; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_two_side; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_wrap; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_subtexture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture3D; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_array; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_dxt1; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_latc; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_rgtc; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_s3tc; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_cube_map; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_edge_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_add; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_combine; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_dot3; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_filter_anisotropic; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_integer; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_lod_bias; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_mirror_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_perturb_normal; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_rectangle; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_sRGB; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_shared_exponent; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_swizzle; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_timer_query; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_transform_feedback; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_array; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_array_bgra; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_weighting; +GLEW_VAR_EXPORT GLboolean __GLEW_GREMEDY_frame_terminator; +GLEW_VAR_EXPORT GLboolean __GLEW_GREMEDY_string_marker; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_convolution_border_modes; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_image_transform; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_occlusion_test; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_texture_lighting; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_cull_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_multimode_draw_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_rasterpos_clip; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_static_data; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_texture_mirrored_repeat; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_vertex_array_lists; +GLEW_VAR_EXPORT GLboolean __GLEW_INGR_color_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_INGR_interlace_read; +GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_parallel_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_texture_scissor; +GLEW_VAR_EXPORT GLboolean __GLEW_KTX_buffer_region; +GLEW_VAR_EXPORT GLboolean __GLEW_MESAX_texture_stack; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_pack_invert; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_resize_buffers; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_window_pos; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_ycbcr_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_blend_square; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_conditional_render; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_depth_to_color; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_buffer_float; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_range_unclamped; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_evaluators; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_explicit_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fence; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_float_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fog_distance; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program_option; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_framebuffer_multisample_coverage; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_half_float; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_light_max_exponent; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_multisample_filter_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_occlusion_query; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_packed_depth_stencil; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_parameter_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_pixel_data_range; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_point_sprite; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_present_video; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_primitive_restart; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_emboss; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_reflection; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_compression_vtc; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_env_combine4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_expand_normal; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_rectangle; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader3; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_transform_feedback; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program1_1; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2_option; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program3; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_byte_coordinates; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_compressed_paletted_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_read_format; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_single_precision; +GLEW_VAR_EXPORT GLboolean __GLEW_OML_interlace; +GLEW_VAR_EXPORT GLboolean __GLEW_OML_resample; +GLEW_VAR_EXPORT GLboolean __GLEW_OML_subsample; +GLEW_VAR_EXPORT GLboolean __GLEW_PGI_misc_hints; +GLEW_VAR_EXPORT GLboolean __GLEW_PGI_vertex_hints; +GLEW_VAR_EXPORT GLboolean __GLEW_REND_screen_coordinates; +GLEW_VAR_EXPORT GLboolean __GLEW_S3_s3tc; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_color_range; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_detail_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_fog_function; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_generate_mipmap; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_pixel_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_point_line_texgen; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_sharpen_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture4D; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_border_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_edge_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_filter4; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_lod; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_select; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_histogram; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_pixel; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_blend_alpha_minmax; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_clipmap; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_convolution_accuracy; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_depth_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_flush_raster; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_offset; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fragment_specular_lighting; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_framezoom; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_interlace; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ir_instrument1; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_list_priority; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture_bits; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_reference_plane; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_resample; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow_ambient; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_sprite; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_tag_sample_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_add_env; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_coordinate_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_lod_bias; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_multi_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_range; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_scale_bias; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ycrcb; +GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_matrix; +GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_table; +GLEW_VAR_EXPORT GLboolean __GLEW_SGI_texture_color_table; +GLEW_VAR_EXPORT GLboolean __GLEW_SUNX_constant_data; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_convolution_border_modes; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_global_alpha; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_mesh_array; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_read_video_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_slice_accum; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_triangle_list; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_WIN_phong_shading; +GLEW_VAR_EXPORT GLboolean __GLEW_WIN_specular_fog; +GLEW_VAR_EXPORT GLboolean __GLEW_WIN_swap_hint; + +#ifdef GLEW_MX +}; /* GLEWContextStruct */ +#endif /* GLEW_MX */ + +/* ------------------------------------------------------------------------- */ + +/* error codes */ +#define GLEW_OK 0 +#define GLEW_NO_ERROR 0 +#define GLEW_ERROR_NO_GL_VERSION 1 /* missing GL version */ +#define GLEW_ERROR_GL_VERSION_10_ONLY 2 /* GL 1.1 and up are not supported */ +#define GLEW_ERROR_GLX_VERSION_11_ONLY 3 /* GLX 1.2 and up are not supported */ + +/* string codes */ +#define GLEW_VERSION 1 +#define GLEW_VERSION_MAJOR 2 +#define GLEW_VERSION_MINOR 3 +#define GLEW_VERSION_MICRO 4 + +/* API */ +#ifdef GLEW_MX + +typedef struct GLEWContextStruct GLEWContext; +GLEWAPI GLenum glewContextInit (GLEWContext* ctx); +GLEWAPI GLboolean glewContextIsSupported (GLEWContext* ctx, const char* name); + +#define glewInit() glewContextInit(glewGetContext()) +#define glewIsSupported(x) glewContextIsSupported(glewGetContext(), x) +#define glewIsExtensionSupported(x) glewIsSupported(x) + +#define GLEW_GET_VAR(x) (*(const GLboolean*)&(glewGetContext()->x)) +#ifdef _WIN32 +# define GLEW_GET_FUN(x) glewGetContext()->x +#else +# define GLEW_GET_FUN(x) x +#endif + +#else /* GLEW_MX */ + +GLEWAPI GLenum glewInit (); +GLEWAPI GLboolean glewIsSupported (const char* name); +#define glewIsExtensionSupported(x) glewIsSupported(x) + +#define GLEW_GET_VAR(x) (*(const GLboolean*)&x) +#define GLEW_GET_FUN(x) x + +#endif /* GLEW_MX */ + +GLEWAPI GLboolean glewExperimental; +GLEWAPI GLboolean glewGetExtension (const char* name); +GLEWAPI const GLubyte* glewGetErrorString (GLenum error); +GLEWAPI const GLubyte* glewGetString (GLenum name); + +#ifdef __cplusplus +} +#endif + +#ifdef GLEW_APIENTRY_DEFINED +#undef GLEW_APIENTRY_DEFINED +#undef APIENTRY +#undef GLAPIENTRY +#endif + +#ifdef GLEW_CALLBACK_DEFINED +#undef GLEW_CALLBACK_DEFINED +#undef CALLBACK +#endif + +#ifdef GLEW_WINGDIAPI_DEFINED +#undef GLEW_WINGDIAPI_DEFINED +#undef WINGDIAPI +#endif + +#undef GLAPI +/* #undef GLEWAPI */ + +#endif /* __glew_h__ */ diff --git a/test_conformance/gl/GLEW/GL/glxew.h b/test_conformance/gl/GLEW/GL/glxew.h new file mode 100644 index 00000000..625ee0fb --- /dev/null +++ b/test_conformance/gl/GLEW/GL/glxew.h @@ -0,0 +1,1397 @@ +/* +** The OpenGL Extension Wrangler Library +** Copyright (C) 2002-2008, Milan Ikits +** Copyright (C) 2002-2008, Marcelo E. Magallon +** Copyright (C) 2002, Lev Povalahev +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** * The name of the author may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +** THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * Mesa 3-D graphics library + * Version: 7.0 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* +** Copyright (c) 2007 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#ifndef __glxew_h__ +#define __glxew_h__ +#define __GLXEW_H__ + +#ifdef __glxext_h_ +#error glxext.h included before glxew.h +#endif +#ifdef GLX_H +#error glx.h included before glxew.h +#endif + +#define __glxext_h_ +#define __GLX_glx_h__ +#define GLX_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---------------------------- GLX_VERSION_1_0 --------------------------- */ + +#ifndef GLX_VERSION_1_0 +#define GLX_VERSION_1_0 1 + +#define GLX_USE_GL 1 +#define GLX_BUFFER_SIZE 2 +#define GLX_LEVEL 3 +#define GLX_RGBA 4 +#define GLX_DOUBLEBUFFER 5 +#define GLX_STEREO 6 +#define GLX_AUX_BUFFERS 7 +#define GLX_RED_SIZE 8 +#define GLX_GREEN_SIZE 9 +#define GLX_BLUE_SIZE 10 +#define GLX_ALPHA_SIZE 11 +#define GLX_DEPTH_SIZE 12 +#define GLX_STENCIL_SIZE 13 +#define GLX_ACCUM_RED_SIZE 14 +#define GLX_ACCUM_GREEN_SIZE 15 +#define GLX_ACCUM_BLUE_SIZE 16 +#define GLX_ACCUM_ALPHA_SIZE 17 +#define GLX_BAD_SCREEN 1 +#define GLX_BAD_ATTRIBUTE 2 +#define GLX_NO_EXTENSION 3 +#define GLX_BAD_VISUAL 4 +#define GLX_BAD_CONTEXT 5 +#define GLX_BAD_VALUE 6 +#define GLX_BAD_ENUM 7 + +typedef XID GLXDrawable; +typedef XID GLXPixmap; +#ifdef __sun +typedef struct __glXContextRec *GLXContext; +#else +typedef struct __GLXcontextRec *GLXContext; +#endif + +typedef unsigned int GLXVideoDeviceNV; + +extern Bool glXQueryExtension (Display *dpy, int *errorBase, int *eventBase); +extern Bool glXQueryVersion (Display *dpy, int *major, int *minor); +extern int glXGetConfig (Display *dpy, XVisualInfo *vis, int attrib, int *value); +extern XVisualInfo* glXChooseVisual (Display *dpy, int screen, int *attribList); +extern GLXPixmap glXCreateGLXPixmap (Display *dpy, XVisualInfo *vis, Pixmap pixmap); +extern void glXDestroyGLXPixmap (Display *dpy, GLXPixmap pix); +extern GLXContext glXCreateContext (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct); +extern void glXDestroyContext (Display *dpy, GLXContext ctx); +extern Bool glXIsDirect (Display *dpy, GLXContext ctx); +extern void glXCopyContext (Display *dpy, GLXContext src, GLXContext dst, GLulong mask); +extern Bool glXMakeCurrent (Display *dpy, GLXDrawable drawable, GLXContext ctx); +extern GLXContext glXGetCurrentContext (void); +extern GLXDrawable glXGetCurrentDrawable (void); +extern void glXWaitGL (void); +extern void glXWaitX (void); +extern void glXSwapBuffers (Display *dpy, GLXDrawable drawable); +extern void glXUseXFont (Font font, int first, int count, int listBase); + +#define GLXEW_VERSION_1_0 GLXEW_GET_VAR(__GLXEW_VERSION_1_0) + +#endif /* GLX_VERSION_1_0 */ + +/* ---------------------------- GLX_VERSION_1_1 --------------------------- */ + +#ifndef GLX_VERSION_1_1 +#define GLX_VERSION_1_1 + +#define GLX_VENDOR 0x1 +#define GLX_VERSION 0x2 +#define GLX_EXTENSIONS 0x3 + +extern const char* glXQueryExtensionsString (Display *dpy, int screen); +extern const char* glXGetClientString (Display *dpy, int name); +extern const char* glXQueryServerString (Display *dpy, int screen, int name); + +#define GLXEW_VERSION_1_1 GLXEW_GET_VAR(__GLXEW_VERSION_1_1) + +#endif /* GLX_VERSION_1_1 */ + +/* ---------------------------- GLX_VERSION_1_2 ---------------------------- */ + +#ifndef GLX_VERSION_1_2 +#define GLX_VERSION_1_2 1 + +typedef Display* ( * PFNGLXGETCURRENTDISPLAYPROC) (void); + +#define glXGetCurrentDisplay GLXEW_GET_FUN(__glewXGetCurrentDisplay) + +#define GLXEW_VERSION_1_2 GLXEW_GET_VAR(__GLXEW_VERSION_1_2) + +#endif /* GLX_VERSION_1_2 */ + +/* ---------------------------- GLX_VERSION_1_3 ---------------------------- */ + +#ifndef GLX_VERSION_1_3 +#define GLX_VERSION_1_3 1 + +#define GLX_RGBA_BIT 0x00000001 +#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_COLOR_INDEX_BIT 0x00000002 +#define GLX_PIXMAP_BIT 0x00000002 +#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 +#define GLX_PBUFFER_BIT 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 +#define GLX_AUX_BUFFERS_BIT 0x00000010 +#define GLX_CONFIG_CAVEAT 0x20 +#define GLX_DEPTH_BUFFER_BIT 0x00000020 +#define GLX_X_VISUAL_TYPE 0x22 +#define GLX_TRANSPARENT_TYPE 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE 0x24 +#define GLX_TRANSPARENT_RED_VALUE 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 +#define GLX_STENCIL_BUFFER_BIT 0x00000040 +#define GLX_ACCUM_BUFFER_BIT 0x00000080 +#define GLX_NONE 0x8000 +#define GLX_SLOW_CONFIG 0x8001 +#define GLX_TRUE_COLOR 0x8002 +#define GLX_DIRECT_COLOR 0x8003 +#define GLX_PSEUDO_COLOR 0x8004 +#define GLX_STATIC_COLOR 0x8005 +#define GLX_GRAY_SCALE 0x8006 +#define GLX_STATIC_GRAY 0x8007 +#define GLX_TRANSPARENT_RGB 0x8008 +#define GLX_TRANSPARENT_INDEX 0x8009 +#define GLX_VISUAL_ID 0x800B +#define GLX_SCREEN 0x800C +#define GLX_NON_CONFORMANT_CONFIG 0x800D +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_X_RENDERABLE 0x8012 +#define GLX_FBCONFIG_ID 0x8013 +#define GLX_RGBA_TYPE 0x8014 +#define GLX_COLOR_INDEX_TYPE 0x8015 +#define GLX_MAX_PBUFFER_WIDTH 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT 0x8017 +#define GLX_MAX_PBUFFER_PIXELS 0x8018 +#define GLX_PRESERVED_CONTENTS 0x801B +#define GLX_LARGEST_PBUFFER 0x801C +#define GLX_WIDTH 0x801D +#define GLX_HEIGHT 0x801E +#define GLX_EVENT_MASK 0x801F +#define GLX_DAMAGED 0x8020 +#define GLX_SAVED 0x8021 +#define GLX_WINDOW 0x8022 +#define GLX_PBUFFER 0x8023 +#define GLX_PBUFFER_HEIGHT 0x8040 +#define GLX_PBUFFER_WIDTH 0x8041 +#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 +#define GLX_DONT_CARE 0xFFFFFFFF + +typedef XID GLXFBConfigID; +typedef XID GLXWindow; +typedef XID GLXPbuffer; +typedef struct __GLXFBConfigRec *GLXFBConfig; + +typedef struct { + int event_type; + int draw_type; + unsigned long serial; + Bool send_event; + Display *display; + GLXDrawable drawable; + unsigned int buffer_mask; + unsigned int aux_buffer; + int x, y; + int width, height; + int count; +} GLXPbufferClobberEvent; +typedef union __GLXEvent { + GLXPbufferClobberEvent glxpbufferclobber; + long pad[24]; +} GLXEvent; + +typedef GLXFBConfig* ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); +typedef GLXContext ( * PFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +typedef GLXPbuffer ( * PFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list); +typedef GLXPixmap ( * PFNGLXCREATEPIXMAPPROC) (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list); +typedef GLXWindow ( * PFNGLXCREATEWINDOWPROC) (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list); +typedef void ( * PFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf); +typedef void ( * PFNGLXDESTROYPIXMAPPROC) (Display *dpy, GLXPixmap pixmap); +typedef void ( * PFNGLXDESTROYWINDOWPROC) (Display *dpy, GLXWindow win); +typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLEPROC) (void); +typedef int ( * PFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value); +typedef GLXFBConfig* ( * PFNGLXGETFBCONFIGSPROC) (Display *dpy, int screen, int *nelements); +typedef void ( * PFNGLXGETSELECTEDEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long *event_mask); +typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config); +typedef Bool ( * PFNGLXMAKECONTEXTCURRENTPROC) (Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +typedef int ( * PFNGLXQUERYCONTEXTPROC) (Display *dpy, GLXContext ctx, int attribute, int *value); +typedef void ( * PFNGLXQUERYDRAWABLEPROC) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); +typedef void ( * PFNGLXSELECTEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long event_mask); + +#define glXChooseFBConfig GLXEW_GET_FUN(__glewXChooseFBConfig) +#define glXCreateNewContext GLXEW_GET_FUN(__glewXCreateNewContext) +#define glXCreatePbuffer GLXEW_GET_FUN(__glewXCreatePbuffer) +#define glXCreatePixmap GLXEW_GET_FUN(__glewXCreatePixmap) +#define glXCreateWindow GLXEW_GET_FUN(__glewXCreateWindow) +#define glXDestroyPbuffer GLXEW_GET_FUN(__glewXDestroyPbuffer) +#define glXDestroyPixmap GLXEW_GET_FUN(__glewXDestroyPixmap) +#define glXDestroyWindow GLXEW_GET_FUN(__glewXDestroyWindow) +#define glXGetCurrentReadDrawable GLXEW_GET_FUN(__glewXGetCurrentReadDrawable) +#define glXGetFBConfigAttrib GLXEW_GET_FUN(__glewXGetFBConfigAttrib) +#define glXGetFBConfigs GLXEW_GET_FUN(__glewXGetFBConfigs) +#define glXGetSelectedEvent GLXEW_GET_FUN(__glewXGetSelectedEvent) +#define glXGetVisualFromFBConfig GLXEW_GET_FUN(__glewXGetVisualFromFBConfig) +#define glXMakeContextCurrent GLXEW_GET_FUN(__glewXMakeContextCurrent) +#define glXQueryContext GLXEW_GET_FUN(__glewXQueryContext) +#define glXQueryDrawable GLXEW_GET_FUN(__glewXQueryDrawable) +#define glXSelectEvent GLXEW_GET_FUN(__glewXSelectEvent) + +#define GLXEW_VERSION_1_3 GLXEW_GET_VAR(__GLXEW_VERSION_1_3) + +#endif /* GLX_VERSION_1_3 */ + +/* ---------------------------- GLX_VERSION_1_4 ---------------------------- */ + +#ifndef GLX_VERSION_1_4 +#define GLX_VERSION_1_4 1 + +#define GLX_SAMPLE_BUFFERS 100000 +#define GLX_SAMPLES 100001 + +extern void ( * glXGetProcAddress (const GLubyte *procName)) (void); + +#define GLXEW_VERSION_1_4 GLXEW_GET_VAR(__GLXEW_VERSION_1_4) + +#endif /* GLX_VERSION_1_4 */ + +/* -------------------------- GLX_3DFX_multisample ------------------------- */ + +#ifndef GLX_3DFX_multisample +#define GLX_3DFX_multisample 1 + +#define GLX_SAMPLE_BUFFERS_3DFX 0x8050 +#define GLX_SAMPLES_3DFX 0x8051 + +#define GLXEW_3DFX_multisample GLXEW_GET_VAR(__GLXEW_3DFX_multisample) + +#endif /* GLX_3DFX_multisample */ + +/* ------------------------- GLX_ARB_create_context ------------------------ */ + +#ifndef GLX_ARB_create_context +#define GLX_ARB_create_context 1 + +#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define GLX_CONTEXT_FLAGS_ARB 0x2094 + +typedef GLXContext ( * PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list); + +#define glXCreateContextAttribsARB GLXEW_GET_FUN(__glewXCreateContextAttribsARB) + +#define GLXEW_ARB_create_context GLXEW_GET_VAR(__GLXEW_ARB_create_context) + +#endif /* GLX_ARB_create_context */ + +/* ------------------------- GLX_ARB_fbconfig_float ------------------------ */ + +#ifndef GLX_ARB_fbconfig_float +#define GLX_ARB_fbconfig_float 1 + +#define GLX_RGBA_FLOAT_BIT 0x00000004 +#define GLX_RGBA_FLOAT_TYPE 0x20B9 + +#define GLXEW_ARB_fbconfig_float GLXEW_GET_VAR(__GLXEW_ARB_fbconfig_float) + +#endif /* GLX_ARB_fbconfig_float */ + +/* ------------------------ GLX_ARB_framebuffer_sRGB ----------------------- */ + +#ifndef GLX_ARB_framebuffer_sRGB +#define GLX_ARB_framebuffer_sRGB 1 + +#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2 + +#define GLXEW_ARB_framebuffer_sRGB GLXEW_GET_VAR(__GLXEW_ARB_framebuffer_sRGB) + +#endif /* GLX_ARB_framebuffer_sRGB */ + +/* ------------------------ GLX_ARB_get_proc_address ----------------------- */ + +#ifndef GLX_ARB_get_proc_address +#define GLX_ARB_get_proc_address 1 + +extern void ( * glXGetProcAddressARB (const GLubyte *procName)) (void); + +#define GLXEW_ARB_get_proc_address GLXEW_GET_VAR(__GLXEW_ARB_get_proc_address) + +#endif /* GLX_ARB_get_proc_address */ + +/* -------------------------- GLX_ARB_multisample -------------------------- */ + +#ifndef GLX_ARB_multisample +#define GLX_ARB_multisample 1 + +#define GLX_SAMPLE_BUFFERS_ARB 100000 +#define GLX_SAMPLES_ARB 100001 + +#define GLXEW_ARB_multisample GLXEW_GET_VAR(__GLXEW_ARB_multisample) + +#endif /* GLX_ARB_multisample */ + +/* ----------------------- GLX_ATI_pixel_format_float ---------------------- */ + +#ifndef GLX_ATI_pixel_format_float +#define GLX_ATI_pixel_format_float 1 + +#define GLX_RGBA_FLOAT_ATI_BIT 0x00000100 + +#define GLXEW_ATI_pixel_format_float GLXEW_GET_VAR(__GLXEW_ATI_pixel_format_float) + +#endif /* GLX_ATI_pixel_format_float */ + +/* ------------------------- GLX_ATI_render_texture ------------------------ */ + +#ifndef GLX_ATI_render_texture +#define GLX_ATI_render_texture 1 + +#define GLX_BIND_TO_TEXTURE_RGB_ATI 0x9800 +#define GLX_BIND_TO_TEXTURE_RGBA_ATI 0x9801 +#define GLX_TEXTURE_FORMAT_ATI 0x9802 +#define GLX_TEXTURE_TARGET_ATI 0x9803 +#define GLX_MIPMAP_TEXTURE_ATI 0x9804 +#define GLX_TEXTURE_RGB_ATI 0x9805 +#define GLX_TEXTURE_RGBA_ATI 0x9806 +#define GLX_NO_TEXTURE_ATI 0x9807 +#define GLX_TEXTURE_CUBE_MAP_ATI 0x9808 +#define GLX_TEXTURE_1D_ATI 0x9809 +#define GLX_TEXTURE_2D_ATI 0x980A +#define GLX_MIPMAP_LEVEL_ATI 0x980B +#define GLX_CUBE_MAP_FACE_ATI 0x980C +#define GLX_TEXTURE_CUBE_MAP_POSITIVE_X_ATI 0x980D +#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_X_ATI 0x980E +#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Y_ATI 0x980F +#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Y_ATI 0x9810 +#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Z_ATI 0x9811 +#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Z_ATI 0x9812 +#define GLX_FRONT_LEFT_ATI 0x9813 +#define GLX_FRONT_RIGHT_ATI 0x9814 +#define GLX_BACK_LEFT_ATI 0x9815 +#define GLX_BACK_RIGHT_ATI 0x9816 +#define GLX_AUX0_ATI 0x9817 +#define GLX_AUX1_ATI 0x9818 +#define GLX_AUX2_ATI 0x9819 +#define GLX_AUX3_ATI 0x981A +#define GLX_AUX4_ATI 0x981B +#define GLX_AUX5_ATI 0x981C +#define GLX_AUX6_ATI 0x981D +#define GLX_AUX7_ATI 0x981E +#define GLX_AUX8_ATI 0x981F +#define GLX_AUX9_ATI 0x9820 +#define GLX_BIND_TO_TEXTURE_LUMINANCE_ATI 0x9821 +#define GLX_BIND_TO_TEXTURE_INTENSITY_ATI 0x9822 + +typedef void ( * PFNGLXBINDTEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer); +typedef void ( * PFNGLXDRAWABLEATTRIBATIPROC) (Display *dpy, GLXDrawable draw, const int *attrib_list); +typedef void ( * PFNGLXRELEASETEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer); + +#define glXBindTexImageATI GLXEW_GET_FUN(__glewXBindTexImageATI) +#define glXDrawableAttribATI GLXEW_GET_FUN(__glewXDrawableAttribATI) +#define glXReleaseTexImageATI GLXEW_GET_FUN(__glewXReleaseTexImageATI) + +#define GLXEW_ATI_render_texture GLXEW_GET_VAR(__GLXEW_ATI_render_texture) + +#endif /* GLX_ATI_render_texture */ + +/* --------------------- GLX_EXT_fbconfig_packed_float --------------------- */ + +#ifndef GLX_EXT_fbconfig_packed_float +#define GLX_EXT_fbconfig_packed_float 1 + +#define GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT 0x00000008 +#define GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT 0x20B1 + +#define GLXEW_EXT_fbconfig_packed_float GLXEW_GET_VAR(__GLXEW_EXT_fbconfig_packed_float) + +#endif /* GLX_EXT_fbconfig_packed_float */ + +/* ------------------------ GLX_EXT_framebuffer_sRGB ----------------------- */ + +#ifndef GLX_EXT_framebuffer_sRGB +#define GLX_EXT_framebuffer_sRGB 1 + +#define GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20B2 + +#define GLXEW_EXT_framebuffer_sRGB GLXEW_GET_VAR(__GLXEW_EXT_framebuffer_sRGB) + +#endif /* GLX_EXT_framebuffer_sRGB */ + +/* ------------------------- GLX_EXT_import_context ------------------------ */ + +#ifndef GLX_EXT_import_context +#define GLX_EXT_import_context 1 + +#define GLX_SHARE_CONTEXT_EXT 0x800A +#define GLX_VISUAL_ID_EXT 0x800B +#define GLX_SCREEN_EXT 0x800C + +typedef XID GLXContextID; + +typedef void ( * PFNGLXFREECONTEXTEXTPROC) (Display* dpy, GLXContext context); +typedef GLXContextID ( * PFNGLXGETCONTEXTIDEXTPROC) (const GLXContext context); +typedef GLXContext ( * PFNGLXIMPORTCONTEXTEXTPROC) (Display* dpy, GLXContextID contextID); +typedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display* dpy, GLXContext context, int attribute,int *value); + +#define glXFreeContextEXT GLXEW_GET_FUN(__glewXFreeContextEXT) +#define glXGetContextIDEXT GLXEW_GET_FUN(__glewXGetContextIDEXT) +#define glXImportContextEXT GLXEW_GET_FUN(__glewXImportContextEXT) +#define glXQueryContextInfoEXT GLXEW_GET_FUN(__glewXQueryContextInfoEXT) + +#define GLXEW_EXT_import_context GLXEW_GET_VAR(__GLXEW_EXT_import_context) + +#endif /* GLX_EXT_import_context */ + +/* -------------------------- GLX_EXT_scene_marker ------------------------- */ + +#ifndef GLX_EXT_scene_marker +#define GLX_EXT_scene_marker 1 + +#define GLXEW_EXT_scene_marker GLXEW_GET_VAR(__GLXEW_EXT_scene_marker) + +#endif /* GLX_EXT_scene_marker */ + +/* ---------------------- GLX_EXT_texture_from_pixmap ---------------------- */ + +#ifndef GLX_EXT_texture_from_pixmap +#define GLX_EXT_texture_from_pixmap 1 + +#define GLX_TEXTURE_1D_BIT_EXT 0x00000001 +#define GLX_TEXTURE_2D_BIT_EXT 0x00000002 +#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004 +#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0 +#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1 +#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2 +#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3 +#define GLX_Y_INVERTED_EXT 0x20D4 +#define GLX_TEXTURE_FORMAT_EXT 0x20D5 +#define GLX_TEXTURE_TARGET_EXT 0x20D6 +#define GLX_MIPMAP_TEXTURE_EXT 0x20D7 +#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8 +#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9 +#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA +#define GLX_TEXTURE_1D_EXT 0x20DB +#define GLX_TEXTURE_2D_EXT 0x20DC +#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD +#define GLX_FRONT_LEFT_EXT 0x20DE +#define GLX_FRONT_RIGHT_EXT 0x20DF +#define GLX_BACK_LEFT_EXT 0x20E0 +#define GLX_BACK_RIGHT_EXT 0x20E1 +#define GLX_AUX0_EXT 0x20E2 +#define GLX_AUX1_EXT 0x20E3 +#define GLX_AUX2_EXT 0x20E4 +#define GLX_AUX3_EXT 0x20E5 +#define GLX_AUX4_EXT 0x20E6 +#define GLX_AUX5_EXT 0x20E7 +#define GLX_AUX6_EXT 0x20E8 +#define GLX_AUX7_EXT 0x20E9 +#define GLX_AUX8_EXT 0x20EA +#define GLX_AUX9_EXT 0x20EB + +typedef void ( * PFNGLXBINDTEXIMAGEEXTPROC) (Display* display, GLXDrawable drawable, int buffer, const int *attrib_list); +typedef void ( * PFNGLXRELEASETEXIMAGEEXTPROC) (Display* display, GLXDrawable drawable, int buffer); + +#define glXBindTexImageEXT GLXEW_GET_FUN(__glewXBindTexImageEXT) +#define glXReleaseTexImageEXT GLXEW_GET_FUN(__glewXReleaseTexImageEXT) + +#define GLXEW_EXT_texture_from_pixmap GLXEW_GET_VAR(__GLXEW_EXT_texture_from_pixmap) + +#endif /* GLX_EXT_texture_from_pixmap */ + +/* -------------------------- GLX_EXT_visual_info -------------------------- */ + +#ifndef GLX_EXT_visual_info +#define GLX_EXT_visual_info 1 + +#define GLX_X_VISUAL_TYPE_EXT 0x22 +#define GLX_TRANSPARENT_TYPE_EXT 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24 +#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28 +#define GLX_NONE_EXT 0x8000 +#define GLX_TRUE_COLOR_EXT 0x8002 +#define GLX_DIRECT_COLOR_EXT 0x8003 +#define GLX_PSEUDO_COLOR_EXT 0x8004 +#define GLX_STATIC_COLOR_EXT 0x8005 +#define GLX_GRAY_SCALE_EXT 0x8006 +#define GLX_STATIC_GRAY_EXT 0x8007 +#define GLX_TRANSPARENT_RGB_EXT 0x8008 +#define GLX_TRANSPARENT_INDEX_EXT 0x8009 + +#define GLXEW_EXT_visual_info GLXEW_GET_VAR(__GLXEW_EXT_visual_info) + +#endif /* GLX_EXT_visual_info */ + +/* ------------------------- GLX_EXT_visual_rating ------------------------- */ + +#ifndef GLX_EXT_visual_rating +#define GLX_EXT_visual_rating 1 + +#define GLX_VISUAL_CAVEAT_EXT 0x20 +#define GLX_SLOW_VISUAL_EXT 0x8001 +#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D + +#define GLXEW_EXT_visual_rating GLXEW_GET_VAR(__GLXEW_EXT_visual_rating) + +#endif /* GLX_EXT_visual_rating */ + +/* -------------------------- GLX_MESA_agp_offset -------------------------- */ + +#ifndef GLX_MESA_agp_offset +#define GLX_MESA_agp_offset 1 + +typedef unsigned int ( * PFNGLXGETAGPOFFSETMESAPROC) (const void* pointer); + +#define glXGetAGPOffsetMESA GLXEW_GET_FUN(__glewXGetAGPOffsetMESA) + +#define GLXEW_MESA_agp_offset GLXEW_GET_VAR(__GLXEW_MESA_agp_offset) + +#endif /* GLX_MESA_agp_offset */ + +/* ------------------------ GLX_MESA_copy_sub_buffer ----------------------- */ + +#ifndef GLX_MESA_copy_sub_buffer +#define GLX_MESA_copy_sub_buffer 1 + +typedef void ( * PFNGLXCOPYSUBBUFFERMESAPROC) (Display* dpy, GLXDrawable drawable, int x, int y, int width, int height); + +#define glXCopySubBufferMESA GLXEW_GET_FUN(__glewXCopySubBufferMESA) + +#define GLXEW_MESA_copy_sub_buffer GLXEW_GET_VAR(__GLXEW_MESA_copy_sub_buffer) + +#endif /* GLX_MESA_copy_sub_buffer */ + +/* ------------------------ GLX_MESA_pixmap_colormap ----------------------- */ + +#ifndef GLX_MESA_pixmap_colormap +#define GLX_MESA_pixmap_colormap 1 + +typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display* dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap); + +#define glXCreateGLXPixmapMESA GLXEW_GET_FUN(__glewXCreateGLXPixmapMESA) + +#define GLXEW_MESA_pixmap_colormap GLXEW_GET_VAR(__GLXEW_MESA_pixmap_colormap) + +#endif /* GLX_MESA_pixmap_colormap */ + +/* ------------------------ GLX_MESA_release_buffers ----------------------- */ + +#ifndef GLX_MESA_release_buffers +#define GLX_MESA_release_buffers 1 + +typedef Bool ( * PFNGLXRELEASEBUFFERSMESAPROC) (Display* dpy, GLXDrawable d); + +#define glXReleaseBuffersMESA GLXEW_GET_FUN(__glewXReleaseBuffersMESA) + +#define GLXEW_MESA_release_buffers GLXEW_GET_VAR(__GLXEW_MESA_release_buffers) + +#endif /* GLX_MESA_release_buffers */ + +/* ------------------------- GLX_MESA_set_3dfx_mode ------------------------ */ + +#ifndef GLX_MESA_set_3dfx_mode +#define GLX_MESA_set_3dfx_mode 1 + +#define GLX_3DFX_WINDOW_MODE_MESA 0x1 +#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2 + +typedef GLboolean ( * PFNGLXSET3DFXMODEMESAPROC) (GLint mode); + +#define glXSet3DfxModeMESA GLXEW_GET_FUN(__glewXSet3DfxModeMESA) + +#define GLXEW_MESA_set_3dfx_mode GLXEW_GET_VAR(__GLXEW_MESA_set_3dfx_mode) + +#endif /* GLX_MESA_set_3dfx_mode */ + +/* -------------------------- GLX_NV_float_buffer -------------------------- */ + +#ifndef GLX_NV_float_buffer +#define GLX_NV_float_buffer 1 + +#define GLX_FLOAT_COMPONENTS_NV 0x20B0 + +#define GLXEW_NV_float_buffer GLXEW_GET_VAR(__GLXEW_NV_float_buffer) + +#endif /* GLX_NV_float_buffer */ + +/* -------------------------- GLX_NV_present_video ------------------------- */ + +#ifndef GLX_NV_present_video +#define GLX_NV_present_video 1 + +#define GLX_NUM_VIDEO_SLOTS_NV 0x20F0 + +typedef int ( * PFNGLXBINDVIDEODEVICENVPROC) (Display* dpy, unsigned int video_slot, unsigned int video_device, const int *attrib_list); +typedef unsigned int* ( * PFNGLXENUMERATEVIDEODEVICESNVPROC) (Display *dpy, int screen, int *nelements); + +#define glXBindVideoDeviceNV GLXEW_GET_FUN(__glewXBindVideoDeviceNV) +#define glXEnumerateVideoDevicesNV GLXEW_GET_FUN(__glewXEnumerateVideoDevicesNV) + +#define GLXEW_NV_present_video GLXEW_GET_VAR(__GLXEW_NV_present_video) + +#endif /* GLX_NV_present_video */ + +/* --------------------------- GLX_NV_swap_group --------------------------- */ + +#ifndef GLX_NV_swap_group +#define GLX_NV_swap_group 1 + +typedef Bool ( * PFNGLXBINDSWAPBARRIERNVPROC) (Display* dpy, GLuint group, GLuint barrier); +typedef Bool ( * PFNGLXJOINSWAPGROUPNVPROC) (Display* dpy, GLXDrawable drawable, GLuint group); +typedef Bool ( * PFNGLXQUERYFRAMECOUNTNVPROC) (Display* dpy, int screen, GLuint *count); +typedef Bool ( * PFNGLXQUERYMAXSWAPGROUPSNVPROC) (Display* dpy, int screen, GLuint *maxGroups, GLuint *maxBarriers); +typedef Bool ( * PFNGLXQUERYSWAPGROUPNVPROC) (Display* dpy, GLXDrawable drawable, GLuint *group, GLuint *barrier); +typedef Bool ( * PFNGLXRESETFRAMECOUNTNVPROC) (Display* dpy, int screen); + +#define glXBindSwapBarrierNV GLXEW_GET_FUN(__glewXBindSwapBarrierNV) +#define glXJoinSwapGroupNV GLXEW_GET_FUN(__glewXJoinSwapGroupNV) +#define glXQueryFrameCountNV GLXEW_GET_FUN(__glewXQueryFrameCountNV) +#define glXQueryMaxSwapGroupsNV GLXEW_GET_FUN(__glewXQueryMaxSwapGroupsNV) +#define glXQuerySwapGroupNV GLXEW_GET_FUN(__glewXQuerySwapGroupNV) +#define glXResetFrameCountNV GLXEW_GET_FUN(__glewXResetFrameCountNV) + +#define GLXEW_NV_swap_group GLXEW_GET_VAR(__GLXEW_NV_swap_group) + +#endif /* GLX_NV_swap_group */ + +/* ----------------------- GLX_NV_vertex_array_range ----------------------- */ + +#ifndef GLX_NV_vertex_array_range +#define GLX_NV_vertex_array_range 1 + +typedef void * ( * PFNGLXALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority); +typedef void ( * PFNGLXFREEMEMORYNVPROC) (void *pointer); + +#define glXAllocateMemoryNV GLXEW_GET_FUN(__glewXAllocateMemoryNV) +#define glXFreeMemoryNV GLXEW_GET_FUN(__glewXFreeMemoryNV) + +#define GLXEW_NV_vertex_array_range GLXEW_GET_VAR(__GLXEW_NV_vertex_array_range) + +#endif /* GLX_NV_vertex_array_range */ + +/* -------------------------- GLX_NV_video_output -------------------------- */ + +#ifndef GLX_NV_video_output +#define GLX_NV_video_output 1 + +#define GLX_VIDEO_OUT_COLOR_NV 0x20C3 +#define GLX_VIDEO_OUT_ALPHA_NV 0x20C4 +#define GLX_VIDEO_OUT_DEPTH_NV 0x20C5 +#define GLX_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 +#define GLX_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 +#define GLX_VIDEO_OUT_FRAME_NV 0x20C8 +#define GLX_VIDEO_OUT_FIELD_1_NV 0x20C9 +#define GLX_VIDEO_OUT_FIELD_2_NV 0x20CA +#define GLX_VIDEO_OUT_STACKED_FIELDS_1_2_NV 0x20CB +#define GLX_VIDEO_OUT_STACKED_FIELDS_2_1_NV 0x20CC + +typedef int ( * PFNGLXBINDVIDEOIMAGENVPROC) (Display* dpy, GLXVideoDeviceNV VideoDevice, GLXPbuffer pbuf, int iVideoBuffer); +typedef int ( * PFNGLXGETVIDEODEVICENVPROC) (Display* dpy, int screen, int numVideoDevices, GLXVideoDeviceNV *pVideoDevice); +typedef int ( * PFNGLXGETVIDEOINFONVPROC) (Display* dpy, int screen, GLXVideoDeviceNV VideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); +typedef int ( * PFNGLXRELEASEVIDEODEVICENVPROC) (Display* dpy, int screen, GLXVideoDeviceNV VideoDevice); +typedef int ( * PFNGLXRELEASEVIDEOIMAGENVPROC) (Display* dpy, GLXPbuffer pbuf); +typedef int ( * PFNGLXSENDPBUFFERTOVIDEONVPROC) (Display* dpy, GLXPbuffer pbuf, int iBufferType, unsigned long *pulCounterPbuffer, GLboolean bBlock); + +#define glXBindVideoImageNV GLXEW_GET_FUN(__glewXBindVideoImageNV) +#define glXGetVideoDeviceNV GLXEW_GET_FUN(__glewXGetVideoDeviceNV) +#define glXGetVideoInfoNV GLXEW_GET_FUN(__glewXGetVideoInfoNV) +#define glXReleaseVideoDeviceNV GLXEW_GET_FUN(__glewXReleaseVideoDeviceNV) +#define glXReleaseVideoImageNV GLXEW_GET_FUN(__glewXReleaseVideoImageNV) +#define glXSendPbufferToVideoNV GLXEW_GET_FUN(__glewXSendPbufferToVideoNV) + +#define GLXEW_NV_video_output GLXEW_GET_VAR(__GLXEW_NV_video_output) + +#endif /* GLX_NV_video_output */ + +/* -------------------------- GLX_OML_swap_method -------------------------- */ + +#ifndef GLX_OML_swap_method +#define GLX_OML_swap_method 1 + +#define GLX_SWAP_METHOD_OML 0x8060 +#define GLX_SWAP_EXCHANGE_OML 0x8061 +#define GLX_SWAP_COPY_OML 0x8062 +#define GLX_SWAP_UNDEFINED_OML 0x8063 + +#define GLXEW_OML_swap_method GLXEW_GET_VAR(__GLXEW_OML_swap_method) + +#endif /* GLX_OML_swap_method */ + +/* -------------------------- GLX_OML_sync_control ------------------------- */ + +#if !defined(GLX_OML_sync_control) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +#include +#define GLX_OML_sync_control 1 + +typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display* dpy, GLXDrawable drawable, int32_t* numerator, int32_t* denominator); +typedef Bool ( * PFNGLXGETSYNCVALUESOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t* ust, int64_t* msc, int64_t* sbc); +typedef int64_t ( * PFNGLXSWAPBUFFERSMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder); +typedef Bool ( * PFNGLXWAITFORMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t* ust, int64_t* msc, int64_t* sbc); +typedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_sbc, int64_t* ust, int64_t* msc, int64_t* sbc); + +#define glXGetMscRateOML GLXEW_GET_FUN(__glewXGetMscRateOML) +#define glXGetSyncValuesOML GLXEW_GET_FUN(__glewXGetSyncValuesOML) +#define glXSwapBuffersMscOML GLXEW_GET_FUN(__glewXSwapBuffersMscOML) +#define glXWaitForMscOML GLXEW_GET_FUN(__glewXWaitForMscOML) +#define glXWaitForSbcOML GLXEW_GET_FUN(__glewXWaitForSbcOML) + +#define GLXEW_OML_sync_control GLXEW_GET_VAR(__GLXEW_OML_sync_control) + +#endif /* GLX_OML_sync_control */ + +/* ------------------------ GLX_SGIS_blended_overlay ----------------------- */ + +#ifndef GLX_SGIS_blended_overlay +#define GLX_SGIS_blended_overlay 1 + +#define GLX_BLENDED_RGBA_SGIS 0x8025 + +#define GLXEW_SGIS_blended_overlay GLXEW_GET_VAR(__GLXEW_SGIS_blended_overlay) + +#endif /* GLX_SGIS_blended_overlay */ + +/* -------------------------- GLX_SGIS_color_range ------------------------- */ + +#ifndef GLX_SGIS_color_range +#define GLX_SGIS_color_range 1 + +#define GLX_MIN_RED_SGIS 0 +#define GLX_MAX_GREEN_SGIS 0 +#define GLX_MIN_BLUE_SGIS 0 +#define GLX_MAX_ALPHA_SGIS 0 +#define GLX_MIN_GREEN_SGIS 0 +#define GLX_MIN_ALPHA_SGIS 0 +#define GLX_MAX_RED_SGIS 0 +#define GLX_EXTENDED_RANGE_SGIS 0 +#define GLX_MAX_BLUE_SGIS 0 + +#define GLXEW_SGIS_color_range GLXEW_GET_VAR(__GLXEW_SGIS_color_range) + +#endif /* GLX_SGIS_color_range */ + +/* -------------------------- GLX_SGIS_multisample ------------------------- */ + +#ifndef GLX_SGIS_multisample +#define GLX_SGIS_multisample 1 + +#define GLX_SAMPLE_BUFFERS_SGIS 100000 +#define GLX_SAMPLES_SGIS 100001 + +#define GLXEW_SGIS_multisample GLXEW_GET_VAR(__GLXEW_SGIS_multisample) + +#endif /* GLX_SGIS_multisample */ + +/* ---------------------- GLX_SGIS_shared_multisample ---------------------- */ + +#ifndef GLX_SGIS_shared_multisample +#define GLX_SGIS_shared_multisample 1 + +#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026 +#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027 + +#define GLXEW_SGIS_shared_multisample GLXEW_GET_VAR(__GLXEW_SGIS_shared_multisample) + +#endif /* GLX_SGIS_shared_multisample */ + +/* --------------------------- GLX_SGIX_fbconfig --------------------------- */ + +#ifndef GLX_SGIX_fbconfig +#define GLX_SGIX_fbconfig 1 + +#define GLX_WINDOW_BIT_SGIX 0x00000001 +#define GLX_RGBA_BIT_SGIX 0x00000001 +#define GLX_PIXMAP_BIT_SGIX 0x00000002 +#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002 +#define GLX_SCREEN_EXT 0x800C +#define GLX_DRAWABLE_TYPE_SGIX 0x8010 +#define GLX_RENDER_TYPE_SGIX 0x8011 +#define GLX_X_RENDERABLE_SGIX 0x8012 +#define GLX_FBCONFIG_ID_SGIX 0x8013 +#define GLX_RGBA_TYPE_SGIX 0x8014 +#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015 + +typedef XID GLXFBConfigIDSGIX; +typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; + +typedef GLXFBConfigSGIX* ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); +typedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, Pixmap pixmap); +typedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display* dpy, GLXFBConfigSGIX config, int attribute, int *value); +typedef GLXFBConfigSGIX ( * PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (Display* dpy, XVisualInfo *vis); +typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfig config); + +#define glXChooseFBConfigSGIX GLXEW_GET_FUN(__glewXChooseFBConfigSGIX) +#define glXCreateContextWithConfigSGIX GLXEW_GET_FUN(__glewXCreateContextWithConfigSGIX) +#define glXCreateGLXPixmapWithConfigSGIX GLXEW_GET_FUN(__glewXCreateGLXPixmapWithConfigSGIX) +#define glXGetFBConfigAttribSGIX GLXEW_GET_FUN(__glewXGetFBConfigAttribSGIX) +#define glXGetFBConfigFromVisualSGIX GLXEW_GET_FUN(__glewXGetFBConfigFromVisualSGIX) +#define glXGetVisualFromFBConfigSGIX GLXEW_GET_FUN(__glewXGetVisualFromFBConfigSGIX) + +#define GLXEW_SGIX_fbconfig GLXEW_GET_VAR(__GLXEW_SGIX_fbconfig) + +#endif /* GLX_SGIX_fbconfig */ + +/* --------------------------- GLX_SGIX_hyperpipe -------------------------- */ + +#ifndef GLX_SGIX_hyperpipe +#define GLX_SGIX_hyperpipe 1 + +#define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001 +#define GLX_PIPE_RECT_SGIX 0x00000001 +#define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002 +#define GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002 +#define GLX_HYPERPIPE_STEREO_SGIX 0x00000003 +#define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004 +#define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80 +#define GLX_BAD_HYPERPIPE_CONFIG_SGIX 91 +#define GLX_BAD_HYPERPIPE_SGIX 92 +#define GLX_HYPERPIPE_ID_SGIX 0x8030 + +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int networkId; +} GLXHyperpipeNetworkSGIX; +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int XOrigin; + int YOrigin; + int maxHeight; + int maxWidth; +} GLXPipeRectLimits; +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int channel; + unsigned int participationType; + int timeSlice; +} GLXHyperpipeConfigSGIX; +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int srcXOrigin; + int srcYOrigin; + int srcWidth; + int srcHeight; + int destXOrigin; + int destYOrigin; + int destWidth; + int destHeight; +} GLXPipeRect; + +typedef int ( * PFNGLXBINDHYPERPIPESGIXPROC) (Display *dpy, int hpId); +typedef int ( * PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId); +typedef int ( * PFNGLXHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList); +typedef int ( * PFNGLXHYPERPIPECONFIGSGIXPROC) (Display *dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId); +typedef int ( * PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *returnAttribList); +typedef int ( * PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList, void *returnAttribList); +typedef GLXHyperpipeConfigSGIX * ( * PFNGLXQUERYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId, int *npipes); +typedef GLXHyperpipeNetworkSGIX * ( * PFNGLXQUERYHYPERPIPENETWORKSGIXPROC) (Display *dpy, int *npipes); + +#define glXBindHyperpipeSGIX GLXEW_GET_FUN(__glewXBindHyperpipeSGIX) +#define glXDestroyHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXDestroyHyperpipeConfigSGIX) +#define glXHyperpipeAttribSGIX GLXEW_GET_FUN(__glewXHyperpipeAttribSGIX) +#define glXHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXHyperpipeConfigSGIX) +#define glXQueryHyperpipeAttribSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeAttribSGIX) +#define glXQueryHyperpipeBestAttribSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeBestAttribSGIX) +#define glXQueryHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeConfigSGIX) +#define glXQueryHyperpipeNetworkSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeNetworkSGIX) + +#define GLXEW_SGIX_hyperpipe GLXEW_GET_VAR(__GLXEW_SGIX_hyperpipe) + +#endif /* GLX_SGIX_hyperpipe */ + +/* ---------------------------- GLX_SGIX_pbuffer --------------------------- */ + +#ifndef GLX_SGIX_pbuffer +#define GLX_SGIX_pbuffer 1 + +#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002 +#define GLX_PBUFFER_BIT_SGIX 0x00000004 +#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008 +#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010 +#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020 +#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040 +#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080 +#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100 +#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017 +#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018 +#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019 +#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A +#define GLX_PRESERVED_CONTENTS_SGIX 0x801B +#define GLX_LARGEST_PBUFFER_SGIX 0x801C +#define GLX_WIDTH_SGIX 0x801D +#define GLX_HEIGHT_SGIX 0x801E +#define GLX_EVENT_MASK_SGIX 0x801F +#define GLX_DAMAGED_SGIX 0x8020 +#define GLX_SAVED_SGIX 0x8021 +#define GLX_WINDOW_SGIX 0x8022 +#define GLX_PBUFFER_SGIX 0x8023 +#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000 + +typedef XID GLXPbufferSGIX; +typedef struct { int type; unsigned long serial; Bool send_event; Display *display; GLXDrawable drawable; int event_type; int draw_type; unsigned int mask; int x, y; int width, height; int count; } GLXBufferClobberEventSGIX; + +typedef GLXPbuffer ( * PFNGLXCREATEGLXPBUFFERSGIXPROC) (Display* dpy, GLXFBConfig config, unsigned int width, unsigned int height, int *attrib_list); +typedef void ( * PFNGLXDESTROYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf); +typedef void ( * PFNGLXGETSELECTEDEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long *mask); +typedef void ( * PFNGLXQUERYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf, int attribute, unsigned int *value); +typedef void ( * PFNGLXSELECTEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long mask); + +#define glXCreateGLXPbufferSGIX GLXEW_GET_FUN(__glewXCreateGLXPbufferSGIX) +#define glXDestroyGLXPbufferSGIX GLXEW_GET_FUN(__glewXDestroyGLXPbufferSGIX) +#define glXGetSelectedEventSGIX GLXEW_GET_FUN(__glewXGetSelectedEventSGIX) +#define glXQueryGLXPbufferSGIX GLXEW_GET_FUN(__glewXQueryGLXPbufferSGIX) +#define glXSelectEventSGIX GLXEW_GET_FUN(__glewXSelectEventSGIX) + +#define GLXEW_SGIX_pbuffer GLXEW_GET_VAR(__GLXEW_SGIX_pbuffer) + +#endif /* GLX_SGIX_pbuffer */ + +/* ------------------------- GLX_SGIX_swap_barrier ------------------------- */ + +#ifndef GLX_SGIX_swap_barrier +#define GLX_SGIX_swap_barrier 1 + +typedef void ( * PFNGLXBINDSWAPBARRIERSGIXPROC) (Display *dpy, GLXDrawable drawable, int barrier); +typedef Bool ( * PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (Display *dpy, int screen, int *max); + +#define glXBindSwapBarrierSGIX GLXEW_GET_FUN(__glewXBindSwapBarrierSGIX) +#define glXQueryMaxSwapBarriersSGIX GLXEW_GET_FUN(__glewXQueryMaxSwapBarriersSGIX) + +#define GLXEW_SGIX_swap_barrier GLXEW_GET_VAR(__GLXEW_SGIX_swap_barrier) + +#endif /* GLX_SGIX_swap_barrier */ + +/* -------------------------- GLX_SGIX_swap_group -------------------------- */ + +#ifndef GLX_SGIX_swap_group +#define GLX_SGIX_swap_group 1 + +typedef void ( * PFNGLXJOINSWAPGROUPSGIXPROC) (Display *dpy, GLXDrawable drawable, GLXDrawable member); + +#define glXJoinSwapGroupSGIX GLXEW_GET_FUN(__glewXJoinSwapGroupSGIX) + +#define GLXEW_SGIX_swap_group GLXEW_GET_VAR(__GLXEW_SGIX_swap_group) + +#endif /* GLX_SGIX_swap_group */ + +/* ------------------------- GLX_SGIX_video_resize ------------------------- */ + +#ifndef GLX_SGIX_video_resize +#define GLX_SGIX_video_resize 1 + +#define GLX_SYNC_FRAME_SGIX 0x00000000 +#define GLX_SYNC_SWAP_SGIX 0x00000001 + +typedef int ( * PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (Display* display, int screen, int channel, Window window); +typedef int ( * PFNGLXCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int x, int y, int w, int h); +typedef int ( * PFNGLXCHANNELRECTSYNCSGIXPROC) (Display* display, int screen, int channel, GLenum synctype); +typedef int ( * PFNGLXQUERYCHANNELDELTASSGIXPROC) (Display* display, int screen, int channel, int *x, int *y, int *w, int *h); +typedef int ( * PFNGLXQUERYCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int *dx, int *dy, int *dw, int *dh); + +#define glXBindChannelToWindowSGIX GLXEW_GET_FUN(__glewXBindChannelToWindowSGIX) +#define glXChannelRectSGIX GLXEW_GET_FUN(__glewXChannelRectSGIX) +#define glXChannelRectSyncSGIX GLXEW_GET_FUN(__glewXChannelRectSyncSGIX) +#define glXQueryChannelDeltasSGIX GLXEW_GET_FUN(__glewXQueryChannelDeltasSGIX) +#define glXQueryChannelRectSGIX GLXEW_GET_FUN(__glewXQueryChannelRectSGIX) + +#define GLXEW_SGIX_video_resize GLXEW_GET_VAR(__GLXEW_SGIX_video_resize) + +#endif /* GLX_SGIX_video_resize */ + +/* ---------------------- GLX_SGIX_visual_select_group --------------------- */ + +#ifndef GLX_SGIX_visual_select_group +#define GLX_SGIX_visual_select_group 1 + +#define GLX_VISUAL_SELECT_GROUP_SGIX 0x8028 + +#define GLXEW_SGIX_visual_select_group GLXEW_GET_VAR(__GLXEW_SGIX_visual_select_group) + +#endif /* GLX_SGIX_visual_select_group */ + +/* ---------------------------- GLX_SGI_cushion ---------------------------- */ + +#ifndef GLX_SGI_cushion +#define GLX_SGI_cushion 1 + +typedef void ( * PFNGLXCUSHIONSGIPROC) (Display* dpy, Window window, float cushion); + +#define glXCushionSGI GLXEW_GET_FUN(__glewXCushionSGI) + +#define GLXEW_SGI_cushion GLXEW_GET_VAR(__GLXEW_SGI_cushion) + +#endif /* GLX_SGI_cushion */ + +/* ----------------------- GLX_SGI_make_current_read ----------------------- */ + +#ifndef GLX_SGI_make_current_read +#define GLX_SGI_make_current_read 1 + +typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void); +typedef Bool ( * PFNGLXMAKECURRENTREADSGIPROC) (Display* dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); + +#define glXGetCurrentReadDrawableSGI GLXEW_GET_FUN(__glewXGetCurrentReadDrawableSGI) +#define glXMakeCurrentReadSGI GLXEW_GET_FUN(__glewXMakeCurrentReadSGI) + +#define GLXEW_SGI_make_current_read GLXEW_GET_VAR(__GLXEW_SGI_make_current_read) + +#endif /* GLX_SGI_make_current_read */ + +/* -------------------------- GLX_SGI_swap_control ------------------------- */ + +#ifndef GLX_SGI_swap_control +#define GLX_SGI_swap_control 1 + +typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval); + +#define glXSwapIntervalSGI GLXEW_GET_FUN(__glewXSwapIntervalSGI) + +#define GLXEW_SGI_swap_control GLXEW_GET_VAR(__GLXEW_SGI_swap_control) + +#endif /* GLX_SGI_swap_control */ + +/* --------------------------- GLX_SGI_video_sync -------------------------- */ + +#ifndef GLX_SGI_video_sync +#define GLX_SGI_video_sync 1 + +typedef int ( * PFNGLXGETVIDEOSYNCSGIPROC) (uint* count); +typedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int* count); + +#define glXGetVideoSyncSGI GLXEW_GET_FUN(__glewXGetVideoSyncSGI) +#define glXWaitVideoSyncSGI GLXEW_GET_FUN(__glewXWaitVideoSyncSGI) + +#define GLXEW_SGI_video_sync GLXEW_GET_VAR(__GLXEW_SGI_video_sync) + +#endif /* GLX_SGI_video_sync */ + +/* --------------------- GLX_SUN_get_transparent_index --------------------- */ + +#ifndef GLX_SUN_get_transparent_index +#define GLX_SUN_get_transparent_index 1 + +typedef Status ( * PFNGLXGETTRANSPARENTINDEXSUNPROC) (Display* dpy, Window overlay, Window underlay, unsigned long *pTransparentIndex); + +#define glXGetTransparentIndexSUN GLXEW_GET_FUN(__glewXGetTransparentIndexSUN) + +#define GLXEW_SUN_get_transparent_index GLXEW_GET_VAR(__GLXEW_SUN_get_transparent_index) + +#endif /* GLX_SUN_get_transparent_index */ + +/* -------------------------- GLX_SUN_video_resize ------------------------- */ + +#ifndef GLX_SUN_video_resize +#define GLX_SUN_video_resize 1 + +#define GLX_VIDEO_RESIZE_SUN 0x8171 +#define GL_VIDEO_RESIZE_COMPENSATION_SUN 0x85CD + +typedef int ( * PFNGLXGETVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float* factor); +typedef int ( * PFNGLXVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float factor); + +#define glXGetVideoResizeSUN GLXEW_GET_FUN(__glewXGetVideoResizeSUN) +#define glXVideoResizeSUN GLXEW_GET_FUN(__glewXVideoResizeSUN) + +#define GLXEW_SUN_video_resize GLXEW_GET_VAR(__GLXEW_SUN_video_resize) + +#endif /* GLX_SUN_video_resize */ + +/* ------------------------------------------------------------------------- */ + +#ifdef GLEW_MX +#define GLXEW_EXPORT +#else +#define GLXEW_EXPORT extern +#endif /* GLEW_MX */ + +extern PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay; + +extern PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig; +extern PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext; +extern PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer; +extern PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap; +extern PFNGLXCREATEWINDOWPROC __glewXCreateWindow; +extern PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer; +extern PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap; +extern PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow; +extern PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable; +extern PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib; +extern PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs; +extern PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent; +extern PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig; +extern PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent; +extern PFNGLXQUERYCONTEXTPROC __glewXQueryContext; +extern PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable; +extern PFNGLXSELECTEVENTPROC __glewXSelectEvent; + +extern PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB; + +extern PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI; +extern PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI; +extern PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI; + +extern PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT; +extern PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT; +extern PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT; +extern PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT; + +extern PFNGLXBINDTEXIMAGEEXTPROC __glewXBindTexImageEXT; +extern PFNGLXRELEASETEXIMAGEEXTPROC __glewXReleaseTexImageEXT; + +extern PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA; + +extern PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA; + +extern PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA; + +extern PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA; + +extern PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA; + +extern PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV; +extern PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV; + +extern PFNGLXBINDSWAPBARRIERNVPROC __glewXBindSwapBarrierNV; +extern PFNGLXJOINSWAPGROUPNVPROC __glewXJoinSwapGroupNV; +extern PFNGLXQUERYFRAMECOUNTNVPROC __glewXQueryFrameCountNV; +extern PFNGLXQUERYMAXSWAPGROUPSNVPROC __glewXQueryMaxSwapGroupsNV; +extern PFNGLXQUERYSWAPGROUPNVPROC __glewXQuerySwapGroupNV; +extern PFNGLXRESETFRAMECOUNTNVPROC __glewXResetFrameCountNV; + +extern PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV; +extern PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV; + +extern PFNGLXBINDVIDEOIMAGENVPROC __glewXBindVideoImageNV; +extern PFNGLXGETVIDEODEVICENVPROC __glewXGetVideoDeviceNV; +extern PFNGLXGETVIDEOINFONVPROC __glewXGetVideoInfoNV; +extern PFNGLXRELEASEVIDEODEVICENVPROC __glewXReleaseVideoDeviceNV; +extern PFNGLXRELEASEVIDEOIMAGENVPROC __glewXReleaseVideoImageNV; +extern PFNGLXSENDPBUFFERTOVIDEONVPROC __glewXSendPbufferToVideoNV; + +#ifdef GLX_OML_sync_control +extern PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML; +extern PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML; +extern PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML; +extern PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML; +extern PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML; +#endif + +extern PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX; +extern PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX; +extern PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX; +extern PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX; +extern PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX; +extern PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX; + +extern PFNGLXBINDHYPERPIPESGIXPROC __glewXBindHyperpipeSGIX; +extern PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC __glewXDestroyHyperpipeConfigSGIX; +extern PFNGLXHYPERPIPEATTRIBSGIXPROC __glewXHyperpipeAttribSGIX; +extern PFNGLXHYPERPIPECONFIGSGIXPROC __glewXHyperpipeConfigSGIX; +extern PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC __glewXQueryHyperpipeAttribSGIX; +extern PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC __glewXQueryHyperpipeBestAttribSGIX; +extern PFNGLXQUERYHYPERPIPECONFIGSGIXPROC __glewXQueryHyperpipeConfigSGIX; +extern PFNGLXQUERYHYPERPIPENETWORKSGIXPROC __glewXQueryHyperpipeNetworkSGIX; + +extern PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX; +extern PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX; +extern PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX; +extern PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX; +extern PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX; + +extern PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX; +extern PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX; + +extern PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX; + +extern PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX; +extern PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX; +extern PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX; +extern PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX; +extern PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX; + +extern PFNGLXCUSHIONSGIPROC __glewXCushionSGI; + +extern PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI; +extern PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI; + +extern PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI; + +extern PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI; +extern PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI; + +extern PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN; + +extern PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN; +extern PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN; + +#if defined(GLEW_MX) +struct GLXEWContextStruct +{ +#endif /* GLEW_MX */ + +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_0; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_1; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_2; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_3; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_4; +GLXEW_EXPORT GLboolean __GLXEW_3DFX_multisample; +GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context; +GLXEW_EXPORT GLboolean __GLXEW_ARB_fbconfig_float; +GLXEW_EXPORT GLboolean __GLXEW_ARB_framebuffer_sRGB; +GLXEW_EXPORT GLboolean __GLXEW_ARB_get_proc_address; +GLXEW_EXPORT GLboolean __GLXEW_ARB_multisample; +GLXEW_EXPORT GLboolean __GLXEW_ATI_pixel_format_float; +GLXEW_EXPORT GLboolean __GLXEW_ATI_render_texture; +GLXEW_EXPORT GLboolean __GLXEW_EXT_fbconfig_packed_float; +GLXEW_EXPORT GLboolean __GLXEW_EXT_framebuffer_sRGB; +GLXEW_EXPORT GLboolean __GLXEW_EXT_import_context; +GLXEW_EXPORT GLboolean __GLXEW_EXT_scene_marker; +GLXEW_EXPORT GLboolean __GLXEW_EXT_texture_from_pixmap; +GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_info; +GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_rating; +GLXEW_EXPORT GLboolean __GLXEW_MESA_agp_offset; +GLXEW_EXPORT GLboolean __GLXEW_MESA_copy_sub_buffer; +GLXEW_EXPORT GLboolean __GLXEW_MESA_pixmap_colormap; +GLXEW_EXPORT GLboolean __GLXEW_MESA_release_buffers; +GLXEW_EXPORT GLboolean __GLXEW_MESA_set_3dfx_mode; +GLXEW_EXPORT GLboolean __GLXEW_NV_float_buffer; +GLXEW_EXPORT GLboolean __GLXEW_NV_present_video; +GLXEW_EXPORT GLboolean __GLXEW_NV_swap_group; +GLXEW_EXPORT GLboolean __GLXEW_NV_vertex_array_range; +GLXEW_EXPORT GLboolean __GLXEW_NV_video_output; +GLXEW_EXPORT GLboolean __GLXEW_OML_swap_method; +GLXEW_EXPORT GLboolean __GLXEW_OML_sync_control; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_blended_overlay; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_color_range; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_multisample; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_shared_multisample; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_fbconfig; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_hyperpipe; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_pbuffer; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_barrier; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_group; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_video_resize; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_visual_select_group; +GLXEW_EXPORT GLboolean __GLXEW_SGI_cushion; +GLXEW_EXPORT GLboolean __GLXEW_SGI_make_current_read; +GLXEW_EXPORT GLboolean __GLXEW_SGI_swap_control; +GLXEW_EXPORT GLboolean __GLXEW_SGI_video_sync; +GLXEW_EXPORT GLboolean __GLXEW_SUN_get_transparent_index; +GLXEW_EXPORT GLboolean __GLXEW_SUN_video_resize; + +#ifdef GLEW_MX +}; /* GLXEWContextStruct */ +#endif /* GLEW_MX */ + +/* ------------------------------------------------------------------------ */ + +#ifdef GLEW_MX + +typedef struct GLXEWContextStruct GLXEWContext; +extern GLenum glxewContextInit (GLXEWContext* ctx); +extern GLboolean glxewContextIsSupported (GLXEWContext* ctx, const char* name); + +#define glxewInit() glxewContextInit(glxewGetContext()) +#define glxewIsSupported(x) glxewContextIsSupported(glxewGetContext(), x) + +#define GLXEW_GET_VAR(x) (*(const GLboolean*)&(glxewGetContext()->x)) +#define GLXEW_GET_FUN(x) x + +#else /* GLEW_MX */ + +#define GLXEW_GET_VAR(x) (*(const GLboolean*)&x) +#define GLXEW_GET_FUN(x) x + +extern GLboolean glxewIsSupported (const char* name); + +#endif /* GLEW_MX */ + +extern GLboolean glxewGetExtension (const char* name); + +#ifdef __cplusplus +} +#endif + +#endif /* __glxew_h__ */ diff --git a/test_conformance/gl/GLEW/GL/wglew.h b/test_conformance/gl/GLEW/GL/wglew.h new file mode 100644 index 00000000..7f802761 --- /dev/null +++ b/test_conformance/gl/GLEW/GL/wglew.h @@ -0,0 +1,1165 @@ +/* +** The OpenGL Extension Wrangler Library +** Copyright (C) 2002-2008, Milan Ikits +** Copyright (C) 2002-2008, Marcelo E. Magallon +** Copyright (C) 2002, Lev Povalahev +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** * The name of the author may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +** THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* +** Copyright (c) 2007 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#ifndef __wglew_h__ +#define __wglew_h__ +#define __WGLEW_H__ + +#ifdef __wglext_h_ +#error wglext.h included before wglew.h +#endif + +#define __wglext_h_ + +#if !defined(APIENTRY) && !defined(__CYGWIN__) +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif +#include +#endif + +/* + * GLEW_STATIC needs to be set when using the static version. + * GLEW_BUILD is set when building the DLL version. + */ +#ifdef GLEW_STATIC +# define GLEWAPI extern +#else +# ifdef GLEW_BUILD +# define GLEWAPI extern __declspec(dllexport) +# else +# define GLEWAPI extern __declspec(dllimport) +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* -------------------------- WGL_3DFX_multisample ------------------------- */ + +#ifndef WGL_3DFX_multisample +#define WGL_3DFX_multisample 1 + +#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 +#define WGL_SAMPLES_3DFX 0x2061 + +#define WGLEW_3DFX_multisample WGLEW_GET_VAR(__WGLEW_3DFX_multisample) + +#endif /* WGL_3DFX_multisample */ + +/* ------------------------- WGL_3DL_stereo_control ------------------------ */ + +#ifndef WGL_3DL_stereo_control +#define WGL_3DL_stereo_control 1 + +#define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055 +#define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056 +#define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057 +#define WGL_STEREO_POLARITY_INVERT_3DL 0x2058 + +typedef BOOL (WINAPI * PFNWGLSETSTEREOEMITTERSTATE3DLPROC) (HDC hDC, UINT uState); + +#define wglSetStereoEmitterState3DL WGLEW_GET_FUN(__wglewSetStereoEmitterState3DL) + +#define WGLEW_3DL_stereo_control WGLEW_GET_VAR(__WGLEW_3DL_stereo_control) + +#endif /* WGL_3DL_stereo_control */ + +/* ------------------------- WGL_ARB_buffer_region ------------------------- */ + +#ifndef WGL_ARB_buffer_region +#define WGL_ARB_buffer_region 1 + +#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 +#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 +#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 +#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 + +typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); +typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); +typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); +typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); + +#define wglCreateBufferRegionARB WGLEW_GET_FUN(__wglewCreateBufferRegionARB) +#define wglDeleteBufferRegionARB WGLEW_GET_FUN(__wglewDeleteBufferRegionARB) +#define wglRestoreBufferRegionARB WGLEW_GET_FUN(__wglewRestoreBufferRegionARB) +#define wglSaveBufferRegionARB WGLEW_GET_FUN(__wglewSaveBufferRegionARB) + +#define WGLEW_ARB_buffer_region WGLEW_GET_VAR(__WGLEW_ARB_buffer_region) + +#endif /* WGL_ARB_buffer_region */ + +/* ------------------------- WGL_ARB_create_context ------------------------ */ + +#ifndef WGL_ARB_create_context +#define WGL_ARB_create_context 1 + +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 + +typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int* attribList); + +#define wglCreateContextAttribsARB WGLEW_GET_FUN(__wglewCreateContextAttribsARB) + +#define WGLEW_ARB_create_context WGLEW_GET_VAR(__WGLEW_ARB_create_context) + +#endif /* WGL_ARB_create_context */ + +/* ----------------------- WGL_ARB_extensions_string ----------------------- */ + +#ifndef WGL_ARB_extensions_string +#define WGL_ARB_extensions_string 1 + +typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); + +#define wglGetExtensionsStringARB WGLEW_GET_FUN(__wglewGetExtensionsStringARB) + +#define WGLEW_ARB_extensions_string WGLEW_GET_VAR(__WGLEW_ARB_extensions_string) + +#endif /* WGL_ARB_extensions_string */ + +/* ------------------------ WGL_ARB_framebuffer_sRGB ----------------------- */ + +#ifndef WGL_ARB_framebuffer_sRGB +#define WGL_ARB_framebuffer_sRGB 1 + +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 + +#define WGLEW_ARB_framebuffer_sRGB WGLEW_GET_VAR(__WGLEW_ARB_framebuffer_sRGB) + +#endif /* WGL_ARB_framebuffer_sRGB */ + +/* ----------------------- WGL_ARB_make_current_read ----------------------- */ + +#ifndef WGL_ARB_make_current_read +#define WGL_ARB_make_current_read 1 + +#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 +#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 + +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + +#define wglGetCurrentReadDCARB WGLEW_GET_FUN(__wglewGetCurrentReadDCARB) +#define wglMakeContextCurrentARB WGLEW_GET_FUN(__wglewMakeContextCurrentARB) + +#define WGLEW_ARB_make_current_read WGLEW_GET_VAR(__WGLEW_ARB_make_current_read) + +#endif /* WGL_ARB_make_current_read */ + +/* -------------------------- WGL_ARB_multisample -------------------------- */ + +#ifndef WGL_ARB_multisample +#define WGL_ARB_multisample 1 + +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 + +#define WGLEW_ARB_multisample WGLEW_GET_VAR(__WGLEW_ARB_multisample) + +#endif /* WGL_ARB_multisample */ + +/* ---------------------------- WGL_ARB_pbuffer ---------------------------- */ + +#ifndef WGL_ARB_pbuffer +#define WGL_ARB_pbuffer 1 + +#define WGL_DRAW_TO_PBUFFER_ARB 0x202D +#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E +#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 +#define WGL_PBUFFER_LARGEST_ARB 0x2033 +#define WGL_PBUFFER_WIDTH_ARB 0x2034 +#define WGL_PBUFFER_HEIGHT_ARB 0x2035 +#define WGL_PBUFFER_LOST_ARB 0x2036 + +DECLARE_HANDLE(HPBUFFERARB); + +typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int* piValue); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); + +#define wglCreatePbufferARB WGLEW_GET_FUN(__wglewCreatePbufferARB) +#define wglDestroyPbufferARB WGLEW_GET_FUN(__wglewDestroyPbufferARB) +#define wglGetPbufferDCARB WGLEW_GET_FUN(__wglewGetPbufferDCARB) +#define wglQueryPbufferARB WGLEW_GET_FUN(__wglewQueryPbufferARB) +#define wglReleasePbufferDCARB WGLEW_GET_FUN(__wglewReleasePbufferDCARB) + +#define WGLEW_ARB_pbuffer WGLEW_GET_VAR(__WGLEW_ARB_pbuffer) + +#endif /* WGL_ARB_pbuffer */ + +/* -------------------------- WGL_ARB_pixel_format ------------------------- */ + +#ifndef WGL_ARB_pixel_format +#define WGL_ARB_pixel_format 1 + +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B + +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, int *piValues); + +#define wglChoosePixelFormatARB WGLEW_GET_FUN(__wglewChoosePixelFormatARB) +#define wglGetPixelFormatAttribfvARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvARB) +#define wglGetPixelFormatAttribivARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribivARB) + +#define WGLEW_ARB_pixel_format WGLEW_GET_VAR(__WGLEW_ARB_pixel_format) + +#endif /* WGL_ARB_pixel_format */ + +/* ----------------------- WGL_ARB_pixel_format_float ---------------------- */ + +#ifndef WGL_ARB_pixel_format_float +#define WGL_ARB_pixel_format_float 1 + +#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 + +#define WGLEW_ARB_pixel_format_float WGLEW_GET_VAR(__WGLEW_ARB_pixel_format_float) + +#endif /* WGL_ARB_pixel_format_float */ + +/* ------------------------- WGL_ARB_render_texture ------------------------ */ + +#ifndef WGL_ARB_render_texture +#define WGL_ARB_render_texture 1 + +#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 +#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 +#define WGL_TEXTURE_FORMAT_ARB 0x2072 +#define WGL_TEXTURE_TARGET_ARB 0x2073 +#define WGL_MIPMAP_TEXTURE_ARB 0x2074 +#define WGL_TEXTURE_RGB_ARB 0x2075 +#define WGL_TEXTURE_RGBA_ARB 0x2076 +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 +#define WGL_TEXTURE_1D_ARB 0x2079 +#define WGL_TEXTURE_2D_ARB 0x207A +#define WGL_MIPMAP_LEVEL_ARB 0x207B +#define WGL_CUBE_MAP_FACE_ARB 0x207C +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 +#define WGL_FRONT_LEFT_ARB 0x2083 +#define WGL_FRONT_RIGHT_ARB 0x2084 +#define WGL_BACK_LEFT_ARB 0x2085 +#define WGL_BACK_RIGHT_ARB 0x2086 +#define WGL_AUX0_ARB 0x2087 +#define WGL_AUX1_ARB 0x2088 +#define WGL_AUX2_ARB 0x2089 +#define WGL_AUX3_ARB 0x208A +#define WGL_AUX4_ARB 0x208B +#define WGL_AUX5_ARB 0x208C +#define WGL_AUX6_ARB 0x208D +#define WGL_AUX7_ARB 0x208E +#define WGL_AUX8_ARB 0x208F +#define WGL_AUX9_ARB 0x2090 + +typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int* piAttribList); + +#define wglBindTexImageARB WGLEW_GET_FUN(__wglewBindTexImageARB) +#define wglReleaseTexImageARB WGLEW_GET_FUN(__wglewReleaseTexImageARB) +#define wglSetPbufferAttribARB WGLEW_GET_FUN(__wglewSetPbufferAttribARB) + +#define WGLEW_ARB_render_texture WGLEW_GET_VAR(__WGLEW_ARB_render_texture) + +#endif /* WGL_ARB_render_texture */ + +/* ----------------------- WGL_ATI_pixel_format_float ---------------------- */ + +#ifndef WGL_ATI_pixel_format_float +#define WGL_ATI_pixel_format_float 1 + +#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0 +#define GL_RGBA_FLOAT_MODE_ATI 0x8820 +#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835 + +#define WGLEW_ATI_pixel_format_float WGLEW_GET_VAR(__WGLEW_ATI_pixel_format_float) + +#endif /* WGL_ATI_pixel_format_float */ + +/* -------------------- WGL_ATI_render_texture_rectangle ------------------- */ + +#ifndef WGL_ATI_render_texture_rectangle +#define WGL_ATI_render_texture_rectangle 1 + +#define WGL_TEXTURE_RECTANGLE_ATI 0x21A5 + +#define WGLEW_ATI_render_texture_rectangle WGLEW_GET_VAR(__WGLEW_ATI_render_texture_rectangle) + +#endif /* WGL_ATI_render_texture_rectangle */ + +/* -------------------------- WGL_EXT_depth_float -------------------------- */ + +#ifndef WGL_EXT_depth_float +#define WGL_EXT_depth_float 1 + +#define WGL_DEPTH_FLOAT_EXT 0x2040 + +#define WGLEW_EXT_depth_float WGLEW_GET_VAR(__WGLEW_EXT_depth_float) + +#endif /* WGL_EXT_depth_float */ + +/* ---------------------- WGL_EXT_display_color_table ---------------------- */ + +#ifndef WGL_EXT_display_color_table +#define WGL_EXT_display_color_table 1 + +typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef void (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (GLushort* table, GLuint length); + +#define wglBindDisplayColorTableEXT WGLEW_GET_FUN(__wglewBindDisplayColorTableEXT) +#define wglCreateDisplayColorTableEXT WGLEW_GET_FUN(__wglewCreateDisplayColorTableEXT) +#define wglDestroyDisplayColorTableEXT WGLEW_GET_FUN(__wglewDestroyDisplayColorTableEXT) +#define wglLoadDisplayColorTableEXT WGLEW_GET_FUN(__wglewLoadDisplayColorTableEXT) + +#define WGLEW_EXT_display_color_table WGLEW_GET_VAR(__WGLEW_EXT_display_color_table) + +#endif /* WGL_EXT_display_color_table */ + +/* ----------------------- WGL_EXT_extensions_string ----------------------- */ + +#ifndef WGL_EXT_extensions_string +#define WGL_EXT_extensions_string 1 + +typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); + +#define wglGetExtensionsStringEXT WGLEW_GET_FUN(__wglewGetExtensionsStringEXT) + +#define WGLEW_EXT_extensions_string WGLEW_GET_VAR(__WGLEW_EXT_extensions_string) + +#endif /* WGL_EXT_extensions_string */ + +/* ------------------------ WGL_EXT_framebuffer_sRGB ----------------------- */ + +#ifndef WGL_EXT_framebuffer_sRGB +#define WGL_EXT_framebuffer_sRGB 1 + +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9 + +#define WGLEW_EXT_framebuffer_sRGB WGLEW_GET_VAR(__WGLEW_EXT_framebuffer_sRGB) + +#endif /* WGL_EXT_framebuffer_sRGB */ + +/* ----------------------- WGL_EXT_make_current_read ----------------------- */ + +#ifndef WGL_EXT_make_current_read +#define WGL_EXT_make_current_read 1 + +#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 + +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + +#define wglGetCurrentReadDCEXT WGLEW_GET_FUN(__wglewGetCurrentReadDCEXT) +#define wglMakeContextCurrentEXT WGLEW_GET_FUN(__wglewMakeContextCurrentEXT) + +#define WGLEW_EXT_make_current_read WGLEW_GET_VAR(__WGLEW_EXT_make_current_read) + +#endif /* WGL_EXT_make_current_read */ + +/* -------------------------- WGL_EXT_multisample -------------------------- */ + +#ifndef WGL_EXT_multisample +#define WGL_EXT_multisample 1 + +#define WGL_SAMPLE_BUFFERS_EXT 0x2041 +#define WGL_SAMPLES_EXT 0x2042 + +#define WGLEW_EXT_multisample WGLEW_GET_VAR(__WGLEW_EXT_multisample) + +#endif /* WGL_EXT_multisample */ + +/* ---------------------------- WGL_EXT_pbuffer ---------------------------- */ + +#ifndef WGL_EXT_pbuffer +#define WGL_EXT_pbuffer 1 + +#define WGL_DRAW_TO_PBUFFER_EXT 0x202D +#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E +#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 +#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 +#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 +#define WGL_PBUFFER_LARGEST_EXT 0x2033 +#define WGL_PBUFFER_WIDTH_EXT 0x2034 +#define WGL_PBUFFER_HEIGHT_EXT 0x2035 + +DECLARE_HANDLE(HPBUFFEREXT); + +typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int* piValue); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); + +#define wglCreatePbufferEXT WGLEW_GET_FUN(__wglewCreatePbufferEXT) +#define wglDestroyPbufferEXT WGLEW_GET_FUN(__wglewDestroyPbufferEXT) +#define wglGetPbufferDCEXT WGLEW_GET_FUN(__wglewGetPbufferDCEXT) +#define wglQueryPbufferEXT WGLEW_GET_FUN(__wglewQueryPbufferEXT) +#define wglReleasePbufferDCEXT WGLEW_GET_FUN(__wglewReleasePbufferDCEXT) + +#define WGLEW_EXT_pbuffer WGLEW_GET_VAR(__WGLEW_EXT_pbuffer) + +#endif /* WGL_EXT_pbuffer */ + +/* -------------------------- WGL_EXT_pixel_format ------------------------- */ + +#ifndef WGL_EXT_pixel_format +#define WGL_EXT_pixel_format 1 + +#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 +#define WGL_DRAW_TO_WINDOW_EXT 0x2001 +#define WGL_DRAW_TO_BITMAP_EXT 0x2002 +#define WGL_ACCELERATION_EXT 0x2003 +#define WGL_NEED_PALETTE_EXT 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 +#define WGL_SWAP_METHOD_EXT 0x2007 +#define WGL_NUMBER_OVERLAYS_EXT 0x2008 +#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 +#define WGL_TRANSPARENT_EXT 0x200A +#define WGL_TRANSPARENT_VALUE_EXT 0x200B +#define WGL_SHARE_DEPTH_EXT 0x200C +#define WGL_SHARE_STENCIL_EXT 0x200D +#define WGL_SHARE_ACCUM_EXT 0x200E +#define WGL_SUPPORT_GDI_EXT 0x200F +#define WGL_SUPPORT_OPENGL_EXT 0x2010 +#define WGL_DOUBLE_BUFFER_EXT 0x2011 +#define WGL_STEREO_EXT 0x2012 +#define WGL_PIXEL_TYPE_EXT 0x2013 +#define WGL_COLOR_BITS_EXT 0x2014 +#define WGL_RED_BITS_EXT 0x2015 +#define WGL_RED_SHIFT_EXT 0x2016 +#define WGL_GREEN_BITS_EXT 0x2017 +#define WGL_GREEN_SHIFT_EXT 0x2018 +#define WGL_BLUE_BITS_EXT 0x2019 +#define WGL_BLUE_SHIFT_EXT 0x201A +#define WGL_ALPHA_BITS_EXT 0x201B +#define WGL_ALPHA_SHIFT_EXT 0x201C +#define WGL_ACCUM_BITS_EXT 0x201D +#define WGL_ACCUM_RED_BITS_EXT 0x201E +#define WGL_ACCUM_GREEN_BITS_EXT 0x201F +#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 +#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 +#define WGL_DEPTH_BITS_EXT 0x2022 +#define WGL_STENCIL_BITS_EXT 0x2023 +#define WGL_AUX_BUFFERS_EXT 0x2024 +#define WGL_NO_ACCELERATION_EXT 0x2025 +#define WGL_GENERIC_ACCELERATION_EXT 0x2026 +#define WGL_FULL_ACCELERATION_EXT 0x2027 +#define WGL_SWAP_EXCHANGE_EXT 0x2028 +#define WGL_SWAP_COPY_EXT 0x2029 +#define WGL_SWAP_UNDEFINED_EXT 0x202A +#define WGL_TYPE_RGBA_EXT 0x202B +#define WGL_TYPE_COLORINDEX_EXT 0x202C + +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int *piValues); + +#define wglChoosePixelFormatEXT WGLEW_GET_FUN(__wglewChoosePixelFormatEXT) +#define wglGetPixelFormatAttribfvEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvEXT) +#define wglGetPixelFormatAttribivEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribivEXT) + +#define WGLEW_EXT_pixel_format WGLEW_GET_VAR(__WGLEW_EXT_pixel_format) + +#endif /* WGL_EXT_pixel_format */ + +/* ------------------- WGL_EXT_pixel_format_packed_float ------------------- */ + +#ifndef WGL_EXT_pixel_format_packed_float +#define WGL_EXT_pixel_format_packed_float 1 + +#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8 + +#define WGLEW_EXT_pixel_format_packed_float WGLEW_GET_VAR(__WGLEW_EXT_pixel_format_packed_float) + +#endif /* WGL_EXT_pixel_format_packed_float */ + +/* -------------------------- WGL_EXT_swap_control ------------------------- */ + +#ifndef WGL_EXT_swap_control +#define WGL_EXT_swap_control 1 + +typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); +typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); + +#define wglGetSwapIntervalEXT WGLEW_GET_FUN(__wglewGetSwapIntervalEXT) +#define wglSwapIntervalEXT WGLEW_GET_FUN(__wglewSwapIntervalEXT) + +#define WGLEW_EXT_swap_control WGLEW_GET_VAR(__WGLEW_EXT_swap_control) + +#endif /* WGL_EXT_swap_control */ + +/* --------------------- WGL_I3D_digital_video_control --------------------- */ + +#ifndef WGL_I3D_digital_video_control +#define WGL_I3D_digital_video_control 1 + +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 +#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 +#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 + +typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue); +typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue); + +#define wglGetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewGetDigitalVideoParametersI3D) +#define wglSetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewSetDigitalVideoParametersI3D) + +#define WGLEW_I3D_digital_video_control WGLEW_GET_VAR(__WGLEW_I3D_digital_video_control) + +#endif /* WGL_I3D_digital_video_control */ + +/* ----------------------------- WGL_I3D_gamma ----------------------------- */ + +#ifndef WGL_I3D_gamma +#define WGL_I3D_gamma 1 + +#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E +#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F + +typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT* puRed, USHORT *puGreen, USHORT *puBlue); +typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue); +typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT* puRed, const USHORT *puGreen, const USHORT *puBlue); +typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue); + +#define wglGetGammaTableI3D WGLEW_GET_FUN(__wglewGetGammaTableI3D) +#define wglGetGammaTableParametersI3D WGLEW_GET_FUN(__wglewGetGammaTableParametersI3D) +#define wglSetGammaTableI3D WGLEW_GET_FUN(__wglewSetGammaTableI3D) +#define wglSetGammaTableParametersI3D WGLEW_GET_FUN(__wglewSetGammaTableParametersI3D) + +#define WGLEW_I3D_gamma WGLEW_GET_VAR(__WGLEW_I3D_gamma) + +#endif /* WGL_I3D_gamma */ + +/* ---------------------------- WGL_I3D_genlock ---------------------------- */ + +#ifndef WGL_I3D_genlock +#define WGL_I3D_genlock 1 + +#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 +#define WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045 +#define WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046 +#define WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047 +#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 +#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 +#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A +#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B +#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C + +typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC); +typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC); +typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT* uRate); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT* uDelay); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT* uEdge); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT* uSource); +typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL* pFlag); +typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT* uMaxLineDelay, UINT *uMaxPixelDelay); + +#define wglDisableGenlockI3D WGLEW_GET_FUN(__wglewDisableGenlockI3D) +#define wglEnableGenlockI3D WGLEW_GET_FUN(__wglewEnableGenlockI3D) +#define wglGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGenlockSampleRateI3D) +#define wglGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGenlockSourceDelayI3D) +#define wglGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGenlockSourceEdgeI3D) +#define wglGenlockSourceI3D WGLEW_GET_FUN(__wglewGenlockSourceI3D) +#define wglGetGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGetGenlockSampleRateI3D) +#define wglGetGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGetGenlockSourceDelayI3D) +#define wglGetGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGetGenlockSourceEdgeI3D) +#define wglGetGenlockSourceI3D WGLEW_GET_FUN(__wglewGetGenlockSourceI3D) +#define wglIsEnabledGenlockI3D WGLEW_GET_FUN(__wglewIsEnabledGenlockI3D) +#define wglQueryGenlockMaxSourceDelayI3D WGLEW_GET_FUN(__wglewQueryGenlockMaxSourceDelayI3D) + +#define WGLEW_I3D_genlock WGLEW_GET_VAR(__WGLEW_I3D_genlock) + +#endif /* WGL_I3D_genlock */ + +/* -------------------------- WGL_I3D_image_buffer ------------------------- */ + +#ifndef WGL_I3D_image_buffer +#define WGL_I3D_image_buffer 1 + +#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001 +#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002 + +typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, HANDLE* pEvent, LPVOID *pAddress, DWORD *pSize, UINT count); +typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags); +typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress); +typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, LPVOID* pAddress, UINT count); + +#define wglAssociateImageBufferEventsI3D WGLEW_GET_FUN(__wglewAssociateImageBufferEventsI3D) +#define wglCreateImageBufferI3D WGLEW_GET_FUN(__wglewCreateImageBufferI3D) +#define wglDestroyImageBufferI3D WGLEW_GET_FUN(__wglewDestroyImageBufferI3D) +#define wglReleaseImageBufferEventsI3D WGLEW_GET_FUN(__wglewReleaseImageBufferEventsI3D) + +#define WGLEW_I3D_image_buffer WGLEW_GET_VAR(__WGLEW_I3D_image_buffer) + +#endif /* WGL_I3D_image_buffer */ + +/* ------------------------ WGL_I3D_swap_frame_lock ------------------------ */ + +#ifndef WGL_I3D_swap_frame_lock +#define WGL_I3D_swap_frame_lock 1 + +typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL* pFlag); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL* pFlag); + +#define wglDisableFrameLockI3D WGLEW_GET_FUN(__wglewDisableFrameLockI3D) +#define wglEnableFrameLockI3D WGLEW_GET_FUN(__wglewEnableFrameLockI3D) +#define wglIsEnabledFrameLockI3D WGLEW_GET_FUN(__wglewIsEnabledFrameLockI3D) +#define wglQueryFrameLockMasterI3D WGLEW_GET_FUN(__wglewQueryFrameLockMasterI3D) + +#define WGLEW_I3D_swap_frame_lock WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_lock) + +#endif /* WGL_I3D_swap_frame_lock */ + +/* ------------------------ WGL_I3D_swap_frame_usage ----------------------- */ + +#ifndef WGL_I3D_swap_frame_usage +#define WGL_I3D_swap_frame_usage 1 + +typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float* pUsage); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD* pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); + +#define wglBeginFrameTrackingI3D WGLEW_GET_FUN(__wglewBeginFrameTrackingI3D) +#define wglEndFrameTrackingI3D WGLEW_GET_FUN(__wglewEndFrameTrackingI3D) +#define wglGetFrameUsageI3D WGLEW_GET_FUN(__wglewGetFrameUsageI3D) +#define wglQueryFrameTrackingI3D WGLEW_GET_FUN(__wglewQueryFrameTrackingI3D) + +#define WGLEW_I3D_swap_frame_usage WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_usage) + +#endif /* WGL_I3D_swap_frame_usage */ + +/* -------------------------- WGL_NV_float_buffer -------------------------- */ + +#ifndef WGL_NV_float_buffer +#define WGL_NV_float_buffer 1 + +#define WGL_FLOAT_COMPONENTS_NV 0x20B0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4 +#define WGL_TEXTURE_FLOAT_R_NV 0x20B5 +#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6 +#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7 +#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8 + +#define WGLEW_NV_float_buffer WGLEW_GET_VAR(__WGLEW_NV_float_buffer) + +#endif /* WGL_NV_float_buffer */ + +/* -------------------------- WGL_NV_gpu_affinity -------------------------- */ + +#ifndef WGL_NV_gpu_affinity +#define WGL_NV_gpu_affinity 1 + +#define WGL_ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0 +#define WGL_ERROR_MISSING_AFFINITY_MASK_NV 0x20D1 + +DECLARE_HANDLE(HGPUNV); +typedef struct _GPU_DEVICE { + DWORD cb; + CHAR DeviceName[32]; + CHAR DeviceString[128]; + DWORD Flags; + RECT rcVirtualScreen; +} GPU_DEVICE, *PGPU_DEVICE; + +typedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList); +typedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc); +typedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice); +typedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu); +typedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu); + +#define wglCreateAffinityDCNV WGLEW_GET_FUN(__wglewCreateAffinityDCNV) +#define wglDeleteDCNV WGLEW_GET_FUN(__wglewDeleteDCNV) +#define wglEnumGpuDevicesNV WGLEW_GET_FUN(__wglewEnumGpuDevicesNV) +#define wglEnumGpusFromAffinityDCNV WGLEW_GET_FUN(__wglewEnumGpusFromAffinityDCNV) +#define wglEnumGpusNV WGLEW_GET_FUN(__wglewEnumGpusNV) + +#define WGLEW_NV_gpu_affinity WGLEW_GET_VAR(__WGLEW_NV_gpu_affinity) + +#endif /* WGL_NV_gpu_affinity */ + +/* -------------------------- WGL_NV_present_video ------------------------- */ + +#ifndef WGL_NV_present_video +#define WGL_NV_present_video 1 + +#define WGL_NUM_VIDEO_SLOTS_NV 0x20F0 + +DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV); + +typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDc, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int* piAttribList); +typedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDc, HVIDEOOUTPUTDEVICENV* phDeviceList); +typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int* piValue); + +#define wglBindVideoDeviceNV WGLEW_GET_FUN(__wglewBindVideoDeviceNV) +#define wglEnumerateVideoDevicesNV WGLEW_GET_FUN(__wglewEnumerateVideoDevicesNV) +#define wglQueryCurrentContextNV WGLEW_GET_FUN(__wglewQueryCurrentContextNV) + +#define WGLEW_NV_present_video WGLEW_GET_VAR(__WGLEW_NV_present_video) + +#endif /* WGL_NV_present_video */ + +/* ---------------------- WGL_NV_render_depth_texture ---------------------- */ + +#ifndef WGL_NV_render_depth_texture +#define WGL_NV_render_depth_texture 1 + +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 +#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 +#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 +#define WGL_DEPTH_COMPONENT_NV 0x20A7 + +#define WGLEW_NV_render_depth_texture WGLEW_GET_VAR(__WGLEW_NV_render_depth_texture) + +#endif /* WGL_NV_render_depth_texture */ + +/* -------------------- WGL_NV_render_texture_rectangle -------------------- */ + +#ifndef WGL_NV_render_texture_rectangle +#define WGL_NV_render_texture_rectangle 1 + +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 +#define WGL_TEXTURE_RECTANGLE_NV 0x20A2 + +#define WGLEW_NV_render_texture_rectangle WGLEW_GET_VAR(__WGLEW_NV_render_texture_rectangle) + +#endif /* WGL_NV_render_texture_rectangle */ + +/* --------------------------- WGL_NV_swap_group --------------------------- */ + +#ifndef WGL_NV_swap_group +#define WGL_NV_swap_group 1 + +typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier); +typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint* count); +typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint* maxGroups, GLuint *maxBarriers); +typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint* group); +typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC); + +#define wglBindSwapBarrierNV WGLEW_GET_FUN(__wglewBindSwapBarrierNV) +#define wglJoinSwapGroupNV WGLEW_GET_FUN(__wglewJoinSwapGroupNV) +#define wglQueryFrameCountNV WGLEW_GET_FUN(__wglewQueryFrameCountNV) +#define wglQueryMaxSwapGroupsNV WGLEW_GET_FUN(__wglewQueryMaxSwapGroupsNV) +#define wglQuerySwapGroupNV WGLEW_GET_FUN(__wglewQuerySwapGroupNV) +#define wglResetFrameCountNV WGLEW_GET_FUN(__wglewResetFrameCountNV) + +#define WGLEW_NV_swap_group WGLEW_GET_VAR(__WGLEW_NV_swap_group) + +#endif /* WGL_NV_swap_group */ + +/* ----------------------- WGL_NV_vertex_array_range ----------------------- */ + +#ifndef WGL_NV_vertex_array_range +#define WGL_NV_vertex_array_range 1 + +typedef void * (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority); +typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer); + +#define wglAllocateMemoryNV WGLEW_GET_FUN(__wglewAllocateMemoryNV) +#define wglFreeMemoryNV WGLEW_GET_FUN(__wglewFreeMemoryNV) + +#define WGLEW_NV_vertex_array_range WGLEW_GET_VAR(__WGLEW_NV_vertex_array_range) + +#endif /* WGL_NV_vertex_array_range */ + +/* -------------------------- WGL_NV_video_output -------------------------- */ + +#ifndef WGL_NV_video_output +#define WGL_NV_video_output 1 + +#define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0 +#define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1 +#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2 +#define WGL_VIDEO_OUT_COLOR_NV 0x20C3 +#define WGL_VIDEO_OUT_ALPHA_NV 0x20C4 +#define WGL_VIDEO_OUT_DEPTH_NV 0x20C5 +#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 +#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 +#define WGL_VIDEO_OUT_FRAME 0x20C8 +#define WGL_VIDEO_OUT_FIELD_1 0x20C9 +#define WGL_VIDEO_OUT_FIELD_2 0x20CA +#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB +#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC + +DECLARE_HANDLE(HPVIDEODEV); + +typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer); +typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV* hVideoDevice); +typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long* pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer); +typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long* pulCounterPbuffer, BOOL bBlock); + +#define wglBindVideoImageNV WGLEW_GET_FUN(__wglewBindVideoImageNV) +#define wglGetVideoDeviceNV WGLEW_GET_FUN(__wglewGetVideoDeviceNV) +#define wglGetVideoInfoNV WGLEW_GET_FUN(__wglewGetVideoInfoNV) +#define wglReleaseVideoDeviceNV WGLEW_GET_FUN(__wglewReleaseVideoDeviceNV) +#define wglReleaseVideoImageNV WGLEW_GET_FUN(__wglewReleaseVideoImageNV) +#define wglSendPbufferToVideoNV WGLEW_GET_FUN(__wglewSendPbufferToVideoNV) + +#define WGLEW_NV_video_output WGLEW_GET_VAR(__WGLEW_NV_video_output) + +#endif /* WGL_NV_video_output */ + +/* -------------------------- WGL_OML_sync_control ------------------------- */ + +#ifndef WGL_OML_sync_control +#define WGL_OML_sync_control 1 + +typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32* numerator, INT32 *denominator); +typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64* ust, INT64 *msc, INT64 *sbc); +typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, INT fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64* ust, INT64 *msc, INT64 *sbc); +typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64* ust, INT64 *msc, INT64 *sbc); + +#define wglGetMscRateOML WGLEW_GET_FUN(__wglewGetMscRateOML) +#define wglGetSyncValuesOML WGLEW_GET_FUN(__wglewGetSyncValuesOML) +#define wglSwapBuffersMscOML WGLEW_GET_FUN(__wglewSwapBuffersMscOML) +#define wglSwapLayerBuffersMscOML WGLEW_GET_FUN(__wglewSwapLayerBuffersMscOML) +#define wglWaitForMscOML WGLEW_GET_FUN(__wglewWaitForMscOML) +#define wglWaitForSbcOML WGLEW_GET_FUN(__wglewWaitForSbcOML) + +#define WGLEW_OML_sync_control WGLEW_GET_VAR(__WGLEW_OML_sync_control) + +#endif /* WGL_OML_sync_control */ + +/* ------------------------------------------------------------------------- */ + +#ifdef GLEW_MX +#define WGLEW_EXPORT +#else +#define WGLEW_EXPORT GLEWAPI +#endif /* GLEW_MX */ + +#ifdef GLEW_MX +struct WGLEWContextStruct +{ +#endif /* GLEW_MX */ + +WGLEW_EXPORT PFNWGLSETSTEREOEMITTERSTATE3DLPROC __wglewSetStereoEmitterState3DL; + +WGLEW_EXPORT PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB; +WGLEW_EXPORT PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB; +WGLEW_EXPORT PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB; +WGLEW_EXPORT PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB; + +WGLEW_EXPORT PFNWGLCREATECONTEXTATTRIBSARBPROC __wglewCreateContextAttribsARB; + +WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB; + +WGLEW_EXPORT PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB; +WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB; + +WGLEW_EXPORT PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB; +WGLEW_EXPORT PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB; +WGLEW_EXPORT PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB; +WGLEW_EXPORT PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB; +WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB; + +WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB; + +WGLEW_EXPORT PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB; +WGLEW_EXPORT PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB; +WGLEW_EXPORT PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB; + +WGLEW_EXPORT PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT; +WGLEW_EXPORT PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT; +WGLEW_EXPORT PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT; +WGLEW_EXPORT PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT; + +WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT; + +WGLEW_EXPORT PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT; +WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT; + +WGLEW_EXPORT PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT; +WGLEW_EXPORT PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT; +WGLEW_EXPORT PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT; +WGLEW_EXPORT PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT; +WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT; + +WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT; + +WGLEW_EXPORT PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT; +WGLEW_EXPORT PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT; + +WGLEW_EXPORT PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D; +WGLEW_EXPORT PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D; + +WGLEW_EXPORT PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D; +WGLEW_EXPORT PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D; +WGLEW_EXPORT PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D; +WGLEW_EXPORT PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D; + +WGLEW_EXPORT PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D; +WGLEW_EXPORT PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D; +WGLEW_EXPORT PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D; +WGLEW_EXPORT PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D; +WGLEW_EXPORT PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D; +WGLEW_EXPORT PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D; +WGLEW_EXPORT PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D; +WGLEW_EXPORT PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D; + +WGLEW_EXPORT PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D; +WGLEW_EXPORT PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D; +WGLEW_EXPORT PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D; +WGLEW_EXPORT PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D; + +WGLEW_EXPORT PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D; +WGLEW_EXPORT PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D; +WGLEW_EXPORT PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D; +WGLEW_EXPORT PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D; + +WGLEW_EXPORT PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D; +WGLEW_EXPORT PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D; +WGLEW_EXPORT PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D; +WGLEW_EXPORT PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D; + +WGLEW_EXPORT PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV; +WGLEW_EXPORT PFNWGLDELETEDCNVPROC __wglewDeleteDCNV; +WGLEW_EXPORT PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV; +WGLEW_EXPORT PFNWGLENUMGPUSFROMAFFINITYDCNVPROC __wglewEnumGpusFromAffinityDCNV; +WGLEW_EXPORT PFNWGLENUMGPUSNVPROC __wglewEnumGpusNV; + +WGLEW_EXPORT PFNWGLBINDVIDEODEVICENVPROC __wglewBindVideoDeviceNV; +WGLEW_EXPORT PFNWGLENUMERATEVIDEODEVICESNVPROC __wglewEnumerateVideoDevicesNV; +WGLEW_EXPORT PFNWGLQUERYCURRENTCONTEXTNVPROC __wglewQueryCurrentContextNV; + +WGLEW_EXPORT PFNWGLBINDSWAPBARRIERNVPROC __wglewBindSwapBarrierNV; +WGLEW_EXPORT PFNWGLJOINSWAPGROUPNVPROC __wglewJoinSwapGroupNV; +WGLEW_EXPORT PFNWGLQUERYFRAMECOUNTNVPROC __wglewQueryFrameCountNV; +WGLEW_EXPORT PFNWGLQUERYMAXSWAPGROUPSNVPROC __wglewQueryMaxSwapGroupsNV; +WGLEW_EXPORT PFNWGLQUERYSWAPGROUPNVPROC __wglewQuerySwapGroupNV; +WGLEW_EXPORT PFNWGLRESETFRAMECOUNTNVPROC __wglewResetFrameCountNV; + +WGLEW_EXPORT PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV; +WGLEW_EXPORT PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV; + +WGLEW_EXPORT PFNWGLBINDVIDEOIMAGENVPROC __wglewBindVideoImageNV; +WGLEW_EXPORT PFNWGLGETVIDEODEVICENVPROC __wglewGetVideoDeviceNV; +WGLEW_EXPORT PFNWGLGETVIDEOINFONVPROC __wglewGetVideoInfoNV; +WGLEW_EXPORT PFNWGLRELEASEVIDEODEVICENVPROC __wglewReleaseVideoDeviceNV; +WGLEW_EXPORT PFNWGLRELEASEVIDEOIMAGENVPROC __wglewReleaseVideoImageNV; +WGLEW_EXPORT PFNWGLSENDPBUFFERTOVIDEONVPROC __wglewSendPbufferToVideoNV; + +WGLEW_EXPORT PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML; +WGLEW_EXPORT PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML; +WGLEW_EXPORT PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML; +WGLEW_EXPORT PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML; +WGLEW_EXPORT PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML; +WGLEW_EXPORT PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML; +WGLEW_EXPORT GLboolean __WGLEW_3DFX_multisample; +WGLEW_EXPORT GLboolean __WGLEW_3DL_stereo_control; +WGLEW_EXPORT GLboolean __WGLEW_ARB_buffer_region; +WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context; +WGLEW_EXPORT GLboolean __WGLEW_ARB_extensions_string; +WGLEW_EXPORT GLboolean __WGLEW_ARB_framebuffer_sRGB; +WGLEW_EXPORT GLboolean __WGLEW_ARB_make_current_read; +WGLEW_EXPORT GLboolean __WGLEW_ARB_multisample; +WGLEW_EXPORT GLboolean __WGLEW_ARB_pbuffer; +WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format; +WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format_float; +WGLEW_EXPORT GLboolean __WGLEW_ARB_render_texture; +WGLEW_EXPORT GLboolean __WGLEW_ATI_pixel_format_float; +WGLEW_EXPORT GLboolean __WGLEW_ATI_render_texture_rectangle; +WGLEW_EXPORT GLboolean __WGLEW_EXT_depth_float; +WGLEW_EXPORT GLboolean __WGLEW_EXT_display_color_table; +WGLEW_EXPORT GLboolean __WGLEW_EXT_extensions_string; +WGLEW_EXPORT GLboolean __WGLEW_EXT_framebuffer_sRGB; +WGLEW_EXPORT GLboolean __WGLEW_EXT_make_current_read; +WGLEW_EXPORT GLboolean __WGLEW_EXT_multisample; +WGLEW_EXPORT GLboolean __WGLEW_EXT_pbuffer; +WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format; +WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format_packed_float; +WGLEW_EXPORT GLboolean __WGLEW_EXT_swap_control; +WGLEW_EXPORT GLboolean __WGLEW_I3D_digital_video_control; +WGLEW_EXPORT GLboolean __WGLEW_I3D_gamma; +WGLEW_EXPORT GLboolean __WGLEW_I3D_genlock; +WGLEW_EXPORT GLboolean __WGLEW_I3D_image_buffer; +WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_lock; +WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_usage; +WGLEW_EXPORT GLboolean __WGLEW_NV_float_buffer; +WGLEW_EXPORT GLboolean __WGLEW_NV_gpu_affinity; +WGLEW_EXPORT GLboolean __WGLEW_NV_present_video; +WGLEW_EXPORT GLboolean __WGLEW_NV_render_depth_texture; +WGLEW_EXPORT GLboolean __WGLEW_NV_render_texture_rectangle; +WGLEW_EXPORT GLboolean __WGLEW_NV_swap_group; +WGLEW_EXPORT GLboolean __WGLEW_NV_vertex_array_range; +WGLEW_EXPORT GLboolean __WGLEW_NV_video_output; +WGLEW_EXPORT GLboolean __WGLEW_OML_sync_control; + +#ifdef GLEW_MX +}; /* WGLEWContextStruct */ +#endif /* GLEW_MX */ + +/* ------------------------------------------------------------------------- */ + +#ifdef GLEW_MX + +typedef struct WGLEWContextStruct WGLEWContext; +GLEWAPI GLenum wglewContextInit (WGLEWContext* ctx); +GLEWAPI GLboolean wglewContextIsSupported (WGLEWContext* ctx, const char* name); + +#define wglewInit() wglewContextInit(wglewGetContext()) +#define wglewIsSupported(x) wglewContextIsSupported(wglewGetContext(), x) + +#define WGLEW_GET_VAR(x) (*(const GLboolean*)&(wglewGetContext()->x)) +#define WGLEW_GET_FUN(x) wglewGetContext()->x + +#else /* GLEW_MX */ + +#define WGLEW_GET_VAR(x) (*(const GLboolean*)&x) +#define WGLEW_GET_FUN(x) x + +GLEWAPI GLboolean wglewIsSupported (const char* name); + +#endif /* GLEW_MX */ + +GLEWAPI GLboolean wglewGetExtension (const char* name); + +#ifdef __cplusplus +} +#endif + +#undef GLEWAPI + +#endif /* __wglew_h__ */ diff --git a/test_conformance/gl/GLEW/glew.c b/test_conformance/gl/GLEW/glew.c new file mode 100644 index 00000000..1100800a --- /dev/null +++ b/test_conformance/gl/GLEW/glew.c @@ -0,0 +1,10835 @@ +/* +** The OpenGL Extension Wrangler Library +** Copyright (C) 2002-2008, Milan Ikits +** Copyright (C) 2002-2008, Marcelo E. Magallon +** Copyright (C) 2002, Lev Povalahev +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** * The name of the author may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +** THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#if defined(_WIN32) +# include +#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +# include +#endif + +/* + * Define glewGetContext and related helper macros. + */ +#ifdef GLEW_MX +# define glewGetContext() ctx +# ifdef _WIN32 +# define GLEW_CONTEXT_ARG_DEF_INIT GLEWContext* ctx +# define GLEW_CONTEXT_ARG_VAR_INIT ctx +# define wglewGetContext() ctx +# define WGLEW_CONTEXT_ARG_DEF_INIT WGLEWContext* ctx +# define WGLEW_CONTEXT_ARG_DEF_LIST WGLEWContext* ctx +# else /* _WIN32 */ +# define GLEW_CONTEXT_ARG_DEF_INIT void +# define GLEW_CONTEXT_ARG_VAR_INIT +# define glxewGetContext() ctx +# define GLXEW_CONTEXT_ARG_DEF_INIT void +# define GLXEW_CONTEXT_ARG_DEF_LIST GLXEWContext* ctx +# endif /* _WIN32 */ +# define GLEW_CONTEXT_ARG_DEF_LIST GLEWContext* ctx +#else /* GLEW_MX */ +# define GLEW_CONTEXT_ARG_DEF_INIT void +# define GLEW_CONTEXT_ARG_VAR_INIT +# define GLEW_CONTEXT_ARG_DEF_LIST void +# define WGLEW_CONTEXT_ARG_DEF_INIT void +# define WGLEW_CONTEXT_ARG_DEF_LIST void +# define GLXEW_CONTEXT_ARG_DEF_INIT void +# define GLXEW_CONTEXT_ARG_DEF_LIST void +#endif /* GLEW_MX */ + +#if defined(__APPLE__) +#include +#include +#include + +void* NSGLGetProcAddress (const GLubyte *name) +{ + static const struct mach_header* image = NULL; + NSSymbol symbol; + char* symbolName; + if (NULL == image) + { + image = NSAddImage("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", NSADDIMAGE_OPTION_RETURN_ON_ERROR); + } + /* prepend a '_' for the Unix C symbol mangling convention */ + symbolName = malloc(strlen((const char*)name) + 2); + strcpy(symbolName+1, (const char*)name); + symbolName[0] = '_'; + symbol = NULL; + /* if (NSIsSymbolNameDefined(symbolName)) + symbol = NSLookupAndBindSymbol(symbolName); */ + symbol = image ? NSLookupSymbolInImage(image, symbolName, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) : NULL; + free(symbolName); + return symbol ? NSAddressOfSymbol(symbol) : NULL; +} +#endif /* __APPLE__ */ + +#if defined(__sgi) || defined (__sun) +#include +#include +#include + +void* dlGetProcAddress (const GLubyte* name) +{ + static void* h = NULL; + static void* gpa; + + if (h == NULL) + { + if ((h = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL)) == NULL) return NULL; + gpa = dlsym(h, "glXGetProcAddress"); + } + + if (gpa != NULL) + return ((void*(*)(const GLubyte*))gpa)(name); + else + return dlsym(h, (const char*)name); +} +#endif /* __sgi || __sun */ + +/* + * Define glewGetProcAddress. + */ +#if defined(_WIN32) +# define glewGetProcAddress(name) wglGetProcAddress((LPCSTR)name) +#else +# if defined(__APPLE__) +# define glewGetProcAddress(name) NSGLGetProcAddress(name) +# else +# if defined(__sgi) || defined(__sun) +# define glewGetProcAddress(name) dlGetProcAddress(name) +# else /* __linux */ +# define glewGetProcAddress(name) (*glXGetProcAddressARB)(name) +# endif +# endif +#endif + +/* + * Define GLboolean const cast. + */ +#define CONST_CAST(x) (*(GLboolean*)&x) + +/* + * GLEW, just like OpenGL or GLU, does not rely on the standard C library. + * These functions implement the functionality required in this file. + */ +static GLuint _glewStrLen (const GLubyte* s) +{ + GLuint i=0; + if (s == NULL) return 0; + while (s[i] != '\0') i++; + return i; +} + +static GLuint _glewStrCLen (const GLubyte* s, GLubyte c) +{ + GLuint i=0; + if (s == NULL) return 0; + while (s[i] != '\0' && s[i] != c) i++; + return s[i] == c ? i : 0; +} + +static GLboolean _glewStrSame (const GLubyte* a, const GLubyte* b, GLuint n) +{ + GLuint i=0; + if(a == NULL || b == NULL) + return (a == NULL && b == NULL && n == 0) ? GL_TRUE : GL_FALSE; + while (i < n && a[i] != '\0' && b[i] != '\0' && a[i] == b[i]) i++; + return i == n ? GL_TRUE : GL_FALSE; +} + +static GLboolean _glewStrSame1 (GLubyte** a, GLuint* na, const GLubyte* b, GLuint nb) +{ + while (*na > 0 && (**a == ' ' || **a == '\n' || **a == '\r' || **a == '\t')) + { + (*a)++; + (*na)--; + } + if(*na >= nb) + { + GLuint i=0; + while (i < nb && (*a)+i != NULL && b+i != NULL && (*a)[i] == b[i]) i++; + if(i == nb) + { + *a = *a + nb; + *na = *na - nb; + return GL_TRUE; + } + } + return GL_FALSE; +} + +static GLboolean _glewStrSame2 (GLubyte** a, GLuint* na, const GLubyte* b, GLuint nb) +{ + if(*na >= nb) + { + GLuint i=0; + while (i < nb && (*a)+i != NULL && b+i != NULL && (*a)[i] == b[i]) i++; + if(i == nb) + { + *a = *a + nb; + *na = *na - nb; + return GL_TRUE; + } + } + return GL_FALSE; +} + +static GLboolean _glewStrSame3 (GLubyte** a, GLuint* na, const GLubyte* b, GLuint nb) +{ + if(*na >= nb) + { + GLuint i=0; + while (i < nb && (*a)+i != NULL && b+i != NULL && (*a)[i] == b[i]) i++; + if (i == nb && (*na == nb || (*a)[i] == ' ' || (*a)[i] == '\n' || (*a)[i] == '\r' || (*a)[i] == '\t')) + { + *a = *a + nb; + *na = *na - nb; + return GL_TRUE; + } + } + return GL_FALSE; +} + +#if !defined(_WIN32) || !defined(GLEW_MX) + +PFNGLCOPYTEXSUBIMAGE3DPROC __glewCopyTexSubImage3D = NULL; +PFNGLDRAWRANGEELEMENTSPROC __glewDrawRangeElements = NULL; +PFNGLTEXIMAGE3DPROC __glewTexImage3D = NULL; +PFNGLTEXSUBIMAGE3DPROC __glewTexSubImage3D = NULL; + +PFNGLACTIVETEXTUREPROC __glewActiveTexture = NULL; +PFNGLCLIENTACTIVETEXTUREPROC __glewClientActiveTexture = NULL; +PFNGLCOMPRESSEDTEXIMAGE1DPROC __glewCompressedTexImage1D = NULL; +PFNGLCOMPRESSEDTEXIMAGE2DPROC __glewCompressedTexImage2D = NULL; +PFNGLCOMPRESSEDTEXIMAGE3DPROC __glewCompressedTexImage3D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC __glewCompressedTexSubImage1D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC __glewCompressedTexSubImage2D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC __glewCompressedTexSubImage3D = NULL; +PFNGLGETCOMPRESSEDTEXIMAGEPROC __glewGetCompressedTexImage = NULL; +PFNGLLOADTRANSPOSEMATRIXDPROC __glewLoadTransposeMatrixd = NULL; +PFNGLLOADTRANSPOSEMATRIXFPROC __glewLoadTransposeMatrixf = NULL; +PFNGLMULTTRANSPOSEMATRIXDPROC __glewMultTransposeMatrixd = NULL; +PFNGLMULTTRANSPOSEMATRIXFPROC __glewMultTransposeMatrixf = NULL; +PFNGLMULTITEXCOORD1DPROC __glewMultiTexCoord1d = NULL; +PFNGLMULTITEXCOORD1DVPROC __glewMultiTexCoord1dv = NULL; +PFNGLMULTITEXCOORD1FPROC __glewMultiTexCoord1f = NULL; +PFNGLMULTITEXCOORD1FVPROC __glewMultiTexCoord1fv = NULL; +PFNGLMULTITEXCOORD1IPROC __glewMultiTexCoord1i = NULL; +PFNGLMULTITEXCOORD1IVPROC __glewMultiTexCoord1iv = NULL; +PFNGLMULTITEXCOORD1SPROC __glewMultiTexCoord1s = NULL; +PFNGLMULTITEXCOORD1SVPROC __glewMultiTexCoord1sv = NULL; +PFNGLMULTITEXCOORD2DPROC __glewMultiTexCoord2d = NULL; +PFNGLMULTITEXCOORD2DVPROC __glewMultiTexCoord2dv = NULL; +PFNGLMULTITEXCOORD2FPROC __glewMultiTexCoord2f = NULL; +PFNGLMULTITEXCOORD2FVPROC __glewMultiTexCoord2fv = NULL; +PFNGLMULTITEXCOORD2IPROC __glewMultiTexCoord2i = NULL; +PFNGLMULTITEXCOORD2IVPROC __glewMultiTexCoord2iv = NULL; +PFNGLMULTITEXCOORD2SPROC __glewMultiTexCoord2s = NULL; +PFNGLMULTITEXCOORD2SVPROC __glewMultiTexCoord2sv = NULL; +PFNGLMULTITEXCOORD3DPROC __glewMultiTexCoord3d = NULL; +PFNGLMULTITEXCOORD3DVPROC __glewMultiTexCoord3dv = NULL; +PFNGLMULTITEXCOORD3FPROC __glewMultiTexCoord3f = NULL; +PFNGLMULTITEXCOORD3FVPROC __glewMultiTexCoord3fv = NULL; +PFNGLMULTITEXCOORD3IPROC __glewMultiTexCoord3i = NULL; +PFNGLMULTITEXCOORD3IVPROC __glewMultiTexCoord3iv = NULL; +PFNGLMULTITEXCOORD3SPROC __glewMultiTexCoord3s = NULL; +PFNGLMULTITEXCOORD3SVPROC __glewMultiTexCoord3sv = NULL; +PFNGLMULTITEXCOORD4DPROC __glewMultiTexCoord4d = NULL; +PFNGLMULTITEXCOORD4DVPROC __glewMultiTexCoord4dv = NULL; +PFNGLMULTITEXCOORD4FPROC __glewMultiTexCoord4f = NULL; +PFNGLMULTITEXCOORD4FVPROC __glewMultiTexCoord4fv = NULL; +PFNGLMULTITEXCOORD4IPROC __glewMultiTexCoord4i = NULL; +PFNGLMULTITEXCOORD4IVPROC __glewMultiTexCoord4iv = NULL; +PFNGLMULTITEXCOORD4SPROC __glewMultiTexCoord4s = NULL; +PFNGLMULTITEXCOORD4SVPROC __glewMultiTexCoord4sv = NULL; +PFNGLSAMPLECOVERAGEPROC __glewSampleCoverage = NULL; + +PFNGLBLENDCOLORPROC __glewBlendColor = NULL; +PFNGLBLENDEQUATIONPROC __glewBlendEquation = NULL; +PFNGLBLENDFUNCSEPARATEPROC __glewBlendFuncSeparate = NULL; +PFNGLFOGCOORDPOINTERPROC __glewFogCoordPointer = NULL; +PFNGLFOGCOORDDPROC __glewFogCoordd = NULL; +PFNGLFOGCOORDDVPROC __glewFogCoorddv = NULL; +PFNGLFOGCOORDFPROC __glewFogCoordf = NULL; +PFNGLFOGCOORDFVPROC __glewFogCoordfv = NULL; +PFNGLMULTIDRAWARRAYSPROC __glewMultiDrawArrays = NULL; +PFNGLMULTIDRAWELEMENTSPROC __glewMultiDrawElements = NULL; +PFNGLPOINTPARAMETERFPROC __glewPointParameterf = NULL; +PFNGLPOINTPARAMETERFVPROC __glewPointParameterfv = NULL; +PFNGLPOINTPARAMETERIPROC __glewPointParameteri = NULL; +PFNGLPOINTPARAMETERIVPROC __glewPointParameteriv = NULL; +PFNGLSECONDARYCOLOR3BPROC __glewSecondaryColor3b = NULL; +PFNGLSECONDARYCOLOR3BVPROC __glewSecondaryColor3bv = NULL; +PFNGLSECONDARYCOLOR3DPROC __glewSecondaryColor3d = NULL; +PFNGLSECONDARYCOLOR3DVPROC __glewSecondaryColor3dv = NULL; +PFNGLSECONDARYCOLOR3FPROC __glewSecondaryColor3f = NULL; +PFNGLSECONDARYCOLOR3FVPROC __glewSecondaryColor3fv = NULL; +PFNGLSECONDARYCOLOR3IPROC __glewSecondaryColor3i = NULL; +PFNGLSECONDARYCOLOR3IVPROC __glewSecondaryColor3iv = NULL; +PFNGLSECONDARYCOLOR3SPROC __glewSecondaryColor3s = NULL; +PFNGLSECONDARYCOLOR3SVPROC __glewSecondaryColor3sv = NULL; +PFNGLSECONDARYCOLOR3UBPROC __glewSecondaryColor3ub = NULL; +PFNGLSECONDARYCOLOR3UBVPROC __glewSecondaryColor3ubv = NULL; +PFNGLSECONDARYCOLOR3UIPROC __glewSecondaryColor3ui = NULL; +PFNGLSECONDARYCOLOR3UIVPROC __glewSecondaryColor3uiv = NULL; +PFNGLSECONDARYCOLOR3USPROC __glewSecondaryColor3us = NULL; +PFNGLSECONDARYCOLOR3USVPROC __glewSecondaryColor3usv = NULL; +PFNGLSECONDARYCOLORPOINTERPROC __glewSecondaryColorPointer = NULL; +PFNGLWINDOWPOS2DPROC __glewWindowPos2d = NULL; +PFNGLWINDOWPOS2DVPROC __glewWindowPos2dv = NULL; +PFNGLWINDOWPOS2FPROC __glewWindowPos2f = NULL; +PFNGLWINDOWPOS2FVPROC __glewWindowPos2fv = NULL; +PFNGLWINDOWPOS2IPROC __glewWindowPos2i = NULL; +PFNGLWINDOWPOS2IVPROC __glewWindowPos2iv = NULL; +PFNGLWINDOWPOS2SPROC __glewWindowPos2s = NULL; +PFNGLWINDOWPOS2SVPROC __glewWindowPos2sv = NULL; +PFNGLWINDOWPOS3DPROC __glewWindowPos3d = NULL; +PFNGLWINDOWPOS3DVPROC __glewWindowPos3dv = NULL; +PFNGLWINDOWPOS3FPROC __glewWindowPos3f = NULL; +PFNGLWINDOWPOS3FVPROC __glewWindowPos3fv = NULL; +PFNGLWINDOWPOS3IPROC __glewWindowPos3i = NULL; +PFNGLWINDOWPOS3IVPROC __glewWindowPos3iv = NULL; +PFNGLWINDOWPOS3SPROC __glewWindowPos3s = NULL; +PFNGLWINDOWPOS3SVPROC __glewWindowPos3sv = NULL; + +PFNGLBEGINQUERYPROC __glewBeginQuery = NULL; +PFNGLBINDBUFFERPROC __glewBindBuffer = NULL; +PFNGLBUFFERDATAPROC __glewBufferData = NULL; +PFNGLBUFFERSUBDATAPROC __glewBufferSubData = NULL; +PFNGLDELETEBUFFERSPROC __glewDeleteBuffers = NULL; +PFNGLDELETEQUERIESPROC __glewDeleteQueries = NULL; +PFNGLENDQUERYPROC __glewEndQuery = NULL; +PFNGLGENBUFFERSPROC __glewGenBuffers = NULL; +PFNGLGENQUERIESPROC __glewGenQueries = NULL; +PFNGLGETBUFFERPARAMETERIVPROC __glewGetBufferParameteriv = NULL; +PFNGLGETBUFFERPOINTERVPROC __glewGetBufferPointerv = NULL; +PFNGLGETBUFFERSUBDATAPROC __glewGetBufferSubData = NULL; +PFNGLGETQUERYOBJECTIVPROC __glewGetQueryObjectiv = NULL; +PFNGLGETQUERYOBJECTUIVPROC __glewGetQueryObjectuiv = NULL; +PFNGLGETQUERYIVPROC __glewGetQueryiv = NULL; +PFNGLISBUFFERPROC __glewIsBuffer = NULL; +PFNGLISQUERYPROC __glewIsQuery = NULL; +PFNGLMAPBUFFERPROC __glewMapBuffer = NULL; +PFNGLUNMAPBUFFERPROC __glewUnmapBuffer = NULL; + +PFNGLATTACHSHADERPROC __glewAttachShader = NULL; +PFNGLBINDATTRIBLOCATIONPROC __glewBindAttribLocation = NULL; +PFNGLBLENDEQUATIONSEPARATEPROC __glewBlendEquationSeparate = NULL; +PFNGLCOMPILESHADERPROC __glewCompileShader = NULL; +PFNGLCREATEPROGRAMPROC __glewCreateProgram = NULL; +PFNGLCREATESHADERPROC __glewCreateShader = NULL; +PFNGLDELETEPROGRAMPROC __glewDeleteProgram = NULL; +PFNGLDELETESHADERPROC __glewDeleteShader = NULL; +PFNGLDETACHSHADERPROC __glewDetachShader = NULL; +PFNGLDISABLEVERTEXATTRIBARRAYPROC __glewDisableVertexAttribArray = NULL; +PFNGLDRAWBUFFERSPROC __glewDrawBuffers = NULL; +PFNGLENABLEVERTEXATTRIBARRAYPROC __glewEnableVertexAttribArray = NULL; +PFNGLGETACTIVEATTRIBPROC __glewGetActiveAttrib = NULL; +PFNGLGETACTIVEUNIFORMPROC __glewGetActiveUniform = NULL; +PFNGLGETATTACHEDSHADERSPROC __glewGetAttachedShaders = NULL; +PFNGLGETATTRIBLOCATIONPROC __glewGetAttribLocation = NULL; +PFNGLGETPROGRAMINFOLOGPROC __glewGetProgramInfoLog = NULL; +PFNGLGETPROGRAMIVPROC __glewGetProgramiv = NULL; +PFNGLGETSHADERINFOLOGPROC __glewGetShaderInfoLog = NULL; +PFNGLGETSHADERSOURCEPROC __glewGetShaderSource = NULL; +PFNGLGETSHADERIVPROC __glewGetShaderiv = NULL; +PFNGLGETUNIFORMLOCATIONPROC __glewGetUniformLocation = NULL; +PFNGLGETUNIFORMFVPROC __glewGetUniformfv = NULL; +PFNGLGETUNIFORMIVPROC __glewGetUniformiv = NULL; +PFNGLGETVERTEXATTRIBPOINTERVPROC __glewGetVertexAttribPointerv = NULL; +PFNGLGETVERTEXATTRIBDVPROC __glewGetVertexAttribdv = NULL; +PFNGLGETVERTEXATTRIBFVPROC __glewGetVertexAttribfv = NULL; +PFNGLGETVERTEXATTRIBIVPROC __glewGetVertexAttribiv = NULL; +PFNGLISPROGRAMPROC __glewIsProgram = NULL; +PFNGLISSHADERPROC __glewIsShader = NULL; +PFNGLLINKPROGRAMPROC __glewLinkProgram = NULL; +PFNGLSHADERSOURCEPROC __glewShaderSource = NULL; +PFNGLSTENCILFUNCSEPARATEPROC __glewStencilFuncSeparate = NULL; +PFNGLSTENCILMASKSEPARATEPROC __glewStencilMaskSeparate = NULL; +PFNGLSTENCILOPSEPARATEPROC __glewStencilOpSeparate = NULL; +PFNGLUNIFORM1FPROC __glewUniform1f = NULL; +PFNGLUNIFORM1FVPROC __glewUniform1fv = NULL; +PFNGLUNIFORM1IPROC __glewUniform1i = NULL; +PFNGLUNIFORM1IVPROC __glewUniform1iv = NULL; +PFNGLUNIFORM2FPROC __glewUniform2f = NULL; +PFNGLUNIFORM2FVPROC __glewUniform2fv = NULL; +PFNGLUNIFORM2IPROC __glewUniform2i = NULL; +PFNGLUNIFORM2IVPROC __glewUniform2iv = NULL; +PFNGLUNIFORM3FPROC __glewUniform3f = NULL; +PFNGLUNIFORM3FVPROC __glewUniform3fv = NULL; +PFNGLUNIFORM3IPROC __glewUniform3i = NULL; +PFNGLUNIFORM3IVPROC __glewUniform3iv = NULL; +PFNGLUNIFORM4FPROC __glewUniform4f = NULL; +PFNGLUNIFORM4FVPROC __glewUniform4fv = NULL; +PFNGLUNIFORM4IPROC __glewUniform4i = NULL; +PFNGLUNIFORM4IVPROC __glewUniform4iv = NULL; +PFNGLUNIFORMMATRIX2FVPROC __glewUniformMatrix2fv = NULL; +PFNGLUNIFORMMATRIX3FVPROC __glewUniformMatrix3fv = NULL; +PFNGLUNIFORMMATRIX4FVPROC __glewUniformMatrix4fv = NULL; +PFNGLUSEPROGRAMPROC __glewUseProgram = NULL; +PFNGLVALIDATEPROGRAMPROC __glewValidateProgram = NULL; +PFNGLVERTEXATTRIB1DPROC __glewVertexAttrib1d = NULL; +PFNGLVERTEXATTRIB1DVPROC __glewVertexAttrib1dv = NULL; +PFNGLVERTEXATTRIB1FPROC __glewVertexAttrib1f = NULL; +PFNGLVERTEXATTRIB1FVPROC __glewVertexAttrib1fv = NULL; +PFNGLVERTEXATTRIB1SPROC __glewVertexAttrib1s = NULL; +PFNGLVERTEXATTRIB1SVPROC __glewVertexAttrib1sv = NULL; +PFNGLVERTEXATTRIB2DPROC __glewVertexAttrib2d = NULL; +PFNGLVERTEXATTRIB2DVPROC __glewVertexAttrib2dv = NULL; +PFNGLVERTEXATTRIB2FPROC __glewVertexAttrib2f = NULL; +PFNGLVERTEXATTRIB2FVPROC __glewVertexAttrib2fv = NULL; +PFNGLVERTEXATTRIB2SPROC __glewVertexAttrib2s = NULL; +PFNGLVERTEXATTRIB2SVPROC __glewVertexAttrib2sv = NULL; +PFNGLVERTEXATTRIB3DPROC __glewVertexAttrib3d = NULL; +PFNGLVERTEXATTRIB3DVPROC __glewVertexAttrib3dv = NULL; +PFNGLVERTEXATTRIB3FPROC __glewVertexAttrib3f = NULL; +PFNGLVERTEXATTRIB3FVPROC __glewVertexAttrib3fv = NULL; +PFNGLVERTEXATTRIB3SPROC __glewVertexAttrib3s = NULL; +PFNGLVERTEXATTRIB3SVPROC __glewVertexAttrib3sv = NULL; +PFNGLVERTEXATTRIB4NBVPROC __glewVertexAttrib4Nbv = NULL; +PFNGLVERTEXATTRIB4NIVPROC __glewVertexAttrib4Niv = NULL; +PFNGLVERTEXATTRIB4NSVPROC __glewVertexAttrib4Nsv = NULL; +PFNGLVERTEXATTRIB4NUBPROC __glewVertexAttrib4Nub = NULL; +PFNGLVERTEXATTRIB4NUBVPROC __glewVertexAttrib4Nubv = NULL; +PFNGLVERTEXATTRIB4NUIVPROC __glewVertexAttrib4Nuiv = NULL; +PFNGLVERTEXATTRIB4NUSVPROC __glewVertexAttrib4Nusv = NULL; +PFNGLVERTEXATTRIB4BVPROC __glewVertexAttrib4bv = NULL; +PFNGLVERTEXATTRIB4DPROC __glewVertexAttrib4d = NULL; +PFNGLVERTEXATTRIB4DVPROC __glewVertexAttrib4dv = NULL; +PFNGLVERTEXATTRIB4FPROC __glewVertexAttrib4f = NULL; +PFNGLVERTEXATTRIB4FVPROC __glewVertexAttrib4fv = NULL; +PFNGLVERTEXATTRIB4IVPROC __glewVertexAttrib4iv = NULL; +PFNGLVERTEXATTRIB4SPROC __glewVertexAttrib4s = NULL; +PFNGLVERTEXATTRIB4SVPROC __glewVertexAttrib4sv = NULL; +PFNGLVERTEXATTRIB4UBVPROC __glewVertexAttrib4ubv = NULL; +PFNGLVERTEXATTRIB4UIVPROC __glewVertexAttrib4uiv = NULL; +PFNGLVERTEXATTRIB4USVPROC __glewVertexAttrib4usv = NULL; +PFNGLVERTEXATTRIBPOINTERPROC __glewVertexAttribPointer = NULL; + +PFNGLUNIFORMMATRIX2X3FVPROC __glewUniformMatrix2x3fv = NULL; +PFNGLUNIFORMMATRIX2X4FVPROC __glewUniformMatrix2x4fv = NULL; +PFNGLUNIFORMMATRIX3X2FVPROC __glewUniformMatrix3x2fv = NULL; +PFNGLUNIFORMMATRIX3X4FVPROC __glewUniformMatrix3x4fv = NULL; +PFNGLUNIFORMMATRIX4X2FVPROC __glewUniformMatrix4x2fv = NULL; +PFNGLUNIFORMMATRIX4X3FVPROC __glewUniformMatrix4x3fv = NULL; + +PFNGLTBUFFERMASK3DFXPROC __glewTbufferMask3DFX = NULL; + +PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE = NULL; +PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE = NULL; +PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE = NULL; +PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC __glewMultiDrawElementArrayAPPLE = NULL; +PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC __glewMultiDrawRangeElementArrayAPPLE = NULL; + +PFNGLDELETEFENCESAPPLEPROC __glewDeleteFencesAPPLE = NULL; +PFNGLFINISHFENCEAPPLEPROC __glewFinishFenceAPPLE = NULL; +PFNGLFINISHOBJECTAPPLEPROC __glewFinishObjectAPPLE = NULL; +PFNGLGENFENCESAPPLEPROC __glewGenFencesAPPLE = NULL; +PFNGLISFENCEAPPLEPROC __glewIsFenceAPPLE = NULL; +PFNGLSETFENCEAPPLEPROC __glewSetFenceAPPLE = NULL; +PFNGLTESTFENCEAPPLEPROC __glewTestFenceAPPLE = NULL; +PFNGLTESTOBJECTAPPLEPROC __glewTestObjectAPPLE = NULL; + +PFNGLBUFFERPARAMETERIAPPLEPROC __glewBufferParameteriAPPLE = NULL; +PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC __glewFlushMappedBufferRangeAPPLE = NULL; + +PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC __glewGetTexParameterPointervAPPLE = NULL; +PFNGLTEXTURERANGEAPPLEPROC __glewTextureRangeAPPLE = NULL; + +PFNGLBINDVERTEXARRAYAPPLEPROC __glewBindVertexArrayAPPLE = NULL; +PFNGLDELETEVERTEXARRAYSAPPLEPROC __glewDeleteVertexArraysAPPLE = NULL; +PFNGLGENVERTEXARRAYSAPPLEPROC __glewGenVertexArraysAPPLE = NULL; +PFNGLISVERTEXARRAYAPPLEPROC __glewIsVertexArrayAPPLE = NULL; + +PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC __glewFlushVertexArrayRangeAPPLE = NULL; +PFNGLVERTEXARRAYPARAMETERIAPPLEPROC __glewVertexArrayParameteriAPPLE = NULL; +PFNGLVERTEXARRAYRANGEAPPLEPROC __glewVertexArrayRangeAPPLE = NULL; + +PFNGLCLAMPCOLORARBPROC __glewClampColorARB = NULL; + +PFNGLDRAWBUFFERSARBPROC __glewDrawBuffersARB = NULL; + +PFNGLCOLORSUBTABLEPROC __glewColorSubTable = NULL; +PFNGLCOLORTABLEPROC __glewColorTable = NULL; +PFNGLCOLORTABLEPARAMETERFVPROC __glewColorTableParameterfv = NULL; +PFNGLCOLORTABLEPARAMETERIVPROC __glewColorTableParameteriv = NULL; +PFNGLCONVOLUTIONFILTER1DPROC __glewConvolutionFilter1D = NULL; +PFNGLCONVOLUTIONFILTER2DPROC __glewConvolutionFilter2D = NULL; +PFNGLCONVOLUTIONPARAMETERFPROC __glewConvolutionParameterf = NULL; +PFNGLCONVOLUTIONPARAMETERFVPROC __glewConvolutionParameterfv = NULL; +PFNGLCONVOLUTIONPARAMETERIPROC __glewConvolutionParameteri = NULL; +PFNGLCONVOLUTIONPARAMETERIVPROC __glewConvolutionParameteriv = NULL; +PFNGLCOPYCOLORSUBTABLEPROC __glewCopyColorSubTable = NULL; +PFNGLCOPYCOLORTABLEPROC __glewCopyColorTable = NULL; +PFNGLCOPYCONVOLUTIONFILTER1DPROC __glewCopyConvolutionFilter1D = NULL; +PFNGLCOPYCONVOLUTIONFILTER2DPROC __glewCopyConvolutionFilter2D = NULL; +PFNGLGETCOLORTABLEPROC __glewGetColorTable = NULL; +PFNGLGETCOLORTABLEPARAMETERFVPROC __glewGetColorTableParameterfv = NULL; +PFNGLGETCOLORTABLEPARAMETERIVPROC __glewGetColorTableParameteriv = NULL; +PFNGLGETCONVOLUTIONFILTERPROC __glewGetConvolutionFilter = NULL; +PFNGLGETCONVOLUTIONPARAMETERFVPROC __glewGetConvolutionParameterfv = NULL; +PFNGLGETCONVOLUTIONPARAMETERIVPROC __glewGetConvolutionParameteriv = NULL; +PFNGLGETHISTOGRAMPROC __glewGetHistogram = NULL; +PFNGLGETHISTOGRAMPARAMETERFVPROC __glewGetHistogramParameterfv = NULL; +PFNGLGETHISTOGRAMPARAMETERIVPROC __glewGetHistogramParameteriv = NULL; +PFNGLGETMINMAXPROC __glewGetMinmax = NULL; +PFNGLGETMINMAXPARAMETERFVPROC __glewGetMinmaxParameterfv = NULL; +PFNGLGETMINMAXPARAMETERIVPROC __glewGetMinmaxParameteriv = NULL; +PFNGLGETSEPARABLEFILTERPROC __glewGetSeparableFilter = NULL; +PFNGLHISTOGRAMPROC __glewHistogram = NULL; +PFNGLMINMAXPROC __glewMinmax = NULL; +PFNGLRESETHISTOGRAMPROC __glewResetHistogram = NULL; +PFNGLRESETMINMAXPROC __glewResetMinmax = NULL; +PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D = NULL; + +PFNGLCURRENTPALETTEMATRIXARBPROC __glewCurrentPaletteMatrixARB = NULL; +PFNGLMATRIXINDEXPOINTERARBPROC __glewMatrixIndexPointerARB = NULL; +PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB = NULL; +PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB = NULL; +PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB = NULL; + +PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB = NULL; + +PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB = NULL; +PFNGLCLIENTACTIVETEXTUREARBPROC __glewClientActiveTextureARB = NULL; +PFNGLMULTITEXCOORD1DARBPROC __glewMultiTexCoord1dARB = NULL; +PFNGLMULTITEXCOORD1DVARBPROC __glewMultiTexCoord1dvARB = NULL; +PFNGLMULTITEXCOORD1FARBPROC __glewMultiTexCoord1fARB = NULL; +PFNGLMULTITEXCOORD1FVARBPROC __glewMultiTexCoord1fvARB = NULL; +PFNGLMULTITEXCOORD1IARBPROC __glewMultiTexCoord1iARB = NULL; +PFNGLMULTITEXCOORD1IVARBPROC __glewMultiTexCoord1ivARB = NULL; +PFNGLMULTITEXCOORD1SARBPROC __glewMultiTexCoord1sARB = NULL; +PFNGLMULTITEXCOORD1SVARBPROC __glewMultiTexCoord1svARB = NULL; +PFNGLMULTITEXCOORD2DARBPROC __glewMultiTexCoord2dARB = NULL; +PFNGLMULTITEXCOORD2DVARBPROC __glewMultiTexCoord2dvARB = NULL; +PFNGLMULTITEXCOORD2FARBPROC __glewMultiTexCoord2fARB = NULL; +PFNGLMULTITEXCOORD2FVARBPROC __glewMultiTexCoord2fvARB = NULL; +PFNGLMULTITEXCOORD2IARBPROC __glewMultiTexCoord2iARB = NULL; +PFNGLMULTITEXCOORD2IVARBPROC __glewMultiTexCoord2ivARB = NULL; +PFNGLMULTITEXCOORD2SARBPROC __glewMultiTexCoord2sARB = NULL; +PFNGLMULTITEXCOORD2SVARBPROC __glewMultiTexCoord2svARB = NULL; +PFNGLMULTITEXCOORD3DARBPROC __glewMultiTexCoord3dARB = NULL; +PFNGLMULTITEXCOORD3DVARBPROC __glewMultiTexCoord3dvARB = NULL; +PFNGLMULTITEXCOORD3FARBPROC __glewMultiTexCoord3fARB = NULL; +PFNGLMULTITEXCOORD3FVARBPROC __glewMultiTexCoord3fvARB = NULL; +PFNGLMULTITEXCOORD3IARBPROC __glewMultiTexCoord3iARB = NULL; +PFNGLMULTITEXCOORD3IVARBPROC __glewMultiTexCoord3ivARB = NULL; +PFNGLMULTITEXCOORD3SARBPROC __glewMultiTexCoord3sARB = NULL; +PFNGLMULTITEXCOORD3SVARBPROC __glewMultiTexCoord3svARB = NULL; +PFNGLMULTITEXCOORD4DARBPROC __glewMultiTexCoord4dARB = NULL; +PFNGLMULTITEXCOORD4DVARBPROC __glewMultiTexCoord4dvARB = NULL; +PFNGLMULTITEXCOORD4FARBPROC __glewMultiTexCoord4fARB = NULL; +PFNGLMULTITEXCOORD4FVARBPROC __glewMultiTexCoord4fvARB = NULL; +PFNGLMULTITEXCOORD4IARBPROC __glewMultiTexCoord4iARB = NULL; +PFNGLMULTITEXCOORD4IVARBPROC __glewMultiTexCoord4ivARB = NULL; +PFNGLMULTITEXCOORD4SARBPROC __glewMultiTexCoord4sARB = NULL; +PFNGLMULTITEXCOORD4SVARBPROC __glewMultiTexCoord4svARB = NULL; + +PFNGLBEGINQUERYARBPROC __glewBeginQueryARB = NULL; +PFNGLDELETEQUERIESARBPROC __glewDeleteQueriesARB = NULL; +PFNGLENDQUERYARBPROC __glewEndQueryARB = NULL; +PFNGLGENQUERIESARBPROC __glewGenQueriesARB = NULL; +PFNGLGETQUERYOBJECTIVARBPROC __glewGetQueryObjectivARB = NULL; +PFNGLGETQUERYOBJECTUIVARBPROC __glewGetQueryObjectuivARB = NULL; +PFNGLGETQUERYIVARBPROC __glewGetQueryivARB = NULL; +PFNGLISQUERYARBPROC __glewIsQueryARB = NULL; + +PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB = NULL; +PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB = NULL; + +PFNGLATTACHOBJECTARBPROC __glewAttachObjectARB = NULL; +PFNGLCOMPILESHADERARBPROC __glewCompileShaderARB = NULL; +PFNGLCREATEPROGRAMOBJECTARBPROC __glewCreateProgramObjectARB = NULL; +PFNGLCREATESHADEROBJECTARBPROC __glewCreateShaderObjectARB = NULL; +PFNGLDELETEOBJECTARBPROC __glewDeleteObjectARB = NULL; +PFNGLDETACHOBJECTARBPROC __glewDetachObjectARB = NULL; +PFNGLGETACTIVEUNIFORMARBPROC __glewGetActiveUniformARB = NULL; +PFNGLGETATTACHEDOBJECTSARBPROC __glewGetAttachedObjectsARB = NULL; +PFNGLGETHANDLEARBPROC __glewGetHandleARB = NULL; +PFNGLGETINFOLOGARBPROC __glewGetInfoLogARB = NULL; +PFNGLGETOBJECTPARAMETERFVARBPROC __glewGetObjectParameterfvARB = NULL; +PFNGLGETOBJECTPARAMETERIVARBPROC __glewGetObjectParameterivARB = NULL; +PFNGLGETSHADERSOURCEARBPROC __glewGetShaderSourceARB = NULL; +PFNGLGETUNIFORMLOCATIONARBPROC __glewGetUniformLocationARB = NULL; +PFNGLGETUNIFORMFVARBPROC __glewGetUniformfvARB = NULL; +PFNGLGETUNIFORMIVARBPROC __glewGetUniformivARB = NULL; +PFNGLLINKPROGRAMARBPROC __glewLinkProgramARB = NULL; +PFNGLSHADERSOURCEARBPROC __glewShaderSourceARB = NULL; +PFNGLUNIFORM1FARBPROC __glewUniform1fARB = NULL; +PFNGLUNIFORM1FVARBPROC __glewUniform1fvARB = NULL; +PFNGLUNIFORM1IARBPROC __glewUniform1iARB = NULL; +PFNGLUNIFORM1IVARBPROC __glewUniform1ivARB = NULL; +PFNGLUNIFORM2FARBPROC __glewUniform2fARB = NULL; +PFNGLUNIFORM2FVARBPROC __glewUniform2fvARB = NULL; +PFNGLUNIFORM2IARBPROC __glewUniform2iARB = NULL; +PFNGLUNIFORM2IVARBPROC __glewUniform2ivARB = NULL; +PFNGLUNIFORM3FARBPROC __glewUniform3fARB = NULL; +PFNGLUNIFORM3FVARBPROC __glewUniform3fvARB = NULL; +PFNGLUNIFORM3IARBPROC __glewUniform3iARB = NULL; +PFNGLUNIFORM3IVARBPROC __glewUniform3ivARB = NULL; +PFNGLUNIFORM4FARBPROC __glewUniform4fARB = NULL; +PFNGLUNIFORM4FVARBPROC __glewUniform4fvARB = NULL; +PFNGLUNIFORM4IARBPROC __glewUniform4iARB = NULL; +PFNGLUNIFORM4IVARBPROC __glewUniform4ivARB = NULL; +PFNGLUNIFORMMATRIX2FVARBPROC __glewUniformMatrix2fvARB = NULL; +PFNGLUNIFORMMATRIX3FVARBPROC __glewUniformMatrix3fvARB = NULL; +PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB = NULL; +PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB = NULL; +PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB = NULL; + +PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB = NULL; +PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB = NULL; +PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC __glewCompressedTexSubImage1DARB = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC __glewCompressedTexSubImage2DARB = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC __glewCompressedTexSubImage3DARB = NULL; +PFNGLGETCOMPRESSEDTEXIMAGEARBPROC __glewGetCompressedTexImageARB = NULL; + +PFNGLLOADTRANSPOSEMATRIXDARBPROC __glewLoadTransposeMatrixdARB = NULL; +PFNGLLOADTRANSPOSEMATRIXFARBPROC __glewLoadTransposeMatrixfARB = NULL; +PFNGLMULTTRANSPOSEMATRIXDARBPROC __glewMultTransposeMatrixdARB = NULL; +PFNGLMULTTRANSPOSEMATRIXFARBPROC __glewMultTransposeMatrixfARB = NULL; + +PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB = NULL; +PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB = NULL; +PFNGLWEIGHTBVARBPROC __glewWeightbvARB = NULL; +PFNGLWEIGHTDVARBPROC __glewWeightdvARB = NULL; +PFNGLWEIGHTFVARBPROC __glewWeightfvARB = NULL; +PFNGLWEIGHTIVARBPROC __glewWeightivARB = NULL; +PFNGLWEIGHTSVARBPROC __glewWeightsvARB = NULL; +PFNGLWEIGHTUBVARBPROC __glewWeightubvARB = NULL; +PFNGLWEIGHTUIVARBPROC __glewWeightuivARB = NULL; +PFNGLWEIGHTUSVARBPROC __glewWeightusvARB = NULL; + +PFNGLBINDBUFFERARBPROC __glewBindBufferARB = NULL; +PFNGLBUFFERDATAARBPROC __glewBufferDataARB = NULL; +PFNGLBUFFERSUBDATAARBPROC __glewBufferSubDataARB = NULL; +PFNGLDELETEBUFFERSARBPROC __glewDeleteBuffersARB = NULL; +PFNGLGENBUFFERSARBPROC __glewGenBuffersARB = NULL; +PFNGLGETBUFFERPARAMETERIVARBPROC __glewGetBufferParameterivARB = NULL; +PFNGLGETBUFFERPOINTERVARBPROC __glewGetBufferPointervARB = NULL; +PFNGLGETBUFFERSUBDATAARBPROC __glewGetBufferSubDataARB = NULL; +PFNGLISBUFFERARBPROC __glewIsBufferARB = NULL; +PFNGLMAPBUFFERARBPROC __glewMapBufferARB = NULL; +PFNGLUNMAPBUFFERARBPROC __glewUnmapBufferARB = NULL; + +PFNGLBINDPROGRAMARBPROC __glewBindProgramARB = NULL; +PFNGLDELETEPROGRAMSARBPROC __glewDeleteProgramsARB = NULL; +PFNGLDISABLEVERTEXATTRIBARRAYARBPROC __glewDisableVertexAttribArrayARB = NULL; +PFNGLENABLEVERTEXATTRIBARRAYARBPROC __glewEnableVertexAttribArrayARB = NULL; +PFNGLGENPROGRAMSARBPROC __glewGenProgramsARB = NULL; +PFNGLGETPROGRAMENVPARAMETERDVARBPROC __glewGetProgramEnvParameterdvARB = NULL; +PFNGLGETPROGRAMENVPARAMETERFVARBPROC __glewGetProgramEnvParameterfvARB = NULL; +PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC __glewGetProgramLocalParameterdvARB = NULL; +PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC __glewGetProgramLocalParameterfvARB = NULL; +PFNGLGETPROGRAMSTRINGARBPROC __glewGetProgramStringARB = NULL; +PFNGLGETPROGRAMIVARBPROC __glewGetProgramivARB = NULL; +PFNGLGETVERTEXATTRIBPOINTERVARBPROC __glewGetVertexAttribPointervARB = NULL; +PFNGLGETVERTEXATTRIBDVARBPROC __glewGetVertexAttribdvARB = NULL; +PFNGLGETVERTEXATTRIBFVARBPROC __glewGetVertexAttribfvARB = NULL; +PFNGLGETVERTEXATTRIBIVARBPROC __glewGetVertexAttribivARB = NULL; +PFNGLISPROGRAMARBPROC __glewIsProgramARB = NULL; +PFNGLPROGRAMENVPARAMETER4DARBPROC __glewProgramEnvParameter4dARB = NULL; +PFNGLPROGRAMENVPARAMETER4DVARBPROC __glewProgramEnvParameter4dvARB = NULL; +PFNGLPROGRAMENVPARAMETER4FARBPROC __glewProgramEnvParameter4fARB = NULL; +PFNGLPROGRAMENVPARAMETER4FVARBPROC __glewProgramEnvParameter4fvARB = NULL; +PFNGLPROGRAMLOCALPARAMETER4DARBPROC __glewProgramLocalParameter4dARB = NULL; +PFNGLPROGRAMLOCALPARAMETER4DVARBPROC __glewProgramLocalParameter4dvARB = NULL; +PFNGLPROGRAMLOCALPARAMETER4FARBPROC __glewProgramLocalParameter4fARB = NULL; +PFNGLPROGRAMLOCALPARAMETER4FVARBPROC __glewProgramLocalParameter4fvARB = NULL; +PFNGLPROGRAMSTRINGARBPROC __glewProgramStringARB = NULL; +PFNGLVERTEXATTRIB1DARBPROC __glewVertexAttrib1dARB = NULL; +PFNGLVERTEXATTRIB1DVARBPROC __glewVertexAttrib1dvARB = NULL; +PFNGLVERTEXATTRIB1FARBPROC __glewVertexAttrib1fARB = NULL; +PFNGLVERTEXATTRIB1FVARBPROC __glewVertexAttrib1fvARB = NULL; +PFNGLVERTEXATTRIB1SARBPROC __glewVertexAttrib1sARB = NULL; +PFNGLVERTEXATTRIB1SVARBPROC __glewVertexAttrib1svARB = NULL; +PFNGLVERTEXATTRIB2DARBPROC __glewVertexAttrib2dARB = NULL; +PFNGLVERTEXATTRIB2DVARBPROC __glewVertexAttrib2dvARB = NULL; +PFNGLVERTEXATTRIB2FARBPROC __glewVertexAttrib2fARB = NULL; +PFNGLVERTEXATTRIB2FVARBPROC __glewVertexAttrib2fvARB = NULL; +PFNGLVERTEXATTRIB2SARBPROC __glewVertexAttrib2sARB = NULL; +PFNGLVERTEXATTRIB2SVARBPROC __glewVertexAttrib2svARB = NULL; +PFNGLVERTEXATTRIB3DARBPROC __glewVertexAttrib3dARB = NULL; +PFNGLVERTEXATTRIB3DVARBPROC __glewVertexAttrib3dvARB = NULL; +PFNGLVERTEXATTRIB3FARBPROC __glewVertexAttrib3fARB = NULL; +PFNGLVERTEXATTRIB3FVARBPROC __glewVertexAttrib3fvARB = NULL; +PFNGLVERTEXATTRIB3SARBPROC __glewVertexAttrib3sARB = NULL; +PFNGLVERTEXATTRIB3SVARBPROC __glewVertexAttrib3svARB = NULL; +PFNGLVERTEXATTRIB4NBVARBPROC __glewVertexAttrib4NbvARB = NULL; +PFNGLVERTEXATTRIB4NIVARBPROC __glewVertexAttrib4NivARB = NULL; +PFNGLVERTEXATTRIB4NSVARBPROC __glewVertexAttrib4NsvARB = NULL; +PFNGLVERTEXATTRIB4NUBARBPROC __glewVertexAttrib4NubARB = NULL; +PFNGLVERTEXATTRIB4NUBVARBPROC __glewVertexAttrib4NubvARB = NULL; +PFNGLVERTEXATTRIB4NUIVARBPROC __glewVertexAttrib4NuivARB = NULL; +PFNGLVERTEXATTRIB4NUSVARBPROC __glewVertexAttrib4NusvARB = NULL; +PFNGLVERTEXATTRIB4BVARBPROC __glewVertexAttrib4bvARB = NULL; +PFNGLVERTEXATTRIB4DARBPROC __glewVertexAttrib4dARB = NULL; +PFNGLVERTEXATTRIB4DVARBPROC __glewVertexAttrib4dvARB = NULL; +PFNGLVERTEXATTRIB4FARBPROC __glewVertexAttrib4fARB = NULL; +PFNGLVERTEXATTRIB4FVARBPROC __glewVertexAttrib4fvARB = NULL; +PFNGLVERTEXATTRIB4IVARBPROC __glewVertexAttrib4ivARB = NULL; +PFNGLVERTEXATTRIB4SARBPROC __glewVertexAttrib4sARB = NULL; +PFNGLVERTEXATTRIB4SVARBPROC __glewVertexAttrib4svARB = NULL; +PFNGLVERTEXATTRIB4UBVARBPROC __glewVertexAttrib4ubvARB = NULL; +PFNGLVERTEXATTRIB4UIVARBPROC __glewVertexAttrib4uivARB = NULL; +PFNGLVERTEXATTRIB4USVARBPROC __glewVertexAttrib4usvARB = NULL; +PFNGLVERTEXATTRIBPOINTERARBPROC __glewVertexAttribPointerARB = NULL; + +PFNGLBINDATTRIBLOCATIONARBPROC __glewBindAttribLocationARB = NULL; +PFNGLGETACTIVEATTRIBARBPROC __glewGetActiveAttribARB = NULL; +PFNGLGETATTRIBLOCATIONARBPROC __glewGetAttribLocationARB = NULL; + +PFNGLWINDOWPOS2DARBPROC __glewWindowPos2dARB = NULL; +PFNGLWINDOWPOS2DVARBPROC __glewWindowPos2dvARB = NULL; +PFNGLWINDOWPOS2FARBPROC __glewWindowPos2fARB = NULL; +PFNGLWINDOWPOS2FVARBPROC __glewWindowPos2fvARB = NULL; +PFNGLWINDOWPOS2IARBPROC __glewWindowPos2iARB = NULL; +PFNGLWINDOWPOS2IVARBPROC __glewWindowPos2ivARB = NULL; +PFNGLWINDOWPOS2SARBPROC __glewWindowPos2sARB = NULL; +PFNGLWINDOWPOS2SVARBPROC __glewWindowPos2svARB = NULL; +PFNGLWINDOWPOS3DARBPROC __glewWindowPos3dARB = NULL; +PFNGLWINDOWPOS3DVARBPROC __glewWindowPos3dvARB = NULL; +PFNGLWINDOWPOS3FARBPROC __glewWindowPos3fARB = NULL; +PFNGLWINDOWPOS3FVARBPROC __glewWindowPos3fvARB = NULL; +PFNGLWINDOWPOS3IARBPROC __glewWindowPos3iARB = NULL; +PFNGLWINDOWPOS3IVARBPROC __glewWindowPos3ivARB = NULL; +PFNGLWINDOWPOS3SARBPROC __glewWindowPos3sARB = NULL; +PFNGLWINDOWPOS3SVARBPROC __glewWindowPos3svARB = NULL; + +PFNGLDRAWBUFFERSATIPROC __glewDrawBuffersATI = NULL; + +PFNGLDRAWELEMENTARRAYATIPROC __glewDrawElementArrayATI = NULL; +PFNGLDRAWRANGEELEMENTARRAYATIPROC __glewDrawRangeElementArrayATI = NULL; +PFNGLELEMENTPOINTERATIPROC __glewElementPointerATI = NULL; + +PFNGLGETTEXBUMPPARAMETERFVATIPROC __glewGetTexBumpParameterfvATI = NULL; +PFNGLGETTEXBUMPPARAMETERIVATIPROC __glewGetTexBumpParameterivATI = NULL; +PFNGLTEXBUMPPARAMETERFVATIPROC __glewTexBumpParameterfvATI = NULL; +PFNGLTEXBUMPPARAMETERIVATIPROC __glewTexBumpParameterivATI = NULL; + +PFNGLALPHAFRAGMENTOP1ATIPROC __glewAlphaFragmentOp1ATI = NULL; +PFNGLALPHAFRAGMENTOP2ATIPROC __glewAlphaFragmentOp2ATI = NULL; +PFNGLALPHAFRAGMENTOP3ATIPROC __glewAlphaFragmentOp3ATI = NULL; +PFNGLBEGINFRAGMENTSHADERATIPROC __glewBeginFragmentShaderATI = NULL; +PFNGLBINDFRAGMENTSHADERATIPROC __glewBindFragmentShaderATI = NULL; +PFNGLCOLORFRAGMENTOP1ATIPROC __glewColorFragmentOp1ATI = NULL; +PFNGLCOLORFRAGMENTOP2ATIPROC __glewColorFragmentOp2ATI = NULL; +PFNGLCOLORFRAGMENTOP3ATIPROC __glewColorFragmentOp3ATI = NULL; +PFNGLDELETEFRAGMENTSHADERATIPROC __glewDeleteFragmentShaderATI = NULL; +PFNGLENDFRAGMENTSHADERATIPROC __glewEndFragmentShaderATI = NULL; +PFNGLGENFRAGMENTSHADERSATIPROC __glewGenFragmentShadersATI = NULL; +PFNGLPASSTEXCOORDATIPROC __glewPassTexCoordATI = NULL; +PFNGLSAMPLEMAPATIPROC __glewSampleMapATI = NULL; +PFNGLSETFRAGMENTSHADERCONSTANTATIPROC __glewSetFragmentShaderConstantATI = NULL; + +PFNGLMAPOBJECTBUFFERATIPROC __glewMapObjectBufferATI = NULL; +PFNGLUNMAPOBJECTBUFFERATIPROC __glewUnmapObjectBufferATI = NULL; + +PFNGLPNTRIANGLESFATIPROC __glPNTrianglewesfATI = NULL; +PFNGLPNTRIANGLESIATIPROC __glPNTrianglewesiATI = NULL; + +PFNGLSTENCILFUNCSEPARATEATIPROC __glewStencilFuncSeparateATI = NULL; +PFNGLSTENCILOPSEPARATEATIPROC __glewStencilOpSeparateATI = NULL; + +PFNGLARRAYOBJECTATIPROC __glewArrayObjectATI = NULL; +PFNGLFREEOBJECTBUFFERATIPROC __glewFreeObjectBufferATI = NULL; +PFNGLGETARRAYOBJECTFVATIPROC __glewGetArrayObjectfvATI = NULL; +PFNGLGETARRAYOBJECTIVATIPROC __glewGetArrayObjectivATI = NULL; +PFNGLGETOBJECTBUFFERFVATIPROC __glewGetObjectBufferfvATI = NULL; +PFNGLGETOBJECTBUFFERIVATIPROC __glewGetObjectBufferivATI = NULL; +PFNGLGETVARIANTARRAYOBJECTFVATIPROC __glewGetVariantArrayObjectfvATI = NULL; +PFNGLGETVARIANTARRAYOBJECTIVATIPROC __glewGetVariantArrayObjectivATI = NULL; +PFNGLISOBJECTBUFFERATIPROC __glewIsObjectBufferATI = NULL; +PFNGLNEWOBJECTBUFFERATIPROC __glewNewObjectBufferATI = NULL; +PFNGLUPDATEOBJECTBUFFERATIPROC __glewUpdateObjectBufferATI = NULL; +PFNGLVARIANTARRAYOBJECTATIPROC __glewVariantArrayObjectATI = NULL; + +PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC __glewGetVertexAttribArrayObjectfvATI = NULL; +PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC __glewGetVertexAttribArrayObjectivATI = NULL; +PFNGLVERTEXATTRIBARRAYOBJECTATIPROC __glewVertexAttribArrayObjectATI = NULL; + +PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC __glewClientActiveVertexStreamATI = NULL; +PFNGLNORMALSTREAM3BATIPROC __glewNormalStream3bATI = NULL; +PFNGLNORMALSTREAM3BVATIPROC __glewNormalStream3bvATI = NULL; +PFNGLNORMALSTREAM3DATIPROC __glewNormalStream3dATI = NULL; +PFNGLNORMALSTREAM3DVATIPROC __glewNormalStream3dvATI = NULL; +PFNGLNORMALSTREAM3FATIPROC __glewNormalStream3fATI = NULL; +PFNGLNORMALSTREAM3FVATIPROC __glewNormalStream3fvATI = NULL; +PFNGLNORMALSTREAM3IATIPROC __glewNormalStream3iATI = NULL; +PFNGLNORMALSTREAM3IVATIPROC __glewNormalStream3ivATI = NULL; +PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI = NULL; +PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI = NULL; +PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI = NULL; +PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI = NULL; +PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI = NULL; +PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI = NULL; +PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI = NULL; +PFNGLVERTEXSTREAM2FVATIPROC __glewVertexStream2fvATI = NULL; +PFNGLVERTEXSTREAM2IATIPROC __glewVertexStream2iATI = NULL; +PFNGLVERTEXSTREAM2IVATIPROC __glewVertexStream2ivATI = NULL; +PFNGLVERTEXSTREAM2SATIPROC __glewVertexStream2sATI = NULL; +PFNGLVERTEXSTREAM2SVATIPROC __glewVertexStream2svATI = NULL; +PFNGLVERTEXSTREAM3DATIPROC __glewVertexStream3dATI = NULL; +PFNGLVERTEXSTREAM3DVATIPROC __glewVertexStream3dvATI = NULL; +PFNGLVERTEXSTREAM3FATIPROC __glewVertexStream3fATI = NULL; +PFNGLVERTEXSTREAM3FVATIPROC __glewVertexStream3fvATI = NULL; +PFNGLVERTEXSTREAM3IATIPROC __glewVertexStream3iATI = NULL; +PFNGLVERTEXSTREAM3IVATIPROC __glewVertexStream3ivATI = NULL; +PFNGLVERTEXSTREAM3SATIPROC __glewVertexStream3sATI = NULL; +PFNGLVERTEXSTREAM3SVATIPROC __glewVertexStream3svATI = NULL; +PFNGLVERTEXSTREAM4DATIPROC __glewVertexStream4dATI = NULL; +PFNGLVERTEXSTREAM4DVATIPROC __glewVertexStream4dvATI = NULL; +PFNGLVERTEXSTREAM4FATIPROC __glewVertexStream4fATI = NULL; +PFNGLVERTEXSTREAM4FVATIPROC __glewVertexStream4fvATI = NULL; +PFNGLVERTEXSTREAM4IATIPROC __glewVertexStream4iATI = NULL; +PFNGLVERTEXSTREAM4IVATIPROC __glewVertexStream4ivATI = NULL; +PFNGLVERTEXSTREAM4SATIPROC __glewVertexStream4sATI = NULL; +PFNGLVERTEXSTREAM4SVATIPROC __glewVertexStream4svATI = NULL; + +PFNGLGETUNIFORMBUFFERSIZEEXTPROC __glewGetUniformBufferSizeEXT = NULL; +PFNGLGETUNIFORMOFFSETEXTPROC __glewGetUniformOffsetEXT = NULL; +PFNGLUNIFORMBUFFEREXTPROC __glewUniformBufferEXT = NULL; + +PFNGLBLENDCOLOREXTPROC __glewBlendColorEXT = NULL; + +PFNGLBLENDEQUATIONSEPARATEEXTPROC __glewBlendEquationSeparateEXT = NULL; + +PFNGLBLENDFUNCSEPARATEEXTPROC __glewBlendFuncSeparateEXT = NULL; + +PFNGLBLENDEQUATIONEXTPROC __glewBlendEquationEXT = NULL; + +PFNGLCOLORSUBTABLEEXTPROC __glewColorSubTableEXT = NULL; +PFNGLCOPYCOLORSUBTABLEEXTPROC __glewCopyColorSubTableEXT = NULL; + +PFNGLLOCKARRAYSEXTPROC __glewLockArraysEXT = NULL; +PFNGLUNLOCKARRAYSEXTPROC __glewUnlockArraysEXT = NULL; + +PFNGLCONVOLUTIONFILTER1DEXTPROC __glewConvolutionFilter1DEXT = NULL; +PFNGLCONVOLUTIONFILTER2DEXTPROC __glewConvolutionFilter2DEXT = NULL; +PFNGLCONVOLUTIONPARAMETERFEXTPROC __glewConvolutionParameterfEXT = NULL; +PFNGLCONVOLUTIONPARAMETERFVEXTPROC __glewConvolutionParameterfvEXT = NULL; +PFNGLCONVOLUTIONPARAMETERIEXTPROC __glewConvolutionParameteriEXT = NULL; +PFNGLCONVOLUTIONPARAMETERIVEXTPROC __glewConvolutionParameterivEXT = NULL; +PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC __glewCopyConvolutionFilter1DEXT = NULL; +PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC __glewCopyConvolutionFilter2DEXT = NULL; +PFNGLGETCONVOLUTIONFILTEREXTPROC __glewGetConvolutionFilterEXT = NULL; +PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC __glewGetConvolutionParameterfvEXT = NULL; +PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC __glewGetConvolutionParameterivEXT = NULL; +PFNGLGETSEPARABLEFILTEREXTPROC __glewGetSeparableFilterEXT = NULL; +PFNGLSEPARABLEFILTER2DEXTPROC __glewSeparableFilter2DEXT = NULL; + +PFNGLBINORMALPOINTEREXTPROC __glewBinormalPointerEXT = NULL; +PFNGLTANGENTPOINTEREXTPROC __glewTangentPointerEXT = NULL; + +PFNGLCOPYTEXIMAGE1DEXTPROC __glewCopyTexImage1DEXT = NULL; +PFNGLCOPYTEXIMAGE2DEXTPROC __glewCopyTexImage2DEXT = NULL; +PFNGLCOPYTEXSUBIMAGE1DEXTPROC __glewCopyTexSubImage1DEXT = NULL; +PFNGLCOPYTEXSUBIMAGE2DEXTPROC __glewCopyTexSubImage2DEXT = NULL; +PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT = NULL; + +PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT = NULL; +PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT = NULL; + +PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT = NULL; + +PFNGLCOLORMASKINDEXEDEXTPROC __glewColorMaskIndexedEXT = NULL; +PFNGLDISABLEINDEXEDEXTPROC __glewDisableIndexedEXT = NULL; +PFNGLENABLEINDEXEDEXTPROC __glewEnableIndexedEXT = NULL; +PFNGLGETBOOLEANINDEXEDVEXTPROC __glewGetBooleanIndexedvEXT = NULL; +PFNGLGETINTEGERINDEXEDVEXTPROC __glewGetIntegerIndexedvEXT = NULL; +PFNGLISENABLEDINDEXEDEXTPROC __glewIsEnabledIndexedEXT = NULL; + +PFNGLDRAWARRAYSINSTANCEDEXTPROC __glewDrawArraysInstancedEXT = NULL; +PFNGLDRAWELEMENTSINSTANCEDEXTPROC __glewDrawElementsInstancedEXT = NULL; + +PFNGLDRAWRANGEELEMENTSEXTPROC __glewDrawRangeElementsEXT = NULL; + +PFNGLFOGCOORDPOINTEREXTPROC __glewFogCoordPointerEXT = NULL; +PFNGLFOGCOORDDEXTPROC __glewFogCoorddEXT = NULL; +PFNGLFOGCOORDDVEXTPROC __glewFogCoorddvEXT = NULL; +PFNGLFOGCOORDFEXTPROC __glewFogCoordfEXT = NULL; +PFNGLFOGCOORDFVEXTPROC __glewFogCoordfvEXT = NULL; + +PFNGLFRAGMENTCOLORMATERIALEXTPROC __glewFragmentColorMaterialEXT = NULL; +PFNGLFRAGMENTLIGHTMODELFEXTPROC __glewFragmentLightModelfEXT = NULL; +PFNGLFRAGMENTLIGHTMODELFVEXTPROC __glewFragmentLightModelfvEXT = NULL; +PFNGLFRAGMENTLIGHTMODELIEXTPROC __glewFragmentLightModeliEXT = NULL; +PFNGLFRAGMENTLIGHTMODELIVEXTPROC __glewFragmentLightModelivEXT = NULL; +PFNGLFRAGMENTLIGHTFEXTPROC __glewFragmentLightfEXT = NULL; +PFNGLFRAGMENTLIGHTFVEXTPROC __glewFragmentLightfvEXT = NULL; +PFNGLFRAGMENTLIGHTIEXTPROC __glewFragmentLightiEXT = NULL; +PFNGLFRAGMENTLIGHTIVEXTPROC __glewFragmentLightivEXT = NULL; +PFNGLFRAGMENTMATERIALFEXTPROC __glewFragmentMaterialfEXT = NULL; +PFNGLFRAGMENTMATERIALFVEXTPROC __glewFragmentMaterialfvEXT = NULL; +PFNGLFRAGMENTMATERIALIEXTPROC __glewFragmentMaterialiEXT = NULL; +PFNGLFRAGMENTMATERIALIVEXTPROC __glewFragmentMaterialivEXT = NULL; +PFNGLGETFRAGMENTLIGHTFVEXTPROC __glewGetFragmentLightfvEXT = NULL; +PFNGLGETFRAGMENTLIGHTIVEXTPROC __glewGetFragmentLightivEXT = NULL; +PFNGLGETFRAGMENTMATERIALFVEXTPROC __glewGetFragmentMaterialfvEXT = NULL; +PFNGLGETFRAGMENTMATERIALIVEXTPROC __glewGetFragmentMaterialivEXT = NULL; +PFNGLLIGHTENVIEXTPROC __glewLightEnviEXT = NULL; + +PFNGLBLITFRAMEBUFFEREXTPROC __glewBlitFramebufferEXT = NULL; + +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewRenderbufferStorageMultisampleEXT = NULL; + +PFNGLBINDFRAMEBUFFEREXTPROC __glewBindFramebufferEXT = NULL; +PFNGLBINDRENDERBUFFEREXTPROC __glewBindRenderbufferEXT = NULL; +PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC __glewCheckFramebufferStatusEXT = NULL; +PFNGLDELETEFRAMEBUFFERSEXTPROC __glewDeleteFramebuffersEXT = NULL; +PFNGLDELETERENDERBUFFERSEXTPROC __glewDeleteRenderbuffersEXT = NULL; +PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC __glewFramebufferRenderbufferEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE1DEXTPROC __glewFramebufferTexture1DEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE2DEXTPROC __glewFramebufferTexture2DEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE3DEXTPROC __glewFramebufferTexture3DEXT = NULL; +PFNGLGENFRAMEBUFFERSEXTPROC __glewGenFramebuffersEXT = NULL; +PFNGLGENRENDERBUFFERSEXTPROC __glewGenRenderbuffersEXT = NULL; +PFNGLGENERATEMIPMAPEXTPROC __glewGenerateMipmapEXT = NULL; +PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetFramebufferAttachmentParameterivEXT = NULL; +PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC __glewGetRenderbufferParameterivEXT = NULL; +PFNGLISFRAMEBUFFEREXTPROC __glewIsFramebufferEXT = NULL; +PFNGLISRENDERBUFFEREXTPROC __glewIsRenderbufferEXT = NULL; +PFNGLRENDERBUFFERSTORAGEEXTPROC __glewRenderbufferStorageEXT = NULL; + +PFNGLFRAMEBUFFERTEXTUREEXTPROC __glewFramebufferTextureEXT = NULL; +PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC __glewFramebufferTextureFaceEXT = NULL; +PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC __glewFramebufferTextureLayerEXT = NULL; +PFNGLPROGRAMPARAMETERIEXTPROC __glewProgramParameteriEXT = NULL; + +PFNGLPROGRAMENVPARAMETERS4FVEXTPROC __glewProgramEnvParameters4fvEXT = NULL; +PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC __glewProgramLocalParameters4fvEXT = NULL; + +PFNGLBINDFRAGDATALOCATIONEXTPROC __glewBindFragDataLocationEXT = NULL; +PFNGLGETFRAGDATALOCATIONEXTPROC __glewGetFragDataLocationEXT = NULL; +PFNGLGETUNIFORMUIVEXTPROC __glewGetUniformuivEXT = NULL; +PFNGLGETVERTEXATTRIBIIVEXTPROC __glewGetVertexAttribIivEXT = NULL; +PFNGLGETVERTEXATTRIBIUIVEXTPROC __glewGetVertexAttribIuivEXT = NULL; +PFNGLUNIFORM1UIEXTPROC __glewUniform1uiEXT = NULL; +PFNGLUNIFORM1UIVEXTPROC __glewUniform1uivEXT = NULL; +PFNGLUNIFORM2UIEXTPROC __glewUniform2uiEXT = NULL; +PFNGLUNIFORM2UIVEXTPROC __glewUniform2uivEXT = NULL; +PFNGLUNIFORM3UIEXTPROC __glewUniform3uiEXT = NULL; +PFNGLUNIFORM3UIVEXTPROC __glewUniform3uivEXT = NULL; +PFNGLUNIFORM4UIEXTPROC __glewUniform4uiEXT = NULL; +PFNGLUNIFORM4UIVEXTPROC __glewUniform4uivEXT = NULL; +PFNGLVERTEXATTRIBI1IEXTPROC __glewVertexAttribI1iEXT = NULL; +PFNGLVERTEXATTRIBI1IVEXTPROC __glewVertexAttribI1ivEXT = NULL; +PFNGLVERTEXATTRIBI1UIEXTPROC __glewVertexAttribI1uiEXT = NULL; +PFNGLVERTEXATTRIBI1UIVEXTPROC __glewVertexAttribI1uivEXT = NULL; +PFNGLVERTEXATTRIBI2IEXTPROC __glewVertexAttribI2iEXT = NULL; +PFNGLVERTEXATTRIBI2IVEXTPROC __glewVertexAttribI2ivEXT = NULL; +PFNGLVERTEXATTRIBI2UIEXTPROC __glewVertexAttribI2uiEXT = NULL; +PFNGLVERTEXATTRIBI2UIVEXTPROC __glewVertexAttribI2uivEXT = NULL; +PFNGLVERTEXATTRIBI3IEXTPROC __glewVertexAttribI3iEXT = NULL; +PFNGLVERTEXATTRIBI3IVEXTPROC __glewVertexAttribI3ivEXT = NULL; +PFNGLVERTEXATTRIBI3UIEXTPROC __glewVertexAttribI3uiEXT = NULL; +PFNGLVERTEXATTRIBI3UIVEXTPROC __glewVertexAttribI3uivEXT = NULL; +PFNGLVERTEXATTRIBI4BVEXTPROC __glewVertexAttribI4bvEXT = NULL; +PFNGLVERTEXATTRIBI4IEXTPROC __glewVertexAttribI4iEXT = NULL; +PFNGLVERTEXATTRIBI4IVEXTPROC __glewVertexAttribI4ivEXT = NULL; +PFNGLVERTEXATTRIBI4SVEXTPROC __glewVertexAttribI4svEXT = NULL; +PFNGLVERTEXATTRIBI4UBVEXTPROC __glewVertexAttribI4ubvEXT = NULL; +PFNGLVERTEXATTRIBI4UIEXTPROC __glewVertexAttribI4uiEXT = NULL; +PFNGLVERTEXATTRIBI4UIVEXTPROC __glewVertexAttribI4uivEXT = NULL; +PFNGLVERTEXATTRIBI4USVEXTPROC __glewVertexAttribI4usvEXT = NULL; +PFNGLVERTEXATTRIBIPOINTEREXTPROC __glewVertexAttribIPointerEXT = NULL; + +PFNGLGETHISTOGRAMEXTPROC __glewGetHistogramEXT = NULL; +PFNGLGETHISTOGRAMPARAMETERFVEXTPROC __glewGetHistogramParameterfvEXT = NULL; +PFNGLGETHISTOGRAMPARAMETERIVEXTPROC __glewGetHistogramParameterivEXT = NULL; +PFNGLGETMINMAXEXTPROC __glewGetMinmaxEXT = NULL; +PFNGLGETMINMAXPARAMETERFVEXTPROC __glewGetMinmaxParameterfvEXT = NULL; +PFNGLGETMINMAXPARAMETERIVEXTPROC __glewGetMinmaxParameterivEXT = NULL; +PFNGLHISTOGRAMEXTPROC __glewHistogramEXT = NULL; +PFNGLMINMAXEXTPROC __glewMinmaxEXT = NULL; +PFNGLRESETHISTOGRAMEXTPROC __glewResetHistogramEXT = NULL; +PFNGLRESETMINMAXEXTPROC __glewResetMinmaxEXT = NULL; + +PFNGLINDEXFUNCEXTPROC __glewIndexFuncEXT = NULL; + +PFNGLINDEXMATERIALEXTPROC __glewIndexMaterialEXT = NULL; + +PFNGLAPPLYTEXTUREEXTPROC __glewApplyTextureEXT = NULL; +PFNGLTEXTURELIGHTEXTPROC __glewTextureLightEXT = NULL; +PFNGLTEXTUREMATERIALEXTPROC __glewTextureMaterialEXT = NULL; + +PFNGLMULTIDRAWARRAYSEXTPROC __glewMultiDrawArraysEXT = NULL; +PFNGLMULTIDRAWELEMENTSEXTPROC __glewMultiDrawElementsEXT = NULL; + +PFNGLSAMPLEMASKEXTPROC __glewSampleMaskEXT = NULL; +PFNGLSAMPLEPATTERNEXTPROC __glewSamplePatternEXT = NULL; + +PFNGLCOLORTABLEEXTPROC __glewColorTableEXT = NULL; +PFNGLGETCOLORTABLEEXTPROC __glewGetColorTableEXT = NULL; +PFNGLGETCOLORTABLEPARAMETERFVEXTPROC __glewGetColorTableParameterfvEXT = NULL; +PFNGLGETCOLORTABLEPARAMETERIVEXTPROC __glewGetColorTableParameterivEXT = NULL; + +PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC __glewGetPixelTransformParameterfvEXT = NULL; +PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC __glewGetPixelTransformParameterivEXT = NULL; +PFNGLPIXELTRANSFORMPARAMETERFEXTPROC __glewPixelTransformParameterfEXT = NULL; +PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC __glewPixelTransformParameterfvEXT = NULL; +PFNGLPIXELTRANSFORMPARAMETERIEXTPROC __glewPixelTransformParameteriEXT = NULL; +PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC __glewPixelTransformParameterivEXT = NULL; + +PFNGLPOINTPARAMETERFEXTPROC __glewPointParameterfEXT = NULL; +PFNGLPOINTPARAMETERFVEXTPROC __glewPointParameterfvEXT = NULL; + +PFNGLPOLYGONOFFSETEXTPROC __glewPolygonOffsetEXT = NULL; + +PFNGLBEGINSCENEEXTPROC __glewBeginSceneEXT = NULL; +PFNGLENDSCENEEXTPROC __glewEndSceneEXT = NULL; + +PFNGLSECONDARYCOLOR3BEXTPROC __glewSecondaryColor3bEXT = NULL; +PFNGLSECONDARYCOLOR3BVEXTPROC __glewSecondaryColor3bvEXT = NULL; +PFNGLSECONDARYCOLOR3DEXTPROC __glewSecondaryColor3dEXT = NULL; +PFNGLSECONDARYCOLOR3DVEXTPROC __glewSecondaryColor3dvEXT = NULL; +PFNGLSECONDARYCOLOR3FEXTPROC __glewSecondaryColor3fEXT = NULL; +PFNGLSECONDARYCOLOR3FVEXTPROC __glewSecondaryColor3fvEXT = NULL; +PFNGLSECONDARYCOLOR3IEXTPROC __glewSecondaryColor3iEXT = NULL; +PFNGLSECONDARYCOLOR3IVEXTPROC __glewSecondaryColor3ivEXT = NULL; +PFNGLSECONDARYCOLOR3SEXTPROC __glewSecondaryColor3sEXT = NULL; +PFNGLSECONDARYCOLOR3SVEXTPROC __glewSecondaryColor3svEXT = NULL; +PFNGLSECONDARYCOLOR3UBEXTPROC __glewSecondaryColor3ubEXT = NULL; +PFNGLSECONDARYCOLOR3UBVEXTPROC __glewSecondaryColor3ubvEXT = NULL; +PFNGLSECONDARYCOLOR3UIEXTPROC __glewSecondaryColor3uiEXT = NULL; +PFNGLSECONDARYCOLOR3UIVEXTPROC __glewSecondaryColor3uivEXT = NULL; +PFNGLSECONDARYCOLOR3USEXTPROC __glewSecondaryColor3usEXT = NULL; +PFNGLSECONDARYCOLOR3USVEXTPROC __glewSecondaryColor3usvEXT = NULL; +PFNGLSECONDARYCOLORPOINTEREXTPROC __glewSecondaryColorPointerEXT = NULL; + +PFNGLACTIVESTENCILFACEEXTPROC __glewActiveStencilFaceEXT = NULL; + +PFNGLTEXSUBIMAGE1DEXTPROC __glewTexSubImage1DEXT = NULL; +PFNGLTEXSUBIMAGE2DEXTPROC __glewTexSubImage2DEXT = NULL; +PFNGLTEXSUBIMAGE3DEXTPROC __glewTexSubImage3DEXT = NULL; + +PFNGLTEXIMAGE3DEXTPROC __glewTexImage3DEXT = NULL; + +PFNGLTEXBUFFEREXTPROC __glewTexBufferEXT = NULL; + +PFNGLCLEARCOLORIIEXTPROC __glewClearColorIiEXT = NULL; +PFNGLCLEARCOLORIUIEXTPROC __glewClearColorIuiEXT = NULL; +PFNGLGETTEXPARAMETERIIVEXTPROC __glewGetTexParameterIivEXT = NULL; +PFNGLGETTEXPARAMETERIUIVEXTPROC __glewGetTexParameterIuivEXT = NULL; +PFNGLTEXPARAMETERIIVEXTPROC __glewTexParameterIivEXT = NULL; +PFNGLTEXPARAMETERIUIVEXTPROC __glewTexParameterIuivEXT = NULL; + +PFNGLARETEXTURESRESIDENTEXTPROC __glewAreTexturesResidentEXT = NULL; +PFNGLBINDTEXTUREEXTPROC __glewBindTextureEXT = NULL; +PFNGLDELETETEXTURESEXTPROC __glewDeleteTexturesEXT = NULL; +PFNGLGENTEXTURESEXTPROC __glewGenTexturesEXT = NULL; +PFNGLISTEXTUREEXTPROC __glewIsTextureEXT = NULL; +PFNGLPRIORITIZETEXTURESEXTPROC __glewPrioritizeTexturesEXT = NULL; + +PFNGLTEXTURENORMALEXTPROC __glewTextureNormalEXT = NULL; + +PFNGLGETQUERYOBJECTI64VEXTPROC __glewGetQueryObjecti64vEXT = NULL; +PFNGLGETQUERYOBJECTUI64VEXTPROC __glewGetQueryObjectui64vEXT = NULL; + +PFNGLARRAYELEMENTEXTPROC __glewArrayElementEXT = NULL; +PFNGLCOLORPOINTEREXTPROC __glewColorPointerEXT = NULL; +PFNGLDRAWARRAYSEXTPROC __glewDrawArraysEXT = NULL; +PFNGLEDGEFLAGPOINTEREXTPROC __glewEdgeFlagPointerEXT = NULL; +PFNGLGETPOINTERVEXTPROC __glewGetPointervEXT = NULL; +PFNGLINDEXPOINTEREXTPROC __glewIndexPointerEXT = NULL; +PFNGLNORMALPOINTEREXTPROC __glewNormalPointerEXT = NULL; +PFNGLTEXCOORDPOINTEREXTPROC __glewTexCoordPointerEXT = NULL; +PFNGLVERTEXPOINTEREXTPROC __glewVertexPointerEXT = NULL; + +PFNGLBEGINVERTEXSHADEREXTPROC __glewBeginVertexShaderEXT = NULL; +PFNGLBINDLIGHTPARAMETEREXTPROC __glewBindLightParameterEXT = NULL; +PFNGLBINDMATERIALPARAMETEREXTPROC __glewBindMaterialParameterEXT = NULL; +PFNGLBINDPARAMETEREXTPROC __glewBindParameterEXT = NULL; +PFNGLBINDTEXGENPARAMETEREXTPROC __glewBindTexGenParameterEXT = NULL; +PFNGLBINDTEXTUREUNITPARAMETEREXTPROC __glewBindTextureUnitParameterEXT = NULL; +PFNGLBINDVERTEXSHADEREXTPROC __glewBindVertexShaderEXT = NULL; +PFNGLDELETEVERTEXSHADEREXTPROC __glewDeleteVertexShaderEXT = NULL; +PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC __glewDisableVariantClientStateEXT = NULL; +PFNGLENABLEVARIANTCLIENTSTATEEXTPROC __glewEnableVariantClientStateEXT = NULL; +PFNGLENDVERTEXSHADEREXTPROC __glewEndVertexShaderEXT = NULL; +PFNGLEXTRACTCOMPONENTEXTPROC __glewExtractComponentEXT = NULL; +PFNGLGENSYMBOLSEXTPROC __glewGenSymbolsEXT = NULL; +PFNGLGENVERTEXSHADERSEXTPROC __glewGenVertexShadersEXT = NULL; +PFNGLGETINVARIANTBOOLEANVEXTPROC __glewGetInvariantBooleanvEXT = NULL; +PFNGLGETINVARIANTFLOATVEXTPROC __glewGetInvariantFloatvEXT = NULL; +PFNGLGETINVARIANTINTEGERVEXTPROC __glewGetInvariantIntegervEXT = NULL; +PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC __glewGetLocalConstantBooleanvEXT = NULL; +PFNGLGETLOCALCONSTANTFLOATVEXTPROC __glewGetLocalConstantFloatvEXT = NULL; +PFNGLGETLOCALCONSTANTINTEGERVEXTPROC __glewGetLocalConstantIntegervEXT = NULL; +PFNGLGETVARIANTBOOLEANVEXTPROC __glewGetVariantBooleanvEXT = NULL; +PFNGLGETVARIANTFLOATVEXTPROC __glewGetVariantFloatvEXT = NULL; +PFNGLGETVARIANTINTEGERVEXTPROC __glewGetVariantIntegervEXT = NULL; +PFNGLGETVARIANTPOINTERVEXTPROC __glewGetVariantPointervEXT = NULL; +PFNGLINSERTCOMPONENTEXTPROC __glewInsertComponentEXT = NULL; +PFNGLISVARIANTENABLEDEXTPROC __glewIsVariantEnabledEXT = NULL; +PFNGLSETINVARIANTEXTPROC __glewSetInvariantEXT = NULL; +PFNGLSETLOCALCONSTANTEXTPROC __glewSetLocalConstantEXT = NULL; +PFNGLSHADEROP1EXTPROC __glewShaderOp1EXT = NULL; +PFNGLSHADEROP2EXTPROC __glewShaderOp2EXT = NULL; +PFNGLSHADEROP3EXTPROC __glewShaderOp3EXT = NULL; +PFNGLSWIZZLEEXTPROC __glewSwizzleEXT = NULL; +PFNGLVARIANTPOINTEREXTPROC __glewVariantPointerEXT = NULL; +PFNGLVARIANTBVEXTPROC __glewVariantbvEXT = NULL; +PFNGLVARIANTDVEXTPROC __glewVariantdvEXT = NULL; +PFNGLVARIANTFVEXTPROC __glewVariantfvEXT = NULL; +PFNGLVARIANTIVEXTPROC __glewVariantivEXT = NULL; +PFNGLVARIANTSVEXTPROC __glewVariantsvEXT = NULL; +PFNGLVARIANTUBVEXTPROC __glewVariantubvEXT = NULL; +PFNGLVARIANTUIVEXTPROC __glewVariantuivEXT = NULL; +PFNGLVARIANTUSVEXTPROC __glewVariantusvEXT = NULL; +PFNGLWRITEMASKEXTPROC __glewWriteMaskEXT = NULL; + +PFNGLVERTEXWEIGHTPOINTEREXTPROC __glewVertexWeightPointerEXT = NULL; +PFNGLVERTEXWEIGHTFEXTPROC __glewVertexWeightfEXT = NULL; +PFNGLVERTEXWEIGHTFVEXTPROC __glewVertexWeightfvEXT = NULL; + +PFNGLFRAMETERMINATORGREMEDYPROC __glewFrameTerminatorGREMEDY = NULL; + +PFNGLSTRINGMARKERGREMEDYPROC __glewStringMarkerGREMEDY = NULL; + +PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC __glewGetImageTransformParameterfvHP = NULL; +PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC __glewGetImageTransformParameterivHP = NULL; +PFNGLIMAGETRANSFORMPARAMETERFHPPROC __glewImageTransformParameterfHP = NULL; +PFNGLIMAGETRANSFORMPARAMETERFVHPPROC __glewImageTransformParameterfvHP = NULL; +PFNGLIMAGETRANSFORMPARAMETERIHPPROC __glewImageTransformParameteriHP = NULL; +PFNGLIMAGETRANSFORMPARAMETERIVHPPROC __glewImageTransformParameterivHP = NULL; + +PFNGLMULTIMODEDRAWARRAYSIBMPROC __glewMultiModeDrawArraysIBM = NULL; +PFNGLMULTIMODEDRAWELEMENTSIBMPROC __glewMultiModeDrawElementsIBM = NULL; + +PFNGLCOLORPOINTERLISTIBMPROC __glewColorPointerListIBM = NULL; +PFNGLEDGEFLAGPOINTERLISTIBMPROC __glewEdgeFlagPointerListIBM = NULL; +PFNGLFOGCOORDPOINTERLISTIBMPROC __glewFogCoordPointerListIBM = NULL; +PFNGLINDEXPOINTERLISTIBMPROC __glewIndexPointerListIBM = NULL; +PFNGLNORMALPOINTERLISTIBMPROC __glewNormalPointerListIBM = NULL; +PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointerListIBM = NULL; +PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM = NULL; +PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM = NULL; + +PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL = NULL; +PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL = NULL; +PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL = NULL; +PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL = NULL; + +PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL = NULL; +PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL = NULL; + +PFNGLBUFFERREGIONENABLEDEXTPROC __glewBufferRegionEnabledEXT = NULL; +PFNGLDELETEBUFFERREGIONEXTPROC __glewDeleteBufferRegionEXT = NULL; +PFNGLDRAWBUFFERREGIONEXTPROC __glewDrawBufferRegionEXT = NULL; +PFNGLNEWBUFFERREGIONEXTPROC __glewNewBufferRegionEXT = NULL; +PFNGLREADBUFFERREGIONEXTPROC __glewReadBufferRegionEXT = NULL; + +PFNGLRESIZEBUFFERSMESAPROC __glewResizeBuffersMESA = NULL; + +PFNGLWINDOWPOS2DMESAPROC __glewWindowPos2dMESA = NULL; +PFNGLWINDOWPOS2DVMESAPROC __glewWindowPos2dvMESA = NULL; +PFNGLWINDOWPOS2FMESAPROC __glewWindowPos2fMESA = NULL; +PFNGLWINDOWPOS2FVMESAPROC __glewWindowPos2fvMESA = NULL; +PFNGLWINDOWPOS2IMESAPROC __glewWindowPos2iMESA = NULL; +PFNGLWINDOWPOS2IVMESAPROC __glewWindowPos2ivMESA = NULL; +PFNGLWINDOWPOS2SMESAPROC __glewWindowPos2sMESA = NULL; +PFNGLWINDOWPOS2SVMESAPROC __glewWindowPos2svMESA = NULL; +PFNGLWINDOWPOS3DMESAPROC __glewWindowPos3dMESA = NULL; +PFNGLWINDOWPOS3DVMESAPROC __glewWindowPos3dvMESA = NULL; +PFNGLWINDOWPOS3FMESAPROC __glewWindowPos3fMESA = NULL; +PFNGLWINDOWPOS3FVMESAPROC __glewWindowPos3fvMESA = NULL; +PFNGLWINDOWPOS3IMESAPROC __glewWindowPos3iMESA = NULL; +PFNGLWINDOWPOS3IVMESAPROC __glewWindowPos3ivMESA = NULL; +PFNGLWINDOWPOS3SMESAPROC __glewWindowPos3sMESA = NULL; +PFNGLWINDOWPOS3SVMESAPROC __glewWindowPos3svMESA = NULL; +PFNGLWINDOWPOS4DMESAPROC __glewWindowPos4dMESA = NULL; +PFNGLWINDOWPOS4DVMESAPROC __glewWindowPos4dvMESA = NULL; +PFNGLWINDOWPOS4FMESAPROC __glewWindowPos4fMESA = NULL; +PFNGLWINDOWPOS4FVMESAPROC __glewWindowPos4fvMESA = NULL; +PFNGLWINDOWPOS4IMESAPROC __glewWindowPos4iMESA = NULL; +PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA = NULL; +PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA = NULL; +PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA = NULL; + +PFNGLCLEARDEPTHDNVPROC __glewClearDepthdNV = NULL; +PFNGLDEPTHBOUNDSDNVPROC __glewDepthBoundsdNV = NULL; +PFNGLDEPTHRANGEDNVPROC __glewDepthRangedNV = NULL; + +PFNGLEVALMAPSNVPROC __glewEvalMapsNV = NULL; +PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV = NULL; +PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV = NULL; +PFNGLGETMAPCONTROLPOINTSNVPROC __glewGetMapControlPointsNV = NULL; +PFNGLGETMAPPARAMETERFVNVPROC __glewGetMapParameterfvNV = NULL; +PFNGLGETMAPPARAMETERIVNVPROC __glewGetMapParameterivNV = NULL; +PFNGLMAPCONTROLPOINTSNVPROC __glewMapControlPointsNV = NULL; +PFNGLMAPPARAMETERFVNVPROC __glewMapParameterfvNV = NULL; +PFNGLMAPPARAMETERIVNVPROC __glewMapParameterivNV = NULL; + +PFNGLDELETEFENCESNVPROC __glewDeleteFencesNV = NULL; +PFNGLFINISHFENCENVPROC __glewFinishFenceNV = NULL; +PFNGLGENFENCESNVPROC __glewGenFencesNV = NULL; +PFNGLGETFENCEIVNVPROC __glewGetFenceivNV = NULL; +PFNGLISFENCENVPROC __glewIsFenceNV = NULL; +PFNGLSETFENCENVPROC __glewSetFenceNV = NULL; +PFNGLTESTFENCENVPROC __glewTestFenceNV = NULL; + +PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC __glewGetProgramNamedParameterdvNV = NULL; +PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC __glewGetProgramNamedParameterfvNV = NULL; +PFNGLPROGRAMNAMEDPARAMETER4DNVPROC __glewProgramNamedParameter4dNV = NULL; +PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC __glewProgramNamedParameter4dvNV = NULL; +PFNGLPROGRAMNAMEDPARAMETER4FNVPROC __glewProgramNamedParameter4fNV = NULL; +PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC __glewProgramNamedParameter4fvNV = NULL; + +PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC __glewRenderbufferStorageMultisampleCoverageNV = NULL; + +PFNGLPROGRAMVERTEXLIMITNVPROC __glewProgramVertexLimitNV = NULL; + +PFNGLPROGRAMENVPARAMETERI4INVPROC __glewProgramEnvParameterI4iNV = NULL; +PFNGLPROGRAMENVPARAMETERI4IVNVPROC __glewProgramEnvParameterI4ivNV = NULL; +PFNGLPROGRAMENVPARAMETERI4UINVPROC __glewProgramEnvParameterI4uiNV = NULL; +PFNGLPROGRAMENVPARAMETERI4UIVNVPROC __glewProgramEnvParameterI4uivNV = NULL; +PFNGLPROGRAMENVPARAMETERSI4IVNVPROC __glewProgramEnvParametersI4ivNV = NULL; +PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC __glewProgramEnvParametersI4uivNV = NULL; +PFNGLPROGRAMLOCALPARAMETERI4INVPROC __glewProgramLocalParameterI4iNV = NULL; +PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC __glewProgramLocalParameterI4ivNV = NULL; +PFNGLPROGRAMLOCALPARAMETERI4UINVPROC __glewProgramLocalParameterI4uiNV = NULL; +PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC __glewProgramLocalParameterI4uivNV = NULL; +PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC __glewProgramLocalParametersI4ivNV = NULL; +PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC __glewProgramLocalParametersI4uivNV = NULL; + +PFNGLCOLOR3HNVPROC __glewColor3hNV = NULL; +PFNGLCOLOR3HVNVPROC __glewColor3hvNV = NULL; +PFNGLCOLOR4HNVPROC __glewColor4hNV = NULL; +PFNGLCOLOR4HVNVPROC __glewColor4hvNV = NULL; +PFNGLFOGCOORDHNVPROC __glewFogCoordhNV = NULL; +PFNGLFOGCOORDHVNVPROC __glewFogCoordhvNV = NULL; +PFNGLMULTITEXCOORD1HNVPROC __glewMultiTexCoord1hNV = NULL; +PFNGLMULTITEXCOORD1HVNVPROC __glewMultiTexCoord1hvNV = NULL; +PFNGLMULTITEXCOORD2HNVPROC __glewMultiTexCoord2hNV = NULL; +PFNGLMULTITEXCOORD2HVNVPROC __glewMultiTexCoord2hvNV = NULL; +PFNGLMULTITEXCOORD3HNVPROC __glewMultiTexCoord3hNV = NULL; +PFNGLMULTITEXCOORD3HVNVPROC __glewMultiTexCoord3hvNV = NULL; +PFNGLMULTITEXCOORD4HNVPROC __glewMultiTexCoord4hNV = NULL; +PFNGLMULTITEXCOORD4HVNVPROC __glewMultiTexCoord4hvNV = NULL; +PFNGLNORMAL3HNVPROC __glewNormal3hNV = NULL; +PFNGLNORMAL3HVNVPROC __glewNormal3hvNV = NULL; +PFNGLSECONDARYCOLOR3HNVPROC __glewSecondaryColor3hNV = NULL; +PFNGLSECONDARYCOLOR3HVNVPROC __glewSecondaryColor3hvNV = NULL; +PFNGLTEXCOORD1HNVPROC __glewTexCoord1hNV = NULL; +PFNGLTEXCOORD1HVNVPROC __glewTexCoord1hvNV = NULL; +PFNGLTEXCOORD2HNVPROC __glewTexCoord2hNV = NULL; +PFNGLTEXCOORD2HVNVPROC __glewTexCoord2hvNV = NULL; +PFNGLTEXCOORD3HNVPROC __glewTexCoord3hNV = NULL; +PFNGLTEXCOORD3HVNVPROC __glewTexCoord3hvNV = NULL; +PFNGLTEXCOORD4HNVPROC __glewTexCoord4hNV = NULL; +PFNGLTEXCOORD4HVNVPROC __glewTexCoord4hvNV = NULL; +PFNGLVERTEX2HNVPROC __glewVertex2hNV = NULL; +PFNGLVERTEX2HVNVPROC __glewVertex2hvNV = NULL; +PFNGLVERTEX3HNVPROC __glewVertex3hNV = NULL; +PFNGLVERTEX3HVNVPROC __glewVertex3hvNV = NULL; +PFNGLVERTEX4HNVPROC __glewVertex4hNV = NULL; +PFNGLVERTEX4HVNVPROC __glewVertex4hvNV = NULL; +PFNGLVERTEXATTRIB1HNVPROC __glewVertexAttrib1hNV = NULL; +PFNGLVERTEXATTRIB1HVNVPROC __glewVertexAttrib1hvNV = NULL; +PFNGLVERTEXATTRIB2HNVPROC __glewVertexAttrib2hNV = NULL; +PFNGLVERTEXATTRIB2HVNVPROC __glewVertexAttrib2hvNV = NULL; +PFNGLVERTEXATTRIB3HNVPROC __glewVertexAttrib3hNV = NULL; +PFNGLVERTEXATTRIB3HVNVPROC __glewVertexAttrib3hvNV = NULL; +PFNGLVERTEXATTRIB4HNVPROC __glewVertexAttrib4hNV = NULL; +PFNGLVERTEXATTRIB4HVNVPROC __glewVertexAttrib4hvNV = NULL; +PFNGLVERTEXATTRIBS1HVNVPROC __glewVertexAttribs1hvNV = NULL; +PFNGLVERTEXATTRIBS2HVNVPROC __glewVertexAttribs2hvNV = NULL; +PFNGLVERTEXATTRIBS3HVNVPROC __glewVertexAttribs3hvNV = NULL; +PFNGLVERTEXATTRIBS4HVNVPROC __glewVertexAttribs4hvNV = NULL; +PFNGLVERTEXWEIGHTHNVPROC __glewVertexWeighthNV = NULL; +PFNGLVERTEXWEIGHTHVNVPROC __glewVertexWeighthvNV = NULL; + +PFNGLBEGINOCCLUSIONQUERYNVPROC __glewBeginOcclusionQueryNV = NULL; +PFNGLDELETEOCCLUSIONQUERIESNVPROC __glewDeleteOcclusionQueriesNV = NULL; +PFNGLENDOCCLUSIONQUERYNVPROC __glewEndOcclusionQueryNV = NULL; +PFNGLGENOCCLUSIONQUERIESNVPROC __glewGenOcclusionQueriesNV = NULL; +PFNGLGETOCCLUSIONQUERYIVNVPROC __glewGetOcclusionQueryivNV = NULL; +PFNGLGETOCCLUSIONQUERYUIVNVPROC __glewGetOcclusionQueryuivNV = NULL; +PFNGLISOCCLUSIONQUERYNVPROC __glewIsOcclusionQueryNV = NULL; + +PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC __glewProgramBufferParametersIivNV = NULL; +PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC __glewProgramBufferParametersIuivNV = NULL; +PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC __glewProgramBufferParametersfvNV = NULL; + +PFNGLFLUSHPIXELDATARANGENVPROC __glewFlushPixelDataRangeNV = NULL; +PFNGLPIXELDATARANGENVPROC __glewPixelDataRangeNV = NULL; + +PFNGLPOINTPARAMETERINVPROC __glewPointParameteriNV = NULL; +PFNGLPOINTPARAMETERIVNVPROC __glewPointParameterivNV = NULL; + +PFNGLPRIMITIVERESTARTINDEXNVPROC __glewPrimitiveRestartIndexNV = NULL; +PFNGLPRIMITIVERESTARTNVPROC __glewPrimitiveRestartNV = NULL; + +PFNGLCOMBINERINPUTNVPROC __glewCombinerInputNV = NULL; +PFNGLCOMBINEROUTPUTNVPROC __glewCombinerOutputNV = NULL; +PFNGLCOMBINERPARAMETERFNVPROC __glewCombinerParameterfNV = NULL; +PFNGLCOMBINERPARAMETERFVNVPROC __glewCombinerParameterfvNV = NULL; +PFNGLCOMBINERPARAMETERINVPROC __glewCombinerParameteriNV = NULL; +PFNGLCOMBINERPARAMETERIVNVPROC __glewCombinerParameterivNV = NULL; +PFNGLFINALCOMBINERINPUTNVPROC __glewFinalCombinerInputNV = NULL; +PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC __glewGetCombinerInputParameterfvNV = NULL; +PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC __glewGetCombinerInputParameterivNV = NULL; +PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC __glewGetCombinerOutputParameterfvNV = NULL; +PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC __glewGetCombinerOutputParameterivNV = NULL; +PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC __glewGetFinalCombinerInputParameterfvNV = NULL; +PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC __glewGetFinalCombinerInputParameterivNV = NULL; + +PFNGLCOMBINERSTAGEPARAMETERFVNVPROC __glewCombinerStageParameterfvNV = NULL; +PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC __glewGetCombinerStageParameterfvNV = NULL; + +PFNGLACTIVEVARYINGNVPROC __glewActiveVaryingNV = NULL; +PFNGLBEGINTRANSFORMFEEDBACKNVPROC __glewBeginTransformFeedbackNV = NULL; +PFNGLBINDBUFFERBASENVPROC __glewBindBufferBaseNV = NULL; +PFNGLBINDBUFFEROFFSETNVPROC __glewBindBufferOffsetNV = NULL; +PFNGLBINDBUFFERRANGENVPROC __glewBindBufferRangeNV = NULL; +PFNGLENDTRANSFORMFEEDBACKNVPROC __glewEndTransformFeedbackNV = NULL; +PFNGLGETACTIVEVARYINGNVPROC __glewGetActiveVaryingNV = NULL; +PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC __glewGetTransformFeedbackVaryingNV = NULL; +PFNGLGETVARYINGLOCATIONNVPROC __glewGetVaryingLocationNV = NULL; +PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC __glewTransformFeedbackAttribsNV = NULL; +PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC __glewTransformFeedbackVaryingsNV = NULL; + +PFNGLFLUSHVERTEXARRAYRANGENVPROC __glewFlushVertexArrayRangeNV = NULL; +PFNGLVERTEXARRAYRANGENVPROC __glewVertexArrayRangeNV = NULL; + +PFNGLAREPROGRAMSRESIDENTNVPROC __glewAreProgramsResidentNV = NULL; +PFNGLBINDPROGRAMNVPROC __glewBindProgramNV = NULL; +PFNGLDELETEPROGRAMSNVPROC __glewDeleteProgramsNV = NULL; +PFNGLEXECUTEPROGRAMNVPROC __glewExecuteProgramNV = NULL; +PFNGLGENPROGRAMSNVPROC __glewGenProgramsNV = NULL; +PFNGLGETPROGRAMPARAMETERDVNVPROC __glewGetProgramParameterdvNV = NULL; +PFNGLGETPROGRAMPARAMETERFVNVPROC __glewGetProgramParameterfvNV = NULL; +PFNGLGETPROGRAMSTRINGNVPROC __glewGetProgramStringNV = NULL; +PFNGLGETPROGRAMIVNVPROC __glewGetProgramivNV = NULL; +PFNGLGETTRACKMATRIXIVNVPROC __glewGetTrackMatrixivNV = NULL; +PFNGLGETVERTEXATTRIBPOINTERVNVPROC __glewGetVertexAttribPointervNV = NULL; +PFNGLGETVERTEXATTRIBDVNVPROC __glewGetVertexAttribdvNV = NULL; +PFNGLGETVERTEXATTRIBFVNVPROC __glewGetVertexAttribfvNV = NULL; +PFNGLGETVERTEXATTRIBIVNVPROC __glewGetVertexAttribivNV = NULL; +PFNGLISPROGRAMNVPROC __glewIsProgramNV = NULL; +PFNGLLOADPROGRAMNVPROC __glewLoadProgramNV = NULL; +PFNGLPROGRAMPARAMETER4DNVPROC __glewProgramParameter4dNV = NULL; +PFNGLPROGRAMPARAMETER4DVNVPROC __glewProgramParameter4dvNV = NULL; +PFNGLPROGRAMPARAMETER4FNVPROC __glewProgramParameter4fNV = NULL; +PFNGLPROGRAMPARAMETER4FVNVPROC __glewProgramParameter4fvNV = NULL; +PFNGLPROGRAMPARAMETERS4DVNVPROC __glewProgramParameters4dvNV = NULL; +PFNGLPROGRAMPARAMETERS4FVNVPROC __glewProgramParameters4fvNV = NULL; +PFNGLREQUESTRESIDENTPROGRAMSNVPROC __glewRequestResidentProgramsNV = NULL; +PFNGLTRACKMATRIXNVPROC __glewTrackMatrixNV = NULL; +PFNGLVERTEXATTRIB1DNVPROC __glewVertexAttrib1dNV = NULL; +PFNGLVERTEXATTRIB1DVNVPROC __glewVertexAttrib1dvNV = NULL; +PFNGLVERTEXATTRIB1FNVPROC __glewVertexAttrib1fNV = NULL; +PFNGLVERTEXATTRIB1FVNVPROC __glewVertexAttrib1fvNV = NULL; +PFNGLVERTEXATTRIB1SNVPROC __glewVertexAttrib1sNV = NULL; +PFNGLVERTEXATTRIB1SVNVPROC __glewVertexAttrib1svNV = NULL; +PFNGLVERTEXATTRIB2DNVPROC __glewVertexAttrib2dNV = NULL; +PFNGLVERTEXATTRIB2DVNVPROC __glewVertexAttrib2dvNV = NULL; +PFNGLVERTEXATTRIB2FNVPROC __glewVertexAttrib2fNV = NULL; +PFNGLVERTEXATTRIB2FVNVPROC __glewVertexAttrib2fvNV = NULL; +PFNGLVERTEXATTRIB2SNVPROC __glewVertexAttrib2sNV = NULL; +PFNGLVERTEXATTRIB2SVNVPROC __glewVertexAttrib2svNV = NULL; +PFNGLVERTEXATTRIB3DNVPROC __glewVertexAttrib3dNV = NULL; +PFNGLVERTEXATTRIB3DVNVPROC __glewVertexAttrib3dvNV = NULL; +PFNGLVERTEXATTRIB3FNVPROC __glewVertexAttrib3fNV = NULL; +PFNGLVERTEXATTRIB3FVNVPROC __glewVertexAttrib3fvNV = NULL; +PFNGLVERTEXATTRIB3SNVPROC __glewVertexAttrib3sNV = NULL; +PFNGLVERTEXATTRIB3SVNVPROC __glewVertexAttrib3svNV = NULL; +PFNGLVERTEXATTRIB4DNVPROC __glewVertexAttrib4dNV = NULL; +PFNGLVERTEXATTRIB4DVNVPROC __glewVertexAttrib4dvNV = NULL; +PFNGLVERTEXATTRIB4FNVPROC __glewVertexAttrib4fNV = NULL; +PFNGLVERTEXATTRIB4FVNVPROC __glewVertexAttrib4fvNV = NULL; +PFNGLVERTEXATTRIB4SNVPROC __glewVertexAttrib4sNV = NULL; +PFNGLVERTEXATTRIB4SVNVPROC __glewVertexAttrib4svNV = NULL; +PFNGLVERTEXATTRIB4UBNVPROC __glewVertexAttrib4ubNV = NULL; +PFNGLVERTEXATTRIB4UBVNVPROC __glewVertexAttrib4ubvNV = NULL; +PFNGLVERTEXATTRIBPOINTERNVPROC __glewVertexAttribPointerNV = NULL; +PFNGLVERTEXATTRIBS1DVNVPROC __glewVertexAttribs1dvNV = NULL; +PFNGLVERTEXATTRIBS1FVNVPROC __glewVertexAttribs1fvNV = NULL; +PFNGLVERTEXATTRIBS1SVNVPROC __glewVertexAttribs1svNV = NULL; +PFNGLVERTEXATTRIBS2DVNVPROC __glewVertexAttribs2dvNV = NULL; +PFNGLVERTEXATTRIBS2FVNVPROC __glewVertexAttribs2fvNV = NULL; +PFNGLVERTEXATTRIBS2SVNVPROC __glewVertexAttribs2svNV = NULL; +PFNGLVERTEXATTRIBS3DVNVPROC __glewVertexAttribs3dvNV = NULL; +PFNGLVERTEXATTRIBS3FVNVPROC __glewVertexAttribs3fvNV = NULL; +PFNGLVERTEXATTRIBS3SVNVPROC __glewVertexAttribs3svNV = NULL; +PFNGLVERTEXATTRIBS4DVNVPROC __glewVertexAttribs4dvNV = NULL; +PFNGLVERTEXATTRIBS4FVNVPROC __glewVertexAttribs4fvNV = NULL; +PFNGLVERTEXATTRIBS4SVNVPROC __glewVertexAttribs4svNV = NULL; +PFNGLVERTEXATTRIBS4UBVNVPROC __glewVertexAttribs4ubvNV = NULL; + +PFNGLCLEARDEPTHFOESPROC __glewClearDepthfOES = NULL; +PFNGLCLIPPLANEFOESPROC __glewClipPlanefOES = NULL; +PFNGLDEPTHRANGEFOESPROC __glewDepthRangefOES = NULL; +PFNGLFRUSTUMFOESPROC __glewFrustumfOES = NULL; +PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES = NULL; +PFNGLORTHOFOESPROC __glewOrthofOES = NULL; + +PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS = NULL; +PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS = NULL; + +PFNGLFOGFUNCSGISPROC __glewFogFuncSGIS = NULL; +PFNGLGETFOGFUNCSGISPROC __glewGetFogFuncSGIS = NULL; + +PFNGLSAMPLEMASKSGISPROC __glewSampleMaskSGIS = NULL; +PFNGLSAMPLEPATTERNSGISPROC __glewSamplePatternSGIS = NULL; + +PFNGLGETSHARPENTEXFUNCSGISPROC __glewGetSharpenTexFuncSGIS = NULL; +PFNGLSHARPENTEXFUNCSGISPROC __glewSharpenTexFuncSGIS = NULL; + +PFNGLTEXIMAGE4DSGISPROC __glewTexImage4DSGIS = NULL; +PFNGLTEXSUBIMAGE4DSGISPROC __glewTexSubImage4DSGIS = NULL; + +PFNGLGETTEXFILTERFUNCSGISPROC __glewGetTexFilterFuncSGIS = NULL; +PFNGLTEXFILTERFUNCSGISPROC __glewTexFilterFuncSGIS = NULL; + +PFNGLASYNCMARKERSGIXPROC __glewAsyncMarkerSGIX = NULL; +PFNGLDELETEASYNCMARKERSSGIXPROC __glewDeleteAsyncMarkersSGIX = NULL; +PFNGLFINISHASYNCSGIXPROC __glewFinishAsyncSGIX = NULL; +PFNGLGENASYNCMARKERSSGIXPROC __glewGenAsyncMarkersSGIX = NULL; +PFNGLISASYNCMARKERSGIXPROC __glewIsAsyncMarkerSGIX = NULL; +PFNGLPOLLASYNCSGIXPROC __glewPollAsyncSGIX = NULL; + +PFNGLFLUSHRASTERSGIXPROC __glewFlushRasterSGIX = NULL; + +PFNGLTEXTUREFOGSGIXPROC __glewTextureFogSGIX = NULL; + +PFNGLFRAGMENTCOLORMATERIALSGIXPROC __glewFragmentColorMaterialSGIX = NULL; +PFNGLFRAGMENTLIGHTMODELFSGIXPROC __glewFragmentLightModelfSGIX = NULL; +PFNGLFRAGMENTLIGHTMODELFVSGIXPROC __glewFragmentLightModelfvSGIX = NULL; +PFNGLFRAGMENTLIGHTMODELISGIXPROC __glewFragmentLightModeliSGIX = NULL; +PFNGLFRAGMENTLIGHTMODELIVSGIXPROC __glewFragmentLightModelivSGIX = NULL; +PFNGLFRAGMENTLIGHTFSGIXPROC __glewFragmentLightfSGIX = NULL; +PFNGLFRAGMENTLIGHTFVSGIXPROC __glewFragmentLightfvSGIX = NULL; +PFNGLFRAGMENTLIGHTISGIXPROC __glewFragmentLightiSGIX = NULL; +PFNGLFRAGMENTLIGHTIVSGIXPROC __glewFragmentLightivSGIX = NULL; +PFNGLFRAGMENTMATERIALFSGIXPROC __glewFragmentMaterialfSGIX = NULL; +PFNGLFRAGMENTMATERIALFVSGIXPROC __glewFragmentMaterialfvSGIX = NULL; +PFNGLFRAGMENTMATERIALISGIXPROC __glewFragmentMaterialiSGIX = NULL; +PFNGLFRAGMENTMATERIALIVSGIXPROC __glewFragmentMaterialivSGIX = NULL; +PFNGLGETFRAGMENTLIGHTFVSGIXPROC __glewGetFragmentLightfvSGIX = NULL; +PFNGLGETFRAGMENTLIGHTIVSGIXPROC __glewGetFragmentLightivSGIX = NULL; +PFNGLGETFRAGMENTMATERIALFVSGIXPROC __glewGetFragmentMaterialfvSGIX = NULL; +PFNGLGETFRAGMENTMATERIALIVSGIXPROC __glewGetFragmentMaterialivSGIX = NULL; + +PFNGLFRAMEZOOMSGIXPROC __glewFrameZoomSGIX = NULL; + +PFNGLPIXELTEXGENSGIXPROC __glewPixelTexGenSGIX = NULL; + +PFNGLREFERENCEPLANESGIXPROC __glewReferencePlaneSGIX = NULL; + +PFNGLSPRITEPARAMETERFSGIXPROC __glewSpriteParameterfSGIX = NULL; +PFNGLSPRITEPARAMETERFVSGIXPROC __glewSpriteParameterfvSGIX = NULL; +PFNGLSPRITEPARAMETERISGIXPROC __glewSpriteParameteriSGIX = NULL; +PFNGLSPRITEPARAMETERIVSGIXPROC __glewSpriteParameterivSGIX = NULL; + +PFNGLTAGSAMPLEBUFFERSGIXPROC __glewTagSampleBufferSGIX = NULL; + +PFNGLCOLORTABLEPARAMETERFVSGIPROC __glewColorTableParameterfvSGI = NULL; +PFNGLCOLORTABLEPARAMETERIVSGIPROC __glewColorTableParameterivSGI = NULL; +PFNGLCOLORTABLESGIPROC __glewColorTableSGI = NULL; +PFNGLCOPYCOLORTABLESGIPROC __glewCopyColorTableSGI = NULL; +PFNGLGETCOLORTABLEPARAMETERFVSGIPROC __glewGetColorTableParameterfvSGI = NULL; +PFNGLGETCOLORTABLEPARAMETERIVSGIPROC __glewGetColorTableParameterivSGI = NULL; +PFNGLGETCOLORTABLESGIPROC __glewGetColorTableSGI = NULL; + +PFNGLFINISHTEXTURESUNXPROC __glewFinishTextureSUNX = NULL; + +PFNGLGLOBALALPHAFACTORBSUNPROC __glewGlobalAlphaFactorbSUN = NULL; +PFNGLGLOBALALPHAFACTORDSUNPROC __glewGlobalAlphaFactordSUN = NULL; +PFNGLGLOBALALPHAFACTORFSUNPROC __glewGlobalAlphaFactorfSUN = NULL; +PFNGLGLOBALALPHAFACTORISUNPROC __glewGlobalAlphaFactoriSUN = NULL; +PFNGLGLOBALALPHAFACTORSSUNPROC __glewGlobalAlphaFactorsSUN = NULL; +PFNGLGLOBALALPHAFACTORUBSUNPROC __glewGlobalAlphaFactorubSUN = NULL; +PFNGLGLOBALALPHAFACTORUISUNPROC __glewGlobalAlphaFactoruiSUN = NULL; +PFNGLGLOBALALPHAFACTORUSSUNPROC __glewGlobalAlphaFactorusSUN = NULL; + +PFNGLREADVIDEOPIXELSSUNPROC __glewReadVideoPixelsSUN = NULL; + +PFNGLREPLACEMENTCODEPOINTERSUNPROC __glewReplacementCodePointerSUN = NULL; +PFNGLREPLACEMENTCODEUBSUNPROC __glewReplacementCodeubSUN = NULL; +PFNGLREPLACEMENTCODEUBVSUNPROC __glewReplacementCodeubvSUN = NULL; +PFNGLREPLACEMENTCODEUISUNPROC __glewReplacementCodeuiSUN = NULL; +PFNGLREPLACEMENTCODEUIVSUNPROC __glewReplacementCodeuivSUN = NULL; +PFNGLREPLACEMENTCODEUSSUNPROC __glewReplacementCodeusSUN = NULL; +PFNGLREPLACEMENTCODEUSVSUNPROC __glewReplacementCodeusvSUN = NULL; + +PFNGLCOLOR3FVERTEX3FSUNPROC __glewColor3fVertex3fSUN = NULL; +PFNGLCOLOR3FVERTEX3FVSUNPROC __glewColor3fVertex3fvSUN = NULL; +PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewColor4fNormal3fVertex3fSUN = NULL; +PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewColor4fNormal3fVertex3fvSUN = NULL; +PFNGLCOLOR4UBVERTEX2FSUNPROC __glewColor4ubVertex2fSUN = NULL; +PFNGLCOLOR4UBVERTEX2FVSUNPROC __glewColor4ubVertex2fvSUN = NULL; +PFNGLCOLOR4UBVERTEX3FSUNPROC __glewColor4ubVertex3fSUN = NULL; +PFNGLCOLOR4UBVERTEX3FVSUNPROC __glewColor4ubVertex3fvSUN = NULL; +PFNGLNORMAL3FVERTEX3FSUNPROC __glewNormal3fVertex3fSUN = NULL; +PFNGLNORMAL3FVERTEX3FVSUNPROC __glewNormal3fVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC __glewReplacementCodeuiColor3fVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor3fVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC __glewReplacementCodeuiColor4ubVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC __glewReplacementCodeuiColor4ubVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiNormal3fVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiNormal3fVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC __glewReplacementCodeuiVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC __glewReplacementCodeuiVertex3fvSUN = NULL; +PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC __glewTexCoord2fColor3fVertex3fSUN = NULL; +PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC __glewTexCoord2fColor3fVertex3fvSUN = NULL; +PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fSUN = NULL; +PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fvSUN = NULL; +PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC __glewTexCoord2fColor4ubVertex3fSUN = NULL; +PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC __glewTexCoord2fColor4ubVertex3fvSUN = NULL; +PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fNormal3fVertex3fSUN = NULL; +PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fNormal3fVertex3fvSUN = NULL; +PFNGLTEXCOORD2FVERTEX3FSUNPROC __glewTexCoord2fVertex3fSUN = NULL; +PFNGLTEXCOORD2FVERTEX3FVSUNPROC __glewTexCoord2fVertex3fvSUN = NULL; +PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fSUN = NULL; +PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fvSUN = NULL; +PFNGLTEXCOORD4FVERTEX4FSUNPROC __glewTexCoord4fVertex4fSUN = NULL; +PFNGLTEXCOORD4FVERTEX4FVSUNPROC __glewTexCoord4fVertex4fvSUN = NULL; + +PFNGLADDSWAPHINTRECTWINPROC __glewAddSwapHintRectWIN = NULL; + +#endif /* !WIN32 || !GLEW_MX */ + +#if !defined(GLEW_MX) + +GLboolean __GLEW_VERSION_1_1 = GL_FALSE; +GLboolean __GLEW_VERSION_1_2 = GL_FALSE; +GLboolean __GLEW_VERSION_1_3 = GL_FALSE; +GLboolean __GLEW_VERSION_1_4 = GL_FALSE; +GLboolean __GLEW_VERSION_1_5 = GL_FALSE; +GLboolean __GLEW_VERSION_2_0 = GL_FALSE; +GLboolean __GLEW_VERSION_2_1 = GL_FALSE; +GLboolean __GLEW_3DFX_multisample = GL_FALSE; +GLboolean __GLEW_3DFX_tbuffer = GL_FALSE; +GLboolean __GLEW_3DFX_texture_compression_FXT1 = GL_FALSE; +GLboolean __GLEW_APPLE_client_storage = GL_FALSE; +GLboolean __GLEW_APPLE_element_array = GL_FALSE; +GLboolean __GLEW_APPLE_fence = GL_FALSE; +GLboolean __GLEW_APPLE_float_pixels = GL_FALSE; +GLboolean __GLEW_APPLE_flush_buffer_range = GL_FALSE; +GLboolean __GLEW_APPLE_pixel_buffer = GL_FALSE; +GLboolean __GLEW_APPLE_specular_vector = GL_FALSE; +GLboolean __GLEW_APPLE_texture_range = GL_FALSE; +GLboolean __GLEW_APPLE_transform_hint = GL_FALSE; +GLboolean __GLEW_APPLE_vertex_array_object = GL_FALSE; +GLboolean __GLEW_APPLE_vertex_array_range = GL_FALSE; +GLboolean __GLEW_APPLE_ycbcr_422 = GL_FALSE; +GLboolean __GLEW_ARB_color_buffer_float = GL_FALSE; +GLboolean __GLEW_ARB_depth_texture = GL_FALSE; +GLboolean __GLEW_ARB_draw_buffers = GL_FALSE; +GLboolean __GLEW_ARB_fragment_program = GL_FALSE; +GLboolean __GLEW_ARB_fragment_program_shadow = GL_FALSE; +GLboolean __GLEW_ARB_fragment_shader = GL_FALSE; +GLboolean __GLEW_ARB_half_float_pixel = GL_FALSE; +GLboolean __GLEW_ARB_imaging = GL_FALSE; +GLboolean __GLEW_ARB_matrix_palette = GL_FALSE; +GLboolean __GLEW_ARB_multisample = GL_FALSE; +GLboolean __GLEW_ARB_multitexture = GL_FALSE; +GLboolean __GLEW_ARB_occlusion_query = GL_FALSE; +GLboolean __GLEW_ARB_pixel_buffer_object = GL_FALSE; +GLboolean __GLEW_ARB_point_parameters = GL_FALSE; +GLboolean __GLEW_ARB_point_sprite = GL_FALSE; +GLboolean __GLEW_ARB_shader_objects = GL_FALSE; +GLboolean __GLEW_ARB_shading_language_100 = GL_FALSE; +GLboolean __GLEW_ARB_shadow = GL_FALSE; +GLboolean __GLEW_ARB_shadow_ambient = GL_FALSE; +GLboolean __GLEW_ARB_texture_border_clamp = GL_FALSE; +GLboolean __GLEW_ARB_texture_compression = GL_FALSE; +GLboolean __GLEW_ARB_texture_cube_map = GL_FALSE; +GLboolean __GLEW_ARB_texture_env_add = GL_FALSE; +GLboolean __GLEW_ARB_texture_env_combine = GL_FALSE; +GLboolean __GLEW_ARB_texture_env_crossbar = GL_FALSE; +GLboolean __GLEW_ARB_texture_env_dot3 = GL_FALSE; +GLboolean __GLEW_ARB_texture_float = GL_FALSE; +GLboolean __GLEW_ARB_texture_mirrored_repeat = GL_FALSE; +GLboolean __GLEW_ARB_texture_non_power_of_two = GL_FALSE; +GLboolean __GLEW_ARB_texture_rectangle = GL_FALSE; +GLboolean __GLEW_ARB_transpose_matrix = GL_FALSE; +GLboolean __GLEW_ARB_vertex_blend = GL_FALSE; +GLboolean __GLEW_ARB_vertex_buffer_object = GL_FALSE; +GLboolean __GLEW_ARB_vertex_program = GL_FALSE; +GLboolean __GLEW_ARB_vertex_shader = GL_FALSE; +GLboolean __GLEW_ARB_window_pos = GL_FALSE; +GLboolean __GLEW_ATIX_point_sprites = GL_FALSE; +GLboolean __GLEW_ATIX_texture_env_combine3 = GL_FALSE; +GLboolean __GLEW_ATIX_texture_env_route = GL_FALSE; +GLboolean __GLEW_ATIX_vertex_shader_output_point_size = GL_FALSE; +GLboolean __GLEW_ATI_draw_buffers = GL_FALSE; +GLboolean __GLEW_ATI_element_array = GL_FALSE; +GLboolean __GLEW_ATI_envmap_bumpmap = GL_FALSE; +GLboolean __GLEW_ATI_fragment_shader = GL_FALSE; +GLboolean __GLEW_ATI_map_object_buffer = GL_FALSE; +GLboolean __GLEW_ATI_pn_triangles = GL_FALSE; +GLboolean __GLEW_ATI_separate_stencil = GL_FALSE; +GLboolean __GLEW_ATI_shader_texture_lod = GL_FALSE; +GLboolean __GLEW_ATI_text_fragment_shader = GL_FALSE; +GLboolean __GLEW_ATI_texture_compression_3dc = GL_FALSE; +GLboolean __GLEW_ATI_texture_env_combine3 = GL_FALSE; +GLboolean __GLEW_ATI_texture_float = GL_FALSE; +GLboolean __GLEW_ATI_texture_mirror_once = GL_FALSE; +GLboolean __GLEW_ATI_vertex_array_object = GL_FALSE; +GLboolean __GLEW_ATI_vertex_attrib_array_object = GL_FALSE; +GLboolean __GLEW_ATI_vertex_streams = GL_FALSE; +GLboolean __GLEW_EXT_422_pixels = GL_FALSE; +GLboolean __GLEW_EXT_Cg_shader = GL_FALSE; +GLboolean __GLEW_EXT_abgr = GL_FALSE; +GLboolean __GLEW_EXT_bgra = GL_FALSE; +GLboolean __GLEW_EXT_bindable_uniform = GL_FALSE; +GLboolean __GLEW_EXT_blend_color = GL_FALSE; +GLboolean __GLEW_EXT_blend_equation_separate = GL_FALSE; +GLboolean __GLEW_EXT_blend_func_separate = GL_FALSE; +GLboolean __GLEW_EXT_blend_logic_op = GL_FALSE; +GLboolean __GLEW_EXT_blend_minmax = GL_FALSE; +GLboolean __GLEW_EXT_blend_subtract = GL_FALSE; +GLboolean __GLEW_EXT_clip_volume_hint = GL_FALSE; +GLboolean __GLEW_EXT_cmyka = GL_FALSE; +GLboolean __GLEW_EXT_color_subtable = GL_FALSE; +GLboolean __GLEW_EXT_compiled_vertex_array = GL_FALSE; +GLboolean __GLEW_EXT_convolution = GL_FALSE; +GLboolean __GLEW_EXT_coordinate_frame = GL_FALSE; +GLboolean __GLEW_EXT_copy_texture = GL_FALSE; +GLboolean __GLEW_EXT_cull_vertex = GL_FALSE; +GLboolean __GLEW_EXT_depth_bounds_test = GL_FALSE; +GLboolean __GLEW_EXT_draw_buffers2 = GL_FALSE; +GLboolean __GLEW_EXT_draw_instanced = GL_FALSE; +GLboolean __GLEW_EXT_draw_range_elements = GL_FALSE; +GLboolean __GLEW_EXT_fog_coord = GL_FALSE; +GLboolean __GLEW_EXT_fragment_lighting = GL_FALSE; +GLboolean __GLEW_EXT_framebuffer_blit = GL_FALSE; +GLboolean __GLEW_EXT_framebuffer_multisample = GL_FALSE; +GLboolean __GLEW_EXT_framebuffer_object = GL_FALSE; +GLboolean __GLEW_EXT_framebuffer_sRGB = GL_FALSE; +GLboolean __GLEW_EXT_geometry_shader4 = GL_FALSE; +GLboolean __GLEW_EXT_gpu_program_parameters = GL_FALSE; +GLboolean __GLEW_EXT_gpu_shader4 = GL_FALSE; +GLboolean __GLEW_EXT_histogram = GL_FALSE; +GLboolean __GLEW_EXT_index_array_formats = GL_FALSE; +GLboolean __GLEW_EXT_index_func = GL_FALSE; +GLboolean __GLEW_EXT_index_material = GL_FALSE; +GLboolean __GLEW_EXT_index_texture = GL_FALSE; +GLboolean __GLEW_EXT_light_texture = GL_FALSE; +GLboolean __GLEW_EXT_misc_attribute = GL_FALSE; +GLboolean __GLEW_EXT_multi_draw_arrays = GL_FALSE; +GLboolean __GLEW_EXT_multisample = GL_FALSE; +GLboolean __GLEW_EXT_packed_depth_stencil = GL_FALSE; +GLboolean __GLEW_EXT_packed_float = GL_FALSE; +GLboolean __GLEW_EXT_packed_pixels = GL_FALSE; +GLboolean __GLEW_EXT_paletted_texture = GL_FALSE; +GLboolean __GLEW_EXT_pixel_buffer_object = GL_FALSE; +GLboolean __GLEW_EXT_pixel_transform = GL_FALSE; +GLboolean __GLEW_EXT_pixel_transform_color_table = GL_FALSE; +GLboolean __GLEW_EXT_point_parameters = GL_FALSE; +GLboolean __GLEW_EXT_polygon_offset = GL_FALSE; +GLboolean __GLEW_EXT_rescale_normal = GL_FALSE; +GLboolean __GLEW_EXT_scene_marker = GL_FALSE; +GLboolean __GLEW_EXT_secondary_color = GL_FALSE; +GLboolean __GLEW_EXT_separate_specular_color = GL_FALSE; +GLboolean __GLEW_EXT_shadow_funcs = GL_FALSE; +GLboolean __GLEW_EXT_shared_texture_palette = GL_FALSE; +GLboolean __GLEW_EXT_stencil_clear_tag = GL_FALSE; +GLboolean __GLEW_EXT_stencil_two_side = GL_FALSE; +GLboolean __GLEW_EXT_stencil_wrap = GL_FALSE; +GLboolean __GLEW_EXT_subtexture = GL_FALSE; +GLboolean __GLEW_EXT_texture = GL_FALSE; +GLboolean __GLEW_EXT_texture3D = GL_FALSE; +GLboolean __GLEW_EXT_texture_array = GL_FALSE; +GLboolean __GLEW_EXT_texture_buffer_object = GL_FALSE; +GLboolean __GLEW_EXT_texture_compression_dxt1 = GL_FALSE; +GLboolean __GLEW_EXT_texture_compression_latc = GL_FALSE; +GLboolean __GLEW_EXT_texture_compression_rgtc = GL_FALSE; +GLboolean __GLEW_EXT_texture_compression_s3tc = GL_FALSE; +GLboolean __GLEW_EXT_texture_cube_map = GL_FALSE; +GLboolean __GLEW_EXT_texture_edge_clamp = GL_FALSE; +GLboolean __GLEW_EXT_texture_env = GL_FALSE; +GLboolean __GLEW_EXT_texture_env_add = GL_FALSE; +GLboolean __GLEW_EXT_texture_env_combine = GL_FALSE; +GLboolean __GLEW_EXT_texture_env_dot3 = GL_FALSE; +GLboolean __GLEW_EXT_texture_filter_anisotropic = GL_FALSE; +GLboolean __GLEW_EXT_texture_integer = GL_FALSE; +GLboolean __GLEW_EXT_texture_lod_bias = GL_FALSE; +GLboolean __GLEW_EXT_texture_mirror_clamp = GL_FALSE; +GLboolean __GLEW_EXT_texture_object = GL_FALSE; +GLboolean __GLEW_EXT_texture_perturb_normal = GL_FALSE; +GLboolean __GLEW_EXT_texture_rectangle = GL_FALSE; +GLboolean __GLEW_EXT_texture_sRGB = GL_FALSE; +GLboolean __GLEW_EXT_texture_shared_exponent = GL_FALSE; +GLboolean __GLEW_EXT_timer_query = GL_FALSE; +GLboolean __GLEW_EXT_vertex_array = GL_FALSE; +GLboolean __GLEW_EXT_vertex_shader = GL_FALSE; +GLboolean __GLEW_EXT_vertex_weighting = GL_FALSE; +GLboolean __GLEW_GREMEDY_frame_terminator = GL_FALSE; +GLboolean __GLEW_GREMEDY_string_marker = GL_FALSE; +GLboolean __GLEW_HP_convolution_border_modes = GL_FALSE; +GLboolean __GLEW_HP_image_transform = GL_FALSE; +GLboolean __GLEW_HP_occlusion_test = GL_FALSE; +GLboolean __GLEW_HP_texture_lighting = GL_FALSE; +GLboolean __GLEW_IBM_cull_vertex = GL_FALSE; +GLboolean __GLEW_IBM_multimode_draw_arrays = GL_FALSE; +GLboolean __GLEW_IBM_rasterpos_clip = GL_FALSE; +GLboolean __GLEW_IBM_static_data = GL_FALSE; +GLboolean __GLEW_IBM_texture_mirrored_repeat = GL_FALSE; +GLboolean __GLEW_IBM_vertex_array_lists = GL_FALSE; +GLboolean __GLEW_INGR_color_clamp = GL_FALSE; +GLboolean __GLEW_INGR_interlace_read = GL_FALSE; +GLboolean __GLEW_INTEL_parallel_arrays = GL_FALSE; +GLboolean __GLEW_INTEL_texture_scissor = GL_FALSE; +GLboolean __GLEW_KTX_buffer_region = GL_FALSE; +GLboolean __GLEW_MESAX_texture_stack = GL_FALSE; +GLboolean __GLEW_MESA_pack_invert = GL_FALSE; +GLboolean __GLEW_MESA_resize_buffers = GL_FALSE; +GLboolean __GLEW_MESA_window_pos = GL_FALSE; +GLboolean __GLEW_MESA_ycbcr_texture = GL_FALSE; +GLboolean __GLEW_NV_blend_square = GL_FALSE; +GLboolean __GLEW_NV_copy_depth_to_color = GL_FALSE; +GLboolean __GLEW_NV_depth_buffer_float = GL_FALSE; +GLboolean __GLEW_NV_depth_clamp = GL_FALSE; +GLboolean __GLEW_NV_depth_range_unclamped = GL_FALSE; +GLboolean __GLEW_NV_evaluators = GL_FALSE; +GLboolean __GLEW_NV_fence = GL_FALSE; +GLboolean __GLEW_NV_float_buffer = GL_FALSE; +GLboolean __GLEW_NV_fog_distance = GL_FALSE; +GLboolean __GLEW_NV_fragment_program = GL_FALSE; +GLboolean __GLEW_NV_fragment_program2 = GL_FALSE; +GLboolean __GLEW_NV_fragment_program4 = GL_FALSE; +GLboolean __GLEW_NV_fragment_program_option = GL_FALSE; +GLboolean __GLEW_NV_framebuffer_multisample_coverage = GL_FALSE; +GLboolean __GLEW_NV_geometry_program4 = GL_FALSE; +GLboolean __GLEW_NV_geometry_shader4 = GL_FALSE; +GLboolean __GLEW_NV_gpu_program4 = GL_FALSE; +GLboolean __GLEW_NV_half_float = GL_FALSE; +GLboolean __GLEW_NV_light_max_exponent = GL_FALSE; +GLboolean __GLEW_NV_multisample_filter_hint = GL_FALSE; +GLboolean __GLEW_NV_occlusion_query = GL_FALSE; +GLboolean __GLEW_NV_packed_depth_stencil = GL_FALSE; +GLboolean __GLEW_NV_parameter_buffer_object = GL_FALSE; +GLboolean __GLEW_NV_pixel_data_range = GL_FALSE; +GLboolean __GLEW_NV_point_sprite = GL_FALSE; +GLboolean __GLEW_NV_primitive_restart = GL_FALSE; +GLboolean __GLEW_NV_register_combiners = GL_FALSE; +GLboolean __GLEW_NV_register_combiners2 = GL_FALSE; +GLboolean __GLEW_NV_texgen_emboss = GL_FALSE; +GLboolean __GLEW_NV_texgen_reflection = GL_FALSE; +GLboolean __GLEW_NV_texture_compression_vtc = GL_FALSE; +GLboolean __GLEW_NV_texture_env_combine4 = GL_FALSE; +GLboolean __GLEW_NV_texture_expand_normal = GL_FALSE; +GLboolean __GLEW_NV_texture_rectangle = GL_FALSE; +GLboolean __GLEW_NV_texture_shader = GL_FALSE; +GLboolean __GLEW_NV_texture_shader2 = GL_FALSE; +GLboolean __GLEW_NV_texture_shader3 = GL_FALSE; +GLboolean __GLEW_NV_transform_feedback = GL_FALSE; +GLboolean __GLEW_NV_vertex_array_range = GL_FALSE; +GLboolean __GLEW_NV_vertex_array_range2 = GL_FALSE; +GLboolean __GLEW_NV_vertex_program = GL_FALSE; +GLboolean __GLEW_NV_vertex_program1_1 = GL_FALSE; +GLboolean __GLEW_NV_vertex_program2 = GL_FALSE; +GLboolean __GLEW_NV_vertex_program2_option = GL_FALSE; +GLboolean __GLEW_NV_vertex_program3 = GL_FALSE; +GLboolean __GLEW_NV_vertex_program4 = GL_FALSE; +GLboolean __GLEW_OES_byte_coordinates = GL_FALSE; +GLboolean __GLEW_OES_compressed_paletted_texture = GL_FALSE; +GLboolean __GLEW_OES_read_format = GL_FALSE; +GLboolean __GLEW_OES_single_precision = GL_FALSE; +GLboolean __GLEW_OML_interlace = GL_FALSE; +GLboolean __GLEW_OML_resample = GL_FALSE; +GLboolean __GLEW_OML_subsample = GL_FALSE; +GLboolean __GLEW_PGI_misc_hints = GL_FALSE; +GLboolean __GLEW_PGI_vertex_hints = GL_FALSE; +GLboolean __GLEW_REND_screen_coordinates = GL_FALSE; +GLboolean __GLEW_S3_s3tc = GL_FALSE; +GLboolean __GLEW_SGIS_color_range = GL_FALSE; +GLboolean __GLEW_SGIS_detail_texture = GL_FALSE; +GLboolean __GLEW_SGIS_fog_function = GL_FALSE; +GLboolean __GLEW_SGIS_generate_mipmap = GL_FALSE; +GLboolean __GLEW_SGIS_multisample = GL_FALSE; +GLboolean __GLEW_SGIS_pixel_texture = GL_FALSE; +GLboolean __GLEW_SGIS_sharpen_texture = GL_FALSE; +GLboolean __GLEW_SGIS_texture4D = GL_FALSE; +GLboolean __GLEW_SGIS_texture_border_clamp = GL_FALSE; +GLboolean __GLEW_SGIS_texture_edge_clamp = GL_FALSE; +GLboolean __GLEW_SGIS_texture_filter4 = GL_FALSE; +GLboolean __GLEW_SGIS_texture_lod = GL_FALSE; +GLboolean __GLEW_SGIS_texture_select = GL_FALSE; +GLboolean __GLEW_SGIX_async = GL_FALSE; +GLboolean __GLEW_SGIX_async_histogram = GL_FALSE; +GLboolean __GLEW_SGIX_async_pixel = GL_FALSE; +GLboolean __GLEW_SGIX_blend_alpha_minmax = GL_FALSE; +GLboolean __GLEW_SGIX_clipmap = GL_FALSE; +GLboolean __GLEW_SGIX_depth_texture = GL_FALSE; +GLboolean __GLEW_SGIX_flush_raster = GL_FALSE; +GLboolean __GLEW_SGIX_fog_offset = GL_FALSE; +GLboolean __GLEW_SGIX_fog_texture = GL_FALSE; +GLboolean __GLEW_SGIX_fragment_specular_lighting = GL_FALSE; +GLboolean __GLEW_SGIX_framezoom = GL_FALSE; +GLboolean __GLEW_SGIX_interlace = GL_FALSE; +GLboolean __GLEW_SGIX_ir_instrument1 = GL_FALSE; +GLboolean __GLEW_SGIX_list_priority = GL_FALSE; +GLboolean __GLEW_SGIX_pixel_texture = GL_FALSE; +GLboolean __GLEW_SGIX_pixel_texture_bits = GL_FALSE; +GLboolean __GLEW_SGIX_reference_plane = GL_FALSE; +GLboolean __GLEW_SGIX_resample = GL_FALSE; +GLboolean __GLEW_SGIX_shadow = GL_FALSE; +GLboolean __GLEW_SGIX_shadow_ambient = GL_FALSE; +GLboolean __GLEW_SGIX_sprite = GL_FALSE; +GLboolean __GLEW_SGIX_tag_sample_buffer = GL_FALSE; +GLboolean __GLEW_SGIX_texture_add_env = GL_FALSE; +GLboolean __GLEW_SGIX_texture_coordinate_clamp = GL_FALSE; +GLboolean __GLEW_SGIX_texture_lod_bias = GL_FALSE; +GLboolean __GLEW_SGIX_texture_multi_buffer = GL_FALSE; +GLboolean __GLEW_SGIX_texture_range = GL_FALSE; +GLboolean __GLEW_SGIX_texture_scale_bias = GL_FALSE; +GLboolean __GLEW_SGIX_vertex_preclip = GL_FALSE; +GLboolean __GLEW_SGIX_vertex_preclip_hint = GL_FALSE; +GLboolean __GLEW_SGIX_ycrcb = GL_FALSE; +GLboolean __GLEW_SGI_color_matrix = GL_FALSE; +GLboolean __GLEW_SGI_color_table = GL_FALSE; +GLboolean __GLEW_SGI_texture_color_table = GL_FALSE; +GLboolean __GLEW_SUNX_constant_data = GL_FALSE; +GLboolean __GLEW_SUN_convolution_border_modes = GL_FALSE; +GLboolean __GLEW_SUN_global_alpha = GL_FALSE; +GLboolean __GLEW_SUN_mesh_array = GL_FALSE; +GLboolean __GLEW_SUN_read_video_pixels = GL_FALSE; +GLboolean __GLEW_SUN_slice_accum = GL_FALSE; +GLboolean __GLEW_SUN_triangle_list = GL_FALSE; +GLboolean __GLEW_SUN_vertex = GL_FALSE; +GLboolean __GLEW_WIN_phong_shading = GL_FALSE; +GLboolean __GLEW_WIN_specular_fog = GL_FALSE; +GLboolean __GLEW_WIN_swap_hint = GL_FALSE; + +#endif /* !GLEW_MX */ + +#ifdef GL_VERSION_1_2 + +static GLboolean _glewInit_GL_VERSION_1_2 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage3D")) == NULL) || r; + r = ((glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElements")) == NULL) || r; + r = ((glTexImage3D = (PFNGLTEXIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glTexImage3D")) == NULL) || r; + r = ((glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage3D")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_1_2 */ + +#ifdef GL_VERSION_1_3 + +static GLboolean _glewInit_GL_VERSION_1_3 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glActiveTexture = (PFNGLACTIVETEXTUREPROC)glewGetProcAddress((const GLubyte*)"glActiveTexture")) == NULL) || r; + r = ((glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC)glewGetProcAddress((const GLubyte*)"glClientActiveTexture")) == NULL) || r; + r = ((glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage1D")) == NULL) || r; + r = ((glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage2D")) == NULL) || r; + r = ((glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage3D")) == NULL) || r; + r = ((glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage1D")) == NULL) || r; + r = ((glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage2D")) == NULL) || r; + r = ((glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage3D")) == NULL) || r; + r = ((glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC)glewGetProcAddress((const GLubyte*)"glGetCompressedTexImage")) == NULL) || r; + r = ((glLoadTransposeMatrixd = (PFNGLLOADTRANSPOSEMATRIXDPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixd")) == NULL) || r; + r = ((glLoadTransposeMatrixf = (PFNGLLOADTRANSPOSEMATRIXFPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixf")) == NULL) || r; + r = ((glMultTransposeMatrixd = (PFNGLMULTTRANSPOSEMATRIXDPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixd")) == NULL) || r; + r = ((glMultTransposeMatrixf = (PFNGLMULTTRANSPOSEMATRIXFPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixf")) == NULL) || r; + r = ((glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1d")) == NULL) || r; + r = ((glMultiTexCoord1dv = (PFNGLMULTITEXCOORD1DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1dv")) == NULL) || r; + r = ((glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1f")) == NULL) || r; + r = ((glMultiTexCoord1fv = (PFNGLMULTITEXCOORD1FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1fv")) == NULL) || r; + r = ((glMultiTexCoord1i = (PFNGLMULTITEXCOORD1IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1i")) == NULL) || r; + r = ((glMultiTexCoord1iv = (PFNGLMULTITEXCOORD1IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1iv")) == NULL) || r; + r = ((glMultiTexCoord1s = (PFNGLMULTITEXCOORD1SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1s")) == NULL) || r; + r = ((glMultiTexCoord1sv = (PFNGLMULTITEXCOORD1SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1sv")) == NULL) || r; + r = ((glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2d")) == NULL) || r; + r = ((glMultiTexCoord2dv = (PFNGLMULTITEXCOORD2DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2dv")) == NULL) || r; + r = ((glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2f")) == NULL) || r; + r = ((glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2fv")) == NULL) || r; + r = ((glMultiTexCoord2i = (PFNGLMULTITEXCOORD2IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2i")) == NULL) || r; + r = ((glMultiTexCoord2iv = (PFNGLMULTITEXCOORD2IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2iv")) == NULL) || r; + r = ((glMultiTexCoord2s = (PFNGLMULTITEXCOORD2SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2s")) == NULL) || r; + r = ((glMultiTexCoord2sv = (PFNGLMULTITEXCOORD2SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2sv")) == NULL) || r; + r = ((glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3d")) == NULL) || r; + r = ((glMultiTexCoord3dv = (PFNGLMULTITEXCOORD3DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3dv")) == NULL) || r; + r = ((glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3f")) == NULL) || r; + r = ((glMultiTexCoord3fv = (PFNGLMULTITEXCOORD3FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3fv")) == NULL) || r; + r = ((glMultiTexCoord3i = (PFNGLMULTITEXCOORD3IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3i")) == NULL) || r; + r = ((glMultiTexCoord3iv = (PFNGLMULTITEXCOORD3IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3iv")) == NULL) || r; + r = ((glMultiTexCoord3s = (PFNGLMULTITEXCOORD3SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3s")) == NULL) || r; + r = ((glMultiTexCoord3sv = (PFNGLMULTITEXCOORD3SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3sv")) == NULL) || r; + r = ((glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4d")) == NULL) || r; + r = ((glMultiTexCoord4dv = (PFNGLMULTITEXCOORD4DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4dv")) == NULL) || r; + r = ((glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4f")) == NULL) || r; + r = ((glMultiTexCoord4fv = (PFNGLMULTITEXCOORD4FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4fv")) == NULL) || r; + r = ((glMultiTexCoord4i = (PFNGLMULTITEXCOORD4IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4i")) == NULL) || r; + r = ((glMultiTexCoord4iv = (PFNGLMULTITEXCOORD4IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4iv")) == NULL) || r; + r = ((glMultiTexCoord4s = (PFNGLMULTITEXCOORD4SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4s")) == NULL) || r; + r = ((glMultiTexCoord4sv = (PFNGLMULTITEXCOORD4SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4sv")) == NULL) || r; + r = ((glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC)glewGetProcAddress((const GLubyte*)"glSampleCoverage")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_1_3 */ + +#ifdef GL_VERSION_1_4 + +static GLboolean _glewInit_GL_VERSION_1_4 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendColor = (PFNGLBLENDCOLORPROC)glewGetProcAddress((const GLubyte*)"glBlendColor")) == NULL) || r; + r = ((glBlendEquation = (PFNGLBLENDEQUATIONPROC)glewGetProcAddress((const GLubyte*)"glBlendEquation")) == NULL) || r; + r = ((glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparate")) == NULL) || r; + r = ((glFogCoordPointer = (PFNGLFOGCOORDPOINTERPROC)glewGetProcAddress((const GLubyte*)"glFogCoordPointer")) == NULL) || r; + r = ((glFogCoordd = (PFNGLFOGCOORDDPROC)glewGetProcAddress((const GLubyte*)"glFogCoordd")) == NULL) || r; + r = ((glFogCoorddv = (PFNGLFOGCOORDDVPROC)glewGetProcAddress((const GLubyte*)"glFogCoorddv")) == NULL) || r; + r = ((glFogCoordf = (PFNGLFOGCOORDFPROC)glewGetProcAddress((const GLubyte*)"glFogCoordf")) == NULL) || r; + r = ((glFogCoordfv = (PFNGLFOGCOORDFVPROC)glewGetProcAddress((const GLubyte*)"glFogCoordfv")) == NULL) || r; + r = ((glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArrays")) == NULL) || r; + r = ((glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElements")) == NULL) || r; + r = ((glPointParameterf = (PFNGLPOINTPARAMETERFPROC)glewGetProcAddress((const GLubyte*)"glPointParameterf")) == NULL) || r; + r = ((glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfv")) == NULL) || r; + r = ((glPointParameteri = (PFNGLPOINTPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glPointParameteri")) == NULL) || r; + r = ((glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glPointParameteriv")) == NULL) || r; + r = ((glSecondaryColor3b = (PFNGLSECONDARYCOLOR3BPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3b")) == NULL) || r; + r = ((glSecondaryColor3bv = (PFNGLSECONDARYCOLOR3BVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3bv")) == NULL) || r; + r = ((glSecondaryColor3d = (PFNGLSECONDARYCOLOR3DPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3d")) == NULL) || r; + r = ((glSecondaryColor3dv = (PFNGLSECONDARYCOLOR3DVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3dv")) == NULL) || r; + r = ((glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3f")) == NULL) || r; + r = ((glSecondaryColor3fv = (PFNGLSECONDARYCOLOR3FVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3fv")) == NULL) || r; + r = ((glSecondaryColor3i = (PFNGLSECONDARYCOLOR3IPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3i")) == NULL) || r; + r = ((glSecondaryColor3iv = (PFNGLSECONDARYCOLOR3IVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3iv")) == NULL) || r; + r = ((glSecondaryColor3s = (PFNGLSECONDARYCOLOR3SPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3s")) == NULL) || r; + r = ((glSecondaryColor3sv = (PFNGLSECONDARYCOLOR3SVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3sv")) == NULL) || r; + r = ((glSecondaryColor3ub = (PFNGLSECONDARYCOLOR3UBPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ub")) == NULL) || r; + r = ((glSecondaryColor3ubv = (PFNGLSECONDARYCOLOR3UBVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ubv")) == NULL) || r; + r = ((glSecondaryColor3ui = (PFNGLSECONDARYCOLOR3UIPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ui")) == NULL) || r; + r = ((glSecondaryColor3uiv = (PFNGLSECONDARYCOLOR3UIVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3uiv")) == NULL) || r; + r = ((glSecondaryColor3us = (PFNGLSECONDARYCOLOR3USPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3us")) == NULL) || r; + r = ((glSecondaryColor3usv = (PFNGLSECONDARYCOLOR3USVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3usv")) == NULL) || r; + r = ((glSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorPointer")) == NULL) || r; + r = ((glWindowPos2d = (PFNGLWINDOWPOS2DPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2d")) == NULL) || r; + r = ((glWindowPos2dv = (PFNGLWINDOWPOS2DVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dv")) == NULL) || r; + r = ((glWindowPos2f = (PFNGLWINDOWPOS2FPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2f")) == NULL) || r; + r = ((glWindowPos2fv = (PFNGLWINDOWPOS2FVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fv")) == NULL) || r; + r = ((glWindowPos2i = (PFNGLWINDOWPOS2IPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2i")) == NULL) || r; + r = ((glWindowPos2iv = (PFNGLWINDOWPOS2IVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2iv")) == NULL) || r; + r = ((glWindowPos2s = (PFNGLWINDOWPOS2SPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2s")) == NULL) || r; + r = ((glWindowPos2sv = (PFNGLWINDOWPOS2SVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2sv")) == NULL) || r; + r = ((glWindowPos3d = (PFNGLWINDOWPOS3DPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3d")) == NULL) || r; + r = ((glWindowPos3dv = (PFNGLWINDOWPOS3DVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dv")) == NULL) || r; + r = ((glWindowPos3f = (PFNGLWINDOWPOS3FPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3f")) == NULL) || r; + r = ((glWindowPos3fv = (PFNGLWINDOWPOS3FVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fv")) == NULL) || r; + r = ((glWindowPos3i = (PFNGLWINDOWPOS3IPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3i")) == NULL) || r; + r = ((glWindowPos3iv = (PFNGLWINDOWPOS3IVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3iv")) == NULL) || r; + r = ((glWindowPos3s = (PFNGLWINDOWPOS3SPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3s")) == NULL) || r; + r = ((glWindowPos3sv = (PFNGLWINDOWPOS3SVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3sv")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_1_4 */ + +#ifdef GL_VERSION_1_5 + +static GLboolean _glewInit_GL_VERSION_1_5 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginQuery = (PFNGLBEGINQUERYPROC)glewGetProcAddress((const GLubyte*)"glBeginQuery")) == NULL) || r; + r = ((glBindBuffer = (PFNGLBINDBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindBuffer")) == NULL) || r; + r = ((glBufferData = (PFNGLBUFFERDATAPROC)glewGetProcAddress((const GLubyte*)"glBufferData")) == NULL) || r; + r = ((glBufferSubData = (PFNGLBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glBufferSubData")) == NULL) || r; + r = ((glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteBuffers")) == NULL) || r; + r = ((glDeleteQueries = (PFNGLDELETEQUERIESPROC)glewGetProcAddress((const GLubyte*)"glDeleteQueries")) == NULL) || r; + r = ((glEndQuery = (PFNGLENDQUERYPROC)glewGetProcAddress((const GLubyte*)"glEndQuery")) == NULL) || r; + r = ((glGenBuffers = (PFNGLGENBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glGenBuffers")) == NULL) || r; + r = ((glGenQueries = (PFNGLGENQUERIESPROC)glewGetProcAddress((const GLubyte*)"glGenQueries")) == NULL) || r; + r = ((glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetBufferParameteriv")) == NULL) || r; + r = ((glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC)glewGetProcAddress((const GLubyte*)"glGetBufferPointerv")) == NULL) || r; + r = ((glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glGetBufferSubData")) == NULL) || r; + r = ((glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectiv")) == NULL) || r; + r = ((glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectuiv")) == NULL) || r; + r = ((glGetQueryiv = (PFNGLGETQUERYIVPROC)glewGetProcAddress((const GLubyte*)"glGetQueryiv")) == NULL) || r; + r = ((glIsBuffer = (PFNGLISBUFFERPROC)glewGetProcAddress((const GLubyte*)"glIsBuffer")) == NULL) || r; + r = ((glIsQuery = (PFNGLISQUERYPROC)glewGetProcAddress((const GLubyte*)"glIsQuery")) == NULL) || r; + r = ((glMapBuffer = (PFNGLMAPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glMapBuffer")) == NULL) || r; + r = ((glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glUnmapBuffer")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_1_5 */ + +#ifdef GL_VERSION_2_0 + +static GLboolean _glewInit_GL_VERSION_2_0 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glAttachShader = (PFNGLATTACHSHADERPROC)glewGetProcAddress((const GLubyte*)"glAttachShader")) == NULL) || r; + r = ((glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glBindAttribLocation")) == NULL) || r; + r = ((glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparate")) == NULL) || r; + r = ((glCompileShader = (PFNGLCOMPILESHADERPROC)glewGetProcAddress((const GLubyte*)"glCompileShader")) == NULL) || r; + r = ((glCreateProgram = (PFNGLCREATEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glCreateProgram")) == NULL) || r; + r = ((glCreateShader = (PFNGLCREATESHADERPROC)glewGetProcAddress((const GLubyte*)"glCreateShader")) == NULL) || r; + r = ((glDeleteProgram = (PFNGLDELETEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glDeleteProgram")) == NULL) || r; + r = ((glDeleteShader = (PFNGLDELETESHADERPROC)glewGetProcAddress((const GLubyte*)"glDeleteShader")) == NULL) || r; + r = ((glDetachShader = (PFNGLDETACHSHADERPROC)glewGetProcAddress((const GLubyte*)"glDetachShader")) == NULL) || r; + r = ((glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)glewGetProcAddress((const GLubyte*)"glDisableVertexAttribArray")) == NULL) || r; + r = ((glDrawBuffers = (PFNGLDRAWBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffers")) == NULL) || r; + r = ((glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)glewGetProcAddress((const GLubyte*)"glEnableVertexAttribArray")) == NULL) || r; + r = ((glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)glewGetProcAddress((const GLubyte*)"glGetActiveAttrib")) == NULL) || r; + r = ((glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniform")) == NULL) || r; + r = ((glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)glewGetProcAddress((const GLubyte*)"glGetAttachedShaders")) == NULL) || r; + r = ((glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetAttribLocation")) == NULL) || r; + r = ((glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)glewGetProcAddress((const GLubyte*)"glGetProgramInfoLog")) == NULL) || r; + r = ((glGetProgramiv = (PFNGLGETPROGRAMIVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramiv")) == NULL) || r; + r = ((glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)glewGetProcAddress((const GLubyte*)"glGetShaderInfoLog")) == NULL) || r; + r = ((glGetShaderSource = (PFNGLGETSHADERSOURCEPROC)glewGetProcAddress((const GLubyte*)"glGetShaderSource")) == NULL) || r; + r = ((glGetShaderiv = (PFNGLGETSHADERIVPROC)glewGetProcAddress((const GLubyte*)"glGetShaderiv")) == NULL) || r; + r = ((glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetUniformLocation")) == NULL) || r; + r = ((glGetUniformfv = (PFNGLGETUNIFORMFVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformfv")) == NULL) || r; + r = ((glGetUniformiv = (PFNGLGETUNIFORMIVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformiv")) == NULL) || r; + r = ((glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribPointerv")) == NULL) || r; + r = ((glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribdv")) == NULL) || r; + r = ((glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribfv")) == NULL) || r; + r = ((glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribiv")) == NULL) || r; + r = ((glIsProgram = (PFNGLISPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glIsProgram")) == NULL) || r; + r = ((glIsShader = (PFNGLISSHADERPROC)glewGetProcAddress((const GLubyte*)"glIsShader")) == NULL) || r; + r = ((glLinkProgram = (PFNGLLINKPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glLinkProgram")) == NULL) || r; + r = ((glShaderSource = (PFNGLSHADERSOURCEPROC)glewGetProcAddress((const GLubyte*)"glShaderSource")) == NULL) || r; + r = ((glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glStencilFuncSeparate")) == NULL) || r; + r = ((glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glStencilMaskSeparate")) == NULL) || r; + r = ((glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glStencilOpSeparate")) == NULL) || r; + r = ((glUniform1f = (PFNGLUNIFORM1FPROC)glewGetProcAddress((const GLubyte*)"glUniform1f")) == NULL) || r; + r = ((glUniform1fv = (PFNGLUNIFORM1FVPROC)glewGetProcAddress((const GLubyte*)"glUniform1fv")) == NULL) || r; + r = ((glUniform1i = (PFNGLUNIFORM1IPROC)glewGetProcAddress((const GLubyte*)"glUniform1i")) == NULL) || r; + r = ((glUniform1iv = (PFNGLUNIFORM1IVPROC)glewGetProcAddress((const GLubyte*)"glUniform1iv")) == NULL) || r; + r = ((glUniform2f = (PFNGLUNIFORM2FPROC)glewGetProcAddress((const GLubyte*)"glUniform2f")) == NULL) || r; + r = ((glUniform2fv = (PFNGLUNIFORM2FVPROC)glewGetProcAddress((const GLubyte*)"glUniform2fv")) == NULL) || r; + r = ((glUniform2i = (PFNGLUNIFORM2IPROC)glewGetProcAddress((const GLubyte*)"glUniform2i")) == NULL) || r; + r = ((glUniform2iv = (PFNGLUNIFORM2IVPROC)glewGetProcAddress((const GLubyte*)"glUniform2iv")) == NULL) || r; + r = ((glUniform3f = (PFNGLUNIFORM3FPROC)glewGetProcAddress((const GLubyte*)"glUniform3f")) == NULL) || r; + r = ((glUniform3fv = (PFNGLUNIFORM3FVPROC)glewGetProcAddress((const GLubyte*)"glUniform3fv")) == NULL) || r; + r = ((glUniform3i = (PFNGLUNIFORM3IPROC)glewGetProcAddress((const GLubyte*)"glUniform3i")) == NULL) || r; + r = ((glUniform3iv = (PFNGLUNIFORM3IVPROC)glewGetProcAddress((const GLubyte*)"glUniform3iv")) == NULL) || r; + r = ((glUniform4f = (PFNGLUNIFORM4FPROC)glewGetProcAddress((const GLubyte*)"glUniform4f")) == NULL) || r; + r = ((glUniform4fv = (PFNGLUNIFORM4FVPROC)glewGetProcAddress((const GLubyte*)"glUniform4fv")) == NULL) || r; + r = ((glUniform4i = (PFNGLUNIFORM4IPROC)glewGetProcAddress((const GLubyte*)"glUniform4i")) == NULL) || r; + r = ((glUniform4iv = (PFNGLUNIFORM4IVPROC)glewGetProcAddress((const GLubyte*)"glUniform4iv")) == NULL) || r; + r = ((glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2fv")) == NULL) || r; + r = ((glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3fv")) == NULL) || r; + r = ((glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4fv")) == NULL) || r; + r = ((glUseProgram = (PFNGLUSEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glUseProgram")) == NULL) || r; + r = ((glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glValidateProgram")) == NULL) || r; + r = ((glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1d")) == NULL) || r; + r = ((glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dv")) == NULL) || r; + r = ((glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1f")) == NULL) || r; + r = ((glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fv")) == NULL) || r; + r = ((glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1s")) == NULL) || r; + r = ((glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1sv")) == NULL) || r; + r = ((glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2d")) == NULL) || r; + r = ((glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dv")) == NULL) || r; + r = ((glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2f")) == NULL) || r; + r = ((glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fv")) == NULL) || r; + r = ((glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2s")) == NULL) || r; + r = ((glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2sv")) == NULL) || r; + r = ((glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3d")) == NULL) || r; + r = ((glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dv")) == NULL) || r; + r = ((glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3f")) == NULL) || r; + r = ((glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fv")) == NULL) || r; + r = ((glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3s")) == NULL) || r; + r = ((glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3sv")) == NULL) || r; + r = ((glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nbv")) == NULL) || r; + r = ((glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Niv")) == NULL) || r; + r = ((glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nsv")) == NULL) || r; + r = ((glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nub")) == NULL) || r; + r = ((glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nubv")) == NULL) || r; + r = ((glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nuiv")) == NULL) || r; + r = ((glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nusv")) == NULL) || r; + r = ((glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4bv")) == NULL) || r; + r = ((glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4d")) == NULL) || r; + r = ((glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dv")) == NULL) || r; + r = ((glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4f")) == NULL) || r; + r = ((glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fv")) == NULL) || r; + r = ((glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4iv")) == NULL) || r; + r = ((glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4s")) == NULL) || r; + r = ((glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4sv")) == NULL) || r; + r = ((glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubv")) == NULL) || r; + r = ((glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4uiv")) == NULL) || r; + r = ((glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4usv")) == NULL) || r; + r = ((glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointer")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_2_0 */ + +#ifdef GL_VERSION_2_1 + +static GLboolean _glewInit_GL_VERSION_2_1 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2x3fv")) == NULL) || r; + r = ((glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2x4fv")) == NULL) || r; + r = ((glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3x2fv")) == NULL) || r; + r = ((glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3x4fv")) == NULL) || r; + r = ((glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4x2fv")) == NULL) || r; + r = ((glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4x3fv")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_2_1 */ + +#ifdef GL_3DFX_multisample + +#endif /* GL_3DFX_multisample */ + +#ifdef GL_3DFX_tbuffer + +static GLboolean _glewInit_GL_3DFX_tbuffer (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTbufferMask3DFX = (PFNGLTBUFFERMASK3DFXPROC)glewGetProcAddress((const GLubyte*)"glTbufferMask3DFX")) == NULL) || r; + + return r; +} + +#endif /* GL_3DFX_tbuffer */ + +#ifdef GL_3DFX_texture_compression_FXT1 + +#endif /* GL_3DFX_texture_compression_FXT1 */ + +#ifdef GL_APPLE_client_storage + +#endif /* GL_APPLE_client_storage */ + +#ifdef GL_APPLE_element_array + +static GLboolean _glewInit_GL_APPLE_element_array (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawElementArrayAPPLE = (PFNGLDRAWELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDrawElementArrayAPPLE")) == NULL) || r; + r = ((glDrawRangeElementArrayAPPLE = (PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElementArrayAPPLE")) == NULL) || r; + r = ((glElementPointerAPPLE = (PFNGLELEMENTPOINTERAPPLEPROC)glewGetProcAddress((const GLubyte*)"glElementPointerAPPLE")) == NULL) || r; + r = ((glMultiDrawElementArrayAPPLE = (PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementArrayAPPLE")) == NULL) || r; + r = ((glMultiDrawRangeElementArrayAPPLE = (PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawRangeElementArrayAPPLE")) == NULL) || r; + + return r; +} + +#endif /* GL_APPLE_element_array */ + +#ifdef GL_APPLE_fence + +static GLboolean _glewInit_GL_APPLE_fence (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDeleteFencesAPPLE = (PFNGLDELETEFENCESAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDeleteFencesAPPLE")) == NULL) || r; + r = ((glFinishFenceAPPLE = (PFNGLFINISHFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFinishFenceAPPLE")) == NULL) || r; + r = ((glFinishObjectAPPLE = (PFNGLFINISHOBJECTAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFinishObjectAPPLE")) == NULL) || r; + r = ((glGenFencesAPPLE = (PFNGLGENFENCESAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGenFencesAPPLE")) == NULL) || r; + r = ((glIsFenceAPPLE = (PFNGLISFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glIsFenceAPPLE")) == NULL) || r; + r = ((glSetFenceAPPLE = (PFNGLSETFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glSetFenceAPPLE")) == NULL) || r; + r = ((glTestFenceAPPLE = (PFNGLTESTFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glTestFenceAPPLE")) == NULL) || r; + r = ((glTestObjectAPPLE = (PFNGLTESTOBJECTAPPLEPROC)glewGetProcAddress((const GLubyte*)"glTestObjectAPPLE")) == NULL) || r; + + return r; +} + +#endif /* GL_APPLE_fence */ + +#ifdef GL_APPLE_float_pixels + +#endif /* GL_APPLE_float_pixels */ + +#ifdef GL_APPLE_flush_buffer_range + +static GLboolean _glewInit_GL_APPLE_flush_buffer_range (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBufferParameteriAPPLE = (PFNGLBUFFERPARAMETERIAPPLEPROC)glewGetProcAddress((const GLubyte*)"glBufferParameteriAPPLE")) == NULL) || r; + r = ((glFlushMappedBufferRangeAPPLE = (PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFlushMappedBufferRangeAPPLE")) == NULL) || r; + + return r; +} + +#endif /* GL_APPLE_flush_buffer_range */ + +#ifdef GL_APPLE_pixel_buffer + +#endif /* GL_APPLE_pixel_buffer */ + +#ifdef GL_APPLE_specular_vector + +#endif /* GL_APPLE_specular_vector */ + +#ifdef GL_APPLE_texture_range + +static GLboolean _glewInit_GL_APPLE_texture_range (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetTexParameterPointervAPPLE = (PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterPointervAPPLE")) == NULL) || r; + r = ((glTextureRangeAPPLE = (PFNGLTEXTURERANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glTextureRangeAPPLE")) == NULL) || r; + + return r; +} + +#endif /* GL_APPLE_texture_range */ + +#ifdef GL_APPLE_transform_hint + +#endif /* GL_APPLE_transform_hint */ + +#ifdef GL_APPLE_vertex_array_object + +static GLboolean _glewInit_GL_APPLE_vertex_array_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindVertexArrayAPPLE = (PFNGLBINDVERTEXARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glBindVertexArrayAPPLE")) == NULL) || r; + r = ((glDeleteVertexArraysAPPLE = (PFNGLDELETEVERTEXARRAYSAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDeleteVertexArraysAPPLE")) == NULL) || r; + r = ((glGenVertexArraysAPPLE = (PFNGLGENVERTEXARRAYSAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGenVertexArraysAPPLE")) == NULL) || r; + r = ((glIsVertexArrayAPPLE = (PFNGLISVERTEXARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glIsVertexArrayAPPLE")) == NULL) || r; + + return r; +} + +#endif /* GL_APPLE_vertex_array_object */ + +#ifdef GL_APPLE_vertex_array_range + +static GLboolean _glewInit_GL_APPLE_vertex_array_range (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFlushVertexArrayRangeAPPLE = (PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFlushVertexArrayRangeAPPLE")) == NULL) || r; + r = ((glVertexArrayParameteriAPPLE = (PFNGLVERTEXARRAYPARAMETERIAPPLEPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayParameteriAPPLE")) == NULL) || r; + r = ((glVertexArrayRangeAPPLE = (PFNGLVERTEXARRAYRANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayRangeAPPLE")) == NULL) || r; + + return r; +} + +#endif /* GL_APPLE_vertex_array_range */ + +#ifdef GL_APPLE_ycbcr_422 + +#endif /* GL_APPLE_ycbcr_422 */ + +#ifdef GL_ARB_color_buffer_float + +static GLboolean _glewInit_GL_ARB_color_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glClampColorARB = (PFNGLCLAMPCOLORARBPROC)glewGetProcAddress((const GLubyte*)"glClampColorARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_color_buffer_float */ + +#ifdef GL_ARB_depth_texture + +#endif /* GL_ARB_depth_texture */ + +#ifdef GL_ARB_draw_buffers + +static GLboolean _glewInit_GL_ARB_draw_buffers (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffersARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_draw_buffers */ + +#ifdef GL_ARB_fragment_program + +#endif /* GL_ARB_fragment_program */ + +#ifdef GL_ARB_fragment_program_shadow + +#endif /* GL_ARB_fragment_program_shadow */ + +#ifdef GL_ARB_fragment_shader + +#endif /* GL_ARB_fragment_shader */ + +#ifdef GL_ARB_half_float_pixel + +#endif /* GL_ARB_half_float_pixel */ + +#ifdef GL_ARB_imaging + +static GLboolean _glewInit_GL_ARB_imaging (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendEquation = (PFNGLBLENDEQUATIONPROC)glewGetProcAddress((const GLubyte*)"glBlendEquation")) == NULL) || r; + r = ((glColorSubTable = (PFNGLCOLORSUBTABLEPROC)glewGetProcAddress((const GLubyte*)"glColorSubTable")) == NULL) || r; + r = ((glColorTable = (PFNGLCOLORTABLEPROC)glewGetProcAddress((const GLubyte*)"glColorTable")) == NULL) || r; + r = ((glColorTableParameterfv = (PFNGLCOLORTABLEPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameterfv")) == NULL) || r; + r = ((glColorTableParameteriv = (PFNGLCOLORTABLEPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameteriv")) == NULL) || r; + r = ((glConvolutionFilter1D = (PFNGLCONVOLUTIONFILTER1DPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter1D")) == NULL) || r; + r = ((glConvolutionFilter2D = (PFNGLCONVOLUTIONFILTER2DPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter2D")) == NULL) || r; + r = ((glConvolutionParameterf = (PFNGLCONVOLUTIONPARAMETERFPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterf")) == NULL) || r; + r = ((glConvolutionParameterfv = (PFNGLCONVOLUTIONPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterfv")) == NULL) || r; + r = ((glConvolutionParameteri = (PFNGLCONVOLUTIONPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameteri")) == NULL) || r; + r = ((glConvolutionParameteriv = (PFNGLCONVOLUTIONPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameteriv")) == NULL) || r; + r = ((glCopyColorSubTable = (PFNGLCOPYCOLORSUBTABLEPROC)glewGetProcAddress((const GLubyte*)"glCopyColorSubTable")) == NULL) || r; + r = ((glCopyColorTable = (PFNGLCOPYCOLORTABLEPROC)glewGetProcAddress((const GLubyte*)"glCopyColorTable")) == NULL) || r; + r = ((glCopyConvolutionFilter1D = (PFNGLCOPYCONVOLUTIONFILTER1DPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter1D")) == NULL) || r; + r = ((glCopyConvolutionFilter2D = (PFNGLCOPYCONVOLUTIONFILTER2DPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter2D")) == NULL) || r; + r = ((glGetColorTable = (PFNGLGETCOLORTABLEPROC)glewGetProcAddress((const GLubyte*)"glGetColorTable")) == NULL) || r; + r = ((glGetColorTableParameterfv = (PFNGLGETCOLORTABLEPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterfv")) == NULL) || r; + r = ((glGetColorTableParameteriv = (PFNGLGETCOLORTABLEPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameteriv")) == NULL) || r; + r = ((glGetConvolutionFilter = (PFNGLGETCONVOLUTIONFILTERPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionFilter")) == NULL) || r; + r = ((glGetConvolutionParameterfv = (PFNGLGETCONVOLUTIONPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameterfv")) == NULL) || r; + r = ((glGetConvolutionParameteriv = (PFNGLGETCONVOLUTIONPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameteriv")) == NULL) || r; + r = ((glGetHistogram = (PFNGLGETHISTOGRAMPROC)glewGetProcAddress((const GLubyte*)"glGetHistogram")) == NULL) || r; + r = ((glGetHistogramParameterfv = (PFNGLGETHISTOGRAMPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameterfv")) == NULL) || r; + r = ((glGetHistogramParameteriv = (PFNGLGETHISTOGRAMPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameteriv")) == NULL) || r; + r = ((glGetMinmax = (PFNGLGETMINMAXPROC)glewGetProcAddress((const GLubyte*)"glGetMinmax")) == NULL) || r; + r = ((glGetMinmaxParameterfv = (PFNGLGETMINMAXPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameterfv")) == NULL) || r; + r = ((glGetMinmaxParameteriv = (PFNGLGETMINMAXPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameteriv")) == NULL) || r; + r = ((glGetSeparableFilter = (PFNGLGETSEPARABLEFILTERPROC)glewGetProcAddress((const GLubyte*)"glGetSeparableFilter")) == NULL) || r; + r = ((glHistogram = (PFNGLHISTOGRAMPROC)glewGetProcAddress((const GLubyte*)"glHistogram")) == NULL) || r; + r = ((glMinmax = (PFNGLMINMAXPROC)glewGetProcAddress((const GLubyte*)"glMinmax")) == NULL) || r; + r = ((glResetHistogram = (PFNGLRESETHISTOGRAMPROC)glewGetProcAddress((const GLubyte*)"glResetHistogram")) == NULL) || r; + r = ((glResetMinmax = (PFNGLRESETMINMAXPROC)glewGetProcAddress((const GLubyte*)"glResetMinmax")) == NULL) || r; + r = ((glSeparableFilter2D = (PFNGLSEPARABLEFILTER2DPROC)glewGetProcAddress((const GLubyte*)"glSeparableFilter2D")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_imaging */ + +#ifdef GL_ARB_matrix_palette + +static GLboolean _glewInit_GL_ARB_matrix_palette (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCurrentPaletteMatrixARB = (PFNGLCURRENTPALETTEMATRIXARBPROC)glewGetProcAddress((const GLubyte*)"glCurrentPaletteMatrixARB")) == NULL) || r; + r = ((glMatrixIndexPointerARB = (PFNGLMATRIXINDEXPOINTERARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexPointerARB")) == NULL) || r; + r = ((glMatrixIndexubvARB = (PFNGLMATRIXINDEXUBVARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexubvARB")) == NULL) || r; + r = ((glMatrixIndexuivARB = (PFNGLMATRIXINDEXUIVARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexuivARB")) == NULL) || r; + r = ((glMatrixIndexusvARB = (PFNGLMATRIXINDEXUSVARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexusvARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_matrix_palette */ + +#ifdef GL_ARB_multisample + +static GLboolean _glewInit_GL_ARB_multisample (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glSampleCoverageARB = (PFNGLSAMPLECOVERAGEARBPROC)glewGetProcAddress((const GLubyte*)"glSampleCoverageARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_multisample */ + +#ifdef GL_ARB_multitexture + +static GLboolean _glewInit_GL_ARB_multitexture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)glewGetProcAddress((const GLubyte*)"glActiveTextureARB")) == NULL) || r; + r = ((glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)glewGetProcAddress((const GLubyte*)"glClientActiveTextureARB")) == NULL) || r; + r = ((glMultiTexCoord1dARB = (PFNGLMULTITEXCOORD1DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1dARB")) == NULL) || r; + r = ((glMultiTexCoord1dvARB = (PFNGLMULTITEXCOORD1DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1dvARB")) == NULL) || r; + r = ((glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1fARB")) == NULL) || r; + r = ((glMultiTexCoord1fvARB = (PFNGLMULTITEXCOORD1FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1fvARB")) == NULL) || r; + r = ((glMultiTexCoord1iARB = (PFNGLMULTITEXCOORD1IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1iARB")) == NULL) || r; + r = ((glMultiTexCoord1ivARB = (PFNGLMULTITEXCOORD1IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1ivARB")) == NULL) || r; + r = ((glMultiTexCoord1sARB = (PFNGLMULTITEXCOORD1SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1sARB")) == NULL) || r; + r = ((glMultiTexCoord1svARB = (PFNGLMULTITEXCOORD1SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1svARB")) == NULL) || r; + r = ((glMultiTexCoord2dARB = (PFNGLMULTITEXCOORD2DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2dARB")) == NULL) || r; + r = ((glMultiTexCoord2dvARB = (PFNGLMULTITEXCOORD2DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2dvARB")) == NULL) || r; + r = ((glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2fARB")) == NULL) || r; + r = ((glMultiTexCoord2fvARB = (PFNGLMULTITEXCOORD2FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2fvARB")) == NULL) || r; + r = ((glMultiTexCoord2iARB = (PFNGLMULTITEXCOORD2IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2iARB")) == NULL) || r; + r = ((glMultiTexCoord2ivARB = (PFNGLMULTITEXCOORD2IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2ivARB")) == NULL) || r; + r = ((glMultiTexCoord2sARB = (PFNGLMULTITEXCOORD2SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2sARB")) == NULL) || r; + r = ((glMultiTexCoord2svARB = (PFNGLMULTITEXCOORD2SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2svARB")) == NULL) || r; + r = ((glMultiTexCoord3dARB = (PFNGLMULTITEXCOORD3DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3dARB")) == NULL) || r; + r = ((glMultiTexCoord3dvARB = (PFNGLMULTITEXCOORD3DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3dvARB")) == NULL) || r; + r = ((glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3fARB")) == NULL) || r; + r = ((glMultiTexCoord3fvARB = (PFNGLMULTITEXCOORD3FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3fvARB")) == NULL) || r; + r = ((glMultiTexCoord3iARB = (PFNGLMULTITEXCOORD3IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3iARB")) == NULL) || r; + r = ((glMultiTexCoord3ivARB = (PFNGLMULTITEXCOORD3IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3ivARB")) == NULL) || r; + r = ((glMultiTexCoord3sARB = (PFNGLMULTITEXCOORD3SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3sARB")) == NULL) || r; + r = ((glMultiTexCoord3svARB = (PFNGLMULTITEXCOORD3SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3svARB")) == NULL) || r; + r = ((glMultiTexCoord4dARB = (PFNGLMULTITEXCOORD4DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4dARB")) == NULL) || r; + r = ((glMultiTexCoord4dvARB = (PFNGLMULTITEXCOORD4DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4dvARB")) == NULL) || r; + r = ((glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4fARB")) == NULL) || r; + r = ((glMultiTexCoord4fvARB = (PFNGLMULTITEXCOORD4FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4fvARB")) == NULL) || r; + r = ((glMultiTexCoord4iARB = (PFNGLMULTITEXCOORD4IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4iARB")) == NULL) || r; + r = ((glMultiTexCoord4ivARB = (PFNGLMULTITEXCOORD4IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4ivARB")) == NULL) || r; + r = ((glMultiTexCoord4sARB = (PFNGLMULTITEXCOORD4SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4sARB")) == NULL) || r; + r = ((glMultiTexCoord4svARB = (PFNGLMULTITEXCOORD4SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4svARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_multitexture */ + +#ifdef GL_ARB_occlusion_query + +static GLboolean _glewInit_GL_ARB_occlusion_query (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginQueryARB = (PFNGLBEGINQUERYARBPROC)glewGetProcAddress((const GLubyte*)"glBeginQueryARB")) == NULL) || r; + r = ((glDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteQueriesARB")) == NULL) || r; + r = ((glEndQueryARB = (PFNGLENDQUERYARBPROC)glewGetProcAddress((const GLubyte*)"glEndQueryARB")) == NULL) || r; + r = ((glGenQueriesARB = (PFNGLGENQUERIESARBPROC)glewGetProcAddress((const GLubyte*)"glGenQueriesARB")) == NULL) || r; + r = ((glGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectivARB")) == NULL) || r; + r = ((glGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectuivARB")) == NULL) || r; + r = ((glGetQueryivARB = (PFNGLGETQUERYIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetQueryivARB")) == NULL) || r; + r = ((glIsQueryARB = (PFNGLISQUERYARBPROC)glewGetProcAddress((const GLubyte*)"glIsQueryARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_occlusion_query */ + +#ifdef GL_ARB_pixel_buffer_object + +#endif /* GL_ARB_pixel_buffer_object */ + +#ifdef GL_ARB_point_parameters + +static GLboolean _glewInit_GL_ARB_point_parameters (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfARB")) == NULL) || r; + r = ((glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfvARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_point_parameters */ + +#ifdef GL_ARB_point_sprite + +#endif /* GL_ARB_point_sprite */ + +#ifdef GL_ARB_shader_objects + +static GLboolean _glewInit_GL_ARB_shader_objects (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glAttachObjectARB")) == NULL) || r; + r = ((glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)glewGetProcAddress((const GLubyte*)"glCompileShaderARB")) == NULL) || r; + r = ((glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glCreateProgramObjectARB")) == NULL) || r; + r = ((glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glCreateShaderObjectARB")) == NULL) || r; + r = ((glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteObjectARB")) == NULL) || r; + r = ((glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glDetachObjectARB")) == NULL) || r; + r = ((glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniformARB")) == NULL) || r; + r = ((glGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC)glewGetProcAddress((const GLubyte*)"glGetAttachedObjectsARB")) == NULL) || r; + r = ((glGetHandleARB = (PFNGLGETHANDLEARBPROC)glewGetProcAddress((const GLubyte*)"glGetHandleARB")) == NULL) || r; + r = ((glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)glewGetProcAddress((const GLubyte*)"glGetInfoLogARB")) == NULL) || r; + r = ((glGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetObjectParameterfvARB")) == NULL) || r; + r = ((glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetObjectParameterivARB")) == NULL) || r; + r = ((glGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC)glewGetProcAddress((const GLubyte*)"glGetShaderSourceARB")) == NULL) || r; + r = ((glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)glewGetProcAddress((const GLubyte*)"glGetUniformLocationARB")) == NULL) || r; + r = ((glGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetUniformfvARB")) == NULL) || r; + r = ((glGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetUniformivARB")) == NULL) || r; + r = ((glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glLinkProgramARB")) == NULL) || r; + r = ((glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)glewGetProcAddress((const GLubyte*)"glShaderSourceARB")) == NULL) || r; + r = ((glUniform1fARB = (PFNGLUNIFORM1FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1fARB")) == NULL) || r; + r = ((glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1fvARB")) == NULL) || r; + r = ((glUniform1iARB = (PFNGLUNIFORM1IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1iARB")) == NULL) || r; + r = ((glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1ivARB")) == NULL) || r; + r = ((glUniform2fARB = (PFNGLUNIFORM2FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2fARB")) == NULL) || r; + r = ((glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2fvARB")) == NULL) || r; + r = ((glUniform2iARB = (PFNGLUNIFORM2IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2iARB")) == NULL) || r; + r = ((glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2ivARB")) == NULL) || r; + r = ((glUniform3fARB = (PFNGLUNIFORM3FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3fARB")) == NULL) || r; + r = ((glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3fvARB")) == NULL) || r; + r = ((glUniform3iARB = (PFNGLUNIFORM3IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3iARB")) == NULL) || r; + r = ((glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3ivARB")) == NULL) || r; + r = ((glUniform4fARB = (PFNGLUNIFORM4FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4fARB")) == NULL) || r; + r = ((glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4fvARB")) == NULL) || r; + r = ((glUniform4iARB = (PFNGLUNIFORM4IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4iARB")) == NULL) || r; + r = ((glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4ivARB")) == NULL) || r; + r = ((glUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2fvARB")) == NULL) || r; + r = ((glUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3fvARB")) == NULL) || r; + r = ((glUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4fvARB")) == NULL) || r; + r = ((glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glUseProgramObjectARB")) == NULL) || r; + r = ((glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glValidateProgramARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_shader_objects */ + +#ifdef GL_ARB_shading_language_100 + +#endif /* GL_ARB_shading_language_100 */ + +#ifdef GL_ARB_shadow + +#endif /* GL_ARB_shadow */ + +#ifdef GL_ARB_shadow_ambient + +#endif /* GL_ARB_shadow_ambient */ + +#ifdef GL_ARB_texture_border_clamp + +#endif /* GL_ARB_texture_border_clamp */ + +#ifdef GL_ARB_texture_compression + +static GLboolean _glewInit_GL_ARB_texture_compression (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCompressedTexImage1DARB = (PFNGLCOMPRESSEDTEXIMAGE1DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage1DARB")) == NULL) || r; + r = ((glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage2DARB")) == NULL) || r; + r = ((glCompressedTexImage3DARB = (PFNGLCOMPRESSEDTEXIMAGE3DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage3DARB")) == NULL) || r; + r = ((glCompressedTexSubImage1DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage1DARB")) == NULL) || r; + r = ((glCompressedTexSubImage2DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage2DARB")) == NULL) || r; + r = ((glCompressedTexSubImage3DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage3DARB")) == NULL) || r; + r = ((glGetCompressedTexImageARB = (PFNGLGETCOMPRESSEDTEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"glGetCompressedTexImageARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_texture_compression */ + +#ifdef GL_ARB_texture_cube_map + +#endif /* GL_ARB_texture_cube_map */ + +#ifdef GL_ARB_texture_env_add + +#endif /* GL_ARB_texture_env_add */ + +#ifdef GL_ARB_texture_env_combine + +#endif /* GL_ARB_texture_env_combine */ + +#ifdef GL_ARB_texture_env_crossbar + +#endif /* GL_ARB_texture_env_crossbar */ + +#ifdef GL_ARB_texture_env_dot3 + +#endif /* GL_ARB_texture_env_dot3 */ + +#ifdef GL_ARB_texture_float + +#endif /* GL_ARB_texture_float */ + +#ifdef GL_ARB_texture_mirrored_repeat + +#endif /* GL_ARB_texture_mirrored_repeat */ + +#ifdef GL_ARB_texture_non_power_of_two + +#endif /* GL_ARB_texture_non_power_of_two */ + +#ifdef GL_ARB_texture_rectangle + +#endif /* GL_ARB_texture_rectangle */ + +#ifdef GL_ARB_transpose_matrix + +static GLboolean _glewInit_GL_ARB_transpose_matrix (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glLoadTransposeMatrixdARB = (PFNGLLOADTRANSPOSEMATRIXDARBPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixdARB")) == NULL) || r; + r = ((glLoadTransposeMatrixfARB = (PFNGLLOADTRANSPOSEMATRIXFARBPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixfARB")) == NULL) || r; + r = ((glMultTransposeMatrixdARB = (PFNGLMULTTRANSPOSEMATRIXDARBPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixdARB")) == NULL) || r; + r = ((glMultTransposeMatrixfARB = (PFNGLMULTTRANSPOSEMATRIXFARBPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixfARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_transpose_matrix */ + +#ifdef GL_ARB_vertex_blend + +static GLboolean _glewInit_GL_ARB_vertex_blend (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glVertexBlendARB = (PFNGLVERTEXBLENDARBPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendARB")) == NULL) || r; + r = ((glWeightPointerARB = (PFNGLWEIGHTPOINTERARBPROC)glewGetProcAddress((const GLubyte*)"glWeightPointerARB")) == NULL) || r; + r = ((glWeightbvARB = (PFNGLWEIGHTBVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightbvARB")) == NULL) || r; + r = ((glWeightdvARB = (PFNGLWEIGHTDVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightdvARB")) == NULL) || r; + r = ((glWeightfvARB = (PFNGLWEIGHTFVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightfvARB")) == NULL) || r; + r = ((glWeightivARB = (PFNGLWEIGHTIVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightivARB")) == NULL) || r; + r = ((glWeightsvARB = (PFNGLWEIGHTSVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightsvARB")) == NULL) || r; + r = ((glWeightubvARB = (PFNGLWEIGHTUBVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightubvARB")) == NULL) || r; + r = ((glWeightuivARB = (PFNGLWEIGHTUIVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightuivARB")) == NULL) || r; + r = ((glWeightusvARB = (PFNGLWEIGHTUSVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightusvARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_vertex_blend */ + +#ifdef GL_ARB_vertex_buffer_object + +static GLboolean _glewInit_GL_ARB_vertex_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindBufferARB = (PFNGLBINDBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glBindBufferARB")) == NULL) || r; + r = ((glBufferDataARB = (PFNGLBUFFERDATAARBPROC)glewGetProcAddress((const GLubyte*)"glBufferDataARB")) == NULL) || r; + r = ((glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)glewGetProcAddress((const GLubyte*)"glBufferSubDataARB")) == NULL) || r; + r = ((glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteBuffersARB")) == NULL) || r; + r = ((glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)glewGetProcAddress((const GLubyte*)"glGenBuffersARB")) == NULL) || r; + r = ((glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetBufferParameterivARB")) == NULL) || r; + r = ((glGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC)glewGetProcAddress((const GLubyte*)"glGetBufferPointervARB")) == NULL) || r; + r = ((glGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC)glewGetProcAddress((const GLubyte*)"glGetBufferSubDataARB")) == NULL) || r; + r = ((glIsBufferARB = (PFNGLISBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glIsBufferARB")) == NULL) || r; + r = ((glMapBufferARB = (PFNGLMAPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glMapBufferARB")) == NULL) || r; + r = ((glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glUnmapBufferARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_vertex_buffer_object */ + +#ifdef GL_ARB_vertex_program + +static GLboolean _glewInit_GL_ARB_vertex_program (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindProgramARB = (PFNGLBINDPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glBindProgramARB")) == NULL) || r; + r = ((glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteProgramsARB")) == NULL) || r; + r = ((glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)glewGetProcAddress((const GLubyte*)"glDisableVertexAttribArrayARB")) == NULL) || r; + r = ((glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC)glewGetProcAddress((const GLubyte*)"glEnableVertexAttribArrayARB")) == NULL) || r; + r = ((glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC)glewGetProcAddress((const GLubyte*)"glGenProgramsARB")) == NULL) || r; + r = ((glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramEnvParameterdvARB")) == NULL) || r; + r = ((glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramEnvParameterfvARB")) == NULL) || r; + r = ((glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramLocalParameterdvARB")) == NULL) || r; + r = ((glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramLocalParameterfvARB")) == NULL) || r; + r = ((glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramStringARB")) == NULL) || r; + r = ((glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramivARB")) == NULL) || r; + r = ((glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribPointervARB")) == NULL) || r; + r = ((glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribdvARB")) == NULL) || r; + r = ((glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribfvARB")) == NULL) || r; + r = ((glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribivARB")) == NULL) || r; + r = ((glIsProgramARB = (PFNGLISPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glIsProgramARB")) == NULL) || r; + r = ((glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4dARB")) == NULL) || r; + r = ((glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4dvARB")) == NULL) || r; + r = ((glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4fARB")) == NULL) || r; + r = ((glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4fvARB")) == NULL) || r; + r = ((glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4dARB")) == NULL) || r; + r = ((glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4dvARB")) == NULL) || r; + r = ((glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4fARB")) == NULL) || r; + r = ((glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4fvARB")) == NULL) || r; + r = ((glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glProgramStringARB")) == NULL) || r; + r = ((glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dARB")) == NULL) || r; + r = ((glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dvARB")) == NULL) || r; + r = ((glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fARB")) == NULL) || r; + r = ((glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fvARB")) == NULL) || r; + r = ((glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1sARB")) == NULL) || r; + r = ((glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1svARB")) == NULL) || r; + r = ((glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dARB")) == NULL) || r; + r = ((glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dvARB")) == NULL) || r; + r = ((glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fARB")) == NULL) || r; + r = ((glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fvARB")) == NULL) || r; + r = ((glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2sARB")) == NULL) || r; + r = ((glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2svARB")) == NULL) || r; + r = ((glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dARB")) == NULL) || r; + r = ((glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dvARB")) == NULL) || r; + r = ((glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fARB")) == NULL) || r; + r = ((glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fvARB")) == NULL) || r; + r = ((glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3sARB")) == NULL) || r; + r = ((glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3svARB")) == NULL) || r; + r = ((glVertexAttrib4NbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NbvARB")) == NULL) || r; + r = ((glVertexAttrib4NivARB = (PFNGLVERTEXATTRIB4NIVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NivARB")) == NULL) || r; + r = ((glVertexAttrib4NsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NsvARB")) == NULL) || r; + r = ((glVertexAttrib4NubARB = (PFNGLVERTEXATTRIB4NUBARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NubARB")) == NULL) || r; + r = ((glVertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NubvARB")) == NULL) || r; + r = ((glVertexAttrib4NuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NuivARB")) == NULL) || r; + r = ((glVertexAttrib4NusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NusvARB")) == NULL) || r; + r = ((glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4bvARB")) == NULL) || r; + r = ((glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dARB")) == NULL) || r; + r = ((glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dvARB")) == NULL) || r; + r = ((glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fARB")) == NULL) || r; + r = ((glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fvARB")) == NULL) || r; + r = ((glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ivARB")) == NULL) || r; + r = ((glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4sARB")) == NULL) || r; + r = ((glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4svARB")) == NULL) || r; + r = ((glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubvARB")) == NULL) || r; + r = ((glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4uivARB")) == NULL) || r; + r = ((glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4usvARB")) == NULL) || r; + r = ((glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointerARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_vertex_program */ + +#ifdef GL_ARB_vertex_shader + +static GLboolean _glewInit_GL_ARB_vertex_shader (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC)glewGetProcAddress((const GLubyte*)"glBindAttribLocationARB")) == NULL) || r; + r = ((glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC)glewGetProcAddress((const GLubyte*)"glGetActiveAttribARB")) == NULL) || r; + r = ((glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC)glewGetProcAddress((const GLubyte*)"glGetAttribLocationARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_vertex_shader */ + +#ifdef GL_ARB_window_pos + +static GLboolean _glewInit_GL_ARB_window_pos (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glWindowPos2dARB = (PFNGLWINDOWPOS2DARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dARB")) == NULL) || r; + r = ((glWindowPos2dvARB = (PFNGLWINDOWPOS2DVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dvARB")) == NULL) || r; + r = ((glWindowPos2fARB = (PFNGLWINDOWPOS2FARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fARB")) == NULL) || r; + r = ((glWindowPos2fvARB = (PFNGLWINDOWPOS2FVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fvARB")) == NULL) || r; + r = ((glWindowPos2iARB = (PFNGLWINDOWPOS2IARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2iARB")) == NULL) || r; + r = ((glWindowPos2ivARB = (PFNGLWINDOWPOS2IVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2ivARB")) == NULL) || r; + r = ((glWindowPos2sARB = (PFNGLWINDOWPOS2SARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2sARB")) == NULL) || r; + r = ((glWindowPos2svARB = (PFNGLWINDOWPOS2SVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2svARB")) == NULL) || r; + r = ((glWindowPos3dARB = (PFNGLWINDOWPOS3DARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dARB")) == NULL) || r; + r = ((glWindowPos3dvARB = (PFNGLWINDOWPOS3DVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dvARB")) == NULL) || r; + r = ((glWindowPos3fARB = (PFNGLWINDOWPOS3FARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fARB")) == NULL) || r; + r = ((glWindowPos3fvARB = (PFNGLWINDOWPOS3FVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fvARB")) == NULL) || r; + r = ((glWindowPos3iARB = (PFNGLWINDOWPOS3IARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3iARB")) == NULL) || r; + r = ((glWindowPos3ivARB = (PFNGLWINDOWPOS3IVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3ivARB")) == NULL) || r; + r = ((glWindowPos3sARB = (PFNGLWINDOWPOS3SARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3sARB")) == NULL) || r; + r = ((glWindowPos3svARB = (PFNGLWINDOWPOS3SVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3svARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_window_pos */ + +#ifdef GL_ATIX_point_sprites + +#endif /* GL_ATIX_point_sprites */ + +#ifdef GL_ATIX_texture_env_combine3 + +#endif /* GL_ATIX_texture_env_combine3 */ + +#ifdef GL_ATIX_texture_env_route + +#endif /* GL_ATIX_texture_env_route */ + +#ifdef GL_ATIX_vertex_shader_output_point_size + +#endif /* GL_ATIX_vertex_shader_output_point_size */ + +#ifdef GL_ATI_draw_buffers + +static GLboolean _glewInit_GL_ATI_draw_buffers (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawBuffersATI = (PFNGLDRAWBUFFERSATIPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffersATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_draw_buffers */ + +#ifdef GL_ATI_element_array + +static GLboolean _glewInit_GL_ATI_element_array (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawElementArrayATI = (PFNGLDRAWELEMENTARRAYATIPROC)glewGetProcAddress((const GLubyte*)"glDrawElementArrayATI")) == NULL) || r; + r = ((glDrawRangeElementArrayATI = (PFNGLDRAWRANGEELEMENTARRAYATIPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElementArrayATI")) == NULL) || r; + r = ((glElementPointerATI = (PFNGLELEMENTPOINTERATIPROC)glewGetProcAddress((const GLubyte*)"glElementPointerATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_element_array */ + +#ifdef GL_ATI_envmap_bumpmap + +static GLboolean _glewInit_GL_ATI_envmap_bumpmap (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetTexBumpParameterfvATI = (PFNGLGETTEXBUMPPARAMETERFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetTexBumpParameterfvATI")) == NULL) || r; + r = ((glGetTexBumpParameterivATI = (PFNGLGETTEXBUMPPARAMETERIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetTexBumpParameterivATI")) == NULL) || r; + r = ((glTexBumpParameterfvATI = (PFNGLTEXBUMPPARAMETERFVATIPROC)glewGetProcAddress((const GLubyte*)"glTexBumpParameterfvATI")) == NULL) || r; + r = ((glTexBumpParameterivATI = (PFNGLTEXBUMPPARAMETERIVATIPROC)glewGetProcAddress((const GLubyte*)"glTexBumpParameterivATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_envmap_bumpmap */ + +#ifdef GL_ATI_fragment_shader + +static GLboolean _glewInit_GL_ATI_fragment_shader (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glAlphaFragmentOp1ATI = (PFNGLALPHAFRAGMENTOP1ATIPROC)glewGetProcAddress((const GLubyte*)"glAlphaFragmentOp1ATI")) == NULL) || r; + r = ((glAlphaFragmentOp2ATI = (PFNGLALPHAFRAGMENTOP2ATIPROC)glewGetProcAddress((const GLubyte*)"glAlphaFragmentOp2ATI")) == NULL) || r; + r = ((glAlphaFragmentOp3ATI = (PFNGLALPHAFRAGMENTOP3ATIPROC)glewGetProcAddress((const GLubyte*)"glAlphaFragmentOp3ATI")) == NULL) || r; + r = ((glBeginFragmentShaderATI = (PFNGLBEGINFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glBeginFragmentShaderATI")) == NULL) || r; + r = ((glBindFragmentShaderATI = (PFNGLBINDFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glBindFragmentShaderATI")) == NULL) || r; + r = ((glColorFragmentOp1ATI = (PFNGLCOLORFRAGMENTOP1ATIPROC)glewGetProcAddress((const GLubyte*)"glColorFragmentOp1ATI")) == NULL) || r; + r = ((glColorFragmentOp2ATI = (PFNGLCOLORFRAGMENTOP2ATIPROC)glewGetProcAddress((const GLubyte*)"glColorFragmentOp2ATI")) == NULL) || r; + r = ((glColorFragmentOp3ATI = (PFNGLCOLORFRAGMENTOP3ATIPROC)glewGetProcAddress((const GLubyte*)"glColorFragmentOp3ATI")) == NULL) || r; + r = ((glDeleteFragmentShaderATI = (PFNGLDELETEFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glDeleteFragmentShaderATI")) == NULL) || r; + r = ((glEndFragmentShaderATI = (PFNGLENDFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glEndFragmentShaderATI")) == NULL) || r; + r = ((glGenFragmentShadersATI = (PFNGLGENFRAGMENTSHADERSATIPROC)glewGetProcAddress((const GLubyte*)"glGenFragmentShadersATI")) == NULL) || r; + r = ((glPassTexCoordATI = (PFNGLPASSTEXCOORDATIPROC)glewGetProcAddress((const GLubyte*)"glPassTexCoordATI")) == NULL) || r; + r = ((glSampleMapATI = (PFNGLSAMPLEMAPATIPROC)glewGetProcAddress((const GLubyte*)"glSampleMapATI")) == NULL) || r; + r = ((glSetFragmentShaderConstantATI = (PFNGLSETFRAGMENTSHADERCONSTANTATIPROC)glewGetProcAddress((const GLubyte*)"glSetFragmentShaderConstantATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_fragment_shader */ + +#ifdef GL_ATI_map_object_buffer + +static GLboolean _glewInit_GL_ATI_map_object_buffer (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glMapObjectBufferATI = (PFNGLMAPOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glMapObjectBufferATI")) == NULL) || r; + r = ((glUnmapObjectBufferATI = (PFNGLUNMAPOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glUnmapObjectBufferATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_map_object_buffer */ + +#ifdef GL_ATI_pn_triangles + +static GLboolean _glewInit_GL_ATI_pn_triangles (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glPNTrianglesfATI = (PFNGLPNTRIANGLESFATIPROC)glewGetProcAddress((const GLubyte*)"glPNTrianglesfATI")) == NULL) || r; + r = ((glPNTrianglesiATI = (PFNGLPNTRIANGLESIATIPROC)glewGetProcAddress((const GLubyte*)"glPNTrianglesiATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_pn_triangles */ + +#ifdef GL_ATI_separate_stencil + +static GLboolean _glewInit_GL_ATI_separate_stencil (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glStencilFuncSeparateATI = (PFNGLSTENCILFUNCSEPARATEATIPROC)glewGetProcAddress((const GLubyte*)"glStencilFuncSeparateATI")) == NULL) || r; + r = ((glStencilOpSeparateATI = (PFNGLSTENCILOPSEPARATEATIPROC)glewGetProcAddress((const GLubyte*)"glStencilOpSeparateATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_separate_stencil */ + +#ifdef GL_ATI_shader_texture_lod + +#endif /* GL_ATI_shader_texture_lod */ + +#ifdef GL_ATI_text_fragment_shader + +#endif /* GL_ATI_text_fragment_shader */ + +#ifdef GL_ATI_texture_compression_3dc + +#endif /* GL_ATI_texture_compression_3dc */ + +#ifdef GL_ATI_texture_env_combine3 + +#endif /* GL_ATI_texture_env_combine3 */ + +#ifdef GL_ATI_texture_float + +#endif /* GL_ATI_texture_float */ + +#ifdef GL_ATI_texture_mirror_once + +#endif /* GL_ATI_texture_mirror_once */ + +#ifdef GL_ATI_vertex_array_object + +static GLboolean _glewInit_GL_ATI_vertex_array_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glArrayObjectATI = (PFNGLARRAYOBJECTATIPROC)glewGetProcAddress((const GLubyte*)"glArrayObjectATI")) == NULL) || r; + r = ((glFreeObjectBufferATI = (PFNGLFREEOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glFreeObjectBufferATI")) == NULL) || r; + r = ((glGetArrayObjectfvATI = (PFNGLGETARRAYOBJECTFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetArrayObjectfvATI")) == NULL) || r; + r = ((glGetArrayObjectivATI = (PFNGLGETARRAYOBJECTIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetArrayObjectivATI")) == NULL) || r; + r = ((glGetObjectBufferfvATI = (PFNGLGETOBJECTBUFFERFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetObjectBufferfvATI")) == NULL) || r; + r = ((glGetObjectBufferivATI = (PFNGLGETOBJECTBUFFERIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetObjectBufferivATI")) == NULL) || r; + r = ((glGetVariantArrayObjectfvATI = (PFNGLGETVARIANTARRAYOBJECTFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVariantArrayObjectfvATI")) == NULL) || r; + r = ((glGetVariantArrayObjectivATI = (PFNGLGETVARIANTARRAYOBJECTIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVariantArrayObjectivATI")) == NULL) || r; + r = ((glIsObjectBufferATI = (PFNGLISOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glIsObjectBufferATI")) == NULL) || r; + r = ((glNewObjectBufferATI = (PFNGLNEWOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glNewObjectBufferATI")) == NULL) || r; + r = ((glUpdateObjectBufferATI = (PFNGLUPDATEOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glUpdateObjectBufferATI")) == NULL) || r; + r = ((glVariantArrayObjectATI = (PFNGLVARIANTARRAYOBJECTATIPROC)glewGetProcAddress((const GLubyte*)"glVariantArrayObjectATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_vertex_array_object */ + +#ifdef GL_ATI_vertex_attrib_array_object + +static GLboolean _glewInit_GL_ATI_vertex_attrib_array_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetVertexAttribArrayObjectfvATI = (PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribArrayObjectfvATI")) == NULL) || r; + r = ((glGetVertexAttribArrayObjectivATI = (PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribArrayObjectivATI")) == NULL) || r; + r = ((glVertexAttribArrayObjectATI = (PFNGLVERTEXATTRIBARRAYOBJECTATIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribArrayObjectATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_vertex_attrib_array_object */ + +#ifdef GL_ATI_vertex_streams + +static GLboolean _glewInit_GL_ATI_vertex_streams (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glClientActiveVertexStreamATI = (PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC)glewGetProcAddress((const GLubyte*)"glClientActiveVertexStreamATI")) == NULL) || r; + r = ((glNormalStream3bATI = (PFNGLNORMALSTREAM3BATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3bATI")) == NULL) || r; + r = ((glNormalStream3bvATI = (PFNGLNORMALSTREAM3BVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3bvATI")) == NULL) || r; + r = ((glNormalStream3dATI = (PFNGLNORMALSTREAM3DATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3dATI")) == NULL) || r; + r = ((glNormalStream3dvATI = (PFNGLNORMALSTREAM3DVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3dvATI")) == NULL) || r; + r = ((glNormalStream3fATI = (PFNGLNORMALSTREAM3FATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3fATI")) == NULL) || r; + r = ((glNormalStream3fvATI = (PFNGLNORMALSTREAM3FVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3fvATI")) == NULL) || r; + r = ((glNormalStream3iATI = (PFNGLNORMALSTREAM3IATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3iATI")) == NULL) || r; + r = ((glNormalStream3ivATI = (PFNGLNORMALSTREAM3IVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3ivATI")) == NULL) || r; + r = ((glNormalStream3sATI = (PFNGLNORMALSTREAM3SATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3sATI")) == NULL) || r; + r = ((glNormalStream3svATI = (PFNGLNORMALSTREAM3SVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3svATI")) == NULL) || r; + r = ((glVertexBlendEnvfATI = (PFNGLVERTEXBLENDENVFATIPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendEnvfATI")) == NULL) || r; + r = ((glVertexBlendEnviATI = (PFNGLVERTEXBLENDENVIATIPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendEnviATI")) == NULL) || r; + r = ((glVertexStream2dATI = (PFNGLVERTEXSTREAM2DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2dATI")) == NULL) || r; + r = ((glVertexStream2dvATI = (PFNGLVERTEXSTREAM2DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2dvATI")) == NULL) || r; + r = ((glVertexStream2fATI = (PFNGLVERTEXSTREAM2FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2fATI")) == NULL) || r; + r = ((glVertexStream2fvATI = (PFNGLVERTEXSTREAM2FVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2fvATI")) == NULL) || r; + r = ((glVertexStream2iATI = (PFNGLVERTEXSTREAM2IATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2iATI")) == NULL) || r; + r = ((glVertexStream2ivATI = (PFNGLVERTEXSTREAM2IVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2ivATI")) == NULL) || r; + r = ((glVertexStream2sATI = (PFNGLVERTEXSTREAM2SATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2sATI")) == NULL) || r; + r = ((glVertexStream2svATI = (PFNGLVERTEXSTREAM2SVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2svATI")) == NULL) || r; + r = ((glVertexStream3dATI = (PFNGLVERTEXSTREAM3DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3dATI")) == NULL) || r; + r = ((glVertexStream3dvATI = (PFNGLVERTEXSTREAM3DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3dvATI")) == NULL) || r; + r = ((glVertexStream3fATI = (PFNGLVERTEXSTREAM3FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3fATI")) == NULL) || r; + r = ((glVertexStream3fvATI = (PFNGLVERTEXSTREAM3FVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3fvATI")) == NULL) || r; + r = ((glVertexStream3iATI = (PFNGLVERTEXSTREAM3IATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3iATI")) == NULL) || r; + r = ((glVertexStream3ivATI = (PFNGLVERTEXSTREAM3IVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3ivATI")) == NULL) || r; + r = ((glVertexStream3sATI = (PFNGLVERTEXSTREAM3SATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3sATI")) == NULL) || r; + r = ((glVertexStream3svATI = (PFNGLVERTEXSTREAM3SVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3svATI")) == NULL) || r; + r = ((glVertexStream4dATI = (PFNGLVERTEXSTREAM4DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4dATI")) == NULL) || r; + r = ((glVertexStream4dvATI = (PFNGLVERTEXSTREAM4DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4dvATI")) == NULL) || r; + r = ((glVertexStream4fATI = (PFNGLVERTEXSTREAM4FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4fATI")) == NULL) || r; + r = ((glVertexStream4fvATI = (PFNGLVERTEXSTREAM4FVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4fvATI")) == NULL) || r; + r = ((glVertexStream4iATI = (PFNGLVERTEXSTREAM4IATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4iATI")) == NULL) || r; + r = ((glVertexStream4ivATI = (PFNGLVERTEXSTREAM4IVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4ivATI")) == NULL) || r; + r = ((glVertexStream4sATI = (PFNGLVERTEXSTREAM4SATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4sATI")) == NULL) || r; + r = ((glVertexStream4svATI = (PFNGLVERTEXSTREAM4SVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4svATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_vertex_streams */ + +#ifdef GL_EXT_422_pixels + +#endif /* GL_EXT_422_pixels */ + +#ifdef GL_EXT_Cg_shader + +#endif /* GL_EXT_Cg_shader */ + +#ifdef GL_EXT_abgr + +#endif /* GL_EXT_abgr */ + +#ifdef GL_EXT_bgra + +#endif /* GL_EXT_bgra */ + +#ifdef GL_EXT_bindable_uniform + +static GLboolean _glewInit_GL_EXT_bindable_uniform (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetUniformBufferSizeEXT = (PFNGLGETUNIFORMBUFFERSIZEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetUniformBufferSizeEXT")) == NULL) || r; + r = ((glGetUniformOffsetEXT = (PFNGLGETUNIFORMOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glGetUniformOffsetEXT")) == NULL) || r; + r = ((glUniformBufferEXT = (PFNGLUNIFORMBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glUniformBufferEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_bindable_uniform */ + +#ifdef GL_EXT_blend_color + +static GLboolean _glewInit_GL_EXT_blend_color (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendColorEXT = (PFNGLBLENDCOLOREXTPROC)glewGetProcAddress((const GLubyte*)"glBlendColorEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_blend_color */ + +#ifdef GL_EXT_blend_equation_separate + +static GLboolean _glewInit_GL_EXT_blend_equation_separate (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendEquationSeparateEXT = (PFNGLBLENDEQUATIONSEPARATEEXTPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparateEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_blend_equation_separate */ + +#ifdef GL_EXT_blend_func_separate + +static GLboolean _glewInit_GL_EXT_blend_func_separate (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparateEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_blend_func_separate */ + +#ifdef GL_EXT_blend_logic_op + +#endif /* GL_EXT_blend_logic_op */ + +#ifdef GL_EXT_blend_minmax + +static GLboolean _glewInit_GL_EXT_blend_minmax (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendEquationEXT = (PFNGLBLENDEQUATIONEXTPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_blend_minmax */ + +#ifdef GL_EXT_blend_subtract + +#endif /* GL_EXT_blend_subtract */ + +#ifdef GL_EXT_clip_volume_hint + +#endif /* GL_EXT_clip_volume_hint */ + +#ifdef GL_EXT_cmyka + +#endif /* GL_EXT_cmyka */ + +#ifdef GL_EXT_color_subtable + +static GLboolean _glewInit_GL_EXT_color_subtable (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColorSubTableEXT = (PFNGLCOLORSUBTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glColorSubTableEXT")) == NULL) || r; + r = ((glCopyColorSubTableEXT = (PFNGLCOPYCOLORSUBTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyColorSubTableEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_color_subtable */ + +#ifdef GL_EXT_compiled_vertex_array + +static GLboolean _glewInit_GL_EXT_compiled_vertex_array (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glLockArraysEXT = (PFNGLLOCKARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glLockArraysEXT")) == NULL) || r; + r = ((glUnlockArraysEXT = (PFNGLUNLOCKARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glUnlockArraysEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_compiled_vertex_array */ + +#ifdef GL_EXT_convolution + +static GLboolean _glewInit_GL_EXT_convolution (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glConvolutionFilter1DEXT = (PFNGLCONVOLUTIONFILTER1DEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter1DEXT")) == NULL) || r; + r = ((glConvolutionFilter2DEXT = (PFNGLCONVOLUTIONFILTER2DEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter2DEXT")) == NULL) || r; + r = ((glConvolutionParameterfEXT = (PFNGLCONVOLUTIONPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterfEXT")) == NULL) || r; + r = ((glConvolutionParameterfvEXT = (PFNGLCONVOLUTIONPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterfvEXT")) == NULL) || r; + r = ((glConvolutionParameteriEXT = (PFNGLCONVOLUTIONPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameteriEXT")) == NULL) || r; + r = ((glConvolutionParameterivEXT = (PFNGLCONVOLUTIONPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterivEXT")) == NULL) || r; + r = ((glCopyConvolutionFilter1DEXT = (PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter1DEXT")) == NULL) || r; + r = ((glCopyConvolutionFilter2DEXT = (PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter2DEXT")) == NULL) || r; + r = ((glGetConvolutionFilterEXT = (PFNGLGETCONVOLUTIONFILTEREXTPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionFilterEXT")) == NULL) || r; + r = ((glGetConvolutionParameterfvEXT = (PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameterfvEXT")) == NULL) || r; + r = ((glGetConvolutionParameterivEXT = (PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameterivEXT")) == NULL) || r; + r = ((glGetSeparableFilterEXT = (PFNGLGETSEPARABLEFILTEREXTPROC)glewGetProcAddress((const GLubyte*)"glGetSeparableFilterEXT")) == NULL) || r; + r = ((glSeparableFilter2DEXT = (PFNGLSEPARABLEFILTER2DEXTPROC)glewGetProcAddress((const GLubyte*)"glSeparableFilter2DEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_convolution */ + +#ifdef GL_EXT_coordinate_frame + +static GLboolean _glewInit_GL_EXT_coordinate_frame (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBinormalPointerEXT = (PFNGLBINORMALPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glBinormalPointerEXT")) == NULL) || r; + r = ((glTangentPointerEXT = (PFNGLTANGENTPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glTangentPointerEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_coordinate_frame */ + +#ifdef GL_EXT_copy_texture + +static GLboolean _glewInit_GL_EXT_copy_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCopyTexImage1DEXT = (PFNGLCOPYTEXIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexImage1DEXT")) == NULL) || r; + r = ((glCopyTexImage2DEXT = (PFNGLCOPYTEXIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexImage2DEXT")) == NULL) || r; + r = ((glCopyTexSubImage1DEXT = (PFNGLCOPYTEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage1DEXT")) == NULL) || r; + r = ((glCopyTexSubImage2DEXT = (PFNGLCOPYTEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage2DEXT")) == NULL) || r; + r = ((glCopyTexSubImage3DEXT = (PFNGLCOPYTEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage3DEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_copy_texture */ + +#ifdef GL_EXT_cull_vertex + +static GLboolean _glewInit_GL_EXT_cull_vertex (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCullParameterdvEXT = (PFNGLCULLPARAMETERDVEXTPROC)glewGetProcAddress((const GLubyte*)"glCullParameterdvEXT")) == NULL) || r; + r = ((glCullParameterfvEXT = (PFNGLCULLPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glCullParameterfvEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_cull_vertex */ + +#ifdef GL_EXT_depth_bounds_test + +static GLboolean _glewInit_GL_EXT_depth_bounds_test (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDepthBoundsEXT = (PFNGLDEPTHBOUNDSEXTPROC)glewGetProcAddress((const GLubyte*)"glDepthBoundsEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_depth_bounds_test */ + +#ifdef GL_EXT_draw_buffers2 + +static GLboolean _glewInit_GL_EXT_draw_buffers2 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColorMaskIndexedEXT = (PFNGLCOLORMASKINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glColorMaskIndexedEXT")) == NULL) || r; + r = ((glDisableIndexedEXT = (PFNGLDISABLEINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableIndexedEXT")) == NULL) || r; + r = ((glEnableIndexedEXT = (PFNGLENABLEINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableIndexedEXT")) == NULL) || r; + r = ((glGetBooleanIndexedvEXT = (PFNGLGETBOOLEANINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetBooleanIndexedvEXT")) == NULL) || r; + r = ((glGetIntegerIndexedvEXT = (PFNGLGETINTEGERINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetIntegerIndexedvEXT")) == NULL) || r; + r = ((glIsEnabledIndexedEXT = (PFNGLISENABLEDINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glIsEnabledIndexedEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_draw_buffers2 */ + +#ifdef GL_EXT_draw_instanced + +static GLboolean _glewInit_GL_EXT_draw_instanced (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawArraysInstancedEXT = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysInstancedEXT")) == NULL) || r; + r = ((glDrawElementsInstancedEXT = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_draw_instanced */ + +#ifdef GL_EXT_draw_range_elements + +static GLboolean _glewInit_GL_EXT_draw_range_elements (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawRangeElementsEXT = (PFNGLDRAWRANGEELEMENTSEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElementsEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_draw_range_elements */ + +#ifdef GL_EXT_fog_coord + +static GLboolean _glewInit_GL_EXT_fog_coord (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFogCoordPointerEXT = (PFNGLFOGCOORDPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoordPointerEXT")) == NULL) || r; + r = ((glFogCoorddEXT = (PFNGLFOGCOORDDEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoorddEXT")) == NULL) || r; + r = ((glFogCoorddvEXT = (PFNGLFOGCOORDDVEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoorddvEXT")) == NULL) || r; + r = ((glFogCoordfEXT = (PFNGLFOGCOORDFEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoordfEXT")) == NULL) || r; + r = ((glFogCoordfvEXT = (PFNGLFOGCOORDFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoordfvEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_fog_coord */ + +#ifdef GL_EXT_fragment_lighting + +static GLboolean _glewInit_GL_EXT_fragment_lighting (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFragmentColorMaterialEXT = (PFNGLFRAGMENTCOLORMATERIALEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentColorMaterialEXT")) == NULL) || r; + r = ((glFragmentLightModelfEXT = (PFNGLFRAGMENTLIGHTMODELFEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfEXT")) == NULL) || r; + r = ((glFragmentLightModelfvEXT = (PFNGLFRAGMENTLIGHTMODELFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfvEXT")) == NULL) || r; + r = ((glFragmentLightModeliEXT = (PFNGLFRAGMENTLIGHTMODELIEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModeliEXT")) == NULL) || r; + r = ((glFragmentLightModelivEXT = (PFNGLFRAGMENTLIGHTMODELIVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelivEXT")) == NULL) || r; + r = ((glFragmentLightfEXT = (PFNGLFRAGMENTLIGHTFEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfEXT")) == NULL) || r; + r = ((glFragmentLightfvEXT = (PFNGLFRAGMENTLIGHTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfvEXT")) == NULL) || r; + r = ((glFragmentLightiEXT = (PFNGLFRAGMENTLIGHTIEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightiEXT")) == NULL) || r; + r = ((glFragmentLightivEXT = (PFNGLFRAGMENTLIGHTIVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightivEXT")) == NULL) || r; + r = ((glFragmentMaterialfEXT = (PFNGLFRAGMENTMATERIALFEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfEXT")) == NULL) || r; + r = ((glFragmentMaterialfvEXT = (PFNGLFRAGMENTMATERIALFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfvEXT")) == NULL) || r; + r = ((glFragmentMaterialiEXT = (PFNGLFRAGMENTMATERIALIEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialiEXT")) == NULL) || r; + r = ((glFragmentMaterialivEXT = (PFNGLFRAGMENTMATERIALIVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialivEXT")) == NULL) || r; + r = ((glGetFragmentLightfvEXT = (PFNGLGETFRAGMENTLIGHTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightfvEXT")) == NULL) || r; + r = ((glGetFragmentLightivEXT = (PFNGLGETFRAGMENTLIGHTIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightivEXT")) == NULL) || r; + r = ((glGetFragmentMaterialfvEXT = (PFNGLGETFRAGMENTMATERIALFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialfvEXT")) == NULL) || r; + r = ((glGetFragmentMaterialivEXT = (PFNGLGETFRAGMENTMATERIALIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialivEXT")) == NULL) || r; + r = ((glLightEnviEXT = (PFNGLLIGHTENVIEXTPROC)glewGetProcAddress((const GLubyte*)"glLightEnviEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_fragment_lighting */ + +#ifdef GL_EXT_framebuffer_blit + +static GLboolean _glewInit_GL_EXT_framebuffer_blit (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glBlitFramebufferEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_framebuffer_blit */ + +#ifdef GL_EXT_framebuffer_multisample + +static GLboolean _glewInit_GL_EXT_framebuffer_multisample (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisampleEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_framebuffer_multisample */ + +#ifdef GL_EXT_framebuffer_object + +static GLboolean _glewInit_GL_EXT_framebuffer_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindFramebufferEXT")) == NULL) || r; + r = ((glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindRenderbufferEXT")) == NULL) || r; + r = ((glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)glewGetProcAddress((const GLubyte*)"glCheckFramebufferStatusEXT")) == NULL) || r; + r = ((glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteFramebuffersEXT")) == NULL) || r; + r = ((glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteRenderbuffersEXT")) == NULL) || r; + r = ((glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferRenderbufferEXT")) == NULL) || r; + r = ((glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture1DEXT")) == NULL) || r; + r = ((glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture2DEXT")) == NULL) || r; + r = ((glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture3DEXT")) == NULL) || r; + r = ((glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenFramebuffersEXT")) == NULL) || r; + r = ((glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenRenderbuffersEXT")) == NULL) || r; + r = ((glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC)glewGetProcAddress((const GLubyte*)"glGenerateMipmapEXT")) == NULL) || r; + r = ((glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFramebufferAttachmentParameterivEXT")) == NULL) || r; + r = ((glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetRenderbufferParameterivEXT")) == NULL) || r; + r = ((glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glIsFramebufferEXT")) == NULL) || r; + r = ((glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glIsRenderbufferEXT")) == NULL) || r; + r = ((glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_framebuffer_object */ + +#ifdef GL_EXT_framebuffer_sRGB + +#endif /* GL_EXT_framebuffer_sRGB */ + +#ifdef GL_EXT_geometry_shader4 + +static GLboolean _glewInit_GL_EXT_geometry_shader4 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFramebufferTextureEXT = (PFNGLFRAMEBUFFERTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureEXT")) == NULL) || r; + r = ((glFramebufferTextureFaceEXT = (PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureFaceEXT")) == NULL) || r; + r = ((glFramebufferTextureLayerEXT = (PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureLayerEXT")) == NULL) || r; + r = ((glProgramParameteriEXT = (PFNGLPROGRAMPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramParameteriEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_geometry_shader4 */ + +#ifdef GL_EXT_gpu_program_parameters + +static GLboolean _glewInit_GL_EXT_gpu_program_parameters (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glProgramEnvParameters4fvEXT = (PFNGLPROGRAMENVPARAMETERS4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameters4fvEXT")) == NULL) || r; + r = ((glProgramLocalParameters4fvEXT = (PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameters4fvEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_gpu_program_parameters */ + +#ifdef GL_EXT_gpu_shader4 + +static GLboolean _glewInit_GL_EXT_gpu_shader4 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindFragDataLocationEXT = (PFNGLBINDFRAGDATALOCATIONEXTPROC)glewGetProcAddress((const GLubyte*)"glBindFragDataLocationEXT")) == NULL) || r; + r = ((glGetFragDataLocationEXT = (PFNGLGETFRAGDATALOCATIONEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragDataLocationEXT")) == NULL) || r; + r = ((glGetUniformuivEXT = (PFNGLGETUNIFORMUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetUniformuivEXT")) == NULL) || r; + r = ((glGetVertexAttribIivEXT = (PFNGLGETVERTEXATTRIBIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribIivEXT")) == NULL) || r; + r = ((glGetVertexAttribIuivEXT = (PFNGLGETVERTEXATTRIBIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribIuivEXT")) == NULL) || r; + r = ((glUniform1uiEXT = (PFNGLUNIFORM1UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform1uiEXT")) == NULL) || r; + r = ((glUniform1uivEXT = (PFNGLUNIFORM1UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform1uivEXT")) == NULL) || r; + r = ((glUniform2uiEXT = (PFNGLUNIFORM2UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform2uiEXT")) == NULL) || r; + r = ((glUniform2uivEXT = (PFNGLUNIFORM2UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform2uivEXT")) == NULL) || r; + r = ((glUniform3uiEXT = (PFNGLUNIFORM3UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform3uiEXT")) == NULL) || r; + r = ((glUniform3uivEXT = (PFNGLUNIFORM3UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform3uivEXT")) == NULL) || r; + r = ((glUniform4uiEXT = (PFNGLUNIFORM4UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform4uiEXT")) == NULL) || r; + r = ((glUniform4uivEXT = (PFNGLUNIFORM4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform4uivEXT")) == NULL) || r; + r = ((glVertexAttribI1iEXT = (PFNGLVERTEXATTRIBI1IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1iEXT")) == NULL) || r; + r = ((glVertexAttribI1ivEXT = (PFNGLVERTEXATTRIBI1IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1ivEXT")) == NULL) || r; + r = ((glVertexAttribI1uiEXT = (PFNGLVERTEXATTRIBI1UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1uiEXT")) == NULL) || r; + r = ((glVertexAttribI1uivEXT = (PFNGLVERTEXATTRIBI1UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1uivEXT")) == NULL) || r; + r = ((glVertexAttribI2iEXT = (PFNGLVERTEXATTRIBI2IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2iEXT")) == NULL) || r; + r = ((glVertexAttribI2ivEXT = (PFNGLVERTEXATTRIBI2IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2ivEXT")) == NULL) || r; + r = ((glVertexAttribI2uiEXT = (PFNGLVERTEXATTRIBI2UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2uiEXT")) == NULL) || r; + r = ((glVertexAttribI2uivEXT = (PFNGLVERTEXATTRIBI2UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2uivEXT")) == NULL) || r; + r = ((glVertexAttribI3iEXT = (PFNGLVERTEXATTRIBI3IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3iEXT")) == NULL) || r; + r = ((glVertexAttribI3ivEXT = (PFNGLVERTEXATTRIBI3IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3ivEXT")) == NULL) || r; + r = ((glVertexAttribI3uiEXT = (PFNGLVERTEXATTRIBI3UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3uiEXT")) == NULL) || r; + r = ((glVertexAttribI3uivEXT = (PFNGLVERTEXATTRIBI3UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3uivEXT")) == NULL) || r; + r = ((glVertexAttribI4bvEXT = (PFNGLVERTEXATTRIBI4BVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4bvEXT")) == NULL) || r; + r = ((glVertexAttribI4iEXT = (PFNGLVERTEXATTRIBI4IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4iEXT")) == NULL) || r; + r = ((glVertexAttribI4ivEXT = (PFNGLVERTEXATTRIBI4IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4ivEXT")) == NULL) || r; + r = ((glVertexAttribI4svEXT = (PFNGLVERTEXATTRIBI4SVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4svEXT")) == NULL) || r; + r = ((glVertexAttribI4ubvEXT = (PFNGLVERTEXATTRIBI4UBVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4ubvEXT")) == NULL) || r; + r = ((glVertexAttribI4uiEXT = (PFNGLVERTEXATTRIBI4UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4uiEXT")) == NULL) || r; + r = ((glVertexAttribI4uivEXT = (PFNGLVERTEXATTRIBI4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4uivEXT")) == NULL) || r; + r = ((glVertexAttribI4usvEXT = (PFNGLVERTEXATTRIBI4USVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4usvEXT")) == NULL) || r; + r = ((glVertexAttribIPointerEXT = (PFNGLVERTEXATTRIBIPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribIPointerEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_gpu_shader4 */ + +#ifdef GL_EXT_histogram + +static GLboolean _glewInit_GL_EXT_histogram (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetHistogramEXT = (PFNGLGETHISTOGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramEXT")) == NULL) || r; + r = ((glGetHistogramParameterfvEXT = (PFNGLGETHISTOGRAMPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameterfvEXT")) == NULL) || r; + r = ((glGetHistogramParameterivEXT = (PFNGLGETHISTOGRAMPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameterivEXT")) == NULL) || r; + r = ((glGetMinmaxEXT = (PFNGLGETMINMAXEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxEXT")) == NULL) || r; + r = ((glGetMinmaxParameterfvEXT = (PFNGLGETMINMAXPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameterfvEXT")) == NULL) || r; + r = ((glGetMinmaxParameterivEXT = (PFNGLGETMINMAXPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameterivEXT")) == NULL) || r; + r = ((glHistogramEXT = (PFNGLHISTOGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glHistogramEXT")) == NULL) || r; + r = ((glMinmaxEXT = (PFNGLMINMAXEXTPROC)glewGetProcAddress((const GLubyte*)"glMinmaxEXT")) == NULL) || r; + r = ((glResetHistogramEXT = (PFNGLRESETHISTOGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glResetHistogramEXT")) == NULL) || r; + r = ((glResetMinmaxEXT = (PFNGLRESETMINMAXEXTPROC)glewGetProcAddress((const GLubyte*)"glResetMinmaxEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_histogram */ + +#ifdef GL_EXT_index_array_formats + +#endif /* GL_EXT_index_array_formats */ + +#ifdef GL_EXT_index_func + +static GLboolean _glewInit_GL_EXT_index_func (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glIndexFuncEXT = (PFNGLINDEXFUNCEXTPROC)glewGetProcAddress((const GLubyte*)"glIndexFuncEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_index_func */ + +#ifdef GL_EXT_index_material + +static GLboolean _glewInit_GL_EXT_index_material (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glIndexMaterialEXT = (PFNGLINDEXMATERIALEXTPROC)glewGetProcAddress((const GLubyte*)"glIndexMaterialEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_index_material */ + +#ifdef GL_EXT_index_texture + +#endif /* GL_EXT_index_texture */ + +#ifdef GL_EXT_light_texture + +static GLboolean _glewInit_GL_EXT_light_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glApplyTextureEXT = (PFNGLAPPLYTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glApplyTextureEXT")) == NULL) || r; + r = ((glTextureLightEXT = (PFNGLTEXTURELIGHTEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureLightEXT")) == NULL) || r; + r = ((glTextureMaterialEXT = (PFNGLTEXTUREMATERIALEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureMaterialEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_light_texture */ + +#ifdef GL_EXT_misc_attribute + +#endif /* GL_EXT_misc_attribute */ + +#ifdef GL_EXT_multi_draw_arrays + +static GLboolean _glewInit_GL_EXT_multi_draw_arrays (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glMultiDrawArraysEXT = (PFNGLMULTIDRAWARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArraysEXT")) == NULL) || r; + r = ((glMultiDrawElementsEXT = (PFNGLMULTIDRAWELEMENTSEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_multi_draw_arrays */ + +#ifdef GL_EXT_multisample + +static GLboolean _glewInit_GL_EXT_multisample (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glSampleMaskEXT = (PFNGLSAMPLEMASKEXTPROC)glewGetProcAddress((const GLubyte*)"glSampleMaskEXT")) == NULL) || r; + r = ((glSamplePatternEXT = (PFNGLSAMPLEPATTERNEXTPROC)glewGetProcAddress((const GLubyte*)"glSamplePatternEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_multisample */ + +#ifdef GL_EXT_packed_depth_stencil + +#endif /* GL_EXT_packed_depth_stencil */ + +#ifdef GL_EXT_packed_float + +#endif /* GL_EXT_packed_float */ + +#ifdef GL_EXT_packed_pixels + +#endif /* GL_EXT_packed_pixels */ + +#ifdef GL_EXT_paletted_texture + +static GLboolean _glewInit_GL_EXT_paletted_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColorTableEXT = (PFNGLCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glColorTableEXT")) == NULL) || r; + r = ((glGetColorTableEXT = (PFNGLGETCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableEXT")) == NULL) || r; + r = ((glGetColorTableParameterfvEXT = (PFNGLGETCOLORTABLEPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterfvEXT")) == NULL) || r; + r = ((glGetColorTableParameterivEXT = (PFNGLGETCOLORTABLEPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterivEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_paletted_texture */ + +#ifdef GL_EXT_pixel_buffer_object + +#endif /* GL_EXT_pixel_buffer_object */ + +#ifdef GL_EXT_pixel_transform + +static GLboolean _glewInit_GL_EXT_pixel_transform (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetPixelTransformParameterfvEXT = (PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetPixelTransformParameterfvEXT")) == NULL) || r; + r = ((glGetPixelTransformParameterivEXT = (PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetPixelTransformParameterivEXT")) == NULL) || r; + r = ((glPixelTransformParameterfEXT = (PFNGLPIXELTRANSFORMPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameterfEXT")) == NULL) || r; + r = ((glPixelTransformParameterfvEXT = (PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameterfvEXT")) == NULL) || r; + r = ((glPixelTransformParameteriEXT = (PFNGLPIXELTRANSFORMPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameteriEXT")) == NULL) || r; + r = ((glPixelTransformParameterivEXT = (PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameterivEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_pixel_transform */ + +#ifdef GL_EXT_pixel_transform_color_table + +#endif /* GL_EXT_pixel_transform_color_table */ + +#ifdef GL_EXT_point_parameters + +static GLboolean _glewInit_GL_EXT_point_parameters (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glPointParameterfEXT = (PFNGLPOINTPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfEXT")) == NULL) || r; + r = ((glPointParameterfvEXT = (PFNGLPOINTPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfvEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_point_parameters */ + +#ifdef GL_EXT_polygon_offset + +static GLboolean _glewInit_GL_EXT_polygon_offset (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glPolygonOffsetEXT = (PFNGLPOLYGONOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glPolygonOffsetEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_polygon_offset */ + +#ifdef GL_EXT_rescale_normal + +#endif /* GL_EXT_rescale_normal */ + +#ifdef GL_EXT_scene_marker + +static GLboolean _glewInit_GL_EXT_scene_marker (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginSceneEXT = (PFNGLBEGINSCENEEXTPROC)glewGetProcAddress((const GLubyte*)"glBeginSceneEXT")) == NULL) || r; + r = ((glEndSceneEXT = (PFNGLENDSCENEEXTPROC)glewGetProcAddress((const GLubyte*)"glEndSceneEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_scene_marker */ + +#ifdef GL_EXT_secondary_color + +static GLboolean _glewInit_GL_EXT_secondary_color (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glSecondaryColor3bEXT = (PFNGLSECONDARYCOLOR3BEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3bEXT")) == NULL) || r; + r = ((glSecondaryColor3bvEXT = (PFNGLSECONDARYCOLOR3BVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3bvEXT")) == NULL) || r; + r = ((glSecondaryColor3dEXT = (PFNGLSECONDARYCOLOR3DEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3dEXT")) == NULL) || r; + r = ((glSecondaryColor3dvEXT = (PFNGLSECONDARYCOLOR3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3dvEXT")) == NULL) || r; + r = ((glSecondaryColor3fEXT = (PFNGLSECONDARYCOLOR3FEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3fEXT")) == NULL) || r; + r = ((glSecondaryColor3fvEXT = (PFNGLSECONDARYCOLOR3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3fvEXT")) == NULL) || r; + r = ((glSecondaryColor3iEXT = (PFNGLSECONDARYCOLOR3IEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3iEXT")) == NULL) || r; + r = ((glSecondaryColor3ivEXT = (PFNGLSECONDARYCOLOR3IVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ivEXT")) == NULL) || r; + r = ((glSecondaryColor3sEXT = (PFNGLSECONDARYCOLOR3SEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3sEXT")) == NULL) || r; + r = ((glSecondaryColor3svEXT = (PFNGLSECONDARYCOLOR3SVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3svEXT")) == NULL) || r; + r = ((glSecondaryColor3ubEXT = (PFNGLSECONDARYCOLOR3UBEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ubEXT")) == NULL) || r; + r = ((glSecondaryColor3ubvEXT = (PFNGLSECONDARYCOLOR3UBVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ubvEXT")) == NULL) || r; + r = ((glSecondaryColor3uiEXT = (PFNGLSECONDARYCOLOR3UIEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3uiEXT")) == NULL) || r; + r = ((glSecondaryColor3uivEXT = (PFNGLSECONDARYCOLOR3UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3uivEXT")) == NULL) || r; + r = ((glSecondaryColor3usEXT = (PFNGLSECONDARYCOLOR3USEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3usEXT")) == NULL) || r; + r = ((glSecondaryColor3usvEXT = (PFNGLSECONDARYCOLOR3USVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3usvEXT")) == NULL) || r; + r = ((glSecondaryColorPointerEXT = (PFNGLSECONDARYCOLORPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorPointerEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_secondary_color */ + +#ifdef GL_EXT_separate_specular_color + +#endif /* GL_EXT_separate_specular_color */ + +#ifdef GL_EXT_shadow_funcs + +#endif /* GL_EXT_shadow_funcs */ + +#ifdef GL_EXT_shared_texture_palette + +#endif /* GL_EXT_shared_texture_palette */ + +#ifdef GL_EXT_stencil_clear_tag + +#endif /* GL_EXT_stencil_clear_tag */ + +#ifdef GL_EXT_stencil_two_side + +static GLboolean _glewInit_GL_EXT_stencil_two_side (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glActiveStencilFaceEXT = (PFNGLACTIVESTENCILFACEEXTPROC)glewGetProcAddress((const GLubyte*)"glActiveStencilFaceEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_stencil_two_side */ + +#ifdef GL_EXT_stencil_wrap + +#endif /* GL_EXT_stencil_wrap */ + +#ifdef GL_EXT_subtexture + +static GLboolean _glewInit_GL_EXT_subtexture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexSubImage1DEXT = (PFNGLTEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage1DEXT")) == NULL) || r; + r = ((glTexSubImage2DEXT = (PFNGLTEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage2DEXT")) == NULL) || r; + r = ((glTexSubImage3DEXT = (PFNGLTEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage3DEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_subtexture */ + +#ifdef GL_EXT_texture + +#endif /* GL_EXT_texture */ + +#ifdef GL_EXT_texture3D + +static GLboolean _glewInit_GL_EXT_texture3D (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexImage3DEXT = (PFNGLTEXIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexImage3DEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_texture3D */ + +#ifdef GL_EXT_texture_array + +#endif /* GL_EXT_texture_array */ + +#ifdef GL_EXT_texture_buffer_object + +static GLboolean _glewInit_GL_EXT_texture_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexBufferEXT = (PFNGLTEXBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glTexBufferEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_texture_buffer_object */ + +#ifdef GL_EXT_texture_compression_dxt1 + +#endif /* GL_EXT_texture_compression_dxt1 */ + +#ifdef GL_EXT_texture_compression_latc + +#endif /* GL_EXT_texture_compression_latc */ + +#ifdef GL_EXT_texture_compression_rgtc + +#endif /* GL_EXT_texture_compression_rgtc */ + +#ifdef GL_EXT_texture_compression_s3tc + +#endif /* GL_EXT_texture_compression_s3tc */ + +#ifdef GL_EXT_texture_cube_map + +#endif /* GL_EXT_texture_cube_map */ + +#ifdef GL_EXT_texture_edge_clamp + +#endif /* GL_EXT_texture_edge_clamp */ + +#ifdef GL_EXT_texture_env + +#endif /* GL_EXT_texture_env */ + +#ifdef GL_EXT_texture_env_add + +#endif /* GL_EXT_texture_env_add */ + +#ifdef GL_EXT_texture_env_combine + +#endif /* GL_EXT_texture_env_combine */ + +#ifdef GL_EXT_texture_env_dot3 + +#endif /* GL_EXT_texture_env_dot3 */ + +#ifdef GL_EXT_texture_filter_anisotropic + +#endif /* GL_EXT_texture_filter_anisotropic */ + +#ifdef GL_EXT_texture_integer + +static GLboolean _glewInit_GL_EXT_texture_integer (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glClearColorIiEXT = (PFNGLCLEARCOLORIIEXTPROC)glewGetProcAddress((const GLubyte*)"glClearColorIiEXT")) == NULL) || r; + r = ((glClearColorIuiEXT = (PFNGLCLEARCOLORIUIEXTPROC)glewGetProcAddress((const GLubyte*)"glClearColorIuiEXT")) == NULL) || r; + r = ((glGetTexParameterIivEXT = (PFNGLGETTEXPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterIivEXT")) == NULL) || r; + r = ((glGetTexParameterIuivEXT = (PFNGLGETTEXPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterIuivEXT")) == NULL) || r; + r = ((glTexParameterIivEXT = (PFNGLTEXPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTexParameterIivEXT")) == NULL) || r; + r = ((glTexParameterIuivEXT = (PFNGLTEXPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTexParameterIuivEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_texture_integer */ + +#ifdef GL_EXT_texture_lod_bias + +#endif /* GL_EXT_texture_lod_bias */ + +#ifdef GL_EXT_texture_mirror_clamp + +#endif /* GL_EXT_texture_mirror_clamp */ + +#ifdef GL_EXT_texture_object + +static GLboolean _glewInit_GL_EXT_texture_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glAreTexturesResidentEXT = (PFNGLARETEXTURESRESIDENTEXTPROC)glewGetProcAddress((const GLubyte*)"glAreTexturesResidentEXT")) == NULL) || r; + r = ((glBindTextureEXT = (PFNGLBINDTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glBindTextureEXT")) == NULL) || r; + r = ((glDeleteTexturesEXT = (PFNGLDELETETEXTURESEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteTexturesEXT")) == NULL) || r; + r = ((glGenTexturesEXT = (PFNGLGENTEXTURESEXTPROC)glewGetProcAddress((const GLubyte*)"glGenTexturesEXT")) == NULL) || r; + r = ((glIsTextureEXT = (PFNGLISTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glIsTextureEXT")) == NULL) || r; + r = ((glPrioritizeTexturesEXT = (PFNGLPRIORITIZETEXTURESEXTPROC)glewGetProcAddress((const GLubyte*)"glPrioritizeTexturesEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_texture_object */ + +#ifdef GL_EXT_texture_perturb_normal + +static GLboolean _glewInit_GL_EXT_texture_perturb_normal (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTextureNormalEXT = (PFNGLTEXTURENORMALEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureNormalEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_texture_perturb_normal */ + +#ifdef GL_EXT_texture_rectangle + +#endif /* GL_EXT_texture_rectangle */ + +#ifdef GL_EXT_texture_sRGB + +#endif /* GL_EXT_texture_sRGB */ + +#ifdef GL_EXT_texture_shared_exponent + +#endif /* GL_EXT_texture_shared_exponent */ + +#ifdef GL_EXT_timer_query + +static GLboolean _glewInit_GL_EXT_timer_query (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetQueryObjecti64vEXT = (PFNGLGETQUERYOBJECTI64VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjecti64vEXT")) == NULL) || r; + r = ((glGetQueryObjectui64vEXT = (PFNGLGETQUERYOBJECTUI64VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectui64vEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_timer_query */ + +#ifdef GL_EXT_vertex_array + +static GLboolean _glewInit_GL_EXT_vertex_array (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glArrayElementEXT = (PFNGLARRAYELEMENTEXTPROC)glewGetProcAddress((const GLubyte*)"glArrayElementEXT")) == NULL) || r; + r = ((glColorPointerEXT = (PFNGLCOLORPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glColorPointerEXT")) == NULL) || r; + r = ((glDrawArraysEXT = (PFNGLDRAWARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysEXT")) == NULL) || r; + r = ((glEdgeFlagPointerEXT = (PFNGLEDGEFLAGPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glEdgeFlagPointerEXT")) == NULL) || r; + r = ((glGetPointervEXT = (PFNGLGETPOINTERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetPointervEXT")) == NULL) || r; + r = ((glIndexPointerEXT = (PFNGLINDEXPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glIndexPointerEXT")) == NULL) || r; + r = ((glNormalPointerEXT = (PFNGLNORMALPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glNormalPointerEXT")) == NULL) || r; + r = ((glTexCoordPointerEXT = (PFNGLTEXCOORDPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glTexCoordPointerEXT")) == NULL) || r; + r = ((glVertexPointerEXT = (PFNGLVERTEXPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexPointerEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_vertex_array */ + +#ifdef GL_EXT_vertex_shader + +static GLboolean _glewInit_GL_EXT_vertex_shader (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginVertexShaderEXT = (PFNGLBEGINVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glBeginVertexShaderEXT")) == NULL) || r; + r = ((glBindLightParameterEXT = (PFNGLBINDLIGHTPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindLightParameterEXT")) == NULL) || r; + r = ((glBindMaterialParameterEXT = (PFNGLBINDMATERIALPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindMaterialParameterEXT")) == NULL) || r; + r = ((glBindParameterEXT = (PFNGLBINDPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindParameterEXT")) == NULL) || r; + r = ((glBindTexGenParameterEXT = (PFNGLBINDTEXGENPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindTexGenParameterEXT")) == NULL) || r; + r = ((glBindTextureUnitParameterEXT = (PFNGLBINDTEXTUREUNITPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindTextureUnitParameterEXT")) == NULL) || r; + r = ((glBindVertexShaderEXT = (PFNGLBINDVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindVertexShaderEXT")) == NULL) || r; + r = ((glDeleteVertexShaderEXT = (PFNGLDELETEVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteVertexShaderEXT")) == NULL) || r; + r = ((glDisableVariantClientStateEXT = (PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableVariantClientStateEXT")) == NULL) || r; + r = ((glEnableVariantClientStateEXT = (PFNGLENABLEVARIANTCLIENTSTATEEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableVariantClientStateEXT")) == NULL) || r; + r = ((glEndVertexShaderEXT = (PFNGLENDVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glEndVertexShaderEXT")) == NULL) || r; + r = ((glExtractComponentEXT = (PFNGLEXTRACTCOMPONENTEXTPROC)glewGetProcAddress((const GLubyte*)"glExtractComponentEXT")) == NULL) || r; + r = ((glGenSymbolsEXT = (PFNGLGENSYMBOLSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenSymbolsEXT")) == NULL) || r; + r = ((glGenVertexShadersEXT = (PFNGLGENVERTEXSHADERSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenVertexShadersEXT")) == NULL) || r; + r = ((glGetInvariantBooleanvEXT = (PFNGLGETINVARIANTBOOLEANVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetInvariantBooleanvEXT")) == NULL) || r; + r = ((glGetInvariantFloatvEXT = (PFNGLGETINVARIANTFLOATVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetInvariantFloatvEXT")) == NULL) || r; + r = ((glGetInvariantIntegervEXT = (PFNGLGETINVARIANTINTEGERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetInvariantIntegervEXT")) == NULL) || r; + r = ((glGetLocalConstantBooleanvEXT = (PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetLocalConstantBooleanvEXT")) == NULL) || r; + r = ((glGetLocalConstantFloatvEXT = (PFNGLGETLOCALCONSTANTFLOATVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetLocalConstantFloatvEXT")) == NULL) || r; + r = ((glGetLocalConstantIntegervEXT = (PFNGLGETLOCALCONSTANTINTEGERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetLocalConstantIntegervEXT")) == NULL) || r; + r = ((glGetVariantBooleanvEXT = (PFNGLGETVARIANTBOOLEANVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantBooleanvEXT")) == NULL) || r; + r = ((glGetVariantFloatvEXT = (PFNGLGETVARIANTFLOATVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantFloatvEXT")) == NULL) || r; + r = ((glGetVariantIntegervEXT = (PFNGLGETVARIANTINTEGERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantIntegervEXT")) == NULL) || r; + r = ((glGetVariantPointervEXT = (PFNGLGETVARIANTPOINTERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantPointervEXT")) == NULL) || r; + r = ((glInsertComponentEXT = (PFNGLINSERTCOMPONENTEXTPROC)glewGetProcAddress((const GLubyte*)"glInsertComponentEXT")) == NULL) || r; + r = ((glIsVariantEnabledEXT = (PFNGLISVARIANTENABLEDEXTPROC)glewGetProcAddress((const GLubyte*)"glIsVariantEnabledEXT")) == NULL) || r; + r = ((glSetInvariantEXT = (PFNGLSETINVARIANTEXTPROC)glewGetProcAddress((const GLubyte*)"glSetInvariantEXT")) == NULL) || r; + r = ((glSetLocalConstantEXT = (PFNGLSETLOCALCONSTANTEXTPROC)glewGetProcAddress((const GLubyte*)"glSetLocalConstantEXT")) == NULL) || r; + r = ((glShaderOp1EXT = (PFNGLSHADEROP1EXTPROC)glewGetProcAddress((const GLubyte*)"glShaderOp1EXT")) == NULL) || r; + r = ((glShaderOp2EXT = (PFNGLSHADEROP2EXTPROC)glewGetProcAddress((const GLubyte*)"glShaderOp2EXT")) == NULL) || r; + r = ((glShaderOp3EXT = (PFNGLSHADEROP3EXTPROC)glewGetProcAddress((const GLubyte*)"glShaderOp3EXT")) == NULL) || r; + r = ((glSwizzleEXT = (PFNGLSWIZZLEEXTPROC)glewGetProcAddress((const GLubyte*)"glSwizzleEXT")) == NULL) || r; + r = ((glVariantPointerEXT = (PFNGLVARIANTPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVariantPointerEXT")) == NULL) || r; + r = ((glVariantbvEXT = (PFNGLVARIANTBVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantbvEXT")) == NULL) || r; + r = ((glVariantdvEXT = (PFNGLVARIANTDVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantdvEXT")) == NULL) || r; + r = ((glVariantfvEXT = (PFNGLVARIANTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantfvEXT")) == NULL) || r; + r = ((glVariantivEXT = (PFNGLVARIANTIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantivEXT")) == NULL) || r; + r = ((glVariantsvEXT = (PFNGLVARIANTSVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantsvEXT")) == NULL) || r; + r = ((glVariantubvEXT = (PFNGLVARIANTUBVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantubvEXT")) == NULL) || r; + r = ((glVariantuivEXT = (PFNGLVARIANTUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantuivEXT")) == NULL) || r; + r = ((glVariantusvEXT = (PFNGLVARIANTUSVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantusvEXT")) == NULL) || r; + r = ((glWriteMaskEXT = (PFNGLWRITEMASKEXTPROC)glewGetProcAddress((const GLubyte*)"glWriteMaskEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_vertex_shader */ + +#ifdef GL_EXT_vertex_weighting + +static GLboolean _glewInit_GL_EXT_vertex_weighting (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glVertexWeightPointerEXT = (PFNGLVERTEXWEIGHTPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexWeightPointerEXT")) == NULL) || r; + r = ((glVertexWeightfEXT = (PFNGLVERTEXWEIGHTFEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexWeightfEXT")) == NULL) || r; + r = ((glVertexWeightfvEXT = (PFNGLVERTEXWEIGHTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexWeightfvEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_vertex_weighting */ + +#ifdef GL_GREMEDY_frame_terminator + +static GLboolean _glewInit_GL_GREMEDY_frame_terminator (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFrameTerminatorGREMEDY = (PFNGLFRAMETERMINATORGREMEDYPROC)glewGetProcAddress((const GLubyte*)"glFrameTerminatorGREMEDY")) == NULL) || r; + + return r; +} + +#endif /* GL_GREMEDY_frame_terminator */ + +#ifdef GL_GREMEDY_string_marker + +static GLboolean _glewInit_GL_GREMEDY_string_marker (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glStringMarkerGREMEDY = (PFNGLSTRINGMARKERGREMEDYPROC)glewGetProcAddress((const GLubyte*)"glStringMarkerGREMEDY")) == NULL) || r; + + return r; +} + +#endif /* GL_GREMEDY_string_marker */ + +#ifdef GL_HP_convolution_border_modes + +#endif /* GL_HP_convolution_border_modes */ + +#ifdef GL_HP_image_transform + +static GLboolean _glewInit_GL_HP_image_transform (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetImageTransformParameterfvHP = (PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC)glewGetProcAddress((const GLubyte*)"glGetImageTransformParameterfvHP")) == NULL) || r; + r = ((glGetImageTransformParameterivHP = (PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC)glewGetProcAddress((const GLubyte*)"glGetImageTransformParameterivHP")) == NULL) || r; + r = ((glImageTransformParameterfHP = (PFNGLIMAGETRANSFORMPARAMETERFHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameterfHP")) == NULL) || r; + r = ((glImageTransformParameterfvHP = (PFNGLIMAGETRANSFORMPARAMETERFVHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameterfvHP")) == NULL) || r; + r = ((glImageTransformParameteriHP = (PFNGLIMAGETRANSFORMPARAMETERIHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameteriHP")) == NULL) || r; + r = ((glImageTransformParameterivHP = (PFNGLIMAGETRANSFORMPARAMETERIVHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameterivHP")) == NULL) || r; + + return r; +} + +#endif /* GL_HP_image_transform */ + +#ifdef GL_HP_occlusion_test + +#endif /* GL_HP_occlusion_test */ + +#ifdef GL_HP_texture_lighting + +#endif /* GL_HP_texture_lighting */ + +#ifdef GL_IBM_cull_vertex + +#endif /* GL_IBM_cull_vertex */ + +#ifdef GL_IBM_multimode_draw_arrays + +static GLboolean _glewInit_GL_IBM_multimode_draw_arrays (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glMultiModeDrawArraysIBM = (PFNGLMULTIMODEDRAWARRAYSIBMPROC)glewGetProcAddress((const GLubyte*)"glMultiModeDrawArraysIBM")) == NULL) || r; + r = ((glMultiModeDrawElementsIBM = (PFNGLMULTIMODEDRAWELEMENTSIBMPROC)glewGetProcAddress((const GLubyte*)"glMultiModeDrawElementsIBM")) == NULL) || r; + + return r; +} + +#endif /* GL_IBM_multimode_draw_arrays */ + +#ifdef GL_IBM_rasterpos_clip + +#endif /* GL_IBM_rasterpos_clip */ + +#ifdef GL_IBM_static_data + +#endif /* GL_IBM_static_data */ + +#ifdef GL_IBM_texture_mirrored_repeat + +#endif /* GL_IBM_texture_mirrored_repeat */ + +#ifdef GL_IBM_vertex_array_lists + +static GLboolean _glewInit_GL_IBM_vertex_array_lists (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColorPointerListIBM = (PFNGLCOLORPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glColorPointerListIBM")) == NULL) || r; + r = ((glEdgeFlagPointerListIBM = (PFNGLEDGEFLAGPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glEdgeFlagPointerListIBM")) == NULL) || r; + r = ((glFogCoordPointerListIBM = (PFNGLFOGCOORDPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glFogCoordPointerListIBM")) == NULL) || r; + r = ((glIndexPointerListIBM = (PFNGLINDEXPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glIndexPointerListIBM")) == NULL) || r; + r = ((glNormalPointerListIBM = (PFNGLNORMALPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glNormalPointerListIBM")) == NULL) || r; + r = ((glSecondaryColorPointerListIBM = (PFNGLSECONDARYCOLORPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorPointerListIBM")) == NULL) || r; + r = ((glTexCoordPointerListIBM = (PFNGLTEXCOORDPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glTexCoordPointerListIBM")) == NULL) || r; + r = ((glVertexPointerListIBM = (PFNGLVERTEXPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glVertexPointerListIBM")) == NULL) || r; + + return r; +} + +#endif /* GL_IBM_vertex_array_lists */ + +#ifdef GL_INGR_color_clamp + +#endif /* GL_INGR_color_clamp */ + +#ifdef GL_INGR_interlace_read + +#endif /* GL_INGR_interlace_read */ + +#ifdef GL_INTEL_parallel_arrays + +static GLboolean _glewInit_GL_INTEL_parallel_arrays (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColorPointervINTEL = (PFNGLCOLORPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glColorPointervINTEL")) == NULL) || r; + r = ((glNormalPointervINTEL = (PFNGLNORMALPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glNormalPointervINTEL")) == NULL) || r; + r = ((glTexCoordPointervINTEL = (PFNGLTEXCOORDPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glTexCoordPointervINTEL")) == NULL) || r; + r = ((glVertexPointervINTEL = (PFNGLVERTEXPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glVertexPointervINTEL")) == NULL) || r; + + return r; +} + +#endif /* GL_INTEL_parallel_arrays */ + +#ifdef GL_INTEL_texture_scissor + +static GLboolean _glewInit_GL_INTEL_texture_scissor (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexScissorFuncINTEL = (PFNGLTEXSCISSORFUNCINTELPROC)glewGetProcAddress((const GLubyte*)"glTexScissorFuncINTEL")) == NULL) || r; + r = ((glTexScissorINTEL = (PFNGLTEXSCISSORINTELPROC)glewGetProcAddress((const GLubyte*)"glTexScissorINTEL")) == NULL) || r; + + return r; +} + +#endif /* GL_INTEL_texture_scissor */ + +#ifdef GL_KTX_buffer_region + +static GLboolean _glewInit_GL_KTX_buffer_region (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBufferRegionEnabledEXT = (PFNGLBUFFERREGIONENABLEDEXTPROC)glewGetProcAddress((const GLubyte*)"glBufferRegionEnabledEXT")) == NULL) || r; + r = ((glDeleteBufferRegionEXT = (PFNGLDELETEBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteBufferRegionEXT")) == NULL) || r; + r = ((glDrawBufferRegionEXT = (PFNGLDRAWBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawBufferRegionEXT")) == NULL) || r; + r = ((glNewBufferRegionEXT = (PFNGLNEWBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glNewBufferRegionEXT")) == NULL) || r; + r = ((glReadBufferRegionEXT = (PFNGLREADBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glReadBufferRegionEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_KTX_buffer_region */ + +#ifdef GL_MESAX_texture_stack + +#endif /* GL_MESAX_texture_stack */ + +#ifdef GL_MESA_pack_invert + +#endif /* GL_MESA_pack_invert */ + +#ifdef GL_MESA_resize_buffers + +static GLboolean _glewInit_GL_MESA_resize_buffers (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glResizeBuffersMESA = (PFNGLRESIZEBUFFERSMESAPROC)glewGetProcAddress((const GLubyte*)"glResizeBuffersMESA")) == NULL) || r; + + return r; +} + +#endif /* GL_MESA_resize_buffers */ + +#ifdef GL_MESA_window_pos + +static GLboolean _glewInit_GL_MESA_window_pos (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glWindowPos2dMESA = (PFNGLWINDOWPOS2DMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dMESA")) == NULL) || r; + r = ((glWindowPos2dvMESA = (PFNGLWINDOWPOS2DVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dvMESA")) == NULL) || r; + r = ((glWindowPos2fMESA = (PFNGLWINDOWPOS2FMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fMESA")) == NULL) || r; + r = ((glWindowPos2fvMESA = (PFNGLWINDOWPOS2FVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fvMESA")) == NULL) || r; + r = ((glWindowPos2iMESA = (PFNGLWINDOWPOS2IMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2iMESA")) == NULL) || r; + r = ((glWindowPos2ivMESA = (PFNGLWINDOWPOS2IVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2ivMESA")) == NULL) || r; + r = ((glWindowPos2sMESA = (PFNGLWINDOWPOS2SMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2sMESA")) == NULL) || r; + r = ((glWindowPos2svMESA = (PFNGLWINDOWPOS2SVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2svMESA")) == NULL) || r; + r = ((glWindowPos3dMESA = (PFNGLWINDOWPOS3DMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dMESA")) == NULL) || r; + r = ((glWindowPos3dvMESA = (PFNGLWINDOWPOS3DVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dvMESA")) == NULL) || r; + r = ((glWindowPos3fMESA = (PFNGLWINDOWPOS3FMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fMESA")) == NULL) || r; + r = ((glWindowPos3fvMESA = (PFNGLWINDOWPOS3FVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fvMESA")) == NULL) || r; + r = ((glWindowPos3iMESA = (PFNGLWINDOWPOS3IMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3iMESA")) == NULL) || r; + r = ((glWindowPos3ivMESA = (PFNGLWINDOWPOS3IVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3ivMESA")) == NULL) || r; + r = ((glWindowPos3sMESA = (PFNGLWINDOWPOS3SMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3sMESA")) == NULL) || r; + r = ((glWindowPos3svMESA = (PFNGLWINDOWPOS3SVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3svMESA")) == NULL) || r; + r = ((glWindowPos4dMESA = (PFNGLWINDOWPOS4DMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4dMESA")) == NULL) || r; + r = ((glWindowPos4dvMESA = (PFNGLWINDOWPOS4DVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4dvMESA")) == NULL) || r; + r = ((glWindowPos4fMESA = (PFNGLWINDOWPOS4FMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4fMESA")) == NULL) || r; + r = ((glWindowPos4fvMESA = (PFNGLWINDOWPOS4FVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4fvMESA")) == NULL) || r; + r = ((glWindowPos4iMESA = (PFNGLWINDOWPOS4IMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4iMESA")) == NULL) || r; + r = ((glWindowPos4ivMESA = (PFNGLWINDOWPOS4IVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4ivMESA")) == NULL) || r; + r = ((glWindowPos4sMESA = (PFNGLWINDOWPOS4SMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4sMESA")) == NULL) || r; + r = ((glWindowPos4svMESA = (PFNGLWINDOWPOS4SVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4svMESA")) == NULL) || r; + + return r; +} + +#endif /* GL_MESA_window_pos */ + +#ifdef GL_MESA_ycbcr_texture + +#endif /* GL_MESA_ycbcr_texture */ + +#ifdef GL_NV_blend_square + +#endif /* GL_NV_blend_square */ + +#ifdef GL_NV_copy_depth_to_color + +#endif /* GL_NV_copy_depth_to_color */ + +#ifdef GL_NV_depth_buffer_float + +static GLboolean _glewInit_GL_NV_depth_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glClearDepthdNV = (PFNGLCLEARDEPTHDNVPROC)glewGetProcAddress((const GLubyte*)"glClearDepthdNV")) == NULL) || r; + r = ((glDepthBoundsdNV = (PFNGLDEPTHBOUNDSDNVPROC)glewGetProcAddress((const GLubyte*)"glDepthBoundsdNV")) == NULL) || r; + r = ((glDepthRangedNV = (PFNGLDEPTHRANGEDNVPROC)glewGetProcAddress((const GLubyte*)"glDepthRangedNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_depth_buffer_float */ + +#ifdef GL_NV_depth_clamp + +#endif /* GL_NV_depth_clamp */ + +#ifdef GL_NV_depth_range_unclamped + +#endif /* GL_NV_depth_range_unclamped */ + +#ifdef GL_NV_evaluators + +static GLboolean _glewInit_GL_NV_evaluators (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glEvalMapsNV = (PFNGLEVALMAPSNVPROC)glewGetProcAddress((const GLubyte*)"glEvalMapsNV")) == NULL) || r; + r = ((glGetMapAttribParameterfvNV = (PFNGLGETMAPATTRIBPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapAttribParameterfvNV")) == NULL) || r; + r = ((glGetMapAttribParameterivNV = (PFNGLGETMAPATTRIBPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapAttribParameterivNV")) == NULL) || r; + r = ((glGetMapControlPointsNV = (PFNGLGETMAPCONTROLPOINTSNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapControlPointsNV")) == NULL) || r; + r = ((glGetMapParameterfvNV = (PFNGLGETMAPPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapParameterfvNV")) == NULL) || r; + r = ((glGetMapParameterivNV = (PFNGLGETMAPPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapParameterivNV")) == NULL) || r; + r = ((glMapControlPointsNV = (PFNGLMAPCONTROLPOINTSNVPROC)glewGetProcAddress((const GLubyte*)"glMapControlPointsNV")) == NULL) || r; + r = ((glMapParameterfvNV = (PFNGLMAPPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glMapParameterfvNV")) == NULL) || r; + r = ((glMapParameterivNV = (PFNGLMAPPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glMapParameterivNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_evaluators */ + +#ifdef GL_NV_fence + +static GLboolean _glewInit_GL_NV_fence (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDeleteFencesNV = (PFNGLDELETEFENCESNVPROC)glewGetProcAddress((const GLubyte*)"glDeleteFencesNV")) == NULL) || r; + r = ((glFinishFenceNV = (PFNGLFINISHFENCENVPROC)glewGetProcAddress((const GLubyte*)"glFinishFenceNV")) == NULL) || r; + r = ((glGenFencesNV = (PFNGLGENFENCESNVPROC)glewGetProcAddress((const GLubyte*)"glGenFencesNV")) == NULL) || r; + r = ((glGetFenceivNV = (PFNGLGETFENCEIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetFenceivNV")) == NULL) || r; + r = ((glIsFenceNV = (PFNGLISFENCENVPROC)glewGetProcAddress((const GLubyte*)"glIsFenceNV")) == NULL) || r; + r = ((glSetFenceNV = (PFNGLSETFENCENVPROC)glewGetProcAddress((const GLubyte*)"glSetFenceNV")) == NULL) || r; + r = ((glTestFenceNV = (PFNGLTESTFENCENVPROC)glewGetProcAddress((const GLubyte*)"glTestFenceNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_fence */ + +#ifdef GL_NV_float_buffer + +#endif /* GL_NV_float_buffer */ + +#ifdef GL_NV_fog_distance + +#endif /* GL_NV_fog_distance */ + +#ifdef GL_NV_fragment_program + +static GLboolean _glewInit_GL_NV_fragment_program (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetProgramNamedParameterdvNV = (PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramNamedParameterdvNV")) == NULL) || r; + r = ((glGetProgramNamedParameterfvNV = (PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramNamedParameterfvNV")) == NULL) || r; + r = ((glProgramNamedParameter4dNV = (PFNGLPROGRAMNAMEDPARAMETER4DNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4dNV")) == NULL) || r; + r = ((glProgramNamedParameter4dvNV = (PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4dvNV")) == NULL) || r; + r = ((glProgramNamedParameter4fNV = (PFNGLPROGRAMNAMEDPARAMETER4FNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4fNV")) == NULL) || r; + r = ((glProgramNamedParameter4fvNV = (PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4fvNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_fragment_program */ + +#ifdef GL_NV_fragment_program2 + +#endif /* GL_NV_fragment_program2 */ + +#ifdef GL_NV_fragment_program4 + +#endif /* GL_NV_fragment_program4 */ + +#ifdef GL_NV_fragment_program_option + +#endif /* GL_NV_fragment_program_option */ + +#ifdef GL_NV_framebuffer_multisample_coverage + +static GLboolean _glewInit_GL_NV_framebuffer_multisample_coverage (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glRenderbufferStorageMultisampleCoverageNV = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisampleCoverageNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_framebuffer_multisample_coverage */ + +#ifdef GL_NV_geometry_program4 + +static GLboolean _glewInit_GL_NV_geometry_program4 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glProgramVertexLimitNV = (PFNGLPROGRAMVERTEXLIMITNVPROC)glewGetProcAddress((const GLubyte*)"glProgramVertexLimitNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_geometry_program4 */ + +#ifdef GL_NV_geometry_shader4 + +#endif /* GL_NV_geometry_shader4 */ + +#ifdef GL_NV_gpu_program4 + +static GLboolean _glewInit_GL_NV_gpu_program4 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glProgramEnvParameterI4iNV = (PFNGLPROGRAMENVPARAMETERI4INVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4iNV")) == NULL) || r; + r = ((glProgramEnvParameterI4ivNV = (PFNGLPROGRAMENVPARAMETERI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4ivNV")) == NULL) || r; + r = ((glProgramEnvParameterI4uiNV = (PFNGLPROGRAMENVPARAMETERI4UINVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4uiNV")) == NULL) || r; + r = ((glProgramEnvParameterI4uivNV = (PFNGLPROGRAMENVPARAMETERI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4uivNV")) == NULL) || r; + r = ((glProgramEnvParametersI4ivNV = (PFNGLPROGRAMENVPARAMETERSI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParametersI4ivNV")) == NULL) || r; + r = ((glProgramEnvParametersI4uivNV = (PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParametersI4uivNV")) == NULL) || r; + r = ((glProgramLocalParameterI4iNV = (PFNGLPROGRAMLOCALPARAMETERI4INVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4iNV")) == NULL) || r; + r = ((glProgramLocalParameterI4ivNV = (PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4ivNV")) == NULL) || r; + r = ((glProgramLocalParameterI4uiNV = (PFNGLPROGRAMLOCALPARAMETERI4UINVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4uiNV")) == NULL) || r; + r = ((glProgramLocalParameterI4uivNV = (PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4uivNV")) == NULL) || r; + r = ((glProgramLocalParametersI4ivNV = (PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParametersI4ivNV")) == NULL) || r; + r = ((glProgramLocalParametersI4uivNV = (PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParametersI4uivNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_gpu_program4 */ + +#ifdef GL_NV_half_float + +static GLboolean _glewInit_GL_NV_half_float (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColor3hNV = (PFNGLCOLOR3HNVPROC)glewGetProcAddress((const GLubyte*)"glColor3hNV")) == NULL) || r; + r = ((glColor3hvNV = (PFNGLCOLOR3HVNVPROC)glewGetProcAddress((const GLubyte*)"glColor3hvNV")) == NULL) || r; + r = ((glColor4hNV = (PFNGLCOLOR4HNVPROC)glewGetProcAddress((const GLubyte*)"glColor4hNV")) == NULL) || r; + r = ((glColor4hvNV = (PFNGLCOLOR4HVNVPROC)glewGetProcAddress((const GLubyte*)"glColor4hvNV")) == NULL) || r; + r = ((glFogCoordhNV = (PFNGLFOGCOORDHNVPROC)glewGetProcAddress((const GLubyte*)"glFogCoordhNV")) == NULL) || r; + r = ((glFogCoordhvNV = (PFNGLFOGCOORDHVNVPROC)glewGetProcAddress((const GLubyte*)"glFogCoordhvNV")) == NULL) || r; + r = ((glMultiTexCoord1hNV = (PFNGLMULTITEXCOORD1HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1hNV")) == NULL) || r; + r = ((glMultiTexCoord1hvNV = (PFNGLMULTITEXCOORD1HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1hvNV")) == NULL) || r; + r = ((glMultiTexCoord2hNV = (PFNGLMULTITEXCOORD2HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2hNV")) == NULL) || r; + r = ((glMultiTexCoord2hvNV = (PFNGLMULTITEXCOORD2HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2hvNV")) == NULL) || r; + r = ((glMultiTexCoord3hNV = (PFNGLMULTITEXCOORD3HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3hNV")) == NULL) || r; + r = ((glMultiTexCoord3hvNV = (PFNGLMULTITEXCOORD3HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3hvNV")) == NULL) || r; + r = ((glMultiTexCoord4hNV = (PFNGLMULTITEXCOORD4HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4hNV")) == NULL) || r; + r = ((glMultiTexCoord4hvNV = (PFNGLMULTITEXCOORD4HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4hvNV")) == NULL) || r; + r = ((glNormal3hNV = (PFNGLNORMAL3HNVPROC)glewGetProcAddress((const GLubyte*)"glNormal3hNV")) == NULL) || r; + r = ((glNormal3hvNV = (PFNGLNORMAL3HVNVPROC)glewGetProcAddress((const GLubyte*)"glNormal3hvNV")) == NULL) || r; + r = ((glSecondaryColor3hNV = (PFNGLSECONDARYCOLOR3HNVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3hNV")) == NULL) || r; + r = ((glSecondaryColor3hvNV = (PFNGLSECONDARYCOLOR3HVNVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3hvNV")) == NULL) || r; + r = ((glTexCoord1hNV = (PFNGLTEXCOORD1HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1hNV")) == NULL) || r; + r = ((glTexCoord1hvNV = (PFNGLTEXCOORD1HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1hvNV")) == NULL) || r; + r = ((glTexCoord2hNV = (PFNGLTEXCOORD2HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2hNV")) == NULL) || r; + r = ((glTexCoord2hvNV = (PFNGLTEXCOORD2HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2hvNV")) == NULL) || r; + r = ((glTexCoord3hNV = (PFNGLTEXCOORD3HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3hNV")) == NULL) || r; + r = ((glTexCoord3hvNV = (PFNGLTEXCOORD3HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3hvNV")) == NULL) || r; + r = ((glTexCoord4hNV = (PFNGLTEXCOORD4HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4hNV")) == NULL) || r; + r = ((glTexCoord4hvNV = (PFNGLTEXCOORD4HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4hvNV")) == NULL) || r; + r = ((glVertex2hNV = (PFNGLVERTEX2HNVPROC)glewGetProcAddress((const GLubyte*)"glVertex2hNV")) == NULL) || r; + r = ((glVertex2hvNV = (PFNGLVERTEX2HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertex2hvNV")) == NULL) || r; + r = ((glVertex3hNV = (PFNGLVERTEX3HNVPROC)glewGetProcAddress((const GLubyte*)"glVertex3hNV")) == NULL) || r; + r = ((glVertex3hvNV = (PFNGLVERTEX3HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertex3hvNV")) == NULL) || r; + r = ((glVertex4hNV = (PFNGLVERTEX4HNVPROC)glewGetProcAddress((const GLubyte*)"glVertex4hNV")) == NULL) || r; + r = ((glVertex4hvNV = (PFNGLVERTEX4HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertex4hvNV")) == NULL) || r; + r = ((glVertexAttrib1hNV = (PFNGLVERTEXATTRIB1HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1hNV")) == NULL) || r; + r = ((glVertexAttrib1hvNV = (PFNGLVERTEXATTRIB1HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1hvNV")) == NULL) || r; + r = ((glVertexAttrib2hNV = (PFNGLVERTEXATTRIB2HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2hNV")) == NULL) || r; + r = ((glVertexAttrib2hvNV = (PFNGLVERTEXATTRIB2HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2hvNV")) == NULL) || r; + r = ((glVertexAttrib3hNV = (PFNGLVERTEXATTRIB3HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3hNV")) == NULL) || r; + r = ((glVertexAttrib3hvNV = (PFNGLVERTEXATTRIB3HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3hvNV")) == NULL) || r; + r = ((glVertexAttrib4hNV = (PFNGLVERTEXATTRIB4HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4hNV")) == NULL) || r; + r = ((glVertexAttrib4hvNV = (PFNGLVERTEXATTRIB4HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4hvNV")) == NULL) || r; + r = ((glVertexAttribs1hvNV = (PFNGLVERTEXATTRIBS1HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1hvNV")) == NULL) || r; + r = ((glVertexAttribs2hvNV = (PFNGLVERTEXATTRIBS2HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2hvNV")) == NULL) || r; + r = ((glVertexAttribs3hvNV = (PFNGLVERTEXATTRIBS3HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3hvNV")) == NULL) || r; + r = ((glVertexAttribs4hvNV = (PFNGLVERTEXATTRIBS4HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4hvNV")) == NULL) || r; + r = ((glVertexWeighthNV = (PFNGLVERTEXWEIGHTHNVPROC)glewGetProcAddress((const GLubyte*)"glVertexWeighthNV")) == NULL) || r; + r = ((glVertexWeighthvNV = (PFNGLVERTEXWEIGHTHVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexWeighthvNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_half_float */ + +#ifdef GL_NV_light_max_exponent + +#endif /* GL_NV_light_max_exponent */ + +#ifdef GL_NV_multisample_filter_hint + +#endif /* GL_NV_multisample_filter_hint */ + +#ifdef GL_NV_occlusion_query + +static GLboolean _glewInit_GL_NV_occlusion_query (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginOcclusionQueryNV = (PFNGLBEGINOCCLUSIONQUERYNVPROC)glewGetProcAddress((const GLubyte*)"glBeginOcclusionQueryNV")) == NULL) || r; + r = ((glDeleteOcclusionQueriesNV = (PFNGLDELETEOCCLUSIONQUERIESNVPROC)glewGetProcAddress((const GLubyte*)"glDeleteOcclusionQueriesNV")) == NULL) || r; + r = ((glEndOcclusionQueryNV = (PFNGLENDOCCLUSIONQUERYNVPROC)glewGetProcAddress((const GLubyte*)"glEndOcclusionQueryNV")) == NULL) || r; + r = ((glGenOcclusionQueriesNV = (PFNGLGENOCCLUSIONQUERIESNVPROC)glewGetProcAddress((const GLubyte*)"glGenOcclusionQueriesNV")) == NULL) || r; + r = ((glGetOcclusionQueryivNV = (PFNGLGETOCCLUSIONQUERYIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetOcclusionQueryivNV")) == NULL) || r; + r = ((glGetOcclusionQueryuivNV = (PFNGLGETOCCLUSIONQUERYUIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetOcclusionQueryuivNV")) == NULL) || r; + r = ((glIsOcclusionQueryNV = (PFNGLISOCCLUSIONQUERYNVPROC)glewGetProcAddress((const GLubyte*)"glIsOcclusionQueryNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_occlusion_query */ + +#ifdef GL_NV_packed_depth_stencil + +#endif /* GL_NV_packed_depth_stencil */ + +#ifdef GL_NV_parameter_buffer_object + +static GLboolean _glewInit_GL_NV_parameter_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glProgramBufferParametersIivNV = (PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramBufferParametersIivNV")) == NULL) || r; + r = ((glProgramBufferParametersIuivNV = (PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramBufferParametersIuivNV")) == NULL) || r; + r = ((glProgramBufferParametersfvNV = (PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramBufferParametersfvNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_parameter_buffer_object */ + +#ifdef GL_NV_pixel_data_range + +static GLboolean _glewInit_GL_NV_pixel_data_range (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFlushPixelDataRangeNV = (PFNGLFLUSHPIXELDATARANGENVPROC)glewGetProcAddress((const GLubyte*)"glFlushPixelDataRangeNV")) == NULL) || r; + r = ((glPixelDataRangeNV = (PFNGLPIXELDATARANGENVPROC)glewGetProcAddress((const GLubyte*)"glPixelDataRangeNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_pixel_data_range */ + +#ifdef GL_NV_point_sprite + +static GLboolean _glewInit_GL_NV_point_sprite (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glPointParameteriNV = (PFNGLPOINTPARAMETERINVPROC)glewGetProcAddress((const GLubyte*)"glPointParameteriNV")) == NULL) || r; + r = ((glPointParameterivNV = (PFNGLPOINTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glPointParameterivNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_point_sprite */ + +#ifdef GL_NV_primitive_restart + +static GLboolean _glewInit_GL_NV_primitive_restart (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glPrimitiveRestartIndexNV = (PFNGLPRIMITIVERESTARTINDEXNVPROC)glewGetProcAddress((const GLubyte*)"glPrimitiveRestartIndexNV")) == NULL) || r; + r = ((glPrimitiveRestartNV = (PFNGLPRIMITIVERESTARTNVPROC)glewGetProcAddress((const GLubyte*)"glPrimitiveRestartNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_primitive_restart */ + +#ifdef GL_NV_register_combiners + +static GLboolean _glewInit_GL_NV_register_combiners (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCombinerInputNV = (PFNGLCOMBINERINPUTNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerInputNV")) == NULL) || r; + r = ((glCombinerOutputNV = (PFNGLCOMBINEROUTPUTNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerOutputNV")) == NULL) || r; + r = ((glCombinerParameterfNV = (PFNGLCOMBINERPARAMETERFNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameterfNV")) == NULL) || r; + r = ((glCombinerParameterfvNV = (PFNGLCOMBINERPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameterfvNV")) == NULL) || r; + r = ((glCombinerParameteriNV = (PFNGLCOMBINERPARAMETERINVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameteriNV")) == NULL) || r; + r = ((glCombinerParameterivNV = (PFNGLCOMBINERPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameterivNV")) == NULL) || r; + r = ((glFinalCombinerInputNV = (PFNGLFINALCOMBINERINPUTNVPROC)glewGetProcAddress((const GLubyte*)"glFinalCombinerInputNV")) == NULL) || r; + r = ((glGetCombinerInputParameterfvNV = (PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerInputParameterfvNV")) == NULL) || r; + r = ((glGetCombinerInputParameterivNV = (PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerInputParameterivNV")) == NULL) || r; + r = ((glGetCombinerOutputParameterfvNV = (PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerOutputParameterfvNV")) == NULL) || r; + r = ((glGetCombinerOutputParameterivNV = (PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerOutputParameterivNV")) == NULL) || r; + r = ((glGetFinalCombinerInputParameterfvNV = (PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetFinalCombinerInputParameterfvNV")) == NULL) || r; + r = ((glGetFinalCombinerInputParameterivNV = (PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetFinalCombinerInputParameterivNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_register_combiners */ + +#ifdef GL_NV_register_combiners2 + +static GLboolean _glewInit_GL_NV_register_combiners2 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCombinerStageParameterfvNV = (PFNGLCOMBINERSTAGEPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerStageParameterfvNV")) == NULL) || r; + r = ((glGetCombinerStageParameterfvNV = (PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerStageParameterfvNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_register_combiners2 */ + +#ifdef GL_NV_texgen_emboss + +#endif /* GL_NV_texgen_emboss */ + +#ifdef GL_NV_texgen_reflection + +#endif /* GL_NV_texgen_reflection */ + +#ifdef GL_NV_texture_compression_vtc + +#endif /* GL_NV_texture_compression_vtc */ + +#ifdef GL_NV_texture_env_combine4 + +#endif /* GL_NV_texture_env_combine4 */ + +#ifdef GL_NV_texture_expand_normal + +#endif /* GL_NV_texture_expand_normal */ + +#ifdef GL_NV_texture_rectangle + +#endif /* GL_NV_texture_rectangle */ + +#ifdef GL_NV_texture_shader + +#endif /* GL_NV_texture_shader */ + +#ifdef GL_NV_texture_shader2 + +#endif /* GL_NV_texture_shader2 */ + +#ifdef GL_NV_texture_shader3 + +#endif /* GL_NV_texture_shader3 */ + +#ifdef GL_NV_transform_feedback + +static GLboolean _glewInit_GL_NV_transform_feedback (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glActiveVaryingNV = (PFNGLACTIVEVARYINGNVPROC)glewGetProcAddress((const GLubyte*)"glActiveVaryingNV")) == NULL) || r; + r = ((glBeginTransformFeedbackNV = (PFNGLBEGINTRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glBeginTransformFeedbackNV")) == NULL) || r; + r = ((glBindBufferBaseNV = (PFNGLBINDBUFFERBASENVPROC)glewGetProcAddress((const GLubyte*)"glBindBufferBaseNV")) == NULL) || r; + r = ((glBindBufferOffsetNV = (PFNGLBINDBUFFEROFFSETNVPROC)glewGetProcAddress((const GLubyte*)"glBindBufferOffsetNV")) == NULL) || r; + r = ((glBindBufferRangeNV = (PFNGLBINDBUFFERRANGENVPROC)glewGetProcAddress((const GLubyte*)"glBindBufferRangeNV")) == NULL) || r; + r = ((glEndTransformFeedbackNV = (PFNGLENDTRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glEndTransformFeedbackNV")) == NULL) || r; + r = ((glGetActiveVaryingNV = (PFNGLGETACTIVEVARYINGNVPROC)glewGetProcAddress((const GLubyte*)"glGetActiveVaryingNV")) == NULL) || r; + r = ((glGetTransformFeedbackVaryingNV = (PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC)glewGetProcAddress((const GLubyte*)"glGetTransformFeedbackVaryingNV")) == NULL) || r; + r = ((glGetVaryingLocationNV = (PFNGLGETVARYINGLOCATIONNVPROC)glewGetProcAddress((const GLubyte*)"glGetVaryingLocationNV")) == NULL) || r; + r = ((glTransformFeedbackAttribsNV = (PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC)glewGetProcAddress((const GLubyte*)"glTransformFeedbackAttribsNV")) == NULL) || r; + r = ((glTransformFeedbackVaryingsNV = (PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC)glewGetProcAddress((const GLubyte*)"glTransformFeedbackVaryingsNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_transform_feedback */ + +#ifdef GL_NV_vertex_array_range + +static GLboolean _glewInit_GL_NV_vertex_array_range (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFlushVertexArrayRangeNV = (PFNGLFLUSHVERTEXARRAYRANGENVPROC)glewGetProcAddress((const GLubyte*)"glFlushVertexArrayRangeNV")) == NULL) || r; + r = ((glVertexArrayRangeNV = (PFNGLVERTEXARRAYRANGENVPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayRangeNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_vertex_array_range */ + +#ifdef GL_NV_vertex_array_range2 + +#endif /* GL_NV_vertex_array_range2 */ + +#ifdef GL_NV_vertex_program + +static GLboolean _glewInit_GL_NV_vertex_program (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glAreProgramsResidentNV = (PFNGLAREPROGRAMSRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glAreProgramsResidentNV")) == NULL) || r; + r = ((glBindProgramNV = (PFNGLBINDPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glBindProgramNV")) == NULL) || r; + r = ((glDeleteProgramsNV = (PFNGLDELETEPROGRAMSNVPROC)glewGetProcAddress((const GLubyte*)"glDeleteProgramsNV")) == NULL) || r; + r = ((glExecuteProgramNV = (PFNGLEXECUTEPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glExecuteProgramNV")) == NULL) || r; + r = ((glGenProgramsNV = (PFNGLGENPROGRAMSNVPROC)glewGetProcAddress((const GLubyte*)"glGenProgramsNV")) == NULL) || r; + r = ((glGetProgramParameterdvNV = (PFNGLGETPROGRAMPARAMETERDVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramParameterdvNV")) == NULL) || r; + r = ((glGetProgramParameterfvNV = (PFNGLGETPROGRAMPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramParameterfvNV")) == NULL) || r; + r = ((glGetProgramStringNV = (PFNGLGETPROGRAMSTRINGNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramStringNV")) == NULL) || r; + r = ((glGetProgramivNV = (PFNGLGETPROGRAMIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramivNV")) == NULL) || r; + r = ((glGetTrackMatrixivNV = (PFNGLGETTRACKMATRIXIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetTrackMatrixivNV")) == NULL) || r; + r = ((glGetVertexAttribPointervNV = (PFNGLGETVERTEXATTRIBPOINTERVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribPointervNV")) == NULL) || r; + r = ((glGetVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribdvNV")) == NULL) || r; + r = ((glGetVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribfvNV")) == NULL) || r; + r = ((glGetVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribivNV")) == NULL) || r; + r = ((glIsProgramNV = (PFNGLISPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glIsProgramNV")) == NULL) || r; + r = ((glLoadProgramNV = (PFNGLLOADPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glLoadProgramNV")) == NULL) || r; + r = ((glProgramParameter4dNV = (PFNGLPROGRAMPARAMETER4DNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4dNV")) == NULL) || r; + r = ((glProgramParameter4dvNV = (PFNGLPROGRAMPARAMETER4DVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4dvNV")) == NULL) || r; + r = ((glProgramParameter4fNV = (PFNGLPROGRAMPARAMETER4FNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4fNV")) == NULL) || r; + r = ((glProgramParameter4fvNV = (PFNGLPROGRAMPARAMETER4FVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4fvNV")) == NULL) || r; + r = ((glProgramParameters4dvNV = (PFNGLPROGRAMPARAMETERS4DVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameters4dvNV")) == NULL) || r; + r = ((glProgramParameters4fvNV = (PFNGLPROGRAMPARAMETERS4FVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameters4fvNV")) == NULL) || r; + r = ((glRequestResidentProgramsNV = (PFNGLREQUESTRESIDENTPROGRAMSNVPROC)glewGetProcAddress((const GLubyte*)"glRequestResidentProgramsNV")) == NULL) || r; + r = ((glTrackMatrixNV = (PFNGLTRACKMATRIXNVPROC)glewGetProcAddress((const GLubyte*)"glTrackMatrixNV")) == NULL) || r; + r = ((glVertexAttrib1dNV = (PFNGLVERTEXATTRIB1DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dNV")) == NULL) || r; + r = ((glVertexAttrib1dvNV = (PFNGLVERTEXATTRIB1DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dvNV")) == NULL) || r; + r = ((glVertexAttrib1fNV = (PFNGLVERTEXATTRIB1FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fNV")) == NULL) || r; + r = ((glVertexAttrib1fvNV = (PFNGLVERTEXATTRIB1FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fvNV")) == NULL) || r; + r = ((glVertexAttrib1sNV = (PFNGLVERTEXATTRIB1SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1sNV")) == NULL) || r; + r = ((glVertexAttrib1svNV = (PFNGLVERTEXATTRIB1SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1svNV")) == NULL) || r; + r = ((glVertexAttrib2dNV = (PFNGLVERTEXATTRIB2DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dNV")) == NULL) || r; + r = ((glVertexAttrib2dvNV = (PFNGLVERTEXATTRIB2DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dvNV")) == NULL) || r; + r = ((glVertexAttrib2fNV = (PFNGLVERTEXATTRIB2FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fNV")) == NULL) || r; + r = ((glVertexAttrib2fvNV = (PFNGLVERTEXATTRIB2FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fvNV")) == NULL) || r; + r = ((glVertexAttrib2sNV = (PFNGLVERTEXATTRIB2SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2sNV")) == NULL) || r; + r = ((glVertexAttrib2svNV = (PFNGLVERTEXATTRIB2SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2svNV")) == NULL) || r; + r = ((glVertexAttrib3dNV = (PFNGLVERTEXATTRIB3DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dNV")) == NULL) || r; + r = ((glVertexAttrib3dvNV = (PFNGLVERTEXATTRIB3DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dvNV")) == NULL) || r; + r = ((glVertexAttrib3fNV = (PFNGLVERTEXATTRIB3FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fNV")) == NULL) || r; + r = ((glVertexAttrib3fvNV = (PFNGLVERTEXATTRIB3FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fvNV")) == NULL) || r; + r = ((glVertexAttrib3sNV = (PFNGLVERTEXATTRIB3SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3sNV")) == NULL) || r; + r = ((glVertexAttrib3svNV = (PFNGLVERTEXATTRIB3SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3svNV")) == NULL) || r; + r = ((glVertexAttrib4dNV = (PFNGLVERTEXATTRIB4DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dNV")) == NULL) || r; + r = ((glVertexAttrib4dvNV = (PFNGLVERTEXATTRIB4DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dvNV")) == NULL) || r; + r = ((glVertexAttrib4fNV = (PFNGLVERTEXATTRIB4FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fNV")) == NULL) || r; + r = ((glVertexAttrib4fvNV = (PFNGLVERTEXATTRIB4FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fvNV")) == NULL) || r; + r = ((glVertexAttrib4sNV = (PFNGLVERTEXATTRIB4SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4sNV")) == NULL) || r; + r = ((glVertexAttrib4svNV = (PFNGLVERTEXATTRIB4SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4svNV")) == NULL) || r; + r = ((glVertexAttrib4ubNV = (PFNGLVERTEXATTRIB4UBNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubNV")) == NULL) || r; + r = ((glVertexAttrib4ubvNV = (PFNGLVERTEXATTRIB4UBVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubvNV")) == NULL) || r; + r = ((glVertexAttribPointerNV = (PFNGLVERTEXATTRIBPOINTERNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointerNV")) == NULL) || r; + r = ((glVertexAttribs1dvNV = (PFNGLVERTEXATTRIBS1DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1dvNV")) == NULL) || r; + r = ((glVertexAttribs1fvNV = (PFNGLVERTEXATTRIBS1FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1fvNV")) == NULL) || r; + r = ((glVertexAttribs1svNV = (PFNGLVERTEXATTRIBS1SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1svNV")) == NULL) || r; + r = ((glVertexAttribs2dvNV = (PFNGLVERTEXATTRIBS2DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2dvNV")) == NULL) || r; + r = ((glVertexAttribs2fvNV = (PFNGLVERTEXATTRIBS2FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2fvNV")) == NULL) || r; + r = ((glVertexAttribs2svNV = (PFNGLVERTEXATTRIBS2SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2svNV")) == NULL) || r; + r = ((glVertexAttribs3dvNV = (PFNGLVERTEXATTRIBS3DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3dvNV")) == NULL) || r; + r = ((glVertexAttribs3fvNV = (PFNGLVERTEXATTRIBS3FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3fvNV")) == NULL) || r; + r = ((glVertexAttribs3svNV = (PFNGLVERTEXATTRIBS3SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3svNV")) == NULL) || r; + r = ((glVertexAttribs4dvNV = (PFNGLVERTEXATTRIBS4DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4dvNV")) == NULL) || r; + r = ((glVertexAttribs4fvNV = (PFNGLVERTEXATTRIBS4FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4fvNV")) == NULL) || r; + r = ((glVertexAttribs4svNV = (PFNGLVERTEXATTRIBS4SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4svNV")) == NULL) || r; + r = ((glVertexAttribs4ubvNV = (PFNGLVERTEXATTRIBS4UBVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4ubvNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_vertex_program */ + +#ifdef GL_NV_vertex_program1_1 + +#endif /* GL_NV_vertex_program1_1 */ + +#ifdef GL_NV_vertex_program2 + +#endif /* GL_NV_vertex_program2 */ + +#ifdef GL_NV_vertex_program2_option + +#endif /* GL_NV_vertex_program2_option */ + +#ifdef GL_NV_vertex_program3 + +#endif /* GL_NV_vertex_program3 */ + +#ifdef GL_NV_vertex_program4 + +#endif /* GL_NV_vertex_program4 */ + +#ifdef GL_OES_byte_coordinates + +#endif /* GL_OES_byte_coordinates */ + +#ifdef GL_OES_compressed_paletted_texture + +#endif /* GL_OES_compressed_paletted_texture */ + +#ifdef GL_OES_read_format + +#endif /* GL_OES_read_format */ + +#ifdef GL_OES_single_precision + +static GLboolean _glewInit_GL_OES_single_precision (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glClearDepthfOES = (PFNGLCLEARDEPTHFOESPROC)glewGetProcAddress((const GLubyte*)"glClearDepthfOES")) == NULL) || r; + r = ((glClipPlanefOES = (PFNGLCLIPPLANEFOESPROC)glewGetProcAddress((const GLubyte*)"glClipPlanefOES")) == NULL) || r; + r = ((glDepthRangefOES = (PFNGLDEPTHRANGEFOESPROC)glewGetProcAddress((const GLubyte*)"glDepthRangefOES")) == NULL) || r; + r = ((glFrustumfOES = (PFNGLFRUSTUMFOESPROC)glewGetProcAddress((const GLubyte*)"glFrustumfOES")) == NULL) || r; + r = ((glGetClipPlanefOES = (PFNGLGETCLIPPLANEFOESPROC)glewGetProcAddress((const GLubyte*)"glGetClipPlanefOES")) == NULL) || r; + r = ((glOrthofOES = (PFNGLORTHOFOESPROC)glewGetProcAddress((const GLubyte*)"glOrthofOES")) == NULL) || r; + + return r; +} + +#endif /* GL_OES_single_precision */ + +#ifdef GL_OML_interlace + +#endif /* GL_OML_interlace */ + +#ifdef GL_OML_resample + +#endif /* GL_OML_resample */ + +#ifdef GL_OML_subsample + +#endif /* GL_OML_subsample */ + +#ifdef GL_PGI_misc_hints + +#endif /* GL_PGI_misc_hints */ + +#ifdef GL_PGI_vertex_hints + +#endif /* GL_PGI_vertex_hints */ + +#ifdef GL_REND_screen_coordinates + +#endif /* GL_REND_screen_coordinates */ + +#ifdef GL_S3_s3tc + +#endif /* GL_S3_s3tc */ + +#ifdef GL_SGIS_color_range + +#endif /* GL_SGIS_color_range */ + +#ifdef GL_SGIS_detail_texture + +static GLboolean _glewInit_GL_SGIS_detail_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDetailTexFuncSGIS = (PFNGLDETAILTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glDetailTexFuncSGIS")) == NULL) || r; + r = ((glGetDetailTexFuncSGIS = (PFNGLGETDETAILTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetDetailTexFuncSGIS")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIS_detail_texture */ + +#ifdef GL_SGIS_fog_function + +static GLboolean _glewInit_GL_SGIS_fog_function (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFogFuncSGIS = (PFNGLFOGFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glFogFuncSGIS")) == NULL) || r; + r = ((glGetFogFuncSGIS = (PFNGLGETFOGFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetFogFuncSGIS")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIS_fog_function */ + +#ifdef GL_SGIS_generate_mipmap + +#endif /* GL_SGIS_generate_mipmap */ + +#ifdef GL_SGIS_multisample + +static GLboolean _glewInit_GL_SGIS_multisample (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glSampleMaskSGIS = (PFNGLSAMPLEMASKSGISPROC)glewGetProcAddress((const GLubyte*)"glSampleMaskSGIS")) == NULL) || r; + r = ((glSamplePatternSGIS = (PFNGLSAMPLEPATTERNSGISPROC)glewGetProcAddress((const GLubyte*)"glSamplePatternSGIS")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIS_multisample */ + +#ifdef GL_SGIS_pixel_texture + +#endif /* GL_SGIS_pixel_texture */ + +#ifdef GL_SGIS_sharpen_texture + +static GLboolean _glewInit_GL_SGIS_sharpen_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetSharpenTexFuncSGIS = (PFNGLGETSHARPENTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetSharpenTexFuncSGIS")) == NULL) || r; + r = ((glSharpenTexFuncSGIS = (PFNGLSHARPENTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glSharpenTexFuncSGIS")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIS_sharpen_texture */ + +#ifdef GL_SGIS_texture4D + +static GLboolean _glewInit_GL_SGIS_texture4D (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexImage4DSGIS = (PFNGLTEXIMAGE4DSGISPROC)glewGetProcAddress((const GLubyte*)"glTexImage4DSGIS")) == NULL) || r; + r = ((glTexSubImage4DSGIS = (PFNGLTEXSUBIMAGE4DSGISPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage4DSGIS")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIS_texture4D */ + +#ifdef GL_SGIS_texture_border_clamp + +#endif /* GL_SGIS_texture_border_clamp */ + +#ifdef GL_SGIS_texture_edge_clamp + +#endif /* GL_SGIS_texture_edge_clamp */ + +#ifdef GL_SGIS_texture_filter4 + +static GLboolean _glewInit_GL_SGIS_texture_filter4 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetTexFilterFuncSGIS = (PFNGLGETTEXFILTERFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetTexFilterFuncSGIS")) == NULL) || r; + r = ((glTexFilterFuncSGIS = (PFNGLTEXFILTERFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glTexFilterFuncSGIS")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIS_texture_filter4 */ + +#ifdef GL_SGIS_texture_lod + +#endif /* GL_SGIS_texture_lod */ + +#ifdef GL_SGIS_texture_select + +#endif /* GL_SGIS_texture_select */ + +#ifdef GL_SGIX_async + +static GLboolean _glewInit_GL_SGIX_async (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glAsyncMarkerSGIX = (PFNGLASYNCMARKERSGIXPROC)glewGetProcAddress((const GLubyte*)"glAsyncMarkerSGIX")) == NULL) || r; + r = ((glDeleteAsyncMarkersSGIX = (PFNGLDELETEASYNCMARKERSSGIXPROC)glewGetProcAddress((const GLubyte*)"glDeleteAsyncMarkersSGIX")) == NULL) || r; + r = ((glFinishAsyncSGIX = (PFNGLFINISHASYNCSGIXPROC)glewGetProcAddress((const GLubyte*)"glFinishAsyncSGIX")) == NULL) || r; + r = ((glGenAsyncMarkersSGIX = (PFNGLGENASYNCMARKERSSGIXPROC)glewGetProcAddress((const GLubyte*)"glGenAsyncMarkersSGIX")) == NULL) || r; + r = ((glIsAsyncMarkerSGIX = (PFNGLISASYNCMARKERSGIXPROC)glewGetProcAddress((const GLubyte*)"glIsAsyncMarkerSGIX")) == NULL) || r; + r = ((glPollAsyncSGIX = (PFNGLPOLLASYNCSGIXPROC)glewGetProcAddress((const GLubyte*)"glPollAsyncSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_async */ + +#ifdef GL_SGIX_async_histogram + +#endif /* GL_SGIX_async_histogram */ + +#ifdef GL_SGIX_async_pixel + +#endif /* GL_SGIX_async_pixel */ + +#ifdef GL_SGIX_blend_alpha_minmax + +#endif /* GL_SGIX_blend_alpha_minmax */ + +#ifdef GL_SGIX_clipmap + +#endif /* GL_SGIX_clipmap */ + +#ifdef GL_SGIX_depth_texture + +#endif /* GL_SGIX_depth_texture */ + +#ifdef GL_SGIX_flush_raster + +static GLboolean _glewInit_GL_SGIX_flush_raster (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFlushRasterSGIX = (PFNGLFLUSHRASTERSGIXPROC)glewGetProcAddress((const GLubyte*)"glFlushRasterSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_flush_raster */ + +#ifdef GL_SGIX_fog_offset + +#endif /* GL_SGIX_fog_offset */ + +#ifdef GL_SGIX_fog_texture + +static GLboolean _glewInit_GL_SGIX_fog_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTextureFogSGIX = (PFNGLTEXTUREFOGSGIXPROC)glewGetProcAddress((const GLubyte*)"glTextureFogSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_fog_texture */ + +#ifdef GL_SGIX_fragment_specular_lighting + +static GLboolean _glewInit_GL_SGIX_fragment_specular_lighting (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFragmentColorMaterialSGIX = (PFNGLFRAGMENTCOLORMATERIALSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentColorMaterialSGIX")) == NULL) || r; + r = ((glFragmentLightModelfSGIX = (PFNGLFRAGMENTLIGHTMODELFSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfSGIX")) == NULL) || r; + r = ((glFragmentLightModelfvSGIX = (PFNGLFRAGMENTLIGHTMODELFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfvSGIX")) == NULL) || r; + r = ((glFragmentLightModeliSGIX = (PFNGLFRAGMENTLIGHTMODELISGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModeliSGIX")) == NULL) || r; + r = ((glFragmentLightModelivSGIX = (PFNGLFRAGMENTLIGHTMODELIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelivSGIX")) == NULL) || r; + r = ((glFragmentLightfSGIX = (PFNGLFRAGMENTLIGHTFSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfSGIX")) == NULL) || r; + r = ((glFragmentLightfvSGIX = (PFNGLFRAGMENTLIGHTFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfvSGIX")) == NULL) || r; + r = ((glFragmentLightiSGIX = (PFNGLFRAGMENTLIGHTISGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightiSGIX")) == NULL) || r; + r = ((glFragmentLightivSGIX = (PFNGLFRAGMENTLIGHTIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightivSGIX")) == NULL) || r; + r = ((glFragmentMaterialfSGIX = (PFNGLFRAGMENTMATERIALFSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfSGIX")) == NULL) || r; + r = ((glFragmentMaterialfvSGIX = (PFNGLFRAGMENTMATERIALFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfvSGIX")) == NULL) || r; + r = ((glFragmentMaterialiSGIX = (PFNGLFRAGMENTMATERIALISGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialiSGIX")) == NULL) || r; + r = ((glFragmentMaterialivSGIX = (PFNGLFRAGMENTMATERIALIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialivSGIX")) == NULL) || r; + r = ((glGetFragmentLightfvSGIX = (PFNGLGETFRAGMENTLIGHTFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightfvSGIX")) == NULL) || r; + r = ((glGetFragmentLightivSGIX = (PFNGLGETFRAGMENTLIGHTIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightivSGIX")) == NULL) || r; + r = ((glGetFragmentMaterialfvSGIX = (PFNGLGETFRAGMENTMATERIALFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialfvSGIX")) == NULL) || r; + r = ((glGetFragmentMaterialivSGIX = (PFNGLGETFRAGMENTMATERIALIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialivSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_fragment_specular_lighting */ + +#ifdef GL_SGIX_framezoom + +static GLboolean _glewInit_GL_SGIX_framezoom (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFrameZoomSGIX = (PFNGLFRAMEZOOMSGIXPROC)glewGetProcAddress((const GLubyte*)"glFrameZoomSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_framezoom */ + +#ifdef GL_SGIX_interlace + +#endif /* GL_SGIX_interlace */ + +#ifdef GL_SGIX_ir_instrument1 + +#endif /* GL_SGIX_ir_instrument1 */ + +#ifdef GL_SGIX_list_priority + +#endif /* GL_SGIX_list_priority */ + +#ifdef GL_SGIX_pixel_texture + +static GLboolean _glewInit_GL_SGIX_pixel_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glPixelTexGenSGIX = (PFNGLPIXELTEXGENSGIXPROC)glewGetProcAddress((const GLubyte*)"glPixelTexGenSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_pixel_texture */ + +#ifdef GL_SGIX_pixel_texture_bits + +#endif /* GL_SGIX_pixel_texture_bits */ + +#ifdef GL_SGIX_reference_plane + +static GLboolean _glewInit_GL_SGIX_reference_plane (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glReferencePlaneSGIX = (PFNGLREFERENCEPLANESGIXPROC)glewGetProcAddress((const GLubyte*)"glReferencePlaneSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_reference_plane */ + +#ifdef GL_SGIX_resample + +#endif /* GL_SGIX_resample */ + +#ifdef GL_SGIX_shadow + +#endif /* GL_SGIX_shadow */ + +#ifdef GL_SGIX_shadow_ambient + +#endif /* GL_SGIX_shadow_ambient */ + +#ifdef GL_SGIX_sprite + +static GLboolean _glewInit_GL_SGIX_sprite (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glSpriteParameterfSGIX = (PFNGLSPRITEPARAMETERFSGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameterfSGIX")) == NULL) || r; + r = ((glSpriteParameterfvSGIX = (PFNGLSPRITEPARAMETERFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameterfvSGIX")) == NULL) || r; + r = ((glSpriteParameteriSGIX = (PFNGLSPRITEPARAMETERISGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameteriSGIX")) == NULL) || r; + r = ((glSpriteParameterivSGIX = (PFNGLSPRITEPARAMETERIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameterivSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_sprite */ + +#ifdef GL_SGIX_tag_sample_buffer + +static GLboolean _glewInit_GL_SGIX_tag_sample_buffer (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTagSampleBufferSGIX = (PFNGLTAGSAMPLEBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glTagSampleBufferSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_tag_sample_buffer */ + +#ifdef GL_SGIX_texture_add_env + +#endif /* GL_SGIX_texture_add_env */ + +#ifdef GL_SGIX_texture_coordinate_clamp + +#endif /* GL_SGIX_texture_coordinate_clamp */ + +#ifdef GL_SGIX_texture_lod_bias + +#endif /* GL_SGIX_texture_lod_bias */ + +#ifdef GL_SGIX_texture_multi_buffer + +#endif /* GL_SGIX_texture_multi_buffer */ + +#ifdef GL_SGIX_texture_range + +#endif /* GL_SGIX_texture_range */ + +#ifdef GL_SGIX_texture_scale_bias + +#endif /* GL_SGIX_texture_scale_bias */ + +#ifdef GL_SGIX_vertex_preclip + +#endif /* GL_SGIX_vertex_preclip */ + +#ifdef GL_SGIX_vertex_preclip_hint + +#endif /* GL_SGIX_vertex_preclip_hint */ + +#ifdef GL_SGIX_ycrcb + +#endif /* GL_SGIX_ycrcb */ + +#ifdef GL_SGI_color_matrix + +#endif /* GL_SGI_color_matrix */ + +#ifdef GL_SGI_color_table + +static GLboolean _glewInit_GL_SGI_color_table (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColorTableParameterfvSGI = (PFNGLCOLORTABLEPARAMETERFVSGIPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameterfvSGI")) == NULL) || r; + r = ((glColorTableParameterivSGI = (PFNGLCOLORTABLEPARAMETERIVSGIPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameterivSGI")) == NULL) || r; + r = ((glColorTableSGI = (PFNGLCOLORTABLESGIPROC)glewGetProcAddress((const GLubyte*)"glColorTableSGI")) == NULL) || r; + r = ((glCopyColorTableSGI = (PFNGLCOPYCOLORTABLESGIPROC)glewGetProcAddress((const GLubyte*)"glCopyColorTableSGI")) == NULL) || r; + r = ((glGetColorTableParameterfvSGI = (PFNGLGETCOLORTABLEPARAMETERFVSGIPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterfvSGI")) == NULL) || r; + r = ((glGetColorTableParameterivSGI = (PFNGLGETCOLORTABLEPARAMETERIVSGIPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterivSGI")) == NULL) || r; + r = ((glGetColorTableSGI = (PFNGLGETCOLORTABLESGIPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableSGI")) == NULL) || r; + + return r; +} + +#endif /* GL_SGI_color_table */ + +#ifdef GL_SGI_texture_color_table + +#endif /* GL_SGI_texture_color_table */ + +#ifdef GL_SUNX_constant_data + +static GLboolean _glewInit_GL_SUNX_constant_data (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFinishTextureSUNX = (PFNGLFINISHTEXTURESUNXPROC)glewGetProcAddress((const GLubyte*)"glFinishTextureSUNX")) == NULL) || r; + + return r; +} + +#endif /* GL_SUNX_constant_data */ + +#ifdef GL_SUN_convolution_border_modes + +#endif /* GL_SUN_convolution_border_modes */ + +#ifdef GL_SUN_global_alpha + +static GLboolean _glewInit_GL_SUN_global_alpha (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGlobalAlphaFactorbSUN = (PFNGLGLOBALALPHAFACTORBSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorbSUN")) == NULL) || r; + r = ((glGlobalAlphaFactordSUN = (PFNGLGLOBALALPHAFACTORDSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactordSUN")) == NULL) || r; + r = ((glGlobalAlphaFactorfSUN = (PFNGLGLOBALALPHAFACTORFSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorfSUN")) == NULL) || r; + r = ((glGlobalAlphaFactoriSUN = (PFNGLGLOBALALPHAFACTORISUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactoriSUN")) == NULL) || r; + r = ((glGlobalAlphaFactorsSUN = (PFNGLGLOBALALPHAFACTORSSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorsSUN")) == NULL) || r; + r = ((glGlobalAlphaFactorubSUN = (PFNGLGLOBALALPHAFACTORUBSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorubSUN")) == NULL) || r; + r = ((glGlobalAlphaFactoruiSUN = (PFNGLGLOBALALPHAFACTORUISUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactoruiSUN")) == NULL) || r; + r = ((glGlobalAlphaFactorusSUN = (PFNGLGLOBALALPHAFACTORUSSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorusSUN")) == NULL) || r; + + return r; +} + +#endif /* GL_SUN_global_alpha */ + +#ifdef GL_SUN_mesh_array + +#endif /* GL_SUN_mesh_array */ + +#ifdef GL_SUN_read_video_pixels + +static GLboolean _glewInit_GL_SUN_read_video_pixels (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glReadVideoPixelsSUN = (PFNGLREADVIDEOPIXELSSUNPROC)glewGetProcAddress((const GLubyte*)"glReadVideoPixelsSUN")) == NULL) || r; + + return r; +} + +#endif /* GL_SUN_read_video_pixels */ + +#ifdef GL_SUN_slice_accum + +#endif /* GL_SUN_slice_accum */ + +#ifdef GL_SUN_triangle_list + +static GLboolean _glewInit_GL_SUN_triangle_list (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glReplacementCodePointerSUN = (PFNGLREPLACEMENTCODEPOINTERSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodePointerSUN")) == NULL) || r; + r = ((glReplacementCodeubSUN = (PFNGLREPLACEMENTCODEUBSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeubSUN")) == NULL) || r; + r = ((glReplacementCodeubvSUN = (PFNGLREPLACEMENTCODEUBVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeubvSUN")) == NULL) || r; + r = ((glReplacementCodeuiSUN = (PFNGLREPLACEMENTCODEUISUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiSUN")) == NULL) || r; + r = ((glReplacementCodeuivSUN = (PFNGLREPLACEMENTCODEUIVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuivSUN")) == NULL) || r; + r = ((glReplacementCodeusSUN = (PFNGLREPLACEMENTCODEUSSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeusSUN")) == NULL) || r; + r = ((glReplacementCodeusvSUN = (PFNGLREPLACEMENTCODEUSVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeusvSUN")) == NULL) || r; + + return r; +} + +#endif /* GL_SUN_triangle_list */ + +#ifdef GL_SUN_vertex + +static GLboolean _glewInit_GL_SUN_vertex (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColor3fVertex3fSUN = (PFNGLCOLOR3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor3fVertex3fSUN")) == NULL) || r; + r = ((glColor3fVertex3fvSUN = (PFNGLCOLOR3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor3fVertex3fvSUN")) == NULL) || r; + r = ((glColor4fNormal3fVertex3fSUN = (PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4fNormal3fVertex3fSUN")) == NULL) || r; + r = ((glColor4fNormal3fVertex3fvSUN = (PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4fNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glColor4ubVertex2fSUN = (PFNGLCOLOR4UBVERTEX2FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex2fSUN")) == NULL) || r; + r = ((glColor4ubVertex2fvSUN = (PFNGLCOLOR4UBVERTEX2FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex2fvSUN")) == NULL) || r; + r = ((glColor4ubVertex3fSUN = (PFNGLCOLOR4UBVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex3fSUN")) == NULL) || r; + r = ((glColor4ubVertex3fvSUN = (PFNGLCOLOR4UBVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex3fvSUN")) == NULL) || r; + r = ((glNormal3fVertex3fSUN = (PFNGLNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glNormal3fVertex3fSUN")) == NULL) || r; + r = ((glNormal3fVertex3fvSUN = (PFNGLNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiColor3fVertex3fSUN = (PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor3fVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiColor3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor3fVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiColor4fNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4fNormal3fVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiColor4fNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4fNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiColor4ubVertex3fSUN = (PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4ubVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiColor4ubVertex3fvSUN = (PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4ubVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiNormal3fVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiTexCoord2fVertex3fSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiTexCoord2fVertex3fvSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiVertex3fSUN = (PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiVertex3fvSUN = (PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiVertex3fvSUN")) == NULL) || r; + r = ((glTexCoord2fColor3fVertex3fSUN = (PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor3fVertex3fSUN")) == NULL) || r; + r = ((glTexCoord2fColor3fVertex3fvSUN = (PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor3fVertex3fvSUN")) == NULL) || r; + r = ((glTexCoord2fColor4fNormal3fVertex3fSUN = (PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4fNormal3fVertex3fSUN")) == NULL) || r; + r = ((glTexCoord2fColor4fNormal3fVertex3fvSUN = (PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4fNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glTexCoord2fColor4ubVertex3fSUN = (PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4ubVertex3fSUN")) == NULL) || r; + r = ((glTexCoord2fColor4ubVertex3fvSUN = (PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4ubVertex3fvSUN")) == NULL) || r; + r = ((glTexCoord2fNormal3fVertex3fSUN = (PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fNormal3fVertex3fSUN")) == NULL) || r; + r = ((glTexCoord2fNormal3fVertex3fvSUN = (PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glTexCoord2fVertex3fSUN = (PFNGLTEXCOORD2FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fVertex3fSUN")) == NULL) || r; + r = ((glTexCoord2fVertex3fvSUN = (PFNGLTEXCOORD2FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fVertex3fvSUN")) == NULL) || r; + r = ((glTexCoord4fColor4fNormal3fVertex4fSUN = (PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fColor4fNormal3fVertex4fSUN")) == NULL) || r; + r = ((glTexCoord4fColor4fNormal3fVertex4fvSUN = (PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fColor4fNormal3fVertex4fvSUN")) == NULL) || r; + r = ((glTexCoord4fVertex4fSUN = (PFNGLTEXCOORD4FVERTEX4FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fVertex4fSUN")) == NULL) || r; + r = ((glTexCoord4fVertex4fvSUN = (PFNGLTEXCOORD4FVERTEX4FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fVertex4fvSUN")) == NULL) || r; + + return r; +} + +#endif /* GL_SUN_vertex */ + +#ifdef GL_WIN_phong_shading + +#endif /* GL_WIN_phong_shading */ + +#ifdef GL_WIN_specular_fog + +#endif /* GL_WIN_specular_fog */ + +#ifdef GL_WIN_swap_hint + +static GLboolean _glewInit_GL_WIN_swap_hint (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glAddSwapHintRectWIN = (PFNGLADDSWAPHINTRECTWINPROC)glewGetProcAddress((const GLubyte*)"glAddSwapHintRectWIN")) == NULL) || r; + + return r; +} + +#endif /* GL_WIN_swap_hint */ + +/* ------------------------------------------------------------------------- */ + +/* + * Search for name in the extensions string. Use of strstr() + * is not sufficient because extension names can be prefixes of + * other extension names. Could use strtok() but the constant + * string returned by glGetString might be in read-only memory. + */ +GLboolean glewGetExtension (const char* name) +{ + GLubyte* p; + GLubyte* end; + GLuint len = _glewStrLen((const GLubyte*)name); + p = (GLubyte*)glGetString(GL_EXTENSIONS); + if (0 == p) return GL_FALSE; + end = p + _glewStrLen(p); + while (p < end) + { + GLuint n = _glewStrCLen(p, ' '); + if (len == n && _glewStrSame((const GLubyte*)name, p, n)) return GL_TRUE; + p += n+1; + } + return GL_FALSE; +} + +/* ------------------------------------------------------------------------- */ + +#ifndef GLEW_MX +static +#endif +GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) +{ + const GLubyte* s; + GLuint dot, major, minor; + /* query opengl version */ + s = glGetString(GL_VERSION); + dot = _glewStrCLen(s, '.'); + major = dot-1; + minor = dot+1; + if (dot == 0 || s[minor] == '\0') + return GLEW_ERROR_NO_GL_VERSION; + if (s[major] == '1' && s[minor] == '0') + { + return GLEW_ERROR_GL_VERSION_10_ONLY; + } + else + { + CONST_CAST(GLEW_VERSION_1_1) = GL_TRUE; + if (s[major] >= '2') + { + CONST_CAST(GLEW_VERSION_1_2) = GL_TRUE; + CONST_CAST(GLEW_VERSION_1_3) = GL_TRUE; + CONST_CAST(GLEW_VERSION_1_4) = GL_TRUE; + CONST_CAST(GLEW_VERSION_1_5) = GL_TRUE; + CONST_CAST(GLEW_VERSION_2_0) = GL_TRUE; + if (s[minor] >= '1') + { + CONST_CAST(GLEW_VERSION_2_1) = GL_TRUE; + } + } + else + { + if (s[minor] >= '5') + { + CONST_CAST(GLEW_VERSION_1_2) = GL_TRUE; + CONST_CAST(GLEW_VERSION_1_3) = GL_TRUE; + CONST_CAST(GLEW_VERSION_1_4) = GL_TRUE; + CONST_CAST(GLEW_VERSION_1_5) = GL_TRUE; + CONST_CAST(GLEW_VERSION_2_0) = GL_FALSE; + CONST_CAST(GLEW_VERSION_2_1) = GL_FALSE; + } + if (s[minor] == '4') + { + CONST_CAST(GLEW_VERSION_1_2) = GL_TRUE; + CONST_CAST(GLEW_VERSION_1_3) = GL_TRUE; + CONST_CAST(GLEW_VERSION_1_4) = GL_TRUE; + CONST_CAST(GLEW_VERSION_1_5) = GL_FALSE; + CONST_CAST(GLEW_VERSION_2_0) = GL_FALSE; + CONST_CAST(GLEW_VERSION_2_1) = GL_FALSE; + } + if (s[minor] == '3') + { + CONST_CAST(GLEW_VERSION_1_2) = GL_TRUE; + CONST_CAST(GLEW_VERSION_1_3) = GL_TRUE; + CONST_CAST(GLEW_VERSION_1_4) = GL_FALSE; + CONST_CAST(GLEW_VERSION_1_5) = GL_FALSE; + CONST_CAST(GLEW_VERSION_2_0) = GL_FALSE; + CONST_CAST(GLEW_VERSION_2_1) = GL_FALSE; + } + if (s[minor] == '2') + { + CONST_CAST(GLEW_VERSION_1_2) = GL_TRUE; + CONST_CAST(GLEW_VERSION_1_3) = GL_FALSE; + CONST_CAST(GLEW_VERSION_1_4) = GL_FALSE; + CONST_CAST(GLEW_VERSION_1_5) = GL_FALSE; + CONST_CAST(GLEW_VERSION_2_0) = GL_FALSE; + CONST_CAST(GLEW_VERSION_2_1) = GL_FALSE; + } + if (s[minor] < '2') + { + CONST_CAST(GLEW_VERSION_1_2) = GL_FALSE; + CONST_CAST(GLEW_VERSION_1_3) = GL_FALSE; + CONST_CAST(GLEW_VERSION_1_4) = GL_FALSE; + CONST_CAST(GLEW_VERSION_1_5) = GL_FALSE; + CONST_CAST(GLEW_VERSION_2_0) = GL_FALSE; + CONST_CAST(GLEW_VERSION_2_1) = GL_FALSE; + } + } + } + /* initialize extensions */ +#ifdef GL_VERSION_1_2 + if (glewExperimental || GLEW_VERSION_1_2) CONST_CAST(GLEW_VERSION_1_2) = !_glewInit_GL_VERSION_1_2(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_1_2 */ +#ifdef GL_VERSION_1_3 + if (glewExperimental || GLEW_VERSION_1_3) CONST_CAST(GLEW_VERSION_1_3) = !_glewInit_GL_VERSION_1_3(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_1_3 */ +#ifdef GL_VERSION_1_4 + if (glewExperimental || GLEW_VERSION_1_4) CONST_CAST(GLEW_VERSION_1_4) = !_glewInit_GL_VERSION_1_4(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_1_4 */ +#ifdef GL_VERSION_1_5 + if (glewExperimental || GLEW_VERSION_1_5) CONST_CAST(GLEW_VERSION_1_5) = !_glewInit_GL_VERSION_1_5(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_1_5 */ +#ifdef GL_VERSION_2_0 + if (glewExperimental || GLEW_VERSION_2_0) CONST_CAST(GLEW_VERSION_2_0) = !_glewInit_GL_VERSION_2_0(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_2_0 */ +#ifdef GL_VERSION_2_1 + if (glewExperimental || GLEW_VERSION_2_1) CONST_CAST(GLEW_VERSION_2_1) = !_glewInit_GL_VERSION_2_1(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_2_1 */ +#ifdef GL_3DFX_multisample + CONST_CAST(GLEW_3DFX_multisample) = glewGetExtension("GL_3DFX_multisample"); +#endif /* GL_3DFX_multisample */ +#ifdef GL_3DFX_tbuffer + CONST_CAST(GLEW_3DFX_tbuffer) = glewGetExtension("GL_3DFX_tbuffer"); + if (glewExperimental || GLEW_3DFX_tbuffer) CONST_CAST(GLEW_3DFX_tbuffer) = !_glewInit_GL_3DFX_tbuffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_3DFX_tbuffer */ +#ifdef GL_3DFX_texture_compression_FXT1 + CONST_CAST(GLEW_3DFX_texture_compression_FXT1) = glewGetExtension("GL_3DFX_texture_compression_FXT1"); +#endif /* GL_3DFX_texture_compression_FXT1 */ +#ifdef GL_APPLE_client_storage + CONST_CAST(GLEW_APPLE_client_storage) = glewGetExtension("GL_APPLE_client_storage"); +#endif /* GL_APPLE_client_storage */ +#ifdef GL_APPLE_element_array + CONST_CAST(GLEW_APPLE_element_array) = glewGetExtension("GL_APPLE_element_array"); + if (glewExperimental || GLEW_APPLE_element_array) CONST_CAST(GLEW_APPLE_element_array) = !_glewInit_GL_APPLE_element_array(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_APPLE_element_array */ +#ifdef GL_APPLE_fence + CONST_CAST(GLEW_APPLE_fence) = glewGetExtension("GL_APPLE_fence"); + if (glewExperimental || GLEW_APPLE_fence) CONST_CAST(GLEW_APPLE_fence) = !_glewInit_GL_APPLE_fence(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_APPLE_fence */ +#ifdef GL_APPLE_float_pixels + CONST_CAST(GLEW_APPLE_float_pixels) = glewGetExtension("GL_APPLE_float_pixels"); +#endif /* GL_APPLE_float_pixels */ +#ifdef GL_APPLE_flush_buffer_range + CONST_CAST(GLEW_APPLE_flush_buffer_range) = glewGetExtension("GL_APPLE_flush_buffer_range"); + if (glewExperimental || GLEW_APPLE_flush_buffer_range) CONST_CAST(GLEW_APPLE_flush_buffer_range) = !_glewInit_GL_APPLE_flush_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_APPLE_flush_buffer_range */ +#ifdef GL_APPLE_pixel_buffer + CONST_CAST(GLEW_APPLE_pixel_buffer) = glewGetExtension("GL_APPLE_pixel_buffer"); +#endif /* GL_APPLE_pixel_buffer */ +#ifdef GL_APPLE_specular_vector + CONST_CAST(GLEW_APPLE_specular_vector) = glewGetExtension("GL_APPLE_specular_vector"); +#endif /* GL_APPLE_specular_vector */ +#ifdef GL_APPLE_texture_range + CONST_CAST(GLEW_APPLE_texture_range) = glewGetExtension("GL_APPLE_texture_range"); + if (glewExperimental || GLEW_APPLE_texture_range) CONST_CAST(GLEW_APPLE_texture_range) = !_glewInit_GL_APPLE_texture_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_APPLE_texture_range */ +#ifdef GL_APPLE_transform_hint + CONST_CAST(GLEW_APPLE_transform_hint) = glewGetExtension("GL_APPLE_transform_hint"); +#endif /* GL_APPLE_transform_hint */ +#ifdef GL_APPLE_vertex_array_object + CONST_CAST(GLEW_APPLE_vertex_array_object) = glewGetExtension("GL_APPLE_vertex_array_object"); + if (glewExperimental || GLEW_APPLE_vertex_array_object) CONST_CAST(GLEW_APPLE_vertex_array_object) = !_glewInit_GL_APPLE_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_APPLE_vertex_array_object */ +#ifdef GL_APPLE_vertex_array_range + CONST_CAST(GLEW_APPLE_vertex_array_range) = glewGetExtension("GL_APPLE_vertex_array_range"); + if (glewExperimental || GLEW_APPLE_vertex_array_range) CONST_CAST(GLEW_APPLE_vertex_array_range) = !_glewInit_GL_APPLE_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_APPLE_vertex_array_range */ +#ifdef GL_APPLE_ycbcr_422 + CONST_CAST(GLEW_APPLE_ycbcr_422) = glewGetExtension("GL_APPLE_ycbcr_422"); +#endif /* GL_APPLE_ycbcr_422 */ +#ifdef GL_ARB_color_buffer_float + CONST_CAST(GLEW_ARB_color_buffer_float) = glewGetExtension("GL_ARB_color_buffer_float"); + if (glewExperimental || GLEW_ARB_color_buffer_float) CONST_CAST(GLEW_ARB_color_buffer_float) = !_glewInit_GL_ARB_color_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_color_buffer_float */ +#ifdef GL_ARB_depth_texture + CONST_CAST(GLEW_ARB_depth_texture) = glewGetExtension("GL_ARB_depth_texture"); +#endif /* GL_ARB_depth_texture */ +#ifdef GL_ARB_draw_buffers + CONST_CAST(GLEW_ARB_draw_buffers) = glewGetExtension("GL_ARB_draw_buffers"); + if (glewExperimental || GLEW_ARB_draw_buffers) CONST_CAST(GLEW_ARB_draw_buffers) = !_glewInit_GL_ARB_draw_buffers(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_draw_buffers */ +#ifdef GL_ARB_fragment_program + CONST_CAST(GLEW_ARB_fragment_program) = glewGetExtension("GL_ARB_fragment_program"); +#endif /* GL_ARB_fragment_program */ +#ifdef GL_ARB_fragment_program_shadow + CONST_CAST(GLEW_ARB_fragment_program_shadow) = glewGetExtension("GL_ARB_fragment_program_shadow"); +#endif /* GL_ARB_fragment_program_shadow */ +#ifdef GL_ARB_fragment_shader + CONST_CAST(GLEW_ARB_fragment_shader) = glewGetExtension("GL_ARB_fragment_shader"); +#endif /* GL_ARB_fragment_shader */ +#ifdef GL_ARB_half_float_pixel + CONST_CAST(GLEW_ARB_half_float_pixel) = glewGetExtension("GL_ARB_half_float_pixel"); +#endif /* GL_ARB_half_float_pixel */ +#ifdef GL_ARB_imaging + CONST_CAST(GLEW_ARB_imaging) = glewGetExtension("GL_ARB_imaging"); + if (glewExperimental || GLEW_ARB_imaging) CONST_CAST(GLEW_ARB_imaging) = !_glewInit_GL_ARB_imaging(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_imaging */ +#ifdef GL_ARB_matrix_palette + CONST_CAST(GLEW_ARB_matrix_palette) = glewGetExtension("GL_ARB_matrix_palette"); + if (glewExperimental || GLEW_ARB_matrix_palette) CONST_CAST(GLEW_ARB_matrix_palette) = !_glewInit_GL_ARB_matrix_palette(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_matrix_palette */ +#ifdef GL_ARB_multisample + CONST_CAST(GLEW_ARB_multisample) = glewGetExtension("GL_ARB_multisample"); + if (glewExperimental || GLEW_ARB_multisample) CONST_CAST(GLEW_ARB_multisample) = !_glewInit_GL_ARB_multisample(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_multisample */ +#ifdef GL_ARB_multitexture + CONST_CAST(GLEW_ARB_multitexture) = glewGetExtension("GL_ARB_multitexture"); + if (glewExperimental || GLEW_ARB_multitexture) CONST_CAST(GLEW_ARB_multitexture) = !_glewInit_GL_ARB_multitexture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_multitexture */ +#ifdef GL_ARB_occlusion_query + CONST_CAST(GLEW_ARB_occlusion_query) = glewGetExtension("GL_ARB_occlusion_query"); + if (glewExperimental || GLEW_ARB_occlusion_query) CONST_CAST(GLEW_ARB_occlusion_query) = !_glewInit_GL_ARB_occlusion_query(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_occlusion_query */ +#ifdef GL_ARB_pixel_buffer_object + CONST_CAST(GLEW_ARB_pixel_buffer_object) = glewGetExtension("GL_ARB_pixel_buffer_object"); +#endif /* GL_ARB_pixel_buffer_object */ +#ifdef GL_ARB_point_parameters + CONST_CAST(GLEW_ARB_point_parameters) = glewGetExtension("GL_ARB_point_parameters"); + if (glewExperimental || GLEW_ARB_point_parameters) CONST_CAST(GLEW_ARB_point_parameters) = !_glewInit_GL_ARB_point_parameters(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_point_parameters */ +#ifdef GL_ARB_point_sprite + CONST_CAST(GLEW_ARB_point_sprite) = glewGetExtension("GL_ARB_point_sprite"); +#endif /* GL_ARB_point_sprite */ +#ifdef GL_ARB_shader_objects + CONST_CAST(GLEW_ARB_shader_objects) = glewGetExtension("GL_ARB_shader_objects"); + if (glewExperimental || GLEW_ARB_shader_objects) CONST_CAST(GLEW_ARB_shader_objects) = !_glewInit_GL_ARB_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_shader_objects */ +#ifdef GL_ARB_shading_language_100 + CONST_CAST(GLEW_ARB_shading_language_100) = glewGetExtension("GL_ARB_shading_language_100"); +#endif /* GL_ARB_shading_language_100 */ +#ifdef GL_ARB_shadow + CONST_CAST(GLEW_ARB_shadow) = glewGetExtension("GL_ARB_shadow"); +#endif /* GL_ARB_shadow */ +#ifdef GL_ARB_shadow_ambient + CONST_CAST(GLEW_ARB_shadow_ambient) = glewGetExtension("GL_ARB_shadow_ambient"); +#endif /* GL_ARB_shadow_ambient */ +#ifdef GL_ARB_texture_border_clamp + CONST_CAST(GLEW_ARB_texture_border_clamp) = glewGetExtension("GL_ARB_texture_border_clamp"); +#endif /* GL_ARB_texture_border_clamp */ +#ifdef GL_ARB_texture_compression + CONST_CAST(GLEW_ARB_texture_compression) = glewGetExtension("GL_ARB_texture_compression"); + if (glewExperimental || GLEW_ARB_texture_compression) CONST_CAST(GLEW_ARB_texture_compression) = !_glewInit_GL_ARB_texture_compression(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_texture_compression */ +#ifdef GL_ARB_texture_cube_map + CONST_CAST(GLEW_ARB_texture_cube_map) = glewGetExtension("GL_ARB_texture_cube_map"); +#endif /* GL_ARB_texture_cube_map */ +#ifdef GL_ARB_texture_env_add + CONST_CAST(GLEW_ARB_texture_env_add) = glewGetExtension("GL_ARB_texture_env_add"); +#endif /* GL_ARB_texture_env_add */ +#ifdef GL_ARB_texture_env_combine + CONST_CAST(GLEW_ARB_texture_env_combine) = glewGetExtension("GL_ARB_texture_env_combine"); +#endif /* GL_ARB_texture_env_combine */ +#ifdef GL_ARB_texture_env_crossbar + CONST_CAST(GLEW_ARB_texture_env_crossbar) = glewGetExtension("GL_ARB_texture_env_crossbar"); +#endif /* GL_ARB_texture_env_crossbar */ +#ifdef GL_ARB_texture_env_dot3 + CONST_CAST(GLEW_ARB_texture_env_dot3) = glewGetExtension("GL_ARB_texture_env_dot3"); +#endif /* GL_ARB_texture_env_dot3 */ +#ifdef GL_ARB_texture_float + CONST_CAST(GLEW_ARB_texture_float) = glewGetExtension("GL_ARB_texture_float"); +#endif /* GL_ARB_texture_float */ +#ifdef GL_ARB_texture_mirrored_repeat + CONST_CAST(GLEW_ARB_texture_mirrored_repeat) = glewGetExtension("GL_ARB_texture_mirrored_repeat"); +#endif /* GL_ARB_texture_mirrored_repeat */ +#ifdef GL_ARB_texture_non_power_of_two + CONST_CAST(GLEW_ARB_texture_non_power_of_two) = glewGetExtension("GL_ARB_texture_non_power_of_two"); +#endif /* GL_ARB_texture_non_power_of_two */ +#ifdef GL_ARB_texture_rectangle + CONST_CAST(GLEW_ARB_texture_rectangle) = glewGetExtension("GL_ARB_texture_rectangle"); +#endif /* GL_ARB_texture_rectangle */ +#ifdef GL_ARB_transpose_matrix + CONST_CAST(GLEW_ARB_transpose_matrix) = glewGetExtension("GL_ARB_transpose_matrix"); + if (glewExperimental || GLEW_ARB_transpose_matrix) CONST_CAST(GLEW_ARB_transpose_matrix) = !_glewInit_GL_ARB_transpose_matrix(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_transpose_matrix */ +#ifdef GL_ARB_vertex_blend + CONST_CAST(GLEW_ARB_vertex_blend) = glewGetExtension("GL_ARB_vertex_blend"); + if (glewExperimental || GLEW_ARB_vertex_blend) CONST_CAST(GLEW_ARB_vertex_blend) = !_glewInit_GL_ARB_vertex_blend(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_vertex_blend */ +#ifdef GL_ARB_vertex_buffer_object + CONST_CAST(GLEW_ARB_vertex_buffer_object) = glewGetExtension("GL_ARB_vertex_buffer_object"); + if (glewExperimental || GLEW_ARB_vertex_buffer_object) CONST_CAST(GLEW_ARB_vertex_buffer_object) = !_glewInit_GL_ARB_vertex_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_vertex_buffer_object */ +#ifdef GL_ARB_vertex_program + CONST_CAST(GLEW_ARB_vertex_program) = glewGetExtension("GL_ARB_vertex_program"); + if (glewExperimental || GLEW_ARB_vertex_program) CONST_CAST(GLEW_ARB_vertex_program) = !_glewInit_GL_ARB_vertex_program(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_vertex_program */ +#ifdef GL_ARB_vertex_shader + CONST_CAST(GLEW_ARB_vertex_shader) = glewGetExtension("GL_ARB_vertex_shader"); + if (glewExperimental || GLEW_ARB_vertex_shader) CONST_CAST(GLEW_ARB_vertex_shader) = !_glewInit_GL_ARB_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_vertex_shader */ +#ifdef GL_ARB_window_pos + CONST_CAST(GLEW_ARB_window_pos) = glewGetExtension("GL_ARB_window_pos"); + if (glewExperimental || GLEW_ARB_window_pos) CONST_CAST(GLEW_ARB_window_pos) = !_glewInit_GL_ARB_window_pos(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_window_pos */ +#ifdef GL_ATIX_point_sprites + CONST_CAST(GLEW_ATIX_point_sprites) = glewGetExtension("GL_ATIX_point_sprites"); +#endif /* GL_ATIX_point_sprites */ +#ifdef GL_ATIX_texture_env_combine3 + CONST_CAST(GLEW_ATIX_texture_env_combine3) = glewGetExtension("GL_ATIX_texture_env_combine3"); +#endif /* GL_ATIX_texture_env_combine3 */ +#ifdef GL_ATIX_texture_env_route + CONST_CAST(GLEW_ATIX_texture_env_route) = glewGetExtension("GL_ATIX_texture_env_route"); +#endif /* GL_ATIX_texture_env_route */ +#ifdef GL_ATIX_vertex_shader_output_point_size + CONST_CAST(GLEW_ATIX_vertex_shader_output_point_size) = glewGetExtension("GL_ATIX_vertex_shader_output_point_size"); +#endif /* GL_ATIX_vertex_shader_output_point_size */ +#ifdef GL_ATI_draw_buffers + CONST_CAST(GLEW_ATI_draw_buffers) = glewGetExtension("GL_ATI_draw_buffers"); + if (glewExperimental || GLEW_ATI_draw_buffers) CONST_CAST(GLEW_ATI_draw_buffers) = !_glewInit_GL_ATI_draw_buffers(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_draw_buffers */ +#ifdef GL_ATI_element_array + CONST_CAST(GLEW_ATI_element_array) = glewGetExtension("GL_ATI_element_array"); + if (glewExperimental || GLEW_ATI_element_array) CONST_CAST(GLEW_ATI_element_array) = !_glewInit_GL_ATI_element_array(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_element_array */ +#ifdef GL_ATI_envmap_bumpmap + CONST_CAST(GLEW_ATI_envmap_bumpmap) = glewGetExtension("GL_ATI_envmap_bumpmap"); + if (glewExperimental || GLEW_ATI_envmap_bumpmap) CONST_CAST(GLEW_ATI_envmap_bumpmap) = !_glewInit_GL_ATI_envmap_bumpmap(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_envmap_bumpmap */ +#ifdef GL_ATI_fragment_shader + CONST_CAST(GLEW_ATI_fragment_shader) = glewGetExtension("GL_ATI_fragment_shader"); + if (glewExperimental || GLEW_ATI_fragment_shader) CONST_CAST(GLEW_ATI_fragment_shader) = !_glewInit_GL_ATI_fragment_shader(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_fragment_shader */ +#ifdef GL_ATI_map_object_buffer + CONST_CAST(GLEW_ATI_map_object_buffer) = glewGetExtension("GL_ATI_map_object_buffer"); + if (glewExperimental || GLEW_ATI_map_object_buffer) CONST_CAST(GLEW_ATI_map_object_buffer) = !_glewInit_GL_ATI_map_object_buffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_map_object_buffer */ +#ifdef GL_ATI_pn_triangles + CONST_CAST(GLEW_ATI_pn_triangles) = glewGetExtension("GL_ATI_pn_triangles"); + if (glewExperimental || GLEW_ATI_pn_triangles) CONST_CAST(GLEW_ATI_pn_triangles) = !_glewInit_GL_ATI_pn_triangles(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_pn_triangles */ +#ifdef GL_ATI_separate_stencil + CONST_CAST(GLEW_ATI_separate_stencil) = glewGetExtension("GL_ATI_separate_stencil"); + if (glewExperimental || GLEW_ATI_separate_stencil) CONST_CAST(GLEW_ATI_separate_stencil) = !_glewInit_GL_ATI_separate_stencil(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_separate_stencil */ +#ifdef GL_ATI_shader_texture_lod + CONST_CAST(GLEW_ATI_shader_texture_lod) = glewGetExtension("GL_ATI_shader_texture_lod"); +#endif /* GL_ATI_shader_texture_lod */ +#ifdef GL_ATI_text_fragment_shader + CONST_CAST(GLEW_ATI_text_fragment_shader) = glewGetExtension("GL_ATI_text_fragment_shader"); +#endif /* GL_ATI_text_fragment_shader */ +#ifdef GL_ATI_texture_compression_3dc + CONST_CAST(GLEW_ATI_texture_compression_3dc) = glewGetExtension("GL_ATI_texture_compression_3dc"); +#endif /* GL_ATI_texture_compression_3dc */ +#ifdef GL_ATI_texture_env_combine3 + CONST_CAST(GLEW_ATI_texture_env_combine3) = glewGetExtension("GL_ATI_texture_env_combine3"); +#endif /* GL_ATI_texture_env_combine3 */ +#ifdef GL_ATI_texture_float + CONST_CAST(GLEW_ATI_texture_float) = glewGetExtension("GL_ATI_texture_float"); +#endif /* GL_ATI_texture_float */ +#ifdef GL_ATI_texture_mirror_once + CONST_CAST(GLEW_ATI_texture_mirror_once) = glewGetExtension("GL_ATI_texture_mirror_once"); +#endif /* GL_ATI_texture_mirror_once */ +#ifdef GL_ATI_vertex_array_object + CONST_CAST(GLEW_ATI_vertex_array_object) = glewGetExtension("GL_ATI_vertex_array_object"); + if (glewExperimental || GLEW_ATI_vertex_array_object) CONST_CAST(GLEW_ATI_vertex_array_object) = !_glewInit_GL_ATI_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_vertex_array_object */ +#ifdef GL_ATI_vertex_attrib_array_object + CONST_CAST(GLEW_ATI_vertex_attrib_array_object) = glewGetExtension("GL_ATI_vertex_attrib_array_object"); + if (glewExperimental || GLEW_ATI_vertex_attrib_array_object) CONST_CAST(GLEW_ATI_vertex_attrib_array_object) = !_glewInit_GL_ATI_vertex_attrib_array_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_vertex_attrib_array_object */ +#ifdef GL_ATI_vertex_streams + CONST_CAST(GLEW_ATI_vertex_streams) = glewGetExtension("GL_ATI_vertex_streams"); + if (glewExperimental || GLEW_ATI_vertex_streams) CONST_CAST(GLEW_ATI_vertex_streams) = !_glewInit_GL_ATI_vertex_streams(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_vertex_streams */ +#ifdef GL_EXT_422_pixels + CONST_CAST(GLEW_EXT_422_pixels) = glewGetExtension("GL_EXT_422_pixels"); +#endif /* GL_EXT_422_pixels */ +#ifdef GL_EXT_Cg_shader + CONST_CAST(GLEW_EXT_Cg_shader) = glewGetExtension("GL_EXT_Cg_shader"); +#endif /* GL_EXT_Cg_shader */ +#ifdef GL_EXT_abgr + CONST_CAST(GLEW_EXT_abgr) = glewGetExtension("GL_EXT_abgr"); +#endif /* GL_EXT_abgr */ +#ifdef GL_EXT_bgra + CONST_CAST(GLEW_EXT_bgra) = glewGetExtension("GL_EXT_bgra"); +#endif /* GL_EXT_bgra */ +#ifdef GL_EXT_bindable_uniform + CONST_CAST(GLEW_EXT_bindable_uniform) = glewGetExtension("GL_EXT_bindable_uniform"); + if (glewExperimental || GLEW_EXT_bindable_uniform) CONST_CAST(GLEW_EXT_bindable_uniform) = !_glewInit_GL_EXT_bindable_uniform(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_bindable_uniform */ +#ifdef GL_EXT_blend_color + CONST_CAST(GLEW_EXT_blend_color) = glewGetExtension("GL_EXT_blend_color"); + if (glewExperimental || GLEW_EXT_blend_color) CONST_CAST(GLEW_EXT_blend_color) = !_glewInit_GL_EXT_blend_color(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_blend_color */ +#ifdef GL_EXT_blend_equation_separate + CONST_CAST(GLEW_EXT_blend_equation_separate) = glewGetExtension("GL_EXT_blend_equation_separate"); + if (glewExperimental || GLEW_EXT_blend_equation_separate) CONST_CAST(GLEW_EXT_blend_equation_separate) = !_glewInit_GL_EXT_blend_equation_separate(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_blend_equation_separate */ +#ifdef GL_EXT_blend_func_separate + CONST_CAST(GLEW_EXT_blend_func_separate) = glewGetExtension("GL_EXT_blend_func_separate"); + if (glewExperimental || GLEW_EXT_blend_func_separate) CONST_CAST(GLEW_EXT_blend_func_separate) = !_glewInit_GL_EXT_blend_func_separate(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_blend_func_separate */ +#ifdef GL_EXT_blend_logic_op + CONST_CAST(GLEW_EXT_blend_logic_op) = glewGetExtension("GL_EXT_blend_logic_op"); +#endif /* GL_EXT_blend_logic_op */ +#ifdef GL_EXT_blend_minmax + CONST_CAST(GLEW_EXT_blend_minmax) = glewGetExtension("GL_EXT_blend_minmax"); + if (glewExperimental || GLEW_EXT_blend_minmax) CONST_CAST(GLEW_EXT_blend_minmax) = !_glewInit_GL_EXT_blend_minmax(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_blend_minmax */ +#ifdef GL_EXT_blend_subtract + CONST_CAST(GLEW_EXT_blend_subtract) = glewGetExtension("GL_EXT_blend_subtract"); +#endif /* GL_EXT_blend_subtract */ +#ifdef GL_EXT_clip_volume_hint + CONST_CAST(GLEW_EXT_clip_volume_hint) = glewGetExtension("GL_EXT_clip_volume_hint"); +#endif /* GL_EXT_clip_volume_hint */ +#ifdef GL_EXT_cmyka + CONST_CAST(GLEW_EXT_cmyka) = glewGetExtension("GL_EXT_cmyka"); +#endif /* GL_EXT_cmyka */ +#ifdef GL_EXT_color_subtable + CONST_CAST(GLEW_EXT_color_subtable) = glewGetExtension("GL_EXT_color_subtable"); + if (glewExperimental || GLEW_EXT_color_subtable) CONST_CAST(GLEW_EXT_color_subtable) = !_glewInit_GL_EXT_color_subtable(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_color_subtable */ +#ifdef GL_EXT_compiled_vertex_array + CONST_CAST(GLEW_EXT_compiled_vertex_array) = glewGetExtension("GL_EXT_compiled_vertex_array"); + if (glewExperimental || GLEW_EXT_compiled_vertex_array) CONST_CAST(GLEW_EXT_compiled_vertex_array) = !_glewInit_GL_EXT_compiled_vertex_array(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_compiled_vertex_array */ +#ifdef GL_EXT_convolution + CONST_CAST(GLEW_EXT_convolution) = glewGetExtension("GL_EXT_convolution"); + if (glewExperimental || GLEW_EXT_convolution) CONST_CAST(GLEW_EXT_convolution) = !_glewInit_GL_EXT_convolution(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_convolution */ +#ifdef GL_EXT_coordinate_frame + CONST_CAST(GLEW_EXT_coordinate_frame) = glewGetExtension("GL_EXT_coordinate_frame"); + if (glewExperimental || GLEW_EXT_coordinate_frame) CONST_CAST(GLEW_EXT_coordinate_frame) = !_glewInit_GL_EXT_coordinate_frame(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_coordinate_frame */ +#ifdef GL_EXT_copy_texture + CONST_CAST(GLEW_EXT_copy_texture) = glewGetExtension("GL_EXT_copy_texture"); + if (glewExperimental || GLEW_EXT_copy_texture) CONST_CAST(GLEW_EXT_copy_texture) = !_glewInit_GL_EXT_copy_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_copy_texture */ +#ifdef GL_EXT_cull_vertex + CONST_CAST(GLEW_EXT_cull_vertex) = glewGetExtension("GL_EXT_cull_vertex"); + if (glewExperimental || GLEW_EXT_cull_vertex) CONST_CAST(GLEW_EXT_cull_vertex) = !_glewInit_GL_EXT_cull_vertex(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_cull_vertex */ +#ifdef GL_EXT_depth_bounds_test + CONST_CAST(GLEW_EXT_depth_bounds_test) = glewGetExtension("GL_EXT_depth_bounds_test"); + if (glewExperimental || GLEW_EXT_depth_bounds_test) CONST_CAST(GLEW_EXT_depth_bounds_test) = !_glewInit_GL_EXT_depth_bounds_test(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_depth_bounds_test */ +#ifdef GL_EXT_draw_buffers2 + CONST_CAST(GLEW_EXT_draw_buffers2) = glewGetExtension("GL_EXT_draw_buffers2"); + if (glewExperimental || GLEW_EXT_draw_buffers2) CONST_CAST(GLEW_EXT_draw_buffers2) = !_glewInit_GL_EXT_draw_buffers2(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_draw_buffers2 */ +#ifdef GL_EXT_draw_instanced + CONST_CAST(GLEW_EXT_draw_instanced) = glewGetExtension("GL_EXT_draw_instanced"); + if (glewExperimental || GLEW_EXT_draw_instanced) CONST_CAST(GLEW_EXT_draw_instanced) = !_glewInit_GL_EXT_draw_instanced(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_draw_instanced */ +#ifdef GL_EXT_draw_range_elements + CONST_CAST(GLEW_EXT_draw_range_elements) = glewGetExtension("GL_EXT_draw_range_elements"); + if (glewExperimental || GLEW_EXT_draw_range_elements) CONST_CAST(GLEW_EXT_draw_range_elements) = !_glewInit_GL_EXT_draw_range_elements(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_draw_range_elements */ +#ifdef GL_EXT_fog_coord + CONST_CAST(GLEW_EXT_fog_coord) = glewGetExtension("GL_EXT_fog_coord"); + if (glewExperimental || GLEW_EXT_fog_coord) CONST_CAST(GLEW_EXT_fog_coord) = !_glewInit_GL_EXT_fog_coord(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_fog_coord */ +#ifdef GL_EXT_fragment_lighting + CONST_CAST(GLEW_EXT_fragment_lighting) = glewGetExtension("GL_EXT_fragment_lighting"); + if (glewExperimental || GLEW_EXT_fragment_lighting) CONST_CAST(GLEW_EXT_fragment_lighting) = !_glewInit_GL_EXT_fragment_lighting(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_fragment_lighting */ +#ifdef GL_EXT_framebuffer_blit + CONST_CAST(GLEW_EXT_framebuffer_blit) = glewGetExtension("GL_EXT_framebuffer_blit"); + if (glewExperimental || GLEW_EXT_framebuffer_blit) CONST_CAST(GLEW_EXT_framebuffer_blit) = !_glewInit_GL_EXT_framebuffer_blit(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_framebuffer_blit */ +#ifdef GL_EXT_framebuffer_multisample + CONST_CAST(GLEW_EXT_framebuffer_multisample) = glewGetExtension("GL_EXT_framebuffer_multisample"); + if (glewExperimental || GLEW_EXT_framebuffer_multisample) CONST_CAST(GLEW_EXT_framebuffer_multisample) = !_glewInit_GL_EXT_framebuffer_multisample(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_framebuffer_multisample */ +#ifdef GL_EXT_framebuffer_object + CONST_CAST(GLEW_EXT_framebuffer_object) = glewGetExtension("GL_EXT_framebuffer_object"); + if (glewExperimental || GLEW_EXT_framebuffer_object) CONST_CAST(GLEW_EXT_framebuffer_object) = !_glewInit_GL_EXT_framebuffer_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_framebuffer_object */ +#ifdef GL_EXT_framebuffer_sRGB + CONST_CAST(GLEW_EXT_framebuffer_sRGB) = glewGetExtension("GL_EXT_framebuffer_sRGB"); +#endif /* GL_EXT_framebuffer_sRGB */ +#ifdef GL_EXT_geometry_shader4 + CONST_CAST(GLEW_EXT_geometry_shader4) = glewGetExtension("GL_EXT_geometry_shader4"); + if (glewExperimental || GLEW_EXT_geometry_shader4) CONST_CAST(GLEW_EXT_geometry_shader4) = !_glewInit_GL_EXT_geometry_shader4(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_geometry_shader4 */ +#ifdef GL_EXT_gpu_program_parameters + CONST_CAST(GLEW_EXT_gpu_program_parameters) = glewGetExtension("GL_EXT_gpu_program_parameters"); + if (glewExperimental || GLEW_EXT_gpu_program_parameters) CONST_CAST(GLEW_EXT_gpu_program_parameters) = !_glewInit_GL_EXT_gpu_program_parameters(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_gpu_program_parameters */ +#ifdef GL_EXT_gpu_shader4 + CONST_CAST(GLEW_EXT_gpu_shader4) = glewGetExtension("GL_EXT_gpu_shader4"); + if (glewExperimental || GLEW_EXT_gpu_shader4) CONST_CAST(GLEW_EXT_gpu_shader4) = !_glewInit_GL_EXT_gpu_shader4(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_gpu_shader4 */ +#ifdef GL_EXT_histogram + CONST_CAST(GLEW_EXT_histogram) = glewGetExtension("GL_EXT_histogram"); + if (glewExperimental || GLEW_EXT_histogram) CONST_CAST(GLEW_EXT_histogram) = !_glewInit_GL_EXT_histogram(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_histogram */ +#ifdef GL_EXT_index_array_formats + CONST_CAST(GLEW_EXT_index_array_formats) = glewGetExtension("GL_EXT_index_array_formats"); +#endif /* GL_EXT_index_array_formats */ +#ifdef GL_EXT_index_func + CONST_CAST(GLEW_EXT_index_func) = glewGetExtension("GL_EXT_index_func"); + if (glewExperimental || GLEW_EXT_index_func) CONST_CAST(GLEW_EXT_index_func) = !_glewInit_GL_EXT_index_func(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_index_func */ +#ifdef GL_EXT_index_material + CONST_CAST(GLEW_EXT_index_material) = glewGetExtension("GL_EXT_index_material"); + if (glewExperimental || GLEW_EXT_index_material) CONST_CAST(GLEW_EXT_index_material) = !_glewInit_GL_EXT_index_material(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_index_material */ +#ifdef GL_EXT_index_texture + CONST_CAST(GLEW_EXT_index_texture) = glewGetExtension("GL_EXT_index_texture"); +#endif /* GL_EXT_index_texture */ +#ifdef GL_EXT_light_texture + CONST_CAST(GLEW_EXT_light_texture) = glewGetExtension("GL_EXT_light_texture"); + if (glewExperimental || GLEW_EXT_light_texture) CONST_CAST(GLEW_EXT_light_texture) = !_glewInit_GL_EXT_light_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_light_texture */ +#ifdef GL_EXT_misc_attribute + CONST_CAST(GLEW_EXT_misc_attribute) = glewGetExtension("GL_EXT_misc_attribute"); +#endif /* GL_EXT_misc_attribute */ +#ifdef GL_EXT_multi_draw_arrays + CONST_CAST(GLEW_EXT_multi_draw_arrays) = glewGetExtension("GL_EXT_multi_draw_arrays"); + if (glewExperimental || GLEW_EXT_multi_draw_arrays) CONST_CAST(GLEW_EXT_multi_draw_arrays) = !_glewInit_GL_EXT_multi_draw_arrays(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_multi_draw_arrays */ +#ifdef GL_EXT_multisample + CONST_CAST(GLEW_EXT_multisample) = glewGetExtension("GL_EXT_multisample"); + if (glewExperimental || GLEW_EXT_multisample) CONST_CAST(GLEW_EXT_multisample) = !_glewInit_GL_EXT_multisample(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_multisample */ +#ifdef GL_EXT_packed_depth_stencil + CONST_CAST(GLEW_EXT_packed_depth_stencil) = glewGetExtension("GL_EXT_packed_depth_stencil"); +#endif /* GL_EXT_packed_depth_stencil */ +#ifdef GL_EXT_packed_float + CONST_CAST(GLEW_EXT_packed_float) = glewGetExtension("GL_EXT_packed_float"); +#endif /* GL_EXT_packed_float */ +#ifdef GL_EXT_packed_pixels + CONST_CAST(GLEW_EXT_packed_pixels) = glewGetExtension("GL_EXT_packed_pixels"); +#endif /* GL_EXT_packed_pixels */ +#ifdef GL_EXT_paletted_texture + CONST_CAST(GLEW_EXT_paletted_texture) = glewGetExtension("GL_EXT_paletted_texture"); + if (glewExperimental || GLEW_EXT_paletted_texture) CONST_CAST(GLEW_EXT_paletted_texture) = !_glewInit_GL_EXT_paletted_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_paletted_texture */ +#ifdef GL_EXT_pixel_buffer_object + CONST_CAST(GLEW_EXT_pixel_buffer_object) = glewGetExtension("GL_EXT_pixel_buffer_object"); +#endif /* GL_EXT_pixel_buffer_object */ +#ifdef GL_EXT_pixel_transform + CONST_CAST(GLEW_EXT_pixel_transform) = glewGetExtension("GL_EXT_pixel_transform"); + if (glewExperimental || GLEW_EXT_pixel_transform) CONST_CAST(GLEW_EXT_pixel_transform) = !_glewInit_GL_EXT_pixel_transform(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_pixel_transform */ +#ifdef GL_EXT_pixel_transform_color_table + CONST_CAST(GLEW_EXT_pixel_transform_color_table) = glewGetExtension("GL_EXT_pixel_transform_color_table"); +#endif /* GL_EXT_pixel_transform_color_table */ +#ifdef GL_EXT_point_parameters + CONST_CAST(GLEW_EXT_point_parameters) = glewGetExtension("GL_EXT_point_parameters"); + if (glewExperimental || GLEW_EXT_point_parameters) CONST_CAST(GLEW_EXT_point_parameters) = !_glewInit_GL_EXT_point_parameters(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_point_parameters */ +#ifdef GL_EXT_polygon_offset + CONST_CAST(GLEW_EXT_polygon_offset) = glewGetExtension("GL_EXT_polygon_offset"); + if (glewExperimental || GLEW_EXT_polygon_offset) CONST_CAST(GLEW_EXT_polygon_offset) = !_glewInit_GL_EXT_polygon_offset(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_polygon_offset */ +#ifdef GL_EXT_rescale_normal + CONST_CAST(GLEW_EXT_rescale_normal) = glewGetExtension("GL_EXT_rescale_normal"); +#endif /* GL_EXT_rescale_normal */ +#ifdef GL_EXT_scene_marker + CONST_CAST(GLEW_EXT_scene_marker) = glewGetExtension("GL_EXT_scene_marker"); + if (glewExperimental || GLEW_EXT_scene_marker) CONST_CAST(GLEW_EXT_scene_marker) = !_glewInit_GL_EXT_scene_marker(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_scene_marker */ +#ifdef GL_EXT_secondary_color + CONST_CAST(GLEW_EXT_secondary_color) = glewGetExtension("GL_EXT_secondary_color"); + if (glewExperimental || GLEW_EXT_secondary_color) CONST_CAST(GLEW_EXT_secondary_color) = !_glewInit_GL_EXT_secondary_color(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_secondary_color */ +#ifdef GL_EXT_separate_specular_color + CONST_CAST(GLEW_EXT_separate_specular_color) = glewGetExtension("GL_EXT_separate_specular_color"); +#endif /* GL_EXT_separate_specular_color */ +#ifdef GL_EXT_shadow_funcs + CONST_CAST(GLEW_EXT_shadow_funcs) = glewGetExtension("GL_EXT_shadow_funcs"); +#endif /* GL_EXT_shadow_funcs */ +#ifdef GL_EXT_shared_texture_palette + CONST_CAST(GLEW_EXT_shared_texture_palette) = glewGetExtension("GL_EXT_shared_texture_palette"); +#endif /* GL_EXT_shared_texture_palette */ +#ifdef GL_EXT_stencil_clear_tag + CONST_CAST(GLEW_EXT_stencil_clear_tag) = glewGetExtension("GL_EXT_stencil_clear_tag"); +#endif /* GL_EXT_stencil_clear_tag */ +#ifdef GL_EXT_stencil_two_side + CONST_CAST(GLEW_EXT_stencil_two_side) = glewGetExtension("GL_EXT_stencil_two_side"); + if (glewExperimental || GLEW_EXT_stencil_two_side) CONST_CAST(GLEW_EXT_stencil_two_side) = !_glewInit_GL_EXT_stencil_two_side(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_stencil_two_side */ +#ifdef GL_EXT_stencil_wrap + CONST_CAST(GLEW_EXT_stencil_wrap) = glewGetExtension("GL_EXT_stencil_wrap"); +#endif /* GL_EXT_stencil_wrap */ +#ifdef GL_EXT_subtexture + CONST_CAST(GLEW_EXT_subtexture) = glewGetExtension("GL_EXT_subtexture"); + if (glewExperimental || GLEW_EXT_subtexture) CONST_CAST(GLEW_EXT_subtexture) = !_glewInit_GL_EXT_subtexture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_subtexture */ +#ifdef GL_EXT_texture + CONST_CAST(GLEW_EXT_texture) = glewGetExtension("GL_EXT_texture"); +#endif /* GL_EXT_texture */ +#ifdef GL_EXT_texture3D + CONST_CAST(GLEW_EXT_texture3D) = glewGetExtension("GL_EXT_texture3D"); + if (glewExperimental || GLEW_EXT_texture3D) CONST_CAST(GLEW_EXT_texture3D) = !_glewInit_GL_EXT_texture3D(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_texture3D */ +#ifdef GL_EXT_texture_array + CONST_CAST(GLEW_EXT_texture_array) = glewGetExtension("GL_EXT_texture_array"); +#endif /* GL_EXT_texture_array */ +#ifdef GL_EXT_texture_buffer_object + CONST_CAST(GLEW_EXT_texture_buffer_object) = glewGetExtension("GL_EXT_texture_buffer_object"); + if (glewExperimental || GLEW_EXT_texture_buffer_object) CONST_CAST(GLEW_EXT_texture_buffer_object) = !_glewInit_GL_EXT_texture_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_texture_buffer_object */ +#ifdef GL_EXT_texture_compression_dxt1 + CONST_CAST(GLEW_EXT_texture_compression_dxt1) = glewGetExtension("GL_EXT_texture_compression_dxt1"); +#endif /* GL_EXT_texture_compression_dxt1 */ +#ifdef GL_EXT_texture_compression_latc + CONST_CAST(GLEW_EXT_texture_compression_latc) = glewGetExtension("GL_EXT_texture_compression_latc"); +#endif /* GL_EXT_texture_compression_latc */ +#ifdef GL_EXT_texture_compression_rgtc + CONST_CAST(GLEW_EXT_texture_compression_rgtc) = glewGetExtension("GL_EXT_texture_compression_rgtc"); +#endif /* GL_EXT_texture_compression_rgtc */ +#ifdef GL_EXT_texture_compression_s3tc + CONST_CAST(GLEW_EXT_texture_compression_s3tc) = glewGetExtension("GL_EXT_texture_compression_s3tc"); +#endif /* GL_EXT_texture_compression_s3tc */ +#ifdef GL_EXT_texture_cube_map + CONST_CAST(GLEW_EXT_texture_cube_map) = glewGetExtension("GL_EXT_texture_cube_map"); +#endif /* GL_EXT_texture_cube_map */ +#ifdef GL_EXT_texture_edge_clamp + CONST_CAST(GLEW_EXT_texture_edge_clamp) = glewGetExtension("GL_EXT_texture_edge_clamp"); +#endif /* GL_EXT_texture_edge_clamp */ +#ifdef GL_EXT_texture_env + CONST_CAST(GLEW_EXT_texture_env) = glewGetExtension("GL_EXT_texture_env"); +#endif /* GL_EXT_texture_env */ +#ifdef GL_EXT_texture_env_add + CONST_CAST(GLEW_EXT_texture_env_add) = glewGetExtension("GL_EXT_texture_env_add"); +#endif /* GL_EXT_texture_env_add */ +#ifdef GL_EXT_texture_env_combine + CONST_CAST(GLEW_EXT_texture_env_combine) = glewGetExtension("GL_EXT_texture_env_combine"); +#endif /* GL_EXT_texture_env_combine */ +#ifdef GL_EXT_texture_env_dot3 + CONST_CAST(GLEW_EXT_texture_env_dot3) = glewGetExtension("GL_EXT_texture_env_dot3"); +#endif /* GL_EXT_texture_env_dot3 */ +#ifdef GL_EXT_texture_filter_anisotropic + CONST_CAST(GLEW_EXT_texture_filter_anisotropic) = glewGetExtension("GL_EXT_texture_filter_anisotropic"); +#endif /* GL_EXT_texture_filter_anisotropic */ +#ifdef GL_EXT_texture_integer + CONST_CAST(GLEW_EXT_texture_integer) = glewGetExtension("GL_EXT_texture_integer"); + if (glewExperimental || GLEW_EXT_texture_integer) CONST_CAST(GLEW_EXT_texture_integer) = !_glewInit_GL_EXT_texture_integer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_texture_integer */ +#ifdef GL_EXT_texture_lod_bias + CONST_CAST(GLEW_EXT_texture_lod_bias) = glewGetExtension("GL_EXT_texture_lod_bias"); +#endif /* GL_EXT_texture_lod_bias */ +#ifdef GL_EXT_texture_mirror_clamp + CONST_CAST(GLEW_EXT_texture_mirror_clamp) = glewGetExtension("GL_EXT_texture_mirror_clamp"); +#endif /* GL_EXT_texture_mirror_clamp */ +#ifdef GL_EXT_texture_object + CONST_CAST(GLEW_EXT_texture_object) = glewGetExtension("GL_EXT_texture_object"); + if (glewExperimental || GLEW_EXT_texture_object) CONST_CAST(GLEW_EXT_texture_object) = !_glewInit_GL_EXT_texture_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_texture_object */ +#ifdef GL_EXT_texture_perturb_normal + CONST_CAST(GLEW_EXT_texture_perturb_normal) = glewGetExtension("GL_EXT_texture_perturb_normal"); + if (glewExperimental || GLEW_EXT_texture_perturb_normal) CONST_CAST(GLEW_EXT_texture_perturb_normal) = !_glewInit_GL_EXT_texture_perturb_normal(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_texture_perturb_normal */ +#ifdef GL_EXT_texture_rectangle + CONST_CAST(GLEW_EXT_texture_rectangle) = glewGetExtension("GL_EXT_texture_rectangle"); +#endif /* GL_EXT_texture_rectangle */ +#ifdef GL_EXT_texture_sRGB + CONST_CAST(GLEW_EXT_texture_sRGB) = glewGetExtension("GL_EXT_texture_sRGB"); +#endif /* GL_EXT_texture_sRGB */ +#ifdef GL_EXT_texture_shared_exponent + CONST_CAST(GLEW_EXT_texture_shared_exponent) = glewGetExtension("GL_EXT_texture_shared_exponent"); +#endif /* GL_EXT_texture_shared_exponent */ +#ifdef GL_EXT_timer_query + CONST_CAST(GLEW_EXT_timer_query) = glewGetExtension("GL_EXT_timer_query"); + if (glewExperimental || GLEW_EXT_timer_query) CONST_CAST(GLEW_EXT_timer_query) = !_glewInit_GL_EXT_timer_query(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_timer_query */ +#ifdef GL_EXT_vertex_array + CONST_CAST(GLEW_EXT_vertex_array) = glewGetExtension("GL_EXT_vertex_array"); + if (glewExperimental || GLEW_EXT_vertex_array) CONST_CAST(GLEW_EXT_vertex_array) = !_glewInit_GL_EXT_vertex_array(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_vertex_array */ +#ifdef GL_EXT_vertex_shader + CONST_CAST(GLEW_EXT_vertex_shader) = glewGetExtension("GL_EXT_vertex_shader"); + if (glewExperimental || GLEW_EXT_vertex_shader) CONST_CAST(GLEW_EXT_vertex_shader) = !_glewInit_GL_EXT_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_vertex_shader */ +#ifdef GL_EXT_vertex_weighting + CONST_CAST(GLEW_EXT_vertex_weighting) = glewGetExtension("GL_EXT_vertex_weighting"); + if (glewExperimental || GLEW_EXT_vertex_weighting) CONST_CAST(GLEW_EXT_vertex_weighting) = !_glewInit_GL_EXT_vertex_weighting(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_vertex_weighting */ +#ifdef GL_GREMEDY_frame_terminator + CONST_CAST(GLEW_GREMEDY_frame_terminator) = glewGetExtension("GL_GREMEDY_frame_terminator"); + if (glewExperimental || GLEW_GREMEDY_frame_terminator) CONST_CAST(GLEW_GREMEDY_frame_terminator) = !_glewInit_GL_GREMEDY_frame_terminator(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_GREMEDY_frame_terminator */ +#ifdef GL_GREMEDY_string_marker + CONST_CAST(GLEW_GREMEDY_string_marker) = glewGetExtension("GL_GREMEDY_string_marker"); + if (glewExperimental || GLEW_GREMEDY_string_marker) CONST_CAST(GLEW_GREMEDY_string_marker) = !_glewInit_GL_GREMEDY_string_marker(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_GREMEDY_string_marker */ +#ifdef GL_HP_convolution_border_modes + CONST_CAST(GLEW_HP_convolution_border_modes) = glewGetExtension("GL_HP_convolution_border_modes"); +#endif /* GL_HP_convolution_border_modes */ +#ifdef GL_HP_image_transform + CONST_CAST(GLEW_HP_image_transform) = glewGetExtension("GL_HP_image_transform"); + if (glewExperimental || GLEW_HP_image_transform) CONST_CAST(GLEW_HP_image_transform) = !_glewInit_GL_HP_image_transform(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_HP_image_transform */ +#ifdef GL_HP_occlusion_test + CONST_CAST(GLEW_HP_occlusion_test) = glewGetExtension("GL_HP_occlusion_test"); +#endif /* GL_HP_occlusion_test */ +#ifdef GL_HP_texture_lighting + CONST_CAST(GLEW_HP_texture_lighting) = glewGetExtension("GL_HP_texture_lighting"); +#endif /* GL_HP_texture_lighting */ +#ifdef GL_IBM_cull_vertex + CONST_CAST(GLEW_IBM_cull_vertex) = glewGetExtension("GL_IBM_cull_vertex"); +#endif /* GL_IBM_cull_vertex */ +#ifdef GL_IBM_multimode_draw_arrays + CONST_CAST(GLEW_IBM_multimode_draw_arrays) = glewGetExtension("GL_IBM_multimode_draw_arrays"); + if (glewExperimental || GLEW_IBM_multimode_draw_arrays) CONST_CAST(GLEW_IBM_multimode_draw_arrays) = !_glewInit_GL_IBM_multimode_draw_arrays(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_IBM_multimode_draw_arrays */ +#ifdef GL_IBM_rasterpos_clip + CONST_CAST(GLEW_IBM_rasterpos_clip) = glewGetExtension("GL_IBM_rasterpos_clip"); +#endif /* GL_IBM_rasterpos_clip */ +#ifdef GL_IBM_static_data + CONST_CAST(GLEW_IBM_static_data) = glewGetExtension("GL_IBM_static_data"); +#endif /* GL_IBM_static_data */ +#ifdef GL_IBM_texture_mirrored_repeat + CONST_CAST(GLEW_IBM_texture_mirrored_repeat) = glewGetExtension("GL_IBM_texture_mirrored_repeat"); +#endif /* GL_IBM_texture_mirrored_repeat */ +#ifdef GL_IBM_vertex_array_lists + CONST_CAST(GLEW_IBM_vertex_array_lists) = glewGetExtension("GL_IBM_vertex_array_lists"); + if (glewExperimental || GLEW_IBM_vertex_array_lists) CONST_CAST(GLEW_IBM_vertex_array_lists) = !_glewInit_GL_IBM_vertex_array_lists(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_IBM_vertex_array_lists */ +#ifdef GL_INGR_color_clamp + CONST_CAST(GLEW_INGR_color_clamp) = glewGetExtension("GL_INGR_color_clamp"); +#endif /* GL_INGR_color_clamp */ +#ifdef GL_INGR_interlace_read + CONST_CAST(GLEW_INGR_interlace_read) = glewGetExtension("GL_INGR_interlace_read"); +#endif /* GL_INGR_interlace_read */ +#ifdef GL_INTEL_parallel_arrays + CONST_CAST(GLEW_INTEL_parallel_arrays) = glewGetExtension("GL_INTEL_parallel_arrays"); + if (glewExperimental || GLEW_INTEL_parallel_arrays) CONST_CAST(GLEW_INTEL_parallel_arrays) = !_glewInit_GL_INTEL_parallel_arrays(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_INTEL_parallel_arrays */ +#ifdef GL_INTEL_texture_scissor + CONST_CAST(GLEW_INTEL_texture_scissor) = glewGetExtension("GL_INTEL_texture_scissor"); + if (glewExperimental || GLEW_INTEL_texture_scissor) CONST_CAST(GLEW_INTEL_texture_scissor) = !_glewInit_GL_INTEL_texture_scissor(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_INTEL_texture_scissor */ +#ifdef GL_KTX_buffer_region + CONST_CAST(GLEW_KTX_buffer_region) = glewGetExtension("GL_KTX_buffer_region"); + if (glewExperimental || GLEW_KTX_buffer_region) CONST_CAST(GLEW_KTX_buffer_region) = !_glewInit_GL_KTX_buffer_region(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_KTX_buffer_region */ +#ifdef GL_MESAX_texture_stack + CONST_CAST(GLEW_MESAX_texture_stack) = glewGetExtension("GL_MESAX_texture_stack"); +#endif /* GL_MESAX_texture_stack */ +#ifdef GL_MESA_pack_invert + CONST_CAST(GLEW_MESA_pack_invert) = glewGetExtension("GL_MESA_pack_invert"); +#endif /* GL_MESA_pack_invert */ +#ifdef GL_MESA_resize_buffers + CONST_CAST(GLEW_MESA_resize_buffers) = glewGetExtension("GL_MESA_resize_buffers"); + if (glewExperimental || GLEW_MESA_resize_buffers) CONST_CAST(GLEW_MESA_resize_buffers) = !_glewInit_GL_MESA_resize_buffers(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_MESA_resize_buffers */ +#ifdef GL_MESA_window_pos + CONST_CAST(GLEW_MESA_window_pos) = glewGetExtension("GL_MESA_window_pos"); + if (glewExperimental || GLEW_MESA_window_pos) CONST_CAST(GLEW_MESA_window_pos) = !_glewInit_GL_MESA_window_pos(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_MESA_window_pos */ +#ifdef GL_MESA_ycbcr_texture + CONST_CAST(GLEW_MESA_ycbcr_texture) = glewGetExtension("GL_MESA_ycbcr_texture"); +#endif /* GL_MESA_ycbcr_texture */ +#ifdef GL_NV_blend_square + CONST_CAST(GLEW_NV_blend_square) = glewGetExtension("GL_NV_blend_square"); +#endif /* GL_NV_blend_square */ +#ifdef GL_NV_copy_depth_to_color + CONST_CAST(GLEW_NV_copy_depth_to_color) = glewGetExtension("GL_NV_copy_depth_to_color"); +#endif /* GL_NV_copy_depth_to_color */ +#ifdef GL_NV_depth_buffer_float + CONST_CAST(GLEW_NV_depth_buffer_float) = glewGetExtension("GL_NV_depth_buffer_float"); + if (glewExperimental || GLEW_NV_depth_buffer_float) CONST_CAST(GLEW_NV_depth_buffer_float) = !_glewInit_GL_NV_depth_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_depth_buffer_float */ +#ifdef GL_NV_depth_clamp + CONST_CAST(GLEW_NV_depth_clamp) = glewGetExtension("GL_NV_depth_clamp"); +#endif /* GL_NV_depth_clamp */ +#ifdef GL_NV_depth_range_unclamped + CONST_CAST(GLEW_NV_depth_range_unclamped) = glewGetExtension("GL_NV_depth_range_unclamped"); +#endif /* GL_NV_depth_range_unclamped */ +#ifdef GL_NV_evaluators + CONST_CAST(GLEW_NV_evaluators) = glewGetExtension("GL_NV_evaluators"); + if (glewExperimental || GLEW_NV_evaluators) CONST_CAST(GLEW_NV_evaluators) = !_glewInit_GL_NV_evaluators(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_evaluators */ +#ifdef GL_NV_fence + CONST_CAST(GLEW_NV_fence) = glewGetExtension("GL_NV_fence"); + if (glewExperimental || GLEW_NV_fence) CONST_CAST(GLEW_NV_fence) = !_glewInit_GL_NV_fence(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_fence */ +#ifdef GL_NV_float_buffer + CONST_CAST(GLEW_NV_float_buffer) = glewGetExtension("GL_NV_float_buffer"); +#endif /* GL_NV_float_buffer */ +#ifdef GL_NV_fog_distance + CONST_CAST(GLEW_NV_fog_distance) = glewGetExtension("GL_NV_fog_distance"); +#endif /* GL_NV_fog_distance */ +#ifdef GL_NV_fragment_program + CONST_CAST(GLEW_NV_fragment_program) = glewGetExtension("GL_NV_fragment_program"); + if (glewExperimental || GLEW_NV_fragment_program) CONST_CAST(GLEW_NV_fragment_program) = !_glewInit_GL_NV_fragment_program(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_fragment_program */ +#ifdef GL_NV_fragment_program2 + CONST_CAST(GLEW_NV_fragment_program2) = glewGetExtension("GL_NV_fragment_program2"); +#endif /* GL_NV_fragment_program2 */ +#ifdef GL_NV_fragment_program4 + CONST_CAST(GLEW_NV_fragment_program4) = glewGetExtension("GL_NV_fragment_program4"); +#endif /* GL_NV_fragment_program4 */ +#ifdef GL_NV_fragment_program_option + CONST_CAST(GLEW_NV_fragment_program_option) = glewGetExtension("GL_NV_fragment_program_option"); +#endif /* GL_NV_fragment_program_option */ +#ifdef GL_NV_framebuffer_multisample_coverage + CONST_CAST(GLEW_NV_framebuffer_multisample_coverage) = glewGetExtension("GL_NV_framebuffer_multisample_coverage"); + if (glewExperimental || GLEW_NV_framebuffer_multisample_coverage) CONST_CAST(GLEW_NV_framebuffer_multisample_coverage) = !_glewInit_GL_NV_framebuffer_multisample_coverage(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_framebuffer_multisample_coverage */ +#ifdef GL_NV_geometry_program4 + CONST_CAST(GLEW_NV_geometry_program4) = glewGetExtension("GL_NV_geometry_program4"); + if (glewExperimental || GLEW_NV_geometry_program4) CONST_CAST(GLEW_NV_geometry_program4) = !_glewInit_GL_NV_geometry_program4(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_geometry_program4 */ +#ifdef GL_NV_geometry_shader4 + CONST_CAST(GLEW_NV_geometry_shader4) = glewGetExtension("GL_NV_geometry_shader4"); +#endif /* GL_NV_geometry_shader4 */ +#ifdef GL_NV_gpu_program4 + CONST_CAST(GLEW_NV_gpu_program4) = glewGetExtension("GL_NV_gpu_program4"); + if (glewExperimental || GLEW_NV_gpu_program4) CONST_CAST(GLEW_NV_gpu_program4) = !_glewInit_GL_NV_gpu_program4(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_gpu_program4 */ +#ifdef GL_NV_half_float + CONST_CAST(GLEW_NV_half_float) = glewGetExtension("GL_NV_half_float"); + if (glewExperimental || GLEW_NV_half_float) CONST_CAST(GLEW_NV_half_float) = !_glewInit_GL_NV_half_float(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_half_float */ +#ifdef GL_NV_light_max_exponent + CONST_CAST(GLEW_NV_light_max_exponent) = glewGetExtension("GL_NV_light_max_exponent"); +#endif /* GL_NV_light_max_exponent */ +#ifdef GL_NV_multisample_filter_hint + CONST_CAST(GLEW_NV_multisample_filter_hint) = glewGetExtension("GL_NV_multisample_filter_hint"); +#endif /* GL_NV_multisample_filter_hint */ +#ifdef GL_NV_occlusion_query + CONST_CAST(GLEW_NV_occlusion_query) = glewGetExtension("GL_NV_occlusion_query"); + if (glewExperimental || GLEW_NV_occlusion_query) CONST_CAST(GLEW_NV_occlusion_query) = !_glewInit_GL_NV_occlusion_query(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_occlusion_query */ +#ifdef GL_NV_packed_depth_stencil + CONST_CAST(GLEW_NV_packed_depth_stencil) = glewGetExtension("GL_NV_packed_depth_stencil"); +#endif /* GL_NV_packed_depth_stencil */ +#ifdef GL_NV_parameter_buffer_object + CONST_CAST(GLEW_NV_parameter_buffer_object) = glewGetExtension("GL_NV_parameter_buffer_object"); + if (glewExperimental || GLEW_NV_parameter_buffer_object) CONST_CAST(GLEW_NV_parameter_buffer_object) = !_glewInit_GL_NV_parameter_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_parameter_buffer_object */ +#ifdef GL_NV_pixel_data_range + CONST_CAST(GLEW_NV_pixel_data_range) = glewGetExtension("GL_NV_pixel_data_range"); + if (glewExperimental || GLEW_NV_pixel_data_range) CONST_CAST(GLEW_NV_pixel_data_range) = !_glewInit_GL_NV_pixel_data_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_pixel_data_range */ +#ifdef GL_NV_point_sprite + CONST_CAST(GLEW_NV_point_sprite) = glewGetExtension("GL_NV_point_sprite"); + if (glewExperimental || GLEW_NV_point_sprite) CONST_CAST(GLEW_NV_point_sprite) = !_glewInit_GL_NV_point_sprite(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_point_sprite */ +#ifdef GL_NV_primitive_restart + CONST_CAST(GLEW_NV_primitive_restart) = glewGetExtension("GL_NV_primitive_restart"); + if (glewExperimental || GLEW_NV_primitive_restart) CONST_CAST(GLEW_NV_primitive_restart) = !_glewInit_GL_NV_primitive_restart(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_primitive_restart */ +#ifdef GL_NV_register_combiners + CONST_CAST(GLEW_NV_register_combiners) = glewGetExtension("GL_NV_register_combiners"); + if (glewExperimental || GLEW_NV_register_combiners) CONST_CAST(GLEW_NV_register_combiners) = !_glewInit_GL_NV_register_combiners(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_register_combiners */ +#ifdef GL_NV_register_combiners2 + CONST_CAST(GLEW_NV_register_combiners2) = glewGetExtension("GL_NV_register_combiners2"); + if (glewExperimental || GLEW_NV_register_combiners2) CONST_CAST(GLEW_NV_register_combiners2) = !_glewInit_GL_NV_register_combiners2(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_register_combiners2 */ +#ifdef GL_NV_texgen_emboss + CONST_CAST(GLEW_NV_texgen_emboss) = glewGetExtension("GL_NV_texgen_emboss"); +#endif /* GL_NV_texgen_emboss */ +#ifdef GL_NV_texgen_reflection + CONST_CAST(GLEW_NV_texgen_reflection) = glewGetExtension("GL_NV_texgen_reflection"); +#endif /* GL_NV_texgen_reflection */ +#ifdef GL_NV_texture_compression_vtc + CONST_CAST(GLEW_NV_texture_compression_vtc) = glewGetExtension("GL_NV_texture_compression_vtc"); +#endif /* GL_NV_texture_compression_vtc */ +#ifdef GL_NV_texture_env_combine4 + CONST_CAST(GLEW_NV_texture_env_combine4) = glewGetExtension("GL_NV_texture_env_combine4"); +#endif /* GL_NV_texture_env_combine4 */ +#ifdef GL_NV_texture_expand_normal + CONST_CAST(GLEW_NV_texture_expand_normal) = glewGetExtension("GL_NV_texture_expand_normal"); +#endif /* GL_NV_texture_expand_normal */ +#ifdef GL_NV_texture_rectangle + CONST_CAST(GLEW_NV_texture_rectangle) = glewGetExtension("GL_NV_texture_rectangle"); +#endif /* GL_NV_texture_rectangle */ +#ifdef GL_NV_texture_shader + CONST_CAST(GLEW_NV_texture_shader) = glewGetExtension("GL_NV_texture_shader"); +#endif /* GL_NV_texture_shader */ +#ifdef GL_NV_texture_shader2 + CONST_CAST(GLEW_NV_texture_shader2) = glewGetExtension("GL_NV_texture_shader2"); +#endif /* GL_NV_texture_shader2 */ +#ifdef GL_NV_texture_shader3 + CONST_CAST(GLEW_NV_texture_shader3) = glewGetExtension("GL_NV_texture_shader3"); +#endif /* GL_NV_texture_shader3 */ +#ifdef GL_NV_transform_feedback + CONST_CAST(GLEW_NV_transform_feedback) = glewGetExtension("GL_NV_transform_feedback"); + if (glewExperimental || GLEW_NV_transform_feedback) CONST_CAST(GLEW_NV_transform_feedback) = !_glewInit_GL_NV_transform_feedback(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_transform_feedback */ +#ifdef GL_NV_vertex_array_range + CONST_CAST(GLEW_NV_vertex_array_range) = glewGetExtension("GL_NV_vertex_array_range"); + if (glewExperimental || GLEW_NV_vertex_array_range) CONST_CAST(GLEW_NV_vertex_array_range) = !_glewInit_GL_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_vertex_array_range */ +#ifdef GL_NV_vertex_array_range2 + CONST_CAST(GLEW_NV_vertex_array_range2) = glewGetExtension("GL_NV_vertex_array_range2"); +#endif /* GL_NV_vertex_array_range2 */ +#ifdef GL_NV_vertex_program + CONST_CAST(GLEW_NV_vertex_program) = glewGetExtension("GL_NV_vertex_program"); + if (glewExperimental || GLEW_NV_vertex_program) CONST_CAST(GLEW_NV_vertex_program) = !_glewInit_GL_NV_vertex_program(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_vertex_program */ +#ifdef GL_NV_vertex_program1_1 + CONST_CAST(GLEW_NV_vertex_program1_1) = glewGetExtension("GL_NV_vertex_program1_1"); +#endif /* GL_NV_vertex_program1_1 */ +#ifdef GL_NV_vertex_program2 + CONST_CAST(GLEW_NV_vertex_program2) = glewGetExtension("GL_NV_vertex_program2"); +#endif /* GL_NV_vertex_program2 */ +#ifdef GL_NV_vertex_program2_option + CONST_CAST(GLEW_NV_vertex_program2_option) = glewGetExtension("GL_NV_vertex_program2_option"); +#endif /* GL_NV_vertex_program2_option */ +#ifdef GL_NV_vertex_program3 + CONST_CAST(GLEW_NV_vertex_program3) = glewGetExtension("GL_NV_vertex_program3"); +#endif /* GL_NV_vertex_program3 */ +#ifdef GL_NV_vertex_program4 + CONST_CAST(GLEW_NV_vertex_program4) = glewGetExtension("GL_NV_vertex_program4"); +#endif /* GL_NV_vertex_program4 */ +#ifdef GL_OES_byte_coordinates + CONST_CAST(GLEW_OES_byte_coordinates) = glewGetExtension("GL_OES_byte_coordinates"); +#endif /* GL_OES_byte_coordinates */ +#ifdef GL_OES_compressed_paletted_texture + CONST_CAST(GLEW_OES_compressed_paletted_texture) = glewGetExtension("GL_OES_compressed_paletted_texture"); +#endif /* GL_OES_compressed_paletted_texture */ +#ifdef GL_OES_read_format + CONST_CAST(GLEW_OES_read_format) = glewGetExtension("GL_OES_read_format"); +#endif /* GL_OES_read_format */ +#ifdef GL_OES_single_precision + CONST_CAST(GLEW_OES_single_precision) = glewGetExtension("GL_OES_single_precision"); + if (glewExperimental || GLEW_OES_single_precision) CONST_CAST(GLEW_OES_single_precision) = !_glewInit_GL_OES_single_precision(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_OES_single_precision */ +#ifdef GL_OML_interlace + CONST_CAST(GLEW_OML_interlace) = glewGetExtension("GL_OML_interlace"); +#endif /* GL_OML_interlace */ +#ifdef GL_OML_resample + CONST_CAST(GLEW_OML_resample) = glewGetExtension("GL_OML_resample"); +#endif /* GL_OML_resample */ +#ifdef GL_OML_subsample + CONST_CAST(GLEW_OML_subsample) = glewGetExtension("GL_OML_subsample"); +#endif /* GL_OML_subsample */ +#ifdef GL_PGI_misc_hints + CONST_CAST(GLEW_PGI_misc_hints) = glewGetExtension("GL_PGI_misc_hints"); +#endif /* GL_PGI_misc_hints */ +#ifdef GL_PGI_vertex_hints + CONST_CAST(GLEW_PGI_vertex_hints) = glewGetExtension("GL_PGI_vertex_hints"); +#endif /* GL_PGI_vertex_hints */ +#ifdef GL_REND_screen_coordinates + CONST_CAST(GLEW_REND_screen_coordinates) = glewGetExtension("GL_REND_screen_coordinates"); +#endif /* GL_REND_screen_coordinates */ +#ifdef GL_S3_s3tc + CONST_CAST(GLEW_S3_s3tc) = glewGetExtension("GL_S3_s3tc"); +#endif /* GL_S3_s3tc */ +#ifdef GL_SGIS_color_range + CONST_CAST(GLEW_SGIS_color_range) = glewGetExtension("GL_SGIS_color_range"); +#endif /* GL_SGIS_color_range */ +#ifdef GL_SGIS_detail_texture + CONST_CAST(GLEW_SGIS_detail_texture) = glewGetExtension("GL_SGIS_detail_texture"); + if (glewExperimental || GLEW_SGIS_detail_texture) CONST_CAST(GLEW_SGIS_detail_texture) = !_glewInit_GL_SGIS_detail_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIS_detail_texture */ +#ifdef GL_SGIS_fog_function + CONST_CAST(GLEW_SGIS_fog_function) = glewGetExtension("GL_SGIS_fog_function"); + if (glewExperimental || GLEW_SGIS_fog_function) CONST_CAST(GLEW_SGIS_fog_function) = !_glewInit_GL_SGIS_fog_function(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIS_fog_function */ +#ifdef GL_SGIS_generate_mipmap + CONST_CAST(GLEW_SGIS_generate_mipmap) = glewGetExtension("GL_SGIS_generate_mipmap"); +#endif /* GL_SGIS_generate_mipmap */ +#ifdef GL_SGIS_multisample + CONST_CAST(GLEW_SGIS_multisample) = glewGetExtension("GL_SGIS_multisample"); + if (glewExperimental || GLEW_SGIS_multisample) CONST_CAST(GLEW_SGIS_multisample) = !_glewInit_GL_SGIS_multisample(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIS_multisample */ +#ifdef GL_SGIS_pixel_texture + CONST_CAST(GLEW_SGIS_pixel_texture) = glewGetExtension("GL_SGIS_pixel_texture"); +#endif /* GL_SGIS_pixel_texture */ +#ifdef GL_SGIS_sharpen_texture + CONST_CAST(GLEW_SGIS_sharpen_texture) = glewGetExtension("GL_SGIS_sharpen_texture"); + if (glewExperimental || GLEW_SGIS_sharpen_texture) CONST_CAST(GLEW_SGIS_sharpen_texture) = !_glewInit_GL_SGIS_sharpen_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIS_sharpen_texture */ +#ifdef GL_SGIS_texture4D + CONST_CAST(GLEW_SGIS_texture4D) = glewGetExtension("GL_SGIS_texture4D"); + if (glewExperimental || GLEW_SGIS_texture4D) CONST_CAST(GLEW_SGIS_texture4D) = !_glewInit_GL_SGIS_texture4D(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIS_texture4D */ +#ifdef GL_SGIS_texture_border_clamp + CONST_CAST(GLEW_SGIS_texture_border_clamp) = glewGetExtension("GL_SGIS_texture_border_clamp"); +#endif /* GL_SGIS_texture_border_clamp */ +#ifdef GL_SGIS_texture_edge_clamp + CONST_CAST(GLEW_SGIS_texture_edge_clamp) = glewGetExtension("GL_SGIS_texture_edge_clamp"); +#endif /* GL_SGIS_texture_edge_clamp */ +#ifdef GL_SGIS_texture_filter4 + CONST_CAST(GLEW_SGIS_texture_filter4) = glewGetExtension("GL_SGIS_texture_filter4"); + if (glewExperimental || GLEW_SGIS_texture_filter4) CONST_CAST(GLEW_SGIS_texture_filter4) = !_glewInit_GL_SGIS_texture_filter4(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIS_texture_filter4 */ +#ifdef GL_SGIS_texture_lod + CONST_CAST(GLEW_SGIS_texture_lod) = glewGetExtension("GL_SGIS_texture_lod"); +#endif /* GL_SGIS_texture_lod */ +#ifdef GL_SGIS_texture_select + CONST_CAST(GLEW_SGIS_texture_select) = glewGetExtension("GL_SGIS_texture_select"); +#endif /* GL_SGIS_texture_select */ +#ifdef GL_SGIX_async + CONST_CAST(GLEW_SGIX_async) = glewGetExtension("GL_SGIX_async"); + if (glewExperimental || GLEW_SGIX_async) CONST_CAST(GLEW_SGIX_async) = !_glewInit_GL_SGIX_async(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_async */ +#ifdef GL_SGIX_async_histogram + CONST_CAST(GLEW_SGIX_async_histogram) = glewGetExtension("GL_SGIX_async_histogram"); +#endif /* GL_SGIX_async_histogram */ +#ifdef GL_SGIX_async_pixel + CONST_CAST(GLEW_SGIX_async_pixel) = glewGetExtension("GL_SGIX_async_pixel"); +#endif /* GL_SGIX_async_pixel */ +#ifdef GL_SGIX_blend_alpha_minmax + CONST_CAST(GLEW_SGIX_blend_alpha_minmax) = glewGetExtension("GL_SGIX_blend_alpha_minmax"); +#endif /* GL_SGIX_blend_alpha_minmax */ +#ifdef GL_SGIX_clipmap + CONST_CAST(GLEW_SGIX_clipmap) = glewGetExtension("GL_SGIX_clipmap"); +#endif /* GL_SGIX_clipmap */ +#ifdef GL_SGIX_depth_texture + CONST_CAST(GLEW_SGIX_depth_texture) = glewGetExtension("GL_SGIX_depth_texture"); +#endif /* GL_SGIX_depth_texture */ +#ifdef GL_SGIX_flush_raster + CONST_CAST(GLEW_SGIX_flush_raster) = glewGetExtension("GL_SGIX_flush_raster"); + if (glewExperimental || GLEW_SGIX_flush_raster) CONST_CAST(GLEW_SGIX_flush_raster) = !_glewInit_GL_SGIX_flush_raster(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_flush_raster */ +#ifdef GL_SGIX_fog_offset + CONST_CAST(GLEW_SGIX_fog_offset) = glewGetExtension("GL_SGIX_fog_offset"); +#endif /* GL_SGIX_fog_offset */ +#ifdef GL_SGIX_fog_texture + CONST_CAST(GLEW_SGIX_fog_texture) = glewGetExtension("GL_SGIX_fog_texture"); + if (glewExperimental || GLEW_SGIX_fog_texture) CONST_CAST(GLEW_SGIX_fog_texture) = !_glewInit_GL_SGIX_fog_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_fog_texture */ +#ifdef GL_SGIX_fragment_specular_lighting + CONST_CAST(GLEW_SGIX_fragment_specular_lighting) = glewGetExtension("GL_SGIX_fragment_specular_lighting"); + if (glewExperimental || GLEW_SGIX_fragment_specular_lighting) CONST_CAST(GLEW_SGIX_fragment_specular_lighting) = !_glewInit_GL_SGIX_fragment_specular_lighting(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_fragment_specular_lighting */ +#ifdef GL_SGIX_framezoom + CONST_CAST(GLEW_SGIX_framezoom) = glewGetExtension("GL_SGIX_framezoom"); + if (glewExperimental || GLEW_SGIX_framezoom) CONST_CAST(GLEW_SGIX_framezoom) = !_glewInit_GL_SGIX_framezoom(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_framezoom */ +#ifdef GL_SGIX_interlace + CONST_CAST(GLEW_SGIX_interlace) = glewGetExtension("GL_SGIX_interlace"); +#endif /* GL_SGIX_interlace */ +#ifdef GL_SGIX_ir_instrument1 + CONST_CAST(GLEW_SGIX_ir_instrument1) = glewGetExtension("GL_SGIX_ir_instrument1"); +#endif /* GL_SGIX_ir_instrument1 */ +#ifdef GL_SGIX_list_priority + CONST_CAST(GLEW_SGIX_list_priority) = glewGetExtension("GL_SGIX_list_priority"); +#endif /* GL_SGIX_list_priority */ +#ifdef GL_SGIX_pixel_texture + CONST_CAST(GLEW_SGIX_pixel_texture) = glewGetExtension("GL_SGIX_pixel_texture"); + if (glewExperimental || GLEW_SGIX_pixel_texture) CONST_CAST(GLEW_SGIX_pixel_texture) = !_glewInit_GL_SGIX_pixel_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_pixel_texture */ +#ifdef GL_SGIX_pixel_texture_bits + CONST_CAST(GLEW_SGIX_pixel_texture_bits) = glewGetExtension("GL_SGIX_pixel_texture_bits"); +#endif /* GL_SGIX_pixel_texture_bits */ +#ifdef GL_SGIX_reference_plane + CONST_CAST(GLEW_SGIX_reference_plane) = glewGetExtension("GL_SGIX_reference_plane"); + if (glewExperimental || GLEW_SGIX_reference_plane) CONST_CAST(GLEW_SGIX_reference_plane) = !_glewInit_GL_SGIX_reference_plane(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_reference_plane */ +#ifdef GL_SGIX_resample + CONST_CAST(GLEW_SGIX_resample) = glewGetExtension("GL_SGIX_resample"); +#endif /* GL_SGIX_resample */ +#ifdef GL_SGIX_shadow + CONST_CAST(GLEW_SGIX_shadow) = glewGetExtension("GL_SGIX_shadow"); +#endif /* GL_SGIX_shadow */ +#ifdef GL_SGIX_shadow_ambient + CONST_CAST(GLEW_SGIX_shadow_ambient) = glewGetExtension("GL_SGIX_shadow_ambient"); +#endif /* GL_SGIX_shadow_ambient */ +#ifdef GL_SGIX_sprite + CONST_CAST(GLEW_SGIX_sprite) = glewGetExtension("GL_SGIX_sprite"); + if (glewExperimental || GLEW_SGIX_sprite) CONST_CAST(GLEW_SGIX_sprite) = !_glewInit_GL_SGIX_sprite(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_sprite */ +#ifdef GL_SGIX_tag_sample_buffer + CONST_CAST(GLEW_SGIX_tag_sample_buffer) = glewGetExtension("GL_SGIX_tag_sample_buffer"); + if (glewExperimental || GLEW_SGIX_tag_sample_buffer) CONST_CAST(GLEW_SGIX_tag_sample_buffer) = !_glewInit_GL_SGIX_tag_sample_buffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_tag_sample_buffer */ +#ifdef GL_SGIX_texture_add_env + CONST_CAST(GLEW_SGIX_texture_add_env) = glewGetExtension("GL_SGIX_texture_add_env"); +#endif /* GL_SGIX_texture_add_env */ +#ifdef GL_SGIX_texture_coordinate_clamp + CONST_CAST(GLEW_SGIX_texture_coordinate_clamp) = glewGetExtension("GL_SGIX_texture_coordinate_clamp"); +#endif /* GL_SGIX_texture_coordinate_clamp */ +#ifdef GL_SGIX_texture_lod_bias + CONST_CAST(GLEW_SGIX_texture_lod_bias) = glewGetExtension("GL_SGIX_texture_lod_bias"); +#endif /* GL_SGIX_texture_lod_bias */ +#ifdef GL_SGIX_texture_multi_buffer + CONST_CAST(GLEW_SGIX_texture_multi_buffer) = glewGetExtension("GL_SGIX_texture_multi_buffer"); +#endif /* GL_SGIX_texture_multi_buffer */ +#ifdef GL_SGIX_texture_range + CONST_CAST(GLEW_SGIX_texture_range) = glewGetExtension("GL_SGIX_texture_range"); +#endif /* GL_SGIX_texture_range */ +#ifdef GL_SGIX_texture_scale_bias + CONST_CAST(GLEW_SGIX_texture_scale_bias) = glewGetExtension("GL_SGIX_texture_scale_bias"); +#endif /* GL_SGIX_texture_scale_bias */ +#ifdef GL_SGIX_vertex_preclip + CONST_CAST(GLEW_SGIX_vertex_preclip) = glewGetExtension("GL_SGIX_vertex_preclip"); +#endif /* GL_SGIX_vertex_preclip */ +#ifdef GL_SGIX_vertex_preclip_hint + CONST_CAST(GLEW_SGIX_vertex_preclip_hint) = glewGetExtension("GL_SGIX_vertex_preclip_hint"); +#endif /* GL_SGIX_vertex_preclip_hint */ +#ifdef GL_SGIX_ycrcb + CONST_CAST(GLEW_SGIX_ycrcb) = glewGetExtension("GL_SGIX_ycrcb"); +#endif /* GL_SGIX_ycrcb */ +#ifdef GL_SGI_color_matrix + CONST_CAST(GLEW_SGI_color_matrix) = glewGetExtension("GL_SGI_color_matrix"); +#endif /* GL_SGI_color_matrix */ +#ifdef GL_SGI_color_table + CONST_CAST(GLEW_SGI_color_table) = glewGetExtension("GL_SGI_color_table"); + if (glewExperimental || GLEW_SGI_color_table) CONST_CAST(GLEW_SGI_color_table) = !_glewInit_GL_SGI_color_table(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGI_color_table */ +#ifdef GL_SGI_texture_color_table + CONST_CAST(GLEW_SGI_texture_color_table) = glewGetExtension("GL_SGI_texture_color_table"); +#endif /* GL_SGI_texture_color_table */ +#ifdef GL_SUNX_constant_data + CONST_CAST(GLEW_SUNX_constant_data) = glewGetExtension("GL_SUNX_constant_data"); + if (glewExperimental || GLEW_SUNX_constant_data) CONST_CAST(GLEW_SUNX_constant_data) = !_glewInit_GL_SUNX_constant_data(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SUNX_constant_data */ +#ifdef GL_SUN_convolution_border_modes + CONST_CAST(GLEW_SUN_convolution_border_modes) = glewGetExtension("GL_SUN_convolution_border_modes"); +#endif /* GL_SUN_convolution_border_modes */ +#ifdef GL_SUN_global_alpha + CONST_CAST(GLEW_SUN_global_alpha) = glewGetExtension("GL_SUN_global_alpha"); + if (glewExperimental || GLEW_SUN_global_alpha) CONST_CAST(GLEW_SUN_global_alpha) = !_glewInit_GL_SUN_global_alpha(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SUN_global_alpha */ +#ifdef GL_SUN_mesh_array + CONST_CAST(GLEW_SUN_mesh_array) = glewGetExtension("GL_SUN_mesh_array"); +#endif /* GL_SUN_mesh_array */ +#ifdef GL_SUN_read_video_pixels + CONST_CAST(GLEW_SUN_read_video_pixels) = glewGetExtension("GL_SUN_read_video_pixels"); + if (glewExperimental || GLEW_SUN_read_video_pixels) CONST_CAST(GLEW_SUN_read_video_pixels) = !_glewInit_GL_SUN_read_video_pixels(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SUN_read_video_pixels */ +#ifdef GL_SUN_slice_accum + CONST_CAST(GLEW_SUN_slice_accum) = glewGetExtension("GL_SUN_slice_accum"); +#endif /* GL_SUN_slice_accum */ +#ifdef GL_SUN_triangle_list + CONST_CAST(GLEW_SUN_triangle_list) = glewGetExtension("GL_SUN_triangle_list"); + if (glewExperimental || GLEW_SUN_triangle_list) CONST_CAST(GLEW_SUN_triangle_list) = !_glewInit_GL_SUN_triangle_list(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SUN_triangle_list */ +#ifdef GL_SUN_vertex + CONST_CAST(GLEW_SUN_vertex) = glewGetExtension("GL_SUN_vertex"); + if (glewExperimental || GLEW_SUN_vertex) CONST_CAST(GLEW_SUN_vertex) = !_glewInit_GL_SUN_vertex(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SUN_vertex */ +#ifdef GL_WIN_phong_shading + CONST_CAST(GLEW_WIN_phong_shading) = glewGetExtension("GL_WIN_phong_shading"); +#endif /* GL_WIN_phong_shading */ +#ifdef GL_WIN_specular_fog + CONST_CAST(GLEW_WIN_specular_fog) = glewGetExtension("GL_WIN_specular_fog"); +#endif /* GL_WIN_specular_fog */ +#ifdef GL_WIN_swap_hint + CONST_CAST(GLEW_WIN_swap_hint) = glewGetExtension("GL_WIN_swap_hint"); + if (glewExperimental || GLEW_WIN_swap_hint) CONST_CAST(GLEW_WIN_swap_hint) = !_glewInit_GL_WIN_swap_hint(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_WIN_swap_hint */ + + return GLEW_OK; +} + + +#if defined(_WIN32) + +#if !defined(GLEW_MX) + +PFNWGLSETSTEREOEMITTERSTATE3DLPROC __wglewSetStereoEmitterState3DL = NULL; + +PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB = NULL; +PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB = NULL; +PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB = NULL; +PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB = NULL; + +PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB = NULL; + +PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB = NULL; +PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB = NULL; + +PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB = NULL; +PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB = NULL; +PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB = NULL; +PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB = NULL; +PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB = NULL; + +PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB = NULL; +PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB = NULL; +PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB = NULL; + +PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB = NULL; +PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB = NULL; +PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB = NULL; + +PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT = NULL; +PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT = NULL; +PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT = NULL; +PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT = NULL; + +PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT = NULL; + +PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT = NULL; +PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT = NULL; + +PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT = NULL; +PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT = NULL; +PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT = NULL; +PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT = NULL; +PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT = NULL; + +PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT = NULL; +PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT = NULL; +PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT = NULL; + +PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT = NULL; +PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT = NULL; + +PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D = NULL; +PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D = NULL; + +PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D = NULL; +PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D = NULL; +PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D = NULL; +PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D = NULL; + +PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D = NULL; +PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D = NULL; +PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D = NULL; +PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D = NULL; +PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D = NULL; +PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D = NULL; +PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D = NULL; +PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D = NULL; +PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D = NULL; +PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D = NULL; +PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D = NULL; +PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D = NULL; + +PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D = NULL; +PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D = NULL; +PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D = NULL; +PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D = NULL; + +PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D = NULL; +PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D = NULL; +PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D = NULL; +PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D = NULL; + +PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D = NULL; +PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D = NULL; +PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D = NULL; +PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D = NULL; + +PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV = NULL; +PFNWGLDELETEDCNVPROC __wglewDeleteDCNV = NULL; +PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV = NULL; +PFNWGLENUMGPUSFROMAFFINITYDCNVPROC __wglewEnumGpusFromAffinityDCNV = NULL; +PFNWGLENUMGPUSNVPROC __wglewEnumGpusNV = NULL; + +PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV = NULL; +PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV = NULL; + +PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML = NULL; +PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML = NULL; +PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML = NULL; +PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML = NULL; +PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML = NULL; +PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML = NULL; +GLboolean __WGLEW_3DFX_multisample = GL_FALSE; +GLboolean __WGLEW_3DL_stereo_control = GL_FALSE; +GLboolean __WGLEW_ARB_buffer_region = GL_FALSE; +GLboolean __WGLEW_ARB_extensions_string = GL_FALSE; +GLboolean __WGLEW_ARB_make_current_read = GL_FALSE; +GLboolean __WGLEW_ARB_multisample = GL_FALSE; +GLboolean __WGLEW_ARB_pbuffer = GL_FALSE; +GLboolean __WGLEW_ARB_pixel_format = GL_FALSE; +GLboolean __WGLEW_ARB_pixel_format_float = GL_FALSE; +GLboolean __WGLEW_ARB_render_texture = GL_FALSE; +GLboolean __WGLEW_ATI_pixel_format_float = GL_FALSE; +GLboolean __WGLEW_ATI_render_texture_rectangle = GL_FALSE; +GLboolean __WGLEW_EXT_depth_float = GL_FALSE; +GLboolean __WGLEW_EXT_display_color_table = GL_FALSE; +GLboolean __WGLEW_EXT_extensions_string = GL_FALSE; +GLboolean __WGLEW_EXT_framebuffer_sRGB = GL_FALSE; +GLboolean __WGLEW_EXT_make_current_read = GL_FALSE; +GLboolean __WGLEW_EXT_multisample = GL_FALSE; +GLboolean __WGLEW_EXT_pbuffer = GL_FALSE; +GLboolean __WGLEW_EXT_pixel_format = GL_FALSE; +GLboolean __WGLEW_EXT_pixel_format_packed_float = GL_FALSE; +GLboolean __WGLEW_EXT_swap_control = GL_FALSE; +GLboolean __WGLEW_I3D_digital_video_control = GL_FALSE; +GLboolean __WGLEW_I3D_gamma = GL_FALSE; +GLboolean __WGLEW_I3D_genlock = GL_FALSE; +GLboolean __WGLEW_I3D_image_buffer = GL_FALSE; +GLboolean __WGLEW_I3D_swap_frame_lock = GL_FALSE; +GLboolean __WGLEW_I3D_swap_frame_usage = GL_FALSE; +GLboolean __WGLEW_NV_float_buffer = GL_FALSE; +GLboolean __WGLEW_NV_gpu_affinity = GL_FALSE; +GLboolean __WGLEW_NV_render_depth_texture = GL_FALSE; +GLboolean __WGLEW_NV_render_texture_rectangle = GL_FALSE; +GLboolean __WGLEW_NV_vertex_array_range = GL_FALSE; +GLboolean __WGLEW_OML_sync_control = GL_FALSE; + +#endif /* !GLEW_MX */ + +#ifdef WGL_3DFX_multisample + +#endif /* WGL_3DFX_multisample */ + +#ifdef WGL_3DL_stereo_control + +static GLboolean _glewInit_WGL_3DL_stereo_control (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglSetStereoEmitterState3DL = (PFNWGLSETSTEREOEMITTERSTATE3DLPROC)glewGetProcAddress((const GLubyte*)"wglSetStereoEmitterState3DL")) == NULL) || r; + + return r; +} + +#endif /* WGL_3DL_stereo_control */ + +#ifdef WGL_ARB_buffer_region + +static GLboolean _glewInit_WGL_ARB_buffer_region (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglCreateBufferRegionARB = (PFNWGLCREATEBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglCreateBufferRegionARB")) == NULL) || r; + r = ((wglDeleteBufferRegionARB = (PFNWGLDELETEBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglDeleteBufferRegionARB")) == NULL) || r; + r = ((wglRestoreBufferRegionARB = (PFNWGLRESTOREBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglRestoreBufferRegionARB")) == NULL) || r; + r = ((wglSaveBufferRegionARB = (PFNWGLSAVEBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglSaveBufferRegionARB")) == NULL) || r; + + return r; +} + +#endif /* WGL_ARB_buffer_region */ + +#ifdef WGL_ARB_extensions_string + +static GLboolean _glewInit_WGL_ARB_extensions_string (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringARB")) == NULL) || r; + + return r; +} + +#endif /* WGL_ARB_extensions_string */ + +#ifdef WGL_ARB_make_current_read + +static GLboolean _glewInit_WGL_ARB_make_current_read (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetCurrentReadDCARB = (PFNWGLGETCURRENTREADDCARBPROC)glewGetProcAddress((const GLubyte*)"wglGetCurrentReadDCARB")) == NULL) || r; + r = ((wglMakeContextCurrentARB = (PFNWGLMAKECONTEXTCURRENTARBPROC)glewGetProcAddress((const GLubyte*)"wglMakeContextCurrentARB")) == NULL) || r; + + return r; +} + +#endif /* WGL_ARB_make_current_read */ + +#ifdef WGL_ARB_multisample + +#endif /* WGL_ARB_multisample */ + +#ifdef WGL_ARB_pbuffer + +static GLboolean _glewInit_WGL_ARB_pbuffer (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"wglCreatePbufferARB")) == NULL) || r; + r = ((wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"wglDestroyPbufferARB")) == NULL) || r; + r = ((wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC)glewGetProcAddress((const GLubyte*)"wglGetPbufferDCARB")) == NULL) || r; + r = ((wglQueryPbufferARB = (PFNWGLQUERYPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"wglQueryPbufferARB")) == NULL) || r; + r = ((wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC)glewGetProcAddress((const GLubyte*)"wglReleasePbufferDCARB")) == NULL) || r; + + return r; +} + +#endif /* WGL_ARB_pbuffer */ + +#ifdef WGL_ARB_pixel_format + +static GLboolean _glewInit_WGL_ARB_pixel_format (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)glewGetProcAddress((const GLubyte*)"wglChoosePixelFormatARB")) == NULL) || r; + r = ((wglGetPixelFormatAttribfvARB = (PFNWGLGETPIXELFORMATATTRIBFVARBPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribfvARB")) == NULL) || r; + r = ((wglGetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribivARB")) == NULL) || r; + + return r; +} + +#endif /* WGL_ARB_pixel_format */ + +#ifdef WGL_ARB_pixel_format_float + +#endif /* WGL_ARB_pixel_format_float */ + +#ifdef WGL_ARB_render_texture + +static GLboolean _glewInit_WGL_ARB_render_texture (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglBindTexImageARB = (PFNWGLBINDTEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"wglBindTexImageARB")) == NULL) || r; + r = ((wglReleaseTexImageARB = (PFNWGLRELEASETEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"wglReleaseTexImageARB")) == NULL) || r; + r = ((wglSetPbufferAttribARB = (PFNWGLSETPBUFFERATTRIBARBPROC)glewGetProcAddress((const GLubyte*)"wglSetPbufferAttribARB")) == NULL) || r; + + return r; +} + +#endif /* WGL_ARB_render_texture */ + +#ifdef WGL_ATI_pixel_format_float + +#endif /* WGL_ATI_pixel_format_float */ + +#ifdef WGL_ATI_render_texture_rectangle + +#endif /* WGL_ATI_render_texture_rectangle */ + +#ifdef WGL_EXT_depth_float + +#endif /* WGL_EXT_depth_float */ + +#ifdef WGL_EXT_display_color_table + +static GLboolean _glewInit_WGL_EXT_display_color_table (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglBindDisplayColorTableEXT = (PFNWGLBINDDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglBindDisplayColorTableEXT")) == NULL) || r; + r = ((wglCreateDisplayColorTableEXT = (PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglCreateDisplayColorTableEXT")) == NULL) || r; + r = ((wglDestroyDisplayColorTableEXT = (PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglDestroyDisplayColorTableEXT")) == NULL) || r; + r = ((wglLoadDisplayColorTableEXT = (PFNWGLLOADDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglLoadDisplayColorTableEXT")) == NULL) || r; + + return r; +} + +#endif /* WGL_EXT_display_color_table */ + +#ifdef WGL_EXT_extensions_string + +static GLboolean _glewInit_WGL_EXT_extensions_string (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringEXT")) == NULL) || r; + + return r; +} + +#endif /* WGL_EXT_extensions_string */ + +#ifdef WGL_EXT_framebuffer_sRGB + +#endif /* WGL_EXT_framebuffer_sRGB */ + +#ifdef WGL_EXT_make_current_read + +static GLboolean _glewInit_WGL_EXT_make_current_read (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetCurrentReadDCEXT = (PFNWGLGETCURRENTREADDCEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetCurrentReadDCEXT")) == NULL) || r; + r = ((wglMakeContextCurrentEXT = (PFNWGLMAKECONTEXTCURRENTEXTPROC)glewGetProcAddress((const GLubyte*)"wglMakeContextCurrentEXT")) == NULL) || r; + + return r; +} + +#endif /* WGL_EXT_make_current_read */ + +#ifdef WGL_EXT_multisample + +#endif /* WGL_EXT_multisample */ + +#ifdef WGL_EXT_pbuffer + +static GLboolean _glewInit_WGL_EXT_pbuffer (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglCreatePbufferEXT = (PFNWGLCREATEPBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"wglCreatePbufferEXT")) == NULL) || r; + r = ((wglDestroyPbufferEXT = (PFNWGLDESTROYPBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"wglDestroyPbufferEXT")) == NULL) || r; + r = ((wglGetPbufferDCEXT = (PFNWGLGETPBUFFERDCEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetPbufferDCEXT")) == NULL) || r; + r = ((wglQueryPbufferEXT = (PFNWGLQUERYPBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"wglQueryPbufferEXT")) == NULL) || r; + r = ((wglReleasePbufferDCEXT = (PFNWGLRELEASEPBUFFERDCEXTPROC)glewGetProcAddress((const GLubyte*)"wglReleasePbufferDCEXT")) == NULL) || r; + + return r; +} + +#endif /* WGL_EXT_pbuffer */ + +#ifdef WGL_EXT_pixel_format + +static GLboolean _glewInit_WGL_EXT_pixel_format (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglChoosePixelFormatEXT = (PFNWGLCHOOSEPIXELFORMATEXTPROC)glewGetProcAddress((const GLubyte*)"wglChoosePixelFormatEXT")) == NULL) || r; + r = ((wglGetPixelFormatAttribfvEXT = (PFNWGLGETPIXELFORMATATTRIBFVEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribfvEXT")) == NULL) || r; + r = ((wglGetPixelFormatAttribivEXT = (PFNWGLGETPIXELFORMATATTRIBIVEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribivEXT")) == NULL) || r; + + return r; +} + +#endif /* WGL_EXT_pixel_format */ + +#ifdef WGL_EXT_pixel_format_packed_float + +#endif /* WGL_EXT_pixel_format_packed_float */ + +#ifdef WGL_EXT_swap_control + +static GLboolean _glewInit_WGL_EXT_swap_control (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetSwapIntervalEXT")) == NULL) || r; + r = ((wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)glewGetProcAddress((const GLubyte*)"wglSwapIntervalEXT")) == NULL) || r; + + return r; +} + +#endif /* WGL_EXT_swap_control */ + +#ifdef WGL_I3D_digital_video_control + +static GLboolean _glewInit_WGL_I3D_digital_video_control (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetDigitalVideoParametersI3D = (PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetDigitalVideoParametersI3D")) == NULL) || r; + r = ((wglSetDigitalVideoParametersI3D = (PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglSetDigitalVideoParametersI3D")) == NULL) || r; + + return r; +} + +#endif /* WGL_I3D_digital_video_control */ + +#ifdef WGL_I3D_gamma + +static GLboolean _glewInit_WGL_I3D_gamma (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetGammaTableI3D = (PFNWGLGETGAMMATABLEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGammaTableI3D")) == NULL) || r; + r = ((wglGetGammaTableParametersI3D = (PFNWGLGETGAMMATABLEPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGammaTableParametersI3D")) == NULL) || r; + r = ((wglSetGammaTableI3D = (PFNWGLSETGAMMATABLEI3DPROC)glewGetProcAddress((const GLubyte*)"wglSetGammaTableI3D")) == NULL) || r; + r = ((wglSetGammaTableParametersI3D = (PFNWGLSETGAMMATABLEPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglSetGammaTableParametersI3D")) == NULL) || r; + + return r; +} + +#endif /* WGL_I3D_gamma */ + +#ifdef WGL_I3D_genlock + +static GLboolean _glewInit_WGL_I3D_genlock (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglDisableGenlockI3D = (PFNWGLDISABLEGENLOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglDisableGenlockI3D")) == NULL) || r; + r = ((wglEnableGenlockI3D = (PFNWGLENABLEGENLOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglEnableGenlockI3D")) == NULL) || r; + r = ((wglGenlockSampleRateI3D = (PFNWGLGENLOCKSAMPLERATEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSampleRateI3D")) == NULL) || r; + r = ((wglGenlockSourceDelayI3D = (PFNWGLGENLOCKSOURCEDELAYI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSourceDelayI3D")) == NULL) || r; + r = ((wglGenlockSourceEdgeI3D = (PFNWGLGENLOCKSOURCEEDGEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSourceEdgeI3D")) == NULL) || r; + r = ((wglGenlockSourceI3D = (PFNWGLGENLOCKSOURCEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSourceI3D")) == NULL) || r; + r = ((wglGetGenlockSampleRateI3D = (PFNWGLGETGENLOCKSAMPLERATEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSampleRateI3D")) == NULL) || r; + r = ((wglGetGenlockSourceDelayI3D = (PFNWGLGETGENLOCKSOURCEDELAYI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSourceDelayI3D")) == NULL) || r; + r = ((wglGetGenlockSourceEdgeI3D = (PFNWGLGETGENLOCKSOURCEEDGEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSourceEdgeI3D")) == NULL) || r; + r = ((wglGetGenlockSourceI3D = (PFNWGLGETGENLOCKSOURCEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSourceI3D")) == NULL) || r; + r = ((wglIsEnabledGenlockI3D = (PFNWGLISENABLEDGENLOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglIsEnabledGenlockI3D")) == NULL) || r; + r = ((wglQueryGenlockMaxSourceDelayI3D = (PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC)glewGetProcAddress((const GLubyte*)"wglQueryGenlockMaxSourceDelayI3D")) == NULL) || r; + + return r; +} + +#endif /* WGL_I3D_genlock */ + +#ifdef WGL_I3D_image_buffer + +static GLboolean _glewInit_WGL_I3D_image_buffer (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglAssociateImageBufferEventsI3D = (PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC)glewGetProcAddress((const GLubyte*)"wglAssociateImageBufferEventsI3D")) == NULL) || r; + r = ((wglCreateImageBufferI3D = (PFNWGLCREATEIMAGEBUFFERI3DPROC)glewGetProcAddress((const GLubyte*)"wglCreateImageBufferI3D")) == NULL) || r; + r = ((wglDestroyImageBufferI3D = (PFNWGLDESTROYIMAGEBUFFERI3DPROC)glewGetProcAddress((const GLubyte*)"wglDestroyImageBufferI3D")) == NULL) || r; + r = ((wglReleaseImageBufferEventsI3D = (PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC)glewGetProcAddress((const GLubyte*)"wglReleaseImageBufferEventsI3D")) == NULL) || r; + + return r; +} + +#endif /* WGL_I3D_image_buffer */ + +#ifdef WGL_I3D_swap_frame_lock + +static GLboolean _glewInit_WGL_I3D_swap_frame_lock (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglDisableFrameLockI3D = (PFNWGLDISABLEFRAMELOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglDisableFrameLockI3D")) == NULL) || r; + r = ((wglEnableFrameLockI3D = (PFNWGLENABLEFRAMELOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglEnableFrameLockI3D")) == NULL) || r; + r = ((wglIsEnabledFrameLockI3D = (PFNWGLISENABLEDFRAMELOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglIsEnabledFrameLockI3D")) == NULL) || r; + r = ((wglQueryFrameLockMasterI3D = (PFNWGLQUERYFRAMELOCKMASTERI3DPROC)glewGetProcAddress((const GLubyte*)"wglQueryFrameLockMasterI3D")) == NULL) || r; + + return r; +} + +#endif /* WGL_I3D_swap_frame_lock */ + +#ifdef WGL_I3D_swap_frame_usage + +static GLboolean _glewInit_WGL_I3D_swap_frame_usage (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglBeginFrameTrackingI3D = (PFNWGLBEGINFRAMETRACKINGI3DPROC)glewGetProcAddress((const GLubyte*)"wglBeginFrameTrackingI3D")) == NULL) || r; + r = ((wglEndFrameTrackingI3D = (PFNWGLENDFRAMETRACKINGI3DPROC)glewGetProcAddress((const GLubyte*)"wglEndFrameTrackingI3D")) == NULL) || r; + r = ((wglGetFrameUsageI3D = (PFNWGLGETFRAMEUSAGEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetFrameUsageI3D")) == NULL) || r; + r = ((wglQueryFrameTrackingI3D = (PFNWGLQUERYFRAMETRACKINGI3DPROC)glewGetProcAddress((const GLubyte*)"wglQueryFrameTrackingI3D")) == NULL) || r; + + return r; +} + +#endif /* WGL_I3D_swap_frame_usage */ + +#ifdef WGL_NV_float_buffer + +#endif /* WGL_NV_float_buffer */ + +#ifdef WGL_NV_gpu_affinity + +static GLboolean _glewInit_WGL_NV_gpu_affinity (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglCreateAffinityDCNV = (PFNWGLCREATEAFFINITYDCNVPROC)glewGetProcAddress((const GLubyte*)"wglCreateAffinityDCNV")) == NULL) || r; + r = ((wglDeleteDCNV = (PFNWGLDELETEDCNVPROC)glewGetProcAddress((const GLubyte*)"wglDeleteDCNV")) == NULL) || r; + r = ((wglEnumGpuDevicesNV = (PFNWGLENUMGPUDEVICESNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumGpuDevicesNV")) == NULL) || r; + r = ((wglEnumGpusFromAffinityDCNV = (PFNWGLENUMGPUSFROMAFFINITYDCNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumGpusFromAffinityDCNV")) == NULL) || r; + r = ((wglEnumGpusNV = (PFNWGLENUMGPUSNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumGpusNV")) == NULL) || r; + + return r; +} + +#endif /* WGL_NV_gpu_affinity */ + +#ifdef WGL_NV_render_depth_texture + +#endif /* WGL_NV_render_depth_texture */ + +#ifdef WGL_NV_render_texture_rectangle + +#endif /* WGL_NV_render_texture_rectangle */ + +#ifdef WGL_NV_vertex_array_range + +static GLboolean _glewInit_WGL_NV_vertex_array_range (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglAllocateMemoryNV = (PFNWGLALLOCATEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"wglAllocateMemoryNV")) == NULL) || r; + r = ((wglFreeMemoryNV = (PFNWGLFREEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"wglFreeMemoryNV")) == NULL) || r; + + return r; +} + +#endif /* WGL_NV_vertex_array_range */ + +#ifdef WGL_OML_sync_control + +static GLboolean _glewInit_WGL_OML_sync_control (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetMscRateOML = (PFNWGLGETMSCRATEOMLPROC)glewGetProcAddress((const GLubyte*)"wglGetMscRateOML")) == NULL) || r; + r = ((wglGetSyncValuesOML = (PFNWGLGETSYNCVALUESOMLPROC)glewGetProcAddress((const GLubyte*)"wglGetSyncValuesOML")) == NULL) || r; + r = ((wglSwapBuffersMscOML = (PFNWGLSWAPBUFFERSMSCOMLPROC)glewGetProcAddress((const GLubyte*)"wglSwapBuffersMscOML")) == NULL) || r; + r = ((wglSwapLayerBuffersMscOML = (PFNWGLSWAPLAYERBUFFERSMSCOMLPROC)glewGetProcAddress((const GLubyte*)"wglSwapLayerBuffersMscOML")) == NULL) || r; + r = ((wglWaitForMscOML = (PFNWGLWAITFORMSCOMLPROC)glewGetProcAddress((const GLubyte*)"wglWaitForMscOML")) == NULL) || r; + r = ((wglWaitForSbcOML = (PFNWGLWAITFORSBCOMLPROC)glewGetProcAddress((const GLubyte*)"wglWaitForSbcOML")) == NULL) || r; + + return r; +} + +#endif /* WGL_OML_sync_control */ + +/* ------------------------------------------------------------------------- */ + +static PFNWGLGETEXTENSIONSSTRINGARBPROC _wglewGetExtensionsStringARB = NULL; +static PFNWGLGETEXTENSIONSSTRINGEXTPROC _wglewGetExtensionsStringEXT = NULL; + +GLboolean wglewGetExtension (const char* name) +{ + GLubyte* p; + GLubyte* end; + GLuint len = _glewStrLen((const GLubyte*)name); + if (_wglewGetExtensionsStringARB == NULL) + if (_wglewGetExtensionsStringEXT == NULL) + return GL_FALSE; + else + p = (GLubyte*)_wglewGetExtensionsStringEXT(); + else + p = (GLubyte*)_wglewGetExtensionsStringARB(wglGetCurrentDC()); + if (0 == p) return GL_FALSE; + end = p + _glewStrLen(p); + while (p < end) + { + GLuint n = _glewStrCLen(p, ' '); + if (len == n && _glewStrSame((const GLubyte*)name, p, n)) return GL_TRUE; + p += n+1; + } + return GL_FALSE; +} + +GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST) +{ + GLboolean crippled; + /* find wgl extension string query functions */ + _wglewGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringARB"); + _wglewGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringEXT"); + /* initialize extensions */ + crippled = _wglewGetExtensionsStringARB == NULL && _wglewGetExtensionsStringEXT == NULL; +#ifdef WGL_3DFX_multisample + CONST_CAST(WGLEW_3DFX_multisample) = wglewGetExtension("WGL_3DFX_multisample"); +#endif /* WGL_3DFX_multisample */ +#ifdef WGL_3DL_stereo_control + CONST_CAST(WGLEW_3DL_stereo_control) = wglewGetExtension("WGL_3DL_stereo_control"); + if (glewExperimental || WGLEW_3DL_stereo_control|| crippled) CONST_CAST(WGLEW_3DL_stereo_control)= !_glewInit_WGL_3DL_stereo_control(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_3DL_stereo_control */ +#ifdef WGL_ARB_buffer_region + CONST_CAST(WGLEW_ARB_buffer_region) = wglewGetExtension("WGL_ARB_buffer_region"); + if (glewExperimental || WGLEW_ARB_buffer_region|| crippled) CONST_CAST(WGLEW_ARB_buffer_region)= !_glewInit_WGL_ARB_buffer_region(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_ARB_buffer_region */ +#ifdef WGL_ARB_extensions_string + CONST_CAST(WGLEW_ARB_extensions_string) = wglewGetExtension("WGL_ARB_extensions_string"); + if (glewExperimental || WGLEW_ARB_extensions_string|| crippled) CONST_CAST(WGLEW_ARB_extensions_string)= !_glewInit_WGL_ARB_extensions_string(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_ARB_extensions_string */ +#ifdef WGL_ARB_make_current_read + CONST_CAST(WGLEW_ARB_make_current_read) = wglewGetExtension("WGL_ARB_make_current_read"); + if (glewExperimental || WGLEW_ARB_make_current_read|| crippled) CONST_CAST(WGLEW_ARB_make_current_read)= !_glewInit_WGL_ARB_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_ARB_make_current_read */ +#ifdef WGL_ARB_multisample + CONST_CAST(WGLEW_ARB_multisample) = wglewGetExtension("WGL_ARB_multisample"); +#endif /* WGL_ARB_multisample */ +#ifdef WGL_ARB_pbuffer + CONST_CAST(WGLEW_ARB_pbuffer) = wglewGetExtension("WGL_ARB_pbuffer"); + if (glewExperimental || WGLEW_ARB_pbuffer|| crippled) CONST_CAST(WGLEW_ARB_pbuffer)= !_glewInit_WGL_ARB_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_ARB_pbuffer */ +#ifdef WGL_ARB_pixel_format + CONST_CAST(WGLEW_ARB_pixel_format) = wglewGetExtension("WGL_ARB_pixel_format"); + if (glewExperimental || WGLEW_ARB_pixel_format|| crippled) CONST_CAST(WGLEW_ARB_pixel_format)= !_glewInit_WGL_ARB_pixel_format(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_ARB_pixel_format */ +#ifdef WGL_ARB_pixel_format_float + CONST_CAST(WGLEW_ARB_pixel_format_float) = wglewGetExtension("WGL_ARB_pixel_format_float"); +#endif /* WGL_ARB_pixel_format_float */ +#ifdef WGL_ARB_render_texture + CONST_CAST(WGLEW_ARB_render_texture) = wglewGetExtension("WGL_ARB_render_texture"); + if (glewExperimental || WGLEW_ARB_render_texture|| crippled) CONST_CAST(WGLEW_ARB_render_texture)= !_glewInit_WGL_ARB_render_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_ARB_render_texture */ +#ifdef WGL_ATI_pixel_format_float + CONST_CAST(WGLEW_ATI_pixel_format_float) = wglewGetExtension("WGL_ATI_pixel_format_float"); +#endif /* WGL_ATI_pixel_format_float */ +#ifdef WGL_ATI_render_texture_rectangle + CONST_CAST(WGLEW_ATI_render_texture_rectangle) = wglewGetExtension("WGL_ATI_render_texture_rectangle"); +#endif /* WGL_ATI_render_texture_rectangle */ +#ifdef WGL_EXT_depth_float + CONST_CAST(WGLEW_EXT_depth_float) = wglewGetExtension("WGL_EXT_depth_float"); +#endif /* WGL_EXT_depth_float */ +#ifdef WGL_EXT_display_color_table + CONST_CAST(WGLEW_EXT_display_color_table) = wglewGetExtension("WGL_EXT_display_color_table"); + if (glewExperimental || WGLEW_EXT_display_color_table|| crippled) CONST_CAST(WGLEW_EXT_display_color_table)= !_glewInit_WGL_EXT_display_color_table(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_EXT_display_color_table */ +#ifdef WGL_EXT_extensions_string + CONST_CAST(WGLEW_EXT_extensions_string) = wglewGetExtension("WGL_EXT_extensions_string"); + if (glewExperimental || WGLEW_EXT_extensions_string|| crippled) CONST_CAST(WGLEW_EXT_extensions_string)= !_glewInit_WGL_EXT_extensions_string(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_EXT_extensions_string */ +#ifdef WGL_EXT_framebuffer_sRGB + CONST_CAST(WGLEW_EXT_framebuffer_sRGB) = wglewGetExtension("WGL_EXT_framebuffer_sRGB"); +#endif /* WGL_EXT_framebuffer_sRGB */ +#ifdef WGL_EXT_make_current_read + CONST_CAST(WGLEW_EXT_make_current_read) = wglewGetExtension("WGL_EXT_make_current_read"); + if (glewExperimental || WGLEW_EXT_make_current_read|| crippled) CONST_CAST(WGLEW_EXT_make_current_read)= !_glewInit_WGL_EXT_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_EXT_make_current_read */ +#ifdef WGL_EXT_multisample + CONST_CAST(WGLEW_EXT_multisample) = wglewGetExtension("WGL_EXT_multisample"); +#endif /* WGL_EXT_multisample */ +#ifdef WGL_EXT_pbuffer + CONST_CAST(WGLEW_EXT_pbuffer) = wglewGetExtension("WGL_EXT_pbuffer"); + if (glewExperimental || WGLEW_EXT_pbuffer|| crippled) CONST_CAST(WGLEW_EXT_pbuffer)= !_glewInit_WGL_EXT_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_EXT_pbuffer */ +#ifdef WGL_EXT_pixel_format + CONST_CAST(WGLEW_EXT_pixel_format) = wglewGetExtension("WGL_EXT_pixel_format"); + if (glewExperimental || WGLEW_EXT_pixel_format|| crippled) CONST_CAST(WGLEW_EXT_pixel_format)= !_glewInit_WGL_EXT_pixel_format(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_EXT_pixel_format */ +#ifdef WGL_EXT_pixel_format_packed_float + CONST_CAST(WGLEW_EXT_pixel_format_packed_float) = wglewGetExtension("WGL_EXT_pixel_format_packed_float"); +#endif /* WGL_EXT_pixel_format_packed_float */ +#ifdef WGL_EXT_swap_control + CONST_CAST(WGLEW_EXT_swap_control) = wglewGetExtension("WGL_EXT_swap_control"); + if (glewExperimental || WGLEW_EXT_swap_control|| crippled) CONST_CAST(WGLEW_EXT_swap_control)= !_glewInit_WGL_EXT_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_EXT_swap_control */ +#ifdef WGL_I3D_digital_video_control + CONST_CAST(WGLEW_I3D_digital_video_control) = wglewGetExtension("WGL_I3D_digital_video_control"); + if (glewExperimental || WGLEW_I3D_digital_video_control|| crippled) CONST_CAST(WGLEW_I3D_digital_video_control)= !_glewInit_WGL_I3D_digital_video_control(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_I3D_digital_video_control */ +#ifdef WGL_I3D_gamma + CONST_CAST(WGLEW_I3D_gamma) = wglewGetExtension("WGL_I3D_gamma"); + if (glewExperimental || WGLEW_I3D_gamma|| crippled) CONST_CAST(WGLEW_I3D_gamma)= !_glewInit_WGL_I3D_gamma(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_I3D_gamma */ +#ifdef WGL_I3D_genlock + CONST_CAST(WGLEW_I3D_genlock) = wglewGetExtension("WGL_I3D_genlock"); + if (glewExperimental || WGLEW_I3D_genlock|| crippled) CONST_CAST(WGLEW_I3D_genlock)= !_glewInit_WGL_I3D_genlock(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_I3D_genlock */ +#ifdef WGL_I3D_image_buffer + CONST_CAST(WGLEW_I3D_image_buffer) = wglewGetExtension("WGL_I3D_image_buffer"); + if (glewExperimental || WGLEW_I3D_image_buffer|| crippled) CONST_CAST(WGLEW_I3D_image_buffer)= !_glewInit_WGL_I3D_image_buffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_I3D_image_buffer */ +#ifdef WGL_I3D_swap_frame_lock + CONST_CAST(WGLEW_I3D_swap_frame_lock) = wglewGetExtension("WGL_I3D_swap_frame_lock"); + if (glewExperimental || WGLEW_I3D_swap_frame_lock|| crippled) CONST_CAST(WGLEW_I3D_swap_frame_lock)= !_glewInit_WGL_I3D_swap_frame_lock(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_I3D_swap_frame_lock */ +#ifdef WGL_I3D_swap_frame_usage + CONST_CAST(WGLEW_I3D_swap_frame_usage) = wglewGetExtension("WGL_I3D_swap_frame_usage"); + if (glewExperimental || WGLEW_I3D_swap_frame_usage|| crippled) CONST_CAST(WGLEW_I3D_swap_frame_usage)= !_glewInit_WGL_I3D_swap_frame_usage(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_I3D_swap_frame_usage */ +#ifdef WGL_NV_float_buffer + CONST_CAST(WGLEW_NV_float_buffer) = wglewGetExtension("WGL_NV_float_buffer"); +#endif /* WGL_NV_float_buffer */ +#ifdef WGL_NV_gpu_affinity + CONST_CAST(WGLEW_NV_gpu_affinity) = wglewGetExtension("WGL_NV_gpu_affinity"); + if (glewExperimental || WGLEW_NV_gpu_affinity|| crippled) CONST_CAST(WGLEW_NV_gpu_affinity)= !_glewInit_WGL_NV_gpu_affinity(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_NV_gpu_affinity */ +#ifdef WGL_NV_render_depth_texture + CONST_CAST(WGLEW_NV_render_depth_texture) = wglewGetExtension("WGL_NV_render_depth_texture"); +#endif /* WGL_NV_render_depth_texture */ +#ifdef WGL_NV_render_texture_rectangle + CONST_CAST(WGLEW_NV_render_texture_rectangle) = wglewGetExtension("WGL_NV_render_texture_rectangle"); +#endif /* WGL_NV_render_texture_rectangle */ +#ifdef WGL_NV_vertex_array_range + CONST_CAST(WGLEW_NV_vertex_array_range) = wglewGetExtension("WGL_NV_vertex_array_range"); + if (glewExperimental || WGLEW_NV_vertex_array_range|| crippled) CONST_CAST(WGLEW_NV_vertex_array_range)= !_glewInit_WGL_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_NV_vertex_array_range */ +#ifdef WGL_OML_sync_control + CONST_CAST(WGLEW_OML_sync_control) = wglewGetExtension("WGL_OML_sync_control"); + if (glewExperimental || WGLEW_OML_sync_control|| crippled) CONST_CAST(WGLEW_OML_sync_control)= !_glewInit_WGL_OML_sync_control(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_OML_sync_control */ + + return GLEW_OK; +} + +#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) + +PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay = NULL; + +PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig = NULL; +PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext = NULL; +PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer = NULL; +PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap = NULL; +PFNGLXCREATEWINDOWPROC __glewXCreateWindow = NULL; +PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer = NULL; +PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap = NULL; +PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow = NULL; +PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable = NULL; +PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib = NULL; +PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs = NULL; +PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent = NULL; +PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig = NULL; +PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent = NULL; +PFNGLXQUERYCONTEXTPROC __glewXQueryContext = NULL; +PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable = NULL; +PFNGLXSELECTEVENTPROC __glewXSelectEvent = NULL; + +PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI = NULL; +PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI = NULL; +PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI = NULL; + +PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT = NULL; +PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT = NULL; +PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT = NULL; +PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT = NULL; + +PFNGLXBINDTEXIMAGEEXTPROC __glewXBindTexImageEXT = NULL; +PFNGLXRELEASETEXIMAGEEXTPROC __glewXReleaseTexImageEXT = NULL; + +PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA = NULL; + +PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA = NULL; + +PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA = NULL; + +PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA = NULL; + +PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA = NULL; + +PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV = NULL; +PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV = NULL; + +#ifdef GLX_OML_sync_control +PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML = NULL; +PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML = NULL; +PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML = NULL; +PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML = NULL; +PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML = NULL; +#endif + +PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX = NULL; +PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX = NULL; +PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX = NULL; +PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX = NULL; +PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX = NULL; +PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX = NULL; + +PFNGLXBINDHYPERPIPESGIXPROC __glewXBindHyperpipeSGIX = NULL; +PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC __glewXDestroyHyperpipeConfigSGIX = NULL; +PFNGLXHYPERPIPEATTRIBSGIXPROC __glewXHyperpipeAttribSGIX = NULL; +PFNGLXHYPERPIPECONFIGSGIXPROC __glewXHyperpipeConfigSGIX = NULL; +PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC __glewXQueryHyperpipeAttribSGIX = NULL; +PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC __glewXQueryHyperpipeBestAttribSGIX = NULL; +PFNGLXQUERYHYPERPIPECONFIGSGIXPROC __glewXQueryHyperpipeConfigSGIX = NULL; +PFNGLXQUERYHYPERPIPENETWORKSGIXPROC __glewXQueryHyperpipeNetworkSGIX = NULL; + +PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX = NULL; +PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX = NULL; +PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX = NULL; +PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX = NULL; +PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX = NULL; + +PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX = NULL; +PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX = NULL; + +PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX = NULL; + +PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX = NULL; +PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX = NULL; +PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX = NULL; +PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX = NULL; +PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX = NULL; + +PFNGLXCUSHIONSGIPROC __glewXCushionSGI = NULL; + +PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI = NULL; +PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI = NULL; + +PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI = NULL; + +PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI = NULL; +PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI = NULL; + +PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN = NULL; + +PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN = NULL; +PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN = NULL; + +#if !defined(GLEW_MX) + +GLboolean __GLXEW_VERSION_1_0 = GL_FALSE; +GLboolean __GLXEW_VERSION_1_1 = GL_FALSE; +GLboolean __GLXEW_VERSION_1_2 = GL_FALSE; +GLboolean __GLXEW_VERSION_1_3 = GL_FALSE; +GLboolean __GLXEW_VERSION_1_4 = GL_FALSE; +GLboolean __GLXEW_3DFX_multisample = GL_FALSE; +GLboolean __GLXEW_ARB_fbconfig_float = GL_FALSE; +GLboolean __GLXEW_ARB_get_proc_address = GL_FALSE; +GLboolean __GLXEW_ARB_multisample = GL_FALSE; +GLboolean __GLXEW_ATI_pixel_format_float = GL_FALSE; +GLboolean __GLXEW_ATI_render_texture = GL_FALSE; +GLboolean __GLXEW_EXT_fbconfig_packed_float = GL_FALSE; +GLboolean __GLXEW_EXT_framebuffer_sRGB = GL_FALSE; +GLboolean __GLXEW_EXT_import_context = GL_FALSE; +GLboolean __GLXEW_EXT_scene_marker = GL_FALSE; +GLboolean __GLXEW_EXT_texture_from_pixmap = GL_FALSE; +GLboolean __GLXEW_EXT_visual_info = GL_FALSE; +GLboolean __GLXEW_EXT_visual_rating = GL_FALSE; +GLboolean __GLXEW_MESA_agp_offset = GL_FALSE; +GLboolean __GLXEW_MESA_copy_sub_buffer = GL_FALSE; +GLboolean __GLXEW_MESA_pixmap_colormap = GL_FALSE; +GLboolean __GLXEW_MESA_release_buffers = GL_FALSE; +GLboolean __GLXEW_MESA_set_3dfx_mode = GL_FALSE; +GLboolean __GLXEW_NV_float_buffer = GL_FALSE; +GLboolean __GLXEW_NV_vertex_array_range = GL_FALSE; +GLboolean __GLXEW_OML_swap_method = GL_FALSE; +#ifdef GLX_OML_sync_control +GLboolean __GLXEW_OML_sync_control = GL_FALSE; +#endif +GLboolean __GLXEW_SGIS_blended_overlay = GL_FALSE; +GLboolean __GLXEW_SGIS_color_range = GL_FALSE; +GLboolean __GLXEW_SGIS_multisample = GL_FALSE; +GLboolean __GLXEW_SGIS_shared_multisample = GL_FALSE; +GLboolean __GLXEW_SGIX_fbconfig = GL_FALSE; +GLboolean __GLXEW_SGIX_hyperpipe = GL_FALSE; +GLboolean __GLXEW_SGIX_pbuffer = GL_FALSE; +GLboolean __GLXEW_SGIX_swap_barrier = GL_FALSE; +GLboolean __GLXEW_SGIX_swap_group = GL_FALSE; +GLboolean __GLXEW_SGIX_video_resize = GL_FALSE; +GLboolean __GLXEW_SGIX_visual_select_group = GL_FALSE; +GLboolean __GLXEW_SGI_cushion = GL_FALSE; +GLboolean __GLXEW_SGI_make_current_read = GL_FALSE; +GLboolean __GLXEW_SGI_swap_control = GL_FALSE; +GLboolean __GLXEW_SGI_video_sync = GL_FALSE; +GLboolean __GLXEW_SUN_get_transparent_index = GL_FALSE; +GLboolean __GLXEW_SUN_video_resize = GL_FALSE; + +#endif /* !GLEW_MX */ + +#ifdef GLX_VERSION_1_2 + +static GLboolean _glewInit_GLX_VERSION_1_2 (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXGetCurrentDisplay = (PFNGLXGETCURRENTDISPLAYPROC)glewGetProcAddress((const GLubyte*)"glXGetCurrentDisplay")) == NULL) || r; + + return r; +} + +#endif /* GLX_VERSION_1_2 */ + +#ifdef GLX_VERSION_1_3 + +static GLboolean _glewInit_GLX_VERSION_1_3 (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glewGetProcAddress((const GLubyte*)"glXChooseFBConfig")) == NULL) || r; + r = ((glXCreateNewContext = (PFNGLXCREATENEWCONTEXTPROC)glewGetProcAddress((const GLubyte*)"glXCreateNewContext")) == NULL) || r; + r = ((glXCreatePbuffer = (PFNGLXCREATEPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glXCreatePbuffer")) == NULL) || r; + r = ((glXCreatePixmap = (PFNGLXCREATEPIXMAPPROC)glewGetProcAddress((const GLubyte*)"glXCreatePixmap")) == NULL) || r; + r = ((glXCreateWindow = (PFNGLXCREATEWINDOWPROC)glewGetProcAddress((const GLubyte*)"glXCreateWindow")) == NULL) || r; + r = ((glXDestroyPbuffer = (PFNGLXDESTROYPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glXDestroyPbuffer")) == NULL) || r; + r = ((glXDestroyPixmap = (PFNGLXDESTROYPIXMAPPROC)glewGetProcAddress((const GLubyte*)"glXDestroyPixmap")) == NULL) || r; + r = ((glXDestroyWindow = (PFNGLXDESTROYWINDOWPROC)glewGetProcAddress((const GLubyte*)"glXDestroyWindow")) == NULL) || r; + r = ((glXGetCurrentReadDrawable = (PFNGLXGETCURRENTREADDRAWABLEPROC)glewGetProcAddress((const GLubyte*)"glXGetCurrentReadDrawable")) == NULL) || r; + r = ((glXGetFBConfigAttrib = (PFNGLXGETFBCONFIGATTRIBPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigAttrib")) == NULL) || r; + r = ((glXGetFBConfigs = (PFNGLXGETFBCONFIGSPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigs")) == NULL) || r; + r = ((glXGetSelectedEvent = (PFNGLXGETSELECTEDEVENTPROC)glewGetProcAddress((const GLubyte*)"glXGetSelectedEvent")) == NULL) || r; + r = ((glXGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)glewGetProcAddress((const GLubyte*)"glXGetVisualFromFBConfig")) == NULL) || r; + r = ((glXMakeContextCurrent = (PFNGLXMAKECONTEXTCURRENTPROC)glewGetProcAddress((const GLubyte*)"glXMakeContextCurrent")) == NULL) || r; + r = ((glXQueryContext = (PFNGLXQUERYCONTEXTPROC)glewGetProcAddress((const GLubyte*)"glXQueryContext")) == NULL) || r; + r = ((glXQueryDrawable = (PFNGLXQUERYDRAWABLEPROC)glewGetProcAddress((const GLubyte*)"glXQueryDrawable")) == NULL) || r; + r = ((glXSelectEvent = (PFNGLXSELECTEVENTPROC)glewGetProcAddress((const GLubyte*)"glXSelectEvent")) == NULL) || r; + + return r; +} + +#endif /* GLX_VERSION_1_3 */ + +#ifdef GLX_VERSION_1_4 + +#endif /* GLX_VERSION_1_4 */ + +#ifdef GLX_3DFX_multisample + +#endif /* GLX_3DFX_multisample */ + +#ifdef GLX_ARB_fbconfig_float + +#endif /* GLX_ARB_fbconfig_float */ + +#ifdef GLX_ARB_get_proc_address + +#endif /* GLX_ARB_get_proc_address */ + +#ifdef GLX_ARB_multisample + +#endif /* GLX_ARB_multisample */ + +#ifdef GLX_ATI_pixel_format_float + +#endif /* GLX_ATI_pixel_format_float */ + +#ifdef GLX_ATI_render_texture + +static GLboolean _glewInit_GLX_ATI_render_texture (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXBindTexImageATI = (PFNGLXBINDTEXIMAGEATIPROC)glewGetProcAddress((const GLubyte*)"glXBindTexImageATI")) == NULL) || r; + r = ((glXDrawableAttribATI = (PFNGLXDRAWABLEATTRIBATIPROC)glewGetProcAddress((const GLubyte*)"glXDrawableAttribATI")) == NULL) || r; + r = ((glXReleaseTexImageATI = (PFNGLXRELEASETEXIMAGEATIPROC)glewGetProcAddress((const GLubyte*)"glXReleaseTexImageATI")) == NULL) || r; + + return r; +} + +#endif /* GLX_ATI_render_texture */ + +#ifdef GLX_EXT_fbconfig_packed_float + +#endif /* GLX_EXT_fbconfig_packed_float */ + +#ifdef GLX_EXT_framebuffer_sRGB + +#endif /* GLX_EXT_framebuffer_sRGB */ + +#ifdef GLX_EXT_import_context + +static GLboolean _glewInit_GLX_EXT_import_context (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXFreeContextEXT = (PFNGLXFREECONTEXTEXTPROC)glewGetProcAddress((const GLubyte*)"glXFreeContextEXT")) == NULL) || r; + r = ((glXGetContextIDEXT = (PFNGLXGETCONTEXTIDEXTPROC)glewGetProcAddress((const GLubyte*)"glXGetContextIDEXT")) == NULL) || r; + r = ((glXImportContextEXT = (PFNGLXIMPORTCONTEXTEXTPROC)glewGetProcAddress((const GLubyte*)"glXImportContextEXT")) == NULL) || r; + r = ((glXQueryContextInfoEXT = (PFNGLXQUERYCONTEXTINFOEXTPROC)glewGetProcAddress((const GLubyte*)"glXQueryContextInfoEXT")) == NULL) || r; + + return r; +} + +#endif /* GLX_EXT_import_context */ + +#ifdef GLX_EXT_scene_marker + +#endif /* GLX_EXT_scene_marker */ + +#ifdef GLX_EXT_texture_from_pixmap + +static GLboolean _glewInit_GLX_EXT_texture_from_pixmap (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glXBindTexImageEXT")) == NULL) || r; + r = ((glXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glXReleaseTexImageEXT")) == NULL) || r; + + return r; +} + +#endif /* GLX_EXT_texture_from_pixmap */ + +#ifdef GLX_EXT_visual_info + +#endif /* GLX_EXT_visual_info */ + +#ifdef GLX_EXT_visual_rating + +#endif /* GLX_EXT_visual_rating */ + +#ifdef GLX_MESA_agp_offset + +static GLboolean _glewInit_GLX_MESA_agp_offset (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXGetAGPOffsetMESA = (PFNGLXGETAGPOFFSETMESAPROC)glewGetProcAddress((const GLubyte*)"glXGetAGPOffsetMESA")) == NULL) || r; + + return r; +} + +#endif /* GLX_MESA_agp_offset */ + +#ifdef GLX_MESA_copy_sub_buffer + +static GLboolean _glewInit_GLX_MESA_copy_sub_buffer (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXCopySubBufferMESA = (PFNGLXCOPYSUBBUFFERMESAPROC)glewGetProcAddress((const GLubyte*)"glXCopySubBufferMESA")) == NULL) || r; + + return r; +} + +#endif /* GLX_MESA_copy_sub_buffer */ + +#ifdef GLX_MESA_pixmap_colormap + +static GLboolean _glewInit_GLX_MESA_pixmap_colormap (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXCreateGLXPixmapMESA = (PFNGLXCREATEGLXPIXMAPMESAPROC)glewGetProcAddress((const GLubyte*)"glXCreateGLXPixmapMESA")) == NULL) || r; + + return r; +} + +#endif /* GLX_MESA_pixmap_colormap */ + +#ifdef GLX_MESA_release_buffers + +static GLboolean _glewInit_GLX_MESA_release_buffers (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXReleaseBuffersMESA = (PFNGLXRELEASEBUFFERSMESAPROC)glewGetProcAddress((const GLubyte*)"glXReleaseBuffersMESA")) == NULL) || r; + + return r; +} + +#endif /* GLX_MESA_release_buffers */ + +#ifdef GLX_MESA_set_3dfx_mode + +static GLboolean _glewInit_GLX_MESA_set_3dfx_mode (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXSet3DfxModeMESA = (PFNGLXSET3DFXMODEMESAPROC)glewGetProcAddress((const GLubyte*)"glXSet3DfxModeMESA")) == NULL) || r; + + return r; +} + +#endif /* GLX_MESA_set_3dfx_mode */ + +#ifdef GLX_NV_float_buffer + +#endif /* GLX_NV_float_buffer */ + +#ifdef GLX_NV_vertex_array_range + +static GLboolean _glewInit_GLX_NV_vertex_array_range (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXAllocateMemoryNV = (PFNGLXALLOCATEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"glXAllocateMemoryNV")) == NULL) || r; + r = ((glXFreeMemoryNV = (PFNGLXFREEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"glXFreeMemoryNV")) == NULL) || r; + + return r; +} + +#endif /* GLX_NV_vertex_array_range */ + +#ifdef GLX_OML_swap_method + +#endif /* GLX_OML_swap_method */ + +#if defined(GLX_OML_sync_control) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +#include + +static GLboolean _glewInit_GLX_OML_sync_control (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXGetMscRateOML = (PFNGLXGETMSCRATEOMLPROC)glewGetProcAddress((const GLubyte*)"glXGetMscRateOML")) == NULL) || r; + r = ((glXGetSyncValuesOML = (PFNGLXGETSYNCVALUESOMLPROC)glewGetProcAddress((const GLubyte*)"glXGetSyncValuesOML")) == NULL) || r; + r = ((glXSwapBuffersMscOML = (PFNGLXSWAPBUFFERSMSCOMLPROC)glewGetProcAddress((const GLubyte*)"glXSwapBuffersMscOML")) == NULL) || r; + r = ((glXWaitForMscOML = (PFNGLXWAITFORMSCOMLPROC)glewGetProcAddress((const GLubyte*)"glXWaitForMscOML")) == NULL) || r; + r = ((glXWaitForSbcOML = (PFNGLXWAITFORSBCOMLPROC)glewGetProcAddress((const GLubyte*)"glXWaitForSbcOML")) == NULL) || r; + + return r; +} + +#endif /* GLX_OML_sync_control */ + +#ifdef GLX_SGIS_blended_overlay + +#endif /* GLX_SGIS_blended_overlay */ + +#ifdef GLX_SGIS_color_range + +#endif /* GLX_SGIS_color_range */ + +#ifdef GLX_SGIS_multisample + +#endif /* GLX_SGIS_multisample */ + +#ifdef GLX_SGIS_shared_multisample + +#endif /* GLX_SGIS_shared_multisample */ + +#ifdef GLX_SGIX_fbconfig + +static GLboolean _glewInit_GLX_SGIX_fbconfig (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXChooseFBConfigSGIX")) == NULL) || r; + r = ((glXCreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXCreateContextWithConfigSGIX")) == NULL) || r; + r = ((glXCreateGLXPixmapWithConfigSGIX = (PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXCreateGLXPixmapWithConfigSGIX")) == NULL) || r; + r = ((glXGetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigAttribSGIX")) == NULL) || r; + r = ((glXGetFBConfigFromVisualSGIX = (PFNGLXGETFBCONFIGFROMVISUALSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigFromVisualSGIX")) == NULL) || r; + r = ((glXGetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetVisualFromFBConfigSGIX")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGIX_fbconfig */ + +#ifdef GLX_SGIX_hyperpipe + +static GLboolean _glewInit_GLX_SGIX_hyperpipe (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXBindHyperpipeSGIX = (PFNGLXBINDHYPERPIPESGIXPROC)glewGetProcAddress((const GLubyte*)"glXBindHyperpipeSGIX")) == NULL) || r; + r = ((glXDestroyHyperpipeConfigSGIX = (PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXDestroyHyperpipeConfigSGIX")) == NULL) || r; + r = ((glXHyperpipeAttribSGIX = (PFNGLXHYPERPIPEATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXHyperpipeAttribSGIX")) == NULL) || r; + r = ((glXHyperpipeConfigSGIX = (PFNGLXHYPERPIPECONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXHyperpipeConfigSGIX")) == NULL) || r; + r = ((glXQueryHyperpipeAttribSGIX = (PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeAttribSGIX")) == NULL) || r; + r = ((glXQueryHyperpipeBestAttribSGIX = (PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeBestAttribSGIX")) == NULL) || r; + r = ((glXQueryHyperpipeConfigSGIX = (PFNGLXQUERYHYPERPIPECONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeConfigSGIX")) == NULL) || r; + r = ((glXQueryHyperpipeNetworkSGIX = (PFNGLXQUERYHYPERPIPENETWORKSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeNetworkSGIX")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGIX_hyperpipe */ + +#ifdef GLX_SGIX_pbuffer + +static GLboolean _glewInit_GLX_SGIX_pbuffer (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXCreateGLXPbufferSGIX = (PFNGLXCREATEGLXPBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXCreateGLXPbufferSGIX")) == NULL) || r; + r = ((glXDestroyGLXPbufferSGIX = (PFNGLXDESTROYGLXPBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXDestroyGLXPbufferSGIX")) == NULL) || r; + r = ((glXGetSelectedEventSGIX = (PFNGLXGETSELECTEDEVENTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetSelectedEventSGIX")) == NULL) || r; + r = ((glXQueryGLXPbufferSGIX = (PFNGLXQUERYGLXPBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryGLXPbufferSGIX")) == NULL) || r; + r = ((glXSelectEventSGIX = (PFNGLXSELECTEVENTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXSelectEventSGIX")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGIX_pbuffer */ + +#ifdef GLX_SGIX_swap_barrier + +static GLboolean _glewInit_GLX_SGIX_swap_barrier (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXBindSwapBarrierSGIX = (PFNGLXBINDSWAPBARRIERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXBindSwapBarrierSGIX")) == NULL) || r; + r = ((glXQueryMaxSwapBarriersSGIX = (PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryMaxSwapBarriersSGIX")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGIX_swap_barrier */ + +#ifdef GLX_SGIX_swap_group + +static GLboolean _glewInit_GLX_SGIX_swap_group (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXJoinSwapGroupSGIX = (PFNGLXJOINSWAPGROUPSGIXPROC)glewGetProcAddress((const GLubyte*)"glXJoinSwapGroupSGIX")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGIX_swap_group */ + +#ifdef GLX_SGIX_video_resize + +static GLboolean _glewInit_GLX_SGIX_video_resize (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXBindChannelToWindowSGIX = (PFNGLXBINDCHANNELTOWINDOWSGIXPROC)glewGetProcAddress((const GLubyte*)"glXBindChannelToWindowSGIX")) == NULL) || r; + r = ((glXChannelRectSGIX = (PFNGLXCHANNELRECTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXChannelRectSGIX")) == NULL) || r; + r = ((glXChannelRectSyncSGIX = (PFNGLXCHANNELRECTSYNCSGIXPROC)glewGetProcAddress((const GLubyte*)"glXChannelRectSyncSGIX")) == NULL) || r; + r = ((glXQueryChannelDeltasSGIX = (PFNGLXQUERYCHANNELDELTASSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryChannelDeltasSGIX")) == NULL) || r; + r = ((glXQueryChannelRectSGIX = (PFNGLXQUERYCHANNELRECTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryChannelRectSGIX")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGIX_video_resize */ + +#ifdef GLX_SGIX_visual_select_group + +#endif /* GLX_SGIX_visual_select_group */ + +#ifdef GLX_SGI_cushion + +static GLboolean _glewInit_GLX_SGI_cushion (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXCushionSGI = (PFNGLXCUSHIONSGIPROC)glewGetProcAddress((const GLubyte*)"glXCushionSGI")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGI_cushion */ + +#ifdef GLX_SGI_make_current_read + +static GLboolean _glewInit_GLX_SGI_make_current_read (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXGetCurrentReadDrawableSGI = (PFNGLXGETCURRENTREADDRAWABLESGIPROC)glewGetProcAddress((const GLubyte*)"glXGetCurrentReadDrawableSGI")) == NULL) || r; + r = ((glXMakeCurrentReadSGI = (PFNGLXMAKECURRENTREADSGIPROC)glewGetProcAddress((const GLubyte*)"glXMakeCurrentReadSGI")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGI_make_current_read */ + +#ifdef GLX_SGI_swap_control + +static GLboolean _glewInit_GLX_SGI_swap_control (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glewGetProcAddress((const GLubyte*)"glXSwapIntervalSGI")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGI_swap_control */ + +#ifdef GLX_SGI_video_sync + +static GLboolean _glewInit_GLX_SGI_video_sync (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXGetVideoSyncSGI = (PFNGLXGETVIDEOSYNCSGIPROC)glewGetProcAddress((const GLubyte*)"glXGetVideoSyncSGI")) == NULL) || r; + r = ((glXWaitVideoSyncSGI = (PFNGLXWAITVIDEOSYNCSGIPROC)glewGetProcAddress((const GLubyte*)"glXWaitVideoSyncSGI")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGI_video_sync */ + +#ifdef GLX_SUN_get_transparent_index + +static GLboolean _glewInit_GLX_SUN_get_transparent_index (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXGetTransparentIndexSUN = (PFNGLXGETTRANSPARENTINDEXSUNPROC)glewGetProcAddress((const GLubyte*)"glXGetTransparentIndexSUN")) == NULL) || r; + + return r; +} + +#endif /* GLX_SUN_get_transparent_index */ + +#ifdef GLX_SUN_video_resize + +static GLboolean _glewInit_GLX_SUN_video_resize (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXGetVideoResizeSUN = (PFNGLXGETVIDEORESIZESUNPROC)glewGetProcAddress((const GLubyte*)"glXGetVideoResizeSUN")) == NULL) || r; + r = ((glXVideoResizeSUN = (PFNGLXVIDEORESIZESUNPROC)glewGetProcAddress((const GLubyte*)"glXVideoResizeSUN")) == NULL) || r; + + return r; +} + +#endif /* GLX_SUN_video_resize */ + +/* ------------------------------------------------------------------------ */ + +GLboolean glxewGetExtension (const char* name) +{ + GLubyte* p; + GLubyte* end; + GLuint len = _glewStrLen((const GLubyte*)name); +/* if (glXQueryExtensionsString == NULL || glXGetCurrentDisplay == NULL) return GL_FALSE; */ +/* p = (GLubyte*)glXQueryExtensionsString(glXGetCurrentDisplay(), DefaultScreen(glXGetCurrentDisplay())); */ + if (glXGetClientString == NULL || glXGetCurrentDisplay == NULL) return GL_FALSE; + p = (GLubyte*)glXGetClientString(glXGetCurrentDisplay(), GLX_EXTENSIONS); + if (0 == p) return GL_FALSE; + end = p + _glewStrLen(p); + while (p < end) + { + GLuint n = _glewStrCLen(p, ' '); + if (len == n && _glewStrSame((const GLubyte*)name, p, n)) return GL_TRUE; + p += n+1; + } + return GL_FALSE; +} + +GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST) +{ + int major, minor; + /* initialize core GLX 1.2 */ + if (_glewInit_GLX_VERSION_1_2(GLEW_CONTEXT_ARG_VAR_INIT)) return GLEW_ERROR_GLX_VERSION_11_ONLY; + /* initialize flags */ + CONST_CAST(GLXEW_VERSION_1_0) = GL_TRUE; + CONST_CAST(GLXEW_VERSION_1_1) = GL_TRUE; + CONST_CAST(GLXEW_VERSION_1_2) = GL_TRUE; + CONST_CAST(GLXEW_VERSION_1_3) = GL_TRUE; + CONST_CAST(GLXEW_VERSION_1_4) = GL_TRUE; + /* query GLX version */ + glXQueryVersion(glXGetCurrentDisplay(), &major, &minor); + if (major == 1 && minor <= 3) + { + switch (minor) + { + case 3: + CONST_CAST(GLXEW_VERSION_1_4) = GL_FALSE; + break; + case 2: + CONST_CAST(GLXEW_VERSION_1_4) = GL_FALSE; + CONST_CAST(GLXEW_VERSION_1_3) = GL_FALSE; + break; + default: + return GLEW_ERROR_GLX_VERSION_11_ONLY; + break; + } + } + /* initialize extensions */ +#ifdef GLX_VERSION_1_3 + if (glewExperimental || GLXEW_VERSION_1_3) CONST_CAST(GLXEW_VERSION_1_3) = !_glewInit_GLX_VERSION_1_3(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_VERSION_1_3 */ +#ifdef GLX_3DFX_multisample + CONST_CAST(GLXEW_3DFX_multisample) = glxewGetExtension("GLX_3DFX_multisample"); +#endif /* GLX_3DFX_multisample */ +#ifdef GLX_ARB_fbconfig_float + CONST_CAST(GLXEW_ARB_fbconfig_float) = glxewGetExtension("GLX_ARB_fbconfig_float"); +#endif /* GLX_ARB_fbconfig_float */ +#ifdef GLX_ARB_get_proc_address + CONST_CAST(GLXEW_ARB_get_proc_address) = glxewGetExtension("GLX_ARB_get_proc_address"); +#endif /* GLX_ARB_get_proc_address */ +#ifdef GLX_ARB_multisample + CONST_CAST(GLXEW_ARB_multisample) = glxewGetExtension("GLX_ARB_multisample"); +#endif /* GLX_ARB_multisample */ +#ifdef GLX_ATI_pixel_format_float + CONST_CAST(GLXEW_ATI_pixel_format_float) = glxewGetExtension("GLX_ATI_pixel_format_float"); +#endif /* GLX_ATI_pixel_format_float */ +#ifdef GLX_ATI_render_texture + CONST_CAST(GLXEW_ATI_render_texture) = glxewGetExtension("GLX_ATI_render_texture"); + if (glewExperimental || GLXEW_ATI_render_texture) CONST_CAST(GLXEW_ATI_render_texture) = !_glewInit_GLX_ATI_render_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_ATI_render_texture */ +#ifdef GLX_EXT_fbconfig_packed_float + CONST_CAST(GLXEW_EXT_fbconfig_packed_float) = glxewGetExtension("GLX_EXT_fbconfig_packed_float"); +#endif /* GLX_EXT_fbconfig_packed_float */ +#ifdef GLX_EXT_framebuffer_sRGB + CONST_CAST(GLXEW_EXT_framebuffer_sRGB) = glxewGetExtension("GLX_EXT_framebuffer_sRGB"); +#endif /* GLX_EXT_framebuffer_sRGB */ +#ifdef GLX_EXT_import_context + CONST_CAST(GLXEW_EXT_import_context) = glxewGetExtension("GLX_EXT_import_context"); + if (glewExperimental || GLXEW_EXT_import_context) CONST_CAST(GLXEW_EXT_import_context) = !_glewInit_GLX_EXT_import_context(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_EXT_import_context */ +#ifdef GLX_EXT_scene_marker + CONST_CAST(GLXEW_EXT_scene_marker) = glxewGetExtension("GLX_EXT_scene_marker"); +#endif /* GLX_EXT_scene_marker */ +#ifdef GLX_EXT_texture_from_pixmap + CONST_CAST(GLXEW_EXT_texture_from_pixmap) = glxewGetExtension("GLX_EXT_texture_from_pixmap"); + if (glewExperimental || GLXEW_EXT_texture_from_pixmap) CONST_CAST(GLXEW_EXT_texture_from_pixmap) = !_glewInit_GLX_EXT_texture_from_pixmap(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_EXT_texture_from_pixmap */ +#ifdef GLX_EXT_visual_info + CONST_CAST(GLXEW_EXT_visual_info) = glxewGetExtension("GLX_EXT_visual_info"); +#endif /* GLX_EXT_visual_info */ +#ifdef GLX_EXT_visual_rating + CONST_CAST(GLXEW_EXT_visual_rating) = glxewGetExtension("GLX_EXT_visual_rating"); +#endif /* GLX_EXT_visual_rating */ +#ifdef GLX_MESA_agp_offset + CONST_CAST(GLXEW_MESA_agp_offset) = glxewGetExtension("GLX_MESA_agp_offset"); + if (glewExperimental || GLXEW_MESA_agp_offset) CONST_CAST(GLXEW_MESA_agp_offset) = !_glewInit_GLX_MESA_agp_offset(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_MESA_agp_offset */ +#ifdef GLX_MESA_copy_sub_buffer + CONST_CAST(GLXEW_MESA_copy_sub_buffer) = glxewGetExtension("GLX_MESA_copy_sub_buffer"); + if (glewExperimental || GLXEW_MESA_copy_sub_buffer) CONST_CAST(GLXEW_MESA_copy_sub_buffer) = !_glewInit_GLX_MESA_copy_sub_buffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_MESA_copy_sub_buffer */ +#ifdef GLX_MESA_pixmap_colormap + CONST_CAST(GLXEW_MESA_pixmap_colormap) = glxewGetExtension("GLX_MESA_pixmap_colormap"); + if (glewExperimental || GLXEW_MESA_pixmap_colormap) CONST_CAST(GLXEW_MESA_pixmap_colormap) = !_glewInit_GLX_MESA_pixmap_colormap(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_MESA_pixmap_colormap */ +#ifdef GLX_MESA_release_buffers + CONST_CAST(GLXEW_MESA_release_buffers) = glxewGetExtension("GLX_MESA_release_buffers"); + if (glewExperimental || GLXEW_MESA_release_buffers) CONST_CAST(GLXEW_MESA_release_buffers) = !_glewInit_GLX_MESA_release_buffers(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_MESA_release_buffers */ +#ifdef GLX_MESA_set_3dfx_mode + CONST_CAST(GLXEW_MESA_set_3dfx_mode) = glxewGetExtension("GLX_MESA_set_3dfx_mode"); + if (glewExperimental || GLXEW_MESA_set_3dfx_mode) CONST_CAST(GLXEW_MESA_set_3dfx_mode) = !_glewInit_GLX_MESA_set_3dfx_mode(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_MESA_set_3dfx_mode */ +#ifdef GLX_NV_float_buffer + CONST_CAST(GLXEW_NV_float_buffer) = glxewGetExtension("GLX_NV_float_buffer"); +#endif /* GLX_NV_float_buffer */ +#ifdef GLX_NV_vertex_array_range + CONST_CAST(GLXEW_NV_vertex_array_range) = glxewGetExtension("GLX_NV_vertex_array_range"); + if (glewExperimental || GLXEW_NV_vertex_array_range) CONST_CAST(GLXEW_NV_vertex_array_range) = !_glewInit_GLX_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_NV_vertex_array_range */ +#ifdef GLX_OML_swap_method + CONST_CAST(GLXEW_OML_swap_method) = glxewGetExtension("GLX_OML_swap_method"); +#endif /* GLX_OML_swap_method */ +#if defined(GLX_OML_sync_control) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +#include + CONST_CAST(GLXEW_OML_sync_control) = glxewGetExtension("GLX_OML_sync_control"); + if (glewExperimental || GLXEW_OML_sync_control) CONST_CAST(GLXEW_OML_sync_control) = !_glewInit_GLX_OML_sync_control(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_OML_sync_control */ +#ifdef GLX_SGIS_blended_overlay + CONST_CAST(GLXEW_SGIS_blended_overlay) = glxewGetExtension("GLX_SGIS_blended_overlay"); +#endif /* GLX_SGIS_blended_overlay */ +#ifdef GLX_SGIS_color_range + CONST_CAST(GLXEW_SGIS_color_range) = glxewGetExtension("GLX_SGIS_color_range"); +#endif /* GLX_SGIS_color_range */ +#ifdef GLX_SGIS_multisample + CONST_CAST(GLXEW_SGIS_multisample) = glxewGetExtension("GLX_SGIS_multisample"); +#endif /* GLX_SGIS_multisample */ +#ifdef GLX_SGIS_shared_multisample + CONST_CAST(GLXEW_SGIS_shared_multisample) = glxewGetExtension("GLX_SGIS_shared_multisample"); +#endif /* GLX_SGIS_shared_multisample */ +#ifdef GLX_SGIX_fbconfig + CONST_CAST(GLXEW_SGIX_fbconfig) = glxewGetExtension("GLX_SGIX_fbconfig"); + if (glewExperimental || GLXEW_SGIX_fbconfig) CONST_CAST(GLXEW_SGIX_fbconfig) = !_glewInit_GLX_SGIX_fbconfig(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGIX_fbconfig */ +#ifdef GLX_SGIX_hyperpipe + CONST_CAST(GLXEW_SGIX_hyperpipe) = glxewGetExtension("GLX_SGIX_hyperpipe"); + if (glewExperimental || GLXEW_SGIX_hyperpipe) CONST_CAST(GLXEW_SGIX_hyperpipe) = !_glewInit_GLX_SGIX_hyperpipe(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGIX_hyperpipe */ +#ifdef GLX_SGIX_pbuffer + CONST_CAST(GLXEW_SGIX_pbuffer) = glxewGetExtension("GLX_SGIX_pbuffer"); + if (glewExperimental || GLXEW_SGIX_pbuffer) CONST_CAST(GLXEW_SGIX_pbuffer) = !_glewInit_GLX_SGIX_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGIX_pbuffer */ +#ifdef GLX_SGIX_swap_barrier + CONST_CAST(GLXEW_SGIX_swap_barrier) = glxewGetExtension("GLX_SGIX_swap_barrier"); + if (glewExperimental || GLXEW_SGIX_swap_barrier) CONST_CAST(GLXEW_SGIX_swap_barrier) = !_glewInit_GLX_SGIX_swap_barrier(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGIX_swap_barrier */ +#ifdef GLX_SGIX_swap_group + CONST_CAST(GLXEW_SGIX_swap_group) = glxewGetExtension("GLX_SGIX_swap_group"); + if (glewExperimental || GLXEW_SGIX_swap_group) CONST_CAST(GLXEW_SGIX_swap_group) = !_glewInit_GLX_SGIX_swap_group(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGIX_swap_group */ +#ifdef GLX_SGIX_video_resize + CONST_CAST(GLXEW_SGIX_video_resize) = glxewGetExtension("GLX_SGIX_video_resize"); + if (glewExperimental || GLXEW_SGIX_video_resize) CONST_CAST(GLXEW_SGIX_video_resize) = !_glewInit_GLX_SGIX_video_resize(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGIX_video_resize */ +#ifdef GLX_SGIX_visual_select_group + CONST_CAST(GLXEW_SGIX_visual_select_group) = glxewGetExtension("GLX_SGIX_visual_select_group"); +#endif /* GLX_SGIX_visual_select_group */ +#ifdef GLX_SGI_cushion + CONST_CAST(GLXEW_SGI_cushion) = glxewGetExtension("GLX_SGI_cushion"); + if (glewExperimental || GLXEW_SGI_cushion) CONST_CAST(GLXEW_SGI_cushion) = !_glewInit_GLX_SGI_cushion(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGI_cushion */ +#ifdef GLX_SGI_make_current_read + CONST_CAST(GLXEW_SGI_make_current_read) = glxewGetExtension("GLX_SGI_make_current_read"); + if (glewExperimental || GLXEW_SGI_make_current_read) CONST_CAST(GLXEW_SGI_make_current_read) = !_glewInit_GLX_SGI_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGI_make_current_read */ +#ifdef GLX_SGI_swap_control + CONST_CAST(GLXEW_SGI_swap_control) = glxewGetExtension("GLX_SGI_swap_control"); + if (glewExperimental || GLXEW_SGI_swap_control) CONST_CAST(GLXEW_SGI_swap_control) = !_glewInit_GLX_SGI_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGI_swap_control */ +#ifdef GLX_SGI_video_sync + CONST_CAST(GLXEW_SGI_video_sync) = glxewGetExtension("GLX_SGI_video_sync"); + if (glewExperimental || GLXEW_SGI_video_sync) CONST_CAST(GLXEW_SGI_video_sync) = !_glewInit_GLX_SGI_video_sync(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGI_video_sync */ +#ifdef GLX_SUN_get_transparent_index + CONST_CAST(GLXEW_SUN_get_transparent_index) = glxewGetExtension("GLX_SUN_get_transparent_index"); + if (glewExperimental || GLXEW_SUN_get_transparent_index) CONST_CAST(GLXEW_SUN_get_transparent_index) = !_glewInit_GLX_SUN_get_transparent_index(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SUN_get_transparent_index */ +#ifdef GLX_SUN_video_resize + CONST_CAST(GLXEW_SUN_video_resize) = glxewGetExtension("GLX_SUN_video_resize"); + if (glewExperimental || GLXEW_SUN_video_resize) CONST_CAST(GLXEW_SUN_video_resize) = !_glewInit_GLX_SUN_video_resize(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SUN_video_resize */ + + return GLEW_OK; +} + +#endif /* !__APPLE__ || GLEW_APPLE_GLX */ + +/* ------------------------------------------------------------------------ */ + +const GLubyte* glewGetErrorString (GLenum error) +{ + static const GLubyte* _glewErrorString[] = + { + (const GLubyte*)"No error", + (const GLubyte*)"Missing GL version", + (const GLubyte*)"GL 1.1 and up are not supported", + (const GLubyte*)"GLX 1.2 and up are not supported", + (const GLubyte*)"Unknown error" + }; + const int max_error = sizeof(_glewErrorString)/sizeof(*_glewErrorString) - 1; + return _glewErrorString[(int)error > max_error ? max_error : (int)error]; +} + +const GLubyte* glewGetString (GLenum name) +{ + static const GLubyte* _glewString[] = + { + (const GLubyte*)NULL, + (const GLubyte*)"1.5.0", + (const GLubyte*)"1", + (const GLubyte*)"5", + (const GLubyte*)"0" + }; + const int max_string = sizeof(_glewString)/sizeof(*_glewString) - 1; + return _glewString[(int)name > max_string ? 0 : (int)name]; +} + +/* ------------------------------------------------------------------------ */ + +GLboolean glewExperimental = GL_FALSE; + +#if !defined(GLEW_MX) + +#if defined(_WIN32) +extern GLenum wglewContextInit (void); +#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) /* _UNIX */ +extern GLenum glxewContextInit (void); +#endif /* _WIN32 */ + +GLenum glewInit () +{ + GLenum r; + if ( (r = glewContextInit()) ) return r; +#if defined(_WIN32) + return wglewContextInit(); +#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) /* _UNIX */ + return glxewContextInit(); +#else + return r; +#endif /* _WIN32 */ +} + +#endif /* !GLEW_MX */ +#ifdef GLEW_MX +GLboolean glewContextIsSupported (GLEWContext* ctx, const char* name) +#else +GLboolean glewIsSupported (const char* name) +#endif +{ + GLubyte* pos = (GLubyte*)name; + GLuint len = _glewStrLen(pos); + GLboolean ret = GL_TRUE; + while (ret && len > 0) + { + if (_glewStrSame1(&pos, &len, (const GLubyte*)"GL_", 3)) + { + if (_glewStrSame2(&pos, &len, (const GLubyte*)"VERSION_", 8)) + { +#ifdef GL_VERSION_1_2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_2", 3)) + { + ret = GLEW_VERSION_1_2; + continue; + } +#endif +#ifdef GL_VERSION_1_3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_3", 3)) + { + ret = GLEW_VERSION_1_3; + continue; + } +#endif +#ifdef GL_VERSION_1_4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_4", 3)) + { + ret = GLEW_VERSION_1_4; + continue; + } +#endif +#ifdef GL_VERSION_1_5 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_5", 3)) + { + ret = GLEW_VERSION_1_5; + continue; + } +#endif +#ifdef GL_VERSION_2_0 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"2_0", 3)) + { + ret = GLEW_VERSION_2_0; + continue; + } +#endif +#ifdef GL_VERSION_2_1 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"2_1", 3)) + { + ret = GLEW_VERSION_2_1; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DFX_", 5)) + { +#ifdef GL_3DFX_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = GLEW_3DFX_multisample; + continue; + } +#endif +#ifdef GL_3DFX_tbuffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"tbuffer", 7)) + { + ret = GLEW_3DFX_tbuffer; + continue; + } +#endif +#ifdef GL_3DFX_texture_compression_FXT1 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_FXT1", 24)) + { + ret = GLEW_3DFX_texture_compression_FXT1; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"APPLE_", 6)) + { +#ifdef GL_APPLE_client_storage + if (_glewStrSame3(&pos, &len, (const GLubyte*)"client_storage", 14)) + { + ret = GLEW_APPLE_client_storage; + continue; + } +#endif +#ifdef GL_APPLE_element_array + if (_glewStrSame3(&pos, &len, (const GLubyte*)"element_array", 13)) + { + ret = GLEW_APPLE_element_array; + continue; + } +#endif +#ifdef GL_APPLE_fence + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fence", 5)) + { + ret = GLEW_APPLE_fence; + continue; + } +#endif +#ifdef GL_APPLE_float_pixels + if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_pixels", 12)) + { + ret = GLEW_APPLE_float_pixels; + continue; + } +#endif +#ifdef GL_APPLE_flush_buffer_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"flush_buffer_range", 18)) + { + ret = GLEW_APPLE_flush_buffer_range; + continue; + } +#endif +#ifdef GL_APPLE_pixel_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_buffer", 12)) + { + ret = GLEW_APPLE_pixel_buffer; + continue; + } +#endif +#ifdef GL_APPLE_specular_vector + if (_glewStrSame3(&pos, &len, (const GLubyte*)"specular_vector", 15)) + { + ret = GLEW_APPLE_specular_vector; + continue; + } +#endif +#ifdef GL_APPLE_texture_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_range", 13)) + { + ret = GLEW_APPLE_texture_range; + continue; + } +#endif +#ifdef GL_APPLE_transform_hint + if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_hint", 14)) + { + ret = GLEW_APPLE_transform_hint; + continue; + } +#endif +#ifdef GL_APPLE_vertex_array_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_object", 19)) + { + ret = GLEW_APPLE_vertex_array_object; + continue; + } +#endif +#ifdef GL_APPLE_vertex_array_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18)) + { + ret = GLEW_APPLE_vertex_array_range; + continue; + } +#endif +#ifdef GL_APPLE_ycbcr_422 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"ycbcr_422", 9)) + { + ret = GLEW_APPLE_ycbcr_422; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"ARB_", 4)) + { +#ifdef GL_ARB_color_buffer_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_buffer_float", 18)) + { + ret = GLEW_ARB_color_buffer_float; + continue; + } +#endif +#ifdef GL_ARB_depth_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_texture", 13)) + { + ret = GLEW_ARB_depth_texture; + continue; + } +#endif +#ifdef GL_ARB_draw_buffers + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers", 12)) + { + ret = GLEW_ARB_draw_buffers; + continue; + } +#endif +#ifdef GL_ARB_fragment_program + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program", 16)) + { + ret = GLEW_ARB_fragment_program; + continue; + } +#endif +#ifdef GL_ARB_fragment_program_shadow + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program_shadow", 23)) + { + ret = GLEW_ARB_fragment_program_shadow; + continue; + } +#endif +#ifdef GL_ARB_fragment_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_shader", 15)) + { + ret = GLEW_ARB_fragment_shader; + continue; + } +#endif +#ifdef GL_ARB_half_float_pixel + if (_glewStrSame3(&pos, &len, (const GLubyte*)"half_float_pixel", 16)) + { + ret = GLEW_ARB_half_float_pixel; + continue; + } +#endif +#ifdef GL_ARB_imaging + if (_glewStrSame3(&pos, &len, (const GLubyte*)"imaging", 7)) + { + ret = GLEW_ARB_imaging; + continue; + } +#endif +#ifdef GL_ARB_matrix_palette + if (_glewStrSame3(&pos, &len, (const GLubyte*)"matrix_palette", 14)) + { + ret = GLEW_ARB_matrix_palette; + continue; + } +#endif +#ifdef GL_ARB_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = GLEW_ARB_multisample; + continue; + } +#endif +#ifdef GL_ARB_multitexture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multitexture", 12)) + { + ret = GLEW_ARB_multitexture; + continue; + } +#endif +#ifdef GL_ARB_occlusion_query + if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_query", 15)) + { + ret = GLEW_ARB_occlusion_query; + continue; + } +#endif +#ifdef GL_ARB_pixel_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_buffer_object", 19)) + { + ret = GLEW_ARB_pixel_buffer_object; + continue; + } +#endif +#ifdef GL_ARB_point_parameters + if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_parameters", 16)) + { + ret = GLEW_ARB_point_parameters; + continue; + } +#endif +#ifdef GL_ARB_point_sprite + if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_sprite", 12)) + { + ret = GLEW_ARB_point_sprite; + continue; + } +#endif +#ifdef GL_ARB_shader_objects + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_objects", 14)) + { + ret = GLEW_ARB_shader_objects; + continue; + } +#endif +#ifdef GL_ARB_shading_language_100 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shading_language_100", 20)) + { + ret = GLEW_ARB_shading_language_100; + continue; + } +#endif +#ifdef GL_ARB_shadow + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow", 6)) + { + ret = GLEW_ARB_shadow; + continue; + } +#endif +#ifdef GL_ARB_shadow_ambient + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow_ambient", 14)) + { + ret = GLEW_ARB_shadow_ambient; + continue; + } +#endif +#ifdef GL_ARB_texture_border_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_border_clamp", 20)) + { + ret = GLEW_ARB_texture_border_clamp; + continue; + } +#endif +#ifdef GL_ARB_texture_compression + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression", 19)) + { + ret = GLEW_ARB_texture_compression; + continue; + } +#endif +#ifdef GL_ARB_texture_cube_map + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_cube_map", 16)) + { + ret = GLEW_ARB_texture_cube_map; + continue; + } +#endif +#ifdef GL_ARB_texture_env_add + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_add", 15)) + { + ret = GLEW_ARB_texture_env_add; + continue; + } +#endif +#ifdef GL_ARB_texture_env_combine + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine", 19)) + { + ret = GLEW_ARB_texture_env_combine; + continue; + } +#endif +#ifdef GL_ARB_texture_env_crossbar + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_crossbar", 20)) + { + ret = GLEW_ARB_texture_env_crossbar; + continue; + } +#endif +#ifdef GL_ARB_texture_env_dot3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_dot3", 16)) + { + ret = GLEW_ARB_texture_env_dot3; + continue; + } +#endif +#ifdef GL_ARB_texture_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_float", 13)) + { + ret = GLEW_ARB_texture_float; + continue; + } +#endif +#ifdef GL_ARB_texture_mirrored_repeat + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirrored_repeat", 23)) + { + ret = GLEW_ARB_texture_mirrored_repeat; + continue; + } +#endif +#ifdef GL_ARB_texture_non_power_of_two + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_non_power_of_two", 24)) + { + ret = GLEW_ARB_texture_non_power_of_two; + continue; + } +#endif +#ifdef GL_ARB_texture_rectangle + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rectangle", 17)) + { + ret = GLEW_ARB_texture_rectangle; + continue; + } +#endif +#ifdef GL_ARB_transpose_matrix + if (_glewStrSame3(&pos, &len, (const GLubyte*)"transpose_matrix", 16)) + { + ret = GLEW_ARB_transpose_matrix; + continue; + } +#endif +#ifdef GL_ARB_vertex_blend + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_blend", 12)) + { + ret = GLEW_ARB_vertex_blend; + continue; + } +#endif +#ifdef GL_ARB_vertex_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_buffer_object", 20)) + { + ret = GLEW_ARB_vertex_buffer_object; + continue; + } +#endif +#ifdef GL_ARB_vertex_program + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program", 14)) + { + ret = GLEW_ARB_vertex_program; + continue; + } +#endif +#ifdef GL_ARB_vertex_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader", 13)) + { + ret = GLEW_ARB_vertex_shader; + continue; + } +#endif +#ifdef GL_ARB_window_pos + if (_glewStrSame3(&pos, &len, (const GLubyte*)"window_pos", 10)) + { + ret = GLEW_ARB_window_pos; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATIX_", 5)) + { +#ifdef GL_ATIX_point_sprites + if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_sprites", 13)) + { + ret = GLEW_ATIX_point_sprites; + continue; + } +#endif +#ifdef GL_ATIX_texture_env_combine3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine3", 20)) + { + ret = GLEW_ATIX_texture_env_combine3; + continue; + } +#endif +#ifdef GL_ATIX_texture_env_route + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_route", 17)) + { + ret = GLEW_ATIX_texture_env_route; + continue; + } +#endif +#ifdef GL_ATIX_vertex_shader_output_point_size + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader_output_point_size", 31)) + { + ret = GLEW_ATIX_vertex_shader_output_point_size; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATI_", 4)) + { +#ifdef GL_ATI_draw_buffers + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers", 12)) + { + ret = GLEW_ATI_draw_buffers; + continue; + } +#endif +#ifdef GL_ATI_element_array + if (_glewStrSame3(&pos, &len, (const GLubyte*)"element_array", 13)) + { + ret = GLEW_ATI_element_array; + continue; + } +#endif +#ifdef GL_ATI_envmap_bumpmap + if (_glewStrSame3(&pos, &len, (const GLubyte*)"envmap_bumpmap", 14)) + { + ret = GLEW_ATI_envmap_bumpmap; + continue; + } +#endif +#ifdef GL_ATI_fragment_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_shader", 15)) + { + ret = GLEW_ATI_fragment_shader; + continue; + } +#endif +#ifdef GL_ATI_map_object_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_object_buffer", 17)) + { + ret = GLEW_ATI_map_object_buffer; + continue; + } +#endif +#ifdef GL_ATI_pn_triangles + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pn_triangles", 12)) + { + ret = GLEW_ATI_pn_triangles; + continue; + } +#endif +#ifdef GL_ATI_separate_stencil + if (_glewStrSame3(&pos, &len, (const GLubyte*)"separate_stencil", 16)) + { + ret = GLEW_ATI_separate_stencil; + continue; + } +#endif +#ifdef GL_ATI_shader_texture_lod + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_texture_lod", 18)) + { + ret = GLEW_ATI_shader_texture_lod; + continue; + } +#endif +#ifdef GL_ATI_text_fragment_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"text_fragment_shader", 20)) + { + ret = GLEW_ATI_text_fragment_shader; + continue; + } +#endif +#ifdef GL_ATI_texture_compression_3dc + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_3dc", 23)) + { + ret = GLEW_ATI_texture_compression_3dc; + continue; + } +#endif +#ifdef GL_ATI_texture_env_combine3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine3", 20)) + { + ret = GLEW_ATI_texture_env_combine3; + continue; + } +#endif +#ifdef GL_ATI_texture_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_float", 13)) + { + ret = GLEW_ATI_texture_float; + continue; + } +#endif +#ifdef GL_ATI_texture_mirror_once + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirror_once", 19)) + { + ret = GLEW_ATI_texture_mirror_once; + continue; + } +#endif +#ifdef GL_ATI_vertex_array_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_object", 19)) + { + ret = GLEW_ATI_vertex_array_object; + continue; + } +#endif +#ifdef GL_ATI_vertex_attrib_array_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_attrib_array_object", 26)) + { + ret = GLEW_ATI_vertex_attrib_array_object; + continue; + } +#endif +#ifdef GL_ATI_vertex_streams + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_streams", 14)) + { + ret = GLEW_ATI_vertex_streams; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"EXT_", 4)) + { +#ifdef GL_EXT_422_pixels + if (_glewStrSame3(&pos, &len, (const GLubyte*)"422_pixels", 10)) + { + ret = GLEW_EXT_422_pixels; + continue; + } +#endif +#ifdef GL_EXT_Cg_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"Cg_shader", 9)) + { + ret = GLEW_EXT_Cg_shader; + continue; + } +#endif +#ifdef GL_EXT_abgr + if (_glewStrSame3(&pos, &len, (const GLubyte*)"abgr", 4)) + { + ret = GLEW_EXT_abgr; + continue; + } +#endif +#ifdef GL_EXT_bgra + if (_glewStrSame3(&pos, &len, (const GLubyte*)"bgra", 4)) + { + ret = GLEW_EXT_bgra; + continue; + } +#endif +#ifdef GL_EXT_bindable_uniform + if (_glewStrSame3(&pos, &len, (const GLubyte*)"bindable_uniform", 16)) + { + ret = GLEW_EXT_bindable_uniform; + continue; + } +#endif +#ifdef GL_EXT_blend_color + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_color", 11)) + { + ret = GLEW_EXT_blend_color; + continue; + } +#endif +#ifdef GL_EXT_blend_equation_separate + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_equation_separate", 23)) + { + ret = GLEW_EXT_blend_equation_separate; + continue; + } +#endif +#ifdef GL_EXT_blend_func_separate + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_func_separate", 19)) + { + ret = GLEW_EXT_blend_func_separate; + continue; + } +#endif +#ifdef GL_EXT_blend_logic_op + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_logic_op", 14)) + { + ret = GLEW_EXT_blend_logic_op; + continue; + } +#endif +#ifdef GL_EXT_blend_minmax + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_minmax", 12)) + { + ret = GLEW_EXT_blend_minmax; + continue; + } +#endif +#ifdef GL_EXT_blend_subtract + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_subtract", 14)) + { + ret = GLEW_EXT_blend_subtract; + continue; + } +#endif +#ifdef GL_EXT_clip_volume_hint + if (_glewStrSame3(&pos, &len, (const GLubyte*)"clip_volume_hint", 16)) + { + ret = GLEW_EXT_clip_volume_hint; + continue; + } +#endif +#ifdef GL_EXT_cmyka + if (_glewStrSame3(&pos, &len, (const GLubyte*)"cmyka", 5)) + { + ret = GLEW_EXT_cmyka; + continue; + } +#endif +#ifdef GL_EXT_color_subtable + if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_subtable", 14)) + { + ret = GLEW_EXT_color_subtable; + continue; + } +#endif +#ifdef GL_EXT_compiled_vertex_array + if (_glewStrSame3(&pos, &len, (const GLubyte*)"compiled_vertex_array", 21)) + { + ret = GLEW_EXT_compiled_vertex_array; + continue; + } +#endif +#ifdef GL_EXT_convolution + if (_glewStrSame3(&pos, &len, (const GLubyte*)"convolution", 11)) + { + ret = GLEW_EXT_convolution; + continue; + } +#endif +#ifdef GL_EXT_coordinate_frame + if (_glewStrSame3(&pos, &len, (const GLubyte*)"coordinate_frame", 16)) + { + ret = GLEW_EXT_coordinate_frame; + continue; + } +#endif +#ifdef GL_EXT_copy_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_texture", 12)) + { + ret = GLEW_EXT_copy_texture; + continue; + } +#endif +#ifdef GL_EXT_cull_vertex + if (_glewStrSame3(&pos, &len, (const GLubyte*)"cull_vertex", 11)) + { + ret = GLEW_EXT_cull_vertex; + continue; + } +#endif +#ifdef GL_EXT_depth_bounds_test + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_bounds_test", 17)) + { + ret = GLEW_EXT_depth_bounds_test; + continue; + } +#endif +#ifdef GL_EXT_draw_buffers2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers2", 13)) + { + ret = GLEW_EXT_draw_buffers2; + continue; + } +#endif +#ifdef GL_EXT_draw_instanced + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_instanced", 14)) + { + ret = GLEW_EXT_draw_instanced; + continue; + } +#endif +#ifdef GL_EXT_draw_range_elements + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_range_elements", 19)) + { + ret = GLEW_EXT_draw_range_elements; + continue; + } +#endif +#ifdef GL_EXT_fog_coord + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_coord", 9)) + { + ret = GLEW_EXT_fog_coord; + continue; + } +#endif +#ifdef GL_EXT_fragment_lighting + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_lighting", 17)) + { + ret = GLEW_EXT_fragment_lighting; + continue; + } +#endif +#ifdef GL_EXT_framebuffer_blit + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_blit", 16)) + { + ret = GLEW_EXT_framebuffer_blit; + continue; + } +#endif +#ifdef GL_EXT_framebuffer_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_multisample", 23)) + { + ret = GLEW_EXT_framebuffer_multisample; + continue; + } +#endif +#ifdef GL_EXT_framebuffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_object", 18)) + { + ret = GLEW_EXT_framebuffer_object; + continue; + } +#endif +#ifdef GL_EXT_framebuffer_sRGB + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16)) + { + ret = GLEW_EXT_framebuffer_sRGB; + continue; + } +#endif +#ifdef GL_EXT_geometry_shader4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"geometry_shader4", 16)) + { + ret = GLEW_EXT_geometry_shader4; + continue; + } +#endif +#ifdef GL_EXT_gpu_program_parameters + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program_parameters", 22)) + { + ret = GLEW_EXT_gpu_program_parameters; + continue; + } +#endif +#ifdef GL_EXT_gpu_shader4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_shader4", 11)) + { + ret = GLEW_EXT_gpu_shader4; + continue; + } +#endif +#ifdef GL_EXT_histogram + if (_glewStrSame3(&pos, &len, (const GLubyte*)"histogram", 9)) + { + ret = GLEW_EXT_histogram; + continue; + } +#endif +#ifdef GL_EXT_index_array_formats + if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_array_formats", 19)) + { + ret = GLEW_EXT_index_array_formats; + continue; + } +#endif +#ifdef GL_EXT_index_func + if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_func", 10)) + { + ret = GLEW_EXT_index_func; + continue; + } +#endif +#ifdef GL_EXT_index_material + if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_material", 14)) + { + ret = GLEW_EXT_index_material; + continue; + } +#endif +#ifdef GL_EXT_index_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_texture", 13)) + { + ret = GLEW_EXT_index_texture; + continue; + } +#endif +#ifdef GL_EXT_light_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"light_texture", 13)) + { + ret = GLEW_EXT_light_texture; + continue; + } +#endif +#ifdef GL_EXT_misc_attribute + if (_glewStrSame3(&pos, &len, (const GLubyte*)"misc_attribute", 14)) + { + ret = GLEW_EXT_misc_attribute; + continue; + } +#endif +#ifdef GL_EXT_multi_draw_arrays + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multi_draw_arrays", 17)) + { + ret = GLEW_EXT_multi_draw_arrays; + continue; + } +#endif +#ifdef GL_EXT_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = GLEW_EXT_multisample; + continue; + } +#endif +#ifdef GL_EXT_packed_depth_stencil + if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_depth_stencil", 20)) + { + ret = GLEW_EXT_packed_depth_stencil; + continue; + } +#endif +#ifdef GL_EXT_packed_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_float", 12)) + { + ret = GLEW_EXT_packed_float; + continue; + } +#endif +#ifdef GL_EXT_packed_pixels + if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_pixels", 13)) + { + ret = GLEW_EXT_packed_pixels; + continue; + } +#endif +#ifdef GL_EXT_paletted_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"paletted_texture", 16)) + { + ret = GLEW_EXT_paletted_texture; + continue; + } +#endif +#ifdef GL_EXT_pixel_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_buffer_object", 19)) + { + ret = GLEW_EXT_pixel_buffer_object; + continue; + } +#endif +#ifdef GL_EXT_pixel_transform + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_transform", 15)) + { + ret = GLEW_EXT_pixel_transform; + continue; + } +#endif +#ifdef GL_EXT_pixel_transform_color_table + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_transform_color_table", 27)) + { + ret = GLEW_EXT_pixel_transform_color_table; + continue; + } +#endif +#ifdef GL_EXT_point_parameters + if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_parameters", 16)) + { + ret = GLEW_EXT_point_parameters; + continue; + } +#endif +#ifdef GL_EXT_polygon_offset + if (_glewStrSame3(&pos, &len, (const GLubyte*)"polygon_offset", 14)) + { + ret = GLEW_EXT_polygon_offset; + continue; + } +#endif +#ifdef GL_EXT_rescale_normal + if (_glewStrSame3(&pos, &len, (const GLubyte*)"rescale_normal", 14)) + { + ret = GLEW_EXT_rescale_normal; + continue; + } +#endif +#ifdef GL_EXT_scene_marker + if (_glewStrSame3(&pos, &len, (const GLubyte*)"scene_marker", 12)) + { + ret = GLEW_EXT_scene_marker; + continue; + } +#endif +#ifdef GL_EXT_secondary_color + if (_glewStrSame3(&pos, &len, (const GLubyte*)"secondary_color", 15)) + { + ret = GLEW_EXT_secondary_color; + continue; + } +#endif +#ifdef GL_EXT_separate_specular_color + if (_glewStrSame3(&pos, &len, (const GLubyte*)"separate_specular_color", 23)) + { + ret = GLEW_EXT_separate_specular_color; + continue; + } +#endif +#ifdef GL_EXT_shadow_funcs + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow_funcs", 12)) + { + ret = GLEW_EXT_shadow_funcs; + continue; + } +#endif +#ifdef GL_EXT_shared_texture_palette + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shared_texture_palette", 22)) + { + ret = GLEW_EXT_shared_texture_palette; + continue; + } +#endif +#ifdef GL_EXT_stencil_clear_tag + if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_clear_tag", 17)) + { + ret = GLEW_EXT_stencil_clear_tag; + continue; + } +#endif +#ifdef GL_EXT_stencil_two_side + if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_two_side", 16)) + { + ret = GLEW_EXT_stencil_two_side; + continue; + } +#endif +#ifdef GL_EXT_stencil_wrap + if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_wrap", 12)) + { + ret = GLEW_EXT_stencil_wrap; + continue; + } +#endif +#ifdef GL_EXT_subtexture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"subtexture", 10)) + { + ret = GLEW_EXT_subtexture; + continue; + } +#endif +#ifdef GL_EXT_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture", 7)) + { + ret = GLEW_EXT_texture; + continue; + } +#endif +#ifdef GL_EXT_texture3D + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture3D", 9)) + { + ret = GLEW_EXT_texture3D; + continue; + } +#endif +#ifdef GL_EXT_texture_array + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_array", 13)) + { + ret = GLEW_EXT_texture_array; + continue; + } +#endif +#ifdef GL_EXT_texture_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_buffer_object", 21)) + { + ret = GLEW_EXT_texture_buffer_object; + continue; + } +#endif +#ifdef GL_EXT_texture_compression_dxt1 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_dxt1", 24)) + { + ret = GLEW_EXT_texture_compression_dxt1; + continue; + } +#endif +#ifdef GL_EXT_texture_compression_latc + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_latc", 24)) + { + ret = GLEW_EXT_texture_compression_latc; + continue; + } +#endif +#ifdef GL_EXT_texture_compression_rgtc + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_rgtc", 24)) + { + ret = GLEW_EXT_texture_compression_rgtc; + continue; + } +#endif +#ifdef GL_EXT_texture_compression_s3tc + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_s3tc", 24)) + { + ret = GLEW_EXT_texture_compression_s3tc; + continue; + } +#endif +#ifdef GL_EXT_texture_cube_map + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_cube_map", 16)) + { + ret = GLEW_EXT_texture_cube_map; + continue; + } +#endif +#ifdef GL_EXT_texture_edge_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_edge_clamp", 18)) + { + ret = GLEW_EXT_texture_edge_clamp; + continue; + } +#endif +#ifdef GL_EXT_texture_env + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env", 11)) + { + ret = GLEW_EXT_texture_env; + continue; + } +#endif +#ifdef GL_EXT_texture_env_add + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_add", 15)) + { + ret = GLEW_EXT_texture_env_add; + continue; + } +#endif +#ifdef GL_EXT_texture_env_combine + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine", 19)) + { + ret = GLEW_EXT_texture_env_combine; + continue; + } +#endif +#ifdef GL_EXT_texture_env_dot3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_dot3", 16)) + { + ret = GLEW_EXT_texture_env_dot3; + continue; + } +#endif +#ifdef GL_EXT_texture_filter_anisotropic + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_filter_anisotropic", 26)) + { + ret = GLEW_EXT_texture_filter_anisotropic; + continue; + } +#endif +#ifdef GL_EXT_texture_integer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_integer", 15)) + { + ret = GLEW_EXT_texture_integer; + continue; + } +#endif +#ifdef GL_EXT_texture_lod_bias + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lod_bias", 16)) + { + ret = GLEW_EXT_texture_lod_bias; + continue; + } +#endif +#ifdef GL_EXT_texture_mirror_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirror_clamp", 20)) + { + ret = GLEW_EXT_texture_mirror_clamp; + continue; + } +#endif +#ifdef GL_EXT_texture_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_object", 14)) + { + ret = GLEW_EXT_texture_object; + continue; + } +#endif +#ifdef GL_EXT_texture_perturb_normal + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_perturb_normal", 22)) + { + ret = GLEW_EXT_texture_perturb_normal; + continue; + } +#endif +#ifdef GL_EXT_texture_rectangle + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rectangle", 17)) + { + ret = GLEW_EXT_texture_rectangle; + continue; + } +#endif +#ifdef GL_EXT_texture_sRGB + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_sRGB", 12)) + { + ret = GLEW_EXT_texture_sRGB; + continue; + } +#endif +#ifdef GL_EXT_texture_shared_exponent + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shared_exponent", 23)) + { + ret = GLEW_EXT_texture_shared_exponent; + continue; + } +#endif +#ifdef GL_EXT_timer_query + if (_glewStrSame3(&pos, &len, (const GLubyte*)"timer_query", 11)) + { + ret = GLEW_EXT_timer_query; + continue; + } +#endif +#ifdef GL_EXT_vertex_array + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array", 12)) + { + ret = GLEW_EXT_vertex_array; + continue; + } +#endif +#ifdef GL_EXT_vertex_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader", 13)) + { + ret = GLEW_EXT_vertex_shader; + continue; + } +#endif +#ifdef GL_EXT_vertex_weighting + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_weighting", 16)) + { + ret = GLEW_EXT_vertex_weighting; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"GREMEDY_", 8)) + { +#ifdef GL_GREMEDY_frame_terminator + if (_glewStrSame3(&pos, &len, (const GLubyte*)"frame_terminator", 16)) + { + ret = GLEW_GREMEDY_frame_terminator; + continue; + } +#endif +#ifdef GL_GREMEDY_string_marker + if (_glewStrSame3(&pos, &len, (const GLubyte*)"string_marker", 13)) + { + ret = GLEW_GREMEDY_string_marker; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"HP_", 3)) + { +#ifdef GL_HP_convolution_border_modes + if (_glewStrSame3(&pos, &len, (const GLubyte*)"convolution_border_modes", 24)) + { + ret = GLEW_HP_convolution_border_modes; + continue; + } +#endif +#ifdef GL_HP_image_transform + if (_glewStrSame3(&pos, &len, (const GLubyte*)"image_transform", 15)) + { + ret = GLEW_HP_image_transform; + continue; + } +#endif +#ifdef GL_HP_occlusion_test + if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_test", 14)) + { + ret = GLEW_HP_occlusion_test; + continue; + } +#endif +#ifdef GL_HP_texture_lighting + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lighting", 16)) + { + ret = GLEW_HP_texture_lighting; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"IBM_", 4)) + { +#ifdef GL_IBM_cull_vertex + if (_glewStrSame3(&pos, &len, (const GLubyte*)"cull_vertex", 11)) + { + ret = GLEW_IBM_cull_vertex; + continue; + } +#endif +#ifdef GL_IBM_multimode_draw_arrays + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multimode_draw_arrays", 21)) + { + ret = GLEW_IBM_multimode_draw_arrays; + continue; + } +#endif +#ifdef GL_IBM_rasterpos_clip + if (_glewStrSame3(&pos, &len, (const GLubyte*)"rasterpos_clip", 14)) + { + ret = GLEW_IBM_rasterpos_clip; + continue; + } +#endif +#ifdef GL_IBM_static_data + if (_glewStrSame3(&pos, &len, (const GLubyte*)"static_data", 11)) + { + ret = GLEW_IBM_static_data; + continue; + } +#endif +#ifdef GL_IBM_texture_mirrored_repeat + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirrored_repeat", 23)) + { + ret = GLEW_IBM_texture_mirrored_repeat; + continue; + } +#endif +#ifdef GL_IBM_vertex_array_lists + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_lists", 18)) + { + ret = GLEW_IBM_vertex_array_lists; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"INGR_", 5)) + { +#ifdef GL_INGR_color_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_clamp", 11)) + { + ret = GLEW_INGR_color_clamp; + continue; + } +#endif +#ifdef GL_INGR_interlace_read + if (_glewStrSame3(&pos, &len, (const GLubyte*)"interlace_read", 14)) + { + ret = GLEW_INGR_interlace_read; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"INTEL_", 6)) + { +#ifdef GL_INTEL_parallel_arrays + if (_glewStrSame3(&pos, &len, (const GLubyte*)"parallel_arrays", 15)) + { + ret = GLEW_INTEL_parallel_arrays; + continue; + } +#endif +#ifdef GL_INTEL_texture_scissor + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_scissor", 15)) + { + ret = GLEW_INTEL_texture_scissor; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"KTX_", 4)) + { +#ifdef GL_KTX_buffer_region + if (_glewStrSame3(&pos, &len, (const GLubyte*)"buffer_region", 13)) + { + ret = GLEW_KTX_buffer_region; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"MESAX_", 6)) + { +#ifdef GL_MESAX_texture_stack + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_stack", 13)) + { + ret = GLEW_MESAX_texture_stack; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"MESA_", 5)) + { +#ifdef GL_MESA_pack_invert + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pack_invert", 11)) + { + ret = GLEW_MESA_pack_invert; + continue; + } +#endif +#ifdef GL_MESA_resize_buffers + if (_glewStrSame3(&pos, &len, (const GLubyte*)"resize_buffers", 14)) + { + ret = GLEW_MESA_resize_buffers; + continue; + } +#endif +#ifdef GL_MESA_window_pos + if (_glewStrSame3(&pos, &len, (const GLubyte*)"window_pos", 10)) + { + ret = GLEW_MESA_window_pos; + continue; + } +#endif +#ifdef GL_MESA_ycbcr_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"ycbcr_texture", 13)) + { + ret = GLEW_MESA_ycbcr_texture; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3)) + { +#ifdef GL_NV_blend_square + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_square", 12)) + { + ret = GLEW_NV_blend_square; + continue; + } +#endif +#ifdef GL_NV_copy_depth_to_color + if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_depth_to_color", 19)) + { + ret = GLEW_NV_copy_depth_to_color; + continue; + } +#endif +#ifdef GL_NV_depth_buffer_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_buffer_float", 18)) + { + ret = GLEW_NV_depth_buffer_float; + continue; + } +#endif +#ifdef GL_NV_depth_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_clamp", 11)) + { + ret = GLEW_NV_depth_clamp; + continue; + } +#endif +#ifdef GL_NV_depth_range_unclamped + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_range_unclamped", 21)) + { + ret = GLEW_NV_depth_range_unclamped; + continue; + } +#endif +#ifdef GL_NV_evaluators + if (_glewStrSame3(&pos, &len, (const GLubyte*)"evaluators", 10)) + { + ret = GLEW_NV_evaluators; + continue; + } +#endif +#ifdef GL_NV_fence + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fence", 5)) + { + ret = GLEW_NV_fence; + continue; + } +#endif +#ifdef GL_NV_float_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_buffer", 12)) + { + ret = GLEW_NV_float_buffer; + continue; + } +#endif +#ifdef GL_NV_fog_distance + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_distance", 12)) + { + ret = GLEW_NV_fog_distance; + continue; + } +#endif +#ifdef GL_NV_fragment_program + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program", 16)) + { + ret = GLEW_NV_fragment_program; + continue; + } +#endif +#ifdef GL_NV_fragment_program2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program2", 17)) + { + ret = GLEW_NV_fragment_program2; + continue; + } +#endif +#ifdef GL_NV_fragment_program4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program4", 17)) + { + ret = GLEW_NV_fragment_program4; + continue; + } +#endif +#ifdef GL_NV_fragment_program_option + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program_option", 23)) + { + ret = GLEW_NV_fragment_program_option; + continue; + } +#endif +#ifdef GL_NV_framebuffer_multisample_coverage + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_multisample_coverage", 32)) + { + ret = GLEW_NV_framebuffer_multisample_coverage; + continue; + } +#endif +#ifdef GL_NV_geometry_program4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"geometry_program4", 17)) + { + ret = GLEW_NV_geometry_program4; + continue; + } +#endif +#ifdef GL_NV_geometry_shader4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"geometry_shader4", 16)) + { + ret = GLEW_NV_geometry_shader4; + continue; + } +#endif +#ifdef GL_NV_gpu_program4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program4", 12)) + { + ret = GLEW_NV_gpu_program4; + continue; + } +#endif +#ifdef GL_NV_half_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"half_float", 10)) + { + ret = GLEW_NV_half_float; + continue; + } +#endif +#ifdef GL_NV_light_max_exponent + if (_glewStrSame3(&pos, &len, (const GLubyte*)"light_max_exponent", 18)) + { + ret = GLEW_NV_light_max_exponent; + continue; + } +#endif +#ifdef GL_NV_multisample_filter_hint + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample_filter_hint", 23)) + { + ret = GLEW_NV_multisample_filter_hint; + continue; + } +#endif +#ifdef GL_NV_occlusion_query + if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_query", 15)) + { + ret = GLEW_NV_occlusion_query; + continue; + } +#endif +#ifdef GL_NV_packed_depth_stencil + if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_depth_stencil", 20)) + { + ret = GLEW_NV_packed_depth_stencil; + continue; + } +#endif +#ifdef GL_NV_parameter_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"parameter_buffer_object", 23)) + { + ret = GLEW_NV_parameter_buffer_object; + continue; + } +#endif +#ifdef GL_NV_pixel_data_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_data_range", 16)) + { + ret = GLEW_NV_pixel_data_range; + continue; + } +#endif +#ifdef GL_NV_point_sprite + if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_sprite", 12)) + { + ret = GLEW_NV_point_sprite; + continue; + } +#endif +#ifdef GL_NV_primitive_restart + if (_glewStrSame3(&pos, &len, (const GLubyte*)"primitive_restart", 17)) + { + ret = GLEW_NV_primitive_restart; + continue; + } +#endif +#ifdef GL_NV_register_combiners + if (_glewStrSame3(&pos, &len, (const GLubyte*)"register_combiners", 18)) + { + ret = GLEW_NV_register_combiners; + continue; + } +#endif +#ifdef GL_NV_register_combiners2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"register_combiners2", 19)) + { + ret = GLEW_NV_register_combiners2; + continue; + } +#endif +#ifdef GL_NV_texgen_emboss + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texgen_emboss", 13)) + { + ret = GLEW_NV_texgen_emboss; + continue; + } +#endif +#ifdef GL_NV_texgen_reflection + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texgen_reflection", 17)) + { + ret = GLEW_NV_texgen_reflection; + continue; + } +#endif +#ifdef GL_NV_texture_compression_vtc + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_vtc", 23)) + { + ret = GLEW_NV_texture_compression_vtc; + continue; + } +#endif +#ifdef GL_NV_texture_env_combine4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine4", 20)) + { + ret = GLEW_NV_texture_env_combine4; + continue; + } +#endif +#ifdef GL_NV_texture_expand_normal + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_expand_normal", 21)) + { + ret = GLEW_NV_texture_expand_normal; + continue; + } +#endif +#ifdef GL_NV_texture_rectangle + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rectangle", 17)) + { + ret = GLEW_NV_texture_rectangle; + continue; + } +#endif +#ifdef GL_NV_texture_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shader", 14)) + { + ret = GLEW_NV_texture_shader; + continue; + } +#endif +#ifdef GL_NV_texture_shader2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shader2", 15)) + { + ret = GLEW_NV_texture_shader2; + continue; + } +#endif +#ifdef GL_NV_texture_shader3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shader3", 15)) + { + ret = GLEW_NV_texture_shader3; + continue; + } +#endif +#ifdef GL_NV_transform_feedback + if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback", 18)) + { + ret = GLEW_NV_transform_feedback; + continue; + } +#endif +#ifdef GL_NV_vertex_array_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18)) + { + ret = GLEW_NV_vertex_array_range; + continue; + } +#endif +#ifdef GL_NV_vertex_array_range2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range2", 19)) + { + ret = GLEW_NV_vertex_array_range2; + continue; + } +#endif +#ifdef GL_NV_vertex_program + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program", 14)) + { + ret = GLEW_NV_vertex_program; + continue; + } +#endif +#ifdef GL_NV_vertex_program1_1 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program1_1", 17)) + { + ret = GLEW_NV_vertex_program1_1; + continue; + } +#endif +#ifdef GL_NV_vertex_program2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program2", 15)) + { + ret = GLEW_NV_vertex_program2; + continue; + } +#endif +#ifdef GL_NV_vertex_program2_option + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program2_option", 22)) + { + ret = GLEW_NV_vertex_program2_option; + continue; + } +#endif +#ifdef GL_NV_vertex_program3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program3", 15)) + { + ret = GLEW_NV_vertex_program3; + continue; + } +#endif +#ifdef GL_NV_vertex_program4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program4", 15)) + { + ret = GLEW_NV_vertex_program4; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"OES_", 4)) + { +#ifdef GL_OES_byte_coordinates + if (_glewStrSame3(&pos, &len, (const GLubyte*)"byte_coordinates", 16)) + { + ret = GLEW_OES_byte_coordinates; + continue; + } +#endif +#ifdef GL_OES_compressed_paletted_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"compressed_paletted_texture", 27)) + { + ret = GLEW_OES_compressed_paletted_texture; + continue; + } +#endif +#ifdef GL_OES_read_format + if (_glewStrSame3(&pos, &len, (const GLubyte*)"read_format", 11)) + { + ret = GLEW_OES_read_format; + continue; + } +#endif +#ifdef GL_OES_single_precision + if (_glewStrSame3(&pos, &len, (const GLubyte*)"single_precision", 16)) + { + ret = GLEW_OES_single_precision; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"OML_", 4)) + { +#ifdef GL_OML_interlace + if (_glewStrSame3(&pos, &len, (const GLubyte*)"interlace", 9)) + { + ret = GLEW_OML_interlace; + continue; + } +#endif +#ifdef GL_OML_resample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"resample", 8)) + { + ret = GLEW_OML_resample; + continue; + } +#endif +#ifdef GL_OML_subsample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"subsample", 9)) + { + ret = GLEW_OML_subsample; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"PGI_", 4)) + { +#ifdef GL_PGI_misc_hints + if (_glewStrSame3(&pos, &len, (const GLubyte*)"misc_hints", 10)) + { + ret = GLEW_PGI_misc_hints; + continue; + } +#endif +#ifdef GL_PGI_vertex_hints + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_hints", 12)) + { + ret = GLEW_PGI_vertex_hints; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"REND_", 5)) + { +#ifdef GL_REND_screen_coordinates + if (_glewStrSame3(&pos, &len, (const GLubyte*)"screen_coordinates", 18)) + { + ret = GLEW_REND_screen_coordinates; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"S3_", 3)) + { +#ifdef GL_S3_s3tc + if (_glewStrSame3(&pos, &len, (const GLubyte*)"s3tc", 4)) + { + ret = GLEW_S3_s3tc; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIS_", 5)) + { +#ifdef GL_SGIS_color_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_range", 11)) + { + ret = GLEW_SGIS_color_range; + continue; + } +#endif +#ifdef GL_SGIS_detail_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"detail_texture", 14)) + { + ret = GLEW_SGIS_detail_texture; + continue; + } +#endif +#ifdef GL_SGIS_fog_function + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_function", 12)) + { + ret = GLEW_SGIS_fog_function; + continue; + } +#endif +#ifdef GL_SGIS_generate_mipmap + if (_glewStrSame3(&pos, &len, (const GLubyte*)"generate_mipmap", 15)) + { + ret = GLEW_SGIS_generate_mipmap; + continue; + } +#endif +#ifdef GL_SGIS_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = GLEW_SGIS_multisample; + continue; + } +#endif +#ifdef GL_SGIS_pixel_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_texture", 13)) + { + ret = GLEW_SGIS_pixel_texture; + continue; + } +#endif +#ifdef GL_SGIS_sharpen_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"sharpen_texture", 15)) + { + ret = GLEW_SGIS_sharpen_texture; + continue; + } +#endif +#ifdef GL_SGIS_texture4D + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture4D", 9)) + { + ret = GLEW_SGIS_texture4D; + continue; + } +#endif +#ifdef GL_SGIS_texture_border_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_border_clamp", 20)) + { + ret = GLEW_SGIS_texture_border_clamp; + continue; + } +#endif +#ifdef GL_SGIS_texture_edge_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_edge_clamp", 18)) + { + ret = GLEW_SGIS_texture_edge_clamp; + continue; + } +#endif +#ifdef GL_SGIS_texture_filter4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_filter4", 15)) + { + ret = GLEW_SGIS_texture_filter4; + continue; + } +#endif +#ifdef GL_SGIS_texture_lod + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lod", 11)) + { + ret = GLEW_SGIS_texture_lod; + continue; + } +#endif +#ifdef GL_SGIS_texture_select + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_select", 14)) + { + ret = GLEW_SGIS_texture_select; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIX_", 5)) + { +#ifdef GL_SGIX_async + if (_glewStrSame3(&pos, &len, (const GLubyte*)"async", 5)) + { + ret = GLEW_SGIX_async; + continue; + } +#endif +#ifdef GL_SGIX_async_histogram + if (_glewStrSame3(&pos, &len, (const GLubyte*)"async_histogram", 15)) + { + ret = GLEW_SGIX_async_histogram; + continue; + } +#endif +#ifdef GL_SGIX_async_pixel + if (_glewStrSame3(&pos, &len, (const GLubyte*)"async_pixel", 11)) + { + ret = GLEW_SGIX_async_pixel; + continue; + } +#endif +#ifdef GL_SGIX_blend_alpha_minmax + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_alpha_minmax", 18)) + { + ret = GLEW_SGIX_blend_alpha_minmax; + continue; + } +#endif +#ifdef GL_SGIX_clipmap + if (_glewStrSame3(&pos, &len, (const GLubyte*)"clipmap", 7)) + { + ret = GLEW_SGIX_clipmap; + continue; + } +#endif +#ifdef GL_SGIX_depth_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_texture", 13)) + { + ret = GLEW_SGIX_depth_texture; + continue; + } +#endif +#ifdef GL_SGIX_flush_raster + if (_glewStrSame3(&pos, &len, (const GLubyte*)"flush_raster", 12)) + { + ret = GLEW_SGIX_flush_raster; + continue; + } +#endif +#ifdef GL_SGIX_fog_offset + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_offset", 10)) + { + ret = GLEW_SGIX_fog_offset; + continue; + } +#endif +#ifdef GL_SGIX_fog_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_texture", 11)) + { + ret = GLEW_SGIX_fog_texture; + continue; + } +#endif +#ifdef GL_SGIX_fragment_specular_lighting + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_specular_lighting", 26)) + { + ret = GLEW_SGIX_fragment_specular_lighting; + continue; + } +#endif +#ifdef GL_SGIX_framezoom + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framezoom", 9)) + { + ret = GLEW_SGIX_framezoom; + continue; + } +#endif +#ifdef GL_SGIX_interlace + if (_glewStrSame3(&pos, &len, (const GLubyte*)"interlace", 9)) + { + ret = GLEW_SGIX_interlace; + continue; + } +#endif +#ifdef GL_SGIX_ir_instrument1 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"ir_instrument1", 14)) + { + ret = GLEW_SGIX_ir_instrument1; + continue; + } +#endif +#ifdef GL_SGIX_list_priority + if (_glewStrSame3(&pos, &len, (const GLubyte*)"list_priority", 13)) + { + ret = GLEW_SGIX_list_priority; + continue; + } +#endif +#ifdef GL_SGIX_pixel_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_texture", 13)) + { + ret = GLEW_SGIX_pixel_texture; + continue; + } +#endif +#ifdef GL_SGIX_pixel_texture_bits + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_texture_bits", 18)) + { + ret = GLEW_SGIX_pixel_texture_bits; + continue; + } +#endif +#ifdef GL_SGIX_reference_plane + if (_glewStrSame3(&pos, &len, (const GLubyte*)"reference_plane", 15)) + { + ret = GLEW_SGIX_reference_plane; + continue; + } +#endif +#ifdef GL_SGIX_resample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"resample", 8)) + { + ret = GLEW_SGIX_resample; + continue; + } +#endif +#ifdef GL_SGIX_shadow + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow", 6)) + { + ret = GLEW_SGIX_shadow; + continue; + } +#endif +#ifdef GL_SGIX_shadow_ambient + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow_ambient", 14)) + { + ret = GLEW_SGIX_shadow_ambient; + continue; + } +#endif +#ifdef GL_SGIX_sprite + if (_glewStrSame3(&pos, &len, (const GLubyte*)"sprite", 6)) + { + ret = GLEW_SGIX_sprite; + continue; + } +#endif +#ifdef GL_SGIX_tag_sample_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"tag_sample_buffer", 17)) + { + ret = GLEW_SGIX_tag_sample_buffer; + continue; + } +#endif +#ifdef GL_SGIX_texture_add_env + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_add_env", 15)) + { + ret = GLEW_SGIX_texture_add_env; + continue; + } +#endif +#ifdef GL_SGIX_texture_coordinate_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_coordinate_clamp", 24)) + { + ret = GLEW_SGIX_texture_coordinate_clamp; + continue; + } +#endif +#ifdef GL_SGIX_texture_lod_bias + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lod_bias", 16)) + { + ret = GLEW_SGIX_texture_lod_bias; + continue; + } +#endif +#ifdef GL_SGIX_texture_multi_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_multi_buffer", 20)) + { + ret = GLEW_SGIX_texture_multi_buffer; + continue; + } +#endif +#ifdef GL_SGIX_texture_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_range", 13)) + { + ret = GLEW_SGIX_texture_range; + continue; + } +#endif +#ifdef GL_SGIX_texture_scale_bias + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_scale_bias", 18)) + { + ret = GLEW_SGIX_texture_scale_bias; + continue; + } +#endif +#ifdef GL_SGIX_vertex_preclip + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_preclip", 14)) + { + ret = GLEW_SGIX_vertex_preclip; + continue; + } +#endif +#ifdef GL_SGIX_vertex_preclip_hint + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_preclip_hint", 19)) + { + ret = GLEW_SGIX_vertex_preclip_hint; + continue; + } +#endif +#ifdef GL_SGIX_ycrcb + if (_glewStrSame3(&pos, &len, (const GLubyte*)"ycrcb", 5)) + { + ret = GLEW_SGIX_ycrcb; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGI_", 4)) + { +#ifdef GL_SGI_color_matrix + if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_matrix", 12)) + { + ret = GLEW_SGI_color_matrix; + continue; + } +#endif +#ifdef GL_SGI_color_table + if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_table", 11)) + { + ret = GLEW_SGI_color_table; + continue; + } +#endif +#ifdef GL_SGI_texture_color_table + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_color_table", 19)) + { + ret = GLEW_SGI_texture_color_table; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SUNX_", 5)) + { +#ifdef GL_SUNX_constant_data + if (_glewStrSame3(&pos, &len, (const GLubyte*)"constant_data", 13)) + { + ret = GLEW_SUNX_constant_data; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SUN_", 4)) + { +#ifdef GL_SUN_convolution_border_modes + if (_glewStrSame3(&pos, &len, (const GLubyte*)"convolution_border_modes", 24)) + { + ret = GLEW_SUN_convolution_border_modes; + continue; + } +#endif +#ifdef GL_SUN_global_alpha + if (_glewStrSame3(&pos, &len, (const GLubyte*)"global_alpha", 12)) + { + ret = GLEW_SUN_global_alpha; + continue; + } +#endif +#ifdef GL_SUN_mesh_array + if (_glewStrSame3(&pos, &len, (const GLubyte*)"mesh_array", 10)) + { + ret = GLEW_SUN_mesh_array; + continue; + } +#endif +#ifdef GL_SUN_read_video_pixels + if (_glewStrSame3(&pos, &len, (const GLubyte*)"read_video_pixels", 17)) + { + ret = GLEW_SUN_read_video_pixels; + continue; + } +#endif +#ifdef GL_SUN_slice_accum + if (_glewStrSame3(&pos, &len, (const GLubyte*)"slice_accum", 11)) + { + ret = GLEW_SUN_slice_accum; + continue; + } +#endif +#ifdef GL_SUN_triangle_list + if (_glewStrSame3(&pos, &len, (const GLubyte*)"triangle_list", 13)) + { + ret = GLEW_SUN_triangle_list; + continue; + } +#endif +#ifdef GL_SUN_vertex + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex", 6)) + { + ret = GLEW_SUN_vertex; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"WIN_", 4)) + { +#ifdef GL_WIN_phong_shading + if (_glewStrSame3(&pos, &len, (const GLubyte*)"phong_shading", 13)) + { + ret = GLEW_WIN_phong_shading; + continue; + } +#endif +#ifdef GL_WIN_specular_fog + if (_glewStrSame3(&pos, &len, (const GLubyte*)"specular_fog", 12)) + { + ret = GLEW_WIN_specular_fog; + continue; + } +#endif +#ifdef GL_WIN_swap_hint + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_hint", 9)) + { + ret = GLEW_WIN_swap_hint; + continue; + } +#endif + } + } + ret = (len == 0); + } + return ret; +} + +#if defined(_WIN32) + +#if defined(GLEW_MX) +GLboolean wglewContextIsSupported (WGLEWContext* ctx, const char* name) +#else +GLboolean wglewIsSupported (const char* name) +#endif +{ + GLubyte* pos = (GLubyte*)name; + GLuint len = _glewStrLen(pos); + GLboolean ret = GL_TRUE; + while (ret && len > 0) + { + if (_glewStrSame1(&pos, &len, (const GLubyte*)"WGL_", 4)) + { + if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DFX_", 5)) + { +#ifdef WGL_3DFX_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = WGLEW_3DFX_multisample; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DL_", 4)) + { +#ifdef WGL_3DL_stereo_control + if (_glewStrSame3(&pos, &len, (const GLubyte*)"stereo_control", 14)) + { + ret = WGLEW_3DL_stereo_control; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"ARB_", 4)) + { +#ifdef WGL_ARB_buffer_region + if (_glewStrSame3(&pos, &len, (const GLubyte*)"buffer_region", 13)) + { + ret = WGLEW_ARB_buffer_region; + continue; + } +#endif +#ifdef WGL_ARB_extensions_string + if (_glewStrSame3(&pos, &len, (const GLubyte*)"extensions_string", 17)) + { + ret = WGLEW_ARB_extensions_string; + continue; + } +#endif +#ifdef WGL_ARB_make_current_read + if (_glewStrSame3(&pos, &len, (const GLubyte*)"make_current_read", 17)) + { + ret = WGLEW_ARB_make_current_read; + continue; + } +#endif +#ifdef WGL_ARB_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = WGLEW_ARB_multisample; + continue; + } +#endif +#ifdef WGL_ARB_pbuffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pbuffer", 7)) + { + ret = WGLEW_ARB_pbuffer; + continue; + } +#endif +#ifdef WGL_ARB_pixel_format + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format", 12)) + { + ret = WGLEW_ARB_pixel_format; + continue; + } +#endif +#ifdef WGL_ARB_pixel_format_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_float", 18)) + { + ret = WGLEW_ARB_pixel_format_float; + continue; + } +#endif +#ifdef WGL_ARB_render_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture", 14)) + { + ret = WGLEW_ARB_render_texture; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATI_", 4)) + { +#ifdef WGL_ATI_pixel_format_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_float", 18)) + { + ret = WGLEW_ATI_pixel_format_float; + continue; + } +#endif +#ifdef WGL_ATI_render_texture_rectangle + if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture_rectangle", 24)) + { + ret = WGLEW_ATI_render_texture_rectangle; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"EXT_", 4)) + { +#ifdef WGL_EXT_depth_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_float", 11)) + { + ret = WGLEW_EXT_depth_float; + continue; + } +#endif +#ifdef WGL_EXT_display_color_table + if (_glewStrSame3(&pos, &len, (const GLubyte*)"display_color_table", 19)) + { + ret = WGLEW_EXT_display_color_table; + continue; + } +#endif +#ifdef WGL_EXT_extensions_string + if (_glewStrSame3(&pos, &len, (const GLubyte*)"extensions_string", 17)) + { + ret = WGLEW_EXT_extensions_string; + continue; + } +#endif +#ifdef WGL_EXT_framebuffer_sRGB + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16)) + { + ret = WGLEW_EXT_framebuffer_sRGB; + continue; + } +#endif +#ifdef WGL_EXT_make_current_read + if (_glewStrSame3(&pos, &len, (const GLubyte*)"make_current_read", 17)) + { + ret = WGLEW_EXT_make_current_read; + continue; + } +#endif +#ifdef WGL_EXT_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = WGLEW_EXT_multisample; + continue; + } +#endif +#ifdef WGL_EXT_pbuffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pbuffer", 7)) + { + ret = WGLEW_EXT_pbuffer; + continue; + } +#endif +#ifdef WGL_EXT_pixel_format + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format", 12)) + { + ret = WGLEW_EXT_pixel_format; + continue; + } +#endif +#ifdef WGL_EXT_pixel_format_packed_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_packed_float", 25)) + { + ret = WGLEW_EXT_pixel_format_packed_float; + continue; + } +#endif +#ifdef WGL_EXT_swap_control + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control", 12)) + { + ret = WGLEW_EXT_swap_control; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"I3D_", 4)) + { +#ifdef WGL_I3D_digital_video_control + if (_glewStrSame3(&pos, &len, (const GLubyte*)"digital_video_control", 21)) + { + ret = WGLEW_I3D_digital_video_control; + continue; + } +#endif +#ifdef WGL_I3D_gamma + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gamma", 5)) + { + ret = WGLEW_I3D_gamma; + continue; + } +#endif +#ifdef WGL_I3D_genlock + if (_glewStrSame3(&pos, &len, (const GLubyte*)"genlock", 7)) + { + ret = WGLEW_I3D_genlock; + continue; + } +#endif +#ifdef WGL_I3D_image_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"image_buffer", 12)) + { + ret = WGLEW_I3D_image_buffer; + continue; + } +#endif +#ifdef WGL_I3D_swap_frame_lock + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_frame_lock", 15)) + { + ret = WGLEW_I3D_swap_frame_lock; + continue; + } +#endif +#ifdef WGL_I3D_swap_frame_usage + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_frame_usage", 16)) + { + ret = WGLEW_I3D_swap_frame_usage; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3)) + { +#ifdef WGL_NV_float_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_buffer", 12)) + { + ret = WGLEW_NV_float_buffer; + continue; + } +#endif +#ifdef WGL_NV_gpu_affinity + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_affinity", 12)) + { + ret = WGLEW_NV_gpu_affinity; + continue; + } +#endif +#ifdef WGL_NV_render_depth_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_depth_texture", 20)) + { + ret = WGLEW_NV_render_depth_texture; + continue; + } +#endif +#ifdef WGL_NV_render_texture_rectangle + if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture_rectangle", 24)) + { + ret = WGLEW_NV_render_texture_rectangle; + continue; + } +#endif +#ifdef WGL_NV_vertex_array_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18)) + { + ret = WGLEW_NV_vertex_array_range; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"OML_", 4)) + { +#ifdef WGL_OML_sync_control + if (_glewStrSame3(&pos, &len, (const GLubyte*)"sync_control", 12)) + { + ret = WGLEW_OML_sync_control; + continue; + } +#endif + } + } + ret = (len == 0); + } + return ret; +} + +#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) + +#if defined(GLEW_MX) +GLboolean glxewContextIsSupported (GLXEWContext* ctx, const char* name) +#else +GLboolean glxewIsSupported (const char* name) +#endif +{ + GLubyte* pos = (GLubyte*)name; + GLuint len = _glewStrLen(pos); + GLboolean ret = GL_TRUE; + while (ret && len > 0) + { + if(_glewStrSame1(&pos, &len, (const GLubyte*)"GLX_", 4)) + { + if (_glewStrSame2(&pos, &len, (const GLubyte*)"VERSION_", 8)) + { +#ifdef GLX_VERSION_1_2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_2", 3)) + { + ret = GLXEW_VERSION_1_2; + continue; + } +#endif +#ifdef GLX_VERSION_1_3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_3", 3)) + { + ret = GLXEW_VERSION_1_3; + continue; + } +#endif +#ifdef GLX_VERSION_1_4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_4", 3)) + { + ret = GLXEW_VERSION_1_4; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DFX_", 5)) + { +#ifdef GLX_3DFX_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = GLXEW_3DFX_multisample; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"ARB_", 4)) + { +#ifdef GLX_ARB_fbconfig_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbconfig_float", 14)) + { + ret = GLXEW_ARB_fbconfig_float; + continue; + } +#endif +#ifdef GLX_ARB_get_proc_address + if (_glewStrSame3(&pos, &len, (const GLubyte*)"get_proc_address", 16)) + { + ret = GLXEW_ARB_get_proc_address; + continue; + } +#endif +#ifdef GLX_ARB_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = GLXEW_ARB_multisample; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATI_", 4)) + { +#ifdef GLX_ATI_pixel_format_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_float", 18)) + { + ret = GLXEW_ATI_pixel_format_float; + continue; + } +#endif +#ifdef GLX_ATI_render_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture", 14)) + { + ret = GLXEW_ATI_render_texture; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"EXT_", 4)) + { +#ifdef GLX_EXT_fbconfig_packed_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbconfig_packed_float", 21)) + { + ret = GLXEW_EXT_fbconfig_packed_float; + continue; + } +#endif +#ifdef GLX_EXT_framebuffer_sRGB + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16)) + { + ret = GLXEW_EXT_framebuffer_sRGB; + continue; + } +#endif +#ifdef GLX_EXT_import_context + if (_glewStrSame3(&pos, &len, (const GLubyte*)"import_context", 14)) + { + ret = GLXEW_EXT_import_context; + continue; + } +#endif +#ifdef GLX_EXT_scene_marker + if (_glewStrSame3(&pos, &len, (const GLubyte*)"scene_marker", 12)) + { + ret = GLXEW_EXT_scene_marker; + continue; + } +#endif +#ifdef GLX_EXT_texture_from_pixmap + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_from_pixmap", 19)) + { + ret = GLXEW_EXT_texture_from_pixmap; + continue; + } +#endif +#ifdef GLX_EXT_visual_info + if (_glewStrSame3(&pos, &len, (const GLubyte*)"visual_info", 11)) + { + ret = GLXEW_EXT_visual_info; + continue; + } +#endif +#ifdef GLX_EXT_visual_rating + if (_glewStrSame3(&pos, &len, (const GLubyte*)"visual_rating", 13)) + { + ret = GLXEW_EXT_visual_rating; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"MESA_", 5)) + { +#ifdef GLX_MESA_agp_offset + if (_glewStrSame3(&pos, &len, (const GLubyte*)"agp_offset", 10)) + { + ret = GLXEW_MESA_agp_offset; + continue; + } +#endif +#ifdef GLX_MESA_copy_sub_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_sub_buffer", 15)) + { + ret = GLXEW_MESA_copy_sub_buffer; + continue; + } +#endif +#ifdef GLX_MESA_pixmap_colormap + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixmap_colormap", 15)) + { + ret = GLXEW_MESA_pixmap_colormap; + continue; + } +#endif +#ifdef GLX_MESA_release_buffers + if (_glewStrSame3(&pos, &len, (const GLubyte*)"release_buffers", 15)) + { + ret = GLXEW_MESA_release_buffers; + continue; + } +#endif +#ifdef GLX_MESA_set_3dfx_mode + if (_glewStrSame3(&pos, &len, (const GLubyte*)"set_3dfx_mode", 13)) + { + ret = GLXEW_MESA_set_3dfx_mode; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3)) + { +#ifdef GLX_NV_float_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_buffer", 12)) + { + ret = GLXEW_NV_float_buffer; + continue; + } +#endif +#ifdef GLX_NV_vertex_array_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18)) + { + ret = GLXEW_NV_vertex_array_range; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"OML_", 4)) + { +#ifdef GLX_OML_swap_method + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_method", 11)) + { + ret = GLXEW_OML_swap_method; + continue; + } +#endif +#if defined(GLX_OML_sync_control) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +#include + if (_glewStrSame3(&pos, &len, (const GLubyte*)"sync_control", 12)) + { + ret = GLXEW_OML_sync_control; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIS_", 5)) + { +#ifdef GLX_SGIS_blended_overlay + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blended_overlay", 15)) + { + ret = GLXEW_SGIS_blended_overlay; + continue; + } +#endif +#ifdef GLX_SGIS_color_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_range", 11)) + { + ret = GLXEW_SGIS_color_range; + continue; + } +#endif +#ifdef GLX_SGIS_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = GLXEW_SGIS_multisample; + continue; + } +#endif +#ifdef GLX_SGIS_shared_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shared_multisample", 18)) + { + ret = GLXEW_SGIS_shared_multisample; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIX_", 5)) + { +#ifdef GLX_SGIX_fbconfig + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbconfig", 8)) + { + ret = GLXEW_SGIX_fbconfig; + continue; + } +#endif +#ifdef GLX_SGIX_hyperpipe + if (_glewStrSame3(&pos, &len, (const GLubyte*)"hyperpipe", 9)) + { + ret = GLXEW_SGIX_hyperpipe; + continue; + } +#endif +#ifdef GLX_SGIX_pbuffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pbuffer", 7)) + { + ret = GLXEW_SGIX_pbuffer; + continue; + } +#endif +#ifdef GLX_SGIX_swap_barrier + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_barrier", 12)) + { + ret = GLXEW_SGIX_swap_barrier; + continue; + } +#endif +#ifdef GLX_SGIX_swap_group + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_group", 10)) + { + ret = GLXEW_SGIX_swap_group; + continue; + } +#endif +#ifdef GLX_SGIX_video_resize + if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_resize", 12)) + { + ret = GLXEW_SGIX_video_resize; + continue; + } +#endif +#ifdef GLX_SGIX_visual_select_group + if (_glewStrSame3(&pos, &len, (const GLubyte*)"visual_select_group", 19)) + { + ret = GLXEW_SGIX_visual_select_group; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGI_", 4)) + { +#ifdef GLX_SGI_cushion + if (_glewStrSame3(&pos, &len, (const GLubyte*)"cushion", 7)) + { + ret = GLXEW_SGI_cushion; + continue; + } +#endif +#ifdef GLX_SGI_make_current_read + if (_glewStrSame3(&pos, &len, (const GLubyte*)"make_current_read", 17)) + { + ret = GLXEW_SGI_make_current_read; + continue; + } +#endif +#ifdef GLX_SGI_swap_control + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control", 12)) + { + ret = GLXEW_SGI_swap_control; + continue; + } +#endif +#ifdef GLX_SGI_video_sync + if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_sync", 10)) + { + ret = GLXEW_SGI_video_sync; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SUN_", 4)) + { +#ifdef GLX_SUN_get_transparent_index + if (_glewStrSame3(&pos, &len, (const GLubyte*)"get_transparent_index", 21)) + { + ret = GLXEW_SUN_get_transparent_index; + continue; + } +#endif +#ifdef GLX_SUN_video_resize + if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_resize", 12)) + { + ret = GLXEW_SUN_video_resize; + continue; + } +#endif + } + } + ret = (len == 0); + } + return ret; +} + +#endif /* _WIN32 */ diff --git a/test_conformance/gl/Jamfile b/test_conformance/gl/Jamfile new file mode 100644 index 00000000..5064d5e5 --- /dev/null +++ b/test_conformance/gl/Jamfile @@ -0,0 +1,28 @@ +project + : requirements +# gcc:-xc++ +# msvc:"/TP" + ; + +exe test_gl + : helpers.cpp + main.cpp + test_buffers.cpp + test_images_2D.cpp + test_images_2D_info.cpp + test_images_3D.cpp + test_images_3D_info.cpp + test_renderbuffer.cpp + test_renderbuffer_info.cpp + : darwin:setup_osx.cpp + linux:setup_x11.cpp + windows:setup_win32.cpp + ../..//glut + ../..//glew + ; + +install dist + : test_gl + : debug:$(DIST)/debug/tests/test_conformance/gl + release:$(DIST)/release/tests/test_conformance/gl + ; diff --git a/test_conformance/gl/Makefile b/test_conformance/gl/Makefile new file mode 100644 index 00000000..521e0688 --- /dev/null +++ b/test_conformance/gl/Makefile @@ -0,0 +1,62 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.cpp \ + helpers.cpp \ + test_buffers.cpp \ + test_fence_sync.cpp \ + test_images_1D.cpp \ + test_images_1Darray.cpp \ + test_images_2Darray.cpp \ + test_images_2D.cpp \ + test_images_3D.cpp \ + test_images_getinfo_common.cpp \ + test_images_read_common.cpp \ + test_images_write_common.cpp \ + test_renderbuffer.cpp \ + test_renderbuffer_info.cpp \ + test_images_depth.cpp \ + test_images_multisample.cpp \ + test_image_methods.cpp \ + ../../test_common/gl/helpers.cpp \ + ../../test_common/gl/setup_osx.cpp \ + ../../test_common/harness/conversions.c \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/genericThread.cpp \ + ../../test_common/harness/imageHelpers.c \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/threadTesting.c + +DEFINES = + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = $(SOURCES) +HEADERS = +TARGET = test_gl +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/gl/common.h b/test_conformance/gl/common.h new file mode 100644 index 00000000..36221da1 --- /dev/null +++ b/test_conformance/gl/common.h @@ -0,0 +1,78 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include "testBase.h" + +typedef struct { + size_t width; + size_t height; + size_t depth; +} sizevec_t; + +struct format { + GLenum internal; + GLenum formattype; + GLenum datatype; + ExplicitType type; +}; + +// These are the typically tested formats. + +static struct format common_formats[] = { +#ifdef __APPLE__ + { GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, kUChar }, + { GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + // { GL_RGB10, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, kFloat }, +#endif + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar }, + { GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort }, + { GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt }, + { GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt }, + { GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat }, + { GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT, kHalf } +}; + +#ifdef GL_VERSION_3_2 +static struct format depth_formats[] = { + { GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, kUShort }, + { GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, kFloat }, + { GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, kUInt }, + { GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, kFloat }, +}; +#endif + +int test_images_write_common(cl_device_id device, cl_context context, + cl_command_queue queue, struct format* formats, size_t nformats, + GLenum *targets, size_t ntargets, sizevec_t* sizes, size_t nsizes ); + +int test_images_read_common( cl_device_id device, cl_context context, + cl_command_queue queue, struct format* formats, size_t nformats, + GLenum *targets, size_t ntargets, sizevec_t *sizes, size_t nsizes ); + +int test_images_get_info_common( cl_device_id device, cl_context context, + cl_command_queue queue, struct format* formats, size_t nformats, + GLenum *targets, size_t ntargets, sizevec_t *sizes, size_t nsizes ); + +int is_rgb_101010_supported( cl_context context, GLenum gl_target ); + +#endif // __COMMON_H__ diff --git a/test_conformance/gl/helpers.cpp b/test_conformance/gl/helpers.cpp new file mode 100644 index 00000000..864059ba --- /dev/null +++ b/test_conformance/gl/helpers.cpp @@ -0,0 +1,657 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#if defined( __APPLE__ ) + #include +#else + #include +#endif + +const char *get_kernel_suffix( cl_image_format *format ) +{ + switch( format->image_channel_data_type ) + { + case CL_UNORM_INT8: + case CL_UNORM_INT16: + case CL_UNORM_INT24: + case CL_SNORM_INT8: + case CL_SNORM_INT16: + case CL_HALF_FLOAT: + case CL_FLOAT: + case CL_UNORM_INT_101010: + return "f"; + case CL_SIGNED_INT8: + case CL_SIGNED_INT16: + case CL_SIGNED_INT32: + return "i"; + case CL_UNSIGNED_INT8: + case CL_UNSIGNED_INT16: + case CL_UNSIGNED_INT32: + return "ui"; + default: + log_error("Test error: unsupported kernel suffix for image_channel_data_type 0x%X\n",format->image_channel_data_type); + return ""; + } +} + +ExplicitType get_read_kernel_type( cl_image_format *format ) +{ + switch( format->image_channel_data_type ) + { + case CL_UNORM_INT8: + case CL_UNORM_INT16: + case CL_UNORM_INT24: + case CL_SNORM_INT8: + case CL_SNORM_INT16: + case CL_HALF_FLOAT: + case CL_FLOAT: + case CL_UNORM_INT_101010: +#ifdef GL_VERSION_3_2 + case CL_DEPTH: +#endif + return kFloat; + case CL_SIGNED_INT8: + case CL_SIGNED_INT16: + case CL_SIGNED_INT32: + return kInt; + case CL_UNSIGNED_INT8: + case CL_UNSIGNED_INT16: + case CL_UNSIGNED_INT32: + return kUInt; + default: + log_error("Test error: unsupported kernel suffix for image_channel_data_type 0x%X\n",format->image_channel_data_type); + return kNumExplicitTypes; + } +} + +ExplicitType get_write_kernel_type( cl_image_format *format ) +{ + switch( format->image_channel_data_type ) + { + case CL_UNORM_INT8: + return kFloat; + case CL_UNORM_INT16: + return kFloat; + case CL_UNORM_INT24: + return kFloat; + case CL_SNORM_INT8: + return kFloat; + case CL_SNORM_INT16: + return kFloat; + case CL_HALF_FLOAT: + return kHalf; + case CL_FLOAT: + return kFloat; + case CL_SIGNED_INT8: + return kChar; + case CL_SIGNED_INT16: + return kShort; + case CL_SIGNED_INT32: + return kInt; + case CL_UNSIGNED_INT8: + return kUChar; + case CL_UNSIGNED_INT16: + return kUShort; + case CL_UNSIGNED_INT32: + return kUInt; + case CL_UNORM_INT_101010: + return kFloat; +#ifdef GL_VERSION_3_2 + case CL_DEPTH: + return kFloat; +#endif + default: + return kInt; + } +} + +const char* get_write_conversion( cl_image_format *format, ExplicitType type ) +{ + switch( format->image_channel_data_type ) + { + case CL_UNORM_INT8: + case CL_UNORM_INT16: + case CL_SNORM_INT8: + case CL_SNORM_INT16: + case CL_HALF_FLOAT: + case CL_FLOAT: + case CL_UNORM_INT_101010: + case CL_UNORM_INT24: + if(type != kFloat) return "convert_float4"; + break; + case CL_SIGNED_INT8: + case CL_SIGNED_INT16: + case CL_SIGNED_INT32: + if(type != kInt) return "convert_int4"; + break; + case CL_UNSIGNED_INT8: + case CL_UNSIGNED_INT16: + case CL_UNSIGNED_INT32: + if(type != kUInt) return "convert_uint4"; + break; + default: + return ""; + } + return ""; +} + +// The only three input types to this function are kInt, kUInt and kFloat, due to the way we set up our tests +// The output types, though, are pretty much anything valid for GL to receive + +#define DOWNSCALE_INTEGER_CASE( enum, type, bitShift ) \ + case enum: \ + { \ + cl_##type *dst = new cl_##type[ numPixels * 4 ]; \ + for( size_t i = 0; i < numPixels * 4; i++ ) \ + dst[ i ] = src[ i ]; \ + return (char *)dst; \ + } + +#define UPSCALE_FLOAT_CASE( enum, type, typeMax ) \ + case enum: \ + { \ + cl_##type *dst = new cl_##type[ numPixels * 4 ]; \ + for( size_t i = 0; i < numPixels * 4; i++ ) \ + dst[ i ] = (cl_##type)( src[ i ] * typeMax ); \ + return (char *)dst; \ + } + +char * convert_to_expected( void * inputBuffer, size_t numPixels, ExplicitType inType, ExplicitType outType, size_t channelNum, GLenum glDataType ) +{ +#ifdef DEBUG + log_info( "- Converting from input type '%s' to output type '%s'\n", + get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); +#endif + + if( inType == outType ) + { + char *outData = new char[ numPixels * channelNum * get_explicit_type_size(outType) ] ; // sizeof( cl_int ) ]; + if (glDataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV) { + for (size_t i = 0; i < numPixels; ++i) { + ((cl_float*)outData)[i] = ((cl_float*)inputBuffer)[2 * i]; + } + } + else { + memcpy( outData, inputBuffer, numPixels * channelNum * get_explicit_type_size(inType) ); + } + return outData; + } + else if( inType == kChar ) + { + cl_char *src = (cl_char *)inputBuffer; + + switch( outType ) + { + case kInt: + { + cl_int *outData = new cl_int[ numPixels * channelNum ]; + for( size_t i = 0; i < numPixels * channelNum; i++ ) + { + outData[ i ] = (cl_int)((src[ i ])); + } + return (char *)outData; + } + case kFloat: + { + // If we're converting to float, then CL decided that we should be normalized + cl_float *outData = new cl_float[ numPixels * channelNum ]; + for( size_t i = 0; i < numPixels * channelNum; i++ ) + { + outData[ i ] = (cl_float)src[ i ] / 127.0f; + } + return (char *)outData; + } + default: + log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); + return NULL; + } + } + else if( inType == kUChar ) + { + cl_uchar *src = (cl_uchar *)inputBuffer; + + switch( outType ) + { + case kUInt: + { + cl_uint *outData = new cl_uint[ numPixels * channelNum ]; + for( size_t i = 0; i < numPixels * channelNum; i++ ) + { + outData[ i ] = (cl_uint)((src[ i ])); + } + return (char *)outData; + } + case kFloat: + { + // If we're converting to float, then CL decided that we should be normalized + cl_float *outData = new cl_float[ numPixels * channelNum ]; + for( size_t i = 0; i < numPixels * channelNum; i++ ) + { + outData[ i ] = (cl_float)(src[ i ]) / 256.0f; + } + return (char *)outData; + } + default: + log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); + return NULL; + } + } + else if( inType == kShort ) + { + cl_short *src = (cl_short *)inputBuffer; + + switch( outType ) + { + case kInt: + { + cl_int *outData = new cl_int[ numPixels * channelNum ]; + for( size_t i = 0; i < numPixels * channelNum; i++ ) + { + outData[ i ] = (cl_int)((src[ i ])); + } + return (char *)outData; + } + case kFloat: + { + // If we're converting to float, then CL decided that we should be normalized + cl_float *outData = new cl_float[ numPixels * channelNum ]; + for( size_t i = 0; i < numPixels * channelNum; i++ ) + { + outData[ i ] = (cl_float)src[ i ] / 32768.0f; + } + return (char *)outData; + } + default: + log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); + return NULL; + } + } + else if( inType == kUShort ) + { + cl_ushort *src = (cl_ushort *)inputBuffer; + + switch( outType ) + { + case kUInt: + { + cl_uint *outData = new cl_uint[ numPixels * channelNum ]; + for( size_t i = 0; i < numPixels * channelNum; i++ ) + { + outData[ i ] = (cl_uint)((src[ i ])); + } + return (char *)outData; + } + case kFloat: + { + // If we're converting to float, then CL decided that we should be normalized + cl_float *outData = new cl_float[ numPixels * channelNum ]; + for( size_t i = 0; i < numPixels * channelNum; i++ ) + { + outData[ i ] = (cl_float)(src[ i ]) / 65535.0f; + } + return (char *)outData; + } + default: + log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); + return NULL; + } + } + else if( inType == kInt ) + { + cl_int *src = (cl_int *)inputBuffer; + + switch( outType ) + { + DOWNSCALE_INTEGER_CASE( kShort, short, 16 ) + DOWNSCALE_INTEGER_CASE( kChar, char, 24 ) + case kFloat: + { + // If we're converting to float, then CL decided that we should be normalized + cl_float *outData = new cl_float[ numPixels * channelNum ]; + for( size_t i = 0; i < numPixels * channelNum; i++ ) + { + outData[ i ] = (cl_float)fmaxf( (float)src[ i ] / 2147483647.f, -1.f ); + } + return (char *)outData; + } + default: + log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); + return NULL; + } + } + else if( inType == kUInt ) + { + cl_uint *src = (cl_uint *)inputBuffer; + + switch( outType ) + { + DOWNSCALE_INTEGER_CASE( kUShort, ushort, 16 ) + DOWNSCALE_INTEGER_CASE( kUChar, uchar, 24 ) + case kFloat: + { + // If we're converting to float, then CL decided that we should be normalized + cl_float *outData = new cl_float[ numPixels * channelNum ]; + const cl_float MaxValue = (glDataType == GL_UNSIGNED_INT_24_8) ? 16777215.f : 4294967295.f; + const cl_uint ShiftBits = (glDataType == GL_UNSIGNED_INT_24_8) ? 8 : 0; + for( size_t i = 0; i < numPixels * channelNum; i++ ) + { + outData[ i ] = (cl_float)(src[ i ] >> ShiftBits) / MaxValue; + } + return (char *)outData; + } + default: + log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); + return NULL; + } + } + else if( inType == kHalf ) + { + cl_half *src = (cl_half *)inputBuffer; + + switch( outType ) + { + case kFloat: + { + cl_float *outData = new cl_float[ numPixels * channelNum ]; + for( size_t i = 0; i < numPixels * channelNum; i++ ) + { + outData[ i ] = convert_half_to_float(src[ i ]); + } + return (char *)outData; + } + default: + log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); + return NULL; + } + } + else + { + cl_float *src = (cl_float *)inputBuffer; + + switch( outType ) + { + UPSCALE_FLOAT_CASE( kChar, char, 127.f ) + UPSCALE_FLOAT_CASE( kUChar, uchar, 255.f ) + UPSCALE_FLOAT_CASE( kShort, short, 32767.f ) + UPSCALE_FLOAT_CASE( kUShort, ushort, 65535.f ) + UPSCALE_FLOAT_CASE( kInt, int, 2147483647.f ) + UPSCALE_FLOAT_CASE( kUInt, uint, 4294967295.f ) + default: + log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); + return NULL; + } + } + + return NULL; +} + +int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t sampleNum, size_t typeSize ) +{ + return validate_integer_results( expectedResults, actualResults, width, height, sampleNum, 0, typeSize ); +} + +int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t sampleNum, size_t typeSize ) +{ + char *expected = (char *)expectedResults; + char *actual = (char *)actualResults; + for ( size_t s = 0; s < sampleNum; s++ ) + { + for( size_t z = 0; z < ( ( depth == 0 ) ? 1 : depth ); z++ ) + { + for( size_t y = 0; y < height; y++ ) + { + for( size_t x = 0; x < width; x++ ) + { + if( memcmp( expected, actual, typeSize * 4 ) != 0 ) + { + char scratch[ 1024 ]; + + if( depth == 0 ) + log_error( "ERROR: Data sample %d,%d,%d did not validate!\n", (int)x, (int)y, (int)s ); + else + log_error( "ERROR: Data sample %d,%d,%d,%d did not validate!\n", (int)x, (int)y, (int)z, (int)s ); + log_error( "\tExpected: %s\n", GetDataVectorString( expected, typeSize, 4, scratch ) ); + log_error( "\t Actual: %s\n", GetDataVectorString( actual, typeSize, 4, scratch ) ); + return -1; + } + expected += typeSize * 4; + actual += typeSize * 4; + } + } + } + } + + return 0; +} + +int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t sampleNum, size_t channelNum ) +{ + return validate_float_results( expectedResults, actualResults, width, height, sampleNum, 0, channelNum ); +} + +int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t sampleNum, size_t channelNum ) +{ + cl_float *expected = (cl_float *)expectedResults; + cl_float *actual = (cl_float *)actualResults; + for ( size_t s = 0; s < sampleNum; s++ ) + { + for( size_t z = 0; z < ( ( depth == 0 ) ? 1 : depth ); z++ ) + { + for( size_t y = 0; y < height; y++ ) + { + for( size_t x = 0; x < width; x++ ) + { + float err = 0.f; + for( size_t i = 0; i < channelNum; i++ ) + { + float error = fabsf( expected[ i ] - actual[ i ] ); + if( error > err ) + err = error; + } + + if( err > 1.f / 127.f ) // Max expected range of error if we converted from an 8-bit integer to a normalized float + { + if( depth == 0 ) + log_error( "ERROR: Data sample %d,%d,%d did not validate!\n", (int)x, (int)y, (int)s ); + else + log_error( "ERROR: Data sample %d,%d,%d,%d did not validate!\n", (int)x, (int)y, (int)z, (int)s ); + + if (channelNum == 4) + { + log_error( "\tExpected: %f %f %f %f\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] ); + log_error( "\t : %a %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] ); + log_error( "\t Actual: %f %f %f %f\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] ); + log_error( "\t : %a %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] ); + } + else if(channelNum == 1) + { + log_error( "\tExpected: %f\n", expected[ 0 ] ); + log_error( "\t : %a\n", expected[ 0 ] ); + log_error( "\t Actual: %f\n", actual[ 0 ] ); + log_error( "\t : %a\n", actual[ 0 ] ); + } + return -1; + } + expected += channelNum; + actual += channelNum; + } + } + } + } + + return 0; +} + +int validate_float_results_rgb_101010( void *expectedResults, void *actualResults, size_t width, size_t height, size_t sampleNum ) +{ + return validate_float_results_rgb_101010( expectedResults, actualResults, width, height, sampleNum, 0 ); +} + +int validate_float_results_rgb_101010( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t sampleNum ) +{ + cl_float *expected = (cl_float *)expectedResults; + cl_float *actual = (cl_float *)actualResults; + for ( size_t s = 0; s < sampleNum; s++ ) + { + for( size_t z = 0; z < ( ( depth == 0 ) ? 1 : depth ); z++ ) + { + for( size_t y = 0; y < height; y++ ) + { + for( size_t x = 0; x < width; x++ ) + { + float err = 0.f; + for( size_t i = 0; i < 3; i++ ) // skip the fourth channel + { + float error = fabsf( expected[ i ] - actual[ i ] ); + if( error > err ) + err = error; + } + + if( err > 1.f / 127.f ) // Max expected range of error if we converted from an 8-bit integer to a normalized float + { + if( depth == 0 ) + log_error( "ERROR: Data sample %d,%d,%d did not validate!\n", (int)x, (int)y, (int)s ); + else + log_error( "ERROR: Data sample %d,%d,%d,%d did not validate!\n", (int)x, (int)y, (int)z, (int)s ); + log_error( "\tExpected: %f %f %f\n", expected[ 0 ], expected[ 1 ], expected[ 2 ] ); + log_error( "\t : %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ] ); + log_error( "\t Actual: %f %f %f\n", actual[ 0 ], actual[ 1 ], actual[ 2 ] ); + log_error( "\t : %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ] ); + return -1; + } + expected += 4; + actual += 4; + } + } + } + } + + return 0; +} + +int CheckGLObjectInfo(cl_mem mem, cl_gl_object_type expected_cl_gl_type, GLuint expected_gl_name, + GLenum expected_cl_gl_texture_target, GLint expected_cl_gl_mipmap_level) +{ + cl_gl_object_type object_type; + GLuint object_name; + GLenum texture_target; + GLint mipmap_level; + int error; + + error = (*clGetGLObjectInfo_ptr)(mem, &object_type, &object_name); + test_error( error, "clGetGLObjectInfo failed"); + if (object_type != expected_cl_gl_type) { + log_error("clGetGLObjectInfo did not return expected object type: expected %d, got %d.\n", expected_cl_gl_type, object_type); + return -1; + } + if (object_name != expected_gl_name) { + log_error("clGetGLObjectInfo did not return expected object name: expected %d, got %d.\n", expected_gl_name, object_name); + return -1; + } + + // If we're dealing with a buffer or render buffer, we are done. + + if (object_type == CL_GL_OBJECT_BUFFER || object_type == CL_GL_OBJECT_RENDERBUFFER) { + return 0; + } + + // Otherwise, it's a texture-based object and requires a bit more checking. + + error = (*clGetGLTextureInfo_ptr)(mem, CL_GL_TEXTURE_TARGET, sizeof(texture_target), &texture_target, NULL); + test_error( error, "clGetGLTextureInfo for CL_GL_TEXTURE_TARGET failed"); + + if (texture_target != expected_cl_gl_texture_target) { + log_error("clGetGLTextureInfo did not return expected texture target: expected %d, got %d.\n", expected_cl_gl_texture_target, texture_target); + return -1; + } + + error = (*clGetGLTextureInfo_ptr)(mem, CL_GL_MIPMAP_LEVEL, sizeof(mipmap_level), &mipmap_level, NULL); + test_error( error, "clGetGLTextureInfo for CL_GL_MIPMAP_LEVEL failed"); + + if (mipmap_level != expected_cl_gl_mipmap_level) { + log_error("clGetGLTextureInfo did not return expected mipmap level: expected %d, got %d.\n", expected_cl_gl_mipmap_level, mipmap_level); + return -1; + } + + return 0; +} + +bool CheckGLIntegerExtensionSupport() +{ + // Get the OpenGL version and supported extensions + const GLubyte *glVersion = glGetString(GL_VERSION); + const GLubyte *glExtensionList = glGetString(GL_EXTENSIONS); + + // Check if the OpenGL vrsion is 3.0 or grater or GL_EXT_texture_integer is supported + return (((glVersion[0] - '0') >= 3) || (strstr((const char*)glExtensionList, "GL_EXT_texture_integer"))); +} + +int is_rgb_101010_supported( cl_context context, GLenum gl_target ) +{ + cl_image_format formatList[ 128 ]; + cl_uint formatCount = 0; + unsigned int i; + int error; + + cl_mem_object_type image_type; + + switch (get_base_gl_target(gl_target)) { + case GL_TEXTURE_1D: + image_type = CL_MEM_OBJECT_IMAGE1D; + case GL_TEXTURE_BUFFER: + image_type = CL_MEM_OBJECT_IMAGE1D_BUFFER; + break; + case GL_TEXTURE_RECTANGLE_EXT: + case GL_TEXTURE_2D: + case GL_COLOR_ATTACHMENT0: + case GL_RENDERBUFFER: + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + image_type = CL_MEM_OBJECT_IMAGE2D; + break; + case GL_TEXTURE_3D: + image_type = CL_MEM_OBJECT_IMAGE3D; + case GL_TEXTURE_1D_ARRAY: + image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + case GL_TEXTURE_2D_ARRAY: + image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + break; + default: + image_type = CL_MEM_OBJECT_IMAGE2D; + } + + if ((error = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, + image_type, 128, formatList, + &formatCount ))) { + return error; + } + + // Check if the RGB 101010 format is supported + for( i = 0; i < formatCount; i++ ) + { + if( formatList[ i ].image_channel_data_type == CL_UNORM_INT_101010 ) + { + return 1; + } + } + + return 0; +} diff --git a/test_conformance/gl/main.cpp b/test_conformance/gl/main.cpp new file mode 100644 index 00000000..5b223784 --- /dev/null +++ b/test_conformance/gl/main.cpp @@ -0,0 +1,453 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include + +#if !defined (__APPLE__) +#include +#endif + +#include "procs.h" +#include "../../test_common/gl/setup.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/parseParameters.h" + +#if !defined(_WIN32) +#include +#endif + +static cl_context sCurrentContext = NULL; + + +#define TEST_FN_REDIRECT( fn ) redirect_##fn +#define TEST_FN_REDIRECTOR( fn ) \ +int redirect_##fn(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) \ +{ \ + int error; \ + clCommandQueueWrapper realQueue = clCreateCommandQueueWithProperties( sCurrentContext, device, 0, &error ); \ + test_error( error, "Unable to create command queue" ); \ + return fn( device, sCurrentContext, realQueue, numElements ); \ +} + +// buffers: +TEST_FN_REDIRECTOR( test_buffers ) +TEST_FN_REDIRECTOR( test_buffers_getinfo ) + +// 1D images: +TEST_FN_REDIRECTOR( test_images_read_1D ) +TEST_FN_REDIRECTOR( test_images_write_1D ) +TEST_FN_REDIRECTOR( test_images_1D_getinfo ) + +// 1D image arrays: +TEST_FN_REDIRECTOR( test_images_read_1Darray ) +TEST_FN_REDIRECTOR( test_images_write_1Darray ) +TEST_FN_REDIRECTOR( test_images_1Darray_getinfo ) + +// 2D images: +TEST_FN_REDIRECTOR( test_images_read_2D ) +TEST_FN_REDIRECTOR( test_images_read_cube ) +TEST_FN_REDIRECTOR( test_images_write ) +TEST_FN_REDIRECTOR( test_images_write_cube ) +TEST_FN_REDIRECTOR( test_images_2D_getinfo ) +TEST_FN_REDIRECTOR( test_images_cube_getinfo ) + +// 2D image arrays: +TEST_FN_REDIRECTOR( test_images_read_2Darray ) +TEST_FN_REDIRECTOR( test_images_write_2Darray ) +TEST_FN_REDIRECTOR( test_images_2Darray_getinfo ) + +// 3D images: +TEST_FN_REDIRECTOR( test_images_read_3D ) +TEST_FN_REDIRECTOR( test_images_write_3D ) +TEST_FN_REDIRECTOR( test_images_3D_getinfo ) + +#ifdef GL_VERSION_3_2 + +TEST_FN_REDIRECTOR( test_images_read_texturebuffer ) +TEST_FN_REDIRECTOR( test_images_write_texturebuffer ) +TEST_FN_REDIRECTOR( test_images_texturebuffer_getinfo ) + +// depth textures +TEST_FN_REDIRECTOR( test_images_read_2D_depth ) +TEST_FN_REDIRECTOR( test_images_write_2D_depth ) +TEST_FN_REDIRECTOR( test_images_read_2Darray_depth ) +TEST_FN_REDIRECTOR( test_images_write_2Darray_depth ) + +TEST_FN_REDIRECTOR( test_images_read_2D_multisample ) +TEST_FN_REDIRECTOR( test_images_read_2Darray_multisample ) +TEST_FN_REDIRECTOR( test_image_methods_depth ); +TEST_FN_REDIRECTOR( test_image_methods_multisample ); +#endif + +// Renderbuffer-backed images: +TEST_FN_REDIRECTOR( test_renderbuffer_read ) +TEST_FN_REDIRECTOR( test_renderbuffer_write ) +TEST_FN_REDIRECTOR( test_renderbuffer_getinfo ) + +TEST_FN_REDIRECTOR( test_fence_sync ) + +basefn basefn_list[] = { + TEST_FN_REDIRECT( test_buffers ), + TEST_FN_REDIRECT( test_buffers_getinfo ), + + TEST_FN_REDIRECT( test_images_read_1D ), + TEST_FN_REDIRECT( test_images_write_1D ), + TEST_FN_REDIRECT( test_images_1D_getinfo ), + + TEST_FN_REDIRECT( test_images_read_1Darray ), + TEST_FN_REDIRECT( test_images_write_1Darray ), + TEST_FN_REDIRECT( test_images_1Darray_getinfo ), + + TEST_FN_REDIRECT( test_images_read_2D ), + TEST_FN_REDIRECT( test_images_write ), + TEST_FN_REDIRECT( test_images_2D_getinfo ), + + TEST_FN_REDIRECT( test_images_read_cube ), + TEST_FN_REDIRECT( test_images_write_cube ), + TEST_FN_REDIRECT( test_images_cube_getinfo ), + + TEST_FN_REDIRECT( test_images_read_2Darray ), + TEST_FN_REDIRECT( test_images_write_2Darray), + TEST_FN_REDIRECT( test_images_2Darray_getinfo ), + + TEST_FN_REDIRECT( test_images_read_3D ), + TEST_FN_REDIRECT( test_images_write_3D ), + TEST_FN_REDIRECT( test_images_3D_getinfo ), + + TEST_FN_REDIRECT( test_renderbuffer_read ), + TEST_FN_REDIRECT( test_renderbuffer_write ), + TEST_FN_REDIRECT( test_renderbuffer_getinfo ) +}; + +basefn basefn_list32[] = { + TEST_FN_REDIRECT( test_images_read_texturebuffer ), + TEST_FN_REDIRECT( test_images_write_texturebuffer ), + TEST_FN_REDIRECT( test_images_texturebuffer_getinfo ), + + TEST_FN_REDIRECT( test_fence_sync ), + TEST_FN_REDIRECT( test_images_read_2D_depth ), + TEST_FN_REDIRECT( test_images_write_2D_depth ), + TEST_FN_REDIRECT( test_images_read_2Darray_depth ), + TEST_FN_REDIRECT( test_images_write_2Darray_depth ), + TEST_FN_REDIRECT( test_images_read_2D_multisample ), + TEST_FN_REDIRECT( test_images_read_2Darray_multisample ), + TEST_FN_REDIRECT( test_image_methods_depth ), + TEST_FN_REDIRECT( test_image_methods_multisample) +}; + +const char *basefn_names[] = { + "buffers", + "buffers_getinfo", + + "images_read_1D", + "images_write_1D", + "images_1D_getinfo", + + "images_read_1Darray", + "images_write_1Darray", + "images_1Darray_getinfo", + + "images_read", /* 2D */ + "images_write", + "images_2D_getinfo", + + "images_read_cube", + "images_write_cube", + "images_cube_getinfo", + + "images_read_2Darray", + "images_write_2Darray", + "images_2Darray_getinfo", + + "images_read_3D", + "images_write_3D", + "images_3D_getinfo", + + "renderbuffer_read", + "renderbuffer_write", + "renderbuffer_getinfo", +}; + +const char *basefn_names32[] = { + "images_read_texturebuffer", + "images_write_texturebuffer", + "images_texturebuffer_getinfo", + + "fence_sync", + "images_read_2D_depth", + "images_write_2D_depth", + "images_read_2D_array_depth", + "images_write_2D_array_depth", + + "images_read_2D_multisample", + "images_read_2D_array_multisample", + "image_methods_depth", + "image_methods_multisample", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); +ct_assert((sizeof(basefn_names32) / sizeof(basefn_names32[0])) == (sizeof(basefn_list32) / sizeof(basefn_list32[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); +int num_fns32 = sizeof(basefn_names32) / sizeof(char *); + +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +bool gTestRounding = true; + +int main(int argc, const char *argv[]) +{ + int error = 0; + int numErrors = 0; + + test_start(); + argc = parseCustomParam(argc, argv); + if (argc == -1) + { + test_finish (); + return -1; + } + + cl_device_type requestedDeviceType = CL_DEVICE_TYPE_DEFAULT; + checkDeviceTypeOverride(&requestedDeviceType); + + /* Do we have a CPU/GPU specification? */ + if( argc > 1 ) + { + if( strcmp( argv[ argc - 1 ], "gpu" ) == 0 || strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_GPU" ) == 0 ) + { + requestedDeviceType = CL_DEVICE_TYPE_GPU; + argc--; + } + else if( strcmp( argv[ argc - 1 ], "cpu" ) == 0 || strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_CPU" ) == 0 ) + { + requestedDeviceType = CL_DEVICE_TYPE_CPU; + argc--; + } + else if( strcmp( argv[ argc - 1 ], "accelerator" ) == 0 || strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + { + requestedDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + argc--; + } + else if( strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + { + requestedDeviceType = CL_DEVICE_TYPE_DEFAULT; + argc--; + } + } + + if( argc > 1 && strcmp( argv[ 1 ], "-list" ) == 0 ) + { + log_info( "Available 2.x tests:\n" ); + for( int i = 0; i < num_fns; i++ ) + log_info( "\t%s\n", basefn_names[ i ] ); + + log_info( "Available 3.2 tests:\n" ); + for( int i = 0; i < num_fns32; i++ ) + log_info( "\t%s\n", basefn_names32[ i ] ); + + log_info( "Note: Any 3.2 test names must follow 2.1 test names on the command line.\n" ); + log_info( "Use environment variables to specify desired device.\n" ); + + test_finish(); + return 0; + } + + // Check to see if any 2.x or 3.2 test names were specified on the command line. + unsigned first_32_testname = 0; + + for (int j=1; (jSupportsCLGLInterop( requestedDeviceType ); + if( supported == 0 ) { + log_info("Test not run because GL-CL interop is not supported for any devices of the requested type.\n"); + test_finish(); + return 0; + } else if ( supported == -1 ) { + log_error("Unable to setup the test or failed to determine if CL-GL interop is supported.\n"); + test_finish(); + return -1; + } + + // Initialize function pointers. + error = init_clgl_ext(); + if (error < 0) { + return error; + } + + // OpenGL tests for non-3.2 //////////////////////////////////////////////////////// + if ((argc == 1) || (first_32_testname != 1)) { + + // At least one device supports CL-GL interop, so init the test. + if( glEnv->Init( &argc, (char **)argv, CL_FALSE ) ) { + log_error("Failed to initialize the GL environment for this test.\n"); + test_finish(); + return -1; + } + + // Create a context to use and then grab a device (or devices) from it + sCurrentContext = glEnv->CreateCLContext(); + if( sCurrentContext == NULL ) + { + log_error( "ERROR: Unable to obtain CL context from GL\n" ); + test_finish(); + return -1; + } + + size_t numDevices = 0; + cl_device_id *deviceIDs; + + error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, 0, NULL, &numDevices); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to get device count from context" ); + test_finish(); + return -1; + } + deviceIDs = (cl_device_id *)malloc(numDevices); + if (deviceIDs == NULL) { + print_error( error, "malloc failed" ); + test_finish(); + return -1; + } + error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, numDevices, deviceIDs, NULL); + if( error != CL_SUCCESS ) { + print_error( error, "Unable to get device list from context" ); + test_finish(); + return -1; + } + + numDevices /= sizeof(cl_device_id); + + if (numDevices < 1) { + log_error("No devices found.\n"); + test_finish(); + return -1; + } + + // Execute tests. + int argc_ = (first_32_testname) ? first_32_testname : argc; + + for( size_t i = 0; i < numDevices; i++ ) { + log_info( "\nTesting OpenGL 2.x\n" ); + if( printDeviceHeader( deviceIDs[ i ] ) != CL_SUCCESS ) { + test_finish(); + return -1; + } + + // Note: don't use the entire harness, because we have a different way of obtaining the device (via the context) + error = parseAndCallCommandLineTests( argc_, argv, deviceIDs[ i ], num_fns, basefn_list, basefn_names, true, 0, 1024 ); + if( error != 0 ) + break; + } + + numErrors += error; + + // Clean-up. + free(deviceIDs); + clReleaseContext( sCurrentContext ); + //delete glEnv; + } + + // OpenGL 3.2 tests. //////////////////////////////////////////////////////// + if ((argc==1) || first_32_testname) { + + // At least one device supports CL-GL interop, so init the test. + if( glEnv->Init( &argc, (char **)argv, CL_TRUE ) ) { + log_error("Failed to initialize the GL environment for this test.\n"); + test_finish(); + return -1; + } + + // Create a context to use and then grab a device (or devices) from it + sCurrentContext = glEnv->CreateCLContext(); + if( sCurrentContext == NULL ) { + log_error( "ERROR: Unable to obtain CL context from GL\n" ); + test_finish(); + return -1; + } + + size_t numDevices = 0; + cl_device_id *deviceIDs; + + error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, 0, NULL, &numDevices); + if( error != CL_SUCCESS ) { + print_error( error, "Unable to get device count from context" ); + test_finish(); + return -1; + } + deviceIDs = (cl_device_id *)malloc(numDevices); + if (deviceIDs == NULL) { + print_error( error, "malloc failed" ); + test_finish(); + return -1; + } + error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, numDevices, deviceIDs, NULL); + if( error != CL_SUCCESS ) { + print_error( error, "Unable to get device list from context" ); + test_finish(); + return -1; + } + + numDevices /= sizeof(cl_device_id); + + if (numDevices < 1) { + log_error("No devices found.\n"); + test_finish(); + return -1; + } + + int argc_ = (first_32_testname) ? 1 + (argc - first_32_testname) : argc; + const char** argv_ = (first_32_testname) ? &argv[first_32_testname-1] : argv; + + // Execute the tests. + for( size_t i = 0; i < numDevices; i++ ) { + log_info( "\nTesting OpenGL 3.2\n" ); + if( printDeviceHeader( deviceIDs[ i ] ) != CL_SUCCESS ) { + test_finish(); + return -1; + } + + // Note: don't use the entire harness, because we have a different way of obtaining the device (via the context) + error = parseAndCallCommandLineTests( argc_, argv_, deviceIDs[ i ], num_fns32, basefn_list32, basefn_names32, true, 0, 1024 ); + if( error != 0 ) + break; + } + + numErrors += error; + + // Clean-up. + free(deviceIDs); + clReleaseContext( sCurrentContext ); + delete glEnv; + + } + + //All done. + return numErrors; +} + + diff --git a/test_conformance/gl/procs.h b/test_conformance/gl/procs.h new file mode 100644 index 00000000..57c5eefa --- /dev/null +++ b/test_conformance/gl/procs.h @@ -0,0 +1,140 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/mt19937.h" + + +#pragma mark - +#pragma Misc tests + +extern int test_buffers( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +extern int test_fence_sync( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ); + + +#pragma mark - +#pragma mark Tead tests + +extern int test_images_read_2D( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +extern int test_images_read_1D( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +extern int test_images_read_texturebuffer( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +extern int test_images_read_1Darray( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +extern int test_images_read_2Darray( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +extern int test_images_read_cube( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +extern int test_images_read_3D( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +extern int test_renderbuffer_read( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +#pragma mark - +#pragma mark Write tests + +// 2D tests are the ones with no suffix: + +extern int test_images_write( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +extern int test_images_write_cube( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +extern int test_renderbuffer_write( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +// Here are the rest: + +extern int test_images_write_1D( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +extern int test_images_write_texturebuffer( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +extern int test_images_write_1Darray( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +extern int test_images_write_2Darray( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +extern int test_images_write_3D( cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements ); + +#pragma mark - +#pragma mark Get info test entry points + +extern int test_buffers_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ); + +extern int test_images_1D_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ); + +extern int test_images_texturebuffer_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ); + +extern int test_images_1Darray_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ); + +extern int test_images_2D_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ); + +extern int test_images_2Darray_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ); + +extern int test_images_cube_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ); + +extern int test_images_3D_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ); + +extern int test_images_read_2D_depth( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ); + +extern int test_images_write_2D_depth( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ); + +extern int test_images_read_2Darray_depth( cl_device_id device, cl_context context, + cl_command_queue queue, int ); + +extern int test_images_write_2Darray_depth( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ); + +extern int test_images_read_2D_multisample( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ); + +extern int test_images_read_2Darray_multisample( cl_device_id device, cl_context context, + cl_command_queue queue, int ); + +extern int test_image_methods_depth( cl_device_id device, cl_context context, + cl_command_queue queue, int ); + +extern int test_image_methods_multisample( cl_device_id device, cl_context context, + cl_command_queue queue, int ); + +extern int test_renderbuffer_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ); \ No newline at end of file diff --git a/test_conformance/gl/testBase.h b/test_conformance/gl/testBase.h new file mode 100644 index 00000000..6d445f7c --- /dev/null +++ b/test_conformance/gl/testBase.h @@ -0,0 +1,65 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testBase_h +#define _testBase_h + +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#if !defined (__APPLE__) +#include +#include "../../test_common/gl/gl_headers.h" +#include +#else +#include "../../test_common/gl/gl_headers.h" +#endif + +#include "../../test_common/harness/imageHelpers.h" +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/threadTesting.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/mt19937.h" + +#include "../../test_common/gl/helpers.h" + +extern const char *get_kernel_suffix( cl_image_format *format ); +extern const char *get_write_conversion( cl_image_format *format, ExplicitType type); +extern ExplicitType get_read_kernel_type( cl_image_format *format ); +extern ExplicitType get_write_kernel_type( cl_image_format *format ); + +extern char * convert_to_expected( void * inputBuffer, size_t numPixels, ExplicitType inType, ExplicitType outType, size_t channelNum, GLenum glDataType = 0); +extern int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t sampleNum, size_t typeSize ); +extern int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t sampleNum, size_t typeSize ); +extern int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t sampleNum, size_t channelNum ); +extern int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t sampleNum, size_t channelNum ); +extern int validate_float_results_rgb_101010( void *expectedResults, void *actualResults, size_t width, size_t height, size_t sampleNum ); +extern int validate_float_results_rgb_101010( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t sampleNum ); + +extern int CheckGLObjectInfo(cl_mem mem, cl_gl_object_type expected_cl_gl_type, GLuint expected_gl_name, + GLenum expected_cl_gl_texture_target, GLint expected_cl_gl_mipmap_level); + +extern bool CheckGLIntegerExtensionSupport(); + +#endif // _testBase_h + + + diff --git a/test_conformance/gl/test_buffers.cpp b/test_conformance/gl/test_buffers.cpp new file mode 100644 index 00000000..afe7e32e --- /dev/null +++ b/test_conformance/gl/test_buffers.cpp @@ -0,0 +1,357 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" + +#if !defined (__APPLE__) + #include +#endif + +extern "C" { extern cl_uint gRandomSeed; }; + +static const char *bufferKernelPattern = +"__kernel void sample_test( __global %s%s *source, __global %s%s *clDest, __global %s%s *glDest )\n" +"{\n" +" int tid = get_global_id(0);\n" +" clDest[ tid ] = source[ tid ] + (%s%s)(1);\n" +" glDest[ tid ] = source[ tid ] + (%s%s)(2);\n" +"}\n"; + +#define TYPE_CASE( enum, type, range, offset ) \ + case enum: \ + { \ + cl_##type *ptr = (cl_##type *)outData; \ + for( i = 0; i < count; i++ ) \ + ptr[ i ] = (cl_##type)( ( genrand_int32(d) & range ) - offset ); \ + break; \ + } + +void gen_input_data( ExplicitType type, size_t count, MTdata d, void *outData ) +{ + size_t i; + + switch( type ) + { + case kBool: + { + bool *boolPtr = (bool *)outData; + for( i = 0; i < count; i++ ) + { + boolPtr[i] = ( genrand_int32(d) & 1 ) ? true : false; + } + break; + } + + TYPE_CASE( kChar, char, 250, 127 ) + TYPE_CASE( kUChar, uchar, 250, 0 ) + TYPE_CASE( kShort, short, 65530, 32767 ) + TYPE_CASE( kUShort, ushort, 65530, 0 ) + TYPE_CASE( kInt, int, 0x0fffffff, 0x70000000 ) + TYPE_CASE( kUInt, uint, 0x0fffffff, 0 ) + + case kLong: + { + cl_long *longPtr = (cl_long *)outData; + for( i = 0; i < count; i++ ) + { + longPtr[i] = (cl_long)genrand_int32(d) | ( (cl_ulong)genrand_int32(d) << 32 ); + } + break; + } + + case kULong: + { + cl_ulong *ulongPtr = (cl_ulong *)outData; + for( i = 0; i < count; i++ ) + { + ulongPtr[i] = (cl_ulong)genrand_int32(d) | ( (cl_ulong)genrand_int32(d) << 32 ); + } + break; + } + + case kFloat: + { + cl_float *floatPtr = (float *)outData; + for( i = 0; i < count; i++ ) + floatPtr[i] = get_random_float( -100000.f, 100000.f, d ); + break; + } + + default: + log_error( "ERROR: Invalid type passed in to generate_random_data!\n" ); + break; + } +} + +#define INC_CASE( enum, type ) \ + case enum: \ + { \ + cl_##type *src = (cl_##type *)inData; \ + cl_##type *dst = (cl_##type *)outData; \ + *dst = *src + 1; \ + break; \ + } + +void get_incremented_value( void *inData, void *outData, ExplicitType type ) +{ + switch( type ) + { + INC_CASE( kChar, char ) + INC_CASE( kUChar, uchar ) + INC_CASE( kShort, short ) + INC_CASE( kUShort, ushort ) + INC_CASE( kInt, int ) + INC_CASE( kUInt, uint ) + INC_CASE( kLong, long ) + INC_CASE( kULong, ulong ) + INC_CASE( kFloat, float ) + default: + break; + } +} + +int test_buffer_kernel(cl_context context, cl_command_queue queue, ExplicitType vecType, size_t vecSize, int numElements, int validate_only, MTdata d) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 3 ]; + size_t dataSize = numElements * 16 * sizeof(cl_long); +#if !(defined(_WIN32) && defined(_MSC_VER)) + cl_long inData[numElements * 16], outDataCL[numElements * 16], outDataGL[ numElements * 16 ]; +#else + cl_long* inData = (cl_long*)_malloca(dataSize); + cl_long* outDataCL = (cl_long*)_malloca(dataSize); + cl_long* outDataGL = (cl_long*)_malloca(dataSize); +#endif + glBufferWrapper inGLBuffer, outGLBuffer; + int i; + size_t bufferSize; + + int error; + size_t threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + char sizeName[4]; + + /* Create the source */ + if( vecSize == 1 ) + sizeName[ 0 ] = 0; + else + sprintf( sizeName, "%d", (int)vecSize ); + + sprintf( kernelSource, bufferKernelPattern, get_explicit_type_name( vecType ), sizeName, + get_explicit_type_name( vecType ), sizeName, + get_explicit_type_name( vecType ), sizeName, + get_explicit_type_name( vecType ), sizeName, + get_explicit_type_name( vecType ), sizeName ); + + /* Create kernels */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + { + return -1; + } + + bufferSize = numElements * vecSize * get_explicit_type_size( vecType ); + + /* Generate some almost-random input data */ + gen_input_data( vecType, vecSize * numElements, d, inData ); + memset( outDataCL, 0, dataSize ); + memset( outDataGL, 0, dataSize ); + + /* Generate some GL buffers to go against */ + glGenBuffers( 1, &inGLBuffer ); + glGenBuffers( 1, &outGLBuffer ); + + glBindBuffer( GL_ARRAY_BUFFER, inGLBuffer ); + glBufferData( GL_ARRAY_BUFFER, bufferSize, inData, GL_STATIC_DRAW ); + + // Note: we need to bind the output buffer, even though we don't care about its values yet, + // because CL needs it to get the buffer size + glBindBuffer( GL_ARRAY_BUFFER, outGLBuffer ); + glBufferData( GL_ARRAY_BUFFER, bufferSize, outDataGL, GL_STATIC_DRAW ); + + glBindBuffer( GL_ARRAY_BUFFER, 0 ); + glFlush(); + + + /* Generate some streams. The first and last ones are GL, middle one just vanilla CL */ + streams[ 0 ] = (*clCreateFromGLBuffer_ptr)( context, CL_MEM_READ_ONLY, inGLBuffer, &error ); + test_error( error, "Unable to create input GL buffer" ); + + streams[ 1 ] = clCreateBuffer( context, CL_MEM_READ_WRITE, bufferSize, NULL, &error ); + test_error( error, "Unable to create output CL buffer" ); + + streams[ 2 ] = (*clCreateFromGLBuffer_ptr)( context, CL_MEM_WRITE_ONLY, outGLBuffer, &error ); + test_error( error, "Unable to create output GL buffer" ); + + + /* Validate the info */ + if (validate_only) { + int result = (CheckGLObjectInfo(streams[0], CL_GL_OBJECT_BUFFER, (GLuint)inGLBuffer, (GLenum)0, 0) | + CheckGLObjectInfo(streams[2], CL_GL_OBJECT_BUFFER, (GLuint)outGLBuffer, (GLenum)0, 0) ); + for(i=0;i<3;i++) + { + clReleaseMemObject(streams[i]); + streams[i] = NULL; + } + + glDeleteBuffers(1, &inGLBuffer); inGLBuffer = 0; + glDeleteBuffers(1, &outGLBuffer); outGLBuffer = 0; + + return result; + } + + /* Assign streams and execute */ + for( int i = 0; i < 3; i++ ) + { + error = clSetKernelArg( kernel, i, sizeof( streams[ i ] ), &streams[ i ] ); + test_error( error, "Unable to set kernel arguments" ); + } + error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &streams[ 0 ], 0, NULL, NULL); + test_error( error, "Unable to acquire GL obejcts"); + error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &streams[ 2 ], 0, NULL, NULL); + test_error( error, "Unable to acquire GL obejcts"); + + /* Run the kernel */ + threads[0] = numElements; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &streams[ 0 ], 0, NULL, NULL ); + test_error(error, "clEnqueueReleaseGLObjects failed"); + error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &streams[ 2 ], 0, NULL, NULL ); + test_error(error, "clEnqueueReleaseGLObjects failed"); + + // Get the results from both CL and GL and make sure everything looks correct + error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, bufferSize, outDataCL, 0, NULL, NULL ); + test_error( error, "Unable to read output CL array!" ); + + glBindBuffer( GL_ARRAY_BUFFER, outGLBuffer ); + void *glMem = glMapBuffer( GL_ARRAY_BUFFER, GL_READ_ONLY ); + memcpy( outDataGL, glMem, bufferSize ); + glUnmapBuffer( GL_ARRAY_BUFFER ); + + char *inP = (char *)inData, *glP = (char *)outDataGL, *clP = (char *)outDataCL; + error = 0; + for( size_t i = 0; i < numElements * vecSize; i++ ) + { + cl_long expectedCLValue, expectedGLValue; + get_incremented_value( inP, &expectedCLValue, vecType ); + get_incremented_value( &expectedCLValue, &expectedGLValue, vecType ); + + if( memcmp( clP, &expectedCLValue, get_explicit_type_size( vecType ) ) != 0 ) + { + char scratch[ 64 ]; + log_error( "ERROR: Data sample %d from the CL output did not validate!\n", (int)i ); + log_error( "\t Input: %s\n", GetDataVectorString( inP, get_explicit_type_size( vecType ), 1, scratch ) ); + log_error( "\tExpected: %s\n", GetDataVectorString( &expectedCLValue, get_explicit_type_size( vecType ), 1, scratch ) ); + log_error( "\t Actual: %s\n", GetDataVectorString( clP, get_explicit_type_size( vecType ), 1, scratch ) ); + error = -1; + } + + if( memcmp( glP, &expectedGLValue, get_explicit_type_size( vecType ) ) != 0 ) + { + char scratch[ 64 ]; + log_error( "ERROR: Data sample %d from the GL output did not validate!\n", (int)i ); + log_error( "\t Input: %s\n", GetDataVectorString( inP, get_explicit_type_size( vecType ), 1, scratch ) ); + log_error( "\tExpected: %s\n", GetDataVectorString( &expectedGLValue, get_explicit_type_size( vecType ), 1, scratch ) ); + log_error( "\t Actual: %s\n", GetDataVectorString( glP, get_explicit_type_size( vecType ), 1, scratch ) ); + error = -1; + } + + if( error ) + return error; + + inP += get_explicit_type_size( vecType ); + glP += get_explicit_type_size( vecType ); + clP += get_explicit_type_size( vecType ); + } + + for(i=0;i<3;i++) + { + clReleaseMemObject(streams[i]); + streams[i] = NULL; + } + + glDeleteBuffers(1, &inGLBuffer); inGLBuffer = 0; + glDeleteBuffers(1, &outGLBuffer); outGLBuffer = 0; + + return 0; +} + +int test_buffers( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 4, 8, 16, 0 }; + unsigned int index, typeIndex; + int retVal = 0; + RandomSeed seed(gRandomSeed); + + + for( typeIndex = 0; vecType[ typeIndex ] != kNumExplicitTypes; typeIndex++ ) + { + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + // Test! + if( test_buffer_kernel( context, queue, vecType[ typeIndex ], vecSizes[ index ], numElements, 0, seed) != 0 ) + { + char sizeNames[][ 4 ] = { "", "", "2", "", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + log_error( " Buffer test %s%s FAILED\n", get_explicit_type_name( vecType[ typeIndex ] ), sizeNames[ vecSizes[ index ] ] ); + retVal++; + } + } + } + + return retVal; + +} + + +int test_buffers_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 4, 8, 16, 0 }; + unsigned int index, typeIndex; + int retVal = 0; + RandomSeed seed( gRandomSeed ); + + + for( typeIndex = 0; vecType[ typeIndex ] != kNumExplicitTypes; typeIndex++ ) + { + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + // Test! + if( test_buffer_kernel( context, queue, vecType[ typeIndex ], vecSizes[ index ], numElements, 1, seed ) != 0 ) + { + char sizeNames[][ 4 ] = { "", "", "2", "", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + log_error( " Buffer test %s%s FAILED\n", get_explicit_type_name( vecType[ typeIndex ] ), sizeNames[ vecSizes[ index ] ] ); + retVal++; + } + } + } + + return retVal; + +} + + + diff --git a/test_conformance/gl/test_fence_sync.cpp b/test_conformance/gl/test_fence_sync.cpp new file mode 100644 index 00000000..3a6857bd --- /dev/null +++ b/test_conformance/gl/test_fence_sync.cpp @@ -0,0 +1,730 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/gl/setup.h" +#include "../../test_common/harness/genericThread.h" + +#if defined( __APPLE__ ) +#include +#else +#include +#include +#if !defined(_WIN32) && !defined(__ANDROID__) +#include +#endif +#endif + +#ifndef GLsync +// For OpenGL before 3.2, we look for the ARB_sync extension and try to use that +#if !defined(_WIN32) +#include +#endif // !_WIN32 +typedef int64_t GLint64; +typedef uint64_t GLuint64; +typedef struct __GLsync *GLsync; + +#ifndef APIENTRY +#define APIENTRY +#endif + +typedef GLsync (APIENTRY *glFenceSyncPtr)(GLenum condition,GLbitfield flags); +glFenceSyncPtr glFenceSyncFunc; + +typedef bool (APIENTRY *glIsSyncPtr)(GLsync sync); +glIsSyncPtr glIsSyncFunc; + +typedef void (APIENTRY *glDeleteSyncPtr)(GLsync sync); +glDeleteSyncPtr glDeleteSyncFunc; + +typedef GLenum (APIENTRY *glClientWaitSyncPtr)(GLsync sync,GLbitfield flags,GLuint64 timeout); +glClientWaitSyncPtr glClientWaitSyncFunc; + +typedef void (APIENTRY *glWaitSyncPtr)(GLsync sync,GLbitfield flags,GLuint64 timeout); +glWaitSyncPtr glWaitSyncFunc; + +typedef void (APIENTRY *glGetInteger64vPtr)(GLenum pname, GLint64 *params); +glGetInteger64vPtr glGetInteger64vFunc; + +typedef void (APIENTRY *glGetSyncivPtr)(GLsync sync,GLenum pname,GLsizei bufSize,GLsizei *length, + GLint *values); +glGetSyncivPtr glGetSyncivFunc; + +#define CHK_GL_ERR() printf("%s\n", gluErrorString(glGetError())) + +static void InitSyncFns( void ) +{ + glFenceSyncFunc = (glFenceSyncPtr)glutGetProcAddress( "glFenceSync" ); + glIsSyncFunc = (glIsSyncPtr)glutGetProcAddress( "glIsSync" ); + glDeleteSyncFunc = (glDeleteSyncPtr)glutGetProcAddress( "glDeleteSync" ); + glClientWaitSyncFunc = (glClientWaitSyncPtr)glutGetProcAddress( "glClientWaitSync" ); + glWaitSyncFunc = (glWaitSyncPtr)glutGetProcAddress( "glWaitSync" ); + glGetInteger64vFunc = (glGetInteger64vPtr)glutGetProcAddress( "glGetInteger64v" ); + glGetSyncivFunc = (glGetSyncivPtr)glutGetProcAddress( "glGetSynciv" ); +} + +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 + +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 + +#define GL_SYNC_FENCE 0x9116 + +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 + +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 + +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 + +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull + +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D + +#define USING_ARB_sync 1 +#endif + +typedef cl_event (CL_API_CALL *clCreateEventFromGLsyncKHR_fn)( cl_context context, GLsync sync, cl_int *errCode_ret) ; + +clCreateEventFromGLsyncKHR_fn clCreateEventFromGLsyncKHR_ptr; + + +static const char *updateBuffersKernel[] = { + "__kernel void update( __global float4 * vertices, __global float4 *colors, int horizWrap, int rowIdx )\n" + "{\n" + " size_t tid = get_global_id(0);\n" + "\n" + " size_t xVal = ( tid & ( horizWrap - 1 ) );\n" + " vertices[ tid * 2 + 0 ] = (float4)( xVal, rowIdx*16.f, 0.0f, 1.f );\n" + " vertices[ tid * 2 + 1 ] = (float4)( xVal, rowIdx*16.f + 4.0f, 0.0f, 1.f );\n" + "\n" + " int rowV = rowIdx + 1;\n" + " colors[ tid * 2 + 0 ] = (float4)( ( rowV & 1 ) / 255.f, ( ( rowV & 2 ) >> 1 ) / 255.f, ( ( rowV & 4 ) >> 2 ) / 255.f, 1.f );\n" + " //colors[ tid * 2 + 0 ] = (float4)( (float)xVal/(float)horizWrap, 1.0f, 1.0f, 1.0f );\n" + " colors[ tid * 2 + 1 ] = colors[ tid * 2 + 0 ];\n" + "}\n" }; + +//Passthrough VertexShader +static const char *vertexshader = +"#version 150\n" +"uniform mat4 projMatrix;\n" +"in vec4 inPosition;\n" +"in vec4 inColor;\n" +"out vec4 vertColor;\n" +"void main (void) {\n" +" gl_Position = projMatrix*inPosition;\n" +" vertColor = inColor;\n" +"}\n"; + +//Passthrough FragmentShader +static const char *fragmentshader = +"#version 150\n" +"in vec4 vertColor;\n" +"out vec4 outColor;\n" +"void main (void) {\n" +" outColor = vertColor;\n" +"}\n"; + +GLuint createShaderProgram(GLint *posLoc, GLint *colLoc) +{ + GLint logLength, status; + GLuint program = glCreateProgram(); + GLuint vpShader; + + vpShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vpShader, 1, (const GLchar **)&vertexshader, NULL); + glCompileShader(vpShader); + glGetShaderiv(vpShader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar*) malloc(logLength); + glGetShaderInfoLog(vpShader, logLength, &logLength, log); + log_info("Vtx Shader compile log:\n%s", log); + free(log); + } + + glGetShaderiv(vpShader, GL_COMPILE_STATUS, &status); + if (status == 0) + { + log_error("Failed to compile vtx shader:\n"); + return 0; + } + + glAttachShader(program, vpShader); + + GLuint fpShader; + fpShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fpShader, 1, (const GLchar **)&fragmentshader, NULL); + glCompileShader(fpShader); + + glGetShaderiv(fpShader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar*)malloc(logLength); + glGetShaderInfoLog(fpShader, logLength, &logLength, log); + log_info("Frag Shader compile log:\n%s", log); + free(log); + } + + glAttachShader(program, fpShader); + glGetShaderiv(fpShader, GL_COMPILE_STATUS, &status); + if (status == 0) + { + log_error("Failed to compile frag shader:\n\n"); + return 0; + } + + glLinkProgram(program); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar*)malloc(logLength); + glGetProgramInfoLog(program, logLength, &logLength, log); + log_info("Program link log:\n%s", log); + free(log); + } + + glGetProgramiv(program, GL_LINK_STATUS, &status); + if (status == 0) + { + log_error("Failed to link program\n"); + return 0; + } + + *posLoc = glGetAttribLocation(program, "inPosition"); + *colLoc = glGetAttribLocation(program, "inColor"); + + return program; +} + +void destroyShaderProgram(GLuint program) +{ + GLuint shaders[2]; + GLsizei count; + glUseProgram(0); + glGetAttachedShaders(program, 2, &count, shaders); + int i; + for(i = 0; i < count; i++) + { + glDetachShader(program, shaders[i]); + glDeleteShader(shaders[i]); + } + glDeleteProgram(program); +} + +// This function queues up and runs the above CL kernel that writes the vertex data +cl_int run_cl_kernel( cl_kernel kernel, cl_command_queue queue, cl_mem stream0, cl_mem stream1, + cl_int rowIdx, cl_event fenceEvent, size_t numThreads ) +{ + cl_int error = clSetKernelArg( kernel, 3, sizeof( rowIdx ), &rowIdx ); + test_error( error, "Unable to set kernel arguments" ); + + clEventWrapper acqEvent1, acqEvent2, kernEvent, relEvent1, relEvent2; + int numEvents = ( fenceEvent != NULL ) ? 1 : 0; + cl_event *fence_evt = ( fenceEvent != NULL ) ? &fenceEvent : NULL; + + error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &stream0, numEvents, fence_evt, &acqEvent1 ); + test_error( error, "Unable to acquire GL obejcts"); + error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &stream1, numEvents, fence_evt, &acqEvent2 ); + test_error( error, "Unable to acquire GL obejcts"); + + cl_event evts[ 2 ] = { acqEvent1, acqEvent2 }; + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, &numThreads, NULL, 2, evts, &kernEvent ); + test_error( error, "Unable to execute test kernel" ); + + error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &stream0, 1, &kernEvent, &relEvent1 ); + test_error(error, "clEnqueueReleaseGLObjects failed"); + error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &stream1, 1, &kernEvent, &relEvent2 ); + test_error(error, "clEnqueueReleaseGLObjects failed"); + + evts[ 0 ] = relEvent1; + evts[ 1 ] = relEvent2; + error = clWaitForEvents( 2, evts ); + test_error( error, "Unable to wait for release events" ); + + return 0; +} + +class RunThread : public genericThread +{ +public: + + cl_kernel mKernel; + cl_command_queue mQueue; + cl_mem mStream0, mStream1; + cl_int mRowIdx; + cl_event mFenceEvent; + size_t mNumThreads; + + RunThread( cl_kernel kernel, cl_command_queue queue, cl_mem stream0, cl_mem stream1, size_t numThreads ) + : mKernel( kernel ), mQueue( queue ), mStream0( stream0 ), mStream1( stream1 ), mNumThreads( numThreads ) + { + } + + void SetRunData( cl_int rowIdx, cl_event fenceEvent ) + { + mRowIdx = rowIdx; + mFenceEvent = fenceEvent; + } + + virtual void * IRun( void ) + { + cl_int error = run_cl_kernel( mKernel, mQueue, mStream0, mStream1, mRowIdx, mFenceEvent, mNumThreads ); + return (void *)error; + } +}; + + +int test_fence_sync_single( cl_device_id device, cl_context context, cl_command_queue queue, bool separateThreads, GLint rend_vs, GLint read_vs, cl_device_id rend_device ) +{ + int error; + const int framebufferSize = 512; + + + if( !is_extension_available( device, "cl_khr_gl_event" ) ) + { + log_info( "NOTE: cl_khr_gl_event extension not present on this device; skipping fence sync test\n" ); + return 0; + } + + // Ask OpenCL for the platforms. Warn if more than one platform found, + // since this might not be the platform we want. By default, we simply + // use the first returned platform. + + cl_uint nplatforms; + cl_platform_id platform; + clGetPlatformIDs(0, NULL, &nplatforms); + clGetPlatformIDs(1, &platform, NULL); + + if (nplatforms > 1) { + log_info("clGetPlatformIDs returned multiple values. This is not " + "an error, but might result in obtaining incorrect function " + "pointers if you do not want the first returned platform.\n"); + + // Show them the platform name, in case it is a problem. + + size_t size; + char *name; + + clGetPlatformInfo(platform, CL_PLATFORM_NAME, 0, NULL, &size); + name = (char*)malloc(size); + clGetPlatformInfo(platform, CL_PLATFORM_NAME, size, name, NULL); + + log_info("Using platform with name: %s \n", name); + free(name); + } + + clCreateEventFromGLsyncKHR_ptr = (clCreateEventFromGLsyncKHR_fn)clGetExtensionFunctionAddressForPlatform(platform, "clCreateEventFromGLsyncKHR"); + if( clCreateEventFromGLsyncKHR_ptr == NULL ) + { + log_error( "ERROR: Unable to run fence_sync test (clCreateEventFromGLsyncKHR function not discovered!)\n" ); + clCreateEventFromGLsyncKHR_ptr = (clCreateEventFromGLsyncKHR_fn)clGetExtensionFunctionAddressForPlatform(platform, "clCreateEventFromGLsyncAPPLE"); + return -1; + } + +#ifdef USING_ARB_sync + char *gl_version_str = (char*)glGetString( GL_VERSION ); + float glCoreVersion; + sscanf(gl_version_str, "%f", &glCoreVersion); + if( glCoreVersion < 3.0f ) + { + log_info( "OpenGL version %f does not support fence/sync! Skipping test.\n", glCoreVersion ); + return 0; + } + +#ifdef __APPLE__ + CGLContextObj currCtx = CGLGetCurrentContext(); + CGLPixelFormatObj pixFmt = CGLGetPixelFormat(currCtx); + GLint val, screen; + CGLGetVirtualScreen(currCtx, &screen); + CGLDescribePixelFormat(pixFmt, screen, kCGLPFAOpenGLProfile, &val); + if(val != kCGLOGLPVersion_3_2_Core) + { + log_error( "OpenGL context was not created with OpenGL version >= 3.0 profile even though platform supports it" + "OpenGL profile %f does not support fence/sync! Skipping test.\n", glCoreVersion ); + return -1; + } +#else +#ifdef _WIN32 + HDC hdc = wglGetCurrentDC(); + HGLRC hglrc = wglGetCurrentContext(); +#else + Display* dpy = glXGetCurrentDisplay(); + GLXDrawable drawable = glXGetCurrentDrawable(); + GLXContext ctx = glXGetCurrentContext(); +#endif +#endif + + InitSyncFns(); +#endif + +#ifdef __APPLE__ + CGLSetVirtualScreen(CGLGetCurrentContext(), rend_vs); +#else +#ifdef _WIN32 + wglMakeCurrent(hdc, hglrc); +#else + glXMakeCurrent(dpy, drawable, ctx); +#endif +#endif + + GLint posLoc, colLoc; + GLuint shaderprogram = createShaderProgram(&posLoc, &colLoc); + if(!shaderprogram) + { + log_error("Failed to create shader program\n"); + return -1; + } + + float l = 0.0f; float r = framebufferSize; + float b = 0.0f; float t = framebufferSize; + + float projMatrix[16] = { 2.0f/(r-l), 0.0f, 0.0f, 0.0f, + 0.0f, 2.0f/(t-b), 0.0f, 0.0f, + 0.0f, 0.0f, -1.0f, 0.0f, + -(r+l)/(r-l), -(t+b)/(t-b), 0.0f, 1.0f + }; + + glUseProgram(shaderprogram); + GLuint projMatLoc = glGetUniformLocation(shaderprogram, "projMatrix"); + glUniformMatrix4fv(projMatLoc, 1, 0, projMatrix); + glUseProgram(0); + + // Note: the framebuffer is just the target to verify our results against, so we don't + // really care to go through all the possible formats in this case + glFramebufferWrapper glFramebuffer; + glRenderbufferWrapper glRenderbuffer; + error = CreateGLRenderbufferRaw( framebufferSize, 128, GL_COLOR_ATTACHMENT0_EXT, + GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, + &glFramebuffer, &glRenderbuffer ); + if( error != 0 ) + return error; + + GLuint vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + glBufferWrapper vtxBuffer, colorBuffer; + glGenBuffers( 1, &vtxBuffer ); + glGenBuffers( 1, &colorBuffer ); + + const int numHorizVertices = ( framebufferSize * 64 ) + 1; + + glBindBuffer( GL_ARRAY_BUFFER, vtxBuffer ); + glBufferData( GL_ARRAY_BUFFER, sizeof( GLfloat ) * numHorizVertices * 2 * 4, NULL, GL_STATIC_DRAW ); + + glBindBuffer( GL_ARRAY_BUFFER, colorBuffer ); + glBufferData( GL_ARRAY_BUFFER, sizeof( GLfloat ) * numHorizVertices * 2 * 4, NULL, GL_STATIC_DRAW ); + + // Now that the requisite objects are bound, we can attempt program + // validation: + + glValidateProgram(shaderprogram); + + GLint logLength, status; + glGetProgramiv(shaderprogram, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar*)malloc(logLength); + glGetProgramInfoLog(shaderprogram, logLength, &logLength, log); + log_info("Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(shaderprogram, GL_VALIDATE_STATUS, &status); + if (status == 0) + { + log_error("Failed to validate program\n"); + return 0; + } + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 2 ]; + + if( create_single_kernel_helper( context, &program, &kernel, 1, updateBuffersKernel, "update" ) ) + return -1; + + streams[ 0 ] = (*clCreateFromGLBuffer_ptr)( context, CL_MEM_READ_WRITE, vtxBuffer, &error ); + test_error( error, "Unable to create CL buffer from GL vertex buffer" ); + + streams[ 1 ] = (*clCreateFromGLBuffer_ptr)( context, CL_MEM_READ_WRITE, colorBuffer, &error ); + test_error( error, "Unable to create CL buffer from GL color buffer" ); + + error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] ); + test_error( error, "Unable to set kernel arguments" ); + + error = clSetKernelArg( kernel, 1, sizeof( streams[ 1 ] ), &streams[ 1 ] ); + test_error( error, "Unable to set kernel arguments" ); + + cl_int horizWrap = (cl_int)framebufferSize; + error = clSetKernelArg( kernel, 2, sizeof( horizWrap ), &horizWrap ); + test_error( error, "Unable to set kernel arguments" ); + + glViewport( 0, 0, framebufferSize, framebufferSize ); + glClearColor( 0, 0, 0, 0 ); + glClear( GL_COLOR_BUFFER_BIT ); + glClear( GL_DEPTH_BUFFER_BIT ); + glDisable( GL_DEPTH_TEST ); + glEnable( GL_BLEND ); + glBlendFunc( GL_ONE, GL_ONE ); + + clEventWrapper fenceEvent; + GLsync glFence = 0; + + // Do a loop through 8 different horizontal stripes against the framebuffer + RunThread thread( kernel, queue, streams[ 0 ], streams[ 1 ], (size_t)numHorizVertices ); + + for( int i = 0; i < 8; i++ ) + { + // if current rendering device is not the compute device and + // separateThreads == false which means compute is going on same + // thread and we are using implicit synchronization (no GLSync obj used) + // then glFlush by clEnqueueAcquireGLObject is not sufficient ... we need + // to wait for rendering to finish on other device before CL can start + // writing to CL/GL shared mem objects. When separateThreads is true i.e. + // we are using GLSync obj to synchronize then we dont need to call glFinish + // here since CL should wait for rendering on other device before this + // GLSync object to finish before it starts writing to shared mem object. + // Also rend_device == compute_device no need to call glFinish + if(rend_device != device && !separateThreads) + glFinish(); + + if( separateThreads ) + { + if (fenceEvent != NULL) + { + clReleaseEvent(fenceEvent); + glDeleteSyncFunc(glFence); + } + + glFence = glFenceSyncFunc(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + fenceEvent = clCreateEventFromGLsyncKHR_ptr(context, glFence, &error); + test_error(error, "Unable to create CL event from GL fence"); + + // in case of explicit synchronization, we just wait for the sync object to complete + // in clEnqueueAcquireGLObject but we dont flush. Its application's responsibility + // to flush on the context on which glSync is created + glFlush(); + + thread.SetRunData( (cl_int)i, fenceEvent ); + thread.Start(); + + error = (cl_int)(size_t)thread.Join(); + } + else + { + error = run_cl_kernel( kernel, queue, streams[ 0 ], streams[ 1 ], (cl_int)i, fenceEvent, (size_t)numHorizVertices ); + } + test_error( error, "Unable to run CL kernel" ); + + glUseProgram(shaderprogram); + glEnableVertexAttribArray(posLoc); + glEnableVertexAttribArray(colLoc); + glBindBuffer( GL_ARRAY_BUFFER, vtxBuffer ); + glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0); + glBindBuffer( GL_ARRAY_BUFFER, colorBuffer ); + glVertexAttribPointer(colLoc, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0); + glBindBuffer( GL_ARRAY_BUFFER, 0 ); + + glDrawArrays( GL_TRIANGLE_STRIP, 0, numHorizVertices * 2 ); + + glDisableVertexAttribArray(posLoc); + glDisableVertexAttribArray(colLoc); + glUseProgram(0); + + if( separateThreads ) + { + // If we're on the same thread, then we're testing implicit syncing, so we + // don't need the actual fence code + if( fenceEvent != NULL ) + { + clReleaseEvent( fenceEvent ); + glDeleteSyncFunc( glFence ); + } + + glFence = glFenceSyncFunc( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 ); + fenceEvent = clCreateEventFromGLsyncKHR_ptr( context, glFence, &error ); + test_error( error, "Unable to create CL event from GL fence" ); + + // in case of explicit synchronization, we just wait for the sync object to complete + // in clEnqueueAcquireGLObject but we dont flush. Its application's responsibility + // to flush on the context on which glSync is created + glFlush(); + } + else + glFinish(); + } + + if( glFence != 0 ) + // Don't need the final release for fenceEvent, because the wrapper will take care of that + glDeleteSyncFunc( glFence ); + +#ifdef __APPLE__ + CGLSetVirtualScreen(CGLGetCurrentContext(), read_vs); +#else +#ifdef _WIN32 + wglMakeCurrent(hdc, hglrc); +#else + glXMakeCurrent(dpy, drawable, ctx); +#endif +#endif + // Grab the contents of the final framebuffer + BufferOwningPtr resultData( ReadGLRenderbuffer( glFramebuffer, glRenderbuffer, + GL_COLOR_ATTACHMENT0_EXT, + GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar, + framebufferSize, 128 ) ); + + // Check the contents now. We should end up with solid color bands 32 pixels high and the + // full width of the framebuffer, at values (128,128,128) due to the additive blending + for( int i = 0; i < 8; i++ ) + { + for( int y = 0; y < 4; y++ ) + { + // Note: coverage will be double because the 63-0 triangle overwrites again at the end of the pass + cl_uchar valA = ( ( ( i + 1 ) & 1 ) ) * numHorizVertices * 2 / framebufferSize; + cl_uchar valB = ( ( ( i + 1 ) & 2 ) >> 1 ) * numHorizVertices * 2 / framebufferSize; + cl_uchar valC = ( ( ( i + 1 ) & 4 ) >> 2 ) * numHorizVertices * 2 / framebufferSize; + + cl_uchar *row = (cl_uchar *)&resultData[ ( i * 16 + y ) * framebufferSize * 4 ]; + for( int x = 0; x < ( framebufferSize - 1 ) - 1; x++ ) + { + if( ( row[ x * 4 ] != valA ) || ( row[ x * 4 + 1 ] != valB ) || + ( row[ x * 4 + 2 ] != valC ) ) + { + log_error( "ERROR: Output framebuffer did not validate!\n" ); + DumpGLBuffer( GL_UNSIGNED_BYTE, framebufferSize, 128, resultData ); + log_error( "RUNS:\n" ); + uint32_t *p = (uint32_t *)(char *)resultData; + size_t a = 0; + for( size_t t = 1; t < framebufferSize * framebufferSize; t++ ) + { + if( p[ a ] != 0 ) + { + if( p[ t ] == 0 ) + { + log_error( "RUN: %ld to %ld (%d,%d to %d,%d) 0x%08x\n", a, t - 1, + (int)( a % framebufferSize ), (int)( a / framebufferSize ), + (int)( ( t - 1 ) % framebufferSize ), (int)( ( t - 1 ) / framebufferSize ), + p[ a ] ); + a = t; + } + } + else + { + if( p[ t ] != 0 ) + { + a = t; + } + } + + } + return -1; + } + } + } + } + + destroyShaderProgram(shaderprogram); + glDeleteVertexArrays(1, &vao); + return 0; +} + +int test_fence_sync( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLint vs_count = 0; + cl_device_id *device_list = NULL; + + if( !is_extension_available( device, "cl_khr_gl_event" ) ) + { + log_info( "NOTE: cl_khr_gl_event extension not present on this device; skipping fence sync test\n" ); + return 0; + } +#ifdef __APPLE__ + CGLContextObj ctx = CGLGetCurrentContext(); + CGLPixelFormatObj pix = CGLGetPixelFormat(ctx); + CGLError err = CGLDescribePixelFormat(pix, 0, kCGLPFAVirtualScreenCount, &vs_count); + + device_list = (cl_device_id *) malloc(sizeof(cl_device_id)*vs_count); + clGetGLContextInfoAPPLE(context, ctx, CL_CGL_DEVICES_FOR_SUPPORTED_VIRTUAL_SCREENS_APPLE, sizeof(cl_device_id)*vs_count, device_list, NULL); +#else + // Need platform specific way of getting devices from CL context to which OpenGL can render + // If not available it can be replaced with clGetContextInfo with CL_CONTEXT_DEVICES + size_t device_cb; + cl_int err = clGetContextInfo( context, CL_CONTEXT_DEVICES, 0, NULL, &device_cb); + if( err != CL_SUCCESS ) + { + print_error( err, "Unable to get device count from context" ); + test_finish(); + return -1; + } + vs_count = (GLint)device_cb / sizeof(cl_device_id); + + if (vs_count < 1) { + log_error("No devices found.\n"); + return -1; + } + + device_list = (cl_device_id *) malloc(device_cb); + err = clGetContextInfo( context, CL_CONTEXT_DEVICES, device_cb, device_list, NULL); + if( err != CL_SUCCESS ) { + free(device_list); + print_error( err, "Unable to get device list from context" ); + return -1; + } + +#endif + + GLint rend_vs, read_vs; + int error = 0; + int any_failed = 0; + + // Loop through all the devices capable to OpenGL rendering + // and set them as current rendering target + for(rend_vs = 0; rend_vs < vs_count; rend_vs++) + { + // Loop through all the devices and set them as current + // compute target + for(read_vs = 0; read_vs < vs_count; read_vs++) + { + cl_device_id rend_device = device_list[rend_vs], read_device = device_list[read_vs]; + char rend_name[200], read_name[200]; + + clGetDeviceInfo(rend_device, CL_DEVICE_NAME, sizeof(rend_name), rend_name, NULL); + clGetDeviceInfo(read_device, CL_DEVICE_NAME, sizeof(read_name), read_name, NULL); + + log_info("Rendering on: %s, read back on: %s\n", rend_name, read_name); + error = test_fence_sync_single( device, context, queue, false, rend_vs, read_vs, rend_device ); + any_failed |= error; + if( error != 0 ) + log_error( "ERROR: Implicit syncing with GL sync events failed!\n\n" ); + else + log_info("Implicit syncing Passed\n"); + + error = test_fence_sync_single( device, context, queue, true, rend_vs, read_vs, rend_device ); + any_failed |= error; + if( error != 0 ) + log_error( "ERROR: Explicit syncing with GL sync events failed!\n\n" ); + else + log_info("Explicit syncing Passed\n"); + } + } + + free(device_list); + + return any_failed; +} diff --git a/test_conformance/gl/test_image_methods.cpp b/test_conformance/gl/test_image_methods.cpp new file mode 100644 index 00000000..fa0c00a6 --- /dev/null +++ b/test_conformance/gl/test_image_methods.cpp @@ -0,0 +1,405 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" + +#include + +using namespace std; + +typedef struct image_kernel_data +{ + cl_int width; + cl_int height; + cl_int depth; + cl_int arraySize; + cl_int widthDim; + cl_int heightDim; + cl_int channelType; + cl_int channelOrder; + cl_int expectedChannelType; + cl_int expectedChannelOrder; + cl_int numSamples; +}; + +static const char *methodTestKernelPattern = +"typedef struct {\n" +" int width;\n" +" int height;\n" +" int depth;\n" +" int arraySize;\n" +" int widthDim;\n" +" int heightDim;\n" +" int channelType;\n" +" int channelOrder;\n" +" int expectedChannelType;\n" +" int expectedChannelOrder;\n" +" int numSamples;\n" +" } image_kernel_data;\n" +"__kernel void sample_kernel( read_only %s input, __global image_kernel_data *outData )\n" +"{\n" +"%s%s%s%s%s%s%s%s%s%s%s" +"}\n"; + +static const char *arraySizeKernelLine = +" outData->arraySize = get_image_array_size( input );\n"; +static const char *imageWidthKernelLine = +" outData->width = get_image_width( input );\n"; +static const char *imageHeightKernelLine = +" outData->height = get_image_height( input );\n"; +static const char *imageDimKernelLine = +" int2 dim = get_image_dim( input );\n"; +static const char *imageWidthDimKernelLine = +" outData->widthDim = dim.x;\n"; +static const char *imageHeightDimKernelLine = +" outData->heightDim = dim.y;\n"; +static const char *channelTypeKernelLine = +" outData->channelType = get_image_channel_data_type( input );\n"; +static const char *channelTypeConstLine = +" outData->expectedChannelType = CLK_%s;\n"; +static const char *channelOrderKernelLine = +" outData->channelOrder = get_image_channel_order( input );\n"; +static const char *channelOrderConstLine = +" outData->expectedChannelOrder = CLK_%s;\n"; +static const char *numSamplesKernelLine = +" outData->numSamples = get_image_num_samples( input );\n"; + +static int verify(cl_int input, cl_int kernelOutput, const char * description) +{ + if( kernelOutput != input ) + { + log_error( "ERROR: %s did not validate (expected %d, got %d)\n", description, input, kernelOutput); + return -1; + } + return 0; +} + +extern int supportsMsaa(cl_context context, bool* supports_msaa); +extern int supportsDepth(cl_context context, bool* supports_depth); + +int test_image_format_methods( cl_device_id device, cl_context context, cl_command_queue queue, + size_t width, size_t height, size_t arraySize, size_t samples, + GLenum target, format format, MTdata d ) +{ + int error, result=0; + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper image, outDataBuffer; + char programSrc[ 10240 ]; + + image_kernel_data outKernelData; + +#ifdef GL_VERSION_3_2 + if (get_base_gl_target(target) == GL_TEXTURE_2D_MULTISAMPLE || + get_base_gl_target(target) == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) + { + bool supports_msaa; + error = supportsMsaa(context, &supports_msaa); + if( error != 0 ) return error; + if (!supports_msaa) return 0; + } + if (format.formattype == GL_DEPTH_COMPONENT || + format.formattype == GL_DEPTH_STENCIL) + { + bool supports_depth; + error = supportsDepth(context, &supports_depth); + if( error != 0 ) return error; + if (!supports_depth) return 0; + } +#endif + DetectFloatToHalfRoundingMode(queue); + + glTextureWrapper glTexture; + switch (get_base_gl_target(target)) { + case GL_TEXTURE_2D: + CreateGLTexture2D( width, height, target, + format.formattype, format.internal, format.datatype, + format.type, &glTexture, &error, false, d ); + break; + case GL_TEXTURE_2D_ARRAY: + CreateGLTexture2DArray( width, height, arraySize, target, + format.formattype, format.internal, format.datatype, + format.type, &glTexture, &error, false, d ); + break; + case GL_TEXTURE_2D_MULTISAMPLE: + CreateGLTexture2DMultisample( width, height, samples, target, + format.formattype, format.internal, format.datatype, + format.type, &glTexture, &error, false, d, false); + break; + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + CreateGLTexture2DArrayMultisample( width, height, arraySize, samples, target, + format.formattype, format.internal, format.datatype, + format.type, &glTexture, &error, false, d, false); + break; + + default: + log_error("Unsupported GL tex target (%s) passed to write test: " + "%s (%s):%d", GetGLTargetName(target), __FUNCTION__, + __FILE__, __LINE__); + } + + // Check to see if the texture could not be created for some other reason like + // GL_FRAMEBUFFER_UNSUPPORTED + if (error == GL_FRAMEBUFFER_UNSUPPORTED) { + return 0; + } + + // Construct testing source + log_info( " - Creating image %d by %d...\n", width, height ); + // Create a CL image from the supplied GL texture + image = (*clCreateFromGLTexture_ptr)( context, CL_MEM_READ_ONLY, + target, 0, glTexture, &error ); + + if ( error != CL_SUCCESS ) { + print_error( error, "Unable to create CL image from GL texture" ); + GLint fmt; + glGetTexLevelParameteriv( target, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt ); + log_error( " Supplied GL texture was base format %s and internal " + "format %s\n", GetGLBaseFormatName( fmt ), GetGLFormatName( fmt ) ); + return error; + } + + cl_image_format imageFormat; + error = clGetImageInfo (image, CL_IMAGE_FORMAT, + sizeof(imageFormat), &imageFormat, NULL); + test_error(error, "Failed to get image format"); + + const char * imageType = 0; + bool doArraySize = false; + bool doImageWidth = false; + bool doImageHeight = false; + bool doImageChannelDataType = false; + bool doImageChannelOrder = false; + bool doImageDim = false; + bool doNumSamples = false; + switch(target) { + case GL_TEXTURE_2D: + imageType = "image2d_depth_t"; + doImageWidth = true; + doImageHeight = true; + doImageChannelDataType = true; + doImageChannelOrder = true; + doImageDim = true; + break; + case GL_TEXTURE_2D_ARRAY: + imageType = "image2d_array_depth_t"; + doImageWidth = true; + doImageHeight = true; + doArraySize = true; + doImageChannelDataType = true; + doImageChannelOrder = true; + doImageDim = true; + doArraySize = true; + break; + case GL_TEXTURE_2D_MULTISAMPLE: + doNumSamples = true; + if(format.formattype == GL_DEPTH_COMPONENT) { + doImageWidth = true; + imageType = "image2d_msaa_depth_t"; + } else { + imageType = "image2d_msaa_t"; + } + break; + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + if(format.formattype == GL_DEPTH_COMPONENT) { + doImageWidth = true; + imageType = "image2d_msaa_array_depth_t"; + } else { + imageType = "image2d_array_msaa_t"; + } + break; + } + + + + char channelTypeConstKernelLine[512] = {0}; + char channelOrderConstKernelLine[512] = {0}; + const char* channelTypeName=0; + const char* channelOrderName=0; + if(doImageChannelDataType) { + channelTypeName = GetChannelTypeName( imageFormat.image_channel_data_type ); + if(channelTypeName && strlen(channelTypeName)) { + // replace CL_* with CLK_* + sprintf(channelTypeConstKernelLine, channelTypeConstLine, &channelTypeName[3]); + } + } + if(doImageChannelOrder) { + channelOrderName = GetChannelOrderName( imageFormat.image_channel_order ); + if(channelOrderName && strlen(channelOrderName)) { + // replace CL_* with CLK_* + sprintf(channelOrderConstKernelLine, channelOrderConstLine, &channelOrderName[3]); + } + } + + // Create a program to run against + sprintf( programSrc, methodTestKernelPattern, + imageType, + ( doArraySize ) ? arraySizeKernelLine : "", + ( doImageWidth ) ? imageWidthKernelLine : "", + ( doImageHeight ) ? imageHeightKernelLine : "", + ( doImageChannelDataType ) ? channelTypeKernelLine : "", + ( doImageChannelDataType ) ? channelTypeConstKernelLine : "", + ( doImageChannelOrder ) ? channelOrderKernelLine : "", + ( doImageChannelOrder ) ? channelOrderConstKernelLine : "", + ( doImageDim ) ? imageDimKernelLine : "", + ( doImageDim && doImageWidth ) ? imageWidthDimKernelLine : "", + ( doImageDim && doImageHeight ) ? imageHeightDimKernelLine : "", + ( doNumSamples ) ? numSamplesKernelLine : ""); + + + //log_info("-----------------------------------\n%s\n", programSrc); + error = clFinish(queue); + if (error) + print_error(error, "clFinish failed.\n"); + const char *ptr = programSrc; + error = create_single_kernel_helper( context, &program, &kernel, 1, &ptr, "sample_kernel" ); + test_error( error, "Unable to create kernel to test against" ); + + // Create an output buffer + outDataBuffer = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof( outKernelData ), NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + // Set up arguments and run + error = clSetKernelArg( kernel, 0, sizeof( image ), &image ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 1, sizeof( outDataBuffer ), &outDataBuffer ); + test_error( error, "Unable to set kernel argument" ); + + // Flush and Acquire. + glFlush(); + error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &image, 0, NULL, NULL); + test_error( error, "Unable to acquire GL obejcts"); + + size_t threads[1] = { 1 }, localThreads[1] = { 1 }; + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + error = clEnqueueReadBuffer( queue, outDataBuffer, CL_TRUE, 0, sizeof( outKernelData ), &outKernelData, 0, NULL, NULL ); + test_error( error, "Unable to read data buffer" ); + + // Verify the results now + if( doImageWidth ) + result |= verify(width, outKernelData.width, "width"); + if( doImageHeight) + result |= verify(height, outKernelData.height, "height"); + if( doImageDim && doImageWidth ) + result |= verify(width, outKernelData.widthDim, "width from get_image_dim"); + if( doImageDim && doImageHeight ) + result |= verify(height, outKernelData.heightDim, "height from get_image_dim"); + if( doImageChannelDataType ) + result |= verify(outKernelData.channelType, outKernelData.expectedChannelType, channelTypeName); + if( doImageChannelOrder ) + result |= verify(outKernelData.channelOrder, outKernelData.expectedChannelOrder, channelOrderName); + if( doArraySize ) + result |= verify(arraySize, outKernelData.arraySize, "array size"); + if( doNumSamples ) + result |= verify(samples, outKernelData.numSamples, "samples"); + if(result) { + log_error("Test image methods failed"); + } + + clEventWrapper event; + error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &image, 0, NULL, &event ); + test_error(error, "clEnqueueReleaseGLObjects failed"); + + error = clWaitForEvents( 1, &event ); + test_error(error, "clWaitForEvents failed"); + + return result; +} + +int test_image_methods_depth( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ){ + if (!is_extension_available(device, "cl_khr_gl_depth_images")) { + log_info("Test not run because 'cl_khr_gl_depth_images' extension is not supported by the tested device\n"); + return 0; + } + + size_t pixelSize; + int result = 0; + GLenum depth_targets[] = {GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY}; + size_t ntargets = sizeof(depth_targets) / sizeof(depth_targets[0]); + size_t nformats = sizeof(depth_formats) / sizeof(depth_formats[0]); + + const size_t nsizes = 5; + sizevec_t sizes[nsizes]; + // Need to limit texture size according to GL device properties + GLint maxTextureSize = 4096, maxTextureRectangleSize = 4096, maxTextureLayers = 16, size; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT, &maxTextureRectangleSize); + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers); + + size = min(maxTextureSize, maxTextureRectangleSize); + + RandomSeed seed( gRandomSeed ); + + // Generate some random sizes (within reasonable ranges) + for (size_t i = 0; i < nsizes; i++) { + sizes[i].width = random_in_range( 2, min(size, 1<<(i+4)), seed ); + sizes[i].height = random_in_range( 2, min(size, 1<<(i+4)), seed ); + sizes[i].depth = random_in_range( 2, min(maxTextureLayers, 1<<(i+4)), seed ); + } + + for (size_t i = 0; i < nsizes; i++) { + for(size_t itarget = 0; itarget < ntargets; ++itarget) { + for(size_t iformat = 0; iformat < nformats; ++iformat) + result |= test_image_format_methods(device, context, queue, sizes[i].width, sizes[i].height, (depth_targets[itarget] == GL_TEXTURE_2D_ARRAY) ? sizes[i].depth: 1, 0, + depth_targets[itarget], depth_formats[iformat], seed ); + } + } + return result; +} + +int test_image_methods_multisample( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ){ + if (!is_extension_available(device, "cl_khr_gl_msaa_sharing")) { + log_info("Test not run because 'cl_khr_gl_msaa_sharing' extension is not supported by the tested device\n"); + return 0; + } + + size_t pixelSize; + int result = 0; + GLenum targets[] = {GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY}; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + const size_t nsizes = 5; + sizevec_t sizes[nsizes]; + GLint maxTextureLayers = 16, maxTextureSize = 4096; + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + + RandomSeed seed( gRandomSeed ); + + // Generate some random sizes (within reasonable ranges) + for (size_t i = 0; i < nsizes; i++) { + sizes[i].width = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed ); + sizes[i].height = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed ); + sizes[i].depth = random_in_range( 2, min(maxTextureLayers, 1<<(i+4)), seed ); + } + + glEnable(GL_MULTISAMPLE); + + for (size_t i = 0; i < nsizes; i++) { + for(size_t itarget = 0; itarget < ntargets; ++itarget) { + for(size_t iformat = 0; iformat < nformats; ++iformat) { + GLint samples = get_gl_max_samples(targets[itarget], common_formats[iformat].internal); + result |= test_image_format_methods(device, context, queue, sizes[i].width, sizes[i].height, (targets[ntargets] == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) ? sizes[i].depth: 1, + samples, targets[itarget], common_formats[iformat], seed ); + } + } + } + return result; +} diff --git a/test_conformance/gl/test_images_1D.cpp b/test_conformance/gl/test_images_1D.cpp new file mode 100644 index 00000000..172dd4b5 --- /dev/null +++ b/test_conformance/gl/test_images_1D.cpp @@ -0,0 +1,141 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" +#include "testBase.h" + +#if defined( __APPLE__ ) + #include +#else + #include + #include +#endif +#include + +using namespace std; + +void calc_test_size_descriptors(sizevec_t* sizes, size_t nsizes) +{ + // Need to limit array size according to GL device properties + GLint maxTextureSize = 4096, maxTextureBufferSize = 4096, size; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureBufferSize); + + size = min(maxTextureSize, maxTextureBufferSize); + + RandomSeed seed( gRandomSeed ); + + // Generate some random sizes (within reasonable ranges) + for (size_t i = 0; i < nsizes; i++) { + sizes[i].width = random_in_range( 2, min(size, 1<<(i+4)), seed ); + sizes[i].height = 1; + sizes[i].depth = 1; + } +} + +int test_images_read_1D( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + GLenum targets[] = { GL_TEXTURE_1D }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_test_size_descriptors(sizes, nsizes); + + return test_images_read_common(device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes); +} + +int test_images_write_1D( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + GLenum targets[] = { GL_TEXTURE_1D }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_test_size_descriptors(sizes, nsizes); + + return test_images_write_common( device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes ); +} + +int test_images_1D_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + GLenum targets[] = { GL_TEXTURE_1D }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_test_size_descriptors(sizes, nsizes); + + return test_images_get_info_common( device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes); +} + +int test_images_read_texturebuffer( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + GLenum targets[] = { GL_TEXTURE_BUFFER }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_test_size_descriptors(sizes, nsizes); + + return test_images_read_common(device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes); +} + +int test_images_write_texturebuffer( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + GLenum targets[] = { GL_TEXTURE_BUFFER }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_test_size_descriptors(sizes, nsizes); + + return test_images_write_common( device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes ); +} + +int test_images_texturebuffer_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + GLenum targets[] = { GL_TEXTURE_BUFFER }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_test_size_descriptors(sizes, nsizes); + + return test_images_get_info_common( device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes); +} + diff --git a/test_conformance/gl/test_images_1Darray.cpp b/test_conformance/gl/test_images_1Darray.cpp new file mode 100644 index 00000000..1914a457 --- /dev/null +++ b/test_conformance/gl/test_images_1Darray.cpp @@ -0,0 +1,90 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" +#include "testBase.h" + +#if defined( __APPLE__ ) + #include +#else + #include + #include +#endif +#include + +using namespace std; +void calc_1D_array_size_descriptors(sizevec_t* sizes, size_t nsizes) +{ + // Need to limit array size according to GL device properties + GLint maxTextureLayers = 16, maxTextureSize = 4096; + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + + RandomSeed seed( gRandomSeed ); + + // Generate some random sizes (within reasonable ranges) + for (size_t i = 0; i < nsizes; i++) { + sizes[i].width = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed ); + sizes[i].height = random_in_range( 2, min(maxTextureLayers, 1<<(i+4)), seed ); + sizes[i].depth = 1; + } +} + +int test_images_read_1Darray( cl_device_id device, cl_context context, + cl_command_queue queue, int ) +{ + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + GLenum targets[] = { GL_TEXTURE_1D_ARRAY }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_1D_array_size_descriptors(sizes, nsizes); + + return test_images_read_common(device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes); +} + +int test_images_write_1Darray( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + GLenum targets[] = { GL_TEXTURE_1D_ARRAY }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_1D_array_size_descriptors(sizes, nsizes); + + return test_images_write_common( device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes ); +} + +int test_images_1Darray_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int ) +{ + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + GLenum targets[] = { GL_TEXTURE_1D_ARRAY }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_1D_array_size_descriptors(sizes, nsizes); + + return test_images_get_info_common(device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes); +} \ No newline at end of file diff --git a/test_conformance/gl/test_images_2D.cpp b/test_conformance/gl/test_images_2D.cpp new file mode 100644 index 00000000..5af48ea8 --- /dev/null +++ b/test_conformance/gl/test_images_2D.cpp @@ -0,0 +1,190 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "common.h" + +#if defined( __APPLE__ ) +#include +#else +#include +#include +#endif +#include + +using namespace std; + +extern "C" { extern cl_uint gRandomSeed; } + +#pragma mark - +#pragma mark _2D read tests + +void calc_2D_test_size_descriptors(sizevec_t* sizes, size_t nsizes) +{ + // Need to limit array size according to GL device properties + // Need to limit texture size according to GL device properties + GLint maxTextureSize = 4096, maxTextureRectangleSize = 4096, size; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT, &maxTextureRectangleSize); + + size = min(maxTextureSize, maxTextureRectangleSize); + + RandomSeed seed( gRandomSeed ); + + // Generate some random sizes (within reasonable ranges) + for (size_t i = 0; i < nsizes; i++) { + sizes[i].width = random_in_range( 2, min(size, 1<<(i+4)), seed ); + sizes[i].height = random_in_range( 2, min(size, 1<<(i+4)), seed ); + sizes[i].depth = 1; + } +} + +void calc_cube_test_size_descriptors(sizevec_t* sizes, size_t nsizes) +{ + // Need to limit array size according to GL device properties + // Need to limit texture size according to GL device properties + GLint maxQubeMapSize = 4096; + glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxQubeMapSize); + + RandomSeed seed( gRandomSeed ); + + // Generate some random sizes (within reasonable ranges) + for (size_t i = 0; i < nsizes; i++) { + sizes[i].width = sizes[i].height = random_in_range( 2, min(maxQubeMapSize, 1<<(i+4)), seed ); + sizes[i].depth = 1; + } +} + +int test_images_read_2D( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_2D_test_size_descriptors(sizes, nsizes); + + return test_images_read_common(device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes); +} + +int test_images_read_cube( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + GLenum targets[] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; + + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_cube_test_size_descriptors(sizes, nsizes); + + return test_images_read_common(device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes); +} + +#pragma mark - +#pragma mark _2D write tests + +#include "common.h" + +int test_images_write( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_2D_test_size_descriptors(sizes, nsizes); + + return test_images_write_common( device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes ); +} + +int test_images_write_cube( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + GLenum targets[] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_cube_test_size_descriptors(sizes, nsizes); + + return test_images_write_common( device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes ); +} + +#pragma mark - +#pragma mark _2D get info tests + +int test_images_2D_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_2D_test_size_descriptors(sizes, nsizes); + + return test_images_get_info_common(device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes); +} + +int test_images_cube_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + GLenum targets[] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_cube_test_size_descriptors(sizes, nsizes); + + return test_images_get_info_common(device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes); +} diff --git a/test_conformance/gl/test_images_2Darray.cpp b/test_conformance/gl/test_images_2Darray.cpp new file mode 100644 index 00000000..bb7095d1 --- /dev/null +++ b/test_conformance/gl/test_images_2Darray.cpp @@ -0,0 +1,93 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" +#include "testBase.h" + +#if defined( __APPLE__ ) + #include +#else + #include + #include +#endif +#include + +using namespace std; + +void calc_2D_array_size_descriptors(sizevec_t* sizes, size_t nsizes) +{ + // Need to limit array size according to GL device properties + GLint maxTextureLayers = 16, maxTextureSize = 4096; + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + + RandomSeed seed( gRandomSeed ); + + // Generate some random sizes (within reasonable ranges) + for (size_t i = 0; i < nsizes; i++) { + sizes[i].width = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed ); + sizes[i].height = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed ); + sizes[i].depth = random_in_range( 2, min(maxTextureLayers, 1<<(i+4)), seed ); + } +} + +int test_images_read_2Darray( cl_device_id device, cl_context context, + cl_command_queue queue, int ) +{ + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + GLenum targets[] = { GL_TEXTURE_2D_ARRAY }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + + const size_t nsizes = 6; + sizevec_t sizes[nsizes]; + calc_2D_array_size_descriptors(sizes, nsizes); + + return test_images_read_common(device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes); +} + +int test_images_write_2Darray( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + // FIXME: Query for 2D image array write support. + + GLenum targets[] = { GL_TEXTURE_2D_ARRAY }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + const size_t nsizes = 6; + sizevec_t sizes[nsizes]; + calc_2D_array_size_descriptors(sizes, nsizes); + + return test_images_write_common( device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes ); +} + +int test_images_2Darray_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int ) +{ + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + GLenum targets[] = { GL_TEXTURE_2D_ARRAY }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + + const size_t nsizes = 6; + sizevec_t sizes[nsizes]; + calc_2D_array_size_descriptors(sizes, nsizes); + + return test_images_get_info_common(device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes); +} \ No newline at end of file diff --git a/test_conformance/gl/test_images_3D.cpp b/test_conformance/gl/test_images_3D.cpp new file mode 100644 index 00000000..a8c80f6e --- /dev/null +++ b/test_conformance/gl/test_images_3D.cpp @@ -0,0 +1,109 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "common.h" + +#if defined( __APPLE__ ) + #include +#else + #include + #include +#endif +#include + +using namespace std; + +extern "C" { extern cl_uint gRandomSeed; }; + +#pragma mark - +#pragma mark _3D read test + +void calc_3D_size_descriptors(sizevec_t* sizes, size_t nsizes) +{ + // Need to limit array size according to GL device properties + GLint maxTextureSize = 2048; + glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &maxTextureSize); + + RandomSeed seed( gRandomSeed ); + + // Generate some random sizes (within reasonable ranges) + for (size_t i = 0; i < nsizes; i++) { + sizes[i].width = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed ); + sizes[i].height = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed ); + sizes[i].depth = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed ); + } +} + +int test_images_read_3D( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLenum targets[] = { GL_TEXTURE_3D }; + size_t ntargets = 1; + + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + const size_t nsizes = 6; + sizevec_t sizes[nsizes]; + calc_3D_size_descriptors(sizes, nsizes); + + return test_images_read_common(device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes); +} + +#pragma mark - +#pragma marm _3D write test + +int test_images_write_3D( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + // TODO: Perhaps the expected behavior is to FAIL if 3D images are + // unsupported? + + if (!is_extension_available(device, "cl_khr_3d_image_writes")) { + log_info("This device does not support 3D image writes. Skipping test.\n"); + return 0; + } + + GLenum targets[] = { GL_TEXTURE_3D }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + + const size_t nsizes = 6; + sizevec_t sizes[nsizes]; + calc_3D_size_descriptors(sizes, nsizes); + + return test_images_write_common( device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes ); +} + +#pragma mark - +#pragma mark _3D get info test + +int test_images_3D_getinfo( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + GLenum targets[] = { GL_TEXTURE_3D }; + size_t ntargets = 1; + + size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]); + + const size_t nsizes = 6; + sizevec_t sizes[nsizes]; + calc_3D_size_descriptors(sizes, nsizes); + + return test_images_get_info_common(device, context, queue, common_formats, + nformats, targets, ntargets, sizes, nsizes); +} diff --git a/test_conformance/gl/test_images_depth.cpp b/test_conformance/gl/test_images_depth.cpp new file mode 100644 index 00000000..09152850 --- /dev/null +++ b/test_conformance/gl/test_images_depth.cpp @@ -0,0 +1,162 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "common.h" + +#if defined( __APPLE__ ) +#include +#else +#include +#include +#endif + +#include + +using namespace std; + +extern "C" { extern cl_uint gRandomSeed; } + +#pragma mark - +#pragma mark _2D depth read tests + +void calc_depth_size_descriptors(sizevec_t* sizes, size_t nsizes) +{ + // Need to limit texture size according to GL device properties + GLint maxTextureSize = 4096, maxTextureRectangleSize = 4096, size; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT, &maxTextureRectangleSize); + + size = min(maxTextureSize, maxTextureRectangleSize); + + RandomSeed seed( gRandomSeed ); + + // Generate some random sizes (within reasonable ranges) + for (size_t i = 0; i < nsizes; i++) { + sizes[i].width = random_in_range( 2, min(size, 1<<(i+4)), seed ); + sizes[i].height = random_in_range( 2, min(size, 1<<(i+4)), seed ); + sizes[i].depth = 1; + } +} + +void calc_depth_array_size_descriptors(sizevec_t* sizes, size_t nsizes) +{ + // Need to limit texture size according to GL device properties + GLint maxTextureSize = 4096, maxTextureRectangleSize = 4096, maxTextureLayers = 16, size; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT, &maxTextureRectangleSize); + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers); + + size = min(maxTextureSize, maxTextureRectangleSize); + + RandomSeed seed( gRandomSeed ); + + // Generate some random sizes (within reasonable ranges) + for (size_t i = 0; i < nsizes; i++) { + sizes[i].width = random_in_range( 2, min(size, 1<<(i+4)), seed ); + sizes[i].height = random_in_range( 2, min(size, 1<<(i+4)), seed ); + sizes[i].depth = random_in_range( 2, min(maxTextureLayers, 1<<(i+4)), seed ); + } +} + +int test_images_read_2D_depth( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + if (!is_extension_available(device, "cl_khr_gl_depth_images")) { + log_info("Test not run because 'cl_khr_gl_depth_images' extension is not supported by the tested device\n"); + return 0; + } + + RandomSeed seed( gRandomSeed ); + + GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + + size_t nformats = sizeof(depth_formats) / sizeof(depth_formats[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_depth_size_descriptors(sizes, nsizes); + + return test_images_read_common(device, context, queue, depth_formats, + nformats, targets, ntargets, sizes, nsizes); +} + +#pragma mark - +#pragma mark _2D depth write tests + + +int test_images_write_2D_depth( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + if (!is_extension_available(device, "cl_khr_gl_depth_images")) { + log_info("Test not run because 'cl_khr_gl_depth_images' extension is not supported by the tested device\n"); + return 0; + } + + GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + size_t nformats = sizeof(depth_formats) / sizeof(depth_formats[0]); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_depth_size_descriptors(sizes, nsizes); + + return test_images_write_common( device, context, queue, depth_formats, + nformats, targets, ntargets, sizes, nsizes ); +} + +int test_images_read_2Darray_depth( cl_device_id device, cl_context context, + cl_command_queue queue, int ) +{ + if (!is_extension_available(device, "cl_khr_gl_depth_images")) { + log_info("Test not run because 'cl_khr_gl_depth_images' extension is not supported by the tested device\n"); + return 0; + } + + size_t nformats = sizeof(depth_formats) / sizeof(depth_formats[0]); + GLenum targets[] = { GL_TEXTURE_2D_ARRAY }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + + const size_t nsizes = 6; + sizevec_t sizes[nsizes]; + calc_depth_array_size_descriptors(sizes, nsizes); + + return test_images_read_common(device, context, queue, depth_formats, + nformats, targets, ntargets, sizes, nsizes); +} + +int test_images_write_2Darray_depth( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + if (!is_extension_available(device, "cl_khr_gl_depth_images")) { + log_info("Test not run because 'cl_khr_gl_depth_images' extension is not supported by the tested device\n"); + return 0; + } + + // FIXME: Query for 2D image array write support. + + GLenum targets[] = { GL_TEXTURE_2D_ARRAY }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + size_t nformats = sizeof(depth_formats) / sizeof(depth_formats[0]); + + const size_t nsizes = 6; + sizevec_t sizes[nsizes]; + calc_depth_array_size_descriptors(sizes, nsizes); + + return test_images_write_common( device, context, queue, depth_formats, + nformats, targets, ntargets, sizes, nsizes ); +} + diff --git a/test_conformance/gl/test_images_getinfo_common.cpp b/test_conformance/gl/test_images_getinfo_common.cpp new file mode 100644 index 00000000..bc21496a --- /dev/null +++ b/test_conformance/gl/test_images_getinfo_common.cpp @@ -0,0 +1,262 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "common.h" + +#if defined( __APPLE__ ) + #include +#else + #include + #include +#endif + +extern "C" { extern cl_uint gRandomSeed; }; + +extern int supportsHalf(cl_context context, bool* supports_half); + +static int test_image_info( cl_context context, cl_command_queue queue, + GLenum glTarget, GLuint glTexture, size_t imageWidth, size_t imageHeight, + size_t imageDepth, cl_image_format *outFormat, ExplicitType *outType, + void **outResultBuffer ) +{ + clMemWrapper streams[ 2 ]; + + int error; + + // Create a CL image from the supplied GL texture + streams[ 0 ] = (*clCreateFromGLTexture_ptr)( context, CL_MEM_READ_ONLY, + glTarget, 0, glTexture, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create CL image from GL texture" ); + GLint fmt; + glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt ); + log_error( " Supplied GL texture was format %s\n", GetGLFormatName( fmt ) ); + return error; + } + + // Determine data type and format that CL came up with + error = clGetImageInfo( streams[ 0 ], CL_IMAGE_FORMAT, + sizeof( cl_image_format ), outFormat, NULL ); + test_error( error, "Unable to get CL image format" ); + + cl_gl_object_type object_type; + switch (glTarget) { + case GL_TEXTURE_1D: + object_type = CL_GL_OBJECT_TEXTURE1D; + break; + case GL_TEXTURE_BUFFER: + object_type = CL_GL_OBJECT_TEXTURE_BUFFER; + break; + case GL_TEXTURE_1D_ARRAY: + object_type = CL_GL_OBJECT_TEXTURE1D_ARRAY; + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE_EXT: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + object_type = CL_GL_OBJECT_TEXTURE2D; + break; + case GL_TEXTURE_2D_ARRAY: + object_type = CL_GL_OBJECT_TEXTURE2D_ARRAY; + break; + case GL_TEXTURE_3D: + object_type = CL_GL_OBJECT_TEXTURE3D; + break; + default: + log_error("Unsupported texture target."); + return 1; + } + + return CheckGLObjectInfo(streams[0], object_type, glTexture, glTarget, 0); +} + +static int test_image_format_get_info( + cl_context context, cl_command_queue queue, + size_t width, size_t height, size_t depth, + GLenum target, struct format* fmt, MTdata data) +{ + int error = 0; + + // If we're testing a half float format, then we need to determine the + // rounding mode of this machine. Punt if we fail to do so. + + if( fmt->type == kHalf ) + { + if( DetectFloatToHalfRoundingMode(queue) ) + return 0; + bool supports_half = false; + error = supportsHalf(context, &supports_half); + if( error != 0 ) + return error; + if (!supports_half) return 0; + } + + size_t w = width, h = height, d = depth; + + // Unpack the format and use it, along with the target, to create an + // appropriate GL texture. + + GLenum gl_fmt = fmt->formattype; + GLenum gl_internal_fmt = fmt->internal; + GLenum gl_type = fmt->datatype; + ExplicitType type = fmt->type; + + glTextureWrapper texture; + glBufferWrapper glbuf; + + // If we're testing a half float format, then we need to determine the + // rounding mode of this machine. Punt if we fail to do so. + + if( fmt->type == kHalf ) + if( DetectFloatToHalfRoundingMode(queue) ) + return 1; + + // Use the correct texture creation function depending on the target, and + // adjust width, height, depth as appropriate so subsequent size calculations + // succeed. + + switch (target) { + case GL_TEXTURE_1D: + h = 1; d = 1; + CreateGLTexture1D( width, target, gl_fmt, + gl_internal_fmt, gl_type, type, &texture, &error, false, data ); + break; + case GL_TEXTURE_BUFFER: + h = 1; d = 1; + CreateGLTextureBuffer( width, target, gl_fmt, + gl_internal_fmt, gl_type, type, &texture, &glbuf, &error, false, data ); + break; + case GL_TEXTURE_1D_ARRAY: + d = 1; + CreateGLTexture1DArray( width, height, target, gl_fmt, + gl_internal_fmt, gl_type, type, &texture, &error, false, data ); + break; + case GL_TEXTURE_RECTANGLE_EXT: + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + d = 1; + CreateGLTexture2D( width, height, target, gl_fmt, + gl_internal_fmt, gl_type, type, &texture, &error, false, data ); + break; + case GL_TEXTURE_2D_ARRAY: + CreateGLTexture2DArray( width, height, depth, target, gl_fmt, + gl_internal_fmt, gl_type, type, &texture, &error, false, data ); + break; + case GL_TEXTURE_3D: + d = 1; + CreateGLTexture3D( width, height, depth, target, gl_fmt, + gl_internal_fmt, gl_type, type, &texture, &error, data, false ); + break; + default: + log_error("Unsupported texture target.\n"); + return 1; + } + + if ( error == -2 ) { + log_info("OpenGL texture couldn't be created, because a texture is too big. Skipping test.\n"); + return 0; + } + + if ( error != 0 ) { + if ((gl_fmt == GL_RGBA_INTEGER_EXT) && (!CheckGLIntegerExtensionSupport())) { + log_info("OpenGL version does not support GL_RGBA_INTEGER_EXT. " + "Skipping test.\n"); + return 0; + } else { + return error; + } + } + + cl_image_format clFormat; + ExplicitType actualType; + char *outBuffer; + + // Perform the info check: + return test_image_info( context, queue, target, texture, w, h, d, &clFormat, + &actualType, (void **)&outBuffer ); +} + +int test_images_get_info_common( cl_device_id device, cl_context context, + cl_command_queue queue, struct format* formats, size_t nformats, + GLenum *targets, size_t ntargets, sizevec_t *sizes, size_t nsizes ) +{ + int error = 0; + RandomSeed seed(gRandomSeed); + + // First, ensure this device supports images. + + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + size_t fidx, tidx, sidx; + + // Test each format on every target, every size. + + for ( fidx = 0; fidx < nformats; fidx++ ) { + for ( tidx = 0; tidx < ntargets; tidx++ ) { + + if ( formats[ fidx ].datatype == GL_UNSIGNED_INT_2_10_10_10_REV ) + { + // Check if the RGB 101010 format is supported + if ( is_rgb_101010_supported( context, targets[ tidx ] ) == 0 ) + break; // skip + } + + log_info( "Testing image info for GL format %s : %s : %s : %s\n", + GetGLTargetName( targets[ tidx ] ), + GetGLFormatName( formats[ fidx ].internal ), + GetGLBaseFormatName( formats[ fidx ].formattype ), + GetGLTypeName( formats[ fidx ].datatype ) ); + + for ( sidx = 0; sidx < nsizes; sidx++ ) { + + // Test this format + size: + + if ( test_image_format_get_info(context, queue, + sizes[sidx].width, sizes[sidx].height, sizes[sidx].depth, + targets[tidx], &formats[fidx], seed) ) + { + // We land here in the event of test failure. + + log_error( "ERROR: Image info test failed for %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tidx ] ), + GetGLFormatName( formats[ fidx ].internal ), + GetGLBaseFormatName( formats[ fidx ].formattype ), + GetGLTypeName( formats[ fidx ].datatype ) ); + error++; + + // Skip the other sizes for this format. + + break; + } + } + } + } + + return error; +} diff --git a/test_conformance/gl/test_images_multisample.cpp b/test_conformance/gl/test_images_multisample.cpp new file mode 100644 index 00000000..99f9ff2e --- /dev/null +++ b/test_conformance/gl/test_images_multisample.cpp @@ -0,0 +1,118 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" +#include "testBase.h" + +#if defined( __APPLE__ ) + #include +#else + #include + #include +#endif + +#include + +using namespace std; + +void calc_2D_multisample_size_descriptors(sizevec_t* sizes, size_t nsizes) +{ + // Need to limit texture size according to GL device properties + GLint maxTextureSize = 4096; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + + RandomSeed seed( gRandomSeed ); + + // Generate some random sizes (within reasonable ranges) + for (size_t i = 0; i < nsizes; i++) { + sizes[i].width = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed ); + sizes[i].height = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed ); + sizes[i].depth = 1; + } +} + +void calc_2D_array_multisample_size_descriptors(sizevec_t* sizes, size_t nsizes) +{ + // Need to limit array size according to GL device properties + GLint maxTextureLayers = 16, maxTextureSize = 4096; + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + + RandomSeed seed( gRandomSeed ); + + // Generate some random sizes (within reasonable ranges) + for (size_t i = 0; i < nsizes; i++) { + sizes[i].width = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed ); + sizes[i].height = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed ); + sizes[i].depth = random_in_range( 2, min(maxTextureLayers, 1<<(i+4)), seed ); + } +} + +int test_images_read_2D_multisample( cl_device_id device, cl_context context, + cl_command_queue queue, int numElements ) +{ + if (!is_extension_available(device, "cl_khr_gl_msaa_sharing")) { + log_info("Test not run because 'cl_khr_gl_msaa_sharing' extension is not supported by the tested device\n"); + return 0; + } + + glEnable(GL_MULTISAMPLE); + + const size_t nsizes = 8; + sizevec_t sizes[nsizes]; + calc_2D_multisample_size_descriptors(sizes, nsizes); + + size_t nformats; + + GLenum targets[] = { GL_TEXTURE_2D_MULTISAMPLE }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + + nformats = sizeof(common_formats) / sizeof(common_formats[0]); + int ret_common = test_images_read_common(device, context, queue, common_formats, nformats, targets, ntargets, sizes, nsizes); + + nformats = sizeof(depth_formats) / sizeof(depth_formats[0]); + int ret_depth = test_images_read_common(device, context, queue, depth_formats, nformats, targets, ntargets, sizes, nsizes); + + return (ret_common) ? ret_common : ret_depth; +} + +int test_images_read_2Darray_multisample( cl_device_id device, cl_context context, + cl_command_queue queue, int ) +{ + if (!is_extension_available(device, "cl_khr_gl_msaa_sharing")) { + log_info("Test not run because 'cl_khr_gl_msaa_sharing' extension is not supported by the tested device\n"); + return 0; + } + + glEnable(GL_MULTISAMPLE); + + const size_t nsizes = 4; + sizevec_t sizes[nsizes]; + calc_2D_array_multisample_size_descriptors(sizes, nsizes); + + size_t nformats; + + GLenum targets[] = { GL_TEXTURE_2D_MULTISAMPLE_ARRAY }; + size_t ntargets = sizeof(targets) / sizeof(targets[0]); + + nformats = sizeof(common_formats) / sizeof(common_formats[0]); + int ret_common = test_images_read_common(device, context, queue, common_formats, nformats, targets, ntargets, sizes, nsizes); + + nformats = sizeof(depth_formats) / sizeof(depth_formats[0]); + int ret_depth = test_images_read_common(device, context, queue, depth_formats, nformats, targets, ntargets, sizes, nsizes); + + return (ret_common) ? ret_common : ret_depth; +} + diff --git a/test_conformance/gl/test_images_read_common.cpp b/test_conformance/gl/test_images_read_common.cpp new file mode 100644 index 00000000..068b9a29 --- /dev/null +++ b/test_conformance/gl/test_images_read_common.cpp @@ -0,0 +1,736 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" +#include "testBase.h" + +#if defined( __APPLE__ ) + #include +#else + #include + #include +#endif + +extern "C" { extern cl_uint gRandomSeed; }; + +extern int supportsHalf(cl_context context, bool* supports_half); +extern int supportsMsaa(cl_context context, bool* supports_msaa); +extern int supportsDepth(cl_context context, bool* supports_depth); + +static const char *kernelpattern_image_read_1d = +"__kernel void sample_test( read_only image1d_t source, sampler_t sampler, __global %s4 *results )\n" +"{\n" +" int offset = get_global_id(0);\n" +" results[ offset ] = read_image%s( source, sampler, offset );\n" +"}\n"; + +static const char *kernelpattern_image_read_1d_buffer = +"__kernel void sample_test( read_only image1d_buffer_t source, sampler_t sampler, __global %s4 *results )\n" +"{\n" +" int offset = get_global_id(0);\n" +" results[ offset ] = read_image%s( source, offset );\n" +"}\n"; + +static const char *kernelpattern_image_read_1darray = +"__kernel void sample_test( read_only image1d_array_t source, sampler_t sampler, __global %s4 *results )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" results[ tidY * get_image_width( source ) + tidX ] = read_image%s( source, sampler, (int2)( tidX, tidY ) );\n" +"}\n"; + +static const char *kernelpattern_image_read_2d = +"__kernel void sample_test( read_only image2d_t source, sampler_t sampler, __global %s4 *results )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" results[ tidY * get_image_width( source ) + tidX ] = read_image%s( source, sampler, (int2)( tidX, tidY ) );\n" +"}\n"; + +static const char *kernelpattern_image_read_2darray = +"__kernel void sample_test( read_only image2d_array_t source, sampler_t sampler, __global %s4 *results )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" int tidZ = get_global_id(2);\n" +" int width = get_image_width( source );\n" +" int height = get_image_height( source );\n" +" int offset = tidZ * width * height + tidY * width + tidX;\n" +"\n" +" results[ offset ] = read_image%s( source, sampler, (int4)( tidX, tidY, tidZ, 0 ) );\n" +"}\n"; + +static const char *kernelpattern_image_read_3d = +"__kernel void sample_test( read_only image3d_t source, sampler_t sampler, __global %s4 *results )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" int tidZ = get_global_id(2);\n" +" int width = get_image_width( source );\n" +" int height = get_image_height( source );\n" +" int offset = tidZ * width * height + tidY * width + tidX;\n" +"\n" +" results[ offset ] = read_image%s( source, sampler, (int4)( tidX, tidY, tidZ, 0 ) );\n" +"}\n"; + +static const char *kernelpattern_image_read_2d_depth = +"__kernel void sample_test( read_only image2d_depth_t source, sampler_t sampler, __global %s *results )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" results[ tidY * get_image_width( source ) + tidX ] = read_image%s( source, sampler, (int2)( tidX, tidY ) );\n" +"}\n"; + +static const char *kernelpattern_image_read_2darray_depth = +"__kernel void sample_test( read_only image2d_array_depth_t source, sampler_t sampler, __global %s *results )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" int tidZ = get_global_id(2);\n" +" int width = get_image_width( source );\n" +" int height = get_image_height( source );\n" +" int offset = tidZ * width * height + tidY * width + tidX;\n" +"\n" +" results[ offset ] = read_image%s( source, sampler, (int4)( tidX, tidY, tidZ, 0 ) );\n" +"}\n"; + +static const char *kernelpattern_image_multisample_read_2d = +"__kernel void sample_test( read_only image2d_msaa_t source, sampler_t sampler, __global %s4 *results )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" int width = get_image_width( source );\n" +" int height = get_image_height( source );\n" +" int num_samples = get_image_num_samples( source );\n" +" for(size_t sample = 0; sample < num_samples; sample++ ) {\n" +" int offset = sample * width * height + tidY * width + tidX;\n" +" results[ offset ] = read_image%s( source, (int2)( tidX, tidY ), sample );\n" +" }\n" +"}\n"; + +static const char *kernelpattern_image_multisample_read_2d_depth = + "__kernel void sample_test( read_only image2d_msaa_depth_t source, sampler_t sampler, __global %s *results )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" int width = get_image_width( source );\n" +" int height = get_image_height( source );\n" + " int num_samples = get_image_num_samples( source );\n" + " for(size_t sample = 0; sample < num_samples; sample++ ) {\n" +" int offset = sample * width * height + tidY * width + tidX;\n" +" results[ offset ] = read_image%s( source, (int2)( tidX, tidY ), sample );\n" + " }\n" +"}\n"; + +static const char *kernelpattern_image_multisample_read_2darray = +"__kernel void sample_test( read_only image2d_array_msaa_t source, sampler_t sampler, __global %s4 *results )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" int tidZ = get_global_id(2);\n" +" int num_samples = get_image_num_samples( source );\n" +" int width = get_image_width( source );\n" +" int height = get_image_height( source );\n" +" int array_size = get_image_array_size( source );\n" +" for(size_t sample = 0; sample< num_samples; ++sample) {\n" +" int offset = (array_size * width * height) * sample + (width * height) * tidZ + tidY * width + tidX;\n" +" results[ offset ] = read_image%s( source, (int4)( tidX, tidY, tidZ, 1 ), sample );\n" +" }\n" +"}\n"; + +static const char *kernelpattern_image_multisample_read_2darray_depth = + "__kernel void sample_test( read_only image2d_array_msaa_depth_t source, sampler_t sampler, __global %s *results )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" int tidZ = get_global_id(2);\n" +" int num_samples = get_image_num_samples( source );\n" +" int width = get_image_width( source );\n" +" int height = get_image_height( source );\n" + " int array_size = get_image_array_size( source );\n" + " for(size_t sample = 0; sample < num_samples; ++sample) {\n" + " int offset = (array_size * width * height) * sample + (width * height) * tidZ + tidY * width + tidX;\n" + " results[ offset ] = read_image%s( source, (int4)( tidX, tidY, tidZ, 1 ), sample );\n" + " }\n" +"}\n"; + +static const char* get_appropriate_kernel_for_target(GLenum target, cl_channel_order channel_order) { + + switch (get_base_gl_target(target)) { + case GL_TEXTURE_1D: + return kernelpattern_image_read_1d; + case GL_TEXTURE_BUFFER: + return kernelpattern_image_read_1d_buffer; + case GL_TEXTURE_1D_ARRAY: + return kernelpattern_image_read_1darray; + case GL_TEXTURE_RECTANGLE_EXT: + case GL_TEXTURE_2D: + case GL_COLOR_ATTACHMENT0: + case GL_RENDERBUFFER: + case GL_TEXTURE_CUBE_MAP: +#ifdef GL_VERSION_3_2 + if(channel_order == CL_DEPTH || channel_order == CL_DEPTH_STENCIL) + return kernelpattern_image_read_2d_depth; +#endif + return kernelpattern_image_read_2d; + case GL_TEXTURE_2D_ARRAY: +#ifdef GL_VERSION_3_2 + if(channel_order == CL_DEPTH || channel_order == CL_DEPTH_STENCIL) + return kernelpattern_image_read_2darray_depth; +#endif + return kernelpattern_image_read_2darray; + case GL_TEXTURE_3D: + return kernelpattern_image_read_3d; + case GL_TEXTURE_2D_MULTISAMPLE: +#ifdef GL_VERSION_3_2 + if(channel_order == CL_DEPTH || channel_order == CL_DEPTH_STENCIL) + return kernelpattern_image_multisample_read_2d_depth; +#endif + return kernelpattern_image_multisample_read_2d; + break; + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: +#ifdef GL_VERSION_3_2 + if(channel_order == CL_DEPTH || channel_order == CL_DEPTH_STENCIL) + return kernelpattern_image_multisample_read_2darray_depth; +#endif + return kernelpattern_image_multisample_read_2darray; + break; + default: + log_error("Unsupported texture target (%s); cannot determine " + "appropriate kernel.", GetGLTargetName(target)); + return NULL; + } +} + +int test_cl_image_read( cl_context context, cl_command_queue queue, + GLenum gl_target, cl_mem image, size_t width, size_t height, size_t depth, size_t sampleNum, + cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 2 ]; + + int error; + char kernelSource[2048]; + char *programPtr; + + // Use the image created from the GL texture. + streams[ 0 ] = image; + + // Determine data type and format that CL came up with + error = clGetImageInfo( streams[ 0 ], CL_IMAGE_FORMAT, sizeof( cl_image_format ), outFormat, NULL ); + test_error( error, "Unable to get CL image format" ); + + // Determine the number of samples + cl_uint samples = 0; + error = clGetImageInfo( streams[ 0 ], CL_IMAGE_NUM_SAMPLES, sizeof( samples ), &samples, NULL ); + test_error( error, "Unable to get CL_IMAGE_NUM_SAMPLES" ); + + // Create the source + *outType = get_read_kernel_type( outFormat ); + size_t channelSize = get_explicit_type_size( *outType ); + + const char* source = get_appropriate_kernel_for_target(gl_target, outFormat->image_channel_order); + + sprintf( kernelSource, source, get_explicit_type_name( *outType ), + get_kernel_suffix( outFormat ) ); + + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, + (const char **)&programPtr, "sample_test" ) ) + { + return -1; + } + + // Create a vanilla output buffer + cl_device_id device; + error = clGetCommandQueueInfo(queue, CL_QUEUE_DEVICE, sizeof(device), &device, NULL); + test_error( error, "Unable to get queue device" ); + + cl_ulong maxAllocSize = 0; + error = clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE" ); + + size_t buffer_bytes = channelSize * get_channel_order_channel_count(outFormat->image_channel_order) * width * height * depth * sampleNum; + if (buffer_bytes > maxAllocSize) { + log_info("Output buffer size %d is too large for device (max alloc size %d) Skipping...\n", + (int)buffer_bytes, (int)maxAllocSize); + return 1; + } + + streams[ 1 ] = clCreateBuffer( context, CL_MEM_READ_WRITE, buffer_bytes, NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + /* Assign streams and execute */ + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_NONE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + clSamplerWrapper sampler = clCreateSamplerWithProperties( context, properties, &error ); + test_error( error, "Unable to create sampler" ); + + error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( sampler ), &sampler ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, 2, sizeof( streams[ 1 ] ), &streams[ 1 ] ); + test_error( error, "Unable to set kernel arguments" ); + + glFinish(); + + error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &streams[ 0 ], 0, NULL, NULL); + test_error( error, "Unable to acquire GL obejcts"); + + // The ND range we use is a function of the dimensionality of the image. + size_t global_range[3] = { width, height, depth }; + size_t *local_range = NULL; + int ndim = 1; + + switch (get_base_gl_target(gl_target)) { + case GL_TEXTURE_1D: + case GL_TEXTURE_BUFFER: + ndim = 1; + break; + case GL_TEXTURE_RECTANGLE_EXT: + case GL_TEXTURE_2D: + case GL_TEXTURE_1D_ARRAY: + case GL_COLOR_ATTACHMENT0: + case GL_RENDERBUFFER: + case GL_TEXTURE_CUBE_MAP: + ndim = 2; + break; + case GL_TEXTURE_3D: + case GL_TEXTURE_2D_ARRAY: +#ifdef GL_VERSION_3_2 + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + ndim = 3; + break; +#endif + default: + log_error("Test error: Unsupported texture target.\n"); + return 1; + } + + // 2D and 3D images have a special way to set the local size (legacy). + // Otherwise, we let CL select by leaving local_range as NULL. + + if (gl_target == GL_TEXTURE_2D) { + local_range = (size_t*)malloc(sizeof(size_t) * ndim); + get_max_common_2D_work_group_size( context, kernel, global_range, local_range ); + + } else if (gl_target == GL_TEXTURE_3D) { + local_range = (size_t*)malloc(sizeof(size_t) * ndim); + get_max_common_3D_work_group_size( context, kernel, global_range, local_range ); + } + + error = clEnqueueNDRangeKernel( queue, kernel, ndim, NULL, global_range, + local_range, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &streams[ 0 ], + 0, NULL, NULL ); + test_error(error, "clEnqueueReleaseGLObjects failed"); + + // Read results from the CL buffer + *outResultBuffer = (void *)( new char[ channelSize * get_channel_order_channel_count(outFormat->image_channel_order) * width * height * depth * sampleNum] ); + error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, + channelSize * get_channel_order_channel_count(outFormat->image_channel_order) * width * height * depth * sampleNum, *outResultBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read output CL buffer!" ); + + // free the ranges + if (local_range) free(local_range); + + return 0; +} + +static int test_image_read( cl_context context, cl_command_queue queue, + GLenum target, GLuint globj, size_t width, size_t height, size_t depth, size_t sampleNum, + cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer ) +{ + int error; + + // Create a CL image from the supplied GL texture or renderbuffer. + cl_mem image; + if (target == GL_RENDERBUFFER || target == GL_COLOR_ATTACHMENT0) { + image = (*clCreateFromGLRenderbuffer_ptr)( context, CL_MEM_READ_ONLY, globj, &error ); + } else { + image = (*clCreateFromGLTexture_ptr)( context, CL_MEM_READ_ONLY, + target, 0, globj, &error ); + } + + if( error != CL_SUCCESS ) { + if (target == GL_RENDERBUFFER || target == GL_COLOR_ATTACHMENT0) { + print_error( error, "Unable to create CL image from GL renderbuffer" ); + } else { + print_error( error, "Unable to create CL image from GL texture" ); + GLint fmt; + glGetTexLevelParameteriv( target, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt ); + log_error( " Supplied GL texture was base format %s and internal " + "format %s\n", GetGLBaseFormatName( fmt ), GetGLFormatName( fmt ) ); + } + return error; + } + + return test_cl_image_read( context, queue, target, image, + width, height, depth, sampleNum, outFormat, outType, outResultBuffer ); +} + +static int test_image_format_read( + cl_context context, cl_command_queue queue, + size_t width, size_t height, size_t depth, + GLenum target, struct format* fmt, MTdata data) +{ + int error = 0; + + // Determine the maximum number of supported samples + GLint samples = 1; + if (target == GL_TEXTURE_2D_MULTISAMPLE || target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) + samples = get_gl_max_samples(target, fmt->internal); + + // If we're testing a half float format, then we need to determine the + // rounding mode of this machine. Punt if we fail to do so. + + if( fmt->type == kHalf ) + { + if( DetectFloatToHalfRoundingMode(queue) ) + return 1; + bool supports_half = false; + error = supportsHalf(context, &supports_half); + if( error != 0 ) + return error; + if (!supports_half) return 0; + } +#ifdef GL_VERSION_3_2 + if (get_base_gl_target(target) == GL_TEXTURE_2D_MULTISAMPLE || + get_base_gl_target(target) == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) + { + bool supports_msaa; + error = supportsMsaa(context, &supports_msaa); + if( error != 0 ) return error; + if (!supports_msaa) return 0; + } + if (fmt->formattype == GL_DEPTH_COMPONENT || + fmt->formattype == GL_DEPTH_STENCIL) + { + bool supports_depth; + error = supportsDepth(context, &supports_depth); + if( error != 0 ) return error; + if (!supports_depth) return 0; + } +#endif + size_t w = width, h = height, d = depth; + + // Unpack the format and use it, along with the target, to create an + // appropriate GL texture. + + GLenum gl_fmt = fmt->formattype; + GLenum gl_internal_fmt = fmt->internal; + GLenum gl_type = fmt->datatype; + ExplicitType type = fmt->type; + + // Required for most of the texture-backed cases: + glTextureWrapper texture; + + // Required for the special case of TextureBuffer textures: + glBufferWrapper glbuf; + + // And these are required for the case of Renderbuffer images: + glFramebufferWrapper glFramebuffer; + glRenderbufferWrapper glRenderbuffer; + + void* buffer = NULL; + + // Use the correct texture creation function depending on the target, and + // adjust width, height, depth as appropriate so subsequent size calculations + // succeed. + + switch (get_base_gl_target(target)) { + case GL_TEXTURE_1D: + h = 1; d = 1; + buffer = CreateGLTexture1D( width, target, gl_fmt, + gl_internal_fmt, gl_type, type, &texture, &error, true, data ); + break; + case GL_TEXTURE_BUFFER: + h = 1; d = 1; + buffer = CreateGLTextureBuffer(width, target, gl_fmt, gl_internal_fmt, + gl_type, type, &texture, &glbuf, &error, true, data); + break; + case GL_RENDERBUFFER: + case GL_COLOR_ATTACHMENT0: + d = 1; + buffer = CreateGLRenderbuffer(width, height, target, gl_fmt, + gl_internal_fmt, gl_type, type, &glFramebuffer, &glRenderbuffer, &error, + data, true); + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE_EXT: + case GL_TEXTURE_CUBE_MAP: + d = 1; + buffer = CreateGLTexture2D(width, height, target, gl_fmt, gl_internal_fmt, + gl_type, type, &texture, &error, true, data); + break; + case GL_TEXTURE_1D_ARRAY: + d = 1; + buffer = CreateGLTexture1DArray( width, height, target, gl_fmt, + gl_internal_fmt, gl_type, type, &texture, &error, true, data ); + break; + case GL_TEXTURE_2D_ARRAY: + buffer = CreateGLTexture2DArray( width, height, depth, target, gl_fmt, + gl_internal_fmt, gl_type, type, &texture, &error, true, data ); + break; + case GL_TEXTURE_3D: + buffer = CreateGLTexture3D( width, height, depth, target, gl_fmt, + gl_internal_fmt, gl_type, type, &texture, &error, data, true ); + break; +#ifdef GL_VERSION_3_2 + case GL_TEXTURE_2D_MULTISAMPLE: + d = 1; + buffer = CreateGLTexture2DMultisample( width, height, samples, target, gl_fmt, + gl_internal_fmt, gl_type, type, &texture, &error, true, data, true ); + break; + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + buffer = CreateGLTexture2DArrayMultisample( width, height, depth, samples, target, gl_fmt, + gl_internal_fmt, gl_type, type, &texture, &error, true, data, true ); + break; +#endif + default: + log_error("Unsupported texture target."); + return 1; + } + + if ( error == -2 ) { + log_info("OpenGL texture couldn't be created, because a texture is too big. Skipping test.\n"); + return 0; + } + + // Check to see if the texture could not be created for some other reason like + // GL_FRAMEBUFFER_UNSUPPORTED + if (error == GL_FRAMEBUFFER_UNSUPPORTED) { + log_info("Skipping...\n"); + return 0; + } + + if ( error != 0 ) { + if ((gl_fmt == GL_RGBA_INTEGER_EXT) && (!CheckGLIntegerExtensionSupport())){ + log_info("OpenGL version does not support GL_RGBA_INTEGER_EXT. " + "Skipping test.\n"); + return 0; + } else { + return error; + } + } + + BufferOwningPtr inputBuffer(buffer); + if( inputBuffer == NULL ) + return -1; + + cl_image_format clFormat; + ExplicitType actualType; + char *outBuffer; + + // Perform the read: + + GLuint globj = texture; + if (target == GL_RENDERBUFFER || target == GL_COLOR_ATTACHMENT0) { + globj = glRenderbuffer; + } + + error = test_image_read( context, queue, target, globj, w, h, d, samples, &clFormat, + &actualType, (void **)&outBuffer ); + + if( error != 0 ) + return error; + + BufferOwningPtr actualResults(outBuffer); + if( actualResults == NULL ) + return -1; + + log_info( "- Read [%4d x %4d x %4d x %4d] : GL Texture : %s : %s : %s => CL Image : %s : %s \n", + (int)w, (int)h, (int)d, (int)samples, GetGLFormatName( gl_fmt ), GetGLFormatName( gl_internal_fmt ), + GetGLTypeName( gl_type ), GetChannelOrderName( clFormat.image_channel_order ), + GetChannelTypeName( clFormat.image_channel_data_type )); + + BufferOwningPtr convertedInputs; + + // We have to convert our input buffer to the returned type, so we can validate. + // This is necessary because OpenCL might not actually pick an internal format + // that actually matches our input format (for example, if it picks a normalized + // format, the results will come out as floats instead of going in as ints). + + if ( gl_type == GL_UNSIGNED_INT_2_10_10_10_REV ) + { + cl_uint *p = (cl_uint *)buffer; + float *inData = (float *)malloc( w * h * d * samples * sizeof(float) ); + + for( size_t i = 0; i < 4 * w * h * d * samples; i += 4 ) + { + inData[ i + 0 ] = (float)( ( p[ 0 ] >> 20 ) & 0x3ff ) / (float)1023; + inData[ i + 1 ] = (float)( ( p[ 0 ] >> 10 ) & 0x3ff ) / (float)1023; + inData[ i + 2 ] = (float)( p[ 0 ] & 0x3ff ) / (float)1023; + p++; + } + + convertedInputs.reset( inData ); + if( convertedInputs == NULL ) + return -1; + } + else if ( gl_type == GL_DEPTH24_STENCIL8 ) + { + // GL_DEPTH24_STENCIL8 is treated as CL_UNORM_INT24 + CL_DEPTH_STENCIL where + // the stencil is ignored. + cl_uint *p = (cl_uint *)buffer; + float *inData = (float *)malloc( w * h * d * samples * sizeof(float) ); + + for( size_t i = 0; i < w * h * d * samples; i++ ) + { + inData[ i ] = (float)((p[i] >> 8) & 0xffffff) / (float)0xfffffe; + } + + convertedInputs.reset( inData ); + if( convertedInputs == NULL ) + return -1; + } + else if ( gl_type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV) + { + // GL_FLOAT_32_UNSIGNED_INT_24_8_REV is treated as a CL_FLOAT + + // unused 24 + CL_DEPTH_STENCIL; we check the float value and ignore the + // second word + + float *p = (float *)buffer; + float *inData = (float *)malloc( w * h * d * samples * sizeof(float) ); + + for( size_t i = 0; i < w * h * d * samples; i++ ) + { + inData[ i ] = p[i*2]; + } + + convertedInputs.reset( inData ); + if( convertedInputs == NULL ) + return -1; + } + else + { + convertedInputs.reset(convert_to_expected( inputBuffer, + w * h * d * samples, type, actualType, get_channel_order_channel_count(clFormat.image_channel_order) )); + if( convertedInputs == NULL ) + return -1; + } + + // Now we validate + if( actualType == kFloat ) + { + if ( clFormat.image_channel_data_type == CL_UNORM_INT_101010 ) + { + return validate_float_results_rgb_101010( convertedInputs, actualResults, w, h, d, samples ); + } + else + { + return validate_float_results( convertedInputs, actualResults, w, h, d, samples, get_channel_order_channel_count(clFormat.image_channel_order) ); + } + } + else + { + return validate_integer_results( convertedInputs, actualResults, w, h, d, samples, get_explicit_type_size( actualType ) ); + } +} + +int test_images_read_common( cl_device_id device, cl_context context, + cl_command_queue queue, struct format* formats, size_t nformats, + GLenum *targets, size_t ntargets, sizevec_t *sizes, size_t nsizes ) +{ + int error = 0; + RandomSeed seed(gRandomSeed); + + // First, ensure this device supports images. + + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + size_t fidx, tidx, sidx; + + // Test each format on every target, every size. + + for ( fidx = 0; fidx < nformats; fidx++ ) { + for ( tidx = 0; tidx < ntargets; tidx++ ) { + + // Texture buffer only takes an internal format, so the level data passed + // by the test and used for verification must match the internal format + if ((targets[tidx] == GL_TEXTURE_BUFFER) && (GetGLFormat(formats[ fidx ].internal) != formats[fidx].formattype)) + continue; + + if ( formats[ fidx ].datatype == GL_UNSIGNED_INT_2_10_10_10_REV ) + { + // Check if the RGB 101010 format is supported + if ( is_rgb_101010_supported( context, targets[ tidx ] ) == 0 ) + break; // skip + } + + if (targets[tidx] != GL_TEXTURE_BUFFER) + log_info( "Testing image read for GL format %s : %s : %s : %s\n", + GetGLTargetName( targets[ tidx ] ), + GetGLFormatName( formats[ fidx ].internal ), + GetGLBaseFormatName( formats[ fidx ].formattype ), + GetGLTypeName( formats[ fidx ].datatype ) ); + else + log_info( "Testing image read for GL format %s : %s\n", + GetGLTargetName( targets[ tidx ] ), + GetGLFormatName( formats[ fidx ].internal )); + + for ( sidx = 0; sidx < nsizes; sidx++ ) { + + // Test this format + size: + int err; + if ((err = test_image_format_read(context, queue, + sizes[sidx].width, sizes[sidx].height, sizes[sidx].depth, + targets[tidx], &formats[fidx], seed) )) + { + // Negative return values are errors, positive mean the test was skipped + if (err < 0) { + + // We land here in the event of test failure. + + log_error( "ERROR: Image read test failed for %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tidx ] ), + GetGLFormatName( formats[ fidx ].internal ), + GetGLBaseFormatName( formats[ fidx ].formattype ), + GetGLTypeName( formats[ fidx ].datatype ) ); + error++; + } + + // Skip the other sizes for this format. + printf("Skipping remaining sizes for this format\n"); + + break; + } + } + + // Note a successful format test, if we passed every size. + + if( sidx == sizeof (sizes) / sizeof( sizes[0] ) ) { + log_info( "passed: Image read test for GL format %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tidx ] ), + GetGLFormatName( formats[ fidx ].internal ), + GetGLBaseFormatName( formats[ fidx ].formattype ), + GetGLTypeName( formats[ fidx ].datatype ) ); + } + } + } + + return error; +} diff --git a/test_conformance/gl/test_images_write_common.cpp b/test_conformance/gl/test_images_write_common.cpp new file mode 100644 index 00000000..7b91f585 --- /dev/null +++ b/test_conformance/gl/test_images_write_common.cpp @@ -0,0 +1,868 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "common.h" +#include + +#if defined( __APPLE__ ) + #include +#else + #include + #include +#endif + +extern "C" { extern cl_uint gRandomSeed; }; + +#pragma mark - +#pragma mark Write test kernels + +static const char *kernelpattern_image_write_1D = +"__kernel void sample_test( __global %s4 *source, write_only image1d_t dest )\n" +"{\n" +" uint index = get_global_id(0);\n" +" %s4 value = source[index];\n" +" write_image%s( dest, index, %s(value));\n" +"}\n"; + +static const char *kernelpattern_image_write_1D_half = +"__kernel void sample_test( __global half4 *source, write_only image1d_t dest )\n" +"{\n" +" uint index = get_global_id(0);\n" +" write_imagef( dest, index, vload_half4(index, (__global half *)source));\n" +"}\n"; + +static const char *kernelpattern_image_write_1D_buffer = +"__kernel void sample_test( __global %s4 *source, write_only image1d_buffer_t dest )\n" +"{\n" +" uint index = get_global_id(0);\n" +" %s4 value = source[index];\n" +" write_image%s( dest, index, %s(value));\n" +"}\n"; + +static const char *kernelpattern_image_write_1D_buffer_half = +"__kernel void sample_test( __global half4 *source, write_only image1d_buffer_t dest )\n" +"{\n" +" uint index = get_global_id(0);\n" +" write_imagef( dest, index, vload_half4(index, (__global half *)source));\n" +"}\n"; + +static const char *kernelpattern_image_write_2D = +"__kernel void sample_test( __global %s4 *source, write_only image2d_t dest )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" uint index = tidY * get_image_width( dest ) + tidX;\n" +" %s4 value = source[index];\n" +" write_image%s( dest, (int2)( tidX, tidY ), %s(value));\n" +"}\n"; + +static const char *kernelpattern_image_write_2D_half = +"__kernel void sample_test( __global half4 *source, write_only image2d_t dest )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" uint index = tidY * get_image_width( dest ) + tidX;\n" +" write_imagef( dest, (int2)( tidX, tidY ), vload_half4(index, (__global half *)source));\n" +"}\n"; + +static const char *kernelpattern_image_write_1Darray = +"__kernel void sample_test( __global %s4 *source, write_only image1d_array_t dest )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" uint index = tidY * get_image_width( dest ) + tidX;\n" +" %s4 value = source[index];\n" +" write_image%s( dest, (int2)( tidX, tidY ), %s(value));\n" +"}\n"; + +static const char *kernelpattern_image_write_1Darray_half = +"__kernel void sample_test( __global half4 *source, write_only image1d_array_t dest )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" uint index = tidY * get_image_width( dest ) + tidX;\n" +" write_imagef( dest, (int2)( tidX, tidY ), vload_half4(index, (__global half *)source));\n" +"}\n"; + +static const char *kernelpattern_image_write_3D = +"__kernel void sample_test( __global %s4 *source, write_only image3d_t dest )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" int tidZ = get_global_id(2);\n" +" int width = get_image_width( dest );\n" +" int height = get_image_height( dest );\n" +" int index = tidZ * width * height + tidY * width + tidX;\n" +" %s4 value = source[index];\n" +" write_image%s( dest, (int4)( tidX, tidY, tidZ, 0 ), %s(value));\n" +"}\n"; + +static const char *kernelpattern_image_write_3D_half = +"__kernel void sample_test( __global half4 *source, write_only image3d_t dest )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" int tidZ = get_global_id(2);\n" +" int width = get_image_width( dest );\n" +" int height = get_image_height( dest );\n" +" int index = tidZ * width * height + tidY * width + tidX;\n" +" write_imagef( dest, (int4)( tidX, tidY, tidZ, 0 ), vload_half4(index, (__global half *)source));\n" +"}\n"; + +static const char *kernelpattern_image_write_2Darray = +"__kernel void sample_test( __global %s4 *source, write_only image2d_array_t dest )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" int tidZ = get_global_id(2);\n" +" int width = get_image_width( dest );\n" +" int height = get_image_height( dest );\n" +" int index = tidZ * width * height + tidY * width + tidX;\n" +" %s4 value = source[index];\n" +" write_image%s( dest, (int4)( tidX, tidY, tidZ, 0 ), %s(value));\n" +"}\n"; + +static const char *kernelpattern_image_write_2Darray_half = +"__kernel void sample_test( __global half4 *source, write_only image2d_array_t dest )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" int tidZ = get_global_id(2);\n" +" int width = get_image_width( dest );\n" +" int height = get_image_height( dest );\n" +" int index = tidZ * width * height + tidY * width + tidX;\n" +" write_imagef( dest, (int4)( tidX, tidY, tidZ, 0 ), vload_half4(index, (__global half *)source));\n" +"}\n"; + +#ifdef GL_VERSION_3_2 + +static const char * kernelpattern_image_write_2D_depth = +"__kernel void sample_test( __global %s *source, write_only image2d_depth_t dest )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" uint index = tidY * get_image_width( dest ) + tidX;\n" +" float value = source[index];\n" +" write_imagef( dest, (int2)( tidX, tidY ), value);\n" +"}\n"; + +static const char * kernelpattern_image_write_2D_array_depth = +"__kernel void sample_test( __global %s *source, write_only image2d_array_depth_t dest )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" int tidZ = get_global_id(2);\n" +" int width = get_image_width( dest );\n" +" int height = get_image_height( dest );\n" +" int index = tidZ * width * height + tidY * width + tidX;\n" +" %s value = source[index];\n" +" write_image%s( dest, (int4)( tidX, tidY, tidZ, 0 ), %s(value));\n" +"}\n"; + + +#endif + +#pragma mark - +#pragma mark Utility functions + +static const char* get_appropriate_write_kernel(GLenum target, + ExplicitType type, cl_channel_order channel_order) +{ + switch (get_base_gl_target(target)) { + case GL_TEXTURE_1D: + + if (type == kHalf) + return kernelpattern_image_write_1D_half; + else + return kernelpattern_image_write_1D; + break; + case GL_TEXTURE_BUFFER: + if (type == kHalf) + return kernelpattern_image_write_1D_buffer_half; + else + return kernelpattern_image_write_1D_buffer; + break; + case GL_TEXTURE_1D_ARRAY: + if (type == kHalf) + return kernelpattern_image_write_1Darray_half; + else + return kernelpattern_image_write_1Darray; + break; + case GL_COLOR_ATTACHMENT0: + case GL_RENDERBUFFER: + case GL_TEXTURE_RECTANGLE_EXT: + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP: +#ifdef GL_VERSION_3_2 + if (channel_order == CL_DEPTH || channel_order == CL_DEPTH_STENCIL) + return kernelpattern_image_write_2D_depth; +#endif + if (type == kHalf) + return kernelpattern_image_write_2D_half; + else + return kernelpattern_image_write_2D; + break; + + case GL_TEXTURE_2D_ARRAY: +#ifdef GL_VERSION_3_2 + if (channel_order == CL_DEPTH || channel_order == CL_DEPTH_STENCIL) + return kernelpattern_image_write_2D_array_depth; +#endif + if (type == kHalf) + return kernelpattern_image_write_2Darray_half; + else + return kernelpattern_image_write_2Darray; + break; + + case GL_TEXTURE_3D: + if (type == kHalf) + return kernelpattern_image_write_3D_half; + else + return kernelpattern_image_write_3D; + break; + + default: + log_error("Unsupported GL tex target (%s) passed to write test: " + "%s (%s):%d", GetGLTargetName(target), __FUNCTION__, + __FILE__, __LINE__); + return NULL; + } +} + +void set_dimensions_by_target(GLenum target, size_t *dims, size_t sizes[3], + size_t width, size_t height, size_t depth) +{ + switch (get_base_gl_target(target)) { + case GL_TEXTURE_1D: + sizes[0] = width; + *dims = 1; + break; + + case GL_TEXTURE_BUFFER: + sizes[0] = width; + *dims = 1; + break; + + case GL_TEXTURE_1D_ARRAY: + sizes[0] = width; + sizes[1] = height; + *dims = 2; + break; + + case GL_COLOR_ATTACHMENT0: + case GL_RENDERBUFFER: + case GL_TEXTURE_RECTANGLE_EXT: + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP: + + sizes[0] = width; + sizes[1] = height; + *dims = 2; + break; + + case GL_TEXTURE_2D_ARRAY: + sizes[0] = width; + sizes[1] = height; + sizes[2] = depth; + *dims = 3; + break; + + case GL_TEXTURE_3D: + sizes[0] = width; + sizes[1] = height; + sizes[2] = depth; + *dims = 3; + break; + + default: + log_error("Unsupported GL tex target (%s) passed to write test: " + "%s (%s):%d", GetGLTargetName(target), __FUNCTION__, + __FILE__, __LINE__); + } +} + +int test_cl_image_write( cl_context context, cl_command_queue queue, + GLenum target, cl_mem clImage, size_t width, size_t height, size_t depth, + cl_image_format *outFormat, ExplicitType *outType, void **outSourceBuffer, + MTdata d, bool supports_half ) +{ + size_t global_dims, global_sizes[3]; + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper inStream; + char* programPtr; + int error; + char kernelSource[2048]; + + // What CL format did we get from the texture? + + error = clGetImageInfo(clImage, CL_IMAGE_FORMAT, sizeof(cl_image_format), + outFormat, NULL); + test_error(error, "Unable to get the CL image format"); + + // Create the kernel source. The target and the data type will influence + // which particular kernel we choose. + + *outType = get_write_kernel_type( outFormat ); + size_t channelSize = get_explicit_type_size(*outType); + + const char* appropriateKernel = get_appropriate_write_kernel(target, + *outType, outFormat->image_channel_order); + if (*outType == kHalf && !supports_half) { + log_info("cl_khr_fp16 isn't supported. Skip this test.\n"); + return 0; + } + + const char* suffix = get_kernel_suffix( outFormat ); + const char* convert = get_write_conversion( outFormat, *outType ); + + sprintf(kernelSource, appropriateKernel, get_explicit_type_name( *outType ), + get_explicit_type_name( *outType ), suffix, convert); + + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, + (const char **)&programPtr, "sample_test" ) ) + { + return -1; + } + + // Create an appropriately-sized output buffer. + + // Check to see if the output buffer will fit on the device + size_t bytes = channelSize * 4 * width * height * depth; + cl_ulong alloc_size = 0; + + cl_device_id device = NULL; + error = clGetCommandQueueInfo(queue, CL_QUEUE_DEVICE, sizeof(device), &device, NULL); + test_error( error, "Unable to query command queue for device" ); + + error = clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(alloc_size), &alloc_size, NULL); + test_error( error, "Unable to device for max mem alloc size" ); + + if (bytes > alloc_size) { + log_info(" Skipping: Buffer size (%lu) is greater than CL_DEVICE_MAX_MEM_ALLOC_SIZE (%lu)\n", bytes, alloc_size); + *outSourceBuffer = NULL; + return 0; + } + + *outSourceBuffer = CreateRandomData(*outType, width * height * depth * 4, d); + + inStream = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, + channelSize * 4 * width * height * depth, *outSourceBuffer, &error ); + test_error( error, "Unable to create output buffer" ); + + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_NONE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + clSamplerWrapper sampler = clCreateSamplerWithProperties( context, properties, &error ); + test_error( error, "Unable to create sampler" ); + + error = clSetKernelArg( kernel, 0, sizeof( inStream ), &inStream ); + test_error( error, "Unable to set kernel arguments" ); + + error = clSetKernelArg( kernel, 1, sizeof( clImage ), &clImage ); + test_error( error, "Unable to set kernel arguments" ); + + // Flush and Acquire. + + glFinish(); + + error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &clImage, 0, NULL, NULL); + test_error( error, "Unable to acquire GL obejcts"); + + // Execute ( letting OpenCL choose the local size ) + + // Setup the global dimensions and sizes based on the target type. + set_dimensions_by_target(target, &global_dims, global_sizes, + width, height, depth); + + error = clEnqueueNDRangeKernel( queue, kernel, global_dims, NULL, + global_sizes, NULL, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + clEventWrapper event; + error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &clImage, 0, NULL, &event ); + test_error(error, "clEnqueueReleaseGLObjects failed"); + + error = clWaitForEvents( 1, &event ); + test_error(error, "clWaitForEvents failed"); + + return 0; +} + +static int test_image_write( cl_context context, cl_command_queue queue, + GLenum glTarget, GLuint glTexture, size_t width, size_t height, size_t depth, + cl_image_format *outFormat, ExplicitType *outType, void **outSourceBuffer, + MTdata d, bool supports_half ) +{ + int error; + + // Create a CL image from the supplied GL texture + clMemWrapper image = (*clCreateFromGLTexture_ptr)( context, CL_MEM_WRITE_ONLY, + glTarget, 0, glTexture, &error ); + + if ( error != CL_SUCCESS ) { + print_error( error, "Unable to create CL image from GL texture" ); + GLint fmt; + glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt ); + log_error( " Supplied GL texture was base format %s and internal " + "format %s\n", GetGLBaseFormatName( fmt ), GetGLFormatName( fmt ) ); + return error; + } + + return test_cl_image_write( context, queue, glTarget, image, + width, height, depth, outFormat, outType, outSourceBuffer, d, supports_half ); +} + +int supportsHalf(cl_context context, bool* supports_half) +{ + int error; + size_t size; + cl_uint numDev; + + error = clGetContextInfo(context, CL_CONTEXT_NUM_DEVICES, sizeof(cl_uint), &numDev, NULL); + test_error(error, "clGetContextInfo for CL_CONTEXT_NUM_DEVICES failed"); + + cl_device_id* devices = new cl_device_id[numDev]; + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, numDev * sizeof(cl_device_id), devices, NULL); + test_error(error, "clGetContextInfo for CL_CONTEXT_DEVICES failed"); + + // Get the extensions string for the device + error = clGetDeviceInfo(devices[0], CL_DEVICE_EXTENSIONS, 0, NULL, &size); + test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS size failed"); + + char *extensions = new char[size+1]; + if (extensions == 0) { + log_error("Failed to allocate memory for extensions string.\n"); + return -1; + } + memset( extensions, CHAR_MIN, sizeof(char)*(size+1) ); + + error = clGetDeviceInfo(devices[0], CL_DEVICE_EXTENSIONS, sizeof(char)*size, extensions, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS failed"); + + *supports_half = strstr(extensions, "cl_khr_fp16"); + delete [] extensions; + delete [] devices; + + return error; +} + +int supportsMsaa(cl_context context, bool* supports_msaa) +{ + int error; + size_t size; + cl_uint numDev; + + error = clGetContextInfo(context, CL_CONTEXT_NUM_DEVICES, sizeof(cl_uint), &numDev, NULL); + test_error(error, "clGetContextInfo for CL_CONTEXT_NUM_DEVICES failed"); + + cl_device_id* devices = new cl_device_id[numDev]; + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, numDev * sizeof(cl_device_id), devices, NULL); + test_error(error, "clGetContextInfo for CL_CONTEXT_DEVICES failed"); + + // Get the extensions string for the device + error = clGetDeviceInfo(devices[0], CL_DEVICE_EXTENSIONS, 0, NULL, &size); + test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS size failed"); + + char *extensions = new char[size+1]; + if (extensions == 0) { + log_error("Failed to allocate memory for extensions string.\n"); + return -1; + } + memset( extensions, CHAR_MIN, sizeof(char)*(size+1) ); + + error = clGetDeviceInfo(devices[0], CL_DEVICE_EXTENSIONS, sizeof(char)*size, extensions, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS failed"); + + *supports_msaa = strstr(extensions, "cl_khr_gl_msaa_sharing"); + delete [] extensions; + delete [] devices; + + return error; +} + +int supportsDepth(cl_context context, bool* supports_depth) +{ + int error; + size_t size; + cl_uint numDev; + + error = clGetContextInfo(context, CL_CONTEXT_NUM_DEVICES, sizeof(cl_uint), &numDev, NULL); + test_error(error, "clGetContextInfo for CL_CONTEXT_NUM_DEVICES failed"); + + cl_device_id* devices = new cl_device_id[numDev]; + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, numDev * sizeof(cl_device_id), devices, NULL); + test_error(error, "clGetContextInfo for CL_CONTEXT_DEVICES failed"); + + // Get the extensions string for the device + error = clGetDeviceInfo(devices[0], CL_DEVICE_EXTENSIONS, 0, NULL, &size); + test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS size failed"); + + char *extensions = new char[size+1]; + if (extensions == 0) { + log_error("Failed to allocate memory for extensions string.\n"); + return -1; + } + memset( extensions, CHAR_MIN, sizeof(char)*(size+1) ); + + error = clGetDeviceInfo(devices[0], CL_DEVICE_EXTENSIONS, sizeof(char)*size, extensions, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS failed"); + + *supports_depth = strstr(extensions, "cl_khr_gl_depth_images"); + delete [] extensions; + delete [] devices; + + return error; +} + +static int test_image_format_write( cl_context context, cl_command_queue queue, + size_t width, size_t height, size_t depth, GLenum target, GLenum format, + GLenum internalFormat, GLenum glType, ExplicitType type, MTdata d ) +{ + int error; + int samples = 8; + // If we're testing a half float format, then we need to determine the + // rounding mode of this machine. Punt if we fail to do so. + + if( type == kHalf ) + if( DetectFloatToHalfRoundingMode(queue) ) + return 1; + + // Create an appropriate GL texture or renderbuffer, given the target. + + glTextureWrapper glTexture; + glBufferWrapper glBuf; + glFramebufferWrapper glFramebuffer; + glRenderbufferWrapper glRenderbuffer; + switch (get_base_gl_target(target)) { + case GL_TEXTURE_1D: + CreateGLTexture1D( width, target, format, internalFormat, glType, + type, &glTexture, &error, false, d ); + break; + case GL_TEXTURE_BUFFER: + CreateGLTextureBuffer( width, target, format, internalFormat, glType, + type, &glTexture, &glBuf, &error, false, d ); + break; + case GL_TEXTURE_1D_ARRAY: + CreateGLTexture1DArray( width, height, target, format, internalFormat, + glType, type, &glTexture, &error, false, d ); + break; + case GL_TEXTURE_RECTANGLE_EXT: + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP: + CreateGLTexture2D( width, height, target, format, internalFormat, glType, + type, &glTexture, &error, false, d ); + break; + case GL_COLOR_ATTACHMENT0: + case GL_RENDERBUFFER: + CreateGLRenderbuffer(width, height, target, format, internalFormat, + glType, type, &glFramebuffer, &glRenderbuffer, &error, d, false); + case GL_TEXTURE_2D_ARRAY: + CreateGLTexture2DArray( width, height, depth, target, format, + internalFormat, glType, type, &glTexture, &error, false, d ); + break; + case GL_TEXTURE_3D: + CreateGLTexture3D( width, height, depth, target, format, + internalFormat, glType, type, &glTexture, &error, d, false ); + break; + + default: + log_error("Unsupported GL tex target (%s) passed to write test: " + "%s (%s):%d", GetGLTargetName(target), __FUNCTION__, + __FILE__, __LINE__); + } + + // If there was a problem during creation, make sure it isn't a known + // cause, and then complain. + if ( error == -2 ) { + log_info("OpenGL texture couldn't be created, because a texture is too big. Skipping test.\n"); + return 0; + } + + if ( error != 0 ) { + if ((format == GL_RGBA_INTEGER_EXT) && (!CheckGLIntegerExtensionSupport())){ + log_info("OpenGL version does not support GL_RGBA_INTEGER_EXT. " + "Skipping test.\n"); + return 0; + } else { + return error; + } + } + + // Run and get the results + cl_image_format clFormat; + ExplicitType sourceType; + ExplicitType validationType; + void *outSourceBuffer = NULL; + + GLenum globj = glTexture; + if (target == GL_RENDERBUFFER || target == GL_COLOR_ATTACHMENT0) { + globj = glRenderbuffer; + } + + bool supports_half = false; + error = supportsHalf(context, &supports_half); + if( error != 0 ) + return error; + + error = test_image_write( context, queue, target, globj, width, height, + depth, &clFormat, &sourceType, (void **)&outSourceBuffer, d, supports_half ); + + if( error != 0 || ((sourceType == kHalf ) && !supports_half)) { + if (outSourceBuffer) + free(outSourceBuffer); + return error; + } + + if (!outSourceBuffer) + return 0; + + // If actual source type was half, convert to float for validation. + + if ( sourceType == kHalf ) + validationType = kFloat; + else + validationType = sourceType; + + BufferOwningPtr validationSource; + + if ( clFormat.image_channel_data_type == CL_UNORM_INT_101010 ) + { + validationSource.reset( outSourceBuffer ); + } + else + { + validationSource.reset( convert_to_expected( outSourceBuffer, + width * height * depth, sourceType, validationType, get_channel_order_channel_count(clFormat.image_channel_order) ) ); + free(outSourceBuffer); + } + + log_info( "- Write for %s [%4ld x %4ld x %4ld] : GL Texture : %s : %s : %s =>" + " CL Image : %s : %s \n", + GetGLTargetName(target), + width, height, depth, + GetGLFormatName( format ), + GetGLFormatName( internalFormat ), + GetGLTypeName( glType), + GetChannelOrderName( clFormat.image_channel_order ), + GetChannelTypeName( clFormat.image_channel_data_type )); + + // Read the results from the GL texture. + + ExplicitType readType = type; + BufferOwningPtr glResults( ReadGLTexture( + target, glTexture, glBuf, width, format, + internalFormat, glType, readType, /* unused */ 1, 1 ) ); + if( glResults == NULL ) + return -1; + + // We have to convert our input buffer to the returned type, so we can validate. + BufferOwningPtr convertedGLResults; + if ( clFormat.image_channel_data_type != CL_UNORM_INT_101010 ) + { + convertedGLResults.reset( convert_to_expected( + glResults, width * height * depth, readType, validationType, get_channel_order_channel_count(clFormat.image_channel_order), glType )); + } + + // Validate. + + int valid = 0; + if (convertedGLResults) { + if( sourceType == kFloat || sourceType == kHalf ) + { + if ( clFormat.image_channel_data_type == CL_UNORM_INT_101010 ) + { + valid = validate_float_results_rgb_101010( validationSource, glResults, width, height, depth, 1 ); + } + else + { + valid = validate_float_results( validationSource, convertedGLResults, + width, height, depth, 1, get_channel_order_channel_count(clFormat.image_channel_order) ); + } + } + else + { + valid = validate_integer_results( validationSource, convertedGLResults, + width, height, depth, 1, get_explicit_type_size( readType ) ); + } + } + + return valid; +} + +#pragma mark - +#pragma mark Write test common entry point + +// This is the main loop for all of the write tests. It iterates over the +// given formats & targets, testing a variety of sizes against each +// combination. + +int test_images_write_common(cl_device_id device, cl_context context, + cl_command_queue queue, struct format* formats, size_t nformats, + GLenum *targets, size_t ntargets, sizevec_t* sizes, size_t nsizes ) +{ + int err = 0; + int error = 0; + RandomSeed seed(gRandomSeed); + + // First, ensure this device supports images. + + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + // Get the value of CL_DEVICE_MAX_MEM_ALLOC_SIZE + cl_ulong max_individual_allocation_size = 0; + err = clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, + sizeof(max_individual_allocation_size), + &max_individual_allocation_size, NULL); + if (err) { + log_error("ERROR: clGetDeviceInfo failed for CL_DEVICE_MAX_MEM_ALLOC_SIZE.\n"); + error++; + return error; + } + + size_t total_allocation_size; + size_t fidx, tidx, sidx; + + for ( fidx = 0; fidx < nformats; fidx++ ) { + for ( tidx = 0; tidx < ntargets; tidx++ ) { + + // Texture buffer only takes an internal format, so the level data passed + // by the test and used for verification must match the internal format + if ((targets[tidx] == GL_TEXTURE_BUFFER) && (GetGLFormat(formats[ fidx ].internal) != formats[fidx].formattype)) + continue; + + if ( formats[ fidx ].datatype == GL_UNSIGNED_INT_2_10_10_10_REV ) + { + // Check if the RGB 101010 format is supported + if ( is_rgb_101010_supported( context, targets[ tidx ] ) == 0 ) + continue; // skip + } + + if (formats[ fidx ].datatype == GL_UNSIGNED_INT_24_8) + { + //check if a implementation supports writing to the depth stencil formats + cl_image_format imageFormat = { CL_DEPTH_STENCIL, CL_UNORM_INT24 }; + if (!is_image_format_supported(context, CL_MEM_WRITE_ONLY, (targets[tidx] == GL_TEXTURE_2D || targets[tidx] == GL_TEXTURE_RECTANGLE) ? CL_MEM_OBJECT_IMAGE2D: CL_MEM_OBJECT_IMAGE2D_ARRAY, &imageFormat)) + continue; + } + + if (formats[ fidx ].datatype == GL_FLOAT_32_UNSIGNED_INT_24_8_REV) + { + //check if a implementation supports writing to the depth stencil formats + cl_image_format imageFormat = { CL_DEPTH_STENCIL, CL_FLOAT}; + if (!is_image_format_supported(context, CL_MEM_WRITE_ONLY, (targets[tidx] == GL_TEXTURE_2D || targets[tidx] == GL_TEXTURE_RECTANGLE) ? CL_MEM_OBJECT_IMAGE2D: CL_MEM_OBJECT_IMAGE2D_ARRAY, &imageFormat)) + continue; + } + + if (targets[tidx] != GL_TEXTURE_BUFFER) + log_info( "Testing image write for GL format %s : %s : %s : %s\n", + GetGLTargetName( targets[ tidx ] ), + GetGLFormatName( formats[ fidx ].internal ), + GetGLBaseFormatName( formats[ fidx ].formattype ), + GetGLTypeName( formats[ fidx ].datatype ) ); + else + log_info( "Testing image write for GL format %s : %s\n", + GetGLTargetName( targets[ tidx ] ), + GetGLFormatName( formats[ fidx ].internal )); + + + for (sidx = 0; sidx < nsizes; sidx++) { + + // All tested formats are 4-channel formats + total_allocation_size = + sizes[sidx].width * sizes[sidx].height * sizes[sidx].depth * + 4 * get_explicit_type_size( formats[ fidx ].type ); + + if (total_allocation_size > max_individual_allocation_size) { + log_info( "The requested allocation size (%gMB) is larger than the " + "maximum individual allocation size (%gMB)\n", + total_allocation_size/(1024.0*1024.0), + max_individual_allocation_size/(1024.0*1024.0)); + log_info( "Skipping write test for %s : %s : %s : %s " + " and size (%ld, %ld, %ld)\n", + GetGLTargetName( targets[ tidx ] ), + GetGLFormatName( formats[ fidx ].internal ), + GetGLBaseFormatName( formats[ fidx ].formattype ), + GetGLTypeName( formats[ fidx ].datatype ), + sizes[sidx].width, + sizes[sidx].height, + sizes[sidx].depth); + continue; + } +#ifdef GL_VERSION_3_2 + if (get_base_gl_target(targets[ tidx ]) == GL_TEXTURE_2D_MULTISAMPLE || + get_base_gl_target(targets[ tidx ]) == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) + { + bool supports_msaa; + error = supportsMsaa(context, &supports_msaa); + if( error != 0 ) return error; + if (!supports_msaa) return 0; + } + if (formats[ fidx ].formattype == GL_DEPTH_COMPONENT || + formats[ fidx ].formattype == GL_DEPTH_STENCIL) + { + bool supports_depth; + error = supportsDepth(context, &supports_depth); + if( error != 0 ) return error; + if (!supports_depth) return 0; + } +#endif + + if( test_image_format_write( context, queue, + sizes[sidx].width, + sizes[sidx].height, + sizes[sidx].depth, + targets[ tidx ], + formats[ fidx ].formattype, + formats[ fidx ].internal, + formats[ fidx ].datatype, + formats[ fidx ].type, seed ) ) + { + log_error( "ERROR: Image write test failed for %s : %s : %s : %s " + " and size (%ld, %ld, %ld)\n\n", + GetGLTargetName( targets[ tidx ] ), + GetGLFormatName( formats[ fidx ].internal ), + GetGLBaseFormatName( formats[ fidx ].formattype ), + GetGLTypeName( formats[ fidx ].datatype ), + sizes[sidx].width, + sizes[sidx].height, + sizes[sidx].depth); + + error++; + break; // Skip other sizes for this combination + } + } + + // If we passed all sizes (check versus size loop count): + + if (sidx == nsizes) { + log_info( "passed: Image write for GL format %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tidx ] ), + GetGLFormatName( formats[ fidx ].internal ), + GetGLBaseFormatName( formats[ fidx ].formattype ), + GetGLTypeName( formats[ fidx ].datatype ) ); + } + } + } + + return error; +} diff --git a/test_conformance/gl/test_renderbuffer.cpp b/test_conformance/gl/test_renderbuffer.cpp new file mode 100644 index 00000000..c7f6e702 --- /dev/null +++ b/test_conformance/gl/test_renderbuffer.cpp @@ -0,0 +1,479 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +#if defined( __APPLE__ ) + #include +#else + #include + #include +#endif + +#if defined (__linux__) +GLboolean +gluCheckExtension(const GLubyte *extension, const GLubyte *extensions) +{ + const GLubyte *start; + GLubyte *where, *terminator; + + /* Extension names should not have spaces. */ + where = (GLubyte *) strchr((const char*)extension, ' '); + if (where || *extension == '\0') + return 0; + /* It takes a bit of care to be fool-proof about parsing the + OpenGL extensions string. Don't be fooled by sub-strings, + etc. */ + start = extensions; + for (;;) { + where = (GLubyte *) strstr((const char *) start, (const char*) extension); + if (!where) + break; + terminator = where + strlen((const char*) extension); + if (where == start || *(where - 1) == ' ') + if (*terminator == ' ' || *terminator == '\0') + return 1; + start = terminator; + } + return 0; +} +#endif + + +extern "C" { extern cl_uint gRandomSeed; }; + +// This is defined in the write common code: +extern int test_cl_image_write( cl_context context, cl_command_queue queue, + GLenum target, cl_mem clImage, size_t width, size_t height, size_t depth, + cl_image_format *outFormat, ExplicitType *outType, void **outSourceBuffer, + MTdata d, bool supports_half ); + +extern int test_cl_image_read( cl_context context, cl_command_queue queue, + GLenum gl_target, cl_mem image, size_t width, size_t height, size_t depth, size_t sampleNum, + cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer ); + +extern int supportsHalf(cl_context context, bool* supports_half); + +static int test_attach_renderbuffer_read_image( cl_context context, cl_command_queue queue, GLenum glTarget, GLuint glRenderbuffer, + size_t imageWidth, size_t imageHeight, cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer ) +{ + int error; + + // Create a CL image from the supplied GL renderbuffer + cl_mem image = (*clCreateFromGLRenderbuffer_ptr)( context, CL_MEM_READ_ONLY, glRenderbuffer, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create CL image from GL renderbuffer" ); + return error; + } + + return test_cl_image_read( context, queue, glTarget, image, imageWidth, + imageHeight, 1, 1, outFormat, outType, outResultBuffer ); +} + +int test_renderbuffer_read_image( cl_context context, cl_command_queue queue, + GLsizei width, GLsizei height, GLenum attachment, + GLenum format, GLenum internalFormat, + GLenum glType, ExplicitType type, MTdata d ) +{ + int error; + + if( type == kHalf ) + if( DetectFloatToHalfRoundingMode(queue) ) + return 1; + + // Create the GL renderbuffer + glFramebufferWrapper glFramebuffer; + glRenderbufferWrapper glRenderbuffer; + void *tmp = CreateGLRenderbuffer( width, height, attachment, format, internalFormat, glType, type, &glFramebuffer, &glRenderbuffer, &error, d, true ); + BufferOwningPtr inputBuffer(tmp); + if( error != 0 ) + { + if ((format == GL_RGBA_INTEGER_EXT) && (!CheckGLIntegerExtensionSupport())) + { + log_info("OpenGL version does not support GL_RGBA_INTEGER_EXT. Skipping test.\n"); + return 0; + } + else + { + return error; + } + } + + // Run and get the results + cl_image_format clFormat; + ExplicitType actualType; + char *outBuffer; + error = test_attach_renderbuffer_read_image( context, queue, attachment, glRenderbuffer, width, height, &clFormat, &actualType, (void **)&outBuffer ); + if( error != 0 ) + return error; + BufferOwningPtr actualResults(outBuffer); + + log_info( "- Read [%4d x %4d] : GL renderbuffer : %s : %s : %s => CL Image : %s : %s \n", width, height, + GetGLFormatName( format ), GetGLFormatName( internalFormat ), GetGLTypeName( glType), + GetChannelOrderName( clFormat.image_channel_order ), GetChannelTypeName( clFormat.image_channel_data_type )); + +#ifdef DEBUG + log_info("- start read GL data -- \n"); + DumpGLBuffer(glType, width, height, actualResults); + log_info("- end read GL data -- \n"); +#endif + + // We have to convert our input buffer to the returned type, so we can validate. + BufferOwningPtr convertedInput(convert_to_expected( inputBuffer, width * height, type, actualType, get_channel_order_channel_count(clFormat.image_channel_order) )); + +#ifdef DEBUG + log_info("- start input data -- \n"); + DumpGLBuffer(GetGLTypeForExplicitType(actualType), width, height, convertedInput); + log_info("- end input data -- \n"); +#endif + +#ifdef DEBUG + log_info("- start converted data -- \n"); + DumpGLBuffer(GetGLTypeForExplicitType(actualType), width, height, actualResults); + log_info("- end converted data -- \n"); +#endif + + // Now we validate + int valid = 0; + if(convertedInput) { + if( actualType == kFloat ) + valid = validate_float_results( convertedInput, actualResults, width, height, 1, get_channel_order_channel_count(clFormat.image_channel_order) ); + else + valid = validate_integer_results( convertedInput, actualResults, width, height, 1, get_explicit_type_size( actualType ) ); + } + + return valid; +} + +int test_renderbuffer_read( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLenum attachments[] = { GL_COLOR_ATTACHMENT0_EXT }; + + struct { + GLenum internal; + GLenum format; + GLenum datatype; + ExplicitType type; + + } formats[] = { + { GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + +// Renderbuffers with integer formats do not seem to work reliably across +// platforms/implementations. Disabling this in version 1.0 of CL conformance tests. + +#ifdef TEST_INTEGER_FORMATS + + { GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar }, + { GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort }, + { GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt }, + { GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt }, +#endif + { GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat }, + { GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT, kHalf } + }; + + size_t fmtIdx, attIdx; + int error = 0; +#ifdef DEBUG + size_t iter = 1; +#else + size_t iter = 6; +#endif + RandomSeed seed( gRandomSeed ); + + // Check if images are supported + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + if( !gluCheckExtension( (const GLubyte *)"GL_EXT_framebuffer_object", glGetString( GL_EXTENSIONS ) ) ) + { + log_info( "Renderbuffers are not supported by this OpenGL implementation; skipping test\n" ); + return 0; + } + + // Loop through a set of GL formats, testing a set of sizes against each one + for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ ) + { + for( attIdx = 0; attIdx < sizeof( attachments ) / sizeof( attachments[ 0 ] ); attIdx++ ) + { + size_t i; + + log_info( "Testing renderbuffer read for %s : %s : %s : %s\n", + GetGLAttachmentName( attachments[ attIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + for( i = 0; i < iter; i++ ) + { + GLsizei width = random_in_range( 16, 512, seed ); + GLsizei height = random_in_range( 16, 512, seed ); +#ifdef DEBUG + width = height = 4; +#endif + + if( test_renderbuffer_read_image( context, queue, width, height, + attachments[ attIdx ], + formats[ fmtIdx ].format, + formats[ fmtIdx ].internal, + formats[ fmtIdx ].datatype, + formats[ fmtIdx ].type, seed ) ) + + { + log_error( "ERROR: Renderbuffer read test failed for %s : %s : %s : %s\n\n", + GetGLAttachmentName( attachments[ attIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + error++; + break; // Skip other sizes for this combination + } + } + if( i == iter ) + { + log_info( "passed: Renderbuffer read test passed for %s : %s : %s : %s\n\n", + GetGLAttachmentName( attachments[ attIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + } + } + } + + return error; +} + + +#pragma mark -------------------- Write tests ------------------------- + +int test_attach_renderbuffer_write_to_image( cl_context context, cl_command_queue queue, GLenum glTarget, GLuint glRenderbuffer, + size_t imageWidth, size_t imageHeight, cl_image_format *outFormat, ExplicitType *outType, MTdata d, void **outSourceBuffer, bool supports_half ) +{ + int error; + + // Create a CL image from the supplied GL renderbuffer + clMemWrapper image = (*clCreateFromGLRenderbuffer_ptr)( context, CL_MEM_WRITE_ONLY, glRenderbuffer, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create CL image from GL renderbuffer" ); + return error; + } + + return test_cl_image_write( context, queue, glTarget, image, imageWidth, + imageHeight, 1, outFormat, outType, outSourceBuffer, d, supports_half ); +} + +int test_renderbuffer_image_write( cl_context context, cl_command_queue queue, + GLsizei width, GLsizei height, GLenum attachment, + GLenum format, GLenum internalFormat, + GLenum glType, ExplicitType type, MTdata d ) +{ + int error; + + if( type == kHalf ) + if( DetectFloatToHalfRoundingMode(queue) ) + return 1; + + // Create the GL renderbuffer + glFramebufferWrapper glFramebuffer; + glRenderbufferWrapper glRenderbuffer; + CreateGLRenderbuffer( width, height, attachment, format, internalFormat, glType, type, &glFramebuffer, &glRenderbuffer, &error, d, false ); + if( error != 0 ) + { + if ((format == GL_RGBA_INTEGER_EXT) && (!CheckGLIntegerExtensionSupport())) + { + log_info("OpenGL version does not support GL_RGBA_INTEGER_EXT. Skipping test.\n"); + return 0; + } + else + { + return error; + } + } + + // Run and get the results + cl_image_format clFormat; + ExplicitType sourceType; + ExplicitType validationType; + void *outSourceBuffer; + + bool supports_half = false; + error = supportsHalf(context, &supports_half); + if( error != 0 ) + return error; + + error = test_attach_renderbuffer_write_to_image( context, queue, attachment, glRenderbuffer, width, height, &clFormat, &sourceType, d, (void **)&outSourceBuffer, supports_half ); + if( error != 0 || ((sourceType == kHalf ) && !supports_half)) + return error; + + // If actual source type was half, convert to float for validation. + if( sourceType == kHalf ) + validationType = kFloat; + else + validationType = sourceType; + + BufferOwningPtr validationSource( convert_to_expected( outSourceBuffer, width * height, sourceType, validationType, get_channel_order_channel_count(clFormat.image_channel_order) ) ); + + log_info( "- Write [%4d x %4d] : GL Renderbuffer : %s : %s : %s => CL Image : %s : %s \n", width, height, + GetGLFormatName( format ), GetGLFormatName( internalFormat ), GetGLTypeName( glType), + GetChannelOrderName( clFormat.image_channel_order ), GetChannelTypeName( clFormat.image_channel_data_type )); + + // Now read the results from the GL renderbuffer + BufferOwningPtr resultData( ReadGLRenderbuffer( glFramebuffer, glRenderbuffer, attachment, format, internalFormat, glType, type, width, height ) ); + +#ifdef DEBUG + log_info("- start result data -- \n"); + DumpGLBuffer(glType, width, height, resultData); + log_info("- end result data -- \n"); +#endif + + // We have to convert our input buffer to the returned type, so we can validate. + BufferOwningPtr convertedData( convert_to_expected( resultData, width * height, type, validationType, get_channel_order_channel_count(clFormat.image_channel_order) ) ); + +#ifdef DEBUG + log_info("- start input data -- \n"); + DumpGLBuffer(GetGLTypeForExplicitType(validationType), width, height, validationSource); + log_info("- end input data -- \n"); +#endif + +#ifdef DEBUG + log_info("- start converted data -- \n"); + DumpGLBuffer(GetGLTypeForExplicitType(validationType), width, height, convertedData); + log_info("- end converted data -- \n"); +#endif + + // Now we validate + int valid = 0; + if(convertedData) { + if( sourceType == kFloat || sourceType == kHalf ) + valid = validate_float_results( validationSource, convertedData, width, height, 1, get_channel_order_channel_count(clFormat.image_channel_order) ); + else + valid = validate_integer_results( validationSource, convertedData, width, height, 1, get_explicit_type_size( type ) ); + } + + return valid; +} + +int test_renderbuffer_write( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLenum attachments[] = { GL_COLOR_ATTACHMENT0_EXT }; + + struct { + GLenum internal; + GLenum format; + GLenum datatype; + ExplicitType type; + + } formats[] = { + { GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + +// Renderbuffers with integer formats do not seem to work reliably across +// platforms/implementations. Disabling this in version 1.0 of CL conformance tests. + +#ifdef TEST_INTEGER_FORMATS + + { GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar }, + { GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort }, + { GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt }, + { GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt }, +#endif + { GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat }, + { GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT, kHalf } + }; + + size_t fmtIdx, attIdx; + int error = 0; + size_t iter = 6; +#ifdef DEBUG + iter = 1; +#endif + RandomSeed seed( gRandomSeed ); + + // Check if images are supported + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + if( !gluCheckExtension( (const GLubyte *)"GL_EXT_framebuffer_object", glGetString( GL_EXTENSIONS ) ) ) + { + log_info( "Renderbuffers are not supported by this OpenGL implementation; skipping test\n" ); + return 0; + } + + // Loop through a set of GL formats, testing a set of sizes against each one + for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ ) + { + for( attIdx = 0; attIdx < sizeof( attachments ) / sizeof( attachments[ 0 ] ); attIdx++ ) + { + log_info( "Testing Renderbuffer write test for %s : %s : %s : %s\n", + GetGLAttachmentName( attachments[ attIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + size_t i; + for( i = 0; i < iter; i++ ) + { + GLsizei width = random_in_range( 16, 512, seed ); + GLsizei height = random_in_range( 16, 512, seed ); +#ifdef DEBUG + width = height = 4; +#endif + + if( test_renderbuffer_image_write( context, queue, width, height, + attachments[ attIdx ], + formats[ fmtIdx ].format, + formats[ fmtIdx ].internal, + formats[ fmtIdx ].datatype, + formats[ fmtIdx ].type, seed ) ) + { + log_error( "ERROR: Renderbuffer write test failed for %s : %s : %s : %s\n\n", + GetGLAttachmentName( attachments[ attIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + error++; + break; // Skip other sizes for this combination + } + } + if( i == iter ) + { + log_info( "passed: Renderbuffer write test passed for %s : %s : %s : %s\n\n", + GetGLAttachmentName( attachments[ attIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + } + } + } + + return error; +} diff --git a/test_conformance/gl/test_renderbuffer_info.cpp b/test_conformance/gl/test_renderbuffer_info.cpp new file mode 100644 index 00000000..61a8adfa --- /dev/null +++ b/test_conformance/gl/test_renderbuffer_info.cpp @@ -0,0 +1,133 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#if defined( __APPLE__ ) +#include +#else +#include +#include +#endif + +extern "C" {extern cl_uint gRandomSeed;}; + +static int test_renderbuffer_object_info( cl_context context, cl_command_queue queue, + GLsizei width, GLsizei height, GLenum attachment, + GLenum format, GLenum internalFormat, + GLenum glType, ExplicitType type, MTdata d ) +{ + int error; + + if( type == kHalf ) + if( DetectFloatToHalfRoundingMode(queue) ) + return 1; + + // Create the GL render buffer + glFramebufferWrapper glFramebuffer; + glRenderbufferWrapper glRenderbuffer; + BufferOwningPtr inputBuffer(CreateGLRenderbuffer( width, height, attachment, format, internalFormat, glType, type, &glFramebuffer, &glRenderbuffer, &error, d, true )); + if( error != 0 ) + return error; + + clMemWrapper image = (*clCreateFromGLRenderbuffer_ptr)(context, CL_MEM_READ_ONLY, glRenderbuffer, &error); + test_error(error, "clCreateFromGLRenderbuffer failed"); + + log_info( "- Given a GL format of %s, input type was %s, size was %d x %d\n", + GetGLFormatName( internalFormat ), + get_explicit_type_name( type ), (int)width, (int)height ); + + // Verify the expected information here. + return CheckGLObjectInfo(image, CL_GL_OBJECT_RENDERBUFFER, (GLuint)glRenderbuffer, internalFormat, 0); +} + +int test_renderbuffer_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLenum attachments[] = { GL_COLOR_ATTACHMENT0_EXT }; + + struct { + GLenum internal; + GLenum format; + GLenum datatype; + ExplicitType type; + + } formats[] = { + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat }, + { GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT, kHalf } + }; + + size_t fmtIdx, tgtIdx; + int error = 0; + size_t iter = 6; + RandomSeed seed(gRandomSeed); + + // Check if images are supported + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + if( !gluCheckExtension( (const GLubyte *)"GL_EXT_framebuffer_object", glGetString( GL_EXTENSIONS ) ) ) + { + log_info( "Renderbuffers are not supported by this OpenGL implementation; skipping test\n" ); + return 0; + } + + // Loop through a set of GL formats, testing a set of sizes against each one + for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ ) + { + for( tgtIdx = 0; tgtIdx < sizeof( attachments ) / sizeof( attachments[ 0 ] ); tgtIdx++ ) + { + log_info( "Testing Renderbuffer object info for %s : %s : %s\n", + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + size_t i; + for( i = 0; i < iter; i++ ) + { + GLsizei width = random_in_range( 16, 512, seed ); + GLsizei height = random_in_range( 16, 512, seed ); + + if( test_renderbuffer_object_info( context, queue, (int)width, (int)height, + attachments[ tgtIdx ], + formats[ fmtIdx ].format, + formats[ fmtIdx ].internal, + formats[ fmtIdx ].datatype, + formats[ fmtIdx ].type, seed ) ) + { + log_error( "ERROR: Renderbuffer write test failed for GL format %s : %s\n\n", + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + error++; + break; // Skip other sizes for this combination + } + } + if( i == iter ) + { + log_info( "passed: Renderbuffer write test passed for GL format %s : %s\n\n", + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + } + } + } + + return error; +} + diff --git a/test_conformance/gles/CMakeLists.txt b/test_conformance/gles/CMakeLists.txt new file mode 100644 index 00000000..e64b58e8 --- /dev/null +++ b/test_conformance/gles/CMakeLists.txt @@ -0,0 +1,34 @@ +set (MODULE_NAME GLES) + +set (${MODULE_NAME}_SOURCES + main.cpp + test_buffers.cpp + test_images_2D.cpp + test_images_3D.cpp + test_renderbuffer.cpp + test_images_2D_info.cpp + test_images_3D_info.cpp + test_renderbuffer_info.cpp + test_fence_sync.cpp + helpers.cpp + setup_egl.cpp + ../../test_common/gles/helpers.cpp + ../../test_common/harness/genericThread.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp + ) + +if(ANDROID) + list(APPEND CLConform_LIBRARIES GLESv2) +elseif(WIN32) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGLES3") + list(APPEND CLConform_LIBRARIES libEGL libGLESv2 ) +endif(ANDROID) + +include(../CMakeCommon.txt) diff --git a/test_conformance/gles/helpers.cpp b/test_conformance/gles/helpers.cpp new file mode 100644 index 00000000..dfff21f5 --- /dev/null +++ b/test_conformance/gles/helpers.cpp @@ -0,0 +1,481 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +#include "gl_headers.h" + +const char *get_kernel_suffix( cl_image_format *format ) +{ + switch( format->image_channel_data_type ) + { + case CL_UNORM_INT8: + case CL_UNORM_INT16: + case CL_SNORM_INT8: + case CL_SNORM_INT16: + case CL_FLOAT: + return "f"; + case CL_HALF_FLOAT: + return "h"; + case CL_SIGNED_INT8: + case CL_SIGNED_INT16: + case CL_SIGNED_INT32: + return "i"; + case CL_UNSIGNED_INT8: + case CL_UNSIGNED_INT16: + case CL_UNSIGNED_INT32: + return "ui"; + default: + return ""; + } +} + +ExplicitType get_read_kernel_type( cl_image_format *format ) +{ + switch( format->image_channel_data_type ) + { + case CL_UNORM_INT8: + case CL_UNORM_INT16: + case CL_SNORM_INT8: + case CL_SNORM_INT16: + case CL_FLOAT: + return kFloat; + case CL_HALF_FLOAT: + return kHalf; + case CL_SIGNED_INT8: + case CL_SIGNED_INT16: + case CL_SIGNED_INT32: + return kInt; + case CL_UNSIGNED_INT8: + case CL_UNSIGNED_INT16: + case CL_UNSIGNED_INT32: + return kUInt; + default: + return kInt; + } +} + +ExplicitType get_write_kernel_type( cl_image_format *format ) +{ + switch( format->image_channel_data_type ) + { + case CL_UNORM_INT8: + return kFloat; + case CL_UNORM_INT16: + return kFloat; + case CL_SNORM_INT8: + return kFloat; + case CL_SNORM_INT16: + return kFloat; + case CL_HALF_FLOAT: + return kHalf; + case CL_FLOAT: + return kFloat; + case CL_SIGNED_INT8: + return kChar; + case CL_SIGNED_INT16: + return kShort; + case CL_SIGNED_INT32: + return kInt; + case CL_UNSIGNED_INT8: + return kUChar; + case CL_UNSIGNED_INT16: + return kUShort; + case CL_UNSIGNED_INT32: + return kUInt; + default: + return kInt; + } +} + +const char* get_write_conversion( cl_image_format *format, ExplicitType type ) +{ + switch( format->image_channel_data_type ) + { + case CL_UNORM_INT8: + case CL_UNORM_INT16: + case CL_SNORM_INT8: + case CL_SNORM_INT16: + case CL_FLOAT: + if(type != kFloat) return "convert_float4"; + break; + case CL_HALF_FLOAT: + break; + case CL_SIGNED_INT8: + case CL_SIGNED_INT16: + case CL_SIGNED_INT32: + if(type != kInt) return "convert_int4"; + break; + case CL_UNSIGNED_INT8: + case CL_UNSIGNED_INT16: + case CL_UNSIGNED_INT32: + if(type != kUInt) return "convert_uint4"; + break; + default: + return ""; + } + return ""; +} + +// The only three input types to this function are kInt, kUInt and kFloat, due to the way we set up our tests +// The output types, though, are pretty much anything valid for GL to receive + +#define DOWNSCALE_INTEGER_CASE( enum, type, bitShift ) \ + case enum: \ + { \ + cl_##type *dst = new cl_##type[ numPixels * 4 ]; \ + for( size_t i = 0; i < numPixels * 4; i++ ) \ + dst[ i ] = src[ i ]; \ + return (char *)dst; \ + } + +#define UPSCALE_FLOAT_CASE( enum, type, typeMax ) \ + case enum: \ + { \ + cl_##type *dst = new cl_##type[ numPixels * 4 ]; \ + for( size_t i = 0; i < numPixels * 4; i++ ) \ + dst[ i ] = (cl_##type)( src[ i ] * typeMax ); \ + return (char *)dst; \ + } + +char * convert_to_expected( void * inputBuffer, size_t numPixels, ExplicitType inType, ExplicitType outType ) +{ +#ifdef GLES_DEBUG + log_info( "- Converting from input type '%s' to output type '%s'\n", + get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); +#endif + + if( inType == outType ) + { + char *outData = new char[ numPixels * 4 * get_explicit_type_size(outType) ] ; // sizeof( cl_int ) ]; + memcpy( outData, inputBuffer, numPixels * 4 * get_explicit_type_size(inType) ); + return outData; + } + else if( inType == kChar ) + { + cl_char *src = (cl_char *)inputBuffer; + + switch( outType ) + { + case kInt: + { + cl_int *outData = new cl_int[ numPixels * 4 ]; + for( size_t i = 0; i < numPixels * 4; i++ ) + { + outData[ i ] = (cl_int)((src[ i ])); + } + return (char *)outData; + } + case kFloat: + { + // If we're converting to float, then CL decided that we should be normalized + cl_float *outData = new cl_float[ numPixels * 4 ]; + for( size_t i = 0; i < numPixels * 4; i++ ) + { + outData[ i ] = (cl_float)src[ i ] / 127.0f; + } + return (char *)outData; + } + default: + log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); + return NULL; + } + } + else if( inType == kUChar ) + { + cl_uchar *src = (cl_uchar *)inputBuffer; + + switch( outType ) + { + case kUInt: + { + cl_uint *outData = new cl_uint[ numPixels * 4 ]; + for( size_t i = 0; i < numPixels * 4; i++ ) + { + outData[ i ] = (cl_uint)((src[ i ])); + } + return (char *)outData; + } + case kFloat: + { + // If we're converting to float, then CL decided that we should be normalized + cl_float *outData = new cl_float[ numPixels * 4 ]; + for( size_t i = 0; i < numPixels * 4; i++ ) + { + outData[ i ] = (cl_float)(src[ i ]) / 256.0f; + } + return (char *)outData; + } + default: + log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); + return NULL; + } + } + else if( inType == kShort ) + { + cl_short *src = (cl_short *)inputBuffer; + + switch( outType ) + { + case kInt: + { + cl_int *outData = new cl_int[ numPixels * 4 ]; + for( size_t i = 0; i < numPixels * 4; i++ ) + { + outData[ i ] = (cl_int)((src[ i ])); + } + return (char *)outData; + } + case kFloat: + { + // If we're converting to float, then CL decided that we should be normalized + cl_float *outData = new cl_float[ numPixels * 4 ]; + for( size_t i = 0; i < numPixels * 4; i++ ) + { + outData[ i ] = (cl_float)src[ i ] / 32768.0f; + } + return (char *)outData; + } + default: + log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); + return NULL; + } + } + else if( inType == kUShort ) + { + cl_ushort *src = (cl_ushort *)inputBuffer; + + switch( outType ) + { + case kUInt: + { + cl_uint *outData = new cl_uint[ numPixels * 4 ]; + for( size_t i = 0; i < numPixels * 4; i++ ) + { + outData[ i ] = (cl_uint)((src[ i ])); + } + return (char *)outData; + } + case kFloat: + { + // If we're converting to float, then CL decided that we should be normalized + cl_float *outData = new cl_float[ numPixels * 4 ]; + for( size_t i = 0; i < numPixels * 4; i++ ) + { + outData[ i ] = (cl_float)(src[ i ]) / 65535.0f; + } + return (char *)outData; + } + default: + log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); + return NULL; + } + } + else if( inType == kInt ) + { + cl_int *src = (cl_int *)inputBuffer; + + switch( outType ) + { + DOWNSCALE_INTEGER_CASE( kShort, short, 16 ) + DOWNSCALE_INTEGER_CASE( kChar, char, 24 ) + case kFloat: + { + // If we're converting to float, then CL decided that we should be normalized + cl_float *outData = new cl_float[ numPixels * 4 ]; + for( size_t i = 0; i < numPixels * 4; i++ ) + { + outData[ i ] = (cl_float)fmaxf( (float)src[ i ] / 2147483647.f, -1.f ); + } + return (char *)outData; + } + default: + log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); + return NULL; + } + } + else if( inType == kUInt ) + { + cl_uint *src = (cl_uint *)inputBuffer; + + switch( outType ) + { + DOWNSCALE_INTEGER_CASE( kUShort, ushort, 16 ) + DOWNSCALE_INTEGER_CASE( kUChar, uchar, 24 ) + case kFloat: + { + // If we're converting to float, then CL decided that we should be normalized + cl_float *outData = new cl_float[ numPixels * 4 ]; + for( size_t i = 0; i < numPixels * 4; i++ ) + { + outData[ i ] = (cl_float)src[ i ] / 4294967295.f; + } + return (char *)outData; + } + default: + log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); + return NULL; + } + } + else + { + cl_float *src = (cl_float *)inputBuffer; + + switch( outType ) + { + UPSCALE_FLOAT_CASE( kChar, char, 127.f ) + UPSCALE_FLOAT_CASE( kUChar, uchar, 255.f ) + UPSCALE_FLOAT_CASE( kShort, short, 32767.f ) + UPSCALE_FLOAT_CASE( kUShort, ushort, 65535.f ) + UPSCALE_FLOAT_CASE( kInt, int, 2147483647.f ) + UPSCALE_FLOAT_CASE( kUInt, uint, 4294967295.f ) + default: + log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) ); + return NULL; + } + } + + return NULL; +} + +int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t typeSize ) +{ + return validate_integer_results( expectedResults, actualResults, width, height, 0, typeSize ); +} + +int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t typeSize ) +{ + char *expected = (char *)expectedResults; + char *actual = (char *)actualResults; + for( size_t z = 0; z < ( ( depth == 0 ) ? 1 : depth ); z++ ) + { + for( size_t y = 0; y < height; y++ ) + { + for( size_t x = 0; x < width; x++ ) + { + if( memcmp( expected, actual, typeSize * 4 ) != 0 ) + { + char scratch[ 1024 ]; + + if( depth == 0 ) + log_error( "ERROR: Data sample %d,%d did not validate!\n", (int)x, (int)y ); + else + log_error( "ERROR: Data sample %d,%d,%d did not validate!\n", (int)x, (int)y, (int)z ); + log_error( "\tExpected: %s\n", GetDataVectorString( expected, typeSize, 4, scratch ) ); + log_error( "\t Actual: %s\n", GetDataVectorString( actual, typeSize, 4, scratch ) ); + return -1; + } + expected += typeSize * 4; + actual += typeSize * 4; + } + } + } + + return 0; +} + +int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height ) +{ + return validate_float_results( expectedResults, actualResults, width, height, 0 ); +} + +int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth ) +{ + cl_float *expected = (cl_float *)expectedResults; + cl_float *actual = (cl_float *)actualResults; + for( size_t z = 0; z < ( ( depth == 0 ) ? 1 : depth ); z++ ) + { + for( size_t y = 0; y < height; y++ ) + { + for( size_t x = 0; x < width; x++ ) + { + float err = 0.f; + for( size_t i = 0; i < 4; i++ ) + { + float error = fabsf( expected[ i ] - actual[ i ] ); + if( error > err ) + err = error; + } + + if( err > 1.f / 127.f ) // Max expected range of error if we converted from an 8-bit integer to a normalized float + { + if( depth == 0 ) + log_error( "ERROR: Data sample %d,%d did not validate!\n", (int)x, (int)y ); + else + log_error( "ERROR: Data sample %d,%d,%d did not validate!\n", (int)x, (int)y, (int)z ); + log_error( "\tExpected: %f %f %f %f\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] ); + log_error( "\t : %a %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] ); + log_error( "\t Actual: %f %f %f %f\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] ); + log_error( "\t : %a %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] ); + return -1; + } + expected += 4; + actual += 4; + } + } + } + + return 0; +} + +int CheckGLObjectInfo(cl_mem mem, cl_gl_object_type expected_cl_gl_type, GLuint expected_gl_name, + GLenum expected_cl_gl_texture_target, GLint expected_cl_gl_mipmap_level) +{ + cl_gl_object_type object_type; + GLuint object_name; + GLenum texture_target; + GLint mipmap_level; + int error; + + error = (*clGetGLObjectInfo_ptr)(mem, &object_type, &object_name); + test_error( error, "clGetGLObjectInfo failed"); + if (object_type != expected_cl_gl_type) { + log_error("clGetGLObjectInfo did not return expected object type: expected %d, got %d.\n", expected_cl_gl_type, object_type); + return -1; + } + if (object_name != expected_gl_name) { + log_error("clGetGLObjectInfo did not return expected object name: expected %d, got %d.\n", expected_gl_name, object_name); + return -1; + } + + if (object_type == CL_GL_OBJECT_TEXTURE2D || object_type == CL_GL_OBJECT_TEXTURE3D) { + error = (*clGetGLTextureInfo_ptr)(mem, CL_GL_TEXTURE_TARGET, sizeof(texture_target), &texture_target, NULL); + test_error( error, "clGetGLTextureInfo for CL_GL_TEXTURE_TARGET failed"); + + if (texture_target != expected_cl_gl_texture_target) { + log_error("clGetGLTextureInfo did not return expected texture target: expected %d, got %d.\n", expected_cl_gl_texture_target, texture_target); + return -1; + } + + error = (*clGetGLTextureInfo_ptr)(mem, CL_GL_MIPMAP_LEVEL, sizeof(mipmap_level), &mipmap_level, NULL); + test_error( error, "clGetGLTextureInfo for CL_GL_MIPMAP_LEVEL failed"); + + if (mipmap_level != expected_cl_gl_mipmap_level) { + log_error("clGetGLTextureInfo did not return expected mipmap level: expected %d, got %d.\n", expected_cl_gl_mipmap_level, mipmap_level); + return -1; + } + } + return 0; +} + +bool CheckGLIntegerExtensionSupport() +{ + // Get the OpenGL version and supported extensions + const GLubyte *glVersion = glGetString(GL_VERSION); + const GLubyte *glExtensionList = glGetString(GL_EXTENSIONS); + + // Check if the OpenGL vrsion is 3.0 or grater or GL_EXT_texture_integer is supported + return (((glVersion[0] - '0') >= 3) || (strstr((const char*)glExtensionList, "GL_EXT_texture_integer"))); +} diff --git a/test_conformance/gles/main.cpp b/test_conformance/gles/main.cpp new file mode 100644 index 00000000..e7aeb938 --- /dev/null +++ b/test_conformance/gles/main.cpp @@ -0,0 +1,402 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include + +#if !defined(_WIN32) +#include +#endif + +#include +#include + +#if !defined (__APPLE__) +#include +#endif + +#include "procs.h" +#include "../../test_common/gles/setup.h" +#include "../../test_common/harness/testHarness.h" + +#if !defined(_WIN32) +#include +#endif + +static cl_context sCurrentContext = NULL; + + +#define TEST_FN_REDIRECT( fn ) redirect_##fn +#define TEST_FN_REDIRECTOR( fn ) \ +int redirect_##fn(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) \ +{ \ + int error; \ + clCommandQueueWrapper realQueue = clCreateCommandQueue( sCurrentContext, device, 0, &error ); \ + test_error( error, "Unable to create command queue" ); \ + return fn( device, sCurrentContext, realQueue, numElements ); \ +} + +TEST_FN_REDIRECTOR( test_buffers ) +TEST_FN_REDIRECTOR( test_buffers_getinfo ) +TEST_FN_REDIRECTOR( test_images_read ) +TEST_FN_REDIRECTOR( test_images_2D_getinfo ) +TEST_FN_REDIRECTOR( test_images_read_cube ) +TEST_FN_REDIRECTOR( test_images_cube_getinfo ) +TEST_FN_REDIRECTOR( test_images_read_3D ) +TEST_FN_REDIRECTOR( test_images_3D_getinfo ) +TEST_FN_REDIRECTOR( test_images_write ) +TEST_FN_REDIRECTOR( test_images_write_cube ) +TEST_FN_REDIRECTOR( test_renderbuffer_read ) +TEST_FN_REDIRECTOR( test_renderbuffer_write ) +TEST_FN_REDIRECTOR( test_renderbuffer_getinfo ) + +#ifndef GL_ES_VERSION_2_0 +TEST_FN_REDIRECTOR( test_fence_sync ) +#endif + +basefn basefn_list[] = { + TEST_FN_REDIRECT( test_buffers ), + TEST_FN_REDIRECT( test_buffers_getinfo ), + TEST_FN_REDIRECT( test_images_read ), + TEST_FN_REDIRECT( test_images_2D_getinfo ), + TEST_FN_REDIRECT( test_images_read_cube ), + TEST_FN_REDIRECT( test_images_cube_getinfo ), + TEST_FN_REDIRECT( test_images_read_3D ), + TEST_FN_REDIRECT( test_images_3D_getinfo ), + TEST_FN_REDIRECT( test_images_write ), + TEST_FN_REDIRECT( test_images_write_cube ), + TEST_FN_REDIRECT( test_renderbuffer_read ), + TEST_FN_REDIRECT( test_renderbuffer_write ), + TEST_FN_REDIRECT( test_renderbuffer_getinfo ) +}; + +#ifndef GL_ES_VERSION_2_0 +basefn basefn_list32[] = { + TEST_FN_REDIRECT( test_fence_sync ) +}; +#endif + +const char *basefn_names[] = { + "buffers", + "buffers_getinfo", + "images_read", + "images_2D_getinfo", + "images_read_cube", + "images_cube_getinfo", + "images_read_3D", + "images_3D_getinfo", + "images_write", + "images_write_cube", + "renderbuffer_read", + "renderbuffer_write", + "renderbuffer_getinfo", + "all" +}; + +const char *basefn_names32[] = { + "fence_sync", + "all" +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0]) - 1) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); +int num_fns32 = sizeof(basefn_names32) / sizeof(char *); + + +int main(int argc, const char *argv[]) +{ + int error = 0; + cl_platform_id platform_id = NULL; + /* To keep it simple, use a static allocation of 32 argv pointers. + argc is not expected to go beyond 32 */ + const char* argv_tmp[32] = {0}; + int argc_tmp = 0; + + test_start(); + + cl_device_type requestedDeviceType = CL_DEVICE_TYPE_DEFAULT; + + for(int z = 1; z < argc; ++z) + {//for + if(strcmp( argv[ z ], "-list" ) == 0 ) + { + log_info( "Available 2.x tests:\n" ); + for( int i = 0; i < num_fns - 1; i++ ) + log_info( "\t%s\n", basefn_names[ i ] ); + + log_info( "Available 3.2 tests:\n" ); + for( int i = 0; i < num_fns32 - 1; i++ ) + log_info( "\t%s\n", basefn_names32[ i ] ); + + log_info( "Note: Any 3.2 test names must follow 2.1 test names on the command line." ); + log_info( "Use environment variables to specify desired device." ); + + test_finish(); + return 0; + } + + /* support requested device type */ + if(!strcmp(argv[z], "CL_DEVICE_TYPE_GPU")) + { + printf("Requested device type is CL_DEVICE_TYPE_GPU\n"); + requestedDeviceType = CL_DEVICE_TYPE_GPU; + } + else + if(!strcmp(argv[z], "CL_DEVICE_TYPE_CPU")) + { + printf("Requested device type is CL_DEVICE_TYPE_CPU\n"); + log_info("Invalid CL device type. GL tests can only run on a GPU device.\n"); + test_finish(); + return 0; + } + }//for + + // Check to see if any 2.x or 3.2 test names were specified on the command line. + unsigned first_32_testname = 0; + + for (int j=1; (jSupportsCLGLInterop( requestedDeviceType ); + if( supported == 0 ) { + log_info("Test not run because GL-CL interop is not supported for any devices of the requested type.\n"); + test_finish(); + error = 0; + goto cleanup; + } else if ( supported == -1 ) { + log_error("Failed to determine if CL-GL interop is supported.\n"); + test_finish(); + error = -1; + goto cleanup; + } + + // OpenGL tests for non-3.2 //////////////////////////////////////////////////////// + if ((argc == 1) || (first_32_testname != 1)) { + + // At least one device supports CL-GL interop, so init the test. + if( glEnv->Init( &argc, (char **)argv, CL_FALSE ) ) { + log_error("Failed to initialize the GL environment for this test.\n"); + test_finish(); + error = -1; + goto cleanup; + } + + // Create a context to use and then grab a device (or devices) from it + sCurrentContext = glEnv->CreateCLContext(); + if( sCurrentContext == NULL ) + { + log_error( "ERROR: Unable to obtain CL context from GL\n" ); + test_finish(); + error = -1; + goto cleanup; + } + + size_t numDevices = 0; + cl_device_id deviceIDs[ 16 ]; + + error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, 0, NULL, &numDevices); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to get device count from context" ); + test_finish(); + error = -1; + goto cleanup; + } + numDevices /= sizeof(cl_device_id); + + if (numDevices < 1) { + log_error("No devices found.\n"); + test_finish(); + error = -1; + goto cleanup; + } + + error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, sizeof( deviceIDs ), deviceIDs, NULL); + if( error != CL_SUCCESS ) { + print_error( error, "Unable to get device list from context" ); + test_finish(); + error = -1; + goto cleanup; + } + + // Execute tests. + int argc_ = (first_32_testname) ? first_32_testname : argc; + + for( size_t i = 0; i < numDevices; i++ ) { + log_info( "\nTesting OpenGL 2.x\n" ); + if( printDeviceHeader( deviceIDs[ i ] ) != CL_SUCCESS ) { + test_finish(); + error = -1; + goto cleanup; + } + + error = clGetDeviceInfo(deviceIDs[ i ], + CL_DEVICE_PLATFORM, + sizeof(platform_id), + &platform_id, + NULL); + if(error) + { + goto cleanup; + } + + error = init_clgl_ext(platform_id); + if (error < 0) + { + goto cleanup; + } + + /* parseAndCallCommandLineTests considers every command line argument + as a test name. This results in the test failing because of considering + args such as 'CL_DEVICE_TYPE_GPU' as test names unless + the actual test name happens to be the first argument. + Instead of changing the behaviour of parseAndCallCommandLineTests + modify the arguments passed to it so as to not affect other tests. + */ + int w = 1; + argc_tmp= argc_; + for(int k = 1; k < argc; k++) + { + if( (strcmp(argv[k], "full") == 0) || + (strcmp(argv[k], "CL_DEVICE_TYPE_CPU") == 0) || + (strcmp(argv[k], "CL_DEVICE_TYPE_GPU") == 0)) + { + argc_tmp--; + continue; + } + else + { + argv_tmp[w++] = argv[k]; + } + } + + // Note: don't use the entire harness, because we have a different way of obtaining the device (via the context) + error = parseAndCallCommandLineTests( argc_tmp, argv_tmp, deviceIDs[ i ], num_fns, basefn_list, basefn_names, true, 0, 1024 ); + if( error != 0 ) + break; + } + + // Clean-up. + // We move this to a common cleanup step to make sure that things will be released properly before the test exit + goto cleanup; + // clReleaseContext( sCurrentContext ); + // delete glEnv; + } + + // OpenGL 3.2 tests. //////////////////////////////////////////////////////// + if ((argc==1) || first_32_testname) { + + // At least one device supports CL-GL interop, so init the test. + if( glEnv->Init( &argc, (char **)argv, CL_TRUE ) ) { + log_error("Failed to initialize the GL environment for this test.\n"); + test_finish(); + error = -1; + goto cleanup; + } + + // Create a context to use and then grab a device (or devices) from it + sCurrentContext = glEnv->CreateCLContext(); + if( sCurrentContext == NULL ) { + log_error( "ERROR: Unable to obtain CL context from GL\n" ); + test_finish(); + error = -1; + goto cleanup; + } + + size_t numDevices = 0; + cl_device_id deviceIDs[ 16 ]; + + error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, 0, NULL, &numDevices); + if( error != CL_SUCCESS ) { + print_error( error, "Unable to get device count from context" ); + test_finish(); + error = -1; + goto cleanup; + } + numDevices /= sizeof(cl_device_id); + + if (numDevices < 1) { + log_error("No devices found.\n"); + test_finish(); + error = -1; + goto cleanup; + } + + error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, sizeof( deviceIDs ), deviceIDs, NULL); + if( error != CL_SUCCESS ) { + print_error( error, "Unable to get device list from context" ); + test_finish(); + error = -1; + goto cleanup; + } + + int argc_ = (first_32_testname) ? 1 + (argc - first_32_testname) : argc; + const char** argv_ = (first_32_testname) ? &argv[first_32_testname-1] : argv; + + // Execute the tests. + for( size_t i = 0; i < numDevices; i++ ) { + log_info( "\nTesting OpenGL 3.2\n" ); + if( printDeviceHeader( deviceIDs[ i ] ) != CL_SUCCESS ) { + test_finish(); + error = -1; + goto cleanup; + } +#ifdef GL_ES_VERSION_2_0 + log_info("Cannot test OpenGL 3.2! This test was built for OpenGL ES 2.0\n"); + test_finish(); + error = -1; + goto cleanup; +#else + // Note: don't use the entire harness, because we have a different way of obtaining the device (via the context) + error = parseAndCallCommandLineTests( argc_, argv_, deviceIDs[ i ], num_fns32, basefn_list32, basefn_names32, true, 0, 1024 ); + if( error != 0 ) + break; +#endif + } + + // Converge on a common cleanup to make sure that things will be released properly before the test exit + goto cleanup; + } + + +// cleanup CL/GL/EGL environment properly when the test exit. +// This change does not affect any functionality of the test + +// Intentional falling through +cleanup: + + // Cleanup EGL + glEnv->terminate_egl_display(); + + // Always make sure that OpenCL context is released properly when the test exit + if(sCurrentContext) + { + clReleaseContext( sCurrentContext ); + sCurrentContext = NULL; + } + delete glEnv; + + + return error; +} \ No newline at end of file diff --git a/test_conformance/gles/procs.h b/test_conformance/gles/procs.h new file mode 100644 index 00000000..9df80d6c --- /dev/null +++ b/test_conformance/gles/procs.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/mt19937.h" + + +extern int test_buffers( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_buffers_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_images_create( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_images_read( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_images_2D_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_images_read_cube( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_images_cube_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_images_read_3D( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_images_3D_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_images_write( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_images_write_cube( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_renderbuffer_read( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_renderbuffer_write( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_renderbuffer_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_fence_sync( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); + diff --git a/test_conformance/gles/setup_egl.cpp b/test_conformance/gles/setup_egl.cpp new file mode 100644 index 00000000..c72f7f27 --- /dev/null +++ b/test_conformance/gles/setup_egl.cpp @@ -0,0 +1,215 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "setup.h" +#include "testBase.h" +#include "../../test_common/harness/errorHelpers.h" +#include + +#include +#include + +#define EGLERR() \ + assert(eglGetError() == EGL_SUCCESS); \ + +#define MAX_DEVICES 10 + +class EGLGLEnvironment : public GLEnvironment +{ +private: + cl_platform_id _platform; + EGLDisplay _display; + EGLContext _context; + EGLSurface _surface; + +public: + EGLGLEnvironment() + :_platform(NULL) + ,_display(EGL_NO_DISPLAY) + ,_context(NULL) + ,_surface(EGL_NO_SURFACE) + { + } + + virtual int Init( int *argc, char **argv, int use_opengl_32 ) + { + EGLint ConfigAttribs[] = + { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 16, + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, +// EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE, + EGL_NONE + }; + + static const EGLint ContextAttribs[] = + { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + EGLint conf_list[] = { + EGL_WIDTH, 512, + EGL_HEIGHT, 512, + EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, + EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, + EGL_NONE}; + + EGLint majorVersion; + EGLint minorVersion; + EGLConfig config; + EGLint numConfigs; + + EGLERR(); + _display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + EGLERR(); + + eglInitialize(_display, &majorVersion, &minorVersion); + EGLERR(); + + eglBindAPI(EGL_OPENGL_ES_API); + EGLERR(); + + eglChooseConfig(_display, ConfigAttribs, &config, 1, &numConfigs); + EGLERR(); + + _context = eglCreateContext(_display, config, NULL, ContextAttribs); + EGLERR(); + + _surface = eglCreatePbufferSurface(_display, config, conf_list); + EGLERR(); + + eglMakeCurrent(_display, _surface, _surface, _context); + EGLERR(); + + return 0; + } + + virtual cl_context CreateCLContext( void ) + { + cl_context_properties properties[] = { + CL_CONTEXT_PLATFORM, (cl_context_properties) _platform, + CL_GL_CONTEXT_KHR, (cl_context_properties) _context, + CL_EGL_DISPLAY_KHR, (cl_context_properties) _display, + 0 + }; + cl_device_id devices[MAX_DEVICES]; + size_t dev_size; + cl_int status; + + status = clGetGLContextInfoKHR(properties, + CL_DEVICES_FOR_GL_CONTEXT_KHR, + sizeof(devices), + devices, + &dev_size); + if (status != CL_SUCCESS) { + print_error(status, "clGetGLContextInfoKHR failed"); + return NULL; + } + dev_size /= sizeof(cl_device_id); + log_info("GL _context supports %d compute devices\n", dev_size); + + status = clGetGLContextInfoKHR(properties, + CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR, + sizeof(devices), + devices, + &dev_size); + if (status != CL_SUCCESS) { + print_error(status, "clGetGLContextInfoKHR failed"); + return NULL; + } + + if (!dev_size) + { + log_info("GL _context current device is not a CL device.\n"); + return NULL; + } + + return clCreateContext(properties, 1, &devices[0], NULL, NULL, &status); + } + + virtual int SupportsCLGLInterop( cl_device_type device_type ) + { + cl_device_id devices[MAX_DEVICES]; + cl_uint num_of_devices; + int interop_devices = 0; + int error; + + error = clGetPlatformIDs(1, &_platform, NULL); + if (error) { + print_error(error, "clGetPlatformIDs failed"); + return -1; + } + + error = clGetDeviceIDs(_platform, device_type, MAX_DEVICES, devices, &num_of_devices); + if (error) { + print_error(error, "clGetDeviceIDs failed"); + return -1; + } + + // Check all devices, search for one that supports cl_khr_gl_sharing + char extensions[8192]; + for (int i=0; i<(int)num_of_devices; i++) { + error = clGetDeviceInfo(devices[i], CL_DEVICE_EXTENSIONS, sizeof(extensions), extensions, NULL); + if (error) { + print_error(error, "clGetDeviceInfo failed"); + return -1; + } + + if (strstr(extensions, "cl_khr_gl_sharing ") == NULL) { + log_info("Device %d of %d does not support required extension cl_khr_gl_sharing.\n", i+1, num_of_devices); + } else { + log_info("Device %d of %d supports required extension cl_khr_gl_sharing.\n", i+1, num_of_devices); + interop_devices++; + } + } + return interop_devices > 0; + } + + // Change to cleanup egl environment properly when the test exit. + // This change does not affect any functionality of the test it self + virtual void terminate_egl_display() + { + if(_display != EGL_NO_DISPLAY) + { + eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + EGLERR(); + + eglDestroyContext(_display, _context); + EGLERR(); + _context = EGL_NO_CONTEXT; + + eglDestroySurface(_display, _surface); + EGLERR(); + _surface = EGL_NO_SURFACE; + + eglTerminate(_display); + EGLERR(); + _display = EGL_NO_DISPLAY; + } + } + + virtual ~EGLGLEnvironment() + { + } +}; + +GLEnvironment * GLEnvironment::Instance( void ) +{ + return new EGLGLEnvironment(); +} diff --git a/test_conformance/gles/testBase.h b/test_conformance/gles/testBase.h new file mode 100644 index 00000000..2bb59a61 --- /dev/null +++ b/test_conformance/gles/testBase.h @@ -0,0 +1,71 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testBase_h +#define _testBase_h + +#include +#include +#include +#include + +#if !defined(_WIN32) +#include +#endif + +#include +#include + +#if !defined (__APPLE__) +#include +#include "../../test_common/gles/gl_headers.h" +#include +#else +#include "../../test_common/gl/gl_headers.h" +#endif + +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/threadTesting.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/mt19937.h" + +#ifdef GL_ES_VERSION_2_0 +#include "../../test_common/gles/helpers.h" +#else +#include "../../test_common/gl/helpers.h" +#endif + +extern const char *get_kernel_suffix( cl_image_format *format ); +extern const char *get_write_conversion( cl_image_format *format, ExplicitType type); +extern ExplicitType get_read_kernel_type( cl_image_format *format ); +extern ExplicitType get_write_kernel_type( cl_image_format *format ); + +extern char * convert_to_expected( void * inputBuffer, size_t numPixels, ExplicitType inType, ExplicitType outType ); +extern int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t typeSize ); +extern int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t typeSize ); +extern int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height ); +extern int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth ); + +extern int CheckGLObjectInfo(cl_mem mem, cl_gl_object_type expected_cl_gl_type, GLuint expected_gl_name, + GLenum expected_cl_gl_texture_target, GLint expected_cl_gl_mipmap_level); + +extern bool CheckGLIntegerExtensionSupport(); + +#endif // _testBase_h + + + diff --git a/test_conformance/gles/test_buffers.cpp b/test_conformance/gles/test_buffers.cpp new file mode 100644 index 00000000..31d81d64 --- /dev/null +++ b/test_conformance/gles/test_buffers.cpp @@ -0,0 +1,402 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "testHarness.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" +#include +#include + +#if !defined (__APPLE__) + #include +#endif + +extern "C" { extern cl_uint gRandomSeed; }; + +static const char *bufferKernelPattern = +"__kernel void sample_test( __global %s%s *source, __global %s%s *clDest, __global %s%s *glDest )\n" +"{\n" +" int tid = get_global_id(0);\n" +" clDest[ tid ] = source[ tid ] + (%s%s)(1);\n" +" glDest[ tid ] = source[ tid ] + (%s%s)(2);\n" +"}\n"; + +#define TYPE_CASE( enum, type, range, offset ) \ + case enum: \ + { \ + cl_##type *ptr = (cl_##type *)outData; \ + for( i = 0; i < count; i++ ) \ + ptr[ i ] = (cl_##type)( ( genrand_int32(d) & range ) - offset ); \ + break; \ + } + +void gen_input_data( ExplicitType type, size_t count, MTdata d, void *outData ) +{ + size_t i; + + switch( type ) + { + case kBool: + { + bool *boolPtr = (bool *)outData; + for( i = 0; i < count; i++ ) + { + boolPtr[i] = ( genrand_int32(d) & 1 ) ? true : false; + } + break; + } + + TYPE_CASE( kChar, char, 250, 127 ) + TYPE_CASE( kUChar, uchar, 250, 0 ) + TYPE_CASE( kShort, short, 65530, 32767 ) + TYPE_CASE( kUShort, ushort, 65530, 0 ) + TYPE_CASE( kInt, int, 0x0fffffff, 0x70000000 ) + TYPE_CASE( kUInt, uint, 0x0fffffff, 0 ) + + case kLong: + { + cl_long *longPtr = (cl_long *)outData; + for( i = 0; i < count; i++ ) + { + longPtr[i] = (cl_long)genrand_int32(d) | ( (cl_ulong)genrand_int32(d) << 32 ); + } + break; + } + + case kULong: + { + cl_ulong *ulongPtr = (cl_ulong *)outData; + for( i = 0; i < count; i++ ) + { + ulongPtr[i] = (cl_ulong)genrand_int32(d) | ( (cl_ulong)genrand_int32(d) << 32 ); + } + break; + } + + case kFloat: + { + cl_float *floatPtr = (float *)outData; + for( i = 0; i < count; i++ ) + floatPtr[i] = get_random_float( -100000.f, 100000.f, d ); + break; + } + + default: + log_error( "ERROR: Invalid type passed in to generate_random_data!\n" ); + break; + } +} + +#define INC_CASE( enum, type ) \ + case enum: \ + { \ + cl_##type *src = (cl_##type *)inData; \ + cl_##type *dst = (cl_##type *)outData; \ + *dst = *src + 1; \ + break; \ + } + +void get_incremented_value( void *inData, void *outData, ExplicitType type ) +{ + switch( type ) + { + INC_CASE( kChar, char ) + INC_CASE( kUChar, uchar ) + INC_CASE( kShort, short ) + INC_CASE( kUShort, ushort ) + INC_CASE( kInt, int ) + INC_CASE( kUInt, uint ) + INC_CASE( kLong, long ) + INC_CASE( kULong, ulong ) + INC_CASE( kFloat, float ) + default: + break; + } +} + +int test_buffer_kernel(cl_context context, cl_command_queue queue, ExplicitType vecType, size_t vecSize, int numElements, int validate_only, MTdata d) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 3 ]; + size_t dataSize = numElements * 16 * sizeof(cl_long); +#if !(defined(_WIN32) && defined(_MSC_VER)) + cl_long inData[numElements * 16], outDataCL[numElements * 16], outDataGL[ numElements * 16 ]; +#else + cl_long* inData = (cl_long*)_malloca(dataSize); + cl_long* outDataCL = (cl_long*)_malloca(dataSize); + cl_long* outDataGL = (cl_long*)_malloca(dataSize); +#endif + glBufferWrapper inGLBuffer, outGLBuffer; + int i; + size_t bufferSize; + + int error; + size_t threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + char sizeName[4]; + + /* Create the source */ + if( vecSize == 1 ) + sizeName[ 0 ] = 0; + else + sprintf( sizeName, "%d", (int)vecSize ); + + sprintf( kernelSource, bufferKernelPattern, get_explicit_type_name( vecType ), sizeName, + get_explicit_type_name( vecType ), sizeName, + get_explicit_type_name( vecType ), sizeName, + get_explicit_type_name( vecType ), sizeName, + get_explicit_type_name( vecType ), sizeName ); + + /* Create kernels */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + { + return -1; + } + + bufferSize = numElements * vecSize * get_explicit_type_size( vecType ); + + /* Generate some almost-random input data */ + gen_input_data( vecType, vecSize * numElements, d, inData ); + memset( outDataCL, 0, dataSize ); + memset( outDataGL, 0, dataSize ); + + /* Generate some GL buffers to go against */ + glGenBuffers( 1, &inGLBuffer ); + glGenBuffers( 1, &outGLBuffer ); + + glBindBuffer( GL_ARRAY_BUFFER, inGLBuffer ); + glBufferData( GL_ARRAY_BUFFER, bufferSize, inData, GL_STATIC_DRAW ); + + // Note: we need to bind the output buffer, even though we don't care about its values yet, + // because CL needs it to get the buffer size + glBindBuffer( GL_ARRAY_BUFFER, outGLBuffer ); + glBufferData( GL_ARRAY_BUFFER, bufferSize, outDataGL, GL_STATIC_DRAW ); + + glBindBuffer( GL_ARRAY_BUFFER, 0 ); + glFlush(); + + + /* Generate some streams. The first and last ones are GL, middle one just vanilla CL */ + streams[ 0 ] = (*clCreateFromGLBuffer_ptr)( context, CL_MEM_READ_ONLY, inGLBuffer, &error ); + test_error( error, "Unable to create input GL buffer" ); + + streams[ 1 ] = clCreateBuffer( context, CL_MEM_READ_WRITE, bufferSize, NULL, &error ); + test_error( error, "Unable to create output CL buffer" ); + + streams[ 2 ] = (*clCreateFromGLBuffer_ptr)( context, CL_MEM_WRITE_ONLY, outGLBuffer, &error ); + test_error( error, "Unable to create output GL buffer" ); + + + /* Validate the info */ + if (validate_only) { + int result = (CheckGLObjectInfo(streams[0], CL_GL_OBJECT_BUFFER, (GLuint)inGLBuffer, (GLenum)0, 0) | + CheckGLObjectInfo(streams[2], CL_GL_OBJECT_BUFFER, (GLuint)outGLBuffer, (GLenum)0, 0) ); + for(i=0;i<3;i++) + { + clReleaseMemObject(streams[i]); + streams[i] = NULL; + } + + glDeleteBuffers(1, &inGLBuffer); inGLBuffer = 0; + glDeleteBuffers(1, &outGLBuffer); outGLBuffer = 0; + + return result; + } + + /* Assign streams and execute */ + for( int i = 0; i < 3; i++ ) + { + error = clSetKernelArg( kernel, i, sizeof( streams[ i ] ), &streams[ i ] ); + test_error( error, "Unable to set kernel arguments" ); + } + error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &streams[ 0 ], 0, NULL, NULL); + test_error( error, "Unable to acquire GL obejcts"); + error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &streams[ 2 ], 0, NULL, NULL); + test_error( error, "Unable to acquire GL obejcts"); + + /* Run the kernel */ + threads[0] = numElements; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &streams[ 0 ], 0, NULL, NULL ); + test_error(error, "clEnqueueReleaseGLObjects failed"); + error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &streams[ 2 ], 0, NULL, NULL ); + test_error(error, "clEnqueueReleaseGLObjects failed"); + + // Get the results from both CL and GL and make sure everything looks correct + error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, bufferSize, outDataCL, 0, NULL, NULL ); + test_error( error, "Unable to read output CL array!" ); + glBindBuffer( GL_ARRAY_BUFFER, outGLBuffer ); + void *glMem = glMapBufferRange(GL_ARRAY_BUFFER, 0, bufferSize, GL_MAP_READ_BIT ); + memcpy( outDataGL, glMem, bufferSize ); + glUnmapBuffer( GL_ARRAY_BUFFER ); + char *inP = (char *)inData, *glP = (char *)outDataGL, *clP = (char *)outDataCL; + error = 0; + for( size_t i = 0; i < numElements * vecSize; i++ ) + { + cl_long expectedCLValue, expectedGLValue; + get_incremented_value( inP, &expectedCLValue, vecType ); + get_incremented_value( &expectedCLValue, &expectedGLValue, vecType ); + + if( memcmp( clP, &expectedCLValue, get_explicit_type_size( vecType ) ) != 0 ) + { + char scratch[ 64 ]; + log_error( "ERROR: Data sample %d from the CL output did not validate!\n", (int)i ); + log_error( "\t Input: %s\n", GetDataVectorString( inP, get_explicit_type_size( vecType ), 1, scratch ) ); + log_error( "\tExpected: %s\n", GetDataVectorString( &expectedCLValue, get_explicit_type_size( vecType ), 1, scratch ) ); + log_error( "\t Actual: %s\n", GetDataVectorString( clP, get_explicit_type_size( vecType ), 1, scratch ) ); + error = -1; + } + + if( memcmp( glP, &expectedGLValue, get_explicit_type_size( vecType ) ) != 0 ) + { + char scratch[ 64 ]; + log_error( "ERROR: Data sample %d from the GL output did not validate!\n", (int)i ); + log_error( "\t Input: %s\n", GetDataVectorString( inP, get_explicit_type_size( vecType ), 1, scratch ) ); + log_error( "\tExpected: %s\n", GetDataVectorString( &expectedGLValue, get_explicit_type_size( vecType ), 1, scratch ) ); + log_error( "\t Actual: %s\n", GetDataVectorString( glP, get_explicit_type_size( vecType ), 1, scratch ) ); + error = -1; + } + + if( error ) + return error; + + inP += get_explicit_type_size( vecType ); + glP += get_explicit_type_size( vecType ); + clP += get_explicit_type_size( vecType ); + } + + for(i=0;i<3;i++) + { + clReleaseMemObject(streams[i]); + streams[i] = NULL; + } + + glDeleteBuffers(1, &inGLBuffer); inGLBuffer = 0; + glDeleteBuffers(1, &outGLBuffer); outGLBuffer = 0; + +#if (defined(_WIN32) && defined(_MSC_VER)) + _freea(inData); + _freea(outDataCL); + _freea(outDataGL); +#endif + + return 0; +} + +int test_buffers( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 4, 8, 16, 0 }; + unsigned int index, typeIndex; + int retVal = 0; + RandomSeed seed(gRandomSeed); + + /* 64-bit ints optional in embedded profile */ + int hasLong = 1; + int isEmbedded = 0; + char profile[1024] = ""; + retVal = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL); + if (retVal) + { + print_error(retVal, "clGetDeviceInfo for CL_DEVICE_PROFILE failed\n" ); + return -1; + } + isEmbedded = NULL != strstr(profile, "EMBEDDED_PROFILE"); + if(isEmbedded && !is_extension_available(device, "cles_khr_int64")) + { + hasLong = 0; + } + + for( typeIndex = 0; vecType[ typeIndex ] != kNumExplicitTypes; typeIndex++ ) + { + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + /* Fix bug 7124 */ + if ( (vecType[ typeIndex ] == kLong || vecType[ typeIndex ] == kULong) && !hasLong ) + continue; + + // Test! + if( test_buffer_kernel( context, queue, vecType[ typeIndex ], vecSizes[ index ], numElements, 0, seed) != 0 ) + { + char sizeNames[][ 4 ] = { "", "", "2", "", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + log_error( " Buffer test %s%s FAILED\n", get_explicit_type_name( vecType[ typeIndex ] ), sizeNames[ vecSizes[ index ] ] ); + retVal++; + } + } + } + + return retVal; + +} + + +int test_buffers_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 4, 8, 16, 0 }; + unsigned int index, typeIndex; + int retVal = 0; + RandomSeed seed( gRandomSeed ); + + /* 64-bit ints optional in embedded profile */ + int hasLong = 1; + int isEmbedded = 0; + char profile[1024] = ""; + retVal = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL); + if (retVal) + { + print_error(retVal, "clGetDeviceInfo for CL_DEVICE_PROFILE failed\n" ); + return -1; + } + isEmbedded = NULL != strstr(profile, "EMBEDDED_PROFILE"); + if(isEmbedded && !is_extension_available(device, "cles_khr_int64")) + { + hasLong = 0; + } + + for( typeIndex = 0; vecType[ typeIndex ] != kNumExplicitTypes; typeIndex++ ) + { + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + /* Fix bug 7124 */ + if ( (vecType[ typeIndex ] == kLong || vecType[ typeIndex ] == kULong) && !hasLong ) + continue; + + // Test! + if( test_buffer_kernel( context, queue, vecType[ typeIndex ], vecSizes[ index ], numElements, 1, seed ) != 0 ) + { + char sizeNames[][ 4 ] = { "", "", "2", "", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + log_error( " Buffer test %s%s FAILED\n", get_explicit_type_name( vecType[ typeIndex ] ), sizeNames[ vecSizes[ index ] ] ); + retVal++; + } + } + } + + return retVal; + +} + + + diff --git a/test_conformance/gles/test_fence_sync.cpp b/test_conformance/gles/test_fence_sync.cpp new file mode 100644 index 00000000..1c117943 --- /dev/null +++ b/test_conformance/gles/test_fence_sync.cpp @@ -0,0 +1,664 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "gl_headers.h" + +#include "testBase.h" +#include "setup.h" +#include "../../test_common/harness/genericThread.h" + +#ifndef GLsync +// For OpenGL before 3.2, we look for the ARB_sync extension and try to use that +#if !defined(_WIN32) +#include +#endif // !_WIN32 +typedef int64_t GLint64; +typedef uint64_t GLuint64; +typedef struct __GLsync *GLsync; + +typedef GLsync (*glFenceSyncPtr)(GLenum condition,GLbitfield flags); +glFenceSyncPtr glFenceSyncFunc; + +typedef bool (*glIsSyncPtr)(GLsync sync); +glIsSyncPtr glIsSyncFunc; + +typedef void (*glDeleteSyncPtr)(GLsync sync); +glDeleteSyncPtr glDeleteSyncFunc; + +typedef GLenum (*glClientWaitSyncPtr)(GLsync sync,GLbitfield flags,GLuint64 timeout); +glClientWaitSyncPtr glClientWaitSyncFunc; + +typedef void (*glWaitSyncPtr)(GLsync sync,GLbitfield flags,GLuint64 timeout); +glWaitSyncPtr glWaitSyncFunc; + +typedef void (*glGetInteger64vPtr)(GLenum pname, GLint64 *params); +glGetInteger64vPtr glGetInteger64vFunc; + +typedef void (*glGetSyncivPtr)(GLsync sync,GLenum pname,GLsizei bufSize,GLsizei *length, + GLint *values); +glGetSyncivPtr glGetSyncivFunc; + +#define CHK_GL_ERR() printf("%s\n", gluErrorString(glGetError())) + +static void InitSyncFns( void ) +{ + glFenceSyncFunc = (glFenceSyncPtr)glutGetProcAddress( "glFenceSync" ); + glIsSyncFunc = (glIsSyncPtr)glutGetProcAddress( "glIsSync" ); + glDeleteSyncFunc = (glDeleteSyncPtr)glutGetProcAddress( "glDeleteSync" ); + glClientWaitSyncFunc = (glClientWaitSyncPtr)glutGetProcAddress( "glClientWaitSync" ); + glWaitSyncFunc = (glWaitSyncPtr)glutGetProcAddress( "glWaitSync" ); + glGetInteger64vFunc = (glGetInteger64vPtr)glutGetProcAddress( "glGetInteger64v" ); + glGetSyncivFunc = (glGetSyncivPtr)glutGetProcAddress( "glGetSynciv" ); +} + +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 + +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 + +#define GL_SYNC_FENCE 0x9116 + +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 + +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 + +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 + +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull + +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D + +#define USING_ARB_sync 1 +#endif + +typedef cl_event (CL_API_CALL *clCreateEventFromGLsyncKHR_fn)( cl_context context, GLsync sync, cl_int *errCode_ret) ; + +clCreateEventFromGLsyncKHR_fn clCreateEventFromGLsyncKHR_ptr; + + +static const char *updateBuffersKernel[] = { + "__kernel void update( __global float4 * vertices, __global float4 *colors, int horizWrap, int rowIdx )\n" + "{\n" + " size_t tid = get_global_id(0);\n" + "\n" + " size_t xVal = ( tid & ( horizWrap - 1 ) );\n" + " vertices[ tid * 2 + 0 ] = (float4)( xVal, rowIdx*16.f, 0.0f, 1.f );\n" + " vertices[ tid * 2 + 1 ] = (float4)( xVal, rowIdx*16.f + 4.0f, 0.0f, 1.f );\n" + "\n" + " int rowV = rowIdx + 1;\n" + " colors[ tid * 2 + 0 ] = (float4)( ( rowV & 1 ) / 255.f, ( ( rowV & 2 ) >> 1 ) / 255.f, ( ( rowV & 4 ) >> 2 ) / 255.f, 1.f );\n" + " //colors[ tid * 2 + 0 ] = (float4)( (float)xVal/(float)horizWrap, 1.0f, 1.0f, 1.0f );\n" + " colors[ tid * 2 + 1 ] = colors[ tid * 2 + 0 ];\n" + "}\n" }; + +//Passthrough VertexShader +static const char vertexshader[] = +"uniform mat4 projMatrix;\n" +"attribute vec4 inPosition;\n" +"attribute vec4 inColor;\n" +"varying vec4 outColor;\n" +"void main (void) {\n" +" gl_Position = projMatrix*inPosition;\n" +" outColor = inColor;\n" +"}\n"; + +//Passthrough FragmentShader +static const char fragmentshader[] = +"varying vec4 outColor;\n" +"void main (void) {\n" +" gl_FragColor = outColor;\n" +"}\n"; + +GLuint createShaderProgram(GLint *posLoc, GLint *colLoc) +{ + GLint logLength, status; + GLuint program = glCreateProgram(); + GLuint vpShader; + + char* vpstr = (char*)malloc(sizeof(vertexshader)); + strcpy(vpstr, vertexshader); + + vpShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vpShader, 1, (const GLchar **)&vpstr, NULL); + glCompileShader(vpShader); + glGetShaderiv(vpShader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar*) malloc(logLength); + glGetShaderInfoLog(vpShader, logLength, &logLength, log); + log_info("Vtx Shader compile log:\n%s", log); + free(log); + } + + free(vpstr); + vpstr = NULL; + + glGetShaderiv(vpShader, GL_COMPILE_STATUS, &status); + if (status == 0) + { + log_error("Failed to compile vtx shader:\n"); + return 0; + } + + glAttachShader(program, vpShader); + + GLuint fpShader; + char* fpstr = (char*)malloc(strlen(fragmentshader)); + strcpy(fpstr, fragmentshader); + fpShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fpShader, 1, (const GLchar **)&fpstr, NULL); + glCompileShader(fpShader); + + free(fpstr); + fpstr = NULL; + + glGetShaderiv(fpShader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar*)malloc(logLength); + glGetShaderInfoLog(fpShader, logLength, &logLength, log); + log_info("Frag Shader compile log:\n%s", log); + free(log); + } + + glAttachShader(program, fpShader); + glGetShaderiv(fpShader, GL_COMPILE_STATUS, &status); + if (status == 0) + { + log_error("Failed to compile frag shader:\n\n"); + return 0; + } + + glLinkProgram(program); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar*)malloc(logLength); + glGetProgramInfoLog(program, logLength, &logLength, log); + log_info("Program link log:\n%s", log); + free(log); + } + + glGetProgramiv(program, GL_LINK_STATUS, &status); + if (status == 0) + { + log_error("Failed to link program\n"); + return 0; + } + + glValidateProgram(program); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar*)malloc(logLength); + glGetProgramInfoLog(program, logLength, &logLength, log); + log_info("Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(program, GL_VALIDATE_STATUS, &status); + if (status == 0) + { + log_error("Failed to validate program\n"); + return 0; + } + + *posLoc = glGetAttribLocation(program, "inPosition"); + *colLoc = glGetAttribLocation(program, "inColor"); + + return program; +} + +void destroyShaderProgram(GLuint program) +{ + GLuint shaders[2]; + GLsizei count; + glUseProgram(0); + glGetAttachedShaders(program, 2, &count, shaders); + int i; + for(i = 0; i < count; i++) + { + glDetachShader(program, shaders[i]); + glDeleteShader(shaders[i]); + } + glDeleteProgram(program); +} + +// This function queues up and runs the above CL kernel that writes the vertex data +cl_int run_cl_kernel( cl_kernel kernel, cl_command_queue queue, cl_mem stream0, cl_mem stream1, + cl_int rowIdx, cl_event fenceEvent, size_t numThreads ) +{ + cl_int error = clSetKernelArg( kernel, 3, sizeof( rowIdx ), &rowIdx ); + test_error( error, "Unable to set kernel arguments" ); + + clEventWrapper acqEvent1, acqEvent2, kernEvent, relEvent1, relEvent2; + int numEvents = ( fenceEvent != NULL ) ? 1 : 0; + cl_event *fence_evt = ( fenceEvent != NULL ) ? &fenceEvent : NULL; + + error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &stream0, numEvents, fence_evt, &acqEvent1 ); + test_error( error, "Unable to acquire GL obejcts"); + error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &stream1, numEvents, fence_evt, &acqEvent2 ); + test_error( error, "Unable to acquire GL obejcts"); + + cl_event evts[ 2 ] = { acqEvent1, acqEvent2 }; + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, &numThreads, NULL, 2, evts, &kernEvent ); + test_error( error, "Unable to execute test kernel" ); + + error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &stream0, 1, &kernEvent, &relEvent1 ); + test_error(error, "clEnqueueReleaseGLObjects failed"); + error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &stream1, 1, &kernEvent, &relEvent2 ); + test_error(error, "clEnqueueReleaseGLObjects failed"); + + evts[ 0 ] = relEvent1; + evts[ 1 ] = relEvent2; + error = clWaitForEvents( 2, evts ); + test_error( error, "Unable to wait for release events" ); + + return 0; +} + +class RunThread : public genericThread +{ +public: + + cl_kernel mKernel; + cl_command_queue mQueue; + cl_mem mStream0, mStream1; + cl_int mRowIdx; + cl_event mFenceEvent; + size_t mNumThreads; + + RunThread( cl_kernel kernel, cl_command_queue queue, cl_mem stream0, cl_mem stream1, size_t numThreads ) + : mKernel( kernel ), mQueue( queue ), mStream0( stream0 ), mStream1( stream1 ), mNumThreads( numThreads ) + { + } + + void SetRunData( cl_int rowIdx, cl_event fenceEvent ) + { + mRowIdx = rowIdx; + mFenceEvent = fenceEvent; + } + + virtual void * IRun( void ) + { + cl_int error = run_cl_kernel( mKernel, mQueue, mStream0, mStream1, mRowIdx, mFenceEvent, mNumThreads ); + return (void *)error; + } +}; + + +int test_fence_sync_single( cl_device_id device, cl_context context, cl_command_queue queue, bool separateThreads, GLint rend_vs, GLint read_vs, cl_device_id rend_device ) +{ + int error; + const int framebufferSize = 512; + cl_platform_id platform_id = NULL; + + if( !is_extension_available( device, "cl_khr_gl_event" ) ) + { + log_info( "NOTE: cl_khr_gl_event extension not present on this device; skipping fence sync test\n" ); + return 0; + } + + error = clGetDeviceInfo(device, + CL_DEVICE_PLATFORM, + sizeof(platform_id), + &platform_id, + NULL); + if(error) + { + return error; + } + + clCreateEventFromGLsyncKHR_ptr = \ + (clCreateEventFromGLsyncKHR_fn)clGetExtensionFunctionAddressForPlatform(platform_id,"clCreateEventFromGLsyncKHR"); + if( clCreateEventFromGLsyncKHR_ptr == NULL ) + { + log_error( "ERROR: Unable to run fence_sync test (clCreateEventFromGLsyncKHR function not discovered!)\n" ); + clCreateEventFromGLsyncKHR_ptr = \ + (clCreateEventFromGLsyncKHR_fn)clGetExtensionFunctionAddressForPlatform(platform_id, "clCreateEventFromGLsyncAPPLE"); + return -1; + } + +#ifdef USING_ARB_sync + char *gl_version_str = (char*)glGetString( GL_VERSION ); + float glCoreVersion; + sscanf(gl_version_str, "%f", &glCoreVersion); + if( glCoreVersion < 3.0f ) + { + log_info( "OpenGL version %f does not support fence/sync! Skipping test.\n", glCoreVersion ); + return 0; + } + +#ifdef __APPLE__ + CGLContextObj currCtx = CGLGetCurrentContext(); + CGLPixelFormatObj pixFmt = CGLGetPixelFormat(currCtx); + GLint val, screen; + CGLGetVirtualScreen(currCtx, &screen); + CGLDescribePixelFormat(pixFmt, screen, kCGLPFAOpenGLProfile, &val); + if(val != kCGLOGLPVersion_3_2_Core) + { + log_error( "OpenGL context was not created with OpenGL version >= 3.0 profile even though platform supports it" + "OpenGL profile %f does not support fence/sync! Skipping test.\n", glCoreVersion ); + return -1; + } +#else + // Need platform specific way to query if current GL context was created with 3.x profile + log_error( "ERROR: not implemented\n\n" ); + return -1; +#endif + + InitSyncFns(); +#endif + +#ifdef __APPLE__ + CGLSetVirtualScreen(CGLGetCurrentContext(), rend_vs); +#else + // Need platform specific way to set device with id rend_vs the current + // rendering target + log_error( "ERROR: not implemented\n\n" ); + return -1; +#endif + + GLint posLoc, colLoc; + GLuint shaderprogram = createShaderProgram(&posLoc, &colLoc); + if(!shaderprogram) + { + log_error("Failed to create shader program\n"); + return -1; + } + + float l = 0.0f; float r = framebufferSize; + float b = 0.0f; float t = framebufferSize; + + float projMatrix[16] = { 2.0f/(r-l), 0.0f, 0.0f, 0.0f, + 0.0f, 2.0f/(t-b), 0.0f, 0.0f, + 0.0f, 0.0f, -1.0f, 0.0f, + -(r+l)/(r-l), -(t+b)/(t-b), 0.0f, 1.0f + }; + + glUseProgram(shaderprogram); + GLuint projMatLoc = glGetUniformLocation(shaderprogram, "projMatrix"); + glUniformMatrix4fv(projMatLoc, 1, 0, projMatrix); + glUseProgram(0); + + // Note: the framebuffer is just the target to verify our results against, so we don't + // really care to go through all the possible formats in this case + glFramebufferWrapper glFramebuffer; + glRenderbufferWrapper glRenderbuffer; + error = CreateGLRenderbufferRaw( framebufferSize, 128, GL_COLOR_ATTACHMENT0_EXT, + GL_RGBA, GL_UNSIGNED_BYTE, + &glFramebuffer, &glRenderbuffer ); + if( error != 0 ) + return error; + +// GLuint vao; +// glGenVertexArrays(1, &vao); +// glBindVertexArray(vao); + + glBufferWrapper vtxBuffer, colorBuffer; + glGenBuffers( 1, &vtxBuffer ); + glGenBuffers( 1, &colorBuffer ); + + const int numHorizVertices = ( framebufferSize * 64 ) + 1; + + glBindBuffer( GL_ARRAY_BUFFER, vtxBuffer ); + glBufferData( GL_ARRAY_BUFFER, sizeof( GLfloat ) * numHorizVertices * 2 * 4, NULL, GL_STATIC_DRAW ); + + glBindBuffer( GL_ARRAY_BUFFER, colorBuffer ); + glBufferData( GL_ARRAY_BUFFER, sizeof( GLfloat ) * numHorizVertices * 2 * 4, NULL, GL_STATIC_DRAW ); + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 2 ]; + + if( create_single_kernel_helper( context, &program, &kernel, 1, updateBuffersKernel, "update" ) ) + return -1; + + + streams[ 0 ] = (*clCreateFromGLBuffer_ptr)( context, CL_MEM_READ_WRITE, vtxBuffer, &error ); + test_error( error, "Unable to create CL buffer from GL vertex buffer" ); + + streams[ 1 ] = (*clCreateFromGLBuffer_ptr)( context, CL_MEM_READ_WRITE, colorBuffer, &error ); + test_error( error, "Unable to create CL buffer from GL color buffer" ); + + error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] ); + test_error( error, "Unable to set kernel arguments" ); + + error = clSetKernelArg( kernel, 1, sizeof( streams[ 1 ] ), &streams[ 1 ] ); + test_error( error, "Unable to set kernel arguments" ); + + cl_int horizWrap = (cl_int)framebufferSize; + error = clSetKernelArg( kernel, 2, sizeof( horizWrap ), &horizWrap ); + test_error( error, "Unable to set kernel arguments" ); + + glViewport( 0, 0, framebufferSize, framebufferSize ); + glClearColor( 0, 0, 0, 0 ); + glClear( GL_COLOR_BUFFER_BIT ); + glClear( GL_DEPTH_BUFFER_BIT ); + glDisable( GL_DEPTH_TEST ); + glEnable( GL_BLEND ); + glBlendFunc( GL_ONE, GL_ONE ); + + clEventWrapper fenceEvent; + GLsync glFence = 0; + + // Do a loop through 8 different horizontal stripes against the framebuffer + RunThread thread( kernel, queue, streams[ 0 ], streams[ 1 ], (size_t)numHorizVertices ); + + for( int i = 0; i < 8; i++ ) + { + // if current rendering device is not the compute device and + // separateThreads == false which means compute is going on same + // thread and we are using implicit synchronization (no GLSync obj used) + // then glFlush by clEnqueueAcquireGLObject is not sufficient ... we need + // to wait for rendering to finish on other device before CL can start + // writing to CL/GL shared mem objects. When separateThreads is true i.e. + // we are using GLSync obj to synchronize then we dont need to call glFinish + // here since CL should wait for rendering on other device before this + // GLSync object to finish before it starts writing to shared mem object. + // Also rend_device == compute_device no need to call glFinish + if(rend_device != device && !separateThreads) + glFinish(); + + if( separateThreads ) + { + thread.SetRunData( (cl_int)i, fenceEvent ); + thread.Start(); + + error = (cl_int)(size_t)thread.Join(); + } + else + { + error = run_cl_kernel( kernel, queue, streams[ 0 ], streams[ 1 ], (cl_int)i, fenceEvent, (size_t)numHorizVertices ); + } + test_error( error, "Unable to run CL kernel" ); + + glUseProgram(shaderprogram); + glEnableVertexAttribArray(posLoc); + glEnableVertexAttribArray(colLoc); + glBindBuffer( GL_ARRAY_BUFFER, vtxBuffer ); + glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0); + glBindBuffer( GL_ARRAY_BUFFER, colorBuffer ); + glVertexAttribPointer(colLoc, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0); + glBindBuffer( GL_ARRAY_BUFFER, 0 ); + + glDrawArrays( GL_TRIANGLE_STRIP, 0, numHorizVertices * 2 ); + + glDisableVertexAttribArray(posLoc); + glDisableVertexAttribArray(colLoc); + glUseProgram(0); + + if( separateThreads ) + { + // If we're on the same thread, then we're testing implicit syncing, so we + // don't need the actual fence code + if( fenceEvent != NULL ) + { + clReleaseEvent( fenceEvent ); + glDeleteSyncFunc( glFence ); + } + + glFence = glFenceSyncFunc( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 ); + fenceEvent = clCreateEventFromGLsyncKHR_ptr( context, glFence, &error ); + test_error( error, "Unable to create CL event from GL fence" ); + + // in case of explicit synchronization, we just wait for the sync object to complete + // in clEnqueueAcquireGLObject but we dont flush. Its application's responsibility + // to flush on the context on which glSync is created + glFlush(); + } + } + + if( glFence != 0 ) + // Don't need the final release for fenceEvent, because the wrapper will take care of that + glDeleteSyncFunc( glFence ); + +#ifdef __APPLE__ + CGLSetVirtualScreen(CGLGetCurrentContext(), read_vs); +#else + // Need platform specific code to set the current rendering device (OpenGL target) + // to device with id read_vs so that next glReadPixels get submitted to that device + log_error( "ERROR: not implemented\n\n" ); + return -1; +#endif + // Grab the contents of the final framebuffer + BufferOwningPtr resultData( ReadGLRenderbuffer( glFramebuffer, glRenderbuffer, + GL_COLOR_ATTACHMENT0_EXT, + GL_RGBA8_OES, GL_UNSIGNED_BYTE, GL_RGBA, GL_UNSIGNED_BYTE, kUChar, + framebufferSize, 128 ) ); + + // Check the contents now. We should end up with solid color bands 32 pixels high and the + // full width of the framebuffer, at values (128,128,128) due to the additive blending + for( int i = 0; i < 8; i++ ) + { + for( int y = 0; y < 4; y++ ) + { + // Note: coverage will be double because the 63-0 triangle overwrites again at the end of the pass + cl_uchar valA = ( ( ( i + 1 ) & 1 ) ) * numHorizVertices * 2 / framebufferSize; + cl_uchar valB = ( ( ( i + 1 ) & 2 ) >> 1 ) * numHorizVertices * 2 / framebufferSize; + cl_uchar valC = ( ( ( i + 1 ) & 4 ) >> 2 ) * numHorizVertices * 2 / framebufferSize; + + cl_uchar *row = (cl_uchar *)&resultData[ ( i * 16 + y ) * framebufferSize * 4 ]; + for( int x = 0; x < ( framebufferSize - 1 ) - 1; x++ ) + { + if( ( row[ x * 4 ] != valA ) || ( row[ x * 4 + 1 ] != valB ) || + ( row[ x * 4 + 2 ] != valC ) ) + { + log_error( "ERROR: Output framebuffer did not validate!\n" ); + DumpGLBuffer( GL_UNSIGNED_BYTE, framebufferSize, 128, resultData ); + log_error( "RUNS:\n" ); + uint32_t *p = (uint32_t *)(char *)resultData; + size_t a = 0; + for( size_t t = 1; t < framebufferSize * framebufferSize; t++ ) + { + if( p[ a ] != 0 ) + { + if( p[ t ] == 0 ) + { + log_error( "RUN: %ld to %ld (%d,%d to %d,%d) 0x%08x\n", a, t - 1, + (int)( a % framebufferSize ), (int)( a / framebufferSize ), + (int)( ( t - 1 ) % framebufferSize ), (int)( ( t - 1 ) / framebufferSize ), + p[ a ] ); + a = t; + } + } + else + { + if( p[ t ] != 0 ) + { + a = t; + } + } + + } + return -1; + } + } + } + } + + glDeleteBuffers( 1, &vtxBuffer ); + glDeleteBuffers( 1, &colorBuffer ); + destroyShaderProgram(shaderprogram); +// glDeleteVertexArrays(1, &vao); + return 0; +} + +int test_fence_sync( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLint vs_count = 0; + cl_device_id *device_list = NULL; + + if( !is_extension_available( device, "cl_khr_gl_event" ) ) + { + log_info( "NOTE: cl_khr_gl_event extension not present on this device; skipping fence sync test\n" ); + return 0; + } +#ifdef __APPLE__ + CGLContextObj ctx = CGLGetCurrentContext(); + CGLPixelFormatObj pix = CGLGetPixelFormat(ctx); + CGLError err = CGLDescribePixelFormat(pix, 0, kCGLPFAVirtualScreenCount, &vs_count); + + device_list = (cl_device_id *) malloc(sizeof(cl_device_id)*vs_count); + clGetGLContextInfoAPPLE(context, ctx, CL_CGL_DEVICES_FOR_SUPPORTED_VIRTUAL_SCREENS_APPLE, sizeof(cl_device_id)*vs_count, device_list, NULL); +#else + // Need platform specific way of getting devices from CL context to which OpenGL can render + // If not available it can be replaced with clGetContextInfo with CL_CONTEXT_DEVICES + log_error( "ERROR: not implemented\n\n" ); + return -1; +#endif + + GLint rend_vs, read_vs; + int error = 0; + int any_failed = 0; + + // Loop through all the devices capable to OpenGL rendering + // and set them as current rendering target + for(rend_vs = 0; rend_vs < vs_count; rend_vs++) + { + // Loop through all the devices and set them as current + // compute target + for(read_vs = 0; read_vs < vs_count; read_vs++) + { + cl_device_id rend_device = device_list[rend_vs], read_device = device_list[read_vs]; + char rend_name[200], read_name[200]; + + clGetDeviceInfo(rend_device, CL_DEVICE_NAME, sizeof(rend_name), rend_name, NULL); + clGetDeviceInfo(read_device, CL_DEVICE_NAME, sizeof(read_name), read_name, NULL); + + log_info("Rendering on: %s, read back on: %s\n", rend_name, read_name); + error = test_fence_sync_single( device, context, queue, false, rend_vs, read_vs, rend_device ); + any_failed |= error; + if( error != 0 ) + log_error( "ERROR: Implicit syncing with GL sync events failed!\n\n" ); + else + log_info("Implicit syncing Passed\n"); + + error = test_fence_sync_single( device, context, queue, true, rend_vs, read_vs, rend_device ); + any_failed |= error; + if( error != 0 ) + log_error( "ERROR: Explicit syncing with GL sync events failed!\n\n" ); + else + log_info("Explicit syncing Passed\n"); + } + } + + free(device_list); + + return any_failed; +} diff --git a/test_conformance/gles/test_images_2D.cpp b/test_conformance/gles/test_images_2D.cpp new file mode 100644 index 00000000..f2c66fd7 --- /dev/null +++ b/test_conformance/gles/test_images_2D.cpp @@ -0,0 +1,749 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +#include "gl_headers.h" + +extern "C" { extern cl_uint gRandomSeed; } + +static const char *imageReadKernelPattern = +"#pragma OPENCL EXTENSION cl_khr_fp16 : enable\n" /* added support for half floats */ +"__kernel void sample_test( read_only image2d_t source, sampler_t sampler, __global %s4 *results )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" results[ tidY * get_image_width( source ) + tidX ] = read_image%s( source, sampler, (int2)( tidX, tidY ) );\n" +"}\n"; + +static const char *imageWriteKernelPattern = +"#pragma OPENCL EXTENSION cl_khr_fp16 : enable\n" /* added support for half floats */ +"__kernel void sample_test( __global %s4 *source, write_only image2d_t dest )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" uint index = tidY * get_image_width( dest ) + tidX;\n" +" %s4 value = source[index];\n" +" write_image%s( dest, (int2)( tidX, tidY ), %s(value));\n" +"}\n"; + +int test_cl_image_read( cl_context context, cl_command_queue queue, cl_mem clImage, + size_t imageWidth, size_t imageHeight, cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper outStream; + + int error; + size_t threads[ 2 ], localThreads[ 2 ]; + char kernelSource[10240]; + char *programPtr; + + + // Determine data type and format that CL came up with + error = clGetImageInfo( clImage, CL_IMAGE_FORMAT, sizeof( cl_image_format ), outFormat, NULL ); + test_error( error, "Unable to get CL image format" ); + + /* Create the source */ + *outType = get_read_kernel_type( outFormat ); + size_t channelSize = get_explicit_type_size( *outType ); + + sprintf( kernelSource, imageReadKernelPattern, get_explicit_type_name( *outType ), get_kernel_suffix( outFormat ) ); + +#ifdef GLES_DEBUG + log_info("-- start cl image read kernel --\n"); + log_info("%s", kernelSource); + log_info("-- end cl image read kernel --\n"); +#endif + + /* Create kernel */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + { + return -1; + } + + + // Create a vanilla output buffer + outStream = clCreateBuffer( context, CL_MEM_READ_WRITE, channelSize * 4 * imageWidth * imageHeight, NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + + /* Assign streams and execute */ + clSamplerWrapper sampler = clCreateSampler( context, CL_FALSE, CL_ADDRESS_NONE, CL_FILTER_NEAREST, &error ); + test_error( error, "Unable to create sampler" ); + + error = clSetKernelArg( kernel, 0, sizeof( clImage ), &clImage ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( sampler ), &sampler ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, 2, sizeof( outStream ), &outStream ); + test_error( error, "Unable to set kernel arguments" ); + + glFlush(); + + error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &clImage, 0, NULL, NULL); + test_error( error, "Unable to acquire GL obejcts"); + + /* Run the kernel */ + threads[ 0 ] = imageWidth; + threads[ 1 ] = imageHeight; + + error = get_max_common_2D_work_group_size( context, kernel, threads, localThreads ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + + error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &clImage, 0, NULL, NULL ); + test_error(error, "clEnqueueReleaseGLObjects failed"); + + // Read results from the CL buffer + *outResultBuffer = malloc(channelSize * 4 * imageWidth * imageHeight); + error = clEnqueueReadBuffer( queue, outStream, CL_TRUE, 0, channelSize * 4 * imageWidth * imageHeight, + *outResultBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read output CL buffer!" ); + + return 0; +} + +static int test_image_read( cl_context context, cl_command_queue queue, GLenum glTarget, GLuint glTexture, + size_t imageWidth, size_t imageHeight, cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer ) +{ + // Create a CL image from the supplied GL texture + int error; + clMemWrapper image = (*clCreateFromGLTexture_ptr)( context, CL_MEM_READ_ONLY, glTarget, 0, glTexture, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create CL image from GL texture" ); +#ifndef GL_ES_VERSION_2_0 + GLint fmt; + glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt ); + log_error( " Supplied GL texture was baseformat %s and internalformat %s\n", GetGLBaseFormatName( fmt ), GetGLFormatName( fmt ) ); +#endif + return error; + } + + return test_cl_image_read( context, queue, image, imageWidth, imageHeight, outFormat, outType, outResultBuffer ); +} + +int test_image_format_read( cl_context context, cl_command_queue queue, + size_t width, size_t height, GLenum target, + GLenum format, GLenum internalFormat, + GLenum glType, ExplicitType type, MTdata d ) +{ + int error; + + + // Create the GL texture + glTextureWrapper glTexture; + void *tmp = CreateGLTexture2D( width, height, target, format, internalFormat, glType, type, &glTexture, &error, true, d ); + BufferOwningPtr inputBuffer(tmp); + if( error != 0 ) + { + return error; + } + + /* skip formats not supported by OpenGL */ + if(!tmp) + { + return 0; + } + + // Run and get the results + cl_image_format clFormat; + ExplicitType actualType; + char *outBuffer; + error = test_image_read( context, queue, target, glTexture, width, height, &clFormat, &actualType, (void **)&outBuffer ); + if( error != 0 ) + return error; + BufferOwningPtr actualResults(outBuffer); + + log_info( "- Read [%4d x %4d] : GL Texture : %s : %s : %s => CL Image : %s : %s \n", (int)width, (int)height, + GetGLFormatName( format ), GetGLFormatName( internalFormat ), GetGLTypeName( glType), + GetChannelOrderName( clFormat.image_channel_order ), GetChannelTypeName( clFormat.image_channel_data_type )); + + // We have to convert our input buffer to the returned type, so we can validate. + BufferOwningPtr convertedInputs(convert_to_expected( inputBuffer, width * height, type, actualType )); + + // Now we validate + int valid = 0; + if(convertedInputs) { + if( actualType == kFloat ) + valid = validate_float_results( convertedInputs, actualResults, width, height ); + else + valid = validate_integer_results( convertedInputs, actualResults, width, height, get_explicit_type_size( actualType ) ); + } + + return valid; +} + +int test_images_read( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLenum targets[] = +#ifdef GL_ES_VERSION_2_0 + { GL_TEXTURE_2D }; +#else // GL_ES_VERSION_2_0 + { GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT }; +#endif // GL_ES_VERSION_2_0 + + struct { + GLenum internal; + GLenum format; + GLenum datatype; + ExplicitType type; + + } formats[] = { + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA, GL_RGBA, GL_FLOAT, kFloat }, + }; + + size_t fmtIdx, tgtIdx; + int error = 0; + size_t iter = 6; + RandomSeed seed(gRandomSeed ); + + // Check if images are supported + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + // Loop through a set of GL formats, testing a set of sizes against each one + for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ ) + { + for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ ) + { + size_t i; + + log_info( "Testing image read for GL format %s : %s : %s : %s\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + for( i = 0; i < iter; i++ ) + { + size_t width = random_in_range( 16, 512, seed ); + size_t height = random_in_range( 16, 512, seed ); + + if( test_image_format_read( context, queue, width, height, + targets[ tgtIdx ], + formats[ fmtIdx ].format, + formats[ fmtIdx ].internal, + formats[ fmtIdx ].datatype, + formats[ fmtIdx ].type, seed ) ) + { + log_error( "ERROR: Image read test failed for %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + error++; + break; // Skip other sizes for this combination + } + } + if( i == iter ) + { + log_info( "passed: Image read for GL format %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + } + } + } + + return error; +} + +int test_images_read_cube( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLenum targets[] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; + + struct { + GLenum internal; + GLenum format; + GLenum datatype; + ExplicitType type; + + } formats[] = { +#ifdef GL_ES_VERSION_2_0 + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + // XXX add others +#else // GL_ES_VERSION_2_0 + { GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar }, + { GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort }, + { GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt }, + { GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt }, + { GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat } +#endif + }; + + size_t sizes[] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 }; + + size_t fmtIdx, tgtIdx; + int error = 0; + size_t iter = 6; + RandomSeed seed(gRandomSeed); + + // Check if images are supported + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + // Loop through a set of GL formats, testing a set of sizes against each one + for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ ) + { + for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ ) + { + size_t i; + + log_info( "Testing image read cubemap for GL format %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + for( i = 0; i < iter; i++ ) + { + if( test_image_format_read( context, queue, sizes[i], sizes[i], + targets[ tgtIdx ], + formats[ fmtIdx ].format, + formats[ fmtIdx ].internal, + formats[ fmtIdx ].datatype, + formats[ fmtIdx ].type, seed ) ) + { + log_error( "ERROR: Image read cubemap test failed for %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + error++; + break; // Skip other sizes for this combination + } + } + if( i == iter ) + { + log_info( "passed: Image read cubemap for GL format %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + } + else + break; // Skip other cube map targets; they're unlikely to pass either + } + } + + return error; +} + + +#pragma mark -------------------- Write tests ------------------------- + + +int test_cl_image_write( cl_context context, cl_command_queue queue, cl_mem clImage, + size_t imageWidth, size_t imageHeight, cl_image_format *outFormat, ExplicitType *outType, void **outSourceBuffer, MTdata d ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper inStream; + + int error; + size_t threads[ 2 ], localThreads[ 2 ]; + char kernelSource[10240]; + char *programPtr; + + // Determine data type and format that CL came up with + error = clGetImageInfo( clImage, CL_IMAGE_FORMAT, sizeof( cl_image_format ), outFormat, NULL ); + test_error( error, "Unable to get CL image format" ); + + /* Create the source */ + *outType = get_write_kernel_type( outFormat ); + size_t channelSize = get_explicit_type_size( *outType ); + + const char* suffix = get_kernel_suffix( outFormat ); + const char* convert = get_write_conversion( outFormat, *outType ); + + sprintf( kernelSource, imageWriteKernelPattern, get_explicit_type_name( *outType ), get_explicit_type_name( *outType ), suffix, convert); + +#ifdef GLES_DEBUG + log_info("-- start cl image write kernel --\n"); + log_info("%s", kernelSource); + log_info("-- end cl image write kernel --\n"); +#endif + + /* Create kernel */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + { + return -1; + } + + // Generate some source data based on the input type we need + *outSourceBuffer = CreateRandomData(*outType, imageWidth * imageHeight * 4, d); + + // Create a vanilla input buffer + inStream = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, channelSize * 4 * imageWidth * imageHeight, *outSourceBuffer, &error ); + test_error( error, "Unable to create output buffer" ); + + /* Assign streams and execute */ + clSamplerWrapper sampler = clCreateSampler( context, CL_FALSE, CL_ADDRESS_NONE, CL_FILTER_NEAREST, &error ); + test_error( error, "Unable to create sampler" ); + + error = clSetKernelArg( kernel, 0, sizeof( inStream ), &inStream ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( clImage ), &clImage ); + test_error( error, "Unable to set kernel arguments" ); + + glFlush(); + + error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &clImage, 0, NULL, NULL); + test_error( error, "Unable to acquire GL obejcts"); + + /* Run the kernel */ + threads[ 0 ] = imageWidth; + threads[ 1 ] = imageHeight; + + error = get_max_common_2D_work_group_size( context, kernel, threads, localThreads ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + clEventWrapper event; + error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &clImage, 0, NULL, &event ); + test_error(error, "clEnqueueReleaseGLObjects failed"); + + error = clWaitForEvents( 1, &event ); + test_error(error, "clWaitForEvents failed"); + +#ifdef GLES_DEBUG + int i; + size_t origin[] = {0, 0, 0,}; + size_t region[] = {imageWidth, imageHeight, 1 }; + void* cldata = malloc( channelSize * 4 * imageWidth * imageHeight ); + clEnqueueReadImage( queue, clImage, 1, origin, region, 0, 0, cldata, 0, 0, 0); + log_info("- start CL Image Data -- \n"); + DumpGLBuffer(GetGLTypeForExplicitType(*outType), imageWidth, imageHeight, cldata); + log_info("- end CL Image Data -- \n"); + free(cldata); +#endif + + // All done! + return 0; +} + +int test_image_write( cl_context context, cl_command_queue queue, GLenum glTarget, GLuint glTexture, + size_t imageWidth, size_t imageHeight, cl_image_format *outFormat, ExplicitType *outType, void **outSourceBuffer, MTdata d ) +{ + int error; + + // Create a CL image from the supplied GL texture + clMemWrapper image = (*clCreateFromGLTexture_ptr)( context, CL_MEM_WRITE_ONLY, glTarget, 0, glTexture, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create CL image from GL texture" ); +#ifndef GL_ES_VERSION_2_0 + GLint fmt; + glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt ); + log_error( " Supplied GL texture was baseformat %s and internalformat %s\n", GetGLBaseFormatName( fmt ), GetGLFormatName( fmt ) ); +#endif + return error; + } + + return test_cl_image_write( context, queue, image, imageWidth, imageHeight, outFormat, outType, outSourceBuffer, d ); +} + + +int test_image_format_write( cl_context context, cl_command_queue queue, + size_t width, size_t height, GLenum target, + GLenum format, GLenum internalFormat, + GLenum glType, ExplicitType type, MTdata d ) +{ + int error; + + // Create the GL texture + glTextureWrapper glTexture; + void *tmp = CreateGLTexture2D( width, height, target, format, internalFormat, glType, type, &glTexture, &error, true, d ); + BufferOwningPtr inputBuffer(tmp); + if( error != 0 ) + { + return error; + } + + /* skip formats not supported by OpenGL */ + if(!tmp) + { + return 0; + } + + // Run and get the results + cl_image_format clFormat; + ExplicitType sourceType; + void *outSourceBuffer; + error = test_image_write( context, queue, target, glTexture, width, height, &clFormat, &sourceType, (void **)&outSourceBuffer, d ); + if( error != 0 ) + return error; + + BufferOwningPtr actualSource(outSourceBuffer); + + log_info( "- Write [%4d x %4d] : GL Texture : %s : %s : %s => CL Image : %s : %s \n", (int)width, (int)height, + GetGLFormatName( format ), GetGLFormatName( internalFormat ), GetGLTypeName( glType), + GetChannelOrderName( clFormat.image_channel_order ), GetChannelTypeName( clFormat.image_channel_data_type )); + + // Now read the results from the GL texture + ExplicitType readType = type; + BufferOwningPtr glResults( ReadGLTexture( target, glTexture, format, internalFormat, glType, readType, width, height ) ); + + // We have to convert our input buffer to the returned type, so we can validate. + BufferOwningPtr convertedGLResults( convert_to_expected( glResults, width * height, readType, sourceType ) ); + +#ifdef GLES_DEBUG + log_info("- start read GL data -- \n"); + DumpGLBuffer(glType, width, height, glResults); + log_info("- end read GL data -- \n"); + + log_info("- start converted data -- \n"); + DumpGLBuffer(glType, width, height, convertedGLResults); + log_info("- end converted data -- \n"); +#endif + + // Now we validate + int valid = 0; + if(convertedGLResults) { + if( sourceType == kFloat ) + valid = validate_float_results( actualSource, convertedGLResults, width, height ); + else + valid = validate_integer_results( actualSource, convertedGLResults, width, height, get_explicit_type_size( readType ) ); + } + + return valid; +} + +int test_images_write( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLenum targets[] = +#ifdef GL_ES_VERSION_2_0 + { GL_TEXTURE_2D }; +#else // GL_ES_VERSION_2_0 + { GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT }; +#endif + + struct { + GLenum internal; + GLenum format; + GLenum datatype; + ExplicitType type; + + } formats[] = { +#ifdef GL_ES_VERSION_2_0 + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + // XXX add others +#else // GL_ES_VERSION_2_0 + { GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar }, + { GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort }, + { GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt }, + { GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt }, + { GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat } +#endif + }; + + size_t fmtIdx, tgtIdx; + int error = 0; + size_t iter = 6; + RandomSeed seed(gRandomSeed); + + // Check if images are supported + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + // Loop through a set of GL formats, testing a set of sizes against each one + for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ ) + { + for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ ) + { + log_info( "Testing image write test for %s : %s : %s : %s\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + size_t i; + for( i = 0; i < iter; i++ ) + { + size_t width = random_in_range( 16, 512, seed ); + size_t height = random_in_range( 16, 512, seed ); + + if( targets[ tgtIdx ] == GL_TEXTURE_2D ) + width = height; + + if( test_image_format_write( context, queue, width, height, + targets[ tgtIdx ], + formats[ fmtIdx ].format, + formats[ fmtIdx ].internal, + formats[ fmtIdx ].datatype, + formats[ fmtIdx ].type, seed ) ) + { + log_error( "ERROR: Image write test failed for %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + error++; + break; // Skip other sizes for this combination + } + } + if( i == 6 ) + { + log_info( "passed: Image write for GL format %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + } + } + } + + return error; +} + +int test_images_write_cube( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLenum targets[] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; + + struct { + GLenum internal; + GLenum format; + GLenum datatype; + ExplicitType type; + + } formats[] = { +#ifdef GL_ES_VERSION_2_0 + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + // XXX add others +#else // GL_ES_VERSION_2_0 + { GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar }, + { GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort }, + { GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt }, + { GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt }, + { GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat } +#endif + }; + + size_t sizes[] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 }; + + size_t fmtIdx, tgtIdx; + int error = 0; + size_t iter = 6; + RandomSeed seed( gRandomSeed ); + + // Check if images are supported + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + // Loop through a set of GL formats, testing a set of sizes against each one + for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ ) + { + for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ ) + { + size_t i; + log_info( "Testing image write cubemap test for %s : %s : %s : %s\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + for( i = 0; i < iter; i++ ) + { + if( test_image_format_write( context, queue, sizes[i], sizes[i], + targets[ tgtIdx ], + formats[ fmtIdx ].format, + formats[ fmtIdx ].internal, + formats[ fmtIdx ].datatype, + formats[ fmtIdx ].type, seed ) ) + { + log_error( "ERROR: Image write cubemap test failed for %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + + error++; + break; // Skip other sizes for this combination + } + } + if( i == iter ) + { + log_info( "passed: Image write cubemap for GL format %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + } + else + break; // Skip other cube map targets; they're unlikely to pass either + } + } + + return error; +} diff --git a/test_conformance/gles/test_images_2D_info.cpp b/test_conformance/gles/test_images_2D_info.cpp new file mode 100644 index 00000000..ce6717e6 --- /dev/null +++ b/test_conformance/gles/test_images_2D_info.cpp @@ -0,0 +1,256 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +#include "gl_headers.h" + +extern "C" {extern cl_uint gRandomSeed;}; + +static int test_image_read( cl_context context, cl_command_queue queue, GLenum glTarget, GLuint glTexture, + size_t imageWidth, size_t imageHeight, cl_image_format *outFormat, + ExplicitType *outType, void **outResultBuffer ) +{ + // Create a CL image from the supplied GL texture + int error; + clMemWrapper image = (*clCreateFromGLTexture_ptr)( context, CL_MEM_READ_ONLY, glTarget, 0, glTexture, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create CL image from GL texture" ); +#ifndef GL_ES_VERSION_2_0 + GLint fmt; + glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt ); + log_error( " Supplied GL texture was baseformat %s and internalformat %s\n", GetGLBaseFormatName( fmt ), GetGLFormatName( fmt ) ); +#endif + return error; + } + + // Determine data type and format that CL came up with + error = clGetImageInfo( image, CL_IMAGE_FORMAT, sizeof( cl_image_format ), outFormat, NULL ); + test_error( error, "Unable to get CL image format" ); + + return CheckGLObjectInfo(image, CL_GL_OBJECT_TEXTURE2D, glTexture, glTarget, 0); +} + +static int test_image_object_info( cl_context context, cl_command_queue queue, + size_t width, size_t height, GLenum target, + GLenum format, GLenum internalFormat, + GLenum glType, ExplicitType type, MTdata d ) +{ + int error; + + // Create the GL texture + glTextureWrapper glTexture; + void *tmp = CreateGLTexture2D( width, height, target, format, internalFormat, glType, type, &glTexture, &error, true, d ); + BufferOwningPtr inputBuffer(tmp); + if( error != 0 ) + { + // GL_RGBA_INTEGER_EXT doesn't exist in GLES2. No need to check for it. + return error; + } + + /* skip formats not supported by OpenGL */ + if(!tmp) + { + return 0; + } + + // Run and get the results + cl_image_format clFormat; + ExplicitType actualType; + char *outBuffer; + error = test_image_read( context, queue, target, glTexture, width, height, &clFormat, &actualType, (void **)&outBuffer ); + + return error; +} + +int test_images_2D_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLenum targets[] = +#ifdef GL_ES_VERSION_2_0 + { GL_TEXTURE_2D }; +#else // GL_ES_VERSION_2_0 + { GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT }; +#endif // GL_ES_VERSION_2_0 + + struct { + GLenum internal; + GLenum format; + GLenum datatype; + ExplicitType type; + + } formats[] = { + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES, kHalf }, + { GL_RGBA, GL_RGBA, GL_FLOAT, kFloat }, + }; + + size_t sizes[] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 }; + + size_t fmtIdx, tgtIdx; + int error = 0; + size_t iter = 6; + RandomSeed seed( gRandomSeed ); + + // Check if images are supported + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + // Loop through a set of GL formats, testing a set of sizes against each one + for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ ) + { + for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ ) + { + size_t i; + log_info( "Testing image texture object info test for %s : %s : %s : %s\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + for( i = 0; i < iter; i++ ) + { + if( test_image_object_info( context, queue, sizes[i], sizes[i], + targets[ tgtIdx ], + formats[ fmtIdx ].format, + formats[ fmtIdx ].internal, + formats[ fmtIdx ].datatype, + formats[ fmtIdx ].type, seed ) ) + { + log_error( "ERROR: Image texture object info test failed for %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + + error++; + break; // Skip other sizes for this combination + } + } + if( i == iter ) + { + log_info( "passed: Image texture object info test passed for %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + } + else + break; // Skip other cube map targets; they're unlikely to pass either + } + } + + return error; +} +int test_images_cube_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLenum targets[] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; + + struct { + GLenum internal; + GLenum format; + GLenum datatype; + ExplicitType type; + + } formats[] = { +#ifdef GL_ES_VERSION_2_0 + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + // XXX add others +#else // GL_ES_VERSION_2_0 + { GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar }, + { GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort }, + { GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt }, + { GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt }, + { GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat } +#endif + }; + + size_t sizes[] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 }; + + size_t fmtIdx, tgtIdx; + int error = 0; + size_t iter = 6; + RandomSeed seed( gRandomSeed ); + + // Check if images are supported + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + // Loop through a set of GL formats, testing a set of sizes against each one + for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ ) + { + for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ ) + { + size_t i; + log_info( "Testing cube map object info test for %s : %s : %s : %s\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + for( i = 0; i < iter; i++ ) + { + if( test_image_object_info( context, queue, sizes[i], sizes[i], + targets[ tgtIdx ], + formats[ fmtIdx ].format, + formats[ fmtIdx ].internal, + formats[ fmtIdx ].datatype, + formats[ fmtIdx ].type, seed ) ) + { + log_error( "ERROR: Cube map object info test failed for %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + + error++; + break; // Skip other sizes for this combination + } + } + if( i == iter ) + { + log_info( "passed: Cube map object info test passed for %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + } + else + break; // Skip other cube map targets; they're unlikely to pass either + } + } + + return error; +} diff --git a/test_conformance/gles/test_images_3D.cpp b/test_conformance/gles/test_images_3D.cpp new file mode 100644 index 00000000..7babc91e --- /dev/null +++ b/test_conformance/gles/test_images_3D.cpp @@ -0,0 +1,268 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" + +#include "gl_headers.h" + +extern "C" { extern cl_uint gRandomSeed; }; + +static const char *imageReadKernelPattern = +"__kernel void sample_test( read_only image3d_t source, sampler_t sampler, __global %s4 *results )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int tidY = get_global_id(1);\n" +" int tidZ = get_global_id(2);\n" +" int width = get_image_width( source );\n" +" int height = get_image_height( source );\n" +" int offset = tidZ * width * height + tidY * width + tidX;\n" +"\n" +" results[ offset ] = read_image%s( source, sampler, (int4)( tidX, tidY, tidZ, 0 ) );\n" +"}\n"; + +static int test_image_read( cl_context context, cl_command_queue queue, GLenum glTarget, GLuint glTexture, + size_t imageWidth, size_t imageHeight, size_t imageDepth, + cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[ 2 ]; + + int error; + size_t threads[ 3 ], localThreads[ 3 ]; + char kernelSource[1024]; + char *programPtr; + + + // Create a CL image from the supplied GL texture + streams[ 0 ] = (*clCreateFromGLTexture_ptr)( context, CL_MEM_READ_ONLY, glTarget, 0, glTexture, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create CL image from GL texture" ); +#ifndef GL_ES_VERSION_2_0 + GLint fmt; + glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt ); + log_error( " Supplied GL texture was format %s\n", GetGLFormatName( fmt ) ); +#endif + return error; + } + + // Determine data type and format that CL came up with + error = clGetImageInfo( streams[ 0 ], CL_IMAGE_FORMAT, sizeof( cl_image_format ), outFormat, NULL ); + test_error( error, "Unable to get CL image format" ); + + /* Create the source */ + *outType = get_read_kernel_type( outFormat ); + size_t channelSize = get_explicit_type_size( *outType ); + + sprintf( kernelSource, imageReadKernelPattern, get_explicit_type_name( *outType ), get_kernel_suffix( outFormat ) ); + + /* Create kernel */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + { + return -1; + } + + + // Create a vanilla output buffer + streams[ 1 ] = clCreateBuffer( context, CL_MEM_READ_WRITE, channelSize * 4 * imageWidth * imageHeight * imageDepth, NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + + /* Assign streams and execute */ + clSamplerWrapper sampler = clCreateSampler( context, CL_FALSE, CL_ADDRESS_NONE, CL_FILTER_NEAREST, &error ); + test_error( error, "Unable to create sampler" ); + + error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( sampler ), &sampler ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, 2, sizeof( streams[ 1 ] ), &streams[ 1 ] ); + test_error( error, "Unable to set kernel arguments" ); + + glFlush(); + + error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &streams[ 0 ], 0, NULL, NULL); + test_error( error, "Unable to acquire GL obejcts"); + + /* Run the kernel */ + threads[ 0 ] = imageWidth; + threads[ 1 ] = imageHeight; + threads[ 2 ] = imageDepth; + + error = get_max_common_3D_work_group_size( context, kernel, threads, localThreads ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 3, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + + error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &streams[ 0 ], 0, NULL, NULL ); + test_error(error, "clEnqueueReleaseGLObjects failed"); + + // Read results from the CL buffer + *outResultBuffer = (void *)( new char[ channelSize * 4 * imageWidth * imageHeight * imageDepth ] ); + error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, channelSize * 4 * imageWidth * imageHeight * imageDepth, + *outResultBuffer, 0, NULL, NULL ); + test_error( error, "Unable to read output CL buffer!" ); + + return 0; +} + +int test_image_format_read( cl_context context, cl_command_queue queue, + size_t width, size_t height, size_t depth, + GLenum target, GLenum format, GLenum internalFormat, + GLenum glType, ExplicitType type, MTdata d ) +{ + int error; + + + // Create the GL texture + glTextureWrapper glTexture; + void* tmp = CreateGLTexture3D( width, height, depth, target, format, internalFormat, glType, type, &glTexture, &error, d ); + BufferOwningPtr inputBuffer(tmp); + if( error != 0 ) + { + return error; + } + + /* skip formats not supported by OpenGL */ + if(!tmp) + { + return 0; + } + + // Run and get the results + cl_image_format clFormat; + ExplicitType actualType; + char *outBuffer; + error = test_image_read( context, queue, target, glTexture, width, height, depth, &clFormat, &actualType, (void **)&outBuffer ); + if( error != 0 ) + return error; + BufferOwningPtr actualResults(outBuffer); + + log_info( "- Read [%4d x %4d x %4d] : GL Texture : %s : %s : %s => CL Image : %s : %s \n", + (int)width, (int)height, (int)depth, + GetGLFormatName( format ), GetGLFormatName( internalFormat ), GetGLTypeName( glType), + GetChannelOrderName( clFormat.image_channel_order ), GetChannelTypeName( clFormat.image_channel_data_type )); + + // We have to convert our input buffer to the returned type, so we can validate. + // This is necessary because OpenCL might not actually pick an internal format that actually matches our + // input format (for example, if it picks a normalized format, the results will come out as floats instead of + // going in as ints). + + BufferOwningPtr convertedInputs(convert_to_expected( inputBuffer, width * height * depth, type, actualType )); + if( convertedInputs == NULL ) + return -1; + + // Now we validate + if( actualType == kFloat ) + return validate_float_results( convertedInputs, actualResults, width, height, depth ); + else + return validate_integer_results( convertedInputs, actualResults, width, height, depth, get_explicit_type_size( actualType ) ); +} + + +int test_images_read_3D( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLenum targets[] = { GL_TEXTURE_3D }; + + struct { + GLenum internal; + GLenum format; + GLenum datatype; + ExplicitType type; + + } formats[] = { +#ifdef GL_ES_VERSION_2_0 + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + // XXX add others +#else // GL_ES_VERSION_2_0 + { GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar }, + { GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort }, + { GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt }, + { GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt }, + { GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat } +#endif + }; + + size_t sizes[] = { 2, 4, 8, 16, 32, 64, 128 }; + size_t fmtIdx, tgtIdx; + int error = 0; + RandomSeed seed(gRandomSeed); + + size_t iter = sizeof(sizes)/sizeof(sizes[0]); + + // Check if images are supported + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + // Loop through a set of GL formats, testing a set of sizes against each one + for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ ) + { + for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ ) + { + size_t i; + + log_info( "Testing image read for GL format %s : %s : %s : %s\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + for( i = 0; i < iter; i++ ) + { + if( test_image_format_read( context, queue, sizes[i], sizes[i], sizes[i], + targets[ tgtIdx ], + formats[ fmtIdx ].format, + formats[ fmtIdx ].internal, + formats[ fmtIdx ].datatype, + formats[ fmtIdx ].type, seed ) ) + { + log_error( "ERROR: Image read test failed for %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + error++; + break; // Skip other sizes for this combination + } + } + if( i == sizeof (sizes) / sizeof( sizes[0] ) ) + { + log_info( "passed: Image read test for GL format %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + } + } + } + + return error; +} + diff --git a/test_conformance/gles/test_images_3D_info.cpp b/test_conformance/gles/test_images_3D_info.cpp new file mode 100644 index 00000000..f2e98c01 --- /dev/null +++ b/test_conformance/gles/test_images_3D_info.cpp @@ -0,0 +1,166 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "gl_headers.h" +#include "testBase.h" + +extern "C" {extern cl_uint gRandomSeed;}; + +static int test_image_read( cl_context context, cl_command_queue queue, GLenum glTarget, GLuint glTexture, + size_t imageWidth, size_t imageHeight, size_t imageDepth, cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer ) +{ + clMemWrapper streams[ 2 ]; + + int error; + + // Create a CL image from the supplied GL texture + streams[ 0 ] = (*clCreateFromGLTexture_ptr)( context, CL_MEM_READ_ONLY, glTarget, 0, glTexture, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create CL image from GL texture" ); +#ifndef GL_ES_VERSION_2_0 + GLint fmt; + glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt ); + log_error( " Supplied GL texture was format %s\n", GetGLFormatName( fmt ) ); +#endif + return error; + } + + // Determine data type and format that CL came up with + error = clGetImageInfo( streams[ 0 ], CL_IMAGE_FORMAT, sizeof( cl_image_format ), outFormat, NULL ); + test_error( error, "Unable to get CL image format" ); + + return CheckGLObjectInfo(streams[0], CL_GL_OBJECT_TEXTURE3D, glTexture, glTarget, 0); +} + +static int test_image_format_read( cl_context context, cl_command_queue queue, + size_t width, size_t height, size_t depth, + GLenum target, GLenum format, GLenum internalFormat, + GLenum glType, ExplicitType type, MTdata d ) +{ + int error; + + + // Create the GL texture + glTextureWrapper glTexture; + void* tmp = CreateGLTexture3D( width, height, depth, target, format, internalFormat, glType, type, &glTexture, &error, d, true ); + BufferOwningPtr inputBuffer(tmp); + if( error != 0 ) + { + return error; + } + + /* skip formats not supported by OpenGL */ + if(!tmp) + { + return 0; + } + + // Run and get the results + cl_image_format clFormat; + ExplicitType actualType; + char *outBuffer; + return test_image_read( context, queue, target, glTexture, width, height, depth, &clFormat, &actualType, (void **)&outBuffer ); +} + + +int test_images_3D_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLenum targets[] = { GL_TEXTURE_3D }; + + struct { + GLenum internal; + GLenum format; + GLenum datatype; + ExplicitType type; + + } formats[] = { +#ifdef GL_ES_VERSION_2_0 + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, +// { GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar }, +// { GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort }, +// { GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt }, +// { GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar }, +// { GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort }, +// { GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt }, +// { GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat } +#else // GL_ES_VERSION_2_0 + { GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar }, + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar }, + { GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort }, + { GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt }, + { GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort }, + { GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt }, + { GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat } +#endif + }; + + size_t sizes[] = { 2, 4, 8, 16, 32, 64, 128 }; + + size_t fmtIdx, tgtIdx; + int error = 0; + RandomSeed seed(gRandomSeed); + + size_t iter = sizeof(sizes)/sizeof(sizes[0]); + + // Check if images are supported + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + // Loop through a set of GL formats, testing a set of sizes against each one + for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ ) + { + for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ ) + { + size_t i; + + log_info( "Testing image info for GL format %s : %s : %s : %s\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + for( i = 0; i < iter; i++ ) + { + if( test_image_format_read( context, queue, sizes[i], sizes[i], sizes[i], + targets[ tgtIdx ], + formats[ fmtIdx ].format, + formats[ fmtIdx ].internal, + formats[ fmtIdx ].datatype, + formats[ fmtIdx ].type, seed ) ) + { + log_error( "ERROR: Image info test failed for %s : %s : %s : %s\n\n", + GetGLTargetName( targets[ tgtIdx ] ), + GetGLFormatName( formats[ fmtIdx ].internal ), + GetGLBaseFormatName( formats[ fmtIdx ].format ), + GetGLTypeName( formats[ fmtIdx ].datatype ) ); + + error++; + break; // Skip other sizes for this combination + } + } + } + } + + return error; +} + diff --git a/test_conformance/gles/test_renderbuffer.cpp b/test_conformance/gles/test_renderbuffer.cpp new file mode 100644 index 00000000..b4c6f148 --- /dev/null +++ b/test_conformance/gles/test_renderbuffer.cpp @@ -0,0 +1,373 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "helpers.h" + +#include "gl_headers.h" + +extern "C" { extern cl_uint gRandomSeed; }; + +extern int test_cl_image_write( cl_context context, cl_command_queue queue, cl_mem clImage, + size_t imageWidth, size_t imageHeight, cl_image_format *outFormat, + ExplicitType *outType, void **outSourceBuffer, MTdata d ); + +extern int test_cl_image_read( cl_context context, cl_command_queue queue, cl_mem clImage, + size_t imageWidth, size_t imageHeight, cl_image_format *outFormat, + ExplicitType *outType, void **outResultBuffer ); + +static int test_attach_renderbuffer_read_image( cl_context context, cl_command_queue queue, GLenum glTarget, GLuint glRenderbuffer, + size_t imageWidth, size_t imageHeight, cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer ) +{ + int error; + + // Create a CL image from the supplied GL renderbuffer + clMemWrapper image = (*clCreateFromGLRenderbuffer_ptr)( context, CL_MEM_READ_ONLY, glRenderbuffer, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create CL image from GL renderbuffer" ); + return error; + } + + return test_cl_image_read( context, queue, image, imageWidth, imageHeight, outFormat, outType, outResultBuffer ); +} + +int test_renderbuffer_read_image( cl_context context, cl_command_queue queue, + GLsizei width, GLsizei height, GLenum attachment, + GLenum rbFormat, GLenum rbType, + GLenum texFormat, GLenum texType, + ExplicitType type, MTdata d ) +{ + int error; + + + // Create the GL renderbuffer + glFramebufferWrapper glFramebuffer; + glRenderbufferWrapper glRenderbuffer; + void *tmp = CreateGLRenderbuffer( width, height, attachment, rbFormat, rbType, texFormat, texType, + type, &glFramebuffer, &glRenderbuffer, &error, d, true ); + BufferOwningPtr inputBuffer(tmp); + if( error != 0 ) + { + // GL_RGBA_INTEGER_EXT doesn't exist in GLES2. No need to check for it. + return error; + } + + // Run and get the results + cl_image_format clFormat; + ExplicitType actualType; + char *outBuffer; + error = test_attach_renderbuffer_read_image( context, queue, attachment, glRenderbuffer, width, height, &clFormat, &actualType, (void **)&outBuffer ); + if( error != 0 ) + return error; + BufferOwningPtr actualResults(outBuffer); + + log_info( "- Read [%4d x %4d] : GL renderbuffer : %s : %s : %s => CL Image : %s : %s \n", width, height, + GetGLFormatName( rbFormat ), GetGLFormatName( rbFormat ), GetGLTypeName( rbType ), + GetChannelOrderName( clFormat.image_channel_order ), GetChannelTypeName( clFormat.image_channel_data_type )); + +#ifdef GLES_DEBUG + log_info("- start read GL data -- \n"); + DumpGLBuffer(glType, width, height, actualResults); + log_info("- end read GL data -- \n"); +#endif + + // We have to convert our input buffer to the returned type, so we can validate. + BufferOwningPtr convertedInput(convert_to_expected( inputBuffer, width * height, type, actualType )); + +#ifdef GLES_DEBUG + log_info("- start input data -- \n"); + DumpGLBuffer(GetGLTypeForExplicitType(actualType), width, height, convertedInput); + log_info("- end input data -- \n"); +#endif + +#ifdef GLES_DEBUG + log_info("- start converted data -- \n"); + DumpGLBuffer(GetGLTypeForExplicitType(actualType), width, height, actualResults); + log_info("- end converted data -- \n"); +#endif + + // Now we validate + int valid = 0; + if(convertedInput) { + if( actualType == kFloat ) + valid = validate_float_results( convertedInput, actualResults, width, height ); + else + valid = validate_integer_results( convertedInput, actualResults, width, height, get_explicit_type_size( actualType ) ); + } + + return valid; +} + +int test_renderbuffer_read( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLenum attachments[] = { GL_COLOR_ATTACHMENT0_EXT }; + + struct { + GLenum rbFormat; + GLenum rbType; + GLenum texFormat; + GLenum texType; + ExplicitType type; + + } formats[] = { + { GL_RGBA8_OES, GL_UNSIGNED_BYTE, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + //{ GL_RGBA16F_QCOM, GL_HALF_FLOAT_OES, GL_RGBA, GL_HALF_FLOAT_OES, kHalf }, // Half-float not supported by ReadPixels + { GL_RGBA32F, GL_FLOAT, GL_RGBA, GL_FLOAT, kFloat}, + // XXX add others + }; + + size_t fmtIdx, attIdx; + int error = 0; +#ifdef GLES_DEBUG + size_t iter = 1; +#else + size_t iter = 6; +#endif + RandomSeed seed( gRandomSeed ); + + // Check if images are supported + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + // Loop through a set of GL formats, testing a set of sizes against each one + for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ ) + { + for( attIdx = 0; attIdx < sizeof( attachments ) / sizeof( attachments[ 0 ] ); attIdx++ ) + { + size_t i; + + log_info( "Testing renderbuffer read for %s : %s : %s : %s\n", + GetGLAttachmentName( attachments[ attIdx ] ), + GetGLFormatName( formats[ fmtIdx ].rbFormat ), + GetGLBaseFormatName( formats[ fmtIdx ].rbFormat ), + GetGLTypeName( formats[ fmtIdx ].rbType ) ); + + for( i = 0; i < iter; i++ ) + { + GLsizei width = random_in_range( 16, 512, seed ); + GLsizei height = random_in_range( 16, 512, seed ); +#ifdef GLES_DEBUG + width = height = 4; +#endif + + if( test_renderbuffer_read_image( context, queue, width, height, + attachments[ attIdx ], + formats[ fmtIdx ].rbFormat, + formats[ fmtIdx ].rbType, + formats[ fmtIdx ].texFormat, + formats[ fmtIdx ].texType, + formats[ fmtIdx ].type, seed ) ) + + { + log_error( "ERROR: Renderbuffer read test failed for %s : %s : %s : %s\n\n", + GetGLAttachmentName( attachments[ attIdx ] ), + GetGLFormatName( formats[ fmtIdx ].rbFormat ), + GetGLBaseFormatName( formats[ fmtIdx ].rbFormat ), + GetGLTypeName( formats[ fmtIdx ].rbType ) ); + + error++; + break; // Skip other sizes for this combination + } + } + if( i == iter ) + { + log_info( "passed: Renderbuffer read test passed for %s : %s : %s : %s\n\n", + GetGLAttachmentName( attachments[ attIdx ] ), + GetGLFormatName( formats[ fmtIdx ].rbFormat ), + GetGLBaseFormatName( formats[ fmtIdx ].rbFormat ), + GetGLTypeName( formats[ fmtIdx ].rbType ) ); + } + } + } + + return error; +} + + +#pragma mark -------------------- Write tests ------------------------- + +int test_attach_renderbuffer_write_to_image( cl_context context, cl_command_queue queue, GLenum glTarget, GLuint glRenderbuffer, + size_t imageWidth, size_t imageHeight, cl_image_format *outFormat, ExplicitType *outType, MTdata d, void **outSourceBuffer ) +{ + int error; + + // Create a CL image from the supplied GL renderbuffer + clMemWrapper image = (*clCreateFromGLRenderbuffer_ptr)( context, CL_MEM_WRITE_ONLY, glRenderbuffer, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create CL image from GL renderbuffer" ); + return error; + } + + return test_cl_image_write( context, queue, image, imageWidth, imageHeight, outFormat, outType, outSourceBuffer, d ); +} + +int test_renderbuffer_image_write( cl_context context, cl_command_queue queue, + GLsizei width, GLsizei height, GLenum attachment, + GLenum rbFormat, GLenum rbType, + GLenum texFormat, GLenum texType, + ExplicitType type, MTdata d) +{ + int error; + + // Create the GL renderbuffer + glFramebufferWrapper glFramebuffer; + glRenderbufferWrapper glRenderbuffer; + CreateGLRenderbuffer( width, height, attachment, rbFormat, rbType, texFormat, texType, + type, &glFramebuffer, &glRenderbuffer, &error, d, false ); + if( error != 0 ) + { + // GL_RGBA_INTEGER_EXT doesn't exist in GLES2. No need to check for it. + return error; + } + + // Run and get the results + cl_image_format clFormat; + ExplicitType sourceType; + void *outSourceBuffer; + error = test_attach_renderbuffer_write_to_image( context, queue, attachment, glRenderbuffer, width, height, &clFormat, &sourceType, d, (void **)&outSourceBuffer ); + if( error != 0 ) + return error; + + BufferOwningPtr sourceData(outSourceBuffer); + + log_info( "- Write [%4d x %4d] : GL Renderbuffer : %s : %s : %s => CL Image : %s : %s \n", width, height, + GetGLFormatName( rbFormat ), GetGLFormatName( rbFormat ), GetGLTypeName( rbType), + GetChannelOrderName( clFormat.image_channel_order ), GetChannelTypeName( clFormat.image_channel_data_type )); + + // Now read the results from the GL renderbuffer + void* tmp = ReadGLRenderbuffer( glFramebuffer, glRenderbuffer, attachment, rbFormat, rbType, + texFormat, texType, type, width, height ); + BufferOwningPtr resultData( tmp ); + +#ifdef GLES_DEBUG + log_info("- start result data -- \n"); + DumpGLBuffer(glType, width, height, resultData); + log_info("- end result data -- \n"); +#endif + + // We have to convert our input buffer to the returned type, so we can validate. + BufferOwningPtr convertedData( convert_to_expected( resultData, width * height, type, sourceType ) ); + +#ifdef GLES_DEBUG + log_info("- start input data -- \n"); + DumpGLBuffer(GetGLTypeForExplicitType(sourceType), width, height, sourceData); + log_info("- end input data -- \n"); +#endif + +#ifdef GLES_DEBUG + log_info("- start converted data -- \n"); + DumpGLBuffer(GetGLTypeForExplicitType(sourceType), width, height, convertedData); + log_info("- end converted data -- \n"); +#endif + + // Now we validate + int valid = 0; + if(convertedData) { + if( sourceType == kFloat ) + valid = validate_float_results( sourceData, convertedData, width, height ); + else + valid = validate_integer_results( sourceData, convertedData, width, height, get_explicit_type_size( type ) ); + } + + return valid; +} + +int test_renderbuffer_write( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLenum attachments[] = { GL_COLOR_ATTACHMENT0_EXT }; + + struct { + GLenum rbFormat; + GLenum rbType; + GLenum texFormat; + GLenum texType; + ExplicitType type; + + } formats[] = { + { GL_RGBA8_OES, GL_UNSIGNED_BYTE, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + //{ GL_RGBA16F_QCOM, GL_UNSIGNED_SHORT, GL_RGBA, GL_UNSIGNED_SHORT, kHalf }, // Half float not supported by ReadPixels + { GL_RGBA32F, GL_FLOAT, GL_RGBA, GL_FLOAT, kFloat}, + // XXX add others + }; + + size_t fmtIdx, attIdx; + int error = 0; + size_t iter = 6; +#ifdef GLES_DEBUG + iter = 1; +#endif + RandomSeed seed( gRandomSeed ); + + // Check if images are supported + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + // Loop through a set of GL formats, testing a set of sizes against each one + for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ ) + { + for( attIdx = 0; attIdx < sizeof( attachments ) / sizeof( attachments[ 0 ] ); attIdx++ ) + { + log_info( "Testing Renderbuffer write test for %s : %s : %s : %s\n", + GetGLAttachmentName( attachments[ attIdx ] ), + GetGLFormatName( formats[ fmtIdx ].rbFormat ), + GetGLBaseFormatName( formats[ fmtIdx ].rbFormat ), + GetGLTypeName( formats[ fmtIdx ].rbType) ); + + size_t i; + for( i = 0; i < iter; i++ ) + { + GLsizei width = random_in_range( 16, 512, seed ); + GLsizei height = random_in_range( 16, 512, seed ); +#ifdef GLES_DEBUG + width = height = 4; +#endif + + if( test_renderbuffer_image_write( context, queue, width, height, + attachments[ attIdx ], + formats[ fmtIdx ].rbFormat, + formats[ fmtIdx ].rbType, + formats[ fmtIdx ].texFormat, + formats[ fmtIdx ].texType, + formats[ fmtIdx ].type, seed ) ) + { + log_error( "ERROR: Renderbuffer write test failed for %s : %s : %s : %s\n\n", + GetGLAttachmentName( attachments[ attIdx ] ), + GetGLFormatName( formats[ fmtIdx ].rbFormat ), + GetGLBaseFormatName( formats[ fmtIdx ].rbFormat ), + GetGLTypeName( formats[ fmtIdx ].rbType ) ); + + error++; + break; // Skip other sizes for this combination + } + } + if( i == iter ) + { + log_info( "passed: Renderbuffer write test passed for %s : %s : %s : %s\n\n", + GetGLAttachmentName( attachments[ attIdx ] ), + GetGLFormatName( formats[ fmtIdx ].rbFormat ), + GetGLBaseFormatName( formats[ fmtIdx ].rbFormat ), + GetGLTypeName( formats[ fmtIdx ].rbType ) ); + } + } + } + + return error; +} diff --git a/test_conformance/gles/test_renderbuffer_info.cpp b/test_conformance/gles/test_renderbuffer_info.cpp new file mode 100644 index 00000000..4724187d --- /dev/null +++ b/test_conformance/gles/test_renderbuffer_info.cpp @@ -0,0 +1,119 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "gl_headers.h" +#include "testBase.h" + +extern "C" {extern cl_uint gRandomSeed;}; + +static int test_renderbuffer_object_info( cl_context context, cl_command_queue queue, + GLsizei width, GLsizei height, GLenum attachment, + GLenum rbFormat, GLenum rbType, + GLenum texFormat, GLenum texType, + ExplicitType type, MTdata d ) +{ + int error; + + // Create the GL render buffer + glFramebufferWrapper glFramebuffer; + glRenderbufferWrapper glRenderbuffer; + void* tmp = CreateGLRenderbuffer( width, height, attachment, rbFormat, rbType, texFormat, texType, + type, &glFramebuffer, &glRenderbuffer, &error, d, true ); + BufferOwningPtr inputBuffer(tmp); + if( error != 0 ) + return error; + + clMemWrapper image = (*clCreateFromGLRenderbuffer_ptr)(context, CL_MEM_READ_ONLY, glRenderbuffer, &error); + test_error(error, "clCreateFromGLRenderbuffer failed"); + + log_info( "- Given a GL format of %s, input type was %s, size was %d x %d\n", + GetGLFormatName( rbFormat ), + get_explicit_type_name( type ), (int)width, (int)height ); + + // Verify the expected information here. + return CheckGLObjectInfo(image, CL_GL_OBJECT_RENDERBUFFER, (GLuint)glRenderbuffer, rbFormat, 0); +} + +int test_renderbuffer_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + GLenum attachments[] = { GL_COLOR_ATTACHMENT0_EXT }; + + struct { + GLenum rbFormat; + GLenum rbType; + GLenum texFormat; + GLenum texType; + ExplicitType type; + + } formats[] = { + { GL_RGBA8_OES, GL_UNSIGNED_BYTE, GL_RGBA, GL_UNSIGNED_BYTE, kUChar }, + { GL_RGBA32F, GL_FLOAT, GL_RGBA, GL_FLOAT, kFloat } + }; + + size_t fmtIdx, tgtIdx; + int error = 0; + size_t iter = 6; + RandomSeed seed(gRandomSeed); + + // Check if images are supported + if (checkForImageSupport(device)) { + log_info("Device does not support images. Skipping test.\n"); + return 0; + } + + // Loop through a set of GL formats, testing a set of sizes against each one + for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ ) + { + for( tgtIdx = 0; tgtIdx < sizeof( attachments ) / sizeof( attachments[ 0 ] ); tgtIdx++ ) + { + log_info( "Testing Renderbuffer object info for %s : %s : %s\n", + GetGLFormatName( formats[ fmtIdx ].rbFormat ), + GetGLBaseFormatName( formats[ fmtIdx ].rbFormat ), + GetGLTypeName( formats[ fmtIdx ].type ) ); + + size_t i; + for( i = 0; i < iter; i++ ) + { + GLsizei width = random_in_range( 16, 512, seed ); + GLsizei height = random_in_range( 16, 512, seed ); + + if( test_renderbuffer_object_info( context, queue, (int)width, (int)height, + attachments[ tgtIdx ], + formats[ fmtIdx ].rbFormat, + formats[ fmtIdx ].rbType, + formats[ fmtIdx ].texFormat, + formats[ fmtIdx ].texType, + formats[ fmtIdx ].type, seed ) ) + { + log_error( "ERROR: Renderbuffer write test failed for GL format %s : %s\n\n", + GetGLFormatName( formats[ fmtIdx ].rbFormat ), + GetGLTypeName( formats[ fmtIdx ].rbType ) ); + + error++; + break; // Skip other sizes for this combination + } + } + if( i == iter ) + { + log_info( "passed: Renderbuffer write test passed for GL format %s : %s\n\n", + GetGLFormatName( formats[ fmtIdx ].rbFormat ), + GetGLTypeName( formats[ fmtIdx ].rbType ) ); + + } + } + } + + return error; +} diff --git a/test_conformance/half/CMakeLists.txt b/test_conformance/half/CMakeLists.txt new file mode 100644 index 00000000..03308d25 --- /dev/null +++ b/test_conformance/half/CMakeLists.txt @@ -0,0 +1,17 @@ +set(MODULE_NAME HALF) + +set(${MODULE_NAME}_SOURCES + cl_utils.c + Test_vLoadHalf.c + Test_roundTrip.c + Test_vStoreHalf.c main.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/mingw_compat.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/ThreadPool.c + ../../test_common/harness/parseParameters.cpp + ../../test_common/harness/kernelHelpers.c +) + +include(../CMakeCommon.txt) + diff --git a/test_conformance/half/Jamfile b/test_conformance/half/Jamfile new file mode 100644 index 00000000..22d3efac --- /dev/null +++ b/test_conformance/half/Jamfile @@ -0,0 +1,22 @@ +project + : requirements + -/harness//harness /harness//harness +# gcc:-xc++ + msvc:"/TP" + ; + +exe Test_half + : cl_utils.c + main.c + Test_roundTrip.c + Test_vLoadHalf.c + Test_vStoreHalf.c + /harness//errorHelpers.c + : windows:/harness//msvc9.c + ; + +install dist + : Test_half + : debug:$(DIST)/debug/tests/test_conformance/half + release:$(DIST)/release/tests/test_conformance/half + ; diff --git a/test_conformance/half/Makefile b/test_conformance/half/Makefile new file mode 100644 index 00000000..b9f5e71f --- /dev/null +++ b/test_conformance/half/Makefile @@ -0,0 +1,45 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCFILES = cl_utils.c Test_vLoadHalf.c Test_roundTrip.c \ + Test_vStoreHalf.c main.c + +CC = c++ +CFLAGS = -g -Wall -Wshorten-64-to-32 $(COMPILERFLAGS) ${RC_CFLAGS} \ + ${USE_ATF} + +LIBRARIES = -framework OpenCL ${RC_CFLAGS} ${ATF} + + +all: release + +OBJECTS := ${SRCFILES:.c=.o} + +release: + echo "Build Release" + $(CC) $(SRCFILES) -Os $(CFLAGS) -o Test_half $(LIBRARIES) + +debug: $(OBJECTS) + echo "Build Debug" + $(CC) $(OBJECTS) -O0 $(CFLAGS) -o Test_half_debug -D_DEBUG=1 $(LIBRARIES) + +test: release + arch -i386 ./Test_half -c > cpu.log & + arch -i386 ./Test_half -g > gpu.log & + echo "Testing 32-bit mode in progress. See cpu.log and gpu.log for results." + +test64: release + arch -x86_64 ./Test_half -c > cpu64.log & + arch -x86_64 ./Test_half -g > gpu64.log & + echo "Testing 64-bit mode in progress. See cpu64.log and gpu64.log for results." + + +clean: + rm -f ./Test_half_debug + rm -f ./Test_half + + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/half/Test_half.xcodeproj/project.pbxproj b/test_conformance/half/Test_half.xcodeproj/project.pbxproj new file mode 100644 index 00000000..d3860565 --- /dev/null +++ b/test_conformance/half/Test_half.xcodeproj/project.pbxproj @@ -0,0 +1,292 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 44; + objects = { + +/* Begin PBXBuildFile section */ + 3B1B765F0DE342BC00837A59 /* Test_vStoreHalf.c in Sources */ = {isa = PBXBuildFile; fileRef = 3B1B765E0DE342BC00837A59 /* Test_vStoreHalf.c */; }; + 3B6173C40DE2B14800384A2C /* Test_roundTrip.c in Sources */ = {isa = PBXBuildFile; fileRef = 3B6173C30DE2B14800384A2C /* Test_roundTrip.c */; }; + 3BA6BFB80DE21DB9008685CF /* Test_vLoadHalf.c in Sources */ = {isa = PBXBuildFile; fileRef = 3BA6BFB70DE21DB9008685CF /* Test_vLoadHalf.c */; }; + 3BA6BFBB0DE21EFA008685CF /* cl_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 3BA6BFBA0DE21EFA008685CF /* cl_utils.c */; }; + 3BA6BFF30DE229C5008685CF /* OpenCL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BA6BFF20DE229C5008685CF /* OpenCL.framework */; }; + 8DD76FAC0486AB0100D96B5E /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* main.c */; settings = {ATTRIBUTES = (); }; }; + 8DD76FB00486AB0100D96B5E /* Test_half.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6A0FF2C0290799A04C91782 /* Test_half.1 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76FAF0486AB0100D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + 8DD76FB00486AB0100D96B5E /* Test_half.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 08FB7796FE84155DC02AAC07 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 3B1B765E0DE342BC00837A59 /* Test_vStoreHalf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Test_vStoreHalf.c; sourceTree = ""; }; + 3B1B77910DE3896E00837A59 /* builtins.cl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = builtins.cl; path = ../../../compute/OpenCL/cl_headers/private/builtins.cl; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.c; }; + 3B6173C30DE2B14800384A2C /* Test_roundTrip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Test_roundTrip.c; sourceTree = ""; }; + 3BA6BFB70DE21DB9008685CF /* Test_vLoadHalf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Test_vLoadHalf.c; sourceTree = ""; }; + 3BA6BFB90DE21EFA008685CF /* cl_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cl_utils.h; sourceTree = ""; }; + 3BA6BFBA0DE21EFA008685CF /* cl_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_utils.c; sourceTree = ""; }; + 3BA6BFF20DE229C5008685CF /* OpenCL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenCL.framework; path = /System/Library/Frameworks/OpenCL.framework; sourceTree = ""; }; + 3BA6C00A0DE22A95008685CF /* test_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = test_config.h; sourceTree = ""; }; + 3BA6C0770DE24F41008685CF /* tests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tests.h; sourceTree = ""; }; + 8DD76FB20486AB0100D96B5E /* Test_half */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Test_half; sourceTree = BUILT_PRODUCTS_DIR; }; + C6A0FF2C0290799A04C91782 /* Test_half.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = Test_half.1; sourceTree = ""; }; + FFB9F1420E5E155400F45584 /* ATF.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ATF.framework; path = /Library/Frameworks/ATF.framework; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76FAD0486AB0100D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3BA6BFF30DE229C5008685CF /* OpenCL.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* Test_half */ = { + isa = PBXGroup; + children = ( + 3BA6C00A0DE22A95008685CF /* test_config.h */, + 3BA6C0770DE24F41008685CF /* tests.h */, + 08FB7796FE84155DC02AAC07 /* main.c */, + 08FB7795FE84155DC02AAC07 /* Source */, + 3BA6BFF80DE229CC008685CF /* Resources */, + 3B1B77910DE3896E00837A59 /* builtins.cl */, + C6A0FF2B0290797F04C91782 /* Documentation */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + FFB9F1420E5E155400F45584 /* ATF.framework */, + ); + name = Test_half; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + 3BA6BFB90DE21EFA008685CF /* cl_utils.h */, + 3BA6BFBA0DE21EFA008685CF /* cl_utils.c */, + 3BA6BFB70DE21DB9008685CF /* Test_vLoadHalf.c */, + 3B6173C30DE2B14800384A2C /* Test_roundTrip.c */, + 3B1B765E0DE342BC00837A59 /* Test_vStoreHalf.c */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8DD76FB20486AB0100D96B5E /* Test_half */, + ); + name = Products; + sourceTree = ""; + }; + 3BA6BFF80DE229CC008685CF /* Resources */ = { + isa = PBXGroup; + children = ( + 3BA6BFF20DE229C5008685CF /* OpenCL.framework */, + ); + name = Resources; + sourceTree = ""; + }; + C6A0FF2B0290797F04C91782 /* Documentation */ = { + isa = PBXGroup; + children = ( + C6A0FF2C0290799A04C91782 /* Test_half.1 */, + ); + name = Documentation; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76FA90486AB0100D96B5E /* Test_half */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB928508733DD80010E9CD /* Build configuration list for PBXNativeTarget "Test_half" */; + buildPhases = ( + 8DD76FAB0486AB0100D96B5E /* Sources */, + 8DD76FAD0486AB0100D96B5E /* Frameworks */, + 8DD76FAF0486AB0100D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Test_half; + productInstallPath = "$(HOME)/bin"; + productName = Test_half; + productReference = 8DD76FB20486AB0100D96B5E /* Test_half */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "Test_half" */; + compatibilityVersion = "Xcode 3.0"; + hasScannedForEncodings = 1; + mainGroup = 08FB7794FE84155DC02AAC07 /* Test_half */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76FA90486AB0100D96B5E /* Test_half */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76FAB0486AB0100D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8DD76FAC0486AB0100D96B5E /* main.c in Sources */, + 3BA6BFB80DE21DB9008685CF /* Test_vLoadHalf.c in Sources */, + 3BA6BFBB0DE21EFA008685CF /* cl_utils.c in Sources */, + 3B6173C40DE2B14800384A2C /* Test_roundTrip.c in Sources */, + 3B1B765F0DE342BC00837A59 /* Test_vStoreHalf.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB928608733DD80010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + INSTALL_PATH = /usr/local/bin; + PRODUCT_NAME = Test_half; + ZERO_LINK = YES; + }; + name = Debug; + }; + 1DEB928708733DD80010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PRODUCT_NAME = Test_half; + }; + name = Release; + }; + 1DEB928A08733DD80010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + ATF_Config_Comment = "Set ATF_DEFAULT to non-empty to link to ATF iff the BUILD_WITH_ATF env var is set"; + ATF_DEFAULT = SKIPPING; + ATF_DEFINES = "$(ATF_DEFINES_$(SKIPPING_ATF))"; + ATF_DEFINES_ = "USE_ATF=1"; + ATF_LINK = "$(ATF_LINK_$(SKIPPING_ATF))"; + ATF_LINK_ = "-framework ATF"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = _DEBUG; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = NO; + GCC_WARN_PEDANTIC = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; + GCC_WARN_UNINITIALIZED_AUTOS = NO; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SKIPPING_ATF = SKIPPING; + VALID_ARCHS = "i386 x86_64"; + }; + name = Debug; + }; + 1DEB928B08733DD80010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + ppc, + i386, + ); + ATF_Config_Comment = "Set ATF_DEFAULT to non-empty to link to ATF iff the BUILD_WITH_ATF env var is set"; + ATF_DEFAULT = SKIPPING; + ATF_DEFINES = "$(ATF_DEFINES_$(SKIPPING_ATF))"; + ATF_DEFINES_ = "USE_ATF=1"; + ATF_LINK = "$(ATF_LINK_$(SKIPPING_ATF))"; + ATF_LINK_ = "-framework ATF"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = NO; + GCC_WARN_PEDANTIC = NO; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; + GCC_WARN_UNINITIALIZED_AUTOS = NO; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SKIPPING_ATF = SKIPPING; + VALID_ARCHS = "i386 x86_64"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB928508733DD80010E9CD /* Build configuration list for PBXNativeTarget "Test_half" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB928608733DD80010E9CD /* Debug */, + 1DEB928708733DD80010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "Test_half" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB928A08733DD80010E9CD /* Debug */, + 1DEB928B08733DD80010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/test_conformance/half/Test_roundTrip.c b/test_conformance/half/Test_roundTrip.c new file mode 100644 index 00000000..18eb5f9f --- /dev/null +++ b/test_conformance/half/Test_roundTrip.c @@ -0,0 +1,398 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include "cl_utils.h" +#include "tests.h" + + + +int Test_roundTrip( void ) +{ + int vectorSize, error; + uint64_t i, j; + cl_program programs[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + cl_kernel kernels[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + cl_program doublePrograms[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + cl_kernel doubleKernels[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + uint64_t time[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + uint64_t min_time[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + uint64_t doubleTime[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + uint64_t min_double_time[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + memset( min_time, -1, sizeof( min_time ) ); + memset( min_double_time, -1, sizeof( min_double_time ) ); + + vlog( "Testing roundTrip\n" ); + fflush( stdout ); + + + for( vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + { + const char *source[] = { + "__kernel void test( const __global half *in, __global half *out )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " vstore_half",vector_size_name_extensions[vectorSize],"( vload_half",vector_size_name_extensions[vectorSize],"(i, in), i, out);\n" + "}\n" + }; + + const char *doubleSource[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( const __global half *in, __global half *out )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " vstore_half",vector_size_name_extensions[vectorSize],"( convert_double", vector_size_name_extensions[vectorSize], "( vload_half",vector_size_name_extensions[vectorSize],"(i, in)), i, out);\n" + "}\n" + }; + + const char *sourceV3[] = { + "__kernel void test( const __global half *in, __global half *out," + " uint extra_last_thread )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " size_t last_i = get_global_size(0)-1;\n" + " size_t adjust = 0;\n" + " if(i == last_i && extra_last_thread != 0) { \n" + " adjust = 3-extra_last_thread;\n" + " }\n" + " vstore_half3( vload_half3(i, in-adjust), i, out-adjust);\n" + "}\n" + }; + + const char *doubleSourceV3[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( const __global half *in, __global half *out," + " uint extra_last_thread )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " size_t last_i = get_global_size(0)-1;\n" + " size_t adjust = 0;\n" + " if(i == last_i && extra_last_thread != 0) { \n" + " adjust = 3-extra_last_thread;\n" + " }\n" + " vstore_half3( vload_half3(i, in-adjust), i, out-adjust);\n" + "}\n" + }; + +/* + const char *sourceV3aligned[] = { + "__kernel void test( const __global half *in, __global half *out )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " vstorea_half3( vloada_half3(i, in), i, out);\n" + " vstore_half(vload_half(4*i+3, in), 4*i+3, out);\n" + "}\n" + }; + + const char *doubleSourceV3aligned[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( const __global half *in, __global half *out )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " vstorea_half3( vloada_half3(i, in), i, out);\n" + " vstore_half(vload_half(4*i+3, in), 4*i+3, out);\n" + "}\n" + }; +*/ + + if(g_arrVecSizes[vectorSize] == 3) { + programs[vectorSize] = MakeProgram( sourceV3, sizeof( sourceV3) / sizeof( sourceV3[0]) ); + if( NULL == programs[ vectorSize ] ) + { + gFailCount++; + + return -1; + } + } else { + programs[vectorSize] = MakeProgram( source, sizeof( source) / sizeof( source[0]) ); + if( NULL == programs[ vectorSize ] ) + { + gFailCount++; + return -1; + } + } + + kernels[ vectorSize ] = clCreateKernel( programs[ vectorSize ], "test", &error ); + if( NULL == kernels[vectorSize] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create kernel. (%d)\n", error ); + return error; + } + + if( gTestDouble ) + { + if(g_arrVecSizes[vectorSize] == 3) { + doublePrograms[vectorSize] = MakeProgram( doubleSourceV3, sizeof( doubleSourceV3) / sizeof( doubleSourceV3[0]) ); + if( NULL == programs[ vectorSize ] ) + { + gFailCount++; + return -1; + } + } else { + doublePrograms[vectorSize] = MakeProgram( doubleSource, sizeof( doubleSource) / sizeof( doubleSource[0]) ); + if( NULL == programs[ vectorSize ] ) + { + gFailCount++; + return -1; + } + } + + doubleKernels[ vectorSize ] = clCreateKernel( doublePrograms[ vectorSize ], "test", &error ); + if( NULL == kernels[vectorSize] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create kernel. (%d)\n", error ); + return error; + } + } + } + + // Figure out how many elements are in a work block + size_t elementSize = MAX( sizeof(cl_half), sizeof(cl_float)); + size_t blockCount = (size_t)getBufferSize(gDevice) / elementSize; //elementSize is a power of two + uint64_t lastCase = 1ULL << (8*sizeof(cl_half)); // number of cl_half + size_t stride = blockCount; + + error = 0; + uint64_t printMask = (lastCase >> 4) - 1; + uint32_t count; + size_t loopCount; + + for( i = 0; i < (uint64_t)lastCase; i += stride ) + { + count = (uint32_t) MIN( blockCount, lastCase - i ); + + //Init the input stream + uint16_t *p = (uint16_t *)gIn_half; + for( j = 0; j < count; j++ ) + p[j] = j + i; + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer_half, CL_TRUE, 0, count * sizeof( cl_half ), gIn_half, 0, NULL, NULL)) ) + { + vlog_error( "Failure in clWriteArray\n" ); + gFailCount++; + goto exit; + } + + //Check the vector lengths + for( vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + { // here we loop through vector sizes -- 3 is last. + uint32_t pattern = 0xdeaddead; + memset_pattern4( gOut_half, &pattern, (size_t)getBufferSize(gDevice)/2); + + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer_half, CL_TRUE, 0, count * sizeof(cl_half), gOut_half, 0, NULL, NULL)) ) + { + vlog_error( "Failure in clWriteArray\n" ); + gFailCount++; + goto exit; + } + + + // here is where "3" starts to cause problems. + error = RunKernel( kernels[vectorSize], gInBuffer_half, gOutBuffer_half, numVecs(count, vectorSize, false) , + runsOverBy(count, vectorSize, false) ); + if(error) + { + gFailCount++; + goto exit; + } + + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer_half, CL_TRUE, 0, count * sizeof(cl_half), gOut_half, 0, NULL, NULL)) ) + { + vlog_error( "Failure in clReadArray\n" ); + gFailCount++; + goto exit; + } + + if( (memcmp( gOut_half, gIn_half, count * sizeof(cl_half))) ) + { + uint16_t *u1 = (uint16_t *)gOut_half; + uint16_t *u2 = (uint16_t *)gIn_half; + for( j = 0; j < count; j++ ) + { + if( u1[j] != u2[j] ) + { + uint16_t abs1 = u1[j] & 0x7fff; + uint16_t abs2 = u2[j] & 0x7fff; + if( abs1 > 0x7c00 && abs2 > 0x7c00 ) + continue; //any NaN is okay if NaN is input + + // if reference result is sub normal, test if the output is flushed to zero + if( IsHalfSubnormal(u2[j]) && ( (u1[j] == 0) || (u1[j] == 0x8000) ) ) + continue; + + vlog_error( "%lld) (of %lld) Failure at 0x%4.4x: 0x%4.4x vector_size = %d \n", j, (uint64_t)count, u2[j], u1[j], (g_arrVecSizes[vectorSize]) ); + gFailCount++; + goto exit; + } + } + } + + if( gTestDouble ) + { + memset_pattern4( gOut_half, &pattern, (size_t)getBufferSize(gDevice)/2); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer_half, CL_TRUE, 0, count * sizeof(cl_half), gOut_half, 0, NULL, NULL)) ) + { + vlog_error( "Failure in clWriteArray\n" ); + gFailCount++; + goto exit; + } + + + if( (error = RunKernel( doubleKernels[vectorSize], gInBuffer_half, gOutBuffer_half, numVecs(count, vectorSize, false) , + runsOverBy(count, vectorSize, false) ) ) ) + { + gFailCount++; + goto exit; + } + + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer_half, CL_TRUE, 0, count * sizeof(cl_half), gOut_half, 0, NULL, NULL)) ) + { + vlog_error( "Failure in clReadArray\n" ); + gFailCount++; + goto exit; + } + + if( (memcmp( gOut_half, gIn_half, count * sizeof(cl_half))) ) + { + uint16_t *u1 = (uint16_t *)gOut_half; + uint16_t *u2 = (uint16_t *)gIn_half; + for( j = 0; j < count; j++ ) + { + if( u1[j] != u2[j] ) + { + uint16_t abs1 = u1[j] & 0x7fff; + uint16_t abs2 = u2[j] & 0x7fff; + if( abs1 > 0x7c00 && abs2 > 0x7c00 ) + continue; //any NaN is okay if NaN is input + + // if reference result is sub normal, test if the output is flushed to zero + if( IsHalfSubnormal(u2[j]) && ( (u1[j] == 0) || (u1[j] == 0x8000) ) ) + continue; + + vlog_error( "%lld) Failure at 0x%4.4x: 0x%4.4x vector_size = %d (double precsion)\n", j, u2[j], u1[j], (g_arrVecSizes[vectorSize]) ); + gFailCount++; + goto exit; + } + } + } + } + } + + if( ((i+blockCount) & ~printMask) == (i+blockCount) ) + { + vlog( "." ); + fflush( stdout ); + } + } + + vlog( "\tPassed\n" ); + + loopCount = 100; + if( gReportTimes ) + { + //Run again for timing + for( vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + { + uint64_t bestTime = -1ULL; + + for( j = 0; j < loopCount; j++ ) + { + uint64_t startTime = ReadTime(); + if( (error = RunKernel( kernels[vectorSize], gInBuffer_half, gOutBuffer_half,numVecs(count, vectorSize, false) , + runsOverBy(count, vectorSize, false)) ) ) + { + gFailCount++; + goto exit; + } + + if( (error = clFinish(gQueue)) ) + { + vlog_error( "Failure in clFinish\n" ); + gFailCount++; + goto exit; + } + uint64_t currentTime = ReadTime() - startTime; + if( currentTime < bestTime ) + bestTime = currentTime; + time[ vectorSize ] += currentTime; + } + if( bestTime < min_time[ vectorSize ] ) + min_time[ vectorSize ] = bestTime; + + if( gTestDouble ) + { + bestTime = -1ULL; + for( j = 0; j < loopCount; j++ ) + { + uint64_t startTime = ReadTime(); + if( (error = RunKernel( doubleKernels[vectorSize], gInBuffer_half, gOutBuffer_half, numVecs(count, vectorSize, false) , + runsOverBy(count, vectorSize, false)) ) ) + { + gFailCount++; + goto exit; + } + + if( (error = clFinish(gQueue)) ) + { + vlog_error( "Failure in clFinish\n" ); + gFailCount++; + goto exit; + } + uint64_t currentTime = ReadTime() - startTime; + if( currentTime < bestTime ) + bestTime = currentTime; + doubleTime[ vectorSize ] += currentTime; + } + if( bestTime < min_double_time[ vectorSize ] ) + min_double_time[ vectorSize ] = bestTime; + } + } + } + + if( gReportTimes ) + { + for( vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + vlog_perf( SubtractTime( time[ vectorSize ], 0 ) * 1e6 * gDeviceFrequency * gComputeDevices / (double) (count * loopCount), 0, "average us/elem", "roundTrip avg. (vector size: %d)", (g_arrVecSizes[vectorSize]) ); + for( vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + vlog_perf( SubtractTime( min_time[ vectorSize ], 0 ) * 1e6 * gDeviceFrequency * gComputeDevices / (double) count, 0, "best us/elem", "roundTrip best (vector size: %d)", (g_arrVecSizes[vectorSize]) ); + if( gTestDouble ) + { + for( vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + vlog_perf( SubtractTime( doubleTime[ vectorSize ], 0 ) * 1e6 * gDeviceFrequency * gComputeDevices / (double) (count * loopCount), 0, "average us/elem (double)", "roundTrip avg. d (vector size: %d)", (g_arrVecSizes[vectorSize]) ); + for( vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + vlog_perf( SubtractTime( min_double_time[ vectorSize ], 0 ) * 1e6 * gDeviceFrequency * gComputeDevices / (double) count, 0, "best us/elem (double)", "roundTrip best d (vector size: %d)", (g_arrVecSizes[vectorSize]) ); + } + } + +exit: + //clean up + for( vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + { + clReleaseKernel( kernels[ vectorSize ] ); + clReleaseProgram( programs[ vectorSize ] ); + if( gTestDouble ) + { + clReleaseKernel( doubleKernels[ vectorSize ] ); + clReleaseProgram( doublePrograms[ vectorSize ] ); + } + } + + gTestCount++; + return error; +} + + diff --git a/test_conformance/half/Test_vLoadHalf.c b/test_conformance/half/Test_vLoadHalf.c new file mode 100644 index 00000000..3ca8a203 --- /dev/null +++ b/test_conformance/half/Test_vLoadHalf.c @@ -0,0 +1,628 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include "cl_utils.h" +#include "tests.h" + +extern const char *addressSpaceNames[]; + +static inline float half2float( cl_ushort us ) +{ + uint32_t u = us; + uint32_t sign = (u << 16) & 0x80000000; + int32_t exponent = (u & 0x7c00) >> 10; + uint32_t mantissa = (u & 0x03ff) << 13; + union{ unsigned int u; float f;}uu; + + if( exponent == 0 ) + { + if( mantissa == 0 ) + return sign ? -0.0f : 0.0f; + + int shift = __builtin_clz( mantissa ) - 8; + exponent -= shift-1; + mantissa <<= shift; + mantissa &= 0x007fffff; + } + else + if( exponent == 31) + { + uu.u = mantissa | sign; + if( mantissa ) + uu.u |= 0x7fc00000; + else + uu.u |= 0x7f800000; + + return uu.f; + } + + exponent += 127 - 15; + exponent <<= 23; + + exponent |= mantissa; + uu.u = exponent | sign; + + return uu.f; +} + +int Test_vLoadHalf_private( bool aligned ); + +int Test_vLoadHalf_private( bool aligned ) +{ + cl_int error; + int vectorSize; + cl_program programs[kVectorSizeCount+kStrangeVectorSizeCount][4] = {{0}}; + cl_kernel kernels[kVectorSizeCount+kStrangeVectorSizeCount][4] = {{0}}; + uint64_t time[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + uint64_t min_time[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + size_t q; + + memset( min_time, -1, sizeof( min_time ) ); + + vlog( "Testing vload%s_half\n", aligned ? "a" : "" ); + fflush( stdout ); + const char *vector_size_names[] = {"1", "2", "4", "8", "16", "3"}; + + int minVectorSize = kMinVectorSize; + // There is no aligned scalar vloada_half in CL 1.1 +#if ! defined( CL_VERSION_1_1 ) && ! defined(__APPLE__) + vlog("Note: testing vloada_half.\n"); + if (aligned && minVectorSize == 0) + minVectorSize = 1; +#endif + + for( vectorSize = minVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + { + + int effectiveVectorSize = g_arrVecSizes[vectorSize]; + if(effectiveVectorSize == 3 && aligned) { + effectiveVectorSize = 4; + } + const char *source[] = { + "__kernel void test( const __global half *p, __global float", vector_size_name_extensions[vectorSize], " *f )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " f[i] = vload", aligned ? "a" : "", "_half",vector_size_name_extensions[vectorSize],"( i, p );\n" + "}\n" + }; + + const char *sourceV3[] = { + "__kernel void test( const __global half *p, __global float *f,\n" + " uint extra_last_thread)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " size_t last_i = get_global_size(0)-1;\n" + " if(last_i == i && extra_last_thread != 0) {\n" + " if(extra_last_thread ==2) {\n" + " f[3*i+1] = vload_half(3*i+1, p);\n" + " }\n" + " f[3*i] = vload_half(3*i, p);\n" + " } else {\n" + " vstore3(vload_half3( i, p ),i,f);\n" + " }\n" + "}\n" + }; + + const char *sourceV3aligned[] = { + "__kernel void test( const __global half *p, __global float3 *f )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " f[i] = vloada_half3( i, p );\n" + " ((__global float *)f)[4*i+3] = vloada_half(4*i+3,p);\n" + "}\n" + }; + + const char *source_private1[] = { + "__kernel void test( const __global half *p, __global float *f )\n" + "{\n" + " __private ushort data[1];\n" + " __private half* hdata_p = (__private half*) data;\n" + " size_t i = get_global_id(0);\n" + " data[0] = ((__global ushort*)p)[i];\n" + " f[i] = vload", (aligned ? "a" : ""), "_half( 0, hdata_p );\n" + "}\n" + }; + + const char *source_private2[] = { + "__kernel void test( const __global half *p, __global float", vector_size_name_extensions[vectorSize], " *f )\n" + "{\n" + " __private ", align_types[vectorSize], " data[", vector_size_names[vectorSize], "/", align_divisors[vectorSize], "];\n" + " __private half* hdata_p = (__private half*) data;\n" + " __global ", align_types[vectorSize], "* i_p = (__global ", align_types[vectorSize], "*)p;\n" + " size_t i = get_global_id(0);\n" + " int k;\n" + " for (k=0; k<",vector_size_names[vectorSize],"/",align_divisors[vectorSize],"; k++)\n" + " data[k] = i_p[i+k];\n" + " f[i] = vload", aligned ? "a" : "", "_half",vector_size_name_extensions[vectorSize],"( 0, hdata_p );\n" + "}\n" + }; + + const char *source_privateV3[] = { + "__kernel void test( const __global half *p, __global float *f," + " uint extra_last_thread )\n" + "{\n" + " __private ushort data[3];\n" + " __private half* hdata_p = (__private half*) data;\n" + " __global ushort* i_p = (__global ushort*)p;\n" + " size_t i = get_global_id(0);\n" + " int k;\n" + // " data = vload3(i, i_p);\n" + " size_t last_i = get_global_size(0)-1;\n" + " if(last_i == i && extra_last_thread != 0) {\n" + " if(extra_last_thread ==2) {\n" + " f[3*i+1] = vload_half(3*i+1, p);\n" + " }\n" + " f[3*i] = vload_half(3*i, p);\n" + " } else {\n" + " for (k=0; k<3; k++)\n" + " data[k] = i_p[i*3+k];\n" + " vstore3(vload_half3( 0, hdata_p ), i, f);\n" + " }\n" + "}\n" + }; + + const char *source_privateV3aligned[] = { + "__kernel void test( const __global half *p, __global float3 *f )\n" + "{\n" + " ushort4 data[4];\n" // declare as vector for alignment. Make four to check to see vloada_half3 index is working. + " half* hdata_p = (half*) &data;\n" + " size_t i = get_global_id(0);\n" + " global ushort* i_p = (global ushort*)p + i * 4;\n" + " int offset = i & 3;\n" + " data[offset] = (ushort4)( i_p[0], i_p[1], i_p[2], USHRT_MAX ); \n" + " data[offset^1] = USHRT_MAX; \n" + " data[offset^2] = USHRT_MAX; \n" + " data[offset^3] = USHRT_MAX; \n" + // test vloada_half3 + " f[i] = vloada_half3( offset, hdata_p );\n" + // Fill in the 4th value so we don't have to special case this code elsewhere in the test. + " mem_fence(CLK_GLOBAL_MEM_FENCE );\n" + " ((__global float *)f)[4*i+3] = vload_half(4*i+3, p);\n" + "}\n" + }; + + char local_buf_size[10]; + + sprintf(local_buf_size, "%lld", (uint64_t)((effectiveVectorSize))*gWorkGroupSize); + const char *source_local1[] = { + "__kernel void test( const __global half *p, __global float *f )\n" + "{\n" + " __local ushort data[",local_buf_size,"];\n" + " __local half* hdata_p = (__local half*) data;\n" + " size_t i = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " data[lid] = ((__global ushort*)p)[i];\n" + " f[i] = vload", aligned ? "a" : "", "_half( lid, hdata_p );\n" + "}\n" + }; + + const char *source_local2[] = { + "__kernel void test( const __global half *p, __global float", vector_size_name_extensions[vectorSize], " *f )\n" + "{\n" + " __local ", align_types[vectorSize], " data[", local_buf_size, "/", align_divisors[vectorSize], "];\n" + " __local half* hdata_p = (__local half*) data;\n" + " __global ", align_types[vectorSize], "* i_p = (__global ", align_types[vectorSize],"*)p;\n" + " size_t i = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " int k;\n" + " for (k=0; k<",vector_size_names[vectorSize],"/",align_divisors[vectorSize],"; k++)\n" + " data[lid*",vector_size_names[vectorSize],"/",align_divisors[vectorSize],"+k] = i_p[i*",vector_size_names[vectorSize],"/",align_divisors[vectorSize],"+k];\n" + " f[i] = vload", aligned ? "a" : "", "_half",vector_size_name_extensions[vectorSize],"( lid, hdata_p );\n" + "}\n" + }; + + const char *source_localV3[] = { + "__kernel void test( const __global half *p, __global float *f,\n" + " uint extra_last_thread)\n" + "{\n" + " __local ushort data[", local_buf_size,"];\n" + " __local half* hdata_p = (__local half*) data;\n" + " __global ushort* i_p = (__global ushort*)p;\n" + " size_t i = get_global_id(0);\n" + " size_t last_i = get_global_size(0)-1;\n" + " size_t lid = get_local_id(0);\n" + " int k;\n" + " if(last_i == i && extra_last_thread != 0) {\n" + " if(extra_last_thread ==2) {\n" + " f[3*i+1] = vload_half(3*i+1, p);\n" + " }\n" + " f[3*i] = vload_half(3*i, p);\n" + " } else {\n" + " for (k=0; k<3; k++)\n" + " data[lid*3+k] = i_p[i*3+k];\n" + " vstore3( vload_half3( lid, hdata_p ),i,f);\n" + " };\n" + "}\n" + }; + + const char *source_localV3aligned[] = { + "__kernel void test( const __global half *p, __global float3 *f )\n" + "{\n" + " __local ushort data[", local_buf_size,"];\n" + " __local half* hdata_p = (__local half*) data;\n" + " __global ushort* i_p = (__global ushort*)p;\n" + " size_t i = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " int k;\n" + " for (k=0; k<4; k++)\n" + " data[lid*4+k] = i_p[i*4+k];\n" + " f[i] = vloada_half3( lid, hdata_p );\n" + " ((__global float *)f)[4*i+3] = vload_half(lid*4+3, hdata_p);\n" + "}\n" + }; + + const char *source_constant[] = { + "__kernel void test( __constant half *p, __global float", vector_size_name_extensions[vectorSize], " *f )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " f[i] = vload", aligned ? "a" : "", "_half",vector_size_name_extensions[vectorSize],"( i, p );\n" + "}\n" + }; + + const char *source_constantV3[] = { + "__kernel void test( __constant half *p, __global float *f,\n" + " uint extra_last_thread)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " size_t last_i = get_global_size(0)-1;\n" + " if(last_i == i && extra_last_thread != 0) {\n" + " if(extra_last_thread ==2) {\n" + " f[3*i+1] = vload_half(3*i+1, p);\n" + " }\n" + " f[3*i] = vload_half(3*i, p);\n" + " } else {\n" + " vstore3(vload_half",vector_size_name_extensions[vectorSize],"( i, p ), i, f);\n" + " }\n" + "}\n" + }; + + const char *source_constantV3aligned[] = { + "__kernel void test( __constant half *p, __global float3 *f )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " f[i] = vloada_half3( i, p );\n" + " ((__global float *)f)[4*i+3] = vload_half(4*i+3,p);\n" + "}\n" + }; + + + if(g_arrVecSizes[vectorSize] != 3) { + programs[vectorSize][0] = MakeProgram( source, sizeof( source) / sizeof( source[0]) ); + if( NULL == programs[ vectorSize ][0] ) { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create program.\n" ); + for ( q= 0; q < sizeof( source) / sizeof( source[0]); q++) + vlog_error("%s", source[q]); + return -1; + } else { + } + } else if(aligned) { + programs[vectorSize][0] = MakeProgram( sourceV3aligned, sizeof( sourceV3aligned) / sizeof( sourceV3aligned[0]) ); + if( NULL == programs[ vectorSize ][0] ) { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create program.\n" ); + for ( q= 0; q < sizeof( sourceV3aligned) / sizeof( sourceV3aligned[0]); q++) + vlog_error("%s", sourceV3aligned[q]); + return -1; + } else { + } + } else { + programs[vectorSize][0] = MakeProgram( sourceV3, sizeof( sourceV3) / sizeof( sourceV3[0]) ); + if( NULL == programs[ vectorSize ][0] ) { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create program.\n" ); + for ( q= 0; q < sizeof( sourceV3) / sizeof( sourceV3[0]); q++) + vlog_error("%s", sourceV3[q]); + return -1; + } + } + + kernels[ vectorSize ][0] = clCreateKernel( programs[ vectorSize ][0], "test", &error ); + if( NULL == kernels[vectorSize][0] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create kernel. (%d)\n", error ); + return -2; + } + + const char** source_ptr; + uint32_t source_size; + if (vectorSize == 0) { + source_ptr = source_private1; + source_size = sizeof( source_private1) / sizeof( source_private1[0]); + } else if(g_arrVecSizes[vectorSize] == 3) { + if(aligned) { + source_ptr = source_privateV3aligned; + source_size = sizeof( source_privateV3aligned) / sizeof( source_privateV3aligned[0]); + } else { + source_ptr = source_privateV3; + source_size = sizeof( source_privateV3) / sizeof( source_privateV3[0]); + } + } else { + source_ptr = source_private2; + source_size = sizeof( source_private2) / sizeof( source_private2[0]); + } + programs[vectorSize][1] = MakeProgram( source_ptr, source_size ); + if( NULL == programs[ vectorSize ][1] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create private program.\n" ); + for ( q= 0; q < source_size; q++) + vlog_error("%s", source_ptr[q]); + return -1; + } + + kernels[ vectorSize ][1] = clCreateKernel( programs[ vectorSize ][1], "test", &error ); + if( NULL == kernels[vectorSize][1] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create private kernel. (%d)\n", error ); + return -2; + } + + if (vectorSize == 0) { + source_ptr = source_local1; + source_size = sizeof( source_local1) / sizeof( source_local1[0]); + } else if(g_arrVecSizes[vectorSize] == 3) { + if(aligned) { + source_ptr = source_localV3aligned; + source_size = sizeof(source_localV3aligned)/sizeof(source_localV3aligned[0]); + } else { + source_ptr = source_localV3; + source_size = sizeof(source_localV3)/sizeof(source_localV3[0]); + } + } else { + source_ptr = source_local2; + source_size = sizeof( source_local2) / sizeof( source_local2[0]); + } + programs[vectorSize][2] = MakeProgram( source_ptr, source_size ); + if( NULL == programs[ vectorSize ][2] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create local program.\n" ); + for ( q= 0; q < source_size; q++) + vlog_error("%s", source_ptr[q]); + return -1; + } + + kernels[ vectorSize ][2] = clCreateKernel( programs[ vectorSize ][2], "test", &error ); + if( NULL == kernels[vectorSize][2] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create local kernel. (%d)\n", error ); + return -2; + } + + if(g_arrVecSizes[vectorSize] == 3) { + if(aligned) { + programs[vectorSize][3] = MakeProgram( source_constantV3aligned, sizeof(source_constantV3aligned) / sizeof( source_constantV3aligned[0]) ); + if( NULL == programs[ vectorSize ][3] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create constant program.\n" ); + for ( q= 0; q < sizeof( source_constantV3aligned) / sizeof( source_constantV3aligned[0]); q++) + vlog_error("%s", source_constantV3aligned[q]); + return -1; + } + } else { + programs[vectorSize][3] = MakeProgram( source_constantV3, sizeof(source_constantV3) / sizeof( source_constantV3[0]) ); + if( NULL == programs[ vectorSize ][3] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create constant program.\n" ); + for ( q= 0; q < sizeof( source_constantV3) / sizeof( source_constantV3[0]); q++) + vlog_error("%s", source_constantV3[q]); + return -1; + } + } + } else { + programs[vectorSize][3] = MakeProgram( source_constant, sizeof(source_constant) / sizeof( source_constant[0]) ); + if( NULL == programs[ vectorSize ][3] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create constant program.\n" ); + for ( q= 0; q < sizeof( source_constant) / sizeof( source_constant[0]); q++) + vlog_error("%s", source_constant[q]); + return -1; + } + } + + kernels[ vectorSize ][3] = clCreateKernel( programs[ vectorSize ][3], "test", &error ); + if( NULL == kernels[vectorSize][3] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create constant kernel. (%d)\n", error ); + return -2; + } + } + + // Figure out how many elements are in a work block + size_t elementSize = MAX( sizeof(cl_half), sizeof(cl_float)); + size_t blockCount = getBufferSize(gDevice) / elementSize; // elementSize is power of 2 + uint64_t lastCase = 1ULL << (8*sizeof(cl_half)); // number of things of size cl_half + + // we handle 64-bit types a bit differently. + if( lastCase == 0 ) + lastCase = 0x100000000ULL; + + + uint64_t i, j; + uint64_t printMask = (lastCase >> 4) - 1; + uint32_t count = 0; + error = 0; + int addressSpace; + // int reported_vector_skip = 0; + + for( i = 0; i < (uint64_t)lastCase; i += blockCount ) + { + count = (uint32_t) MIN( blockCount, lastCase - i ); + + //Init the input stream + uint16_t *p = (uint16_t *)gIn_half; + for( j = 0; j < count; j++ ) + p[j] = j + i; + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer_half, CL_TRUE, 0, count * sizeof( cl_half ), gIn_half, 0, NULL, NULL))) + { + vlog_error( "Failure in clWriteArray\n" ); + gFailCount++; + goto exit; + } + + //create the reference result + const unsigned short *s = (const unsigned short *)gIn_half; + float *d = (float *)gOut_single_reference; + for( j = 0; j < count; j++ ) + d[j] = half2float( s[j] ); + + //Check the vector lengths + for( vectorSize = minVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + { // here we loop through vector sizes, 3 is last + + for ( addressSpace = 0; addressSpace < 4; addressSpace++) { + uint32_t pattern = 0x7fffdead; + + /* + if (addressSpace == 3) { + vlog("Note: skipping address space %s due to small buffer size.\n", addressSpaceNames[addressSpace]); + continue; + } + */ + memset_pattern4( gOut_single, &pattern, getBufferSize(gDevice)); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer_single, CL_TRUE, 0, count * sizeof( float ), gOut_single, 0, NULL, NULL)) ) + { + vlog_error( "Failure in clWriteArray\n" ); + gFailCount++; + goto exit; + } + + if(g_arrVecSizes[vectorSize] == 3 && !aligned) { + // now we need to add the extra const argument for how + // many elements the last thread should take care of. + } + + // okay, here is where we have to be careful + if( (error = RunKernel( kernels[vectorSize][addressSpace], gInBuffer_half, gOutBuffer_single, numVecs(count, vectorSize, aligned) , + runsOverBy(count, vectorSize, aligned) ) ) ) + { + gFailCount++; + goto exit; + } + + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer_single, CL_TRUE, 0, count * sizeof( float ), gOut_single, 0, NULL, NULL)) ) + { + vlog_error( "Failure in clReadArray\n" ); + gFailCount++; + goto exit; + } + + if( memcmp( gOut_single, gOut_single_reference, count * sizeof( float )) ) + { + uint32_t *u1 = (uint32_t *)gOut_single; + uint32_t *u2 = (uint32_t *)gOut_single_reference; + float *f1 = (float *)gOut_single; + float *f2 = (float *)gOut_single_reference; + for( j = 0; j < count; j++ ) + { + if(isnan(f1[j]) && isnan(f2[j])) // both are nan dont compare them + continue; + if( u1[j] != u2[j]) + { + vlog_error( " %lld) (of %lld) Failure at 0x%4.4x: %a vs *%a (0x%8.8x vs *0x%8.8x) vector_size = %d (%s) address space = %s, load is %s\n", + j, (uint64_t)count, ((unsigned short*)gIn_half)[j], f1[j], f2[j], u1[j], u2[j], (g_arrVecSizes[vectorSize]), + vector_size_names[vectorSize], addressSpaceNames[addressSpace], + (aligned?"aligned":"unaligned")); + gFailCount++; + break; // goto exit; + } + } + } + + if( gReportTimes && addressSpace == 0) + { + //Run again for timing + for( j = 0; j < 100; j++ ) + { + uint64_t startTime = ReadTime(); + error = + RunKernel( kernels[vectorSize][addressSpace], gInBuffer_half, gOutBuffer_single, numVecs(count, vectorSize, aligned) , + runsOverBy(count, vectorSize, aligned)); + if(error) + { + gFailCount++; + goto exit; + } + + if( (error = clFinish(gQueue)) ) + { + vlog_error( "Failure in clFinish\n" ); + gFailCount++; + goto exit; + } + uint64_t currentTime = ReadTime() - startTime; + time[ vectorSize ] += currentTime; + if( currentTime < min_time[ vectorSize ] ) + min_time[ vectorSize ] = currentTime ; + } + } + } + } + + if( ((i+blockCount) & ~printMask) == (i+blockCount) ) + { + vlog( "." ); + fflush( stdout ); + } + } + + vlog( "\tPassed\n" ); + + if( gReportTimes ) + { + for( vectorSize = minVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + vlog_perf( SubtractTime( time[ vectorSize ], 0 ) * 1e6 * gDeviceFrequency * gComputeDevices / (double) (count * 100), 0, + "average us/elem", "vLoad%sHalf avg. (%s, vector size: %d)", ( (aligned) ? "a" : ""), addressSpaceNames[0], (g_arrVecSizes[vectorSize]) ); + for( vectorSize = minVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + vlog_perf( SubtractTime( min_time[ vectorSize ], 0 ) * 1e6 * gDeviceFrequency * gComputeDevices / (double) count, 0, + "best us/elem", "vLoad%sHalf best (%s vector size: %d)", ( (aligned) ? "a" : ""), addressSpaceNames[0], (g_arrVecSizes[vectorSize]) ); + } + +exit: + //clean up + for( vectorSize = minVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + { + for ( addressSpace = 0; addressSpace < 3; addressSpace++) { + clReleaseKernel( kernels[ vectorSize ][addressSpace] ); + clReleaseProgram( programs[ vectorSize ][addressSpace] ); + } + } + + gTestCount++; + return error; +} + +int Test_vload_half( void ) +{ + return Test_vLoadHalf_private( false ); +} + +int Test_vloada_half( void ) +{ + return Test_vLoadHalf_private( true ); +} + diff --git a/test_conformance/half/Test_vStoreHalf.c b/test_conformance/half/Test_vStoreHalf.c new file mode 100644 index 00000000..a3117bcb --- /dev/null +++ b/test_conformance/half/Test_vStoreHalf.c @@ -0,0 +1,1947 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" +#include "../../test_common/harness/kernelHelpers.h" + +#include +#include "cl_utils.h" +#include "tests.h" + +extern const char *addressSpaceNames[]; + +typedef struct ComputeReferenceInfoF_ +{ + float *x; + cl_ushort *r; + f2h f; + cl_ulong i; + cl_uint lim; + cl_uint count; +} ComputeReferenceInfoF; + +typedef struct ComputeReferenceInfoD_ +{ + double *x; + cl_ushort *r; + d2h f; + cl_ulong i; + cl_uint lim; + cl_uint count; +} ComputeReferenceInfoD; + +typedef struct CheckResultInfoF_ +{ + const float *x; + const cl_ushort *r; + const cl_ushort *s; + f2h f; + const char *aspace; + cl_uint lim; + cl_uint count; + int vsz; +} CheckResultInfoF; + +typedef struct CheckResultInfoD_ +{ + const double *x; + const cl_ushort *r; + const cl_ushort *s; + d2h f; + const char *aspace; + cl_uint lim; + cl_uint count; + int vsz; +} CheckResultInfoD; + +static cl_int +ReferenceF(cl_uint jid, cl_uint tid, void *userInfo) +{ + ComputeReferenceInfoF *cri = (ComputeReferenceInfoF *)userInfo; + cl_uint lim = cri->lim; + cl_uint count = cri->count; + cl_uint off = jid * count; + float *x = cri->x + off; + cl_ushort *r = cri->r + off; + f2h f = cri->f; + cl_ulong i = cri->i + off; + cl_uint j, rr; + + if (off + count > lim) + count = lim - off; + + for (j = 0; j < count; ++j) { + x[j] = as_float((cl_uint)(i + j)); + r[j] = f(x[j]); + } + + return 0; +} + +static cl_int +CheckF(cl_uint jid, cl_uint tid, void *userInfo) +{ + CheckResultInfoF *cri = (CheckResultInfoF *)userInfo; + cl_uint lim = cri->lim; + cl_uint count = cri->count; + cl_uint off = jid * count; + const float *x = cri->x + off; + const cl_ushort *r = cri->r + off; + const cl_ushort *s = cri->s + off; + f2h f = cri->f; + cl_uint j; + cl_ushort correct2 = f( 0.0f); + cl_ushort correct3 = f(-0.0f); + cl_int ret = 0; + + if (off + count > lim) + count = lim - off; + + if (!memcmp(r, s, count*sizeof(cl_ushort))) + return 0; + + for (j = 0; j < count; j++) { + if (s[j] == r[j]) + continue; + + // Pass any NaNs + if ((s[j] & 0x7fff) > 0x7c00 && (r[j] & 0x7fff) > 0x7c00 ) + continue; + + // retry per section 6.5.3.3 + if (IsFloatSubnormal(x[j]) && (s[j] == correct2 || s[j] == correct3)) + continue; + + // if reference result is subnormal, pass any zero + if (gIsEmbedded && IsHalfSubnormal(r[j]) && (s[j] == 0x0000 || s[j] == 0x8000)) + continue; + + vlog_error("\nFailure at [%u] with %.6a: *0x%04x vs 0x%04x, vector_size = %d, address_space = %s\n", + j+off, x[j], r[j], s[j], cri->vsz, cri->aspace); + + ret = 1; + break; + } + + return ret; +} + +static cl_int +ReferenceD(cl_uint jid, cl_uint tid, void *userInfo) +{ + ComputeReferenceInfoD *cri = (ComputeReferenceInfoD *)userInfo; + cl_uint lim = cri->lim; + cl_uint count = cri->count; + cl_uint off = jid * count; + double *x = cri->x + off; + cl_ushort *r = cri->r + off; + d2h f = cri->f; + cl_uint j; + cl_ulong i = cri->i + off; + + if (off + count > lim) + count = lim - off; + + for (j = 0; j < count; ++j) { + x[j] = as_double(DoubleFromUInt((cl_uint)(i + j))); + r[j] = f(x[j]); + } + + return 0; +} + +static cl_int +CheckD(cl_uint jid, cl_uint tid, void *userInfo) +{ + CheckResultInfoD *cri = (CheckResultInfoD *)userInfo; + cl_uint lim = cri->lim; + cl_uint count = cri->count; + cl_uint off = jid * count; + const double *x = cri->x + off; + const cl_ushort *r = cri->r + off; + const cl_ushort *s = cri->s + off; + d2h f = cri->f; + cl_uint j; + cl_ushort correct2 = f( 0.0); + cl_ushort correct3 = f(-0.0); + cl_int ret = 0; + + if (off + count > lim) + count = lim - off; + + if (!memcmp(r, s, count*sizeof(cl_ushort))) + return 0; + + for (j = 0; j < count; j++) { + if (s[j] == r[j]) + continue; + + // Pass any NaNs + if ((s[j] & 0x7fff) > 0x7c00 && (r[j] & 0x7fff) > 0x7c00) + continue; + + if (IsDoubleSubnormal(x[j]) && (s[j] == correct2 || s[j] == correct3)) + continue; + + // if reference result is subnormal, pass any zero result + if (gIsEmbedded && IsHalfSubnormal(r[j]) && (s[j] == 0x0000 || s[j] == 0x8000)) + continue; + + vlog_error("\nFailure at [%u] with %.13la: *0x%04x vs 0x%04x, vector_size = %d, address space = %s (double precision)\n", + j+off, x[j], r[j], s[j], cri->vsz, cri->aspace); + + ret = 1; + break; + } + + return ret; +} + +static cl_ushort float2half_rte( float f ); +static cl_ushort float2half_rtz( float f ); +static cl_ushort float2half_rtp( float f ); +static cl_ushort float2half_rtn( float f ); +static cl_ushort double2half_rte( double f ); +static cl_ushort double2half_rtz( double f ); +static cl_ushort double2half_rtp( double f ); +static cl_ushort double2half_rtn( double f ); + +static cl_ushort +float2half_rte( float f ) +{ + union{ float f; cl_uint u; } u = {f}; + cl_uint sign = (u.u >> 16) & 0x8000; + float x = fabsf(f); + + //Nan + if( x != x ) + { + u.u >>= (24-11); + u.u &= 0x7fff; + u.u |= 0x0200; //silence the NaN + return u.u | sign; + } + + // overflow + if( x >= MAKE_HEX_FLOAT(0x1.ffep15f, 0x1ffeL, 3) ) + return 0x7c00 | sign; + + // underflow + if( x <= MAKE_HEX_FLOAT(0x1.0p-25f, 0x1L, -25) ) + return sign; // The halfway case can return 0x0001 or 0. 0 is even. + + // very small + if( x < MAKE_HEX_FLOAT(0x1.8p-24f, 0x18L, -28) ) + return sign | 1; + + // half denormal + if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) ) + { + u.f = x * MAKE_HEX_FLOAT(0x1.0p-125f, 0x1L, -125); + return sign | u.u; + } + + u.f *= MAKE_HEX_FLOAT(0x1.0p13f, 0x1L, 13); + u.u &= 0x7f800000; + x += u.f; + u.f = x - u.f; + u.f *= MAKE_HEX_FLOAT(0x1.0p-112f, 0x1L, -112); + + return (u.u >> (24-11)) | sign; +} + +static cl_ushort +float2half_rtz( float f ) +{ + union{ float f; cl_uint u; } u = {f}; + cl_uint sign = (u.u >> 16) & 0x8000; + float x = fabsf(f); + + //Nan + if( x != x ) + { + u.u >>= (24-11); + u.u &= 0x7fff; + u.u |= 0x0200; //silence the NaN + return u.u | sign; + } + + // overflow + if( x >= MAKE_HEX_FLOAT(0x1.0p16f, 0x1L, 16) ) + { + if( x == INFINITY ) + return 0x7c00 | sign; + + return 0x7bff | sign; + } + + // underflow + if( x < MAKE_HEX_FLOAT(0x1.0p-24f, 0x1L, -24) ) + return sign; // The halfway case can return 0x0001 or 0. 0 is even. + + // half denormal + if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) ) + { + x *= MAKE_HEX_FLOAT(0x1.0p24f, 0x1L, 24); + return (cl_ushort)((int) x | sign); + } + + u.u &= 0xFFFFE000U; + u.u -= 0x38000000U; + + return (u.u >> (24-11)) | sign; +} + +static cl_ushort +float2half_rtp( float f ) +{ + union{ float f; cl_uint u; } u = {f}; + cl_uint sign = (u.u >> 16) & 0x8000; + float x = fabsf(f); + + //Nan + if( x != x ) + { + u.u >>= (24-11); + u.u &= 0x7fff; + u.u |= 0x0200; //silence the NaN + return u.u | sign; + } + + // overflow + if( f > MAKE_HEX_FLOAT(0x1.ffcp15f, 0x1ffcL, 3) ) + return 0x7c00; + + if( f <= MAKE_HEX_FLOAT(-0x1.0p16f, -0x1L, 16) ) + { + if( f == -INFINITY ) + return 0xfc00; + + return 0xfbff; + } + + // underflow + if( x < MAKE_HEX_FLOAT(0x1.0p-24f, 0x1L, -24) ) + { + if( f > 0 ) + return 1; + return sign; + } + + // half denormal + if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) ) + { + x *= MAKE_HEX_FLOAT(0x1.0p24f, 0x1L, 24); + int r = (int) x; + r += (float) r != x && f > 0.0f; + + return (cl_ushort)( r | sign); + } + + float g = u.f; + u.u &= 0xFFFFE000U; + if( g > u.f ) + u.u += 0x00002000U; + u.u -= 0x38000000U; + + return (u.u >> (24-11)) | sign; +} + + +static cl_ushort +float2half_rtn( float f ) +{ + union{ float f; cl_uint u; } u = {f}; + cl_uint sign = (u.u >> 16) & 0x8000; + float x = fabsf(f); + + //Nan + if( x != x ) + { + u.u >>= (24-11); + u.u &= 0x7fff; + u.u |= 0x0200; //silence the NaN + return u.u | sign; + } + + // overflow + if( f >= MAKE_HEX_FLOAT(0x1.0p16f, 0x1L, 16) ) + { + if( f == INFINITY ) + return 0x7c00; + + return 0x7bff; + } + + if( f < MAKE_HEX_FLOAT(-0x1.ffcp15f, -0x1ffcL, 3) ) + return 0xfc00; + + // underflow + if( x < MAKE_HEX_FLOAT(0x1.0p-24f, 0x1L, -24) ) + { + if( f < 0 ) + return 0x8001; + return sign; + } + + // half denormal + if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) ) + { + x *= MAKE_HEX_FLOAT(0x1.0p24f, 0x1L, 24); + int r = (int) x; + r += (float) r != x && f < 0.0f; + + return (cl_ushort)( r | sign); + } + + u.u &= 0xFFFFE000U; + if( u.f > f ) + u.u += 0x00002000U; + u.u -= 0x38000000U; + + return (u.u >> (24-11)) | sign; +} + +static cl_ushort +double2half_rte( double f ) +{ + union{ double f; cl_ulong u; } u = {f}; + cl_ulong sign = (u.u >> 48) & 0x8000; + double x = fabs(f); + + //Nan + if( x != x ) + { + u.u >>= (53-11); + u.u &= 0x7fff; + u.u |= 0x0200; //silence the NaN + return u.u | sign; + } + + // overflow + if( x >= MAKE_HEX_DOUBLE(0x1.ffep15, 0x1ffeLL, 3) ) + return 0x7c00 | sign; + + // underflow + if( x <= MAKE_HEX_DOUBLE(0x1.0p-25, 0x1LL, -25) ) + return sign; // The halfway case can return 0x0001 or 0. 0 is even. + + // very small + if( x < MAKE_HEX_DOUBLE(0x1.8p-24, 0x18LL, -28) ) + return sign | 1; + + // half denormal + if( x < MAKE_HEX_DOUBLE(0x1.0p-14, 0x1LL, -14) ) + { + u.f = x * MAKE_HEX_DOUBLE(0x1.0p-1050, 0x1LL, -1050); + return sign | u.u; + } + + u.f *= MAKE_HEX_DOUBLE(0x1.0p42, 0x1LL, 42); + u.u &= 0x7ff0000000000000ULL; + x += u.f; + u.f = x - u.f; + u.f *= MAKE_HEX_DOUBLE(0x1.0p-1008, 0x1LL, -1008); + + return (u.u >> (53-11)) | sign; +} + +static cl_ushort +double2half_rtz( double f ) +{ + union{ double f; cl_ulong u; } u = {f}; + cl_ulong sign = (u.u >> 48) & 0x8000; + double x = fabs(f); + + //Nan + if( x != x ) + { + u.u >>= (53-11); + u.u &= 0x7fff; + u.u |= 0x0200; //silence the NaN + return u.u | sign; + } + + if( x == INFINITY ) + return 0x7c00 | sign; + + // overflow + if( x >= MAKE_HEX_DOUBLE(0x1.0p16, 0x1LL, 16) ) + return 0x7bff | sign; + + // underflow + if( x < MAKE_HEX_DOUBLE(0x1.0p-24, 0x1LL, -24) ) + return sign; // The halfway case can return 0x0001 or 0. 0 is even. + + // half denormal + if( x < MAKE_HEX_DOUBLE(0x1.0p-14, 0x1LL, -14) ) + { + x *= MAKE_HEX_FLOAT(0x1.0p24f, 0x1L, 24); + return (cl_ushort)((int) x | sign); + } + + u.u &= 0xFFFFFC0000000000ULL; + u.u -= 0x3F00000000000000ULL; + + return (u.u >> (53-11)) | sign; +} + +static cl_ushort +double2half_rtp( double f ) +{ + union{ double f; cl_ulong u; } u = {f}; + cl_ulong sign = (u.u >> 48) & 0x8000; + double x = fabs(f); + + //Nan + if( x != x ) + { + u.u >>= (53-11); + u.u &= 0x7fff; + u.u |= 0x0200; //silence the NaN + return u.u | sign; + } + + // overflow + if( f > MAKE_HEX_DOUBLE(0x1.ffcp15, 0x1ffcLL, 3) ) + return 0x7c00; + + if( f <= MAKE_HEX_DOUBLE(-0x1.0p16, -0x1LL, 16) ) + { + if( f == -INFINITY ) + return 0xfc00; + + return 0xfbff; + } + + // underflow + if( x < MAKE_HEX_DOUBLE(0x1.0p-24, 0x1LL, -24) ) + { + if( f > 0 ) + return 1; + return sign; + } + + // half denormal + if( x < MAKE_HEX_DOUBLE(0x1.0p-14, 0x1LL, -14) ) + { + x *= MAKE_HEX_FLOAT(0x1.0p24f, 0x1L, 24); + int r = (int) x; + if( 0 == sign ) + r += (double) r != x; + + return (cl_ushort)( r | sign); + } + + double g = u.f; + u.u &= 0xFFFFFC0000000000ULL; + if( g != u.f && 0 == sign) + u.u += 0x0000040000000000ULL; + u.u -= 0x3F00000000000000ULL; + + return (u.u >> (53-11)) | sign; +} + + +static cl_ushort +double2half_rtn( double f ) +{ + union{ double f; cl_ulong u; } u = {f}; + cl_ulong sign = (u.u >> 48) & 0x8000; + double x = fabs(f); + + //Nan + if( x != x ) + { + u.u >>= (53-11); + u.u &= 0x7fff; + u.u |= 0x0200; //silence the NaN + return u.u | sign; + } + + // overflow + if( f >= MAKE_HEX_DOUBLE(0x1.0p16, 0x1LL, 16) ) + { + if( f == INFINITY ) + return 0x7c00; + + return 0x7bff; + } + + if( f < MAKE_HEX_DOUBLE(-0x1.ffcp15, -0x1ffcLL, 3) ) + return 0xfc00; + + // underflow + if( x < MAKE_HEX_DOUBLE(0x1.0p-24, 0x1LL, -24) ) + { + if( f < 0 ) + return 0x8001; + return sign; + } + + // half denormal + if( x < MAKE_HEX_DOUBLE(0x1.0p-14, 0x1LL, -14) ) + { + x *= MAKE_HEX_DOUBLE(0x1.0p24, 0x1LL, 24); + int r = (int) x; + if( sign ) + r += (double) r != x; + + return (cl_ushort)( r | sign); + } + + double g = u.f; + u.u &= 0xFFFFFC0000000000ULL; + if( g < u.f && sign) + u.u += 0x0000040000000000ULL; + u.u -= 0x3F00000000000000ULL; + + return (u.u >> (53-11)) | sign; +} + +int Test_vstore_half( void ) +{ + switch (get_default_rounding_mode(gDevice)) + { + case CL_FP_ROUND_TO_ZERO: + return Test_vStoreHalf_private(float2half_rtz, double2half_rte, ""); + case 0: + return -1; + default: + return Test_vStoreHalf_private(float2half_rte, double2half_rte, ""); + } +} + +int Test_vstore_half_rte( void ) +{ + return Test_vStoreHalf_private(float2half_rte, double2half_rte, "_rte"); +} + +int Test_vstore_half_rtz( void ) +{ + return Test_vStoreHalf_private(float2half_rtz, double2half_rtz, "_rtz"); +} + +int Test_vstore_half_rtp( void ) +{ + return Test_vStoreHalf_private(float2half_rtp, double2half_rtp, "_rtp"); +} + +int Test_vstore_half_rtn( void ) +{ + return Test_vStoreHalf_private(float2half_rtn, double2half_rtn, "_rtn"); +} + +int Test_vstorea_half( void ) +{ + switch (get_default_rounding_mode(gDevice)) + { + case CL_FP_ROUND_TO_ZERO: + return Test_vStoreaHalf_private(float2half_rtz, double2half_rte, ""); + case 0: + return -1; + default: + return Test_vStoreaHalf_private(float2half_rte, double2half_rte, ""); + } +} + +int Test_vstorea_half_rte( void ) +{ + return Test_vStoreaHalf_private(float2half_rte, double2half_rte, "_rte"); +} + +int Test_vstorea_half_rtz( void ) +{ + return Test_vStoreaHalf_private(float2half_rtz, double2half_rtz, "_rtz"); +} + +int Test_vstorea_half_rtp( void ) +{ + return Test_vStoreaHalf_private(float2half_rtp, double2half_rtp, "_rtp"); +} + +int Test_vstorea_half_rtn( void ) +{ + return Test_vStoreaHalf_private(float2half_rtn, double2half_rtn, "_rtn"); +} + +#pragma mark - + +int Test_vStoreHalf_private( f2h referenceFunc, d2h doubleReferenceFunc, const char *roundName ) +{ + int vectorSize, error; + cl_program programs[kVectorSizeCount+kStrangeVectorSizeCount][3]; + cl_kernel kernels[kVectorSizeCount+kStrangeVectorSizeCount][3]; + + uint64_t time[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + uint64_t min_time[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + memset( min_time, -1, sizeof( min_time ) ); + cl_program doublePrograms[kVectorSizeCount+kStrangeVectorSizeCount][3]; + cl_kernel doubleKernels[kVectorSizeCount+kStrangeVectorSizeCount][3]; + uint64_t doubleTime[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + uint64_t min_double_time[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + memset( min_double_time, -1, sizeof( min_double_time ) ); + + vlog( "Testing vstore_half%s\n", roundName ); + fflush( stdout ); + + bool aligned= false; + + for( vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + { + const char *source[] = { + "__kernel void test( __global float", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " vstore_half",vector_size_name_extensions[vectorSize],roundName,"( p[i], i, f );\n" + "}\n" + }; + + const char *source_v3[] = { + "__kernel void test( __global float *p, __global half *f,\n" + " uint extra_last_thread)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " size_t last_i = get_global_size(0)-1;\n" + " size_t adjust = 0;\n" + " if(last_i == i && extra_last_thread != 0) {\n" + " adjust = 3-extra_last_thread;\n" + " } " + " vstore_half3",roundName,"( vload3(i, p-adjust), i, f-adjust );\n" + "}\n" + }; + + const char *source_private_store[] = { + "__kernel void test( __global float", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " __private ushort data[16];\n" + " size_t i = get_global_id(0);\n" + " size_t offset = 0;\n" + " size_t vecsize = vec_step(p[i]);\n" + " vstore_half",vector_size_name_extensions[vectorSize],roundName,"( p[i], 0, (__private half *)(&data[0]) );\n" + " for(offset = 0; offset < vecsize; offset++)\n" + " {\n" + " vstore_half(vload_half(offset, (__private half *)data), 0, &f[vecsize*i+offset]);\n" + " }\n" + "}\n" + }; + + + const char *source_private_store_v3[] = { + "__kernel void test( __global float *p, __global half *f,\n" + " uint extra_last_thread )\n" + "{\n" + " __private ushort data[4];\n" + " size_t i = get_global_id(0);\n" + " size_t last_i = get_global_size(0)-1;\n" + " size_t adjust = 0;\n" + " size_t offset = 0;\n" + " if(last_i == i && extra_last_thread != 0) {\n" + " adjust = 3-extra_last_thread;\n" + " } " + " vstore_half3",roundName,"( vload3(i, p-adjust), 0, (__private half *)(&data[0]) );\n" + " for(offset = 0; offset < 3; offset++)\n" + " {\n" + " vstore_half(vload_half(offset, (__private half *) data), 0, &f[3*i+offset-adjust]);\n" + " }\n" + "}\n" + }; + + char local_buf_size[10]; + sprintf(local_buf_size, "%lld", (uint64_t)gWorkGroupSize); + + + const char *source_local_store[] = { + "__kernel void test( __global float", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " __local ushort data[16*", local_buf_size, "];\n" + " size_t i = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " size_t lsize = get_local_size(0);\n" + " size_t vecsize = vec_step(p[0]);\n" + " event_t async_event;\n" + " vstore_half",vector_size_name_extensions[vectorSize],roundName,"( p[i], lid, (__local half *)(&data[0]) );\n" + " barrier( CLK_LOCAL_MEM_FENCE ); \n" + " async_event = async_work_group_copy((__global ushort *)f+vecsize*(i-lid), (__local ushort *)(&data[0]), vecsize*lsize, 0);\n" // investigate later + " wait_group_events(1, &async_event);\n" + "}\n" + }; + + const char *source_local_store_v3[] = { + "__kernel void test( __global float *p, __global half *f,\n" + " uint extra_last_thread )\n" + "{\n" + " __local ushort data[3*(", local_buf_size, "+1)];\n" + " size_t i = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " size_t last_i = get_global_size(0)-1;\n" + " size_t adjust = 0;\n" + " size_t lsize = get_local_size(0);\n" + " event_t async_event;\n" + " if(last_i == i && extra_last_thread != 0) {\n" + " adjust = 3-extra_last_thread;\n" + " } " + " vstore_half3",roundName,"( vload3(i,p-adjust), lid, (__local half *)(&data[0]) );\n" + " barrier( CLK_LOCAL_MEM_FENCE ); \n" + " async_event = async_work_group_copy((__global ushort *)(f+3*(i-lid)), (__local ushort *)(&data[adjust]), lsize*3-adjust, 0);\n" // investigate later + " wait_group_events(1, &async_event);\n" + "}\n" + }; + + const char *double_source[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global double", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " vstore_half",vector_size_name_extensions[vectorSize],roundName,"( p[i], i, f );\n" + "}\n" + }; + + const char *double_source_private_store[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global double", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " __private ushort data[16];\n" + " size_t i = get_global_id(0);\n" + " size_t offset = 0;\n" + " size_t vecsize = vec_step(p[i]);\n" + " vstore_half",vector_size_name_extensions[vectorSize],roundName,"( p[i], 0, (__private half *)(&data[0]) );\n" + " for(offset = 0; offset < vecsize; offset++)\n" + " {\n" + " vstore_half(vload_half(offset, (__private half *)data), 0, &f[vecsize*i+offset]);\n" + " }\n" + "}\n" + }; + + + const char *double_source_local_store[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global double", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " __local ushort data[16*", local_buf_size, "];\n" + " size_t i = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " size_t vecsize = vec_step(p[0]);\n" + " size_t lsize = get_local_size(0);\n" + " event_t async_event;\n" + " vstore_half",vector_size_name_extensions[vectorSize],roundName,"( p[i], lid, (__local half *)(&data[0]) );\n" + " barrier( CLK_LOCAL_MEM_FENCE ); \n" + " async_event = async_work_group_copy((__global ushort *)(f+vecsize*(i-lid)), (__local ushort *)(&data[0]), vecsize*lsize, 0);\n" // investigate later + " wait_group_events(1, &async_event);\n" + "}\n" + }; + + + const char *double_source_v3[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global double *p, __global half *f ,\n" + " uint extra_last_thread)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " size_t last_i = get_global_size(0)-1;\n" + " size_t adjust = 0;\n" + " if(last_i == i && extra_last_thread != 0) {\n" + " adjust = 3-extra_last_thread;\n" + " } " + " vstore_half3",roundName,"( vload3(i,p-adjust), i, f -adjust);\n" + "}\n" + }; + + const char *double_source_private_store_v3[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global double *p, __global half *f,\n" + " uint extra_last_thread )\n" + "{\n" + " __private ushort data[4];\n" + " size_t i = get_global_id(0);\n" + " size_t last_i = get_global_size(0)-1;\n" + " size_t adjust = 0;\n" + " size_t offset = 0;\n" + " if(last_i == i && extra_last_thread != 0) {\n" + " adjust = 3-extra_last_thread;\n" + " } " + " vstore_half3",roundName,"( vload3(i, p-adjust), 0, (__private half *)(&data[0]) );\n" + " for(offset = 0; offset < 3; offset++)\n" + " {\n" + " vstore_half(vload_half(offset, (__private half *)data), 0, &f[3*i+offset-adjust]);\n" + " }\n" + "}\n" + }; + + const char *double_source_local_store_v3[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global double *p, __global half *f,\n" + " uint extra_last_thread )\n" + "{\n" + " __local ushort data[3*(", local_buf_size, "+1)];\n" + " size_t i = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " size_t last_i = get_global_size(0)-1;\n" + " size_t adjust = 0;\n" + " size_t lsize = get_local_size(0);\n" + " event_t async_event;\n" + " if(last_i == i && extra_last_thread != 0) {\n" + " adjust = 3-extra_last_thread;\n" + " }\n " + " vstore_half3",roundName,"( vload3(i,p-adjust), lid, (__local half *)(&data[0]) );\n" + " barrier( CLK_LOCAL_MEM_FENCE ); \n" + " async_event = async_work_group_copy((__global ushort *)(f+3*(i-lid)), (__local ushort *)(&data[adjust]), lsize*3-adjust, 0);\n" // investigate later + " wait_group_events(1, &async_event);\n" + "}\n" + }; + + + + if(g_arrVecSizes[vectorSize] == 3) { + programs[vectorSize][0] = MakeProgram( source_v3, sizeof(source_v3) / sizeof( source_v3[0]) ); + } else { + programs[vectorSize][0] = MakeProgram( source, sizeof(source) / sizeof( source[0]) ); + } + if( NULL == programs[ vectorSize ][0] ) + { + gFailCount++; + return -1; + } + + kernels[ vectorSize ][0] = clCreateKernel( programs[ vectorSize ][0], "test", &error ); + if( NULL == kernels[vectorSize][0] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create kernel. (%d)\n", error ); + return error; + } + + if(g_arrVecSizes[vectorSize] == 3) { + programs[vectorSize][1] = MakeProgram( source_private_store_v3, sizeof(source_private_store_v3) / sizeof( source_private_store_v3[0]) ); + } else { + programs[vectorSize][1] = MakeProgram( source_private_store, sizeof(source_private_store) / sizeof( source_private_store[0]) ); + } + if( NULL == programs[ vectorSize ][1] ) + { + gFailCount++; + return -1; + } + + kernels[ vectorSize ][1] = clCreateKernel( programs[ vectorSize ][1], "test", &error ); + if( NULL == kernels[vectorSize][1] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create private kernel. (%d)\n", error ); + return error; + } + + if(g_arrVecSizes[vectorSize] == 3) { + programs[vectorSize][2] = MakeProgram( source_local_store_v3, sizeof(source_local_store_v3) / sizeof( source_local_store_v3[0]) ); + if( NULL == programs[ vectorSize ][2] ) + { + unsigned q; + for ( q= 0; q < sizeof( source_local_store_v3) / sizeof( source_local_store_v3[0]); q++) + vlog_error("%s", source_local_store_v3[q]); + + gFailCount++; + return -1; + + } + } else { + programs[vectorSize][2] = MakeProgram( source_local_store, sizeof(source_local_store) / sizeof( source_local_store[0]) ); + if( NULL == programs[ vectorSize ][2] ) + { + unsigned q; + for ( q= 0; q < sizeof( source_local_store) / sizeof( source_local_store[0]); q++) + vlog_error("%s", source_local_store[q]); + + gFailCount++; + return -1; + + } + } + + kernels[ vectorSize ][2] = clCreateKernel( programs[ vectorSize ][2], "test", &error ); + if( NULL == kernels[vectorSize][2] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create local kernel. (%d)\n", error ); + return error; + } + + if( gTestDouble ) + { + if(g_arrVecSizes[vectorSize] == 3) { + doublePrograms[vectorSize][0] = MakeProgram( double_source_v3, sizeof(double_source_v3) / sizeof( double_source_v3[0]) ); + } else { + doublePrograms[vectorSize][0] = MakeProgram( double_source, sizeof(double_source) / sizeof( double_source[0]) ); + } + if( NULL == doublePrograms[ vectorSize ][0] ) + { + gFailCount++; + return -1; + } + + doubleKernels[ vectorSize ][0] = clCreateKernel( doublePrograms[ vectorSize ][0], "test", &error ); + if( NULL == kernels[vectorSize][0] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create double kernel. (%d)\n", error ); + return error; + } + + if(g_arrVecSizes[vectorSize] == 3) + doublePrograms[vectorSize][1] = MakeProgram( double_source_private_store_v3, sizeof(double_source_private_store_v3) / sizeof( double_source_private_store_v3[0]) ); + else + doublePrograms[vectorSize][1] = MakeProgram( double_source_private_store, sizeof(double_source_private_store) / sizeof( double_source_private_store[0]) ); + + if( NULL == doublePrograms[ vectorSize ][1] ) + { + gFailCount++; + return -1; + } + + doubleKernels[ vectorSize ][1] = clCreateKernel( doublePrograms[ vectorSize ][1], "test", &error ); + if( NULL == kernels[vectorSize][1] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create double private kernel. (%d)\n", error ); + return error; + } + + if(g_arrVecSizes[vectorSize] == 3) { + doublePrograms[vectorSize][2] = MakeProgram( double_source_local_store_v3, sizeof(double_source_local_store_v3) / sizeof( double_source_local_store_v3[0]) ); + } else { + doublePrograms[vectorSize][2] = MakeProgram( double_source_local_store, sizeof(double_source_local_store) / sizeof( double_source_local_store[0]) ); + } + if( NULL == doublePrograms[ vectorSize ][2] ) + { + gFailCount++; + return -1; + } + + doubleKernels[ vectorSize ][2] = clCreateKernel( doublePrograms[ vectorSize ][2], "test", &error ); + if( NULL == kernels[vectorSize][2] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create double local kernel. (%d)\n", error ); + return error; + } + } + } // end for vector size + + // Figure out how many elements are in a work block + size_t elementSize = MAX( sizeof(cl_ushort), sizeof(float)); + size_t blockCount = BUFFER_SIZE / elementSize; // elementSize is power of 2 + uint64_t lastCase = 1ULL << (8*sizeof(float)); // number of floats. + size_t stride = blockCount; + + if (gWimpyMode) + stride = 0x10000000U; + + // we handle 64-bit types a bit differently. + if( lastCase == 0 ) + lastCase = 0x100000000ULL; + + uint64_t i, j; + error = 0; + uint64_t printMask = (lastCase >> 4) - 1; + cl_uint count = 0; + int addressSpace; + size_t loopCount; + cl_uint threadCount = GetThreadCount(); + + ComputeReferenceInfoF fref; + fref.x = (float *)gIn_single; + fref.r = (cl_ushort *)gOut_half_reference; + fref.f = referenceFunc; + fref.lim = blockCount; + fref.count = (blockCount + threadCount - 1) / threadCount; + + CheckResultInfoF fchk; + fchk.x = (const float *)gIn_single; + fchk.r = (const cl_ushort *)gOut_half_reference; + fchk.s = (const cl_ushort *)gOut_half; + fchk.f = referenceFunc; + fchk.lim = blockCount; + fchk.count = (blockCount + threadCount - 1) / threadCount; + + ComputeReferenceInfoD dref; + dref.x = (double *)gIn_double; + dref.r = (cl_ushort *)gOut_half_reference_double; + dref.f = doubleReferenceFunc; + dref.lim = blockCount; + dref.count = (blockCount + threadCount - 1) / threadCount; + + CheckResultInfoD dchk; + dchk.x = (const double *)gIn_double; + dchk.r = (const cl_ushort *)gOut_half_reference_double; + dchk.s = (const cl_ushort *)gOut_half; + dchk.f = doubleReferenceFunc; + dchk.lim = blockCount; + dchk.count = (blockCount + threadCount - 1) / threadCount; + + for( i = 0; i < lastCase; i += stride ) + { + count = (cl_uint) MIN( blockCount, lastCase - i ); + fref.i = i; + dref.i = i; + + // Compute the input and reference + ThreadPool_Do(ReferenceF, threadCount, &fref); + + error = clEnqueueWriteBuffer(gQueue, gInBuffer_single, CL_FALSE, 0, count * sizeof(float ), gIn_single, 0, NULL, NULL); + if (error) { + vlog_error( "Failure in clWriteBuffer\n" ); + gFailCount++; + goto exit; + } + + if (gTestDouble) { + ThreadPool_Do(ReferenceD, threadCount, &dref); + + error = clEnqueueWriteBuffer(gQueue, gInBuffer_double, CL_FALSE, 0, count * sizeof(double ), gIn_double, 0, NULL, NULL); + if (error) { + vlog_error( "Failure in clWriteBuffer\n" ); + gFailCount++; + goto exit; + } + } + + for (vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) { + // Loop through vector sizes + fchk.vsz = g_arrVecSizes[vectorSize]; + dchk.vsz = g_arrVecSizes[vectorSize]; + + for ( addressSpace = 0; addressSpace < 3; addressSpace++) { + // Loop over address spaces + fchk.aspace = addressSpaceNames[addressSpace]; + dchk.aspace = addressSpaceNames[addressSpace]; + + cl_uint pattern = 0xdeaddead; + memset_pattern4( gOut_half, &pattern, BUFFER_SIZE/2); + + error = clEnqueueWriteBuffer(gQueue, gOutBuffer_half, CL_FALSE, 0, count * sizeof(cl_ushort), gOut_half, 0, NULL, NULL); + if (error) { + vlog_error( "Failure in clWriteArray\n" ); + gFailCount++; + goto exit; + } + + error = RunKernel(kernels[vectorSize][addressSpace], gInBuffer_single, gOutBuffer_half, + numVecs(count, vectorSize, aligned) , + runsOverBy(count, vectorSize, aligned)); + if (error) { + gFailCount++; + goto exit; + } + + error = clEnqueueReadBuffer(gQueue, gOutBuffer_half, CL_TRUE, 0, count * sizeof(cl_ushort), gOut_half, 0, NULL, NULL); + if (error) { + vlog_error( "Failure in clReadArray\n" ); + gFailCount++; + goto exit; + } + + error = ThreadPool_Do(CheckF, threadCount, &fchk); + if (error) { + gFailCount++; + goto exit; + } + + if (gTestDouble) { + memset_pattern4( gOut_half, &pattern, BUFFER_SIZE/2); + + error = clEnqueueWriteBuffer(gQueue, gOutBuffer_half, CL_FALSE, 0, count * sizeof(cl_ushort), gOut_half, 0, NULL, NULL); + if (error) { + vlog_error( "Failure in clWriteArray\n" ); + gFailCount++; + goto exit; + } + + error = RunKernel(doubleKernels[vectorSize][addressSpace], gInBuffer_double, gOutBuffer_half, + numVecs(count, vectorSize, aligned), + runsOverBy(count, vectorSize, aligned)); + if (error) { + gFailCount++; + goto exit; + } + + error = clEnqueueReadBuffer(gQueue, gOutBuffer_half, CL_TRUE, 0, count * sizeof(cl_ushort), gOut_half, 0, NULL, NULL); + if (error) { + vlog_error( "Failure in clReadArray\n" ); + gFailCount++; + goto exit; + } + + error = ThreadPool_Do(CheckD, threadCount, &dchk); + if (error) { + gFailCount++; + goto exit; + } + } + } + } + + if( ((i+blockCount) & ~printMask) == (i+blockCount) ) + { + vlog( "." ); + fflush( stdout ); + } + } // end last case + + loopCount = count == blockCount ? 1 : 100; + if( gReportTimes ) + { + //Init the input stream + cl_float *p = (cl_float *)gIn_single; + for( j = 0; j < count; j++ ) + p[j] = (float)((double) (rand() - RAND_MAX/2) / (RAND_MAX/2)); + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer_single, CL_TRUE, 0, count * sizeof( float ), gIn_single, 0, NULL, NULL)) ) + { + vlog_error( "Failure in clWriteArray\n" ); + gFailCount++; + goto exit; + } + + if( gTestDouble ) + { + //Init the input stream + cl_double *q = (cl_double *)gIn_double; + for( j = 0; j < count; j++ ) + q[j] = ((double) (rand() - RAND_MAX/2) / (RAND_MAX/2)); + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer_double, CL_TRUE, 0, count * sizeof( double ), gIn_double, 0, NULL, NULL)) ) + { + vlog_error( "Failure in clWriteArray\n" ); + gFailCount++; + goto exit; + } + } + + //Run again for timing + for( vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + { + uint64_t bestTime = -1ULL; + for( j = 0; j < loopCount; j++ ) + { + uint64_t startTime = ReadTime(); + + + if( (error = RunKernel( kernels[vectorSize][0], gInBuffer_single, gOutBuffer_half, numVecs(count, vectorSize, aligned) , + runsOverBy(count, vectorSize, aligned)) ) ) + { + gFailCount++; + goto exit; + } + + if( (error = clFinish(gQueue)) ) + { + vlog_error( "Failure in clFinish\n" ); + gFailCount++; + goto exit; + } + uint64_t currentTime = ReadTime() - startTime; + if( currentTime < bestTime ) + bestTime = currentTime; + time[ vectorSize ] += currentTime; + } + if( bestTime < min_time[ vectorSize ] ) + min_time[ vectorSize ] = bestTime ; + + if( gTestDouble ) + { + bestTime = -1ULL; + for( j = 0; j < loopCount; j++ ) + { + uint64_t startTime = ReadTime(); + if( (error = RunKernel( doubleKernels[vectorSize][0], gInBuffer_double, gOutBuffer_half, numVecs(count, vectorSize, aligned) , + runsOverBy(count, vectorSize, aligned)) ) ) + { + gFailCount++; + goto exit; + } + + if( (error = clFinish(gQueue)) ) + { + vlog_error( "Failure in clFinish\n" ); + gFailCount++; + goto exit; + } + uint64_t currentTime = ReadTime() - startTime; + if( currentTime < bestTime ) + bestTime = currentTime; + doubleTime[ vectorSize ] += currentTime; + } + if( bestTime < min_double_time[ vectorSize ] ) + min_double_time[ vectorSize ] = bestTime; + } + } + } + + if( 0 == gFailCount ) + { + if( gWimpyMode ) + { + vlog( "\tfloat: Wimp Passed\n" ); + if( gTestDouble ) + vlog( "\tdouble: Wimp Passed\n" ); + } + else + { + vlog( "\tfloat Passed\n" ); + if( gTestDouble ) + vlog( "\tdouble Passed\n" ); + } + } + + if( gReportTimes ) + { + for( vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + vlog_perf( SubtractTime( time[ vectorSize ], 0 ) * 1e6 * gDeviceFrequency * gComputeDevices / (double) (count * loopCount), 0, + "average us/elem", "vStoreHalf%s avg. (%s vector size: %d)", roundName, addressSpaceNames[0], (g_arrVecSizes[vectorSize]) ); + for( vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + vlog_perf( SubtractTime( min_time[ vectorSize ], 0 ) * 1e6 * gDeviceFrequency * gComputeDevices / (double) count, 0, + "best us/elem", "vStoreHalf%s best (%s vector size: %d)", roundName, addressSpaceNames[0], (g_arrVecSizes[vectorSize]) ); + if( gTestDouble ) + { + for( vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + vlog_perf( SubtractTime( doubleTime[ vectorSize ], 0 ) * 1e6 * gDeviceFrequency * gComputeDevices / (double) (count * loopCount), 0, + "average us/elem (double)", "vStoreHalf%s avg. d (%s vector size: %d)", roundName, addressSpaceNames[0], (g_arrVecSizes[vectorSize]) ); + for( vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + vlog_perf( SubtractTime( min_double_time[ vectorSize ], 0 ) * 1e6 * gDeviceFrequency * gComputeDevices / (double) count, 0, + "best us/elem (double)", "vStoreHalf%s best d (%s vector size: %d)", roundName, addressSpaceNames[0], (g_arrVecSizes[vectorSize]) ); + } + } + +exit: + //clean up + for( vectorSize = kMinVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + { + for ( addressSpace = 0; addressSpace < 3; addressSpace++) { + clReleaseKernel( kernels[ vectorSize ][ addressSpace ] ); + clReleaseProgram( programs[ vectorSize ][ addressSpace ] ); + if( gTestDouble ) + { + clReleaseKernel( doubleKernels[ vectorSize ][addressSpace] ); + clReleaseProgram( doublePrograms[ vectorSize ][addressSpace] ); + } + } + } + + gTestCount++; + return error; +} + +int Test_vStoreaHalf_private( f2h referenceFunc, d2h doubleReferenceFunc, const char *roundName ) +{ + int vectorSize, error; + cl_program programs[kVectorSizeCount+kStrangeVectorSizeCount][3]; + cl_kernel kernels[kVectorSizeCount+kStrangeVectorSizeCount][3]; + + uint64_t time[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + uint64_t min_time[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + memset( min_time, -1, sizeof( min_time ) ); + cl_program doublePrograms[kVectorSizeCount+kStrangeVectorSizeCount][3]; + cl_kernel doubleKernels[kVectorSizeCount+kStrangeVectorSizeCount][3]; + uint64_t doubleTime[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + uint64_t min_double_time[kVectorSizeCount+kStrangeVectorSizeCount] = {0}; + memset( min_double_time, -1, sizeof( min_double_time ) ); + + bool aligned = true; + + vlog( "Testing vstorea_half%s\n", roundName ); + fflush( stdout ); + + int minVectorSize = kMinVectorSize; + // There is no aligned scalar vstorea_half + if( 0 == minVectorSize ) + minVectorSize = 1; + + //Loop over vector sizes + for( vectorSize = minVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + { + const char *source[] = { + "__kernel void test( __global float", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " vstorea_half",vector_size_name_extensions[vectorSize],roundName,"( p[i], i, f );\n" + "}\n" + }; + + const char *source_v3[] = { + "__kernel void test( __global float3 *p, __global half *f )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " vstorea_half3",roundName,"( p[i], i, f );\n" + " vstore_half",roundName,"( ((__global float *)p)[4*i+3], 4*i+3, f);\n" + "}\n" + }; + + const char *source_private[] = { + "__kernel void test( __global float", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " __private float", vector_size_name_extensions[vectorSize], " data;\n" + " size_t i = get_global_id(0);\n" + " data = p[i];\n" + " vstorea_half",vector_size_name_extensions[vectorSize],roundName,"( data, i, f );\n" + "}\n" + }; + + const char *source_private_v3[] = { + "__kernel void test( __global float3 *p, __global half *f )\n" + "{\n" + " __private float", vector_size_name_extensions[vectorSize], " data;\n" + " size_t i = get_global_id(0);\n" + " data = p[i];\n" + " vstorea_half3",roundName,"( data, i, f );\n" + " vstore_half",roundName,"( ((__global float *)p)[4*i+3], 4*i+3, f);\n" + "}\n" + }; + + char local_buf_size[10]; + sprintf(local_buf_size, "%lld", (uint64_t)gWorkGroupSize); + const char *source_local[] = { + "__kernel void test( __global float", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " __local float", vector_size_name_extensions[vectorSize], " data[", local_buf_size, "];\n" + " size_t i = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " data[lid] = p[i];\n" + " vstorea_half",vector_size_name_extensions[vectorSize],roundName,"( data[lid], i, f );\n" + "}\n" + }; + + const char *source_local_v3[] = { + "__kernel void test( __global float", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " __local float", vector_size_name_extensions[vectorSize], " data[", local_buf_size, "];\n" + " size_t i = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " data[lid] = p[i];\n" + " vstorea_half",vector_size_name_extensions[vectorSize],roundName,"( data[lid], i, f );\n" + " vstore_half",roundName,"( ((__global float *)p)[4*i+3], 4*i+3, f);\n" + "}\n" + }; + + const char *double_source[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global double", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " vstorea_half",vector_size_name_extensions[vectorSize],roundName,"( p[i], i, f );\n" + "}\n" + }; + + const char *double_source_v3[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global double", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " vstorea_half",vector_size_name_extensions[vectorSize],roundName,"( p[i], i, f );\n" + " vstore_half",roundName,"( ((__global double *)p)[4*i+3], 4*i+3, f);\n" + "}\n" + }; + + const char *double_source_private[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global double", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " __private double", vector_size_name_extensions[vectorSize], " data;\n" + " size_t i = get_global_id(0);\n" + " data = p[i];\n" + " vstorea_half",vector_size_name_extensions[vectorSize],roundName,"( data, i, f );\n" + "}\n" + }; + + const char *double_source_private_v3[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global double", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " __private double", vector_size_name_extensions[vectorSize], " data;\n" + " size_t i = get_global_id(0);\n" + " data = p[i];\n" + " vstorea_half",vector_size_name_extensions[vectorSize],roundName,"( data, i, f );\n" + " vstore_half",roundName,"( ((__global double *)p)[4*i+3], 4*i+3, f);\n" + "}\n" + }; + + const char *double_source_local[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global double", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " __local double", vector_size_name_extensions[vectorSize], " data[", local_buf_size, "];\n" + " size_t i = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " data[lid] = p[i];\n" + " vstorea_half",vector_size_name_extensions[vectorSize],roundName,"( data[lid], i, f );\n" + "}\n" + }; + + const char *double_source_local_v3[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void test( __global double", vector_size_name_extensions[vectorSize]," *p, __global half *f )\n" + "{\n" + " __local double", vector_size_name_extensions[vectorSize], " data[", local_buf_size, "];\n" + " size_t i = get_global_id(0);\n" + " size_t lid = get_local_id(0);\n" + " data[lid] = p[i];\n" + " vstorea_half",vector_size_name_extensions[vectorSize],roundName,"( data[lid], i, f );\n" + " vstore_half",roundName,"( ((__global double *)p)[4*i+3], 4*i+3, f);\n" + "}\n" + }; + + if(g_arrVecSizes[vectorSize] == 3) { + programs[vectorSize][0] = MakeProgram( source_v3, sizeof(source_v3) / sizeof( source_v3[0]) ); + if( NULL == programs[ vectorSize ][0] ) + { + gFailCount++; + return -1; + } + } else { + programs[vectorSize][0] = MakeProgram( source, sizeof(source) / sizeof( source[0]) ); + if( NULL == programs[ vectorSize ][0] ) + { + gFailCount++; + return -1; + } + } + + kernels[ vectorSize ][0] = clCreateKernel( programs[ vectorSize ][0], "test", &error ); + if( NULL == kernels[vectorSize][0] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create kernel. (%d)\n", error ); + return error; + } + + if(g_arrVecSizes[vectorSize] == 3) { + programs[vectorSize][1] = MakeProgram( source_private_v3, sizeof(source_private_v3) / sizeof( source_private_v3[0]) ); + if( NULL == programs[ vectorSize ][1] ) + { + gFailCount++; + return -1; + } + } else { + programs[vectorSize][1] = MakeProgram( source_private, sizeof(source_private) / sizeof( source_private[0]) ); + if( NULL == programs[ vectorSize ][1] ) + { + gFailCount++; + return -1; + } + } + + kernels[ vectorSize ][1] = clCreateKernel( programs[ vectorSize ][1], "test", &error ); + if( NULL == kernels[vectorSize][1] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create private kernel. (%d)\n", error ); + return error; + } + + if(g_arrVecSizes[vectorSize] == 3) { + programs[vectorSize][2] = MakeProgram( source_local_v3, sizeof(source_local_v3) / sizeof( source_local_v3[0]) ); + if( NULL == programs[ vectorSize ][2] ) + { + gFailCount++; + return -1; + } + } else { + programs[vectorSize][2] = MakeProgram( source_local, sizeof(source_local) / sizeof( source_local[0]) ); + if( NULL == programs[ vectorSize ][2] ) + { + gFailCount++; + return -1; + } + } + + kernels[ vectorSize ][2] = clCreateKernel( programs[ vectorSize ][2], "test", &error ); + if( NULL == kernels[vectorSize][2] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create local kernel. (%d)\n", error ); + return error; + } + + if( gTestDouble ) + { + if(g_arrVecSizes[vectorSize] == 3) { + doublePrograms[vectorSize][0] = MakeProgram( double_source_v3, sizeof(double_source_v3) / sizeof( double_source_v3[0]) ); + if( NULL == doublePrograms[ vectorSize ][0] ) + { + gFailCount++; + return -1; + } + } else { + doublePrograms[vectorSize][0] = MakeProgram( double_source, sizeof(double_source) / sizeof( double_source[0]) ); + if( NULL == doublePrograms[ vectorSize ][0] ) + { + gFailCount++; + return -1; + } + } + + doubleKernels[ vectorSize ][0] = clCreateKernel( doublePrograms[ vectorSize ][0], "test", &error ); + if( NULL == kernels[vectorSize][0] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create double kernel. (%d)\n", error ); + return error; + } + + if(g_arrVecSizes[vectorSize] == 3) { + doublePrograms[vectorSize][1] = MakeProgram( double_source_private_v3, sizeof(double_source_private_v3) / sizeof( double_source_private_v3[0]) ); + if( NULL == doublePrograms[ vectorSize ][1] ) + { + gFailCount++; + return -1; + } + } else { + doublePrograms[vectorSize][1] = MakeProgram( double_source_private, sizeof(double_source_private) / sizeof( double_source_private[0]) ); + if( NULL == doublePrograms[ vectorSize ][1] ) + { + gFailCount++; + return -1; + } + } + + doubleKernels[ vectorSize ][1] = clCreateKernel( doublePrograms[ vectorSize ][1], "test", &error ); + if( NULL == kernels[vectorSize][1] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create double private kernel. (%d)\n", error ); + return error; + } + + if(g_arrVecSizes[vectorSize] == 3) { + doublePrograms[vectorSize][2] = MakeProgram( double_source_local_v3, sizeof(double_source_local_v3) / sizeof( double_source_local_v3[0]) ); + if( NULL == doublePrograms[ vectorSize ][2] ) + { + gFailCount++; + return -1; + } + } else { + doublePrograms[vectorSize][2] = MakeProgram( double_source_local, sizeof(double_source_local) / sizeof( double_source_local[0]) ); + if( NULL == doublePrograms[ vectorSize ][2] ) + { + gFailCount++; + return -1; + } + } + + doubleKernels[ vectorSize ][2] = clCreateKernel( doublePrograms[ vectorSize ][2], "test", &error ); + if( NULL == kernels[vectorSize][2] ) + { + gFailCount++; + vlog_error( "\t\tFAILED -- Failed to create double local kernel. (%d)\n", error ); + return error; + } + } + } + + // Figure out how many elements are in a work block + size_t elementSize = MAX( sizeof(cl_ushort), sizeof(float)); + size_t blockCount = BUFFER_SIZE / elementSize; + uint64_t lastCase = 1ULL << (8*sizeof(float)); + size_t stride = blockCount; + + if (gWimpyMode) + stride = 0x10000000U; + + // we handle 64-bit types a bit differently. + if( lastCase == 0 ) + lastCase = 0x100000000ULL; + uint64_t i, j; + error = 0; + uint64_t printMask = (lastCase >> 4) - 1; + cl_uint count = 0; + int addressSpace; + size_t loopCount; + cl_uint threadCount = GetThreadCount(); + + ComputeReferenceInfoF fref; + fref.x = (float *)gIn_single; + fref.r = (cl_ushort *)gOut_half_reference; + fref.f = referenceFunc; + fref.lim = blockCount; + fref.count = (blockCount + threadCount - 1) / threadCount; + + CheckResultInfoF fchk; + fchk.x = (const float *)gIn_single; + fchk.r = (const cl_ushort *)gOut_half_reference; + fchk.s = (const cl_ushort *)gOut_half; + fchk.f = referenceFunc; + fchk.lim = blockCount; + fchk.count = (blockCount + threadCount - 1) / threadCount; + + ComputeReferenceInfoD dref; + dref.x = (double *)gIn_double; + dref.r = (cl_ushort *)gOut_half_reference_double; + dref.f = doubleReferenceFunc; + dref.lim = blockCount; + dref.count = (blockCount + threadCount - 1) / threadCount; + + CheckResultInfoD dchk; + dchk.x = (const double *)gIn_double; + dchk.r = (const cl_ushort *)gOut_half_reference_double; + dchk.s = (const cl_ushort *)gOut_half; + dchk.f = doubleReferenceFunc; + dchk.lim = blockCount; + dchk.count = (blockCount + threadCount - 1) / threadCount; + + for( i = 0; i < (uint64_t)lastCase; i += stride ) + { + count = (cl_uint) MIN( blockCount, lastCase - i ); + fref.i = i; + dref.i = i; + + // Create the input and reference + ThreadPool_Do(ReferenceF, threadCount, &fref); + + error = clEnqueueWriteBuffer(gQueue, gInBuffer_single, CL_FALSE, 0, count * sizeof(float ), gIn_single, 0, NULL, NULL); + if (error) { + vlog_error( "Failure in clWriteArray\n" ); + gFailCount++; + goto exit; + } + + if (gTestDouble) { + ThreadPool_Do(ReferenceD, threadCount, &dref); + + error = clEnqueueWriteBuffer(gQueue, gInBuffer_double, CL_FALSE, 0, count * sizeof(double ), gIn_double, 0, NULL, NULL); + if (error) { + vlog_error( "Failure in clWriteArray\n" ); + gFailCount++; + goto exit; + } + } + + for (vectorSize = minVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) { + // Loop over vector legths + fchk.vsz = g_arrVecSizes[vectorSize]; + dchk.vsz = g_arrVecSizes[vectorSize]; + + for ( addressSpace = 0; addressSpace < 3; addressSpace++) { + // Loop over address spaces + fchk.aspace = addressSpaceNames[addressSpace]; + dchk.aspace = addressSpaceNames[addressSpace]; + + cl_uint pattern = 0xdeaddead; + memset_pattern4(gOut_half, &pattern, BUFFER_SIZE/2); + + error = clEnqueueWriteBuffer(gQueue, gOutBuffer_half, CL_FALSE, 0, count * sizeof(cl_ushort), gOut_half, 0, NULL, NULL); + if (error) { + vlog_error( "Failure in clWriteArray\n" ); + gFailCount++; + goto exit; + } + + error = RunKernel(kernels[vectorSize][addressSpace], gInBuffer_single, gOutBuffer_half, + numVecs(count, vectorSize, aligned), + runsOverBy(count, vectorSize, aligned)); + if (error) { + gFailCount++; + goto exit; + } + + error = clEnqueueReadBuffer(gQueue, gOutBuffer_half, CL_TRUE, 0, count * sizeof(cl_ushort), gOut_half, 0, NULL, NULL); + if (error) { + vlog_error( "Failure in clReadArray\n" ); + gFailCount++; + goto exit; + } + + error = ThreadPool_Do(CheckF, threadCount, &fchk); + if (error) { + gFailCount++; + goto exit; + } + + if (gTestDouble) { + memset_pattern4(gOut_half, &pattern, BUFFER_SIZE/2); + + error = clEnqueueWriteBuffer(gQueue, gOutBuffer_half, CL_FALSE, 0, count * sizeof(cl_ushort), gOut_half, 0, NULL, NULL); + if (error) { + vlog_error( "Failure in clWriteArray\n" ); + gFailCount++; + goto exit; + } + + error = RunKernel(doubleKernels[vectorSize][addressSpace], gInBuffer_double, gOutBuffer_half, + numVecs(count, vectorSize, aligned), + runsOverBy(count, vectorSize, aligned)); + if (error) { + gFailCount++; + goto exit; + } + + error = clEnqueueReadBuffer(gQueue, gOutBuffer_half, CL_TRUE, 0, count * sizeof(cl_ushort), gOut_half, 0, NULL, NULL); + if (error) { + vlog_error( "Failure in clReadArray\n" ); + gFailCount++; + goto exit; + } + + error = ThreadPool_Do(CheckD, threadCount, &dchk); + if (error) { + gFailCount++; + goto exit; + } + } + } + } // end for vector size + + if( ((i+blockCount) & ~printMask) == (i+blockCount) ) { + vlog( "." ); + fflush( stdout ); + } + } // for end lastcase + + loopCount = count == blockCount ? 1 : 100; + if( gReportTimes ) + { + //Init the input stream + cl_float *p = (cl_float *)gIn_single; + for( j = 0; j < count; j++ ) + p[j] = (float)((double) (rand() - RAND_MAX/2) / (RAND_MAX/2)); + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer_single, CL_TRUE, 0, count * sizeof( float ), gIn_single, 0, NULL, NULL)) ) + { + vlog_error( "Failure in clWriteArray\n" ); + gFailCount++; + goto exit; + } + + if( gTestDouble ) + { + //Init the input stream + cl_double *q = (cl_double *)gIn_double; + for( j = 0; j < count; j++ ) + q[j] = ((double) (rand() - RAND_MAX/2) / (RAND_MAX/2)); + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer_double, CL_TRUE, 0, count * sizeof( double ), gIn_double, 0, NULL, NULL)) ) + { + vlog_error( "Failure in clWriteArray\n" ); + gFailCount++; + goto exit; + } + } + + //Run again for timing + for( vectorSize = minVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + { + uint64_t bestTime = -1ULL; + for( j = 0; j < loopCount; j++ ) + { + uint64_t startTime = ReadTime(); + if( (error = RunKernel( kernels[vectorSize][0], gInBuffer_single, gOutBuffer_half, numVecs(count, vectorSize, aligned) , + runsOverBy(count, vectorSize, aligned)) ) ) + { + gFailCount++; + goto exit; + } + + if( (error = clFinish(gQueue)) ) + { + vlog_error( "Failure in clFinish\n" ); + gFailCount++; + goto exit; + } + uint64_t currentTime = ReadTime() - startTime; + if( currentTime < bestTime ) + bestTime = currentTime; + time[ vectorSize ] += currentTime; + } + if( bestTime < min_time[ vectorSize ] ) + min_time[ vectorSize ] = bestTime ; + + if( gTestDouble ) + { + bestTime = -1ULL; + for( j = 0; j < loopCount; j++ ) + { + uint64_t startTime = ReadTime(); + if( (error = RunKernel( doubleKernels[vectorSize][0], gInBuffer_double, gOutBuffer_half, numVecs(count, vectorSize, aligned) , + runsOverBy(count, vectorSize, aligned)) ) ) + { + gFailCount++; + goto exit; + } + + if( (error = clFinish(gQueue)) ) + { + vlog_error( "Failure in clFinish\n" ); + gFailCount++; + goto exit; + } + uint64_t currentTime = ReadTime() - startTime; + if( currentTime < bestTime ) + bestTime = currentTime; + doubleTime[ vectorSize ] += currentTime; + } + if( bestTime < min_double_time[ vectorSize ] ) + min_double_time[ vectorSize ] = bestTime; + } + } + } + + if( gWimpyMode ) + { + vlog( "\tfloat: Wimp Passed\n" ); + + if( gTestDouble ) + vlog( "\tdouble: Wimp Passed\n" ); + } + else + { + vlog( "\tfloat Passed\n" ); + if( gTestDouble ) + vlog( "\tdouble Passed\n" ); + } + + if( gReportTimes ) + { + for( vectorSize = minVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + vlog_perf( SubtractTime( time[ vectorSize ], 0 ) * 1e6 * gDeviceFrequency * gComputeDevices / (double) (count * loopCount), 0, + "average us/elem", "vStoreaHalf%s avg. (%s vector size: %d)", roundName, addressSpaceNames[0], (g_arrVecSizes[vectorSize]) ); + for( vectorSize = minVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + vlog_perf( SubtractTime( min_time[ vectorSize ], 0 ) * 1e6 * gDeviceFrequency * gComputeDevices / (double) count, 0, + "best us/elem", "vStoreaHalf%s best (%s vector size: %d)", roundName, addressSpaceNames[0], (g_arrVecSizes[vectorSize]) ); + if( gTestDouble ) + { + for( vectorSize = minVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + vlog_perf( SubtractTime( doubleTime[ vectorSize ], 0 ) * 1e6 * gDeviceFrequency * gComputeDevices / (double) (count * loopCount), 0, + "average us/elem (double)", "vStoreaHalf%s avg. d (%s vector size: %d)", roundName, addressSpaceNames[0], (g_arrVecSizes[vectorSize]) ); + for( vectorSize = minVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + vlog_perf( SubtractTime( min_double_time[ vectorSize ], 0 ) * 1e6 * gDeviceFrequency * gComputeDevices / (double) count, 0, + "best us/elem (double)", "vStoreaHalf%s best d (%s vector size: %d)", roundName, addressSpaceNames[0], (g_arrVecSizes[vectorSize]) ); + } + } + +exit: + //clean up + for( vectorSize = minVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++) + { + for ( addressSpace = 0; addressSpace < 3; addressSpace++) { + clReleaseKernel( kernels[ vectorSize ][addressSpace] ); + clReleaseProgram( programs[ vectorSize ][addressSpace] ); + if( gTestDouble ) + { + clReleaseKernel( doubleKernels[ vectorSize ][addressSpace] ); + clReleaseProgram( doublePrograms[ vectorSize ][addressSpace] ); + } + } + } + + gTestCount++; + return error; +} + diff --git a/test_conformance/half/cl_utils.c b/test_conformance/half/cl_utils.c new file mode 100644 index 00000000..939cddf3 --- /dev/null +++ b/test_conformance/half/cl_utils.c @@ -0,0 +1,493 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "cl_utils.h" +#include + +#if !defined (_WIN32) +#include +#endif + +#include "test_config.h" +#include "string.h" +#include "../../test_common/harness/kernelHelpers.h" + +#define HALF_MIN 1.0p-14 + + +const char *vector_size_name_extensions[kVectorSizeCount+kStrangeVectorSizeCount] = { "", "2", "4", "8", "16", "3" }; +const char *vector_size_strings[kVectorSizeCount+kStrangeVectorSizeCount] = { "1", "2", "4", "8", "16", "3" }; +const char *align_divisors[kVectorSizeCount+kStrangeVectorSizeCount] = { "1", "2", "4", "8", "16", "4" }; +const char *align_types[kVectorSizeCount+kStrangeVectorSizeCount] = { "half", "int", "int2", "int4", "int8", "int2" }; + + +void *gIn_half = NULL; +void *gOut_half = NULL; +void *gOut_half_reference = NULL; +void *gOut_half_reference_double = NULL; +void *gIn_single = NULL; +void *gOut_single = NULL; +void *gOut_single_reference = NULL; +void *gIn_double = NULL; +// void *gOut_double = NULL; +// void *gOut_double_reference = NULL; +cl_mem gInBuffer_half = NULL; +cl_mem gOutBuffer_half = NULL; +cl_mem gInBuffer_single = NULL; +cl_mem gOutBuffer_single = NULL; +cl_mem gInBuffer_double = NULL; +// cl_mem gOutBuffer_double = NULL; + +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +cl_device_id gDevice = NULL; +cl_context gContext = NULL; +cl_command_queue gQueue = NULL; +uint32_t gDeviceFrequency = 0; +uint32_t gComputeDevices = 0; +size_t gMaxThreadGroupSize = 0; +size_t gWorkGroupSize = 0; +int gTestCount = 0; +int gFailCount = 0; +bool gWimpyMode = false; +int gTestDouble = 0; +uint32_t gDeviceIndex = 0; +int gIsEmbedded = 0; + +#if defined( __APPLE__ ) +int gReportTimes = 1; +#else +int gReportTimes = 0; +#endif + +#pragma mark - + +static void CL_CALLBACK notify_callback(const char *errinfo, const void *private_info, size_t cb, void *user_data) +{ + vlog( "%s\n", errinfo ); +} + +int InitCL( void ) +{ + cl_platform_id platform = NULL; + size_t configSize = sizeof( gComputeDevices ); + int error; + + if( (error = clGetPlatformIDs(1, &platform, NULL) ) ) + return error; + + // gDeviceType & gDeviceIndex are globals set in ParseArgs + + cl_uint ndevices; + if ( (error = clGetDeviceIDs(platform, gDeviceType, 0, NULL, &ndevices)) ) + return error; + + cl_device_id *gDeviceList = (cl_device_id *)malloc(ndevices*sizeof( cl_device_id )); + if ( gDeviceList == 0 ) + { + log_error("Unable to allocate memory for devices\n"); + return -1; + } + if( (error = clGetDeviceIDs(platform, gDeviceType, ndevices, gDeviceList, NULL )) ) + { + free( gDeviceList ); + return error; + } + + gDevice = gDeviceList[gDeviceIndex]; + free( gDeviceList ); + +#if MULTITHREAD + if( (error = clGetDeviceInfo( gDevice, CL_DEVICE_MAX_COMPUTE_UNITS, configSize, &gComputeDevices, NULL )) ) +#endif + gComputeDevices = 1; + + configSize = sizeof( gMaxThreadGroupSize ); + if( (error = clGetDeviceInfo( gDevice, CL_DEVICE_MAX_WORK_GROUP_SIZE, configSize, &gMaxThreadGroupSize, NULL )) ) + gMaxThreadGroupSize = 1; + + // Use only one-eighth the work group size + if (gMaxThreadGroupSize > 8) + gWorkGroupSize = gMaxThreadGroupSize / 8; + else + gWorkGroupSize = gMaxThreadGroupSize; + + configSize = sizeof( gDeviceFrequency ); + if( (error = clGetDeviceInfo( gDevice, CL_DEVICE_MAX_CLOCK_FREQUENCY, configSize, &gDeviceFrequency, NULL )) ) + gDeviceFrequency = 1; + + // Check extensions + size_t extSize = 0; + int hasDouble = 0; + if((error = clGetDeviceInfo( gDevice, CL_DEVICE_EXTENSIONS, 0, NULL, &extSize))) + { vlog_error( "Unable to get device extension string to see if double present. (%d) \n", error ); } + else + { + char *ext = (char *)malloc( extSize ); + if( NULL == ext ) + { vlog_error( "malloc failed at %s:%d\nUnable to determine if double present.\n", __FILE__, __LINE__ ); } + else + { + if((error = clGetDeviceInfo( gDevice, CL_DEVICE_EXTENSIONS, extSize, ext, NULL))) + { vlog_error( "Unable to get device extension string to see if double present. (%d) \n", error ); } + else + { + if( strstr( ext, "cl_khr_fp64" )) + hasDouble = 1; + } + free(ext); + } + } + gTestDouble ^= hasDouble; + + + + //detect whether profile of the device is embedded + char profile[64] = ""; + if( (error = clGetDeviceInfo( gDevice, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL ) ) ) + { + vlog_error( "Unable to get device CL DEVICE PROFILE string. (%d) \n", error ); + } + else if( strstr(profile, "EMBEDDED_PROFILE" ) ) + { + gIsEmbedded = 1; + } + + vlog( "%d compute devices at %f GHz\n", gComputeDevices, (double) gDeviceFrequency / 1000. ); + vlog( "Max thread group size is %lld.\n", (uint64_t) gMaxThreadGroupSize ); + + gContext = clCreateContext( NULL, 1, &gDevice, notify_callback, NULL, &error ); + if( NULL == gContext ) + { + vlog_error( "clCreateDeviceGroup failed. (%d)\n", error ); + return -1; + } + + gQueue = clCreateCommandQueueWithProperties(gContext, gDevice, 0, &error); + if( NULL == gQueue ) + { + vlog_error( "clCreateContext failed. (%d)\n", error ); + return -2; + } + +#if defined( __APPLE__ ) + // FIXME: use clProtectedArray +#endif + //Allocate buffers + gIn_half = malloc( getBufferSize(gDevice)/2 ); + gOut_half = malloc( BUFFER_SIZE/2 ); + gOut_half_reference = malloc( BUFFER_SIZE/2 ); + gOut_half_reference_double = malloc( BUFFER_SIZE/2 ); + gIn_single = malloc( BUFFER_SIZE ); + gOut_single = malloc( getBufferSize(gDevice) ); + gOut_single_reference = malloc( getBufferSize(gDevice) ); + gIn_double = malloc( 2*BUFFER_SIZE ); + // gOut_double = malloc( (2*getBufferSize(gDevice)) ); + // gOut_double_reference = malloc( (2*getBufferSize(gDevice)) ); + + if ( NULL == gIn_half || + NULL == gOut_half || + NULL == gOut_half_reference || + NULL == gOut_half_reference_double || + NULL == gIn_single || + NULL == gOut_single || + NULL == gOut_single_reference || + NULL == gIn_double // || NULL == gOut_double || NULL == gOut_double_reference + ) + return -3; + + gInBuffer_half = clCreateBuffer(gContext, CL_MEM_READ_ONLY, getBufferSize(gDevice) / 2, NULL, &error); + if( gInBuffer_half == NULL ) + { + vlog_error( "clCreateArray failed for input (%d)\n", error ); + return -4; + } + + gInBuffer_single = clCreateBuffer(gContext, CL_MEM_READ_ONLY, BUFFER_SIZE, NULL, &error ); + if( gInBuffer_single == NULL ) + { + vlog_error( "clCreateArray failed for input (%d)\n", error ); + return -4; + } + + gInBuffer_double = clCreateBuffer(gContext, CL_MEM_READ_ONLY, BUFFER_SIZE*2, NULL, &error ); + if( gInBuffer_double == NULL ) + { + vlog_error( "clCreateArray failed for input (%d)\n", error ); + return -4; + } + + gOutBuffer_half = clCreateBuffer(gContext, CL_MEM_WRITE_ONLY, BUFFER_SIZE/2, NULL, &error ); + if( gOutBuffer_half == NULL ) + { + vlog_error( "clCreateArray failed for output (%d)\n", error ); + return -5; + } + + gOutBuffer_single = clCreateBuffer(gContext, CL_MEM_WRITE_ONLY, getBufferSize(gDevice), NULL, &error ); + if( gOutBuffer_single == NULL ) + { + vlog_error( "clCreateArray failed for output (%d)\n", error ); + return -5; + } + +#if 0 + gOutBuffer_double = clCreateBuffer(gContext, CL_MEM_WRITE_ONLY, (size_t)(2*getBufferSize(gDevice)), NULL, &error ); + if( gOutBuffer_double == NULL ) + { + vlog_error( "clCreateArray failed for output (%d)\n", error ); + return -5; + } +#endif + + char string[16384]; + vlog( "\nCompute Device info:\n" ); + error = clGetDeviceInfo(gDevice, CL_DEVICE_NAME, sizeof(string), string, NULL); + vlog( "\tDevice Name: %s\n", string ); + error = clGetDeviceInfo(gDevice, CL_DEVICE_VENDOR, sizeof(string), string, NULL); + vlog( "\tVendor: %s\n", string ); + error = clGetDeviceInfo(gDevice, CL_DEVICE_VERSION, sizeof(string), string, NULL); + vlog( "\tDevice Version: %s\n", string ); + error = clGetDeviceInfo(gDevice, CL_DEVICE_OPENCL_C_VERSION, sizeof(string), string, NULL); + vlog( "\tOpenCL C Version: %s\n", string ); + error = clGetDeviceInfo(gDevice, CL_DRIVER_VERSION, sizeof(string), string, NULL); + vlog( "\tDriver Version: %s\n", string ); + vlog( "\tProcessing with %d devices\n", gComputeDevices ); + vlog( "\tDevice Frequency: %d MHz\n", gDeviceFrequency ); + vlog( "\tHas double? %s\n", hasDouble ? "YES" : "NO" ); + vlog( "\tTest double? %s\n", gTestDouble ? "YES" : "NO" ); + + return 0; +} + +cl_program MakeProgram( const char *source[], int count ) +{ + int error; + int i; + + //create the program + cl_program program; + error = create_single_kernel_helper_create_program(gContext, &program, (cl_uint)count, source); + if( NULL == program ) + { + vlog_error( "\t\tFAILED -- Failed to create program. (%d)\n", error ); + return NULL; + } + + // build it + if( (error = clBuildProgram( program, 1, &gDevice, NULL, NULL, NULL )) ) + { + size_t len; + char buffer[16384]; + + vlog_error("\t\tFAILED -- clBuildProgramExecutable() failed:\n"); + clGetProgramBuildInfo(program, gDevice, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len); + vlog_error("Log: %s\n", buffer); + vlog_error("Source :\n"); + for(i = 0; i < count; ++i) { + vlog_error("%s", source[i]); + } + vlog_error("\n"); + + clReleaseProgram( program ); + return NULL; + } + + return program; +} + +void ReleaseCL(void) +{ + clReleaseMemObject(gInBuffer_half); + clReleaseMemObject(gOutBuffer_half); + clReleaseMemObject(gInBuffer_single); + clReleaseMemObject(gOutBuffer_single); + clReleaseMemObject(gInBuffer_double); + // clReleaseMemObject(gOutBuffer_double); + clReleaseCommandQueue(gQueue); + clReleaseContext(gContext); +} + +cl_uint numVecs(cl_uint count, int vectorSizeIdx, bool aligned) { + if(aligned && g_arrVecSizes[vectorSizeIdx] == 3) { + return count/4; + } + return (count + g_arrVecSizes[vectorSizeIdx] - 1)/ + ( (g_arrVecSizes[vectorSizeIdx]) ); +} + +cl_uint runsOverBy(cl_uint count, int vectorSizeIdx, bool aligned) { + if(aligned || g_arrVecSizes[vectorSizeIdx] != 3) { return -1; } + return count% (g_arrVecSizes[vectorSizeIdx]); +} + +void printSource(const char * src[], int len) { + int i; + for(i = 0; i < len; ++i) { + vlog("%s", src[i]); + } +} + +int RunKernel( cl_kernel kernel, void *inBuf, void *outBuf, uint32_t blockCount , int extraArg) +{ + size_t localCount = blockCount; + size_t wg_size; + int error; + + error = clSetKernelArg(kernel, 0, sizeof inBuf, &inBuf); + error |= clSetKernelArg(kernel, 1, sizeof outBuf, &outBuf); + + if(extraArg >= 0) { + error |= clSetKernelArg(kernel, 2, sizeof(cl_uint), &extraArg); + } + + if( error ) + { + vlog_error( "FAILED -- could not set kernel args\n" ); + return -3; + } + + error = clGetKernelWorkGroupInfo(kernel, gDevice, CL_KERNEL_WORK_GROUP_SIZE, sizeof( wg_size ), &wg_size, NULL); + if (error) + { + vlog_error( "FAILED -- could not get kernel work group info\n" ); + return -4; + } + + wg_size = (wg_size > gWorkGroupSize) ? gWorkGroupSize : wg_size; + while( localCount % wg_size ) + wg_size--; + + if( (error = clEnqueueNDRangeKernel( gQueue, kernel, 1, NULL, &localCount, &wg_size, 0, NULL, NULL )) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + return -5; + } + + return 0; +} + +#if defined (__APPLE__ ) + +#include + +uint64_t ReadTime( void ) +{ + return mach_absolute_time(); // returns time since boot. Ticks have better than microsecond precsion. +} + +double SubtractTime( uint64_t endTime, uint64_t startTime ) +{ + static double conversion = 0.0; + + if( 0.0 == conversion ) + { + mach_timebase_info_data_t info; + kern_return_t err = mach_timebase_info( &info ); + if( 0 == err ) + conversion = 1e-9 * (double) info.numer / (double) info.denom; + } + + return (double) (endTime - startTime) * conversion; +} + +#elif defined( _WIN32 ) && defined (_MSC_VER) + +// functions are defined in compat.h + +#else + +// +// Please feel free to substitute your own timing facility here. +// + +#warning Times are meaningless. No timing facility in place for this platform. +uint64_t ReadTime( void ) +{ + return 0ULL; +} + +// return the difference between two times obtained from ReadTime in seconds +double SubtractTime( uint64_t endTime, uint64_t startTime ) +{ + return INFINITY; +} + +#endif + +#if !defined( __APPLE__ ) +void memset_pattern4(void *dest, const void *src_pattern, size_t bytes ) +{ + uint32_t pat = ((uint32_t*) src_pattern)[0]; + size_t count = bytes / 4; + size_t i; + uint32_t *d = (uint32_t*)dest; + + for( i = 0; i < count; i++ ) + d[i] = pat; + + d += i; + + bytes &= 3; + if( bytes ) + memcpy( d, src_pattern, bytes ); +} +#endif + +size_t getBufferSize(cl_device_id device_id) +{ + static int s_initialized = 0; + static cl_device_id s_device_id; + static cl_ulong s_result = 64*1024; + + if(s_initialized == 0 || s_device_id != device_id) + { + cl_ulong result; + cl_int err = clGetDeviceInfo (device_id, + CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, + sizeof(result), (void *)&result, + NULL); + if(err) + { + vlog_error("clGetDeviceInfo() failed\n"); + s_result = 64*1024; + goto exit; + } + result = result / 2; + log_info("Const buffer size is %llx (%llu)\n", result, result); + s_initialized = 1; + s_device_id = device_id; + s_result = result; + } + +exit: + if( s_result > SIZE_MAX ) + { + vlog_error( "ERROR: clGetDeviceInfo is reporting a CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE larger than addressable memory on the host.\n It seems highly unlikely that this is usable, due to the API design.\n" ); + fflush(stdout); + abort(); + } + + return (size_t) s_result; +} + +cl_ulong getBufferCount(cl_device_id device_id, size_t vecSize, size_t typeSize) +{ + cl_ulong tmp = getBufferSize(device_id); + if(vecSize == 3) + { + return tmp/(cl_ulong)(4*typeSize); + } + return tmp/(cl_ulong)(vecSize*typeSize); +} diff --git a/test_conformance/half/cl_utils.h b/test_conformance/half/cl_utils.h new file mode 100644 index 00000000..9a720efd --- /dev/null +++ b/test_conformance/half/cl_utils.h @@ -0,0 +1,162 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef CL_UTILS_H +#define CL_UTILS_H + +#include "../../test_common/harness/compat.h" + +#include + +#if !defined(_WIN32) +#include +#endif + + +#ifdef __MINGW32__ +#define __mingw_printf printf +#endif +#include "../../test_common/harness/errorHelpers.h" + +#include "../../test_common/harness/ThreadPool.h" + + + +#include "test_config.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +extern void *gIn_half; +extern void *gOut_half; +extern void *gOut_half_reference; +extern void *gOut_half_reference_double; +extern void *gIn_single; +extern void *gOut_single; +extern void *gOut_single_reference; +extern void *gIn_double; +// extern void *gOut_double; +// extern void *gOut_double_reference; +extern cl_mem gInBuffer_half; +extern cl_mem gOutBuffer_half; +extern cl_mem gInBuffer_single; +extern cl_mem gOutBuffer_single; +extern cl_mem gInBuffer_double; +// extern cl_mem gOutBuffer_double; + +extern uint32_t gDeviceIndex; +extern cl_device_type gDeviceType; +extern cl_device_id gDevice; +extern cl_context gContext; +extern cl_command_queue gQueue; +extern uint32_t gDeviceFrequency; +extern uint32_t gComputeDevices; +extern size_t gMaxThreadGroupSize; +extern size_t gWorkGroupSize; +extern int gTestCount; +extern int gFailCount; +extern int gTestDouble; +extern int gReportTimes; +extern int gIsEmbedded; + +// gWimpyMode indicates if we run the test in wimpy mode where we limit the +// size of 32 bit ranges to a much smaller set. This is meant to be used +// as a smoke test +extern bool gWimpyMode; + +uint64_t ReadTime( void ); +double SubtractTime( uint64_t endTime, uint64_t startTime ); + +cl_uint numVecs(cl_uint count, int vectorSizeIdx, bool aligned); +cl_uint runsOverBy(cl_uint count, int vectorSizeIdx, bool aligned); + +void printSource(const char * src[], int len); + +extern const char *vector_size_name_extensions[kVectorSizeCount+kStrangeVectorSizeCount]; +extern const char *vector_size_strings[kVectorSizeCount+kStrangeVectorSizeCount]; +extern const char *align_divisors[kVectorSizeCount+kStrangeVectorSizeCount]; +extern const char *align_types[kVectorSizeCount+kStrangeVectorSizeCount]; + +int InitCL( void ); +void ReleaseCL( void ); +int RunKernel( cl_kernel kernel, void *inBuf, void *outBuf, uint32_t blockCount , int extraArg); +cl_program MakeProgram( const char *source[], int count ); + +#if ! defined( __APPLE__ ) + extern void memset_pattern4(void *dest, const void *src_pattern, size_t bytes ); +#endif + +#define STRING( _x ) STRINGIFY( _x ) +#define STRINGIFY(x) #x + +static inline float as_float(cl_uint u) { union { cl_uint u; float f; }v; v.u = u; return v.f; } +static inline double as_double(cl_ulong u) { union { cl_ulong u; double d; }v; v.u = u; return v.d; } + +// used to convert a bucket of bits into a search pattern through double +static inline cl_ulong DoubleFromUInt( cl_uint bits ); +static inline cl_ulong DoubleFromUInt( cl_uint bits ) +{ + // split 0x89abcdef to 0x89abcd00000000ef + cl_ulong u = ((cl_ulong)(bits & ~0xffU) << 32) | ((cl_ulong)(bits & 0xffU)); + + // sign extend the leading bit of def segment as sign bit so that the middle region consists of either all 1s or 0s + u -= (cl_ulong)((bits & 0x80U) << 1); + + return u; +} + +static inline int IsHalfSubnormal( uint16_t x ) +{ + return ((x&0x7fffU)-1U) < 0x03ffU; +} + +// prevent silent failures due to missing FLT_RADIX +#ifndef FLT_RADIX + #error FLT_RADIX is not defined by float.h +#endif + +static inline int IsFloatSubnormal( double x ) +{ +#if 2 == FLT_RADIX + // Do this in integer to avoid problems with FTZ behavior + union{ float d; uint32_t u;}u; + u.d = fabsf((float) x); + return (u.u-1) < 0x007fffffU; +#else + // rely on floating point hardware for non-radix2 non-IEEE-754 hardware -- will fail if you flush subnormals to zero + return fabs(x) < (double) FLT_MIN && x != 0.0; +#endif +} + +static inline int IsDoubleSubnormal( long double x ) +{ +#if 2 == FLT_RADIX + // Do this in integer to avoid problems with FTZ behavior + union{ double d; uint64_t u;}u; + u.d = fabs((double)x); + return (u.u-1) < 0x000fffffffffffffULL; +#else + // rely on floating point hardware for non-radix2 non-IEEE-754 hardware -- will fail if you flush subnormals to zero + return fabs(x) < (double) DBL_MIN && x != 0.0; +#endif +} + +#endif /* CL_UTILS_H */ + + + diff --git a/test_conformance/half/main.c b/test_conformance/half/main.c new file mode 100644 index 00000000..fe3b6f17 --- /dev/null +++ b/test_conformance/half/main.c @@ -0,0 +1,434 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include + +#if !defined (_WIN32) +#include +#if !defined(__ANDROID__) +#include +#endif +#include +#include +#endif + +#include "../../test_common/harness/mingw_compat.h" +#include "../../test_common/harness/parseParameters.h" +#if defined (__MINGW32__) +#include +#endif + +#include "cl_utils.h" +#include "tests.h" + +const char ** argList = NULL; +size_t argCount = 0; +char appName[64] = "ctest"; +const char *addressSpaceNames[] = {"global", "private", "local", "constant"}; + +#pragma mark - +#pragma mark Declarations + + +static int ParseArgs( int argc, const char **argv ); +static void PrintUsage( void ); +static void PrintArch(void); +static void PrintDevice(void); +static int DoTest( void); + + +int g_arrVecSizes[kVectorSizeCount+kStrangeVectorSizeCount]; +int g_arrVecAligns[kLargestVectorSize+1]; +static int arrStrangeVecSizes[kStrangeVectorSizeCount] = {3}; + +int main (int argc, const char **argv ) +{ + int error; + int i; + int alignbound; + + for(i = 0; i < kVectorSizeCount; ++i) { + g_arrVecSizes[i] = (1< 1) + vlog("PASSED %d of %d tests.\n", gTestCount, gTestCount); + else + vlog("PASSED test.\n"); + } else if (gFailCount > 0) { + if (gFailCount+gTestCount > 1) + vlog_error("FAILED %d of %d tests.\n", gFailCount, gTestCount+gFailCount); + else + vlog_error("FAILED test.\n"); + } + + if (gQueue) { + int flush_error = clFinish(gQueue); + if (flush_error) + vlog_error("clFinish failed: %d\n", flush_error); + } + + ReleaseCL(); + test_finish(); + + if (gFailCount) + return gFailCount; + + return error; +} + +#pragma mark - +#pragma mark setup + +static int ParseArgs( int argc, const char **argv ) +{ + int i; + argList = (const char **)calloc( argc - 1, sizeof( char*) ); + + argCount = 0; + + if( NULL == argList && argc > 1 ) + return -1; + +#if (defined( __APPLE__ ) || defined(__linux__) || defined(__MINGW32__)) + { // Extract the app name + char baseName[ MAXPATHLEN ]; + strncpy( baseName, argv[0], MAXPATHLEN ); + char *base = basename( baseName ); + if( NULL != base ) + { + strncpy( appName, base, sizeof( appName ) ); + appName[ sizeof( appName ) -1 ] = '\0'; + } + } +#elif defined (_WIN32) + { + char fname[_MAX_FNAME + _MAX_EXT + 1]; + char ext[_MAX_EXT]; + + errno_t err = _splitpath_s( argv[0], NULL, 0, NULL, 0, + fname, _MAX_FNAME, ext, _MAX_EXT ); + if (err == 0) { // no error + strcat (fname, ext); //just cat them, size of frame can keep both + strncpy (appName, fname, sizeof(appName)); + appName[ sizeof( appName ) -1 ] = '\0'; + } + } +#endif + + /* Check for environment variable to set device type */ + char *env_mode = getenv( "CL_DEVICE_TYPE" ); + if( env_mode != NULL ) + { + if( strcmp( env_mode, "gpu" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_GPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_GPU; + else if( strcmp( env_mode, "cpu" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_CPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_CPU; + else if( strcmp( env_mode, "accelerator" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( env_mode, "default" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_DEFAULT; + else + { + vlog_error( "Unknown CL_DEVICE_TYPE env variable setting: %s.\nAborting...\n", env_mode ); + abort(); + } + } + + unsigned int num_devices; + cl_platform_id platform = NULL; + clGetPlatformIDs(1, &platform, NULL); + clGetDeviceIDs(platform, gDeviceType, 0, NULL, &num_devices); + + const char* device_index_env = getenv("CL_DEVICE_INDEX"); + if (device_index_env) { + if (device_index_env) { + gDeviceIndex = atoi(device_index_env); + } + + if (gDeviceIndex >= num_devices) { + vlog("Specified CL_DEVICE_INDEX=%d out of range, using index 0.\n", + gDeviceIndex); + gDeviceIndex = 0; + } + } + + vlog( "\n%s", appName ); + for( i = 1; i < argc; i++ ) + { + const char *arg = argv[i]; + if( NULL == arg ) + break; + + vlog( "\t%s", arg ); + if( arg[0] == '-' ) + { + arg++; + while( *arg != '\0' ) + { + switch( *arg ) + { + case 'd': + gTestDouble ^= 1; + break; + + case 'h': + PrintUsage(); + return -1; + + case 't': + gReportTimes ^= 1; + break; + + case 'w': // Wimpy mode + gWimpyMode = true; + break; + + default: + vlog_error( " <-- unknown flag: %c (0x%2.2x)\n)", *arg, *arg ); + PrintUsage(); + return -1; + } + arg++; + } + } + else + { + if( 0 == strcmp( arg, "CL_DEVICE_TYPE_CPU" ) ) + gDeviceType = CL_DEVICE_TYPE_CPU; + else if( 0 == strcmp( arg, "CL_DEVICE_TYPE_GPU" ) ) + gDeviceType = CL_DEVICE_TYPE_GPU; + else if( 0 == strcmp( arg, "CL_DEVICE_TYPE_ACCELERATOR" ) ) + gDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + else if( 0 == strcmp( arg, "CL_DEVICE_TYPE_DEFAULT" ) ) + gDeviceType = CL_DEVICE_TYPE_DEFAULT; + else + { + argList[ argCount ] = arg; + argCount++; + } + } + } + + if (getenv("CL_WIMPY_MODE")) { + vlog( "\n" ); + vlog( "*** Detected CL_WIMPY_MODE env ***\n" ); + gWimpyMode = 1; + } + + vlog( "Test binary built %s %s\n", __DATE__, __TIME__ ); + PrintArch(); + PrintDevice(); + if( gWimpyMode ) + { + vlog( "\n" ); + vlog( "*** WARNING: Testing in Wimpy mode! ***\n" ); + vlog( "*** Wimpy mode is not sufficient to verify correctness. ***\n" ); + vlog( "*** It gives warm fuzzy feelings and then nevers calls. ***\n\n" ); + } + return 0; +} + +static void PrintUsage( void ) +{ + vlog( "%s [-dthw]: \n", appName ); + vlog( "\t\t-d\tToggle double precision testing (default: on if double supported)\n" ); + vlog( "\t\t-t\tToggle reporting performance data.\n" ); + vlog( "\t\t-w\tRun in wimpy mode\n" ); + vlog( "\t\t-h\tHelp\n" ); + vlog( "\n" ); +} + +static void PrintArch( void ) +{ + vlog( "sizeof( void*) = %ld\n", sizeof( void *) ); + +#if defined( __APPLE__ ) +#if defined( __ppc__ ) + vlog( "ARCH:\tppc\n" ); +#elif defined( __ppc64__ ) + vlog( "ARCH:\tppc64\n" ); +#elif defined( __i386__ ) + vlog( "ARCH:\ti386\n" ); +#elif defined( __x86_64__ ) + vlog( "ARCH:\tx86_64\n" ); +#elif defined( __arm__ ) + vlog( "ARCH:\tarm\n" ); +#else +#error unknown arch +#endif + + int type = 0; + size_t typeSize = sizeof( type ); + sysctlbyname( "hw.cputype", &type, &typeSize, NULL, 0 ); + vlog( "cpu type:\t%d\n", type ); + typeSize = sizeof( type ); + sysctlbyname( "hw.cpusubtype", &type, &typeSize, NULL, 0 ); + vlog( "cpu subtype:\t%d\n", type ); +#endif +} + +static void PrintDevice( void) +{ + switch(gDeviceType) { + case CL_DEVICE_TYPE_CPU: + vlog( "DEVICE:\tcpu\n" ); + break; + case CL_DEVICE_TYPE_GPU: + vlog( "DEVICE:\tgpu\n" ); + break; + case CL_DEVICE_TYPE_ACCELERATOR: + vlog( "DEVICE:\taccelerator\n" ); + break; + default: + vlog_error( "DEVICE:\tunknown\n" ); + break; + } +} + +static int DoTest( void ) +{ + int error = 0; + + if( 0 == argCount ) + { // test all + if( (error = Test_vload_half()) ) + return error; + + if( (error = Test_vloada_half()) ) + return error; + + if( (error = Test_vstore_half()) ) + return error; + + if( (error = Test_vstorea_half()) ) + return error; + + if( (error = Test_vstore_half_rte()) ) + return error; + + if( (error = Test_vstorea_half_rte()) ) + return error; + + if( (error = Test_vstore_half_rtz()) ) + return error; + + if( (error = Test_vstorea_half_rtz()) ) + return error; + + if( (error = Test_vstore_half_rtp()) ) + return error; + + if( (error = Test_vstorea_half_rtp()) ) + return error; + + if( (error = Test_vstore_half_rtn()) ) + return error; + + if( (error = Test_vstorea_half_rtn()) ) + return error; + + if( (error = Test_roundTrip()) ) + return error; + } + else + { + typedef struct{ int (*f)(void); const char *name; }TestItem; +#define ENTRY( _x ) { Test_ ## _x, STRINGIFY(_x) } + static const TestItem list[] = + { + ENTRY(vload_half), + ENTRY(vloada_half), + ENTRY(vstore_half), + ENTRY(vstorea_half), + ENTRY(vstore_half_rte), + ENTRY(vstorea_half_rte), + ENTRY(vstore_half_rtz), + ENTRY(vstorea_half_rtz), + ENTRY(vstore_half_rtp), + ENTRY(vstorea_half_rtp), + ENTRY(vstore_half_rtn), + ENTRY(vstorea_half_rtn), + ENTRY(roundTrip) + }; + static const size_t list_count = sizeof( list ) / sizeof( list[0] ); + + size_t i, j; + for( i = 0; i < argCount; i++ ) + { + const char *argp = argList[i]; + for( j = 0; j < list_count; j++ ) + { + if( 0 == strcmp(argp, list[j].name) ) + { + if( (error = list[j].f()) ) + return error; + + break; + } + } + if( j == list_count ) + { + vlog_error( "Unknown test name: %s\n. Exiting...\n", argp ); + return -5; + } + } + } + + return error; +} + + diff --git a/test_conformance/half/test_config.h b/test_conformance/half/test_config.h new file mode 100644 index 00000000..a81f429d --- /dev/null +++ b/test_conformance/half/test_config.h @@ -0,0 +1,41 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TEST_CONFIG_H +#define TEST_CONFIG_H + +#define MULTITHREAD 1 + +#define kVectorSizeCount 5 +#define kStrangeVectorSizeCount 1 +#define kMinVectorSize 0 +#define kLargestVectorSize (1 << (kVectorSizeCount-1)) + +#define kLastVectorSizeToTest (kVectorSizeCount + kStrangeVectorSizeCount) + +#define BUFFER_SIZE ((size_t)2 * 1024 * 1024) + +extern size_t getBufferSize(cl_device_id device_id); +extern cl_ulong getBufferCount(cl_device_id device_id, size_t vecSize, size_t typeSize); +// could call +// CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE +#define kPageSize 4096 + +extern int g_arrVecSizes[kVectorSizeCount+kStrangeVectorSizeCount]; +extern int g_arrVecAligns[kLargestVectorSize+1]; + +#endif /* TEST_CONFIG_H */ + + diff --git a/test_conformance/half/tests.h b/test_conformance/half/tests.h new file mode 100644 index 00000000..bf869658 --- /dev/null +++ b/test_conformance/half/tests.h @@ -0,0 +1,41 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TESTS_H +#define TESTS_H + + +int Test_vload_half( void ); +int Test_vloada_half( void ); +int Test_vstore_half( void ); +int Test_vstorea_half( void ); +int Test_vstore_half_rte( void ); +int Test_vstorea_half_rte( void ); +int Test_vstore_half_rtz( void ); +int Test_vstorea_half_rtz( void ); +int Test_vstore_half_rtp( void ); +int Test_vstorea_half_rtp( void ); +int Test_vstore_half_rtn( void ); +int Test_vstorea_half_rtn( void ); +int Test_roundTrip( void ); + +typedef cl_ushort (*f2h)( float ); +typedef cl_ushort (*d2h)( double ); +int Test_vStoreHalf_private( f2h referenceFunc, d2h referenceDoubleFunc, const char *roundName ); +int Test_vStoreaHalf_private( f2h referenceFunc, d2h referenceDoubleFunc, const char *roundName ); + +#endif /* TESTS_H */ + + diff --git a/test_conformance/headers/CMakeLists.txt b/test_conformance/headers/CMakeLists.txt new file mode 100644 index 00000000..eff8e286 --- /dev/null +++ b/test_conformance/headers/CMakeLists.txt @@ -0,0 +1,87 @@ +set(HEADERS_SOURCES + test_headers.c +) + +set(HEADERS_OUT ${CONFORMANCE_PREFIX}headers${CONFORMANCE_SUFFIX}) + +add_executable( + ${HEADERS_OUT} + ${HEADERS_SOURCES} +) + +set_property(TARGET ${HEADERS_OUT} PROPERTY FOLDER "CONFORMANCE${CONFORMANCE_SUFFIX}") + +TARGET_LINK_LIBRARIES(${HEADERS_OUT} ${CLConform_LIBRARIES}) + +######################################################################################## + +set(CL_H_SOURCES + test_cl.h.c +) + +set(CL_H_OUT ${CONFORMANCE_PREFIX}cl_h${CONFORMANCE_SUFFIX}) + +add_executable( + ${CL_H_OUT} + ${CL_H_SOURCES} +) + +set_property(TARGET ${CL_H_OUT} PROPERTY FOLDER "CONFORMANCE${CONFORMANCE_SUFFIX}") + +TARGET_LINK_LIBRARIES(${CL_H_OUT} ${CLConform_LIBRARIES}) + +######################################################################################## + +set(CL_PLATFORM_H_SOURCES + test_cl_platform.h.c +) + +set(CL_PLATFORM_H_OUT ${CONFORMANCE_PREFIX}cl_platform_h${CONFORMANCE_SUFFIX}) + +add_executable( + ${CL_PLATFORM_H_OUT} + ${CL_PLATFORM_H_SOURCES} +) + +set_property(TARGET ${CL_PLATFORM_H_OUT} PROPERTY FOLDER "CONFORMANCE${CONFORMANCE_SUFFIX}") + +TARGET_LINK_LIBRARIES(${CL_PLATFORM_H_OUT} ${CLConform_LIBRARIES}) + +######################################################################################## + +set(CL_GL_H_SOURCES + test_cl_gl.h.c +) + +set(CL_GL_H_OUT ${CONFORMANCE_PREFIX}cl_gl_h${CONFORMANCE_SUFFIX}) + +add_executable( + ${CL_GL_H_OUT} + ${CL_GL_H_SOURCES} +) + +set_property(TARGET ${CL_GL_H_OUT} PROPERTY FOLDER "CONFORMANCE${CONFORMANCE_SUFFIX}") + +TARGET_LINK_LIBRARIES(${CL_GL_H_OUT} ${CLConform_LIBRARIES}) + +######################################################################################## + +set(OPENCL_H_SOURCES + test_opencl.h.c +) + +set(OPENCL_H_OUT ${CONFORMANCE_PREFIX}opencl_h${CONFORMANCE_SUFFIX}) + +add_executable( + ${OPENCL_H_OUT} + ${OPENCL_H_SOURCES} +) + +set_property(TARGET ${OPENCL_H_OUT} PROPERTY FOLDER "CONFORMANCE${CONFORMANCE_SUFFIX}") + +TARGET_LINK_LIBRARIES(${OPENCL_H_OUT} ${CLConform_LIBRARIES}) + +######################################################################################## + + +# end of file # diff --git a/test_conformance/headers/Makefile b/test_conformance/headers/Makefile new file mode 100644 index 00000000..dc649238 --- /dev/null +++ b/test_conformance/headers/Makefile @@ -0,0 +1,38 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +EXECUTABLES = test_headers \ + test_cl_h \ + test_cl_platform_h \ + test_cl_gl_h \ + test_opencl_h \ + test_cl_h_c99 \ + test_cl_platform_h_c99 \ + test_cl_gl_h_c99 \ + test_opencl_h_c99 + +INCLUDE = +HCFLAGS = ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CFLAGS = -Wall -pedantic ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = ${ATF} + +all : debug +release : debug +debug: + cc $(HCFLAGS) test_headers.c $(LIBRARIES) -o test_headers + cc $(CFLAGS) test_cl.h.c $(LIBRARIES) -o test_cl_h + cc $(CFLAGS) test_cl_platform.h.c $(LIBRARIES) -o test_cl_platform_h + cc $(CFLAGS) test_cl_gl.h.c $(LIBRARIES) -o test_cl_gl_h + cc $(CFLAGS) test_opencl.h.c $(LIBRARIES) -o test_opencl_h + cc $(CFLAGS) -std=c99 test_cl.h.c $(LIBRARIES) -o test_cl_h_c99 + cc $(CFLAGS) -std=c99 test_cl_platform.h.c $(LIBRARIES) -o test_cl_platform_h_c99 + cc $(CFLAGS) -std=c99 test_cl_gl.h.c $(LIBRARIES) -o test_cl_gl_h_c99 + cc $(CFLAGS) -std=c99 test_opencl.h.c $(LIBRARIES) -o test_opencl_h_c99 + +install: + + +clean: + rm -f $(EXECUTABLES) diff --git a/test_conformance/headers/README.txt b/test_conformance/headers/README.txt new file mode 100644 index 00000000..52bfea7a --- /dev/null +++ b/test_conformance/headers/README.txt @@ -0,0 +1,26 @@ +test_conformance/headers README +=============================== + +The test_headers.c test is designed to make sure that the various +cl_typen types work and conform to expectation for recent versions +of cl_platform.h. Conforming to these expectations make use of +these types practical for developers writing portable code. + +The various tests ending in .h.c are there to verify that the various +OpenCL headers can compile stand alone. That is to ensure that they +may be used a la carte. This provides developers a lifeline in the case +that some unneeded part of OpenCL (e.g. cl/gl sharing) brings in a pile +of symbols (e.g. all of OpenGL) that collides with other headers needed +by the application. It is also poor form to require headers to be +included in a particular order, especially if multiple systems require +they be included in mutually incompatible order. So, here we require +that each header can be used standalone so that the order is irrelevant. + +In the .h.c tests, we also check to make sure that the headers don't +cause spurious warnings. These tests are intended to be compiled using +the most stringent compiler flags available for the platform, within +reason. All warnings should be errors and extra warnings that it is +expected developers are likely to use should be turned on. The current +Makefile includes such flags for a GCC compiler. Implementors are +expected to modify these flags and make system as necessary to conform +to the local build environment. diff --git a/test_conformance/headers/test_cl.h.c b/test_conformance/headers/test_cl.h.c new file mode 100644 index 00000000..1fabcba9 --- /dev/null +++ b/test_conformance/headers/test_cl.h.c @@ -0,0 +1,27 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#if defined( __APPLE__ ) + #include +#else + #include +#endif +#include + +int main( void ) +{ + printf("cl.h standalone test PASSED.\n"); + return 0; +} diff --git a/test_conformance/headers/test_cl_gl.h.c b/test_conformance/headers/test_cl_gl.h.c new file mode 100644 index 00000000..d20dfc07 --- /dev/null +++ b/test_conformance/headers/test_cl_gl.h.c @@ -0,0 +1,27 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#if defined( __APPLE__ ) + #include +#else + #include +#endif +#include + +int main( void ) +{ + printf("cl_gl.h standalone test PASSED.\n"); + return 0; +} diff --git a/test_conformance/headers/test_cl_platform.h.c b/test_conformance/headers/test_cl_platform.h.c new file mode 100644 index 00000000..7fdd6ff7 --- /dev/null +++ b/test_conformance/headers/test_cl_platform.h.c @@ -0,0 +1,27 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#if defined( __APPLE__ ) + #include +#else + #include +#endif +#include + +int main( void ) +{ + printf("cl_platform.h standalone test PASSED.\n"); + return 0; +} diff --git a/test_conformance/headers/test_headers.c b/test_conformance/headers/test_headers.c new file mode 100644 index 00000000..6fe0f558 --- /dev/null +++ b/test_conformance/headers/test_headers.c @@ -0,0 +1,650 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#if defined( __APPLE__ ) + #include +#else + #include +#endif +#include +#include "../../test_common/harness/errorHelpers.h" + + +void test_char( void ); +void test_uchar( void ); +void test_short( void ); +void test_ushort( void ); +void test_int( void ); +void test_uint( void ); +void test_long( void ); +void test_ulong( void ); +void test_float( void ); +void test_double( void ); + +void test_char( void ) +{ +/* char */ + /* Constructor */ + cl_char a = 0; + cl_char2 a2 = {{ 0, 1 }}; + cl_char4 a4 = {{ 0, 1, 2, 3 }}; + cl_char8 a8 = {{ 0, 1, 2, 3, 4, 5, 6, 7 }}; + cl_char16 a16 = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }}; + + /* assignment */ + cl_char b = a; + cl_char2 b2 = a2; + cl_char4 b4 = a4; + cl_char8 b8 = a8; + cl_char16 b16 = a16; + + log_info("\nVerifying assignment:\n" ); + log_info("b: %d\n", b ); + log_info("b2: %d %d \n", b2.s[0], b2.s[1] ); + log_info("b4: %d %d %d %d\n", b4.s[0], b4.s[1], b4.s[2], b4.s[3] ); + log_info("b8: %d %d %d %d %d %d %d %d\n", b8.s[0], b8.s[1], b8.s[2], b8.s[3], b8.s[4], b8.s[5], b8.s[6], b8.s[7] ); + log_info("b16: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", b16.s[0], b16.s[1], b16.s[2], b16.s[3], b16.s[4], b16.s[5], b16.s[6], b16.s[7], + b16.s[8], b16.s[9], b16.s[10], b16.s[11], b16.s[12], b16.s[13], b16.s[14], b16.s[15]); + + /* vector access */ + log_info("\nVerifying vector access:\n" ); +#if defined( __CL_CHAR2__ ) + __cl_char2 v2 = b2.v2; + log_info("__cl_char2: %d %d \n", ((cl_char*)&v2)[0], ((cl_char*)&v2)[1] ); +#else + log_info( "__cl_char2 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_CHAR4__ ) + __cl_char4 v4 = b4.v4; + log_info("__cl_char4: %d %d %d %d \n", ((cl_char*)&v4)[0], ((cl_char*)&v4)[1], ((cl_char*)&v4)[2], ((cl_char*)&v4)[3] ); +#else + log_info( "__cl_char4 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_CHAR8__ ) + __cl_char8 v8 = b8.v8; + log_info("__cl_char8: %d %d %d %d %d %d %d %d \n", ((cl_char*)&v8)[0], ((cl_char*)&v8)[1], ((cl_char*)&v8)[2], ((cl_char*)&v8)[3], ((cl_char*)&v8)[4], ((cl_char*)&v8)[5], ((cl_char*)&v8)[6], ((cl_char*)&v8)[7] ); +#else + log_info( "__cl_char8 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_CHAR16__ ) + __cl_char16 v16 = b16.v16; + log_info("__cl_char16: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d \n", ((cl_char*)&v16)[0], ((cl_char*)&v16)[1], ((cl_char*)&v16)[2], ((cl_char*)&v16)[3], ((cl_char*)&v16)[4], ((cl_char*)&v16)[5], ((cl_char*)&v16)[6], ((cl_char*)&v16)[7], + ((cl_char*)&v16)[8], ((cl_char*)&v16)[9], ((cl_char*)&v16)[10], ((cl_char*)&v16)[11], ((cl_char*)&v16)[12], ((cl_char*)&v16)[13], ((cl_char*)&v16)[14], ((cl_char*)&v16)[15]); +#else + log_info( "__cl_char16 SIMD vectors not supported on this architecture.\n" ); +#endif + + log_info( "\n" ); +} + +void test_uchar( void ) +{ +/* uchar */ + /* Constructor */ + cl_uchar a = 0; + cl_uchar2 a2 = {{ 0, 1 }}; + cl_uchar4 a4 = {{ 0, 1, 2, 3 }}; + cl_uchar8 a8 = {{ 0, 1, 2, 3, 4, 5, 6, 7 }}; + cl_uchar16 a16 = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }}; + + /* assignment */ + cl_uchar b = a; + cl_uchar2 b2 = a2; + cl_uchar4 b4 = a4; + cl_uchar8 b8 = a8; + cl_uchar16 b16 = a16; + + log_info("\nVerifying assignment:\n" ); + log_info("b: %d\n", b ); + log_info("b2: %d %d \n", b2.s[0], b2.s[1] ); + log_info("b4: %d %d %d %d\n", b4.s[0], b4.s[1], b4.s[2], b4.s[3] ); + log_info("b8: %d %d %d %d %d %d %d %d\n", b8.s[0], b8.s[1], b8.s[2], b8.s[3], b8.s[4], b8.s[5], b8.s[6], b8.s[7] ); + log_info("b16: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", b16.s[0], b16.s[1], b16.s[2], b16.s[3], b16.s[4], b16.s[5], b16.s[6], b16.s[7], + b16.s[8], b16.s[9], b16.s[10], b16.s[11], b16.s[12], b16.s[13], b16.s[14], b16.s[15]); + + /* vector access */ + log_info("\nVerifying vector access:\n" ); +#if defined( __CL_UCHAR2__ ) + __cl_uchar2 v2 = b2.v2; + log_info("__cl_uchar2: %d %d \n", ((uchar*)&v2)[0], ((cl_uchar*)&v2)[1] ); +#else + log_info( "__cl_uchar2 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_UCHAR4__ ) + __cl_uchar4 v4 = b4.v4; + log_info("__cl_uchar4: %d %d %d %d \n", ((uchar*)&v4)[0], ((cl_uchar*)&v4)[1], ((cl_uchar*)&v4)[2], ((cl_uchar*)&v4)[3] ); +#else + log_info( "__cl_uchar4 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_UCHAR8__ ) + __cl_uchar8 v8 = b8.v8; + log_info("__cl_uchar8: %d %d %d %d %d %d %d %d \n", ((cl_uchar*)&v8)[0], ((cl_uchar*)&v8)[1], ((cl_uchar*)&v8)[2], ((cl_uchar*)&v8)[3], ((cl_uchar*)&v8)[4], ((cl_uchar*)&v8)[5], ((cl_uchar*)&v8)[6], ((cl_uchar*)&v8)[7] ); +#else + log_info( "__cl_uchar8 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_UCHAR16__ ) + __cl_uchar16 v16 = b16.v16; + log_info("__cl_uchar16: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d \n", ((cl_uchar*)&v16)[0], ((cl_uchar*)&v16)[1], ((cl_uchar*)&v16)[2], ((cl_uchar*)&v16)[3], ((cl_uchar*)&v16)[4], ((cl_uchar*)&v16)[5], ((cl_uchar*)&v16)[6], ((cl_uchar*)&v16)[7], + ((cl_uchar*)&v16)[8], ((cl_uchar*)&v16)[9], ((cl_uchar*)&v16)[10], ((cl_uchar*)&v16)[11], ((cl_uchar*)&v16)[12], ((cl_uchar*)&v16)[13], ((cl_uchar*)&v16)[14], ((cl_uchar*)&v16)[15]); +#else + log_info( "__cl_uchar16 SIMD vectors not supported on this architecture.\n" ); +#endif + + log_info( "\n" ); +} + +void test_short( void ) +{ +/* short */ + /* Constructor */ + cl_short a = 0; + cl_short2 a2 = {{ 0, 1 }}; + cl_short4 a4 = {{ 0, 1, 2, 3 }}; + cl_short8 a8 = {{ 0, 1, 2, 3, 4, 5, 6, 7 }}; + cl_short16 a16 = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }}; + + /* assignment */ + cl_short b = a; + cl_short2 b2 = a2; + cl_short4 b4 = a4; + cl_short8 b8 = a8; + cl_short16 b16 = a16; + + log_info("\nVerifying assignment:\n" ); + log_info("b: %d\n", b ); + log_info("b2: %d %d \n", b2.s[0], b2.s[1] ); + log_info("b4: %d %d %d %d\n", b4.s[0], b4.s[1], b4.s[2], b4.s[3] ); + log_info("b8: %d %d %d %d %d %d %d %d\n", b8.s[0], b8.s[1], b8.s[2], b8.s[3], b8.s[4], b8.s[5], b8.s[6], b8.s[7] ); + log_info("b16: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", b16.s[0], b16.s[1], b16.s[2], b16.s[3], b16.s[4], b16.s[5], b16.s[6], b16.s[7], + b16.s[8], b16.s[9], b16.s[10], b16.s[11], b16.s[12], b16.s[13], b16.s[14], b16.s[15]); + + /* vector access */ + log_info("\nVerifying vector access:\n" ); +#if defined( __CL_SHORT2__ ) + __cl_short2 v2 = b2.v2; + log_info("__cl_short2: %d %d \n", ((cl_short*)&v2)[0], ((cl_short*)&v2)[1] ); +#else + log_info( "__cl_short2 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_SHORT4__ ) + __cl_short4 v4 = b4.v4; + log_info("__cl_short4: %d %d %d %d \n", ((cl_short*)&v4)[0], ((cl_short*)&v4)[1], ((cl_short*)&v4)[2], ((cl_short*)&v4)[3] ); +#else + log_info( "__cl_short4 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_SHORT8__ ) + __cl_short8 v8 = b8.v8; + log_info("__cl_short8: %d %d %d %d %d %d %d %d \n", ((cl_short*)&v8)[0], ((cl_short*)&v8)[1], ((cl_short*)&v8)[2], ((cl_short*)&v8)[3], ((cl_short*)&v8)[4], ((cl_short*)&v8)[5], ((cl_short*)&v8)[6], ((cl_short*)&v8)[7] ); +#else + log_info( "__cl_short8 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_SHORT16__ ) + __cl_short16 v16 = b16.v16; + log_info("__cl_short16: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d \n", ((cl_short*)&v16)[0], ((cl_short*)&v16)[1], ((cl_short*)&v16)[2], ((cl_short*)&v16)[3], ((cl_short*)&v16)[4], ((cl_short*)&v16)[5], ((cl_short*)&v16)[6], ((cl_short*)&v16)[7], + ((cl_short*)&v16)[8], ((cl_short*)&v16)[9], ((cl_short*)&v16)[10], ((cl_short*)&v16)[11], ((cl_short*)&v16)[12], ((cl_short*)&v16)[13], ((cl_short*)&v16)[14], ((cl_short*)&v16)[15]); +#else + log_info( "__cl_short16 SIMD vectors not supported on this architecture.\n" ); +#endif + + log_info( "\n" ); +} + +void test_ushort( void ) +{ +/* ushort */ + /* Constructor */ + cl_ushort a = 0; + cl_ushort2 a2 = {{ 0, 1 }}; + cl_ushort4 a4 = {{ 0, 1, 2, 3 }}; + cl_ushort8 a8 = {{ 0, 1, 2, 3, 4, 5, 6, 7 }}; + cl_ushort16 a16 = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }}; + + /* assignment */ + cl_ushort b = a; + cl_ushort2 b2 = a2; + cl_ushort4 b4 = a4; + cl_ushort8 b8 = a8; + cl_ushort16 b16 = a16; + + log_info("\nVerifying assignment:\n" ); + log_info("b: %d\n", b ); + log_info("b2: %d %d \n", b2.s[0], b2.s[1] ); + log_info("b4: %d %d %d %d\n", b4.s[0], b4.s[1], b4.s[2], b4.s[3] ); + log_info("b8: %d %d %d %d %d %d %d %d\n", b8.s[0], b8.s[1], b8.s[2], b8.s[3], b8.s[4], b8.s[5], b8.s[6], b8.s[7] ); + log_info("b16: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", b16.s[0], b16.s[1], b16.s[2], b16.s[3], b16.s[4], b16.s[5], b16.s[6], b16.s[7], + b16.s[8], b16.s[9], b16.s[10], b16.s[11], b16.s[12], b16.s[13], b16.s[14], b16.s[15]); + + /* vector access */ + log_info("\nVerifying vector access:\n" ); +#if defined( __CL_USHORT2__ ) + __cl_ushort2 v2 = b2.v2; + log_info("__cl_ushort2: %d %d \n", ((unsigned short*)&v2)[0], ((unsigned short*)&v2)[1] ); +#else + log_info( "__cl_ushort2 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_USHORT4__ ) + __cl_ushort4 v4 = b4.v4; + log_info("__cl_ushort4: %d %d %d %d \n", ((unsigned short*)&v4)[0], ((unsigned short*)&v4)[1], ((unsigned short*)&v4)[2], ((unsigned short*)&v4)[3] ); +#else + log_info( "__cl_ushort4 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_USHORT8__ ) + __cl_ushort8 v8 = b8.v8; + log_info("__cl_ushort8: %d %d %d %d %d %d %d %d \n", ((unsigned short*)&v8)[0], ((unsigned short*)&v8)[1], ((unsigned short*)&v8)[2], ((unsigned short*)&v8)[3], ((unsigned short*)&v8)[4], ((unsigned short*)&v8)[5], ((unsigned short*)&v8)[6], ((unsigned short*)&v8)[7] ); +#else + log_info( "__cl_ushort8 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_USHORT16__ ) + __cl_ushort16 v16 = b16.v16; + log_info("__cl_ushort16: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d \n", ((unsigned short*)&v16)[0], ((unsigned short*)&v16)[1], ((unsigned short*)&v16)[2], ((unsigned short*)&v16)[3], ((unsigned short*)&v16)[4], ((unsigned short*)&v16)[5], ((unsigned short*)&v16)[6], ((unsigned short*)&v16)[7], + ((unsigned short*)&v16)[8], ((unsigned short*)&v16)[9], ((unsigned short*)&v16)[10], ((unsigned short*)&v16)[11], ((unsigned short*)&v16)[12], ((unsigned short*)&v16)[13], ((unsigned short*)&v16)[14], ((unsigned short*)&v16)[15]); +#else + log_info( "__cl_ushort16 SIMD vectors not supported on this architecture.\n" ); +#endif + + log_info( "\n" ); +} + +void test_int( void ) +{ +/* int */ + /* Constructor */ + cl_int a = 0; + cl_int2 a2 = {{ 0, 1 }}; + cl_int4 a4 = {{ 0, 1, 2, 3 }}; + cl_int8 a8 = {{ 0, 1, 2, 3, 4, 5, 6, 7 }}; + cl_int16 a16 = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }}; + + /* assignment */ + cl_int b = a; + cl_int2 b2 = a2; + cl_int4 b4 = a4; + cl_int8 b8 = a8; + cl_int16 b16 = a16; + + log_info("\nVerifying assignment:\n" ); + log_info("b: %d\n", b ); + log_info("b2: %d %d \n", b2.s[0], b2.s[1] ); + log_info("b4: %d %d %d %d\n", b4.s[0], b4.s[1], b4.s[2], b4.s[3] ); + log_info("b8: %d %d %d %d %d %d %d %d\n", b8.s[0], b8.s[1], b8.s[2], b8.s[3], b8.s[4], b8.s[5], b8.s[6], b8.s[7] ); + log_info("b16: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", b16.s[0], b16.s[1], b16.s[2], b16.s[3], b16.s[4], b16.s[5], b16.s[6], b16.s[7], + b16.s[8], b16.s[9], b16.s[10], b16.s[11], b16.s[12], b16.s[13], b16.s[14], b16.s[15]); + + /* vector access */ + log_info("\nVerifying vector access:\n" ); +#if defined( __CL_INT2__ ) + __cl_int2 v2 = b2.v2; + log_info("__cl_int2: %d %d \n", ((cl_int*)&v2)[0], ((cl_int*)&v2)[1] ); +#else + log_info( "__cl_int2 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_INT4__ ) + __cl_int4 v4 = b4.v4; + log_info("__cl_int4: %d %d %d %d \n", ((cl_int*)&v4)[0], ((cl_int*)&v4)[1], ((cl_int*)&v4)[2], ((cl_int*)&v4)[3] ); +#else + log_info( "__cl_int4 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_INT8__ ) + __cl_int8 v8 = b8.v8; + log_info("__cl_int8: %d %d %d %d %d %d %d %d \n", ((cl_int*)&v8)[0], ((cl_int*)&v8)[1], ((cl_int*)&v8)[2], ((cl_int*)&v8)[3], ((cl_int*)&v8)[4], ((cl_int*)&v8)[5], ((cl_int*)&v8)[6], ((cl_int*)&v8)[7] ); +#else + log_info( "__cl_int8 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_INT16__ ) + __cl_int16 v16 = b16.v16; + log_info("__cl_int16: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d \n", ((cl_int*)&v16)[0], ((cl_int*)&v16)[1], ((cl_int*)&v16)[2], ((cl_int*)&v16)[3], ((cl_int*)&v16)[4], ((cl_int*)&v16)[5], ((cl_int*)&v16)[6], ((cl_int*)&v16)[7], + ((cl_int*)&v16)[8], ((cl_int*)&v16)[9], ((cl_int*)&v16)[10], ((cl_int*)&v16)[11], ((cl_int*)&v16)[12], ((cl_int*)&v16)[13], ((cl_int*)&v16)[14], ((cl_int*)&v16)[15]); +#else + log_info( "__cl_int16 SIMD vectors not supported on this architecture.\n" ); +#endif + + log_info( "\n" ); +} + +void test_uint( void ) +{ +/* uint */ + /* Constructor */ + cl_uint a = 0; + cl_uint2 a2 = {{ 0, 1 }}; + cl_uint4 a4 = {{ 0, 1, 2, 3 }}; + cl_uint8 a8 = {{ 0, 1, 2, 3, 4, 5, 6, 7 }}; + cl_uint16 a16 = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }}; + + /* assignment */ + cl_uint b = a; + cl_uint2 b2 = a2; + cl_uint4 b4 = a4; + cl_uint8 b8 = a8; + cl_uint16 b16 = a16; + + log_info("\nVerifying assignment:\n" ); + log_info("b: %d\n", b ); + log_info("b2: %d %d \n", b2.s[0], b2.s[1] ); + log_info("b4: %d %d %d %d\n", b4.s[0], b4.s[1], b4.s[2], b4.s[3] ); + log_info("b8: %d %d %d %d %d %d %d %d\n", b8.s[0], b8.s[1], b8.s[2], b8.s[3], b8.s[4], b8.s[5], b8.s[6], b8.s[7] ); + log_info("b16: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", b16.s[0], b16.s[1], b16.s[2], b16.s[3], b16.s[4], b16.s[5], b16.s[6], b16.s[7], + b16.s[8], b16.s[9], b16.s[10], b16.s[11], b16.s[12], b16.s[13], b16.s[14], b16.s[15]); + + /* vector access */ + log_info("\nVerifying vector access:\n" ); +#if defined( __CL_UINT2__ ) + __cl_uint2 v2 = b2.v2; + log_info("__cl_uint2: %d %d \n", ((cl_uint*)&v2)[0], ((cl_uint*)&v2)[1] ); +#else + log_info( "__cl_uint2 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_UINT4__ ) + __cl_uint4 v4 = b4.v4; + log_info("__cl_uint4: %d %d %d %d \n", ((cl_uint*)&v4)[0], ((cl_uint*)&v4)[1], ((cl_uint*)&v4)[2], ((cl_uint*)&v4)[3] ); +#else + log_info( "__cl_uint4 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_UINT8__ ) + __cl_uint8 v8 = b8.v8; + log_info("__cl_uint8: %d %d %d %d %d %d %d %d \n", ((cl_uint*)&v8)[0], ((cl_uint*)&v8)[1], ((cl_uint*)&v8)[2], ((cl_uint*)&v8)[3], ((cl_uint*)&v8)[4], ((cl_uint*)&v8)[5], ((cl_uint*)&v8)[6], ((cl_uint*)&v8)[7] ); +#else + log_info( "__cl_uint8 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_UINT16__ ) + __cl_uint16 v16 = b16.v16; + log_info("__cl_uint16: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d \n", ((cl_uint*)&v16)[0], ((cl_uint*)&v16)[1], ((cl_uint*)&v16)[2], ((cl_uint*)&v16)[3], ((cl_uint*)&v16)[4], ((cl_uint*)&v16)[5], ((cl_uint*)&v16)[6], ((cl_uint*)&v16)[7], + ((cl_uint*)&v16)[8], ((cl_uint*)&v16)[9], ((cl_uint*)&v16)[10], ((cl_uint*)&v16)[11], ((cl_uint*)&v16)[12], ((cl_uint*)&v16)[13], ((cl_uint*)&v16)[14], ((cl_uint*)&v16)[15]); +#else + log_info( "__cl_uint16 SIMD vectors not supported on this architecture.\n" ); +#endif + + log_info( "\n" ); +} + +void test_long( void ) +{ +/* long */ + /* Constructor */ + cl_long a = 0; + cl_long2 a2 = {{ 0, 1 }}; + cl_long4 a4 = {{ 0, 1, 2, 3 }}; + cl_long8 a8 = {{ 0, 1, 2, 3, 4, 5, 6, 7 }}; + cl_long16 a16 = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }}; + + /* assignment */ + cl_long b = a; + cl_long2 b2 = a2; + cl_long4 b4 = a4; + cl_long8 b8 = a8; + cl_long16 b16 = a16; + + log_info("\nVerifying assignment:\n" ); + log_info("b: %lld\n", b ); + log_info("b2: %lld %lld \n", b2.s[0], b2.s[1] ); + log_info("b4: %lld %lld %lld %lld\n", b4.s[0], b4.s[1], b4.s[2], b4.s[3] ); + log_info("b8: %lld %lld %lld %lld %lld %lld %lld %lld\n", b8.s[0], b8.s[1], b8.s[2], b8.s[3], b8.s[4], b8.s[5], b8.s[6], b8.s[7] ); + log_info("b16: %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld\n", b16.s[0], b16.s[1], b16.s[2], b16.s[3], b16.s[4], b16.s[5], b16.s[6], b16.s[7], + b16.s[8], b16.s[9], b16.s[10], b16.s[11], b16.s[12], b16.s[13], b16.s[14], b16.s[15]); + + /* vector access */ + log_info("\nVerifying vector access:\n" ); +#if defined( __CL_LONG2__ ) + __cl_long2 v2 = b2.v2; + log_info("__cl_long2: %lld %lld \n", ((cl_long*)&v2)[0], ((cl_long*)&v2)[1] ); +#else + log_info( "__cl_long2 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_LONG4__ ) + __cl_long4 v4 = b4.v4; + log_info("__cl_long4: %lld %lld %lld %lld \n", ((cl_long*)&v4)[0], ((cl_long*)&v4)[1], ((cl_long*)&v4)[2], ((cl_long*)&v4)[3] ); +#else + log_info( "__cl_long4 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_LONG8__ ) + __cl_long8 v8 = b8.v8; + log_info("__cl_long8: %lld %lld %lld %lld %lld %lld %lld %lld \n", ((cl_long*)&v8)[0], ((cl_long*)&v8)[1], ((cl_long*)&v8)[2], ((cl_long*)&v8)[3], ((cl_long*)&v8)[4], ((cl_long*)&v8)[5], ((cl_long*)&v8)[6], ((cl_long*)&v8)[7] ); +#else + log_info( "__cl_long8 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_LONG16__ ) + __cl_long16 v16 = b16.v16; + log_info("__cl_long16: %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld \n", ((cl_long*)&v16)[0], ((cl_long*)&v16)[1], ((cl_long*)&v16)[2], ((cl_long*)&v16)[3], ((cl_long*)&v16)[4], ((cl_long*)&v16)[5], ((cl_long*)&v16)[6], ((cl_long*)&v16)[7], + ((cl_long*)&v16)[8], ((cl_long*)&v16)[9], ((cl_long*)&v16)[10], ((cl_long*)&v16)[11], ((cl_long*)&v16)[12], ((cl_long*)&v16)[13], ((cl_long*)&v16)[14], ((cl_long*)&v16)[15]); +#else + log_info( "__cl_long16 SIMD vectors not supported on this architecture.\n" ); +#endif + + log_info( "\n" ); +} + +void test_ulong( void ) +{ +/* ulong */ + /* Constructor */ + cl_ulong a = 0; + cl_ulong2 a2 = {{ 0, 1 }}; + cl_ulong4 a4 = {{ 0, 1, 2, 3 }}; + cl_ulong8 a8 = {{ 0, 1, 2, 3, 4, 5, 6, 7 }}; + cl_ulong16 a16 = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }}; + + /* assignment */ + cl_ulong b = a; + cl_ulong2 b2 = a2; + cl_ulong4 b4 = a4; + cl_ulong8 b8 = a8; + cl_ulong16 b16 = a16; + + log_info("\nVerifying assignment:\n" ); + log_info("b: %lld\n", b ); + log_info("b2: %lld %lld \n", b2.s[0], b2.s[1] ); + log_info("b4: %lld %lld %lld %lld\n", b4.s[0], b4.s[1], b4.s[2], b4.s[3] ); + log_info("b8: %lld %lld %lld %lld %lld %lld %lld %lld\n", b8.s[0], b8.s[1], b8.s[2], b8.s[3], b8.s[4], b8.s[5], b8.s[6], b8.s[7] ); + log_info("b16: %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld\n", b16.s[0], b16.s[1], b16.s[2], b16.s[3], b16.s[4], b16.s[5], b16.s[6], b16.s[7], + b16.s[8], b16.s[9], b16.s[10], b16.s[11], b16.s[12], b16.s[13], b16.s[14], b16.s[15]); + + /* vector access */ + log_info("\nVerifying vector access:\n" ); +#if defined( __CL_ULONG2__ ) + __cl_ulong2 v2 = b2.v2; + log_info("__cl_ulong2: %lld %lld \n", ((cl_ulong*)&v2)[0], ((cl_ulong*)&v2)[1] ); +#else + log_info( "__cl_ulong2 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_ULONG4__ ) + __cl_ulong4 v4 = b4.v4; + log_info("__cl_ulong4: %lld %lld %lld %lld \n", ((cl_ulong*)&v4)[0], ((cl_ulong*)&v4)[1], ((cl_ulong*)&v4)[2], ((cl_ulong*)&v4)[3] ); +#else + log_info( "__cl_ulong4 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_ULONG8__ ) + __cl_ulong8 v8 = b8.v8; + log_info("__cl_ulong8: %lld %lld %lld %lld %lld %lld %lld %lld \n", ((cl_ulong*)&v8)[0], ((cl_ulong*)&v8)[1], ((cl_ulong*)&v8)[2], ((cl_ulong*)&v8)[3], ((cl_ulong*)&v8)[4], ((cl_ulong*)&v8)[5], ((cl_ulong*)&v8)[6], ((cl_ulong*)&v8)[7] ); +#else + log_info( "__cl_ulong8 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_ULONG16__ ) + __cl_ulong16 v16 = b16.v16; + log_info("__cl_ulong16: %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld \n", ((cl_ulong*)&v16)[0], ((cl_ulong*)&v16)[1], ((cl_ulong*)&v16)[2], ((cl_ulong*)&v16)[3], ((cl_ulong*)&v16)[4], ((cl_ulong*)&v16)[5], ((cl_ulong*)&v16)[6], ((cl_ulong*)&v16)[7], + ((cl_ulong*)&v16)[8], ((cl_ulong*)&v16)[9], ((cl_ulong*)&v16)[10], ((cl_ulong*)&v16)[11], ((cl_ulong*)&v16)[12], ((cl_ulong*)&v16)[13], ((cl_ulong*)&v16)[14], ((cl_ulong*)&v16)[15]); +#else + log_info( "__cl_ulong16 SIMD vectors not supported on this architecture.\n" ); +#endif + + log_info( "\n" ); +} + + +void test_float( void ) +{ +/* float */ + /* Constructor */ + cl_float a = 0.0f; + cl_float2 a2 = {{ 0.0f, 1.0f }}; + cl_float4 a4 = {{ 0.0f, 1.0f, 2.0f, 3.0f }}; + cl_float8 a8 = {{ 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f }}; + cl_float16 a16 = {{ 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f }}; + + /* assignment */ + cl_float b = a; + cl_float2 b2 = a2; + cl_float4 b4 = a4; + cl_float8 b8 = a8; + cl_float16 b16 = a16; + + log_info("\nVerifying assignment:\n" ); + log_info("b: %f\n", b ); + log_info("b2: %f %f \n", b2.s[0], b2.s[1] ); + log_info("b4: %f %f %f %f\n", b4.s[0], b4.s[1], b4.s[2], b4.s[3] ); + log_info("b8: %f %f %f %f %f %f %f %f\n", b8.s[0], b8.s[1], b8.s[2], b8.s[3], b8.s[4], b8.s[5], b8.s[6], b8.s[7] ); + log_info("b16: %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n", b16.s[0], b16.s[1], b16.s[2], b16.s[3], b16.s[4], b16.s[5], b16.s[6], b16.s[7], + b16.s[8], b16.s[9], b16.s[10], b16.s[11], b16.s[12], b16.s[13], b16.s[14], b16.s[15]); + + /* vector access */ + log_info("\nVerifying vector access:\n" ); +#if defined( __CL_FLOAT2__ ) + __cl_float2 v2 = b2.v2; + log_info("__cl_float2: %f %f \n", ((cl_float*)&v2)[0], ((cl_float*)&v2)[1] ); +#else + log_info( "__cl_float2 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_FLOAT4__ ) + { + __cl_float4 v4 = b4.v4; + log_info("__cl_float4: %f %f %f %f \n", ((cl_float*)&v4)[0], ((cl_float*)&v4)[1], ((cl_float*)&v4)[2], ((cl_float*)&v4)[3] ); + } +#else + log_info( "__cl_float4 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_FLOAT8__ ) + __cl_float8 v8 = b8.v8; + log_info("__cl_float8: %f %f %f %f %f %f %f %f \n", ((cl_float*)&v8)[0], ((cl_float*)&v8)[1], ((cl_float*)&v8)[2], ((cl_float*)&v8)[3], ((cl_float*)&v8)[4], ((cl_float*)&v8)[5], ((cl_float*)&v8)[6], ((cl_float*)&v8)[7] ); +#else + log_info( "__cl_float8 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_FLOAT16__ ) + __cl_float16 v16 = b16.v16; + log_info("__cl_float16: %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f \n", ((cl_float*)&v16)[0], ((cl_float*)&v16)[1], ((cl_float*)&v16)[2], ((cl_float*)&v16)[3], ((cl_float*)&v16)[4], ((cl_float*)&v16)[5], ((cl_float*)&v16)[6], ((cl_float*)&v16)[7], + ((cl_float*)&v16)[8], ((cl_float*)&v16)[9], ((cl_float*)&v16)[10], ((cl_float*)&v16)[11], ((cl_float*)&v16)[12], ((cl_float*)&v16)[13], ((cl_float*)&v16)[14], ((cl_float*)&v16)[15]); +#else + log_info( "__cl_float16 SIMD vectors not supported on this architecture.\n" ); +#endif + + log_info( "\n" ); +} + +void test_double( void ) +{ +/* double */ + /* Constructor */ + cl_double a = 0.0f; + cl_double2 a2 = {{ 0.0f, 1.0f }}; + cl_double4 a4 = {{ 0.0f, 1.0f, 2.0f, 3.0f }}; + cl_double8 a8 = {{ 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f }}; + cl_double16 a16 = {{ 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f }}; + + /* assignment */ + cl_double b = a; + cl_double2 b2 = a2; + cl_double4 b4 = a4; + cl_double8 b8 = a8; + cl_double16 b16 = a16; + + log_info("\nVerifying assignment:\n" ); + log_info("b: %f\n", b ); + log_info("b2: %f %f \n", b2.s[0], b2.s[1] ); + log_info("b4: %f %f %f %f\n", b4.s[0], b4.s[1], b4.s[2], b4.s[3] ); + log_info("b8: %f %f %f %f %f %f %f %f\n", b8.s[0], b8.s[1], b8.s[2], b8.s[3], b8.s[4], b8.s[5], b8.s[6], b8.s[7] ); + log_info("b16: %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n", b16.s[0], b16.s[1], b16.s[2], b16.s[3], b16.s[4], b16.s[5], b16.s[6], b16.s[7], + b16.s[8], b16.s[9], b16.s[10], b16.s[11], b16.s[12], b16.s[13], b16.s[14], b16.s[15]); + + /* vector access */ + log_info("\nVerifying vector access:\n" ); +#if defined( __CL_DOUBLE2__ ) + __cl_double2 v2 = b2.v2; + log_info("__cl_double2: %f %f \n", ((cl_double*)&v2)[0], ((cl_double*)&v2)[1] ); +#else + log_info( "__cl_double2 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_DOUBLE4__ ) + __cl_double4 v4 = b4.v4; + log_info("__cl_double4: %f %f %f %f \n", ((cl_double*)&v4)[0], ((cl_double*)&v4)[1], ((cl_double*)&v4)[2], ((cl_double*)&v4)[3] ); +#else + log_info( "__cl_double4 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_DOUBLE8__ ) + __cl_double8 v8 = b8.v8; + log_info("__cl_double8: %f %f %f %f %f %f %f %f \n", ((cl_double*)&v8)[0], ((cl_double*)&v8)[1], ((cl_double*)&v8)[2], ((cl_double*)&v8)[3], ((cl_double*)&v8)[4], ((cl_double*)&v8)[5], ((cl_double*)&v8)[6], ((cl_double*)&v8)[7] ); +#else + log_info( "__cl_double8 SIMD vectors not supported on this architecture.\n" ); +#endif + +#if defined( __CL_DOUBLE16__ ) + __cl_double16 v16 = b16.v16; + log_info("__cl_double16: %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f \n", ((cl_double*)&v16)[0], ((cl_double*)&v16)[1], ((cl_double*)&v16)[2], ((cl_double*)&v16)[3], ((cl_double*)&v16)[4], ((cl_double*)&v16)[5], ((cl_double*)&v16)[6], ((cl_double*)&v16)[7], + ((cl_double*)&v16)[8], ((cl_double*)&v16)[9], ((cl_double*)&v16)[10], ((cl_double*)&v16)[11], ((cl_double*)&v16)[12], ((cl_double*)&v16)[13], ((cl_double*)&v16)[14], ((cl_double*)&v16)[15]); +#else + log_info( "__cl_double16 SIMD vectors not supported on this architecture.\n" ); +#endif + + log_info( "\n" ); +} + +int main( void ) +{ + test_start(); + + log_info( "\nChecking operations on cl_types.\nNumbers, where presented, should walk upward from 0, with step of 1:\n" ); + + test_char(); + test_uchar(); + test_short(); + test_ushort(); + test_int(); + test_uint(); + test_long(); + test_ulong(); + test_float(); + test_double(); + + test_finish(); + log_info("PASSED test.\n"); + + return 0; +} diff --git a/test_conformance/headers/test_opencl.h.c b/test_conformance/headers/test_opencl.h.c new file mode 100644 index 00000000..d7318387 --- /dev/null +++ b/test_conformance/headers/test_opencl.h.c @@ -0,0 +1,27 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#if defined( __APPLE__ ) + #include +#else + #include +#endif +#include + +int main( void ) +{ + printf("opencl.h standalone test PASSED.\n"); + return 0; +} diff --git a/test_conformance/images/CMakeLists.txt b/test_conformance/images/CMakeLists.txt new file mode 100644 index 00000000..e0eb3fe1 --- /dev/null +++ b/test_conformance/images/CMakeLists.txt @@ -0,0 +1,15 @@ +if(NOT MSVC) +# IGL: Force no optimizations +set(CMAKE_C_FLAGS_RELEASE "-O0") +set(CMAKE_CXX_FLAGS_RELEASE "-O0") +endif(NOT MSVC) + +add_subdirectory(clCopyImage) +add_subdirectory(clFillImage) +add_subdirectory(clGetInfo) +add_subdirectory(clReadWriteImage) +add_subdirectory(kernel_image_methods) +add_subdirectory(kernel_read_write) +add_subdirectory(samplerlessReads) + + diff --git a/test_conformance/images/Jamfile b/test_conformance/images/Jamfile new file mode 100644 index 00000000..081a4702 --- /dev/null +++ b/test_conformance/images/Jamfile @@ -0,0 +1,9 @@ +build-project clCopyImage ; +build-project clFillImage ; +build-project clGetInfo ; +build-project clReadWriteImage ; +build-project kernel_image_methods ; +build-project kernel_read_write ; +build_project samplerlessReads ; + +use-project /images : . ; diff --git a/test_conformance/images/Makefile b/test_conformance/images/Makefile new file mode 100644 index 00000000..9028f6c6 --- /dev/null +++ b/test_conformance/images/Makefile @@ -0,0 +1,31 @@ + +PRODUCTS = \ + clCopyImage/ \ + clFillImage/ \ + clGetInfo/ \ + clReadWriteImage/ \ + kernel_image_methods/ \ + kernel_read_write/ \ + samplerlessReads/ + +TOP=$(shell pwd) + +all: $(PRODUCTS) + +clean: + @for testdir in $(dir $(PRODUCTS)) ; \ + do ( \ + echo "==================================================================================" ; \ + echo "Cleaning $$testdir" ; \ + echo "==================================================================================" ; \ + cd $$testdir && make clean \ + ); \ + done \ + +$(PRODUCTS): + @echo "==================================================================================" ; + @echo "(`date "+%H:%M:%S"`) Make $@" ; + @echo "==================================================================================" ; + cd $(dir $@) && make -i + +.PHONY: clean $(PRODUCTS) all diff --git a/test_conformance/images/clCopyImage/CMakeLists.txt b/test_conformance/images/clCopyImage/CMakeLists.txt new file mode 100644 index 00000000..f69ca0db --- /dev/null +++ b/test_conformance/images/clCopyImage/CMakeLists.txt @@ -0,0 +1,28 @@ +set(MODULE_NAME CL_COPY_IMAGES) + +set(${MODULE_NAME}_SOURCES + main.cpp + test_copy_1D.cpp + test_copy_1D_array.cpp + test_copy_2D.cpp + test_copy_2D_2D_array.cpp + test_copy_2D_3D.cpp + test_copy_2D_array.cpp + test_copy_3D.cpp + test_copy_3D_2D_array.cpp + test_copy_generic.cpp + test_loops.cpp + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/threadTesting.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/imageHelpers.cpp + ../../../test_common/harness/mt19937.c + ../../../test_common/harness/conversions.c + ../../../test_common/harness/typeWrappers.cpp + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) + diff --git a/test_conformance/images/clCopyImage/Jamfile b/test_conformance/images/clCopyImage/Jamfile new file mode 100644 index 00000000..526e206c --- /dev/null +++ b/test_conformance/images/clCopyImage/Jamfile @@ -0,0 +1,19 @@ +project + : requirements +# gcc:-xc++ +# msvc:"/TP" + ; + +exe test_cl_copy_images + : main.cpp + test_copy_2D_3D.cpp + test_copy_2D.cpp + test_copy_3D.cpp + test_loops.cpp + ; + +install dist + : test_cl_copy_images + : debug:$(DIST)/debug/tests/test_conformance/images/clCopyImage + release:$(DIST)/release/tests/test_conformance/images/clCopyImage + ; diff --git a/test_conformance/images/clCopyImage/Makefile b/test_conformance/images/clCopyImage/Makefile new file mode 100644 index 00000000..18b93f07 --- /dev/null +++ b/test_conformance/images/clCopyImage/Makefile @@ -0,0 +1,56 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.cpp \ + test_copy_generic.cpp \ + test_copy_1D.cpp \ + test_copy_2D.cpp \ + test_loops.cpp \ + test_copy_3D.cpp \ + test_copy_1D_array.cpp \ + test_copy_2D_array.cpp \ + test_copy_2D_3D.cpp \ + test_copy_2D_2D_array.cpp \ + test_copy_3D_2D_array.cpp \ + ../../../test_common/harness/errorHelpers.c \ + ../../../test_common/harness/threadTesting.c \ + ../../../test_common/harness/kernelHelpers.c \ + ../../../test_common/harness/imageHelpers.cpp \ + ../../../test_common/harness/conversions.c \ + ../../../test_common/harness/testHarness.c \ + ../../../test_common/harness/typeWrappers.cpp \ + ../../../test_common/harness/mt19937.c + + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = +HEADERS = +TARGET = test_cl_copy_images +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os +CC = c++ +CXX = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/images/clCopyImage/main.cpp b/test_conformance/images/clCopyImage/main.cpp new file mode 100644 index 00000000..8b56b537 --- /dev/null +++ b/test_conformance/images/clCopyImage/main.cpp @@ -0,0 +1,265 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../../test_common/harness/compat.h" + +#include +#include + +#if !defined(_WIN32) +#include +#include +#endif + +#include "../testBase.h" + +bool gDebugTrace = false, gTestSmallImages = false, gTestMaxImages = false, gUseRamp = false, gTestRounding = false, gEnablePitch = false, gTestMipmaps = false; +int gTypesToTest = 0; +cl_channel_type gChannelTypeToUse = (cl_channel_type)-1; +cl_channel_order gChannelOrderToUse = (cl_channel_order)-1; +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +cl_context context; +cl_command_queue queue; + +extern int test_image_set( cl_device_id device, MethodsToTest testMethod ); + +#define MAX_ALLOWED_STD_DEVIATION_IN_MB 8.0 + +void printUsage( const char *execName ) +{ + const char *p = strrchr( execName, '/' ); + if( p != NULL ) + execName = p + 1; + + log_info( "Usage: %s [debug_trace] [small_images]\n", execName ); + log_info( "Where:\n" ); + log_info( "\t1D - Only test 1D images\n" ); + log_info( "\t2D - Only test 2D images\n" ); + log_info( "\t3D - Only test 3D images\n" ); + log_info( "\t1Darray - Only test 1D image arrays\n" ); + log_info( "\t2Darray - Only test 2D image arrays\n" ); + log_info( "\t2Dto3D - Only test 2D -> 3D images\n" ); + log_info( "\t3Dto2D - Only test 3D -> 2D images\n" ); + log_info( "\t2Darrayto2D - Only test 2D image arrays -> 2D images\n" ); + log_info( "\t2Dto2Darray - Only test 2D images -> 2D image arrays\n" ); + log_info( "\t2Darrayto3D - Only test 2D image arrays -> 3D images\n" ); + log_info( "\t3Dto2Darray - Only test 3D images -> 2D image arrays\n" ); + log_info( "\n" ); + log_info( "\ttest_mipmaps - Test with mipmapped images\n" ); + log_info( "\tdebug_trace - Enables additional debug info logging\n" ); + log_info( "\tsmall_images - Runs every format through a loop of widths 1-13 and heights 1-9, instead of random sizes\n" ); + log_info( "\tmax_images - Runs every format through a set of size combinations with the max values, max values - 1, and max values / 128\n" ); + log_info( "\trounding - Runs every format through a single image filled with every possible value for that image format, to verify rounding works properly\n" ); + //log_info( "\tuse_pitches - Enables row and slice pitches\n" ); + log_info( "\tuse_ramp - Instead of random data, uses images filled with ramps (and 0xff on any padding pixels) to ease debugging\n" ); +} + + +int main(int argc, const char *argv[]) +{ + cl_platform_id platform; + cl_device_id device; + cl_channel_type chanType; + cl_channel_order chanOrder; + char str[ 128 ]; + int testMethods = 0; + bool randomize = false; + + test_start(); + + checkDeviceTypeOverride( &gDeviceType ); + + // Parse arguments + for( int i = 1; i < argc; i++ ) + { + strncpy( str, argv[ i ], sizeof( str ) - 1 ); + + if( strcmp( str, "cpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_CPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_CPU; + else if( strcmp( str, "gpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_GPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_GPU; + else if( strcmp( str, "accelerator" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( str, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_DEFAULT; + + else if( strcmp( str, "test_mipmaps" ) == 0 ) + { + gTestMipmaps = true; + // Don't test pitches with mipmaps, at least currently. + gEnablePitch = false; + } + else if( strcmp( str, "debug_trace" ) == 0 ) + gDebugTrace = true; + + else if( strcmp( str, "small_images" ) == 0 ) + gTestSmallImages = true; + else if( strcmp( str, "max_images" ) == 0 ) + gTestMaxImages = true; + else if( strcmp( str, "use_ramps" ) == 0 ) + gUseRamp = true; + + else if( strcmp( str, "use_pitches" ) == 0 ) + gEnablePitch = true; + + else if( strcmp( str, "randomize" ) == 0 ) + randomize = true; + + else if( strcmp( str, "1D" ) == 0 ) + testMethods |= k1D; + else if( strcmp( str, "2D" ) == 0 ) + testMethods |= k2D; + else if( strcmp( str, "3D" ) == 0 ) + testMethods |= k3D; + else if( strcmp( str, "1Darray" ) == 0 ) + testMethods |= k1DArray; + else if( strcmp( str, "2Darray" ) == 0 ) + testMethods |= k2DArray; + else if( strcmp( str, "2Dto3D" ) == 0 ) + testMethods |= k2DTo3D; + else if( strcmp( str, "3Dto2D" ) == 0 ) + testMethods |= k3DTo2D; + else if( strcmp( str, "2Darrayto2D" ) == 0 ) + testMethods |= k2DArrayTo2D; + else if( strcmp( str, "2Dto2Darray" ) == 0 ) + testMethods |= k2DTo2DArray; + else if( strcmp( str, "2Darrayto3D" ) == 0 ) + testMethods |= k2DArrayTo3D; + else if( strcmp( str, "3Dto2Darray" ) == 0 ) + testMethods |= k3DTo2DArray; + + else if( strcmp( str, "help" ) == 0 || strcmp( str, "?" ) == 0 ) + { + printUsage( argv[ 0 ] ); + return -1; + } + + else if( ( chanType = get_channel_type_from_name( str ) ) != (cl_channel_type)-1 ) + gChannelTypeToUse = chanType; + + else if( ( chanOrder = get_channel_order_from_name( str ) ) != (cl_channel_order)-1 ) + gChannelOrderToUse = chanOrder; + else + { + log_error( "ERROR: Unknown argument %d: %s. Exiting....\n", i, str ); + return -1; + } + + } + + if( testMethods == 0 ) + testMethods = k1D | k2D | k3D | k1DArray | k2DArray | k2DTo3D | k3DTo2D | k2DArrayTo2D | k2DTo2DArray | k2DArrayTo3D | k3DTo2DArray; + + // Seed the random # generators + if( randomize ) + { + gRandomSeed = (cl_uint) time( NULL ); + log_info( "Random seed: %u.\n", gRandomSeed ); + gReSeed = 1; + } + + int error; + // Get our platform + error = clGetPlatformIDs(1, &platform, NULL); + if( error ) + { + print_error( error, "Unable to get platform" ); + test_finish(); + return -1; + } + + // Get our device + error = clGetDeviceIDs(platform, gDeviceType, 1, &device, NULL ); + if( error ) + { + print_error( error, "Unable to get specified device" ); + test_finish(); + return -1; + } + + char deviceName[ 128 ], deviceVendor[ 128 ], deviceVersion[ 128 ]; + error = clGetDeviceInfo( device, CL_DEVICE_NAME, sizeof( deviceName ), deviceName, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_VENDOR, sizeof( deviceVendor ), deviceVendor, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_VERSION, sizeof( deviceVersion ), deviceVersion, NULL ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to get device information" ); + test_finish(); + return -1; + } + log_info("Using compute device: Name = %s, Vendor = %s, Version = %s\n", deviceName, deviceVendor, deviceVersion ); + + // Check for image support + if(checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) { + log_info("Device does not support images. Skipping test.\n"); + test_finish(); + return 0; + } + + // Create a context to test with + context = clCreateContext( NULL, 1, &device, notify_callback, NULL, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create testing context" ); + test_finish(); + return -1; + } + + // Create a queue against the context + queue = clCreateCommandQueueWithProperties( context, device, 0, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create testing command queue" ); + test_finish(); + return -1; + } + + if( gTestSmallImages ) + log_info( "Note: Using small test images\n" ); + + // Run the test now + int ret = 0; + for( int test = k1D; test <= k3DTo2DArray; test <<= 1 ) + { + if( testMethods & test ) + ret += test_image_set( device, (MethodsToTest)test ); + } + + error = clFinish(queue); + if (error) + print_error(error, "clFinish failed."); + + if (gTestFailure == 0) { + if (gTestCount > 1) + log_info("PASSED %d of %d tests.\n", gTestCount, gTestCount); + else + log_info("PASSED test.\n"); + } else if (gTestFailure > 0) { + if (gTestCount > 1) + log_error("FAILED %d of %d tests.\n", gTestFailure, gTestCount); + else + log_error("FAILED test.\n"); + } + + // Clean up + clReleaseCommandQueue(queue); + clReleaseContext(context); + test_finish(); + + if (gTestFailure > 0) + return gTestFailure; + + return ret; +} diff --git a/test_conformance/images/clCopyImage/test_copy_1D.cpp b/test_conformance/images/clCopyImage/test_copy_1D.cpp new file mode 100644 index 00000000..205f0ea3 --- /dev/null +++ b/test_conformance/images/clCopyImage/test_copy_1D.cpp @@ -0,0 +1,235 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_command_queue queue; +extern cl_context context; + +extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, + const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d ); + +int test_copy_image_size_1D( cl_device_id device, image_descriptor *imageInfo, MTdata d ) +{ + size_t sourcePos[ 3 ], destPos[ 3 ], regionSize[ 3 ]; + int ret = 0, retCode; + size_t src_lod = 0, src_width_lod = imageInfo->width, src_row_pitch_lod; + size_t dst_lod = 0, dst_width_lod = imageInfo->width, dst_row_pitch_lod; + size_t width_lod = imageInfo->width; + size_t max_mip_level; + + if( gTestMipmaps ) + { + max_mip_level = imageInfo->num_mip_levels; + // Work at a random mip level + src_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d ); + dst_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d ); + src_width_lod = ( imageInfo->width >> src_lod )? ( imageInfo->width >> src_lod ) : 1; + dst_width_lod = ( imageInfo->width >> dst_lod )? ( imageInfo->width >> dst_lod ) : 1; + width_lod = ( src_width_lod > dst_width_lod ) ? dst_width_lod : src_width_lod; + src_row_pitch_lod = src_width_lod * get_pixel_size( imageInfo->format ); + dst_row_pitch_lod = dst_width_lod * get_pixel_size( imageInfo->format ); + } + + // First, try just a full covering region + sourcePos[ 0 ] = sourcePos[ 1 ] = sourcePos[ 2 ] = 0; + destPos[ 0 ] = destPos[ 1 ] = destPos[ 2 ] = 0; + regionSize[ 0 ] = imageInfo->width; + regionSize[ 1 ] = 1; + regionSize[ 2 ] = 1; + + if(gTestMipmaps) + { + sourcePos[ 1 ] = src_lod; + destPos[ 1 ] = dst_lod; + regionSize[ 0 ] = width_lod; + } + + retCode = test_copy_image_generic( device, imageInfo, imageInfo, sourcePos, destPos, regionSize, d ); + if( retCode < 0 ) + return retCode; + else + ret += retCode; + + // Now try a sampling of different random regions + for( int i = 0; i < 8; i++ ) + { + if( gTestMipmaps ) + { + // Work at a random mip level + src_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d ); + dst_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d ); + src_width_lod = ( imageInfo->width >> src_lod )? ( imageInfo->width >> src_lod ) : 1; + dst_width_lod = ( imageInfo->width >> dst_lod )? ( imageInfo->width >> dst_lod ) : 1; + width_lod = ( src_width_lod > dst_width_lod ) ? dst_width_lod : src_width_lod; + sourcePos[ 1 ] = src_lod; + destPos[ 1 ] = dst_lod; + } + // Pick a random size + regionSize[ 0 ] = ( width_lod > 8 ) ? (size_t)random_in_range( 8, (int)width_lod - 1, d ) : width_lod; + + // Now pick positions within valid ranges + sourcePos[ 0 ] = ( width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + destPos[ 0 ] = ( width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + + + // Go for it! + retCode = test_copy_image_generic( device, imageInfo, imageInfo, sourcePos, destPos, regionSize, d ); + if( retCode < 0 ) + return retCode; + else + ret += retCode; + } + + return ret; +} + +int test_copy_image_set_1D( cl_device_id device, cl_image_format *format ) +{ + size_t maxWidth; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed(gRandomSeed); + size_t pixelSize; + + imageInfo.format = format; + imageInfo.height = imageInfo.depth = imageInfo.arraySize = imageInfo.slicePitch = 0; + imageInfo.type = CL_MEM_OBJECT_IMAGE1D; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + size_t rowPadding = gEnablePitch ? 48 : 0; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed); + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + if( gDebugTrace ) + log_info( " at size %d\n", (int)imageInfo.width ); + + int ret = test_copy_image_size_1D( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + size_t rowPadding = gEnablePitch ? 48 : 0; + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed); + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + log_info( "Testing %d\n", (int)sizes[ idx ][ 0 ] ); + if( gDebugTrace ) + log_info( " at max size %d\n", (int)sizes[ idx ][ 0 ] ); + if( test_copy_image_size_1D( device, &imageInfo, seed ) ) + return -1; + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + size_t rowPadding = gEnablePitch ? 48 : 0; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + + if (gTestMipmaps) + { + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed); + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + size = compute_mipmapped_image_size( imageInfo ); + size = size*4; + } + else + { + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + size = (size_t)imageInfo.rowPitch * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + { + log_info( " at size %d (row pitch %d) out of %d\n", (int)imageInfo.width, (int)imageInfo.rowPitch, (int)maxWidth ); + if ( gTestMipmaps ) + log_info( " and %llu mip levels\n", (size_t) imageInfo.num_mip_levels ); + } + + int ret = test_copy_image_size_1D( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clCopyImage/test_copy_1D_array.cpp b/test_conformance/images/clCopyImage/test_copy_1D_array.cpp new file mode 100644 index 00000000..3d3633ec --- /dev/null +++ b/test_conformance/images/clCopyImage/test_copy_1D_array.cpp @@ -0,0 +1,248 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_command_queue queue; +extern cl_context context; + +extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, + const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d ); + +int test_copy_image_size_1D_array( cl_device_id device, image_descriptor *imageInfo, MTdata d ) +{ + size_t sourcePos[ 3 ], destPos[ 3 ], regionSize[ 3 ]; + int ret = 0, retCode; + size_t src_lod = 0, src_width_lod = imageInfo->width, src_row_pitch_lod; + size_t dst_lod = 0, dst_width_lod = imageInfo->width, dst_row_pitch_lod; + size_t width_lod = imageInfo->width; + size_t max_mip_level; + + if( gTestMipmaps ) + { + max_mip_level = imageInfo->num_mip_levels; + // Work at a random mip level + src_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d ); + dst_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d ); + src_width_lod = ( imageInfo->width >> src_lod )? ( imageInfo->width >> src_lod ) : 1; + dst_width_lod = ( imageInfo->width >> dst_lod )? ( imageInfo->width >> dst_lod ) : 1; + width_lod = ( src_width_lod > dst_width_lod ) ? dst_width_lod : src_width_lod; + src_row_pitch_lod = src_width_lod * get_pixel_size( imageInfo->format ); + dst_row_pitch_lod = dst_width_lod * get_pixel_size( imageInfo->format ); + } + + // First, try just a full covering region + sourcePos[ 0 ] = sourcePos[ 1 ] = sourcePos[ 2 ] = 0; + destPos[ 0 ] = destPos[ 1 ] = destPos[ 2 ] = 0; + regionSize[ 0 ] = imageInfo->width; + regionSize[ 1 ] = imageInfo->arraySize; + regionSize[ 2 ] = 1; + + if(gTestMipmaps) + { + sourcePos[ 2 ] = src_lod; + destPos[ 2 ] = dst_lod; + regionSize[ 0 ] = width_lod; + } + + retCode = test_copy_image_generic( device, imageInfo, imageInfo, sourcePos, destPos, regionSize, d ); + if( retCode < 0 ) + return retCode; + else + ret += retCode; + + // Now try a sampling of different random regions + for( int i = 0; i < 8; i++ ) + { + if( gTestMipmaps ) + { + // Work at a random mip level + src_lod = (size_t) ( max_mip_level > 1 )? random_in_range( 0, max_mip_level - 1 , d ) : 0; + dst_lod = (size_t) ( max_mip_level > 1 )? random_in_range( 0, max_mip_level - 1 , d ) : 0; + src_width_lod = ( imageInfo->width >> src_lod )? ( imageInfo->width >> src_lod ) : 1; + dst_width_lod = ( imageInfo->width >> dst_lod )? ( imageInfo->width >> dst_lod ) : 1; + width_lod = ( src_width_lod > dst_width_lod ) ? dst_width_lod : src_width_lod; + sourcePos[ 2 ] = src_lod; + destPos[ 2 ] = dst_lod; + } + // Pick a random size + regionSize[ 0 ] = ( width_lod > 8 ) ? (size_t)random_in_range( 8, (int)width_lod - 1, d ) : (int)width_lod; + regionSize[ 1 ] = ( imageInfo->arraySize > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->arraySize - 1, d ) : imageInfo->arraySize; + + // Now pick positions within valid ranges + sourcePos[ 0 ] = ( width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + sourcePos[ 1 ] = ( imageInfo->arraySize > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->arraySize - regionSize[ 1 ] - 1 ), d ) : 0; + + + destPos[ 0 ] = ( width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + destPos[ 1 ] = ( imageInfo->arraySize > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->arraySize - regionSize[ 1 ] - 1 ), d ) : 0; + + + // Go for it! + retCode = test_copy_image_generic( device, imageInfo, imageInfo, sourcePos, destPos, regionSize, d ); + if( retCode < 0 ) + return retCode; + else + ret += retCode; + } + + return ret; +} + +int test_copy_image_set_1D_array( cl_device_id device, cl_image_format *format ) +{ + size_t maxWidth, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed(gRandomSeed); + size_t pixelSize; + + imageInfo.format = format; + imageInfo.type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 1D array size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + size_t rowPadding = gEnablePitch ? 48 : 0; + + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed); + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + imageInfo.slicePitch = imageInfo.rowPitch; + for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ ) + { + if( gDebugTrace ) + log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize ); + + int ret = test_copy_image_size_1D_array( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D_ARRAY, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + size_t rowPadding = gEnablePitch ? 48 : 0; + + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.arraySize = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed); + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + imageInfo.slicePitch = imageInfo.rowPitch; + log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ] ); + if( gDebugTrace ) + log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ] ); + if( test_copy_image_size_1D_array( device, &imageInfo, seed ) ) + return -1; + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + size_t rowPadding = gEnablePitch ? 48 : 0; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed ); + imageInfo.height = imageInfo.depth = 0; + + if (gTestMipmaps) + { + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed); + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.rowPitch; + size = compute_mipmapped_image_size( imageInfo ); + size = size*4; + } + else + { + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + imageInfo.slicePitch = imageInfo.rowPitch; + + size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.arraySize * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxArraySize ); + int ret = test_copy_image_size_1D_array( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clCopyImage/test_copy_2D.cpp b/test_conformance/images/clCopyImage/test_copy_2D.cpp new file mode 100644 index 00000000..3a9ed478 --- /dev/null +++ b/test_conformance/images/clCopyImage/test_copy_2D.cpp @@ -0,0 +1,248 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_command_queue queue; +extern cl_context context; + +extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, + const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d ); + +int test_copy_image_size_2D( cl_device_id device, image_descriptor *imageInfo, MTdata d ) +{ + size_t sourcePos[ 3 ], destPos[ 3 ], regionSize[ 3 ]; + int ret = 0, retCode; + size_t src_lod = 0, src_width_lod = imageInfo->width, src_row_pitch_lod; + size_t src_height_lod = imageInfo->height; + size_t dst_lod = 0, dst_width_lod = imageInfo->width, dst_row_pitch_lod; + size_t dst_height_lod = imageInfo->height; + size_t width_lod = imageInfo->width, height_lod = imageInfo->height; + size_t max_mip_level; + + if( gTestMipmaps ) + { + max_mip_level = imageInfo->num_mip_levels; + // Work at a random mip level + src_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d ); + dst_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d ); + src_width_lod = ( imageInfo->width >> src_lod )? ( imageInfo->width >> src_lod ) : 1; + dst_width_lod = ( imageInfo->width >> dst_lod )? ( imageInfo->width >> dst_lod ) : 1; + src_height_lod = ( imageInfo->height >> src_lod )? ( imageInfo->height >> src_lod ) : 1; + dst_height_lod = ( imageInfo->height >> dst_lod )? ( imageInfo->height >> dst_lod ) : 1; + width_lod = ( src_width_lod > dst_width_lod ) ? dst_width_lod : src_width_lod; + height_lod = ( src_height_lod > dst_height_lod ) ? dst_height_lod : src_height_lod; + src_row_pitch_lod = src_width_lod * get_pixel_size( imageInfo->format ); + dst_row_pitch_lod = dst_width_lod * get_pixel_size( imageInfo->format ); + } + + // First, try just a full covering region + sourcePos[ 0 ] = sourcePos[ 1 ] = sourcePos[ 2 ] = 0; + destPos[ 0 ] = destPos[ 1 ] = destPos[ 2 ] = 0; + regionSize[ 0 ] = imageInfo->width; + regionSize[ 1 ] = imageInfo->height; + regionSize[ 2 ] = 1; + + if(gTestMipmaps) + { + sourcePos[ 2 ] = src_lod; + destPos[ 2 ] = dst_lod; + regionSize[ 0 ] = width_lod; + regionSize[ 1 ] = height_lod; + } + + retCode = test_copy_image_generic( device, imageInfo, imageInfo, sourcePos, destPos, regionSize, d ); + if( retCode < 0 ) + return retCode; + else + ret += retCode; + + // Now try a sampling of different random regions + for( int i = 0; i < 8; i++ ) + { + if( gTestMipmaps ) + { + // Work at a random mip level + src_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d ); + dst_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d ); + src_width_lod = ( imageInfo->width >> src_lod )? ( imageInfo->width >> src_lod ) : 1; + dst_width_lod = ( imageInfo->width >> dst_lod )? ( imageInfo->width >> dst_lod ) : 1; + src_height_lod = ( imageInfo->height >> src_lod )? ( imageInfo->height >> src_lod ) : 1; + dst_height_lod = ( imageInfo->height >> dst_lod )? ( imageInfo->height >> dst_lod ) : 1; + width_lod = ( src_width_lod > dst_width_lod ) ? dst_width_lod : src_width_lod; + height_lod = ( src_height_lod > dst_height_lod ) ? dst_height_lod : src_height_lod; + sourcePos[ 2 ] = src_lod; + destPos[ 2 ] = dst_lod; + } + // Pick a random size + regionSize[ 0 ] = ( width_lod > 8 ) ? (size_t)random_in_range( 8, (int)width_lod - 1, d ) : width_lod; + regionSize[ 1 ] = ( height_lod > 8 ) ? (size_t)random_in_range( 8, (int)height_lod - 1, d ) : height_lod; + + // Now pick positions within valid ranges + sourcePos[ 0 ] = ( width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + sourcePos[ 1 ] = ( height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( height_lod - regionSize[ 1 ] - 1 ), d ) : 0; + + destPos[ 0 ] = ( width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + destPos[ 1 ] = ( height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( height_lod - regionSize[ 1 ] - 1 ), d ) : 0; + + // Go for it! + retCode = test_copy_image_generic( device, imageInfo, imageInfo, sourcePos, destPos, regionSize, d ); + if( retCode < 0 ) + return retCode; + else + ret += retCode; + } + + return ret; +} + +int test_copy_image_set_2D( cl_device_id device, cl_image_format *format ) +{ + size_t maxWidth, maxHeight; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed(gRandomSeed); + size_t pixelSize; + + imageInfo.format = format; + imageInfo.type = CL_MEM_OBJECT_IMAGE2D; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + size_t rowPadding = gEnablePitch ? 48 : 0; + + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed); + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + if( gDebugTrace ) + log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.height ); + + int ret = test_copy_image_size_2D( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + size_t rowPadding = gEnablePitch ? 48 : 0; + + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed); + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] ); + if( gDebugTrace ) + log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] ); + if( test_copy_image_size_2D( device, &imageInfo, seed ) ) + return -1; + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + size_t rowPadding = gEnablePitch ? 48 : 0; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + + if (gTestMipmaps) + { + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed); + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + size = compute_mipmapped_image_size( imageInfo ); + size = size*4; + } + else + { + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.height * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight ); + int ret = test_copy_image_size_2D( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clCopyImage/test_copy_2D_2D_array.cpp b/test_conformance/images/clCopyImage/test_copy_2D_2D_array.cpp new file mode 100644 index 00000000..d7d63040 --- /dev/null +++ b/test_conformance/images/clCopyImage/test_copy_2D_2D_array.cpp @@ -0,0 +1,419 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gTestRounding, gEnablePitch, gTestMipmaps; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_command_queue queue; +extern cl_context context; + +extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, + const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d ); + + +static size_t random_in_ranges( size_t minimum, size_t rangeA, size_t rangeB, MTdata d ) +{ + if( rangeB < rangeA ) + rangeA = rangeB; + if( rangeA < minimum ) + return rangeA; + return (size_t)random_in_range( (int)minimum, (int)rangeA - 1, d ); +} + + +static void set_image_dimensions( image_descriptor *imageInfo, size_t width, size_t height, size_t arraySize, size_t rowPadding, size_t slicePadding ) +{ + size_t pixelSize = get_pixel_size( imageInfo->format ); + + imageInfo->width = width; + imageInfo->height = height; + imageInfo->arraySize = arraySize; + imageInfo->rowPitch = imageInfo->width * pixelSize + rowPadding; + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo->rowPitch = imageInfo->width * pixelSize + rowPadding; + } while ((imageInfo->rowPitch % pixelSize) != 0); + } + + if (arraySize == 0) + { + imageInfo->type = CL_MEM_OBJECT_IMAGE2D; + imageInfo->slicePitch = 0; + } + else + { + imageInfo->type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + imageInfo->slicePitch = imageInfo->rowPitch * (imageInfo->height + slicePadding); + } +} + + +int test_copy_image_size_2D_2D_array( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, MTdata d ) +{ + size_t sourcePos[ 4 ] = { 0 }, destPos[ 4 ] = { 0 }, regionSize[ 3 ]; + int ret = 0, retCode; + + image_descriptor *threeImage, *twoImage; + + if( srcImageInfo->arraySize > 0 ) + { + threeImage = srcImageInfo; + twoImage = dstImageInfo; + } + else + { + threeImage = dstImageInfo; + twoImage = srcImageInfo; + } + + size_t twoImage_lod = 0, twoImage_width_lod = twoImage->width, twoImage_row_pitch_lod; + size_t twoImage_height_lod = twoImage->height; + size_t threeImage_lod = 0, threeImage_width_lod = threeImage->width, threeImage_row_pitch_lod, threeImage_slice_pitch_lod; + size_t threeImage_height_lod = threeImage->height; + size_t width_lod, height_lod; + size_t twoImage_max_mip_level,threeImage_max_mip_level; + + if( gTestMipmaps ) + { + twoImage_max_mip_level = twoImage->num_mip_levels; + threeImage_max_mip_level = threeImage->num_mip_levels; + // Work at random mip levels + twoImage_lod = (size_t)random_in_range( 0, twoImage_max_mip_level ? twoImage_max_mip_level - 1 : 0, d ); + threeImage_lod = (size_t)random_in_range( 0, threeImage_max_mip_level ? threeImage_max_mip_level - 1 : 0, d ); + twoImage_width_lod = ( twoImage->width >> twoImage_lod )? ( twoImage->width >> twoImage_lod ) : 1; + threeImage_width_lod = ( threeImage->width >> threeImage_lod )? ( threeImage->width >> threeImage_lod ) : 1; + twoImage_height_lod = ( twoImage->height >> twoImage_lod )? ( twoImage->height >> twoImage_lod ) : 1; + threeImage_height_lod = ( threeImage->height >> threeImage_lod )? ( threeImage->height >> threeImage_lod ) : 1; + twoImage_row_pitch_lod = twoImage_width_lod * get_pixel_size( twoImage->format ); + threeImage_row_pitch_lod = threeImage_width_lod * get_pixel_size( threeImage->format ); + threeImage_slice_pitch_lod = threeImage_height_lod * threeImage_row_pitch_lod; + } + width_lod = ( twoImage_width_lod > threeImage_width_lod ) ? threeImage_width_lod : twoImage_width_lod; + height_lod = ( twoImage_height_lod > threeImage_height_lod ) ? threeImage_height_lod : twoImage_height_lod; + + // First, try just a full covering region + sourcePos[ 0 ] = sourcePos[ 1 ] = sourcePos[ 2 ] = sourcePos[ 3 ] = 0; + destPos[ 0 ] = destPos[ 1 ] = destPos[ 2 ] = destPos[ 3 ] = 0; + regionSize[ 0 ] = width_lod; + regionSize[ 1 ] = height_lod; + regionSize[ 2 ] = 1; + + if( srcImageInfo->arraySize == 0 ) + { + // 2D to 2D array + destPos[ 2 ] = (size_t)random_in_range( 0, (int)dstImageInfo->arraySize - 1, d ); + if(gTestMipmaps) + { + sourcePos[ 2 ] = twoImage_lod; + destPos[ 3 ] = threeImage_lod; + regionSize[ 0 ] = width_lod; + regionSize[ 1 ] = height_lod; + } + } + else + { + // 2D array to 2D + sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)srcImageInfo->arraySize - 1, d ); + if(gTestMipmaps) + { + sourcePos[ 3 ] = threeImage_lod; + destPos[ 2 ] = twoImage_lod; + regionSize[ 0 ] = width_lod; + regionSize[ 1 ] = height_lod; + } + } + + retCode = test_copy_image_generic( device, srcImageInfo, dstImageInfo, sourcePos, destPos, regionSize, d ); + if( retCode < 0 ) + return retCode; + else + ret += retCode; + + // Now try a sampling of different random regions + for( int i = 0; i < 8; i++ ) + { + if( gTestMipmaps ) + { + // Work at a random mip level + twoImage_lod = (size_t)random_in_range( 0, twoImage_max_mip_level ? twoImage_max_mip_level - 1 : 0, d ); + threeImage_lod = (size_t)random_in_range( 0, threeImage_max_mip_level ? threeImage_max_mip_level - 1 : 0, d ); + twoImage_width_lod = ( twoImage->width >> twoImage_lod )? ( twoImage->width >> twoImage_lod ) : 1; + threeImage_width_lod = ( threeImage->width >> threeImage_lod )? ( threeImage->width >> threeImage_lod ) : 1; + twoImage_height_lod = ( twoImage->height >> twoImage_lod )? ( twoImage->height >> twoImage_lod ) : 1; + threeImage_height_lod = ( threeImage->height >> threeImage_lod )? ( threeImage->height >> threeImage_lod ) : 1; + width_lod = ( twoImage_width_lod > threeImage_width_lod ) ? threeImage_width_lod : twoImage_width_lod; + height_lod = ( twoImage_height_lod > threeImage_height_lod ) ? threeImage_height_lod : twoImage_height_lod; + } + // Pick a random size + regionSize[ 0 ] = random_in_ranges( 8, srcImageInfo->width, dstImageInfo->width, d ); + regionSize[ 1 ] = random_in_ranges( 8, srcImageInfo->height, dstImageInfo->height, d ); + if( gTestMipmaps ) + { + regionSize[ 0 ] = ( width_lod > 8 ) ? random_in_range( 8, width_lod, d ) : width_lod; + regionSize[ 1 ] = ( height_lod > 8) ? random_in_range( 8, height_lod, d ): height_lod; + } + + // Now pick positions within valid ranges + sourcePos[ 0 ] = ( srcImageInfo->width > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->width - regionSize[ 0 ] - 1 ), d ) : 0; + sourcePos[ 1 ] = ( srcImageInfo->height > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->height - regionSize[ 1 ] - 1 ), d ) : 0; + sourcePos[ 2 ] = ( srcImageInfo->arraySize > 0 ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->arraySize - 1 ), d ) : gTestMipmaps ? twoImage_lod : 0; + if ( gTestMipmaps ) + if( srcImageInfo->arraySize > 0 ) + { + sourcePos[ 0 ] = ( threeImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + sourcePos[ 1 ] = ( threeImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0; + sourcePos[ 3 ] = threeImage_lod; + } + else + { + sourcePos[ 0 ] = ( twoImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + sourcePos[ 1 ] = ( twoImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0; + + } + + destPos[ 0 ] = ( dstImageInfo->width > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->width - regionSize[ 0 ] - 1 ), d ) : 0; + destPos[ 1 ] = ( dstImageInfo->height > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->height - regionSize[ 1 ] - 1 ), d ) : 0; + destPos[ 2 ] = ( dstImageInfo->arraySize > 0 ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->arraySize - 1 ), d ) : gTestMipmaps ? twoImage_lod : 0; + if ( gTestMipmaps ) + if( dstImageInfo->arraySize > 0 ) + { + destPos[ 0 ] = ( threeImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + destPos[ 1 ] = ( threeImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0; + destPos[ 3 ] = threeImage_lod; + } + else + { + destPos[ 0 ] = ( twoImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + destPos[ 1 ] = ( twoImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0; + + } + + // Go for it! + retCode = test_copy_image_generic( device, srcImageInfo, dstImageInfo, sourcePos, destPos, regionSize, d ); + if( retCode < 0 ) + return retCode; + else + ret += retCode; + } + + return ret; +} + + +int test_copy_image_set_2D_2D_array( cl_device_id device, cl_image_format *format, bool reverse = false ) +{ + size_t maxWidth, maxHeight, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor srcImageInfo = { 0 }; + image_descriptor dstImageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + + srcImageInfo.format = dstImageInfo.format = format; + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( dstImageInfo.width = 4; dstImageInfo.width < 17; dstImageInfo.width++ ) + { + for( dstImageInfo.height = 4; dstImageInfo.height < 13; dstImageInfo.height++ ) + { + for( dstImageInfo.arraySize = 4; dstImageInfo.arraySize < 9; dstImageInfo.arraySize++ ) + { + size_t rowPadding = gEnablePitch ? 256 : 0; + size_t slicePadding = gEnablePitch ? 3 : 0; + + set_image_dimensions( &dstImageInfo, dstImageInfo.width, dstImageInfo.height, dstImageInfo.arraySize, rowPadding, slicePadding ); + set_image_dimensions( &srcImageInfo, dstImageInfo.width, dstImageInfo.height, 0, rowPadding, slicePadding ); + + if (gTestMipmaps) + { + srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, 0), seed); + srcImageInfo.type = CL_MEM_OBJECT_IMAGE2D; + dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, 0), seed); + dstImageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format ); + srcImageInfo.slicePitch = 0; + dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format ); + dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height; + } + + if( gDebugTrace ) + { + if (reverse) + log_info( " at size %d,%d,%d to %d,%d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height ); + else + log_info( " at size %d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize ); + } + int ret; + if( reverse ) + ret = test_copy_image_size_2D_2D_array( device, &dstImageInfo, &srcImageInfo, seed ); + else + ret = test_copy_image_size_2D_2D_array( device, &srcImageInfo, &dstImageInfo, seed ); + if( ret ) + return -1; + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numberOfSizes2DArray, numberOfSizes2D; + size_t sizes2DArray[100][3], sizes2D[100][3]; + + // Try to allocate a bit smaller images because we need the 2D ones as well for the copy. + get_max_sizes(&numberOfSizes2DArray, 100, sizes2DArray, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize/2, memSize/2, CL_MEM_OBJECT_IMAGE2D_ARRAY, dstImageInfo.format); + get_max_sizes(&numberOfSizes2D, 100, sizes2D, maxWidth, maxHeight, 1, 1, maxAllocSize/2, memSize/2, CL_MEM_OBJECT_IMAGE2D, dstImageInfo.format); + + for( size_t i = 0; i < numberOfSizes2D; i++ ) + { + for( size_t j = 0; j < numberOfSizes2DArray; j++ ) + { + size_t rowPadding = gEnablePitch ? 256 : 0; + size_t slicePadding = gEnablePitch ? 3 : 0; + + set_image_dimensions( &dstImageInfo, sizes2DArray[ j ][ 0 ], sizes2DArray[ j ][ 1 ], sizes2DArray[ j ][ 2 ], rowPadding, slicePadding ); + set_image_dimensions( &srcImageInfo, sizes2D[ i ][ 0 ], sizes2D[ i ][ 1 ], 0, rowPadding, slicePadding ); + + cl_ulong dstSize = get_image_size(&dstImageInfo); + cl_ulong srcSize = get_image_size(&srcImageInfo); + + if (gTestMipmaps) + { + srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, 0), seed); + srcImageInfo.type = CL_MEM_OBJECT_IMAGE2D; + dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, 0), seed); + dstImageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format ); + srcImageInfo.slicePitch = 0; + dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format ); + dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height; + dstSize = 4 * compute_mipmapped_image_size( dstImageInfo ); + srcSize = 4 * compute_mipmapped_image_size( srcImageInfo ); + } + + if( dstSize < maxAllocSize && dstSize < ( memSize / 3 ) && srcSize < maxAllocSize && srcSize < ( memSize / 3 ) ) + { + if (reverse) + log_info( "Testing %d x %d x %d to %d x %d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height ); + else + log_info( "Testing %d x %d to %d x %d x %d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize ); + + if( gDebugTrace ) + { + if (reverse) + log_info( " at max size %d,%d,%d to %d,%d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height ); + else + log_info( " at max size %d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize ); + } + int ret; + if( reverse ) + ret = test_copy_image_size_2D_2D_array( device, &dstImageInfo, &srcImageInfo, seed ); + else + ret = test_copy_image_size_2D_2D_array( device, &srcImageInfo, &dstImageInfo, seed ); + if( ret ) + return -1; + } + else + { + if (reverse) + log_info("Not testing max size %d x %d x %d to %d x %d due to memory constraints.\n", + (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height); + else + log_info("Not testing max size %d x %d to %d x %d x %d due to memory constraints.\n", + (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize); + } + + } + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong srcSize, dstSize; + size_t rowPadding = gEnablePitch ? 256 : 0; + size_t slicePadding = gEnablePitch ? 3 : 0; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + dstImageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + dstImageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + dstImageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed ); + srcImageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + srcImageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + + if (gTestMipmaps) + { + srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, 0), seed); + srcImageInfo.type = CL_MEM_OBJECT_IMAGE2D; + dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, 0), seed); + dstImageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format ); + srcImageInfo.slicePitch = 0; + dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format ); + dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height; + srcSize = 4 * compute_mipmapped_image_size( srcImageInfo ); + dstSize = 4 * compute_mipmapped_image_size( dstImageInfo ); + } + else + { + set_image_dimensions( &srcImageInfo, srcImageInfo.width, srcImageInfo.height, 0, rowPadding, slicePadding ); + set_image_dimensions( &dstImageInfo, dstImageInfo.width, dstImageInfo.height, dstImageInfo.arraySize, rowPadding, slicePadding ); + + srcSize = (cl_ulong)srcImageInfo.rowPitch * (cl_ulong)srcImageInfo.height * 4; + dstSize = (cl_ulong)dstImageInfo.slicePitch * (cl_ulong)dstImageInfo.arraySize * 4; + } + } while( srcSize > maxAllocSize || ( srcSize * 3 ) > memSize || dstSize > maxAllocSize || ( dstSize * 3 ) > memSize); + + if( gDebugTrace ) + { + if (reverse) + log_info( " at size %d,%d,%d to %d,%d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height ); + else + log_info( " at size %d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize ); + } + int ret; + if( reverse ) + ret = test_copy_image_size_2D_2D_array( device, &dstImageInfo, &srcImageInfo, seed ); + else + ret = test_copy_image_size_2D_2D_array( device, &srcImageInfo, &dstImageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clCopyImage/test_copy_2D_3D.cpp b/test_conformance/images/clCopyImage/test_copy_2D_3D.cpp new file mode 100644 index 00000000..8873e48b --- /dev/null +++ b/test_conformance/images/clCopyImage/test_copy_2D_3D.cpp @@ -0,0 +1,401 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gTestRounding, gEnablePitch, gTestMipmaps; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_command_queue queue; +extern cl_context context; + +extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, + const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d ); + + +static size_t random_in_ranges( size_t minimum, size_t rangeA, size_t rangeB, MTdata d ) +{ + if( rangeB < rangeA ) + rangeA = rangeB; + if( rangeA < minimum ) + return rangeA; + return (size_t)random_in_range( (int)minimum, (int)rangeA - 1, d ); +} + + +static void set_image_dimensions( image_descriptor *imageInfo, size_t width, size_t height, size_t depth, size_t rowPadding, size_t slicePadding ) +{ + size_t pixelSize = get_pixel_size( imageInfo->format ); + + imageInfo->width = width; + imageInfo->height = height; + imageInfo->depth = depth; + imageInfo->rowPitch = imageInfo->width * pixelSize + rowPadding; + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo->rowPitch = imageInfo->width * pixelSize + rowPadding; + } while ((imageInfo->rowPitch % pixelSize) != 0); + } + + imageInfo->slicePitch = imageInfo->rowPitch * (imageInfo->height + slicePadding); + + if (depth == 0) + imageInfo->type = CL_MEM_OBJECT_IMAGE2D; + else + imageInfo->type = CL_MEM_OBJECT_IMAGE3D; +} + + +int test_copy_image_size_2D_3D( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, MTdata d ) +{ + size_t sourcePos[ 4 ] = { 0 }, destPos[ 4 ] = { 0 }, regionSize[ 3 ]; + int ret = 0, retCode; + + image_descriptor *threeImage, *twoImage; + + if( srcImageInfo->depth > 0 ) + { + threeImage = srcImageInfo; + twoImage = dstImageInfo; + } + else + { + threeImage = dstImageInfo; + twoImage = srcImageInfo; + } + + size_t twoImage_lod = 0, twoImage_width_lod = twoImage->width, twoImage_row_pitch_lod; + size_t twoImage_height_lod = twoImage->height; + size_t threeImage_lod = 0, threeImage_width_lod = threeImage->width, threeImage_row_pitch_lod, threeImage_slice_pitch_lod; + size_t threeImage_height_lod = threeImage->height, depth_lod = threeImage->depth; + size_t width_lod, height_lod; + size_t twoImage_max_mip_level,threeImage_max_mip_level; + + if( gTestMipmaps ) + { + twoImage_max_mip_level = twoImage->num_mip_levels; + threeImage_max_mip_level = threeImage->num_mip_levels; + // Work at random mip levels + twoImage_lod = (size_t)random_in_range( 0, twoImage_max_mip_level ? twoImage_max_mip_level - 1 : 0, d ); + threeImage_lod = (size_t)random_in_range( 0, threeImage_max_mip_level ? threeImage_max_mip_level - 1 : 0, d ); + twoImage_width_lod = ( twoImage->width >> twoImage_lod )? ( twoImage->width >> twoImage_lod ) : 1; + threeImage_width_lod = ( threeImage->width >> threeImage_lod )? ( threeImage->width >> threeImage_lod ) : 1; + twoImage_height_lod = ( twoImage->height >> twoImage_lod )? ( twoImage->height >> twoImage_lod ) : 1; + threeImage_height_lod = ( threeImage->height >> threeImage_lod )? ( threeImage->height >> threeImage_lod ) : 1; + depth_lod = ( threeImage->depth >> threeImage_lod )? ( threeImage->depth >> threeImage_lod ) : 1; + twoImage_row_pitch_lod = twoImage_width_lod * get_pixel_size( twoImage->format ); + threeImage_row_pitch_lod = threeImage_width_lod * get_pixel_size( threeImage->format ); + threeImage_slice_pitch_lod = threeImage_height_lod * threeImage_row_pitch_lod; + } + width_lod = ( twoImage_width_lod > threeImage_width_lod ) ? threeImage_width_lod : twoImage_width_lod; + height_lod = ( twoImage_height_lod > threeImage_height_lod ) ? threeImage_height_lod : twoImage_height_lod; + + // First, try just a full covering region + sourcePos[ 0 ] = sourcePos[ 1 ] = sourcePos[ 2 ] = sourcePos[ 3 ] = 0; + destPos[ 0 ] = destPos[ 1 ] = destPos[ 2 ] = destPos[ 3 ] = 0; + regionSize[ 0 ] = width_lod; + regionSize[ 1 ] = height_lod; + regionSize[ 2 ] = 1; + + if( srcImageInfo->depth == 0 ) + { + // 2D to 3D + destPos[ 2 ] = (size_t)random_in_range( 0, (int)dstImageInfo->depth - 1, d ); + if(gTestMipmaps) + { + destPos[ 2 ] = (size_t)random_in_range( 0, (int)depth_lod - 1, d ); + sourcePos[ 2 ] = twoImage_lod; + destPos[ 3 ] = threeImage_lod; + regionSize[ 0 ] = width_lod; + regionSize[ 1 ] = height_lod; + } + } + else + { + // 3D to 2D + sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)srcImageInfo->depth - 1, d ); + if(gTestMipmaps) + { + sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)depth_lod - 1, d ); + sourcePos[ 3 ] = threeImage_lod; + destPos[ 2 ] = twoImage_lod; + regionSize[ 0 ] = width_lod; + regionSize[ 1 ] = height_lod; + } + } + + retCode = test_copy_image_generic( device, srcImageInfo, dstImageInfo, sourcePos, destPos, regionSize, d ); + if( retCode < 0 ) + return retCode; + else + ret += retCode; + + // Now try a sampling of different random regions + for( int i = 0; i < 8; i++ ) + { + if( gTestMipmaps ) + { + // Work at a random mip level + twoImage_lod = (size_t)random_in_range( 0, twoImage_max_mip_level ? twoImage_max_mip_level - 1 : 0, d ); + threeImage_lod = (size_t)random_in_range( 0, threeImage_max_mip_level ? threeImage_max_mip_level - 1 : 0, d ); + twoImage_width_lod = ( twoImage->width >> twoImage_lod )? ( twoImage->width >> twoImage_lod ) : 1; + threeImage_width_lod = ( threeImage->width >> threeImage_lod )? ( threeImage->width >> threeImage_lod ) : 1; + twoImage_height_lod = ( twoImage->height >> twoImage_lod )? ( twoImage->height >> twoImage_lod ) : 1; + threeImage_height_lod = ( threeImage->height >> threeImage_lod )? ( threeImage->height >> threeImage_lod ) : 1; + width_lod = ( twoImage_width_lod > threeImage_width_lod ) ? threeImage_width_lod : twoImage_width_lod; + height_lod = ( twoImage_height_lod > threeImage_height_lod ) ? threeImage_height_lod : twoImage_height_lod; + depth_lod = ( threeImage->depth >> threeImage_lod )? ( threeImage->depth >> threeImage_lod ) : 1; + } + // Pick a random size + regionSize[ 0 ] = random_in_ranges( 8, srcImageInfo->width, dstImageInfo->width, d ); + regionSize[ 1 ] = random_in_ranges( 8, srcImageInfo->height, dstImageInfo->height, d ); + if( gTestMipmaps ) + { + regionSize[ 0 ] = ( width_lod > 8 ) ? random_in_range( 8, width_lod, d ) : width_lod; + regionSize[ 1 ] = ( height_lod > 8) ? random_in_range( 8, height_lod, d ): height_lod; + } + + // Now pick positions within valid ranges + sourcePos[ 0 ] = ( srcImageInfo->width > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->width - regionSize[ 0 ] - 1 ), d ) : 0; + sourcePos[ 1 ] = ( srcImageInfo->height > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->height - regionSize[ 1 ] - 1 ), d ) : 0; + sourcePos[ 2 ] = ( srcImageInfo->depth > 0 ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->depth - 1 ), d ) : 0; + + if ( gTestMipmaps ) + if( srcImageInfo->depth > 0 ) + { + sourcePos[ 0 ] = ( threeImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + sourcePos[ 1 ] = ( threeImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0; + sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)( depth_lod - 1 ), d ); + sourcePos[ 3 ] = threeImage_lod; + } + else + { + sourcePos[ 0 ] = ( twoImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + sourcePos[ 1 ] = ( twoImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0; + + } + + destPos[ 0 ] = ( dstImageInfo->width > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->width - regionSize[ 0 ] - 1 ), d ) : 0; + destPos[ 1 ] = ( dstImageInfo->height > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->height - regionSize[ 1 ] - 1 ), d ) : 0; + destPos[ 2 ] = ( dstImageInfo->depth > 0 ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->depth - 1 ), d ) : 0; + + if ( gTestMipmaps ) + if( dstImageInfo->depth > 0 ) + { + destPos[ 0 ] = ( threeImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + destPos[ 1 ] = ( threeImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0; + destPos[ 2 ] = (size_t)random_in_range( 0, (int)( depth_lod - 1 ), d ); + destPos[ 3 ] = threeImage_lod; + } + else + { + destPos[ 0 ] = ( twoImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + destPos[ 1 ] = ( twoImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0; + + } + + // Go for it! + retCode = test_copy_image_generic( device, srcImageInfo, dstImageInfo, sourcePos, destPos, regionSize, d ); + if( retCode < 0 ) + return retCode; + else + ret += retCode; + } + + return ret; +} + + +int test_copy_image_set_2D_3D( cl_device_id device, cl_image_format *format, bool reverse = false ) +{ + size_t maxWidth, maxHeight, max3DWidth, max3DHeight, max3DDepth; + cl_ulong maxAllocSize, memSize; + image_descriptor srcImageInfo = { 0 }; + image_descriptor dstImageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + + srcImageInfo.format = dstImageInfo.format = format; + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( max3DWidth ), &max3DWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( max3DHeight ), &max3DHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( max3DDepth ), &max3DDepth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D or 3D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( dstImageInfo.width = 4; dstImageInfo.width < 17; dstImageInfo.width++ ) + { + for( dstImageInfo.height = 4; dstImageInfo.height < 13; dstImageInfo.height++ ) + { + for( dstImageInfo.depth = 4; dstImageInfo.depth < 9; dstImageInfo.depth++ ) + { + size_t rowPadding = gEnablePitch ? 256 : 0; + size_t slicePadding = gEnablePitch ? 3 : 0; + + set_image_dimensions( &dstImageInfo, dstImageInfo.width, dstImageInfo.height, dstImageInfo.depth, rowPadding, slicePadding ); + set_image_dimensions( &srcImageInfo, dstImageInfo.width, dstImageInfo.height, 0, rowPadding, slicePadding ); + + if (gTestMipmaps) + { + srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, 0), seed); + srcImageInfo.type = CL_MEM_OBJECT_IMAGE2D; + dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, dstImageInfo.depth), seed); + dstImageInfo.type = CL_MEM_OBJECT_IMAGE3D; + srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format ); + srcImageInfo.slicePitch = 0; + dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format ); + dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height; + } + + if( gDebugTrace ) + log_info( " at size %d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.depth ); + + int ret; + if( reverse ) + ret = test_copy_image_size_2D_3D( device, &dstImageInfo, &srcImageInfo, seed ); + else + ret = test_copy_image_size_2D_3D( device, &srcImageInfo, &dstImageInfo, seed ); + if( ret ) + return -1; + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numberOfSizes3D, numberOfSizes2D; + size_t sizes3D[100][3], sizes2D[100][3]; + + // Try to allocate a bit smaller images because we need the 2D ones as well for the copy. + get_max_sizes(&numberOfSizes3D, 100, sizes3D, max3DWidth, max3DHeight, max3DDepth, 1, maxAllocSize/2, memSize/2, CL_MEM_OBJECT_IMAGE3D, dstImageInfo.format); + get_max_sizes(&numberOfSizes2D, 100, sizes2D, maxWidth, maxHeight, 1, 1, maxAllocSize/2, memSize/2, CL_MEM_OBJECT_IMAGE2D, srcImageInfo.format); + + for( size_t i = 0; i < numberOfSizes2D; i++ ) + for( size_t j = 0; j < numberOfSizes3D; j++ ) + { + size_t rowPadding = gEnablePitch ? 256 : 0; + size_t slicePadding = gEnablePitch ? 3 : 0; + + set_image_dimensions( &dstImageInfo, sizes3D[ j ][ 0 ], sizes3D[ j ][ 1 ], sizes3D[ j ][ 2 ], rowPadding, slicePadding ); + set_image_dimensions( &srcImageInfo, sizes2D[ i ][ 0 ], sizes2D[ i ][ 1 ], 0, rowPadding, slicePadding ); + cl_ulong dstSize = get_image_size(&dstImageInfo); + cl_ulong srcSize = get_image_size(&srcImageInfo); + + if (gTestMipmaps) + { + srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, 0), seed); + srcImageInfo.type = CL_MEM_OBJECT_IMAGE2D; + dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, dstImageInfo.depth), seed); + dstImageInfo.type = CL_MEM_OBJECT_IMAGE3D; + srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format ); + srcImageInfo.slicePitch = 0; + dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format ); + dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height; + dstSize = 4 * compute_mipmapped_image_size( dstImageInfo ); + srcSize = 4 * compute_mipmapped_image_size( srcImageInfo ); + } + + if( dstSize < maxAllocSize && dstSize < ( memSize / 3 ) && srcSize < maxAllocSize && srcSize < ( memSize / 3 ) ) + { + log_info( "Testing %d x %d to %d x %d x %d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.depth ); + if( gDebugTrace ) + log_info( " at max size %d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.depth ); + int ret; + if( reverse ) + ret = test_copy_image_size_2D_3D( device, &dstImageInfo, &srcImageInfo, seed ); + else + ret = test_copy_image_size_2D_3D( device, &srcImageInfo, &dstImageInfo, seed ); + if( ret ) + return -1; + } + else + { + log_info("Not testing max size %d x %d to %d x %d x %d due to memory constraints.\n", + (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.depth); + } + + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong srcSize, dstSize; + size_t rowPadding = gEnablePitch ? 256 : 0; + size_t slicePadding = gEnablePitch ? 3 : 0; + + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + dstImageInfo.width = (size_t)random_log_in_range( 16, (int)max3DWidth / 32, seed ); + dstImageInfo.height = (size_t)random_log_in_range( 16, (int)max3DHeight / 32, seed ); + dstImageInfo.depth = (size_t)random_log_in_range( 16, (int)max3DDepth / 32, seed ); + srcImageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + srcImageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + + if (gTestMipmaps) + { + srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, 0), seed); + srcImageInfo.type = CL_MEM_OBJECT_IMAGE2D; + dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, dstImageInfo.depth), seed); + dstImageInfo.type = CL_MEM_OBJECT_IMAGE3D; + srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format ); + srcImageInfo.slicePitch = 0; + dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format ); + dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height; + srcSize = 4 * compute_mipmapped_image_size( srcImageInfo ); + dstSize = 4 * compute_mipmapped_image_size( dstImageInfo ); + } + else + { + set_image_dimensions( &srcImageInfo, srcImageInfo.width, srcImageInfo.height, 0, rowPadding, slicePadding ); + set_image_dimensions( &dstImageInfo, dstImageInfo.width, dstImageInfo.height, dstImageInfo.depth, rowPadding, slicePadding ); + + srcSize = (cl_ulong)srcImageInfo.rowPitch * (cl_ulong)srcImageInfo.height * 4; + dstSize = (cl_ulong)dstImageInfo.slicePitch * (cl_ulong)dstImageInfo.depth * 4; + } + } while( srcSize > maxAllocSize || ( srcSize * 3 ) > memSize || dstSize > maxAllocSize || ( dstSize * 3 ) > memSize); + + if( gDebugTrace ) + log_info( " at size %d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.depth ); + int ret; + if( reverse ) + ret = test_copy_image_size_2D_3D( device, &dstImageInfo, &srcImageInfo, seed ); + else + ret = test_copy_image_size_2D_3D( device, &srcImageInfo, &dstImageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clCopyImage/test_copy_2D_array.cpp b/test_conformance/images/clCopyImage/test_copy_2D_array.cpp new file mode 100644 index 00000000..0175a8f7 --- /dev/null +++ b/test_conformance/images/clCopyImage/test_copy_2D_array.cpp @@ -0,0 +1,205 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gEnablePitch, gTestRounding, gTestMipmaps; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern cl_command_queue queue; +extern cl_context context; + +// Defined in test_copy_generic.cpp +extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, + const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d ); + +int test_copy_image_2D_array( cl_device_id device, image_descriptor *imageInfo, MTdata d ) +{ + size_t srcPos[] = { 0, 0, 0, 0}, dstPos[] = {0, 0, 0, 0}; + size_t region[] = { imageInfo->width, imageInfo->height, imageInfo->arraySize }; + + size_t src_lod = 0, src_width_lod = imageInfo->width, src_height_lod = imageInfo->height; + size_t dst_lod = 0, dst_width_lod = imageInfo->width, dst_height_lod = imageInfo->height; + size_t width_lod = imageInfo->width, height_lod = imageInfo->height; + size_t max_mip_level; + + if( gTestMipmaps ) + { + max_mip_level = imageInfo->num_mip_levels; + // Work at a random mip level + src_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d ); + dst_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d ); + src_width_lod = ( imageInfo->width >> src_lod )? ( imageInfo->width >> src_lod ) : 1; + dst_width_lod = ( imageInfo->width >> dst_lod )? ( imageInfo->width >> dst_lod ) : 1; + src_height_lod = ( imageInfo->height >> src_lod )? ( imageInfo->height >> src_lod ) : 1; + dst_height_lod = ( imageInfo->height >> dst_lod )? ( imageInfo->height >> dst_lod ) : 1; + width_lod = ( src_width_lod > dst_width_lod ) ? dst_width_lod : src_width_lod; + height_lod = ( src_height_lod > dst_height_lod ) ? dst_height_lod : src_height_lod; + + region[ 0 ] = width_lod; + region[ 1 ] = height_lod; + srcPos[ 3 ] = src_lod; + dstPos[ 3 ] = dst_lod; +} + return test_copy_image_generic( device, imageInfo, imageInfo, srcPos, dstPos, region, d ); +} + +int test_copy_image_set_2D_array( cl_device_id device, cl_image_format *format ) +{ + size_t maxWidth, maxHeight, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + imageInfo.format = format; + imageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D array size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + size_t rowPadding = gEnablePitch ? 80 : 0; + size_t slicePadding = gEnablePitch ? 3 : 0; + + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed); + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding); + + for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ ) + { + if( gDebugTrace ) + log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize ); + int ret = test_copy_image_2D_array( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize, memSize, imageInfo.type, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + size_t rowPadding = gEnablePitch ? 80 : 0; + size_t slicePadding = gEnablePitch ? 3 : 0; + + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.arraySize = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed); + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding); + log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + if( gDebugTrace ) + log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + if( test_copy_image_2D_array( device, &imageInfo, seed ) ) + return -1; + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + size_t rowPadding = gEnablePitch ? 80 : 0; + size_t slicePadding = gEnablePitch ? 3 : 0; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed ); + + if (gTestMipmaps) + { + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed); + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + size = compute_mipmapped_image_size( imageInfo ); + size = size*4; + } + else + { + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding); + + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxArraySize ); + int ret = test_copy_image_2D_array( device, &imageInfo,seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clCopyImage/test_copy_3D.cpp b/test_conformance/images/clCopyImage/test_copy_3D.cpp new file mode 100644 index 00000000..d479589f --- /dev/null +++ b/test_conformance/images/clCopyImage/test_copy_3D.cpp @@ -0,0 +1,192 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gEnablePitch, gTestRounding, gTestMipmaps; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern cl_command_queue queue; +extern cl_context context; + +// Defined in test_copy_generic.cpp +extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, + const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d ); + +int test_copy_image_3D( cl_device_id device, image_descriptor *imageInfo, MTdata d ) +{ + size_t origin[] = { 0, 0, 0, 0}; + size_t region[] = { imageInfo->width, imageInfo->height, imageInfo->depth }; + + if( gTestMipmaps ) + { + size_t lod = (imageInfo->num_mip_levels > 1 )? (size_t)random_in_range( 0, imageInfo->num_mip_levels - 1, d ) : 0 ; + origin[ 3 ] = lod; + region[ 0 ] = ( imageInfo->width >> lod ) ? ( imageInfo->width >> lod ) : 1; + region[ 1 ] = ( imageInfo->height >> lod ) ? ( imageInfo->height >> lod ) : 1; + region[ 2 ] = ( imageInfo->depth >> lod ) ? ( imageInfo->depth >> lod ) : 1; + } + + return test_copy_image_generic( device, imageInfo, imageInfo, origin, origin, region, d ); +} + +int test_copy_image_set_3D( cl_device_id device, cl_image_format *format ) +{ + size_t maxWidth, maxHeight, maxDepth; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + imageInfo.format = format; + imageInfo.type = CL_MEM_OBJECT_IMAGE3D; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 3D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + size_t rowPadding = gEnablePitch ? 80 : 0; + size_t slicePadding = gEnablePitch ? 3 : 0; + + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth), seed); + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding); + for( imageInfo.depth = 2; imageInfo.depth < 9; imageInfo.depth++ ) + { + if( gDebugTrace ) + log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth ); + int ret = test_copy_image_3D( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, maxDepth, 1, maxAllocSize, memSize, imageInfo.type, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + size_t rowPadding = gEnablePitch ? 80 : 0; + size_t slicePadding = gEnablePitch ? 3 : 0; + + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.depth = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth), seed); + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding); + log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + if( gDebugTrace ) + log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + if( test_copy_image_3D( device, &imageInfo, seed ) ) + return -1; + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + size_t rowPadding = gEnablePitch ? 80 : 0; + size_t slicePadding = gEnablePitch ? 3 : 0; + + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + imageInfo.depth = (size_t)random_log_in_range( 16, (int)maxDepth / 32,seed ); + + if (gTestMipmaps) + { + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth), seed); + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + size = compute_mipmapped_image_size( imageInfo ); + size = size*4; + } + else + { + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding); + + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.depth * 4 * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxDepth ); + int ret = test_copy_image_3D( device, &imageInfo,seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clCopyImage/test_copy_3D_2D_array.cpp b/test_conformance/images/clCopyImage/test_copy_3D_2D_array.cpp new file mode 100644 index 00000000..b0b02932 --- /dev/null +++ b/test_conformance/images/clCopyImage/test_copy_3D_2D_array.cpp @@ -0,0 +1,442 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gTestRounding, gEnablePitch, gTestMipmaps; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_command_queue queue; +extern cl_context context; + +extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, + const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d ); + + +static size_t random_in_ranges( size_t minimum, size_t rangeA, size_t rangeB, MTdata d ) +{ + if( rangeB < rangeA ) + rangeA = rangeB; + if( rangeA < minimum ) + return rangeA; + return (size_t)random_in_range( (int)minimum, (int)rangeA - 1, d ); +} + + +static void set_image_dimensions( image_descriptor *imageInfo, size_t width, size_t height, size_t depth, size_t arraySize, size_t rowPadding, size_t slicePadding ) +{ + size_t pixelSize = get_pixel_size( imageInfo->format ); + + imageInfo->width = width; + imageInfo->height = height; + imageInfo->depth = depth; + imageInfo->arraySize = arraySize; + imageInfo->rowPitch = imageInfo->width * pixelSize + rowPadding; + + if (gEnablePitch) + { + do { + rowPadding++; + imageInfo->rowPitch = imageInfo->width * pixelSize + rowPadding; + } while ((imageInfo->rowPitch % pixelSize) != 0); + } + + imageInfo->slicePitch = imageInfo->rowPitch * (imageInfo->height + slicePadding); + + if (arraySize == 0) + imageInfo->type = CL_MEM_OBJECT_IMAGE3D; + else + imageInfo->type = CL_MEM_OBJECT_IMAGE2D_ARRAY; +} + + +int test_copy_image_size_3D_2D_array( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, MTdata d ) +{ + size_t sourcePos[ 4 ], destPos[ 4 ], regionSize[ 3 ]; + int ret = 0, retCode; + + image_descriptor *threeImage, *twoImage; + + if( srcImageInfo->arraySize == 0 ) + { + threeImage = srcImageInfo; + twoImage = dstImageInfo; + } + else + { + threeImage = dstImageInfo; + twoImage = srcImageInfo; + } + + size_t twoImage_width_lod = twoImage->width, twoImage_height_lod = twoImage->height; + size_t threeImage_width_lod = threeImage->width, threeImage_height_lod = threeImage->height; + size_t twoImage_lod = 0, threeImage_lod = 0; + size_t width_lod = 0, height_lod = 0, depth_lod = 0; + size_t twoImage_max_mip_level,threeImage_max_mip_level; + + if( gTestMipmaps ) + { + twoImage_max_mip_level = twoImage->num_mip_levels; + threeImage_max_mip_level = threeImage->num_mip_levels; + // Work at random mip levels + twoImage_lod = (size_t)random_in_range( 0, twoImage_max_mip_level ? twoImage_max_mip_level - 1 : 0, d ); + threeImage_lod = (size_t)random_in_range( 0, threeImage_max_mip_level ? threeImage_max_mip_level - 1 : 0, d ); + twoImage_width_lod = ( twoImage->width >> twoImage_lod )? ( twoImage->width >> twoImage_lod ) : 1; + threeImage_width_lod = ( threeImage->width >> threeImage_lod )? ( threeImage->width >> threeImage_lod ) : 1; + twoImage_height_lod = ( twoImage->height >> twoImage_lod )? ( twoImage->height >> twoImage_lod ) : 1; + threeImage_height_lod = ( threeImage->height >> threeImage_lod )? ( threeImage->height >> threeImage_lod ) : 1; + depth_lod = ( threeImage->depth >> threeImage_lod )? ( threeImage->depth >> threeImage_lod ) : 1; + } + width_lod = ( twoImage_width_lod > threeImage_width_lod ) ? threeImage_width_lod : twoImage_width_lod; + height_lod = ( twoImage_height_lod > threeImage_height_lod ) ? threeImage_height_lod : twoImage_height_lod; + depth_lod = ( depth_lod > twoImage->arraySize ) ? twoImage->arraySize : depth_lod; + + // First, try just a full covering region + sourcePos[ 0 ] = sourcePos[ 1 ] = sourcePos[ 2 ] = 0; + destPos[ 0 ] = destPos[ 1 ] = destPos[ 2 ] = 0; + regionSize[ 0 ] = ( threeImage->width < twoImage->width ) ? threeImage->width : twoImage->width; + regionSize[ 1 ] = ( threeImage->height < twoImage->height ) ? threeImage->height : twoImage->height; + regionSize[ 2 ] = 1; + + if( srcImageInfo->type == CL_MEM_OBJECT_IMAGE3D ) + { + // 3D to 2D array + sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)srcImageInfo->depth - 1, d ); + destPos[ 2 ] = (size_t)random_in_range( 0, (int)dstImageInfo->arraySize - 1, d ); + if(gTestMipmaps) + { + sourcePos[ 2 ] = 0/*(size_t)random_in_range( 0, (int)depth_lod - 1, d )*/; + destPos[ 2 ] = ( twoImage->arraySize > depth_lod ) ? (size_t)random_in_range( 0, twoImage->arraySize - depth_lod, d) : 0; + sourcePos[ 3 ] = threeImage_lod; + destPos[ 3 ] = twoImage_lod; + regionSize[ 0 ] = width_lod; + regionSize[ 1 ] = height_lod; + regionSize[ 2 ] = depth_lod; + } + } + else + { + // 2D array to 3D + sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)srcImageInfo->arraySize - 1, d ); + destPos[ 2 ] = (size_t)random_in_range( 0, (int)dstImageInfo->depth - 1, d ); + if(gTestMipmaps) + { + destPos[ 2 ] = 0 /*(size_t)random_in_range( 0, (int)depth_lod - 1, d )*/; + sourcePos[ 2 ] = ( twoImage->arraySize > depth_lod ) ? (size_t)random_in_range( 0, twoImage->arraySize - depth_lod, d) : 0; + sourcePos[ 3 ] = twoImage_lod; + destPos[ 3 ] = threeImage_lod; + regionSize[ 0 ] = width_lod; + regionSize[ 1 ] = height_lod; + regionSize[ 2 ] = depth_lod; + } + } + + retCode = test_copy_image_generic( device, srcImageInfo, dstImageInfo, sourcePos, destPos, regionSize, d ); + if( retCode < 0 ) + return retCode; + else + ret += retCode; + + // Now try a sampling of different random regions + for( int i = 0; i < 8; i++ ) + { + if( gTestMipmaps ) + { + twoImage_max_mip_level = twoImage->num_mip_levels; + threeImage_max_mip_level = threeImage->num_mip_levels; + // Work at random mip levels + twoImage_lod = (size_t)random_in_range( 0, twoImage_max_mip_level ? twoImage_max_mip_level - 1 : 0, d ); + threeImage_lod = (size_t)random_in_range( 0, threeImage_max_mip_level ? threeImage_max_mip_level - 1 : 0, d ); + twoImage_width_lod = ( twoImage->width >> twoImage_lod )? ( twoImage->width >> twoImage_lod ) : 1; + threeImage_width_lod = ( threeImage->width >> threeImage_lod )? ( threeImage->width >> threeImage_lod ) : 1; + twoImage_height_lod = ( twoImage->height >> twoImage_lod )? ( twoImage->height >> twoImage_lod ) : 1; + threeImage_height_lod = ( threeImage->height >> threeImage_lod )? ( threeImage->height >> threeImage_lod ) : 1; + depth_lod = ( threeImage->depth >> threeImage_lod )? ( threeImage->depth >> threeImage_lod ) : 1; + width_lod = ( twoImage_width_lod > threeImage_width_lod ) ? threeImage_width_lod : twoImage_width_lod; + height_lod = ( twoImage_height_lod > threeImage_height_lod ) ? threeImage_height_lod : twoImage_height_lod; + depth_lod = ( twoImage->arraySize > depth_lod ) ? depth_lod : twoImage->arraySize; + } + // Pick a random size + regionSize[ 0 ] = random_in_ranges( 8, srcImageInfo->width, dstImageInfo->width, d ); + regionSize[ 1 ] = random_in_ranges( 8, srcImageInfo->height, dstImageInfo->height, d ); + if( gTestMipmaps ) + { + regionSize[ 0 ] = random_in_range( 1, width_lod, d ); + regionSize[ 1 ] = random_in_range( 1, height_lod, d ); + regionSize[ 2 ] = depth_lod/*random_in_range( 0, depth_lod, d )*/; + } + + // Now pick positions within valid ranges + sourcePos[ 0 ] = ( srcImageInfo->width > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->width - regionSize[ 0 ] - 1 ), d ) : 0; + sourcePos[ 1 ] = ( srcImageInfo->height > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->height - regionSize[ 1 ] - 1 ), d ) : 0; + + if (srcImageInfo->type == CL_MEM_OBJECT_IMAGE3D) + { + sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)( srcImageInfo->depth - 1 ), d ); + if(gTestMipmaps) + { + sourcePos[ 0 ] = ( threeImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + sourcePos[ 1 ] = ( threeImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0; + sourcePos[ 2 ] = 0 /*( depth_lod > regionSize[ 2 ] ) ? (size_t)random_in_range( 0, (int)( depth_lod - regionSize[ 2 ] - 1 ), d ) : 0*/; + sourcePos[ 3 ] = threeImage_lod; + } + } + else + { + sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)( srcImageInfo->arraySize - 1 ), d ); + if(gTestMipmaps) + { + sourcePos[ 0 ] = ( twoImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + sourcePos[ 1 ] = ( twoImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0; + sourcePos[ 2 ] = ( twoImage->arraySize > regionSize[ 2 ] ) ? (size_t)random_in_range( 0, (int)( twoImage->arraySize - regionSize[ 2 ] - 1 ), d ) : 0; + sourcePos[ 3 ] = twoImage_lod; + } + } + + destPos[ 0 ] = ( dstImageInfo->width > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->width - regionSize[ 0 ] - 1 ), d ) : 0; + destPos[ 1 ] = ( dstImageInfo->height > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->height - regionSize[ 1 ] - 1 ), d ) : 0; + if (dstImageInfo->type == CL_MEM_OBJECT_IMAGE3D) + { + destPos[ 2 ] = (size_t)random_in_range( 0, (int)( dstImageInfo->depth - 1 ), d ); + if(gTestMipmaps) + { + destPos[ 0 ] = ( threeImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + destPos[ 1 ] = ( threeImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0; + destPos[ 2 ] = 0/*( depth_lod > regionSize[ 2 ] ) ? (size_t)random_in_range( 0, (int)( depth_lod - regionSize[ 2 ] - 1 ), d ) : 0*/; + destPos[ 3 ] = threeImage_lod; + } + } + else + { + destPos[ 2 ] = (size_t)random_in_range( 0, (int)( dstImageInfo->arraySize - 1 ), d ); + if(gTestMipmaps) + { + destPos[ 0 ] = ( twoImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0; + destPos[ 1 ] = ( twoImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0; + destPos[ 2 ] = ( twoImage->arraySize > regionSize[ 2 ] ) ? (size_t)random_in_range( 0, (int)( twoImage->arraySize - regionSize[ 2 ] - 1 ), d ) : 0; + destPos[ 3 ] = twoImage_lod; + } + } + + + // Go for it! + retCode = test_copy_image_generic( device, srcImageInfo, dstImageInfo, sourcePos, destPos, regionSize, d ); + if( retCode < 0 ) + return retCode; + else + ret += retCode; + } + + return ret; +} + + +int test_copy_image_set_3D_2D_array( cl_device_id device, cl_image_format *format, bool reverse = false ) +{ + size_t maxWidth, maxHeight, max3DWidth, max3DHeight, maxDepth, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor srcImageInfo = { 0 }; + image_descriptor dstImageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t rowPadding = gEnablePitch ? 256 : 0; + size_t slicePadding = gEnablePitch ? 3 : 0; + + srcImageInfo.format = dstImageInfo.format = format; + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( max3DWidth ), &max3DWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( max3DHeight ), &max3DHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D image array or 3D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( dstImageInfo.width = 4; dstImageInfo.width < 17; dstImageInfo.width++ ) + { + for( dstImageInfo.height = 4; dstImageInfo.height < 13; dstImageInfo.height++ ) + { + for( dstImageInfo.arraySize = 4; dstImageInfo.arraySize < 9; dstImageInfo.arraySize++ ) + { + set_image_dimensions( &dstImageInfo, dstImageInfo.width, dstImageInfo.height, 0, dstImageInfo.arraySize, rowPadding, slicePadding ); + set_image_dimensions( &srcImageInfo, dstImageInfo.width, dstImageInfo.height, dstImageInfo.arraySize, 0, rowPadding, slicePadding ); + + if (gTestMipmaps) + { + dstImageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, 0), seed); + srcImageInfo.type = CL_MEM_OBJECT_IMAGE3D; + srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, srcImageInfo.depth), seed); + srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format ); + srcImageInfo.slicePitch = srcImageInfo.rowPitch * srcImageInfo.height; + dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format ); + dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height; + } + + if( gDebugTrace ) + { + if (reverse) + log_info( " at size %d,%d,%d to %d,%d,%d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth ); + else + log_info( " at size %d,%d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize ); + } + int ret; + if( reverse ) + ret = test_copy_image_size_3D_2D_array( device, &dstImageInfo, &srcImageInfo, seed ); + else + ret = test_copy_image_size_3D_2D_array( device, &srcImageInfo, &dstImageInfo, seed ); + if( ret ) + return -1; + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes3D[100][3]; + size_t sizes2Darray[100][3]; + + // Try to allocate a bit smaller images because we need the 3D ones as well for the copy. + get_max_sizes(&numbeOfSizes, 100, sizes2Darray, maxWidth, maxHeight, maxDepth, maxArraySize, maxAllocSize/2, memSize/2, CL_MEM_OBJECT_IMAGE3D, srcImageInfo.format); + get_max_sizes(&numbeOfSizes, 100, sizes3D, max3DWidth, max3DHeight, maxDepth, maxArraySize, maxAllocSize/2, memSize/2, CL_MEM_OBJECT_IMAGE3D, dstImageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + set_image_dimensions( &srcImageInfo, sizes3D[ idx ][ 0 ], sizes3D[ idx ][ 1 ], sizes3D[ idx ][ 2 ], 0, rowPadding, slicePadding ); + set_image_dimensions( &dstImageInfo, sizes2Darray[ idx ][ 0 ], sizes2Darray[ idx ][ 1 ], 0, sizes2Darray[ idx ][ 2 ], rowPadding, slicePadding ); + + cl_ulong dstSize = (cl_ulong)dstImageInfo.slicePitch * (cl_ulong)dstImageInfo.arraySize; + cl_ulong srcSize = (cl_ulong)srcImageInfo.slicePitch * (cl_ulong)srcImageInfo.depth; + + if (gTestMipmaps) + { + dstImageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, 0), seed); + srcImageInfo.type = CL_MEM_OBJECT_IMAGE3D; + srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, srcImageInfo.depth), seed); + srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format ); + srcImageInfo.slicePitch = srcImageInfo.rowPitch * srcImageInfo.height; + dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format ); + dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height; + srcSize = 4 * compute_mipmapped_image_size( srcImageInfo ); + dstSize = 4 * compute_mipmapped_image_size( dstImageInfo ); + } + + if ( ( dstSize < maxAllocSize && dstSize < ( memSize / 3 ) ) && + ( srcSize < maxAllocSize && srcSize < ( memSize / 3 ) ) ) + { + if (reverse) + log_info( "Testing %d x %d x %d to %d x %d x %d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth ); + else + log_info( "Testing %d x %d x %d to %d x %d x %d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize ); + + if( gDebugTrace ) + { + if (reverse) + log_info( " at max size %d,%d,%d to %d,%d,%d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth ); + else + log_info( " at max size %d,%d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize ); + } + int ret; + if( reverse ) + ret = test_copy_image_size_3D_2D_array( device, &dstImageInfo, &srcImageInfo, seed ); + else + ret = test_copy_image_size_3D_2D_array( device, &srcImageInfo, &dstImageInfo, seed ); + if( ret ) + return -1; + } + else + { + if (reverse) + log_info("Not testing max size %d x %d x %d x %d to %d x %d due to memory constraints.\n", + (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth); + else + log_info("Not testing max size %d x %d x %d to %d x %d x %d due to memory constraints.\n", + (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize); + } + + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong srcSize, dstSize; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + dstImageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + dstImageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + dstImageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed ); + srcImageInfo.width = (size_t)random_log_in_range( 16, (int)max3DWidth / 32, seed ); + srcImageInfo.height = (size_t)random_log_in_range( 16, (int)max3DHeight / 32, seed ); + srcImageInfo.depth = (size_t)random_log_in_range( 16, (int)maxDepth / 32, seed ); + + if (gTestMipmaps) + { + dstImageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, 0), seed); + srcImageInfo.type = CL_MEM_OBJECT_IMAGE3D; + srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, srcImageInfo.depth), seed); + srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format ); + srcImageInfo.slicePitch = srcImageInfo.rowPitch * srcImageInfo.height; + dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format ); + dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height; + srcSize = 4 * compute_mipmapped_image_size( srcImageInfo ); + dstSize = 4 * compute_mipmapped_image_size( dstImageInfo ); + } + else + { + set_image_dimensions( &srcImageInfo, srcImageInfo.width, srcImageInfo.height, srcImageInfo.depth, 0, rowPadding, slicePadding ); + set_image_dimensions( &dstImageInfo, dstImageInfo.width, dstImageInfo.height, 0, dstImageInfo.arraySize, rowPadding, slicePadding ); + + srcSize = (cl_ulong)srcImageInfo.slicePitch * (cl_ulong)srcImageInfo.depth * 4; + dstSize = (cl_ulong)dstImageInfo.slicePitch * (cl_ulong)dstImageInfo.arraySize * 4; + } + } while( srcSize > maxAllocSize || ( srcSize * 3 ) > memSize || dstSize > maxAllocSize || ( dstSize * 3 ) > memSize); + + if( gDebugTrace ) + { + if (reverse) + log_info( " at size %d,%d,%d to %d,%d,%d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth ); + else + log_info( " at size %d,%d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize ); + } + int ret; + if( reverse ) + ret = test_copy_image_size_3D_2D_array( device, &dstImageInfo, &srcImageInfo, seed ); + else + ret = test_copy_image_size_3D_2D_array( device, &srcImageInfo, &dstImageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clCopyImage/test_copy_generic.cpp b/test_conformance/images/clCopyImage/test_copy_generic.cpp new file mode 100644 index 00000000..ed111bcd --- /dev/null +++ b/test_conformance/images/clCopyImage/test_copy_generic.cpp @@ -0,0 +1,763 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gTestRounding, gEnablePitch, gTestMipmaps; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_command_queue queue; +extern cl_context context; + +size_t random_in_ranges( size_t minimum, size_t rangeA, size_t rangeB, MTdata d ) +{ + if( rangeB < rangeA ) + rangeA = rangeB; + if( rangeA < minimum ) + return rangeA; + return (size_t)random_in_range( (int)minimum, (int)rangeA - 1, d ); +} + +static void CL_CALLBACK free_pitch_buffer( cl_mem image, void *buf ) +{ + free( buf ); +} + +cl_mem create_image( cl_context context, BufferOwningPtr& data, image_descriptor *imageInfo, int *error ) +{ + cl_mem img; + cl_image_desc imageDesc; + cl_mem_flags mem_flags = CL_MEM_READ_ONLY; + void *host_ptr = NULL; + + memset(&imageDesc, 0x0, sizeof(cl_image_desc)); + imageDesc.image_type = imageInfo->type; + imageDesc.image_width = imageInfo->width; + imageDesc.image_height = imageInfo->height; + imageDesc.image_depth = imageInfo->depth; + imageDesc.image_array_size = imageInfo->arraySize; + imageDesc.image_row_pitch = gEnablePitch ? imageInfo->rowPitch : 0; + imageDesc.image_slice_pitch = gEnablePitch ? imageInfo->slicePitch : 0; + imageDesc.num_mip_levels = gTestMipmaps ? imageInfo->num_mip_levels : 0; + + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + if ( gDebugTrace ) + log_info( " - Creating 1D image %d ...\n", (int)imageInfo->width ); + if ( gEnablePitch ) + host_ptr = malloc( imageInfo->rowPitch ); + break; + case CL_MEM_OBJECT_IMAGE2D: + if ( gDebugTrace ) + log_info( " - Creating 2D image %d by %d ...\n", (int)imageInfo->width, (int)imageInfo->height ); + if ( gEnablePitch ) + host_ptr = malloc( imageInfo->height * imageInfo->rowPitch ); + break; + case CL_MEM_OBJECT_IMAGE3D: + if ( gDebugTrace ) + log_info( " - Creating 3D image %d by %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth ); + if ( gEnablePitch ) + host_ptr = malloc( imageInfo->depth * imageInfo->slicePitch ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + if ( gDebugTrace ) + log_info( " - Creating 1D image array %d by %d...\n", (int)imageInfo->width, (int)imageInfo->arraySize ); + if ( gEnablePitch ) + host_ptr = malloc( imageInfo->arraySize * imageInfo->slicePitch ); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + if ( gDebugTrace ) + log_info( " - Creating 2D image array %d by %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize ); + if ( gEnablePitch ) + host_ptr = malloc( imageInfo->arraySize * imageInfo->slicePitch ); + break; + } + + if ( gDebugTrace && gTestMipmaps ) + log_info(" - with %llu mip levels\n", (unsigned long long) imageInfo->num_mip_levels); + + if (gEnablePitch) + { + if ( NULL == host_ptr ) + { + log_error( "ERROR: Unable to create backing store for pitched 3D image. %ld bytes\n", imageInfo->depth * imageInfo->slicePitch ); + return NULL; + } + mem_flags = CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR; + } + + img = clCreateImage(context, mem_flags, imageInfo->format, &imageDesc, host_ptr, error); + + if (gEnablePitch) + { + if ( *error == CL_SUCCESS ) + { + int callbackError = clSetMemObjectDestructorCallback( img, free_pitch_buffer, host_ptr ); + if ( CL_SUCCESS != callbackError ) + { + free( host_ptr ); + log_error( "ERROR: Unable to attach destructor callback to pitched 3D image. Err: %d\n", callbackError ); + clReleaseMemObject( img ); + return NULL; + } + } + else + free(host_ptr); + } + + if ( *error != CL_SUCCESS ) + { + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + log_error( "ERROR: Unable to create 1D image of size %d (%s)", (int)imageInfo->width, IGetErrorString( *error ) ); + break; + case CL_MEM_OBJECT_IMAGE2D: + log_error( "ERROR: Unable to create 2D image of size %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, IGetErrorString( *error ) ); + break; + case CL_MEM_OBJECT_IMAGE3D: + log_error( "ERROR: Unable to create 3D image of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, IGetErrorString( *error ) ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + log_error( "ERROR: Unable to create 1D image array of size %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->arraySize, IGetErrorString( *error ) ); + break; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + log_error( "ERROR: Unable to create 2D image array of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, IGetErrorString( *error ) ); + break; + } + log_error("ERROR: and %llu mip levels\n", (unsigned long long) imageInfo->num_mip_levels); + return NULL; + } + + // Copy the specified data to the image via a Map operation. + size_t mappedRow, mappedSlice; + size_t width = imageInfo->width; + size_t height = 1; + size_t depth = 1; + size_t row_pitch_lod, slice_pitch_lod; + row_pitch_lod = imageInfo->rowPitch; + slice_pitch_lod = imageInfo->slicePitch; + + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + height = imageInfo->arraySize; + depth = 1; + break; + case CL_MEM_OBJECT_IMAGE1D: + height = depth = 1; + break; + case CL_MEM_OBJECT_IMAGE2D: + height = imageInfo->height; + depth = 1; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + height = imageInfo->height; + depth = imageInfo->arraySize; + break; + case CL_MEM_OBJECT_IMAGE3D: + height = imageInfo->height; + depth = imageInfo->depth; + break; + } + + size_t origin[ 4 ] = { 0, 0, 0, 0 }; + size_t region[ 3 ] = { imageInfo->width, height, depth }; + + for ( size_t lod = 0; (gTestMipmaps && (lod < imageInfo->num_mip_levels)) || (!gTestMipmaps && (lod < 1)); lod++) + { + // Map the appropriate miplevel to copy the specified data. + if(gTestMipmaps) + { + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE3D: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + origin[ 3 ] = lod; + break; + case CL_MEM_OBJECT_IMAGE2D: + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + origin[ 2 ] = lod; + break; + case CL_MEM_OBJECT_IMAGE1D: + origin[ 1 ] = lod; + break; + } + + //Adjust image dimensions as per miplevel + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE3D: + depth = ( imageInfo->depth >> lod ) ? (imageInfo->depth >> lod) : 1; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + case CL_MEM_OBJECT_IMAGE2D: + height = ( imageInfo->height >> lod ) ? (imageInfo->height >> lod) : 1; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE1D: + width = ( imageInfo->width >> lod ) ? (imageInfo->width >> lod) : 1; + } + row_pitch_lod = width * get_pixel_size(imageInfo->format); + slice_pitch_lod = row_pitch_lod * height; + region[0] = width; + region[1] = height; + region[2] = depth; + } + + void* mapped = (char*)clEnqueueMapImage(queue, img, CL_TRUE, CL_MAP_WRITE, origin, region, &mappedRow, &mappedSlice, 0, NULL, NULL, error); + if (*error != CL_SUCCESS) + { + log_error( "ERROR: Unable to map image for writing: %s\n", IGetErrorString( *error ) ); + return NULL; + } + size_t mappedSlicePad = mappedSlice - (mappedRow * height); + + // Copy the image. + size_t scanlineSize = row_pitch_lod; + size_t sliceSize = slice_pitch_lod - scanlineSize * height; + size_t imageSize = scanlineSize * height * depth; + size_t data_lod_offset = 0; + if( gTestMipmaps ) + data_lod_offset = compute_mip_level_offset(imageInfo, lod); + + char* src = (char*)data + data_lod_offset; + char* dst = (char*)mapped; + + if ((mappedRow == scanlineSize) && (mappedSlicePad==0 || (imageInfo->depth==0 && imageInfo->arraySize==0))) { + // Copy the whole image. + memcpy( dst, src, imageSize ); + } + else { + // Else copy one scan line at a time. + size_t dstPitch2D = 0; + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE3D: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + case CL_MEM_OBJECT_IMAGE2D: + dstPitch2D = mappedRow; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE1D: + dstPitch2D = mappedSlice; + break; + } + for ( size_t z = 0; z < depth; z++ ) + { + for ( size_t y = 0; y < height; y++ ) + { + memcpy( dst, src, scanlineSize ); + dst += dstPitch2D; + src += scanlineSize; + } + + // mappedSlicePad is incorrect for 2D images here, but we will exit the z loop before this is a problem. + dst += mappedSlicePad; + src += sliceSize; + } + } + + // Unmap the image. + *error = clEnqueueUnmapMemObject(queue, img, mapped, 0, NULL, NULL); + if (*error != CL_SUCCESS) + { + log_error( "ERROR: Unable to unmap image after writing: %s\n", IGetErrorString( *error ) ); + return NULL; + } + } + return img; +} + + +// WARNING -- not thread safe +BufferOwningPtr srcData; +BufferOwningPtr dstData; +BufferOwningPtr srcHost; +BufferOwningPtr dstHost; + +int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, + const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d ) +{ + int error; + + clMemWrapper srcImage, dstImage; + + if( gDebugTrace ) + log_info( " ++ Entering inner test loop...\n" ); + + // Generate some data to test against + size_t srcBytes = 0; + if( gTestMipmaps ) + { + srcBytes = (size_t)compute_mipmapped_image_size( *srcImageInfo ); + } + else + { + switch (srcImageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + srcBytes = srcImageInfo->rowPitch; + break; + case CL_MEM_OBJECT_IMAGE2D: + srcBytes = srcImageInfo->height * srcImageInfo->rowPitch; + break; + case CL_MEM_OBJECT_IMAGE3D: + srcBytes = srcImageInfo->depth * srcImageInfo->slicePitch; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + srcBytes = srcImageInfo->arraySize * srcImageInfo->slicePitch; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + srcBytes = srcImageInfo->arraySize * srcImageInfo->slicePitch; + break; + } + } + + if (srcBytes > srcData.getSize()) + { + if( gDebugTrace ) + log_info( " - Resizing random image data...\n" ); + + generate_random_image_data( srcImageInfo, srcData, d ); + + // Update the host verification copy of the data. + srcHost.reset(malloc(srcBytes),NULL,0,srcBytes); + if (srcHost == NULL) { + log_error( "ERROR: Unable to malloc %lu bytes for srcHost\n", srcBytes ); + return -1; + } + memcpy(srcHost,srcData,srcBytes); + } + + // Construct testing sources + if( gDebugTrace ) + log_info( " - Writing source image...\n" ); + + srcImage = create_image( context, srcData, srcImageInfo, &error ); + if( srcImage == NULL ) + return error; + + + // Initialize the destination to empty + size_t destImageSize = 0; + if( gTestMipmaps ) + { + destImageSize = (size_t)compute_mipmapped_image_size( *dstImageInfo ); + } + else + { + switch (dstImageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + destImageSize = dstImageInfo->rowPitch; + break; + case CL_MEM_OBJECT_IMAGE2D: + destImageSize = dstImageInfo->height * dstImageInfo->rowPitch; + break; + case CL_MEM_OBJECT_IMAGE3D: + destImageSize = dstImageInfo->depth * dstImageInfo->slicePitch; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + destImageSize = dstImageInfo->arraySize * dstImageInfo->slicePitch; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + destImageSize = dstImageInfo->arraySize * dstImageInfo->slicePitch; + break; + } + } + + if (destImageSize > dstData.getSize()) + { + if( gDebugTrace ) + log_info( " - Resizing destination buffer...\n" ); + dstData.reset(malloc(destImageSize),NULL,0,destImageSize); + if (dstData == NULL) { + log_error( "ERROR: Unable to malloc %lu bytes for dstData\n", destImageSize ); + return -1; + } + + dstHost.reset(malloc(destImageSize),NULL,0,destImageSize); + if (dstHost == NULL) { + dstData.reset(NULL); + log_error( "ERROR: Unable to malloc %lu bytes for dstHost\n", destImageSize ); + return -1; + } + } + memset( dstData, 0xff, destImageSize ); + memset( dstHost, 0xff, destImageSize ); + + if( gDebugTrace ) + log_info( " - Writing destination image...\n" ); + + dstImage = create_image( context, dstData, dstImageInfo, &error ); + if( dstImage == NULL ) + return error; + + size_t dstRegion[ 3 ] = { dstImageInfo->width, 1, 1}; + size_t dst_lod = 0; + size_t origin[ 4 ] = { 0, 0, 0, 0 }; + + if(gTestMipmaps) + { + switch(dstImageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + dst_lod = destPos[1]; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE2D: + dst_lod = destPos[2]; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + case CL_MEM_OBJECT_IMAGE3D: + dst_lod = destPos[3]; + break; + } + + dstRegion[ 0 ] = (dstImageInfo->width >> dst_lod)?(dstImageInfo->width >> dst_lod) : 1; + } + switch (dstImageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + if( gTestMipmaps ) + origin[ 1 ] = dst_lod; + break; + case CL_MEM_OBJECT_IMAGE2D: + dstRegion[ 1 ] = dstImageInfo->height; + if( gTestMipmaps ) + { + dstRegion[ 1 ] = (dstImageInfo->height >> dst_lod) ?(dstImageInfo->height >> dst_lod): 1; + origin[ 2 ] = dst_lod; + } + break; + case CL_MEM_OBJECT_IMAGE3D: + dstRegion[ 1 ] = dstImageInfo->height; + dstRegion[ 2 ] = dstImageInfo->depth; + if( gTestMipmaps ) + { + dstRegion[ 1 ] = (dstImageInfo->height >> dst_lod) ?(dstImageInfo->height >> dst_lod): 1; + dstRegion[ 2 ] = (dstImageInfo->depth >> dst_lod) ?(dstImageInfo->depth >> dst_lod): 1; + origin[ 3 ] = dst_lod; + } + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + dstRegion[ 1 ] = dstImageInfo->arraySize; + if( gTestMipmaps ) + origin[ 2 ] = dst_lod; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + dstRegion[ 1 ] = dstImageInfo->height; + dstRegion[ 2 ] = dstImageInfo->arraySize; + if( gTestMipmaps ) + { + dstRegion[ 1 ] = (dstImageInfo->height >> dst_lod) ?(dstImageInfo->height >> dst_lod): 1; + origin[ 3 ] = dst_lod; + } + break; + } + + size_t region[ 3 ] = { dstRegion[ 0 ], dstRegion[ 1 ], dstRegion[ 2 ] }; + + // Now copy a subset to the destination image. This is the meat of what we're testing + if( gDebugTrace ) + { + if( gTestMipmaps ) + { + log_info( " - Copying from %d,%d,%d,%d to %d,%d,%d,%d size %d,%d,%d\n", (int)sourcePos[ 0 ], (int)sourcePos[ 1 ], (int)sourcePos[ 2 ],(int)sourcePos[ 3 ], + (int)destPos[ 0 ], (int)destPos[ 1 ], (int)destPos[ 2 ],(int)destPos[ 3 ], + (int)regionSize[ 0 ], (int)regionSize[ 1 ], (int)regionSize[ 2 ] ); + } + else + { + log_info( " - Copying from %d,%d,%d to %d,%d,%d size %d,%d,%d\n", (int)sourcePos[ 0 ], (int)sourcePos[ 1 ], (int)sourcePos[ 2 ], + (int)destPos[ 0 ], (int)destPos[ 1 ], (int)destPos[ 2 ], + (int)regionSize[ 0 ], (int)regionSize[ 1 ], (int)regionSize[ 2 ] ); + } + } + + error = clEnqueueCopyImage( queue, srcImage, dstImage, sourcePos, destPos, regionSize, 0, NULL, NULL ); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to copy image from pos %d,%d,%d to %d,%d,%d size %d,%d,%d! (%s)\n", + (int)sourcePos[ 0 ], (int)sourcePos[ 1 ], (int)sourcePos[ 2 ], (int)destPos[ 0 ], (int)destPos[ 1 ], (int)destPos[ 2 ], + (int)regionSize[ 0 ], (int)regionSize[ 1 ], (int)regionSize[ 2 ], IGetErrorString( error ) ); + return error; + } + + // Construct the final dest image values to test against + if( gDebugTrace ) + log_info( " - Host verification copy...\n" ); + + copy_image_data( srcImageInfo, dstImageInfo, srcHost, dstHost, sourcePos, destPos, regionSize ); + + // Map the destination image to verify the results with the host + // copy. The contents of the entire buffer are compared. + if( gDebugTrace ) + log_info( " - Mapping results...\n" ); + + size_t mappedRow, mappedSlice; + void* mapped = (char*)clEnqueueMapImage(queue, dstImage, CL_TRUE, CL_MAP_READ, origin, region, &mappedRow, &mappedSlice, 0, NULL, NULL, &error); + if (error != CL_SUCCESS) + { + log_error( "ERROR: Unable to map image for verification: %s\n", IGetErrorString( error ) ); + return error; + } + + // Verify scanline by scanline, since the pitches are different + char *sourcePtr = dstHost; + size_t cur_lod_offset = 0; + char *destPtr = (char*)mapped; + + if( gTestMipmaps ) + { + cur_lod_offset = compute_mip_level_offset(dstImageInfo, dst_lod); + sourcePtr += cur_lod_offset; + } + + size_t scanlineSize = dstImageInfo->width * get_pixel_size( dstImageInfo->format ); + size_t rowPitch = dstImageInfo->rowPitch; + size_t slicePitch = dstImageInfo->slicePitch; + size_t dst_height_lod = dstImageInfo->height; + if(gTestMipmaps) + { + size_t dst_width_lod = (dstImageInfo->width >> dst_lod)?(dstImageInfo->width >> dst_lod) : 1; + dst_height_lod = (dstImageInfo->height >> dst_lod)?(dstImageInfo->height >> dst_lod) : 1; + scanlineSize = dst_width_lod * get_pixel_size(dstImageInfo->format); + rowPitch = scanlineSize; + slicePitch = rowPitch * dst_height_lod; + } + + if( gDebugTrace ) + log_info( " - Scanline verification...\n" ); + + size_t thirdDim; + size_t secondDim; + if (dstImageInfo->type == CL_MEM_OBJECT_IMAGE1D_ARRAY) + { + secondDim = dstImageInfo->arraySize; + thirdDim = 1; + } + else if (dstImageInfo->type == CL_MEM_OBJECT_IMAGE2D_ARRAY) + { + secondDim = dstImageInfo->height; + if( gTestMipmaps ) + secondDim = (dstImageInfo->height >> dst_lod) ? (dstImageInfo->height >> dst_lod):1; + thirdDim = dstImageInfo->arraySize; + } + else + { + secondDim = dstImageInfo->height; + thirdDim = dstImageInfo->depth; + if( gTestMipmaps ) + { + secondDim = (dstImageInfo->height >> dst_lod) ? (dstImageInfo->height >> dst_lod):1; + if(dstImageInfo->type == CL_MEM_OBJECT_IMAGE3D) + thirdDim = (dstImageInfo->depth >> dst_lod) ? (dstImageInfo->depth >> dst_lod):1; + } + } + + for( size_t z = 0; z < thirdDim; z++ ) + { + for( size_t y = 0; y < secondDim; y++ ) + { + if( memcmp( sourcePtr, destPtr, scanlineSize ) != 0 ) + { + log_error( "ERROR: Scanline %d did not verify for image size %d,%d,%d pitch %d (extra %d bytes)\n", (int)y, (int)dstImageInfo->width, (int)dstImageInfo->height, (int)dstImageInfo->depth, (int)dstImageInfo->rowPitch, (int)dstImageInfo->rowPitch - (int)dstImageInfo->width * (int)get_pixel_size( dstImageInfo->format ) ); + + // Find the first missing pixel + size_t pixel_size = get_pixel_size( dstImageInfo->format ); + size_t where = 0; + for( where = 0; where < dstImageInfo->width; where++ ) + if( memcmp( sourcePtr + pixel_size * where, destPtr + pixel_size * where, pixel_size) ) + break; + log_error( "Failed at column: %ld ", where ); + switch( pixel_size ) + { + case 1: + log_error( "*0x%2.2x vs. 0x%2.2x\n", ((cl_uchar*)(sourcePtr + pixel_size * where))[0], ((cl_uchar*)(destPtr + pixel_size * where))[0] ); + break; + case 2: + log_error( "*0x%4.4x vs. 0x%4.4x\n", ((cl_ushort*)(sourcePtr + pixel_size * where))[0], ((cl_ushort*)(destPtr + pixel_size * where))[0] ); + break; + case 3: + log_error( "*{0x%2.2x, 0x%2.2x, 0x%2.2x} vs. {0x%2.2x, 0x%2.2x, 0x%2.2x}\n", + ((cl_uchar*)(sourcePtr + pixel_size * where))[0], ((cl_uchar*)(sourcePtr + pixel_size * where))[1], ((cl_uchar*)(sourcePtr + pixel_size * where))[2], + ((cl_uchar*)(destPtr + pixel_size * where))[0], ((cl_uchar*)(destPtr + pixel_size * where))[1], ((cl_uchar*)(destPtr + pixel_size * where))[2] + ); + break; + case 4: + log_error( "*0x%8.8x vs. 0x%8.8x\n", ((cl_uint*)(sourcePtr + pixel_size * where))[0], ((cl_uint*)(destPtr + pixel_size * where))[0] ); + break; + case 6: + log_error( "*{0x%4.4x, 0x%4.4x, 0x%4.4x} vs. {0x%4.4x, 0x%4.4x, 0x%4.4x}\n", + ((cl_ushort*)(sourcePtr + pixel_size * where))[0], ((cl_ushort*)(sourcePtr + pixel_size * where))[1], ((cl_ushort*)(sourcePtr + pixel_size * where))[2], + ((cl_ushort*)(destPtr + pixel_size * where))[0], ((cl_ushort*)(destPtr + pixel_size * where))[1], ((cl_ushort*)(destPtr + pixel_size * where))[2] + ); + break; + case 8: + log_error( "*0x%16.16llx vs. 0x%16.16llx\n", ((cl_ulong*)(sourcePtr + pixel_size * where))[0], ((cl_ulong*)(destPtr + pixel_size * where))[0] ); + break; + case 12: + log_error( "*{0x%8.8x, 0x%8.8x, 0x%8.8x} vs. {0x%8.8x, 0x%8.8x, 0x%8.8x}\n", + ((cl_uint*)(sourcePtr + pixel_size * where))[0], ((cl_uint*)(sourcePtr + pixel_size * where))[1], ((cl_uint*)(sourcePtr + pixel_size * where))[2], + ((cl_uint*)(destPtr + pixel_size * where))[0], ((cl_uint*)(destPtr + pixel_size * where))[1], ((cl_uint*)(destPtr + pixel_size * where))[2] + ); + break; + case 16: + log_error( "*{0x%8.8x, 0x%8.8x, 0x%8.8x, 0x%8.8x} vs. {0x%8.8x, 0x%8.8x, 0x%8.8x, 0x%8.8x}\n", + ((cl_uint*)(sourcePtr + pixel_size * where))[0], ((cl_uint*)(sourcePtr + pixel_size * where))[1], ((cl_uint*)(sourcePtr + pixel_size * where))[2], ((cl_uint*)(sourcePtr + pixel_size * where))[3], + ((cl_uint*)(destPtr + pixel_size * where))[0], ((cl_uint*)(destPtr + pixel_size * where))[1], ((cl_uint*)(destPtr + pixel_size * where))[2], ((cl_uint*)(destPtr + pixel_size * where))[3] + ); + break; + default: + log_error( "Don't know how to print pixel size of %ld\n", pixel_size ); + break; + } + + return -1; + } + sourcePtr += rowPitch; + if((dstImageInfo->type == CL_MEM_OBJECT_IMAGE1D_ARRAY || dstImageInfo->type == CL_MEM_OBJECT_IMAGE1D)) + destPtr += mappedSlice; + else + destPtr += mappedRow; + } + sourcePtr += slicePitch - rowPitch * dst_height_lod; + destPtr += mappedSlice - mappedRow * dst_height_lod; + } + + // Unmap the image. + error = clEnqueueUnmapMemObject(queue, dstImage, mapped, 0, NULL, NULL); + if (error != CL_SUCCESS) + { + log_error( "ERROR: Unable to unmap image after verify: %s\n", IGetErrorString( error ) ); + return error; + } + + return 0; +} + +int test_copy_image_size_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, MTdata d ) +{ + size_t sourcePos[ 3 ], destPos[ 3 ], regionSize[ 3 ]; + int ret = 0, retCode; + + for (int i = 0; i < 8; i++) + { + switch (srcImageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + sourcePos[ 0 ] = random_in_range( 0, (int)(srcImageInfo->width - 4), d ); + sourcePos[ 1 ] = 1; + sourcePos[ 2 ] = 1; + break; + case CL_MEM_OBJECT_IMAGE2D: + sourcePos[ 0 ] = random_in_range( 0, (int)(srcImageInfo->width - 4), d ); + sourcePos[ 1 ] = random_in_range( 0, (int)(srcImageInfo->height - 4), d ); + sourcePos[ 2 ] = 1; + break; + case CL_MEM_OBJECT_IMAGE3D: + sourcePos[ 0 ] = random_in_range( 0, (int)(srcImageInfo->width - 4), d ); + sourcePos[ 1 ] = random_in_range( 0, (int)(srcImageInfo->height - 4), d ); + sourcePos[ 2 ] = random_in_range( 0, (int)(srcImageInfo->depth - 4), d ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + sourcePos[ 0 ] = random_in_range( 0, (int)(srcImageInfo->width - 4), d ); + sourcePos[ 1 ] = random_in_range( 0, (int)(srcImageInfo->arraySize - 4), d ); + sourcePos[ 2 ] = 1; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + sourcePos[ 0 ] = random_in_range( 0, (int)(srcImageInfo->width - 4), d ); + sourcePos[ 1 ] = random_in_range( 0, (int)(srcImageInfo->height - 4), d ); + sourcePos[ 2 ] = random_in_range( 0, (int)(srcImageInfo->arraySize - 4), d ); + break; + } + + switch (dstImageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + destPos[ 0 ] = random_in_range( 0, (int)(dstImageInfo->width - 4), d ); + destPos[ 1 ] = 1; + destPos[ 2 ] = 1; + break; + case CL_MEM_OBJECT_IMAGE2D: + destPos[ 0 ] = random_in_range( 0, (int)(dstImageInfo->width - 4), d ); + destPos[ 1 ] = random_in_range( 0, (int)(dstImageInfo->height - 4), d ); + destPos[ 2 ] = 1; + break; + case CL_MEM_OBJECT_IMAGE3D: + destPos[ 0 ] = random_in_range( 0, (int)(dstImageInfo->width - 4), d ); + destPos[ 1 ] = random_in_range( 0, (int)(dstImageInfo->height - 4), d ); + destPos[ 2 ] = random_in_range( 0, (int)(dstImageInfo->depth - 4), d ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + destPos[ 0 ] = random_in_range( 0, (int)(dstImageInfo->width - 4), d ); + destPos[ 1 ] = random_in_range( 0, (int)(dstImageInfo->arraySize - 4), d ); + destPos[ 2 ] = 1; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + destPos[ 0 ] = random_in_range( 0, (int)(dstImageInfo->width - 4), d ); + destPos[ 1 ] = random_in_range( 0, (int)(dstImageInfo->height - 4), d ); + destPos[ 2 ] = random_in_range( 0, (int)(dstImageInfo->arraySize - 4), d ); + break; + } + + if ( (dstImageInfo->width - destPos[0]) < (srcImageInfo->width - sourcePos[0]) ) + regionSize[0] = random_in_range(1, (dstImageInfo->width - destPos[0]), d); + else + regionSize[0] = random_in_range(1, (srcImageInfo->width - sourcePos[0]), d); + + if (srcImageInfo->type == CL_MEM_OBJECT_IMAGE1D || dstImageInfo->type == CL_MEM_OBJECT_IMAGE1D) + regionSize[1] = 0; + else + { + if ( (dstImageInfo->height - destPos[1]) < (srcImageInfo->height - sourcePos[1]) ) + regionSize[1] = random_in_range(1, (dstImageInfo->height - destPos[1]), d); + else + regionSize[1] = random_in_range(1, (srcImageInfo->height - sourcePos[1]), d); + } + + regionSize[2] = 0; + if (dstImageInfo->type == CL_MEM_OBJECT_IMAGE3D && srcImageInfo->type == CL_MEM_OBJECT_IMAGE3D) + { + if ( (dstImageInfo->depth - destPos[2]) < (srcImageInfo->depth - sourcePos[2]) ) + regionSize[2] = random_in_range(1, (dstImageInfo->depth - destPos[2]), d); + else + regionSize[2] = random_in_range(1, (srcImageInfo->depth - sourcePos[2]), d); + } + else if ( (dstImageInfo->type == CL_MEM_OBJECT_IMAGE2D_ARRAY && srcImageInfo->type == CL_MEM_OBJECT_IMAGE2D_ARRAY) ) + { + if ( (dstImageInfo->arraySize - destPos[2]) < (srcImageInfo->arraySize - sourcePos[2]) ) + regionSize[2] = random_in_range(1, (dstImageInfo->arraySize - destPos[2]), d); + else + regionSize[2] = random_in_range(1, (srcImageInfo->arraySize - sourcePos[2]), d); + } + + // Go for it! + retCode = test_copy_image_generic( device, srcImageInfo, dstImageInfo, sourcePos, destPos, regionSize, d ); + if( retCode < 0 ) + return retCode; + else + ret += retCode; + } + + return ret; +} + diff --git a/test_conformance/images/clCopyImage/test_loops.cpp b/test_conformance/images/clCopyImage/test_loops.cpp new file mode 100644 index 00000000..ba8f588e --- /dev/null +++ b/test_conformance/images/clCopyImage/test_loops.cpp @@ -0,0 +1,274 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern int gTypesToTest; +extern int gNormalizedModeToUse; +extern bool gTestMipmaps; +extern cl_channel_type gChannelTypeToUse; +extern cl_command_queue queue; +extern cl_context context; +extern cl_channel_type gChannelTypeToUse; +extern cl_channel_order gChannelOrderToUse; + + +extern bool gDebugTrace; + +extern int test_copy_image_set_1D( cl_device_id device, cl_image_format *format ); +extern int test_copy_image_set_2D( cl_device_id device, cl_image_format *format ); +extern int test_copy_image_set_3D( cl_device_id device, cl_image_format *format ); +extern int test_copy_image_set_1D_array( cl_device_id device, cl_image_format *format ); +extern int test_copy_image_set_2D_array( cl_device_id device, cl_image_format *format ); +extern int test_copy_image_set_2D_3D( cl_device_id device, cl_image_format *format, bool reverse ); +extern int test_copy_image_set_2D_2D_array( cl_device_id device, cl_image_format *format, bool reverse ); +extern int test_copy_image_set_3D_2D_array( cl_device_id device, cl_image_format *format, bool reverse ); + + +int filter_formats( cl_image_format *formatList, bool *filterFlags, unsigned int formatCount, cl_channel_type *channelDataTypesToFilter ) +{ + int numSupported = 0; + for( unsigned int j = 0; j < formatCount; j++ ) + { + // If this format has been previously filtered, remove the filter + if( filterFlags[ j ] ) + filterFlags[ j ] = false; + + // Have we already discarded this via the command line? + if( gChannelTypeToUse != (cl_channel_type)-1 && gChannelTypeToUse != formatList[ j ].image_channel_data_type ) + { + filterFlags[ j ] = true; + continue; + } + + // Have we already discarded the channel order via the command line? + if( gChannelOrderToUse != (cl_channel_order)-1 && gChannelOrderToUse != formatList[ j ].image_channel_order ) + { + filterFlags[ j ] = true; + continue; + } + + // Is given format standard channel order and type given by spec. We don't want to test it if this is vendor extension + if( !IsChannelOrderSupported( formatList[ j ].image_channel_order ) || !IsChannelTypeSupported( formatList[ j ].image_channel_data_type ) ) + { + filterFlags[ j ] = true; + continue; + } + + // We don't filter by channel type + if( !channelDataTypesToFilter ) + { + numSupported++; + continue; + } + + // Is the format supported? + int i; + for( i = 0; channelDataTypesToFilter[ i ] != (cl_channel_type)-1; i++ ) + { + if( formatList[ j ].image_channel_data_type == channelDataTypesToFilter[ i ] ) + { + numSupported++; + break; + } + } + if( channelDataTypesToFilter[ i ] == (cl_channel_type)-1 ) + { + // Format is NOT supported, so mark it as such + filterFlags[ j ] = true; + } + } + return numSupported; +} + +int get_format_list( cl_device_id device, cl_mem_object_type imageType, cl_image_format * &outFormatList, unsigned int &outFormatCount, cl_mem_flags flags ) +{ + int error; + + cl_image_format tempList[ 128 ]; + error = clGetSupportedImageFormats( context, (cl_mem_flags)flags, + imageType, 128, tempList, &outFormatCount ); + test_error( error, "Unable to get count of supported image formats" ); + + outFormatList = new cl_image_format[ outFormatCount ]; + error = clGetSupportedImageFormats( context, (cl_mem_flags)flags, + imageType, outFormatCount, outFormatList, NULL ); + test_error( error, "Unable to get list of supported image formats" ); + return 0; +} + +int test_image_type( cl_device_id device, MethodsToTest testMethod, cl_mem_flags flags ) +{ + const char *name; + cl_mem_object_type imageType; + + if ( gTestMipmaps ) + { + if ( 0 == is_extension_available( device, "cl_khr_mipmap_image" )) + { + log_info( "-----------------------------------------------------\n" ); + log_info( "This device does not support cl_khr_mipmap_image.\nSkipping mipmapped image test. \n" ); + log_info( "-----------------------------------------------------\n\n" ); + return 0; + } + } + + if( testMethod == k1D ) + { + name = "1D -> 1D"; + imageType = CL_MEM_OBJECT_IMAGE1D; + } + else if( testMethod == k2D ) + { + name = "2D -> 2D"; + imageType = CL_MEM_OBJECT_IMAGE2D; + } + else if( testMethod == k3D ) + { + name = "3D -> 3D"; + imageType = CL_MEM_OBJECT_IMAGE3D; + } + else if( testMethod == k1DArray ) + { + name = "1D array -> 1D array"; + imageType = CL_MEM_OBJECT_IMAGE1D_ARRAY; + } + else if( testMethod == k2DArray ) + { + name = "2D array -> 2D array"; + imageType = CL_MEM_OBJECT_IMAGE2D_ARRAY; + } + else if( testMethod == k2DTo3D ) + { + name = "2D -> 3D"; + imageType = CL_MEM_OBJECT_IMAGE3D; + } + else if( testMethod == k3DTo2D ) + { + name = "3D -> 2D"; + imageType = CL_MEM_OBJECT_IMAGE3D; + } + else if( testMethod == k2DArrayTo2D ) + { + name = "2D array -> 2D"; + imageType = CL_MEM_OBJECT_IMAGE2D_ARRAY; + } + else if( testMethod == k2DTo2DArray ) + { + name = "2D -> 2D array"; + imageType = CL_MEM_OBJECT_IMAGE2D_ARRAY; + } + else if( testMethod == k2DArrayTo3D ) + { + name = "2D array -> 3D"; + imageType = CL_MEM_OBJECT_IMAGE3D; + } + else if( testMethod == k3DTo2DArray ) + { + name = "3D -> 2D array"; + imageType = CL_MEM_OBJECT_IMAGE3D; + } + + if(gTestMipmaps) + log_info( "Running mipmapped %s tests...\n", name ); + else + log_info( "Running %s tests...\n", name ); + + int ret = 0; + + // Grab the list of supported image formats for integer reads + cl_image_format *formatList; + bool *filterFlags; + unsigned int numFormats; + + if( get_format_list( device, imageType, formatList, numFormats, flags ) ) + return -1; + + filterFlags = new bool[ numFormats ]; + if( filterFlags == NULL ) + { + log_error( "ERROR: Out of memory allocating filter flags list!\n" ); + return -1; + } + memset( filterFlags, 0, sizeof( bool ) * numFormats ); + + filter_formats(formatList, filterFlags, numFormats, NULL); + + // Run the format list + for( unsigned int i = 0; i < numFormats; i++ ) + { + int test_return = 0; + if( filterFlags[i] ) + { + continue; + } + + print_header( &formatList[ i ], false ); + + gTestCount++; + + if( testMethod == k1D ) + test_return = test_copy_image_set_1D( device, &formatList[ i ] ); + else if( testMethod == k2D ) + test_return = test_copy_image_set_2D( device, &formatList[ i ] ); + else if( testMethod == k3D ) + test_return = test_copy_image_set_3D( device, &formatList[ i ] ); + else if( testMethod == k1DArray ) + test_return = test_copy_image_set_1D_array( device, &formatList[ i ] ); + else if( testMethod == k2DArray ) + test_return = test_copy_image_set_2D_array( device, &formatList[ i ] ); + else if( testMethod == k2DTo3D ) + test_return = test_copy_image_set_2D_3D( device, &formatList[ i ], false ); + else if( testMethod == k3DTo2D ) + test_return = test_copy_image_set_2D_3D( device, &formatList[ i ], true ); + else if( testMethod == k2DArrayTo2D) + test_return = test_copy_image_set_2D_2D_array( device, &formatList[ i ], true); + else if( testMethod == k2DTo2DArray) + test_return = test_copy_image_set_2D_2D_array( device, &formatList[ i ], false); + else if( testMethod == k2DArrayTo3D) + test_return = test_copy_image_set_3D_2D_array( device, &formatList[ i ], true); + else if( testMethod == k3DTo2DArray) + test_return = test_copy_image_set_3D_2D_array( device, &formatList[ i ], false); + + if (test_return) { + gTestFailure++; + log_error( "FAILED: " ); + print_header( &formatList[ i ], true ); + log_info( "\n" ); + } + + ret += test_return; + } + + delete filterFlags; + delete formatList; + + return ret; +} + +int test_image_set( cl_device_id device, MethodsToTest testMethod ) +{ + int ret = 0; + + ret += test_image_type( device, testMethod, CL_MEM_READ_ONLY ); + + return ret; +} + + + + diff --git a/test_conformance/images/clFillImage/CMakeLists.txt b/test_conformance/images/clFillImage/CMakeLists.txt new file mode 100644 index 00000000..7ee70944 --- /dev/null +++ b/test_conformance/images/clFillImage/CMakeLists.txt @@ -0,0 +1,27 @@ + +set(MODULE_NAME CL_FILL_IMAGES) + +set(${MODULE_NAME}_SOURCES + main.cpp + test_fill_1D.cpp + test_fill_1D_array.cpp + test_fill_2D.cpp + test_fill_2D_array.cpp + test_fill_generic.cpp + test_loops.cpp + test_fill_3D.cpp +# test_fill_2D_3D.cpp + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/threadTesting.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/imageHelpers.cpp + ../../../test_common/harness/mt19937.c + ../../../test_common/harness/conversions.c + ../../../test_common/harness/typeWrappers.cpp + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + + +include(../../CMakeCommon.txt) diff --git a/test_conformance/images/clFillImage/Jamfile b/test_conformance/images/clFillImage/Jamfile new file mode 100644 index 00000000..14812f04 --- /dev/null +++ b/test_conformance/images/clFillImage/Jamfile @@ -0,0 +1,19 @@ +project + : requirements +# gcc:-xc++ +# msvc:"/TP" + ; + +exe test_cl_fill_images + : main.cpp + test_fill_2D_3D.cpp + test_fill_2D.cpp + test_fill_3D.cpp + test_loops.cpp + ; + +install dist + : test_cl_fill_images + : debug:$(DIST)/debug/tests/test_conformance/images/clFillImage + release:$(DIST)/release/tests/test_conformance/images/clFillImage + ; diff --git a/test_conformance/images/clFillImage/Makefile b/test_conformance/images/clFillImage/Makefile new file mode 100644 index 00000000..58f12012 --- /dev/null +++ b/test_conformance/images/clFillImage/Makefile @@ -0,0 +1,53 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.cpp \ + test_fill_generic.cpp \ + test_fill_1D.cpp \ + test_fill_2D.cpp \ + test_fill_3D.cpp \ + test_fill_1D_array.cpp \ + test_fill_2D_array.cpp \ + test_loops.cpp \ + ../../../test_common/harness/errorHelpers.c \ + ../../../test_common/harness/threadTesting.c \ + ../../../test_common/harness/kernelHelpers.c \ + ../../../test_common/harness/imageHelpers.cpp \ + ../../../test_common/harness/conversions.c \ + ../../../test_common/harness/testHarness.cpp \ + ../../../test_common/harness/typeWrappers.cpp \ + ../../../test_common/harness/mt19937.c + + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = +HEADERS = +TARGET = test_cl_fill_images +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os +CC = c++ +CXX = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/images/clFillImage/main.cpp b/test_conformance/images/clFillImage/main.cpp new file mode 100644 index 00000000..9c1f7904 --- /dev/null +++ b/test_conformance/images/clFillImage/main.cpp @@ -0,0 +1,252 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../../test_common/harness/compat.h" + +#include +#include + +#if !defined(_WIN32) +#include +#include +#endif + +#include "../testBase.h" + +bool gDebugTrace = false, gTestSmallImages = false, gTestMaxImages = false, gTestRounding = false, gEnablePitch = false; +int gTypesToTest = 0; +cl_channel_type gChannelTypeToUse = (cl_channel_type)-1; +cl_channel_order gChannelOrderToUse = (cl_channel_order)-1; +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +cl_context context; +cl_command_queue queue; + +extern int test_image_set( cl_device_id device, MethodsToTest testMethod ); + +#define MAX_ALLOWED_STD_DEVIATION_IN_MB 8.0 + +void printUsage( const char *execName ) +{ + const char *p = strrchr( execName, '/' ); + if ( p != NULL ) + execName = p + 1; + + log_info( "Usage: %s [debug_trace] [small_images]\n", execName ); + log_info( "Where:\n" ); + log_info( "\t1D - Only test 1D images\n" ); + log_info( "\t2D - Only test 2D images\n" ); + log_info( "\t3D - Only test 3D images\n" ); + log_info( "\t1Darray - Only test 1D image arrays\n" ); + log_info( "\t2Darray - Only test 2D image arrays\n" ); + log_info( "\n" ); + log_info( "\tThe following flags specify the types to test. They can be combined; if none are specified, all are tested:\n" ); + log_info( "\t\tint - Test integer fill\n" ); + log_info( "\t\tuint - Test unsigned integer fill\n" ); + log_info( "\t\tfloat - Test float fill\n" ); + log_info( "\n" ); + log_info( "\tdebug_trace - Enables additional debug info logging\n" ); + log_info( "\tsmall_images - Runs every format through a loop of widths 1-13 and heights 1-9, instead of random sizes\n" ); + log_info( "\tmax_images - Runs every format through a set of size combinations with the max values, max values - 1, and max values / 128\n" ); + log_info( "\tuse_pitches - Enables row and slice pitches\n" ); + log_info( "You may also use appropriate CL_ channel type and ordering constants.\n" ); +} + + +int main(int argc, const char *argv[]) +{ + cl_platform_id platform; + cl_device_id device; + cl_channel_type chanType; + cl_channel_order chanOrder; + char str[ 128 ]; + int testMethods = 0; + bool randomize = false; + + test_start(); + + checkDeviceTypeOverride( &gDeviceType ); + + // Parse arguments + for ( int i = 1; i < argc; i++ ) + { + strncpy( str, argv[ i ], sizeof( str ) - 1 ); + + if ( strcmp( str, "cpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_CPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_CPU; + else if ( strcmp( str, "gpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_GPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_GPU; + else if ( strcmp( str, "accelerator" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + else if ( strcmp( str, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_DEFAULT; + + else if ( strcmp( str, "debug_trace" ) == 0 ) + gDebugTrace = true; + + else if ( strcmp( str, "small_images" ) == 0 ) + gTestSmallImages = true; + else if ( strcmp( str, "max_images" ) == 0 ) + gTestMaxImages = true; + + else if ( strcmp( str, "use_pitches" ) == 0 ) + gEnablePitch = true; + + else if ( strcmp( str, "randomize" ) == 0 ) + randomize = true; + + else if ( strcmp( str, "1D" ) == 0 ) + testMethods |= k1D; + else if ( strcmp( str, "2D" ) == 0 ) + testMethods |= k2D; + else if ( strcmp( str, "3D" ) == 0 ) + testMethods |= k3D; + else if( strcmp( str, "1Darray" ) == 0 ) + testMethods |= k1DArray; + else if( strcmp( str, "2Darray" ) == 0 ) + testMethods |= k2DArray; + + else if( strcmp( str, "int" ) == 0 ) + gTypesToTest |= kTestInt; + else if( strcmp( str, "uint" ) == 0 ) + gTypesToTest |= kTestUInt; + else if( strcmp( str, "float" ) == 0 ) + gTypesToTest |= kTestFloat; + + else if ( strcmp( str, "help" ) == 0 || strcmp( str, "?" ) == 0 ) + { + printUsage( argv[ 0 ] ); + return -1; + } + + else if ( ( chanType = get_channel_type_from_name( str ) ) != (cl_channel_type)-1 ) + gChannelTypeToUse = chanType; + + else if ( ( chanOrder = get_channel_order_from_name( str ) ) != (cl_channel_order)-1 ) + gChannelOrderToUse = chanOrder; + else + { + log_error( "ERROR: Unknown argument %d: %s. Exiting....\n", i, str ); + return -1; + } + + } + + if (testMethods == 0) + testMethods = k1D | k2D | k3D | k1DArray | k2DArray; + if ( gTypesToTest == 0 ) + gTypesToTest = kTestAllTypes; + + // Seed the random # generators + if ( randomize ) + { + gRandomSeed = (cl_uint) time( NULL ); + log_info( "Random seed: %u.\n", gRandomSeed ); + gReSeed = 1; + } + + int error; + // Get our platform + error = clGetPlatformIDs(1, &platform, NULL); + if ( error ) + { + print_error( error, "Unable to get platform" ); + test_finish(); + return -1; + } + + // Get our device + error = clGetDeviceIDs(platform, gDeviceType, 1, &device, NULL ); + if ( error ) + { + print_error( error, "Unable to get specified device" ); + test_finish(); + return -1; + } + + char deviceName[ 128 ], deviceVendor[ 128 ], deviceVersion[ 128 ]; + error = clGetDeviceInfo( device, CL_DEVICE_NAME, sizeof( deviceName ), deviceName, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_VENDOR, sizeof( deviceVendor ), deviceVendor, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_VERSION, sizeof( deviceVersion ), deviceVersion, NULL ); + if ( error != CL_SUCCESS ) + { + print_error( error, "Unable to get device information" ); + test_finish(); + return -1; + } + log_info("Using compute device: Name = %s, Vendor = %s, Version = %s\n", deviceName, deviceVendor, deviceVersion ); + + // Check for image support + if (checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) { + log_info("Device does not support images. Skipping test.\n"); + test_finish(); + return 0; + } + + // Create a context to test with + context = clCreateContext( NULL, 1, &device, notify_callback, NULL, &error ); + if ( error != CL_SUCCESS ) + { + print_error( error, "Unable to create testing context" ); + test_finish(); + return -1; + } + + // Create a queue against the context + queue = clCreateCommandQueueWithProperties( context, device, 0, &error ); + if ( error != CL_SUCCESS ) + { + print_error( error, "Unable to create testing command queue" ); + test_finish(); + return -1; + } + + if ( gTestSmallImages ) + log_info( "Note: Using small test images\n" ); + + // Run the test now + int ret = 0; + for ( int test = k1D; test <= k3D; test <<= 1 ) + { + if ( testMethods & test ) + ret += test_image_set( device, (MethodsToTest)test ); + } + + error = clFinish(queue); + if (error) + print_error(error, "clFinish failed."); + + if (gTestFailure == 0) { + if (gTestCount > 1) + log_info("PASSED %d of %d tests.\n", gTestCount, gTestCount); + else + log_info("PASSED test.\n"); + } + else if (gTestFailure > 0) { + if (gTestCount > 1) + log_error("FAILED %d of %d tests.\n", gTestFailure, gTestCount); + else + log_error("FAILED test.\n"); + } + + // Clean up + clReleaseCommandQueue(queue); + clReleaseContext(context); + test_finish(); + + if (gTestFailure > 0) + return gTestFailure; + + return ret; +} diff --git a/test_conformance/images/clFillImage/test_fill_1D.cpp b/test_conformance/images/clFillImage/test_fill_1D.cpp new file mode 100644 index 00000000..bd3bcaec --- /dev/null +++ b/test_conformance/images/clFillImage/test_fill_1D.cpp @@ -0,0 +1,181 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_command_queue queue; +extern cl_context context; + +// Defined in test_fill_2D_3D.cpp +extern int test_fill_image_generic( cl_device_id device, image_descriptor *imageInfo, + const size_t origin[], const size_t region[], ExplicitType outputType, MTdata d ); + + +int test_fill_image_size_1D( cl_device_id device, image_descriptor *imageInfo, ExplicitType outputType, MTdata d ) +{ + size_t origin[ 3 ], region[ 3 ]; + int ret = 0, retCode; + + // First, try just a full covering region fill + origin[ 0 ] = origin[ 1 ] = origin[ 2 ] = 0; + region[ 0 ] = imageInfo->width; + region[ 1 ] = 1; + region[ 2 ] = 1; + + retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d ); + if ( retCode < 0 ) + return retCode; + else + ret += retCode; + + // Now try a sampling of different random regions + for ( int i = 0; i < 8; i++ ) + { + // Pick a random size + region[ 0 ] = ( imageInfo->width > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->width - 1, d ) : imageInfo->width; + + // Now pick positions within valid ranges + origin[ 0 ] = ( imageInfo->width > region[ 0 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->width - region[ 0 ] - 1 ), d ) : 0; + + // Go for it! + retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d ); + if ( retCode < 0 ) + return retCode; + else + ret += retCode; + } + + return ret; +} + + +int test_fill_image_set_1D( cl_device_id device, cl_image_format *format, ExplicitType outputType ) +{ + size_t maxWidth; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed(gRandomSeed); + const size_t rowPadding_default = 48; + size_t rowPadding = gEnablePitch ? rowPadding_default : 0; + size_t pixelSize; + + memset(&imageInfo, 0x0, sizeof(image_descriptor)); + imageInfo.type = CL_MEM_OBJECT_IMAGE1D; + imageInfo.format = format; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if ( gTestSmallImages ) + { + for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + rowPadding = rowPadding_default; + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + if ( gDebugTrace ) + log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.height ); + + int ret = test_fill_image_size_1D( device, &imageInfo, outputType, seed ); + if ( ret ) + return -1; + } + } + else if ( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format); + + for ( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + rowPadding = rowPadding_default; + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + log_info( "Testing %d\n", (int)sizes[ idx ][ 0 ] ); + if ( gDebugTrace ) + log_info( " at max size %d\n", (int)sizes[ idx ][ 0 ] ); + if ( test_fill_image_size_1D( device, &imageInfo, outputType, seed ) ) + return -1; + } + } + else + { + for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + rowPadding = rowPadding_default; + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + size = (size_t)imageInfo.rowPitch * 4; + } while ( size > maxAllocSize || ( size * 3 ) > memSize ); + + if ( gDebugTrace ) + log_info( " at size %d (row pitch %d) out of %d\n", (int)imageInfo.width, (int)imageInfo.rowPitch, (int)maxWidth ); + int ret = test_fill_image_size_1D( device, &imageInfo, outputType, seed ); + if ( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clFillImage/test_fill_1D_array.cpp b/test_conformance/images/clFillImage/test_fill_1D_array.cpp new file mode 100644 index 00000000..45caa24f --- /dev/null +++ b/test_conformance/images/clFillImage/test_fill_1D_array.cpp @@ -0,0 +1,193 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_command_queue queue; +extern cl_context context; + +// Defined in test_fill_2D_3D.cpp +extern int test_fill_image_generic( cl_device_id device, image_descriptor *imageInfo, + const size_t origin[], const size_t region[], ExplicitType outputType, MTdata d ); + + +int test_fill_image_size_1D_array( cl_device_id device, image_descriptor *imageInfo, ExplicitType outputType, MTdata d ) +{ + size_t origin[ 3 ], region[ 3 ]; + int ret = 0, retCode; + + // First, try just a full covering region fill + origin[ 0 ] = origin[ 1 ] = origin[ 2 ] = 0; + region[ 0 ] = imageInfo->width; + region[ 1 ] = imageInfo->arraySize; + region[ 2 ] = 1; + + retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d ); + if ( retCode < 0 ) + return retCode; + else + ret += retCode; + + // Now try a sampling of different random regions + for ( int i = 0; i < 8; i++ ) + { + // Pick a random size + region[ 0 ] = ( imageInfo->width > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->width - 1, d ) : imageInfo->width; + region[ 1 ] = ( imageInfo->arraySize > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->arraySize - 1, d ) : imageInfo->arraySize; + + // Now pick positions within valid ranges + origin[ 0 ] = ( imageInfo->width > region[ 0 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->width - region[ 0 ] - 1 ), d ) : 0; + origin[ 1 ] = ( imageInfo->arraySize > region[ 1 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->arraySize - region[ 1 ] - 1 ), d ) : 0; + + // Go for it! + retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d ); + if ( retCode < 0 ) + return retCode; + else + ret += retCode; + } + + return ret; +} + + +int test_fill_image_set_1D_array( cl_device_id device, cl_image_format *format, ExplicitType outputType ) +{ + size_t maxWidth, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed(gRandomSeed); + const size_t rowPadding_default = 48; + size_t rowPadding = gEnablePitch ? rowPadding_default : 0; + size_t pixelSize; + + memset(&imageInfo, 0x0, sizeof(image_descriptor)); + imageInfo.type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + imageInfo.format = format; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 1D array size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if ( gTestSmallImages ) + { + for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + rowPadding = rowPadding_default; + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + imageInfo.slicePitch = imageInfo.rowPitch; + for ( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ ) + { + if ( gDebugTrace ) + log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize ); + + int ret = test_fill_image_size_1D_array( device, &imageInfo, outputType, seed ); + if ( ret ) + return -1; + } + } + } + else if ( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D_ARRAY, imageInfo.format); + + for ( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.arraySize = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + rowPadding = rowPadding_default; + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + imageInfo.slicePitch = imageInfo.rowPitch; + log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ] ); + if ( gDebugTrace ) + log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ] ); + if ( test_fill_image_size_1D_array( device, &imageInfo, outputType, seed ) ) + return -1; + } + } + else + { + for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + rowPadding = rowPadding_default; + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + imageInfo.slicePitch = imageInfo.rowPitch; + + size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.arraySize * 4; + } while ( size > maxAllocSize || ( size * 3 ) > memSize ); + + if ( gDebugTrace ) + log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxArraySize ); + int ret = test_fill_image_size_1D_array( device, &imageInfo, outputType, seed ); + if ( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clFillImage/test_fill_2D.cpp b/test_conformance/images/clFillImage/test_fill_2D.cpp new file mode 100644 index 00000000..01b80ffb --- /dev/null +++ b/test_conformance/images/clFillImage/test_fill_2D.cpp @@ -0,0 +1,189 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_command_queue queue; +extern cl_context context; + +// Defined in test_fill_2D_3D.cpp +extern int test_fill_image_generic( cl_device_id device, image_descriptor *imageInfo, + const size_t origin[], const size_t region[], ExplicitType outputType, MTdata d ); + + +int test_fill_image_size_2D( cl_device_id device, image_descriptor *imageInfo, ExplicitType outputType, MTdata d ) +{ + size_t origin[ 3 ], region[ 3 ]; + int ret = 0, retCode; + + // First, try just a full covering region fill + origin[ 0 ] = origin[ 1 ] = origin[ 2 ] = 0; + region[ 0 ] = imageInfo->width; + region[ 1 ] = imageInfo->height; + region[ 2 ] = 1; + + retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d ); + if ( retCode < 0 ) + return retCode; + else + ret += retCode; + + // Now try a sampling of different random regions + for ( int i = 0; i < 8; i++ ) + { + // Pick a random size + region[ 0 ] = ( imageInfo->width > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->width - 1, d ) : imageInfo->width; + region[ 1 ] = ( imageInfo->height > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->height - 1, d ) : imageInfo->height; + + // Now pick positions within valid ranges + origin[ 0 ] = ( imageInfo->width > region[ 0 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->width - region[ 0 ] - 1 ), d ) : 0; + origin[ 1 ] = ( imageInfo->height > region[ 1 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->height - region[ 1 ] - 1 ), d ) : 0; + + // Go for it! + retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d ); + if ( retCode < 0 ) + return retCode; + else + ret += retCode; + } + + return ret; +} + + +int test_fill_image_set_2D( cl_device_id device, cl_image_format *format, ExplicitType outputType ) +{ + size_t maxWidth, maxHeight; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed(gRandomSeed); + const size_t rowPadding_default = 48; + size_t rowPadding = gEnablePitch ? rowPadding_default : 0; + size_t pixelSize; + + memset(&imageInfo, 0x0, sizeof(image_descriptor)); + imageInfo.type = CL_MEM_OBJECT_IMAGE2D; + imageInfo.format = format; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if ( gTestSmallImages ) + { + for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + rowPadding = rowPadding_default; + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + for ( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + if ( gDebugTrace ) + log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.height ); + + int ret = test_fill_image_size_2D( device, &imageInfo, outputType, seed ); + if ( ret ) + return -1; + } + } + } + else if ( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D, imageInfo.format); + + for ( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + rowPadding = rowPadding_default; + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] ); + if ( gDebugTrace ) + log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] ); + if ( test_fill_image_size_2D( device, &imageInfo, outputType, seed ) ) + return -1; + } + } + else + { + for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + rowPadding = rowPadding_default; + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.height * 4; + } while ( size > maxAllocSize || ( size * 3 ) > memSize ); + + if ( gDebugTrace ) + log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight ); + int ret = test_fill_image_size_2D( device, &imageInfo, outputType, seed ); + if ( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clFillImage/test_fill_2D_array.cpp b/test_conformance/images/clFillImage/test_fill_2D_array.cpp new file mode 100644 index 00000000..2ec35f6b --- /dev/null +++ b/test_conformance/images/clFillImage/test_fill_2D_array.cpp @@ -0,0 +1,200 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gEnablePitch, gTestRounding; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern cl_command_queue queue; +extern cl_context context; + +// Defined in test_fill_2D_3D.cpp +extern int test_fill_image_generic( cl_device_id device, image_descriptor *imageInfo, + const size_t origin[], const size_t region[], ExplicitType outputType, MTdata d ); + + +static int test_fill_image_2D_array( cl_device_id device, image_descriptor *imageInfo, ExplicitType outputType, MTdata d ) +{ + size_t origin[ 3 ], region[ 3 ]; + int ret = 0, retCode; + + // First, try just a full covering region + origin[ 0 ] = origin[ 1 ] = origin[ 2 ] = 0; + region[ 0 ] = imageInfo->width; + region[ 1 ] = imageInfo->height; + region[ 2 ] = imageInfo->arraySize; + + retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d ); + if ( retCode < 0 ) + return retCode; + else + ret += retCode; + + // Now try a sampling of different random regions + for ( int i = 0; i < 8; i++ ) + { + // Pick a random size + region[ 0 ] = ( imageInfo->width > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->width - 1, d ) : imageInfo->width; + region[ 1 ] = ( imageInfo->height > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->height - 1, d ) : imageInfo->height; + region[ 2 ] = ( imageInfo->arraySize > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->arraySize - 1, d ) : imageInfo->arraySize; + + // Now pick positions within valid ranges + origin[ 0 ] = ( imageInfo->width > region[ 0 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->width - region[ 0 ] - 1 ), d ) : 0; + origin[ 1 ] = ( imageInfo->height > region[ 1 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->height - region[ 1 ] - 1 ), d ) : 0; + origin[ 2 ] = ( imageInfo->arraySize > region[ 2 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->arraySize - region[ 2 ] - 1 ), d ) : 0; + + // Go for it! + retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d ); + if ( retCode < 0 ) + return retCode; + else + ret += retCode; + } + + return ret; +} + + +int test_fill_image_set_2D_array( cl_device_id device, cl_image_format *format, ExplicitType outputType ) +{ + size_t maxWidth, maxHeight, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + const size_t rowPadding_default = 80; + size_t rowPadding = gEnablePitch ? rowPadding_default : 0; + size_t slicePadding = gEnablePitch ? 3 : 0; + size_t pixelSize; + + memset(&imageInfo, 0x0, sizeof(image_descriptor)); + imageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + imageInfo.format = format; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D array size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if ( gTestSmallImages ) + { + for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + rowPadding = rowPadding_default; + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + for ( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding); + for ( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ ) + { + if ( gDebugTrace ) + log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize ); + int ret = test_fill_image_2D_array( device, &imageInfo, outputType, seed ); + if ( ret ) + return -1; + } + } + } + } + else if ( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D_ARRAY, imageInfo.format); + + for ( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.arraySize = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + rowPadding = rowPadding_default; + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding); + + log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + if ( gDebugTrace ) + log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + if ( test_fill_image_2D_array( device, &imageInfo, outputType, seed ) ) + return -1; + } + } + else + { + for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 64, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 64, seed ); + imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32,seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + rowPadding = rowPadding_default; + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding); + + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4; + } while ( size > maxAllocSize || ( size * 3 ) > memSize ); + + if ( gDebugTrace ) + log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxArraySize ); + int ret = test_fill_image_2D_array( device, &imageInfo, outputType, seed ); + if ( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clFillImage/test_fill_3D.cpp b/test_conformance/images/clFillImage/test_fill_3D.cpp new file mode 100644 index 00000000..0c4c2079 --- /dev/null +++ b/test_conformance/images/clFillImage/test_fill_3D.cpp @@ -0,0 +1,200 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gEnablePitch, gTestRounding; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern cl_command_queue queue; +extern cl_context context; + +// Defined in test_fill_2D_3D.cpp +extern int test_fill_image_generic( cl_device_id device, image_descriptor *imageInfo, + const size_t origin[], const size_t region[], ExplicitType outputType, MTdata d ); + + +int test_fill_image_3D( cl_device_id device, image_descriptor *imageInfo, ExplicitType outputType, MTdata d ) +{ + size_t origin[ 3 ], region[ 3 ]; + int ret = 0, retCode; + + // First, try just a full covering region + origin[ 0 ] = origin[ 1 ] = origin[ 2 ] = 0; + region[ 0 ] = imageInfo->width; + region[ 1 ] = imageInfo->height; + region[ 2 ] = imageInfo->depth; + + retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d ); + if ( retCode < 0 ) + return retCode; + else + ret += retCode; + + // Now try a sampling of different random regions + for ( int i = 0; i < 8; i++ ) + { + // Pick a random size + region[ 0 ] = ( imageInfo->width > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->width - 1, d ) : imageInfo->width; + region[ 1 ] = ( imageInfo->height > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->height - 1, d ) : imageInfo->height; + region[ 2 ] = ( imageInfo->depth > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->depth - 1, d ) : imageInfo->depth; + + // Now pick positions within valid ranges + origin[ 0 ] = ( imageInfo->width > region[ 0 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->width - region[ 0 ] - 1 ), d ) : 0; + origin[ 1 ] = ( imageInfo->height > region[ 1 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->height - region[ 1 ] - 1 ), d ) : 0; + origin[ 2 ] = ( imageInfo->depth > region[ 2 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->depth - region[ 2 ] - 1 ), d ) : 0; + + // Go for it! + retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d ); + if ( retCode < 0 ) + return retCode; + else + ret += retCode; + } + + return ret; +} + + +int test_fill_image_set_3D( cl_device_id device, cl_image_format *format, ExplicitType outputType ) +{ + size_t maxWidth, maxHeight, maxDepth; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + const size_t rowPadding_default = 80; + size_t rowPadding = gEnablePitch ? rowPadding_default : 0; + size_t slicePadding = gEnablePitch ? 3 : 0; + size_t pixelSize; + + memset(&imageInfo, 0x0, sizeof(image_descriptor)); + imageInfo.type = CL_MEM_OBJECT_IMAGE3D; + imageInfo.format = format; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 3D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if ( gTestSmallImages ) + { + for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + rowPadding = rowPadding_default; + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + for ( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding); + for ( imageInfo.depth = 2; imageInfo.depth < 9; imageInfo.depth++ ) + { + if ( gDebugTrace ) + log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth ); + int ret = test_fill_image_3D( device, &imageInfo, outputType, seed ); + if ( ret ) + return -1; + } + } + } + } + else if ( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, maxDepth, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE3D, imageInfo.format); + + for ( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.depth = sizes[ idx ][ 2 ]; + + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + rowPadding = rowPadding_default; + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding); + log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + if ( gDebugTrace ) + log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + if ( test_fill_image_3D( device, &imageInfo, outputType, seed ) ) + return -1; + } + } + else + { + for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + imageInfo.depth = (size_t)random_log_in_range( 16, (int)maxDepth / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + + if (gEnablePitch) + { + rowPadding = rowPadding_default; + do { + rowPadding++; + imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding; + } while ((imageInfo.rowPitch % pixelSize) != 0); + } + + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding); + + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.depth * 4 * 4; + } while ( size > maxAllocSize || ( size * 3 ) > memSize ); + + if ( gDebugTrace ) + log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxDepth ); + int ret = test_fill_image_3D( device, &imageInfo, outputType, seed ); + if ( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clFillImage/test_fill_generic.cpp b/test_conformance/images/clFillImage/test_fill_generic.cpp new file mode 100644 index 00000000..eb4cac98 --- /dev/null +++ b/test_conformance/images/clFillImage/test_fill_generic.cpp @@ -0,0 +1,556 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gTestRounding, gEnablePitch; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_command_queue queue; +extern cl_context context; + +extern void read_image_pixel_float( void *imageData, image_descriptor *imageInfo, int x, int y, int z, float *outData ); + + +static void CL_CALLBACK free_pitch_buffer( cl_mem image, void *buf ) +{ + free( buf ); +} + + +cl_mem create_image( cl_context context, BufferOwningPtr& data, image_descriptor *imageInfo, int *error ) +{ + cl_mem img; + cl_image_desc imageDesc; + cl_mem_flags mem_flags = CL_MEM_READ_ONLY; + void *host_ptr = NULL; + + memset(&imageDesc, 0x0, sizeof(cl_image_desc)); + imageDesc.image_type = imageInfo->type; + imageDesc.image_width = imageInfo->width; + imageDesc.image_height = imageInfo->height; + imageDesc.image_depth = imageInfo->depth; + imageDesc.image_array_size = imageInfo->arraySize; + imageDesc.image_row_pitch = gEnablePitch ? imageInfo->rowPitch : 0; + imageDesc.image_slice_pitch = gEnablePitch ? imageInfo->slicePitch : 0; + + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + if ( gDebugTrace ) + log_info( " - Creating 1D image %d ...\n", (int)imageInfo->width ); + if ( gEnablePitch ) + host_ptr = malloc( imageInfo->rowPitch ); + break; + case CL_MEM_OBJECT_IMAGE2D: + if ( gDebugTrace ) + log_info( " - Creating 2D image %d by %d ...\n", (int)imageInfo->width, (int)imageInfo->height ); + if ( gEnablePitch ) + host_ptr = malloc( imageInfo->height * imageInfo->rowPitch ); + break; + case CL_MEM_OBJECT_IMAGE3D: + if ( gDebugTrace ) + log_info( " - Creating 3D image %d by %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth ); + if ( gEnablePitch ) + host_ptr = malloc( imageInfo->depth * imageInfo->slicePitch ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + if ( gDebugTrace ) + log_info( " - Creating 1D image array %d by %d...\n", (int)imageInfo->width, (int)imageInfo->arraySize ); + if ( gEnablePitch ) + host_ptr = malloc( imageInfo->arraySize * imageInfo->slicePitch ); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + if ( gDebugTrace ) + log_info( " - Creating 2D image array %d by %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize ); + if ( gEnablePitch ) + host_ptr = malloc( imageInfo->arraySize * imageInfo->slicePitch ); + break; + } + + if (gEnablePitch) + { + if ( NULL == host_ptr ) + { + log_error( "ERROR: Unable to create backing store for pitched 3D image. %ld bytes\n", imageInfo->depth * imageInfo->slicePitch ); + return NULL; + } + mem_flags = CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR; + } + + img = clCreateImage(context, mem_flags, imageInfo->format, &imageDesc, host_ptr, error); + + if (gEnablePitch) + { + if ( *error == CL_SUCCESS ) + { + int callbackError = clSetMemObjectDestructorCallback( img, free_pitch_buffer, host_ptr ); + if ( CL_SUCCESS != callbackError ) + { + free( host_ptr ); + log_error( "ERROR: Unable to attach destructor callback to pitched 3D image. Err: %d\n", callbackError ); + clReleaseMemObject( img ); + return NULL; + } + } + else + free(host_ptr); + } + + if ( *error != CL_SUCCESS ) + { + long long unsigned imageSize = get_image_size_mb( imageInfo ); + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + log_error( "ERROR: Unable to create 1D image of size %d (%llu MB): %s\n", (int)imageInfo->width, imageSize, IGetErrorString( *error ) ); + break; + case CL_MEM_OBJECT_IMAGE2D: + log_error( "ERROR: Unable to create 2D image of size %d x %d (%llu MB): %s\n", (int)imageInfo->width, (int)imageInfo->height, imageSize, IGetErrorString( *error ) ); + break; + case CL_MEM_OBJECT_IMAGE3D: + log_error( "ERROR: Unable to create 3D image of size %d x %d x %d (%llu MB): %s\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, imageSize, IGetErrorString( *error ) ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + log_error( "ERROR: Unable to create 1D image array of size %d x %d (%llu MB): %s\n", (int)imageInfo->width, (int)imageInfo->arraySize, imageSize, IGetErrorString( *error ) ); + break; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + log_error( "ERROR: Unable to create 2D image array of size %d x %d x %d (%llu MB): %s\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, imageSize, IGetErrorString( *error ) ); + break; + } + return NULL; + } + + // Copy the specified data to the image via a Map operation. + size_t mappedRow, mappedSlice; + size_t height; + size_t depth; + size_t imageSize = 0; + + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + height = imageInfo->arraySize; + depth = 1; + imageSize = imageInfo->rowPitch * imageInfo->arraySize; + break; + case CL_MEM_OBJECT_IMAGE1D: + height = depth = 1; + imageSize = imageInfo->rowPitch; + break; + case CL_MEM_OBJECT_IMAGE2D: + height = imageInfo->height; + depth = 1; + imageSize = imageInfo->rowPitch * imageInfo->height; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + height = imageInfo->height; + depth = imageInfo->arraySize; + imageSize = imageInfo->slicePitch * imageInfo->arraySize; + break; + case CL_MEM_OBJECT_IMAGE3D: + height = imageInfo->height; + depth = imageInfo->depth; + imageSize = imageInfo->slicePitch * imageInfo->depth; + break; + } + + size_t origin[ 3 ] = { 0, 0, 0 }; + size_t region[ 3 ] = { imageInfo->width, height, depth }; + + void* mapped = (char*)clEnqueueMapImage(queue, img, CL_TRUE, CL_MAP_WRITE, origin, region, &mappedRow, &mappedSlice, 0, NULL, NULL, error); + if (*error != CL_SUCCESS || !mapped) + { + log_error( "ERROR: Unable to map image for writing: %s\n", IGetErrorString( *error ) ); + return NULL; + } + size_t mappedSlicePad = mappedSlice - (mappedRow * height); + + // Copy the image. + size_t scanlineSize = imageInfo->rowPitch; + size_t sliceSize = imageInfo->slicePitch - scanlineSize * height; + + char* src = (char*)data; + char* dst = (char*)mapped; + + if ((mappedRow == scanlineSize) && ((mappedSlice == imageInfo->slicePitch) || (imageInfo->depth==0 && imageInfo->arraySize==0))) { + // Copy the whole image. + memcpy( dst, src, imageSize ); + } + else { + // Else copy one scan line at a time. + for ( size_t z = 0; z < depth; z++ ) + { + for ( size_t y = 0; y < height; y++ ) + { + memcpy( dst, src, imageInfo->width * get_pixel_size(imageInfo->format) ); + dst += mappedRow; + src += scanlineSize; + } + + // mappedSlicePad is incorrect for 2D images here, but we will exit the z loop before this is a problem. + dst += mappedSlicePad; + src += sliceSize; + } + } + + // Unmap the image. + *error = clEnqueueUnmapMemObject(queue, img, mapped, 0, NULL, NULL); + if (*error != CL_SUCCESS) + { + log_error( "ERROR: Unable to unmap image after writing: %s\n", IGetErrorString( *error ) ); + return NULL; + } + + return img; +} + +static void fill_region_with_value( image_descriptor *imageInfo, void *imageValues, + void *value, const size_t origin[], const size_t region[] ) +{ + size_t pixelSize = get_pixel_size( imageInfo->format ); + + // Get initial pointer + char *destPtr = (char *)imageValues + origin[ 2 ] * imageInfo->slicePitch + + origin[ 1 ] * imageInfo->rowPitch + pixelSize * origin[ 0 ]; + + char *fillColor = (char *)malloc(pixelSize); + memcpy(fillColor, value, pixelSize); + + // Use pixel at origin to fill region. + for( size_t z = 0; z < ( region[ 2 ] > 0 ? region[ 2 ] : 1 ); z++ ) { + char *rowDestPtr = destPtr; + for( size_t y = 0; y < region[ 1 ]; y++ ) { + char *pixelDestPtr = rowDestPtr; + + for( size_t x = 0; x < region[ 0 ]; x++ ) { + memcpy( pixelDestPtr, fillColor, pixelSize ); + pixelDestPtr += pixelSize; + } + rowDestPtr += imageInfo->rowPitch; + } + destPtr += imageInfo->slicePitch; + } + + free(fillColor); +} + +int test_fill_image_generic( cl_device_id device, image_descriptor *imageInfo, + const size_t origin[], const size_t region[], ExplicitType outputType, MTdata d ) +{ + BufferOwningPtr imgData; + BufferOwningPtr imgHost; + + int error; + clMemWrapper image; + + if ( gDebugTrace ) + log_info( " ++ Entering inner test loop...\n" ); + + // Generate some data to test against + size_t dataBytes = 0; + + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + dataBytes = imageInfo->rowPitch; + break; + case CL_MEM_OBJECT_IMAGE2D: + dataBytes = imageInfo->height * imageInfo->rowPitch; + break; + case CL_MEM_OBJECT_IMAGE3D: + dataBytes = imageInfo->depth * imageInfo->slicePitch; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + dataBytes = imageInfo->arraySize * imageInfo->slicePitch; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + dataBytes = imageInfo->arraySize * imageInfo->slicePitch; + break; + } + + if (dataBytes > imgData.getSize()) + { + if ( gDebugTrace ) + log_info( " - Resizing random image data...\n" ); + + generate_random_image_data( imageInfo, imgData, d ); + + imgHost.reset( NULL ); // Free previously allocated memory first. + imgHost.reset(malloc(dataBytes),NULL,0,dataBytes); + if (imgHost == NULL) + { + log_error( "ERROR: Unable to malloc %lu bytes for imgHost\n", dataBytes ); + return -1; + } + } + + // Reset the host verification copy of the data. + memcpy(imgHost, imgData, dataBytes); + + // Construct testing sources + if ( gDebugTrace ) + log_info( " - Creating image...\n" ); + + image = create_image( context, imgData, imageInfo, &error ); + if ( image == NULL ) + return error; + + // Now fill the region defined by origin, region with the pixel value found at origin. + if ( gDebugTrace ) + log_info( " - Filling at %d,%d,%d size %d,%d,%d\n", (int)origin[ 0 ], (int)origin[ 1 ], (int)origin[ 2 ], + (int)region[ 0 ], (int)region[ 1 ], (int)region[ 2 ] ); + + // We need to know the rounding mode, in the case of half to allow the + // pixel pack that generates the verification value to succeed. + if (imageInfo->format->image_channel_data_type == CL_HALF_FLOAT) + DetectFloatToHalfRoundingMode(queue); + + if( outputType == kFloat ) + { + cl_float fillColor[ 4 ]; + read_image_pixel_float( imgHost, imageInfo, origin[ 0 ], origin[ 1 ], origin[ 2 ], fillColor ); + if ( gDebugTrace ) + log_info( " - with value %g, %g, %g, %g\n", fillColor[ 0 ], fillColor[ 1 ], fillColor[ 2 ], fillColor[ 3 ] ); + error = clEnqueueFillImage ( queue, image, fillColor, origin, region, 0, NULL, NULL ); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to fill image at %d,%d,%d size %d,%d,%d! (%s)\n", + (int)origin[ 0 ], (int)origin[ 1 ], (int)origin[ 2 ], + (int)region[ 0 ], (int)region[ 1 ], (int)region[ 2 ], IGetErrorString( error ) ); + return error; + } + + // Write the approriate verification value to the correct region. + void* verificationValue = malloc(get_pixel_size(imageInfo->format)); + pack_image_pixel(fillColor, imageInfo->format, verificationValue); + fill_region_with_value( imageInfo, imgHost, verificationValue, origin, region ); + free(verificationValue); + } + else if( outputType == kInt ) + { + cl_int fillColor[ 4 ]; + read_image_pixel( imgHost, imageInfo, origin[ 0 ], origin[ 1 ], origin[ 2 ], fillColor ); + if ( gDebugTrace ) + log_info( " - with value %d, %d, %d, %d\n", fillColor[ 0 ], fillColor[ 1 ], fillColor[ 2 ], fillColor[ 3 ] ); + error = clEnqueueFillImage ( queue, image, fillColor, origin, region, 0, NULL, NULL ); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to fill image at %d,%d,%d size %d,%d,%d! (%s)\n", + (int)origin[ 0 ], (int)origin[ 1 ], (int)origin[ 2 ], + (int)region[ 0 ], (int)region[ 1 ], (int)region[ 2 ], IGetErrorString( error ) ); + return error; + } + + // Write the approriate verification value to the correct region. + void* verificationValue = malloc(get_pixel_size(imageInfo->format)); + pack_image_pixel(fillColor, imageInfo->format, verificationValue); + fill_region_with_value( imageInfo, imgHost, verificationValue, origin, region ); + free(verificationValue); + } + else // if( outputType == kUInt ) + { + cl_uint fillColor[ 4 ]; + read_image_pixel( imgHost, imageInfo, origin[ 0 ], origin[ 1 ], origin[ 2 ], fillColor ); + if ( gDebugTrace ) + log_info( " - with value %u, %u, %u, %u\n", fillColor[ 0 ], fillColor[ 1 ], fillColor[ 2 ], fillColor[ 3 ] ); + error = clEnqueueFillImage ( queue, image, fillColor, origin, region, 0, NULL, NULL ); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to fill image at %d,%d,%d size %d,%d,%d! (%s)\n", + (int)origin[ 0 ], (int)origin[ 1 ], (int)origin[ 2 ], + (int)region[ 0 ], (int)region[ 1 ], (int)region[ 2 ], IGetErrorString( error ) ); + return error; + } + + // Write the approriate verification value to the correct region. + void* verificationValue = malloc(get_pixel_size(imageInfo->format)); + pack_image_pixel(fillColor, imageInfo->format, verificationValue); + fill_region_with_value( imageInfo, imgHost, verificationValue, origin, region ); + free(verificationValue); + } + + // Map the destination image to verify the results with the host + // copy. The contents of the entire buffer are compared. + if ( gDebugTrace ) + log_info( " - Mapping results...\n" ); + + size_t imageOrigin[ 3 ] = { 0, 0, 0 }; + size_t imageRegion[ 3 ] = { imageInfo->width, 1, 1 }; + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + break; + case CL_MEM_OBJECT_IMAGE2D: + imageRegion[ 1 ] = imageInfo->height; + break; + case CL_MEM_OBJECT_IMAGE3D: + imageRegion[ 1 ] = imageInfo->height; + imageRegion[ 2 ] = imageInfo->depth; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + imageRegion[ 1 ] = imageInfo->arraySize; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + imageRegion[ 1 ] = imageInfo->height; + imageRegion[ 2 ] = imageInfo->arraySize; + break; + } + + size_t mappedRow, mappedSlice; + void* mapped = (char*)clEnqueueMapImage(queue, image, CL_TRUE, CL_MAP_READ, imageOrigin, imageRegion, &mappedRow, &mappedSlice, 0, NULL, NULL, &error); + if (error != CL_SUCCESS) + { + log_error( "ERROR: Unable to map image for verification: %s\n", IGetErrorString( error ) ); + return NULL; + } + + // Verify scanline by scanline, since the pitches are different + char *sourcePtr = imgHost; + char *destPtr = (char*)mapped; + + size_t scanlineSize = imageInfo->width * get_pixel_size( imageInfo->format ); + + if ( gDebugTrace ) + log_info( " - Scanline verification...\n" ); + + size_t thirdDim = 1; + size_t secondDim = 1; + + switch (imageInfo->type) { + case CL_MEM_OBJECT_IMAGE1D: + secondDim = 1; + thirdDim = 1; + break; + case CL_MEM_OBJECT_IMAGE2D: + secondDim = imageInfo->height; + thirdDim = 1; + break; + case CL_MEM_OBJECT_IMAGE3D: + secondDim = imageInfo->height; + thirdDim = imageInfo->depth; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + secondDim = imageInfo->arraySize; + thirdDim = 1; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + secondDim = imageInfo->height; + thirdDim = imageInfo->arraySize; + break; + default: + log_error("Test error: unhandled image type at %s:%d\n",__FILE__,__LINE__); + }; + + // Count the number of bytes successfully matched + size_t total_matched = 0; + + for ( size_t z = 0; z < thirdDim; z++ ) + { + for ( size_t y = 0; y < secondDim; y++ ) + { + // If the data type is 101010 ignore bits 31 and 32 when comparing the row + if (imageInfo->format->image_channel_data_type == CL_UNORM_INT_101010) { + for (size_t w=0;w!=scanlineSize/4;++w) { + ((cl_uint*)sourcePtr)[w] &= 0x3FFFFFFF; + ((cl_uint*)destPtr)[w] &= 0x3FFFFFFF; + } + } + + if (memcmp( sourcePtr, destPtr, scanlineSize ) != 0) + { + log_error( "ERROR: Scanline %d did not verify for image size %d,%d,%d pitch %d (extra %d bytes)\n", (int)y, (int)imageInfo->width, (int)imageInfo->height, (int)thirdDim, (int)imageInfo->rowPitch, (int)imageInfo->rowPitch - (int)imageInfo->width * (int)get_pixel_size( imageInfo->format ) ); + + // Find the first missing pixel + size_t pixel_size = get_pixel_size( imageInfo->format ); + size_t where = 0; + for ( where = 0; where < imageInfo->width; where++ ) + if ( memcmp( sourcePtr + pixel_size * where, destPtr + pixel_size * where, pixel_size) ) + break; + log_error( "Failed at column: %ld ", where ); + switch ( pixel_size ) + { + case 1: + log_error( "*0x%2.2x vs. 0x%2.2x\n", ((cl_uchar*)(sourcePtr + pixel_size * where))[0], ((cl_uchar*)(destPtr + pixel_size * where))[0] ); + break; + case 2: + log_error( "*0x%4.4x vs. 0x%4.4x\n", ((cl_ushort*)(sourcePtr + pixel_size * where))[0], ((cl_ushort*)(destPtr + pixel_size * where))[0] ); + break; + case 3: + log_error( "*{0x%2.2x, 0x%2.2x, 0x%2.2x} vs. {0x%2.2x, 0x%2.2x, 0x%2.2x}\n", + ((cl_uchar*)(sourcePtr + pixel_size * where))[0], ((cl_uchar*)(sourcePtr + pixel_size * where))[1], ((cl_uchar*)(sourcePtr + pixel_size * where))[2], + ((cl_uchar*)(destPtr + pixel_size * where))[0], ((cl_uchar*)(destPtr + pixel_size * where))[1], ((cl_uchar*)(destPtr + pixel_size * where))[2] + ); + break; + case 4: + log_error( "*0x%8.8x vs. 0x%8.8x\n", ((cl_uint*)(sourcePtr + pixel_size * where))[0], ((cl_uint*)(destPtr + pixel_size * where))[0] ); + break; + case 6: + log_error( "*{0x%4.4x, 0x%4.4x, 0x%4.4x} vs. {0x%4.4x, 0x%4.4x, 0x%4.4x}\n", + ((cl_ushort*)(sourcePtr + pixel_size * where))[0], ((cl_ushort*)(sourcePtr + pixel_size * where))[1], ((cl_ushort*)(sourcePtr + pixel_size * where))[2], + ((cl_ushort*)(destPtr + pixel_size * where))[0], ((cl_ushort*)(destPtr + pixel_size * where))[1], ((cl_ushort*)(destPtr + pixel_size * where))[2] + ); + break; + case 8: + log_error( "*0x%16.16llx vs. 0x%16.16llx\n", ((cl_ulong*)(sourcePtr + pixel_size * where))[0], ((cl_ulong*)(destPtr + pixel_size * where))[0] ); + break; + case 12: + log_error( "*{0x%8.8x, 0x%8.8x, 0x%8.8x} vs. {0x%8.8x, 0x%8.8x, 0x%8.8x}\n", + ((cl_uint*)(sourcePtr + pixel_size * where))[0], ((cl_uint*)(sourcePtr + pixel_size * where))[1], ((cl_uint*)(sourcePtr + pixel_size * where))[2], + ((cl_uint*)(destPtr + pixel_size * where))[0], ((cl_uint*)(destPtr + pixel_size * where))[1], ((cl_uint*)(destPtr + pixel_size * where))[2] + ); + break; + case 16: + log_error( "*{0x%8.8x, 0x%8.8x, 0x%8.8x, 0x%8.8x} vs. {0x%8.8x, 0x%8.8x, 0x%8.8x, 0x%8.8x}\n", + ((cl_uint*)(sourcePtr + pixel_size * where))[0], ((cl_uint*)(sourcePtr + pixel_size * where))[1], ((cl_uint*)(sourcePtr + pixel_size * where))[2], ((cl_uint*)(sourcePtr + pixel_size * where))[3], + ((cl_uint*)(destPtr + pixel_size * where))[0], ((cl_uint*)(destPtr + pixel_size * where))[1], ((cl_uint*)(destPtr + pixel_size * where))[2], ((cl_uint*)(destPtr + pixel_size * where))[3] + ); + break; + default: + log_error( "Don't know how to print pixel size of %ld\n", pixel_size ); + break; + } + + return -1; + } + + total_matched += scanlineSize; + sourcePtr += imageInfo->rowPitch; + destPtr += mappedRow; + } + + sourcePtr += imageInfo->slicePitch - ( imageInfo->rowPitch * (imageInfo->height > 0 ? imageInfo->height : 1) ); + destPtr += mappedSlice - ( mappedRow * (imageInfo->height > 0 ? imageInfo->height : 1) ); + } + + // Unmap the image. + error = clEnqueueUnmapMemObject(queue, image, mapped, 0, NULL, NULL); + if (error != CL_SUCCESS) + { + log_error( "ERROR: Unable to unmap image after verify: %s\n", IGetErrorString( error ) ); + return NULL; + } + + imgHost.reset(0x0); + imgData.reset(0x0); + + size_t expected_bytes = scanlineSize * imageRegion[1] * imageRegion[2]; + return (total_matched == expected_bytes) ? 0 : -1; +} diff --git a/test_conformance/images/clFillImage/test_loops.cpp b/test_conformance/images/clFillImage/test_loops.cpp new file mode 100644 index 00000000..c5cbc4a4 --- /dev/null +++ b/test_conformance/images/clFillImage/test_loops.cpp @@ -0,0 +1,327 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +extern bool gDebugTrace; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern int gTypesToTest; +extern int gNormalizedModeToUse; +extern cl_channel_type gChannelTypeToUse; +extern cl_channel_order gChannelOrderToUse; +extern cl_command_queue queue; +extern cl_context context; + + +extern int test_fill_image_set_1D( cl_device_id device, cl_image_format *format, ExplicitType outputType ); +extern int test_fill_image_set_2D( cl_device_id device, cl_image_format *format, ExplicitType outputType ); +extern int test_fill_image_set_3D( cl_device_id device, cl_image_format *format, ExplicitType outputType ); +extern int test_fill_image_set_1D_array( cl_device_id device, cl_image_format *format, ExplicitType outputType ); +extern int test_fill_image_set_2D_array( cl_device_id device, cl_image_format *format, ExplicitType outputType ); + + +int filter_formats( cl_image_format *formatList, bool *filterFlags, unsigned int formatCount, cl_channel_type *channelDataTypesToFilter ) +{ + int numSupported = 0; + for ( unsigned int j = 0; j < formatCount; j++ ) + { + // If this format has been previously filtered, remove the filter + if ( filterFlags[ j ] ) + filterFlags[ j ] = false; + + // Have we already discarded this via the command line? + if ( gChannelTypeToUse != (cl_channel_type)-1 && gChannelTypeToUse != formatList[ j ].image_channel_data_type ) + { + filterFlags[ j ] = true; + continue; + } + + // Have we already discarded the channel order via the command line? + if ( gChannelOrderToUse != (cl_channel_order)-1 && gChannelOrderToUse != formatList[ j ].image_channel_order ) + { + filterFlags[ j ] = true; + continue; + } + + // Is given format standard channel order and type given by spec. We don't want to test it if this is vendor extension + if( !IsChannelOrderSupported( formatList[ j ].image_channel_order ) || !IsChannelTypeSupported( formatList[ j ].image_channel_data_type ) ) + { + filterFlags[ j ] = true; + continue; + } + + // We don't filter by channel type + if( !channelDataTypesToFilter ) + { + numSupported++; + continue; + } + + // Is the format supported? + int i; + for ( i = 0; channelDataTypesToFilter[ i ] != (cl_channel_type)-1; i++ ) + { + if ( formatList[ j ].image_channel_data_type == channelDataTypesToFilter[ i ] ) + { + numSupported++; + break; + } + } + if ( channelDataTypesToFilter[ i ] == (cl_channel_type)-1 ) + { + // Format is NOT supported, so mark it as such + filterFlags[ j ] = true; + } + + + } + return numSupported; +} + + +int get_format_list( cl_device_id device, cl_mem_object_type image_type, cl_image_format * &outFormatList, + unsigned int &outFormatCount, cl_mem_flags flags ) +{ + int error; + + cl_image_format tempList[ 128 ]; + error = clGetSupportedImageFormats( context, (cl_mem_flags)flags, + image_type, 128, tempList, &outFormatCount ); + test_error( error, "Unable to get count of supported image formats" ); + + outFormatList = new cl_image_format[ outFormatCount ]; + error = clGetSupportedImageFormats( context, (cl_mem_flags)flags, + image_type, outFormatCount, outFormatList, NULL ); + test_error( error, "Unable to get list of supported image formats" ); + return 0; +} + + +int test_image_type( cl_device_id device, MethodsToTest testMethod, cl_mem_flags flags ) +{ + const char *name; + cl_mem_object_type imageType; + + if ( testMethod == k1D ) + { + name = "1D Image Fill"; + imageType = CL_MEM_OBJECT_IMAGE1D; + } + else if ( testMethod == k2D ) + { + name = "2D Image Fill"; + imageType = CL_MEM_OBJECT_IMAGE2D; + } + else if ( testMethod == k1DArray ) + { + name = "1D Image Array Fill"; + imageType = CL_MEM_OBJECT_IMAGE1D_ARRAY; + } + else if ( testMethod == k2DArray ) + { + name = "2D Image Array Fill"; + imageType = CL_MEM_OBJECT_IMAGE2D_ARRAY; + } + else if ( testMethod == k3D ) + { + name = "3D Image Fill"; + imageType = CL_MEM_OBJECT_IMAGE3D; + } + + log_info( "Running %s tests...\n", name ); + + int ret = 0; + + // Grab the list of supported image formats + cl_image_format *formatList; + bool *filterFlags; + unsigned int numFormats; + + if ( get_format_list( device, imageType, formatList, numFormats, flags ) ) + return -1; + + filterFlags = new bool[ numFormats ]; + if ( filterFlags == NULL ) + { + log_error( "ERROR: Out of memory allocating filter flags list!\n" ); + return -1; + } + memset( filterFlags, 0, sizeof( bool ) * numFormats ); + + /////// float tests /////// + + if( gTypesToTest & kTestFloat ) + { + cl_channel_type floatFormats[] = { CL_UNORM_SHORT_565, CL_UNORM_SHORT_555, CL_UNORM_INT_101010, +#ifdef OBSOLETE_FORAMT + CL_UNORM_SHORT_565_REV, CL_UNORM_SHORT_555_REV, CL_UNORM_INT_8888, CL_UNORM_INT_8888_REV, CL_UNORM_INT_101010_REV, +#endif +#ifdef CL_SFIXED14_APPLE + CL_SFIXED14_APPLE, +#endif + CL_UNORM_INT8, CL_SNORM_INT8, + CL_UNORM_INT16, CL_SNORM_INT16, CL_FLOAT, CL_HALF_FLOAT, (cl_channel_type)-1 }; + if( filter_formats( formatList, filterFlags, numFormats, floatFormats ) == 0 ) + { + log_info( "No formats supported for float type\n" ); + } + else + { + // Run the format list + for ( unsigned int i = 0; i < numFormats; i++ ) + { + int test_return = 0; + if ( filterFlags[i] ) + { + continue; + } + + print_header( &formatList[ i ], false ); + + gTestCount++; + + if ( testMethod == k1D ) + test_return = test_fill_image_set_1D( device, &formatList[ i ], kFloat ); + else if ( testMethod == k2D ) + test_return = test_fill_image_set_2D( device, &formatList[ i ], kFloat ); + else if ( testMethod == k1DArray ) + test_return = test_fill_image_set_1D_array( device, &formatList[ i ], kFloat ); + else if ( testMethod == k2DArray ) + test_return = test_fill_image_set_2D_array( device, &formatList[ i ], kFloat ); + else if ( testMethod == k3D ) + test_return = test_fill_image_set_3D( device, &formatList[ i ], kFloat ); + + if (test_return) + { + gTestFailure++; + log_error( "FAILED: " ); + print_header( &formatList[ i ], true ); + log_info( "\n" ); + } + + ret += test_return; + } + } + } + + /////// int tests /////// + if( gTypesToTest & kTestInt ) + { + cl_channel_type intFormats[] = { CL_SIGNED_INT8, CL_SIGNED_INT16, CL_SIGNED_INT32, (cl_channel_type)-1 }; + if( filter_formats( formatList, filterFlags, numFormats, intFormats ) == 0 ) + { + log_info( "No formats supported for integer type\n" ); + } + else + { + // Run the format list + for ( unsigned int i = 0; i < numFormats; i++ ) + { + int test_return = 0; + if ( filterFlags[i] ) + { + continue; + } + + print_header( &formatList[ i ], false ); + + gTestCount++; + + if ( testMethod == k1D ) + test_return = test_fill_image_set_1D( device, &formatList[ i ], kInt ); + else if ( testMethod == k2D ) + test_return = test_fill_image_set_2D( device, &formatList[ i ], kInt ); + else if ( testMethod == k1DArray ) + test_return = test_fill_image_set_1D_array( device, &formatList[ i ], kInt ); + else if ( testMethod == k2DArray ) + test_return = test_fill_image_set_2D_array( device, &formatList[ i ], kInt ); + else if ( testMethod == k3D ) + test_return = test_fill_image_set_3D( device, &formatList[ i ], kInt ); + + if (test_return) { + gTestFailure++; + log_error( "FAILED: " ); + print_header( &formatList[ i ], true ); + log_info( "\n" ); + } + + ret += test_return; + } + } + } + + /////// uint tests /////// + + if( gTypesToTest & kTestUInt ) + { + cl_channel_type uintFormats[] = { CL_UNSIGNED_INT8, CL_UNSIGNED_INT16, CL_UNSIGNED_INT32, (cl_channel_type)-1 }; + if( filter_formats( formatList, filterFlags, numFormats, uintFormats ) == 0 ) + { + log_info( "No formats supported for unsigned int type\n" ); + } + else + { + // Run the format list + for ( unsigned int i = 0; i < numFormats; i++ ) + { + int test_return = 0; + if ( filterFlags[i] ) + { + continue; + } + + print_header( &formatList[ i ], false ); + + gTestCount++; + + if ( testMethod == k1D ) + test_return = test_fill_image_set_1D( device, &formatList[ i ], kUInt ); + else if ( testMethod == k2D ) + test_return = test_fill_image_set_2D( device, &formatList[ i ], kUInt ); + else if ( testMethod == k1DArray ) + test_return = test_fill_image_set_1D_array( device, &formatList[ i ], kUInt ); + else if ( testMethod == k2DArray ) + test_return = test_fill_image_set_2D_array( device, &formatList[ i ], kUInt ); + else if ( testMethod == k3D ) + test_return = test_fill_image_set_3D( device, &formatList[ i ], kUInt ); + + if (test_return) { + gTestFailure++; + log_error( "FAILED: " ); + print_header( &formatList[ i ], true ); + log_info( "\n" ); + } + + ret += test_return; + } + } + } + + delete filterFlags; + delete formatList; + + return ret; +} + + +int test_image_set( cl_device_id device, MethodsToTest testMethod ) +{ + int ret = 0; + + ret += test_image_type( device, testMethod, CL_MEM_READ_ONLY ); + + return ret; +} diff --git a/test_conformance/images/clGetInfo/CMakeLists.txt b/test_conformance/images/clGetInfo/CMakeLists.txt new file mode 100644 index 00000000..df5f781a --- /dev/null +++ b/test_conformance/images/clGetInfo/CMakeLists.txt @@ -0,0 +1,22 @@ +set(MODULE_NAME CL_GET_INFO) + +set(${MODULE_NAME}_SOURCES + main.cpp + test_1D_2D_array.cpp + test_1D.cpp + test_2D.cpp + test_loops.cpp + test_3D.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/threadTesting.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/imageHelpers.cpp + ../../../test_common/harness/mt19937.c + ../../../test_common/harness/conversions.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/typeWrappers.cpp + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/images/clGetInfo/Jamfile b/test_conformance/images/clGetInfo/Jamfile new file mode 100644 index 00000000..9e8ac8d3 --- /dev/null +++ b/test_conformance/images/clGetInfo/Jamfile @@ -0,0 +1,18 @@ +project + : requirements +# gcc:-xc++ +# msvc:"/TP" + ; + +exe test_cl_get_info + : main.cpp + test_2D.cpp + test_3D.cpp + test_loops.cpp + ; + +install dist + : test_cl_get_info + : debug:$(DIST)/debug/tests/test_conformance/images/clGetInfo + release:$(DIST)/release/tests/test_conformance/images/clGetInfo + ; diff --git a/test_conformance/images/clGetInfo/Makefile b/test_conformance/images/clGetInfo/Makefile new file mode 100644 index 00000000..eb8b3cd0 --- /dev/null +++ b/test_conformance/images/clGetInfo/Makefile @@ -0,0 +1,50 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.cpp \ + test_1D.cpp \ + test_2D.cpp \ + test_1D_2D_array.cpp \ + test_loops.cpp \ + test_3D.cpp \ + ../../../test_common/harness/errorHelpers.c \ + ../../../test_common/harness/threadTesting.c \ + ../../../test_common/harness/kernelHelpers.c \ + ../../../test_common/harness/imageHelpers.cpp \ + ../../../test_common/harness/conversions.c \ + ../../../test_common/harness/testHarness.c \ + ../../../test_common/harness/mt19937.c \ + ../../../test_common/harness/typeWrappers.cpp + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = +HEADERS = +TARGET = test_cl_get_info +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os +CC = c++ +CXX = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/images/clGetInfo/main.cpp b/test_conformance/images/clGetInfo/main.cpp new file mode 100644 index 00000000..d61766f1 --- /dev/null +++ b/test_conformance/images/clGetInfo/main.cpp @@ -0,0 +1,287 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../../test_common/harness/compat.h" + +#include +#include + +#if !defined(_WIN32) +#include +#include +#endif + +#include "../testBase.h" + +bool gDebugTrace = false, gTestSmallImages = false, gTestMaxImages = false, gTestRounding = false; +int gTypesToTest = 0; +cl_channel_type gChannelTypeToUse = (cl_channel_type)-1; +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +cl_command_queue queue; +cl_context context; + +extern int test_image_set( cl_device_id device, cl_mem_object_type image_type ); + +#define MAX_ALLOWED_STD_DEVIATION_IN_MB 8.0 + +void printUsage( const char *execName ) +{ + const char *p = strrchr( execName, '/' ); + if( p != NULL ) + execName = p + 1; + + log_info( "Usage: %s [debug_trace] [1D|2D|3D|1Darray|2Darray] [small_images|max_images] [randomize]\n", execName ); + log_info( "Where:\n" ); + log_info( "\t1D - Only test 1D images\n" ); + log_info( "\t2D - Only test 2D images\n" ); + log_info( "\t3D - Only test 3D images\n" ); + log_info( "\t1Darray - Only test 1D image arrays\n" ); + log_info( "\t2Darray - Only test 2D image arrays\n" ); + log_info( "\n" ); + log_info( "\tdebug_trace - Enables additional debug info logging (default no debug info)\n" ); + log_info( "\n" ); + log_info( "\tsmall_images - Runs every format through a loop of widths 1-13 and heights 1-9, instead of random sizes (default test random sizes)\n" ); + log_info( "\tmax_images - Runs every format through a set of size combinations with the max values, max values - 1, and max values / 128 (default test random sizes)\n" ); + log_info( "\n" ); + log_info( "\trandomize - Seed random number generator (default do not seed random number generator)\n" ); +} + + +int main(int argc, const char *argv[]) +{ + cl_platform_id platform; + cl_device_id device; + cl_channel_type chanType; + char str[ 128 ]; + bool test3DImages = true; + bool randomize = false; + int testMethods = 0; + + test_start(); + + checkDeviceTypeOverride( &gDeviceType ); + + // Parse arguments + for( int i = 1; i < argc; i++ ) + { + strncpy( str, argv[ i ], sizeof( str ) - 1 ); + + if( strcmp( str, "cpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_CPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_CPU; + else if( strcmp( str, "gpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_GPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_GPU; + else if( strcmp( str, "accelerator" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( str, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_DEFAULT; + + else if( strcmp( str, "debug_trace" ) == 0 ) + gDebugTrace = true; + + else if( strcmp( str, "small_images" ) == 0 ) + gTestSmallImages = true; + else if( strcmp( str, "max_images" ) == 0 ) + gTestMaxImages = true; + + else if( strcmp( str, "randomize" ) == 0 ) + randomize = true; + + else if( strcmp( str, "1D" ) == 0 ) + testMethods |= k1D; + else if( strcmp( str, "2D" ) == 0 ) + testMethods |= k2D; + else if( strcmp( str, "3D" ) == 0 ) + testMethods |= k3D; + else if( strcmp( str, "1Darray" ) == 0 ) + testMethods |= k1DArray; + else if( strcmp( str, "2Darray" ) == 0 ) + testMethods |= k2DArray; + + else if( strcmp( str, "help" ) == 0 || strcmp( str, "?" ) == 0 ) + { + printUsage( argv[ 0 ] ); + return -1; + } + else if( ( chanType = get_channel_type_from_name( str ) ) != (cl_channel_type)-1 ) + gChannelTypeToUse = chanType; + else + { + log_error( "ERROR: Unknown argument %d: %s. Exiting....\n", i, str ); + return -1; + } + + } + + if ( testMethods == 0 ) + testMethods = k1D | k2D | k3D | k1DArray | k2DArray; + + // Seed the random # generators + if( randomize ) + { + gRandomSeed = (cl_uint) time( NULL ); + log_info( "Random seed: %u.\n", gRandomSeed ); + gReSeed = 1; + } + + int error; + // Get our platform + error = clGetPlatformIDs(1, &platform, NULL); + if( error ) + { + print_error( error, "Unable to get platform" ); + test_finish(); + return -1; + } + + // Get our device + unsigned int num_devices; + error = clGetDeviceIDs(platform, gDeviceType, 0, NULL, &num_devices); + if( error ) + { + print_error( error, "Unable to get number of devices" ); + test_finish(); + return -1; + } + + uint32_t gDeviceIndex = 0; + const char* device_index_env = getenv("CL_DEVICE_INDEX"); + if (device_index_env) { + if (device_index_env) { + gDeviceIndex = atoi(device_index_env); + } + + if (gDeviceIndex >= num_devices) { + vlog("Specified CL_DEVICE_INDEX=%d out of range, using index 0.\n", gDeviceIndex); + gDeviceIndex = 0; + } + } + + cl_device_id *gDeviceList = (cl_device_id *)malloc( num_devices * sizeof( cl_device_id ) ); + error = clGetDeviceIDs(platform, gDeviceType, num_devices, gDeviceList, NULL); + if( error ) + { + print_error( error, "Unable to get devices" ); + free( gDeviceList ); + test_finish(); + return -1; + } + + device = gDeviceList[gDeviceIndex]; + free( gDeviceList ); + + log_info( "Using " ); + if( printDeviceHeader( device ) != CL_SUCCESS ) + { + test_finish(); + return -1; + } + + // Check for image support + if(checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) { + log_info("Device does not support images. Skipping test.\n"); + test_finish(); + return 0; + } + + // Check for 3D image support + { + size_t max_height, max_depth, max_width; + max_height = max_depth = max_width = -1L; + + if( (error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( max_width ), &max_width, NULL ) )) + { print_error( error, "FAILURE: Unable to get CL_DEVICE_IMAGE3D_MAX_WIDTH" ); test_finish(); return -1; } + if( (error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( max_height ), &max_height, NULL ) )) + { print_error( error, "FAILURE: Unable to get CL_DEVICE_IMAGE3D_MAX_HEIGHT"); test_finish(); return -1; } + if( (error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( max_depth ), &max_depth, NULL ) )) + { print_error( error, "FAILURE: Unable to get CL_DEVICE_IMAGE3D_MAX_DEPTH" ); test_finish(); return -1; } + + if( 0 == (max_height | max_depth | max_width) ) + { + char deviceProfile[128]; + error = clGetDeviceInfo( device, CL_DEVICE_PROFILE, sizeof( deviceProfile ), deviceProfile, NULL ); + if( error ) + { + print_error( error, "Unable to get device profile" ); + test_finish(); + return -1; + } + + if( strcmp( deviceProfile, "EMBEDDED_PROFILE" ) ) + { + log_error( "FAILURE: non-Embedded device with image support does not support 3D images." ); + test_finish(); + return -1; + } + + test3DImages = false; + } + } + + // Create a context to test with + context = clCreateContext( NULL, 1, &device, notify_callback, NULL, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create testing context" ); + test_finish(); + return -1; + } + + // Create a queue against the context + queue = clCreateCommandQueueWithProperties( context, device, 0, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create testing command queue" ); + test_finish(); + return -1; + } + + if( gTestSmallImages ) + log_info( "Note: Using small test images\n" ); + + // Run the test now + int ret = 0; + if (testMethods & k1D) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE1D ); + if (testMethods & k2D) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE2D ); + if (test3DImages && (testMethods & k3D)) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE3D ); + if (testMethods & k1DArray) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE1D_ARRAY ); + if (testMethods & k2DArray) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE2D_ARRAY ); + + if (gTestFailure == 0) { + if (gTestCount > 1) + log_info("PASSED %d of %d tests.\n", gTestCount, gTestCount); + else + log_info("PASSED test.\n"); + } else if (gTestFailure > 0) { + if (gTestCount > 1) + log_error("FAILED %d of %d tests.\n", gTestFailure, gTestCount); + else + log_error("FAILED test.\n"); + } + + // Clean up + clReleaseCommandQueue(queue); + clReleaseContext(context); + test_finish(); + + if (gTestFailure > 0) + return gTestFailure; + + return ret; +} diff --git a/test_conformance/images/clGetInfo/test_1D.cpp b/test_conformance/images/clGetInfo/test_1D.cpp new file mode 100644 index 00000000..8a484804 --- /dev/null +++ b/test_conformance/images/clGetInfo/test_1D.cpp @@ -0,0 +1,138 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gTestSmallImages, gTestMaxImages; + +extern int test_get_image_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d, cl_mem_flags flags, size_t row_pitch, size_t slice_pitch ); + + +int test_get_image_info_1D( cl_device_id device, cl_image_format *format, cl_mem_flags flags ) +{ + size_t maxWidth; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + cl_mem_flags all_host_ptr_flags[5] = { + flags, + CL_MEM_ALLOC_HOST_PTR | flags, + CL_MEM_COPY_HOST_PTR | flags, + CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR | flags, + CL_MEM_USE_HOST_PTR | flags + }; + + memset(&imageInfo, 0x0, sizeof(image_descriptor)); + imageInfo.type = CL_MEM_OBJECT_IMAGE1D; + imageInfo.format = format; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 1D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++) + { + if( gDebugTrace ) + log_info( " at size %d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch ); + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) ) + return -1; + if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) ) + return -1; + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + log_info( "Testing %d x 1\n", (int)sizes[ idx ][ 0 ]); + for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++) + { + if( gDebugTrace ) + log_info( " at max size %d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch ); + if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) ) + return -1; + if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL + if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) ) + return -1; + } + } + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth; + + do { + extraWidth++; + imageInfo.rowPitch += extraWidth; + } while ((imageInfo.rowPitch % pixelSize) != 0); + + size = (cl_ulong)imageInfo.rowPitch * 4; + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++) + { + if( gDebugTrace ) + log_info( " at size %d (flags[%u] 0x%x pitch %d) out of %d\n", (int)imageInfo.width, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch, (int)maxWidth ); + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) ) + return -1; + if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) ) + return -1; + } + } + } + } + + return 0; +} diff --git a/test_conformance/images/clGetInfo/test_1D_2D_array.cpp b/test_conformance/images/clGetInfo/test_1D_2D_array.cpp new file mode 100644 index 00000000..132a9c32 --- /dev/null +++ b/test_conformance/images/clGetInfo/test_1D_2D_array.cpp @@ -0,0 +1,279 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gTestSmallImages, gTestMaxImages; + +extern int test_get_image_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d, cl_mem_flags flags, size_t row_pitch, size_t slice_pitch ); + +int test_get_image_info_1D_array( cl_device_id device, cl_image_format *format, cl_mem_flags flags ) +{ + size_t maxWidth, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + + cl_mem_flags all_host_ptr_flags[5] = { + flags, + CL_MEM_ALLOC_HOST_PTR | flags, + CL_MEM_COPY_HOST_PTR | flags, + CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR | flags, + CL_MEM_USE_HOST_PTR | flags + }; + + memset(&imageInfo, 0x0, sizeof(image_descriptor)); + imageInfo.format = format; + imageInfo.type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 1D array size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.rowPitch; + for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ ) + { + for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++) + { + if( gDebugTrace ) + log_info( " at size %d,%d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, (int)imageInfo.arraySize, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch ); + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) ) + return -1; + if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) ) + return -1; + } + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, maxArraySize, maxAllocSize, memSize, + CL_MEM_OBJECT_IMAGE1D_ARRAY, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.arraySize = sizes [ idx] [ 2 ]; + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.rowPitch; + + log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ] ); + for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++) + { + if( gDebugTrace ) + log_info( " at max size %d,%d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, (int)imageInfo.arraySize, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch ); + if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) ) + return -1; + if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL + if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) ) + return -1; + } + } + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth; + + imageInfo.slicePitch = imageInfo.rowPitch; + + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4; + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++) + { + if( gDebugTrace ) + log_info( " at size %d,%d (flags[%u] 0x%x pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch, (int)maxWidth, (int)maxArraySize ); + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) ) + return -1; + if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) ) + return -1; + } + } + } + } + + return 0; +} + + +int test_get_image_info_2D_array( cl_device_id device, cl_image_format *format, cl_mem_flags flags ) +{ + size_t maxWidth, maxHeight, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + cl_mem_flags all_host_ptr_flags[5] = { + flags, + CL_MEM_ALLOC_HOST_PTR | flags, + CL_MEM_COPY_HOST_PTR | flags, + CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR | flags, + CL_MEM_USE_HOST_PTR | flags + }; + + memset(&imageInfo, 0x0, sizeof(image_descriptor)); + imageInfo.format = format; + imageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 1D array size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ ) + { + for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++) + { + if( gDebugTrace ) + log_info( " at size %d,%d,%d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch ); + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) ) + return -1; + if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) ) + return -1; + } + } + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D_ARRAY, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.arraySize = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + + log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++) + { + if( gDebugTrace ) + log_info( " at max size %d,%d,%d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch ); + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) ) + return -1; + if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) ) + return -1; + } + } + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth; + + do { + extraWidth++; + imageInfo.rowPitch += extraWidth; + } while ((imageInfo.rowPitch % pixelSize) != 0); + + size_t extraHeight = (int)random_log_in_range( 0, 8, seed ); + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight); + + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4; + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++) + { + if( gDebugTrace ) + log_info( " at size %d,%d,%d (flags[%u] 0x%x pitch %d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight, (int)maxArraySize ); + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) ) + return -1; + if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) ) + return -1; + } + } + } + } + + return 0; +} diff --git a/test_conformance/images/clGetInfo/test_2D.cpp b/test_conformance/images/clGetInfo/test_2D.cpp new file mode 100644 index 00000000..20933581 --- /dev/null +++ b/test_conformance/images/clGetInfo/test_2D.cpp @@ -0,0 +1,385 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gTestSmallImages, gTestMaxImages; +extern cl_command_queue queue; +extern cl_context context; + + +int test_get_image_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d, cl_mem_flags flags, size_t row_pitch, size_t slice_pitch ) +{ + int error; + clMemWrapper image; + cl_image_desc imageDesc; + void *host_ptr = NULL; + + // Generate some data to test against + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + if (flags & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { + host_ptr = (char *)imageValues; + } + + memset(&imageDesc, 0x0, sizeof(cl_image_desc)); + imageDesc.image_type = imageInfo->type; + imageDesc.image_width = imageInfo->width; + imageDesc.image_height = imageInfo->height; + imageDesc.image_depth = imageInfo->depth; + imageDesc.image_array_size = imageInfo->arraySize; + imageDesc.image_row_pitch = row_pitch; + imageDesc.image_slice_pitch = slice_pitch; + + // Construct testing source + // Note: for now, just reset the pitches, since they only can actually be different + // if we use CL_MEM_USE_HOST_PTR or CL_MEM_COPY_HOST_PTR + imageInfo->rowPitch = imageInfo->width * get_pixel_size( imageInfo->format ); + imageInfo->slicePitch = 0; + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + if ( gDebugTrace ) + log_info( " - Creating 1D image %d with flags=0x%lx row_pitch=%d slice_pitch=%d host_ptr=%p...\n", (int)imageInfo->width, (unsigned long)flags, (int)row_pitch, (int)slice_pitch, host_ptr ); + break; + case CL_MEM_OBJECT_IMAGE2D: + if ( gDebugTrace ) + log_info( " - Creating 2D image %d by %d with flags=0x%lx row_pitch=%d slice_pitch=%d host_ptr=%p...\n", (int)imageInfo->width, (int)imageInfo->height, (unsigned long)flags, (int)row_pitch, (int)slice_pitch, host_ptr ); + break; + case CL_MEM_OBJECT_IMAGE3D: + imageInfo->slicePitch = imageInfo->rowPitch * imageInfo->height; + if ( gDebugTrace ) + log_info( " - Creating 3D image %d by %d by %d with flags=0x%lx row_pitch=%d slice_pitch=%d host_ptr=%p...\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, (unsigned long)flags, (int)row_pitch, (int)slice_pitch, host_ptr ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + imageInfo->slicePitch = imageInfo->rowPitch; + if ( gDebugTrace ) + log_info( " - Creating 1D image array %d by %d with flags=0x%lx row_pitch=%d slice_pitch=%d host_ptr=%p...\n", (int)imageInfo->width, (int)imageInfo->arraySize, (unsigned long)flags, (int)row_pitch, (int)slice_pitch, host_ptr ); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + imageInfo->slicePitch = imageInfo->rowPitch * imageInfo->height; + if ( gDebugTrace ) + log_info( " - Creating 2D image array %d by %d by %d with flags=0x%lx row_pitch=%d slice_pitch=%d host_ptr=%p...\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, (unsigned long)flags, (int)row_pitch, (int)slice_pitch, host_ptr ); + break; + } + + image = clCreateImage(context, flags, imageInfo->format, &imageDesc, host_ptr, &error); + if( image == NULL ) + { + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + log_error( "ERROR: Unable to create 1D image of size %d (%s)", (int)imageInfo->width, IGetErrorString( error ) ); + break; + case CL_MEM_OBJECT_IMAGE2D: + log_error( "ERROR: Unable to create 2D image of size %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, IGetErrorString( error ) ); + break; + case CL_MEM_OBJECT_IMAGE3D: + log_error( "ERROR: Unable to create 3D image of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, IGetErrorString( error ) ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + log_error( "ERROR: Unable to create 1D image array of size %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->arraySize, IGetErrorString( error ) ); + break; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + log_error( "ERROR: Unable to create 2D image array of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, IGetErrorString( error ) ); + break; + } + return -1; + } + + // Get info of the image and verify each item is correct + cl_image_format outFormat; + error = clGetImageInfo( image, CL_IMAGE_FORMAT, sizeof( outFormat ), &outFormat, NULL ); + test_error( error, "Unable to get image info (format)" ); + if( outFormat.image_channel_order != imageInfo->format->image_channel_order || + outFormat.image_channel_data_type != imageInfo->format->image_channel_data_type ) + { + log_error( "ERROR: image format returned is invalid! (expected %s:%s, got %s:%s (%d:%d))\n", + GetChannelOrderName( imageInfo->format->image_channel_order ), GetChannelTypeName( imageInfo->format->image_channel_data_type ), + GetChannelOrderName( outFormat.image_channel_order ), GetChannelTypeName( outFormat.image_channel_data_type ), + (int)outFormat.image_channel_order, (int)outFormat.image_channel_data_type ); + return 1; + } + + size_t outElementSize; + error = clGetImageInfo( image, CL_IMAGE_ELEMENT_SIZE, sizeof( outElementSize ), &outElementSize, NULL ); + test_error( error, "Unable to get image info (element size)" ); + if( outElementSize != get_pixel_size( imageInfo->format ) ) + { + log_error( "ERROR: image element size returned is invalid! (expected %d, got %d)\n", + (int)get_pixel_size( imageInfo->format ), (int)outElementSize ); + return 1; + } + + size_t outRowPitch; + error = clGetImageInfo( image, CL_IMAGE_ROW_PITCH, sizeof( outRowPitch ), &outRowPitch, NULL ); + test_error( error, "Unable to get image info (row pitch)" ); + + size_t outSlicePitch; + error = clGetImageInfo( image, CL_IMAGE_SLICE_PITCH, sizeof( outSlicePitch ), &outSlicePitch, NULL ); + test_error( error, "Unable to get image info (row pitch)" ); + if( imageInfo->type == CL_MEM_OBJECT_IMAGE1D && outSlicePitch != 0 ) + { + log_error( "ERROR: slice pitch returned is invalid! (expected %d, got %d)\n", + (int)0, (int)outSlicePitch ); + return 1; + } + + size_t outWidth; + error = clGetImageInfo( image, CL_IMAGE_WIDTH, sizeof( outWidth ), &outWidth, NULL ); + test_error( error, "Unable to get image info (width)" ); + if( outWidth != imageInfo->width ) + { + log_error( "ERROR: image width returned is invalid! (expected %d, got %d)\n", + (int)imageInfo->width, (int)outWidth ); + return 1; + } + + size_t required_height; + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + required_height = 0; + break; + case CL_MEM_OBJECT_IMAGE2D: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + case CL_MEM_OBJECT_IMAGE3D: + required_height = imageInfo->height; + break; + } + + size_t outHeight; + error = clGetImageInfo( image, CL_IMAGE_HEIGHT, sizeof( outHeight ), &outHeight, NULL ); + test_error( error, "Unable to get image info (height)" ); + if( outHeight != required_height ) + { + log_error( "ERROR: image height returned is invalid! (expected %d, got %d)\n", + (int)required_height, (int)outHeight ); + return 1; + } + + size_t required_depth; + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + case CL_MEM_OBJECT_IMAGE2D: + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + required_depth = 0; + break; + case CL_MEM_OBJECT_IMAGE3D: + required_depth = imageInfo->depth; + break; + } + + size_t outDepth; + error = clGetImageInfo( image, CL_IMAGE_DEPTH, sizeof( outDepth ), &outDepth, NULL ); + test_error( error, "Unable to get image info (depth)" ); + if( outDepth != required_depth ) + { + log_error( "ERROR: image depth returned is invalid! (expected %d, got %d)\n", + (int)required_depth, (int)outDepth ); + return 1; + } + + size_t required_array_size; + switch (imageInfo->type) + { + case CL_MEM_OBJECT_IMAGE1D: + case CL_MEM_OBJECT_IMAGE2D: + case CL_MEM_OBJECT_IMAGE3D: + required_array_size = 0; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + required_array_size = imageInfo->arraySize; + break; + } + + size_t outArraySize; + error = clGetImageInfo( image, CL_IMAGE_ARRAY_SIZE, sizeof( outArraySize ), &outArraySize, NULL ); + test_error( error, "Unable to get image info (array size)" ); + if( outArraySize != required_array_size ) + { + log_error( "ERROR: image array size returned is invalid! (expected %d, got %d)\n", + (int)required_array_size, (int)outArraySize ); + return 1; + } + + cl_mem outBuffer; + error = clGetImageInfo( image, CL_IMAGE_BUFFER, sizeof( outBuffer ), &outBuffer, NULL ); + test_error( error, "Unable to get image info (buffer)" ); + if (imageInfo->type == CL_MEM_OBJECT_IMAGE1D_BUFFER) { + if (outBuffer != imageInfo->buffer) { + log_error( "ERROR: cl_mem returned is invalid! (expected %p, got %p)\n", + imageInfo->buffer, outBuffer ); + return 1; + } + } else { + if (outBuffer != (cl_mem)NULL) { + log_error( "ERROR: cl_mem returned is invalid! (expected %p, got %p)\n", + (cl_mem)NULL, outBuffer ); + return 1; + } + } + + cl_uint numMipLevels; + error = clGetImageInfo( image, CL_IMAGE_NUM_MIP_LEVELS, sizeof( numMipLevels ), &numMipLevels, NULL ); + test_error( error, "Unable to get image info (num mip levels)" ); + if( numMipLevels != 0 ) + { + log_error( "ERROR: image num_mip_levels returned is invalid! (expected %d, got %d)\n", + (int)0, (int)numMipLevels ); + return 1; + } + + cl_uint numSamples; + error = clGetImageInfo( image, CL_IMAGE_NUM_SAMPLES, sizeof( numSamples ), &numSamples, NULL ); + test_error( error, "Unable to get image info (num samples)" ); + if( numSamples != 0 ) + { + log_error( "ERROR: image num_samples returned is invalid! (expected %d, got %d)\n", + (int)0, (int)numSamples ); + return 1; + } + + return 0; +} + +int test_get_image_info_2D( cl_device_id device, cl_image_format *format, cl_mem_flags flags ) +{ + size_t maxWidth, maxHeight; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + cl_mem_flags all_host_ptr_flags[5] = { + flags, + CL_MEM_ALLOC_HOST_PTR | flags, + CL_MEM_COPY_HOST_PTR | flags, + CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR | flags, + CL_MEM_USE_HOST_PTR | flags + }; + + memset(&imageInfo, 0x0, sizeof(image_descriptor)); + imageInfo.format = format; + imageInfo.type = CL_MEM_OBJECT_IMAGE2D; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D width or max image 3D height or max memory allocation size or global memory size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++) + { + if( gDebugTrace ) + log_info( " at size %d,%d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, (int)imageInfo.height, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch ); + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) ) + return -1; + if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) ) + return -1; + } + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] ); + for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++) + { + if( gDebugTrace ) + log_info( " at max size %d,%d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, (int)imageInfo.height, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch ); + if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) ) + return -1; + if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL + if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) ) + return -1; + } + } + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth; + + do { + extraWidth++; + imageInfo.rowPitch += extraWidth; + } while ((imageInfo.rowPitch % pixelSize) != 0); + + size = (cl_ulong)imageInfo.rowPitch * (cl_ulong)imageInfo.height * 4; + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++) + { + if( gDebugTrace ) + log_info( " at size %d,%d (flags[%u] 0x%x pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.height, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight ); + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) ) + return -1; + if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) ) + return -1; + } + } + } + } + + return 0; +} diff --git a/test_conformance/images/clGetInfo/test_3D.cpp b/test_conformance/images/clGetInfo/test_3D.cpp new file mode 100644 index 00000000..24f7021d --- /dev/null +++ b/test_conformance/images/clGetInfo/test_3D.cpp @@ -0,0 +1,158 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gTestSmallImages, gTestMaxImages; + +extern int test_get_image_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d, cl_mem_flags flags, size_t row_pitch, size_t slice_pitch ); + +int test_get_image_info_3D( cl_device_id device, cl_image_format *format, cl_mem_flags flags ) +{ + size_t maxWidth, maxHeight, maxDepth; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + cl_mem_flags all_host_ptr_flags[] = { + flags, + CL_MEM_ALLOC_HOST_PTR | flags, + CL_MEM_COPY_HOST_PTR | flags, + CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR | flags, + CL_MEM_USE_HOST_PTR | flags + }; + + memset(&imageInfo, 0x0, sizeof(image_descriptor)); + imageInfo.format = format; + imageInfo.type = CL_MEM_OBJECT_IMAGE3D; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 3D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + for( imageInfo.depth = 2; imageInfo.depth < 9; imageInfo.depth++ ) + { + for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++) + { + if( gDebugTrace ) + log_info( " at size %d,%d,%d (flags[%u] 0x%lx pitch %d,%d)\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth, j, (unsigned long)all_host_ptr_flags[j], (int)imageInfo.rowPitch, (int)imageInfo.slicePitch ); + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) ) + return -1; + if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, imageInfo.slicePitch ) ) + return -1; + } + } + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, maxDepth, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE3D, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.depth = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + + log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++) + { + if( gDebugTrace ) + log_info( " at max size %d,%d,%d (flags[%u] 0x%lx pitch %d,%d)\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ], j, (unsigned long)all_host_ptr_flags[j], (int)imageInfo.rowPitch, (int)imageInfo.slicePitch ); + if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) ) + return -1; + if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL + if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, imageInfo.slicePitch ) ) + return -1; + } + } + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + imageInfo.depth = (size_t)random_log_in_range( 16, (int)maxDepth / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth; + + do { + extraWidth++; + imageInfo.rowPitch += extraWidth; + } while ((imageInfo.rowPitch % pixelSize) != 0); + + size_t extraHeight = (int)random_log_in_range( 0, 8, seed ); + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight); + + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.depth * 4 * 4; + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++) + { + if( gDebugTrace ) + log_info( " at size %d,%d,%d (flags[%u] 0x%lx pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth, j, (unsigned long) all_host_ptr_flags[i], (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxDepth ); + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) ) + return -1; + if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL + if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, imageInfo.slicePitch ) ) + return -1; + } + } + } + } + + return 0; +} diff --git a/test_conformance/images/clGetInfo/test_loops.cpp b/test_conformance/images/clGetInfo/test_loops.cpp new file mode 100644 index 00000000..2c9e400f --- /dev/null +++ b/test_conformance/images/clGetInfo/test_loops.cpp @@ -0,0 +1,228 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern int gTypesToTest; +extern int gNormalizedModeToUse; +extern cl_channel_type gChannelTypeToUse; +extern cl_command_queue queue; +extern cl_context context; + + +extern bool gDebugTrace; + +extern int test_get_image_info_1D( cl_device_id device, cl_image_format *format, cl_mem_flags flags ); +extern int test_get_image_info_2D( cl_device_id device, cl_image_format *format, cl_mem_flags flags ); +extern int test_get_image_info_3D( cl_device_id device, cl_image_format *format, cl_mem_flags flags ); +extern int test_get_image_info_1D_array( cl_device_id device, cl_image_format *format, cl_mem_flags flags ); +extern int test_get_image_info_2D_array( cl_device_id device, cl_image_format *format, cl_mem_flags flags ); + +static const char *str_1d_image = "1D"; +static const char *str_2d_image = "2D"; +static const char *str_3d_image = "3D"; +static const char *str_1d_image_array = "1D array"; +static const char *str_2d_image_array = "2D array"; + +static const char *convert_image_type_to_string(cl_mem_object_type image_type) +{ + const char *p; + switch (image_type) + { + case CL_MEM_OBJECT_IMAGE1D: + p = str_1d_image; + break; + case CL_MEM_OBJECT_IMAGE2D: + p = str_2d_image; + break; + case CL_MEM_OBJECT_IMAGE3D: + p = str_3d_image; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + p = str_1d_image_array; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + p = str_2d_image_array; + break; + } + return p; +} + + +int filter_formats( cl_image_format *formatList, bool *filterFlags, unsigned int formatCount, cl_channel_type *channelDataTypesToFilter ) +{ + int numSupported = 0; + for( unsigned int j = 0; j < formatCount; j++ ) + { + // If this format has been previously filtered, remove the filter + if( filterFlags[ j ] ) + filterFlags[ j ] = false; + + // Have we already discarded this via the command line? + if( gChannelTypeToUse != (cl_channel_type)-1 && gChannelTypeToUse != formatList[ j ].image_channel_data_type ) + { + filterFlags[ j ] = true; + continue; + } + + // Is given format standard channel order and type given by spec. We don't want to test it if this is vendor extension + if( !IsChannelOrderSupported( formatList[ j ].image_channel_order ) || !IsChannelTypeSupported( formatList[ j ].image_channel_data_type ) ) + { + filterFlags[ j ] = true; + continue; + } + + // We don't filter by channel type + if( !channelDataTypesToFilter ) + { + numSupported++; + continue; + } + + // Is the format supported? + int i; + for( i = 0; channelDataTypesToFilter[ i ] != (cl_channel_type)-1; i++ ) + { + if( formatList[ j ].image_channel_data_type == channelDataTypesToFilter[ i ] ) + { + numSupported++; + break; + } + } + if( channelDataTypesToFilter[ i ] == (cl_channel_type)-1 ) + { + // Format is NOT supported, so mark it as such + filterFlags[ j ] = true; + } + } + return numSupported; +} + +int get_format_list( cl_device_id device, cl_mem_object_type image_type, cl_image_format * &outFormatList, + unsigned int &outFormatCount, cl_mem_flags flags ) +{ + int error; + + cl_image_format tempList[ 128 ]; + error = clGetSupportedImageFormats( context, (cl_mem_flags)flags, + image_type, 128, tempList, &outFormatCount ); + test_error( error, "Unable to get count of supported image formats" ); + + outFormatList = new cl_image_format[ outFormatCount ]; + error = clGetSupportedImageFormats( context, (cl_mem_flags)flags, + image_type, outFormatCount, outFormatList, NULL ); + test_error( error, "Unable to get list of supported image formats" ); + return 0; +} + +int test_image_type( cl_device_id device, cl_mem_object_type image_type, cl_mem_flags flags ) +{ + log_info( "Running %s %s-only tests...\n", convert_image_type_to_string(image_type), flags == CL_MEM_READ_ONLY ? "read" : "write" ); + + int ret = 0; + + // Grab the list of supported image formats for integer reads + cl_image_format *formatList; + bool *filterFlags; + unsigned int numFormats; + + if ( get_format_list( device, image_type, formatList, numFormats, flags ) ) + return -1; + + BufferOwningPtr formatListBuf(formatList); + + if ((image_type == CL_MEM_OBJECT_IMAGE3D) && (flags != CL_MEM_READ_ONLY)) { + log_info("No requirement for 3D write in OpenCL 1.2. Not checking formats.\n"); + } else { + log_info("Checking for required OpenCL 1.2 formats.\n"); + if (check_minimum_supported( formatList, numFormats, flags ) == false) { + ret++; + } else { + log_info("All required formats present.\n"); + } + } + + filterFlags = new bool[ numFormats ]; + BufferOwningPtr filterFlagsBuf(filterFlags); + + if( filterFlags == NULL ) + { + log_error( "ERROR: Out of memory allocating filter flags list!\n" ); + return -1; + } + memset( filterFlags, 0, sizeof( bool ) * numFormats ); + filter_formats( formatList, filterFlags, numFormats, 0 ); + + // Run the format list + for( unsigned int i = 0; i < numFormats; i++ ) + { + int test_return = 0; + if( filterFlags[i] ) + { + log_info( "NOT RUNNING: " ); + print_header( &formatList[ i ], false ); + continue; + } + + print_header( &formatList[ i ], false ); + + gTestCount++; + + switch (image_type) { + case CL_MEM_OBJECT_IMAGE1D: + test_return = test_get_image_info_1D( device, &formatList[ i ], flags ); + break; + case CL_MEM_OBJECT_IMAGE2D: + test_return = test_get_image_info_2D( device, &formatList[ i ], flags ); + break; + case CL_MEM_OBJECT_IMAGE3D: + test_return = test_get_image_info_3D( device, &formatList[ i ], flags ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + test_return = test_get_image_info_1D_array( device, &formatList[ i ], flags ); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + test_return = test_get_image_info_2D_array( device, &formatList[ i ], flags ); + break; + } + + if (test_return) { + gTestFailure++; + log_error( "FAILED: " ); + print_header( &formatList[ i ], true ); + log_info( "\n" ); + } + + ret += test_return; + } + + return ret; +} + +int test_image_set( cl_device_id device, cl_mem_object_type image_type ) +{ + int ret = 0; + + ret += test_image_type( device, image_type, CL_MEM_READ_ONLY ); + ret += test_image_type( device, image_type, CL_MEM_WRITE_ONLY ); + + return ret; +} + + + + diff --git a/test_conformance/images/clReadWriteImage/CMakeLists.txt b/test_conformance/images/clReadWriteImage/CMakeLists.txt new file mode 100644 index 00000000..b56b1e34 --- /dev/null +++ b/test_conformance/images/clReadWriteImage/CMakeLists.txt @@ -0,0 +1,24 @@ +set(MODULE_NAME CL_READ_WRITE_IMAGES) + +set(${MODULE_NAME}_SOURCES + main.cpp + test_read_1D.cpp + test_read_1D_array.cpp + test_read_2D.cpp + test_read_2D_array.cpp + test_loops.cpp + test_read_3D.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/threadTesting.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/imageHelpers.cpp + ../../../test_common/harness/mt19937.c + ../../../test_common/harness/conversions.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/typeWrappers.cpp + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) + diff --git a/test_conformance/images/clReadWriteImage/Jamfile b/test_conformance/images/clReadWriteImage/Jamfile new file mode 100644 index 00000000..70fa42f1 --- /dev/null +++ b/test_conformance/images/clReadWriteImage/Jamfile @@ -0,0 +1,18 @@ +project + : requirements +# gcc:-xc++ +# msvc:"/TP" + ; + +exe test_cl_read_write_images + : main.cpp + test_read_2D.cpp + test_read_3D.cpp + test_loops.cpp + ; + +install dist + : test_cl_read_write_images + : debug:$(DIST)/debug/tests/test_conformance/images/clReadWriteImage + release:$(DIST)/release/tests/test_conformance/images/clReadWriteImage + ; diff --git a/test_conformance/images/clReadWriteImage/Makefile b/test_conformance/images/clReadWriteImage/Makefile new file mode 100644 index 00000000..458dcef1 --- /dev/null +++ b/test_conformance/images/clReadWriteImage/Makefile @@ -0,0 +1,51 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.cpp \ + test_read_1D.cpp \ + test_read_1D_array.cpp \ + test_read_2D.cpp \ + test_read_2D_array.cpp \ + test_loops.cpp \ + test_read_3D.cpp \ + ../../../test_common/harness/errorHelpers.c \ + ../../../test_common/harness/threadTesting.c \ + ../../../test_common/harness/kernelHelpers.c \ + ../../../test_common/harness/imageHelpers.cpp \ + ../../../test_common/harness/conversions.c \ + ../../../test_common/harness/testHarness.c \ + ../../../test_common/harness/mt19937.c \ + ../../../test_common/harness/typeWrappers.cpp + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = +HEADERS = +TARGET = test_cl_read_write_images +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os +CC = c++ +CXX = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/images/clReadWriteImage/main.cpp b/test_conformance/images/clReadWriteImage/main.cpp new file mode 100644 index 00000000..afee9c4c --- /dev/null +++ b/test_conformance/images/clReadWriteImage/main.cpp @@ -0,0 +1,265 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../../test_common/harness/compat.h" + +#include +#include + +#if !defined(_WIN32) +#include +#include +#endif + +#include "../testBase.h" + +bool gDebugTrace = false, gTestSmallImages = false, gTestMaxImages = false, gUseRamp = false, gTestRounding = false, gTestMipmaps = false; +int gTypesToTest = 0; +cl_channel_type gChannelTypeToUse = (cl_channel_type)-1; +bool gEnablePitch = false; +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +cl_command_queue queue; +cl_context context; + +#define MAX_ALLOWED_STD_DEVIATION_IN_MB 8.0 + +void printUsage( const char *execName ) +{ + const char *p = strrchr( execName, '/' ); + if( p != NULL ) + execName = p + 1; + + log_info( "Usage: %s [debug_trace] [small_images]\n", execName ); + log_info( "Where:\n" ); + log_info( "\t1D - Only test 1D images\n" ); + log_info( "\t2D - Only test 2D images\n" ); + log_info( "\t3D - Only test 3D images\n" ); + log_info( "\t1Darray - Only test 1D image arrays\n" ); + log_info( "\t2Darray - Only test 2D image arrays\n" ); + log_info( "\n" ); + log_info( "\tdebug_trace - Enables additional debug info logging\n" ); + log_info( "\tsmall_images - Runs every format through a loop of widths 1-13 and heights 1-9, instead of random sizes\n" ); + log_info( "\tmax_images - Runs every format through a set of size combinations with the max values, max values - 1, and max values / 128\n" ); + log_info( "\trounding - Runs every format through a single image filled with every possible value for that image format, to verify rounding works properly\n" ); + log_info( "\tuse_pitches - Enables row and slice pitches\n" ); + log_info( "\tuse_ramp - Instead of random data, uses images filled with ramps (and 0xff on any padding pixels) to ease debugging\n" ); + log_info( "\ttest_mipmaps - Test mipmapped images\n" ); +} + + +extern int test_image_set( cl_device_id device, cl_mem_object_type image_type ); + +int main(int argc, const char *argv[]) +{ + cl_platform_id platform; + cl_device_id device; + cl_channel_type chanType; + char str[ 128 ]; + bool randomize = false; + int testMethods = 0; + + test_start(); + + checkDeviceTypeOverride( &gDeviceType ); + + // Parse arguments + for( int i = 1; i < argc; i++ ) + { + strncpy( str, argv[ i ], sizeof( str ) - 1 ); + + if( strcmp( str, "cpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_CPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_CPU; + else if( strcmp( str, "gpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_GPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_GPU; + else if( strcmp( str, "accelerator" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( str, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_DEFAULT; + + else if( strcmp( str, "debug_trace" ) == 0 ) + gDebugTrace = true; + + else if( strcmp( str, "small_images" ) == 0 ) + gTestSmallImages = true; + else if( strcmp( str, "max_images" ) == 0 ) + gTestMaxImages = true; + else if( strcmp( str, "use_pitches" ) == 0 ) + gEnablePitch = true; + else if( strcmp( str, "use_ramps" ) == 0 ) + gUseRamp = true; + else if( strcmp(str, "test_mipmaps") == 0 ) { + gTestMipmaps = true; + // Don't test pitches with mipmaps right now. + gEnablePitch = false; + } + else if( strcmp( str, "randomize" ) == 0 ) + randomize = true; + + else if( strcmp( str, "1D" ) == 0 ) + testMethods |= k1D; + else if( strcmp( str, "2D" ) == 0 ) + testMethods |= k2D; + else if( strcmp( str, "3D" ) == 0 ) + testMethods |= k3D; + else if( strcmp( str, "1Darray" ) == 0 ) + testMethods |= k1DArray; + else if( strcmp( str, "2Darray" ) == 0 ) + testMethods |= k2DArray; + + else if( strcmp( str, "help" ) == 0 || strcmp( str, "?" ) == 0 ) + { + printUsage( argv[ 0 ] ); + return -1; + } + else if( ( chanType = get_channel_type_from_name( str ) ) != (cl_channel_type)-1 ) + gChannelTypeToUse = chanType; + else + { + log_error( "ERROR: Unknown argument %d: %s. Exiting....\n", i, str ); + return -1; + } + } + + if (testMethods == 0) + testMethods = k1D | k2D | k3D | k1DArray | k2DArray; + + // Seed the random # generators + if( randomize ) + { + gRandomSeed = (cl_uint) time( NULL ); + log_info( "Random seed: %u.\n", gRandomSeed ); + gReSeed = 1; + } + + int error; + // Get our platform + error = clGetPlatformIDs(1, &platform, NULL); + if( error ) + { + print_error( error, "Unable to get platform" ); + test_finish(); + return -1; + } + + // Get our device + unsigned int num_devices; + error = clGetDeviceIDs(platform, gDeviceType, 0, NULL, &num_devices); + if( error ) + { + print_error( error, "Unable to get number of devices" ); + test_finish(); + return -1; + } + + uint32_t gDeviceIndex = 0; + const char* device_index_env = getenv("CL_DEVICE_INDEX"); + if (device_index_env) { + if (device_index_env) { + gDeviceIndex = atoi(device_index_env); + } + + if (gDeviceIndex >= num_devices) { + vlog("Specified CL_DEVICE_INDEX=%d out of range, using index 0.\n", gDeviceIndex); + gDeviceIndex = 0; + } + } + + cl_device_id *gDeviceList = (cl_device_id *)malloc( num_devices * sizeof( cl_device_id ) ); + error = clGetDeviceIDs(platform, gDeviceType, num_devices, gDeviceList, NULL); + if( error ) + { + print_error( error, "Unable to get devices" ); + free( gDeviceList ); + test_finish(); + return -1; + } + + device = gDeviceList[gDeviceIndex]; + free( gDeviceList ); + + log_info( "Using " ); + if( printDeviceHeader( device ) != CL_SUCCESS ) + { + test_finish(); + return -1; + } + + // Check for image support + if(checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) { + log_info("Device does not support images. Skipping test.\n"); + test_finish(); + return 0; + } + + // Create a context to test with + context = clCreateContext( NULL, 1, &device, notify_callback, NULL, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create testing context" ); + test_finish(); + return -1; + } + + // Create a queue against the context + queue = clCreateCommandQueueWithProperties( context, device, 0, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create testing command queue" ); + test_finish(); + return -1; + } + + if( gTestSmallImages ) + log_info( "Note: Using small test images\n" ); + + // Run the test now + int ret = 0; + if (testMethods & k1D) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE1D ); + if (testMethods & k2D) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE2D ); + if (testMethods & k3D) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE3D ); + if (testMethods & k1DArray) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE1D_ARRAY ); + if (testMethods & k2DArray) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE2D_ARRAY ); + + error = clFinish(queue); + if (error) + print_error(error, "clFinish failed."); + + if (gTestFailure == 0) { + if (gTestCount > 1) + log_info("PASSED %d of %d tests.\n", gTestCount, gTestCount); + else + log_info("PASSED test.\n"); + } else if (gTestFailure > 0) { + if (gTestCount > 1) + log_error("FAILED %d of %d tests.\n", gTestFailure, gTestCount); + else + log_error("FAILED test.\n"); + } + + // Clean up + clReleaseCommandQueue(queue); + clReleaseContext(context); + test_finish(); + + if (gTestFailure > 0) + return gTestFailure; + + return ret; +} diff --git a/test_conformance/images/clReadWriteImage/test_loops.cpp b/test_conformance/images/clReadWriteImage/test_loops.cpp new file mode 100644 index 00000000..ab2cc5e3 --- /dev/null +++ b/test_conformance/images/clReadWriteImage/test_loops.cpp @@ -0,0 +1,227 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern int gTypesToTest; +extern int gNormalizedModeToUse; +extern cl_channel_type gChannelTypeToUse; +extern cl_command_queue queue; +extern cl_context context; + + +extern bool gDebugTrace; +extern bool gTestMipmaps; + +extern int test_read_image_set_1D( cl_device_id device, cl_image_format *format ); +extern int test_read_image_set_2D( cl_device_id device, cl_image_format *format ); +extern int test_read_image_set_3D( cl_device_id device, cl_image_format *format ); +extern int test_read_image_set_1D_array( cl_device_id device, cl_image_format *format ); +extern int test_read_image_set_2D_array( cl_device_id device, cl_image_format *format ); + +static const char *str_1d_image = "1D"; +static const char *str_2d_image = "2D"; +static const char *str_3d_image = "3D"; +static const char *str_1d_image_array = "1D array"; +static const char *str_2d_image_array = "2D array"; + +static const char *convert_image_type_to_string(cl_mem_object_type imageType) +{ + const char *p; + switch (imageType) + { + case CL_MEM_OBJECT_IMAGE1D: + p = str_1d_image; + break; + case CL_MEM_OBJECT_IMAGE2D: + p = str_2d_image; + break; + case CL_MEM_OBJECT_IMAGE3D: + p = str_3d_image; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + p = str_1d_image_array; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + p = str_2d_image_array; + break; + } + return p; +} + + +int filter_formats( cl_image_format *formatList, bool *filterFlags, unsigned int formatCount, cl_channel_type *channelDataTypesToFilter ) +{ + int numSupported = 0; + for( unsigned int j = 0; j < formatCount; j++ ) + { + // If this format has been previously filtered, remove the filter + if( filterFlags[ j ] ) + filterFlags[ j ] = false; + + // Have we already discarded this via the command line? + if( gChannelTypeToUse != (cl_channel_type)-1 && gChannelTypeToUse != formatList[ j ].image_channel_data_type ) + { + filterFlags[ j ] = true; + continue; + } + + // Is given format standard channel order and type given by spec. We don't want to test it if this is vendor extension + if( !IsChannelOrderSupported( formatList[ j ].image_channel_order ) || !IsChannelTypeSupported( formatList[ j ].image_channel_data_type ) ) + { + filterFlags[ j ] = true; + continue; + } + + // We don't filter by channel type + if( !channelDataTypesToFilter ) + { + numSupported++; + continue; + } + + // Is the format supported? + int i; + for( i = 0; channelDataTypesToFilter[ i ] != (cl_channel_type)-1; i++ ) + { + if( formatList[ j ].image_channel_data_type == channelDataTypesToFilter[ i ] ) + { + numSupported++; + break; + } + } + if( channelDataTypesToFilter[ i ] == (cl_channel_type)-1 ) + { + // Format is NOT supported, so mark it as such + filterFlags[ j ] = true; + } + } + return numSupported; +} + +int get_format_list( cl_device_id device, cl_mem_object_type imageType, cl_image_format * &outFormatList, unsigned int &outFormatCount, cl_mem_flags flags ) +{ + int error; + + cl_image_format tempList[ 128 ]; + error = clGetSupportedImageFormats( context, (cl_mem_flags)flags, + imageType, 128, tempList, &outFormatCount ); + test_error( error, "Unable to get count of supported image formats" ); + + outFormatList = new cl_image_format[ outFormatCount ]; + error = clGetSupportedImageFormats( context, (cl_mem_flags)flags, + imageType, outFormatCount, outFormatList, NULL ); + test_error( error, "Unable to get list of supported image formats" ); + return 0; +} + +int test_image_type( cl_device_id device, cl_mem_object_type imageType, cl_mem_flags flags ) +{ + log_info( "Running %s %s %s-only tests...\n", gTestMipmaps?"mipmapped":"",convert_image_type_to_string(imageType), flags == CL_MEM_READ_ONLY ? "read" : "write" ); + + int ret = 0; + + // Grab the list of supported image formats for integer reads + cl_image_format *formatList; + bool *filterFlags; + unsigned int numFormats; + + if ( gTestMipmaps ) + { + if ( 0 == is_extension_available( device, "cl_khr_mipmap_image" )) + { + log_info( "-----------------------------------------------------\n" ); + log_info( "This device does not support cl_khr_mipmap_image.\nSkipping mipmapped image test. \n" ); + log_info( "-----------------------------------------------------\n\n" ); + return 0; + } + } + + if( get_format_list( device, imageType, formatList, numFormats, flags ) ) + return -1; + + filterFlags = new bool[ numFormats ]; + if( filterFlags == NULL ) + { + log_error( "ERROR: Out of memory allocating filter flags list!\n" ); + return -1; + } + memset( filterFlags, 0, sizeof( bool ) * numFormats ); + filter_formats( formatList, filterFlags, numFormats, 0 ); + + // Run the format list + for( unsigned int i = 0; i < numFormats; i++ ) + { + int test_return = 0; + if( filterFlags[i] ) + { + log_info( "NOT RUNNING: " ); + print_header( &formatList[ i ], false ); + continue; + } + + print_header( &formatList[ i ], false ); + + gTestCount++; + + switch (imageType) { + case CL_MEM_OBJECT_IMAGE1D: + test_return = test_read_image_set_1D( device, &formatList[ i ] ); + break; + case CL_MEM_OBJECT_IMAGE2D: + test_return = test_read_image_set_2D( device, &formatList[ i ] ); + break; + case CL_MEM_OBJECT_IMAGE3D: + test_return = test_read_image_set_3D( device, &formatList[ i ] ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + test_return = test_read_image_set_1D_array( device, &formatList[ i ] ); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + test_return = test_read_image_set_2D_array( device, &formatList[ i ] ); + break; + } + + if (test_return) { + gTestFailure++; + log_error( "FAILED: " ); + print_header( &formatList[ i ], true ); + log_info( "\n" ); + } + + ret += test_return; + } + + delete filterFlags; + delete formatList; + + return ret; +} + +int test_image_set( cl_device_id device, cl_mem_object_type imageType ) +{ + int ret = 0; + + ret += test_image_type( device, imageType, CL_MEM_READ_ONLY ); + ret += test_image_type( device, imageType, CL_MEM_WRITE_ONLY ); + + return ret; +} + + + + diff --git a/test_conformance/images/clReadWriteImage/test_read_1D.cpp b/test_conformance/images/clReadWriteImage/test_read_1D.cpp new file mode 100644 index 00000000..407f27fe --- /dev/null +++ b/test_conformance/images/clReadWriteImage/test_read_1D.cpp @@ -0,0 +1,273 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_command_queue queue; +extern cl_context context; + + +int test_read_image_1D( cl_device_id device, image_descriptor *imageInfo, MTdata d ) +{ + int error; + + clMemWrapper image; + + // Generate some data to test against + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + if( gDebugTrace ) + { + log_info( " - Creating %s 1D image %d...\n", gTestMipmaps?"mipmapped":"", (int)imageInfo->width ); + log_info( " with %llu mip levels\n", (unsigned long long) imageInfo->num_mip_levels ); + } + + // Construct testing sources + if(!gTestMipmaps) + { + image = create_image_1d( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, 0, NULL, NULL, &error ); + if( image == NULL ) + { + log_error( "ERROR: Unable to create 1D image of size %d (%s)", (int)imageInfo->width, IGetErrorString( error ) ); + return -1; + } + } + else + { + cl_image_desc image_desc = {0}; + image_desc.image_type = CL_MEM_OBJECT_IMAGE1D; + image_desc.image_width = imageInfo->width; + image_desc.num_mip_levels = imageInfo->num_mip_levels; + + image = clCreateImage( context, CL_MEM_READ_ONLY, imageInfo->format, &image_desc, NULL, &error); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create %d level mipmapped 1D image of size %d x %d (pitch %d ) (%s)",(int)imageInfo->num_mip_levels, (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + } + + if( gDebugTrace ) + log_info( " - Writing image...\n" ); + + size_t origin[ 3 ] = { 0, 0, 0 }; + size_t region[ 3 ] = { 0, 1, 1 }; + size_t fullImageSize; + if( gTestMipmaps ) + { + fullImageSize = (size_t)compute_mipmapped_image_size( *imageInfo ); + } + else + { + fullImageSize = imageInfo->rowPitch; + } + + BufferOwningPtr resultValues(malloc(fullImageSize)); + size_t imgValMipLevelOffset = 0; + + for( size_t lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++) + { + float lod_float = (float) lod; + origin[1] = lod; + size_t width_lod, row_pitch_lod; + + width_lod = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1; + row_pitch_lod = gTestMipmaps ? (width_lod * get_pixel_size( imageInfo->format )): imageInfo->rowPitch; + + region[0] = width_lod; + + if ( gDebugTrace ) + if ( gTestMipmaps) { + log_info(" - Working at mipLevel :%llu\n", (unsigned long long)lod); + } + error = clEnqueueWriteImage(queue, image, CL_FALSE, + origin, region, ( gEnablePitch ? row_pitch_lod : 0 ), 0, + (char*)imageValues + imgValMipLevelOffset, 0, NULL, NULL); + if (error != CL_SUCCESS) { + log_error( "ERROR: Unable to write to 1D image of size %d \n", (int)width_lod ); + return -1; + } + + // To verify, we just read the results right back and see whether they match the input + if( gDebugTrace ) + { + log_info( " - Initing result array...\n" ); + } + + // Note: we read back without any pitch, to verify pitch actually WORKED + size_t scanlineSize = width_lod * get_pixel_size( imageInfo->format ); + size_t imageSize = scanlineSize; + memset( resultValues, 0xff, imageSize ); + + if( gDebugTrace ) + log_info( " - Reading results...\n" ); + + error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read image values" ); + + // Verify scanline by scanline, since the pitches are different + char *sourcePtr = (char*)imageValues + imgValMipLevelOffset; + char *destPtr = resultValues; + + if( memcmp( sourcePtr, destPtr, scanlineSize ) != 0 ) + { + log_error( "ERROR: Scanline did not verify for image size %d pitch %d (extra %d bytes)\n", (int)width_lod, (int)row_pitch_lod, (int)row_pitch_lod - (int)width_lod * (int)get_pixel_size( imageInfo->format ) ); + + log_error( "First few values: \n" ); + log_error( " Input: " ); + uint32_t *s = (uint32_t *)sourcePtr; + uint32_t *d = (uint32_t *)destPtr; + for( int q = 0; q < 12; q++ ) + log_error( "%08x ", s[ q ] ); + log_error( "\nOutput: " ); + for( int q = 0; q < 12; q++ ) + log_error( "%08x ", d[ q ] ); + log_error( "\n" ); + + int outX; + int offset = (int)get_pixel_size( imageInfo->format ) * (int)( width_lod - 16 ); + if( offset < 0 ) + offset = 0; + int foundCount = debug_find_vector_in_image( (char*)imageValues + imgValMipLevelOffset, imageInfo, destPtr + offset, get_pixel_size( imageInfo->format ), &outX, NULL, NULL ); + if( foundCount > 0 ) + { + int returnedOffset = ( offset / (int)get_pixel_size( imageInfo->format ) ) - outX; + + if( memcmp( sourcePtr + returnedOffset * get_pixel_size( imageInfo->format ), destPtr, get_pixel_size( imageInfo->format ) * 8 ) == 0 ) + log_error( " Values appear to be offsetted by %d\n", returnedOffset ); + else + log_error( " Calculated offset is %d but unable to verify\n", returnedOffset ); + } + else + { + log_error( " Unable to determine offset\n" ); + } + return -1; + } + imgValMipLevelOffset += width_lod * get_pixel_size( imageInfo->format ); + } + return 0; +} + +int test_read_image_set_1D( cl_device_id device, cl_image_format *format ) +{ + size_t maxWidth; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + imageInfo.type = CL_MEM_OBJECT_IMAGE1D; + imageInfo.format = format; + imageInfo.height = imageInfo.depth = imageInfo.slicePitch = 0; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed); + + if( gDebugTrace ) + log_info( " at size %d\n", (int)imageInfo.width ); + + int ret = test_read_image_1D( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[idx][0]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed); + + log_info("Testing %d\n", (int)imageInfo.width); + if( gDebugTrace ) + log_info( " at max size %d\n", (int)maxWidth ); + if( test_read_image_1D( device, &imageInfo, seed ) ) + return -1; + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + + if (gTestMipmaps) + { + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed); + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + size = compute_mipmapped_image_size( imageInfo ); + } + else + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + if( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth * pixelSize; + } + + size = (size_t)imageInfo.rowPitch * 4; + } + } while( size > maxAllocSize || ( size / 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d (row pitch %d) out of %d\n", (int)imageInfo.width, (int)imageInfo.rowPitch, (int)maxWidth ); + int ret = test_read_image_1D( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clReadWriteImage/test_read_1D_array.cpp b/test_conformance/images/clReadWriteImage/test_read_1D_array.cpp new file mode 100644 index 00000000..b6e8ce01 --- /dev/null +++ b/test_conformance/images/clReadWriteImage/test_read_1D_array.cpp @@ -0,0 +1,287 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_command_queue queue; +extern cl_context context; + + +int test_read_image_1D_array( cl_device_id device, image_descriptor *imageInfo, MTdata d ) +{ + int error; + + clMemWrapper image; + + // Generate some data to test against + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + if( gDebugTrace ) + { + log_info( " - Creating %s image array of size %d by %d...\n", gTestMipmaps?"mipmapped":"", (int)imageInfo->width, (int)imageInfo->arraySize ); + if( gTestMipmaps ) + log_info( " with %llu mip levels\n", (unsigned long long) imageInfo->num_mip_levels ); + } + + // Construct testing sources + if(!gTestMipmaps) + { + image = create_image_1d_array( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->arraySize, 0, 0, NULL, &error ); + if( image == NULL ) + { + log_error( "ERROR: Unable to create 1D image array of size %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->arraySize, IGetErrorString( error ) ); + return -1; + } + } + else + { + cl_image_desc image_desc = {0}; + image_desc.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + image_desc.image_width = imageInfo->width; + image_desc.image_array_size = imageInfo->arraySize; + image_desc.num_mip_levels = imageInfo->num_mip_levels; + + image = clCreateImage( context, CL_MEM_READ_ONLY, imageInfo->format, &image_desc, NULL, &error); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create %d level mipmapped 1D image of width %d and array size %d (pitch %d ) (%s)",(int)imageInfo->num_mip_levels, (int)imageInfo->width, (int)imageInfo->arraySize, (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + } + if( gDebugTrace ) + log_info( " - Writing image...\n" ); + + size_t origin[ 3 ] = { 0, 0, 0 }; + size_t region[ 3 ] = { 0, 0, 1 }; + size_t fullImageSize; + if( gTestMipmaps ) + { + fullImageSize = (size_t)compute_mipmapped_image_size( *imageInfo ); + } + else + { + fullImageSize = imageInfo->arraySize * imageInfo->slicePitch; + } + + size_t imgValMipLevelOffset = 0; + BufferOwningPtr resultValues(malloc(fullImageSize)); + + for( size_t lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++) + { + float lod_float = (float) lod; + size_t width_lod, row_pitch_lod, slice_pitch_lod; + if( gTestMipmaps ) + origin[2] = lod; + + width_lod = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1; + row_pitch_lod = gTestMipmaps ? (width_lod * get_pixel_size( imageInfo->format )): imageInfo->rowPitch; + slice_pitch_lod = row_pitch_lod; + + region[0] = width_lod; + region[1] = imageInfo->arraySize; + + if ( gDebugTrace && gTestMipmaps ) + log_info("Working at mip level %llu\n", (unsigned long long) lod); + + error = clEnqueueWriteImage(queue, image, CL_FALSE, + origin, region, ( gEnablePitch ? row_pitch_lod : 0 ), 0, + (char*)imageValues + imgValMipLevelOffset, 0, NULL, NULL); + if (error != CL_SUCCESS) { + log_error( "ERROR: Unable to write to 1D image array of width %d and size %d\n", (int)width_lod, (int)imageInfo->arraySize ); + return -1; + } + + // To verify, we just read the results right back and see whether they match the input + if( gDebugTrace ) + log_info( " - Initing result array...\n" ); + + // Note: we read back without any pitch, to verify pitch actually WORKED + size_t scanlineSize = width_lod * get_pixel_size( imageInfo->format ); + size_t imageSize = scanlineSize * imageInfo->arraySize; + memset( resultValues, 0xff, imageSize ); + + if( gDebugTrace ) + log_info( " - Reading results...\n" ); + + error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read image values" ); + + // Verify scanline by scanline, since the pitches are different + char *sourcePtr = (char *)imageValues + imgValMipLevelOffset; + char *destPtr = resultValues; + + for( size_t y = 0; y < imageInfo->arraySize; y++ ) + { + if( memcmp( sourcePtr, destPtr, scanlineSize ) != 0 ) + { + log_error( "ERROR: Image array index %d did not verify for image size %d,%d pitch %d (extra %d bytes)\n", (int)y, (int)width_lod, (int)imageInfo->arraySize, (int)row_pitch_lod, (int)row_pitch_lod - (int)width_lod * (int)get_pixel_size( imageInfo->format ) ); + + log_error( "First few values: \n" ); + log_error( " Input: " ); + uint32_t *s = (uint32_t *)sourcePtr; + uint32_t *d = (uint32_t *)destPtr; + for( int q = 0; q < 12; q++ ) + log_error( "%08x ", s[ q ] ); + log_error( "\nOutput: " ); + for( int q = 0; q < 12; q++ ) + log_error( "%08x ", d[ q ] ); + log_error( "\n" ); + + int outX, outY; + int offset = (int)get_pixel_size( imageInfo->format ) * (int)( width_lod - 16 ); + if( offset < 0 ) + offset = 0; + int foundCount = debug_find_vector_in_image( imageValues + imgValMipLevelOffset, imageInfo, destPtr + offset, get_pixel_size( imageInfo->format ), &outX, &outY, NULL ); + if( foundCount > 0 ) + { + int returnedOffset = ( (int)y * (int)width_lod + offset / (int)get_pixel_size( imageInfo->format ) ) - ( outY * (int)width_lod + outX ); + + if( memcmp( sourcePtr + returnedOffset * get_pixel_size( imageInfo->format ), destPtr, get_pixel_size( imageInfo->format ) * 8 ) == 0 ) + log_error( " Values appear to be offsetted by %d\n", returnedOffset ); + else + log_error( " Calculated offset is %d but unable to verify\n", returnedOffset ); + } + else + { + log_error( " Unable to determine offset\n" ); + } + return -1; + } + sourcePtr += row_pitch_lod; + destPtr += scanlineSize; + } + imgValMipLevelOffset += width_lod * imageInfo->arraySize * get_pixel_size( imageInfo->format ); + } + return 0; +} + +int test_read_image_set_1D_array( cl_device_id device, cl_image_format *format ) +{ + size_t maxWidth, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + imageInfo.type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + imageInfo.format = format; + imageInfo.height = imageInfo.depth = 0; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch; + for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ ) + { + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed); + + if( gDebugTrace ) + log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize ); + + int ret = test_read_image_1D_array( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D_ARRAY, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[idx][0]; + imageInfo.arraySize = sizes[idx][2]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed); + + log_info("Testing %d x %d\n", (int)imageInfo.width, (int)imageInfo.arraySize); + if( gDebugTrace ) + log_info( " at max size %d,%d\n", (int)maxWidth, (int)maxArraySize ); + if( test_read_image_1D_array( device, &imageInfo, seed ) ) + return -1; + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed ); + if (gTestMipmaps) + { + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed); + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.rowPitch; + size = compute_mipmapped_image_size( imageInfo ); + } + else + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + if( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth * pixelSize; + } + imageInfo.slicePitch = imageInfo.rowPitch; + + size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.arraySize * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxArraySize ); + int ret = test_read_image_1D_array( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clReadWriteImage/test_read_2D.cpp b/test_conformance/images/clReadWriteImage/test_read_2D.cpp new file mode 100644 index 00000000..22f5ea1b --- /dev/null +++ b/test_conformance/images/clReadWriteImage/test_read_2D.cpp @@ -0,0 +1,286 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_command_queue queue; +extern cl_context context; + + +int test_read_image_2D( cl_device_id device, image_descriptor *imageInfo, MTdata d ) +{ + int error; + + clMemWrapper image; + + // Generate some data to test against + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + if( gDebugTrace ) + { + log_info( " - Creating %s image %d by %d...\n", gTestMipmaps?"mipmapped":"", (int)imageInfo->width, (int)imageInfo->height ); + if( gTestMipmaps ) + log_info( " with %llu mip levels\n", (unsigned long long) imageInfo->num_mip_levels ); + } + + // Construct testing sources + if(!gTestMipmaps) + { + image = create_image_2d( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->height, 0, NULL, &error ); + if( image == NULL ) + { + log_error( "ERROR: Unable to create 2D image of size %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, IGetErrorString( error ) ); + return -1; + } + } + else + { + cl_image_desc image_desc = {0}; + image_desc.image_type = CL_MEM_OBJECT_IMAGE2D; + image_desc.image_width = imageInfo->width; + image_desc.image_height = imageInfo->height; + image_desc.num_mip_levels = imageInfo->num_mip_levels; + + image = clCreateImage( context, CL_MEM_READ_ONLY, imageInfo->format, &image_desc, NULL, &error); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create %d level mipmapped 2D image of size %d x %d (pitch %d ) (%s)",(int)imageInfo->num_mip_levels, (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + } + if( gDebugTrace ) + log_info( " - Writing image...\n" ); + + size_t origin[ 3 ] = { 0, 0, 0 }; + size_t region[ 3 ] = { 0, 0, 1 }; + size_t fullImageSize; + if( gTestMipmaps ) + { + fullImageSize = (size_t)compute_mipmapped_image_size( *imageInfo ); + } + else + { + fullImageSize = imageInfo->height * imageInfo->rowPitch; + } + BufferOwningPtr resultValues(malloc(fullImageSize)); + size_t imgValMipLevelOffset = 0; + + for( size_t lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++) + { + float lod_float = (float) lod; + origin[2] = lod; + size_t width_lod, height_lod, row_pitch_lod; + + width_lod = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1; + height_lod = (imageInfo->height >> lod) ? (imageInfo->height >> lod) : 1; + row_pitch_lod = gTestMipmaps ? (width_lod * get_pixel_size( imageInfo->format )): imageInfo->rowPitch; + + region[0] = width_lod; + region[1] = height_lod; + + if ( gDebugTrace && gTestMipmaps) { + log_info(" - Working at mipLevel :%llu\n", (unsigned long long)lod); + } + error = clEnqueueWriteImage(queue, image, CL_FALSE, + origin, region, ( gEnablePitch ? row_pitch_lod : 0 ), 0, + (char*)imageValues + imgValMipLevelOffset, 0, NULL, NULL); + if (error != CL_SUCCESS) { + log_error( "ERROR: Unable to write to 2D image of size %d x %d \n", (int)width_lod, (int)height_lod ); + return -1; + } + + // To verify, we just read the results right back and see whether they match the input + if( gDebugTrace ) { + log_info( " - Initing result array...\n" ); + } + + // Note: we read back without any pitch, to verify pitch actually WORKED + size_t scanlineSize = width_lod * get_pixel_size( imageInfo->format ); + size_t imageSize = scanlineSize * height_lod; + memset( resultValues, 0xff, imageSize ); + + if( gDebugTrace ) + log_info( " - Reading results...\n" ); + + error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read image values" ); + + // Verify scanline by scanline, since the pitches are different + char *sourcePtr = (char *)imageValues + imgValMipLevelOffset; + char *destPtr = resultValues; + + for( size_t y = 0; y < height_lod; y++ ) + { + if( memcmp( sourcePtr, destPtr, scanlineSize ) != 0 ) + { + if(gTestMipmaps) + { + log_error("At mip level %llu\n",(unsigned long long) lod); + } + log_error( "ERROR: Scanline %d did not verify for image size %d,%d pitch %d (extra %d bytes)\n", (int)y, (int)width_lod, (int)height_lod, (int)row_pitch_lod, (int)row_pitch_lod - (int)width_lod * (int)get_pixel_size( imageInfo->format ) ); + + log_error( "First few values: \n" ); + log_error( " Input: " ); + uint32_t *s = (uint32_t *)sourcePtr; + uint32_t *d = (uint32_t *)destPtr; + for( int q = 0; q < 12; q++ ) + log_error( "%08x ", s[ q ] ); + log_error( "\nOutput: " ); + for( int q = 0; q < 12; q++ ) + log_error( "%08x ", d[ q ] ); + log_error( "\n" ); + + int outX, outY; + int offset = (int)get_pixel_size( imageInfo->format ) * (int)( width_lod - 16 ); + if( offset < 0 ) + offset = 0; + int foundCount = debug_find_vector_in_image( (char*)imageValues + imgValMipLevelOffset, imageInfo, destPtr + offset, get_pixel_size( imageInfo->format ), &outX, &outY, NULL ); + if( foundCount > 0 ) + { + int returnedOffset = ( (int)y * (int)width_lod + offset / (int)get_pixel_size( imageInfo->format ) ) - ( outY * (int)width_lod + outX ); + + if( memcmp( sourcePtr + returnedOffset * get_pixel_size( imageInfo->format ), destPtr, get_pixel_size( imageInfo->format ) * 8 ) == 0 ) + log_error( " Values appear to be offsetted by %d\n", returnedOffset ); + else + log_error( " Calculated offset is %d but unable to verify\n", returnedOffset ); + } + else + { + log_error( " Unable to determine offset\n" ); + } + return -1; + } + sourcePtr += row_pitch_lod; + destPtr += scanlineSize; + } + imgValMipLevelOffset += width_lod * height_lod * get_pixel_size( imageInfo->format ); + } + return 0; +} + +int test_read_image_set_2D( cl_device_id device, cl_image_format *format ) +{ + size_t maxWidth, maxHeight; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + imageInfo.type = CL_MEM_OBJECT_IMAGE2D; + imageInfo.format = format; + imageInfo.depth = imageInfo.slicePitch = 0; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed); + + if( gDebugTrace ) + log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.height ); + + int ret = test_read_image_2D( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[idx][0]; + imageInfo.height = sizes[idx][1]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed); + + log_info("Testing %d x %d\n", (int)imageInfo.width, (int)imageInfo.height); + if( gDebugTrace ) + log_info( " at max size %d,%d\n", (int)maxWidth, (int)maxHeight ); + if( test_read_image_2D( device, &imageInfo, seed ) ) + return -1; + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + if (gTestMipmaps) + { + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed); + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + size = compute_mipmapped_image_size( imageInfo ); + } + else + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + if( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth * pixelSize; + } + + size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.height * 4; + } + } while( size > maxAllocSize || ( size / 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight ); + int ret = test_read_image_2D( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clReadWriteImage/test_read_2D_array.cpp b/test_conformance/images/clReadWriteImage/test_read_2D_array.cpp new file mode 100644 index 00000000..b82a8bac --- /dev/null +++ b/test_conformance/images/clReadWriteImage/test_read_2D_array.cpp @@ -0,0 +1,272 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern cl_command_queue queue; +extern cl_context context; + +int test_read_image_2D_array( cl_device_id device, image_descriptor *imageInfo, MTdata d ) +{ + int error; + + clMemWrapper image; + + // Create some data to test against + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + if( gDebugTrace ) + { + log_info( " - Creating %s image %d by %d by %d...\n", gTestMipmaps?"mipmapped":"", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize ); + if( gTestMipmaps ) + log_info( " with %llu mip levels\n", (unsigned long long) imageInfo->num_mip_levels ); + } + + // Construct testing sources + if(!gTestMipmaps) + { + image = create_image_2d_array( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->height, imageInfo->arraySize, 0, 0, NULL, &error ); + if( image == NULL ) + { + log_error( "ERROR: Unable to create 2D image array of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, IGetErrorString( error ) ); + return -1; + } + } + else + { + cl_image_desc image_desc = {0}; + image_desc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + image_desc.image_width = imageInfo->width; + image_desc.image_height = imageInfo->height; + image_desc.image_array_size = imageInfo->arraySize; + image_desc.num_mip_levels = imageInfo->num_mip_levels; + + image = clCreateImage( context, CL_MEM_READ_ONLY, imageInfo->format, &image_desc, NULL, &error); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create %d level mipmapped 3D image of size %d x %d x %d (pitch %d, %d ) (%s)",(int)imageInfo->num_mip_levels, (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + } + + if( gDebugTrace ) + log_info( " - Writing image...\n" ); + + size_t origin[ 4 ] = { 0, 0, 0, 0 }; + size_t region[ 3 ] = { 0, 0, 0 }; + size_t fullImageSize; + if( gTestMipmaps ) + { + fullImageSize = (size_t)compute_mipmapped_image_size( *imageInfo ); + } + else + { + fullImageSize = imageInfo->arraySize * imageInfo->slicePitch; + } + BufferOwningPtr resultValues(malloc(fullImageSize)); + size_t imgValMipLevelOffset = 0; + + for(size_t lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++) + { + float lod_float = (float) lod; + origin[3] = lod; + size_t width_lod, height_lod, depth_lod, row_pitch_lod, slice_pitch_lod; + + width_lod = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1; + height_lod = (imageInfo->height >> lod) ? (imageInfo->height >> lod) : 1; + row_pitch_lod = gTestMipmaps ? (width_lod * get_pixel_size( imageInfo->format )): imageInfo->rowPitch; + slice_pitch_lod = gTestMipmaps ? (row_pitch_lod * height_lod): imageInfo->slicePitch; + region[0] = width_lod; + region[1] = height_lod; + region[2] = imageInfo->arraySize; + + if ( gDebugTrace && gTestMipmaps) { + log_info(" - Working at mipLevel :%llu\n", (unsigned long long)lod); + } + + error = clEnqueueWriteImage(queue, image, CL_FALSE, + origin, region, ( gEnablePitch ? row_pitch_lod : 0 ), ( gEnablePitch ? slice_pitch_lod : 0 ), + (char*)imageValues + imgValMipLevelOffset, 0, NULL, NULL); + if (error != CL_SUCCESS) { + log_error( "ERROR: Unable to write to 2D image array of size %d x %d x %d\n", (int)width_lod, (int)height_lod, (int)imageInfo->arraySize ); + return -1; + } + + // To verify, we just read the results right back and see whether they match the input + if( gDebugTrace ) + log_info( " - Initing result array...\n" ); + + // Note: we read back without any pitch, to verify pitch actually WORKED + size_t scanlineSize = width_lod * get_pixel_size( imageInfo->format ); + size_t pageSize = scanlineSize * height_lod; + size_t imageSize = pageSize * imageInfo->arraySize; + memset( resultValues, 0xff, imageSize ); + + if( gDebugTrace ) + log_info( " - Reading results...\n" ); + + error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read image values" ); + + // Verify scanline by scanline, since the pitches are different + char *sourcePtr = (char *)imageValues + imgValMipLevelOffset; + char *destPtr = resultValues; + + for( size_t z = 0; z < imageInfo->arraySize; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + if( memcmp( sourcePtr, destPtr, scanlineSize ) != 0 ) + { + log_error( "ERROR: Scanline %d,%d did not verify for image size %d,%d,%d pitch %d,%d\n", (int)y, (int)z, (int)width_lod, (int)height_lod, (int)imageInfo->arraySize, (int)row_pitch_lod, (int)slice_pitch_lod ); + return -1; + } + sourcePtr += row_pitch_lod; + destPtr += scanlineSize; + } + sourcePtr += slice_pitch_lod - ( row_pitch_lod * height_lod ); + destPtr += pageSize - scanlineSize * height_lod; + } + imgValMipLevelOffset += width_lod * height_lod * imageInfo->arraySize * get_pixel_size( imageInfo->format ); + } + return 0; +} + +int test_read_image_set_2D_array( cl_device_id device, cl_image_format *format ) +{ + size_t maxWidth, maxHeight, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + imageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + imageInfo.format = format; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 3D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ ) + { + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed); + + if( gDebugTrace ) + log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize ); + int ret = test_read_image_2D_array( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D_ARRAY, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + // Try a specific set of maximum sizes + imageInfo.width = sizes[idx][0]; + imageInfo.height = sizes[idx][1]; + imageInfo.arraySize = sizes[idx][2]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed); + + log_info("Testing %d x %d x %d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize); + if( test_read_image_2D_array( device, &imageInfo, seed ) ) + return -1; + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed ); + + if (gTestMipmaps) + { + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed); + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + size = compute_mipmapped_image_size( imageInfo ) * 4; + } + else + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + + if( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth * pixelSize; + + size_t extraHeight = (int)random_log_in_range( 0, 8, seed ); + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight); + } + + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxArraySize ); + int ret = test_read_image_2D_array( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/clReadWriteImage/test_read_3D.cpp b/test_conformance/images/clReadWriteImage/test_read_3D.cpp new file mode 100644 index 00000000..b8ac3fec --- /dev/null +++ b/test_conformance/images/clReadWriteImage/test_read_3D.cpp @@ -0,0 +1,276 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern cl_command_queue queue; +extern cl_context context; + +int test_read_image_3D( cl_device_id device, image_descriptor *imageInfo, MTdata d ) +{ + int error; + + clMemWrapper image; + + // Create some data to test against + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + if( gDebugTrace ) + { + log_info( " - Creating %s image %d by %d by %d...\n", gTestMipmaps?"mipmapped":"", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth ); + if( gTestMipmaps ) + log_info( " with %llu mip levels\n", (unsigned long long) imageInfo->num_mip_levels ); + } + // Construct testing sources + if(!gTestMipmaps) + { + image = create_image_3d( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->height, imageInfo->depth, 0, 0, NULL, &error ); + if( image == NULL ) + { + log_error( "ERROR: Unable to create 2D image of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, IGetErrorString( error ) ); + return -1; + } + } + else + { + cl_image_desc image_desc = {0}; + image_desc.image_type = CL_MEM_OBJECT_IMAGE3D; + image_desc.image_width = imageInfo->width; + image_desc.image_height = imageInfo->height; + image_desc.image_depth = imageInfo->depth; + image_desc.num_mip_levels = imageInfo->num_mip_levels; + + image = clCreateImage( context, CL_MEM_READ_ONLY, imageInfo->format, &image_desc, NULL, &error); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create %d level mipmapped 3D image of size %d x %d x %d (pitch %d, %d ) (%s)",(int)imageInfo->num_mip_levels, (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + } + + if( gDebugTrace ) + log_info( " - Writing image...\n" ); + + size_t origin[ 4 ] = { 0, 0, 0, 0 }; + size_t region[ 3 ] = { 0, 0, 0 }; + size_t fullImageSize; + if( gTestMipmaps ) + { + fullImageSize = (size_t)compute_mipmapped_image_size( *imageInfo ); + } + else + { + fullImageSize = imageInfo->depth * imageInfo->slicePitch; + } + + BufferOwningPtr resultValues(malloc(fullImageSize)); + size_t imgValMipLevelOffset = 0; + + for(size_t lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++) + { + float lod_float = (float) lod; + origin[3] = lod; + size_t width_lod, height_lod, depth_lod, row_pitch_lod, slice_pitch_lod; + + width_lod = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1; + height_lod = (imageInfo->height >> lod) ? (imageInfo->height >> lod) : 1; + depth_lod = (imageInfo->depth >> lod) ? (imageInfo->depth >> lod) : 1; + row_pitch_lod = gTestMipmaps ? (width_lod * get_pixel_size( imageInfo->format )): imageInfo->rowPitch; + slice_pitch_lod = gTestMipmaps ? (row_pitch_lod * height_lod): imageInfo->slicePitch; + region[0] = width_lod; + region[1] = height_lod; + region[2] = depth_lod; + + if ( gDebugTrace && gTestMipmaps) { + log_info(" - Working at mipLevel :%llu\n", (unsigned long long)lod); + } + error = clEnqueueWriteImage(queue, image, CL_FALSE, + origin, region, ( gEnablePitch ? imageInfo->rowPitch : 0 ), ( gEnablePitch ? imageInfo->slicePitch : 0 ), + (char*)imageValues + imgValMipLevelOffset, 0, NULL, NULL); + if (error != CL_SUCCESS) { + log_error( "ERROR: Unable to write to %s 3D image of size %d x %d x %d\n", gTestMipmaps?"mipmapped":"", (int)width_lod, (int)height_lod, (int)depth_lod ); + return -1; + } + + // To verify, we just read the results right back and see whether they match the input + if( gDebugTrace ) { + log_info( " - Initing result array...\n" ); + } + + // Note: we read back without any pitch, to verify pitch actually WORKED + size_t scanlineSize = width_lod * get_pixel_size( imageInfo->format ); + size_t pageSize = scanlineSize * height_lod; + size_t imageSize = pageSize * depth_lod; + memset( resultValues, 0xff, imageSize ); + + if( gDebugTrace ) + log_info( " - Reading results...\n" ); + + error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read image values" ); + + // Verify scanline by scanline, since the pitches are different + char *sourcePtr = (char *)imageValues + imgValMipLevelOffset; + char *destPtr = resultValues; + + for( size_t z = 0; z < depth_lod; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + if( memcmp( sourcePtr, destPtr, scanlineSize ) != 0 ) + { + if(gTestMipmaps) + { + log_error("At mip level %llu\n",(unsigned long long) lod); + } + log_error( "ERROR: Scanline %d,%d did not verify for image size %d,%d,%d pitch %d,%d\n", (int)y, (int)z, (int)width_lod, (int)height_lod, (int)depth_lod, (int)row_pitch_lod, (int)slice_pitch_lod ); + return -1; + } + sourcePtr += row_pitch_lod; + destPtr += scanlineSize; + } + sourcePtr += slice_pitch_lod - ( row_pitch_lod * height_lod ); + destPtr += pageSize - scanlineSize * height_lod; + } + imgValMipLevelOffset += width_lod * height_lod * depth_lod * get_pixel_size( imageInfo->format ); + } + return 0; +} + +int test_read_image_set_3D( cl_device_id device, cl_image_format *format ) +{ + size_t maxWidth, maxHeight, maxDepth; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + imageInfo.type = CL_MEM_OBJECT_IMAGE3D; + imageInfo.format = format; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 3D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + for( imageInfo.depth = 2; imageInfo.depth < 9; imageInfo.depth++ ) + { + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth), seed); + + if( gDebugTrace ) + log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth ); + int ret = test_read_image_3D( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, maxDepth, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE3D, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + // Try a specific set of maximum sizes + imageInfo.width = sizes[idx][0]; + imageInfo.height = sizes[idx][1]; + imageInfo.depth = sizes[idx][2]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth), seed); + + log_info("Testing %d x %d x %d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth); + if( test_read_image_3D( device, &imageInfo, seed ) ) + return -1; + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + imageInfo.depth = (size_t)random_log_in_range( 16, (int)maxDepth / 32, seed ); + if (gTestMipmaps) + { + imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth), seed); + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + size = compute_mipmapped_image_size( imageInfo ); + } + else + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + + if( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth * pixelSize; + + size_t extraHeight = (int)random_log_in_range( 0, 8, seed ); + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight); + } + + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.depth * 4 * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxDepth ); + int ret = test_read_image_3D( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/kernel_image_methods/CMakeLists.txt b/test_conformance/images/kernel_image_methods/CMakeLists.txt new file mode 100644 index 00000000..bc2663fd --- /dev/null +++ b/test_conformance/images/kernel_image_methods/CMakeLists.txt @@ -0,0 +1,23 @@ +set(MODULE_NAME KERNEL_IMAGE_METHODS) + +set(${MODULE_NAME}_SOURCES + main.cpp + test_1D.cpp + test_1D_array.cpp + test_2D.cpp + test_2D_array.cpp + test_loops.cpp + test_3D.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/threadTesting.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/imageHelpers.cpp + ../../../test_common/harness/mt19937.c + ../../../test_common/harness/conversions.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/typeWrappers.cpp + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/images/kernel_image_methods/Jamfile b/test_conformance/images/kernel_image_methods/Jamfile new file mode 100644 index 00000000..1d5e227a --- /dev/null +++ b/test_conformance/images/kernel_image_methods/Jamfile @@ -0,0 +1,18 @@ +project + : requirements +# gcc:-xc++ +# msvc:"/TP" + ; + +exe test_kernel_image_methods + : main.cpp + test_2D.cpp + test_3D.cpp + test_loops.cpp + ; + +install dist + : test_kernel_image_methods + : debug:$(DIST)/debug/tests/test_conformance/images/kernel_image_methods + release:$(DIST)/release/tests/test_conformance/images/kernel_image_methods + ; diff --git a/test_conformance/images/kernel_image_methods/Makefile b/test_conformance/images/kernel_image_methods/Makefile new file mode 100644 index 00000000..8079f5fb --- /dev/null +++ b/test_conformance/images/kernel_image_methods/Makefile @@ -0,0 +1,51 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.cpp \ + test_1D.cpp \ + test_1D_array.cpp \ + test_2D.cpp \ + test_2D_array.cpp \ + test_loops.cpp \ + test_3D.cpp \ + ../../../test_common/harness/errorHelpers.c \ + ../../../test_common/harness/threadTesting.c \ + ../../../test_common/harness/kernelHelpers.c \ + ../../../test_common/harness/imageHelpers.cpp \ + ../../../test_common/harness/conversions.c \ + ../../../test_common/harness/testHarness.c \ + ../../../test_common/harness/mt19937.c \ + ../../../test_common/harness/typeWrappers.cpp + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = +HEADERS = +TARGET = test_kernel_image_methods +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os +CC = c++ +CXX = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/images/kernel_image_methods/main.cpp b/test_conformance/images/kernel_image_methods/main.cpp new file mode 100644 index 00000000..f3dd9c55 --- /dev/null +++ b/test_conformance/images/kernel_image_methods/main.cpp @@ -0,0 +1,262 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../../test_common/harness/compat.h" +#include "../../../test_common/harness/parseParameters.h" + +#include +#include + +#if !defined(_WIN32) +#include +#include +#endif + +#include "../testBase.h" + +bool gDebugTrace = false, gTestSmallImages = false, gTestMaxImages = false, gTestRounding = false; +int gTypesToTest = 0; +cl_channel_type gChannelTypeToUse = (cl_channel_type)-1; +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; + +extern int test_image_set( cl_device_id device, cl_mem_object_type imageType ); + +#define MAX_ALLOWED_STD_DEVIATION_IN_MB 8.0 + +clCommandQueueWrapper queue; +clContextWrapper context; + +void printUsage( const char *execName ) +{ + const char *p = strrchr( execName, '/' ); + if( p != NULL ) + execName = p + 1; + + log_info( "Usage: %s [debug_trace] [small_images]\n", execName ); + log_info( "Where:\n" ); + log_info( "\t1D - Only test 1D images\n" ); + log_info( "\t2D - Only test 2D images\n" ); + log_info( "\t3D - Only test 3D images\n" ); + log_info( "\t1Darray - Only test 1D image arrays\n" ); + log_info( "\t2Darray - Only test 2D image arrays\n" ); + log_info( "\n" ); + log_info( "\tdebug_trace - Enables additional debug info logging\n" ); + log_info( "\tsmall_images - Runs every format through a loop of widths 1-13 and heights 1-9, instead of random sizes\n" ); + log_info( "\tmax_images - Runs every format through a set of size combinations with the max values, max values - 1, and max values / 128\n" ); +} + + +int main(int argc, const char *argv[]) +{ + cl_platform_id platform; + cl_device_id device; + cl_channel_type chanType; + char str[ 128 ]; + int testMethods = 0; + bool randomize = false; + + test_start(); + + argc = parseCustomParam(argc, argv); + if (argc == -1) + { + test_finish(); + return -1; + } + + checkDeviceTypeOverride( &gDeviceType ); + + // Parse arguments + for( int i = 1; i < argc; i++ ) + { + strncpy( str, argv[ i ], sizeof( str ) - 1 ); + + if( strcmp( str, "cpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_CPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_CPU; + else if( strcmp( str, "gpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_GPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_GPU; + else if( strcmp( str, "accelerator" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( str, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_DEFAULT; + + else if( strcmp( str, "debug_trace" ) == 0 ) + gDebugTrace = true; + + else if( strcmp( str, "small_images" ) == 0 ) + gTestSmallImages = true; + else if( strcmp( str, "max_images" ) == 0 ) + gTestMaxImages = true; + + else if( strcmp( str, "randomize" ) == 0 ) + randomize = true; + + else if ( strcmp( str, "1D" ) == 0 ) + testMethods |= k1D; + else if( strcmp( str, "2D" ) == 0 ) + testMethods |= k2D; + else if( strcmp( str, "3D" ) == 0 ) + testMethods |= k3D; + else if( strcmp( str, "1Darray" ) == 0 ) + testMethods |= k1DArray; + else if( strcmp( str, "2Darray" ) == 0 ) + testMethods |= k2DArray; + + else if( strcmp( str, "help" ) == 0 || strcmp( str, "?" ) == 0 ) + { + printUsage( argv[ 0 ] ); + return -1; + } + else if( ( chanType = get_channel_type_from_name( str ) ) != (cl_channel_type)-1 ) + gChannelTypeToUse = chanType; + else + { + log_error( "ERROR: Unknown argument %d: %s. Exiting....\n", i, str ); + return -1; + } + } + + if (testMethods == 0) + testMethods = k1D | k2D | k3D | k1DArray | k2DArray; + + // Seed the random # generators + if( randomize ) + { + gRandomSeed = (cl_uint) time( NULL ); + log_info( "Random seed: %u.\n", gRandomSeed ); + gReSeed = 1; + } + + // Get our device + int error; + + // Get our platform + error = clGetPlatformIDs(1, &platform, NULL); + if( error ) + { + print_error( error, "Unable to get platform" ); + test_finish(); + return -1; + } + + // Get our device + unsigned int num_devices; + error = clGetDeviceIDs(platform, gDeviceType, 0, NULL, &num_devices); + if( error ) + { + print_error( error, "Unable to get number of devices" ); + test_finish(); + return -1; + } + + uint32_t gDeviceIndex = 0; + const char* device_index_env = getenv("CL_DEVICE_INDEX"); + if (device_index_env) { + if (device_index_env) { + gDeviceIndex = atoi(device_index_env); + } + + if (gDeviceIndex >= num_devices) { + vlog("Specified CL_DEVICE_INDEX=%d out of range, using index 0.\n", gDeviceIndex); + gDeviceIndex = 0; + } + } + + cl_device_id *gDeviceList = (cl_device_id *)malloc( num_devices * sizeof( cl_device_id ) ); + error = clGetDeviceIDs(platform, gDeviceType, num_devices, gDeviceList, NULL); + if( error ) + { + print_error( error, "Unable to get devices" ); + free( gDeviceList ); + test_finish(); + return -1; + } + + device = gDeviceList[gDeviceIndex]; + free( gDeviceList ); + + log_info( "Using " ); + if( printDeviceHeader( device ) != CL_SUCCESS ) + { + test_finish(); + return -1; + } + + // Check for image support + if (checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) + { + log_info("Device does not support images. Skipping test.\n"); + test_finish(); + return 0; + } + + // Create a context to test with + context = clCreateContext( NULL, 1, &device, notify_callback, NULL, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create testing context" ); + test_finish(); + return -1; + } + + // Create a queue against the context + queue = clCreateCommandQueueWithProperties( context, device, 0, &error ); + if ( error != CL_SUCCESS ) + { + print_error( error, "Unable to create testing command queue" ); + test_finish(); + return -1; + } + + if( gTestSmallImages ) + log_info( "Note: Using small test images\n" ); + + // Run the test now + int ret = 0; + if (testMethods & k1D) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE1D ); + if (testMethods & k2D) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE2D ); + if (testMethods & k3D) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE3D ); + if (testMethods & k1DArray) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE1D_ARRAY ); + if (testMethods & k2DArray) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE2D_ARRAY ); + + // Clean up + error = clFinish(queue); + if (error) + print_error(error, "clFinish failed."); + + if (gTestFailure == 0) { + if (gTestCount > 1) + log_info("PASSED %d of %d tests.\n", gTestCount, gTestCount); + else + log_info("PASSED test.\n"); + } else if (gTestFailure > 0) { + if (gTestCount > 1) + log_error("FAILED %d of %d tests.\n", gTestFailure, gTestCount); + else + log_error("FAILED test.\n"); + } + + test_finish(); + + if (gTestFailure > 0) + return gTestFailure; + + return ret; +} diff --git a/test_conformance/images/kernel_image_methods/test_1D.cpp b/test_conformance/images/kernel_image_methods/test_1D.cpp new file mode 100644 index 00000000..f1b92bee --- /dev/null +++ b/test_conformance/images/kernel_image_methods/test_1D.cpp @@ -0,0 +1,237 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gTestSmallImages, gTestMaxImages; + +extern clCommandQueueWrapper queue; +extern clContextWrapper context; + +typedef struct image_kernel_data +{ + cl_int width; + cl_int channelType; + cl_int channelOrder; + cl_int expectedChannelType; + cl_int expectedChannelOrder; +}; + +static const char *methodTest1DImageKernelPattern = +"typedef struct {\n" +" int width;\n" +" int channelType;\n" +" int channelOrder;\n" +" int expectedChannelType;\n" +" int expectedChannelOrder;\n" +" } image_kernel_data;\n" +"__kernel void sample_kernel( read_only image1d_t input, __global image_kernel_data *outData )\n" +"{\n" +" outData->width = get_image_width( input );\n" +" outData->channelType = get_image_channel_data_type( input );\n" +" outData->channelOrder = get_image_channel_order( input );\n" +"\n" +" outData->expectedChannelType = %s;\n" +" outData->expectedChannelOrder = %s;\n" +"}"; + +static int test_get_1Dimage_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d ) +{ + int error = 0; + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper image, outDataBuffer; + char programSrc[ 10240 ]; + + image_kernel_data outKernelData; + + // Generate some data to test against + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + // Construct testing source + if( gDebugTrace ) + log_info( " - Creating 1D image %d ...\n", (int)imageInfo->width ); + + image = create_image_1d( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, 0, NULL, NULL, &error ); + if( image == NULL ) + { + log_error( "ERROR: Unable to create 1D image of size %d (%s)", (int)imageInfo->width, IGetErrorString( error ) ); + return -1; + } + + char channelTypeConstantString[256] = {0}; + char channelOrderConstantString[256] = {0}; + + const char* channelTypeName = GetChannelTypeName( imageInfo->format->image_channel_data_type ); + const char* channelOrderName = GetChannelOrderName( imageInfo->format->image_channel_order ); + + if(channelTypeName && strlen(channelTypeName)) + sprintf(channelTypeConstantString, "CLK_%s", &channelTypeName[3]); // replace CL_* with CLK_* + + if(channelOrderName && strlen(channelOrderName)) + sprintf(channelOrderConstantString, "CLK_%s", &channelOrderName[3]); // replace CL_* with CLK_* + + // Create a program to run against + sprintf( programSrc, methodTest1DImageKernelPattern, + channelTypeConstantString, channelOrderConstantString); + + //log_info("-----------------------------------\n%s\n", programSrc); + error = clFinish(queue); + if (error) + print_error(error, "clFinish failed.\n"); + const char *ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create kernel to test against" ); + + // Create an output buffer + outDataBuffer = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof( outKernelData ), NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + // Set up arguments and run + error = clSetKernelArg( kernel, 0, sizeof( image ), &image ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 1, sizeof( outDataBuffer ), &outDataBuffer ); + test_error( error, "Unable to set kernel argument" ); + + size_t threads[1] = { 1 }, localThreads[1] = { 1 }; + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + error = clEnqueueReadBuffer( queue, outDataBuffer, CL_TRUE, 0, sizeof( outKernelData ), &outKernelData, 0, NULL, NULL ); + test_error( error, "Unable to read data buffer" ); + + + // Verify the results now + if( outKernelData.width != (cl_int)imageInfo->width ) + { + log_error( "ERROR: Returned width did not validate (expected %d, got %d)\n", (int)imageInfo->width, (int)outKernelData.width ); + error = -1; + } + if( outKernelData.channelType != (cl_int)outKernelData.expectedChannelType ) + { + log_error( "ERROR: Returned channel type did not validate (expected %s (%d), got %d)\n", GetChannelTypeName( imageInfo->format->image_channel_data_type ), + (int)outKernelData.expectedChannelType, (int)outKernelData.channelType ); + error = -1; + } + if( outKernelData.channelOrder != (cl_int)outKernelData.expectedChannelOrder ) + { + log_error( "ERROR: Returned channel order did not validate (expected %s (%d), got %d)\n", GetChannelOrderName( imageInfo->format->image_channel_order ), + (int)outKernelData.expectedChannelOrder, (int)outKernelData.channelOrder ); + error = -1; + } + + if( clFinish(queue) != CL_SUCCESS ) + { + log_error( "ERROR: CL Finished failed in %s \n", __FUNCTION__); + error = -1; + } + + return error; +} + +int test_get_image_info_1D( cl_device_id device, cl_image_format *format ) +{ + size_t maxWidth; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + imageInfo.type = CL_MEM_OBJECT_IMAGE1D; + imageInfo.format = format; + imageInfo.height = imageInfo.depth = imageInfo.slicePitch = 0; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 1D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + if( gDebugTrace ) + log_info( " at size %d\n", (int)imageInfo.width ); + + int ret = test_get_1Dimage_info_single( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + + log_info( "Testing %d\n", (int)sizes[ idx ][ 0 ]); + if( gDebugTrace ) + log_info( " at max size %d\n", (int)sizes[ idx ][ 0 ] ); + if( test_get_1Dimage_info_single( device, &imageInfo, seed ) ) + return -1; + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth; + + do { + extraWidth++; + imageInfo.rowPitch += extraWidth; + } while ((imageInfo.rowPitch % pixelSize) != 0); + + size = (cl_ulong)imageInfo.rowPitch * (cl_ulong)imageInfo.height * 4; + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d (row pitch %d) out of %d\n", (int)imageInfo.width, (int)imageInfo.rowPitch, (int)maxWidth ); + int ret = test_get_1Dimage_info_single( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/kernel_image_methods/test_1D_array.cpp b/test_conformance/images/kernel_image_methods/test_1D_array.cpp new file mode 100644 index 00000000..c99b3f8e --- /dev/null +++ b/test_conformance/images/kernel_image_methods/test_1D_array.cpp @@ -0,0 +1,255 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gTestSmallImages, gTestMaxImages; + +extern clCommandQueueWrapper queue; +extern clContextWrapper context; + +typedef struct image_kernel_data +{ + cl_int width; + cl_int arraySize; + cl_int channelType; + cl_int channelOrder; + cl_int expectedChannelType; + cl_int expectedChannelOrder; +}; + +static const char *methodTestKernelPattern = +"typedef struct {\n" +" int width;\n" +" int arraySize;\n" +" int channelType;\n" +" int channelOrder;\n" +" int expectedChannelType;\n" +" int expectedChannelOrder;\n" +" } image_kernel_data;\n" +"__kernel void sample_kernel( read_only image1d_array_t input, __global image_kernel_data *outData )\n" +"{\n" +" outData->width = get_image_width( input );\n" +" outData->arraySize = get_image_array_size( input );\n" +" outData->channelType = get_image_channel_data_type( input );\n" +" outData->channelOrder = get_image_channel_order( input );\n" +"\n" +" outData->expectedChannelType = %s;\n" +" outData->expectedChannelOrder = %s;\n" +"}"; + +int test_get_1Dimage_array_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d ) +{ + int error = 0; + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper image, outDataBuffer; + char programSrc[ 10240 ]; + + image_kernel_data outKernelData; + + // Generate some data to test against + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + // Construct testing source + if( gDebugTrace ) + log_info( " - Creating 1D image array %d by %d...\n", (int)imageInfo->width, (int)imageInfo->arraySize ); + + image = create_image_1d_array( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->arraySize, 0, 0, NULL, &error ); + if( image == NULL ) + { + log_error( "ERROR: Unable to create 1D image array of size %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->arraySize, IGetErrorString( error ) ); + return -1; + } + + char channelTypeConstantString[256] = {0}; + char channelOrderConstantString[256] = {0}; + + const char* channelTypeName = GetChannelTypeName( imageInfo->format->image_channel_data_type ); + const char* channelOrderName = GetChannelOrderName( imageInfo->format->image_channel_order ); + + if(channelTypeName && strlen(channelTypeName)) + sprintf(channelTypeConstantString, "CLK_%s", &channelTypeName[3]); // replace CL_* with CLK_* + + if(channelOrderName && strlen(channelOrderName)) + sprintf(channelOrderConstantString, "CLK_%s", &channelOrderName[3]); // replace CL_* with CLK_* + + // Create a program to run against + sprintf( programSrc, methodTestKernelPattern, + channelTypeConstantString, channelOrderConstantString); + + //log_info("-----------------------------------\n%s\n", programSrc); + error = clFinish(queue); + if (error) + print_error(error, "clFinish failed.\n"); + const char *ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create kernel to test against" ); + + // Create an output buffer + outDataBuffer = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof( outKernelData ), NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + // Set up arguments and run + error = clSetKernelArg( kernel, 0, sizeof( image ), &image ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 1, sizeof( outDataBuffer ), &outDataBuffer ); + test_error( error, "Unable to set kernel argument" ); + + size_t threads[1] = { 1 }, localThreads[1] = { 1 }; + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + error = clEnqueueReadBuffer( queue, outDataBuffer, CL_TRUE, 0, sizeof( outKernelData ), &outKernelData, 0, NULL, NULL ); + test_error( error, "Unable to read data buffer" ); + + + // Verify the results now + if( outKernelData.width != (cl_int)imageInfo->width ) + { + log_error( "ERROR: Returned width did not validate (expected %d, got %d)\n", (int)imageInfo->width, (int)outKernelData.width ); + error = -1; + } + if( outKernelData.arraySize != (cl_int)imageInfo->arraySize ) + { + log_error( "ERROR: Returned array size did not validate (expected %d, got %d)\n", (int)imageInfo->arraySize, (int)outKernelData.arraySize ); + error = -1; + } + if( outKernelData.channelType != (cl_int)outKernelData.expectedChannelType ) + { + log_error( "ERROR: Returned channel type did not validate (expected %s (%d), got %d)\n", GetChannelTypeName( imageInfo->format->image_channel_data_type ), + (int)outKernelData.expectedChannelType, (int)outKernelData.channelType ); + error = -1; + } + if( outKernelData.channelOrder != (cl_int)outKernelData.expectedChannelOrder ) + { + log_error( "ERROR: Returned channel order did not validate (expected %s (%d), got %d)\n", GetChannelOrderName( imageInfo->format->image_channel_order ), + (int)outKernelData.expectedChannelOrder, (int)outKernelData.channelOrder ); + error = -1; + } + + if( clFinish(queue) != CL_SUCCESS ) + { + log_error( "ERROR: CL Finished failed in %s \n", __FUNCTION__); + error = -1; + } + + return error; +} + +int test_get_image_info_1D_array( cl_device_id device, cl_image_format *format ) +{ + size_t maxWidth, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + imageInfo.type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + imageInfo.format = format; + imageInfo.height = imageInfo.depth = imageInfo.slicePitch = 0; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch; + for( imageInfo.arraySize = 1; imageInfo.arraySize < 9; imageInfo.arraySize++ ) + { + if( gDebugTrace ) + log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize ); + + int ret = test_get_1Dimage_array_info_single( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D_ARRAY, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.arraySize = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch; + + log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ]); + if( gDebugTrace ) + log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ] ); + if( test_get_1Dimage_array_info_single( device, &imageInfo, seed ) ) + return -1; + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth; + + do { + extraWidth++; + imageInfo.rowPitch += extraWidth; + } while ((imageInfo.rowPitch % pixelSize) != 0); + + imageInfo.slicePitch = imageInfo.rowPitch; + + size = (cl_ulong)imageInfo.rowPitch * (cl_ulong)imageInfo.arraySize * 4; + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxArraySize ); + int ret = test_get_1Dimage_array_info_single( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/kernel_image_methods/test_2D.cpp b/test_conformance/images/kernel_image_methods/test_2D.cpp new file mode 100644 index 00000000..6eddbebb --- /dev/null +++ b/test_conformance/images/kernel_image_methods/test_2D.cpp @@ -0,0 +1,295 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gTestSmallImages, gTestMaxImages; + +extern clCommandQueueWrapper queue; +extern clContextWrapper context; + +typedef struct image_kernel_data +{ + cl_int width; + cl_int height; + cl_int depth; + cl_int widthDim; + cl_int heightDim; + cl_int depthDim; + cl_int channelType; + cl_int channelOrder; + cl_int expectedChannelType; + cl_int expectedChannelOrder; +}; + +static const char *methodTestKernelPattern = +"typedef struct {\n" +" int width;\n" +" int height;\n" +" int depth;\n" +" int widthDim;\n" +" int heightDim;\n" +" int depthDim;\n" +" int channelType;\n" +" int channelOrder;\n" +" int expectedChannelType;\n" +" int expectedChannelOrder;\n" +" } image_kernel_data;\n" +"__kernel void sample_kernel( read_only image%dd%s_t input, __global image_kernel_data *outData )\n" +"{\n" +" outData->width = get_image_width( input );\n" +" outData->height = get_image_height( input );\n" +"%s\n" +" int%d dim = get_image_dim( input );\n" +" outData->widthDim = dim.x;\n" +" outData->heightDim = dim.y;\n" +"%s\n" +" outData->channelType = get_image_channel_data_type( input );\n" +" outData->channelOrder = get_image_channel_order( input );\n" +"\n" +" outData->expectedChannelType = %s;\n" +" outData->expectedChannelOrder = %s;\n" +"}"; + +static const char *depthKernelLine = " outData->depth = get_image_depth( input );\n"; +static const char *depthDimKernelLine = " outData->depthDim = dim.z;\n"; + +int test_get_image_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d ) +{ + int error = 0; + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper image, outDataBuffer; + char programSrc[ 10240 ]; + + image_kernel_data outKernelData; + + // Generate some data to test against + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + // Construct testing source + if( gDebugTrace ) + log_info( " - Creating image %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height ); + + if( imageInfo->depth != 0 ) + image = create_image_3d( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->height, imageInfo->depth, 0, 0, NULL, &error ); + else + image = create_image_2d( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->height, 0, NULL, &error ); + if( image == NULL ) + { + log_error( "ERROR: Unable to create image of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, IGetErrorString( error ) ); + return -1; + } + + char channelTypeConstantString[256] = {0}; + char channelOrderConstantString[256] = {0}; + + const char* channelTypeName = GetChannelTypeName( imageInfo->format->image_channel_data_type ); + const char* channelOrderName = GetChannelOrderName( imageInfo->format->image_channel_order ); + + if(channelTypeName && strlen(channelTypeName)) + sprintf(channelTypeConstantString, "CLK_%s", &channelTypeName[3]); // replace CL_* with CLK_* + + if(channelOrderName && strlen(channelOrderName)) + sprintf(channelOrderConstantString, "CLK_%s", &channelOrderName[3]); // replace CL_* with CLK_* + + // Create a program to run against + sprintf( programSrc, methodTestKernelPattern, + ( imageInfo->depth != 0 ) ? 3 : 2, + (imageInfo->format->image_channel_order == CL_DEPTH) ? "_depth" : "", + ( imageInfo->depth != 0 ) ? depthKernelLine : "", + ( imageInfo->depth != 0 ) ? 4 : 2, + ( imageInfo->depth != 0 ) ? depthDimKernelLine : "", + channelTypeConstantString, channelOrderConstantString); + + //log_info("-----------------------------------\n%s\n", programSrc); + error = clFinish(queue); + if (error) + print_error(error, "clFinish failed.\n"); + const char *ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create kernel to test against" ); + + // Create an output buffer + outDataBuffer = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof( outKernelData ), NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + // Set up arguments and run + error = clSetKernelArg( kernel, 0, sizeof( image ), &image ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 1, sizeof( outDataBuffer ), &outDataBuffer ); + test_error( error, "Unable to set kernel argument" ); + + size_t threads[1] = { 1 }, localThreads[1] = { 1 }; + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + error = clEnqueueReadBuffer( queue, outDataBuffer, CL_TRUE, 0, sizeof( outKernelData ), &outKernelData, 0, NULL, NULL ); + test_error( error, "Unable to read data buffer" ); + + + // Verify the results now + if( outKernelData.width != (cl_int)imageInfo->width ) + { + log_error( "ERROR: Returned width did not validate (expected %d, got %d)\n", (int)imageInfo->width, (int)outKernelData.width ); + error = -1; + } + if( outKernelData.height != (cl_int)imageInfo->height ) + { + log_error( "ERROR: Returned height did not validate (expected %d, got %d)\n", (int)imageInfo->height, (int)outKernelData.height ); + error = -1; + } + if( ( imageInfo->depth != 0 ) && ( outKernelData.depth != (cl_int)imageInfo->depth ) ) + { + log_error( "ERROR: Returned depth did not validate (expected %d, got %d)\n", (int)imageInfo->depth, (int)outKernelData.depth ); + error = -1; + } + if( outKernelData.widthDim != (cl_int)imageInfo->width ) + { + log_error( "ERROR: Returned width from get_image_dim did not validate (expected %d, got %d)\n", (int)imageInfo->width, (int)outKernelData.widthDim ); + error = -1; + } + if( outKernelData.heightDim != (cl_int)imageInfo->height ) + { + log_error( "ERROR: Returned height from get_image_dim did not validate (expected %d, got %d)\n", (int)imageInfo->height, (int)outKernelData.heightDim ); + error = -1; + } + if( ( imageInfo->depth != 0 ) && ( outKernelData.depthDim != (cl_int)imageInfo->depth ) ) + { + log_error( "ERROR: Returned depth from get_image_dim did not validate (expected %d, got %d)\n", (int)imageInfo->depth, (int)outKernelData.depthDim ); + error = -1; + } + if( outKernelData.channelType != (cl_int)outKernelData.expectedChannelType ) + { + log_error( "ERROR: Returned channel type did not validate (expected %s (%d), got %d)\n", GetChannelTypeName( imageInfo->format->image_channel_data_type ), + (int)outKernelData.expectedChannelType, (int)outKernelData.channelType ); + error = -1; + } + if( outKernelData.channelOrder != (cl_int)outKernelData.expectedChannelOrder ) + { + log_error( "ERROR: Returned channel order did not validate (expected %s (%d), got %d)\n", GetChannelOrderName( imageInfo->format->image_channel_order ), + (int)outKernelData.expectedChannelOrder, (int)outKernelData.channelOrder ); + error = -1; + } + + if( clFinish(queue) != CL_SUCCESS ) + { + log_error( "ERROR: CL Finished failed in %s \n", __FUNCTION__); + error = -1; + } + + return error; +} + +int test_get_image_info_2D( cl_device_id device, cl_image_format *format ) +{ + size_t maxWidth, maxHeight; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + imageInfo.type = CL_MEM_OBJECT_IMAGE2D; + imageInfo.format = format; + imageInfo.depth = imageInfo.slicePitch = 0; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + if( gDebugTrace ) + log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.height ); + + int ret = test_get_image_info_single( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + + log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ]); + if( gDebugTrace ) + log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] ); + if( test_get_image_info_single( device, &imageInfo, seed ) ) + return -1; + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth; + + do { + extraWidth++; + imageInfo.rowPitch += extraWidth; + } while ((imageInfo.rowPitch % pixelSize) != 0); + + size = (cl_ulong)imageInfo.rowPitch * (cl_ulong)imageInfo.height * 4; + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight ); + int ret = test_get_image_info_single( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/kernel_image_methods/test_2D_array.cpp b/test_conformance/images/kernel_image_methods/test_2D_array.cpp new file mode 100644 index 00000000..3542077e --- /dev/null +++ b/test_conformance/images/kernel_image_methods/test_2D_array.cpp @@ -0,0 +1,272 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gTestSmallImages, gTestMaxImages; + +extern clCommandQueueWrapper queue; +extern clContextWrapper context; + +typedef struct image_kernel_data +{ + cl_int width; + cl_int height; + cl_int arraySize; + cl_int channelType; + cl_int channelOrder; + cl_int expectedChannelType; + cl_int expectedChannelOrder; +}; + +static const char *methodTestKernelPattern = +"typedef struct {\n" +" int width;\n" +" int height;\n" +" int arraySize;\n" +" int channelType;\n" +" int channelOrder;\n" +" int expectedChannelType;\n" +" int expectedChannelOrder;\n" +" } image_kernel_data;\n" +"__kernel void sample_kernel( read_only %s input, __global image_kernel_data *outData )\n" +"{\n" +" outData->width = get_image_width( input );\n" +" outData->height = get_image_height( input );\n" +" outData->arraySize = get_image_array_size( input );\n" +" outData->channelType = get_image_channel_data_type( input );\n" +" outData->channelOrder = get_image_channel_order( input );\n" +"\n" +" outData->expectedChannelType = %s;\n" +" outData->expectedChannelOrder = %s;\n" +"}"; + +int test_get_2Dimage_array_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d ) +{ + int error = 0; + + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper image, outDataBuffer; + char programSrc[ 10240 ]; + + image_kernel_data outKernelData; + + // Generate some data to test against + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + // Construct testing source + if( gDebugTrace ) + log_info( " - Creating 2D image array %d by %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize ); + + image = create_image_2d_array( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->height, imageInfo->arraySize, 0, 0, NULL, &error ); + if( image == NULL ) + { + log_error( "ERROR: Unable to create 2D image array of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, IGetErrorString( error ) ); + return -1; + } + + char channelTypeConstantString[256] = {0}; + char channelOrderConstantString[256] = {0}; + + const char* channelTypeName = GetChannelTypeName( imageInfo->format->image_channel_data_type ); + const char* channelOrderName = GetChannelOrderName( imageInfo->format->image_channel_order ); + + if(channelTypeName && strlen(channelTypeName)) + sprintf(channelTypeConstantString, "CLK_%s", &channelTypeName[3]); // replace CL_* with CLK_* + + if(channelOrderName && strlen(channelOrderName)) + sprintf(channelOrderConstantString, "CLK_%s", &channelOrderName[3]); // replace CL_* with CLK_* + + // Create a program to run against + sprintf( programSrc, methodTestKernelPattern, + (imageInfo->format->image_channel_order == CL_DEPTH) ? "image2d_array_depth_t" : "image2d_array_t" , + channelTypeConstantString, channelOrderConstantString); + + //log_info("-----------------------------------\n%s\n", programSrc); + error = clFinish(queue); + if (error) + print_error(error, "clFinish failed.\n"); + const char *ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create kernel to test against" ); + + // Create an output buffer + outDataBuffer = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof( outKernelData ), NULL, &error ); + test_error( error, "Unable to create output buffer" ); + + // Set up arguments and run + error = clSetKernelArg( kernel, 0, sizeof( image ), &image ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, 1, sizeof( outDataBuffer ), &outDataBuffer ); + test_error( error, "Unable to set kernel argument" ); + + size_t threads[1] = { 1 }, localThreads[1] = { 1 }; + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + error = clEnqueueReadBuffer( queue, outDataBuffer, CL_TRUE, 0, sizeof( outKernelData ), &outKernelData, 0, NULL, NULL ); + test_error( error, "Unable to read data buffer" ); + + + // Verify the results now + if( outKernelData.width != (cl_int)imageInfo->width ) + { + log_error( "ERROR: Returned width did not validate (expected %d, got %d)\n", (int)imageInfo->width, (int)outKernelData.width ); + error = -1; + } + if( outKernelData.height != (cl_int)imageInfo->height ) + { + log_error( "ERROR: Returned height did not validate (expected %d, got %d)\n", (int)imageInfo->height, (int)outKernelData.height ); + error = -1; + } + if( outKernelData.arraySize != (cl_int)imageInfo->arraySize ) + { + log_error( "ERROR: Returned array size did not validate (expected %d, got %d)\n", (int)imageInfo->arraySize, (int)outKernelData.arraySize ); + error = -1; + } + if( outKernelData.channelType != (cl_int)outKernelData.expectedChannelType ) + { + log_error( "ERROR: Returned channel type did not validate (expected %s (%d), got %d)\n", GetChannelTypeName( imageInfo->format->image_channel_data_type ), + (int)outKernelData.expectedChannelType, (int)outKernelData.channelType ); + error = -1; + } + if( outKernelData.channelOrder != (cl_int)outKernelData.expectedChannelOrder ) + { + log_error( "ERROR: Returned channel order did not validate (expected %s (%d), got %d)\n", GetChannelOrderName( imageInfo->format->image_channel_order ), + (int)outKernelData.expectedChannelOrder, (int)outKernelData.channelOrder ); + error = -1; + } + + if( clFinish(queue) != CL_SUCCESS ) + { + log_error( "ERROR: CL Finished failed in %s \n", __FUNCTION__); + error = -1; + } + + return error; +} + +int test_get_image_info_2D_array( cl_device_id device, cl_image_format *format ) +{ + size_t maxWidth, maxHeight, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + imageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + imageInfo.format = format; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 3D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ ) + { + if( gDebugTrace ) + log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize ); + int ret = test_get_2Dimage_array_info_single( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D_ARRAY, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.arraySize = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + + log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + if( gDebugTrace ) + log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + if( test_get_2Dimage_array_info_single( device, &imageInfo, seed ) ) + return -1; + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth; + + do { + extraWidth++; + imageInfo.rowPitch += extraWidth; + } while ((imageInfo.rowPitch % pixelSize) != 0); + + size_t extraHeight = (int)random_log_in_range( 0, 8, seed ); + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight); + + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4; + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxArraySize ); + int ret = test_get_2Dimage_array_info_single( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} diff --git a/test_conformance/images/kernel_image_methods/test_3D.cpp b/test_conformance/images/kernel_image_methods/test_3D.cpp new file mode 100644 index 00000000..1e8237be --- /dev/null +++ b/test_conformance/images/kernel_image_methods/test_3D.cpp @@ -0,0 +1,131 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern bool gDebugTrace, gTestSmallImages, gTestMaxImages; + +extern int test_get_image_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d ); + +int test_get_image_info_3D( cl_device_id device, cl_image_format *format ) +{ + size_t maxWidth, maxHeight, maxDepth; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + RandomSeed seed( gRandomSeed ); + size_t pixelSize; + + imageInfo.type = CL_MEM_OBJECT_IMAGE3D; + imageInfo.format = format; + pixelSize = get_pixel_size( imageInfo.format ); + + int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 3D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + for( imageInfo.depth = 2; imageInfo.depth < 9; imageInfo.depth++ ) + { + if( gDebugTrace ) + log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth ); + int ret = test_get_image_info_single( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, maxDepth, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE3D, imageInfo.format); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.depth = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + + log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + if( gDebugTrace ) + log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + if( test_get_image_info_single( device, &imageInfo, seed ) ) + return -1; + } + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + imageInfo.depth = (size_t)random_log_in_range( 16, (int)maxDepth / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth; + + do { + extraWidth++; + imageInfo.rowPitch += extraWidth; + } while ((imageInfo.rowPitch % pixelSize) != 0); + + size_t extraHeight = (int)random_log_in_range( 0, 8, seed ); + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight); + + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.depth * 4 * 4; + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxDepth ); + int ret = test_get_image_info_single( device, &imageInfo, seed ); + if( ret ) + return -1; + } + } + + return 0; +} + diff --git a/test_conformance/images/kernel_image_methods/test_loops.cpp b/test_conformance/images/kernel_image_methods/test_loops.cpp new file mode 100644 index 00000000..0c7a2b13 --- /dev/null +++ b/test_conformance/images/kernel_image_methods/test_loops.cpp @@ -0,0 +1,219 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern int gTypesToTest; +extern int gNormalizedModeToUse; +extern cl_channel_type gChannelTypeToUse; + + +extern bool gDebugTrace; + +extern int test_get_image_info_1D( cl_device_id device, cl_image_format *format ); +extern int test_get_image_info_2D( cl_device_id device, cl_image_format *format ); +extern int test_get_image_info_3D( cl_device_id device, cl_image_format *format ); +extern int test_get_image_info_1D_array( cl_device_id device, cl_image_format *format ); +extern int test_get_image_info_2D_array( cl_device_id device, cl_image_format *format ); + +static const char *str_1d_image = "1D"; +static const char *str_2d_image = "2D"; +static const char *str_3d_image = "3D"; +static const char *str_1d_image_array = "1D array"; +static const char *str_2d_image_array = "2D array"; + +static const char *convert_image_type_to_string(cl_mem_object_type imageType) +{ + const char *p; + switch (imageType) + { + case CL_MEM_OBJECT_IMAGE1D: + p = str_1d_image; + break; + case CL_MEM_OBJECT_IMAGE2D: + p = str_2d_image; + break; + case CL_MEM_OBJECT_IMAGE3D: + p = str_3d_image; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + p = str_1d_image_array; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + p = str_2d_image_array; + break; + } + return p; +} + + +int filter_formats( cl_image_format *formatList, bool *filterFlags, unsigned int formatCount, cl_channel_type *channelDataTypesToFilter ) +{ + int numSupported = 0; + for( unsigned int j = 0; j < formatCount; j++ ) + { + // If this format has been previously filtered, remove the filter + if( filterFlags[ j ] ) + filterFlags[ j ] = false; + + // Have we already discarded this via the command line? + if( gChannelTypeToUse != (cl_channel_type)-1 && gChannelTypeToUse != formatList[ j ].image_channel_data_type ) + { + filterFlags[ j ] = true; + continue; + } + + // Is given format standard channel order and type given by spec. We don't want to test it if this is vendor extension + if( !IsChannelOrderSupported( formatList[ j ].image_channel_order ) || !IsChannelTypeSupported( formatList[ j ].image_channel_data_type ) ) + { + filterFlags[ j ] = true; + continue; + } + + // We don't filter by channel type + if( !channelDataTypesToFilter ) + { + numSupported++; + continue; + } + + // Is the format supported? + int i; + for( i = 0; channelDataTypesToFilter[ i ] != (cl_channel_type)-1; i++ ) + { + if( formatList[ j ].image_channel_data_type == channelDataTypesToFilter[ i ] ) + { + numSupported++; + break; + } + } + if( channelDataTypesToFilter[ i ] == (cl_channel_type)-1 ) + { + // Format is NOT supported, so mark it as such + filterFlags[ j ] = true; + } + } + return numSupported; +} + +int get_format_list( cl_device_id device, cl_mem_object_type imageType, cl_image_format * &outFormatList, unsigned int &outFormatCount, cl_mem_flags flags ) +{ + extern clContextWrapper context; + int error = clGetSupportedImageFormats( context, (cl_mem_flags)flags, + imageType, 0, NULL, &outFormatCount ); + test_error( error, "Unable to get count of supported image formats" ); + + outFormatList = new cl_image_format[ outFormatCount ]; + error = clGetSupportedImageFormats( context, (cl_mem_flags)flags, + imageType, outFormatCount, outFormatList, NULL ); + test_error( error, "Unable to get list of supported image formats" ); + return 0; +} + + +int test_image_type( cl_device_id device, cl_mem_object_type imageType, cl_mem_flags flags ) +{ + log_info( "Running %s %s-only tests...\n", convert_image_type_to_string(imageType), flags == CL_MEM_READ_ONLY ? "read" : "write" ); + + int ret = 0; + + // Grab the list of supported image formats for integer reads + cl_image_format *formatList; + bool *filterFlags; + unsigned int numFormats; + + if( get_format_list( device, imageType, formatList, numFormats, flags ) ) + return -1; + + filterFlags = new bool[ numFormats ]; + if( filterFlags == NULL ) + { + log_error( "ERROR: Out of memory allocating filter flags list!\n" ); + return -1; + } + memset( filterFlags, 0, sizeof( bool ) * numFormats ); + filter_formats( formatList, filterFlags, numFormats, 0 ); + + // Run the format list + for( unsigned int i = 0; i < numFormats; i++ ) + { + int test_return = 0; + if( filterFlags[i] ) + { + log_info( "NOT RUNNING: " ); + print_header( &formatList[ i ], false ); + continue; + } + + print_header( &formatList[ i ], false ); + + gTestCount++; + + switch (imageType) { + case CL_MEM_OBJECT_IMAGE1D: + test_return = test_get_image_info_1D( device, &formatList[ i ] ); + break; + case CL_MEM_OBJECT_IMAGE2D: + test_return = test_get_image_info_2D( device, &formatList[ i ] ); + break; + case CL_MEM_OBJECT_IMAGE3D: + test_return = test_get_image_info_3D( device, &formatList[ i ] ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + test_return = test_get_image_info_1D_array( device, &formatList[ i ] ); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + test_return = test_get_image_info_2D_array( device, &formatList[ i ] ); + break; + } + + if (test_return) { + gTestFailure++; + log_error( "FAILED: " ); + print_header( &formatList[ i ], true ); + log_info( "\n" ); + } + + ret += test_return; + } + + delete filterFlags; + delete formatList; + + return ret; +} + +int test_image_set( cl_device_id device, cl_mem_object_type imageType ) +{ + int version_check; + if ((version_check = check_opencl_version(device,1,2))) { + switch (imageType) { + case CL_MEM_OBJECT_IMAGE1D: + test_missing_feature(version_check, "image_1D"); + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + test_missing_feature(version_check, "image_1D_array"); + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + test_missing_feature(version_check, "image_2D_array"); + } + } + + int ret = 0; + ret += test_image_type( device, imageType, CL_MEM_READ_ONLY ); + ret += test_image_type( device, imageType, CL_MEM_WRITE_ONLY ); + + return ret; +} diff --git a/test_conformance/images/kernel_read_write/CMakeLists.txt b/test_conformance/images/kernel_read_write/CMakeLists.txt new file mode 100644 index 00000000..92109df2 --- /dev/null +++ b/test_conformance/images/kernel_read_write/CMakeLists.txt @@ -0,0 +1,29 @@ +set(MODULE_NAME IMAGE_STREAMS) + +set(${MODULE_NAME}_SOURCES + main.cpp + test_iterations.cpp + test_loops.cpp + test_read_1D.cpp + test_read_1D_array.cpp + test_read_2D_array.cpp + test_read_3D.cpp + test_write_image.cpp + test_write_1D.cpp + test_write_1D_array.cpp + test_write_2D_array.cpp + test_write_3D.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/threadTesting.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/imageHelpers.cpp + ../../../test_common/harness/mt19937.c + ../../../test_common/harness/conversions.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/typeWrappers.cpp + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) + diff --git a/test_conformance/images/kernel_read_write/Jamfile b/test_conformance/images/kernel_read_write/Jamfile new file mode 100644 index 00000000..db1d2455 --- /dev/null +++ b/test_conformance/images/kernel_read_write/Jamfile @@ -0,0 +1,19 @@ +project + : requirements +# gcc:-xc++ +# msvc:"/TP" + ; + +exe test_image_streams + : main.cpp + test_iterations.cpp + test_loops.cpp + test_read_3D.cpp + test_write_image.cpp + ; + +install dist + : test_image_streams + : debug:$(DIST)/debug/tests/test_conformance/images/kernel_read_write + release:$(DIST)/release/tests/test_conformance/images/kernel_read_write + ; diff --git a/test_conformance/images/kernel_read_write/Makefile b/test_conformance/images/kernel_read_write/Makefile new file mode 100644 index 00000000..a9af0878 --- /dev/null +++ b/test_conformance/images/kernel_read_write/Makefile @@ -0,0 +1,56 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.cpp \ + test_iterations.cpp \ + test_loops.cpp \ + test_write_image.cpp \ + test_read_1D.cpp \ + test_read_3D.cpp \ + test_read_1D_array.cpp \ + test_read_2D_array.cpp \ + test_write_1D.cpp \ + test_write_3D.cpp \ + test_write_1D_array.cpp \ + test_write_2D_array.cpp \ + ../../../test_common/harness/errorHelpers.c \ + ../../../test_common/harness/threadTesting.c \ + ../../../test_common/harness/kernelHelpers.c \ + ../../../test_common/harness/imageHelpers.cpp \ + ../../../test_common/harness/conversions.c \ + ../../../test_common/harness/testHarness.c \ + ../../../test_common/harness/mt19937.c \ + ../../../test_common/harness/typeWrappers.cpp + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = +HEADERS = +TARGET = test_image_streams +INCLUDE = -I../../test_common/harness +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os +CC = c++ +CXX = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/images/kernel_read_write/main.cpp b/test_conformance/images/kernel_read_write/main.cpp new file mode 100644 index 00000000..3a7f1047 --- /dev/null +++ b/test_conformance/images/kernel_read_write/main.cpp @@ -0,0 +1,659 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../../test_common/harness/compat.h" + +#include +#include + +#if !defined(_WIN32) +#include +#include +#endif + +#include "../testBase.h" +#include "../../../test_common/harness/fpcontrol.h" +#include "../../../test_common/harness/parseParameters.h" + +#include + +#if defined(__PPC__) +// Global varaiable used to hold the FPU control register state. The FPSCR register can not +// be used because not all Power implementations retain or observed the NI (non-IEEE +// mode) bit. +__thread fpu_control_t fpu_control = 0; +#endif + +bool gDebugTrace = false, gExtraValidateInfo = false, gDisableOffsets = false, gTestSmallImages = false, gTestMaxImages = false, gTestRounding = false, gTestImage2DFromBuffer = 0, gTestMipmaps = false; +cl_filter_mode gFilterModeToUse = (cl_filter_mode)-1; +// Default is CL_MEM_USE_HOST_PTR for the test +cl_mem_flags gMemFlagsToUse = CL_MEM_USE_HOST_PTR; +bool gUseKernelSamplers = false; +int gTypesToTest = 0; +cl_addressing_mode gAddressModeToUse = (cl_addressing_mode)-1; +int gNormalizedModeToUse = 7; +cl_channel_type gChannelTypeToUse = (cl_channel_type)-1; +cl_channel_order gChannelOrderToUse = (cl_channel_order)-1; +bool gEnablePitch = false; +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; + +int gtestTypesToRun = 0; +cl_command_queue queue; +cl_context context; + +#define MAX_ALLOWED_STD_DEVIATION_IN_MB 8.0 + +void printUsage( const char *execName ) +{ + const char *p = strrchr( execName, '/' ); + if( p != NULL ) + execName = p + 1; + + log_info( "Usage: %s [read] [write] [CL_FILTER_LINEAR|CL_FILTER_NEAREST] [no_offsets] [debug_trace] [small_images]\n", execName ); + log_info( "Where:\n" ); + log_info( "\n" ); + log_info( "\tThe following flags specify what kinds of operations to test. They can be combined; if none are specified, all are tested:\n" ); + log_info( "\t\tread - Tests reading from an image\n" ); + log_info( "\t\twrite - Tests writing to an image (can be specified with read to run both; default is both)\n" ); + log_info( "\n" ); + log_info( "\tThe following flags specify the types to test. They can be combined; if none are specified, all are tested:\n" ); + log_info( "\t\tint - Test integer I/O (read_imagei, write_imagei)\n" ); + log_info( "\t\tuint - Test unsigned integer I/O (read_imageui, write_imageui)\n" ); + log_info( "\t\tfloat - Test float I/O (read_imagef, write_imagef)\n" ); + log_info( "\n" ); + log_info( "\tCL_FILTER_LINEAR - Only tests formats with CL_FILTER_LINEAR filtering\n" ); + log_info( "\tCL_FILTER_NEAREST - Only tests formats with CL_FILTER_NEAREST filtering\n" ); + log_info( "\n" ); + log_info( "\tNORMALIZED - Only tests formats with NORMALIZED coordinates\n" ); + log_info( "\tUNNORMALIZED - Only tests formats with UNNORMALIZED coordinates\n" ); + log_info( "\n" ); + log_info( "\tCL_ADDRESS_CLAMP - Only tests formats with CL_ADDRESS_CLAMP addressing\n" ); + log_info( "\tCL_ADDRESS_CLAMP_TO_EDGE - Only tests formats with CL_ADDRESS_CLAMP_TO_EDGE addressing\n" ); + log_info( "\tCL_ADDRESS_REPEAT - Only tests formats with CL_ADDRESS_REPEAT addressing\n" ); + log_info( "\tCL_ADDRESS_MIRRORED_REPEAT - Only tests formats with CL_ADDRESS_MIRRORED_REPEAT addressing\n" ); + log_info( "\n" ); + log_info( "You may also use appropriate CL_ channel type and ordering constants.\n" ); + log_info( "\n" ); + log_info( "\t1D - Only test 1D images\n" ); + log_info( "\t2D - Only test 2D images\n" ); + log_info( "\t3D - Only test 3D images\n" ); + log_info( "\t1Darray - Only test 1D image arrays\n" ); + log_info( "\t2Darray - Only test 2D image arrays\n" ); + log_info( "\n" ); + log_info( "\tlocal_samplers - Use samplers declared in the kernel functions instead of passed in as arguments\n" ); + log_info( "\n" ); + log_info( "\tThe following specify to use the specific flag to allocate images to use in the tests:\n" ); + log_info( "\t\tCL_MEM_COPY_HOST_PTR\n" ); + log_info( "\t\tCL_MEM_USE_HOST_PTR (default)\n" ); + log_info( "\t\tCL_MEM_ALLOC_HOST_PTR\n" ); + log_info( "\t\tNO_HOST_PTR - Specifies to use none of the above flags\n" ); + log_info( "\n" ); + log_info( "\tThe following modify the types of images tested:\n" ); + log_info( "\t\tsmall_images - Runs every format through a loop of widths 1-13 and heights 1-9, instead of random sizes\n" ); + log_info( "\t\tmax_images - Runs every format through a set of size combinations with the max values, max values - 1, and max values / 128\n" ); + log_info( "\t\trounding - Runs every format through a single image filled with every possible value for that image format, to verify rounding works properly\n" ); + log_info( "\n" ); + log_info( "\tno_offsets - Disables offsets when testing reads (can be good for diagnosing address repeating/clamping problems)\n" ); + log_info( "\tdebug_trace - Enables additional debug info logging\n" ); + log_info( "\textra_validate - Enables additional validation failure debug information\n" ); + log_info( "\tuse_pitches - Enables row and slice pitches\n" ); + log_info( "\ttest_mipmaps - Enables mipmapped images\n"); +} + +extern int test_image_set( cl_device_id device, test_format_set_fn formatTestFn, cl_mem_object_type imageType ); + +/** read_write images only support sampler-less read buildt-ins which require special settings + * for some global parameters. This pair of functions temporarily overwrite those global parameters + * and then recover them after completing a read_write test. + */ +static void overwrite_global_params_for_read_write_test( bool *tTestMipmaps, + bool *tDisableOffsets, + bool *tNormalizedModeToUse, + cl_filter_mode *tFilterModeToUse) +{ + log_info("Overwrite global settings for read_write image tests. The overwritten values:\n"); + log_info("gTestMipmaps = false, gDisableOffsets = true, gNormalizedModeToUse = false, gFilterModeToUse = CL_FILTER_NEAREST\n" ); + // mipmap images only support sampler read built-in while read_write images only support + // sampler-less read built-in. Hence we cannot test mipmap for read_write image. + *tTestMipmaps = gTestMipmaps; + gTestMipmaps = false; + + // Read_write images are read by sampler-less read which does not handle out-of-bound read + // It's application responsibility to make sure that the read happens in-bound + // Therefore we should not enable offset in testing read_write images because it will cause out-of-bound + *tDisableOffsets = gDisableOffsets; + gDisableOffsets = true; + + // The sampler-less read image functions behave exactly as the corresponding read image functions + + + *tNormalizedModeToUse = gNormalizedModeToUse; + gNormalizedModeToUse = false; + *tFilterModeToUse = gFilterModeToUse; + gFilterModeToUse = CL_FILTER_NEAREST; +} + +/** Recover the global settings overwritten for read_write tests. This is necessary because + * there may be other tests (i.e. read or write) are called together with read_write test. + */ +static void recover_global_params_from_read_write_test(bool tTestMipmaps, + bool tDisableOffsets, + bool tNormalizedModeToUse, + cl_filter_mode tFilterModeToUse) +{ + gTestMipmaps = tTestMipmaps; + gDisableOffsets = tDisableOffsets; + gNormalizedModeToUse = tNormalizedModeToUse; + gFilterModeToUse = tFilterModeToUse; +} + +int main(int argc, const char *argv[]) +{ + cl_platform_id platform; + cl_device_id device; + cl_channel_type chanType; + cl_channel_order chanOrder; + char str[ 128 ]; + int testTypesToRun = 0; + int testMethods = 0; + bool randomize = false; + bool tTestMipMaps = false; + bool tDisableOffsets = false; + bool tNormalizedModeToUse = false; + cl_filter_mode tFilterModeToUse = (cl_filter_mode)-1; + + test_start(); + + argc = parseCustomParam(argc, argv); + if (argc == -1) + { + test_finish(); + return -1; + } + + //Check CL_DEVICE_TYPE environment variable + checkDeviceTypeOverride( &gDeviceType ); + + // Parse arguments + for( int i = 1; i < argc; i++ ) + { + strncpy( str, argv[ i ], sizeof( str ) - 1 ); + + if( strcmp( str, "cpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_CPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_CPU; + else if( strcmp( str, "gpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_GPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_GPU; + else if( strcmp( str, "accelerator" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( str, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_DEFAULT; + + else if( strcmp( str, "debug_trace" ) == 0 ) + gDebugTrace = true; + + else if( strcmp( str, "CL_FILTER_NEAREST" ) == 0 || strcmp( str, "NEAREST" ) == 0 ) + gFilterModeToUse = CL_FILTER_NEAREST; + else if( strcmp( str, "CL_FILTER_LINEAR" ) == 0 || strcmp( str, "LINEAR" ) == 0 ) + gFilterModeToUse = CL_FILTER_LINEAR; + + else if( strcmp( str, "CL_ADDRESS_NONE" ) == 0 ) + gAddressModeToUse = CL_ADDRESS_NONE; + else if( strcmp( str, "CL_ADDRESS_CLAMP" ) == 0 ) + gAddressModeToUse = CL_ADDRESS_CLAMP; + else if( strcmp( str, "CL_ADDRESS_CLAMP_TO_EDGE" ) == 0 ) + gAddressModeToUse = CL_ADDRESS_CLAMP_TO_EDGE; + else if( strcmp( str, "CL_ADDRESS_REPEAT" ) == 0 ) + gAddressModeToUse = CL_ADDRESS_REPEAT; + else if( strcmp( str, "CL_ADDRESS_MIRRORED_REPEAT" ) == 0 ) + gAddressModeToUse = CL_ADDRESS_MIRRORED_REPEAT; + + else if( strcmp( str, "NORMALIZED" ) == 0 ) + gNormalizedModeToUse = true; + else if( strcmp( str, "UNNORMALIZED" ) == 0 ) + gNormalizedModeToUse = false; + + + else if( strcmp( str, "no_offsets" ) == 0 ) + gDisableOffsets = true; + else if( strcmp( str, "small_images" ) == 0 ) + gTestSmallImages = true; + else if( strcmp( str, "max_images" ) == 0 ) + gTestMaxImages = true; + else if( strcmp( str, "use_pitches" ) == 0 ) + gEnablePitch = true; + else if( strcmp( str, "rounding" ) == 0 ) + gTestRounding = true; + else if( strcmp( str, "extra_validate" ) == 0 ) + gExtraValidateInfo = true; + else if( strcmp( str, "test_mipmaps" ) == 0 ) { + // 2.0 Spec does not allow using mem flags, unnormalized coordinates with mipmapped images + gTestMipmaps = true; + gMemFlagsToUse = 0; + gNormalizedModeToUse = true; + } + + else if( strcmp( str, "read" ) == 0 ) + testTypesToRun |= kReadTests; + else if( strcmp( str, "write" ) == 0 ) + testTypesToRun |= kWriteTests; + else if( strcmp( str, "read_write" ) == 0 ) + { + testTypesToRun |= kReadWriteTests; + } + + else if( strcmp( str, "local_samplers" ) == 0 ) + gUseKernelSamplers = true; + + else if( strcmp( str, "int" ) == 0 ) + gTypesToTest |= kTestInt; + else if( strcmp( str, "uint" ) == 0 ) + gTypesToTest |= kTestUInt; + else if( strcmp( str, "float" ) == 0 ) + gTypesToTest |= kTestFloat; + + else if( strcmp( str, "randomize" ) == 0 ) + randomize = true; + + else if ( strcmp( str, "1D" ) == 0 ) + testMethods |= k1D; + else if( strcmp( str, "2D" ) == 0 ) + testMethods |= k2D; + else if( strcmp( str, "3D" ) == 0 ) + testMethods |= k3D; + else if( strcmp( str, "1Darray" ) == 0 ) + testMethods |= k1DArray; + else if( strcmp( str, "2Darray" ) == 0 ) + testMethods |= k2DArray; + + else if( strcmp( str, "CL_MEM_COPY_HOST_PTR" ) == 0 || strcmp( str, "COPY_HOST_PTR" ) == 0 ) + gMemFlagsToUse = CL_MEM_COPY_HOST_PTR; + else if( strcmp( str, "CL_MEM_USE_HOST_PTR" ) == 0 || strcmp( str, "USE_HOST_PTR" ) == 0 ) + gMemFlagsToUse = CL_MEM_USE_HOST_PTR; + else if( strcmp( str, "CL_MEM_ALLOC_HOST_PTR" ) == 0 || strcmp( str, "ALLOC_HOST_PTR" ) == 0 ) + gMemFlagsToUse = CL_MEM_ALLOC_HOST_PTR; + else if( strcmp( str, "NO_HOST_PTR" ) == 0 ) + gMemFlagsToUse = 0; + + else if( strcmp( str, "help" ) == 0 || strcmp( str, "?" ) == 0 ) + { + printUsage( argv[ 0 ] ); + return -1; + } + + else if( ( chanType = get_channel_type_from_name( str ) ) != (cl_channel_type)-1 ) + gChannelTypeToUse = chanType; + + else if( ( chanOrder = get_channel_order_from_name( str ) ) != (cl_channel_order)-1 ) + gChannelOrderToUse = chanOrder; + else + { + log_error( "ERROR: Unknown argument %d: %s. Exiting....\n", i, str ); + return -1; + } + + } + + if (testMethods == 0) + testMethods = k1D | k2D | k3D | k1DArray | k2DArray; + if( testTypesToRun == 0 ) + testTypesToRun = kAllTests; + if( gTypesToTest == 0 ) + gTypesToTest = kTestAllTypes; + +#if defined( __APPLE__ ) +#if defined( __i386__ ) || defined( __x86_64__ ) +#define kHasSSE3 0x00000008 +#define kHasSupplementalSSE3 0x00000100 +#define kHasSSE4_1 0x00000400 +#define kHasSSE4_2 0x00000800 + /* check our environment for a hint to disable SSE variants */ + { + const char *env = getenv( "CL_MAX_SSE" ); + if( env ) + { + extern int _cpu_capabilities; + int mask = 0; + if( 0 == strcmp( env, "SSE4.1" ) ) + mask = kHasSSE4_2; + else if( 0 == strcmp( env, "SSSE3" ) ) + mask = kHasSSE4_2 | kHasSSE4_1; + else if( 0 == strcmp( env, "SSE3" ) ) + mask = kHasSSE4_2 | kHasSSE4_1 | kHasSupplementalSSE3; + else if( 0 == strcmp( env, "SSE2" ) ) + mask = kHasSSE4_2 | kHasSSE4_1 | kHasSupplementalSSE3 | kHasSSE3; + + log_info( "*** Environment: CL_MAX_SSE = %s ***\n", env ); + _cpu_capabilities &= ~mask; + } + } +#endif +#endif + + // Seed the random # generators + if( randomize ) + { + gRandomSeed = (cl_uint) time( NULL ); + gReSeed = 1; + log_info( "Random seed: %u\n", gRandomSeed ); + } + + int error; + // Get our platform + error = clGetPlatformIDs(1, &platform, NULL); + if( error ) + { + print_error( error, "Unable to get platform" ); + test_finish(); + return -1; + } + + // Get our device + cl_uint num_devices = 0; + error = clGetDeviceIDs(platform, gDeviceType, 0, NULL, &num_devices ); + if( error ) + { + print_error( error, "Unable to get the number of devices" ); + test_finish(); + return -1; + } + + std::vector devices(num_devices); + error = clGetDeviceIDs(platform, gDeviceType, num_devices, &devices[0], NULL ); + if( error ) + { + print_error( error, "Unable to get specified device type" ); + test_finish(); + return -1; + } + + int device_index = 0; + char* device_index_str = getenv("CL_DEVICE_INDEX"); + if (device_index_str && ((device_index = atoi(device_index_str))) >= num_devices) { + log_error("CL_DEVICE_INDEX=%d is greater than the number of devices %d\n",device_index,num_devices); + test_finish(); + return -1; + } + + device = devices[device_index]; + + // Get the device type so we know if it is a GPU even if default is passed in. + error = clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(gDeviceType), &gDeviceType, NULL); + if( error ) + { + print_error( error, "Unable to get device type" ); + test_finish(); + return -1; + } + + if( printDeviceHeader( device ) != CL_SUCCESS ) + { + test_finish(); + return -1; + } + + // Check for image support + if(checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) { + log_info("Device does not support images. Skipping test.\n"); + test_finish(); + return 0; + } + + // Create a context to test with + context = clCreateContext( NULL, 1, &device, notify_callback, NULL, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create testing context" ); + test_finish(); + return -1; + } + + // Create a queue against the context + queue = clCreateCommandQueueWithProperties( context, device, 0, &error ); + if( error != CL_SUCCESS ) + { + print_error( error, "Unable to create testing command queue" ); + test_finish(); + return -1; + } + + if( gTestSmallImages ) + log_info( "Note: Using small test images\n" ); + + // On most platforms which support denorm, default is FTZ off. However, + // on some hardware where the reference is computed, default might be flush denorms to zero e.g. arm. + // This creates issues in result verification. Since spec allows the implementation to either flush or + // not flush denorms to zero, an implementation may choose not to flush i.e. return denorm result whereas + // reference result may be zero (flushed denorm). Hence we need to disable denorm flushing on host side + // where reference is being computed to make sure we get non-flushed reference result. If implementation + // returns flushed result, we correctly take care of that in verification code. + + FPU_mode_type oldMode; + DisableFTZ(&oldMode); + + // Run the test now + int ret = 0; + if (testMethods & k1D) + { + if (testTypesToRun & kReadTests) + { + gtestTypesToRun = kReadTests; + ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE1D ); + } + + if (testTypesToRun & kWriteTests) + { + gtestTypesToRun = kWriteTests; + ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE1D ); + } + + if ((testTypesToRun & kReadWriteTests) && !gTestMipmaps) + { + gtestTypesToRun = kReadWriteTests; + overwrite_global_params_for_read_write_test(&tTestMipMaps, &tDisableOffsets, &tNormalizedModeToUse, &tFilterModeToUse); + ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE1D ); + ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE1D ); + recover_global_params_from_read_write_test(tTestMipMaps, tDisableOffsets, tNormalizedModeToUse, tFilterModeToUse); + } + } + if (testMethods & k2D) + { + if (testTypesToRun & kReadTests) + { + gtestTypesToRun = kReadTests; + ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE2D ); + if (is_extension_available(device, "cl_khr_image2d_from_buffer")) + { + log_info("Testing read_image{f | i | ui} for 2D image from buffer\n"); + // NOTE: for 2D image from buffer test, gTestSmallImages, gTestMaxImages, gTestRounding and gTestMipmaps must be false + if (gTestSmallImages == false && gTestMaxImages == false && gTestRounding == false && gTestMipmaps == false) + { + cl_mem_flags saved_gMemFlagsToUse = gMemFlagsToUse; + gTestImage2DFromBuffer = true; + // disable CL_MEM_USE_HOST_PTR for 1.2 extension but enable this for 2.0 + gMemFlagsToUse = CL_MEM_COPY_HOST_PTR; + ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE2D ); + gTestImage2DFromBuffer = false; + gMemFlagsToUse = saved_gMemFlagsToUse; + } + } + } + + if (testTypesToRun & kWriteTests) + { + gtestTypesToRun = kWriteTests; + ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE2D ); + if (is_extension_available(device, "cl_khr_image2d_from_buffer")) + { + log_info("Testing write_image{f | i | ui} for 2D image from buffer\n"); + // NOTE: for 2D image from buffer test, gTestSmallImages, gTestMaxImages,gTestRounding and gTestMipmaps must be false + if (gTestSmallImages == false && gTestMaxImages == false && gTestRounding == false && gTestMipmaps == false) + { + bool saved_gEnablePitch = gEnablePitch; + cl_mem_flags saved_gMemFlagsToUse = gMemFlagsToUse; + gEnablePitch = true; + // disable CL_MEM_USE_HOST_PTR for 1.2 extension but enable this for 2.0 + gMemFlagsToUse = CL_MEM_COPY_HOST_PTR; + gTestImage2DFromBuffer = true; + ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE2D ); + gTestImage2DFromBuffer = false; + gMemFlagsToUse = saved_gMemFlagsToUse; + gEnablePitch = saved_gEnablePitch; + } + } + } + + if ((testTypesToRun & kReadWriteTests) && !gTestMipmaps) + { + gtestTypesToRun = kReadWriteTests; + overwrite_global_params_for_read_write_test(&tTestMipMaps, &tDisableOffsets, &tNormalizedModeToUse, &tFilterModeToUse); + ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE2D ); + if (is_extension_available(device, "cl_khr_image2d_from_buffer")) + { + log_info("Testing read_image{f | i | ui} for 2D image from buffer\n"); + // NOTE: for 2D image from buffer test, gTestSmallImages, gTestMaxImages, gTestRounding and gTestMipmaps must be false + if (gTestSmallImages == false && gTestMaxImages == false && gTestRounding == false && gTestMipmaps == false) + { + cl_mem_flags saved_gMemFlagsToUse = gMemFlagsToUse; + gTestImage2DFromBuffer = true; + // disable CL_MEM_USE_HOST_PTR for 1.2 extension but enable this for 2.0 + gMemFlagsToUse = CL_MEM_COPY_HOST_PTR; + ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE2D ); + gTestImage2DFromBuffer = false; + gMemFlagsToUse = saved_gMemFlagsToUse; + } + } + + ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE2D ); + if (is_extension_available(device, "cl_khr_image2d_from_buffer")) + { + log_info("Testing write_image{f | i | ui} for 2D image from buffer\n"); + // NOTE: for 2D image from buffer test, gTestSmallImages, gTestMaxImages,gTestRounding and gTestMipmaps must be false + if (gTestSmallImages == false && gTestMaxImages == false && gTestRounding == false && gTestMipmaps == false) + { + bool saved_gEnablePitch = gEnablePitch; + cl_mem_flags saved_gMemFlagsToUse = gMemFlagsToUse; + gEnablePitch = true; + // disable CL_MEM_USE_HOST_PTR for 1.2 extension but enable this for 2.0 + gMemFlagsToUse = CL_MEM_COPY_HOST_PTR; + gTestImage2DFromBuffer = true; + ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE2D ); + gTestImage2DFromBuffer = false; + gMemFlagsToUse = saved_gMemFlagsToUse; + gEnablePitch = saved_gEnablePitch; + } + } + recover_global_params_from_read_write_test(tTestMipMaps, tDisableOffsets, tNormalizedModeToUse, tFilterModeToUse); + } + } + if (testMethods & k3D) + { + if (testTypesToRun & kReadTests) + { + gtestTypesToRun = kReadTests; + ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE3D ); + } + + if (testTypesToRun & kWriteTests) + { + gtestTypesToRun = kWriteTests; + ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE3D ); + } + + if ((testTypesToRun & kReadWriteTests) && !gTestMipmaps) + { + gtestTypesToRun = kReadWriteTests; + overwrite_global_params_for_read_write_test(&tTestMipMaps, &tDisableOffsets, &tNormalizedModeToUse, &tFilterModeToUse); + ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE3D ); + ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE3D ); + recover_global_params_from_read_write_test(tTestMipMaps, tDisableOffsets, tNormalizedModeToUse, tFilterModeToUse); + } + } + if (testMethods & k1DArray) + { + if (testTypesToRun & kReadTests) + { + gtestTypesToRun = kReadTests; + ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE1D_ARRAY ); + } + + if (testTypesToRun & kWriteTests) + { + gtestTypesToRun = kWriteTests; + ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE1D_ARRAY ); + } + + if ((testTypesToRun & kReadWriteTests) && !gTestMipmaps) + { + gtestTypesToRun = kReadWriteTests; + overwrite_global_params_for_read_write_test(&tTestMipMaps, &tDisableOffsets, &tNormalizedModeToUse, &tFilterModeToUse); + ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE1D_ARRAY ); + ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE1D_ARRAY ); + recover_global_params_from_read_write_test(tTestMipMaps, tDisableOffsets, tNormalizedModeToUse, tFilterModeToUse); + } + } + if (testMethods & k2DArray) + { + if (testTypesToRun & kReadTests) + { + gtestTypesToRun = kReadTests; + ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE2D_ARRAY ); + } + + if (testTypesToRun & kWriteTests) + { + gtestTypesToRun = kWriteTests; + ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE2D_ARRAY ); + } + + if ((testTypesToRun & kReadWriteTests) && !gTestMipmaps) + { + gtestTypesToRun = kReadWriteTests; + overwrite_global_params_for_read_write_test(&tTestMipMaps, &tDisableOffsets, &tNormalizedModeToUse, &tFilterModeToUse); + ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE2D_ARRAY ); + ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE2D_ARRAY ); + recover_global_params_from_read_write_test(tTestMipMaps, tDisableOffsets, tNormalizedModeToUse, tFilterModeToUse); + } + } + + // Restore FP state before leaving + RestoreFPState(&oldMode); + + error = clFinish(queue); + if (error) + print_error(error, "clFinish failed."); + + clReleaseContext(context); + clReleaseCommandQueue(queue); + + if (gTestFailure == 0) { + if (gTestCount > 1) + log_info("PASSED %d of %d tests.\n", gTestCount, gTestCount); + else + log_info("PASSED test.\n"); + } else if (gTestFailure > 0) { + if (gTestCount > 1) + log_error("FAILED %d of %d tests.\n", gTestFailure, gTestCount); + else + log_error("FAILED test.\n"); + } + + // Clean up + test_finish(); + + if (gTestFailure > 0) + return gTestFailure; + + return ret; +} diff --git a/test_conformance/images/kernel_read_write/test_iterations.cpp b/test_conformance/images/kernel_read_write/test_iterations.cpp new file mode 100644 index 00000000..854ccc8b --- /dev/null +++ b/test_conformance/images/kernel_read_write/test_iterations.cpp @@ -0,0 +1,1765 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" +#include + +#if defined( __APPLE__ ) + #include + #include + #include +#endif + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gExtraValidateInfo, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestImage2DFromBuffer, gTestMipmaps; +extern cl_device_type gDeviceType; +extern bool gUseKernelSamplers; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_mem_flags gMemFlagsToUse; +extern int gtestTypesToRun; + +#define MAX_TRIES 1 +#define MAX_CLAMPED 1 + +// Utility function to clamp down image sizes for certain tests to avoid +// using too much memory. +static size_t reduceImageSizeRange(size_t maxDimSize) { + size_t DimSize = maxDimSize/32; + if (DimSize < (size_t) 16) + return 16; + else if (DimSize > (size_t) 256) + return 256; + else + return DimSize; +} + +const char *read2DKernelSourcePattern = +"__kernel void sample_kernel( read_only %s input,%s __global float *xOffsets, __global float *yOffsets, __global %s%s *results %s)\n" +"{\n" +"%s" +" int tidX = get_global_id(0), tidY = get_global_id(1);\n" +"%s" +"%s" +" results[offset] = read_image%s( input, imageSampler, coords %s);\n" +"}"; + +const char *read_write2DKernelSourcePattern = +"__kernel void sample_kernel( read_write %s input,%s __global float *xOffsets, __global float *yOffsets, __global %s%s *results %s)\n" +"{\n" +"%s" +" int tidX = get_global_id(0), tidY = get_global_id(1);\n" +"%s" +"%s" +" results[offset] = read_image%s( input, coords %s);\n" +"}"; + +const char *intCoordKernelSource = +" int2 coords = (int2)( xOffsets[offset], yOffsets[offset]);\n"; + +const char *floatKernelSource = +" float2 coords = (float2)( (float)( xOffsets[offset] ), (float)( yOffsets[offset] ) );\n"; + +static const char *samplerKernelArg = " sampler_t imageSampler,"; + +static const char *lodOffsetSource = +" unsigned int lod_int = (unsigned int) lod;\n" +" int width_lod = (get_image_width(input) >> lod_int) ?(get_image_width(input) >> lod_int):1 ;\n" +" int offset = tidY*width_lod + tidX;\n"; + +static const char *offsetSource = +" int offset = tidY*get_image_width(input) + tidX;\n"; + +#define ABS_ERROR( result, expected ) ( fabsf( (float)expected - (float)result ) ) + +extern void read_image_pixel_float( void *imageData, image_descriptor *imageInfo, + int x, int y, int z, float *outData ); +template int determine_validation_error( void *imagePtr, image_descriptor *imageInfo, image_sampler_data *imageSampler, + T *resultPtr, T * expected, float error, + float x, float y, float xAddressOffset, float yAddressOffset, size_t j, int &numTries, int &numClamped, bool printAsFloat, int lod = 0 ) +{ + int actualX, actualY; + int found = debug_find_pixel_in_image( imagePtr, imageInfo, resultPtr, &actualX, &actualY, NULL, lod ); + bool clampingErr = false, clamped = false, otherClampingBug = false; + int clampedX, clampedY, ignoreMe; + + clamped = get_integer_coords_offset( x, y, 0.f, xAddressOffset, yAddressOffset, 0.0f, imageInfo->width, imageInfo->height, 0, imageSampler, imageInfo, clampedX, clampedY, ignoreMe ); + + if( found ) + { + // Is it a clamping bug? + if( clamped && clampedX == actualX && clampedY == actualY ) + { + if( (--numClamped) == 0 ) + { + log_error( "ERROR: TEST FAILED: Read is erroneously clamping coordinates for image size %ld x %ld!\n", imageInfo->width, imageInfo->height ); + if (imageInfo->format->image_channel_order == CL_DEPTH) + { + if( printAsFloat ) + { + log_error( "Sample %d: coord {%f(%.6a), %f(%.6a)} did not validate!\n\tExpected (%g),\n\tgot (%g),\n\terror of %g\n", + (int)j, x, x, y, y, (float)expected[ 0 ], (float)resultPtr[ 0 ], error ); + } + else + { + log_error( "Sample %d: coord {%f(%.6a), %f(%.6a)} did not validate!\n\tExpected (%x),\n\tgot (%x)\n", + (int)j, x, x, y, y, (int)expected[ 0 ], (int)resultPtr[ 0 ] ); + } + } + else + { + if( printAsFloat ) + { + log_error( "Sample %d: coord {%f(%.6a), %f(%.6a)} did not validate!\n\tExpected (%g,%g,%g,%g),\n\tgot (%g,%g,%g,%g),\n\terror of %g\n", + (int)j, x, x, y, y, (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ], + (float)resultPtr[ 0 ], (float)resultPtr[ 1 ], (float)resultPtr[ 2 ], (float)resultPtr[ 3 ], error ); + } + else + { + log_error( "Sample %d: coord {%f(%.6a), %f(%.6a)} did not validate!\n\tExpected (%x,%x,%x,%x),\n\tgot (%x,%x,%x,%x)\n", + (int)j, x, x, y, y, (int)expected[ 0 ], (int)expected[ 1 ], (int)expected[ 2 ], (int)expected[ 3 ], + (int)resultPtr[ 0 ], (int)resultPtr[ 1 ], (int)resultPtr[ 2 ], (int)resultPtr[ 3 ] ); + } + } + return 1; + } + clampingErr = true; + otherClampingBug = true; + } + } + if( clamped && !otherClampingBug ) + { + // If we are in clamp-to-edge mode and we're getting zeroes, it's possible we're getting border erroneously + if( resultPtr[ 0 ] == 0 && resultPtr[ 1 ] == 0 && resultPtr[ 2 ] == 0 && resultPtr[ 3 ] == 0 ) + { + if( (--numClamped) == 0 ) + { + log_error( "ERROR: TEST FAILED: Clamping is erroneously returning border color for image size %ld x %ld!\n", imageInfo->width, imageInfo->height ); + if (imageInfo->format->image_channel_order == CL_DEPTH) + { + if( printAsFloat ) + { + log_error( "Sample %d: coord {%f(%.6a), %f(%.6a)} did not validate!\n\tExpected (%g),\n\tgot (%g),\n\terror of %g\n", + (int)j, x, x, y, y, (float)expected[ 0 ], (float)resultPtr[ 0 ], error ); + } + else + { + log_error( "Sample %d: coord {%f(%.6a), %f(%.6a)} did not validate!\n\tExpected (%x),\n\tgot (%x)\n", + (int)j, x, x, y, y, (int)expected[ 0 ], (int)resultPtr[ 0 ] ); + } + } + else + { + if( printAsFloat ) + { + log_error( "Sample %d: coord {%f(%.6a), %f(%.6a)} did not validate!\n\tExpected (%g,%g,%g,%g),\n\tgot (%g,%g,%g,%g),\n\terror of %g\n", + (int)j, x, x, y, y, (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ], + (float)resultPtr[ 0 ], (float)resultPtr[ 1 ], (float)resultPtr[ 2 ], (float)resultPtr[ 3 ], error ); + } + else + { + log_error( "Sample %d: coord {%f(%.6a), %f(%.6a)} did not validate!\n\tExpected (%x,%x,%x,%x),\n\tgot (%x,%x,%x,%x)\n", + (int)j, x, x, y, y, (int)expected[ 0 ], (int)expected[ 1 ], (int)expected[ 2 ], (int)expected[ 3 ], + (int)resultPtr[ 0 ], (int)resultPtr[ 1 ], (int)resultPtr[ 2 ], (int)resultPtr[ 3 ] ); + } + } + return 1; + } + clampingErr = true; + } + } + if( !clampingErr ) + { + if (imageInfo->format->image_channel_order == CL_DEPTH) + { + if( printAsFloat ) + { + log_error( "Sample %d: coord {%f(%.6a), %f(%.6a)} did not validate!\n\tExpected (%g),\n\tgot (%g),\n\terror of %g\n", + (int)j, x, x, y, y, (float)expected[ 0 ], (float)resultPtr[ 0 ], error ); + } + else + { + log_error( "Sample %d: coord {%f(%.6a), %f(%.6a)} did not validate!\n\tExpected (%x),\n\tgot (%x)\n", + (int)j, x, x, y, y, (int)expected[ 0 ], (int)resultPtr[ 0 ] ); + } + } + else + { + if( printAsFloat ) + { + log_error( "Sample %d: coord {%f(%.6a), %f(%.6a)} did not validate!\n\tExpected (%g,%g,%g,%g),\n\tgot (%g,%g,%g,%g), error of %g\n", + (int)j, x, x, y, y, (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ], + (float)resultPtr[ 0 ], (float)resultPtr[ 1 ], (float)resultPtr[ 2 ], (float)resultPtr[ 3 ], error ); + } + else + { + log_error( "Sample %d: coord {%f(%.6a), %f(%.6a)} did not validate!\n\tExpected (%x,%x,%x,%x),\n\tgot (%x,%x,%x,%x)\n", + (int)j, x, x, y, y, (int)expected[ 0 ], (int)expected[ 1 ], (int)expected[ 2 ], (int)expected[ 3 ], + (int)resultPtr[ 0 ], (int)resultPtr[ 1 ], (int)resultPtr[ 2 ], (int)resultPtr[ 3 ] ); + } + } + log_error( "img size %ld,%ld (pitch %ld)", imageInfo->width, imageInfo->height, imageInfo->rowPitch ); + if( clamped ) + { + log_error( " which would clamp to %d,%d\n", clampedX, clampedY ); + } + if( printAsFloat && gExtraValidateInfo) + { + log_error( "Nearby values:\n" ); + log_error( "\t%d\t%d\t%d\t%d\n", clampedX - 2, clampedX - 1, clampedX, clampedX + 1 ); + for( int yOff = -2; yOff <= 1; yOff++ ) + { + float top[ 4 ], real[ 4 ], bot[ 4 ], bot2[ 4 ]; + read_image_pixel_float( imagePtr, imageInfo, clampedX - 2 , clampedY + yOff, 0, top ); + read_image_pixel_float( imagePtr, imageInfo, clampedX - 1 ,clampedY + yOff, 0, real ); + read_image_pixel_float( imagePtr, imageInfo, clampedX, clampedY + yOff, 0, bot ); + read_image_pixel_float( imagePtr, imageInfo, clampedX + 1, clampedY + yOff, 0, bot2 ); + if (imageInfo->format->image_channel_order == CL_DEPTH) + { + log_error( "%d\t(%g)",clampedY + yOff, top[0] ); + log_error( " (%g)", real[0] ); + log_error( " (%g)",bot[0] ); + log_error( " (%g)\n",bot2[0] ); + } + else + { + log_error( "%d\t(%g,%g,%g,%g)",clampedY + yOff, top[0], top[1], top[2], top[3] ); + log_error( " (%g,%g,%g,%g)", real[0], real[1], real[2], real[3] ); + log_error( " (%g,%g,%g,%g)",bot[0], bot[1], bot[2], bot[3] ); + log_error( " (%g,%g,%g,%g)\n",bot2[0], bot2[1], bot2[2], bot2[3] ); + } + } + + if( clampedY < 1 ) + { + log_error( "Nearby values:\n" ); + log_error( "\t%d\t%d\t%d\t%d\n", clampedX - 2, clampedX - 1, clampedX, clampedX + 1 ); + for( int yOff = (int)imageInfo->height - 2; yOff <= (int)imageInfo->height + 1; yOff++ ) + { + float top[ 4 ], real[ 4 ], bot[ 4 ], bot2[ 4 ]; + read_image_pixel_float( imagePtr, imageInfo, clampedX - 2 , clampedY + yOff, 0, top ); + read_image_pixel_float( imagePtr, imageInfo, clampedX - 1 ,clampedY + yOff, 0, real ); + read_image_pixel_float( imagePtr, imageInfo, clampedX, clampedY + yOff, 0, bot ); + read_image_pixel_float( imagePtr, imageInfo, clampedX + 1, clampedY + yOff, 0, bot2 ); + if (imageInfo->format->image_channel_order == CL_DEPTH) + { + log_error( "%d\t(%g)",clampedY + yOff, top[0] ); + log_error( " (%g)", real[0] ); + log_error( " (%g)",bot[0] ); + log_error( " (%g)\n",bot2[0] ); + } + else + { + log_error( "%d\t(%g,%g,%g,%g)",clampedY + yOff, top[0], top[1], top[2], top[3] ); + log_error( " (%g,%g,%g,%g)", real[0], real[1], real[2], real[3] ); + log_error( " (%g,%g,%g,%g)",bot[0], bot[1], bot[2], bot[3] ); + log_error( " (%g,%g,%g,%g)\n",bot2[0], bot2[1], bot2[2], bot2[3] ); + } + } + } + } + + if( imageSampler->filter_mode != CL_FILTER_LINEAR ) + { + if( found ) + log_error( "\tValue really found in image at %d,%d (%s)\n", actualX, actualY, ( found > 1 ) ? "NOT unique!!" : "unique" ); + else + log_error( "\tValue not actually found in image\n" ); + } + log_error( "\n" ); + + numClamped = -1; // We force the clamped counter to never work + if( ( --numTries ) == 0 ) + { + return 1; + } + } + return 0; +} + +#define CLAMP( _val, _min, _max ) ((_val) < (_min) ? (_min) : (_val) > (_max) ? (_max) : (_val)) + +static void InitFloatCoords( image_descriptor *imageInfo, image_sampler_data *imageSampler, float *xOffsets, float *yOffsets, float xfract, float yfract, int normalized_coords, MTdata d ) +{ + size_t i = 0; + if( gDisableOffsets ) + { + for( size_t y = 0; y < imageInfo->height; y++ ) + { + for( size_t x = 0; x < imageInfo->width; x++, i++ ) + { + xOffsets[ i ] = (float) (xfract + (double) x); + yOffsets[ i ] = (float) (yfract + (double) y); + } + } + } + else + { + for( size_t y = 0; y < imageInfo->height; y++ ) + { + for( size_t x = 0; x < imageInfo->width; x++, i++ ) + { + xOffsets[ i ] = (float) (xfract + (double) ((int) x + random_in_range( -10, 10, d ))); + yOffsets[ i ] = (float) (yfract + (double) ((int) y + random_in_range( -10, 10, d ))); + } + } + } + + if( imageSampler->addressing_mode == CL_ADDRESS_NONE ) + { + i = 0; + for( size_t y = 0; y < imageInfo->height; y++ ) + { + for( size_t x = 0; x < imageInfo->width; x++, i++ ) + { + xOffsets[ i ] = (float) CLAMP( (double) xOffsets[ i ], 0.0, (double) imageInfo->width - 1.0); + yOffsets[ i ] = (float) CLAMP( (double) yOffsets[ i ], 0.0, (double)imageInfo->height - 1.0); + } + } + } + + if( normalized_coords ) + { + i = 0; + for( size_t y = 0; y < imageInfo->height; y++ ) + { + for( size_t x = 0; x < imageInfo->width; x++, i++ ) + { + xOffsets[ i ] = (float) ((double) xOffsets[ i ] / (double) imageInfo->width); + yOffsets[ i ] = (float) ((double) yOffsets[ i ] / (double) imageInfo->height); + } + } + } +} + +static void InitFloatCoords( image_descriptor *imageInfo, image_sampler_data *imageSampler, float *xOffsets, float *yOffsets, float xfract, float yfract, int normalized_coords, MTdata d, size_t lod) +{ + size_t i = 0; + size_t width_lod = imageInfo->width, height_lod = imageInfo->height; + + if( gTestMipmaps ) + { + width_lod = (imageInfo->width >> lod)?(imageInfo->width >> lod):1; + height_lod = (imageInfo->height >> lod)?(imageInfo->height >> lod):1; + } + if( gDisableOffsets ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) (xfract + (float) x); + yOffsets[ i ] = (float) (yfract + (float) y); + } + } + } + else + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) (xfract + (double) ((int) x + random_in_range( -10, 10, d ))); + yOffsets[ i ] = (float) (yfract + (double) ((int) y + random_in_range( -10, 10, d ))); + } + } + } + + if( imageSampler->addressing_mode == CL_ADDRESS_NONE ) + { + i = 0; + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) CLAMP( (double) xOffsets[ i ], 0.0, (double) width_lod - 1.0); + yOffsets[ i ] = (float) CLAMP( (double) yOffsets[ i ], 0.0, (double)height_lod - 1.0); + } + } + } + + if( normalized_coords ) + { + i = 0; + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) ((float) xOffsets[ i ] / (float) width_lod); + yOffsets[ i ] = (float) ((float) yOffsets[ i ] / (float) height_lod); + } + } + } +} +#ifndef MAX + #define MAX( _a, _b ) ((_a) > (_b) ? (_a) : (_b)) +#endif + +int validate_image_2D_depth_results(void *imageValues, void *resultValues, double formatAbsoluteError, float *xOffsetValues, float *yOffsetValues, + ExplicitType outputType, int &numTries, int &numClamped, image_sampler_data *imageSampler, image_descriptor *imageInfo, size_t lod, char *imagePtr) +{ + // Validate results element by element + size_t width_lod = (imageInfo->width >> lod ) ?(imageInfo->width >> lod ) : 1; + size_t height_lod = (imageInfo->height >> lod ) ?(imageInfo->height >> lod ) : 1; + /* + * FLOAT output type + */ + if( outputType == kFloat ) + { + // Validate float results + float *resultPtr = (float *)(char *)resultValues; + float expected[4], error=0.0f; + float maxErr = get_max_relative_error( imageInfo->format, imageSampler, 0 /*not 3D*/, CL_FILTER_LINEAR == imageSampler->filter_mode ); + for( size_t y = 0, j = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + float offset = NORM_OFFSET; + if (!imageSampler->normalized_coords || imageSampler->filter_mode != CL_FILTER_NEAREST || NORM_OFFSET == 0 +#if defined( __APPLE__ ) + // Apple requires its CPU implementation to do correctly rounded address arithmetic in all modes + || gDeviceType != CL_DEVICE_TYPE_GPU +#endif + ) + offset = 0.0f; // Loop only once + + for (float norm_offset_x = -offset; norm_offset_x <= offset && !found_pixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !found_pixel; norm_offset_y += NORM_OFFSET) { + + // Try sampling the pixel, without flushing denormals. + int containsDenormals = 0; + FloatPixel maxPixel; + maxPixel = sample_image_pixel_float_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.0f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, &containsDenormals ); + + float err1 = fabsf( resultPtr[0] - expected[0] ); + // Clamp to the minimum absolute error for the format + if (err1 > 0 && err1 < formatAbsoluteError) { err1 = 0.0f; } + float maxErr1 = MAX( maxErr * maxPixel.p[0], FLT_MIN ); + + // Check if the result matches. + if( ! (err1 <= maxErr1) ) + { + //try flushing the denormals, if there is a failure. + if( containsDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr1 += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, NULL ); + + err1 = fabsf( resultPtr[0] - expected[0] ); + } + } + + // If the final result DOES match, then we've found a valid result and we're done with this pixel. + found_pixel = (err1 <= maxErr1); + }//norm_offset_x + }//norm_offset_y + + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -offset; norm_offset_x <= offset && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + checkOnlyOnePixel = 1; + } + + int containsDenormals = 0; + FloatPixel maxPixel; + maxPixel = sample_image_pixel_float_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, &containsDenormals ); + + float err1 = fabsf( resultPtr[0] - expected[0] ); + float maxErr1 = MAX( maxErr * maxPixel.p[0], FLT_MIN ); + + + if( ! (err1 <= maxErr1) ) + { + //try flushing the denormals, if there is a failure. + if( containsDenormals ) + { + maxErr1 += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, NULL ); + + err1 = fabsf( resultPtr[0] - expected[0] ); + } + } + if( ! (err1 <= maxErr1) ) + { + log_error("FAILED norm_offsets: %g , %g:\n", norm_offset_x, norm_offset_y); + + float tempOut[4]; + shouldReturn |= determine_validation_error( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[ j ], yOffsetValues[ j ], norm_offset_x, norm_offset_y, j, numTries, numClamped, true, lod ); + + log_error( "Step by step:\n" ); + FloatPixel temp; + temp = sample_image_pixel_float_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, tempOut, 1 /* verbose */, &containsDenormals /*dont flush while error reporting*/ ); + log_error( "\tulps: %2.2f (max allowed: %2.2f)\n\n", + Ulp_Error( resultPtr[0], expected[0] ), + Ulp_Error( MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) + maxErr, MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) ) ); + + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + + }//norm_offset_x + }//norm_offset_y + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 1; + } + } + } + else + { + log_error("Test error: Not supported format.\n"); + return 1; + } + return 0; +} + +int validate_image_2D_results(void *imageValues, void *resultValues, double formatAbsoluteError, float *xOffsetValues, float *yOffsetValues, + ExplicitType outputType, int &numTries, int &numClamped, image_sampler_data *imageSampler, image_descriptor *imageInfo, size_t lod, char *imagePtr) +{ + // Validate results element by element + size_t width_lod = (imageInfo->width >> lod ) ?(imageInfo->width >> lod ) : 1; + size_t height_lod = (imageInfo->height >> lod ) ?(imageInfo->height >> lod ) : 1; + /* + * FLOAT output type + */ + if( outputType == kFloat ) + { + // Validate float results + float *resultPtr = (float *)(char *)resultValues; + float expected[4], error=0.0f; + float maxErr = get_max_relative_error( imageInfo->format, imageSampler, 0 /*not 3D*/, CL_FILTER_LINEAR == imageSampler->filter_mode ); + for( size_t y = 0, j = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + float offset = NORM_OFFSET; + if (!imageSampler->normalized_coords || imageSampler->filter_mode != CL_FILTER_NEAREST || NORM_OFFSET == 0 +#if defined( __APPLE__ ) + // Apple requires its CPU implementation to do correctly rounded address arithmetic in all modes + || gDeviceType != CL_DEVICE_TYPE_GPU +#endif + ) + offset = 0.0f; // Loop only once + + for (float norm_offset_x = -offset; norm_offset_x <= offset && !found_pixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !found_pixel; norm_offset_y += NORM_OFFSET) { + + + // Try sampling the pixel, without flushing denormals. + int containsDenormals = 0; + FloatPixel maxPixel; + if ( gTestMipmaps ) + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.0f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, &containsDenormals, lod ); + else + maxPixel = sample_image_pixel_float_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.0f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, &containsDenormals ); + + float err1 = fabsf( resultPtr[0] - expected[0] ); + float err2 = fabsf( resultPtr[1] - expected[1] ); + float err3 = fabsf( resultPtr[2] - expected[2] ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + // Clamp to the minimum absolute error for the format + if (err1 > 0 && err1 < formatAbsoluteError) { err1 = 0.0f; } + if (err2 > 0 && err2 < formatAbsoluteError) { err2 = 0.0f; } + if (err3 > 0 && err3 < formatAbsoluteError) { err3 = 0.0f; } + if (err4 > 0 && err4 < formatAbsoluteError) { err4 = 0.0f; } + float maxErr1 = MAX( maxErr * maxPixel.p[0], FLT_MIN ); + float maxErr2 = MAX( maxErr * maxPixel.p[1], FLT_MIN ); + float maxErr3 = MAX( maxErr * maxPixel.p[2], FLT_MIN ); + float maxErr4 = MAX( maxErr * maxPixel.p[3], FLT_MIN ); + + // Check if the result matches. + if( ! (err1 <= maxErr1) || ! (err2 <= maxErr2) || + ! (err3 <= maxErr3) || ! (err4 <= maxErr4) ) + { + //try flushing the denormals, if there is a failure. + if( containsDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr1 += 4 * FLT_MIN; + maxErr2 += 4 * FLT_MIN; + maxErr3 += 4 * FLT_MIN; + maxErr4 += 4 * FLT_MIN; + + if(gTestMipmaps) + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, NULL,lod ); + else + maxPixel = sample_image_pixel_float_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, NULL ); + + err1 = fabsf( resultPtr[0] - expected[0] ); + err2 = fabsf( resultPtr[1] - expected[1] ); + err3 = fabsf( resultPtr[2] - expected[2] ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + + // If the final result DOES match, then we've found a valid result and we're done with this pixel. + found_pixel = (err1 <= maxErr1) && (err2 <= maxErr2) && (err3 <= maxErr3) && (err4 <= maxErr4); + }//norm_offset_x + }//norm_offset_y + + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -offset; norm_offset_x <= offset && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + checkOnlyOnePixel = 1; + } + + int containsDenormals = 0; + FloatPixel maxPixel; + if(gTestMipmaps) + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, &containsDenormals, lod ); + else + maxPixel = sample_image_pixel_float_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, &containsDenormals ); + + float err1 = fabsf( resultPtr[0] - expected[0] ); + float err2 = fabsf( resultPtr[1] - expected[1] ); + float err3 = fabsf( resultPtr[2] - expected[2] ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + float maxErr1 = MAX( maxErr * maxPixel.p[0], FLT_MIN ); + float maxErr2 = MAX( maxErr * maxPixel.p[1], FLT_MIN ); + float maxErr3 = MAX( maxErr * maxPixel.p[2], FLT_MIN ); + float maxErr4 = MAX( maxErr * maxPixel.p[3], FLT_MIN ); + + + if( ! (err1 <= maxErr1) || ! (err2 <= maxErr2) || + ! (err3 <= maxErr3) || ! (err4 <= maxErr4) ) + { + //try flushing the denormals, if there is a failure. + if( containsDenormals ) + { + maxErr1 += 4 * FLT_MIN; + maxErr2 += 4 * FLT_MIN; + maxErr3 += 4 * FLT_MIN; + maxErr4 += 4 * FLT_MIN; + + if(gTestMipmaps) + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, NULL, lod ); + else + maxPixel = sample_image_pixel_float_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, NULL ); + + err1 = fabsf( resultPtr[0] - expected[0] ); + err2 = fabsf( resultPtr[1] - expected[1] ); + err3 = fabsf( resultPtr[2] - expected[2] ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + if( ! (err1 <= maxErr1) || ! (err2 <= maxErr2) || + ! (err3 <= maxErr3) || ! (err4 <= maxErr4) ) + { + log_error("FAILED norm_offsets: %g , %g:\n", norm_offset_x, norm_offset_y); + + float tempOut[4]; + shouldReturn |= determine_validation_error( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[ j ], yOffsetValues[ j ], norm_offset_x, norm_offset_y, j, numTries, numClamped, true, lod ); + + log_error( "Step by step:\n" ); + FloatPixel temp; + if( gTestMipmaps ) + temp = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, tempOut, 1 /* verbose */, &containsDenormals /*dont flush while error reporting*/, lod ); + else + temp = sample_image_pixel_float_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, tempOut, 1 /* verbose */, &containsDenormals /*dont flush while error reporting*/ ); + log_error( "\tulps: %2.2f, %2.2f, %2.2f, %2.2f (max allowed: %2.2f)\n\n", + Ulp_Error( resultPtr[0], expected[0] ), + Ulp_Error( resultPtr[1], expected[1] ), + Ulp_Error( resultPtr[2], expected[2] ), + Ulp_Error( resultPtr[3], expected[3] ), + Ulp_Error( MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) + maxErr, MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) ) ); + + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + + }//norm_offset_x + }//norm_offset_y + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + /* + * UINT output type + */ + else if( outputType == kUInt ) + { + // Validate unsigned integer results + unsigned int *resultPtr = (unsigned int *)(char *)resultValues; + unsigned int expected[4]; + float error; + for( size_t y = 0, j = 0; y < height_lod ; y++ ) + { + for( size_t x = 0; x < width_lod ; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + checkOnlyOnePixel = 1; + } + + if ( gTestMipmaps ) + sample_image_pixel_offset( (char*)imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, lod ); + else + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected); + + + error = errMax( errMax( abs_diff_uint(expected[ 0 ], resultPtr[ 0 ]), abs_diff_uint(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_uint(expected[ 2 ], resultPtr[ 2 ]), abs_diff_uint(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if (error <= MAX_ERR) + found_pixel = 1; + }//norm_offset_x + }//norm_offset_y + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + checkOnlyOnePixel = 1; + } + + if( gTestMipmaps ) + sample_image_pixel_offset( imagePtr , imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, lod ); + else + sample_image_pixel_offset( imagePtr , imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected); + + + error = errMax( errMax( abs_diff_uint(expected[ 0 ], resultPtr[ 0 ]), abs_diff_uint(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_uint(expected[ 2 ], resultPtr[ 2 ]), abs_diff_uint(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if( error > MAX_ERR ) + { + log_error("FAILED norm_offsets: %g , %g:\n", norm_offset_x, norm_offset_y); + + shouldReturn |= determine_validation_error( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[j], yOffsetValues[j], norm_offset_x, norm_offset_y, j, numTries, numClamped, false, lod ); + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + }//norm_offset_x + }//norm_offset_y + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + /* + * INT output type + */ + else + { + // Validate integer results + int *resultPtr = (int *)(char *)resultValues; + int expected[4]; + float error; + for( size_t y = 0, j = 0; y < height_lod ; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + checkOnlyOnePixel = 1; + } + + if ( gTestMipmaps ) + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected , lod); + else + sample_image_pixel_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected ); + + + error = errMax( errMax( abs_diff_int(expected[ 0 ], resultPtr[ 0 ]), abs_diff_int(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_int(expected[ 2 ], resultPtr[ 2 ]), abs_diff_int(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if (error <= MAX_ERR) + found_pixel = 1; + }//norm_offset_x + }//norm_offset_y + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + checkOnlyOnePixel = 1; + } + + if ( gTestMipmaps ) + sample_image_pixel_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, lod ); + else + sample_image_pixel_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected ); + + + error = errMax( errMax( abs_diff_int(expected[ 0 ], resultPtr[ 0 ]), abs_diff_int(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_int(expected[ 2 ], resultPtr[ 2 ]), abs_diff_int(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if( error > MAX_ERR ) + { + log_error("FAILED norm_offsets: %g , %g:\n", norm_offset_x, norm_offset_y); + + shouldReturn |= determine_validation_error( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[j], yOffsetValues[j], norm_offset_x, norm_offset_y, j, numTries, numClamped, false, lod ); + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + }//norm_offset_x + }//norm_offset_y + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + return 0; +} + +int validate_image_2D_sRGB_results(void *imageValues, void *resultValues, double formatAbsoluteError, float *xOffsetValues, float *yOffsetValues, + ExplicitType outputType, int &numTries, int &numClamped, image_sampler_data *imageSampler, image_descriptor *imageInfo, size_t lod, char *imagePtr) +{ + // Validate results element by element + size_t width_lod = (imageInfo->width >> lod ) ?(imageInfo->width >> lod ) : 1; + size_t height_lod = (imageInfo->height >> lod ) ?(imageInfo->height >> lod ) : 1; + /* + * FLOAT output type + */ + if( outputType == kFloat ) + { + // Validate float results + float *resultPtr = (float *)(char *)resultValues; + float expected[4], error=0.0f; + float maxErr = get_max_relative_error( imageInfo->format, imageSampler, 0 /*not 3D*/, CL_FILTER_LINEAR == imageSampler->filter_mode ); + for( size_t y = 0, j = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + float offset = NORM_OFFSET; + if (!imageSampler->normalized_coords || imageSampler->filter_mode != CL_FILTER_NEAREST || NORM_OFFSET == 0 +#if defined( __APPLE__ ) + // Apple requires its CPU implementation to do correctly rounded address arithmetic in all modes + || gDeviceType != CL_DEVICE_TYPE_GPU +#endif + ) + offset = 0.0f; // Loop only once + + for (float norm_offset_x = -offset; norm_offset_x <= offset && !found_pixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !found_pixel; norm_offset_y += NORM_OFFSET) { + + + // Try sampling the pixel, without flushing denormals. + int containsDenormals = 0; + FloatPixel maxPixel; + if ( gTestMipmaps ) + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.0f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, &containsDenormals, lod ); + else + maxPixel = sample_image_pixel_float_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.0f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, &containsDenormals ); + float err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + float err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + float err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + float maxErr = 0.5; + + // Check if the result matches. + if( ! (err1 <= maxErr) || ! (err2 <= maxErr) || + ! (err3 <= maxErr) || ! (err4 <= maxErr) ) + { + //try flushing the denormals, if there is a failure. + if( containsDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr += 4 * FLT_MIN; + + if(gTestMipmaps) + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, NULL,lod ); + else + maxPixel = sample_image_pixel_float_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, NULL ); + + err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + + // If the final result DOES match, then we've found a valid result and we're done with this pixel. + found_pixel = (err1 <= maxErr) && (err2 <= maxErr) && (err3 <= maxErr) && (err4 <= maxErr); + }//norm_offset_x + }//norm_offset_y + + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -offset; norm_offset_x <= offset && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + checkOnlyOnePixel = 1; + } + + int containsDenormals = 0; + FloatPixel maxPixel; + if(gTestMipmaps) + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, &containsDenormals, lod ); + else + maxPixel = sample_image_pixel_float_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, &containsDenormals ); + + float err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + float err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + float err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + float maxErr = 0.6; + + if( ! (err1 <= maxErr) || ! (err2 <= maxErr) || + ! (err3 <= maxErr) || ! (err4 <= maxErr) ) + { + //try flushing the denormals, if there is a failure. + if( containsDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr += 4 * FLT_MIN; + if(gTestMipmaps) + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, NULL, lod ); + else + maxPixel = sample_image_pixel_float_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, NULL ); + + err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + if( ! (err1 <= maxErr) || ! (err2 <= maxErr) || + ! (err3 <= maxErr) || ! (err4 <= maxErr) ) + { + log_error("FAILED norm_offsets: %g , %g:\n", norm_offset_x, norm_offset_y); + + float tempOut[4]; + shouldReturn |= determine_validation_error( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[ j ], yOffsetValues[ j ], norm_offset_x, norm_offset_y, j, numTries, numClamped, true, lod ); + + log_error( "Step by step:\n" ); + FloatPixel temp; + if( gTestMipmaps ) + temp = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, tempOut, 1 /* verbose */, &containsDenormals /*dont flush while error reporting*/, lod ); + else + temp = sample_image_pixel_float_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, tempOut, 1 /* verbose */, &containsDenormals /*dont flush while error reporting*/ ); + log_error( "\tulps: %2.2f, %2.2f, %2.2f, %2.2f (max allowed: %2.2f)\n\n", + Ulp_Error( resultPtr[0], expected[0] ), + Ulp_Error( resultPtr[1], expected[1] ), + Ulp_Error( resultPtr[2], expected[2] ), + Ulp_Error( resultPtr[3], expected[3] ), + Ulp_Error( MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) + maxErr, MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) ) ); + + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + + }//norm_offset_x + }//norm_offset_y + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + else { + log_error("Test error: NOT SUPPORTED.\n"); + } + return 0; +} + +int test_read_image_2D( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, image_sampler_data *imageSampler, + bool useFloatCoords, ExplicitType outputType, MTdata d ) +{ + int error; + static int initHalf = 0; + cl_mem imageBuffer; + cl_mem_flags image_read_write_flags = CL_MEM_READ_ONLY; + size_t threads[2]; + + clMemWrapper xOffsets, yOffsets, results; + clSamplerWrapper actualSampler; + BufferOwningPtr maxImageUseHostPtrBackingStore; + + // The DataBuffer template class really does use delete[], not free -- IRO + BufferOwningPtr xOffsetValues(malloc(sizeof(cl_float) * imageInfo->width * imageInfo->height)); + BufferOwningPtr yOffsetValues(malloc(sizeof(cl_float) * imageInfo->width * imageInfo->height)); + + if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) + if( DetectFloatToHalfRoundingMode(queue) ) + return 1; + + // generate_random_image_data allocates with malloc, so we use a MallocDataBuffer here + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + if( gDebugTrace ) + { + log_info( " - Creating image %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height ); + if( gTestMipmaps ) + { + log_info( " - with %d mip levels", (int) imageInfo->num_mip_levels ); + } + } + + // Construct testing sources + clProtectedImage protImage; + clMemWrapper unprotImage; + cl_mem image; + + if(gtestTypesToRun & kReadTests) + { + image_read_write_flags = CL_MEM_READ_ONLY; + } + else + { + image_read_write_flags = CL_MEM_READ_WRITE; + } + + if( gMemFlagsToUse == CL_MEM_USE_HOST_PTR ) + { + if (gTestImage2DFromBuffer) + { + generate_random_image_data( imageInfo, maxImageUseHostPtrBackingStore, d ); + imageBuffer = clCreateBuffer( context, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + imageInfo->rowPitch * imageInfo->height, maxImageUseHostPtrBackingStore, &error); + test_error( error, "Unable to create buffer" ); + unprotImage = create_image_2d_buffer( context, + image_read_write_flags, + imageInfo->format, + imageInfo->width, imageInfo->height, imageInfo->rowPitch, + imageBuffer, &error ); + + } + else + { + // clProtectedImage uses USE_HOST_PTR, so just rely on that for the testing (via Ian) + // Do not use protected images for max image size test since it rounds the row size to a page size + if (gTestMaxImages) { + generate_random_image_data( imageInfo, maxImageUseHostPtrBackingStore, d ); + unprotImage = create_image_2d( context, + image_read_write_flags | CL_MEM_USE_HOST_PTR, + imageInfo->format, + imageInfo->width, imageInfo->height, ( gEnablePitch ? imageInfo->rowPitch : 0 ), + maxImageUseHostPtrBackingStore, &error ); + } + else + { + error = protImage.Create( context, + image_read_write_flags, + imageInfo->format, imageInfo->width, imageInfo->height ); + } + } + + if( error != CL_SUCCESS ) + { + if (gTestImage2DFromBuffer) { + clReleaseMemObject(imageBuffer); + if (error == CL_INVALID_IMAGE_FORMAT_DESCRIPTOR) { + log_info( "Format not supported for cl_khr_image2d_from_buffer skipping...\n" ); + return 0; + } + } + + log_error( "ERROR: Unable to create 2D image of size %d x %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + + if (gTestMaxImages || gTestImage2DFromBuffer) + image = (cl_mem)unprotImage; + else + image = (cl_mem)protImage; + } + else if( gMemFlagsToUse == CL_MEM_COPY_HOST_PTR ) + { + if (gTestImage2DFromBuffer) + { + imageBuffer = clCreateBuffer( context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + imageInfo->rowPitch * imageInfo->height, imageValues, &error); + test_error( error, "Unable to create buffer" ); + unprotImage = create_image_2d_buffer( context, + image_read_write_flags, + imageInfo->format, + imageInfo->width, imageInfo->height, imageInfo->rowPitch, + imageBuffer, &error ); + + } + else + { + // Don't use clEnqueueWriteImage; just use copy host ptr to get the data in + unprotImage = create_image_2d( context, + image_read_write_flags | CL_MEM_COPY_HOST_PTR, + imageInfo->format, + imageInfo->width, imageInfo->height, ( gEnablePitch ? imageInfo->rowPitch : 0 ), + imageValues, &error ); + } + if( error != CL_SUCCESS ) + { + if (gTestImage2DFromBuffer) { + clReleaseMemObject(imageBuffer); + if (error == CL_INVALID_IMAGE_FORMAT_DESCRIPTOR) { + log_info( "Format not supported for cl_khr_image2d_from_buffer skipping...\n" ); + return 0; + } + } + + log_error( "ERROR: Unable to create 2D image of size %d x %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + image = unprotImage; + } + else // Either CL_MEM_ALLOC_HOST_PTR or none + { + if( gTestMipmaps ) + { + cl_image_desc image_desc = {0}; + image_desc.image_type = CL_MEM_OBJECT_IMAGE2D; + image_desc.image_width = imageInfo->width; + image_desc.image_height = imageInfo->height; + image_desc.num_mip_levels = imageInfo->num_mip_levels; + unprotImage = clCreateImage( context, CL_MEM_READ_ONLY, imageInfo->format, &image_desc, NULL, &error); + } + else if (gTestImage2DFromBuffer) + { + imageBuffer = clCreateBuffer( context, CL_MEM_READ_WRITE | gMemFlagsToUse, + imageInfo->rowPitch * imageInfo->height, imageValues, &error); + test_error( error, "Unable to create buffer" ); + unprotImage = create_image_2d_buffer( context, + image_read_write_flags, + imageInfo->format, + imageInfo->width, imageInfo->height, imageInfo->rowPitch, + imageBuffer, &error ); + + } + else + { + // Note: if ALLOC_HOST_PTR is used, the driver allocates memory that can be accessed by the host, but otherwise + // it works just as if no flag is specified, so we just do the same thing either way + unprotImage = create_image_2d( context, + image_read_write_flags | gMemFlagsToUse, + imageInfo->format, + imageInfo->width, imageInfo->height, ( gEnablePitch ? imageInfo->rowPitch : 0 ), + imageValues, &error ); + } + if( error != CL_SUCCESS ) + { + if (gTestImage2DFromBuffer) { + clReleaseMemObject(imageBuffer); + if (error == CL_INVALID_IMAGE_FORMAT_DESCRIPTOR) { + log_info( "Format not supported for cl_khr_image2d_from_buffer skipping...\n" ); + return 0; + } + } + + log_error( "ERROR: Unable to create 2D image of size %d x %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + image = unprotImage; + } + + if( gMemFlagsToUse != CL_MEM_COPY_HOST_PTR ) + { + if( gDebugTrace ) + log_info( " - Writing image...\n" ); + + size_t origin[ 3 ] = { 0, 0, 0 }; + size_t region[ 3 ] = { imageInfo->width, imageInfo->height, 1 }; + + if(!gTestMipmaps) + { + error = clEnqueueWriteImage(queue, image, CL_TRUE, + origin, region, ( gEnablePitch ? imageInfo->rowPitch : 0 ), 0, + imageValues, 0, NULL, NULL); + if (error != CL_SUCCESS) + { + log_error( "ERROR: Unable to write to 2D image of size %d x %d\n", (int)imageInfo->width, (int)imageInfo->height ); + return error; + } + } + else + { + size_t tmpNextLevelOffset = 0; + for(size_t level = 0; level < imageInfo->num_mip_levels; level++) + { + origin[2] = level; + error = clEnqueueWriteImage(queue, image, CL_TRUE, + origin, region, (( gEnablePitch || gTestImage2DFromBuffer) ? imageInfo->rowPitch : 0 ), 0, + (char*)imageValues + tmpNextLevelOffset, 0, NULL, NULL); + tmpNextLevelOffset += region[0]*region[1]*get_pixel_size(imageInfo->format); + region[0] = (region[0] >> 1) ? (region[0] >> 1) : 1; + region[1] = (region[1] >> 1) ? (region[1] >> 1) : 1; + } + } + } + + if( gDebugTrace ) + log_info( " - Creating kernel arguments...\n" ); + + xOffsets = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), sizeof( cl_float ) * imageInfo->width * imageInfo->height, xOffsetValues, &error ); + test_error( error, "Unable to create x offset buffer" ); + yOffsets = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), sizeof( cl_float ) * imageInfo->width * imageInfo->height, yOffsetValues, &error ); + test_error( error, "Unable to create y offset buffer" ); + results = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), get_explicit_type_size( outputType ) * 4 * imageInfo->width * imageInfo->height, NULL, &error ); + test_error( error, "Unable to create result buffer" ); + + // Create sampler to use + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, imageSampler->normalized_coords, + CL_SAMPLER_ADDRESSING_MODE, imageSampler->addressing_mode, + CL_SAMPLER_FILTER_MODE, imageSampler->filter_mode, + 0, 0, 0 }; + if (gTestMipmaps) { + properties[6] = CL_SAMPLER_MIP_FILTER_MODE; + properties[7] = imageSampler->filter_mode; + } + actualSampler = clCreateSamplerWithProperties(context, properties, &error ); + test_error( error, "Unable to create image sampler" ); + + // Set arguments + int idx = 0; + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &image ); + test_error( error, "Unable to set kernel arguments" ); + if( !gUseKernelSamplers ) + { + error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler ); + test_error( error, "Unable to set kernel arguments" ); + } + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &xOffsets ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &yOffsets ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results ); + test_error( error, "Unable to set kernel arguments" ); + + // A cast of troublesome offsets. The first one has to be zero. + const float float_offsets[] = { 0.0f, MAKE_HEX_FLOAT(0x1.0p-30f, 0x1L, -30), 0.25f, 0.3f, 0.5f - FLT_EPSILON/4.0f, 0.5f, 0.9f, 1.0f - FLT_EPSILON/2 }; + int float_offset_count = sizeof( float_offsets) / sizeof( float_offsets[0] ); + int numTries = MAX_TRIES, numClamped = MAX_CLAMPED; + int loopCount = 2 * float_offset_count; + if( ! useFloatCoords ) + loopCount = 1; + if (gTestMaxImages) { + loopCount = 1; + log_info("Testing each size only once with pixel offsets of %g for max sized images.\n", float_offsets[0]); + } + + if(gtestTypesToRun & kReadWriteTests) + { + loopCount = 1; + } + + // Get the maximum absolute error for this format + double formatAbsoluteError = get_max_absolute_error(imageInfo->format, imageSampler); + if (gDebugTrace) log_info("\tformatAbsoluteError is %e\n", formatAbsoluteError); + + if (0 == initHalf && imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) { + initHalf = CL_SUCCESS == DetectFloatToHalfRoundingMode( queue ); + if (initHalf) { + log_info("Half rounding mode successfully detected.\n"); + } + } + + size_t nextLevelOffset = 0; + size_t width_lod = imageInfo->width, height_lod = imageInfo->height; + for( size_t lod = 0; (gTestMipmaps && (lod < imageInfo->num_mip_levels))|| (!gTestMipmaps && lod < 1); lod ++) + { + size_t resultValuesSize = width_lod * height_lod * get_explicit_type_size( outputType ) * 4; + BufferOwningPtr resultValues(malloc(resultValuesSize)); + float lod_float = (float)lod; + char *imagePtr = (char *)imageValues + nextLevelOffset; + if( gTestMipmaps ) + { + if(gDebugTrace) + log_info("\t- Working at mip level %d\n", lod); + error = clSetKernelArg( kernel, idx, sizeof(float), &lod_float); + } + + // Validate results element by element + for( int q = 0; q < loopCount; q++ ) + { + float offset = float_offsets[ q % float_offset_count ]; + + // Init the coordinates + InitFloatCoords( imageInfo, imageSampler, xOffsetValues, yOffsetValues, + q>=float_offset_count ? -offset: offset, + q>=float_offset_count ? offset: -offset, imageSampler->normalized_coords, d, lod ); + + error = clEnqueueWriteBuffer( queue, xOffsets, CL_TRUE, 0, sizeof(cl_float) * imageInfo->height * imageInfo->width, xOffsetValues, 0, NULL, NULL ); + test_error( error, "Unable to write x offsets" ); + error = clEnqueueWriteBuffer( queue, yOffsets, CL_TRUE, 0, sizeof(cl_float) * imageInfo->height * imageInfo->width, yOffsetValues, 0, NULL, NULL ); + test_error( error, "Unable to write y offsets" ); + + // Get results + memset( resultValues, 0xff, resultValuesSize ); + clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + + // Run the kernel + threads[0] = (size_t)width_lod; + threads[1] = (size_t)height_lod; + error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + if( gDebugTrace ) + log_info( " reading results, %ld kbytes\n", (unsigned long)( width_lod * height_lod * get_explicit_type_size( outputType ) * 4 / 1024 ) ); + + error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, width_lod * height_lod * get_explicit_type_size( outputType ) * 4, resultValues, 0, NULL, NULL ); //XXX check + test_error( error, "Unable to read results from kernel" ); + if( gDebugTrace ) + log_info( " results read\n" ); + + int retCode; + switch (imageInfo->format->image_channel_order) { + case CL_DEPTH: + retCode = validate_image_2D_depth_results((char*)imageValues + nextLevelOffset, resultValues, formatAbsoluteError, xOffsetValues, yOffsetValues, outputType, numTries, numClamped, imageSampler, imageInfo, lod, imagePtr); + break; + case CL_sRGB: + case CL_sRGBx: + case CL_sRGBA: + case CL_sBGRA: + retCode = validate_image_2D_sRGB_results((char*)imageValues + nextLevelOffset, resultValues, formatAbsoluteError, xOffsetValues, yOffsetValues, outputType, numTries, numClamped, imageSampler, imageInfo, lod, imagePtr); + break; + default: + retCode = validate_image_2D_results((char*)imageValues + nextLevelOffset, resultValues, formatAbsoluteError, xOffsetValues, yOffsetValues, outputType, numTries, numClamped, imageSampler, imageInfo, lod, imagePtr); + } + if (retCode) + return retCode; + } + end: + if ( gTestMipmaps ) + { + nextLevelOffset += width_lod * height_lod * get_pixel_size( imageInfo->format ); + width_lod = (width_lod >> 1) ? (width_lod >> 1) : 1; + height_lod = (height_lod >> 1) ? (height_lod >> 1) : 1; + } + } + + if (gTestImage2DFromBuffer) clReleaseMemObject(imageBuffer); + + return numTries != MAX_TRIES || numClamped != MAX_CLAMPED; +} + +int test_read_image_set_2D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, + bool floatCoords, ExplicitType outputType ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + clProgramWrapper program; + clKernelWrapper kernel; + const char *KernelSourcePattern = NULL; + + if (gTestImage2DFromBuffer) + { + if (format->image_channel_order == CL_RGB || format->image_channel_order == CL_RGBx) + { + switch (format->image_channel_data_type) + { + case CL_UNORM_INT8: + case CL_UNORM_INT16: + case CL_SNORM_INT8: + case CL_SNORM_INT16: + case CL_HALF_FLOAT: + case CL_FLOAT: + case CL_SIGNED_INT8: + case CL_SIGNED_INT16: + case CL_SIGNED_INT32: + case CL_UNSIGNED_INT8: + case CL_UNSIGNED_INT16: + case CL_UNSIGNED_INT32: + log_info( "Skipping image format: %s %s\n", GetChannelOrderName( format->image_channel_order ), + GetChannelTypeName( format->image_channel_data_type )); + return 0; + default: + break; + } + } + } + + + RandomSeed seed( gRandomSeed ); + int error; + + // Get our operating params + size_t maxWidth, maxHeight; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0x0 }; + size_t pixelSize; + + imageInfo.format = format; + imageInfo.depth = imageInfo.arraySize = imageInfo.slicePitch = 0; + imageInfo.type = CL_MEM_OBJECT_IMAGE2D; + pixelSize = get_pixel_size( imageInfo.format ); + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // Determine types + if( outputType == kInt ) + readFormat = "i"; + else if( outputType == kUInt ) + readFormat = "ui"; + else // kFloat + readFormat = "f"; + + // Construct the source + const char *samplerArg = samplerKernelArg; + char samplerVar[ 1024 ] = ""; + if( gUseKernelSamplers ) + { + get_sampler_kernel_code( imageSampler, samplerVar ); + samplerArg = ""; + } + + if(gtestTypesToRun & kReadTests) + { + KernelSourcePattern = read2DKernelSourcePattern; + } + else + { + KernelSourcePattern = read_write2DKernelSourcePattern; + } + + + sprintf( programSrc, KernelSourcePattern, + (format->image_channel_order == CL_DEPTH) ? "image2d_depth_t" : "image2d_t", + samplerArg, get_explicit_type_name( outputType ), + (format->image_channel_order == CL_DEPTH) ? "" : "4", + gTestMipmaps?", float lod":" ", + samplerVar, + gTestMipmaps? lodOffsetSource : offsetSource, + floatCoords ? floatKernelSource : intCoordKernelSource, + readFormat, + gTestMipmaps?", lod":" "); + + ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create testing kernel" ); + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + if( gTestMipmaps ) + imageInfo.num_mip_levels = (size_t) random_in_range(2, compute_max_mip_levels(imageInfo.width, imageInfo.height, 0)-1, seed); + + if( gDebugTrace ) + log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.height ); + + int retCode = test_read_image_2D( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D, imageInfo.format, CL_TRUE); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + log_info("Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ]); + + if( gTestMipmaps ) + imageInfo.num_mip_levels = (size_t) random_in_range(2, compute_max_mip_levels(imageInfo.width, imageInfo.height, 0)-1, seed); + + if( gDebugTrace ) + log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] ); + int retCode = test_read_image_2D( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + } + else if( gTestRounding ) + { + uint64_t typeRange = 1LL << ( get_format_type_size( imageInfo.format ) * 8 ); + typeRange /= pixelSize / get_format_type_size( imageInfo.format ); + imageInfo.height = (size_t)( ( typeRange + 255LL ) / 256LL ); + imageInfo.width = (size_t)( typeRange / (cl_ulong)imageInfo.height ); + while( imageInfo.height >= maxHeight / 2 ) + { + imageInfo.width <<= 1; + imageInfo.height >>= 1; + } + + while( imageInfo.width >= maxWidth / 2 ) + imageInfo.width >>= 1; + imageInfo.rowPitch = imageInfo.width * pixelSize; + + gRoundingStartValue = 0; + do + { + if( gDebugTrace ) + log_info( " at size %d,%d, starting round ramp at %llu for range %llu\n", (int)imageInfo.width, (int)imageInfo.height, gRoundingStartValue, typeRange ); + int retCode = test_read_image_2D( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + + gRoundingStartValue += imageInfo.width * imageInfo.height * pixelSize / get_format_type_size( imageInfo.format ); + + } while( gRoundingStartValue < typeRange ); + } + else + { + cl_uint imagePitchAlign = 0; + if (gTestImage2DFromBuffer) + { +#if defined(CL_DEVICE_IMAGE_PITCH_ALIGNMENT) + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE_PITCH_ALIGNMENT, sizeof( cl_uint ), &imagePitchAlign, NULL ); +#endif + if (!imagePitchAlign || error) { + test_error( error, "Unable to get CL_DEVICE_IMAGE_PITCH_ALIGNMENT from device" ); + imagePitchAlign = 1; + } + } + + int maxWidthRange = (int) reduceImageSizeRange(maxWidth); + int maxHeightRange = (int) reduceImageSizeRange(maxHeight); + + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, maxWidthRange, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, maxHeightRange, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + if( gTestMipmaps ) + { + imageInfo.num_mip_levels = (size_t) random_in_range(2, compute_max_mip_levels(imageInfo.width, imageInfo.height, 0)-1, seed); + size = 4 * compute_mipmapped_image_size(imageInfo); + } + else + { + if( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth * pixelSize; + } + + // if we are creating a 2D image from a buffer, make sure that the rowpitch is aligned to CL_DEVICE_IMAGE_PITCH_ALIGNMENT_APPLE + if (gTestImage2DFromBuffer) + { + size_t pitch = imagePitchAlign * pixelSize; + imageInfo.rowPitch = ((imageInfo.rowPitch + pitch - 1) / pitch ) * pitch; + } + + size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.height * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight ); + int retCode = test_read_image_2D( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + } + + return 0; +} diff --git a/test_conformance/images/kernel_read_write/test_loops.cpp b/test_conformance/images/kernel_read_write/test_loops.cpp new file mode 100644 index 00000000..dbaa9c33 --- /dev/null +++ b/test_conformance/images/kernel_read_write/test_loops.cpp @@ -0,0 +1,466 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +extern cl_context context; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern int gTypesToTest; +extern int gNormalizedModeToUse; +extern cl_channel_type gChannelTypeToUse; +extern cl_channel_order gChannelOrderToUse; + +extern bool gDebugTrace; +extern bool gTestMipmaps; + +extern int gtestTypesToRun; + +extern int test_read_image_set_1D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, + bool floatCoords, ExplicitType outputType ); +extern int test_read_image_set_2D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, + bool floatCoords, ExplicitType outputType ); +extern int test_read_image_set_3D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, + bool floatCoords, ExplicitType outputType ); +extern int test_read_image_set_1D_array( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, + bool floatCoords, ExplicitType outputType ); +extern int test_read_image_set_2D_array( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, + bool floatCoords, ExplicitType outputType ); + +static const char *str_1d_image = "1D"; +static const char *str_2d_image = "2D"; +static const char *str_3d_image = "3D"; +static const char *str_1d_image_array = "1D array"; +static const char *str_2d_image_array = "2D array"; + +static const char *convert_image_type_to_string(cl_mem_object_type imageType) +{ + const char *p; + switch (imageType) + { + case CL_MEM_OBJECT_IMAGE1D: + p = str_1d_image; + break; + case CL_MEM_OBJECT_IMAGE2D: + p = str_2d_image; + break; + case CL_MEM_OBJECT_IMAGE3D: + p = str_3d_image; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + p = str_1d_image_array; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + p = str_2d_image_array; + break; + } + return p; +} + +int filter_formats( cl_image_format *formatList, bool *filterFlags, unsigned int formatCount, cl_channel_type *channelDataTypesToFilter ) +{ + int numSupported = 0; + for( unsigned int j = 0; j < formatCount; j++ ) + { + // If this format has been previously filtered, remove the filter + if( filterFlags[ j ] ) + filterFlags[ j ] = false; + + // skip mipmap tests for CL_DEPTH formats (re# Khronos Bug 13762) + if(gTestMipmaps && (formatList[ j ].image_channel_order == CL_DEPTH)) + { + log_info("Skip mipmap tests for CL_DEPTH format\n"); + filterFlags[ j ] = true; + continue; + } + + // Have we already discarded the channel type via the command line? + if( gChannelTypeToUse != (cl_channel_type)-1 && gChannelTypeToUse != formatList[ j ].image_channel_data_type ) + { + filterFlags[ j ] = true; + continue; + } + + // Have we already discarded the channel order via the command line? + if( gChannelOrderToUse != (cl_channel_order)-1 && gChannelOrderToUse != formatList[ j ].image_channel_order ) + { + filterFlags[ j ] = true; + continue; + } + + // Is given format standard channel order and type given by spec. We don't want to test it if this is vendor extension + if( !IsChannelOrderSupported( formatList[ j ].image_channel_order ) || !IsChannelTypeSupported( formatList[ j ].image_channel_data_type ) ) + { + filterFlags[ j ] = true; + continue; + } + + if ( !channelDataTypesToFilter ) + { + numSupported++; + continue; + } + + // Is the format supported? + int i; + for( i = 0; channelDataTypesToFilter[ i ] != (cl_channel_type)-1; i++ ) + { + if( formatList[ j ].image_channel_data_type == channelDataTypesToFilter[ i ] ) + { + numSupported++; + break; + } + } + if( channelDataTypesToFilter[ i ] == (cl_channel_type)-1 ) + { + // Format is NOT supported, so mark it as such + filterFlags[ j ] = true; + } + } + return numSupported; +} + +int get_format_list( cl_device_id device, cl_mem_object_type imageType, cl_image_format * &outFormatList, unsigned int &outFormatCount, cl_mem_flags flags ) +{ + int error; + + cl_image_format tempList[ 128 ]; + error = clGetSupportedImageFormats( context, flags, + imageType, 128, tempList, &outFormatCount ); + test_error( error, "Unable to get count of supported image formats" ); + + outFormatList = new cl_image_format[ outFormatCount ]; + error = clGetSupportedImageFormats( context, flags, + imageType, outFormatCount, outFormatList, NULL ); + test_error( error, "Unable to get list of supported image formats" ); + + return 0; +} + +int test_read_image_type( cl_device_id device, cl_image_format *format, bool floatCoords, + image_sampler_data *imageSampler, ExplicitType outputType, cl_mem_object_type imageType ) +{ + int ret = 0; + cl_addressing_mode *addressModes = NULL; + + // The sampler-less read image functions behave exactly as the corresponding read image functions + // described in section 6.13.14.2 that take integer coordinates and a sampler with filter mode set to + // CLK_FILTER_NEAREST, normalized coordinates set to CLK_NORMALIZED_COORDS_FALSE and addressing mode to CLK_ADDRESS_NONE + cl_addressing_mode addressModes_rw[] = { CL_ADDRESS_NONE, (cl_addressing_mode)-1 }; + cl_addressing_mode addressModes_ro[] = { /* CL_ADDRESS_CLAMP_NONE,*/ CL_ADDRESS_CLAMP_TO_EDGE, CL_ADDRESS_CLAMP, CL_ADDRESS_REPEAT, CL_ADDRESS_MIRRORED_REPEAT, (cl_addressing_mode)-1 }; + + if(gtestTypesToRun & kReadWriteTests) + { + addressModes = addressModes_rw; + } + else + { + addressModes = addressModes_ro; + } + +#if defined( __APPLE__ ) + // According to the OpenCL specification, we do not guarantee the precision + // of operations for linear filtering on the GPU. We do not test linear + // filtering for the CL_RGB CL_UNORM_INT_101010 image format; however, we + // test it internally for a set of other image formats. + if ((gDeviceType == CL_DEVICE_TYPE_GPU) && + (imageSampler->filter_mode == CL_FILTER_LINEAR) && + (format->image_channel_order == CL_RGB) && + (format->image_channel_data_type == CL_UNORM_INT_101010)) + { + log_info("--- Skipping CL_RGB CL_UNORM_INT_101010 format with CL_FILTER_LINEAR on GPU.\n"); + return 0; + } +#endif + + for( int adMode = 0; addressModes[ adMode ] != (cl_addressing_mode)-1; adMode++ ) + { + imageSampler->addressing_mode = addressModes[ adMode ]; + + if( (addressModes[ adMode ] == CL_ADDRESS_REPEAT || addressModes[ adMode ] == CL_ADDRESS_MIRRORED_REPEAT) && !( imageSampler->normalized_coords ) ) + continue; // Repeat doesn't make sense for non-normalized coords + + // Use this run if we were told to only run a certain filter mode + if( gAddressModeToUse != (cl_addressing_mode)-1 && imageSampler->addressing_mode != gAddressModeToUse ) + continue; + + /* + Remove redundant check to see if workaround still necessary + // Check added in because this case was leaking through causing a crash on CPU + if( ! imageSampler->normalized_coords && imageSampler->addressing_mode == CL_ADDRESS_REPEAT ) + continue; //repeat mode requires normalized coordinates + */ + print_read_header( format, imageSampler, false ); + + gTestCount++; + + int retCode = 0; + switch (imageType) + { + case CL_MEM_OBJECT_IMAGE1D: + retCode = test_read_image_set_1D( device, format, imageSampler, floatCoords, outputType ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + retCode = test_read_image_set_1D_array( device, format, imageSampler, floatCoords, outputType ); + break; + case CL_MEM_OBJECT_IMAGE2D: + retCode = test_read_image_set_2D( device, format, imageSampler, floatCoords, outputType ); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + retCode = test_read_image_set_2D_array( device, format, imageSampler, floatCoords, outputType ); + break; + case CL_MEM_OBJECT_IMAGE3D: + retCode = test_read_image_set_3D( device, format, imageSampler, floatCoords, outputType ); + break; + } + if( retCode != 0 ) + { + gTestFailure++; + log_error( "FAILED: " ); + print_read_header( format, imageSampler, true ); + log_info( "\n" ); + } + ret |= retCode; + } + + return ret; +} + +int test_read_image_formats( cl_device_id device, cl_image_format *formatList, bool *filterFlags, unsigned int numFormats, + image_sampler_data *imageSampler, ExplicitType outputType, cl_mem_object_type imageType ) +{ + int ret = 0; + bool flipFlop[2] = { false, true }; + int normalizedIdx, floatCoordIdx; + + + // Use this run if we were told to only run a certain filter mode + if( gFilterModeToUse != (cl_filter_mode)-1 && imageSampler->filter_mode != gFilterModeToUse ) + return 0; + + // Test normalized/non-normalized + for( normalizedIdx = 0; normalizedIdx < 2; normalizedIdx++ ) + { + imageSampler->normalized_coords = flipFlop[ normalizedIdx ]; + if( gNormalizedModeToUse != 7 && gNormalizedModeToUse != (int)imageSampler->normalized_coords ) + continue; + + for( floatCoordIdx = 0; floatCoordIdx < 2; floatCoordIdx++ ) + { + // Checks added in because this case was leaking through causing a crash on CPU + if( !flipFlop[ floatCoordIdx ] ) + if( imageSampler->filter_mode != CL_FILTER_NEAREST || // integer coords can only be used with nearest + flipFlop[ normalizedIdx ]) // Normalized integer coords makes no sense (they'd all be zero) + continue; + + if( flipFlop[ floatCoordIdx ] && (gtestTypesToRun & kReadWriteTests)) + // sampler-less read in read_write tests run only integer coord + continue; + + + log_info( "read_image (%s coords, %s results) *****************************\n", + flipFlop[ floatCoordIdx ] ? ( imageSampler->normalized_coords ? "normalized float" : "unnormalized float" ) : "integer", + get_explicit_type_name( outputType ) ); + + for( unsigned int i = 0; i < numFormats; i++ ) + { + if( filterFlags[i] ) + continue; + + cl_image_format &imageFormat = formatList[ i ]; + + ret |= test_read_image_type( device, &imageFormat, flipFlop[ floatCoordIdx ], imageSampler, outputType, imageType ); + } + } + } + return ret; +} + + +int test_image_set( cl_device_id device, test_format_set_fn formatTestFn, cl_mem_object_type imageType ) +{ + int ret = 0; + static int printedFormatList = -1; + + + if ( ( 0 == is_extension_available( device, "cl_khr_3d_image_writes" )) && (imageType == CL_MEM_OBJECT_IMAGE3D) && (formatTestFn == test_write_image_formats) ) + { + gTestFailure++; + log_error( "-----------------------------------------------------\n" ); + log_error( "FAILED: test writing CL_MEM_OBJECT_IMAGE3D images\n" ); + log_error( "This device does not support the mandated extension cl_khr_3d_image_writes.\n"); + log_error( "-----------------------------------------------------\n\n" ); + return -1; + } + + if ( gTestMipmaps ) + { + if ( 0 == is_extension_available( device, "cl_khr_mipmap_image" )) + { + log_info( "-----------------------------------------------------\n" ); + log_info( "This device does not support cl_khr_mipmap_image.\nSkipping mipmapped image test. \n" ); + log_info( "-----------------------------------------------------\n\n" ); + return 0; + } + if ( ( 0 == is_extension_available( device, "cl_khr_mipmap_image_writes" )) && (formatTestFn == test_write_image_formats)) + { + log_info( "-----------------------------------------------------\n" ); + log_info( "This device does not support cl_khr_mipmap_image_writes.\nSkipping mipmapped image write test. \n" ); + log_info( "-----------------------------------------------------\n\n" ); + return 0; + } + } + + int version_check = check_opencl_version(device,1,2); + if (version_check != 0) { + switch (imageType) { + case CL_MEM_OBJECT_IMAGE1D: + test_missing_feature(version_check, "image_1D"); + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + test_missing_feature(version_check, "image_1D_array"); + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + test_missing_feature(version_check, "image_2D_array"); + } + } + + // Grab the list of supported image formats for integer reads + cl_image_format *formatList; + bool *filterFlags; + unsigned int numFormats; + + // This flag is only for querying the list of supported formats + // The flag for creating image will be set explicitly in test functions + cl_mem_flags flags; + const char *flagNames; + if( formatTestFn == test_read_image_formats ) + { + if(gtestTypesToRun & kReadTests) + { + flags = CL_MEM_READ_ONLY; + flagNames = "read"; + } + else + { + flags = CL_MEM_KERNEL_READ_AND_WRITE; + flagNames = "read_write"; + } + } + else + { + if(gtestTypesToRun & kWriteTests) + { + flags = CL_MEM_WRITE_ONLY; + flagNames = "write"; + } + else + { + flags = CL_MEM_KERNEL_READ_AND_WRITE; + flagNames = "read_write"; + } + } + + if( get_format_list( device, imageType, formatList, numFormats, flags ) ) + return -1; + BufferOwningPtr formatListBuf(formatList); + + + filterFlags = new bool[ numFormats ]; + if( filterFlags == NULL ) + { + log_error( "ERROR: Out of memory allocating filter flags list!\n" ); + return -1; + } + BufferOwningPtr filterFlagsBuf(filterFlags); + memset( filterFlags, 0, sizeof( bool ) * numFormats ); + + // First time through, we'll go ahead and print the formats supported, regardless of type + int test = imageType | (formatTestFn == test_read_image_formats ? (1 << 16) : (1 << 17)); + if( printedFormatList != test ) + { + log_info( "---- Supported %s %s formats for this device ---- \n", convert_image_type_to_string(imageType), flagNames ); + for( unsigned int f = 0; f < numFormats; f++ ) + { + if ( IsChannelOrderSupported( formatList[ f ].image_channel_order ) && IsChannelTypeSupported( formatList[ f ].image_channel_data_type ) ) + log_info( " %-7s %-24s %d\n", GetChannelOrderName( formatList[ f ].image_channel_order ), + GetChannelTypeName( formatList[ f ].image_channel_data_type ), + (int)get_format_channel_count( &formatList[ f ] ) ); + } + log_info( "------------------------------------------- \n" ); + printedFormatList = test; + } + + image_sampler_data imageSampler; + + /////// float tests /////// + + if( gTypesToTest & kTestFloat ) + { + cl_channel_type floatFormats[] = { CL_UNORM_SHORT_565, CL_UNORM_SHORT_555, CL_UNORM_INT_101010, +#ifdef OBSOLETE_FORAMT + CL_UNORM_SHORT_565_REV, CL_UNORM_SHORT_555_REV, CL_UNORM_INT_8888, CL_UNORM_INT_8888_REV, CL_UNORM_INT_101010_REV, +#endif +#ifdef CL_SFIXED14_APPLE + CL_SFIXED14_APPLE, +#endif + CL_UNORM_INT8, CL_SNORM_INT8, + CL_UNORM_INT16, CL_SNORM_INT16, CL_FLOAT, CL_HALF_FLOAT, (cl_channel_type)-1 }; + if( filter_formats( formatList, filterFlags, numFormats, floatFormats ) == 0 ) + { + log_info( "No formats supported for float type\n" ); + } + else + { + imageSampler.filter_mode = CL_FILTER_NEAREST; + ret += formatTestFn( device, formatList, filterFlags, numFormats, &imageSampler, kFloat, imageType ); + + imageSampler.filter_mode = CL_FILTER_LINEAR; + ret += formatTestFn( device, formatList, filterFlags, numFormats, &imageSampler, kFloat, imageType ); + } + } + + /////// int tests /////// + if( gTypesToTest & kTestInt ) + { + cl_channel_type intFormats[] = { CL_SIGNED_INT8, CL_SIGNED_INT16, CL_SIGNED_INT32, (cl_channel_type)-1 }; + if( filter_formats( formatList, filterFlags, numFormats, intFormats ) == 0 ) + { + log_info( "No formats supported for integer type\n" ); + } + else + { + // Only filter mode we support on int is nearest + imageSampler.filter_mode = CL_FILTER_NEAREST; + ret += formatTestFn( device, formatList, filterFlags, numFormats, &imageSampler, kInt, imageType ); + } + } + + /////// uint tests /////// + + if( gTypesToTest & kTestUInt ) + { + cl_channel_type uintFormats[] = { CL_UNSIGNED_INT8, CL_UNSIGNED_INT16, CL_UNSIGNED_INT32, (cl_channel_type)-1 }; + if( filter_formats( formatList, filterFlags, numFormats, uintFormats ) == 0 ) + { + log_info( "No formats supported for unsigned int type\n" ); + } + else + { + // Only filter mode we support on uint is nearest + imageSampler.filter_mode = CL_FILTER_NEAREST; + ret += formatTestFn( device, formatList, filterFlags, numFormats, &imageSampler, kUInt, imageType ); + } + } + return ret; +} diff --git a/test_conformance/images/kernel_read_write/test_read_1D.cpp b/test_conformance/images/kernel_read_write/test_read_1D.cpp new file mode 100644 index 00000000..18158294 --- /dev/null +++ b/test_conformance/images/kernel_read_write/test_read_1D.cpp @@ -0,0 +1,1169 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" +#include + +#if defined( __APPLE__ ) + #include + #include + #include +#endif + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gExtraValidateInfo, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_device_type gDeviceType; +extern bool gUseKernelSamplers; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_mem_flags gMemFlagsToUse; +extern int gtestTypesToRun; + +#define MAX_TRIES 1 +#define MAX_CLAMPED 1 + +const char *read1DKernelSourcePattern = +"__kernel void sample_kernel( read_only image1d_t input,%s __global float *xOffsets, __global %s4 *results %s)\n" +"{\n" +"%s" +" int tidX = get_global_id(0);\n" +" int offset = tidX;\n" +"%s" +" results[offset] = read_image%s( input, imageSampler, coord %s);\n" +"}"; + +const char *read_write1DKernelSourcePattern = +"__kernel void sample_kernel( read_write image1d_t input,%s __global float *xOffsets, __global %s4 *results %s)\n" +"{\n" +"%s" +" int tidX = get_global_id(0);\n" +" int offset = tidX;\n" +"%s" +" results[offset] = read_image%s( input, coord %s);\n" +"}"; + +const char *int1DCoordKernelSource = +" int coord = xOffsets[offset];\n"; + +const char *float1DKernelSource = +" float coord = (float)xOffsets[offset];\n"; + +static const char *samplerKernelArg = " sampler_t imageSampler,"; + +#define ABS_ERROR( result, expected ) ( fabsf( (float)expected - (float)result ) ) + +extern void read_image_pixel_float( void *imageData, image_descriptor *imageInfo, + int x, int y, int z, float *outData ); +template int determine_validation_error_1D( void *imagePtr, image_descriptor *imageInfo, image_sampler_data *imageSampler, + T *resultPtr, T * expected, float error, + float x, float xAddressOffset, size_t j, int &numTries, int &numClamped, bool printAsFloat, int lod ) +{ + int actualX, actualY; + int found = debug_find_pixel_in_image( imagePtr, imageInfo, resultPtr, &actualX, &actualY, NULL, lod ); + bool clampingErr = false, clamped = false, otherClampingBug = false; + int clampedX, ignoreMe; + + clamped = get_integer_coords_offset( x, 0.0f, 0.0f, xAddressOffset, 0.0f, 0.0f, imageInfo->width, 0, 0, imageSampler, imageInfo, clampedX, ignoreMe, ignoreMe ); + + if( found ) + { + // Is it a clamping bug? + if( clamped && clampedX == actualX ) + { + if( (--numClamped) == 0 ) + { + log_error( "ERROR: TEST FAILED: Read is erroneously clamping coordinates for image size %ld!\n", imageInfo->width ); + if( printAsFloat ) + { + log_error( "Sample %d: coord {%f(%a)} did not validate!\n\tExpected (%g,%g,%g,%g),\n\tgot (%g,%g,%g,%g),\n\terror of %g\n", + (int)j, x, x, (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ], + (float)resultPtr[ 0 ], (float)resultPtr[ 1 ], (float)resultPtr[ 2 ], (float)resultPtr[ 3 ], error ); + } + else + { + log_error( "Sample %d: coord {%f(%a)} did not validate!\n\tExpected (%x,%x,%x,%x),\n\tgot (%x,%x,%x,%x)\n", + (int)j, x, x, (int)expected[ 0 ], (int)expected[ 1 ], (int)expected[ 2 ], (int)expected[ 3 ], + (int)resultPtr[ 0 ], (int)resultPtr[ 1 ], (int)resultPtr[ 2 ], (int)resultPtr[ 3 ] ); + } + return 1; + } + clampingErr = true; + otherClampingBug = true; + } + } + if( clamped && !otherClampingBug ) + { + // If we are in clamp-to-edge mode and we're getting zeroes, it's possible we're getting border erroneously + if( resultPtr[ 0 ] == 0 && resultPtr[ 1 ] == 0 && resultPtr[ 2 ] == 0 && resultPtr[ 3 ] == 0 ) + { + if( (--numClamped) == 0 ) + { + log_error( "ERROR: TEST FAILED: Clamping is erroneously returning border color for image size %ld!\n", imageInfo->width ); + if( printAsFloat ) + { + log_error( "Sample %d: coord {%f(%a)} did not validate!\n\tExpected (%g,%g,%g,%g),\n\tgot (%g,%g,%g,%g),\n\terror of %g\n", + (int)j, x, x, (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ], + (float)resultPtr[ 0 ], (float)resultPtr[ 1 ], (float)resultPtr[ 2 ], (float)resultPtr[ 3 ], error ); + } + else + { + log_error( "Sample %d: coord {%f(%a)} did not validate!\n\tExpected (%x,%x,%x,%x),\n\tgot (%x,%x,%x,%x)\n", + (int)j, x, x, (int)expected[ 0 ], (int)expected[ 1 ], (int)expected[ 2 ], (int)expected[ 3 ], + (int)resultPtr[ 0 ], (int)resultPtr[ 1 ], (int)resultPtr[ 2 ], (int)resultPtr[ 3 ] ); + } + return 1; + } + clampingErr = true; + } + } + if( !clampingErr ) + { + if( printAsFloat ) + { + log_error( "Sample %d: coord {%f(%a)} did not validate!\n\tExpected (%g,%g,%g,%g),\n\tgot (%g,%g,%g,%g), error of %g\n", + (int)j, x, x, (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ], + (float)resultPtr[ 0 ], (float)resultPtr[ 1 ], (float)resultPtr[ 2 ], (float)resultPtr[ 3 ], error ); + } + else + { + log_error( "Sample %d: coord {%f(%a)} did not validate!\n\tExpected (%x,%x,%x,%x),\n\tgot (%x,%x,%x,%x)\n", + (int)j, x, x, (int)expected[ 0 ], (int)expected[ 1 ], (int)expected[ 2 ], (int)expected[ 3 ], + (int)resultPtr[ 0 ], (int)resultPtr[ 1 ], (int)resultPtr[ 2 ], (int)resultPtr[ 3 ] ); + } + log_error( "img size %ld (pitch %ld)", imageInfo->width, imageInfo->rowPitch ); + if( clamped ) + { + log_error( " which would clamp to %d\n", clampedX ); + } + if( printAsFloat && gExtraValidateInfo) + { + log_error( "Nearby values:\n" ); + log_error( "\t%d\t%d\t%d\t%d\n", clampedX - 2, clampedX - 1, clampedX, clampedX + 1 ); + { + float top[ 4 ], real[ 4 ], bot[ 4 ], bot2[ 4 ]; + read_image_pixel_float( imagePtr, imageInfo, clampedX - 2, 0, 0, top ); + read_image_pixel_float( imagePtr, imageInfo, clampedX - 1, 0, 0, real ); + read_image_pixel_float( imagePtr, imageInfo, clampedX, 0, 0, bot ); + read_image_pixel_float( imagePtr, imageInfo, clampedX + 1, 0, 0, bot2 ); + log_error( "\t(%g,%g,%g,%g)",top[0], top[1], top[2], top[3] ); + log_error( " (%g,%g,%g,%g)", real[0], real[1], real[2], real[3] ); + log_error( " (%g,%g,%g,%g)",bot[0], bot[1], bot[2], bot[3] ); + log_error( " (%g,%g,%g,%g)\n",bot2[0], bot2[1], bot2[2], bot2[3] ); + } + } + + if( imageSampler->filter_mode != CL_FILTER_LINEAR ) + { + if( found ) + log_error( "\tValue really found in image at %d (%s)\n", actualX, ( found > 1 ) ? "NOT unique!!" : "unique" ); + else + log_error( "\tValue not actually found in image\n" ); + } + log_error( "\n" ); + + numClamped = -1; // We force the clamped counter to never work + if( ( --numTries ) == 0 ) + { + return 1; + } + } + return 0; +} + +#define CLAMP( _val, _min, _max ) ((_val) < (_min) ? (_min) : (_val) > (_max) ? (_max) : (_val)) + +static void InitFloatCoords( image_descriptor *imageInfo, image_sampler_data *imageSampler, float *xOffsets, float xfract, int normalized_coords, MTdata d, int lod) +{ + size_t i = 0; + size_t width_lod = imageInfo->width; + + if(gTestMipmaps) + width_lod = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1; + + if( gDisableOffsets ) + { + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) (xfract + (double) x); + } + } + else + { + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) (xfract + (double) ((int) x + random_in_range( -10, 10, d ))); + } + } + + if( imageSampler->addressing_mode == CL_ADDRESS_NONE ) + { + i = 0; + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) CLAMP( (double) xOffsets[ i ], 0.0, (double) width_lod - 1.0); + } + } + + if( normalized_coords ) + { + i = 0; + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) ((double) xOffsets[ i ] / (double) width_lod); + } + } +} + +#ifndef MAX + #define MAX( _a, _b ) ((_a) > (_b) ? (_a) : (_b)) +#endif + + +int test_read_image_1D( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, image_sampler_data *imageSampler, + bool useFloatCoords, ExplicitType outputType, MTdata d ) +{ + int error; + static int initHalf = 0; + + size_t threads[2]; + cl_mem_flags image_read_write_flags = CL_MEM_READ_ONLY; + clMemWrapper xOffsets, results; + clSamplerWrapper actualSampler; + BufferOwningPtr maxImageUseHostPtrBackingStore; + + // The DataBuffer template class really does use delete[], not free -- IRO + BufferOwningPtr xOffsetValues(malloc(sizeof(cl_float) * imageInfo->width)); + + // generate_random_image_data allocates with malloc, so we use a MallocDataBuffer here + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + if( gDebugTrace ) + { + log_info( " - Creating 1D image %d ...\n", (int)imageInfo->width ); + if(gTestMipmaps) + log_info(" - and %d mip levels\n", (int)imageInfo->num_mip_levels); + } + // Construct testing sources + clProtectedImage protImage; + clMemWrapper unprotImage; + cl_mem image; + + if(gtestTypesToRun & kReadTests) + { + image_read_write_flags = CL_MEM_READ_ONLY; + } + else + { + image_read_write_flags = CL_MEM_READ_WRITE; + } + + if( gMemFlagsToUse == CL_MEM_USE_HOST_PTR ) + { + // clProtectedImage uses USE_HOST_PTR, so just rely on that for the testing (via Ian) + // Do not use protected images for max image size test since it rounds the row size to a page size + if (gTestMaxImages) { + generate_random_image_data( imageInfo, maxImageUseHostPtrBackingStore, d ); + unprotImage = create_image_1d( context, + image_read_write_flags | CL_MEM_USE_HOST_PTR, + imageInfo->format, + imageInfo->width, ( gEnablePitch ? imageInfo->rowPitch : 0 ), + maxImageUseHostPtrBackingStore, NULL, &error ); + } else { + error = protImage.Create( context, + image_read_write_flags, + imageInfo->format, imageInfo->width ); + } + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 1D image of size %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + + if (gTestMaxImages) + image = (cl_mem)unprotImage; + else + image = (cl_mem)protImage; + } + else if( gMemFlagsToUse == CL_MEM_COPY_HOST_PTR ) + { + // Don't use clEnqueueWriteImage; just use copy host ptr to get the data in + unprotImage = create_image_1d( context, + image_read_write_flags | CL_MEM_COPY_HOST_PTR, + imageInfo->format, + imageInfo->width, ( gEnablePitch ? imageInfo->rowPitch : 0 ), + imageValues, NULL, &error ); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 1D image of size %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + image = unprotImage; + } + else // Either CL_MEM_ALLOC_HOST_PTR or none + { + // Note: if ALLOC_HOST_PTR is used, the driver allocates memory that can be accessed by the host, but otherwise + // it works just as if no flag is specified, so we just do the same thing either way + if(gTestMipmaps) + { + cl_image_desc image_desc = {0}; + image_desc.image_type = CL_MEM_OBJECT_IMAGE1D; + image_desc.image_width = imageInfo->width; + image_desc.num_mip_levels = imageInfo->num_mip_levels; + + unprotImage = clCreateImage( context, + image_read_write_flags, + imageInfo->format, &image_desc, NULL, &error); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create %d level mipmapped 1D image of size %d (pitch %d, %d ) (%s)",(int)imageInfo->num_mip_levels, (int)imageInfo->width, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + } + else + { + unprotImage = create_image_1d( context, + image_read_write_flags | gMemFlagsToUse, + imageInfo->format, + imageInfo->width, ( gEnablePitch ? imageInfo->rowPitch : 0 ), + imageValues, NULL, &error ); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 1D image of size %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + } + image = unprotImage; + } + + if( gMemFlagsToUse != CL_MEM_COPY_HOST_PTR ) + { + if( gDebugTrace ) + log_info( " - Writing image...\n" ); + + size_t origin[ 3 ] = { 0, 0, 0 }; + size_t region[ 3 ] = { imageInfo->width, 1, 1 }; + + if(gTestMipmaps) + { + int nextLevelOffset = 0; + + for (int i =0; i < imageInfo->num_mip_levels; i++) + { origin[1] = i; + error = clEnqueueWriteImage(queue, image, CL_TRUE, + origin, region, /*gEnablePitch ? imageInfo->rowPitch :*/ 0, /*gEnablePitch ? imageInfo->slicePitch :*/ 0, + ((char*)imageValues + nextLevelOffset), 0, NULL, NULL); + if (error != CL_SUCCESS) + { + log_error( "ERROR: Unable to write to %d level mipmapped 3D image of size %d x %d x %d\n", (int)imageInfo->num_mip_levels,(int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth ); + return error; + } + nextLevelOffset += region[0]*get_pixel_size(imageInfo->format); + //Subsequent mip level dimensions keep halving + region[0] = region[0] >> 1 ? region[0] >> 1 : 1; + } + } + else + { + error = clEnqueueWriteImage(queue, image, CL_TRUE, + origin, region, ( gEnablePitch ? imageInfo->rowPitch : 0 ), 0, + imageValues, 0, NULL, NULL); + if (error != CL_SUCCESS) + { + log_error( "ERROR: Unable to write to 1D image of size %d\n", (int)imageInfo->width ); + return error; + } + } + } + + if( gDebugTrace ) + log_info( " - Creating kernel arguments...\n" ); + + xOffsets = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), sizeof( cl_float ) * imageInfo->width, xOffsetValues, &error ); + test_error( error, "Unable to create x offset buffer" ); + results = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), get_explicit_type_size( outputType ) * 4 * imageInfo->width, NULL, &error ); + test_error( error, "Unable to create result buffer" ); + + // Create sampler to use + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, imageSampler->normalized_coords, + CL_SAMPLER_ADDRESSING_MODE, imageSampler->addressing_mode, + CL_SAMPLER_FILTER_MODE, imageSampler->filter_mode, + 0, 0, 0 }; + if (gTestMipmaps) { + properties[6] = CL_SAMPLER_MIP_FILTER_MODE; + properties[7] = imageSampler->filter_mode; + } + actualSampler = clCreateSamplerWithProperties(context, properties, &error ); + test_error( error, "Unable to create image sampler" ); + + // Set arguments + int idx = 0; + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &image ); + test_error( error, "Unable to set kernel arguments" ); + if( !gUseKernelSamplers ) + { + error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler ); + test_error( error, "Unable to set kernel arguments" ); + } + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &xOffsets ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results ); + test_error( error, "Unable to set kernel arguments" ); + + // A cast of troublesome offsets. The first one has to be zero. + const float float_offsets[] = { 0.0f, MAKE_HEX_FLOAT(0x1.0p-30f, 0x1L, -30), 0.25f, 0.3f, 0.5f - FLT_EPSILON/4.0f, 0.5f, 0.9f, 1.0f - FLT_EPSILON/2 }; + int float_offset_count = sizeof( float_offsets) / sizeof( float_offsets[0] ); + int numTries = MAX_TRIES, numClamped = MAX_CLAMPED; + int loopCount = 2 * float_offset_count; + if( ! useFloatCoords ) + loopCount = 1; + if (gTestMaxImages) { + loopCount = 1; + log_info("Testing each size only once with pixel offsets of %g for max sized images.\n", float_offsets[0]); + } + + // Get the maximum absolute error for this format + double formatAbsoluteError = get_max_absolute_error(imageInfo->format, imageSampler); + if (gDebugTrace) log_info("\tformatAbsoluteError is %e\n", formatAbsoluteError); + + if (0 == initHalf && imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) { + initHalf = CL_SUCCESS == DetectFloatToHalfRoundingMode( queue ); + if (initHalf) { + log_info("Half rounding mode successfully detected.\n"); + } + } + + size_t width_lod = imageInfo->width; + size_t nextLevelOffset = 0; + for(int lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++) + { + float lod_float = (float)lod; + size_t resultValuesSize = width_lod * get_explicit_type_size( outputType ) * 4; + BufferOwningPtr resultValues(malloc(resultValuesSize)); + char *imagePtr = (char*)imageValues + nextLevelOffset; + if (gTestMipmaps) { + //Set the lod kernel arg + if(gDebugTrace) + log_info(" - Working at mip level %d\n", lod); + error = clSetKernelArg( kernel, idx, sizeof( float ), &lod_float); + test_error( error, "Unable to set kernel arguments" ); + } + for( int q = 0; q < loopCount; q++ ) + { + float offset = float_offsets[ q % float_offset_count ]; + + // Init the coordinates + InitFloatCoords( imageInfo, imageSampler, xOffsetValues, + q>=float_offset_count ? -offset: offset, + imageSampler->normalized_coords, d , lod); + + error = clEnqueueWriteBuffer( queue, xOffsets, CL_TRUE, 0, sizeof(cl_float) * width_lod, xOffsetValues, 0, NULL, NULL ); + test_error( error, "Unable to write x offsets" ); + + // Get results + memset( resultValues, 0xff, resultValuesSize ); + clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + + // Run the kernel + threads[0] = (size_t)width_lod; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + if( gDebugTrace ) + log_info( " reading results, %ld kbytes\n", (unsigned long)( width_lod * get_explicit_type_size( outputType ) * 4 / 1024 ) ); + + error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, width_lod * get_explicit_type_size( outputType ) * 4, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + if( gDebugTrace ) + log_info( " results read\n" ); + + // Validate results element by element + char *imagePtr = imageValues + nextLevelOffset; + /* + * FLOAT output type + */ + if(is_sRGBA_order(imageInfo->format->image_channel_order) && ( outputType == kFloat )) + { + // Validate float results + float *resultPtr = (float *)(char *)resultValues; + float expected[4], error=0.0f; + float maxErr = get_max_relative_error( imageInfo->format, imageSampler, 0 /*not 3D*/, CL_FILTER_LINEAR == imageSampler->filter_mode ); + { + for( size_t x = 0, j = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + float offset = NORM_OFFSET; + if (!imageSampler->normalized_coords || imageSampler->filter_mode != CL_FILTER_NEAREST || NORM_OFFSET == 0 +#if defined( __APPLE__ ) + // Apple requires its CPU implementation to do correctly rounded address arithmetic in all modes + || gDeviceType != CL_DEVICE_TYPE_GPU +#endif + ) + offset = 0.0f; // Loop only once + + for (float norm_offset_x = -offset; norm_offset_x <= offset && !found_pixel; norm_offset_x += NORM_OFFSET) { + + // Try sampling the pixel, without flushing denormals. + int containsDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected, 0, &containsDenormals, lod ); + + float err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + float err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + float err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + + float maxErr = 0.5; + + // Check if the result matches. + if( ! (err1 <= maxErr) || ! (err2 <= maxErr) || + ! (err3 <= maxErr) || ! (err4 <= maxErr) ) + { + //try flushing the denormals, if there is a failure. + if( containsDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + + // If the final result DOES match, then we've found a valid result and we're done with this pixel. + found_pixel = (err1 <= maxErr) && (err2 <= maxErr) && (err3 <= maxErr) && (err4 <= maxErr); + }//norm_offset_x + + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -offset; norm_offset_x <= offset && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + checkOnlyOnePixel = 1; + } + + int containsDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected, 0, &containsDenormals, lod ); + + float err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + float err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + float err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + + float maxErr = 0.6; + + if( ! (err1 <= maxErr) || ! (err2 <= maxErr) || + ! (err3 <= maxErr) || ! (err4 <= maxErr) ) + { + //try flushing the denormals, if there is a failure. + if( containsDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + if( ! (err1 <= maxErr) || ! (err2 <= maxErr) || + ! (err3 <= maxErr) || ! (err4 <= maxErr) ) + { + log_error("FAILED norm_offsets: %g:\n", norm_offset_x); + + float tempOut[4]; + shouldReturn |= determine_validation_error_1D( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[ j ], norm_offset_x, j, numTries, numClamped, true, lod ); + + log_error( "Step by step:\n" ); + FloatPixel temp = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, tempOut, 1 /* verbose */, &containsDenormals /*dont flush while error reporting*/, lod ); + log_error( "\tulps: %2.2f, %2.2f, %2.2f, %2.2f (max allowed: %2.2f)\n\n", + Ulp_Error( resultPtr[0], expected[0] ), + Ulp_Error( resultPtr[1], expected[1] ), + Ulp_Error( resultPtr[2], expected[2] ), + Ulp_Error( resultPtr[3], expected[3] ), + Ulp_Error( MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) + maxErr, MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) ) ); + + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + + }//norm_offset_x + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + else if( outputType == kFloat ) + { + // Validate float results + float *resultPtr = (float *)(char *)resultValues; + float expected[4], error=0.0f; + float maxErr = get_max_relative_error( imageInfo->format, imageSampler, 0 /*not 3D*/, CL_FILTER_LINEAR == imageSampler->filter_mode ); + { + for( size_t x = 0, j = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + float offset = NORM_OFFSET; + if (!imageSampler->normalized_coords || imageSampler->filter_mode != CL_FILTER_NEAREST || NORM_OFFSET == 0 +#if defined( __APPLE__ ) + // Apple requires its CPU implementation to do correctly rounded address arithmetic in all modes + || gDeviceType != CL_DEVICE_TYPE_GPU +#endif + ) + offset = 0.0f; // Loop only once + + for (float norm_offset_x = -offset; norm_offset_x <= offset && !found_pixel; norm_offset_x += NORM_OFFSET) { + + // Try sampling the pixel, without flushing denormals. + int containsDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected, 0, &containsDenormals, lod ); + + float err1 = fabsf( resultPtr[0] - expected[0] ); + float err2 = fabsf( resultPtr[1] - expected[1] ); + float err3 = fabsf( resultPtr[2] - expected[2] ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + // Clamp to the minimum absolute error for the format + if (err1 > 0 && err1 < formatAbsoluteError) { err1 = 0.0f; } + if (err2 > 0 && err2 < formatAbsoluteError) { err2 = 0.0f; } + if (err3 > 0 && err3 < formatAbsoluteError) { err3 = 0.0f; } + if (err4 > 0 && err4 < formatAbsoluteError) { err4 = 0.0f; } + float maxErr1 = MAX( maxErr * maxPixel.p[0], FLT_MIN ); + float maxErr2 = MAX( maxErr * maxPixel.p[1], FLT_MIN ); + float maxErr3 = MAX( maxErr * maxPixel.p[2], FLT_MIN ); + float maxErr4 = MAX( maxErr * maxPixel.p[3], FLT_MIN ); + + // Check if the result matches. + if( ! (err1 <= maxErr1) || ! (err2 <= maxErr2) || + ! (err3 <= maxErr3) || ! (err4 <= maxErr4) ) + { + //try flushing the denormals, if there is a failure. + if( containsDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr1 += 4 * FLT_MIN; + maxErr2 += 4 * FLT_MIN; + maxErr3 += 4 * FLT_MIN; + maxErr4 += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( resultPtr[0] - expected[0] ); + err2 = fabsf( resultPtr[1] - expected[1] ); + err3 = fabsf( resultPtr[2] - expected[2] ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + + // If the final result DOES match, then we've found a valid result and we're done with this pixel. + found_pixel = (err1 <= maxErr1) && (err2 <= maxErr2) && (err3 <= maxErr3) && (err4 <= maxErr4); + }//norm_offset_x + + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -offset; norm_offset_x <= offset && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + checkOnlyOnePixel = 1; + } + + int containsDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected, 0, &containsDenormals, lod ); + + float err1 = fabsf( resultPtr[0] - expected[0] ); + float err2 = fabsf( resultPtr[1] - expected[1] ); + float err3 = fabsf( resultPtr[2] - expected[2] ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + float maxErr1 = MAX( maxErr * maxPixel.p[0], FLT_MIN ); + float maxErr2 = MAX( maxErr * maxPixel.p[1], FLT_MIN ); + float maxErr3 = MAX( maxErr * maxPixel.p[2], FLT_MIN ); + float maxErr4 = MAX( maxErr * maxPixel.p[3], FLT_MIN ); + + + if( ! (err1 <= maxErr1) || ! (err2 <= maxErr2) || + ! (err3 <= maxErr3) || ! (err4 <= maxErr4) ) + { + //try flushing the denormals, if there is a failure. + if( containsDenormals ) + { + maxErr1 += 4 * FLT_MIN; + maxErr2 += 4 * FLT_MIN; + maxErr3 += 4 * FLT_MIN; + maxErr4 += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( resultPtr[0] - expected[0] ); + err2 = fabsf( resultPtr[1] - expected[1] ); + err3 = fabsf( resultPtr[2] - expected[2] ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + if( ! (err1 <= maxErr1) || ! (err2 <= maxErr2) || + ! (err3 <= maxErr3) || ! (err4 <= maxErr4) ) + { + log_error("FAILED norm_offsets: %g:\n", norm_offset_x); + + float tempOut[4]; + shouldReturn |= determine_validation_error_1D( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[ j ], norm_offset_x, j, numTries, numClamped, true, lod ); + + log_error( "Step by step:\n" ); + FloatPixel temp = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, tempOut, 1 /* verbose */, &containsDenormals /*dont flush while error reporting*/, lod ); + log_error( "\tulps: %2.2f, %2.2f, %2.2f, %2.2f (max allowed: %2.2f)\n\n", + Ulp_Error( resultPtr[0], expected[0] ), + Ulp_Error( resultPtr[1], expected[1] ), + Ulp_Error( resultPtr[2], expected[2] ), + Ulp_Error( resultPtr[3], expected[3] ), + Ulp_Error( MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) + maxErr, MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) ) ); + + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + + }//norm_offset_x + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + /* + * UINT output type + */ + else if( outputType == kUInt ) + { + // Validate unsigned integer results + unsigned int *resultPtr = (unsigned int *)(char *)resultValues; + unsigned int expected[4]; + float error; + for( size_t x = 0, j = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + checkOnlyOnePixel = 1; + } + + if ( gTestMipmaps ) + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected, lod ); + else + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected ); + + error = errMax( errMax( abs_diff_uint(expected[ 0 ], resultPtr[ 0 ]), abs_diff_uint(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_uint(expected[ 2 ], resultPtr[ 2 ]), abs_diff_uint(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if (error <= MAX_ERR) + found_pixel = 1; + }//norm_offset_x + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + checkOnlyOnePixel = 1; + } + + if ( gTestMipmaps ) + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected, lod ); + else + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected ); + + + + error = errMax( errMax( abs_diff_uint(expected[ 0 ], resultPtr[ 0 ]), abs_diff_uint(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_uint(expected[ 2 ], resultPtr[ 2 ]), abs_diff_uint(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if( error > MAX_ERR ) + { + log_error("FAILED norm_offsets: %g:\n", norm_offset_x); + + shouldReturn |= determine_validation_error_1D( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[j], norm_offset_x, j, numTries, numClamped, false, lod ); + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + }//norm_offset_x + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + /* + * INT output type + */ + else + { + // Validate integer results + int *resultPtr = (int *)(char *)resultValues; + int expected[4]; + float error; + for( size_t x = 0, j = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + checkOnlyOnePixel = 1; + } + + if ( gTestMipmaps ) + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected, lod); + else + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected ); + + error = errMax( errMax( abs_diff_int(expected[ 0 ], resultPtr[ 0 ]), abs_diff_int(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_int(expected[ 2 ], resultPtr[ 2 ]), abs_diff_int(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if (error <= MAX_ERR) + found_pixel = 1; + }//norm_offset_x + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + checkOnlyOnePixel = 1; + } + + if ( gTestMipmaps ) + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected, lod); + else + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], 0.0f, 0.0f, norm_offset_x, 0.0f, 0.0f, + imageSampler, expected ); + + + error = errMax( errMax( abs_diff_int(expected[ 0 ], resultPtr[ 0 ]), abs_diff_int(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_int(expected[ 2 ], resultPtr[ 2 ]), abs_diff_int(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if( error > MAX_ERR ) + { + log_error("FAILED norm_offsets: %g:\n", norm_offset_x); + + shouldReturn |= determine_validation_error_1D( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[j], norm_offset_x, j, numTries, numClamped, false, lod ); + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + }//norm_offset_x + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + { + nextLevelOffset += width_lod * get_pixel_size(imageInfo->format); + width_lod = (width_lod >> 1) ? (width_lod >> 1) : 1; + } + } + + return numTries != MAX_TRIES || numClamped != MAX_CLAMPED; +} + +int test_read_image_set_1D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, + bool floatCoords, ExplicitType outputType ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + clProgramWrapper program; + clKernelWrapper kernel; + RandomSeed seed( gRandomSeed ); + int error; + + // Get our operating params + size_t maxWidth; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0x0 }; + size_t pixelSize; + + const char *KernelSourcePattern = NULL; + + imageInfo.format = format; + imageInfo.height = 1; + imageInfo.depth = imageInfo.arraySize = imageInfo.slicePitch = 0; + imageInfo.type = CL_MEM_OBJECT_IMAGE1D; + pixelSize = get_pixel_size( imageInfo.format ); + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // Determine types + if( outputType == kInt ) + readFormat = "i"; + else if( outputType == kUInt ) + readFormat = "ui"; + else // kFloat + readFormat = "f"; + + // Construct the source + const char *samplerArg = samplerKernelArg; + char samplerVar[ 1024 ] = ""; + if( gUseKernelSamplers ) + { + get_sampler_kernel_code( imageSampler, samplerVar ); + samplerArg = ""; + } + + if(gtestTypesToRun & kReadWriteTests) + { + KernelSourcePattern = read_write1DKernelSourcePattern; + } + else + { + KernelSourcePattern = read1DKernelSourcePattern; + } + sprintf( programSrc, + KernelSourcePattern, + samplerArg, get_explicit_type_name( outputType ), + gTestMipmaps ? ", float lod" : "", + samplerVar, + floatCoords ? float1DKernelSource : int1DCoordKernelSource, + readFormat, + gTestMipmaps ? ", lod" : "" ); + + ptr = programSrc; + + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + if(error) + { + exit(1); + } + test_error( error, "Unable to create testing kernel" ); + + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + + if(gTestMipmaps) + imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), seed); + + if( gDebugTrace ) + log_info( " at size %d\n", (int)imageInfo.width ); + + int retCode = test_read_image_1D( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format, CL_TRUE); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + log_info("Testing %d\n", (int)sizes[ idx ][ 0 ]); + if(gTestMipmaps) + imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), seed); + if( gDebugTrace ) + log_info( " at max size %d\n", (int)sizes[ idx ][ 0 ] ); + int retCode = test_read_image_1D( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + } + else if( gTestRounding ) + { + uint64_t typeRange = 1LL << ( get_format_type_size( imageInfo.format ) * 8 ); + typeRange /= get_pixel_size( imageInfo.format ) / get_format_type_size( imageInfo.format ); + imageInfo.width = (size_t)( ( typeRange + 255LL ) / 256LL ); + + while( imageInfo.width >= maxWidth / 2 ) + imageInfo.width >>= 1; + imageInfo.rowPitch = imageInfo.width * pixelSize; + + gRoundingStartValue = 0; + do + { + if( gDebugTrace ) + log_info( " at size %d, starting round ramp at %llu for range %llu\n", (int)imageInfo.width, gRoundingStartValue, typeRange ); + int retCode = test_read_image_1D( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + + gRoundingStartValue += imageInfo.width * pixelSize / get_format_type_size( imageInfo.format ); + + } while( gRoundingStartValue < typeRange ); + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + if(gTestMipmaps) + { + imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), seed); + size = (cl_ulong) compute_mipmapped_image_size(imageInfo) * 4; + } + else + { + if( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth * pixelSize; + } + + size = (size_t)imageInfo.rowPitch * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d (row pitch %d) out of %d\n", (int)imageInfo.width, (int)imageInfo.rowPitch, (int)maxWidth ); + int retCode = test_read_image_1D( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + } + + return 0; +} diff --git a/test_conformance/images/kernel_read_write/test_read_1D_array.cpp b/test_conformance/images/kernel_read_write/test_read_1D_array.cpp new file mode 100644 index 00000000..2cd7f8a6 --- /dev/null +++ b/test_conformance/images/kernel_read_write/test_read_1D_array.cpp @@ -0,0 +1,1284 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" +#include + +#if defined( __APPLE__ ) +#include +#include +#include +#endif + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gExtraValidateInfo, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_device_type gDeviceType; +extern bool gUseKernelSamplers; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern uint64_t gRoundingStartValue; +extern cl_mem_flags gMemFlagsToUse; +extern int gtestTypesToRun; + +#define MAX_TRIES 1 +#define MAX_CLAMPED 1 + +const char *read1DArrayKernelSourcePattern = +"__kernel void sample_kernel( read_only image1d_array_t input,%s __global float *xOffsets, __global float *yOffsets, __global %s4 *results %s)\n" +"{\n" +"%s" +" int tidX = get_global_id(0), tidY = get_global_id(1);\n" +"%s" +"%s" +" results[offset] = read_image%s( input, imageSampler, coords %s);\n" +"}"; + +const char *read_write1DArrayKernelSourcePattern = +"__kernel void sample_kernel( read_write image1d_array_t input,%s __global float *xOffsets, __global float *yOffsets, __global %s4 *results %s )\n" +"{\n" +"%s" +" int tidX = get_global_id(0), tidY = get_global_id(1);\n" +"%s" +"%s" +" results[offset] = read_image%s( input, coords %s);\n" +"}"; + +const char *offset1DArrayKernelSource = +" int offset = tidY*get_image_width(input) + tidX;\n"; + +const char *offset1DArrayLodKernelSource = +" int lod_int = (int)lod;\n" +" int width_lod = (get_image_width(input) >> lod_int) ? (get_image_width(input) >> lod_int): 1;\n" +" int offset = tidY*width_lod + tidX;\n"; + +const char *intCoordKernelSource1DArray = +" int2 coords = (int2)( xOffsets[offset], yOffsets[offset]);\n"; + +const char *floatKernelSource1DArray = +" float2 coords = (float2)( (float)( xOffsets[offset] ), (float)( yOffsets[offset] ) );\n"; + +static const char *samplerKernelArg = " sampler_t imageSampler,"; + +#define ABS_ERROR( result, expected ) ( fabsf( (float)expected - (float)result ) ) + +extern void read_image_pixel_float( void *imageData, image_descriptor *imageInfo, + int x, int y, int z, float *outData ); + +extern void read_image_pixel_float( void *imageData, image_descriptor *imageInfo, + int x, int y, int z, float *outData , int lod); + +template int determine_validation_error_1D_arr( void *imagePtr, image_descriptor *imageInfo, image_sampler_data *imageSampler, + T *resultPtr, T * expected, float error, + float x, float y, float xAddressOffset, float yAddressOffset, size_t j, int &numTries, int &numClamped, bool printAsFloat, int lod ) +{ + int actualX, actualY; + int found = debug_find_pixel_in_image( imagePtr, imageInfo, resultPtr, &actualX, &actualY, NULL, lod ); + bool clampingErr = false, clamped = false, otherClampingBug = false; + int clampedX, clampedY, ignoreMe; + + // FIXME: I do not believe this is correct for 1D or 2D image arrays; + // it will report spurious validation failure reasons since + // the clamping for such image objects is different than 1D-3D + // image objects. + clamped = get_integer_coords_offset( x, y, 0.0f, xAddressOffset, yAddressOffset, 0.0f, imageInfo->width, imageInfo->arraySize, 0, imageSampler, imageInfo, clampedX, clampedY, ignoreMe ); + + if( found ) + { + // Is it a clamping bug? + if( clamped && clampedX == actualX && clampedY == actualY ) + { + if( (--numClamped) == 0 ) + { + log_error( "ERROR: TEST FAILED: Read is erroneously clamping coordinates for image size %ld x %ld!\n", imageInfo->width, imageInfo->arraySize ); + if( printAsFloat ) + { + log_error( "Sample %d: coord {%f(%a), %f(%a)} did not validate!\n\tExpected (%g,%g,%g,%g),\n\tgot (%g,%g,%g,%g),\n\terror of %g\n", + (int)j, x, x, y, y, (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ], + (float)resultPtr[ 0 ], (float)resultPtr[ 1 ], (float)resultPtr[ 2 ], (float)resultPtr[ 3 ], error ); + } + else + { + log_error( "Sample %d: coord {%f(%a), %f(%a)} did not validate!\n\tExpected (%x,%x,%x,%x),\n\tgot (%x,%x,%x,%x)\n", + (int)j, x, x, y, y, (int)expected[ 0 ], (int)expected[ 1 ], (int)expected[ 2 ], (int)expected[ 3 ], + (int)resultPtr[ 0 ], (int)resultPtr[ 1 ], (int)resultPtr[ 2 ], (int)resultPtr[ 3 ] ); + } + return 1; + } + clampingErr = true; + otherClampingBug = true; + } + } + if( clamped && !otherClampingBug ) + { + // If we are in clamp-to-edge mode and we're getting zeroes, it's possible we're getting border erroneously + if( resultPtr[ 0 ] == 0 && resultPtr[ 1 ] == 0 && resultPtr[ 2 ] == 0 && resultPtr[ 3 ] == 0 ) + { + if( (--numClamped) == 0 ) + { + log_error( "ERROR: TEST FAILED: Clamping is erroneously returning border color for image size %ld x %ld!\n", imageInfo->width, imageInfo->arraySize ); + if( printAsFloat ) + { + log_error( "Sample %d: coord {%f(%a), %f(%a)} did not validate!\n\tExpected (%g,%g,%g,%g),\n\tgot (%g,%g,%g,%g),\n\terror of %g\n", + (int)j, x, x, y, y, (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ], + (float)resultPtr[ 0 ], (float)resultPtr[ 1 ], (float)resultPtr[ 2 ], (float)resultPtr[ 3 ], error ); + } + else + { + log_error( "Sample %d: coord {%f(%a), %f(%a)} did not validate!\n\tExpected (%x,%x,%x,%x),\n\tgot (%x,%x,%x,%x)\n", + (int)j, x, x, y, y, (int)expected[ 0 ], (int)expected[ 1 ], (int)expected[ 2 ], (int)expected[ 3 ], + (int)resultPtr[ 0 ], (int)resultPtr[ 1 ], (int)resultPtr[ 2 ], (int)resultPtr[ 3 ] ); + } + return 1; + } + clampingErr = true; + } + } + if( !clampingErr ) + { + if( printAsFloat ) + { + log_error( "Sample %d: coord {%f(%a), %f(%a)} did not validate!\n\tExpected (%g,%g,%g,%g),\n\tgot (%g,%g,%g,%g), error of %g\n", + (int)j, x, x, y, y, (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ], + (float)resultPtr[ 0 ], (float)resultPtr[ 1 ], (float)resultPtr[ 2 ], (float)resultPtr[ 3 ], error ); + } + else + { + log_error( "Sample %d: coord {%f(%a), %f(%a)} did not validate!\n\tExpected (%x,%x,%x,%x),\n\tgot (%x,%x,%x,%x)\n", + (int)j, x, x, y, y, (int)expected[ 0 ], (int)expected[ 1 ], (int)expected[ 2 ], (int)expected[ 3 ], + (int)resultPtr[ 0 ], (int)resultPtr[ 1 ], (int)resultPtr[ 2 ], (int)resultPtr[ 3 ] ); + } + log_error( "img size %ld,%ld (pitch %ld)", imageInfo->width, imageInfo->arraySize, imageInfo->rowPitch ); + if( clamped ) + { + log_error( " which would clamp to %d,%d\n", clampedX, clampedY ); + } + if( printAsFloat && gExtraValidateInfo) + { + log_error( "Nearby values:\n" ); + log_error( "\t%d\t%d\t%d\t%d\n", clampedX - 2, clampedX - 1, clampedX, clampedX + 1 ); + for( int yOff = -2; yOff <= 1; yOff++ ) + { + float top[ 4 ], real[ 4 ], bot[ 4 ], bot2[ 4 ]; + read_image_pixel_float( imagePtr, imageInfo, clampedX - 2 , clampedY + yOff, 0, top ); + read_image_pixel_float( imagePtr, imageInfo, clampedX - 1 ,clampedY + yOff, 0, real ); + read_image_pixel_float( imagePtr, imageInfo, clampedX, clampedY + yOff, 0, bot ); + read_image_pixel_float( imagePtr, imageInfo, clampedX + 1, clampedY + yOff, 0, bot2 ); + log_error( "%d\t(%g,%g,%g,%g)",clampedY + yOff, top[0], top[1], top[2], top[3] ); + log_error( " (%g,%g,%g,%g)", real[0], real[1], real[2], real[3] ); + log_error( " (%g,%g,%g,%g)",bot[0], bot[1], bot[2], bot[3] ); + log_error( " (%g,%g,%g,%g)\n",bot2[0], bot2[1], bot2[2], bot2[3] ); + } + + if( clampedY < 1 ) + { + log_error( "Nearby values:\n" ); + log_error( "\t%d\t%d\t%d\t%d\n", clampedX - 2, clampedX - 1, clampedX, clampedX + 1 ); + for( int yOff = (int)imageInfo->arraySize - 2; yOff <= (int)imageInfo->arraySize + 1; yOff++ ) + { + float top[ 4 ], real[ 4 ], bot[ 4 ], bot2[ 4 ]; + read_image_pixel_float( imagePtr, imageInfo, clampedX - 2 , clampedY + yOff, 0, top ); + read_image_pixel_float( imagePtr, imageInfo, clampedX - 1 ,clampedY + yOff, 0, real ); + read_image_pixel_float( imagePtr, imageInfo, clampedX, clampedY + yOff, 0, bot ); + read_image_pixel_float( imagePtr, imageInfo, clampedX + 1, clampedY + yOff, 0, bot2 ); + log_error( "%d\t(%g,%g,%g,%g)",clampedY + yOff, top[0], top[1], top[2], top[3] ); + log_error( " (%g,%g,%g,%g)", real[0], real[1], real[2], real[3] ); + log_error( " (%g,%g,%g,%g)",bot[0], bot[1], bot[2], bot[3] ); + log_error( " (%g,%g,%g,%g)\n",bot2[0], bot2[1], bot2[2], bot2[3] ); + } + } + } + + if( imageSampler->filter_mode != CL_FILTER_LINEAR ) + { + if( found ) + log_error( "\tValue really found in image at %d,%d (%s)\n", actualX, actualY, ( found > 1 ) ? "NOT unique!!" : "unique" ); + else + log_error( "\tValue not actually found in image\n" ); + } + log_error( "\n" ); + + numClamped = -1; // We force the clamped counter to never work + if( ( --numTries ) == 0 ) + { + return 1; + } + } + return 0; +} + +#define CLAMP( _val, _min, _max ) ((_val) < (_min) ? (_min) : (_val) > (_max) ? (_max) : (_val)) + +static void InitFloatCoords( image_descriptor *imageInfo, image_sampler_data *imageSampler, float *xOffsets, float *yOffsets, float xfract, float yfract, int normalized_coords, MTdata d , int lod) +{ + size_t i = 0; + size_t width_lod = imageInfo->width; + + if(gTestMipmaps) + width_lod = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1; + + if( gDisableOffsets ) + { + for( size_t y = 0; y < imageInfo->arraySize; y++ ) + { + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) (xfract + (double) x); + yOffsets[ i ] = (float) (yfract + (double) y); + } + } + } + else + { + for( size_t y = 0; y < imageInfo->arraySize; y++ ) + { + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) (xfract + (double) ((int) x + random_in_range( -10, 10, d ))); + yOffsets[ i ] = (float) (yfract + (double) ((int) y + random_in_range( -10, 10, d ))); + } + } + } + + if( imageSampler->addressing_mode == CL_ADDRESS_NONE ) + { + i = 0; + for( size_t y = 0; y < imageInfo->arraySize; y++ ) + { + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) CLAMP( (double) xOffsets[ i ], 0.0, (double)width_lod - 1.0); + yOffsets[ i ] = (float) CLAMP( (double) yOffsets[ i ], 0.0, (double)imageInfo->arraySize - 1.0); + } + } + } + + if( normalized_coords ) + { + i = 0; + for( size_t y = 0; y < imageInfo->arraySize; y++ ) + { + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) ((double) xOffsets[ i ] / (double) width_lod); + } + } + } +} + +#ifndef MAX +#define MAX( _a, _b ) ((_a) > (_b) ? (_a) : (_b)) +#endif + + +int test_read_image_1D_array( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, image_sampler_data *imageSampler, + bool useFloatCoords, ExplicitType outputType, MTdata d ) +{ + int error; + static int initHalf = 0; + + size_t threads[2]; + cl_mem_flags image_read_write_flags = CL_MEM_READ_ONLY; + clMemWrapper xOffsets, yOffsets, results; + clSamplerWrapper actualSampler; + BufferOwningPtr maxImageUseHostPtrBackingStore; + + // The DataBuffer template class really does use delete[], not free -- IRO + BufferOwningPtr xOffsetValues(malloc(sizeof(cl_float) * imageInfo->width * imageInfo->arraySize)); + BufferOwningPtr yOffsetValues(malloc(sizeof(cl_float) * imageInfo->width * imageInfo->arraySize)); + + if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) + if( DetectFloatToHalfRoundingMode(queue) ) + return 1; + + // generate_random_image_data allocates with malloc, so we use a MallocDataBuffer here + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + if( gDebugTrace ) + { + log_info( " - Creating 1D image array %d by %d...\n", (int)imageInfo->width, (int)imageInfo->arraySize ); + if(gTestMipmaps) + log_info(" - and %d mip levels\n", (int)imageInfo->num_mip_levels); + } + + // Construct testing sources + clProtectedImage protImage; + clMemWrapper unprotImage; + cl_mem image; + + if(gtestTypesToRun & kReadTests) + { + image_read_write_flags = CL_MEM_READ_ONLY; + } + else + { + image_read_write_flags = CL_MEM_READ_WRITE; + } + + if( gMemFlagsToUse == CL_MEM_USE_HOST_PTR ) + { + // clProtectedImage uses USE_HOST_PTR, so just rely on that for the testing (via Ian) + // Do not use protected images for max image size test since it rounds the row size to a page size + if (gTestMaxImages) { + generate_random_image_data( imageInfo, maxImageUseHostPtrBackingStore, d ); + + unprotImage = create_image_1d_array(context, + image_read_write_flags | CL_MEM_USE_HOST_PTR, + imageInfo->format, + imageInfo->width, imageInfo->arraySize, + ( gEnablePitch ? imageInfo->rowPitch : 0 ), + ( gEnablePitch ? imageInfo->slicePitch : 0), + maxImageUseHostPtrBackingStore, &error); + } else { + error = protImage.Create( context, CL_MEM_OBJECT_IMAGE1D_ARRAY, + image_read_write_flags, + imageInfo->format, + imageInfo->width, 1, 1, imageInfo->arraySize ); + } + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 1D image array of size %d x %d pitch %d (%s)\n", + (int)imageInfo->width, (int)imageInfo->arraySize, + (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + + if (gTestMaxImages) + image = (cl_mem)unprotImage; + else + image = (cl_mem)protImage; + } + else if( gMemFlagsToUse == CL_MEM_COPY_HOST_PTR ) + { + // Don't use clEnqueueWriteImage; just use copy host ptr to get the data in + unprotImage = create_image_1d_array(context, + image_read_write_flags | CL_MEM_COPY_HOST_PTR, + imageInfo->format, + imageInfo->width, imageInfo->arraySize, + ( gEnablePitch ? imageInfo->rowPitch : 0 ), + ( gEnablePitch ? imageInfo->slicePitch : 0), + imageValues, &error); + + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 1D image array of size %d x %d pitch %d (%s)\n", + (int)imageInfo->width, (int)imageInfo->arraySize, + (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + image = unprotImage; + } + else // Either CL_MEM_ALLOC_HOST_PTR or none + { + // Note: if ALLOC_HOST_PTR is used, the driver allocates memory that can be accessed by the host, but otherwise + // it works just as if no flag is specified, so we just do the same thing either way + if(gTestMipmaps) + { + cl_image_desc image_desc = {0}; + image_desc.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + image_desc.image_width = imageInfo->width; + image_desc.image_array_size = imageInfo->arraySize; + image_desc.num_mip_levels = imageInfo->num_mip_levels; + + unprotImage = clCreateImage( context, + image_read_write_flags, + imageInfo->format, &image_desc, NULL, &error); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create %d level mipmapped 1D image array of size %d x %d (pitch %d, %d ) (%s)",(int)imageInfo->num_mip_levels, (int)imageInfo->width, (int)imageInfo->arraySize, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + } + else + { + unprotImage = create_image_1d_array(context, + image_read_write_flags | gMemFlagsToUse, + imageInfo->format, + imageInfo->width, imageInfo->arraySize, + ( gEnablePitch ? imageInfo->rowPitch : 0 ), + ( gEnablePitch ? imageInfo->slicePitch : 0), + imageValues, &error); + + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 1D image array of size %d x %d pitch %d (%s)\n", + (int)imageInfo->width, (int)imageInfo->arraySize, + (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + } + image = unprotImage; + } + + if( gMemFlagsToUse != CL_MEM_COPY_HOST_PTR ) + { + if( gDebugTrace ) + log_info( " - Writing image...\n" ); + + size_t origin[ 3 ] = { 0, 0, 0 }; + size_t region[ 3 ] = { imageInfo->width, imageInfo->arraySize, 1 }; + + if(gTestMipmaps) + { + int nextLevelOffset = 0; + + for (int i =0; i < imageInfo->num_mip_levels; i++) + { origin[2] = i; + error = clEnqueueWriteImage(queue, image, CL_TRUE, + origin, region, /*gEnablePitch ? imageInfo->rowPitch :*/ 0, /*gEnablePitch ? imageInfo->slicePitch :*/ 0, + ((char*)imageValues + nextLevelOffset), 0, NULL, NULL); + if (error != CL_SUCCESS) + { + log_error( "ERROR: Unable to write to %d level mipmapped 3D image of size %d x %d x %d\n", (int)imageInfo->num_mip_levels,(int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth ); + return error; + } + nextLevelOffset += region[0]*region[1]*get_pixel_size(imageInfo->format); + //Subsequent mip level dimensions keep halving + region[0] = region[0] >> 1 ? region[0] >> 1 : 1; + } + } + else + { + error = clEnqueueWriteImage(queue, image, CL_TRUE, + origin, region, ( gEnablePitch ? imageInfo->rowPitch : 0 ), 0, + imageValues, 0, NULL, NULL); + if (error != CL_SUCCESS) + { + log_error( "ERROR: Unable to write to %d level 1D image array of size %d x %d\n", + (int)imageInfo->num_mip_levels, + (int)imageInfo->width, (int)imageInfo->arraySize ); + return error; + } + } + } + + if( gDebugTrace ) + log_info( " - Creating kernel arguments...\n" ); + + xOffsets = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), + sizeof( cl_float ) * imageInfo->width * imageInfo->arraySize, xOffsetValues, &error ); + test_error( error, "Unable to create x offset buffer" ); + + yOffsets = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), + sizeof( cl_float ) * imageInfo->width * imageInfo->arraySize, yOffsetValues, &error ); + test_error( error, "Unable to create y offset buffer" ); + + results = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), + get_explicit_type_size( outputType ) * 4 * imageInfo->width * imageInfo->arraySize, NULL, &error ); + test_error( error, "Unable to create result buffer" ); + + // Create sampler to use + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, imageSampler->normalized_coords, + CL_SAMPLER_ADDRESSING_MODE, imageSampler->addressing_mode, + CL_SAMPLER_FILTER_MODE, imageSampler->filter_mode, + 0, 0, 0 }; + if (gTestMipmaps) { + properties[6] = CL_SAMPLER_MIP_FILTER_MODE; + properties[7] = imageSampler->filter_mode; + } + actualSampler = clCreateSamplerWithProperties(context, properties, &error ); + test_error( error, "Unable to create image sampler" ); + + // Set arguments + int idx = 0; + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &image ); + test_error( error, "Unable to set kernel arguments" ); + if( !gUseKernelSamplers ) + { + error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler ); + test_error( error, "Unable to set kernel arguments" ); + } + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &xOffsets ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &yOffsets ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results ); + test_error( error, "Unable to set kernel arguments" ); + + // A cast of troublesome offsets. The first one has to be zero. + const float float_offsets[] = { 0.0f, MAKE_HEX_FLOAT(0x1.0p-30f, 0x1L, -30), 0.25f, 0.3f, 0.5f - FLT_EPSILON/4.0f, 0.5f, 0.9f, 1.0f - FLT_EPSILON/2 }; + int float_offset_count = sizeof( float_offsets) / sizeof( float_offsets[0] ); + int numTries = MAX_TRIES, numClamped = MAX_CLAMPED; + int loopCount = 2 * float_offset_count; + if( ! useFloatCoords ) + loopCount = 1; + if (gTestMaxImages) { + loopCount = 1; + log_info("Testing each size only once with pixel offsets of %g for max sized images.\n", float_offsets[0]); + } + + // Get the maximum absolute error for this format + if(gtestTypesToRun & kReadWriteTests) + { + loopCount = 1; + } + + // Get the maximum absolute error for this format + double formatAbsoluteError = get_max_absolute_error(imageInfo->format, imageSampler); + if (gDebugTrace) log_info("\tformatAbsoluteError is %e\n", formatAbsoluteError); + + if (0 == initHalf && imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) { + initHalf = CL_SUCCESS == DetectFloatToHalfRoundingMode( queue ); + if (initHalf) { + log_info("Half rounding mode successfully detected.\n"); + } + } + + size_t width_lod = imageInfo->width; + size_t nextLevelOffset = 0; + char * imagePtr; + for(int lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++) + { + size_t resultValuesSize = width_lod * imageInfo->arraySize * get_explicit_type_size( outputType ) * 4; + BufferOwningPtr resultValues(malloc(resultValuesSize)); + float lod_float = (float)lod; + if (gTestMipmaps) { + //Set the lod kernel arg + if(gDebugTrace) + log_info(" - Working at mip level %d\n", lod); + error = clSetKernelArg( kernel, idx, sizeof( float ), &lod_float); + test_error( error, "Unable to set kernel arguments" ); + } + + for( int q = 0; q < loopCount; q++ ) + { + float offset = float_offsets[ q % float_offset_count ]; + + // Init the coordinates + InitFloatCoords(imageInfo, imageSampler, xOffsetValues, yOffsetValues, + q>=float_offset_count ? -offset: offset, + q>=float_offset_count ? offset: -offset, imageSampler->normalized_coords, d, lod ); + + error = clEnqueueWriteBuffer( queue, xOffsets, CL_TRUE, 0, sizeof(cl_float) * imageInfo->arraySize * imageInfo->width, xOffsetValues, 0, NULL, NULL ); + test_error( error, "Unable to write x offsets" ); + error = clEnqueueWriteBuffer( queue, yOffsets, CL_TRUE, 0, sizeof(cl_float) * imageInfo->arraySize * imageInfo->width, yOffsetValues, 0, NULL, NULL ); + test_error( error, "Unable to write y offsets" ); + + // Get results + memset( resultValues, 0xff, resultValuesSize ); + clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + + // Run the kernel + threads[0] = (size_t)width_lod; + threads[1] = (size_t)imageInfo->arraySize; + error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + if( gDebugTrace ) + log_info( " reading results, %ld kbytes\n", (unsigned long)( width_lod * imageInfo->arraySize * get_explicit_type_size( outputType ) * 4 / 1024 ) ); + + error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, width_lod * imageInfo->arraySize * get_explicit_type_size( outputType ) * 4, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + if( gDebugTrace ) + log_info( " results read\n" ); + + // Validate results element by element + imagePtr = (char*)imageValues + nextLevelOffset; + /* + * FLOAT output type, order= sRGB + */ + if(is_sRGBA_order(imageInfo->format->image_channel_order) && ( outputType == kFloat )) + { + // Validate float results + float *resultPtr = (float *)(char *)resultValues; + float expected[4], error=0.0f; + float maxErr = get_max_relative_error( imageInfo->format, imageSampler, 0 /*not 3D*/, CL_FILTER_LINEAR == imageSampler->filter_mode ); + for( size_t y = 0, j = 0; y < imageInfo->arraySize; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + float offset = NORM_OFFSET; + if (!imageSampler->normalized_coords || imageSampler->filter_mode != CL_FILTER_NEAREST || NORM_OFFSET == 0 +#if defined( __APPLE__ ) + // Apple requires its CPU implementation to do correctly rounded address arithmetic in all modes + || gDeviceType != CL_DEVICE_TYPE_GPU +#endif + ) + offset = 0.0f; // Loop only once + + for (float norm_offset_x = -offset; norm_offset_x <= offset && !found_pixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !found_pixel; norm_offset_y += NORM_OFFSET) { + + + // Try sampling the pixel, without flushing denormals. + int containsDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, &containsDenormals, lod ); + + float err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + float err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + float err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + float maxErr = 0.5; + + // Check if the result matches. + if( ! (err1 <= maxErr) || ! (err2 <= maxErr) || + ! (err3 <= maxErr) || ! (err4 <= maxErr) ) + { + //try flushing the denormals, if there is a failure. + if( containsDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + + // If the final result DOES match, then we've found a valid result and we're done with this pixel. + found_pixel = (err1 <= maxErr) && (err2 <= maxErr) && (err3 <= maxErr) && (err4 <= maxErr); + }//norm_offset_x + }//norm_offset_y + + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -offset; norm_offset_x <= offset && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + checkOnlyOnePixel = 1; + } + + int containsDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, &containsDenormals, lod ); + + float err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + float err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + float err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + + float maxErr = 0.6; + + if( ! (err1 <= maxErr) || ! (err2 <= maxErr) || + ! (err3 <= maxErr) || ! (err4 <= maxErr) ) + { + //try flushing the denormals, if there is a failure. + if( containsDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + if( ! (err1 <= maxErr) || ! (err2 <= maxErr) || + ! (err3 <= maxErr) || ! (err4 <= maxErr) ) + { + log_error("FAILED norm_offsets: %g , %g:\n", norm_offset_x, norm_offset_y); + + float tempOut[4]; + shouldReturn |= determine_validation_error_1D_arr( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[ j ], yOffsetValues[ j ], norm_offset_x, norm_offset_y, j, numTries, numClamped, true, lod ); + + log_error( "Step by step:\n" ); + FloatPixel temp = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, tempOut, 1 /* verbose */, &containsDenormals /*dont flush while error reporting*/, lod ); + log_error( "\tulps: %2.2f, %2.2f, %2.2f, %2.2f (max allowed: %2.2f)\n\n", + Ulp_Error( resultPtr[0], expected[0] ), + Ulp_Error( resultPtr[1], expected[1] ), + Ulp_Error( resultPtr[2], expected[2] ), + Ulp_Error( resultPtr[3], expected[3] ), + Ulp_Error( MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) + maxErr, MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) ) ); + + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + + }//norm_offset_x + }//norm_offset_y + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + /* + * FLOAT output type + */ + else if( outputType == kFloat ) + { + // Validate float results + float *resultPtr = (float *)(char *)resultValues; + float expected[4], error=0.0f; + float maxErr = get_max_relative_error( imageInfo->format, imageSampler, 0 /*not 3D*/, CL_FILTER_LINEAR == imageSampler->filter_mode ); + for( size_t y = 0, j = 0; y < imageInfo->arraySize; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + float offset = NORM_OFFSET; + if (!imageSampler->normalized_coords || imageSampler->filter_mode != CL_FILTER_NEAREST || NORM_OFFSET == 0 +#if defined( __APPLE__ ) + // Apple requires its CPU implementation to do correctly rounded address arithmetic in all modes + || gDeviceType != CL_DEVICE_TYPE_GPU +#endif + ) + offset = 0.0f; // Loop only once + + for (float norm_offset_x = -offset; norm_offset_x <= offset && !found_pixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !found_pixel; norm_offset_y += NORM_OFFSET) { + + + // Try sampling the pixel, without flushing denormals. + int containsDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, &containsDenormals, lod ); + + float err1 = fabsf( resultPtr[0] - expected[0] ); + float err2 = fabsf( resultPtr[1] - expected[1] ); + float err3 = fabsf( resultPtr[2] - expected[2] ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + // Clamp to the minimum absolute error for the format + if (err1 > 0 && err1 < formatAbsoluteError) { err1 = 0.0f; } + if (err2 > 0 && err2 < formatAbsoluteError) { err2 = 0.0f; } + if (err3 > 0 && err3 < formatAbsoluteError) { err3 = 0.0f; } + if (err4 > 0 && err4 < formatAbsoluteError) { err4 = 0.0f; } + float maxErr1 = MAX( maxErr * maxPixel.p[0], FLT_MIN ); + float maxErr2 = MAX( maxErr * maxPixel.p[1], FLT_MIN ); + float maxErr3 = MAX( maxErr * maxPixel.p[2], FLT_MIN ); + float maxErr4 = MAX( maxErr * maxPixel.p[3], FLT_MIN ); + + // Check if the result matches. + if( ! (err1 <= maxErr1) || ! (err2 <= maxErr2) || + ! (err3 <= maxErr3) || ! (err4 <= maxErr4) ) + { + //try flushing the denormals, if there is a failure. + if( containsDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr1 += 4 * FLT_MIN; + maxErr2 += 4 * FLT_MIN; + maxErr3 += 4 * FLT_MIN; + maxErr4 += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( resultPtr[0] - expected[0] ); + err2 = fabsf( resultPtr[1] - expected[1] ); + err3 = fabsf( resultPtr[2] - expected[2] ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + + // If the final result DOES match, then we've found a valid result and we're done with this pixel. + found_pixel = (err1 <= maxErr1) && (err2 <= maxErr2) && (err3 <= maxErr3) && (err4 <= maxErr4); + }//norm_offset_x + }//norm_offset_y + + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -offset; norm_offset_x <= offset && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + checkOnlyOnePixel = 1; + } + + int containsDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, &containsDenormals, lod ); + + float err1 = fabsf( resultPtr[0] - expected[0] ); + float err2 = fabsf( resultPtr[1] - expected[1] ); + float err3 = fabsf( resultPtr[2] - expected[2] ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + float maxErr1 = MAX( maxErr * maxPixel.p[0], FLT_MIN ); + float maxErr2 = MAX( maxErr * maxPixel.p[1], FLT_MIN ); + float maxErr3 = MAX( maxErr * maxPixel.p[2], FLT_MIN ); + float maxErr4 = MAX( maxErr * maxPixel.p[3], FLT_MIN ); + + + if( ! (err1 <= maxErr1) || ! (err2 <= maxErr2) || + ! (err3 <= maxErr3) || ! (err4 <= maxErr4) ) + { + //try flushing the denormals, if there is a failure. + if( containsDenormals ) + { + maxErr1 += 4 * FLT_MIN; + maxErr2 += 4 * FLT_MIN; + maxErr3 += 4 * FLT_MIN; + maxErr4 += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( resultPtr[0] - expected[0] ); + err2 = fabsf( resultPtr[1] - expected[1] ); + err3 = fabsf( resultPtr[2] - expected[2] ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + if( ! (err1 <= maxErr1) || ! (err2 <= maxErr2) || + ! (err3 <= maxErr3) || ! (err4 <= maxErr4) ) + { + log_error("FAILED norm_offsets: %g , %g:\n", norm_offset_x, norm_offset_y); + + float tempOut[4]; + shouldReturn |= determine_validation_error_1D_arr( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[ j ], yOffsetValues[ j ], norm_offset_x, norm_offset_y, j, numTries, numClamped, true, lod ); + + log_error( "Step by step:\n" ); + FloatPixel temp = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, tempOut, 1 /* verbose */, &containsDenormals /*dont flush while error reporting*/, lod ); + log_error( "\tulps: %2.2f, %2.2f, %2.2f, %2.2f (max allowed: %2.2f)\n\n", + Ulp_Error( resultPtr[0], expected[0] ), + Ulp_Error( resultPtr[1], expected[1] ), + Ulp_Error( resultPtr[2], expected[2] ), + Ulp_Error( resultPtr[3], expected[3] ), + Ulp_Error( MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) + maxErr, MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) ) ); + + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + + }//norm_offset_x + }//norm_offset_y + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + /* + * UINT output type + */ + else if( outputType == kUInt ) + { + // Validate unsigned integer results + unsigned int *resultPtr = (unsigned int *)(char *)resultValues; + unsigned int expected[4]; + float error; + for( size_t y = 0, j = 0; y < imageInfo->arraySize; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + checkOnlyOnePixel = 1; + } + + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, lod ); + + + error = errMax( errMax( abs_diff_uint(expected[ 0 ], resultPtr[ 0 ]), abs_diff_uint(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_uint(expected[ 2 ], resultPtr[ 2 ]), abs_diff_uint(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if (error <= MAX_ERR) + found_pixel = 1; + }//norm_offset_x + }//norm_offset_y + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + checkOnlyOnePixel = 1; + } + + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, lod ); + + + error = errMax( errMax( abs_diff_uint(expected[ 0 ], resultPtr[ 0 ]), abs_diff_uint(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_uint(expected[ 2 ], resultPtr[ 2 ]), abs_diff_uint(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if( error > MAX_ERR ) + { + log_error("FAILED norm_offsets: %g , %g:\n", norm_offset_x, norm_offset_y); + + shouldReturn |= determine_validation_error_1D_arr( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[j], yOffsetValues[j], norm_offset_x, norm_offset_y, j, numTries, numClamped, false, lod ); + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + }//norm_offset_x + }//norm_offset_y + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + /* + * INT output type + */ + else + { + // Validate integer results + int *resultPtr = (int *)(char *)resultValues; + int expected[4]; + float error; + for( size_t y = 0, j = 0; y < imageInfo->arraySize; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + checkOnlyOnePixel = 1; + } + + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, lod ); + + + error = errMax( errMax( abs_diff_int(expected[ 0 ], resultPtr[ 0 ]), abs_diff_int(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_int(expected[ 2 ], resultPtr[ 2 ]), abs_diff_int(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if (error <= MAX_ERR) + found_pixel = 1; + }//norm_offset_x + }//norm_offset_y + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + checkOnlyOnePixel = 1; + } + + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], 0.f, norm_offset_x, norm_offset_y, 0.0f, + imageSampler, expected, lod ); + + + error = errMax( errMax( abs_diff_int(expected[ 0 ], resultPtr[ 0 ]), abs_diff_int(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_int(expected[ 2 ], resultPtr[ 2 ]), abs_diff_int(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if( error > MAX_ERR ) + { + log_error("FAILED norm_offsets: %g , %g:\n", norm_offset_x, norm_offset_y); + + shouldReturn |= determine_validation_error_1D_arr( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[j], yOffsetValues[j], norm_offset_x, norm_offset_y, j, numTries, numClamped, false, lod ); + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + }//norm_offset_x + }//norm_offset_y + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + } + { + nextLevelOffset += width_lod * imageInfo->arraySize * get_pixel_size(imageInfo->format); + width_lod = (width_lod >> 1) ? (width_lod >> 1) : 1; + } + } + + return numTries != MAX_TRIES || numClamped != MAX_CLAMPED; +} + +int test_read_image_set_1D_array( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, + bool floatCoords, ExplicitType outputType ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + clProgramWrapper program; + clKernelWrapper kernel; + RandomSeed seed( gRandomSeed ); + int error; + const char *KernelSourcePattern = NULL; + + // Get our operating params + size_t maxWidth, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0x0 }; + size_t pixelSize; + + imageInfo.format = format; + imageInfo.depth = imageInfo.height = 0; + imageInfo.type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + pixelSize = get_pixel_size( imageInfo.format ); + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D array size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // Determine types + if( outputType == kInt ) + readFormat = "i"; + else if( outputType == kUInt ) + readFormat = "ui"; + else // kFloat + readFormat = "f"; + + // Construct the source + const char *samplerArg = samplerKernelArg; + char samplerVar[ 1024 ] = ""; + if( gUseKernelSamplers ) + { + get_sampler_kernel_code( imageSampler, samplerVar ); + samplerArg = ""; + } + + if(gtestTypesToRun & kReadTests) + { + KernelSourcePattern = read1DArrayKernelSourcePattern; + } + else + { + KernelSourcePattern = read_write1DArrayKernelSourcePattern; + } + + sprintf( programSrc, + KernelSourcePattern, + samplerArg, get_explicit_type_name( outputType ), + gTestMipmaps ? ", float lod" : "", + samplerVar, + gTestMipmaps ? offset1DArrayLodKernelSource : offset1DArrayKernelSource, + floatCoords ? floatKernelSource1DArray : intCoordKernelSource1DArray, + readFormat, + gTestMipmaps ? ", lod" : "" ); + + ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create testing kernel" ); + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.slicePitch = imageInfo.width * pixelSize; + for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ ) + { + if(gTestMipmaps) + imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), seed); + + if( gDebugTrace ) + log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize ); + + int retCode = test_read_image_1D_array( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D_ARRAY, imageInfo.format, CL_TRUE); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.arraySize = sizes[ idx ][ 2 ]; // 3rd dimension in get_max_sizes + imageInfo.rowPitch = imageInfo.slicePitch = imageInfo.width * pixelSize; + log_info("Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ]); + if(gTestMipmaps) + imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), seed); + if( gDebugTrace ) + log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] ); + int retCode = test_read_image_1D_array( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + } + else if( gTestRounding ) + { + uint64_t typeRange = 1LL << ( get_format_type_size( imageInfo.format ) * 8 ); + typeRange /= pixelSize / get_format_type_size( imageInfo.format ); + imageInfo.arraySize = (size_t)( ( typeRange + 255LL ) / 256LL ); + imageInfo.width = (size_t)( typeRange / (cl_ulong)imageInfo.arraySize ); + while( imageInfo.arraySize >= maxArraySize / 2 ) + { + imageInfo.width <<= 1; + imageInfo.arraySize >>= 1; + } + + while( imageInfo.width >= maxWidth / 2 ) + imageInfo.width >>= 1; + imageInfo.rowPitch = imageInfo.slicePitch = imageInfo.width * pixelSize; + + gRoundingStartValue = 0; + do + { + if( gDebugTrace ) + log_info( " at size %d,%d, starting round ramp at %llu for range %llu\n", (int)imageInfo.width, (int)imageInfo.arraySize, gRoundingStartValue, typeRange ); + int retCode = test_read_image_1D_array( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + + gRoundingStartValue += imageInfo.width * imageInfo.arraySize * pixelSize / get_format_type_size( imageInfo.format ); + + } while( gRoundingStartValue < typeRange ); + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + if(gTestMipmaps) + { + imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), seed); + size = (cl_ulong) compute_mipmapped_image_size(imageInfo) * 4; + } + else + { + if( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth * pixelSize; + } + imageInfo.slicePitch = imageInfo.rowPitch; + + size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.arraySize * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxArraySize ); + int retCode = test_read_image_1D_array( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + } + + return 0; +} diff --git a/test_conformance/images/kernel_read_write/test_read_2D_array.cpp b/test_conformance/images/kernel_read_write/test_read_2D_array.cpp new file mode 100644 index 00000000..61af6925 --- /dev/null +++ b/test_conformance/images/kernel_read_write/test_read_2D_array.cpp @@ -0,0 +1,1502 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" +#include + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gExtraValidateInfo, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_device_type gDeviceType; +extern bool gUseKernelSamplers; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern cl_mem_flags gMemFlagsToUse; +extern int gtestTypesToRun; +#define MAX_TRIES 1 +#define MAX_CLAMPED 1 + +// Utility function to clamp down image sizes for certain tests to avoid +// using too much memory. +static size_t reduceImageSizeRange(size_t maxDimSize) { + size_t DimSize = maxDimSize/128; + if (DimSize < (size_t) 16) + return 16; + else if (DimSize > (size_t) 64) + return 64; + else + return DimSize; +} + +static size_t reduceImageDepth(size_t maxDepth) { + size_t Depth = maxDepth/32; + if (Depth < (size_t) 8) + return 8; + else if (Depth > (size_t) 32) + return 32; + else + return Depth; +} + +const char *read2DArrayKernelSourcePattern = +"__kernel void sample_kernel( read_only %s input,%s __global float *xOffsets, __global float *yOffsets, __global float *zOffsets, __global %s%s *results %s )\n" +"{\n" +"%s" +" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n" +"%s" +"%s" +" results[offset] = read_image%s( input, imageSampler, coords %s);\n" +"}"; + +const char *read_write2DArrayKernelSourcePattern = +"__kernel void sample_kernel( read_write %s input,%s __global float *xOffsets, __global float *yOffsets, __global float *zOffsets, __global %s%s *results %s)\n" +"{\n" +"%s" +" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n" +"%s" +"%s" +" results[offset] = read_image%s( input, coords %s);\n" +"}"; + +const char* offset2DarraySource =" int offset = tidZ*get_image_width(input)*get_image_height(input) + tidY*get_image_width(input) + tidX;\n"; +const char* offset2DarraySourceLod = + " int lod_int = (int)lod;\n" + " int width_lod, height_lod;\n" + " width_lod = (get_image_width(input) >> lod_int ) ? (get_image_width(input) >> lod_int ) : 1;\n" + " height_lod = (get_image_height(input) >> lod_int ) ? (get_image_height(input) >> lod_int ) : 1;\n" + " int offset = tidZ*width_lod*height_lod + tidY*width_lod + tidX;\n"; + +const char *int2DArrayCoordKernelSource = +" int4 coords = (int4)( (int) xOffsets[offset], (int) yOffsets[offset], (int) zOffsets[offset], 0 );\n"; + +const char *float2DArrayUnnormalizedCoordKernelSource = +" float4 coords = (float4)( xOffsets[offset], yOffsets[offset], zOffsets[offset], 0.0f );\n"; + + +static const char *samplerKernelArg = " sampler_t imageSampler,"; + +#define ABS_ERROR( result, expected ) ( fabsf( (float)expected - (float)result ) ) + +extern void read_image_pixel_float( void *imageData, image_descriptor *imageInfo, int x, int y, int z, float *outData ); +template int determine_validation_error_offset_2D_array( void *imagePtr, image_descriptor *imageInfo, image_sampler_data *imageSampler, + T *resultPtr, T * expected, float error, + float x, float y, float z, float xAddressOffset, float yAddressOffset, float zAddressOffset, size_t j, int &numTries, int &numClamped, bool printAsFloat, int lod ) +{ + int actualX, actualY, actualZ; + int found = debug_find_pixel_in_image( imagePtr, imageInfo, resultPtr, &actualX, &actualY, &actualZ, lod ); + bool clampingErr = false, clamped = false, otherClampingBug = false; + int clampedX, clampedY, clampedZ; + + size_t imageWidth = imageInfo->width, imageHeight = imageInfo->height, imageDepth = imageInfo->arraySize; + + clamped = get_integer_coords_offset( x, y, z, xAddressOffset, yAddressOffset, zAddressOffset, imageWidth, imageHeight, imageDepth, imageSampler, imageInfo, clampedX, clampedY, clampedZ ); + + if( found ) + { + // Is it a clamping bug? + if( clamped && clampedX == actualX && clampedY == actualY && clampedZ == actualZ ) + { + if( (--numClamped) == 0 ) + { + log_error( "\nERROR: TEST FAILED! Read is erroneously clamping coordinates!\n" ); + if( printAsFloat ) + { + log_error( "Sample %ld: coord {%f(%a),%f(%a),%f(%a)} did not validate!\n" + " Expected (%g,%g,%g,%g)\n" + " Observed (%g,%g,%g,%g)\n" + " error of %g\n", + j, x, x, y, y, z, z, (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ], + (float)resultPtr[ 0 ], (float)resultPtr[ 1 ], (float)resultPtr[ 2 ], (float)resultPtr[ 3 ], error ); + } + else + { + log_error( "Sample %ld: coord {%f(%a),%f(%a),%f(%a)} did not validate!\n" + " Expected (%x,%x,%x,%x)\n" + " Observed (%x,%x,%x,%x)\n", + j, x, x, y, y, z, z, (int)expected[ 0 ], (int)expected[ 1 ], (int)expected[ 2 ], (int)expected[ 3 ], + (int)resultPtr[ 0 ], (int)resultPtr[ 1 ], (int)resultPtr[ 2 ], (int)resultPtr[ 3 ] ); + } + + if( imageSampler->filter_mode != CL_FILTER_LINEAR ) + { + if( found ) + log_error( "\tValue really found in image at %d,%d,%d (%s)\n", actualX, actualY, actualZ, ( found > 1 ) ? "NOT unique!!" : "unique" ); + else + log_error( "\tValue not actually found in image\n" ); + } + log_error( "\n" ); + + return -1; + } + clampingErr = true; + otherClampingBug = true; + } + } + if( clamped && !otherClampingBug ) + { + // If we are in clamp-to-edge mode and we're getting zeroes, it's possible we're getting border erroneously + if( resultPtr[ 0 ] == 0 && resultPtr[ 1 ] == 0 && resultPtr[ 2 ] == 0 && resultPtr[ 3 ] == 0 ) + { + if( (--numClamped) == 0 ) + { + log_error( "\nERROR: TEST FAILED: Clamping is erroneously returning border color!\n" ); + if( printAsFloat ) + { + log_error( "Sample %ld: coord {%f(%a),%f(%a),%f(%a)} did not validate!\n" + " Expected (%g,%g,%g,%g)\n" + " Observed (%g,%g,%g,%g)\n" + " error of %g\n", + j, x, x, y, y, z, z, (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ], + (float)resultPtr[ 0 ], (float)resultPtr[ 1 ], (float)resultPtr[ 2 ], (float)resultPtr[ 3 ], error ); + } + else + { + log_error( "Sample %ld: coord {%f(%a),%f(%a),%f(%a)} did not validate!\n" + " Expected (%x,%x,%x,%x)\n" + " Observed (%x,%x,%x,%x)\n", + j, x, x, y, y, z, z, (int)expected[ 0 ], (int)expected[ 1 ], (int)expected[ 2 ], (int)expected[ 3 ], + (int)resultPtr[ 0 ], (int)resultPtr[ 1 ], (int)resultPtr[ 2 ], (int)resultPtr[ 3 ] ); + } + return -1; + } + clampingErr = true; + } + } + if( !clampingErr ) + { + if( true ) // gExtraValidateInfo ) + { + if( printAsFloat ) + { + log_error( "Sample %ld: coord {%f(%a),%f(%a),%f(%a)} did not validate!\n" + " Expected (%g,%g,%g,%g)\n" + " Observed (%g,%g,%g,%g)\n" + " error of %g\n", + j, x, x, y, y, z, z, (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ], + (float)resultPtr[ 0 ], (float)resultPtr[ 1 ], (float)resultPtr[ 2 ], (float)resultPtr[ 3 ], error ); + } + else + { + log_error( "Sample %ld: coord {%f(%a),%f(%a),%f(%a)} did not validate!\n" + " Expected (%x,%x,%x,%x)\n" + " Observed (%x,%x,%x,%x)\n", + j, x, x, y, y, z, z, (int)expected[ 0 ], (int)expected[ 1 ], (int)expected[ 2 ], (int)expected[ 3 ], + (int)resultPtr[ 0 ], (int)resultPtr[ 1 ], (int)resultPtr[ 2 ], (int)resultPtr[ 3 ] ); + } + log_error( "Integer coords resolve to %d,%d,%d, image size = %d,%d,%d\n", clampedX, clampedY, clampedZ, (int)imageWidth, (int)imageHeight, (int)imageDepth ); + + if( printAsFloat && gExtraValidateInfo ) + { + log_error( "\nNearby values:\n" ); + for( int zOff = -1; zOff <= 1; zOff++ ) + { + for( int yOff = -1; yOff <= 1; yOff++ ) + { + float top[ 4 ], real[ 4 ], bot[ 4 ]; + read_image_pixel_float( imagePtr, imageInfo, clampedX - 1 , clampedY + yOff, clampedZ + zOff, top ); + read_image_pixel_float( imagePtr, imageInfo, clampedX ,clampedY + yOff, clampedZ + zOff, real ); + read_image_pixel_float( imagePtr, imageInfo, clampedX + 1, clampedY + yOff, clampedZ + zOff, bot ); + log_error( "\t(%g,%g,%g,%g)",top[0], top[1], top[2], top[3] ); + log_error( " (%g,%g,%g,%g)", real[0], real[1], real[2], real[3] ); + log_error( " (%g,%g,%g,%g)\n",bot[0], bot[1], bot[2], bot[3] ); + } + } + } + if( imageSampler->filter_mode != CL_FILTER_LINEAR ) + { + if( found ) + log_error( "Value really found in image at %d,%d,%d (%s)\n", actualX, actualY, actualZ, ( found > 1 ) ? "NOT unique!!" : "unique" ); + else + log_error( "Value not actually found in image\n" ); + } + log_error( "\n" ); + } + + numClamped = -1; // We force the clamped counter to never work + if( ( --numTries ) == 0 ) + return -1; + } + return 0; +} + +#define CLAMP( _val, _min, _max ) ((_val) < (_min) ? (_min) : (_val) > (_max) ? (_max) : (_val)) + +static void InitFloatCoords( image_descriptor *imageInfo, image_sampler_data *imageSampler, float *xOffsets, float *yOffsets, float *zOffsets, float xfract, float yfract, float zfract, int normalized_coords, MTdata d , int lod) +{ + size_t i = 0; + size_t width_lod = imageInfo->width; + size_t height_lod = imageInfo->height; + if(gTestMipmaps) + { + width_lod = ( imageInfo->width >> lod) ?( imageInfo->width >> lod) : 1; + height_lod = ( imageInfo->height >> lod) ?( imageInfo->height >> lod) : 1; + + } + if( gDisableOffsets ) + { + for( size_t z = 0; z < imageInfo->arraySize; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) (xfract + (double) x); + yOffsets[ i ] = (float) (yfract + (double) y); + zOffsets[ i ] = (float) (zfract + (double) z); + } + } + } + } + else + { + for( size_t z = 0; z < imageInfo->arraySize; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) (xfract + (double) ((int) x + random_in_range( -10, 10, d ))); + yOffsets[ i ] = (float) (yfract + (double) ((int) y + random_in_range( -10, 10, d ))); + zOffsets[ i ] = (float) (zfract + (double) ((int) z + random_in_range( -10, 10, d ))); + } + } + } + } + + if( imageSampler->addressing_mode == CL_ADDRESS_NONE ) + { + i = 0; + for( size_t z = 0; z < imageInfo->arraySize; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) CLAMP( (double) xOffsets[ i ], 0.0, (double) width_lod - 1.0); + yOffsets[ i ] = (float) CLAMP( (double) yOffsets[ i ], 0.0, (double) height_lod - 1.0); + zOffsets[ i ] = (float) CLAMP( (double) zOffsets[ i ], 0.0, (double) imageInfo->arraySize - 1.0); + } + } + } + } + + if( normalized_coords ) + { + i = 0; + for( size_t z = 0; z < imageInfo->arraySize; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) ((double) xOffsets[ i ] / (double) width_lod); + yOffsets[ i ] = (float) ((double) yOffsets[ i ] / (double) height_lod); + } + } + } + } +} + +#ifndef MAX +#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b)) +#endif + +int test_read_image_2D_array( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, image_sampler_data *imageSampler, + bool useFloatCoords, ExplicitType outputType, MTdata d ) +{ + int error; + size_t threads[3]; + static int initHalf = 0; + cl_mem_flags image_read_write_flags = CL_MEM_READ_ONLY; + + clMemWrapper xOffsets, yOffsets, zOffsets, results; + clSamplerWrapper actualSampler; + BufferOwningPtr maxImageUseHostPtrBackingStore; + + // Create offset data + BufferOwningPtr xOffsetValues(malloc(sizeof(cl_float) *imageInfo->width * imageInfo->height * imageInfo->arraySize)); + BufferOwningPtr yOffsetValues(malloc(sizeof(cl_float) *imageInfo->width * imageInfo->height * imageInfo->arraySize)); + BufferOwningPtr zOffsetValues(malloc(sizeof(cl_float) *imageInfo->width * imageInfo->height * imageInfo->arraySize)); + + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + // Construct testing sources + clProtectedImage protImage; + clMemWrapper unprotImage; + cl_mem image; + + if(gtestTypesToRun & kReadTests) + { + image_read_write_flags = CL_MEM_READ_ONLY; + } + else + { + image_read_write_flags = CL_MEM_READ_WRITE; + } + + if( gMemFlagsToUse == CL_MEM_USE_HOST_PTR ) + { + // clProtectedImage uses USE_HOST_PTR, so just rely on that for the testing (via Ian) + // Do not use protected images for max image size test since it rounds the row size to a page size + if (gTestMaxImages) { + generate_random_image_data( imageInfo, maxImageUseHostPtrBackingStore, d ); + unprotImage = create_image_2d_array( context, + image_read_write_flags | CL_MEM_USE_HOST_PTR, + imageInfo->format, + imageInfo->width, imageInfo->height, + imageInfo->arraySize, + ( gEnablePitch ? imageInfo->rowPitch : 0 ), + ( gEnablePitch ? imageInfo->slicePitch : 0 ), + maxImageUseHostPtrBackingStore, &error ); + } else { + error = protImage.Create( context, CL_MEM_OBJECT_IMAGE2D_ARRAY, + image_read_write_flags, + imageInfo->format, imageInfo->width, imageInfo->height, 1, imageInfo->arraySize ); + } + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 2D image array of size %d x %d x %d (pitch %d, %d ) (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + if (gTestMaxImages) + image = (cl_mem)unprotImage; + else + image = (cl_mem)protImage; + } + else if( gMemFlagsToUse == CL_MEM_COPY_HOST_PTR ) + { + // Don't use clEnqueueWriteImage; just use copy host ptr to get the data in + unprotImage = create_image_2d_array( context, + image_read_write_flags | CL_MEM_COPY_HOST_PTR, + imageInfo->format, + imageInfo->width, + imageInfo->height, + imageInfo->arraySize, + ( gEnablePitch ? imageInfo->rowPitch : 0 ), + ( gEnablePitch ? imageInfo->slicePitch : 0 ), + imageValues, &error ); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 2D image array of size %d x %d x %d (pitch %d, %d ) (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + image = unprotImage; + } + else // Either CL_MEM_ALLOC_HOST_PTR or none + { + if ( gTestMipmaps ) + { + cl_image_desc image_desc = {0}; + image_desc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + image_desc.image_width = imageInfo->width; + image_desc.image_height = imageInfo->height; + image_desc.image_array_size = imageInfo->arraySize; + //image_desc.image_rowPitch = imageInfo->rowPitch; + //image_desc.image_slicePitch = imageInfo->slicePitch; + image_desc.num_mip_levels = imageInfo->num_mip_levels; + + unprotImage = clCreateImage( context, + image_read_write_flags, + imageInfo->format, &image_desc, NULL, &error); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create %d level mipmapped 2D image array of size %d x %d x %d (pitch %d, %d ) (%s)", (int)imageInfo->num_mip_levels, (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + } + else + { + // Note: if ALLOC_HOST_PTR is used, the driver allocates memory that can be accessed by the host, but otherwise + // it works just as if no flag is specified, so we just do the same thing either way + unprotImage = create_image_2d_array( context, + image_read_write_flags | gMemFlagsToUse, + imageInfo->format, + imageInfo->width, imageInfo->height, imageInfo->arraySize, + ( gEnablePitch ? imageInfo->rowPitch : 0 ), + ( gEnablePitch ? imageInfo->slicePitch : 0 ), + imageValues, &error ); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 2D image array of size %d x %d x %d (pitch %d, %d ) (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + } + image = unprotImage; + } + + if( gMemFlagsToUse != CL_MEM_COPY_HOST_PTR ) + { + if( gDebugTrace ) + log_info( " - Writing image...\n" ); + + size_t origin[ 4 ] = { 0, 0, 0, 0 }; + size_t region[ 3 ] = { imageInfo->width, imageInfo->height, imageInfo->arraySize }; + size_t tmpNextLevelOffset = 0; + + if( gTestMipmaps ) + { + for(int level = 0; level < imageInfo->num_mip_levels; level++) + { + origin[3] = level; + error = clEnqueueWriteImage(queue, image, CL_TRUE, + origin, region, /*gEnablePitch ? imageInfo->rowPitch :*/ 0, /*gEnablePitch ? imageInfo->slicePitch :*/ 0, + imageValues + tmpNextLevelOffset, 0, NULL, NULL); + if (error != CL_SUCCESS) + { + log_error( "ERROR: Unable to write to level %d of 2D image array of size %d x %d x %d\n", (int)imageInfo->num_mip_levels, (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize ); + return error; + } + + tmpNextLevelOffset += region[0]*region[1]*region[2]*get_pixel_size(imageInfo->format); + region[0] = ( region[0] >> 1 ) ? ( region[0] >> 1 ) : 1; + region[1] = ( region[1] >> 1 ) ? ( region[1] >> 1 ) : 1; + } + } + else + { + error = clEnqueueWriteImage(queue, image, CL_TRUE, + origin, region, gEnablePitch ? imageInfo->rowPitch : 0, gEnablePitch ? imageInfo->slicePitch : 0, + imageValues, 0, NULL, NULL); + if (error != CL_SUCCESS) + { + log_error( "ERROR: Unable to write to 2D image array of size %d x %d x %d\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize ); + return error; + } + } + } + + xOffsets = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), sizeof( cl_float ) * imageInfo->width * imageInfo->height * imageInfo->arraySize, xOffsetValues, &error ); + test_error( error, "Unable to create x offset buffer" ); + yOffsets = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), sizeof( cl_float ) * imageInfo->width * imageInfo->height * imageInfo->arraySize, yOffsetValues, &error ); + test_error( error, "Unable to create y offset buffer" ); + zOffsets = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), sizeof( cl_float ) * imageInfo->width * imageInfo->height * imageInfo->arraySize, zOffsetValues, &error ); + test_error( error, "Unable to create y offset buffer" ); + results = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), get_explicit_type_size( outputType ) * 4 * imageInfo->width * imageInfo->height * imageInfo->arraySize, NULL, &error ); + test_error( error, "Unable to create result buffer" ); + + // Create sampler to use + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, imageSampler->normalized_coords, + CL_SAMPLER_ADDRESSING_MODE, imageSampler->addressing_mode, + CL_SAMPLER_FILTER_MODE, imageSampler->filter_mode, + 0, 0, 0 }; + if (gTestMipmaps) { + properties[6] = CL_SAMPLER_MIP_FILTER_MODE; + properties[7] = imageSampler->filter_mode; + } + actualSampler = clCreateSamplerWithProperties(context, properties, &error ); + test_error( error, "Unable to create image sampler" ); + + // Set arguments + int idx = 0; + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &image ); + test_error( error, "Unable to set kernel arguments" ); + if( !gUseKernelSamplers ) + { + error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler ); + test_error( error, "Unable to set kernel arguments" ); + } + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &xOffsets ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &yOffsets ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &zOffsets ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results ); + test_error( error, "Unable to set kernel arguments" ); + + const float float_offsets[] = { 0.0f, MAKE_HEX_FLOAT(0x1.0p-30f, 0x1L, -30), 0.25f, 0.3f, 0.5f - FLT_EPSILON/4.0f, 0.5f, 0.9f, 1.0f - FLT_EPSILON/2 }; + int float_offset_count = sizeof( float_offsets) / sizeof( float_offsets[0] ); + int numTries = MAX_TRIES, numClamped = MAX_CLAMPED; + int loopCount = 2 * float_offset_count; + if( ! useFloatCoords ) + loopCount = 1; + if (gTestMaxImages) { + loopCount = 1; + log_info("Testing each size only once with pixel offsets of %g for max sized images.\n", float_offsets[0]); + } + + // Get the maximum absolute error for this format + double formatAbsoluteError = get_max_absolute_error(imageInfo->format, imageSampler); + if (gDebugTrace) log_info("\tformatAbsoluteError is %e\n", formatAbsoluteError); + + if (0 == initHalf && imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) { + initHalf = CL_SUCCESS == DetectFloatToHalfRoundingMode( queue ); + if (initHalf) { + log_info("Half rounding mode successfully detected.\n"); + } + } + size_t nextLevelOffset = 0; + size_t width_lod = imageInfo->width, height_lod = imageInfo->height; + for( size_t lod = 0; (gTestMipmaps && (lod < imageInfo->num_mip_levels))|| (!gTestMipmaps && lod < 1); lod ++) + { + size_t resultValuesSize = width_lod * height_lod * imageInfo->arraySize * get_explicit_type_size( outputType ) * 4; + BufferOwningPtr resultValues(malloc( resultValuesSize )); + float lod_float = (float)lod; + if( gTestMipmaps ) + { + if(gDebugTrace) + log_info(" - Working at mip level %d\n", lod); + error = clSetKernelArg( kernel, idx, sizeof(float), &lod_float); + } + for( int q = 0; q < loopCount; q++ ) + { + float offset = float_offsets[ q % float_offset_count ]; + + // Init the coordinates + InitFloatCoords( imageInfo, imageSampler, xOffsetValues, yOffsetValues, zOffsetValues, + q>=float_offset_count ? -offset: offset, + q>=float_offset_count ? offset: -offset, + q>=float_offset_count ? -offset: offset, + imageSampler->normalized_coords, d, lod ); + + error = clEnqueueWriteBuffer( queue, xOffsets, CL_TRUE, 0, sizeof(cl_float) * imageInfo->height * imageInfo->width * imageInfo->arraySize, xOffsetValues, 0, NULL, NULL ); + test_error( error, "Unable to write x offsets" ); + error = clEnqueueWriteBuffer( queue, yOffsets, CL_TRUE, 0, sizeof(cl_float) * imageInfo->height * imageInfo->width * imageInfo->arraySize, yOffsetValues, 0, NULL, NULL ); + test_error( error, "Unable to write y offsets" ); + error = clEnqueueWriteBuffer( queue, zOffsets, CL_TRUE, 0, sizeof(cl_float) * imageInfo->height * imageInfo->width * imageInfo->arraySize, zOffsetValues, 0, NULL, NULL ); + test_error( error, "Unable to write z offsets" ); + + + memset( resultValues, 0xff, resultValuesSize ); + clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + + // Figure out thread dimensions + threads[0] = (size_t)width_lod; + threads[1] = (size_t)height_lod; + threads[2] = (size_t)imageInfo->arraySize; + + // Run the kernel + error = clEnqueueNDRangeKernel( queue, kernel, 3, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + // Get results + error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, width_lod * height_lod * imageInfo->arraySize * get_explicit_type_size( outputType ) * 4, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + if( gDebugTrace ) + log_info( " results read\n" ); + + // Validate results element by element + char *imagePtr = (char *)imageValues + nextLevelOffset; + + if((imageInfo->format->image_channel_order == CL_DEPTH) && (outputType == kFloat) ) + { + // Validate float results + float *resultPtr = (float *)(char *)resultValues; + float expected[4], error=0.0f; + float maxErr = get_max_relative_error( imageInfo->format, imageSampler, 1 /*3D*/, CL_FILTER_LINEAR == imageSampler->filter_mode ); + + for( size_t z = 0, j = 0; z < imageInfo->arraySize; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X, Y and Z to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + float offset = NORM_OFFSET; + if (!imageSampler->normalized_coords || imageSampler->filter_mode != CL_FILTER_NEAREST || NORM_OFFSET == 0 +#if defined( __APPLE__ ) + // Apple requires its CPU implementation to do correctly rounded address arithmetic in all modes + || gDeviceType != CL_DEVICE_TYPE_GPU +#endif + ) + offset = 0.0f; // Loop only once + + for (float norm_offset_x = -offset; norm_offset_x <= offset && !found_pixel ; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !found_pixel ; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -offset; norm_offset_z <= NORM_OFFSET && !found_pixel; norm_offset_z += NORM_OFFSET) { + + int hasDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0, &hasDenormals, lod ); + + float err1 = fabsf( resultPtr[0] - expected[0] ); + // Clamp to the minimum absolute error for the format + if (err1 > 0 && err1 < formatAbsoluteError) { err1 = 0.0f; } + float maxErr1 = MAX( maxErr * maxPixel.p[0], FLT_MIN ); + + if( ! (err1 <= maxErr1) ) + { + // Try flushing the denormals + if( hasDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr1 += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( resultPtr[0] - expected[0] ); + } + } + + found_pixel = (err1 <= maxErr1); + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -offset; norm_offset_x <= offset && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -offset; norm_offset_z <= offset && !checkOnlyOnePixel; norm_offset_z += NORM_OFFSET) { + + int hasDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0, &hasDenormals, lod ); + + float err1 = fabsf( resultPtr[0] - expected[0] ); + float maxErr1 = MAX( maxErr * maxPixel.p[0], FLT_MIN ); + + + if( ! (err1 <= maxErr1) ) + { + // Try flushing the denormals + if( hasDenormals ) + { + maxErr1 += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( resultPtr[0] - expected[0] ); + } + } + + if( ! (err1 <= maxErr1) ) + { + log_error("FAILED norm_offsets: %g , %g , %g:\n", norm_offset_x, norm_offset_y, norm_offset_z); + + float tempOut[4]; + shouldReturn |= determine_validation_error_offset_2D_array( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[j], yOffsetValues[j], zOffsetValues[j], + norm_offset_x, norm_offset_y, norm_offset_z, j, + numTries, numClamped, true, lod ); + log_error( "Step by step:\n" ); + FloatPixel temp = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, tempOut, 1 /*verbose*/, &hasDenormals, lod); + log_error( "\tulps: %2.2f (max allowed: %2.2f)\n\n", + Ulp_Error( resultPtr[0], expected[0] ), + Ulp_Error( MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) + maxErr, MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) ) ); + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 1; + } + } + } + } + /* + * FLOAT output type, order=CL_sRGBA, CL_sRGB, CL_sRGBx, CL_BGRA + */ + else if(is_sRGBA_order(imageInfo->format->image_channel_order) && (outputType == kFloat) ) + { + // Validate float results + float *resultPtr = (float *)(char *)resultValues; + float expected[4], error=0.0f; + float maxErr = get_max_relative_error( imageInfo->format, imageSampler, 1 /*3D*/, CL_FILTER_LINEAR == imageSampler->filter_mode ); + + for( size_t z = 0, j = 0; z < imageInfo->arraySize; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X, Y and Z to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + float offset = NORM_OFFSET; + if (!imageSampler->normalized_coords || imageSampler->filter_mode != CL_FILTER_NEAREST || NORM_OFFSET == 0 +#if defined( __APPLE__ ) + // Apple requires its CPU implementation to do correctly rounded address arithmetic in all modes + || gDeviceType != CL_DEVICE_TYPE_GPU +#endif + ) + offset = 0.0f; // Loop only once + + for (float norm_offset_x = -offset; norm_offset_x <= offset && !found_pixel ; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !found_pixel ; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -offset; norm_offset_z <= NORM_OFFSET && !found_pixel; norm_offset_z += NORM_OFFSET) { + + int hasDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0, &hasDenormals, lod ); + + float err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + float err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + float err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + float maxErr = 0.5; + + if( ! (err1 <= maxErr) || ! (err2 <= maxErr) || ! (err3 <= maxErr) || ! (err4 <= maxErr) ) + { + // Try flushing the denormals + if( hasDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + + found_pixel = (err1 <= maxErr) && (err2 <= maxErr) && (err3 <= maxErr) && (err4 <= maxErr); + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -offset; norm_offset_x <= offset && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -offset; norm_offset_z <= offset && !checkOnlyOnePixel; norm_offset_z += NORM_OFFSET) { + + int hasDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0, &hasDenormals, lod ); + + float err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + float err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + float err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + float maxErr = 0.6; + + if( ! (err1 <= maxErr) || ! (err2 <= maxErr) || ! (err3 <= maxErr) || ! (err4 <= maxErr) ) + { + // Try flushing the denormals + if( hasDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + + if( ! (err1 <= maxErr) || ! (err2 <= maxErr) || ! (err3 <= maxErr) || ! (err4 <= maxErr) ) + { + log_error("FAILED norm_offsets: %g , %g , %g:\n", norm_offset_x, norm_offset_y, norm_offset_z); + + float tempOut[4]; + shouldReturn |= determine_validation_error_offset_2D_array( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[j], yOffsetValues[j], zOffsetValues[j], + norm_offset_x, norm_offset_y, norm_offset_z, j, + numTries, numClamped, true, lod ); + log_error( "Step by step:\n" ); + FloatPixel temp = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, tempOut, 1 /*verbose*/, &hasDenormals, lod); + log_error( "\tulps: %2.2f, %2.2f, %2.2f, %2.2f (max allowed: %2.2f)\n\n", + Ulp_Error( resultPtr[0], expected[0] ), + Ulp_Error( resultPtr[1], expected[1] ), + Ulp_Error( resultPtr[2], expected[2] ), + Ulp_Error( resultPtr[3], expected[3] ), + Ulp_Error( MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) + maxErr, MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) ) ); + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + } + /* + * FLOAT output type + */ + else if( outputType == kFloat ) + { + // Validate float results + float *resultPtr = (float *)(char *)resultValues; + float expected[4], error=0.0f; + float maxErr = get_max_relative_error( imageInfo->format, imageSampler, 1 /*3D*/, CL_FILTER_LINEAR == imageSampler->filter_mode ); + + for( size_t z = 0, j = 0; z < imageInfo->arraySize; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X, Y and Z to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + float offset = NORM_OFFSET; + if (!imageSampler->normalized_coords || imageSampler->filter_mode != CL_FILTER_NEAREST || NORM_OFFSET == 0 +#if defined( __APPLE__ ) + // Apple requires its CPU implementation to do correctly rounded address arithmetic in all modes + || gDeviceType != CL_DEVICE_TYPE_GPU +#endif + ) + offset = 0.0f; // Loop only once + + for (float norm_offset_x = -offset; norm_offset_x <= offset && !found_pixel ; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !found_pixel ; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -offset; norm_offset_z <= NORM_OFFSET && !found_pixel; norm_offset_z += NORM_OFFSET) { + + int hasDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0, &hasDenormals, lod ); + + float err1 = fabsf( resultPtr[0] - expected[0] ); + float err2 = fabsf( resultPtr[1] - expected[1] ); + float err3 = fabsf( resultPtr[2] - expected[2] ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + // Clamp to the minimum absolute error for the format + if (err1 > 0 && err1 < formatAbsoluteError) { err1 = 0.0f; } + if (err2 > 0 && err2 < formatAbsoluteError) { err2 = 0.0f; } + if (err3 > 0 && err3 < formatAbsoluteError) { err3 = 0.0f; } + if (err4 > 0 && err4 < formatAbsoluteError) { err4 = 0.0f; } + float maxErr1 = MAX( maxErr * maxPixel.p[0], FLT_MIN ); + float maxErr2 = MAX( maxErr * maxPixel.p[1], FLT_MIN ); + float maxErr3 = MAX( maxErr * maxPixel.p[2], FLT_MIN ); + float maxErr4 = MAX( maxErr * maxPixel.p[3], FLT_MIN ); + + if( ! (err1 <= maxErr1) || ! (err2 <= maxErr2) || ! (err3 <= maxErr3) || ! (err4 <= maxErr4) ) + { + // Try flushing the denormals + if( hasDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr1 += 4 * FLT_MIN; + maxErr2 += 4 * FLT_MIN; + maxErr3 += 4 * FLT_MIN; + maxErr4 += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( resultPtr[0] - expected[0] ); + err2 = fabsf( resultPtr[1] - expected[1] ); + err3 = fabsf( resultPtr[2] - expected[2] ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + + found_pixel = (err1 <= maxErr1) && (err2 <= maxErr2) && (err3 <= maxErr3) && (err4 <= maxErr4); + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -offset; norm_offset_x <= offset && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -offset; norm_offset_z <= offset && !checkOnlyOnePixel; norm_offset_z += NORM_OFFSET) { + + int hasDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0, &hasDenormals, lod ); + + float err1 = fabsf( resultPtr[0] - expected[0] ); + float err2 = fabsf( resultPtr[1] - expected[1] ); + float err3 = fabsf( resultPtr[2] - expected[2] ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + float maxErr1 = MAX( maxErr * maxPixel.p[0], FLT_MIN ); + float maxErr2 = MAX( maxErr * maxPixel.p[1], FLT_MIN ); + float maxErr3 = MAX( maxErr * maxPixel.p[2], FLT_MIN ); + float maxErr4 = MAX( maxErr * maxPixel.p[3], FLT_MIN ); + + + if( ! (err1 <= maxErr1) || ! (err2 <= maxErr2) || ! (err3 <= maxErr3) || ! (err4 <= maxErr4) ) + { + // Try flushing the denormals + if( hasDenormals ) + { + maxErr1 += 4 * FLT_MIN; + maxErr2 += 4 * FLT_MIN; + maxErr3 += 4 * FLT_MIN; + maxErr4 += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( resultPtr[0] - expected[0] ); + err2 = fabsf( resultPtr[1] - expected[1] ); + err3 = fabsf( resultPtr[2] - expected[2] ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + + if( ! (err1 <= maxErr1) || ! (err2 <= maxErr2) || ! (err3 <= maxErr3) || ! (err4 <= maxErr4) ) + { + log_error("FAILED norm_offsets: %g , %g , %g:\n", norm_offset_x, norm_offset_y, norm_offset_z); + + float tempOut[4]; + shouldReturn |= determine_validation_error_offset_2D_array( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[j], yOffsetValues[j], zOffsetValues[j], + norm_offset_x, norm_offset_y, norm_offset_z, j, + numTries, numClamped, true, lod ); + log_error( "Step by step:\n" ); + FloatPixel temp = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, tempOut, 1 /*verbose*/, &hasDenormals, lod); + log_error( "\tulps: %2.2f, %2.2f, %2.2f, %2.2f (max allowed: %2.2f)\n\n", + Ulp_Error( resultPtr[0], expected[0] ), + Ulp_Error( resultPtr[1], expected[1] ), + Ulp_Error( resultPtr[2], expected[2] ), + Ulp_Error( resultPtr[3], expected[3] ), + Ulp_Error( MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) + maxErr, MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) ) ); + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + } + /* + * UINT output type + */ + else if( outputType == kUInt ) + { + // Validate unsigned integer results + unsigned int *resultPtr = (unsigned int *)(char *)resultValues; + unsigned int expected[4]; + float error; + for( size_t z = 0, j = 0; z < imageInfo->arraySize; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X, Y and Z to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -NORM_OFFSET; norm_offset_z <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_z += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + norm_offset_z = 0.0f; + checkOnlyOnePixel = 1; + } + + if(gTestMipmaps) + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, lod ); + else + sample_image_pixel_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected ); + + error = errMax( errMax( abs_diff_uint(expected[ 0 ], resultPtr[ 0 ]), abs_diff_uint(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_uint(expected[ 2 ], resultPtr[ 2 ]), abs_diff_uint(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if (error < MAX_ERR) + found_pixel = 1; + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -NORM_OFFSET; norm_offset_z <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_z += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + norm_offset_z = 0.0f; + checkOnlyOnePixel = 1; + } + + if(gTestMipmaps) + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, lod ); + else + sample_image_pixel_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected ); + + error = errMax( errMax( abs_diff_uint(expected[ 0 ], resultPtr[ 0 ]), abs_diff_uint(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_uint(expected[ 2 ], resultPtr[ 2 ]), abs_diff_uint(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if( error > MAX_ERR ) + { + log_error("FAILED norm_offsets: %g , %g , %g:\n", norm_offset_x, norm_offset_y, norm_offset_z); + shouldReturn |= determine_validation_error_offset_2D_array( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[j], yOffsetValues[j], zOffsetValues[j], + norm_offset_x, norm_offset_y, norm_offset_z, + j, numTries, numClamped, false, lod ); + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + } + else + /* + * INT output type + */ + { + // Validate integer results + int *resultPtr = (int *)(char *)resultValues; + int expected[4]; + float error; + for( size_t z = 0, j = 0; z < imageInfo->arraySize; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X, Y and Z to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -NORM_OFFSET; norm_offset_z <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_z += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + norm_offset_z = 0.0f; + checkOnlyOnePixel = 1; + } + + if(gTestMipmaps) + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, lod ); + else + sample_image_pixel_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected ); + + error = errMax( errMax( abs_diff_int(expected[ 0 ], resultPtr[ 0 ]), abs_diff_int(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_int(expected[ 2 ], resultPtr[ 2 ]), abs_diff_int(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if (error < MAX_ERR) + found_pixel = 1; + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -NORM_OFFSET; norm_offset_z <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_z += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0 || NORM_OFFSET == 0 || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + norm_offset_z = 0.0f; + checkOnlyOnePixel = 1; + } + + if(gTestMipmaps) + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, lod ); + else + sample_image_pixel_offset( imageValues, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0 ); + + error = errMax( errMax( abs_diff_int(expected[ 0 ], resultPtr[ 0 ]), abs_diff_int(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_int(expected[ 2 ], resultPtr[ 2 ]), abs_diff_int(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if( error > MAX_ERR ) + { + log_error("FAILED norm_offsets: %g , %g , %g:\n", norm_offset_x, norm_offset_y, norm_offset_z); + shouldReturn |= determine_validation_error_offset_2D_array( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[j], yOffsetValues[j], zOffsetValues[j], + norm_offset_x, norm_offset_y, norm_offset_z, + j, numTries, numClamped, false, lod ); + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + } + } + { + nextLevelOffset += width_lod * height_lod * imageInfo->arraySize * get_pixel_size(imageInfo->format); + width_lod = ( width_lod >> 1 ) ? ( width_lod >> 1 ) : 1; + height_lod = ( height_lod >> 1 ) ? ( height_lod >> 1 ) : 1; + } + } + + return numTries != MAX_TRIES || numClamped != MAX_CLAMPED; +} + +int test_read_image_set_2D_array( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, + bool floatCoords, ExplicitType outputType ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + RandomSeed seed( gRandomSeed ); + + const char *KernelSourcePattern = NULL; + + int error; + + clProgramWrapper program; + clKernelWrapper kernel; + + // Get operating parameters + size_t maxWidth, maxHeight, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0x0 }; + size_t pixelSize; + + imageInfo.format = format; + imageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + pixelSize = get_pixel_size( imageInfo.format ); + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 3D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // Determine types + if( outputType == kInt ) + readFormat = "i"; + else if( outputType == kUInt ) + readFormat = "ui"; + else // kFloat + readFormat = "f"; + + // Construct the source + const char *samplerArg = samplerKernelArg; + char samplerVar[ 1024 ] = ""; + if( gUseKernelSamplers ) + { + get_sampler_kernel_code( imageSampler, samplerVar ); + samplerArg = ""; + } + + const char *imageType; + const char *imageElement; + if (format->image_channel_order == CL_DEPTH) + { + imageType = "image2d_array_depth_t"; + imageElement = ""; + } + else + { + imageType = "image2d_array_t"; + imageElement = "4"; + } + + // Construct the source + if(gtestTypesToRun & kReadTests) + { + KernelSourcePattern = read2DArrayKernelSourcePattern; + } + else + { + KernelSourcePattern = read_write2DArrayKernelSourcePattern; + } + + // Construct the source + sprintf( programSrc, + KernelSourcePattern, + imageType, + samplerArg, get_explicit_type_name( outputType ), + imageElement, + gTestMipmaps ? ", float lod" : " ", + samplerVar, + gTestMipmaps ? offset2DarraySourceLod : offset2DarraySource, + floatCoords ? float2DArrayUnnormalizedCoordKernelSource : int2DArrayCoordKernelSource, + readFormat, + gTestMipmaps ? ", lod" : " " ); + + ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create testing kernel" ); + + // Run tests + + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ ) + { + if( gTestMipmaps ) + imageInfo.num_mip_levels = (size_t) random_in_range(2, compute_max_mip_levels(imageInfo.width, imageInfo.height, 0)-1, seed); + + if( gDebugTrace ) + log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize ); + int retCode = test_read_image_2D_array( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D_ARRAY, imageInfo.format, CL_TRUE); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.arraySize = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + if( gTestMipmaps ) + imageInfo.num_mip_levels = (size_t) random_in_range(2, compute_max_mip_levels(imageInfo.width, imageInfo.height, 0)-1, seed); + cl_ulong size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + while( size > maxAllocSize || ( size * 3 ) > memSize ) + { + if(imageInfo.arraySize == 1) + { + // ArraySize cannot be 0. + break; + } + imageInfo.arraySize--; + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4; + } + + while( size > maxAllocSize || ( size * 3 ) > memSize ) + { + imageInfo.height--; + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4; + } + log_info("Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ]); + if( gDebugTrace ) + log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + int retCode = test_read_image_2D_array( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + } + else if( gTestRounding ) + { + size_t typeRange = 1 << ( get_format_type_size( imageInfo.format ) * 8 ); + imageInfo.height = typeRange / 256; + imageInfo.width = (size_t)( typeRange / (cl_ulong)imageInfo.height ); + imageInfo.arraySize = 2; + + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + int retCode = test_read_image_2D_array( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + else + { + int maxWidthRange = (int) reduceImageSizeRange(maxWidth); + int maxHeighthRange = (int) reduceImageSizeRange(maxHeight); + int maxArraySizeRange = (int) reduceImageDepth(maxArraySize); + + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, maxWidthRange, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, maxHeighthRange, seed ); + imageInfo.arraySize = (size_t)random_log_in_range( 8, maxArraySizeRange, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + + if( gTestMipmaps ) + { + imageInfo.num_mip_levels = random_in_range(2,compute_max_mip_levels(imageInfo.width, imageInfo.height, 0) - 1, seed); + //Need to take into account the output buffer size, otherwise we will end up with input buffer that is exceeding MaxAlloc + size = (cl_ulong) 4*compute_mipmapped_image_size( imageInfo ) * get_explicit_type_size( outputType ); + } + else + { + if( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth * pixelSize; + + size_t extraHeight = (int)random_log_in_range( 0, 64, seed ); + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight); + } + + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + { + log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxArraySize ); + if ( gTestMipmaps ) + log_info(" and %d mip levels\n", (int) imageInfo.num_mip_levels); + } + int retCode = test_read_image_2D_array( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + } + + return 0; +} diff --git a/test_conformance/images/kernel_read_write/test_read_3D.cpp b/test_conformance/images/kernel_read_write/test_read_3D.cpp new file mode 100644 index 00000000..7cf2a4f5 --- /dev/null +++ b/test_conformance/images/kernel_read_write/test_read_3D.cpp @@ -0,0 +1,1328 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" +#include + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gExtraValidateInfo, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_device_type gDeviceType; +extern bool gUseKernelSamplers; +extern cl_filter_mode gFilterModeToUse; +extern cl_addressing_mode gAddressModeToUse; +extern cl_mem_flags gMemFlagsToUse; + +extern int gtestTypesToRun; + +#define MAX_TRIES 1 +#define MAX_CLAMPED 1 + +// Utility function to clamp down image sizes for certain tests to avoid +// using too much memory. +static size_t reduceImageSizeRange(size_t maxDimSize, RandomSeed& seed) { + size_t DimSize = random_log_in_range(16, (int) maxDimSize/32, seed); + if (DimSize > (size_t) 128) + return 128; + else + return DimSize; +} + +static size_t reduceImageDepth(size_t maxDimSize, RandomSeed& seed) { + size_t DimSize = random_log_in_range(8, (int) maxDimSize/32, seed); + if (DimSize > (size_t) 32) + return 32; + else + return DimSize; +} + + +const char *read3DKernelSourcePattern = +"__kernel void sample_kernel( read_only image3d_t input,%s __global float *xOffsets, __global float *yOffsets, __global float *zOffsets, __global %s4 *results %s)\n" +"{\n" +"%s" +" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n" +"%s" +"%s" +" results[offset] = read_image%s( input, imageSampler, coords %s);\n" +"}"; + +const char *read_write3DKernelSourcePattern = +"__kernel void sample_kernel( read_write image3d_t input,%s __global float *xOffsets, __global float *yOffsets, __global float *zOffsets, __global %s4 *results %s)\n" +"{\n" +"%s" +" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n" +"%s" +"%s" +" results[offset] = read_image%s( input, coords %s);\n" +"}"; + +const char *offset3DKernelSource = +" int offset = tidZ*get_image_width(input)*get_image_height(input) + tidY*get_image_width(input) + tidX;\n"; + +const char *offset3DLodKernelSource = +" int lod_int = (int)lod;\n" +" int width_lod = (get_image_width(input) >> lod_int) ?(get_image_width(input) >> lod_int): 1;\n" +" int height_lod = (get_image_height(input) >> lod_int) ?(get_image_height(input) >> lod_int): 1;\n" +" int offset = tidZ*width_lod*height_lod + tidY*width_lod + tidX;\n"; + +const char *int3DCoordKernelSource = +" int4 coords = (int4)( (int) xOffsets[offset], (int) yOffsets[offset], (int) zOffsets[offset], 0 );\n"; + +const char *float3DUnnormalizedCoordKernelSource = +" float4 coords = (float4)( xOffsets[offset], yOffsets[offset], zOffsets[offset], 0.0f );\n"; + + +static const char *samplerKernelArg = " sampler_t imageSampler,"; + +#define ABS_ERROR( result, expected ) ( fabsf( (float)expected - (float)result ) ) + +extern void read_image_pixel_float( void *imageData, image_descriptor *imageInfo, int x, int y, int z, float *outData ); +template int determine_validation_error_offset( void *imagePtr, image_descriptor *imageInfo, image_sampler_data *imageSampler, + T *resultPtr, T * expected, float error, + float x, float y, float z, float xAddressOffset, float yAddressOffset, float zAddressOffset, size_t j, int &numTries, int &numClamped, bool printAsFloat, int lod ) +{ + int actualX, actualY, actualZ; + int found = debug_find_pixel_in_image( imagePtr, imageInfo, resultPtr, &actualX, &actualY, &actualZ, lod ); + bool clampingErr = false, clamped = false, otherClampingBug = false; + int clampedX, clampedY, clampedZ; + + size_t imageWidth = imageInfo->width, imageHeight = imageInfo->height, imageDepth = imageInfo->depth; + + clamped = get_integer_coords_offset( x, y, z, xAddressOffset, yAddressOffset, zAddressOffset, imageWidth, imageHeight, imageDepth, imageSampler, imageInfo, clampedX, clampedY, clampedZ ); + + if( found ) + { + // Is it a clamping bug? + if( clamped && clampedX == actualX && clampedY == actualY && clampedZ == actualZ ) + { + if( (--numClamped) == 0 ) + { + if( printAsFloat ) + { + log_error( "Sample %ld: coord {%f(%a),%f(%a),%f(%a)} did not validate! Expected (%g,%g,%g,%g), got (%g,%g,%g,%g), error of %g\n", + j, x, x, y, y, z, z, (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ], + (float)resultPtr[ 0 ], (float)resultPtr[ 1 ], (float)resultPtr[ 2 ], (float)resultPtr[ 3 ], error ); + } + else + { + log_error( "Sample %ld: coord {%f(%a),%f(%a),%f(%a)} did not validate! Expected (%x,%x,%x,%x), got (%x,%x,%x,%x)\n", + j, x, x, y, y, z, z, (int)expected[ 0 ], (int)expected[ 1 ], (int)expected[ 2 ], (int)expected[ 3 ], + (int)resultPtr[ 0 ], (int)resultPtr[ 1 ], (int)resultPtr[ 2 ], (int)resultPtr[ 3 ] ); + } + log_error( "ERROR: TEST FAILED: Read is erroneously clamping coordinates!\n" ); + return -1; + } + clampingErr = true; + otherClampingBug = true; + } + } + if( clamped && !otherClampingBug ) + { + // If we are in clamp-to-edge mode and we're getting zeroes, it's possible we're getting border erroneously + if( resultPtr[ 0 ] == 0 && resultPtr[ 1 ] == 0 && resultPtr[ 2 ] == 0 && resultPtr[ 3 ] == 0 ) + { + if( (--numClamped) == 0 ) + { + if( printAsFloat ) + { + log_error( "Sample %ld: coord {%f(%a),%f(%a),%f(%a)} did not validate! Expected (%g,%g,%g,%g), got (%g,%g,%g,%g), error of %g\n", + j, x, x, y, y, z, z, (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ], + (float)resultPtr[ 0 ], (float)resultPtr[ 1 ], (float)resultPtr[ 2 ], (float)resultPtr[ 3 ], error ); + } + else + { + log_error( "Sample %ld: coord {%f(%a),%f(%a),%f(%a)} did not validate! Expected (%x,%x,%x,%x), got (%x,%x,%x,%x)\n", + j, x, x, y, y, z, z, (int)expected[ 0 ], (int)expected[ 1 ], (int)expected[ 2 ], (int)expected[ 3 ], + (int)resultPtr[ 0 ], (int)resultPtr[ 1 ], (int)resultPtr[ 2 ], (int)resultPtr[ 3 ] ); + } + log_error( "ERROR: TEST FAILED: Clamping is erroneously returning border color!\n" ); + return -1; + } + clampingErr = true; + } + } + if( !clampingErr ) + { + /* if( clamped && ( (int)x + (int)xOffsetValues[ j ] < 0 || (int)y + (int)yOffsetValues[ j ] < 0 ) ) + { + log_error( "NEGATIVE COORDINATE ERROR\n" ); + return -1; + } + */ + if( true ) // gExtraValidateInfo ) + { + if( printAsFloat ) + { + log_error( "Sample %ld: coord {%f(%a),%f(%a),%f(%a)} did not validate!\n\tExpected (%g,%g,%g,%g),\n\t got (%g,%g,%g,%g), error of %g\n", + j, x, x, y, y, z, z, (float)expected[ 0 ], (float)expected[ 1 ], (float)expected[ 2 ], (float)expected[ 3 ], + (float)resultPtr[ 0 ], (float)resultPtr[ 1 ], (float)resultPtr[ 2 ], (float)resultPtr[ 3 ], error ); + } + else + { + log_error( "Sample %ld: coord {%f(%a),%f(%a),%f(%a)} did not validate!\n\tExpected (%x,%x,%x,%x),\n\t got (%x,%x,%x,%x)\n", + j, x, x, y, y, z, z, (int)expected[ 0 ], (int)expected[ 1 ], (int)expected[ 2 ], (int)expected[ 3 ], + (int)resultPtr[ 0 ], (int)resultPtr[ 1 ], (int)resultPtr[ 2 ], (int)resultPtr[ 3 ] ); + } + log_error( "Integer coords resolve to %d,%d,%d with img size %d,%d,%d\n", clampedX, clampedY, clampedZ, (int)imageWidth, (int)imageHeight, (int)imageDepth ); + + if( printAsFloat && gExtraValidateInfo ) + { + log_error( "\nNearby values:\n" ); + for( int zOff = -1; zOff <= 1; zOff++ ) + { + for( int yOff = -1; yOff <= 1; yOff++ ) + { + float top[ 4 ], real[ 4 ], bot[ 4 ]; + read_image_pixel_float( imagePtr, imageInfo, clampedX - 1 , clampedY + yOff, clampedZ + zOff, top ); + read_image_pixel_float( imagePtr, imageInfo, clampedX ,clampedY + yOff, clampedZ + zOff, real ); + read_image_pixel_float( imagePtr, imageInfo, clampedX + 1, clampedY + yOff, clampedZ + zOff, bot ); + log_error( "\t(%g,%g,%g,%g)",top[0], top[1], top[2], top[3] ); + log_error( " (%g,%g,%g,%g)", real[0], real[1], real[2], real[3] ); + log_error( " (%g,%g,%g,%g)\n",bot[0], bot[1], bot[2], bot[3] ); + } + } + } + // } + // else + // log_error( "\n" ); + if( imageSampler->filter_mode != CL_FILTER_LINEAR ) + { + if( found ) + log_error( "\tValue really found in image at %d,%d,%d (%s)\n", actualX, actualY, actualZ, ( found > 1 ) ? "NOT unique!!" : "unique" ); + else + log_error( "\tValue not actually found in image\n" ); + } + log_error( "\n" ); + } + + numClamped = -1; // We force the clamped counter to never work + if( ( --numTries ) == 0 ) + return -1; + } + return 0; +} + +#define CLAMP( _val, _min, _max ) ((_val) < (_min) ? (_min) : (_val) > (_max) ? (_max) : (_val)) + +static void InitFloatCoords( image_descriptor *imageInfo, image_sampler_data *imageSampler, float *xOffsets, float *yOffsets, float *zOffsets, float xfract, float yfract, float zfract, int normalized_coords, MTdata d , int lod) +{ + size_t i = 0; + if( gDisableOffsets ) + { + for( size_t z = 0; z < imageInfo->depth; z++ ) + { + for( size_t y = 0; y < imageInfo->height; y++ ) + { + for( size_t x = 0; x < imageInfo->width; x++, i++ ) + { + xOffsets[ i ] = (float) (xfract + (double) x); + yOffsets[ i ] = (float) (yfract + (double) y); + zOffsets[ i ] = (float) (zfract + (double) z); + } + } + } + } + else + { + for( size_t z = 0; z < imageInfo->depth; z++ ) + { + for( size_t y = 0; y < imageInfo->height; y++ ) + { + for( size_t x = 0; x < imageInfo->width; x++, i++ ) + { + xOffsets[ i ] = (float) (xfract + (double) ((int) x + random_in_range( -10, 10, d ))); + yOffsets[ i ] = (float) (yfract + (double) ((int) y + random_in_range( -10, 10, d ))); + zOffsets[ i ] = (float) (zfract + (double) ((int) z + random_in_range( -10, 10, d ))); + } + } + } + } + + if( imageSampler->addressing_mode == CL_ADDRESS_NONE ) + { + i = 0; + for( size_t z = 0; z < imageInfo->depth; z++ ) + { + for( size_t y = 0; y < imageInfo->height; y++ ) + { + for( size_t x = 0; x < imageInfo->width; x++, i++ ) + { + xOffsets[ i ] = (float) CLAMP( (double) xOffsets[ i ], 0.0, (double) imageInfo->width - 1.0); + yOffsets[ i ] = (float) CLAMP( (double) yOffsets[ i ], 0.0, (double) imageInfo->height - 1.0); + zOffsets[ i ] = (float) CLAMP( (double) zOffsets[ i ], 0.0, (double) imageInfo->depth - 1.0); + } + } + } + } + + if( normalized_coords || gTestMipmaps) + { + i = 0; + if (lod == 0) + { + for( size_t z = 0; z < imageInfo->depth; z++ ) + { + for( size_t y = 0; y < imageInfo->height; y++ ) + { + for( size_t x = 0; x < imageInfo->width; x++, i++ ) + { + xOffsets[ i ] = (float) ((double) xOffsets[ i ] / (double) imageInfo->width); + yOffsets[ i ] = (float) ((double) yOffsets[ i ] / (double) imageInfo->height); + zOffsets[ i ] = (float) ((double) zOffsets[ i ] / (double) imageInfo->depth); + } + } + } + } + else if (gTestMipmaps) + { + size_t width_lod, height_lod, depth_lod; + + width_lod = (imageInfo->width >> lod)?(imageInfo->width >> lod):1; + height_lod = (imageInfo->height >> lod)?(imageInfo->height >> lod):1; + depth_lod = (imageInfo->depth >> lod)?(imageInfo->depth >> lod):1; + + for( size_t z = 0; z < depth_lod; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, i++ ) + { + xOffsets[ i ] = (float) ((double) xOffsets[ i ] / (double) width_lod); + yOffsets[ i ] = (float) ((double) yOffsets[ i ] / (double) height_lod); + zOffsets[ i ] = (float) ((double) zOffsets[ i ] / (double) depth_lod); + } + } + } + } + } +} + +#ifndef MAX +#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b)) +#endif + +int test_read_image_3D( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, image_sampler_data *imageSampler, + bool useFloatCoords, ExplicitType outputType, MTdata d ) +{ + int error; + size_t threads[3]; + static int initHalf = 0; + + cl_mem_flags image_read_write_flags = CL_MEM_READ_ONLY; + + clMemWrapper xOffsets, yOffsets, zOffsets, results; + clSamplerWrapper actualSampler; + BufferOwningPtr maxImageUseHostPtrBackingStore; + + // Create offset data + BufferOwningPtr xOffsetValues(malloc(sizeof(cl_float) *imageInfo->width * imageInfo->height * imageInfo->depth)); + BufferOwningPtr yOffsetValues(malloc(sizeof(cl_float) *imageInfo->width * imageInfo->height * imageInfo->depth)); + BufferOwningPtr zOffsetValues(malloc(sizeof(cl_float) *imageInfo->width * imageInfo->height * imageInfo->depth)); + + if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) + if( DetectFloatToHalfRoundingMode(queue) ) + return 1; + + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + // Construct testing sources + clProtectedImage protImage; + clMemWrapper unprotImage; + cl_mem image; + + if(gtestTypesToRun & kReadTests) + { + image_read_write_flags = CL_MEM_READ_ONLY; + } + else + { + image_read_write_flags = CL_MEM_READ_WRITE; + } + + if( gMemFlagsToUse == CL_MEM_USE_HOST_PTR ) + { + // clProtectedImage uses USE_HOST_PTR, so just rely on that for the testing (via Ian) + // Do not use protected images for max image size test since it rounds the row size to a page size + if (gTestMaxImages) { + generate_random_image_data( imageInfo, maxImageUseHostPtrBackingStore, d ); + unprotImage = create_image_3d( context, + image_read_write_flags | CL_MEM_USE_HOST_PTR, + imageInfo->format, + imageInfo->width, + imageInfo->height, + imageInfo->depth, + ( gEnablePitch ? imageInfo->rowPitch : 0 ), + ( gEnablePitch ? imageInfo->slicePitch : 0 ), maxImageUseHostPtrBackingStore, &error ); + } else { + error = protImage.Create( context, + (cl_mem_flags)(image_read_write_flags), + imageInfo->format, imageInfo->width, imageInfo->height, imageInfo->depth ); + } + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 3D image of size %d x %d x %d (pitch %d, %d ) (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + if (gTestMaxImages) + image = (cl_mem)unprotImage; + else + image = (cl_mem)protImage; + } + else if( gMemFlagsToUse == CL_MEM_COPY_HOST_PTR ) + { + // Don't use clEnqueueWriteImage; just use copy host ptr to get the data in + unprotImage = create_image_3d( context, + image_read_write_flags | CL_MEM_COPY_HOST_PTR, + imageInfo->format, + imageInfo->width, + imageInfo->height, + imageInfo->depth, + ( gEnablePitch ? imageInfo->rowPitch : 0 ), + ( gEnablePitch ? imageInfo->slicePitch : 0 ), + imageValues, &error ); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 3D image of size %d x %d x %d (pitch %d, %d ) (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + image = unprotImage; + } + else // Either CL_MEM_ALLOC_HOST_PTR or none + { + // Note: if ALLOC_HOST_PTR is used, the driver allocates memory that can be accessed by the host, but otherwise + // it works just as if no flag is specified, so we just do the same thing either way + if ( !gTestMipmaps ) + { + unprotImage = create_image_3d( context, + image_read_write_flags | gMemFlagsToUse, + imageInfo->format, + imageInfo->width, imageInfo->height, imageInfo->depth, + ( gEnablePitch ? imageInfo->rowPitch : 0 ), + ( gEnablePitch ? imageInfo->slicePitch : 0 ), + imageValues, &error ); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 3D image of size %d x %d x %d (pitch %d, %d ) (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + image = unprotImage; + } + else + { + cl_image_desc image_desc = {0}; + image_desc.image_type = CL_MEM_OBJECT_IMAGE3D; + image_desc.image_width = imageInfo->width; + image_desc.image_height = imageInfo->height; + image_desc.image_depth = imageInfo->depth; + image_desc.num_mip_levels = imageInfo->num_mip_levels; + + + unprotImage = clCreateImage( context, + image_read_write_flags, + imageInfo->format, &image_desc, NULL, &error); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create %d level mipmapped 3D image of size %d x %d x %d (pitch %d, %d ) (%s)",(int)imageInfo->num_mip_levels, (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + image = unprotImage; + } + } + + if( gMemFlagsToUse != CL_MEM_COPY_HOST_PTR ) + { + size_t origin[ 4 ] = { 0, 0, 0, 0}; + size_t region[ 3 ] = { imageInfo->width, imageInfo->height, imageInfo->depth }; + + if( gDebugTrace ) + log_info( " - Writing image...\n" ); + + if ( !gTestMipmaps ) + { + + error = clEnqueueWriteImage(queue, image, CL_TRUE, + origin, region, gEnablePitch ? imageInfo->rowPitch : 0, gEnablePitch ? imageInfo->slicePitch : 0, + imageValues , 0, NULL, NULL); + + if (error != CL_SUCCESS) + { + log_error( "ERROR: Unable to write to 3D image of size %d x %d x %d \n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth ); + return error; + } + } + else + { + int nextLevelOffset = 0; + + for (int i =0; i < imageInfo->num_mip_levels; i++) + { origin[3] = i; + error = clEnqueueWriteImage(queue, image, CL_TRUE, + origin, region, /*gEnablePitch ? imageInfo->rowPitch :*/ 0, /*gEnablePitch ? imageInfo->slicePitch :*/ 0, + ((char*)imageValues + nextLevelOffset), 0, NULL, NULL); + if (error != CL_SUCCESS) + { + log_error( "ERROR: Unable to write to %d level mipmapped 3D image of size %d x %d x %d\n", (int)imageInfo->num_mip_levels,(int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth ); + return error; + } + nextLevelOffset += region[0]*region[1]*region[2]*get_pixel_size(imageInfo->format); + //Subsequent mip level dimensions keep halving + region[0] = region[0] >> 1 ? region[0] >> 1 : 1; + region[1] = region[1] >> 1 ? region[1] >> 1 : 1; + region[2] = region[2] >> 1 ? region[2] >> 1 : 1; + } + } + } + + xOffsets = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), sizeof( cl_float ) * imageInfo->width * imageInfo->height * imageInfo->depth, xOffsetValues, &error ); + test_error( error, "Unable to create x offset buffer" ); + yOffsets = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), sizeof( cl_float ) * imageInfo->width * imageInfo->height * imageInfo->depth, yOffsetValues, &error ); + test_error( error, "Unable to create y offset buffer" ); + zOffsets = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), sizeof( cl_float ) * imageInfo->width * imageInfo->height * imageInfo->depth, zOffsetValues, &error ); + test_error( error, "Unable to create y offset buffer" ); + results = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), get_explicit_type_size( outputType ) * 4 * imageInfo->width * imageInfo->height * imageInfo->depth, NULL, &error ); + test_error( error, "Unable to create result buffer" ); + + // Create sampler to use + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, imageSampler->normalized_coords, + CL_SAMPLER_ADDRESSING_MODE, imageSampler->addressing_mode, + CL_SAMPLER_FILTER_MODE, imageSampler->filter_mode, + 0, 0, 0 }; + if (gTestMipmaps) { + properties[6] = CL_SAMPLER_MIP_FILTER_MODE; + properties[7] = imageSampler->filter_mode; + } + actualSampler = clCreateSamplerWithProperties(context, properties, &error ); + test_error( error, "Unable to create image sampler" ); + + // Set arguments + int idx = 0; + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &image ); + test_error( error, "Unable to set kernel arguments" ); + if( !gUseKernelSamplers ) + { + error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler ); + test_error( error, "Unable to set kernel arguments" ); + } + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &xOffsets ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &yOffsets ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &zOffsets ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results ); + test_error( error, "Unable to set kernel arguments" ); + + const float float_offsets[] = { 0.0f, MAKE_HEX_FLOAT(0x1.0p-30f, 0x1L, -30), 0.25f, 0.3f, 0.5f - FLT_EPSILON/4.0f, 0.5f, 0.9f, 1.0f - FLT_EPSILON/2 }; + int float_offset_count = sizeof( float_offsets) / sizeof( float_offsets[0] ); + int numTries = MAX_TRIES, numClamped = MAX_CLAMPED; + int loopCount = 2 * float_offset_count; + if( ! useFloatCoords ) + loopCount = 1; + if (gTestMaxImages) { + loopCount = 1; + log_info("Testing each size only once with pixel offsets of %g for max sized images.\n", float_offsets[0]); + } + + // Get the maximum absolute error for this format + double formatAbsoluteError = get_max_absolute_error(imageInfo->format, imageSampler); + if (gDebugTrace) log_info("\tformatAbsoluteError is %e\n", formatAbsoluteError); + + if (0 == initHalf && imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) { + initHalf = CL_SUCCESS == DetectFloatToHalfRoundingMode( queue ); + if (initHalf) { + log_info("Half rounding mode successfully detected.\n"); + } + } + + int nextLevelOffset = 0; + size_t width_lod = imageInfo->width, height_lod = imageInfo->height, depth_lod = imageInfo->depth; + + //Loop over all mipmap levels, if we are testing mipmapped images. + for(int lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++) + { + size_t resultValuesSize = width_lod * height_lod * depth_lod * get_explicit_type_size( outputType ) * 4; + BufferOwningPtr resultValues(malloc( resultValuesSize )); + float lod_float = (float)lod; + if (gTestMipmaps) { + //Set the lod kernel arg + if(gDebugTrace) + log_info(" - Working at mip level %d\n", lod); + error = clSetKernelArg( kernel, idx, sizeof( float ), &lod_float); + test_error( error, "Unable to set kernel arguments" ); + } + + for( int q = 0; q < loopCount; q++ ) + { + float offset = float_offsets[ q % float_offset_count ]; + + // Init the coordinates + InitFloatCoords( imageInfo, imageSampler, xOffsetValues, yOffsetValues, zOffsetValues, + q>=float_offset_count ? -offset: offset, + q>=float_offset_count ? offset: -offset, + q>=float_offset_count ? -offset: offset, + imageSampler->normalized_coords, d, lod ); + + error = clEnqueueWriteBuffer( queue, xOffsets, CL_TRUE, 0, sizeof(cl_float) * imageInfo->height * imageInfo->width * imageInfo->depth, xOffsetValues, 0, NULL, NULL ); + test_error( error, "Unable to write x offsets" ); + error = clEnqueueWriteBuffer( queue, yOffsets, CL_TRUE, 0, sizeof(cl_float) * imageInfo->height * imageInfo->width * imageInfo->depth, yOffsetValues, 0, NULL, NULL ); + test_error( error, "Unable to write y offsets" ); + error = clEnqueueWriteBuffer( queue, zOffsets, CL_TRUE, 0, sizeof(cl_float) * imageInfo->height * imageInfo->width * imageInfo->depth, zOffsetValues, 0, NULL, NULL ); + test_error( error, "Unable to write z offsets" ); + + + memset( resultValues, 0xff, resultValuesSize ); + clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + + // Figure out thread dimensions + threads[0] = (size_t)width_lod; + threads[1] = (size_t)height_lod; + threads[2] = (size_t)depth_lod; + + // Run the kernel + error = clEnqueueNDRangeKernel( queue, kernel, 3, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + // Get results + error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, width_lod * height_lod * depth_lod * get_explicit_type_size( outputType ) * 4, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + if( gDebugTrace ) + log_info( " results read\n" ); + + // Validate results element by element + char *imagePtr = (char*)imageValues + nextLevelOffset; + /* + * FLOAT output type + */ + if(is_sRGBA_order(imageInfo->format->image_channel_order) && (outputType == kFloat) ) + { + // Validate float results + float *resultPtr = (float *)(char *)resultValues; + float expected[4], error=0.0f; + float maxErr = get_max_relative_error( imageInfo->format, imageSampler, 1 /*3D*/, CL_FILTER_LINEAR == imageSampler->filter_mode ); + + for( size_t z = 0, j = 0; z < depth_lod; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X, Y and Z to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + float offset = NORM_OFFSET; + if (!imageSampler->normalized_coords || imageSampler->filter_mode != CL_FILTER_NEAREST || NORM_OFFSET == 0 +#if defined( __APPLE__ ) + // Apple requires its CPU implementation to do correctly rounded address arithmetic in all modes + || gDeviceType != CL_DEVICE_TYPE_GPU +#endif + ) + offset = 0.0f; // Loop only once + + for (float norm_offset_x = -offset; norm_offset_x <= offset && !found_pixel ; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !found_pixel ; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -offset; norm_offset_z <= NORM_OFFSET && !found_pixel; norm_offset_z += NORM_OFFSET) { + + int hasDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0, &hasDenormals, lod ); + + float err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + float err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + float err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + // Clamp to the minimum absolute error for the format + if (err1 > 0 && err1 < formatAbsoluteError) { err1 = 0.0f; } + if (err2 > 0 && err2 < formatAbsoluteError) { err2 = 0.0f; } + if (err3 > 0 && err3 < formatAbsoluteError) { err3 = 0.0f; } + if (err4 > 0 && err4 < formatAbsoluteError) { err4 = 0.0f; } + float maxErr = 0.5; + + if( ! (err1 <= maxErr) || ! (err2 <= maxErr) || ! (err3 <= maxErr) || ! (err4 <= maxErr) ) + { + // Try flushing the denormals + if( hasDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + + found_pixel = (err1 <= maxErr) && (err2 <= maxErr) && (err3 <= maxErr) && (err4 <= maxErr); + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -offset; norm_offset_x <= offset && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -offset; norm_offset_z <= offset && !checkOnlyOnePixel; norm_offset_z += NORM_OFFSET) { + + int hasDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0, &hasDenormals, lod ); + + float err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + float err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + float err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + float maxErr = 0.6; + + if( ! (err1 <= maxErr) || ! (err2 <= maxErr) || ! (err3 <= maxErr) || ! (err4 <= maxErr) ) + { + // Try flushing the denormals + if( hasDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( sRGBmap( resultPtr[0] ) - sRGBmap( expected[0] ) ); + err2 = fabsf( sRGBmap( resultPtr[1] ) - sRGBmap( expected[1] ) ); + err3 = fabsf( sRGBmap( resultPtr[2] ) - sRGBmap( expected[2] ) ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + + if( ! (err1 <= maxErr) || ! (err2 <= maxErr) || ! (err3 <= maxErr) || ! (err4 <= maxErr) ) + { + log_error("FAILED norm_offsets: %g , %g , %g:\n", norm_offset_x, norm_offset_y, norm_offset_z); + + float tempOut[4]; + shouldReturn |= determine_validation_error_offset( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[j], yOffsetValues[j], zOffsetValues[j], + norm_offset_x, norm_offset_y, norm_offset_z, j, + numTries, numClamped, true, lod ); + log_error( "Step by step:\n" ); + FloatPixel temp = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, tempOut, 1 /*verbose*/, &hasDenormals, lod); + log_error( "\tulps: %2.2f, %2.2f, %2.2f, %2.2f (max allowed: %2.2f)\n\n", + Ulp_Error( resultPtr[0], expected[0] ), + Ulp_Error( resultPtr[1], expected[1] ), + Ulp_Error( resultPtr[2], expected[2] ), + Ulp_Error( resultPtr[3], expected[3] ), + Ulp_Error( MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) + maxErr, MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) ) ); + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + } + /* + * FLOAT output type + */ + else if( outputType == kFloat ) + { + // Validate float results + float *resultPtr = (float *)(char *)resultValues; + float expected[4], error=0.0f; + float maxErr = get_max_relative_error( imageInfo->format, imageSampler, 1 /*3D*/, CL_FILTER_LINEAR == imageSampler->filter_mode ); + + for( size_t z = 0, j = 0; z < depth_lod; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X, Y and Z to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + float offset = NORM_OFFSET; + if (!imageSampler->normalized_coords || imageSampler->filter_mode != CL_FILTER_NEAREST || NORM_OFFSET == 0 +#if defined( __APPLE__ ) + // Apple requires its CPU implementation to do correctly rounded address arithmetic in all modes + || gDeviceType != CL_DEVICE_TYPE_GPU +#endif + ) + offset = 0.0f; // Loop only once + + for (float norm_offset_x = -offset; norm_offset_x <= offset && !found_pixel ; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !found_pixel ; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -offset; norm_offset_z <= NORM_OFFSET && !found_pixel; norm_offset_z += NORM_OFFSET) { + + int hasDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0, &hasDenormals, lod ); + + float err1 = fabsf( resultPtr[0] - expected[0] ); + float err2 = fabsf( resultPtr[1] - expected[1] ); + float err3 = fabsf( resultPtr[2] - expected[2] ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + // Clamp to the minimum absolute error for the format + if (err1 > 0 && err1 < formatAbsoluteError) { err1 = 0.0f; } + if (err2 > 0 && err2 < formatAbsoluteError) { err2 = 0.0f; } + if (err3 > 0 && err3 < formatAbsoluteError) { err3 = 0.0f; } + if (err4 > 0 && err4 < formatAbsoluteError) { err4 = 0.0f; } + float maxErr1 = MAX( maxErr * maxPixel.p[0], FLT_MIN ); + float maxErr2 = MAX( maxErr * maxPixel.p[1], FLT_MIN ); + float maxErr3 = MAX( maxErr * maxPixel.p[2], FLT_MIN ); + float maxErr4 = MAX( maxErr * maxPixel.p[3], FLT_MIN ); + + if( ! (err1 <= maxErr1) || ! (err2 <= maxErr2) || ! (err3 <= maxErr3) || ! (err4 <= maxErr4) ) + { + // Try flushing the denormals + if( hasDenormals ) + { + // If implementation decide to flush subnormals to zero, + // max error needs to be adjusted + maxErr1 += 4 * FLT_MIN; + maxErr2 += 4 * FLT_MIN; + maxErr3 += 4 * FLT_MIN; + maxErr4 += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( resultPtr[0] - expected[0] ); + err2 = fabsf( resultPtr[1] - expected[1] ); + err3 = fabsf( resultPtr[2] - expected[2] ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + + found_pixel = (err1 <= maxErr1) && (err2 <= maxErr2) && (err3 <= maxErr3) && (err4 <= maxErr4); + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -offset; norm_offset_x <= offset && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -offset; norm_offset_y <= offset && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -offset; norm_offset_z <= offset && !checkOnlyOnePixel; norm_offset_z += NORM_OFFSET) { + + int hasDenormals = 0; + FloatPixel maxPixel = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, 0, &hasDenormals, lod ); + + float err1 = fabsf( resultPtr[0] - expected[0] ); + float err2 = fabsf( resultPtr[1] - expected[1] ); + float err3 = fabsf( resultPtr[2] - expected[2] ); + float err4 = fabsf( resultPtr[3] - expected[3] ); + float maxErr1 = MAX( maxErr * maxPixel.p[0], FLT_MIN ); + float maxErr2 = MAX( maxErr * maxPixel.p[1], FLT_MIN ); + float maxErr3 = MAX( maxErr * maxPixel.p[2], FLT_MIN ); + float maxErr4 = MAX( maxErr * maxPixel.p[3], FLT_MIN ); + + + if( ! (err1 <= maxErr1) || ! (err2 <= maxErr2) || ! (err3 <= maxErr3) || ! (err4 <= maxErr4) ) + { + // Try flushing the denormals + if( hasDenormals ) + { + maxErr1 += 4 * FLT_MIN; + maxErr2 += 4 * FLT_MIN; + maxErr3 += 4 * FLT_MIN; + maxErr4 += 4 * FLT_MIN; + + maxPixel = sample_image_pixel_float( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + imageSampler, expected, 0, NULL, lod ); + + err1 = fabsf( resultPtr[0] - expected[0] ); + err2 = fabsf( resultPtr[1] - expected[1] ); + err3 = fabsf( resultPtr[2] - expected[2] ); + err4 = fabsf( resultPtr[3] - expected[3] ); + } + } + + if( ! (err1 <= maxErr1) || ! (err2 <= maxErr2) || ! (err3 <= maxErr3) || ! (err4 <= maxErr4) ) + { + log_error("FAILED norm_offsets: %g , %g , %g:\n", norm_offset_x, norm_offset_y, norm_offset_z); + + float tempOut[4]; + shouldReturn |= determine_validation_error_offset( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[j], yOffsetValues[j], zOffsetValues[j], + norm_offset_x, norm_offset_y, norm_offset_z, j, + numTries, numClamped, true, lod ); + log_error( "Step by step:\n" ); + FloatPixel temp = sample_image_pixel_float_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, tempOut, 1 /*verbose*/, &hasDenormals, lod); + log_error( "\tulps: %2.2f, %2.2f, %2.2f, %2.2f (max allowed: %2.2f)\n\n", + Ulp_Error( resultPtr[0], expected[0] ), + Ulp_Error( resultPtr[1], expected[1] ), + Ulp_Error( resultPtr[2], expected[2] ), + Ulp_Error( resultPtr[3], expected[3] ), + Ulp_Error( MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) + maxErr, MAKE_HEX_FLOAT(0x1.000002p0f, 0x1000002L, -24) ) ); + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + } + /* + * UINT output type + */ + else if( outputType == kUInt ) + { + // Validate unsigned integer results + unsigned int *resultPtr = (unsigned int *)(char *)resultValues; + unsigned int expected[4]; + float error; + for( size_t z = 0, j = 0; z < depth_lod; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X, Y and Z to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -NORM_OFFSET; norm_offset_z <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_z += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + norm_offset_z = 0.0f; + checkOnlyOnePixel = 1; + } + + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, lod ); + + error = errMax( errMax( abs_diff_uint(expected[ 0 ], resultPtr[ 0 ]), abs_diff_uint(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_uint(expected[ 2 ], resultPtr[ 2 ]), abs_diff_uint(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if (error < MAX_ERR) + found_pixel = 1; + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -NORM_OFFSET; norm_offset_z <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_z += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + norm_offset_z = 0.0f; + checkOnlyOnePixel = 1; + } + + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, lod ); + + error = errMax( errMax( abs_diff_uint(expected[ 0 ], resultPtr[ 0 ]), abs_diff_uint(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_uint(expected[ 2 ], resultPtr[ 2 ]), abs_diff_uint(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if( error > MAX_ERR ) + { + log_error("FAILED norm_offsets: %g , %g , %g:\n", norm_offset_x, norm_offset_y, norm_offset_z); + shouldReturn |= determine_validation_error_offset( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[j], yOffsetValues[j], zOffsetValues[j], + norm_offset_x, norm_offset_y, norm_offset_z, + j, numTries, numClamped, false, lod ); + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + } + else + /* + * INT output type + */ + { + // Validate integer results + int *resultPtr = (int *)(char *)resultValues; + int expected[4]; + float error; + for( size_t z = 0, j = 0; z < depth_lod; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + for( size_t x = 0; x < width_lod; x++, j++ ) + { + // Step 1: go through and see if the results verify for the pixel + // For the normalized case on a GPU we put in offsets to the X, Y and Z to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + int checkOnlyOnePixel = 0; + int found_pixel = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -NORM_OFFSET; norm_offset_z <= NORM_OFFSET && !found_pixel && !checkOnlyOnePixel; norm_offset_z += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + norm_offset_z = 0.0f; + checkOnlyOnePixel = 1; + } + + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, lod ); + + error = errMax( errMax( abs_diff_int(expected[ 0 ], resultPtr[ 0 ]), abs_diff_int(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_int(expected[ 2 ], resultPtr[ 2 ]), abs_diff_int(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if (error < MAX_ERR) + found_pixel = 1; + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + + // Step 2: If we did not find a match, then print out debugging info. + if (!found_pixel) { + // For the normalized case on a GPU we put in offsets to the X and Y to see if we land on the + // right pixel. This addresses the significant inaccuracy in GPU normalization in OpenCL 1.0. + checkOnlyOnePixel = 0; + int shouldReturn = 0; + for (float norm_offset_x = -NORM_OFFSET; norm_offset_x <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_x += NORM_OFFSET) { + for (float norm_offset_y = -NORM_OFFSET; norm_offset_y <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_y += NORM_OFFSET) { + for (float norm_offset_z = -NORM_OFFSET; norm_offset_z <= NORM_OFFSET && !checkOnlyOnePixel; norm_offset_z += NORM_OFFSET) { + + // If we are not on a GPU, or we are not normalized, then only test with offsets (0.0, 0.0) + // E.g., test one pixel. + if (!imageSampler->normalized_coords || gDeviceType != CL_DEVICE_TYPE_GPU || NORM_OFFSET == 0 || NORM_OFFSET == 0 || NORM_OFFSET == 0) { + norm_offset_x = 0.0f; + norm_offset_y = 0.0f; + norm_offset_z = 0.0f; + checkOnlyOnePixel = 1; + } + + sample_image_pixel_offset( imagePtr, imageInfo, + xOffsetValues[ j ], yOffsetValues[ j ], zOffsetValues[ j ], + norm_offset_x, norm_offset_y, norm_offset_z, + imageSampler, expected, lod ); + + error = errMax( errMax( abs_diff_int(expected[ 0 ], resultPtr[ 0 ]), abs_diff_int(expected[ 1 ], resultPtr[ 1 ]) ), + errMax( abs_diff_int(expected[ 2 ], resultPtr[ 2 ]), abs_diff_int(expected[ 3 ], resultPtr[ 3 ]) ) ); + + if( error > MAX_ERR ) + { + log_error("FAILED norm_offsets: %g , %g , %g:\n", norm_offset_x, norm_offset_y, norm_offset_z); + shouldReturn |= determine_validation_error_offset( imagePtr, imageInfo, imageSampler, resultPtr, + expected, error, xOffsetValues[j], yOffsetValues[j], zOffsetValues[j], + norm_offset_x, norm_offset_y, norm_offset_z, + j, numTries, numClamped, false, lod ); + } else { + log_error("Test error: we should have detected this passing above.\n"); + } + }//norm_offset_z + }//norm_offset_y + }//norm_offset_x + if( shouldReturn ) + return 1; + } // if (!found_pixel) + + resultPtr += 4; + } + } + } + } + } + { + nextLevelOffset += width_lod * height_lod * depth_lod * get_pixel_size(imageInfo->format); + width_lod = ( width_lod >> 1) ?( width_lod >> 1) : 1; + height_lod = ( height_lod >> 1) ?( height_lod >> 1) : 1; + depth_lod = ( depth_lod >> 1) ?( depth_lod >> 1) : 1; + } + } + + return numTries != MAX_TRIES || numClamped != MAX_CLAMPED; +} + +int test_read_image_set_3D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, + bool floatCoords, ExplicitType outputType ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + RandomSeed seed( gRandomSeed ); + + int error; + + clProgramWrapper program; + clKernelWrapper kernel; + const char *KernelSourcePattern = NULL; + + // Get operating parameters + size_t maxWidth, maxHeight, maxDepth; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0x0 }; + + imageInfo.format = format; + imageInfo.type = CL_MEM_OBJECT_IMAGE3D; + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 3D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // Determine types + if( outputType == kInt ) + readFormat = "i"; + else if( outputType == kUInt ) + readFormat = "ui"; + else // kFloat + readFormat = "f"; + + // Construct the source + const char *samplerArg = samplerKernelArg; + char samplerVar[ 1024 ] = ""; + if( gUseKernelSamplers ) + { + get_sampler_kernel_code( imageSampler, samplerVar ); + samplerArg = ""; + } + + // Construct the source + if(gtestTypesToRun & kReadTests) + { + KernelSourcePattern = read3DKernelSourcePattern; + } + else + { + KernelSourcePattern = read_write3DKernelSourcePattern; + } + + sprintf( programSrc, + KernelSourcePattern, + samplerArg, get_explicit_type_name( outputType ), + gTestMipmaps? ", float lod": " ", + samplerVar, + gTestMipmaps? offset3DLodKernelSource: offset3DKernelSource, + floatCoords ? float3DUnnormalizedCoordKernelSource : int3DCoordKernelSource, + readFormat, + gTestMipmaps? ",lod":" "); + + ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create testing kernel" ); + + // Run tests + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + for( imageInfo.depth = 2; imageInfo.depth < 9; imageInfo.depth++ ) + { + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) (2+rand()%(compute_max_mip_levels(imageInfo.width,imageInfo.height,imageInfo.depth) - 1)); + + if( gDebugTrace ) + log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth ); + int retCode = test_read_image_3D( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, maxDepth, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE3D, imageInfo.format, CL_TRUE); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.depth = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + if (gTestMipmaps) + imageInfo.num_mip_levels = (cl_uint) (2+rand()%(compute_max_mip_levels(imageInfo.width,imageInfo.height,imageInfo.depth) - 1)); + log_info("Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ]); + if( gDebugTrace ) + log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + int retCode = test_read_image_3D( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + } + else if( gTestRounding ) + { + size_t typeRange = 1 << ( get_format_type_size( imageInfo.format ) * 8 ); + imageInfo.height = typeRange / 256; + imageInfo.width = (size_t)( typeRange / (cl_ulong)imageInfo.height ); + imageInfo.depth = 2; + + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + int retCode = test_read_image_3D( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = reduceImageSizeRange(maxWidth, seed ); + imageInfo.height = reduceImageSizeRange(maxHeight, seed ); + imageInfo.depth = reduceImageDepth(maxDepth, seed ); + + if (gTestMipmaps) + { + //imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.depth, imageInfo.depth), seed); + imageInfo.num_mip_levels = (cl_uint) (2+rand()%(compute_max_mip_levels(imageInfo.width,imageInfo.height,imageInfo.depth) - 1)); + //Need to take into account the output buffer size, otherwise we will end up with input buffer that is exceeding MaxAlloc + size = compute_mipmapped_image_size( imageInfo )*4 * get_explicit_type_size( outputType ); + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + } + else + { + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + + if( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth * get_pixel_size( imageInfo.format ); + + size_t extraHeight = (int)random_log_in_range( 0, 64, seed ); + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight); + } + + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.depth * 4 * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + { + log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxDepth ); + if ( gTestMipmaps ) + log_info( " and number of mip levels :%d\n", (int)imageInfo.num_mip_levels ); + } + int retCode = test_read_image_3D( device, context, queue, kernel, &imageInfo, imageSampler, floatCoords, outputType, seed ); + if( retCode ) + return retCode; + } + } + + return 0; +} + + + + diff --git a/test_conformance/images/kernel_read_write/test_write_1D.cpp b/test_conformance/images/kernel_read_write/test_write_1D.cpp new file mode 100644 index 00000000..85756222 --- /dev/null +++ b/test_conformance/images/kernel_read_write/test_write_1D.cpp @@ -0,0 +1,696 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#if !defined(_WIN32) +#include +#endif + +#define MAX_ERR 0.005f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_filter_mode gFilterModeToSkip; +extern cl_mem_flags gMemFlagsToUse; + +extern int gtestTypesToRun; + +const char *readwrite1DKernelSourcePattern = +"__kernel void sample_kernel( __global %s4 *input, read_write image1d_t output %s)\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int offset = tidX;\n" +" write_image%s( output, tidX %s, input[ offset ]);\n" +"}"; + +const char *write1DKernelSourcePattern = +"__kernel void sample_kernel( __global %s4 *input, write_only image1d_t output %s)\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int offset = tidX;\n" +" write_image%s( output, tidX %s, input[ offset ]);\n" +"}"; + +int test_write_image_1D( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, ExplicitType inputType, MTdata d ) +{ + int totalErrors = 0; + size_t num_flags = 0; + const cl_mem_flags *mem_flag_types = NULL; + const char * *mem_flag_names = NULL; + const cl_mem_flags write_only_mem_flag_types[2] = { CL_MEM_WRITE_ONLY, CL_MEM_READ_WRITE }; + const char * write_only_mem_flag_names[2] = { "CL_MEM_WRITE_ONLY", "CL_MEM_READ_WRITE" }; + const cl_mem_flags read_write_mem_flag_types[1] = { CL_MEM_READ_WRITE}; + const char * read_write_mem_flag_names[1] = { "CL_MEM_READ_WRITE"}; + + if(gtestTypesToRun & kWriteTests) + { + mem_flag_types = write_only_mem_flag_types; + mem_flag_names = write_only_mem_flag_names; + num_flags = sizeof( write_only_mem_flag_types ) / sizeof( write_only_mem_flag_types[0] ); + } + else + { + mem_flag_types = read_write_mem_flag_types; + mem_flag_names = read_write_mem_flag_names; + num_flags = sizeof( read_write_mem_flag_types ) / sizeof( read_write_mem_flag_types[0] ); + } + for( size_t mem_flag_index = 0; mem_flag_index < num_flags; mem_flag_index++ ) + { + int error; + size_t threads[2]; + bool verifyRounding = false; + int totalErrors = 0; + int forceCorrectlyRoundedWrites = 0; + +#if defined( __APPLE__ ) + // Require Apple's CPU implementation to be correctly rounded, not just within 0.6 + cl_device_type type = 0; + if( (error = clGetDeviceInfo( device, CL_DEVICE_TYPE, sizeof( type), &type, NULL ))) + { + log_error("Error: Could not get device type for Apple device! (%d) \n", error ); + return 1; + } + if( type == CL_DEVICE_TYPE_CPU ) + forceCorrectlyRoundedWrites = 1; +#endif + + if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) + if( DetectFloatToHalfRoundingMode(queue) ) + return 1; + + BufferOwningPtr maxImageUseHostPtrBackingStore, imageValues; + + create_random_image_data( inputType, imageInfo, imageValues, d ); + + if(!gTestMipmaps) + { + if( inputType == kFloat && imageInfo->format->image_channel_data_type != CL_FLOAT && imageInfo->format->image_channel_data_type != CL_HALF_FLOAT ) + { + /* Pilot data for sRGB images */ + if(is_sRGBA_order(imageInfo->format->image_channel_order)) + { + // We want to generate ints (mostly) in range of the target format which should be [0,255] + // However the range chosen here is [-test_range_ext, 255 + test_range_ext] so that + // it can test some out-of-range data points + const unsigned int test_range_ext = 16; + int formatMin = 0 - test_range_ext; + int formatMax = 255 + test_range_ext; + int pixel_value = 0; + float *inputValues = NULL; + + // First, fill with arbitrary floats + { + inputValues = (float *)(char*)imageValues; + for( size_t i = 0; i < imageInfo->width * 4; i++ ) + { + pixel_value = random_in_range( formatMin, (int)formatMax, d ); + inputValues[ i ] = (float)(pixel_value/255.0f); + } + } + + // Throw a few extra test values in there + inputValues = (float *)(char*)imageValues; + size_t i = 0; + + // Piloting some debug inputs. + inputValues[ i++ ] = -0.5f; + inputValues[ i++ ] = 0.5f; + inputValues[ i++ ] = 2.f; + inputValues[ i++ ] = 0.5f; + + // Also fill in the first few vectors with some deliberate tests to determine the rounding mode + // is correct + if( imageInfo->width > 12 ) + { + float formatMax = (float)get_format_max_int( imageInfo->format ); + inputValues[ i++ ] = 4.0f / formatMax; + inputValues[ i++ ] = 4.3f / formatMax; + inputValues[ i++ ] = 4.5f / formatMax; + inputValues[ i++ ] = 4.7f / formatMax; + inputValues[ i++ ] = 5.0f / formatMax; + inputValues[ i++ ] = 5.3f / formatMax; + inputValues[ i++ ] = 5.5f / formatMax; + inputValues[ i++ ] = 5.7f / formatMax; + } + } + else + { + // First, fill with arbitrary floats + { + float *inputValues = (float *)(char*)imageValues; + for( size_t i = 0; i < imageInfo->width * 4; i++ ) + inputValues[ i ] = get_random_float( -0.1f, 1.1f, d ); + } + + // Throw a few extra test values in there + float *inputValues = (float *)(char*)imageValues; + size_t i = 0; + inputValues[ i++ ] = -0.0000000000009f; + inputValues[ i++ ] = 1.f; + inputValues[ i++ ] = -1.f; + inputValues[ i++ ] = 2.f; + + // Also fill in the first few vectors with some deliberate tests to determine the rounding mode + // is correct + if( imageInfo->width > 12 ) + { + float formatMax = (float)get_format_max_int( imageInfo->format ); + inputValues[ i++ ] = 4.0f / formatMax; + inputValues[ i++ ] = 4.3f / formatMax; + inputValues[ i++ ] = 4.5f / formatMax; + inputValues[ i++ ] = 4.7f / formatMax; + inputValues[ i++ ] = 5.0f / formatMax; + inputValues[ i++ ] = 5.3f / formatMax; + inputValues[ i++ ] = 5.5f / formatMax; + inputValues[ i++ ] = 5.7f / formatMax; + verifyRounding = true; + } + } + } + else if( inputType == kUInt ) + { + unsigned int *inputValues = (unsigned int*)(char*)imageValues; + size_t i = 0; + inputValues[ i++ ] = 0; + inputValues[ i++ ] = 65535; + inputValues[ i++ ] = 7271820; + inputValues[ i++ ] = 0; + } + } + + // Construct testing sources + clProtectedImage protImage; + clMemWrapper unprotImage; + cl_mem image; + + if( gMemFlagsToUse == CL_MEM_USE_HOST_PTR ) + { + // clProtectedImage uses USE_HOST_PTR, so just rely on that for the testing (via Ian) + // Do not use protected images for max image size test since it rounds the row size to a page size + if (gTestMaxImages) { + create_random_image_data( inputType, imageInfo, maxImageUseHostPtrBackingStore, d ); + + unprotImage = create_image_1d( context, mem_flag_types[mem_flag_index] | CL_MEM_USE_HOST_PTR, imageInfo->format, + imageInfo->width, 0, + maxImageUseHostPtrBackingStore, NULL, &error ); + } else { + error = protImage.Create( context, mem_flag_types[mem_flag_index], imageInfo->format, imageInfo->width ); + } + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 1D image of size %ld pitch %ld (%s, %s)\n", imageInfo->width, + imageInfo->rowPitch, IGetErrorString( error ), mem_flag_names[mem_flag_index] ); + return error; + } + + if (gTestMaxImages) + image = (cl_mem)unprotImage; + else + image = (cl_mem)protImage; + } + else // Either CL_MEM_ALLOC_HOST_PTR, CL_MEM_COPY_HOST_PTR or none + { + // Note: if ALLOC_HOST_PTR is used, the driver allocates memory that can be accessed by the host, but otherwise + // it works just as if no flag is specified, so we just do the same thing either way + // Note: if the flags is really CL_MEM_COPY_HOST_PTR, we want to remove it, because we don't want to copy any incoming data + if( gTestMipmaps ) + { + cl_image_desc image_desc = {0}; + image_desc.image_type = imageInfo->type; + image_desc.num_mip_levels = imageInfo->num_mip_levels; + image_desc.image_width = imageInfo->width; + image_desc.image_array_size = imageInfo->arraySize; + + unprotImage = clCreateImage( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ), + imageInfo->format, &image_desc, NULL, &error); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create %d level 1D image of size %ld (%s, %s)\n", imageInfo->num_mip_levels, imageInfo->width, + IGetErrorString( error ), mem_flag_names[mem_flag_index] ); + return error; + } + } + else + { + unprotImage = create_image_1d( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ), imageInfo->format, + imageInfo->width, 0, + imageValues, NULL, &error ); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 1D image of size %ld pitch %ld (%s, %s)\n", imageInfo->width, + imageInfo->rowPitch, IGetErrorString( error ), mem_flag_names[mem_flag_index] ); + return error; + } + } + image = unprotImage; + } + + error = clSetKernelArg( kernel, 1, sizeof( cl_mem ), &image ); + test_error( error, "Unable to set kernel arguments" ); + + size_t width_lod = imageInfo->width, nextLevelOffset = 0; + size_t origin[ 3 ] = { 0, 0, 0 }; + size_t region[ 3 ] = { imageInfo->width, 1, 1 }; + size_t resultSize; + + for( int lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++) + { + if(gTestMipmaps) + { + error = clSetKernelArg( kernel, 2, sizeof( int ), &lod ); + } + + clMemWrapper inputStream; + + char *imagePtrOffset = imageValues + nextLevelOffset; + inputStream = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), + get_explicit_type_size( inputType ) * 4 * width_lod, imagePtrOffset, &error ); + test_error( error, "Unable to create input buffer" ); + + // Set arguments + error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &inputStream ); + test_error( error, "Unable to set kernel arguments" ); + + // Run the kernel + threads[0] = (size_t)width_lod; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + // Get results + if( gTestMipmaps ) + resultSize = width_lod * get_pixel_size( imageInfo->format ); + else + resultSize = imageInfo->rowPitch; + clProtectedArray PA(resultSize); + char *resultValues = (char *)((void *)PA); + + if( gDebugTrace ) + log_info( " reading results, %ld kbytes\n", (unsigned long)( resultSize / 1024 ) ); + + origin[ 1 ] = lod; + region[ 0 ] = width_lod; + + error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, gEnablePitch ? imageInfo->rowPitch : 0, 0, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + if( gDebugTrace ) + log_info( " results read\n" ); + + // Validate results element by element + char *imagePtr = imageValues + nextLevelOffset; + int numTries = 5; + { + char *resultPtr = (char *)resultValues; + for( size_t x = 0, i = 0; x < width_lod; x++, i++ ) + { + char resultBuffer[ 16 ]; // Largest format would be 4 channels * 4 bytes (32 bits) each + + // Convert this pixel + if( inputType == kFloat ) + pack_image_pixel( (float *)imagePtr, imageInfo->format, resultBuffer ); + else if( inputType == kInt ) + pack_image_pixel( (int *)imagePtr, imageInfo->format, resultBuffer ); + else // if( inputType == kUInt ) + pack_image_pixel( (unsigned int *)imagePtr, imageInfo->format, resultBuffer ); + + // Compare against the results + if(is_sRGBA_order(imageInfo->format->image_channel_order)) + { + // Compare sRGB-mapped values + cl_float expected[4] = {0}; + cl_float* input_values = (float*)imagePtr; + cl_uchar *actual = (cl_uchar*)resultPtr; + float max_err = MAX_lRGB_TO_sRGB_CONVERSION_ERROR; + float err[4] = {0.0f}; + + for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ ) + { + if(j < 3) + { + expected[j] = sRGBmap(input_values[j]); + } + else // there is no sRGB conversion for alpha component if it exists + { + expected[j] = NORMALIZE(input_values[j], 255.0f); + } + + err[j] = fabsf( expected[ j ] - actual[ j ] ); + } + + if ((err[0] > max_err) || + (err[1] > max_err) || + (err[2] > max_err) || + (err[3] > 0)) // there is no conversion for alpha so the error should be zero + { + log_error( " Error: %g %g %g %g\n", err[0], err[1], err[2], err[3]); + log_error( " Input: %g %g %g %g\n", *((float *)imagePtr), *((float *)imagePtr + 1), *((float *)imagePtr + 2), *((float *)imagePtr + 3)); + log_error( " Expected: %g %g %g %g\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] ); + log_error( " Actual: %d %d %d %d\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] ); + return 1; + } + } + else if( imageInfo->format->image_channel_data_type == CL_FLOAT ) + { + // Compare floats + float *expected = (float *)resultBuffer; + float *actual = (float *)resultPtr; + float err = 0.f; + for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ ) + err += ( expected[ j ] != 0 ) ? fabsf( ( expected[ j ] - actual[ j ] ) / expected[ j ] ) : fabsf( expected[ j ] - actual[ j ] ); + + err /= (float)get_format_channel_count( imageInfo->format ); + if( err > MAX_ERR ) + { + unsigned int *e = (unsigned int *)expected; + unsigned int *a = (unsigned int *)actual; + log_error( "ERROR: Sample %ld (%ld) did not validate! (%s)\n", i, x, mem_flag_names[mem_flag_index] ); + log_error( " Error: %g\n", err ); + log_error( " Expected: %a %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] ); + log_error( " Expected: %08x %08x %08x %08x\n", e[ 0 ], e[ 1 ], e[ 2 ], e[ 3 ] ); + log_error( " Actual: %a %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] ); + log_error( " Actual: %08x %08x %08x %08x\n", a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ] ); + totalErrors++; + if( ( --numTries ) == 0 ) + return 1; + } + } + else if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) + { + // Compare half floats + if( memcmp( resultBuffer, resultPtr, 2 * get_format_channel_count( imageInfo->format ) ) != 0 ) + { + cl_ushort *e = (cl_ushort *)resultBuffer; + cl_ushort *a = (cl_ushort *)resultPtr; + int err_cnt = 0; + + //Fix up cases where we have NaNs + for( size_t j = 0; j < get_format_channel_count( imageInfo->format ); j++ ) + { + if( is_half_nan( e[j] ) && is_half_nan(a[j]) ) + continue; + if( e[j] != a[j] ) + err_cnt++; + } + + if( err_cnt ) + { + totalErrors++; + log_error( "ERROR: Sample %ld (%ld) did not validate! (%s)\n", i, x, mem_flag_names[mem_flag_index] ); + log_error( " Expected: 0x%04x 0x%04x 0x%04x 0x%04x\n", e[0], e[1], e[2], e[3] ); + log_error( " Actual: 0x%04x 0x%04x 0x%04x 0x%04x\n", a[0], a[1], a[2], a[3] ); + if( inputType == kFloat ) + { + float *p = (float *)(char *)imagePtr; + log_error( " Source: %a %a %a %a\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] ); + log_error( " : %12.24f %12.24f %12.24f %12.24f\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] ); + } + if( ( --numTries ) == 0 ) + return 1; + } + } + } + else + { + // Exact result passes every time + if( memcmp( resultBuffer, resultPtr, get_pixel_size( imageInfo->format ) ) != 0 ) + { + // result is inexact. Calculate error + int failure = 1; + float errors[4] = {NAN, NAN, NAN, NAN}; + pack_image_pixel_error( (float *)imagePtr, imageInfo->format, resultBuffer, errors ); + + // We are allowed 0.6 absolute error vs. infinitely precise for some normalized formats + if( 0 == forceCorrectlyRoundedWrites && + ( + imageInfo->format->image_channel_data_type == CL_UNORM_INT8 || + imageInfo->format->image_channel_data_type == CL_UNORM_INT_101010 || + imageInfo->format->image_channel_data_type == CL_UNORM_INT16 || + imageInfo->format->image_channel_data_type == CL_SNORM_INT8 || + imageInfo->format->image_channel_data_type == CL_SNORM_INT16 + )) + { + if( ! (fabsf( errors[0] ) > 0.6f) && ! (fabsf( errors[1] ) > 0.6f) && + ! (fabsf( errors[2] ) > 0.6f) && ! (fabsf( errors[3] ) > 0.6f) ) + failure = 0; + } + + + if( failure ) + { + totalErrors++; + // Is it our special rounding test? + if( verifyRounding && i >= 1 && i <= 2 ) + { + // Try to guess what the rounding mode of the device really is based on what it returned + const char *deviceRounding = "unknown"; + unsigned int deviceResults[8]; + read_image_pixel( resultPtr, imageInfo, 0, 0, 0, deviceResults, lod); + read_image_pixel( resultPtr, imageInfo, 1, 0, 0, &deviceResults[ 4 ], lod ); + + if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 4 && + deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 5 && deviceResults[ 7 ] == 5 ) + deviceRounding = "truncate"; + else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 5 && deviceResults[ 3 ] == 5 && + deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 ) + deviceRounding = "round to nearest"; + else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 5 && + deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 ) + deviceRounding = "round to even"; + + log_error( "ERROR: Rounding mode sample (%ld) did not validate, probably due to the device's rounding mode being wrong (%s)\n", i, mem_flag_names[mem_flag_index] ); + log_error( " Actual values rounded by device: %x %x %x %x %x %x %x %x\n", deviceResults[ 0 ], deviceResults[ 1 ], deviceResults[ 2 ], deviceResults[ 3 ], + deviceResults[ 4 ], deviceResults[ 5 ], deviceResults[ 6 ], deviceResults[ 7 ] ); + log_error( " Rounding mode of device appears to be %s\n", deviceRounding ); + return 1; + } + log_error( "ERROR: Sample %d (%d) did not validate!\n", (int)i, (int)x ); + switch(imageInfo->format->image_channel_data_type) + { + case CL_UNORM_INT8: + case CL_SNORM_INT8: + case CL_UNSIGNED_INT8: + case CL_SIGNED_INT8: + log_error( " Expected: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultBuffer)[0], ((cl_uchar*)resultBuffer)[1], ((cl_uchar*)resultBuffer)[2], ((cl_uchar*)resultBuffer)[3] ); + log_error( " Actual: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultPtr)[0], ((cl_uchar*)resultPtr)[1], ((cl_uchar*)resultPtr)[2], ((cl_uchar*)resultPtr)[3] ); + log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + case CL_UNORM_INT16: + case CL_SNORM_INT16: + case CL_UNSIGNED_INT16: + case CL_SIGNED_INT16: +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: +#endif + log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] ); + log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] ); + log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + case CL_HALF_FLOAT: + log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] ); + log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] ); + log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + case CL_UNSIGNED_INT32: + case CL_SIGNED_INT32: + log_error( " Expected: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultBuffer)[0], ((cl_uint*)resultBuffer)[1], ((cl_uint*)resultBuffer)[2], ((cl_uint*)resultBuffer)[3] ); + log_error( " Actual: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultPtr)[0], ((cl_uint*)resultPtr)[1], ((cl_uint*)resultPtr)[2], ((cl_uint*)resultPtr)[3] ); + break; + case CL_FLOAT: + log_error( " Expected: %a %a %a %a\n", ((cl_float*)resultBuffer)[0], ((cl_float*)resultBuffer)[1], ((cl_float*)resultBuffer)[2], ((cl_float*)resultBuffer)[3] ); + log_error( " Actual: %a %a %a %a\n", ((cl_float*)resultPtr)[0], ((cl_float*)resultPtr)[1], ((cl_float*)resultPtr)[2], ((cl_float*)resultPtr)[3] ); + log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + } + + float *v = (float *)(char *)imagePtr; + log_error( " src: %g %g %g %g\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] ); + log_error( " : %a %a %a %a\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] ); + log_error( " src: %12.24f %12.24f %12.24f %12.24f\n", v[0 ], v[ 1], v[ 2 ], v[ 3 ] ); + + if( ( --numTries ) == 0 ) + return 1; + } + } + } + imagePtr += get_explicit_type_size( inputType ) * 4; + resultPtr += get_pixel_size( imageInfo->format ); + } + } + { + nextLevelOffset += width_lod * get_pixel_size( imageInfo->format ); + width_lod = (width_lod >> 1) ? (width_lod >> 1) : 1; + } + } + } + + // All done! + return totalErrors; +} + + +int test_write_image_1D_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + clProgramWrapper program; + clKernelWrapper kernel; + const char *KernelSourcePattern = NULL; + int error; + + // Get our operating parameters + size_t maxWidth; + cl_ulong maxAllocSize, memSize; + size_t pixelSize; + + image_descriptor imageInfo = { 0x0 }; + + imageInfo.format = format; + imageInfo.slicePitch = imageInfo.arraySize = 0; + imageInfo.height = imageInfo.depth = 1; + imageInfo.type = CL_MEM_OBJECT_IMAGE1D; + pixelSize = get_pixel_size( imageInfo.format ); + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // Determine types + if( inputType == kInt ) + readFormat = "i"; + else if( inputType == kUInt ) + readFormat = "ui"; + else // kFloat + readFormat = "f"; + + // Construct the source + if(gtestTypesToRun & kWriteTests) + { + KernelSourcePattern = write1DKernelSourcePattern; + } + else + { + KernelSourcePattern = readwrite1DKernelSourcePattern; + } + + sprintf( programSrc, + KernelSourcePattern, + get_explicit_type_name( inputType ), + gTestMipmaps ? ", int lod" : "", + readFormat, + gTestMipmaps ? ", lod" :"" ); + + ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create testing kernel" ); + + // Run tests + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + + if(gTestMipmaps) + imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), d); + + if( gDebugTrace ) + log_info( " at size %d\n", (int)imageInfo.width ); + int retCode = test_write_image_1D( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format, CL_TRUE); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + if(gTestMipmaps) + imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), d); + log_info("Testing %d\n", (int)imageInfo.width); + int retCode = test_write_image_1D( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + } + else if( gTestRounding ) + { + size_t typeRange = 1 << ( get_format_type_size( imageInfo.format ) * 8 ); + imageInfo.width = typeRange / 256; + + imageInfo.rowPitch = imageInfo.width * pixelSize; + int retCode = test_write_image_1D( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, d ); + + if( gTestMipmaps) + { + imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), d); + size = (cl_ulong) compute_mipmapped_image_size(imageInfo) * 4; + } + else + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + if( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, d ); + imageInfo.rowPitch += extraWidth * pixelSize; + } + + size = (size_t)imageInfo.rowPitch * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + { + log_info( " at size %d (pitch %d) out of %d\n", (int)imageInfo.width, (int)imageInfo.rowPitch, (int)maxWidth ); + if( gTestMipmaps ) + log_info( " and %d mip levels\n", (int)imageInfo.num_mip_levels ); + } + + int retCode = test_write_image_1D( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + } + + return 0; +} diff --git a/test_conformance/images/kernel_read_write/test_write_1D_array.cpp b/test_conformance/images/kernel_read_write/test_write_1D_array.cpp new file mode 100644 index 00000000..aa9aab1f --- /dev/null +++ b/test_conformance/images/kernel_read_write/test_write_1D_array.cpp @@ -0,0 +1,723 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#if !defined(_WIN32) +#include +#endif + +#define MAX_ERR 0.005f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_filter_mode gFilterModeToSkip; +extern cl_mem_flags gMemFlagsToUse; +extern int gtestTypesToRun; + +const char *readwrite1DArrayKernelSourcePattern = +"__kernel void sample_kernel( __global %s4 *input, read_write image1d_array_t output %s)\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1);\n" +"%s" +" write_image%s( output, (int2)( tidX, tidY )%s, input[ offset ]);\n" +"}"; + +const char *write1DArrayKernelSourcePattern = +"__kernel void sample_kernel( __global %s4 *input, write_only image1d_array_t output %s)\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1);\n" +"%s" +" write_image%s( output, (int2)( tidX, tidY ) %s, input[ offset ]);\n" +"}"; + +const char *offset1DArraySource = +" int offset = tidY*get_image_width(output) + tidX;\n"; + +const char *offset1DArrayLodSource = +" int width_lod = ( get_image_width(output) >> lod ) ? ( get_image_width(output) >> lod ) : 1;\n" +" int offset = tidY*width_lod + tidX;\n"; + +int test_write_image_1D_array( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, ExplicitType inputType, MTdata d ) +{ + int totalErrors = 0; + size_t num_flags = 0; + const cl_mem_flags *mem_flag_types = NULL; + const char * *mem_flag_names = NULL; + const cl_mem_flags write_only_mem_flag_types[2] = { CL_MEM_WRITE_ONLY, CL_MEM_READ_WRITE }; + const char * write_only_mem_flag_names[2] = { "CL_MEM_WRITE_ONLY", "CL_MEM_READ_WRITE" }; + const cl_mem_flags read_write_mem_flag_types[1] = { CL_MEM_READ_WRITE}; + const char * read_write_mem_flag_names[1] = { "CL_MEM_READ_WRITE"}; + + if(gtestTypesToRun & kWriteTests) + { + mem_flag_types = write_only_mem_flag_types; + mem_flag_names = write_only_mem_flag_names; + num_flags = sizeof( write_only_mem_flag_types ) / sizeof( write_only_mem_flag_types[0] ); + } + else + { + mem_flag_types = read_write_mem_flag_types; + mem_flag_names = read_write_mem_flag_names; + num_flags = sizeof( read_write_mem_flag_types ) / sizeof( read_write_mem_flag_types[0] ); + } + + size_t pixelSize = get_pixel_size( imageInfo->format ); + + for( size_t mem_flag_index = 0; mem_flag_index < num_flags; mem_flag_index++ ) + { + int error; + size_t threads[2]; + bool verifyRounding = false; + int totalErrors = 0; + int forceCorrectlyRoundedWrites = 0; + +#if defined( __APPLE__ ) + // Require Apple's CPU implementation to be correctly rounded, not just within 0.6 + cl_device_type type = 0; + if( (error = clGetDeviceInfo( device, CL_DEVICE_TYPE, sizeof( type), &type, NULL ))) + { + log_error("Error: Could not get device type for Apple device! (%d) \n", error ); + return 1; + } + if( type == CL_DEVICE_TYPE_CPU ) + forceCorrectlyRoundedWrites = 1; +#endif + + if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) + if( DetectFloatToHalfRoundingMode(queue) ) + return 1; + + BufferOwningPtr maxImageUseHostPtrBackingStore, imageValues; + + create_random_image_data( inputType, imageInfo, imageValues, d ); + + if(!gTestMipmaps) + { + if( inputType == kFloat && imageInfo->format->image_channel_data_type != CL_FLOAT && imageInfo->format->image_channel_data_type != CL_HALF_FLOAT ) + { + /* Pilot data for sRGB images */ + if(is_sRGBA_order(imageInfo->format->image_channel_order)) + { + // We want to generate ints (mostly) in range of the target format which should be [0,255] + // However the range chosen here is [-test_range_ext, 255 + test_range_ext] so that + // it can test some out-of-range data points + const unsigned int test_range_ext = 16; + int formatMin = 0 - test_range_ext; + int formatMax = 255 + test_range_ext; + int pixel_value = 0; + + // First, fill with arbitrary floats + for( size_t y = 0; y < imageInfo->arraySize; y++ ) + { + float *inputValues = (float *)(char*)imageValues + y * imageInfo->width * 4; + for( size_t i = 0; i < imageInfo->width * 4; i++ ) + { + pixel_value = random_in_range( formatMin, (int)formatMax, d ); + inputValues[ i ] = (float)(pixel_value/255.0f); + } + } + + // Throw a few extra test values in there + float *inputValues = (float *)(char*)imageValues; + size_t i = 0; + + // Piloting some debug inputs. + inputValues[ i++ ] = -0.5f; + inputValues[ i++ ] = 0.5f; + inputValues[ i++ ] = 2.f; + inputValues[ i++ ] = 0.5f; + + // Also fill in the first few vectors with some deliberate tests to determine the rounding mode + // is correct + if( imageInfo->width > 12 ) + { + float formatMax = (float)get_format_max_int( imageInfo->format ); + inputValues[ i++ ] = 4.0f / formatMax; + inputValues[ i++ ] = 4.3f / formatMax; + inputValues[ i++ ] = 4.5f / formatMax; + inputValues[ i++ ] = 4.7f / formatMax; + inputValues[ i++ ] = 5.0f / formatMax; + inputValues[ i++ ] = 5.3f / formatMax; + inputValues[ i++ ] = 5.5f / formatMax; + inputValues[ i++ ] = 5.7f / formatMax; + } + } + else + { + // First, fill with arbitrary floats + for( size_t y = 0; y < imageInfo->arraySize; y++ ) + { + float *inputValues = (float *)(char*)imageValues + y * imageInfo->width * 4; + for( size_t i = 0; i < imageInfo->width * 4; i++ ) + inputValues[ i ] = get_random_float( -0.1f, 1.1f, d ); + } + + // Throw a few extra test values in there + float *inputValues = (float *)(char*)imageValues; + size_t i = 0; + inputValues[ i++ ] = -0.0000000000009f; + inputValues[ i++ ] = 1.f; + inputValues[ i++ ] = -1.f; + inputValues[ i++ ] = 2.f; + + // Also fill in the first few vectors with some deliberate tests to determine the rounding mode + // is correct + if( imageInfo->width > 12 ) + { + float formatMax = (float)get_format_max_int( imageInfo->format ); + inputValues[ i++ ] = 4.0f / formatMax; + inputValues[ i++ ] = 4.3f / formatMax; + inputValues[ i++ ] = 4.5f / formatMax; + inputValues[ i++ ] = 4.7f / formatMax; + inputValues[ i++ ] = 5.0f / formatMax; + inputValues[ i++ ] = 5.3f / formatMax; + inputValues[ i++ ] = 5.5f / formatMax; + inputValues[ i++ ] = 5.7f / formatMax; + verifyRounding = true; + } + } + } + else if( inputType == kUInt ) + { + unsigned int *inputValues = (unsigned int*)(char*)imageValues; + size_t i = 0; + inputValues[ i++ ] = 0; + inputValues[ i++ ] = 65535; + inputValues[ i++ ] = 7271820; + inputValues[ i++ ] = 0; + } + } + + // Construct testing sources + clProtectedImage protImage; + clMemWrapper unprotImage; + cl_mem image; + + if( gMemFlagsToUse == CL_MEM_USE_HOST_PTR ) + { + // clProtectedImage uses USE_HOST_PTR, so just rely on that for the testing (via Ian) + // Do not use protected images for max image size test since it rounds the row size to a page size + if (gTestMaxImages) { + create_random_image_data( inputType, imageInfo, maxImageUseHostPtrBackingStore, d ); + + unprotImage = create_image_1d_array( context, mem_flag_types[mem_flag_index] | CL_MEM_USE_HOST_PTR, imageInfo->format, + imageInfo->width, imageInfo->arraySize, 0, 0, + maxImageUseHostPtrBackingStore, &error ); + } else { + error = protImage.Create( context, (cl_mem_object_type)CL_MEM_OBJECT_IMAGE1D_ARRAY, mem_flag_types[mem_flag_index], imageInfo->format, imageInfo->width, 1, 1, imageInfo->arraySize ); + } + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 1D image array of size %ld x %ld pitch %ld (%s, %s)\n", imageInfo->width, imageInfo->arraySize, + imageInfo->rowPitch, IGetErrorString( error ), mem_flag_names[mem_flag_index] ); + return error; + } + + if (gTestMaxImages) + image = (cl_mem)unprotImage; + else + image = (cl_mem)protImage; + } + else // Either CL_MEM_ALLOC_HOST_PTR, CL_MEM_COPY_HOST_PTR or none + { + // Note: if ALLOC_HOST_PTR is used, the driver allocates memory that can be accessed by the host, but otherwise + // it works just as if no flag is specified, so we just do the same thing either way + // Note: if the flags is really CL_MEM_COPY_HOST_PTR, we want to remove it, because we don't want to copy any incoming data + if( gTestMipmaps ) + { + cl_image_desc image_desc = {0}; + image_desc.image_type = imageInfo->type; + image_desc.num_mip_levels = imageInfo->num_mip_levels; + image_desc.image_width = imageInfo->width; + image_desc.image_array_size = imageInfo->arraySize; + + unprotImage = clCreateImage( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ), + imageInfo->format, &image_desc, NULL, &error); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create %d level 1D image array of size %ld x %ld (%s, %s)\n", imageInfo->num_mip_levels, imageInfo->width, imageInfo->arraySize, + IGetErrorString( error ), mem_flag_names[mem_flag_index] ); + return error; + } + } + else + { + unprotImage = create_image_1d_array( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ), imageInfo->format, + imageInfo->width, imageInfo->arraySize, 0, 0, + imageValues, &error ); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 1D image array of size %ld x %ld pitch %ld (%s, %s)\n", imageInfo->width, imageInfo->arraySize, + imageInfo->rowPitch, IGetErrorString( error ), mem_flag_names[mem_flag_index] ); + return error; + } + } + image = unprotImage; + } + + error = clSetKernelArg( kernel, 1, sizeof( cl_mem ), &image ); + test_error( error, "Unable to set kernel arguments" ); + + size_t width_lod = imageInfo->width, nextLevelOffset = 0; + size_t origin[ 3 ] = { 0, 0, 0 }; + size_t region[ 3 ] = { imageInfo->width, imageInfo->arraySize, 1 }; + size_t resultSize; + + for( int lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++) + { + if(gTestMipmaps) + { + error = clSetKernelArg( kernel, 2, sizeof( int ), &lod ); + + } + // Run the kernel + threads[0] = (size_t)width_lod; + threads[1] = (size_t)imageInfo->arraySize; + + clMemWrapper inputStream; + + char *imagePtrOffset = imageValues + nextLevelOffset; + inputStream = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), + get_explicit_type_size( inputType ) * 4 * width_lod * imageInfo->arraySize, imagePtrOffset, &error ); + test_error( error, "Unable to create input buffer" ); + + // Set arguments + error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &inputStream ); + test_error( error, "Unable to set kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + // Get results + if( gTestMipmaps ) + resultSize = width_lod * get_pixel_size(imageInfo->format) * imageInfo->arraySize; + else + resultSize = imageInfo->rowPitch * imageInfo->arraySize; + + clProtectedArray PA(resultSize); + char *resultValues = (char *)((void *)PA); + + if( gDebugTrace ) + log_info( " reading results, %ld kbytes\n", (unsigned long)( resultSize / 1024 ) ); + + + origin[2] = lod; + region[0] = width_lod; + error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, + gEnablePitch ? imageInfo->rowPitch : 0, gEnablePitch ? imageInfo->slicePitch : 0, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + if( gDebugTrace ) + log_info( " results read\n" ); + + // Validate results element by element + char *imagePtr = imageValues + nextLevelOffset; + int numTries = 5; + for( size_t y = 0, i = 0; y < imageInfo->arraySize; y++ ) + { + char *resultPtr; + if( gTestMipmaps ) + resultPtr = (char *)resultValues + y * width_lod * pixelSize; + else + resultPtr = (char*)resultValues + y * imageInfo->rowPitch; + for( size_t x = 0; x < width_lod; x++, i++ ) + { + char resultBuffer[ 16 ]; // Largest format would be 4 channels * 4 bytes (32 bits) each + + // Convert this pixel + if( inputType == kFloat ) + pack_image_pixel( (float *)imagePtr, imageInfo->format, resultBuffer ); + else if( inputType == kInt ) + pack_image_pixel( (int *)imagePtr, imageInfo->format, resultBuffer ); + else // if( inputType == kUInt ) + pack_image_pixel( (unsigned int *)imagePtr, imageInfo->format, resultBuffer ); + + // Compare against the results + if(is_sRGBA_order(imageInfo->format->image_channel_order)) + { + // Compare sRGB-mapped values + cl_float expected[4] = {0}; + cl_float* input_values = (float*)imagePtr; + cl_uchar *actual = (cl_uchar*)resultPtr; + float max_err = MAX_lRGB_TO_sRGB_CONVERSION_ERROR; + float err[4] = {0.0f}; + + for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ ) + { + if(j < 3) + { + expected[j] = sRGBmap(input_values[j]); + } + else // there is no sRGB conversion for alpha component if it exists + { + expected[j] = NORMALIZE(input_values[j], 255.0f); + } + + err[j] = fabsf( expected[ j ] - actual[ j ] ); + } + + if ((err[0] > max_err) || + (err[1] > max_err) || + (err[2] > max_err) || + (err[3] > 0)) // there is no conversion for alpha so the error should be zero + { + log_error( " Error: %g %g %g %g\n", err[0], err[1], err[2], err[3]); + log_error( " Input: %g %g %g %g\n", *((float *)imagePtr), *((float *)imagePtr + 1), *((float *)imagePtr + 2), *((float *)imagePtr + 3)); + log_error( " Expected: %g %g %g %g\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] ); + log_error( " Actual: %d %d %d %d\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] ); + return 1; + } + } + else if( imageInfo->format->image_channel_data_type == CL_FLOAT ) + { + // Compare floats + float *expected = (float *)resultBuffer; + float *actual = (float *)resultPtr; + float err = 0.f; + for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ ) + err += ( expected[ j ] != 0 ) ? fabsf( ( expected[ j ] - actual[ j ] ) / expected[ j ] ) : fabsf( expected[ j ] - actual[ j ] ); + + err /= (float)get_format_channel_count( imageInfo->format ); + if( err > MAX_ERR ) + { + unsigned int *e = (unsigned int *)expected; + unsigned int *a = (unsigned int *)actual; + log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] ); + log_error( " Error: %g\n", err ); + log_error( " Expected: %a %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] ); + log_error( " Expected: %08x %08x %08x %08x\n", e[ 0 ], e[ 1 ], e[ 2 ], e[ 3 ] ); + log_error( " Actual: %a %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] ); + log_error( " Actual: %08x %08x %08x %08x\n", a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ] ); + totalErrors++; + if( ( --numTries ) == 0 ) + return 1; + } + } + else if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) + { + + // Compare half floats + if( memcmp( resultBuffer, resultPtr, 2 * get_format_channel_count( imageInfo->format ) ) != 0 ) + { + cl_ushort *e = (cl_ushort *)resultBuffer; + cl_ushort *a = (cl_ushort *)resultPtr; + int err_cnt = 0; + + //Fix up cases where we have NaNs + for( size_t j = 0; j < get_format_channel_count( imageInfo->format ); j++ ) + { + if( is_half_nan( e[j] ) && is_half_nan(a[j]) ) + continue; + if( e[j] != a[j] ) + err_cnt++; + } + + if( err_cnt ) + { + totalErrors++; + log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] ); + log_error( " Expected: 0x%04x 0x%04x 0x%04x 0x%04x\n", e[0], e[1], e[2], e[3] ); + log_error( " Actual: 0x%04x 0x%04x 0x%04x 0x%04x\n", a[0], a[1], a[2], a[3] ); + if( inputType == kFloat ) + { + float *p = (float *)(char *)imagePtr; + log_error( " Source: %a %a %a %a\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] ); + log_error( " : %12.24f %12.24f %12.24f %12.24f\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] ); + } + if( ( --numTries ) == 0 ) + return 1; + } + } + } + else + { + // Exact result passes every time + if( memcmp( resultBuffer, resultPtr, pixelSize ) != 0 ) + { + // result is inexact. Calculate error + int failure = 1; + float errors[4] = {NAN, NAN, NAN, NAN}; + pack_image_pixel_error( (float *)imagePtr, imageInfo->format, resultBuffer, errors ); + + // We are allowed 0.6 absolute error vs. infinitely precise for some normalized formats + if( 0 == forceCorrectlyRoundedWrites && + ( + imageInfo->format->image_channel_data_type == CL_UNORM_INT8 || + imageInfo->format->image_channel_data_type == CL_UNORM_INT_101010 || + imageInfo->format->image_channel_data_type == CL_UNORM_INT16 || + imageInfo->format->image_channel_data_type == CL_SNORM_INT8 || + imageInfo->format->image_channel_data_type == CL_SNORM_INT16 + )) + { + if( ! (fabsf( errors[0] ) > 0.6f) && ! (fabsf( errors[1] ) > 0.6f) && + ! (fabsf( errors[2] ) > 0.6f) && ! (fabsf( errors[3] ) > 0.6f) ) + failure = 0; + } + + + if( failure ) + { + totalErrors++; + // Is it our special rounding test? + if( verifyRounding && i >= 1 && i <= 2 ) + { + // Try to guess what the rounding mode of the device really is based on what it returned + const char *deviceRounding = "unknown"; + unsigned int deviceResults[8]; + read_image_pixel( resultPtr, imageInfo, 0, 0, 0, deviceResults, lod ); + read_image_pixel( resultPtr, imageInfo, 1, 0, 0, &deviceResults[ 4 ], lod ); + + if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 4 && + deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 5 && deviceResults[ 7 ] == 5 ) + deviceRounding = "truncate"; + else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 5 && deviceResults[ 3 ] == 5 && + deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 ) + deviceRounding = "round to nearest"; + else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 5 && + deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 ) + deviceRounding = "round to even"; + + log_error( "ERROR: Rounding mode sample (%ld) did not validate, probably due to the device's rounding mode being wrong (%s)\n", i, mem_flag_names[mem_flag_index] ); + log_error( " Actual values rounded by device: %x %x %x %x %x %x %x %x\n", deviceResults[ 0 ], deviceResults[ 1 ], deviceResults[ 2 ], deviceResults[ 3 ], + deviceResults[ 4 ], deviceResults[ 5 ], deviceResults[ 6 ], deviceResults[ 7 ] ); + log_error( " Rounding mode of device appears to be %s\n", deviceRounding ); + return 1; + } + log_error( "ERROR: Sample %d (%d,%d) did not validate!\n", (int)i, (int)x, (int)y ); + switch(imageInfo->format->image_channel_data_type) + { + case CL_UNORM_INT8: + case CL_SNORM_INT8: + case CL_UNSIGNED_INT8: + case CL_SIGNED_INT8: + log_error( " Expected: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultBuffer)[0], ((cl_uchar*)resultBuffer)[1], ((cl_uchar*)resultBuffer)[2], ((cl_uchar*)resultBuffer)[3] ); + log_error( " Actual: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultPtr)[0], ((cl_uchar*)resultPtr)[1], ((cl_uchar*)resultPtr)[2], ((cl_uchar*)resultPtr)[3] ); + log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + case CL_UNORM_INT16: + case CL_SNORM_INT16: + case CL_UNSIGNED_INT16: + case CL_SIGNED_INT16: +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: +#endif + log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] ); + log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] ); + log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + case CL_HALF_FLOAT: + log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] ); + log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] ); + log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + case CL_UNSIGNED_INT32: + case CL_SIGNED_INT32: + log_error( " Expected: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultBuffer)[0], ((cl_uint*)resultBuffer)[1], ((cl_uint*)resultBuffer)[2], ((cl_uint*)resultBuffer)[3] ); + log_error( " Actual: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultPtr)[0], ((cl_uint*)resultPtr)[1], ((cl_uint*)resultPtr)[2], ((cl_uint*)resultPtr)[3] ); + break; + case CL_FLOAT: + log_error( " Expected: %a %a %a %a\n", ((cl_float*)resultBuffer)[0], ((cl_float*)resultBuffer)[1], ((cl_float*)resultBuffer)[2], ((cl_float*)resultBuffer)[3] ); + log_error( " Actual: %a %a %a %a\n", ((cl_float*)resultPtr)[0], ((cl_float*)resultPtr)[1], ((cl_float*)resultPtr)[2], ((cl_float*)resultPtr)[3] ); + log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + } + + float *v = (float *)(char *)imagePtr; + log_error( " src: %g %g %g %g\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] ); + log_error( " : %a %a %a %a\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] ); + log_error( " src: %12.24f %12.24f %12.24f %12.24f\n", v[0 ], v[ 1], v[ 2 ], v[ 3 ] ); + + if( ( --numTries ) == 0 ) + return 1; + } + } + } + imagePtr += get_explicit_type_size( inputType ) * 4; + resultPtr += pixelSize; + } + } + { + nextLevelOffset += width_lod * imageInfo->arraySize * get_pixel_size(imageInfo->format); + width_lod = (width_lod >> 1) ? (width_lod >> 1) : 1; + } + } + } + + // All done! + return totalErrors; +} + + +int test_write_image_1D_array_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + clProgramWrapper program; + clKernelWrapper kernel; + const char *KernelSourcePattern = NULL; + int error; + + // Get our operating parameters + size_t maxWidth, maxArraySize; + cl_ulong maxAllocSize, memSize; + size_t pixelSize; + + image_descriptor imageInfo = { 0x0 }; + + imageInfo.format = format; + imageInfo.slicePitch = 0; + imageInfo.height = imageInfo.depth = 1; + imageInfo.type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + pixelSize = get_pixel_size( imageInfo.format ); + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // Determine types + if( inputType == kInt ) + readFormat = "i"; + else if( inputType == kUInt ) + readFormat = "ui"; + else // kFloat + readFormat = "f"; + + if(gtestTypesToRun & kWriteTests) + { + KernelSourcePattern = write1DArrayKernelSourcePattern; + } + else + { + KernelSourcePattern = readwrite1DArrayKernelSourcePattern; + } + // Construct the source + // Construct the source + sprintf( programSrc, + KernelSourcePattern, + get_explicit_type_name( inputType ), + gTestMipmaps ? ", int lod" : "", + gTestMipmaps ? offset1DArrayLodSource : offset1DArraySource, + readFormat, + gTestMipmaps ? ", lod" :"" ); + + ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create testing kernel" ); + + // Run tests + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch; + for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ ) + { + if(gTestMipmaps) + imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), d); + + if( gDebugTrace ) + log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize ); + int retCode = test_write_image_1D_array( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D_ARRAY, imageInfo.format, CL_TRUE); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.arraySize = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch; + if(gTestMipmaps) + imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), d); + log_info("Testing %d x %d\n", (int)imageInfo.width, (int)imageInfo.arraySize); + int retCode = test_write_image_1D_array( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + } + else if( gTestRounding ) + { + size_t typeRange = 1 << ( get_format_type_size( imageInfo.format ) * 8 ); + imageInfo.arraySize = typeRange / 256; + imageInfo.width = (size_t)( typeRange / (cl_ulong)imageInfo.arraySize ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch; + int retCode = test_write_image_1D_array( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, d ); + imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, d ); + + if( gTestMipmaps) + { + imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), d); + size = (cl_ulong) compute_mipmapped_image_size(imageInfo) * 4; + } + else + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + if( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, d ); + imageInfo.rowPitch += extraWidth * pixelSize; + } + imageInfo.slicePitch = imageInfo.rowPitch; + + size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.arraySize * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d (pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxArraySize ); + + int retCode = test_write_image_1D_array( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + } + + return 0; +} diff --git a/test_conformance/images/kernel_read_write/test_write_2D_array.cpp b/test_conformance/images/kernel_read_write/test_write_2D_array.cpp new file mode 100644 index 00000000..d46d93b8 --- /dev/null +++ b/test_conformance/images/kernel_read_write/test_write_2D_array.cpp @@ -0,0 +1,771 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#if !defined(_WIN32) +#include +#endif + +#define MAX_ERR 0.005f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_filter_mode gFilterModeToSkip; +extern cl_mem_flags gMemFlagsToUse; + +extern int gtestTypesToRun; + +extern int verify_write_results( size_t &i, int &numTries, int &totalErrors, char *&imagePtr, void *resultValues, size_t y, size_t z, + ExplicitType inputType, image_descriptor *imageInfo, bool verifyRounding ); + +// Utility function to clamp down image sizes for certain tests to avoid +// using too much memory. +static size_t reduceImageSizeRange(size_t maxDimSize) { + size_t DimSize = maxDimSize/32; + if (DimSize < (size_t) 16) + return 16; + else if (DimSize > (size_t) 128) + return 128; + else + return DimSize; +} + +static size_t reduceImageDepth(size_t maxDepth) { + size_t Depth = maxDepth/32; + if (Depth < (size_t) 8) + return 8; + else if (Depth > (size_t) 32) + return 32; + else + return Depth; +} + +const char *write2DArrayKernelSourcePattern = +"__kernel void sample_kernel( __global %s%s *input, write_only %s output %s)\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n" +"%s" +" write_image%s( output, (int4)( tidX, tidY, tidZ, 0 ) %s, input[ offset ]);\n" +"}"; + +const char *readwrite2DArrayKernelSourcePattern = +"__kernel void sample_kernel( __global %s%s *input, read_write %s output %s)\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n" +"%s" +" write_image%s( output, (int4)( tidX, tidY, tidZ, 0 ) %s, input[ offset ] );\n" +"}"; + +const char *offset2DArrayKernelSource = +" int offset = tidZ*get_image_width(output)*get_image_height(output) + tidY*get_image_width(output) + tidX;\n"; + +const char *offset2DArrayLodKernelSource = +" int width_lod = ( get_image_width(output) >> lod ) ? ( get_image_width(output) >> lod ) : 1;\n" +" int height_lod = ( get_image_height(output) >> lod ) ? ( get_image_height(output) >> lod ) : 1;\n" +" int offset = tidZ*width_lod*height_lod + tidY*width_lod + tidX;\n"; + +int test_write_image_2D_array( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, ExplicitType inputType, MTdata d ) +{ + int totalErrors = 0; + + size_t num_flags = 0; + const cl_mem_flags *mem_flag_types = NULL; + const char * *mem_flag_names = NULL; + const cl_mem_flags write_only_mem_flag_types[2] = { CL_MEM_WRITE_ONLY, CL_MEM_READ_WRITE }; + const char * write_only_mem_flag_names[2] = { "CL_MEM_WRITE_ONLY", "CL_MEM_READ_WRITE" }; + const cl_mem_flags read_write_mem_flag_types[1] = { CL_MEM_READ_WRITE}; + const char * read_write_mem_flag_names[1] = { "CL_MEM_READ_WRITE"}; + if(gtestTypesToRun & kWriteTests) + { + mem_flag_types = write_only_mem_flag_types; + mem_flag_names = write_only_mem_flag_names; + num_flags = sizeof( write_only_mem_flag_types ) / sizeof( write_only_mem_flag_types[0] ); + } + else + { + mem_flag_types = read_write_mem_flag_types; + mem_flag_names = read_write_mem_flag_names; + num_flags = sizeof( read_write_mem_flag_types ) / sizeof( read_write_mem_flag_types[0] ); + } + + size_t pixelSize = get_pixel_size( imageInfo->format ); + + for( size_t mem_flag_index = 0; mem_flag_index < num_flags; mem_flag_index++ ) + { + int error; + size_t threads[3]; + bool verifyRounding = false; + int totalErrors = 0; + int forceCorrectlyRoundedWrites = 0; + +#if defined( __APPLE__ ) + // Require Apple's CPU implementation to be correctly rounded, not just within 0.6 + cl_device_type type = 0; + if( (error = clGetDeviceInfo( device, CL_DEVICE_TYPE, sizeof( type), &type, NULL ))) + { + log_error("Error: Could not get device type for Apple device! (%d) \n", error ); + return 1; + } + if( type == CL_DEVICE_TYPE_CPU ) + forceCorrectlyRoundedWrites = 1; +#endif + + if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) + if( DetectFloatToHalfRoundingMode(queue) ) + return 1; + + BufferOwningPtr maxImageUseHostPtrBackingStore, imageValues; + + create_random_image_data( inputType, imageInfo, imageValues, d ); + + if(!gTestMipmaps) + { + if( inputType == kFloat && imageInfo->format->image_channel_data_type != CL_FLOAT ) + { + /* Pilot data for sRGB images */ + if(is_sRGBA_order(imageInfo->format->image_channel_order)) + { + // We want to generate ints (mostly) in range of the target format which should be [0,255] + // However the range chosen here is [-test_range_ext, 255 + test_range_ext] so that + // it can test some out-of-range data points + const unsigned int test_range_ext = 16; + int formatMin = 0 - test_range_ext; + int formatMax = 255 + test_range_ext; + int pixel_value = 0; + + // First, fill with arbitrary floats + for( size_t z = 0; z < imageInfo->arraySize; z++ ) + { + for( size_t y = 0; y < imageInfo->height; y++ ) + { + float *inputValues = (float *)(char*)imageValues + imageInfo->width * y * 4 + imageInfo->height * imageInfo->width * z * 4; + for( size_t i = 0; i < imageInfo->width * 4; i++ ) + { + pixel_value = random_in_range( formatMin, (int)formatMax, d ); + inputValues[ i ] = (float)(pixel_value/255.0f); + } + } + } + + // Throw a few extra test values in there + float *inputValues = (float *)(char*)imageValues; + size_t i = 0; + // Piloting some debug inputs. + inputValues[ i++ ] = -0.5f; + inputValues[ i++ ] = 0.5f; + inputValues[ i++ ] = 2.f; + inputValues[ i++ ] = 0.5f; + + // Also fill in the first few vectors with some deliberate tests to determine the rounding mode + // is correct + if( imageInfo->width > 12 ) + { + float formatMax = (float)get_format_max_int( imageInfo->format ); + inputValues[ i++ ] = 4.0f / formatMax; + inputValues[ i++ ] = 4.3f / formatMax; + inputValues[ i++ ] = 4.5f / formatMax; + inputValues[ i++ ] = 4.7f / formatMax; + inputValues[ i++ ] = 5.0f / formatMax; + inputValues[ i++ ] = 5.3f / formatMax; + inputValues[ i++ ] = 5.5f / formatMax; + inputValues[ i++ ] = 5.7f / formatMax; + } + } + else + { + // First, fill with arbitrary floats + for( size_t z = 0; z < imageInfo->arraySize; z++ ) + { + for( size_t y = 0; y < imageInfo->height; y++ ) + { + float *inputValues = (float *)(char*)imageValues + imageInfo->width * y * 4 + imageInfo->height * imageInfo->width * z * 4; + for( size_t i = 0; i < imageInfo->width * 4; i++ ) + inputValues[ i ] = get_random_float( -0.1f, 1.1f, d ); + } + } + + // Throw a few extra test values in there + float *inputValues = (float *)(char*)imageValues; + size_t i = 0; + inputValues[ i++ ] = -0.0000000000009f; + inputValues[ i++ ] = 1.f; + inputValues[ i++ ] = -1.f; + inputValues[ i++ ] = 2.f; + + // Also fill in the first few vectors with some deliberate tests to determine the rounding mode + // is correct + if( imageInfo->width > 12 ) + { + float formatMax = (float)get_format_max_int( imageInfo->format ); + inputValues[ i++ ] = 4.0f / formatMax; + inputValues[ i++ ] = 4.3f / formatMax; + inputValues[ i++ ] = 4.5f / formatMax; + inputValues[ i++ ] = 4.7f / formatMax; + inputValues[ i++ ] = 5.0f / formatMax; + inputValues[ i++ ] = 5.3f / formatMax; + inputValues[ i++ ] = 5.5f / formatMax; + inputValues[ i++ ] = 5.7f / formatMax; + verifyRounding = true; + } + } + } + else if( inputType == kUInt ) + { + unsigned int *inputValues = (unsigned int*)(char*)imageValues; + size_t i = 0; + inputValues[ i++ ] = 0; + inputValues[ i++ ] = 65535; + inputValues[ i++ ] = 7271820; + inputValues[ i++ ] = 0; + } + } + + // Construct testing sources + clProtectedImage protImage; + clMemWrapper unprotImage; + cl_mem image; + + if( gMemFlagsToUse == CL_MEM_USE_HOST_PTR ) + { + create_random_image_data( inputType, imageInfo, maxImageUseHostPtrBackingStore, d ); + + unprotImage = create_image_2d_array( context, mem_flag_types[mem_flag_index] | CL_MEM_USE_HOST_PTR, imageInfo->format, + imageInfo->width, imageInfo->height, imageInfo->arraySize, 0, 0, + maxImageUseHostPtrBackingStore, &error ); + + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 2D image array of size %ld x %ld x %ld pitch %ld (%s)\n", imageInfo->width, imageInfo->height, imageInfo->arraySize, imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + + image = (cl_mem)unprotImage; + } + else // Either CL_MEM_ALLOC_HOST_PTR, CL_MEM_COPY_HOST_PTR or none + { + // Note: if ALLOC_HOST_PTR is used, the driver allocates memory that can be accessed by the host, but otherwise + // it works just as if no flag is specified, so we just do the same thing either way + // Note: if the flags is really CL_MEM_COPY_HOST_PTR, we want to remove it, because we don't want to copy any incoming data + if( gTestMipmaps ) + { + cl_image_desc image_desc = {0}; + image_desc.image_type = imageInfo->type; + image_desc.num_mip_levels = imageInfo->num_mip_levels; + image_desc.image_width = imageInfo->width; + image_desc.image_height = imageInfo->height; + image_desc.image_array_size = imageInfo->arraySize; + + unprotImage = clCreateImage( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ), + imageInfo->format, &image_desc, NULL, &error); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create %d level 2D image array of size %ld x %ld x %ld (%s, %s)\n", imageInfo->num_mip_levels, imageInfo->width, imageInfo->height, imageInfo->arraySize, + IGetErrorString( error ), mem_flag_names[mem_flag_index] ); + return error; + } + } + else + { + unprotImage = create_image_2d_array( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ), imageInfo->format, + imageInfo->width, imageInfo->height, imageInfo->arraySize, 0, 0, imageValues, &error ); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 2D image array of size %ld x %ld x %ld pitch %ld (%s)\n", imageInfo->width, imageInfo->height, imageInfo->arraySize, imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + } + image = unprotImage; + } + + error = clSetKernelArg( kernel, 1, sizeof( cl_mem ), &image ); + test_error( error, "Unable to set kernel arguments" ); + + size_t width_lod = imageInfo->width, height_lod = imageInfo->height, nextLevelOffset = 0; + size_t origin[ 4 ] = { 0, 0, 0, 0 }; + size_t region[ 3 ] = { imageInfo->width, imageInfo->height, imageInfo->arraySize }; + size_t resultSize; + + int num_lod_loops = (gTestMipmaps)? imageInfo->num_mip_levels : 1; + for( int lod = 0; lod < num_lod_loops; lod++) + { + if(gTestMipmaps) + { + error = clSetKernelArg( kernel, 2, sizeof( int ), &lod ); + } + // Run the kernel + threads[0] = (size_t)width_lod; + threads[1] = (size_t)height_lod; + threads[2] = (size_t)imageInfo->arraySize; + + clMemWrapper inputStream; + + char *imagePtrOffset = imageValues + nextLevelOffset; + inputStream = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), + get_explicit_type_size( inputType ) * 4 * width_lod * height_lod * imageInfo->arraySize, imagePtrOffset, &error ); + test_error( error, "Unable to create input buffer" ); + + // Set arguments + error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &inputStream ); + test_error( error, "Unable to set kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 3, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + // Get results + if( gTestMipmaps ) + resultSize = width_lod * height_lod *imageInfo->arraySize * pixelSize; + else + resultSize = imageInfo->slicePitch *imageInfo->arraySize; + clProtectedArray PA(resultSize); + char *resultValues = (char *)((void *)PA); + + if( gDebugTrace ) + log_info( " reading results, %ld kbytes\n", (unsigned long)( resultSize / 1024 ) ); + + origin[3] = lod; + region[0] = width_lod; + region[1] = height_lod; + + error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, gEnablePitch ? imageInfo->rowPitch : 0, gEnablePitch ? imageInfo->slicePitch : 0, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + if( gDebugTrace ) + log_info( " results read\n" ); + + // Validate results element by element + char *imagePtr = imageValues + nextLevelOffset; + int numTries = 5; + for( size_t z = 0, i = 0; z < imageInfo->arraySize; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + char *resultPtr; + if( gTestMipmaps ) + resultPtr = (char *)resultValues + y * width_lod * pixelSize + z * width_lod * height_lod * pixelSize; + else + resultPtr = (char*)resultValues + y * imageInfo->rowPitch + z * imageInfo->slicePitch; + for( size_t x = 0; x < width_lod; x++, i++ ) + { + char resultBuffer[ 16 ]; // Largest format would be 4 channels * 4 bytes (32 bits) each + + // Convert this pixel + if( inputType == kFloat ) + pack_image_pixel( (float *)imagePtr, imageInfo->format, resultBuffer ); + else if( inputType == kInt ) + pack_image_pixel( (int *)imagePtr, imageInfo->format, resultBuffer ); + else // if( inputType == kUInt ) + pack_image_pixel( (unsigned int *)imagePtr, imageInfo->format, resultBuffer ); + + // Compare against the results + if(is_sRGBA_order(imageInfo->format->image_channel_order)) + { + // Compare sRGB-mapped values + cl_float expected[4] = {0}; + cl_float* input_values = (float*)imagePtr; + cl_uchar *actual = (cl_uchar*)resultPtr; + float max_err = MAX_lRGB_TO_sRGB_CONVERSION_ERROR; + float err[4] = {0.0f}; + + for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ ) + { + if(j < 3) + { + expected[j] = sRGBmap(input_values[j]); + } + else // there is no sRGB conversion for alpha component if it exists + { + expected[j] = NORMALIZE(input_values[j], 255.0f); + } + + err[j] = fabsf( expected[ j ] - actual[ j ] ); + } + + if ((err[0] > max_err) || + (err[1] > max_err) || + (err[2] > max_err) || + (err[3] > 0)) // there is no conversion for alpha so the error should be zero + { + log_error( " Error: %g %g %g %g\n", err[0], err[1], err[2], err[3]); + log_error( " Input: %g %g %g %g\n", *((float *)imagePtr), *((float *)imagePtr + 1), *((float *)imagePtr + 2), *((float *)imagePtr + 3)); + log_error( " Expected: %g %g %g %g\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] ); + log_error( " Actual: %d %d %d %d\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] ); + return 1; + } + } + else if( imageInfo->format->image_channel_data_type == CL_FLOAT ) + { + // Compare floats + float *expected = (float *)resultBuffer; + float *actual = (float *)resultPtr; + float err = 0.f; + for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ ) + err += ( expected[ j ] != 0 ) ? fabsf( ( expected[ j ] - actual[ j ] ) / expected[ j ] ) : fabsf( expected[ j ] - actual[ j ] ); + + err /= (float)get_format_channel_count( imageInfo->format ); + if( err > MAX_ERR ) + { + unsigned int *e = (unsigned int *)expected; + unsigned int *a = (unsigned int *)actual; + log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] ); + log_error( " Error: %g\n", err ); + log_error( " Expected: %a %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] ); + log_error( " Expected: %08x %08x %08x %08x\n", e[ 0 ], e[ 1 ], e[ 2 ], e[ 3 ] ); + log_error( " Actual: %a %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] ); + log_error( " Actual: %08x %08x %08x %08x\n", a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ] ); + totalErrors++; + if( ( --numTries ) == 0 ) + return 1; + } + } + else if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) + { + // Compare half floats + if( memcmp( resultBuffer, resultPtr, 2 * get_format_channel_count( imageInfo->format ) ) != 0 ) + { + cl_ushort *e = (cl_ushort *)resultBuffer; + cl_ushort *a = (cl_ushort *)resultPtr; + int err_cnt = 0; + + //Fix up cases where we have NaNs + for( size_t j = 0; j < get_format_channel_count( imageInfo->format ); j++ ) + { + if( is_half_nan( e[j] ) && is_half_nan(a[j]) ) + continue; + if( e[j] != a[j] ) + err_cnt++; + } + + if( err_cnt ) + { + totalErrors++; + log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] ); + unsigned short *e = (unsigned short *)resultBuffer; + unsigned short *a = (unsigned short *)resultPtr; + log_error( " Expected: 0x%04x 0x%04x 0x%04x 0x%04x\n", e[0], e[1], e[2], e[3] ); + log_error( " Actual: 0x%04x 0x%04x 0x%04x 0x%04x\n", a[0], a[1], a[2], a[3] ); + if( inputType == kFloat ) + { + float *p = (float *)(char *)imagePtr; + log_error( " Source: %a %a %a %a\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] ); + log_error( " : %12.24f %12.24f %12.24f %12.24f\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] ); + } + if( ( --numTries ) == 0 ) + return 1; + } + } + } + else + { + // Exact result passes every time + if( memcmp( resultBuffer, resultPtr, get_pixel_size( imageInfo->format ) ) != 0 ) + { + // result is inexact. Calculate error + int failure = 1; + float errors[4] = {NAN, NAN, NAN, NAN}; + pack_image_pixel_error( (float *)imagePtr, imageInfo->format, resultBuffer, errors ); + + // We are allowed 0.6 absolute error vs. infinitely precise for some normalized formats + if( 0 == forceCorrectlyRoundedWrites && + ( + imageInfo->format->image_channel_data_type == CL_UNORM_INT8 || + imageInfo->format->image_channel_data_type == CL_UNORM_INT_101010 || + imageInfo->format->image_channel_data_type == CL_UNORM_INT16 || + imageInfo->format->image_channel_data_type == CL_SNORM_INT8 || + imageInfo->format->image_channel_data_type == CL_SNORM_INT16 + )) + { + if( ! (fabsf( errors[0] ) > 0.6f) && ! (fabsf( errors[1] ) > 0.6f) && + ! (fabsf( errors[2] ) > 0.6f) && ! (fabsf( errors[3] ) > 0.6f) ) + failure = 0; + } + + + if( failure ) + { + totalErrors++; + // Is it our special rounding test? + if( verifyRounding && i >= 1 && i <= 2 ) + { + // Try to guess what the rounding mode of the device really is based on what it returned + const char *deviceRounding = "unknown"; + unsigned int deviceResults[8]; + read_image_pixel( resultPtr, imageInfo, 0, 0, 0, deviceResults, lod); + read_image_pixel( resultPtr, imageInfo, 1, 0, 0, &deviceResults[ 4 ], lod ); + + if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 4 && + deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 5 && deviceResults[ 7 ] == 5 ) + deviceRounding = "truncate"; + else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 5 && deviceResults[ 3 ] == 5 && + deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 ) + deviceRounding = "round to nearest"; + else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 5 && + deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 ) + deviceRounding = "round to even"; + + log_error( "ERROR: Rounding mode sample (%ld) did not validate, probably due to the device's rounding mode being wrong (%s)\n", i, mem_flag_names[mem_flag_index] ); + log_error( " Actual values rounded by device: %d %d %d %d %d %d %d %d\n", deviceResults[ 0 ], deviceResults[ 1 ], deviceResults[ 2 ], deviceResults[ 3 ], + deviceResults[ 4 ], deviceResults[ 5 ], deviceResults[ 6 ], deviceResults[ 7 ] ); + log_error( " Rounding mode of device appears to be %s\n", deviceRounding ); + return 1; + } + log_error( "ERROR: Sample %d (%d,%d) did not validate!\n", (int)i, (int)x, (int)y ); + switch(imageInfo->format->image_channel_data_type) + { + case CL_UNORM_INT8: + case CL_SNORM_INT8: + case CL_UNSIGNED_INT8: + case CL_SIGNED_INT8: + log_error( " Expected: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultBuffer)[0], ((cl_uchar*)resultBuffer)[1], ((cl_uchar*)resultBuffer)[2], ((cl_uchar*)resultBuffer)[3] ); + log_error( " Actual: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultPtr)[0], ((cl_uchar*)resultPtr)[1], ((cl_uchar*)resultPtr)[2], ((cl_uchar*)resultPtr)[3] ); + log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + case CL_UNORM_INT16: + case CL_SNORM_INT16: + case CL_UNSIGNED_INT16: + case CL_SIGNED_INT16: +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: +#endif + log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] ); + log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] ); + log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + case CL_HALF_FLOAT: + log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] ); + log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] ); + log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + case CL_UNSIGNED_INT32: + case CL_SIGNED_INT32: + log_error( " Expected: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultBuffer)[0], ((cl_uint*)resultBuffer)[1], ((cl_uint*)resultBuffer)[2], ((cl_uint*)resultBuffer)[3] ); + log_error( " Actual: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultPtr)[0], ((cl_uint*)resultPtr)[1], ((cl_uint*)resultPtr)[2], ((cl_uint*)resultPtr)[3] ); + break; + case CL_FLOAT: + log_error( " Expected: %a %a %a %a\n", ((cl_float*)resultBuffer)[0], ((cl_float*)resultBuffer)[1], ((cl_float*)resultBuffer)[2], ((cl_float*)resultBuffer)[3] ); + log_error( " Actual: %a %a %a %a\n", ((cl_float*)resultPtr)[0], ((cl_float*)resultPtr)[1], ((cl_float*)resultPtr)[2], ((cl_float*)resultPtr)[3] ); + log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + } + + float *v = (float *)(char *)imagePtr; + log_error( " src: %g %g %g %g\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] ); + log_error( " : %a %a %a %a\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] ); + log_error( " src: %12.24f %12.24f %12.24f %12.24f\n", v[0 ], v[ 1], v[ 2 ], v[ 3 ] ); + + if( ( --numTries ) == 0 ) + return 1; + } + } + } + imagePtr += get_explicit_type_size( inputType ) * (( imageInfo->format->image_channel_order == CL_DEPTH ) ? 1 : 4); + resultPtr += get_pixel_size( imageInfo->format ); + } + } + } + { + nextLevelOffset += width_lod*height_lod*imageInfo->arraySize*pixelSize; + width_lod = (width_lod >> 1) ? (width_lod >> 1) : 1; + height_lod = (height_lod >> 1) ? (height_lod >> 1) : 1; + } + } + } + // All done! + return totalErrors; +} + + +int test_write_image_2D_array_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + clProgramWrapper program; + clKernelWrapper kernel; + const char *KernelSourcePattern = NULL; + int error; + + // Get our operating parameters + size_t maxWidth, maxHeight, maxArraySize; + cl_ulong maxAllocSize, memSize; + + image_descriptor imageInfo = { 0x0 }; + + imageInfo.format = format; + imageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + imageInfo.depth = 1; + imageInfo.slicePitch = 0; + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 3D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // Determine types + if( inputType == kInt ) + readFormat = "i"; + else if( inputType == kUInt ) + readFormat = "ui"; + else // kFloat + readFormat = "f"; + + if(gtestTypesToRun & kWriteTests) + { + KernelSourcePattern = write2DArrayKernelSourcePattern; + } + else + { + KernelSourcePattern = readwrite2DArrayKernelSourcePattern; + } + // Construct the source + // Construct the source + sprintf( programSrc, + KernelSourcePattern, + get_explicit_type_name( inputType ), + (format->image_channel_order == CL_DEPTH) ? "" : "4", + (format->image_channel_order == CL_DEPTH) ? "image2d_array_depth_t" : "image2d_array_t", + gTestMipmaps ? " , int lod" : "", + gTestMipmaps ? offset2DArrayLodKernelSource : offset2DArrayKernelSource, + readFormat, + gTestMipmaps ? ", lod" : "" ); + + ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create testing kernel" ); + + // Run tests + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + for( imageInfo.arraySize = 2; imageInfo.arraySize < 7; imageInfo.arraySize++ ) + { + if( gTestMipmaps ) + imageInfo.num_mip_levels = (size_t) random_in_range(2, compute_max_mip_levels(imageInfo.width, imageInfo.height, 0)-1, d); + + if( gDebugTrace ) + log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize ); + int retCode = test_write_image_2D_array( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D_ARRAY, imageInfo.format, CL_TRUE); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.arraySize = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + if( gTestMipmaps ) + imageInfo.num_mip_levels = (size_t) random_in_range(2, compute_max_mip_levels(imageInfo.width, imageInfo.height, 0)-1, d); + log_info("Testing %d x %d x %d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize); + int retCode = test_write_image_2D_array( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + } + else if( gTestRounding ) + { + size_t typeRange = 1 << ( get_format_type_size( imageInfo.format ) * 8 ); + imageInfo.height = typeRange / 256; + imageInfo.width = (size_t)( typeRange / (cl_ulong)imageInfo.height ); + imageInfo.arraySize = 2; + + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + int retCode = test_write_image_2D_array( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + int maxWidthRange = (int) reduceImageSizeRange(maxWidth); + int maxHeighthRange = (int) reduceImageSizeRange(maxHeight); + int maxArraySizeRange = (int) reduceImageDepth(maxArraySize); + + cl_ulong size, buffSize; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, maxWidthRange, d ); + imageInfo.height = (size_t)random_log_in_range( 16, maxHeighthRange, d ); + imageInfo.arraySize = (size_t)random_log_in_range( 8, maxArraySizeRange, d ); + + if(gTestMipmaps) + { + imageInfo.num_mip_levels = (size_t) random_in_range(2,(compute_max_mip_levels(imageInfo.width, imageInfo.height, 0) - 1), d); + //Need to take into account the input buffer size, otherwise we will end up with input buffer that is exceeding MaxAlloc + size = 4 * compute_mipmapped_image_size(imageInfo); + buffSize = size * get_explicit_type_size( inputType ); + } + else + { + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + if( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, d ); + imageInfo.rowPitch += extraWidth * get_pixel_size( imageInfo.format ); + + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + extraWidth = (int)random_log_in_range( 0, 64, d ); + imageInfo.slicePitch += extraWidth * imageInfo.rowPitch; + } + + + // Image size and buffer size may differ due to different pixel size. + // See creation of buffer at line ~153. + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4; + buffSize = (cl_ulong)imageInfo.width * (cl_ulong)imageInfo.height * imageInfo.arraySize * get_explicit_type_size(inputType) * 4; + } + } while( size > maxAllocSize || buffSize > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %ld,%ld,%ld (pitch %ld, slice %ld) out of %ld,%ld,%ld\n", imageInfo.width, imageInfo.height, imageInfo.arraySize, + imageInfo.rowPitch, imageInfo.slicePitch, maxWidth, maxHeight, maxArraySize ); + + int retCode = test_write_image_2D_array( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + } + + return 0; +} diff --git a/test_conformance/images/kernel_read_write/test_write_3D.cpp b/test_conformance/images/kernel_read_write/test_write_3D.cpp new file mode 100644 index 00000000..e228af55 --- /dev/null +++ b/test_conformance/images/kernel_read_write/test_write_3D.cpp @@ -0,0 +1,768 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#if !defined(_WIN32) +#include +#endif + +#define MAX_ERR 0.005f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps; +extern cl_filter_mode gFilterModeToSkip; +extern cl_mem_flags gMemFlagsToUse; + +extern int gtestTypesToRun; + +extern int verify_write_results( size_t &i, int &numTries, int &totalErrors, char *&imagePtr, void *resultValues, size_t y, size_t z, + ExplicitType inputType, image_descriptor *imageInfo, bool verifyRounding ); + +// Utility function to clamp down image sizes for certain tests to avoid +// using too much memory. +static size_t reduceImageSizeRange(size_t maxDimSize, MTdata& seed) { + size_t DimSize = random_log_in_range(8, (int) maxDimSize/32, seed); + if (DimSize > (size_t) 128) + return 128; + else + return DimSize; +} + +static size_t reduceImageDepth(size_t maxDimSize, MTdata& seed) { + size_t DimSize = random_log_in_range(8, (int) maxDimSize/32, seed); + if (DimSize > (size_t) 32) + return 32; + else + return DimSize; +} + + +const char *write3DKernelSourcePattern = +"%s" +"__kernel void sample_kernel( __global %s4 *input, write_only image3d_t output %s )\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n" +"%s" +" write_image%s( output, (int4)( tidX, tidY, tidZ, 0 ) %s, input[ offset ]);\n" +"}"; + +const char *readwrite3DKernelSourcePattern = +"%s" +"__kernel void sample_kernel( __global %s4 *input, read_write image3d_t output %s )\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n" +"%s" +" write_image%s( output, (int4)( tidX, tidY, tidZ, 0 ) %s, input[ offset ]);\n" +"}"; + +const char *khr3DWritesPragma = +"#pragma OPENCL EXTENSION cl_khr_3d_image_writes : enable\n"; + +const char *offset3DSource= +" int offset = tidZ*get_image_width(output)*get_image_height(output) + tidY*get_image_width(output) + tidX;\n"; + +const char *offset3DLodSource = +" int width_lod = ( get_image_width(output) >> lod ) ? ( get_image_width(output) >> lod ) : 1;\n" +" int height_lod = ( get_image_height(output) >> lod ) ? ( get_image_height(output) >> lod ) : 1;\n" +" int offset = tidZ*width_lod*height_lod + tidY*width_lod + tidX;\n"; + +int test_write_image_3D( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, ExplicitType inputType, MTdata d ) +{ + int totalErrors = 0; + + size_t num_flags = 0; + const cl_mem_flags *mem_flag_types = NULL; + const char * *mem_flag_names = NULL; + const cl_mem_flags write_only_mem_flag_types[2] = { CL_MEM_WRITE_ONLY, CL_MEM_READ_WRITE }; + const char * write_only_mem_flag_names[2] = { "CL_MEM_WRITE_ONLY", "CL_MEM_READ_WRITE" }; + const cl_mem_flags read_write_mem_flag_types[1] = { CL_MEM_READ_WRITE}; + const char * read_write_mem_flag_names[1] = { "CL_MEM_READ_WRITE"}; + + if(gtestTypesToRun & kWriteTests) + { + mem_flag_types = write_only_mem_flag_types; + mem_flag_names = write_only_mem_flag_names; + num_flags = sizeof( write_only_mem_flag_types ) / sizeof( write_only_mem_flag_types[0] ); + } + else + { + mem_flag_types = read_write_mem_flag_types; + mem_flag_names = read_write_mem_flag_names; + num_flags = sizeof( read_write_mem_flag_types ) / sizeof( read_write_mem_flag_types[0] ); + } + + size_t pixelSize = get_pixel_size( imageInfo->format ); + + for( size_t mem_flag_index = 0; mem_flag_index < num_flags; mem_flag_index++ ) + { + int error; + size_t threads[3]; + bool verifyRounding = false; + int totalErrors = 0; + int forceCorrectlyRoundedWrites = 0; + +#if defined( __APPLE__ ) + // Require Apple's CPU implementation to be correctly rounded, not just within 0.6 + cl_device_type type = 0; + if( (error = clGetDeviceInfo( device, CL_DEVICE_TYPE, sizeof( type), &type, NULL ))) + { + log_error("Error: Could not get device type for Apple device! (%d) \n", error ); + return 1; + } + if( type == CL_DEVICE_TYPE_CPU ) + forceCorrectlyRoundedWrites = 1; +#endif + + if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) + if( DetectFloatToHalfRoundingMode(queue) ) + return 1; + + BufferOwningPtr maxImageUseHostPtrBackingStore, imageValues; + + create_random_image_data( inputType, imageInfo, imageValues, d ); + + if(!gTestMipmaps) + { + if( inputType == kFloat && imageInfo->format->image_channel_data_type != CL_FLOAT ) + { + /* Pilot data for sRGB images */ + if(is_sRGBA_order(imageInfo->format->image_channel_order)) + { + // We want to generate ints (mostly) in range of the target format which should be [0,255] + // However the range chosen here is [-test_range_ext, 255 + test_range_ext] so that + // it can test some out-of-range data points + const unsigned int test_range_ext = 16; + int formatMin = 0 - test_range_ext; + int formatMax = 255 + test_range_ext; + int pixel_value = 0; + + // First, fill with arbitrary floats + for( size_t z = 0; z < imageInfo->depth; z++ ) + { + for( size_t y = 0; y < imageInfo->height; y++ ) + { + float *inputValues = (float *)(char*)imageValues + imageInfo->width * y * 4 + imageInfo->height * imageInfo->width * z * 4; + for( size_t i = 0; i < imageInfo->width * 4; i++ ) + { + pixel_value = random_in_range( formatMin, (int)formatMax, d ); + inputValues[ i ] = (float)(pixel_value/255.0f); + } + } + } + + // Throw a few extra test values in there + float *inputValues = (float *)(char*)imageValues; + size_t i = 0; + + // Piloting some debug inputs. + inputValues[ i++ ] = -0.5f; + inputValues[ i++ ] = 0.5f; + inputValues[ i++ ] = 2.f; + inputValues[ i++ ] = 0.5f; + + // Also fill in the first few vectors with some deliberate tests to determine the rounding mode + // is correct + if( imageInfo->width > 12 ) + { + float formatMax = (float)get_format_max_int( imageInfo->format ); + inputValues[ i++ ] = 4.0f / formatMax; + inputValues[ i++ ] = 4.3f / formatMax; + inputValues[ i++ ] = 4.5f / formatMax; + inputValues[ i++ ] = 4.7f / formatMax; + inputValues[ i++ ] = 5.0f / formatMax; + inputValues[ i++ ] = 5.3f / formatMax; + inputValues[ i++ ] = 5.5f / formatMax; + inputValues[ i++ ] = 5.7f / formatMax; + } + } + else + { + // First, fill with arbitrary floats + for( size_t z = 0; z < imageInfo->depth; z++ ) + { + for( size_t y = 0; y < imageInfo->height; y++ ) + { + float *inputValues = (float *)(char*)imageValues + imageInfo->width * y * 4 + imageInfo->height * imageInfo->width * z * 4; + for( size_t i = 0; i < imageInfo->width * 4; i++ ) + inputValues[ i ] = get_random_float( -0.1f, 1.1f, d ); + } + } + + // Throw a few extra test values in there + float *inputValues = (float *)(char*)imageValues; + size_t i = 0; + inputValues[ i++ ] = -0.0000000000009f; + inputValues[ i++ ] = 1.f; + inputValues[ i++ ] = -1.f; + inputValues[ i++ ] = 2.f; + + // Also fill in the first few vectors with some deliberate tests to determine the rounding mode + // is correct + if( imageInfo->width > 12 ) + { + float formatMax = (float)get_format_max_int( imageInfo->format ); + inputValues[ i++ ] = 4.0f / formatMax; + inputValues[ i++ ] = 4.3f / formatMax; + inputValues[ i++ ] = 4.5f / formatMax; + inputValues[ i++ ] = 4.7f / formatMax; + inputValues[ i++ ] = 5.0f / formatMax; + inputValues[ i++ ] = 5.3f / formatMax; + inputValues[ i++ ] = 5.5f / formatMax; + inputValues[ i++ ] = 5.7f / formatMax; + verifyRounding = true; + } + } + } + else if( inputType == kUInt ) + { + unsigned int *inputValues = (unsigned int*)(char*)imageValues; + size_t i = 0; + inputValues[ i++ ] = 0; + inputValues[ i++ ] = 65535; + inputValues[ i++ ] = 7271820; + inputValues[ i++ ] = 0; + } + } + + // Construct testing sources + clProtectedImage protImage; + clMemWrapper unprotImage; + cl_mem image; + + if( gMemFlagsToUse == CL_MEM_USE_HOST_PTR ) + { + create_random_image_data( inputType, imageInfo, maxImageUseHostPtrBackingStore, d ); + + unprotImage = create_image_3d( context, mem_flag_types[mem_flag_index] | CL_MEM_USE_HOST_PTR, imageInfo->format, + imageInfo->width, imageInfo->height, imageInfo->depth, 0, 0, + maxImageUseHostPtrBackingStore, &error ); + + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 3D image of size %ld x %ld x %ld pitch %ld (%s)\n", imageInfo->width, imageInfo->height, imageInfo->depth, imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + + image = (cl_mem)unprotImage; + } + else // Either CL_MEM_ALLOC_HOST_PTR, CL_MEM_COPY_HOST_PTR or none + { + // Note: if ALLOC_HOST_PTR is used, the driver allocates memory that can be accessed by the host, but otherwise + // it works just as if no flag is specified, so we just do the same thing either way + // Note: if the flags is really CL_MEM_COPY_HOST_PTR, we want to remove it, because we don't want to copy any incoming data + if(gTestMipmaps) + { + cl_image_desc image_desc = {0}; + image_desc.image_type = imageInfo->type; + image_desc.num_mip_levels = imageInfo->num_mip_levels; + image_desc.image_width = imageInfo->width; + image_desc.image_height = imageInfo->height; + image_desc.image_depth = imageInfo->depth; + + unprotImage = clCreateImage( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ), + imageInfo->format, &image_desc, NULL, &error); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create %d level mipmapped 3D image of size %ld x %ld *%ld (%s, %s)\n", imageInfo->num_mip_levels, imageInfo->width, imageInfo->height, imageInfo->depth, + IGetErrorString( error ), mem_flag_names[mem_flag_index] ); + return error; + } + } + else + { + unprotImage = create_image_3d( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ), imageInfo->format, + imageInfo->width, imageInfo->height, imageInfo->depth, 0, 0, imageValues, &error ); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 3D image of size %ld x %ld x %ld pitch %ld (%s)\n", imageInfo->width, imageInfo->height, imageInfo->depth, imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + } + image = unprotImage; + } + + error = clSetKernelArg( kernel, 1, sizeof( cl_mem ), &image ); + test_error( error, "Unable to set kernel arguments" ); + + size_t width_lod = imageInfo->width; + size_t height_lod = imageInfo->height; + size_t depth_lod = imageInfo->depth; + size_t nextLevelOffset = 0; + size_t origin[ 4 ] = { 0, 0, 0, 0 }; + size_t region[ 3 ] = { imageInfo->width, imageInfo->height, imageInfo->depth }; + + int num_lod_loops = (gTestMipmaps)? imageInfo->num_mip_levels : 1; + for( int lod = 0; lod < num_lod_loops; lod++) + { + if(gTestMipmaps) + { + error = clSetKernelArg( kernel, 2, sizeof( int ), &lod ); + } + // Run the kernel + threads[0] = (size_t)width_lod; + threads[1] = (size_t)height_lod; + threads[2] = (size_t)depth_lod; + + clMemWrapper inputStream; + + char *imagePtrOffset = imageValues + nextLevelOffset; + inputStream = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), + get_explicit_type_size( inputType ) * 4 * width_lod * height_lod * depth_lod, imagePtrOffset, &error ); + test_error( error, "Unable to create input buffer" ); + + // Set arguments + error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &inputStream ); + test_error( error, "Unable to set kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 3, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + // Get results + size_t resultSize; + if(gTestMipmaps) + resultSize = width_lod * height_lod * depth_lod * pixelSize; + else + resultSize = imageInfo->slicePitch *imageInfo->depth; + clProtectedArray PA(resultSize); + char *resultValues = (char *)((void *)PA); + + if( gDebugTrace ) + log_info( " reading results, %ld kbytes\n", (unsigned long)( resultSize / 1024 ) ); + + origin[3] = lod; + region[0] = width_lod; + region[1] = height_lod; + region[2] = depth_lod; + error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, gEnablePitch ? imageInfo->rowPitch : 0, gEnablePitch ? imageInfo->slicePitch : 0, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + if( gDebugTrace ) + log_info( " results read\n" ); + + // Validate results element by element + char *imagePtr = (char*)imageValues + nextLevelOffset; + int numTries = 5; + for( size_t z = 0, i = 0; z < depth_lod; z++ ) + { + for( size_t y = 0; y < height_lod; y++ ) + { + char *resultPtr; + if( gTestMipmaps ) + resultPtr = (char *)resultValues + y * width_lod * pixelSize + z * width_lod * height_lod * pixelSize; + else + resultPtr = (char *)resultValues + y * imageInfo->rowPitch + z * imageInfo->slicePitch; + for( size_t x = 0; x < width_lod; x++, i++ ) + { + char resultBuffer[ 16 ]; // Largest format would be 4 channels * 4 bytes (32 bits) each + + // Convert this pixel + if( inputType == kFloat ) + pack_image_pixel( (float *)imagePtr, imageInfo->format, resultBuffer ); + else if( inputType == kInt ) + pack_image_pixel( (int *)imagePtr, imageInfo->format, resultBuffer ); + else // if( inputType == kUInt ) + pack_image_pixel( (unsigned int *)imagePtr, imageInfo->format, resultBuffer ); + + // Compare against the results + if(is_sRGBA_order(imageInfo->format->image_channel_order)) + { + // Compare sRGB-mapped values + cl_float expected[4] = {0}; + cl_float* input_values = (float*)imagePtr; + cl_uchar *actual = (cl_uchar*)resultPtr; + float max_err = MAX_lRGB_TO_sRGB_CONVERSION_ERROR; + float err[4] = {0.0f}; + + for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ ) + { + if(j < 3) + { + expected[j] = sRGBmap(input_values[j]); + } + else // there is no sRGB conversion for alpha component if it exists + { + expected[j] = NORMALIZE(input_values[j], 255.0f); + } + + err[j] = fabsf( expected[ j ] - actual[ j ] ); + } + + if ((err[0] > max_err) || + (err[1] > max_err) || + (err[2] > max_err) || + (err[3] > FLT_EPSILON)) // there is no conversion for alpha + { + log_error( " Error: %g %g %g %g\n", err[0], err[1], err[2], err[3]); + log_error( " Input: %g %g %g %g\n", *((float *)imagePtr), *((float *)imagePtr + 1), *((float *)imagePtr + 2), *((float *)imagePtr + 3)); + log_error( " Expected: %g %g %g %g\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] ); + log_error( " Actual: %d %d %d %d\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] ); + return 1; + } + } + else if( imageInfo->format->image_channel_data_type == CL_FLOAT ) + { + // Compare floats + float *expected = (float *)resultBuffer; + float *actual = (float *)resultPtr; + float err = 0.f; + for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ ) + err += ( expected[ j ] != 0 ) ? fabsf( ( expected[ j ] - actual[ j ] ) / expected[ j ] ) : fabsf( expected[ j ] - actual[ j ] ); + + err /= (float)get_format_channel_count( imageInfo->format ); + if( err > MAX_ERR ) + { + unsigned int *e = (unsigned int *)expected; + unsigned int *a = (unsigned int *)actual; + log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] ); + log_error( " Error: %g\n", err ); + log_error( " Expected: %a %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] ); + log_error( " Expected: %08x %08x %08x %08x\n", e[ 0 ], e[ 1 ], e[ 2 ], e[ 3 ] ); + log_error( " Actual: %a %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] ); + log_error( " Actual: %08x %08x %08x %08x\n", a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ] ); + totalErrors++; + if( ( --numTries ) == 0 ) + return 1; + } + } + else if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) + { + // Compare half floats + if( memcmp( resultBuffer, resultPtr, 2 * get_format_channel_count( imageInfo->format ) ) != 0 ) + { + cl_ushort *e = (cl_ushort *)resultBuffer; + cl_ushort *a = (cl_ushort *)resultPtr; + int err_cnt = 0; + + //Fix up cases where we have NaNs + for( size_t j = 0; j < get_format_channel_count( imageInfo->format ); j++ ) + { + if( is_half_nan( e[j] ) && is_half_nan(a[j]) ) + continue; + if( e[j] != a[j] ) + err_cnt++; + } + + if( err_cnt ) + { + totalErrors++; + log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] ); + unsigned short *e = (unsigned short *)resultBuffer; + unsigned short *a = (unsigned short *)resultPtr; + log_error( " Expected: 0x%04x 0x%04x 0x%04x 0x%04x\n", e[0], e[1], e[2], e[3] ); + log_error( " Actual: 0x%04x 0x%04x 0x%04x 0x%04x\n", a[0], a[1], a[2], a[3] ); + if( inputType == kFloat ) + { + float *p = (float *)(char *)imagePtr; + log_error( " Source: %a %a %a %a\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] ); + log_error( " : %12.24f %12.24f %12.24f %12.24f\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] ); + } + if( ( --numTries ) == 0 ) + return 1; + } + } + } + else + { + // Exact result passes every time + if( memcmp( resultBuffer, resultPtr, get_pixel_size( imageInfo->format ) ) != 0 ) + { + // result is inexact. Calculate error + int failure = 1; + float errors[4] = {NAN, NAN, NAN, NAN}; + pack_image_pixel_error( (float *)imagePtr, imageInfo->format, resultBuffer, errors ); + + // We are allowed 0.6 absolute error vs. infinitely precise for some normalized formats + if( 0 == forceCorrectlyRoundedWrites && + ( + imageInfo->format->image_channel_data_type == CL_UNORM_INT8 || + imageInfo->format->image_channel_data_type == CL_UNORM_INT_101010 || + imageInfo->format->image_channel_data_type == CL_UNORM_INT16 || + imageInfo->format->image_channel_data_type == CL_SNORM_INT8 || + imageInfo->format->image_channel_data_type == CL_SNORM_INT16 + )) + { + if( ! (fabsf( errors[0] ) > 0.6f) && ! (fabsf( errors[1] ) > 0.6f) && + ! (fabsf( errors[2] ) > 0.6f) && ! (fabsf( errors[3] ) > 0.6f) ) + failure = 0; + } + + + if( failure ) + { + totalErrors++; + // Is it our special rounding test? + if( verifyRounding && i >= 1 && i <= 2 ) + { + // Try to guess what the rounding mode of the device really is based on what it returned + const char *deviceRounding = "unknown"; + unsigned int deviceResults[8]; + read_image_pixel( resultPtr, imageInfo, 0, 0, 0, deviceResults, lod ); + read_image_pixel( resultPtr, imageInfo, 1, 0, 0, &deviceResults[ 4 ], lod ); + + if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 4 && + deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 5 && deviceResults[ 7 ] == 5 ) + deviceRounding = "truncate"; + else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 5 && deviceResults[ 3 ] == 5 && + deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 ) + deviceRounding = "round to nearest"; + else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 5 && + deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 ) + deviceRounding = "round to even"; + + log_error( "ERROR: Rounding mode sample (%ld) did not validate, probably due to the device's rounding mode being wrong (%s)\n", i, mem_flag_names[mem_flag_index] ); + log_error( " Actual values rounded by device: %d %d %d %d %d %d %d %d\n", deviceResults[ 0 ], deviceResults[ 1 ], deviceResults[ 2 ], deviceResults[ 3 ], + deviceResults[ 4 ], deviceResults[ 5 ], deviceResults[ 6 ], deviceResults[ 7 ] ); + log_error( " Rounding mode of device appears to be %s\n", deviceRounding ); + return 1; + } + log_error( "ERROR: Sample %d (%d,%d) did not validate!\n", (int)i, (int)x, (int)y ); + switch(imageInfo->format->image_channel_data_type) + { + case CL_UNORM_INT8: + case CL_SNORM_INT8: + case CL_UNSIGNED_INT8: + case CL_SIGNED_INT8: + log_error( " Expected: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultBuffer)[0], ((cl_uchar*)resultBuffer)[1], ((cl_uchar*)resultBuffer)[2], ((cl_uchar*)resultBuffer)[3] ); + log_error( " Actual: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultPtr)[0], ((cl_uchar*)resultPtr)[1], ((cl_uchar*)resultPtr)[2], ((cl_uchar*)resultPtr)[3] ); + log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + case CL_UNORM_INT16: + case CL_SNORM_INT16: + case CL_UNSIGNED_INT16: + case CL_SIGNED_INT16: +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: +#endif + log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] ); + log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] ); + log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + case CL_HALF_FLOAT: + log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] ); + log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] ); + log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + case CL_UNSIGNED_INT32: + case CL_SIGNED_INT32: + log_error( " Expected: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultBuffer)[0], ((cl_uint*)resultBuffer)[1], ((cl_uint*)resultBuffer)[2], ((cl_uint*)resultBuffer)[3] ); + log_error( " Actual: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultPtr)[0], ((cl_uint*)resultPtr)[1], ((cl_uint*)resultPtr)[2], ((cl_uint*)resultPtr)[3] ); + break; + case CL_FLOAT: + log_error( " Expected: %a %a %a %a\n", ((cl_float*)resultBuffer)[0], ((cl_float*)resultBuffer)[1], ((cl_float*)resultBuffer)[2], ((cl_float*)resultBuffer)[3] ); + log_error( " Actual: %a %a %a %a\n", ((cl_float*)resultPtr)[0], ((cl_float*)resultPtr)[1], ((cl_float*)resultPtr)[2], ((cl_float*)resultPtr)[3] ); + log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + } + + float *v = (float *)(char *)imagePtr; + log_error( " src: %g %g %g %g\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] ); + log_error( " : %a %a %a %a\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] ); + log_error( " src: %12.24f %12.24f %12.24f %12.24f\n", v[0 ], v[ 1], v[ 2 ], v[ 3 ] ); + + if( ( --numTries ) == 0 ) + return 1; + } + } + } + imagePtr += get_explicit_type_size( inputType ) * 4; + resultPtr += get_pixel_size( imageInfo->format ); + } + } + } + { + nextLevelOffset += width_lod * height_lod * depth_lod * pixelSize; + width_lod = ( width_lod >> 1 ) ? ( width_lod >> 1 ) : 1; + height_lod = ( height_lod >> 1 ) ? ( height_lod >> 1 ) : 1; + depth_lod = ( depth_lod >> 1 ) ? ( depth_lod >> 1 ) : 1; + } + } + } + // All done! + return totalErrors; +} + + +int test_write_image_3D_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + clProgramWrapper program; + clKernelWrapper kernel; + const char *KernelSourcePattern = NULL; + + int error; + + // Get our operating parameters + size_t maxWidth, maxHeight, maxDepth; + cl_ulong maxAllocSize, memSize; + + image_descriptor imageInfo = { 0x0 }; + + imageInfo.format = format; + imageInfo.type = CL_MEM_OBJECT_IMAGE3D; + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 3D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // Determine types + if( inputType == kInt ) + readFormat = "i"; + else if( inputType == kUInt ) + readFormat = "ui"; + else // kFloat + readFormat = "f"; + + if(gtestTypesToRun & kWriteTests) + { + KernelSourcePattern = write3DKernelSourcePattern; + } + else + { + KernelSourcePattern = readwrite3DKernelSourcePattern; + } + + // Construct the source + sprintf( programSrc, + KernelSourcePattern, + gTestMipmaps ? "" : khr3DWritesPragma, + get_explicit_type_name( inputType ), + gTestMipmaps ? ", int lod" : "", + gTestMipmaps ? offset3DLodSource : offset3DSource, + readFormat, + gTestMipmaps ? ", lod" : "" ); + + ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create testing kernel" ); + + // Run tests + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + for( imageInfo.depth = 2; imageInfo.depth < 7; imageInfo.depth++ ) + { + if (gTestMipmaps) + imageInfo.num_mip_levels = (size_t) random_in_range(2,(compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth) - 1), d); + + if( gDebugTrace ) + log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth ); + int retCode = test_write_image_3D( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, maxDepth, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE3D, imageInfo.format, CL_TRUE); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.depth = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + if (gTestMipmaps) + imageInfo.num_mip_levels = (size_t) random_in_range(2,(compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth) - 1), d); + log_info("Testing %d x %d x %d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth); + int retCode = test_write_image_3D( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + } + else if( gTestRounding ) + { + size_t typeRange = 1 << ( get_format_type_size( imageInfo.format ) * 8 ); + imageInfo.height = typeRange / 256; + imageInfo.width = (size_t)( typeRange / (cl_ulong)imageInfo.height ); + imageInfo.depth = 1; + + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + int retCode = test_write_image_3D( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + else + { + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = reduceImageSizeRange(maxWidth, d ); + imageInfo.height = reduceImageSizeRange(maxHeight, d ); + imageInfo.depth = reduceImageDepth(maxDepth, d ); + + if(gTestMipmaps) + { + imageInfo.num_mip_levels = (size_t) random_in_range(2,(compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth) - 1), d); + //Need to take into account the input buffer size, otherwise we will end up with input buffer that is exceeding MaxAlloc + size = 4 * compute_mipmapped_image_size(imageInfo) * get_explicit_type_size( inputType ); + } + else + { + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + if( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, d ); + imageInfo.rowPitch += extraWidth * get_pixel_size( imageInfo.format ); + + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + extraWidth = (int)random_log_in_range( 0, 64, d ); + imageInfo.slicePitch += extraWidth * imageInfo.rowPitch; + } + + size = (size_t)imageInfo.slicePitch * (size_t)imageInfo.depth * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %ld,%ld,%ld (pitch %ld, slice %ld) out of %ld,%ld,%ld\n", imageInfo.width, imageInfo.height, imageInfo.depth, + imageInfo.rowPitch, imageInfo.slicePitch, maxWidth, maxHeight, maxDepth ); + + int retCode = test_write_image_3D( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + } + + return 0; +} diff --git a/test_conformance/images/kernel_read_write/test_write_image.cpp b/test_conformance/images/kernel_read_write/test_write_image.cpp new file mode 100644 index 00000000..455098bb --- /dev/null +++ b/test_conformance/images/kernel_read_write/test_write_image.cpp @@ -0,0 +1,887 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +#if !defined(_WIN32) +#include +#endif + +#define MAX_ERR 0.005f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestImage2DFromBuffer, gTestMipmaps; +extern cl_filter_mode gFilterModeToSkip; +extern cl_mem_flags gMemFlagsToUse; +extern int gtestTypesToRun; + +extern int test_write_image_1D_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d ); +extern int test_write_image_3D_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d ); +extern int test_write_image_1D_array_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d ); +extern int test_write_image_2D_array_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d ); + + +const char *writeKernelSourcePattern = +"__kernel void sample_kernel( __global %s%s *input, write_only %s output %s)\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1);\n" +"%s" +" write_image%s( output, (int2)( tidX, tidY ) %s, input[ offset ]);\n" +"}"; + +const char *read_writeKernelSourcePattern = +"__kernel void sample_kernel( __global %s%s *input, read_write %s output %s)\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1);\n" +"%s" +" write_image%s( output, (int2)( tidX, tidY )%s, input[ offset ] );\n" +"}"; + +const char *offset2DKernelSource = +" int offset = tidY*get_image_width(output) + tidX;\n"; + +const char *offset2DLodKernelSource = +" int width_lod = ( get_image_width(output) >> lod ) ? ( get_image_width(output) >> lod ) : 1;\n" +" int offset = tidY * width_lod + tidX;\n"; + +int test_write_image( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, ExplicitType inputType, MTdata d ) +{ + int totalErrors = 0; + size_t num_flags = 0; + const cl_mem_flags *mem_flag_types = NULL; + const char * *mem_flag_names = NULL; + const cl_mem_flags write_only_mem_flag_types[2] = { CL_MEM_WRITE_ONLY, CL_MEM_READ_WRITE }; + const char * write_only_mem_flag_names[2] = { "CL_MEM_WRITE_ONLY", "CL_MEM_READ_WRITE" }; + const cl_mem_flags read_write_mem_flag_types[1] = { CL_MEM_READ_WRITE}; + const char * read_write_mem_flag_names[1] = { "CL_MEM_READ_WRITE"}; + + if(gtestTypesToRun & kWriteTests) + { + mem_flag_types = write_only_mem_flag_types; + mem_flag_names = write_only_mem_flag_names; + num_flags = sizeof( write_only_mem_flag_types ) / sizeof( write_only_mem_flag_types[0] ); + } + else + { + mem_flag_types = read_write_mem_flag_types; + mem_flag_names = read_write_mem_flag_names; + num_flags = sizeof( read_write_mem_flag_types ) / sizeof( read_write_mem_flag_types[0] ); + } + + size_t pixelSize = get_pixel_size( imageInfo->format ); + int channel_scale = (imageInfo->format->image_channel_order == CL_DEPTH) ? 1 : 4; + + for( size_t mem_flag_index = 0; mem_flag_index < num_flags; mem_flag_index++ ) + { + int error; + size_t threads[2]; + bool verifyRounding = false; + int totalErrors = 0; + int forceCorrectlyRoundedWrites = 0; + +#if defined( __APPLE__ ) + // Require Apple's CPU implementation to be correctly rounded, not just within 0.6 + cl_device_type type = 0; + if( (error = clGetDeviceInfo( device, CL_DEVICE_TYPE, sizeof( type), &type, NULL ))) + { + log_error("Error: Could not get device type for Apple device! (%d) \n", error ); + return 1; + } + if( type == CL_DEVICE_TYPE_CPU ) + forceCorrectlyRoundedWrites = 1; +#endif + + if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) + if( DetectFloatToHalfRoundingMode(queue) ) + return 1; + + BufferOwningPtr maxImageUseHostPtrBackingStore, imageValues, imageBufferValues; + + create_random_image_data( inputType, imageInfo, imageValues, d, gTestImage2DFromBuffer ); + + if(!gTestMipmaps) + { + if( inputType == kFloat && imageInfo->format->image_channel_data_type != CL_FLOAT && imageInfo->format->image_channel_data_type != CL_HALF_FLOAT ) + { + /* Pilot data for sRGB images */ + if(is_sRGBA_order(imageInfo->format->image_channel_order)) + { + // We want to generate ints (mostly) in range of the target format which should be [0,255] + // However the range chosen here is [-test_range_ext, 255 + test_range_ext] so that + // it can test some out-of-range data points + const unsigned int test_range_ext = 16; + int formatMin = 0 - test_range_ext; + int formatMax = 255 + test_range_ext; + int pixel_value = 0; + + // First, fill with arbitrary floats + for( size_t y = 0; y < imageInfo->height; y++ ) + { + float *inputValues = (float *)(char*)imageValues + imageInfo->width * y * 4; + for( size_t i = 0; i < imageInfo->width * 4; i++ ) + { + pixel_value = random_in_range( formatMin, (int)formatMax, d ); + inputValues[ i ] = (float)(pixel_value/255.0f); + } + } + + // Throw a few extra test values in there + float *inputValues = (float *)(char*)imageValues; + size_t i = 0; + + // Piloting some debug inputs. + inputValues[ i++ ] = -0.5f; + inputValues[ i++ ] = 0.5f; + inputValues[ i++ ] = 2.0f; + inputValues[ i++ ] = 0.5f; + + // Also fill in the first few vectors with some deliberate tests to determine the rounding mode + // is correct + if( imageInfo->width > 12 ) + { + float formatMax = (float)get_format_max_int( imageInfo->format ); + inputValues[ i++ ] = 4.0f / formatMax; + inputValues[ i++ ] = 4.3f / formatMax; + inputValues[ i++ ] = 4.5f / formatMax; + inputValues[ i++ ] = 4.7f / formatMax; + inputValues[ i++ ] = 5.0f / formatMax; + inputValues[ i++ ] = 5.3f / formatMax; + inputValues[ i++ ] = 5.5f / formatMax; + inputValues[ i++ ] = 5.7f / formatMax; + } + } + else + { + // First, fill with arbitrary floats + for( size_t y = 0; y < imageInfo->height; y++ ) + { + float *inputValues = (float *)(char*)imageValues + imageInfo->width * y * channel_scale; + for( size_t i = 0; i < imageInfo->width * channel_scale; i++ ) + inputValues[ i ] = get_random_float( -0.1f, 1.1f, d ); + } + + // Throw a few extra test values in there + float *inputValues = (float *)(char*)imageValues; + size_t i = 0; + inputValues[ i++ ] = -0.0000000000009f; + inputValues[ i++ ] = 1.f; + inputValues[ i++ ] = -1.f; + inputValues[ i++ ] = 2.f; + + // Also fill in the first few vectors with some deliberate tests to determine the rounding mode + // is correct + if( imageInfo->width > 12 ) + { + float formatMax = (float)get_format_max_int( imageInfo->format ); + inputValues[ i++ ] = 4.0f / formatMax; + inputValues[ i++ ] = 4.3f / formatMax; + inputValues[ i++ ] = 4.5f / formatMax; + inputValues[ i++ ] = 4.7f / formatMax; + inputValues[ i++ ] = 5.0f / formatMax; + inputValues[ i++ ] = 5.3f / formatMax; + inputValues[ i++ ] = 5.5f / formatMax; + inputValues[ i++ ] = 5.7f / formatMax; + verifyRounding = true; + } + } + } + else if( inputType == kUInt ) + { + unsigned int *inputValues = (unsigned int*)(char*)imageValues; + size_t i = 0; + inputValues[ i++ ] = 0; + inputValues[ i++ ] = 65535; + inputValues[ i++ ] = 7271820; + inputValues[ i++ ] = 0; + } + } + + // Construct testing sources + clProtectedImage protImage; + clMemWrapper unprotImage; + cl_mem image; + cl_mem imageBuffer; + + if( gMemFlagsToUse == CL_MEM_USE_HOST_PTR ) + { + if (gTestImage2DFromBuffer) + { + imageBuffer = clCreateBuffer( context, mem_flag_types[mem_flag_index] | CL_MEM_USE_HOST_PTR, + imageInfo->rowPitch * imageInfo->height, maxImageUseHostPtrBackingStore, &error); + test_error( error, "Unable to create buffer" ); + unprotImage = create_image_2d_buffer( context, mem_flag_types[mem_flag_index], imageInfo->format, + imageInfo->width, imageInfo->height, imageInfo->rowPitch, + imageBuffer, &error ); + + } + else + { + // clProtectedImage uses USE_HOST_PTR, so just rely on that for the testing (via Ian) + // Do not use protected images for max image size test since it rounds the row size to a page size + if (gTestMaxImages) { + create_random_image_data( inputType, imageInfo, maxImageUseHostPtrBackingStore, d ); + + unprotImage = create_image_2d( context, mem_flag_types[mem_flag_index] | CL_MEM_USE_HOST_PTR, imageInfo->format, + imageInfo->width, imageInfo->height, 0, + maxImageUseHostPtrBackingStore, &error ); + } else { + error = protImage.Create( context, mem_flag_types[mem_flag_index], imageInfo->format, imageInfo->width, imageInfo->height ); + } + } + if( error != CL_SUCCESS ) + { + if (gTestImage2DFromBuffer) { + clReleaseMemObject(imageBuffer); + if (error == CL_INVALID_IMAGE_FORMAT_DESCRIPTOR) { + log_info( "Format not supported for cl_khr_image2d_from_buffer skipping...\n" ); + return 0; + } + } + + log_error( "ERROR: Unable to create 2D image of size %ld x %ld pitch %ld (%s, %s)\n", imageInfo->width, imageInfo->height, + imageInfo->rowPitch, IGetErrorString( error ), mem_flag_names[mem_flag_index] ); + return error; + } + + if (gTestMaxImages || gTestImage2DFromBuffer) + image = (cl_mem)unprotImage; + else + image = (cl_mem)protImage; + } + else // Either CL_MEM_ALLOC_HOST_PTR, CL_MEM_COPY_HOST_PTR or none + { + if( gTestMipmaps ) + { + cl_image_desc image_desc = {0}; + image_desc.image_type = imageInfo->type; + image_desc.num_mip_levels = imageInfo->num_mip_levels; + image_desc.image_width = imageInfo->width; + image_desc.image_height = imageInfo->height; + + unprotImage = clCreateImage( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ), + imageInfo->format, &image_desc, NULL, &error); + if( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create %d level 2D image of size %ld x %ld (%s, %s)\n", imageInfo->num_mip_levels, imageInfo->width, imageInfo->height, + IGetErrorString( error ), mem_flag_names[mem_flag_index] ); + return error; + } + } + else if (gTestImage2DFromBuffer) + { + generate_random_image_data( imageInfo, imageBufferValues, d ); + imageBuffer = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, + imageInfo->rowPitch * imageInfo->height, imageBufferValues, &error); + test_error( error, "Unable to create buffer" ); + unprotImage = create_image_2d_buffer( context, mem_flag_types[mem_flag_index], imageInfo->format, + imageInfo->width, imageInfo->height, imageInfo->rowPitch, + imageBuffer, &error ); + + } + else + { + // Note: if ALLOC_HOST_PTR is used, the driver allocates memory that can be accessed by the host, but otherwise + // it works just as if no flag is specified, so we just do the same thing either way + // Note: if the flags is really CL_MEM_COPY_HOST_PTR, we want to remove it, because we don't want to copy any incoming data + unprotImage = create_image_2d( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ), imageInfo->format, + imageInfo->width, imageInfo->height, 0, + imageValues, &error ); + } + if( error != CL_SUCCESS ) + { + if (gTestImage2DFromBuffer) { + clReleaseMemObject(imageBuffer); + if (error == CL_INVALID_IMAGE_FORMAT_DESCRIPTOR) { + log_info( "Format not supported for cl_khr_image2d_from_buffer skipping...\n" ); + return 0; + } + } + + log_error( "ERROR: Unable to create 2D image of size %ld x %ld pitch %ld (%s, %s)\n", imageInfo->width, imageInfo->height, + imageInfo->rowPitch, IGetErrorString( error ), mem_flag_names[mem_flag_index] ); + return error; + } + image = unprotImage; + } + + error = clSetKernelArg( kernel, 1, sizeof( cl_mem ), &image ); + test_error( error, "Unable to set kernel arguments" ); + + size_t width_lod = imageInfo->width, height_lod = imageInfo->height, nextLevelOffset = 0; + size_t origin[ 3 ] = { 0, 0, 0 }; + size_t region[ 3 ] = { imageInfo->width, imageInfo->height, 1 }; + size_t resultSize; + + int num_lod_loops = (gTestMipmaps)? imageInfo->num_mip_levels : 1; + for( int lod = 0; lod < num_lod_loops; lod++) + { + if(gTestMipmaps) + { + error = clSetKernelArg( kernel, 2, sizeof( int ), &lod ); + } + // Run the kernel + threads[0] = (size_t)width_lod; + threads[1] = (size_t)height_lod; + + clMemWrapper inputStream; + + char *imagePtrOffset = imageValues + nextLevelOffset; + + inputStream = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ), + get_explicit_type_size( inputType ) * channel_scale * width_lod * height_lod, imagePtrOffset, &error ); + test_error( error, "Unable to create input buffer" ); + + // Set arguments + error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &inputStream ); + test_error( error, "Unable to set kernel arguments" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + // Get results + if( gTestMipmaps ) + resultSize = width_lod * height_lod * get_pixel_size(imageInfo->format); + else + resultSize = imageInfo->rowPitch * imageInfo->height; + clProtectedArray PA(resultSize); + char *resultValues = (char *)((void *)PA); + + if( gDebugTrace ) + log_info( " reading results, %ld kbytes\n", (unsigned long)( resultSize / 1024 ) ); + + origin[2] = lod; + region[0] = width_lod; + region[1] = height_lod; + error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, gEnablePitch ? imageInfo->rowPitch : 0, 0, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + if( gDebugTrace ) + log_info( " results read\n" ); + + // Validate results element by element + char *imagePtr = (char*)imageValues + nextLevelOffset; + int numTries = 5; + for( size_t y = 0, i = 0; y < height_lod; y++ ) + { + char *resultPtr; + if( gTestMipmaps ) + resultPtr = (char *)resultValues + y * width_lod * pixelSize; + else + resultPtr = (char*)resultValues + y * imageInfo->rowPitch; + for( size_t x = 0; x < width_lod; x++, i++ ) + { + char resultBuffer[ 16 ]; // Largest format would be 4 channels * 4 bytes (32 bits) each + + // Convert this pixel + if( inputType == kFloat ) + pack_image_pixel( (float *)imagePtr, imageInfo->format, resultBuffer ); + else if( inputType == kInt ) + pack_image_pixel( (int *)imagePtr, imageInfo->format, resultBuffer ); + else // if( inputType == kUInt ) + pack_image_pixel( (unsigned int *)imagePtr, imageInfo->format, resultBuffer ); + + // Compare against the results + if(is_sRGBA_order(imageInfo->format->image_channel_order)) + { + // Compare sRGB-mapped values + cl_float expected[4] = {0}; + cl_float* input_values = (float*)imagePtr; + cl_uchar *actual = (cl_uchar*)resultPtr; + float max_err = MAX_lRGB_TO_sRGB_CONVERSION_ERROR; + float err[4] = {0.0f}; + + for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ ) + { + if(j < 3) + { + expected[j] = sRGBmap(input_values[j]); + } + else // there is no sRGB conversion for alpha component if it exists + { + expected[j] = NORMALIZE(input_values[j], 255.0f); + } + + err[j] = fabsf( expected[ j ] - actual[ j ] ); + } + + if ((err[0] > max_err) || + (err[1] > max_err) || + (err[2] > max_err) || + (err[3] > 0)) // there is no conversion for alpha so the error should be zero + { + log_error( " Error: %g %g %g %g\n", err[0], err[1], err[2], err[3]); + log_error( " Input: %g %g %g %g\n", *((float *)imagePtr), *((float *)imagePtr + 1), *((float *)imagePtr + 2), *((float *)imagePtr + 3)); + log_error( " Expected: %g %g %g %g\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] ); + log_error( " Actual: %d %d %d %d\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] ); + return 1; + } + } + else if( imageInfo->format->image_channel_data_type == CL_FLOAT ) + { + // Compare floats + float *expected = (float *)resultBuffer; + float *actual = (float *)resultPtr; + float err = 0.f; + for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ ) + err += ( expected[ j ] != 0 ) ? fabsf( ( expected[ j ] - actual[ j ] ) / expected[ j ] ) : fabsf( expected[ j ] - actual[ j ] ); + + err /= (float)get_format_channel_count( imageInfo->format ); + if( err > MAX_ERR ) + { + unsigned int *e = (unsigned int *)expected; + unsigned int *a = (unsigned int *)actual; + log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] ); + log_error( " Error: %g\n", err ); + log_error( " Expected: %a %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] ); + log_error( " Expected: %08x %08x %08x %08x\n", e[ 0 ], e[ 1 ], e[ 2 ], e[ 3 ] ); + log_error( " Actual: %a %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] ); + log_error( " Actual: %08x %08x %08x %08x\n", a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ] ); + totalErrors++; + if( ( --numTries ) == 0 ) + return 1; + } + } + else if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT ) + { + + // Compare half floats + if( memcmp( resultBuffer, resultPtr, 2 * get_format_channel_count( imageInfo->format ) ) != 0 ) + { + cl_ushort *e = (cl_ushort *)resultBuffer; + cl_ushort *a = (cl_ushort *)resultPtr; + int err_cnt = 0; + + //Fix up cases where we have NaNs + for( size_t j = 0; j < get_format_channel_count( imageInfo->format ); j++ ) + { + if( is_half_nan( e[j] ) && is_half_nan(a[j]) ) + continue; + if( e[j] != a[j] ) + err_cnt++; + } + + if( err_cnt ) + { + totalErrors++; + log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] ); + log_error( " Expected: 0x%04x 0x%04x 0x%04x 0x%04x\n", e[0], e[1], e[2], e[3] ); + log_error( " Actual: 0x%04x 0x%04x 0x%04x 0x%04x\n", a[0], a[1], a[2], a[3] ); + if( inputType == kFloat ) + { + float *p = (float *)(char *)imagePtr; + log_error( " Source: %a %a %a %a\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] ); + log_error( " : %12.24f %12.24f %12.24f %12.24f\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] ); + } + if( ( --numTries ) == 0 ) + return 1; + } + } + } + else + { + // Exact result passes every time + if( memcmp( resultBuffer, resultPtr, get_pixel_size( imageInfo->format ) ) != 0 ) + { + // result is inexact. Calculate error + int failure = 1; + float errors[4] = {NAN, NAN, NAN, NAN}; + pack_image_pixel_error( (float *)imagePtr, imageInfo->format, resultBuffer, errors ); + + // We are allowed 0.6 absolute error vs. infinitely precise for some normalized formats + if( 0 == forceCorrectlyRoundedWrites && + ( + imageInfo->format->image_channel_data_type == CL_UNORM_INT8 || + imageInfo->format->image_channel_data_type == CL_UNORM_INT_101010 || + imageInfo->format->image_channel_data_type == CL_UNORM_INT16 || + imageInfo->format->image_channel_data_type == CL_SNORM_INT8 || + imageInfo->format->image_channel_data_type == CL_SNORM_INT16 + )) + { + if( ! (fabsf( errors[0] ) > 0.6f) && ! (fabsf( errors[1] ) > 0.6f) && + ! (fabsf( errors[2] ) > 0.6f) && ! (fabsf( errors[3] ) > 0.6f) ) + failure = 0; + } + + + if( failure ) + { + totalErrors++; + // Is it our special rounding test? + if( verifyRounding && i >= 1 && i <= 2 ) + { + // Try to guess what the rounding mode of the device really is based on what it returned + const char *deviceRounding = "unknown"; + unsigned int deviceResults[8]; + read_image_pixel( resultPtr, imageInfo, 0, 0, 0, deviceResults, lod ); + read_image_pixel( resultPtr, imageInfo, 1, 0, 0, &deviceResults[ 4 ], lod ); + + if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 4 && + deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 5 && deviceResults[ 7 ] == 5 ) + deviceRounding = "truncate"; + else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 5 && deviceResults[ 3 ] == 5 && + deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 ) + deviceRounding = "round to nearest"; + else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 5 && + deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 ) + deviceRounding = "round to even"; + + log_error( "ERROR: Rounding mode sample (%ld) did not validate, probably due to the device's rounding mode being wrong (%s)\n", i, mem_flag_names[mem_flag_index] ); + log_error( " Actual values rounded by device: %x %x %x %x %x %x %x %x\n", deviceResults[ 0 ], deviceResults[ 1 ], deviceResults[ 2 ], deviceResults[ 3 ], + deviceResults[ 4 ], deviceResults[ 5 ], deviceResults[ 6 ], deviceResults[ 7 ] ); + log_error( " Rounding mode of device appears to be %s\n", deviceRounding ); + return 1; + } + log_error( "ERROR: Sample %d (%d,%d) did not validate!\n", (int)i, (int)x, (int)y ); + switch(imageInfo->format->image_channel_data_type) + { + case CL_UNORM_INT8: + case CL_SNORM_INT8: + case CL_UNSIGNED_INT8: + case CL_SIGNED_INT8: + case CL_UNORM_INT_101010: + log_error( " Expected: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultBuffer)[0], ((cl_uchar*)resultBuffer)[1], ((cl_uchar*)resultBuffer)[2], ((cl_uchar*)resultBuffer)[3] ); + log_error( " Actual: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultPtr)[0], ((cl_uchar*)resultPtr)[1], ((cl_uchar*)resultPtr)[2], ((cl_uchar*)resultPtr)[3] ); + log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + case CL_UNORM_INT16: + case CL_SNORM_INT16: + case CL_UNSIGNED_INT16: + case CL_SIGNED_INT16: +#ifdef CL_SFIXED14_APPLE + case CL_SFIXED14_APPLE: +#endif + log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] ); + log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] ); + log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + case CL_HALF_FLOAT: + log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] ); + log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] ); + log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + case CL_UNSIGNED_INT32: + case CL_SIGNED_INT32: + log_error( " Expected: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultBuffer)[0], ((cl_uint*)resultBuffer)[1], ((cl_uint*)resultBuffer)[2], ((cl_uint*)resultBuffer)[3] ); + log_error( " Actual: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultPtr)[0], ((cl_uint*)resultPtr)[1], ((cl_uint*)resultPtr)[2], ((cl_uint*)resultPtr)[3] ); + break; + case CL_FLOAT: + log_error( " Expected: %a %a %a %a\n", ((cl_float*)resultBuffer)[0], ((cl_float*)resultBuffer)[1], ((cl_float*)resultBuffer)[2], ((cl_float*)resultBuffer)[3] ); + log_error( " Actual: %a %a %a %a\n", ((cl_float*)resultPtr)[0], ((cl_float*)resultPtr)[1], ((cl_float*)resultPtr)[2], ((cl_float*)resultPtr)[3] ); + log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] ); + break; + } + + float *v = (float *)(char *)imagePtr; + log_error( " src: %g %g %g %g\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] ); + log_error( " : %a %a %a %a\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] ); + log_error( " src: %12.24f %12.24f %12.24f %12.24f\n", v[0 ], v[ 1], v[ 2 ], v[ 3 ] ); + + if( ( --numTries ) == 0 ) + return 1; + } + } + } + imagePtr += get_explicit_type_size( inputType ) * channel_scale; + resultPtr += get_pixel_size( imageInfo->format ); + } + } + { + nextLevelOffset += width_lod * height_lod * get_pixel_size( imageInfo->format); + width_lod = (width_lod >> 1) ?(width_lod >> 1) : 1; + height_lod = (height_lod >> 1) ?(height_lod >> 1) : 1; + } + } + + if (gTestImage2DFromBuffer) clReleaseMemObject(imageBuffer); + } + + + // All done! + return totalErrors; +} + + +int test_write_image_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + clProgramWrapper program; + clKernelWrapper kernel; + const char *KernelSourcePattern = NULL; + int error; + + if (gTestImage2DFromBuffer) + { + if (format->image_channel_order == CL_RGB || format->image_channel_order == CL_RGBx) + { + switch (format->image_channel_data_type) + { + case CL_UNORM_INT8: + case CL_UNORM_INT16: + case CL_SNORM_INT8: + case CL_SNORM_INT16: + case CL_HALF_FLOAT: + case CL_FLOAT: + case CL_SIGNED_INT8: + case CL_SIGNED_INT16: + case CL_SIGNED_INT32: + case CL_UNSIGNED_INT8: + case CL_UNSIGNED_INT16: + case CL_UNSIGNED_INT32: + log_info( "Skipping image format: %s %s\n", GetChannelOrderName( format->image_channel_order ), + GetChannelTypeName( format->image_channel_data_type )); + return 0; + default: + break; + } + } + } + + // Get our operating parameters + size_t maxWidth, maxHeight; + cl_ulong maxAllocSize, memSize; + + image_descriptor imageInfo = { 0x0 }; + + imageInfo.format = format; + imageInfo.slicePitch = imageInfo.arraySize = imageInfo.depth = 0; + imageInfo.type = CL_MEM_OBJECT_IMAGE2D; + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // Determine types + if( inputType == kInt ) + readFormat = "i"; + else if( inputType == kUInt ) + readFormat = "ui"; + else // kFloat + readFormat = "f"; + + if(gtestTypesToRun & kWriteTests) + { + KernelSourcePattern = writeKernelSourcePattern; + } + else + { + KernelSourcePattern = read_writeKernelSourcePattern; + } + + // Construct the source + sprintf( programSrc, + KernelSourcePattern, + get_explicit_type_name( inputType ), + (format->image_channel_order == CL_DEPTH) ? "" : "4", + (format->image_channel_order == CL_DEPTH) ? "image2d_depth_t" : "image2d_t", + gTestMipmaps ? ", int lod" : "", + gTestMipmaps ? offset2DLodKernelSource : offset2DKernelSource, + readFormat, + gTestMipmaps ? ", lod" : "" ); + + ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create testing kernel" ); + + // Run tests + if( gTestSmallImages ) + { + for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + if( gTestMipmaps ) + imageInfo.num_mip_levels = (size_t) random_in_range(1, compute_max_mip_levels(imageInfo.width, imageInfo.height, 0)-1, d); + + if( gDebugTrace ) + log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.height ); + int retCode = test_write_image( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + } + } + else if( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D, imageInfo.format, CL_TRUE); + + for( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + if( gTestMipmaps ) + imageInfo.num_mip_levels = (size_t) random_in_range(1, compute_max_mip_levels(imageInfo.width, imageInfo.height, 0)-1, d); + log_info("Testing %d x %d\n", (int)imageInfo.width, (int)imageInfo.height); + int retCode = test_write_image( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + } + else if( gTestRounding ) + { + size_t typeRange = 1 << ( get_format_type_size( imageInfo.format ) * 8 ); + imageInfo.height = typeRange / 256; + imageInfo.width = (size_t)( typeRange / (cl_ulong)imageInfo.height ); + + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + int retCode = test_write_image( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + else + { + + cl_uint imagePitchAlign = 0; + if (gTestImage2DFromBuffer) + { +#if defined(CL_DEVICE_IMAGE_PITCH_ALIGNMENT) + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE_PITCH_ALIGNMENT, sizeof( cl_uint ), &imagePitchAlign, NULL ); + if (!imagePitchAlign) + imagePitchAlign = 1; +#endif + test_error( error, "Unable to get CL_DEVICE_IMAGE_PITCH_ALIGNMENT from device" ); + } + + for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, d ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, d ); + + if(gTestMipmaps) + { + imageInfo.num_mip_levels = (size_t) random_in_range(1, compute_max_mip_levels(imageInfo.width, imageInfo.height, 0) - 1, d); + size = 4 * compute_mipmapped_image_size(imageInfo); + } + else + { + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + if( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, d ); + imageInfo.rowPitch += extraWidth * get_pixel_size( imageInfo.format ); + } + + // if we are creating a 2D image from a buffer, make sure that the rowpitch is aligned to CL_DEVICE_IMAGE_PITCH_ALIGNMENT_APPLE + if (gTestImage2DFromBuffer) + { + size_t pitch = imagePitchAlign * get_pixel_size( imageInfo.format ); + imageInfo.rowPitch = ((imageInfo.rowPitch + pitch - 1) / pitch ) * pitch; + } + + size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.height * 4; + } + } while( size > maxAllocSize || ( size * 3 ) > memSize ); + + if( gDebugTrace ) + log_info( " at size %d,%d (pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight ); + + int retCode = test_write_image( device, context, queue, kernel, &imageInfo, inputType, d ); + if( retCode ) + return retCode; + } + } + + return 0; +} + +int test_write_image_formats( cl_device_id device, cl_image_format *formatList, bool *filterFlags, unsigned int numFormats, + image_sampler_data *imageSampler, ExplicitType inputType, cl_mem_object_type imageType ) +{ + if( imageSampler->filter_mode == CL_FILTER_LINEAR ) + // No need to run for linear filters + return 0; + + int ret = 0; + + log_info( "write_image (%s input) *****************************\n", get_explicit_type_name( inputType ) ); + + + RandomSeed seed( gRandomSeed ); + + for( unsigned int i = 0; i < numFormats; i++ ) + { + cl_image_format &imageFormat = formatList[ i ]; + + if( filterFlags[ i ] ) + continue; + + if (is_sRGBA_order(imageFormat.image_channel_order)) + { + if( !is_extension_available( device, "cl_khr_srgb_image_writes" )) + { + log_missing_feature( "-----------------------------------------------------\n" ); + log_missing_feature( "WARNING!!! sRGB formats are shown in the supported write-format list.\n"); + log_missing_feature( "However the extension cl_khr_srgb_image_writes is not available.\n"); + log_missing_feature( "Please make sure the extension is officially supported by the device .\n"); + log_missing_feature( "-----------------------------------------------------\n\n" ); + continue; + } + } + + gTestCount++; + + print_write_header( &imageFormat, false ); + int retCode; + switch (imageType) + { + case CL_MEM_OBJECT_IMAGE1D: + retCode = test_write_image_1D_set( device, &imageFormat, inputType, seed ); + break; + case CL_MEM_OBJECT_IMAGE2D: + retCode = test_write_image_set( device, &imageFormat, inputType, seed ); + break; + case CL_MEM_OBJECT_IMAGE3D: + retCode = test_write_image_3D_set( device, &imageFormat, inputType, seed ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + retCode = test_write_image_1D_array_set( device, &imageFormat, inputType, seed ); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + retCode = test_write_image_2D_array_set( device, &imageFormat, inputType, seed ); + break; + } + + if( retCode != 0 ) + { + gTestFailure++; + log_error( "FAILED: " ); + print_write_header( &imageFormat, true ); + log_info( "\n" ); + } + ret += retCode; + } + return ret; +} + + diff --git a/test_conformance/images/samplerlessReads/CMakeLists.txt b/test_conformance/images/samplerlessReads/CMakeLists.txt new file mode 100644 index 00000000..0f98f4ef --- /dev/null +++ b/test_conformance/images/samplerlessReads/CMakeLists.txt @@ -0,0 +1,24 @@ +set(MODULE_NAME SAMPLERLESS_READS) + +set(${MODULE_NAME}_SOURCES + main.cpp + test_iterations.cpp + test_loops.cpp + test_read_1D.cpp + test_read_3D.cpp + test_read_1D_buffer.cpp + test_read_1D_array.cpp + test_read_2D_array.cpp + ../../../test_common/harness/errorHelpers.c + ../../../test_common/harness/threadTesting.c + ../../../test_common/harness/kernelHelpers.c + ../../../test_common/harness/imageHelpers.cpp + ../../../test_common/harness/mt19937.c + ../../../test_common/harness/conversions.c + ../../../test_common/harness/testHarness.c + ../../../test_common/harness/typeWrappers.cpp + ../../../test_common/harness/msvc9.c + ../../../test_common/harness/parseParameters.cpp +) + +include(../../CMakeCommon.txt) diff --git a/test_conformance/images/samplerlessReads/Jamfile b/test_conformance/images/samplerlessReads/Jamfile new file mode 100644 index 00000000..cc495b35 --- /dev/null +++ b/test_conformance/images/samplerlessReads/Jamfile @@ -0,0 +1,19 @@ +project + : requirements +# gcc:-xc++ +# msvc:"/TP" + ; + +exe test_samplerless_reads + : main.cpp + test_iterations.cpp + test_loops.cpp + test_read_3D.cpp + ; + +install dist + : test_samplerless_reads + : debug:$(DIST)/debug/tests/test_conformance/images/samplerlessReads + release:$(DIST)/release/tests/test_conformance/images/samplerlessReads + ; + diff --git a/test_conformance/images/samplerlessReads/Makefile b/test_conformance/images/samplerlessReads/Makefile new file mode 100644 index 00000000..c257a11a --- /dev/null +++ b/test_conformance/images/samplerlessReads/Makefile @@ -0,0 +1,52 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.cpp \ + test_iterations.cpp \ + test_loops.cpp \ + test_read_1D.cpp \ + test_read_1D_buffer.cpp \ + test_read_1D_array.cpp \ + test_read_2D_array.cpp \ + test_read_3D.cpp \ + ../../../test_common/harness/errorHelpers.c \ + ../../../test_common/harness/threadTesting.c \ + ../../../test_common/harness/kernelHelpers.c \ + ../../../test_common/harness/imageHelpers.cpp \ + ../../../test_common/harness/conversions.c \ + ../../../test_common/harness/testHarness.c \ + ../../../test_common/harness/mt19937.c \ + ../../../test_common/harness/typeWrappers.cpp + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = +HEADERS = +TARGET = test_samplerless_reads +INCLUDE = -I../../test_common/harness +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os +CC = c++ +CXX = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/images/samplerlessReads/main.cpp b/test_conformance/images/samplerlessReads/main.cpp new file mode 100644 index 00000000..cb95dc92 --- /dev/null +++ b/test_conformance/images/samplerlessReads/main.cpp @@ -0,0 +1,303 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../../test_common/harness/compat.h" + +#include +#include + +#if !defined(_WIN32) +#include +#include +#endif + +#include "../testBase.h" +#include "../../../test_common/harness/fpcontrol.h" +#include "../../../test_common/harness/parseParameters.h" + +#if defined(__PPC__) +// Global varaiable used to hold the FPU control register state. The FPSCR register can not +// be used because not all Power implementations retain or observed the NI (non-IEEE +// mode) bit. +__thread fpu_control_t fpu_control = 0; +#endif + +bool gTestReadWrite = false; +bool gDebugTrace = false; +bool gTestMaxImages = false, gTestSmallImages = false, gTestRounding = false; +int gTypesToTest = 0; +cl_channel_type gChannelTypeToUse = (cl_channel_type)-1; +cl_channel_order gChannelOrderToUse = (cl_channel_order)-1; +bool gEnablePitch = false; +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; + +cl_command_queue queue; +cl_context context; + +#define MAX_ALLOWED_STD_DEVIATION_IN_MB 8.0 + +void printUsage( const char *execName ) +{ + const char *p = strrchr( execName, '/' ); + if ( p != NULL ) + execName = p + 1; + + log_info( "Usage: %s [options]\n", execName ); + log_info( "Where:\n" ); + log_info( "\n" ); + log_info( "\tThe following flags specify the types to test. They can be combined; if none are specified, all are tested:\n" ); + log_info( "\t\tint - Test integer I/O (read_imagei)\n" ); + log_info( "\t\tuint - Test unsigned integer I/O (read_imageui)\n" ); + log_info( "\t\tfloat - Test float I/O (read_imagef)\n" ); + log_info( "\n" ); + log_info( "You may also use appropriate CL_ channel type and ordering constants.\n" ); + log_info( "\n" ); + log_info( "\t1D - Only test 1D images\n" ); + log_info( "\t2D - Only test 2D images\n" ); + log_info( "\t3D - Only test 3D images\n" ); + log_info( "\t1Darray - Only test 1D image arrays\n" ); + log_info( "\t2Darray - Only test 2D image arrays\n" ); + log_info( "\n" ); + log_info( "\tThe following modify the types of images tested:\n" ); + log_info( "\t\read_write - Runs the tests with read_write images which allow a kernel do both read and write to the same image \n" ); + log_info( "\t\tsmall_images - Runs every format through a loop of widths 1-13 and heights 1-9, instead of random sizes\n" ); + log_info( "\t\tmax_images - Runs every format through a set of size combinations with the max values, max values - 1, and max values / 128\n" ); + log_info( "\n" ); + log_info( "\tdebug_trace - Enables additional debug info logging\n" ); + log_info( "\tuse_pitches - Enables row and slice pitches\n" ); +} + + +extern int test_image_set( cl_device_id device, cl_mem_object_type imageType ); + +int main(int argc, const char *argv[]) +{ + cl_platform_id platform; + cl_device_id device; + cl_channel_type chanType; + cl_channel_order chanOrder; + char str[ 128 ]; + int testMethods = 0; + bool randomize = false; + + test_start(); + + argc = parseCustomParam(argc, argv); + if (argc == -1) + { + test_finish(); + return -1; + } + + //Check CL_DEVICE_TYPE environment variable + checkDeviceTypeOverride( &gDeviceType ); + + // Parse arguments + for ( int i = 1; i < argc; i++ ) + { + strncpy( str, argv[ i ], sizeof( str ) - 1 ); + + if ( strcmp( str, "cpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_CPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_CPU; + else if ( strcmp( str, "gpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_GPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_GPU; + else if ( strcmp( str, "accelerator" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + else if ( strcmp( str, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_DEFAULT; + + else if ( strcmp( str, "debug_trace" ) == 0 ) + gDebugTrace = true; + else if ( strcmp( str, "read_write" ) == 0 ) + gTestReadWrite = true; + else if ( strcmp( str, "small_images" ) == 0 ) + gTestSmallImages = true; + else if ( strcmp( str, "max_images" ) == 0 ) + gTestMaxImages = true; + else if ( strcmp( str, "use_pitches" ) == 0 ) + gEnablePitch = true; + + else if ( strcmp( str, "int" ) == 0 ) + gTypesToTest |= kTestInt; + else if ( strcmp( str, "uint" ) == 0 ) + gTypesToTest |= kTestUInt; + else if ( strcmp( str, "float" ) == 0 ) + gTypesToTest |= kTestFloat; + + else if ( strcmp( str, "randomize" ) == 0 ) + randomize = true; + + else if ( strcmp( str, "1D" ) == 0 ) + testMethods |= k1D; + else if( strcmp( str, "2D" ) == 0 ) + testMethods |= k2D; + else if( strcmp( str, "3D" ) == 0 ) + testMethods |= k3D; + else if( strcmp( str, "1Darray" ) == 0 ) + testMethods |= k1DArray; + else if( strcmp( str, "2Darray" ) == 0 ) + testMethods |= k2DArray; + + else if ( strcmp( str, "help" ) == 0 || strcmp( str, "?" ) == 0 ) + { + printUsage( argv[ 0 ] ); + return -1; + } + + else if ( ( chanType = get_channel_type_from_name( str ) ) != (cl_channel_type)-1 ) + gChannelTypeToUse = chanType; + + else if ( ( chanOrder = get_channel_order_from_name( str ) ) != (cl_channel_order)-1 ) + gChannelOrderToUse = chanOrder; + else + { + log_error( "ERROR: Unknown argument %d: %s. Exiting....\n", i, str ); + return -1; + } + } + + if (testMethods == 0) + testMethods = k1D | k2D | k3D | k1DArray | k2DArray; + if ( gTypesToTest == 0 ) + gTypesToTest = kTestAllTypes; + + // Seed the random # generators + if ( randomize ) + { + gRandomSeed = (cl_uint) time( NULL ); + gReSeed = 1; + log_info( "Random seed: %u.\n", gRandomSeed ); + } + + int error; + // Get our platform + error = clGetPlatformIDs(1, &platform, NULL); + if ( error ) + { + print_error( error, "Unable to get platform" ); + test_finish(); + return -1; + } + + // Get our device + error = clGetDeviceIDs(platform, gDeviceType, 1, &device, NULL ); + if ( error ) + { + print_error( error, "Unable to get specified device" ); + test_finish(); + return -1; + } + + // Get the device type so we know if it is a GPU even if default is passed in. + error = clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(gDeviceType), &gDeviceType, NULL); + if ( error ) + { + print_error( error, "Unable to get device type" ); + test_finish(); + return -1; + } + + + if ( printDeviceHeader( device ) != CL_SUCCESS ) + { + test_finish(); + return -1; + } + + // Check for image support + if (checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) { + log_info("Device does not support images. Skipping test.\n"); + test_finish(); + return 0; + } + + // Create a context to test with + context = clCreateContext( NULL, 1, &device, notify_callback, NULL, &error ); + if ( error != CL_SUCCESS ) + { + print_error( error, "Unable to create testing context" ); + test_finish(); + return -1; + } + + // Create a queue against the context + queue = clCreateCommandQueueWithProperties( context, device, 0, &error ); + if ( error != CL_SUCCESS ) + { + print_error( error, "Unable to create testing command queue" ); + test_finish(); + return -1; + } + + if ( gTestSmallImages ) + log_info( "Note: Using small test images\n" ); + + // On most platforms which support denorm, default is FTZ off. However, + // on some hardware where the reference is computed, default might be flush denorms to zero e.g. arm. + // This creates issues in result verification. Since spec allows the implementation to either flush or + // not flush denorms to zero, an implementation may choose not to flush i.e. return denorm result whereas + // reference result may be zero (flushed denorm). Hence we need to disable denorm flushing on host side + // where reference is being computed to make sure we get non-flushed reference result. If implementation + // returns flushed result, we correctly take care of that in verification code. + + FPU_mode_type oldMode; + DisableFTZ(&oldMode); + + // Run the test now + int ret = 0; + if (testMethods & k1D) { + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE1D ); + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE1D_BUFFER ); + } + if (testMethods & k2D) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE2D ); + if (testMethods & k3D) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE3D ); + if (testMethods & k1DArray) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE1D_ARRAY ); + if (testMethods & k2DArray) + ret += test_image_set( device, CL_MEM_OBJECT_IMAGE2D_ARRAY ); + + // Restore FP state before leaving + RestoreFPState(&oldMode); + + error = clFinish(queue); + if (error) + print_error(error, "clFinish failed."); + + clReleaseContext(context); + clReleaseCommandQueue(queue); + + if (gTestFailure == 0) { + if (gTestCount > 1) + log_info("PASSED %d of %d tests.\n", gTestCount, gTestCount); + else + log_info("PASSED test.\n"); + } + else if (gTestFailure > 0) { + if (gTestCount > 1) + log_error("FAILED %d of %d tests.\n", gTestFailure, gTestCount); + else + log_error("FAILED test.\n"); + } + + // Clean up + test_finish(); + + if (gTestFailure > 0) + return gTestFailure; + + return ret; +} diff --git a/test_conformance/images/samplerlessReads/test_iterations.cpp b/test_conformance/images/samplerlessReads/test_iterations.cpp new file mode 100644 index 00000000..185023de --- /dev/null +++ b/test_conformance/images/samplerlessReads/test_iterations.cpp @@ -0,0 +1,337 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" +#include + +#if defined( __APPLE__ ) + #include + #include + #include +#endif + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding; +extern cl_device_type gDeviceType; +extern bool gTestReadWrite; + +#define MAX_TRIES 1 +#define MAX_CLAMPED 1 + +const char *read2DKernelSourcePattern = +"__kernel void sample_kernel( read_only %s input, sampler_t sampler, __global int *results )\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1);\n" +" int offset = tidY*get_image_width(input) + tidX;\n" +" int2 coords = (int2)(tidX, tidY);\n" +" %s clr = read_image%s( input, coords );\n" +" int4 test = (clr != read_image%s( input, sampler, coords ));\n" +" if ( test.x || test.y || test.z || test.w )\n" +" results[offset] = -1;\n" +" else\n" +" results[offset] = 0;\n" +"}"; + + +const char *read_write2DKernelSourcePattern = +"__kernel void sample_kernel( read_only %s read_only_image, read_write %s read_write_image, sampler_t sampler, __global int *results )\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1);\n" +" int offset = tidY*get_image_width(read_only_image) + tidX;\n" +" int2 coords = (int2)(tidX, tidY);\n" +" %s clr = read_image%s( read_only_image, sampler, coords );\n" +" write_image%s(read_write_image, coords, clr);\n" +" atomic_work_item_fence(CLK_IMAGE_MEM_FENCE, memory_order_acq_rel, memory_scope_work_item);\n" +" int4 test = (clr != read_image%s( read_write_image, coords ));\n" +" if ( test.x || test.y || test.z || test.w )\n" +" results[offset] = -1;\n" +" else\n" +" results[offset] = 0;\n" +"}"; +int test_read_image_2D( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, image_sampler_data *imageSampler, + ExplicitType outputType, MTdata d ) +{ + int error; + size_t threads[2]; + cl_sampler actualSampler; + + // generate_random_image_data allocates with malloc, so we use a MallocDataBuffer here + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + if ( gDebugTrace ) + log_info( " - Creating image %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height ); + + // Construct testing sources + cl_mem read_only_image, read_write_image; + cl_image_desc image_desc; + + memset(&image_desc, 0x0, sizeof(cl_image_desc)); + image_desc.image_type = CL_MEM_OBJECT_IMAGE2D; + image_desc.image_width = imageInfo->width; + image_desc.image_height = imageInfo->height; + image_desc.image_row_pitch = ( gEnablePitch ? imageInfo->rowPitch : 0 ); + image_desc.num_mip_levels = 0; + read_only_image = clCreateImage( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, imageInfo->format, + &image_desc, imageValues, &error ); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 2D read_only image of size %d x %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + + if(gTestReadWrite) + { + read_write_image = clCreateImage(context, + CL_MEM_READ_WRITE, + imageInfo->format, + &image_desc, + NULL, + &error ); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create 2D read_write image of size %d x %d pitch %d (%s)\n", + (int)imageInfo->width, + (int)imageInfo->height, + (int)imageInfo->rowPitch, + IGetErrorString( error ) ); + return error; + } + } + + if ( gDebugTrace ) + log_info( " - Creating kernel arguments...\n" ); + + // Create sampler to use + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_NONE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + actualSampler = clCreateSamplerWithProperties( context, properties, &error ); + test_error( error, "Unable to create image sampler" ); + + // Create results buffer + cl_mem results = clCreateBuffer( context, 0, imageInfo->width * imageInfo->height * sizeof(cl_int), NULL, &error); + test_error( error, "Unable to create results buffer" ); + + size_t resultValuesSize = imageInfo->width * imageInfo->height * sizeof(cl_int); + BufferOwningPtr resultValues(malloc( resultValuesSize )); + memset( resultValues, 0xff, resultValuesSize ); + clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + + // Set arguments + int idx = 0; + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_only_image ); + test_error( error, "Unable to set kernel arguments" ); + if(gTestReadWrite) + { + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_write_image ); + test_error( error, "Unable to set kernel arguments" ); + } + error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results ); + test_error( error, "Unable to set kernel arguments" ); + + // Run the kernel + threads[0] = (size_t)imageInfo->width; + threads[1] = (size_t)imageInfo->height; + error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + if ( gDebugTrace ) + log_info( " reading results, %ld kbytes\n", (unsigned long)( imageInfo->width * imageInfo->height * sizeof(cl_int) / 1024 ) ); + + error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + if ( gDebugTrace ) + log_info( " results read\n" ); + + // Check for non-zero comps + bool allZeroes = true; + for ( size_t ic = 0; ic < imageInfo->width * imageInfo->height; ++ic ) + { + if ( resultValues[ic] ) { + allZeroes = false; + break; + } + } + if ( !allZeroes ) + { + log_error( " Sampler-less reads differ from reads with sampler.\n" ); + return -1; + } + + clReleaseSampler(actualSampler); + clReleaseMemObject(results); + clReleaseMemObject(read_only_image); + if(gTestReadWrite) + { + clReleaseMemObject(read_write_image); + } + + return 0; +} + +int test_read_image_set_2D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, + ExplicitType outputType ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + const char *dataType; + clProgramWrapper program; + clKernelWrapper kernel; + RandomSeed seed( gRandomSeed ); + int error; + + // Get our operating params + size_t maxWidth, maxHeight; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + size_t pixelSize; + + imageInfo.format = format; + imageInfo.depth = imageInfo.arraySize = imageInfo.slicePitch = 0; + imageInfo.type = CL_MEM_OBJECT_IMAGE2D; + pixelSize = get_pixel_size( imageInfo.format ); + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // Determine types + if ( outputType == kInt ) + { + readFormat = "i"; + dataType = "int4"; + } + else if ( outputType == kUInt ) + { + readFormat = "ui"; + dataType = "uint4"; + } + else // kFloat + { + readFormat = "f"; + dataType = (format->image_channel_order == CL_DEPTH) ? "float" : "float4"; + } + + if(gTestReadWrite) + { + sprintf(programSrc, + read_write2DKernelSourcePattern, + (format->image_channel_order == CL_DEPTH) ? "image2d_depth_t" : "image2d_t", + (format->image_channel_order == CL_DEPTH) ? "image2d_depth_t" : "image2d_t", + dataType, + readFormat, + readFormat, + readFormat); + } + else + { + sprintf(programSrc, + read2DKernelSourcePattern, + (format->image_channel_order == CL_DEPTH) ? "image2d_depth_t" : "image2d_t", + dataType, + readFormat, + readFormat ); + } + + ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create testing kernel" ); + + if ( gTestSmallImages ) + { + for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + for ( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + if ( gDebugTrace ) + log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.height ); + + int retCode = test_read_image_2D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + } + else if ( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D, imageInfo.format); + + for ( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + log_info("Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ]); + if ( gDebugTrace ) + log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] ); + int retCode = test_read_image_2D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + else + { + for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + if ( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth * pixelSize; + } + + size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.height * 4; + } while ( size > maxAllocSize || ( size * 3 ) > memSize ); + + if ( gDebugTrace ) + log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight ); + int retCode = test_read_image_2D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + + return 0; +} diff --git a/test_conformance/images/samplerlessReads/test_loops.cpp b/test_conformance/images/samplerlessReads/test_loops.cpp new file mode 100644 index 00000000..7d1b8fc1 --- /dev/null +++ b/test_conformance/images/samplerlessReads/test_loops.cpp @@ -0,0 +1,305 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" + +extern cl_context context; +extern int gTypesToTest; +extern cl_channel_type gChannelTypeToUse; +extern cl_channel_order gChannelOrderToUse; + +extern bool gDebugTrace; + +extern bool gTestReadWrite; + +extern int test_read_image_set_1D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType ); +extern int test_read_image_set_1D_buffer( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType ); +extern int test_read_image_set_2D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType ); +extern int test_read_image_set_3D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType ); +extern int test_read_image_set_1D_array( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType ); +extern int test_read_image_set_2D_array( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType ); + +static const char *str_1d_image = "1D"; +static const char *str_2d_image = "2D"; +static const char *str_3d_image = "3D"; +static const char *str_1d_image_array = "1D array"; +static const char *str_2d_image_array = "2D array"; +static const char *str_1d_image_buffer = "1D image buffer"; + +static const char *convert_image_type_to_string(cl_mem_object_type imageType) +{ + const char *p; + switch (imageType) + { + case CL_MEM_OBJECT_IMAGE1D: + p = str_1d_image; + break; + case CL_MEM_OBJECT_IMAGE2D: + p = str_2d_image; + break; + case CL_MEM_OBJECT_IMAGE3D: + p = str_3d_image; + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + p = str_1d_image_array; + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + p = str_2d_image_array; + break; + case CL_MEM_OBJECT_IMAGE1D_BUFFER: + p = str_1d_image_buffer; + } + return p; +} + + +int filter_formats( cl_image_format *formatList, bool *filterFlags, unsigned int formatCount, cl_channel_type *channelDataTypesToFilter ) +{ + int numSupported = 0; + for ( unsigned int j = 0; j < formatCount; j++ ) + { + // If this format has been previously filtered, remove the filter + if ( filterFlags[ j ] ) + filterFlags[ j ] = false; + + // Have we already discarded the channel type via the command line? + if ( gChannelTypeToUse != (cl_channel_type)-1 && gChannelTypeToUse != formatList[ j ].image_channel_data_type ) + { + filterFlags[ j ] = true; + continue; + } + + // Have we already discarded the channel order via the command line? + if ( gChannelOrderToUse != (cl_channel_order)-1 && gChannelOrderToUse != formatList[ j ].image_channel_order ) + { + filterFlags[ j ] = true; + continue; + } + + // Is given format standard channel order and type given by spec. We don't want to test it if this is vendor extension + if( !IsChannelOrderSupported( formatList[ j ].image_channel_order ) || !IsChannelTypeSupported( formatList[ j ].image_channel_data_type ) ) + { + filterFlags[ j ] = true; + continue; + } + + // We don't filter by channel type + if( !channelDataTypesToFilter ) + { + numSupported++; + continue; + } + + // Is the format supported? + int i; + for ( i = 0; channelDataTypesToFilter[ i ] != (cl_channel_type)-1; i++ ) + { + if ( formatList[ j ].image_channel_data_type == channelDataTypesToFilter[ i ] ) + { + numSupported++; + break; + } + } + if ( channelDataTypesToFilter[ i ] == (cl_channel_type)-1 ) + { + // Format is NOT supported, so mark it as such + filterFlags[ j ] = true; + } + } + return numSupported; +} + +int get_format_list( cl_device_id device, cl_mem_object_type imageType, cl_image_format * &outFormatList, unsigned int &outFormatCount, cl_mem_flags flags ) +{ + int error; + + cl_image_format tempList[ 128 ]; + error = clGetSupportedImageFormats( context, flags, + imageType, 128, tempList, &outFormatCount ); + test_error( error, "Unable to get count of supported image formats" ); + + outFormatList = new cl_image_format[ outFormatCount ]; + error = clGetSupportedImageFormats( context, flags, + imageType, outFormatCount, outFormatList, NULL ); + test_error( error, "Unable to get list of supported image formats" ); + + return 0; +} + +int test_read_image_type( cl_device_id device, cl_image_format *format, + image_sampler_data *imageSampler, ExplicitType outputType, cl_mem_object_type imageType ) +{ + int ret = 0; + imageSampler->addressing_mode = CL_ADDRESS_NONE; + + print_read_header( format, imageSampler, false ); + + gTestCount++; + + switch (imageType) + { + case CL_MEM_OBJECT_IMAGE1D: + ret = test_read_image_set_1D( device, format, imageSampler, outputType ); + break; + case CL_MEM_OBJECT_IMAGE1D_BUFFER: + ret += test_read_image_set_1D_buffer( device, format, imageSampler, outputType ); + break; + case CL_MEM_OBJECT_IMAGE2D: + ret = test_read_image_set_2D( device, format, imageSampler, outputType ); + break; + case CL_MEM_OBJECT_IMAGE3D: + ret = test_read_image_set_3D( device, format, imageSampler, outputType ); + break; + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + ret = test_read_image_set_1D_array( device, format, imageSampler, outputType ); + break; + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + ret = test_read_image_set_2D_array( device, format, imageSampler, outputType ); + break; + } + + if ( ret != 0 ) + { + gTestFailure++; + log_error( "FAILED: " ); + print_read_header( format, imageSampler, true ); + log_info( "\n" ); + } + return ret; +} + +int test_read_image_formats( cl_device_id device, cl_image_format *formatList, bool *filterFlags, unsigned int numFormats, + image_sampler_data *imageSampler, ExplicitType outputType, cl_mem_object_type imageType ) +{ + int ret = 0; + imageSampler->normalized_coords = false; + log_info( "read_image (%s coords, %s results) *****************************\n", + "integer", get_explicit_type_name( outputType ) ); + + for ( unsigned int i = 0; i < numFormats; i++ ) + { + if ( filterFlags[i] ) + continue; + + cl_image_format &imageFormat = formatList[ i ]; + + ret |= test_read_image_type( device, &imageFormat, imageSampler, outputType, imageType ); + } + return ret; +} + + +int test_image_set( cl_device_id device, cl_mem_object_type imageType ) +{ + int ret = 0; + static int printedFormatList = -1; + + // Grab the list of supported image formats + cl_image_format *formatList; + bool *filterFlags; + unsigned int numFormats; + + // This flag is only for querying the list of supported formats + // The flag for creating image will be set explicitly in test functions + cl_mem_flags flags = (gTestReadWrite)? CL_MEM_KERNEL_READ_AND_WRITE : CL_MEM_READ_ONLY; + + if ( get_format_list( device, imageType, formatList, numFormats, flags ) ) + return -1; + + filterFlags = new bool[ numFormats ]; + if ( filterFlags == NULL ) + { + log_error( "ERROR: Out of memory allocating filter flags list!\n" ); + return -1; + } + memset( filterFlags, 0, sizeof( bool ) * numFormats ); + + // First time through, we'll go ahead and print the formats supported, regardless of type + if ( printedFormatList != (int)imageType ) + { + log_info( "---- Supported %s read formats for this device ---- \n", convert_image_type_to_string(imageType) ); + for ( unsigned int f = 0; f < numFormats; f++ ) + log_info( " %-7s %-24s %d\n", GetChannelOrderName( formatList[ f ].image_channel_order ), + GetChannelTypeName( formatList[ f ].image_channel_data_type ), + (int)get_format_channel_count( &formatList[ f ] ) ); + log_info( "------------------------------------------- \n" ); + printedFormatList = imageType; + } + + image_sampler_data imageSampler; + + /////// float tests /////// + + if ( gTypesToTest & kTestFloat ) + { + cl_channel_type floatFormats[] = { CL_UNORM_SHORT_565, CL_UNORM_SHORT_555, CL_UNORM_INT_101010, +#ifdef OBSOLETE_FORAMT + CL_UNORM_SHORT_565_REV, CL_UNORM_SHORT_555_REV, CL_UNORM_INT_8888, CL_UNORM_INT_8888_REV, CL_UNORM_INT_101010_REV, +#endif +#ifdef CL_SFIXED14_APPLE + CL_SFIXED14_APPLE, +#endif + CL_UNORM_INT8, CL_SNORM_INT8, + CL_UNORM_INT16, CL_SNORM_INT16, CL_FLOAT, CL_HALF_FLOAT, (cl_channel_type)-1 }; + if ( filter_formats( formatList, filterFlags, numFormats, floatFormats ) == 0 ) + { + log_info( "No formats supported for float type\n" ); + } + else + { + imageSampler.filter_mode = CL_FILTER_NEAREST; + ret += test_read_image_formats( device, formatList, filterFlags, numFormats, &imageSampler, kFloat, imageType ); + } + } + + /////// int tests /////// + if ( gTypesToTest & kTestInt ) + { + cl_channel_type intFormats[] = { CL_SIGNED_INT8, CL_SIGNED_INT16, CL_SIGNED_INT32, (cl_channel_type)-1 }; + if ( filter_formats( formatList, filterFlags, numFormats, intFormats ) == 0 ) + { + log_info( "No formats supported for integer type\n" ); + } + else + { + // Only filter mode we support on int is nearest + imageSampler.filter_mode = CL_FILTER_NEAREST; + ret += test_read_image_formats( device, formatList, filterFlags, numFormats, &imageSampler, kInt, imageType ); + } + } + + /////// uint tests /////// + + if ( gTypesToTest & kTestUInt ) + { + cl_channel_type uintFormats[] = { CL_UNSIGNED_INT8, CL_UNSIGNED_INT16, CL_UNSIGNED_INT32, (cl_channel_type)-1 }; + if ( filter_formats( formatList, filterFlags, numFormats, uintFormats ) == 0 ) + { + log_info( "No formats supported for unsigned int type\n" ); + } + else + { + // Only filter mode we support on uint is nearest + imageSampler.filter_mode = CL_FILTER_NEAREST; + ret += test_read_image_formats( device, formatList, filterFlags, numFormats, &imageSampler, kUInt, imageType ); + } + } + + + delete[] filterFlags; + delete[] formatList; + + return ret; +} diff --git a/test_conformance/images/samplerlessReads/test_read_1D.cpp b/test_conformance/images/samplerlessReads/test_read_1D.cpp new file mode 100644 index 00000000..a0e8e623 --- /dev/null +++ b/test_conformance/images/samplerlessReads/test_read_1D.cpp @@ -0,0 +1,332 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" +#include + +#if defined( __APPLE__ ) + #include + #include + #include +#endif + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding; +extern cl_device_type gDeviceType; +extern bool gTestReadWrite; + +#define MAX_TRIES 1 +#define MAX_CLAMPED 1 + +const char *read1DKernelSourcePattern = +"__kernel void sample_kernel( read_only image1d_t input, sampler_t sampler, __global int *results )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int offset = tidX;\n" +" %s clr = read_image%s( input, tidX );\n" +" int4 test = (clr != read_image%s( input, sampler, tidX ));\n" +" if ( test.x || test.y || test.z || test.w )\n" +" results[offset] = -1;\n" +" else\n" +" results[offset] = 0;\n" +"}"; + +const char *read_write1DKernelSourcePattern = +"__kernel void sample_kernel( read_only image1d_t read_only_image, read_write image1d_t read_write_image, sampler_t sampler, __global int *results )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int offset = tidX;\n" +" %s clr = read_image%s( read_only_image, sampler, tidX );\n" +" write_image%s(read_write_image, tidX, clr);\n" +" atomic_work_item_fence(CLK_IMAGE_MEM_FENCE, memory_order_acq_rel, memory_scope_work_item);\n" +" int4 test = (clr != read_image%s(read_write_image, tidX));\n" +" if ( test.x || test.y || test.z || test.w )\n" +" results[offset] = -1;\n" +" else\n" +" results[offset] = 0;\n" +"}"; + +int test_read_image_1D( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, image_sampler_data *imageSampler, + ExplicitType outputType, MTdata d ) +{ + int error; + size_t threads[2]; + cl_sampler actualSampler; + + // generate_random_image_data allocates with malloc, so we use a MallocDataBuffer here + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + if ( gDebugTrace ) + log_info( " - Creating image %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height ); + + // Construct testing sources + cl_mem read_only_image, read_write_image; + cl_image_desc image_desc; + + memset(&image_desc, 0x0, sizeof(cl_image_desc)); + image_desc.image_type = CL_MEM_OBJECT_IMAGE1D; + image_desc.image_width = imageInfo->width; + image_desc.image_row_pitch = ( gEnablePitch ? imageInfo->rowPitch : 0 ); + image_desc.num_mip_levels = 0; + + read_only_image = clCreateImage(context, + CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + imageInfo->format, + &image_desc, + imageValues, + &error ); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create read_only 1D image of size %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + + if(gTestReadWrite) + { + read_write_image = clCreateImage(context, + CL_MEM_READ_WRITE, + imageInfo->format, + &image_desc, + NULL, + &error ); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create read_write 1D image of size %d pitch %d (%s)\n", + (int)imageInfo->width, + (int)imageInfo->rowPitch, + IGetErrorString( error ) ); + return error; + } + } + + + if ( gDebugTrace ) + log_info( " - Creating kernel arguments...\n" ); + + // Create sampler to use + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_NONE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + actualSampler = clCreateSamplerWithProperties( context, properties, &error ); + test_error( error, "Unable to create image sampler" ); + + // Create results buffer + cl_mem results = clCreateBuffer( context, 0, imageInfo->width * sizeof(cl_int), NULL, &error); + test_error( error, "Unable to create results buffer" ); + + size_t resultValuesSize = imageInfo->width * sizeof(cl_int); + BufferOwningPtr resultValues(malloc( resultValuesSize )); + memset( resultValues, 0xff, resultValuesSize ); + clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + + // Set arguments + int idx = 0; + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_only_image ); + test_error( error, "Unable to set kernel arguments" ); + if(gTestReadWrite) + { + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_write_image ); + test_error( error, "Unable to set kernel arguments" ); + } + error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results ); + test_error( error, "Unable to set kernel arguments" ); + + // Run the kernel + threads[0] = (size_t)imageInfo->width; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + if ( gDebugTrace ) + log_info( " reading results, %ld kbytes\n", (unsigned long)( imageInfo->width * sizeof(cl_int) / 1024 ) ); + + error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + if ( gDebugTrace ) + log_info( " results read\n" ); + + // Check for non-zero comps + bool allZeroes = true; + for ( size_t ic = 0; ic < imageInfo->width; ++ic ) + { + if ( resultValues[ic] ) { + allZeroes = false; + break; + } + } + if ( !allZeroes ) + { + log_error( " Sampler-less reads differ from reads with sampler.\n" ); + return -1; + } + + clReleaseSampler(actualSampler); + clReleaseMemObject(results); + clReleaseMemObject(read_only_image); + if(gTestReadWrite) + { + clReleaseMemObject(read_write_image); + } + + return 0; +} + +int test_read_image_set_1D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, + ExplicitType outputType ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + const char *dataType; + clProgramWrapper program; + clKernelWrapper kernel; + RandomSeed seed( gRandomSeed ); + int error; + + // Get our operating params + size_t maxWidth; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + size_t pixelSize; + + imageInfo.format = format; + imageInfo.height = imageInfo.depth = imageInfo.arraySize = imageInfo.slicePitch = 0; + imageInfo.type = CL_MEM_OBJECT_IMAGE1D; + pixelSize = get_pixel_size( imageInfo.format ); + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 1D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // Determine types + if ( outputType == kInt ) + { + readFormat = "i"; + dataType = "int4"; + } + else if ( outputType == kUInt ) + { + readFormat = "ui"; + dataType = "uint4"; + } + else // kFloat + { + readFormat = "f"; + dataType = "float4"; + } + + if(gTestReadWrite) + { + sprintf( programSrc, + read_write1DKernelSourcePattern, + dataType, + readFormat, + readFormat, + readFormat); + } + else + { + sprintf( programSrc, + read1DKernelSourcePattern, + dataType, + readFormat, + readFormat ); + } + + + ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create testing kernel" ); + + if ( gTestSmallImages ) + { + for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + { + if ( gDebugTrace ) + log_info( " at size %d\n", (int)imageInfo.width ); + + int retCode = test_read_image_1D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + } + else if ( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format); + + for ( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + log_info("Testing %d\n", (int)sizes[ idx ][ 0 ]); + if ( gDebugTrace ) + log_info( " at max size %d\n", (int)sizes[ idx ][ 0 ] ); + int retCode = test_read_image_1D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + else + { + for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + if ( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth * pixelSize; + } + + size = (size_t)imageInfo.rowPitch * 4; + } while ( size > maxAllocSize || ( size * 3 ) > memSize ); + + if ( gDebugTrace ) + log_info( " at size %d (row pitch %d) out of %d\n", (int)imageInfo.width, (int)imageInfo.rowPitch, (int)maxWidth ); + int retCode = test_read_image_1D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + + return 0; +} diff --git a/test_conformance/images/samplerlessReads/test_read_1D_array.cpp b/test_conformance/images/samplerlessReads/test_read_1D_array.cpp new file mode 100644 index 00000000..72614378 --- /dev/null +++ b/test_conformance/images/samplerlessReads/test_read_1D_array.cpp @@ -0,0 +1,336 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" +#include + +#if defined( __APPLE__ ) + #include + #include + #include +#endif + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding; +extern cl_device_type gDeviceType; +extern bool gTestReadWrite; + +#define MAX_TRIES 1 +#define MAX_CLAMPED 1 + +const char *read1DArrayKernelSourcePattern = +"__kernel void sample_kernel( read_only image1d_array_t input, sampler_t sampler, __global int *results )\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1);\n" +" int offset = tidY*get_image_width(input) + tidX;\n" +" int2 coords = (int2)(tidX, tidY);\n" +" %s clr = read_image%s( input, coords );\n" +" int4 test = (clr != read_image%s( input, sampler, coords ));\n" +" if ( test.x || test.y || test.z || test.w )\n" +" results[offset] = -1;\n" +" else\n" +" results[offset] = 0;\n" +"}"; + +const char *read_write1DArrayKernelSourcePattern = +"__kernel void sample_kernel( read_only image1d_array_t read_only_image, read_write image1d_array_t read_write_image, sampler_t sampler, __global int *results )\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1);\n" +" int offset = tidY*get_image_width(read_only_image) + tidX;\n" +" int2 coords = (int2)(tidX, tidY);\n" +" %s clr = read_image%s( read_only_image, sampler, coords );\n" +" write_image%s(read_write_image, coords, clr);\n" +" atomic_work_item_fence(CLK_IMAGE_MEM_FENCE, memory_order_acq_rel, memory_scope_work_item);\n" +" int4 test = (clr != read_image%s( read_write_image, coords ));\n" +" if ( test.x || test.y || test.z || test.w )\n" +" results[offset] = -1;\n" +" else\n" +" results[offset] = 0;\n" +"}"; + +int test_read_image_1D_array( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, image_sampler_data *imageSampler, + ExplicitType outputType, MTdata d ) +{ + int error; + size_t threads[2]; + cl_sampler actualSampler; + + // generate_random_image_data allocates with malloc, so we use a MallocDataBuffer here + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + if ( gDebugTrace ) + log_info( " - Creating image %d by %d...\n", (int)imageInfo->width, (int)imageInfo->arraySize ); + + // Construct testing sources + cl_mem read_only_image, read_write_image; + cl_image_desc image_desc; + + memset(&image_desc, 0x0, sizeof(cl_image_desc)); + image_desc.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + image_desc.image_width = imageInfo->width; + image_desc.image_height = imageInfo->height; + image_desc.image_array_size = imageInfo->arraySize; + image_desc.image_row_pitch = ( gEnablePitch ? imageInfo->rowPitch : 0 ); + image_desc.image_slice_pitch = 0; + image_desc.num_mip_levels = 0; + read_only_image = clCreateImage( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, imageInfo->format, + &image_desc, imageValues, &error ); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create read_only 1D image array of size %d x %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->arraySize, (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + + if(gTestReadWrite) + { + read_write_image = clCreateImage(context, + CL_MEM_READ_WRITE, + imageInfo->format, + &image_desc, + NULL, + &error ); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create read_write 1D image array of size %d x %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->arraySize, (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + } + if ( gDebugTrace ) + log_info( " - Creating kernel arguments...\n" ); + + // Create sampler to use + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_NONE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + actualSampler = clCreateSamplerWithProperties( context, properties, &error ); + test_error( error, "Unable to create image sampler" ); + + // Create results buffer + cl_mem results = clCreateBuffer( context, 0, imageInfo->width * imageInfo->arraySize * sizeof(cl_int), NULL, &error); + test_error( error, "Unable to create results buffer" ); + + size_t resultValuesSize = imageInfo->width * imageInfo->arraySize * sizeof(cl_int); + BufferOwningPtr resultValues(malloc( resultValuesSize )); + memset( resultValues, 0xff, resultValuesSize ); + clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + + // Set arguments + int idx = 0; + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_only_image ); + test_error( error, "Unable to set kernel arguments" ); + if(gTestReadWrite) + { + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_write_image ); + test_error( error, "Unable to set kernel arguments" ); + } + error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results ); + test_error( error, "Unable to set kernel arguments" ); + + // Run the kernel + threads[0] = (size_t)imageInfo->width; + threads[1] = (size_t)imageInfo->arraySize; + + error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + if ( gDebugTrace ) + log_info( " reading results, %ld kbytes\n", (unsigned long)( imageInfo->width * imageInfo->arraySize * sizeof(cl_int) / 1024 ) ); + + error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + if ( gDebugTrace ) + log_info( " results read\n" ); + + // Check for non-zero comps + bool allZeroes = true; + size_t ic; + for ( ic = 0; ic < imageInfo->width * imageInfo->arraySize; ++ic ) + { + if ( resultValues[ic] ) { + allZeroes = false; + break; + } + } + if ( !allZeroes ) + { + log_error( " Sampler-less reads differ from reads with sampler at index %lu.\n", ic ); + return -1; + } + + clReleaseSampler(actualSampler); + clReleaseMemObject(results); + if(gTestReadWrite) + { + clReleaseMemObject(read_write_image); + } + return 0; +} + +int test_read_image_set_1D_array( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, + ExplicitType outputType ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + const char *dataType; + clProgramWrapper program; + clKernelWrapper kernel; + RandomSeed seed( gRandomSeed ); + int error; + + // Get our operating params + size_t maxWidth, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + size_t pixelSize; + + imageInfo.format = format; + imageInfo.height = imageInfo.depth = 0; + imageInfo.type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + pixelSize = get_pixel_size( imageInfo.format ); + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // Determine types + if ( outputType == kInt ) + { + readFormat = "i"; + dataType = "int4"; + } + else if ( outputType == kUInt ) + { + readFormat = "ui"; + dataType = "uint4"; + } + else // kFloat + { + readFormat = "f"; + dataType = "float4"; + } + + if(gTestReadWrite) + { + sprintf( programSrc, + read_write1DArrayKernelSourcePattern, + dataType, + readFormat, + readFormat, + readFormat); + } + else + { + sprintf( programSrc, + read1DArrayKernelSourcePattern, + dataType, + readFormat, + readFormat ); + } + + + ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create testing kernel" ); + + if ( gTestSmallImages ) + { + for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch; + for ( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ ) + { + if ( gDebugTrace ) + log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize ); + + int retCode = test_read_image_1D_array( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + } + else if ( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D_ARRAY, imageInfo.format); + + for ( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.arraySize = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch; + log_info("Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ]); + if ( gDebugTrace ) + log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ] ); + int retCode = test_read_image_1D_array( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + else + { + for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + if ( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth * pixelSize; + } + + imageInfo.slicePitch = imageInfo.rowPitch; + + size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.arraySize * 4; + } while ( size > maxAllocSize || ( size * 3 ) > memSize ); + + if ( gDebugTrace ) + log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxArraySize ); + int retCode = test_read_image_1D_array( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + + return 0; +} diff --git a/test_conformance/images/samplerlessReads/test_read_1D_buffer.cpp b/test_conformance/images/samplerlessReads/test_read_1D_buffer.cpp new file mode 100644 index 00000000..5342d068 --- /dev/null +++ b/test_conformance/images/samplerlessReads/test_read_1D_buffer.cpp @@ -0,0 +1,324 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" +#include + +#if defined( __APPLE__ ) + #include + #include + #include +#endif + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gTestSmallImages, gTestMaxImages, gTestRounding; +extern cl_device_type gDeviceType; + +#define MAX_TRIES 1 +#define MAX_CLAMPED 1 + +const char *read1DBufferKernelSourcePattern = +"__kernel void sample_kernel( read_only image1d_buffer_t inputA, read_only image1d_t inputB, sampler_t sampler, __global int *results )\n" +"{\n" +" int tidX = get_global_id(0);\n" +" int offset = tidX;\n" +" %s clr = read_image%s( inputA, tidX );\n" +" int4 test = (clr != read_image%s( inputB, sampler, tidX ));\n" +" if ( test.x || test.y || test.z || test.w )\n" +" results[offset] = -1;\n" +" else\n" +" results[offset] = 0;\n" +"}"; + + +int test_read_image_1D_buffer( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, image_sampler_data *imageSampler, + ExplicitType outputType, MTdata d ) +{ + int error; + size_t threads[2]; + cl_sampler actualSampler; + + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + + if ( gDebugTrace ) + log_info( " - Creating 1D image from buffer %d ...\n", (int)imageInfo->width ); + + // Construct testing sources + cl_mem image[2]; + cl_image_desc image_desc; + + cl_mem imageBuffer = clCreateBuffer( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, imageInfo->rowPitch, imageValues, &error); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create buffer of size %d bytes (%s)\n", (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + + memset(&image_desc, 0x0, sizeof(cl_image_desc)); + image_desc.image_type = CL_MEM_OBJECT_IMAGE1D_BUFFER; + image_desc.image_width = imageInfo->width; + image_desc.mem_object = imageBuffer; + image[0] = clCreateImage( context, CL_MEM_READ_ONLY, imageInfo->format, + &image_desc, NULL, &error ); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create IMAGE1D_BUFFER of size %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + + cl_mem ret = NULL; + error = clGetMemObjectInfo(image[0], CL_MEM_ASSOCIATED_MEMOBJECT, sizeof(ret), &ret, NULL); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to query CL_MEM_ASSOCIATED_MEMOBJECT\n", IGetErrorString( error ) ); + return error; + } + + if (ret != imageBuffer) { + log_error("ERROR: clGetImageInfo for CL_IMAGE_BUFFER returned wrong value\n"); + return -1; + } + + memset(&image_desc, 0x0, sizeof(cl_image_desc)); + image_desc.image_type = CL_MEM_OBJECT_IMAGE1D; + image_desc.image_width = imageInfo->width; + image[1] = clCreateImage( context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, imageInfo->format, &image_desc, imageValues, &error ); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create IMAGE1D of size %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->rowPitch, IGetErrorString( error ) ); + return error; + } + + if ( gDebugTrace ) + log_info( " - Creating kernel arguments...\n" ); + + // Create sampler to use + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_NONE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + actualSampler = clCreateSamplerWithProperties( context, properties, &error ); + test_error( error, "Unable to create image sampler" ); + + // Create results buffer + cl_mem results = clCreateBuffer( context, 0, imageInfo->width * sizeof(cl_int), NULL, &error); + test_error( error, "Unable to create results buffer" ); + + size_t resultValuesSize = imageInfo->width * sizeof(cl_int); + BufferOwningPtr resultValues(malloc( resultValuesSize )); + memset( resultValues, 0xff, resultValuesSize ); + clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + + // Set arguments + int idx = 0; + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &image[0] ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &image[1] ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results ); + test_error( error, "Unable to set kernel arguments" ); + + // Run the kernel + threads[0] = (size_t)imageInfo->width; + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + if ( gDebugTrace ) + log_info( " reading results, %ld kbytes\n", (unsigned long)( imageInfo->width * sizeof(cl_int) / 1024 ) ); + + error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + if ( gDebugTrace ) + log_info( " results read\n" ); + + // Check for non-zero comps + bool allZeroes = true; + for ( size_t ic = 0; ic < imageInfo->width; ++ic ) + { + if ( resultValues[ic] ) { + allZeroes = false; + break; + } + } + if ( !allZeroes ) + { + log_error( " Sampler-less reads differ from reads with sampler.\n" ); + return -1; + } + + clReleaseSampler(actualSampler); + clReleaseMemObject(results); + clReleaseMemObject(image[0]); + clReleaseMemObject(image[1]); + clReleaseMemObject(imageBuffer); + return 0; +} + +int test_read_image_set_1D_buffer( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, + ExplicitType outputType ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + const char *dataType; + clProgramWrapper program; + clKernelWrapper kernel; + RandomSeed seed( gRandomSeed ); + int error; + + // Get our operating params + size_t maxWidth, maxWidth1D; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + size_t pixelSize; + + if (format->image_channel_order == CL_RGB || format->image_channel_order == CL_RGBx) + { + switch (format->image_channel_data_type) + { + case CL_UNORM_INT8: + case CL_UNORM_INT16: + case CL_SNORM_INT8: + case CL_SNORM_INT16: + case CL_HALF_FLOAT: + case CL_FLOAT: + case CL_SIGNED_INT8: + case CL_SIGNED_INT16: + case CL_SIGNED_INT32: + case CL_UNSIGNED_INT8: + case CL_UNSIGNED_INT16: + case CL_UNSIGNED_INT32: + case CL_UNORM_INT_101010: + log_info( "Skipping image format: %s %s\n", GetChannelOrderName( format->image_channel_order ), + GetChannelTypeName( format->image_channel_data_type )); + return 0; + default: + break; + } + } + + imageInfo.format = format; + imageInfo.height = imageInfo.depth = imageInfo.arraySize = imageInfo.slicePitch = 0; + imageInfo.type = CL_MEM_OBJECT_IMAGE1D; + pixelSize = get_pixel_size( imageInfo.format ); + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_BUFFER_SIZE, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth1D, NULL ); + test_error( error, "Unable to get max image 1D buffer size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // note: image_buffer test uses image1D for results validation. + // So the test can't use the biggest possible size for image_buffer if it's bigger than the max image1D size + maxWidth = (maxWidth > maxWidth1D) ? maxWidth1D : maxWidth; + // Determine types + if ( outputType == kInt ) + { + readFormat = "i"; + dataType = "int4"; + } + else if ( outputType == kUInt ) + { + readFormat = "ui"; + dataType = "uint4"; + } + else // kFloat + { + readFormat = "f"; + dataType = "float4"; + } + + sprintf( programSrc, read1DBufferKernelSourcePattern, dataType, + readFormat, + readFormat ); + + ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create testing kernel" ); + + if ( gTestSmallImages ) + { + for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + { + if ( gDebugTrace ) + log_info( " at size %d\n", (int)imageInfo.width ); + + int retCode = test_read_image_1D_buffer( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + } + else if ( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format); + + for ( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + log_info("Testing %d\n", (int)sizes[ idx ][ 0 ]); + if ( gDebugTrace ) + log_info( " at max size %d\n", (int)sizes[ idx ][ 0 ] ); + int retCode = test_read_image_1D_buffer( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + else + { + for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.rowPitch = imageInfo.width * pixelSize; + size = (size_t)imageInfo.rowPitch * 4; + } while ( size > maxAllocSize || ( size * 3 ) > memSize ); + + if ( gDebugTrace ) + log_info( " at size %d (row pitch %d) out of %d\n", (int)imageInfo.width, (int)imageInfo.rowPitch, (int)maxWidth ); + int retCode = test_read_image_1D_buffer( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + + return 0; +} + + diff --git a/test_conformance/images/samplerlessReads/test_read_2D_array.cpp b/test_conformance/images/samplerlessReads/test_read_2D_array.cpp new file mode 100644 index 00000000..2d6c889d --- /dev/null +++ b/test_conformance/images/samplerlessReads/test_read_2D_array.cpp @@ -0,0 +1,334 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" +#include + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding; +extern cl_device_type gDeviceType; +extern bool gTestReadWrite; + +const char *read2DArrayKernelSourcePattern = +"__kernel void sample_kernel( read_only %s input, sampler_t sampler, __global int *results )\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n" +" int offset = tidZ*get_image_width(input)*get_image_height(input) + tidY*get_image_width(input) + tidX;\n" +" int4 coords = (int4)( tidX, tidY, tidZ, 0 );\n" +" %s clr = read_image%s( input, coords );\n" +" int4 test = (clr != read_image%s( input, sampler, coords ));\n" +" if ( test.x || test.y || test.z || test.w )\n" +" results[offset] = -1;\n" +" else\n" +" results[offset] = 0;\n" +"}"; + +const char *read_write2DArrayKernelSourcePattern = +"__kernel void sample_kernel( read_only %s read_only_image, read_write %s read_write_image, sampler_t sampler, __global int *results )\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n" +" int offset = tidZ*get_image_width(read_only_image)*get_image_height(read_only_image) + tidY*get_image_width(read_only_image) + tidX;\n" +" int4 coords = (int4)( tidX, tidY, tidZ, 0 );\n" +" %s clr = read_image%s( read_only_image, sampler, coords );\n" +" write_image%s(read_write_image, coords, clr);\n" +" atomic_work_item_fence(CLK_IMAGE_MEM_FENCE, memory_order_acq_rel, memory_scope_work_item);\n" +" int4 test = (clr != read_image%s( read_write_image, coords ));\n" +" if ( test.x || test.y || test.z || test.w )\n" +" results[offset] = -1;\n" +" else\n" +" results[offset] = 0;\n" +"}"; + +int test_read_image_2D_array( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, image_sampler_data *imageSampler, + ExplicitType outputType, MTdata d ) +{ + int error; + size_t threads[3]; + cl_sampler actualSampler; + + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + // Don't use clEnqueueWriteImage; just use copy host ptr to get the data in + cl_image_desc image_desc; + cl_mem read_only_image, read_write_image; + + memset(&image_desc, 0x0, sizeof(cl_image_desc)); + image_desc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + image_desc.image_width = imageInfo->width; + image_desc.image_height = imageInfo->height; + image_desc.image_array_size = imageInfo->arraySize; + image_desc.image_row_pitch = ( gEnablePitch ? imageInfo->rowPitch : 0 ); + image_desc.image_slice_pitch = ( gEnablePitch ? imageInfo->slicePitch : 0 ); + image_desc.num_mip_levels = 0; + read_only_image = clCreateImage( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, imageInfo->format, + &image_desc, imageValues, &error ); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create read_only 2D image array of size %d x %d x %d (pitch %d, %d ) (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + + if(gTestReadWrite) + { + read_write_image = clCreateImage(context, + CL_MEM_READ_WRITE, + imageInfo->format, + &image_desc, + NULL, + &error ); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create read_write 2D image array of size %d x %d x %d (pitch %d, %d ) (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + } + + // Create sampler to use + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_NONE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + actualSampler = clCreateSamplerWithProperties( context, properties, &error ); + test_error( error, "Unable to create image sampler" ); + + // Create results buffer + cl_mem results = clCreateBuffer( context, 0, imageInfo->width * imageInfo->height * imageInfo->arraySize * sizeof(cl_int), NULL, &error); + test_error( error, "Unable to create results buffer" ); + + size_t resultValuesSize = imageInfo->width * imageInfo->height * imageInfo->arraySize * sizeof(cl_int); + BufferOwningPtr resultValues(malloc( resultValuesSize )); + memset( resultValues, 0xff, resultValuesSize ); + clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + + // Set arguments + int idx = 0; + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_only_image ); + test_error( error, "Unable to set kernel arguments" ); + if(gTestReadWrite) + { + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_write_image ); + test_error( error, "Unable to set kernel arguments" ); + } + error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results ); + test_error( error, "Unable to set kernel arguments" ); + + // Figure out thread dimensions + threads[0] = (size_t)imageInfo->width; + threads[1] = (size_t)imageInfo->height; + threads[2] = (size_t)imageInfo->arraySize; + + // Run the kernel + error = clEnqueueNDRangeKernel( queue, kernel, 3, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + // Get results + error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + if ( gDebugTrace ) + log_info( " results read\n" ); + + // Check for non-zero comps + bool allZeroes = true; + for ( size_t ic = 0; ic < imageInfo->width * imageInfo->height * imageInfo->arraySize; ++ic ) + { + if ( resultValues[ic] ) { + allZeroes = false; + break; + } + } + if ( !allZeroes ) + { + log_error( " Sampler-less reads differ from reads with sampler.\n" ); + return -1; + } + + clReleaseSampler(actualSampler); + clReleaseMemObject(results); + clReleaseMemObject(read_only_image); + if(gTestReadWrite) + { + clReleaseMemObject(read_write_image); + } + + return 0; +} + +int test_read_image_set_2D_array( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + const char *dataType; + RandomSeed seed( gRandomSeed ); + + int error; + + clProgramWrapper program; + clKernelWrapper kernel; + + // Get operating parameters + size_t maxWidth, maxHeight, maxArraySize; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + size_t pixelSize; + + imageInfo.format = format; + imageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + pixelSize = get_pixel_size( imageInfo.format ); + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 2D array size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // Determine types + if ( outputType == kInt ) + { + readFormat = "i"; + dataType = "int4"; + } + else if ( outputType == kUInt ) + { + readFormat = "ui"; + dataType = "uint4"; + } + else // kFloat + { + readFormat = "f"; + dataType = (format->image_channel_order == CL_DEPTH) ? "float" : "float4"; + } + + // Construct the source + if(gTestReadWrite) + { + sprintf( programSrc, read_write2DArrayKernelSourcePattern, + (format->image_channel_order == CL_DEPTH) ? "image2d_array_depth_t" : "image2d_array_t", + (format->image_channel_order == CL_DEPTH) ? "image2d_array_depth_t" : "image2d_array_t", + dataType, + readFormat, + readFormat, + readFormat); + } + else + { + sprintf( programSrc, read2DArrayKernelSourcePattern, + (format->image_channel_order == CL_DEPTH) ? "image2d_array_depth_t" : "image2d_array_t", + dataType, + readFormat, + readFormat ); + } + + + ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create testing kernel" ); + + + // Run tests + if ( gTestSmallImages ) + { + for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format ); + + for ( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + for ( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ ) + { + if ( gDebugTrace ) + log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize ); + int retCode = test_read_image_2D_array( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + } + } + else if ( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D_ARRAY, imageInfo.format); + + for ( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.arraySize = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + log_info("Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ]); + if ( gDebugTrace ) + log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + int retCode = test_read_image_2D_array( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + else + { + for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + + if ( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth * pixelSize; + + size_t extraHeight = (int)random_log_in_range( 0, 64, seed ); + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight); + } + + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4; + } while ( size > maxAllocSize || ( size * 3 ) > memSize ); + + if ( gDebugTrace ) + log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxArraySize ); + int retCode = test_read_image_2D_array( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + + return 0; +} diff --git a/test_conformance/images/samplerlessReads/test_read_3D.cpp b/test_conformance/images/samplerlessReads/test_read_3D.cpp new file mode 100644 index 00000000..5913afed --- /dev/null +++ b/test_conformance/images/samplerlessReads/test_read_3D.cpp @@ -0,0 +1,337 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" +#include + +#define MAX_ERR 0.005f +#define MAX_HALF_LINEAR_ERR 0.3f + +extern cl_command_queue queue; +extern cl_context context; +extern bool gDebugTrace, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding; +extern cl_device_type gDeviceType; +extern bool gTestReadWrite; + +const char *read3DKernelSourcePattern = +"__kernel void sample_kernel( read_only image3d_t input, sampler_t sampler, __global int *results )\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n" +" int offset = tidZ*get_image_width(input)*get_image_height(input) + tidY*get_image_width(input) + tidX;\n" +" int4 coords = (int4)( tidX, tidY, tidZ, 0 );\n" +" %s clr = read_image%s( input, coords );\n" +" int4 test = (clr != read_image%s( input, sampler, coords ));\n" +" if ( test.x || test.y || test.z || test.w )\n" +" results[offset] = -1;\n" +" else\n" +" results[offset] = 0;\n" +"}"; + +const char *read_write3DKernelSourcePattern = +"__kernel void sample_kernel( read_only image3d_t read_only_image, read_write image3d_t read_write_image, sampler_t sampler, __global int *results )\n" +"{\n" +" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n" +" int offset = tidZ*get_image_width(read_only_image)*get_image_height(read_only_image) + tidY*get_image_width(read_only_image) + tidX;\n" +" int4 coords = (int4)( tidX, tidY, tidZ, 0 );\n" +" %s clr = read_image%s( read_only_image, sampler, coords );\n" +" write_image%s(read_write_image, coords, clr);\n" +" atomic_work_item_fence(CLK_IMAGE_MEM_FENCE, memory_order_acq_rel, memory_scope_work_item);\n" +" int4 test = (clr != read_image%s( read_write_image, coords ));\n" +" if ( test.x || test.y || test.z || test.w )\n" +" results[offset] = -1;\n" +" else\n" +" results[offset] = 0;\n" +"}"; +int test_read_image_3D( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel, + image_descriptor *imageInfo, image_sampler_data *imageSampler, + ExplicitType outputType, MTdata d ) +{ + int error; + size_t threads[3]; + cl_sampler actualSampler; + + BufferOwningPtr imageValues; + generate_random_image_data( imageInfo, imageValues, d ); + // Don't use clEnqueueWriteImage; just use copy host ptr to get the data in + cl_image_desc image_desc; + cl_mem read_only_image, read_write_image; + + memset(&image_desc, 0x0, sizeof(cl_image_desc)); + image_desc.image_type = CL_MEM_OBJECT_IMAGE3D; + image_desc.image_width = imageInfo->width; + image_desc.image_height = imageInfo->height; + image_desc.image_depth = imageInfo->depth; + image_desc.image_row_pitch = ( gEnablePitch ? imageInfo->rowPitch : 0 ); + image_desc.image_slice_pitch = ( gEnablePitch ? imageInfo->slicePitch : 0 ); + image_desc.num_mip_levels = 0; + read_only_image = clCreateImage( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, imageInfo->format, + &image_desc, imageValues, &error ); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create read_only 3D image of size %d x %d x %d (pitch %d, %d ) (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + + if(gTestReadWrite) + { + read_write_image = clCreateImage(context, + CL_MEM_READ_WRITE, + imageInfo->format, + &image_desc, + NULL, + &error); + if ( error != CL_SUCCESS ) + { + log_error( "ERROR: Unable to create read_write 3D image of size %d x %d x %d (pitch %d, %d ) (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) ); + return error; + } + } + + // Create sampler to use + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_NONE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + actualSampler = clCreateSamplerWithProperties( context, properties, &error ); + test_error( error, "Unable to create image sampler" ); + + // Create results buffer + cl_mem results = clCreateBuffer( context, 0, imageInfo->width * imageInfo->height * imageInfo->depth * sizeof(cl_int), NULL, &error); + test_error( error, "Unable to create results buffer" ); + + size_t resultValuesSize = imageInfo->width * imageInfo->height * imageInfo->depth * sizeof(cl_int); + BufferOwningPtr resultValues(malloc( resultValuesSize )); + memset( resultValues, 0xff, resultValuesSize ); + clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + + // Set arguments + int idx = 0; + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_only_image ); + test_error( error, "Unable to set kernel arguments" ); + if(gTestReadWrite) + { + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_write_image ); + test_error( error, "Unable to set kernel arguments" ); + } + error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results ); + test_error( error, "Unable to set kernel arguments" ); + + // Figure out thread dimensions + threads[0] = (size_t)imageInfo->width; + threads[1] = (size_t)imageInfo->height; + threads[2] = (size_t)imageInfo->depth; + + // Run the kernel + error = clEnqueueNDRangeKernel( queue, kernel, 3, NULL, threads, NULL, 0, NULL, NULL ); + test_error( error, "Unable to run kernel" ); + + if ( gDebugTrace ) + log_info( " reading results, %ld kbytes\n", (unsigned long)( imageInfo->width * imageInfo->height * imageInfo->depth * sizeof(cl_int) / 1024 ) ); + + // Get results + error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL ); + test_error( error, "Unable to read results from kernel" ); + if ( gDebugTrace ) + log_info( " results read\n" ); + + // Check for non-zero comps + bool allZeroes = true; + size_t ic; + for ( ic = 0; ic < imageInfo->width * imageInfo->height * imageInfo->depth; ++ic ) + { + if ( resultValues[ic] ) { + allZeroes = false; + break; + } + } + if ( !allZeroes ) + { + log_error( " Sampler-less reads differ from reads with sampler at index %lu.\n", ic ); + return -1; + } + + clReleaseSampler(actualSampler); + clReleaseMemObject(results); + clReleaseMemObject(read_only_image); + if(gTestReadWrite) + { + clReleaseMemObject(read_write_image); + } + + return 0; +} + +int test_read_image_set_3D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType ) +{ + char programSrc[10240]; + const char *ptr; + const char *readFormat; + const char *dataType; + RandomSeed seed( gRandomSeed ); + + int error; + + clProgramWrapper program; + clKernelWrapper kernel; + + // Get operating parameters + size_t maxWidth, maxHeight, maxDepth; + cl_ulong maxAllocSize, memSize; + image_descriptor imageInfo = { 0 }; + size_t pixelSize; + + imageInfo.format = format; + imageInfo.arraySize = 0; + imageInfo.type = CL_MEM_OBJECT_IMAGE3D; + pixelSize = get_pixel_size( imageInfo.format ); + + error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL ); + error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL ); + test_error( error, "Unable to get max image 3D size from device" ); + + if (memSize > (cl_ulong)SIZE_MAX) { + memSize = (cl_ulong)SIZE_MAX; + } + + // Determine types + if ( outputType == kInt ) + { + readFormat = "i"; + dataType = "int4"; + } + else if ( outputType == kUInt ) + { + readFormat = "ui"; + dataType = "uint4"; + } + else // kFloat + { + readFormat = "f"; + dataType = "float4"; + } + + // Construct the source + if(gTestReadWrite) + { + sprintf( programSrc, + read_write3DKernelSourcePattern, + dataType, + readFormat, + readFormat, + readFormat); + } + else + { + sprintf( programSrc, + read3DKernelSourcePattern, + dataType, + readFormat, + readFormat ); + } + + + ptr = programSrc; + error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" ); + test_error( error, "Unable to create testing kernel" ); + + + // Run tests + if ( gTestSmallImages ) + { + for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ ) + { + imageInfo.rowPitch = imageInfo.width * pixelSize; + + for ( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ ) + { + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + for ( imageInfo.depth = 2; imageInfo.depth < 9; imageInfo.depth++ ) + { + if ( gDebugTrace ) + log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth ); + int retCode = test_read_image_3D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + } + } + else if ( gTestMaxImages ) + { + // Try a specific set of maximum sizes + size_t numbeOfSizes; + size_t sizes[100][3]; + + get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, maxDepth, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE3D, imageInfo.format); + + for ( size_t idx = 0; idx < numbeOfSizes; idx++ ) + { + imageInfo.width = sizes[ idx ][ 0 ]; + imageInfo.height = sizes[ idx ][ 1 ]; + imageInfo.depth = sizes[ idx ][ 2 ]; + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch; + log_info("Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ]); + if ( gDebugTrace ) + log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] ); + int retCode = test_read_image_3D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + else + { + for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ ) + { + cl_ulong size; + // Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that + // image, the result array, plus offset arrays, will fit in the global ram space + do + { + imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed ); + imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed ); + imageInfo.depth = (size_t)random_log_in_range( 16, (int)maxDepth / 32, seed ); + + imageInfo.rowPitch = imageInfo.width * pixelSize; + imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height; + + if ( gEnablePitch ) + { + size_t extraWidth = (int)random_log_in_range( 0, 64, seed ); + imageInfo.rowPitch += extraWidth * pixelSize; + + size_t extraHeight = (int)random_log_in_range( 0, 64, seed ); + imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight); + } + + size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.depth * 4 * 4; + } while ( size > maxAllocSize || ( size * 3 ) > memSize ); + + if ( gDebugTrace ) + log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxDepth ); + int retCode = test_read_image_3D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed ); + if ( retCode ) + return retCode; + } + } + + return 0; +} diff --git a/test_conformance/images/testBase.h b/test_conformance/images/testBase.h new file mode 100644 index 00000000..69845865 --- /dev/null +++ b/test_conformance/images/testBase.h @@ -0,0 +1,78 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testBase_h +#define _testBase_h + +#include "../../test_common/harness/compat.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/clImageHelper.h" +#include "../../test_common/harness/imageHelpers.h" + +// Amount to offset pixels for checking normalized reads +#define NORM_OFFSET 0.1f + +enum TypesToTest +{ + kTestInt = ( 1 << 0 ), + kTestUInt = ( 1 << 1 ), + kTestFloat = ( 1 << 2 ), + kTestAllTypes = kTestInt | kTestUInt | kTestFloat +}; + +// For the clCopyImage test +enum MethodsToTest +{ + k1D = ( 1 << 0 ), + k2D = ( 1 << 1 ), + k1DArray = ( 1 << 2 ), + k2DArray = ( 1 << 3 ), + k3D = ( 1 << 4 ), + k2DTo3D = ( 1 << 5 ), + k3DTo2D = ( 1 << 6 ), + k2DArrayTo2D = ( 1 << 7 ), + k2DTo2DArray = ( 1 << 8 ), + k2DArrayTo3D = ( 1 << 9 ), + k3DTo2DArray = ( 1 << 10 ), +}; + + +enum TestTypes +{ + kReadTests = 1 << 0 , + kWriteTests = 1 << 1, + kReadWriteTests = 1 << 2, + kAllTests = ( kReadTests | kWriteTests | kReadWriteTests ) +}; + +typedef int (*test_format_set_fn)( cl_device_id device, + cl_image_format *formatList, bool *filterFlags, unsigned int numFormats, + image_sampler_data *imageSampler, ExplicitType outputType, + cl_mem_object_type imageType ); + +extern int test_read_image_formats( cl_device_id device, + cl_image_format *formatList, bool *filterFlags, unsigned int numFormats, + image_sampler_data *imageSampler, ExplicitType outputType, + cl_mem_object_type imageType ); +extern int test_write_image_formats( cl_device_id device, + cl_image_format *formatList, bool *filterFlags, unsigned int numFormats, + image_sampler_data *imageSampler, ExplicitType outputType, + cl_mem_object_type imageType ); + +#endif // _testBase_h + + + diff --git a/test_conformance/integer_ops/CMakeLists.txt b/test_conformance/integer_ops/CMakeLists.txt new file mode 100644 index 00000000..c5c41276 --- /dev/null +++ b/test_conformance/integer_ops/CMakeLists.txt @@ -0,0 +1,26 @@ +set(MODULE_NAME INTEGER_OPS) + +set(${MODULE_NAME}_SOURCES + main.c + test_int_basic_ops.c + test_integers.cpp + test_upsample.cpp + test_intmul24.c test_intmad24.c + test_sub_sat.c test_add_sat.c + test_abs.c test_absdiff.c + test_unary_ops.cpp + verification_and_generation_functions.c + test_popcount.c + ../../test_common/harness/ThreadPool.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) + diff --git a/test_conformance/integer_ops/Jamfile b/test_conformance/integer_ops/Jamfile new file mode 100644 index 00000000..961dc955 --- /dev/null +++ b/test_conformance/integer_ops/Jamfile @@ -0,0 +1,28 @@ +project + : requirements + gcc:-xc++ + msvc:"/TP" + ; + +exe test_integer_ops + : main.c + test_abs.c + test_absdiff.c + test_add_sat.c + test_int.c + test_integers.cpp + test_intmad24.c + test_intmul24.c + test_long.c + test_sub_sat.c + test_uint.c + test_ulong.c + test_upsample.cpp + ; + +install dist + : test_integer_ops + : debug:$(DIST)/debug/tests/test_conformance/integer_ops + release:$(DIST)/release/tests/test_conformance/integer_ops + ; + diff --git a/test_conformance/integer_ops/Makefile b/test_conformance/integer_ops/Makefile new file mode 100644 index 00000000..9848e76e --- /dev/null +++ b/test_conformance/integer_ops/Makefile @@ -0,0 +1,52 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + test_popcount.c \ + test_int_basic_ops.c \ + test_integers.cpp \ + test_upsample.cpp \ + test_intmul24.c test_intmad24.c \ + test_sub_sat.c test_add_sat.c \ + test_abs.c test_absdiff.c \ + test_unary_ops.cpp \ + verification_and_generation_functions.c \ + ../../test_common/harness/conversions.c \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/ThreadPool.c \ + ../../test_common/harness/kernelHelpers.c + +DEFINES = + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = $(SOURCES) +HEADERS = +TARGET = test_integer_ops +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/integer_ops/main.c b/test_conformance/integer_ops/main.c new file mode 100644 index 00000000..c10848d6 --- /dev/null +++ b/test_conformance/integer_ops/main.c @@ -0,0 +1,347 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include "procs.h" +#include "../../test_common/harness/testHarness.h" + +#if !defined(_WIN32) +#include +#endif + +basefn basefn_list[] = { + test_integer_clz, + test_integer_ctz, + test_integer_hadd, + test_integer_rhadd, + test_integer_mul_hi, + test_integer_rotate, + test_integer_clamp, + test_integer_mad_sat, + test_integer_mad_hi, + test_integer_min, + test_integer_max, + test_integer_upsample, + + test_abs, + test_absdiff, + test_add_sat, + test_sub_sat, + + test_integer_addAssign, + test_integer_subtractAssign, + test_integer_multiplyAssign, + test_integer_divideAssign, + test_integer_moduloAssign, + test_integer_andAssign, + test_integer_orAssign, + test_integer_exclusiveOrAssign, + + test_unary_ops_increment, + test_unary_ops_decrement, + test_unary_ops_full, + + test_intmul24, + test_intmad24, + + test_long_math, + test_long_logic, + test_long_shift, + test_long_compare, + + test_ulong_math, + test_ulong_logic, + test_ulong_shift, + test_ulong_compare, + + test_int_math, + test_int_logic, + test_int_shift, + test_int_compare, + + test_uint_math, + test_uint_logic, + test_uint_shift, + test_uint_compare, + + test_short_math, + test_short_logic, + test_short_shift, + test_short_compare, + + test_ushort_math, + test_ushort_logic, + test_ushort_shift, + test_ushort_compare, + + test_char_math, + test_char_logic, + test_char_shift, + test_char_compare, + + test_uchar_math, + test_uchar_logic, + test_uchar_shift, + test_uchar_compare, + + test_popcount, + + + // Quick + test_quick_long_math, + test_quick_long_logic, + test_quick_long_shift, + test_quick_long_compare, + + test_quick_ulong_math, + test_quick_ulong_logic, + test_quick_ulong_shift, + test_quick_ulong_compare, + + test_quick_int_math, + test_quick_int_logic, + test_quick_int_shift, + test_quick_int_compare, + + test_quick_uint_math, + test_quick_uint_logic, + test_quick_uint_shift, + test_quick_uint_compare, + + test_quick_short_math, + test_quick_short_logic, + test_quick_short_shift, + test_quick_short_compare, + + test_quick_ushort_math, + test_quick_ushort_logic, + test_quick_ushort_shift, + test_quick_ushort_compare, + + test_quick_char_math, + test_quick_char_logic, + test_quick_char_shift, + test_quick_char_compare, + + test_quick_uchar_math, + test_quick_uchar_logic, + test_quick_uchar_shift, + test_quick_uchar_compare, + + test_vector_scalar_ops, +}; + + +const char *basefn_names[] = { + "integer_clz", + "integer_ctz", + "integer_hadd", + "integer_rhadd", + "integer_mul_hi", + "integer_rotate", + "integer_clamp", + "integer_mad_sat", + "integer_mad_hi", + "integer_min", + "integer_max", + "integer_upsample", + + "integer_abs", + "integer_abs_diff", + "integer_add_sat", + "integer_sub_sat", + + "integer_addAssign", + "integer_subtractAssign", + "integer_multiplyAssign", + "integer_divideAssign", + "integer_moduloAssign", + "integer_andAssign", + "integer_orAssign", + "integer_exclusiveOrAssign", + + "unary_ops_increment", + "unary_ops_decrement", + "unary_ops_full", + + "integer_mul24", + "integer_mad24", + + "long_math", + "long_logic", + "long_shift", + "long_compare", + + "ulong_math", + "ulong_logic", + "ulong_shift", + "ulong_compare", + + "int_math", + "int_logic", + "int_shift", + "int_compare", + + "uint_math", + "uint_logic", + "uint_shift", + "uint_compare", + + "short_math", + "short_logic", + "short_shift", + "short_compare", + + "ushort_math", + "ushort_logic", + "ushort_shift", + "ushort_compare", + + "char_math", + "char_logic", + "char_shift", + "char_compare", + + "uchar_math", + "uchar_logic", + "uchar_shift", + "uchar_compare", + + "popcount", + + // Quick + "quick_long_math", + "quick_long_logic", + "quick_long_shift", + "quick_long_compare", + + "quick_ulong_math", + "quick_ulong_logic", + "quick_ulong_shift", + "quick_ulong_compare", + + "quick_int_math", + "quick_int_logic", + "quick_int_shift", + "quick_int_compare", + + "quick_uint_math", + "quick_uint_logic", + "quick_uint_shift", + "quick_uint_compare", + + "quick_short_math", + "quick_short_logic", + "quick_short_shift", + "quick_short_compare", + + "quick_ushort_math", + "quick_ushort_logic", + "quick_ushort_shift", + "quick_ushort_compare", + + "quick_char_math", + "quick_char_logic", + "quick_char_shift", + "quick_char_compare", + + "quick_uchar_math", + "quick_uchar_logic", + "quick_uchar_shift", + "quick_uchar_compare", + + "vector_scalar", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + +void fill_test_values( cl_long *outBufferA, cl_long *outBufferB, size_t numElements, MTdata d ) +{ + static const cl_long sUniqueValues[] = { 0x3333333333333333LL, 0x5555555555555555LL, 0x9999999999999999LL, 0xaaaaaaaaaaaaaaaaLL, 0xccccccccccccccccLL, + 0x3030303030303030LL, 0x5050505050505050LL, 0x9090909090909090LL, 0xa0a0a0a0a0a0a0a0LL, 0xc0c0c0c0c0c0c0c0LL, 0xf0f0f0f0f0f0f0f0LL, + 0x0303030303030303LL, 0x0505050505050505LL, 0x0909090909090909LL, 0x0a0a0a0a0a0a0a0aLL, 0x0c0c0c0c0c0c0c0cLL, 0x0f0f0f0f0f0f0f0fLL, + 0x3300330033003300LL, 0x5500550055005500LL, 0x9900990099009900LL, 0xaa00aa00aa00aa00LL, 0xcc00cc00cc00cc00LL, 0xff00ff00ff00ff00LL, + 0x0033003300330033LL, 0x0055005500550055LL, 0x0099009900990099LL, 0x00aa00aa00aa00aaLL, 0x00cc00cc00cc00ccLL, 0x00ff00ff00ff00ffLL, + 0x3333333300000000LL, 0x5555555500000000LL, 0x9999999900000000LL, 0xaaaaaaaa00000000LL, 0xcccccccc00000000LL, 0xffffffff00000000LL, + 0x0000000033333333LL, 0x0000000055555555LL, 0x0000000099999999LL, 0x00000000aaaaaaaaLL, 0x00000000ccccccccLL, 0x00000000ffffffffLL, + 0x3333000000003333LL, 0x5555000000005555LL, 0x9999000000009999LL, 0xaaaa00000000aaaaLL, 0xcccc00000000ccccLL, 0xffff00000000ffffLL}; + static cl_long sSpecialValues[ 128 + 128 + 128 + ( sizeof( sUniqueValues ) / sizeof( sUniqueValues[ 0 ] ) ) ] = { 0 }; + + if( sSpecialValues[ 0 ] == 0 ) + { + // Init the power-of-two special values + for( size_t i = 0; i < 64; i++ ) + { + sSpecialValues[ i ] = 1LL << i; + sSpecialValues[ i + 64 ] = -1LL << i; + sSpecialValues[ i + 128 ] = sSpecialValues[ i ] - 1; + sSpecialValues[ i + 128 + 64 ] = sSpecialValues[ i ] - 1; + sSpecialValues[ i + 256 ] = sSpecialValues[ i ] + 1; + sSpecialValues[ i + 256 + 64 ] = sSpecialValues[ i ] + 1; + } + memcpy( &sSpecialValues[ 128 + 128 + 128 ], sUniqueValues, sizeof( sUniqueValues ) ); + } + + size_t i, aIdx = 0, bIdx = 0; + size_t numSpecials = sizeof( sSpecialValues ) / sizeof( sSpecialValues[ 0 ] ); + + for( i = 0; i < numElements; i++ ) + { + outBufferA[ i ] = sSpecialValues[ aIdx ]; + outBufferB[ i ] = sSpecialValues[ bIdx ]; + bIdx++; + if( bIdx == numSpecials ) + { + bIdx = 0; + aIdx++; + if( aIdx == numSpecials ) + break; + } + } + if( i < numElements ) + { + // Fill remainder with random values + for( ; i < numElements; i++ ) + { + int a = (int)genrand_int32(d); + int b = (int)genrand_int32(d); + outBufferA[ i ] = ((cl_long)a <<33 | (cl_long)b) ^ ((cl_long)b << 16); + + a = (int)genrand_int32(d); + b = (int)genrand_int32(d); + outBufferB[ i ] = ((cl_long)a <<33 | (cl_long)b) ^ ((cl_long)b << 16); + } + } + else if( aIdx < numSpecials ) + { + log_info( "WARNING: Not enough space to fill all special values for long test! (need %d additional elements)\n", (int)( ( numSpecials - aIdx ) * numSpecials ) ); + } +} + + + +int main(int argc, const char *argv[]) +{ + return runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false /* image support required */, false /* force no context creation */, 0 ); +} + + + + diff --git a/test_conformance/integer_ops/procs.h b/test_conformance/integer_ops/procs.h new file mode 100644 index 00000000..90255db7 --- /dev/null +++ b/test_conformance/integer_ops/procs.h @@ -0,0 +1,143 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/threadTesting.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/mt19937.h" + + +// The number of errors to print out for each test +#define MAX_ERRORS_TO_PRINT 10 + +extern const size_t vector_aligns[]; + +extern int create_program_and_kernel(const char *source, const char *kernel_name, cl_program *program_ret, cl_kernel *kernel_ret); +extern void fill_test_values( cl_long *outBufferA, cl_long *outBufferB, size_t numElements, MTdata d ); + + +extern int test_popcount(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_clz(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_ctz(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_hadd(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_rhadd(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_mul_hi(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_rotate(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_clamp(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_mad_sat(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_mad_hi(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_min(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_max(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_upsample(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_integer_addAssign(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_subtractAssign(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_multiplyAssign(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_divideAssign(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_moduloAssign(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_andAssign(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_orAssign(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_integer_exclusiveOrAssign(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_abs(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_absdiff(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_add_sat(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_sub_sat(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_intmul24(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_intmad24(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + + +extern int test_long_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_long_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_long_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_long_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_ulong_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_ulong_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_ulong_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_ulong_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_int_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_int_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_int_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_int_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_uint_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_uint_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_uint_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_uint_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_short_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_short_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_short_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_short_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_ushort_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_ushort_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_ushort_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_ushort_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_char_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_char_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_char_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_char_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_uchar_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_uchar_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_uchar_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_uchar_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + + +extern int test_quick_long_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_long_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_long_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_long_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_ulong_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_ulong_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_ulong_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_ulong_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_quick_int_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_int_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_int_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_int_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_uint_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_uint_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_uint_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_uint_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_quick_short_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_short_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_short_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_short_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_ushort_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_ushort_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_ushort_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_ushort_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_quick_char_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_char_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_char_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_char_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_uchar_math(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_uchar_logic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_uchar_shift(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_quick_uchar_compare(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_unary_ops_full(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_unary_ops_increment(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_unary_ops_decrement(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_vector_scalar_ops(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + diff --git a/test_conformance/integer_ops/testBase.h b/test_conformance/integer_ops/testBase.h new file mode 100644 index 00000000..5073b21f --- /dev/null +++ b/test_conformance/integer_ops/testBase.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testBase_h +#define _testBase_h + +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +#endif // _testBase_h + + + diff --git a/test_conformance/integer_ops/test_abs.c b/test_conformance/integer_ops/test_abs.c new file mode 100644 index 00000000..e8479c53 --- /dev/null +++ b/test_conformance/integer_ops/test_abs.c @@ -0,0 +1,335 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" + + +static int verify_abs_char( const void *p, const void *q, size_t n, const char *sizeName, size_t vecSize ) +{ + const cl_char *inA = (const cl_char*) p; + const cl_uchar *outptr = (const cl_uchar*) q; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_uchar r = inA[i]; + if( inA[i] < 0 ) + r = -inA[i]; + if( r != outptr[i] ) + { log_info( "%ld) Failure for abs( (char%s) 0x%2.2x) = *0x%2.2x vs 0x%2.2x\n", i, sizeName, inA[i],r, outptr[i] ); return -1; } + } + return 0; +} + + +static int verify_abs_short( const void *p, const void *q, size_t n, const char *sizeName, size_t vecSize ) +{ + const cl_short *inA = (const cl_short*) p; + const cl_ushort *outptr = (const cl_ushort*) q; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_ushort r = inA[i]; + if( inA[i] < 0 ) + r = -inA[i]; + if( r != outptr[i] ) + { log_info( "%ld) Failure for abs( (short%s) 0x%4.4x) = *0x%4.4x vs 0x%4.4x\n", i, sizeName, inA[i],r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_abs_int( const void *p, const void *q, size_t n, const char *sizeName , size_t vecSize) +{ + const cl_int *inA = (const cl_int*) p; + const cl_uint *outptr = (const cl_uint*) q; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_uint r = inA[i]; + if( inA[i] < 0 ) + r = -inA[i]; + if( r != outptr[i] ) + { log_info( "%ld) Failure for abs( (int%s) 0x%2.2x) = *0x%8.8x vs 0x%8.8x\n", i, sizeName, inA[i],r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_abs_long( const void *p, const void *q, size_t n, const char *sizeName, size_t vecSize ) +{ + const cl_long *inA = (const cl_long*) p; + const cl_ulong *outptr = (const cl_ulong*) q; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_ulong r = inA[i]; + if( inA[i] < 0 ) + r = -inA[i]; + if( r != outptr[i] ) + { log_info( "%ld) Failure for abs( (long%s) 0x%16.16llx) = *0x%16.16llx vs 0x%16.16llx\n", i, sizeName, inA[i],r, outptr[i] ); return -1; } + } + return 0; +} + + + +static int verify_abs_uchar( const void *p, const void *q, size_t n, const char *sizeName, size_t vecSize ) +{ + const cl_uchar *inA = (const cl_uchar*) p; + const cl_uchar *outptr = (const cl_uchar*) q; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_uchar r = inA[i]; + if( r != outptr[i] ) + { log_info( "%ld) Failure for abs( (uchar%s) 0x%2.2x) = *0x%2.2x vs 0x%2.2x\n", i, sizeName, inA[i],r, outptr[i] ); return -1; } + } + return 0; +} + + +static int verify_abs_ushort( const void *p, const void *q, size_t n, const char *sizeName, size_t vecSize ) +{ + const cl_ushort *inA = (const cl_ushort*) p; + const cl_ushort *outptr = (const cl_ushort*) q; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_ushort r = inA[i]; + if( r != outptr[i] ) + { log_info( "%ld) Failure for abs( (short%s) 0x%4.4x) = *0x%4.4x vs 0x%4.4x\n", i, sizeName, inA[i],r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_abs_uint( const void *p, const void *q, size_t n, const char *sizeName , size_t vecSize) +{ + const cl_uint *inA = (const cl_uint*) p; + const cl_uint *outptr = (const cl_uint*) q; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_uint r = inA[i]; + if( r != outptr[i] ) + { log_info( "%ld) Failure for abs( (int%s) 0x%2.2x) = *0x%8.8x vs 0x%8.8x\n", i, sizeName, inA[i],r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_abs_ulong( const void *p, const void *q, size_t n, const char *sizeName, size_t vecSize ) +{ + const cl_ulong *inA = (const cl_ulong*) p; + const cl_ulong *outptr = (const cl_ulong*) q; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_ulong r = inA[i]; + if( r != outptr[i] ) + { log_info( "%ld) Failure for abs( (long%s) 0x%16.16llx) = *0x%16.16llx vs 0x%16.16llx\n", i, sizeName, inA[i],r, outptr[i] ); return -1; } + } + return 0; +} + + +typedef int (*verifyFunc)( const void *, const void *, size_t n, const char *sizeName, size_t vecSize ); +static const verifyFunc verify[] = { + verify_abs_char, verify_abs_short, verify_abs_int, verify_abs_long, + verify_abs_uchar, verify_abs_ushort, verify_abs_uint, verify_abs_ulong +}; + +static const char *test_str_names[] = { "char", "short", "int", "long" , + "uchar", "ushort", "uint", "ulong"}; +static const char *test_ustr_names[] = { "uchar", "ushort", "uint", "ulong" , + "uchar", "ushort", "uint", "ulong"}; +static const int vector_sizes[] = {1, 2, 3, 4, 8, 16}; +static const char *vector_size_names[] = { "", "2", "3", "4", "8", "16" }; +static const char *vector_size_names_io_types[] = { "", "2", "", "4", "8", "16" }; +static const size_t kSizes[9] = { 1, 2, 4, 8, 1, 2, 4, 8 }; + +static const char * source_loads[] = { + "srcA[tid]", + "vload3(tid, srcA)" +}; + +static const char * dest_stores[] = { + " dst[tid] = tmp;\n", + " vstore3(tmp, tid, dst);\n" +}; + +int test_abs(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_int *input_ptr, *output_ptr, *p; + int err; + int i; + cl_uint vectorSizeIdx; + cl_uint type; + MTdata d; + int fail_count = 0; + + size_t length = sizeof(cl_int) * 4 * n_elems; + + input_ptr = (cl_int*)malloc(length); + output_ptr = (cl_int*)malloc(length); + + p = input_ptr; + d = init_genrand( gRandomSeed ); + for (i=0; i +#include +#include +#include + +#include "procs.h" + +static int verify_absdiff_char( const void *p, const void *q, const void *r, size_t n, const char *sizeName, size_t vecSize ) +{ + const cl_char *inA = (const cl_char *)p; + const cl_char *inB = (const cl_char *)q; + const cl_uchar *outptr = (const cl_uchar *)r; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_uchar r = inA[i] - inB[i]; + if( inB[i] > inA[i] ) + r = inB[i] - inA[i]; + if( r != outptr[i] ) + { log_info( "%ld) Failure for absdiff( (char%s) 0x%2.2x, (char%s) 0x%2.2x) = *0x%2.2x vs 0x%2.2x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_absdiff_uchar( const void *p, const void *q, const void *r, size_t n, const char *sizeName, size_t vecSize ) +{ + const cl_uchar *inA = (const cl_uchar *)p; + const cl_uchar *inB = (const cl_uchar *)q; + const cl_uchar *outptr = (const cl_uchar *)r; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_uchar r = inA[i] - inB[i]; + if( inB[i] > inA[i] ) + r = inB[i] - inA[i]; + if( r != outptr[i] ) + { log_info( "%ld) Failure for absdiff( (uchar%s) 0x%2.2x, (uchar%s) 0x%2.2x) = *0x%2.2x vs 0x%2.2x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_absdiff_short( const void *p, const void *q, const void *r, size_t n, const char *sizeName, size_t vecSize ) +{ + const cl_short *inA = (const cl_short *)p; + const cl_short *inB = (const cl_short *)q; + const cl_ushort *outptr = (const cl_ushort *)r; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_ushort r = inA[i] - inB[i]; + if( inB[i] > inA[i] ) + r = inB[i] - inA[i]; + if( r != outptr[i] ) + { log_info( "%ld) Failure for absdiff( (short%s) 0x%4.4x, (short%s) 0x%4.4x) = *0x%4.4x vs 0x%4.4x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_absdiff_ushort( const void *p, const void *q, const void *r, size_t n, const char *sizeName, size_t vecSize ) +{ + const cl_ushort *inA = (const cl_ushort *)p; + const cl_ushort *inB = (const cl_ushort *)q; + const cl_ushort *outptr = (const cl_ushort *)r; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_ushort r = inA[i] - inB[i]; + if( inB[i] > inA[i] ) + r = inB[i] - inA[i]; + if( r != outptr[i] ) + { log_info( "%ld) Failure for absdiff( (ushort%s) 0x%4.4x, (ushort%s) 0x%4.4x) = *0x%4.4x vs 0x%4.4x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_absdiff_int( const void *p, const void *q, const void *r, size_t n, const char *sizeName, size_t vecSize ) +{ + const cl_int *inA = (const cl_int *)p; + const cl_int *inB = (const cl_int *)q; + const cl_uint *outptr = (const cl_uint *)r; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_uint r = inA[i] - inB[i]; + if( inB[i] > inA[i] ) + r = inB[i] - inA[i]; + if( r != outptr[i] ) + { + log_info( "%ld) Failure for absdiff( (int%s) 0x%8.8x, (int%s) 0x%8.8x) = *0x%8.8x vs 0x%8.8x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); + return -1; + } + } + return 0; +} + +static int verify_absdiff_uint( const void *p, const void *q, const void *r, size_t n, const char *sizeName, size_t vecSize ) +{ + const cl_uint *inA = (const cl_uint *)p; + const cl_uint *inB = (const cl_uint *)q; + const cl_uint *outptr = (const cl_uint *)r; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_uint r = inA[i] - inB[i]; + if( inB[i] > inA[i] ) + r = inB[i] - inA[i]; + if( r != outptr[i] ) + { log_info( "%ld) Failure for absdiff( (uint%s) 0x%8.8x, (uint%s) 0x%8.8x) = *0x%8.8x vs 0x%8.8x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_absdiff_long( const void *p, const void *q, const void *r, size_t n, const char *sizeName, size_t vecSize ) +{ + const cl_long *inA = (const cl_long *)p; + const cl_long *inB = (const cl_long *)q; + const cl_ulong *outptr = (const cl_ulong *)r; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_ulong r = inA[i] - inB[i]; + if( inB[i] > inA[i] ) + r = inB[i] - inA[i]; + if( r != outptr[i] ) + { log_info( "%ld) Failure for absdiff( (long%s) 0x%16.16llx, (long%s) 0x%16.16llx) = *0x%16.16llx vs 0x%16.16llx\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_absdiff_ulong( const void *p, const void *q, const void *r, size_t n, const char *sizeName, size_t vecSize ) +{ + const cl_ulong *inA = (const cl_ulong *)p; + const cl_ulong *inB = (const cl_ulong *)q; + const cl_ulong *outptr = (const cl_ulong *)r; + size_t i; + for( i = 0; i < n; i++ ) + { + cl_ulong r = inA[i] - inB[i]; + if( inB[i] > inA[i] ) + r = inB[i] - inA[i]; + if( r != outptr[i] ) + { log_info( "%ld) Failure for absdiff( (ulong%s) 0x%16.16llx, (ulong%s) 0x%16.16llx) = *0x%16.16llx vs 0x%16.16llx\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +typedef int (*verifyFunc)( const void *, const void *, const void *, size_t n, const char *sizeName, size_t vecSize); +static const verifyFunc verify[] = { verify_absdiff_char, verify_absdiff_uchar, + verify_absdiff_short, verify_absdiff_ushort, + verify_absdiff_int, verify_absdiff_uint, + verify_absdiff_long, verify_absdiff_ulong }; + +//FIXME: enable long and ulong when GPU path is working +static const char *test_str_names[] = { "char", "uchar", "short", "ushort", "int", "uint", "long", "ulong" }; + +//FIXME: enable "16" when support for > 64 byte vectors go into LLVM +static const int vector_sizes[] = {1, 2, 3, 4, 8, 16}; +static const char *vector_size_names[] = { "", "2", "3", "4", "8", "16" }; +static const char *vector_param_size_names[] = { "", "2", "", "4", "8", "16" }; +static const size_t kSizes[8] = { 1, 1, 2, 2, 4, 4, 8, 8 }; + +static void printSrc(const char *src[], int nSrcStrings) { + int i; + for(i = 0; i < nSrcStrings; ++i) { + log_info("%s", src[i]); + } +} + +int test_absdiff(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_int *input_ptr[2], *output_ptr, *p; + int err; + int i; + cl_uint vectorSize; + cl_uint type; + MTdata d; + int fail_count = 0; + + size_t length = sizeof(cl_int) * 4 * n_elems; + + input_ptr[0] = (cl_int*)malloc(length); + input_ptr[1] = (cl_int*)malloc(length); + output_ptr = (cl_int*)malloc(length); + + d = init_genrand( gRandomSeed ); + p = input_ptr[0]; + for (i=0; i<4 * n_elems; i++) + p[i] = genrand_int32(d); + p = input_ptr[1]; + for (i=0; i<4 * n_elems; i++) + p[i] = genrand_int32(d); + free_mtdata(d); d = NULL; + + for( type = 0; type < sizeof( test_str_names ) / sizeof( test_str_names[0] ); type++ ) + { + //embedded devices don't support long/ulong so skip over + if (! gHasLong && strstr(test_str_names[type],"long")) + { + log_info( "WARNING: 64 bit integers are not supported on this device. Skipping %s\n", test_str_names[type] ); + continue; + } + + verifyFunc f = verify[ type ]; + // Note: restrict the element count here so we don't end up overrunning the output buffer if we're compensating for 32-bit writes + size_t elementCount = length / kSizes[type]; + cl_mem streams[3]; + + log_info( "%s", test_str_names[type] ); + fflush( stdout ); + + // Set up data streams for the type + streams[0] = clCreateBuffer(context, 0, length, NULL, NULL); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer(context, 0, length, NULL, NULL); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer(context, 0, length, NULL, NULL); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + err = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, length, input_ptr[0], 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + err = clEnqueueWriteBuffer(queue, streams[1], CL_TRUE, 0, length, input_ptr[1], 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + + for( vectorSize = 0; vectorSize < sizeof( vector_size_names ) / sizeof( vector_size_names[0] ); vectorSize++ ) + { + cl_program program = NULL; + cl_kernel kernel = NULL; + + const char *source[] = { + "__kernel void test_absdiff_", test_str_names[type], vector_size_names[vectorSize], + "(__global ", test_str_names[type], vector_param_size_names[vectorSize], + " *srcA, __global ", test_str_names[type], vector_param_size_names[vectorSize], + " *srcB, __global u", test_str_names[type & -2], vector_param_size_names[vectorSize], + " *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " ", test_str_names[type], vector_size_names[vectorSize], " sA, sB;\n", + " sA = ", ( vector_sizes[ vectorSize ] == 3 ) ? "vload3( tid, srcA )" : "srcA[tid]", ";\n", + " sB = ", ( vector_sizes[ vectorSize ] == 3 ) ? "vload3( tid, srcB )" : "srcB[tid]", ";\n", + " u", test_str_names[type & -2], vector_size_names[vectorSize], " dstVal = abs_diff(sA, sB);\n" + " ", ( vector_sizes[ vectorSize ] == 3 ) ? "vstore3( dstVal, tid, dst )" : "dst[ tid ] = dstVal", ";\n", + "}\n" }; + + + char kernelName[128]; + snprintf( kernelName, sizeof( kernelName ), "test_absdiff_%s%s", test_str_names[type], vector_size_names[vectorSize] ); + + err = create_single_kernel_helper(context, &program, &kernel, sizeof( source ) / sizeof( source[0] ), source, kernelName ); + + if (err) { + return -1; + } + +#if 0 + log_info("About to run\n"); + log_info("=====\n"); + printSrc(source, sizeof(source)/sizeof(source[0])); + log_info("=====\n"); +#endif + + err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]); + err |= clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]); + err |= clSetKernelArg(kernel, 2, sizeof streams[2], &streams[2]); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + //Wipe the output buffer clean + uint32_t pattern = 0xdeadbeef; + memset_pattern4( output_ptr, &pattern, length ); + err = clEnqueueWriteBuffer(queue, streams[2], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + + size_t size = elementCount / (vector_sizes[vectorSize]); + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &size, NULL, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + err = clEnqueueReadBuffer(queue, streams[2], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueReadBuffer failed\n"); + return -1; + } + + char *inP = (char *)input_ptr[0]; + char *inP2 = (char *)input_ptr[1]; + char *outP = (char *)output_ptr; + + for( size_t e = 0; e < size; e++ ) + { + if( f( inP, inP2, outP, (vector_sizes[vectorSize]), vector_size_names[vectorSize], vector_sizes[vectorSize] ) ) { + printSrc(source, sizeof(source)/sizeof(source[0])); + ++fail_count; break; // return -1; + } + inP += kSizes[type] * ( (vector_sizes[vectorSize]) ); + inP2 += kSizes[type] * ( (vector_sizes[vectorSize]) ); + outP += kSizes[type] * ( (vector_sizes[vectorSize]) ); + } + + clReleaseKernel( kernel ); + clReleaseProgram( program ); + log_info( "." ); + fflush( stdout ); + } + + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + clReleaseMemObject( streams[2] ); + log_info( "done\n" ); + } + + + if(fail_count) { + log_info("Failed on %d types\n", fail_count); + return -1; + } + log_info("ABS_DIFF test passed\n"); + + free(input_ptr[0]); + free(input_ptr[1]); + free(output_ptr); + + return err; +} + + diff --git a/test_conformance/integer_ops/test_add_sat.c b/test_conformance/integer_ops/test_add_sat.c new file mode 100644 index 00000000..702b735b --- /dev/null +++ b/test_conformance/integer_ops/test_add_sat.c @@ -0,0 +1,378 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" + +#define UCHAR_MIN 0 +#define USHRT_MIN 0 +#define UINT_MIN 0 + +#ifndef MAX +#define MAX( _a, _b ) ( (_a) > (_b) ? (_a) : (_b) ) +#endif +#ifndef MIN +#define MIN( _a, _b ) ( (_a) < (_b) ? (_a) : (_b) ) +#endif + +static int verify_addsat_char( const cl_char *inA, const cl_char *inB, const cl_char *outptr, int n, const char *sizeName, int vecSize ) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_int r = (cl_int) inA[i] + (cl_int) inB[i]; + r = MAX( r, CL_CHAR_MIN ); + r = MIN( r, CL_CHAR_MAX ); + + if( r != outptr[i] ) + { log_info( "\n%d) Failure for add_sat( (char%s) 0x%2.2x, (char%s) 0x%2.2x) = *0x%2.2x vs 0x%2.2x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_addsat_uchar( const cl_uchar *inA, const cl_uchar *inB, const cl_uchar *outptr, int n, const char *sizeName, int vecSize ) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_int r = (int) inA[i] + (int) inB[i]; + r = MAX( r, 0 ); + r = MIN( r, CL_UCHAR_MAX ); + if( r != outptr[i] ) + { log_info( "\n%d) Failure for add_sat( (uchar%s) 0x%2.2x, (uchar%s) 0x%2.2x) = *0x%2.2x vs 0x%2.2x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_addsat_short( const cl_short *inA, const cl_short *inB, const cl_short *outptr, int n, const char *sizeName , int vecSize) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_int r = (cl_int) inA[i] + (cl_int) inB[i]; + r = MAX( r, CL_SHRT_MIN ); + r = MIN( r, CL_SHRT_MAX ); + + if( r != outptr[i] ) + { log_info( "\n%d) Failure for add_sat( (short%s) 0x%4.4x, (short%s) 0x%4.4x) = *0x%4.4x vs 0x%4.4x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_addsat_ushort( const cl_ushort *inA, const cl_ushort *inB, const cl_ushort *outptr, int n, const char *sizeName , int vecSize) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_int r = (cl_int) inA[i] + (cl_int) inB[i]; + r = MAX( r, 0 ); + r = MIN( r, CL_USHRT_MAX ); + + if( r != outptr[i] ) + { log_info( "\n%d) Failure for add_sat( (ushort%s) 0x%4.4x, (ushort%s) 0x%4.4x) = *0x%4.4x vs 0x%4.4x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_addsat_int( const cl_int *inA, const cl_int *inB, const cl_int *outptr, int n, const char *sizeName , int vecSize) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_int r = (cl_int) ((cl_uint) inA[i] + (cl_uint)inB[i]); + if( inB[i] > 0 ) + { + if( r < inA[i] ) + r = CL_INT_MAX; + } + else + { + if( r > inA[i] ) + r = CL_INT_MIN; + } + + + if( r != outptr[i] ) + { log_info( "\n%d) Failure for add_sat( (int%s) 0x%8.8x, (int%s) 0x%8.8x) = *0x%8.8x vs 0x%8.8x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_addsat_uint( const cl_uint *inA, const cl_uint *inB, const cl_uint *outptr, int n, const char *sizeName , int vecSize) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_uint r = inA[i] + inB[i]; + if( r < inA[i] ) + r = CL_UINT_MAX; + + if( r != outptr[i] ) + { log_info( "\n%d) Failure for add_sat( (uint%s) 0x%8.8x, (uint%s) 0x%8.8x) = *0x%8.8x vs 0x%8.8x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_addsat_long( const cl_long *inA, const cl_long *inB, const cl_long *outptr, int n, const char *sizeName , int vecSize) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_long r = (cl_long)((cl_ulong)inA[i] + (cl_ulong)inB[i]); + if( inB[i] > 0 ) + { + if( r < inA[i] ) + r = CL_LONG_MAX; + } + else + { + if( r > inA[i] ) + r = CL_LONG_MIN; + } + if( r != outptr[i] ) + { log_info( "%d) Failure for add_sat( (long%s) 0x%16.16llx, (long%s) 0x%16.16llx) = *0x%16.16llx vs 0x%16.16llx\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_addsat_ulong( const cl_ulong *inA, const cl_ulong *inB, const cl_ulong *outptr, int n, const char *sizeName , int vecSize) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_ulong r = inA[i] + inB[i]; + if( r < inA[i] ) + r = CL_ULONG_MAX; + if( r != outptr[i] ) + { log_info( "%d) Failure for add_sat( (ulong%s) 0x%16.16llx, (ulong%s) 0x%16.16llx) = *0x%16.16llx vs 0x%16.16llx\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +typedef int (*verifyFunc)( const void *, const void *, const void *, int n, const char *sizeName, int ); +static const verifyFunc verify[] = { (verifyFunc) verify_addsat_char, (verifyFunc) verify_addsat_uchar, + (verifyFunc) verify_addsat_short, (verifyFunc) verify_addsat_ushort, + (verifyFunc) verify_addsat_int, (verifyFunc) verify_addsat_uint, + (verifyFunc) verify_addsat_long, (verifyFunc) verify_addsat_ulong }; +//FIXME: enable long and ulong when GPU path is working +static const char *test_str_names[] = { "char", "uchar", "short", "ushort", "int", "uint", "long", "ulong" }; + +//FIXME: enable "16" when support for > 64 byte vectors go into LLVM +static const int vector_sizes[] = {1, 2, 3, 4, 8, 16}; +static const char *vector_size_names[] = { "", "2", "3", "4", "8", "16" }; +static const size_t kSizes[8] = { 1, 1, 2, 2, 4, 4, 8, 8 }; + +int test_add_sat(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_int *input_ptr[2], *output_ptr, *p; + int err; + int i; + cl_uint vectorSize; + cl_uint type; + MTdata d; + int fail_count = 0; + + size_t length = sizeof(cl_int) * 4 * n_elems; + + input_ptr[0] = (cl_int*)malloc(length); + input_ptr[1] = (cl_int*)malloc(length); + output_ptr = (cl_int*)malloc(length); + + d = init_genrand( gRandomSeed ); + p = input_ptr[0]; + for (i=0; i<4 * n_elems; i++) + p[i] = genrand_int32(d); + p = input_ptr[1]; + for (i=0; i<4 * n_elems; i++) + p[i] = genrand_int32(d); + free_mtdata(d); d = NULL; + + for( type = 0; type < sizeof( test_str_names ) / sizeof( test_str_names[0] ); type++ ) + { + + //embedded devices don't support long/ulong so skip over + if (! gHasLong && strstr(test_str_names[type],"long")) + { + log_info( "WARNING: 64 bit integers are not supported on this device. Skipping %s\n", test_str_names[type] ); + continue; + } + + verifyFunc f = verify[ type ]; + // Note: restrict the element count here so we don't end up overrunning the output buffer if we're compensating for 32-bit writes + size_t elementCount = length / kSizes[type]; + cl_mem streams[3]; + + log_info( "%s", test_str_names[type] ); + fflush( stdout ); + + // Set up data streams for the type + streams[0] = clCreateBuffer(context, 0, length, NULL, NULL); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer(context, 0, length, NULL, NULL); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer(context, 0, length, NULL, NULL); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + err = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, length, input_ptr[0], 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + err = clEnqueueWriteBuffer(queue, streams[1], CL_TRUE, 0, length, input_ptr[1], 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + + for( vectorSize = 0; vectorSize < sizeof( vector_size_names ) / sizeof( vector_size_names[0] ); vectorSize++ ) + { + cl_program program = NULL; + cl_kernel kernel = NULL; + + const char *source[] = { + "__kernel void test_add_sat_", test_str_names[type], vector_size_names[vectorSize], + "(__global ", test_str_names[type], vector_size_names[vectorSize], + " *srcA, __global ", test_str_names[type], vector_size_names[vectorSize], + " *srcB, __global ", test_str_names[type], vector_size_names[vectorSize], + " *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " ", test_str_names[type], vector_size_names[vectorSize], " tmp = add_sat(srcA[tid], srcB[tid]);\n" + " dst[tid] = tmp;\n" + "}\n" }; + + + const char *sourceV3[] = { + "__kernel void test_add_sat_", test_str_names[type], vector_size_names[vectorSize], + "(__global ", test_str_names[type], + " *srcA, __global ", test_str_names[type], + " *srcB, __global ", test_str_names[type], + " *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " ", test_str_names[type], vector_size_names[vectorSize], " tmp = add_sat(vload3(tid, srcA), vload3(tid, srcB));\n" + " vstore3(tmp, tid, dst);\n" + "}\n" }; + + char kernelName[128]; + snprintf( kernelName, sizeof( kernelName ), "test_add_sat_%s%s", test_str_names[type], vector_size_names[vectorSize] ); + if(vector_sizes[vectorSize] != 3) + { + err = create_single_kernel_helper(context, &program, &kernel, sizeof( source ) / sizeof( source[0] ), source, kernelName ); + } + else + { + err = create_single_kernel_helper(context, &program, &kernel, sizeof( sourceV3 ) / sizeof( sourceV3[0] ), sourceV3, kernelName ); + } + if (err) + return -1; + + err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]); + err |= clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]); + err |= clSetKernelArg(kernel, 2, sizeof streams[2], &streams[2]); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + //Wipe the output buffer clean + uint32_t pattern = 0xdeadbeef; + memset_pattern4( output_ptr, &pattern, length ); + err = clEnqueueWriteBuffer(queue, streams[2], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clWriteArray failed\n"); + return -1; + } + + size_t size = elementCount / (vector_sizes[vectorSize]); + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &size, NULL, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clExecuteKernel failed\n"); + return -1; + } + + err = clEnqueueReadBuffer(queue, streams[2], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clReadArray failed\n"); + return -1; + } + + char *inP = (char *)input_ptr[0]; + char *inP2 = (char *)input_ptr[1]; + char *outP = (char *)output_ptr; + + for( size_t e = 0; e < size; e++ ) + { + if( f( inP, inP2, outP, (vector_sizes[vectorSize]), vector_size_names[vectorSize], vector_sizes[vectorSize] ) ) { + ++fail_count; break; // return -1; + } + inP += kSizes[type] * vector_sizes[vectorSize]; + inP2 += kSizes[type] * vector_sizes[vectorSize]; + outP += kSizes[type] * vector_sizes[vectorSize]; + } + + clReleaseKernel( kernel ); + clReleaseProgram( program ); + log_info( "." ); + fflush( stdout ); + } + + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + clReleaseMemObject( streams[2] ); + log_info( "done\n" ); + } + if(fail_count) { + log_info("Failed on %d types\n", fail_count); + return -1; + } + + log_info("ADD_SAT test passed\n"); + + free(input_ptr[0]); + free(input_ptr[1]); + free(output_ptr); + + return err; +} + + diff --git a/test_conformance/integer_ops/test_int_basic_ops.c b/test_conformance/integer_ops/test_int_basic_ops.c new file mode 100644 index 00000000..64040251 --- /dev/null +++ b/test_conformance/integer_ops/test_int_basic_ops.c @@ -0,0 +1,1551 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/ThreadPool.h" + +#define NUM_TESTS 23 + +#define LONG_MATH_SHIFT_SIZE 26 +#define QUICK_MATH_SHIFT_SIZE 16 + +static const char *kernel_code = +"__kernel void test(__global %s%s *srcA, __global %s%s *srcB, __global %s%s *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] %s srcB[tid];\n" +"}\n"; + +static const char *kernel_code_V3 = +"__kernel void test(__global %s /*%s*/ *srcA, __global %s/*%s*/ *srcB, __global %s/*%s*/ *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" vstore3( vload3( tid, srcA ) %s vload3( tid, srcB), tid, dst );\n" +"}\n"; + +static const char *kernel_code_V3_scalar_vector = +"__kernel void test(__global %s /*%s*/ *srcA, __global %s/*%s*/ *srcB, __global %s/*%s*/ *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" vstore3( srcA[tid] %s vload3( tid, srcB), tid, dst );\n" +"}\n"; + +static const char *kernel_code_V3_vector_scalar = +"__kernel void test(__global %s /*%s*/ *srcA, __global %s/*%s*/ *srcB, __global %s/*%s*/ *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" vstore3( vload3( tid, srcA ) %s srcB[tid], tid, dst );\n" +"}\n"; + + +// Separate kernel here because it does not fit the pattern +static const char *not_kernel_code = +"__kernel void test(__global %s%s *srcA, __global %s%s *srcB, __global %s%s *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = %ssrcA[tid];\n" +"}\n"; + +static const char *not_kernel_code_V3 = +"__kernel void test(__global %s /*%s*/ *srcA, __global %s/*%s*/ *srcB, __global %s/*%s*/ *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" vstore3( %s vload3( tid, srcA ), tid, dst );\n" +"}\n"; + +static const char *kernel_code_scalar_shift = +"__kernel void test(__global %s%s *srcA, __global %s%s *srcB, __global %s%s *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = srcA[tid] %s srcB[tid]%s;\n" +"}\n"; + +static const char *kernel_code_scalar_shift_V3 = +"__kernel void test(__global %s/*%s*/ *srcA, __global %s/*%s*/ *srcB, __global %s/*%s*/ *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" vstore3( vload3( tid, srcA) %s vload3( tid, srcB )%s, tid, dst );\n" +"}\n"; + +static const char *kernel_code_question_colon = +"__kernel void test(__global %s%s *srcA, __global %s%s *srcB, __global %s%s *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (srcA[tid]%s < srcB[tid]%s) ? srcA[tid] : srcB[tid];\n" +"}\n"; + +static const char *kernel_code_question_colon_V3 = +"__kernel void test(__global %s/*%s*/ *srcA, __global %s/*%s*/ *srcB, __global %s/*%s*/ *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" vstore3( (vload3( tid, srcA)%s < vload3(tid, srcB)%s) ? vload3( tid, srcA) : vload3( tid, srcB), tid, dst );\n" +"}\n"; + + + + +// External verification and data generation functions +extern const char *tests[]; +extern const char *test_names[]; +extern int verify_long(int test, size_t vector_size, cl_long *inptrA, cl_long *inptrB, cl_long *outptr, size_t n); +extern void init_long_data(uint64_t indx, int num_elements, cl_long *input_ptr[], MTdata d) ; +extern int verify_ulong(int test, size_t vector_size, cl_ulong *inptrA, cl_ulong *inptrB, cl_ulong *outptr, size_t n); +extern void init_ulong_data(uint64_t indx, int num_elements, cl_ulong *input_ptr[], MTdata d) ; +extern int verify_int(int test, size_t vector_size, cl_int *inptrA, cl_int *inptrB, cl_int *outptr, size_t n); +extern void init_int_data(uint64_t indx, int num_elements, cl_int *input_ptr[], MTdata d) ; +extern int verify_uint(int test, size_t vector_size, cl_uint *inptrA, cl_uint *inptrB, cl_uint *outptr, size_t n); +extern void init_uint_data(uint64_t indx, int num_elements, cl_uint *input_ptr[], MTdata d) ; +extern int verify_short(int test, size_t vector_size, cl_short *inptrA, cl_short *inptrB, cl_short *outptr, size_t n); +extern void init_short_data(uint64_t indx, int num_elements, cl_short *input_ptr[], MTdata d) ; +extern int verify_ushort(int test, size_t vector_size, cl_ushort *inptrA, cl_ushort *inptrB, cl_ushort *outptr, size_t n); +extern void init_ushort_data(uint64_t indx, int num_elements, cl_ushort *input_ptr[], MTdata d) ; +extern int verify_char(int test, size_t vector_size, cl_char *inptrA, cl_char *inptrB, cl_char *outptr, size_t n); +extern void init_char_data(uint64_t indx, int num_elements, cl_char *input_ptr[], MTdata d) ; +extern int verify_uchar(int test, size_t vector_size, cl_uchar *inptrA, cl_uchar *inptrB, cl_uchar *outptr, size_t n); +extern void init_uchar_data(uint64_t indx, int num_elements, cl_uchar *input_ptr[], MTdata d) ; + +// Supported type list +const ExplicitType types[] = { + kChar, + kUChar, + kShort, + kUShort, + kInt, + kUInt, + kLong, + kULong, +}; + +enum TestStyle +{ + kDontCare=0, + kBothVectors, + kInputAScalar, + kInputBScalar, + kVectorScalarScalar, // for the ?: operator only; indicates vector ? scalar : scalar. + kInputCAlsoScalar = 0x80 // Or'ed flag to indicate that the selector for the ?: operator is also scalar +}; + +typedef struct _perThreadData +{ + cl_mem m_streams[3]; + cl_int *m_input_ptr[2], *m_output_ptr; + size_t m_type_size; + cl_program m_program[NUM_TESTS]; + cl_kernel m_kernel[NUM_TESTS]; +} perThreadData; + + +perThreadData * perThreadDataNew() +{ + perThreadData * pThis = (perThreadData *)malloc(sizeof(perThreadData)); + + + memset(pThis->m_program, 0, sizeof(cl_program)*NUM_TESTS); + memset(pThis->m_kernel, 0, sizeof(cl_kernel)*NUM_TESTS); + + pThis->m_input_ptr[0] = pThis->m_input_ptr[1] = NULL; + pThis->m_output_ptr = NULL; + + return pThis; +} + + +void perThreadDataDestroy(perThreadData * pThis) +{ + int i; + // cleanup + clReleaseMemObject(pThis->m_streams[0]); + clReleaseMemObject(pThis->m_streams[1]); + clReleaseMemObject(pThis->m_streams[2]); + for (i=0; im_kernel[i] != NULL) clReleaseKernel(pThis->m_kernel[i]); + if (pThis->m_program[i] != NULL) clReleaseProgram(pThis->m_program[i]); + } + free(pThis->m_input_ptr[0]); + free(pThis->m_input_ptr[1]); + free(pThis->m_output_ptr); + + free(pThis); +} + + +cl_int perThreadDataInit(perThreadData * pThis, ExplicitType type, + int num_elements, int vectorSize, + int inputAVecSize, int inputBVecSize, + cl_context context, int start_test_ID, + int end_test_ID, int testID) +{ + int i; + const char * sizeNames[] = { "", "", "2", "3", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + + const char *type_name = get_explicit_type_name(type); + pThis->m_type_size = get_explicit_type_size(type); + int err; + // Used for the && and || tests where the vector case returns a signed value + const char *signed_type_name; + switch (type) { + case kChar: + case kUChar: + signed_type_name = get_explicit_type_name(kChar); + break; + case kShort: + case kUShort: + signed_type_name = get_explicit_type_name(kShort); + break; + case kInt: + case kUInt: + signed_type_name = get_explicit_type_name(kInt); + break; + case kLong: + case kULong: + signed_type_name = get_explicit_type_name(kLong); + break; + default: + log_error("Invalid type.\n"); + return -1; + break; + } + + pThis->m_input_ptr[0] = + (cl_int*)malloc(pThis->m_type_size * num_elements * vectorSize); + pThis->m_input_ptr[1] = + (cl_int*)malloc(pThis->m_type_size * num_elements * vectorSize); + pThis->m_output_ptr = + (cl_int*)malloc(pThis->m_type_size * num_elements * vectorSize); + pThis->m_streams[0] = + clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), pThis->m_type_size * num_elements * inputAVecSize, NULL, &err); + + test_error(err, "clCreateBuffer failed"); + + pThis->m_streams[1] = + clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), pThis->m_type_size * num_elements * inputBVecSize, NULL, &err ); + + test_error(err, "clCreateBuffer failed"); + + pThis->m_streams[2] = + clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), pThis->m_type_size * num_elements * vectorSize, NULL, &err ); + + test_error(err, "clCreateBuffer failed"); + + const char *vectorString = sizeNames[ vectorSize ]; + const char *inputAVectorString = sizeNames[ inputAVecSize ]; + const char *inputBVectorString = sizeNames[ inputBVecSize ]; + + if (testID == -1) + { + log_info("\tTesting %s%s (%d bytes)...\n", type_name, vectorString, (int)(pThis->m_type_size*vectorSize)); + } + + char programString[4096]; + const char *ptr; + + + const char * kernel_code_base = ( vectorSize != 3 ) ? kernel_code : ( inputAVecSize == 1 ) ? kernel_code_V3_scalar_vector : ( inputBVecSize == 1 ) ? kernel_code_V3_vector_scalar : kernel_code_V3; + + for (i=start_test_ID; i 1 + sprintf(programString, kernel_code_base, type_name, inputAVectorString, type_name, inputBVectorString, + ((vectorSize == 1) ? type_name : signed_type_name), vectorString, tests[i]); + break; + case 22: + // Need an unsigned result here for vector sizes > 1 + sprintf(programString, vectorSize == 3 ? not_kernel_code_V3 : not_kernel_code, type_name, inputAVectorString, type_name, inputBVectorString, + ((vectorSize == 1) ? type_name : signed_type_name), vectorString, tests[i]); + break; + default: + sprintf(programString, kernel_code_base, type_name, inputAVectorString, type_name, inputBVectorString, + type_name, vectorString, tests[i]); + break; + } + + //printf("kernel: %s\n", programString); + ptr = programString; + err = create_single_kernel_helper( context, + &(pThis->m_program[ i ]), + &(pThis->m_kernel[ i ]), 1, + &ptr, "test" ); + test_error( err, "Unable to create test kernel" ); + err = clSetKernelArg(pThis->m_kernel[i], 0, + sizeof pThis->m_streams[0], + &(pThis->m_streams[0]) ); + err |= clSetKernelArg(pThis->m_kernel[i], 1, + sizeof pThis->m_streams[1], + &(pThis->m_streams[1]) ); + err |= clSetKernelArg(pThis->m_kernel[i], 2, + sizeof pThis->m_streams[2], + &(pThis->m_streams[2]) ); + test_error(err, "clSetKernelArgs failed"); + } + + return CL_SUCCESS; +} + +typedef struct _globalThreadData +{ + cl_device_id m_deviceID; + cl_context m_context; + // cl_command_queue m_queue; + int m_num_elements; + int m_threadcount; + int m_vectorSize; + int m_num_runs_shift; + TestStyle m_style; + ExplicitType m_type; + MTdata * m_pRandData; + uint64_t m_offset; + int m_testID; + perThreadData **m_arrPerThreadData; +} globalThreadData; + + + +globalThreadData * globalThreadDataNew(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements, + int vectorSize, TestStyle style, int num_runs_shift, + ExplicitType type, int testID, + int threadcount) +{ + int i; + globalThreadData * pThis = (globalThreadData *)malloc(sizeof(globalThreadData)); + pThis->m_deviceID = deviceID; + pThis->m_context = context; + // pThis->m_queue = queue; + pThis->m_num_elements = num_elements; + pThis->m_num_runs_shift = num_runs_shift; + pThis->m_vectorSize = vectorSize; + pThis->m_style = style; + pThis->m_type = type; + pThis->m_offset = (uint64_t)0; + pThis->m_testID = testID; + pThis->m_arrPerThreadData = NULL; + pThis->m_threadcount = threadcount; + + pThis->m_pRandData = (MTdata *)malloc(threadcount*sizeof(MTdata)); + pThis->m_arrPerThreadData = (perThreadData **) + malloc(threadcount*sizeof(perThreadData *)); + for(i=0; i < threadcount; ++i) + { + pThis->m_pRandData[i] = init_genrand(i+1); + pThis->m_arrPerThreadData[i] = NULL; + } + + return pThis; +} + +void globalThreadDataDestroy(globalThreadData * pThis) +{ + int i; + + for(i=0; i < pThis->m_threadcount; ++i) + { + free_mtdata(pThis->m_pRandData[i]); + if(pThis->m_arrPerThreadData[i] != NULL) + { + perThreadDataDestroy(pThis->m_arrPerThreadData[i]); + } + } + free(pThis->m_arrPerThreadData); + free(pThis->m_pRandData); + free(pThis); +} + +int +test_integer_ops(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, int vectorSize, TestStyle style, int num_runs_shift, ExplicitType type, int testID, MTdata randIn, uint64_t startIndx, uint64_t endIndx, + perThreadData ** ppThreadData); + + +cl_int test_integer_ops_do_thread( cl_uint job_id, cl_uint thread_id, void *userInfo ) +{ + cl_int error; cl_int result; + globalThreadData * threadInfoGlobal = (globalThreadData *)userInfo; + cl_command_queue queue; + +#if THREAD_DEBUG + log_error("Thread %x (job %x) about to create command queue\n", + thread_id, job_id); +#endif + + queue = clCreateCommandQueue (threadInfoGlobal->m_context, + threadInfoGlobal->m_deviceID,0, + &error); + + if(error != CL_SUCCESS) + { + log_error("Thread %x (job %x) could not create command queue\n", + thread_id, job_id); + return error; // should we clean up the queue too? + } + +#if THREAD_DEBUG + log_error("Thread %x (job %x) created command queue\n", + thread_id, job_id); +#endif + + result = test_integer_ops( threadInfoGlobal->m_deviceID, + threadInfoGlobal->m_context, + queue, + threadInfoGlobal->m_num_elements, + threadInfoGlobal->m_vectorSize, threadInfoGlobal->m_style, + threadInfoGlobal->m_num_runs_shift, + threadInfoGlobal->m_type, threadInfoGlobal->m_testID, + threadInfoGlobal->m_pRandData[thread_id], + threadInfoGlobal->m_offset + threadInfoGlobal->m_num_elements*job_id, + threadInfoGlobal->m_offset + threadInfoGlobal->m_num_elements*(job_id+1), + &(threadInfoGlobal->m_arrPerThreadData[thread_id]) + ); + + if(result != 0) + { + log_error("Thread %x (job %x) failed test_integer_ops with result %x\n", + thread_id, job_id, result); + // return error; + } + + + error = clReleaseCommandQueue(queue); + if(error != CL_SUCCESS) + { + log_error("Thread %x (job %x) could not release command queue\n", + thread_id, job_id); + return error; + } + return result; +} + +int +test_integer_ops_threaded(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, int vectorSize, TestStyle style, int num_runs_shift, ExplicitType type, int testID) +{ + globalThreadData * pThreadInfo = NULL; + cl_int result=0; + cl_uint threadcount = GetThreadCount(); + + // Check to see if we are using single threaded mode on other than a 1.0 device + if (getenv( "CL_TEST_SINGLE_THREADED" )) { + + char device_version[1024] = { 0 }; + result = clGetDeviceInfo( deviceID, CL_DEVICE_VERSION, sizeof(device_version), device_version, NULL ); + if(result != CL_SUCCESS) + { + log_error("clGetDeviceInfo(CL_DEVICE_GLOBAL_MEM_SIZE) failed: %d\n", result); + return result; + } + + if (strcmp("OpenCL 1.0 ",device_version)) { + log_error("ERROR: CL_TEST_SINGLE_THREADED is set in the environment. Running single threaded.\n"); + } + } + + // This test will run threadcount threads concurrently; each thread will execute test_integer_ops() + // which will allocate 2 OpenCL buffers on the device; each buffer has size num_elements * type_size * vectorSize. + // We need to make sure that the total device memory allocated by all threads does not exceed the maximum + // memory on the device. If it does, we decrease num_elements until all threads combined will not + // over-subscribe device memory. + cl_ulong maxDeviceGlobalMem; + result = clGetDeviceInfo(deviceID, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(maxDeviceGlobalMem), &maxDeviceGlobalMem, NULL); + if(result != CL_SUCCESS) + { + log_error("clGetDeviceInfo(CL_DEVICE_GLOBAL_MEM_SIZE) failed: %d\n", result); + return result; + } + + if (maxDeviceGlobalMem > (cl_ulong)SIZE_MAX) { + maxDeviceGlobalMem = (cl_ulong)SIZE_MAX; + } + + // Let's not take all device memory - reduce by 75% + maxDeviceGlobalMem = (maxDeviceGlobalMem * 3) >> 2; + // Now reduce num_elements so that the total device memory usage does not exceed 75% of global device memory. + size_t type_size = get_explicit_type_size(type); + while ((cl_ulong)threadcount * 4 * num_elements * type_size * vectorSize > maxDeviceGlobalMem) + { + num_elements >>= 1; + } + + uint64_t startIndx = (uint64_t)0; + uint64_t endIndx = (1ULL<m_offset = startIndx; + +#if THREAD_DEBUG + log_error("Launching %llx jobs\n", + jobcount); +#endif + + result = ThreadPool_Do(test_integer_ops_do_thread, (cl_uint)jobcount, (void *)pThreadInfo); + + if(result != 0) + { + // cleanup ?? + log_error("ThreadPool_Do return non-success value %d\n", result); + + } + globalThreadDataDestroy(pThreadInfo); + return result; +} + + + +int +test_integer_ops(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements, + int vectorSize, TestStyle style, int num_runs_shift, + ExplicitType type, int testID, MTdata randDataIn, + uint64_t startIndx, uint64_t endIndx, + perThreadData ** ppThreadData) +{ + size_t threads[1]; + int err; + int i; + int inputAVecSize, inputBVecSize; + + + + inputAVecSize = inputBVecSize = vectorSize; + if( style == kInputAScalar ) + inputAVecSize = 1; + else if( style == kInputBScalar ) + inputBVecSize = 1; + + /* + if( inputAVecSize != inputBVecSize ) + log_info("Testing \"%s\" on %s%d (%s-%s inputs) (range %llx - %llx of 0-%llx)\n", + test_names[testID], + get_explicit_type_name(type), vectorSize, + ( inputAVecSize == 1 ) ? "scalar" : "vector", + ( inputBVecSize == 1 ) ? "scalar" : "vector", + startIndx, endIndx, (1ULL< NUM_TESTS) { + log_error("Invalid test ID: %d\n", testID); + return -1; + } + + if(*ppThreadData == NULL) + { + *ppThreadData = perThreadDataNew(); + err = perThreadDataInit(*ppThreadData, + type, num_elements, vectorSize, + inputAVecSize, inputBVecSize, + context, start_test_ID, + end_test_ID, testID); + test_error(err, "failed to init per thread data\n"); + } + + perThreadData * pThreadData = *ppThreadData; + + + + threads[0] = (size_t)num_elements; + int error_count = 0; + for (i=start_test_ID; i= endIndx) + { + startIndx = (uint64_t)0; + endIndx = (1ULL<m_input_ptr), randDataIn); + break; + case kUChar: + init_uchar_data(indx, num_elements * vectorSize, (cl_uchar**)(pThreadData->m_input_ptr), randDataIn); + break; + case kShort: + init_short_data(indx, num_elements * vectorSize, (cl_short**)(pThreadData->m_input_ptr), randDataIn); + break; + case kUShort: + init_ushort_data(indx, num_elements * vectorSize, (cl_ushort**)(pThreadData->m_input_ptr), randDataIn); + break; + case kInt: + init_int_data(indx, num_elements * vectorSize, (cl_int**)(pThreadData->m_input_ptr), randDataIn); + break; + case kUInt: + init_uint_data(indx, num_elements * vectorSize, (cl_uint**)(pThreadData->m_input_ptr), randDataIn); + break; + case kLong: + init_long_data(indx, num_elements * vectorSize, (cl_long**)(pThreadData->m_input_ptr), randDataIn); + break; + case kULong: + init_ulong_data(indx, num_elements * vectorSize, (cl_ulong**)(pThreadData->m_input_ptr), randDataIn); + break; + default: + err = 1; + log_error("Invalid type.\n"); + break; + } + + + err = clEnqueueWriteBuffer(queue, pThreadData->m_streams[0], CL_FALSE, 0, pThreadData->m_type_size*num_elements * inputAVecSize, (void *)pThreadData->m_input_ptr[0], 0, NULL, NULL); + test_error(err, "clEnqueueWriteBuffer failed"); + err = clEnqueueWriteBuffer( queue, pThreadData->m_streams[1], CL_FALSE, 0, pThreadData->m_type_size*num_elements * inputBVecSize, (void *)pThreadData->m_input_ptr[1], 0, NULL, NULL ); + test_error(err, "clEnqueueWriteBuffer failed"); + + err = clEnqueueNDRangeKernel( queue, pThreadData->m_kernel[i], 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error(err, "clEnqueueNDRangeKernel failed"); + + err = clEnqueueReadBuffer( queue, pThreadData->m_streams[2], CL_TRUE, 0, pThreadData->m_type_size*num_elements * vectorSize, (void *)pThreadData->m_output_ptr, 0, NULL, NULL ); + test_error(err, "clEnqueueReadBuffer failed"); + + // log_info("Performing verification\n"); + + // If one of the inputs are scalar, we need to extend the input values to vectors + // to accommodate the verify functions + if( vectorSize > 1 ) + { + char * p = NULL; + if( style == kInputAScalar ) + p = (char *)pThreadData->m_input_ptr[ 0 ]; + else if( style == kInputBScalar ) + p = (char *)pThreadData->m_input_ptr[ 1 ]; + if( p != NULL ) + { + for( int element = num_elements - 1; element >= 0; element-- ) + { + for( int vec = ( element == 0 ) ? 1 : 0; vec < vectorSize; vec++ ) + memcpy( p + ( element * vectorSize + vec ) * pThreadData->m_type_size, p + element * pThreadData->m_type_size, pThreadData->m_type_size ); + } + } + } + + switch (type) { + case kChar: + err = verify_char(i, vectorSize, (cl_char*)pThreadData->m_input_ptr[0], (cl_char*)pThreadData->m_input_ptr[1], (cl_char*)pThreadData->m_output_ptr, num_elements * vectorSize); + break; + case kUChar: + err = verify_uchar(i, vectorSize, (cl_uchar*)pThreadData->m_input_ptr[0], (cl_uchar*)pThreadData->m_input_ptr[1], (cl_uchar*)pThreadData->m_output_ptr, num_elements * vectorSize); + break; + case kShort: + err = verify_short(i, vectorSize, (cl_short*)pThreadData->m_input_ptr[0], (cl_short*)pThreadData->m_input_ptr[1], (cl_short*)pThreadData->m_output_ptr, num_elements * vectorSize); + break; + case kUShort: + err = verify_ushort(i, vectorSize, (cl_ushort*)pThreadData->m_input_ptr[0], (cl_ushort*)pThreadData->m_input_ptr[1], (cl_ushort*)pThreadData->m_output_ptr, num_elements * vectorSize); + break; + case kInt: + err = verify_int(i, vectorSize, (cl_int*)pThreadData->m_input_ptr[0], (cl_int*)pThreadData->m_input_ptr[1], (cl_int*)pThreadData->m_output_ptr, num_elements * vectorSize); + break; + case kUInt: + err = verify_uint(i, vectorSize, (cl_uint*)pThreadData->m_input_ptr[0], (cl_uint*)pThreadData->m_input_ptr[1], (cl_uint*)pThreadData->m_output_ptr, num_elements * vectorSize); + break; + case kLong: + err = verify_long(i, vectorSize, (cl_long*)pThreadData->m_input_ptr[0], (cl_long*)pThreadData->m_input_ptr[1], (cl_long*)pThreadData->m_output_ptr, num_elements * vectorSize); + break; + case kULong: + err = verify_ulong(i, vectorSize, (cl_ulong*)pThreadData->m_input_ptr[0], (cl_ulong*)pThreadData->m_input_ptr[1], (cl_ulong*)pThreadData->m_output_ptr, num_elements * vectorSize); + break; + default: + err = 1; + log_error("Invalid type.\n"); + break; + } + + if (err) { +#if 0 + log_error( "* inASize: %d inBSize: %d numElem: %d\n", inputAVecSize, inputBVecSize, num_elements ); + cl_char *inP = (cl_char *)pThreadData->m_input_ptr[0]; + log_error( "from 18:\n" ); + for( int q = 18; q < 64; q++ ) + { + log_error( "%02x ", inP[ q ] ); + } + log_error( "\n" ); + inP = (cl_char *)pThreadData->m_input_ptr[1]; + for( int q = 18; q < 64; q++ ) + { + log_error( "%02x ", inP[ q ] ); + } + log_error( "\n" ); + inP = (cl_char *)pThreadData->m_output_ptr; + for( int q = 18; q < 64; q++ ) + { + log_error( "%02x ", inP[ q ] ); + } + log_error( "\n" ); + log_error( "from 36:\n" ); + inP = (cl_char *)pThreadData->m_input_ptr[0]; + for( int q = 36; q < 64; q++ ) + { + log_error( "%02x ", inP[ q ] ); + } + log_error( "\n" ); + inP = (cl_char *)pThreadData->m_input_ptr[1]; + for( int q = 36; q < 64; q++ ) + { + log_error( "%02x ", inP[ q ] ); + } + log_error( "\n" ); + inP = (cl_char *)pThreadData->m_output_ptr; + for( int q = 36; q < 64; q++ ) + { + log_error( "%02x ", inP[ q ] ); + } + log_error( "\n" ); +#endif + error_count++; + break; + } + } + + /* + + const char * sizeNames[] = { "", "", "2", "3", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + + if (err) { + log_error("\t\t%s%s test %s failed (range %llx - %llx of 0-%llx)\n", + get_explicit_type_name(type), sizeNames[vectorSize], + test_names[i], + startIndx, endIndx, + (1ULL<> scalar case tested by tests 10 and 11 + // so they get skipped entirely + + int testsToRun[] = { 0, 1, 2, 3, 4, 5, 6, 7, + 13, 14, 15, 16, 17, 18, 19, 20, 21 }; + for (i=0; i< sizeof(testsToRun)/sizeof(testsToRun[0]); i++) + { + errors += run_test_sizes(deviceID, context, queue, 2048, type, num, testsToRun[i]); + } + return errors; +} + +int test_vector_scalar_ops(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + int errors = 0; + int numTypes = sizeof( types ) / sizeof( types[ 0 ] ); + + for( int t = 0; t < numTypes; t++ ) + { + if ((types[ t ] == kLong || types[ t ] == kULong) && !gHasLong) + continue; + + errors += run_vector_scalar_tests( deviceID, context, queue, num_elements, types[ t ], 1 ); + break; + } + + return errors; +} + +void generate_random_bool_data( size_t count, MTdata d, cl_char *outData, size_t outDataSize ) +{ + cl_uint bits = genrand_int32(d); + cl_uint bitsLeft = 32; + + memset( outData, 0, outDataSize * count ); + + for( size_t i = 0; i < count; i++ ) + { + if( 0 == bitsLeft) + { + bits = genrand_int32(d); + bitsLeft = 32; + } + + // Note: we will be setting just any bit non-zero for the type, so we can easily skip past + // and just write bytes (assuming the entire output buffer is already zeroed, which we did) + *outData = ( bits & 1 ) ? 0xff : 0; + + bits >>= 1; bitsLeft -= 1; + + outData += outDataSize; + } +} + +static const char *kernel_question_colon_full = +"__kernel void test(__global %s%s *srcA, __global %s%s *srcB, __global %s%s *srcC, __global %s%s *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" %s%s valA = %ssrcA%s" +" %s%s valB = %ssrcB%s" +" %s%s valC = %ssrcC%s" +" %s%s destVal = valC ? valA : valB;\n" +" %s" +"}\n"; + +static const char *kernel_qc_load_plain_prefix = ""; +static const char *kernel_qc_load_plain_suffix = "[ tid ];\n"; + +static const char *kernel_qc_load_vec3_prefix = "vload3( tid, "; +static const char *kernel_qc_load_vec3_suffix = ");\n"; + +static const char *kernel_qc_store_plain = "dst[ tid ] = destVal;\n"; +static const char *kernel_qc_store_vec3 = "vstore3( destVal, tid, dst );\n"; + +int test_question_colon_op(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements, + int vectorSize, TestStyle style, ExplicitType type ) +{ + cl_mem streams[4]; + cl_int *input_ptr[3], *output_ptr; + cl_program program; + cl_kernel kernel; + size_t threads[1]; + int err; + int inputAVecSize, inputBVecSize, inputCVecSize; + const char * sizeNames[] = { "", "", "2", "3", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + // Identical to sizeNames but with a blank for 3, since we use vload/store there + const char * paramSizeNames[] = { "", "", "2", "", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + MTdata s_randStates; + + inputAVecSize = inputBVecSize = inputCVecSize = vectorSize; + if( style & kInputCAlsoScalar ) + { + style = (TestStyle)( style & ~kInputCAlsoScalar ); + inputCVecSize = 1; + } + if( style == kInputAScalar ) + inputAVecSize = 1; + else if( style == kInputBScalar ) + inputBVecSize = 1; + else if( style == kVectorScalarScalar ) + inputAVecSize = inputBVecSize = 1; + + log_info("Testing \"?:\" on %s%d (%s?%s:%s inputs)\n", + get_explicit_type_name(type), vectorSize, ( inputCVecSize == 1 ) ? "scalar" : "vector", + ( inputAVecSize == 1 ) ? "scalar" : "vector", + ( inputBVecSize == 1 ) ? "scalar" : "vector" ); + + + const char *type_name = get_explicit_type_name(type); + size_t type_size = get_explicit_type_size(type); + + // Create and initialize I/O buffers + + input_ptr[0] = (cl_int*)malloc(type_size * num_elements * vectorSize); + input_ptr[1] = (cl_int*)malloc(type_size * num_elements * vectorSize); + input_ptr[2] = (cl_int*)malloc(type_size * num_elements * vectorSize); + output_ptr = (cl_int*)malloc(type_size * num_elements * vectorSize); + + s_randStates = init_genrand( gRandomSeed ); + + generate_random_data( type, num_elements * inputAVecSize, s_randStates, input_ptr[ 0 ] ); + generate_random_data( type, num_elements * inputBVecSize, s_randStates, input_ptr[ 1 ] ); + generate_random_bool_data( num_elements * inputCVecSize, s_randStates, (cl_char *)input_ptr[ 2 ], type_size ); + + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR), type_size * num_elements * inputAVecSize, input_ptr[0], &err); + test_error(err, "clCreateBuffer failed"); + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR), type_size * num_elements * inputBVecSize, input_ptr[1], &err ); + test_error(err, "clCreateBuffer failed"); + streams[2] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR), type_size * num_elements * inputCVecSize, input_ptr[2], &err ); + test_error(err, "clCreateBuffer failed"); + streams[3] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_WRITE_ONLY), type_size * num_elements * vectorSize, NULL, &err ); + test_error(err, "clCreateBuffer failed"); + + const char *vectorString = sizeNames[ vectorSize ]; + const char *inputAVectorString = sizeNames[ inputAVecSize ]; + const char *inputBVectorString = sizeNames[ inputBVecSize ]; + const char *inputCVectorString = sizeNames[ inputCVecSize ]; + + char programString[4096]; + const char *ptr; + + sprintf( programString, kernel_question_colon_full, type_name, paramSizeNames[ inputAVecSize ], + type_name, paramSizeNames[ inputBVecSize ], + type_name, paramSizeNames[ inputCVecSize ], + type_name, paramSizeNames[ vectorSize ], + // Loads + type_name, inputAVectorString, ( inputAVecSize == 3 ) ? kernel_qc_load_vec3_prefix : kernel_qc_load_plain_prefix, ( inputAVecSize == 3 ) ? kernel_qc_load_vec3_suffix : kernel_qc_load_plain_suffix, + type_name, inputBVectorString, ( inputBVecSize == 3 ) ? kernel_qc_load_vec3_prefix : kernel_qc_load_plain_prefix, ( inputBVecSize == 3 ) ? kernel_qc_load_vec3_suffix : kernel_qc_load_plain_suffix, + type_name, inputCVectorString, ( inputCVecSize == 3 ) ? kernel_qc_load_vec3_prefix : kernel_qc_load_plain_prefix, ( inputCVecSize == 3 ) ? kernel_qc_load_vec3_suffix : kernel_qc_load_plain_suffix, + // Dest type + type_name, vectorString, + // Store + ( vectorSize == 3 ) ? kernel_qc_store_vec3 : kernel_qc_store_plain ); + + ptr = programString; + err = create_single_kernel_helper( context, &program, &kernel, 1, &ptr, "test" ); + test_error( err, "Unable to create test kernel" ); + + err = clSetKernelArg( kernel, 0, sizeof streams[0], &streams[0] ); + err |= clSetKernelArg( kernel, 1, sizeof streams[1], &streams[1] ); + err |= clSetKernelArg( kernel, 2, sizeof streams[2], &streams[2] ); + err |= clSetKernelArg( kernel, 3, sizeof streams[3], &streams[3] ); + test_error(err, "clSetKernelArgs failed"); + + // Run + threads[0] = (size_t)num_elements; + + err = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL ); + test_error(err, "clEnqueueNDRangeKernel failed"); + + // Read and verify results + err = clEnqueueReadBuffer( queue, streams[3], CL_TRUE, 0, type_size*num_elements * vectorSize, (void *)output_ptr, 0, NULL, NULL ); + test_error(err, "clEnqueueReadBuffer failed"); + + // log_info("Performing verification\n"); + int error_count = 0; + + char *inputAPtr = (char *)input_ptr[ 0 ]; + char *inputBPtr = (char *)input_ptr[ 1 ]; + cl_char *inputCPtr = (cl_char *)input_ptr[ 2 ]; + char *actualPtr = (char *)output_ptr; + + for( int i = 0; i < num_elements; i++ ) + { + for( int j = 0; j < vectorSize; j++ ) + { + char *expectedPtr = ( *inputCPtr ) ? inputAPtr : inputBPtr; + if( memcmp( expectedPtr, actualPtr, type_size ) != 0 ) + { +#if 0 + char expectedStr[ 128 ], actualStr[ 128 ], inputAStr[ 128 ], inputBStr[ 128 ]; + print_type_to_string( type, inputAPtr, inputAStr ); + print_type_to_string( type, inputBPtr, inputBStr ); + print_type_to_string( type, expectedPtr, expectedStr ); + print_type_to_string( type, actualPtr, actualStr ); + log_error( "cl_%s verification failed at element %d:%d (expected %s, got %s, inputs: %s, %s, %s)\n", + type_name, i, j, expectedStr, actualStr, inputAStr, inputBStr, ( *inputCPtr ) ? "true" : "false" ); +#endif + error_count++; + } + // Advance for each element member. Note if any of the vec sizes are 1, they don't advance here + inputAPtr += ( inputAVecSize == 1 ) ? 0 : type_size; + inputBPtr += ( inputBVecSize == 1 ) ? 0 : type_size; + inputCPtr += ( inputCVecSize == 1 ) ? 0 : type_size; + actualPtr += ( vectorSize == 1 ) ? 0 : type_size; + } + // Reverse for the member advance. If the vec sizes are 1, we need to advance, but otherwise they're already correct + inputAPtr += ( inputAVecSize == 1 ) ? type_size : 0; + inputBPtr += ( inputBVecSize == 1 ) ? type_size : 0; + inputCPtr += ( inputCVecSize == 1 ) ? type_size : 0; + actualPtr += ( vectorSize == 1 ) ? type_size : 0; + } + + // cleanup + clReleaseMemObject(streams[0]); + clReleaseMemObject(streams[1]); + clReleaseMemObject(streams[2]); + clReleaseMemObject(streams[3]); + clReleaseKernel(kernel); + clReleaseProgram(program); + free(input_ptr[0]); + free(input_ptr[1]); + free(input_ptr[2]); + free(output_ptr); + free_mtdata( s_randStates ); + + return error_count; +} diff --git a/test_conformance/integer_ops/test_integers.cpp b/test_conformance/integer_ops/test_integers.cpp new file mode 100644 index 00000000..fa7133cf --- /dev/null +++ b/test_conformance/integer_ops/test_integers.cpp @@ -0,0 +1,1889 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/conversions.h" + +#define TEST_SIZE 512 + +#ifndef MIN + #define MIN( _a, _b ) ((_a) < (_b) ? (_a) : (_b)) +#endif +#ifndef MAX + #define MAX( _a, _b ) ((_a) > (_b) ? (_a) : (_b)) +#endif + +const char *singleParamIntegerKernelSourcePattern = +"__kernel void sample_test(__global %s *sourceA, __global %s *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" %s%s tmp = vload%s( tid, destValues );\n" +" tmp %s= %s( vload%s( tid, sourceA ) );\n" +" vstore%s( tmp, tid, destValues );\n" +"\n" +"}\n"; + +const char *singleParamSingleSizeIntegerKernelSourcePattern = +"__kernel void sample_test(__global %s *sourceA, __global %s *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] %s= %s( sourceA[tid] );\n" +"}\n"; + +typedef bool (*singleParamIntegerVerifyFn)( void *source, void *destination, ExplicitType vecType ); +static void patchup_divide_results( void *outData, const void *inDataA, const void *inDataB, size_t count, ExplicitType vecType ); +bool verify_integer_divideAssign( void *source, void *destination, ExplicitType vecType ); +bool verify_integer_moduloAssign( void *source, void *destination, ExplicitType vecType ); + +int test_single_param_integer_kernel(cl_command_queue queue, cl_context context, const char *fnName, + ExplicitType vecType, size_t vecSize, singleParamIntegerVerifyFn verifyFn, + MTdata d, bool useOpKernel = false ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + cl_long inDataA[TEST_SIZE * 16], outData[TEST_SIZE * 16], inDataB[TEST_SIZE * 16], expected; + int error, i; + size_t threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + char sizeName[4]; + + if (! gHasLong && strstr(get_explicit_type_name(vecType),"long")) + { + log_info( "WARNING: 64 bit integers are not supported on this device. Skipping %s\n", get_explicit_type_name(vecType) ); + return CL_SUCCESS; + } + + /* Create the source */ + if( vecSize == 1 ) + sizeName[ 0 ] = 0; + else + sprintf( sizeName, "%d", (int)vecSize ); + + if( vecSize == 1 ) + sprintf( kernelSource, singleParamSingleSizeIntegerKernelSourcePattern, + get_explicit_type_name( vecType ), get_explicit_type_name( vecType ), + useOpKernel ? fnName : "", useOpKernel ? "" : fnName ); + else + sprintf( kernelSource, singleParamIntegerKernelSourcePattern, + get_explicit_type_name( vecType ), get_explicit_type_name( vecType ), + get_explicit_type_name( vecType ), sizeName, sizeName, + useOpKernel ? fnName : "", useOpKernel ? "" : fnName, sizeName, + sizeName ); + + bool isOpenCL20Function = (strcmp(fnName,"ctz") == 0)? true: false; + + /* Create kernels */ + programPtr = kernelSource; + if( create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test", isOpenCL20Function ? "-cl-std=CL2.0": "" ) ) + { + log_error("The program we attempted to compile was: \n%s\n", kernelSource); + return -1; + } + + /* Generate some streams */ + generate_random_data( vecType, vecSize * TEST_SIZE, d, inDataA ); + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), + get_explicit_type_size( vecType ) * vecSize * TEST_SIZE, + inDataA, NULL); + if( streams[0] == NULL ) + { + log_error("ERROR: Creating input array A failed!\n"); + return -1; + } + + if( useOpKernel ) + { + // Op kernels use an r/w buffer for the second param, so we need to init it with data + generate_random_data( vecType, vecSize * TEST_SIZE, d, inDataB ); + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE | ( useOpKernel ? CL_MEM_COPY_HOST_PTR : 0 )), + get_explicit_type_size( vecType ) * vecSize * TEST_SIZE, + ( useOpKernel ) ? &inDataB : NULL, NULL ); + if( streams[1] == NULL ) + { + log_error("ERROR: Creating output array failed!\n"); + return -1; + } + + /* Assign streams and execute */ + error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + /* Run the kernel */ + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + memset(outData, 0xFF, get_explicit_type_size( vecType ) * TEST_SIZE * vecSize ); + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, + get_explicit_type_size( vecType ) * TEST_SIZE * vecSize, + outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + // deal with division by 0 -- any answer is allowed here + if( verifyFn == verify_integer_divideAssign || verifyFn == verify_integer_moduloAssign ) + patchup_divide_results( outData, inDataA, inDataB, TEST_SIZE * vecSize, vecType ); + + /* And verify! */ + char *p = (char *)outData; + char *in = (char *)inDataA; + char *in2 = (char *)inDataB; + for( i = 0; i < (int)TEST_SIZE; i++ ) + { + for( size_t j = 0; j < vecSize; j++ ) + { + if( useOpKernel ) + memcpy( &expected, in2, get_explicit_type_size( vecType ) ); + + verifyFn( in, &expected, vecType ); + if( memcmp( &expected, p, get_explicit_type_size( vecType ) ) != 0 ) + { + switch( get_explicit_type_size( vecType )) + { + case 1: + if( useOpKernel ) + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%2.2x), got (0x%2.2x), sources (0x%2.2x, 0x%2.2x)\n", + (int)i, (int)j, + ((cl_uchar*)&expected)[0], + *( (cl_uchar *)p ), + *( (cl_uchar *)in ), + *( (cl_uchar *)in2 ) ); + else + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%2.2x), got (0x%2.2x), sources (0x%2.2x)\n", + (int)i, (int)j, + ((cl_uchar*)&expected)[0], + *( (cl_uchar *)p ), + *( (cl_uchar *)in ) ); + break; + + case 2: + if( useOpKernel ) + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%4.4x), got (0x%4.4x), sources (0x%4.4x, 0x%4.4x)\n", + (int)i, (int)j, ((cl_ushort*)&expected)[0], *( (cl_ushort *)p ), + *( (cl_ushort *)in ), *( (cl_ushort *)in2 ) ); + else + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%4.4x), got (0x%4.4x), sources (0x%4.4x)\n", + (int)i, (int)j, ((cl_ushort*)&expected)[0], *( (cl_ushort *)p ), + *( (cl_ushort *)in ) ); + break; + + case 4: + if( useOpKernel ) + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%8.8x), got (0x%8.8x), sources (0x%8.8x, 0x%8.8x)\n", + (int)i, (int)j, ((cl_uint*)&expected)[0], *( (cl_uint *)p ), + *( (cl_uint *)in ), *( (cl_uint *)in2 ) ); + else + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%8.8x), got (0x%8.8x), sources (0x%8.8x)\n", + (int)i, (int)j, ((cl_uint*)&expected)[0], *( (cl_uint *)p ), + *( (cl_uint *)in ) ); + break; + + case 8: + if( useOpKernel ) + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%16.16llx), got (0x%16.16llx), sources (0x%16.16llx, 0x%16.16llx)\n", + (int)i, (int)j, ((cl_ulong*)&expected)[0], *( (cl_ulong *)p ), + *( (cl_ulong *)in ), *( (cl_ulong *)in2 ) ); + else + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%16.16llx), got (0x%16.16llx), sources (0x%16.16llx)\n", + (int)i, (int)j, ((cl_ulong*)&expected)[0], *( (cl_ulong *)p ), + *( (cl_ulong *)in ) ); + break; + } + return -1; + } + p += get_explicit_type_size( vecType ); + in += get_explicit_type_size( vecType ); + in2 += get_explicit_type_size( vecType ); + } + } + + return 0; +} + +int test_single_param_integer_fn( cl_command_queue queue, cl_context context, const char *fnName, singleParamIntegerVerifyFn verifyFn, bool useOpKernel = false ) +{ + ExplicitType types[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 }; // TODO 3 not tested + unsigned int index, typeIndex; + int retVal = 0; + RandomSeed seed(gRandomSeed ); + + for( typeIndex = 0; types[ typeIndex ] != kNumExplicitTypes; typeIndex++ ) + { + if ((types[ typeIndex ] == kLong || types[ typeIndex ] == kULong) && !gHasLong) + continue; + + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + if( test_single_param_integer_kernel(queue, context, fnName, types[ typeIndex ], vecSizes[ index ], verifyFn, seed, useOpKernel ) != 0 ) + { + log_error( " Vector %s%d FAILED\n", get_explicit_type_name( types[ typeIndex ] ), vecSizes[ index ] ); + retVal = -1; + } + } + } + + return retVal; +} + +bool verify_integer_clz( void *source, void *destination, ExplicitType vecType ) +{ + cl_long testValue; + int count; + int typeBits; + + switch( vecType ) + { + case kChar: + testValue = *( (cl_char *)source ); + typeBits = 8 * sizeof( cl_char ); + break; + case kUChar: + testValue = *( (cl_uchar *)source ); + typeBits = 8 * sizeof( cl_uchar ); + break; + case kShort: + testValue = *( (cl_short *)source ); + typeBits = 8 * sizeof( cl_short ); + break; + case kUShort: + testValue = *( (cl_ushort *)source ); + typeBits = 8 * sizeof( cl_ushort ); + break; + case kInt: + testValue = *( (cl_int *)source ); + typeBits = 8 * sizeof( cl_int ); + break; + case kUInt: + testValue = *( (cl_uint *)source ); + typeBits = 8 * sizeof( cl_uint ); + break; + case kLong: + testValue = *( (cl_long *)source ); + typeBits = 8 * sizeof( cl_long ); + break; + case kULong: + // Hack for now: just treat it as a signed cl_long, since it won't matter for bitcounting + testValue = *( (cl_ulong *)source ); + typeBits = 8 * sizeof( cl_ulong ); + break; + default: + // Should never happen + return false; + } + + count = typeBits; + if( testValue ) + { + testValue <<= 8 * sizeof( testValue ) - typeBits; + for( count = 0; 0 == (testValue & CL_LONG_MIN); count++ ) + testValue <<= 1; + } + + switch( vecType ) + { + case kChar: + *( (cl_char *)destination ) = count; + break; + case kUChar: + *( (cl_uchar *)destination ) = count; + break; + case kShort: + *( (cl_short *)destination ) = count; + break; + case kUShort: + *( (cl_ushort *)destination ) = count; + break; + case kInt: + *( (cl_int *)destination ) = count; + break; + case kUInt: + *( (cl_uint *)destination ) = count; + break; + case kLong: + *( (cl_long *)destination ) = count; + break; + case kULong: + *( (cl_ulong *)destination ) = count; + break; + default: + // Should never happen + return false; + } + return true; +} + +int test_integer_clz(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_single_param_integer_fn( queue, context, "clz", verify_integer_clz ); +} + + +bool verify_integer_ctz( void *source, void *destination, ExplicitType vecType ) +{ + cl_long testValue; + int count; + int typeBits; + + switch( vecType ) + { + case kChar: + testValue = *( (cl_char *)source ); + typeBits = 8 * sizeof( cl_char ); + break; + case kUChar: + testValue = *( (cl_uchar *)source ); + typeBits = 8 * sizeof( cl_uchar ); + break; + case kShort: + testValue = *( (cl_short *)source ); + typeBits = 8 * sizeof( cl_short ); + break; + case kUShort: + testValue = *( (cl_ushort *)source ); + typeBits = 8 * sizeof( cl_ushort ); + break; + case kInt: + testValue = *( (cl_int *)source ); + typeBits = 8 * sizeof( cl_int ); + break; + case kUInt: + testValue = *( (cl_uint *)source ); + typeBits = 8 * sizeof( cl_uint ); + break; + case kLong: + testValue = *( (cl_long *)source ); + typeBits = 8 * sizeof( cl_long ); + break; + case kULong: + // Hack for now: just treat it as a signed cl_long, since it won't matter for bitcounting + testValue = *( (cl_ulong *)source ); + typeBits = 8 * sizeof( cl_ulong ); + break; + default: + // Should never happen + return false; + } + + if ( testValue == 0 ) + count = typeBits; + else + { + for( count = 0; (0 == (testValue & 0x1)); count++ ) + testValue >>= 1; + } + + switch( vecType ) + { + case kChar: + *( (cl_char *)destination ) = count; + break; + case kUChar: + *( (cl_uchar *)destination ) = count; + break; + case kShort: + *( (cl_short *)destination ) = count; + break; + case kUShort: + *( (cl_ushort *)destination ) = count; + break; + case kInt: + *( (cl_int *)destination ) = count; + break; + case kUInt: + *( (cl_uint *)destination ) = count; + break; + case kLong: + *( (cl_long *)destination ) = count; + break; + case kULong: + *( (cl_ulong *)destination ) = count; + break; + default: + // Should never happen + return false; + } + return true; +} + + +int test_integer_ctz(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_single_param_integer_fn( queue, context, "ctz", verify_integer_ctz ); +} + +#define OP_CASE( op, sizeName, size ) \ + case sizeName: \ + { \ + cl_##size *d = (cl_##size *)destination; \ + *d op##= *( (cl_##size *)source ); \ + break; \ + } + +#define OP_CASES( op ) \ + switch( vecType ) \ + { \ + OP_CASE( op, kChar, char ) \ + OP_CASE( op, kUChar, uchar ) \ + OP_CASE( op, kShort, short ) \ + OP_CASE( op, kUShort, ushort ) \ + OP_CASE( op, kInt, int ) \ + OP_CASE( op, kUInt, uint ) \ + OP_CASE( op, kLong, long ) \ + OP_CASE( op, kULong, ulong ) \ + default: \ + break; \ + } + +#define OP_TEST( op, opName ) \ + bool verify_integer_##opName##Assign( void *source, void *destination, ExplicitType vecType ) \ + { \ + OP_CASES( op ) \ + return true; \ + } \ + int test_integer_##opName##Assign(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) \ + { \ + return test_single_param_integer_fn( queue, context, #op, verify_integer_##opName##Assign, true ); \ + } + +OP_TEST( +, add ) +OP_TEST( -, subtract ) +OP_TEST( *, multiply ) +OP_TEST( ^, exclusiveOr ) +OP_TEST( |, or ) +OP_TEST( &, and ) + +#define OP_CASE_GUARD( op, sizeName, size ) \ + case sizeName: \ + { \ + cl_##size *d = (cl_##size *)destination; \ + cl_##size *s = (cl_##size *)source; \ + if( *s == 0 ) \ + *d = -1; \ + else \ + *d op##= *s; \ + break; \ + } + +#define OP_CASE_GUARD_SIGNED( op, sizeName, size, MIN_VAL ) \ + case sizeName: \ + { \ + cl_##size *d = (cl_##size *)destination; \ + cl_##size *s = (cl_##size *)source; \ + if( *s == 0 || (*d == MIN_VAL && *s == -1)) \ + *d = -1 - MIN_VAL; \ + else \ + *d op##= *s; \ + break; \ + } + +#define OP_CASES_GUARD( op ) \ + switch( vecType ) \ + { \ + OP_CASE_GUARD_SIGNED( op, kChar, char, CL_CHAR_MIN ) \ + OP_CASE_GUARD( op, kUChar, uchar ) \ + OP_CASE_GUARD_SIGNED( op, kShort, short, CL_SHRT_MIN ) \ + OP_CASE_GUARD( op, kUShort, ushort ) \ + OP_CASE_GUARD_SIGNED( op, kInt, int, CL_INT_MIN ) \ + OP_CASE_GUARD( op, kUInt, uint ) \ + OP_CASE_GUARD_SIGNED( op, kLong, long, CL_LONG_MIN ) \ + OP_CASE_GUARD( op, kULong, ulong ) \ + default: \ + break; \ + } + +#define OP_TEST_GUARD( op, opName ) \ + bool verify_integer_##opName##Assign( void *source, void *destination, ExplicitType vecType ) \ + { \ + OP_CASES_GUARD( op ) \ + return true; \ + } \ + int test_integer_##opName##Assign(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) \ + { \ + return test_single_param_integer_fn( queue, context, #op, verify_integer_##opName##Assign, true ); \ + } + +OP_TEST_GUARD( /, divide ) +OP_TEST_GUARD( %, modulo ) + +#define PATCH_CASE( _out, _src, _dest, _count, _cl_type ) \ + { \ + const _cl_type *denom = (const _cl_type* ) _src; \ + _cl_type *result = (_cl_type* ) _out; \ + for( size_t i = 0; i < _count; i++ ) \ + if( denom[i] == 0 ) \ + result[i] = (_cl_type) -1; \ + } + +#define PATCH_CASE_SIGNED( _out, _src, _dest, _count, _cl_type, _MIN_VAL ) \ + { \ + const _cl_type *num = (const _cl_type* ) _dest; \ + const _cl_type *denom = (const _cl_type* ) _src; \ + _cl_type *result = (_cl_type* ) _out; \ + for( size_t i = 0; i < _count; i++ ) \ + if( denom[i] == 0 || ( num[i] == _MIN_VAL && denom[i] == -1)) \ + result[i] = -1 - _MIN_VAL; \ + } + +static void patchup_divide_results( void *outData, const void *inDataA, const void *inDataB, size_t count, ExplicitType vecType ) +{ + switch( vecType ) + { + case kChar: + PATCH_CASE_SIGNED( outData, inDataA, inDataB, count, cl_char, CL_CHAR_MIN ) + break; + case kUChar: + PATCH_CASE( outData, inDataA, inDataB, count, cl_uchar ) + break; + case kShort: + PATCH_CASE_SIGNED( outData, inDataA, inDataB, count, cl_short, CL_SHRT_MIN ) + break; + case kUShort: + PATCH_CASE( outData, inDataA, inDataB, count, cl_ushort ) + break; + case kInt: + PATCH_CASE_SIGNED( outData, inDataA, inDataB, count, cl_int, CL_INT_MIN ) + break; + case kUInt: + PATCH_CASE( outData, inDataA, inDataB, count, cl_uint ) + break; + case kLong: + PATCH_CASE_SIGNED( outData, inDataA, inDataB, count, cl_long, CL_LONG_MIN ) + break; + case kULong: + PATCH_CASE( outData, inDataA, inDataB, count, cl_ulong ) + break; + default: + log_error( "ERROR: internal test error -- unknown data type %d\n", vecType ); + break; + } +} + +const char *twoParamIntegerKernelSourcePattern = +"__kernel void sample_test(__global %s%s *sourceA, __global %s%s *sourceB, __global %s%s *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" %s%s sA = %s;\n" +" %s%s sB = %s;\n" +" %s%s dst = %s( sA, sB );\n" +" %s;\n" +"\n" +"}\n"; + +typedef bool (*twoParamIntegerVerifyFn)( void *sourceA, void *sourceB, void *destination, ExplicitType vecType ); + +static char * build_load_statement( char *outString, size_t vecSize, const char *name ) +{ + if( vecSize != 3 ) + sprintf( outString, "%s[ tid ]", name ); + else + sprintf( outString, "vload3( tid, %s )", name ); + return outString; +} + +static char * build_store_statement( char *outString, size_t vecSize, const char *name, const char *srcName ) +{ + if( vecSize != 3 ) + sprintf( outString, "%s[ tid ] = %s", name, srcName ); + else + sprintf( outString, "vstore3( %s, tid, %s )", srcName, name ); + return outString; +} + +int test_two_param_integer_kernel(cl_command_queue queue, cl_context context, const char *fnName, + ExplicitType vecAType, ExplicitType vecBType, unsigned int vecSize, twoParamIntegerVerifyFn verifyFn, MTdata d ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[3]; + cl_long inDataA[TEST_SIZE * 16], inDataB[TEST_SIZE * 16], outData[TEST_SIZE * 16], expected; + int error, i; + size_t threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + char sizeName[4], paramSizeName[4]; + + // embedded profiles don't support long/ulong datatypes + if (! gHasLong && strstr(get_explicit_type_name(vecAType),"long")) + { + log_info( "WARNING: 64 bit integers are not supported on this device. Skipping %s\n", get_explicit_type_name(vecAType) ); + return CL_SUCCESS; + } + + /* Create the source */ + if( vecSize == 1 ) + sizeName[ 0 ] = 0; + else + sprintf( sizeName, "%d", vecSize ); + if( ( vecSize == 1 ) || ( vecSize == 3 ) ) + paramSizeName[ 0 ] = 0; + else + sprintf( paramSizeName, "%d", vecSize ); + + char sourceALoad[ 128 ], sourceBLoad[ 128 ], destStore[ 128 ]; + + sprintf( kernelSource, twoParamIntegerKernelSourcePattern, + get_explicit_type_name( vecAType ), paramSizeName, + get_explicit_type_name( vecBType ), paramSizeName, + get_explicit_type_name( vecAType ), paramSizeName, + get_explicit_type_name( vecAType ), sizeName, build_load_statement( sourceALoad, (size_t)vecSize, "sourceA" ), + get_explicit_type_name( vecBType ), sizeName, build_load_statement( sourceBLoad, (size_t)vecSize, "sourceB" ), + get_explicit_type_name( vecAType ), sizeName, + fnName, + build_store_statement( destStore, (size_t)vecSize, "destValues", "dst" ) + ); + + /* Create kernels */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + { + log_error("The program we attempted to compile was: \n%s\n", kernelSource); + return -1; + } + + /* Generate some streams */ + generate_random_data( vecAType, vecSize * TEST_SIZE, d, inDataA ); + generate_random_data( vecBType, vecSize * TEST_SIZE, d, inDataB ); + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), + get_explicit_type_size( vecAType ) * vecSize * TEST_SIZE, + &inDataA, NULL); + if( streams[0] == NULL ) + { + log_error("ERROR: Creating input array A failed!\n"); + return -1; + } + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), + get_explicit_type_size( vecBType ) * vecSize * TEST_SIZE, + &inDataB, NULL); + if( streams[1] == NULL ) + { + log_error("ERROR: Creating input array B failed!\n"); + return -1; + } + streams[2] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), + get_explicit_type_size( vecAType ) * vecSize * TEST_SIZE, + NULL, NULL ); + if( streams[2] == NULL ) + { + log_error("ERROR: Creating output array failed!\n"); + return -1; + } + + /* Assign streams and execute */ + error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 2, sizeof( streams[2] ), &streams[2] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + /* Run the kernel */ + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + memset(outData, 0xFF, get_explicit_type_size( vecAType ) * TEST_SIZE * vecSize); + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[2], CL_TRUE, 0, + get_explicit_type_size( vecAType ) * TEST_SIZE * vecSize, outData, 0, + NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + /* And verify! */ + char *inA = (char *)inDataA; + char *inB = (char *)inDataB; + char *out = (char *)outData; + for( i = 0; i < (int)TEST_SIZE; i++ ) + { + for( size_t j = 0; j < vecSize; j++ ) + { + bool test = verifyFn( inA, inB, &expected, vecAType ); + if( test && ( memcmp( &expected, out, get_explicit_type_size( vecAType ) ) != 0 ) ) + { + switch( get_explicit_type_size( vecAType )) + { + case 1: + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%2.2x), got (0x%2.2x), sources (0x%2.2x, 0x%2.2x), TEST_SIZE %d\n", + (int)i, (int)j, ((cl_uchar*)&expected)[ 0 ], *( (cl_uchar *)out ), + *( (cl_uchar *)inA ), + *( (cl_uchar *)inB ) , + TEST_SIZE); + break; + + case 2: + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%4.4x), got (0x%4.4x), sources (0x%4.4x, 0x%4.4x), TEST_SIZE %d\n", + (int)i, (int)j, ((cl_ushort*)&expected)[ 0 ], *( (cl_ushort *)out ), + *( (cl_ushort *)inA ), + *( (cl_ushort *)inB ), + TEST_SIZE); + break; + + case 4: + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%8.8x), got (0x%8.8x), sources (0x%8.8x, 0x%8.8x)\n", + (int)i, (int)j, ((cl_uint*)&expected)[ 0 ], *( (cl_uint *)out ), + *( (cl_uint *)inA ), + *( (cl_uint *)inB ) ); + break; + + case 8: + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%16.16llx), got (0x%16.16llx), sources (0x%16.16llx, 0x%16.16llx)\n", + (int)i, (int)j, ((cl_ulong*)&expected)[ 0 ], *( (cl_ulong *)out ), + *( (cl_ulong *)inA ), + *( (cl_ulong *)inB ) ); + break; + } + return -1; + } + inA += get_explicit_type_size( vecAType ); + inB += get_explicit_type_size( vecBType ); + out += get_explicit_type_size( vecAType ); + } + } + + return 0; +} + +int test_two_param_integer_fn(cl_command_queue queue, cl_context context, const char *fnName, twoParamIntegerVerifyFn verifyFn) +{ + ExplicitType types[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 }; // TODO : 3 not tested + unsigned int index, typeIndex; + int retVal = 0; + RandomSeed seed(gRandomSeed ); + + for( typeIndex = 0; types[ typeIndex ] != kNumExplicitTypes; typeIndex++ ) + { + if (( types[ typeIndex ] == kLong || types[ typeIndex ] == kULong) && !gHasLong) + continue; + + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + if( test_two_param_integer_kernel(queue, context, fnName, types[ typeIndex ], types[ typeIndex ], vecSizes[ index ], verifyFn, seed ) != 0 ) + { + log_error( " Vector %s%d FAILED\n", get_explicit_type_name( types[ typeIndex ] ), vecSizes[ index ] ); + retVal = -1; + } + } + } + + return retVal; +} + +int test_two_param_unmatched_integer_fn(cl_command_queue queue, cl_context context, const char *fnName, twoParamIntegerVerifyFn verifyFn) +{ + ExplicitType types[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 4, 8, 16, 0 }; + unsigned int index, typeAIndex, typeBIndex; + int retVal = 0; + RandomSeed seed( gRandomSeed ); + + for( typeAIndex = 0; types[ typeAIndex ] != kNumExplicitTypes; typeAIndex++ ) + { + if (( types[ typeAIndex ] == kLong || types[ typeAIndex ] == kULong) && !gHasLong) + continue; + + for( typeBIndex = 0; types[ typeBIndex ] != kNumExplicitTypes; typeBIndex++ ) + { + if (( types[ typeBIndex ] == kLong || types[ typeBIndex ] == kULong) && !gHasLong) + continue; + + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + if( test_two_param_integer_kernel( queue, context, fnName, types[ typeAIndex ], types[ typeBIndex ], vecSizes[ index ], verifyFn, seed ) != 0 ) + { + log_error( " Vector %s%d / %s%d FAILED\n", get_explicit_type_name( types[ typeAIndex ] ), vecSizes[ index ], get_explicit_type_name( types[ typeBIndex ] ), vecSizes[ index ] ); + retVal = -1; + } + } + } + } + + return retVal; +} + +bool verify_integer_hadd( void *sourceA, void *sourceB, void *destination, ExplicitType vecType ) +{ + cl_long testValueA, testValueB, overflow; + cl_ulong uValueA, uValueB, uOverflow; + + switch( vecType ) + { + case kChar: + testValueA = *( (cl_char *)sourceA ); + testValueB = *( (cl_char *)sourceB ); + *( (cl_char *)destination ) = (cl_char)( ( testValueA + testValueB ) >> 1 ); + break; + case kUChar: + testValueA = *( (cl_uchar *)sourceA ); + testValueB = *( (cl_uchar *)sourceB ); + *( (cl_uchar *)destination ) = (cl_uchar)( ( testValueA + testValueB ) >> 1 ); + break; + case kShort: + testValueA = *( (cl_short *)sourceA ); + testValueB = *( (cl_short *)sourceB ); + *( (cl_short *)destination ) = (cl_short)( ( testValueA + testValueB ) >> 1 ); + break; + case kUShort: + testValueA = *( (cl_ushort *)sourceA ); + testValueB = *( (cl_ushort *)sourceB ); + *( (cl_ushort *)destination ) = (cl_ushort)( ( testValueA + testValueB ) >> 1 ); + break; + case kInt: + testValueA = *( (cl_int *)sourceA ); + testValueB = *( (cl_int *)sourceB ); + *( (cl_int *)destination ) = (cl_int)( ( testValueA + testValueB ) >> 1 ); + break; + case kUInt: + testValueA = *( (cl_uint *)sourceA ); + testValueB = *( (cl_uint *)sourceB ); + *( (cl_uint *)destination ) = (cl_uint)( ( testValueA + testValueB ) >> 1 ); + break; + case kLong: + // The long way to avoid dropping bits + testValueA = *( (cl_long *)sourceA ); + testValueB = *( (cl_long *)sourceB ); + overflow = ( testValueA & 0x1 ) + ( testValueB & 0x1 ); + *( (cl_long *)destination ) = ( ( testValueA >> 1 ) + ( testValueB >> 1 ) ) + ( overflow >> 1 ); + break; + case kULong: + // The long way to avoid dropping bits + uValueA = *( (cl_ulong *)sourceA ); + uValueB = *( (cl_ulong *)sourceB ); + uOverflow = ( uValueA & 0x1 ) + ( uValueB & 0x1 ); + *( (cl_ulong *)destination ) = ( ( uValueA >> 1 ) + ( uValueB >> 1 ) ) + ( uOverflow >> 1 ); + break; + default: + // Should never happen + return false; + } + return true; +} + +int test_integer_hadd(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_two_param_integer_fn( queue, context, "hadd", verify_integer_hadd ); +} + +bool verify_integer_rhadd( void *sourceA, void *sourceB, void *destination, ExplicitType vecType ) +{ + cl_long testValueA, testValueB, overflow; + cl_ulong uValueA, uValueB, uOverflow; + + switch( vecType ) + { + case kChar: + testValueA = *( (cl_char *)sourceA ); + testValueB = *( (cl_char *)sourceB ); + *( (cl_char *)destination ) = (cl_char)( ( testValueA + testValueB + 1 ) >> 1 ); + break; + case kUChar: + testValueA = *( (cl_uchar *)sourceA ); + testValueB = *( (cl_uchar *)sourceB ); + *( (cl_uchar *)destination ) = (cl_uchar)( ( testValueA + testValueB + 1 ) >> 1 ); + break; + case kShort: + testValueA = *( (cl_short *)sourceA ); + testValueB = *( (cl_short *)sourceB ); + *( (cl_short *)destination ) = (cl_short)( ( testValueA + testValueB + 1 ) >> 1 ); + break; + case kUShort: + testValueA = *( (cl_ushort *)sourceA ); + testValueB = *( (cl_ushort *)sourceB ); + *( (cl_ushort *)destination ) = (cl_ushort)( ( testValueA + testValueB + 1 ) >> 1 ); + break; + case kInt: + testValueA = *( (cl_int *)sourceA ); + testValueB = *( (cl_int *)sourceB ); + *( (cl_int *)destination ) = (cl_int)( ( testValueA + testValueB + 1 ) >> 1 ); + break; + case kUInt: + testValueA = *( (cl_uint *)sourceA ); + testValueB = *( (cl_uint *)sourceB ); + *( (cl_uint *)destination ) = (cl_uint)( ( testValueA + testValueB + 1 ) >> 1 ); + break; + case kLong: + // The long way to avoid dropping bits + testValueA = *( (cl_long *)sourceA ); + testValueB = *( (cl_long *)sourceB ); + overflow = ( testValueA | testValueB ) & 0x1; + *( (cl_long *)destination ) = ( ( testValueA >> 1 ) + ( testValueB >> 1 ) ) + overflow; + break; + case kULong: + // The long way to avoid dropping bits + uValueA = *( (cl_ulong *)sourceA ); + uValueB = *( (cl_ulong *)sourceB ); + uOverflow = ( uValueA | uValueB ) & 0x1; + *( (cl_ulong *)destination ) = ( ( uValueA >> 1 ) + ( uValueB >> 1 ) ) + uOverflow; + break; + default: + // Should never happen + return false; + } + return true; +} + +int test_integer_rhadd(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_two_param_integer_fn( queue, context, "rhadd", verify_integer_rhadd ); +} + +#define MIN_CASE( type, const ) \ + case const : \ + { \ + cl_##type valueA = *( (cl_##type *)sourceA ); \ + cl_##type valueB = *( (cl_##type *)sourceB ); \ + *( (cl_##type *)destination ) = (cl_##type)( valueB < valueA ? valueB : valueA ); \ + break; \ + } + +bool verify_integer_min( void *sourceA, void *sourceB, void *destination, ExplicitType vecType ) +{ + switch( vecType ) + { + MIN_CASE( char, kChar ) + MIN_CASE( uchar, kUChar ) + MIN_CASE( short, kShort ) + MIN_CASE( ushort, kUShort ) + MIN_CASE( int, kInt ) + MIN_CASE( uint, kUInt ) + MIN_CASE( long, kLong ) + MIN_CASE( ulong, kULong ) + default: + // Should never happen + return false; + } + return true; +} + +int test_integer_min(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_two_param_integer_fn( queue, context, "min", verify_integer_min); +} + +#define MAX_CASE( type, const ) \ + case const : \ + { \ + cl_##type valueA = *( (cl_##type *)sourceA ); \ + cl_##type valueB = *( (cl_##type *)sourceB ); \ + *( (cl_##type *)destination ) = (cl_##type)( valueA < valueB ? valueB : valueA ); \ + break; \ + } + +bool verify_integer_max( void *sourceA, void *sourceB, void *destination, ExplicitType vecType ) +{ + switch( vecType ) + { + MAX_CASE( char, kChar ) + MAX_CASE( uchar, kUChar ) + MAX_CASE( short, kShort ) + MAX_CASE( ushort, kUShort ) + MAX_CASE( int, kInt ) + MAX_CASE( uint, kUInt ) + MAX_CASE( long, kLong ) + MAX_CASE( ulong, kULong ) + default: + // Should never happen + return false; + } + return true; +} + +int test_integer_max(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_two_param_integer_fn( queue, context, "max", verify_integer_max ); +} + + +void multiply_unsigned_64_by_64( cl_ulong sourceA, cl_ulong sourceB, cl_ulong &destLow, cl_ulong &destHi ) +{ + cl_ulong lowA, lowB; + cl_ulong highA, highB; + + // Split up the values + lowA = sourceA & 0xffffffff; + highA = sourceA >> 32; + lowB = sourceB & 0xffffffff; + highB = sourceB >> 32; + + // Note that, with this split, our multiplication becomes: + // ( a * b ) + // = ( ( aHI << 32 + aLO ) * ( bHI << 32 + bLO ) ) >> 64 + // = ( ( aHI << 32 * bHI << 32 ) + ( aHI << 32 * bLO ) + ( aLO * bHI << 32 ) + ( aLO * bLO ) ) >> 64 + // = ( ( aHI * bHI << 64 ) + ( aHI * bLO << 32 ) + ( aLO * bHI << 32 ) + ( aLO * bLO ) ) >> 64 + // = ( aHI * bHI ) + ( aHI * bLO >> 32 ) + ( aLO * bHI >> 32 ) + ( aLO * bLO >> 64 ) + + // Now, since each value is 32 bits, the max size of any multiplication is: + // ( 2 ^ 32 - 1 ) * ( 2 ^ 32 - 1 ) = 2^64 - 4^32 + 1 = 2^64 - 2^33 + 1, which fits within 64 bits + // Which means we can do each component within a 64-bit integer as necessary (each component above marked as AB1 - AB4) + cl_ulong aHibHi = highA * highB; + cl_ulong aHibLo = highA * lowB; + cl_ulong aLobHi = lowA * highB; + cl_ulong aLobLo = lowA * lowB; + + // Assemble terms. + // We note that in certain cases, sums of products cannot overflow: + // + // The maximum product of two N-bit unsigned numbers is + // + // (2**N-1)^2 = 2**2N - 2**(N+1) + 1 + // + // We note that we can add the maximum N-bit number to the 2N-bit product twice without overflow: + // + // (2**N-1)^2 + 2*(2**N-1) = 2**2N - 2**(N+1) + 1 + 2**(N+1) - 2 = 2**2N - 1 + // + // If we breakdown the product of two numbers a,b into high and low halves of partial products as follows: + // + // a.hi a.lo + // x b.hi b.lo + //=============================================================================== + // (b.hi*a.hi).hi (b.hi*a.hi).lo + // (b.lo*a.hi).hi (b.lo*a.hi).lo + // (b.hi*a.lo).hi (b.hi*a.lo).lo + // + (b.lo*a.lo).hi (b.lo*a.lo).lo + //=============================================================================== + // + // The (b.lo*a.lo).lo term cannot cause a carry, so we can ignore them for now. We also know from above, that we can add (b.lo*a.lo).hi + // and (b.hi*a.lo).lo to the 2N bit term [(b.lo*a.hi).hi + (b.lo*a.hi).lo] without overflow. That takes care of all of the terms + // on the right half that might carry. Do that now. + // + cl_ulong aLobLoHi = aLobLo >> 32; + cl_ulong aLobHiLo = aLobHi & 0xFFFFFFFFULL; + aHibLo += aLobLoHi + aLobHiLo; + + // That leaves us with these terms: + // + // a.hi a.lo + // x b.hi b.lo + //=============================================================================== + // (b.hi*a.hi).hi (b.hi*a.hi).lo + // (b.hi*a.lo).hi + // [ (b.lo*a.hi).hi + (b.lo*a.hi).lo + other ] + // + (b.lo*a.lo).lo + //=============================================================================== + + // All of the overflow potential from the right half has now been accumulated into the [ (b.lo*a.hi).hi + (b.lo*a.hi).lo ] 2N bit term. + // We can safely separate into high and low parts. Per our rule above, we know we can accumulate the high part of that and (b.hi*a.lo).hi + // into the 2N bit term (b.lo*a.hi) without carry. The low part can be pieced together with (b.lo*a.lo).lo, to give the final low result + + destHi = aHibHi + (aHibLo >> 32 ) + (aLobHi >> 32); // Cant overflow + destLow = (aHibLo << 32) | ( aLobLo & 0xFFFFFFFFULL ); +} + +void multiply_signed_64_by_64( cl_long sourceA, cl_long sourceB, cl_ulong &destLow, cl_long &destHi ) +{ + // Find sign of result + cl_long aSign = sourceA >> 63; + cl_long bSign = sourceB >> 63; + cl_long resultSign = aSign ^ bSign; + + // take absolute values of the argument + sourceA = (sourceA ^ aSign) - aSign; + sourceB = (sourceB ^ bSign) - bSign; + + cl_ulong hi; + multiply_unsigned_64_by_64( (cl_ulong) sourceA, (cl_ulong) sourceB, destLow, hi ); + + // Fix the sign + if( resultSign ) + { + destLow ^= resultSign; + hi ^= resultSign; + destLow -= resultSign; + + //carry if necessary + if( 0 == destLow ) + hi -= resultSign; + } + + destHi = (cl_long) hi; +} + +bool verify_integer_mul_hi( void *sourceA, void *sourceB, void *destination, ExplicitType vecType ) +{ + cl_long testValueA, testValueB, highSigned; + cl_ulong highUnsigned, lowHalf; + + switch( vecType ) + { + case kChar: + testValueA = *( (cl_char *)sourceA ); + testValueB = *( (cl_char *)sourceB ); + *( (cl_char *)destination ) = (cl_char)( ( testValueA * testValueB ) >> 8 ); + break; + case kUChar: + testValueA = *( (cl_uchar *)sourceA ); + testValueB = *( (cl_uchar *)sourceB ); + *( (cl_uchar *)destination ) = (cl_uchar)( ( testValueA * testValueB ) >> 8 ); + break; + case kShort: + testValueA = *( (cl_short *)sourceA ); + testValueB = *( (cl_short *)sourceB ); + *( (cl_short *)destination ) = (cl_short)( ( testValueA * testValueB ) >> 16 ); + break; + case kUShort: + testValueA = *( (cl_ushort *)sourceA ); + testValueB = *( (cl_ushort *)sourceB ); + *( (cl_ushort *)destination ) = (cl_ushort)( ( testValueA * testValueB ) >> 16 ); + break; + case kInt: + testValueA = *( (cl_int *)sourceA ); + testValueB = *( (cl_int *)sourceB ); + *( (cl_int *)destination ) = (cl_int)( ( testValueA * testValueB ) >> 32 ); + break; + case kUInt: + testValueA = *( (cl_uint *)sourceA ); + testValueB = *( (cl_uint *)sourceB ); + *( (cl_uint *)destination ) = (cl_uint)( ( testValueA * testValueB ) >> 32 ); + break; + case kLong: + testValueA = *( (cl_long *)sourceA ); + testValueB = *( (cl_long *)sourceB ); + + multiply_signed_64_by_64( testValueA, testValueB, lowHalf, highSigned ); + *( (cl_long *)destination ) = highSigned; + break; + case kULong: + testValueA = *( (cl_ulong *)sourceA ); + testValueB = *( (cl_ulong *)sourceB ); + + multiply_unsigned_64_by_64( testValueA, testValueB, lowHalf, highUnsigned ); + *( (cl_ulong *)destination ) = highUnsigned; + break; + default: + // Should never happen + return false; + } + return true; +} + +int test_integer_mul_hi(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_two_param_integer_fn( queue, context, "mul_hi", verify_integer_mul_hi ); +} + +bool verify_integer_rotate( void *sourceA, void *sourceB, void *destination, ExplicitType vecType ) +{ + cl_ulong testValueA; + char numBits; + + switch( vecType ) + { + case kChar: + case kUChar: + testValueA = *( (cl_uchar *)sourceA ); + numBits = *( (cl_uchar *)sourceB ); + numBits &= 7; + if ( numBits == 0 ) + *( (cl_uchar *)destination ) = (cl_uchar)testValueA; + else + *( (cl_uchar *)destination ) = (cl_uchar)( ( testValueA << numBits ) | ( testValueA >> ( 8 - numBits ) ) ); + break; + case kShort: + case kUShort: + testValueA = *( (cl_ushort *)sourceA ); + numBits = *( (cl_ushort *)sourceB ); + numBits &= 15; + if ( numBits == 0 ) + *( (cl_ushort *)destination ) = (cl_ushort)testValueA; + else + *( (cl_ushort *)destination ) = (cl_ushort)( ( testValueA << numBits ) | ( testValueA >> ( 16 - numBits ) ) ); + break; + case kInt: + case kUInt: + testValueA = *( (cl_uint *)sourceA ); + numBits = *( (cl_uint *)sourceB ); + numBits &= 31; + if ( numBits == 0 ) + *( (cl_uint *)destination ) = (cl_uint) testValueA; + else + *( (cl_uint *)destination ) = (cl_uint)( ( testValueA << numBits ) | ( testValueA >> ( 32 - numBits ) ) ); + break; + case kLong: + case kULong: + testValueA = *( (cl_ulong *)sourceA ); + numBits = *( (cl_ulong *)sourceB ); + numBits &= 63; + if ( numBits == 0 ) + *( (cl_ulong *)destination ) = (cl_ulong)testValueA; + else + *( (cl_ulong *)destination ) = (cl_ulong)( ( testValueA << numBits ) | ( testValueA >> ( 64 - numBits ) ) ); + break; + default: + // Should never happen + log_error( "Unknown type encountered in verify_integer_rotate. Test failed. Aborting...\n" ); + abort(); + return false; + } + return true; +} + +int test_integer_rotate(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_two_param_integer_fn( queue, context, "rotate", verify_integer_rotate ); +} + +const char *threeParamIntegerKernelSourcePattern = +"__kernel void sample_test(__global %s%s *sourceA, __global %s%s *sourceB, __global %s%s *sourceC, __global %s%s *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" %s%s sA = %s;\n" +" %s%s sB = %s;\n" +" %s%s sC = %s;\n" +" %s%s dst = %s( sA, sB, sC );\n" +" %s;\n" +"\n" +"}\n"; + +typedef bool (*threeParamIntegerVerifyFn)( void *sourceA, void *sourceB, void *sourceC, void *destination, + ExplicitType vecAType, ExplicitType vecBType, ExplicitType vecCType, ExplicitType destType ); + +int test_three_param_integer_kernel(cl_command_queue queue, cl_context context, const char *fnName, + ExplicitType vecAType, ExplicitType vecBType, ExplicitType vecCType, ExplicitType destType, + unsigned int vecSize, threeParamIntegerVerifyFn verifyFn, MTdata d ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[4]; + cl_long inDataA[TEST_SIZE * 16], inDataB[TEST_SIZE * 16], inDataC[TEST_SIZE * 16], outData[TEST_SIZE * 16], expected; + int error, i; + size_t threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + char sizeName[4], paramSizeName[4]; + + if (! gHasLong && strstr(get_explicit_type_name(vecAType),"long")) + { + log_info( "WARNING: 64 bit integers are not supported on this device. Skipping %s\n", get_explicit_type_name(vecAType) ); + return CL_SUCCESS; + } + + + /* Create the source */ + if( vecSize == 1 ) + sizeName[ 0 ] = 0; + else + sprintf( sizeName, "%d", vecSize ); + if( ( vecSize == 1 ) || ( vecSize == 3 ) ) + paramSizeName[ 0 ] = 0; + else + sprintf( paramSizeName, "%d", vecSize ); + + char sourceALoad[ 128 ], sourceBLoad[ 128 ], sourceCLoad[ 128 ], destStore[ 128 ]; + + sprintf( kernelSource, threeParamIntegerKernelSourcePattern, + get_explicit_type_name( vecAType ), paramSizeName, + get_explicit_type_name( vecBType ), paramSizeName, + get_explicit_type_name( vecCType ), paramSizeName, + get_explicit_type_name( destType ), paramSizeName, + get_explicit_type_name( vecAType ), sizeName, build_load_statement( sourceALoad, (size_t)vecSize, "sourceA" ), + get_explicit_type_name( vecBType ), sizeName, build_load_statement( sourceBLoad, (size_t)vecSize, "sourceB" ), + get_explicit_type_name( vecCType ), sizeName, build_load_statement( sourceCLoad, (size_t)vecSize, "sourceC" ), + get_explicit_type_name( destType ), sizeName, + fnName, + build_store_statement( destStore, (size_t)vecSize, "destValues", "dst" ) + ); + + /* Create kernels */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + { + log_error("The program we attempted to compile was: \n%s\n", kernelSource); + return -1; + } + + /* Generate some streams */ + generate_random_data( vecAType, vecSize * TEST_SIZE, d, inDataA ); + generate_random_data( vecBType, vecSize * TEST_SIZE, d, inDataB ); + generate_random_data( vecCType, vecSize * TEST_SIZE, d, inDataC ); + + streams[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), get_explicit_type_size( vecAType ) * vecSize * TEST_SIZE, &inDataA, NULL); + if( streams[0] == NULL ) + { + log_error("ERROR: Creating input array A failed!\n"); + return -1; + } + streams[1] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), get_explicit_type_size( vecBType ) * vecSize * TEST_SIZE, &inDataB, NULL); + if( streams[1] == NULL ) + { + log_error("ERROR: Creating input array B failed!\n"); + return -1; + } + streams[2] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), get_explicit_type_size( vecCType ) * vecSize * TEST_SIZE, &inDataC, NULL); + if( streams[2] == NULL ) + { + log_error("ERROR: Creating input array C failed!\n"); + return -1; + } + streams[3] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), get_explicit_type_size( destType ) * vecSize * TEST_SIZE, NULL, NULL ); + if( streams[3] == NULL ) + { + log_error("ERROR: Creating output array failed!\n"); + return -1; + } + + /* Assign streams and execute */ + error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 2, sizeof( streams[2] ), &streams[2] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 3, sizeof( streams[3] ), &streams[3] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + /* Run the kernel */ + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + memset(outData, 0xFF, get_explicit_type_size( destType ) * TEST_SIZE * vecSize); + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[3], CL_TRUE, 0, get_explicit_type_size( destType ) * TEST_SIZE * vecSize, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + /* And verify! */ + char *inA = (char *)inDataA; + char *inB = (char *)inDataB; + char *inC = (char *)inDataC; + char *out = (char *)outData; + for( i = 0; i < (int)TEST_SIZE; i++ ) + { + for( size_t j = 0; j < vecSize; j++ ) + { + bool test = verifyFn( inA, inB, inC, &expected, vecAType, vecBType, vecCType, destType ); + if( test && ( memcmp( &expected, out, get_explicit_type_size( destType ) ) != 0 ) ) + { + switch( get_explicit_type_size( vecAType )) + { + case 1: + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%2.2x), got (0x%2.2x), sources (0x%2.2x, 0x%2.2x, 0x%2.2x)\n", + (int)i, (int)j, ((cl_uchar*)&expected)[ 0 ], *( (cl_uchar *)out ), + *( (cl_uchar *)inA ), + *( (cl_uchar *)inB ), + *( (cl_uchar *)inC ) ); + break; + + case 2: + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%4.4x), got (0x%4.4x), sources (0x%4.4x, 0x%4.4x, 0x%4.4x)\n", + (int)i, (int)j, ((cl_ushort*)&expected)[ 0 ], *( (cl_ushort *)out ), + *( (cl_ushort *)inA ), + *( (cl_ushort *)inB ), + *( (cl_ushort *)inC ) ); + break; + + case 4: + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%8.8x), got (0x%8.8x), sources (0x%8.8x, 0x%8.8x, 0x%8.8x)\n", + (int)i, (int)j, ((cl_uint*)&expected)[ 0 ], *( (cl_uint *)out ), + *( (cl_uint *)inA ), + *( (cl_uint *)inB ), + *( (cl_uint *)inC ) ); + break; + + case 8: + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%16.16llx), got (0x%16.16llx), sources (0x%16.16llx, 0x%16.16llx, 0x%16.16llx)\n", + (int)i, (int)j, ((cl_ulong*)&expected)[ 0 ], *( (cl_ulong *)out ), + *( (cl_ulong *)inA ), + *( (cl_ulong *)inB ), + *( (cl_ulong *)inC ) ); + break; + } + return -1; + } + inA += get_explicit_type_size( vecAType ); + inB += get_explicit_type_size( vecBType ); + inC += get_explicit_type_size( vecCType ); + out += get_explicit_type_size( destType ); + } + } + + return 0; +} + +int test_three_param_integer_fn(cl_command_queue queue, cl_context context, const char *fnName, threeParamIntegerVerifyFn verifyFn) +{ + ExplicitType types[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 }; + unsigned int index, typeAIndex; + int retVal = 0; + RandomSeed seed(gRandomSeed); + + for( typeAIndex = 0; types[ typeAIndex ] != kNumExplicitTypes; typeAIndex++ ) + { + if ((types[ typeAIndex ] == kLong || types[ typeAIndex] == kULong) && !gHasLong) + continue; + + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + if( test_three_param_integer_kernel(queue, context, fnName, types[ typeAIndex ], types[ typeAIndex ], types[ typeAIndex ], types[ typeAIndex ], vecSizes[ index ], verifyFn, seed ) != 0 ) + { + log_error( " Vector %s%d,%s%d,%s%d FAILED\n", get_explicit_type_name( types[ typeAIndex ] ), vecSizes[ index ], + get_explicit_type_name( types[ typeAIndex ] ), vecSizes[ index ] , + get_explicit_type_name( types[ typeAIndex ] ), vecSizes[ index ] ); + retVal = -1; + } + } + } + + return retVal; +} + +bool verify_integer_clamp( void *sourceA, void *sourceB, void *sourceC, void *destination, + ExplicitType vecAType, ExplicitType vecBType, ExplicitType vecCType, ExplicitType destType ) +{ + if( vecAType == kULong || vecAType == kUInt || vecAType == kUShort || vecAType == kUChar ) + { + cl_ulong valueA, valueB, valueC; + + switch( vecAType ) + { + case kULong: + valueA = ((cl_ulong*) sourceA)[0]; + valueB = ((cl_ulong*) sourceB)[0]; + valueC = ((cl_ulong*) sourceC)[0]; + break; + case kUInt: + valueA = ((cl_uint*) sourceA)[0]; + valueB = ((cl_uint*) sourceB)[0]; + valueC = ((cl_uint*) sourceC)[0]; + break; + case kUShort: + valueA = ((cl_ushort*) sourceA)[0]; + valueB = ((cl_ushort*) sourceB)[0]; + valueC = ((cl_ushort*) sourceC)[0]; + break; + case kUChar: + valueA = ((cl_uchar*) sourceA)[0]; + valueB = ((cl_uchar*) sourceB)[0]; + valueC = ((cl_uchar*) sourceC)[0]; + break; + default: + //error -- should never get here + abort(); + break; + } + + + if(valueB > valueC) { + return false; // results are undefined : let expected alone. + } + + switch( vecAType ) + { + case kULong: + ((cl_ulong*) destination)[0] = MAX(MIN(valueA, valueC), valueB); + break; + case kUInt: + ((cl_uint*) destination)[0] = (cl_uint) + (MAX(MIN(valueA, valueC), valueB)); + break; + case kUShort: + ((cl_ushort*) destination)[0] = (cl_ushort) + (MAX(MIN(valueA, valueC), valueB)); + break; + case kUChar: + ((cl_uchar*) destination)[0] = (cl_uchar) + (MAX(MIN(valueA, valueC), valueB)); + break; + default: + //error -- should never get here + abort(); + break; + } + + + + + } + else + { + cl_long valueA, valueB, valueC; + + + switch( vecAType ) + { + case kLong: + valueA = ((cl_long*) sourceA)[0]; + valueB = ((cl_long*) sourceB)[0]; + valueC = ((cl_long*) sourceC)[0]; + break; + case kInt: + valueA = ((cl_int*) sourceA)[0]; + valueB = ((cl_int*) sourceB)[0]; + valueC = ((cl_int*) sourceC)[0]; + break; + case kShort: + valueA = ((cl_short*) sourceA)[0]; + valueB = ((cl_short*) sourceB)[0]; + valueC = ((cl_short*) sourceC)[0]; + break; + case kChar: + valueA = ((cl_char*) sourceA)[0]; + valueB = ((cl_char*) sourceB)[0]; + valueC = ((cl_char*) sourceC)[0]; + break; + default: + //error -- should never get here + abort(); + break; + } + + if(valueB > valueC) { + return false; // undefined behavior : leave "expected" alone + } + + switch( vecAType ) + { + case kLong: + ((cl_long*) destination)[0] = MAX(MIN(valueA, valueC), valueB); + break; + case kInt: + ((cl_int*) destination)[0] = (cl_int) + (MAX(MIN(valueA, valueC), valueB)); + break; + case kShort: + ((cl_short*) destination)[0] = (cl_short) + (MAX(MIN(valueA, valueC), valueB)); + break; + case kChar: + ((cl_char*) destination)[0] = (cl_char) + (MAX(MIN(valueA, valueC), valueB)); + break; + default: + //error -- should never get here + abort(); + break; + } + + } + return true; +} + +int test_integer_clamp(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_three_param_integer_fn( queue, context, "clamp", verify_integer_clamp ); +} + +bool verify_integer_mad_sat( void *sourceA, void *sourceB, void *sourceC, void *destination, + ExplicitType vecAType, ExplicitType vecBType, ExplicitType vecCType, ExplicitType destType ) +{ + if( vecAType == kULong || vecAType == kUInt || vecAType == kUShort || vecAType == kUChar ) + { + cl_ulong valueA, valueB, valueC; + + switch( vecAType ) + { + case kULong: + valueA = ((cl_ulong*) sourceA)[0]; + valueB = ((cl_ulong*) sourceB)[0]; + valueC = ((cl_ulong*) sourceC)[0]; + break; + case kUInt: + valueA = ((cl_uint*) sourceA)[0]; + valueB = ((cl_uint*) sourceB)[0]; + valueC = ((cl_uint*) sourceC)[0]; + break; + case kUShort: + valueA = ((cl_ushort*) sourceA)[0]; + valueB = ((cl_ushort*) sourceB)[0]; + valueC = ((cl_ushort*) sourceC)[0]; + break; + case kUChar: + valueA = ((cl_uchar*) sourceA)[0]; + valueB = ((cl_uchar*) sourceB)[0]; + valueC = ((cl_uchar*) sourceC)[0]; + break; + default: + //error -- should never get here + abort(); + break; + } + + cl_ulong multHi, multLo; + multiply_unsigned_64_by_64( valueA, valueB, multLo, multHi ); + + multLo += valueC; + multHi += multLo < valueC; // carry if overflow + if( multHi ) + multLo = 0xFFFFFFFFFFFFFFFFULL; + + switch( vecAType ) + { + case kULong: + ((cl_ulong*) destination)[0] = multLo; + break; + case kUInt: + ((cl_uint*) destination)[0] = (cl_uint) MIN( multLo, (cl_ulong) CL_UINT_MAX ); + break; + case kUShort: + ((cl_ushort*) destination)[0] = (cl_ushort) MIN( multLo, (cl_ulong) CL_USHRT_MAX ); + break; + case kUChar: + ((cl_uchar*) destination)[0] = (cl_uchar) MIN( multLo, (cl_ulong) CL_UCHAR_MAX ); + break; + default: + //error -- should never get here + abort(); + break; + } + } + else + { + cl_long valueA, valueB, valueC; + + switch( vecAType ) + { + case kLong: + valueA = ((cl_long*) sourceA)[0]; + valueB = ((cl_long*) sourceB)[0]; + valueC = ((cl_long*) sourceC)[0]; + break; + case kInt: + valueA = ((cl_int*) sourceA)[0]; + valueB = ((cl_int*) sourceB)[0]; + valueC = ((cl_int*) sourceC)[0]; + break; + case kShort: + valueA = ((cl_short*) sourceA)[0]; + valueB = ((cl_short*) sourceB)[0]; + valueC = ((cl_short*) sourceC)[0]; + break; + case kChar: + valueA = ((cl_char*) sourceA)[0]; + valueB = ((cl_char*) sourceB)[0]; + valueC = ((cl_char*) sourceC)[0]; + break; + default: + //error -- should never get here + abort(); + break; + } + + cl_long multHi; + cl_ulong multLo; + multiply_signed_64_by_64( valueA, valueB, multLo, multHi ); + + cl_ulong sum = multLo + valueC; + // carry if overflow + if( valueC >= 0 ) + { + if( multLo > sum ) + { + multHi++; + if( CL_LONG_MIN == multHi ) + { + multHi = CL_LONG_MAX; + sum = CL_ULONG_MAX; + } + } + } + else + { + if( multLo < sum ) + { + multHi--; + if( CL_LONG_MAX == multHi ) + { + multHi = CL_LONG_MIN; + sum = 0; + } + } + } + + // saturate + if( multHi > 0 ) + sum = CL_LONG_MAX; + else if( multHi < -1 ) + sum = CL_LONG_MIN; + cl_long result = (cl_long) sum; + + switch( vecAType ) + { + case kLong: + ((cl_long*) destination)[0] = result; + break; + case kInt: + result = MIN( result, (cl_long) CL_INT_MAX ); + result = MAX( result, (cl_long) CL_INT_MIN ); + ((cl_int*) destination)[0] = (cl_int) result; + break; + case kShort: + result = MIN( result, (cl_long) CL_SHRT_MAX ); + result = MAX( result, (cl_long) CL_SHRT_MIN ); + ((cl_short*) destination)[0] = (cl_short) result; + break; + case kChar: + result = MIN( result, (cl_long) CL_CHAR_MAX ); + result = MAX( result, (cl_long) CL_CHAR_MIN ); + ((cl_char*) destination)[0] = (cl_char) result; + break; + default: + //error -- should never get here + abort(); + break; + } + } + return true; +} + +int test_integer_mad_sat(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_three_param_integer_fn( queue, context, "mad_sat", verify_integer_mad_sat ); +} + +bool verify_integer_mad_hi( void *sourceA, void *sourceB, void *sourceC, void *destination, + ExplicitType vecAType, ExplicitType vecBType, ExplicitType vecCType, ExplicitType destType ) +{ + if( vecAType == kULong || vecAType == kUInt || vecAType == kUShort || vecAType == kUChar ) + { + cl_ulong valueA, valueB, valueC; + + switch( vecAType ) + { + case kULong: + valueA = ((cl_ulong*) sourceA)[0]; + valueB = ((cl_ulong*) sourceB)[0]; + valueC = ((cl_ulong*) sourceC)[0]; + break; + case kUInt: + valueA = ((cl_uint*) sourceA)[0]; + valueB = ((cl_uint*) sourceB)[0]; + valueC = ((cl_uint*) sourceC)[0]; + break; + case kUShort: + valueA = ((cl_ushort*) sourceA)[0]; + valueB = ((cl_ushort*) sourceB)[0]; + valueC = ((cl_ushort*) sourceC)[0]; + break; + case kUChar: + valueA = ((cl_uchar*) sourceA)[0]; + valueB = ((cl_uchar*) sourceB)[0]; + valueC = ((cl_uchar*) sourceC)[0]; + break; + default: + //error -- should never get here + abort(); + break; + } + + cl_ulong multHi, multLo; + multiply_unsigned_64_by_64( valueA, valueB, multLo, multHi ); + + switch( vecAType ) + { + case kULong: + ((cl_ulong*) destination)[0] = multHi + valueC; + break; + case kUInt: + ((cl_uint*) destination)[0] = (cl_uint) (( multLo >> 32) + valueC ); + break; + case kUShort: + ((cl_ushort*) destination)[0] = (cl_ushort) (( multLo >> 16) + valueC ); + break; + case kUChar: + ((cl_uchar*) destination)[0] = (cl_uchar) (( multLo >> 8) + valueC ); + break; + default: + //error -- should never get here + abort(); + break; + } + } + else + { + cl_long valueA, valueB, valueC; + + switch( vecAType ) + { + case kLong: + valueA = ((cl_long*) sourceA)[0]; + valueB = ((cl_long*) sourceB)[0]; + valueC = ((cl_long*) sourceC)[0]; + break; + case kInt: + valueA = ((cl_int*) sourceA)[0]; + valueB = ((cl_int*) sourceB)[0]; + valueC = ((cl_int*) sourceC)[0]; + break; + case kShort: + valueA = ((cl_short*) sourceA)[0]; + valueB = ((cl_short*) sourceB)[0]; + valueC = ((cl_short*) sourceC)[0]; + break; + case kChar: + valueA = ((cl_char*) sourceA)[0]; + valueB = ((cl_char*) sourceB)[0]; + valueC = ((cl_char*) sourceC)[0]; + break; + default: + //error -- should never get here + abort(); + break; + } + + cl_long multHi; + cl_ulong multLo; + multiply_signed_64_by_64( valueA, valueB, multLo, multHi ); + + switch( vecAType ) + { + case kLong: + ((cl_long*) destination)[0] = multHi + valueC; + break; + case kInt: + ((cl_int*) destination)[0] = (cl_int) ((multLo >> 32) + valueC); + break; + case kShort: + ((cl_short*) destination)[0] = (cl_int) ((multLo >> 16) + valueC); + break; + case kChar: + ((cl_char*) destination)[0] = (cl_char) (cl_int) ((multLo >> 8) + valueC); + break; + default: + //error -- should never get here + abort(); + break; + } + } + return true; +} + +int test_integer_mad_hi( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_three_param_integer_fn( queue, context, "mad_hi", verify_integer_mad_hi ); +} + + diff --git a/test_conformance/integer_ops/test_intmad24.c b/test_conformance/integer_ops/test_intmad24.c new file mode 100644 index 00000000..d513442c --- /dev/null +++ b/test_conformance/integer_ops/test_intmad24.c @@ -0,0 +1,365 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +#define NUM_PROGRAMS 6 + +static const int vector_sizes[] = {1, 2, 3, 4, 8, 16}; + + +const char *int_mad24_kernel_code = +"__kernel void test_int_mad24(__global int *srcA, __global int *srcB, __global int *srcC, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mad24(srcA[tid], srcB[tid], srcC[tid]);\n" +"}\n"; + +const char *int2_mad24_kernel_code = +"__kernel void test_int2_mad24(__global int2 *srcA, __global int2 *srcB, __global int2 *srcC, __global int2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mad24(srcA[tid], srcB[tid], srcC[tid]);\n" +"}\n"; + +const char *int3_mad24_kernel_code = +"__kernel void test_int3_mad24(__global int *srcA, __global int *srcB, __global int *srcC, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +" int3 tmp = mad24(vload3(tid, srcA), vload3(tid, srcB), vload3(tid, srcC));\n" +" vstore3(tmp, tid, dst);\n" +"}\n"; + +const char *int4_mad24_kernel_code = +"__kernel void test_int4_mad24(__global int4 *srcA, __global int4 *srcB, __global int4 *srcC, __global int4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mad24(srcA[tid], srcB[tid], srcC[tid]);\n" +"}\n"; + +const char *int8_mad24_kernel_code = +"__kernel void test_int8_mad24(__global int8 *srcA, __global int8 *srcB, __global int8 *srcC, __global int8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mad24(srcA[tid], srcB[tid], srcC[tid]);\n" +"}\n"; + +const char *int16_mad24_kernel_code = +"__kernel void test_int16_mad24(__global int16 *srcA, __global int16 *srcB, __global int16 *srcC, __global int16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mad24(srcA[tid], srcB[tid], srcC[tid]);\n" +"}\n"; + + +const char *uint_mad24_kernel_code = +"__kernel void test_uint_mad24(__global uint *srcA, __global uint *srcB, __global uint *srcC, __global uint *dst)\n" +"{\n" +" uint tid = get_global_id(0);\n" +"\n" +" dst[tid] = mad24(srcA[tid], srcB[tid], srcC[tid]);\n" +"}\n"; + +const char *uint2_mad24_kernel_code = +"__kernel void test_uint2_mad24(__global uint2 *srcA, __global uint2 *srcB, __global uint2 *srcC, __global uint2 *dst)\n" +"{\n" +" uint tid = get_global_id(0);\n" +"\n" +" dst[tid] = mad24(srcA[tid], srcB[tid], srcC[tid]);\n" +"}\n"; + +const char *uint3_mad24_kernel_code = +"__kernel void test_uint3_mad24(__global uint *srcA, __global uint *srcB, __global uint *srcC, __global uint *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +" uint3 tmp = mad24(vload3(tid, srcA), vload3(tid, srcB), vload3(tid, srcC));\n" +" vstore3(tmp, tid, dst);\n" +"}\n"; + + +const char *uint4_mad24_kernel_code = +"__kernel void test_uint4_mad24(__global uint4 *srcA, __global uint4 *srcB, __global uint4 *srcC, __global uint4 *dst)\n" +"{\n" +" uint tid = get_global_id(0);\n" +"\n" +" dst[tid] = mad24(srcA[tid], srcB[tid], srcC[tid]);\n" +"}\n"; + +const char *uint8_mad24_kernel_code = +"__kernel void test_uint8_mad24(__global uint8 *srcA, __global uint8 *srcB, __global uint8 *srcC, __global uint8 *dst)\n" +"{\n" +" uint tid = get_global_id(0);\n" +"\n" +" dst[tid] = mad24(srcA[tid], srcB[tid], srcC[tid]);\n" +"}\n"; + +const char *uint16_mad24_kernel_code = +"__kernel void test_uint16_mad24(__global uint16 *srcA, __global uint16 *srcB, __global uint16 *srcC, __global uint16 *dst)\n" +"{\n" +" uint tid = get_global_id(0);\n" +"\n" +" dst[tid] = mad24(srcA[tid], srcB[tid], srcC[tid]);\n" +"}\n"; + + +int +verify_int_mad24(int *inptrA, int *inptrB, int *inptrC, int *outptr, size_t n, size_t vecSize) +{ + int r; + size_t i; + + for (i=0; i> 8; +} + +static inline int random_int32( MTdata d ) +{ + return genrand_int32(d); +} + + +int +test_intmad24(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[4]; + cl_int *input_ptr[3], *output_ptr, *p; + + cl_program program[2*NUM_PROGRAMS]; + cl_kernel kernel[2*NUM_PROGRAMS]; + size_t threads[1]; + + int num_elements; + int err; + int i; + MTdata d; + + size_t length = sizeof(cl_int) * 16 * n_elems; + num_elements = n_elems * 16; + + input_ptr[0] = (cl_int*)malloc(length); + input_ptr[1] = (cl_int*)malloc(length); + input_ptr[2] = (cl_int*)malloc(length); + output_ptr = (cl_int*)malloc(length); + + streams[0] = clCreateBuffer(context, 0, length, NULL, &err); + test_error(err, "clCreateBuffer failed"); + streams[1] = clCreateBuffer(context, 0, length, NULL, &err); + test_error(err, "clCreateBuffer failed"); + streams[2] = clCreateBuffer(context, 0, length, NULL, &err); + test_error(err, "clCreateBuffer failed"); + streams[3] = clCreateBuffer(context, 0, length, NULL, &err); + test_error(err, "clCreateBuffer failed"); + + d = init_genrand( gRandomSeed ); + p = input_ptr[0]; + for (i=0; i +#include +#include +#include + +#include "procs.h" + +#define NUM_PROGRAMS 6 + +static const int vector_sizes[] = {1, 2, 3, 4, 8, 16}; + + +const char *int_mul24_kernel_code = +"__kernel void test_int_mul24(__global int *srcA, __global int *srcB, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mul24(srcA[tid], srcB[tid]);\n" +"}\n"; + +const char *int2_mul24_kernel_code = +"__kernel void test_int2_mul24(__global int2 *srcA, __global int2 *srcB, __global int2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mul24(srcA[tid], srcB[tid]);\n" +"}\n"; + +const char *int3_mul24_kernel_code = +"__kernel void test_int3_mul24(__global int *srcA, __global int *srcB, __global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +" int3 tmp = mul24(vload3(tid, srcA), vload3(tid, srcB));\n" +" vstore3(tmp, tid, dst);\n" +"}\n"; + +const char *int4_mul24_kernel_code = +"__kernel void test_int4_mul24(__global int4 *srcA, __global int4 *srcB, __global int4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mul24(srcA[tid], srcB[tid]);\n" +"}\n"; + +const char *int8_mul24_kernel_code = +"__kernel void test_int8_mul24(__global int8 *srcA, __global int8 *srcB, __global int8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mul24(srcA[tid], srcB[tid]);\n" +"}\n"; + +const char *int16_mul24_kernel_code = +"__kernel void test_int16_mul24(__global int16 *srcA, __global int16 *srcB, __global int16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mul24(srcA[tid], srcB[tid]);\n" +"}\n"; + +const char *uint_mul24_kernel_code = +"__kernel void test_int_mul24(__global uint *srcA, __global uint *srcB, __global uint *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mul24(srcA[tid], srcB[tid]);\n" +"}\n"; + +const char *uint2_mul24_kernel_code = +"__kernel void test_int2_mul24(__global uint2 *srcA, __global uint2 *srcB, __global uint2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mul24(srcA[tid], srcB[tid]);\n" +"}\n"; + +const char *uint3_mul24_kernel_code = +"__kernel void test_int3_mul24(__global uint *srcA, __global uint *srcB, __global uint *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +" uint3 tmp = mul24(vload3(tid, srcA), vload3(tid, srcB));\n" +" vstore3(tmp, tid, dst);\n" +"}\n"; + +const char *uint4_mul24_kernel_code = +"__kernel void test_int4_mul24(__global uint4 *srcA, __global uint4 *srcB, __global uint4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mul24(srcA[tid], srcB[tid]);\n" +"}\n"; + +const char *uint8_mul24_kernel_code = +"__kernel void test_int8_mul24(__global uint8 *srcA, __global uint8 *srcB, __global uint8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mul24(srcA[tid], srcB[tid]);\n" +"}\n"; + +const char *uint16_mul24_kernel_code = +"__kernel void test_int16_mul24(__global uint16 *srcA, __global uint16 *srcB, __global uint16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = mul24(srcA[tid], srcB[tid]);\n" +"}\n"; + + +int +verify_int_mul24(int *inptrA, int *inptrB, int *outptr, size_t n, size_t vecSize) +{ + int r; + size_t i; + + for (i=0; i> 8; + int b = (inptrB[i] << 8 ) >> 8; + r = a * b; + if (r != outptr[i]) + return -1; + } + + return 0; +} + +int +verify_uint_mul24(cl_uint *inptrA, cl_uint *inptrB, cl_uint *outptr, size_t n, size_t vecSize) +{ + cl_uint r; + size_t i; + + for (i=0; i> 8; +} + + +static const char *test_str_names[] = { "int", "int2", "int3", "int4", "int8", "int16", "uint", "uint2", "uint3", "uint4", "uint8", "uint16" }; + +int +test_intmul24(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_mem streams[3]; + cl_int *input_ptr[2], *output_ptr, *p; + + cl_program program[NUM_PROGRAMS*2]; + cl_kernel kernel[NUM_PROGRAMS*2]; + size_t threads[1]; + + int num_elements; + int err; + int i; + MTdata d; + + size_t length = sizeof(cl_int) * 16 * n_elems; + num_elements = n_elems * 16; + + input_ptr[0] = (cl_int*)malloc(length); + input_ptr[1] = (cl_int*)malloc(length); + output_ptr = (cl_int*)malloc(length); + + streams[0] = clCreateBuffer(context, 0, length, NULL, NULL); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer(context, 0, length, NULL, NULL); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer(context, 0, length, NULL, NULL); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + d = init_genrand( gRandomSeed ); + p = input_ptr[0]; + for (i=0; i +#include +#include +#include + +#include "procs.h" + +#define str(s) #s + +#define __popcnt(x, __T, __n, __r) \ + { \ + __T y = x; \ + __r = 0; \ + int k; \ + for(k = 0; k < __n; k++) \ + { \ + if(y & (__T)0x1) __r++; \ + y >>= (__T)1; \ + } \ + } + +#define __verify_popcount_func(__T) \ + static int verify_popcount_##__T( const void *p, const void *r, size_t n, const char *sizeName, size_t vecSize ) \ + { \ + const __T *inA = (const __T *) p; \ + const __T *outptr = (const __T *) r; \ + size_t i; \ + int _n = sizeof(__T)*8; \ + __T ref; \ + for(i = 0; i < n; i++) \ + { \ + __T x = inA[i]; \ + __T res = outptr[i]; \ + __popcnt(x, __T, _n, ref); \ + if(res != ref) \ + { \ + log_info( "%ld) Failure for popcount( (%s%s) 0x%x ) = *%d vs %d\n", i, str(__T), sizeName, x, (int)ref, (int)res ); \ + return -1; \ + }\ + } \ + return 0; \ + } + +__verify_popcount_func(cl_char); +__verify_popcount_func(cl_uchar); +__verify_popcount_func(cl_short); +__verify_popcount_func(cl_ushort); +__verify_popcount_func(cl_int); +__verify_popcount_func(cl_uint); +__verify_popcount_func(cl_long); +__verify_popcount_func(cl_ulong); + +typedef int (*verifyFunc)( const void *, const void *, size_t n, const char *sizeName, size_t vecSize); +static const verifyFunc verify[] = { verify_popcount_cl_char, verify_popcount_cl_uchar, + verify_popcount_cl_short, verify_popcount_cl_ushort, + verify_popcount_cl_int, verify_popcount_cl_uint, + verify_popcount_cl_long, verify_popcount_cl_ulong }; + +static const char *test_str_names[] = { "char", "uchar", "short", "ushort", "int", "uint", "long", "ulong" }; + +static const int vector_sizes[] = {1, 2, 3, 4, 8, 16}; +static const char *vector_size_names[] = { "", "2", "3", "4", "8", "16" }; +static const char *vector_param_size_names[] = { "", "2", "", "4", "8", "16" }; +static const size_t kSizes[8] = { 1, 1, 2, 2, 4, 4, 8, 8 }; + +static void printSrc(const char *src[], int nSrcStrings) { + int i; + for(i = 0; i < nSrcStrings; ++i) { + log_info("%s", src[i]); + } +} + +int test_popcount(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + cl_int *input_ptr[1], *output_ptr, *p; + int err; + int i; + cl_uint vectorSize; + cl_uint type; + MTdata d; + int fail_count = 0; + + size_t length = sizeof(cl_int) * 8 * n_elems; + + input_ptr[0] = (cl_int*)malloc(length); + output_ptr = (cl_int*)malloc(length); + + d = init_genrand( gRandomSeed ); + p = input_ptr[0]; + for (i=0; i<8 * n_elems; i++) + p[i] = genrand_int32(d); + free_mtdata(d); d = NULL; + + for( type = 0; type < sizeof( test_str_names ) / sizeof( test_str_names[0] ); type++ ) + { + //embedded devices don't support long/ulong so skip over + if (! gHasLong && strstr(test_str_names[type],"long")) + { + log_info( "WARNING: 64 bit integers are not supported on this device. Skipping %s\n", test_str_names[type] ); + continue; + } + + verifyFunc f = verify[ type ]; + // Note: restrict the element count here so we don't end up overrunning the output buffer if we're compensating for 32-bit writes + size_t elementCount = length / kSizes[type]; + cl_mem streams[2]; + + log_info( "%s", test_str_names[type] ); + fflush( stdout ); + + // Set up data streams for the type + streams[0] = clCreateBuffer(context, 0, length, NULL, NULL); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer(context, 0, length, NULL, NULL); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + err = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, length, input_ptr[0], 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + + for( vectorSize = 0; vectorSize < sizeof( vector_size_names ) / sizeof( vector_size_names[0] ); vectorSize++ ) + { + cl_program program = NULL; + cl_kernel kernel = NULL; + + const char *source[] = { + "__kernel void test_popcount_", test_str_names[type], vector_size_names[vectorSize], + "(__global ", test_str_names[type], vector_param_size_names[vectorSize], + " *srcA, __global ", test_str_names[type], vector_param_size_names[vectorSize], + " *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " ", test_str_names[type], vector_size_names[vectorSize], " sA;\n", + " sA = ", ( vector_sizes[ vectorSize ] == 3 ) ? "vload3( tid, srcA )" : "srcA[tid]", ";\n", + " ", test_str_names[type], vector_size_names[vectorSize], " dstVal = popcount(sA);\n" + " ", ( vector_sizes[ vectorSize ] == 3 ) ? "vstore3( dstVal, tid, dst )" : "dst[ tid ] = dstVal", ";\n", + "}\n" }; + + + char kernelName[128]; + snprintf( kernelName, sizeof( kernelName ), "test_popcount_%s%s", test_str_names[type], vector_size_names[vectorSize] ); + + err = create_single_kernel_helper(context, &program, &kernel, sizeof( source ) / sizeof( source[0] ), source, kernelName ); + + if (err) { + return -1; + } + + err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]); + err |= clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + //Wipe the output buffer clean + uint32_t pattern = 0xdeadbeef; + memset_pattern4( output_ptr, &pattern, length ); + err = clEnqueueWriteBuffer(queue, streams[1], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + + size_t size = elementCount / (vector_sizes[vectorSize]); + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &size, NULL, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + err = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueReadBuffer failed\n"); + return -1; + } + + char *inP = (char *)input_ptr[0]; + char *outP = (char *)output_ptr; + + for( size_t e = 0; e < size; e++ ) + { + if( f( inP, outP, (vector_sizes[vectorSize]), vector_size_names[vectorSize], vector_sizes[vectorSize] ) ) { + printSrc(source, sizeof(source)/sizeof(source[0])); + ++fail_count; break; // return -1; + } + inP += kSizes[type] * ( (vector_sizes[vectorSize]) ); + outP += kSizes[type] * ( (vector_sizes[vectorSize]) ); + } + + clReleaseKernel( kernel ); + clReleaseProgram( program ); + log_info( "." ); + fflush( stdout ); + } + + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + log_info( "done\n" ); + } + + + if(fail_count) { + log_info("Failed on %d types\n", fail_count); + return -1; + } + log_info("popcount test passed\n"); + + free(input_ptr[0]); + free(output_ptr); + + return err; +} + + diff --git a/test_conformance/integer_ops/test_sub_sat.c b/test_conformance/integer_ops/test_sub_sat.c new file mode 100644 index 00000000..cc8a902d --- /dev/null +++ b/test_conformance/integer_ops/test_sub_sat.c @@ -0,0 +1,376 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" + +#define UCHAR_MIN 0 +#define USHRT_MIN 0 +#define UINT_MIN 0 + +#ifndef MAX +#define MAX( _a, _b ) ( (_a) > (_b) ? (_a) : (_b) ) +#endif +#ifndef MIN +#define MIN( _a, _b ) ( (_a) < (_b) ? (_a) : (_b) ) +#endif + + +static int verify_subsat_char( const cl_char *inA, const cl_char *inB, const cl_char *outptr, int n, const char *sizeName, int vecSize ) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_int r = (cl_int) inA[i] - (cl_int) inB[i]; + r = MAX( r, CL_CHAR_MIN ); + r = MIN( r, CL_CHAR_MAX ); + + if( r != outptr[i] ) + { log_info( "\n%d) Failure for sub_sat( (char%s) 0x%2.2x, (char%s) 0x%2.2x) = *0x%2.2x vs 0x%2.2x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_subsat_uchar( const cl_uchar *inA, const cl_uchar *inB, const cl_uchar *outptr, int n, const char *sizeName, int vecSize ) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_int r = (cl_int) inA[i] - (cl_int) inB[i]; + r = MAX( r, 0 ); + r = MIN( r, CL_UCHAR_MAX ); + if( r != outptr[i] ) + { log_info( "\n%d) Failure for sub_sat( (uchar%s) 0x%2.2x, (uchar%s) 0x%2.2x) = *0x%2.2x vs 0x%2.2x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_subsat_short( const cl_short *inA, const cl_short *inB, const cl_short *outptr, int n, const char *sizeName, int vecSize ) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_int r = (cl_int) inA[i] - (cl_int) inB[i]; + r = MAX( r, CL_SHRT_MIN ); + r = MIN( r, CL_SHRT_MAX ); + + if( r != outptr[i] ) + { log_info( "\n%d) Failure for sub_sat( (short%s) 0x%4.4x, (short%s) 0x%4.4x) = *0x%4.4x vs 0x%4.4x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_subsat_ushort( const cl_ushort *inA, const cl_ushort *inB, const cl_ushort *outptr, int n, const char *sizeName , int vecSize) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_int r = (cl_int) inA[i] - (cl_int) inB[i]; + r = MAX( r, 0 ); + r = MIN( r, CL_USHRT_MAX ); + + if( r != outptr[i] ) + { log_info( "\n%d) Failure for sub_sat( (ushort%s) 0x%4.4x, (ushort%s) 0x%4.4x) = *0x%4.4x vs 0x%4.4x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_subsat_int( const cl_int *inA, const cl_int *inB, const cl_int *outptr, int n, const char *sizeName , int vecSize) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_int r = (cl_int) ((cl_uint)inA[i] - (cl_uint)inB[i]); + if( inB[i] < 0 ) + { + if( r < inA[i] ) + r = CL_INT_MAX; + } + else + { + if( r > inA[i] ) + r = CL_INT_MIN; + } + + + if( r != outptr[i] ) + { log_info( "\n%d) Failure for sub_sat( (int%s) 0x%8.8x, (int%s) 0x%8.8x) = *0x%8.8x vs 0x%8.8x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_subsat_uint( const cl_uint *inA, const cl_uint *inB, const cl_uint *outptr, int n, const char *sizeName , int vecSize) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_uint r = inA[i] - inB[i]; + if( inA[i] < inB[i] ) + r = 0; + + if( r != outptr[i] ) + { log_info( "\n%d) Failure for sub_sat( (uint%s) 0x%8.8x, (uint%s) 0x%8.8x) = *0x%8.8x vs 0x%8.8x\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_subsat_long( const cl_long *inA, const cl_long *inB, const cl_long *outptr, int n, const char *sizeName , int vecSize) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_long r = (cl_long)((cl_ulong)inA[i] - (cl_ulong)inB[i]); + if( inB[i] < 0 ) + { + if( r < inA[i] ) + r = CL_LONG_MAX; + } + else + { + if( r > inA[i] ) + r = CL_LONG_MIN; + } + if( r != outptr[i] ) + { log_info( "%d) Failure for sub_sat( (long%s) 0x%16.16llx, (long%s) 0x%16.16llx) = *0x%16.16llx vs 0x%16.16llx\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +static int verify_subsat_ulong( const cl_ulong *inA, const cl_ulong *inB, const cl_ulong *outptr, int n, const char *sizeName , int vecSize) +{ + int i; + for( i = 0; i < n; i++ ) + { + cl_ulong r = inA[i] - inB[i]; + if( inA[i] < inB[i] ) + r = 0; + if( r != outptr[i] ) + { log_info( "%d) Failure for sub_sat( (ulong%s) 0x%16.16llx, (ulong%s) 0x%16.16llx) = *0x%16.16llx vs 0x%16.16llx\n", i, sizeName, inA[i], sizeName, inB[i], r, outptr[i] ); return -1; } + } + return 0; +} + +typedef int (*verifyFunc)( const void *, const void *, const void *, int n, const char *sizeName, int ); +static const verifyFunc verify[] = { (verifyFunc) verify_subsat_char, (verifyFunc) verify_subsat_uchar, + (verifyFunc) verify_subsat_short, (verifyFunc) verify_subsat_ushort, + (verifyFunc) verify_subsat_int, (verifyFunc) verify_subsat_uint, + (verifyFunc) verify_subsat_long, (verifyFunc) verify_subsat_ulong }; + +static const char *test_str_names[] = { "char", "uchar", "short", "ushort", "int", "uint", "long", "ulong" }; +static const int vector_sizes[] = {1, 2, 3, 4, 8, 16}; +static const char *vector_size_names[] = { "", "2", "3", "4", "8", "16" }; + +static const size_t kSizes[8] = { 1, 1, 2, 2, 4, 4, 8, 8 }; + +int test_sub_sat(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + int *input_ptr[2], *output_ptr, *p; + int err; + cl_uint i; + cl_uint vectorSize; + cl_uint type; + MTdata d; + int fail_count = 0; + + size_t length = sizeof(int) * 4 * n_elems; + + input_ptr[0] = (int*)malloc(length); + input_ptr[1] = (int*)malloc(length); + output_ptr = (int*)malloc(length); + + d = init_genrand( gRandomSeed ); + p = input_ptr[0]; + for (i=0; i<4 * (cl_uint) n_elems; i++) + p[i] = genrand_int32(d); + p = input_ptr[1]; + for (i=0; i<4 * (cl_uint) n_elems; i++) + p[i] = genrand_int32(d); + free_mtdata(d); d = NULL; + + for( type = 0; type < sizeof( test_str_names ) / sizeof( test_str_names[0] ); type++ ) + { + + //embedded devices don't support long/ulong so skip over + if (! gHasLong && strstr(test_str_names[type],"long")) + { + log_info( "WARNING: device does not support 64-bit integers. Skipping %s\n", test_str_names[type] ); + continue; + } + + verifyFunc f = verify[ type ]; + // Note: restrict the element count here so we don't end up overrunning the output buffer if we're compensating for 32-bit writes + size_t elementCount = length / kSizes[type]; + cl_mem streams[3]; + + log_info( "%s", test_str_names[type] ); + fflush( stdout ); + + // Set up data streams for the type + streams[0] = clCreateBuffer(context, 0, length, NULL, NULL); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer(context, 0, length, NULL, NULL); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[2] = clCreateBuffer(context, 0, length, NULL, NULL); + if (!streams[2]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + err = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, length, input_ptr[0], 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + err = clEnqueueWriteBuffer(queue, streams[1], CL_TRUE, 0, length, input_ptr[1], 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + + for( vectorSize = 0; vectorSize < sizeof( vector_size_names ) / sizeof( vector_size_names[0] ); vectorSize++ ) + { + cl_program program = NULL; + cl_kernel kernel = NULL; + + const char *source[] = { + "__kernel void test_sub_sat_", test_str_names[type], vector_size_names[vectorSize], + "(__global ", test_str_names[type], vector_size_names[vectorSize], + " *srcA, __global ", test_str_names[type], vector_size_names[vectorSize], + " *srcB, __global ", test_str_names[type], vector_size_names[vectorSize], + " *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " ", test_str_names[type], vector_size_names[vectorSize], " tmp = sub_sat(srcA[tid], srcB[tid]);\n" + " dst[tid] = tmp;\n" + "}\n" + }; + + const char *sourceV3[] = { + "__kernel void test_sub_sat_", test_str_names[type], vector_size_names[vectorSize], + "(__global ", test_str_names[type], + " *srcA, __global ", test_str_names[type], + " *srcB, __global ", test_str_names[type], + " *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " ", test_str_names[type], vector_size_names[vectorSize], " tmp = sub_sat(vload3(tid, srcA), vload3(tid, srcB));\n" + " vstore3(tmp, tid, dst);\n" + "}\n" + }; + + char kernelName[128]; + snprintf( kernelName, sizeof( kernelName ), "test_sub_sat_%s%s", test_str_names[type], vector_size_names[vectorSize] ); + if(vector_sizes[vectorSize] != 3) + { + err = create_single_kernel_helper(context, &program, &kernel, sizeof( source ) / sizeof( source[0] ), source, kernelName ); + } else { + err = create_single_kernel_helper(context, &program, &kernel, sizeof( sourceV3 ) / sizeof( sourceV3[0] ), sourceV3, kernelName ); + } + if (err) + return -1; + + err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]); + err |= clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]); + err |= clSetKernelArg(kernel, 2, sizeof streams[2], &streams[2]); + if (err != CL_SUCCESS) + { + log_error("clSetKernelArgs failed\n"); + return -1; + } + + //Wipe the output buffer clean + uint32_t pattern = 0xdeadbeef; + memset_pattern4( output_ptr, &pattern, length ); + err = clEnqueueWriteBuffer(queue, streams[2], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueWriteBuffer failed\n"); + return -1; + } + + size_t size = elementCount / vector_sizes[vectorSize]; + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &size, NULL, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueNDRangeKernel failed\n"); + return -1; + } + + err = clEnqueueReadBuffer(queue, streams[2], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + log_error("clEnqueueReadBuffer failed\n"); + return -1; + } + + char *inP = (char *)input_ptr[0]; + char *inP2 = (char *)input_ptr[1]; + char *outP = (char *)output_ptr; + + for( size_t e = 0; e < size; e++ ) + { + if( f( inP, inP2, outP, vector_sizes[vectorSize], vector_size_names[vectorSize], vector_sizes[vectorSize] ) ) { + ++fail_count; break; // return -1; + } + inP += kSizes[type] * vector_sizes[vectorSize]; + inP2 += kSizes[type] * vector_sizes[vectorSize]; + outP += kSizes[type] * vector_sizes[vectorSize]; + } + + clReleaseKernel( kernel ); + clReleaseProgram( program ); + log_info( "." ); + fflush( stdout ); + } + + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + clReleaseMemObject( streams[2] ); + log_info( "done\n" ); + } + if(fail_count) { + log_info("Failed on %d types\n", fail_count); + return -1; + } + log_info("SUB_SAT test passed\n"); + + free(input_ptr[0]); + free(input_ptr[1]); + free(output_ptr); + + return err; +} + + diff --git a/test_conformance/integer_ops/test_unary_ops.cpp b/test_conformance/integer_ops/test_unary_ops.cpp new file mode 100644 index 00000000..06c6cf06 --- /dev/null +++ b/test_conformance/integer_ops/test_unary_ops.cpp @@ -0,0 +1,211 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/conversions.h" + +#define TEST_SIZE 512 + +enum OpKonstants +{ + kIncrement = 0, + kDecrement, + kBoth +}; + +const char *testKernel = +"__kernel void test( __global %s *inOut, __global char * control )\n" +"{\n" +" size_t tid = get_global_id(0);\n" +"\n" +" %s%s inOutVal = %s;\n" +"\n" +" if( control[tid] == 0 )\n" +" inOutVal++;\n" +" else if( control[tid] == 1 )\n" +" ++inOutVal;\n" +" else if( control[tid] == 2 )\n" +" inOutVal--;\n" +" else // if( control[tid] == 3 )\n" +" --inOutVal;\n" +"\n" +" %s;\n" +"}\n"; + +typedef int (*OpVerifyFn)( void * actualPtr, void * inputPtr, size_t vecSize, size_t numVecs, cl_char * controls ); + +int test_unary_op( cl_command_queue queue, cl_context context, OpKonstants whichOp, + ExplicitType vecType, size_t vecSize, + MTdata d, OpVerifyFn verifyFn ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + cl_long inData[TEST_SIZE * 16], outData[TEST_SIZE * 16]; + cl_char controlData[TEST_SIZE]; + int error; + size_t i; + size_t threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + + + // Create the source + char loadLine[ 1024 ], storeLine[ 1024 ]; + if( vecSize == 1 ) + { + sprintf( loadLine, "inOut[tid]" ); + sprintf( storeLine, "inOut[tid] = inOutVal" ); + } + else + { + sprintf( loadLine, "vload%ld( tid, inOut )", vecSize ); + sprintf( storeLine, "vstore%ld( inOutVal, tid, inOut )", vecSize ); + } + + char sizeNames[][4] = { "", "", "2", "3", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + sprintf( kernelSource, testKernel, get_explicit_type_name( vecType ), /*sizeNames[ vecSize ],*/ + get_explicit_type_name( vecType ), sizeNames[ vecSize ], + loadLine, storeLine ); + + // Create the kernel + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "test" ) ) + { + log_error( "ERROR: Unable to create test program!\n" ); + return -1; + } + + // Generate two streams. The first is our random data to test against, the second is our control stream + generate_random_data( vecType, vecSize * TEST_SIZE, d, inData ); + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), + get_explicit_type_size( vecType ) * vecSize * TEST_SIZE, + inData, &error ); + test_error( error, "Creating input data array failed" ); + + cl_uint bits; + for( i = 0; i < TEST_SIZE; i++ ) + { + size_t which = i & 7; + if( which == 0 ) + bits = genrand_int32(d); + + controlData[ i ] = ( bits >> ( which << 1 ) ) & 0x03; + if( whichOp == kDecrement ) + // For sub ops, the min control value is 2. Otherwise, it's 0 + controlData[ i ] |= 0x02; + else if( whichOp == kIncrement ) + // For addition ops, the MAX control value is 1. Otherwise, it's 3 + controlData[ i ] &= ~0x02; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), + sizeof( controlData ), controlData, &error ); + test_error( error, "Unable to create control stream" ); + + // Assign streams and execute + error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + + // Run the kernel + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + + // Read the results + error = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, + get_explicit_type_size( vecType ) * TEST_SIZE * vecSize, + outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + // Now verify the results + return verifyFn( outData, inData, vecSize, TEST_SIZE, controlData ); +} + +template int VerifyFn( void * actualPtr, void * inputPtr, size_t vecSize, size_t numVecs, cl_char * controls ) +{ + T * actualData = (T *)actualPtr; + T * inputData = (T *)inputPtr; + + size_t index = 0; + for( size_t i = 0; i < numVecs; i++ ) + { + for( size_t j = 0; j < vecSize; j++, index++ ) + { + T nextVal = inputData[ index ]; + if( controls[ i ] & 0x02 ) + nextVal--; + else + nextVal++; + + if( actualData[ index ] != nextVal ) + { + log_error( "ERROR: Validation failed on vector %ld:%ld (expected %lld, got %lld)", i, j, + (cl_long)nextVal, (cl_long)actualData[ index ] ); + return -1; + } + } + } + return 0; +} + +int test_unary_op_set( cl_command_queue queue, cl_context context, OpKonstants whichOp ) +{ + ExplicitType types[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kNumExplicitTypes }; + OpVerifyFn verifys[] = { VerifyFn, VerifyFn, VerifyFn, VerifyFn, VerifyFn, VerifyFn, VerifyFn, VerifyFn, NULL }; + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 }; + unsigned int index, typeIndex; + int retVal = 0; + RandomSeed seed(gRandomSeed ); + + for( typeIndex = 0; types[ typeIndex ] != kNumExplicitTypes; typeIndex++ ) + { + if ((types[ typeIndex ] == kLong || types[ typeIndex ] == kULong) && !gHasLong) + continue; + + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + if( test_unary_op( queue, context, whichOp, types[ typeIndex ], vecSizes[ index ], seed, verifys[ typeIndex ] ) != 0 ) + { + log_error( " Vector %s%d FAILED\n", get_explicit_type_name( types[ typeIndex ] ), vecSizes[ index ] ); + retVal = -1; + } + } + } + + return retVal; +} + +int test_unary_ops_full(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_unary_op_set( queue, context, kBoth ); +} + +int test_unary_ops_increment(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_unary_op_set( queue, context, kIncrement ); +} + +int test_unary_ops_decrement(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_unary_op_set( queue, context, kDecrement ); +} diff --git a/test_conformance/integer_ops/test_upsample.cpp b/test_conformance/integer_ops/test_upsample.cpp new file mode 100644 index 00000000..6e823398 --- /dev/null +++ b/test_conformance/integer_ops/test_upsample.cpp @@ -0,0 +1,263 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/conversions.h" + +static const int vector_sizes[] = {1, 2, 3, 4, 8, 16}; +#define NUM_VECTOR_SIZES 6 + +const char *permute_2_param_kernel_pattern = +"__kernel void test_upsample(__global %s *sourceA, __global %s *sourceB, __global %s *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( sourceA[tid], sourceB[tid] );\n" +"\n" +"}\n"; + + +const char *permute_2_param_kernel_pattern_v3srcdst = +"__kernel void test_upsample(__global %s *sourceA, __global %s *sourceB, __global %s *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" vstore3( %s( vload3(tid,sourceA), vload3(tid, sourceB) ), tid, destValues);\n" +"\n" +"}\n"; + +int test_upsample_2_param_fn(cl_command_queue queue, cl_context context, const char *fnName, ExplicitType sourceAType, ExplicitType sourceBType, ExplicitType outType, + size_t sourceAVecSize, size_t sourceBVecSize, size_t outVecSize, size_t count, + void *sourceA, void *sourceB, void *expectedResults ) +{ + cl_program program; + cl_kernel kernel; + int error, retCode = 0; + cl_mem streams[3]; + void *outData; + size_t threadSize, groupSize, i; + unsigned char *expectedPtr, *outPtr; + size_t sourceATypeSize, sourceBTypeSize, outTypeSize, outStride; + char programSource[ 10240 ], aType[ 64 ], bType[ 64 ], tType[ 64 ]; + const char *progPtr; + + + sourceATypeSize = get_explicit_type_size( sourceAType ); + sourceBTypeSize = get_explicit_type_size( sourceBType ); + outTypeSize = get_explicit_type_size( outType ); + + outStride = outTypeSize * outVecSize; + outData = malloc( outStride * count ); + + /* Construct the program */ + strcpy( aType, get_explicit_type_name( sourceAType ) ); + strcpy( bType, get_explicit_type_name( sourceBType ) ); + strcpy( tType, get_explicit_type_name( outType ) ); + if( sourceAVecSize > 1 && sourceAVecSize != 3) + sprintf( aType + strlen( aType ), "%d", (int)sourceAVecSize ); + if( sourceBVecSize > 1 && sourceBVecSize != 3) + sprintf( bType + strlen( bType ), "%d", (int)sourceBVecSize ); + if( outVecSize > 1 && outVecSize != 3) + sprintf( tType + strlen( tType ), "%d", (int)outVecSize ); + + if(sourceAVecSize == 3 && sourceBVecSize == 3 && outVecSize == 3) + { + // permute_2_param_kernel_pattern_v3srcdst + sprintf( programSource, permute_2_param_kernel_pattern_v3srcdst, aType, bType, tType, fnName ); + } + else if(sourceAVecSize != 3 && sourceBVecSize != 3 && outVecSize != 3) + { + sprintf( programSource, permute_2_param_kernel_pattern, aType, bType, tType, fnName ); + } else { + vlog_error("Not implemented for %d,%d -> %d\n", + (int)sourceAVecSize, (int)sourceBVecSize, (int)outVecSize); + return -1; + } + + progPtr = (const char *)programSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, &progPtr, "test_upsample" ) ) + { + free( outData ); + return -1; + } + + /* Set up parameters */ + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sourceATypeSize * sourceAVecSize * count, sourceA, NULL ); + if (!streams[0]) + { + log_error("ERROR: Creating input array A failed!\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sourceBTypeSize * sourceBVecSize * count, sourceB, NULL ); + if (!streams[1]) + { + log_error("ERROR: Creating input array B failed!\n"); + return -1; + } + streams[2] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), outStride * count, NULL, NULL ); + if (!streams[2]) + { + log_error("ERROR: Creating output array failed!\n"); + return -1; + } + + /* Set the arguments */ + error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set kernel arguments" ); + error = clSetKernelArg(kernel, 2, sizeof( streams[2] ), &streams[2] ); + test_error( error, "Unable to set kernel arguments" ); + + /* Run the kernel */ + threadSize = count; + + error = get_max_common_work_group_size( context, kernel, threadSize, &groupSize ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, &threadSize, &groupSize, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* Now verify the results. Each value should have been duplicated four times, and we should be able to just + do a memcpy instead of relying on the actual type of data */ + error = clEnqueueReadBuffer( queue, streams[2], CL_TRUE, 0, outStride * count, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output values!" ); + + expectedPtr = (unsigned char *)expectedResults; + outPtr = (unsigned char *)outData; + + for( i = 0; i < count; i++ ) + { + if( memcmp( outPtr, expectedPtr, outTypeSize * outVecSize ) != 0 ) + { + log_error( "ERROR: Output value %d does not validate!\n", (int)i ); + retCode = -1; + break; + } + expectedPtr += outTypeSize * outVecSize; + outPtr += outStride; + } + + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + clReleaseMemObject( streams[2] ); + clReleaseKernel( kernel ); + clReleaseProgram( program ); + free( outData ); + + return retCode; +} + +void * create_upsample_data( ExplicitType type, void *sourceA, void *sourceB, size_t count ) +{ + void *outData; + size_t i, tSize; + + tSize = get_explicit_type_size( type ); + outData = malloc( tSize * count * 2 ); + + switch( tSize ) + { + case 1: + { + const cl_uchar *aPtr = (const cl_uchar *) sourceA; + const cl_uchar *bPtr = (const cl_uchar *) sourceB; + cl_ushort *dPtr = (cl_ushort*) outData; + for( i = 0; i < count; i++ ) + { + cl_ushort u = *bPtr++; + u |= ((cl_ushort) *aPtr++) << 8; + *dPtr++ = u; + } + } + break; + case 2: + { + const cl_ushort *aPtr = (const cl_ushort *) sourceA; + const cl_ushort *bPtr = (const cl_ushort *) sourceB; + cl_uint *dPtr = (cl_uint*) outData; + for( i = 0; i < count; i++ ) + { + cl_uint u = *bPtr++; + u |= ((cl_uint) *aPtr++) << 16; + *dPtr++ = u; + } + } + break; + case 4: + { + const cl_uint *aPtr = (const cl_uint *) sourceA; + const cl_uint *bPtr = (const cl_uint *) sourceB; + cl_ulong *dPtr = (cl_ulong*) outData; + for( i = 0; i < count; i++ ) + { + cl_ulong u = *bPtr++; + u |= ((cl_ulong) *aPtr++) << 32; + *dPtr++ = u; + } + } + break; + default: + log_error( "ERROR: unknown type size: %ld\n", tSize ); + return NULL; + } + + return outData; +} + +int test_integer_upsample(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + ExplicitType typesToTest[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kNumExplicitTypes }; + ExplicitType baseTypes[] = { kUChar, kUChar, kUShort, kUShort, kUInt, kUInt, kNumExplicitTypes }; + ExplicitType outTypes[] = { kShort, kUShort, kInt, kUInt, kLong, kULong, kNumExplicitTypes }; + int i, err = 0; + int sizeIndex; + size_t size; + void *sourceA, *sourceB, *expected; + RandomSeed seed(gRandomSeed ); + + for( i = 0; typesToTest[ i ] != kNumExplicitTypes; i++ ) + { + if ((outTypes[i] == kLong || outTypes[i] == kULong) && !gHasLong) + { + log_info( "Longs unsupported on this device. Skipping...\n"); + continue; + } + + for( sizeIndex = 0; sizeIndex < NUM_VECTOR_SIZES; sizeIndex++) + { + size = (size_t)vector_sizes[sizeIndex]; + log_info("running upsample test for %s %s vector size %d\n", get_explicit_type_name(typesToTest[i]), get_explicit_type_name(baseTypes[i]), (int)size); + sourceA = create_random_data( typesToTest[ i ], seed, 256 ); + sourceB = create_random_data( baseTypes[ i ], seed, 256 ); + expected = create_upsample_data( typesToTest[ i ], sourceA, sourceB, 256 ); + + if( test_upsample_2_param_fn( queue, context, "upsample", + typesToTest[ i ], baseTypes[ i ], + outTypes[ i ], + size, size, size, + 256 / size, + sourceA, sourceB, expected ) != 0 ) + { + log_error( "TEST FAILED: %s for %s%d\n", "upsample", get_explicit_type_name( typesToTest[ i ] ), (int)size ); + err = -1; + } + free( sourceA ); + free( sourceB ); + free( expected ); + } + } + return err; +} + + diff --git a/test_conformance/integer_ops/verification_and_generation_functions.c b/test_conformance/integer_ops/verification_and_generation_functions.c new file mode 100644 index 00000000..f36a1bf4 --- /dev/null +++ b/test_conformance/integer_ops/verification_and_generation_functions.c @@ -0,0 +1,1675 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/conversions.h" + +extern MTdata d; + +// The tests we are running +const char *tests[] = { + "+", + "-", + "*", + "/", + "%", + "&", + "|", + "^", + ">>", + "<<", + ">>", + "<<", + "~", + "?:", + "&&", + "||", + "<", + ">", + "<=", + ">=", + "==", + "!=", + "!", +}; + +// The names of the tests +const char *test_names[] = { + "+", // 0 + "-", // 1 + "*", // 2 + "/", // 3 + "%", // 4 + "&", // 5 + "|", // 6 + "^", // 7 + ">> by vector", // 8 + "<< by vector", // 9 + ">> by scalar", // 10 + "<< by scalar", // 11 + "~", // 12 + "?:", // 13 + "&&", // 14 + "||", // 15 + "<", // 16 + ">", // 17 + "<=", // 18 + ">=", // 19 + "==", // 20 + "!=", // 21 + "!", // 22 +}; + +const size_t vector_aligns[] = {0, 1, 2, 4, 4, + 8, 8, 8, 8, + 16, 16, 16, 16, + 16, 16, 16, 16}; + +// ======================================= +// long +// ======================================= +int +verify_long(int test, size_t vector_size, cl_long *inptrA, cl_long *inptrB, cl_long *outptr, size_t n) +{ + cl_long r, shift_mask = (sizeof(cl_long)*8)-1; + size_t i, j; + int count=0; + + for (j=0; j> (inptrB[i] & shift_mask); + break; + case 9: + r = inptrA[i] << (inptrB[i] & shift_mask); + break; + case 10: + r = inptrA[i] >> (inptrB[j] & shift_mask); + break; + case 11: + r = inptrA[i] << (inptrB[j] & shift_mask); + break; + case 12: + r = ~inptrA[i]; + break; + case 13: + r = (inptrA[j] < inptrB[j]) ? inptrA[i] : inptrB[i]; + break; + case 14: + // Scalars are set to 1/0 + r = inptrA[i] && inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 15: + // Scalars are set to 1/0 + r = inptrA[i] || inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 16: + // Scalars are set to 1/0 + r = inptrA[i] < inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 17: + // Scalars are set to 1/0 + r = inptrA[i] > inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 18: + // Scalars are set to 1/0 + r = inptrA[i] <= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 19: + // Scalars are set to 1/0 + r = inptrA[i] >= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 20: + // Scalars are set to 1/0 + r = inptrA[i] == inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 21: + // Scalars are set to 1/0 + r = inptrA[i] != inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 22: + // Scalars are set to 1/0 + r = !inptrA[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + default: + log_error("Invalid test: %d\n", test); + return -1; + break; + } + if (r != outptr[i]) { + // Shift is tricky + if (test == 8 || test == 9) { + log_error("cl_long Verification failed at element %ld of %ld : 0x%llx %s 0x%llx = 0x%llx, got 0x%llx\n", i, n, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + log_error("\t1) Vector shift failure at element %ld: original is 0x%llx %s %d (0x%llx)\n", i, inptrA[i], tests[test], (int)inptrB[i], inptrB[i]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %lld (0x%llx).\n", (int)log2(sizeof(cl_long)*8), inptrB[i]&shift_mask, inptrB[i]&shift_mask); + } + else if (test == 10 || test == 11) { + + log_error("cl_long Verification failed at element %ld of %ld (%ld): 0x%llx %s 0x%llx = 0x%llx, got 0x%llx\n", i, n, j, inptrA[i], tests[test], inptrB[j], r, outptr[i]); + log_error("\t1) Scalar shift failure at element %ld: original is 0x%llx %s %d (0x%llx)\n", i, inptrA[i], tests[test], (int)inptrB[j], inptrB[j]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %lld (0x%llx).\n", (int)log2(sizeof(cl_long)*8), inptrB[j]&shift_mask, inptrB[j]&shift_mask); + } else if (test == 13) { + log_error("cl_int Verification failed at element %ld (%ld): (0x%llx < 0x%llx) ? 0x%llx : 0x%llx = 0x%llx, got 0x%llx\n", i, j, inptrA[j], inptrB[j], + inptrA[i], inptrB[i], r, outptr[i]); + } else { + log_error("cl_long Verification failed at element %ld of %ld: 0x%llx %s 0x%llx = 0x%llx, got 0x%llx\n", i, n, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + } + count++; + if (count >= MAX_ERRORS_TO_PRINT) { + log_error("Further errors ignored.\n"); + return -1; + } + } + } + } + + if (count) return -1; else return 0; +} + +void +init_long_data(uint64_t indx, int num_elements, cl_long *input_ptr[], MTdata d) +{ + cl_ulong *p = (cl_ulong *)input_ptr[0]; + int j; + + if (indx == 0) { + // Do the tricky values the first time around + fill_test_values( input_ptr[ 0 ], input_ptr[ 1 ], (size_t)num_elements, d ); + } else { + // Then just test lots of random ones. + for (j=0; j> (inptrB[i] & shift_mask); + break; + case 9: + r = inptrA[i] << (inptrB[i] & shift_mask); + break; + case 10: + r = inptrA[i] >> (inptrB[j] & shift_mask); + break; + case 11: + r = inptrA[i] << (inptrB[j] & shift_mask); + break; + case 12: + r = ~inptrA[i]; + break; + case 13: + r = (inptrA[j] < inptrB[j]) ? inptrA[i] : inptrB[i]; + break; + case 14: + // Scalars are set to 1/0 + r = inptrA[i] && inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 15: + // Scalars are set to 1/0 + r = inptrA[i] || inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 16: + // Scalars are set to 1/0 + r = inptrA[i] < inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 17: + // Scalars are set to 1/0 + r = inptrA[i] > inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 18: + // Scalars are set to 1/0 + r = inptrA[i] <= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 19: + // Scalars are set to 1/0 + r = inptrA[i] >= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 20: + // Scalars are set to 1/0 + r = inptrA[i] == inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 21: + // Scalars are set to 1/0 + r = inptrA[i] != inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 22: + // Scalars are set to 1/0 + r = !inptrA[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + default: + log_error("Invalid test: %d\n", test); + return -1; + break; + } + if (r != outptr[i]) { + // Shift is tricky + if (test == 8 || test == 9) { + log_error("cl_ulong Verification failed at element %ld of %ld: 0x%llx %s 0x%llx = 0x%llx, got 0x%llx\n", i, n, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + log_error("\t1) Shift failure at element %ld: original is 0x%llx %s %d (0x%llx)\n", i, inptrA[i], tests[test], (int)inptrB[i], inptrB[i]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %llu (0x%llx).\n", (int)log2(sizeof(cl_ulong)*8), inptrB[i]&shift_mask, inptrB[i]&shift_mask); + } + else if (test == 10 || test == 11) { + log_error("cl_ulong Verification failed at element %ld of %ld (%ld): 0x%llx %s 0x%llx = 0x%llx, got 0x%llx\n", i, n, j, inptrA[i], tests[test], inptrB[j], r, outptr[i]); + log_error("\t1) Scalar shift failure at element %ld: original is 0x%llx %s %d (0x%llx)\n", i, inptrA[i], tests[test], (int)inptrB[j], inptrB[j]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %lld (0x%llx).\n", (int)log2(sizeof(cl_long)*8), inptrB[j]&shift_mask, inptrB[j]&shift_mask); + } else if (test == 13) { + log_error("cl_int Verification failed at element %ld of %ld (%ld): (0x%llx < 0x%llx) ? 0x%llx : 0x%llx = 0x%llx, got 0x%llx\n", i, n, j, inptrA[j], inptrB[j], + inptrA[i], inptrB[i], r, outptr[i]); + } else { + log_error("cl_ulong Verification failed at element %ld of %ld: 0x%llx %s 0x%llx = 0x%llx, got 0x%llx\n", i, n, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + } + count++; + if (count >= MAX_ERRORS_TO_PRINT) { + log_error("Further errors ignored.\n"); + return -1; + } + } + } + } + if (count) return -1; else return 0; +} + +void +init_ulong_data(uint64_t indx, int num_elements, cl_ulong *input_ptr[], MTdata d) +{ + cl_ulong *p = (cl_ulong *)input_ptr[0]; + int j; + + if (indx == 0) + { + // Do the tricky values the first time around + fill_test_values( (cl_long*)input_ptr[ 0 ], (cl_long*)input_ptr[ 1 ], (size_t)num_elements, d ); + } + else + { + // Then just test lots of random ones. + for (j=0; j> (inptrB[i] & shift_mask); + break; + case 9: + r = inptrA[i] << (inptrB[i] & shift_mask); + break; + case 10: + r = inptrA[i] >> (inptrB[j] & shift_mask); + break; + case 11: + r = inptrA[i] << (inptrB[j] & shift_mask); + break; + case 12: + r = ~inptrA[i]; + break; + case 13: + r = (inptrA[j] < inptrB[j]) ? inptrA[i] : inptrB[i]; + break; + case 14: + // Scalars are set to 1/0 + r = inptrA[i] && inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 15: + // Scalars are set to 1/0 + r = inptrA[i] || inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 16: + // Scalars are set to 1/0 + r = inptrA[i] < inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 17: + // Scalars are set to 1/0 + r = inptrA[i] > inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 18: + // Scalars are set to 1/0 + r = inptrA[i] <= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 19: + // Scalars are set to 1/0 + r = inptrA[i] >= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 20: + // Scalars are set to 1/0 + r = inptrA[i] == inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 21: + // Scalars are set to 1/0 + r = inptrA[i] != inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 22: + // Scalars are set to 1/0 + r = !inptrA[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + default: + log_error("Invalid test: %d\n", test); + return -1; + break; + } + if (r != outptr[i]) { + // Shift is tricky + if (test == 8 || test == 9) { + log_error("cl_int Verification failed at element %ld: 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + log_error("\t1) Shift failure at element %ld: original is 0x%x %s %d (0x%x)\n", i, inptrA[i], tests[test], (int)inptrB[i], inptrB[i]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %d (0x%x).\n", (int)log2(sizeof(cl_int)*8), inptrB[i]&shift_mask, inptrB[i]&shift_mask); + } + else if (test == 10 || test == 11) { + log_error("cl_int Verification failed at element %ld (%ld): 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, j, inptrA[i], tests[test], inptrB[j], r, outptr[i]); + log_error("\t1) Scalar shift failure at element %ld: original is 0x%x %s %d (0x%x)\n", i, inptrA[i], tests[test], (int)inptrB[j], inptrB[j]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %d (0x%x).\n", (int)log2(sizeof(cl_int)*8), inptrB[j]&shift_mask, inptrB[j]&shift_mask); + } else if (test == 13) { + log_error("cl_int Verification failed at element %ld (%ld): (0x%x < 0x%x) ? 0x%x : 0x%x = 0x%x, got 0x%x\n", i, j, inptrA[j], inptrB[j], + inptrA[i], inptrB[i], r, outptr[i]); + } else { + log_error("cl_int Verification failed at element %ld: 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + } + count++; + if (count >= MAX_ERRORS_TO_PRINT) { + log_error("Further errors ignored.\n"); + return -1; + } + } + } + } + + if (count) return -1; else return 0; +} + +void +init_int_data(uint64_t indx, int num_elements, cl_int *input_ptr[], MTdata d) +{ + static const cl_int specialCaseList[] = { 0, -1, 1, CL_INT_MIN, CL_INT_MIN + 1, CL_INT_MAX }; + int j; + + // Set the inputs to a random number + for (j=0; j> (inptrB[i] & shift_mask); + break; + case 9: + r = inptrA[i] << (inptrB[i] & shift_mask); + break; + case 10: + r = inptrA[i] >> (inptrB[j] & shift_mask); + break; + case 11: + r = inptrA[i] << (inptrB[j] & shift_mask); + break; + case 12: + r = ~inptrA[i]; + break; + case 13: + r = (inptrA[j] < inptrB[j]) ? inptrA[i] : inptrB[i]; + break; + case 14: + // Scalars are set to 1/0 + r = inptrA[i] && inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 15: + // Scalars are set to 1/0 + r = inptrA[i] || inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 16: + // Scalars are set to 1/0 + r = inptrA[i] < inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 17: + // Scalars are set to 1/0 + r = inptrA[i] > inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 18: + // Scalars are set to 1/0 + r = inptrA[i] <= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 19: + // Scalars are set to 1/0 + r = inptrA[i] >= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 20: + // Scalars are set to 1/0 + r = inptrA[i] == inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 21: + // Scalars are set to 1/0 + r = inptrA[i] != inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 22: + // Scalars are set to 1/0 + r = !inptrA[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + default: + log_error("Invalid test: %d\n", test); + return -1; + break; + } + if (r != outptr[i]) { + // Shift is tricky + if (test == 8 || test == 9) { + log_error("cl_uint Verification failed at element %ld: 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + log_error("\t1) Shift failure at element %ld: original is 0x%x %s %d (0x%x)\n", i, inptrA[i], tests[test], (int)inptrB[i], inptrB[i]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %d (0x%x).\n", (int)log2(sizeof(cl_uint)*8), inptrB[i]&shift_mask, inptrB[i]&shift_mask); + } + else if (test == 10 || test == 11) { + log_error("cl_uint Verification failed at element %ld (%ld): 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, j, inptrA[i], tests[test], inptrB[j], r, outptr[i]); + log_error("\t1) Scalar shift failure at element %ld: original is 0x%x %s %d (0x%x)\n", i, inptrA[i], tests[test], (int)inptrB[j], inptrB[j]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %d (0x%x).\n", (int)log2(sizeof(cl_uint)*8), inptrB[j]&shift_mask, inptrB[j]&shift_mask); + } else if (test == 13) { + log_error("cl_int Verification failed at element %ld (%ld): (0x%x < 0x%x) ? 0x%x : 0x%x = 0x%x, got 0x%x\n", i, j, inptrA[j], inptrB[j], + inptrA[i], inptrB[i], r, outptr[i]); + } else { + log_error("cl_uint Verification failed at element %ld: 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + } + count++; + if (count >= MAX_ERRORS_TO_PRINT) { + log_error("Further errors ignored.\n"); + return -1; + } + } + } + } + if (count) return -1; else return 0; +} + +void +init_uint_data(uint64_t indx, int num_elements, cl_uint *input_ptr[], MTdata d) +{ + static cl_uint specialCaseList[] = { 0, (cl_uint) CL_INT_MAX, (cl_uint) CL_INT_MAX + 1, CL_UINT_MAX-1, CL_UINT_MAX }; + int j; + + // Set the first input to an incrementing number + // Set the second input to a random number + for (j=0; j> (inptrB[i] & shift_mask); + break; + case 9: + r = inptrA[i] << (inptrB[i] & shift_mask); + break; + case 10: + r = inptrA[i] >> (inptrB[j] & shift_mask); + break; + case 11: + r = inptrA[i] << (inptrB[j] & shift_mask); + break; + case 12: + r = ~inptrA[i]; + break; + case 13: + r = (inptrA[j] < inptrB[j]) ? inptrA[i] : inptrB[i]; + break; + case 14: + // Scalars are set to 1/0 + r = inptrA[i] && inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 15: + // Scalars are set to 1/0 + r = inptrA[i] || inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 16: + // Scalars are set to 1/0 + r = inptrA[i] < inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 17: + // Scalars are set to 1/0 + r = inptrA[i] > inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 18: + // Scalars are set to 1/0 + r = inptrA[i] <= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 19: + // Scalars are set to 1/0 + r = inptrA[i] >= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 20: + // Scalars are set to 1/0 + r = inptrA[i] == inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 21: + // Scalars are set to 1/0 + r = inptrA[i] != inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 22: + // Scalars are set to 1/0 + r = !inptrA[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + default: + log_error("Invalid test: %d\n", test); + return -1; + break; + } + if (r != outptr[i]) { + // Shift is tricky + if (test == 8 || test == 9) { + log_error("cl_short Verification failed at element %ld: 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + log_error("\t1) Shift failure at element %ld: original is 0x%x %s %d (0x%x)\n", i, inptrA[i], tests[test], (int)inptrB[i], inptrB[i]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %d (0x%x).\n", (int)log2(sizeof(cl_short)*8), inptrB[i]&shift_mask, inptrB[i]&shift_mask); + } + else if (test == 10 || test == 11) { + log_error("cl_short Verification failed at element %ld (%ld): 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, j, inptrA[i], tests[test], inptrB[j], r, outptr[i]); + log_error("\t1) Scalar shift failure at element %ld: original is 0x%x %s %d (0x%x)\n", i, inptrA[i], tests[test], (int)inptrB[j], inptrB[j]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %d (0x%x).\n", (int)log2(sizeof(cl_short)*8), inptrB[j]&shift_mask, inptrB[j]&shift_mask); + } else if (test == 13) { + log_error("cl_int Verification failed at element %ld (%ld): (0x%x < 0x%x) ? 0x%x : 0x%x = 0x%x, got 0x%x\n", i, j, inptrA[j], inptrB[j], + inptrA[i], inptrB[i], r, outptr[i]); + } else { + log_error("cl_short Verification failed at element %ld: 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + } + count++; + if (count >= MAX_ERRORS_TO_PRINT) { + log_error("Further errors ignored.\n"); + return -1; + } + } + } + } + + if (count) return -1; else return 0; +} + +void +init_short_data(uint64_t indx, int num_elements, cl_short *input_ptr[], MTdata d) +{ + static const cl_short specialCaseList[] = { 0, -1, 1, CL_SHRT_MIN, CL_SHRT_MIN + 1, CL_SHRT_MAX }; + int j; + + // Set the inputs to a random number + for (j=0; j> 16); + } + + // Init the first few values to test special cases + { + size_t x, y, index = 0; + for( x = 0; x < sizeof( specialCaseList ) / sizeof( specialCaseList[0] ); x++ ) + for( y = 0; y < sizeof( specialCaseList ) / sizeof( specialCaseList[0] ); y++ ) + { + ((cl_short *)input_ptr[0])[index] = specialCaseList[x]; + ((cl_short *)input_ptr[1])[index++] = specialCaseList[y]; + } + } +} + + +// ======================================= +// ushort +// ======================================= +int +verify_ushort(int test, size_t vector_size, cl_ushort *inptrA, cl_ushort *inptrB, cl_ushort *outptr, size_t n) +{ + cl_ushort r; + cl_uint shift_mask = vector_size == 1 ? (cl_uint)(sizeof(cl_uint)*8)-1 + : (cl_uint)(sizeof(cl_ushort)*8)-1; + size_t i, j; + int count=0; + + for (j=0; j> (inptrB[i] & shift_mask); + break; + case 9: + r = inptrA[i] << (inptrB[i] & shift_mask); + break; + case 10: + r = inptrA[i] >> (inptrB[j] & shift_mask); + break; + case 11: + r = inptrA[i] << (inptrB[j] & shift_mask); + break; + case 12: + r = ~inptrA[i]; + break; + case 13: + r = (inptrA[j] < inptrB[j]) ? inptrA[i] : inptrB[i]; + break; + case 14: + // Scalars are set to 1/0 + r = inptrA[i] && inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 15: + // Scalars are set to 1/0 + r = inptrA[i] || inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 16: + // Scalars are set to 1/0 + r = inptrA[i] < inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 17: + // Scalars are set to 1/0 + r = inptrA[i] > inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 18: + // Scalars are set to 1/0 + r = inptrA[i] <= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 19: + // Scalars are set to 1/0 + r = inptrA[i] >= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 20: + // Scalars are set to 1/0 + r = inptrA[i] == inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 21: + // Scalars are set to 1/0 + r = inptrA[i] != inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 22: + // Scalars are set to 1/0 + r = !inptrA[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + default: + log_error("Invalid test: %d\n", test); + return -1; + break; + } + if (r != outptr[i]) { + // Shift is tricky + if (test == 8 || test == 9) { + log_error("cl_ushort Verification failed at element %ld: 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + log_error("\t1) Shift failure at element %ld: original is 0x%x %s %d (0x%x)\n", i, inptrA[i], tests[test], (int)inptrB[i], inptrB[i]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %d (0x%x).\n", (int)log2(sizeof(cl_ushort)*8), inptrB[i]&shift_mask, inptrB[i]&shift_mask); + } + else if (test == 10 || test == 11) { + log_error("cl_ushort Verification failed at element %ld (%ld): 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, j, inptrA[i], tests[test], inptrB[j], r, outptr[i]); + log_error("\t1) Scalar shift failure at element %ld: original is 0x%x %s %d (0x%x)\n", i, inptrA[i], tests[test], (int)inptrB[j], inptrB[j]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %d (0x%x).\n", (int)log2(sizeof(cl_ushort)*8), inptrB[j]&shift_mask, inptrB[j]&shift_mask); + } else if (test == 13) { + log_error("cl_int Verification failed at element %ld (%ld): (0x%x < 0x%x) ? 0x%x : 0x%x = 0x%x, got 0x%x\n", i, j, inptrA[j], inptrB[j], + inptrA[i], inptrB[i], r, outptr[i]); + } else { + log_error("cl_ushort Verification failed at element %ld: 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + } + count++; + if (count >= MAX_ERRORS_TO_PRINT) { + log_error("Further errors ignored.\n"); + return -1; + } + } + } + } + + if (count) return -1; else return 0; +} + +void +init_ushort_data(uint64_t indx, int num_elements, cl_ushort *input_ptr[], MTdata d) +{ + static const cl_ushort specialCaseList[] = { 0, -1, 1, CL_SHRT_MAX, CL_SHRT_MAX + 1, CL_USHRT_MAX }; + int j; + + // Set the inputs to a random number + for (j=0; j> 16); + } + + // Init the first few values to test special cases + { + size_t x, y, index = 0; + for( x = 0; x < sizeof( specialCaseList ) / sizeof( specialCaseList[0] ); x++ ) + for( y = 0; y < sizeof( specialCaseList ) / sizeof( specialCaseList[0] ); y++ ) + { + ((cl_ushort *)input_ptr[0])[index] = specialCaseList[x]; + ((cl_ushort *)input_ptr[1])[index++] = specialCaseList[y]; + } + } +} + + + +// ======================================= +// char +// ======================================= +int +verify_char(int test, size_t vector_size, cl_char *inptrA, cl_char *inptrB, cl_char *outptr, size_t n) +{ + cl_char r; + cl_int shift_mask = vector_size == 1 ? (cl_int)(sizeof(cl_int)*8)-1 + : (cl_int)(sizeof(cl_char)*8)-1; + size_t i, j; + int count=0; + + for (j=0; j> (inptrB[i] & shift_mask); + break; + case 9: + r = inptrA[i] << (inptrB[i] & shift_mask); + break; + case 10: + r = inptrA[i] >> (inptrB[j] & shift_mask); + break; + case 11: + r = inptrA[i] << (inptrB[j] & shift_mask); + break; + case 12: + r = ~inptrA[i]; + break; + case 13: + r = (inptrA[j] < inptrB[j]) ? inptrA[i] : inptrB[i]; + break; + case 14: + // Scalars are set to 1/0 + r = inptrA[i] && inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 15: + // Scalars are set to 1/0 + r = inptrA[i] || inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 16: + // Scalars are set to 1/0 + r = inptrA[i] < inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 17: + // Scalars are set to 1/0 + r = inptrA[i] > inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 18: + // Scalars are set to 1/0 + r = inptrA[i] <= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 19: + // Scalars are set to 1/0 + r = inptrA[i] >= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 20: + // Scalars are set to 1/0 + r = inptrA[i] == inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 21: + // Scalars are set to 1/0 + r = inptrA[i] != inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 22: + // Scalars are set to 1/0 + r = !inptrA[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + default: + log_error("Invalid test: %d\n", test); + return -1; + break; + } + if (r != outptr[i]) { + // Shift is tricky + if (test == 8 || test == 9) { + log_error("cl_char Verification failed at element %ld: 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + log_error("\t1) Shift failure at element %ld: original is 0x%x %s %d (0x%x)\n", i, inptrA[i], tests[test], (int)inptrB[i], inptrB[i]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %d (0x%x).\n", (int)log2(sizeof(cl_char)*8), inptrB[i]&shift_mask, inptrB[i]&shift_mask); + } + else if (test == 10 || test == 11) { + log_error("cl_char Verification failed at element %ld (%ld): 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, j, inptrA[i], tests[test], inptrB[j], r, outptr[i]); + log_error("\t1) Scalar shift failure at element %ld: original is 0x%x %s %d (0x%x)\n", i, inptrA[i], tests[test], (int)inptrB[j], inptrB[j]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %d (0x%x).\n", (int)log2(sizeof(cl_long)*8), inptrB[j]&shift_mask, inptrB[j]&shift_mask); + } else if (test == 13) { + log_error("cl_int Verification failed at element %ld (%ld): (0x%x < 0x%x) ? 0x%x : 0x%x = 0x%x, got 0x%x\n", i, j, inptrA[j], inptrB[j], + inptrA[i], inptrB[i], r, outptr[i]); + } else { + log_error("cl_char Verification failed at element %ld: 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + } + count++; + if (count >= MAX_ERRORS_TO_PRINT) { + log_error("Further errors ignored.\n"); + return -1; + } + } + } + } + if (count) return -1; else return 0; +} + +void +init_char_data(uint64_t indx, int num_elements, cl_char *input_ptr[], MTdata d) +{ + static const cl_char specialCaseList[] = { 0, -1, 1, CL_CHAR_MIN, CL_CHAR_MIN + 1, CL_CHAR_MAX }; + int j; + + // FIXME comment below might not be appropriate for + // vector data. Yes, checking every scalar char against every + // scalar char is only 2^16 ~ 64000 tests, but once we get to vec3, + // vec4, vec8... + + // in the meantime, this means I can use [] to access vec3 instead of + // vload3 / vstore3 :D + + // FIXME: we really should just check every char against every char here + // Set the inputs to a random number + for (j=0; j> 16); + } + + // Init the first few values to test special cases + { + size_t x, y, index = 0; + for( x = 0; x < sizeof( specialCaseList ) / sizeof( specialCaseList[0] ); x++ ) + for( y = 0; y < sizeof( specialCaseList ) / sizeof( specialCaseList[0] ); y++ ) + { + ((cl_char *)input_ptr[0])[index] = specialCaseList[x]; + ((cl_char *)input_ptr[1])[index++] = specialCaseList[y]; + } + } +} + + +// ======================================= +// uchar +// ======================================= +int +verify_uchar(int test, size_t vector_size, cl_uchar *inptrA, cl_uchar *inptrB, cl_uchar *outptr, size_t n) +{ + cl_uchar r; + cl_uint shift_mask = vector_size == 1 ? (cl_uint)(sizeof(cl_uint)*8)-1 + : (cl_uint)(sizeof(cl_uchar)*8)-1;; + size_t i, j; + int count=0; + + for (j=0; j> (inptrB[i] & shift_mask); + break; + case 9: + r = inptrA[i] << (inptrB[i] & shift_mask); + break; + case 10: + r = inptrA[i] >> (inptrB[j] & shift_mask); + break; + case 11: + r = inptrA[i] << (inptrB[j] & shift_mask); + break; + case 12: + r = ~inptrA[i]; + break; + case 13: + r = (inptrA[j] < inptrB[j]) ? inptrA[i] : inptrB[i]; + break; + case 14: + // Scalars are set to 1/0 + r = inptrA[i] && inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 15: + // Scalars are set to 1/0 + r = inptrA[i] || inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 16: + // Scalars are set to 1/0 + r = inptrA[i] < inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 17: + // Scalars are set to 1/0 + r = inptrA[i] > inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 18: + // Scalars are set to 1/0 + r = inptrA[i] <= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 19: + // Scalars are set to 1/0 + r = inptrA[i] >= inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 20: + // Scalars are set to 1/0 + r = inptrA[i] == inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 21: + // Scalars are set to 1/0 + r = inptrA[i] != inptrB[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + case 22: + // Scalars are set to 1/0 + r = !inptrA[i]; + // Vectors are set to -1/0 + if (vector_size != 1 && r) { + r = -1; + } + break; + default: + log_error("Invalid test: %d\n", test); + return -1; + break; + } + if (r != outptr[i]) { + // Shift is tricky + if (test == 8 || test == 9) { + log_error("cl_uchar Verification failed at element %ld: 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + log_error("\t1) Shift failure at element %ld: original is 0x%x %s %d (0x%x)\n", i, inptrA[i], tests[test], (int)inptrB[i], inptrB[i]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %d (0x%x).\n", (int)log2(sizeof(cl_uchar)*8), inptrB[i]&shift_mask, inptrB[i]&shift_mask); + } + else if (test == 10 || test == 11) { + log_error("cl_uchar Verification failed at element %ld (%ld): 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, j, inptrA[i], tests[test], inptrB[j], r, outptr[i]); + log_error("\t1) Scalar shift failure at element %ld: original is 0x%x %s %d (0x%x)\n", i, inptrA[i], tests[test], (int)inptrB[j], inptrB[j]); + log_error("\t2) Take the %d LSBs of the shift to get the final shift amount %d (0x%x).\n", (int)log2(sizeof(cl_uchar)*8), inptrB[j]&shift_mask, inptrB[j]&shift_mask); + } else if (test == 13) { + log_error("cl_int Verification failed at element %ld (%ld): (0x%x < 0x%x) ? 0x%x : 0x%x = 0x%x, got 0x%x\n", i, j, inptrA[j], inptrB[j], + inptrA[i], inptrB[i], r, outptr[i]); + } else { + log_error("cl_uchar Verification failed at element %ld: 0x%x %s 0x%x = 0x%x, got 0x%x\n", i, inptrA[i], tests[test], inptrB[i], r, outptr[i]); + } + count++; + if (count >= MAX_ERRORS_TO_PRINT) { + log_error("Further errors ignored.\n"); + return -1; + } + } + } + } + + if (count) return -1; else return 0; +} + +void +init_uchar_data(uint64_t indx, int num_elements, cl_uchar *input_ptr[], MTdata d) +{ + static const cl_uchar specialCaseList[] = { 0, -1, 1, CL_CHAR_MAX, CL_CHAR_MAX + 1, CL_UCHAR_MAX }; + int j; + + // FIXME: we really should just check every char against every char here + + // Set the inputs to a random number + for (j=0; j> 16); + } + + // Init the first few values to test special cases + { + size_t x, y, index = 0; + for( x = 0; x < sizeof( specialCaseList ) / sizeof( specialCaseList[0] ); x++ ) + for( y = 0; y < sizeof( specialCaseList ) / sizeof( specialCaseList[0] ); y++ ) + { + ((cl_uchar *)input_ptr[0])[index] = specialCaseList[x]; + ((cl_uchar *)input_ptr[1])[index++] = specialCaseList[y]; + } + } +} + diff --git a/test_conformance/math_brute_force/CMakeLists.txt b/test_conformance/math_brute_force/CMakeLists.txt new file mode 100644 index 00000000..176b3f66 --- /dev/null +++ b/test_conformance/math_brute_force/CMakeLists.txt @@ -0,0 +1,86 @@ +set(MODULE_NAME BRUTEFORCE) + +set(${MODULE_NAME}_SOURCES + FunctionList.c + Sleep.c + binary.c + binaryOperator.c + Utility.c + binary_i.c + binary_two_results_i.c + i_unary.c + macro_binary.c + macro_unary.c + mad.c + main.c + reference_math.c + ternary.c + unary.c + unary_two_results.c + unary_two_results_i.c + unary_u.c + ../../test_common/harness/rounding_mode.c + ../../test_common/harness/ThreadPool.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/errorHelpers.c +) + + +if (NOT ANDROID) +set_source_files_properties( + FunctionList.c + Sleep.c + binary.c + binaryOperator.c + Utility.c + binary_i.c + binary_two_results_i.c + i_unary.c + macro_binary.c + macro_unary.c + mad.c + main.c reference_math.c + ternary.c unary.c unary_two_results.c + unary_two_results_i.c unary_u.c + COMPILE_FLAGS -msse2 ) +endif(NOT ANDROID) + +set_source_files_properties( + FunctionList.c + Sleep.c + binary.c + binaryOperator.c + Utility.c + binary_i.c + binary_two_results_i.c + i_unary.c + macro_binary.c + macro_unary.c + mad.c + main.c + reference_math.c + ternary.c + unary.c + unary_two_results.c + unary_two_results_i.c unary_u.c + ../../test_common/harness/rounding_mode.c + ../../test_common/harness/ThreadPool.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp + PROPERTIES LANGUAGE CXX) + +if (NOT CMAKE_CL_64 AND NOT MSVC AND NOT ANDROID) +set_source_files_properties( +${MODULE_NAME}_SOURCES + COMPILE_FLAGS -march=i686) +endif (NOT CMAKE_CL_64 AND NOT MSVC AND NOT ANDROID) + +if(CMAKE_COMPILER_IS_GNUCC) +set_source_files_properties( + COMPILE_FLAGS -O0) +endif(CMAKE_COMPILER_IS_GNUCC) + +include(../CMakeCommon.txt) diff --git a/test_conformance/math_brute_force/FunctionList.c b/test_conformance/math_brute_force/FunctionList.c new file mode 100644 index 00000000..027672fb --- /dev/null +++ b/test_conformance/math_brute_force/FunctionList.c @@ -0,0 +1,180 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "FunctionList.h" +#include "reference_math.h" + +#define FTZ_ON 1 +#define FTZ_OFF 0 +#define EXACT 0.0f +#define RELAXED_ON 1 +#define RELAXED_OFF 0 + +#define STRINGIFY( _s) #_s + +#define ENTRY( _name, _ulp, _embedded_ulp, _rmode, _type ) { STRINGIFY(_name), STRINGIFY(_name), {(void*)reference_##_name}, {(void*)reference_##_name##l}, {(void*)reference_##_name}, _ulp, _ulp, _embedded_ulp, INFINITY, _rmode, RELAXED_OFF, _type } +#define ENTRY_EXT( _name, _ulp, _embedded_ulp, _relaxed_ulp, _rmode, _type ) { STRINGIFY(_name), STRINGIFY(_name), {(void*)reference_##_name}, {(void*)reference_##_name##l}, {(void*)reference_##relaxed_##_name}, _ulp, _ulp, _embedded_ulp, _relaxed_ulp, _rmode, RELAXED_ON, _type } +#define HALF_ENTRY( _name, _ulp, _embedded_ulp, _rmode, _type ) { "half_" STRINGIFY(_name), "half_" STRINGIFY(_name), {(void*)reference_##_name}, {NULL}, {NULL}, _ulp, _ulp, _embedded_ulp, INFINITY, _rmode, RELAXED_OFF, _type } +#define OPERATOR_ENTRY(_name, _operator, _ulp, _embedded_ulp, _rmode, _type) { STRINGIFY(_name), _operator, {(void*)reference_##_name}, {(void*)reference_##_name##l}, {NULL}, _ulp, _ulp, _embedded_ulp, INFINITY, _rmode, RELAXED_OFF, _type } + +#if defined( __cplusplus ) + extern "C" { +#endif +extern const vtbl _unary; // float foo( float ) +extern const vtbl _unary_u; // float foo( uint ), double foo( ulong ) +extern const vtbl _i_unary; // int foo( float ) +extern const vtbl _macro_unary; // int foo( float ), returns {0,1} for scalar, { 0, -1 } for vector +extern const vtbl _binary; // float foo( float, float ) +extern const vtbl _binary_nextafter; // float foo( float, float ), special handling for nextafter +extern const vtbl _binary_operator; // float .op. float +extern const vtbl _macro_binary; // int foo( float, float ), returns {0,1} for scalar, { 0, -1 } for vector +extern const vtbl _binary_i; // float foo( float, int ) +extern const vtbl _ternary; // float foo( float, float, float ) +extern const vtbl _unary_two_results; // float foo( float, float * ) +extern const vtbl _unary_two_results_i; // float foo( float, int * ) +extern const vtbl _binary_two_results_i; // float foo( float, float, int * ) +extern const vtbl _mad_tbl; // float mad( float, float, float ) +#if defined( __cplusplus) + } +#endif + +#define unaryF &_unary +#define i_unaryF &_i_unary +#define unaryF_u &_unary_u +#define macro_unaryF &_macro_unary +#define binaryF &_binary +#define binaryF_nextafter &_binary_nextafter +#define binaryOperatorF &_binary_operator +#define binaryF_i &_binary_i +#define macro_binaryF &_macro_binary +#define ternaryF &_ternary +#define unaryF_two_results &_unary_two_results +#define unaryF_two_results_i &_unary_two_results_i +#define binaryF_two_results_i &_binary_two_results_i +#define mad_function &_mad_tbl + + +const Func functionList[] = { + ENTRY( acos, 4.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY( acosh, 4.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY( acospi, 5.0f, 5.0f, FTZ_OFF, unaryF), + ENTRY( asin, 4.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY( asinh, 4.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY( asinpi, 5.0f, 5.0f, FTZ_OFF, unaryF), + ENTRY( atan, 5.0f, 5.0f, FTZ_OFF, unaryF), + ENTRY( atanh, 5.0f, 5.0f, FTZ_OFF, unaryF), + ENTRY( atanpi, 5.0f, 5.0f, FTZ_OFF, unaryF), + ENTRY( atan2, 6.0f, 6.0f, FTZ_OFF, binaryF), + ENTRY( atan2pi, 6.0f, 6.0f, FTZ_OFF, binaryF), + ENTRY( cbrt, 2.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY( ceil, 0.0f, 0.0f, FTZ_OFF, unaryF), + ENTRY( copysign, 0.0f, 0.0f, FTZ_OFF, binaryF), + ENTRY_EXT( cos, 4.0f, 4.0f, 0.00048828125f, FTZ_OFF, unaryF), //relaxed ulp 2^-11 + ENTRY( cosh, 4.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY( cospi, 4.0f, 4.0f, FTZ_OFF, unaryF), +// ENTRY( erfc, 16.0f, 16.0f, FTZ_OFF, unaryF), //disabled for 1.0 due to lack of reference implementation +// ENTRY( erf, 16.0f, 16.0f, FTZ_OFF, unaryF), //disabled for 1.0 due to lack of reference implementation + ENTRY_EXT( exp, 3.0f, 4.0f, 3.0f, FTZ_OFF, unaryF), //relaxed error is actually overwritten in unary.c as it is 3+floor(fabs(2*x)) + ENTRY_EXT( exp2, 3.0f, 4.0f, 3.0f, FTZ_OFF, unaryF), //relaxed error is actually overwritten in unary.c as it is 3+floor(fabs(2*x)) + ENTRY_EXT( exp10, 3.0f, 4.0f, 8192.0f, FTZ_OFF, unaryF), //relaxed error is actually overwritten in unary.c as it is 3+floor(fabs(2*x)) in derived mode, + // in non-derived mode it uses the ulp error for half_exp10. + ENTRY( expm1, 3.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY( fabs, 0.0f, 0.0f, FTZ_OFF, unaryF), + ENTRY( fdim, 0.0f, 0.0f, FTZ_OFF, binaryF), + ENTRY( floor, 0.0f, 0.0f, FTZ_OFF, unaryF), + ENTRY( fma, 0.0f, 0.0f, FTZ_OFF, ternaryF), + ENTRY( fmax, 0.0f, 0.0f, FTZ_OFF, binaryF), + ENTRY( fmin, 0.0f, 0.0f, FTZ_OFF, binaryF), + ENTRY( fmod, 0.0f, 0.0f, FTZ_OFF, binaryF ), + ENTRY( fract, 0.0f, 0.0f, FTZ_OFF, unaryF_two_results), + ENTRY( frexp, 0.0f, 0.0f, FTZ_OFF, unaryF_two_results_i), + ENTRY( hypot, 4.0f, 4.0f, FTZ_OFF, binaryF), + ENTRY( ilogb, 0.0f, 0.0f, FTZ_OFF, i_unaryF), + ENTRY( isequal, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY( isfinite, 0.0f, 0.0f, FTZ_OFF, macro_unaryF), + ENTRY( isgreater, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY( isgreaterequal, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY( isinf, 0.0f, 0.0f, FTZ_OFF, macro_unaryF), + ENTRY( isless, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY( islessequal, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY( islessgreater, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY( isnan, 0.0f, 0.0f, FTZ_OFF, macro_unaryF), + ENTRY( isnormal, 0.0f, 0.0f, FTZ_OFF, macro_unaryF), + ENTRY( isnotequal, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY( isordered, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY( isunordered, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY( ldexp, 0.0f, 0.0f, FTZ_OFF, binaryF_i), + ENTRY( lgamma, INFINITY, INFINITY, FTZ_OFF, unaryF), + ENTRY( lgamma_r, INFINITY, INFINITY, FTZ_OFF, unaryF_two_results_i), + ENTRY_EXT( log, 3.0f, 4.0f, 4.76837158203125e-7f, FTZ_OFF, unaryF), //relaxed ulp 2^-21 + ENTRY_EXT( log2, 3.0f, 4.0f, 4.76837158203125e-7f, FTZ_OFF, unaryF), //relaxed ulp 2^-21 + ENTRY( log10, 3.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY( log1p, 2.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY( logb, 0.0f, 0.0f, FTZ_OFF, unaryF), + ENTRY_EXT( mad, INFINITY, INFINITY, INFINITY, FTZ_OFF, mad_function), //in fast-relaxed-math mode it has to be either exactly rounded fma or exactly rounded a*b+c + ENTRY( maxmag, 0.0f, 0.0f, FTZ_OFF, binaryF ), + ENTRY( minmag, 0.0f, 0.0f, FTZ_OFF, binaryF ), + ENTRY( modf, 0.0f, 0.0f, FTZ_OFF, unaryF_two_results ), + ENTRY( nan, 0.0f, 0.0f, FTZ_OFF, unaryF_u), + ENTRY( nextafter, 0.0f, 0.0f, FTZ_OFF, binaryF_nextafter), + ENTRY_EXT( pow, 16.0f, 16.0f, 8192.0f, FTZ_OFF, binaryF), //in derived mode the ulp error is calculated as exp2(y*log2(x)) and in non-derived it is the same as half_pow + ENTRY( pown, 16.0f, 16.0f, FTZ_OFF, binaryF_i), + ENTRY( powr, 16.0f, 16.0f, FTZ_OFF, binaryF), +// ENTRY( reciprocal, 1.0f, 1.0f, FTZ_OFF, unaryF), + ENTRY( remainder, 0.0f, 0.0f, FTZ_OFF, binaryF), + ENTRY( remquo, 0.0f, 0.0f, FTZ_OFF, binaryF_two_results_i), + ENTRY( rint, 0.0f, 0.0f, FTZ_OFF, unaryF), + ENTRY( rootn, 16.0f, 16.0f, FTZ_OFF, binaryF_i), + ENTRY( round, 0.0f, 0.0f, FTZ_OFF, unaryF), + ENTRY( rsqrt, 2.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY( signbit, 0.0f, 0.0f, FTZ_OFF, macro_unaryF), + ENTRY_EXT( sin, 4.0f, 4.0f, 0.00048828125f, FTZ_OFF, unaryF), //relaxed ulp 2^-11 + ENTRY_EXT( sincos, 4.0f, 4.0f, 0.00048828125f, FTZ_OFF, unaryF_two_results), //relaxed ulp 2^-11 + ENTRY( sinh, 4.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY( sinpi, 4.0f, 4.0f, FTZ_OFF, unaryF), + { "sqrt", "sqrt", {(void*)reference_sqrt}, {(void*)reference_sqrtl}, {NULL}, 3.0f, 0.0f, 4.0f, INFINITY, FTZ_OFF, RELAXED_OFF, unaryF }, + { "sqrt_cr", "sqrt", {(void*)reference_sqrt}, {(void*)reference_sqrtl}, {NULL}, 0.0f, 0.0f, 0.0f, INFINITY, FTZ_OFF, RELAXED_OFF, unaryF }, + ENTRY_EXT( tan, 5.0f, 5.0f, 8192.0f, FTZ_OFF, unaryF), //in derived mode it the ulp error is calculated as sin/cos and in non-derived mode it is the same as half_tan. + ENTRY( tanh, 5.0f, 5.0f, FTZ_OFF, unaryF), + ENTRY( tanpi, 6.0f, 6.0f, FTZ_OFF, unaryF), +// ENTRY( tgamma, 16.0f, 16.0f, FTZ_OFF, unaryF), // Commented this out until we can be sure this requirement is realistic + ENTRY( trunc, 0.0f, 0.0f, FTZ_OFF, unaryF), + + HALF_ENTRY( cos, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY( divide, 8192.0f, 8192.0f, FTZ_ON, binaryF), + HALF_ENTRY( exp, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY( exp2, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY( exp10, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY( log, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY( log2, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY( log10, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY( powr, 8192.0f, 8192.0f, FTZ_ON, binaryF), + HALF_ENTRY( recip, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY( rsqrt, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY( sin, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY( sqrt, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY( tan, 8192.0f, 8192.0f, FTZ_ON, unaryF), + + // basic operations + OPERATOR_ENTRY( add, "+", 0.0f, 0.0f, FTZ_OFF, binaryOperatorF), + OPERATOR_ENTRY( subtract, "-", 0.0f, 0.0f, FTZ_OFF, binaryOperatorF), + { "divide", "/", {(void*)reference_divide}, {(void*)reference_dividel}, {(void*)reference_relaxed_divide}, 2.5f, 0.0f, 3.0f, 2.5f, FTZ_OFF, RELAXED_ON, binaryOperatorF }, + { "divide_cr", "/", {(void*)reference_divide}, {(void*)reference_dividel}, {(void*)reference_relaxed_divide}, 0.0f, 0.0f, 0.0f, 0.f, FTZ_OFF, RELAXED_OFF, binaryOperatorF }, + OPERATOR_ENTRY( multiply, "*", 0.0f, 0.0f, FTZ_OFF, binaryOperatorF), + OPERATOR_ENTRY( assignment, "", 0.0f, 0.0f, FTZ_OFF, unaryF), // A simple copy operation + OPERATOR_ENTRY( not, "!", 0.0f, 0.0f, FTZ_OFF, macro_unaryF), + }; + +const size_t functionListCount = sizeof( functionList ) / sizeof( functionList[0] ); diff --git a/test_conformance/math_brute_force/FunctionList.h b/test_conformance/math_brute_force/FunctionList.h new file mode 100644 index 00000000..346654fb --- /dev/null +++ b/test_conformance/math_brute_force/FunctionList.h @@ -0,0 +1,99 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef FUNCTIONLIST_H +#define FUNCTIONLIST_H + +#include "../../test_common/harness/compat.h" + +#ifndef WIN32 +#include +#endif + +#if defined( __APPLE__ ) + #include +#else + #include +#endif + +#include "../../test_common/harness/mt19937.h" + +typedef union fptr +{ + void *p; + double (*f_f)(double); + double (*f_u)(cl_uint); + int (*i_f)(double); + int (*i_f_f)(float); + float (*f_ff_f)(float, float); + double (*f_ff)(double, double); + int (*i_ff)(double, double); + double (*f_fi)(double, int); + double (*f_fpf)(double, double*); + double (*f_fpI)(double, int*); + double (*f_ffpI)(double, double, int*); + double (*f_fff)(double, double, double ); + float (*f_fma)(float, float, float, int); +}fptr; + +typedef union dptr +{ + void *p; + long double (*f_f)(long double); + long double (*f_u)(cl_ulong); + int (*i_f)(long double); + long double (*f_ff)(long double, long double); + int (*i_ff)(long double, long double); + long double (*f_fi)(long double, int); + long double (*f_fpf)(long double, long double*); + long double (*f_fpI)(long double, int*); + long double (*f_ffpI)(long double, long double, int*); + long double (*f_fff)(long double, long double, long double); +}dptr; + +struct Func; + +typedef struct vtbl +{ + const char *type_name; + int (*TestFunc)( const struct Func *, MTdata ); + int (*DoubleTestFunc)( const struct Func *, MTdata); // may be NULL if function is single precision only +}vtbl; + +typedef struct Func +{ + const char *name; // common name, to be used as an argument in the shell + const char *nameInCode; // name as it appears in the __kernel, usually the same as name, but different for multiplication + fptr func; + dptr dfunc; + fptr rfunc; + float float_ulps; + float double_ulps; + float float_embedded_ulps; + float relaxed_error; + int ftz; + int relaxed; + const ::vtbl *vtbl; +}Func; + + +extern const Func functionList[]; + +extern const size_t functionListCount; + + +#endif + + diff --git a/test_conformance/math_brute_force/Jamfile b/test_conformance/math_brute_force/Jamfile new file mode 100644 index 00000000..39ee8bc8 --- /dev/null +++ b/test_conformance/math_brute_force/Jamfile @@ -0,0 +1,36 @@ +project + : requirements + -/harness//harness /harness//harness + /Runtime//OpenCL.lib +# gcc:-xc++ + msvc:"/TP" + ; + +exe bruteforce + : binary.c + binary_i.c + binaryOperator.c + binary_two_results_i.c + FunctionList.c + i_unary.c + macro_binary.c + macro_unary.c + mad.c + main.c + reference_math.c + Sleep.c + ternary.c + unary.c + unary_two_results.c + unary_two_results_i.c + unary_u.c + Utility.c + /harness//mt19937.c + : windows:/harness//msvc9.c + ; + +install dist + : bruteforce + : debug:$(DIST)/debug/tests/test_conformance/math_brute_force + release:$(DIST)/release/tests/test_conformance/math_brute_force + ; diff --git a/test_conformance/math_brute_force/Makefile b/test_conformance/math_brute_force/Makefile new file mode 100644 index 00000000..3c69e3e2 --- /dev/null +++ b/test_conformance/math_brute_force/Makefile @@ -0,0 +1,33 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +CC = cc +CFLAGS = -g -Wall -Wshorten-64-to-32 $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} +LIBRARIES = -framework OpenCL -framework ApplicationServices -framework IOKit -I/System/Library/Frameworks/OpenCL.framework/Headers ${RC_CFLAGS} ${ATF} + +release: + echo "Build Release" + $(CC) *.c ../../test_common/harness/mt19937.c ../../test_common/harness/rounding_mode.c ../../test_common/harness/ThreadPool.c -Os $(CFLAGS) -o bruteforce $(LIBRARIES) + +debug: + echo "Build Debug" + $(CC) *.c ../../test_common/harness/mt19937.c ../../test_common/harness/rounding_mode.c ../../test_common/harness/ThreadPool.c -O0 $(CFLAGS) -D_DEBUG=1 -o bruteforce_debug $(LIBRARIES) + +test: release + arch -i386 ./bruteforce -c > cpu.log & + arch -i386 ./bruteforce -g > gpu.log & + echo "Testing 32-bit mode in progress. This may take up to 1 day to complete. See cpu.log and gpu.log for results." + +test64: release + arch -x86_64 ./bruteforce -c > cpu64.log & + arch -x86_64 ./bruteforce -g > gpu64.log & + echo "Testing 64-bit mode in progress. This may take up to 1 day to complete. See cpu64.log and gpu64.log for results." + + +clean: + rm -f ./bruteforce_debug + rm -f ./bruteforce + +all: release diff --git a/test_conformance/math_brute_force/README.txt b/test_conformance/math_brute_force/README.txt new file mode 100644 index 00000000..5b289868 --- /dev/null +++ b/test_conformance/math_brute_force/README.txt @@ -0,0 +1,150 @@ +Copyright: (c) 2009-2013 by Apple Inc. All Rights Reserved. + +math_brute_force test Feb 24, 2009 +===================== + +Usage: + + Please run the executable with --help for usage information. + + + +System Requirements: + + This test requires support for correctly rounded single and double precision arithmetic. +The current version also requires a reasonably accurate operating system math library to +be present. The OpenCL implementation must be able to compile kernels online. The test assumes +that the host system stores its floating point data according to the IEEE-754 binary single and +double precision floating point formats. + + +Test Completion Time: + + This test takes a while. Modern desktop systems can usually finish it in 1-3 +days. Engineers doing OpenCL math library software development may find wimpy mode (-w) +a useful screen to quickly look for problems in a new implementation, before committing +to a lengthy test run. Likewise, it is possible to run just a range of tests, or specific +tests. See Usage above. + + +Test Design: + + This test is designed to do a somewhat exhaustive examination of the single +and double precision math library functions in OpenCL, for all vector lengths. Math +library functions are compared against results from a higher precision reference +function to determine correctness. All possible inputs are examined for unary +single precision functions. Other functions are tested against a table of difficult +values, followed by a few billion random values. If an error is found in a function, +the test for that function terminates early, reports an error, and moves on to the +next test, if any. + +The test currently doesn't support half precision math functions covered in section +9 of the OpenCL 1.0 specification, but does cover the half_func functions covered in +section six. It also doesn't test the native_ functions, for which any result +is conformant. + +For the OpenCL 1.0 time frame, the reference library shall be the operating system +math library, as modified by the test itself to conform to the OpenCL specification. +That will help ensure that all devices on a particular operating system are returning +similar results. Going forward to future OpenCL releases, it is planned to gradually +introduce a reference math library directly into the test, so as to reduce inter- +platform variance between OpenCL implementations. + +Generally speaking, this test will consider a result correct if it is one of the following: + + 1) bitwise identical to the output of the reference function, + rounded to the appropriate precision + + 2) within the allowed ulp error tolerance of the infinitely precise + result (as estimated by the reference function) + + 3) If the reference result is a NaN, then any NaN is deemed correct. + + 4) if the devices is running in FTZ mode, then the result is also correct + if the infinitely precise result (as estimated by the reference + function) is subnormal, and the returned result is a zero + + 5) if the devices is running in FTZ mode, then we also calculate the + estimate of the infinitely precise result with the reference function + with subnormal inputs flushed to +- zero. If any of those results + are within the error tolerance of the returned result, then it is + deemed correct + + 6) half_func functions may flush per 4&5 above, even if the device is not + in FTZ mode. + + 7) Functions are allowed to prematurely overflow to infinity, so long as + the estimated infinitely precise result is within the stated ulp + error limit of the maximum finite representable value of appropriate + sign + + 8) Functions are allowed to prematurely underflow (and if in FTZ mode, + have behavior covered by 4&5 above), so long as the estimated + infinitely precise result is within the stated ulp error limit + of the minimum normal representable value of appropriate sign + + 9) Some functions have limited range. Results of inputs outside that range + are considered correct, so long as a result is returned. + + 10) Some functions have infinite error bounds. Results of these function + are considered correct, so long as a result is returned. + + 11) The test currently does not discriminate based on the sign of zero + We anticipate a later test will. + + 12) The test currently does not check to make sure that edge cases called + out in the standard (e.g. pow(1.0, any) = 1.0) are exactly correct. + We anticipate a later test will. + + 13) The test doesn't check IEEE flags or exceptions. See section 7.3 of the + OpenCL standard. + + + +Performance Measurement: + + There is also some optional timing code available, currently turned off by default. +These may be useful for tracking internal performance regressions, but is not required to +be part of the conformance submission. + + +If the test is believed to be in error: + +The above correctness heuristics shall not be construed to be an alternative to the correctness +criteria established by the OpenCL standard. An implementation shall be judged correct +or not on appeal based on whether it is within prescribed error bounds of the infinitely +precise result. (The ulp is defined in section 7.4 of the spec.) If the input value corresponds +to an edge case listed in OpenCL specification sections covering edge case behavior, or +similar sections in the C99 TC2 standard (section F.9 and G.6), the the function shall return +exactly that result, and the sign of a zero result shall be correct. In the event that the test +is found to be faulty, resulting in a spurious failure result, the committee shall make a reasonable +attempt to fix the test. If no practical and timely remedy can be found, then the implementation +shall be granted a waiver. + + +Guidelines for reference function error tolerances: + + Errors are measured in ulps, and stored in a single precision representation. So as +to avoid introducing error into the error measurement due to error in the reference function +itself, the reference function should attempt to deliver 24 bits more precision than the test +function return type. (All functions are currently either required to be correctly rounded or +may have >= 1 ulp of error. This places the 1's bit at the LSB of the result, with 23 bits of +sub-ulp accuracy. One more bit is required to avoid accrual of extra error due to round-to- +nearest behavior. If we start to require sub-ulp precision, then the accuracy requirements +for reference functions increase.) Therefore reference functions for single precision should +have 24+24=48 bits of accuracy, and reference functions for double precision should ideally +have 53+24 = 77 bits of accuracy. + +A double precision system math library function should be sufficient to safely verify a single +precision OpenCL math library function. A long double precision math library function may or +may not be sufficient to verify a double precision OpenCL math library function, depending on +the precision of the long double type. A later version of these tests is expected to replace +long double with a head+tail double double representation that can represent sufficient precision, +on all platforms that support double. + + +Revision history: + + Feb 24, 2009 IRO Created README + Added some reference functions so the test will run on Windows. + diff --git a/test_conformance/math_brute_force/Sleep.c b/test_conformance/math_brute_force/Sleep.c new file mode 100644 index 00000000..4d3b2c64 --- /dev/null +++ b/test_conformance/math_brute_force/Sleep.c @@ -0,0 +1,118 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Sleep.h" +#include "Utility.h" + +#if defined( __APPLE__ ) + #include + #include + + struct + { + io_connect_t connection; + IONotificationPortRef port; + io_object_t iterator; + }sleepInfo; + + void sleepCallback( void * refcon, + io_service_t service, + natural_t messageType, + void * messageArgument ); + + void sleepCallback( void * refcon UNUSED, + io_service_t service UNUSED, + natural_t messageType, + void * messageArgument ) + { + + IOReturn result; + /* + service -- The IOService whose state has changed. + messageType -- A messageType enum, defined by IOKit/IOMessage.h or by the IOService's family. + messageArgument -- An argument for the message, dependent on the messageType. + */ + switch ( messageType ) + { + case kIOMessageSystemWillSleep: + // Handle demand sleep (such as sleep caused by running out of + // batteries, closing the lid of a laptop, or selecting + // sleep from the Apple menu. + IOAllowPowerChange(sleepInfo.connection,(long)messageArgument); + vlog( "Hard sleep occurred.\n" ); + break; + case kIOMessageCanSystemSleep: + // In this case, the computer has been idle for several minutes + // and will sleep soon so you must either allow or cancel + // this notification. Important: if you don’t respond, there will + // be a 30-second timeout before the computer sleeps. + // IOCancelPowerChange(root_port,(long)messageArgument); + result = IOCancelPowerChange(sleepInfo.connection,(long)messageArgument); + if( kIOReturnSuccess != result ) + vlog( "sleep prevention failed. (%d)\n", result); + break; + case kIOMessageSystemHasPoweredOn: + // Handle wakeup. + break; + } + } +#endif + + + + + +void PreventSleep( void ) +{ +#if defined( __APPLE__ ) + vlog( "Disabling sleep... " ); + sleepInfo.iterator = (io_object_t) 0; + sleepInfo.port = NULL; + sleepInfo.connection = IORegisterForSystemPower + ( + &sleepInfo, //void * refcon, + &sleepInfo.port, //IONotificationPortRef * thePortRef, + sleepCallback, //IOServiceInterestCallback callback, + &sleepInfo.iterator //io_object_t * notifier + ); + + if( (io_connect_t) 0 == sleepInfo.connection ) + vlog( "failed.\n" ); + else + vlog( "done.\n" ); + + CFRunLoopAddSource(CFRunLoopGetCurrent(), + IONotificationPortGetRunLoopSource(sleepInfo.port), + kCFRunLoopDefaultMode); +#else + vlog( "*** PreventSleep() is not implemented on this platform.\n" ); +#endif +} + +void ResumeSleep( void ) +{ +#if defined( __APPLE__ ) + IOReturn result = IODeregisterForSystemPower ( &sleepInfo.iterator ); + if( 0 != result ) + vlog( "Got error %d restoring sleep \n", result ); + else + vlog( "Sleep restored.\n" ); +#else + vlog( "*** ResumeSleep() is not implemented on this platform.\n" ); +#endif +} + + + diff --git a/test_conformance/math_brute_force/Sleep.h b/test_conformance/math_brute_force/Sleep.h new file mode 100644 index 00000000..f983a32f --- /dev/null +++ b/test_conformance/math_brute_force/Sleep.h @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef SLEEP_H +#define SLEEP_H + +void PreventSleep( void ); +void ResumeSleep( void ); + +#endif /* SLEEP_H */ + + diff --git a/test_conformance/math_brute_force/Utility.c b/test_conformance/math_brute_force/Utility.c new file mode 100644 index 00000000..3c706fab --- /dev/null +++ b/test_conformance/math_brute_force/Utility.c @@ -0,0 +1,169 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Utility.h" + +#if defined(__PPC__) +// Global varaiable used to hold the FPU control register state. The FPSCR register can not +// be used because not all Power implementations retain or observed the NI (non-IEEE +// mode) bit. +__thread fpu_control_t fpu_control = 0; +#endif + +void MulD(double *rhi, double *rlo, double u, double v) +{ + const double c = 134217729.0; // 1+2^27 + double up, u1, u2, vp, v1, v2; + + up = u*c; + u1 = (u - up) + up; + u2 = u - u1; + + vp = v*c; + v1 = (v - vp) + vp; + v2 = v - v1; + + double rh = u*v; + double rl = (((u1*v1 - rh) + (u1*v2)) + (u2*v1)) + (u2*v2); + + *rhi = rh; + *rlo = rl; +} + +void AddD(double *rhi, double *rlo, double a, double b) +{ + double zhi, zlo; + zhi = a + b; + if(fabs(a) > fabs(b)) { + zlo = zhi - a; + zlo = b - zlo; + } + else { + zlo = zhi - b; + zlo = a - zlo; + } + + *rhi = zhi; + *rlo = zlo; +} + +void MulDD(double *rhi, double *rlo, double xh, double xl, double yh, double yl) +{ + double mh, ml; + double c = 134217729.0; + double up, u1, u2, vp, v1, v2; + + up = xh*c; + u1 = (xh - up) + up; + u2 = xh - u1; + + vp = yh*c; + v1 = (yh - vp) + vp; + v2 = yh - v1; + + mh = xh*yh; + ml = (((u1*v1 - mh) + (u1*v2)) + (u2*v1)) + (u2*v2); + ml += xh*yl + xl*yh; + + *rhi = mh + ml; + *rlo = (mh - (*rhi)) + ml; +} + +void AddDD(double *rhi, double *rlo, double xh, double xl, double yh, double yl) +{ + double r, s; + r = xh + yh; + s = (fabs(xh) > fabs(yh)) ? (xh - r + yh + yl + xl) : (yh - r + xh + xl + yl); + *rhi = r + s; + *rlo = (r - (*rhi)) + s; +} + +void DivideDD(double *chi, double *clo, double a, double b) +{ + *chi = a / b; + double rhi, rlo; + MulD(&rhi, &rlo, *chi, b); + AddDD(&rhi, &rlo, -rhi, -rlo, a, 0.0); + *clo = rhi / b; +} + +// These functions comapre two floats/doubles. Since some platforms may choose to +// flush denormals to zeros before comparison, comparison like a < b may give wrong +// result in "certain cases" where we do need correct compasion result when operands +// are denormals .... these functions comapre floats/doubles using signed integer/long int +// rep. In other cases, when flushing to zeros is fine, these should not be used. +// Also these doesn't check for nans and assume nans are handled separately as special edge case +// by the caller which calls these functions +// return 0 if both are equal, 1 if x > y and -1 if x < y. + +inline +int compareFloats(float x, float y) +{ + int32f_t a, b; + + a.f = x; + b.f = y; + + if( a.i & 0x80000000 ) + a.i = 0x80000000 - a.i; + if( b.i & 0x80000000 ) + b.i = 0x80000000 - b.i; + + if( a.i == b.i ) + return 0; + + return a.i < b.i ? -1 : 1; +} + +inline +int compareDoubles(double x, double y) +{ + int64d_t a, b; + + a.d = x; + b.d = y; + + if( a.l & 0x8000000000000000LL ) + a.l = 0x8000000000000000LL - a.l; + if( b.l & 0x8000000000000000LL ) + b.l = 0x8000000000000000LL - b.l; + + if( a.l == b.l ) + return 0; + + return a.l < b.l ? -1 : 1; +} + +void logFunctionInfo(const char *fname, unsigned int float_size, unsigned int isFastRelaxed) +{ + char const *fpSizeStr = NULL; + char const *fpFastRelaxedStr = ""; + switch (float_size) { + case sizeof(cl_double): + fpSizeStr = "fp64"; + break; + case sizeof(cl_float): + fpSizeStr = "fp32"; + break; + case sizeof(cl_half): + fpSizeStr = "fp16"; + break; + } + if (isFastRelaxed) { + fpFastRelaxedStr = "rlx"; + } + vlog("%15s %4s %4s",fname, fpSizeStr, fpFastRelaxedStr); +} + diff --git a/test_conformance/math_brute_force/Utility.h b/test_conformance/math_brute_force/Utility.h new file mode 100644 index 00000000..13651037 --- /dev/null +++ b/test_conformance/math_brute_force/Utility.h @@ -0,0 +1,280 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef UTILITY_H +#define UTILITY_H + +#include "../../test_common/harness/compat.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif +#include +#include "../../test_common/harness/rounding_mode.h" +#include "../../test_common/harness/fpcontrol.h" + +#if defined( _WIN32) && defined (_MSC_VER) +#include "../../test_common/harness/testHarness.h" +#endif + +#include "../../test_common/harness/ThreadPool.h" +#define BUFFER_SIZE (1024*1024*2) + +#if defined( __GNUC__ ) + #define UNUSED __attribute__ ((unused)) +#else + #define UNUSED +#endif + +extern int gWimpyBufferSize; +extern int gWimpyReductionFactor; + +#define VECTOR_SIZE_COUNT 6 +extern const char *sizeNames[VECTOR_SIZE_COUNT]; +extern const int sizeValues[VECTOR_SIZE_COUNT]; + +extern cl_device_type gDeviceType; +extern cl_device_id gDevice; +extern cl_context gContext; +extern cl_command_queue gQueue; +extern void *gIn; +extern void *gIn2; +extern void *gIn3; +extern void *gOut_Ref; +extern void *gOut_Ref2; +extern void *gOut[VECTOR_SIZE_COUNT]; +extern void *gOut2[VECTOR_SIZE_COUNT]; +extern cl_mem gInBuffer; +extern cl_mem gInBuffer2; +extern cl_mem gInBuffer3; +extern cl_mem gOutBuffer[VECTOR_SIZE_COUNT]; +extern cl_mem gOutBuffer2[VECTOR_SIZE_COUNT]; +extern uint32_t gComputeDevices; +extern uint32_t gSimdSize; +extern int gSkipCorrectnessTesting; +extern int gMeasureTimes; +extern int gReportAverageTimes; +extern int gForceFTZ; +extern volatile int gTestFastRelaxed; +extern int gFastRelaxedDerived; +extern int gWimpyMode; +extern int gHasDouble; +extern int gIsInRTZMode; +extern int gInfNanSupport; +extern int gIsEmbedded; +extern int gVerboseBruteForce; +extern uint32_t gMaxVectorSizeIndex; +extern uint32_t gMinVectorSizeIndex; +extern uint32_t gDeviceFrequency; +extern cl_device_fp_config gFloatCapabilities; +extern cl_device_fp_config gDoubleCapabilities; + +#define LOWER_IS_BETTER 0 +#define HIGHER_IS_BETTER 1 + +#if USE_ATF + + #include + #define test_start() ATFTestStart() + #define test_finish() ATFTestFinish() + #define vlog( ... ) ATFLogInfo(__VA_ARGS__) + #define vlog_error( ... ) ATFLogError(__VA_ARGS__) + #define vlog_perf( _number, _higherIsBetter, _units, _nameFmt, ... ) ATFLogPerformanceNumber(_number, _higherIsBetter, _units, _nameFmt, __VA_ARGS__ ) + +#else + #include "../../test_common/harness/errorHelpers.h" +#endif + +#if defined (_MSC_VER ) + //Deal with missing scalbn on windows + #define scalbnf( _a, _i ) ldexpf( _a, _i ) + #define scalbn( _a, _i ) ldexp( _a, _i ) + #define scalbnl( _a, _i ) ldexpl( _a, _i ) +#endif + +#ifdef __cplusplus +extern "C" { +#endif +float Abs_Error( float test, double reference ); +float Ulp_Error( float test, double reference ); +//float Ulp_Error_Half( float test, double reference ); +float Ulp_Error_Double( double test, long double reference ); +#ifdef __cplusplus +} //extern "C" +#endif + +uint64_t GetTime( void ); +double SubtractTime( uint64_t endTime, uint64_t startTime ); +int MakeKernel( const char **c, cl_uint count, const char *name, cl_kernel *k, cl_program *p ); +int MakeKernels( const char **c, cl_uint count, const char *name, cl_uint kernel_count, cl_kernel *k, cl_program *p ); + +// used to convert a bucket of bits into a search pattern through double +static inline double DoubleFromUInt32( uint32_t bits ); +static inline double DoubleFromUInt32( uint32_t bits ) +{ + union{ uint64_t u; double d;} u; + + // split 0x89abcdef to 0x89abc00000000def + u.u = bits & 0xfffU; + u.u |= (uint64_t) (bits & ~0xfffU) << 32; + + // sign extend the leading bit of def segment as sign bit so that the middle region consists of either all 1s or 0s + u.u -= (bits & 0x800U) << 1; + + // return result + return u.d; +} + +void _LogBuildError( cl_program p, int line, const char *file ); +#define LogBuildError( program ) _LogBuildError( program, __LINE__, __FILE__ ) + +#define PERF_LOOP_COUNT 100 + +// Note: though this takes a double, this is for use with single precision tests +static inline int IsFloatSubnormal( double x ) +{ +#if 2 == FLT_RADIX + // Do this in integer to avoid problems with FTZ behavior + union{ float d; uint32_t u;}u; + u.d = fabsf((float)x); + return (u.u-1) < 0x007fffffU; +#else + // rely on floating point hardware for non-radix2 non-IEEE-754 hardware -- will fail if you flush subnormals to zero + return fabs(x) < (double) FLT_MIN && x != 0.0; +#endif +} + + +static inline int IsDoubleSubnormal( long double x ) +{ +#if 2 == FLT_RADIX + // Do this in integer to avoid problems with FTZ behavior + union{ double d; uint64_t u;}u; + u.d = fabs((double) x); + return (u.u-1) < 0x000fffffffffffffULL; +#else + // rely on floating point hardware for non-radix2 non-IEEE-754 hardware -- will fail if you flush subnormals to zero + return fabs(x) < (double) DBL_MIN && x != 0.0; +#endif +} + +//The spec is fairly clear that we may enforce a hard cutoff to prevent premature flushing to zero. +// However, to avoid conflict for 1.0, we are letting results at TYPE_MIN + ulp_limit to be flushed to zero. +static inline int IsFloatResultSubnormal( double x, float ulps ) +{ + x = fabs(x) - MAKE_HEX_DOUBLE( 0x1.0p-149, 0x1, -149) * (double) ulps; + return x < MAKE_HEX_DOUBLE( 0x1.0p-126, 0x1, -126 ); +} + +static inline int IsFloatResultSubnormalAbsError( double x , float abs_err) +{ + x = x - abs_err; + return x < MAKE_HEX_DOUBLE( 0x1.0p-126, 0x1, -126 ); +} + +static inline int IsDoubleResultSubnormal( long double x, float ulps ) +{ + x = fabsl(x) - MAKE_HEX_LONG( 0x1.0p-1074, 0x1, -1074) * (long double) ulps; + return x < MAKE_HEX_LONG( 0x1.0p-1022, 0x1, -1022 ); +} + +static inline int IsFloatInfinity(double x) +{ + union { cl_float d; cl_uint u; } u; + u.d = (cl_float) x; + return ((u.u & 0x7fffffffU) == 0x7F800000U); +} + +static inline int IsFloatMaxFloat(double x) +{ + union { cl_float d; cl_uint u; } u; + u.d = (cl_float) x; + return ((u.u & 0x7fffffffU) == 0x7F7FFFFFU); +} + +static inline int IsFloatNaN(double x) +{ + union { cl_float d; cl_uint u; } u; + u.d = (cl_float) x; + return ((u.u & 0x7fffffffU) > 0x7F800000U); +} + +extern cl_uint RoundUpToNextPowerOfTwo( cl_uint x ); + +// Windows (since long double got deprecated) sets the x87 to 53-bit precision +// (that's x87 default state). This causes problems with the tests that +// convert long and ulong to float and double or otherwise deal with values +// that need more precision than 53-bit. So, set the x87 to 64-bit precision. +static inline void Force64BitFPUPrecision(void) +{ +#if __MINGW32__ + // The usual method is to use _controlfp as follows: + // #include + // _controlfp(_PC_64, _MCW_PC); + // + // _controlfp is available on MinGW32 but not on MinGW64. Instead of having + // divergent code just use inline assembly which works for both. + unsigned short int orig_cw = 0; + unsigned short int new_cw = 0; + __asm__ __volatile__ ("fstcw %0":"=m" (orig_cw)); + new_cw = orig_cw | 0x0300; // set precision to 64-bit + __asm__ __volatile__ ("fldcw %0"::"m" (new_cw)); +#elif defined( _WIN32 ) && defined( __INTEL_COMPILER ) + // Unfortunately, usual method (`_controlfp( _PC_64, _MCW_PC );') does *not* work on win.x64: + // > On the x64 architecture, changing the floating point precision is not supported. + // (Taken from http://msdn.microsoft.com/en-us/library/e9b52ceh%28v=vs.100%29.aspx) + int cw; + __asm { fnstcw cw }; // Get current value of FPU control word. + cw = cw & 0xfffffcff | ( 3 << 8 ); // Set Precision Control to Double Extended Precision. + __asm { fldcw cw }; // Set new value of FPU control word. +#else + /* Implement for other platforms if needed */ +#endif +} + +#ifdef __cplusplus +extern "C" +#else +extern +#endif +void memset_pattern4(void *dest, const void *src_pattern, size_t bytes ); + +typedef union +{ + int32_t i; + float f; +}int32f_t; + +typedef union +{ + int64_t l; + double d; +}int64d_t; + +void MulD(double *rhi, double *rlo, double u, double v); +void AddD(double *rhi, double *rlo, double a, double b); +void MulDD(double *rhi, double *rlo, double xh, double xl, double yh, double yl); +void AddDD(double *rhi, double *rlo, double xh, double xl, double yh, double yl); +void DivideDD(double *chi, double *clo, double a, double b); +int compareFloats(float x, float y); +int compareDoubles(double x, double y); + +void logFunctionInfo(const char *fname, unsigned int float_size, unsigned int isFastRelaxed); + +#endif /* UTILITY_H */ + + diff --git a/test_conformance/math_brute_force/binary.c b/test_conformance/math_brute_force/binary.c new file mode 100644 index 00000000..5800aaf5 --- /dev/null +++ b/test_conformance/math_brute_force/binary.c @@ -0,0 +1,1537 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Utility.h" + +#include +#include "FunctionList.h" + +int TestFunc_Float_Float_Float(const Func *f, MTdata); +int TestFunc_Double_Double_Double(const Func *f, MTdata); +int TestFunc_Float_Float_Float_nextafter(const Func *f, MTdata); +int TestFunc_Double_Double_Double_nextafter(const Func *f, MTdata); +int TestFunc_Float_Float_Float_common(const Func *f, MTdata, int isNextafter); +int TestFunc_Double_Double_Double_common(const Func *f, MTdata, int isNextafter); + +const float twoToMinus126 = MAKE_HEX_FLOAT(0x1p-126f, 1, -126); +const double twoToMinus1022 = MAKE_HEX_DOUBLE(0x1p-1022, 1, -1022); + +#if defined( __cplusplus ) + extern "C" +#endif +const vtbl _binary = { "binary", TestFunc_Float_Float_Float, TestFunc_Double_Double_Double }; + +#if defined( __cplusplus ) + extern "C" +#endif +const vtbl _binary_nextafter = { "binary_nextafter", TestFunc_Float_Float_Float_nextafter, TestFunc_Double_Double_Double_nextafter }; + +static int BuildKernel( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ); + +static int BuildKernel( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global float", sizeNames[vectorSize], "* out, __global float", sizeNames[vectorSize], "* in1, __global float", sizeNames[vectorSize], "* in2 )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in1[i], in2[i] );\n" + "}\n" + }; + + const char *c3[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global float* out, __global float* in, __global float* in2)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " float3 f0 = vload3( 0, in + 3 * i );\n" + " float3 f1 = vload3( 0, in2 + 3 * i );\n" + " f0 = ", name, "( f0, f1 );\n" + " vstore3( f0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " float3 f0, f1;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (float3)( in[3*i], NAN, NAN ); \n" + " f1 = (float3)( in2[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " f0 = (float3)( in[3*i], in[3*i+1], NAN ); \n" + " f1 = (float3)( in2[3*i], in2[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " f0 = ", name, "( f0, f1 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = f0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = f0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernels(kern, (cl_uint) kernSize, testName, kernel_count, k, p); +} + +static int BuildKernelDouble( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double", sizeNames[vectorSize], "* out, __global double", sizeNames[vectorSize], "* in1, __global double", sizeNames[vectorSize], "* in2 )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in1[i], in2[i] );\n" + "}\n" + }; + + const char *c3[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double* out, __global double* in, __global double* in2)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " double3 d0 = vload3( 0, in + 3 * i );\n" + " double3 d1 = vload3( 0, in2 + 3 * i );\n" + " d0 = ", name, "( d0, d1 );\n" + " vstore3( d0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " double3 d0, d1;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " d0 = (double3)( in[3*i], NAN, NAN ); \n" + " d1 = (double3)( in2[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " d0 = (double3)( in[3*i], in[3*i+1], NAN ); \n" + " d1 = (double3)( in2[3*i], in2[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " d0 = ", name, "( d0, d1 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = d0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = d0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernels(kern, (cl_uint) kernSize, testName, kernel_count, k, p); +} + +// A table of more difficult cases to get right +static const float specialValuesFloat[] = { + -NAN, -INFINITY, -FLT_MAX, MAKE_HEX_FLOAT(-0x1.000002p64f, -0x1000002L, 40), MAKE_HEX_FLOAT(-0x1.0p64f, -0x1L, 64), MAKE_HEX_FLOAT(-0x1.fffffep63f, -0x1fffffeL, 39), MAKE_HEX_FLOAT(-0x1.000002p63f, -0x1000002L, 39), MAKE_HEX_FLOAT(-0x1.0p63f, -0x1L, 63), MAKE_HEX_FLOAT(-0x1.fffffep62f, -0x1fffffeL, 38), + MAKE_HEX_FLOAT(-0x1.000002p32f, -0x1000002L, 8), MAKE_HEX_FLOAT(-0x1.0p32f, -0x1L, 32), MAKE_HEX_FLOAT(-0x1.fffffep31f, -0x1fffffeL, 7), MAKE_HEX_FLOAT(-0x1.000002p31f, -0x1000002L, 7), MAKE_HEX_FLOAT(-0x1.0p31f, -0x1L, 31), MAKE_HEX_FLOAT(-0x1.fffffep30f, -0x1fffffeL, 6), -1000.f, -100.f, -4.0f, -3.5f, + -3.0f, MAKE_HEX_FLOAT(-0x1.800002p1f, -0x1800002L, -23), -2.5f, MAKE_HEX_FLOAT(-0x1.7ffffep1f, -0x17ffffeL, -23), -2.0f, MAKE_HEX_FLOAT(-0x1.800002p0f, -0x1800002L, -24), -1.5f, MAKE_HEX_FLOAT(-0x1.7ffffep0f, -0x17ffffeL, -24),MAKE_HEX_FLOAT(-0x1.000002p0f, -0x1000002L, -24), -1.0f, MAKE_HEX_FLOAT(-0x1.fffffep-1f, -0x1fffffeL, -25), + MAKE_HEX_FLOAT(-0x1.000002p-1f, -0x1000002L, -25), -0.5f, MAKE_HEX_FLOAT(-0x1.fffffep-2f, -0x1fffffeL, -26), MAKE_HEX_FLOAT(-0x1.000002p-2f, -0x1000002L, -26), -0.25f, MAKE_HEX_FLOAT(-0x1.fffffep-3f, -0x1fffffeL, -27), + MAKE_HEX_FLOAT(-0x1.000002p-126f, -0x1000002L, -150), -FLT_MIN, MAKE_HEX_FLOAT(-0x0.fffffep-126f, -0x0fffffeL, -150), MAKE_HEX_FLOAT(-0x0.000ffep-126f, -0x0000ffeL, -150), MAKE_HEX_FLOAT(-0x0.0000fep-126f, -0x00000feL, -150), MAKE_HEX_FLOAT(-0x0.00000ep-126f, -0x000000eL, -150), MAKE_HEX_FLOAT(-0x0.00000cp-126f, -0x000000cL, -150), MAKE_HEX_FLOAT(-0x0.00000ap-126f, -0x000000aL, -150), + MAKE_HEX_FLOAT(-0x0.000008p-126f, -0x0000008L, -150), MAKE_HEX_FLOAT(-0x0.000006p-126f, -0x0000006L, -150), MAKE_HEX_FLOAT(-0x0.000004p-126f, -0x0000004L, -150), MAKE_HEX_FLOAT(-0x0.000002p-126f, -0x0000002L, -150), -0.0f, + + +NAN, +INFINITY, +FLT_MAX, MAKE_HEX_FLOAT(+0x1.000002p64f, +0x1000002L, 40), MAKE_HEX_FLOAT(+0x1.0p64f, +0x1L, 64), MAKE_HEX_FLOAT(+0x1.fffffep63f, +0x1fffffeL, 39), MAKE_HEX_FLOAT(+0x1.000002p63f, +0x1000002L, 39), MAKE_HEX_FLOAT(+0x1.0p63f, +0x1L, 63), MAKE_HEX_FLOAT(+0x1.fffffep62f, +0x1fffffeL, 38), + MAKE_HEX_FLOAT(+0x1.000002p32f, +0x1000002L, 8), MAKE_HEX_FLOAT(+0x1.0p32f, +0x1L, 32), MAKE_HEX_FLOAT(+0x1.fffffep31f, +0x1fffffeL, 7), MAKE_HEX_FLOAT(+0x1.000002p31f, +0x1000002L, 7), MAKE_HEX_FLOAT(+0x1.0p31f, +0x1L, 31), MAKE_HEX_FLOAT(+0x1.fffffep30f, +0x1fffffeL, 6), +1000.f, +100.f, +4.0f, +3.5f, + +3.0f, MAKE_HEX_FLOAT(+0x1.800002p1f, +0x1800002L, -23), 2.5f, MAKE_HEX_FLOAT(+0x1.7ffffep1f, +0x17ffffeL, -23),+2.0f, MAKE_HEX_FLOAT(+0x1.800002p0f, +0x1800002L, -24), 1.5f, MAKE_HEX_FLOAT(+0x1.7ffffep0f, +0x17ffffeL, -24), MAKE_HEX_FLOAT(+0x1.000002p0f, +0x1000002L, -24), +1.0f, MAKE_HEX_FLOAT(+0x1.fffffep-1f, +0x1fffffeL, -25), + MAKE_HEX_FLOAT(+0x1.000002p-1f, +0x1000002L, -25), +0.5f, MAKE_HEX_FLOAT(+0x1.fffffep-2f, +0x1fffffeL, -26), MAKE_HEX_FLOAT(+0x1.000002p-2f, +0x1000002L, -26), +0.25f, MAKE_HEX_FLOAT(+0x1.fffffep-3f, +0x1fffffeL, -27), + MAKE_HEX_FLOAT(0x1.000002p-126f, 0x1000002L, -150), +FLT_MIN, MAKE_HEX_FLOAT(+0x0.fffffep-126f, +0x0fffffeL, -150), MAKE_HEX_FLOAT(+0x0.000ffep-126f, +0x0000ffeL, -150), MAKE_HEX_FLOAT(+0x0.0000fep-126f, +0x00000feL, -150), MAKE_HEX_FLOAT(+0x0.00000ep-126f, +0x000000eL, -150), MAKE_HEX_FLOAT(+0x0.00000cp-126f, +0x000000cL, -150), MAKE_HEX_FLOAT(+0x0.00000ap-126f, +0x000000aL, -150), + MAKE_HEX_FLOAT(+0x0.000008p-126f, +0x0000008L, -150), MAKE_HEX_FLOAT(+0x0.000006p-126f, +0x0000006L, -150), MAKE_HEX_FLOAT(+0x0.000004p-126f, +0x0000004L, -150), MAKE_HEX_FLOAT(+0x0.000002p-126f, +0x0000002L, -150), +0.0f +}; + +static size_t specialValuesFloatCount = sizeof( specialValuesFloat ) / sizeof( specialValuesFloat[0] ); + +typedef struct BuildKernelInfo +{ + cl_uint offset; // the first vector size to build + cl_uint kernel_count; + cl_kernel **kernels; + cl_program *programs; + const char *nameInCode; +}BuildKernelInfo; + +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernel( info->nameInCode, i, info->kernel_count, info->kernels[i], info->programs + i ); +} + +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernelDouble( info->nameInCode, i, info->kernel_count, info->kernels[i], info->programs + i ); +} + +//Thread specific data for a worker thread +typedef struct ThreadInfo +{ + cl_mem inBuf; // input buffer for the thread + cl_mem inBuf2; // input buffer for the thread + cl_mem outBuf[ VECTOR_SIZE_COUNT ]; // output buffers for the thread + float maxError; // max error value. Init to 0. + double maxErrorValue; // position of the max error value (param 1). Init to 0. + double maxErrorValue2; // position of the max error value (param 2). Init to 0. + MTdata d; + cl_command_queue tQueue; // per thread command queue to improve performance +}ThreadInfo; + +typedef struct TestInfo +{ + size_t subBufferSize; // Size of the sub-buffer in elements + const Func *f; // A pointer to the function info + cl_program programs[ VECTOR_SIZE_COUNT ]; // programs for various vector sizes + cl_kernel *k[VECTOR_SIZE_COUNT ]; // arrays of thread-specific kernels for each worker thread: k[vector_size][thread_id] + ThreadInfo *tinfo; // An array of thread specific information for each worker thread + cl_uint threadCount; // Number of worker threads + cl_uint step; // step between each chunk and the next. + cl_uint scale; // stride between individual test values + float ulps; // max_allowed ulps + int ftz; // non-zero if running in flush to zero mode + + int isFDim; + int skipNanInf; + int isNextafter; +}TestInfo; + +static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *p ); + +int TestFunc_Float_Float_Float_common(const Func *f, MTdata d, int isNextafter) +{ + TestInfo test_info; + cl_int error; + size_t i, j; + float maxError = 0.0f; + double maxErrorVal = 0.0; + double maxErrorVal2 = 0.0; + int skipTestingRelaxed = 0; + + logFunctionInfo(f->name,sizeof(cl_float),gTestFastRelaxed); + + // Init test_info + memset( &test_info, 0, sizeof( test_info ) ); + test_info.threadCount = GetThreadCount(); + test_info.subBufferSize = BUFFER_SIZE / (sizeof( cl_float) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = 1; + + if (gWimpyMode){ + test_info.subBufferSize = gWimpyBufferSize / (sizeof( cl_float) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = (cl_uint) sizeof(cl_float) * 2 * gWimpyReductionFactor; + } + test_info.step = (cl_uint) test_info.subBufferSize * test_info.scale; + test_info.f = f; + test_info.ulps = gIsEmbedded ? f->float_embedded_ulps : f->float_ulps; + test_info.ftz = f->ftz || gForceFTZ || 0 == (CL_FP_DENORM & gFloatCapabilities); + + test_info.isFDim = 0 == strcmp( "fdim", f->nameInCode ); + test_info.skipNanInf = test_info.isFDim && ! gInfNanSupport; + test_info.isNextafter = isNextafter; + // cl_kernels aren't thread safe, so we make one for each vector size for every thread + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + size_t array_size = test_info.threadCount * sizeof( cl_kernel ); + test_info.k[i] = (cl_kernel*)malloc( array_size ); + if( NULL == test_info.k[i] ) + { + vlog_error( "Error: Unable to allocate storage for kernels!\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.k[i], 0, array_size ); + } + test_info.tinfo = (ThreadInfo*)malloc( test_info.threadCount * sizeof(*test_info.tinfo) ); + if( NULL == test_info.tinfo ) + { + vlog_error( "Error: Unable to allocate storage for thread specific data.\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.tinfo, 0, test_info.threadCount * sizeof(*test_info.tinfo) ); + for( i = 0; i < test_info.threadCount; i++ ) + { + cl_buffer_region region = { i * test_info.subBufferSize * sizeof( cl_float), test_info.subBufferSize * sizeof( cl_float) }; + test_info.tinfo[i].inBuf = clCreateSubBuffer( gInBuffer, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + test_info.tinfo[i].inBuf2 = clCreateSubBuffer( gInBuffer2, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf2 ) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer2 for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + test_info.tinfo[i].outBuf[j] = clCreateSubBuffer( gOutBuffer[j], CL_MEM_WRITE_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].outBuf[j] ) + { + vlog_error( "Error: Unable to create sub-buffer of gOutBuffer[%d] for region {%zd, %zd}\n", (int) j, region.origin, region.size ); + goto exit; + } + } + test_info.tinfo[i].tQueue = clCreateCommandQueueWithProperties(gContext, gDevice, 0, &error); + if( NULL == test_info.tinfo[i].tQueue || error ) + { + vlog_error( "clCreateCommandQueue failed. (%d)\n", error ); + goto exit; + } + + test_info.tinfo[i].d = init_genrand(genrand_int32(d)); + } + + // Init the kernels + { + BuildKernelInfo build_info = { gMinVectorSizeIndex, test_info.threadCount, test_info.k, test_info.programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_FloatFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + goto exit; + } + + // Run the kernels + if( !gSkipCorrectnessTesting ) + { + error = ThreadPool_Do( TestFloat, (cl_uint) ((1ULL<<32) / test_info.step), &test_info ); + + // Accumulate the arithmetic errors + for( i = 0; i < test_info.threadCount; i++ ) + { + if( test_info.tinfo[i].maxError > maxError ) + { + maxError = test_info.tinfo[i].maxError; + maxErrorVal = test_info.tinfo[i].maxErrorValue; + maxErrorVal2 = test_info.tinfo[i].maxErrorValue2; + } + } + + if( error ) + goto exit; + + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + + if( gMeasureTimes ) + { + //Init input arrays + uint32_t *p = (uint32_t *)gIn; + uint32_t *p2 = (uint32_t *)gIn2; + for( j = 0; j < BUFFER_SIZE / sizeof( float ); j++ ) + { + p[j] = (genrand_int32(d) & ~0x40000000) | 0x20000000; + p2[j] = 0x3fc00000; + } + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, BUFFER_SIZE, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, BUFFER_SIZE, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_float ) * sizeValues[j]; + size_t localCount = (BUFFER_SIZE + vectorSize - 1) / vectorSize; // BUFFER_SIZE / vectorSize rounded up + if( ( error = clSetKernelArg( test_info.k[j][0], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(test_info.programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( i = 0; i < PERF_LOOP_COUNT; i++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, test_info.k[j][0], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (BUFFER_SIZE / sizeof( float ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sf%s", f->name, sizeNames[j] ); + } + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t%8.2f @ {%a, %a}", maxError, maxErrorVal, maxErrorVal2 ); + vlog( "\n" ); + + +exit: + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + clReleaseProgram(test_info.programs[i]); + if( test_info.k[i] ) + { + for( j = 0; j < test_info.threadCount; j++ ) + clReleaseKernel(test_info.k[i][j]); + + free( test_info.k[i] ); + } + } + if( test_info.tinfo ) + { + for( i = 0; i < test_info.threadCount; i++ ) + { + free_mtdata( test_info.tinfo[i].d ); + clReleaseMemObject(test_info.tinfo[i].inBuf); + clReleaseMemObject(test_info.tinfo[i].inBuf2); + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + clReleaseMemObject(test_info.tinfo[i].outBuf[j]); + clReleaseCommandQueue(test_info.tinfo[i].tQueue); + } + + free( test_info.tinfo ); + } + + return error; +} + +static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *data ) +{ + const TestInfo *job = (const TestInfo *) data; + size_t buffer_elements = job->subBufferSize; + size_t buffer_size = buffer_elements * sizeof( cl_float ); + cl_uint base = job_id * (cl_uint) job->step; + ThreadInfo *tinfo = job->tinfo + thread_id; + float ulps = job->ulps; + fptr func = job->f->func; + int ftz = job->ftz; + MTdata d = tinfo->d; + cl_uint j, k; + cl_int error; + cl_uchar *overflow = (cl_uchar*)malloc(buffer_size); + const char *name = job->f->name; + int isFDim = job->isFDim; + int skipNanInf = job->skipNanInf; + int isNextafter = job->isNextafter; + cl_uint *t = 0; + float *r=0,*s=0,*s2=0; + cl_int copysign_test = 0; + RoundingMode oldRoundMode; + int skipVerification = 0; + + if(gTestFastRelaxed) + { + if (strcmp(name,"pow")==0 && gFastRelaxedDerived) + { + func = job->f->rfunc; + ulps = INFINITY; + skipVerification = 1; + }else + { + func = job->f->rfunc; + ulps = job->f->relaxed_error; + } + } + + // start the map of the output arrays + cl_event e[ VECTOR_SIZE_COUNT ]; + cl_uint *out[ VECTOR_SIZE_COUNT ]; + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_uint*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_WRITE, 0, buffer_size, 0, NULL, e + j, &error); + if( error || NULL == out[j]) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush failed\n" ); + + //Init input array + cl_uint *p = (cl_uint *)gIn + thread_id * buffer_elements; + cl_uint *p2 = (cl_uint *)gIn2 + thread_id * buffer_elements; + j = 0; + + int totalSpecialValueCount = specialValuesFloatCount * specialValuesFloatCount; + int indx = (totalSpecialValueCount - 1) / buffer_elements; + + if (job_id <= (cl_uint)indx) + { // test edge cases + float *fp = (float *)p; + float *fp2 = (float *)p2; + uint32_t x, y; + + x = (job_id * buffer_elements) % specialValuesFloatCount; + y = (job_id * buffer_elements) / specialValuesFloatCount; + + for( ; j < buffer_elements; j++ ) + { + fp[j] = specialValuesFloat[x]; + fp2[j] = specialValuesFloat[y]; + if( ++x >= specialValuesFloatCount ) + { + x = 0; + y++; + if( y >= specialValuesFloatCount ) + break; + } + } + } + + //Init any remaining values. + for( ; j < buffer_elements; j++ ) + { + p[j] = genrand_int32(d); + p2[j] = genrand_int32(d); + } + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf, CL_FALSE, 0, buffer_size, p, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf2, CL_FALSE, 0, buffer_size, p2, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + //Wait for the map to finish + if( (error = clWaitForEvents(1, e + j) )) + { + vlog_error( "Error: clWaitForEvents failed! err: %d\n", error ); + goto exit; + } + if( (error = clReleaseEvent( e[j] ) )) + { + vlog_error( "Error: clReleaseEvent failed! err: %d\n", error ); + goto exit; + } + + // Fill the result buffer with garbage, so that old results don't carry over + uint32_t pattern = 0xffffdead; + memset_pattern4(out[j], &pattern, buffer_size); + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueMapBuffer failed! err: %d\n", error ); + goto exit; + } + + // run the kernel + size_t vectorCount = (buffer_elements + sizeValues[j] - 1) / sizeValues[j]; + cl_kernel kernel = job->k[j][thread_id]; //each worker thread has its own copy of the cl_kernel + cl_program program = job->programs[j]; + + if( ( error = clSetKernelArg( kernel, 0, sizeof( tinfo->outBuf[j] ), &tinfo->outBuf[j] ))){ LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 1, sizeof( tinfo->inBuf ), &tinfo->inBuf ) )) { LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 2, sizeof( tinfo->inBuf2 ), &tinfo->inBuf2 ) )) { LogBuildError(program); return error; } + + if( (error = clEnqueueNDRangeKernel(tinfo->tQueue, kernel, 1, NULL, &vectorCount, NULL, 0, NULL, NULL))) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 2 failed\n" ); + + if( gSkipCorrectnessTesting ) + { + if( (error = clFinish(tinfo->tQueue)) ) + { + vlog_error( "Error: clFinish failed! err: %d\n", error ); + goto exit; + } + free(overflow); + return CL_SUCCESS; + } + + FPU_mode_type oldMode; + oldRoundMode = kRoundToNearestEven; + if( isFDim ) + { + //Calculate the correctly rounded reference result + memset( &oldMode, 0, sizeof( oldMode ) ); + if( ftz ) + ForceFTZ( &oldMode ); + + // Set the rounding mode to match the device + if (gIsInRTZMode) + oldRoundMode = set_round(kRoundTowardZero, kfloat); + } + + if(!strcmp(name, "copysign")) + copysign_test = 1; + +#define ref_func(s, s2) (copysign_test ? func.f_ff_f( s, s2 ) : func.f_ff( s, s2 )) + + //Calculate the correctly rounded reference result + r = (float *)gOut_Ref + thread_id * buffer_elements; + s = (float *)gIn + thread_id * buffer_elements; + s2 = (float *)gIn2 + thread_id * buffer_elements; + if( skipNanInf ) + { + for( j = 0; j < buffer_elements; j++ ) + { + feclearexcept(FE_OVERFLOW); + r[j] = (float) ref_func( s[j], s2[j] ); + overflow[j] = FE_OVERFLOW == (FE_OVERFLOW & fetestexcept(FE_OVERFLOW)); + } + } + else + { + for( j = 0; j < buffer_elements; j++ ) + r[j] = (float) ref_func( s[j], s2[j] ); + } + + if( isFDim && ftz ) + RestoreFPState( &oldMode ); + + // Read the data back -- no need to wait for the first N-1 buffers. This is an in order queue. + for( j = gMinVectorSizeIndex; j + 1 < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_uint*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + } + + // Wait for the last buffer + out[j] = (cl_uint*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_TRUE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + + if (!skipVerification) { + //Verify data + t = (cl_uint *)r; + for( j = 0; j < buffer_elements; j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + cl_uint *q = out[k]; + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + float test = ((float*) q)[j]; + double correct = ref_func( s[j], s2[j] ); + + // Per section 10 paragraph 6, accept any result if an input or output is a infinity or NaN or overflow + // As per OpenCL 2.0 spec, section 5.8.4.3, enabling fast-relaxed-math mode also enables + // -cl-finite-math-only optimization. This optimization allows to assume that arguments and + // results are not NaNs or +/-INFs. Hence, accept any result if inputs or results are NaNs or INFs. + if ( gTestFastRelaxed || skipNanInf) + { + if( skipNanInf && overflow[j]) + continue; + // Note: no double rounding here. Reference functions calculate in single precision. + if( IsFloatInfinity(correct) || IsFloatNaN(correct) || + IsFloatInfinity(s2[j]) || IsFloatNaN(s2[j]) || + IsFloatInfinity(s[j]) || IsFloatNaN(s[j]) ) + continue; + } + + float err = Ulp_Error( test, correct ); + int fail = ! (fabsf(err) <= ulps); + + if( fail && ftz ) + { + // retry per section 6.5.3.2 + if( IsFloatResultSubnormal(correct, ulps ) ) + { + fail = fail && ( test != 0.0f ); + if( ! fail ) + err = 0.0f; + } + + // nextafter on FTZ platforms may return the smallest + // normal float (2^-126) given a denormal or a zero + // as the first argument. The rationale here is that + // nextafter flushes the argument to zero and then + // returns the next representable number in the + // direction of the second argument, and since + // denorms are considered as zero, the smallest + // normal number is the next representable number. + // In which case, it should have the same sign as the + // second argument. + if (isNextafter ) + { + if(IsFloatSubnormal(s[j]) || s[j] == 0.0f) + { + float value = copysignf(twoToMinus126, s2[j]); + fail = fail && (test != value); + if (!fail) + err = 0.0f; + } + } + else + { + // retry per section 6.5.3.3 + if( IsFloatSubnormal( s[j] ) ) + { + double correct2, correct3; + float err2, err3; + + if( skipNanInf ) + feclearexcept(FE_OVERFLOW); + + correct2 = ref_func( 0.0, s2[j] ); + correct3 = ref_func( -0.0, s2[j] ); + + // Per section 10 paragraph 6, accept any result if an input or output is a infinity or NaN or overflow + // As per OpenCL 2.0 spec, section 5.8.4.3, enabling fast-relaxed-math mode also enables + // -cl-finite-math-only optimization. This optimization allows to assume that arguments and + // results are not NaNs or +/-INFs. Hence, accept any result if inputs or results are NaNs or INFs. + if( gTestFastRelaxed || skipNanInf ) + { + if( fetestexcept(FE_OVERFLOW) && skipNanInf ) + continue; + + // Note: no double rounding here. Reference functions calculate in single precision. + if( IsFloatInfinity(correct2) || IsFloatNaN(correct2) || + IsFloatInfinity(correct3) || IsFloatNaN(correct3) ) + continue; + } + + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal( correct2, ulps ) || IsFloatResultSubnormal( correct3, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + + //try with both args as zero + if( IsFloatSubnormal( s2[j] ) ) + { + double correct4, correct5; + float err4, err5; + + if( skipNanInf ) + feclearexcept(FE_OVERFLOW); + + correct2 = ref_func( 0.0, 0.0 ); + correct3 = ref_func( -0.0, 0.0 ); + correct4 = ref_func( 0.0, -0.0 ); + correct5 = ref_func( -0.0, -0.0 ); + + // Per section 10 paragraph 6, accept any result if an input or output is a infinity or NaN or overflow + // As per OpenCL 2.0 spec, section 5.8.4.3, enabling fast-relaxed-math mode also enables + // -cl-finite-math-only optimization. This optimization allows to assume that arguments and + // results are not NaNs or +/-INFs. Hence, accept any result if inputs or results are NaNs or INFs. + if( gTestFastRelaxed || skipNanInf ) + { + if( fetestexcept(FE_OVERFLOW) && skipNanInf ) + continue; + + // Note: no double rounding here. Reference functions calculate in single precision. + if( IsFloatInfinity(correct2) || IsFloatNaN(correct2) || + IsFloatInfinity(correct3) || IsFloatNaN(correct3) || + IsFloatInfinity(correct4) || IsFloatNaN(correct4) || + IsFloatInfinity(correct5) || IsFloatNaN(correct5) ) + continue; + } + + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + err4 = Ulp_Error( test, correct4 ); + err5 = Ulp_Error( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps)) && + (!(fabsf(err4) <= ulps)) && (!(fabsf(err5) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal( correct2, ulps ) || IsFloatResultSubnormal( correct3, ulps ) || + IsFloatResultSubnormal( correct4, ulps ) || IsFloatResultSubnormal( correct5, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + else if(IsFloatSubnormal(s2[j]) ) + { + double correct2, correct3; + float err2, err3; + + if( skipNanInf ) + feclearexcept(FE_OVERFLOW); + + correct2 = ref_func( s[j], 0.0 ); + correct3 = ref_func( s[j], -0.0 ); + + // Per section 10 paragraph 6, accept any result if an input or output is a infinity or NaN or overflow + // As per OpenCL 2.0 spec, section 5.8.4.3, enabling fast-relaxed-math mode also enables + // -cl-finite-math-only optimization. This optimization allows to assume that arguments and + // results are not NaNs or +/-INFs. Hence, accept any result if inputs or results are NaNs or INFs. + if ( gTestFastRelaxed || skipNanInf ) + { + // Note: no double rounding here. Reference functions calculate in single precision. + if( overflow[j] && skipNanInf) + continue; + + if( IsFloatInfinity(correct2) || IsFloatNaN(correct2) || + IsFloatInfinity(correct3) || IsFloatNaN(correct3) ) + continue; + } + + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal( correct2, ulps ) || IsFloatResultSubnormal( correct3, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + } + + if( fabsf(err ) > tinfo->maxError ) + { + tinfo->maxError = fabsf(err); + tinfo->maxErrorValue = s[j]; + tinfo->maxErrorValue2 = s2[j]; + } + if( fail ) + { + vlog_error( "\nERROR: %s%s: %f ulp error at {%a (0x%x), %a (0x%x)}: *%a vs. %a (0x%8.8x) at index: %d\n", name, sizeNames[k], err, s[j], ((cl_uint*)s)[j], s2[j], ((cl_uint*)s2)[j], r[j], test, ((cl_uint*)&test)[0], j ); + error = -1; + goto exit; + } + } + } + } + } + + if (isFDim && gIsInRTZMode) + (void)set_round(oldRoundMode, kfloat); + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL)) ) + { + vlog_error( "Error: clEnqueueUnmapMemObject %d failed 2! err: %d\n", j, error ); + return error; + } + } + + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 3 failed\n" ); + + + if( 0 == ( base & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10u scale:%10zu buf_elements:%10u ulps:%5.3f ThreadCount:%2u\n", base, job->step, job->scale, buffer_elements, job->ulps, job->threadCount); + } else + { + vlog("." ); + } + fflush(stdout); + } + + +exit: + if( overflow ) + free( overflow ); + return error; + +} + + +// A table of more difficult cases to get right +static const double specialValuesDouble[] = { + -NAN, -INFINITY, -DBL_MAX, MAKE_HEX_DOUBLE(-0x1.0000000000001p64, -0x10000000000001LL, 12), MAKE_HEX_DOUBLE(-0x1.0p64, -0x1LL, 64), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp63, -0x1fffffffffffffLL, 11), MAKE_HEX_DOUBLE(-0x1.0000000000001p63, -0x10000000000001LL, 11), MAKE_HEX_DOUBLE(-0x1.0p63, -0x1LL, 63), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp62, -0x1fffffffffffffLL, 10), + MAKE_HEX_DOUBLE(-0x1.000002p32, -0x1000002LL, 8), MAKE_HEX_DOUBLE(-0x1.0p32, -0x1LL, 32), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp31, -0x1fffffffffffffLL, -21), MAKE_HEX_DOUBLE(-0x1.0000000000001p31, -0x10000000000001LL, -21), MAKE_HEX_DOUBLE(-0x1.0p31, -0x1LL, 31), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp30, -0x1fffffffffffffLL, -22), -1000., -100., -4.0, -3.5, + -3.0, MAKE_HEX_DOUBLE(-0x1.8000000000001p1, -0x18000000000001LL, -51), -2.5, MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp1, -0x17ffffffffffffLL, -51), -2.0, MAKE_HEX_DOUBLE(-0x1.8000000000001p0, -0x18000000000001LL, -52), -1.5, MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp0, -0x17ffffffffffffLL, -52),MAKE_HEX_DOUBLE(-0x1.0000000000001p0, -0x10000000000001LL, -52), -1.0, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-1, -0x1fffffffffffffLL, -53), + MAKE_HEX_DOUBLE(-0x1.0000000000001p-1, -0x10000000000001LL, -53), -0.5, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-2, -0x1fffffffffffffLL, -54), MAKE_HEX_DOUBLE(-0x1.0000000000001p-2, -0x10000000000001LL, -54), -0.25, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-3, -0x1fffffffffffffLL, -55), + MAKE_HEX_DOUBLE(-0x1.0000000000001p-1022, -0x10000000000001LL, -1074), -DBL_MIN, MAKE_HEX_DOUBLE(-0x0.fffffffffffffp-1022, -0x0fffffffffffffLL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000fffp-1022, -0x00000000000fffLL, -1074), MAKE_HEX_DOUBLE(-0x0.00000000000fep-1022, -0x000000000000feLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000ep-1022, -0x0000000000000eLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000cp-1022, -0x0000000000000cLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000ap-1022, -0x0000000000000aLL, -1074), + MAKE_HEX_DOUBLE(-0x0.0000000000008p-1022, -0x00000000000008LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000007p-1022, -0x00000000000007LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000006p-1022, -0x00000000000006LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000005p-1022, -0x00000000000005LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000004p-1022, -0x00000000000004LL, -1074), + MAKE_HEX_DOUBLE(-0x0.0000000000003p-1022, -0x00000000000003LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000002p-1022, -0x00000000000002LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000001p-1022, -0x00000000000001LL, -1074), -0.0, + + +NAN, +INFINITY, +DBL_MAX, MAKE_HEX_DOUBLE(+0x1.0000000000001p64, +0x10000000000001LL, 12), MAKE_HEX_DOUBLE(+0x1.0p64, +0x1LL, 64), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp63, +0x1fffffffffffffLL, 11), MAKE_HEX_DOUBLE(+0x1.0000000000001p63, +0x10000000000001LL, 11), MAKE_HEX_DOUBLE(+0x1.0p63, +0x1LL, 63), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp62, +0x1fffffffffffffLL, 10), + MAKE_HEX_DOUBLE(+0x1.000002p32, +0x1000002LL, 8), MAKE_HEX_DOUBLE(+0x1.0p32, +0x1LL, 32), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp31, +0x1fffffffffffffLL, -21), MAKE_HEX_DOUBLE(+0x1.0000000000001p31, +0x10000000000001LL, -21), MAKE_HEX_DOUBLE(+0x1.0p31, +0x1LL, 31), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp30, +0x1fffffffffffffLL, -22), +1000., +100., +4.0, +3.5, + +3.0, MAKE_HEX_DOUBLE(+0x1.8000000000001p1, +0x18000000000001LL, -51), +2.5, MAKE_HEX_DOUBLE(+0x1.7ffffffffffffp1, +0x17ffffffffffffLL, -51), +2.0, MAKE_HEX_DOUBLE(+0x1.8000000000001p0, +0x18000000000001LL, -52), +1.5, MAKE_HEX_DOUBLE(+0x1.7ffffffffffffp0, +0x17ffffffffffffLL, -52),MAKE_HEX_DOUBLE(-0x1.0000000000001p0, -0x10000000000001LL, -52), +1.0, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-1, +0x1fffffffffffffLL, -53), + MAKE_HEX_DOUBLE(+0x1.0000000000001p-1, +0x10000000000001LL, -53), +0.5, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-2, +0x1fffffffffffffLL, -54), MAKE_HEX_DOUBLE(+0x1.0000000000001p-2, +0x10000000000001LL, -54), +0.25, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-3, +0x1fffffffffffffLL, -55), + MAKE_HEX_DOUBLE(+0x1.0000000000001p-1022, +0x10000000000001LL, -1074), +DBL_MIN, MAKE_HEX_DOUBLE(+0x0.fffffffffffffp-1022, +0x0fffffffffffffLL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000fffp-1022, +0x00000000000fffLL, -1074), MAKE_HEX_DOUBLE(+0x0.00000000000fep-1022, +0x000000000000feLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000ep-1022, +0x0000000000000eLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000cp-1022, +0x0000000000000cLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000ap-1022, +0x0000000000000aLL, -1074), + MAKE_HEX_DOUBLE(+0x0.0000000000008p-1022, +0x00000000000008LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000007p-1022, +0x00000000000007LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000006p-1022, +0x00000000000006LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000005p-1022, +0x00000000000005LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000004p-1022, +0x00000000000004LL, -1074), + MAKE_HEX_DOUBLE(+0x0.0000000000003p-1022, +0x00000000000003LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000002p-1022, +0x00000000000002LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000001p-1022, +0x00000000000001LL, -1074), +0.0, +}; + +static size_t specialValuesDoubleCount = sizeof( specialValuesDouble ) / sizeof( specialValuesDouble[0] ); + +static cl_int TestDouble( cl_uint job_id, cl_uint thread_id, void *p ); + +int TestFunc_Double_Double_Double_common(const Func *f, MTdata d, int isNextafter) +{ + TestInfo test_info; + cl_int error; + size_t i, j; + float maxError = 0.0f; + double maxErrorVal = 0.0; + double maxErrorVal2 = 0.0; + + logFunctionInfo(f->name,sizeof(cl_double),gTestFastRelaxed); + + // Init test_info + memset( &test_info, 0, sizeof( test_info ) ); + test_info.threadCount = GetThreadCount(); + test_info.subBufferSize = BUFFER_SIZE / (sizeof( cl_double) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = 1; + + + if (gWimpyMode){ + test_info.subBufferSize = gWimpyBufferSize / (sizeof( cl_double) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = (cl_uint) sizeof(cl_double) * 2 * gWimpyReductionFactor; + } + test_info.step = (cl_uint) test_info.subBufferSize * test_info.scale; + test_info.f = f; + test_info.ulps = f->double_ulps; + test_info.ftz = f->ftz || gForceFTZ; + + test_info.isFDim = 0 == strcmp( "fdim", f->nameInCode ); + test_info.skipNanInf = 0; + test_info.isNextafter = isNextafter; + // cl_kernels aren't thread safe, so we make one for each vector size for every thread + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + size_t array_size = test_info.threadCount * sizeof( cl_kernel ); + test_info.k[i] = (cl_kernel*)malloc( array_size ); + if( NULL == test_info.k[i] ) + { + vlog_error( "Error: Unable to allocate storage for kernels!\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.k[i], 0, array_size ); + } + test_info.tinfo = (ThreadInfo*)malloc( test_info.threadCount * sizeof(*test_info.tinfo) ); + if( NULL == test_info.tinfo ) + { + vlog_error( "Error: Unable to allocate storage for thread specific data.\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.tinfo, 0, test_info.threadCount * sizeof(*test_info.tinfo) ); + for( i = 0; i < test_info.threadCount; i++ ) + { + cl_buffer_region region = { i * test_info.subBufferSize * sizeof( cl_double), test_info.subBufferSize * sizeof( cl_double) }; + test_info.tinfo[i].inBuf = clCreateSubBuffer( gInBuffer, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + test_info.tinfo[i].inBuf2 = clCreateSubBuffer( gInBuffer2, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + test_info.tinfo[i].outBuf[j] = clCreateSubBuffer( gOutBuffer[j], CL_MEM_WRITE_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].outBuf[j] ) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + } + test_info.tinfo[i].tQueue = clCreateCommandQueueWithProperties(gContext, gDevice, 0, &error); + if( NULL == test_info.tinfo[i].tQueue || error ) + { + vlog_error( "clCreateCommandQueue failed. (%d)\n", error ); + goto exit; + } + test_info.tinfo[i].d = init_genrand(genrand_int32(d)); + } + + + // Init the kernels + { + BuildKernelInfo build_info = { gMinVectorSizeIndex, test_info.threadCount, test_info.k, test_info.programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_DoubleFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + goto exit; + } + + if( !gSkipCorrectnessTesting ) + { + error = ThreadPool_Do( TestDouble, (cl_uint) ((1ULL<<32) / test_info.step), &test_info ); + + // Accumulate the arithmetic errors + for( i = 0; i < test_info.threadCount; i++ ) + { + if( test_info.tinfo[i].maxError > maxError ) + { + maxError = test_info.tinfo[i].maxError; + maxErrorVal = test_info.tinfo[i].maxErrorValue; + maxErrorVal2 = test_info.tinfo[i].maxErrorValue2; + } + } + + if( error ) + goto exit; + + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input arrays + double *p = (double *)gIn; + double *p2 = (double *)gIn2; + for( j = 0; j < BUFFER_SIZE / sizeof( cl_double ); j++ ) + { + p[j] = DoubleFromUInt32(genrand_int32(d)); + p2[j] = DoubleFromUInt32(genrand_int32(d)); + } + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, BUFFER_SIZE, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, BUFFER_SIZE, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_double ) * sizeValues[j]; + size_t localCount = (BUFFER_SIZE + vectorSize - 1) / vectorSize; // BUFFER_SIZE / vectorSize rounded up + if( ( error = clSetKernelArg( test_info.k[j][0], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(test_info.programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( i = 0; i < PERF_LOOP_COUNT; i++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, test_info.k[j][0], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (BUFFER_SIZE / sizeof( double ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sD%s", f->name, sizeNames[j] ); + } + for( ; j < gMaxVectorSizeIndex; j++ ) + vlog( "\t -- " ); + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t%8.2f @ {%a, %a}", maxError, maxErrorVal, maxErrorVal2 ); + vlog( "\n" ); + + +exit: + // Release + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + clReleaseProgram(test_info.programs[i]); + if( test_info.k[i] ) + { + for( j = 0; j < test_info.threadCount; j++ ) + clReleaseKernel(test_info.k[i][j]); + + free( test_info.k[i] ); + } + } + if( test_info.tinfo ) + { + for( i = 0; i < test_info.threadCount; i++ ) + { + free_mtdata( test_info.tinfo[i].d ); + clReleaseMemObject(test_info.tinfo[i].inBuf); + clReleaseMemObject(test_info.tinfo[i].inBuf2); + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + clReleaseMemObject(test_info.tinfo[i].outBuf[j]); + clReleaseCommandQueue(test_info.tinfo[i].tQueue); + } + + free( test_info.tinfo ); + } + + return error; +} + +static cl_int TestDouble( cl_uint job_id, cl_uint thread_id, void *data ) +{ + const TestInfo *job = (const TestInfo *) data; + size_t buffer_elements = job->subBufferSize; + size_t buffer_size = buffer_elements * sizeof( cl_double ); + cl_uint base = job_id * (cl_uint) job->step; + ThreadInfo *tinfo = job->tinfo + thread_id; + float ulps = job->ulps; + dptr func = job->f->dfunc; + int ftz = job->ftz; + MTdata d = tinfo->d; + cl_uint j, k; + cl_int error; + const char *name = job->f->name; + + int isNextafter = job->isNextafter; + cl_ulong *t; + cl_double *r,*s,*s2; + + Force64BitFPUPrecision(); + + // start the map of the output arrays + cl_event e[ VECTOR_SIZE_COUNT ]; + cl_ulong *out[ VECTOR_SIZE_COUNT ]; + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_ulong*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_WRITE, 0, buffer_size, 0, NULL, e + j, &error); + if( error || NULL == out[j]) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush failed\n" ); + + //Init input array + cl_ulong *p = (cl_ulong *)gIn + thread_id * buffer_elements; + cl_ulong *p2 = (cl_ulong *)gIn2 + thread_id * buffer_elements; + j = 0; + int totalSpecialValueCount = specialValuesDoubleCount * specialValuesDoubleCount; + int indx = (totalSpecialValueCount - 1) / buffer_elements; + + if( job_id <= (cl_uint)indx ) + { // test edge cases + cl_double *fp = (cl_double *)p; + cl_double *fp2 = (cl_double *)p2; + uint32_t x, y; + + x = (job_id * buffer_elements) % specialValuesDoubleCount; + y = (job_id * buffer_elements) / specialValuesDoubleCount; + + for( ; j < buffer_elements; j++ ) + { + fp[j] = specialValuesDouble[x]; + fp2[j] = specialValuesDouble[y]; + if( ++x >= specialValuesDoubleCount ) + { + x = 0; + y++; + if( y >= specialValuesDoubleCount ) + break; + } + } + } + + //Init any remaining values. + for( ; j < buffer_elements; j++ ) + { + p[j] = genrand_int64(d); + p2[j] = genrand_int64(d); + } + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf, CL_FALSE, 0, buffer_size, p, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf2, CL_FALSE, 0, buffer_size, p2, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + //Wait for the map to finish + if( (error = clWaitForEvents(1, e + j) )) + { + vlog_error( "Error: clWaitForEvents failed! err: %d\n", error ); + goto exit; + } + if( (error = clReleaseEvent( e[j] ) )) + { + vlog_error( "Error: clReleaseEvent failed! err: %d\n", error ); + goto exit; + } + + // Fill the result buffer with garbage, so that old results don't carry over + uint32_t pattern = 0xffffdead; + memset_pattern4(out[j], &pattern, buffer_size); + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueMapBuffer failed! err: %d\n", error ); + goto exit; + } + + // run the kernel + size_t vectorCount = (buffer_elements + sizeValues[j] - 1) / sizeValues[j]; + cl_kernel kernel = job->k[j][thread_id]; //each worker thread has its own copy of the cl_kernel + cl_program program = job->programs[j]; + + if( ( error = clSetKernelArg( kernel, 0, sizeof( tinfo->outBuf[j] ), &tinfo->outBuf[j] ))){ LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 1, sizeof( tinfo->inBuf ), &tinfo->inBuf ) )) { LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 2, sizeof( tinfo->inBuf2 ), &tinfo->inBuf2 ) )) { LogBuildError(program); return error; } + + if( (error = clEnqueueNDRangeKernel(tinfo->tQueue, kernel, 1, NULL, &vectorCount, NULL, 0, NULL, NULL))) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 2 failed\n" ); + + if( gSkipCorrectnessTesting ) + return CL_SUCCESS; + + //Calculate the correctly rounded reference result + r = (cl_double *)gOut_Ref + thread_id * buffer_elements; + s = (cl_double *)gIn + thread_id * buffer_elements; + s2 = (cl_double *)gIn2 + thread_id * buffer_elements; + for( j = 0; j < buffer_elements; j++ ) + r[j] = (cl_double) func.f_ff( s[j], s2[j] ); + + // Read the data back -- no need to wait for the first N-1 buffers. This is an in order queue. + for( j = gMinVectorSizeIndex; j + 1 < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_ulong*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + } + + // Wait for the last buffer + out[j] = (cl_ulong*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_TRUE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + + //Verify data + t = (cl_ulong *)r; + for( j = 0; j < buffer_elements; j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + cl_ulong *q = out[k]; + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + cl_double test = ((cl_double*) q)[j]; + long double correct = func.f_ff( s[j], s2[j] ); + float err = Ulp_Error_Double( test, correct ); + int fail = ! (fabsf(err) <= ulps); + + if( fail && ftz ) + { + // retry per section 6.5.3.2 + if( IsDoubleResultSubnormal(correct, ulps ) ) + { + fail = fail && ( test != 0.0f ); + if( ! fail ) + err = 0.0f; + } + + // nextafter on FTZ platforms may return the smallest + // normal float (2^-126) given a denormal or a zero + // as the first argument. The rationale here is that + // nextafter flushes the argument to zero and then + // returns the next representable number in the + // direction of the second argument, and since + // denorms are considered as zero, the smallest + // normal number is the next representable number. + // In which case, it should have the same sign as the + // second argument. + if (isNextafter ) + { + if(IsDoubleSubnormal(s[j]) || s[j] == 0.0f) + { + cl_double value = copysign(twoToMinus1022, s2[j]); + fail = fail && (test != value); + if (!fail) + err = 0.0f; + } + } + else + { + // retry per section 6.5.3.3 + if( IsDoubleSubnormal( s[j] ) ) + { + long double correct2 = func.f_ff( 0.0, s2[j] ); + long double correct3 = func.f_ff( -0.0, s2[j] ); + float err2 = Ulp_Error_Double( test, correct2 ); + float err3 = Ulp_Error_Double( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, ulps ) || IsDoubleResultSubnormal( correct3, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + + //try with both args as zero + if( IsDoubleSubnormal( s2[j] ) ) + { + correct2 = func.f_ff( 0.0, 0.0 ); + correct3 = func.f_ff( -0.0, 0.0 ); + long double correct4 = func.f_ff( 0.0, -0.0 ); + long double correct5 = func.f_ff( -0.0, -0.0 ); + err2 = Ulp_Error_Double( test, correct2 ); + err3 = Ulp_Error_Double( test, correct3 ); + float err4 = Ulp_Error_Double( test, correct4 ); + float err5 = Ulp_Error_Double( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps)) && + (!(fabsf(err4) <= ulps)) && (!(fabsf(err5) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, ulps ) || IsDoubleResultSubnormal( correct3, ulps ) || + IsDoubleResultSubnormal( correct4, ulps ) || IsDoubleResultSubnormal( correct5, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + else if(IsDoubleSubnormal(s2[j]) ) + { + long double correct2 = func.f_ff( s[j], 0.0 ); + long double correct3 = func.f_ff( s[j], -0.0 ); + float err2 = Ulp_Error_Double( test, correct2 ); + float err3 = Ulp_Error_Double( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, ulps ) || IsDoubleResultSubnormal( correct3, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + } + + if( fabsf(err ) > tinfo->maxError ) + { + tinfo->maxError = fabsf(err); + tinfo->maxErrorValue = s[j]; + tinfo->maxErrorValue2 = s2[j]; + } + if( fail ) + { + vlog_error( "\nERROR: %s%s: %f ulp error at {%.13la, %.13la}: *%.13la vs. %.13la\n", name, sizeNames[k], err, s[j], s2[j], r[j], test ); + error = -1; + goto exit; + } + } + } + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL)) ) + { + vlog_error( "Error: clEnqueueUnmapMemObject %d failed 2! err: %d\n", j, error ); + return error; + } + } + + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 3 failed\n" ); + + + if( 0 == ( base & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10u scale:%10zu buf_elements:%10u ulps:%5.3f ThreadCount:%2u\n", base, job->step, job->scale, buffer_elements, job->ulps, job->threadCount); + } else + { + vlog("." ); + } + fflush(stdout); + } +exit: + return error; + +} + +int TestFunc_Float_Float_Float(const Func *f, MTdata d) +{ + return TestFunc_Float_Float_Float_common(f, d, 0); +} + +int TestFunc_Double_Double_Double(const Func *f, MTdata d) +{ + return TestFunc_Double_Double_Double_common(f, d, 0); +} + +int TestFunc_Float_Float_Float_nextafter(const Func *f, MTdata d) +{ + return TestFunc_Float_Float_Float_common(f, d, 1); +} + +int TestFunc_Double_Double_Double_nextafter(const Func *f, MTdata d) +{ + return TestFunc_Double_Double_Double_common(f, d, 1); +} + diff --git a/test_conformance/math_brute_force/binaryOperator.c b/test_conformance/math_brute_force/binaryOperator.c new file mode 100644 index 00000000..718afd3d --- /dev/null +++ b/test_conformance/math_brute_force/binaryOperator.c @@ -0,0 +1,1455 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Utility.h" + +#include +#include "FunctionList.h" + +int TestFunc_Float_Float_Float_Operator(const Func *f, MTdata); +int TestFunc_Double_Double_Double_Operator(const Func *f, MTdata); + +#if defined(__cplusplus) + extern "C" +#endif + +const vtbl _binary_operator = { "binaryOperator", TestFunc_Float_Float_Float_Operator, TestFunc_Double_Double_Double_Operator }; + +static int BuildKernel( const char *name, const char *operator_symbol, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ); +static int BuildKernelDouble( const char *name, const char *operator_symbol, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ); + +static int BuildKernel( const char *name, const char *operator_symbol, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { + "__kernel void ", name, "_kernel", sizeNames[vectorSize], "( __global float", sizeNames[vectorSize], "* out, __global float", sizeNames[vectorSize], "* in1, __global float", sizeNames[vectorSize], "* in2 )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " out[i] = in1[i] ", operator_symbol, " in2[i];\n" + "}\n" + }; + const char *c3[] = { "__kernel void ", name, "_kernel", sizeNames[vectorSize], "( __global float* out, __global float* in, __global float* in2)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " float3 f0 = vload3( 0, in + 3 * i );\n" + " float3 f1 = vload3( 0, in2 + 3 * i );\n" + " f0 = f0 ", operator_symbol, " f1;\n" + " vstore3( f0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " float3 f0, f1;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (float3)( in[3*i], NAN, NAN ); \n" + " f1 = (float3)( in2[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " f0 = (float3)( in[3*i], in[3*i+1], NAN ); \n" + " f1 = (float3)( in2[3*i], in2[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " f0 = f0 ", operator_symbol, " f1;\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = f0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = f0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "%s_kernel%s", name, sizeNames[vectorSize] ); + + return MakeKernels(kern, (cl_uint) kernSize, testName, kernel_count, k, p); + +} + +static int BuildKernelDouble( const char *name, const char *operator_symbol, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void ", name, "_kernel", sizeNames[vectorSize], "( __global double", sizeNames[vectorSize], "* out, __global double", sizeNames[vectorSize], "* in1, __global double", sizeNames[vectorSize], "* in2 )\n" + "{\n" + " size_t i = get_global_id(0);\n" + " out[i] = in1[i] ", operator_symbol, " in2[i];\n" + "}\n" + }; + const char *c3[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "__kernel void ", name, "_kernel", sizeNames[vectorSize], "( __global double* out, __global double* in, __global double* in2)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " double3 d0 = vload3( 0, in + 3 * i );\n" + " double3 d1 = vload3( 0, in2 + 3 * i );\n" + " d0 = d0 ", operator_symbol, " d1;\n" + " vstore3( d0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " double3 d0, d1;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " d0 = (double3)( in[3*i], NAN, NAN ); \n" + " d1 = (double3)( in2[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " d0 = (double3)( in[3*i], in[3*i+1], NAN ); \n" + " d1 = (double3)( in2[3*i], in2[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " d0 = d0 ", operator_symbol, " d1;\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = d0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = d0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "%s_kernel%s", name, sizeNames[vectorSize] ); + + return MakeKernels(kern, (cl_uint) kernSize, testName, kernel_count, k, p); + +} + +typedef struct BuildKernelInfo +{ + cl_uint offset; // the first vector size to build + cl_uint kernel_count; + cl_kernel **kernels; + cl_program *programs; + const char *name; + const char *operator_symbol; +}BuildKernelInfo; + +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernel( info->name, info->operator_symbol, i, info->kernel_count, info->kernels[i], info->programs + i ); +} + +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernelDouble( info->name, info->operator_symbol, i, info->kernel_count, info->kernels[i], info->programs + i ); +} + +//Thread specific data for a worker thread +typedef struct ThreadInfo +{ + cl_mem inBuf; // input buffer for the thread + cl_mem inBuf2; // input buffer for the thread + cl_mem outBuf[ VECTOR_SIZE_COUNT ]; // output buffers for the thread + float maxError; // max error value. Init to 0. + double maxErrorValue; // position of the max error value (param 1). Init to 0. + double maxErrorValue2; // position of the max error value (param 2). Init to 0. + MTdata d; + cl_command_queue tQueue; // per thread command queue to improve performance +}ThreadInfo; + +typedef struct TestInfo +{ + size_t subBufferSize; // Size of the sub-buffer in elements + const Func *f; // A pointer to the function info + cl_program programs[ VECTOR_SIZE_COUNT ]; // programs for various vector sizes + cl_kernel *k[VECTOR_SIZE_COUNT ]; // arrays of thread-specific kernels for each worker thread: k[vector_size][thread_id] + ThreadInfo *tinfo; // An array of thread specific information for each worker thread + cl_uint threadCount; // Number of worker threads + cl_uint step; // step between each chunk and the next. + cl_uint scale; // stride between individual test values + float ulps; // max_allowed ulps + int ftz; // non-zero if running in flush to zero mode + + // no special fields +}TestInfo; + +static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *p ); + +// A table of more difficult cases to get right +static const float specialValuesFloat[] = { + -NAN, -INFINITY, -FLT_MAX, MAKE_HEX_FLOAT(-0x1.000002p64f, -0x1000002L, 40), MAKE_HEX_FLOAT(-0x1.0p64f, -0x1L, 64), MAKE_HEX_FLOAT(-0x1.fffffep63f, -0x1fffffeL, 39), MAKE_HEX_FLOAT(-0x1.000002p63f, -0x1000002L, 39), MAKE_HEX_FLOAT(-0x1.0p63f, -0x1L, 63), MAKE_HEX_FLOAT(-0x1.fffffep62f, -0x1fffffeL, 38), + MAKE_HEX_FLOAT(-0x1.000002p32f, -0x1000002L, 8), MAKE_HEX_FLOAT(-0x1.0p32f, -0x1L, 32), MAKE_HEX_FLOAT(-0x1.fffffep31f, -0x1fffffeL, 7), MAKE_HEX_FLOAT(-0x1.000002p31f, -0x1000002L, 7), MAKE_HEX_FLOAT(-0x1.0p31f, -0x1L, 31), MAKE_HEX_FLOAT(-0x1.fffffep30f, -0x1fffffeL, 6), -1000.f, -100.f, -4.0f, -3.5f, + -3.0f, MAKE_HEX_FLOAT(-0x1.800002p1f, -0x1800002L, -23), -2.5f, MAKE_HEX_FLOAT(-0x1.7ffffep1f, -0x17ffffeL, -23), -2.0f, MAKE_HEX_FLOAT(-0x1.800002p0f, -0x1800002L, -24), -1.5f, MAKE_HEX_FLOAT(-0x1.7ffffep0f, -0x17ffffeL, -24),MAKE_HEX_FLOAT(-0x1.000002p0f, -0x1000002L, -24), -1.0f, MAKE_HEX_FLOAT(-0x1.fffffep-1f, -0x1fffffeL, -25), + MAKE_HEX_FLOAT(-0x1.000002p-1f, -0x1000002L, -25), -0.5f, MAKE_HEX_FLOAT(-0x1.fffffep-2f, -0x1fffffeL, -26), MAKE_HEX_FLOAT(-0x1.000002p-2f, -0x1000002L, -26), -0.25f, MAKE_HEX_FLOAT(-0x1.fffffep-3f, -0x1fffffeL, -27), + MAKE_HEX_FLOAT(-0x1.000002p-126f, -0x1000002L, -150), -FLT_MIN, MAKE_HEX_FLOAT(-0x0.fffffep-126f, -0x0fffffeL, -150), MAKE_HEX_FLOAT(-0x0.000ffep-126f, -0x0000ffeL, -150), MAKE_HEX_FLOAT(-0x0.0000fep-126f, -0x00000feL, -150), MAKE_HEX_FLOAT(-0x0.00000ep-126f, -0x000000eL, -150), MAKE_HEX_FLOAT(-0x0.00000cp-126f, -0x000000cL, -150), MAKE_HEX_FLOAT(-0x0.00000ap-126f, -0x000000aL, -150), + MAKE_HEX_FLOAT(-0x0.000008p-126f, -0x0000008L, -150), MAKE_HEX_FLOAT(-0x0.000006p-126f, -0x0000006L, -150), MAKE_HEX_FLOAT(-0x0.000004p-126f, -0x0000004L, -150), MAKE_HEX_FLOAT(-0x0.000002p-126f, -0x0000002L, -150), -0.0f, + + +NAN, +INFINITY, +FLT_MAX, MAKE_HEX_FLOAT(+0x1.000002p64f, +0x1000002L, 40), MAKE_HEX_FLOAT(+0x1.0p64f, +0x1L, 64), MAKE_HEX_FLOAT(+0x1.fffffep63f, +0x1fffffeL, 39), MAKE_HEX_FLOAT(+0x1.000002p63f, +0x1000002L, 39), MAKE_HEX_FLOAT(+0x1.0p63f, +0x1L, 63), MAKE_HEX_FLOAT(+0x1.fffffep62f, +0x1fffffeL, 38), + MAKE_HEX_FLOAT(+0x1.000002p32f, +0x1000002L, 8), MAKE_HEX_FLOAT(+0x1.0p32f, +0x1L, 32), MAKE_HEX_FLOAT(+0x1.fffffep31f, +0x1fffffeL, 7), MAKE_HEX_FLOAT(+0x1.000002p31f, +0x1000002L, 7), MAKE_HEX_FLOAT(+0x1.0p31f, +0x1L, 31), MAKE_HEX_FLOAT(+0x1.fffffep30f, +0x1fffffeL, 6), +1000.f, +100.f, +4.0f, +3.5f, + +3.0f, MAKE_HEX_FLOAT(+0x1.800002p1f, +0x1800002L, -23), 2.5f, MAKE_HEX_FLOAT(+0x1.7ffffep1f, +0x17ffffeL, -23),+2.0f, MAKE_HEX_FLOAT(+0x1.800002p0f, +0x1800002L, -24), 1.5f, MAKE_HEX_FLOAT(+0x1.7ffffep0f, +0x17ffffeL, -24), MAKE_HEX_FLOAT(+0x1.000002p0f, +0x1000002L, -24), +1.0f, MAKE_HEX_FLOAT(+0x1.fffffep-1f, +0x1fffffeL, -25), + MAKE_HEX_FLOAT(+0x1.000002p-1f, +0x1000002L, -25), +0.5f, MAKE_HEX_FLOAT(+0x1.fffffep-2f, +0x1fffffeL, -26), MAKE_HEX_FLOAT(+0x1.000002p-2f, +0x1000002L, -26), +0.25f, MAKE_HEX_FLOAT(+0x1.fffffep-3f, +0x1fffffeL, -27), + MAKE_HEX_FLOAT(0x1.000002p-126f, 0x1000002L, -150), +FLT_MIN, MAKE_HEX_FLOAT(+0x0.fffffep-126f, +0x0fffffeL, -150), MAKE_HEX_FLOAT(+0x0.000ffep-126f, +0x0000ffeL, -150), MAKE_HEX_FLOAT(+0x0.0000fep-126f, +0x00000feL, -150), MAKE_HEX_FLOAT(+0x0.00000ep-126f, +0x000000eL, -150), MAKE_HEX_FLOAT(+0x0.00000cp-126f, +0x000000cL, -150), MAKE_HEX_FLOAT(+0x0.00000ap-126f, +0x000000aL, -150), + MAKE_HEX_FLOAT(+0x0.000008p-126f, +0x0000008L, -150), MAKE_HEX_FLOAT(+0x0.000006p-126f, +0x0000006L, -150), MAKE_HEX_FLOAT(+0x0.000004p-126f, +0x0000004L, -150), MAKE_HEX_FLOAT(+0x0.000002p-126f, +0x0000002L, -150), +0.0f +}; + +static size_t specialValuesFloatCount = sizeof( specialValuesFloat ) / sizeof( specialValuesFloat[0] ); + +static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *p ); + +int TestFunc_Float_Float_Float_Operator(const Func *f, MTdata d) +{ + TestInfo test_info; + cl_int error; + size_t i, j; + float maxError = 0.0f; + double maxErrorVal = 0.0; + double maxErrorVal2 = 0.0; + + logFunctionInfo(f->name,sizeof(cl_float),gTestFastRelaxed); + + // Init test_info + memset( &test_info, 0, sizeof( test_info ) ); + test_info.threadCount = GetThreadCount(); + test_info.subBufferSize = BUFFER_SIZE / (sizeof( cl_float) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = 1; + if (gWimpyMode) { + test_info.subBufferSize = gWimpyBufferSize / (sizeof( cl_float) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = (cl_uint) sizeof(cl_float) * 2 * gWimpyReductionFactor; + } + + test_info.step = test_info.subBufferSize * test_info.scale; + test_info.f = f; + test_info.ulps = gIsEmbedded ? f->float_embedded_ulps : f->float_ulps; + test_info.ftz = f->ftz || gForceFTZ || 0 == (CL_FP_DENORM & gFloatCapabilities); + + // cl_kernels aren't thread safe, so we make one for each vector size for every thread + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + size_t array_size = test_info.threadCount * sizeof( cl_kernel ); + test_info.k[i] = (cl_kernel*)malloc( array_size ); + if( NULL == test_info.k[i] ) + { + vlog_error( "Error: Unable to allocate storage for kernels!\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.k[i], 0, array_size ); + } + test_info.tinfo = (ThreadInfo*)malloc( test_info.threadCount * sizeof(*test_info.tinfo) ); + if( NULL == test_info.tinfo ) + { + vlog_error( "Error: Unable to allocate storage for thread specific data.\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.tinfo, 0, test_info.threadCount * sizeof(*test_info.tinfo) ); + for( i = 0; i < test_info.threadCount; i++ ) + { + cl_buffer_region region = { i * test_info.subBufferSize * sizeof( cl_float), test_info.subBufferSize * sizeof( cl_float) }; + test_info.tinfo[i].inBuf = clCreateSubBuffer( gInBuffer, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + test_info.tinfo[i].inBuf2 = clCreateSubBuffer( gInBuffer2, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + test_info.tinfo[i].outBuf[j] = clCreateSubBuffer( gOutBuffer[j], CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].outBuf[j] ) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + } + test_info.tinfo[i].tQueue = clCreateCommandQueueWithProperties(gContext, gDevice, 0, &error); + if( NULL == test_info.tinfo[i].tQueue || error ) + { + vlog_error( "clCreateCommandQueue failed. (%d)\n", error ); + goto exit; + } + + test_info.tinfo[i].d = init_genrand(genrand_int32(d)); + } + + // Init the kernels + { + BuildKernelInfo build_info = { gMinVectorSizeIndex, test_info.threadCount, test_info.k, test_info.programs, f->name, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_FloatFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + goto exit; + } + + if( !gSkipCorrectnessTesting ) + { + error = ThreadPool_Do( TestFloat, (cl_uint) ((1ULL<<32) / test_info.step), &test_info ); + + // Accumulate the arithmetic errors + for( i = 0; i < test_info.threadCount; i++ ) + { + if( test_info.tinfo[i].maxError > maxError ) + { + maxError = test_info.tinfo[i].maxError; + maxErrorVal = test_info.tinfo[i].maxErrorValue; + maxErrorVal2 = test_info.tinfo[i].maxErrorValue2; + } + } + + if( error ) + goto exit; + + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + + if( gMeasureTimes ) + { + //Init input arrays + uint32_t *p = (uint32_t *)gIn; + uint32_t *p2 = (uint32_t *)gIn2; + for( j = 0; j < BUFFER_SIZE / sizeof( float ); j++ ) + { + p[j] = (genrand_int32(d) & ~0x40000000) | 0x20000000; + p2[j] = 0x3fc00000; + } + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, BUFFER_SIZE, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, BUFFER_SIZE, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_float ) * sizeValues[j]; + size_t localCount = (BUFFER_SIZE + vectorSize - 1) / vectorSize; // BUFFER_SIZE / vectorSize rounded up + if( ( error = clSetKernelArg( test_info.k[j][0], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(test_info.programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( i = 0; i < PERF_LOOP_COUNT; i++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, test_info.k[j][0], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (BUFFER_SIZE / sizeof( float ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sf%s", f->name, sizeNames[j] ); + } + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t%8.2f @ {%a, %a}", maxError, maxErrorVal, maxErrorVal2 ); + vlog( "\n" ); + + +exit: + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + clReleaseProgram(test_info.programs[i]); + if( test_info.k[i] ) + { + for( j = 0; j < test_info.threadCount; j++ ) + clReleaseKernel(test_info.k[i][j]); + + free( test_info.k[i] ); + } + } + if( test_info.tinfo ) + { + for( i = 0; i < test_info.threadCount; i++ ) + { + free_mtdata(test_info.tinfo[i].d); + clReleaseMemObject(test_info.tinfo[i].inBuf); + clReleaseMemObject(test_info.tinfo[i].inBuf2); + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + clReleaseMemObject(test_info.tinfo[i].outBuf[j]); + clReleaseCommandQueue(test_info.tinfo[i].tQueue); + } + + free( test_info.tinfo ); + } + + return error; +} + +static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *data ) +{ + const TestInfo *job = (const TestInfo *) data; + size_t buffer_elements = job->subBufferSize; + size_t buffer_size = buffer_elements * sizeof( cl_float ); + cl_uint base = job_id * (cl_uint) job->step; + ThreadInfo *tinfo = job->tinfo + thread_id; + float ulps = job->ulps; + fptr func = job->f->func; + if ( gTestFastRelaxed ) + { + func = job->f->rfunc; + } + + + int ftz = job->ftz; + MTdata d = tinfo->d; + cl_uint j, k; + cl_int error; + cl_uchar *overflow = (cl_uchar*)malloc(buffer_size); + const char *name = job->f->name; + cl_uint *t; + cl_float *r,*s,*s2; + RoundingMode oldRoundMode; + + // start the map of the output arrays + cl_event e[ VECTOR_SIZE_COUNT ]; + cl_uint *out[ VECTOR_SIZE_COUNT ]; + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + out[j] = (uint32_t*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_WRITE, 0, buffer_size, 0, NULL, e + j, &error); + if( error || NULL == out[j]) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush failed\n" ); + + //Init input array + cl_uint *p = (cl_uint *)gIn + thread_id * buffer_elements; + cl_uint *p2 = (cl_uint *)gIn2 + thread_id * buffer_elements; + j = 0; + + int totalSpecialValueCount = specialValuesFloatCount * specialValuesFloatCount; + int indx = (totalSpecialValueCount - 1) / buffer_elements; + + if( job_id <= (cl_uint)indx ) + { // test edge cases + float *fp = (float *)p; + float *fp2 = (float *)p2; + uint32_t x, y; + + x = (job_id * buffer_elements) % specialValuesFloatCount; + y = (job_id * buffer_elements) / specialValuesFloatCount; + + for( ; j < buffer_elements; j++ ) + { + fp[j] = specialValuesFloat[x]; + fp2[j] = specialValuesFloat[y]; + if( ++x >= specialValuesFloatCount ) + { + x = 0; + y++; + if( y >= specialValuesFloatCount ) + break; + } + if(gTestFastRelaxed && strcmp(name,"divide") == 0 ) + { + float fpj = *(float*)&fp[j]; + float fpj2 = *(float*)&fp2[j]; + if(fabs(fpj) > 0x5E800000 ) //[2^-62,2^62] + { + fp[j] = NAN; + } + if( fabs(fpj2) > 0x5E800000 ) //[2^-62,2^62] + { + fp2[j] = NAN; + } + } + } + } + + //Init any remaining values. + for( ; j < buffer_elements; j++ ) + { + p[j] = genrand_int32(d); + p2[j] = genrand_int32(d); + + if(gTestFastRelaxed) + { + if( strcmp(name,"divide")==0){ + float pj = *(float*)&p[j]; + float pj2 = *(float*)&p2[j]; + if(fabs(pj) > 0x5E800000 ) //[2^-62,2^62] + { + p[j] = NAN; + } + if( fabs(pj2) > 0x5E800000 ) //[2^-62,2^62] + { + p2[j] = NAN; + } + } + } + } + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf, CL_FALSE, 0, buffer_size, p, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf2, CL_FALSE, 0, buffer_size, p2, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + //Wait for the map to finish + if( (error = clWaitForEvents(1, e + j) )) + { + vlog_error( "Error: clWaitForEvents failed! err: %d\n", error ); + goto exit; + } + if( (error = clReleaseEvent( e[j] ) )) + { + vlog_error( "Error: clReleaseEvent failed! err: %d\n", error ); + goto exit; + } + + // Fill the result buffer with garbage, so that old results don't carry over + uint32_t pattern = 0xffffdead; + memset_pattern4(out[j], &pattern, buffer_size); + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueMapBuffer failed! err: %d\n", error ); + goto exit; + } + + // run the kernel + size_t vectorCount = (buffer_elements + sizeValues[j] - 1) / sizeValues[j]; + cl_kernel kernel = job->k[j][thread_id]; //each worker thread has its own copy of the cl_kernel + cl_program program = job->programs[j]; + + if( ( error = clSetKernelArg( kernel, 0, sizeof( tinfo->outBuf[j] ), &tinfo->outBuf[j] ))){ LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 1, sizeof( tinfo->inBuf ), &tinfo->inBuf ) )) { LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 2, sizeof( tinfo->inBuf2 ), &tinfo->inBuf2 ) )) { LogBuildError(program); return error; } + + if( (error = clEnqueueNDRangeKernel(tinfo->tQueue, kernel, 1, NULL, &vectorCount, NULL, 0, NULL, NULL))) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 2 failed\n" ); + + if( gSkipCorrectnessTesting ) + { + free( overflow ); + return CL_SUCCESS; + } + + //Calculate the correctly rounded reference result + FPU_mode_type oldMode; + memset( &oldMode, 0, sizeof( oldMode ) ); + if( ftz ) + ForceFTZ( &oldMode ); + + // Set the rounding mode to match the device + oldRoundMode = kRoundToNearestEven; + if (gIsInRTZMode) + oldRoundMode = set_round(kRoundTowardZero, kfloat); + + //Calculate the correctly rounded reference result + r = (float *)gOut_Ref + thread_id * buffer_elements; + s = (float *)gIn + thread_id * buffer_elements; + s2 = (float *)gIn2 + thread_id * buffer_elements; + if( gInfNanSupport ) + { + for( j = 0; j < buffer_elements; j++ ) + r[j] = (float) func.f_ff( s[j], s2[j] ); + } + else + { + for( j = 0; j < buffer_elements; j++ ) + { + feclearexcept(FE_OVERFLOW); + r[j] = (float) func.f_ff( s[j], s2[j] ); + overflow[j] = FE_OVERFLOW == (FE_OVERFLOW & fetestexcept(FE_OVERFLOW)); + } + } + + if (gIsInRTZMode) + (void)set_round(oldRoundMode, kfloat); + + if( ftz ) + RestoreFPState( &oldMode ); + + // Read the data back -- no need to wait for the first N-1 buffers. This is an in order queue. + for( j = gMinVectorSizeIndex; j + 1 < gMaxVectorSizeIndex; j++ ) + { + out[j] = (uint32_t*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + } + + // Wait for the last buffer + out[j] = (uint32_t*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_TRUE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + + //Verify data + t = (cl_uint *)r; + for( j = 0; j < buffer_elements; j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + cl_uint *q = out[k]; + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + float test = ((float*) q)[j]; + double correct = func.f_ff( s[j], s2[j] ); + + // Per section 10 paragraph 6, accept any result if an input or output is a infinity or NaN or overflow + if ( !gInfNanSupport) + { + // Note: no double rounding here. Reference functions calculate in single precision. + if( overflow[j] || + IsFloatInfinity(correct) || IsFloatNaN(correct) || + IsFloatInfinity(s2[j]) || IsFloatNaN(s2[j]) || + IsFloatInfinity(s[j]) || IsFloatNaN(s[j]) ) + continue; + } + + // Per section 10 paragraph 6, accept embedded devices always returning positive 0.0. + if (gIsEmbedded && (t[j] == 0x80000000) && (q[j] == 0x00000000)) continue; + + float err = Ulp_Error( test, correct ); + float errB = Ulp_Error( test, (float) correct ); + + if( gTestFastRelaxed ) + ulps = job->f->relaxed_error; + + int fail = ((!(fabsf(err) <= ulps)) && (!(fabsf(errB) <= ulps))); + if( fabsf( errB ) < fabsf(err ) ) + err = errB; + + if( fail && ftz ) + { + // retry per section 6.5.3.2 + if( IsFloatResultSubnormal(correct, ulps ) ) + { + fail = fail && ( test != 0.0f ); + if( ! fail ) + err = 0.0f; + } + + // retry per section 6.5.3.3 + if( IsFloatSubnormal( s[j] ) ) + { + double correct2, correct3; + float err2, err3; + + if( !gInfNanSupport ) + feclearexcept(FE_OVERFLOW); + + correct2 = func.f_ff( 0.0, s2[j] ); + correct3 = func.f_ff( -0.0, s2[j] ); + + // Per section 10 paragraph 6, accept any result if an input or output is a infinity or NaN or overflow + if( !gInfNanSupport ) + { + if( fetestexcept(FE_OVERFLOW) ) + continue; + + // Note: no double rounding here. Reference functions calculate in single precision. + if( IsFloatInfinity(correct2) || IsFloatNaN(correct2) || + IsFloatInfinity(correct3) || IsFloatNaN(correct3) ) + continue; + } + + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal( correct2, ulps ) || IsFloatResultSubnormal( correct3, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + + //try with both args as zero + if( IsFloatSubnormal( s2[j] ) ) + { + double correct4, correct5; + float err4, err5; + + if( !gInfNanSupport ) + feclearexcept(FE_OVERFLOW); + + correct2 = func.f_ff( 0.0, 0.0 ); + correct3 = func.f_ff( -0.0, 0.0 ); + correct4 = func.f_ff( 0.0, -0.0 ); + correct5 = func.f_ff( -0.0, -0.0 ); + + // Per section 10 paragraph 6, accept any result if an input or output is a infinity or NaN or overflow + if( !gInfNanSupport ) + { + if( fetestexcept(FE_OVERFLOW) ) + continue; + + // Note: no double rounding here. Reference functions calculate in single precision. + if( IsFloatInfinity(correct2) || IsFloatNaN(correct2) || + IsFloatInfinity(correct3) || IsFloatNaN(correct3) || + IsFloatInfinity(correct4) || IsFloatNaN(correct4) || + IsFloatInfinity(correct5) || IsFloatNaN(correct5) ) + continue; + } + + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + err4 = Ulp_Error( test, correct4 ); + err5 = Ulp_Error( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps)) && + (!(fabsf(err4) <= ulps)) && (!(fabsf(err5) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal( correct2, ulps ) || IsFloatResultSubnormal( correct3, ulps ) || + IsFloatResultSubnormal( correct4, ulps ) || IsFloatResultSubnormal( correct5, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + else if(IsFloatSubnormal(s2[j]) ) + { + double correct2, correct3; + float err2, err3; + + if( !gInfNanSupport ) + feclearexcept(FE_OVERFLOW); + + correct2 = func.f_ff( s[j], 0.0 ); + correct3 = func.f_ff( s[j], -0.0 ); + + // Per section 10 paragraph 6, accept any result if an input or output is a infinity or NaN or overflow + if ( !gInfNanSupport) + { + // Note: no double rounding here. Reference functions calculate in single precision. + if( overflow[j] || + IsFloatInfinity(correct) || IsFloatNaN(correct) || + IsFloatInfinity(correct2)|| IsFloatNaN(correct2) ) + continue; + } + + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal( correct2, ulps ) || IsFloatResultSubnormal( correct3, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + + + if( fabsf(err ) > tinfo->maxError ) + { + tinfo->maxError = fabsf(err); + tinfo->maxErrorValue = s[j]; + tinfo->maxErrorValue2 = s2[j]; + } + if( fail ) + { + vlog_error( "\nERROR: %s%s: %f ulp error at {%a, %a}: *%a vs. %a (0x%8.8x) at index: %d\n", name, sizeNames[k], err, s[j], s2[j], r[j], test, ((cl_uint*)&test)[0], j ); + error = -1; + goto exit; + } + } + } + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL)) ) + { + vlog_error( "Error: clEnqueueUnmapMemObject %d failed 2! err: %d\n", j, error ); + return error; + } + } + + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 3 failed\n" ); + + + if( 0 == ( base & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10u scale:%10zu buf_elements:%10u ulps:%5.3f ThreadCount:%2u\n", base, job->step, job->scale, buffer_elements, job->ulps, job->threadCount); + } else + { + vlog("." ); + } + fflush(stdout); + } +exit: + if( overflow ) + free( overflow ); + return error; + +} + + +// A table of more difficult cases to get right +static const double specialValuesDouble[] = { + -NAN, -INFINITY, -DBL_MAX, MAKE_HEX_DOUBLE(-0x1.0000000000001p64, -0x10000000000001LL, 12), MAKE_HEX_DOUBLE(-0x1.0p64, -0x1LL, 64), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp63, -0x1fffffffffffffLL, 11), MAKE_HEX_DOUBLE(-0x1.0000000000001p63, -0x10000000000001LL, 11), MAKE_HEX_DOUBLE(-0x1.0p63, -0x1LL, 63), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp62, -0x1fffffffffffffLL, 10), + MAKE_HEX_DOUBLE(-0x1.000002p32, -0x1000002LL, 8), MAKE_HEX_DOUBLE(-0x1.0p32, -0x1LL, 32), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp31, -0x1fffffffffffffLL, -21), MAKE_HEX_DOUBLE(-0x1.0000000000001p31, -0x10000000000001LL, -21), MAKE_HEX_DOUBLE(-0x1.0p31, -0x1LL, 31), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp30, -0x1fffffffffffffLL, -22), -1000., -100., -4.0, -3.5, + -3.0, MAKE_HEX_DOUBLE(-0x1.8000000000001p1, -0x18000000000001LL, -51), -2.5, MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp1, -0x17ffffffffffffLL, -51), -2.0, MAKE_HEX_DOUBLE(-0x1.8000000000001p0, -0x18000000000001LL, -52), -1.5, MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp0, -0x17ffffffffffffLL, -52),MAKE_HEX_DOUBLE(-0x1.0000000000001p0, -0x10000000000001LL, -52), -1.0, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-1, -0x1fffffffffffffLL, -53), + MAKE_HEX_DOUBLE(-0x1.0000000000001p-1, -0x10000000000001LL, -53), -0.5, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-2, -0x1fffffffffffffLL, -54), MAKE_HEX_DOUBLE(-0x1.0000000000001p-2, -0x10000000000001LL, -54), -0.25, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-3, -0x1fffffffffffffLL, -55), + MAKE_HEX_DOUBLE(-0x1.0000000000001p-1022, -0x10000000000001LL, -1074), -DBL_MIN, MAKE_HEX_DOUBLE(-0x0.fffffffffffffp-1022, -0x0fffffffffffffLL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000fffp-1022, -0x00000000000fffLL, -1074), MAKE_HEX_DOUBLE(-0x0.00000000000fep-1022, -0x000000000000feLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000ep-1022, -0x0000000000000eLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000cp-1022, -0x0000000000000cLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000ap-1022, -0x0000000000000aLL, -1074), + MAKE_HEX_DOUBLE(-0x0.0000000000008p-1022, -0x00000000000008LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000007p-1022, -0x00000000000007LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000006p-1022, -0x00000000000006LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000005p-1022, -0x00000000000005LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000004p-1022, -0x00000000000004LL, -1074), + MAKE_HEX_DOUBLE(-0x0.0000000000003p-1022, -0x00000000000003LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000002p-1022, -0x00000000000002LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000001p-1022, -0x00000000000001LL, -1074), -0.0, + + +NAN, +INFINITY, +DBL_MAX, MAKE_HEX_DOUBLE(+0x1.0000000000001p64, +0x10000000000001LL, 12), MAKE_HEX_DOUBLE(+0x1.0p64, +0x1LL, 64), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp63, +0x1fffffffffffffLL, 11), MAKE_HEX_DOUBLE(+0x1.0000000000001p63, +0x10000000000001LL, 11), MAKE_HEX_DOUBLE(+0x1.0p63, +0x1LL, 63), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp62, +0x1fffffffffffffLL, 10), + MAKE_HEX_DOUBLE(+0x1.000002p32, +0x1000002LL, 8), MAKE_HEX_DOUBLE(+0x1.0p32, +0x1LL, 32), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp31, +0x1fffffffffffffLL, -21), MAKE_HEX_DOUBLE(+0x1.0000000000001p31, +0x10000000000001LL, -21), MAKE_HEX_DOUBLE(+0x1.0p31, +0x1LL, 31), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp30, +0x1fffffffffffffLL, -22), +1000., +100., +4.0, +3.5, + +3.0, MAKE_HEX_DOUBLE(+0x1.8000000000001p1, +0x18000000000001LL, -51), +2.5, MAKE_HEX_DOUBLE(+0x1.7ffffffffffffp1, +0x17ffffffffffffLL, -51), +2.0, MAKE_HEX_DOUBLE(+0x1.8000000000001p0, +0x18000000000001LL, -52), +1.5, MAKE_HEX_DOUBLE(+0x1.7ffffffffffffp0, +0x17ffffffffffffLL, -52),MAKE_HEX_DOUBLE(-0x1.0000000000001p0, -0x10000000000001LL, -52), +1.0, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-1, +0x1fffffffffffffLL, -53), + MAKE_HEX_DOUBLE(+0x1.0000000000001p-1, +0x10000000000001LL, -53), +0.5, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-2, +0x1fffffffffffffLL, -54), MAKE_HEX_DOUBLE(+0x1.0000000000001p-2, +0x10000000000001LL, -54), +0.25, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-3, +0x1fffffffffffffLL, -55), + MAKE_HEX_DOUBLE(+0x1.0000000000001p-1022, +0x10000000000001LL, -1074), +DBL_MIN, MAKE_HEX_DOUBLE(+0x0.fffffffffffffp-1022, +0x0fffffffffffffLL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000fffp-1022, +0x00000000000fffLL, -1074), MAKE_HEX_DOUBLE(+0x0.00000000000fep-1022, +0x000000000000feLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000ep-1022, +0x0000000000000eLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000cp-1022, +0x0000000000000cLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000ap-1022, +0x0000000000000aLL, -1074), + MAKE_HEX_DOUBLE(+0x0.0000000000008p-1022, +0x00000000000008LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000007p-1022, +0x00000000000007LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000006p-1022, +0x00000000000006LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000005p-1022, +0x00000000000005LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000004p-1022, +0x00000000000004LL, -1074), + MAKE_HEX_DOUBLE(+0x0.0000000000003p-1022, +0x00000000000003LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000002p-1022, +0x00000000000002LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000001p-1022, +0x00000000000001LL, -1074), +0.0, +}; + +static size_t specialValuesDoubleCount = sizeof( specialValuesDouble ) / sizeof( specialValuesDouble[0] ); + +static cl_int TestDouble( cl_uint job_id, cl_uint thread_id, void *p ); + +int TestFunc_Double_Double_Double_Operator(const Func *f, MTdata d) +{ + TestInfo test_info; + cl_int error; + size_t i, j; + float maxError = 0.0f; + double maxErrorVal = 0.0; + double maxErrorVal2 = 0.0; + logFunctionInfo(f->name,sizeof(cl_double),gTestFastRelaxed); + + // Init test_info + memset( &test_info, 0, sizeof( test_info ) ); + test_info.threadCount = GetThreadCount(); + test_info.subBufferSize = BUFFER_SIZE / (sizeof( cl_double) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = 1; + if (gWimpyMode) + { + test_info.subBufferSize = gWimpyBufferSize / (sizeof( cl_double) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = (cl_uint) sizeof(cl_double) * 2 * gWimpyReductionFactor; + } + + test_info.step = (cl_uint) test_info.subBufferSize * test_info.scale; + test_info.f = f; + test_info.ulps = f->double_ulps; + test_info.ftz = f->ftz || gForceFTZ; + + // cl_kernels aren't thread safe, so we make one for each vector size for every thread + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + size_t array_size = test_info.threadCount * sizeof( cl_kernel ); + test_info.k[i] = (cl_kernel*)malloc( array_size ); + if( NULL == test_info.k[i] ) + { + vlog_error( "Error: Unable to allocate storage for kernels!\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.k[i], 0, array_size ); + } + test_info.tinfo = (ThreadInfo*)malloc( test_info.threadCount * sizeof(*test_info.tinfo) ); + if( NULL == test_info.tinfo ) + { + vlog_error( "Error: Unable to allocate storage for thread specific data.\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.tinfo, 0, test_info.threadCount * sizeof(*test_info.tinfo) ); + for( i = 0; i < test_info.threadCount; i++ ) + { + cl_buffer_region region = { i * test_info.subBufferSize * sizeof( cl_double), test_info.subBufferSize * sizeof( cl_double) }; + test_info.tinfo[i].inBuf = clCreateSubBuffer( gInBuffer, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + test_info.tinfo[i].inBuf2 = clCreateSubBuffer( gInBuffer2, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + test_info.tinfo[i].outBuf[j] = clCreateSubBuffer( gOutBuffer[j], CL_MEM_WRITE_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].outBuf[j] ) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + } + test_info.tinfo[i].tQueue = clCreateCommandQueueWithProperties(gContext, gDevice, 0, &error); + if( NULL == test_info.tinfo[i].tQueue || error ) + { + vlog_error( "clCreateCommandQueue failed. (%d)\n", error ); + goto exit; + } + + test_info.tinfo[i].d = init_genrand(genrand_int32(d)); + } + + + // Init the kernels + { + BuildKernelInfo build_info = { gMinVectorSizeIndex, test_info.threadCount, test_info.k, test_info.programs, f->name, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_DoubleFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + goto exit; + } + + if( !gSkipCorrectnessTesting ) + { + error = ThreadPool_Do( TestDouble, (cl_uint) ((1ULL<<32) / test_info.step), &test_info ); + + // Accumulate the arithmetic errors + for( i = 0; i < test_info.threadCount; i++ ) + { + if( test_info.tinfo[i].maxError > maxError ) + { + maxError = test_info.tinfo[i].maxError; + maxErrorVal = test_info.tinfo[i].maxErrorValue; + maxErrorVal2 = test_info.tinfo[i].maxErrorValue2; + } + } + + if( error ) + goto exit; + + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + + if( gMeasureTimes ) + { + //Init input arrays + double *p = (double *)gIn; + double *p2 = (double *)gIn2; + for( j = 0; j < BUFFER_SIZE / sizeof( cl_double ); j++ ) + { + p[j] = DoubleFromUInt32(genrand_int32(d)); + p2[j] = DoubleFromUInt32(genrand_int32(d)); + } + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, BUFFER_SIZE, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, BUFFER_SIZE, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_double ) * sizeValues[j]; + size_t localCount = (BUFFER_SIZE + vectorSize - 1) / vectorSize; // BUFFER_SIZE / vectorSize rounded up + if( ( error = clSetKernelArg( test_info.k[j][0], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(test_info.programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( i = 0; i < PERF_LOOP_COUNT; i++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, test_info.k[j][0], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (BUFFER_SIZE / sizeof( double ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sD%s", f->name, sizeNames[j] ); + } + for( ; j < gMaxVectorSizeIndex; j++ ) + vlog( "\t -- " ); + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t%8.2f @ {%a, %a}", maxError, maxErrorVal, maxErrorVal2 ); + vlog( "\n" ); + + +exit: + // Release + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + clReleaseProgram(test_info.programs[i]); + if( test_info.k[i] ) + { + for( j = 0; j < test_info.threadCount; j++ ) + clReleaseKernel(test_info.k[i][j]); + + free( test_info.k[i] ); + } + } + if( test_info.tinfo ) + { + for( i = 0; i < test_info.threadCount; i++ ) + { + free_mtdata(test_info.tinfo[i].d); + clReleaseMemObject(test_info.tinfo[i].inBuf); + clReleaseMemObject(test_info.tinfo[i].inBuf2); + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + clReleaseMemObject(test_info.tinfo[i].outBuf[j]); + clReleaseCommandQueue(test_info.tinfo[i].tQueue); + } + + free( test_info.tinfo ); + } + + return error; +} + +static cl_int TestDouble( cl_uint job_id, cl_uint thread_id, void *data ) +{ + const TestInfo *job = (const TestInfo *) data; + size_t buffer_elements = job->subBufferSize; + size_t buffer_size = buffer_elements * sizeof( cl_double ); + cl_uint base = job_id * (cl_uint) job->step; + ThreadInfo *tinfo = job->tinfo + thread_id; + float ulps = job->ulps; + dptr func = job->f->dfunc; + int ftz = job->ftz; + MTdata d = tinfo->d; + cl_uint j, k; + cl_int error; + const char *name = job->f->name; + cl_ulong *t; + cl_double *r,*s,*s2; + + Force64BitFPUPrecision(); + + // start the map of the output arrays + cl_event e[ VECTOR_SIZE_COUNT ]; + cl_ulong *out[ VECTOR_SIZE_COUNT ]; + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_ulong*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_WRITE, 0, buffer_size, 0, NULL, e + j, &error); + if( error || NULL == out[j]) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush failed\n" ); + + //Init input array + cl_ulong *p = (cl_ulong *)gIn + thread_id * buffer_elements; + cl_ulong *p2 = (cl_ulong *)gIn2 + thread_id * buffer_elements; + j = 0; + int totalSpecialValueCount = specialValuesDoubleCount * specialValuesDoubleCount; + int indx = (totalSpecialValueCount - 1) / buffer_elements; + + if( job_id <= (cl_uint)indx ) + { // test edge cases + cl_double *fp = (cl_double *)p; + cl_double *fp2 = (cl_double *)p2; + uint32_t x, y; + + x = (job_id * buffer_elements) % specialValuesDoubleCount; + y = (job_id * buffer_elements) / specialValuesDoubleCount; + + for( ; j < buffer_elements; j++ ) + { + fp[j] = specialValuesDouble[x]; + fp2[j] = specialValuesDouble[y]; + if( ++x >= specialValuesDoubleCount ) + { + x = 0; + y++; + if( y >= specialValuesDoubleCount ) + break; + } + } + } + + //Init any remaining values. + for( ; j < buffer_elements; j++ ) + { + p[j] = genrand_int64(d); + p2[j] = genrand_int64(d); + } + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf, CL_FALSE, 0, buffer_size, p, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf2, CL_FALSE, 0, buffer_size, p2, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + //Wait for the map to finish + if( (error = clWaitForEvents(1, e + j) )) + { + vlog_error( "Error: clWaitForEvents failed! err: %d\n", error ); + goto exit; + } + if( (error = clReleaseEvent( e[j] ) )) + { + vlog_error( "Error: clReleaseEvent failed! err: %d\n", error ); + goto exit; + } + + // Fill the result buffer with garbage, so that old results don't carry over + uint32_t pattern = 0xffffdead; + memset_pattern4(out[j], &pattern, buffer_size); + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueMapBuffer failed! err: %d\n", error ); + goto exit; + } + + // run the kernel + size_t vectorCount = (buffer_elements + sizeValues[j] - 1) / sizeValues[j]; + cl_kernel kernel = job->k[j][thread_id]; //each worker thread has its own copy of the cl_kernel + cl_program program = job->programs[j]; + + if( ( error = clSetKernelArg( kernel, 0, sizeof( tinfo->outBuf[j] ), &tinfo->outBuf[j] ))){ LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 1, sizeof( tinfo->inBuf ), &tinfo->inBuf ) )) { LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 2, sizeof( tinfo->inBuf2 ), &tinfo->inBuf2 ) )) { LogBuildError(program); return error; } + + if( (error = clEnqueueNDRangeKernel(tinfo->tQueue, kernel, 1, NULL, &vectorCount, NULL, 0, NULL, NULL))) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 2 failed\n" ); + + if( gSkipCorrectnessTesting ) + return CL_SUCCESS; + + //Calculate the correctly rounded reference result + r = (cl_double *)gOut_Ref + thread_id * buffer_elements; + s = (cl_double *)gIn + thread_id * buffer_elements; + s2 = (cl_double *)gIn2 + thread_id * buffer_elements; + for( j = 0; j < buffer_elements; j++ ) + r[j] = (cl_double) func.f_ff( s[j], s2[j] ); + + // Read the data back -- no need to wait for the first N-1 buffers. This is an in order queue. + for( j = gMinVectorSizeIndex; j + 1 < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_ulong*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + } + + // Wait for the last buffer + out[j] = (cl_ulong*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_TRUE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + + //Verify data + t = (cl_ulong *)r; + for( j = 0; j < buffer_elements; j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + cl_ulong *q = out[k]; + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + cl_double test = ((cl_double*) q)[j]; + long double correct = func.f_ff( s[j], s2[j] ); + float err = Ulp_Error_Double( test, correct ); + int fail = ! (fabsf(err) <= ulps); + + if( fail && ftz ) + { + // retry per section 6.5.3.2 + if( IsDoubleResultSubnormal(correct, ulps ) ) + { + fail = fail && ( test != 0.0f ); + if( ! fail ) + err = 0.0f; + } + + + // retry per section 6.5.3.3 + if( IsDoubleSubnormal( s[j] ) ) + { + long double correct2 = func.f_ff( 0.0, s2[j] ); + long double correct3 = func.f_ff( -0.0, s2[j] ); + float err2 = Ulp_Error_Double( test, correct2 ); + float err3 = Ulp_Error_Double( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, ulps ) || IsDoubleResultSubnormal( correct3, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + + //try with both args as zero + if( IsDoubleSubnormal( s2[j] ) ) + { + correct2 = func.f_ff( 0.0, 0.0 ); + correct3 = func.f_ff( -0.0, 0.0 ); + long double correct4 = func.f_ff( 0.0, -0.0 ); + long double correct5 = func.f_ff( -0.0, -0.0 ); + err2 = Ulp_Error_Double( test, correct2 ); + err3 = Ulp_Error_Double( test, correct3 ); + float err4 = Ulp_Error_Double( test, correct4 ); + float err5 = Ulp_Error_Double( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps)) && + (!(fabsf(err4) <= ulps)) && (!(fabsf(err5) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, ulps ) || IsDoubleResultSubnormal( correct3, ulps ) || + IsDoubleResultSubnormal( correct4, ulps ) || IsDoubleResultSubnormal( correct5, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + else if(IsDoubleSubnormal(s2[j]) ) + { + long double correct2 = func.f_ff( s[j], 0.0 ); + long double correct3 = func.f_ff( s[j], -0.0 ); + float err2 = Ulp_Error_Double( test, correct2 ); + float err3 = Ulp_Error_Double( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, ulps ) || IsDoubleResultSubnormal( correct3, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + + if( fabsf(err ) > tinfo->maxError ) + { + tinfo->maxError = fabsf(err); + tinfo->maxErrorValue = s[j]; + tinfo->maxErrorValue2 = s2[j]; + } + if( fail ) + { + vlog_error( "\nERROR: %s%s: %f ulp error at {%a, %a}: *%a vs. %a\n", name, sizeNames[k], err, s[j], s2[j], r[j], test ); + error = -1; + goto exit; + } + } + } + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL)) ) + { + vlog_error( "Error: clEnqueueUnmapMemObject %d failed 2! err: %d\n", j, error ); + return error; + } + } + + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 3 failed\n" ); + + + if( 0 == ( base & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10u scale:%10zu buf_elements:%10u ulps:%5.3f ThreadCount:%2u\n", base, job->step, job->scale, buffer_elements, job->ulps, job->threadCount); + } else + { + vlog("." ); + } + fflush(stdout); + } + +exit: + return error; + +} + + + + diff --git a/test_conformance/math_brute_force/binary_i.c b/test_conformance/math_brute_force/binary_i.c new file mode 100644 index 00000000..b72d117f --- /dev/null +++ b/test_conformance/math_brute_force/binary_i.c @@ -0,0 +1,1214 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Utility.h" + +#include +#include +#include "FunctionList.h" + +int TestFunc_Float_Float_Int(const Func *f, MTdata); +int TestFunc_Double_Double_Int(const Func *f, MTdata); + +#if defined( __cplusplus) + extern "C" +#endif +const vtbl _binary_i = { "binary_i", TestFunc_Float_Float_Int, TestFunc_Double_Double_Int }; + +static int BuildKernel( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ); +static int BuildKernelDouble( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ); + +static int BuildKernel( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global float", sizeNames[vectorSize], "* out, __global float", sizeNames[vectorSize], "* in1, __global int", sizeNames[vectorSize], "* in2 )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in1[i], in2[i] );\n" + "}\n" + }; + + const char *c3[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global float* out, __global float* in, __global int* in2)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " float3 f0 = vload3( 0, in + 3 * i );\n" + " int3 i0 = vload3( 0, in2 + 3 * i );\n" + " f0 = ", name, "( f0, i0 );\n" + " vstore3( f0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " float3 f0;\n" + " int3 i0;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (float3)( in[3*i], NAN, NAN ); \n" + " i0 = (int3)( in2[3*i], 0xdead, 0xdead ); \n" + " break;\n" + " case 0:\n" + " f0 = (float3)( in[3*i], in[3*i+1], NAN ); \n" + " i0 = (int3)( in2[3*i], in2[3*i+1], 0xdead ); \n" + " break;\n" + " }\n" + " f0 = ", name, "( f0, i0 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = f0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = f0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernels(kern, (cl_uint) kernSize, testName, kernel_count, k, p); +} + +static int BuildKernelDouble( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double", sizeNames[vectorSize], "* out, __global double", sizeNames[vectorSize], "* in1, __global int", sizeNames[vectorSize], "* in2 )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in1[i], in2[i] );\n" + "}\n" + }; + + const char *c3[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double* out, __global double* in, __global int* in2)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " double3 d0 = vload3( 0, in + 3 * i );\n" + " int3 i0 = vload3( 0, in2 + 3 * i );\n" + " d0 = ", name, "( d0, i0 );\n" + " vstore3( d0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " double3 d0;\n" + " int3 i0;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " d0 = (double3)( in[3*i], NAN, NAN ); \n" + " i0 = (int3)( in2[3*i], 0xdead, 0xdead ); \n" + " break;\n" + " case 0:\n" + " d0 = (double3)( in[3*i], in[3*i+1], NAN ); \n" + " i0 = (int3)( in2[3*i], in2[3*i+1], 0xdead ); \n" + " break;\n" + " }\n" + " d0 = ", name, "( d0, i0 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = d0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = d0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernels(kern, (cl_uint) kernSize, testName, kernel_count, k, p); +} + +typedef struct BuildKernelInfo +{ + cl_uint offset; // the first vector size to build + cl_uint kernel_count; + cl_kernel **kernels; + cl_program *programs; + const char *nameInCode; +}BuildKernelInfo; + +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernel( info->nameInCode, i, info->kernel_count, info->kernels[i], info->programs + i ); +} + +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernelDouble( info->nameInCode, i, info->kernel_count, info->kernels[i], info->programs + i ); +} + + +// A table of more difficult cases to get right +static const float specialValuesFloat[] = { + -NAN, -INFINITY, -FLT_MAX, MAKE_HEX_FLOAT(-0x1.000002p64f, -0x1000002L, 40), MAKE_HEX_FLOAT(-0x1.0p64f, -0x1L, 64), MAKE_HEX_FLOAT(-0x1.fffffep63f, -0x1fffffeL, 39), MAKE_HEX_FLOAT(-0x1.000002p63f, -0x1000002L, 39), MAKE_HEX_FLOAT(-0x1.0p63f, -0x1L, 63), MAKE_HEX_FLOAT(-0x1.fffffep62f, -0x1fffffeL, 38), + MAKE_HEX_FLOAT(-0x1.000002p32f, -0x1000002L, 8), MAKE_HEX_FLOAT(-0x1.0p32f, -0x1L, 32), MAKE_HEX_FLOAT(-0x1.fffffep31f, -0x1fffffeL, 7), MAKE_HEX_FLOAT(-0x1.000002p31f, -0x1000002L, 7), MAKE_HEX_FLOAT(-0x1.0p31f, -0x1L, 31), MAKE_HEX_FLOAT(-0x1.fffffep30f, -0x1fffffeL, 6), -1000.f, -100.f, -4.0f, -3.5f, + -3.0f, MAKE_HEX_FLOAT(-0x1.800002p1f, -0x1800002L, -23), -2.5f, MAKE_HEX_FLOAT(-0x1.7ffffep1f, -0x17ffffeL, -23), -2.0f, MAKE_HEX_FLOAT(-0x1.800002p0f, -0x1800002L, -24), -1.5f, MAKE_HEX_FLOAT(-0x1.7ffffep0f, -0x17ffffeL, -24),MAKE_HEX_FLOAT(-0x1.000002p0f, -0x1000002L, -24), -1.0f, MAKE_HEX_FLOAT(-0x1.fffffep-1f, -0x1fffffeL, -25), + MAKE_HEX_FLOAT(-0x1.000002p-1f, -0x1000002L, -25), -0.5f, MAKE_HEX_FLOAT(-0x1.fffffep-2f, -0x1fffffeL, -26), MAKE_HEX_FLOAT(-0x1.000002p-2f, -0x1000002L, -26), -0.25f, MAKE_HEX_FLOAT(-0x1.fffffep-3f, -0x1fffffeL, -27), + MAKE_HEX_FLOAT(-0x1.000002p-126f, -0x1000002L, -150), -FLT_MIN, MAKE_HEX_FLOAT(-0x0.fffffep-126f, -0x0fffffeL, -150), MAKE_HEX_FLOAT(-0x0.000ffep-126f, -0x0000ffeL, -150), MAKE_HEX_FLOAT(-0x0.0000fep-126f, -0x00000feL, -150), MAKE_HEX_FLOAT(-0x0.00000ep-126f, -0x000000eL, -150), MAKE_HEX_FLOAT(-0x0.00000cp-126f, -0x000000cL, -150), MAKE_HEX_FLOAT(-0x0.00000ap-126f, -0x000000aL, -150), + MAKE_HEX_FLOAT(-0x0.000008p-126f, -0x0000008L, -150), MAKE_HEX_FLOAT(-0x0.000006p-126f, -0x0000006L, -150), MAKE_HEX_FLOAT(-0x0.000004p-126f, -0x0000004L, -150), MAKE_HEX_FLOAT(-0x0.000002p-126f, -0x0000002L, -150), -0.0f, + + +NAN, +INFINITY, +FLT_MAX, MAKE_HEX_FLOAT(+0x1.000002p64f, +0x1000002L, 40), MAKE_HEX_FLOAT(+0x1.0p64f, +0x1L, 64), MAKE_HEX_FLOAT(+0x1.fffffep63f, +0x1fffffeL, 39), MAKE_HEX_FLOAT(+0x1.000002p63f, +0x1000002L, 39), MAKE_HEX_FLOAT(+0x1.0p63f, +0x1L, 63), MAKE_HEX_FLOAT(+0x1.fffffep62f, +0x1fffffeL, 38), + MAKE_HEX_FLOAT(+0x1.000002p32f, +0x1000002L, 8), MAKE_HEX_FLOAT(+0x1.0p32f, +0x1L, 32), MAKE_HEX_FLOAT(+0x1.fffffep31f, +0x1fffffeL, 7), MAKE_HEX_FLOAT(+0x1.000002p31f, +0x1000002L, 7), MAKE_HEX_FLOAT(+0x1.0p31f, +0x1L, 31), MAKE_HEX_FLOAT(+0x1.fffffep30f, +0x1fffffeL, 6), +1000.f, +100.f, +4.0f, +3.5f, + +3.0f, MAKE_HEX_FLOAT(+0x1.800002p1f, +0x1800002L, -23), 2.5f, MAKE_HEX_FLOAT(+0x1.7ffffep1f, +0x17ffffeL, -23),+2.0f, MAKE_HEX_FLOAT(+0x1.800002p0f, +0x1800002L, -24), 1.5f, MAKE_HEX_FLOAT(+0x1.7ffffep0f, +0x17ffffeL, -24), MAKE_HEX_FLOAT(+0x1.000002p0f, +0x1000002L, -24), +1.0f, MAKE_HEX_FLOAT(+0x1.fffffep-1f, +0x1fffffeL, -25), + MAKE_HEX_FLOAT(+0x1.000002p-1f, +0x1000002L, -25), +0.5f, MAKE_HEX_FLOAT(+0x1.fffffep-2f, +0x1fffffeL, -26), MAKE_HEX_FLOAT(+0x1.000002p-2f, +0x1000002L, -26), +0.25f, MAKE_HEX_FLOAT(+0x1.fffffep-3f, +0x1fffffeL, -27), + MAKE_HEX_FLOAT(0x1.000002p-126f, 0x1000002L, -150), +FLT_MIN, MAKE_HEX_FLOAT(+0x0.fffffep-126f, +0x0fffffeL, -150), MAKE_HEX_FLOAT(+0x0.000ffep-126f, +0x0000ffeL, -150), MAKE_HEX_FLOAT(+0x0.0000fep-126f, +0x00000feL, -150), MAKE_HEX_FLOAT(+0x0.00000ep-126f, +0x000000eL, -150), MAKE_HEX_FLOAT(+0x0.00000cp-126f, +0x000000cL, -150), MAKE_HEX_FLOAT(+0x0.00000ap-126f, +0x000000aL, -150), + MAKE_HEX_FLOAT(+0x0.000008p-126f, +0x0000008L, -150), MAKE_HEX_FLOAT(+0x0.000006p-126f, +0x0000006L, -150), MAKE_HEX_FLOAT(+0x0.000004p-126f, +0x0000004L, -150), MAKE_HEX_FLOAT(+0x0.000002p-126f, +0x0000002L, -150), +0.0f +}; +static size_t specialValuesFloatCount = sizeof( specialValuesFloat ) / sizeof( specialValuesFloat[0] ); + + +static const int specialValuesInt[] = { 0, 1, 2, 3, 126, 127, 128, 0x02000001, 0x04000001, 1465264071, 1488522147, + -1, -2, -3, -126, -127, -128, -0x02000001, -0x04000001, -1465264071, -1488522147 }; +static size_t specialValuesIntCount = sizeof( specialValuesInt ) / sizeof( specialValuesInt[0] ); + +//Thread specific data for a worker thread +typedef struct ThreadInfo +{ + cl_mem inBuf; // input buffer for the thread + cl_mem inBuf2; // input buffer for the thread + cl_mem outBuf[ VECTOR_SIZE_COUNT ]; // output buffers for the thread + float maxError; // max error value. Init to 0. + double maxErrorValue; // position of the max error value (param 1). Init to 0. + cl_int maxErrorValue2; // position of the max error value (param 2). Init to 0. + MTdata d; + cl_command_queue tQueue; // per thread command queue to improve performance +}ThreadInfo; + +typedef struct TestInfo +{ + size_t subBufferSize; // Size of the sub-buffer in elements + const Func *f; // A pointer to the function info + cl_program programs[ VECTOR_SIZE_COUNT ]; // programs for various vector sizes + cl_kernel *k[VECTOR_SIZE_COUNT ]; // arrays of thread-specific kernels for each worker thread: k[vector_size][thread_id] + ThreadInfo *tinfo; // An array of thread specific information for each worker thread + cl_uint threadCount; // Number of worker threads + cl_uint step; // step between each chunk and the next. + cl_uint scale; // stride between individual test values + float ulps; // max_allowed ulps + int ftz; // non-zero if running in flush to zero mode + + // no special values +}TestInfo; + +static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *p ); + +int TestFunc_Float_Float_Int(const Func *f, MTdata d) +{ + TestInfo test_info; + cl_int error; + size_t i, j; + float maxError = 0.0f; + double maxErrorVal = 0.0; + cl_int maxErrorVal2 = 0; + + logFunctionInfo(f->name,sizeof(cl_float),gTestFastRelaxed); + + // Init test_info + memset( &test_info, 0, sizeof( test_info ) ); + test_info.threadCount = GetThreadCount(); + test_info.subBufferSize = BUFFER_SIZE / (sizeof( cl_float) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = 1; + if (gWimpyMode) + { + test_info.subBufferSize = gWimpyBufferSize / (sizeof( cl_float) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = (cl_uint) sizeof(cl_float) * 2 * gWimpyReductionFactor; + } + test_info.step = (cl_uint) test_info.subBufferSize * test_info.scale; + test_info.f = f; + test_info.ulps = gIsEmbedded ? f->float_embedded_ulps : f->float_ulps; + test_info.ftz = f->ftz || gForceFTZ || 0 == (CL_FP_DENORM & gFloatCapabilities); + + // cl_kernels aren't thread safe, so we make one for each vector size for every thread + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + size_t array_size = test_info.threadCount * sizeof( cl_kernel ); + test_info.k[i] = (cl_kernel*)malloc( array_size ); + if( NULL == test_info.k[i] ) + { + vlog_error( "Error: Unable to allocate storage for kernels!\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.k[i], 0, array_size ); + } + test_info.tinfo = (ThreadInfo*)malloc( test_info.threadCount * sizeof(*test_info.tinfo) ); + if( NULL == test_info.tinfo ) + { + vlog_error( "Error: Unable to allocate storage for thread specific data.\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.tinfo, 0, test_info.threadCount * sizeof(*test_info.tinfo) ); + for( i = 0; i < test_info.threadCount; i++ ) + { + cl_buffer_region region = { i * test_info.subBufferSize * sizeof( cl_float), test_info.subBufferSize * sizeof( cl_float) }; + test_info.tinfo[i].inBuf = clCreateSubBuffer( gInBuffer, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + cl_buffer_region region2 = { i * test_info.subBufferSize * sizeof( cl_int), test_info.subBufferSize * sizeof( cl_int) }; + test_info.tinfo[i].inBuf2 = clCreateSubBuffer( gInBuffer2, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion2, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + test_info.tinfo[i].outBuf[j] = clCreateSubBuffer( gOutBuffer[j], CL_MEM_WRITE_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].outBuf[j] ) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + } + test_info.tinfo[i].tQueue = clCreateCommandQueueWithProperties(gContext, gDevice, 0, &error); + if( NULL == test_info.tinfo[i].tQueue || error ) + { + vlog_error( "clCreateCommandQueue failed. (%d)\n", error ); + goto exit; + } + test_info.tinfo[i].d = init_genrand(genrand_int32(d)); + } + + // Init the kernels + { + BuildKernelInfo build_info = { gMinVectorSizeIndex, test_info.threadCount, test_info.k, test_info.programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_FloatFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + goto exit; + } + + // Run the kernels + error = ThreadPool_Do( TestFloat, (cl_uint) ((1ULL<<32) / test_info.step), &test_info ); + + + // Accumulate the arithmetic errors + for( i = 0; i < test_info.threadCount; i++ ) + { + if( test_info.tinfo[i].maxError > maxError ) + { + maxError = test_info.tinfo[i].maxError; + maxErrorVal = test_info.tinfo[i].maxErrorValue; + maxErrorVal2 = test_info.tinfo[i].maxErrorValue2; + } + } + + if( error ) + goto exit; + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + + if( gMeasureTimes ) + { + //Init input arrays + uint32_t *p = (uint32_t *)gIn; + uint32_t *p2 = (uint32_t *)gIn2; + for( j = 0; j < BUFFER_SIZE / sizeof( float ); j++ ) + { + p[j] = (genrand_int32(d) & ~0x40000000) | 0x38000000; + p2[j] = 3; + } + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, BUFFER_SIZE, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, BUFFER_SIZE, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_float ) * sizeValues[j]; + size_t localCount = (BUFFER_SIZE + vectorSize - 1) / vectorSize; // BUFFER_SIZE / vectorSize rounded up + if( ( error = clSetKernelArg( test_info.k[j][0], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(test_info.programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( i = 0; i < PERF_LOOP_COUNT; i++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, test_info.k[j][0], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (BUFFER_SIZE / sizeof( float ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sf%s", f->name, sizeNames[j] ); + } + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t%8.2f @ {%a, %d}", maxError, maxErrorVal, maxErrorVal2 ); + vlog( "\n" ); + + +exit: + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + clReleaseProgram(test_info.programs[i]); + if( test_info.k[i] ) + { + for( j = 0; j < test_info.threadCount; j++ ) + clReleaseKernel(test_info.k[i][j]); + + free( test_info.k[i] ); + } + } + if( test_info.tinfo ) + { + for( i = 0; i < test_info.threadCount; i++ ) + { + free_mtdata(test_info.tinfo[i].d); + clReleaseMemObject(test_info.tinfo[i].inBuf); + clReleaseMemObject(test_info.tinfo[i].inBuf2); + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + clReleaseMemObject(test_info.tinfo[i].outBuf[j]); + clReleaseCommandQueue(test_info.tinfo[i].tQueue); + } + + free( test_info.tinfo ); + } + + return error; +} + + +static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *data ) +{ + const TestInfo *job = (const TestInfo *) data; + size_t buffer_elements = job->subBufferSize; + size_t buffer_size = buffer_elements * sizeof( cl_float ); + cl_uint base = job_id * (cl_uint) job->step; + ThreadInfo *tinfo = job->tinfo + thread_id; + float ulps = job->ulps; + fptr func = job->f->func; + int ftz = job->ftz; + MTdata d = tinfo->d; + cl_uint j, k; + cl_int error; + const char *name = job->f->name; + cl_uint *t; + cl_float *r,*s; + cl_int *s2; + + // start the map of the output arrays + cl_event e[ VECTOR_SIZE_COUNT ]; + cl_uint *out[ VECTOR_SIZE_COUNT ]; + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + out[j] = (uint32_t*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_WRITE, 0, buffer_size, 0, NULL, e + j, &error); + if( error || NULL == out[j]) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush failed\n" ); + + //Init input array + cl_uint *p = (cl_uint *)gIn + thread_id * buffer_elements; + cl_uint *p2 = (cl_uint *)gIn2 + thread_id * buffer_elements; + j = 0; + int totalSpecialValueCount = specialValuesFloatCount * specialValuesIntCount; + int indx = (totalSpecialValueCount - 1) / buffer_elements; + if( job_id <= (cl_uint)indx ) + { // test edge cases + float *fp = (float *)p; + cl_int *ip2 = (cl_int *)p2; + uint32_t x, y; + + x = (job_id * buffer_elements) % specialValuesFloatCount; + y = (job_id * buffer_elements) / specialValuesFloatCount; + + for( ; j < buffer_elements; j++ ) + { + fp[j] = specialValuesFloat[x]; + ip2[j] = specialValuesInt[y]; + if( ++x >= specialValuesFloatCount ) + { + x = 0; + y++; + if( y >= specialValuesIntCount ) + break; + } + } + } + + //Init any remaining values. + for( ; j < buffer_elements; j++ ) + { + p[j] = genrand_int32(d); + p2[j] = genrand_int32(d); + } + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf, CL_FALSE, 0, buffer_size, p, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf2, CL_FALSE, 0, buffer_size, p2, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + //Wait for the map to finish + if( (error = clWaitForEvents(1, e + j) )) + { + vlog_error( "Error: clWaitForEvents failed! err: %d\n", error ); + goto exit; + } + if( (error = clReleaseEvent( e[j] ) )) + { + vlog_error( "Error: clReleaseEvent failed! err: %d\n", error ); + goto exit; + } + + // Fill the result buffer with garbage, so that old results don't carry over + uint32_t pattern = 0xffffdead; + memset_pattern4(out[j], &pattern, buffer_size); + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueMapBuffer failed! err: %d\n", error ); + goto exit; + } + + // run the kernel + size_t vectorCount = (buffer_elements + sizeValues[j] - 1) / sizeValues[j]; + cl_kernel kernel = job->k[j][thread_id]; //each worker thread has its own copy of the cl_kernel + cl_program program = job->programs[j]; + + if( ( error = clSetKernelArg( kernel, 0, sizeof( tinfo->outBuf[j] ), &tinfo->outBuf[j] ))){ LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 1, sizeof( tinfo->inBuf ), &tinfo->inBuf ) )) { LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 2, sizeof( tinfo->inBuf2 ), &tinfo->inBuf2 ) )) { LogBuildError(program); return error; } + + if( (error = clEnqueueNDRangeKernel(tinfo->tQueue, kernel, 1, NULL, &vectorCount, NULL, 0, NULL, NULL))) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 2 failed\n" ); + + if( gSkipCorrectnessTesting ) + return CL_SUCCESS; + + //Calculate the correctly rounded reference result + r = (float *)gOut_Ref + thread_id * buffer_elements; + s = (float *)gIn + thread_id * buffer_elements; + s2 = (cl_int *)gIn2 + thread_id * buffer_elements; + for( j = 0; j < buffer_elements; j++ ) + r[j] = (float) func.f_fi( s[j], s2[j] ); + + // Read the data back -- no need to wait for the first N-1 buffers. This is an in order queue. + for( j = gMinVectorSizeIndex; j + 1 < gMaxVectorSizeIndex; j++ ) + { + out[j] = (uint32_t*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + } + + // Wait for the last buffer + out[j] = (uint32_t*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_TRUE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + + //Verify data + t = (cl_uint *)r; + for( j = 0; j < buffer_elements; j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + cl_uint *q = out[k]; + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + float test = ((float*) q)[j]; + double correct = func.f_fi( s[j], s2[j] ); + float err = Ulp_Error( test, correct ); + int fail = ! (fabsf(err) <= ulps); + + if( fail && ftz ) + { + // retry per section 6.5.3.2 + if( IsFloatResultSubnormal(correct, ulps ) ) + { + fail = fail && ( test != 0.0f ); + if( ! fail ) + err = 0.0f; + } + + // retry per section 6.5.3.3 + if( IsFloatSubnormal( s[j] ) ) + { + double correct2, correct3; + float err2, err3; + correct2 = func.f_fi( 0.0, s2[j] ); + correct3 = func.f_fi( -0.0, s2[j] ); + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal( correct2, ulps ) || IsFloatResultSubnormal( correct3, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + + if( fabsf(err ) > tinfo->maxError ) + { + tinfo->maxError = fabsf(err); + tinfo->maxErrorValue = s[j]; + tinfo->maxErrorValue2 = s2[j]; + } + if( fail ) + { + vlog_error( "\nERROR: %s%s: %f ulp error at {%a, %d}: *%a vs. %a (0x%8.8x) at index: %d\n", name, sizeNames[k], err, s[j], s2[j], r[j], test, ((cl_uint*)&test)[0], j ); + error = -1; + goto exit; + } + } + } + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL)) ) + { + vlog_error( "Error: clEnqueueUnmapMemObject %d failed 2! err: %d\n", j, error ); + return error; + } + } + + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 3 failed\n" ); + + + if( 0 == ( base & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10u scale:%10zu buf_elements:%10u ulps:%5.3f ThreadCount:%2u\n", base, job->step, job->scale, buffer_elements, job->ulps, job->threadCount); + } else + { + vlog("." ); + } + fflush(stdout); + } + +exit: + return error; + +} + + + +// A table of more difficult cases to get right +static const double specialValuesDouble[] = { + -NAN, -INFINITY, -DBL_MAX, MAKE_HEX_DOUBLE(-0x1.0000000000001p64, -0x10000000000001LL, 12), MAKE_HEX_DOUBLE(-0x1.0p64, -0x1LL, 64), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp63, -0x1fffffffffffffLL, 11), MAKE_HEX_DOUBLE(-0x1.0000000000001p63, -0x10000000000001LL, 11), MAKE_HEX_DOUBLE(-0x1.0p63, -0x1LL, 63), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp62, -0x1fffffffffffffLL, 10), + MAKE_HEX_DOUBLE(-0x1.000002p32, -0x1000002LL, 8), MAKE_HEX_DOUBLE(-0x1.0p32, -0x1LL, 32), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp31, -0x1fffffffffffffLL, -21), MAKE_HEX_DOUBLE(-0x1.0000000000001p31, -0x10000000000001LL, -21), MAKE_HEX_DOUBLE(-0x1.0p31, -0x1LL, 31), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp30, -0x1fffffffffffffLL, -22), -1000., -100., -4.0, -3.5, + -3.0, MAKE_HEX_DOUBLE(-0x1.8000000000001p1, -0x18000000000001LL, -51), -2.5, MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp1, -0x17ffffffffffffLL, -51), -2.0, MAKE_HEX_DOUBLE(-0x1.8000000000001p0, -0x18000000000001LL, -52), -1.5, MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp0, -0x17ffffffffffffLL, -52),MAKE_HEX_DOUBLE(-0x1.0000000000001p0, -0x10000000000001LL, -52), -1.0, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-1, -0x1fffffffffffffLL, -53), + MAKE_HEX_DOUBLE(-0x1.0000000000001p-1, -0x10000000000001LL, -53), -0.5, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-2, -0x1fffffffffffffLL, -54), MAKE_HEX_DOUBLE(-0x1.0000000000001p-2, -0x10000000000001LL, -54), -0.25, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-3, -0x1fffffffffffffLL, -55), + MAKE_HEX_DOUBLE(-0x1.0000000000001p-1022, -0x10000000000001LL, -1074), -DBL_MIN, MAKE_HEX_DOUBLE(-0x0.fffffffffffffp-1022, -0x0fffffffffffffLL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000fffp-1022, -0x00000000000fffLL, -1074), MAKE_HEX_DOUBLE(-0x0.00000000000fep-1022, -0x000000000000feLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000ep-1022, -0x0000000000000eLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000cp-1022, -0x0000000000000cLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000ap-1022, -0x0000000000000aLL, -1074), + MAKE_HEX_DOUBLE(-0x0.0000000000008p-1022, -0x00000000000008LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000007p-1022, -0x00000000000007LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000006p-1022, -0x00000000000006LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000005p-1022, -0x00000000000005LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000004p-1022, -0x00000000000004LL, -1074), + MAKE_HEX_DOUBLE(-0x0.0000000000003p-1022, -0x00000000000003LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000002p-1022, -0x00000000000002LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000001p-1022, -0x00000000000001LL, -1074), -0.0, + + +NAN, +INFINITY, +DBL_MAX, MAKE_HEX_DOUBLE(+0x1.0000000000001p64, +0x10000000000001LL, 12), MAKE_HEX_DOUBLE(+0x1.0p64, +0x1LL, 64), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp63, +0x1fffffffffffffLL, 11), MAKE_HEX_DOUBLE(+0x1.0000000000001p63, +0x10000000000001LL, 11), MAKE_HEX_DOUBLE(+0x1.0p63, +0x1LL, 63), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp62, +0x1fffffffffffffLL, 10), + MAKE_HEX_DOUBLE(+0x1.000002p32, +0x1000002LL, 8), MAKE_HEX_DOUBLE(+0x1.0p32, +0x1LL, 32), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp31, +0x1fffffffffffffLL, -21), MAKE_HEX_DOUBLE(+0x1.0000000000001p31, +0x10000000000001LL, -21), MAKE_HEX_DOUBLE(+0x1.0p31, +0x1LL, 31), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp30, +0x1fffffffffffffLL, -22), +1000., +100., +4.0, +3.5, + +3.0, MAKE_HEX_DOUBLE(+0x1.8000000000001p1, +0x18000000000001LL, -51), +2.5, MAKE_HEX_DOUBLE(+0x1.7ffffffffffffp1, +0x17ffffffffffffLL, -51), +2.0, MAKE_HEX_DOUBLE(+0x1.8000000000001p0, +0x18000000000001LL, -52), +1.5, MAKE_HEX_DOUBLE(+0x1.7ffffffffffffp0, +0x17ffffffffffffLL, -52),MAKE_HEX_DOUBLE(-0x1.0000000000001p0, -0x10000000000001LL, -52), +1.0, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-1, +0x1fffffffffffffLL, -53), + MAKE_HEX_DOUBLE(+0x1.0000000000001p-1, +0x10000000000001LL, -53), +0.5, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-2, +0x1fffffffffffffLL, -54), MAKE_HEX_DOUBLE(+0x1.0000000000001p-2, +0x10000000000001LL, -54), +0.25, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-3, +0x1fffffffffffffLL, -55), + MAKE_HEX_DOUBLE(+0x1.0000000000001p-1022, +0x10000000000001LL, -1074), +DBL_MIN, MAKE_HEX_DOUBLE(+0x0.fffffffffffffp-1022, +0x0fffffffffffffLL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000fffp-1022, +0x00000000000fffLL, -1074), MAKE_HEX_DOUBLE(+0x0.00000000000fep-1022, +0x000000000000feLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000ep-1022, +0x0000000000000eLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000cp-1022, +0x0000000000000cLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000ap-1022, +0x0000000000000aLL, -1074), + MAKE_HEX_DOUBLE(+0x0.0000000000008p-1022, +0x00000000000008LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000007p-1022, +0x00000000000007LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000006p-1022, +0x00000000000006LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000005p-1022, +0x00000000000005LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000004p-1022, +0x00000000000004LL, -1074), + MAKE_HEX_DOUBLE(+0x0.0000000000003p-1022, +0x00000000000003LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000002p-1022, +0x00000000000002LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000001p-1022, +0x00000000000001LL, -1074), +0.0, +}; +static size_t specialValuesDoubleCount = sizeof( specialValuesDouble ) / sizeof( specialValuesDouble[0] ); + +static const int specialValuesInt2[] = { 0, 1, 2, 3, 1022, 1023, 1024, INT_MIN, INT_MAX, + -1, -2, -3, -1022, -1023, -11024, -INT_MAX }; +static size_t specialValuesInt2Count = sizeof( specialValuesInt ) / sizeof( specialValuesInt[0] ); + +static cl_int TestDouble( cl_uint job_id, cl_uint thread_id, void *p ); + +int TestFunc_Double_Double_Int(const Func *f, MTdata d) +{ + TestInfo test_info; + cl_int error; + size_t i, j; + float maxError = 0.0f; + double maxErrorVal = 0.0; + cl_int maxErrorVal2 = 0; + + logFunctionInfo(f->name,sizeof(cl_double),gTestFastRelaxed); + + // Init test_info + memset( &test_info, 0, sizeof( test_info ) ); + test_info.threadCount = GetThreadCount(); + test_info.subBufferSize = BUFFER_SIZE / (sizeof( cl_double) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = 1; + if (gWimpyMode) + { + test_info.subBufferSize = gWimpyBufferSize / (sizeof( cl_double) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = (cl_uint) sizeof(cl_double) * 2 * gWimpyReductionFactor; + } + test_info.step = (cl_uint) test_info.subBufferSize * test_info.scale; + test_info.f = f; + test_info.ulps = f->double_ulps; + test_info.ftz = f->ftz || gForceFTZ; + + // cl_kernels aren't thread safe, so we make one for each vector size for every thread + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + size_t array_size = test_info.threadCount * sizeof( cl_kernel ); + test_info.k[i] = (cl_kernel*)malloc( array_size ); + if( NULL == test_info.k[i] ) + { + vlog_error( "Error: Unable to allocate storage for kernels!\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.k[i], 0, array_size ); + } + test_info.tinfo = (ThreadInfo*)malloc( test_info.threadCount * sizeof(*test_info.tinfo) ); + if( NULL == test_info.tinfo ) + { + vlog_error( "Error: Unable to allocate storage for thread specific data.\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.tinfo, 0, test_info.threadCount * sizeof(*test_info.tinfo) ); + for( i = 0; i < test_info.threadCount; i++ ) + { + cl_buffer_region region = { i * test_info.subBufferSize * sizeof( cl_double), test_info.subBufferSize * sizeof( cl_double) }; + test_info.tinfo[i].inBuf = clCreateSubBuffer( gInBuffer, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + cl_buffer_region region2 = { i * test_info.subBufferSize * sizeof( cl_int), test_info.subBufferSize * sizeof( cl_int) }; + test_info.tinfo[i].inBuf2 = clCreateSubBuffer( gInBuffer2, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion2, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + /* Qualcomm fix: 9461 read-write flags must be compatible with parent buffer */ + test_info.tinfo[i].outBuf[j] = clCreateSubBuffer( gOutBuffer[j], CL_MEM_WRITE_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + /* Qualcomm fix: end */ + if( error || NULL == test_info.tinfo[i].outBuf[j] ) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + } + test_info.tinfo[i].tQueue = clCreateCommandQueueWithProperties(gContext, gDevice, 0, &error); + if( NULL == test_info.tinfo[i].tQueue || error ) + { + vlog_error( "clCreateCommandQueue failed. (%d)\n", error ); + goto exit; + } + + test_info.tinfo[i].d = init_genrand(genrand_int32(d)); + } + + + // Init the kernels + { + BuildKernelInfo build_info = { gMinVectorSizeIndex, test_info.threadCount, test_info.k, test_info.programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_DoubleFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + goto exit; + } + + // Run the kernels + if( !gSkipCorrectnessTesting ) + error = ThreadPool_Do( TestDouble, (cl_uint) ((1ULL<<32) / test_info.step), &test_info ); + + + // Accumulate the arithmetic errors + for( i = 0; i < test_info.threadCount; i++ ) + { + if( test_info.tinfo[i].maxError > maxError ) + { + maxError = test_info.tinfo[i].maxError; + maxErrorVal = test_info.tinfo[i].maxErrorValue; + maxErrorVal2 = test_info.tinfo[i].maxErrorValue2; + } + } + + if( error ) + goto exit; + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input arrays + double *p = (double *)gIn; + cl_int *p2 = (cl_int *)gIn2; + for( j = 0; j < BUFFER_SIZE / sizeof( cl_double ); j++ ) + { + p[j] = DoubleFromUInt32(genrand_int32(d)); + p2[j] = 3; + } + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, BUFFER_SIZE, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, BUFFER_SIZE/2, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_double ) * sizeValues[j]; + size_t localCount = (BUFFER_SIZE + vectorSize - 1) / vectorSize; // BUFFER_SIZE / vectorSize rounded up + if( ( error = clSetKernelArg( test_info.k[j][0], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(test_info.programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( i = 0; i < PERF_LOOP_COUNT; i++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, test_info.k[j][0], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (BUFFER_SIZE / sizeof( double ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sD%s", f->name, sizeNames[j] ); + } + for( ; j < gMaxVectorSizeIndex; j++ ) + vlog( "\t -- " ); + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t%8.2f @ {%a, %d}", maxError, maxErrorVal, maxErrorVal2 ); + vlog( "\n" ); + + +exit: + // Release + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + clReleaseProgram(test_info.programs[i]); + if( test_info.k[i] ) + { + for( j = 0; j < test_info.threadCount; j++ ) + clReleaseKernel(test_info.k[i][j]); + + free( test_info.k[i] ); + } + } + if( test_info.tinfo ) + { + for( i = 0; i < test_info.threadCount; i++ ) + { + free_mtdata(test_info.tinfo[i].d); + clReleaseMemObject(test_info.tinfo[i].inBuf); + clReleaseMemObject(test_info.tinfo[i].inBuf2); + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + clReleaseMemObject(test_info.tinfo[i].outBuf[j]); + clReleaseCommandQueue(test_info.tinfo[i].tQueue); + } + + free( test_info.tinfo ); + } + + return error; +} + +static cl_int TestDouble( cl_uint job_id, cl_uint thread_id, void *data ) +{ + const TestInfo *job = (const TestInfo *) data; + size_t buffer_elements = job->subBufferSize; + size_t buffer_size = buffer_elements * sizeof( cl_double ); + cl_uint base = job_id * (cl_uint) job->step; + ThreadInfo *tinfo = job->tinfo + thread_id; + float ulps = job->ulps; + dptr func = job->f->dfunc; + int ftz = job->ftz; + MTdata d = tinfo->d; + cl_uint j, k; + cl_int error; + const char *name = job->f->name; + cl_ulong *t; + cl_double *r,*s; + cl_int *s2; + + Force64BitFPUPrecision(); + + // start the map of the output arrays + cl_event e[ VECTOR_SIZE_COUNT ]; + cl_ulong *out[ VECTOR_SIZE_COUNT ]; + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_ulong*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_WRITE, 0, buffer_size, 0, NULL, e + j, &error); + if( error || NULL == out[j]) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush failed\n" ); + + //Init input array + cl_ulong *p = (cl_ulong *)gIn + thread_id * buffer_elements; + cl_int *p2 = (cl_int *)gIn2 + thread_id * buffer_elements; + j = 0; + int totalSpecialValueCount = specialValuesDoubleCount * specialValuesInt2Count; + int indx = (totalSpecialValueCount - 1) / buffer_elements; + if( job_id <= (cl_uint)indx ) + { // test edge cases + cl_double *fp = (cl_double *)p; + cl_int *ip2 = (cl_int *)p2; + uint32_t x, y; + + x = (job_id * buffer_elements) % specialValuesDoubleCount; + y = (job_id * buffer_elements) / specialValuesDoubleCount; + + for( ; j < buffer_elements; j++ ) + { + fp[j] = specialValuesDouble[x]; + ip2[j] = specialValuesInt2[y]; + if( ++x >= specialValuesDoubleCount ) + { + x = 0; + y++; + if( y >= specialValuesInt2Count ) + break; + } + } + } + + //Init any remaining values. + for( ; j < buffer_elements; j++ ) + { + p[j] = DoubleFromUInt32(genrand_int32(d)); + p2[j] = genrand_int32(d); + } + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf, CL_FALSE, 0, buffer_size, p, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf2, CL_FALSE, 0, buffer_size/2, p2, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + //Wait for the map to finish + if( (error = clWaitForEvents(1, e + j) )) + { + vlog_error( "Error: clWaitForEvents failed! err: %d\n", error ); + goto exit; + } + if( (error = clReleaseEvent( e[j] ) )) + { + vlog_error( "Error: clReleaseEvent failed! err: %d\n", error ); + goto exit; + } + + // Fill the result buffer with garbage, so that old results don't carry over + uint32_t pattern = 0xffffdead; + memset_pattern4(out[j], &pattern, buffer_size); + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueMapBuffer failed! err: %d\n", error ); + goto exit; + } + + // run the kernel + size_t vectorCount = (buffer_elements + sizeValues[j] - 1) / sizeValues[j]; + cl_kernel kernel = job->k[j][thread_id]; //each worker thread has its own copy of the cl_kernel + cl_program program = job->programs[j]; + + if( ( error = clSetKernelArg( kernel, 0, sizeof( tinfo->outBuf[j] ), &tinfo->outBuf[j] ))){ LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 1, sizeof( tinfo->inBuf ), &tinfo->inBuf ) )) { LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 2, sizeof( tinfo->inBuf2 ), &tinfo->inBuf2 ) )) { LogBuildError(program); return error; } + + if( (error = clEnqueueNDRangeKernel(tinfo->tQueue, kernel, 1, NULL, &vectorCount, NULL, 0, NULL, NULL))) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 2 failed\n" ); + + if( gSkipCorrectnessTesting ) + return CL_SUCCESS; + + //Calculate the correctly rounded reference result + r = (cl_double *)gOut_Ref + thread_id * buffer_elements; + s = (cl_double *)gIn + thread_id * buffer_elements; + s2 = (cl_int *)gIn2 + thread_id * buffer_elements; + for( j = 0; j < buffer_elements; j++ ) + r[j] = (cl_double) func.f_fi( s[j], s2[j] ); + + // Read the data back -- no need to wait for the first N-1 buffers. This is an in order queue. + for( j = gMinVectorSizeIndex; j + 1 < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_ulong*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + } + + // Wait for the last buffer + out[j] = (cl_ulong*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_TRUE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + + //Verify data + t = (cl_ulong *)r; + for( j = 0; j < buffer_elements; j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + cl_ulong *q = out[k]; + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + cl_double test = ((cl_double*) q)[j]; + long double correct = func.f_fi( s[j], s2[j] ); + float err = Ulp_Error_Double( test, correct ); + int fail = ! (fabsf(err) <= ulps); + + if( fail && ftz ) + { + // retry per section 6.5.3.2 + if( IsDoubleResultSubnormal(correct, ulps ) ) + { + fail = fail && ( test != 0.0f ); + if( ! fail ) + err = 0.0f; + } + + // retry per section 6.5.3.3 + if( IsDoubleSubnormal( s[j] ) ) + { + long double correct2 = func.f_fi( 0.0, s2[j] ); + long double correct3 = func.f_fi( -0.0, s2[j] ); + float err2 = Ulp_Error_Double( test, correct2 ); + float err3 = Ulp_Error_Double( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, ulps ) || IsDoubleResultSubnormal( correct3, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + + if( fabsf(err ) > tinfo->maxError ) + { + tinfo->maxError = fabsf(err); + tinfo->maxErrorValue = s[j]; + tinfo->maxErrorValue2 = s2[j]; + } + if( fail ) + { + vlog_error( "\nERROR: %s%s: %f ulp error at {%.13la, %d}: *%.13la vs. %.13la\n", name, sizeNames[k], err, s[j], s2[j], r[j], test ); + error = -1; + goto exit; + } + } + } + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL)) ) + { + vlog_error( "Error: clEnqueueUnmapMemObject %d failed 2! err: %d\n", j, error ); + return error; + } + } + + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 3 failed\n" ); + + + if( 0 == ( base & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10u scale:%10u buf_elements:%10zd ulps:%5.3f ThreadCount:%2u\n", base, job->step, job->scale, buffer_elements, job->ulps, job->threadCount); + } else + { + vlog("." ); + } + fflush(stdout); + } + +exit: + return error; + +} + + + diff --git a/test_conformance/math_brute_force/binary_two_results_i.c b/test_conformance/math_brute_force/binary_two_results_i.c new file mode 100644 index 00000000..ab06c450 --- /dev/null +++ b/test_conformance/math_brute_force/binary_two_results_i.c @@ -0,0 +1,1133 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Utility.h" + +#include +#include +#include "FunctionList.h" + +#define PARALLEL_REFERENCE + +int TestFunc_FloatI_Float_Float(const Func *f, MTdata); +int TestFunc_DoubleI_Double_Double(const Func *f, MTdata); + +#if defined( __cplusplus ) + extern "C" +#endif +const vtbl _binary_two_results_i = { "binary_two_results_i", TestFunc_FloatI_Float_Float, TestFunc_DoubleI_Double_Double }; + +static int BuildKernel( const char *name, int vectorSize, cl_kernel *k, cl_program *p ); +static int BuildKernelDouble( const char *name, int vectorSize, cl_kernel *k, cl_program *p ); + +static int BuildKernel( const char *name, int vectorSize, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global float", sizeNames[vectorSize], "* out, __global int", sizeNames[vectorSize], "* out2, __global float", sizeNames[vectorSize], "* in1, __global float", sizeNames[vectorSize], "* in2)\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in1[i], in2[i], out2 + i );\n" + "}\n" + }; + + const char *c3[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global float* out, __global int* out2, __global float* in, __global float* in2)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " float3 f0 = vload3( 0, in + 3 * i );\n" + " float3 f1 = vload3( 0, in2 + 3 * i );\n" + " int3 i0 = 0xdeaddead;\n" + " f0 = ", name, "( f0, f1, &i0 );\n" + " vstore3( f0, 0, out + 3*i );\n" + " vstore3( i0, 0, out2 + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " float3 f0, f1;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (float3)( in[3*i], NAN, NAN ); \n" + " f1 = (float3)( in2[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " f0 = (float3)( in[3*i], in[3*i+1], NAN ); \n" + " f1 = (float3)( in2[3*i], in2[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " int3 i0 = 0xdeaddead;\n" + " f0 = ", name, "( f0, f1, &i0 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = f0.y; \n" + " out2[3*i+1] = i0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = f0.x; \n" + " out2[3*i] = i0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernel(kern, (cl_uint) kernSize, testName, k, p); +} + +static int BuildKernelDouble( const char *name, int vectorSize, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double", sizeNames[vectorSize], "* out, __global int", sizeNames[vectorSize], "* out2, __global double", sizeNames[vectorSize], "* in1, __global double", sizeNames[vectorSize], "* in2)\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in1[i], in2[i], out2 + i );\n" + "}\n" + }; + + const char *c3[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double* out, __global int* out2, __global double* in, __global double* in2)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " double3 d0 = vload3( 0, in + 3 * i );\n" + " double3 d1 = vload3( 0, in2 + 3 * i );\n" + " int3 i0 = 0xdeaddead;\n" + " d0 = ", name, "( d0, d1, &i0 );\n" + " vstore3( d0, 0, out + 3*i );\n" + " vstore3( i0, 0, out2 + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " double3 d0, d1;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " d0 = (double3)( in[3*i], NAN, NAN ); \n" + " d1 = (double3)( in2[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " d0 = (double3)( in[3*i], in[3*i+1], NAN ); \n" + " d1 = (double3)( in2[3*i], in2[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " int3 i0 = 0xdeaddead;\n" + " d0 = ", name, "( d0, d1, &i0 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = d0.y; \n" + " out2[3*i+1] = i0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = d0.x; \n" + " out2[3*i] = i0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernel(kern, (cl_uint) kernSize, testName, k, p); +} + +typedef struct BuildKernelInfo +{ + cl_uint offset; // the first vector size to build + cl_kernel *kernels; + cl_program *programs; + const char *nameInCode; +}BuildKernelInfo; + +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernel( info->nameInCode, i, info->kernels + i, info->programs + i ); +} + +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernelDouble( info->nameInCode, i, info->kernels + i, info->programs + i ); +} + +#if defined PARALLEL_REFERENCE +typedef struct ComputeReferenceInfoF_ +{ + const float *x; + const float *y; + float *r; + int *i; + double (*f_ffpI)(double, double, int*); + cl_uint lim; + cl_uint count; +} ComputeReferenceInfoF; + +typedef struct ComputeReferenceInfoD_ +{ + const double *x; + const double *y; + double *r; + int *i; + long double (*f_ffpI)(long double, long double, int*); + cl_uint lim; + cl_uint count; +} ComputeReferenceInfoD; + +static cl_int +ReferenceF(cl_uint jid, cl_uint tid, void *userInfo) +{ + ComputeReferenceInfoF *cri = (ComputeReferenceInfoF *)userInfo; + cl_uint lim = cri->lim; + cl_uint count = cri->count; + cl_uint off = jid * count; + const float *x = cri->x + off; + const float *y = cri->y + off; + float *r = cri->r + off; + int *i = cri->i + off; + double (*f)(double, double, int *) = cri->f_ffpI; + cl_uint j; + + if (off + count > lim) + count = lim - off; + + for (j = 0; j < count; ++j) + r[j] = (float)f((double)x[j], (double)y[j], i + j); + + return CL_SUCCESS; +} + +static cl_int +ReferenceD(cl_uint jid, cl_uint tid, void *userInfo) +{ + ComputeReferenceInfoD *cri = (ComputeReferenceInfoD *)userInfo; + cl_uint lim = cri->lim; + cl_uint count = cri->count; + cl_uint off = jid * count; + const double *x = cri->x + off; + const double *y = cri->y + off; + double *r = cri->r + off; + int *i = cri->i + off; + long double (*f)(long double, long double, int *) = cri->f_ffpI; + cl_uint j; + + if (off + count > lim) + count = lim - off; + + Force64BitFPUPrecision(); + + for (j = 0; j < count; ++j) + r[j] = (double)f((long double)x[j], (long double)y[j], i + j); + + return CL_SUCCESS; +} + +#endif + +int TestFunc_FloatI_Float_Float(const Func *f, MTdata d) +{ + uint64_t i; + uint32_t j, k; + int error; + cl_program programs[ VECTOR_SIZE_COUNT ]; + cl_kernel kernels[ VECTOR_SIZE_COUNT ]; + float maxError = 0.0f; + float float_ulps; + int64_t maxError2 = 0; + int ftz = f->ftz || gForceFTZ || 0 == (CL_FP_DENORM & gFloatCapabilities); + float maxErrorVal = 0.0f; + float maxErrorVal2 = 0.0f; + size_t bufferSize = (gWimpyMode)? gWimpyBufferSize: BUFFER_SIZE; + uint64_t step = bufferSize / sizeof( float ); + +#if defined PARALLEL_REFERENCE + cl_uint threadCount = GetThreadCount(); +#endif + logFunctionInfo(f->name,sizeof(cl_float),gTestFastRelaxed); + + if(gWimpyMode ){ + step = (1ULL<<32) * gWimpyReductionFactor / (512); + } + + if( gIsEmbedded ) + float_ulps = f->float_embedded_ulps; + else + float_ulps = f->float_ulps; + + int testingRemquo = !strcmp(f->name, "remquo"); + + // Init the kernels + { + BuildKernelInfo build_info = { gMinVectorSizeIndex, kernels, programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_FloatFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + return error; + } +/* + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + if( (error = BuildKernel( f->nameInCode, (int) i, kernels + i, programs + i) ) ) + return error; +*/ + + for( i = 0; i < (1ULL<<32); i += step ) + { + //Init input array + cl_uint *p = (cl_uint *)gIn; + cl_uint *p2 = (cl_uint *)gIn2; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + p[j] = genrand_int32(d); + p2[j] = genrand_int32(d); + } + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_TRUE, 0, bufferSize, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + + // write garbage into output arrays + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + uint32_t pattern = 0xffffdead; + memset_pattern4(gOut[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer[j], CL_FALSE, 0, bufferSize, gOut[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2(%d) ***\n", error, j ); + goto exit; + } + + memset_pattern4(gOut2[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer2[j], CL_FALSE, 0, bufferSize, gOut2[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2b(%d) ***\n", error, j ); + goto exit; + } + } + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_float ) * sizeValues[j]; + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; // bufferSize / vectorSize rounded up + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gOutBuffer2[j] ), &gOutBuffer2[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 3, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(programs[j]); goto exit; } + + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(gQueue) )) + vlog( "clFlush failed\n" ); + + // Calculate the correctly rounded reference result + float *s = (float *)gIn; + float *s2 = (float *)gIn2; + +#if defined PARALLEL_REFERENCE + if (threadCount > 1) { + ComputeReferenceInfoF cri; + cri.x = s; + cri.y = s2; + cri.r = (float *)gOut_Ref; + cri.i = (int *)gOut_Ref2; + cri.f_ffpI = f->func.f_ffpI; + cri.lim = bufferSize / sizeof( float ); + cri.count = (cri.lim + threadCount - 1) / threadCount; + ThreadPool_Do(ReferenceF, threadCount, &cri); + } else { +#endif + float *r = (float *)gOut_Ref; + int *r2 = (int *)gOut_Ref2; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + r[j] = (float) f->func.f_ffpI( s[j], s2[j], r2+j ); +#if defined PARALLEL_REFERENCE + } +#endif + + // Read the data back + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0, bufferSize, gOut[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray failed %d\n", error ); + goto exit; + } + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer2[j], CL_TRUE, 0, bufferSize, gOut2[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray2 failed %d\n", error ); + goto exit; + } + } + + if( gSkipCorrectnessTesting ) + break; + + //Verify data + uint32_t *t = (uint32_t *)gOut_Ref; + int32_t *t2 = (int32_t *)gOut_Ref2; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + uint32_t *q = (uint32_t *)gOut[k]; + int32_t *q2 = (int32_t *)gOut2[k]; + + // Check for exact match to correctly rounded result + if (t[j] == q[j] && t2[j] == q2[j]) + continue; + + // Check for paired NaNs + if ((t[j] & 0x7fffffff) > 0x7f800000 && (q[j] & 0x7fffffff) > 0x7f800000 && t2[j] == q2[j]) + continue; + + // if( t[j] != q[j] || t2[j] != q2[j] ) + { + float test = ((float*) q)[j]; + int correct2 = INT_MIN; + double correct = f->func.f_ffpI( s[j], s2[j], &correct2 ); + float err = Ulp_Error( test, correct ); + int64_t iErr; + + // in case of remquo, we only care about the sign and last seven bits of + // integer as per the spec. + if(testingRemquo) + iErr = (long long) (q2[j] & 0x0000007f) - (long long) (correct2 & 0x0000007f); + else + iErr = (long long) q2[j] - (long long) correct2; + + //For remquo, if y = 0, x is infinite, or either is NaN then the standard either neglects + //to say what is returned in iptr or leaves it undefined or implementation defined. + int iptrUndefined = fabs(((float*) gIn)[j]) == INFINITY || + ((float*) gIn2)[j] == 0.0f || + isnan(((float*) gIn2)[j]) || + isnan(((float*) gIn)[j]); + if(iptrUndefined) + iErr = 0; + + int fail = ! (fabsf(err) <= float_ulps && iErr == 0 ); + if( ftz && fail ) + { + // retry per section 6.5.3.2 + if( IsFloatResultSubnormal(correct, float_ulps ) ) + { + fail = fail && ! ( test == 0.0f && iErr == 0 ); + if( ! fail ) + err = 0.0f; + } + + // retry per section 6.5.3.3 + if( IsFloatSubnormal( s[j] ) ) + { + int correct3i, correct4i; + double correct3 = f->func.f_ffpI( 0.0, s2[j], &correct3i ); + double correct4 = f->func.f_ffpI( -0.0, s2[j], &correct4i ); + float err2 = Ulp_Error( test, correct3 ); + float err3 = Ulp_Error( test, correct4 ); + int64_t iErr3 = (long long) q2[j] - (long long) correct3i; + int64_t iErr4 = (long long) q2[j] - (long long) correct4i; + fail = fail && ((!(fabsf(err2) <= float_ulps && iErr3 == 0)) && (!(fabsf(err3) <= float_ulps && iErr4 == 0))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( llabs(iErr3) < llabs( iErr ) ) + iErr = iErr3; + if( llabs(iErr4) < llabs( iErr ) ) + iErr = iErr4; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal(correct2, float_ulps ) || IsFloatResultSubnormal(correct3, float_ulps ) ) + { + fail = fail && ! ( test == 0.0f && (iErr3 == 0 || iErr4 == 0) ); + if( ! fail ) + err = 0.0f; + } + + //try with both args as zero + if( IsFloatSubnormal( s2[j] ) ) + { + int correct7i, correct8i; + correct3 = f->func.f_ffpI( 0.0, 0.0, &correct3i ); + correct4 = f->func.f_ffpI( -0.0, 0.0, &correct4i ); + double correct7 = f->func.f_ffpI( 0.0, -0.0, &correct7i ); + double correct8 = f->func.f_ffpI( -0.0, -0.0, &correct8i ); + err2 = Ulp_Error( test, correct3 ); + err3 = Ulp_Error( test, correct4 ); + float err4 = Ulp_Error( test, correct7 ); + float err5 = Ulp_Error( test, correct8 ); + iErr3 = (long long) q2[j] - (long long) correct3i; + iErr4 = (long long) q2[j] - (long long) correct4i; + int64_t iErr7 = (long long) q2[j] - (long long) correct7i; + int64_t iErr8 = (long long) q2[j] - (long long) correct8i; + fail = fail && ((!(fabsf(err2) <= float_ulps && iErr3 == 0)) && (!(fabsf(err3) <= float_ulps && iErr4 == 0)) && + (!(fabsf(err4) <= float_ulps && iErr7 == 0)) && (!(fabsf(err5) <= float_ulps && iErr8 == 0))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + if( llabs(iErr3) < llabs( iErr ) ) + iErr = iErr3; + if( llabs(iErr4) < llabs( iErr ) ) + iErr = iErr4; + if( llabs(iErr7) < llabs( iErr ) ) + iErr = iErr7; + if( llabs(iErr8) < llabs( iErr ) ) + iErr = iErr8; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal(correct3, float_ulps ) || IsFloatResultSubnormal(correct4, float_ulps ) || + IsFloatResultSubnormal(correct7, float_ulps ) || IsFloatResultSubnormal(correct8, float_ulps ) ) + { + fail = fail && ! ( test == 0.0f && (iErr3 == 0 || iErr4 == 0 || iErr7 == 0 || iErr8 == 0)); + if( ! fail ) + err = 0.0f; + } + } + } + else if( IsFloatSubnormal( s2[j] ) ) + { + int correct3i, correct4i; + double correct3 = f->func.f_ffpI( s[j], 0.0, &correct3i ); + double correct4 = f->func.f_ffpI( s[j], -0.0, &correct4i ); + float err2 = Ulp_Error( test, correct3 ); + float err3 = Ulp_Error( test, correct4 ); + int64_t iErr3 = (long long) q2[j] - (long long) correct3i; + int64_t iErr4 = (long long) q2[j] - (long long) correct4i; + fail = fail && ((!(fabsf(err2) <= float_ulps && iErr3 == 0)) && (!(fabsf(err3) <= float_ulps && iErr4 == 0))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( llabs(iErr3) < llabs( iErr ) ) + iErr = iErr3; + if( llabs(iErr4) < llabs( iErr ) ) + iErr = iErr4; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal(correct2, float_ulps ) || IsFloatResultSubnormal(correct3, float_ulps ) ) + { + fail = fail && ! ( test == 0.0f && (iErr3 == 0 || iErr4 == 0) ); + if( ! fail ) + err = 0.0f; + } + } + } + if( fabsf(err ) > maxError ) + { + maxError = fabsf(err); + maxErrorVal = s[j]; + } + if( llabs(iErr) > maxError2 ) + { + maxError2 = llabs(iErr ); + maxErrorVal2 = s[j]; + } + + if( fail ) + { + vlog_error( "\nERROR: %s%s: {%f, %lld} ulp error at {%a, %a} ({0x%8.8x, 0x%8.8x}): *{%a, %d} ({0x%8.8x, 0x%8.8x}) vs. {%a, %d} ({0x%8.8x, 0x%8.8x})\n", + f->name, sizeNames[k], err, iErr, + ((float*) gIn)[j], ((float*) gIn2)[j], + ((cl_uint*) gIn)[j], ((cl_uint*) gIn2)[j], + ((float*) gOut_Ref)[j], ((int*) gOut_Ref2)[j], + ((cl_uint*) gOut_Ref)[j], ((cl_uint*) gOut_Ref2)[j], + test, q2[j], + ((cl_uint*)&test)[0], ((cl_uint*) q2)[j] ); + error = -1; + goto exit; + } + } + } + } + + if( 0 == (i & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10zu bufferSize:%10zd \n", i, step, bufferSize); + } else + { + vlog("." ); + } + fflush(stdout); + + } + } + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input array + uint32_t *p = (uint32_t *)gIn; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + p[j] = genrand_int32(d); + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, bufferSize, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_float ) * sizeValues[j]; + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; // bufferSize / vectorSize rounded up + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gOutBuffer2[j] ), &gOutBuffer2[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 3, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( k = 0; k < PERF_LOOP_COUNT; k++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (bufferSize / sizeof( float ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sf%s", f->name, sizeNames[j] ); + } + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t{%8.2f, %lld} @ %a", maxError, maxError2, maxErrorVal ); + vlog( "\n" ); + +exit: + // Release + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + clReleaseKernel(kernels[k]); + clReleaseProgram(programs[k]); + } + + return error; +} + +int TestFunc_DoubleI_Double_Double(const Func *f, MTdata d) +{ + uint64_t i; + uint32_t j, k; + int error; + cl_program programs[ VECTOR_SIZE_COUNT ]; + cl_kernel kernels[ VECTOR_SIZE_COUNT ]; + float maxError = 0.0f; + int64_t maxError2 = 0; + int ftz = f->ftz || gForceFTZ; + double maxErrorVal = 0.0f; + double maxErrorVal2 = 0.0f; + size_t bufferSize = (gWimpyMode)? gWimpyBufferSize: BUFFER_SIZE; + uint64_t step = bufferSize / sizeof( double ); + + logFunctionInfo(f->name,sizeof(cl_double),gTestFastRelaxed); + if(gWimpyMode ){ + step = (1ULL<<32) * gWimpyReductionFactor / (512); + } + +#if defined PARALLEL_REFERENCE + cl_uint threadCount = GetThreadCount(); +#endif + + Force64BitFPUPrecision(); + + int testingRemquo = !strcmp(f->name, "remquo"); + + // Init the kernels + { + BuildKernelInfo build_info = { gMinVectorSizeIndex, kernels, programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_DoubleFn, + gMaxVectorSizeIndex - gMinVectorSizeIndex, + &build_info ) )) + { + return error; + } + } +/* + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + if( (error = BuildKernelDouble( f->nameInCode, (int) i, kernels + i, programs + i) ) ) + return error; +*/ + + for( i = 0; i < (1ULL<<32); i += step ) + { + //Init input array + double *p = (double *)gIn; + double *p2 = (double *)gIn2; + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + { + p[j] = DoubleFromUInt32(genrand_int32(d)); + p2[j] = DoubleFromUInt32(genrand_int32(d)); + } + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_TRUE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_TRUE, 0, bufferSize, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + + // write garbage into output arrays + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + uint32_t pattern = 0xffffdead; + memset_pattern4(gOut[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0, bufferSize, gOut[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2(%d) ***\n", error, j ); + goto exit; + } + + memset_pattern4(gOut2[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer2[j], CL_TRUE, 0, bufferSize, gOut2[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2b(%d) ***\n", error, j ); + goto exit; + } + } + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_double ) * sizeValues[j]; + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; // bufferSize / vectorSize rounded up + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gOutBuffer2[j] ), &gOutBuffer2[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 3, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(programs[j]); goto exit; } + + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(gQueue) )) + vlog( "clFlush failed\n" ); + + //Calculate the correctly rounded reference result + double *s = (double *)gIn; + double *s2 = (double *)gIn2; + +#if defined PARALLEL_REFERENCE + if (threadCount > 1) { + ComputeReferenceInfoD cri; + cri.x = s; + cri.y = s2; + cri.r = (double *)gOut_Ref; + cri.i = (int *)gOut_Ref2; + cri.f_ffpI = f->dfunc.f_ffpI; + cri.lim = bufferSize / sizeof( double ); + cri.count = (cri.lim + threadCount - 1) / threadCount; + ThreadPool_Do(ReferenceD, threadCount, &cri); + } else { +#endif + double *r = (double *)gOut_Ref; + int *r2 = (int *)gOut_Ref2; + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + r[j] = (double) f->dfunc.f_ffpI( s[j], s2[j], r2+j ); +#if defined PARALLEL_REFERENCE + } +#endif + + // Read the data back + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0, bufferSize, gOut[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray failed %d\n", error ); + goto exit; + } + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer2[j], CL_TRUE, 0, bufferSize, gOut2[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray2 failed %d\n", error ); + goto exit; + } + } + + if( gSkipCorrectnessTesting ) + break; + + //Verify data + uint64_t *t = (uint64_t *)gOut_Ref; + int32_t *t2 = (int32_t *)gOut_Ref2; + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + uint64_t *q = (uint64_t *)gOut[k]; + int32_t *q2 = (int32_t *)gOut2[k]; + + // Check for exact match to correctly rounded result + if (t[j] == q[j] && t2[j] == q2[j]) + continue; + + // Check for paired NaNs + if ((t[j] & 0x7fffffffffffffffUL) > 0x7ff0000000000000UL && + (q[j] & 0x7fffffffffffffffUL) > 0x7ff0000000000000UL && + t2[j] == q2[j]) + continue; + + // if( t[j] != q[j] || t2[j] != q2[j] ) + { + double test = ((double*) q)[j]; + int correct2 = INT_MIN; + long double correct = f->dfunc.f_ffpI( s[j], s2[j], &correct2 ); + float err = Ulp_Error_Double( test, correct ); + int64_t iErr; + + // in case of remquo, we only care about the sign and last seven bits of + // integer as per the spec. + if(testingRemquo) + iErr = (long long) (q2[j] & 0x0000007f) - (long long) (correct2 & 0x0000007f); + else + iErr = (long long) q2[j] - (long long) correct2; + + //For remquo, if y = 0, x is infinite, or either is NaN then the standard either neglects + //to say what is returned in iptr or leaves it undefined or implementation defined. + int iptrUndefined = fabs(((double*) gIn)[j]) == INFINITY || + ((double*) gIn2)[j] == 0.0 || + isnan(((double*) gIn2)[j]) || + isnan(((double*) gIn)[j]); + if(iptrUndefined) + iErr = 0; + + int fail = ! (fabsf(err) <= f->double_ulps && iErr == 0 ); + if( ftz && fail ) + { + // retry per section 6.5.3.2 + if( IsDoubleResultSubnormal(correct, f->double_ulps ) ) + { + fail = fail && ! ( test == 0.0f && iErr == 0 ); + if( ! fail ) + err = 0.0f; + } + + // retry per section 6.5.3.3 + if( IsDoubleSubnormal( s[j] ) ) + { + int correct3i, correct4i; + long double correct3 = f->dfunc.f_ffpI( 0.0, s2[j], &correct3i ); + long double correct4 = f->dfunc.f_ffpI( -0.0, s2[j], &correct4i ); + float err2 = Ulp_Error_Double( test, correct3 ); + float err3 = Ulp_Error_Double( test, correct4 ); + int64_t iErr3 = (long long) q2[j] - (long long) correct3i; + int64_t iErr4 = (long long) q2[j] - (long long) correct4i; + fail = fail && ((!(fabsf(err2) <= f->double_ulps && iErr3 == 0)) && (!(fabsf(err3) <= f->double_ulps && iErr4 == 0))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( llabs(iErr3) < llabs( iErr ) ) + iErr = iErr3; + if( llabs(iErr4) < llabs( iErr ) ) + iErr = iErr4; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) ) + { + fail = fail && ! ( test == 0.0f && (iErr3 == 0 || iErr4 == 0) ); + if( ! fail ) + err = 0.0f; + } + + //try with both args as zero + if( IsDoubleSubnormal( s2[j] ) ) + { + int correct7i, correct8i; + correct3 = f->dfunc.f_ffpI( 0.0, 0.0, &correct3i ); + correct4 = f->dfunc.f_ffpI( -0.0, 0.0, &correct4i ); + long double correct7 = f->dfunc.f_ffpI( 0.0, -0.0, &correct7i ); + long double correct8 = f->dfunc.f_ffpI( -0.0, -0.0, &correct8i ); + err2 = Ulp_Error_Double( test, correct3 ); + err3 = Ulp_Error_Double( test, correct4 ); + float err4 = Ulp_Error_Double( test, correct7 ); + float err5 = Ulp_Error_Double( test, correct8 ); + iErr3 = (long long) q2[j] - (long long) correct3i; + iErr4 = (long long) q2[j] - (long long) correct4i; + int64_t iErr7 = (long long) q2[j] - (long long) correct7i; + int64_t iErr8 = (long long) q2[j] - (long long) correct8i; + fail = fail && ((!(fabsf(err2) <= f->double_ulps && iErr3 == 0)) && (!(fabsf(err3) <= f->double_ulps && iErr4 == 0)) && + (!(fabsf(err4) <= f->double_ulps && iErr7 == 0)) && (!(fabsf(err5) <= f->double_ulps && iErr8 == 0))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + if( llabs(iErr3) < llabs( iErr ) ) + iErr = iErr3; + if( llabs(iErr4) < llabs( iErr ) ) + iErr = iErr4; + if( llabs(iErr7) < llabs( iErr ) ) + iErr = iErr7; + if( llabs(iErr8) < llabs( iErr ) ) + iErr = iErr8; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct3, f->double_ulps ) || IsDoubleResultSubnormal( correct4, f->double_ulps ) || + IsDoubleResultSubnormal( correct7, f->double_ulps ) || IsDoubleResultSubnormal( correct8, f->double_ulps ) ) + { + fail = fail && ! ( test == 0.0f && (iErr3 == 0 || iErr4 == 0 || iErr7 == 0 || iErr8 == 0)); + if( ! fail ) + err = 0.0f; + } + } + } + else if( IsDoubleSubnormal( s2[j] ) ) + { + int correct3i, correct4i; + long double correct3 = f->dfunc.f_ffpI( s[j], 0.0, &correct3i ); + long double correct4 = f->dfunc.f_ffpI( s[j], -0.0, &correct4i ); + float err2 = Ulp_Error_Double( test, correct3 ); + float err3 = Ulp_Error_Double( test, correct4 ); + int64_t iErr3 = (long long) q2[j] - (long long) correct3i; + int64_t iErr4 = (long long) q2[j] - (long long) correct4i; + fail = fail && ((!(fabsf(err2) <= f->double_ulps && iErr3 == 0)) && (!(fabsf(err3) <= f->double_ulps && iErr4 == 0))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( llabs(iErr3) < llabs( iErr ) ) + iErr = iErr3; + if( llabs(iErr4) < llabs( iErr ) ) + iErr = iErr4; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) ) + { + fail = fail && ! ( test == 0.0f && (iErr3 == 0 || iErr4 == 0) ); + if( ! fail ) + err = 0.0f; + } + } + } + if( fabsf(err ) > maxError ) + { + maxError = fabsf(err); + maxErrorVal = s[j]; + } + if( llabs(iErr) > maxError2 ) + { + maxError2 = llabs(iErr ); + maxErrorVal2 = s[j]; + } + + if( fail ) + { + vlog_error( "\nERROR: %sD%s: {%f, %lld} ulp error at {%.13la, %.13la} ({ 0x%16.16llx, 0x%16.16llx}): *{%.13la, %d} ({ 0x%16.16llx, 0x%8.8x}) vs. {%.13la, %d} ({ 0x%16.16llx, 0x%8.8x})\n", + f->name, sizeNames[k], err, iErr, + ((double*) gIn)[j], ((double*) gIn2)[j], + ((cl_ulong*) gIn)[j], ((cl_ulong*) gIn2)[j], + ((double*) gOut_Ref)[j], ((int*) gOut_Ref2)[j], + ((cl_ulong*) gOut_Ref)[j], ((cl_uint*) gOut_Ref2)[j], + test, q2[j], + ((cl_ulong*) q)[j], ((cl_uint*) q2)[j]); + error = -1; + goto exit; + } + } + } + } + + if( 0 == (i & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10zu bufferSize:%10zd \n", i, step, bufferSize); + } else + { + vlog("." ); + } + + fflush(stdout); + } + } + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input array + double *p = (double *)gIn; + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + p[j] = DoubleFromUInt32( genrand_int32(d) ); + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_TRUE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_TRUE, 0, bufferSize, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_double ) * sizeValues[j]; + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; // bufferSize / vectorSize rounded up + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gOutBuffer2[j] ), &gOutBuffer2[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 3, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( k = 0; k < PERF_LOOP_COUNT; k++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (bufferSize / sizeof( double ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sD%s", f->name, sizeNames[j] ); + } + for( ; j < gMaxVectorSizeIndex; j++ ) + vlog( "\t -- " ); + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t{%8.2f, %lld} @ %a", maxError, maxError2, maxErrorVal ); + vlog( "\n" ); + +exit: + // Release + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + clReleaseKernel(kernels[k]); + clReleaseProgram(programs[k]); + } + + return error; +} + + + diff --git a/test_conformance/math_brute_force/i_unary.c b/test_conformance/math_brute_force/i_unary.c new file mode 100644 index 00000000..e41d5d82 --- /dev/null +++ b/test_conformance/math_brute_force/i_unary.c @@ -0,0 +1,629 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Utility.h" + +#include +#include "FunctionList.h" + +int TestFunc_Int_Float(const Func *f, MTdata); +int TestFunc_Int_Double(const Func *f, MTdata); + +#if defined( __cplusplus) + extern "C" +#endif +const vtbl _i_unary = { "i_unary", TestFunc_Int_Float, TestFunc_Int_Double }; + + +static int BuildKernel( const char *name, int vectorSize, cl_kernel *k, cl_program *p ); +static int BuildKernelDouble( const char *name, int vectorSize, cl_kernel *k, cl_program *p ); + +static int BuildKernel( const char *name, int vectorSize, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global int", sizeNames[vectorSize], "* out, __global float", sizeNames[vectorSize], "* in)\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in[i] );\n" + "}\n" + }; + const char *c3[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global int* out, __global float* in)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " float3 f0 = vload3( 0, in + 3 * i );\n" + " int3 i0 = ", name, "( f0 );\n" + " vstore3( i0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " float3 f0;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (float3)( in[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " f0 = (float3)( in[3*i], in[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " int3 i0 = ", name, "( f0 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = i0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = i0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernel(kern, (cl_uint) kernSize, testName, k, p); +} + +static int BuildKernelDouble( const char *name, int vectorSize, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global int", sizeNames[vectorSize], "* out, __global double", sizeNames[vectorSize], "* in)\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in[i] );\n" + "}\n" + }; + + const char *c3[] = {"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global int* out, __global double* in)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " double3 f0 = vload3( 0, in + 3 * i );\n" + " int3 i0 = ", name, "( f0 );\n" + " vstore3( i0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " double3 f0;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (double3)( in[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " f0 = (double3)( in[3*i], in[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " int3 i0 = ", name, "( f0 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = i0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = i0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernel(kern, (cl_uint) kernSize, testName, k, p); +} + +typedef struct BuildKernelInfo +{ + cl_uint offset; // the first vector size to build + cl_kernel *kernels; + cl_program *programs; + const char *nameInCode; +}BuildKernelInfo; + +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernel( info->nameInCode, i, info->kernels + i, info->programs + i ); +} + +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernelDouble( info->nameInCode, i, info->kernels + i, info->programs + i ); +} + +int TestFunc_Int_Float(const Func *f, MTdata d) +{ + uint64_t i; + uint32_t j, k; + int error; + cl_program programs[ VECTOR_SIZE_COUNT ]; + cl_kernel kernels[ VECTOR_SIZE_COUNT ]; + int ftz = f->ftz || 0 == (gFloatCapabilities & CL_FP_DENORM) || gForceFTZ; + size_t bufferSize = (gWimpyMode)?gWimpyBufferSize:BUFFER_SIZE; + uint64_t step = bufferSize / sizeof( float ); + int scale = (int)((1ULL<<32) / (16 * bufferSize / sizeof( float )) + 1); + + logFunctionInfo(f->name,sizeof(cl_float),gTestFastRelaxed); + if( gWimpyMode ) + { + step = (1ULL<<32) * gWimpyReductionFactor / (512); + } + + // This test is not using ThreadPool so we need to disable FTZ here + // for reference computations + FPU_mode_type oldMode; + DisableFTZ(&oldMode); + + Force64BitFPUPrecision(); + + // Init the kernels + BuildKernelInfo build_info = { gMinVectorSizeIndex, kernels, programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_FloatFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + return error; +/* + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + if( (error = BuildKernel( f->nameInCode, (int) i, kernels + i, programs + i) ) ) + return error; +*/ + + for( i = 0; i < (1ULL<<32); i += step ) + { + //Init input array + uint32_t *p = (uint32_t *)gIn; + if( gWimpyMode ) + { + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + p[j] = (uint32_t) i + j * scale; + } + else + { + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + p[j] = (uint32_t) i + j; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + // write garbage into output arrays + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + uint32_t pattern = 0xffffdead; + memset_pattern4(gOut[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer[j], CL_FALSE, 0, bufferSize, gOut[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2(%d) ***\n", error, j ); + goto exit; + } + } + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_float); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(gQueue) )) + vlog( "clFlush failed\n" ); + + //Calculate the correctly rounded reference result + int *r = (int *)gOut_Ref; + float *s = (float *)gIn; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + r[j] = f->func.i_f( s[j] ); + + // Read the data back + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0, bufferSize, gOut[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray failed %d\n", error ); + goto exit; + } + } + + if( gSkipCorrectnessTesting ) + break; + + //Verify data + uint32_t *t = (uint32_t *)gOut_Ref; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + uint32_t *q = (uint32_t *)(gOut[k]); + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + if( ftz && IsFloatSubnormal(s[j])) + { + unsigned int correct0 = f->func.i_f( 0.0 ); + unsigned int correct1 = f->func.i_f( -0.0 ); + if( q[j] == correct0 || q[j] == correct1 ) + continue; + } + + uint32_t err = t[j] - q[j]; + if( q[j] > t[j] ) + err = q[j] - t[j]; + vlog_error( "\nERROR: %s%s: %d ulp error at %a (0x%8.8x): *%d vs. %d\n", f->name, sizeNames[k], err, ((float*) gIn)[j], ((cl_uint*) gIn)[j], t[j], q[j] ); + error = -1; + goto exit; + } + } + } + + if( 0 == (i & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10zu bufferSize:%10zd \n", i, step, bufferSize); + } else + { + vlog("." ); + } + fflush(stdout); + } + } + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input array + uint32_t *p = (uint32_t *)gIn; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + p[j] = genrand_int32(d); + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_float); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( k = 0; k < PERF_LOOP_COUNT; k++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (bufferSize / sizeof( float ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sf%s", f->name, sizeNames[j] ); + } + } + + vlog( "\n" ); +exit: + RestoreFPState(&oldMode); + // Release + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + clReleaseKernel(kernels[k]); + clReleaseProgram(programs[k]); + } + + return error; +} + +int TestFunc_Int_Double(const Func *f, MTdata d) +{ + uint64_t i; + uint32_t j, k; + int error; + cl_program programs[ VECTOR_SIZE_COUNT ]; + cl_kernel kernels[ VECTOR_SIZE_COUNT ]; + int ftz = f->ftz || gForceFTZ; + size_t bufferSize = (gWimpyMode)?gWimpyBufferSize:BUFFER_SIZE; + uint64_t step = bufferSize / sizeof( cl_double ); + int scale = (int)((1ULL<<32) / (16 * bufferSize / sizeof( cl_double )) + 1); + + logFunctionInfo(f->name,sizeof(cl_double),gTestFastRelaxed); + if( gWimpyMode ) + { + step = (1ULL<<32) * gWimpyReductionFactor / (512); + } + // This test is not using ThreadPool so we need to disable FTZ here + // for reference computations + FPU_mode_type oldMode; + DisableFTZ(&oldMode); + + Force64BitFPUPrecision(); + + // Init the kernels + BuildKernelInfo build_info = { gMinVectorSizeIndex, kernels, programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_DoubleFn, + gMaxVectorSizeIndex - gMinVectorSizeIndex, + &build_info ) )) + { + return error; + } +/* + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + if( (error = BuildKernelDouble( f->nameInCode, (int) i, kernels + i, programs + i) ) ) + return error; +*/ + + for( i = 0; i < (1ULL<<32); i += step ) + { + //Init input array + double *p = (double *)gIn; + if( gWimpyMode ) + { + for( j = 0; j < bufferSize / sizeof( cl_double ); j++ ) + p[j] = DoubleFromUInt32( (uint32_t) i + j * scale ); + } + else + { + for( j = 0; j < bufferSize / sizeof( cl_double ); j++ ) + p[j] = DoubleFromUInt32( (uint32_t) i + j ); + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + // write garbage into output arrays + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + uint32_t pattern = 0xffffdead; + memset_pattern4(gOut[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer[j], CL_FALSE, 0, bufferSize, gOut[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2(%d) ***\n", error, j ); + goto exit; + } + } + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_double); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(gQueue) )) + vlog( "clFlush failed\n" ); + + //Calculate the correctly rounded reference result + int *r = (int *)gOut_Ref; + double *s = (double *)gIn; + for( j = 0; j < bufferSize / sizeof( cl_double ); j++ ) + r[j] = f->dfunc.i_f( s[j] ); + + // Read the data back + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0, bufferSize, gOut[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray failed %d\n", error ); + goto exit; + } + } + + if( gSkipCorrectnessTesting ) + break; + + //Verify data + uint32_t *t = (uint32_t *)gOut_Ref; + for( j = 0; j < bufferSize / sizeof( cl_double ); j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + uint32_t *q = (uint32_t *)(gOut[k]); + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + if( ftz && IsDoubleSubnormal(s[j])) + { + unsigned int correct0 = f->dfunc.i_f( 0.0 ); + unsigned int correct1 = f->dfunc.i_f( -0.0 ); + if( q[j] == correct0 || q[j] == correct1 ) + continue; + } + + uint32_t err = t[j] - q[j]; + if( q[j] > t[j] ) + err = q[j] - t[j]; + vlog_error( "\nERROR: %sD%s: %d ulp error at %.13la: *%d vs. %d\n", f->name, sizeNames[k], err, ((double*) gIn)[j], t[j], q[j] ); + error = -1; + goto exit; + } + } + } + + if( 0 == (i & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10zu bufferSize:%10zd \n", i, step, bufferSize); + } else + { + vlog("." ); + } + fflush(stdout); + + } + } + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input array + double *p = (double *)gIn; + for( j = 0; j < bufferSize / sizeof( cl_double ); j++ ) + p[j] = DoubleFromUInt32( genrand_int32(d) ); + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_double); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( k = 0; k < PERF_LOOP_COUNT; k++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (bufferSize / sizeof( double ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sD%s", f->name, sizeNames[j] ); + } + for( ; j < gMaxVectorSizeIndex; j++ ) + vlog( "\t -- " ); + } + + vlog( "\n" ); + + +exit: + RestoreFPState(&oldMode); + // Release + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + clReleaseKernel(kernels[k]); + clReleaseProgram(programs[k]); + } + + return error; +} + + + diff --git a/test_conformance/math_brute_force/macro_binary.c b/test_conformance/math_brute_force/macro_binary.c new file mode 100644 index 00000000..e489c598 --- /dev/null +++ b/test_conformance/math_brute_force/macro_binary.c @@ -0,0 +1,1215 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Utility.h" + +#include +#include "FunctionList.h" + +int TestMacro_Int_Float_Float(const Func *f, MTdata); +int TestMacro_Int_Double_Double(const Func *f, MTdata); + +#if defined( __cplusplus) +extern "C" +#endif +const vtbl _macro_binary = { "macro_binary", TestMacro_Int_Float_Float, TestMacro_Int_Double_Double }; + +static int BuildKernel( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ); +static int BuildKernelDouble( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ); + +static int BuildKernel( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global int", sizeNames[vectorSize], "* out, __global float", sizeNames[vectorSize], "* in1, __global float", sizeNames[vectorSize], "* in2 )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in1[i], in2[i] );\n" + "}\n" + }; + + const char *c3[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global int* out, __global float* in, __global float* in2)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " float3 f0 = vload3( 0, in + 3 * i );\n" + " float3 f1 = vload3( 0, in2 + 3 * i );\n" + " int3 i0 = ", name, "( f0, f1 );\n" + " vstore3( i0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " float3 f0, f1;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (float3)( in[3*i], NAN, NAN ); \n" + " f1 = (float3)( in2[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " f0 = (float3)( in[3*i], in[3*i+1], NAN ); \n" + " f1 = (float3)( in2[3*i], in2[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " int3 i0 = ", name, "( f0, f1 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = i0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = i0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernels(kern, (cl_uint) kernSize, testName, kernel_count, k, p); } + + +static int BuildKernelDouble( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global long", sizeNames[vectorSize], "* out, __global double", sizeNames[vectorSize], "* in1, __global double", sizeNames[vectorSize], "* in2 )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in1[i], in2[i] );\n" + "}\n" + }; + + const char *c3[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global long* out, __global double* in, __global double* in2)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " double3 f0 = vload3( 0, in + 3 * i );\n" + " double3 f1 = vload3( 0, in2 + 3 * i );\n" + " long3 l0 = ", name, "( f0, f1 );\n" + " vstore3( l0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " double3 f0, f1;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (double3)( in[3*i], NAN, NAN ); \n" + " f1 = (double3)( in2[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " f0 = (double3)( in[3*i], in[3*i+1], NAN ); \n" + " f1 = (double3)( in2[3*i], in2[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " long3 l0 = ", name, "( f0, f1 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = l0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = l0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernels(kern, (cl_uint) kernSize, testName, kernel_count, k, p); +} + +typedef struct BuildKernelInfo +{ + cl_uint offset; // the first vector size to build + cl_uint kernel_count; + cl_kernel **kernels; + cl_program *programs; + const char *nameInCode; +}BuildKernelInfo; + +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernel( info->nameInCode, i, info->kernel_count, info->kernels[i], info->programs + i ); +} + +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernelDouble( info->nameInCode, i, info->kernel_count, info->kernels[i], info->programs + i ); +} + + +// A table of more difficult cases to get right +static const float specialValuesFloat[] = { + -NAN, -INFINITY, -FLT_MAX, MAKE_HEX_FLOAT(-0x1.000002p64f, -0x1000002L, 40), MAKE_HEX_FLOAT(-0x1.0p64f, -0x1L, 64), MAKE_HEX_FLOAT(-0x1.fffffep63f, -0x1fffffeL, 39), MAKE_HEX_FLOAT(-0x1.000002p63f, -0x1000002L, 39), MAKE_HEX_FLOAT(-0x1.0p63f, -0x1L, 63), MAKE_HEX_FLOAT(-0x1.fffffep62f, -0x1fffffeL, 38), + MAKE_HEX_FLOAT(-0x1.000002p32f, -0x1000002L, 8), MAKE_HEX_FLOAT(-0x1.0p32f, -0x1L, 32), MAKE_HEX_FLOAT(-0x1.fffffep31f, -0x1fffffeL, 7), MAKE_HEX_FLOAT(-0x1.000002p31f, -0x1000002L, 7), MAKE_HEX_FLOAT(-0x1.0p31f, -0x1L, 31), MAKE_HEX_FLOAT(-0x1.fffffep30f, -0x1fffffeL, 6), -1000.f, -100.f, -4.0f, -3.5f, + -3.0f, MAKE_HEX_FLOAT(-0x1.800002p1f, -0x1800002L, -23), -2.5f, MAKE_HEX_FLOAT(-0x1.7ffffep1f, -0x17ffffeL, -23), -2.0f, MAKE_HEX_FLOAT(-0x1.800002p0f, -0x1800002L, -24), -1.5f, MAKE_HEX_FLOAT(-0x1.7ffffep0f, -0x17ffffeL, -24),MAKE_HEX_FLOAT(-0x1.000002p0f, -0x1000002L, -24), -1.0f, MAKE_HEX_FLOAT(-0x1.fffffep-1f, -0x1fffffeL, -25), + MAKE_HEX_FLOAT(-0x1.000002p-1f, -0x1000002L, -25), -0.5f, MAKE_HEX_FLOAT(-0x1.fffffep-2f, -0x1fffffeL, -26), MAKE_HEX_FLOAT(-0x1.000002p-2f, -0x1000002L, -26), -0.25f, MAKE_HEX_FLOAT(-0x1.fffffep-3f, -0x1fffffeL, -27), + MAKE_HEX_FLOAT(-0x1.000002p-126f, -0x1000002L, -150), -FLT_MIN, MAKE_HEX_FLOAT(-0x0.fffffep-126f, -0x0fffffeL, -150), MAKE_HEX_FLOAT(-0x0.000ffep-126f, -0x0000ffeL, -150), MAKE_HEX_FLOAT(-0x0.0000fep-126f, -0x00000feL, -150), MAKE_HEX_FLOAT(-0x0.00000ep-126f, -0x000000eL, -150), MAKE_HEX_FLOAT(-0x0.00000cp-126f, -0x000000cL, -150), MAKE_HEX_FLOAT(-0x0.00000ap-126f, -0x000000aL, -150), + MAKE_HEX_FLOAT(-0x0.000008p-126f, -0x0000008L, -150), MAKE_HEX_FLOAT(-0x0.000006p-126f, -0x0000006L, -150), MAKE_HEX_FLOAT(-0x0.000004p-126f, -0x0000004L, -150), MAKE_HEX_FLOAT(-0x0.000002p-126f, -0x0000002L, -150), -0.0f, + + +NAN, +INFINITY, +FLT_MAX, MAKE_HEX_FLOAT(+0x1.000002p64f, +0x1000002L, 40), MAKE_HEX_FLOAT(+0x1.0p64f, +0x1L, 64), MAKE_HEX_FLOAT(+0x1.fffffep63f, +0x1fffffeL, 39), MAKE_HEX_FLOAT(+0x1.000002p63f, +0x1000002L, 39), MAKE_HEX_FLOAT(+0x1.0p63f, +0x1L, 63), MAKE_HEX_FLOAT(+0x1.fffffep62f, +0x1fffffeL, 38), + MAKE_HEX_FLOAT(+0x1.000002p32f, +0x1000002L, 8), MAKE_HEX_FLOAT(+0x1.0p32f, +0x1L, 32), MAKE_HEX_FLOAT(+0x1.fffffep31f, +0x1fffffeL, 7), MAKE_HEX_FLOAT(+0x1.000002p31f, +0x1000002L, 7), MAKE_HEX_FLOAT(+0x1.0p31f, +0x1L, 31), MAKE_HEX_FLOAT(+0x1.fffffep30f, +0x1fffffeL, 6), +1000.f, +100.f, +4.0f, +3.5f, + +3.0f, MAKE_HEX_FLOAT(+0x1.800002p1f, +0x1800002L, -23), 2.5f, MAKE_HEX_FLOAT(+0x1.7ffffep1f, +0x17ffffeL, -23),+2.0f, MAKE_HEX_FLOAT(+0x1.800002p0f, +0x1800002L, -24), 1.5f, MAKE_HEX_FLOAT(+0x1.7ffffep0f, +0x17ffffeL, -24), MAKE_HEX_FLOAT(+0x1.000002p0f, +0x1000002L, -24), +1.0f, MAKE_HEX_FLOAT(+0x1.fffffep-1f, +0x1fffffeL, -25), + MAKE_HEX_FLOAT(+0x1.000002p-1f, +0x1000002L, -25), +0.5f, MAKE_HEX_FLOAT(+0x1.fffffep-2f, +0x1fffffeL, -26), MAKE_HEX_FLOAT(+0x1.000002p-2f, +0x1000002L, -26), +0.25f, MAKE_HEX_FLOAT(+0x1.fffffep-3f, +0x1fffffeL, -27), + MAKE_HEX_FLOAT(0x1.000002p-126f, 0x1000002L, -150), +FLT_MIN, MAKE_HEX_FLOAT(+0x0.fffffep-126f, +0x0fffffeL, -150), MAKE_HEX_FLOAT(+0x0.000ffep-126f, +0x0000ffeL, -150), MAKE_HEX_FLOAT(+0x0.0000fep-126f, +0x00000feL, -150), MAKE_HEX_FLOAT(+0x0.00000ep-126f, +0x000000eL, -150), MAKE_HEX_FLOAT(+0x0.00000cp-126f, +0x000000cL, -150), MAKE_HEX_FLOAT(+0x0.00000ap-126f, +0x000000aL, -150), + MAKE_HEX_FLOAT(+0x0.000008p-126f, +0x0000008L, -150), MAKE_HEX_FLOAT(+0x0.000006p-126f, +0x0000006L, -150), MAKE_HEX_FLOAT(+0x0.000004p-126f, +0x0000004L, -150), MAKE_HEX_FLOAT(+0x0.000002p-126f, +0x0000002L, -150), +0.0f +}; + +static const size_t specialValuesFloatCount = sizeof(specialValuesFloat) / sizeof(specialValuesFloat[0]); + +//Thread specific data for a worker thread +typedef struct ThreadInfo +{ + cl_mem inBuf; // input buffer for the thread + cl_mem inBuf2; // input buffer for the thread + cl_mem outBuf[ VECTOR_SIZE_COUNT ]; // output buffers for the thread + MTdata d; + cl_command_queue tQueue; // per thread command queue to improve performance +}ThreadInfo; + +typedef struct TestInfo +{ + size_t subBufferSize; // Size of the sub-buffer in elements + const Func *f; // A pointer to the function info + cl_program programs[ VECTOR_SIZE_COUNT ]; // programs for various vector sizes + cl_kernel *k[VECTOR_SIZE_COUNT ]; // arrays of thread-specific kernels for each worker thread: k[vector_size][thread_id] + ThreadInfo *tinfo; // An array of thread specific information for each worker thread + cl_uint threadCount; // Number of worker threads + cl_uint step; // step between each chunk and the next. + cl_uint scale; // stride between individual test values + int ftz; // non-zero if running in flush to zero mode + +}TestInfo; + +static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *p ); + +int TestMacro_Int_Float_Float(const Func *f, MTdata d) +{ + TestInfo test_info; + cl_int error; + size_t i, j; + + logFunctionInfo(f->name,sizeof(cl_float),gTestFastRelaxed); + + // Init test_info + memset( &test_info, 0, sizeof( test_info ) ); + test_info.threadCount = GetThreadCount(); + test_info.subBufferSize = BUFFER_SIZE / (sizeof( cl_float) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = 1; + if (gWimpyMode) + { + test_info.subBufferSize = gWimpyBufferSize / (sizeof( cl_float) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = (cl_uint) sizeof(cl_float) * 2 * gWimpyReductionFactor; + } + test_info.step = (cl_uint) test_info.subBufferSize * test_info.scale; + test_info.f = f; + test_info.ftz = f->ftz || gForceFTZ || 0 == (CL_FP_DENORM & gFloatCapabilities); + + // cl_kernels aren't thread safe, so we make one for each vector size for every thread + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + size_t array_size = test_info.threadCount * sizeof( cl_kernel ); + test_info.k[i] = (cl_kernel*)malloc( array_size ); + if( NULL == test_info.k[i] ) + { + vlog_error( "Error: Unable to allocate storage for kernels!\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.k[i], 0, array_size ); + } + test_info.tinfo = (ThreadInfo*)malloc( test_info.threadCount * sizeof(*test_info.tinfo) ); + if( NULL == test_info.tinfo ) + { + vlog_error( "Error: Unable to allocate storage for thread specific data.\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.tinfo, 0, test_info.threadCount * sizeof(*test_info.tinfo) ); + for( i = 0; i < test_info.threadCount; i++ ) + { + cl_buffer_region region = { i * test_info.subBufferSize * sizeof( cl_float), test_info.subBufferSize * sizeof( cl_float) }; + test_info.tinfo[i].inBuf = clCreateSubBuffer( gInBuffer, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + test_info.tinfo[i].inBuf2 = clCreateSubBuffer( gInBuffer2, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + test_info.tinfo[i].outBuf[j] = clCreateSubBuffer( gOutBuffer[j], CL_MEM_WRITE_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].outBuf[j] ) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + } + test_info.tinfo[i].tQueue = clCreateCommandQueueWithProperties(gContext, gDevice, 0, &error); + if( NULL == test_info.tinfo[i].tQueue || error ) + { + vlog_error( "clCreateCommandQueue failed. (%d)\n", error ); + goto exit; + } + + test_info.tinfo[i].d = init_genrand(genrand_int32(d)); + } + + // Init the kernels + { + BuildKernelInfo build_info = { gMinVectorSizeIndex, test_info.threadCount, test_info.k, test_info.programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_FloatFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + goto exit; + } + + + // Run the kernels + if( !gSkipCorrectnessTesting ) + { + error = ThreadPool_Do( TestFloat, (cl_uint) ((1ULL<<32) / test_info.step), &test_info ); + + if( error ) + goto exit; + + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input arrays + uint32_t *p = (uint32_t *)gIn; + uint32_t *p2 = (uint32_t *)gIn2; + for( j = 0; j < BUFFER_SIZE / sizeof( float ); j++ ) + { + p[j] = genrand_int32(d); + p2[j] = genrand_int32(d); + } + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, BUFFER_SIZE, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, BUFFER_SIZE, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_float); + size_t localCount = (BUFFER_SIZE + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg( test_info.k[j][0], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(test_info.programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( i = 0; i < PERF_LOOP_COUNT; i++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, test_info.k[j][0], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (BUFFER_SIZE / sizeof( float ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sf%s", f->name, sizeNames[j] ); + } + } + vlog( "\n" ); + +exit: + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + clReleaseProgram(test_info.programs[i]); + if( test_info.k[i] ) + { + for( j = 0; j < test_info.threadCount; j++ ) + clReleaseKernel(test_info.k[i][j]); + + free( test_info.k[i] ); + } + } + if( test_info.tinfo ) + { + for( i = 0; i < test_info.threadCount; i++ ) + { + free_mtdata(test_info.tinfo[i].d); + clReleaseMemObject(test_info.tinfo[i].inBuf); + clReleaseMemObject(test_info.tinfo[i].inBuf2); + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + clReleaseMemObject(test_info.tinfo[i].outBuf[j]); + clReleaseCommandQueue(test_info.tinfo[i].tQueue); + } + + free( test_info.tinfo ); + } + + return error; +} + +static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *data ) +{ + const TestInfo *job = (const TestInfo *) data; + size_t buffer_elements = job->subBufferSize; + size_t buffer_size = buffer_elements * sizeof( cl_float ); + cl_uint base = job_id * (cl_uint) job->step; + ThreadInfo *tinfo = job->tinfo + thread_id; + fptr func = job->f->func; + int ftz = job->ftz; + MTdata d = tinfo->d; + cl_uint j, k; + cl_int error; + const char *name = job->f->name; + cl_int *t,*r; + cl_float *s,*s2; + + // start the map of the output arrays + cl_event e[ VECTOR_SIZE_COUNT ]; + cl_int *out[ VECTOR_SIZE_COUNT ]; + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_int*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_WRITE, 0, buffer_size, 0, NULL, e + j, &error); + if( error || NULL == out[j]) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush failed\n" ); + + //Init input array + cl_uint *p = (cl_uint *)gIn + thread_id * buffer_elements; + cl_uint *p2 = (cl_uint *)gIn2 + thread_id * buffer_elements; + j = 0; + int totalSpecialValueCount = specialValuesFloatCount * specialValuesFloatCount; + int indx = (totalSpecialValueCount - 1) / buffer_elements; + + if( job_id <= (cl_uint)indx ) + { // test edge cases + float *fp = (float *)p; + float *fp2 = (float *)p2; + uint32_t x, y; + + x = (job_id * buffer_elements) % specialValuesFloatCount; + y = (job_id * buffer_elements) / specialValuesFloatCount; + + for( ; j < buffer_elements; j++ ) + { + fp[j] = specialValuesFloat[x]; + fp2[j] = specialValuesFloat[y]; + if( ++x >= specialValuesFloatCount ) + { + x = 0; + y++; + if( y >= specialValuesFloatCount ) + break; + } + } + } + + //Init any remaining values. + for( ; j < buffer_elements; j++ ) + { + p[j] = genrand_int32(d); + p2[j] = genrand_int32(d); + } + + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf, CL_FALSE, 0, buffer_size, p, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf2, CL_FALSE, 0, buffer_size, p2, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + //Wait for the map to finish + if( (error = clWaitForEvents(1, e + j) )) + { + vlog_error( "Error: clWaitForEvents failed! err: %d\n", error ); + goto exit; + } + if( (error = clReleaseEvent( e[j] ) )) + { + vlog_error( "Error: clReleaseEvent failed! err: %d\n", error ); + goto exit; + } + + // Fill the result buffer with garbage, so that old results don't carry over + uint32_t pattern = 0xffffdead; + memset_pattern4(out[j], &pattern, buffer_size); + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueMapBuffer failed! err: %d\n", error ); + goto exit; + } + + // run the kernel + size_t vectorCount = (buffer_elements + sizeValues[j] - 1) / sizeValues[j]; + cl_kernel kernel = job->k[j][thread_id]; //each worker thread has its own copy of the cl_kernel + cl_program program = job->programs[j]; + + if( ( error = clSetKernelArg( kernel, 0, sizeof( tinfo->outBuf[j] ), &tinfo->outBuf[j] ))){ LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 1, sizeof( tinfo->inBuf ), &tinfo->inBuf ) )) { LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 2, sizeof( tinfo->inBuf2 ), &tinfo->inBuf2 ) )) { LogBuildError(program); return error; } + + if( (error = clEnqueueNDRangeKernel(tinfo->tQueue, kernel, 1, NULL, &vectorCount, NULL, 0, NULL, NULL))) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 2 failed\n" ); + + if( gSkipCorrectnessTesting ) + return CL_SUCCESS; + + //Calculate the correctly rounded reference result + r = (cl_int *)gOut_Ref + thread_id * buffer_elements; + s = (float *)gIn + thread_id * buffer_elements; + s2 = (float *)gIn2 + thread_id * buffer_elements; + for( j = 0; j < buffer_elements; j++ ) + r[j] = func.i_ff( s[j], s2[j] ); + + + // Read the data back -- no need to wait for the first N-1 buffers. This is an in order queue. + for( j = gMinVectorSizeIndex; j + 1 < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_int*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + } + + // Wait for the last buffer + out[j] = (cl_int*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_TRUE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + + //Verify data + t = (cl_int *)r; + for( j = 0; j < buffer_elements; j++ ) + { + cl_int *q = out[0]; + + if( gMinVectorSizeIndex == 0 && t[j] != q[j] ) + { + if( ftz ) + { + if( IsFloatSubnormal( s[j]) ) + { + if( IsFloatSubnormal( s2[j] ) ) + { + int correct = func.i_ff( 0.0f, 0.0f ); + int correct2 = func.i_ff( 0.0f, -0.0f ); + int correct3 = func.i_ff( -0.0f, 0.0f ); + int correct4 = func.i_ff( -0.0f, -0.0f ); + + if( correct == q[j] || correct2 == q[j] || correct3 == q[j] || correct4 == q[j] ) + continue; + } + else + { + int correct = func.i_ff( 0.0f, s2[j] ); + int correct2 = func.i_ff( -0.0f, s2[j] ); + if( correct == q[j] || correct2 == q[j] ) + continue; + } + } + else if( IsFloatSubnormal( s2[j] ) ) + { + int correct = func.i_ff( s[j], 0.0f ); + int correct2 = func.i_ff( s[j], -0.0f ); + if( correct == q[j] || correct2 == q[j] ) + continue; + } + + } + + uint32_t err = t[j] - q[j]; + if( q[j] > t[j] ) + err = q[j] - t[j]; + vlog_error( "\nERROR: %s: %d ulp error at {%a, %a}: *0x%8.8x vs. 0x%8.8x (index: %d)\n", name, err, ((float*) s)[j], ((float*) s2)[j], t[j], q[j], j ); + error = -1; + goto exit; + } + + for( k = MAX(1, gMinVectorSizeIndex); k < gMaxVectorSizeIndex; k++ ) + { + q = out[k]; + // If we aren't getting the correctly rounded result + if( -t[j] != q[j] ) + { + if( ftz ) + { + if( IsFloatSubnormal( s[j]) ) + { + if( IsFloatSubnormal( s2[j] ) ) + { + int correct = -func.i_ff( 0.0f, 0.0f ); + int correct2 = -func.i_ff( 0.0f, -0.0f ); + int correct3 = -func.i_ff( -0.0f, 0.0f ); + int correct4 = -func.i_ff( -0.0f, -0.0f ); + + if( correct == q[j] || correct2 == q[j] || correct3 == q[j] || correct4 == q[j] ) + continue; + } + else + { + int correct = -func.i_ff( 0.0f, s2[j] ); + int correct2 = -func.i_ff( -0.0f, s2[j] ); + if( correct == q[j] || correct2 == q[j] ) + continue; + } + } + else if( IsFloatSubnormal( s2[j] ) ) + { + int correct = -func.i_ff( s[j], 0.0f ); + int correct2 = -func.i_ff( s[j], -0.0f ); + if( correct == q[j] || correct2 == q[j] ) + continue; + } + + } + cl_uint err = -t[j] - q[j]; + if( q[j] > -t[j] ) + err = q[j] + t[j]; + vlog_error( "\nERROR: %s%s: %d ulp error at {%a, %a}: *0x%8.8x vs. 0x%8.8x (index: %d)\n", name, sizeNames[k], err, ((float*) s)[j], ((float*) s2)[j], -t[j], q[j], j ); + error = -1; + goto exit; + } + } + } + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL)) ) + { + vlog_error( "Error: clEnqueueUnmapMemObject %d failed 2! err: %d\n", j, error ); + return error; + } + } + + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 3 failed\n" ); + + + if( 0 == ( base & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10u scale:%10u buf_elements:%10zd ThreadCount:%2u\n", base, job->step, job->scale, buffer_elements, job->threadCount); + } else + { + vlog("." ); + } + fflush(stdout); + } + +exit: + return error; +} + + +// A table of more difficult cases to get right +static const double specialValuesDouble[] = { + -NAN, -INFINITY, -DBL_MAX, MAKE_HEX_DOUBLE(-0x1.0000000000001p64, -0x10000000000001LL, 12), MAKE_HEX_DOUBLE(-0x1.0p64, -0x1LL, 64), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp63, -0x1fffffffffffffLL, 11), MAKE_HEX_DOUBLE(-0x1.0000000000001p63, -0x10000000000001LL, 11), MAKE_HEX_DOUBLE(-0x1.0p63, -0x1LL, 63), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp62, -0x1fffffffffffffLL, 10), + MAKE_HEX_DOUBLE(-0x1.000002p32, -0x1000002LL, 8), MAKE_HEX_DOUBLE(-0x1.0p32, -0x1LL, 32), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp31, -0x1fffffffffffffLL, -21), MAKE_HEX_DOUBLE(-0x1.0000000000001p31, -0x10000000000001LL, -21), MAKE_HEX_DOUBLE(-0x1.0p31, -0x1LL, 31), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp30, -0x1fffffffffffffLL, -22), -1000., -100., -4.0, -3.5, + -3.0, MAKE_HEX_DOUBLE(-0x1.8000000000001p1, -0x18000000000001LL, -51), -2.5, MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp1, -0x17ffffffffffffLL, -51), -2.0, MAKE_HEX_DOUBLE(-0x1.8000000000001p0, -0x18000000000001LL, -52), -1.5, MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp0, -0x17ffffffffffffLL, -52),MAKE_HEX_DOUBLE(-0x1.0000000000001p0, -0x10000000000001LL, -52), -1.0, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-1, -0x1fffffffffffffLL, -53), + MAKE_HEX_DOUBLE(-0x1.0000000000001p-1, -0x10000000000001LL, -53), -0.5, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-2, -0x1fffffffffffffLL, -54), MAKE_HEX_DOUBLE(-0x1.0000000000001p-2, -0x10000000000001LL, -54), -0.25, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-3, -0x1fffffffffffffLL, -55), + MAKE_HEX_DOUBLE(-0x1.0000000000001p-1022, -0x10000000000001LL, -1074), -DBL_MIN, MAKE_HEX_DOUBLE(-0x0.fffffffffffffp-1022, -0x0fffffffffffffLL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000fffp-1022, -0x00000000000fffLL, -1074), MAKE_HEX_DOUBLE(-0x0.00000000000fep-1022, -0x000000000000feLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000ep-1022, -0x0000000000000eLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000cp-1022, -0x0000000000000cLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000ap-1022, -0x0000000000000aLL, -1074), + MAKE_HEX_DOUBLE(-0x0.0000000000008p-1022, -0x00000000000008LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000007p-1022, -0x00000000000007LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000006p-1022, -0x00000000000006LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000005p-1022, -0x00000000000005LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000004p-1022, -0x00000000000004LL, -1074), + MAKE_HEX_DOUBLE(-0x0.0000000000003p-1022, -0x00000000000003LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000002p-1022, -0x00000000000002LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000001p-1022, -0x00000000000001LL, -1074), -0.0, + + +NAN, +INFINITY, +DBL_MAX, MAKE_HEX_DOUBLE(+0x1.0000000000001p64, +0x10000000000001LL, 12), MAKE_HEX_DOUBLE(+0x1.0p64, +0x1LL, 64), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp63, +0x1fffffffffffffLL, 11), MAKE_HEX_DOUBLE(+0x1.0000000000001p63, +0x10000000000001LL, 11), MAKE_HEX_DOUBLE(+0x1.0p63, +0x1LL, 63), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp62, +0x1fffffffffffffLL, 10), + MAKE_HEX_DOUBLE(+0x1.000002p32, +0x1000002LL, 8), MAKE_HEX_DOUBLE(+0x1.0p32, +0x1LL, 32), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp31, +0x1fffffffffffffLL, -21), MAKE_HEX_DOUBLE(+0x1.0000000000001p31, +0x10000000000001LL, -21), MAKE_HEX_DOUBLE(+0x1.0p31, +0x1LL, 31), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp30, +0x1fffffffffffffLL, -22), +1000., +100., +4.0, +3.5, + +3.0, MAKE_HEX_DOUBLE(+0x1.8000000000001p1, +0x18000000000001LL, -51), +2.5, MAKE_HEX_DOUBLE(+0x1.7ffffffffffffp1, +0x17ffffffffffffLL, -51), +2.0, MAKE_HEX_DOUBLE(+0x1.8000000000001p0, +0x18000000000001LL, -52), +1.5, MAKE_HEX_DOUBLE(+0x1.7ffffffffffffp0, +0x17ffffffffffffLL, -52),MAKE_HEX_DOUBLE(-0x1.0000000000001p0, -0x10000000000001LL, -52), +1.0, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-1, +0x1fffffffffffffLL, -53), + MAKE_HEX_DOUBLE(+0x1.0000000000001p-1, +0x10000000000001LL, -53), +0.5, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-2, +0x1fffffffffffffLL, -54), MAKE_HEX_DOUBLE(+0x1.0000000000001p-2, +0x10000000000001LL, -54), +0.25, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-3, +0x1fffffffffffffLL, -55), + MAKE_HEX_DOUBLE(+0x1.0000000000001p-1022, +0x10000000000001LL, -1074), +DBL_MIN, MAKE_HEX_DOUBLE(+0x0.fffffffffffffp-1022, +0x0fffffffffffffLL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000fffp-1022, +0x00000000000fffLL, -1074), MAKE_HEX_DOUBLE(+0x0.00000000000fep-1022, +0x000000000000feLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000ep-1022, +0x0000000000000eLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000cp-1022, +0x0000000000000cLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000ap-1022, +0x0000000000000aLL, -1074), + MAKE_HEX_DOUBLE(+0x0.0000000000008p-1022, +0x00000000000008LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000007p-1022, +0x00000000000007LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000006p-1022, +0x00000000000006LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000005p-1022, +0x00000000000005LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000004p-1022, +0x00000000000004LL, -1074), + MAKE_HEX_DOUBLE(+0x0.0000000000003p-1022, +0x00000000000003LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000002p-1022, +0x00000000000002LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000001p-1022, +0x00000000000001LL, -1074), +0.0, +}; + +static size_t specialValuesDoubleCount = sizeof( specialValuesDouble ) / sizeof( specialValuesDouble[0] ); + + +static cl_int TestDouble( cl_uint job_id, cl_uint thread_id, void *p ); + +int TestMacro_Int_Double_Double(const Func *f, MTdata d) +{ + TestInfo test_info; + cl_int error; + size_t i, j; + + logFunctionInfo(f->name,sizeof(cl_double),gTestFastRelaxed); + + // Init test_info + memset( &test_info, 0, sizeof( test_info ) ); + test_info.threadCount = GetThreadCount(); + test_info.subBufferSize = BUFFER_SIZE / (sizeof( cl_double) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = 1; + if (gWimpyMode) + { + test_info.subBufferSize = gWimpyBufferSize / (sizeof( cl_double) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = (cl_uint) sizeof(cl_double) * 2 * gWimpyReductionFactor; + } + + test_info.step = (cl_uint) test_info.subBufferSize * test_info.scale; + test_info.f = f; + test_info.ftz = f->ftz || gForceFTZ; + + // cl_kernels aren't thread safe, so we make one for each vector size for every thread + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + size_t array_size = test_info.threadCount * sizeof( cl_kernel ); + test_info.k[i] = (cl_kernel*)malloc( array_size ); + if( NULL == test_info.k[i] ) + { + vlog_error( "Error: Unable to allocate storage for kernels!\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.k[i], 0, array_size ); + } + test_info.tinfo = (ThreadInfo*)malloc( test_info.threadCount * sizeof(*test_info.tinfo) ); + if( NULL == test_info.tinfo ) + { + vlog_error( "Error: Unable to allocate storage for thread specific data.\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.tinfo, 0, test_info.threadCount * sizeof(*test_info.tinfo) ); + for( i = 0; i < test_info.threadCount; i++ ) + { + cl_buffer_region region = { i * test_info.subBufferSize * sizeof( cl_double), test_info.subBufferSize * sizeof( cl_double) }; + test_info.tinfo[i].inBuf = clCreateSubBuffer( gInBuffer, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + test_info.tinfo[i].inBuf2 = clCreateSubBuffer( gInBuffer2, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + /* Qualcomm fix: 9461 read-write flags must be compatible with parent buffer */ + test_info.tinfo[i].outBuf[j] = clCreateSubBuffer( gOutBuffer[j], CL_MEM_WRITE_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + /* Qualcomm fix: end */ + if( error || NULL == test_info.tinfo[i].outBuf[j] ) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + } + test_info.tinfo[i].tQueue = clCreateCommandQueueWithProperties(gContext, gDevice, 0, &error); + if( NULL == test_info.tinfo[i].tQueue || error ) + { + vlog_error( "clCreateCommandQueue failed. (%d)\n", error ); + goto exit; + } + + test_info.tinfo[i].d = init_genrand(genrand_int32(d)); + } + + + // Init the kernels + { + BuildKernelInfo build_info = { gMinVectorSizeIndex, test_info.threadCount, test_info.k, test_info.programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_DoubleFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + goto exit; + } + + if( !gSkipCorrectnessTesting ) + { + error = ThreadPool_Do( TestDouble, (cl_uint) ((1ULL<<32) / test_info.step), &test_info ); + + if( error ) + goto exit; + + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input arrays + uint64_t *p = (uint64_t *)gIn; + uint64_t *p2 = (uint64_t *)gIn2; + for( j = 0; j < BUFFER_SIZE / sizeof( double ); j++ ) + { + p[j] = (cl_ulong) genrand_int32(d) | ((cl_ulong) genrand_int32(d) << 32); + p2[j] = (cl_ulong) genrand_int32(d) | ((cl_ulong) genrand_int32(d) << 32); + } + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, BUFFER_SIZE, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, BUFFER_SIZE, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_double); + size_t localCount = (BUFFER_SIZE + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg( test_info.k[j][0], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(test_info.programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( i = 0; i < PERF_LOOP_COUNT; i++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, test_info.k[j][0], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (BUFFER_SIZE / sizeof( double ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sD%s", f->name, sizeNames[j] ); + } + for( ; j < gMaxVectorSizeIndex; j++ ) + vlog( "\t -- " ); + } + + vlog( "\n" ); + +exit: + // Release + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + clReleaseProgram(test_info.programs[i]); + if( test_info.k[i] ) + { + for( j = 0; j < test_info.threadCount; j++ ) + clReleaseKernel(test_info.k[i][j]); + + free( test_info.k[i] ); + } + } + if( test_info.tinfo ) + { + for( i = 0; i < test_info.threadCount; i++ ) + { + free_mtdata(test_info.tinfo[i].d); + clReleaseMemObject(test_info.tinfo[i].inBuf); + clReleaseMemObject(test_info.tinfo[i].inBuf2); + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + clReleaseMemObject(test_info.tinfo[i].outBuf[j]); + clReleaseCommandQueue(test_info.tinfo[i].tQueue); + } + + free( test_info.tinfo ); + } + + return error; +} + +static cl_int TestDouble( cl_uint job_id, cl_uint thread_id, void *data ) +{ + const TestInfo *job = (const TestInfo *) data; + size_t buffer_elements = job->subBufferSize; + size_t buffer_size = buffer_elements * sizeof( cl_double ); + cl_uint base = job_id * (cl_uint) job->step; + ThreadInfo *tinfo = job->tinfo + thread_id; + dptr dfunc = job->f->dfunc; + int ftz = job->ftz; + MTdata d = tinfo->d; + cl_uint j, k; + cl_int error; + const char *name = job->f->name; + cl_long *t,*r; + cl_double *s,*s2; + + Force64BitFPUPrecision(); + + // start the map of the output arrays + cl_event e[ VECTOR_SIZE_COUNT ]; + cl_long *out[ VECTOR_SIZE_COUNT ]; + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_long*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_WRITE, 0, buffer_size, 0, NULL, e + j, &error); + if( error || NULL == out[j]) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush failed\n" ); + + //Init input array + double *p = (double *)gIn + thread_id * buffer_elements; + double *p2 = (double *)gIn2 + thread_id * buffer_elements; + j = 0; + int totalSpecialValueCount = specialValuesDoubleCount * specialValuesDoubleCount; + int indx = (totalSpecialValueCount - 1) / buffer_elements; + + if( job_id <= (cl_uint)indx ) + { // test edge cases + uint32_t x, y; + + x = (job_id * buffer_elements) % specialValuesDoubleCount; + y = (job_id * buffer_elements) / specialValuesDoubleCount; + + for( ; j < buffer_elements; j++ ) + { + p[j] = specialValuesDouble[x]; + p2[j] = specialValuesDouble[y]; + if( ++x >= specialValuesDoubleCount ) + { + x = 0; + y++; + if( y >= specialValuesDoubleCount ) + break; + } + } + } + + //Init any remaining values. + for( ; j < buffer_elements; j++ ) + { + ((cl_ulong*)p)[j] = genrand_int64(d); + ((cl_ulong*)p2)[j] = genrand_int64(d); + } + + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf, CL_FALSE, 0, buffer_size, p, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf2, CL_FALSE, 0, buffer_size, p2, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + //Wait for the map to finish + if( (error = clWaitForEvents(1, e + j) )) + { + vlog_error( "Error: clWaitForEvents failed! err: %d\n", error ); + goto exit; + } + if( (error = clReleaseEvent( e[j] ) )) + { + vlog_error( "Error: clReleaseEvent failed! err: %d\n", error ); + goto exit; + } + + // Fill the result buffer with garbage, so that old results don't carry over + uint32_t pattern = 0xffffdead; + memset_pattern4(out[j], &pattern, buffer_size); + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueMapBuffer failed! err: %d\n", error ); + goto exit; + } + + // run the kernel + size_t vectorCount = (buffer_elements + sizeValues[j] - 1) / sizeValues[j]; + cl_kernel kernel = job->k[j][thread_id]; //each worker thread has its own copy of the cl_kernel + cl_program program = job->programs[j]; + + if( ( error = clSetKernelArg( kernel, 0, sizeof( tinfo->outBuf[j] ), &tinfo->outBuf[j] ))){ LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 1, sizeof( tinfo->inBuf ), &tinfo->inBuf ) )) { LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 2, sizeof( tinfo->inBuf2 ), &tinfo->inBuf2 ) )) { LogBuildError(program); return error; } + + if( (error = clEnqueueNDRangeKernel(tinfo->tQueue, kernel, 1, NULL, &vectorCount, NULL, 0, NULL, NULL))) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 2 failed\n" ); + + if( gSkipCorrectnessTesting ) + return CL_SUCCESS; + + //Calculate the correctly rounded reference result + r = (cl_long *)gOut_Ref + thread_id * buffer_elements; + s = (cl_double *)gIn + thread_id * buffer_elements; + s2 = (cl_double *)gIn2 + thread_id * buffer_elements; + for( j = 0; j < buffer_elements; j++ ) + r[j] = dfunc.i_ff( s[j], s2[j] ); + + + // Read the data back -- no need to wait for the first N-1 buffers. This is an in order queue. + for( j = gMinVectorSizeIndex; j + 1 < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_long*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + } + + // Wait for the last buffer + out[j] = (cl_long*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_TRUE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + goto exit; + } + + //Verify data + t = (cl_long *)r; + for( j = 0; j < buffer_elements; j++ ) + { + cl_long *q = (cl_long *) out[0]; + + // If we aren't getting the correctly rounded result + if( gMinVectorSizeIndex == 0 && t[j] != q[j] ) + { + if( ftz ) + { + if( IsDoubleSubnormal( s[j]) ) + { + if( IsDoubleSubnormal( s2[j] ) ) + { + int64_t correct = dfunc.i_ff( 0.0f, 0.0f ); + int64_t correct2 = dfunc.i_ff( 0.0f, -0.0f ); + int64_t correct3 = dfunc.i_ff( -0.0f, 0.0f ); + int64_t correct4 = dfunc.i_ff( -0.0f, -0.0f ); + + if( correct == q[j] || correct2 == q[j] || correct3 == q[j] || correct4 == q[j] ) + continue; + } + else + { + int64_t correct = dfunc.i_ff( 0.0f, s2[j] ); + int64_t correct2 = dfunc.i_ff( -0.0f, s2[j] ); + if( correct == q[j] || correct2 == q[j] ) + continue; + } + } + else if( IsDoubleSubnormal( s2[j] ) ) + { + int64_t correct = dfunc.i_ff( s[j], 0.0f ); + int64_t correct2 = dfunc.i_ff( s[j], -0.0f ); + if( correct == q[j] || correct2 == q[j] ) + continue; + } + + } + + uint64_t err = t[j] - q[j]; + if( q[j] > t[j] ) + err = q[j] - t[j]; + vlog_error( "\nERROR: %s: %lld ulp error at {%.13la, %.13la}: *%lld vs. %lld (index: %d)\n", name, err, ((double*) s)[j], ((double*) s2)[j], t[j], q[j], j ); + error = -1; + goto exit; + } + + + for( k = MAX(1, gMinVectorSizeIndex); k < gMaxVectorSizeIndex; k++ ) + { + q = (cl_long*) out[k]; + // If we aren't getting the correctly rounded result + if( -t[j] != q[j] ) + { + if( ftz ) + { + if( IsDoubleSubnormal( s[j]) ) + { + if( IsDoubleSubnormal( s2[j] ) ) + { + int64_t correct = -dfunc.i_ff( 0.0f, 0.0f ); + int64_t correct2 = -dfunc.i_ff( 0.0f, -0.0f ); + int64_t correct3 = -dfunc.i_ff( -0.0f, 0.0f ); + int64_t correct4 = -dfunc.i_ff( -0.0f, -0.0f ); + + if( correct == q[j] || correct2 == q[j] || correct3 == q[j] || correct4 == q[j] ) + continue; + } + else + { + int64_t correct = -dfunc.i_ff( 0.0f, s2[j] ); + int64_t correct2 = -dfunc.i_ff( -0.0f, s2[j] ); + if( correct == q[j] || correct2 == q[j] ) + continue; + } + } + else if( IsDoubleSubnormal( s2[j] ) ) + { + int64_t correct = -dfunc.i_ff( s[j], 0.0f ); + int64_t correct2 = -dfunc.i_ff( s[j], -0.0f ); + if( correct == q[j] || correct2 == q[j] ) + continue; + } + + } + + uint64_t err = -t[j] - q[j]; + if( q[j] > -t[j] ) + err = q[j] + t[j]; + vlog_error( "\nERROR: %sD%s: %lld ulp error at {%.13la, %.13la}: *%lld vs. %lld (index: %d)\n", name, sizeNames[k], err, ((double*) s)[j], ((double*) s2)[j], -t[j], q[j], j ); + error = -1; + goto exit; + } + } + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL)) ) + { + vlog_error( "Error: clEnqueueUnmapMemObject %d failed 2! err: %d\n", j, error ); + return error; + } + } + + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 3 failed\n" ); + + + if( 0 == ( base & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10u scale:%10u buf_elements:%10zd ThreadCount:%2u\n", base, job->step, job->scale, buffer_elements, job->threadCount); + } else + { + vlog("." ); + } + fflush(stdout); + } + +exit: + return error; +} + diff --git a/test_conformance/math_brute_force/macro_unary.c b/test_conformance/math_brute_force/macro_unary.c new file mode 100644 index 00000000..74e1dece --- /dev/null +++ b/test_conformance/math_brute_force/macro_unary.c @@ -0,0 +1,965 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Utility.h" + +#include +#include "FunctionList.h" + +int TestMacro_Int_Float(const Func *f, MTdata); +int TestMacro_Int_Double(const Func *f, MTdata); + +#if defined( __cplusplus) + extern "C" +#endif +const vtbl _macro_unary = { "macro_unary", TestMacro_Int_Float, TestMacro_Int_Double }; + +static int BuildKernel( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ); +static int BuildKernelDouble( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ); + +static int BuildKernel( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global int", sizeNames[vectorSize], "* out, __global float", sizeNames[vectorSize], "* in)\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in[i] );\n" + "}\n" + }; + const char *c3[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global int* out, __global float* in)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " float3 f0 = vload3( 0, in + 3 * i );\n" + " int3 i0 = ", name, "( f0 );\n" + " vstore3( i0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " int3 i0;\n" + " float3 f0;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (float3)( in[3*i], 0xdead, 0xdead ); \n" + " break;\n" + " case 0:\n" + " f0 = (float3)( in[3*i], in[3*i+1], 0xdead ); \n" + " break;\n" + " }\n" + " i0 = ", name, "( f0 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = i0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = i0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernels(kern, (cl_uint) kernSize, testName, kernel_count, k, p); +} + +static int BuildKernelDouble( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global long", sizeNames[vectorSize], "* out, __global double", sizeNames[vectorSize], "* in)\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in[i] );\n" + "}\n" + }; + + const char *c3[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global long* out, __global double* in)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " double3 d0 = vload3( 0, in + 3 * i );\n" + " long3 l0 = ", name, "( d0 );\n" + " vstore3( l0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " double3 d0;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " d0 = (double3)( in[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " d0 = (double3)( in[3*i], in[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " long3 l0 = ", name, "( d0 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = l0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = l0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernels(kern, (cl_uint) kernSize, testName, kernel_count, k, p); +} + +typedef struct BuildKernelInfo +{ + cl_uint offset; // the first vector size to build + cl_uint kernel_count; + cl_kernel **kernels; + cl_program *programs; + const char *nameInCode; +}BuildKernelInfo; + +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernel( info->nameInCode, i, info->kernel_count, info->kernels[i], info->programs + i ); +} + +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernelDouble( info->nameInCode, i, info->kernel_count, info->kernels[i], info->programs + i ); +} + +//Thread specific data for a worker thread +typedef struct ThreadInfo +{ + cl_mem inBuf; // input buffer for the thread + cl_mem outBuf[ VECTOR_SIZE_COUNT ]; // output buffers for the thread + cl_command_queue tQueue; // per thread command queue to improve performance +}ThreadInfo; + +typedef struct TestInfo +{ + size_t subBufferSize; // Size of the sub-buffer in elements + const Func *f; // A pointer to the function info + cl_program programs[ VECTOR_SIZE_COUNT ]; // programs for various vector sizes + cl_kernel *k[VECTOR_SIZE_COUNT ]; // arrays of thread-specific kernels for each worker thread: k[vector_size][thread_id] + ThreadInfo *tinfo; // An array of thread specific information for each worker thread + cl_uint threadCount; // Number of worker threads + cl_uint step; // step between each chunk and the next. + cl_uint scale; // stride between individual test values + int ftz; // non-zero if running in flush to zero mode + +}TestInfo; + +static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *p ); + +int TestMacro_Int_Float(const Func *f, MTdata d) +{ + TestInfo test_info; + cl_int error; + size_t i, j; + + logFunctionInfo(f->name,sizeof(cl_float),gTestFastRelaxed); + + // Init test_info + memset( &test_info, 0, sizeof( test_info ) ); + test_info.threadCount = GetThreadCount(); + test_info.subBufferSize = BUFFER_SIZE / (sizeof( cl_float) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = 1; + if (gWimpyMode ) + { + test_info.subBufferSize = gWimpyBufferSize / (sizeof( cl_float) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = (cl_uint) sizeof(cl_float) * 2 * gWimpyReductionFactor; + } + test_info.step = (cl_uint) test_info.subBufferSize * test_info.scale; + test_info.f = f; + test_info.ftz = f->ftz || gForceFTZ || 0 == (CL_FP_DENORM & gFloatCapabilities); + // cl_kernels aren't thread safe, so we make one for each vector size for every thread + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + size_t array_size = test_info.threadCount * sizeof( cl_kernel ); + test_info.k[i] = (cl_kernel*)malloc( array_size ); + if( NULL == test_info.k[i] ) + { + vlog_error( "Error: Unable to allocate storage for kernels!\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.k[i], 0, array_size ); + } + test_info.tinfo = (ThreadInfo*)malloc( test_info.threadCount * sizeof(*test_info.tinfo) ); + if( NULL == test_info.tinfo ) + { + vlog_error( "Error: Unable to allocate storage for thread specific data.\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.tinfo, 0, test_info.threadCount * sizeof(*test_info.tinfo) ); + for( i = 0; i < test_info.threadCount; i++ ) + { + cl_buffer_region region = { i * test_info.subBufferSize * sizeof( cl_float), test_info.subBufferSize * sizeof( cl_float) }; + test_info.tinfo[i].inBuf = clCreateSubBuffer( gInBuffer, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + test_info.tinfo[i].outBuf[j] = clCreateSubBuffer( gOutBuffer[j], CL_MEM_WRITE_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].outBuf[j] ) + { + vlog_error( "Error: Unable to create sub-buffer of gOutBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + } + test_info.tinfo[i].tQueue = clCreateCommandQueueWithProperties(gContext, gDevice, 0, &error); + if( NULL == test_info.tinfo[i].tQueue || error ) + { + vlog_error( "clCreateCommandQueue failed. (%d)\n", error ); + goto exit; + } + } + + // Init the kernels + { + BuildKernelInfo build_info = { gMinVectorSizeIndex, test_info.threadCount, test_info.k, test_info.programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_FloatFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + goto exit; + } + + if( !gSkipCorrectnessTesting ) + { + error = ThreadPool_Do( TestFloat, (cl_uint) ((1ULL<<32) / test_info.step), &test_info ); + + if( error ) + goto exit; + + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input array + cl_uint *p = (cl_uint *)gIn; + for( j = 0; j < BUFFER_SIZE / sizeof( float ); j++ ) + p[j] = genrand_int32(d); + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, BUFFER_SIZE, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_float ) * sizeValues[j]; + size_t localCount = (BUFFER_SIZE + vectorSize - 1) / vectorSize; // BUFFER_SIZE / vectorSize rounded up + if( ( error = clSetKernelArg( test_info.k[j][0], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(test_info.programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( i = 0; i < PERF_LOOP_COUNT; i++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, test_info.k[j][0], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (BUFFER_SIZE / sizeof( float ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sf%s", f->name, sizeNames[j] ); + } + } + + vlog( "\n" ); + +exit: + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + clReleaseProgram(test_info.programs[i]); + if( test_info.k[i] ) + { + for( j = 0; j < test_info.threadCount; j++ ) + clReleaseKernel(test_info.k[i][j]); + + free( test_info.k[i] ); + } + } + if( test_info.tinfo ) + { + for( i = 0; i < test_info.threadCount; i++ ) + { + clReleaseMemObject(test_info.tinfo[i].inBuf); + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + clReleaseMemObject(test_info.tinfo[i].outBuf[j]); + clReleaseCommandQueue(test_info.tinfo[i].tQueue); + } + + free( test_info.tinfo ); + } + + return error; +} + +static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *data ) +{ + const TestInfo *job = (const TestInfo *) data; + size_t buffer_elements = job->subBufferSize; + size_t buffer_size = buffer_elements * sizeof( cl_float ); + cl_uint scale = job->scale; + cl_uint base = job_id * (cl_uint) job->step; + ThreadInfo *tinfo = job->tinfo + thread_id; + fptr func = job->f->func; + int ftz = job->ftz; + cl_uint j, k; + cl_int error = CL_SUCCESS; + const char *name = job->f->name; + + int signbit_test = 0; + if(!strcmp(name, "signbit")) + signbit_test = 1; + + #define ref_func(s) ( signbit_test ? func.i_f_f( s ) : func.i_f( s ) ) + + // start the map of the output arrays + cl_event e[ VECTOR_SIZE_COUNT ]; + cl_int *out[ VECTOR_SIZE_COUNT ]; + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_int*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_WRITE, 0, buffer_size, 0, NULL, e + j, &error); + if( error || NULL == out[j]) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush failed\n" ); + + // Write the new values to the input array + cl_uint *p = (cl_uint*) gIn + thread_id * buffer_elements; + for( j = 0; j < buffer_elements; j++ ) + p[j] = base + j * scale; + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf, CL_FALSE, 0, buffer_size, p, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + return error; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + //Wait for the map to finish + if( (error = clWaitForEvents(1, e + j) )) + { + vlog_error( "Error: clWaitForEvents failed! err: %d\n", error ); + return error; + } + if( (error = clReleaseEvent( e[j] ) )) + { + vlog_error( "Error: clReleaseEvent failed! err: %d\n", error ); + return error; + } + + // Fill the result buffer with garbage, so that old results don't carry over + uint32_t pattern = 0xffffdead; + memset_pattern4(out[j], &pattern, buffer_size); + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueMapBuffer failed! err: %d\n", error ); + return error; + } + + // run the kernel + size_t vectorCount = (buffer_elements + sizeValues[j] - 1) / sizeValues[j]; + cl_kernel kernel = job->k[j][thread_id]; //each worker thread has its own copy of the cl_kernel + cl_program program = job->programs[j]; + + if( ( error = clSetKernelArg( kernel, 0, sizeof( tinfo->outBuf[j] ), &tinfo->outBuf[j] ))){ LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 1, sizeof( tinfo->inBuf ), &tinfo->inBuf ) )) { LogBuildError(program); return error; } + + if( (error = clEnqueueNDRangeKernel(tinfo->tQueue, kernel, 1, NULL, &vectorCount, NULL, 0, NULL, NULL))) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + return error; + } + } + + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 2 failed\n" ); + + if( gSkipCorrectnessTesting ) + return CL_SUCCESS; + + //Calculate the correctly rounded reference result + cl_int *r = (cl_int *)gOut_Ref + thread_id * buffer_elements; + float *s = (float *)p; + for( j = 0; j < buffer_elements; j++ ) + r[j] = ref_func( s[j] ); + + // Read the data back -- no need to wait for the first N-1 buffers. This is an in order queue. + for( j = gMinVectorSizeIndex; j + 1 < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_int*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + // Wait for the last buffer + out[j] = (cl_int*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_TRUE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + + //Verify data + cl_int *t = (cl_int *)r; + for( j = 0; j < buffer_elements; j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + cl_int *q = out[0]; + + // If we aren't getting the correctly rounded result + if( gMinVectorSizeIndex == 0 && t[j] != q[j]) + { + // If we aren't getting the correctly rounded result + if( ftz ) + { + if( IsFloatSubnormal( s[j]) ) + { + int correct = ref_func( +0.0f ); + int correct2 = ref_func( -0.0f ); + if( correct == q[j] || correct2 == q[j] ) + continue; + } + } + + uint32_t err = t[j] - q[j]; + if( q[j] > t[j] ) + err = q[j] - t[j]; + vlog_error( "\nERROR: %s: %d ulp error at %a: *%d vs. %d\n", name, err, ((float*) s)[j], t[j], q[j] ); + error = -1; + goto exit; + } + + + for( k = MAX(1, gMinVectorSizeIndex); k < gMaxVectorSizeIndex; k++ ) + { + q = out[k]; + // If we aren't getting the correctly rounded result + if( -t[j] != q[j] ) + { + if( ftz ) + { + if( IsFloatSubnormal( s[j])) + { + int correct = -ref_func( +0.0f ); + int correct2 = -ref_func( -0.0f ); + if( correct == q[j] || correct2 == q[j] ) + continue; + } + } + + uint32_t err = -t[j] - q[j]; + if( q[j] > -t[j] ) + err = q[j] + t[j]; + vlog_error( "\nERROR: %s%s: %d ulp error at %a: *%d vs. %d\n", name, sizeNames[k], err, ((float*) s)[j], -t[j], q[j] ); + error = -1; + goto exit; + } + } + } + } + +exit: + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL)) ) + { + vlog_error( "Error: clEnqueueUnmapMemObject %d failed 2! err: %d\n", j, error ); + return error; + } + } + + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 3 failed\n" ); + + + if( 0 == ( base & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10u scale:%10u buf_elements:%10zd ThreadCount:%2u\n", base, job->step, job->scale, buffer_elements, job->threadCount); + } else + { + vlog("." ); + } + fflush(stdout); + } + + return error; +} + +static cl_int TestDouble( cl_uint job_id, cl_uint thread_id, void *data ); + +int TestMacro_Int_Double(const Func *f, MTdata d) +{ + TestInfo test_info; + cl_int error; + size_t i, j; + + logFunctionInfo(f->name,sizeof(cl_double),gTestFastRelaxed); + // Init test_info + memset( &test_info, 0, sizeof( test_info ) ); + test_info.threadCount = GetThreadCount(); + test_info.subBufferSize = BUFFER_SIZE / (sizeof( cl_double) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = 1; + if (gWimpyMode ) + { + test_info.subBufferSize = gWimpyBufferSize / (sizeof( cl_double) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = (cl_uint) sizeof(cl_double) * 2 * gWimpyReductionFactor; + } + + test_info.step = (cl_uint) test_info.subBufferSize * test_info.scale; + test_info.f = f; + test_info.ftz = f->ftz || gForceFTZ; + + // cl_kernels aren't thread safe, so we make one for each vector size for every thread + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + size_t array_size = test_info.threadCount * sizeof( cl_kernel ); + test_info.k[i] = (cl_kernel*)malloc( array_size ); + if( NULL == test_info.k[i] ) + { + vlog_error( "Error: Unable to allocate storage for kernels!\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.k[i], 0, array_size ); + } + test_info.tinfo = (ThreadInfo*)malloc( test_info.threadCount * sizeof(*test_info.tinfo) ); + if( NULL == test_info.tinfo ) + { + vlog_error( "Error: Unable to allocate storage for thread specific data.\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.tinfo, 0, test_info.threadCount * sizeof(*test_info.tinfo) ); + for( i = 0; i < test_info.threadCount; i++ ) + { + cl_buffer_region region = { i * test_info.subBufferSize * sizeof( cl_double), test_info.subBufferSize * sizeof( cl_double) }; + test_info.tinfo[i].inBuf = clCreateSubBuffer( gInBuffer, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + /* Qualcomm fix: 9461 read-write flags must be compatible with parent buffer */ + test_info.tinfo[i].outBuf[j] = clCreateSubBuffer( gOutBuffer[j], CL_MEM_WRITE_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + /* Qualcomm fix: end */ + if( error || NULL == test_info.tinfo[i].outBuf[j] ) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + } + test_info.tinfo[i].tQueue = clCreateCommandQueueWithProperties(gContext, gDevice, 0, &error); + if( NULL == test_info.tinfo[i].tQueue || error ) + { + vlog_error( "clCreateCommandQueue failed. (%d)\n", error ); + goto exit; + } + } + + // Init the kernels + { + BuildKernelInfo build_info = { gMinVectorSizeIndex, test_info.threadCount, test_info.k, test_info.programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_DoubleFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + goto exit; + } + + if( !gSkipCorrectnessTesting ) + { + error = ThreadPool_Do( TestDouble, (cl_uint) ((1ULL<<32) / test_info.step), &test_info ); + + if( error ) + goto exit; + + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input array + cl_ulong *p = (cl_ulong *)gIn; + for( j = 0; j < BUFFER_SIZE / sizeof( cl_double ); j++ ) + p[j] = DoubleFromUInt32(genrand_int32(d)); + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, BUFFER_SIZE, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_double); + size_t localCount = (BUFFER_SIZE + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg( test_info.k[j][0], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(test_info.programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( i = 0; i < PERF_LOOP_COUNT; i++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, test_info.k[j][0], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (BUFFER_SIZE / sizeof( double ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sD%s", f->name, sizeNames[j] ); + } + for( ; j < gMaxVectorSizeIndex; j++ ) + vlog( "\t -- " ); + } + + vlog( "\n" ); + +exit: + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + clReleaseProgram(test_info.programs[i]); + if( test_info.k[i] ) + { + for( j = 0; j < test_info.threadCount; j++ ) + clReleaseKernel(test_info.k[i][j]); + + free( test_info.k[i] ); + } + } + if( test_info.tinfo ) + { + for( i = 0; i < test_info.threadCount; i++ ) + { + clReleaseMemObject(test_info.tinfo[i].inBuf); + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + clReleaseMemObject(test_info.tinfo[i].outBuf[j]); + clReleaseCommandQueue(test_info.tinfo[i].tQueue); + } + + free( test_info.tinfo ); + } + + return error; +} + +static cl_int TestDouble( cl_uint job_id, cl_uint thread_id, void *data ) +{ + const TestInfo *job = (const TestInfo *) data; + size_t buffer_elements = job->subBufferSize; + size_t buffer_size = buffer_elements * sizeof( cl_double ); + cl_uint scale = job->scale; + cl_uint base = job_id * (cl_uint) job->step; + ThreadInfo *tinfo = job->tinfo + thread_id; + dptr dfunc = job->f->dfunc; + cl_uint j, k; + cl_int error; + int ftz = job->ftz; + const char *name = job->f->name; + + Force64BitFPUPrecision(); + + // start the map of the output arrays + cl_event e[ VECTOR_SIZE_COUNT ]; + cl_long *out[ VECTOR_SIZE_COUNT ]; + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_long*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_WRITE, 0, buffer_size, 0, NULL, e + j, &error); + if( error || NULL == out[j]) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush failed\n" ); + + // Write the new values to the input array + cl_double *p = (cl_double*) gIn + thread_id * buffer_elements; + for( j = 0; j < buffer_elements; j++ ) + p[j] = DoubleFromUInt32( base + j * scale); + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf, CL_FALSE, 0, buffer_size, p, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + return error; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + //Wait for the map to finish + if( (error = clWaitForEvents(1, e + j) )) + { + vlog_error( "Error: clWaitForEvents failed! err: %d\n", error ); + return error; + } + if( (error = clReleaseEvent( e[j] ) )) + { + vlog_error( "Error: clReleaseEvent failed! err: %d\n", error ); + return error; + } + + // Fill the result buffer with garbage, so that old results don't carry over + uint32_t pattern = 0xffffdead; + memset_pattern4(out[j], &pattern, buffer_size); + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueMapBuffer failed! err: %d\n", error ); + return error; + } + + // run the kernel + size_t vectorCount = (buffer_elements + sizeValues[j] - 1) / sizeValues[j]; + cl_kernel kernel = job->k[j][thread_id]; //each worker thread has its own copy of the cl_kernel + cl_program program = job->programs[j]; + + if( ( error = clSetKernelArg( kernel, 0, sizeof( tinfo->outBuf[j] ), &tinfo->outBuf[j] ))){ LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 1, sizeof( tinfo->inBuf ), &tinfo->inBuf ) )) { LogBuildError(program); return error; } + + if( (error = clEnqueueNDRangeKernel(tinfo->tQueue, kernel, 1, NULL, &vectorCount, NULL, 0, NULL, NULL))) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + return error; + } + } + + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 2 failed\n" ); + + if( gSkipCorrectnessTesting ) + return CL_SUCCESS; + + //Calculate the correctly rounded reference result + cl_long *r = (cl_long *)gOut_Ref + thread_id * buffer_elements; + cl_double *s = (cl_double *)p; + for( j = 0; j < buffer_elements; j++ ) + r[j] = dfunc.i_f( s[j] ); + + // Read the data back -- no need to wait for the first N-1 buffers. This is an in order queue. + for( j = gMinVectorSizeIndex; j + 1 < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_long*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + // Wait for the last buffer + out[j] = (cl_long*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_TRUE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + + + //Verify data + cl_long *t = (cl_long *)r; + for( j = 0; j < buffer_elements; j++ ) + { + cl_long *q = out[0]; + + + // If we aren't getting the correctly rounded result + if( gMinVectorSizeIndex == 0 && t[j] != q[j]) + { + // If we aren't getting the correctly rounded result + if( ftz ) + { + if( IsDoubleSubnormal( s[j]) ) + { + cl_long correct = dfunc.i_f( +0.0f ); + cl_long correct2 = dfunc.i_f( -0.0f ); + if( correct == q[j] || correct2 == q[j] ) + continue; + } + } + + cl_ulong err = t[j] - q[j]; + if( q[j] > t[j] ) + err = q[j] - t[j]; + vlog_error( "\nERROR: %sD: %zd ulp error at %.13la: *%zd vs. %zd\n", name, err, ((double*) gIn)[j], t[j], q[j] ); + return -1; + } + + + for( k = MAX(1, gMinVectorSizeIndex); k < gMaxVectorSizeIndex; k++ ) + { + q = out[k]; + // If we aren't getting the correctly rounded result + if( -t[j] != q[j] ) + { + if( ftz ) + { + if( IsDoubleSubnormal( s[j])) + { + int64_t correct = -dfunc.i_f( +0.0f ); + int64_t correct2 = -dfunc.i_f( -0.0f ); + if( correct == q[j] || correct2 == q[j] ) + continue; + } + } + + cl_ulong err = -t[j] - q[j]; + if( q[j] > -t[j] ) + err = q[j] + t[j]; + vlog_error( "\nERROR: %sD%s: %zd ulp error at %.13la: *%zd vs. %zd\n", name, sizeNames[k], err, ((double*) gIn)[j], -t[j], q[j] ); + return -1; + } + } + + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL)) ) + { + vlog_error( "Error: clEnqueueUnmapMemObject %d failed 2! err: %d\n", j, error ); + return error; + } + } + + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 3 failed\n" ); + + + if( 0 == ( base & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10u scale:%10u buf_elements:%10zd ThreadCount:%2u\n", base, job->step, job->scale, buffer_elements, job->threadCount); + } else + { + vlog("." ); + } + fflush(stdout); + } + + return CL_SUCCESS; +} + + + + diff --git a/test_conformance/math_brute_force/mad.c b/test_conformance/math_brute_force/mad.c new file mode 100644 index 00000000..844da097 --- /dev/null +++ b/test_conformance/math_brute_force/mad.c @@ -0,0 +1,1131 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Utility.h" + +#include +#include "FunctionList.h" + +int TestFunc_mad(const Func *f, MTdata); +int TestFunc_mad_Double(const Func *f, MTdata); + +#if defined( __cplusplus) + extern "C" +#endif +const vtbl _mad_tbl = { "ternary", TestFunc_mad, TestFunc_mad_Double }; + +static int BuildKernel( const char *name, int vectorSize, cl_kernel *k, cl_program *p ); +static int BuildKernelDouble( const char *name, int vectorSize, cl_kernel *k, cl_program *p ); + +static int BuildKernel( const char *name, int vectorSize, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { + "__kernel void math_kernel", sizeNames[vectorSize], "( __global float", sizeNames[vectorSize], "* out, __global float", sizeNames[vectorSize], "* in1, __global float", sizeNames[vectorSize], "* in2, __global float", sizeNames[vectorSize], "* in3 )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in1[i], in2[i], in3[i] );\n" + "}\n" + }; + const char *c3[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global float* out, __global float* in, __global float* in2, __global float* in3)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " float3 f0 = vload3( 0, in + 3 * i );\n" + " float3 f1 = vload3( 0, in2 + 3 * i );\n" + " float3 f2 = vload3( 0, in3 + 3 * i );\n" + " f0 = ", name, "( f0, f1, f2 );\n" + " vstore3( f0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " float3 f0, f1, f2;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (float3)( in[3*i], NAN, NAN ); \n" + " f1 = (float3)( in2[3*i], NAN, NAN ); \n" + " f2 = (float3)( in3[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " f0 = (float3)( in[3*i], in[3*i+1], NAN ); \n" + " f1 = (float3)( in2[3*i], in2[3*i+1], NAN ); \n" + " f2 = (float3)( in3[3*i], in3[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " f0 = ", name, "( f0, f1, f2 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = f0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = f0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernel(kern, (cl_uint) kernSize, testName, k, p); +} + +static int BuildKernelDouble( const char *name, int vectorSize, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double", sizeNames[vectorSize], "* out, __global double", sizeNames[vectorSize], "* in1, __global double", sizeNames[vectorSize], "* in2, __global double", sizeNames[vectorSize], "* in3 )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in1[i], in2[i], in3[i] );\n" + "}\n" + }; + const char *c3[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double* out, __global double* in, __global double* in2, __global double* in3)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " double3 d0 = vload3( 0, in + 3 * i );\n" + " double3 d1 = vload3( 0, in2 + 3 * i );\n" + " double3 d2 = vload3( 0, in3 + 3 * i );\n" + " d0 = ", name, "( d0, d1, d2 );\n" + " vstore3( d0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " double3 d0, d1, d2;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " d0 = (double3)( in[3*i], NAN, NAN ); \n" + " d1 = (double3)( in2[3*i], NAN, NAN ); \n" + " d2 = (double3)( in3[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " d0 = (double3)( in[3*i], in[3*i+1], NAN ); \n" + " d1 = (double3)( in2[3*i], in2[3*i+1], NAN ); \n" + " d2 = (double3)( in3[3*i], in3[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " d0 = ", name, "( d0, d1, d2 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = d0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = d0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernel(kern, (cl_uint) kernSize, testName, k, p); +} + +typedef struct BuildKernelInfo +{ + cl_uint offset; // the first vector size to build + cl_kernel *kernels; + cl_program *programs; + const char *nameInCode; +}BuildKernelInfo; + +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernel( info->nameInCode, i, info->kernels + i, info->programs + i ); +} + +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernelDouble( info->nameInCode, i, info->kernels + i, info->programs + i ); +} + +int TestFunc_mad(const Func *f, MTdata d) +{ + uint64_t i; + uint32_t j, k; + int error; + + logFunctionInfo(f->name,sizeof(cl_float),gTestFastRelaxed); + + cl_program programs[ VECTOR_SIZE_COUNT ]; + cl_kernel kernels[ VECTOR_SIZE_COUNT ]; + float maxError = 0.0f; +// int ftz = f->ftz || gForceFTZ || 0 == (CL_FP_DENORM & gFloatCapabilities); + float maxErrorVal = 0.0f; + float maxErrorVal2 = 0.0f; + float maxErrorVal3 = 0.0f; + size_t bufferSize = (gWimpyMode)? gWimpyBufferSize: BUFFER_SIZE; + uint64_t step = bufferSize / sizeof( float ); + + if( gWimpyMode ) + { + step = (1ULL<<32) * gWimpyReductionFactor / (512); + } + // Init the kernels + BuildKernelInfo build_info = { gMinVectorSizeIndex, kernels, programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_FloatFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + return error; +/* + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + if( (error = BuildKernel( f->nameInCode, (int) i, kernels + i, programs + i) ) ) + return error; +*/ + + for( i = 0; i < (1ULL<<32); i += step ) + { + //Init input array + uint32_t *p = (uint32_t *)gIn; + uint32_t *p2 = (uint32_t *)gIn2; + uint32_t *p3 = (uint32_t *)gIn3; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + p[j] = genrand_int32(d); + p2[j] = genrand_int32(d); + p3[j] = genrand_int32(d); + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, bufferSize, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer3, CL_FALSE, 0, bufferSize, gIn3, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer3 ***\n", error ); + return error; + } + + // write garbage into output arrays + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + uint32_t pattern = 0xffffdead; + memset_pattern4(gOut[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer[j], CL_FALSE, 0, bufferSize, gOut[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2(%d) ***\n", error, j ); + goto exit; + } + } + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_float ) * sizeValues[j]; + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; // bufferSize / vectorSize rounded up + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 3, sizeof( gInBuffer3 ), &gInBuffer3 ) )) { LogBuildError(programs[j]); goto exit; } + + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(gQueue) )) + vlog( "clFlush failed\n" ); + + //Calculate the correctly rounded reference result + float *r = (float *)gOut_Ref; + float *s = (float *)gIn; + float *s2 = (float *)gIn2; + float *s3 = (float *)gIn3; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + r[j] = (float) f->func.f_fff( s[j], s2[j], s3[j] ); + + // Read the data back + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0, bufferSize, gOut[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray failed %d\n", error ); + goto exit; + } + } + + if( gSkipCorrectnessTesting ) + break; + + //Verify data -- Commented out on purpose. no verification possible. MAD is a random number generator. +/* + uint32_t *t = gOut_Ref; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + uint32_t *q = gOut[k]; + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + float test = ((float*) q)[j]; + double correct = f->func.f_fff( s[j], s2[j], s3[j] ); + float err = Ulp_Error( test, correct ); + int fail = ! (fabsf(err) <= f->float_ulps); + + if( fail && ftz ) + { + // retry per section 6.5.3.2 + if( IsFloatSubnormal(correct) ) + { // look at me, + fail = fail && ( test != 0.0f ); + if( ! fail ) + err = 0.0f; + } + + // retry per section 6.5.3.3 + if( fail && IsFloatSubnormal( s[j] ) ) + { // look at me, + double correct2 = f->func.f_fff( 0.0, s2[j], s3[j] ); + double correct3 = f->func.f_fff( -0.0, s2[j], s3[j] ); + float err2 = Ulp_Error( test, correct2 ); + float err3 = Ulp_Error( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= f->float_ulps)) && (!(fabsf(err3) <= f->float_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal(correct2, f->float_ulps ) || IsFloatResultSubnormal(correct3, f->float_ulps ) ) + { // look at me now, + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + + //try with first two args as zero + if( IsFloatSubnormal( s2[j] ) ) + { // its fun to have fun, + correct2 = f->func.f_fff( 0.0, 0.0, s3[j] ); + correct3 = f->func.f_fff( -0.0, 0.0, s3[j] ); + double correct4 = f->func.f_fff( 0.0, -0.0, s3[j] ); + double correct5 = f->func.f_fff( -0.0, -0.0, s3[j] ); + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + float err4 = Ulp_Error( test, correct4 ); + float err5 = Ulp_Error( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= f->float_ulps)) && (!(fabsf(err3) <= f->float_ulps)) && + (!(fabsf(err4) <= f->float_ulps)) && (!(fabsf(err5) <= f->float_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal(correct2, f->float_ulps ) || IsFloatResultSubnormal(correct3, f->float_ulps ) || + IsFloatResultSubnormal(correct4, f->float_ulps ) || IsFloatResultSubnormal(correct5, f->float_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + + if( IsFloatSubnormal( s3[j] ) ) + { // but you have to know how! + correct2 = f->func.f_fff( 0.0, 0.0, 0.0f ); + correct3 = f->func.f_fff( -0.0, 0.0, 0.0f ); + correct4 = f->func.f_fff( 0.0, -0.0, 0.0f ); + correct5 = f->func.f_fff( -0.0, -0.0, 0.0f ); + double correct6 = f->func.f_fff( 0.0, 0.0, -0.0f ); + double correct7 = f->func.f_fff( -0.0, 0.0, -0.0f ); + double correct8 = f->func.f_fff( 0.0, -0.0, -0.0f ); + double correct9 = f->func.f_fff( -0.0, -0.0, -0.0f ); + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + err4 = Ulp_Error( test, correct4 ); + err5 = Ulp_Error( test, correct5 ); + float err6 = Ulp_Error( test, correct6 ); + float err7 = Ulp_Error( test, correct7 ); + float err8 = Ulp_Error( test, correct8 ); + float err9 = Ulp_Error( test, correct9 ); + fail = fail && ((!(fabsf(err2) <= f->float_ulps)) && (!(fabsf(err3) <= f->float_ulps)) && + (!(fabsf(err4) <= f->float_ulps)) && (!(fabsf(err5) <= f->float_ulps)) && + (!(fabsf(err5) <= f->float_ulps)) && (!(fabsf(err6) <= f->float_ulps)) && + (!(fabsf(err7) <= f->float_ulps)) && (!(fabsf(err8) <= f->float_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + if( fabsf( err6 ) < fabsf(err ) ) + err = err6; + if( fabsf( err7 ) < fabsf(err ) ) + err = err7; + if( fabsf( err8 ) < fabsf(err ) ) + err = err8; + if( fabsf( err9 ) < fabsf(err ) ) + err = err9; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal(correct2, f->float_ulps ) || IsFloatResultSubnormal(correct3, f->float_ulps ) || + IsFloatResultSubnormal(correct4, f->float_ulps ) || IsFloatResultSubnormal(correct5, f->float_ulps ) || + IsFloatResultSubnormal( correct6, f->float_ulps ) || IsFloatResultSubnormal(correct7, f->float_ulps ) || + IsFloatResultSubnormal(correct8, f->float_ulps ) || IsFloatResultSubnormal( correct9, f->float_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + else if( IsFloatSubnormal( s3[j] ) ) + { + correct2 = f->func.f_fff( 0.0, s2[j], 0.0 ); + correct3 = f->func.f_fff( -0.0, s2[j], 0.0 ); + double correct4 = f->func.f_fff( 0.0, s2[j], -0.0 ); + double correct5 = f->func.f_fff( -0.0, s2[j], -0.0 ); + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + float err4 = Ulp_Error( test, correct4 ); + float err5 = Ulp_Error( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= f->float_ulps)) && (!(fabsf(err3) <= f->float_ulps)) && + (!(fabsf(err4) <= f->float_ulps)) && (!(fabsf(err5) <= f->float_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal(correct2, f->float_ulps ) || IsFloatResultSubnormal(correct3, f->float_ulps ) || + IsFloatResultSubnormal(correct4, f->float_ulps ) || IsFloatResultSubnormal(correct5, f->float_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + else if( fail && IsFloatSubnormal( s2[j] ) ) + { + double correct2 = f->func.f_fff( s[j], 0.0, s3[j] ); + double correct3 = f->func.f_fff( s[j], -0.0, s3[j] ); + float err2 = Ulp_Error( test, correct2 ); + float err3 = Ulp_Error( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= f->float_ulps)) && (!(fabsf(err3) <= f->float_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal(correct2, f->float_ulps ) || IsFloatResultSubnormal(correct3, f->float_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + + //try with second two args as zero + if( IsFloatSubnormal( s3[j] ) ) + { + correct2 = f->func.f_fff( s[j], 0.0, 0.0 ); + correct3 = f->func.f_fff( s[j], -0.0, 0.0 ); + double correct4 = f->func.f_fff( s[j], 0.0, -0.0 ); + double correct5 = f->func.f_fff( s[j], -0.0, -0.0 ); + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + float err4 = Ulp_Error( test, correct4 ); + float err5 = Ulp_Error( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= f->float_ulps)) && (!(fabsf(err3) <= f->float_ulps)) && + (!(fabsf(err4) <= f->float_ulps)) && (!(fabsf(err5) <= f->float_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal(correct2, f->float_ulps ) || IsFloatResultSubnormal(correct3, f->float_ulps ) || + IsFloatResultSubnormal(correct4, f->float_ulps ) || IsFloatResultSubnormal(correct5, f->float_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + else if( fail && IsFloatSubnormal(s3[j]) ) + { + double correct2 = f->func.f_fff( s[j], s2[j], 0.0 ); + double correct3 = f->func.f_fff( s[j], s2[j], -0.0 ); + float err2 = Ulp_Error( test, correct2 ); + float err3 = Ulp_Error( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= f->float_ulps)) && (!(fabsf(err3) <= f->float_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsFloatResultSubnormal(correct2, f->float_ulps ) || IsFloatResultSubnormal(correct3, f->float_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + + if( fabsf(err ) > maxError ) + { + maxError = fabsf(err); + maxErrorVal = s[j]; + maxErrorVal2 = s2[j]; + maxErrorVal3 = s3[j]; + } + + if( fail ) + { + vlog_error( "\nERROR: %s%s: %f ulp error at {%a, %a, %a}: *%a vs. %a\n", f->name, sizeNames[k], err, s[j], s2[j], s3[j], ((float*) gOut_Ref)[j], test ); + error = -1; + goto exit; + } + } + } + } +*/ + if( 0 == (i & 0x0fffffff) ) + { + vlog("." ); + fflush(stdout); + } + } + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "pass" ); + } + + if( gMeasureTimes ) + { + //Init input array + uint32_t *p = (uint32_t *)gIn; + uint32_t *p2 = (uint32_t *)gIn2; + uint32_t *p3 = (uint32_t *)gIn3; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + p[j] = genrand_int32(d); + p2[j] = genrand_int32(d); + p3[j] = genrand_int32(d); + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, bufferSize, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer3, CL_FALSE, 0, bufferSize, gIn3, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer3 ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_float ) * sizeValues[j]; + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; // bufferSize / vectorSize rounded up + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 3, sizeof( gInBuffer3 ), &gInBuffer3 ) )) { LogBuildError(programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( k = 0; k < PERF_LOOP_COUNT; k++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (bufferSize / sizeof( float ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sf%s", f->name, sizeNames[j] ); + } + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t%8.2f @ {%a, %a, %a}", maxError, maxErrorVal, maxErrorVal2, maxErrorVal3 ); + vlog( "\n" ); + +exit: + // Release + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + clReleaseKernel(kernels[k]); + clReleaseProgram(programs[k]); + } + + return error; +} + +int TestFunc_mad_Double(const Func *f, MTdata d) +{ + uint64_t i; + uint32_t j, k; + int error; + cl_program programs[ VECTOR_SIZE_COUNT ]; + cl_kernel kernels[ VECTOR_SIZE_COUNT ]; + float maxError = 0.0f; +// int ftz = f->ftz || gForceFTZ; + double maxErrorVal = 0.0f; + double maxErrorVal2 = 0.0f; + double maxErrorVal3 = 0.0f; + size_t bufferSize = (gWimpyMode)? gWimpyBufferSize: BUFFER_SIZE; + + logFunctionInfo(f->name,sizeof(cl_double),gTestFastRelaxed); + uint64_t step = bufferSize / sizeof( double ); + if( gWimpyMode ) + { + step = (1ULL<<32) * gWimpyReductionFactor / (512); + } + // Init the kernels + BuildKernelInfo build_info = { gMinVectorSizeIndex, kernels, programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_DoubleFn, + gMaxVectorSizeIndex - gMinVectorSizeIndex, + &build_info ) )) + { + return error; + } +/* + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + if( (error = BuildKernelDouble( f->nameInCode, (int) i, kernels + i, programs + i) ) ) + return error; +*/ + + for( i = 0; i < (1ULL<<32); i += step ) + { + //Init input array + double *p = (double *)gIn; + double *p2 = (double *)gIn2; + double *p3 = (double *)gIn3; + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + { + p[j] = DoubleFromUInt32(genrand_int32(d)); + p2[j] = DoubleFromUInt32(genrand_int32(d)); + p3[j] = DoubleFromUInt32(genrand_int32(d)); + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, bufferSize, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer3, CL_FALSE, 0, bufferSize, gIn3, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer3 ***\n", error ); + return error; + } + + // write garbage into output arrays + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + uint32_t pattern = 0xffffdead; + memset_pattern4(gOut[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer[j], CL_FALSE, 0, bufferSize, gOut[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2(%d) ***\n", error, j ); + goto exit; + } + } + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_double ) * sizeValues[j]; + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; // bufferSize / vectorSize rounded up + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 3, sizeof( gInBuffer3 ), &gInBuffer3 ) )) { LogBuildError(programs[j]); goto exit; } + + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(gQueue) )) + vlog( "clFlush failed\n" ); + + //Calculate the correctly rounded reference result + double *r = (double *)gOut_Ref; + double *s = (double *)gIn; + double *s2 = (double *)gIn2; + double *s3 = (double *)gIn3; + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + r[j] = (double) f->dfunc.f_fff( s[j], s2[j], s3[j] ); + + // Read the data back + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0, bufferSize, gOut[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray failed %d\n", error ); + goto exit; + } + } + + if( gSkipCorrectnessTesting ) + break; + + //Verify data -- Commented out on purpose. no verification possible. MAD is a random number generator. +/* + uint64_t *t = gOut_Ref; + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + uint64_t *q = gOut[k]; + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + double test = ((double*) q)[j]; + long double correct = f->dfunc.f_fff( s[j], s2[j], s3[j] ); + float err = Ulp_Error_Double( test, correct ); + int fail = ! (fabsf(err) <= f->double_ulps); + + if( fail && ftz ) + { + // retry per section 6.5.3.2 + if( IsDoubleResultSubnormal(correct, f->double_ulps) ) + { // look at me, + fail = fail && ( test != 0.0f ); + if( ! fail ) + err = 0.0f; + } + + // retry per section 6.5.3.3 + if( fail && IsDoubleSubnormal( s[j] ) ) + { // look at me, + long double correct2 = f->dfunc.f_fff( 0.0, s2[j], s3[j] ); + long double correct3 = f->dfunc.f_fff( -0.0, s2[j], s3[j] ); + float err2 = Ulp_Error_Double( test, correct2 ); + float err3 = Ulp_Error_Double( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= f->double_ulps)) && (!(fabsf(err3) <= f->double_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) ) + { // look at me now, + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + + //try with first two args as zero + if( IsDoubleSubnormal( s2[j] ) ) + { // its fun to have fun, + correct2 = f->dfunc.f_fff( 0.0, 0.0, s3[j] ); + correct3 = f->dfunc.f_fff( -0.0, 0.0, s3[j] ); + long double correct4 = f->dfunc.f_fff( 0.0, -0.0, s3[j] ); + long double correct5 = f->dfunc.f_fff( -0.0, -0.0, s3[j] ); + err2 = Ulp_Error_Double( test, correct2 ); + err3 = Ulp_Error_Double( test, correct3 ); + float err4 = Ulp_Error_Double( test, correct4 ); + float err5 = Ulp_Error_Double( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= f->double_ulps)) && (!(fabsf(err3) <= f->double_ulps)) && + (!(fabsf(err4) <= f->double_ulps)) && (!(fabsf(err5) <= f->double_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) || + IsDoubleResultSubnormal( correct4, f->double_ulps ) || IsDoubleResultSubnormal( correct5, f->double_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + + if( IsDoubleSubnormal( s3[j] ) ) + { // but you have to know how! + correct2 = f->dfunc.f_fff( 0.0, 0.0, 0.0f ); + correct3 = f->dfunc.f_fff( -0.0, 0.0, 0.0f ); + correct4 = f->dfunc.f_fff( 0.0, -0.0, 0.0f ); + correct5 = f->dfunc.f_fff( -0.0, -0.0, 0.0f ); + long double correct6 = f->dfunc.f_fff( 0.0, 0.0, -0.0f ); + long double correct7 = f->dfunc.f_fff( -0.0, 0.0, -0.0f ); + long double correct8 = f->dfunc.f_fff( 0.0, -0.0, -0.0f ); + long double correct9 = f->dfunc.f_fff( -0.0, -0.0, -0.0f ); + err2 = Ulp_Error_Double( test, correct2 ); + err3 = Ulp_Error_Double( test, correct3 ); + err4 = Ulp_Error_Double( test, correct4 ); + err5 = Ulp_Error_Double( test, correct5 ); + float err6 = Ulp_Error_Double( test, correct6 ); + float err7 = Ulp_Error_Double( test, correct7 ); + float err8 = Ulp_Error_Double( test, correct8 ); + float err9 = Ulp_Error_Double( test, correct9 ); + fail = fail && ((!(fabsf(err2) <= f->double_ulps)) && (!(fabsf(err3) <= f->double_ulps)) && + (!(fabsf(err4) <= f->double_ulps)) && (!(fabsf(err5) <= f->double_ulps)) && + (!(fabsf(err5) <= f->double_ulps)) && (!(fabsf(err6) <= f->double_ulps)) && + (!(fabsf(err7) <= f->double_ulps)) && (!(fabsf(err8) <= f->double_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + if( fabsf( err6 ) < fabsf(err ) ) + err = err6; + if( fabsf( err7 ) < fabsf(err ) ) + err = err7; + if( fabsf( err8 ) < fabsf(err ) ) + err = err8; + if( fabsf( err9 ) < fabsf(err ) ) + err = err9; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) || + IsDoubleResultSubnormal( correct4, f->double_ulps ) || IsDoubleResultSubnormal( correct5, f->double_ulps ) || + IsDoubleResultSubnormal( correct6, f->double_ulps ) || IsDoubleResultSubnormal( correct7, f->double_ulps ) || + IsDoubleResultSubnormal( correct8, f->double_ulps ) || IsDoubleResultSubnormal( correct9, f->double_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + else if( IsDoubleSubnormal( s3[j] ) ) + { + correct2 = f->dfunc.f_fff( 0.0, s2[j], 0.0 ); + correct3 = f->dfunc.f_fff( -0.0, s2[j], 0.0 ); + long double correct4 = f->dfunc.f_fff( 0.0, s2[j], -0.0 ); + long double correct5 = f->dfunc.f_fff( -0.0, s2[j], -0.0 ); + err2 = Ulp_Error_Double( test, correct2 ); + err3 = Ulp_Error_Double( test, correct3 ); + float err4 = Ulp_Error_Double( test, correct4 ); + float err5 = Ulp_Error_Double( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= f->double_ulps)) && (!(fabsf(err3) <= f->double_ulps)) && + (!(fabsf(err4) <= f->double_ulps)) && (!(fabsf(err5) <= f->double_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) || + IsDoubleResultSubnormal( correct4, f->double_ulps ) || IsDoubleResultSubnormal( correct5, f->double_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + else if( fail && IsDoubleSubnormal( s2[j] ) ) + { + long double correct2 = f->dfunc.f_fff( s[j], 0.0, s3[j] ); + long double correct3 = f->dfunc.f_fff( s[j], -0.0, s3[j] ); + float err2 = Ulp_Error_Double( test, correct2 ); + float err3 = Ulp_Error_Double( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= f->double_ulps)) && (!(fabsf(err3) <= f->double_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + + //try with second two args as zero + if( IsDoubleSubnormal( s3[j] ) ) + { + correct2 = f->dfunc.f_fff( s[j], 0.0, 0.0 ); + correct3 = f->dfunc.f_fff( s[j], -0.0, 0.0 ); + long double correct4 = f->dfunc.f_fff( s[j], 0.0, -0.0 ); + long double correct5 = f->dfunc.f_fff( s[j], -0.0, -0.0 ); + err2 = Ulp_Error_Double( test, correct2 ); + err3 = Ulp_Error_Double( test, correct3 ); + float err4 = Ulp_Error_Double( test, correct4 ); + float err5 = Ulp_Error_Double( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= f->double_ulps)) && (!(fabsf(err3) <= f->double_ulps)) && + (!(fabsf(err4) <= f->double_ulps)) && (!(fabsf(err5) <= f->double_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) || + IsDoubleResultSubnormal( correct4, f->double_ulps ) || IsDoubleResultSubnormal( correct5, f->double_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + else if( fail && IsDoubleSubnormal(s3[j]) ) + { + long double correct2 = f->dfunc.f_fff( s[j], s2[j], 0.0 ); + long double correct3 = f->dfunc.f_fff( s[j], s2[j], -0.0 ); + float err2 = Ulp_Error_Double( test, correct2 ); + float err3 = Ulp_Error_Double( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= f->double_ulps)) && (!(fabsf(err3) <= f->double_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + + if( fabsf(err ) > maxError ) + { + maxError = fabsf(err); + maxErrorVal = s[j]; + maxErrorVal2 = s2[j]; + maxErrorVal3 = s3[j]; + } + + if( fail ) + { + vlog_error( "\nERROR: %sD%s: %f ulp error at {%a, %a, %a}: *%a vs. %a\n", f->name, sizeNames[k], err, s[j], s2[j], s3[j], ((double*) gOut_Ref)[j], test ); + error = -1; + goto exit; + } + } + } + } +*/ + if( 0 == (i & 0x0fffffff) ) + { + vlog("." ); + fflush(stdout); + } + } + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "pass" ); + } + + if( gMeasureTimes ) + { + //Init input array + double *p = (double *)gIn; + double *p2 = (double *)gIn2; + double *p3 = (double *)gIn3; + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + { + p[j] = DoubleFromUInt32(genrand_int32(d)); + p2[j] = DoubleFromUInt32(genrand_int32(d)); + p3[j] = DoubleFromUInt32(genrand_int32(d)); + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, bufferSize, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer3, CL_FALSE, 0, bufferSize, gIn3, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer3 ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_double ) * sizeValues[j]; + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; // bufferSize / vectorSize rounded up + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 3, sizeof( gInBuffer3 ), &gInBuffer3 ) )) { LogBuildError(programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( k = 0; k < PERF_LOOP_COUNT; k++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (bufferSize / sizeof( double ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sD%s", f->name, sizeNames[j] ); + } + for( ; j < gMaxVectorSizeIndex; j++ ) + vlog( "\t -- " ); + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t%8.2f @ {%a, %a, %a}", maxError, maxErrorVal, maxErrorVal2, maxErrorVal3 ); + vlog( "\n" ); + +exit: + // Release + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + clReleaseKernel(kernels[k]); + clReleaseProgram(programs[k]); + } + + return error; +} + + + diff --git a/test_conformance/math_brute_force/main.c b/test_conformance/math_brute_force/main.c new file mode 100644 index 00000000..147e3af2 --- /dev/null +++ b/test_conformance/math_brute_force/main.c @@ -0,0 +1,1571 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Utility.h" + +#include +#include + +#include +#include +#include "FunctionList.h" +#include "Sleep.h" +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/parseParameters.h" + +#if defined( __APPLE__ ) + #include + #include + #include + #include +#elif defined( __linux__ ) + #include + #include + #include + #include +#endif + +#if defined (__linux__) || (defined WIN32 && defined __MINGW32__) +#include +#endif + +#define kPageSize 4096 +#define DOUBLE_REQUIRED_FEATURES ( CL_FP_FMA | CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO | CL_FP_ROUND_TO_INF | CL_FP_INF_NAN | CL_FP_DENORM ) + +const char **gTestNames = NULL; +unsigned int gTestNameCount = 0; +char appName[ MAXPATHLEN ] = ""; +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +cl_device_id gDevice = NULL; +cl_context gContext = NULL; +cl_command_queue gQueue = NULL; +int gTestCount = 0; +int gFailCount = 0; +int32_t gStartTestNumber = -1; +int32_t gEndTestNumber = -1; +int gSkipCorrectnessTesting = 0; +int gStopOnError = 0; +#if defined( __APPLE__ ) +int gMeasureTimes = 1; +#else +int gMeasureTimes = 0; +#endif +int gReportAverageTimes = 0; +int gForceFTZ = 0; +int gWimpyMode = 0; +int gHasDouble = 0; +int gTestFloat = 1; +//This flag should be 'ON' by default and it can be changed through the command line arguments. +volatile int gTestFastRelaxed = 1; +/*This flag corresponds to defining if the implementation has Derived Fast Relaxed functions. + The spec does not specify ULP for derived function. The derived functions are composed of base functions which are tested for ULP, thus when this flag is enabled, + Derived functions will not be tested for ULP, as per table 7.1 of OpenCL 2.0 spec. + Since there is no way of quering the device whether it is a derived or non-derived implementation according to OpenCL 2.0 spec then it has to be changed through a command line argument. +*/ +int gFastRelaxedDerived = 1; +int gToggleCorrectlyRoundedDivideSqrt = 0; +int gDeviceILogb0 = 1; +int gDeviceILogbNaN = 1; +int gCheckTininessBeforeRounding = 1; +int gIsInRTZMode = 0; +int gInfNanSupport = 1; +int gIsEmbedded = 0; +uint32_t gMaxVectorSizeIndex = VECTOR_SIZE_COUNT; +uint32_t gMinVectorSizeIndex = 0; +const char *method[] = { "Best", "Average" }; +void *gIn = NULL; +void *gIn2 = NULL; +void *gIn3 = NULL; +void *gOut_Ref = NULL; +void *gOut[VECTOR_SIZE_COUNT] = {NULL, NULL, NULL, NULL, NULL, NULL }; +void *gOut_Ref2 = NULL; +void *gOut2[VECTOR_SIZE_COUNT] = {NULL, NULL, NULL, NULL, NULL, NULL }; +cl_mem gInBuffer = NULL; +cl_mem gInBuffer2 = NULL; +cl_mem gInBuffer3 = NULL; +cl_mem gOutBuffer[VECTOR_SIZE_COUNT]= {NULL, NULL, NULL, NULL, NULL, NULL }; +cl_mem gOutBuffer2[VECTOR_SIZE_COUNT]= {NULL, NULL, NULL, NULL, NULL, NULL }; +uint32_t gComputeDevices = 0; +uint32_t gSimdSize = 1; +uint32_t gDeviceFrequency = 0; +cl_uint chosen_device_index = 0; +cl_uint chosen_platform_index = 0; +cl_uint gRandomSeed = 0; +cl_device_fp_config gFloatCapabilities = 0; +cl_device_fp_config gDoubleCapabilities = 0; +int gWimpyReductionFactor = 32; +int gWimpyBufferSize = BUFFER_SIZE; +int gVerboseBruteForce = 0; +#if defined( __APPLE__ ) +int gHasBasicDouble = 0; +char* gBasicDoubleFuncs[] = { + "add", + "assignment", + "divide", + "isequal", + "isgreater", + "isgreaterequal", + "isless", + "islessequal", + "isnotequal", + "multiply", + "sqrt", + "subtract" }; +size_t gNumBasicDoubleFuncs = sizeof(gBasicDoubleFuncs)/sizeof(char*); +#endif + + +static int ParseArgs( int argc, const char **argv ); +static void PrintArch( void ); +static void PrintUsage( void ); +static void PrintFunctions( void ); +static int InitCL( void ); +static void ReleaseCL( void ); +static int InitILogbConstants( void ); +static int IsTininessDetectedBeforeRounding( void ); +static int IsInRTZMode( void ); //expensive. Please check gIsInRTZMode global instead. +static void TestFinishAtExit(void); + +#pragma mark - + +int main (int argc, const char * argv[]) +{ + unsigned int i, j, error = 0; + + test_start(); + argc = parseCustomParam(argc, argv); + if (argc == -1) + { + test_finish (); + return -1; + } + atexit(TestFinishAtExit); + +#if defined( __APPLE__ ) + struct timeval startTime; + gettimeofday( &startTime, NULL ); +#endif + + error = ParseArgs( argc, argv ); + if( error ) + return error; + + // Init OpenCL + error = InitCL(); + if( error ) + return error; + + // This takes a while, so prevent the machine from going to sleep. + PreventSleep(); + atexit( ResumeSleep ); + + if( gSkipCorrectnessTesting ) + vlog( "*** Skipping correctness testing! ***\n\n" ); + else if( gStopOnError ) + vlog( "Stopping at first error.\n" ); + + if( gMeasureTimes ) + { + vlog( "%s times are reported at right (cycles per element):\n", method[gReportAverageTimes] ); + vlog( "\n" ); + if( gSkipCorrectnessTesting ) + vlog( " \t "); + else + vlog( " \t "); + if( gWimpyMode ) + vlog( " " ); + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + vlog( "\t float%s", sizeNames[i] ); + } + else + { + vlog( " \t "); + if( gWimpyMode ) + vlog( " " ); + } + if( ! gSkipCorrectnessTesting ) + vlog( "\t max_ulps" ); + + vlog( "\n-----------------------------------------------------------------------------------------------------------\n" ); + + uint32_t start = 0; + if( gStartTestNumber > (int) start ) + { + vlog( "Skipping to test %d...\n", gStartTestNumber ); + start = gStartTestNumber; + } + + uint32_t stop = (uint32_t) functionListCount; + MTdata d = init_genrand( gRandomSeed ); + if( gStartTestNumber <= gEndTestNumber && -1 != gEndTestNumber && (int) functionListCount > gEndTestNumber + 1) + stop = gEndTestNumber + 1; + + FPU_mode_type oldMode; + DisableFTZ( &oldMode ); + + for( i = start; i < stop; i++ ) + { + const Func *f = functionList + i; + + // If the user passed a list of functions to run, make sure we are in that list + if( gTestNameCount ) + { + for( j = 0; j < gTestNameCount; j++ ) + if( 0 == strcmp(gTestNames[j], f->name ) ) + break; + + // If this function doesn't match any on the list skip to the next function + if( j == gTestNameCount ) + continue; + } + + // if correctly rounded divide & sqrt are supported by the implementation + // then test it; otherwise skip the test + if (!strcmp(f->name, "sqrt_cr") || !strcmp(f->name, "divide_cr")) + { + if(( gFloatCapabilities & CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT ) == 0 ) + continue; + + } + + + { + extern int my_ilogb(double); + if( 0 == strcmp( "ilogb", f->name) ) + InitILogbConstants(); + + if ( gTestFastRelaxed ) + { + if( f->relaxed ) + { + gTestCount++; + vlog( "%3d: ", gTestCount ); + if( f->vtbl->TestFunc( f, d ) ) + { + gFailCount++; + error++; + if( gStopOnError ) + break; + } + } + } + + if( gTestFloat ) + { + int testFastRelaxedTmp = gTestFastRelaxed; + gTestFastRelaxed = 0; + gTestCount++; + vlog( "%3d: ", gTestCount ); + if( f->vtbl->TestFunc( f, d ) ) + { + gFailCount++; + error++; + if( gStopOnError ) + { + gTestFastRelaxed = testFastRelaxedTmp; + break; + } + } + gTestFastRelaxed = testFastRelaxedTmp; + } + + if( gHasDouble && NULL != f->vtbl->DoubleTestFunc && NULL != f->dfunc.p ) + { + //Disable fast-relaxed-math for double precision floating-point + int testFastRelaxedTmp = gTestFastRelaxed; + gTestFastRelaxed = 0; + + gTestCount++; + vlog( "%3d: ", gTestCount ); + if( f->vtbl->DoubleTestFunc( f, d ) ) + { + gFailCount++; + error++; + if( gStopOnError ) + break; + } + + //Re-enable testing fast-relaxed-math mode + gTestFastRelaxed = testFastRelaxedTmp; + } + +#if defined( __APPLE__ ) + { + if( gHasBasicDouble && NULL != f->vtbl->DoubleTestFunc && NULL != f->dfunc.p) + { + //Disable fast-relaxed-math for double precision floating-point + int testFastRelaxedTmp = gTestFastRelaxed; + gTestFastRelaxed = 0; + + int isBasicTest = 0; + for( j = 0; j < gNumBasicDoubleFuncs; j++ ) { + if( 0 == strcmp(gBasicDoubleFuncs[j], f->name ) ) { + isBasicTest = 1; + break; + } + } + if (isBasicTest) { + gTestCount++; + if( gTestFloat ) + vlog( " " ); + if( f->vtbl->DoubleTestFunc( f, d ) ) + { + gFailCount++; + error++; + if( gStopOnError ) + break; + } + } + + //Re-enable testing fast-relaxed-math mode + gTestFastRelaxed = testFastRelaxedTmp; + } + } +#endif + } + } + + RestoreFPState( &oldMode ); + + free_mtdata(d); d = NULL; + vlog( "\ndone.\n" ); + + int error_code = clFinish(gQueue); + if (error_code) + vlog_error("clFinish failed:%d\n", error_code); + + if (gFailCount == 0) + { + if (gTestCount > 1) + vlog("PASSED %d of %d tests.\n", gTestCount, gTestCount); + else + vlog("PASSED test.\n"); + } + else if (gFailCount > 0) + { + if (gTestCount > 1) + vlog_error("FAILED %d of %d tests.\n", gFailCount, gTestCount); + else + vlog_error("FAILED test.\n"); + } + + ReleaseCL(); + +#if defined( __APPLE__ ) + struct timeval endTime; + gettimeofday( &endTime, NULL ); + double time = (double) endTime.tv_sec - (double) startTime.tv_sec; + time += 1e-6 * ((double) endTime.tv_usec - (double) startTime.tv_usec); + vlog( "time: %f s\n", time ); +#endif + + + if (gFailCount > 0) + return -1; + return error; +} + +static int ParseArgs( int argc, const char **argv ) +{ + int i; + gTestNames = (const char**) calloc( argc - 1, sizeof( char*) ); + gTestNameCount = 0; + int singleThreaded = 0; + + // Parse arg list + if( NULL == gTestNames && argc > 1 ) + return -1; + + { // Extract the app name + strncpy( appName, argv[0], MAXPATHLEN ); + +#if defined( __APPLE__ ) + char baseName[MAXPATHLEN]; + char *base = NULL; + strncpy( baseName, argv[0], MAXPATHLEN ); + base = basename( baseName ); + if( NULL != base ) + { + strncpy( appName, base, sizeof( appName ) ); + appName[ sizeof( appName ) -1 ] = '\0'; + } +#endif + } + + /* Check for environment variable to set device type */ + char *env_mode = getenv( "CL_DEVICE_TYPE" ); + if( env_mode != NULL ) + { + if( strcmp( env_mode, "gpu" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_GPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_GPU; + else if( strcmp( env_mode, "cpu" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_CPU" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_CPU; + else if( strcmp( env_mode, "accelerator" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( env_mode, "default" ) == 0 || strcmp( env_mode, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + gDeviceType = CL_DEVICE_TYPE_DEFAULT; + else + { + vlog_error( "Unknown CL_DEVICE_TYPE env variable setting: %s.\nAborting...\n", env_mode ); + abort(); + } + } + + + vlog( "\n%s\t", appName ); + for( i = 1; i < argc; i++ ) + { + const char *arg = argv[i]; + if( NULL == arg ) + break; + + vlog( "\t%s", arg ); + int optionFound = 0; + if( arg[0] == '-' ) + { + while( arg[1] != '\0' ) + { + arg++; + optionFound = 1; + switch( *arg ) + { + case 'a': + gReportAverageTimes ^= 1; + break; + + case 'c': + gToggleCorrectlyRoundedDivideSqrt ^= 1; + break; + + case 'd': + gHasDouble ^= 1; + break; + + case 'e': + gFastRelaxedDerived ^= 1; + break; + + case 'f': + gTestFloat ^= 1; + break; + + case 'h': + PrintUsage(); + return -1; + + case 'p': + PrintFunctions(); + return -1; + + case 'l': + gSkipCorrectnessTesting ^= 1; + break; + + case 'm': + singleThreaded ^= 1; + break; + + case 'r': + gTestFastRelaxed ^= 1; + break; + + case 's': + gStopOnError ^= 1; + break; + + case 't': + gMeasureTimes ^= 1; + break; + + case 'v': + gVerboseBruteForce ^= 1; + break; + + case 'w': // wimpy mode + gWimpyMode ^= 1; + break; + + case '[': + // wimpy reduction factor can be set with the option -[2^n] + // Default factor is 32, and n practically can be from 1 to 10 + { + const char *arg_temp = strchr(&arg[1], ']'); + if( arg_temp != 0) + { + int new_factor = atoi(&arg[1]); + arg=arg_temp; // Advance until ']' + if(new_factor && !(new_factor & (new_factor - 1))) + { + vlog( " WimpyReduction factor changed from %d to %d \n",gWimpyReductionFactor, new_factor); + gWimpyReductionFactor = new_factor; + }else + { + vlog( " Error in WimpyReduction factor %d, must be power of 2 \n",gWimpyReductionFactor); + } + } + } + break; + + case 'z': + gForceFTZ ^= 1; + break; + + case '1': + if( arg[1] == '6' ) + { + gMinVectorSizeIndex = 5; + gMaxVectorSizeIndex = gMinVectorSizeIndex + 1; + arg++; + } + else + { + gMinVectorSizeIndex = 0; + gMaxVectorSizeIndex = gMinVectorSizeIndex + 1; + } + break; + case '2': + gMinVectorSizeIndex = 1; + gMaxVectorSizeIndex = gMinVectorSizeIndex + 1; + break; + case '3': + gMinVectorSizeIndex = 2; + gMaxVectorSizeIndex = gMinVectorSizeIndex + 1; + break; + case '4': + gMinVectorSizeIndex = 3; + gMaxVectorSizeIndex = gMinVectorSizeIndex + 1; + break; + case '8': + gMinVectorSizeIndex = 4; + gMaxVectorSizeIndex = gMinVectorSizeIndex + 1; + break; + break; + + default: + vlog( " <-- unknown flag: %c (0x%2.2x)\n)", *arg, *arg ); + PrintUsage(); + return -1; + } + } + } + + // Check if a particular device id was requested + if (strlen(argv[i]) >= 3 && argv[i][0] == 'i' && argv[i][1] =='d') + { + chosen_device_index = atoi(&(argv[i][2])); + optionFound = 1; + } + + // Check if a particular platform was requested + if (strlen(argv[i]) >= 3 && argv[i][0] == 'p' && argv[i][1] =='l') + { + chosen_platform_index = atoi(&(argv[i][2])); + optionFound = 1; + } + + if( ! optionFound ) + { + char *t = NULL; + long number = strtol( arg, &t, 0 ); + if( t != arg ) + { + if( -1 == gStartTestNumber ) + gStartTestNumber = (int32_t) number; + else + gEndTestNumber = gStartTestNumber + (int32_t) number; + } + else + { + // Make sure this is a valid name + unsigned int k; + for (k=0; kname) == 0) + { + gTestNames[ gTestNameCount ] = arg; + gTestNameCount++; + break; + } + } + // If we didn't find it in the list of test names + if (k >= functionListCount) + { + //It may be a device type or rundomize parameter + if( 0 == strcmp(arg, "CL_DEVICE_TYPE_CPU")) { + gDeviceType = CL_DEVICE_TYPE_CPU; + } else if( 0 == strcmp(arg, "CL_DEVICE_TYPE_GPU")) { + gDeviceType = CL_DEVICE_TYPE_GPU; + } else if( 0 == strcmp(arg, "CL_DEVICE_TYPE_ACCELERATOR")) { + gDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + } else if( 0 == strcmp(arg, "randomize")) { + gRandomSeed = (cl_uint) time( NULL ); + vlog( "\nRandom seed: %u.\n", gRandomSeed ); + } else { + vlog_error("\nInvalid function name: %s\n", arg); + test_finish(); + exit(-1); + } + } + } + } + } + + // Check for the wimpy mode environment variable + if (getenv("CL_WIMPY_MODE")) { + vlog( "\n" ); + vlog( "*** Detected CL_WIMPY_MODE env ***\n" ); + gWimpyMode = 1; + } + +#if defined( __APPLE__ ) + #if defined( __i386__ ) || defined( __x86_64__ ) + #define kHasSSE3 0x00000008 + #define kHasSupplementalSSE3 0x00000100 + #define kHasSSE4_1 0x00000400 + #define kHasSSE4_2 0x00000800 + /* check our environment for a hint to disable SSE variants */ + { + const char *env = getenv( "CL_MAX_SSE" ); + if( env ) + { + extern int _cpu_capabilities; + int mask = 0; + if( 0 == strcasecmp( env, "SSE4.1" ) ) + mask = kHasSSE4_2; + else if( 0 == strcasecmp( env, "SSSE3" ) ) + mask = kHasSSE4_2 | kHasSSE4_1; + else if( 0 == strcasecmp( env, "SSE3" ) ) + mask = kHasSSE4_2 | kHasSSE4_1 | kHasSupplementalSSE3; + else if( 0 == strcasecmp( env, "SSE2" ) ) + mask = kHasSSE4_2 | kHasSSE4_1 | kHasSupplementalSSE3 | kHasSSE3; + else + { + vlog_error( "Error: Unknown CL_MAX_SSE setting: %s\n", env ); + return -2; + } + + vlog( "*** Environment: CL_MAX_SSE = %s ***\n", env ); + _cpu_capabilities &= ~mask; + } + } + #endif +#endif /* __APPLE__ */ + + vlog( "\nTest binary built %s %s\n", __DATE__, __TIME__ ); + + PrintArch(); + + if( gWimpyMode ) + { + vlog( "\n" ); + vlog( "*** WARNING: Testing in Wimpy mode! ***\n" ); + vlog( "*** Wimpy mode is not sufficient to verify correctness. ***\n" ); + vlog( "*** Wimpy Reduction Factor: %-27u ***\n\n", gWimpyReductionFactor ); + } + + if( singleThreaded ) + SetThreadCount(1); + + return 0; +} + +static void PrintArch( void ) +{ + vlog( "\nHost info:\n" ); + vlog( "\tsizeof( void*) = %zd\n", sizeof( void *) ); + #if defined( __ppc__ ) + vlog( "\tARCH:\tppc\n" ); + #elif defined( __ppc64__ ) + vlog( "\tARCH:\tppc64\n" ); + #elif defined( __PPC__ ) + vlog( "ARCH:\tppc\n" ); + #elif defined( __i386__ ) + vlog( "\tARCH:\ti386\n" ); + #elif defined( __x86_64__ ) + vlog( "\tARCH:\tx86_64\n" ); + #elif defined( __arm__ ) + vlog( "\tARCH:\tarm\n" ); + #else + vlog( "\tARCH:\tunknown\n" ); + #endif + +#if defined( __APPLE__ ) + int type = 0; + size_t typeSize = sizeof( type ); + sysctlbyname( "hw.cputype", &type, &typeSize, NULL, 0 ); + vlog( "\tcpu type:\t%d\n", type ); + typeSize = sizeof( type ); + sysctlbyname( "hw.cpusubtype", &type, &typeSize, NULL, 0 ); + vlog( "\tcpu subtype:\t%d\n", type ); + +#elif defined( __linux__ ) && !defined(__aarch64__) + int _sysctl(struct __sysctl_args *args ); + #define OSNAMESZ 100 + + struct __sysctl_args args; + char osname[OSNAMESZ]; + size_t osnamelth; + int name[] = { CTL_KERN, KERN_OSTYPE }; + memset(&args, 0, sizeof(struct __sysctl_args)); + args.name = name; + args.nlen = sizeof(name)/sizeof(name[0]); + args.oldval = osname; + args.oldlenp = &osnamelth; + + osnamelth = sizeof(osname); + + if (syscall(SYS__sysctl, &args) == -1) { + vlog( "_sysctl error\n" ); + } + else { + vlog("this machine is running %*s\n", osnamelth, osname); + } + + +#endif +} + +static void PrintFunctions ( void ) +{ + vlog( "\nMath function names:\n" ); + for( int i = 0; i < functionListCount; i++ ) + { + vlog( "\t%s\n", functionList[ i ].name ); + } +} + +static void PrintUsage( void ) +{ + vlog( "%s [-acglstz]: \n", appName ); + vlog( "\toptions:\n" ); + vlog( "\t\t-a\tReport average times instead of best times\n" ); + vlog( "\t\t-c\tToggle test fp correctly rounded divide and sqrt (Default: off)\n"); + vlog( "\t\t-d\tToggle double precision testing. (Default: on iff khr_fp_64 on)\n" ); + vlog( "\t\t-f\tToggle float precision testing. (Default: on)\n" ); + vlog( "\t\t-r\tToggle fast relaxed math precision testing. (Default: on)\n" ); + vlog( "\t\t-e\tToggle test as derived implementations for fast relaxed math precision. (Default: on)\n" ); + vlog( "\t\t-h\tPrint this message and quit\n" ); + vlog( "\t\t-p\tPrint all math function names and quit\n" ); + vlog( "\t\t-l\tlink check only (make sure functions are present, skip accuracy checks.)\n" ); + vlog( "\t\t-m\tToggle run multi-threaded. (Default: on) )\n" ); + vlog( "\t\t-s\tStop on error\n" ); + vlog( "\t\t-t\tToggle timing (on by default)\n" ); + vlog( "\t\t-w\tToggle Wimpy Mode, * Not a valid test * \n"); + vlog( "\t\t-[2^n]\tSet wimpy reduction factor, recommended range of n is 1-10, default factor(%u)\n",gWimpyReductionFactor ); + vlog( "\t\t-z\tToggle FTZ mode (Section 6.5.3) for all functions. (Set by device capabilities by default.)\n" ); + vlog( "\t\t-v\tToggle Verbosity (Default: off)\n "); + vlog( "\t\t-#\tTest only vector sizes #, e.g. \"-1\" tests scalar only, \"-16\" tests 16-wide vectors only.\n" ); + vlog( "\n\tYou may also pass a number instead of a function name.\n" ); + vlog( "\tThis causes the first N tests to be skipped. The tests are numbered.\n" ); + vlog( "\tIf you pass a second number, that is the number tests to run after the first one.\n" ); + vlog( "\tA name list may be used in conjunction with a number range. In that case,\n" ); + vlog( "\tonly the named cases in the number range will run.\n" ); + vlog( "\tYou may also choose to pass no arguments, in which case all tests will be run.\n" ); + vlog( "\tYou may pass CL_DEVICE_TYPE_CPU/GPU/ACCELERATOR to select the device.\n" ); + vlog( "\n" ); +} + +static void CL_CALLBACK notify_callback(const char *errinfo, const void *private_info, size_t cb, void *user_data) +{ + vlog( "%s (%p, %zd, %p)\n", errinfo, private_info, cb, user_data ); +} + +static int InitCL( void ) +{ + int error; + uint32_t i; + int isEmbedded = 0; + size_t configSize = sizeof( gComputeDevices ); + + cl_uint num_devices = 0; + cl_platform_id platform = NULL; + cl_device_id *devices = NULL; + + /* Get the platform */ + cl_uint num_entries = 0; + error = clGetPlatformIDs(0, NULL, &num_entries); + if (error) { + vlog_error( "clGetPlatformIDs failed: %d\n", error ); + return error; + } + + cl_platform_id* pPlatforms = (cl_platform_id*) alloca(num_entries * sizeof(cl_platform_id)); + + /* Get the platform */ + error = clGetPlatformIDs(num_entries, pPlatforms, NULL); + if (error) { + vlog_error( "clGetPlatformIDs failed: %d\n", error ); + return error; + } + + //Choose platform + platform = pPlatforms[chosen_platform_index]; + + /* Get the number of requested devices */ + error = clGetDeviceIDs(platform, gDeviceType, 0, NULL, &num_devices ); + if (error) { + vlog_error( "clGetDeviceIDs failed: %d\n", error ); + return error; + } + + devices = (cl_device_id *) malloc( num_devices * sizeof( cl_device_id ) ); + if (!devices || chosen_device_index >= num_devices) { + vlog_error( "device index out of range -- chosen_device_index (%d) >= num_devices (%d)\n", chosen_device_index, num_devices ); + return -1; + } + + /* Get the requested device */ + error = clGetDeviceIDs(platform, gDeviceType, num_devices, devices, NULL ); + if (error) { + vlog_error( "clGetDeviceIDs failed: %d\n", error ); + return error; + } + + gDevice = devices[chosen_device_index]; + free(devices); + devices = NULL; + + if( (error = clGetDeviceInfo( gDevice, CL_DEVICE_MAX_COMPUTE_UNITS, configSize, &gComputeDevices, NULL )) ) + gComputeDevices = 1; + + // Check extensions + size_t extSize = 0; + if((error = clGetDeviceInfo( gDevice, CL_DEVICE_EXTENSIONS, 0, NULL, &extSize))) + { vlog_error( "Unable to get device extension string to see if double present. (%d) \n", error ); } + else + { + char *ext = (char*) malloc( extSize ); + if( NULL == ext ) + { vlog_error( "malloc failed at %s:%d\nUnable to determine if double present.\n", __FILE__, __LINE__ ); } + else + { + if((error = clGetDeviceInfo( gDevice, CL_DEVICE_EXTENSIONS, extSize, ext, NULL))) + { vlog_error( "Unable to get device extension string to see if double present. (%d) \n", error ); } + else + { + if( strstr( ext, "cl_khr_fp64" )) + { + gHasDouble ^= 1; + +#if defined( CL_DEVICE_DOUBLE_FP_CONFIG ) + if( (error = clGetDeviceInfo(gDevice, CL_DEVICE_DOUBLE_FP_CONFIG, sizeof(gDoubleCapabilities), &gDoubleCapabilities, NULL))) + { + vlog_error( "ERROR: Unable to get device CL_DEVICE_DOUBLE_FP_CONFIG. (%d)\n", error ); + return -1; + } + + if( DOUBLE_REQUIRED_FEATURES != (gDoubleCapabilities & DOUBLE_REQUIRED_FEATURES) ) + { + char list[300] = ""; + if( 0 == (gDoubleCapabilities & CL_FP_FMA) ) + strncat( list, "CL_FP_FMA, ", sizeof( list )-1 ); + if( 0 == (gDoubleCapabilities & CL_FP_ROUND_TO_NEAREST) ) + strncat( list, "CL_FP_ROUND_TO_NEAREST, ", sizeof( list )-1 ); + if( 0 == (gDoubleCapabilities & CL_FP_ROUND_TO_ZERO) ) + strncat( list, "CL_FP_ROUND_TO_ZERO, ", sizeof( list )-1 ); + if( 0 == (gDoubleCapabilities & CL_FP_ROUND_TO_INF) ) + strncat( list, "CL_FP_ROUND_TO_INF, ", sizeof( list )-1 ); + if( 0 == (gDoubleCapabilities & CL_FP_INF_NAN) ) + strncat( list, "CL_FP_INF_NAN, ", sizeof( list )-1 ); + if( 0 == (gDoubleCapabilities & CL_FP_DENORM) ) + strncat( list, "CL_FP_DENORM, ", sizeof( list )-1 ); + vlog_error( "ERROR: required double features are missing: %s\n", list ); + + free(ext); + return -1; + } +#else + vlog_error( "FAIL: device says it supports cl_khr_fp64 but CL_DEVICE_DOUBLE_FP_CONFIG is not in the headers!\n" ); + return -1; +#endif + } +#if defined( __APPLE__ ) + else if( strstr( ext, "cl_APPLE_fp64_basic_ops" )) + { + gHasBasicDouble ^= 1; + +#if defined( CL_DEVICE_DOUBLE_FP_CONFIG ) + if( (error = clGetDeviceInfo(gDevice, CL_DEVICE_DOUBLE_FP_CONFIG, sizeof(gDoubleCapabilities), &gDoubleCapabilities, NULL))) + { + vlog_error( "ERROR: Unable to get device CL_DEVICE_DOUBLE_FP_CONFIG. (%d)\n", error ); + return -1; + } + + if( DOUBLE_REQUIRED_FEATURES != (gDoubleCapabilities & DOUBLE_REQUIRED_FEATURES) ) + { + char list[300] = ""; + if( 0 == (gDoubleCapabilities & CL_FP_FMA) ) + strncat( list, "CL_FP_FMA, ", sizeof( list ) ); + if( 0 == (gDoubleCapabilities & CL_FP_ROUND_TO_NEAREST) ) + strncat( list, "CL_FP_ROUND_TO_NEAREST, ", sizeof( list ) ); + if( 0 == (gDoubleCapabilities & CL_FP_ROUND_TO_ZERO) ) + strncat( list, "CL_FP_ROUND_TO_ZERO, ", sizeof( list ) ); + if( 0 == (gDoubleCapabilities & CL_FP_ROUND_TO_INF) ) + strncat( list, "CL_FP_ROUND_TO_INF, ", sizeof( list ) ); + if( 0 == (gDoubleCapabilities & CL_FP_INF_NAN) ) + strncat( list, "CL_FP_INF_NAN, ", sizeof( list ) ); + if( 0 == (gDoubleCapabilities & CL_FP_DENORM) ) + strncat( list, "CL_FP_DENORM, ", sizeof( list ) ); + vlog_error( "ERROR: required double features are missing: %s\n", list ); + + free(ext); + return -1; + } +#else + vlog_error( "FAIL: device says it supports cl_khr_fp64 but CL_DEVICE_DOUBLE_FP_CONFIG is not in the headers!\n" ); + return -1; +#endif + } +#endif /* __APPLE__ */ + } + free(ext); + } + } + + configSize = sizeof( gDeviceFrequency ); + if( (error = clGetDeviceInfo( gDevice, CL_DEVICE_MAX_CLOCK_FREQUENCY, configSize, &gDeviceFrequency, NULL )) ) + gDeviceFrequency = 0; + + if( (error = clGetDeviceInfo(gDevice, CL_DEVICE_SINGLE_FP_CONFIG, sizeof(gFloatCapabilities), &gFloatCapabilities, NULL))) + { + vlog_error( "ERROR: Unable to get device CL_DEVICE_SINGLE_FP_CONFIG. (%d)\n", error ); + return -1; + } + + char profile[1024] = ""; + if( (error = clGetDeviceInfo(gDevice, CL_DEVICE_PROFILE, sizeof( profile), profile, NULL))) + { vlog_error( "FAILED -- Unable to read device profile\n" ); abort(); } + else + isEmbedded = NULL != strstr(profile, "EMBEDDED_PROFILE"); // we will verify this with a kernel below + + gContext = clCreateContext( NULL, 1, &gDevice, notify_callback, NULL, &error ); + if( NULL == gContext || error ) + { + vlog_error( "clCreateContext failed. (%d) \n", error ); + return -1; + } + + gQueue = clCreateCommandQueueWithProperties(gContext, gDevice, 0, &error); + if( NULL == gQueue || error ) + { + vlog_error( "clCreateCommandQueue failed. (%d)\n", error ); + return -2; + } + +#if defined( __APPLE__ ) + // FIXME: use clProtectedArray +#endif + //Allocate buffers + cl_uint min_alignment = 0; + error = clGetDeviceInfo (gDevice, CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof(cl_uint), (void*)&min_alignment, NULL); + if (CL_SUCCESS != error) + { + vlog_error( "clGetDeviceInfo failed. (%d)\n", error ); + return -2; + } + min_alignment >>= 3; // convert bits to bytes + + gIn = align_malloc( BUFFER_SIZE, min_alignment ); + if( NULL == gIn ) + return -3; + gIn2 = align_malloc( BUFFER_SIZE, min_alignment ); + if( NULL == gIn2 ) + return -3; + gIn3 = align_malloc( BUFFER_SIZE, min_alignment ); + if( NULL == gIn3 ) + return -3; + gOut_Ref = align_malloc( BUFFER_SIZE, min_alignment ); + if( NULL == gOut_Ref ) + return -3; + gOut_Ref2 = align_malloc( BUFFER_SIZE, min_alignment ); + if( NULL == gOut_Ref2 ) + return -3; + + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + gOut[i] = align_malloc( BUFFER_SIZE, min_alignment ); + if( NULL == gOut[i] ) + return -7 + i; + gOut2[i] = align_malloc( BUFFER_SIZE, min_alignment ); + if( NULL == gOut2[i] ) + return -7 + i; + } + + cl_mem_flags device_flags = CL_MEM_READ_ONLY; + // save a copy on the host device to make this go faster + if( CL_DEVICE_TYPE_CPU == gDeviceType ) + device_flags |= CL_MEM_USE_HOST_PTR; + else + device_flags |= CL_MEM_COPY_HOST_PTR; + + // setup input buffers + gInBuffer = clCreateBuffer(gContext, device_flags, BUFFER_SIZE, gIn, &error); + if( gInBuffer == NULL || error ) + { + vlog_error( "clCreateBuffer1 failed for input (%d)\n", error ); + return -4; + } + + gInBuffer2 = clCreateBuffer( gContext, device_flags, BUFFER_SIZE, gIn2, &error ); + if( gInBuffer2 == NULL || error ) + { + vlog_error( "clCreateArray2 failed for input (%d)\n" , error ); + return -4; + } + + gInBuffer3 = clCreateBuffer( gContext, device_flags, BUFFER_SIZE, gIn3, &error ); + if( gInBuffer3 == NULL || error) + { + vlog_error( "clCreateArray3 failed for input (%d)\n", error ); + return -4; + } + + + // setup output buffers + device_flags = CL_MEM_READ_WRITE; + // save a copy on the host device to make this go faster + if( CL_DEVICE_TYPE_CPU == gDeviceType ) + device_flags |= CL_MEM_USE_HOST_PTR; + else + device_flags |= CL_MEM_COPY_HOST_PTR; + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + gOutBuffer[i] = clCreateBuffer( gContext, device_flags, BUFFER_SIZE, gOut[i], &error ); + if( gOutBuffer[i] == NULL || error ) + { + vlog_error( "clCreateArray failed for output (%d)\n", error ); + return -5; + } + gOutBuffer2[i] = clCreateBuffer( gContext, device_flags, BUFFER_SIZE, gOut2[i], &error ); + if( gOutBuffer2[i] == NULL || error) + { + vlog_error( "clCreateArray2 failed for output (%d)\n", error ); + return -5; + } + } + + // we are embedded, check current rounding mode + if( isEmbedded ) + { + gIsInRTZMode = IsInRTZMode(); + if (0 == (gFloatCapabilities & CL_FP_INF_NAN) ) + gInfNanSupport = 0; + + // ensures embedded single precision ulp values are used + gIsEmbedded = 1; + } + + //Check tininess detection + IsTininessDetectedBeforeRounding(); + + + char c[1024]; + static const char *no_yes[] = { "NO", "YES" }; + vlog( "\nCompute Device info:\n" ); + clGetPlatformInfo(platform, CL_PLATFORM_VERSION, sizeof(c), &c, NULL); + vlog( "\tPlatform Version: %s\n", c ); + clGetDeviceInfo(gDevice, CL_DEVICE_NAME, sizeof(c), &c, NULL); + vlog( "\tDevice Name: %s\n", c ); + clGetDeviceInfo(gDevice, CL_DEVICE_VENDOR, sizeof(c), &c, NULL); + vlog( "\tVendor: %s\n", c ); + clGetDeviceInfo(gDevice, CL_DEVICE_VERSION, sizeof(c), &c, NULL); + vlog( "\tDevice Version: %s\n", c ); + clGetDeviceInfo(gDevice, CL_DEVICE_OPENCL_C_VERSION, sizeof(c), &c, NULL); + vlog( "\tCL C Version: %s\n", c ); + clGetDeviceInfo(gDevice, CL_DRIVER_VERSION, sizeof(c), &c, NULL); + vlog( "\tDriver Version: %s\n", c ); + vlog( "\tDevice Frequency: %d MHz\n", gDeviceFrequency ); + vlog( "\tSubnormal values supported for floats? %s\n", no_yes[0 != (CL_FP_DENORM & gFloatCapabilities)] ); + vlog( "\tCorrectly rounded divide and sqrt supported for floats? %s\n", no_yes[0 != (CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT & gFloatCapabilities)] ); + if( gToggleCorrectlyRoundedDivideSqrt ) + { + gFloatCapabilities ^= CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT; + } + vlog( "\tTesting with correctly rounded float divide and sqrt? %s\n", no_yes[0 != (CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT & gFloatCapabilities)] ); + vlog( "\tTesting with FTZ mode ON for floats? %s\n", no_yes[0 != gForceFTZ || 0 == (CL_FP_DENORM & gFloatCapabilities)] ); + vlog( "\tTesting single precision? %s\n", no_yes[0 != gTestFloat] ); + vlog( "\tTesting fast relaxed math? %s\n", no_yes[0 != gTestFastRelaxed] ); + if(gTestFastRelaxed) + { + vlog( "\tFast relaxed math has derived implementations? %s\n", no_yes[0 != gFastRelaxedDerived] ); + } + vlog( "\tTesting double precision? %s\n", no_yes[0 != gHasDouble] ); + if( sizeof( long double) == sizeof( double ) && gHasDouble ) + { + vlog( "\n\t\tWARNING: Host system long double does not have better precision than double!\n" ); + vlog( "\t\t All double results that do not match the reference result have their reported\n" ); + vlog( "\t\t error inflated by 0.5 ulps to account for the fact that this system\n" ); + vlog( "\t\t can not accurately represent the right result to an accuracy closer\n" ); + vlog( "\t\t than half an ulp. See comments in Ulp_Error_Double() for more details.\n\n" ); + } +#if defined( __APPLE__ ) + vlog( "\tTesting basic double precision? %s\n", no_yes[0 != gHasBasicDouble] ); +#endif + + vlog( "\tIs Embedded? %s\n", no_yes[0 != isEmbedded] ); + if( isEmbedded ) + vlog( "\tRunning in RTZ mode? %s\n", no_yes[0 != gIsInRTZMode] ); + vlog( "\tTininess is detected before rounding? %s\n", no_yes[0 != gCheckTininessBeforeRounding] ); + vlog( "\tWorker threads: %d\n", GetThreadCount() ); + vlog( "\tTesting vector sizes:" ); + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + vlog( "\t%d", sizeValues[i] ); + + vlog("\n"); + vlog("\tVerbose? %s\n", no_yes[0 != gVerboseBruteForce]); + vlog( "\n\n" ); + + // Check to see if we are using single threaded mode on other than a 1.0 device + if (getenv( "CL_TEST_SINGLE_THREADED" )) { + + char device_version[1024] = { 0 }; + clGetDeviceInfo( gDevice, CL_DEVICE_VERSION, sizeof(device_version), device_version, NULL ); + + if (strcmp("OpenCL 1.0 ",device_version)) { + vlog("ERROR: CL_TEST_SINGLE_THREADED is set in the environment. Running single threaded.\n"); + } + } + + return 0; +} + +static void ReleaseCL( void ) +{ + uint32_t i; + clReleaseMemObject(gInBuffer); + clReleaseMemObject(gInBuffer2); + clReleaseMemObject(gInBuffer3); + for ( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++) { + clReleaseMemObject(gOutBuffer[i]); + clReleaseMemObject(gOutBuffer2[i]); + } + clReleaseCommandQueue(gQueue); + clReleaseContext(gContext); + + align_free(gIn); + align_free(gIn2); + align_free(gIn3); + align_free(gOut_Ref); + align_free(gOut_Ref2); + + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + align_free(gOut[i]); + align_free(gOut2[i]); + } +} + +void _LogBuildError( cl_program p, int line, const char *file ) +{ + char the_log[2048] = ""; + + vlog_error( "%s:%d: Build Log:\n", file, line ); + if( 0 == clGetProgramBuildInfo(p, gDevice, CL_PROGRAM_BUILD_LOG, sizeof(the_log), the_log, NULL) ) + vlog_error( "%s", the_log ); + else + vlog_error( "*** Error getting build log for program %p\n", p ); +} + +int InitILogbConstants( void ) +{ + int error; + const char *kernel = + "__kernel void GetILogBConstants( __global int *out )\n" + "{\n" + " out[0] = FP_ILOGB0;\n" + " out[1] = FP_ILOGBNAN;\n" + "}\n"; + + cl_program query; + error = create_single_kernel_helper(gContext, &query, NULL, 1, &kernel, NULL); + if (error != CL_SUCCESS) + { + log_error("Error: Unable to build program to get FP_ILOGB0 and FP_ILOGBNAN for the device.\n"); + return -1; + } + + cl_kernel k = clCreateKernel( query, "GetILogBConstants", &error ); + if( NULL == k || error) + { + vlog_error( "Error: Unable to create kernel to get FP_ILOGB0 and FP_ILOGBNAN for the device. Err = %d", error ); + return error; + } + + if((error = clSetKernelArg(k, 0, sizeof( gOutBuffer[gMinVectorSizeIndex]), &gOutBuffer[gMinVectorSizeIndex]))) + { + vlog_error( "Error: Unable to set kernel arg to get FP_ILOGB0 and FP_ILOGBNAN for the device. Err = %d", error ); + return error; + } + + size_t dim = 1; + if((error = clEnqueueNDRangeKernel(gQueue, k, 1, NULL, &dim, NULL, 0, NULL, NULL) )) + { + vlog_error( "Error: Unable to execute kernel to get FP_ILOGB0 and FP_ILOGBNAN for the device. Err = %d", error ); + return error; + } + + struct{ cl_int ilogb0, ilogbnan; }data; + if(( error = clEnqueueReadBuffer( gQueue, gOutBuffer[gMinVectorSizeIndex], CL_TRUE, 0, sizeof( data ), &data, 0, NULL, NULL))) + { + vlog_error( "Error: unable to read FP_ILOGB0 and FP_ILOGBNAN from the device. Err = %d", error ); + return error; + } + + gDeviceILogb0 = data.ilogb0; + gDeviceILogbNaN = data.ilogbnan; + + clReleaseKernel(k); + clReleaseProgram(query); + + return 0; +} + +int IsTininessDetectedBeforeRounding( void ) +{ + int error; + const char *kernel = + "__kernel void IsTininessDetectedBeforeRounding( __global float *out )\n" + "{\n" + " volatile float a = 0x1.000002p-126f;\n" + " volatile float b = 0x1.fffffcp-1f;\n" // product is 0x1.fffffffffff8p-127 + " out[0] = a * b;\n" + "}\n"; + + cl_program query; + + error = create_single_kernel_helper(gContext, &query, NULL, 1, &kernel, NULL); + if (error != CL_SUCCESS) + { + log_error("Error: Unable to build program to detect how tininess is detected for the device.\n"); + return -1; + } + + cl_kernel k = clCreateKernel( query, "IsTininessDetectedBeforeRounding", &error ); + if( NULL == k || error) + { + vlog_error( "Error: Unable to create kernel to detect how tininess is detected for the device. Err = %d", error ); + return error; + } + + if((error = clSetKernelArg(k, 0, sizeof( gOutBuffer[gMinVectorSizeIndex]), &gOutBuffer[gMinVectorSizeIndex]))) + { + vlog_error( "Error: Unable to set kernel arg to detect how tininess is detected for the device. Err = %d", error ); + return error; + } + + size_t dim = 1; + if((error = clEnqueueNDRangeKernel(gQueue, k, 1, NULL, &dim, NULL, 0, NULL, NULL) )) + { + vlog_error( "Error: Unable to execute kernel to detect how tininess is detected for the device. Err = %d", error ); + return error; + } + + struct{ cl_uint f; }data; + if(( error = clEnqueueReadBuffer( gQueue, gOutBuffer[gMinVectorSizeIndex], CL_TRUE, 0, sizeof( data ), &data, 0, NULL, NULL))) + { + vlog_error( "Error: unable to read result from tininess test from the device. Err = %d", error ); + return error; + } + + gCheckTininessBeforeRounding = 0 == (data.f & 0x7fffffff); + + clReleaseKernel(k); + clReleaseProgram(query); + + return 0; +} + + +int MakeKernel( const char **c, cl_uint count, const char *name, cl_kernel *k, cl_program *p ) +{ + int error = 0; + char options[200]; + + strcpy(options, "-cl-std=CL2.0"); + + if( gForceFTZ ) + { + strcat(options," -cl-denorms-are-zero"); + } + + if( gTestFastRelaxed ) + { + strcat(options, " -cl-fast-relaxed-math"); + } + + error = create_single_kernel_helper(gContext, p, NULL, count, c, NULL, options); + if (error != CL_SUCCESS) + { + log_error("create_single_kernel_helper failed\n"); + return -1; + } + + *k = clCreateKernel( *p, name, &error ); + if( NULL == *k || error ) + { + char buffer[2048] = ""; + + vlog_error("\t\tFAILED -- clCreateKernel() failed: (%d)\n", error); + clGetProgramBuildInfo(*p, gDevice, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, NULL); + vlog_error("Log: %s\n", buffer); + clReleaseProgram( *p ); + return error; + } + + return error; +} + +int MakeKernels( const char **c, cl_uint count, const char *name, cl_uint kernel_count, cl_kernel *k, cl_program *p ) +{ + int error = 0; + cl_uint i; + char options[200]; + + strcpy(options, "-cl-std=CL2.0"); + + if (gForceFTZ) + { + strcat(options," -cl-denorms-are-zero "); + } + + if( gFloatCapabilities & CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT ) + { + strcat(options," -cl-fp32-correctly-rounded-divide-sqrt "); + } + + if( gTestFastRelaxed ) + { + strcat(options, " -cl-fast-relaxed-math"); + } + + error = create_single_kernel_helper(gContext, p, NULL, count, c, NULL, options); + if (error != CL_SUCCESS) + { + log_error("create_single_kernel_helper failed\n"); + return -1; + } + + memset( k, 0, kernel_count * sizeof( *k) ); + for( i = 0; i< kernel_count; i++ ) + { + k[i] = clCreateKernel( *p, name, &error ); + if( NULL == k[i]|| error ) + { + char buffer[2048] = ""; + + vlog_error("\t\tFAILED -- clCreateKernel() failed: (%d)\n", error); + clGetProgramBuildInfo(*p, gDevice, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, NULL); + vlog_error("Log: %s\n", buffer); + clReleaseProgram( *p ); + return error; + } + } + + return 0; +} + + +static int IsInRTZMode( void ) +{ + int error; + const char *kernel = + "__kernel void GetRoundingMode( __global int *out )\n" + "{\n" + " volatile float a = 0x1.0p23f;\n" + " volatile float b = -0x1.0p23f;\n" + " out[0] = (a + 0x1.fffffep-1f == a) && (b - 0x1.fffffep-1f == b);\n" + "}\n"; + + cl_program query; + + error = create_single_kernel_helper(gContext, &query, NULL, 1, &kernel, NULL); + if (error != CL_SUCCESS) + { + log_error("Error: Unable to build program to detect RTZ mode for the device.\n"); + return -1; + } + + cl_kernel k = clCreateKernel( query, "GetRoundingMode", &error ); + if( NULL == k || error) + { + vlog_error( "Error: Unable to create kernel to gdetect RTZ mode for the device. Err = %d", error ); + return error; + } + + if((error = clSetKernelArg(k, 0, sizeof( gOutBuffer[gMinVectorSizeIndex]), &gOutBuffer[gMinVectorSizeIndex]))) + { + vlog_error( "Error: Unable to set kernel arg to detect RTZ mode for the device. Err = %d", error ); + return error; + } + + size_t dim = 1; + if((error = clEnqueueNDRangeKernel(gQueue, k, 1, NULL, &dim, NULL, 0, NULL, NULL) )) + { + vlog_error( "Error: Unable to execute kernel to detect RTZ mode for the device. Err = %d", error ); + return error; + } + + struct{ cl_int isRTZ; }data; + if(( error = clEnqueueReadBuffer( gQueue, gOutBuffer[gMinVectorSizeIndex], CL_TRUE, 0, sizeof( data ), &data, 0, NULL, NULL))) + { + vlog_error( "Error: unable to read RTZ mode data from the device. Err = %d", error ); + return error; + } + + clReleaseKernel(k); + clReleaseProgram(query); + + return data.isRTZ; +} + +#pragma mark - + +const char *sizeNames[ VECTOR_SIZE_COUNT] = { "", "2", "3", "4", "8", "16" }; +const int sizeValues[ VECTOR_SIZE_COUNT] = { 1, 2, 3, 4, 8, 16 }; + +float Abs_Error( float test, double reference ) +{ + if( isnan(test) && isnan(reference) ) + return 0.0f; + return fabs((float)(reference-(double)test)); +} + +/* +#define HALF_MIN_EXP -13 +#define HALF_MANT_DIG 11 +float Ulp_Error_Half( float test, double reference ) +{ + union{ double d; uint64_t u; }u; u.d = reference; + + // Note: This function presumes that someone has already tested whether the result is correctly, + // rounded before calling this function. That test: + // + // if( (float) reference == test ) + // return 0.0f; + // + // would ensure that cases like fabs(reference) > FLT_MAX are weeded out before we get here. + // Otherwise, we'll return inf ulp error here, for what are otherwise correctly rounded + // results. + + double testVal = test; + if( u.u & 0x000fffffffffffffULL ) + { // Non-power of two and NaN + if( isnan( reference ) && isnan( test ) ) + return 0.0f; // if we are expecting a NaN, any NaN is fine + + // The unbiased exponent of the ulp unit place + int ulp_exp = HALF_MANT_DIG - 1 - MAX( ilogb( reference), HALF_MIN_EXP-1 ); + + // Scale the exponent of the error + return (float) scalbn( testVal - reference, ulp_exp ); + } + + if( isinf( reference ) ) + { + if( (double) test == reference ) + return 0.0f; + + return (float) (testVal - reference ); + } + + // reference is a normal power of two or a zero + int ulp_exp = HALF_MANT_DIG - 1 - MAX( ilogb( reference) - 1, HALF_MIN_EXP-1 ); + + // Scale the exponent of the error + return (float) scalbn( testVal - reference, ulp_exp ); +} +*/ + + +#if defined( __APPLE__ ) + #include +#endif + +uint64_t GetTime( void ) +{ +#if defined( __APPLE__ ) + return mach_absolute_time(); +#elif defined(_WIN32) && defined(_MSC_VER) + return ReadTime(); +#else + //mach_absolute_time is a high precision timer with precision < 1 microsecond. + #warning need accurate clock here. Times are invalid. + return 0; +#endif +} + + +#if defined(_WIN32) && defined (_MSC_VER) +/* function is defined in "compat.h" */ +#else +double SubtractTime( uint64_t endTime, uint64_t startTime ) +{ + uint64_t diff = endTime - startTime; + static double conversion = 0.0; + + if( 0.0 == conversion ) + { +#if defined( __APPLE__ ) + mach_timebase_info_data_t info = {0,0}; + kern_return_t err = mach_timebase_info( &info ); + if( 0 == err ) + conversion = 1e-9 * (double) info.numer / (double) info.denom; +#else + // This function consumes output from GetTime() above, and converts the time to secionds. + #warning need accurate ticks to seconds conversion factor here. Times are invalid. +#endif + } + + // strictly speaking we should also be subtracting out timer latency here + return conversion * (double) diff; +} +#endif + +cl_uint RoundUpToNextPowerOfTwo( cl_uint x ) +{ + if( 0 == (x & (x-1))) + return x; + + while( x & (x-1) ) + x &= x-1; + + return x+x; +} + +#if !defined( __APPLE__ ) +void memset_pattern4(void *dest, const void *src_pattern, size_t bytes ) +{ + uint32_t pat = ((uint32_t*) src_pattern)[0]; + size_t count = bytes / 4; + size_t i; + uint32_t *d = (uint32_t*)dest; + + for( i = 0; i < count; i++ ) + d[i] = pat; + + d += i; + + bytes &= 3; + if( bytes ) + memcpy( d, src_pattern, bytes ); +} +#endif + +void TestFinishAtExit(void) { + test_finish(); +} + diff --git a/test_conformance/math_brute_force/reference_math.c b/test_conformance/math_brute_force/reference_math.c new file mode 100644 index 00000000..791375bc --- /dev/null +++ b/test_conformance/math_brute_force/reference_math.c @@ -0,0 +1,5499 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" +#include "reference_math.h" +#include + +#if !defined(_WIN32) +#include +#endif + +#include "Utility.h" + +#if defined( __SSE__ ) || (defined( _MSC_VER ) && (defined(_M_IX86) || defined(_M_X64))) + #include +#endif +#if defined( __SSE2__ ) || (defined( _MSC_VER ) && (defined(_M_IX86) || defined(_M_X64))) + #include +#endif + +#ifndef M_PI_4 + #define M_PI_4 (M_PI/4) +#endif + +#define EVALUATE( x ) x +#define CONCATENATE(x, y) x ## EVALUATE(y) + + +// Declare Classification macros for non-C99 platforms +#ifndef isinf + #define isinf(x) ( sizeof (x) == sizeof(float ) ? fabsf(x) == INFINITY \ + : sizeof (x) == sizeof(double) ? fabs(x) == INFINITY \ + : fabsl(x) == INFINITY) +#endif + +#ifndef isfinite + #define isfinite(x) ( sizeof (x) == sizeof(float ) ? fabsf(x) < INFINITY \ + : sizeof (x) == sizeof(double) ? fabs(x) < INFINITY \ + : fabsl(x) < INFINITY) +#endif + +#ifndef isnan + #define isnan(_a) ( (_a) != (_a) ) +#endif + +#ifdef __MINGW32__ + #undef isnormal +#endif + +#ifndef isnormal + #define isnormal(x) ( sizeof (x) == sizeof(float ) ? (fabsf(x) < INFINITY && fabsf(x) >= FLT_MIN) \ + : sizeof (x) == sizeof(double) ? (fabs(x) < INFINITY && fabs(x) >= DBL_MIN) \ + : (fabsl(x) < INFINITY && fabsl(x) >= LDBL_MIN) ) +#endif + +#ifndef islessgreater + // Note: Non-C99 conformant. This will trigger floating point exceptions. We don't care about that here. + #define islessgreater( _x, _y ) ( (_x) < (_y) || (_x) > (_y) ) +#endif + +#pragma STDC FP_CONTRACT OFF +static void __log2_ep(double *hi, double *lo, double x); + +typedef union +{ + uint64_t i; + double d; +}uint64d_t; + +static const uint64d_t _CL_NAN = { 0x7ff8000000000000ULL }; + +#define cl_make_nan() _CL_NAN.d + +static double reduce1( double x ); +static double reduce1( double x ) +{ + if( fabs(x) >= HEX_DBL( +, 1, 0, +, 53 ) ) + { + if( fabs(x) == INFINITY ) + return cl_make_nan(); + + return 0.0; //we patch up the sign for sinPi and cosPi later, since they need different signs + } + + // Find the nearest multiple of 2 + const double r = copysign( HEX_DBL( +, 1, 0, +, 53 ), x ); + double z = x + r; + z -= r; + + // subtract it from x. Value is now in the range -1 <= x <= 1 + return x - z; +} + +/* +static double reduceHalf( double x ); +static double reduceHalf( double x ) +{ + if( fabs(x) >= HEX_DBL( +, 1, 0, +, 52 ) ) + { + if( fabs(x) == INFINITY ) + return cl_make_nan(); + + return 0.0; //we patch up the sign for sinPi and cosPi later, since they need different signs + } + + // Find the nearest multiple of 1 + const double r = copysign( HEX_DBL( +, 1, 0, +, 52 ), x ); + double z = x + r; + z -= r; + + // subtract it from x. Value is now in the range -0.5 <= x <= 0.5 + return x - z; +} +*/ + +double reference_acospi( double x) { return reference_acos( x ) / M_PI; } +double reference_asinpi( double x) { return reference_asin( x ) / M_PI; } +double reference_atanpi( double x) { return reference_atan( x ) / M_PI; } +double reference_atan2pi( double y, double x ) { return reference_atan2( y, x) / M_PI; } +double reference_cospi( double x) +{ + if( reference_fabs(x) >= HEX_DBL( +, 1, 0, +, 52 ) ) + { + if( reference_fabs(x) == INFINITY ) + return cl_make_nan(); + + //Note this probably fails for odd values between 0x1.0p52 and 0x1.0p53. + //However, when starting with single precision inputs, there will be no odd values. + + return 1.0; + } + + x = reduce1(x+0.5); + + // reduce to [-0.5, 0.5] + if( x < -0.5 ) + x = -1 - x; + else if ( x > 0.5 ) + x = 1 - x; + + // cosPi zeros are all +0 + if( x == 0.0 ) + return 0.0; + + return reference_sin( x * M_PI ); +} + +double reference_relaxed_divide( double x, double y ) { return (float)(((float) x ) / ( (float) y )); } + +double reference_divide( double x, double y ) { return x / y; } + +// Add a + b. If the result modulo overflowed, write 1 to *carry, otherwise 0 +static inline cl_ulong add_carry( cl_ulong a, cl_ulong b, cl_ulong *carry ) +{ + cl_ulong result = a + b; + *carry = result < a; + return result; +} + +// Subtract a - b. If the result modulo overflowed, write 1 to *carry, otherwise 0 +static inline cl_ulong sub_carry( cl_ulong a, cl_ulong b, cl_ulong *carry ) +{ + cl_ulong result = a - b; + *carry = result > a; + return result; +} + +static float fallback_frexpf( float x, int *iptr ) +{ + cl_uint u, v; + float fu, fv; + + memcpy( &u, &x, sizeof(u)); + + cl_uint exponent = u & 0x7f800000U; + cl_uint mantissa = u & ~0x7f800000U; + + // add 1 to the exponent + exponent += 0x00800000U; + + if( (cl_int) exponent < (cl_int) 0x01000000 ) + { // subnormal, NaN, Inf + mantissa |= 0x3f000000U; + + v = mantissa & 0xff800000U; + u = mantissa; + memcpy( &fv, &v, sizeof(v)); + memcpy( &fu, &u, sizeof(u)); + + fu -= fv; + + memcpy( &v, &fv, sizeof(v)); + memcpy( &u, &fu, sizeof(u)); + + exponent = u & 0x7f800000U; + mantissa = u & ~0x7f800000U; + + *iptr = (exponent >> 23) + (-126 + 1 -126); + u = mantissa | 0x3f000000U; + memcpy( &fu, &u, sizeof(u)); + return fu; + } + + *iptr = (exponent >> 23) - 127; + u = mantissa | 0x3f000000U; + memcpy( &fu, &u, sizeof(u)); + return fu; +} + +static inline int extractf( float, cl_uint * ); +static inline int extractf( float x, cl_uint *mant ) +{ + static float (*frexppf)(float, int*) = NULL; + int e; + + // verify that frexp works properly + if( NULL == frexppf ) + { + if( 0.5f == frexpf( HEX_FLT( +, 1, 0, -, 130 ), &e ) && e == -129 ) + frexppf = frexpf; + else + frexppf = fallback_frexpf; + } + + *mant = (cl_uint) (HEX_FLT( +, 1, 0, +, 32 ) * fabsf( frexppf( x, &e ))); + return e - 1; +} + +// Shift right by shift bits. Any bits lost on the right side are bitwise OR'd together and ORd into the LSB of the result +static inline void shift_right_sticky_64( cl_ulong *p, int shift ); +static inline void shift_right_sticky_64( cl_ulong *p, int shift ) +{ + cl_ulong sticky = 0; + cl_ulong r = *p; + + // C doesn't handle shifts greater than the size of the variable dependably + if( shift >= 64 ) + { + sticky |= (0 != r); + r = 0; + } + else + { + sticky |= (0 != (r << (64-shift))); + r >>= shift; + } + + *p = r | sticky; +} + +// Add two 64 bit mantissas. Bits that are below the LSB of the result are OR'd into the LSB of the result +static inline void add64( cl_ulong *p, cl_ulong c, int *exponent ); +static inline void add64( cl_ulong *p, cl_ulong c, int *exponent ) +{ + cl_ulong carry; + c = add_carry(c, *p, &carry); + if( carry ) + { + carry = c & 1; // set aside sticky bit + c >>= 1; // right shift to deal with overflow + c |= carry | 0x8000000000000000ULL; // or in carry bit, and sticky bit. The latter is to prevent rounding from believing we are exact half way case + *exponent = *exponent + 1; // adjust exponent + } + + *p = c; +} + +// IEEE-754 round to nearest, ties to even rounding +static float round_to_nearest_even_float( cl_ulong p, int exponent ); +static float round_to_nearest_even_float( cl_ulong p, int exponent ) +{ + union{ cl_uint u; cl_float d;} u; + + // If mantissa is zero, return 0.0f + if (p == 0) return 0.0f; + + // edges + if( exponent > 127 ) + { + volatile float r = exponent * CL_FLT_MAX; // signal overflow + + // attempt to fool the compiler into not optimizing the above line away + if( r > CL_FLT_MAX ) + return INFINITY; + + return r; + } + if( exponent == -150 && p > 0x8000000000000000ULL) + return HEX_FLT( +, 1, 0, -, 149 ); + if( exponent <= -150 ) return 0.0f; + + //Figure out which bits go where + int shift = 8 + 32; + if( exponent < -126 ) + { + shift -= 126 + exponent; // subnormal: shift is not 52 + exponent = -127; // set exponent to 0 + } + else + p &= 0x7fffffffffffffffULL; // normal: leading bit is implicit. Remove it. + + // Assemble the double (round toward zero) + u.u = (cl_uint)(p >> shift) | ((cl_uint) (exponent + 127) << 23); + + // put a representation of the residual bits into hi + p <<= (64-shift); + + //round to nearest, ties to even based on the unused portion of p + if( p < 0x8000000000000000ULL ) return u.d; + if( p == 0x8000000000000000ULL ) u.u += u.u & 1U; + else u.u++; + + return u.d; +} + +static float round_to_nearest_even_float_ftz( cl_ulong p, int exponent ); +static float round_to_nearest_even_float_ftz( cl_ulong p, int exponent ) +{ + extern int gCheckTininessBeforeRounding; + + union{ cl_uint u; cl_float d;} u; + int shift = 8 + 32; + + // If mantissa is zero, return 0.0f + if (p == 0) return 0.0f; + + // edges + if( exponent > 127 ) + { + volatile float r = exponent * CL_FLT_MAX; // signal overflow + + // attempt to fool the compiler into not optimizing the above line away + if( r > CL_FLT_MAX ) + return INFINITY; + + return r; + } + + // Deal with FTZ for gCheckTininessBeforeRounding + if( exponent < (gCheckTininessBeforeRounding - 127) ) + return 0.0f; + + if( exponent == -127 ) // only happens for machines that check tininess after rounding + p = (p&1) | (p>>1); + else + p &= 0x7fffffffffffffffULL; // normal: leading bit is implicit. Remove it. + + cl_ulong q = p; + + + // Assemble the double (round toward zero) + u.u = (cl_uint)(q >> shift) | ((cl_uint) (exponent + 127) << 23); + + // put a representation of the residual bits into hi + q <<= (64-shift); + + //round to nearest, ties to even based on the unused portion of p + if( q > 0x8000000000000000ULL ) + u.u++; + else if( q == 0x8000000000000000ULL ) + u.u += u.u & 1U; + + // Deal with FTZ for ! gCheckTininessBeforeRounding + if( 0 == (u.u & 0x7f800000U ) ) + return 0.0f; + + return u.d; +} + + +// IEEE-754 round toward zero. +static float round_toward_zero_float( cl_ulong p, int exponent ); +static float round_toward_zero_float( cl_ulong p, int exponent ) +{ + union{ cl_uint u; cl_float d;} u; + + // If mantissa is zero, return 0.0f + if (p == 0) return 0.0f; + + // edges + if( exponent > 127 ) + { + volatile float r = exponent * CL_FLT_MAX; // signal overflow + + // attempt to fool the compiler into not optimizing the above line away + if( r > CL_FLT_MAX ) + return CL_FLT_MAX; + + return r; + } + + if( exponent <= -149 ) + return 0.0f; + + //Figure out which bits go where + int shift = 8 + 32; + if( exponent < -126 ) + { + shift -= 126 + exponent; // subnormal: shift is not 52 + exponent = -127; // set exponent to 0 + } + else + p &= 0x7fffffffffffffffULL; // normal: leading bit is implicit. Remove it. + + // Assemble the double (round toward zero) + u.u = (cl_uint)(p >> shift) | ((cl_uint) (exponent + 127) << 23); + + return u.d; +} + +static float round_toward_zero_float_ftz( cl_ulong p, int exponent ); +static float round_toward_zero_float_ftz( cl_ulong p, int exponent ) +{ + extern int gCheckTininessBeforeRounding; + + union{ cl_uint u; cl_float d;} u; + int shift = 8 + 32; + + // If mantissa is zero, return 0.0f + if (p == 0) return 0.0f; + + // edges + if( exponent > 127 ) + { + volatile float r = exponent * CL_FLT_MAX; // signal overflow + + // attempt to fool the compiler into not optimizing the above line away + if( r > CL_FLT_MAX ) + return CL_FLT_MAX; + + return r; + } + + // Deal with FTZ for gCheckTininessBeforeRounding + if( exponent < -126 ) + return 0.0f; + + cl_ulong q = p &= 0x7fffffffffffffffULL; // normal: leading bit is implicit. Remove it. + + // Assemble the double (round toward zero) + u.u = (cl_uint)(q >> shift) | ((cl_uint) (exponent + 127) << 23); + + // put a representation of the residual bits into hi + q <<= (64-shift); + + return u.d; +} + +// Subtract two significands. +static inline void sub64( cl_ulong *c, cl_ulong p, cl_uint *signC, int *expC ); +static inline void sub64( cl_ulong *c, cl_ulong p, cl_uint *signC, int *expC ) +{ + cl_ulong carry; + p = sub_carry( *c, p, &carry ); + + if( carry ) + { + *signC ^= 0x80000000U; + p = -p; + } + + // normalize + if( p ) + { + int shift = 32; + cl_ulong test = 1ULL << 32; + while( 0 == (p & 0x8000000000000000ULL)) + { + if( p < test ) + { + p <<= shift; + *expC = *expC - shift; + } + shift >>= 1; + test <<= shift; + } + } + else + { + // zero result. + *expC = -200; + *signC = 0; // IEEE rules say a - a = +0 for all rounding modes except -inf + } + + *c = p; +} + + +float reference_fma( float a, float b, float c, int shouldFlush ) +{ + static const cl_uint kMSB = 0x80000000U; + + // Make bits accessible + union{ cl_uint u; cl_float d; } ua; ua.d = a; + union{ cl_uint u; cl_float d; } ub; ub.d = b; + union{ cl_uint u; cl_float d; } uc; uc.d = c; + + // deal with Nans, infinities and zeros + if( isnan( a ) || isnan( b ) || isnan(c) || + isinf( a ) || isinf( b ) || isinf(c) || + 0 == ( ua.u & ~kMSB) || // a == 0, defeat host FTZ behavior + 0 == ( ub.u & ~kMSB) || // b == 0, defeat host FTZ behavior + 0 == ( uc.u & ~kMSB) ) // c == 0, defeat host FTZ behavior + { + FPU_mode_type oldMode; + RoundingMode oldRoundMode = kRoundToNearestEven; + if( isinf( c ) && !isinf(a) && !isinf(b) ) + return (c + a) + b; + + if (gIsInRTZMode) + oldRoundMode = set_round(kRoundTowardZero, kfloat); + + memset( &oldMode, 0, sizeof( oldMode ) ); + if( shouldFlush ) + ForceFTZ( &oldMode ); + + a = (float) reference_multiply( a, b ); // some risk that the compiler will insert a non-compliant fma here on some platforms. + a = (float) reference_add( a, c ); // We use STDC FP_CONTRACT OFF above to attempt to defeat that. + + if( shouldFlush ) + RestoreFPState( &oldMode ); + + if( gIsInRTZMode ) + set_round(oldRoundMode, kfloat); + return a; + } + + // extract exponent and mantissa + // exponent is a standard unbiased signed integer + // mantissa is a cl_uint, with leading non-zero bit positioned at the MSB + cl_uint mantA, mantB, mantC; + int expA = extractf( a, &mantA ); + int expB = extractf( b, &mantB ); + int expC = extractf( c, &mantC ); + cl_uint signC = uc.u & kMSB; // We'll need the sign bit of C later to decide if we are adding or subtracting + +// exact product of A and B + int exponent = expA + expB; + cl_uint sign = (ua.u ^ ub.u) & kMSB; + cl_ulong product = (cl_ulong) mantA * (cl_ulong) mantB; + + // renormalize -- 1.m * 1.n yields a number between 1.0 and 3.99999.. + // The MSB might not be set. If so, fix that. Otherwise, reflect the fact that we got another power of two from the multiplication + if( 0 == (0x8000000000000000ULL & product) ) + product <<= 1; + else + exponent++; // 2**31 * 2**31 gives 2**62. If the MSB was set, then our exponent increased. + +//infinite precision add + cl_ulong addend = (cl_ulong) mantC << 32; + if( exponent >= expC ) + { + // Shift C relative to the product so that their exponents match + if( exponent > expC ) + shift_right_sticky_64( &addend, exponent - expC ); + + // Add + if( sign ^ signC ) + sub64( &product, addend, &sign, &exponent ); + else + add64( &product, addend, &exponent ); + } + else + { + // Shift the product relative to C so that their exponents match + shift_right_sticky_64( &product, expC - exponent ); + + // add + if( sign ^ signC ) + sub64( &addend, product, &signC, &expC ); + else + add64( &addend, product, &expC ); + + product = addend; + exponent = expC; + sign = signC; + } + + // round to IEEE result -- we do not do flushing to zero here. That part is handled manually in ternary.c. + if (gIsInRTZMode) + { + if( shouldFlush ) + ua.d = round_toward_zero_float_ftz( product, exponent); + else + ua.d = round_toward_zero_float( product, exponent); + } + else + { + if( shouldFlush ) + ua.d = round_to_nearest_even_float_ftz( product, exponent); + else + ua.d = round_to_nearest_even_float( product, exponent); + } + + // Set the sign + ua.u |= sign; + + return ua.d; +} + +double reference_relaxed_exp10( double x) +{ + return reference_exp10(x); +} + +double reference_exp10( double x) { return reference_exp2( x * HEX_DBL( +, 1, a934f0979a371, +, 1 ) ); } + + +int reference_ilogb( double x ) +{ + extern int gDeviceILogb0, gDeviceILogbNaN; + union { cl_double f; cl_ulong u;} u; + + u.f = (float) x; + cl_int exponent = (cl_int) (u.u >> 52) & 0x7ff; + if( exponent == 0x7ff ) + { + if( u.u & 0x000fffffffffffffULL ) + return gDeviceILogbNaN; + + return CL_INT_MAX; + } + + if( exponent == 0 ) + { // deal with denormals + u.f = x * HEX_DBL( +, 1, 0, +, 64 ); + exponent = (cl_int) (u.u >> 52) & 0x7ff; + if( exponent == 0 ) + return gDeviceILogb0; + + return exponent - (1023 + 64); + } + + return exponent - 1023; +} + +double reference_nan( cl_uint x ) +{ + union{ cl_uint u; cl_float f; }u; + u.u = x | 0x7fc00000U; + return (double) u.f; +} + +double reference_maxmag( double x, double y ) +{ + double fabsx = fabs(x); + double fabsy = fabs(y); + + if( fabsx < fabsy ) + return y; + + if( fabsy < fabsx ) + return x; + + return reference_fmax( x, y ); +} + +double reference_minmag( double x, double y ) +{ + double fabsx = fabs(x); + double fabsy = fabs(y); + + if( fabsx > fabsy ) + return y; + + if( fabsy > fabsx ) + return x; + + return reference_fmin( x, y ); +} + +//double my_nextafter( double x, double y ){ return (double) nextafterf( (float) x, (float) y ); } + +double reference_relaxed_mad( double a, double b, double c) +{ + return ((float) a )* ((float) b) + (float) c; +} + +double reference_mad( double a, double b, double c ) +{ + return a * b + c; +} + +double reference_recip( double x) { return 1.0 / x; } +double reference_rootn( double x, int i ) +{ + + //rootn ( x, 0 ) returns a NaN. + if( 0 == i ) + return cl_make_nan(); + + //rootn ( x, n ) returns a NaN for x < 0 and n is even. + if( x < 0 && 0 == (i&1) ) + return cl_make_nan(); + + if( x == 0.0 ) + { + switch( i & 0x80000001 ) + { + //rootn ( +-0, n ) is +0 for even n > 0. + case 0: + return 0.0f; + + //rootn ( +-0, n ) is +-0 for odd n > 0. + case 1: + return x; + + //rootn ( +-0, n ) is +inf for even n < 0. + case 0x80000000: + return INFINITY; + + //rootn ( +-0, n ) is +-inf for odd n < 0. + case 0x80000001: + return copysign(INFINITY, x); + } + } + + double sign = x; + x = reference_fabs(x); + x = reference_exp2( reference_log2(x) / (double) i ); + return reference_copysignd( x, sign ); +} + +double reference_rsqrt( double x) { return 1.0 / reference_sqrt(x); } +//double reference_sincos( double x, double *c ){ *c = cos(x); return sin(x); } +double reference_sinpi( double x) +{ + double r = reduce1(x); + + // reduce to [-0.5, 0.5] + if( r < -0.5 ) + r = -1 - r; + else if ( r > 0.5 ) + r = 1 - r; + + // sinPi zeros have the same sign as x + if( r == 0.0 ) + return reference_copysignd(0.0, x); + + return reference_sin( r * M_PI ); +} + +double reference_tanpi( double x) +{ + // set aside the sign (allows us to preserve sign of -0) + double sign = reference_copysignd( 1.0, x); + double z = reference_fabs(x); + + // if big and even -- caution: only works if x only has single precision + if( z >= HEX_DBL( +, 1, 0, +, 24 ) ) + { + if( z == INFINITY ) + return x - x; // nan + + return reference_copysignd( 0.0, x); // tanpi ( n ) is copysign( 0.0, n) for even integers n. + } + + // reduce to the range [ -0.5, 0.5 ] + double nearest = reference_rint( z ); // round to nearest even places n + 0.5 values in the right place for us + int i = (int) nearest; // test above against 0x1.0p24 avoids overflow here + z -= nearest; + + //correction for odd integer x for the right sign of zero + if( (i&1) && z == 0.0 ) + sign = -sign; + + // track changes to the sign + sign *= reference_copysignd(1.0, z); // really should just be an xor + z = reference_fabs(z); // remove the sign again + + // reduce once more + // If we don't do this, rounding error in z * M_PI will cause us not to return infinities properly + if( z > 0.25 ) + { + z = 0.5 - z; + return sign / reference_tan( z * M_PI ); // use system tan to get the right result + } + + // + return sign * reference_tan( z * M_PI ); // use system tan to get the right result +} + +double reference_pown( double x, int i) { return reference_pow( x, (double) i ); } +double reference_powr( double x, double y ) +{ + //powr ( x, y ) returns NaN for x < 0. + if( x < 0.0 ) + return cl_make_nan(); + + //powr ( x, NaN ) returns the NaN for x >= 0. + //powr ( NaN, y ) returns the NaN. + if( isnan(x) || isnan(y) ) + return x + y; // Note: behavior different here than for pow(1,NaN), pow(NaN, 0) + + if( x == 1.0 ) + { + //powr ( +1, +-inf ) returns NaN. + if( reference_fabs(y) == INFINITY ) + return cl_make_nan(); + + //powr ( +1, y ) is 1 for finite y. (NaN handled above) + return 1.0; + } + + if( y == 0.0 ) + { + //powr ( +inf, +-0 ) returns NaN. + //powr ( +-0, +-0 ) returns NaN. + if( x == 0.0 || x == INFINITY ) + return cl_make_nan(); + + //powr ( x, +-0 ) is 1 for finite x > 0. (x <= 0, NaN, INF already handled above) + return 1.0; + } + + if( x == 0.0 ) + { + //powr ( +-0, -inf) is +inf. + //powr ( +-0, y ) is +inf for finite y < 0. + if( y < 0.0 ) + return INFINITY; + + //powr ( +-0, y ) is +0 for y > 0. (NaN, y==0 handled above) + return 0.0; + } + + // x = +inf + if( isinf(x) ) + { + if( y < 0 ) + return 0; + return INFINITY; + } + + double fabsx = reference_fabs(x); + double fabsy = reference_fabs(y); + + //y = +-inf cases + if( isinf(fabsy) ) + { + if( y < 0 ) + { + if( fabsx < 1 ) + return INFINITY; + return 0; + } + if( fabsx < 1 ) + return 0; + return INFINITY; + } + + double hi, lo; + __log2_ep(&hi, &lo, x); + double prod = y * hi; + double result = reference_exp2(prod); + + return result; +} + +double reference_fract( double x, double *ip ) +{ + if(isnan(x)) { + *ip = cl_make_nan(); + return cl_make_nan(); + } + + float i; + float f = modff((float) x, &i ); + if( f < 0.0 ) + { + f = 1.0f + f; + i -= 1.0f; + if( f == 1.0f ) + f = HEX_FLT( +, 1, fffffe, -, 1 ); + } + *ip = i; + return f; +} + + +//double my_fdim( double x, double y){ return fdimf( (float) x, (float) y ); } +double reference_add( double x, double y ) +{ + volatile float a = (float) x; + volatile float b = (float) y; + +#if defined( __SSE__ ) || (defined( _MSC_VER ) && (defined(_M_IX86) || defined(_M_X64))) + // defeat x87 + __m128 va = _mm_set_ss( (float) a ); + __m128 vb = _mm_set_ss( (float) b ); + va = _mm_add_ss( va, vb ); + _mm_store_ss( (float*) &a, va ); +#elif defined(__PPC__) + // Most Power host CPUs do not support the non-IEEE mode (NI) which flushes denorm's to zero. + // As such, the reference add with FTZ must be emulated in sw. + if (fpu_control & _FPU_MASK_NI) { + union{ cl_uint u; cl_float d; } ua; ua.d = a; + union{ cl_uint u; cl_float d; } ub; ub.d = b; + cl_uint mantA, mantB; + cl_ulong addendA, addendB, sum; + int expA = extractf( a, &mantA ); + int expB = extractf( b, &mantB ); + cl_uint signA = ua.u & 0x80000000U; + cl_uint signB = ub.u & 0x80000000U; + + // Force matching exponents if an operand is 0 + if (a == 0.0f) { + expA = expB; + } else if (b == 0.0f) { + expB = expA; + } + + addendA = (cl_ulong)mantA << 32; + addendB = (cl_ulong)mantB << 32; + + if (expA >= expB) { + // Shift B relative to the A so that their exponents match + if( expA > expB ) + shift_right_sticky_64( &addendB, expA - expB ); + + // add + if( signA ^ signB ) + sub64( &addendA, addendB, &signA, &expA ); + else + add64( &addendA, addendB, &expA ); + } else { + // Shift the A relative to B so that their exponents match + shift_right_sticky_64( &addendA, expB - expA ); + + // add + if( signA ^ signB ) + sub64( &addendB, addendA, &signB, &expB ); + else + add64( &addendB, addendA, &expB ); + + addendA = addendB; + expA = expB; + signA = signB; + } + + // round to IEEE result + if (gIsInRTZMode) { + ua.d = round_toward_zero_float_ftz( addendA, expA ); + } else { + ua.d = round_to_nearest_even_float_ftz( addendA, expA ); + } + // Set the sign + ua.u |= signA; + a = ua.d; + } else { + a += b; + } +#else + a += b; +#endif + return (double) a; + } + + +double reference_subtract( double x, double y ) +{ + volatile float a = (float) x; + volatile float b = (float) y; +#if defined( __SSE__ ) || (defined( _MSC_VER ) && (defined(_M_IX86) || defined(_M_X64))) + // defeat x87 + __m128 va = _mm_set_ss( (float) a ); + __m128 vb = _mm_set_ss( (float) b ); + va = _mm_sub_ss( va, vb ); + _mm_store_ss( (float*) &a, va ); +#else + a -= b; +#endif + return a; +} + +//double reference_divide( double x, double y ){ return (float) x / (float) y; } +double reference_multiply( double x, double y) +{ + volatile float a = (float) x; + volatile float b = (float) y; +#if defined( __SSE__ ) || (defined( _MSC_VER ) && (defined(_M_IX86) || defined(_M_X64))) + // defeat x87 + __m128 va = _mm_set_ss( (float) a ); + __m128 vb = _mm_set_ss( (float) b ); + va = _mm_mul_ss( va, vb ); + _mm_store_ss( (float*) &a, va ); +#elif defined(__PPC__) + // Most Power host CPUs do not support the non-IEEE mode (NI) which flushes denorm's to zero. + // As such, the reference multiply with FTZ must be emulated in sw. + if (fpu_control & _FPU_MASK_NI) { + // extract exponent and mantissa + // exponent is a standard unbiased signed integer + // mantissa is a cl_uint, with leading non-zero bit positioned at the MSB + union{ cl_uint u; cl_float d; } ua; ua.d = a; + union{ cl_uint u; cl_float d; } ub; ub.d = b; + cl_uint mantA, mantB; + int expA = extractf( a, &mantA ); + int expB = extractf( b, &mantB ); + + // exact product of A and B + int exponent = expA + expB; + cl_uint sign = (ua.u ^ ub.u) & 0x80000000U; + cl_ulong product = (cl_ulong) mantA * (cl_ulong) mantB; + + // renormalize -- 1.m * 1.n yields a number between 1.0 and 3.99999.. + // The MSB might not be set. If so, fix that. Otherwise, reflect the fact that we got another power of two from the multiplication + if( 0 == (0x8000000000000000ULL & product) ) + product <<= 1; + else + exponent++; // 2**31 * 2**31 gives 2**62. If the MSB was set, then our exponent increased. + + // round to IEEE result -- we do not do flushing to zero here. That part is handled manually in ternary.c. + if (gIsInRTZMode) { + ua.d = round_toward_zero_float_ftz( product, exponent); + } else { + ua.d = round_to_nearest_even_float_ftz( product, exponent); + } + // Set the sign + ua.u |= sign; + a = ua.d; + } else { + a *= b; + } +#else + a *= b; +#endif + return a; +} + +/*double my_remquo( double x, double y, int *iptr ) +{ + if( isnan(x) || isnan(y) || + fabs(x) == INFINITY || + y == 0.0 ) + { + *iptr = 0; + return NAN; + } + + return (double) remquof( (float) x, (float) y, iptr ); +}*/ +double reference_lgamma_r( double x, int *signp ) +{ + // This is not currently tested + *signp = 0; + return x; +} + + +int reference_isequal( double x, double y ){ return x == y; } +int reference_isfinite( double x ){ return 0 != isfinite(x); } +int reference_isgreater( double x, double y ){ return x > y; } +int reference_isgreaterequal( double x, double y ){ return x >= y; } +int reference_isinf( double x ){ return 0 != isinf(x); } +int reference_isless( double x, double y ){ return x < y; } +int reference_islessequal( double x, double y ){ return x <= y; } +int reference_islessgreater( double x, double y ){ return 0 != islessgreater( x, y ); } +int reference_isnan( double x ){ return 0 != isnan( x ); } +int reference_isnormal( double x ){ return 0 != isnormal( (float) x ); } +int reference_isnotequal( double x, double y ){ return x != y; } +int reference_isordered( double x, double y){ return x == x && y == y; } +int reference_isunordered( double x, double y ){ return isnan(x) || isnan( y ); } +int reference_signbit( float x ){ return 0 != signbit( x ); } + +#if 1 // defined( _MSC_VER ) + +//Missing functions for win32 + + +float reference_copysign( float x, float y ) +{ + union { float f; cl_uint u;} ux, uy; + ux.f = x; uy.f = y; + ux.u &= 0x7fffffffU; + ux.u |= uy.u & 0x80000000U; + return ux.f; +} + + +double reference_copysignd( double x, double y ) +{ + union { double f; cl_ulong u;} ux, uy; + ux.f = x; uy.f = y; + ux.u &= 0x7fffffffffffffffULL; + ux.u |= uy.u & 0x8000000000000000ULL; + return ux.f; +} + + +double reference_round( double x ) +{ + double absx = reference_fabs(x); + if( absx < 0.5 ) + return reference_copysignd( 0.0, x ); + + if( absx < HEX_DBL( +, 1, 0, +, 53 ) ) + x = reference_trunc( x + reference_copysignd( 0.5, x ) ); + + return x; +} + +double reference_trunc( double x ) +{ + if( fabs(x) < HEX_DBL( +, 1, 0, +, 53 ) ) + { + cl_long l = (cl_long) x; + + return reference_copysignd( (double) l, x ); + } + + return x; +} + +#ifndef FP_ILOGB0 + #define FP_ILOGB0 INT_MIN +#endif + +#ifndef FP_ILOGBNAN + #define FP_ILOGBNAN INT_MAX +#endif + + + +double reference_cbrt(double x){ return reference_copysignd( reference_pow( reference_fabs(x), 1.0/3.0 ), x ); } + +/* +double reference_scalbn(double x, int i) +{ // suitable for checking single precision scalbnf only + + if( i > 300 ) + return copysign( INFINITY, x); + if( i < -300 ) + return copysign( 0.0, x); + + union{ cl_ulong u; double d;} u; + u.u = ((cl_ulong) i + 1023) << 52; + + return x * u.d; +} +*/ + +double reference_rint( double x ) +{ + if( reference_fabs(x) < HEX_DBL( +, 1, 0, +, 52 ) ) + { + double magic = reference_copysignd( HEX_DBL( +, 1, 0, +, 52 ), x ); + double rounded = (x + magic) - magic; + x = reference_copysignd( rounded, x ); + } + + return x; +} + +double reference_acosh( double x ) +{ // not full precision. Sufficient precision to cover float + if( isnan(x) ) + return x + x; + + if( x < 1.0 ) + return cl_make_nan(); + + return reference_log( x + reference_sqrt(x + 1) * reference_sqrt(x-1) ); +} + +double reference_asinh( double x ) +{ +/* + * ==================================================== + * This function is from fdlibm: http://www.netlib.org + * It is Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + if( isnan(x) || isinf(x) ) + return x + x; + + double absx = reference_fabs(x); + if( absx < HEX_DBL( +, 1, 0, -, 28 ) ) + return x; + + double sign = reference_copysignd(1.0, x); + + if( absx > HEX_DBL( +, 1, 0, +, 28 ) ) + return sign * (reference_log( absx ) + 0.693147180559945309417232121458176568); // log(2) + + if( absx > 2.0 ) + return sign * reference_log( 2.0 * absx + 1.0 / (reference_sqrt( x * x + 1.0 ) + absx)); + + return sign * reference_log1p( absx + x*x / (1.0 + reference_sqrt(1.0 + x*x))); +} + + +double reference_atanh( double x ) +{ +/* + * ==================================================== + * This function is from fdlibm: http://www.netlib.org + * It is Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + if( isnan(x) ) + return x + x; + + double signed_half = reference_copysignd( 0.5, x ); + x = reference_fabs(x); + if( x > 1.0 ) + return cl_make_nan(); + + if( x < 0.5 ) + return signed_half * reference_log1p( 2.0 * ( x + x*x / (1-x) ) ); + + return signed_half * reference_log1p(2.0 * x / (1-x)); +} + +double reference_relaxed_exp2( double x ) +{ + return reference_exp2(x); +} + +double reference_exp2( double x ) +{ // Note: only suitable for verifying single precision. Doesn't have range of a full double exp2 implementation. + if( x == 0.0 ) + return 1.0; + + // separate x into fractional and integer parts + double i = reference_rint( x ); // round to nearest integer + + if( i < -150 ) + return 0.0; + + if( i > 129 ) + return INFINITY; + + double f = x - i; // -0.5 <= f <= 0.5 + + // find exp2(f) + // calculate as p(f) = (exp2(f)-1)/f + // exp2(f) = f * p(f) + 1 + // p(f) is a minimax polynomial with error within 0x1.c1fd80f0d1ab7p-50 + + double p = 0.693147180560184539289 + + (0.240226506955902863183 + + (0.055504108656833424373 + + (0.009618129212846484796 + + (0.001333355902958566035 + + (0.000154034191902497930 + + (0.000015252317761038105 + + (0.000001326283129417092 + 0.000000102593187638680 * f)*f)*f)*f)*f)*f)*f)*f; + f *= p; + f += 1.0; + + // scale by 2 ** i + union{ cl_ulong u; double d; } u; + int exponent = (int) i + 1023; + u.u = (cl_ulong) exponent << 52; + + return f * u.d; +} + + +double reference_expm1( double x ) +{ // Note: only suitable for verifying single precision. Doesn't have range of a full double expm1 implementation. It is only accurate to 47 bits or less. + + // early out for small numbers and NaNs + if( ! (reference_fabs(x) > HEX_DBL( +, 1, 0, -, 24 )) ) + return x; + + // early out for large negative numbers + if( x < -130.0 ) + return -1.0; + + // early out for large positive numbers + if( x > 100.0 ) + return INFINITY; + + // separate x into fractional and integer parts + double i = reference_rint( x ); // round to nearest integer + double f = x - i; // -0.5 <= f <= 0.5 + + // reduce f to the range -0.0625 .. f.. 0.0625 + int index = (int) (f * 16.0) + 8; // 0...16 + + static const double reduction[17] = { -0.5, -0.4375, -0.375, -0.3125, -0.25, -0.1875, -0.125, -0.0625, + 0.0, + +0.0625, +0.125, +0.1875, +0.25, +0.3125, +0.375, +0.4375, +0.5 }; + + + // exponentials[i] = expm1(reduction[i]) + static const double exponentials[17] = { HEX_DBL( -, 1, 92e9a0720d3ec, -, 2 ), HEX_DBL( -, 1, 6adb1cd9205ee, -, 2 ), + HEX_DBL( -, 1, 40373d42ce2e3, -, 2 ), HEX_DBL( -, 1, 12d35a41ba104, -, 2 ), + HEX_DBL( -, 1, c5041854df7d4, -, 3 ), HEX_DBL( -, 1, 5e25fb4fde211, -, 3 ), + HEX_DBL( -, 1, e14aed893eef4, -, 4 ), HEX_DBL( -, 1, f0540438fd5c3, -, 5 ), + HEX_DBL( +, 0, 0, +, 0 ), + HEX_DBL( +, 1, 082b577d34ed8, -, 4 ), HEX_DBL( +, 1, 10b022db7ae68, -, 3 ), + HEX_DBL( +, 1, a65c0b85ac1a9, -, 3 ), HEX_DBL( +, 1, 22d78f0fa061a, -, 2 ), + HEX_DBL( +, 1, 77a45d8117fd5, -, 2 ), HEX_DBL( +, 1, d1e944f6fbdaa, -, 2 ), + HEX_DBL( +, 1, 190048ef6002, -, 1 ), HEX_DBL( +, 1, 4c2531c3c0d38, -, 1 ), + }; + + + f -= reduction[index]; + + // find expm1(f) + // calculate as p(f) = (exp(f)-1)/f + // expm1(f) = f * p(f) + // p(f) is a minimax polynomial with error within 0x1.1d7693618d001p-48 over the range +- 0.0625 + double p = 0.999999999999998001599 + + (0.499999999999839628284 + + (0.166666666672817459505 + + (0.041666666612283048687 + + (0.008333330214567431435 + + (0.001389005319303770070 + 0.000198833381525156667 * f)*f)*f)*f)*f)*f; + f *= p; // expm1( reduced f ) + + // expm1(f) = (exmp1( reduced_f) + 1.0) * ( exponentials[index] + 1 ) - 1 + // = exmp1( reduced_f) * exponentials[index] + exmp1( reduced_f) + exponentials[index] + 1 -1 + // = exmp1( reduced_f) * exponentials[index] + exmp1( reduced_f) + exponentials[index] + f += exponentials[index] + f * exponentials[index]; + + // scale by e ** i + int exponent = (int) i; + if( 0 == exponent ) + return f; // precise answer for x near 1 + + // table of e**(i-150) + static const double exp_table[128+150+1] = + { + HEX_DBL( +, 1, 82e16284f5ec5, -, 217 ), HEX_DBL( +, 1, 06e9996332ba1, -, 215 ), + HEX_DBL( +, 1, 6555cb289e44b, -, 214 ), HEX_DBL( +, 1, e5ab364643354, -, 213 ), + HEX_DBL( +, 1, 4a0bd18e64df7, -, 211 ), HEX_DBL( +, 1, c094499cc578e, -, 210 ), + HEX_DBL( +, 1, 30d759323998c, -, 208 ), HEX_DBL( +, 1, 9e5278ab1d4cf, -, 207 ), + HEX_DBL( +, 1, 198fa3f30be25, -, 205 ), HEX_DBL( +, 1, 7eae636d6144e, -, 204 ), + HEX_DBL( +, 1, 040f1036f4863, -, 202 ), HEX_DBL( +, 1, 6174e477a895f, -, 201 ), + HEX_DBL( +, 1, e065b82dd95a, -, 200 ), HEX_DBL( +, 1, 4676be491d129, -, 198 ), + HEX_DBL( +, 1, bbb5da5f7c823, -, 197 ), HEX_DBL( +, 1, 2d884eef5fdcb, -, 195 ), + HEX_DBL( +, 1, 99d3397ab8371, -, 194 ), HEX_DBL( +, 1, 1681497ed15b3, -, 192 ), + HEX_DBL( +, 1, 7a870f597fdbd, -, 191 ), HEX_DBL( +, 1, 013c74edba307, -, 189 ), + HEX_DBL( +, 1, 5d9ec4ada7938, -, 188 ), HEX_DBL( +, 1, db2edfd20fa7c, -, 187 ), + HEX_DBL( +, 1, 42eb9f39afb0b, -, 185 ), HEX_DBL( +, 1, b6e4f282b43f4, -, 184 ), + HEX_DBL( +, 1, 2a42764857b19, -, 182 ), HEX_DBL( +, 1, 9560792d19314, -, 181 ), + HEX_DBL( +, 1, 137b6ce8e052c, -, 179 ), HEX_DBL( +, 1, 766b45dd84f18, -, 178 ), + HEX_DBL( +, 1, fce362fe6e7d, -, 177 ), HEX_DBL( +, 1, 59d34dd8a5473, -, 175 ), + HEX_DBL( +, 1, d606847fc727a, -, 174 ), HEX_DBL( +, 1, 3f6a58b795de3, -, 172 ), + HEX_DBL( +, 1, b2216c6efdac1, -, 171 ), HEX_DBL( +, 1, 2705b5b153fb8, -, 169 ), + HEX_DBL( +, 1, 90fa1509bd50d, -, 168 ), HEX_DBL( +, 1, 107df698da211, -, 166 ), + HEX_DBL( +, 1, 725ae6e7b9d35, -, 165 ), HEX_DBL( +, 1, f75d6040aeff6, -, 164 ), + HEX_DBL( +, 1, 56126259e093c, -, 162 ), HEX_DBL( +, 1, d0ec7df4f7bd4, -, 161 ), + HEX_DBL( +, 1, 3bf2cf6722e46, -, 159 ), HEX_DBL( +, 1, ad6b22f55db42, -, 158 ), + HEX_DBL( +, 1, 23d1f3e5834a, -, 156 ), HEX_DBL( +, 1, 8c9feab89b876, -, 155 ), + HEX_DBL( +, 1, 0d88cf37f00dd, -, 153 ), HEX_DBL( +, 1, 6e55d2bf838a7, -, 152 ), + HEX_DBL( +, 1, f1e6b68529e33, -, 151 ), HEX_DBL( +, 1, 525be4e4e601d, -, 149 ), + HEX_DBL( +, 1, cbe0a45f75eb1, -, 148 ), HEX_DBL( +, 1, 3884e838aea68, -, 146 ), + HEX_DBL( +, 1, a8c1f14e2af5d, -, 145 ), HEX_DBL( +, 1, 20a717e64a9bd, -, 143 ), + HEX_DBL( +, 1, 8851d84118908, -, 142 ), HEX_DBL( +, 1, 0a9bdfb02d24, -, 140 ), + HEX_DBL( +, 1, 6a5bea046b42e, -, 139 ), HEX_DBL( +, 1, ec7f3b269efa8, -, 138 ), + HEX_DBL( +, 1, 4eafb87eab0f2, -, 136 ), HEX_DBL( +, 1, c6e2d05bbc, -, 135 ), + HEX_DBL( +, 1, 35208867c2683, -, 133 ), HEX_DBL( +, 1, a425b317eeacd, -, 132 ), + HEX_DBL( +, 1, 1d8508fa8246a, -, 130 ), HEX_DBL( +, 1, 840fbc08fdc8a, -, 129 ), + HEX_DBL( +, 1, 07b7112bc1ffe, -, 127 ), HEX_DBL( +, 1, 666d0dad2961d, -, 126 ), + HEX_DBL( +, 1, e726c3f64d0fe, -, 125 ), HEX_DBL( +, 1, 4b0dc07cabf98, -, 123 ), + HEX_DBL( +, 1, c1f2daf3b6a46, -, 122 ), HEX_DBL( +, 1, 31c5957a47de2, -, 120 ), + HEX_DBL( +, 1, 9f96445648b9f, -, 119 ), HEX_DBL( +, 1, 1a6baeadb4fd1, -, 117 ), + HEX_DBL( +, 1, 7fd974d372e45, -, 116 ), HEX_DBL( +, 1, 04da4d1452919, -, 114 ), + HEX_DBL( +, 1, 62891f06b345, -, 113 ), HEX_DBL( +, 1, e1dd273aa8a4a, -, 112 ), + HEX_DBL( +, 1, 4775e0840bfdd, -, 110 ), HEX_DBL( +, 1, bd109d9d94bda, -, 109 ), + HEX_DBL( +, 1, 2e73f53fba844, -, 107 ), HEX_DBL( +, 1, 9b138170d6bfe, -, 106 ), + HEX_DBL( +, 1, 175af0cf60ec5, -, 104 ), HEX_DBL( +, 1, 7baee1bffa80b, -, 103 ), + HEX_DBL( +, 1, 02057d1245ceb, -, 101 ), HEX_DBL( +, 1, 5eafffb34ba31, -, 100 ), + HEX_DBL( +, 1, dca23bae16424, -, 99 ), HEX_DBL( +, 1, 43e7fc88b8056, -, 97 ), + HEX_DBL( +, 1, b83bf23a9a9eb, -, 96 ), HEX_DBL( +, 1, 2b2b8dd05b318, -, 94 ), + HEX_DBL( +, 1, 969d47321e4cc, -, 93 ), HEX_DBL( +, 1, 1452b7723aed2, -, 91 ), + HEX_DBL( +, 1, 778fe2497184c, -, 90 ), HEX_DBL( +, 1, fe7116182e9cc, -, 89 ), + HEX_DBL( +, 1, 5ae191a99585a, -, 87 ), HEX_DBL( +, 1, d775d87da854d, -, 86 ), + HEX_DBL( +, 1, 4063f8cc8bb98, -, 84 ), HEX_DBL( +, 1, b374b315f87c1, -, 83 ), + HEX_DBL( +, 1, 27ec458c65e3c, -, 81 ), HEX_DBL( +, 1, 923372c67a074, -, 80 ), + HEX_DBL( +, 1, 1152eaeb73c08, -, 78 ), HEX_DBL( +, 1, 737c5645114b5, -, 77 ), + HEX_DBL( +, 1, f8e6c24b5592e, -, 76 ), HEX_DBL( +, 1, 571db733a9d61, -, 74 ), + HEX_DBL( +, 1, d257d547e083f, -, 73 ), HEX_DBL( +, 1, 3ce9b9de78f85, -, 71 ), + HEX_DBL( +, 1, aebabae3a41b5, -, 70 ), HEX_DBL( +, 1, 24b6031b49bda, -, 68 ), + HEX_DBL( +, 1, 8dd5e1bb09d7e, -, 67 ), HEX_DBL( +, 1, 0e5b73d1ff53d, -, 65 ), + HEX_DBL( +, 1, 6f741de1748ec, -, 64 ), HEX_DBL( +, 1, f36bd37f42f3e, -, 63 ), + HEX_DBL( +, 1, 536452ee2f75c, -, 61 ), HEX_DBL( +, 1, cd480a1b7482, -, 60 ), + HEX_DBL( +, 1, 39792499b1a24, -, 58 ), HEX_DBL( +, 1, aa0de4bf35b38, -, 57 ), + HEX_DBL( +, 1, 2188ad6ae3303, -, 55 ), HEX_DBL( +, 1, 898471fca6055, -, 54 ), + HEX_DBL( +, 1, 0b6c3afdde064, -, 52 ), HEX_DBL( +, 1, 6b7719a59f0e, -, 51 ), + HEX_DBL( +, 1, ee001eed62aa, -, 50 ), HEX_DBL( +, 1, 4fb547c775da8, -, 48 ), + HEX_DBL( +, 1, c8464f7616468, -, 47 ), HEX_DBL( +, 1, 36121e24d3bba, -, 45 ), + HEX_DBL( +, 1, a56e0c2ac7f75, -, 44 ), HEX_DBL( +, 1, 1e642baeb84a, -, 42 ), + HEX_DBL( +, 1, 853f01d6d53ba, -, 41 ), HEX_DBL( +, 1, 0885298767e9a, -, 39 ), + HEX_DBL( +, 1, 67852a7007e42, -, 38 ), HEX_DBL( +, 1, e8a37a45fc32e, -, 37 ), + HEX_DBL( +, 1, 4c1078fe9228a, -, 35 ), HEX_DBL( +, 1, c3527e433fab1, -, 34 ), + HEX_DBL( +, 1, 32b48bf117da2, -, 32 ), HEX_DBL( +, 1, a0db0d0ddb3ec, -, 31 ), + HEX_DBL( +, 1, 1b48655f37267, -, 29 ), HEX_DBL( +, 1, 81056ff2c5772, -, 28 ), + HEX_DBL( +, 1, 05a628c699fa1, -, 26 ), HEX_DBL( +, 1, 639e3175a689d, -, 25 ), + HEX_DBL( +, 1, e355bbaee85cb, -, 24 ), HEX_DBL( +, 1, 4875ca227ec38, -, 22 ), + HEX_DBL( +, 1, be6c6fdb01612, -, 21 ), HEX_DBL( +, 1, 2f6053b981d98, -, 19 ), + HEX_DBL( +, 1, 9c54c3b43bc8b, -, 18 ), HEX_DBL( +, 1, 18354238f6764, -, 16 ), + HEX_DBL( +, 1, 7cd79b5647c9b, -, 15 ), HEX_DBL( +, 1, 02cf22526545a, -, 13 ), + HEX_DBL( +, 1, 5fc21041027ad, -, 12 ), HEX_DBL( +, 1, de16b9c24a98f, -, 11 ), + HEX_DBL( +, 1, 44e51f113d4d6, -, 9 ), HEX_DBL( +, 1, b993fe00d5376, -, 8 ), + HEX_DBL( +, 1, 2c155b8213cf4, -, 6 ), HEX_DBL( +, 1, 97db0ccceb0af, -, 5 ), + HEX_DBL( +, 1, 152aaa3bf81cc, -, 3 ), HEX_DBL( +, 1, 78b56362cef38, -, 2 ), + HEX_DBL( +, 1, 0, +, 0 ), HEX_DBL( +, 1, 5bf0a8b145769, +, 1 ), + HEX_DBL( +, 1, d8e64b8d4ddae, +, 2 ), HEX_DBL( +, 1, 415e5bf6fb106, +, 4 ), + HEX_DBL( +, 1, b4c902e273a58, +, 5 ), HEX_DBL( +, 1, 28d389970338f, +, 7 ), + HEX_DBL( +, 1, 936dc5690c08f, +, 8 ), HEX_DBL( +, 1, 122885aaeddaa, +, 10 ), + HEX_DBL( +, 1, 749ea7d470c6e, +, 11 ), HEX_DBL( +, 1, fa7157c470f82, +, 12 ), + HEX_DBL( +, 1, 5829dcf95056, +, 14 ), HEX_DBL( +, 1, d3c4488ee4f7f, +, 15 ), + HEX_DBL( +, 1, 3de1654d37c9a, +, 17 ), HEX_DBL( +, 1, b00b5916ac955, +, 18 ), + HEX_DBL( +, 1, 259ac48bf05d7, +, 20 ), HEX_DBL( +, 1, 8f0ccafad2a87, +, 21 ), + HEX_DBL( +, 1, 0f2ebd0a8002, +, 23 ), HEX_DBL( +, 1, 709348c0ea4f9, +, 24 ), + HEX_DBL( +, 1, f4f22091940bd, +, 25 ), HEX_DBL( +, 1, 546d8f9ed26e1, +, 27 ), + HEX_DBL( +, 1, ceb088b68e804, +, 28 ), HEX_DBL( +, 1, 3a6e1fd9eecfd, +, 30 ), + HEX_DBL( +, 1, ab5adb9c436, +, 31 ), HEX_DBL( +, 1, 226af33b1fdc1, +, 33 ), + HEX_DBL( +, 1, 8ab7fb5475fb7, +, 34 ), HEX_DBL( +, 1, 0c3d3920962c9, +, 36 ), + HEX_DBL( +, 1, 6c932696a6b5d, +, 37 ), HEX_DBL( +, 1, ef822f7f6731d, +, 38 ), + HEX_DBL( +, 1, 50bba3796379a, +, 40 ), HEX_DBL( +, 1, c9aae4631c056, +, 41 ), + HEX_DBL( +, 1, 370470aec28ed, +, 43 ), HEX_DBL( +, 1, a6b765d8cdf6d, +, 44 ), + HEX_DBL( +, 1, 1f43fcc4b662c, +, 46 ), HEX_DBL( +, 1, 866f34a725782, +, 47 ), + HEX_DBL( +, 1, 0953e2f3a1ef7, +, 49 ), HEX_DBL( +, 1, 689e221bc8d5b, +, 50 ), + HEX_DBL( +, 1, ea215a1d20d76, +, 51 ), HEX_DBL( +, 1, 4d13fbb1a001a, +, 53 ), + HEX_DBL( +, 1, c4b334617cc67, +, 54 ), HEX_DBL( +, 1, 33a43d282a519, +, 56 ), + HEX_DBL( +, 1, a220d397972eb, +, 57 ), HEX_DBL( +, 1, 1c25c88df6862, +, 59 ), + HEX_DBL( +, 1, 8232558201159, +, 60 ), HEX_DBL( +, 1, 0672a3c9eb871, +, 62 ), + HEX_DBL( +, 1, 64b41c6d37832, +, 63 ), HEX_DBL( +, 1, e4cf766fe49be, +, 64 ), + HEX_DBL( +, 1, 49767bc0483e3, +, 66 ), HEX_DBL( +, 1, bfc951eb8bb76, +, 67 ), + HEX_DBL( +, 1, 304d6aeca254b, +, 69 ), HEX_DBL( +, 1, 9d97010884251, +, 70 ), + HEX_DBL( +, 1, 19103e4080b45, +, 72 ), HEX_DBL( +, 1, 7e013cd114461, +, 73 ), + HEX_DBL( +, 1, 03996528e074c, +, 75 ), HEX_DBL( +, 1, 60d4f6fdac731, +, 76 ), + HEX_DBL( +, 1, df8c5af17ba3b, +, 77 ), HEX_DBL( +, 1, 45e3076d61699, +, 79 ), + HEX_DBL( +, 1, baed16a6e0da7, +, 80 ), HEX_DBL( +, 1, 2cffdfebde1a1, +, 82 ), + HEX_DBL( +, 1, 9919cabefcb69, +, 83 ), HEX_DBL( +, 1, 160345c9953e3, +, 85 ), + HEX_DBL( +, 1, 79dbc9dc53c66, +, 86 ), HEX_DBL( +, 1, 00c810d464097, +, 88 ), + HEX_DBL( +, 1, 5d009394c5c27, +, 89 ), HEX_DBL( +, 1, da57de8f107a8, +, 90 ), + HEX_DBL( +, 1, 425982cf597cd, +, 92 ), HEX_DBL( +, 1, b61e5ca3a5e31, +, 93 ), + HEX_DBL( +, 1, 29bb825dfcf87, +, 95 ), HEX_DBL( +, 1, 94a90db0d6fe2, +, 96 ), + HEX_DBL( +, 1, 12fec759586fd, +, 98 ), HEX_DBL( +, 1, 75c1dc469e3af, +, 99 ), + HEX_DBL( +, 1, fbfd219c43b04, +, 100 ), HEX_DBL( +, 1, 5936d44e1a146, +, 102 ), + HEX_DBL( +, 1, d531d8a7ee79c, +, 103 ), HEX_DBL( +, 1, 3ed9d24a2d51b, +, 105 ), + HEX_DBL( +, 1, b15cfe5b6e17b, +, 106 ), HEX_DBL( +, 1, 268038c2c0e, +, 108 ), + HEX_DBL( +, 1, 9044a73545d48, +, 109 ), HEX_DBL( +, 1, 1002ab6218b38, +, 111 ), + HEX_DBL( +, 1, 71b3540cbf921, +, 112 ), HEX_DBL( +, 1, f6799ea9c414a, +, 113 ), + HEX_DBL( +, 1, 55779b984f3eb, +, 115 ), HEX_DBL( +, 1, d01a210c44aa4, +, 116 ), + HEX_DBL( +, 1, 3b63da8e9121, +, 118 ), HEX_DBL( +, 1, aca8d6b0116b8, +, 119 ), + HEX_DBL( +, 1, 234de9e0c74e9, +, 121 ), HEX_DBL( +, 1, 8bec7503ca477, +, 122 ), + HEX_DBL( +, 1, 0d0eda9796b9, +, 124 ), HEX_DBL( +, 1, 6db0118477245, +, 125 ), + HEX_DBL( +, 1, f1056dc7bf22d, +, 126 ), HEX_DBL( +, 1, 51c2cc3433801, +, 128 ), + HEX_DBL( +, 1, cb108ffbec164, +, 129 ), HEX_DBL( +, 1, 37f780991b584, +, 131 ), + HEX_DBL( +, 1, a801c0ea8ac4d, +, 132 ), HEX_DBL( +, 1, 20247cc4c46c1, +, 134 ), + HEX_DBL( +, 1, 87a0553328015, +, 135 ), HEX_DBL( +, 1, 0a233dee4f9bb, +, 137 ), + HEX_DBL( +, 1, 69b7f55b808ba, +, 138 ), HEX_DBL( +, 1, eba064644060a, +, 139 ), + HEX_DBL( +, 1, 4e184933d9364, +, 141 ), HEX_DBL( +, 1, c614fe2531841, +, 142 ), + HEX_DBL( +, 1, 3494a9b171bf5, +, 144 ), HEX_DBL( +, 1, a36798b9d969b, +, 145 ), + HEX_DBL( +, 1, 1d03d8c0c04af, +, 147 ), HEX_DBL( +, 1, 836026385c974, +, 148 ), + HEX_DBL( +, 1, 073fbe9ac901d, +, 150 ), HEX_DBL( +, 1, 65cae0969f286, +, 151 ), + HEX_DBL( +, 1, e64a58639cae8, +, 152 ), HEX_DBL( +, 1, 4a77f5f9b50f9, +, 154 ), + HEX_DBL( +, 1, c12744a3a28e3, +, 155 ), HEX_DBL( +, 1, 313b3b6978e85, +, 157 ), + HEX_DBL( +, 1, 9eda3a31e587e, +, 158 ), HEX_DBL( +, 1, 19ebe56b56453, +, 160 ), + HEX_DBL( +, 1, 7f2bc6e599b7e, +, 161 ), HEX_DBL( +, 1, 04644610df2ff, +, 163 ), + HEX_DBL( +, 1, 61e8b490ac4e6, +, 164 ), HEX_DBL( +, 1, e103201f299b3, +, 165 ), + HEX_DBL( +, 1, 46e1b637beaf5, +, 167 ), HEX_DBL( +, 1, bc473cfede104, +, 168 ), + HEX_DBL( +, 1, 2deb1b9c85e2d, +, 170 ), HEX_DBL( +, 1, 9a5981ca67d1, +, 171 ), + HEX_DBL( +, 1, 16dc8a9ef670b, +, 173 ), HEX_DBL( +, 1, 7b03166942309, +, 174 ), + HEX_DBL( +, 1, 0190be03150a7, +, 176 ), HEX_DBL( +, 1, 5e1152f9a8119, +, 177 ), + HEX_DBL( +, 1, dbca9263f8487, +, 178 ), HEX_DBL( +, 1, 43556dee93bee, +, 180 ), + HEX_DBL( +, 1, b774c12967dfa, +, 181 ), HEX_DBL( +, 1, 2aa4306e922c2, +, 183 ), + HEX_DBL( +, 1, 95e54c5dd4217, +, 184 ) }; + + // scale by e**i -- (expm1(f) + 1)*e**i - 1 = expm1(f) * e**i + e**i - 1 = e**i + return exp_table[exponent+150] + (f * exp_table[exponent+150] - 1.0); +} + + +double reference_fmax( double x, double y ) +{ + if( isnan(y) ) + return x; + + return x >= y ? x : y; +} + +double reference_fmin( double x, double y ) +{ + if( isnan(y) ) + return x; + + return x <= y ? x : y; +} + +double reference_hypot( double x, double y ) +{ + // Since the inputs are actually floats, we don't have to worry about range here + if( isinf(x) || isinf(y) ) + return INFINITY; + + return sqrt( x * x + y * y ); +} + +int reference_ilogbl( long double x) +{ + extern int gDeviceILogb0, gDeviceILogbNaN; + + // Since we are just using this to verify double precision, we can + // use the double precision ilogb here + union { double f; cl_ulong u;} u; + u.f = (double) x; + + int exponent = (int)(u.u >> 52) & 0x7ff; + if( exponent == 0x7ff ) + { + if( u.u & 0x000fffffffffffffULL ) + return gDeviceILogbNaN; + + return CL_INT_MAX; + } + + if( exponent == 0 ) + { // deal with denormals + u.f = x * HEX_DBL( +, 1, 0, +, 64 ); + exponent = (cl_uint)(u.u >> 52) & 0x7ff; + if( exponent == 0 ) + return gDeviceILogb0; + + exponent -= 1023 + 64; + return exponent; + } + + return exponent - 1023; +} + +//double reference_log2( double x ) +//{ +// return log( x ) * 1.44269504088896340735992468100189214; +//} + + +double reference_relaxed_log2( double x ) +{ + return reference_log2(x); +} + +double reference_log2( double x ) +{ + if( isnan(x) || x < 0.0 || x == -INFINITY) + return cl_make_nan(); + + if( x == 0.0f) + return -INFINITY; + + if( x == INFINITY ) + return INFINITY; + + double hi, lo; + __log2_ep( &hi, &lo, x ); + return hi; +} + +double reference_log1p( double x ) +{ // This function is suitable only for verifying log1pf(). It produces several double precision ulps of error. + + // Handle small and NaN + if( ! ( reference_fabs(x) > HEX_DBL( +, 1, 0, -, 53 ) ) ) + return x; + + // deal with special values + if( x <= -1.0 ) + { + if( x < -1.0 ) + return cl_make_nan(); + return -INFINITY; + } + + // infinity + if( x == INFINITY ) + return INFINITY; + + // High precision result for when near 0, to avoid problems with the reference result falling in the wrong binade. + if( reference_fabs(x) < HEX_DBL( +, 1, 0, -, 28 ) ) + return (1.0 - 0.5 * x) * x; + + // Our polynomial is only good in the region +-2**-4. + // If we aren't in that range then we need to reduce to be in that range + double correctionLo = -0.0; // correction down stream to compensate for the reduction, if any + double correctionHi = -0.0; // correction down stream to compensate for the exponent, if any + if( reference_fabs(x) > HEX_DBL( +, 1, 0, -, 4 ) ) + { + x += 1.0; // double should cover any loss of precision here + + // separate x into (1+f) * 2**i + union{ double d; cl_ulong u;} u; u.d = x; + int i = (int) ((u.u >> 52) & 0x7ff) - 1023; + u.u &= 0x000fffffffffffffULL; + int index = (int) (u.u >> 48 ); + u.u |= 0x3ff0000000000000ULL; + double f = u.d; + + // further reduce f to be within 1/16 of 1.0 + static const double scale_table[16] = { 1.0, HEX_DBL( +, 1, d2d2d2d6e3f79, -, 1 ), HEX_DBL( +, 1, b8e38e42737a1, -, 1 ), HEX_DBL( +, 1, a1af28711adf3, -, 1 ), + HEX_DBL( +, 1, 8cccccd88dd65, -, 1 ), HEX_DBL( +, 1, 79e79e810ec8f, -, 1 ), HEX_DBL( +, 1, 68ba2e94df404, -, 1 ), HEX_DBL( +, 1, 590b216defb29, -, 1 ), + HEX_DBL( +, 1, 4aaaaab1500ed, -, 1 ), HEX_DBL( +, 1, 3d70a3e0d6f73, -, 1 ), HEX_DBL( +, 1, 313b13bb39f4f, -, 1 ), HEX_DBL( +, 1, 25ed09823f1cc, -, 1 ), + HEX_DBL( +, 1, 1b6db6e77457b, -, 1 ), HEX_DBL( +, 1, 11a7b96a3a34f, -, 1 ), HEX_DBL( +, 1, 0888888e46fea, -, 1 ), HEX_DBL( +, 1, 00000038e9862, -, 1 ) }; + + // correction_table[i] = -log( scale_table[i] ) + // All entries have >= 64 bits of precision (rather than the expected 53) + static const double correction_table[16] = { -0.0, HEX_DBL( +, 1, 7a5c722c16058, -, 4 ), HEX_DBL( +, 1, 323db16c89ab1, -, 3 ), HEX_DBL( +, 1, a0f87d180629, -, 3 ), + HEX_DBL( +, 1, 050279324e17c, -, 2 ), HEX_DBL( +, 1, 36f885bb270b0, -, 2 ), HEX_DBL( +, 1, 669b771b5cc69, -, 2 ), HEX_DBL( +, 1, 94203a6292a05, -, 2 ), + HEX_DBL( +, 1, bfb4f9cb333a4, -, 2 ), HEX_DBL( +, 1, e982376ddb80e, -, 2 ), HEX_DBL( +, 1, 08d5d8769b2b2, -, 1 ), HEX_DBL( +, 1, 1c288bc00e0cf, -, 1 ), + HEX_DBL( +, 1, 2ec7535b31ecb, -, 1 ), HEX_DBL( +, 1, 40bed0adc63fb, -, 1 ), HEX_DBL( +, 1, 521a5c0330615, -, 1 ), HEX_DBL( +, 1, 62e42f7dd092c, -, 1 ) }; + + f *= scale_table[index]; + correctionLo = correction_table[index]; + + // log( 2**(i) ) = i * log(2) + correctionHi = (double)i * 0.693147180559945309417232121458176568; + + x = f - 1.0; + } + + + // minmax polynomial for p(x) = (log(x+1) - x)/x valid over the range x = [-1/16, 1/16] + // max error HEX_DBL( +, 1, 048f61f9a5eca, -, 52 ) + double p = HEX_DBL( -, 1, cc33de97a9d7b, -, 46 ) + + (HEX_DBL( -, 1, fffffffff3eb7, -, 2 ) + + (HEX_DBL( +, 1, 5555555633ef7, -, 2 ) + + (HEX_DBL( -, 1, 00000062c78, -, 2 ) + + (HEX_DBL( +, 1, 9999958a3321, -, 3 ) + + (HEX_DBL( -, 1, 55534ce65c347, -, 3 ) + + (HEX_DBL( +, 1, 24957208391a5, -, 3 ) + + (HEX_DBL( -, 1, 02287b9a5b4a1, -, 3 ) + + HEX_DBL( +, 1, c757d922180ed, -, 4 ) * x)*x)*x)*x)*x)*x)*x)*x; + + // log(x+1) = x * p(x) + x + x += x * p; + + return correctionHi + (correctionLo + x); +} + +double reference_logb( double x ) +{ + union { float f; cl_uint u;} u; + u.f = (float) x; + + cl_int exponent = (u.u >> 23) & 0xff; + if( exponent == 0xff ) + return x * x; + + if( exponent == 0 ) + { // deal with denormals + u.u = (u.u & 0x007fffff) | 0x3f800000; + u.f -= 1.0f; + exponent = (u.u >> 23) & 0xff; + if( exponent == 0 ) + return -INFINITY; + + return exponent - (127 + 126); + } + + return exponent - 127; +} + +double reference_relaxed_reciprocal(double x) +{ + return 1.0f / ((float) x); +} + +double reference_reciprocal( double x ) +{ + return 1.0 / x; +} + +double reference_remainder( double x, double y ) +{ + int i; + return reference_remquo( x, y, &i ); +} + +double reference_lgamma( double x) +{ +/* + * ==================================================== + * This function is from fdlibm. http://www.netlib.org + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + */ + +static const double //two52 = 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ + one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ + pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ + a0 = 7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */ + a1 = 3.22467033424113591611e-01, /* 0x3FD4A34C, 0xC4A60FAD */ + a2 = 6.73523010531292681824e-02, /* 0x3FB13E00, 0x1A5562A7 */ + a3 = 2.05808084325167332806e-02, /* 0x3F951322, 0xAC92547B */ + a4 = 7.38555086081402883957e-03, /* 0x3F7E404F, 0xB68FEFE8 */ + a5 = 2.89051383673415629091e-03, /* 0x3F67ADD8, 0xCCB7926B */ + a6 = 1.19270763183362067845e-03, /* 0x3F538A94, 0x116F3F5D */ + a7 = 5.10069792153511336608e-04, /* 0x3F40B6C6, 0x89B99C00 */ + a8 = 2.20862790713908385557e-04, /* 0x3F2CF2EC, 0xED10E54D */ + a9 = 1.08011567247583939954e-04, /* 0x3F1C5088, 0x987DFB07 */ + a10 = 2.52144565451257326939e-05, /* 0x3EFA7074, 0x428CFA52 */ + a11 = 4.48640949618915160150e-05, /* 0x3F07858E, 0x90A45837 */ + tc = 1.46163214496836224576e+00, /* 0x3FF762D8, 0x6356BE3F */ + tf = -1.21486290535849611461e-01, /* 0xBFBF19B9, 0xBCC38A42 */ + /* tt = -(tail of tf) */ + tt = -3.63867699703950536541e-18, /* 0xBC50C7CA, 0xA48A971F */ + t0 = 4.83836122723810047042e-01, /* 0x3FDEF72B, 0xC8EE38A2 */ + t1 = -1.47587722994593911752e-01, /* 0xBFC2E427, 0x8DC6C509 */ + t2 = 6.46249402391333854778e-02, /* 0x3FB08B42, 0x94D5419B */ + t3 = -3.27885410759859649565e-02, /* 0xBFA0C9A8, 0xDF35B713 */ + t4 = 1.79706750811820387126e-02, /* 0x3F9266E7, 0x970AF9EC */ + t5 = -1.03142241298341437450e-02, /* 0xBF851F9F, 0xBA91EC6A */ + t6 = 6.10053870246291332635e-03, /* 0x3F78FCE0, 0xE370E344 */ + t7 = -3.68452016781138256760e-03, /* 0xBF6E2EFF, 0xB3E914D7 */ + t8 = 2.25964780900612472250e-03, /* 0x3F6282D3, 0x2E15C915 */ + t9 = -1.40346469989232843813e-03, /* 0xBF56FE8E, 0xBF2D1AF1 */ + t10 = 8.81081882437654011382e-04, /* 0x3F4CDF0C, 0xEF61A8E9 */ + t11 = -5.38595305356740546715e-04, /* 0xBF41A610, 0x9C73E0EC */ + t12 = 3.15632070903625950361e-04, /* 0x3F34AF6D, 0x6C0EBBF7 */ + t13 = -3.12754168375120860518e-04, /* 0xBF347F24, 0xECC38C38 */ + t14 = 3.35529192635519073543e-04, /* 0x3F35FD3E, 0xE8C2D3F4 */ + u0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ + u1 = 6.32827064025093366517e-01, /* 0x3FE4401E, 0x8B005DFF */ + u2 = 1.45492250137234768737e+00, /* 0x3FF7475C, 0xD119BD6F */ + u3 = 9.77717527963372745603e-01, /* 0x3FEF4976, 0x44EA8450 */ + u4 = 2.28963728064692451092e-01, /* 0x3FCD4EAE, 0xF6010924 */ + u5 = 1.33810918536787660377e-02, /* 0x3F8B678B, 0xBF2BAB09 */ + v1 = 2.45597793713041134822e+00, /* 0x4003A5D7, 0xC2BD619C */ + v2 = 2.12848976379893395361e+00, /* 0x40010725, 0xA42B18F5 */ + v3 = 7.69285150456672783825e-01, /* 0x3FE89DFB, 0xE45050AF */ + v4 = 1.04222645593369134254e-01, /* 0x3FBAAE55, 0xD6537C88 */ + v5 = 3.21709242282423911810e-03, /* 0x3F6A5ABB, 0x57D0CF61 */ + s0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ + s1 = 2.14982415960608852501e-01, /* 0x3FCB848B, 0x36E20878 */ + s2 = 3.25778796408930981787e-01, /* 0x3FD4D98F, 0x4F139F59 */ + s3 = 1.46350472652464452805e-01, /* 0x3FC2BB9C, 0xBEE5F2F7 */ + s4 = 2.66422703033638609560e-02, /* 0x3F9B481C, 0x7E939961 */ + s5 = 1.84028451407337715652e-03, /* 0x3F5E26B6, 0x7368F239 */ + s6 = 3.19475326584100867617e-05, /* 0x3F00BFEC, 0xDD17E945 */ + r1 = 1.39200533467621045958e+00, /* 0x3FF645A7, 0x62C4AB74 */ + r2 = 7.21935547567138069525e-01, /* 0x3FE71A18, 0x93D3DCDC */ + r3 = 1.71933865632803078993e-01, /* 0x3FC601ED, 0xCCFBDF27 */ + r4 = 1.86459191715652901344e-02, /* 0x3F9317EA, 0x742ED475 */ + r5 = 7.77942496381893596434e-04, /* 0x3F497DDA, 0xCA41A95B */ + r6 = 7.32668430744625636189e-06, /* 0x3EDEBAF7, 0xA5B38140 */ + w0 = 4.18938533204672725052e-01, /* 0x3FDACFE3, 0x90C97D69 */ + w1 = 8.33333333333329678849e-02, /* 0x3FB55555, 0x5555553B */ + w2 = -2.77777777728775536470e-03, /* 0xBF66C16C, 0x16B02E5C */ + w3 = 7.93650558643019558500e-04, /* 0x3F4A019F, 0x98CF38B6 */ + w4 = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */ + w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */ + w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */ + + static const double zero= 0.00000000000000000000e+00; + double t,y,z,nadj,p,p1,p2,p3,q,r,w; + cl_int i,hx,lx,ix; + + union{ double d; cl_ulong u;}u; u.d = x; + + hx = (cl_int) (u.u >> 32); + lx = (cl_int) (u.u & 0xffffffffULL); + + /* purge off +-inf, NaN, +-0, and negative arguments */ +// *signgamp = 1; + ix = hx&0x7fffffff; + if(ix>=0x7ff00000) return x*x; + if((ix|lx)==0) return (double)(one)/(double)(zero); + if(ix<0x3b900000) { /* |x|<2**-70, return -log(|x|) */ + if(hx<0) { +// *signgamp = -1; + return -reference_log(-x); + } else return -reference_log(x); + } + if(hx<0) { + if(ix>=0x43300000) /* |x|>=2**52, must be -integer */ + return (double)(one)/(double)(zero); + t = reference_sinpi(x); + if(t==zero) (double)(one)/(double)(zero); /* -integer */ + nadj = reference_log(pi/reference_fabs(t*x)); +// if(t=0x3FE76944) {y = 1.0-x; i= 0;} + else if(ix>=0x3FCDA661) {y= x-(tc-one); i=1;} + else {y = x; i=2;} + } else { + r = zero; + if(ix>=0x3FFBB4C3) {y=2.0-x;i=0;} /* [1.7316,2] */ + else if(ix>=0x3FF3B4C4) {y=x-tc;i=1;} /* [1.23,1.73] */ + else {y=x-one;i=2;} + } + switch(i) { + case 0: + z = y*y; + p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10)))); + p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11))))); + p = y*p1+p2; + r += (p-0.5*y); break; + case 1: + z = y*y; + w = z*y; + p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */ + p2 = t1+w*(t4+w*(t7+w*(t10+w*t13))); + p3 = t2+w*(t5+w*(t8+w*(t11+w*t14))); + p = z*p1-(tt-w*(p2+y*p3)); + r += (tf + p); break; + case 2: + p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5))))); + p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5)))); + r += (-0.5*y + p1/p2); + } + } + else if(ix<0x40200000) { /* x < 8.0 */ + i = (int)x; + t = zero; + y = x-(double)i; + p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6)))))); + q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6))))); + r = half*y+p/q; + z = one; /* lgamma(1+s) = log(s) + lgamma(s) */ + switch(i) { + case 7: z *= (y+6.0); /* FALLTHRU */ + case 6: z *= (y+5.0); /* FALLTHRU */ + case 5: z *= (y+4.0); /* FALLTHRU */ + case 4: z *= (y+3.0); /* FALLTHRU */ + case 3: z *= (y+2.0); /* FALLTHRU */ + r += reference_log(z); break; + } + /* 8.0 <= x < 2**58 */ + } else if (ix < 0x43900000) { + t = reference_log(x); + z = one/x; + y = z*z; + w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6))))); + r = (x-half)*(t-one)+w; + } else + /* 2**58 <= x <= inf */ + r = x*(reference_log(x)-one); + if(hx<0) r = nadj - r; + return r; + +} + +#endif // _MSC_VER + +double reference_assignment( double x ){ return x; } + +int reference_not( double x ) +{ + int r = !x; + return r; +} + +#pragma mark - +#pragma mark Double testing + +#ifndef M_PIL + #define M_PIL 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899L +#endif + +static long double reduce1l( long double x ); + +#ifdef __PPC__ +// Since long double on PPC is really extended precision double arithmetic +// consisting of two doubles (a high and low). This form of long double has +// the potential of representing a number with more than LDBL_MANT_DIG digits +// such that reduction algorithm used for other architectures will not work. +// Instead and alternate reduction method is used. + +static long double reduce1l( long double x ) +{ + union { + long double ld; + double d[2]; + } u; + + // Reduce the high and low halfs separately. + u.ld = x; + return ((long double)reduce1(u.d[0]) + reduce1(u.d[1])); +} + +#else // !__PPC__ + +static long double reduce1l( long double x ) +{ + static long double unit_exp = 0; + if( 0.0L == unit_exp ) + unit_exp = scalbnl( 1.0L, LDBL_MANT_DIG); + + if( reference_fabsl(x) >= unit_exp ) + { + if( reference_fabsl(x) == INFINITY ) + return cl_make_nan(); + + return 0.0L; //we patch up the sign for sinPi and cosPi later, since they need different signs + } + + // Find the nearest multiple of 2 + const long double r = reference_copysignl( unit_exp, x ); + long double z = x + r; + z -= r; + + // subtract it from x. Value is now in the range -1 <= x <= 1 + return x - z; +} +#endif // __PPC__ + +long double reference_acospil( long double x){ return reference_acosl( x ) / M_PIL; } +long double reference_asinpil( long double x){ return reference_asinl( x ) / M_PIL; } +long double reference_atanpil( long double x){ return reference_atanl( x ) / M_PIL; } +long double reference_atan2pil( long double y, long double x){ return reference_atan2l( y, x) / M_PIL; } +long double reference_cospil( long double x) +{ + if( reference_fabsl(x) >= HEX_LDBL( +, 1, 0, +, 54 ) ) + { + if( reference_fabsl(x) == INFINITY ) + return cl_make_nan(); + + //Note this probably fails for odd values between 0x1.0p52 and 0x1.0p53. + //However, when starting with single precision inputs, there will be no odd values. + + return 1.0L; + } + + x = reduce1l(x); + +#if DBL_MANT_DIG >= LDBL_MANT_DIG + + // phase adjust + double xhi = 0.0; + double xlo = 0.0; + xhi = (double) x + 0.5; + + if(reference_fabsl(x) > 0.5L) + { + xlo = xhi - x; + xlo = 0.5 - xlo; + } + else + { + xlo = xhi - 0.5; + xlo = x - xlo; + } + + // reduce to [-0.5, 0.5] + if( xhi < -0.5 ) + { + xhi = -1.0 - xhi; + xlo = -xlo; + } + else if ( xhi > 0.5 ) + { + xhi = 1.0 - xhi; + xlo = -xlo; + } + + // cosPi zeros are all +0 + if( xhi == 0.0 && xlo == 0.0 ) + return 0.0; + + xhi *= M_PI; + xlo *= M_PI; + + xhi += xlo; + + return reference_sinl( xhi ); + +#else + // phase adjust + x += 0.5L; + + // reduce to [-0.5, 0.5] + if( x < -0.5L ) + x = -1.0L - x; + else if ( x > 0.5L ) + x = 1.0L - x; + + // cosPi zeros are all +0 + if( x == 0.0L ) + return 0.0L; + + return reference_sinl( x * M_PIL ); +#endif +} + +long double reference_dividel( long double x, long double y) +{ + double dx = x; + double dy = y; + return dx/dy; +} + +typedef struct{ double hi, lo; } double_double; + +// Split doubles_double into a series of consecutive 26-bit precise doubles and a remainder. +// Note for later -- for multiplication, it might be better to split each double into a power of two and two 26 bit portions +// multiplication of a double double by a known power of two is cheap. The current approach causes some inexact arithmetic in mul_dd. +static inline void split_dd( double_double x, double_double *hi, double_double *lo ) +{ + union{ double d; cl_ulong u;}u; + u.d = x.hi; + u.u &= 0xFFFFFFFFF8000000ULL; + hi->hi = u.d; + x.hi -= u.d; + + u.d = x.hi; + u.u &= 0xFFFFFFFFF8000000ULL; + hi->lo = u.d; + x.hi -= u.d; + + double temp = x.hi; + x.hi += x.lo; + x.lo -= x.hi - temp; + u.d = x.hi; + u.u &= 0xFFFFFFFFF8000000ULL; + lo->hi = u.d; + x.hi -= u.d; + + lo->lo = x.hi + x.lo; +} + +static inline double_double accum_d( double_double a, double b ) +{ + double temp; + if( fabs(b) > fabs(a.hi) ) + { + temp = a.hi; + a.hi += b; + a.lo += temp - (a.hi - b); + } + else + { + temp = a.hi; + a.hi += b; + a.lo += b - (a.hi - temp); + } + + if( isnan( a.lo ) ) + a.lo = 0.0; + + return a; +} + +static inline double_double add_dd( double_double a, double_double b ) +{ + double_double r = {-0.0 -0.0 }; + + if( isinf(a.hi) || isinf( b.hi ) || + isnan(a.hi) || isnan( b.hi ) || + 0.0 == a.hi || 0.0 == b.hi ) + { + r.hi = a.hi + b.hi; + r.lo = a.lo + b.lo; + if( isnan( r.lo ) ) + r.lo = 0.0; + return r; + } + + //merge sort terms by magnitude -- here we assume that |a.hi| > |a.lo|, |b.hi| > |b.lo|, so we don't have to do the first merge pass + double terms[4] = { a.hi, b.hi, a.lo, b.lo }; + double temp; + + //Sort hi terms + if( fabs(terms[0]) < fabs(terms[1]) ) + { + temp = terms[0]; + terms[0] = terms[1]; + terms[1] = temp; + } + //sort lo terms + if( fabs(terms[2]) < fabs(terms[3]) ) + { + temp = terms[2]; + terms[2] = terms[3]; + terms[3] = temp; + } + // Fix case where small high term is less than large low term + if( fabs(terms[1]) < fabs(terms[2]) ) + { + temp = terms[1]; + terms[1] = terms[2]; + terms[2] = temp; + } + + // accumulate the results + r.hi = terms[2] + terms[3]; + r.lo = terms[3] - (r.hi - terms[2]); + + temp = r.hi; + r.hi += terms[1]; + r.lo += temp - (r.hi - terms[1]); + + temp = r.hi; + r.hi += terms[0]; + r.lo += temp - (r.hi - terms[0]); + + // canonicalize the result + temp = r.hi; + r.hi += r.lo; + r.lo = r.lo - (r.hi - temp); + if( isnan( r.lo ) ) + r.lo = 0.0; + + return r; +} + +static inline double_double mul_dd( double_double a, double_double b ) +{ + double_double result = {-0.0,-0.0}; + + // Inf, nan and 0 + if( isnan( a.hi ) || isnan( b.hi ) || + isinf( a.hi ) || isinf( b.hi ) || + 0.0 == a.hi || 0.0 == b.hi ) + { + result.hi = a.hi * b.hi; + return result; + } + + double_double ah, al, bh, bl; + split_dd( a, &ah, &al ); + split_dd( b, &bh, &bl ); + + double p0 = ah.hi * bh.hi; // exact (52 bits in product) 0 + double p1 = ah.hi * bh.lo; // exact (52 bits in product) 26 + double p2 = ah.lo * bh.hi; // exact (52 bits in product) 26 + double p3 = ah.lo * bh.lo; // exact (52 bits in product) 52 + double p4 = al.hi * bh.hi; // exact (52 bits in product) 52 + double p5 = al.hi * bh.lo; // exact (52 bits in product) 78 + double p6 = al.lo * bh.hi; // inexact (54 bits in product) 78 + double p7 = al.lo * bh.lo; // inexact (54 bits in product) 104 + double p8 = ah.hi * bl.hi; // exact (52 bits in product) 52 + double p9 = ah.hi * bl.lo; // inexact (54 bits in product) 78 + double pA = ah.lo * bl.hi; // exact (52 bits in product) 78 + double pB = ah.lo * bl.lo; // inexact (54 bits in product) 104 + double pC = al.hi * bl.hi; // exact (52 bits in product) 104 + // the last 3 terms are two low to appear in the result + + + // accumulate from bottom up +#if 0 + // works but slow + result.hi = pC; + result = accum_d( result, pB ); + result = accum_d( result, p7 ); + result = accum_d( result, pA ); + result = accum_d( result, p9 ); + result = accum_d( result, p6 ); + result = accum_d( result, p5 ); + result = accum_d( result, p8 ); + result = accum_d( result, p4 ); + result = accum_d( result, p3 ); + result = accum_d( result, p2 ); + result = accum_d( result, p1 ); + result = accum_d( result, p0 ); + + // canonicalize the result + double temp = result.hi; + result.hi += result.lo; + result.lo -= (result.hi - temp); + if( isnan( result.lo ) ) + result.lo = 0.0; + + return result; +#else + // take advantage of the known relative magnitudes of the partial products to avoid some sorting + // Combine 2**-78 and 2**-104 terms. Here we are a bit sloppy about canonicalizing the double_doubles + double_double t0 = { pA, pC }; + double_double t1 = { p9, pB }; + double_double t2 = { p6, p7 }; + double temp0, temp1, temp2; + + t0 = accum_d( t0, p5 ); // there is an extra 2**-78 term to deal with + + // Add in 2**-52 terms. Here we are a bit sloppy about canonicalizing the double_doubles + temp0 = t0.hi; temp1 = t1.hi; temp2 = t2.hi; + t0.hi += p3; t1.hi += p4; t2.hi += p8; + temp0 -= t0.hi-p3; temp1 -= t1.hi-p4; temp2 -= t2.hi - p8; + t0.lo += temp0; t1.lo += temp1; t2.lo += temp2; + + // Add in 2**-26 terms. Here we are a bit sloppy about canonicalizing the double_doubles + temp1 = t1.hi; temp2 = t2.hi; + t1.hi += p1; t2.hi += p2; + temp1 -= t1.hi-p1; temp2 -= t2.hi - p2; + t1.lo += temp1; t2.lo += temp2; + + // Combine accumulators to get the low bits of result + t1 = add_dd( t1, add_dd( t2, t0 ) ); + + // Add in MSB's, and round to precision + return accum_d( t1, p0 ); // canonicalizes +#endif + +} + + +long double reference_exp10l( long double z ) +{ + const double_double log2_10 = { HEX_DBL( +, 1, a934f0979a371, +, 1 ), HEX_DBL( +, 1, 7f2495fb7fa6d, -, 53 ) }; + double_double x; + int j; + + // Handle NaNs + if( isnan(z) ) + return z; + + // init x + x.hi = z; + x.lo = z - x.hi; + + + // 10**x = exp2( x * log2(10) ) + + x = mul_dd( x, log2_10); // x * log2(10) + + //Deal with overflow and underflow for exp2(x) stage next + if( x.hi >= 1025 ) + return INFINITY; + + if( x.hi < -1075-24 ) + return +0.0; + + // find nearest integer to x + int i = (int) rint(x.hi); + + // x now holds fractional part. The result would be then 2**i * exp2( x ) + x.hi -= i; + + // We could attempt to find a minimax polynomial for exp2(x) over the range x = [-0.5, 0.5]. + // However, this would converge very slowly near the extrema, where 0.5**n is not a lot different + // from 0.5**(n+1), thereby requiring something like a 20th order polynomial to get 53 + 24 bits + // of precision. Instead we further reduce the range to [-1/32, 1/32] by observing that + // + // 2**(a+b) = 2**a * 2**b + // + // We can thus build a table of 2**a values for a = n/16, n = [-8, 8], and reduce the range + // of x to [-1/32, 1/32] by subtracting away the nearest value of n/16 from x. + const double_double corrections[17] = + { + { HEX_DBL( +, 1, 6a09e667f3bcd, -, 1 ), HEX_DBL( -, 1, bdd3413b26456, -, 55 ) }, + { HEX_DBL( +, 1, 7a11473eb0187, -, 1 ), HEX_DBL( -, 1, 41577ee04992f, -, 56 ) }, + { HEX_DBL( +, 1, 8ace5422aa0db, -, 1 ), HEX_DBL( +, 1, 6e9f156864b27, -, 55 ) }, + { HEX_DBL( +, 1, 9c49182a3f09, -, 1 ), HEX_DBL( +, 1, c7c46b071f2be, -, 57 ) }, + { HEX_DBL( +, 1, ae89f995ad3ad, -, 1 ), HEX_DBL( +, 1, 7a1cd345dcc81, -, 55 ) }, + { HEX_DBL( +, 1, c199bdd85529c, -, 1 ), HEX_DBL( +, 1, 11065895048dd, -, 56 ) }, + { HEX_DBL( +, 1, d5818dcfba487, -, 1 ), HEX_DBL( +, 1, 2ed02d75b3707, -, 56 ) }, + { HEX_DBL( +, 1, ea4afa2a490da, -, 1 ), HEX_DBL( -, 1, e9c23179c2893, -, 55 ) }, + { HEX_DBL( +, 1, 0, +, 0 ), HEX_DBL( +, 0, 0, +, 0 ) }, + { HEX_DBL( +, 1, 0b5586cf9890f, +, 0 ), HEX_DBL( +, 1, 8a62e4adc610b, -, 54 ) }, + { HEX_DBL( +, 1, 172b83c7d517b, +, 0 ), HEX_DBL( -, 1, 19041b9d78a76, -, 55 ) }, + { HEX_DBL( +, 1, 2387a6e756238, +, 0 ), HEX_DBL( +, 1, 9b07eb6c70573, -, 54 ) }, + { HEX_DBL( +, 1, 306fe0a31b715, +, 0 ), HEX_DBL( +, 1, 6f46ad23182e4, -, 55 ) }, + { HEX_DBL( +, 1, 3dea64c123422, +, 0 ), HEX_DBL( +, 1, ada0911f09ebc, -, 55 ) }, + { HEX_DBL( +, 1, 4bfdad5362a27, +, 0 ), HEX_DBL( +, 1, d4397afec42e2, -, 56 ) }, + { HEX_DBL( +, 1, 5ab07dd485429, +, 0 ), HEX_DBL( +, 1, 6324c054647ad, -, 54 ) }, + { HEX_DBL( +, 1, 6a09e667f3bcd, +, 0 ), HEX_DBL( -, 1, bdd3413b26456, -, 54 ) } + + }; + int index = (int) rint( x.hi * 16.0 ); + x.hi -= (double) index * 0.0625; + + // canonicalize x + double temp = x.hi; + x.hi += x.lo; + x.lo -= x.hi - temp; + + // Minimax polynomial for (exp2(x)-1)/x, over the range [-1/32, 1/32]. Max Error: 2 * 0x1.e112p-87 + const double_double c[] = { + {HEX_DBL( +, 1, 62e42fefa39ef, -, 1 ), HEX_DBL( +, 1, abc9e3ac1d244, -, 56 )}, + {HEX_DBL( +, 1, ebfbdff82c58f, -, 3 ), HEX_DBL( -, 1, 5e4987a631846, -, 57 )}, + {HEX_DBL( +, 1, c6b08d704a0c, -, 5 ), HEX_DBL( -, 1, d323200a05713, -, 59 )}, + {HEX_DBL( +, 1, 3b2ab6fba4e7a, -, 7 ), HEX_DBL( +, 1, c5ee8f8b9f0c1, -, 63 )}, + {HEX_DBL( +, 1, 5d87fe78a672a, -, 10 ), HEX_DBL( +, 1, 884e5e5cc7ecc, -, 64 )}, + {HEX_DBL( +, 1, 430912f7e8373, -, 13 ), HEX_DBL( +, 1, 4f1b59514a326, -, 67 )}, + {HEX_DBL( +, 1, ffcbfc5985e71, -, 17 ), HEX_DBL( -, 1, db7d6a0953b78, -, 71 )}, + {HEX_DBL( +, 1, 62c150eb16465, -, 20 ), HEX_DBL( +, 1, e0767c2d7abf5, -, 80 )}, + {HEX_DBL( +, 1, b52502b5e953, -, 24 ), HEX_DBL( +, 1, 6797523f944bc, -, 78 )} + }; + size_t count = sizeof( c ) / sizeof( c[0] ); + + // Do polynomial + double_double r = c[count-1]; + for( j = (int) count-2; j >= 0; j-- ) + r = add_dd( c[j], mul_dd( r, x ) ); + + // unwind approximation + r = mul_dd( r, x ); // before: r =(exp2(x)-1)/x; after: r = exp2(x) - 1 + + // correct for [-0.5, 0.5] -> [-1/32, 1/32] reduction above + // exp2(x) = (r + 1) * correction = r * correction + correction + r = mul_dd( r, corrections[index+8] ); + r = add_dd( r, corrections[index+8] ); + +// Format result for output: + + // Get mantissa + long double m = ((long double) r.hi + (long double) r.lo ); + + // Handle a pesky overflow cases when long double = double + if( i > 512 ) + { + m *= HEX_DBL( +, 1, 0, +, 512 ); + i -= 512; + } + else if( i < -512 ) + { + m *= HEX_DBL( +, 1, 0, -, 512 ); + i += 512; + } + + return m * ldexpl( 1.0L, i ); +} + + +static double fallback_frexp( double x, int *iptr ) +{ + cl_ulong u, v; + double fu, fv; + + memcpy( &u, &x, sizeof(u)); + + cl_ulong exponent = u & 0x7ff0000000000000ULL; + cl_ulong mantissa = u & ~0x7ff0000000000000ULL; + + // add 1 to the exponent + exponent += 0x0010000000000000ULL; + + if( (cl_long) exponent < (cl_long) 0x0020000000000000LL ) + { // subnormal, NaN, Inf + mantissa |= 0x3fe0000000000000ULL; + + v = mantissa & 0xfff0000000000000ULL; + u = mantissa; + memcpy( &fv, &v, sizeof(v)); + memcpy( &fu, &u, sizeof(u)); + + fu -= fv; + + memcpy( &v, &fv, sizeof(v)); + memcpy( &u, &fu, sizeof(u)); + + exponent = u & 0x7ff0000000000000ULL; + mantissa = u & ~0x7ff0000000000000ULL; + + *iptr = (exponent >> 52) + (-1022 + 1 -1022); + u = mantissa | 0x3fe0000000000000ULL; + memcpy( &fu, &u, sizeof(u)); + return fu; + } + + *iptr = (exponent >> 52) - 1023; + u = mantissa | 0x3fe0000000000000ULL; + memcpy( &fu, &u, sizeof(u)); + return fu; +} + +// Assumes zeros, infinities and NaNs handed elsewhere +static inline int extract( double x, cl_ulong *mant ); +static inline int extract( double x, cl_ulong *mant ) +{ + static double (*frexpp)(double, int*) = NULL; + int e; + + // verify that frexp works properly + if( NULL == frexpp ) + { + if( 0.5 == frexp( HEX_DBL( +, 1, 0, -, 1030 ), &e ) && e == -1029 ) + frexpp = frexp; + else + frexpp = fallback_frexp; + } + + *mant = (cl_ulong) (HEX_DBL( +, 1, 0, +, 64 ) * fabs( frexpp( x, &e ))); + return e - 1; +} + +// Return 128-bit product of a*b as (hi << 64) + lo +static inline void mul128( cl_ulong a, cl_ulong b, cl_ulong *hi, cl_ulong *lo ); +static inline void mul128( cl_ulong a, cl_ulong b, cl_ulong *hi, cl_ulong *lo ) +{ + cl_ulong alo = a & 0xffffffffULL; + cl_ulong ahi = a >> 32; + cl_ulong blo = b & 0xffffffffULL; + cl_ulong bhi = b >> 32; + cl_ulong aloblo = alo * blo; + cl_ulong alobhi = alo * bhi; + cl_ulong ahiblo = ahi * blo; + cl_ulong ahibhi = ahi * bhi; + + alobhi += (aloblo >> 32) + (ahiblo & 0xffffffffULL); // cannot overflow: (2^32-1)^2 + 2 * (2^32-1) = (2^64 - 2^33 + 1) + (2^33 - 2) = 2^64 - 1 + *hi = ahibhi + (alobhi >> 32) + (ahiblo >> 32); // cannot overflow: (2^32-1)^2 + 2 * (2^32-1) = (2^64 - 2^33 + 1) + (2^33 - 2) = 2^64 - 1 + *lo = (aloblo & 0xffffffffULL) | (alobhi << 32); +} + +// Move the most significant non-zero bit to the MSB +// Note: not general. Only works if the most significant non-zero bit is at MSB-1 +static inline void renormalize( cl_ulong *hi, cl_ulong *lo, int *exponent ) +{ + if( 0 == (0x8000000000000000ULL & *hi )) + { + *hi <<= 1; + *hi |= *lo >> 63; + *lo <<= 1; + *exponent -= 1; + } +} + +static double round_to_nearest_even_double( cl_ulong hi, cl_ulong lo, int exponent ); +static double round_to_nearest_even_double( cl_ulong hi, cl_ulong lo, int exponent ) +{ + union{ cl_ulong u; cl_double d;} u; + + // edges + if( exponent > 1023 ) return INFINITY; + if( exponent == -1075 && (hi | (lo!=0)) > 0x8000000000000000ULL ) + return HEX_DBL( +, 1, 0, -, 1074 ); + if( exponent <= -1075 ) return 0.0; + + //Figure out which bits go where + int shift = 11; + if( exponent < -1022 ) + { + shift -= 1022 + exponent; // subnormal: shift is not 52 + exponent = -1023; // set exponent to 0 + } + else + hi &= 0x7fffffffffffffffULL; // normal: leading bit is implicit. Remove it. + + // Assemble the double (round toward zero) + u.u = (hi >> shift) | ((cl_ulong) (exponent + 1023) << 52); + + // put a representation of the residual bits into hi + hi <<= (64-shift); + hi |= lo >> shift; + lo <<= (64-shift ); + hi |= lo != 0; + + //round to nearest, ties to even + if( hi < 0x8000000000000000ULL ) return u.d; + if( hi == 0x8000000000000000ULL ) u.u += u.u & 1ULL; + else u.u++; + + return u.d; +} + +// Shift right. Bits lost on the right will be OR'd together and OR'd with the LSB +static inline void shift_right_sticky_128( cl_ulong *hi, cl_ulong *lo, int shift ); +static inline void shift_right_sticky_128( cl_ulong *hi, cl_ulong *lo, int shift ) +{ + cl_ulong sticky = 0; + cl_ulong h = *hi; + cl_ulong l = *lo; + + if( shift >= 64 ) + { + shift -= 64; + sticky = 0 != lo; + l = h; + h = 0; + if( shift >= 64 ) + { + sticky |= (0 != l); + l = 0; + } + else + { + sticky |= (0 != (l << (64-shift))); + l >>= shift; + } + } + else + { + sticky |= (0 != (l << (64-shift))); + l >>= shift; + l |= h << (64-shift); + h >>= shift; + } + + *lo = l | sticky; + *hi = h; +} + +// 128-bit add of ((*hi << 64) + *lo) + ((chi << 64) + clo) +// If the 129 bit result doesn't fit, bits lost off the right end will be OR'd with the LSB +static inline void add128( cl_ulong *hi, cl_ulong *lo, cl_ulong chi, cl_ulong clo, int *exp ); +static inline void add128( cl_ulong *hi, cl_ulong *lo, cl_ulong chi, cl_ulong clo, int *exponent ) +{ + cl_ulong carry, carry2; + // extended precision add + clo = add_carry(*lo, clo, &carry); + chi = add_carry(*hi, chi, &carry2); + chi = add_carry(chi, carry, &carry); + + //If we overflowed the 128 bit result + if( carry || carry2 ) + { + carry = clo & 1; // set aside low bit + clo >>= 1; // right shift low 1 + clo |= carry; // or back in the low bit, so we don't come to believe this is an exact half way case for rounding + clo |= chi << 63; // move lowest high bit into highest bit of lo + chi >>= 1; // right shift hi + chi |= 0x8000000000000000ULL; // move the carry bit into hi. + *exponent = *exponent + 1; + } + + *hi = chi; + *lo = clo; +} + +// 128-bit subtract of ((chi << 64) + clo) - ((*hi << 64) + *lo) +static inline void sub128( cl_ulong *chi, cl_ulong *clo, cl_ulong hi, cl_ulong lo, cl_ulong *signC, int *expC ); +static inline void sub128( cl_ulong *chi, cl_ulong *clo, cl_ulong hi, cl_ulong lo, cl_ulong *signC, int *expC ) +{ + cl_ulong rHi = *chi; + cl_ulong rLo = *clo; + cl_ulong carry, carry2; + + //extended precision subtract + rLo = sub_carry(rLo, lo, &carry); + rHi = sub_carry(rHi, hi, &carry2); + rHi = sub_carry(rHi, carry, &carry); + + // Check for sign flip + if( carry || carry2 ) + { + *signC ^= 0x8000000000000000ULL; + + //negate rLo, rHi: -x = (x ^ -1) + 1 + rLo ^= -1ULL; + rHi ^= -1ULL; + rLo++; + rHi += 0 == rLo; + } + + // normalize -- move the most significant non-zero bit to the MSB, and adjust exponent accordingly + if( rHi == 0 ) + { + rHi = rLo; + *expC = *expC - 64; + rLo = 0; + } + + if( rHi ) + { + int shift = 32; + cl_ulong test = 1ULL << 32; + while( 0 == (rHi & 0x8000000000000000ULL)) + { + if( rHi < test ) + { + rHi <<= shift; + rHi |= rLo >> (64-shift); + rLo <<= shift; + *expC = *expC - shift; + } + shift >>= 1; + test <<= shift; + } + } + else + { + //zero + *expC = INT_MIN; + *signC = 0; + } + + + *chi = rHi; + *clo = rLo; +} + +long double reference_fmal( long double x, long double y, long double z) +{ + static const cl_ulong kMSB = 0x8000000000000000ULL; + + // cast values back to double. This is an exact function, so + double a = x; + double b = y; + double c = z; + + // Make bits accessible + union{ cl_ulong u; cl_double d; } ua; ua.d = a; + union{ cl_ulong u; cl_double d; } ub; ub.d = b; + union{ cl_ulong u; cl_double d; } uc; uc.d = c; + + // deal with Nans, infinities and zeros + if( isnan( a ) || isnan( b ) || isnan(c) || + isinf( a ) || isinf( b ) || isinf(c) || + 0 == ( ua.u & ~kMSB) || // a == 0, defeat host FTZ behavior + 0 == ( ub.u & ~kMSB) || // b == 0, defeat host FTZ behavior + 0 == ( uc.u & ~kMSB) ) // c == 0, defeat host FTZ behavior + { + if( isinf( c ) && !isinf(a) && !isinf(b) ) + return (c + a) + b; + + a = (double) reference_multiplyl( a, b ); // some risk that the compiler will insert a non-compliant fma here on some platforms. + return reference_addl(a, c); // We use STDC FP_CONTRACT OFF above to attempt to defeat that. + } + + // extract exponent and mantissa + // exponent is a standard unbiased signed integer + // mantissa is a cl_uint, with leading non-zero bit positioned at the MSB + cl_ulong mantA, mantB, mantC; + int expA = extract( a, &mantA ); + int expB = extract( b, &mantB ); + int expC = extract( c, &mantC ); + cl_ulong signC = uc.u & kMSB; // We'll need the sign bit of C later to decide if we are adding or subtracting + +// exact product of A and B + int exponent = expA + expB; + cl_ulong sign = (ua.u ^ ub.u) & kMSB; + cl_ulong hi, lo; + mul128( mantA, mantB, &hi, &lo ); + + // renormalize + if( 0 == (kMSB & hi) ) + { + hi <<= 1; + hi |= lo >> 63; + lo <<= 1; + } + else + exponent++; // 2**63 * 2**63 gives 2**126. If the MSB was set, then our exponent increased. + +//infinite precision add + cl_ulong chi = mantC; + cl_ulong clo = 0; + + if( exponent >= expC ) + { + // Normalize C relative to the product + if( exponent > expC ) + shift_right_sticky_128( &chi, &clo, exponent - expC ); + + // Add + if( sign ^ signC ) + sub128( &hi, &lo, chi, clo, &sign, &exponent ); + else + add128( &hi, &lo, chi, clo, &exponent ); + } + else + { + // Shift the product relative to C so that their exponents match + shift_right_sticky_128( &hi, &lo, expC - exponent ); + + // add + if( sign ^ signC ) + sub128( &chi, &clo, hi, lo, &signC, &expC ); + else + add128( &chi, &clo, hi, lo, &expC ); + + hi = chi; + lo = clo; + exponent = expC; + sign = signC; + } + + // round + ua.d = round_to_nearest_even_double(hi, lo, exponent); + + // Set the sign + ua.u |= sign; + + return ua.d; +} + + + + +long double reference_madl( long double a, long double b, long double c) { return a * b + c; } + +//long double my_nextafterl(long double x, long double y){ return (long double) nextafter( (double) x, (double) y ); } + +long double reference_recipl( long double x){ return 1.0L / x; } + +long double reference_rootnl( long double x, int i) +{ + double hi, lo; + long double l; + //rootn ( x, 0 ) returns a NaN. + if( 0 == i ) + return cl_make_nan(); + + //rootn ( x, n ) returns a NaN for x < 0 and n is even. + if( x < 0.0L && 0 == (i&1) ) + return cl_make_nan(); + + if( isinf(x) ) + { + if( i < 0 ) + return reference_copysignl(0.0L, x); + + return x; + } + + if( x == 0.0 ) + { + switch( i & 0x80000001 ) + { + //rootn ( +-0, n ) is +0 for even n > 0. + case 0: + return 0.0L; + + //rootn ( +-0, n ) is +-0 for odd n > 0. + case 1: + return x; + + //rootn ( +-0, n ) is +inf for even n < 0. + case 0x80000000: + return INFINITY; + + //rootn ( +-0, n ) is +-inf for odd n < 0. + case 0x80000001: + return copysign(INFINITY, x); + } + } + + if( i == 1 ) + return x; + + if( i == -1 ) + return 1.0 / x; + + long double sign = x; + x = reference_fabsl(x); + double iHi, iLo; + DivideDD(&iHi, &iLo, 1.0, i); + x = reference_powl(x, iHi) * reference_powl(x, iLo); + + return reference_copysignl( x, sign ); + +} + +long double reference_rsqrtl( long double x){ return 1.0L / sqrtl(x); } +//long double reference_sincosl( long double x, long double *c ){ *c = reference_cosl(x); return reference_sinl(x); } +long double reference_sinpil( long double x) +{ + double r = reduce1l(x); + + // reduce to [-0.5, 0.5] + if( r < -0.5L ) + r = -1.0L - r; + else if ( r > 0.5L ) + r = 1.0L - r; + + // sinPi zeros have the same sign as x + if( r == 0.0L ) + return reference_copysignl(0.0L, x); + + return reference_sinl( r * M_PIL ); +} + +long double reference_tanpil( long double x) +{ + // set aside the sign (allows us to preserve sign of -0) + long double sign = reference_copysignl( 1.0L, x); + long double z = reference_fabsl(x); + + // if big and even -- caution: only works if x only has single precision + if( z >= HEX_LDBL( +, 1, 0, +, 53 ) ) + { + if( z == INFINITY ) + return x - x; // nan + + return reference_copysignl( 0.0L, x); // tanpi ( n ) is copysign( 0.0, n) for even integers n. + } + + // reduce to the range [ -0.5, 0.5 ] + long double nearest = reference_rintl( z ); // round to nearest even places n + 0.5 values in the right place for us + int64_t i = (int64_t) nearest; // test above against 0x1.0p53 avoids overflow here + z -= nearest; + + //correction for odd integer x for the right sign of zero + if( (i&1) && z == 0.0L ) + sign = -sign; + + // track changes to the sign + sign *= reference_copysignl(1.0L, z); // really should just be an xor + z = reference_fabsl(z); // remove the sign again + + // reduce once more + // If we don't do this, rounding error in z * M_PI will cause us not to return infinities properly + if( z > 0.25L ) + { + z = 0.5L - z; + return sign / reference_tanl( z * M_PIL ); // use system tan to get the right result + } + + // + return sign * reference_tanl( z * M_PIL ); // use system tan to get the right result +} + +long double reference_pownl( long double x, int i ){ return reference_powl( x, (long double) i ); } + +long double reference_powrl( long double x, long double y ) +{ + //powr ( x, y ) returns NaN for x < 0. + if( x < 0.0L ) + return cl_make_nan(); + + //powr ( x, NaN ) returns the NaN for x >= 0. + //powr ( NaN, y ) returns the NaN. + if( isnan(x) || isnan(y) ) + return x + y; // Note: behavior different here than for pow(1,NaN), pow(NaN, 0) + + if( x == 1.0L ) + { + //powr ( +1, +-inf ) returns NaN. + if( reference_fabsl(y) == INFINITY ) + return cl_make_nan(); + + //powr ( +1, y ) is 1 for finite y. (NaN handled above) + return 1.0L; + } + + if( y == 0.0L ) + { + //powr ( +inf, +-0 ) returns NaN. + //powr ( +-0, +-0 ) returns NaN. + if( x == 0.0L || x == INFINITY ) + return cl_make_nan(); + + //powr ( x, +-0 ) is 1 for finite x > 0. (x <= 0, NaN, INF already handled above) + return 1.0L; + } + + if( x == 0.0L ) + { + //powr ( +-0, -inf) is +inf. + //powr ( +-0, y ) is +inf for finite y < 0. + if( y < 0.0L ) + return INFINITY; + + //powr ( +-0, y ) is +0 for y > 0. (NaN, y==0 handled above) + return 0.0L; + } + + return reference_powl( x, y ); +} + +//long double my_fdiml( long double x, long double y){ return fdim( (double) x, (double) y ); } +long double reference_addl( long double x, long double y) +{ + volatile double a = (double) x; + volatile double b = (double) y; + +#if defined( __SSE2__ ) + // defeat x87 + __m128d va = _mm_set_sd( (double) a ); + __m128d vb = _mm_set_sd( (double) b ); + va = _mm_add_sd( va, vb ); + _mm_store_sd( (double*) &a, va ); +#else + a += b; +#endif + return (long double) a; +} + +long double reference_subtractl( long double x, long double y) +{ + volatile double a = (double) x; + volatile double b = (double) y; + +#if defined( __SSE2__ ) + // defeat x87 + __m128d va = _mm_set_sd( (double) a ); + __m128d vb = _mm_set_sd( (double) b ); + va = _mm_sub_sd( va, vb ); + _mm_store_sd( (double*) &a, va ); +#else + a -= b; +#endif + return (long double) a; +} + +long double reference_multiplyl( long double x, long double y) +{ + volatile double a = (double) x; + volatile double b = (double) y; + +#if defined( __SSE2__ ) + // defeat x87 + __m128d va = _mm_set_sd( (double) a ); + __m128d vb = _mm_set_sd( (double) b ); + va = _mm_mul_sd( va, vb ); + _mm_store_sd( (double*) &a, va ); +#else + a *= b; +#endif + return (long double) a; +} + +/*long double my_remquol( long double x, long double y, int *iptr ) +{ + if( isnan(x) || isnan(y) || + fabs(x) == INFINITY || + y == 0.0 ) + { + *iptr = 0; + return NAN; + } + + return remquo( (double) x, (double) y, iptr ); +}*/ +long double reference_lgamma_rl( long double x, int *signp ) +{ +// long double lgamma_val = (long double)reference_lgamma( (double)x ); +// *signp = signgam; + *signp = 0; + return x; +} + + +int reference_isequall( long double x, long double y){ return x == y; } +int reference_isfinitel( long double x){ return 0 != isfinite(x); } +int reference_isgreaterl( long double x, long double y){ return x > y; } +int reference_isgreaterequall( long double x, long double y){ return x >= y; } +int reference_isinfl( long double x){ return 0 != isinf(x); } +int reference_islessl( long double x, long double y){ return x < y; } +int reference_islessequall( long double x, long double y){ return x <= y; } +int reference_islessgreaterl( long double x, long double y){ return 0 != islessgreater( x, y ); } +int reference_isnanl( long double x){ return 0 != isnan( x ); } +int reference_isnormall( long double x){ return 0 != isnormal( (double) x ); } +int reference_isnotequall( long double x, long double y){ return x != y; } +int reference_isorderedl( long double x, long double y){ return x == x && y == y; } +int reference_isunorderedl( long double x, long double y){ return isnan(x) || isnan( y ); } +int reference_signbitl( long double x){ return 0 != signbit( x ); } + +long double reference_copysignl( long double x, long double y); +long double reference_roundl( long double x ); +long double reference_cbrtl(long double x); + +long double reference_copysignl( long double x, long double y ) +{ + // We hope that the long double to double conversion proceeds with sign fidelity, + // even for zeros and NaNs + union{ double d; cl_ulong u;}u; u.d = (double) y; + + x = reference_fabsl(x); + if( u.u >> 63 ) + x = -x; + + return x; +} + +long double reference_roundl( long double x ) +{ + // Since we are just using this to verify double precision, we can + // use the double precision copysign here + +#if defined(__MINGW32__) && defined(__x86_64__) + long double absx = reference_fabsl(x); + if (absx < 0.5L) + return reference_copysignl(0.0L, x); +#endif + return round( (double) x ); +} + +long double reference_truncl( long double x ) +{ + // Since we are just using this to verify double precision, we can + // use the double precision copysign here + return trunc( (double) x ); +} + +static long double reference_scalblnl(long double x, long n); + +long double reference_cbrtl(long double x) +{ + double yhi = HEX_DBL( +, 1, 5555555555555, -, 2 ); + double ylo = HEX_DBL( +, 1, 558, -, 56 ); + + double fabsx = reference_fabs( x ); + + if( isnan(x) || fabsx == 1.0 || fabsx == 0.0 || isinf(x) ) + return x; + + double iy = 0.0; + double log2x_hi, log2x_lo; + + // extended precision log .... accurate to at least 64-bits + couple of guard bits + __log2_ep(&log2x_hi, &log2x_lo, fabsx); + + double ylog2x_hi, ylog2x_lo; + + double y_hi = yhi; + double y_lo = ylo; + + // compute product of y*log2(x) + MulDD(&ylog2x_hi, &ylog2x_lo, log2x_hi, log2x_lo, y_hi, y_lo); + + long double powxy; + if(isinf(ylog2x_hi) || (reference_fabs(ylog2x_hi) > 2200)) { + powxy = reference_signbit(ylog2x_hi) ? HEX_DBL( +, 0, 0, +, 0 ) : INFINITY; + } else { + // separate integer + fractional part + long int m = lrint(ylog2x_hi); + AddDD(&ylog2x_hi, &ylog2x_lo, ylog2x_hi, ylog2x_lo, -m, 0.0); + + // revert to long double arithemtic + long double ylog2x = (long double) ylog2x_hi + (long double) ylog2x_lo; + powxy = reference_exp2l( ylog2x ); + powxy = reference_scalblnl(powxy, m); + } + + return reference_copysignl( powxy, x ); +} + +/* +long double scalbnl( long double x, int i ) +{ + //suitable for checking double precision scalbn only + + if( i > 3000 ) + return copysignl( INFINITY, x); + if( i < -3000 ) + return copysignl( 0.0L, x); + + if( i > 0 ) + { + while( i >= 1000 ) + { + x *= HEX_LDBL( +, 1, 0, +, 1000 ); + i -= 1000; + } + + union{ cl_ulong u; double d;}u; + u.u = (cl_ulong)( i + 1023 ) << 52; + x *= (long double) u.d; + } + else if( i < 0 ) + { + while( i <= -1000 ) + { + x *= HEX_LDBL( +, 1, 0, -, 1000 ); + i += 1000; + } + + union{ cl_ulong u; double d;}u; + u.u = (cl_ulong)( i + 1023 ) << 52; + x *= (long double) u.d; + } + + return x; +} +*/ + +long double reference_rintl( long double x ) +{ +#if defined(__PPC__) + // On PPC, long doubles are maintained as 2 doubles. Therefore, the combined + // mantissa can represent more than LDBL_MANT_DIG binary digits. + x = rintl(x); +#else + static long double magic[2] = { 0.0L, 0.0L}; + + if( 0.0L == magic[0] ) + { + magic[0] = scalbnl(0.5L, LDBL_MANT_DIG); + magic[1] = scalbnl(-0.5L, LDBL_MANT_DIG); + } + + if( reference_fabsl(x) < magic[0] && x != 0.0L ) + { + long double m = magic[ x < 0 ]; + x += m; + x -= m; + } +#endif // __PPC__ + return x; +} + +// extended precision sqrt using newton iteration on 1/sqrt(x). +// Final result is computed as x * 1/sqrt(x) +static void __sqrt_ep(double *rhi, double *rlo, double xhi, double xlo) +{ + // approximate reciprocal sqrt + double thi = 1.0 / sqrt( xhi ); + double tlo = 0.0; + + // One newton iteration in double-double + double yhi, ylo; + MulDD(&yhi, &ylo, thi, tlo, thi, tlo); + MulDD(&yhi, &ylo, yhi, ylo, xhi, xlo); + AddDD(&yhi, &ylo, -yhi, -ylo, 3.0, 0.0); + MulDD(&yhi, &ylo, yhi, ylo, thi, tlo); + MulDD(&yhi, &ylo, yhi, ylo, 0.5, 0.0); + + MulDD(rhi, rlo, yhi, ylo, xhi, xlo); +} + +long double reference_acoshl( long double x ) +{ +/* + * ==================================================== + * This function derived from fdlibm http://www.netlib.org + * It is Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + */ + if( isnan(x) || isinf(x)) + return x + fabsl(x); + + if( x < 1.0L ) + return cl_make_nan(); + + if( x == 1.0L ) + return 0.0L; + + if( x > HEX_LDBL( +, 1, 0, +, 60 ) ) + return reference_logl(x) + 0.693147180559945309417232121458176568L; + + if( x > 2.0L ) + return reference_logl(2.0L * x - 1.0L / (x + sqrtl(x*x - 1.0L))); + + double hi, lo; + MulD(&hi, &lo, x, x); + AddDD(&hi, &lo, hi, lo, -1.0, 0.0); + __sqrt_ep(&hi, &lo, hi, lo); + AddDD(&hi, &lo, hi, lo, x, 0.0); + double correction = lo / hi; + __log2_ep(&hi, &lo, hi); + double log2Hi = HEX_DBL( +, 1, 62e42fefa39ef, -, 1 ); + double log2Lo = HEX_DBL( +, 1, abc9e3b39803f, -, 56 ); + MulDD(&hi, &lo, hi, lo, log2Hi, log2Lo); + AddDD(&hi, &lo, hi, lo, correction, 0.0); + + return hi + lo; +} + +long double reference_asinhl( long double x ) +{ + long double cutoff = 0.0L; + const long double ln2 = HEX_LDBL( +, b, 17217f7d1cf79ab, -, 4 ); + + if( cutoff == 0.0L ) + cutoff = reference_ldexpl(1.0L, -LDBL_MANT_DIG); + + if( isnan(x) || isinf(x) ) + return x + x; + + long double absx = reference_fabsl(x); + if( absx < cutoff ) + return x; + + long double sign = reference_copysignl(1.0L, x); + + if( absx <= 4.0/3.0 ) { + return sign * reference_log1pl( absx + x*x / (1.0 + sqrtl(1.0 + x*x))); + } + else if( absx <= HEX_LDBL( +, 1, 0, +, 27 ) ) { + return sign * reference_logl( 2.0L * absx + 1.0L / (sqrtl( x * x + 1.0 ) + absx)); + } + else { + return sign * ( reference_logl( absx ) + ln2 ); + } +} + +long double reference_atanhl( long double x ) +{ +/* + * ==================================================== + * This function is from fdlibm: http://www.netlib.org + * It is Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + if( isnan(x) ) + return x + x; + + long double signed_half = reference_copysignl( 0.5L, x ); + x = reference_fabsl(x); + if( x > 1.0L ) + return cl_make_nan(); + + if( x < 0.5L ) + return signed_half * reference_log1pl( 2.0L * ( x + x*x / (1-x) ) ); + + return signed_half * reference_log1pl(2.0L * x / (1-x)); +} + +long double reference_exp2l( long double z) +{ + double_double x; + int j; + + // Handle NaNs + if( isnan(z) ) + return z; + + // init x + x.hi = z; + x.lo = z - x.hi; + + //Deal with overflow and underflow for exp2(x) stage next + if( x.hi >= 1025 ) + return INFINITY; + + if( x.hi < -1075-24 ) + return +0.0; + + // find nearest integer to x + int i = (int) rint(x.hi); + + // x now holds fractional part. The result would be then 2**i * exp2( x ) + x.hi -= i; + + // We could attempt to find a minimax polynomial for exp2(x) over the range x = [-0.5, 0.5]. + // However, this would converge very slowly near the extrema, where 0.5**n is not a lot different + // from 0.5**(n+1), thereby requiring something like a 20th order polynomial to get 53 + 24 bits + // of precision. Instead we further reduce the range to [-1/32, 1/32] by observing that + // + // 2**(a+b) = 2**a * 2**b + // + // We can thus build a table of 2**a values for a = n/16, n = [-8, 8], and reduce the range + // of x to [-1/32, 1/32] by subtracting away the nearest value of n/16 from x. + const double_double corrections[17] = + { + { HEX_DBL( +, 1, 6a09e667f3bcd, -, 1 ), HEX_DBL( -, 1, bdd3413b26456, -, 55 ) }, + { HEX_DBL( +, 1, 7a11473eb0187, -, 1 ), HEX_DBL( -, 1, 41577ee04992f, -, 56 ) }, + { HEX_DBL( +, 1, 8ace5422aa0db, -, 1 ), HEX_DBL( +, 1, 6e9f156864b27, -, 55 ) }, + { HEX_DBL( +, 1, 9c49182a3f09, -, 1 ), HEX_DBL( +, 1, c7c46b071f2be, -, 57 ) }, + { HEX_DBL( +, 1, ae89f995ad3ad, -, 1 ), HEX_DBL( +, 1, 7a1cd345dcc81, -, 55 ) }, + { HEX_DBL( +, 1, c199bdd85529c, -, 1 ), HEX_DBL( +, 1, 11065895048dd, -, 56 ) }, + { HEX_DBL( +, 1, d5818dcfba487, -, 1 ), HEX_DBL( +, 1, 2ed02d75b3707, -, 56 ) }, + { HEX_DBL( +, 1, ea4afa2a490da, -, 1 ), HEX_DBL( -, 1, e9c23179c2893, -, 55 ) }, + { HEX_DBL( +, 1, 0, +, 0 ), HEX_DBL( +, 0, 0, +, 0 ) }, + { HEX_DBL( +, 1, 0b5586cf9890f, +, 0 ), HEX_DBL( +, 1, 8a62e4adc610b, -, 54 ) }, + { HEX_DBL( +, 1, 172b83c7d517b, +, 0 ), HEX_DBL( -, 1, 19041b9d78a76, -, 55 ) }, + { HEX_DBL( +, 1, 2387a6e756238, +, 0 ), HEX_DBL( +, 1, 9b07eb6c70573, -, 54 ) }, + { HEX_DBL( +, 1, 306fe0a31b715, +, 0 ), HEX_DBL( +, 1, 6f46ad23182e4, -, 55 ) }, + { HEX_DBL( +, 1, 3dea64c123422, +, 0 ), HEX_DBL( +, 1, ada0911f09ebc, -, 55 ) }, + { HEX_DBL( +, 1, 4bfdad5362a27, +, 0 ), HEX_DBL( +, 1, d4397afec42e2, -, 56 ) }, + { HEX_DBL( +, 1, 5ab07dd485429, +, 0 ), HEX_DBL( +, 1, 6324c054647ad, -, 54 ) }, + { HEX_DBL( +, 1, 6a09e667f3bcd, +, 0 ), HEX_DBL( -, 1, bdd3413b26456, -, 54 ) } + }; + int index = (int) rint( x.hi * 16.0 ); + x.hi -= (double) index * 0.0625; + + // canonicalize x + double temp = x.hi; + x.hi += x.lo; + x.lo -= x.hi - temp; + + // Minimax polynomial for (exp2(x)-1)/x, over the range [-1/32, 1/32]. Max Error: 2 * 0x1.e112p-87 + const double_double c[] = { + {HEX_DBL( +, 1, 62e42fefa39ef, -, 1 ), HEX_DBL( +, 1, abc9e3ac1d244, -, 56 )}, + {HEX_DBL( +, 1, ebfbdff82c58f, -, 3 ), HEX_DBL( -, 1, 5e4987a631846, -, 57 )}, + {HEX_DBL( +, 1, c6b08d704a0c, -, 5 ), HEX_DBL( -, 1, d323200a05713, -, 59 )}, + {HEX_DBL( +, 1, 3b2ab6fba4e7a, -, 7 ), HEX_DBL( +, 1, c5ee8f8b9f0c1, -, 63 )}, + {HEX_DBL( +, 1, 5d87fe78a672a, -, 10 ), HEX_DBL( +, 1, 884e5e5cc7ecc, -, 64 )}, + {HEX_DBL( +, 1, 430912f7e8373, -, 13 ), HEX_DBL( +, 1, 4f1b59514a326, -, 67 )}, + {HEX_DBL( +, 1, ffcbfc5985e71, -, 17 ), HEX_DBL( -, 1, db7d6a0953b78, -, 71 )}, + {HEX_DBL( +, 1, 62c150eb16465, -, 20 ), HEX_DBL( +, 1, e0767c2d7abf5, -, 80 )}, + {HEX_DBL( +, 1, b52502b5e953, -, 24 ), HEX_DBL( +, 1, 6797523f944bc, -, 78 )} + }; + size_t count = sizeof( c ) / sizeof( c[0] ); + + // Do polynomial + double_double r = c[count-1]; + for( j = (int) count-2; j >= 0; j-- ) + r = add_dd( c[j], mul_dd( r, x ) ); + + // unwind approximation + r = mul_dd( r, x ); // before: r =(exp2(x)-1)/x; after: r = exp2(x) - 1 + + // correct for [-0.5, 0.5] -> [-1/32, 1/32] reduction above + // exp2(x) = (r + 1) * correction = r * correction + correction + r = mul_dd( r, corrections[index+8] ); + r = add_dd( r, corrections[index+8] ); + +// Format result for output: + + // Get mantissa + long double m = ((long double) r.hi + (long double) r.lo ); + + // Handle a pesky overflow cases when long double = double + if( i > 512 ) + { + m *= HEX_DBL( +, 1, 0, +, 512 ); + i -= 512; + } + else if( i < -512 ) + { + m *= HEX_DBL( +, 1, 0, -, 512 ); + i += 512; + } + + return m * ldexpl( 1.0L, i ); +} + +long double reference_expm1l( long double x) +{ +#if defined( _MSC_VER ) && ! defined( __INTEL_COMPILER ) + //unimplemented + return x; +#else + union { double f; cl_ulong u;} u; + u.f = (double) x; + + if (reference_isnanl(x)) + return x; + + if ( x > 710 ) + return INFINITY; + + long double y = expm1l(x); + + // Range of expm1l is -1.0L to +inf. Negative inf + // on a few Linux platforms is clearly the wrong sign. + if (reference_isinfl(y)) + y = INFINITY; + + return y; +#endif +} + +long double reference_fmaxl( long double x, long double y ) +{ + if( isnan(y) ) + return x; + + return x >= y ? x : y; +} + +long double reference_fminl( long double x, long double y ) +{ + if( isnan(y) ) + return x; + + return x <= y ? x : y; +} + +long double reference_hypotl( long double x, long double y ) +{ + static const double tobig = HEX_DBL( +, 1, 0, +, 511 ); + static const double big = HEX_DBL( +, 1, 0, +, 513 ); + static const double rbig = HEX_DBL( +, 1, 0, -, 513 ); + static const double tosmall = HEX_DBL( +, 1, 0, -, 511 ); + static const double smalll = HEX_DBL( +, 1, 0, -, 607 ); + static const double rsmall = HEX_DBL( +, 1, 0, +, 607 ); + + long double max, min; + + if( isinf(x) || isinf(y) ) + return INFINITY; + + if( isnan(x) || isnan(y) ) + return x + y; + + x = reference_fabsl(x); + y = reference_fabsl(y); + + max = reference_fmaxl( x, y ); + min = reference_fminl( x, y ); + + if( max > tobig ) + { + max *= rbig; + min *= rbig; + return big * sqrtl( max * max + min * min ); + } + + if( max < tosmall ) + { + max *= rsmall; + min *= rsmall; + return smalll * sqrtl( max * max + min * min ); + } + return sqrtl( x * x + y * y ); +} + +//long double reference_log2l( long double x ) +//{ +// return log( x ) * 1.44269504088896340735992468100189214L; +//} + +long double reference_log2l( long double x ) +{ + if( isnan(x) || x < 0.0 || x == -INFINITY) + return NAN; + + if( x == 0.0f) + return -INFINITY; + + if( x == INFINITY ) + return INFINITY; + + double hi, lo; + __log2_ep( &hi, &lo, x); + + return (long double) hi + (long double) lo; +} + +long double reference_log1pl( long double x) +{ +#if defined( _MSC_VER ) && ! defined( __INTEL_COMPILER ) + //unimplemented + return x; +#elif defined(__PPC__) + // log1pl on PPC inadvertantly returns NaN for very large values. Work + // around this limitation by returning logl for large values. + return ((x > (long double)(0x1.0p+1022)) ? logl(x) : log1pl(x)); +#else + return log1pl(x); +#endif +} + +long double reference_logbl( long double x ) +{ + // Since we are just using this to verify double precision, we can + // use the double precision copysign here + union { double f; cl_ulong u;} u; + u.f = (double) x; + + cl_int exponent = (cl_uint)(u.u >> 52) & 0x7ff; + if( exponent == 0x7ff ) + return x * x; + + if( exponent == 0 ) + { // deal with denormals + u.f = x * HEX_DBL( +, 1, 0, +, 64 ); + exponent = (cl_int)(u.u >> 52) & 0x7ff; + if( exponent == 0 ) + return -INFINITY; + + return exponent - (1023 + 64); + } + + return exponent - 1023; +} + +long double reference_maxmagl( long double x, long double y ) +{ + long double fabsx = fabsl(x); + long double fabsy = fabsl(y); + + if( fabsx < fabsy ) + return y; + + if( fabsy < fabsx ) + return x; + + return reference_fmaxl(x, y); +} + +long double reference_minmagl( long double x, long double y ) +{ + long double fabsx = fabsl(x); + long double fabsy = fabsl(y); + + if( fabsx > fabsy ) + return y; + + if( fabsy > fabsx ) + return x; + + return reference_fminl(x, y); +} + +long double reference_nanl( cl_ulong x ) +{ + union{ cl_ulong u; cl_double f; }u; + u.u = x | 0x7ff8000000000000ULL; + return (long double) u.f; +} + + +long double reference_reciprocall( long double x ) +{ + return 1.0L / x; +} + +long double reference_remainderl( long double x, long double y ); +long double reference_remainderl( long double x, long double y ) +{ + int i; + return reference_remquol( x, y, &i ); +} + +long double reference_lgammal( long double x); +long double reference_lgammal( long double x) +{ + // lgamma is currently not tested + return reference_lgamma( x ); +} + +static uint32_t two_over_pi[] = { 0x0, 0x28be60db, 0x24e44152, 0x27f09d5f, 0x11f534dd, 0x3036d8a5, 0x1993c439, 0x107f945, 0x23abdebb, 0x31586dc9, +0x6e3a424, 0x374b8019, 0x92eea09, 0x3464873f, 0x21deb1cb, 0x4a69cfb, 0x288235f5, 0xbaed121, 0xe99c702, 0x1ad17df9, +0x13991d6, 0xe60d4ce, 0x1f49c845, 0x3e2ef7e4, 0x283b1ff8, 0x25fff781, 0x1980fef2, 0x3c462d68, 0xa6d1f6d, 0xd9fb3c9, +0x3cb09b74, 0x3d18fd9a, 0x1e5fea2d, 0x1d49eeb1, 0x3ebe5f17, 0x2cf41ce7, 0x378a5292, 0x3a9afed7, 0x3b11f8d5, 0x3421580c, +0x3046fc7b, 0x1aeafc33, 0x3bc209af, 0x10d876a7, 0x2391615e, 0x3986c219, 0x199855f1, 0x1281a102, 0xdffd880, 0x135cc9cc, +0x10606155 +}; + +static uint32_t pi_over_two[] = { 0x1, 0x2487ed51, 0x42d1846, 0x26263314, 0x1701b839, 0x28948127 }; + +typedef union + { + uint64_t u; + double d; + }d_ui64_t; + +// radix or base of representation +#define RADIX (30) +#define DIGITS 6 + +d_ui64_t two_pow_pradix = { (uint64_t) (1023 + RADIX) << 52 }; +d_ui64_t two_pow_mradix = { (uint64_t) (1023 - RADIX) << 52 }; +d_ui64_t two_pow_two_mradix = { (uint64_t) (1023-2*RADIX) << 52 }; + +#define tp_pradix two_pow_pradix.d +#define tp_mradix two_pow_mradix.d + +// extended fixed point representation of double precision +// floating point number. +// x = sign * [ sum_{i = 0 to 2} ( X[i] * 2^(index - i)*RADIX ) ] +typedef struct + { + uint32_t X[3]; // three 32 bit integers are sufficient to represnt double in base_30 + int index; // exponent bias + int sign; // sign of double + }eprep_t; + +static eprep_t double_to_eprep(double x); + +static eprep_t double_to_eprep(double x) +{ + eprep_t result; + + result.sign = (signbit( x ) == 0) ? 1 : -1; + x = fabs( x ); + + int index = 0; + while( x > tp_pradix ) { + index++; + x *= tp_mradix; + } + while( x < 1 ) { + index--; + x *= tp_pradix; + } + + result.index = index; + int i = 0; + result.X[0] = result.X[1] = result.X[2] = 0; + while( x != 0.0 ) { + result.X[i] = (uint32_t) x; + x = (x - (double) result.X[i]) * tp_pradix; + i++; + } + return result; +} + +/* + double eprep_to_double( uint32_t *R, int digits, int index, int sgn ) + { + d_ui64_t nb, rndcorr; + uint64_t lowpart, roundbits, t1; + int expo, expofinal, shift; + double res; + + nb.d = (double) R[0]; + + t1 = R[1]; + lowpart = (t1 << RADIX) + R[2]; + expo = ((nb.u & 0x7ff0000000000000ULL) >> 52) - 1023; + + expofinal = expo + RADIX*index; + + if (expofinal > 1023) { + d_ui64_t inf = { 0x7ff0000000000000ULL }; + res = inf.d; + } + + else if (expofinal >= -1022){ + shift = expo + 2*RADIX - 53; + roundbits = lowpart << (64-shift); + lowpart = lowpart >> shift; + if (lowpart & 0x0000000000000001ULL) { + if(roundbits == 0) { + int i; + for (i=3; i < digits; i++) + roundbits = roundbits | R[i]; + } + if(roundbits == 0) { + if (lowpart & 0x0000000000000002ULL) + rndcorr.u = (uint64_t) (expo - 52 + 1023) << 52; + else + rndcorr.d = 0.0; + } + else + rndcorr.u = (uint64_t) (expo - 52 + 1023) << 52; + } + else{ + rndcorr.d = 0.0; + } + + lowpart = lowpart >> 1; + nb.u = nb.u | lowpart; + res = nb.d + rndcorr.d; + + if(index*RADIX + 1023 > 0) { + nb.u = 0; + nb.u = (uint64_t) (index*RADIX + 1023) << 52; + res *= nb.d; + } + else { + nb.u = 0; + nb.u = (uint64_t) (index*RADIX + 1023 + 2*RADIX) << 52; + res *= two_pow_two_mradix.d; + res *= nb.d; + } + } + else { + if (expofinal < -1022 - 53 ) { + res = 0.0; + } + else { + lowpart = lowpart >> (expo + (2*RADIX) - 52); + nb.u = nb.u | lowpart; + nb.u = (nb.u & 0x000FFFFFFFFFFFFFULL) | 0x0010000000000000ULL; + nb.u = nb.u >> (-1023 - expofinal); + if(nb.u & 0x0000000000000001ULL) + rndcorr.u = 1; + else + rndcorr.d = 0.0; + res = 0.5*(nb.d + rndcorr.d); + } + } + + return sgn*res; + } + */ +static double eprep_to_double( eprep_t epx ); + +static double eprep_to_double( eprep_t epx ) +{ + double res = 0.0; + + res += ldexp((double) epx.X[0], (epx.index - 0)*RADIX); + res += ldexp((double) epx.X[1], (epx.index - 1)*RADIX); + res += ldexp((double) epx.X[2], (epx.index - 2)*RADIX); + + return copysign(res, epx.sign); +} + +static int payne_hanek( double *y, int *exception ); + +static int payne_hanek( double *y, int *exception ) +{ + double x = *y; + + // exception cases .. no reduction required + if( isnan( x ) || isinf( x ) || (fabs( x ) <= M_PI_4) ) { + *exception = 1; + return 0; + } + + *exception = 0; + + // After computation result[0] contains integer part while result[1]....result[DIGITS-1] + // contain fractional part. So we are doing computation with (DIGITS-1)*RADIX precision. + // Default DIGITS=6 and RADIX=30 so default precision is 150 bits. Kahan-McDonald algorithm + // shows that a double precision x, closest to pi/2 is 6381956970095103 x 2^797 which can + // cause 61 digits of cancellation in computation of f = x*2/pi - floor(x*2/pi) ... thus we need + // at least 114 bits (61 leading zeros + 53 bits of mentissa of f) of precision to accurately compute + // f in double precision. Since we are using 150 bits (still an overkill), we should be safe. Extra + // bits can act as guard bits for correct rounding. + uint64_t result[DIGITS+2]; + + // compute extended precision representation of x + eprep_t epx = double_to_eprep( x ); + int index = epx.index; + int i, j; + // extended precision multiplication of 2/pi*x .... we will loose at max two RADIX=30 bit digits in + // the worst case + for(i = 0; i < (DIGITS+2); i++) { + result[i] = 0; + result[i] += ((index + i - 0) >= 0) ? ((uint64_t) two_over_pi[index + i - 0] * (uint64_t) epx.X[0]) : 0; + result[i] += ((index + i - 1) >= 0) ? ((uint64_t) two_over_pi[index + i - 1] * (uint64_t) epx.X[1]) : 0; + result[i] += ((index + i - 2) >= 0) ? ((uint64_t) two_over_pi[index + i - 2] * (uint64_t) epx.X[2]) : 0; + } + + // Carry propagation. + uint64_t tmp; + for(i = DIGITS+2-1; i > 0; i--) { + tmp = result[i] >> RADIX; + result[i - 1] += tmp; + result[i] -= (tmp << RADIX); + } + + // we dont ned to normalize the integer part since only last two bits of this will be used + // subsequently algorithm which remain unaltered by this normalization. + // tmp = result[0] >> RADIX; + // result[0] -= (tmp << RADIX); + unsigned int N = (unsigned int) result[0]; + + // if the result is > pi/4, bring it to (-pi/4, pi/4] range. Note that testing if the final + // x_star = pi/2*(x*2/pi - k) > pi/4 is equivalent to testing, at this stage, if r[1] (the first fractional + // digit) is greater than (2^RADIX)/2 and substracting pi/4 from x_star to bring it to mentioned + // range is equivalent to substracting fractional part at this stage from one and changing the sign. + int sign = 1; + if(result[1] > (uint64_t)(1 << (RADIX - 1))) { + for(i = 1; i < (DIGITS + 2); i++) + result[i] = (~((unsigned int)result[i]) & 0x3fffffff); + N += 1; + sign = -1; + } + + // Again as per Kahan-McDonald algorithim there may be 61 leading zeros in the worst case + // (when x is multiple of 2/pi very close to an integer) so we need to get rid of these zeros + // and adjust the index of final result. So in the worst case, precision of comupted result is + // 90 bits (150 bits original bits - 60 lost in cancellation). + int ind = 1; + for(i = 1; i < (DIGITS+2); i++) { + if(result[i] != 0) + break; + else + ind++; + } + + uint64_t r[DIGITS-1]; + for(i = 0; i < (DIGITS-1); i++) { + r[i] = 0; + for(j = 0; j <= i; j++) { + r[i] += (result[ind+i-j] * (uint64_t) pi_over_two[j]); + } + } + for(i = (DIGITS-2); i > 0; i--) { + tmp = r[i] >> RADIX; + r[i - 1] += tmp; + r[i] -= (tmp << RADIX); + } + tmp = r[0] >> RADIX; + r[0] -= (tmp << RADIX); + + eprep_t epr; + epr.sign = epx.sign*sign; + if(tmp != 0) { + epr.index = -ind + 1; + epr.X[0] = (uint32_t) tmp; + epr.X[1] = (uint32_t) r[0]; + epr.X[2] = (uint32_t) r[1]; + } + else { + epr.index = -ind; + epr.X[0] = (uint32_t) r[0]; + epr.X[1] = (uint32_t) r[1]; + epr.X[2] = (uint32_t) r[2]; + } + + *y = eprep_to_double( epr ); + return epx.sign*N; +} + +double reference_relaxed_cos(double x) +{ + if(isnan(x)) + return NAN; + return (float)cos((float)x); +} + +double reference_cos(double x) +{ + int exception; + int N = payne_hanek( &x, &exception ); + if( exception ) + return cos( x ); + unsigned int c = N & 3; + switch ( c ) { + case 0: + return cos( x ); + case 1: + return -sin( x ); + case 2: + return -cos( x ); + case 3: + return sin( x ); + } + return 0.0; +} + +double reference_relaxed_sin(double x){ + return (float)sin((float)x); +} + +double reference_sin(double x) +{ + int exception; + int N = payne_hanek( &x, &exception ); + if( exception ) + return sin( x ); + int c = N & 3; + switch ( c ) { + case 0: + return sin( x ); + case 1: + return cos( x ); + case 2: + return -sin( x ); + case 3: + return -cos( x ); + } + return 0.0; +} + +double reference_relaxed_sincos(double x, double * y){ + *y = reference_relaxed_cos(x); + return reference_relaxed_sin(x); +} + +double reference_sincos(double x, double *y) +{ + int exception; + int N = payne_hanek( &x, &exception ); + if( exception ) { + *y = cos( x ); + return sin( x ); + } + int c = N & 3; + switch ( c ) { + case 0: + *y = cos( x ); + return sin( x ); + case 1: + *y = -sin( x ); + return cos( x ); + case 2: + *y = -cos( x ); + return -sin( x ); + case 3: + *y = sin( x ); + return -cos( x ); + } + return 0.0; +} + +double reference_relaxed_tan(double x){ + return ((float) reference_relaxed_sin((float)x))/((float) reference_relaxed_cos((float)x)); +} + +double reference_tan(double x) +{ + int exception; + int N = payne_hanek( &x, &exception ); + if( exception ) + return tan( x ); + int c = N & 3; + switch ( c ) { + case 0: + return tan( x ); + case 1: + return -1.0 / tan( x ); + case 2: + return tan( x ); + case 3: + return -1.0 / tan( x ); + } + return 0.0; +} + +long double reference_cosl(long double xx) +{ + double x = (double) xx; + int exception; + int N = payne_hanek( &x, &exception ); + if( exception ) + return cosl( x ); + unsigned int c = N & 3; + switch ( c ) { + case 0: + return cosl( x ); + case 1: + return -sinl( x ); + case 2: + return -cosl( x ); + case 3: + return sinl( x ); + } + return 0.0; +} + +long double reference_sinl(long double xx) +{ + // we use system tanl after reduction which + // can flush denorm input to zero so + //take care of it here. + if(reference_fabsl(xx) < HEX_DBL( +, 1, 0, -, 1022 )) + return xx; + + double x = (double) xx; + int exception; + int N = payne_hanek( &x, &exception ); + if( exception ) + return sinl( x ); + int c = N & 3; + switch ( c ) { + case 0: + return sinl( x ); + case 1: + return cosl( x ); + case 2: + return -sinl( x ); + case 3: + return -cosl( x ); + } + return 0.0; +} + +long double reference_sincosl(long double xx, long double *y) +{ + // we use system tanl after reduction which + // can flush denorm input to zero so + //take care of it here. + if(reference_fabsl(xx) < HEX_DBL( +, 1, 0, -, 1022 )) + { + *y = cosl(xx); + return xx; + } + + double x = (double) xx; + int exception; + int N = payne_hanek( &x, &exception ); + if( exception ) { + *y = cosl( x ); + return sinl( x ); + } + int c = N & 3; + switch ( c ) { + case 0: + *y = cosl( x ); + return sinl( x ); + case 1: + *y = -sinl( x ); + return cosl( x ); + case 2: + *y = -cosl( x ); + return -sinl( x ); + case 3: + *y = sinl( x ); + return -cosl( x ); + } + return 0.0; +} + +long double reference_tanl(long double xx) +{ + // we use system tanl after reduction which + // can flush denorm input to zero so + //take care of it here. + if(reference_fabsl(xx) < HEX_DBL( +, 1, 0, -, 1022 )) + return xx; + + double x = (double) xx; + int exception; + int N = payne_hanek( &x, &exception ); + if( exception ) + return tanl( x ); + int c = N & 3; + switch ( c ) { + case 0: + return tanl( x ); + case 1: + return -1.0 / tanl( x ); + case 2: + return tanl( x ); + case 3: + return -1.0 / tanl( x ); + } + return 0.0; +} + +static double __loglTable1[64][3] = { +{HEX_DBL( +, 1, 5390948f40fea, +, 0 ), HEX_DBL( -, 1, a152f142a, -, 2 ), HEX_DBL( +, 1, f93e27b43bd2c, -, 40 )}, +{HEX_DBL( +, 1, 5015015015015, +, 0 ), HEX_DBL( -, 1, 921800925, -, 2 ), HEX_DBL( +, 1, 162432a1b8df7, -, 41 )}, +{HEX_DBL( +, 1, 4cab88725af6e, +, 0 ), HEX_DBL( -, 1, 8304d90c18, -, 2 ), HEX_DBL( +, 1, 80bb749056fe7, -, 40 )}, +{HEX_DBL( +, 1, 49539e3b2d066, +, 0 ), HEX_DBL( -, 1, 7418acebc, -, 2 ), HEX_DBL( +, 1, ceac7f0607711, -, 43 )}, +{HEX_DBL( +, 1, 460cbc7f5cf9a, +, 0 ), HEX_DBL( -, 1, 6552b49988, -, 2 ), HEX_DBL( +, 1, d8913d0e89fa, -, 42 )}, +{HEX_DBL( +, 1, 42d6625d51f86, +, 0 ), HEX_DBL( -, 1, 56b22e6b58, -, 2 ), HEX_DBL( +, 1, c7eaf515033a1, -, 44 )}, +{HEX_DBL( +, 1, 3fb013fb013fb, +, 0 ), HEX_DBL( -, 1, 48365e696, -, 2 ), HEX_DBL( +, 1, 434adcde7edc7, -, 41 )}, +{HEX_DBL( +, 1, 3c995a47babe7, +, 0 ), HEX_DBL( -, 1, 39de8e156, -, 2 ), HEX_DBL( +, 1, 8246f8e527754, -, 40 )}, +{HEX_DBL( +, 1, 3991c2c187f63, +, 0 ), HEX_DBL( -, 1, 2baa0c34c, -, 2 ), HEX_DBL( +, 1, e1513c28e180d, -, 42 )}, +{HEX_DBL( +, 1, 3698df3de0747, +, 0 ), HEX_DBL( -, 1, 1d982c9d58, -, 2 ), HEX_DBL( +, 1, 63ea3fed4b8a2, -, 40 )}, +{HEX_DBL( +, 1, 33ae45b57bcb1, +, 0 ), HEX_DBL( -, 1, 0fa848045, -, 2 ), HEX_DBL( +, 1, 32ccbacf1779b, -, 40 )}, +{HEX_DBL( +, 1, 30d190130d19, +, 0 ), HEX_DBL( -, 1, 01d9bbcfa8, -, 2 ), HEX_DBL( +, 1, e2bfeb2b884aa, -, 42 )}, +{HEX_DBL( +, 1, 2e025c04b8097, +, 0 ), HEX_DBL( -, 1, e857d3d37, -, 3 ), HEX_DBL( +, 1, d9309b4d2ea85, -, 40 )}, +{HEX_DBL( +, 1, 2b404ad012b4, +, 0 ), HEX_DBL( -, 1, cd3c712d4, -, 3 ), HEX_DBL( +, 1, ddf360962d7ab, -, 40 )}, +{HEX_DBL( +, 1, 288b01288b012, +, 0 ), HEX_DBL( -, 1, b2602497e, -, 3 ), HEX_DBL( +, 1, 597f8a121640f, -, 40 )}, +{HEX_DBL( +, 1, 25e22708092f1, +, 0 ), HEX_DBL( -, 1, 97c1cb13d, -, 3 ), HEX_DBL( +, 1, 02807d15580dc, -, 40 )}, +{HEX_DBL( +, 1, 23456789abcdf, +, 0 ), HEX_DBL( -, 1, 7d60496d, -, 3 ), HEX_DBL( +, 1, 12ce913d7a827, -, 41 )}, +{HEX_DBL( +, 1, 20b470c67c0d8, +, 0 ), HEX_DBL( -, 1, 633a8bf44, -, 3 ), HEX_DBL( +, 1, 0648bca9c96bd, -, 40 )}, +{HEX_DBL( +, 1, 1e2ef3b3fb874, +, 0 ), HEX_DBL( -, 1, 494f863b9, -, 3 ), HEX_DBL( +, 1, 066fceb89b0eb, -, 42 )}, +{HEX_DBL( +, 1, 1bb4a4046ed29, +, 0 ), HEX_DBL( -, 1, 2f9e32d5c, -, 3 ), HEX_DBL( +, 1, 17b8b6c4f846b, -, 46 )}, +{HEX_DBL( +, 1, 19453808ca29c, +, 0 ), HEX_DBL( -, 1, 162593187, -, 3 ), HEX_DBL( +, 1, 2c83506452154, -, 42 )}, +{HEX_DBL( +, 1, 16e0689427378, +, 0 ), HEX_DBL( -, 1, f9c95dc1e, -, 4 ), HEX_DBL( +, 1, dd5d2183150f3, -, 41 )}, +{HEX_DBL( +, 1, 1485f0e0acd3b, +, 0 ), HEX_DBL( -, 1, c7b528b72, -, 4 ), HEX_DBL( +, 1, 0e43c4f4e619d, -, 40 )}, +{HEX_DBL( +, 1, 12358e75d3033, +, 0 ), HEX_DBL( -, 1, 960caf9ac, -, 4 ), HEX_DBL( +, 1, 20fbfd5902a1e, -, 42 )}, +{HEX_DBL( +, 1, 0fef010fef01, +, 0 ), HEX_DBL( -, 1, 64ce26c08, -, 4 ), HEX_DBL( +, 1, 8ebeefb4ac467, -, 40 )}, +{HEX_DBL( +, 1, 0db20a88f4695, +, 0 ), HEX_DBL( -, 1, 33f7cde16, -, 4 ), HEX_DBL( +, 1, 30b3312da7a7d, -, 40 )}, +{HEX_DBL( +, 1, 0b7e6ec259dc7, +, 0 ), HEX_DBL( -, 1, 0387efbcc, -, 4 ), HEX_DBL( +, 1, 796f1632949c3, -, 40 )}, +{HEX_DBL( +, 1, 0953f39010953, +, 0 ), HEX_DBL( -, 1, a6f9c378, -, 5 ), HEX_DBL( +, 1, 1687e151172cc, -, 40 )}, +{HEX_DBL( +, 1, 073260a47f7c6, +, 0 ), HEX_DBL( -, 1, 47aa07358, -, 5 ), HEX_DBL( +, 1, 1f87e4a9cc778, -, 42 )}, +{HEX_DBL( +, 1, 05197f7d73404, +, 0 ), HEX_DBL( -, 1, d23afc498, -, 6 ), HEX_DBL( +, 1, b183a6b628487, -, 40 )}, +{HEX_DBL( +, 1, 03091b51f5e1a, +, 0 ), HEX_DBL( -, 1, 16a21e21, -, 6 ), HEX_DBL( +, 1, 7d75c58973ce5, -, 40 )}, +{HEX_DBL( +, 1, 0, +, 0 ), HEX_DBL( +, 0, 0, +, 0 ), HEX_DBL( +, 0, 0, +, 0 )}, +{HEX_DBL( +, 1, 0, +, 0 ), HEX_DBL( +, 0, 0, +, 0 ), HEX_DBL( +, 0, 0, +, 0 )}, +{HEX_DBL( +, 1, f44659e4a4271, -, 1 ), HEX_DBL( +, 1, 11cd1d51, -, 5 ), HEX_DBL( +, 1, 9a0d857e2f4b2, -, 40 )}, +{HEX_DBL( +, 1, ecc07b301ecc, -, 1 ), HEX_DBL( +, 1, c4dfab908, -, 5 ), HEX_DBL( +, 1, 55b53fce557fd, -, 40 )}, +{HEX_DBL( +, 1, e573ac901e573, -, 1 ), HEX_DBL( +, 1, 3aa2fdd26, -, 4 ), HEX_DBL( +, 1, f1cb0c9532089, -, 40 )}, +{HEX_DBL( +, 1, de5d6e3f8868a, -, 1 ), HEX_DBL( +, 1, 918a16e46, -, 4 ), HEX_DBL( +, 1, 9af0dcd65a6e1, -, 43 )}, +{HEX_DBL( +, 1, d77b654b82c33, -, 1 ), HEX_DBL( +, 1, e72ec117e, -, 4 ), HEX_DBL( +, 1, a5b93c4ebe124, -, 40 )}, +{HEX_DBL( +, 1, d0cb58f6ec074, -, 1 ), HEX_DBL( +, 1, 1dcd19755, -, 3 ), HEX_DBL( +, 1, 5be50e71ddc6c, -, 42 )}, +{HEX_DBL( +, 1, ca4b3055ee191, -, 1 ), HEX_DBL( +, 1, 476a9f983, -, 3 ), HEX_DBL( +, 1, ee9a798719e7f, -, 40 )}, +{HEX_DBL( +, 1, c3f8f01c3f8f, -, 1 ), HEX_DBL( +, 1, 70742d4ef, -, 3 ), HEX_DBL( +, 1, 3ff1352c1219c, -, 46 )}, +{HEX_DBL( +, 1, bdd2b899406f7, -, 1 ), HEX_DBL( +, 1, 98edd077e, -, 3 ), HEX_DBL( +, 1, c383cd11362f4, -, 41 )}, +{HEX_DBL( +, 1, b7d6c3dda338b, -, 1 ), HEX_DBL( +, 1, c0db6cdd9, -, 3 ), HEX_DBL( +, 1, 37bd85b1a824e, -, 41 )}, +{HEX_DBL( +, 1, b2036406c80d9, -, 1 ), HEX_DBL( +, 1, e840be74e, -, 3 ), HEX_DBL( +, 1, a9334d525e1ec, -, 41 )}, +{HEX_DBL( +, 1, ac5701ac5701a, -, 1 ), HEX_DBL( +, 1, 0790adbb, -, 2 ), HEX_DBL( +, 1, 8060bfb6a491, -, 41 )}, +{HEX_DBL( +, 1, a6d01a6d01a6d, -, 1 ), HEX_DBL( +, 1, 1ac05b2918, -, 2 ), HEX_DBL( +, 1, c1c161471580a, -, 40 )}, +{HEX_DBL( +, 1, a16d3f97a4b01, -, 1 ), HEX_DBL( +, 1, 2db10fc4d8, -, 2 ), HEX_DBL( +, 1, ab1aa62214581, -, 42 )}, +{HEX_DBL( +, 1, 9c2d14ee4a101, -, 1 ), HEX_DBL( +, 1, 406463b1b, -, 2 ), HEX_DBL( +, 1, 12e95dbda6611, -, 44 )}, +{HEX_DBL( +, 1, 970e4f80cb872, -, 1 ), HEX_DBL( +, 1, 52dbdfc4c8, -, 2 ), HEX_DBL( +, 1, 6b53fee511af, -, 42 )}, +{HEX_DBL( +, 1, 920fb49d0e228, -, 1 ), HEX_DBL( +, 1, 6518fe467, -, 2 ), HEX_DBL( +, 1, eea7d7d7d1764, -, 40 )}, +{HEX_DBL( +, 1, 8d3018d3018d3, -, 1 ), HEX_DBL( +, 1, 771d2ba7e8, -, 2 ), HEX_DBL( +, 1, ecefa8d4fab97, -, 40 )}, +{HEX_DBL( +, 1, 886e5f0abb049, -, 1 ), HEX_DBL( +, 1, 88e9c72e08, -, 2 ), HEX_DBL( +, 1, 913ea3d33fd14, -, 41 )}, +{HEX_DBL( +, 1, 83c977ab2bedd, -, 1 ), HEX_DBL( +, 1, 9a802391e, -, 2 ), HEX_DBL( +, 1, 197e845877c94, -, 41 )}, +{HEX_DBL( +, 1, 7f405fd017f4, -, 1 ), HEX_DBL( +, 1, abe18797f, -, 2 ), HEX_DBL( +, 1, f4a52f8e8a81, -, 42 )}, +{HEX_DBL( +, 1, 7ad2208e0ecc3, -, 1 ), HEX_DBL( +, 1, bd0f2e9e78, -, 2 ), HEX_DBL( +, 1, 031f4336644cc, -, 42 )}, +{HEX_DBL( +, 1, 767dce434a9b1, -, 1 ), HEX_DBL( +, 1, ce0a4923a, -, 2 ), HEX_DBL( +, 1, 61f33c897020c, -, 40 )}, +{HEX_DBL( +, 1, 724287f46debc, -, 1 ), HEX_DBL( +, 1, ded3fd442, -, 2 ), HEX_DBL( +, 1, b2632e830632, -, 41 )}, +{HEX_DBL( +, 1, 6e1f76b4337c6, -, 1 ), HEX_DBL( +, 1, ef6d673288, -, 2 ), HEX_DBL( +, 1, 888ec245a0bf, -, 40 )}, +{HEX_DBL( +, 1, 6a13cd153729, -, 1 ), HEX_DBL( +, 1, ffd799a838, -, 2 ), HEX_DBL( +, 1, fe6f3b2f5fc8e, -, 40 )}, +{HEX_DBL( +, 1, 661ec6a5122f9, -, 1 ), HEX_DBL( +, 1, 0809cf27f4, -, 1 ), HEX_DBL( +, 1, 81eaa9ef284dd, -, 40 )}, +{HEX_DBL( +, 1, 623fa7701623f, -, 1 ), HEX_DBL( +, 1, 10113b153c, -, 1 ), HEX_DBL( +, 1, 1d7b07d6b1143, -, 42 )}, +{HEX_DBL( +, 1, 5e75bb8d015e7, -, 1 ), HEX_DBL( +, 1, 18028cf728, -, 1 ), HEX_DBL( +, 1, 76b100b1f6c6, -, 41 )}, +{HEX_DBL( +, 1, 5ac056b015ac, -, 1 ), HEX_DBL( +, 1, 1fde3d30e8, -, 1 ), HEX_DBL( +, 1, 26faeb9870945, -, 45 )}, +{HEX_DBL( +, 1, 571ed3c506b39, -, 1 ), HEX_DBL( +, 1, 27a4c0585c, -, 1 ), HEX_DBL( +, 1, 7f2c5344d762b, -, 42 )} +}; + +static double __loglTable2[64][3] = { +{HEX_DBL( +, 1, 01fbe7f0a1be6, +, 0 ), HEX_DBL( -, 1, 6cf6ddd26112a, -, 7 ), HEX_DBL( +, 1, 0725e5755e314, -, 60 )}, +{HEX_DBL( +, 1, 01eba93a97b12, +, 0 ), HEX_DBL( -, 1, 6155b1d99f603, -, 7 ), HEX_DBL( +, 1, 4bcea073117f4, -, 60 )}, +{HEX_DBL( +, 1, 01db6c9029cd1, +, 0 ), HEX_DBL( -, 1, 55b54153137ff, -, 7 ), HEX_DBL( +, 1, 21e8faccad0ec, -, 61 )}, +{HEX_DBL( +, 1, 01cb31f0f534c, +, 0 ), HEX_DBL( -, 1, 4a158c27245bd, -, 7 ), HEX_DBL( +, 1, 1a5b7bfbf35d3, -, 60 )}, +{HEX_DBL( +, 1, 01baf95c9723c, +, 0 ), HEX_DBL( -, 1, 3e76923e3d678, -, 7 ), HEX_DBL( +, 1, eee400eb5fe34, -, 62 )}, +{HEX_DBL( +, 1, 01aac2d2acee6, +, 0 ), HEX_DBL( -, 1, 32d85380ce776, -, 7 ), HEX_DBL( +, 1, cbf7a513937bd, -, 61 )}, +{HEX_DBL( +, 1, 019a8e52d401e, +, 0 ), HEX_DBL( -, 1, 273acfd74be72, -, 7 ), HEX_DBL( +, 1, 5c64599efa5e6, -, 60 )}, +{HEX_DBL( +, 1, 018a5bdca9e42, +, 0 ), HEX_DBL( -, 1, 1b9e072a2e65, -, 7 ), HEX_DBL( +, 1, 364180e0a5d37, -, 60 )}, +{HEX_DBL( +, 1, 017a2b6fcc33e, +, 0 ), HEX_DBL( -, 1, 1001f961f3243, -, 7 ), HEX_DBL( +, 1, 63d795746f216, -, 60 )}, +{HEX_DBL( +, 1, 0169fd0bd8a8a, +, 0 ), HEX_DBL( -, 1, 0466a6671bca4, -, 7 ), HEX_DBL( +, 1, 4c99ff1907435, -, 60 )}, +{HEX_DBL( +, 1, 0159d0b06d129, +, 0 ), HEX_DBL( -, 1, f1981c445cd05, -, 8 ), HEX_DBL( +, 1, 4bfff6366b723, -, 62 )}, +{HEX_DBL( +, 1, 0149a65d275a6, +, 0 ), HEX_DBL( -, 1, da6460f76ab8c, -, 8 ), HEX_DBL( +, 1, 9c5404f47589c, -, 61 )}, +{HEX_DBL( +, 1, 01397e11a581b, +, 0 ), HEX_DBL( -, 1, c3321ab87f4ef, -, 8 ), HEX_DBL( +, 1, c0da537429cea, -, 61 )}, +{HEX_DBL( +, 1, 012957cd85a28, +, 0 ), HEX_DBL( -, 1, ac014958c112c, -, 8 ), HEX_DBL( +, 1, 000c2a1b595e3, -, 64 )}, +{HEX_DBL( +, 1, 0119339065ef7, +, 0 ), HEX_DBL( -, 1, 94d1eca95f67a, -, 8 ), HEX_DBL( +, 1, d8d20b0564d5, -, 61 )}, +{HEX_DBL( +, 1, 01091159e4b3d, +, 0 ), HEX_DBL( -, 1, 7da4047b92b3e, -, 8 ), HEX_DBL( +, 1, 6194a5d68cf2, -, 66 )}, +{HEX_DBL( +, 1, 00f8f129a0535, +, 0 ), HEX_DBL( -, 1, 667790a09bf77, -, 8 ), HEX_DBL( +, 1, ca230e0bea645, -, 61 )}, +{HEX_DBL( +, 1, 00e8d2ff374a1, +, 0 ), HEX_DBL( -, 1, 4f4c90e9c4ead, -, 8 ), HEX_DBL( +, 1, 1de3e7f350c1, -, 61 )}, +{HEX_DBL( +, 1, 00d8b6da482ce, +, 0 ), HEX_DBL( -, 1, 3823052860649, -, 8 ), HEX_DBL( +, 1, 5789b4c5891b8, -, 64 )}, +{HEX_DBL( +, 1, 00c89cba71a8c, +, 0 ), HEX_DBL( -, 1, 20faed2dc9a9e, -, 8 ), HEX_DBL( +, 1, 9e7c40f9839fd, -, 62 )}, +{HEX_DBL( +, 1, 00b8849f52834, +, 0 ), HEX_DBL( -, 1, 09d448cb65014, -, 8 ), HEX_DBL( +, 1, 387e3e9b6d02, -, 62 )}, +{HEX_DBL( +, 1, 00a86e88899a4, +, 0 ), HEX_DBL( -, 1, e55e2fa53ebf1, -, 9 ), HEX_DBL( +, 1, cdaa71fddfddf, -, 62 )}, +{HEX_DBL( +, 1, 00985a75b5e3f, +, 0 ), HEX_DBL( -, 1, b716b429dce0f, -, 9 ), HEX_DBL( +, 1, 2f2af081367bf, -, 63 )}, +{HEX_DBL( +, 1, 00884866766ee, +, 0 ), HEX_DBL( -, 1, 88d21ec7a16d7, -, 9 ), HEX_DBL( +, 1, fb95c228d6f16, -, 62 )}, +{HEX_DBL( +, 1, 0078385a6a61d, +, 0 ), HEX_DBL( -, 1, 5a906f219a9e8, -, 9 ), HEX_DBL( +, 1, 18aff10a89f29, -, 64 )}, +{HEX_DBL( +, 1, 00682a5130fbe, +, 0 ), HEX_DBL( -, 1, 2c51a4dae87f1, -, 9 ), HEX_DBL( +, 1, bcc7e33ddde3, -, 63 )}, +{HEX_DBL( +, 1, 00581e4a69944, +, 0 ), HEX_DBL( -, 1, fc2b7f2d782b1, -, 10 ), HEX_DBL( +, 1, fe3ef3300a9fa, -, 64 )}, +{HEX_DBL( +, 1, 00481445b39a8, +, 0 ), HEX_DBL( -, 1, 9fb97df0b0b83, -, 10 ), HEX_DBL( +, 1, 0d9a601f2f324, -, 65 )}, +{HEX_DBL( +, 1, 00380c42ae963, +, 0 ), HEX_DBL( -, 1, 434d4546227ae, -, 10 ), HEX_DBL( +, 1, 0b9b6a5868f33, -, 63 )}, +{HEX_DBL( +, 1, 00280640fa271, +, 0 ), HEX_DBL( -, 1, cdcda8e930c19, -, 11 ), HEX_DBL( +, 1, 3d424ab39f789, -, 64 )}, +{HEX_DBL( +, 1, 0018024036051, +, 0 ), HEX_DBL( -, 1, 150c558601261, -, 11 ), HEX_DBL( +, 1, 285bb90327a0f, -, 64 )}, +{HEX_DBL( +, 1, 0, +, 0 ), HEX_DBL( +, 0, 0, +, 0 ), HEX_DBL( +, 0, 0, +, 0 )}, +{HEX_DBL( +, 1, 0, +, 0 ), HEX_DBL( +, 0, 0, +, 0 ), HEX_DBL( +, 0, 0, +, 0 )}, +{HEX_DBL( +, 1, ffa011fca0a1e, -, 1 ), HEX_DBL( +, 1, 14e5640c4197b, -, 10 ), HEX_DBL( +, 1, 95728136ae401, -, 63 )}, +{HEX_DBL( +, 1, ff6031f064e07, -, 1 ), HEX_DBL( +, 1, cd61806bf532d, -, 10 ), HEX_DBL( +, 1, 568a4f35d8538, -, 63 )}, +{HEX_DBL( +, 1, ff2061d532b9c, -, 1 ), HEX_DBL( +, 1, 42e34af550eda, -, 9 ), HEX_DBL( +, 1, 8f69cee55fec, -, 62 )}, +{HEX_DBL( +, 1, fee0a1a513253, -, 1 ), HEX_DBL( +, 1, 9f0a5523902ea, -, 9 ), HEX_DBL( +, 1, daec734b11615, -, 63 )}, +{HEX_DBL( +, 1, fea0f15a12139, -, 1 ), HEX_DBL( +, 1, fb25e19f11b26, -, 9 ), HEX_DBL( +, 1, 8bafca62941da, -, 62 )}, +{HEX_DBL( +, 1, fe6150ee3e6d4, -, 1 ), HEX_DBL( +, 1, 2b9af9a28e282, -, 8 ), HEX_DBL( +, 1, 0fd3674e1dc5b, -, 61 )}, +{HEX_DBL( +, 1, fe21c05baa109, -, 1 ), HEX_DBL( +, 1, 599d4678f24b9, -, 8 ), HEX_DBL( +, 1, dafce1f09937b, -, 61 )}, +{HEX_DBL( +, 1, fde23f9c69cf9, -, 1 ), HEX_DBL( +, 1, 8799d8c046eb, -, 8 ), HEX_DBL( +, 1, ffa0ce0bdd217, -, 65 )}, +{HEX_DBL( +, 1, fda2ceaa956e8, -, 1 ), HEX_DBL( +, 1, b590b1e5951ee, -, 8 ), HEX_DBL( +, 1, 645a769232446, -, 62 )}, +{HEX_DBL( +, 1, fd636d8047a1f, -, 1 ), HEX_DBL( +, 1, e381d3555dbcf, -, 8 ), HEX_DBL( +, 1, 882320d368331, -, 61 )}, +{HEX_DBL( +, 1, fd241c179e0cc, -, 1 ), HEX_DBL( +, 1, 08b69f3dccde, -, 7 ), HEX_DBL( +, 1, 01ad5065aba9e, -, 61 )}, +{HEX_DBL( +, 1, fce4da6ab93e8, -, 1 ), HEX_DBL( +, 1, 1fa97a61dd298, -, 7 ), HEX_DBL( +, 1, 84cd1f931ae34, -, 60 )}, +{HEX_DBL( +, 1, fca5a873bcb19, -, 1 ), HEX_DBL( +, 1, 36997bcc54a3f, -, 7 ), HEX_DBL( +, 1, 1485e97eaee03, -, 60 )}, +{HEX_DBL( +, 1, fc66862ccec93, -, 1 ), HEX_DBL( +, 1, 4d86a43264a4f, -, 7 ), HEX_DBL( +, 1, c75e63370988b, -, 61 )}, +{HEX_DBL( +, 1, fc27739018cfe, -, 1 ), HEX_DBL( +, 1, 6470f448fb09d, -, 7 ), HEX_DBL( +, 1, d7361eeaed0a1, -, 65 )}, +{HEX_DBL( +, 1, fbe87097c6f5a, -, 1 ), HEX_DBL( +, 1, 7b586cc4c2523, -, 7 ), HEX_DBL( +, 1, b3df952cc473c, -, 61 )}, +{HEX_DBL( +, 1, fba97d3e084dd, -, 1 ), HEX_DBL( +, 1, 923d0e5a21e06, -, 7 ), HEX_DBL( +, 1, cf56c7b64ae5d, -, 62 )}, +{HEX_DBL( +, 1, fb6a997d0ecdc, -, 1 ), HEX_DBL( +, 1, a91ed9bd3df9a, -, 7 ), HEX_DBL( +, 1, b957bdcd89e43, -, 61 )}, +{HEX_DBL( +, 1, fb2bc54f0f4ab, -, 1 ), HEX_DBL( +, 1, bffdcfa1f7fbb, -, 7 ), HEX_DBL( +, 1, ea8cad9a21771, -, 62 )}, +{HEX_DBL( +, 1, faed00ae41783, -, 1 ), HEX_DBL( +, 1, d6d9f0bbee6f6, -, 7 ), HEX_DBL( +, 1, 5762a9af89c82, -, 60 )}, +{HEX_DBL( +, 1, faae4b94dfe64, -, 1 ), HEX_DBL( +, 1, edb33dbe7d335, -, 7 ), HEX_DBL( +, 1, 21e24fc245697, -, 62 )}, +{HEX_DBL( +, 1, fa6fa5fd27ff8, -, 1 ), HEX_DBL( +, 1, 0244dbae5ed05, -, 6 ), HEX_DBL( +, 1, 12ef51b967102, -, 60 )}, +{HEX_DBL( +, 1, fa310fe15a078, -, 1 ), HEX_DBL( +, 1, 0daeaf24c3529, -, 6 ), HEX_DBL( +, 1, 10d3cfca60b45, -, 59 )}, +{HEX_DBL( +, 1, f9f2893bb9192, -, 1 ), HEX_DBL( +, 1, 1917199bb66bc, -, 6 ), HEX_DBL( +, 1, 6cf6034c32e19, -, 60 )}, +{HEX_DBL( +, 1, f9b412068b247, -, 1 ), HEX_DBL( +, 1, 247e1b6c615d5, -, 6 ), HEX_DBL( +, 1, 42f0fffa229f7, -, 61 )}, +{HEX_DBL( +, 1, f975aa3c18ed6, -, 1 ), HEX_DBL( +, 1, 2fe3b4efcc5ad, -, 6 ), HEX_DBL( +, 1, 70106136a8919, -, 60 )}, +{HEX_DBL( +, 1, f93751d6ae09b, -, 1 ), HEX_DBL( +, 1, 3b47e67edea93, -, 6 ), HEX_DBL( +, 1, 38dd5a4f6959a, -, 59 )}, +{HEX_DBL( +, 1, f8f908d098df6, -, 1 ), HEX_DBL( +, 1, 46aab0725ea6c, -, 6 ), HEX_DBL( +, 1, 821fc1e799e01, -, 60 )}, +{HEX_DBL( +, 1, f8bacf242aa2c, -, 1 ), HEX_DBL( +, 1, 520c1322f1e4e, -, 6 ), HEX_DBL( +, 1, 129dcda3ad563, -, 60 )}, +{HEX_DBL( +, 1, f87ca4cbb755, -, 1 ), HEX_DBL( +, 1, 5d6c0ee91d2ab, -, 6 ), HEX_DBL( +, 1, c5b190c04606e, -, 62 )}, +{HEX_DBL( +, 1, f83e89c195c25, -, 1 ), HEX_DBL( +, 1, 68caa41d448c3, -, 6 ), HEX_DBL( +, 1, 4723441195ac9, -, 59 )} +}; + +static double __loglTable3[8][3] = { +{HEX_DBL( +, 1, 000e00c40ab89, +, 0 ), HEX_DBL( -, 1, 4332be0032168, -, 12 ), HEX_DBL( +, 1, a1003588d217a, -, 65 )}, +{HEX_DBL( +, 1, 000a006403e82, +, 0 ), HEX_DBL( -, 1, cdb2987366fcc, -, 13 ), HEX_DBL( +, 1, 5c86001294bbc, -, 67 )}, +{HEX_DBL( +, 1, 0006002400d8, +, 0 ), HEX_DBL( -, 1, 150297c90fa6f, -, 13 ), HEX_DBL( +, 1, 01fb4865fae32, -, 66 )}, +{HEX_DBL( +, 1, 0, +, 0 ), HEX_DBL( +, 0, 0, +, 0 ), HEX_DBL( +, 0, 0, +, 0 )}, +{HEX_DBL( +, 1, 0, +, 0 ), HEX_DBL( +, 0, 0, +, 0 ), HEX_DBL( +, 0, 0, +, 0 )}, +{HEX_DBL( +, 1, ffe8011ff280a, -, 1 ), HEX_DBL( +, 1, 14f8daf5e3d3b, -, 12 ), HEX_DBL( +, 1, 3c933b4b6b914, -, 68 )}, +{HEX_DBL( +, 1, ffd8031fc184e, -, 1 ), HEX_DBL( +, 1, cd978c38042bb, -, 12 ), HEX_DBL( +, 1, 10f8e642e66fd, -, 65 )}, +{HEX_DBL( +, 1, ffc8061f5492b, -, 1 ), HEX_DBL( +, 1, 43183c878274e, -, 11 ), HEX_DBL( +, 1, 5885dd1eb6582, -, 65 )} +}; + +static void __log2_ep(double *hi, double *lo, double x) +{ + union { uint64_t i; double d; } uu; + + int m; + double f = reference_frexp(x, &m); + + // bring f in [0.75, 1.5) + if( f < 0.75 ) { + f *= 2.0; + m -= 1; + } + + // index first table .... brings down to [1-2^-7, 1+2^6) + uu.d = f; + int index = (int) (((uu.i + ((uint64_t) 1 << 51)) & 0x000fc00000000000ULL) >> 46); + double r1 = __loglTable1[index][0]; + double logr1hi = __loglTable1[index][1]; + double logr1lo = __loglTable1[index][2]; + // since log1rhi has 39 bits of precision, we have 14 bit in hand ... since |m| <= 1023 + // which needs 10bits at max, we can directly add m to log1hi without spilling + logr1hi += m; + + // argument reduction needs to be in double-double since reduced argument will form the + // leading term of polynomial approximation which sets the precision we eventually achieve + double zhi, zlo; + MulD(&zhi, &zlo, r1, uu.d); + + // second index table .... brings down to [1-2^-12, 1+2^-11) + uu.d = zhi; + index = (int) (((uu.i + ((uint64_t) 1 << 46)) & 0x00007e0000000000ULL) >> 41); + double r2 = __loglTable2[index][0]; + double logr2hi = __loglTable2[index][1]; + double logr2lo = __loglTable2[index][2]; + + // reduce argument + MulDD(&zhi, &zlo, zhi, zlo, r2, 0.0); + + // third index table .... brings down to [1-2^-14, 1+2^-13) + // Actually reduction to 2^-11 would have been sufficient to calculate + // second order term in polynomial in double rather than double-double, I + // reduced it a bit more to make sure other systematic arithmetic errors + // are guarded against .... also this allow lower order product of leading polynomial + // term i.e. Ao_hi*z_lo + Ao_lo*z_hi to be done in double rather than double-double ... + // hence only term that needs to be done in double-double is Ao_hi*z_hi + uu.d = zhi; + index = (int) (((uu.i + ((uint64_t) 1 << 41)) & 0x0000038000000000ULL) >> 39); + double r3 = __loglTable3[index][0]; + double logr3hi = __loglTable3[index][1]; + double logr3lo = __loglTable3[index][2]; + + // log2(x) = m + log2(r1) + log2(r1) + log2(1 + (zh + zlo)) + // calculate sum of first three terms ... note that m has already + // been added to log2(r1)_hi + double log2hi, log2lo; + AddDD(&log2hi, &log2lo, logr1hi, logr1lo, logr2hi, logr2lo); + AddDD(&log2hi, &log2lo, logr3hi, logr3lo, log2hi, log2lo); + + // final argument reduction .... zhi will be in [1-2^-14, 1+2^-13) after this + MulDD(&zhi, &zlo, zhi, zlo, r3, 0.0); + // we dont need to do full double-double substract here. substracting 1.0 for higher + // term is exact + zhi = zhi - 1.0; + // normalize + AddD(&zhi, &zlo, zhi, zlo); + + // polynomail fitting to compute log2(1 + z) ... forth order polynomial fit + // to log2(1 + z)/z gives minimax absolute error of O(2^-76) with z in [-2^-14, 2^-13] + // log2(1 + z)/z = Ao + A1*z + A2*z^2 + A3*z^3 + A4*z^4 + // => log2(1 + z) = Ao*z + A1*z^2 + A2*z^3 + A3*z^4 + A4*z^5 + // => log2(1 + z) = (Aohi + Aolo)*(zhi + zlo) + z^2*(A1 + A2*z + A3*z^2 + A4*z^3) + // since we are looking for at least 64 digits of precision and z in [-2^-14, 2^-13], final term + // can be done in double .... also Aolo*zhi + Aohi*zlo can be done in double .... + // Aohi*zhi needs to be done in double-double + + double Aohi = HEX_DBL( +, 1, 71547652b82fe, +, 0 ); + double Aolo = HEX_DBL( +, 1, 777c9cbb675c, -, 56 ); + double y; + y = HEX_DBL( +, 1, 276d2736fade7, -, 2 ); + y = HEX_DBL( -, 1, 7154765782df1, -, 2 ) + y*zhi; + y = HEX_DBL( +, 1, ec709dc3a0f67, -, 2 ) + y*zhi; + y = HEX_DBL( -, 1, 71547652b82fe, -, 1 ) + y*zhi; + double zhisq = zhi*zhi; + y = y*zhisq; + y = y + zhi*Aolo; + y = y + zlo*Aohi; + + MulD(&zhi, &zlo, Aohi, zhi); + AddDD(&zhi, &zlo, zhi, zlo, y, 0.0); + AddDD(&zhi, &zlo, zhi, zlo, log2hi, log2lo); + + *hi = zhi; + *lo = zlo; +} + +long double reference_powl( long double x, long double y ) +{ + + + // this will be used for testing doubles i.e. arguments will + // be doubles so cast the input back to double ... returned + // result will be long double though .... > 53 bits of precision + // if platform allows. + // =========== + // New finding. + // =========== + // this function is getting used for computing reference cube root (cbrt) + // as follows __powl( x, 1.0L/3.0L ) so if the y are assumed to + // be double and is converted from long double to double, truncation + // causes errors. So we need to tread y as long double and convert it + // to hi, lo doubles when performing y*log2(x). + +// double x = (double) xx; +// double y = (double) yy; + + static const double neg_epsilon = HEX_DBL( +, 1, 0, +, 53 ); + + //if x = 1, return x for any y, even NaN + if( x == 1.0 ) + return x; + + //if y == 0, return 1 for any x, even NaN + if( y == 0.0 ) + return 1.0L; + + //get NaNs out of the way + if( x != x || y != y ) + return x + y; + + //do the work required to sort out edge cases + double fabsy = reference_fabs( y ); + double fabsx = reference_fabs( x ); + double iy = reference_rint( fabsy ); //we do round to nearest here so that |fy| <= 0.5 + if( iy > fabsy )//convert nearbyint to floor + iy -= 1.0; + int isOddInt = 0; + if( fabsy == iy && !reference_isinf(fabsy) && iy < neg_epsilon ) + isOddInt = (int) (iy - 2.0 * rint( 0.5 * iy )); //might be 0, -1, or 1 + + ///test a few more edge cases + //deal with x == 0 cases + if( x == 0.0 ) + { + if( ! isOddInt ) + x = 0.0; + + if( y < 0 ) + x = 1.0/ x; + + return x; + } + + //x == +-Inf cases + if( isinf(fabsx) ) + { + if( x < 0 ) + { + if( isOddInt ) + { + if( y < 0 ) + return -0.0; + else + return -INFINITY; + } + else + { + if( y < 0 ) + return 0.0; + else + return INFINITY; + } + } + + if( y < 0 ) + return 0; + return INFINITY; + } + + //y = +-inf cases + if( isinf(fabsy) ) + { + if( x == -1 ) + return 1; + + if( y < 0 ) + { + if( fabsx < 1 ) + return INFINITY; + return 0; + } + if( fabsx < 1 ) + return 0; + return INFINITY; + } + + // x < 0 and y non integer case + if( x < 0 && iy != fabsy ) + { + //return nan; + return cl_make_nan(); + } + + //speedy resolution of sqrt and reciprocal sqrt + if( fabsy == 0.5 ) + { + long double xl = sqrtl( x ); + if( y < 0 ) + xl = 1.0/ xl; + return xl; + } + + double log2x_hi, log2x_lo; + + // extended precision log .... accurate to at least 64-bits + couple of guard bits + __log2_ep(&log2x_hi, &log2x_lo, fabsx); + + double ylog2x_hi, ylog2x_lo; + + double y_hi = (double) y; + double y_lo = (double) ( y - (long double) y_hi); + + // compute product of y*log2(x) + // scale to avoid overflow in double-double multiplication + if( reference_fabs( y ) > HEX_DBL( +, 1, 0, +, 970 ) ) { + y_hi = reference_ldexp(y_hi, -53); + y_lo = reference_ldexp(y_lo, -53); + } + MulDD(&ylog2x_hi, &ylog2x_lo, log2x_hi, log2x_lo, y_hi, y_lo); + if( fabs( y ) > HEX_DBL( +, 1, 0, +, 970 ) ) { + ylog2x_hi = reference_ldexp(ylog2x_hi, 53); + ylog2x_lo = reference_ldexp(ylog2x_lo, 53); + } + + long double powxy; + if(isinf(ylog2x_hi) || (reference_fabs(ylog2x_hi) > 2200)) { + powxy = reference_signbit(ylog2x_hi) ? HEX_DBL( +, 0, 0, +, 0 ) : INFINITY; + } else { + // separate integer + fractional part + long int m = lrint(ylog2x_hi); + AddDD(&ylog2x_hi, &ylog2x_lo, ylog2x_hi, ylog2x_lo, -m, 0.0); + + // revert to long double arithemtic + long double ylog2x = (long double) ylog2x_hi + (long double) ylog2x_lo; + long double tmp = reference_exp2l( ylog2x ); + powxy = reference_scalblnl(tmp, m); + } + + // if y is odd integer and x is negative, reverse sign + if( isOddInt & reference_signbit(x)) + powxy = -powxy; + return powxy; +} + +double reference_nextafter(double xx, double yy) +{ + float x = (float) xx; + float y = (float) yy; + + // take care of nans + if( x != x ) + return x; + + if( y != y ) + return y; + + if( x == y ) + return y; + + int32f_t a, b; + + a.f = x; + b.f = y; + + if( a.i & 0x80000000 ) + a.i = 0x80000000 - a.i; + if(b.i & 0x80000000 ) + b.i = 0x80000000 - b.i; + + a.i += (a.i < b.i) ? 1 : -1; + a.i = (a.i < 0) ? (cl_int) 0x80000000 - a.i : a.i; + + return a.f; +} + + +long double reference_nextafterl(long double xx, long double yy) +{ + double x = (double) xx; + double y = (double) yy; + + // take care of nans + if( x != x ) + return x; + + if( y != y ) + return y; + + int64d_t a, b; + + a.d = x; + b.d = y; + + int64_t tmp = 0x8000000000000000LL; + + if( a.l & tmp ) + a.l = tmp - a.l; + if(b.l & tmp ) + b.l = tmp - b.l; + + // edge case. if (x == y) or (x = 0.0f and y = -0.0f) or (x = -0.0f and y = 0.0f) + // test needs to be done using integer rep because + // subnormals may be flushed to zero on some platforms + if( a.l == b.l ) + return y; + + a.l += (a.l < b.l) ? 1 : -1; + a.l = (a.l < 0) ? tmp - a.l : a.l; + + return a.d; +} + +double reference_fdim(double xx, double yy) +{ + float x = (float) xx; + float y = (float) yy; + + if( x != x ) + return x; + + if( y != y ) + return y; + + float r = ( x > y ) ? (float) reference_subtract( x, y) : 0.0f; + return r; + +} + + +long double reference_fdiml(long double xx, long double yy) +{ + double x = (double) xx; + double y = (double) yy; + + if( x != x ) + return x; + + if( y != y ) + return y; + + double r = ( x > y ) ? (double) reference_subtractl(x, y) : 0.0; + return r; +} + +double reference_remquo(double xd, double yd, int *n) +{ + float xx = (float) xd; + float yy = (float) yd; + + if( isnan(xx) || isnan(yy) || + fabsf(xx) == INFINITY || + yy == 0.0 ) + { + *n = 0; + return cl_make_nan(); + } + + if( fabsf(yy) == INFINITY || xx == 0.0f ) { + *n = 0; + return xd; + } + + if( fabsf(xx) == fabsf(yy) ) { + *n = (xx == yy) ? 1 : -1; + return reference_signbit( xx ) ? -0.0 : 0.0; + } + + int signx = reference_signbit( xx ) ? -1 : 1; + int signy = reference_signbit( yy ) ? -1 : 1; + int signn = (signx == signy) ? 1 : -1; + float x = fabsf(xx); + float y = fabsf(yy); + + int ex, ey; + ex = reference_ilogb( x ); + ey = reference_ilogb( y ); + float xr = x; + float yr = y; + uint32_t q = 0; + + if(ex-ey >= -1) { + + yr = (float) reference_ldexp( y, -ey ); + xr = (float) reference_ldexp( x, -ex ); + + if(ex-ey >= 0) { + + + int i; + for(i = ex-ey; i > 0; i--) { + q <<= 1; + if(xr >= yr) { + xr -= yr; + q += 1; + } + xr += xr; + } + q <<= 1; + if( xr > yr ) { + xr -= yr; + q += 1; + } + } + else //ex-ey = -1 + xr = reference_ldexp(xr, ex-ey); + } + + if( (yr < 2.0f*xr) || ( (yr == 2.0f*xr) && (q & 0x00000001) ) ) { + xr -= yr; + q += 1; + } + + if(ex-ey >= -1) + xr = reference_ldexp(xr, ey); + + int qout = q & 0x0000007f; + if( signn < 0) + qout = -qout; + if( xx < 0.0 ) + xr = -xr; + + *n = qout; + + return xr; +} + +long double reference_remquol(long double xd, long double yd, int *n) +{ + + double xx = (double) xd; + double yy = (double) yd; + + if( isnan(xx) || isnan(yy) || + fabs(xx) == INFINITY || + yy == 0.0 ) + { + *n = 0; + return cl_make_nan(); + } + + if( reference_fabs(yy) == INFINITY || xx == 0.0 ) { + *n = 0; + return xd; + } + + if( reference_fabs(xx) == reference_fabs(yy) ) { + *n = (xx == yy) ? 1 : -1; + return reference_signbit( xx ) ? -0.0 : 0.0; + } + + int signx = reference_signbit( xx ) ? -1 : 1; + int signy = reference_signbit( yy ) ? -1 : 1; + int signn = (signx == signy) ? 1 : -1; + double x = reference_fabs(xx); + double y = reference_fabs(yy); + + int ex, ey; + ex = reference_ilogbl( x ); + ey = reference_ilogbl( y ); + double xr = x; + double yr = y; + uint32_t q = 0; + + if(ex-ey >= -1) { + + yr = reference_ldexp( y, -ey ); + xr = reference_ldexp( x, -ex ); + int i; + + if(ex-ey >= 0) { + + for(i = ex-ey; i > 0; i--) { + q <<= 1; + if(xr >= yr) { + xr -= yr; + q += 1; + } + xr += xr; + } + q <<= 1; + if( xr > yr ) { + xr -= yr; + q += 1; + } + } + else + xr = reference_ldexp(xr, ex-ey); + } + + if( (yr < 2.0*xr) || ( (yr == 2.0*xr) && (q & 0x00000001) ) ) { + xr -= yr; + q += 1; + } + + if(ex-ey >= -1) + xr = reference_ldexp(xr, ey); + + int qout = q & 0x0000007f; + if( signn < 0) + qout = -qout; + if( xx < 0.0 ) + xr = -xr; + + *n = qout; + return xr; +} + +static double reference_scalbn(double x, int n) +{ + if(reference_isinf(x) || reference_isnan(x) || x == 0.0) + return x; + + int bias = 1023; + union { double d; cl_long l; } u; + u.d = (double) x; + int e = (int)((u.l & 0x7ff0000000000000LL) >> 52); + if(e == 0) + { + u.l |= ((cl_long)1023 << 52); + u.d -= 1.0; + e = (int)((u.l & 0x7ff0000000000000LL) >> 52) - 1022; + } + e += n; + if(e >= 2047 || n >= 2098 ) + return reference_copysign(INFINITY, x); + if(e < -51 || n <-2097 ) + return reference_copysign(0.0, x); + if(e <= 0) + { + bias += (e-1); + e = 1; + } + u.l &= 0x800fffffffffffffLL; + u.l |= ((cl_long)e << 52); + x = u.d; + u.l = ((cl_long)bias << 52); + return x * u.d; +} + +static long double reference_scalblnl(long double x, long n) +{ +#if defined(__i386__) || defined(__x86_64__) // INTEL + union + { + long double d; + struct{ cl_ulong m; cl_ushort sexp;}u; + }u; + u.u.m = CL_LONG_MIN; + + if ( reference_isinf(x) ) + return x; + + if( x == 0.0L || n < -2200) + return reference_copysignl( 0.0L, x ); + + if( n > 2200 ) + return reference_copysignl( INFINITY, x ); + + if( n < 0 ) + { + u.u.sexp = 0x3fff - 1022; + while( n <= -1022 ) + { + x *= u.d; + n += 1022; + } + u.u.sexp = 0x3fff + n; + x *= u.d; + return x; + } + + if( n > 0 ) + { + u.u.sexp = 0x3fff + 1023; + while( n >= 1023 ) + { + x *= u.d; + n -= 1023; + } + u.u.sexp = 0x3fff + n; + x *= u.d; + return x; + } + + return x; + +#elif defined(__arm__) // ARM .. sizeof(long double) == sizeof(double) + +#if __DBL_MAX_EXP__ >= __LDBL_MAX_EXP__ + if(reference_isinfl(x) || reference_isnanl(x)) + return x; + + int bias = 1023; + union { double d; cl_long l; } u; + u.d = (double) x; + int e = (int)((u.l & 0x7ff0000000000000LL) >> 52); + if(e == 0) + { + u.l |= ((cl_long)1023 << 52); + u.d -= 1.0; + e = (int)((u.l & 0x7ff0000000000000LL) >> 52) - 1022; + } + e += n; + if(e >= 2047) + return reference_copysignl(INFINITY, x); + if(e < -51) + return reference_copysignl(0.0, x); + if(e <= 0) + { + bias += (e-1); + e = 1; + } + u.l &= 0x800fffffffffffffLL; + u.l |= ((cl_long)e << 52); + x = u.d; + u.l = ((cl_long)bias << 52); + return x * u.d; +#endif + +#else // PPC + return scalblnl(x, n); +#endif +} + +double reference_relaxed_exp( double x ) +{ + return reference_exp(x); +} + +double reference_exp(double x) +{ + return reference_exp2( x * HEX_DBL( +, 1, 71547652b82fe, +, 0 ) ); +} + +long double reference_expl(long double x) +{ +#if defined(__PPC__) + long double scale, bias; + + // The PPC double long version of expl fails to produce denorm results + // and instead generates a 0.0. Compensate for this limitation by + // computing expl as: + // expl(x + 40) * expl(-40) + // Likewise, overflows can prematurely produce an infinity, so we + // compute expl as: + // expl(x - 40) * expl(40) + scale = 1.0L; + bias = 0.0L; + if (x < -708.0L) { + bias = 40.0; + scale = expl(-40.0L); + } else if (x > 708.0L) { + bias = -40.0L; + scale = expl(40.0L); + } + return expl(x + bias) * scale; +#else + return expl( x ); +#endif +} + +double reference_sinh(double x) +{ + return sinh(x); +} + +long double reference_sinhl(long double x) +{ + return sinhl(x); +} + +double reference_fmod(double x, double y) +{ + if( x == 0.0 && fabs(y) > 0.0 ) + return x; + + if( fabs(x) == INFINITY || y == 0 ) + return cl_make_nan(); + + if( fabs(y) == INFINITY ) // we know x is finite from above + return x; +#if defined(_MSC_VER) && defined(_M_X64) + return fmod( x, y ); +#else + return fmodf( (float) x, (float) y ); +#endif +} + +long double reference_fmodl(long double x, long double y) +{ + if( x == 0.0L && fabsl(y) > 0.0L ) + return x; + + if( fabsl(x) == INFINITY || y == 0.0L ) + return cl_make_nan(); + + if( fabsl(y) == INFINITY ) // we know x is finite from above + return x; + + return fmod( (double) x, (double) y ); +} + +double reference_modf(double x, double *n) +{ + if(isnan(x)) { + *n = cl_make_nan(); + return cl_make_nan(); + } + float nr; + float yr = modff((float) x, &nr); + *n = nr; + return yr; +} + +long double reference_modfl(long double x, long double *n) +{ + if(isnan(x)) { + *n = cl_make_nan(); + return cl_make_nan(); + } + double nr; + double yr = modf((double) x, &nr); + *n = nr; + return yr; +} + +long double reference_fractl(long double x, long double *ip ) +{ + if(isnan(x)) { + *ip = cl_make_nan(); + return cl_make_nan(); + } + + double i; + double f = modf((double) x, &i ); + if( f < 0.0 ) + { + f = 1.0 + f; + i -= 1.0; + if( f == 1.0 ) + f = HEX_DBL( +, 1, fffffffffffff, -, 1 ); + } + *ip = i; + return f; +} + +long double reference_fabsl(long double x) +{ + return fabsl( x ); +} + +double reference_relaxed_log( double x ) +{ + return (float)reference_log((float)x); +} + +double reference_log(double x) +{ + if( x == 0.0 ) + return -INFINITY; + + if( x < 0.0 ) + return cl_make_nan(); + + if( isinf(x) ) + return INFINITY; + + double log2Hi = HEX_DBL( +, 1, 62e42fefa39ef, -, 1 ); + double logxHi, logxLo; + __log2_ep(&logxHi, &logxLo, x); + return logxHi*log2Hi; +} + +long double reference_logl(long double x) +{ + if( x == 0.0 ) + return -INFINITY; + + if( x < 0.0 ) + return cl_make_nan(); + + if( isinf(x) ) + return INFINITY; + + double log2Hi = HEX_DBL( +, 1, 62e42fefa39ef, -, 1 ); + double log2Lo = HEX_DBL( +, 1, abc9e3b39803f, -, 56 ); + double logxHi, logxLo; + __log2_ep(&logxHi, &logxLo, x); + + //double rhi, rlo; + //MulDD(&rhi, &rlo, logxHi, logxLo, log2Hi, log2Lo); + //return (long double) rhi + (long double) rlo; + + long double lg2 = (long double) log2Hi + (long double) log2Lo; + long double logx = (long double) logxHi + (long double) logxLo; + return logx*lg2; +} + +double reference_relaxed_pow( double x, double y) { + return (float)reference_exp2( ((float)y) * (float)reference_log2((float)x)); +} + +double reference_pow( double x, double y ) +{ + static const double neg_epsilon = HEX_DBL( +, 1, 0, +, 53 ); + + //if x = 1, return x for any y, even NaN + if( x == 1.0 ) + return x; + + //if y == 0, return 1 for any x, even NaN + if( y == 0.0 ) + return 1.0; + + //get NaNs out of the way + if( x != x || y != y ) + return x + y; + + //do the work required to sort out edge cases + double fabsy = reference_fabs( y ); + double fabsx = reference_fabs( x ); + double iy = reference_rint( fabsy ); //we do round to nearest here so that |fy| <= 0.5 + if( iy > fabsy )//convert nearbyint to floor + iy -= 1.0; + int isOddInt = 0; + if( fabsy == iy && !reference_isinf(fabsy) && iy < neg_epsilon ) + isOddInt = (int) (iy - 2.0 * rint( 0.5 * iy )); //might be 0, -1, or 1 + + ///test a few more edge cases + //deal with x == 0 cases + if( x == 0.0 ) + { + if( ! isOddInt ) + x = 0.0; + + if( y < 0 ) + x = 1.0/ x; + + return x; + } + + //x == +-Inf cases + if( isinf(fabsx) ) + { + if( x < 0 ) + { + if( isOddInt ) + { + if( y < 0 ) + return -0.0; + else + return -INFINITY; + } + else + { + if( y < 0 ) + return 0.0; + else + return INFINITY; + } + } + + if( y < 0 ) + return 0; + return INFINITY; + } + + //y = +-inf cases + if( isinf(fabsy) ) + { + if( x == -1 ) + return 1; + + if( y < 0 ) + { + if( fabsx < 1 ) + return INFINITY; + return 0; + } + if( fabsx < 1 ) + return 0; + return INFINITY; + } + + // x < 0 and y non integer case + if( x < 0 && iy != fabsy ) + { + //return nan; + return cl_make_nan(); + } + + //speedy resolution of sqrt and reciprocal sqrt + if( fabsy == 0.5 ) + { + long double xl = reference_sqrt( x ); + if( y < 0 ) + xl = 1.0/ xl; + return xl; + } + + double hi, lo; + __log2_ep(&hi, &lo, fabsx); + double prod = y * hi; + double result = reference_exp2(prod); + return isOddInt ? reference_copysignd(result, x) : result; +} + +double reference_sqrt(double x) +{ + return sqrt(x); +} + +double reference_floor(double x) +{ + return floorf((float) x); +} + +double reference_ldexp(double value, int exponent) +{ +#ifdef __MINGW32__ +/* + * ==================================================== + * This function is from fdlibm: http://www.netlib.org + * It is Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + if(!finite(value)||value==0.0) return value; + return scalbn(value,exponent); +#else + return reference_scalbn(value, exponent); +#endif +} + +long double reference_ldexpl(long double x, int n) +{ + return ldexpl( x, n); +} + +long double reference_coshl(long double x) +{ + return coshl(x); +} + +double reference_ceil(double x) +{ + return ceilf((float) x); +} + +long double reference_ceill(long double x) +{ + if( x == 0.0 || reference_isinfl(x) || reference_isnanl(x) ) + return x; + + long double absx = reference_fabsl(x); + if( absx >= HEX_LDBL( +, 1, 0, +, 52 ) ) + return x; + + if( absx < 1.0 ) + { + if( x < 0.0 ) + return 0.0; + else + return 1.0; + } + + long double r = (long double) ((cl_long) x); + + if( x > 0.0 && r < x ) + r += 1.0; + + return r; +} + + +long double reference_acosl(long double x) +{ + long double x2 = x * x; + int i; + + //Prepare a head + tail representation of PI in long double. A good compiler should get rid of all of this work. + static const cl_ulong pi_bits[2] = { 0x3243F6A8885A308DULL, 0x313198A2E0370734ULL}; // first 126 bits of pi http://www.super-computing.org/pi-hexa_current.html + long double head, tail, temp; +#if __LDBL_MANT_DIG__ >= 64 + // long double has 64-bits of precision or greater + temp = (long double) pi_bits[0] * 0x1.0p64L; + head = temp + (long double) pi_bits[1]; + temp -= head; // rounding err rounding pi_bits[1] into head + tail = (long double) pi_bits[1] + temp; + head *= HEX_LDBL( +, 1, 0, -, 125 ); + tail *= HEX_LDBL( +, 1, 0, -, 125 ); +#else + head = (long double) pi_bits[0]; + tail = (long double) ((cl_long) pi_bits[0] - (cl_long) head ); // residual part of pi_bits[0] after rounding + tail = tail * HEX_LDBL( +, 1, 0, +, 64 ) + (long double) pi_bits[1]; + head *= HEX_LDBL( +, 1, 0, -, 61 ); + tail *= HEX_LDBL( +, 1, 0, -, 125 ); +#endif + + // oversize values and NaNs go to NaN + if( ! (x2 <= 1.0) ) + return sqrtl(1.0L - x2 ); + + // + // deal with large |x|: + // sqrt( 1 - x**2) + // acos(|x| > sqrt(0.5)) = 2 * atan( z ); z = -------------------- ; z in [0, sqrt(0.5)/(1+sqrt(0.5) = .4142135...] + // 1 + x + if( x2 > 0.5 ) + { + // we handle the x < 0 case as pi - acos(|x|) + + long double sign = reference_copysignl( 1.0L, x ); + long double fabsx = reference_fabsl( x ); + head -= head * sign; // x > 0 ? 0 : pi.hi + tail -= tail * sign; // x > 0 ? 0 : pi.low + + // z = sqrt( 1-x**2 ) / (1+x) = sqrt( (1-x)(1+x) / (1+x)**2 ) = sqrt( (1-x)/(1+x) ) + long double z2 = (1.0L - fabsx) / (1.0L + fabsx); // z**2 + long double z = sign * sqrtl(z2); + + // atan(sqrt(q)) + // Minimax fit p(x) = ---------------- - 1 + // sqrt(q) + // + // Define q = r*r, and solve for atan(r): + // + // atan(r) = (p(r) + 1) * r = rp(r) + r + static long double atan_coeffs[] = { HEX_LDBL( -, b, 3f52e0c278293b3, -, 67 ), HEX_LDBL( -, a, aaaaaaaaaaa95b8, -, 5 ), + HEX_LDBL( +, c, ccccccccc992407, -, 6 ), HEX_LDBL( -, 9, 24924923024398, -, 6 ), + HEX_LDBL( +, e, 38e38d6f92c98f3, -, 7 ), HEX_LDBL( -, b, a2e89bfb8393ec6, -, 7 ), + HEX_LDBL( +, 9, d89a9f574d412cb, -, 7 ), HEX_LDBL( -, 8, 88580517884c547, -, 7 ), + HEX_LDBL( +, f, 0ab6756abdad408, -, 8 ), HEX_LDBL( -, d, 56a5b07a2f15b49, -, 8 ), + HEX_LDBL( +, b, 72ab587e46d80b2, -, 8 ), HEX_LDBL( -, 8, 62ea24bb5b2e636, -, 8 ), + HEX_LDBL( +, e, d67c16582123937, -, 10 ) }; // minimax fit over [ 0x1.0p-52, 0.18] Max error: 0x1.67ea5c184e5d9p-64 + + // Calculate y = p(r) + const size_t atan_coeff_count = sizeof( atan_coeffs ) / sizeof( atan_coeffs[0] ); + long double y = atan_coeffs[ atan_coeff_count - 1]; + for( i = (int)atan_coeff_count - 2; i >= 0; i-- ) + y = atan_coeffs[i] + y * z2; + + z *= 2.0L; // fold in 2.0 for 2.0 * atan(z) + y *= z; // rp(r) + + return head + ((y + tail) + z); + } + + // do |x| <= sqrt(0.5) here + // acos( sqrt(z) ) - PI/2 + // Piecewise minimax polynomial fits for p(z) = 1 + ------------------------; + // sqrt(z) + // + // Define z = x*x, and solve for acos(x) over x in x >= 0: + // + // acos( sqrt(z) ) = acos(x) = x*(p(z)-1) + PI/2 = xp(x**2) - x + PI/2 + // + const long double coeffs[4][14] = { + { HEX_LDBL( -, a, fa7382e1f347974, -, 10 ), HEX_LDBL( -, b, 4d5a992de1ac4da, -, 6 ), + HEX_LDBL( -, a, c526184bd558c17, -, 7 ), HEX_LDBL( -, d, 9ed9b0346ec092a, -, 8 ), + HEX_LDBL( -, 9, dca410c1f04b1f, -, 8 ), HEX_LDBL( -, f, 76e411ba9581ee5, -, 9 ), + HEX_LDBL( -, c, c71b00479541d8e, -, 9 ), HEX_LDBL( -, a, f527a3f9745c9de, -, 9 ), + HEX_LDBL( -, 9, a93060051f48d14, -, 9 ), HEX_LDBL( -, 8, b3d39ad70e06021, -, 9 ), + HEX_LDBL( -, f, f2ab95ab84f79c, -, 10 ), HEX_LDBL( -, e, d1af5f5301ccfe4, -, 10 ), + HEX_LDBL( -, e, 1b53ba562f0f74a, -, 10 ), HEX_LDBL( -, d, 6a3851330e15526, -, 10 ) }, // x - 0.0625 in [ -0x1.fffffffffp-5, 0x1.0p-4 ] Error: 0x1.97839bf07024p-76 + + { HEX_LDBL( -, 8, c2f1d638e4c1b48, -, 8 ), HEX_LDBL( -, c, d47ac903c311c2c, -, 6 ), + HEX_LDBL( -, d, e020b2dabd5606a, -, 7 ), HEX_LDBL( -, a, 086fafac220f16b, -, 7 ), + HEX_LDBL( -, 8, 55b5efaf6b86c3e, -, 7 ), HEX_LDBL( -, f, 05c9774fed2f571, -, 8 ), + HEX_LDBL( -, e, 484a93f7f0fc772, -, 8 ), HEX_LDBL( -, e, 1a32baef01626e4, -, 8 ), + HEX_LDBL( -, e, 528e525b5c9c73d, -, 8 ), HEX_LDBL( -, e, ddd5d27ad49b2c8, -, 8 ), + HEX_LDBL( -, f, b3259e7ae10c6f, -, 8 ), HEX_LDBL( -, 8, 68998170d5b19b7, -, 7 ), + HEX_LDBL( -, 9, 4468907f007727, -, 7 ), HEX_LDBL( -, a, 2ad5e4906a8e7b3, -, 7 ) },// x - 0.1875 in [ -0x1.0p-4, 0x1.0p-4 ] Error: 0x1.647af70073457p-73 + + { HEX_LDBL( -, f, a76585ad399e7ac, -, 8 ), HEX_LDBL( -, e, d665b7dd504ca7c, -, 6 ), + HEX_LDBL( -, 9, 4c7c2402bd4bc33, -, 6 ), HEX_LDBL( -, f, ba76b69074ff71c, -, 7 ), + HEX_LDBL( -, f, 58117784bdb6d5f, -, 7 ), HEX_LDBL( -, 8, 22ddd8eef53227d, -, 6 ), + HEX_LDBL( -, 9, 1d1d3b57a63cdb4, -, 6 ), HEX_LDBL( -, a, 9c4bdc40cca848, -, 6 ), + HEX_LDBL( -, c, b673b12794edb24, -, 6 ), HEX_LDBL( -, f, 9290a06e31575bf, -, 6 ), + HEX_LDBL( -, 9, b4929c16aeb3d1f, -, 5 ), HEX_LDBL( -, c, 461e725765a7581, -, 5 ), + HEX_LDBL( -, 8, 0a59654c98d9207, -, 4 ), HEX_LDBL( -, a, 6de6cbd96c80562, -, 4 ) }, // x - 0.3125 in [ -0x1.0p-4, 0x1.0p-4 ] Error: 0x1.b0246c304ce1ap-70 + + { HEX_LDBL( -, b, dca8b0359f96342, -, 7 ), HEX_LDBL( -, 8, cd2522fcde9823, -, 5 ), + HEX_LDBL( -, d, 2af9397b27ff74d, -, 6 ), HEX_LDBL( -, d, 723f2c2c2409811, -, 6 ), + HEX_LDBL( -, f, ea8f8481ecc3cd1, -, 6 ), HEX_LDBL( -, a, 43fd8a7a646b0b2, -, 5 ), + HEX_LDBL( -, e, 01b0bf63a4e8d76, -, 5 ), HEX_LDBL( -, 9, f0b7096a2a7b4d, -, 4 ), + HEX_LDBL( -, e, 872e7c5a627ab4c, -, 4 ), HEX_LDBL( -, a, dbd760a1882da48, -, 3 ), + HEX_LDBL( -, 8, 424e4dea31dd273, -, 2 ), HEX_LDBL( -, c, c05d7730963e793, -, 2 ), + HEX_LDBL( -, a, 523d97197cd124a, -, 1 ), HEX_LDBL( -, 8, 307ba943978aaee, +, 0 ) } // x - 0.4375 in [ -0x1.0p-4, 0x1.0p-4 ] Error: 0x1.9ecff73da69c9p-66 + }; + + const long double offsets[4] = { 0.0625, 0.1875, 0.3125, 0.4375 }; + const size_t coeff_count = sizeof( coeffs[0] ) / sizeof( coeffs[0][0] ); + + // reduce the incoming values a bit so that they are in the range [-0x1.0p-4, 0x1.0p-4] + const long double *c; + i = x2 * 8.0L; + c = coeffs[i]; + x2 -= offsets[i]; // exact + + // calcualte p(x2) + long double y = c[ coeff_count - 1]; + for( i = (int)coeff_count - 2; i >= 0; i-- ) + y = c[i] + y * x2; + + // xp(x2) + y *= x; + + // return xp(x2) - x + PI/2 + return head + ((y + tail) - x); +} + +double reference_log10(double x) +{ + if( x == 0.0 ) + return -INFINITY; + + if( x < 0.0 ) + return cl_make_nan(); + + if( isinf(x) ) + return INFINITY; + + double log2Hi = HEX_DBL( +, 1, 34413509f79fe, -, 2 ); + double logxHi, logxLo; + __log2_ep(&logxHi, &logxLo, x); + return logxHi*log2Hi; +} + +long double reference_log10l(long double x) +{ + if( x == 0.0 ) + return -INFINITY; + + if( x < 0.0 ) + return cl_make_nan(); + + if( isinf(x) ) + return INFINITY; + + double log2Hi = HEX_DBL( +, 1, 34413509f79fe, -, 2 ); + double log2Lo = HEX_DBL( +, 1, e623e2566b02d, -, 55 ); + double logxHi, logxLo; + __log2_ep(&logxHi, &logxLo, x); + + //double rhi, rlo; + //MulDD(&rhi, &rlo, logxHi, logxLo, log2Hi, log2Lo); + //return (long double) rhi + (long double) rlo; + + long double lg2 = (long double) log2Hi + (long double) log2Lo; + long double logx = (long double) logxHi + (long double) logxLo; + return logx*lg2; +} + +double reference_acos(double x) +{ + return acos( x ); +} + +double reference_atan2(double x, double y) +{ +#if defined(_WIN32) + // fix edge cases for Windows + if (isinf(x) && isinf(y)) { + double retval = (y > 0) ? M_PI_4 : 3.f * M_PI_4; + return (x > 0) ? retval : -retval; + } +#endif // _WIN32 + return atan2(x, y); +} + +long double reference_atan2l(long double x, long double y) +{ +#if defined(_WIN32) + // fix edge cases for Windows + if (isinf(x) && isinf(y)) { + long double retval = (y > 0) ? M_PI_4 : 3.f * M_PI_4; + return (x > 0) ? retval : -retval; + } +#endif // _WIN32 + return atan2l(x, y); +} + +double reference_frexp(double a, int *exp) +{ + if(isnan(a) || isinf(a) || a == 0.0) + { + *exp = 0; + return a; + } + + union { + cl_double d; + cl_ulong l; + } u; + + u.d = a; + + // separate out sign + cl_ulong s = u.l & 0x8000000000000000ULL; + u.l &= 0x7fffffffffffffffULL; + int bias = -1022; + + if((u.l & 0x7ff0000000000000ULL) == 0) + { + double d = u.l; + u.d = d; + bias -= 1074; + } + + int e = (int)((u.l & 0x7ff0000000000000ULL) >> 52); + u.l &= 0x000fffffffffffffULL; + e += bias; + u.l |= ((cl_ulong)1022 << 52); + u.l |= s; + + *exp = e; + return u.d; +} + +long double reference_frexpl(long double a, int *exp) +{ + if(isnan(a) || isinf(a) || a == 0.0) + { + *exp = 0; + return a; + } + + if(sizeof(long double) == sizeof(double)) + { + return reference_frexp(a, exp); + } + else + { + return frexpl(a, exp); + } +} + + +double reference_atan(double x) +{ + return atan( x ); +} + +long double reference_atanl(long double x) +{ + return atanl( x ); +} + +long double reference_asinl(long double x) +{ + return asinl( x ); +} + +double reference_asin(double x) +{ + return asin( x ); +} + +double reference_fabs(double x) +{ + return fabs( x); +} + +double reference_cosh(double x) +{ + return cosh( x ); +} + +long double reference_sqrtl(long double x) +{ +#if defined( __SSE2__ ) || (defined( _MSC_VER ) && (defined(_M_IX86) || defined(_M_X64))) + __m128d result128 = _mm_set_sd((double) x); + result128 = _mm_sqrt_sd(result128, result128); + return _mm_cvtsd_f64(result128); +#else + volatile double dx = x; + return sqrt( dx ); +#endif +} + +long double reference_tanhl(long double x) +{ + return tanhl( x ); +} + +long double reference_floorl(long double x) +{ + if( x == 0.0 || reference_isinfl(x) || reference_isnanl(x) ) + return x; + + long double absx = reference_fabsl(x); + if( absx >= HEX_LDBL( +, 1, 0, +, 52 ) ) + return x; + + if( absx < 1.0 ) + { + if( x < 0.0 ) + return -1.0; + else + return 0.0; + } + + long double r = (long double) ((cl_long) x); + + if( x < 0.0 && r > x ) + r -= 1.0; + + return r; +} + + +double reference_tanh(double x) +{ + return tanh( x ); +} + +long double reference_assignmentl( long double x ){ return x; } + +int reference_notl( long double x ) +{ + int r = !x; + return r; +} + + diff --git a/test_conformance/math_brute_force/reference_math.h b/test_conformance/math_brute_force/reference_math.h new file mode 100644 index 00000000..bcd0df8e --- /dev/null +++ b/test_conformance/math_brute_force/reference_math.h @@ -0,0 +1,232 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef REFERENCE_MATH_H +#define REFERENCE_MATH_H + +#if defined( __APPLE__ ) + #include +#else + #include +#endif + +// -- for testing float -- +double reference_sinh( double x ); +double reference_sqrt( double x ); +double reference_tanh( double x ); +double reference_acos( double ); +double reference_asin( double ); +double reference_atan( double ); +double reference_atan2( double, double ); +double reference_ceil( double ); +double reference_cosh( double ); +double reference_exp( double ); +double reference_fabs( double ); +double reference_acospi( double ); +double reference_asinpi( double ); +double reference_atanpi( double ); +double reference_atan2pi( double, double ); +double reference_cospi( double ); +double reference_divide( double, double ); +double reference_fract( double, double * ); +float reference_fma( float, float, float, int ); +double reference_mad( double, double, double ); +double reference_nextafter(double, double ); +double reference_recip( double ); +double reference_rootn( double, int ); +double reference_rsqrt( double ); +double reference_sincos( double, double * ); +double reference_sinpi( double ); +double reference_tanpi( double ); +double reference_pow(double x, double y); +double reference_pown( double, int ); +double reference_powr( double, double ); +double reference_cos( double ); +double reference_sin( double ); +double reference_tan( double ); +double reference_log( double ); +double reference_log10( double ); +double reference_modf( double, double *n ); + +double reference_fdim( double, double ); +double reference_add( double, double ); +double reference_subtract( double, double ); +double reference_divide( double, double ); +double reference_multiply( double, double ); +double reference_remquo( double, double, int* ); +double reference_lgamma_r( double, int* ); + +int reference_isequal( double, double ); +int reference_isfinite( double ); +int reference_isgreater( double, double ); +int reference_isgreaterequal( double, double ); +int reference_isinf( double ); +int reference_isless( double, double ); +int reference_islessequal( double, double ); +int reference_islessgreater( double, double ); +int reference_isnan( double ); +int reference_isnormal( double ); +int reference_isnotequal( double, double ); +int reference_isordered( double, double ); +int reference_isunordered( double, double ); +int reference_signbit( float ); + +double reference_acosh( double x ); +double reference_asinh( double x ); +double reference_atanh( double x ); +double reference_cbrt(double x); +float reference_copysign( float x, float y); +double reference_copysignd( double x, double y); +double reference_exp10( double ); +double reference_exp2( double x ); +double reference_expm1( double x ); +double reference_fmax( double x, double y ); +double reference_fmin( double x, double y ); +double reference_hypot( double x, double y ); +double reference_lgamma( double x); +int reference_ilogb( double ); +double reference_log2( double x ); +double reference_log1p( double x ); +double reference_logb( double x ); +double reference_maxmag( double x, double y ); +double reference_minmag( double x, double y ); +double reference_nan( cl_uint x ); +double reference_reciprocal( double x ); +double reference_remainder( double x, double y ); +double reference_rint( double x ); +double reference_round( double x ); +double reference_trunc( double x ); +double reference_floor( double x ); +double reference_fmod( double x, double y ); +double reference_frexp( double x, int *n ); +double reference_ldexp( double x, int n ); + +double reference_assignment( double x ); +int reference_not( double x ); +// -- for testing fast-relaxed + +double reference_relaxed_mad( double, double, double ); +double reference_relaxed_divide( double x, double y ); +double reference_relaxed_sin( double x ); +double reference_relaxed_cos( double x ); +double reference_relaxed_sincos( double x, double * y); +double reference_relaxed_tan( double x ); +double reference_relaxed_exp( double x ); +double reference_relaxed_exp2( double x ); +double reference_relaxed_exp10( double x ); +double reference_relaxed_log( double x ); +double reference_relaxed_log2( double x ); +double reference_relaxed_pow( double x, double y); +double reference_relaxed_reciprocal( double x ); + +// -- for testing double -- + +long double reference_sinhl( long double x ); +long double reference_sqrtl( long double x ); +long double reference_tanhl( long double x ); +long double reference_acosl( long double ); +long double reference_asinl( long double ); +long double reference_atanl( long double ); +long double reference_atan2l( long double, long double ); +long double reference_ceill( long double ); +long double reference_coshl( long double ); +long double reference_expl( long double ); +long double reference_fabsl( long double ); +long double reference_acospil( long double ); +long double reference_asinpil( long double ); +long double reference_atanpil( long double ); +long double reference_atan2pil( long double, long double ); +long double reference_cospil( long double ); +long double reference_dividel( long double, long double ); +long double reference_fractl( long double, long double * ); +long double reference_fmal( long double, long double, long double ); +long double reference_madl( long double, long double, long double ); +long double reference_nextafterl(long double, long double ); +long double reference_recipl( long double ); +long double reference_rootnl( long double, int ); +long double reference_rsqrtl( long double ); +long double reference_sincosl( long double, long double * ); +long double reference_sinpil( long double ); +long double reference_tanpil( long double ); +long double reference_powl(long double x, long double y); +long double reference_pownl( long double, int ); +long double reference_powrl( long double, long double ); +long double reference_cosl( long double ); +long double reference_sinl(long double ); +long double reference_tanl( long double ); +long double reference_logl( long double ); +long double reference_log10l( long double ); +long double reference_modfl( long double, long double *n ); + + +long double reference_fdiml( long double, long double ); +long double reference_addl( long double, long double ); +long double reference_subtractl( long double, long double ); +long double reference_dividel( long double, long double ); +long double reference_multiplyl( long double, long double ); +long double reference_remquol( long double, long double, int* ); +long double reference_lgamma_rl( long double, int* ); + + +int reference_isequall( long double, long double ); +int reference_isfinitel( long double ); +int reference_isgreaterl( long double, long double ); +int reference_isgreaterequall( long double, long double ); +int reference_isinfl( long double ); +int reference_islessl( long double, long double ); +int reference_islessequall( long double, long double ); +int reference_islessgreaterl( long double, long double ); +int reference_isnanl( long double ); +int reference_isnormall( long double ); +int reference_isnotequall( long double, long double ); +int reference_isorderedl( long double, long double ); +int reference_isunorderedl( long double, long double ); +int reference_signbitl( long double ); + +long double reference_acoshl( long double x ); +long double reference_asinhl( long double x ); +long double reference_atanhl( long double x ); +long double reference_cbrtl(long double x); +long double reference_copysignl( long double x, long double y); +long double reference_exp10l( long double ); +long double reference_exp2l( long double x ); +long double reference_expm1l( long double x ); +long double reference_fmaxl( long double x, long double y ); +long double reference_fminl( long double x, long double y ); +long double reference_hypotl( long double x, long double y ); +long double reference_lgammal( long double x); +int reference_ilogbl( long double ); +long double reference_log2l( long double x ); +long double reference_log1pl( long double x ); +long double reference_logbl( long double x ); +long double reference_maxmagl( long double x, long double y ); +long double reference_minmagl( long double x, long double y ); +long double reference_nanl( cl_ulong x ); +long double reference_reciprocall( long double x ); +long double reference_remainderl( long double x, long double y ); +long double reference_rintl( long double x ); +long double reference_roundl( long double x ); +long double reference_truncl( long double x ); +long double reference_floorl( long double x ); +long double reference_fmodl( long double x, long double y ); +long double reference_frexpl( long double x, int *n ); +long double reference_ldexpl( long double x, int n ); + +long double reference_assignmentl( long double x ); +int reference_notl( long double x ); + +#endif + + diff --git a/test_conformance/math_brute_force/run_math_brute_force_in_parallel.py b/test_conformance/math_brute_force/run_math_brute_force_in_parallel.py new file mode 100644 index 00000000..51c49ad2 --- /dev/null +++ b/test_conformance/math_brute_force/run_math_brute_force_in_parallel.py @@ -0,0 +1,110 @@ +#! /usr/bin/python + +# // OpenCL Conformance Tests +# // +# // Copyright: (c) 2009-2013 by Apple Inc. All Rights Reserved. +# // + +import os, re, sys, subprocess, time + +# A script to run the entierty of math_brute_force, but to run each separate job in parallel. + +def DEBUG(text, level=1): + if (DEBUG_LEVEL >= level): print(text) + +def write_info(text): + print text, + if (ATF): + ATF_log.write(""+text+"\n") + ATF_log.flush() + +def write_error(text): + print "ERROR:" + text, + if (ATF): + ATF_log.write(""+text+"\n") + ATF_log.flush() + +def start_atf(): + global ATF, ATF_log + DEBUG("start_atf()") + if (os.environ.get("ATF_RESULTSDIRECTORY") == None): + ATF = False + DEBUG("\tATF not defined",0) + return + ATF = True + ATF_output_file_name = "TestLog.xml" + output_path = os.environ.get("ATF_RESULTSDIRECTORY") + try: + ATF_log = open(output_path+ATF_output_file_name, "w") + except IOError: + DEBUG("Could not open ATF file " + ATF_output_file_name, 0) + ATF = False + return + DEBUG("ATF Enabled") + # Generate the XML header + ATF_log.write("\n") + ATF_log.write("\n") + DEBUG("Done start_atf()") + +def stop_atf(): + DEBUG("stop_atf()") + if (ATF): + ATF.write("\n") + ATF.write("\n") + ATF.close() + +def get_time() : + return time.strftime("%A %H:%M:%S", time.localtime()) + +def start_test(id): + DEBUG("start_test("+str(id) + ")") + command = test + " " + str(id) + " " + str(id) + try: + write_info(get_time() + " Executing " + command + "...") + p = subprocess.Popen(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) + except OSError: + write_error("Failed to execute " + command) + return + running_tests[id] = p + DEBUG("start_test("+str(id) + ") added: " + str(running_tests[id]) + \ + ", now " + str(len(running_tests.keys())) + " tests running") + + + + +DEBUG_LEVEL = 2 +test = "./bruteforce -w" +instances = 4 +max_test_ID = 12 +running_tests = {} +ATF_log = None +ATF = False + +# Start the ATF log +start_atf() +next_test = 0 +next_test_to_finish = 0 + +while ( (next_test <= max_test_ID) | (next_test_to_finish <= max_test_ID)): + # If we want to run more tests, start them + while ((len(running_tests.keys()) < instances) & (next_test <= max_test_ID)): + start_test(next_test) + next_test = next_test + 1 + time.sleep(1) + # Check if the oldest test has finished + p = running_tests[next_test_to_finish] + if (p.poll() != None): + write_info(get_time() + " Test " + str(next_test_to_finish) +" finished.") + del running_tests[next_test_to_finish] + next_test_to_finish = next_test_to_finish + 1 + # Write the results from the test out + for line in p.stdout.readlines(): + write_info(line) + for line in p.stderr.readlines(): + write_error(line) + + time.sleep(1) + + +# Stop the ATF log +stop_atf() diff --git a/test_conformance/math_brute_force/ternary.c b/test_conformance/math_brute_force/ternary.c new file mode 100644 index 00000000..a90271d9 --- /dev/null +++ b/test_conformance/math_brute_force/ternary.c @@ -0,0 +1,1361 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Utility.h" + +#include +#include "FunctionList.h" + +#define CORRECTLY_ROUNDED 0 +#define FLUSHED 1 + +int TestFunc_Float_Float_Float_Float(const Func *f, MTdata); +int TestFunc_Double_Double_Double_Double(const Func *f, MTdata); + +#if defined( __cplusplus) +extern "C" +#endif +const vtbl _ternary = { "ternary", TestFunc_Float_Float_Float_Float, TestFunc_Double_Double_Double_Double }; + +static int BuildKernel( const char *name, int vectorSize, cl_kernel *k, cl_program *p ); +static int BuildKernelDouble( const char *name, int vectorSize, cl_kernel *k, cl_program *p ); +static int BuildKernel( const char *name, int vectorSize, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { + "__kernel void math_kernel", sizeNames[vectorSize], "( __global float", sizeNames[vectorSize], "* out, __global float", sizeNames[vectorSize], "* in1, __global float", sizeNames[vectorSize], "* in2, __global float", sizeNames[vectorSize], "* in3 )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in1[i], in2[i], in3[i] );\n" + "}\n" + }; + + const char *c3[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global float* out, __global float* in, __global float* in2 , __global float* in3)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " float3 f0 = vload3( 0, in + 3 * i );\n" + " float3 f1 = vload3( 0, in2 + 3 * i );\n" + " float3 f2 = vload3( 0, in3 + 3 * i );\n" + " f0 = ", name, "( f0, f1, f2 );\n" + " vstore3( f0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " float3 f0, f1, f2;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (float3)( in[3*i], NAN, NAN ); \n" + " f1 = (float3)( in2[3*i], NAN, NAN ); \n" + " f2 = (float3)( in3[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " f0 = (float3)( in[3*i], in[3*i+1], NAN ); \n" + " f1 = (float3)( in2[3*i], in2[3*i+1], NAN ); \n" + " f2 = (float3)( in3[3*i], in3[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " f0 = ", name, "( f0, f1, f2 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = f0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = f0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernel(kern, (cl_uint) kernSize, testName, k, p); + +} + +static int BuildKernelDouble( const char *name, int vectorSize, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double", sizeNames[vectorSize], "* out, __global double", sizeNames[vectorSize], "* in1, __global double", sizeNames[vectorSize], "* in2, __global double", sizeNames[vectorSize], "* in3 )\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in1[i], in2[i], in3[i] );\n" + "}\n" + }; + + const char *c3[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double* out, __global double* in, __global double* in2 , __global double* in3)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " double3 d0 = vload3( 0, in + 3 * i );\n" + " double3 d1 = vload3( 0, in2 + 3 * i );\n" + " double3 d2 = vload3( 0, in3 + 3 * i );\n" + " d0 = ", name, "( d0, d1, d2 );\n" + " vstore3( d0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " double3 d0, d1, d2;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " d0 = (double3)( in[3*i], NAN, NAN ); \n" + " d1 = (double3)( in2[3*i], NAN, NAN ); \n" + " d2 = (double3)( in3[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " d0 = (double3)( in[3*i], in[3*i+1], NAN ); \n" + " d1 = (double3)( in2[3*i], in2[3*i+1], NAN ); \n" + " d2 = (double3)( in3[3*i], in3[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " d0 = ", name, "( d0, d1, d2 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = d0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = d0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernel(kern, (cl_uint) kernSize, testName, k, p); + +} + +typedef struct BuildKernelInfo +{ + cl_uint offset; // the first vector size to build + cl_kernel *kernels; + cl_program *programs; + const char *nameInCode; +}BuildKernelInfo; + +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernel( info->nameInCode, i, info->kernels + i, info->programs + i ); +} + +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernelDouble( info->nameInCode, i, info->kernels + i, info->programs + i ); +} + + +// A table of more difficult cases to get right +static const float specialValuesFloat[] = { + -NAN, -INFINITY, -FLT_MAX, MAKE_HEX_FLOAT(-0x1.000002p64f, -0x1000002L, 40), MAKE_HEX_FLOAT(-0x1.0p64f, -0x1L, 64), MAKE_HEX_FLOAT(-0x1.fffffep63f, -0x1fffffeL, 39), MAKE_HEX_FLOAT(-0x1.000002p63f, -0x1000002L, 39), MAKE_HEX_FLOAT(-0x1.0p63f, -0x1L, 63), MAKE_HEX_FLOAT(-0x1.fffffep62f, -0x1fffffeL, 38), + -3.0f, MAKE_HEX_FLOAT(-0x1.800002p1f, -0x1800002L, -23), -2.5f, MAKE_HEX_FLOAT(-0x1.7ffffep1f, -0x17ffffeL, -23), -2.0f, MAKE_HEX_FLOAT(-0x1.800002p0f, -0x1800002L, -24), -1.75f, -1.5f, -1.25f, MAKE_HEX_FLOAT(-0x1.7ffffep0f, -0x17ffffeL, -24), MAKE_HEX_FLOAT(-0x1.000002p0f, -0x1000002L, -24), MAKE_HEX_FLOAT(-0x1.003p0f, -0x1003000L, -24), -MAKE_HEX_FLOAT(0x1.001p0f, 0x1001000L, -24), -1.0f, MAKE_HEX_FLOAT(-0x1.fffffep-1f, -0x1fffffeL, -25), + MAKE_HEX_FLOAT(-0x1.000002p-126f, -0x1000002L, -150), -FLT_MIN, MAKE_HEX_FLOAT(-0x0.fffffep-126f, -0x0fffffeL, -150), MAKE_HEX_FLOAT(-0x0.000ffep-126f, -0x0000ffeL, -150), MAKE_HEX_FLOAT(-0x0.0000fep-126f, -0x00000feL, -150), MAKE_HEX_FLOAT(-0x0.00000ep-126f, -0x000000eL, -150), MAKE_HEX_FLOAT(-0x0.00000cp-126f, -0x000000cL, -150), MAKE_HEX_FLOAT(-0x0.00000ap-126f, -0x000000aL, -150), + MAKE_HEX_FLOAT(-0x0.000008p-126f, -0x0000008L, -150), MAKE_HEX_FLOAT(-0x0.000006p-126f, -0x0000006L, -150), MAKE_HEX_FLOAT(-0x0.000004p-126f, -0x0000004L, -150), MAKE_HEX_FLOAT(-0x0.000002p-126f, -0x0000002L, -150), -0.0f, + + +NAN, +INFINITY, +FLT_MAX, MAKE_HEX_FLOAT(+0x1.000002p64f, +0x1000002L, 40), MAKE_HEX_FLOAT(+0x1.0p64f, +0x1L, 64), MAKE_HEX_FLOAT(+0x1.fffffep63f, +0x1fffffeL, 39), MAKE_HEX_FLOAT(+0x1.000002p63f, +0x1000002L, 39), MAKE_HEX_FLOAT(+0x1.0p63f, +0x1L, 63), MAKE_HEX_FLOAT(+0x1.fffffep62f, +0x1fffffeL, 38), + +3.0f, MAKE_HEX_FLOAT(+0x1.800002p1f, +0x1800002L, -23), 2.5f, MAKE_HEX_FLOAT(+0x1.7ffffep1f, +0x17ffffeL, -23),+2.0f, MAKE_HEX_FLOAT(+0x1.800002p0f, +0x1800002L, -24), 1.75f, 1.5f, 1.25f, MAKE_HEX_FLOAT(+0x1.7ffffep0f, +0x17ffffeL, -24), MAKE_HEX_FLOAT(+0x1.000002p0f, +0x1000002L, -24), MAKE_HEX_FLOAT(0x1.003p0f, 0x1003000L, -24), +MAKE_HEX_FLOAT(0x1.001p0f, 0x1001000L, -24), +1.0f, MAKE_HEX_FLOAT(+0x1.fffffep-1f, +0x1fffffeL, -25), + MAKE_HEX_FLOAT(0x1.000002p-126f, 0x1000002L, -150), +FLT_MIN, MAKE_HEX_FLOAT(+0x0.fffffep-126f, +0x0fffffeL, -150), MAKE_HEX_FLOAT(+0x0.000ffep-126f, +0x0000ffeL, -150), MAKE_HEX_FLOAT(+0x0.0000fep-126f, +0x00000feL, -150), MAKE_HEX_FLOAT(+0x0.00000ep-126f, +0x000000eL, -150), MAKE_HEX_FLOAT(+0x0.00000cp-126f, +0x000000cL, -150), MAKE_HEX_FLOAT(+0x0.00000ap-126f, +0x000000aL, -150), + MAKE_HEX_FLOAT(+0x0.000008p-126f, +0x0000008L, -150), MAKE_HEX_FLOAT(+0x0.000006p-126f, +0x0000006L, -150), MAKE_HEX_FLOAT(+0x0.000004p-126f, +0x0000004L, -150), MAKE_HEX_FLOAT(+0x0.000002p-126f, +0x0000002L, -150), +0.0f +}; + +static size_t specialValuesFloatCount = sizeof( specialValuesFloat ) / sizeof( specialValuesFloat[0] ); + + +int TestFunc_Float_Float_Float_Float(const Func *f, MTdata d) +{ + uint64_t i; + uint32_t j, k; + int error; + cl_program programs[ VECTOR_SIZE_COUNT ]; + cl_kernel kernels[ VECTOR_SIZE_COUNT ]; + float maxError = 0.0f; + int ftz = f->ftz || gForceFTZ || 0 == (CL_FP_DENORM & gFloatCapabilities); + float maxErrorVal = 0.0f; + float maxErrorVal2 = 0.0f; + float maxErrorVal3 = 0.0f; + size_t bufferSize = (gWimpyMode)? gWimpyBufferSize: BUFFER_SIZE; + + uint64_t step = bufferSize / sizeof( float ); + int skipNanInf = (0 == strcmp( "fma", f->nameInCode )) && ! gInfNanSupport; + cl_uchar overflow[BUFFER_SIZE / sizeof( float )]; + float float_ulps; + + logFunctionInfo(f->name,sizeof(cl_float),gTestFastRelaxed); + if( gWimpyMode ) + { + step = (1ULL<<32) * gWimpyReductionFactor / (512); + } + + if( gIsEmbedded ) + float_ulps = f->float_embedded_ulps; + else + float_ulps = f->float_ulps; + + // Init the kernels + BuildKernelInfo build_info = { gMinVectorSizeIndex, kernels, programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_FloatFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + return error; + /* + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + if( (error = BuildKernel( f->nameInCode, (int) i, kernels + i, programs + i) ) ) + return error; + */ + + for( i = 0; i < (1ULL<<32); i += step ) + { + //Init input array + uint32_t *p = (uint32_t *)gIn; + uint32_t *p2 = (uint32_t *)gIn2; + uint32_t *p3 = (uint32_t *)gIn3; + j = 0; + if( i == 0 ) + { // test edge cases + float *fp = (float *)gIn; + float *fp2 = (float *)gIn2; + float *fp3 = (float *)gIn3; + uint32_t x, y, z; x = y = z = 0; + for( ; j < bufferSize / sizeof( float ); j++ ) + { + fp[j] = specialValuesFloat[x]; + fp2[j] = specialValuesFloat[y]; + fp3[j] = specialValuesFloat[z]; + + if( ++x >= specialValuesFloatCount ) + { + x = 0; + if( ++y >= specialValuesFloatCount ) + { + y = 0; + if( ++z >= specialValuesFloatCount ) + break; + } + } + } + if( j == bufferSize / sizeof( float ) ) + vlog_error( "Test Error: not all special cases tested!\n" ); + } + + for( ; j < bufferSize / sizeof( float ); j++ ) + { + p[j] = genrand_int32(d); + p2[j] = genrand_int32(d); + p3[j] = genrand_int32(d); + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, bufferSize, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer3, CL_FALSE, 0, bufferSize, gIn3, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer3 ***\n", error ); + return error; + } + + // write garbage into output arrays + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + uint32_t pattern = 0xffffdead; + memset_pattern4(gOut[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer[j], CL_FALSE, 0, bufferSize, gOut[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2(%d) ***\n", error, j ); + goto exit; + } + } + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_float ) * sizeValues[j]; + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; // bufferSize / vectorSize rounded up + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 3, sizeof( gInBuffer3 ), &gInBuffer3 ) )) { LogBuildError(programs[j]); goto exit; } + + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(gQueue) )) + vlog( "clFlush failed\n" ); + + //Calculate the correctly rounded reference result + float *r = (float *)gOut_Ref; + float *s = (float *)gIn; + float *s2 = (float *)gIn2; + float *s3 = (float *)gIn3; + if( skipNanInf ) + { + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + feclearexcept(FE_OVERFLOW); + r[j] = (float) f->func.f_fma( s[j], s2[j], s3[j], CORRECTLY_ROUNDED ); + overflow[j] = FE_OVERFLOW == (FE_OVERFLOW & fetestexcept(FE_OVERFLOW)); + } + } + else + { + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + r[j] = (float) f->func.f_fma( s[j], s2[j], s3[j], CORRECTLY_ROUNDED ); + } + + + // Read the data back + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0, bufferSize, gOut[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray failed %d\n", error ); + goto exit; + } + } + + if( gSkipCorrectnessTesting ) + break; + + //Verify data + uint32_t *t = (uint32_t *)gOut_Ref; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + uint32_t *q = (uint32_t *)(gOut[k]); + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + float err; + int fail; + float test = ((float*) q)[j]; + float correct = f->func.f_fma( s[j], s2[j], s3[j], CORRECTLY_ROUNDED ); + + // Per section 10 paragraph 6, accept any result if an input or output is a infinity or NaN or overflow + if( skipNanInf ) + { + if( overflow[j] || + IsFloatInfinity(correct) || IsFloatNaN(correct) || + IsFloatInfinity(s[j]) || IsFloatNaN(s[j]) || + IsFloatInfinity(s2[j]) || IsFloatNaN(s2[j]) || + IsFloatInfinity(s3[j]) || IsFloatNaN(s3[j]) ) + continue; + } + + + err = Ulp_Error( test, correct ); + fail = ! (fabsf(err) <= float_ulps); + + if( fail && ftz ) + { + float correct2, err2; + + // retry per section 6.5.3.2 with flushing on + if( 0.0f == test && 0.0f == f->func.f_fma( s[j], s2[j], s3[j], FLUSHED ) ) + { + fail = 0; + err = 0.0f; + } + + // retry per section 6.5.3.3 + if( fail && IsFloatSubnormal( s[j] ) ) + { // look at me, + float err3, correct3; + + if( skipNanInf ) + feclearexcept( FE_OVERFLOW ); + + correct2 = f->func.f_fma( 0.0f, s2[j], s3[j], CORRECTLY_ROUNDED ); + correct3 = f->func.f_fma( -0.0f, s2[j], s3[j], CORRECTLY_ROUNDED ); + + if( skipNanInf ) + { + if( fetestexcept( FE_OVERFLOW ) ) + continue; + + // Note: no double rounding here. Reference functions calculate in single precision. + if( IsFloatInfinity(correct2) || IsFloatNaN(correct2) || + IsFloatInfinity(correct3) || IsFloatNaN(correct3) ) + continue; + } + + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= float_ulps)) && (!(fabsf(err3) <= float_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( 0.0f == test && + ( 0.0f == f->func.f_fma( 0.0f, s2[j], s3[j], FLUSHED ) || + 0.0f == f->func.f_fma( -0.0f, s2[j], s3[j], FLUSHED ) ) + ) + { + fail = 0; + err = 0.0f; + } + + //try with first two args as zero + if( IsFloatSubnormal( s2[j] ) ) + { // its fun to have fun, + double correct4, correct5; + float err4, err5; + + if( skipNanInf ) + feclearexcept( FE_OVERFLOW ); + + correct2 = f->func.f_fma( 0.0f, 0.0f, s3[j], CORRECTLY_ROUNDED ); + correct3 = f->func.f_fma( -0.0f, 0.0f, s3[j], CORRECTLY_ROUNDED ); + correct4 = f->func.f_fma( 0.0f, -0.0f, s3[j], CORRECTLY_ROUNDED ); + correct5 = f->func.f_fma( -0.0f, -0.0f, s3[j], CORRECTLY_ROUNDED ); + + // Per section 10 paragraph 6, accept any result if an input or output is a infinity or NaN or overflow + if( !gInfNanSupport ) + { + if( fetestexcept(FE_OVERFLOW) ) + continue; + + // Note: no double rounding here. Reference functions calculate in single precision. + if( IsFloatInfinity(correct2) || IsFloatNaN(correct2) || + IsFloatInfinity(correct3) || IsFloatNaN(correct3) || + IsFloatInfinity(correct4) || IsFloatNaN(correct4) || + IsFloatInfinity(correct5) || IsFloatNaN(correct5) ) + continue; + } + + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + err4 = Ulp_Error( test, correct4 ); + err5 = Ulp_Error( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= float_ulps)) && (!(fabsf(err3) <= float_ulps)) && + (!(fabsf(err4) <= float_ulps)) && (!(fabsf(err5) <= float_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( 0.0f == test && + ( 0.0f == f->func.f_fma( 0.0f, 0.0f, s3[j], FLUSHED ) || + 0.0f == f->func.f_fma( -0.0f, 0.0f, s3[j], FLUSHED ) || + 0.0f == f->func.f_fma( 0.0f, -0.0f, s3[j], FLUSHED ) || + 0.0f == f->func.f_fma( -0.0f, -0.0f, s3[j], FLUSHED ) ) + ) + { + fail = 0; + err = 0.0f; + } + + if( IsFloatSubnormal( s3[j] ) ) + { + if( test == 0.0f ) // 0*0+0 is 0 + { + fail = 0; + err = 0.0f; + } + } + } + else if( IsFloatSubnormal( s3[j] ) ) + { + double correct4, correct5; + float err4, err5; + + if( skipNanInf ) + feclearexcept( FE_OVERFLOW ); + + correct2 = f->func.f_fma( 0.0f, s2[j], 0.0f, CORRECTLY_ROUNDED ); + correct3 = f->func.f_fma( -0.0f, s2[j], 0.0f, CORRECTLY_ROUNDED ); + correct4 = f->func.f_fma( 0.0f, s2[j], -0.0f, CORRECTLY_ROUNDED ); + correct5 = f->func.f_fma( -0.0f, s2[j], -0.0f, CORRECTLY_ROUNDED ); + + // Per section 10 paragraph 6, accept any result if an input or output is a infinity or NaN or overflow + if( !gInfNanSupport ) + { + if( fetestexcept(FE_OVERFLOW) ) + continue; + + // Note: no double rounding here. Reference functions calculate in single precision. + if( IsFloatInfinity(correct2) || IsFloatNaN(correct2) || + IsFloatInfinity(correct3) || IsFloatNaN(correct3) || + IsFloatInfinity(correct4) || IsFloatNaN(correct4) || + IsFloatInfinity(correct5) || IsFloatNaN(correct5) ) + continue; + } + + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + err4 = Ulp_Error( test, correct4 ); + err5 = Ulp_Error( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= float_ulps)) && (!(fabsf(err3) <= float_ulps)) && + (!(fabsf(err4) <= float_ulps)) && (!(fabsf(err5) <= float_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( 0.0f == test && + ( 0.0f == f->func.f_fma( 0.0f, s2[j], 0.0f, FLUSHED ) || + 0.0f == f->func.f_fma(-0.0f, s2[j], 0.0f, FLUSHED ) || + 0.0f == f->func.f_fma( 0.0f, s2[j],-0.0f, FLUSHED ) || + 0.0f == f->func.f_fma(-0.0f, s2[j],-0.0f, FLUSHED ) ) + ) + { + fail = 0; + err = 0.0f; + } + } + } + else if( fail && IsFloatSubnormal( s2[j] ) ) + { + double correct2, correct3; + float err2, err3; + + if( skipNanInf ) + feclearexcept( FE_OVERFLOW ); + + correct2 = f->func.f_fma( s[j], 0.0f, s3[j], CORRECTLY_ROUNDED ); + correct3 = f->func.f_fma( s[j], -0.0f, s3[j], CORRECTLY_ROUNDED ); + + if( skipNanInf ) + { + if( fetestexcept( FE_OVERFLOW ) ) + continue; + + // Note: no double rounding here. Reference functions calculate in single precision. + if( IsFloatInfinity(correct2) || IsFloatNaN(correct2) || + IsFloatInfinity(correct3) || IsFloatNaN(correct3) ) + continue; + } + + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= float_ulps)) && (!(fabsf(err3) <= float_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( 0.0f == test && + ( 0.0f == f->func.f_fma( s[j], 0.0f, s3[j], FLUSHED ) || + 0.0f == f->func.f_fma( s[j], -0.0f, s3[j], FLUSHED ) ) + ) + { + fail = 0; + err = 0.0f; + } + + //try with second two args as zero + if( IsFloatSubnormal( s3[j] ) ) + { + double correct4, correct5; + float err4, err5; + + if( skipNanInf ) + feclearexcept( FE_OVERFLOW ); + + correct2 = f->func.f_fma( s[j], 0.0f, 0.0f, CORRECTLY_ROUNDED ); + correct3 = f->func.f_fma( s[j], -0.0f, 0.0f, CORRECTLY_ROUNDED ); + correct4 = f->func.f_fma( s[j], 0.0f, -0.0f, CORRECTLY_ROUNDED ); + correct5 = f->func.f_fma( s[j], -0.0f, -0.0f, CORRECTLY_ROUNDED ); + + // Per section 10 paragraph 6, accept any result if an input or output is a infinity or NaN or overflow + if( !gInfNanSupport ) + { + if( fetestexcept(FE_OVERFLOW) ) + continue; + + // Note: no double rounding here. Reference functions calculate in single precision. + if( IsFloatInfinity(correct2) || IsFloatNaN(correct2) || + IsFloatInfinity(correct3) || IsFloatNaN(correct3) || + IsFloatInfinity(correct4) || IsFloatNaN(correct4) || + IsFloatInfinity(correct5) || IsFloatNaN(correct5) ) + continue; + } + + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + err4 = Ulp_Error( test, correct4 ); + err5 = Ulp_Error( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= float_ulps)) && (!(fabsf(err3) <= float_ulps)) && + (!(fabsf(err4) <= float_ulps)) && (!(fabsf(err5) <= float_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( 0.0f == test && + ( 0.0f == f->func.f_fma( s[j], 0.0f, 0.0f, FLUSHED ) || + 0.0f == f->func.f_fma( s[j],-0.0f, 0.0f, FLUSHED ) || + 0.0f == f->func.f_fma( s[j], 0.0f,-0.0f, FLUSHED ) || + 0.0f == f->func.f_fma( s[j],-0.0f,-0.0f, FLUSHED ) ) + ) + { + fail = 0; + err = 0.0f; + } + } + } + else if( fail && IsFloatSubnormal(s3[j]) ) + { + double correct2, correct3; + float err2, err3; + + if( skipNanInf ) + feclearexcept( FE_OVERFLOW ); + + correct2 = f->func.f_fma( s[j], s2[j], 0.0f, CORRECTLY_ROUNDED ); + correct3 = f->func.f_fma( s[j], s2[j], -0.0f, CORRECTLY_ROUNDED ); + + if( skipNanInf ) + { + if( fetestexcept( FE_OVERFLOW ) ) + continue; + + // Note: no double rounding here. Reference functions calculate in single precision. + if( IsFloatInfinity(correct2) || IsFloatNaN(correct2) || + IsFloatInfinity(correct3) || IsFloatNaN(correct3) ) + continue; + } + + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= float_ulps)) && (!(fabsf(err3) <= float_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( 0.0f == test && + ( 0.0f == f->func.f_fma( s[j], s2[j], 0.0f, FLUSHED ) || + 0.0f == f->func.f_fma( s[j], s2[j],-0.0f, FLUSHED ) ) + ) + { + fail = 0; + err = 0.0f; + } + } + } + + if( fabsf(err ) > maxError ) + { + maxError = fabsf(err); + maxErrorVal = s[j]; + maxErrorVal2 = s2[j]; + maxErrorVal3 = s3[j]; + } + + if( fail ) + { + vlog_error( "\nERROR: %s%s: %f ulp error at {%a, %a, %a} ({0x%8.8x, 0x%8.8x, 0x%8.8x}): *%a vs. %a\n", f->name, sizeNames[k], err, s[j], s2[j], s3[j], ((cl_uint*)s)[j], ((cl_uint*)s2)[j], ((cl_uint*)s3)[j], ((float*) gOut_Ref)[j], test ); + error = -1; + goto exit; + } + } + } + } + + if( 0 == (i & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10u bufferSize:%10zd \n", i, step, bufferSize); + } else + { + vlog("." ); + } + fflush(stdout); + } + } + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input array + uint32_t *p = (uint32_t *)gIn; + uint32_t *p2 = (uint32_t *)gIn2; + uint32_t *p3 = (uint32_t *)gIn3; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + p[j] = genrand_int32(d); + p2[j] = genrand_int32(d); + p3[j] = genrand_int32(d); + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, bufferSize, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer3, CL_FALSE, 0, bufferSize, gIn3, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer3 ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_float ) * sizeValues[j]; + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; // bufferSize / vectorSize rounded up + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 3, sizeof( gInBuffer3 ), &gInBuffer3 ) )) { LogBuildError(programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( k = 0; k < PERF_LOOP_COUNT; k++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (bufferSize / sizeof( float ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sf%s", f->name, sizeNames[j] ); + } + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t%8.2f @ {%a, %a, %a}", maxError, maxErrorVal, maxErrorVal2, maxErrorVal3 ); + vlog( "\n" ); + +exit: + // Release + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + clReleaseKernel(kernels[k]); + clReleaseProgram(programs[k]); + } + + return error; +} + +// A table of more difficult cases to get right +static const double specialValuesDouble[] = { + -NAN, -INFINITY, -DBL_MAX, MAKE_HEX_DOUBLE(-0x1.0000000000001p64, -0x10000000000001LL, 12), MAKE_HEX_DOUBLE(-0x1.0p64, -0x1LL, 64), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp63, -0x1fffffffffffffLL, 11), MAKE_HEX_DOUBLE(-0x1.0000000000001p63, -0x10000000000001LL, 11), MAKE_HEX_DOUBLE(-0x1.0p63, -0x1LL, 63), MAKE_HEX_DOUBLE(-0x1.fffffffffffffp62, -0x1fffffffffffffLL, 10), + -3.0, MAKE_HEX_DOUBLE(-0x1.8000000000001p1, -0x18000000000001LL, -51), -2.5, MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp1, -0x17ffffffffffffLL, -51), -2.0, MAKE_HEX_DOUBLE(-0x1.8000000000001p0, -0x18000000000001LL, -52), -1.5, MAKE_HEX_DOUBLE(-0x1.7ffffffffffffp0, -0x17ffffffffffffLL, -52),MAKE_HEX_DOUBLE(-0x1.0000000000001p0, -0x10000000000001LL, -52), -1.0, MAKE_HEX_DOUBLE(-0x1.fffffffffffffp-1, -0x1fffffffffffffLL, -53), + MAKE_HEX_DOUBLE(-0x1.0000000000001p-1022, -0x10000000000001LL, -1074), -DBL_MIN, MAKE_HEX_DOUBLE(-0x0.fffffffffffffp-1022, -0x0fffffffffffffLL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000fffp-1022, -0x00000000000fffLL, -1074), MAKE_HEX_DOUBLE(-0x0.00000000000fep-1022, -0x000000000000feLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000ep-1022, -0x0000000000000eLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000cp-1022, -0x0000000000000cLL, -1074), MAKE_HEX_DOUBLE(-0x0.000000000000ap-1022, -0x0000000000000aLL, -1074), + MAKE_HEX_DOUBLE(-0x0.0000000000003p-1022, -0x00000000000003LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000002p-1022, -0x00000000000002LL, -1074), MAKE_HEX_DOUBLE(-0x0.0000000000001p-1022, -0x00000000000001LL, -1074), -0.0, + + +NAN, +INFINITY, +DBL_MAX, MAKE_HEX_DOUBLE(+0x1.0000000000001p64, +0x10000000000001LL, 12), MAKE_HEX_DOUBLE(+0x1.0p64, +0x1LL, 64), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp63, +0x1fffffffffffffLL, 11), MAKE_HEX_DOUBLE(+0x1.0000000000001p63, +0x10000000000001LL, 11), MAKE_HEX_DOUBLE(+0x1.0p63, +0x1LL, 63), MAKE_HEX_DOUBLE(+0x1.fffffffffffffp62, +0x1fffffffffffffLL, 10), + +3.0, MAKE_HEX_DOUBLE(+0x1.8000000000001p1, +0x18000000000001LL, -51), +2.5, MAKE_HEX_DOUBLE(+0x1.7ffffffffffffp1, +0x17ffffffffffffLL, -51), +2.0, MAKE_HEX_DOUBLE(+0x1.8000000000001p0, +0x18000000000001LL, -52), +1.5, MAKE_HEX_DOUBLE(+0x1.7ffffffffffffp0, +0x17ffffffffffffLL, -52),MAKE_HEX_DOUBLE(-0x1.0000000000001p0, -0x10000000000001LL, -52), +1.0, MAKE_HEX_DOUBLE(+0x1.fffffffffffffp-1, +0x1fffffffffffffLL, -53), + MAKE_HEX_DOUBLE(+0x1.0000000000001p-1022, +0x10000000000001LL, -1074), +DBL_MIN, MAKE_HEX_DOUBLE(+0x0.fffffffffffffp-1022, +0x0fffffffffffffLL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000fffp-1022, +0x00000000000fffLL, -1074), MAKE_HEX_DOUBLE(+0x0.00000000000fep-1022, +0x000000000000feLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000ep-1022, +0x0000000000000eLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000cp-1022, +0x0000000000000cLL, -1074), MAKE_HEX_DOUBLE(+0x0.000000000000ap-1022, +0x0000000000000aLL, -1074), + MAKE_HEX_DOUBLE(+0x0.0000000000003p-1022, +0x00000000000003LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000002p-1022, +0x00000000000002LL, -1074), MAKE_HEX_DOUBLE(+0x0.0000000000001p-1022, +0x00000000000001LL, -1074), +0.0, +}; + +static const size_t specialValuesDoubleCount = sizeof( specialValuesDouble ) / sizeof( specialValuesDouble[0] ); + + +int TestFunc_Double_Double_Double_Double(const Func *f, MTdata d) +{ + uint64_t i; + uint32_t j, k; + int error; + cl_program programs[ VECTOR_SIZE_COUNT ]; + cl_kernel kernels[ VECTOR_SIZE_COUNT ]; + float maxError = 0.0f; + int ftz = f->ftz || gForceFTZ; + double maxErrorVal = 0.0f; + double maxErrorVal2 = 0.0f; + double maxErrorVal3 = 0.0f; + logFunctionInfo(f->name,sizeof(cl_double),gTestFastRelaxed); + + size_t bufferSize = (gWimpyMode)? gWimpyBufferSize: BUFFER_SIZE; + uint64_t step = bufferSize / sizeof( double ); + if( gWimpyMode ) + { + step = (1ULL<<32) * gWimpyReductionFactor / (512); + } + + Force64BitFPUPrecision(); + + // Init the kernels + BuildKernelInfo build_info = { gMinVectorSizeIndex, kernels, programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_DoubleFn, + gMaxVectorSizeIndex - gMinVectorSizeIndex, + &build_info ) )) + { + return error; + } + /* + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + if( (error = BuildKernelDouble( f->nameInCode, (int) i, kernels + i, programs + i) ) ) + return error; + */ + + for( i = 0; i < (1ULL<<32); i += step ) + { + //Init input array + double *p = (double *)gIn; + double *p2 = (double *)gIn2; + double *p3 = (double *)gIn3; + j = 0; + if( i == 0 ) + { // test edge cases + uint32_t x, y, z; x = y = z = 0; + for( ; j < bufferSize / sizeof( double ); j++ ) + { + p[j] = specialValuesDouble[x]; + p2[j] = specialValuesDouble[y]; + p3[j] = specialValuesDouble[z]; + if( ++x >= specialValuesDoubleCount ) + { + x = 0; + if( ++y >= specialValuesDoubleCount ) + { + y = 0; + if( ++z >= specialValuesDoubleCount ) + break; + } + } + } + if( j == bufferSize / sizeof( double ) ) + vlog_error( "Test Error: not all special cases tested!\n" ); + } + + for( ; j < bufferSize / sizeof( double ); j++ ) + { + p[j] = DoubleFromUInt32(genrand_int32(d)); + p2[j] = DoubleFromUInt32(genrand_int32(d)); + p3[j] = DoubleFromUInt32(genrand_int32(d)); + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, bufferSize, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer3, CL_FALSE, 0, bufferSize, gIn3, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer3 ***\n", error ); + return error; + } + + // write garbage into output arrays + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + uint32_t pattern = 0xffffdead; + memset_pattern4(gOut[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer[j], CL_FALSE, 0, bufferSize, gOut[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2(%d) ***\n", error, j ); + goto exit; + } + } + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_double ) * sizeValues[j]; + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; // bufferSize / vectorSize rounded up + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 3, sizeof( gInBuffer3 ), &gInBuffer3 ) )) { LogBuildError(programs[j]); goto exit; } + + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + + // Get that moving + if( (error = clFlush(gQueue) )) + vlog( "clFlush failed\n" ); + + //Calculate the correctly rounded reference result + double *r = (double *)gOut_Ref; + double *s = (double *)gIn; + double *s2 = (double *)gIn2; + double *s3 = (double *)gIn3; + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + r[j] = (double) f->dfunc.f_fff( s[j], s2[j], s3[j] ); + + // Read the data back + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0, bufferSize, gOut[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray failed %d\n", error ); + goto exit; + } + } + + if( gSkipCorrectnessTesting ) + break; + + //Verify data + uint64_t *t = (uint64_t *)gOut_Ref; + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + uint64_t *q = (uint64_t *)(gOut[k]); + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + double test = ((double*) q)[j]; + long double correct = f->dfunc.f_fff( s[j], s2[j], s3[j] ); + float err = Ulp_Error_Double( test, correct ); + int fail = ! (fabsf(err) <= f->double_ulps); + + if( fail && ftz ) + { + // retry per section 6.5.3.2 + if( IsDoubleSubnormal(correct) ) + { // look at me, + fail = fail && ( test != 0.0f ); + if( ! fail ) + err = 0.0f; + } + + // retry per section 6.5.3.3 + if( fail && IsDoubleSubnormal( s[j] ) ) + { // look at me, + long double correct2 = f->dfunc.f_fff( 0.0, s2[j], s3[j] ); + long double correct3 = f->dfunc.f_fff( -0.0, s2[j], s3[j] ); + float err2 = Ulp_Error_Double( test, correct2 ); + float err3 = Ulp_Error_Double( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= f->double_ulps)) && (!(fabsf(err3) <= f->double_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) ) + { // look at me now, + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + + //try with first two args as zero + if( IsDoubleSubnormal( s2[j] ) ) + { // its fun to have fun, + correct2 = f->dfunc.f_fff( 0.0, 0.0, s3[j] ); + correct3 = f->dfunc.f_fff( -0.0, 0.0, s3[j] ); + long double correct4 = f->dfunc.f_fff( 0.0, -0.0, s3[j] ); + long double correct5 = f->dfunc.f_fff( -0.0, -0.0, s3[j] ); + err2 = Ulp_Error_Double( test, correct2 ); + err3 = Ulp_Error_Double( test, correct3 ); + float err4 = Ulp_Error_Double( test, correct4 ); + float err5 = Ulp_Error_Double( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= f->double_ulps)) && (!(fabsf(err3) <= f->double_ulps)) && + (!(fabsf(err4) <= f->double_ulps)) && (!(fabsf(err5) <= f->double_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) || + IsDoubleResultSubnormal( correct4, f->double_ulps ) || IsDoubleResultSubnormal( correct5, f->double_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + + if( IsDoubleSubnormal( s3[j] ) ) + { // but you have to know how! + correct2 = f->dfunc.f_fff( 0.0, 0.0, 0.0f ); + correct3 = f->dfunc.f_fff( -0.0, 0.0, 0.0f ); + correct4 = f->dfunc.f_fff( 0.0, -0.0, 0.0f ); + correct5 = f->dfunc.f_fff( -0.0, -0.0, 0.0f ); + long double correct6 = f->dfunc.f_fff( 0.0, 0.0, -0.0f ); + long double correct7 = f->dfunc.f_fff( -0.0, 0.0, -0.0f ); + long double correct8 = f->dfunc.f_fff( 0.0, -0.0, -0.0f ); + long double correct9 = f->dfunc.f_fff( -0.0, -0.0, -0.0f ); + err2 = Ulp_Error_Double( test, correct2 ); + err3 = Ulp_Error_Double( test, correct3 ); + err4 = Ulp_Error_Double( test, correct4 ); + err5 = Ulp_Error_Double( test, correct5 ); + float err6 = Ulp_Error_Double( test, correct6 ); + float err7 = Ulp_Error_Double( test, correct7 ); + float err8 = Ulp_Error_Double( test, correct8 ); + float err9 = Ulp_Error_Double( test, correct9 ); + fail = fail && ((!(fabsf(err2) <= f->double_ulps)) && (!(fabsf(err3) <= f->double_ulps)) && + (!(fabsf(err4) <= f->double_ulps)) && (!(fabsf(err5) <= f->double_ulps)) && + (!(fabsf(err5) <= f->double_ulps)) && (!(fabsf(err6) <= f->double_ulps)) && + (!(fabsf(err7) <= f->double_ulps)) && (!(fabsf(err8) <= f->double_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + if( fabsf( err6 ) < fabsf(err ) ) + err = err6; + if( fabsf( err7 ) < fabsf(err ) ) + err = err7; + if( fabsf( err8 ) < fabsf(err ) ) + err = err8; + if( fabsf( err9 ) < fabsf(err ) ) + err = err9; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) || + IsDoubleResultSubnormal( correct4, f->double_ulps ) || IsDoubleResultSubnormal( correct5, f->double_ulps ) || + IsDoubleResultSubnormal( correct6, f->double_ulps ) || IsDoubleResultSubnormal( correct7, f->double_ulps ) || + IsDoubleResultSubnormal( correct8, f->double_ulps ) || IsDoubleResultSubnormal( correct9, f->double_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + else if( IsDoubleSubnormal( s3[j] ) ) + { + correct2 = f->dfunc.f_fff( 0.0, s2[j], 0.0 ); + correct3 = f->dfunc.f_fff( -0.0, s2[j], 0.0 ); + long double correct4 = f->dfunc.f_fff( 0.0, s2[j], -0.0 ); + long double correct5 = f->dfunc.f_fff( -0.0, s2[j], -0.0 ); + err2 = Ulp_Error_Double( test, correct2 ); + err3 = Ulp_Error_Double( test, correct3 ); + float err4 = Ulp_Error_Double( test, correct4 ); + float err5 = Ulp_Error_Double( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= f->double_ulps)) && (!(fabsf(err3) <= f->double_ulps)) && + (!(fabsf(err4) <= f->double_ulps)) && (!(fabsf(err5) <= f->double_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) || + IsDoubleResultSubnormal( correct4, f->double_ulps ) || IsDoubleResultSubnormal( correct5, f->double_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + else if( fail && IsDoubleSubnormal( s2[j] ) ) + { + long double correct2 = f->dfunc.f_fff( s[j], 0.0, s3[j] ); + long double correct3 = f->dfunc.f_fff( s[j], -0.0, s3[j] ); + float err2 = Ulp_Error_Double( test, correct2 ); + float err3 = Ulp_Error_Double( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= f->double_ulps)) && (!(fabsf(err3) <= f->double_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + + //try with second two args as zero + if( IsDoubleSubnormal( s3[j] ) ) + { + correct2 = f->dfunc.f_fff( s[j], 0.0, 0.0 ); + correct3 = f->dfunc.f_fff( s[j], -0.0, 0.0 ); + long double correct4 = f->dfunc.f_fff( s[j], 0.0, -0.0 ); + long double correct5 = f->dfunc.f_fff( s[j], -0.0, -0.0 ); + err2 = Ulp_Error_Double( test, correct2 ); + err3 = Ulp_Error_Double( test, correct3 ); + float err4 = Ulp_Error_Double( test, correct4 ); + float err5 = Ulp_Error_Double( test, correct5 ); + fail = fail && ((!(fabsf(err2) <= f->double_ulps)) && (!(fabsf(err3) <= f->double_ulps)) && + (!(fabsf(err4) <= f->double_ulps)) && (!(fabsf(err5) <= f->double_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + if( fabsf( err4 ) < fabsf(err ) ) + err = err4; + if( fabsf( err5 ) < fabsf(err ) ) + err = err5; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) || + IsDoubleResultSubnormal( correct4, f->double_ulps ) || IsDoubleResultSubnormal( correct5, f->double_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + else if( fail && IsDoubleSubnormal(s3[j]) ) + { + long double correct2 = f->dfunc.f_fff( s[j], s2[j], 0.0 ); + long double correct3 = f->dfunc.f_fff( s[j], s2[j], -0.0 ); + float err2 = Ulp_Error_Double( test, correct2 ); + float err3 = Ulp_Error_Double( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= f->double_ulps)) && (!(fabsf(err3) <= f->double_ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + + if( fabsf(err ) > maxError ) + { + maxError = fabsf(err); + maxErrorVal = s[j]; + maxErrorVal2 = s2[j]; + maxErrorVal3 = s3[j]; + } + + if( fail ) + { + vlog_error( "\nERROR: %sD%s: %f ulp error at {%.13la, %.13la, %.13la}: *%.13la vs. %.13la\n", f->name, sizeNames[k], err, s[j], s2[j], s3[j], ((double*) gOut_Ref)[j], test ); + error = -1; + goto exit; + } + } + } + } + + if( 0 == (i & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10zu bufferSize:%10zd \n", i, step, bufferSize); + } else + { + vlog("." ); + } + fflush(stdout); + } + } + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input array + double *p = (double *)gIn; + double *p2 = (double *)gIn2; + double *p3 = (double *)gIn3; + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + { + p[j] = DoubleFromUInt32(genrand_int32(d)); + p2[j] = DoubleFromUInt32(genrand_int32(d)); + p3[j] = DoubleFromUInt32(genrand_int32(d)); + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0, bufferSize, gIn2, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error ); + return error; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer3, CL_FALSE, 0, bufferSize, gIn3, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer3 ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeof( cl_double ) * sizeValues[j]; + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; // bufferSize / vectorSize rounded up + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer2 ), &gInBuffer2 ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 3, sizeof( gInBuffer3 ), &gInBuffer3 ) )) { LogBuildError(programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( k = 0; k < PERF_LOOP_COUNT; k++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (bufferSize / sizeof( double ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sD%s", f->name, sizeNames[j] ); + } + for( ; j < gMaxVectorSizeIndex; j++ ) + vlog( "\t -- " ); + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t%8.2f @ {%a, %a, %a}", maxError, maxErrorVal, maxErrorVal2, maxErrorVal3 ); + vlog( "\n" ); + +exit: + // Release + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + clReleaseKernel(kernels[k]); + clReleaseProgram(programs[k]); + } + + return error; +} + + diff --git a/test_conformance/math_brute_force/unary.c b/test_conformance/math_brute_force/unary.c new file mode 100644 index 00000000..d8b3dbae --- /dev/null +++ b/test_conformance/math_brute_force/unary.c @@ -0,0 +1,1191 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Utility.h" + +#include +#include "FunctionList.h" + +#if defined( __APPLE__ ) + #include +#endif + +int TestFunc_Float_Float(const Func *f, MTdata); +int TestFunc_Double_Double(const Func *f, MTdata); + +#if defined( __cplusplus) + extern "C" +#endif +const vtbl _unary = { "unary", TestFunc_Float_Float, TestFunc_Double_Double }; + +static int BuildKernel( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ); +static int BuildKernelDouble( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ); + +static int BuildKernel( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { + "__kernel void math_kernel", sizeNames[vectorSize], "( __global float", sizeNames[vectorSize], "* out, __global float", sizeNames[vectorSize], "* in)\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in[i] );\n" + "}\n" + }; + const char *c3[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global float* out, __global float* in)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " float3 f0 = vload3( 0, in + 3 * i );\n" + " f0 = ", name, "( f0 );\n" + " vstore3( f0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " float3 f0;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (float3)( in[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " f0 = (float3)( in[3*i], in[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " f0 = ", name, "( f0 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = f0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = f0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernels(kern, (cl_uint) kernSize, testName, kernel_count, k, p); +} + +static int BuildKernelDouble( const char *name, int vectorSize, cl_uint kernel_count, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double", sizeNames[vectorSize], "* out, __global double", sizeNames[vectorSize], "* in)\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in[i] );\n" + "}\n" + }; + + const char *c3[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double* out, __global double* in)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " double3 f0 = vload3( 0, in + 3 * i );\n" + " f0 = ", name, "( f0 );\n" + " vstore3( f0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " double3 f0;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (double3)( in[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " f0 = (double3)( in[3*i], in[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " f0 = ", name, "( f0 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = f0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = f0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernels(kern, (cl_uint) kernSize, testName, kernel_count, k, p); +} + +typedef struct BuildKernelInfo +{ + cl_uint offset; // the first vector size to build + cl_uint kernel_count; + cl_kernel **kernels; + cl_program *programs; + const char *nameInCode; +}BuildKernelInfo; + +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernel( info->nameInCode, i, info->kernel_count, info->kernels[i], info->programs + i ); +} + +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernelDouble( info->nameInCode, i, info->kernel_count, info->kernels[i], info->programs + i ); +} + +//Thread specific data for a worker thread +typedef struct ThreadInfo +{ + cl_mem inBuf; // input buffer for the thread + cl_mem outBuf[ VECTOR_SIZE_COUNT ]; // output buffers for the thread + float maxError; // max error value. Init to 0. + double maxErrorValue; // position of the max error value. Init to 0. + cl_command_queue tQueue; // per thread command queue to improve performance +}ThreadInfo; + +typedef struct TestInfo +{ + size_t subBufferSize; // Size of the sub-buffer in elements + const Func *f; // A pointer to the function info + cl_program programs[ VECTOR_SIZE_COUNT ]; // programs for various vector sizes + cl_kernel *k[VECTOR_SIZE_COUNT ]; // arrays of thread-specific kernels for each worker thread: k[vector_size][thread_id] + ThreadInfo *tinfo; // An array of thread specific information for each worker thread + cl_uint threadCount; // Number of worker threads + cl_uint step; // step between each chunk and the next. + cl_uint scale; // stride between individual test values + float ulps; // max_allowed ulps + int ftz; // non-zero if running in flush to zero mode + + int isRangeLimited; // 1 if the function is only to be evaluated over a range + float half_sin_cos_tan_limit; +}TestInfo; + +static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *p ); + +int TestFunc_Float_Float(const Func *f, MTdata d) +{ + TestInfo test_info; + cl_int error; + size_t i, j; + float maxError = 0.0f; + double maxErrorVal = 0.0; + int skipTestingRelaxed = ( gTestFastRelaxed && strcmp(f->name,"tan") == 0 ); + + logFunctionInfo(f->name,sizeof(cl_float),gTestFastRelaxed); + + // Init test_info + memset( &test_info, 0, sizeof( test_info ) ); + test_info.threadCount = GetThreadCount(); + + test_info.subBufferSize = BUFFER_SIZE / (sizeof( cl_float) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = 1; + if (gWimpyMode) + { + test_info.subBufferSize = gWimpyBufferSize / (sizeof( cl_float) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = (cl_uint) sizeof(cl_float) * 2 * gWimpyReductionFactor; + } + test_info.step = (cl_uint) test_info.subBufferSize * test_info.scale; + test_info.f = f; + test_info.ulps = gIsEmbedded ? f->float_embedded_ulps : f->float_ulps; + test_info.ftz = f->ftz || gForceFTZ || 0 == (CL_FP_DENORM & gFloatCapabilities); + // cl_kernels aren't thread safe, so we make one for each vector size for every thread + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + size_t array_size = test_info.threadCount * sizeof( cl_kernel ); + test_info.k[i] = (cl_kernel*)malloc( array_size ); + if( NULL == test_info.k[i] ) + { + vlog_error( "Error: Unable to allocate storage for kernels!\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.k[i], 0, array_size ); + } + test_info.tinfo = (ThreadInfo*)malloc( test_info.threadCount * sizeof(*test_info.tinfo) ); + if( NULL == test_info.tinfo ) + { + vlog_error( "Error: Unable to allocate storage for thread specific data.\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.tinfo, 0, test_info.threadCount * sizeof(*test_info.tinfo) ); + for( i = 0; i < test_info.threadCount; i++ ) + { + cl_buffer_region region = { i * test_info.subBufferSize * sizeof( cl_float), test_info.subBufferSize * sizeof( cl_float) }; + test_info.tinfo[i].inBuf = clCreateSubBuffer( gInBuffer, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + test_info.tinfo[i].outBuf[j] = clCreateSubBuffer( gOutBuffer[j], CL_MEM_WRITE_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].outBuf[j] ) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + } + test_info.tinfo[i].tQueue = clCreateCommandQueueWithProperties(gContext, gDevice, 0, &error); + if( NULL == test_info.tinfo[i].tQueue || error ) + { + vlog_error( "clCreateCommandQueue failed. (%d)\n", error ); + goto exit; + } + + } + + // Check for special cases for unary float + test_info.isRangeLimited = 0; + test_info.half_sin_cos_tan_limit = 0; + if( 0 == strcmp( f->name, "half_sin") || 0 == strcmp( f->name, "half_cos") ) + { + test_info.isRangeLimited = 1; + test_info.half_sin_cos_tan_limit = 1.0f + test_info.ulps * (FLT_EPSILON/2.0f); // out of range results from finite inputs must be in [-1,1] + } + else if( 0 == strcmp( f->name, "half_tan")) + { + test_info.isRangeLimited = 1; + test_info.half_sin_cos_tan_limit = INFINITY; // out of range resut from finite inputs must be numeric + } + + // Init the kernels + { + BuildKernelInfo build_info = { gMinVectorSizeIndex, test_info.threadCount, test_info.k, test_info.programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_FloatFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + goto exit; + } + + if( !gSkipCorrectnessTesting || skipTestingRelaxed) + { + error = ThreadPool_Do( TestFloat, (cl_uint) ((1ULL<<32) / test_info.step), &test_info ); + + // Accumulate the arithmetic errors + for( i = 0; i < test_info.threadCount; i++ ) + { + if( test_info.tinfo[i].maxError > maxError ) + { + maxError = test_info.tinfo[i].maxError; + maxErrorVal = test_info.tinfo[i].maxErrorValue; + } + } + + if( error ) + goto exit; + + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + + if( skipTestingRelaxed ) + { + vlog(" (rlx skip correctness testing)\n"); + goto exit; + } + } + + if( gMeasureTimes ) + { + //Init input array + uint32_t *p = (uint32_t *)gIn; + if( strstr( f->name, "exp" ) || strstr( f->name, "sin" ) || strstr( f->name, "cos" ) || strstr( f->name, "tan" ) ) + for( j = 0; j < BUFFER_SIZE / sizeof( float ); j++ ) + ((float*)p)[j] = (float) genrand_real1(d); + else if( strstr( f->name, "log" ) ) + for( j = 0; j < BUFFER_SIZE / sizeof( float ); j++ ) + p[j] = genrand_int32(d) & 0x7fffffff; + else + for( j = 0; j < BUFFER_SIZE / sizeof( float ); j++ ) + p[j] = genrand_int32(d); + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, BUFFER_SIZE, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_float); + size_t localCount = (BUFFER_SIZE + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg( test_info.k[j][0], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError( test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(test_info.programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( i = 0; i < PERF_LOOP_COUNT; i++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, test_info.k[j][0], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double current_time = SubtractTime( endTime, startTime ); + sum += current_time; + if( current_time < bestTime ) + bestTime = current_time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (BUFFER_SIZE / sizeof( float ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sf%s", f->name, sizeNames[j] ); + } + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t%8.2f @ %a", maxError, maxErrorVal ); + vlog( "\n" ); + +exit: + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + clReleaseProgram(test_info.programs[i]); + if( test_info.k[i] ) + { + for( j = 0; j < test_info.threadCount; j++ ) + clReleaseKernel(test_info.k[i][j]); + + free( test_info.k[i] ); + } + } + if( test_info.tinfo ) + { + for( i = 0; i < test_info.threadCount; i++ ) + { + clReleaseMemObject(test_info.tinfo[i].inBuf); + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + clReleaseMemObject(test_info.tinfo[i].outBuf[j]); + clReleaseCommandQueue(test_info.tinfo[i].tQueue); + } + + free( test_info.tinfo ); + } + + return error; +} + +static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *data ) +{ + const TestInfo *job = (const TestInfo *) data; + size_t buffer_elements = job->subBufferSize; + size_t buffer_size = buffer_elements * sizeof( cl_float ); + cl_uint scale = job->scale; + cl_uint base = job_id * (cl_uint) job->step; + ThreadInfo *tinfo = job->tinfo + thread_id; + float ulps = job->ulps; + fptr func = job->f->func; + const char * fname = job->f->name; + if ( gTestFastRelaxed ) + { + ulps = job->f->relaxed_error; + func = job->f->rfunc; + } + + cl_uint j, k; + cl_int error; + + int isRangeLimited = job->isRangeLimited; + float half_sin_cos_tan_limit = job->half_sin_cos_tan_limit; + int ftz = job->ftz; + + // start the map of the output arrays + cl_event e[ VECTOR_SIZE_COUNT ]; + cl_uint *out[ VECTOR_SIZE_COUNT ]; + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + out[j] = (uint32_t*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_WRITE, 0, buffer_size, 0, NULL, e + j, &error); + if( error || NULL == out[j]) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush failed\n" ); + + // Write the new values to the input array + cl_uint *p = (cl_uint*) gIn + thread_id * buffer_elements; + for( j = 0; j < buffer_elements; j++ ) + { + p[j] = base + j * scale; + if( gTestFastRelaxed ) + { + float p_j = *(float *) &p[j]; + if ( strcmp(fname,"sin")==0 || strcmp(fname,"cos")==0 ) //the domain of the function is [-pi,pi] + { + if( fabs(p_j) > M_PI ) + p[j] = NAN; + } + + if ( strcmp( fname, "reciprocal" ) == 0 ) + { + if( fabs(p_j) > 0x7E800000 ) //the domain of the function is [2^-126,2^126] + p[j] = NAN; + } + } + } + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf, CL_FALSE, 0, buffer_size, p, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + return error; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + //Wait for the map to finish + if( (error = clWaitForEvents(1, e + j) )) + { + vlog_error( "Error: clWaitForEvents failed! err: %d\n", error ); + return error; + } + if( (error = clReleaseEvent( e[j] ) )) + { + vlog_error( "Error: clReleaseEvent failed! err: %d\n", error ); + return error; + } + + // Fill the result buffer with garbage, so that old results don't carry over + uint32_t pattern = 0xffffdead; + memset_pattern4(out[j], &pattern, buffer_size); + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueMapBuffer failed! err: %d\n", error ); + return error; + } + + // run the kernel + size_t vectorCount = (buffer_elements + sizeValues[j] - 1) / sizeValues[j]; + cl_kernel kernel = job->k[j][thread_id]; //each worker thread has its own copy of the cl_kernel + cl_program program = job->programs[j]; + + if( ( error = clSetKernelArg( kernel, 0, sizeof( tinfo->outBuf[j] ), &tinfo->outBuf[j] ))){ LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 1, sizeof( tinfo->inBuf ), &tinfo->inBuf ) )) { LogBuildError(program); return error; } + + if( (error = clEnqueueNDRangeKernel(tinfo->tQueue, kernel, 1, NULL, &vectorCount, NULL, 0, NULL, NULL))) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + return error; + } + } + + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 2 failed\n" ); + + if( gSkipCorrectnessTesting ) + return CL_SUCCESS; + + //Calculate the correctly rounded reference result + float *r = (float *)gOut_Ref + thread_id * buffer_elements; + float *s = (float *)p; + for( j = 0; j < buffer_elements; j++ ) + r[j] = (float) func.f_f( s[j] ); + + // Read the data back -- no need to wait for the first N-1 buffers. This is an in order queue. + for( j = gMinVectorSizeIndex; j + 1 < gMaxVectorSizeIndex; j++ ) + { + out[j] = (uint32_t*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + // Wait for the last buffer + out[j] = (uint32_t*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_TRUE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + + //Verify data + uint32_t *t = (uint32_t *)r; + for( j = 0; j < buffer_elements; j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + uint32_t *q = out[k]; + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + float test = ((float*) q)[j]; + double correct = func.f_f( s[j] ); + float err = Ulp_Error( test, correct ); + float abs_error = Abs_Error( test, correct ); + int fail = 0; + int use_abs_error = 0; + + // it is possible for the output to not match the reference result but for Ulp_Error + // to be zero, for example -1.#QNAN vs. 1.#QNAN. In such cases there is no failure + if (err == 0.0f) + { + fail = 0; + } + else if( gTestFastRelaxed ) + { + if ( strcmp(fname,"sin")==0 || strcmp(fname,"cos")==0 ) + { + fail = ! (fabsf(abs_error) <= ulps); + use_abs_error = 1; + } + + if ( strcmp(fname, "reciprocal") == 0 ) + { + fail = ! (fabsf(err) <= ulps); + } + + if ( strcmp(fname, "exp") == 0 || strcmp(fname, "exp2") == 0 ) + { + + float exp_error = 3+floor(fabs(2*s[j])); + fail = ! (fabsf(err) <= exp_error); + ulps = exp_error; + } + if (strcmp(fname, "tan") == 0) { + + if( !gFastRelaxedDerived ) + { + fail = ! (fabsf(err) <= ulps); + } + // Else fast math derived implementation does not require ULP verification + } + if (strcmp(fname, "exp10") == 0) + { + if( !gFastRelaxedDerived ) + { + fail = ! (fabsf(err) <= ulps); + } + // Else fast math derived implementation does not require ULP verification + } + if ( strcmp(fname,"log") == 0 || strcmp(fname,"log2") == 0 ) + { + if( s[j] >= 0.5 && s[j] <= 2 ) + { + fail = ! (fabsf(abs_error) <= ulps ); + } + else + { + ulps = gIsEmbedded ? job->f->float_embedded_ulps : job->f->float_ulps; + fail = ! (fabsf(err) <= ulps); + } + + } + + + // fast-relaxed implies finite-only + if( IsFloatInfinity(correct) || IsFloatNaN(correct) || + IsFloatInfinity(s[j]) || IsFloatNaN(s[j]) ) { + fail = 0; + err = 0; + } + } + else + { + fail = ! (fabsf(err) <= ulps); + } + + // half_sin/cos/tan are only valid between +-2**16, Inf, NaN + if( isRangeLimited && fabsf(s[j]) > MAKE_HEX_FLOAT(0x1.0p16f, 0x1L, 16) && fabsf(s[j]) < INFINITY ) + { + if( fabsf( test ) <= half_sin_cos_tan_limit ) + { + err = 0; + fail = 0; + } + } + + if( fail ) + { + if( ftz ) + { + typedef int (*CheckForSubnormal) (double,float); // If we are in fast relaxed math, we have a different calculation for the subnormal threshold. + CheckForSubnormal isFloatResultSubnormalPtr; + + if ( gTestFastRelaxed ) + { + isFloatResultSubnormalPtr = &IsFloatResultSubnormalAbsError; + } + else + { + isFloatResultSubnormalPtr = &IsFloatResultSubnormal; + } + // retry per section 6.5.3.2 + if( (*isFloatResultSubnormalPtr)(correct, ulps) ) + { + fail = fail && ( test != 0.0f ); + if( ! fail ) + err = 0.0f; + } + + // retry per section 6.5.3.3 + if( IsFloatSubnormal( s[j] ) ) + { + double correct2 = func.f_f( 0.0 ); + double correct3 = func.f_f( -0.0 ); + float err2; + float err3; + if( use_abs_error ) + { + err2 = Abs_Error( test, correct2 ); + err3 = Abs_Error( test, correct3 ); + } + else + { + err2 = Ulp_Error( test, correct2 ); + err3 = Ulp_Error( test, correct3 ); + } + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( (*isFloatResultSubnormalPtr)(correct2, ulps ) || (*isFloatResultSubnormalPtr)(correct3, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + } + if( fabsf(err ) > tinfo->maxError ) + { + tinfo->maxError = fabsf(err); + tinfo->maxErrorValue = s[j]; + } + if( fail ) + { + vlog_error( "\nERROR: %s%s: %f ulp error at %a (0x%8.8x): *%a vs. %a\n", job->f->name, sizeNames[k], err, ((float*) s)[j], ((uint32_t*) s)[j], ((float*) t)[j], test); + return -1; + } + } + } + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL)) ) + { + vlog_error( "Error: clEnqueueUnmapMemObject %d failed 2! err: %d\n", j, error ); + return error; + } + } + + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 3 failed\n" ); + + + if( 0 == ( base & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10u scale:%10u buf_elements:%10zd ulps:%5.3f ThreadCount:%2u\n", base, job->step, job->scale, buffer_elements, job->ulps, job->threadCount); + } else + { + vlog("." ); + } + fflush(stdout); + } + + return CL_SUCCESS; +} + + + +static cl_int TestDouble( cl_uint job_id, cl_uint thread_id, void *data ) +{ + const TestInfo *job = (const TestInfo *) data; + size_t buffer_elements = job->subBufferSize; + size_t buffer_size = buffer_elements * sizeof( cl_double ); + cl_uint scale = job->scale; + cl_uint base = job_id * (cl_uint) job->step; + ThreadInfo *tinfo = job->tinfo + thread_id; + float ulps = job->ulps; + dptr func = job->f->dfunc; + cl_uint j, k; + cl_int error; + int ftz = job->ftz; + + Force64BitFPUPrecision(); + + // start the map of the output arrays + cl_event e[ VECTOR_SIZE_COUNT ]; + cl_ulong *out[ VECTOR_SIZE_COUNT ]; + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_ulong*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_WRITE, 0, buffer_size, 0, NULL, e + j, &error); + if( error || NULL == out[j]) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush failed\n" ); + + // Write the new values to the input array + cl_double *p = (cl_double*) gIn + thread_id * buffer_elements; + for( j = 0; j < buffer_elements; j++ ) + p[j] = DoubleFromUInt32( base + j * scale); + + if( (error = clEnqueueWriteBuffer( tinfo->tQueue, tinfo->inBuf, CL_FALSE, 0, buffer_size, p, 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueWriteBuffer failed! err: %d\n", error ); + return error; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + //Wait for the map to finish + if( (error = clWaitForEvents(1, e + j) )) + { + vlog_error( "Error: clWaitForEvents failed! err: %d\n", error ); + return error; + } + if( (error = clReleaseEvent( e[j] ) )) + { + vlog_error( "Error: clReleaseEvent failed! err: %d\n", error ); + return error; + } + + // Fill the result buffer with garbage, so that old results don't carry over + uint32_t pattern = 0xffffdead; + memset_pattern4(out[j], &pattern, buffer_size); + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL) )) + { + vlog_error( "Error: clEnqueueMapBuffer failed! err: %d\n", error ); + return error; + } + + // run the kernel + size_t vectorCount = (buffer_elements + sizeValues[j] - 1) / sizeValues[j]; + cl_kernel kernel = job->k[j][thread_id]; //each worker thread has its own copy of the cl_kernel + cl_program program = job->programs[j]; + + if( ( error = clSetKernelArg( kernel, 0, sizeof( tinfo->outBuf[j] ), &tinfo->outBuf[j] ))){ LogBuildError(program); return error; } + if( ( error = clSetKernelArg( kernel, 1, sizeof( tinfo->inBuf ), &tinfo->inBuf ) )) { LogBuildError(program); return error; } + + if( (error = clEnqueueNDRangeKernel(tinfo->tQueue, kernel, 1, NULL, &vectorCount, NULL, 0, NULL, NULL))) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + return error; + } + } + + + // Get that moving + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 2 failed\n" ); + + if( gSkipCorrectnessTesting ) + return CL_SUCCESS; + + //Calculate the correctly rounded reference result + cl_double *r = (cl_double *)gOut_Ref + thread_id * buffer_elements; + cl_double *s = (cl_double *)p; + for( j = 0; j < buffer_elements; j++ ) + r[j] = (cl_double) func.f_f( s[j] ); + + // Read the data back -- no need to wait for the first N-1 buffers. This is an in order queue. + for( j = gMinVectorSizeIndex; j + 1 < gMaxVectorSizeIndex; j++ ) + { + out[j] = (cl_ulong*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_FALSE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + } + // Wait for the last buffer + out[j] = (cl_ulong*) clEnqueueMapBuffer( tinfo->tQueue, tinfo->outBuf[j], CL_TRUE, CL_MAP_READ, 0, buffer_size, 0, NULL, NULL, &error); + if( error || NULL == out[j] ) + { + vlog_error( "Error: clEnqueueMapBuffer %d failed! err: %d\n", j, error ); + return error; + } + + + //Verify data + cl_ulong *t = (cl_ulong *)r; + for( j = 0; j < buffer_elements; j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + cl_ulong *q = out[k]; + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + cl_double test = ((cl_double*) q)[j]; + long double correct = func.f_f( s[j] ); + float err = Ulp_Error_Double( test, correct ); + int fail = ! (fabsf(err) <= ulps); + + if( fail ) + { + if( ftz ) + { + // retry per section 6.5.3.2 + if( IsDoubleResultSubnormal(correct, ulps) ) + { + fail = fail && ( test != 0.0f ); + if( ! fail ) + err = 0.0f; + } + + // retry per section 6.5.3.3 + if( IsDoubleSubnormal( s[j] ) ) + { + long double correct2 = func.f_f( 0.0L ); + long double correct3 = func.f_f( -0.0L ); + float err2 = Ulp_Error_Double( test, correct2 ); + float err3 = Ulp_Error_Double( test, correct3 ); + fail = fail && ((!(fabsf(err2) <= ulps)) && (!(fabsf(err3) <= ulps))); + if( fabsf( err2 ) < fabsf(err ) ) + err = err2; + if( fabsf( err3 ) < fabsf(err ) ) + err = err3; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal(correct2, ulps ) || IsDoubleResultSubnormal(correct3, ulps ) ) + { + fail = fail && ( test != 0.0f); + if( ! fail ) + err = 0.0f; + } + } + } + } + if( fabsf(err ) > tinfo->maxError ) + { + tinfo->maxError = fabsf(err); + tinfo->maxErrorValue = s[j]; + } + if( fail ) + { + vlog_error( "\nERROR: %s%s: %f ulp error at %.13la (0x%16.16llx): *%.13la vs. %.13la\n", job->f->name, sizeNames[k], err, ((cl_double*) gIn)[j], ((cl_ulong*) gIn)[j], ((cl_double*) gOut_Ref)[j], test ); + return -1; + } + } + } + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueUnmapMemObject( tinfo->tQueue, tinfo->outBuf[j], out[j], 0, NULL, NULL)) ) + { + vlog_error( "Error: clEnqueueUnmapMemObject %d failed 2! err: %d\n", j, error ); + return error; + } + } + + if( (error = clFlush(tinfo->tQueue) )) + vlog( "clFlush 3 failed\n" ); + + + if( 0 == ( base & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10u scale:%10zd buf_elements:%10u ulps:%5.3f ThreadCount:%2u\n", base, job->step, buffer_elements, job->scale, job->ulps, job->threadCount); + } else + { + vlog("." ); + } + fflush(stdout); + } + + return CL_SUCCESS; +} + +int TestFunc_Double_Double(const Func *f, MTdata d) +{ + TestInfo test_info; + cl_int error; + size_t i, j; + float maxError = 0.0f; + double maxErrorVal = 0.0; +#if defined( __APPLE__ ) + struct timeval time_val; + gettimeofday( &time_val, NULL ); + double start_time = time_val.tv_sec + 1e-6 * time_val.tv_usec; + double end_time; +#endif + + logFunctionInfo(f->name,sizeof(cl_double),gTestFastRelaxed); + // Init test_info + memset( &test_info, 0, sizeof( test_info ) ); + test_info.threadCount = GetThreadCount(); + test_info.subBufferSize = BUFFER_SIZE / (sizeof( cl_double) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = 1; + if (gWimpyMode) + { + test_info.subBufferSize = gWimpyBufferSize / (sizeof( cl_double) * RoundUpToNextPowerOfTwo(test_info.threadCount)); + test_info.scale = (cl_uint) sizeof(cl_double) * 2 * gWimpyReductionFactor; + } + test_info.step = (cl_uint) test_info.subBufferSize * test_info.scale; + + test_info.f = f; + test_info.ulps = f->double_ulps; + test_info.ftz = f->ftz || gForceFTZ; + + // cl_kernels aren't thread safe, so we make one for each vector size for every thread + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + size_t array_size = test_info.threadCount * sizeof( cl_kernel ); + test_info.k[i] = (cl_kernel*)malloc( array_size ); + if( NULL == test_info.k[i] ) + { + vlog_error( "Error: Unable to allocate storage for kernels!\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.k[i], 0, array_size ); + } + test_info.tinfo = (ThreadInfo*)malloc( test_info.threadCount * sizeof(*test_info.tinfo) ); + if( NULL == test_info.tinfo ) + { + vlog_error( "Error: Unable to allocate storage for thread specific data.\n" ); + error = CL_OUT_OF_HOST_MEMORY; + goto exit; + } + memset( test_info.tinfo, 0, test_info.threadCount * sizeof(*test_info.tinfo) ); + for( i = 0; i < test_info.threadCount; i++ ) + { + cl_buffer_region region = { i * test_info.subBufferSize * sizeof( cl_double), test_info.subBufferSize * sizeof( cl_double) }; + test_info.tinfo[i].inBuf = clCreateSubBuffer( gInBuffer, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + if( error || NULL == test_info.tinfo[i].inBuf) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + /* Qualcomm fix: 9461 read-write flags must be compatible with parent buffer */ + test_info.tinfo[i].outBuf[j] = clCreateSubBuffer( gOutBuffer[j], CL_MEM_WRITE_ONLY, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &error); + /* Qualcomm fix: end */ + if( error || NULL == test_info.tinfo[i].outBuf[j] ) + { + vlog_error( "Error: Unable to create sub-buffer of gInBuffer for region {%zd, %zd}\n", region.origin, region.size ); + goto exit; + } + } + test_info.tinfo[i].tQueue = clCreateCommandQueueWithProperties(gContext, gDevice, 0, &error); + if( NULL == test_info.tinfo[i].tQueue || error ) + { + vlog_error( "clCreateCommandQueue failed. (%d)\n", error ); + goto exit; + } + } + + // Init the kernels + { + BuildKernelInfo build_info = { gMinVectorSizeIndex, test_info.threadCount, test_info.k, test_info.programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_DoubleFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + goto exit; + } + + if( !gSkipCorrectnessTesting ) + { + error = ThreadPool_Do( TestDouble, (cl_uint) ((1ULL<<32) / test_info.step), &test_info ); + + // Accumulate the arithmetic errors + for( i = 0; i < test_info.threadCount; i++ ) + { + if( test_info.tinfo[i].maxError > maxError ) + { + maxError = test_info.tinfo[i].maxError; + maxErrorVal = test_info.tinfo[i].maxErrorValue; + } + } + + if( error ) + goto exit; + + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + +#if defined( __APPLE__ ) + gettimeofday( &time_val, NULL); + end_time = time_val.tv_sec + 1e-6 * time_val.tv_usec; +#endif + + if( gMeasureTimes ) + { + //Init input array + double *p = (double *)gIn; + + if( strstr( f->name, "exp" ) ) + for( j = 0; j < BUFFER_SIZE / sizeof( double ); j++ ) + p[j] = (double)genrand_real1(d); + else if( strstr( f->name, "log" ) ) + for( j = 0; j < BUFFER_SIZE / sizeof( double ); j++ ) + p[j] = fabs(DoubleFromUInt32( genrand_int32(d))); + else + for( j = 0; j < BUFFER_SIZE / sizeof( double ); j++ ) + p[j] = DoubleFromUInt32( genrand_int32(d) ); + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, BUFFER_SIZE, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_double); + size_t localCount = (BUFFER_SIZE + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg( test_info.k[j][0], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(test_info.programs[j]); goto exit; } + if( ( error = clSetKernelArg( test_info.k[j][0], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(test_info.programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( i = 0; i < PERF_LOOP_COUNT; i++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, test_info.k[j][0], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double current_time = SubtractTime( endTime, startTime ); + sum += current_time; + if( current_time < bestTime ) + bestTime = current_time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (BUFFER_SIZE / sizeof( double ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sD%s", f->name, sizeNames[j] ); + } + for( ; j < gMaxVectorSizeIndex; j++ ) + vlog( "\t -- " ); + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t%8.2f @ %a", maxError, maxErrorVal ); + +#if defined( __APPLE__ ) + vlog( "\t(%2.2f seconds)", end_time - start_time ); +#endif + vlog( "\n" ); + +exit: + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + { + clReleaseProgram(test_info.programs[i]); + if( test_info.k[i] ) + { + for( j = 0; j < test_info.threadCount; j++ ) + clReleaseKernel(test_info.k[i][j]); + + free( test_info.k[i] ); + } + } + if( test_info.tinfo ) + { + for( i = 0; i < test_info.threadCount; i++ ) + { + clReleaseMemObject(test_info.tinfo[i].inBuf); + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + clReleaseMemObject(test_info.tinfo[i].outBuf[j]); + clReleaseCommandQueue(test_info.tinfo[i].tQueue); + } + + free( test_info.tinfo ); + } + + return error; +} + + diff --git a/test_conformance/math_brute_force/unary_two_results.c b/test_conformance/math_brute_force/unary_two_results.c new file mode 100644 index 00000000..a3fb307d --- /dev/null +++ b/test_conformance/math_brute_force/unary_two_results.c @@ -0,0 +1,993 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Utility.h" + +#include +#include "FunctionList.h" + +int TestFunc_Float2_Float(const Func *f, MTdata); +int TestFunc_Double2_Double(const Func *f, MTdata); + +#if defined(__cplusplus) + extern "C" +#endif +const vtbl _unary_two_results = { "unary_two_results", TestFunc_Float2_Float, TestFunc_Double2_Double }; + +static int BuildKernel( const char *name, int vectorSize, cl_kernel *k, cl_program *p ); +static int BuildKernelDouble( const char *name, int vectorSize, cl_kernel *k, cl_program *p ); +static int BuildKernel( const char *name, int vectorSize, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global float", sizeNames[vectorSize], "* out, __global float", sizeNames[vectorSize], "* out2, __global float", sizeNames[vectorSize], "* in)\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in[i], out2 + i );\n" + "}\n" + }; + + const char *c3[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global float* out, __global float* out2, __global float* in)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " float3 f0 = vload3( 0, in + 3 * i );\n" + " float3 iout = NAN;\n" + " f0 = ", name, "( f0, &iout );\n" + " vstore3( f0, 0, out + 3*i );\n" + " vstore3( iout, 0, out2 + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " float3 iout = NAN;\n" + " float3 f0;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (float3)( in[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " f0 = (float3)( in[3*i], in[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " f0 = ", name, "( f0, &iout );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = f0.y; \n" + " out2[3*i+1] = iout.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = f0.x; \n" + " out2[3*i] = iout.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernel(kern, (cl_uint) kernSize, testName, k, p); + +} + +static int BuildKernelDouble( const char *name, int vectorSize, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double", sizeNames[vectorSize], "* out, __global double", sizeNames[vectorSize], "* out2, __global double", sizeNames[vectorSize], "* in)\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in[i], out2 + i );\n" + "}\n" + }; + + const char *c3[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double* out, __global double* out2, __global double* in)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " double3 f0 = vload3( 0, in + 3 * i );\n" + " double3 iout = NAN;\n" + " f0 = ", name, "( f0, &iout );\n" + " vstore3( f0, 0, out + 3*i );\n" + " vstore3( iout, 0, out2 + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " double3 iout = NAN;\n" + " double3 f0;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (double3)( in[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " f0 = (double3)( in[3*i], in[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " f0 = ", name, "( f0, &iout );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = f0.y; \n" + " out2[3*i+1] = iout.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = f0.x; \n" + " out2[3*i] = iout.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernel(kern, (cl_uint) kernSize, testName, k, p); + +} + +typedef struct BuildKernelInfo +{ + cl_uint offset; // the first vector size to build + cl_kernel *kernels; + cl_program *programs; + const char *nameInCode; +}BuildKernelInfo; + +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernel( info->nameInCode, i, info->kernels + i, info->programs + i ); +} + +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernelDouble( info->nameInCode, i, info->kernels + i, info->programs + i ); +} + +int TestFunc_Float2_Float(const Func *f, MTdata d) +{ + uint64_t i; + uint32_t j, k; + uint32_t l; + int error; + char const * testing_mode; + cl_program programs[ VECTOR_SIZE_COUNT ]; + cl_kernel kernels[ VECTOR_SIZE_COUNT ]; + float maxError0 = 0.0f; + float maxError1 = 0.0f; + int ftz = f->ftz || gForceFTZ || 0 == (CL_FP_DENORM & gFloatCapabilities); + float maxErrorVal0 = 0.0f; + float maxErrorVal1 = 0.0f; + size_t bufferSize = (gWimpyMode)? gWimpyBufferSize: BUFFER_SIZE; + uint64_t step = bufferSize / sizeof( float ); + int scale = (int)((1ULL<<32) / (16 * bufferSize / sizeof( float )) + 1); + cl_uchar overflow[BUFFER_SIZE / sizeof( float )]; + int isFract = 0 == strcmp( "fract", f->nameInCode ); + int skipNanInf = isFract && ! gInfNanSupport; + float float_ulps; + + logFunctionInfo(f->name,sizeof(cl_float),gTestFastRelaxed); + if( gWimpyMode ) + { + step = (1ULL<<32) * gWimpyReductionFactor / (512); + } + if( gIsEmbedded ) + float_ulps = f->float_embedded_ulps; + else + float_ulps = f->float_ulps; + + if (gTestFastRelaxed) + float_ulps = f->relaxed_error; + + // Init the kernels + BuildKernelInfo build_info = { gMinVectorSizeIndex, kernels, programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_FloatFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + return error; +/* + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + if( (error = BuildKernel( f->nameInCode, (int) i, kernels + i, programs + i) ) ) + return error; +*/ + + for( i = 0; i < (1ULL<<32); i += step ) + { + //Init input array + uint32_t *p = (uint32_t *)gIn; + if( gWimpyMode ) + { + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + p[j] = (uint32_t) i + j * scale; + if ( gTestFastRelaxed && strcmp(f->name,"sincos") == 0 ) + { + float pj = *(float *)&p[j]; + if(fabs(pj) > M_PI) + p[j] = NAN; + } + } + } + else + { + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + p[j] = (uint32_t) i + j; + if ( gTestFastRelaxed && strcmp(f->name,"sincos") == 0 ) + { + float pj = *(float *)&p[j]; + if(fabs(pj) > M_PI) + p[j] = NAN; + } + } + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + // write garbage into output arrays + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + uint32_t pattern = 0xffffdead; + memset_pattern4(gOut[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer[j], CL_FALSE, 0, bufferSize, gOut[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2(%d) ***\n", error, j ); + goto exit; + } + + memset_pattern4(gOut2[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer2[j], CL_FALSE, 0, bufferSize, gOut2[j], 0, NULL, NULL))) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2b(%d) ***\n", error, j ); + goto exit; + } + } + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_float); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg(kernels[j], 1, sizeof( gOutBuffer2[j] ), &gOutBuffer2[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg(kernels[j], 2, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(gQueue) )) + vlog( "clFlush failed\n" ); + + FPU_mode_type oldMode; + RoundingMode oldRoundMode = kRoundToNearestEven; + if( isFract ) + { + //Calculate the correctly rounded reference result + memset( &oldMode, 0, sizeof( oldMode ) ); + if( ftz ) + ForceFTZ( &oldMode ); + + // Set the rounding mode to match the device + if (gIsInRTZMode) + oldRoundMode = set_round(kRoundTowardZero, kfloat); + } + + //Calculate the correctly rounded reference result + float *r = (float *)gOut_Ref; + float *r2 = (float *)gOut_Ref2; + float *s = (float *)gIn; + + if( skipNanInf ) + { + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + double dd; + feclearexcept(FE_OVERFLOW); + + if( gTestFastRelaxed ) + r[j] = (float) f->rfunc.f_fpf( s[j], &dd ); + else + r[j] = (float) f->func.f_fpf( s[j], &dd ); + + r2[j] = (float) dd; + overflow[j] = FE_OVERFLOW == (FE_OVERFLOW & fetestexcept(FE_OVERFLOW)); + } + } + else + { + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + double dd; + if( gTestFastRelaxed ) + r[j] = (float) f->rfunc.f_fpf( s[j], &dd ); + else + r[j] = (float) f->func.f_fpf( s[j], &dd ); + + r2[j] = (float) dd; + } + } + + if( isFract && ftz ) + RestoreFPState( &oldMode ); + + // Read the data back + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0, bufferSize, gOut[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray failed %d\n", error ); + goto exit; + } + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer2[j], CL_TRUE, 0, bufferSize, gOut2[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray2 failed %d\n", error ); + goto exit; + } + } + + if( gSkipCorrectnessTesting ) + { + if (isFract && gIsInRTZMode) + (void)set_round(oldRoundMode, kfloat); + break; + } + + //Verify data + uint32_t *t = (uint32_t *)gOut_Ref; + uint32_t *t2 = (uint32_t *)gOut_Ref2; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + uint32_t *q = (uint32_t *)gOut[k]; + uint32_t *q2 = (uint32_t *)gOut2[k]; + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] || t2[j] != q2[j] ) + { + double correct, correct2; + float err, err2; + float test = ((float*) q)[j]; + float test2 = ((float*) q2)[j]; + + if( gTestFastRelaxed ) + correct = f->rfunc.f_fpf( s[j], &correct2 ); + else + correct = f->func.f_fpf( s[j], &correct2 ); + + // Per section 10 paragraph 6, accept any result if an input or output is a infinity or NaN or overflow + if (gTestFastRelaxed || skipNanInf) + { + if (skipNanInf && overflow[j]) + continue; + + // Note: no double rounding here. Reference functions calculate in single precision. + if( IsFloatInfinity(correct) || IsFloatNaN(correct) || + IsFloatInfinity(correct2)|| IsFloatNaN(correct2) || + IsFloatInfinity(s[j]) || IsFloatNaN(s[j]) ) + continue; + } + + typedef int (*CheckForSubnormal) (double,float); // If we are in fast relaxed math, we have a different calculation for the subnormal threshold. + CheckForSubnormal isFloatResultSubnormalPtr; + if( gTestFastRelaxed ) + { + err = Abs_Error( test, correct); + err2 = Abs_Error( test2, correct2); + isFloatResultSubnormalPtr = &IsFloatResultSubnormalAbsError; + } + else + { + err = Ulp_Error( test, correct ); + err2 = Ulp_Error( test2, correct2 ); + isFloatResultSubnormalPtr = &IsFloatResultSubnormal; + } + int fail = ! (fabsf(err) <= float_ulps && fabsf(err2) <= float_ulps); + + if( ftz ) + { + // retry per section 6.5.3.2 + if( (*isFloatResultSubnormalPtr)(correct, float_ulps) ) + { + if( (*isFloatResultSubnormalPtr) (correct2, float_ulps )) + { + fail = fail && ! ( test == 0.0f && test2 == 0.0f ); + if( ! fail ) + { + err = 0.0f; + err2 = 0.0f; + } + } + else + { + fail = fail && ! ( test == 0.0f && fabsf(err2) <= float_ulps); + if( ! fail ) + err = 0.0f; + } + } + else if( (*isFloatResultSubnormalPtr)(correct2, float_ulps ) ) + { + fail = fail && ! ( test2 == 0.0f && fabsf(err) <= float_ulps); + if( ! fail ) + err2 = 0.0f; + } + + + // retry per section 6.5.3.3 + if( IsFloatSubnormal( s[j] ) ) + { + double correctp, correctn; + double correct2p, correct2n; + float errp, err2p, errn, err2n; + + if( skipNanInf ) + feclearexcept(FE_OVERFLOW); + if ( gTestFastRelaxed ) + { + correctp = f->rfunc.f_fpf( 0.0, &correct2p ); + correctn = f->rfunc.f_fpf( -0.0, &correct2n ); + } + else + { + correctp = f->func.f_fpf( 0.0, &correct2p ); + correctn = f->func.f_fpf( -0.0, &correct2n ); + } + + // Per section 10 paragraph 6, accept any result if an input or output is a infinity or NaN or overflow + if( skipNanInf ) + { + if( fetestexcept(FE_OVERFLOW) ) + continue; + + // Note: no double rounding here. Reference functions calculate in single precision. + if( IsFloatInfinity(correctp) || IsFloatNaN(correctp) || + IsFloatInfinity(correctn) || IsFloatNaN(correctn) || + IsFloatInfinity(correct2p) || IsFloatNaN(correct2p) || + IsFloatInfinity(correct2n) || IsFloatNaN(correct2n) ) + continue; + } + + if ( gTestFastRelaxed ) + { + errp = Abs_Error( test, correctp ); + err2p = Abs_Error( test, correct2p ); + errn = Abs_Error( test, correctn ); + err2n = Abs_Error( test, correct2n ); + } + else + { + errp = Ulp_Error( test, correctp ); + err2p = Ulp_Error( test, correct2p ); + errn = Ulp_Error( test, correctn ); + err2n = Ulp_Error( test, correct2n ); + } + + fail = fail && ((!(fabsf(errp) <= float_ulps)) && (!(fabsf(err2p) <= float_ulps)) && + ((!(fabsf(errn) <= float_ulps)) && (!(fabsf(err2n) <= float_ulps))) ); + if( fabsf( errp ) < fabsf(err ) ) + err = errp; + if( fabsf( errn ) < fabsf(err ) ) + err = errn; + if( fabsf( err2p ) < fabsf(err2 ) ) + err2 = err2p; + if( fabsf( err2n ) < fabsf(err2 ) ) + err2 = err2n; + + // retry per section 6.5.3.4 + if( (*isFloatResultSubnormalPtr)( correctp, float_ulps ) || (*isFloatResultSubnormalPtr)( correctn, float_ulps ) ) + { + if( (*isFloatResultSubnormalPtr)( correct2p, float_ulps ) || (*isFloatResultSubnormalPtr)( correct2n, float_ulps ) ) + { + fail = fail && !( test == 0.0f && test2 == 0.0f); + if( ! fail ) + err = err2 = 0.0f; + } + else + { + fail = fail && ! (test == 0.0f && fabsf(err2) <= float_ulps); + if( ! fail ) + err = 0.0f; + } + } + else if( (*isFloatResultSubnormalPtr)( correct2p, float_ulps ) || (*isFloatResultSubnormalPtr)( correct2n, float_ulps ) ) + { + fail = fail && ! (test2 == 0.0f && (fabsf(err) <= float_ulps)); + if( ! fail ) + err2 = 0.0f; + } + } + } + if( fabsf(err ) > maxError0 ) + { + maxError0 = fabsf(err); + maxErrorVal0 = s[j]; + } + if( fabsf(err2 ) > maxError1 ) + { + maxError1 = fabsf(err2); + maxErrorVal1 = s[j]; + } + if( fail ) + { + vlog_error( "\nERROR: %s%s: {%f, %f} ulp error at %a: *{%a, %a} vs. {%a, %a}\n", f->name, sizeNames[k], err, err2, ((float*) gIn)[j], ((float*) gOut_Ref)[j], ((float*) gOut_Ref2)[j], test, test2 ); + error = -1; + goto exit; + } + } + } + } + + if (isFract && gIsInRTZMode) + (void)set_round(oldRoundMode, kfloat); + + if( 0 == (i & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10zu bufferSize:%10zd \n", i, step, bufferSize); + } else + { + vlog("."); + } + fflush(stdout); + } + } + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input array + uint32_t *p = (uint32_t *)gIn; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + p[j] = genrand_int32(d); + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_float); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg(kernels[j], 1, sizeof( gOutBuffer2[j] ), &gOutBuffer2[j]) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( k = 0; k < PERF_LOOP_COUNT; k++ ) + { + + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (bufferSize / sizeof( float ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sf%s", f->name, sizeNames[j] ); + } + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t{%8.2f, %8.2f} @ {%a, %a}", maxError0, maxError1, maxErrorVal0, maxErrorVal1 ); + vlog( "\n" ); + +exit: + // Release + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + clReleaseKernel(kernels[k]); + clReleaseProgram(programs[k]); + } + + return error; +} + +int TestFunc_Double2_Double(const Func *f, MTdata d) +{ + uint64_t i; + uint32_t j, k; + int error; + cl_program programs[ VECTOR_SIZE_COUNT ]; + cl_kernel kernels[ VECTOR_SIZE_COUNT ]; + float maxError0 = 0.0f; + float maxError1 = 0.0f; + int ftz = f->ftz || gForceFTZ; + double maxErrorVal0 = 0.0f; + double maxErrorVal1 = 0.0f; + size_t bufferSize = (gWimpyMode)? gWimpyBufferSize: BUFFER_SIZE; + uint64_t step = bufferSize / sizeof( cl_double ); + int scale = (int)((1ULL<<32) / (16 * bufferSize / sizeof( cl_double )) + 1); + + logFunctionInfo(f->name,sizeof(cl_double),gTestFastRelaxed); + if( gWimpyMode ) + { + step = (1ULL<<32) * gWimpyReductionFactor / (512); + } + + Force64BitFPUPrecision(); + + // Init the kernels + BuildKernelInfo build_info = { gMinVectorSizeIndex, kernels, programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_DoubleFn, + gMaxVectorSizeIndex - gMinVectorSizeIndex, + &build_info ) )) + { + return error; + } +/* + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + if( (error = BuildKernelDouble( f->nameInCode, (int) i, kernels + i, programs + i) ) ) + return error; +*/ + + for( i = 0; i < (1ULL<<32); i += step ) + { + //Init input array + double *p = (double *)gIn; + if( gWimpyMode ) + { + for( j = 0; j < bufferSize / sizeof( cl_double ); j++ ) + p[j] = DoubleFromUInt32((uint32_t) i + j * scale); + } + else + { + for( j = 0; j < bufferSize / sizeof( cl_double ); j++ ) + p[j] = DoubleFromUInt32((uint32_t) i + j); + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + // write garbage into output arrays + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + uint32_t pattern = 0xffffdead; + memset_pattern4(gOut[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer[j], CL_FALSE, 0, bufferSize, gOut[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2(%d) ***\n", error, j ); + goto exit; + } + + memset_pattern4(gOut2[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer2[j], CL_FALSE, 0, bufferSize, gOut2[j], 0, NULL, NULL))) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2b(%d) ***\n", error, j ); + goto exit; + } + } + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_double); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg(kernels[j], 1, sizeof( gOutBuffer2[j] ), &gOutBuffer2[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg(kernels[j], 2, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(gQueue) )) + vlog( "clFlush failed\n" ); + + //Calculate the correctly rounded reference result + double *r = (double *)gOut_Ref; + double *r2 = (double *)gOut_Ref2; + double *s = (double *)gIn; + for( j = 0; j < bufferSize / sizeof( cl_double ); j++ ) + { + long double dd; + r[j] = (double) f->dfunc.f_fpf( s[j], &dd ); + r2[j] = (double) dd; + } + + // Read the data back + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0, bufferSize, gOut[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray failed %d\n", error ); + goto exit; + } + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer2[j], CL_TRUE, 0, bufferSize, gOut2[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray2 failed %d\n", error ); + goto exit; + } + } + + if( gSkipCorrectnessTesting ) + break; + + //Verify data + uint64_t *t = (uint64_t *)gOut_Ref; + uint64_t *t2 = (uint64_t *)gOut_Ref2; + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + uint64_t *q = (uint64_t *)(gOut[k]); + uint64_t *q2 = (uint64_t *)(gOut2[k]); + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] || t2[j] != q2[j] ) + { + double test = ((double*) q)[j]; + double test2 = ((double*) q2)[j]; + long double correct2; + long double correct = f->dfunc.f_fpf( s[j], &correct2 ); + float err = Ulp_Error_Double( test, correct ); + float err2 = Ulp_Error_Double( test2, correct2 ); + int fail = ! (fabsf(err) <= f->double_ulps && fabsf(err2) <= f->double_ulps); + if( ftz ) + { + // retry per section 6.5.3.2 + if( IsDoubleResultSubnormal(correct, f->double_ulps ) ) + { + if( IsDoubleResultSubnormal( correct2, f->double_ulps ) ) + { + fail = fail && ! ( test == 0.0f && test2 == 0.0f ); + if( ! fail ) + { + err = 0.0f; + err2 = 0.0f; + } + } + else + { + fail = fail && ! ( test == 0.0f && fabsf(err2) <= f->double_ulps); + if( ! fail ) + err = 0.0f; + } + } + else if( IsDoubleResultSubnormal( correct2, f->double_ulps ) ) + { + fail = fail && ! ( test2 == 0.0f && fabsf(err) <= f->double_ulps); + if( ! fail ) + err2 = 0.0f; + } + + // retry per section 6.5.3.3 + if( IsDoubleSubnormal( s[j] ) ) + { + long double correct2p, correct2n; + long double correctp = f->dfunc.f_fpf( 0.0, &correct2p ); + long double correctn = f->dfunc.f_fpf( -0.0, &correct2n ); + float errp = Ulp_Error_Double( test, correctp ); + float err2p = Ulp_Error_Double( test, correct2p ); + float errn = Ulp_Error_Double( test, correctn ); + float err2n = Ulp_Error_Double( test, correct2n ); + fail = fail && ((!(fabsf(errp) <= f->double_ulps)) && (!(fabsf(err2p) <= f->double_ulps)) && + ((!(fabsf(errn) <= f->double_ulps)) && (!(fabsf(err2n) <= f->double_ulps))) ); + if( fabsf( errp ) < fabsf(err ) ) + err = errp; + if( fabsf( errn ) < fabsf(err ) ) + err = errn; + if( fabsf( err2p ) < fabsf(err2 ) ) + err2 = err2p; + if( fabsf( err2n ) < fabsf(err2 ) ) + err2 = err2n; + + // retry per section 6.5.3.4 + if( IsDoubleResultSubnormal( correctp, f->double_ulps ) || IsDoubleResultSubnormal( correctn, f->double_ulps ) ) + { + if( IsDoubleResultSubnormal( correct2p, f->double_ulps ) || IsDoubleResultSubnormal( correct2n, f->double_ulps ) ) + { + fail = fail && !( test == 0.0f && test2 == 0.0f); + if( ! fail ) + err = err2 = 0.0f; + } + else + { + fail = fail && ! (test == 0.0f && fabsf(err2) <= f->double_ulps); + if( ! fail ) + err = 0.0f; + } + } + else if( IsDoubleResultSubnormal( correct2p, f->double_ulps ) || IsDoubleResultSubnormal( correct2n, f->double_ulps ) ) + { + fail = fail && ! (test2 == 0.0f && (fabsf(err) <= f->double_ulps)); + if( ! fail ) + err2 = 0.0f; + } + } + } + if( fabsf(err ) > maxError0 ) + { + maxError0 = fabsf(err); + maxErrorVal0 = s[j]; + } + if( fabsf(err2 ) > maxError1 ) + { + maxError1 = fabsf(err2); + maxErrorVal1 = s[j]; + } + if( fail ) + { + vlog_error( "\nERROR: %sD%s: {%f, %f} ulp error at %.13la: *{%.13la, %.13la} vs. {%.13la, %.13la}\n", f->name, sizeNames[k], err, err2, ((double*) gIn)[j], ((double*) gOut_Ref)[j], ((double*) gOut_Ref2)[j], test, test2 ); + error = -1; + goto exit; + } + } + } + } + + if( 0 == (i & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10zu bufferSize:%10zd \n", i, step, bufferSize); + } else + { + vlog("." ); + } + fflush(stdout); + } + } + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input array + double *p = (double*) gIn; + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + p[j] = DoubleFromUInt32(genrand_int32(d) ); + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_double); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg(kernels[j], 1, sizeof( gOutBuffer2[j] ), &gOutBuffer2[j]) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( k = 0; k < PERF_LOOP_COUNT; k++ ) + { + + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (bufferSize / sizeof( double ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sD%s", f->name, sizeNames[j] ); + } + for( ; j < gMaxVectorSizeIndex; j++ ) + vlog( "\t -- " ); + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t{%8.2f, %8.2f} @ {%a, %a}", maxError0, maxError1, maxErrorVal0, maxErrorVal1 ); + vlog( "\n" ); + +exit: + // Release + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + clReleaseKernel(kernels[k]); + clReleaseProgram(programs[k]); + } + + return error; +} + + + diff --git a/test_conformance/math_brute_force/unary_two_results_i.c b/test_conformance/math_brute_force/unary_two_results_i.c new file mode 100644 index 00000000..c4eea8f1 --- /dev/null +++ b/test_conformance/math_brute_force/unary_two_results_i.c @@ -0,0 +1,802 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Utility.h" + +#include +#include +#include "FunctionList.h" + +int TestFunc_FloatI_Float(const Func *f, MTdata); +int TestFunc_DoubleI_Double(const Func *f, MTdata); + +#if defined(__cplusplus) + extern "C" +#endif +const vtbl _unary_two_results_i = { "unary_two_results_i", TestFunc_FloatI_Float, TestFunc_DoubleI_Double }; + +static int BuildKernel( const char *name, int vectorSize, cl_kernel *k, cl_program *p ); +static int BuildKernelDouble( const char *name, int vectorSize, cl_kernel *k, cl_program *p ); + +static int BuildKernel( const char *name, int vectorSize, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global float", sizeNames[vectorSize], "* out, __global int", sizeNames[vectorSize], "* out2, __global float", sizeNames[vectorSize], "* in)\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in[i], out2 + i );\n" + "}\n" + }; + const char *c3[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global float* out, __global int* out2, __global float* in)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " float3 f0 = vload3( 0, in + 3 * i );\n" + " int3 iout = INT_MIN;\n" + " f0 = ", name, "( f0, &iout );\n" + " vstore3( f0, 0, out + 3*i );\n" + " vstore3( iout, 0, out2 + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " int3 iout = INT_MIN;\n" + " float3 f0;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (float3)( in[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " f0 = (float3)( in[3*i], in[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " f0 = ", name, "( f0, &iout );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = f0.y; \n" + " out2[3*i+1] = iout.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = f0.x; \n" + " out2[3*i] = iout.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernel(kern, (cl_uint) kernSize, testName, k, p); + +} + +static int BuildKernelDouble( const char *name, int vectorSize, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double", sizeNames[vectorSize], "* out, __global int", sizeNames[vectorSize], "* out2, __global double", sizeNames[vectorSize], "* in)\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in[i], out2 + i );\n" + "}\n" + }; + const char *c3[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double* out, __global int* out2, __global double* in)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " double3 f0 = vload3( 0, in + 3 * i );\n" + " int3 iout = INT_MIN;\n" + " f0 = ", name, "( f0, &iout );\n" + " vstore3( f0, 0, out + 3*i );\n" + " vstore3( iout, 0, out2 + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " int3 iout = INT_MIN;\n" + " double3 f0;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " f0 = (double3)( in[3*i], NAN, NAN ); \n" + " break;\n" + " case 0:\n" + " f0 = (double3)( in[3*i], in[3*i+1], NAN ); \n" + " break;\n" + " }\n" + " f0 = ", name, "( f0, &iout );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = f0.y; \n" + " out2[3*i+1] = iout.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = f0.x; \n" + " out2[3*i] = iout.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernel(kern, (cl_uint) kernSize, testName, k, p); + +} + +typedef struct BuildKernelInfo +{ + cl_uint offset; // the first vector size to build + cl_kernel *kernels; + cl_program *programs; + const char *nameInCode; +}BuildKernelInfo; + +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernel( info->nameInCode, i, info->kernels + i, info->programs + i ); +} + +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernelDouble( info->nameInCode, i, info->kernels + i, info->programs + i ); +} + +cl_ulong abs_cl_long( cl_long i ); +cl_ulong abs_cl_long( cl_long i ) +{ + cl_long mask = i >> 63; + return (i ^ mask) - mask; +} + +int TestFunc_FloatI_Float(const Func *f, MTdata d) +{ + uint64_t i; + uint32_t j, k; + int error; + cl_program programs[ VECTOR_SIZE_COUNT ]; + cl_kernel kernels[ VECTOR_SIZE_COUNT ]; + float maxError = 0.0f; + int64_t maxError2 = 0; + int ftz = f->ftz || gForceFTZ || 0 == (CL_FP_DENORM & gFloatCapabilities); + float maxErrorVal = 0.0f; + float maxErrorVal2 = 0.0f; + size_t bufferSize = (gWimpyMode)? gWimpyBufferSize: BUFFER_SIZE; + float float_ulps; + uint64_t step = bufferSize / sizeof( float ); + int scale = (int)((1ULL<<32) / (16 * bufferSize / sizeof( float )) + 1); + cl_ulong maxiError; + + logFunctionInfo(f->name,sizeof(cl_float),gTestFastRelaxed); + if( gWimpyMode ) + { + step = (1ULL<<32) * gWimpyReductionFactor / (512); + } + if( gIsEmbedded ) + float_ulps = f->float_embedded_ulps; + else + float_ulps = f->float_ulps; + + maxiError = float_ulps == INFINITY ? CL_ULONG_MAX : 0; + + // Init the kernels + BuildKernelInfo build_info = { gMinVectorSizeIndex, kernels, programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_FloatFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + return error; +/* + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + if( (error = BuildKernel( f->nameInCode, (int) i, kernels + i, programs + i) ) ) + return error; +*/ + + for( i = 0; i < (1ULL<<32); i += step ) + { + //Init input array + uint32_t *p = (uint32_t *)gIn; + if( gWimpyMode ) + { + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + p[j] = (uint32_t) i + j * scale; + } + else + { + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + p[j] = (uint32_t) i + j; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + // write garbage into output arrays + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + uint32_t pattern = 0xffffdead; + memset_pattern4(gOut[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer[j], CL_FALSE, 0, bufferSize, gOut[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2(%d) ***\n", error, j ); + goto exit; + } + + memset_pattern4(gOut2[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer2[j], CL_FALSE, 0, bufferSize, gOut2[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2b(%d) ***\n", error, j ); + goto exit; + } + } + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_float); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gOutBuffer2[j] ), &gOutBuffer2[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(gQueue) )) + vlog( "clFlush failed\n" ); + + //Calculate the correctly rounded reference result + float *r = (float *)gOut_Ref; + int *r2 = (int *)gOut_Ref2; + float *s = (float *)gIn; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + r[j] = (float) f->func.f_fpI( s[j], r2+j ); + + // Read the data back + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0, bufferSize, gOut[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray failed %d\n", error ); + goto exit; + } + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer2[j], CL_TRUE, 0, bufferSize, gOut2[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray2 failed %d\n", error ); + goto exit; + } + } + + if( gSkipCorrectnessTesting ) + break; + + //Verify data + uint32_t *t = (uint32_t *)gOut_Ref; + int32_t *t2 = (int32_t *)gOut_Ref2; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + uint32_t *q = (uint32_t *)(gOut[k]); + int32_t *q2 = (int32_t *)(gOut2[k]); + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] || t2[j] != q2[j] ) + { + float test = ((float*) q)[j]; + int correct2 = INT_MIN; + double correct = f->func.f_fpI( s[j], &correct2 ); + float err = Ulp_Error( test, correct ); + cl_long iErr = (int64_t) q2[j] - (int64_t) correct2; + int fail = ! (fabsf(err) <= float_ulps && abs_cl_long( iErr ) <= maxiError ); + if( ftz ) + { + // retry per section 6.5.3.2 + if( IsFloatResultSubnormal(correct, float_ulps ) ) + { + fail = fail && ! ( test == 0.0f && iErr == 0 ); + if( ! fail ) + err = 0.0f; + } + + // retry per section 6.5.3.3 + if( IsFloatSubnormal( s[j] ) ) + { + int correct5, correct6; + double correct3 = f->func.f_fpI( 0.0, &correct5 ); + double correct4 = f->func.f_fpI( -0.0, &correct6 ); + float err2 = Ulp_Error( test, correct3 ); + float err3 = Ulp_Error( test, correct4 ); + cl_long iErr2 = (long long) q2[j] - (long long) correct5; + cl_long iErr3 = (long long) q2[j] - (long long) correct6; + + // Did +0 work? + if( fabsf(err2) <= float_ulps && abs_cl_long( iErr2 ) <= maxiError ) + { + err = err2; + iErr = iErr2; + fail = 0; + } + // Did -0 work? + else if(fabsf(err3) <= float_ulps && abs_cl_long( iErr3 ) <= maxiError) + { + err = err3; + iErr = iErr3; + fail = 0; + } + + // retry per section 6.5.3.4 + if( fail && (IsFloatResultSubnormal(correct2, float_ulps ) || IsFloatResultSubnormal(correct3, float_ulps )) ) + { + fail = fail && ! ( test == 0.0f && (abs_cl_long( iErr2 ) <= maxiError || abs_cl_long( iErr3 ) <= maxiError) ); + if( ! fail ) + { + err = 0.0f; + iErr = 0; + } + } + } + } + if( fabsf(err ) > maxError ) + { + maxError = fabsf(err); + maxErrorVal = s[j]; + } + if( llabs(iErr) > maxError2 ) + { + maxError2 = llabs(iErr ); + maxErrorVal2 = s[j]; + } + + if( fail ) + { + vlog_error( "\nERROR: %s%s: {%f, %d} ulp error at %a: *{%a, %d} vs. {%a, %d}\n", f->name, sizeNames[k], err, (int) iErr, ((float*) gIn)[j], ((float*) gOut_Ref)[j], ((int*) gOut_Ref2)[j], test, q2[j] ); + error = -1; + goto exit; + } + } + } + } + + if( 0 == (i & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10zu bufferSize:%10zd \n", i, step, bufferSize); + } else + { + vlog("." ); + } + fflush(stdout); + } + } + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input array + uint32_t *p = (uint32_t *)gIn; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + p[j] = genrand_int32(d); + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_float); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gOutBuffer2[j] ), &gOutBuffer2[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( k = 0; k < PERF_LOOP_COUNT; k++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (bufferSize / sizeof( float ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sf%s", f->name, sizeNames[j] ); + } + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t{%8.2f, %lld} @ %a", maxError, maxError2, maxErrorVal ); + vlog( "\n" ); + +exit: + // Release + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + clReleaseKernel(kernels[k]); + clReleaseProgram(programs[k]); + } + + return error; +} + +int TestFunc_DoubleI_Double(const Func *f, MTdata d) +{ + uint64_t i; + uint32_t j, k; + int error; + cl_program programs[ VECTOR_SIZE_COUNT ]; + cl_kernel kernels[ VECTOR_SIZE_COUNT ]; + float maxError = 0.0f; + int64_t maxError2 = 0; + int ftz = f->ftz || gForceFTZ; + double maxErrorVal = 0.0f; + double maxErrorVal2 = 0.0f; + cl_ulong maxiError = f->double_ulps == INFINITY ? CL_ULONG_MAX : 0; + size_t bufferSize = (gWimpyMode)? gWimpyBufferSize: BUFFER_SIZE; + + uint64_t step = bufferSize / sizeof( double ); + int scale = (int)((1ULL<<32) / (16 * bufferSize / sizeof( double )) + 1); + + logFunctionInfo(f->name,sizeof(cl_double),gTestFastRelaxed); + if( gWimpyMode ) + { + step = (1ULL<<32) * gWimpyReductionFactor / (512); + } + + Force64BitFPUPrecision(); + + // Init the kernels + BuildKernelInfo build_info = { gMinVectorSizeIndex, kernels, programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_DoubleFn, + gMaxVectorSizeIndex - gMinVectorSizeIndex, + &build_info ) )) + { + return error; + } +/* + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + if( (error = BuildKernelDouble( f->nameInCode, (int) i, kernels + i, programs + i) ) ) + return error; +*/ + + for( i = 0; i < (1ULL<<32); i += step ) + { + //Init input array + double *p = (double *)gIn; + if( gWimpyMode ) + { + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + p[j] = DoubleFromUInt32((uint32_t) i + j * scale); + } + else + { + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + p[j] = DoubleFromUInt32((uint32_t) i + j); + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + // write garbage into output arrays + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + uint32_t pattern = 0xffffdead; + memset_pattern4(gOut[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer[j], CL_FALSE, 0, bufferSize, gOut[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2(%d) ***\n", error, j ); + goto exit; + } + + memset_pattern4(gOut2[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer2[j], CL_FALSE, 0, bufferSize, gOut2[j], 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2b(%d) ***\n", error, j ); + goto exit; + } + } + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_double); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gOutBuffer2[j] ), &gOutBuffer2[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(gQueue) )) + vlog( "clFlush failed\n" ); + + //Calculate the correctly rounded reference result + double *r = (double *)gOut_Ref; + int *r2 = (int *)gOut_Ref2; + double *s = (double *)gIn; + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + r[j] = (double) f->dfunc.f_fpI( s[j], r2+j ); + + // Read the data back + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0, bufferSize, gOut[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray failed %d\n", error ); + goto exit; + } + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer2[j], CL_TRUE, 0, bufferSize, gOut2[j], 0, NULL, NULL)) ) + { + vlog_error( "ReadArray2 failed %d\n", error ); + goto exit; + } + } + + if( gSkipCorrectnessTesting ) + break; + + //Verify data + uint64_t *t = (uint64_t *)gOut_Ref; + int32_t *t2 = (int32_t *)gOut_Ref2; + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + uint64_t *q = (uint64_t *)(gOut[k]); + int32_t *q2 = (int32_t *)(gOut2[k]); + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] || t2[j] != q2[j] ) + { + double test = ((double*) q)[j]; + int correct2 = INT_MIN; + long double correct = f->dfunc.f_fpI( s[j], &correct2 ); + float err = Ulp_Error_Double( test, correct ); + cl_long iErr = (long long) q2[j] - (long long) correct2; + int fail = ! (fabsf(err) <= f->double_ulps && abs_cl_long( iErr ) <= maxiError ); + if( ftz ) + { + // retry per section 6.5.3.2 + if( IsDoubleResultSubnormal(correct, f->double_ulps ) ) + { + fail = fail && ! ( test == 0.0f && iErr == 0 ); + if( ! fail ) + err = 0.0f; + } + + // retry per section 6.5.3.3 + if( IsDoubleSubnormal( s[j] ) ) + { + int correct5, correct6; + long double correct3 = f->dfunc.f_fpI( 0.0, &correct5 ); + long double correct4 = f->dfunc.f_fpI( -0.0, &correct6 ); + float err2 = Ulp_Error_Double( test, correct3 ); + float err3 = Ulp_Error_Double( test, correct4 ); + cl_long iErr2 = (long long) q2[j] - (long long) correct5; + cl_long iErr3 = (long long) q2[j] - (long long) correct6; + + // Did +0 work? + if( fabsf(err2) <= f->double_ulps && abs_cl_long( iErr2 ) <= maxiError ) + { + err = err2; + iErr = iErr2; + fail = 0; + } + // Did -0 work? + else if(fabsf(err3) <= f->double_ulps && abs_cl_long( iErr3 ) <= maxiError) + { + err = err3; + iErr = iErr3; + fail = 0; + } + + // retry per section 6.5.3.4 + if( fail && (IsDoubleResultSubnormal( correct2, f->double_ulps ) || IsDoubleResultSubnormal( correct3, f->double_ulps )) ) + { + fail = fail && ! ( test == 0.0f && (abs_cl_long( iErr2 ) <= maxiError || abs_cl_long( iErr3 ) <= maxiError) ); + if( ! fail ) + { + err = 0.0f; + iErr = 0; + } + } + } + } + if( fabsf(err ) > maxError ) + { + maxError = fabsf(err); + maxErrorVal = s[j]; + } + if( llabs(iErr) > maxError2 ) + { + maxError2 = llabs(iErr ); + maxErrorVal2 = s[j]; + } + + if( fail ) + { + vlog_error( "\nERROR: %sD%s: {%f, %d} ulp error at %.13la: *{%.13la, %d} vs. {%.13la, %d}\n", f->name, sizeNames[k], err, (int) iErr, ((double*) gIn)[j], ((double*) gOut_Ref)[j], ((int*) gOut_Ref2)[j], test, q2[j] ); + error = -1; + goto exit; + } + } + } + } + + if( 0 == (i & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10zu bufferSize:%10zd \n", i, step, bufferSize); + } else + { + vlog("." ); + } + fflush(stdout); + } + } + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input array + double *p = (double *)gIn; + + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + p[j] = DoubleFromUInt32(genrand_int32(d)); + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_double); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gOutBuffer2[j] ), &gOutBuffer2[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 2, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( k = 0; k < PERF_LOOP_COUNT; k++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILED -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (bufferSize / sizeof( double ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sd%s", f->name, sizeNames[j] ); + } + for( ; j < gMaxVectorSizeIndex; j++ ) + vlog( "\t -- " ); + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t{%8.2f, %lld} @ %a", maxError, maxError2, maxErrorVal ); + vlog( "\n" ); + +exit: + // Release + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + clReleaseKernel(kernels[k]); + clReleaseProgram(programs[k]); + } + + return error; +} + + + diff --git a/test_conformance/math_brute_force/unary_u.c b/test_conformance/math_brute_force/unary_u.c new file mode 100644 index 00000000..131d1e7e --- /dev/null +++ b/test_conformance/math_brute_force/unary_u.c @@ -0,0 +1,694 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "Utility.h" + +#include +#include "FunctionList.h" + +int TestFunc_Float_UInt(const Func *f, MTdata); +int TestFunc_Double_ULong(const Func *f, MTdata); + +#if defined( __cplusplus) + extern "C" +#endif +const vtbl _unary_u = { "unary_u", TestFunc_Float_UInt, TestFunc_Double_ULong }; + + +static int BuildKernel( const char *name, int vectorSize, cl_kernel *k, cl_program *p ); +static int BuildKernelDouble( const char *name, int vectorSize, cl_kernel *k, cl_program *p ); + +static int BuildKernel( const char *name, int vectorSize, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { + "__kernel void math_kernel", sizeNames[vectorSize], "( __global float", sizeNames[vectorSize], "* out, __global uint", sizeNames[vectorSize], "* in)\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in[i] );\n" + "}\n" + }; + const char *c3[] = { "__kernel void math_kernel", sizeNames[vectorSize], "( __global float* out, __global uint* in)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " uint3 u0 = vload3( 0, in + 3 * i );\n" + " float3 f0 = ", name, "( u0 );\n" + " vstore3( f0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " uint3 u0;\n" + " float3 f0;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " u0 = (uint3)( in[3*i], 0xdead, 0xdead ); \n" + " break;\n" + " case 0:\n" + " u0 = (uint3)( in[3*i], in[3*i+1], 0xdead ); \n" + " break;\n" + " }\n" + " f0 = ", name, "( u0 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = f0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = f0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernel(kern, (cl_uint) kernSize, testName, k, p); +} + +static int BuildKernelDouble( const char *name, int vectorSize, cl_kernel *k, cl_program *p ) +{ + const char *c[] = { + "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double", sizeNames[vectorSize], "* out, __global ulong", sizeNames[vectorSize], "* in)\n" + "{\n" + " int i = get_global_id(0);\n" + " out[i] = ", name, "( in[i] );\n" + "}\n" + }; + + const char *c3[] = { "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n", + "__kernel void math_kernel", sizeNames[vectorSize], "( __global double* out, __global ulong* in)\n" + "{\n" + " size_t i = get_global_id(0);\n" + " if( i + 1 < get_global_size(0) )\n" + " {\n" + " ulong3 u0 = vload3( 0, in + 3 * i );\n" + " double3 f0 = ", name, "( u0 );\n" + " vstore3( f0, 0, out + 3*i );\n" + " }\n" + " else\n" + " {\n" + " size_t parity = i & 1; // Figure out how many elements are left over after BUFFER_SIZE % (3*sizeof(float)). Assume power of two buffer size \n" + " ulong3 u0;\n" + " switch( parity )\n" + " {\n" + " case 1:\n" + " u0 = (ulong3)( in[3*i], 0xdeaddeaddeaddeadUL, 0xdeaddeaddeaddeadUL ); \n" + " break;\n" + " case 0:\n" + " u0 = (ulong3)( in[3*i], in[3*i+1], 0xdeaddeaddeaddeadUL ); \n" + " break;\n" + " }\n" + " double3 f0 = ", name, "( u0 );\n" + " switch( parity )\n" + " {\n" + " case 0:\n" + " out[3*i+1] = f0.y; \n" + " // fall through\n" + " case 1:\n" + " out[3*i] = f0.x; \n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + const char **kern = c; + size_t kernSize = sizeof(c)/sizeof(c[0]); + + if( sizeValues[vectorSize] == 3 ) + { + kern = c3; + kernSize = sizeof(c3)/sizeof(c3[0]); + } + + + char testName[32]; + snprintf( testName, sizeof( testName ) -1, "math_kernel%s", sizeNames[vectorSize] ); + + return MakeKernel(kern, (cl_uint) kernSize, testName, k, p); +} + +typedef struct BuildKernelInfo +{ + cl_uint offset; // the first vector size to build + cl_kernel *kernels; + cl_program *programs; + const char *nameInCode; +}BuildKernelInfo; + +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_FloatFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernel( info->nameInCode, i, info->kernels + i, info->programs + i ); +} + +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ); +static cl_int BuildKernel_DoubleFn( cl_uint job_id, cl_uint thread_id UNUSED, void *p ) +{ + BuildKernelInfo *info = (BuildKernelInfo*) p; + cl_uint i = info->offset + job_id; + return BuildKernelDouble( info->nameInCode, i, info->kernels + i, info->programs + i ); +} + +int TestFunc_Float_UInt(const Func *f, MTdata d) +{ + uint64_t i; + uint32_t j, k; + int error; + cl_program programs[ VECTOR_SIZE_COUNT ]; + cl_kernel kernels[ VECTOR_SIZE_COUNT ]; + float maxError = 0.0f; + int ftz = f->ftz || gForceFTZ || 0 == (CL_FP_DENORM & gFloatCapabilities); + float maxErrorVal = 0.0f; + size_t bufferSize = (gWimpyMode)? gWimpyBufferSize: BUFFER_SIZE; + + uint64_t step = bufferSize / sizeof( float ); + int scale = (int)((1ULL<<32) / (16 * bufferSize / sizeof( double )) + 1); + int isRangeLimited = 0; + float float_ulps; + float half_sin_cos_tan_limit = 0; + + logFunctionInfo(f->name,sizeof(cl_float),gTestFastRelaxed); + if( gWimpyMode ) + { + step = (1ULL<<32) * gWimpyReductionFactor / (512); + } + if( gIsEmbedded) + float_ulps = f->float_embedded_ulps; + else + float_ulps = f->float_ulps; + + // Init the kernels + BuildKernelInfo build_info = { gMinVectorSizeIndex, kernels, programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_FloatFn, gMaxVectorSizeIndex - gMinVectorSizeIndex, &build_info ) )) + return error; +/* + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + if( (error = BuildKernel( f->nameInCode, (int) i, kernels + i, programs + i) ) ) + return error; +*/ + + if( 0 == strcmp( f->name, "half_sin") || 0 == strcmp( f->name, "half_cos") ) + { + isRangeLimited = 1; + half_sin_cos_tan_limit = 1.0f + float_ulps * (FLT_EPSILON/2.0f); // out of range results from finite inputs must be in [-1,1] + } + else if( 0 == strcmp( f->name, "half_tan")) + { + isRangeLimited = 1; + half_sin_cos_tan_limit = INFINITY; // out of range resut from finite inputs must be numeric + } + + + for( i = 0; i < (1ULL<<32); i += step ) + { + //Init input array + uint32_t *p = (uint32_t *)gIn; + if( gWimpyMode ) + { + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + p[j] = (uint32_t) i + j * scale; + } + else + { + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + p[j] = (uint32_t) i + j; + } + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL))) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + // write garbage into output arrays + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + uint32_t pattern = 0xffffdead; + memset_pattern4(gOut[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer[j], CL_FALSE, 0, bufferSize, gOut[j], 0, NULL, NULL))) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2(%d) ***\n", error, j ); + goto exit; + } + } + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_float); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ))){ LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL))) + { + vlog_error( "FAILURE -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(gQueue) )) + vlog( "clFlush failed\n" ); + + //Calculate the correctly rounded reference result + float *r = (float*) gOut_Ref; + cl_uint *s = (cl_uint*) gIn; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + r[j] = (float) f->func.f_u( s[j] ); + + // Read the data back + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0, bufferSize, gOut[j], 0, NULL, NULL))) + { + vlog_error( "ReadArray failed %d\n", error ); + goto exit; + } + } + + if( gSkipCorrectnessTesting ) + break; + + + //Verify data + uint32_t *t = (uint32_t*) gOut_Ref; + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + uint32_t *q = (uint32_t*)(gOut[k]); + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + float test = ((float*) q)[j]; + double correct = f->func.f_u( s[j] ); + float err = Ulp_Error( test, correct ); + int fail = ! (fabsf(err) <= float_ulps); + + // half_sin/cos/tan are only valid between +-2**16, Inf, NaN + if( isRangeLimited && fabsf(s[j]) > MAKE_HEX_FLOAT(0x1.0p16f, 0x1L, 16) && fabsf(s[j]) < INFINITY ) + { + if( fabsf( test ) <= half_sin_cos_tan_limit ) + { + err = 0; + fail = 0; + } + } + + if( fail ) + { + if( ftz ) + { + // retry per section 6.5.3.2 + if( IsFloatResultSubnormal(correct, float_ulps) ) + { + fail = fail && ( test != 0.0f ); + if( ! fail ) + err = 0.0f; + } + } + } + if( fabsf(err ) > maxError ) + { + maxError = fabsf(err); + maxErrorVal = s[j]; + } + if( fail ) + { + vlog_error( "\n%s%s: %f ulp error at 0x%8.8x: *%a vs. %a\n", f->name, sizeNames[k], err, ((uint32_t*) gIn)[j], ((float*) gOut_Ref)[j], test ); + error = -1; + goto exit; + } + } + } + } + + if( 0 == (i & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10zu bufferSize:%10zd \n", i, step, bufferSize); + } else + { + vlog("." ); + } + fflush(stdout); + } + } + + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input array + uint32_t *p = (uint32_t*)gIn; + if( strstr( f->name, "exp" ) || strstr( f->name, "sin" ) || strstr( f->name, "cos" ) || strstr( f->name, "tan" ) ) + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + ((float*)p)[j] = (float) genrand_real1(d); + else if( strstr( f->name, "log" ) ) + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + p[j] = genrand_int32(d) & 0x7fffffff; + else + for( j = 0; j < bufferSize / sizeof( float ); j++ ) + p[j] = genrand_int32(d); + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_float); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( k = 0; k < PERF_LOOP_COUNT; k++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILURE -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (bufferSize / sizeof( float ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sf%s", f->name, sizeNames[j] ); + } + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t%8.2f @ %a", maxError, maxErrorVal ); + vlog( "\n" ); + +exit: + // Release + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + clReleaseKernel(kernels[k]); + clReleaseProgram(programs[k]); + } + + return error; +} + +static cl_ulong random64( MTdata d ) +{ + return (cl_ulong) genrand_int32(d) | ((cl_ulong) genrand_int32(d) << 32); +} + +int TestFunc_Double_ULong(const Func *f, MTdata d) +{ + uint64_t i; + uint32_t j, k; + int error; + cl_program programs[ VECTOR_SIZE_COUNT ]; + cl_kernel kernels[ VECTOR_SIZE_COUNT ]; + float maxError = 0.0f; + int ftz = f->ftz || gForceFTZ; + double maxErrorVal = 0.0f; + size_t bufferSize = (gWimpyMode)? gWimpyBufferSize: BUFFER_SIZE; + uint64_t step = bufferSize / sizeof( cl_double ); + + logFunctionInfo(f->name,sizeof(cl_double),gTestFastRelaxed); + if( gWimpyMode ) + { + step = (1ULL<<32) * gWimpyReductionFactor / (512); + } + Force64BitFPUPrecision(); + + // Init the kernels + BuildKernelInfo build_info = { gMinVectorSizeIndex, kernels, programs, f->nameInCode }; + if( (error = ThreadPool_Do( BuildKernel_DoubleFn, + gMaxVectorSizeIndex - gMinVectorSizeIndex, + &build_info ) )) + { + return error; + } +/* + for( i = gMinVectorSizeIndex; i < gMaxVectorSizeIndex; i++ ) + if( (error = BuildKernelDouble( f->nameInCode, (int) i, kernels + i, programs + i) ) ) + return error; +*/ + + for( i = 0; i < (1ULL<<32); i += step ) + { + //Init input array + cl_ulong *p = (cl_ulong *)gIn; + for( j = 0; j < bufferSize / sizeof( cl_ulong ); j++ ) + p[j] = random64(d); + + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL))) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + // write garbage into output arrays + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + uint32_t pattern = 0xffffdead; + memset_pattern4(gOut[j], &pattern, bufferSize); + if( (error = clEnqueueWriteBuffer(gQueue, gOutBuffer[j], CL_FALSE, 0, bufferSize, gOut[j], 0, NULL, NULL))) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer2(%d) ***\n", error, j ); + goto exit; + } + } + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_double); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ))){ LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL))) + { + vlog_error( "FAILURE -- could not execute kernel\n" ); + goto exit; + } + } + + // Get that moving + if( (error = clFlush(gQueue) )) + vlog( "clFlush failed\n" ); + + //Calculate the correctly rounded reference result + double *r = (double*) gOut_Ref; + cl_ulong *s = (cl_ulong*) gIn; + for( j = 0; j < bufferSize / sizeof( cl_double ); j++ ) + r[j] = (double) f->dfunc.f_u( s[j] ); + + // Read the data back + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + if( (error = clEnqueueReadBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0, bufferSize, gOut[j], 0, NULL, NULL))) + { + vlog_error( "ReadArray failed %d\n", error ); + goto exit; + } + } + + if( gSkipCorrectnessTesting ) + break; + + + //Verify data + uint64_t *t = (uint64_t*) gOut_Ref; + for( j = 0; j < bufferSize / sizeof( cl_double ); j++ ) + { + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + uint64_t *q = (uint64_t*)(gOut[k]); + + // If we aren't getting the correctly rounded result + if( t[j] != q[j] ) + { + double test = ((double*) q)[j]; + long double correct = f->dfunc.f_u( s[j] ); + float err = Ulp_Error_Double(test, correct); + int fail = ! (fabsf(err) <= f->double_ulps); + + // half_sin/cos/tan are only valid between +-2**16, Inf, NaN + if( fail ) + { + if( ftz ) + { + // retry per section 6.5.3.2 + if( IsDoubleResultSubnormal(correct, f->double_ulps) ) + { + fail = fail && ( test != 0.0 ); + if( ! fail ) + err = 0.0f; + } + } + } + if( fabsf(err ) > maxError ) + { + maxError = fabsf(err); + maxErrorVal = s[j]; + } + if( fail ) + { + vlog_error( "\n%s%sD: %f ulp error at 0x%16.16llx: *%.13la vs. %.13la\n", f->name, sizeNames[k], err, ((uint64_t*) gIn)[j], ((double*) gOut_Ref)[j], test ); + error = -1; + goto exit; + } + } + } + } + + if( 0 == (i & 0x0fffffff) ) + { + if (gVerboseBruteForce) + { + vlog("base:%14u step:%10zu bufferSize:%10zd \n", i, step, bufferSize); + } else + { + vlog("." ); + } + fflush(stdout); + } + } + + if( ! gSkipCorrectnessTesting ) + { + if( gWimpyMode ) + vlog( "Wimp pass" ); + else + vlog( "passed" ); + } + + if( gMeasureTimes ) + { + //Init input array + double *p = (double*) gIn; + + for( j = 0; j < bufferSize / sizeof( double ); j++ ) + p[j] = random64(d); + if( (error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0, bufferSize, gIn, 0, NULL, NULL) )) + { + vlog_error( "\n*** Error %d in clEnqueueWriteBuffer ***\n", error ); + return error; + } + + + // Run the kernels + for( j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++ ) + { + size_t vectorSize = sizeValues[j] * sizeof(cl_double); + size_t localCount = (bufferSize + vectorSize - 1) / vectorSize; + if( ( error = clSetKernelArg(kernels[j], 0, sizeof( gOutBuffer[j] ), &gOutBuffer[j] ) )) { LogBuildError(programs[j]); goto exit; } + if( ( error = clSetKernelArg( kernels[j], 1, sizeof( gInBuffer ), &gInBuffer ) )) { LogBuildError(programs[j]); goto exit; } + + double sum = 0.0; + double bestTime = INFINITY; + for( k = 0; k < PERF_LOOP_COUNT; k++ ) + { + uint64_t startTime = GetTime(); + if( (error = clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL, &localCount, NULL, 0, NULL, NULL)) ) + { + vlog_error( "FAILURE -- could not execute kernel\n" ); + goto exit; + } + + // Make sure OpenCL is done + if( (error = clFinish(gQueue) ) ) + { + vlog_error( "Error %d at clFinish\n", error ); + goto exit; + } + + uint64_t endTime = GetTime(); + double time = SubtractTime( endTime, startTime ); + sum += time; + if( time < bestTime ) + bestTime = time; + } + + if( gReportAverageTimes ) + bestTime = sum / PERF_LOOP_COUNT; + double clocksPerOp = bestTime * (double) gDeviceFrequency * gComputeDevices * gSimdSize * 1e6 / (bufferSize / sizeof( double ) ); + vlog_perf( clocksPerOp, LOWER_IS_BETTER, "clocks / element", "%sD%s", f->name, sizeNames[j] ); + } + for( ; j < gMaxVectorSizeIndex; j++ ) + vlog( "\t -- " ); + } + + if( ! gSkipCorrectnessTesting ) + vlog( "\t%8.2f @ %a", maxError, maxErrorVal ); + vlog( "\n" ); + +exit: + // Release + for( k = gMinVectorSizeIndex; k < gMaxVectorSizeIndex; k++ ) + { + clReleaseKernel(kernels[k]); + clReleaseProgram(programs[k]); + } + + return error; +} + + diff --git a/test_conformance/mem_host_flags/CMakeLists.txt b/test_conformance/mem_host_flags/CMakeLists.txt new file mode 100644 index 00000000..7325b34e --- /dev/null +++ b/test_conformance/mem_host_flags/CMakeLists.txt @@ -0,0 +1,20 @@ +set(MODULE_NAME MEM_HOST_FLAGS) + +set(${MODULE_NAME}_SOURCES + main.cpp + mem_host_buffer.cpp + mem_host_image.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/genericThread.cpp + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/typeWrappers.cpp + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/ThreadPool.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) diff --git a/test_conformance/mem_host_flags/C_host_memory_block.h b/test_conformance/mem_host_flags/C_host_memory_block.h new file mode 100644 index 00000000..90e0b6b3 --- /dev/null +++ b/test_conformance/mem_host_flags/C_host_memory_block.h @@ -0,0 +1,252 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef test_conformance_cHost_MemoryBlock_h +#define test_conformance_cHost_MemoryBlock_h + +#include "../../test_common/harness/compat.h" + +#include +#include +#include + +template < class T> class C_host_memory_block +{ +public: + int num_elements; + int element_size; + T *pData; + + C_host_memory_block(); + ~C_host_memory_block(); + void Init(int num_elem, T &value); + void Init(int num_elem); + void Set_to(T & val); + void Set_to_zero(); + bool Equal_to(T &val); + size_t Count(T &val); + bool Equal(C_host_memory_block < T > & another); + bool Equal_rect(C_host_memory_block < T > & another, + size_t * host_origin, + size_t * region, + size_t host_row_pitch, + size_t host_slice_pitch); + bool Equal(T *pData, int num_elements); + + bool Equal_rect_from_orig(C_host_memory_block < T > & another, + size_t * soffset, + size_t * region, + size_t host_row_pitch, + size_t host_slice_pitch); + + bool Equal_rect_from_orig(T* another_pdata, + size_t * soffset, + size_t * region, + size_t host_row_pitch, + size_t host_slice_pitch); +}; + +template < class T > +C_host_memory_block::C_host_memory_block() +{ + pData = NULL; + element_size = sizeof (T); + num_elements = 0; +} + +template < class T> +C_host_memory_block::~C_host_memory_block() +{ + if (pData!=NULL) delete pData; + num_elements = 0; +} + +template < class T > +void C_host_memory_block::Init(int num_elem, T & value) +{ + if (pData!=NULL) delete pData; + pData= new T [num_elem]; + for (int i=0; i +void C_host_memory_block::Init(int num_elem) +{ + if (pData!=NULL) delete pData; + pData = new T [num_elem]; + for (int i=0; i +void C_host_memory_block::Set_to_zero() +{ + T v = 0; + Set_to(v); +} + +template < class T > +void C_host_memory_block::Set_to(T &val) +{ + for (int i=0; i +bool C_host_memory_block::Equal_to(T &val) +{ + int count = 0; + + for (int i=0; i +bool C_host_memory_block::Equal(C_host_memory_block < T > & another) +{ + int count = 0; + + for (int i=0; i +bool C_host_memory_block::Equal(T *pIn_Data, int Innum_elements) +{ + if (this->num_elements!= Innum_elements) + return false; + + int count = 0; + + for (int i=0; i +size_t C_host_memory_block::Count(T &val) +{ + size_t count = 0; + for (int i=0; i +bool C_host_memory_block::Equal_rect(C_host_memory_block < T > & another, + size_t * soffset, + size_t * region, + size_t host_row_pitch, + size_t host_slice_pitch) +{ + size_t row_pitch = host_row_pitch ? host_row_pitch : region[0]; + size_t slice_pitch = host_slice_pitch ? host_row_pitch : region[1]; + + size_t count = 0; + + size_t total = region[0] * region[1] * region[2]; + + size_t x, y, z; + size_t orig = (size_t)(soffset[0] + row_pitch*soffset[1] + slice_pitch * soffset[2]); + for (z=0; z +bool C_host_memory_block::Equal_rect_from_orig(C_host_memory_block < T > & another, + size_t * soffset, + size_t * region, + size_t host_row_pitch, + size_t host_slice_pitch) +{ + size_t row_pitch = host_row_pitch ? host_row_pitch : region[0]; + size_t slice_pitch = host_slice_pitch ? host_row_pitch : region[1]; + + size_t count = 0; + + size_t total = region[0] * region[1] * region[2]; + + size_t x, y, z; + size_t orig = soffset[0] + row_pitch * soffset[1] + slice_pitch * soffset[2]; + for (z=0; z +bool C_host_memory_block::Equal_rect_from_orig(T* another_pdata, + size_t * soffset, + size_t * region, + size_t host_row_pitch, + size_t host_slice_pitch) +{ + size_t row_pitch = host_row_pitch ? host_row_pitch : region[0]; + size_t slice_pitch = host_slice_pitch ? host_row_pitch : region[1]; + + size_t count = 0; + + size_t total = region[0] * region[1] * region[2]; + + size_t x, y, z; + size_t orig = soffset[0] + row_pitch*soffset[1] + slice_pitch * soffset[2]; + for (z=0; z +#include + +#include "procs.h" +#include "C_host_memory_block.h" + +#define TEST_VALUE 5 +typedef cl_char TEST_ELEMENT_TYPE; + +enum {SUCCESS, FAILURE=-1000}; + +extern const char *buffer_write_kernel_code[]; + +enum BUFFER_TYPE {_BUFFER, _Sub_BUFFER}; + +template < class T > class cBuffer_checker +{ +public: + cBuffer_checker(cl_device_id deviceID, cl_context context, + cl_command_queue queue); + ~cBuffer_checker(); + + cl_device_id m_deviceID; + cl_context m_context; + cl_command_queue m_queue; + + clMemWrapper m_buffer, m_buffer_parent; + enum BUFFER_TYPE m_buffer_type; + + cl_buffer_region m_sub_buffer_region; + + cl_int err; + cl_bool m_blocking; + cl_mem_flags buffer_mem_flag; + + C_host_memory_block host_m_0, host_m_1, host_m_2; + int m_nNumber_elements; + + void *pData, *pData2; + + void * pHost_ptr; // the host ptr at creation + + size_t buffer_origin[3]; + size_t host_origin[3]; + size_t region[3]; + size_t buffer_row_pitch; + size_t buffer_slice_pitch; + size_t host_row_pitch; + size_t host_slice_pitch; + + size_t buffer_origin_bytes[3]; + size_t host_origin_bytes[3]; + size_t region_bytes[3]; + size_t buffer_row_pitch_bytes; + size_t buffer_slice_pitch_bytes; + size_t host_row_pitch_bytes; + size_t host_slice_pitch_bytes; + + cl_int CreateBuffer(cl_mem_flags buffer_mem_flag, void * pdata); + int get_block_size_bytes() { return (int)(m_nNumber_elements * sizeof(T)); }; + virtual cl_int SetupBuffer() = 0; + + virtual cl_int Setup_Test_Environment(); + + virtual cl_int SetupASSubBuffer(cl_mem_flags parent_buffer_flag); + + virtual cl_int verify(cl_int err, cl_event & event); + + virtual cl_int Check_GetMemObjectInfo(cl_mem_flags buffer_mem_flag); + + void Init_rect(int bufforg[3], int host_org[3], int region[3], + int buffer_pitch[2], int host_pitch[2]); + + void Init_rect(); + + virtual cl_int verify_RW_Buffer() = 0; + virtual cl_int verify_RW_Buffer_rect() = 0; + virtual cl_int verify_RW_Buffer_mapping() = 0; +}; + +template < class T > +cBuffer_checker::cBuffer_checker(cl_device_id deviceID, cl_context context, + cl_command_queue queue) +{ + m_nNumber_elements = 0; + + m_deviceID = deviceID; + m_context = context; + m_queue = queue; + + m_blocking = false; + + buffer_mem_flag = CL_MEM_READ_WRITE; + pData = pData2 = NULL; + + buffer_origin[0] = buffer_origin[1] = buffer_origin[2] = 0; + host_origin[0] = host_origin[1] = host_origin[2] = 0; + region[0] = region[1] = region[2] = 0; + buffer_row_pitch = buffer_slice_pitch = host_row_pitch = host_slice_pitch = 0; + + buffer_origin_bytes[0] = buffer_origin_bytes[1] = buffer_origin_bytes[2] = 0; + host_origin_bytes[0] = host_origin_bytes[1] = host_origin_bytes[2] = 0; + region_bytes[0] = region_bytes[1] = region_bytes[2] = 0; + buffer_row_pitch_bytes = buffer_slice_pitch_bytes = 0; + host_row_pitch_bytes = host_slice_pitch_bytes = 0; + + pHost_ptr = NULL; +} + +template < class T > +cBuffer_checker::~cBuffer_checker() +{ +} + +template < class T > +cl_int cBuffer_checker::SetupBuffer() +{ + m_buffer_type = _BUFFER; + return CL_SUCCESS; +} + +template < class T > +cl_int cBuffer_checker::Setup_Test_Environment() +{ + return CL_SUCCESS; +} + +template < class T > +cl_int cBuffer_checker::SetupASSubBuffer(cl_mem_flags parent_buffer_flag) +{ + m_buffer_type = _Sub_BUFFER; + + int supersize = 8000; + this-> m_nNumber_elements = 1000; + T vv1= TEST_VALUE; + + int block_size_in_byte = (int)(supersize * sizeof(T)); + + this->host_m_0.Init(supersize); + + m_buffer_parent = clCreateBuffer(this->m_context, parent_buffer_flag, + block_size_in_byte, this->host_m_0.pData, &err); + test_error(err, "clCreateBuffer error"); + + int size = this->m_nNumber_elements; // the size of subbuffer in elements + + cl_uint base_addr_align_bits; + err = clGetDeviceInfo(m_deviceID, CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof base_addr_align_bits, &base_addr_align_bits, NULL); + test_error(err,"clGetDeviceInfo for CL_DEVICE_MEM_BASE_ADDR_ALIGN"); + + int base_addr_align_bytes = base_addr_align_bits/8; + + int buffer_origin[3] = {base_addr_align_bytes, 0, 0}; + int host_origin[3] = {0, 0, 0}; + int region[3] = {size, 1, 1}; + int buffer_pitch[2] = {0, 0}; + int host_pitch[2] = {0, 0}; + this->Init_rect(buffer_origin, host_origin, region, buffer_pitch, host_pitch); + + this->m_nNumber_elements = size; // the size of subbuffer in elements + this->host_m_1.Init(this->m_nNumber_elements, vv1); + + this->m_sub_buffer_region.origin = this->buffer_origin_bytes[0]; // in bytes + this->m_sub_buffer_region.size = this->region_bytes[0]; + + cl_event event; + cl_int err = CL_SUCCESS; + err = clEnqueueReadBufferRect(this->m_queue, m_buffer_parent, CL_TRUE, + this->buffer_origin_bytes, + this->host_origin_bytes, + this->region_bytes, + this->buffer_row_pitch_bytes, + this->buffer_slice_pitch_bytes, + this->host_row_pitch_bytes, + this->host_slice_pitch_bytes, + this->host_m_1.pData, + 0, NULL, &event); // update the mem_1 + + if (err == CL_SUCCESS && (parent_buffer_flag & (CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS))) { + log_error("Calling clEnqueueReadBufferRect on a memory object created with the CL_MEM_HOST_WRITE_ONLY flag or the CL_MEM_HOST_NO_ACCESS flag should not return CL_SUCCESS\n"); + err = FAILURE; + return err; + + if (this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error"); + } + } else { + err = CL_SUCCESS; + } + + cl_mem_flags f; + if (parent_buffer_flag & CL_MEM_HOST_READ_ONLY) + f = CL_MEM_HOST_READ_ONLY; + else if (parent_buffer_flag & CL_MEM_HOST_WRITE_ONLY) + f = CL_MEM_HOST_WRITE_ONLY; + else if (parent_buffer_flag & CL_MEM_HOST_NO_ACCESS) + f = CL_MEM_HOST_NO_ACCESS; + + m_buffer = clCreateSubBuffer(m_buffer_parent, f, CL_BUFFER_CREATE_TYPE_REGION, + &(this->m_sub_buffer_region), &err); + test_error(err, "clCreateSubBuffer error"); + + if (parent_buffer_flag | CL_MEM_USE_HOST_PTR) + { + this->pHost_ptr = (this->host_m_0.pData + this->m_sub_buffer_region.origin/sizeof(T)); + } + + T vv2 = 0; + this->host_m_2.Init(this->m_nNumber_elements, vv2); + + return err; +} + +template < class T > +cl_int cBuffer_checker::verify(cl_int err, cl_event & event) +{ + return CL_SUCCESS; +} + +template < class T > +cl_int cBuffer_checker::CreateBuffer(cl_mem_flags buffer_mem_flag, void *pdata) +{ + cl_int err = CL_SUCCESS; + int block_size_in_byte= m_nNumber_elements* sizeof(T); + + m_buffer = clCreateBuffer(m_context, buffer_mem_flag, block_size_in_byte, pdata, &err); + + return err; +}; + +template < class T > +cl_int cBuffer_checker::Check_GetMemObjectInfo(cl_mem_flags buffer_mem_flag) +{ + cl_int err = CL_SUCCESS; + cl_mem_flags buffer_mem_flag_Check; + err = clGetMemObjectInfo(this->m_buffer, CL_MEM_FLAGS, sizeof(cl_mem_flags), + &buffer_mem_flag_Check, NULL); + + if (buffer_mem_flag_Check != buffer_mem_flag) { + log_error("clGetMemObjectInfo result differs from the specified result\n"); + return err; + } + + cl_uint count = 0; + err = clGetMemObjectInfo(this->m_buffer, CL_MEM_REFERENCE_COUNT, + sizeof(cl_uint), &count, NULL); + + if (count > 1) + log_info("========= buffer count %d\n", count); + + test_error(err, "clGetMemObjectInfo failed"); + + return err; +} + +template < class T > +void cBuffer_checker::Init_rect () +{ + int buffer_origin[3] = {10, 0, 0}; + int host_origin[3] = {10, 0, 0}; + int region[3] = {8, 1, 1}; + int buffer_pitch[2] = {0, 0}; + int host_pitch[2] = {0, 0}; + + this->Init_rect(buffer_origin, host_origin, region, buffer_pitch, host_pitch); +} + +template < class T > +void cBuffer_checker::Init_rect(int bufforg[3], int host_org[3], + int region_in[3], int buffer_pitch[2], int host_pitch[2]) +{ + buffer_origin[0] = bufforg[0]; + buffer_origin[1] = bufforg[1]; + buffer_origin[2] = bufforg[2]; + + host_origin[0] = host_org[0]; + host_origin[1] = host_org[1]; + host_origin[2] = host_org[2]; + + region[0] = region_in[0]; + region[1] = region_in[1]; + region[2] = region_in[2]; + + buffer_row_pitch = buffer_pitch[0]; + buffer_slice_pitch = buffer_pitch[1]; + host_row_pitch = host_pitch[0]; + host_slice_pitch = host_pitch[1]; + + int sizeof_element = sizeof(T); + for (int k=0; k<3; k++) + { + buffer_origin_bytes[k] = buffer_origin[k] * sizeof_element; + host_origin_bytes [k] = host_origin[k] * sizeof_element; + } + + region_bytes[0] = region[0] * sizeof_element; + region_bytes[1] = region[1]; + region_bytes[2] = region[2]; + buffer_row_pitch_bytes = buffer_row_pitch* sizeof_element; + buffer_slice_pitch_bytes = buffer_slice_pitch* sizeof_element; + host_row_pitch_bytes = host_row_pitch* sizeof_element; + host_slice_pitch_bytes = host_slice_pitch* sizeof_element; +} + +#endif diff --git a/test_conformance/mem_host_flags/checker_image_mem_host_no_access.hpp b/test_conformance/mem_host_flags/checker_image_mem_host_no_access.hpp new file mode 100644 index 00000000..b1960ba4 --- /dev/null +++ b/test_conformance/mem_host_flags/checker_image_mem_host_no_access.hpp @@ -0,0 +1,151 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef test_conformance_checker_Image_MEM_HOST_NO_ACCESS_h +#define test_conformance_checker_Image_MEM_HOST_NO_ACCESS_h + +#include "checker_image_mem_host_write_only.hpp" + +template < class T> +class cImage_check_mem_host_no_access : public cImage_check_mem_host_write_only +{ +public: + cImage_check_mem_host_no_access (cl_device_id deviceID, cl_context context, cl_command_queue queue) + : cImage_check_mem_host_write_only (deviceID,context, queue) + { + } + + ~cImage_check_mem_host_no_access() {}; + + cl_int verify_RW_Image(); + cl_int verify_RW_Image_Mapping(); +}; + +template < class T> +cl_int cImage_check_mem_host_no_access:: verify_RW_Image() +{ + this->Init_rect(); + + cl_event event; + size_t img_orig[3] = {0, 0, 0}; + size_t img_region[3] = {0, 0, 0}; + img_region[0] = this->m_cl_Image_desc.image_width; + img_region[1] = this->m_cl_Image_desc.image_height; + img_region[2] = this->m_cl_Image_desc.image_depth; + + int color[4] = {0xFF, 0xFF, 0xFF, 0xFF}; + cl_int err = CL_SUCCESS; + err = clEnqueueFillImage(this->m_queue, this->m_Image, + &color, + img_orig, img_region, + 0, NULL, &event); + + if (!this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error"); + } + + this->update_host_mem_2(); + + int total = (int)(this->region[0] * this->region[1] * this->region[2]); + + T v = 0xFFFFFFFF; + int tot = (int)(this->host_m_2.Count(v)); + if(tot != total){ + log_error("Buffer data content difference found\n"); + return FAILURE; + } + + err = clEnqueueWriteImage(this->m_queue, this->m_Image, this->m_blocking, + this->buffer_origin, this->region, + this-> buffer_row_pitch_bytes, this->buffer_slice_pitch_bytes, + this->host_m_1.pData, 0, NULL, &event); + + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueWriteImage on a memory object created with the CL_MEM_HOST_NO_ACCESS flag should not return CL_SUCCESS\n"); + err = FAILURE; + return err; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + v = 0; + this->host_m_2.Set_to(v); + err = clEnqueueReadImage(this->m_queue, this->m_Image, this->m_blocking, + this->buffer_origin, this->region, + this-> buffer_row_pitch_bytes, this->buffer_slice_pitch_bytes, + this->host_m_2.pData, 0, NULL, &event); + + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueReadImage on a memory object created with the CL_MEM_HOST_NO_ACCESS flag should not return CL_SUCCESS\n"); + err = FAILURE; + return err; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + return err; +} + +template < class T> +cl_int cImage_check_mem_host_no_access::verify_RW_Image_Mapping() +{ + this->Init_rect(); + + cl_event event; + cl_int err = CL_SUCCESS; + + T * dataPtr = (T*) clEnqueueMapImage(this->m_queue, this->m_Image, this->m_blocking, + CL_MAP_WRITE, + this->buffer_origin, this->region, + &(this-> buffer_row_pitch_bytes), + &(this->buffer_slice_pitch_bytes), + 0, NULL, &event, &err); + + if ( err == CL_SUCCESS) { + log_error("Calling clEnqueueMapImage (CL_MAP_WRITE) on a memory object created with the CL_MEM_HOST_NO_ACCESS flag should not return CL_SUCCESS\n"); + err = FAILURE; + return err; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + dataPtr = (T*) clEnqueueMapImage(this->m_queue, this->m_Image, this->m_blocking, + CL_MAP_READ, + this->buffer_origin, this->region, + &(this-> buffer_row_pitch_bytes), + &(this->buffer_slice_pitch_bytes), + 0, NULL, &event, &err); + + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueMapImage (CL_MAP_READ) on a memory object created with the CL_MEM_HOST_NO_ACCESS flag should not return CL_SUCCESS\n"); + err = FAILURE; + return err; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + return err; +} + +#endif diff --git a/test_conformance/mem_host_flags/checker_image_mem_host_read_only.hpp b/test_conformance/mem_host_flags/checker_image_mem_host_read_only.hpp new file mode 100644 index 00000000..925d8546 --- /dev/null +++ b/test_conformance/mem_host_flags/checker_image_mem_host_read_only.hpp @@ -0,0 +1,281 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef test_conformance_checker_Image_MEM_HOST_READ_ONLY_h +#define test_conformance_checker_Image_MEM_HOST_READ_ONLY_h + +#include "checker.h" + +template < class T> class cImage_check_mem_host_read_only : public cBuffer_checker +{ +public: + cImage_check_mem_host_read_only(cl_device_id deviceID, cl_context context, cl_command_queue queue) + : cBuffer_checker (deviceID, context, queue) + { + m_cl_image_format.image_channel_order = CL_RGBA; + m_cl_image_format.image_channel_data_type = CL_UNSIGNED_INT8; + + m_cl_Image_desc.image_type = CL_MEM_OBJECT_IMAGE1D; + m_cl_Image_desc.image_width = 0; + m_cl_Image_desc.image_height = 0; + m_cl_Image_desc.image_depth = 0; + m_cl_Image_desc.image_array_size = 0; + m_cl_Image_desc.image_row_pitch = 0; + m_cl_Image_desc.image_slice_pitch = 0; + m_cl_Image_desc.num_mip_levels = 0; + m_cl_Image_desc.num_samples = 0; + m_cl_Image_desc.mem_object = NULL; + + m_Image = NULL; + }; + + ~cImage_check_mem_host_read_only() + { + }; + + cl_int get_image_elements(); + + cl_image_format m_cl_image_format; + cl_image_desc m_cl_Image_desc; + clMemWrapper m_Image; + + virtual cl_int SetupImage(); + virtual cl_int SetupBuffer(); + virtual cl_int verify_RW_Image(); + + virtual cl_int verify_RW_Image_Mapping(); + virtual cl_int verify_data(T *pdtaIn); + virtual cl_int verify_data_with_offset(T *pdtaIn, size_t *offset); + + cl_int get_image_content_size(); + cl_int get_image_data_size(); + + virtual cl_int verify_RW_Buffer(); + virtual cl_int verify_RW_Buffer_rect(); + virtual cl_int verify_RW_Buffer_mapping(); + cl_int verify_mapping_ptr(T *ptr); +}; + +template < class T > +cl_int cImage_check_mem_host_read_only< T >::verify_mapping_ptr( T* dataPtr) +{ + int offset_pixel = (int)(this->buffer_origin[0] + this->buffer_origin[1] * + this->buffer_row_pitch_bytes/ sizeof(T) + this->buffer_origin[2] * + this->buffer_slice_pitch_bytes/sizeof(T)); + + dataPtr = dataPtr - offset_pixel; + + cl_int err = CL_SUCCESS; + + if (this->buffer_mem_flag & CL_MEM_USE_HOST_PTR) + { + if (this->pHost_ptr != this->host_m_1.pData) + { + log_error("Host memory pointer difference found\n"); + return FAILURE; + } + + if(dataPtr != this->host_m_1.pData) + { + log_error("Mapped host pointer difference found\n"); + return FAILURE; + } + } + + return err; +} + +template < class T > +cl_int cImage_check_mem_host_read_only< T >::verify_RW_Buffer() { return CL_SUCCESS; }; + +template < class T > +cl_int cImage_check_mem_host_read_only< T >::verify_RW_Buffer_rect() { return CL_SUCCESS; }; + +template < class T > +cl_int cImage_check_mem_host_read_only< T >::verify_RW_Buffer_mapping() { return CL_SUCCESS; }; + +template < class T > +cl_int cImage_check_mem_host_read_only< T >::SetupBuffer() +{ + return cBuffer_checker< T >::SetupBuffer(); +} + +template < class T > +cl_int cImage_check_mem_host_read_only< T >::get_image_content_size() +{ + return ((cl_int)(m_cl_Image_desc.image_width*m_cl_Image_desc.image_height * + m_cl_Image_desc.image_depth * m_cl_Image_desc.image_array_size)); +} + +template < class T > +cl_int cImage_check_mem_host_read_only< T >::get_image_data_size() +{ + size_t slice_pitch = m_cl_Image_desc.image_slice_pitch ? m_cl_Image_desc.image_slice_pitch : + (m_cl_Image_desc.image_height * m_cl_Image_desc.image_width); + return (slice_pitch * m_cl_Image_desc.image_depth * m_cl_Image_desc.image_array_size); +} + +template < class T > +cl_int cImage_check_mem_host_read_only< T >::get_image_elements() +{ + return ((cl_int)(m_cl_Image_desc.image_width*m_cl_Image_desc.image_height * + m_cl_Image_desc.image_depth * m_cl_Image_desc.image_array_size)); +} + +template < class T > +cl_int cImage_check_mem_host_read_only< T >::SetupImage() +{ + int all = (int)(m_cl_Image_desc.image_width * m_cl_Image_desc.image_height * + m_cl_Image_desc.image_depth * m_cl_Image_desc.image_array_size); + + T v = TEST_VALUE; + this->host_m_1.Init(all, v); + + cl_int err = CL_SUCCESS; + this-> m_Image = clCreateImage(this->m_context, this->buffer_mem_flag, + &( this-> m_cl_image_format), &(this-> m_cl_Image_desc), + this->host_m_1.pData, &err); + test_error(err , "clCreateImage error"); + + this-> pHost_ptr = (void *) (this->host_m_1.pData); + + return err; +} + +template < class T > +cl_int cImage_check_mem_host_read_only< T >::verify_data(T *pDataIN) +{ + cl_int err = CL_SUCCESS; + if (!this->host_m_1.Equal_rect_from_orig(pDataIN, this->buffer_origin, + this->region, this->host_row_pitch, + this->host_slice_pitch)) { + log_error("Buffer data difference found\n"); + return FAILURE; + } + + return err; +} + +template < class T > +cl_int cImage_check_mem_host_read_only< T >::verify_data_with_offset(T *pDataIN, + size_t *offset) +{ + cl_int err = CL_SUCCESS; + if (!this->host_m_2.Equal_rect_from_orig(pDataIN, offset, this->region, + this->host_row_pitch, + this->host_slice_pitch)) { + log_error("Buffer data difference found\n"); + return FAILURE; + } + + return err; +} + +template < class T > +cl_int cImage_check_mem_host_read_only< T >::verify_RW_Image() +{ + this->Init_rect(); + + int imge_content_size = this->get_image_content_size(); + T v = 0; + this->host_m_2.Init( imge_content_size, v); + + cl_event event; + cl_int err = CL_SUCCESS; + err = clEnqueueReadImage(this->m_queue, this->m_Image, this->m_blocking, + this->buffer_origin, this->region, + this-> buffer_row_pitch_bytes, this->buffer_slice_pitch_bytes, + this->host_m_2.pData, 0, NULL, &event); + + test_error(err, "clEnqueueReadImage error"); + + if ( !this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error"); + } + + err = this->verify_data(this->host_m_2.pData); + test_error(err, "verify_data error"); + + err = clEnqueueWriteImage(this->m_queue, this->m_Image, this->m_blocking, + this->buffer_origin, this->region, + this->buffer_row_pitch_bytes, this->buffer_slice_pitch_bytes, + this->host_m_2.pData, 0, NULL, &event); + + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueWriteImage on a memory object created with the CL_MEM_HOST_READ_ONLY flag should not return CL_SUCCESS\n"); + err = FAILURE; + return FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + return err; +} + +template < class T > +cl_int cImage_check_mem_host_read_only< T >::verify_RW_Image_Mapping() +{ + cl_event event; + cl_int err = CL_SUCCESS; + + T * dataPtr = (T*) clEnqueueMapImage(this->m_queue, this->m_Image, this->m_blocking, + CL_MAP_READ, + this->buffer_origin, this->region, + &(this-> buffer_row_pitch_bytes), + &(this->buffer_slice_pitch_bytes), + 0, NULL, &event, &err); + + if (!this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error"); + } + + err= this->verify_mapping_ptr(dataPtr); + test_error(err, "clEnqueueMapImage error"); + + err = this->verify_data(dataPtr); + test_error(err, "verify_data error"); + + err= clEnqueueUnmapMemObject (this->m_queue, this->m_Image, dataPtr, 0, NULL, &event); + test_error(err, "clEnqueueUnmapMemObject error"); + + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error"); + + dataPtr = (T*) clEnqueueMapImage(this->m_queue, this->m_Image, this->m_blocking, + CL_MAP_WRITE, + this->buffer_origin, + this->region, + &(this-> buffer_row_pitch_bytes), + &(this->buffer_slice_pitch_bytes), + 0, NULL, &event, &err); + + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueMapImage (CL_MAP_WRITE) on a memory object created with the CL_MEM_HOST_READ_ONLY flag should not return CL_SUCCESS\n"); + err = FAILURE; + return FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + return err; +} + +#endif diff --git a/test_conformance/mem_host_flags/checker_image_mem_host_write_only.hpp b/test_conformance/mem_host_flags/checker_image_mem_host_write_only.hpp new file mode 100644 index 00000000..94c446b9 --- /dev/null +++ b/test_conformance/mem_host_flags/checker_image_mem_host_write_only.hpp @@ -0,0 +1,293 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef test_conformance_checker_Image_MEM_HOST_WRITE_ONLY_h +#define test_conformance_checker_Image_MEM_HOST_WRITE_ONLY_h + +#include "checker_image_mem_host_read_only.hpp" + +template < class T> class cImage_check_mem_host_write_only : public cImage_check_mem_host_read_only +{ + +public: + cImage_check_mem_host_write_only(cl_device_id deviceID, cl_context context, cl_command_queue queue) + : cImage_check_mem_host_read_only (deviceID, context, queue) + { + } + + ~cImage_check_mem_host_write_only() {}; + + clMemWrapper m_Image_2; + + cl_int verify_RW_Image(); + cl_int verify_RW_Image_Mapping(); + + cl_int Setup_Test_Environment(); + cl_int update_host_mem_2(); + + cl_int verify_data(); +}; + +template < class T > +cl_int cImage_check_mem_host_write_only::Setup_Test_Environment() +{ + int all= this->get_image_elements(); + + T vv2 = 0; + this->host_m_2.Init( all, vv2); + vv2 = TEST_VALUE; + this->host_m_0.Init( all, vv2); + + cl_int err = CL_SUCCESS; + this->m_Image_2 = clCreateImage(this->m_context, + CL_MEM_READ_WRITE | CL_MEM_HOST_READ_ONLY | CL_MEM_COPY_HOST_PTR, + &( this-> m_cl_image_format), &(this->m_cl_Image_desc), + this->host_m_2.pData, &err); + test_error(err, "clCreateImage error"); + + return err; +} + +// Copy image data from a write_only image to a read_write image and read the +// contents. +template < class T > +cl_int cImage_check_mem_host_write_only< T >::update_host_mem_2() +{ + size_t orig[3] = {0, 0, 0}; + size_t img_region[3] = {0, 0, 0}; + img_region[0] = this->m_cl_Image_desc.image_width; + img_region[1] = this->m_cl_Image_desc.image_height; + img_region[2] = this->m_cl_Image_desc.image_depth; + + cl_event event; + cl_int err = CL_SUCCESS; + err = clEnqueueCopyImage(this->m_queue, + this->m_Image, + this->m_Image_2, + orig, + orig, + img_region, + 0, NULL, &event); + test_error(err, "clEnqueueCopyImage error"); + + if (!this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error"); + } + + this->host_m_2.Set_to_zero(); + + err = clEnqueueReadImage(this->m_queue, this->m_Image_2, this->m_blocking, + this->buffer_origin, this->region, + this->buffer_row_pitch_bytes, this->buffer_slice_pitch_bytes, + this->host_m_2.pData, 0, NULL, &event); + test_error(err, "clEnqueueReadImage error"); + + if (!this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error"); + } + + return err; +} + +template < class T > +cl_int cImage_check_mem_host_write_only::verify_data() +{ + cl_int err = CL_SUCCESS; + if (!this->host_m_1.Equal_rect_from_orig(this->host_m_2, this->buffer_origin, + this->region, this->host_row_pitch, + this->host_slice_pitch)) { + log_error("Image and host data difference found\n"); + return FAILURE; + } + + int total = (int)(this->region[0] * this->region[1] * this->region[2]); + T v = TEST_VALUE; + int tot = (int)(this->host_m_2.Count(v)); + if(tot != total) { + log_error("Image data content difference found\n"); + return FAILURE; + } + + return err; +} + +template < class T > +cl_int cImage_check_mem_host_write_only::verify_RW_Image() +{ + cl_int err = CL_SUCCESS; + + this->Init_rect(); + + cl_event event; + size_t img_orig[3] = {0, 0, 0}; + size_t img_region[3] = {0, 0, 0}; + img_region[0] = this->m_cl_Image_desc.image_width; + img_region[1] = this->m_cl_Image_desc.image_height; + img_region[2] = this->m_cl_Image_desc.image_depth; + + int color[4] = {0xFF, 0xFF, 0xFF, 0xFF}; + err = clEnqueueFillImage(this->m_queue, + this->m_Image, + &color, + img_orig, img_region, + 0, NULL, &event); // Fill the buffer with data + + if (!this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error"); + } + test_error(err, "clEnqueueFillImage error"); + + T v = TEST_VALUE; + + err= clEnqueueWriteImage(this->m_queue, this->m_Image, this->m_blocking, + this->buffer_origin, this->region, + this->buffer_row_pitch_bytes, this->buffer_slice_pitch_bytes, + this->host_m_0.pData, 0, NULL, &event); + test_error(err, "clEnqueueWriteImage error"); // Test writing to buffer + + if (!this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error"); + } + + update_host_mem_2(); // Read buffer contents into mem_2 + + err = this->verify_data(); // Compare the contents of mem_2 and mem_1, + // mem_1 is same as mem_0 in setup test environment + test_error(err, "verify_data error"); + + v = 0; + this->host_m_2.Set_to(v); + err = clEnqueueReadImage(this->m_queue, this->m_Image, this->m_blocking, + this->buffer_origin, this->region, + this->buffer_row_pitch_bytes, this->buffer_slice_pitch_bytes, + this->host_m_1.pData, 0, NULL, &event); + + if (err == CL_SUCCESS){ + log_error("Calling clEnqueueReadImage on a memory object created with the CL_MEM_HOST_WRITE_ONLY flag should not return CL_SUCCESS\n"); + err = FAILURE; + return FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + /* Qualcomm fix: 12506 Do not wait on invalid event/ no need for syncronization calls after clEnqueueReadImage fails + * + * The call to clEnqueueReadImage fails as expected and returns an invalid event on + * which clWaitForEvents cannot be called. (It will rightly fail with a CL_INVALID_EVENT error) + * Further, we don't need to do any additional flushes or finishes here since we were in sync + * before the (failing) call to clEnqueueReadImage + + if (!this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, " clWaitForEvents error") + } + Qualcomm fix: end*/ + + return err; +} + +template < class T > +cl_int cImage_check_mem_host_write_only::verify_RW_Image_Mapping() +{ + this->Init_rect(); + + cl_event event; + size_t img_orig[3] = {0, 0, 0}; + size_t img_region[3] = {0, 0, 0}; + img_region[0] = this->m_cl_Image_desc.image_width; + img_region[1] = this->m_cl_Image_desc.image_height; + img_region[2] = this->m_cl_Image_desc.image_depth; + + int color[4] = {0xFF, 0xFF, 0xFF, 0xFF}; + cl_int err = CL_SUCCESS; + + + // Fill image with pattern + err = clEnqueueFillImage(this->m_queue, this->m_Image, + &color, img_orig, img_region, + 0, NULL, &event); + + if (!this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error"); + } + + // Map image for writing + T* dataPtr = (T*) clEnqueueMapImage(this->m_queue, this->m_Image, + this->m_blocking, CL_MAP_WRITE, + this->buffer_origin, this->region, + &(this->buffer_row_pitch_bytes), + &(this->buffer_slice_pitch_bytes), + 0, NULL, &event, &err); + test_error(err, "clEnqueueMapImage CL_MAP_WRITE pointer error"); + + if (!this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error"); + } + + // Verify map pointer + err = this->verify_mapping_ptr(dataPtr); + test_error(err, "clEnqueueMapImage CL_MAP_WRITE pointer error"); + + // Verify mapped data + + // The verify_data_with_offset method below compares dataPtr against + // this->host_m_2.pData. The comparison should start at origin {0, 0, 0}. + update_host_mem_2(); + + // Check the content of mem and host_ptr + size_t offset[3] = {0, 0, 0}; + err = cImage_check_mem_host_read_only::verify_data_with_offset(dataPtr, + offset); + test_error(err, "verify_data error"); + + // Unmap memory object + err = clEnqueueUnmapMemObject(this->m_queue, this->m_Image, dataPtr, + 0, NULL, &event); + test_error(err, "clEnqueueUnmapMemObject error"); + + if (!this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error"); + } + + dataPtr = (T*) clEnqueueMapImage(this->m_queue, this->m_Image, this->m_blocking, + CL_MAP_READ, + this->buffer_origin, this->region, + &(this->buffer_row_pitch_bytes), + &(this->buffer_slice_pitch_bytes), + 0, NULL, &event, &err); + + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueMapImage (CL_MAP_READ) on a memory object created with the CL_MEM_HOST_WRITE_ONLY flag should not return CL_SUCCESS\n"); + err = FAILURE; + return FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + return err; +} + +#endif diff --git a/test_conformance/mem_host_flags/checker_mem_host_no_access.hpp b/test_conformance/mem_host_flags/checker_mem_host_no_access.hpp new file mode 100644 index 00000000..d1f96f25 --- /dev/null +++ b/test_conformance/mem_host_flags/checker_mem_host_no_access.hpp @@ -0,0 +1,202 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef test_conformance_check_mem_host_no_access_h +#define test_conformance_check_mem_host_no_access_h + + +#include "checker_mem_host_write_only.hpp" + +template < class T> class cBuffer_check_mem_host_no_access : public cBuffer_check_mem_host_write_only< T > +{ +public: + cBuffer_check_mem_host_no_access(cl_device_id deviceID, cl_context context, cl_command_queue queue) + : cBuffer_check_mem_host_write_only < T > (deviceID, context, queue) + { + }; + + cBuffer_check_mem_host_no_access() + { + }; + + virtual cl_int SetupBuffer(); + virtual cl_int SetupASSubBuffer(cl_mem_flags parent_buffer_flag); + virtual cl_int Setup_Test_Environment(); + + cl_int verify_RW_Buffer(); + cl_int verify_RW_Buffer_rect(); + cl_int verify_RW_Buffer_mapping(); +}; + +template < class T > +cl_int cBuffer_check_mem_host_no_access< T >::SetupBuffer() +{ + this->m_nNumber_elements = 1000; + T vv1 = TEST_VALUE; + this->host_m_1.Init( this->m_nNumber_elements, vv1); + + T vv2 = 0; + this->host_m_2.Init( this->m_nNumber_elements, vv2); + + cl_int err; + int block_size_in_byte = this->get_block_size_bytes(); + this->m_buffer = clCreateBuffer(this->m_context, this->buffer_mem_flag, + block_size_in_byte, this->host_m_1.pData, &err); + test_error(err, "clCreateBuffer error"); + err = this->Check_GetMemObjectInfo(this->buffer_mem_flag); + + if (this->buffer_mem_flag | CL_MEM_USE_HOST_PTR) + { + this->pHost_ptr = (void *)this->host_m_1.pData; + } + + return err; +} + +template < class T > +cl_int cBuffer_check_mem_host_no_access< T >::SetupASSubBuffer(cl_mem_flags parent_buffer_flag) +{ + return cBuffer_checker::SetupASSubBuffer(parent_buffer_flag); +} + +template < class T > +cl_int cBuffer_check_mem_host_no_access< T >::Setup_Test_Environment() +{ + cBuffer_check_mem_host_write_only::Setup_Test_Environment(); + + return CL_SUCCESS; +} + +template < class T> +cl_int cBuffer_check_mem_host_no_access< T >::verify_RW_Buffer() +{ + cl_event event; + cl_int err = clEnqueueReadBuffer(this->m_queue, this->m_buffer, this->m_blocking, 0, + this->get_block_size_bytes(), this->host_m_1.pData, + 0, NULL, &event); + + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueWriteBuffer on a memory object created with the CL_MEM_HOST_NO_ACCESS flag should not return CL_SUCCESS\n"); + err = FAILURE; + return FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + err = clEnqueueWriteBuffer(this->m_queue, this->m_buffer, this->m_blocking, 0, + this->get_block_size_bytes(), this->host_m_1.pData, + 0, NULL, &event); + + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueWriteBuffer on a memory object created with the CL_MEM_HOST_NO_ACCESS flag should not return CL_SUCCESS\n"); + err = FAILURE; + return FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + return err; +} + +template < class T > +cl_int cBuffer_check_mem_host_no_access< T >::verify_RW_Buffer_rect() +{ + this->Init_rect(); + cl_event event; + cl_int err = CL_SUCCESS; + err = clEnqueueReadBufferRect(this->m_queue, this->m_buffer, this->m_blocking, + this->buffer_origin_bytes, + this->host_origin_bytes, + this->region_bytes, + this->buffer_row_pitch_bytes, + this->buffer_slice_pitch_bytes, + this->host_row_pitch_bytes, + this->host_slice_pitch_bytes, + this->host_m_2.pData, + 0, NULL, &event); + + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueReadBufferRect on a memory object created with the CL_MEM_HOST_NO_ACCESS flag should not return CL_SUCCESS\n"); + err = FAILURE; + return FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + err = clEnqueueWriteBufferRect(this->m_queue, this->m_buffer, this->m_blocking, + this->buffer_origin_bytes , + this->host_origin_bytes, + this->region_bytes, + this->buffer_row_pitch_bytes, + this->buffer_slice_pitch_bytes, + this->host_row_pitch_bytes, + this->host_slice_pitch_bytes, + this->host_m_2.pData, + 0, NULL, &event); + + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueWriteBufferRect on a memory object created with the CL_MEM_HOST_NO_ACCESS flag should not return CL_SUCCESS\n"); + err = FAILURE; + return FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + return err; +} + +template < class T > +cl_int cBuffer_check_mem_host_no_access< T >::verify_RW_Buffer_mapping() +{ + cl_event event; + cl_int err; + + void *dataPtr; + dataPtr = clEnqueueMapBuffer(this->m_queue, this->m_buffer, this->m_blocking, CL_MAP_READ, + 0, this->get_block_size_bytes(), 0, NULL, &event, &err); + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueMapBuffer (CL_MAP_READ) on a memory object created with the CL_MEM_HOST_NO_ACCESS flag should not return CL_SUCCESS\n"); + err = FAILURE; + return FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + dataPtr = clEnqueueMapBuffer(this->m_queue, this->m_buffer, this->m_blocking, CL_MAP_WRITE, + 0, this->get_block_size_bytes(), 0, NULL, &event, &err); + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueMapBuffer (CL_MAP_WRITE) on a memory object created with the CL_MEM_HOST_NO_ACCESS flag should not return CL_SUCCESS\n"); + err = FAILURE; + return FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + return err; +} + +#endif diff --git a/test_conformance/mem_host_flags/checker_mem_host_read_only.hpp b/test_conformance/mem_host_flags/checker_mem_host_read_only.hpp new file mode 100644 index 00000000..669f3601 --- /dev/null +++ b/test_conformance/mem_host_flags/checker_mem_host_read_only.hpp @@ -0,0 +1,264 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef test_conformance_check_mem_host_read_only_h +#define test_conformance_check_mem_host_read_only_h + +#include "checker.h" + +template < class T> class cBuffer_check_mem_host_read_only : public cBuffer_checker +{ +public: + cBuffer_check_mem_host_read_only(cl_device_id deviceID, cl_context context, cl_command_queue queue) + : cBuffer_checker (deviceID, context, queue) + { + }; + + ~cBuffer_check_mem_host_read_only() + { + }; + + virtual cl_int Check_GetMemObjectInfo(cl_mem_flags buffer_mem_flag); + virtual cl_int SetupBuffer(); + virtual cl_int SetupASSubBuffer( cl_mem_flags flag_p); + virtual cl_int Setup_Test_Environment(); + + cl_int verifyData(cl_int err, cl_event & event); + cl_int verify_RW_Buffer(); + cl_int verify_RW_Buffer_rect(); + cl_int verify_RW_Buffer_mapping(); +}; + +template < class T > +cl_int cBuffer_check_mem_host_read_only< T >::SetupBuffer() +{ + this->m_buffer_type = _BUFFER; + + this->m_nNumber_elements = 888; + T vv1 = TEST_VALUE; + this->host_m_1.Init(this->m_nNumber_elements, vv1); + this->host_m_0.Init(this->m_nNumber_elements, vv1); + + cl_int err = CL_SUCCESS; + int block_size_in_byte = (int)(this->m_nNumber_elements * sizeof(T)); + this->m_buffer = clCreateBuffer(this->m_context, this->buffer_mem_flag, + block_size_in_byte, this->host_m_1.pData, &err); + test_error(err, "clCreateBuffer error"); + + if (this->buffer_mem_flag | CL_MEM_USE_HOST_PTR) + { + this->pHost_ptr = (void *)this->host_m_1.pData; + } + + return err; +} + +template < class T > +cl_int cBuffer_check_mem_host_read_only::SetupASSubBuffer(cl_mem_flags flag_p) +{ + return cBuffer_checker::SetupASSubBuffer(flag_p); +} + +template < class T> +cl_int cBuffer_check_mem_host_read_only::Setup_Test_Environment() +{ + cBuffer_checker::Setup_Test_Environment(); + T vv2 = 0; + this->host_m_2.Init(this->m_nNumber_elements, vv2); + + return CL_SUCCESS; +} + +template < class T > +cl_int cBuffer_check_mem_host_read_only< T >::Check_GetMemObjectInfo(cl_mem_flags buffer_mem_flag) +{ + cl_int err = CL_SUCCESS; + cBuffer_checker::Check_GetMemObjectInfo(buffer_mem_flag); + + if (buffer_mem_flag & CL_MEM_ALLOC_HOST_PTR) + { + size_t size = 0; + err = clGetMemObjectInfo(this->m_buffer, CL_MEM_SIZE, sizeof(size), &size, NULL); + void *pp = NULL; + err = clGetMemObjectInfo(this->m_buffer, CL_MEM_HOST_PTR, sizeof( pp ), &pp, NULL); + + if (!this->host_m_1.Equal( (T*) (this->pData), this->m_nNumber_elements )) { + log_error("Buffer data difference found\n"); + return FAILURE; + } + } + + return err; +} + +template < class T > +cl_int cBuffer_check_mem_host_read_only< T >::verifyData( cl_int err, cl_event & event ) +{ + if (err != CL_SUCCESS) { + err = this->m_nERROR_RETURN_CODE; + test_error(err, "clEnqueueReadBuffer error"); + } + + if (!this->host_m_1.Equal(this->host_m_2)) { + err = this->m_nERROR_RETURN_CODE; + test_error(err, "clEnqueueReadBuffer data difference found"); + } + + return err; +} + +template < class T > +cl_int cBuffer_check_mem_host_read_only< T >::verify_RW_Buffer() +{ + cl_event event; + cl_int err = CL_SUCCESS; + + err = clEnqueueReadBuffer(this->m_queue, this->m_buffer, this->m_blocking, + 0, this->get_block_size_bytes(), this->host_m_2.pData, + 0, NULL, &event); + test_error(err, "clEnqueueReadBuffer error"); + + if (!this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error"); + } + + if (!this->host_m_1.Equal(this->host_m_2)) { + log_error("Buffer data difference found\n"); + return FAILURE; + } + + // test write + err = clEnqueueWriteBuffer(this->m_queue, this->m_buffer, this->m_blocking, + 0, this->get_block_size_bytes(), this->host_m_2.pData, + 0, NULL, &event); + + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueWriteBuffer on a memory object created with the CL_MEM_HOST_READ_ONLY flag should not return CL_SUCCESS\n"); + err = FAILURE; + return FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + return err; +} + +template < class T > +cl_int cBuffer_check_mem_host_read_only< T >::verify_RW_Buffer_rect() +{ + this->Init_rect(); + + T vv2 = 0; + this->host_m_2.Set_to( vv2 ); + cl_event event; + cl_int err = CL_SUCCESS; + + err = clEnqueueReadBufferRect(this->m_queue, this->m_buffer, this->m_blocking, + this->buffer_origin_bytes, + this->host_origin_bytes, + this->region_bytes, + this->buffer_row_pitch_bytes, + this->buffer_slice_pitch_bytes, + this->host_row_pitch_bytes, + this->host_slice_pitch_bytes, + this->host_m_2.pData, + 0, NULL, &event); + test_error(err, "clEnqueueReadBufferRect error"); + + if (!this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error"); + } + + if (! this->host_m_1.Equal_rect(this->host_m_2, this->host_origin, this->region, + this->host_row_pitch, this->host_slice_pitch)) { + log_error("Buffer data diffeence found\n"); + return FAILURE; + } + + // test blocking write rect + err = clEnqueueWriteBufferRect(this->m_queue, this->m_buffer, this->m_blocking, + this->buffer_origin_bytes, + this->host_origin_bytes, + this->region_bytes, + this->buffer_row_pitch_bytes, + this->buffer_slice_pitch_bytes, + this->host_row_pitch_bytes, + this->host_slice_pitch_bytes, + this->host_m_2.pData, + 0, NULL, &event); + + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueWriteBufferRect on a memory object created with the CL_MEM_HOST_READ_ONLY flag should not return CL_SUCCESS\n"); + err = FAILURE; + return FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + return err; +} + +template < class T > +cl_int cBuffer_check_mem_host_read_only< T >::verify_RW_Buffer_mapping() +{ + cl_int err = CL_SUCCESS; + cl_event event; + void *dataPtr; + dataPtr = clEnqueueMapBuffer(this->m_queue, this->m_buffer, this->m_blocking, + CL_MAP_READ, + 0, this->get_block_size_bytes(), + 0, NULL, &event, &err); + test_error(err, "clEnqueueMapBuffer error"); + + if (!this->m_blocking) { + err = clWaitForEvents(1, &event ); + test_error(err, "clWaitForEvents error"); + } + + if ((this->buffer_mem_flag & CL_MEM_USE_HOST_PTR) && dataPtr != this->pHost_ptr ) { + log_error("Mapped host pointer difference found\n"); + } + + if(!this->host_m_1.Equal((T*)dataPtr, this->m_nNumber_elements)) { + log_error("Buffer content difference found\n"); + return FAILURE; + } + + // test blocking map read + clEnqueueMapBuffer(this->m_queue, this->m_buffer, this->m_blocking, + CL_MAP_WRITE, + 0, this->get_block_size_bytes(), + 0, NULL, &event, &err); + + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueMapBuffer (CL_MAP_WRITE) on a memory object created with the CL_MEM_HOST_READ_ONLY flag should not return CL_SUCCESS\n"); + err = FAILURE; + return FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + return err; +} + +#endif diff --git a/test_conformance/mem_host_flags/checker_mem_host_write_only.hpp b/test_conformance/mem_host_flags/checker_mem_host_write_only.hpp new file mode 100644 index 00000000..04c82a8e --- /dev/null +++ b/test_conformance/mem_host_flags/checker_mem_host_write_only.hpp @@ -0,0 +1,333 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef test_conformance_check_mem_host_write_only__h +#define test_conformance_check_mem_host_write_only__h + +#include "checker.h" + +template < class T> class cBuffer_check_mem_host_write_only : public cBuffer_checker +{ +public: + cBuffer_check_mem_host_write_only(cl_device_id deviceID, cl_context context, cl_command_queue queue) + : cBuffer_checker < T > (deviceID, context, queue) + { + this->m_nNumber_elements = 1000; + }; + + ~cBuffer_check_mem_host_write_only() + { + }; + + cl_program program; + cl_kernel kernel; + + clMemWrapper m_buffer2; + + cl_int Setup_Test_Environment(); + + cl_int SetupBuffer(); + cl_int SetupASSubBuffer(cl_mem_flags flag_p); + + cl_int verifyData(cl_int err, cl_event &event ); + cl_int update_host_mem_2(); + + cl_int verify_RW_Buffer(); + cl_int verify_RW_Buffer_rect(); + cl_int verify_RW_Buffer_mapping(); + + C_host_memory_block tmp_host_m; + + virtual cl_int verify_Buffer_initialization(); +}; + +template < class T > +cl_int cBuffer_check_mem_host_write_only< T >::SetupBuffer() +{ + T vv1 = 0; + this->host_m_1.Init( this->m_nNumber_elements, vv1); // zero out buffer + + // init buffer to 0 + cl_int err; + int block_size_in_byte = this->get_block_size_bytes(); + + this->m_buffer = clCreateBuffer(this->m_context, this->buffer_mem_flag, + block_size_in_byte, this->host_m_1.pData, &err); + test_error(err, "clCreateBuffer error"); + + err = this->Check_GetMemObjectInfo(this->buffer_mem_flag); + + if (this->buffer_mem_flag | CL_MEM_USE_HOST_PTR) + { + this->pHost_ptr = (void *)this->host_m_1.pData; + } + + return err; +} + +template < class T > +cl_int cBuffer_check_mem_host_write_only::SetupASSubBuffer(cl_mem_flags flag_p) +{ + return cBuffer_checker::SetupASSubBuffer(flag_p); +} + +template < class T > +cl_int cBuffer_check_mem_host_write_only< T >::Setup_Test_Environment() +{ + cl_int err; + T vv2 = 0; + this->host_m_2.Init(this->m_nNumber_elements, vv2); + + // init buffer2 to 0 + cl_mem_flags buffer_mem_flag2 = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR | CL_MEM_HOST_READ_ONLY; + this->m_buffer2 = clCreateBuffer(this->m_context, buffer_mem_flag2, + this->get_block_size_bytes(), this->host_m_2.pData, &err); + test_error(err, "clCreateBuffer error\n"); + + return err; +} + +template < class T > +cl_int cBuffer_check_mem_host_write_only< T >::verify_Buffer_initialization() +{ + cl_int err = CL_SUCCESS; + + if (this->host_m_1.pData == NULL || this->host_m_2.pData == NULL) { + log_error("Data not ready\n"); + return FAILURE; + } + + update_host_mem_2(); + + if (!this->host_m_1.Equal(this->host_m_2)){ + log_error("Buffer content difference found\n"); + return FAILURE; + } + + return err; +} + +template < class T > +cl_int cBuffer_check_mem_host_write_only< T >::verify_RW_Buffer() +{ + T vv1 = TEST_VALUE; + T vv2 = 0; + this->host_m_2.Set_to(vv2); + + tmp_host_m.Init(this->host_m_1.num_elements, vv1) ; + + cl_event event; + cl_int err = CL_SUCCESS; + err = clEnqueueWriteBuffer(this->m_queue, this->m_buffer, this->m_blocking, 0, + this->get_block_size_bytes(), tmp_host_m.pData, + 0, NULL, &event); + if (err != CL_SUCCESS ) { + test_error(err, "clEnqueueWriteBuffer error"); + } + + if (!this->m_blocking){ + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error") + } + + if (tmp_host_m.Equal(this->host_m_2)){ + log_error("Test data should be different\n"); + return FAILURE; + } + + update_host_mem_2(); + + if (!tmp_host_m.Equal(this->host_m_2)){ + log_error("Buffer content difference found\n"); + return FAILURE; + } + + err = clEnqueueReadBuffer(this->m_queue, this->m_buffer, CL_TRUE, 0, + this->get_block_size_bytes(), this->host_m_2.pData, + 0, NULL, &event); + + if ( err == CL_SUCCESS ) { + log_error("Calling clEnqueueReadBuffer on a memory object created with the CL_MEM_HOST_WRITE_ONLY flag should not return CL_SUCCESS\n"); + err = FAILURE; + return FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + return err; +} + +template < class T > +cl_int cBuffer_check_mem_host_write_only< T >::verify_RW_Buffer_rect() +{ + this->Init_rect(); + + T vv1= TEST_VALUE; + this->host_m_1.Set_to(vv1); + + T vv2 = 0; + this->host_m_2.Set_to(vv2); + + cl_event event, event_1; + + cl_int err = CL_SUCCESS; + + vv1 = 0; + C_host_memory_block< T > tmp_host_m; + tmp_host_m.Init(this->host_m_1.num_elements, vv1); // zero out the buffer + err = clEnqueueWriteBuffer(this->m_queue, this->m_buffer, CL_TRUE, 0, + this->get_block_size_bytes(), tmp_host_m.pData, + 0, NULL, &event_1); + + vv1 = TEST_VALUE; + tmp_host_m.Set_to(vv1); + err = clEnqueueWriteBufferRect(this->m_queue, this->m_buffer, this->m_blocking, + this->buffer_origin_bytes, + this->host_origin_bytes, + this->region_bytes, + this->buffer_row_pitch_bytes, + this->buffer_slice_pitch_bytes, + this->host_row_pitch_bytes, + this->host_slice_pitch_bytes, + tmp_host_m.pData, + 1, &event_1, &event); + test_error(err, "clEnqueueWriteBuffer error"); + + if (!this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error") + } + + if (tmp_host_m.Equal(this->host_m_2)) { + log_error("Test data should be different\n"); + return FAILURE; + } + + update_host_mem_2(); + + size_t tot_in_reg = this->region[0] * this->region[1] * this->region[2]; + if (!tmp_host_m.Equal_rect(this->host_m_2, this->host_origin, this->region, + this->host_row_pitch, this->host_slice_pitch)) { + log_error("Buffer rect content difference found\n"); + return FAILURE; + } + + if (this->host_m_2.Count(vv1) != tot_in_reg) + { + log_error("Buffer rect content difference found\n"); + return FAILURE; + } + + err = clEnqueueReadBufferRect(this->m_queue, this->m_buffer, this->m_blocking, + this->buffer_origin_bytes, + this->host_origin_bytes, + this->region_bytes, + this->buffer_row_pitch_bytes, + this->buffer_slice_pitch_bytes, + this->host_row_pitch_bytes, + this->host_slice_pitch_bytes, + this->host_m_2.pData, + 0, NULL, &event); + + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueReadBufferRect on a memory object created with the CL_MEM_HOST_WRITE_ONLY flag should not return CL_SUCCESS\n"); + err = FAILURE; + return FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + return err; +} + +template < class T > +cl_int cBuffer_check_mem_host_write_only< T >::update_host_mem_2() +{ + size_t global_work_size[3] = {0, 1, 1}; + global_work_size[0] = this->get_block_size_bytes(); + + cl_event event, event_2; + cl_int err = clEnqueueCopyBuffer(this->m_queue, this->m_buffer, this->m_buffer2, 0, 0, + this->m_nNumber_elements* sizeof (T), 0, NULL, &event); + + this->host_m_2.Set_to_zero(); + err = clEnqueueReadBuffer(this->m_queue, this->m_buffer2, CL_TRUE, 0, + this->get_block_size_bytes(), this->host_m_2.pData, + 1, &event, &event_2); + test_error(err, "clEnqueueReadBuffer error"); + + clWaitForEvents(1, &event_2); + test_error(err, "clWaitForEvents error"); + + return err; +} + +template < class T > +cl_int cBuffer_check_mem_host_write_only< T >::verify_RW_Buffer_mapping() +{ + T vv2 = 0; + this->host_m_2.Set_to(vv2); + + cl_event event; + cl_int err = CL_SUCCESS; + + void *dataPtr; + int size = this->get_block_size_bytes(); + dataPtr = clEnqueueMapBuffer(this->m_queue, this->m_buffer, this->m_blocking, + CL_MAP_WRITE, + 0, size, + 0, NULL, &event, &err); + test_error(err, "clEnqueueMapBuffer error"); + + if (!this->m_blocking) { + err = clWaitForEvents(1, &event); + test_error(err, "clWaitForEvents error"); + } + + update_host_mem_2(); + + if ((this->buffer_mem_flag & CL_MEM_USE_HOST_PTR) && dataPtr != this->pHost_ptr){ + log_error("Mapped host pointer difference found\n"); + return FAILURE; + } + + if(!this->host_m_2.Equal((T*)dataPtr, this->m_nNumber_elements)) { + log_error("Buffer content difference found\n"); + return FAILURE; + } + + // test map read + clEnqueueMapBuffer(this->m_queue, this->m_buffer, this->m_blocking, + CL_MAP_READ, + 0, this->get_block_size_bytes(), + 0, NULL, &event, &err); + + if (err == CL_SUCCESS) { + log_error("Calling clEnqueueMapBuffer (CL_MAP_READ) on a memory object created with the MEM_HOST_WRITE_ONLY flag should not return CL_SUCCESS\n"); + err = FAILURE; + + } else { + log_info("Test succeeded\n\n"); + err = CL_SUCCESS; + } + + return err; +} + +#endif diff --git a/test_conformance/mem_host_flags/main.cpp b/test_conformance/mem_host_flags/main.cpp new file mode 100644 index 00000000..527468f2 --- /dev/null +++ b/test_conformance/mem_host_flags/main.cpp @@ -0,0 +1,68 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include + +#if !defined (__APPLE__) +#include +#endif + +#include "procs.h" +#include "../../test_common/harness/testHarness.h" + +#if !defined(_WIN32) +#include +#endif + +basefn clfn_list[] = {test_mem_host_read_only_buffer, + test_mem_host_read_only_subbuffer, + test_mem_host_write_only_buffer, + test_mem_host_write_only_subbuffer, + test_mem_host_no_access_buffer, + test_mem_host_no_access_subbuffer, + test_mem_host_read_only_image, + test_mem_host_write_only_image, + test_mem_host_no_access_image}; + +const char *clfn_names[] = {"test_mem_host_read_only_buffer", + "test_mem_host_read_only_subbuffer", + "test_mem_host_write_only_buffer", + "test_mem_host_write_only_subbuffer", + "test_mem_host_no_access_buffer", + "test_mem_host_no_access_subbuffer", + "test_mem_host_read_only_image", + "test_mem_host_write_only_image", + "test_mem_host_no_access_image", +}; + +ct_assert((sizeof(clfn_names) / sizeof(clfn_names[0])) == (sizeof(clfn_list) / sizeof(clfn_list[0]))); + +int num_fns = sizeof(clfn_names) / sizeof(char *); + +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +bool gTestRounding = true; + +int main(int argc, const char *argv[]) +{ + int error = 0; + test_start();// in fact no code + log_info("1st part, non gl-sharing objects...\n"); + error = runTestHarness(argc, argv, num_fns, clfn_list, clfn_names, false, false, 0); + + return error; +} diff --git a/test_conformance/mem_host_flags/mem_host_buffer.cpp b/test_conformance/mem_host_flags/mem_host_buffer.cpp new file mode 100644 index 00000000..5416ec7f --- /dev/null +++ b/test_conformance/mem_host_flags/mem_host_buffer.cpp @@ -0,0 +1,487 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +#include "checker_mem_host_read_only.hpp" +#include "checker_mem_host_write_only.hpp" +#include "checker_mem_host_no_access.hpp" + +static int test_mem_host_read_only_buffer_RW(cl_device_id deviceID, cl_context context, + cl_command_queue queue, cl_bool blocking, + cl_mem_flags buffer_mem_flag, + cl_mem_flags parent_buffer_flag, + enum BUFFER_TYPE buffer_type) +{ + log_info("%s\n", __FUNCTION__); + cBuffer_check_mem_host_read_only< TEST_ELEMENT_TYPE > checker(deviceID, context, queue); + checker.m_blocking = blocking; + checker.buffer_mem_flag = buffer_mem_flag; + cl_int err; + switch (buffer_type) { + case _BUFFER: + err = checker.SetupBuffer(); + break; + case _Sub_BUFFER: + err = checker.SetupASSubBuffer(parent_buffer_flag); + break; + } + + test_error(err, __FUNCTION__); + checker.Setup_Test_Environment(); + err= checker.verify_RW_Buffer(); + test_error(err, __FUNCTION__); + clFinish(queue); + + return err; +} + +static int test_mem_host_read_only_buffer_RW_Rect(cl_device_id deviceID, cl_context context, + cl_command_queue queue, cl_bool blocking, + cl_mem_flags buffer_mem_flag, + cl_mem_flags parent_buffer_flag, + enum BUFFER_TYPE buffer_type) +{ + log_info("%s\n", __FUNCTION__); + + cBuffer_check_mem_host_read_only< TEST_ELEMENT_TYPE > checker(deviceID, context, queue); + checker.m_blocking = blocking; + checker.buffer_mem_flag = buffer_mem_flag; + cl_int err; + switch (buffer_type) { + case _BUFFER: + err= checker.SetupBuffer(); + break; + case _Sub_BUFFER: + err= checker.SetupASSubBuffer(parent_buffer_flag); + break; + } + + test_error(err, __FUNCTION__); + checker.Setup_Test_Environment(); + err = checker.verify_RW_Buffer_rect(); + test_error(err, __FUNCTION__); + clFinish(queue); + + return err; +} + +static int test_mem_host_read_only_buffer_RW_Mapping(cl_device_id deviceID, cl_context context, + cl_command_queue queue, cl_bool blocking, + cl_mem_flags buffer_mem_flag, + cl_mem_flags parent_buffer_flag, + enum BUFFER_TYPE buffer_type) +{ + log_info("%s\n", __FUNCTION__); + + cBuffer_check_mem_host_read_only< TEST_ELEMENT_TYPE > checker(deviceID, context, queue); + checker.m_blocking = blocking; + checker.buffer_mem_flag = buffer_mem_flag; + cl_int err; + switch (buffer_type) { + case _BUFFER: + err= checker.SetupBuffer(); + break; + case _Sub_BUFFER: + err= checker.SetupASSubBuffer(parent_buffer_flag); + break; + } + + test_error(err, __FUNCTION__); + checker.Setup_Test_Environment(); + err = checker.verify_RW_Buffer_mapping(); + test_error(err, __FUNCTION__); + clFinish(queue); + + return err; +} + +int test_mem_host_read_only_buffer(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements) +{ + cl_mem_flags buffer_mem_flags[2] = {CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR | CL_MEM_HOST_READ_ONLY, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR | CL_MEM_HOST_READ_ONLY}; + + cl_int err = CL_SUCCESS; + + cl_bool blocking[2] = {CL_TRUE, CL_FALSE}; + for (int k=0; k<2; k++) + for (int i=0; i< 2; i++) + { + err = test_mem_host_read_only_buffer_RW(deviceID, context, queue, blocking[i], + buffer_mem_flags[k], 0, _BUFFER); + test_error(err, __FUNCTION__); + + err = test_mem_host_read_only_buffer_RW_Rect(deviceID, context, queue, blocking[i], + buffer_mem_flags[k],0, _BUFFER); + test_error(err, __FUNCTION__); + + err = test_mem_host_read_only_buffer_RW_Mapping(deviceID, context, queue, blocking[i], + buffer_mem_flags[k],0, _BUFFER); + test_error(err, __FUNCTION__); + } + + return err; +} + +int test_mem_host_read_only_subbuffer(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements) +{ + cl_mem_flags parent_buffer_mem_flags[1] = {CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR | CL_MEM_HOST_READ_ONLY}; + + cl_mem_flags buffer_mem_flags[4] = {0, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR}; + + cl_int err = CL_SUCCESS; + + cl_bool blocking[2] = {CL_TRUE, CL_FALSE}; + + for (int p=0; p<1; p++) { + for (int k=0; k<4; k++) + for (int i=0; i<2; i++) + { + err = test_mem_host_read_only_buffer_RW(deviceID, context, queue, blocking[i], + buffer_mem_flags[k], parent_buffer_mem_flags[p], _Sub_BUFFER); + test_error(err, __FUNCTION__); + + err = test_mem_host_read_only_buffer_RW_Rect(deviceID, context, queue, blocking[i], + buffer_mem_flags[k], parent_buffer_mem_flags[p], _Sub_BUFFER); + test_error(err, __FUNCTION__); + + err = test_mem_host_read_only_buffer_RW_Mapping(deviceID, context, queue, blocking[i], + buffer_mem_flags[k], parent_buffer_mem_flags[p], _Sub_BUFFER); + test_error(err, __FUNCTION__); + } + } + + return err; +} + +//=============================== Write only + +static cl_int test_mem_host_write_only_buffer_RW(cl_device_id deviceID, cl_context context, + cl_command_queue queue, cl_bool blocking, + cl_mem_flags buffer_mem_flag, + cl_mem_flags parent_buffer_flag, + enum BUFFER_TYPE buffer_type) +{ + log_info("%s\n", __FUNCTION__); + + cBuffer_check_mem_host_write_only< TEST_ELEMENT_TYPE > checker(deviceID, context, queue); + + checker.m_blocking = blocking; + checker.buffer_mem_flag = buffer_mem_flag; + cl_int err; + switch (buffer_type) { + case _BUFFER: + err = checker.SetupBuffer(); + break; + case _Sub_BUFFER: + err = checker.SetupASSubBuffer( parent_buffer_flag ); + break; + } + + test_error(err, __FUNCTION__); + checker.Setup_Test_Environment(); + err= checker.verify_RW_Buffer(); + test_error(err, __FUNCTION__); + clFinish(queue); + + return err; +} + +static cl_int test_mem_host_write_only_buffer_RW_Rect(cl_device_id deviceID, cl_context context, + cl_command_queue queue, cl_bool blocking, + cl_mem_flags buffer_mem_flag, + cl_mem_flags parent_buffer_flag, + enum BUFFER_TYPE buffer_type) +{ + log_info("%s\n", __FUNCTION__); + + cBuffer_check_mem_host_write_only< TEST_ELEMENT_TYPE > checker(deviceID, context, queue); + checker.m_blocking = blocking; + checker.buffer_mem_flag = buffer_mem_flag; + cl_int err; + switch (buffer_type) { + case _BUFFER: + err= checker.SetupBuffer(); + break; + case _Sub_BUFFER: + err= checker.SetupASSubBuffer(parent_buffer_flag); + break; + } + + test_error(err, __FUNCTION__); + checker.Setup_Test_Environment(); + err= checker.verify_RW_Buffer_rect(); + test_error(err, __FUNCTION__); + clFinish(queue); + + return err; +} + +static cl_int test_mem_host_write_only_buffer_RW_Mapping(cl_device_id deviceID, cl_context context, + cl_command_queue queue, cl_bool blocking, + cl_mem_flags buffer_mem_flag, + cl_mem_flags parent_buffer_flag, + enum BUFFER_TYPE buffer_type) +{ + log_info("%s\n", __FUNCTION__); + + cBuffer_check_mem_host_write_only< TEST_ELEMENT_TYPE > checker(deviceID, context, queue); + checker.m_blocking = blocking; + checker.buffer_mem_flag = buffer_mem_flag; + cl_int err; + switch (buffer_type) { + case _BUFFER: + err= checker.SetupBuffer(); + break; + case _Sub_BUFFER: + err= checker.SetupASSubBuffer(parent_buffer_flag); + break; + } + + test_error(err, __FUNCTION__); + checker.Setup_Test_Environment(); + err= checker.verify_RW_Buffer_mapping(); + test_error(err, __FUNCTION__); + clFinish(queue); + + return err; +} + +int test_mem_host_write_only_buffer(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements) +{ + cl_mem_flags buffer_mem_flags[2] = {CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR | CL_MEM_HOST_WRITE_ONLY, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR | CL_MEM_HOST_WRITE_ONLY}; + + cl_int err = CL_SUCCESS; + + cl_bool blocking[2] = {CL_TRUE, CL_FALSE}; + for (int k=0; k<2; k++) + for (int i=0; i<2; i++) + { + err = test_mem_host_write_only_buffer_RW(deviceID, context, queue, blocking[i], + buffer_mem_flags[k], 0, _BUFFER); + test_error(err, __FUNCTION__); + + err = test_mem_host_write_only_buffer_RW_Rect(deviceID, context, queue, blocking[i], + buffer_mem_flags[k], 0, _BUFFER); + test_error(err, __FUNCTION__); + + err = test_mem_host_write_only_buffer_RW_Mapping(deviceID, context, queue, blocking[i], + buffer_mem_flags[k], 0, _BUFFER); + test_error(err, __FUNCTION__); + } + + return err; +} + +int test_mem_host_write_only_subbuffer(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements) +{ + cl_mem_flags parent_buffer_mem_flags[1] = {CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR | CL_MEM_HOST_WRITE_ONLY}; + + cl_mem_flags buffer_mem_flags[4] = {0, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR}; + + cl_int err = CL_SUCCESS; + + cl_bool blocking[2] = {CL_TRUE, CL_FALSE}; + + for (int p=0; p<1; p++) { + for (int m=0; m<4; m++) { + for (int i=0; i< 2; i++) + { + err = test_mem_host_write_only_buffer_RW(deviceID, context, queue, blocking[i], + buffer_mem_flags[m], parent_buffer_mem_flags[p], _Sub_BUFFER); + test_error(err, __FUNCTION__); + + err = test_mem_host_write_only_buffer_RW_Rect(deviceID, context, queue, blocking[i], + buffer_mem_flags[m], parent_buffer_mem_flags[p], _Sub_BUFFER); + test_error(err, __FUNCTION__); + + err = test_mem_host_write_only_buffer_RW_Mapping(deviceID, context, queue, blocking[i], + buffer_mem_flags[m] , parent_buffer_mem_flags[p], _Sub_BUFFER); + test_error(err, __FUNCTION__); + } + } + } + + return err; +} + +//===================== NO ACCESS + +static cl_int test_mem_host_no_access_buffer_RW(cl_device_id deviceID, cl_context context, + cl_command_queue queue, cl_bool blocking, + cl_mem_flags buffer_mem_flag, + cl_mem_flags parent_buffer_flag, + enum BUFFER_TYPE buffer_type) +{ + log_info("%s\n", __FUNCTION__); + + cBuffer_check_mem_host_no_access< TEST_ELEMENT_TYPE > checker(deviceID, context, queue); + checker.m_blocking = blocking; + checker.buffer_mem_flag = buffer_mem_flag; + + cl_int err = CL_SUCCESS; + switch (buffer_type) { + case _BUFFER: + err= checker.SetupBuffer(); + break; + case _Sub_BUFFER: + err= checker.SetupASSubBuffer(parent_buffer_flag); + break; + } + + test_error(err, __FUNCTION__); + checker.Setup_Test_Environment(); + err= checker.verify_RW_Buffer_mapping(); + test_error(err, __FUNCTION__); + clFinish(queue); + + return err; +} + +static cl_int test_mem_host_no_access_buffer_RW_Rect(cl_device_id deviceID, cl_context context, + cl_command_queue queue, cl_bool blocking, + cl_mem_flags buffer_mem_flag, + cl_mem_flags parent_buffer_flag, + enum BUFFER_TYPE buffer_type) +{ + log_info( "%s\n", __FUNCTION__); + + cBuffer_check_mem_host_no_access< TEST_ELEMENT_TYPE > checker(deviceID, context, queue); + checker.m_blocking = blocking; + checker.buffer_mem_flag = buffer_mem_flag; + cl_int err; + switch (buffer_type) { + case _BUFFER: + err= checker.SetupBuffer(); + break; + case _Sub_BUFFER: + err= checker.SetupASSubBuffer(parent_buffer_flag); + break; + } + + test_error(err, __FUNCTION__); + checker.Setup_Test_Environment(); + err= checker.verify_RW_Buffer_mapping(); + test_error(err, __FUNCTION__); + clFinish(queue); + + return err; +} + +static cl_int test_mem_host_no_access_buffer_RW_Mapping(cl_device_id deviceID, cl_context context, + cl_command_queue queue, cl_bool blocking, + cl_mem_flags buffer_mem_flag, + cl_mem_flags parent_buffer_flag, + enum BUFFER_TYPE buffer_type) +{ + log_info("%s\n", __FUNCTION__); + + cBuffer_check_mem_host_no_access< TEST_ELEMENT_TYPE > checker(deviceID, context, queue); + + checker.m_blocking = blocking; + checker.buffer_mem_flag = buffer_mem_flag; + cl_int err; + switch (buffer_type) { + case _BUFFER: + err= checker.SetupBuffer(); + break; + case _Sub_BUFFER: + err= checker.SetupASSubBuffer(parent_buffer_flag); + break; + } + + test_error(err, __FUNCTION__); + checker.Setup_Test_Environment(); + err= checker.verify_RW_Buffer_mapping(); + test_error(err, __FUNCTION__); + clFinish(queue); + + return err; +} + +int test_mem_host_no_access_buffer(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements) +{ + cl_mem_flags buffer_mem_flag[2] = {CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR | CL_MEM_HOST_NO_ACCESS, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR | CL_MEM_HOST_NO_ACCESS}; + + cl_int err = CL_SUCCESS; + + cl_bool blocking[2] = {CL_TRUE, CL_FALSE}; + for (int k=0; k<2; k++) + for (int i=0; i<2; i++) { + err = test_mem_host_no_access_buffer_RW(deviceID, context, queue, blocking[i], + buffer_mem_flag[k], 0, _BUFFER); + test_error(err, __FUNCTION__); + + err = test_mem_host_no_access_buffer_RW_Rect(deviceID, context, queue, blocking[i], + buffer_mem_flag[k], 0, _BUFFER); + test_error(err, __FUNCTION__); + + err = test_mem_host_no_access_buffer_RW_Mapping(deviceID, context, queue, blocking[i], + buffer_mem_flag[k], 0, _BUFFER); + test_error(err, __FUNCTION__); + } + + return err; +} + +int test_mem_host_no_access_subbuffer(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements) +{ + cl_mem_flags parent_buffer_mem_flags[3] = { CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR | CL_MEM_HOST_NO_ACCESS, + CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR | CL_MEM_HOST_NO_ACCESS, + CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR | CL_MEM_HOST_NO_ACCESS}; + + cl_mem_flags buffer_mem_flags[4] = {0, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR}; + + cl_int err = CL_SUCCESS; + + cl_bool blocking[2] = {CL_TRUE, CL_FALSE}; + for (int p=0; p<3; p++) { + for (int k=0; k<4; k++) { + for (int i=0; i<2; i++) { + err += test_mem_host_no_access_buffer_RW(deviceID, context, queue, blocking[i], + buffer_mem_flags[k], parent_buffer_mem_flags[p], _Sub_BUFFER); + + err += test_mem_host_no_access_buffer_RW_Rect(deviceID, context, queue, blocking[i], + buffer_mem_flags[k], parent_buffer_mem_flags[p], _Sub_BUFFER); + + err += test_mem_host_no_access_buffer_RW_Mapping( deviceID, context, queue, blocking[i], + buffer_mem_flags[k], parent_buffer_mem_flags[p], _Sub_BUFFER); + } + } + } + + return err; +} diff --git a/test_conformance/mem_host_flags/mem_host_image.cpp b/test_conformance/mem_host_flags/mem_host_image.cpp new file mode 100644 index 00000000..b7eeb003 --- /dev/null +++ b/test_conformance/mem_host_flags/mem_host_image.cpp @@ -0,0 +1,364 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +#include "checker_image_mem_host_read_only.hpp" +#include "checker_image_mem_host_no_access.hpp" +#include "checker_image_mem_host_write_only.hpp" + +//====================================== +static cl_int test_mem_host_read_only_RW_Image(cl_device_id deviceID, cl_context context, + cl_command_queue queue, cl_bool blocking, + cl_mem_flags buffer_mem_flag, + cl_mem_object_type image_type_in, + size_t array_size, size_t *img_dim) +{ + log_info("%s ... \n ", __FUNCTION__); + cl_int err = CL_SUCCESS; + + cImage_check_mem_host_read_only< int > checker(deviceID, context, queue); + checker.m_blocking = blocking; + checker.buffer_mem_flag = buffer_mem_flag; + + checker.m_cl_Image_desc.image_type = image_type_in; + checker.m_cl_Image_desc.image_width = img_dim[0]; + checker.m_cl_Image_desc.image_height = img_dim[1]; + checker.m_cl_Image_desc.image_depth = img_dim[2]; + checker.m_cl_Image_desc.image_array_size = array_size; + checker.m_cl_Image_desc.image_row_pitch = 0; + checker.m_cl_Image_desc.image_slice_pitch = 0; + checker.m_cl_Image_desc.num_mip_levels = 0; + checker.m_cl_Image_desc.num_samples = 0; + + checker.SetupImage(); + checker.Init_rect(); + err = checker.verify_RW_Image(); + test_error(err, __FUNCTION__); + clFinish(queue); + return err; +} + +static cl_int test_mem_host_read_only_RW_Image_Mapping(cl_device_id deviceID, cl_context context, + cl_command_queue queue, cl_bool blocking, + cl_mem_flags buffer_mem_flag, + cl_mem_object_type image_type_in, + size_t array_size, size_t *img_dim) +{ + log_info("%s ... \n ", __FUNCTION__); + cl_int err = CL_SUCCESS; + + cImage_check_mem_host_read_only< int > checker(deviceID, context, queue); + checker.m_blocking = blocking; + checker.buffer_mem_flag = buffer_mem_flag; + + checker.m_cl_Image_desc.image_type = image_type_in; + checker.m_cl_Image_desc.image_width = img_dim[0]; + checker.m_cl_Image_desc.image_height = img_dim[1]; + checker.m_cl_Image_desc.image_depth = img_dim[2]; + checker.m_cl_Image_desc.image_array_size = array_size; + checker.m_cl_Image_desc.image_row_pitch = 0; + checker.m_cl_Image_desc.image_slice_pitch = 0; + checker.m_cl_Image_desc.num_mip_levels = 0; + checker.m_cl_Image_desc.num_samples = 0; + + checker.SetupImage(); + checker.Init_rect(); + err = checker.verify_RW_Image_Mapping(); + test_error(err, __FUNCTION__); + clFinish(queue); + return err; +} + +int test_mem_host_read_only_image(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements) +{ + cl_mem_flags buffer_mem_flags[2] = { CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR | CL_MEM_HOST_READ_ONLY, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR | CL_MEM_HOST_READ_ONLY }; + + cl_int err = CL_SUCCESS; + + cl_bool image_support; + err = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE_SUPPORT, sizeof image_support, &image_support, NULL); + if (err) { + test_error(err, __FUNCTION__); + return err; + } + if (!image_support) { + log_info("Images are not supported by the device, skipping test...\n"); + return 0; + } + + + cl_mem_object_type img_type[5] = {CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE2D, CL_MEM_OBJECT_IMAGE3D,CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY}; + + size_t img_dims[5][3] = {{200, 1, 1}, {200, 80, 1}, {200, 80, 5}, {200, 1, 1}, {200, 80, 10}}; // in elements + + size_t array_size[5] = {1, 10, 1, 10, 1}; + + cl_bool blocking[2] = {CL_TRUE, CL_FALSE}; + for (int flag=0; flag<2; flag++) + for (int i=0; i<2; i++) // blocking + { + for(int p=0; p<3; p++) + { + err = test_mem_host_read_only_RW_Image(deviceID, context, queue, blocking[i], + buffer_mem_flags[flag], img_type[p], + array_size[p], img_dims[p]); + + test_error(err, __FUNCTION__); + + err = test_mem_host_read_only_RW_Image_Mapping(deviceID, context, queue, blocking[i], + buffer_mem_flags[flag], img_type[p], + array_size[p], img_dims[p]); + + test_error(err, __FUNCTION__); + } + } + + return err; +} + +//---------------------------- +static cl_int test_MEM_HOST_WRIE_ONLY_Image_RW (cl_device_id deviceID, cl_context context, + cl_command_queue queue, cl_bool blocking, + cl_mem_flags buffer_mem_flag, + cl_mem_object_type image_type_in, + size_t array_size, size_t *img_dim) +{ + log_info(" %s ... \n ", __FUNCTION__); + cl_int err = CL_SUCCESS; + + cImage_check_mem_host_write_only< int > checker(deviceID, context, queue); + checker.m_blocking = blocking; + checker.buffer_mem_flag = buffer_mem_flag; + + checker.m_cl_Image_desc.image_type = image_type_in; + checker.m_cl_Image_desc.image_width = img_dim[0]; + checker.m_cl_Image_desc.image_height = img_dim[1]; + checker.m_cl_Image_desc.image_depth = img_dim[2]; + checker.m_cl_Image_desc.image_array_size = array_size; + checker.m_cl_Image_desc.image_row_pitch = 0; + checker.m_cl_Image_desc.image_slice_pitch = 0; + checker.m_cl_Image_desc.num_mip_levels = 0; + checker.m_cl_Image_desc.num_samples = 0; + + checker.SetupImage(); + checker.Init_rect(); + checker.Setup_Test_Environment(); + + err = checker.verify_RW_Image(); + clFinish(queue); + test_error(err, __FUNCTION__); + + return err; +} + +static cl_int test_MEM_HOST_WRITE_ONLY_Image_RW_Mapping(cl_device_id deviceID, cl_context context, + cl_command_queue queue, cl_bool blocking, + cl_mem_flags buffer_mem_flag, + cl_mem_object_type image_type_in, + size_t array_size, size_t *img_dim) +{ + log_info("%s ... \n ", __FUNCTION__); + cl_int err = CL_SUCCESS; + + cImage_check_mem_host_write_only< int > checker(deviceID, context, queue); + checker.m_blocking = blocking; + checker.buffer_mem_flag = buffer_mem_flag; + + checker.m_cl_Image_desc.image_type = image_type_in; + checker.m_cl_Image_desc.image_width = img_dim[0]; + checker.m_cl_Image_desc.image_height = img_dim[1]; + checker.m_cl_Image_desc.image_depth = img_dim[2]; + checker.m_cl_Image_desc.image_array_size = array_size; + checker.m_cl_Image_desc.image_row_pitch = 0; + checker.m_cl_Image_desc.image_slice_pitch = 0; + checker.m_cl_Image_desc.num_mip_levels = 0; + checker.m_cl_Image_desc.num_samples = 0; + + checker.SetupImage(); + checker.Init_rect(); + checker.Setup_Test_Environment(); + + err = checker.verify_RW_Image_Mapping(); + clFinish(queue); + test_error(err, __FUNCTION__); + + return err; +} + +int test_mem_host_write_only_image(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements) +{ + cl_mem_flags buffer_mem_flags[2] = { CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR | CL_MEM_HOST_WRITE_ONLY, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR | CL_MEM_HOST_WRITE_ONLY }; + + cl_int err = CL_SUCCESS; + + cl_bool image_support; + err = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE_SUPPORT, sizeof image_support, &image_support, NULL); + if (err) { + test_error(err, __FUNCTION__); + return err; + } + if (!image_support) { + log_info("Images are not supported by the device, skipping test...\n"); + return 0; + } + + cl_mem_object_type img_type[5]= {CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE2D, CL_MEM_OBJECT_IMAGE3D, + CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY}; + + size_t img_dims[5][3]= {{200, 1, 1}, {200, 80, 1}, {200, 80, 5}, {200, 1, 1}, {200, 80, 1} }; // in elements + + size_t array_size[5] = {1, 10, 1, 10, 1}; + + cl_bool blocking[2] = {CL_TRUE, CL_FALSE}; + for (int k=0; k<2; k++) + for (int i=0; i<2; i++) // blocking + { + for (int p=0; p<3; p++) + { + err = test_MEM_HOST_WRIE_ONLY_Image_RW(deviceID, context, queue, blocking[i], + buffer_mem_flags[k], img_type[p], array_size[p], img_dims[p]); + test_error(err, __FUNCTION__); + + err = test_MEM_HOST_WRITE_ONLY_Image_RW_Mapping(deviceID, context, queue, blocking[i], + buffer_mem_flags[k], img_type[p], array_size[p], img_dims[p]); + test_error(err, __FUNCTION__); + } + } + + return err; +} + +//-------- + +static cl_int test_mem_host_no_access_Image_RW(cl_device_id deviceID, cl_context context, + cl_command_queue queue, cl_bool blocking, + cl_mem_flags buffer_mem_flag, + cl_mem_object_type image_type_in, + size_t array_size, size_t *img_dim) +{ + log_info("%s ... \n", __FUNCTION__); + cl_int err = CL_SUCCESS; + + cImage_check_mem_host_no_access< int > checker(deviceID, context, queue); + + checker.m_blocking = blocking; + checker.buffer_mem_flag = buffer_mem_flag; + + checker.m_cl_Image_desc.image_type = image_type_in; + checker.m_cl_Image_desc.image_width = img_dim[0]; + checker.m_cl_Image_desc.image_height = img_dim[1]; + checker.m_cl_Image_desc.image_depth = img_dim[2]; + checker.m_cl_Image_desc.image_array_size = array_size; + checker.m_cl_Image_desc.image_row_pitch = 0; + checker.m_cl_Image_desc.image_slice_pitch = 0; + checker.m_cl_Image_desc.num_mip_levels = 0; + checker.m_cl_Image_desc.num_samples = 0; + + checker.SetupImage(); + checker.Init_rect(); + checker.Setup_Test_Environment(); + err = checker.verify_RW_Image(); + test_error(err, __FUNCTION__); + clFinish(queue); + return err; +} + +static cl_int test_mem_host_no_access_Image_RW_Mapping(cl_device_id deviceID, cl_context context, + cl_command_queue queue, cl_bool blocking, + cl_mem_flags buffer_mem_flag, + cl_mem_object_type image_type_in, + size_t array_size, size_t *img_dim) +{ + log_info("%s ... \n ", __FUNCTION__); + cl_int err =CL_SUCCESS; + + cImage_check_mem_host_no_access< int > checker(deviceID, context, queue); + + checker.m_blocking = blocking; + checker.buffer_mem_flag = buffer_mem_flag; + + checker.m_cl_Image_desc.image_type = image_type_in; + checker.m_cl_Image_desc.image_width = img_dim[0]; + checker.m_cl_Image_desc.image_height = img_dim[1]; + checker.m_cl_Image_desc.image_depth = img_dim[2]; + checker.m_cl_Image_desc.image_array_size = array_size; + checker.m_cl_Image_desc.image_row_pitch = 0; + checker.m_cl_Image_desc.image_slice_pitch = 0; + checker.m_cl_Image_desc.num_mip_levels = 0; + checker.m_cl_Image_desc.num_samples = 0; + + checker.SetupImage(); + checker.Init_rect(); + checker.Setup_Test_Environment(); + err = checker.verify_RW_Image_Mapping(); + test_error(err, __FUNCTION__); + clFinish(queue); + return err; +} + +int test_mem_host_no_access_image(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements) +{ + cl_mem_flags buffer_mem_flags[2] = {CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR | CL_MEM_HOST_NO_ACCESS, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR | CL_MEM_HOST_NO_ACCESS }; + + cl_int err = CL_SUCCESS; + + cl_bool image_support; + err = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE_SUPPORT, sizeof image_support, &image_support, NULL); + if (err) { + test_error(err, __FUNCTION__); + return err; + } + if (!image_support) { + log_info("Images are not supported by the device, skipping test...\n"); + return 0; + } + + cl_mem_object_type img_type[5] = {CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE2D, CL_MEM_OBJECT_IMAGE3D, + CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY}; + + size_t img_dims[5][3]= {{200, 1, 1}, {200, 80, 1}, {100, 80, 5}, {200, 1, 1}, {200, 80, 1}}; // in elements + + size_t array_size [5] = {1, 1, 1, 10, 10}; + + cl_bool blocking[2] = { CL_TRUE, CL_FALSE}; + for (int k=0; k<2; k++) + for (int i=0; i<2; i++) // blocking + { + for (int p =0; p<3; p++) + { + err += test_mem_host_no_access_Image_RW (deviceID, context, queue, blocking[i], + buffer_mem_flags[k], img_type[p], array_size[p], img_dims[p]); + + err += test_mem_host_no_access_Image_RW_Mapping(deviceID, context, queue, blocking[i], + buffer_mem_flags[k], img_type[p], array_size[p], img_dims[p]); + } + } + + return err; +} diff --git a/test_conformance/mem_host_flags/procs.h b/test_conformance/mem_host_flags/procs.h new file mode 100644 index 00000000..98f81491 --- /dev/null +++ b/test_conformance/mem_host_flags/procs.h @@ -0,0 +1,45 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef __PROCS_H__ +#define __PROCS_H__ + +#include "testBase.h" + +#define NUM_FLAGS 4 + +extern int test_mem_host_read_only_buffer(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements); +extern int test_mem_host_read_only_subbuffer(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements); + +extern int test_mem_host_write_only_buffer(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements); +extern int test_mem_host_write_only_subbuffer(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements); + +extern int test_mem_host_no_access_buffer(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements); +extern int test_mem_host_no_access_subbuffer(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements); + +extern int test_mem_host_read_only_image(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements); +extern int test_mem_host_write_only_image(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements); +extern int test_mem_host_no_access_image(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements); + +#endif // #ifndef __PROCS_H__ diff --git a/test_conformance/mem_host_flags/testBase.h b/test_conformance/mem_host_flags/testBase.h new file mode 100644 index 00000000..afcdf60e --- /dev/null +++ b/test_conformance/mem_host_flags/testBase.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testBase_h +#define _testBase_h + +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#if !defined (__APPLE__) +#include +#else +//#include +#endif + +#include "../../test_common/harness/imageHelpers.h" +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/threadTesting.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/mt19937.h" + +#endif // _testBase_h diff --git a/test_conformance/multiple_device_context/CMakeLists.txt b/test_conformance/multiple_device_context/CMakeLists.txt new file mode 100644 index 00000000..e69c884b --- /dev/null +++ b/test_conformance/multiple_device_context/CMakeLists.txt @@ -0,0 +1,35 @@ +set(MODULE_NAME multiples) + +set(${MODULE_NAME}_SOURCES + main.c + test_multiple_contexts.c + test_multiple_devices.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/genericThread.cpp + ../../test_common/harness/typeWrappers.cpp + ../../test_common/harness/conversions.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + + +set_source_files_properties( + COMPILE_FLAGS -msse2) + +set_source_files_properties( + main.c + test_multiple_contexts.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/conversions.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp + PROPERTIES LANGUAGE CXX) + +include(../CMakeCommon.txt) diff --git a/test_conformance/multiple_device_context/Jamfile b/test_conformance/multiple_device_context/Jamfile new file mode 100644 index 00000000..715c2f11 --- /dev/null +++ b/test_conformance/multiple_device_context/Jamfile @@ -0,0 +1,17 @@ +project + : requirements + gcc:-xc++ + msvc:"/TP" + ; + +exe test_multiple_device_context + : main.c + test_multiple_contexts.c + test_multiple_devices.cpp + ; + +install dist + : test_multiple_device_context + : debug:$(DIST)/debug/tests/test_conformance/multiple_device_context + release:$(DIST)/release/tests/test_conformance/multiple_device_context + ; diff --git a/test_conformance/multiple_device_context/Makefile b/test_conformance/multiple_device_context/Makefile new file mode 100644 index 00000000..4054a55a --- /dev/null +++ b/test_conformance/multiple_device_context/Makefile @@ -0,0 +1,46 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + test_multiple_contexts.c \ + test_multiple_devices.cpp \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/genericThread.cpp \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/conversions.c \ + ../../test_common/harness/typeWrappers.cpp + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = $(SOURCES) +HEADERS = +TARGET = test_multiples +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/multiple_device_context/main.c b/test_conformance/multiple_device_context/main.c new file mode 100644 index 00000000..3982fde3 --- /dev/null +++ b/test_conformance/multiple_device_context/main.c @@ -0,0 +1,62 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include "procs.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/mt19937.h" + +#if !defined(_WIN32) +#include +#endif + +basefn basefn_list[] = { + test_multiple_contexts_same_device, + test_two_contexts_same_device, + test_three_contexts_same_device, + test_four_contexts_same_device, + + test_two_devices, + test_max_devices, + + test_hundred_queues +}; + + +const char *basefn_names[] = { + "context_multiple_contexts_same_device", + "context_two_contexts_same_device", + "context_three_contexts_same_device", + "context_four_contexts_same_device", + + "two_devices", + "max_devices", + + "hundred_queues", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + +int main(int argc, const char *argv[]) +{ + return runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false, true, 0 ); +} + + diff --git a/test_conformance/multiple_device_context/procs.h b/test_conformance/multiple_device_context/procs.h new file mode 100644 index 00000000..d179ccbb --- /dev/null +++ b/test_conformance/multiple_device_context/procs.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/mt19937.h" + +extern int test_multiple_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_two_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_three_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_four_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_two_devices(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_max_devices(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_hundred_queues(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements); + + diff --git a/test_conformance/multiple_device_context/testBase.h b/test_conformance/multiple_device_context/testBase.h new file mode 100644 index 00000000..5073b21f --- /dev/null +++ b/test_conformance/multiple_device_context/testBase.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testBase_h +#define _testBase_h + +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +#endif // _testBase_h + + + diff --git a/test_conformance/multiple_device_context/test_multiple_contexts.c b/test_conformance/multiple_device_context/test_multiple_contexts.c new file mode 100644 index 00000000..3f24b3af --- /dev/null +++ b/test_conformance/multiple_device_context/test_multiple_contexts.c @@ -0,0 +1,529 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/testHarness.h" + +const char *context_test_kernels[] = { + "__kernel void sample_test_1(__global int *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = src[tid];\n" + "\n" + "}\n" + + "__kernel void sample_test_2(__global int *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = src[tid] * 2;\n" + "\n" + "}\n" + + "__kernel void sample_test_3(__global int *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = src[tid] / 2;\n" + "\n" + "}\n" + + "__kernel void sample_test_4(__global int *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + " dst[tid] = src[tid] /3;\n" + "\n" + "}\n" +}; + +int sampleAction1( int source ) { return source; } +int sampleAction2( int source ) { return source * 2; } +int sampleAction3( int source ) { return source / 2; } +int sampleAction4( int source ) { return source / 3; } + + +typedef int (*sampleActionFn)( int source ); + +sampleActionFn sampleActions[4] = { sampleAction1, sampleAction2, sampleAction3, sampleAction4 }; + +#define BUFFER_COUNT 2 +#define TEST_SIZE 512 + +typedef struct TestItem +{ + struct TestItem *next; + cl_context c; + cl_command_queue q; + cl_program p; + cl_kernel k[4]; + cl_mem m[BUFFER_COUNT]; + MTdata d; +}TestItem; + +static void DestroyTestItem( TestItem *item ); + +// Attempt to create a context and associated objects +TestItem *CreateTestItem( cl_device_id deviceID, cl_int *err ) +{ + cl_int error = 0; + size_t i; + + // Allocate the TestItem struct + TestItem *item = (TestItem *) malloc( sizeof(TestItem ) ); + if( NULL == item ) + { + if( err ) + { + log_error( "FAILURE: Failed to allocate TestItem -- out of host memory!\n" ); + *err = CL_OUT_OF_HOST_MEMORY; + } + return NULL; + } + //zero so we know which fields we have initialized + memset( item, 0, sizeof( *item ) ); + + item->d = init_genrand( gRandomSeed ); + if( NULL == item->d ) + { + if( err ) + { + log_error( "FAILURE: Failed to allocate mtdata om CreateTestItem -- out of host memory!\n" ); + *err = CL_OUT_OF_HOST_MEMORY; + } + DestroyTestItem( item ); + return NULL; + } + + + // Create a context + item->c = clCreateContext(NULL, 1, &deviceID, notify_callback, NULL, &error ); + if( item->c == NULL || error != CL_SUCCESS) + { + if (err) { + log_error( "FAILURE: clCreateContext failed in CreateTestItem: %d\n", error); + *err = error; + } + DestroyTestItem( item ); + return NULL; + } + + // Create a queue + item->q = clCreateCommandQueueWithProperties( item->c, deviceID, 0, &error); + if( item->q == NULL || error != CL_SUCCESS) + { + if (err) { + log_error( "FAILURE: clCreateCommandQueue failed in CreateTestItem: %d\n", error ); + *err = error; + } + DestroyTestItem( item ); + return NULL; + } + + // Create a program + error = create_single_kernel_helper_create_program(item->c, &item->p, 1, context_test_kernels); + if( NULL == item->p || CL_SUCCESS != error ) + { + if( err ) + { + log_error( "FAILURE: clCreateProgram failed in CreateTestItem: %d\n", error ); + *err = error; + } + DestroyTestItem( item ); + return NULL; + } + + error = clBuildProgram( item->p, 1, &deviceID, "", NULL, NULL ); + if( error ) + { + if( err ) + { + log_error( "FAILURE: clBuildProgram failed in CreateTestItem: %d\n", error ); + *err = error; + } + DestroyTestItem( item ); + return NULL; + } + + // create some kernels + for( i = 0; i < sizeof( item->k ) / sizeof( item->k[0] ); i++ ) + { + static const char *kernelNames[] = { "sample_test_1", "sample_test_2", "sample_test_3", "sample_test_4" }; + item->k[i] = clCreateKernel( item->p, kernelNames[i], &error ); + if( NULL == item->k[i] || CL_SUCCESS != error ) + { + if( err ) + { + log_error( "FAILURE: clCreateKernel( \"%s\" ) failed in CreateTestItem: %d\n", kernelNames[i], error ); + *err = error; + } + DestroyTestItem( item ); + return NULL; + } + } + + // create some mem objects + for( i = 0; i < BUFFER_COUNT; i++ ) + { + item->m[i] = clCreateBuffer( item->c, CL_MEM_READ_WRITE, TEST_SIZE * sizeof(cl_int), NULL, &error ); + if( NULL == item->m[i] || CL_SUCCESS != error ) + { + if( err ) + { + log_error( "FAILURE: clCreateBuffer( %ld bytes ) failed in CreateTestItem: %d\n", TEST_SIZE * sizeof(cl_int), error ); + *err = error; + } + DestroyTestItem( item ); + return NULL; + } + } + + + return item; +} + +// Destroy a context and associate objects +static void DestroyTestItem( TestItem *item ) +{ + size_t i; + + if( NULL == item ) + return; + + if( item->d ) + free_mtdata( item->d ); + if( item->c) + clReleaseContext( item->c ); + if( item->q) + clReleaseCommandQueue( item->q ); + if( item->p) + clReleaseProgram( item->p ); + for( i = 0; i < sizeof( item->k ) / sizeof( item->k[0] ); i++ ) + { + if( item->k[i]) + clReleaseKernel( item->k[i] ); + } + for( i = 0; i < BUFFER_COUNT; i++ ) + { + if( item->m[i]) + clReleaseMemObject( item->m[i] ); + } + free(item ); +} + + +cl_int UseTestItem( const TestItem *item, cl_int *err ) +{ + size_t i, j; + cl_int error = CL_SUCCESS; + + // Fill buffer 0 with random numbers + cl_int *mapped = (cl_int*) clEnqueueMapBuffer( item->q, item->m[0], CL_TRUE, CL_MAP_WRITE, 0, TEST_SIZE * sizeof( cl_int ), 0, NULL, NULL, &error ); + if( NULL == mapped || CL_SUCCESS != error ) + { + if( err ) + { + log_error( "FAILURE: Failed to map buffer 0 for writing: %d\n", error ); + *err = error; + } + return error; + } + + for( j = 0; j < TEST_SIZE; j++ ) + mapped[j] = genrand_int32(item->d); + + error = clEnqueueUnmapMemObject( item->q, item->m[0], mapped, 0, NULL, NULL ); + if( CL_SUCCESS != error ) + { + if( err ) + { + log_error( "FAILURE: failure to unmap buffer 0 for writing: %d\n", error ); + *err = error; + } + return error; + } + + // try each kernel in turn. + for( j = 0; j < sizeof(item->k) / sizeof( item->k[0] ); j++ ) + { + // Fill buffer 1 with 0xdeaddead + mapped = (cl_int*) clEnqueueMapBuffer( item->q, item->m[1], CL_TRUE, CL_MAP_WRITE, 0, TEST_SIZE * sizeof( cl_int ), 0, NULL, NULL, &error ); + if( NULL == mapped || CL_SUCCESS != error ) + { + if( err ) + { + log_error( "Failed to map buffer 1 for writing: %d\n", error ); + *err = error; + } + return error; + } + + for( i = 0; i < TEST_SIZE; i++ ) + mapped[i] = 0xdeaddead; + + error = clEnqueueUnmapMemObject( item->q, item->m[1], mapped, 0, NULL, NULL ); + if( CL_SUCCESS != error ) + { + if( err ) + { + log_error( "Failed to unmap buffer 1 for writing: %d\n", error ); + *err = error; + } + return error; + } + + // Run the kernel + error = clSetKernelArg( item->k[j], 0, sizeof( cl_mem), &item->m[0] ); + if( error ) + { + if( err ) + { + log_error( "FAILURE to set arg 0 for kernel # %ld : %d\n", j, error ); + *err = error; + } + return error; + } + + error = clSetKernelArg( item->k[j], 1, sizeof( cl_mem), &item->m[1] ); + if( error ) + { + if( err ) + { + log_error( "FAILURE: Unable to set arg 1 for kernel # %ld : %d\n", j, error ); + *err = error; + } + return error; + } + + size_t work_size = TEST_SIZE; + size_t global_offset = 0; + error = clEnqueueNDRangeKernel( item->q, item->k[j], 1, &global_offset, &work_size, NULL, 0, NULL, NULL ); + if( CL_SUCCESS != error ) + { + if( err ) + { + log_error( "FAILURE: Unable to enqueue kernel %ld: %d\n", j, error ); + *err = error; + } + return error; + } + + // Get the results back + mapped = (cl_int*) clEnqueueMapBuffer( item->q, item->m[1], CL_TRUE, CL_MAP_READ, 0, TEST_SIZE * sizeof( cl_int ), 0, NULL, NULL, &error ); + if( NULL == mapped || CL_SUCCESS != error ) + { + if( err ) + { + log_error( "Failed to map buffer 1 for reading: %d\n", error ); + *err = error; + } + return error; + } + + // Get our input data so we can check against it + cl_int *inputData = (cl_int*) clEnqueueMapBuffer( item->q, item->m[0], CL_TRUE, CL_MAP_READ, 0, TEST_SIZE * sizeof( cl_int ), 0, NULL, NULL, &error ); + if( NULL == mapped || CL_SUCCESS != error ) + { + if( err ) + { + log_error( "Failed to map buffer 0 for reading: %d\n", error ); + *err = error; + } + return error; + } + + + //Verify the results + for( i = 0; i < TEST_SIZE; i++ ) + { + int expected = sampleActions[j]( inputData[i] ); + int result = mapped[i]; + if( expected != result ) + { + log_error( "FAILURE: Sample data at position %ld does not match expected result: *0x%8.8x vs. 0x%8.8x\n", i, expected, result ); + if( err ) + *err = -1; + return -1; + } + } + + //Clean up + error = clEnqueueUnmapMemObject( item->q, item->m[0], inputData, 0, NULL, NULL ); + if( CL_SUCCESS != error ) + { + if( err ) + { + log_error( "Failed to unmap buffer 0 for reading: %d\n", error ); + *err = error; + } + return error; + } + + error = clEnqueueUnmapMemObject( item->q, item->m[1], mapped, 0, NULL, NULL ); + if( CL_SUCCESS != error ) + { + if( err ) + { + log_error( "Failed to unmap buffer 1 for reading: %d\n", error ); + *err = error; + } + return error; + } + + } + + // Make sure that the last set of unmap calls get run + error = clFinish( item->q ); + if( CL_SUCCESS != error ) + { + if( err ) + { + log_error( "Failed to clFinish: %d\n", error ); + *err = error; + } + return error; + } + + return CL_SUCCESS; +} + + + +int test_multiple_contexts_same_device(cl_device_id deviceID, size_t maxCount, size_t minCount ) +{ + size_t i, j; + cl_int err = CL_SUCCESS; + + //Figure out how many of these we can make before the first failure + TestItem *list = NULL; + + for( i = 0; i < maxCount; i++ ) + { + // create a context and accompanying objects + TestItem *current = CreateTestItem( deviceID, NULL /*no error reporting*/ ); + if( NULL == current ) + break; + + // Attempt to use it + cl_int failed = UseTestItem( current, NULL ); + + if( failed ) + { + DestroyTestItem( current ); + break; + } + + // Add the successful test item to the list + current->next = list; + list = current; + } + + // Check to make sure we made the minimum amount + if( i < minCount ) + { + log_error( "FAILURE: only could make %ld of %ld contexts!\n", i, minCount ); + err = -1; + goto exit; + } + + // Report how many contexts we made + if( i == maxCount ) + log_info( "Successfully created all %lu contexts.\n", i ); + else + log_info( "Successfully created %lu contexts out of %lu\n", i, maxCount ); + + // Set the count to be the number we succesfully made + maxCount = i; + + // Make sure we can do it again a few times + log_info( "Tring to do it 5 more times" ); + fflush( stdout); + for( j = 0; j < 5; j++ ) + { + //free all the contexts we already made + while( list ) + { + TestItem *current = list; + list = list->next; + current->next = NULL; + DestroyTestItem( current ); + } + + // Attempt to make them again + for( i = 0; i < maxCount; i++ ) + { + // create a context and accompanying objects + TestItem *current = CreateTestItem( deviceID, &err ); + if( err ) + { + log_error( "\nTest Failed with error at CreateTestItem: %d\n", err ); + goto exit; + } + + // Attempt to use it + cl_int failed = UseTestItem( current, &err ); + + if( failed || err ) + { + DestroyTestItem( current ); + log_error( "\nTest Failed with error at UseTestItem: %d\n", err ); + goto exit; + } + + // Add the successful test item to the list + current->next = list; + list = current; + } + log_info( "." ); + fflush( stdout ); + } + + log_info( "Done.\n" ); + +exit: + //free all the contexts we already made + while( list ) + { + TestItem *current = list; + list = list->next; + current->next = NULL; + + DestroyTestItem( current ); + } + + return err; +} + +// This test tests to make sure that your implementation isn't super leaky. We make a bunch of contexts (up to some +// sane limit, currently 200), attempting to use each along the way. We keep track of how many we could make before +// a failure occurred. We then free everything and attempt to go do it again a few times. If you are able to make +// that many contexts 5 times over, then you pass. +int test_multiple_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_multiple_contexts_same_device( deviceID, 200, 1 ); +} + +int test_two_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_multiple_contexts_same_device( deviceID, 2, 2 ); +} + +int test_three_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_multiple_contexts_same_device( deviceID, 3, 3 ); +} + +int test_four_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + return test_multiple_contexts_same_device( deviceID, 4, 4 ); +} + diff --git a/test_conformance/multiple_device_context/test_multiple_devices.cpp b/test_conformance/multiple_device_context/test_multiple_devices.cpp new file mode 100644 index 00000000..1766e669 --- /dev/null +++ b/test_conformance/multiple_device_context/test_multiple_devices.cpp @@ -0,0 +1,236 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/conversions.h" + +const char *test_kernels[] = { +"__kernel void kernelA(__global int *dst)\n" +"{\n" +"\n" +" dst[get_global_id(0)]*=3;\n" +"\n" +"}\n" +"__kernel void kernelB(__global int *dst)\n" +"{\n" +"\n" +" dst[get_global_id(0)]++;\n" +"\n" +"}\n" +}; + +#define TEST_SIZE 512 +#define MAX_DEVICES 8 +#define MAX_QUEUES 1000 + +int test_device_set(size_t deviceCount, size_t queueCount, cl_device_id *devices, int num_elements) +{ + int error; + clContextWrapper context; + clProgramWrapper program; + clKernelWrapper kernels[2]; + clMemWrapper stream; + clCommandQueueWrapper queues[MAX_QUEUES]; + size_t threads[1], localThreads[1]; + int data[TEST_SIZE]; + int outputData[TEST_SIZE]; + int expectedResults[TEST_SIZE]; + int expectedResultsOneDevice[MAX_DEVICES][TEST_SIZE]; + size_t i; + + memset(queues, 0, sizeof(queues)); + + RandomSeed seed( gRandomSeed ); + + if (deviceCount > MAX_DEVICES) { + log_error("Number of devices in set (%ld) is greater than the number for which the test was written (%d).", deviceCount, MAX_DEVICES); + return -1; + } + + if (queueCount > MAX_QUEUES) { + log_error("Number of queues (%ld) is greater than the number for which the test was written (%d).", queueCount, MAX_QUEUES); + return -1; + } + + log_info("Testing with %ld queues on %ld devices, %ld kernel executions.\n", queueCount, deviceCount, queueCount*num_elements/TEST_SIZE); + + for (i=0; i 2) + { + log_info("Note: got %d devices, using just the first two.\n", (int)numDevices); + } + + /* Run test */ + return test_device_set( 2, 2, devices, num_elements ); +} + +int test_max_devices(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_platform_id platform; + cl_device_id devices[MAX_DEVICES]; + cl_uint deviceCount; + int err; + + err = clGetPlatformIDs(1, &platform, NULL); + test_error( err, "Unable to get platform" ); + + /* Get some devices */ + err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, MAX_DEVICES, devices, &deviceCount ); + test_error( err, "Unable to get multiple devices" ); + + log_info("Testing with %d devices.", deviceCount); + + /* Run test */ + return test_device_set( deviceCount, deviceCount, devices, num_elements ); +} + +int test_hundred_queues(cl_device_id device, cl_context contextIgnore, cl_command_queue queueIgnore, int num_elements) +{ + return test_device_set( 1, 100, &device, num_elements ); +} + diff --git a/test_conformance/non_uniform_work_group/CMakeLists.txt b/test_conformance/non_uniform_work_group/CMakeLists.txt new file mode 100644 index 00000000..69dc4adb --- /dev/null +++ b/test_conformance/non_uniform_work_group/CMakeLists.txt @@ -0,0 +1,20 @@ +set(MODULE_NAME NON_UNIFORM_WORK_GROUP) + +set(${MODULE_NAME}_SOURCES + main.cpp + test_advanced_2d.cpp + test_advanced_3d.cpp + test_advanced_other.cpp + test_basic.cpp + TestNonUniformWorkGroup.cpp + tools.cpp + ../../test_common/harness/testHarness.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) + +# end of file # diff --git a/test_conformance/non_uniform_work_group/Makefile b/test_conformance/non_uniform_work_group/Makefile new file mode 100644 index 00000000..3051c618 --- /dev/null +++ b/test_conformance/non_uniform_work_group/Makefile @@ -0,0 +1,46 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + test_basic.cpp \ + test_advanced_2d.cpp \ + test_advanced_3d.cpp \ + test_advanced_other.cpp \ + TestNonUniformWorkGroup.cpp \ + tools.cpp \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/typeWrappers.cpp \ + +DEFINES = DONT_TEST_GARBAGE_POINTERS + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +HEADERS = +TARGET = test_non_uniform_workgroup +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/non_uniform_work_group/TestNonUniformWorkGroup.cpp b/test_conformance/non_uniform_work_group/TestNonUniformWorkGroup.cpp new file mode 100644 index 00000000..381d29bc --- /dev/null +++ b/test_conformance/non_uniform_work_group/TestNonUniformWorkGroup.cpp @@ -0,0 +1,751 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "TestNonUniformWorkGroup.h" +#include +#include +#define NL "\n" + +size_t TestNonUniformWorkGroup::_maxLocalWorkgroupSize = 0; +bool TestNonUniformWorkGroup::_strictMode = false; + +// Main Kernel source code +static const char *KERNEL_FUNCTION = + NL "#define MAX_DIMS 3" + NL "typedef struct _DataContainerAttrib" + NL "{" + NL " unsigned long get_global_size[MAX_DIMS];" + NL " unsigned long get_global_offset[MAX_DIMS];" + NL " unsigned long get_local_size[MAX_DIMS];" + NL " unsigned long get_enqueued_local_size[MAX_DIMS];" + NL " unsigned long get_global_id[MAX_DIMS];" + NL " unsigned long get_local_id[MAX_DIMS];" + NL " unsigned long get_group_id[MAX_DIMS];" + NL " unsigned long get_num_groups[MAX_DIMS];" + NL " unsigned long get_work_dim;" + NL " unsigned short test_local_barrier_result_bool;" + NL " unsigned short test_global_barrier_result_bool;" + NL " unsigned short test_local_atomic_result_value;" + NL "}DataContainerAttrib;" + + NL "enum Error{" + NL " ERR_GLOBAL_SIZE=0," + NL " ERR_GLOBAL_WORK_OFFSET," + NL " ERR_LOCAL_SIZE," + NL " ERR_GLOBAL_ID," + NL " ERR_LOCAL_ID," + NL " ERR_ENQUEUED_LOCAL_SIZE," + NL " ERR_NUM_GROUPS," + NL " ERR_GROUP_ID," + NL " ERR_WORK_DIM," + NL " ERR_GLOBAL_BARRIER," + NL " ERR_LOCAL_BARRIER," + NL " ERR_GLOBAL_ATOMIC," + NL " ERR_LOCAL_ATOMIC," + NL " ERR_STRICT_MODE," + NL " ERR_BUILD_STATUS," + NL " ERR_UNKNOWN," + NL " ERR_DIFFERENT," + NL " _LAST_ELEM" + NL "};" + + NL "uint getGlobalIndex (uint gid2, uint gid1, uint gid0) {" + NL " return gid2*get_global_size(0)*get_global_size(1) + gid1*get_global_size(0) + gid0;" + NL "}" + + NL "int getRegionIndex () {" + NL " uint gid0 = get_global_id(0) - get_global_offset(0);" + NL " uint gid1 = get_global_id(1) - get_global_offset(1);" + NL " uint gid2 = get_global_id(2) - get_global_offset(2);" + NL " if (gid0 == 0 && gid1 == 0 && gid2 == 0) {" + NL " return 0;" + NL " } else if (gid0 == get_global_size(0) - 1 && gid1 == 0 && gid2 == 0) {" + NL " return 1;" + NL " } else if (gid0 == 0 && gid1 == get_global_size(1) - 1 && gid2 == 0) {" + NL " return 2;" + NL " } else if (gid0 == get_global_size(0) - 1 && gid1 == get_global_size(1) - 1 && gid2 == 0) {" + NL " return 3;" + NL " } else if (gid0 == 0 && gid1 == 0 && gid2 == get_global_size(2) - 1) {" + NL " return 4;" + NL " } else if (gid0 == get_global_size(0) - 1 && gid1 == 0 && gid2 == get_global_size(2) - 1) {" + NL " return 5;" + NL " } else if (gid0 == 0 && gid1 == get_global_size(1) - 1 && gid2 == get_global_size(2) - 1) {" + NL " return 6;" + NL " } else if (gid0 == get_global_size(0) - 1 && gid1 == get_global_size(1) - 1 && gid2 == get_global_size(2) - 1) {" + NL " return 7;" + NL " }" + NL " return -1;" + NL "}" + + NL "void getLocalSize(__global DataContainerAttrib *results) {" + NL " for (unsigned short i = 0; i < MAX_DIMS; i++) {" + NL " results->get_local_size[i] = get_local_size(i);" + NL " }" + NL "}" + + NL "#ifdef TESTBASIC" + // values set by this function will be checked on the host side + NL "void testBasicHost(__global DataContainerAttrib *results) {" + NL " for (unsigned short i = 0; i < MAX_DIMS; i++) {" + NL " results->get_global_size[i] = get_global_size(i);" + NL " results->get_global_offset[i] = get_global_offset(i);" + NL " results->get_enqueued_local_size[i] = get_enqueued_local_size(i);" + NL " results->get_global_id[i] = get_global_id(i);" + NL " results->get_local_id[i] = get_local_id(i);" + NL " results->get_group_id[i] = get_group_id(i);" + NL " results->get_num_groups[i] = get_num_groups(i);" + NL " }" + NL " results->get_work_dim = get_work_dim();" + NL "}" + // values set by this function are checked on the kernel side + NL "void testBasicKernel(__global unsigned int *errorCounterBuffer, __local DataContainerAttrib *resultsForThread0) {" + NL " uint lid0 = get_local_id(0);" + NL " uint lid1 = get_local_id(1);" + NL " uint lid2 = get_local_id(2);" + NL " if (lid0 == 0 && lid1 == 0 && lid2 == 0) {" + NL " for (unsigned short i = 0; i < MAX_DIMS; i++) {" + NL " resultsForThread0->get_global_size[i] = get_global_size(i);" + NL " resultsForThread0->get_global_offset[i] = get_global_offset(i);" + NL " resultsForThread0->get_enqueued_local_size[i] = get_enqueued_local_size(i);" + NL " resultsForThread0->get_group_id[i] = get_group_id(i);" + NL " resultsForThread0->get_num_groups[i] = get_num_groups(i);" + NL " }" + NL " resultsForThread0->get_work_dim = get_work_dim();" + NL " }" + NL " barrier(CLK_LOCAL_MEM_FENCE);" + // verifies built in functions on the kernel side + NL " if (lid0 != 0 || lid1 != 0 || lid2 != 0) {" + NL " for (unsigned short i = 0; i < MAX_DIMS; i++) {" + NL " if (resultsForThread0->get_global_size[i] != get_global_size(i)) {" + NL " atomic_inc(&errorCounterBuffer[ERR_GLOBAL_SIZE]);" + NL " }" + NL " if (resultsForThread0->get_global_offset[i] != get_global_offset(i)) {" + NL " atomic_inc(&errorCounterBuffer[ERR_GLOBAL_WORK_OFFSET]);" + NL " }" + NL " if (resultsForThread0->get_enqueued_local_size[i] != get_enqueued_local_size(i)) {" + NL " atomic_inc(&errorCounterBuffer[ERR_ENQUEUED_LOCAL_SIZE]);" + NL " }" + NL " if (resultsForThread0->get_group_id[i] != get_group_id(i)) {" + NL " atomic_inc(&errorCounterBuffer[ERR_GROUP_ID]);" + NL " }" + NL " if (resultsForThread0->get_num_groups[i] != get_num_groups(i)) {" + NL " atomic_inc(&errorCounterBuffer[ERR_NUM_GROUPS]);" + NL " }" + NL " }" + NL " if (resultsForThread0->get_work_dim != get_work_dim()) {" + NL " atomic_inc(&errorCounterBuffer[ERR_WORK_DIM]);" + NL " }" + NL " }" + NL "}" + NL "#endif" + + NL "#ifdef TESTBARRIERS" + NL "void testBarriers(__global unsigned int *errorCounterBuffer, __local unsigned int *testLocalBuffer, __global unsigned int *testGlobalBuffer) {" + NL " uint gid0 = get_global_id(0);" + NL " uint gid1 = get_global_id(1);" + NL " uint gid2 = get_global_id(2);" + NL " uint lid0 = get_local_id(0);" + NL " uint lid1 = get_local_id(1);" + NL " uint lid2 = get_local_id(2);" + NL + NL " uint globalIndex = getGlobalIndex(gid2-get_global_offset(2), gid1-get_global_offset(1), gid0-get_global_offset(0));" + NL " uint localIndex = lid2*get_local_size(0)*get_local_size(1) + lid1*get_local_size(0) + lid0;" + NL " testLocalBuffer[localIndex] = 0;" + NL " testGlobalBuffer[globalIndex] = 0;" + NL " uint maxLocalIndex = get_local_size(0)*get_local_size(1)*get_local_size(2)-1;" + NL " uint nextLocalIndex = (localIndex>=maxLocalIndex)?0:(localIndex+1);" + NL " uint next_lid0 = (lid0+1>=get_local_size(0))?0:lid0+1;" + NL " uint next_lid1 = (lid1+1>=get_local_size(1))?0:lid1+1;" + NL " uint next_lid2 = (lid2+1>=get_local_size(2))?0:lid2+1;" + NL " uint nextGlobalIndexInLocalWorkGroup = getGlobalIndex (get_group_id(2)*get_enqueued_local_size(2)+next_lid2, get_group_id(1)*get_enqueued_local_size(1)+next_lid1, get_group_id(0)*get_enqueued_local_size(0)+next_lid0);" + // testing local barriers + NL " testLocalBuffer[localIndex] = localIndex;" + NL " barrier(CLK_LOCAL_MEM_FENCE);" + NL " uint temp = testLocalBuffer[nextLocalIndex];" + NL " if (temp != nextLocalIndex) {" + NL " atomic_inc(&errorCounterBuffer[ERR_LOCAL_BARRIER]);" + NL " }" + // testing global barriers + NL " testGlobalBuffer[globalIndex] = globalIndex;" + NL " barrier(CLK_GLOBAL_MEM_FENCE);" + NL " uint temp2 = testGlobalBuffer[nextGlobalIndexInLocalWorkGroup];" + NL " if (temp2 != nextGlobalIndexInLocalWorkGroup) {" + NL " atomic_inc(&errorCounterBuffer[ERR_GLOBAL_BARRIER]);" + NL " }" + NL "}" + NL "#endif" + + NL "#ifdef TESTATOMICS" + NL "void testAtomics(__global unsigned int *globalAtomicTestVariable, __local unsigned int *localAtomicTestVariable) {" + NL " uint gid0 = get_global_id(0);" + NL " uint gid1 = get_global_id(1);" + NL " uint gid2 = get_global_id(2);" + NL + NL " uint globalIndex = getGlobalIndex(gid2-get_global_offset(2), gid1-get_global_offset(1), gid0-get_global_offset(0));" + // testing atomic function on local memory + NL " atomic_inc(localAtomicTestVariable);" + NL " barrier(CLK_LOCAL_MEM_FENCE);" + // testing atomic function on global memory + NL " atomic_inc(globalAtomicTestVariable);" + NL "}" + NL "#endif" + + NL "#ifdef RWGSX" + NL "#ifdef RWGSY" + NL "#ifdef RWGSZ" + NL "__attribute__((reqd_work_group_size(RWGSX, RWGSY, RWGSZ)))" + NL "#endif" + NL "#endif" + NL "#endif" + NL "__kernel void testKernel(__global DataContainerAttrib *results, __local unsigned int *testLocalBuffer," + NL " __global unsigned int *testGlobalBuffer, __global unsigned int *globalAtomicTestVariable, __global unsigned int *errorCounterBuffer) {" + NL " uint gid0 = get_global_id(0);" + NL " uint gid1 = get_global_id(1);" + NL " uint gid2 = get_global_id(2);" + NL + NL " uint globalIndex = getGlobalIndex(gid2-get_global_offset(2), gid1-get_global_offset(1), gid0-get_global_offset(0));" + NL " int regionIndex = getRegionIndex();" + NL " if (regionIndex >= 0) {" + NL " getLocalSize(&results[regionIndex]);" + NL " }" + NL "#ifdef TESTBASIC" + NL " if (regionIndex >= 0) {" + NL " testBasicHost(&results[regionIndex]);" + NL " }" + NL " __local DataContainerAttrib resultsForThread0;" + NL " testBasicKernel(errorCounterBuffer, &resultsForThread0);" + NL "#endif" + NL "#ifdef TESTBARRIERS" + NL " testBarriers(errorCounterBuffer, testLocalBuffer, testGlobalBuffer);" + NL "#endif" + NL "#ifdef TESTATOMICS" + NL " __local unsigned int localAtomicTestVariable;" + NL " localAtomicTestVariable = 0;" + NL " barrier(CLK_LOCAL_MEM_FENCE);" + NL " testAtomics(globalAtomicTestVariable, &localAtomicTestVariable);" + NL " barrier(CLK_LOCAL_MEM_FENCE);" + NL " if (localAtomicTestVariable != get_local_size(0) * get_local_size(1) * get_local_size(2)) {" + NL " atomic_inc(&errorCounterBuffer[ERR_LOCAL_ATOMIC]);" + NL " }" + NL "#endif" + NL "}" + NL ; + +TestNonUniformWorkGroup::TestNonUniformWorkGroup (const cl_device_id &device, const cl_context &context, + const cl_command_queue &queue, const cl_uint dims, const size_t *globalSize, const size_t *localSize, const size_t *buffersSize, + const size_t *globalWorkOffset, const size_t *reqdWorkGroupSize) + : _device(device), _context(context), _queue(queue), _dims (dims) { + + if (globalSize == NULL || dims < 1 || dims > 3) { + //throw std::invalid_argument("globalSize is NULL value."); + // This is method of informing that parameters are wrong. + // It would be checked by prepareDevice() function. + // This is used because of lack of exception support. + _globalSize[0] = 0; + return; + } + + cl_uint i; + _globalWorkOffset_IsNull = true; + _localSize_IsNull = true; + + setGlobalWorkgroupSize(globalSize); + setLocalWorkgroupSize(globalSize,localSize); + for (i = _dims; i < MAX_DIMS; i++) { + _globalSize[i] = 1; + } + + for (i = 0; i < MAX_DIMS; i++) { + _globalWorkOffset[i] = 0; + } + + if (globalWorkOffset) { + _globalWorkOffset_IsNull = false; + for (i = 0; i < _dims; i++) { + _globalWorkOffset[i] = globalWorkOffset[i]; + } + } + + for (i = 0; i < MAX_DIMS; i++) { + _enqueuedLocalSize[i] = 1; + } + + if (localSize) { + _localSize_IsNull = false; + for (i = 0; i < _dims; i++) { + _enqueuedLocalSize[i] = _localSize[i]; + } + } + + if (reqdWorkGroupSize) { + for (i = 0; i < _dims; i++) { + _reqdWorkGroupSize[i] = reqdWorkGroupSize[i]; + } + for (i = _dims; i < MAX_DIMS; i++) { + _reqdWorkGroupSize[i] = 1; + } + } else { + _reqdWorkGroupSize[0] = 0; + _reqdWorkGroupSize[1] = 0; + _reqdWorkGroupSize[2] = 0; + } + + _testRange = Range::ALL; + + _numOfGlobalWorkItems = _globalSize[0]*_globalSize[1]*_globalSize[2]; + + DataContainerAttrib temp = {{0, 0, 0}}; + + // array with results from each region + _resultsRegionArray.resize(NUMBER_OF_REGIONS, temp); + _referenceRegionArray.resize(NUMBER_OF_REGIONS, temp); + +} + +TestNonUniformWorkGroup::~TestNonUniformWorkGroup () { + if (_err.checkError()) { + _err.showStats(); + } +} + +void TestNonUniformWorkGroup::setLocalWorkgroupSize (const size_t *globalSize, const size_t *localSize) +{ + cl_uint i; + // Enforce localSize should not exceed globalSize + if (localSize) { + for (i = 0; i < _dims; i++) { + if ((globalSize[i] < localSize[i])) { + _localSize[i] = globalSize[i]; + }else{ + _localSize[i] = localSize[i]; + } + } + } +} + +void TestNonUniformWorkGroup::setGlobalWorkgroupSize (const size_t *globalSize) +{ + cl_uint i; + for (i = 0; i < _dims; i++) { + _globalSize[i] = globalSize[i]; + } +} + +void TestNonUniformWorkGroup::verifyData (DataContainerAttrib * reference, DataContainerAttrib * results, short regionNumber) { + + std::ostringstream tmp; + std::string errorLocation; + + if (_testRange & Range::BASIC) { + for (unsigned short i = 0; i < MAX_DIMS; i++) { + tmp.str(""); + tmp.clear(); + tmp << "region number: " << regionNumber << " for dim: " << i; + errorLocation = tmp.str(); + + if (results->get_global_size[i] != reference->get_global_size[i]) { + _err.show(Error::ERR_GLOBAL_SIZE, errorLocation, results->get_global_size[i], reference->get_global_size[i]); + } + + if (results->get_global_offset[i] != reference->get_global_offset[i]) { + _err.show(Error::ERR_GLOBAL_WORK_OFFSET, errorLocation, results->get_global_offset[i], reference->get_global_offset[i]); + } + + if (results->get_local_size[i] != reference->get_local_size[i] || results->get_local_size[i] > _maxWorkItemSizes[i]) { + _err.show(Error::ERR_LOCAL_SIZE, errorLocation, results->get_local_size[i], reference->get_local_size[i]); + } + + if (results->get_enqueued_local_size[i] != reference->get_enqueued_local_size[i] || results->get_enqueued_local_size[i] > _maxWorkItemSizes[i]) { + _err.show(Error::ERR_ENQUEUED_LOCAL_SIZE, errorLocation, results->get_enqueued_local_size[i], reference->get_enqueued_local_size[i]); + } + + if (results->get_num_groups[i] != reference->get_num_groups[i]) { + _err.show(Error::ERR_NUM_GROUPS, errorLocation, results->get_num_groups[i], reference->get_num_groups[i]); + } + } + } + + tmp.str(""); + tmp.clear(); + tmp << "region number: " << regionNumber; + errorLocation = tmp.str(); + if (_testRange & Range::BASIC) { + if (results->get_work_dim != reference->get_work_dim) { + _err.show(Error::ERR_WORK_DIM, errorLocation, results->get_work_dim, reference->get_work_dim); + } + } +} + +void TestNonUniformWorkGroup::calculateExpectedValues () { + size_t nonRemainderGlobalSize[MAX_DIMS]; + size_t numberOfPossibleRegions[MAX_DIMS]; + + nonRemainderGlobalSize[0] = _globalSize[0] - (_globalSize[0] % _enqueuedLocalSize[0]); + nonRemainderGlobalSize[1] = _globalSize[1] - (_globalSize[1] % _enqueuedLocalSize[1]); + nonRemainderGlobalSize[2] = _globalSize[2] - (_globalSize[2] % _enqueuedLocalSize[2]); + + numberOfPossibleRegions[0] = (_globalSize[0]>1)?2:1; + numberOfPossibleRegions[1] = (_globalSize[1]>1)?2:1; + numberOfPossibleRegions[2] = (_globalSize[2]>1)?2:1; + + for (cl_ushort i = 0; i < NUMBER_OF_REGIONS; ++i) { + + if (i & 0x01 && numberOfPossibleRegions[0] == 1) { + continue; + } + + if (i & 0x02 && numberOfPossibleRegions[1] == 1) { + continue; + } + + if (i & 0x04 && numberOfPossibleRegions[2] == 1) { + continue; + } + + for (cl_ushort dim = 0; dim < MAX_DIMS; ++dim) { + _referenceRegionArray[i].get_global_size[dim] = static_cast(_globalSize[dim]); + _referenceRegionArray[i].get_global_offset[dim] = static_cast(_globalWorkOffset[dim]); + _referenceRegionArray[i].get_enqueued_local_size[dim] = static_cast(_enqueuedLocalSize[dim]); + _referenceRegionArray[i].get_local_size[dim] = static_cast(_enqueuedLocalSize[dim]); + _referenceRegionArray[i].get_num_groups[dim] = static_cast(ceil(static_cast(_globalSize[dim]) / _enqueuedLocalSize[dim])); + } + _referenceRegionArray[i].get_work_dim = _dims; + + if (i & 0x01) { + _referenceRegionArray[i].get_local_size[0] = static_cast((_globalSize[0] - 1) % _enqueuedLocalSize[0] + 1); + } + + if (i & 0x02) { + _referenceRegionArray[i].get_local_size[1] = static_cast((_globalSize[1] - 1) % _enqueuedLocalSize[1] + 1); + } + + if (i & 0x04) { + _referenceRegionArray[i].get_local_size[2] = static_cast((_globalSize[2] - 1) % _enqueuedLocalSize[2] + 1); + } + } +} + +size_t TestNonUniformWorkGroup::getMaxLocalWorkgroupSize (const cl_device_id &device) { + int err; + + if (TestNonUniformWorkGroup::_maxLocalWorkgroupSize == 0) { + err = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, + sizeof(TestNonUniformWorkGroup::_maxLocalWorkgroupSize), &TestNonUniformWorkGroup::_maxLocalWorkgroupSize, NULL); + } + + return TestNonUniformWorkGroup::_maxLocalWorkgroupSize; +} + +void TestNonUniformWorkGroup::enableStrictMode(bool state) { + TestNonUniformWorkGroup::_strictMode = state; +} + +int TestNonUniformWorkGroup::prepareDevice () { + int err; + cl_uint device_max_dimensions; + + if (_globalSize[0] == 0) + { + log_error("Some arguments passed into constructor were wrong.\n"); + return -1; + } + + if(_localSize_IsNull == false) + calculateExpectedValues(); + + err = clGetDeviceInfo(_device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, + sizeof(device_max_dimensions), &device_max_dimensions, NULL); + test_error(err, "clGetDeviceInfo failed"); + + err = clGetDeviceInfo(_device, CL_DEVICE_MAX_WORK_ITEM_SIZES, + sizeof(_maxWorkItemSizes), _maxWorkItemSizes, NULL); + + test_error(err, "clGetDeviceInfo failed"); + + std::string buildOptions = BUILD_CL_STD_2_0; + if(_reqdWorkGroupSize[0] != 0 && _reqdWorkGroupSize[1] != 0 && _reqdWorkGroupSize[2] != 0) { + std::ostringstream tmp(" "); + tmp << " -D RWGSX=" << _reqdWorkGroupSize[0] + << " -D RWGSY=" << _reqdWorkGroupSize[1] + << " -D RWGSZ=" << _reqdWorkGroupSize[2] << " "; + buildOptions += tmp.str(); + } + + if (_testRange & Range::BASIC) + buildOptions += " -D TESTBASIC"; + if (_testRange & Range::ATOMICS) + buildOptions += " -D TESTATOMICS"; + if (_testRange & Range::BARRIERS) + buildOptions += " -D TESTBARRIERS"; + + err = create_single_kernel_helper_with_build_options (_context, &_program, &_testKernel, 1, + &KERNEL_FUNCTION, "testKernel", buildOptions.c_str()); + if (err) + { + log_error("Error %d in line: %d of file %s\n", err, __LINE__, __FILE__); + return -1; + } + + return 0; +} + +int TestNonUniformWorkGroup::verifyResults () { + if (_localSize_IsNull) { + // for global work groups where local work group size is not defined (set to NULL in clEnqueueNDRangeKernel) + // we need to check what optimal size was chosen by device + // we assumed that local size value for work item 0 is right for the rest work items + _enqueuedLocalSize[0] = static_cast(_resultsRegionArray[0].get_local_size[0]); + _enqueuedLocalSize[1] = static_cast(_resultsRegionArray[0].get_local_size[1]); + _enqueuedLocalSize[2] = static_cast(_resultsRegionArray[0].get_local_size[2]); + calculateExpectedValues(); + + // strict mode verification + if(_strictMode) { + size_t localWorkGroupSize = _enqueuedLocalSize[0]*_enqueuedLocalSize[1]*_enqueuedLocalSize[2]; + if (localWorkGroupSize != TestNonUniformWorkGroup::getMaxLocalWorkgroupSize(_device)) + _err.show(Error::ERR_STRICT_MODE, "",localWorkGroupSize, TestNonUniformWorkGroup::getMaxLocalWorkgroupSize(_device)); + } + + log_info ("Local work group size calculated by driver: %s\n", showArray(_enqueuedLocalSize, _dims).c_str()); + } + + for (cl_ushort i = 0; i < NUMBER_OF_REGIONS; ++i) { + verifyData(&_referenceRegionArray[i], &_resultsRegionArray[i], i); + } + + if (_testRange & Range::ATOMICS) { + if (_globalAtomicTestValue != _numOfGlobalWorkItems) { + _err.show(Error::ERR_GLOBAL_ATOMIC); + } + } + + if (_err.checkError()) + return -1; + + return 0; +} + +std::string showArray (const size_t *arr, cl_uint dims) { + std::ostringstream tmpStringStream (""); + + tmpStringStream << "{"; + for (cl_uint i=0; i < dims; i++) { + tmpStringStream << arr[i]; + if (i+1 < dims) + tmpStringStream << ", "; + } + tmpStringStream << "}"; + + return tmpStringStream.str(); +} + +void TestNonUniformWorkGroup::showTestInfo () { + std::string tmpString; + log_info ("T E S T P A R A M E T E R S :\n"); + log_info ("\tNumber of dimensions:\t%d\n", _dims); + + tmpString = showArray(_globalSize, _dims); + + log_info("\tGlobal work group size:\t%s\n", tmpString.c_str()); + + if (!_localSize_IsNull) { + tmpString = showArray(_enqueuedLocalSize, _dims); + } else { + tmpString = "NULL"; + } + log_info("\tLocal work group size:\t%s\n", tmpString.c_str()); + + if (!_globalWorkOffset_IsNull) { + tmpString = showArray(_globalWorkOffset, _dims); + } else { + tmpString = "NULL"; + } + log_info("\tGlobal work group offset:\t%s\n", tmpString.c_str()); + + if (_reqdWorkGroupSize[0] != 0 && _reqdWorkGroupSize[1] != 0 && _reqdWorkGroupSize[2] != 0) { + tmpString = showArray(_reqdWorkGroupSize, _dims); + } else { + tmpString = "attribute disabled"; + } + log_info ("\treqd_work_group_size attribute:\t%s\n", tmpString.c_str()); + + tmpString = ""; + if(_testRange & Range::BASIC) + tmpString += "basic"; + if(_testRange & Range::ATOMICS) { + if(tmpString != "") tmpString += ", "; + tmpString += "atomics"; + } + if(_testRange & Range::BARRIERS) { + if(tmpString != "") tmpString += ", "; + tmpString += "barriers"; + } + log_info ("\tTest range:\t%s\n", tmpString.c_str()); + if(_strictMode) { + log_info ("\tStrict mode:\tON\n"); + if (!_localSize_IsNull) { + log_info ("\tATTENTION: strict mode applies only NULL local work group size\n"); + } else { + log_info ("\t\tExpected value of local work group size is %ld.\n", + TestNonUniformWorkGroup::getMaxLocalWorkgroupSize(_device)); + } + + } +} + +int TestNonUniformWorkGroup::runKernel () { + int err; + + // TEST INFO + showTestInfo(); + + size_t localArraySize = (_localSize_IsNull)?TestNonUniformWorkGroup::getMaxLocalWorkgroupSize(_device):(_enqueuedLocalSize[0]*_enqueuedLocalSize[1]*_enqueuedLocalSize[2]); + clMemWrapper resultsRegionArray = clCreateBuffer(_context, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, _resultsRegionArray.size() * sizeof(DataContainerAttrib), &_resultsRegionArray.front(), &err); + test_error(err, "clCreateBuffer failed"); + + size_t *localSizePtr = (_localSize_IsNull)?NULL:_enqueuedLocalSize; + size_t *globalWorkOffsetPtr = (_globalWorkOffset_IsNull)?NULL:_globalWorkOffset; + + err = clSetKernelArg(_testKernel, 0, sizeof(resultsRegionArray), &resultsRegionArray); + test_error(err, "clSetKernelArg failed"); + + //creating local buffer + err = clSetKernelArg(_testKernel, 1, localArraySize*sizeof(unsigned int), NULL); + test_error(err, "clSetKernelArg failed"); + + clMemWrapper testGlobalArray = clCreateBuffer(_context, CL_MEM_READ_WRITE, _numOfGlobalWorkItems*sizeof(cl_uint), NULL, &err); + test_error(err, "clCreateBuffer failed"); + + err = clSetKernelArg(_testKernel, 2, sizeof(testGlobalArray), &testGlobalArray); + test_error(err, "clSetKernelArg failed"); + + _globalAtomicTestValue = 0; + clMemWrapper globalAtomicTestVariable = clCreateBuffer(_context, (CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR), sizeof(_globalAtomicTestValue), &_globalAtomicTestValue, &err); + test_error(err, "clCreateBuffer failed"); + + err = clSetKernelArg(_testKernel, 3, sizeof(globalAtomicTestVariable), &globalAtomicTestVariable); + test_error(err, "clSetKernelArg failed"); + + clMemWrapper errorArray = clCreateBuffer(_context, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, _err.errorArrayCounterSize(), _err.errorArrayCounter(), &err); + test_error(err, "clCreateBuffer failed"); + + err = clSetKernelArg(_testKernel, 4, sizeof(errorArray), &errorArray); + test_error(err, "clSetKernelArg failed"); + + err = clEnqueueNDRangeKernel(_queue, _testKernel, _dims, globalWorkOffsetPtr, _globalSize, + localSizePtr, 0, NULL, NULL); + test_error(err, "clEnqueueNDRangeKernel failed"); + + + err = clFinish(_queue); + test_error(err, "clFinish failed"); + + err = clEnqueueReadBuffer(_queue, globalAtomicTestVariable, CL_TRUE, 0, sizeof(unsigned int), &_globalAtomicTestValue, 0, NULL, NULL); + test_error(err, "clEnqueueReadBuffer failed"); + + if (_err.checkError()) { + return -1; + } + + // synchronization of main buffer + err = clEnqueueReadBuffer(_queue, resultsRegionArray, CL_TRUE, 0, _resultsRegionArray.size() * sizeof(DataContainerAttrib), &_resultsRegionArray.front(), 0, NULL, NULL); + test_error(err, "clEnqueueReadBuffer failed"); + + err = clEnqueueReadBuffer(_queue, errorArray, CL_TRUE, 0, _err.errorArrayCounterSize(), _err.errorArrayCounter(), 0, NULL, NULL); + test_error(err, "clEnqueueReadBuffer failed"); + // Synchronization of errors occurred in kernel into general error stats + _err.synchronizeStatsMap(); + + return 0; +} + +void SubTestExecutor::runTestNonUniformWorkGroup(const cl_uint dims, const size_t *globalSize, + const size_t *localSize, int range) { + runTestNonUniformWorkGroup (dims, globalSize, localSize, NULL, NULL, range); +} + +void SubTestExecutor::runTestNonUniformWorkGroup(const cl_uint dims, const size_t *globalSize, + const size_t *localSize, const size_t *globalWorkOffset, + const size_t *reqdWorkGroupSize, int range) { + + + int err; + ++_overallCounter; + TestNonUniformWorkGroup test (_device, _context, _queue, dims, globalSize, localSize, + NULL, globalWorkOffset, reqdWorkGroupSize); + + test.setTestRange(range); + err = test.prepareDevice(); + if (err) { + log_error ("Error: prepare device\n"); + ++_failCounter; + return; + } + + err = test.runKernel(); + if (err) { + log_error ("Error: run kernel\n"); + ++_failCounter; + return; + } + + err = test.verifyResults(); + if (err) { + log_error ("Error: verify results\n"); + ++_failCounter; + return; + } +} + +int SubTestExecutor::calculateWorkGroupSize(size_t &maxWgSize, int testRange) { + int err; + + clProgramWrapper program; + clKernelWrapper testKernel; + std::string buildOptions = BUILD_CL_STD_2_0; + + if (testRange & Range::BASIC) + buildOptions += " -D TESTBASIC"; + if (testRange & Range::ATOMICS) + buildOptions += " -D TESTATOMICS"; + if (testRange & Range::BARRIERS) + buildOptions += " -D TESTBARRIERS"; + + err = create_single_kernel_helper_with_build_options (_context, &program, &testKernel, 1, + &KERNEL_FUNCTION, "testKernel", buildOptions.c_str()); + if (err) + { + log_error("Error %d in line: %d of file %s\n", err, __LINE__, __FILE__); + return err; + } + + err = clGetKernelWorkGroupInfo (testKernel, _device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(maxWgSize), &maxWgSize, NULL); + test_error(err, "clGetKernelWorkGroupInfo failed"); + + TestNonUniformWorkGroup::setMaxLocalWorkgroupSize(maxWgSize); + + return 0; +} + +int SubTestExecutor::status() { + + if (_failCounter>0) { + log_error ("%d subtest(s) (of %d) failed\n", _failCounter, _overallCounter); + return -1; + } else { + log_info ("All %d subtest(s) passed\n", _overallCounter); + return 0; + } +} diff --git a/test_conformance/non_uniform_work_group/TestNonUniformWorkGroup.h b/test_conformance/non_uniform_work_group/TestNonUniformWorkGroup.h new file mode 100644 index 00000000..e7f261b5 --- /dev/null +++ b/test_conformance/non_uniform_work_group/TestNonUniformWorkGroup.h @@ -0,0 +1,146 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _TESTNONUNIFORMWORKGROUP_H +#define _TESTNONUNIFORMWORKGROUP_H + +#include "procs.h" +#include +#include "tools.h" +#include + +#define MAX_SIZE_OF_ALLOCATED_MEMORY (400*1024*1024) + +#define NUMBER_OF_REGIONS 8 + +#define BUILD_CL_STD_2_0 "-cl-std=CL2.0" + +#define MAX_DIMS 3 + +// This structure reflects data received from kernel. +typedef struct _DataContainerAttrib +{ + cl_ulong get_global_size[MAX_DIMS]; + cl_ulong get_global_offset[MAX_DIMS]; + cl_ulong get_local_size[MAX_DIMS]; + cl_ulong get_enqueued_local_size[MAX_DIMS]; + cl_ulong get_global_id[MAX_DIMS]; + cl_ulong get_local_id[MAX_DIMS]; + cl_ulong get_group_id[MAX_DIMS]; + cl_ulong get_num_groups[MAX_DIMS]; + cl_ulong get_work_dim; + cl_ushort test_local_barrier_result_bool; + cl_ushort test_global_barrier_result_bool; + cl_ushort test_local_atomic_result_value; +}DataContainerAttrib; + +// Describes range of testing. +namespace Range { + enum RangeEnum { + BASIC = (1 << 0), + BARRIERS = (1 << 1), + ATOMICS = (1 << 2), + + ALL = Range::BASIC | Range::BARRIERS | Range::ATOMICS + }; +} + +std::string showArray (const size_t *arr, cl_uint dims); + +// Main class responsible for testing +class TestNonUniformWorkGroup { +public: + + TestNonUniformWorkGroup (const cl_device_id &device, const cl_context &context, + const cl_command_queue &queue, const cl_uint dims, const size_t *globalSize, + const size_t *localSize, const size_t *buffersSize, const size_t *globalWorkOffset, + const size_t *reqdWorkGroupSize=NULL); + + ~TestNonUniformWorkGroup (); + + static size_t getMaxLocalWorkgroupSize (const cl_device_id &device); + static void setMaxLocalWorkgroupSize (size_t workGroupSize) { + TestNonUniformWorkGroup::_maxLocalWorkgroupSize = workGroupSize; + } + static void enableStrictMode (bool state); + + void setTestRange (int range) {_testRange = range;} + int prepareDevice (); + int verifyResults (); + int runKernel (); + +private: + size_t _globalSize[MAX_DIMS]; + size_t _localSize[MAX_DIMS]; + size_t _globalWorkOffset[MAX_DIMS]; + bool _globalWorkOffset_IsNull; + size_t _enqueuedLocalSize[MAX_DIMS]; + bool _localSize_IsNull; + size_t _reqdWorkGroupSize[MAX_DIMS]; + static size_t _maxLocalWorkgroupSize; + size_t _maxWorkItemSizes[MAX_DIMS]; + size_t _numOfGlobalWorkItems; // in global work group + const cl_device_id _device; + const cl_context _context; + const cl_command_queue _queue; + const cl_uint _dims; + + int _testRange; + + std::vector _resultsRegionArray; + std::vector _referenceRegionArray; + cl_uint _globalAtomicTestValue; + + clProgramWrapper _program; + clKernelWrapper _testKernel; + + Error::ErrorClass _err; + + TestNonUniformWorkGroup (); + + static bool _strictMode; + void setLocalWorkgroupSize (const size_t *globalSize, const size_t *localSize); + void setGlobalWorkgroupSize (const size_t *globalSize); + void verifyData (DataContainerAttrib * reference, DataContainerAttrib * results, short regionNumber); + void calculateExpectedValues (); + void showTestInfo (); +}; + +// Class responsible for running subtest scenarios in test function +class SubTestExecutor { +public: + SubTestExecutor(const cl_device_id &device, const cl_context &context, const cl_command_queue &queue) + : _device (device), _context (context), _queue (queue), _failCounter (0), _overallCounter (0) {} + + void runTestNonUniformWorkGroup (const cl_uint dims, const size_t *globalSize, + const size_t *localSize, int range); + + void runTestNonUniformWorkGroup (const cl_uint dims, const size_t *globalSize, + const size_t *localSize, const size_t *globalWorkOffset, + const size_t *reqdWorkGroupSize, int range); + + int calculateWorkGroupSize(size_t &maxWgSize, int testRange); + int status(); + +private: + SubTestExecutor(); + const cl_device_id _device; + const cl_context _context; + const cl_command_queue _queue; + unsigned int _failCounter; + unsigned int _overallCounter; +}; + +#endif // _TESTNONUNIFORMWORKGROUP_H diff --git a/test_conformance/non_uniform_work_group/main.cpp b/test_conformance/non_uniform_work_group/main.cpp new file mode 100644 index 00000000..66218ef1 --- /dev/null +++ b/test_conformance/non_uniform_work_group/main.cpp @@ -0,0 +1,88 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "procs.h" +#include "tools.h" +#include "../../test_common/harness/testHarness.h" +#include "TestNonUniformWorkGroup.h" + +basefn basefn_list[] = { + test_non_uniform_1d_basic, + test_non_uniform_1d_atomics, + test_non_uniform_1d_barriers, + + test_non_uniform_2d_basic, + test_non_uniform_2d_atomics, + test_non_uniform_2d_barriers, + + test_non_uniform_3d_basic, + test_non_uniform_3d_atomics, + test_non_uniform_3d_barriers, + + test_non_uniform_other_basic, + test_non_uniform_other_atomics, + test_non_uniform_other_barriers +}; + +const char *basefn_names[] = { + "non_uniform_1d_basic", + "non_uniform_1d_atomics", + "non_uniform_1d_barriers", + + "non_uniform_2d_basic", + "non_uniform_2d_atomics", + "non_uniform_2d_barriers", + + "non_uniform_3d_basic", + "non_uniform_3d_atomics", + "non_uniform_3d_barriers", + + "non_uniform_other_basic", + "non_uniform_other_atomics", + "non_uniform_other_barriers", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + +int main(int argc, const char *argv[]) +{ + typedef std::vector ArgsVector; + ArgsVector programArgs; + programArgs.assign(argv, argv+argc); + + int numFns = num_fns; + basefn *baseFnList = basefn_list; + const char **baseFnNames = basefn_names; + + for (ArgsVector::iterator it = programArgs.begin(); it!=programArgs.end();) { + + if(*it == std::string("-strict")) { + TestNonUniformWorkGroup::enableStrictMode(true); + it=programArgs.erase(it); + } else { + ++it; + } + } + + PrimeNumbers::generatePrimeNumbers(100000); + + return runTestHarness(static_cast(programArgs.size()), &programArgs.front(), numFns, baseFnList, baseFnNames, false /* image support required */, false /* force no context creation */, 0 ); +} + + + + diff --git a/test_conformance/non_uniform_work_group/procs.h b/test_conformance/non_uniform_work_group/procs.h new file mode 100644 index 00000000..199bb836 --- /dev/null +++ b/test_conformance/non_uniform_work_group/procs.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/typeWrappers.h" + +extern int test_non_uniform_1d_basic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_non_uniform_1d_atomics(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_non_uniform_1d_barriers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_non_uniform_2d_basic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_non_uniform_2d_atomics(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_non_uniform_2d_barriers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_non_uniform_3d_basic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_non_uniform_3d_atomics(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_non_uniform_3d_barriers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_non_uniform_other_basic(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_non_uniform_other_atomics(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_non_uniform_other_barriers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); diff --git a/test_conformance/non_uniform_work_group/test_advanced_2d.cpp b/test_conformance/non_uniform_work_group/test_advanced_2d.cpp new file mode 100644 index 00000000..3ed1082d --- /dev/null +++ b/test_conformance/non_uniform_work_group/test_advanced_2d.cpp @@ -0,0 +1,383 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "procs.h" +#include "tools.h" + +#include "TestNonUniformWorkGroup.h" + +int + test_non_uniform_2d_basic(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + SubTestExecutor exec(device, context, queue); + + size_t maxWgSize; + int err; + err = exec.calculateWorkGroupSize(maxWgSize, Range::BASIC); + if (err) { + log_error ("Cannot calculate work group size."); + return -1; + } + + // non_uniform_2d_max_wg_size_plus_1_basic + { + size_t globalSize[] = {maxWgSize+1, maxWgSize}; + size_t localSize[] = {maxWgSize, 1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_2d_prime_number_basic + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + size_t globalSize[] = {primeNumber, maxWgSize}; + size_t localSize[] = {maxWgSize/2, 2}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_2d_two_prime_numbers_basic + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + int primeNumber2 = 1759; + size_t globalSize[] = {primeNumber2, primeNumber}; + size_t localSize[] = {16, maxWgSize/16}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_2d_prime_number_basic_2 + { + int primeNumber = 1327; + size_t globalSize[] = {primeNumber, primeNumber}; + size_t localSize[] = {maxWgSize/32, 32}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_2d_combination_of_max_wg_size_basic + { + size_t globalSize[] = {maxWgSize + 2, maxWgSize + 4}; + size_t localSize[] = {maxWgSize/32, 32}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_2d_two_prime_numbers_and_ls_null_basic + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + unsigned int primeNumber2 = 1669; + size_t globalSize[] = {primeNumber, primeNumber2}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_2d_prime_number_and_ls_null_basic + { + unsigned int primeNumber = 1249; + size_t globalSize[] = {primeNumber, primeNumber}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_2d_four_prime_numbers_basic + { + unsigned int primeNumber = 1951; + unsigned int primeNumber2 = 911; + unsigned int primeNumber3 = 13; + unsigned int primeNumber4 = 17; + + PrimeNumbers::Result2d fit2dResult; + fit2dResult = PrimeNumbers::fitMaxPrime2d(primeNumber3, primeNumber4, maxWgSize); + + size_t globalSize[] = {primeNumber, primeNumber2}; + size_t localSize[] = {fit2dResult.Val1, fit2dResult.Val2}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_2d_three_prime_numbers_basic + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize/2, maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + unsigned int primeNumber2 = 42967; + unsigned int primeNumber3 = 13; + size_t globalSize[] = {primeNumber2, primeNumber3}; + size_t localSize[] = {primeNumber, 1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + return exec.status(); +} + +int + test_non_uniform_2d_atomics(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + SubTestExecutor exec(device, context, queue); + + size_t maxWgSize; + int err; + err = exec.calculateWorkGroupSize(maxWgSize, Range::ATOMICS); + if (err) { + log_error ("Cannot calculate work group size."); + return -1; + } + + // non_uniform_2d_max_wg_size_plus_1_atomics + { + size_t globalSize[] = {maxWgSize+1, maxWgSize}; + size_t localSize[] = {maxWgSize, 1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_2d_prime_number_atomics + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + size_t globalSize[] = {primeNumber, maxWgSize}; + size_t localSize[] = {maxWgSize/2, 2}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_2d_two_prime_numbers_atomics + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + int primeNumber2 = 1759; + size_t globalSize[] = {primeNumber2, primeNumber}; + size_t localSize[] = {16, maxWgSize/16}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_2d_prime_number_atomics_2 + { + int primeNumber = 1327; + size_t globalSize[] = {primeNumber, primeNumber}; + size_t localSize[] = {maxWgSize/32, 32}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_2d_combination_of_max_wg_size_atomics + { + size_t globalSize[] = {maxWgSize + 2, maxWgSize + 4}; + size_t localSize[] = {maxWgSize/32, 32}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_2d_two_prime_numbers_and_ls_null_atomics + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + unsigned int primeNumber2 = 1669; + size_t globalSize[] = {primeNumber, primeNumber2}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_2d_prime_number_and_ls_null_atomics + { + unsigned int primeNumber = 1249; + size_t globalSize[] = {primeNumber, primeNumber}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_2d_four_prime_numbers_atomics + { + unsigned int primeNumber = 1951; + unsigned int primeNumber2 = 911; + unsigned int primeNumber3 = 13; + unsigned int primeNumber4 = 17; + + PrimeNumbers::Result2d fit2dResult; + fit2dResult = PrimeNumbers::fitMaxPrime2d(primeNumber3, primeNumber4, maxWgSize); + + size_t globalSize[] = {primeNumber, primeNumber2}; + size_t localSize[] = {fit2dResult.Val1, fit2dResult.Val2}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_2d_three_prime_numbers_atomics + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize/2, maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + unsigned int primeNumber2 = 42967; + unsigned int primeNumber3 = 13; + size_t globalSize[] = {primeNumber2, primeNumber3}; + size_t localSize[] = {primeNumber, 1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + return exec.status(); +} + +int + test_non_uniform_2d_barriers(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + SubTestExecutor exec(device, context, queue); + + size_t maxWgSize; + int err; + err = exec.calculateWorkGroupSize(maxWgSize, Range::BARRIERS); + if (err) { + log_error ("Cannot calculate work group size."); + return -1; + } + + // non_uniform_2d_max_wg_size_plus_1_barriers + { + size_t globalSize[] = {maxWgSize+1, maxWgSize}; + size_t localSize[] = {maxWgSize, 1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_2d_prime_number_barriers + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + size_t globalSize[] = {primeNumber, maxWgSize}; + size_t localSize[] = {maxWgSize/2, 2}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_2d_two_prime_numbers_barriers + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + int primeNumber2 = 1759; + size_t globalSize[] = {primeNumber2, primeNumber}; + size_t localSize[] = {16, maxWgSize/16}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_2d_prime_number_barriers_2 + { + int primeNumber = 1327; + size_t globalSize[] = {primeNumber, primeNumber}; + size_t localSize[] = {maxWgSize/32, 32}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_2d_combination_of_max_wg_size_barriers + { + size_t globalSize[] = {maxWgSize + 2, maxWgSize + 4}; + size_t localSize[] = {maxWgSize/32, 32}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_2d_two_prime_numbers_and_ls_null_barriers + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + unsigned int primeNumber2 = 1669; + size_t globalSize[] = {primeNumber, primeNumber2}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_2d_prime_number_and_ls_null_barriers + { + unsigned int primeNumber = 1249; + size_t globalSize[] = {primeNumber, primeNumber}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_2d_four_prime_numbers_barriers + { + unsigned int primeNumber = 1951; + unsigned int primeNumber2 = 911; + unsigned int primeNumber3 = 13; + unsigned int primeNumber4 = 17; + PrimeNumbers::Result2d fit2dResult; + fit2dResult = PrimeNumbers::fitMaxPrime2d(primeNumber3, primeNumber4, maxWgSize); + size_t globalSize[] = {primeNumber, primeNumber2}; + size_t localSize[] = {fit2dResult.Val1, fit2dResult.Val2}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_2d_three_prime_numbers_barriers + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize/2, maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + unsigned int primeNumber2 = 42967; + unsigned int primeNumber3 = 13; + size_t globalSize[] = {primeNumber2, primeNumber3}; + size_t localSize[] = {primeNumber, 1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + return exec.status(); +} diff --git a/test_conformance/non_uniform_work_group/test_advanced_3d.cpp b/test_conformance/non_uniform_work_group/test_advanced_3d.cpp new file mode 100644 index 00000000..1e205525 --- /dev/null +++ b/test_conformance/non_uniform_work_group/test_advanced_3d.cpp @@ -0,0 +1,410 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "procs.h" +#include "tools.h" + +#include "TestNonUniformWorkGroup.h" + +int + test_non_uniform_3d_basic(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + SubTestExecutor exec(device, context, queue); + + size_t maxWgSize; + int err; + err = exec.calculateWorkGroupSize(maxWgSize, Range::BASIC); + if (err) { + log_error ("Cannot calculate work group size."); + return -1; + } + + // non_uniform_3d_max_wg_size_plus_1_basic + { + size_t globalSize[] = {maxWgSize+1, maxWgSize/24, maxWgSize/24}; + size_t localSize[] = {maxWgSize, 1, 1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_3d_prime_number_basic + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + size_t globalSize[] = {maxWgSize/25, primeNumber, maxWgSize/25}; + size_t localSize[] = {2, std::max(maxWgSize/4,1), 2}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_3d_two_prime_numbers_basic + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + int primeNumber2 = 13; + size_t globalSize[] = {primeNumber2, maxWgSize/8, primeNumber}; + size_t localSize[] = {8, 4, std::max(maxWgSize/32,1)}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_3d_prime_number_basic_2 + { + int primeNumber = 113; + size_t globalSize[] = {primeNumber, primeNumber, primeNumber}; + size_t localSize[] = {8, std::max(maxWgSize/32,1), 4}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_3d_two_prime_numbers_and_ls_null_basic + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + unsigned int primeNumber2 = 23; + size_t globalSize[] = {primeNumber, primeNumber2, maxWgSize/16}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_3d_prime_number_and_ls_null_basic + { + unsigned int primeNumber = 113; + size_t globalSize[] = {primeNumber, primeNumber, primeNumber}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_3d_three_prime_numbers_basic + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize/2, maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + unsigned int primeNumber2 = 10711; + unsigned int primeNumber3 = 13; + size_t globalSize[] = {primeNumber2, primeNumber3, primeNumber3}; + size_t localSize[] = {primeNumber, 1, 1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_3d_four_prime_numbers_basic + { + unsigned int primeNumber = 541; + unsigned int primeNumber2 = 251; + unsigned int primeNumber3 = 13; + unsigned int primeNumber4 = 17; + PrimeNumbers::Result2d fit2dResult; + fit2dResult = PrimeNumbers::fitMaxPrime2d(primeNumber3, primeNumber4, maxWgSize); + + size_t globalSize[] = {primeNumber, primeNumber2, primeNumber3}; + size_t localSize[] = {fit2dResult.Val1, fit2dResult.Val2, 1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_3d_six_prime_numbers_basic + { + unsigned int primeNumber = 373; + unsigned int primeNumber2 = 13; + unsigned int primeNumber3 = 279; + unsigned int primeNumber4 = 3; + unsigned int primeNumber5 = 5; + unsigned int primeNumber6 = 7; + PrimeNumbers::Result3d fit3dResult; + fit3dResult = PrimeNumbers::fitMaxPrime3d(primeNumber4,primeNumber5,primeNumber6,maxWgSize ); + + size_t globalSize[] = {primeNumber, primeNumber2, primeNumber3}; + size_t localSize[] = {fit3dResult.Val1, fit3dResult.Val2, fit3dResult.Val3}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + return exec.status(); +} + +int + test_non_uniform_3d_atomics(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + SubTestExecutor exec(device, context, queue); + + size_t maxWgSize; + int err; + err = exec.calculateWorkGroupSize(maxWgSize, Range::ATOMICS); + if (err) { + log_error ("Cannot calculate work group size."); + return -1; + } + + // non_uniform_3d_max_wg_size_plus_1_atomics + { + size_t globalSize[] = {maxWgSize+1, maxWgSize/24, maxWgSize/24}; + size_t localSize[] = {maxWgSize, 1, 1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_3d_prime_number_atomics + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + size_t globalSize[] = {maxWgSize/25, primeNumber, maxWgSize/25}; + size_t localSize[] = {2, std::max(maxWgSize/4,1), 2}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_3d_two_prime_numbers_atomics + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + int primeNumber2 = 13; + size_t globalSize[] = {primeNumber2, maxWgSize/8, primeNumber}; + size_t localSize[] = {8, 4, std::max(maxWgSize/32,1)}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_3d_prime_number_atomics_2 + { + int primeNumber = 113; + size_t globalSize[] = {primeNumber, primeNumber, primeNumber}; + size_t localSize[] = {8, std::max(maxWgSize/32,1), 4}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_3d_two_prime_numbers_and_ls_null_atomics + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + unsigned int primeNumber2 = 23; + size_t globalSize[] = {primeNumber, primeNumber2, maxWgSize/16}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_3d_prime_number_and_ls_null_atomics + { + unsigned int primeNumber = 113; + size_t globalSize[] = {primeNumber, primeNumber, primeNumber}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_3d_three_prime_numbers_atomics + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize/2, maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + unsigned int primeNumber2 = 10711; + unsigned int primeNumber3 = 13; + size_t globalSize[] = {primeNumber2, primeNumber3, primeNumber3}; + size_t localSize[] = {primeNumber, 1, 1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_3d_four_prime_numbers_atomics + { + unsigned int primeNumber = 541; + unsigned int primeNumber2 = 251; + unsigned int primeNumber3 = 13; + unsigned int primeNumber4 = 17; + PrimeNumbers::Result2d fit2dResult; + fit2dResult = PrimeNumbers::fitMaxPrime2d(primeNumber3, primeNumber4, maxWgSize); + + size_t globalSize[] = {primeNumber, primeNumber2, primeNumber3}; + size_t localSize[] = {fit2dResult.Val1, fit2dResult.Val2, 1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_3d_six_prime_numbers_atomics + { + unsigned int primeNumber = 373; + unsigned int primeNumber2 = 13; + unsigned int primeNumber3 = 279; + unsigned int primeNumber4 = 3; + unsigned int primeNumber5 = 5; + unsigned int primeNumber6 = 7; + PrimeNumbers::Result3d fit3dResult; + fit3dResult = PrimeNumbers::fitMaxPrime3d(primeNumber4, primeNumber5, primeNumber6, maxWgSize); + + size_t globalSize[] = {primeNumber, primeNumber2, primeNumber3}; + size_t localSize[] = {fit3dResult.Val1, fit3dResult.Val2, fit3dResult.Val3}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + return exec.status(); +} + +int + test_non_uniform_3d_barriers(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + SubTestExecutor exec(device, context, queue); + + size_t maxWgSize; + int err; + err = exec.calculateWorkGroupSize(maxWgSize, Range::BARRIERS); + if (err) { + log_error ("Cannot calculate work group size."); + return -1; + } + + // non_uniform_3d_max_wg_size_plus_1_barriers + { + size_t globalSize[] = {maxWgSize+1, maxWgSize/24, maxWgSize/24}; + size_t localSize[] = {maxWgSize, 1, 1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_3d_prime_number_barriers + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + size_t globalSize[] = {maxWgSize/25, primeNumber, maxWgSize/25}; + size_t localSize[] = {2, std::max(maxWgSize/4,1), 2}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_3d_two_prime_numbers_barriers + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + int primeNumber2 = 13; + size_t globalSize[] = {primeNumber2, maxWgSize/8, primeNumber}; + size_t localSize[] = {8, 4, std::max(maxWgSize/32,1)}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_3d_prime_number_barriers_2 + { + int primeNumber = 113; + size_t globalSize[] = {primeNumber, primeNumber, primeNumber}; + size_t localSize[] = {8, std::max(maxWgSize/32,1), 4}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_3d_two_prime_numbers_and_ls_null_barriers + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + unsigned int primeNumber2 = 23; + size_t globalSize[] = {primeNumber, primeNumber2, maxWgSize/16}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_3d_prime_number_and_ls_null_barriers + { + unsigned int primeNumber = 113; + size_t globalSize[] = {primeNumber, primeNumber, primeNumber}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_3d_three_prime_numbers_barriers + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize/2, maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + unsigned int primeNumber2 = 10711; + unsigned int primeNumber3 = 13; + size_t globalSize[] = {primeNumber2, primeNumber3, primeNumber3}; + size_t localSize[] = {primeNumber, 1, 1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_3d_four_prime_numbers_barriers + { + unsigned int primeNumber = 541; + unsigned int primeNumber2 = 251; + unsigned int primeNumber3 = 13; + unsigned int primeNumber4 = 17; + PrimeNumbers::Result2d fit2dResult; + fit2dResult = PrimeNumbers::fitMaxPrime2d(primeNumber3, primeNumber4, maxWgSize); + + size_t globalSize[] = {primeNumber, primeNumber2, primeNumber3}; + size_t localSize[] = {fit2dResult.Val1, fit2dResult.Val2, 1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + + // non_uniform_3d_six_prime_numbers_barriers + { + unsigned int primeNumber = 373; + unsigned int primeNumber2 = 13; + unsigned int primeNumber3 = 279; + unsigned int primeNumber4 = 3; + unsigned int primeNumber5 = 5; + unsigned int primeNumber6 = 7; + PrimeNumbers::Result3d fit3dResult; + fit3dResult = PrimeNumbers::fitMaxPrime3d(primeNumber4,primeNumber5,primeNumber6,maxWgSize ); + + size_t globalSize[] = {primeNumber, primeNumber2, primeNumber3}; + size_t localSize[] = {fit3dResult.Val1, fit3dResult.Val2, fit3dResult.Val3}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + return exec.status(); +} diff --git a/test_conformance/non_uniform_work_group/test_advanced_other.cpp b/test_conformance/non_uniform_work_group/test_advanced_other.cpp new file mode 100644 index 00000000..6aed795c --- /dev/null +++ b/test_conformance/non_uniform_work_group/test_advanced_other.cpp @@ -0,0 +1,279 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "procs.h" +#include "tools.h" + +#include "TestNonUniformWorkGroup.h" + +int + test_non_uniform_other_basic(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + SubTestExecutor exec(device, context, queue); + + size_t maxWgSize; + int err; + err = exec.calculateWorkGroupSize(maxWgSize, Range::BASIC); + if (err) { + log_error ("Cannot calculate work group size."); + return -1; + } + + // non_uniform_1d_two_prime_numbers_offset_basic + { + unsigned int primeNumber = 42967; + unsigned int primeNumber2 = 113; + PrimeNumbers::Result1d fit1dResult; + + fit1dResult = PrimeNumbers::fitMaxPrime1d(primeNumber2, maxWgSize ); + + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {fit1dResult.Val1}; + size_t offset[] = {23}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, offset, NULL, Range::BASIC); + } + + // non_uniform_2d_three_prime_numbers_offset_basic + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize/2, maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + unsigned int primeNumber2 = 42967; + unsigned int primeNumber3 = 13; + size_t globalSize[] = {primeNumber2, primeNumber3}; + size_t localSize[] = {primeNumber, 1}; + size_t offset[] = {23, 17}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, offset, NULL, Range::BASIC); + } + + // non_uniform_3d_six_prime_numbers_offset_basic + { + unsigned int primeNumber = 373; + unsigned int primeNumber2 = 13; + unsigned int primeNumber3 = 279; + unsigned int primeNumber4 = 3; + unsigned int primeNumber5 = 5; + unsigned int primeNumber6 = 7; + + PrimeNumbers::Result3d fit3dResult; + + size_t globalSize[] = {primeNumber, primeNumber2, primeNumber3}; + + fit3dResult = PrimeNumbers::fitMaxPrime3d(primeNumber4, primeNumber5, primeNumber6, maxWgSize ); + + size_t localSize[] = {fit3dResult.Val1, fit3dResult.Val2, fit3dResult.Val3}; + size_t offset[] = {11, 23, 17}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, offset, NULL, Range::BASIC); + } + + // non_uniform_3d_six_prime_numbers_rwgs_basic + { + unsigned int primeNumber = 373; + unsigned int primeNumber2 = 13; + unsigned int primeNumber3 = 279; + unsigned int primeNumber4 = 3; + unsigned int primeNumber5 = 5; + unsigned int primeNumber6 = 7; + PrimeNumbers::Result3d fit3dResult; + + fit3dResult = PrimeNumbers::fitMaxPrime3d(primeNumber4, primeNumber5, primeNumber6, maxWgSize ); + + size_t globalSize[] = {primeNumber, primeNumber2, primeNumber3}; + size_t localSize[] = {fit3dResult.Val1, fit3dResult.Val2, fit3dResult.Val3}; + size_t reqdWorkGroupSize[] = {fit3dResult.Val1, fit3dResult.Val2, fit3dResult.Val3}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, NULL, reqdWorkGroupSize, Range::BASIC); + } + + return exec.status(); +} + +int + test_non_uniform_other_atomics(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + SubTestExecutor exec(device, context, queue); + + size_t maxWgSize; + int err; + err = exec.calculateWorkGroupSize(maxWgSize, Range::ATOMICS); + if (err) { + log_error ("Cannot calculate work group size."); + return -1; + } + + // non_uniform_1d_two_prime_numbers_offset_atomics + { + unsigned int primeNumber = 42967; + unsigned int primeNumber2 = 113; + PrimeNumbers::Result1d fit1dResult; + + fit1dResult = PrimeNumbers::fitMaxPrime1d(primeNumber2, maxWgSize ); + + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {fit1dResult.Val1}; + size_t offset[] = {23}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, offset, NULL, Range::ATOMICS); + } + + // non_uniform_2d_three_prime_numbers_offset_atomics + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize/2, maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + unsigned int primeNumber2 = 42967; + unsigned int primeNumber3 = 13; + size_t globalSize[] = {primeNumber2, primeNumber3}; + size_t localSize[] = {primeNumber, 1}; + size_t offset[] = {23, 17}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, offset, NULL, Range::ATOMICS); + } + + // non_uniform_3d_six_prime_numbers_offset_atomics + { + unsigned int primeNumber = 373; + unsigned int primeNumber2 = 13; + unsigned int primeNumber3 = 279; + unsigned int primeNumber4 = 3; + unsigned int primeNumber5 = 5; + unsigned int primeNumber6 = 7; + PrimeNumbers::Result3d fit3dResult; + + fit3dResult = PrimeNumbers::fitMaxPrime3d(primeNumber4, primeNumber5, primeNumber6, maxWgSize ); + + size_t globalSize[] = {primeNumber, primeNumber2, primeNumber3}; + size_t localSize[] = {fit3dResult.Val1, fit3dResult.Val2, fit3dResult.Val3}; + size_t offset[] = {11, 23, 17}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, offset, NULL, Range::ATOMICS); + } + + // non_uniform_3d_six_prime_numbers_rwgs_atomics + { + unsigned int primeNumber = 373; + unsigned int primeNumber2 = 13; + unsigned int primeNumber3 = 279; + unsigned int primeNumber4 = 3; + unsigned int primeNumber5 = 5; + unsigned int primeNumber6 = 7; + PrimeNumbers::Result3d fit3dResult; + + fit3dResult = PrimeNumbers::fitMaxPrime3d(primeNumber4, primeNumber5, primeNumber6, maxWgSize ); + + size_t globalSize[] = {primeNumber, primeNumber2, primeNumber3}; + size_t localSize[] = {fit3dResult.Val1, fit3dResult.Val2, fit3dResult.Val3}; + size_t reqdWorkGroupSize[] = {fit3dResult.Val1, fit3dResult.Val2, fit3dResult.Val3}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, NULL, reqdWorkGroupSize, Range::ATOMICS); + } + + return exec.status(); +} + +int + test_non_uniform_other_barriers(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + SubTestExecutor exec(device, context, queue); + + size_t maxWgSize; + int err; + err = exec.calculateWorkGroupSize(maxWgSize, Range::BARRIERS); + if (err) { + log_error ("Cannot calculate work group size."); + return -1; + } + + // non_uniform_1d_two_prime_numbers_offset_barriers + { + unsigned int primeNumber = 42967; + unsigned int primeNumber2 = 113; + PrimeNumbers::Result1d fit1dResult; + + fit1dResult = PrimeNumbers::fitMaxPrime1d(primeNumber2, maxWgSize ); + + size_t globalSize[] = {primeNumber}; + + size_t localSize[] = {fit1dResult.Val1}; + size_t offset[] = {23}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, offset, NULL, Range::BARRIERS); + } + + // non_uniform_2d_three_prime_numbers_offset_barriers + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize/2, maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + unsigned int primeNumber2 = 42967; + unsigned int primeNumber3 = 13; + size_t globalSize[] = {primeNumber2, primeNumber3}; + size_t localSize[] = {primeNumber, 1}; + size_t offset[] = {23, 17}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, offset, NULL, Range::BARRIERS); + } + + // non_uniform_3d_six_prime_numbers_offset_barriers + { + unsigned int primeNumber = 373; + unsigned int primeNumber2 = 13; + unsigned int primeNumber3 = 279; + unsigned int primeNumber4 = 3; + unsigned int primeNumber5 = 5; + unsigned int primeNumber6 = 7; + PrimeNumbers::Result3d fit3dResult; + + fit3dResult = PrimeNumbers::fitMaxPrime3d(primeNumber4, primeNumber5, primeNumber6, maxWgSize ); + + size_t globalSize[] = {primeNumber, primeNumber2, primeNumber3}; + + size_t localSize[] = {fit3dResult.Val1, fit3dResult.Val2, fit3dResult.Val3}; + size_t offset[] = {11, 23, 17}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, offset, NULL, Range::BARRIERS); + } + + // non_uniform_3d_six_prime_numbers_rwgs_barriers + { + unsigned int primeNumber = 373; + unsigned int primeNumber2 = 13; + unsigned int primeNumber3 = 279; + unsigned int primeNumber4 = 3; + unsigned int primeNumber5 = 5; + unsigned int primeNumber6 = 7; + PrimeNumbers::Result3d fit3dResult; + + fit3dResult = PrimeNumbers::fitMaxPrime3d(primeNumber4, primeNumber5, primeNumber6, maxWgSize ); + + size_t globalSize[] = {primeNumber, primeNumber2, primeNumber3}; + + size_t localSize[] = {fit3dResult.Val1, fit3dResult.Val2, fit3dResult.Val3}; + size_t reqdWorkGroupSize[] = {fit3dResult.Val1, fit3dResult.Val2, fit3dResult.Val3}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, NULL, reqdWorkGroupSize, Range::BARRIERS); + } + + return exec.status(); +} diff --git a/test_conformance/non_uniform_work_group/test_basic.cpp b/test_conformance/non_uniform_work_group/test_basic.cpp new file mode 100644 index 00000000..2bf410bc --- /dev/null +++ b/test_conformance/non_uniform_work_group/test_basic.cpp @@ -0,0 +1,398 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "procs.h" +#include "tools.h" + +#include "TestNonUniformWorkGroup.h" + +int + test_non_uniform_1d_basic(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + SubTestExecutor exec(device, context, queue); + + size_t maxWgSize; + int err; + err = exec.calculateWorkGroupSize(maxWgSize, Range::BASIC); + if (err) { + log_error ("Cannot calculate work group size."); + return -1; + } + + // non_uniform_1d_max_wg_size_plus_1_basic + { + size_t globalSize[] = {maxWgSize+1}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_1d_prime_number_basic + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_1d_max_wg_size_plus_prime_number_basic + { + int primeNumber = 11; + size_t globalSize[] = {maxWgSize+primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_1d_max_wg_size_plus_prime_number_basic_2 + { + int primeNumber = 53; + size_t globalSize[] = {maxWgSize+primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_1d_2max_wg_size_minus_1_basic + { + size_t globalSize[] = {2*maxWgSize - 1}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_1d_prime_number_basic_2 + { + unsigned int primeNumber = 20101; + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_1d_prime_number_basic_3 + { + unsigned int primeNumber = 42967; + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_1d_prime_number_basic_4 + { + unsigned int primeNumber = 65521; + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_1d_prime_number_and_ls_null_basic_2 + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + size_t globalSize[] = {primeNumber}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_1d_prime_number_and_ls_null_basic_3 + { + unsigned int primeNumber = 65521; + size_t globalSize[] = {primeNumber}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + // non_uniform_1d_two_prime_numbers_basic + { + unsigned int primeNumber = 42967; + unsigned int primeNumber2 = 113; + PrimeNumbers::Result1d fit1dResult; + + fit1dResult = PrimeNumbers::fitMaxPrime1d(primeNumber2, maxWgSize ); + + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {fit1dResult.Val1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BASIC); + } + + return exec.status(); +} + +int + test_non_uniform_1d_atomics(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + SubTestExecutor exec(device, context, queue); + + size_t maxWgSize; + int err; + err = exec.calculateWorkGroupSize(maxWgSize, Range::ATOMICS); + if (err) { + log_error ("Cannot calculate work group size."); + return -1; + } + + // non_uniform_1d_max_wg_size_plus_1_atomics + { + size_t globalSize[] = {maxWgSize+1}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_1d_prime_number_atomics + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_1d_max_wg_size_plus_prime_number_atomics + { + int primeNumber = 11; + size_t globalSize[] = {maxWgSize+primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_1d_max_wg_size_plus_prime_number_atomics_2 + { + int primeNumber = 53; + size_t globalSize[] = {maxWgSize+primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_1d_2max_wg_size_minus_1_atomics + { + size_t globalSize[] = {2*maxWgSize - 1}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_1d_prime_number_atomics_2 + { + unsigned int primeNumber = 20101; + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_1d_prime_number_atomics_3 + { + unsigned int primeNumber = 42967; + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_1d_prime_number_atomics_4 + { + unsigned int primeNumber = 65521; + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_1d_prime_number_and_ls_null_atomics_2 + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + size_t globalSize[] = {primeNumber}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_1d_prime_number_and_ls_null_atomics_3 + { + unsigned int primeNumber = 65521; + size_t globalSize[] = {primeNumber}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + // non_uniform_1d_two_prime_numbers_atomics + { + unsigned int primeNumber = 42967; + unsigned int primeNumber2 = 113; + PrimeNumbers::Result1d fit1dResult; + + fit1dResult = PrimeNumbers::fitMaxPrime1d(primeNumber2, maxWgSize ); + + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {fit1dResult.Val1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::ATOMICS); + } + + return exec.status(); +} + +int + test_non_uniform_1d_barriers(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) +{ + SubTestExecutor exec(device, context, queue); + + size_t maxWgSize; + int err; + err = exec.calculateWorkGroupSize(maxWgSize, Range::BARRIERS); + if (err) { + log_error ("Cannot calculate work group size."); + return -1; + } + + // non_uniform_1d_max_wg_size_plus_1_barriers + { + size_t globalSize[] = {maxWgSize+1}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_1d_prime_number_barriers + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_1d_max_wg_size_plus_prime_number_barriers + { + int primeNumber = 11; + size_t globalSize[] = {maxWgSize+primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_1d_max_wg_size_plus_prime_number_barriers_2 + { + int primeNumber = 53; + size_t globalSize[] = {maxWgSize+primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_1d_2max_wg_size_minus_1_barriers + { + size_t globalSize[] = {2*maxWgSize - 1}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_1d_prime_number_barriers_2 + { + unsigned int primeNumber = 20101; + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_1d_prime_number_barriers_3 + { + unsigned int primeNumber = 42967; + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_1d_prime_number_barriers_4 + { + unsigned int primeNumber = 65521; + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {maxWgSize}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_1d_prime_number_and_ls_null_barriers_2 + { + int primeNumber = PrimeNumbers::getPrimeNumberInRange(maxWgSize, 2*maxWgSize); + if (primeNumber < 1) { + log_error ("Cannot find proper prime number."); + return -1; + } + size_t globalSize[] = {primeNumber}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_1d_prime_number_and_ls_null_barriers_3 + { + unsigned int primeNumber = 65521; + size_t globalSize[] = {primeNumber}; + size_t *localSize = NULL; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + // non_uniform_1d_two_prime_numbers_barriers + { + unsigned int primeNumber = 42967; + unsigned int primeNumber2 = 113; + + PrimeNumbers::Result1d fit1dResult; + + fit1dResult = PrimeNumbers::fitMaxPrime1d(primeNumber2, maxWgSize ); + + size_t globalSize[] = {primeNumber}; + size_t localSize[] = {fit1dResult.Val1}; + + exec.runTestNonUniformWorkGroup(sizeof(globalSize)/sizeof(globalSize[0]), globalSize, localSize, Range::BARRIERS); + } + + return exec.status(); +} diff --git a/test_conformance/non_uniform_work_group/tools.cpp b/test_conformance/non_uniform_work_group/tools.cpp new file mode 100644 index 00000000..ef732d9d --- /dev/null +++ b/test_conformance/non_uniform_work_group/tools.cpp @@ -0,0 +1,274 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "tools.h" +#include +#include "../../test_common/harness/errorHelpers.h" + +PrimeNumbersCollection PrimeNumbers::primeNumbers; +// Method generates prime numbers using Sieve of Eratosthenes algorithm +void PrimeNumbers::generatePrimeNumbers (unsigned int maxValue) { + + primeNumbers.clear(); + + for (unsigned int i=2; i < maxValue; i++) + primeNumbers.push_back(i); + + PrimeNumbersCollection::iterator it, it2; + it = primeNumbers.begin(); + it2 = primeNumbers.begin(); + + unsigned int maxValueSqrt = (unsigned int)sqrt((double)maxValue); + + for (; it != primeNumbers.end(); it++) { + it2 = it; + ++it2; + if(*it>maxValueSqrt) + break; + for (;it2 != primeNumbers.end();) + if (*it2 % *it == 0) + it2 = primeNumbers.erase(it2); + else + ++it2; + } +} + +// Returns prime number for specified range +int PrimeNumbers::getPrimeNumberInRange (size_t lowerValue, size_t higherValue) { + if(lowerValue >= higherValue) + return -1; + + if(primeNumbers.back() < lowerValue) + return -2; + + PrimeNumbersCollection::iterator it = primeNumbers.begin(); + + for (; it != primeNumbers.end(); ++it) { + if (lowerValue<*it) { + if(higherValue>*it) + return *it; + else + return -3; + } + } + return -1; +} + + +int PrimeNumbers::getNextLowerPrimeNumber(size_t upperValue) { + size_t retVal = 1; + + PrimeNumbersCollection::iterator it = primeNumbers.begin(); + + for (; it != primeNumbers.end(); ++it) { + if (upperValue > *it) { + retVal = *it; + } else { + break; + } + } + return retVal; +} + +PrimeNumbers::Result1d PrimeNumbers::fitMaxPrime1d(size_t val1, size_t maxVal){ + + PrimeNumbers::Result1d result; + + if (maxVal == 1) { + result.Val1 = 1; + return result; + } + + while(val1 > maxVal) + { + val1 = PrimeNumbers::getNextLowerPrimeNumber(val1); + } + + result.Val1 = val1; + return result; +} + +PrimeNumbers::Result2d PrimeNumbers::fitMaxPrime2d(size_t val1, size_t val2, size_t productMax) { + + PrimeNumbers::Result2d result; + + if (productMax == 1) { + result.Val1 = 1; + result.Val2 = 1; + return result; + } + + while ((val2 * val1) > productMax) { + if ((val2 > val1) && (val2 > 1)) { + val2 = PrimeNumbers::getNextLowerPrimeNumber(val2); + continue; + } + if (val1 > 1) { + val1 = PrimeNumbers::getNextLowerPrimeNumber(val1); + continue; + } + break; + } + result.Val1 = val1; + result.Val2 = val2; + return result; +} + + +PrimeNumbers::Result3d PrimeNumbers::fitMaxPrime3d(size_t val1, size_t val2, size_t val3, size_t productMax) { + + Result3d result; + + if (productMax == 1) { + result.Val1 = 1; + result.Val2 = 1; + result.Val3 = 1; + return result; + } + + while ((val3 * val2 * val1) > productMax) { + if ((val3 > val2) && (val3 > val1) && (val3 > 1)) { + val3 = PrimeNumbers::getNextLowerPrimeNumber(val3); + continue; + } + if ((val2 > val1) && (val2 > 1)) { + val2 = PrimeNumbers::getNextLowerPrimeNumber(val2); + continue; + } + if (val1 > 1) { + val1 = PrimeNumbers::getNextLowerPrimeNumber(val1); + continue; + } + break; + } + result.Val1 = val1; + result.Val2 = val2; + result.Val3 = val3; + return result; +} + +namespace Error { +ErrorMap::value_type rawDataErrorString[] = { + ErrorMap::value_type(ERR_GLOBAL_SIZE, "global size"), + ErrorMap::value_type(ERR_GLOBAL_WORK_OFFSET, "global work offset"), + ErrorMap::value_type(ERR_LOCAL_SIZE, "local size"), + ErrorMap::value_type(ERR_GLOBAL_ID, "global id"), + ErrorMap::value_type(ERR_LOCAL_ID, "local id"), + ErrorMap::value_type(ERR_ENQUEUED_LOCAL_SIZE, "enqueued local size"), + ErrorMap::value_type(ERR_LOCAL_SIZE, "local size"), + ErrorMap::value_type(ERR_NUM_GROUPS, "num groups"), + ErrorMap::value_type(ERR_GROUP_ID, "group id"), + ErrorMap::value_type(ERR_WORK_DIM, "work dim"), + ErrorMap::value_type(ERR_GLOBAL_BARRIER, "global barrier"), + ErrorMap::value_type(ERR_LOCAL_BARRIER, "local barrier"), + ErrorMap::value_type(ERR_GLOBAL_ATOMIC, "global atomic"), + ErrorMap::value_type(ERR_LOCAL_ATOMIC, "local atomic"), + ErrorMap::value_type(ERR_STRICT_MODE, "strict requirements failed. Wrong local work group size"), + ErrorMap::value_type(ERR_BUILD_STATUS, "build status"), + ErrorMap::value_type(ERR_UNKNOWN, "[unknown]"), + ErrorMap::value_type(ERR_DIFFERENT, "[different]"), +}; + +const int numElems = sizeof(rawDataErrorString)/sizeof(rawDataErrorString[0]); +ErrorMap errorString (rawDataErrorString, rawDataErrorString+numElems); + +ErrorClass::ErrorClass() { + _overallNumberOfErrors = 0; + _stats.clear(); + for (unsigned short i=0; i= MAX_NUMBER_OF_PRINTED_ERRORS) + return; + + std::string errString = "Error "; + errString += errorString[err]; + errString += " appeared"; + + if(where.compare("") != 0) { + errString += " in "; + errString += where; + } + + if(additionalInfo.compare("") != 0) { + errString += " "; + errString += additionalInfo; + } + printError(errString); +} + +void ErrorClass::show(Type whatErr, std::string where, cl_ulong valueIs, cl_ulong valueExpected) { + std::ostringstream tmp; + tmp << "(is: " << valueIs << ", expected: " << valueExpected << ")"; + show(whatErr, where, tmp.str()); +} + + +void ErrorClass::show(std::string description) { + ++_overallNumberOfErrors; + ++_stats[ERR_DIFFERENT]; + if (_overallNumberOfErrors < MAX_NUMBER_OF_PRINTED_ERRORS) + printError(description); + + if (_overallNumberOfErrors == MAX_NUMBER_OF_PRINTED_ERRORS) + printError("\t. . . Too many errors. Application will skip printing them."); +} + +void ErrorClass::printError(std::string errString) { + log_error ("%s\n", errString.c_str()); +} + +void ErrorClass::showStats() { + + Type err; + log_info ("T E S T S U M M A R Y:\n"); + for (ErrorStats::iterator it = _stats.begin(); it != _stats.end(); it++) { + err = (errorString.find(it->first) == errorString.end())?ERR_UNKNOWN:it->first; + std::string errName = errorString[err]; + log_info("Error %s:\t%d\n", errName.c_str(), it->second); + } + + log_info("Overall number of errors:\t%d\n", _overallNumberOfErrors); + +} + +bool ErrorClass::checkError() { + return _overallNumberOfErrors > 0; +} + +// This method is required to synchronize errors counters between kernel and host +void ErrorClass::synchronizeStatsMap() { + for (unsigned short i=0; i(i)] += _errorArrayCounter[i]; + _overallNumberOfErrors += _errorArrayCounter[i]; + } + +} + +} diff --git a/test_conformance/non_uniform_work_group/tools.h b/test_conformance/non_uniform_work_group/tools.h new file mode 100644 index 00000000..2e63c3dd --- /dev/null +++ b/test_conformance/non_uniform_work_group/tools.h @@ -0,0 +1,109 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _TOOLS_H +#define _TOOLS_H + +#include "procs.h" +#include +#include +#include + +typedef std::vector PrimeNumbersCollection; + + + +// Class responsible for distributing prime numbers +class PrimeNumbers { + +public: + struct Result1d{ + size_t Val1; + }; + + struct Result2d{ + size_t Val1; + size_t Val2; + }; + + struct Result3d{ + size_t Val1; + size_t Val2; + size_t Val3; + }; + + static void generatePrimeNumbers (unsigned int maxValue); + static int getPrimeNumberInRange (size_t lowerValue, size_t higherValue); + static int getNextLowerPrimeNumber (size_t upperValue); + static Result1d fitMaxPrime1d(size_t Val1, size_t productMax); + // Return val1 and Val2 which are largest prime numbers who's product is <= productMax + static Result2d fitMaxPrime2d(size_t Val1, size_t Val2, size_t productMax); + // Return val1, val2 and val3, which are largest prime numbers who's product is <= productMax + static Result3d fitMaxPrime3d(size_t Val1, size_t Val2, size_t Val3, size_t productMax); +private: + static PrimeNumbersCollection primeNumbers; + PrimeNumbers(); +}; + +// Stores information about errors +namespace Error { +#define MAX_NUMBER_OF_PRINTED_ERRORS 10 + enum Type{ + ERR_GLOBAL_SIZE=0, + ERR_GLOBAL_WORK_OFFSET, + ERR_LOCAL_SIZE, + ERR_GLOBAL_ID, + ERR_LOCAL_ID, + ERR_ENQUEUED_LOCAL_SIZE, + ERR_NUM_GROUPS, + ERR_GROUP_ID, + ERR_WORK_DIM, + ERR_GLOBAL_BARRIER, + ERR_LOCAL_BARRIER, + ERR_GLOBAL_ATOMIC, + ERR_LOCAL_ATOMIC, + + ERR_STRICT_MODE, + ERR_BUILD_STATUS, + + ERR_UNKNOWN, + ERR_DIFFERENT, + _LAST_ELEM + }; + + typedef std::map ErrorMap; + typedef std::map ErrorStats; + + class ErrorClass { + public: + ErrorClass(); + void show(Type whatErr, std::string where="", std::string additionalInfo=""); + void show(Type whatErr, std::string where, cl_ulong valueIs, cl_ulong valueExpected); + void show(std::string description); + bool checkError(); + void showStats(); + void synchronizeStatsMap(); + cl_uint * errorArrayCounter() {return _errorArrayCounter;}; + size_t errorArrayCounterSize() {return sizeof(_errorArrayCounter);}; + private: + cl_uint _errorArrayCounter[Error::_LAST_ELEM]; // this buffer is passed to kernel + int _overallNumberOfErrors; + ErrorStats _stats; + void printError(std::string errString); + + }; + +} +#endif // _TOOLS_H diff --git a/test_conformance/opencl_conformance_tests_21_full_spirv.csv b/test_conformance/opencl_conformance_tests_21_full_spirv.csv new file mode 100644 index 00000000..cf4921f9 --- /dev/null +++ b/test_conformance/opencl_conformance_tests_21_full_spirv.csv @@ -0,0 +1,122 @@ +# +# OpenCL Conformance Test Suite (full version) +# + +# ######################################### +# Basic Information on the compute device +# ######################################### +Compute Info,computeinfo/test_computeinfo + +# ######################################### +# Basic operation tests +# ######################################### +Basic,basic/test_basic -offlineCompiler spir_v cache . +API,api/test_api -offlineCompiler spir_v cache . +Compiler,compiler/test_compiler -offlineCompiler spir_v cache . + +# ######################################### +# Common mathematical functions +# ######################################### +Common Functions,commonfns/test_commonfns -offlineCompiler spir_v cache . +Geometric Functions,geometrics/test_geometrics -offlineCompiler spir_v cache . +Relationals,relationals/test_relationals -offlineCompiler spir_v cache . + +# ######################################### +# General operation +# ######################################### +Thread Dimensions,thread_dimensions/test_thread_dimensions full* -offlineCompiler spir_v cache . +Multiple Device/Context,multiple_device_context/test_multiples -offlineCompiler spir_v cache . +Atomics,atomics/test_atomics -offlineCompiler spir_v cache . +Profiling,profiling/test_profiling -offlineCompiler spir_v cache . +Events,events/test_events -offlineCompiler spir_v cache . +Allocations (single maximum),allocations/test_allocations single 5 all -offlineCompiler spir_v cache . +Allocations (total maximum),allocations/test_allocations multiple 5 all -offlineCompiler spir_v cache . +VecAlign, vec_align/test_vecalign -offlineCompiler spir_v cache . +VecStep, vec_step/test_vecstep -offlineCompiler spir_v cache . +Printf,printf/test_printf -offlineCompiler spir_v cache . +Device Partitioning,device_partition/test_device_partition -offlineCompiler spir_v cache . + +# ######################################### +# Buffers and images +# ######################################### +Images (API Info),images/clGetInfo/test_cl_get_info +Buffers,buffers/test_buffers -offlineCompiler spir_v cache . +Images (Kernel Methods),images/kernel_image_methods/test_kernel_image_methods -offlineCompiler spir_v cache . +Images (Kernel),images/kernel_read_write/test_image_streams CL_FILTER_NEAREST -offlineCompiler spir_v cache . +Images (Kernel pitch),images/kernel_read_write/test_image_streams use_pitches CL_FILTER_NEAREST -offlineCompiler spir_v cache . +Images (Kernel max size),images/kernel_read_write/test_image_streams max_images CL_FILTER_NEAREST -offlineCompiler spir_v cache . +Images (clCopyImage),images/clCopyImage/test_cl_copy_images +Images (clCopyImage small),images/clCopyImage/test_cl_copy_images small_images +Images (clCopyImage max size),images/clCopyImage/test_cl_copy_images max_images +Images (clReadWriteImage),images/clReadWriteImage/test_cl_read_write_images +Images (clReadWriteImage pitch),images/clReadWriteImage/test_cl_read_write_images use_pitches +Images (clReadWriteImage max size),images/clReadWriteImage/test_cl_read_write_images max_images +Images (clFillImage),images/clFillImage/test_cl_fill_images +Images (clFillImage pitch),images/clFillImage/test_cl_fill_images use_pitches +Images (clFillImage max size),images/clFillImage/test_cl_fill_images max_images +Images (Samplerless),images/samplerlessReads/test_samplerless_reads -offlineCompiler spir_v cache . +Images (Samplerless pitch),images/samplerlessReads/test_samplerless_reads use_pitches -offlineCompiler spir_v cache . +Images (Samplerless max size),images/samplerlessReads/test_samplerless_reads max_images -offlineCompiler spir_v cache . +Mem (Host Flags),mem_host_flags/test_mem_host_flags + +# ######################################### +# Headers +# ######################################### +Headers (cl_typen), headers/test_headers +Headers (cl.h standalone), headers/test_cl_h +Headers (cl_platform.h standalone), headers/test_cl_platform_h +Headers (cl_gl.h standalone), headers/test_cl_gl_h +Headers (opencl.h standalone), headers/test_opencl_h + +# ######################################### +# CPU is required to pass linear and normalized image filtering +# ######################################### +CL_DEVICE_TYPE_CPU, Images (Kernel CL_FILTER_LINEAR),images/kernel_read_write/test_image_streams CL_FILTER_LINEAR -offlineCompiler spir_v cache . +CL_DEVICE_TYPE_CPU, Images (Kernel CL_FILTER_LINEAR pitch),images/kernel_read_write/test_image_streams use_pitches CL_FILTER_LINEAR -offlineCompiler spir_v cache . +CL_DEVICE_TYPE_CPU, Images (Kernel CL_FILTER_LINEAR max size),images/kernel_read_write/test_image_streams max_images CL_FILTER_LINEAR -offlineCompiler spir_v cache . + +# ######################################### +# OpenGL/CL interaction +# ######################################### +OpenCL-GL Sharing,gl/test_gl -offlineCompiler spir_v cache . + +# ######################################### +# Thorough math and conversions tests +# ######################################### +Select,select/test_select -offlineCompiler spir_v cache . +Conversions,conversions/test_conversions -offlineCompiler spir_v cache . +Contractions,contractions/contractions -offlineCompiler spir_v cache . +Math,math_brute_force/bruteforce -offlineCompiler spir_v cache . +Integer Ops,integer_ops/test_integer_ops -offlineCompiler spir_v cache . +Half Ops,half/Test_half -offlineCompiler spir_v cache . + +# ######################################### +# Compatibility with Previous Versions +# ######################################### +Basic 1.2,compatibility/test_conformance/basic/test_basic +API 1.2,compatibility/test_conformance/api/test_api + +##################################### +# OpenCL 2.0 tests +##################################### +C11 Atomics,c11_atomics/test_c11_atomics -offlineCompiler spir_v cache . +Execution Model,device_execution/test_device_execution -offlineCompiler spir_v cache . +Generic Address Space,generic_address_space/test_generic_address_space -offlineCompiler spir_v cache . +Non Uniform Work Groups,non_uniform_work_group/test_non_uniform_work_group -offlineCompiler spir_v cache . +Pipes,pipes/test_pipes -offlineCompiler spir_v cache . +SVM,SVM/test_SVM -offlineCompiler spir_v cache . +Workgroups,workgroups/test_workgroups -offlineCompiler spir_v cache . + +##################################### +# OpenCL 2.1 tests +##################################### +Device timer,device_timer/test_device_timer + +######################################### +# Extensions +######################################### +SPIR,spir/test_spir +Mipmaps (Kernel),images/kernel_read_write/test_image_streams test_mipmaps CL_FILTER_NEAREST -offlineCompiler spir_v cache . +Mipmaps (clCopyImage),images/clCopyImage/test_cl_copy_images test_mipmaps -offlineCompiler spir_v cache . +Mipmaps (clReadWriteImage),images/clReadWriteImage/test_cl_read_write_images test_mipmaps -offlineCompiler spir_v cache . +Subgroups,subgroups/test_subgroups -offlineCompiler spir_v cache . diff --git a/test_conformance/opencl_conformance_tests_21_legacy_wimpy.csv b/test_conformance/opencl_conformance_tests_21_legacy_wimpy.csv new file mode 100644 index 00000000..ee7ab99e --- /dev/null +++ b/test_conformance/opencl_conformance_tests_21_legacy_wimpy.csv @@ -0,0 +1,103 @@ +# +# OpenCL Conformance Test Suite (quick version) +# The quick version skips some long-running image tests, runs a shorter math test, +# and does not run the conversion test. +# + +# ######################################### +# Basic Information on the compute device +# ######################################### +Compute Info,computeinfo/test_computeinfo + +# ######################################### +# Basic operation tests +# ######################################### +Basic,basic/test_basic +API,api/test_api +Compiler,compiler/test_compiler + +# ######################################### +# Common mathematical functions +# ######################################### +Common Functions,commonfns/test_commonfns +Geometric Functions,geometrics/test_geometrics +Relationals,relationals/test_relationals + +# ######################################### +# General operation +# ######################################### +Thread Dimensions,thread_dimensions/test_thread_dimensions quick* +Multiple Device/Context,multiple_device_context/test_multiples +Atomics,atomics/test_atomics +Profiling,profiling/test_profiling +Events,events/test_events +Allocations (single maximum),allocations/test_allocations single 5 all +Allocations (total maximum),allocations/test_allocations multiple 5 all +VecAlign, vec_align/test_vecalign +VecStep, vec_step/test_vecstep +Printf,printf/test_printf +Device Partitioning,device_partition/test_device_partition + +# ######################################### +# Buffers and images +# ######################################### +Buffers,buffers/test_buffers +Images (Kernel Methods),images/kernel_image_methods/test_kernel_image_methods +Images (Kernel),images/kernel_read_write/test_image_streams CL_FILTER_NEAREST +Images (Kernel pitch),images/kernel_read_write/test_image_streams use_pitches CL_FILTER_NEAREST +Images (Kernel max size),images/kernel_read_write/test_image_streams max_images CL_FILTER_NEAREST +Images (Samplerless),images/samplerlessReads/test_samplerless_reads +Images (Samplerless pitch),images/samplerlessReads/test_samplerless_reads use_pitches +Images (Samplerless max size),images/samplerlessReads/test_samplerless_reads max_images +Mem (Host Flags),mem_host_flags/test_mem_host_flags + +# ######################################### +# Headers +# ######################################### +Headers (cl_typen), headers/test_headers +Headers (cl.h standalone), headers/test_cl_h +Headers (cl_platform.h standalone), headers/test_cl_platform_h +Headers (cl_gl.h standalone), headers/test_cl_gl_h +Headers (opencl.h standalone), headers/test_opencl_h + +# ######################################### +# CPU is required to pass linear and normalized image filtering +# ######################################### +CL_DEVICE_TYPE_CPU, Images (Kernel CL_FILTER_LINEAR),images/kernel_read_write/test_image_streams CL_FILTER_LINEAR +CL_DEVICE_TYPE_CPU, Images (Kernel CL_FILTER_LINEAR pitch),images/kernel_read_write/test_image_streams use_pitches CL_FILTER_LINEAR +CL_DEVICE_TYPE_CPU, Images (Kernel CL_FILTER_LINEAR max size),images/kernel_read_write/test_image_streams max_images CL_FILTER_LINEAR + +# ######################################### +# OpenGL/CL interaction +# ######################################### +OpenCL-GL Sharing,gl/test_gl + +# ######################################### +# Thorough math and conversions tests +# ######################################### +Select,select/test_select +Conversions,conversions/test_conversions -w +Contractions,contractions/contractions +Math,math_brute_force/bruteforce -w +Integer Ops,integer_ops/test_integer_ops integer_* quick_* +Half Ops,half/Test_half -w + +##################################### +# OpenCL 2.0 tests +##################################### +C11 Atomics,c11_atomics/test_c11_atomics +Execution Model,device_execution/test_device_execution +Generic Address Space,generic_address_space/test_generic_address_space +Non Uniform Work Groups,non_uniform_work_group/test_non_uniform_work_group +Pipes,pipes/test_pipes +SVM,SVM/test_SVM +Workgroups,workgroups/test_workgroups + +######################################### +# Extensions +######################################### +SPIR,spir/test_spir +Mipmaps (Kernel),images/kernel_read_write/test_image_streams test_mipmaps CL_FILTER_NEAREST +Mipmaps (clCopyImage),images/clCopyImage/test_cl_copy_images test_mipmaps +Mipmaps (clReadWriteImage),images/clReadWriteImage/test_cl_read_write_images test_mipmaps +Subgroups,subgroups/test_subgroups \ No newline at end of file diff --git a/test_conformance/opencl_conformance_tests_22.csv b/test_conformance/opencl_conformance_tests_22.csv new file mode 100644 index 00000000..2ef864a6 --- /dev/null +++ b/test_conformance/opencl_conformance_tests_22.csv @@ -0,0 +1,45 @@ +# +# OpenCL Conformance Test Suite (2.2 version) +# + +# ######################################### +# New API features +# ######################################### +API (ctors and dtors of global scope vars) , clcpp/api/test_cpp_api "test_global_scope*" +API (specialization constants) , clcpp/api/test_cpp_api "test_spec_consts*" + +# ######################################### +# New representation of types +# ######################################### +Images and samplers , clcpp/images/test_cpp_images +Pipes and reservations , clcpp/pipes/test_cpp_pipes "test_pipes_pipe" +Device enqueue and events , clcpp/device_queue/test_cpp_device_queue +Address spaces , clcpp/address_spaces/test_cpp_address_spaces + +# ######################################### +# New representation of functions +# ######################################### +Conversions (convert_cast) , clcpp/convert/test_cpp_convert +Reinterpreting (as_type) , clcpp/reinterpret/test_cpp_reinterpret +Atomics , clcpp/atomics/test_cpp_atomics +Work-item functions , clcpp/workitems/test_cpp_workitems +Work-group functions , clcpp/workgroups/test_cpp_workgroups +Sub-group functions , clcpp/subgroups/test_cpp_subgroups +Synchronization functions , clcpp/synchronization/test_cpp_synchronization "test_work_group_barrier*" "test_sub_group_barrier*" +Math functions , clcpp/math_funcs/test_cpp_math_funcs +Integer functions , clcpp/integer_funcs/test_cpp_integer_funcs +Common functions , clcpp/common_funcs/test_cpp_common_funcs +Geometric functions , clcpp/geometric_funcs/test_cpp_geometric_funcs +Relational functions , clcpp/relational_funcs/test_cpp_relational_funcs +vload and vstore functions , clcpp/vload_vstore/test_cpp_vload_vstore_funcs + +# ######################################### +# New in OpenCL C++ +# ######################################### +Specialization constants , clcpp/spec_constants/test_cpp_spec_constants +Named barriers (KHR extension) , clcpp/synchronization/test_cpp_synchronization "test_work_group_named_barrier*" +required_num_sub_groups attribute , clcpp/attributes/test_cpp_attributes "test_required_num_sub_groups*" +ivdep attribute , clcpp/attributes/test_cpp_attributes "test_ivdep*" +max_size attribute , clcpp/attributes/test_cpp_attributes "test_max_size*" +Ctors and dtors of global scope objects , clcpp/program_scope_ctors_dtors/test_cpp_program_scope_ctors_dtors +Pipe storages , clcpp/pipes/test_cpp_pipes "test_pipes_pipe_storage" diff --git a/test_conformance/opencl_conformance_tests_conversions.csv b/test_conformance/opencl_conformance_tests_conversions.csv new file mode 100644 index 00000000..c8e283a6 --- /dev/null +++ b/test_conformance/opencl_conformance_tests_conversions.csv @@ -0,0 +1,4 @@ +# +# OpenCL Conformance Test Suite (conversions only) +# +Conversions,conversions/test_conversions diff --git a/test_conformance/opencl_conformance_tests_d3d.csv b/test_conformance/opencl_conformance_tests_d3d.csv new file mode 100644 index 00000000..29d2267e --- /dev/null +++ b/test_conformance/opencl_conformance_tests_d3d.csv @@ -0,0 +1,7 @@ +# +# OpenCL Conformance Test for DirectX interop +# + +DX9 media sharing,media_sharing\test_media_surface_sharing +D3D10,d3d10\test_d3d10 +D3D11,d3d11\test_d3d11 \ No newline at end of file diff --git a/test_conformance/opencl_conformance_tests_full.csv b/test_conformance/opencl_conformance_tests_full.csv new file mode 100644 index 00000000..380870e0 --- /dev/null +++ b/test_conformance/opencl_conformance_tests_full.csv @@ -0,0 +1,117 @@ +# +# OpenCL Conformance Test Suite (full version) +# + +# ######################################### +# Basic Information on the compute device +# ######################################### +Compute Info,computeinfo/test_computeinfo + +# ######################################### +# Basic operation tests +# ######################################### +Basic,basic/test_basic +API,api/test_api +Compiler,compiler/test_compiler + +# ######################################### +# Common mathematical functions +# ######################################### +Common Functions,commonfns/test_commonfns +Geometric Functions,geometrics/test_geometrics +Relationals,relationals/test_relationals + +# ######################################### +# General operation +# ######################################### +Thread Dimensions,thread_dimensions/test_thread_dimensions full* +Multiple Device/Context,multiple_device_context/test_multiples +Atomics,atomics/test_atomics +Profiling,profiling/test_profiling +Events,events/test_events +Allocations (single maximum),allocations/test_allocations single 5 all +Allocations (total maximum),allocations/test_allocations multiple 5 all +VecAlign, vec_align/test_vecalign +VecStep, vec_step/test_vecstep +Printf,printf/test_printf +Device Partitioning,device_partition/test_device_partition + +# ######################################### +# Buffers and images +# ######################################### +Buffers,buffers/test_buffers +Images (API Info),images/clGetInfo/test_cl_get_info +Images (Kernel Methods),images/kernel_image_methods/test_kernel_image_methods +Images (Kernel),images/kernel_read_write/test_image_streams CL_FILTER_NEAREST +Images (Kernel pitch),images/kernel_read_write/test_image_streams use_pitches CL_FILTER_NEAREST +Images (Kernel max size),images/kernel_read_write/test_image_streams max_images CL_FILTER_NEAREST +Images (clCopyImage),images/clCopyImage/test_cl_copy_images +Images (clCopyImage small),images/clCopyImage/test_cl_copy_images small_images +Images (clCopyImage max size),images/clCopyImage/test_cl_copy_images max_images +Images (clReadWriteImage),images/clReadWriteImage/test_cl_read_write_images +Images (clReadWriteImage pitch),images/clReadWriteImage/test_cl_read_write_images use_pitches +Images (clReadWriteImage max size),images/clReadWriteImage/test_cl_read_write_images max_images +Images (clFillImage),images/clFillImage/test_cl_fill_images +Images (clFillImage pitch),images/clFillImage/test_cl_fill_images use_pitches +Images (clFillImage max size),images/clFillImage/test_cl_fill_images max_images +Images (Samplerless),images/samplerlessReads/test_samplerless_reads +Images (Samplerless pitch),images/samplerlessReads/test_samplerless_reads use_pitches +Images (Samplerless max size),images/samplerlessReads/test_samplerless_reads max_images +Mem (Host Flags),mem_host_flags/test_mem_host_flags + +# ######################################### +# Headers +# ######################################### +Headers (cl_typen), headers/test_headers +Headers (cl.h standalone), headers/test_cl_h +Headers (cl_platform.h standalone), headers/test_cl_platform_h +Headers (cl_gl.h standalone), headers/test_cl_gl_h +Headers (opencl.h standalone), headers/test_opencl_h + +# ######################################### +# CPU is required to pass linear and normalized image filtering +# ######################################### +CL_DEVICE_TYPE_CPU, Images (Kernel CL_FILTER_LINEAR),images/kernel_read_write/test_image_streams CL_FILTER_LINEAR +CL_DEVICE_TYPE_CPU, Images (Kernel CL_FILTER_LINEAR pitch),images/kernel_read_write/test_image_streams use_pitches CL_FILTER_LINEAR +CL_DEVICE_TYPE_CPU, Images (Kernel CL_FILTER_LINEAR max size),images/kernel_read_write/test_image_streams max_images CL_FILTER_LINEAR + +# ######################################### +# OpenGL/CL interaction +# ######################################### +OpenCL-GL Sharing,gl/test_gl + +# ######################################### +# Thorough math and conversions tests +# ######################################### +Select,select/test_select +Conversions,conversions/test_conversions +Contractions,contractions/contractions +Math,math_brute_force/bruteforce +Integer Ops,integer_ops/test_integer_ops +Half Ops,half/test_half + +# ######################################### +# Compatibility with Previous Versions +# ######################################### +Basic 1.2,compatibility/test_conformance/basic/test_basic +API 1.2,compatibility/test_conformance/api/test_api + +##################################### +# OpenCL 2.0 tests +##################################### +C11 Atomics,c11_atomics/test_c11_atomics +Execution Model,device_execution/test_device_execution +Generic Address Space,generic_address_space/test_generic_address_space +Non Uniform Work Groups,non_uniform_work_group/test_non_uniform_work_group +Pipes,pipes/test_pipes +SVM,SVM/test_SVM +Workgroups,workgroups/test_workgroups + +######################################### +# Extensions +######################################### +SPIR,spir/test_spir +Mipmaps (Kernel),images/kernel_read_write/test_image_streams test_mipmaps CL_FILTER_NEAREST +Mipmaps (clCopyImage),images/clCopyImage/test_cl_copy_images test_mipmaps +Mipmaps (clReadWriteImage),images/clReadWriteImage/test_cl_read_write_images test_mipmaps +Subgroups,subgroups/test_subgroups \ No newline at end of file diff --git a/test_conformance/opencl_conformance_tests_full_no_math_or_conversions.csv b/test_conformance/opencl_conformance_tests_full_no_math_or_conversions.csv new file mode 100644 index 00000000..b52f20c0 --- /dev/null +++ b/test_conformance/opencl_conformance_tests_full_no_math_or_conversions.csv @@ -0,0 +1,92 @@ +# +# OpenCL Conformance Test Suite (full version) +# + +# ######################################### +# Basic Information on the compute device +# ######################################### +Compute Info,computeinfo/test_computeinfo + +# ######################################### +# Basic operation tests +# ######################################### +Basic,basic/test_basic +API,api/test_api +Compiler,compiler/test_compiler + +# ######################################### +# Common mathematical functions +# ######################################### +Common Functions,commonfns/test_commonfns +Geometric Functions,geometrics/test_geometrics +Relationals,relationals/test_relationals + +# ######################################### +# General operation +# ######################################### +Thread Dimensions,thread_dimensions/test_thread_dimensions full* +Multiple Device/Context,multiple_device_context/test_multiples +Atomics,atomics/test_atomics +Profiling,profiling/test_profiling +Events,events/test_events +Allocations (single maximum),allocations/test_allocations single 5 all +Allocations (total maximum),allocations/test_allocations multiple 5 all +VecAlign, vec_align/test_vecalign +VecStep, vec_step/test_vecstep + +# ######################################### +# Buffers and images +# ######################################### +Buffers,buffers/test_buffers +Images (API Info),images/clGetInfo/test_cl_get_info +Images (Kernel Methods),images/kernel_image_methods/test_kernel_image_methods +Images (Kernel),images/kernel_read_write/test_image_streams CL_FILTER_NEAREST +Images (Kernel pitch),images/kernel_read_write/test_image_streams use_pitches CL_FILTER_NEAREST +Images (Kernel max size),images/kernel_read_write/test_image_streams max_images CL_FILTER_NEAREST +Images (clCopyImage),images/clCopyImage/test_cl_copy_images +Images (clCopyImage small),images/clCopyImage/test_cl_copy_images small_images +Images (clCopyImage max size),images/clCopyImage/test_cl_copy_images max_images +Images (clReadWriteImage),images/clReadWriteImage/test_cl_read_write_images +Images (clReadWriteImage pitch),images/clReadWriteImage/test_cl_read_write_images use_pitches +Images (clReadWriteImage max size),images/clReadWriteImage/test_cl_read_write_images max_images +Images (clFillImage),images/clFillImage/test_cl_fill_images +Images (clFillImage pitch),images/clFillImage/test_cl_fill_images use_pitches +Images (clFillImage max size),images/clFillImage/test_cl_fill_images max_images +Images (Samplerless),images/samplerlessReads/test_samplerless_reads +Images (Samplerless pitch),images/samplerlessReads/test_samplerless_reads use_pitches +Images (Samplerless max size),images/samplerlessReads/test_samplerless_reads max_images +Mem (Host Flags),mem_host_flags/test_mem_host_flags + +# ######################################### +# Headers +# ######################################### +Headers (cl_typen), headers/test_headers +Headers (cl.h standalone), headers/test_cl_h +Headers (cl_platform.h standalone), headers/test_cl_platform_h +Headers (cl_gl.h standalone), headers/test_cl_gl_h +Headers (opencl.h standalone), headers/test_opencl_h +Headers (cl.h standalone C99), headers/test_cl_h_c99 +Headers (cl_platform.h standalone C99), headers/test_cl_platform_h_c99 +Headers (cl_gl.h standalone C99), headers/test_cl_gl_h_c99 +Headers (opencl.h standalone C99), headers/test_opencl_h_c99 + +# ######################################### +# CPU is required to pass linear and normalized image filtering +# ######################################### +CL_DEVICE_TYPE_CPU, Images (Kernel CL_FILTER_LINEAR),images/kernel_read_write/test_image_streams CL_FILTER_LINEAR +CL_DEVICE_TYPE_CPU, Images (Kernel CL_FILTER_LINEAR pitch),images/kernel_read_write/test_image_streams use_pitches CL_FILTER_LINEAR +CL_DEVICE_TYPE_CPU, Images (Kernel CL_FILTER_LINEAR max size),images/kernel_read_write/test_image_streams max_images CL_FILTER_LINEAR + +# ######################################### +# OpenGL/CL interaction +# ######################################### +OpenCL-GL Sharing,gl/test_gl + +# ######################################### +# Thorough math and conversions tests +# ######################################### +Select,select/test_select +Contractions,contractions/contractions +Integer Ops,integer_ops/test_integer_ops +Half Ops,half/Test_half + diff --git a/test_conformance/opencl_conformance_tests_generate_spirv.csv b/test_conformance/opencl_conformance_tests_generate_spirv.csv new file mode 100644 index 00000000..1d5baf66 --- /dev/null +++ b/test_conformance/opencl_conformance_tests_generate_spirv.csv @@ -0,0 +1,73 @@ +# +# OpenCL Conformance Test Suite (generate spirv binaries) +# + +# ######################################### +# Basic operation tests +# ######################################### +Basic,basic/test_basic -offlineCompiler spir_v generate . +API,api/test_api -offlineCompiler spir_v generate . +Compiler,compiler/test_compiler -offlineCompiler spir_v generate . + +# ######################################### +# Common mathematical functions +# ######################################### +Common Functions,commonfns/test_commonfns -offlineCompiler spir_v generate . +Geometric Functions,geometrics/test_geometrics -offlineCompiler spir_v generate . +Relationals,relationals/test_relationals -offlineCompiler spir_v generate . + +# ######################################### +# General operation +# ######################################### +Thread Dimensions,thread_dimensions/test_thread_dimensions quick* -offlineCompiler spir_v generate . +Multiple Device/Context,multiple_device_context/test_multiples -offlineCompiler spir_v generate . +Atomics,atomics/test_atomics -offlineCompiler spir_v generate . +Profiling,profiling/test_profiling -offlineCompiler spir_v generate . +Events,events/test_events -offlineCompiler spir_v generate . +Allocations (single maximum),allocations/test_allocations single 5 all -offlineCompiler spir_v generate . +Allocations (total maximum),allocations/test_allocations multiple 5 all -offlineCompiler spir_v generate . +VecAlign, vec_align/test_vecalign -offlineCompiler spir_v generate . +VecStep, vec_step/test_vecstep -offlineCompiler spir_v generate . +Printf,printf/test_printf -offlineCompiler spir_v generate . +Device Partitioning,device_partition/test_device_partition -offlineCompiler spir_v generate . + +# ######################################### +# Buffers and images +# ######################################### +Buffers,buffers/test_buffers +Images (Kernel Methods),images/kernel_image_methods/test_kernel_image_methods -offlineCompiler spir_v generate . +Images (Kernel),images/kernel_read_write/test_image_streams CL_FILTER_NEAREST -offlineCompiler spir_v generate . +Images (Samplerless),images/samplerlessReads/test_samplerless_reads -offlineCompiler spir_v generate . + +# ######################################### +# OpenGL/CL interaction +# ######################################### +OpenCL-GL Sharing,gl/test_gl -offlineCompiler spir_v generate . + +# ######################################### +# Thorough math and conversions tests +# ######################################### +Select,select/test_select -offlineCompiler spir_v generate . +Conversions,conversions/test_conversions -w -offlineCompiler spir_v generate . +Contractions,contractions/contractions -offlineCompiler spir_v generate . +Math,math_brute_force/bruteforce -w -offlineCompiler spir_v generate . +Integer Ops,integer_ops/test_integer_ops integer_* quick_* -offlineCompiler spir_v generate . +Half Ops,half/test_half -w -offlineCompiler spir_v generate . + +##################################### +# OpenCL 2.0 tests +##################################### +C11 Atomics,c11_atomics/test_c11_atomics -offlineCompiler spir_v generate . +Execution Model,device_execution/test_device_execution -offlineCompiler spir_v generate . +Generic Address Space,generic_address_space/test_generic_address_space -offlineCompiler spir_v generate . +Non Uniform Work Groups,non_uniform_work_group/test_non_uniform_work_group -offlineCompiler spir_v generate . +Pipes,pipes/test_pipes -offlineCompiler spir_v generate . +SVM,SVM/test_SVM -offlineCompiler spir_v generate . +Workgroups,workgroups/test_workgroups -offlineCompiler spir_v generate . + +######################################### +# Extensions +######################################### +Mipmaps (Kernel),images/kernel_read_write/test_image_streams test_mipmaps CL_FILTER_NEAREST -offlineCompiler spir_v generate . +Mipmaps (clCopyImage),images/clCopyImage/test_cl_copy_images test_mipmaps -offlineCompiler spir_v generate . +Subgroups,subgroups/test_subgroups -offlineCompiler spir_v generate . diff --git a/test_conformance/opencl_conformance_tests_math.csv b/test_conformance/opencl_conformance_tests_math.csv new file mode 100644 index 00000000..ebc4e4a3 --- /dev/null +++ b/test_conformance/opencl_conformance_tests_math.csv @@ -0,0 +1,4 @@ +# +# OpenCL Conformance Test Suite (math only) +# +Math,math_brute_force/bruteforce diff --git a/test_conformance/opencl_conformance_tests_quick.csv b/test_conformance/opencl_conformance_tests_quick.csv new file mode 100644 index 00000000..b80a3737 --- /dev/null +++ b/test_conformance/opencl_conformance_tests_quick.csv @@ -0,0 +1,90 @@ +# +# OpenCL Conformance Test Suite (quick version) +# The quick version skips some long-running image tests, runs a shorter math test, +# and does not run the conversion test. +# + +# ######################################### +# Basic Information on the compute device +# ######################################### +Compute Info,computeinfo/test_computeinfo + +# ######################################### +# Basic operation tests +# ######################################### +Basic,basic/test_basic +API,api/test_api +Compiler,compiler/test_compiler + +# ######################################### +# Common mathematical functions +# ######################################### +Common Functions,commonfns/test_commonfns +Geometric Functions,geometrics/test_geometrics +Relationals,relationals/test_relationals + +# ######################################### +# General operation +# ######################################### +Thread Dimensions,thread_dimensions/test_thread_dimensions quick* +#Multiple Device/Context,multiple_device_context/test_multiples +Atomics,atomics/test_atomics +Profiling,profiling/test_profiling +Events,events/test_events +Allocations (single maximum),allocations/test_allocations single 5 all +Allocations (total maximum),allocations/test_allocations multiple 5 all +Printf,printf/test_printf +Device Partitioning,device_partition/test_device_partition + +# ######################################### +# Buffers and images +# ######################################### +Buffers,buffers/test_buffers +Images (API Info),images/clGetInfo/test_cl_get_info +Images (Kernel Methods),images/kernel_image_methods/test_kernel_image_methods +Images (Kernel),images/kernel_read_write/test_image_streams CL_FILTER_NEAREST +Images (Kernel pitch),images/kernel_read_write/test_image_streams use_pitches CL_FILTER_NEAREST +Images (Kernel max size),images/kernel_read_write/test_image_streams max_images CL_FILTER_NEAREST +Images (clCopyImage),images/clCopyImage/test_cl_copy_images +Images (clCopyImage max size),images/clCopyImage/test_cl_copy_images max_images +Images (clReadWriteImage),images/clReadWriteImage/test_cl_read_write_images +Images (clReadWriteImage pitch),images/clReadWriteImage/test_cl_read_write_images use_pitches +Images (clReadWriteImage max size),images/clReadWriteImage/test_cl_read_write_images max_images +Images (clFillImage),images/clFillImage/test_cl_fill_images +Images (clFillImage pitch),images/clFillImage/test_cl_fill_images use_pitches +Images (clFillImage max size),images/clFillImage/test_cl_fill_images max_images +Images (Samplerless),images/samplerlessReads/test_samplerless_reads +Images (Samplerless pitch),images/samplerlessReads/test_samplerless_reads use_pitches +Images (Samplerless max size),images/samplerlessReads/test_samplerless_reads max_images +Mem (Host Flags),mem_host_flags/test_mem_host_flags + +# ######################################### +# Headers +# ######################################### +Headers (cl_typen), headers/test_headers +Headers (cl.h standalone), headers/test_cl_h +Headers (cl_platform.h standalone), headers/test_cl_platform_h +Headers (cl_gl.h standalone), headers/test_cl_gl_h +Headers (opencl.h standalone), headers/test_opencl_h + +# ######################################### +# CPU is required to pass linear and normalized image filtering +# ######################################### +CL_DEVICE_TYPE_CPU, Images (Kernel CL_FILTER_LINEAR),images/kernel_read_write/test_image_streams CL_FILTER_LINEAR +CL_DEVICE_TYPE_CPU, Images (Kernel CL_FILTER_LINEAR pitch),images/kernel_read_write/test_image_streams use_pitches CL_FILTER_LINEAR +CL_DEVICE_TYPE_CPU, Images (Kernel CL_FILTER_LINEAR max size),images/kernel_read_write/test_image_streams max_images CL_FILTER_LINEAR + +# ######################################### +# OpenGL/CL interaction +# ######################################### +OpenCL-GL Sharing,gl/test_gl + +# ######################################### +# Thorough math and conversions tests +# ######################################### +Select,select/test_select +#Conversions,conversions/test_conversions +Contractions,contractions/contractions +Math,math_brute_force/bruteforce -w +Integer Ops,integer_ops/test_integer_ops integer_* quick_* +Half Ops,half/Test_half -w diff --git a/test_conformance/pipes/CMakeLists.txt b/test_conformance/pipes/CMakeLists.txt new file mode 100644 index 00000000..e833f0ec --- /dev/null +++ b/test_conformance/pipes/CMakeLists.txt @@ -0,0 +1,22 @@ +set(MODULE_NAME pipes) + +set(${MODULE_NAME}_SOURCES + main.c + test_pipe_read_write.c + test_pipe_info.c + test_pipe_limits.c + test_pipe_query_functions.c + test_pipe_readwrite_errors.c + test_pipe_subgroups.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/typeWrappers.cpp + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) diff --git a/test_conformance/pipes/kernels.h b/test_conformance/pipes/kernels.h new file mode 100644 index 00000000..a2fb70c0 --- /dev/null +++ b/test_conformance/pipes/kernels.h @@ -0,0 +1,130 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _KERNELS_H_ +#define _KERNELS_H_ + +static const char* pipe_readwrite_struct_kernel_code = { + "typedef struct{\n" + "char a;\n" + "int b;\n" + "}TestStruct;\n" + "__kernel void test_pipe_write_struct(__global TestStruct *src, __write_only pipe TestStruct out_pipe)\n" + "{\n" + " int gid = get_global_id(0);\n" + " reserve_id_t res_id; \n" + "\n" + " res_id = reserve_write_pipe(out_pipe, 1);\n" + " if(is_valid_reserve_id(res_id))\n" + " {\n" + " write_pipe(out_pipe, res_id, 0, &src[gid]);\n" + " commit_write_pipe(out_pipe, res_id);\n" + " }\n" + "}\n" + "\n" + "__kernel void test_pipe_read_struct(__read_only pipe TestStruct in_pipe, __global TestStruct *dst)\n" + "{\n" + " int gid = get_global_id(0);\n" + " reserve_id_t res_id; \n" + "\n" + " res_id = reserve_read_pipe(in_pipe, 1);\n" + " if(is_valid_reserve_id(res_id))\n" + " {\n" + " read_pipe(in_pipe, res_id, 0, &dst[gid]);\n" + " commit_read_pipe(in_pipe, res_id);\n" + " }\n" + "}\n" }; + +static const char* pipe_workgroup_readwrite_struct_kernel_code = { + "typedef struct{\n" + "char a;\n" + "int b;\n" + "}TestStruct;\n" + "__kernel void test_pipe_workgroup_write_struct(__global TestStruct *src, __write_only pipe TestStruct out_pipe)\n" + "{\n" + " int gid = get_global_id(0);\n" + " __local reserve_id_t res_id; \n" + "\n" + " res_id = work_group_reserve_write_pipe(out_pipe, get_local_size(0));\n" + " if(is_valid_reserve_id(res_id))\n" + " {\n" + " write_pipe(out_pipe, res_id, get_local_id(0), &src[gid]);\n" + " work_group_commit_write_pipe(out_pipe, res_id);\n" + " }\n" + "}\n" + "\n" + "__kernel void test_pipe_workgroup_read_struct(__read_only pipe TestStruct in_pipe, __global TestStruct *dst)\n" + "{\n" + " int gid = get_global_id(0);\n" + " __local reserve_id_t res_id; \n" + "\n" + " res_id = work_group_reserve_read_pipe(in_pipe, get_local_size(0));\n" + " if(is_valid_reserve_id(res_id))\n" + " {\n" + " read_pipe(in_pipe, res_id, get_local_id(0), &dst[gid]);\n" + " work_group_commit_read_pipe(in_pipe, res_id);\n" + " }\n" + "}\n" }; + +static const char* pipe_subgroup_readwrite_struct_kernel_code = { + "typedef struct{\n" + "char a;\n" + "int b;\n" + "}TestStruct;\n" + "#pragma OPENCL EXTENSION cl_khr_subgroups : enable\n" + "__kernel void test_pipe_subgroup_write_struct(__global TestStruct *src, __write_only pipe TestStruct out_pipe)\n" + "{\n" + " int gid = get_global_id(0);\n" + " reserve_id_t res_id; \n" + "\n" + " res_id = sub_group_reserve_write_pipe(out_pipe, get_sub_group_size());\n" + " if(is_valid_reserve_id(res_id))\n" + " {\n" + " write_pipe(out_pipe, res_id, get_sub_group_local_id(), &src[gid]);\n" + " sub_group_commit_write_pipe(out_pipe, res_id);\n" + " }\n" + "}\n" + "\n" + "__kernel void test_pipe_subgroup_read_struct(__read_only pipe TestStruct in_pipe, __global TestStruct *dst)\n" + "{\n" + " int gid = get_global_id(0);\n" + " reserve_id_t res_id; \n" + "\n" + " res_id = sub_group_reserve_read_pipe(in_pipe, get_sub_group_size());\n" + " if(is_valid_reserve_id(res_id))\n" + " {\n" + " read_pipe(in_pipe, res_id, get_sub_group_local_id(), &dst[gid]);\n" + " sub_group_commit_read_pipe(in_pipe, res_id);\n" + " }\n" + "}\n" }; + +static const char* pipe_convenience_readwrite_struct_kernel_code = { + "typedef struct{\n" + "char a;\n" + "int b;\n" + "}TestStruct;\n" + "__kernel void test_pipe_convenience_write_struct(__global TestStruct *src, __write_only pipe TestStruct out_pipe)\n" + "{\n" + " int gid = get_global_id(0);\n" + " write_pipe(out_pipe, &src[gid]);\n" + "}\n" + "\n" + "__kernel void test_pipe_convenience_read_struct(__read_only pipe TestStruct in_pipe, __global TestStruct *dst)\n" + "{\n" + " int gid = get_global_id(0);\n" + " read_pipe(in_pipe, &dst[gid]);\n" + "}\n" }; + +#endif //_KERNELS_H_ diff --git a/test_conformance/pipes/main.c b/test_conformance/pipes/main.c new file mode 100644 index 00000000..e8597fbc --- /dev/null +++ b/test_conformance/pipes/main.c @@ -0,0 +1,147 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include "procs.h" +#include "../../test_common/harness/testHarness.h" + +basefn pipefn_list[] = { + test_pipe_readwrite_int, + test_pipe_readwrite_uint, + test_pipe_readwrite_long, + test_pipe_readwrite_ulong, + test_pipe_readwrite_short, + test_pipe_readwrite_ushort, + test_pipe_readwrite_float, + test_pipe_readwrite_half, + test_pipe_readwrite_char, + test_pipe_readwrite_uchar, + test_pipe_readwrite_double, + test_pipe_readwrite_struct, + test_pipe_workgroup_readwrite_int, + test_pipe_workgroup_readwrite_uint, + test_pipe_workgroup_readwrite_long, + test_pipe_workgroup_readwrite_ulong, + test_pipe_workgroup_readwrite_short, + test_pipe_workgroup_readwrite_ushort, + test_pipe_workgroup_readwrite_float, + test_pipe_workgroup_readwrite_half, + test_pipe_workgroup_readwrite_char, + test_pipe_workgroup_readwrite_uchar, + test_pipe_workgroup_readwrite_double, + test_pipe_workgroup_readwrite_struct, + test_pipe_subgroup_readwrite_int, + test_pipe_subgroup_readwrite_uint, + test_pipe_subgroup_readwrite_long, + test_pipe_subgroup_readwrite_ulong, + test_pipe_subgroup_readwrite_short, + test_pipe_subgroup_readwrite_ushort, + test_pipe_subgroup_readwrite_float, + test_pipe_subgroup_readwrite_half, + test_pipe_subgroup_readwrite_char, + test_pipe_subgroup_readwrite_uchar, + test_pipe_subgroup_readwrite_double, + test_pipe_subgroup_readwrite_struct, + test_pipe_convenience_readwrite_int, + test_pipe_convenience_readwrite_uint, + test_pipe_convenience_readwrite_long, + test_pipe_convenience_readwrite_ulong, + test_pipe_convenience_readwrite_short, + test_pipe_convenience_readwrite_ushort, + test_pipe_convenience_readwrite_float, + test_pipe_convenience_readwrite_half, + test_pipe_convenience_readwrite_char, + test_pipe_convenience_readwrite_uchar, + test_pipe_convenience_readwrite_double, + test_pipe_convenience_readwrite_struct, + test_pipe_info, + test_pipe_max_args, + test_pipe_max_packet_size, + test_pipe_max_active_reservations, + test_pipe_query_functions, + test_pipe_readwrite_errors, + test_pipe_subgroups_divergence +}; + +const char *pipefn_names[] = { + "pipe_readwrite_int", + "pipe_readwrite_uint", + "pipe_readwrite_long", + "pipe_readwrite_ulong", + "pipe_readwrite_short", + "pipe_readwrite_ushort", + "pipe_readwrite_float", + "pipe_readwrite_half", + "pipe_readwrite_char", + "pipe_readwrite_uchar", + "pipe_readwrite_double", + "pipe_readwrite_struct", + "pipe_workgroup_readwrite_int", + "pipe_workgroup_readwrite_uint", + "pipe_workgroup_readwrite_long", + "pipe_workgroup_readwrite_ulong", + "pipe_workgroup_readwrite_short", + "pipe_workgroup_readwrite_ushort", + "pipe_workgroup_readwrite_float", + "pipe_workgroup_readwrite_half", + "pipe_workgroup_readwrite_char", + "pipe_workgroup_readwrite_uchar", + "pipe_workgroup_readwrite_double", + "pipe_workgroup_readwrite_struct", + "pipe_subgroup_readwrite_int", + "pipe_subgroup_readwrite_uint", + "pipe_subgroup_readwrite_long", + "pipe_subgroup_readwrite_ulong", + "pipe_subgroup_readwrite_short", + "pipe_subgroup_readwrite_ushort", + "pipe_subgroup_readwrite_float", + "pipe_subgroup_readwrite_half", + "pipe_subgroup_readwrite_char", + "pipe_subgroup_readwrite_uchar", + "pipe_subgroup_readwrite_double", + "pipe_subgroup_readwrite_struct", + "pipe_convenience_readwrite_int", + "pipe_convenience_readwrite_uint", + "pipe_convenience_readwrite_long", + "pipe_convenience_readwrite_ulong", + "pipe_convenience_readwrite_short", + "pipe_convenience_readwrite_ushort", + "pipe_convenience_readwrite_float", + "pipe_convenience_readwrite_half", + "pipe_convenience_readwrite_char", + "pipe_convenience_readwrite_uchar", + "pipe_convenience_readwrite_double", + "pipe_convenience_readwrite_struct", + "pipe_info", + "pipe_max_args", + "pipe_max_packet_size", + "pipe_max_active_reservations", + "pipe_query_functions", + "pipe_readwrite_errors", + "pipe_subgroups_divergence", +}; + +ct_assert((sizeof(pipefn_names) / sizeof(pipefn_names[0])) == (sizeof(pipefn_list) / sizeof(pipefn_list[0]))); + +int num_pipefns = sizeof(pipefn_names) / sizeof(char *); + +int main( int argc, const char *argv[] ) +{ + return runTestHarness( argc, argv, num_pipefns, pipefn_list, pipefn_names, + false, false, 0 ); +} diff --git a/test_conformance/pipes/procs.h b/test_conformance/pipes/procs.h new file mode 100644 index 00000000..39c1e5c4 --- /dev/null +++ b/test_conformance/pipes/procs.h @@ -0,0 +1,92 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef __PROCS_H__ +#define __PROCS_H__ + +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/mt19937.h" +#include "../../test_common/harness/conversions.h" + +#ifndef __APPLE__ +#include +#endif + +extern int test_pipe_readwrite_int( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_readwrite_uint( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_readwrite_long( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_readwrite_ulong( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_readwrite_short( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_readwrite_ushort( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_readwrite_float( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_readwrite_half( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_readwrite_char( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_readwrite_uchar( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_readwrite_double( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_readwrite_struct( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); + +extern int test_pipe_workgroup_readwrite_int( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_workgroup_readwrite_uint( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_workgroup_readwrite_long( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_workgroup_readwrite_ulong( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_workgroup_readwrite_short( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_workgroup_readwrite_ushort( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_workgroup_readwrite_float( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_workgroup_readwrite_half( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_workgroup_readwrite_char( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_workgroup_readwrite_uchar( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_workgroup_readwrite_double( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_workgroup_readwrite_struct( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); + +extern int test_pipe_subgroup_readwrite_int( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_subgroup_readwrite_uint( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_subgroup_readwrite_long( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_subgroup_readwrite_ulong( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_subgroup_readwrite_short( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_subgroup_readwrite_ushort( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_subgroup_readwrite_float( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_subgroup_readwrite_half( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_subgroup_readwrite_char( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_subgroup_readwrite_uchar( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_subgroup_readwrite_double( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_subgroup_readwrite_struct( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); + +extern int test_pipe_convenience_readwrite_int( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_convenience_readwrite_uint( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_convenience_readwrite_long( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_convenience_readwrite_ulong( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_convenience_readwrite_short( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_convenience_readwrite_ushort( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_convenience_readwrite_float( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_convenience_readwrite_half( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_convenience_readwrite_char( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_convenience_readwrite_uchar( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_convenience_readwrite_double( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_convenience_readwrite_struct( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); + +extern int test_pipe_info( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_pipe_max_args(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_pipe_max_packet_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_pipe_max_active_reservations(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_pipe_query_functions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_pipe_readwrite_errors(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_pipe_subgroups_divergence(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + + +#endif // #ifndef __PROCS_H__ + diff --git a/test_conformance/pipes/test_pipe_info.c b/test_conformance/pipes/test_pipe_info.c new file mode 100644 index 00000000..5d3e3a49 --- /dev/null +++ b/test_conformance/pipes/test_pipe_info.c @@ -0,0 +1,109 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "procs.h" + +const char* pipe_kernel_code = { + "__kernel void pipe_kernel(__write_only pipe int out_pipe)\n" + "{}\n" }; + +int test_pipe_info( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_mem pipe; + cl_int err; + cl_uint pipe_width = 512; + cl_uint pipe_depth = 1024; + cl_uint returnVal; + cl_program program; + cl_kernel kernel; + + pipe = clCreatePipe(context, CL_MEM_HOST_NO_ACCESS, pipe_width, pipe_depth, NULL, &err); + test_error(err, "clCreatePipe failed."); + + err = clGetPipeInfo(pipe, CL_PIPE_PACKET_SIZE, sizeof(pipe_width), (void *)&returnVal, NULL); + if ( err ) + { + log_error( "Error calling clGetPipeInfo(): %d\n", err ); + clReleaseMemObject(pipe); + return -1; + } + + if(pipe_width != returnVal) + { + log_error( "Error in clGetPipeInfo() check of pipe packet size\n" ); + clReleaseMemObject(pipe); + return -1; + } + else + { + log_info( " CL_PIPE_PACKET_SIZE passed.\n" ); + } + + err = clGetPipeInfo(pipe, CL_PIPE_MAX_PACKETS, sizeof(pipe_depth), (void *)&returnVal, NULL); + if ( err ) + { + log_error( "Error calling clGetPipeInfo(): %d\n", err ); + clReleaseMemObject(pipe); + return -1; + } + + if(pipe_depth != returnVal) + { + log_error( "Error in clGetPipeInfo() check of pipe max packets\n" ); + clReleaseMemObject(pipe); + return -1; + } + else + { + log_info( " CL_PIPE_MAX_PACKETS passed.\n" ); + } + + err = create_single_kernel_helper_with_build_options(context, &program, &kernel, 1, (const char**)&pipe_kernel_code, "pipe_kernel", "-cl-std=CL2.0 -cl-kernel-arg-info"); + if(err) + { + clReleaseMemObject(pipe); + print_error(err, "Error creating program\n"); + return -1; + } + + cl_kernel_arg_type_qualifier arg_type_qualifier = 0; + cl_kernel_arg_type_qualifier expected_type_qualifier = CL_KERNEL_ARG_TYPE_PIPE; + err = clGetKernelArgInfo( kernel, 0, CL_KERNEL_ARG_TYPE_QUALIFIER, sizeof(arg_type_qualifier), &arg_type_qualifier, NULL ); + if(err) + { + clReleaseMemObject(pipe); + clReleaseKernel(kernel); + clReleaseProgram(program); + print_error(err, "clSetKernelArg failed\n"); + return -1; + } + err = (arg_type_qualifier != expected_type_qualifier); + if(err) + { + clReleaseMemObject(pipe); + clReleaseKernel(kernel); + clReleaseProgram(program); + print_error(err, "ERROR: Bad type qualifier\n"); + return -1; + } + + // cleanup + clReleaseMemObject(pipe); + clReleaseKernel(kernel); + clReleaseProgram(program); + + return err; + +} diff --git a/test_conformance/pipes/test_pipe_limits.c b/test_conformance/pipes/test_pipe_limits.c new file mode 100644 index 00000000..2c3ad581 --- /dev/null +++ b/test_conformance/pipes/test_pipe_limits.c @@ -0,0 +1,1085 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/errorHelpers.h" + +#define STRING_LENGTH 1024 + +void createKernelSourceCode(char *source, int num_pipes) +{ + int i; + char str[256]; + int str_length; + + strcpy(source, "__kernel void test_multiple_pipe_write(__global int *src, "); + + for(i = 0; i < num_pipes; i++) { + sprintf(str, "__write_only pipe int pipe%d, ", i); + strcat(source, str); + } + sprintf(str, "int num_pipes ) \n{\n int gid = get_global_id(0);\n reserve_id_t res_id;\n\n"); + strcat(source, str); + sprintf(str, " if(gid < (get_global_size(0))/num_pipes)\n {\n res_id = reserve_write_pipe(pipe0, 1);\n if(is_valid_reserve_id(res_id))\n {\n"); + strcat(source, str); + sprintf(str, " write_pipe(pipe0, res_id, 0, &src[gid]);\n commit_write_pipe(pipe0, res_id);\n }\n }\n"); + strcat(source, str); + for(i = 1; i < num_pipes; i++){ + sprintf(str, " else if(gid < (%d*get_global_size(0))/num_pipes)\n {\n res_id = reserve_write_pipe(pipe%d, 1);\n if(is_valid_reserve_id(res_id))\n {\n", i+1, i); + strcat(source, str); + sprintf(str, " write_pipe(pipe%d, res_id, 0, &src[gid]);\n commit_write_pipe(pipe%d, res_id);\n }\n }\n", i, i); + strcat(source, str); + } + strcat(source, "}\n\n__kernel void test_multiple_pipe_read(__global int *dst, "); + + for(i = 0; i < num_pipes; i++) { + sprintf(str, "__read_only pipe int pipe%d, ", i); + strcat(source, str); + } + sprintf(str, "int num_pipes ) \n{\n int gid = get_global_id(0);\n reserve_id_t res_id;\n\n"); + strcat(source, str); + sprintf(str, " if(gid < (get_global_size(0))/num_pipes)\n {\n res_id = reserve_read_pipe(pipe0, 1);\n if(is_valid_reserve_id(res_id))\n {\n"); + strcat(source, str); + sprintf(str, " read_pipe(pipe0, res_id, 0, &dst[gid]);\n commit_read_pipe(pipe0, res_id);\n }\n }\n"); + strcat(source, str); + for(i = 1; i < num_pipes; i++){ + sprintf(str, " else if(gid < (%d*get_global_size(0))/num_pipes)\n {\n res_id = reserve_read_pipe(pipe%d, 1);\n if(is_valid_reserve_id(res_id))\n {\n", i+1, i); + strcat(source, str); + sprintf(str, " read_pipe(pipe%d, res_id, 0, &dst[gid]);\n commit_read_pipe(pipe%d, res_id);\n }\n }\n", i, i); + strcat(source, str); + } + strcat(source, "}"); + + str_length = strlen(source); + assert(str_length <= STRING_LENGTH*num_pipes); +} + +static int verify_result(void *ptr1, void *ptr2, int n) +{ + int i; + int sum_input = 0, sum_output = 0; + cl_char *inptr = (cl_char *)ptr1; + cl_char *outptr = (cl_char *)ptr2; + + for(i = 0; i < n; i++) + { + sum_input += inptr[i]; + sum_output += outptr[i]; + } + if(sum_input != sum_output){ + return -1; + } + return 0; +} + +static int verify_result_int(void *ptr1, void *ptr2, int n) +{ + int i; + int sum_input = 0, sum_output = 0; + cl_int *inptr = (cl_int *)ptr1; + cl_int *outptr = (cl_int *)ptr2; + + for(i = 0; i < n; i++) + { + sum_input += inptr[i]; + sum_output += outptr[i]; + } + if(sum_input != sum_output){ + return -1; + } + return 0; +} + +int test_pipe_max_args(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + + cl_mem pipes[1024]; + cl_mem buffers[2]; + void *outptr; + cl_int *inptr; + cl_program program; + cl_kernel kernel[2]; + size_t global_work_size[3]; + cl_int err; + cl_int size; + int num_pipe_elements = 1024; + int i, j; + int max_pipe_args; + char *source; + cl_event producer_sync_event = NULL; + cl_event consumer_sync_event = NULL; + MTdata d = init_genrand( gRandomSeed ); + const char* kernelName[] = {"test_multiple_pipe_write", "test_multiple_pipe_read"}; + + size_t min_alignment = get_min_alignment(context); + + err = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_PIPE_ARGS, sizeof(max_pipe_args), (void*)&max_pipe_args, NULL); + if(err){ + print_error(err, " clGetDeviceInfo failed\n"); + return -1; + } + if(max_pipe_args < 16){ + log_error("The device should support minimum 16 pipe objects that could be passed as arguments to the kernel"); + return -1; + } + + global_work_size[0] = (cl_uint)num_pipe_elements * max_pipe_args; + size = sizeof(int) * num_pipe_elements * max_pipe_args; + source = (char *)malloc(STRING_LENGTH * sizeof(char) * max_pipe_args); + + inptr = (cl_int *)align_malloc(size, min_alignment); + + for(i = 0; i < num_pipe_elements * max_pipe_args; i++){ + inptr[i] = (int)genrand_int32(d); + } + + buffers[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, size, inptr, &err); + if(err){ + clReleaseMemObject(buffers[0]); + free(source); + print_error(err, " clCreateBuffer failed\n"); + return -1; + } + outptr = align_malloc(size, min_alignment); + buffers[1] = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, size, outptr, &err); + if ( err ){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free( outptr ); + free(source); + print_error(err, " clCreateBuffer failed\n" ); + return -1; + } + + for(i = 0; i < max_pipe_args; i++){ + pipes[i] = clCreatePipe(context, CL_MEM_HOST_NO_ACCESS, sizeof(int), num_pipe_elements, NULL, &err); + if(err){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free( outptr ); + free(source); + for(j = 0; j < i; j++) { + clReleaseMemObject(pipes[j]); + } + print_error(err, " clCreatePipe failed\n"); + return -1; + } + } + + createKernelSourceCode(source, max_pipe_args); + + // Create producer kernel + err = create_single_kernel_helper_with_build_options(context, &program, &kernel[0], 1, (const char**)&source, kernelName[0], "-cl-std=CL2.0"); + if(err){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + for(j = 0; j < max_pipe_args; j++) { + clReleaseMemObject(pipes[j]); + } + align_free(outptr); + free(source); + print_error(err, "Error creating program\n"); + return -1; + } + //Create consumer kernel + kernel[1] = clCreateKernel(program, kernelName[1], &err); + if( kernel[1] == NULL || err != CL_SUCCESS) + { + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + for(j = 0; j < max_pipe_args; j++) { + clReleaseMemObject(pipes[j]); + } + align_free(outptr); + free(source); + print_error(err, " Error creating kernel\n"); + return -1; + } + + err = clSetKernelArg(kernel[0], 0, sizeof(cl_mem), (void*)&buffers[0]); + for( i = 0; i < max_pipe_args; i++){ + err |= clSetKernelArg(kernel[0], i+1, sizeof(cl_mem), (void*)&pipes[i]); + } + err |= clSetKernelArg(kernel[0], max_pipe_args + 1, sizeof(int), (void*)&max_pipe_args); + err |= clSetKernelArg(kernel[1], 0, sizeof(cl_mem), (void*)&buffers[1]); + for( i = 0; i < max_pipe_args; i++){ + err |= clSetKernelArg(kernel[1], i+1, sizeof(cl_mem), (void*)&pipes[i]); + } + err |= clSetKernelArg(kernel[1], max_pipe_args + 1, sizeof(int), (void*)&max_pipe_args); + if ( err != CL_SUCCESS ){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + for(j = 0; j < max_pipe_args; j++) { + clReleaseMemObject(pipes[j]); + } + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseProgram(program); + align_free(outptr); + free(source); + print_error(err, " clSetKernelArg failed"); + return -1; + } + + // Launch Producer kernel + err = clEnqueueNDRangeKernel( queue, kernel[0], 1, NULL, global_work_size, NULL, 0, NULL, &producer_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + for(j = 0; j < max_pipe_args; j++) { + clReleaseMemObject(pipes[j]); + } + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + free(source); + return -1; + } + + // Launch Consumer kernel + err = clEnqueueNDRangeKernel( queue, kernel[1], 1, NULL, global_work_size, NULL, 1, &producer_sync_event, &consumer_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + for(j = 0; j < max_pipe_args; j++) { + clReleaseMemObject(pipes[j]); + } + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + free(source); + return -1; + } + + err = clEnqueueReadBuffer(queue, buffers[1], true, 0, size, outptr, 1, &consumer_sync_event, NULL); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + for(j = 0; j < max_pipe_args; j++) { + clReleaseMemObject(pipes[j]); + } + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + free(source); + return -1; + } + + err = clWaitForEvents(1, &consumer_sync_event); + if ( err != CL_SUCCESS ){ + print_error( err, " clWaitForEvents failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + for(j = 0; j < max_pipe_args; j++) { + clReleaseMemObject(pipes[j]); + } + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + free(source); + return -1; + } + + if( verify_result( inptr, outptr, num_pipe_elements*sizeof(cl_int))){ + log_error("test_pipe_max_args failed\n"); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + for(j = 0; j < max_pipe_args; j++) { + clReleaseMemObject(pipes[j]); + } + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + free(source); + return -1; + } + else { + log_info("test_pipe_max_args passed\n"); + } + //cleanup + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + for(j = 0; j < max_pipe_args; j++) { + clReleaseMemObject(pipes[j]); + } + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + free(source); + + return 0; +} + + +int test_pipe_max_packet_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem pipe; + cl_mem buffers[2]; + void *outptr; + cl_char *inptr; + cl_program program; + cl_kernel kernel[2]; + size_t global_work_size[3]; + cl_int err; + size_t size; + int num_pipe_elements = 1024; + int i; + cl_uint max_pipe_packet_size; + char *source; + char str[256]; + int str_length; + cl_event producer_sync_event = NULL; + cl_event consumer_sync_event = NULL; + MTdata d = init_genrand( gRandomSeed ); + const char* kernelName[] = {"test_pipe_max_packet_size_write", "test_pipe_max_packet_size_read"}; + + size_t min_alignment = get_min_alignment(context); + + global_work_size[0] = (cl_uint)num_pipe_elements; + + source = (char*)malloc(STRING_LENGTH*sizeof(char)); + + err = clGetDeviceInfo(deviceID, CL_DEVICE_PIPE_MAX_PACKET_SIZE, sizeof(max_pipe_packet_size), (void*)&max_pipe_packet_size, NULL); + if(err){ + print_error(err, " clGetDeviceInfo failed\n"); + return -1; + } + if(max_pipe_packet_size < 1024){ + log_error("The device should support minimum packet size of 1024 bytes"); + return -1; + } + + if(max_pipe_packet_size > (32*1024*1024/num_pipe_elements)) + { + max_pipe_packet_size = 32*1024*1024/num_pipe_elements; + } + + size = max_pipe_packet_size * num_pipe_elements; + + inptr = (cl_char *)align_malloc(size, min_alignment); + + for(i = 0; i < size; i++){ + inptr[i] = (char)genrand_int32(d); + } + + buffers[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, size, inptr, &err); + if(err){ + clReleaseMemObject(buffers[0]); + free(source); + print_error(err, " clCreateBuffer failed\n"); + return -1; + } + outptr = align_malloc(size, min_alignment); + buffers[1] = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, size, outptr, &err); + if ( err ){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free( outptr ); + free(source); + print_error(err, " clCreateBuffer failed\n" ); + return -1; + } + + pipe = clCreatePipe(context, CL_MEM_HOST_NO_ACCESS, max_pipe_packet_size, num_pipe_elements, NULL, &err); + if(err){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free( outptr ); + free(source); + clReleaseMemObject(pipe); + print_error(err, " clCreatePipe failed\n"); + return -1; + } + + sprintf(str, "typedef struct{\n char a[%d];\n}TestStruct;\n\n__kernel void test_pipe_max_packet_size_write(__global TestStruct *src, __write_only pipe TestStruct out_pipe)\n{\n", max_pipe_packet_size); + strcpy(source,str); + strcat(source, " int gid = get_global_id(0);\n reserve_id_t res_id;\n\n"); + sprintf(str, " res_id = reserve_write_pipe(out_pipe, 1);\n if(is_valid_reserve_id(res_id))\n {\n"); + strcat(source, str); + sprintf(str, " write_pipe(out_pipe, res_id, 0, &src[gid]);\n commit_write_pipe(out_pipe, res_id);\n }\n}\n\n"); + strcat(source, str); + sprintf(str, "__kernel void test_pipe_max_packet_size_read(__read_only pipe TestStruct in_pipe, __global TestStruct *dst)\n{\n"); + strcat(source, str); + strcat(source, " int gid = get_global_id(0);\n reserve_id_t res_id;\n\n"); + sprintf(str, " res_id = reserve_read_pipe(in_pipe, 1);\n if(is_valid_reserve_id(res_id))\n {\n"); + strcat(source, str); + sprintf(str, " read_pipe(in_pipe, res_id, 0, &dst[gid]);\n commit_read_pipe(in_pipe, res_id);\n }\n}\n\n"); + strcat(source, str); + + str_length = strlen(source); + assert(str_length <= STRING_LENGTH); + + // Create producer kernel + err = create_single_kernel_helper_with_build_options(context, &program, &kernel[0], 1, (const char**)&source, kernelName[0], "-cl-std=CL2.0"); + if(err){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(pipe); + align_free(outptr); + free(source); + print_error(err, "Error creating program\n"); + return -1; + } + //Create consumer kernel + kernel[1] = clCreateKernel(program, kernelName[1], &err); + if( kernel[1] == NULL || err != CL_SUCCESS) + { + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(pipe); + align_free(outptr); + free(source); + print_error(err, "Error creating kernel\n"); + return -1; + } + + err = clSetKernelArg(kernel[0], 0, sizeof(cl_mem), (void*)&buffers[0]); + err |= clSetKernelArg(kernel[0], 1, sizeof(cl_mem), (void*)&pipe); + err |= clSetKernelArg(kernel[1], 0, sizeof(cl_mem), (void*)&pipe); + err |= clSetKernelArg(kernel[1], 1, sizeof(cl_mem), (void*)&buffers[1]); + if ( err != CL_SUCCESS ){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseProgram(program); + align_free(outptr); + free(source); + print_error(err, " clSetKernelArg failed"); + return -1; + } + + // Launch Producer kernel + err = clEnqueueNDRangeKernel( queue, kernel[0], 1, NULL, global_work_size, NULL, 0, NULL, &producer_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + free(source); + return -1; + } + + // Launch Consumer kernel + err = clEnqueueNDRangeKernel( queue, kernel[1], 1, NULL, global_work_size, NULL, 1, &producer_sync_event, &consumer_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + free(source); + return -1; + } + + err = clEnqueueReadBuffer(queue, buffers[1], true, 0, size, outptr, 1, &consumer_sync_event, NULL); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + free(source); + return -1; + } + + if( verify_result( inptr, outptr, size)){ + log_error("test_pipe_max_packet_size failed\n"); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + free(source); + return -1; + } + else { + log_info("test_pipe_max_packet_size passed\n"); + } + //cleanup + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + free(source); + + return 0; +} + +int test_pipe_max_active_reservations(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem pipe; + cl_mem buffers[2]; + cl_mem buf_reservations; + cl_mem buf_status; + cl_mem buf_reserve_id_t_size; + cl_mem buf_reserve_id_t_size_aligned; + cl_int *inptr; + void *outptr; + int size, i; + cl_program program; + cl_kernel kernel[3]; + size_t global_work_size[3]; + cl_int err; + int status = 0; + cl_uint max_active_reservations = 0; + cl_ulong max_global_size = 0; + int reserve_id_t_size; + int temp; + char *source; + char str[256]; + int str_length; + cl_event sync_event = NULL; + cl_event read_event = NULL; + MTdata d = init_genrand( gRandomSeed ); + const char* kernelName[3] = {"test_pipe_max_active_reservations_write", "test_pipe_max_active_reservations_read", "pipe_get_reserve_id_t_size"}; + + size_t min_alignment = get_min_alignment(context); + + source = (char*)malloc(2*STRING_LENGTH*sizeof(char)); + + global_work_size[0] = 1; + + err = clGetDeviceInfo(deviceID, CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS, sizeof(max_active_reservations), (void*)&max_active_reservations, NULL); + if(err){ + print_error(err, " clGetDeviceInfo failed\n"); + return -1; + } + + err = clGetDeviceInfo(deviceID, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(max_global_size), (void*)&max_global_size, NULL); + if(err){ + print_error(err, " clGetDeviceInfo failed\n"); + return -1; + } + + max_active_reservations = (max_active_reservations > max_global_size) ? 1<<16 : max_active_reservations; + + if(max_active_reservations < 1){ + log_error("The device should support minimum active reservations of 1"); + return -1; + } + + // To get reserve_id_t size + buf_reserve_id_t_size = clCreateBuffer(context, CL_MEM_HOST_READ_ONLY, sizeof(reserve_id_t_size), NULL, &err); + if ( err ){ + clReleaseMemObject(buf_reserve_id_t_size); + print_error(err, " clCreateBuffer failed\n" ); + return -1; + } + + sprintf(str, "__kernel void test_pipe_max_active_reservations_write(__global int *src, __write_only pipe int out_pipe, __global char *reserve_id, __global int *reserve_id_t_size_aligned, __global int *status)\n{\n"); + strcpy(source,str); + sprintf(str, " __global reserve_id_t *res_id_ptr;\n int reserve_idx;\n int commit_idx;\n"); + strcat(source, str); + sprintf(str, " for(reserve_idx = 0; reserve_idx < %d; reserve_idx++)\n {\n", max_active_reservations); + strcat(source, str); + sprintf(str, " res_id_ptr = (__global reserve_id_t*)(reserve_id + reserve_idx*reserve_id_t_size_aligned[0]);\n"); + strcat(source, str); + sprintf(str, " *res_id_ptr = reserve_write_pipe(out_pipe, 1);\n"); + strcat(source, str); + sprintf(str, " if(is_valid_reserve_id(res_id_ptr[0]))\n {\n write_pipe(out_pipe, res_id_ptr[0], 0, &src[reserve_idx]);\n }\n"); + strcat(source, str); + sprintf(str, " else\n {\n *status = -1;\n return;\n }\n }\n"); + strcat(source, str); + sprintf(str, " for(commit_idx = 0; commit_idx < %d; commit_idx++)\n {\n", max_active_reservations); + strcat(source, str); + sprintf(str, " res_id_ptr = (__global reserve_id_t*)(reserve_id + commit_idx*reserve_id_t_size_aligned[0]);\n"); + strcat(source, str); + sprintf(str, " commit_write_pipe(out_pipe, res_id_ptr[0]);\n }\n}\n\n"); + strcat(source, str); + sprintf(str, "__kernel void test_pipe_max_active_reservations_read(__read_only pipe int in_pipe, __global int *dst, __global char *reserve_id, __global int *reserve_id_t_size_aligned, __global int *status)\n{\n"); + strcat(source, str); + sprintf(str, " __global reserve_id_t *res_id_ptr;\n int reserve_idx;\n int commit_idx;\n"); + strcat(source, str); + sprintf(str, " for(reserve_idx = 0; reserve_idx < %d; reserve_idx++)\n {\n", max_active_reservations); + strcat(source, str); + sprintf(str, " res_id_ptr = (__global reserve_id_t*)(reserve_id + reserve_idx*reserve_id_t_size_aligned[0]);\n"); + strcat(source, str); + sprintf(str, " *res_id_ptr = reserve_read_pipe(in_pipe, 1);\n"); + strcat(source, str); + sprintf(str, " if(is_valid_reserve_id(res_id_ptr[0]))\n {\n read_pipe(in_pipe, res_id_ptr[0], 0, &dst[reserve_idx]);\n }\n"); + strcat(source, str); + sprintf(str, " else\n {\n *status = -1;\n return;\n }\n }\n"); + strcat(source, str); + sprintf(str, " for(commit_idx = 0; commit_idx < %d; commit_idx++)\n {\n", max_active_reservations); + strcat(source, str); + sprintf(str, " res_id_ptr = (__global reserve_id_t*)(reserve_id + commit_idx*reserve_id_t_size_aligned[0]);\n"); + strcat(source, str); + sprintf(str, " commit_read_pipe(in_pipe, res_id_ptr[0]);\n }\n}\n\n"); + strcat(source, str); + sprintf(str, "__kernel void pipe_get_reserve_id_t_size(__global int *reserve_id_t_size) \n"); + strcat(source, str); + sprintf(str, "{\n *reserve_id_t_size = sizeof(reserve_id_t);\n}\n"); + strcat(source, str); + + str_length = strlen(source); + assert(str_length <= 2*STRING_LENGTH); + + // Create producer kernel + err = create_single_kernel_helper_with_build_options(context, &program, &kernel[0], 1, (const char**)&source, kernelName[0], "-cl-std=CL2.0"); + if(err){ + clReleaseMemObject(buf_reserve_id_t_size); + print_error(err, "Error creating program\n"); + return -1; + } + + // Create consumer kernel + kernel[1] = clCreateKernel(program, kernelName[1], &err); + if( kernel[1] == NULL || err != CL_SUCCESS) + { + clReleaseMemObject(buf_reserve_id_t_size); + print_error(err, "Error creating kernel\n"); + return -1; + } + + // Create size query kernel for reserve_id_t + kernel[2] = clCreateKernel(program, kernelName[2], &err); + if( kernel[2] == NULL || err != CL_SUCCESS) + { + clReleaseMemObject(buf_reserve_id_t_size); + print_error(err, "Error creating kernel\n"); + return -1; + } + err = clSetKernelArg(kernel[2], 0, sizeof(cl_mem), (void*)&buf_reserve_id_t_size); + if(err){ + clReleaseMemObject(buf_reserve_id_t_size); + print_error(err, "Error creating program\n"); + return -1; + } + //Launch size query kernel for reserve_id_t + err = clEnqueueNDRangeKernel( queue, kernel[2], 1, NULL, global_work_size, NULL, 0, NULL, &sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(sync_event); + clReleaseProgram(program); + return -1; + } + + err = clEnqueueReadBuffer(queue, buf_reserve_id_t_size, true, 0, sizeof(reserve_id_t_size), &reserve_id_t_size, 1, &sync_event, &read_event); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed" ); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(sync_event); + clReleaseProgram(program); + return -1; + } + + err = clWaitForEvents(1, &read_event); + if ( err != CL_SUCCESS ){ + print_error( err, " clWaitForEvents failed" ); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(sync_event); + clReleaseEvent(read_event); + clReleaseProgram(program); + return -1; + } + + // Round reserve_id_t_size to the nearest power of 2 + temp = 1; + while(temp < reserve_id_t_size) + temp *= 2; + reserve_id_t_size = temp; + + size = sizeof(cl_int) * max_active_reservations; + inptr = (cl_int *)align_malloc(size, min_alignment); + + for(i = 0; i < max_active_reservations; i++){ + inptr[i] = (int)genrand_int32(d); + } + + buffers[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, size, inptr, &err); + if ( err ){ + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buffers[0]); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(sync_event); + clReleaseEvent(read_event); + clReleaseProgram(program); + print_error(err, " clCreateBuffer failed\n" ); + return -1; + } + + outptr = align_malloc(size, min_alignment); + buffers[1] = clCreateBuffer(context, CL_MEM_HOST_READ_ONLY, size, NULL, &err); + if ( err ){ + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(sync_event); + clReleaseEvent(read_event); + clReleaseProgram(program); + align_free(outptr); + print_error(err, " clCreateBuffer failed\n" ); + return -1; + } + + buf_reserve_id_t_size_aligned = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, sizeof(reserve_id_t_size), &reserve_id_t_size, &err); + if ( err ){ + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buf_reserve_id_t_size_aligned); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(sync_event); + clReleaseEvent(read_event); + clReleaseProgram(program); + print_error(err, " clCreateBuffer failed\n" ); + return -1; + } + + //For error status + buf_status = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, sizeof(int), &status, &err); + if ( err ){ + clReleaseMemObject(buf_status); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buf_reserve_id_t_size_aligned); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free(outptr); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(sync_event); + clReleaseEvent(read_event); + clReleaseProgram(program); + print_error(err, " clCreateBuffer failed\n" ); + return -1; + } + + pipe = clCreatePipe(context, CL_MEM_HOST_NO_ACCESS, sizeof(int), max_active_reservations, NULL, &err); + if(err){ + clReleaseMemObject(buf_status); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buf_reserve_id_t_size_aligned); + clReleaseMemObject(pipe); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free(outptr); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(sync_event); + clReleaseEvent(read_event); + clReleaseProgram(program); + print_error(err, " clCreatePipe failed\n"); + return -1; + } + + // Global buffer to hold all active reservation ids + buf_reservations = clCreateBuffer(context, CL_MEM_HOST_NO_ACCESS, reserve_id_t_size*max_active_reservations, NULL, &err); + if ( err != CL_SUCCESS ){ + print_error( err, " clCreateBuffer failed" ); + clReleaseMemObject(buf_status); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buf_reserve_id_t_size_aligned); + clReleaseMemObject(buf_reservations); + clReleaseMemObject(pipe); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free(outptr); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(sync_event); + clReleaseEvent(read_event); + clReleaseProgram(program); + return -1; + } + + err = clSetKernelArg(kernel[0], 0, sizeof(cl_mem), (void*)&buffers[0]); + err |= clSetKernelArg(kernel[0], 1, sizeof(cl_mem), (void*)&pipe); + err |= clSetKernelArg(kernel[0], 2, sizeof(cl_mem), (void*)&buf_reservations); + err |= clSetKernelArg(kernel[0], 3, sizeof(cl_mem), (void*)&buf_reserve_id_t_size_aligned); + err |= clSetKernelArg(kernel[0], 4, sizeof(cl_mem), (void*)&buf_status); + if ( err != CL_SUCCESS ){ + clReleaseMemObject(buf_status); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buf_reserve_id_t_size_aligned); + clReleaseMemObject(buf_reservations); + clReleaseMemObject(pipe); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free(outptr); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseProgram(program); + print_error(err, " clSetKernelArg failed"); + return -1; + } + + err = clSetKernelArg(kernel[1], 0, sizeof(cl_mem), (void*)&pipe); + err |= clSetKernelArg(kernel[1], 1, sizeof(cl_mem), (void*)&buffers[1]); + err |= clSetKernelArg(kernel[1], 2, sizeof(cl_mem), (void*)&buf_reservations); + err |= clSetKernelArg(kernel[1], 3, sizeof(cl_mem), (void*)&buf_reserve_id_t_size_aligned); + err |= clSetKernelArg(kernel[1], 4, sizeof(cl_mem), (void*)&buf_status); + if ( err != CL_SUCCESS ){ + clReleaseMemObject(buf_status); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buf_reserve_id_t_size_aligned); + clReleaseMemObject(buf_reservations); + clReleaseMemObject(pipe); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free(outptr); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseProgram(program); + print_error(err, " clSetKernelArg failed"); + return -1; + } + + // Launch Producer kernel + err = clEnqueueNDRangeKernel(queue, kernel[0], 1, NULL, global_work_size, NULL, 0, NULL, &sync_event); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buf_status); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buf_reserve_id_t_size_aligned); + clReleaseMemObject(buf_reservations); + clReleaseMemObject(pipe); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free(outptr); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(sync_event); + clReleaseProgram(program); + return -1; + } + + err = clEnqueueReadBuffer(queue, buf_status, true, 0, sizeof(int), &status, 1, &sync_event, NULL); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed" ); + clReleaseMemObject(buf_status); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buf_reserve_id_t_size_aligned); + clReleaseMemObject(buf_reservations); + clReleaseMemObject(pipe); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free(outptr); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(sync_event); + clReleaseProgram(program); + return -1; + } + + if(status != 0) + { + log_error("test_pipe_max_active_reservations failed\n"); + clReleaseMemObject(buf_status); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buf_reserve_id_t_size_aligned); + clReleaseMemObject(buf_reservations); + clReleaseMemObject(pipe); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free(outptr); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(sync_event); + clReleaseProgram(program); + return -1; + } + + // Launch Consumer kernel + err = clEnqueueNDRangeKernel(queue, kernel[1], 1, NULL, global_work_size, NULL, 0, NULL, &sync_event); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buf_status); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buf_reserve_id_t_size_aligned); + clReleaseMemObject(buf_reservations); + clReleaseMemObject(pipe); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free(outptr); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(sync_event); + clReleaseProgram(program); + return -1; + } + + err = clEnqueueReadBuffer(queue, buf_status, true, 0, sizeof(int), &status, 1, &sync_event, NULL); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed" ); + clReleaseMemObject(buf_status); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buf_reserve_id_t_size_aligned); + clReleaseMemObject(buf_reservations); + clReleaseMemObject(pipe); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free(outptr); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(sync_event); + clReleaseProgram(program); + return -1; + } + + if(status != 0) + { + log_error("test_pipe_max_active_reservations failed\n"); + clReleaseMemObject(buf_status); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buf_reserve_id_t_size_aligned); + clReleaseMemObject(buf_reservations); + clReleaseMemObject(pipe); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free(outptr); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(sync_event); + clReleaseProgram(program); + return -1; + } + + err = clEnqueueReadBuffer(queue, buffers[1], true, 0, size, outptr, 1, &sync_event, NULL); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed" ); + clReleaseMemObject(buf_status); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buf_reserve_id_t_size_aligned); + clReleaseMemObject(buf_reservations); + clReleaseMemObject(pipe); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free(outptr); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(sync_event); + clReleaseProgram(program); + return -1; + } + + if( verify_result_int( inptr, outptr, max_active_reservations)){ + log_error("test_pipe_max_active_reservations failed\n"); + clReleaseMemObject(buf_status); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buf_reserve_id_t_size_aligned); + clReleaseMemObject(buf_reservations); + clReleaseMemObject(pipe); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free(outptr); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(sync_event); + clReleaseProgram(program); + return -1; + } + else { + log_info("test_pipe_max_active_reservations passed\n"); + } + + //cleanup + clReleaseMemObject(buf_status); + clReleaseMemObject(buf_reserve_id_t_size); + clReleaseMemObject(buf_reserve_id_t_size_aligned); + clReleaseMemObject(buf_reservations); + clReleaseMemObject(pipe); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free(outptr); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(sync_event); + clReleaseProgram(program); + return 0; +} \ No newline at end of file diff --git a/test_conformance/pipes/test_pipe_query_functions.c b/test_conformance/pipes/test_pipe_query_functions.c new file mode 100644 index 00000000..ce3baafd --- /dev/null +++ b/test_conformance/pipes/test_pipe_query_functions.c @@ -0,0 +1,544 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/errorHelpers.h" + +#define TEST_PRIME_INT ((1<<16)+1) + +const char* pipe_query_functions_kernel_code = { + "__kernel void test_pipe_write(__global int *src, __write_only pipe int out_pipe)\n" + "{\n" + " int gid = get_global_id(0);\n" + " reserve_id_t res_id;\n" + " res_id = reserve_write_pipe(out_pipe, 1);\n" + " if(is_valid_reserve_id(res_id))\n" + " {\n" + " write_pipe(out_pipe, res_id, 0, &src[gid]);\n" + " commit_write_pipe(out_pipe, res_id);\n" + " }\n" + "}\n" + "\n" + "__kernel void test_pipe_query_functions(__write_only pipe int out_pipe, __global int *num_packets, __global int *max_packets)\n" + "{\n" + " *max_packets = get_pipe_max_packets(out_pipe);\n" + " *num_packets = get_pipe_num_packets(out_pipe);\n" + "}\n" + "\n" + "__kernel void test_pipe_read(__read_only pipe int in_pipe, __global int *dst)\n" + "{\n" + " int gid = get_global_id(0);\n" + " reserve_id_t res_id;\n" + " res_id = reserve_read_pipe(in_pipe, 1);\n" + " if(is_valid_reserve_id(res_id))\n" + " {\n" + " read_pipe(in_pipe, res_id, 0, &dst[gid]);\n" + " commit_read_pipe(in_pipe, res_id);\n" + " }\n" + "}\n" }; + +static int verify_result(void *ptr1, void *ptr2, int n) +{ + int i, sum_output = 0; + cl_int *outptr1 = (int *)ptr1; + cl_int *outptr2 = (int *)ptr2; + int cmp_val = ((n*3)/2) * TEST_PRIME_INT; + + for(i = 0; i < n/2; i++) + { + sum_output += outptr1[i]; + } + for(i = 0; i < n; i++) + { + sum_output += outptr2[i]; + } + if(sum_output != cmp_val){ + return -1; + } + return 0; +} + +int test_pipe_query_functions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem pipe; + cl_mem buffers[4]; + void *outptr1; + void *outptr2; + cl_int *inptr; + cl_program program; + cl_kernel kernel[3]; + size_t global_work_size[3]; + size_t half_global_work_size[3]; + size_t global_work_size_pipe_query[3]; + cl_int pipe_max_packets, pipe_num_packets; + cl_int err; + cl_int size; + cl_int i; + cl_event producer_sync_event = NULL; + cl_event consumer_sync_event = NULL; + cl_event pipe_query_sync_event = NULL; + cl_event pipe_read_sync_event = NULL; + MTdata d = init_genrand( gRandomSeed ); + const char* kernelName[] = {"test_pipe_write", "test_pipe_read", "test_pipe_query_functions"}; + + size_t min_alignment = get_min_alignment(context); + + size = sizeof(int) * num_elements; + global_work_size[0] = (cl_uint)num_elements; + half_global_work_size[0] = (cl_uint)(num_elements / 2); + global_work_size_pipe_query[0] = 1; + + inptr = (int *)align_malloc(size, min_alignment); + + for(i = 0; i < num_elements; i++){ + inptr[i] = TEST_PRIME_INT; + } + + buffers[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, size, inptr, &err); + if(err){ + clReleaseMemObject(buffers[0]); + print_error(err, " clCreateBuffer failed\n"); + return -1; + } + outptr1 = align_malloc(size/2, min_alignment); + outptr2 = align_malloc(size, min_alignment); + buffers[1] = clCreateBuffer(context, CL_MEM_HOST_READ_ONLY, size, NULL, &err); + if ( err ){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free( outptr1 ); + print_error(err, " clCreateBuffer failed\n" ); + return -1; + } + + buffers[2] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(int), NULL, &err); + if ( err ){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + align_free( outptr1 ); + print_error(err, " clCreateBuffer failed\n" ); + return -1; + } + + buffers[3] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(int), NULL, &err); + if ( err ){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + align_free( outptr1 ); + print_error(err, " clCreateBuffer failed\n" ); + return -1; + } + + pipe = clCreatePipe(context, CL_MEM_HOST_NO_ACCESS, sizeof(int), num_elements, NULL, &err); + if(err){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + align_free( outptr1 ); + clReleaseMemObject(pipe); + print_error(err, " clCreatePipe failed\n"); + return -1; + } + + // Create producer kernel + err = create_single_kernel_helper_with_build_options(context, &program, &kernel[0], 1, (const char**)&pipe_query_functions_kernel_code, kernelName[0], "-cl-std=CL2.0"); + if(err){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + align_free(outptr1); + print_error(err, "Error creating program\n"); + return -1; + } + //Create consumer kernel + kernel[1] = clCreateKernel(program, kernelName[1], &err); + if( kernel[1] == NULL || err != CL_SUCCESS) + { + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + align_free(outptr1); + print_error(err, "Error creating kernel\n"); + return -1; + } + //Create pipe query functions kernel + kernel[2] = clCreateKernel(program, kernelName[2], &err); + if( kernel[1] == NULL || err != CL_SUCCESS) + { + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + align_free(outptr1); + print_error(err, "Error creating kernel\n"); + return -1; + } + + err = clSetKernelArg(kernel[0], 0, sizeof(cl_mem), (void*)&buffers[0]); + err |= clSetKernelArg(kernel[0], 1, sizeof(cl_mem), (void*)&pipe); + err |= clSetKernelArg(kernel[1], 0, sizeof(cl_mem), (void*)&pipe); + err |= clSetKernelArg(kernel[1], 1, sizeof(cl_mem), (void*)&buffers[1]); + err |= clSetKernelArg(kernel[2], 0, sizeof(cl_mem), (void*)&pipe); + err |= clSetKernelArg(kernel[2], 1, sizeof(cl_mem), (void*)&buffers[2]); + err |= clSetKernelArg(kernel[2], 2, sizeof(cl_mem), (void*)&buffers[3]); + + if ( err != CL_SUCCESS ){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseProgram(program); + align_free(outptr1); + print_error(err, " clSetKernelArg failed\n"); + return -1; + } + + // Launch Producer kernel + err = clEnqueueNDRangeKernel( queue, kernel[0], 1, NULL, global_work_size, NULL, 0, NULL, &producer_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed\n" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseEvent(pipe_query_sync_event); + clReleaseEvent(pipe_read_sync_event); + clReleaseProgram(program); + align_free(outptr1); + return -1; + } + + // Launch Pipe query kernel + err = clEnqueueNDRangeKernel( queue, kernel[2], 1, NULL, global_work_size_pipe_query, NULL, 1, &producer_sync_event, &pipe_query_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed\n" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseEvent(pipe_query_sync_event); + clReleaseEvent(pipe_read_sync_event); + clReleaseProgram(program); + align_free(outptr1); + return -1; + } + + err = clEnqueueReadBuffer(queue, buffers[2], true, 0, sizeof(cl_int), &pipe_num_packets, 1, &pipe_query_sync_event, NULL); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed\n" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseEvent(pipe_query_sync_event); + clReleaseEvent(pipe_read_sync_event); + clReleaseProgram(program); + align_free(outptr1); + return -1; + } + + + err = clEnqueueReadBuffer(queue, buffers[3], true, 0, sizeof(cl_int), &pipe_max_packets, 1, &pipe_query_sync_event, NULL); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed\n" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseEvent(pipe_query_sync_event); + clReleaseEvent(pipe_read_sync_event); + clReleaseProgram(program); + align_free(outptr1); + return -1; + } + + if(pipe_num_packets != num_elements || pipe_max_packets != num_elements) + { + log_error("test_pipe_query_functions failed\n"); + return -1; + } + + // Launch Consumer kernel with half the previous global size + err = clEnqueueNDRangeKernel( queue, kernel[1], 1, NULL, half_global_work_size, NULL, 1, &producer_sync_event, &consumer_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed\n" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseEvent(pipe_query_sync_event); + clReleaseEvent(pipe_read_sync_event); + clReleaseProgram(program); + align_free(outptr1); + return -1; + } + + err = clEnqueueReadBuffer(queue, buffers[1], true, 0, size / 2, outptr1, 1, &consumer_sync_event, NULL); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed\n" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseEvent(pipe_query_sync_event); + clReleaseEvent(pipe_read_sync_event); + clReleaseProgram(program); + align_free(outptr1); + return -1; + } + + // Launch Pipe query kernel + err = clEnqueueNDRangeKernel( queue, kernel[2], 1, NULL, global_work_size_pipe_query, NULL, 1, &consumer_sync_event, &pipe_query_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed\n" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseEvent(pipe_query_sync_event); + clReleaseEvent(pipe_read_sync_event); + clReleaseProgram(program); + align_free(outptr1); + return -1; + } + + err = clEnqueueReadBuffer(queue, buffers[2], true, 0, sizeof(cl_int), &pipe_num_packets, 1, &pipe_query_sync_event, &pipe_read_sync_event); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed\n" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseEvent(pipe_query_sync_event); + clReleaseEvent(pipe_read_sync_event); + clReleaseProgram(program); + align_free(outptr1); + return -1; + } + + // After consumer kernel consumes num_elements/2 from the pipe, + // there are (num_elements - num_elements/2) remaining package in the pipe. + if(pipe_num_packets != (num_elements - num_elements/2)) + { + log_error("test_pipe_query_functions failed\n"); + return -1; + } + + // Launch Producer kernel to fill the pipe again + global_work_size[0] = pipe_num_packets; + err = clEnqueueNDRangeKernel( queue, kernel[0], 1, NULL, global_work_size, NULL, 1, &pipe_read_sync_event, &producer_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed\n" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseEvent(pipe_query_sync_event); + clReleaseEvent(pipe_read_sync_event); + clReleaseProgram(program); + align_free(outptr1); + return -1; + } + + // Launch Pipe query kernel + err = clEnqueueNDRangeKernel( queue, kernel[2], 1, NULL, global_work_size_pipe_query, NULL, 1, &producer_sync_event, &pipe_query_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed\n" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseEvent(pipe_query_sync_event); + clReleaseEvent(pipe_read_sync_event); + clReleaseProgram(program); + align_free(outptr1); + return -1; + } + + err = clEnqueueReadBuffer(queue, buffers[2], true, 0, sizeof(cl_int), &pipe_num_packets, 1, &pipe_query_sync_event, &pipe_read_sync_event); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed\n" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseEvent(pipe_query_sync_event); + clReleaseEvent(pipe_read_sync_event); + clReleaseProgram(program); + align_free(outptr1); + return -1; + } + + if(pipe_num_packets != num_elements) + { + log_error("test_pipe_query_functions failed\n"); + return -1; + } + + // Launch Consumer kernel to consume all packets from pipe + global_work_size[0] = pipe_num_packets; + err = clEnqueueNDRangeKernel( queue, kernel[1], 1, NULL, global_work_size, NULL, 1, &pipe_read_sync_event, &consumer_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed\n" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseEvent(pipe_query_sync_event); + clReleaseEvent(pipe_read_sync_event); + clReleaseProgram(program); + align_free(outptr1); + return -1; + } + + err = clEnqueueReadBuffer(queue, buffers[1], true, 0, size, outptr2, 1, &consumer_sync_event, NULL); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed\n" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseEvent(pipe_query_sync_event); + clReleaseEvent(pipe_read_sync_event); + clReleaseProgram(program); + align_free(outptr1); + return -1; + } + + + if( verify_result(outptr1, outptr2, num_elements )){ + log_error("test_pipe_query_functions failed\n"); + return -1; + } + else { + log_info("test_pipe_query_functions passed\n"); + } + //cleanup + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(buffers[3]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseKernel(kernel[2]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseEvent(pipe_query_sync_event); + clReleaseEvent(pipe_read_sync_event); + clReleaseProgram(program); + align_free(outptr1); + + return 0; +} + diff --git a/test_conformance/pipes/test_pipe_read_write.c b/test_conformance/pipes/test_pipe_read_write.c new file mode 100644 index 00000000..9191aa0f --- /dev/null +++ b/test_conformance/pipes/test_pipe_read_write.c @@ -0,0 +1,1809 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" +#include "kernels.h" +#include "../../test_common/harness/errorHelpers.h" + +#ifndef uchar +typedef unsigned char uchar; +#endif + +typedef struct{ + char a; + int b; +} TestStruct; + +#define STRING_LENGTH 1024 + +static int useWorkgroupReserve = 0; +static int useSubgroupReserve = 0; +static int useConvenienceBuiltIn = 0; + +static const char* int_kernel_name[] = { "test_pipe_write_int", "test_pipe_read_int", "test_pipe_write_int2", "test_pipe_read_int2", "test_pipe_write_int4", "test_pipe_read_int4", "test_pipe_write_int8", "test_pipe_read_int8", "test_pipe_write_int16", "test_pipe_read_int16" }; +static const char* uint_kernel_name[] = { "test_pipe_write_uint", "test_pipe_read_uint", "test_pipe_write_uint2", "test_pipe_read_uint2", "test_pipe_write_uint4", "test_pipe_read_uint4", "test_pipe_write_uint8", "test_pipe_read_uint8", "test_pipe_write_uint16", "test_pipe_read_uint16" }; +static const char* long_kernel_name[] = { "test_pipe_write_long", "test_pipe_read_long", "test_pipe_write_long2", "test_pipe_read_long2", "test_pipe_write_long4", "test_pipe_read_long4", "test_pipe_write_long8", "test_pipe_read_long8", "test_pipe_write_long16", "test_pipe_read_long16" }; +static const char* ulong_kernel_name[] = { "test_pipe_write_ulong", "test_pipe_read_ulong", "test_pipe_write_ulong2", "test_pipe_read_ulong2", "test_pipe_write_ulong4", "test_pipe_read_ulong4", "test_pipe_write_ulong8", "test_pipe_read_ulong8", "test_pipe_write_ulong16", "test_pipe_read_ulong16" }; +static const char* char_kernel_name[] = { "test_pipe_write_char", "test_pipe_read_char", "test_pipe_write_char2", "test_pipe_read_char2", "test_pipe_write_char4", "test_pipe_read_char4", "test_pipe_write_char8", "test_pipe_read_char8", "test_pipe_write_char16", "test_pipe_read_char16" }; +static const char* uchar_kernel_name[] = { "test_pipe_write_uchar", "test_pipe_read_uchar", "test_pipe_write_uchar2", "test_pipe_read_uchar2", "test_pipe_write_uchar4", "test_pipe_read_uchar4", "test_pipe_write_uchar8", "test_pipe_read_uchar8", "test_pipe_write_uchar16", "test_pipe_read_uchar16" }; +static const char* short_kernel_name[] = { "test_pipe_write_short", "test_pipe_read_short", "test_pipe_write_short2", "test_pipe_read_short2", "test_pipe_write_short4", "test_pipe_read_short4", "test_pipe_write_short8", "test_pipe_read_short8", "test_pipe_write_short16", "test_pipe_read_short16" }; +static const char* ushort_kernel_name[] = { "test_pipe_write_ushort", "test_pipe_read_ushort", "test_pipe_write_ushort2", "test_pipe_read_ushort2", "test_pipe_write_ushort4", "test_pipe_read_ushort4", "test_pipe_write_ushort8", "test_pipe_read_ushort8", "test_pipe_write_ushort16", "test_pipe_read_ushort16" }; +static const char* float_kernel_name[] = { "test_pipe_write_float", "test_pipe_read_float", "test_pipe_write_float2", "test_pipe_read_float2", "test_pipe_write_float4", "test_pipe_read_float4", "test_pipe_write_float8", "test_pipe_read_float8", "test_pipe_write_float16", "test_pipe_read_float16" }; +static const char* half_kernel_name[] = { "test_pipe_write_half", "test_pipe_read_half", "test_pipe_write_half2", "test_pipe_read_half2", "test_pipe_write_half4", "test_pipe_read_half4", "test_pipe_write_half8", "test_pipe_read_half8", "test_pipe_write_half16", "test_pipe_read_half16" }; +static const char* double_kernel_name[] = { "test_pipe_write_double", "test_pipe_read_double", "test_pipe_write_double2", "test_pipe_read_double2", "test_pipe_write_double4", "test_pipe_read_double4", "test_pipe_write_double8", "test_pipe_read_double8", "test_pipe_write_double16", "test_pipe_read_double16" }; + +static const char* workgroup_int_kernel_name[] = { "test_pipe_workgroup_write_int", "test_pipe_workgroup_read_int", "test_pipe_workgroup_write_int2", "test_pipe_workgroup_read_int2", "test_pipe_workgroup_write_int4", "test_pipe_workgroup_read_int4", "test_pipe_workgroup_write_int8", "test_pipe_workgroup_read_int8", "test_pipe_workgroup_write_int16", "test_pipe_workgroup_read_int16" }; +static const char* workgroup_uint_kernel_name[] = { "test_pipe_workgroup_write_uint", "test_pipe_workgroup_read_uint", "test_pipe_workgroup_write_uint2", "test_pipe_workgroup_read_uint2", "test_pipe_workgroup_write_uint4", "test_pipe_workgroup_read_uint4", "test_pipe_workgroup_write_uint8", "test_pipe_workgroup_read_uint8", "test_pipe_workgroup_write_uint16", "test_pipe_workgroup_read_uint16" }; +static const char* workgroup_long_kernel_name[] = { "test_pipe_workgroup_write_long", "test_pipe_workgroup_read_long", "test_pipe_workgroup_write_long2", "test_pipe_workgroup_read_long2", "test_pipe_workgroup_write_long4", "test_pipe_workgroup_read_long4", "test_pipe_workgroup_write_long8", "test_pipe_workgroup_read_long8", "test_pipe_workgroup_write_long16", "test_pipe_workgroup_read_long16" }; +static const char* workgroup_ulong_kernel_name[] = { "test_pipe_workgroup_write_ulong", "test_pipe_workgroup_read_ulong", "test_pipe_workgroup_write_ulong2", "test_pipe_workgroup_read_ulong2", "test_pipe_workgroup_write_ulong4", "test_pipe_workgroup_read_ulong4", "test_pipe_workgroup_write_ulong8", "test_pipe_workgroup_read_ulong8", "test_pipe_workgroup_write_ulong16", "test_pipe_workgroup_read_ulong16" }; +static const char* workgroup_char_kernel_name[] = { "test_pipe_workgroup_write_char", "test_pipe_workgroup_read_char", "test_pipe_workgroup_write_char2", "test_pipe_workgroup_read_char2", "test_pipe_workgroup_write_char4", "test_pipe_workgroup_read_char4", "test_pipe_workgroup_write_char8", "test_pipe_workgroup_read_char8", "test_pipe_workgroup_write_char16", "test_pipe_workgroup_read_char16" }; +static const char* workgroup_uchar_kernel_name[] = { "test_pipe_workgroup_write_uchar", "test_pipe_workgroup_read_uchar", "test_pipe_workgroup_write_uchar2", "test_pipe_workgroup_read_uchar2", "test_pipe_workgroup_write_uchar4", "test_pipe_workgroup_read_uchar4", "test_pipe_workgroup_write_uchar8", "test_pipe_workgroup_read_uchar8", "test_pipe_workgroup_write_uchar16", "test_pipe_workgroup_read_uchar16" }; +static const char* workgroup_short_kernel_name[] = { "test_pipe_workgroup_write_short", "test_pipe_workgroup_read_short", "test_pipe_workgroup_write_short2", "test_pipe_workgroup_read_short2", "test_pipe_workgroup_write_short4", "test_pipe_workgroup_read_short4", "test_pipe_workgroup_write_short8", "test_pipe_workgroup_read_short8", "test_pipe_workgroup_write_short16", "test_pipe_workgroup_read_short16" }; +static const char* workgroup_ushort_kernel_name[] = { "test_pipe_workgroup_write_ushort", "test_pipe_workgroup_read_ushort", "test_pipe_workgroup_write_ushort2", "test_pipe_workgroup_read_ushort2", "test_pipe_workgroup_write_ushort4", "test_pipe_workgroup_read_ushort4", "test_pipe_workgroup_write_ushort8", "test_pipe_workgroup_read_ushort8", "test_pipe_workgroup_write_ushort16", "test_pipe_workgroup_read_ushort16" }; +static const char* workgroup_float_kernel_name[] = { "test_pipe_workgroup_write_float", "test_pipe_workgroup_read_float", "test_pipe_workgroup_write_float2", "test_pipe_workgroup_read_float2", "test_pipe_workgroup_write_float4", "test_pipe_workgroup_read_float4", "test_pipe_workgroup_write_float8", "test_pipe_workgroup_read_float8", "test_pipe_workgroup_write_float16", "test_pipe_workgroup_read_float16" }; +static const char* workgroup_half_kernel_name[] = { "test_pipe_workgroup_write_half", "test_pipe_workgroup_read_half", "test_pipe_workgroup_write_half2", "test_pipe_workgroup_read_half2", "test_pipe_workgroup_write_half4", "test_pipe_workgroup_read_half4", "test_pipe_workgroup_write_half8", "test_pipe_workgroup_read_half8", "test_pipe_workgroup_write_half16", "test_pipe_workgroup_read_half16" }; +static const char* workgroup_double_kernel_name[] = { "test_pipe_workgroup_write_double", "test_pipe_workgroup_read_double", "test_pipe_workgroup_write_double2", "test_pipe_workgroup_read_double2", "test_pipe_workgroup_write_double4", "test_pipe_workgroup_read_double4", "test_pipe_workgroup_write_double8", "test_pipe_workgroup_read_double8", "test_pipe_workgroup_write_double16", "test_pipe_workgroup_read_double16" }; + +static const char* subgroup_int_kernel_name[] = { "test_pipe_subgroup_write_int", "test_pipe_subgroup_read_int", "test_pipe_subgroup_write_int2", "test_pipe_subgroup_read_int2", "test_pipe_subgroup_write_int4", "test_pipe_subgroup_read_int4", "test_pipe_subgroup_write_int8", "test_pipe_subgroup_read_int8", "test_pipe_subgroup_write_int16", "test_pipe_subgroup_read_int16" }; +static const char* subgroup_uint_kernel_name[] = { "test_pipe_subgroup_write_uint", "test_pipe_subgroup_read_uint", "test_pipe_subgroup_write_uint2", "test_pipe_subgroup_read_uint2", "test_pipe_subgroup_write_uint4", "test_pipe_subgroup_read_uint4", "test_pipe_subgroup_write_uint8", "test_pipe_subgroup_read_uint8", "test_pipe_subgroup_write_uint16", "test_pipe_subgroup_read_uint16" }; +static const char* subgroup_long_kernel_name[] = { "test_pipe_subgroup_write_long", "test_pipe_subgroup_read_long", "test_pipe_subgroup_write_long2", "test_pipe_subgroup_read_long2", "test_pipe_subgroup_write_long4", "test_pipe_subgroup_read_long4", "test_pipe_subgroup_write_long8", "test_pipe_subgroup_read_long8", "test_pipe_subgroup_write_long16", "test_pipe_subgroup_read_long16" }; +static const char* subgroup_ulong_kernel_name[] = { "test_pipe_subgroup_write_ulong", "test_pipe_subgroup_read_ulong", "test_pipe_subgroup_write_ulong2", "test_pipe_subgroup_read_ulong2", "test_pipe_subgroup_write_ulong4", "test_pipe_subgroup_read_ulong4", "test_pipe_subgroup_write_ulong8", "test_pipe_subgroup_read_ulong8", "test_pipe_subgroup_write_ulong16", "test_pipe_subgroup_read_ulong16" }; +static const char* subgroup_char_kernel_name[] = { "test_pipe_subgroup_write_char", "test_pipe_subgroup_read_char", "test_pipe_subgroup_write_char2", "test_pipe_subgroup_read_char2", "test_pipe_subgroup_write_char4", "test_pipe_subgroup_read_char4", "test_pipe_subgroup_write_char8", "test_pipe_subgroup_read_char8", "test_pipe_subgroup_write_char16", "test_pipe_subgroup_read_char16" }; +static const char* subgroup_uchar_kernel_name[] = { "test_pipe_subgroup_write_uchar", "test_pipe_subgroup_read_uchar", "test_pipe_subgroup_write_uchar2", "test_pipe_subgroup_read_uchar2", "test_pipe_subgroup_write_uchar4", "test_pipe_subgroup_read_uchar4", "test_pipe_subgroup_write_uchar8", "test_pipe_subgroup_read_uchar8", "test_pipe_subgroup_write_uchar16", "test_pipe_subgroup_read_uchar16" }; +static const char* subgroup_short_kernel_name[] = { "test_pipe_subgroup_write_short", "test_pipe_subgroup_read_short", "test_pipe_subgroup_write_short2", "test_pipe_subgroup_read_short2", "test_pipe_subgroup_write_short4", "test_pipe_subgroup_read_short4", "test_pipe_subgroup_write_short8", "test_pipe_subgroup_read_short8", "test_pipe_subgroup_write_short16", "test_pipe_subgroup_read_short16" }; +static const char* subgroup_ushort_kernel_name[] = { "test_pipe_subgroup_write_ushort", "test_pipe_subgroup_read_ushort", "test_pipe_subgroup_write_ushort2", "test_pipe_subgroup_read_ushort2", "test_pipe_subgroup_write_ushort4", "test_pipe_subgroup_read_ushort4", "test_pipe_subgroup_write_ushort8", "test_pipe_subgroup_read_ushort8", "test_pipe_subgroup_write_ushort16", "test_pipe_subgroup_read_ushort16" }; +static const char* subgroup_float_kernel_name[] = { "test_pipe_subgroup_write_float", "test_pipe_subgroup_read_float", "test_pipe_subgroup_write_float2", "test_pipe_subgroup_read_float2", "test_pipe_subgroup_write_float4", "test_pipe_subgroup_read_float4", "test_pipe_subgroup_write_float8", "test_pipe_subgroup_read_float8", "test_pipe_subgroup_write_float16", "test_pipe_subgroup_read_float16" }; +static const char* subgroup_half_kernel_name[] = { "test_pipe_subgroup_write_half", "test_pipe_subgroup_read_half", "test_pipe_subgroup_write_half2", "test_pipe_subgroup_read_half2", "test_pipe_subgroup_write_half4", "test_pipe_subgroup_read_half4", "test_pipe_subgroup_write_half8", "test_pipe_subgroup_read_half8", "test_pipe_subgroup_write_half16", "test_pipe_subgroup_read_half16" }; +static const char* subgroup_double_kernel_name[] = { "test_pipe_subgroup_write_double", "test_pipe_subgroup_read_double", "test_pipe_subgroup_write_double2", "test_pipe_subgroup_read_double2", "test_pipe_subgroup_write_double4", "test_pipe_subgroup_read_double4", "test_pipe_subgroup_write_double8", "test_pipe_subgroup_read_double8", "test_pipe_subgroup_write_double16", "test_pipe_subgroup_read_double16" }; + + +static const char* convenience_int_kernel_name[] = { "test_pipe_convenience_write_int", "test_pipe_convenience_read_int", "test_pipe_convenience_write_int2", "test_pipe_convenience_read_int2", "test_pipe_convenience_write_int4", "test_pipe_convenience_read_int4", "test_pipe_convenience_write_int8", "test_pipe_convenience_read_int8", "test_pipe_convenience_write_int16", "test_pipe_convenience_read_int16" }; +static const char* convenience_uint_kernel_name[] = { "test_pipe_convenience_write_uint", "test_pipe_convenience_read_uint", "test_pipe_convenience_write_uint2", "test_pipe_convenience_read_uint2", "test_pipe_convenience_write_uint4", "test_pipe_convenience_read_uint4", "test_pipe_convenience_write_uint8", "test_pipe_convenience_read_uint8", "test_pipe_convenience_write_uint16", "test_pipe_convenience_read_uint16" }; +static const char* convenience_long_kernel_name[] = { "test_pipe_convenience_write_long", "test_pipe_convenience_read_long", "test_pipe_convenience_write_long2", "test_pipe_convenience_read_long2", "test_pipe_convenience_write_long4", "test_pipe_convenience_read_long4", "test_pipe_convenience_write_long8", "test_pipe_convenience_read_long8", "test_pipe_convenience_write_long16", "test_pipe_convenience_read_long16" }; +static const char* convenience_ulong_kernel_name[] = { "test_pipe_convenience_write_ulong", "test_pipe_convenience_read_ulong", "test_pipe_convenience_write_ulong2", "test_pipe_convenience_read_ulong2", "test_pipe_convenience_write_ulong4", "test_pipe_convenience_read_ulong4", "test_pipe_convenience_write_ulong8", "test_pipe_convenience_read_ulong8", "test_pipe_convenience_write_ulong16", "test_pipe_convenience_read_ulong16" }; +static const char* convenience_char_kernel_name[] = { "test_pipe_convenience_write_char", "test_pipe_convenience_read_char", "test_pipe_convenience_write_char2", "test_pipe_convenience_read_char2", "test_pipe_convenience_write_char4", "test_pipe_convenience_read_char4", "test_pipe_convenience_write_char8", "test_pipe_convenience_read_char8", "test_pipe_convenience_write_char16", "test_pipe_convenience_read_char16" }; +static const char* convenience_uchar_kernel_name[] = { "test_pipe_convenience_write_uchar", "test_pipe_convenience_read_uchar", "test_pipe_convenience_write_uchar2", "test_pipe_convenience_read_uchar2", "test_pipe_convenience_write_uchar4", "test_pipe_convenience_read_uchar4", "test_pipe_convenience_write_uchar8", "test_pipe_convenience_read_uchar8", "test_pipe_convenience_write_uchar16", "test_pipe_convenience_read_uchar16" }; +static const char* convenience_short_kernel_name[] = { "test_pipe_convenience_write_short", "test_pipe_convenience_read_short", "test_pipe_convenience_write_short2", "test_pipe_convenience_read_short2", "test_pipe_convenience_write_short4", "test_pipe_convenience_read_short4", "test_pipe_convenience_write_short8", "test_pipe_convenience_read_short8", "test_pipe_convenience_write_short16", "test_pipe_convenience_read_short16" }; +static const char* convenience_ushort_kernel_name[] = { "test_pipe_convenience_write_ushort", "test_pipe_convenience_read_ushort", "test_pipe_convenience_write_ushort2", "test_pipe_convenience_read_ushort2", "test_pipe_convenience_write_ushort4", "test_pipe_convenience_read_ushort4", "test_pipe_convenience_write_ushort8", "test_pipe_convenience_read_ushort8", "test_pipe_convenience_write_ushort16", "test_pipe_convenience_read_ushort16" }; +static const char* convenience_float_kernel_name[] = { "test_pipe_convenience_write_float", "test_pipe_convenience_read_float", "test_pipe_convenience_write_float2", "test_pipe_convenience_read_float2", "test_pipe_convenience_write_float4", "test_pipe_convenience_read_float4", "test_pipe_convenience_write_float8", "test_pipe_convenience_read_float8", "test_pipe_convenience_write_float16", "test_pipe_convenience_read_float16" }; +static const char* convenience_half_kernel_name[] = { "test_pipe_convenience_write_half", "test_pipe_convenience_read_half", "test_pipe_convenience_write_half2", "test_pipe_convenience_read_half2", "test_pipe_convenience_write_half4", "test_pipe_convenience_read_half4", "test_pipe_convenience_write_half8", "test_pipe_convenience_read_half8", "test_pipe_convenience_write_half16", "test_pipe_convenience_read_half16" }; +static const char* convenience_double_kernel_name[] = { "test_pipe_convenience_write_double", "test_pipe_convenience_read_double", "test_pipe_convenience_write_double2", "test_pipe_convenience_read_double2", "test_pipe_convenience_write_double4", "test_pipe_convenience_read_double4", "test_pipe_convenience_write_double8", "test_pipe_convenience_read_double8", "test_pipe_convenience_write_double16", "test_pipe_convenience_read_double16" }; + +static void insertPragmaForHalfType(char *source, char *type) +{ + source[0] = 0; + if(strncmp(type, "half",4) == 0) + { + strcat(source, "#pragma OPENCL EXTENSION cl_khr_fp16 : enable\n"); + } +} + +void createKernelSource(char *source, char *type) +{ + char str[512]; + int str_length; + + insertPragmaForHalfType(source, type); + + sprintf(str, "__kernel void test_pipe_write_%s(__global %s *src, __write_only pipe %s out_pipe)\n", type, type, type); + strcat(source, str); + sprintf(str, "{\n int gid = get_global_id(0);\n reserve_id_t res_id; \n\n"); + strcat(source, str); + sprintf(str, " res_id = reserve_write_pipe(out_pipe, 1);\n if(is_valid_reserve_id(res_id))\n {\n"); + strcat(source, str); + sprintf(str, " write_pipe(out_pipe, res_id, 0, &src[gid]);\n commit_write_pipe(out_pipe, res_id);\n }\n}\n\n"); + strcat(source, str); + sprintf(str, "__kernel void test_pipe_read_%s(__read_only pipe %s in_pipe, __global %s *dst)\n", type, type, type); + strcat(source, str); + sprintf(str, "{\n int gid = get_global_id(0);\n reserve_id_t res_id; \n\n"); + strcat(source, str); + sprintf(str, " res_id = reserve_read_pipe(in_pipe, 1);\n if(is_valid_reserve_id(res_id))\n {\n"); + strcat(source, str); + sprintf(str, " read_pipe(in_pipe, res_id, 0, &dst[gid]);\n commit_read_pipe(in_pipe, res_id);\n }\n}\n"); + strcat(source, str); + str_length = strlen(source); + assert(str_length <= STRING_LENGTH); +} + +void createKernelSourceWorkGroup(char *source, char *type) +{ + char str[512]; + int str_length; + + insertPragmaForHalfType(source, type); + + sprintf(str, "__kernel void test_pipe_workgroup_write_%s(__global %s *src, __write_only pipe %s out_pipe)\n", type, type, type); + strcat(source, str); + sprintf(str, "{\n int gid = get_global_id(0);\n __local reserve_id_t res_id; \n\n"); + strcat(source, str); + sprintf(str, " res_id = work_group_reserve_write_pipe(out_pipe, get_local_size(0));\n if(is_valid_reserve_id(res_id))\n {\n"); + strcat(source, str); + sprintf(str, " write_pipe(out_pipe, res_id, get_local_id(0), &src[gid]);\n work_group_commit_write_pipe(out_pipe, res_id);\n }\n}\n\n"); + strcat(source, str); + sprintf(str, "__kernel void test_pipe_workgroup_read_%s(__read_only pipe %s in_pipe, __global %s *dst)\n", type, type, type); + strcat(source, str); + sprintf(str, "{\n int gid = get_global_id(0);\n __local reserve_id_t res_id; \n\n"); + strcat(source, str); + sprintf(str, " res_id = work_group_reserve_read_pipe(in_pipe, get_local_size(0));\n if(is_valid_reserve_id(res_id))\n {\n"); + strcat(source, str); + sprintf(str, " read_pipe(in_pipe, res_id, get_local_id(0), &dst[gid]);\n work_group_commit_read_pipe(in_pipe, res_id);\n }\n}\n"); + strcat(source, str); + str_length = strlen(source); + assert(str_length <= STRING_LENGTH); +} + +void createKernelSourceSubGroup(char *source, char *type) +{ + char str[512]; + int str_length; + + insertPragmaForHalfType(source, type); + + sprintf(str, "#pragma OPENCL EXTENSION cl_khr_subgroups : enable\n__kernel void test_pipe_subgroup_write_%s(__global %s *src, __write_only pipe %s out_pipe)\n", type, type, type); + strcat(source, str); + sprintf(str, "{\n int gid = get_global_id(0);\n reserve_id_t res_id; \n\n"); + strcat(source, str); + sprintf(str, " res_id = sub_group_reserve_write_pipe(out_pipe, get_sub_group_size());\n if(is_valid_reserve_id(res_id))\n {\n"); + strcat(source, str); + sprintf(str, " write_pipe(out_pipe, res_id, get_sub_group_local_id(), &src[gid]);\n sub_group_commit_write_pipe(out_pipe, res_id);\n }\n}\n\n"); + strcat(source, str); + sprintf(str, "__kernel void test_pipe_subgroup_read_%s(__read_only pipe %s in_pipe, __global %s *dst)\n", type, type, type); + strcat(source, str); + sprintf(str, "{\n int gid = get_global_id(0);\n reserve_id_t res_id; \n\n"); + strcat(source, str); + sprintf(str, " res_id = sub_group_reserve_read_pipe(in_pipe, get_sub_group_size());\n if(is_valid_reserve_id(res_id))\n {\n"); + strcat(source, str); + sprintf(str, " read_pipe(in_pipe, res_id, get_sub_group_local_id(), &dst[gid]);\n sub_group_commit_read_pipe(in_pipe, res_id);\n }\n}\n"); + strcat(source, str); + str_length = strlen(source); + assert(str_length <= STRING_LENGTH); +} + +void createKernelSourceConvenience(char *source, char *type) +{ + char str[512]; + int str_length; + + insertPragmaForHalfType(source, type); + + sprintf(str, "__kernel void test_pipe_convenience_write_%s(__global %s *src, __write_only pipe %s out_pipe)\n", type, type, type); + strcat(source, str); + sprintf(str, "{\n int gid = get_global_id(0);\n write_pipe(out_pipe, &src[gid]);\n}\n\n"); + strcat(source, str); + sprintf(str, "__kernel void test_pipe_convenience_read_%s(__read_only pipe %s in_pipe, __global %s *dst)\n", type, type, type); + strcat(source, str); + sprintf(str, "{\n int gid = get_global_id(0);\n read_pipe(in_pipe, &dst[gid]);\n}\n"); + strcat(source, str); + str_length = strlen(source); + assert(str_length <= STRING_LENGTH); +} + +// verify functions +static int verify_readwrite_int(void *ptr1, void *ptr2, int n) +{ + int i; + int sum_input = 0, sum_output = 0; + cl_int *inptr = (cl_int *)ptr1; + cl_int *outptr = (cl_int *)ptr2; + + for(i = 0; i < n; i++) + { + sum_input += inptr[i]; + sum_output += outptr[i]; + } + if(sum_input != sum_output){ + return -1; + } + + return 0; +} + +static int verify_readwrite_uint(void *ptr1, void *ptr2, int n) +{ + int i; + int sum_input = 0, sum_output = 0; + cl_uint *inptr = (cl_uint *)ptr1; + cl_uint *outptr = (cl_uint *)ptr2; + + for(i = 0; i < n; i++) + { + sum_input += inptr[i]; + sum_output += outptr[i]; + } + if(sum_input != sum_output){ + return -1; + } + + return 0; +} + +static int verify_readwrite_short(void *ptr1, void *ptr2, int n) +{ + int i; + int sum_input = 0, sum_output = 0; + cl_short *inptr = (cl_short *)ptr1; + cl_short *outptr = (cl_short *)ptr2; + + for(i = 0; i < n; i++) + { + sum_input += inptr[i]; + sum_output += outptr[i]; + } + if(sum_input != sum_output){ + return -1; + } + return 0; +} + +static int verify_readwrite_ushort(void *ptr1, void *ptr2, int n) +{ + int i; + int sum_input = 0, sum_output = 0; + cl_ushort *inptr = (cl_ushort *)ptr1; + cl_ushort *outptr = (cl_ushort *)ptr2; + + for(i = 0; i < n; i++) + { + sum_input += inptr[i]; + sum_output += outptr[i]; + } + if(sum_input != sum_output){ + return -1; + } + return 0; +} + +static int verify_readwrite_char(void *ptr1, void *ptr2, int n) +{ + int i; + int sum_input = 0, sum_output = 0; + cl_char *inptr = (cl_char *)ptr1; + cl_char *outptr = (cl_char *)ptr2; + + for(i = 0; i < n; i++) + { + sum_input += inptr[i]; + sum_output += outptr[i]; + } + if(sum_input != sum_output){ + return -1; + } + return 0; +} + +static int verify_readwrite_uchar(void *ptr1, void *ptr2, int n) +{ + int i; + int sum_input = 0, sum_output = 0; + cl_uchar *inptr = (cl_uchar *)ptr1; + cl_uchar *outptr = (cl_uchar *)ptr2; + + for(i = 0; i < n; i++) + { + sum_input += inptr[i]; + sum_output += outptr[i]; + } + if(sum_input != sum_output){ + return -1; + } + return 0; +} + +static int verify_readwrite_float(void *ptr1, void *ptr2, int n) +{ + int i; + int sum_input = 0, sum_output = 0; + int *inptr = (int *)ptr1; + int *outptr = (int *)ptr2; + + for(i = 0; i < n; i++) + { + sum_input += inptr[i]; + sum_output += outptr[i]; + } + if(sum_input != sum_output){ + return -1; + } + return 0; +} + +static int verify_readwrite_half(void *ptr1, void *ptr2, int n) +{ + int i; + int sum_input = 0, sum_output = 0; + cl_ushort *inptr = (cl_ushort *)ptr1; + cl_ushort *outptr = (cl_ushort *)ptr2; + + for(i = 0; i < n; i++) + { + sum_input += inptr[i]; + sum_output += outptr[i]; + } + if(sum_input != sum_output){ + return -1; + } + return 0; +} + +static int verify_readwrite_long(void *ptr1, void *ptr2, int n) +{ + int i; + cl_long sum_input = 0, sum_output = 0; + cl_long *inptr = (cl_long *)ptr1; + cl_long *outptr = (cl_long *)ptr2; + + for(i = 0; i < n; i++) + { + sum_input += inptr[i]; + sum_output += outptr[i]; + } + if(sum_input != sum_output){ + return -1; + } + return 0; +} + +static int verify_readwrite_ulong(void *ptr1, void *ptr2, int n) +{ + int i; + cl_ulong sum_input = 0, sum_output = 0; + cl_ulong *inptr = (cl_ulong *)ptr1; + cl_ulong *outptr = (cl_ulong *)ptr2; + + for(i = 0; i < n; i++) + { + sum_input += inptr[i]; + sum_output += outptr[i]; + } + if(sum_input != sum_output){ + return -1; + } + return 0; +} + +static int verify_readwrite_double(void *ptr1, void *ptr2, int n) +{ + int i; + long long int sum_input = 0, sum_output = 0; + long long int *inptr = (long long int *)ptr1; + long long int *outptr = (long long int *)ptr2; + + for(i = 0; i < n; i++) + { + sum_input += inptr[i]; + sum_output += outptr[i]; + } + if(sum_input != sum_output){ + return -1; + } + return 0; +} + +static int verify_readwrite_struct(void *ptr1, void *ptr2, int n) +{ + int i; + int sum_input_char = 0, sum_output_char = 0; + int sum_input_int = 0, sum_output_int = 0; + TestStruct *inptr = (TestStruct *)ptr1; + TestStruct *outptr = (TestStruct *)ptr2; + + for(i = 0; i < n; i++) + { + sum_input_char += inptr[i].a; + sum_input_int += inptr[i].b; + sum_output_char += outptr[i].a; + sum_output_int += outptr[i].b; + } + if( (sum_input_char != sum_output_char) && (sum_input_int != sum_output_int) ){ + return -1; + } + + return 0; +} + +int test_pipe_readwrite( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, size_t size, char *type, int loops, + void *inptr[5], const char *kernelName[], int (*fn)(void *, void *, int) ) +{ + cl_mem pipes[5]; + cl_mem buffers[10]; + void *outptr[5]; + cl_program program[5]; + cl_kernel kernel[10]; + size_t global_work_size[3]; + size_t local_work_size[3]; + cl_int err; + int i, ii; + size_t ptrSizes[5]; + int total_errors = 0; + cl_event producer_sync_event[5]; + cl_event consumer_sync_event[5]; + char *sourceCode[5]; + char vector_type[10]; + + size_t min_alignment = get_min_alignment(context); + + global_work_size[0] = (cl_uint)num_elements; + + ptrSizes[0] = size; + ptrSizes[1] = ptrSizes[0] << 1; + ptrSizes[2] = ptrSizes[1] << 1; + ptrSizes[3] = ptrSizes[2] << 1; + ptrSizes[4] = ptrSizes[3] << 1; + + for( i = 0; i < loops; i++) + { + ii = i << 1; + sourceCode[i] = (char*) malloc(STRING_LENGTH * sizeof(char)); + buffers[ii] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, ptrSizes[i] * num_elements, inptr[i], &err); + if(err){ + clReleaseMemObject(buffers[ii]); + align_free( outptr[i] ); + print_error(err, " clCreateBuffer failed\n"); + return -1; + } + outptr[i] = align_malloc( ptrSizes[i] * num_elements, min_alignment); + buffers[ii+1] = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, ptrSizes[i] * num_elements, outptr[i], &err); + + if ( err ){ + clReleaseMemObject(buffers[ii]); + align_free( outptr[i] ); + print_error(err, " clCreateBuffer failed\n" ); + return -1; + } + // Creating pipe with non-power of 2 size + pipes[i] = clCreatePipe(context, CL_MEM_HOST_NO_ACCESS, ptrSizes[i], num_elements+3, NULL, &err); + if(err){ + clReleaseMemObject(pipes[i]); + print_error(err, " clCreatePipe failed\n"); + return -1; + } + + switch(i) + { + case 0: + sprintf(vector_type, "%s", type); + break; + case 1: + sprintf(vector_type, "%s%d", type, 2); + break; + case 2: + sprintf(vector_type, "%s%d", type, 4); + break; + case 3: + sprintf(vector_type, "%s%d", type, 8); + break; + case 4: + sprintf(vector_type, "%s%d", type, 16); + break; + } + + if(useWorkgroupReserve == 1){ + createKernelSourceWorkGroup(sourceCode[i], vector_type); + } + else if(useSubgroupReserve == 1){ + createKernelSourceSubGroup(sourceCode[i], vector_type); + } + else if(useConvenienceBuiltIn == 1){ + createKernelSourceConvenience(sourceCode[i], vector_type); + } + else{ + createKernelSource(sourceCode[i], vector_type); + } + + // Create producer kernel + err = create_single_kernel_helper_with_build_options(context, &program[i], &kernel[ii], 1, (const char**)&sourceCode[i], kernelName[ii], "-cl-std=CL2.0"); + if(err){ + clReleaseMemObject(buffers[ii]); + clReleaseMemObject(buffers[ii+1]); + clReleaseMemObject(pipes[i]); + align_free( outptr[i] ); + print_error(err, "Error creating program\n"); + return -1; + } + //Create consumer kernel + kernel[ii + 1] = clCreateKernel(program[i], kernelName[ii + 1], &err); + if( kernel[ii + 1] == NULL || err != CL_SUCCESS) + { + clReleaseMemObject(buffers[ii]); + clReleaseMemObject(buffers[ii+1]); + clReleaseMemObject(pipes[i]); + align_free( outptr[i] ); + log_error("Creating program for %s\n", type); + print_error( err, "Unable to create kernel" ); + return -1; + } + + err = clSetKernelArg(kernel[ii], 0, sizeof(cl_mem), (void*)&buffers[ii]); + err |= clSetKernelArg(kernel[ii], 1, sizeof(cl_mem), (void*)&pipes[i]); + err |= clSetKernelArg(kernel[ii + 1], 0, sizeof(cl_mem), (void*)&pipes[i]); + err |= clSetKernelArg(kernel[ii + 1], 1, sizeof(cl_mem), (void*)&buffers[ii + 1]); + if ( err != CL_SUCCESS ){ + clReleaseMemObject(buffers[ii]); + clReleaseMemObject(buffers[ii+1]); + clReleaseMemObject(pipes[i]); + clReleaseKernel(kernel[ii]); + clReleaseKernel(kernel[ii+1]); + clReleaseProgram(program[i]); + align_free(outptr[i]); + print_error(err, " clSetKernelArg failed"); + return -1; + } + + if(useWorkgroupReserve == 1 || useSubgroupReserve == 1) + { + err = get_max_common_work_group_size( context, kernel[ii], global_work_size[0], &local_work_size[0] ); + test_error( err, "Unable to get work group size to use" ); + // Launch Producer kernel + err = clEnqueueNDRangeKernel( queue, kernel[ii], 1, NULL, global_work_size, local_work_size, 0, NULL, &producer_sync_event[i] ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buffers[ii]); + clReleaseMemObject(buffers[ii+1]); + clReleaseMemObject(pipes[i]); + clReleaseKernel(kernel[ii]); + clReleaseKernel(kernel[ii+1]); + clReleaseEvent(producer_sync_event[i]); + clReleaseEvent(consumer_sync_event[i]); + clReleaseProgram(program[i]); + align_free(outptr[i]); + return -1; + } + } + else + { + // Launch Producer kernel + err = clEnqueueNDRangeKernel( queue, kernel[ii], 1, NULL, global_work_size, NULL, 0, NULL, &producer_sync_event[i] ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buffers[ii]); + clReleaseMemObject(buffers[ii+1]); + clReleaseMemObject(pipes[i]); + clReleaseKernel(kernel[ii]); + clReleaseKernel(kernel[ii+1]); + clReleaseEvent(producer_sync_event[i]); + clReleaseEvent(consumer_sync_event[i]); + clReleaseProgram(program[i]); + align_free(outptr[i]); + return -1; + } + } + + if(useWorkgroupReserve == 1 || useSubgroupReserve == 1) + { + err = get_max_common_work_group_size( context, kernel[ii + 1], global_work_size[0], &local_work_size[0] ); + test_error( err, "Unable to get work group size to use" ); + + // Launch Consumer kernel + err = clEnqueueNDRangeKernel( queue, kernel[ii + 1], 1, NULL, global_work_size, local_work_size, 1, &producer_sync_event[i], &consumer_sync_event[i] ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buffers[ii]); + clReleaseMemObject(buffers[ii+1]); + clReleaseMemObject(pipes[i]); + clReleaseKernel(kernel[ii]); + clReleaseKernel(kernel[ii+1]); + clReleaseEvent(producer_sync_event[i]); + clReleaseEvent(consumer_sync_event[i]); + clReleaseProgram(program[i]); + align_free(outptr[i]); + return -1; + } + } + else + { + // Launch Consumer kernel + err = clEnqueueNDRangeKernel( queue, kernel[ii + 1], 1, NULL, global_work_size, NULL, 1, &producer_sync_event[i], &consumer_sync_event[i] ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buffers[ii]); + clReleaseMemObject(buffers[ii+1]); + clReleaseMemObject(pipes[i]); + clReleaseKernel(kernel[ii]); + clReleaseKernel(kernel[ii+1]); + clReleaseEvent(producer_sync_event[i]); + clReleaseEvent(consumer_sync_event[i]); + clReleaseProgram(program[i]); + align_free(outptr[i]); + return -1; + } + } + + err = clEnqueueReadBuffer(queue, buffers[ii+1], true, 0, ptrSizes[i]*num_elements, outptr[i], 1, &consumer_sync_event[i], NULL); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed" ); + clReleaseMemObject(buffers[ii]); + clReleaseMemObject(buffers[ii+1]); + clReleaseMemObject(pipes[i]); + clReleaseKernel(kernel[ii]); + clReleaseKernel(kernel[ii+1]); + clReleaseEvent(producer_sync_event[i]); + clReleaseEvent(consumer_sync_event[i]); + clReleaseProgram(program[i]); + align_free(outptr[i]); + return -1; + } + + if( fn( inptr[i], outptr[i], (int)(ptrSizes[i] * (size_t)num_elements / ptrSizes[0]))){ + log_error("%s%d test failed\n", type, 1< +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/errorHelpers.h" + +const char* pipe_readwrite_errors_kernel_code = { + "__kernel void test_pipe_write_error(__global int *src, __write_only pipe int out_pipe, __global int *status)\n" + "{\n" + " int gid = get_global_id(0);\n" + " int reserve_idx;\n" + " reserve_id_t res_id;\n" + "\n" + " res_id = reserve_write_pipe(out_pipe, 1);\n" + " if(is_valid_reserve_id(res_id))\n" + " {\n" + " write_pipe(out_pipe, res_id, 0, &src[gid]);\n" + " commit_write_pipe(out_pipe, res_id);\n" + " }\n" + " else\n" + " {\n" + " *status = -1;\n" + " }\n" + "}\n" + "\n" + "__kernel void test_pipe_read_error(__read_only pipe int in_pipe, __global int *dst, __global int *status)\n" + "{\n" + " int gid = get_global_id(0);\n" + " int reserve_idx;\n" + " reserve_id_t res_id;\n" + "\n" + " res_id = reserve_read_pipe(in_pipe, 1);\n" + " if(is_valid_reserve_id(res_id))\n" + " {\n" + " read_pipe(in_pipe, res_id, 0, &dst[gid]);\n" + " commit_read_pipe(in_pipe, res_id);\n" + " }\n" + " else\n" + " {\n" + " *status = -1;\n" + " }\n" + "}\n" +}; + + +int test_pipe_readwrite_errors(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem pipe; + cl_mem buffers[3]; + void *outptr; + cl_int *inptr; + cl_program program; + cl_kernel kernel[2]; + size_t global_work_size[3]; + cl_int err; + cl_int size; + cl_int i; + cl_int status = 0; + cl_event producer_sync_event; + cl_event consumer_sync_event; + MTdata d = init_genrand( gRandomSeed ); + const char* kernelName[] = {"test_pipe_write_error", "test_pipe_read_error"}; + + size_t min_alignment = get_min_alignment(context); + + global_work_size[0] = num_elements; + + size = num_elements * sizeof(cl_int); + + inptr = (cl_int *)align_malloc(size, min_alignment); + + for(i = 0; i < (cl_int)(size / sizeof(int)); i++){ + inptr[i] = (int)genrand_int32(d); + } + + buffers[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, size, inptr, &err); + if(err){ + clReleaseMemObject(buffers[0]); + print_error(err, " clCreateBuffer failed\n"); + return -1; + } + outptr = align_malloc(size, min_alignment); + buffers[1] = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, size, outptr, &err); + if ( err ){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free( outptr ); + print_error(err, " clCreateBuffer failed\n" ); + return -1; + } + buffers[2] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, sizeof(int), &status, &err); + if ( err ){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + align_free( outptr ); + print_error(err, " clCreateBuffer failed\n" ); + return -1; + } + //Pipe created with max_packets less than global size + pipe = clCreatePipe(context, CL_MEM_HOST_NO_ACCESS, sizeof(int), num_elements - (num_elements/2), NULL, &err); + if(err){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + align_free( outptr ); + clReleaseMemObject(pipe); + print_error(err, " clCreatePipe failed\n"); + return -1; + } + + // Create producer kernel + err = create_single_kernel_helper_with_build_options(context, &program, &kernel[0], 1, (const char**)&pipe_readwrite_errors_kernel_code, kernelName[0], "-cl-std=CL2.0"); + if(err){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + align_free(outptr); + print_error(err, "Error creating program\n"); + return -1; + } + //Create consumer kernel + kernel[1] = clCreateKernel(program, kernelName[1], &err); + if( kernel[1] == NULL || err != CL_SUCCESS) + { + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + align_free(outptr); + print_error(err, "Error creating kernel\n"); + return -1; + } + + err = clSetKernelArg(kernel[0], 0, sizeof(cl_mem), (void*)&buffers[0]); + err |= clSetKernelArg(kernel[0], 1, sizeof(cl_mem), (void*)&pipe); + err |= clSetKernelArg(kernel[0], 2, sizeof(cl_mem), (void*)&buffers[2]); + err |= clSetKernelArg(kernel[1], 0, sizeof(cl_mem), (void*)&pipe); + err |= clSetKernelArg(kernel[1], 1, sizeof(cl_mem), (void*)&buffers[1]); + err |= clSetKernelArg(kernel[1], 2, sizeof(cl_mem), (void*)&buffers[2]); + if ( err != CL_SUCCESS ){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseProgram(program); + align_free(outptr); + print_error(err, " clSetKernelArg failed"); + return -1; + } + + // Launch Consumer kernel for empty pipe + err = clEnqueueNDRangeKernel( queue, kernel[1], 1, NULL, global_work_size, NULL, 0, NULL, &consumer_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + return -1; + } + + err = clEnqueueReadBuffer(queue, buffers[2], true, 0, sizeof(status), &status, 1, &consumer_sync_event, NULL); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + return -1; + } + + if(status == 0){ + log_error("test_pipe_readwrite_errors failed\n"); + return -1; + } + else{ + status = 0; + } + + // Launch Producer kernel + err = clEnqueueNDRangeKernel( queue, kernel[0], 1, NULL, global_work_size, NULL, 0, NULL, &producer_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseProgram(program); + align_free(outptr); + return -1; + } + + err = clEnqueueReadBuffer(queue, buffers[2], true, 0, sizeof(status), &status, 1, &producer_sync_event, NULL); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseProgram(program); + align_free(outptr); + return -1; + } + + if(status == 0){ + log_error("test_pipe_readwrite_errors failed\n"); + return -1; + } + else{ + status = 0; + } + + // Launch Consumer kernel + err = clEnqueueNDRangeKernel( queue, kernel[1], 1, NULL, global_work_size, NULL, 1, &producer_sync_event, &consumer_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + return -1; + } + + err = clEnqueueReadBuffer(queue, buffers[2], true, 0, sizeof(status), &status, 1, &consumer_sync_event, NULL); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + return -1; + } + + if(status == 0) + { + log_error("test_pipe_readwrite_errors failed\n"); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + return -1; + } + + log_info("test_pipe_readwrite_errors passed\n"); + //cleanup + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + return 0; +} diff --git a/test_conformance/pipes/test_pipe_subgroups.c b/test_conformance/pipes/test_pipe_subgroups.c new file mode 100644 index 00000000..6f8615da --- /dev/null +++ b/test_conformance/pipes/test_pipe_subgroups.c @@ -0,0 +1,339 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/errorHelpers.h" +#define TEST_INT_VALUE 100 + +const char* pipe_subgroups_kernel_code = { + "#pragma OPENCL EXTENSION cl_khr_subgroups : enable\n" + "__kernel void test_pipe_subgroups_divergence_write(__global int *src, __write_only pipe int out_pipe, __global int *active_work_item_buffer)\n" + "{\n" + " int gid = get_global_id(0);\n" + " reserve_id_t res_id; \n" + "\n" + " if(get_sub_group_id() % 2 == 0)\n" + " {\n" + " active_work_item_buffer[gid] = 1;\n" + " res_id = sub_group_reserve_write_pipe(out_pipe, get_sub_group_size());\n" + " if(is_valid_reserve_id(res_id))\n" + " {\n" + " write_pipe(out_pipe, res_id, get_sub_group_local_id(), &src[gid]);\n" + " sub_group_commit_write_pipe(out_pipe, res_id);\n" + " }\n" + " }\n" + "}\n" + "\n" + "__kernel void test_pipe_subgroups_divergence_read(__read_only pipe int in_pipe, __global int *dst)\n" + "{\n" + " int gid = get_global_id(0);\n" + " reserve_id_t res_id; \n" + "\n" + " if(get_sub_group_id() % 2 == 0)\n" + " {\n" + " res_id = sub_group_reserve_read_pipe(in_pipe, get_sub_group_size());\n" + " if(is_valid_reserve_id(res_id))\n" + " {\n" + " read_pipe(in_pipe, res_id, get_sub_group_local_id(), &dst[gid]);\n" + " sub_group_commit_read_pipe(in_pipe, res_id);\n" + " }\n" + " }\n" + "}\n" +}; + +static int verify_result(void *ptr1, void *ptr2, int n) +{ + int i; + int sum_input = 0, sum_output = 0; + cl_int *inptr = (cl_int *)ptr1; + cl_int *outptr = (cl_int *)ptr2; + + for(i = 0; i < n; i++) + { + sum_input += inptr[i]; + } + sum_input *= TEST_INT_VALUE; + for(i = 0; i < n; i++) + { + if(outptr[i] == TEST_INT_VALUE){ + sum_output += outptr[i]; + } + } + + if(sum_input != sum_output){ + return -1; + } + return 0; +} + +int test_pipe_subgroups_divergence(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +{ + cl_mem pipe; + cl_mem buffers[3]; + cl_int *outptr; + cl_int *inptr; + cl_int *active_work_item_buffer; + cl_program program; + cl_kernel kernel[2]; + size_t global_work_size[3]; + size_t local_work_size[3]; + cl_int err; + cl_int size; + int i; + size_t subgroup_count; + cl_event producer_sync_event = NULL; + cl_event consumer_sync_event = NULL; + const char* kernelName[] = {"test_pipe_subgroups_divergence_write", "test_pipe_subgroups_divergence_read"}; + + size_t min_alignment = get_min_alignment(context); + + global_work_size[0] = (cl_uint)num_elements; + + if(!is_extension_available(deviceID, "cl_khr_subgroups")) + { + log_info("cl_khr_subgroups is not supported on this platoform. Skipping test.\n"); + return CL_SUCCESS; + } + + size = sizeof(int) * num_elements; + inptr = (cl_int *)align_malloc(size, min_alignment); + outptr = (cl_int *)align_malloc(size, min_alignment); + active_work_item_buffer = (cl_int *)align_malloc(size, min_alignment); + + for(i = 0; i < num_elements; i++){ + inptr[i] = TEST_INT_VALUE; + outptr[i] = 0; + active_work_item_buffer[i] = 0; + } + + buffers[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, size, inptr, &err); + if(err){ + clReleaseMemObject(buffers[0]); + print_error(err, " clCreateBuffer failed\n"); + return -1; + } + + buffers[1] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, size, outptr, &err); + if ( err ){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + align_free( outptr ); + print_error(err, " clCreateBuffer failed\n" ); + return -1; + } + + buffers[2] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, size, active_work_item_buffer, &err); + if ( err ){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + align_free( outptr ); + print_error(err, " clCreateBuffer failed\n" ); + return -1; + } + + pipe = clCreatePipe(context, CL_MEM_HOST_NO_ACCESS, sizeof(int), num_elements, NULL, &err); + if(err){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + align_free( outptr ); + clReleaseMemObject(pipe); + print_error(err, " clCreatePipe failed\n"); + return -1; + } + + // Create producer kernel + err = create_single_kernel_helper_with_build_options(context, &program, &kernel[0], 1, (const char**)&pipe_subgroups_kernel_code, kernelName[0], "-cl-std=CL2.0"); + if(err){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + align_free(outptr); + print_error(err, "Error creating program\n"); + return -1; + } + //Create consumer kernel + kernel[1] = clCreateKernel(program, kernelName[1], &err); + if( kernel[1] == NULL || err != CL_SUCCESS) + { + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + align_free(outptr); + print_error(err, "Error creating kernel\n"); + return -1; + } + + err = clSetKernelArg(kernel[0], 0, sizeof(cl_mem), (void*)&buffers[0]); + err |= clSetKernelArg(kernel[0], 1, sizeof(cl_mem), (void*)&pipe); + err |= clSetKernelArg(kernel[0], 2, sizeof(cl_mem), (void*)&buffers[2]); + err |= clSetKernelArg(kernel[1], 0, sizeof(cl_mem), (void*)&pipe); + err |= clSetKernelArg(kernel[1], 1, sizeof(cl_mem), (void*)&buffers[1]); + if ( err != CL_SUCCESS ){ + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseProgram(program); + align_free(outptr); + print_error(err, " clSetKernelArg failed"); + return -1; + } + + err = get_max_common_work_group_size( context, kernel[0], global_work_size[0], &local_work_size[0] ); + if( err != CL_SUCCESS) + { + test_error( err, "Unable to get work group size to use" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseProgram(program); + align_free(outptr); + return -1; + } + + cl_platform_id platform; + err = clGetDeviceInfo(deviceID, CL_DEVICE_PLATFORM, sizeof(platform), &platform, NULL); + clGetKernelSubGroupInfoKHR_fn clGetKernelSubGroupInfoKHR = (clGetKernelSubGroupInfoKHR_fn) clGetExtensionFunctionAddressForPlatform(platform, "clGetKernelSubGroupInfoKHR"); + + err = clGetKernelSubGroupInfoKHR(kernel[0], deviceID, CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE_KHR, sizeof(local_work_size[0]), &local_work_size[0], sizeof(subgroup_count), &subgroup_count, NULL); + if(subgroup_count <= 1) + { + log_info("Only 1 subgroup per workgroup for the kernel. Hence no divergence among subgroups possible. Skipping test.\n"); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseProgram(program); + align_free(outptr); + return CL_SUCCESS; + } + + // Launch Producer kernel + err = clEnqueueNDRangeKernel( queue, kernel[0], 1, NULL, global_work_size, local_work_size, 0, NULL, &producer_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + return -1; + } + + err = clEnqueueReadBuffer(queue, buffers[2], true, 0, size, active_work_item_buffer, 1, &producer_sync_event, NULL); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + return -1; + } + + + // Launch Consumer kernel + err = clEnqueueNDRangeKernel( queue, kernel[1], 1, NULL, global_work_size, local_work_size, 1, &producer_sync_event, &consumer_sync_event ); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + return -1; + } + + err = clEnqueueReadBuffer(queue, buffers[1], true, 0, size, outptr, 1, &consumer_sync_event, NULL); + if ( err != CL_SUCCESS ){ + print_error( err, " clEnqueueReadBuffer failed" ); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + return -1; + } + + if( verify_result( active_work_item_buffer, outptr, num_elements)){ + log_error("test_pipe_subgroups_divergence failed\n"); + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + return -1; + } + else { + log_info("test_pipe_subgroups_divergence passed\n"); + } + //cleanup + clReleaseMemObject(buffers[0]); + clReleaseMemObject(buffers[1]); + clReleaseMemObject(buffers[2]); + clReleaseMemObject(pipe); + clReleaseKernel(kernel[0]); + clReleaseKernel(kernel[1]); + clReleaseEvent(producer_sync_event); + clReleaseEvent(consumer_sync_event); + clReleaseProgram(program); + align_free(outptr); + + return 0; +} diff --git a/test_conformance/printf/CMakeLists.txt b/test_conformance/printf/CMakeLists.txt new file mode 100644 index 00000000..914ffb58 --- /dev/null +++ b/test_conformance/printf/CMakeLists.txt @@ -0,0 +1,18 @@ +set(MODULE_NAME PRINTF) + +set(${MODULE_NAME}_SOURCES + test_printf.c + util_printf.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/typeWrappers.cpp + ../../test_common/harness/conversions.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/msvc9.c + #../../test_common/harness/imageHelpers.cpp + ../../test_common/harness/parseParameters.cpp + ../../test_common/harness/kernelHelpers.c + ) + +include(../CMakeCommon.txt) diff --git a/test_conformance/printf/Jamfile b/test_conformance/printf/Jamfile new file mode 100644 index 00000000..b310d5c2 --- /dev/null +++ b/test_conformance/printf/Jamfile @@ -0,0 +1,5 @@ +project : requirements windows,gcc:-xc++ msvc:"/TP" ; +exe test_printf : test_printf.c util_printf.c ../../test_common/harness/mt19937.c ../../test_common/harness/kernelHelpers.c ../../test_common/harness/errorHelpers.c : windows:../../test_common/harness/msvc9.c ; +install dist : test_printf : debug:$(DIST)/debug/tests/conformance/1.2/x86/printf release:$(DIST)/release/tests/conformance/1.2/x86/printf ; + +install dist : test_printf : debug:$(DIST)/debug/tests/conformance/1.2/x86_64/printf release:$(DIST)/release/tests/conformance/1.2/x86_64/printf 64 ; \ No newline at end of file diff --git a/test_conformance/printf/Makefile b/test_conformance/printf/Makefile new file mode 100644 index 00000000..b5cf65d9 --- /dev/null +++ b/test_conformance/printf/Makefile @@ -0,0 +1,44 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = test_printf.c \ + util_printf.c \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/msvc9.c + +DEFINES = + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = $(SOURCES) +HEADERS = +TARGET = test_printf +INCLUDE = +COMPILERFLAGS = -c -Wall -g -O0 -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. + + + diff --git a/test_conformance/printf/test_printf.c b/test_conformance/printf/test_printf.c new file mode 100644 index 00000000..fcb6d69e --- /dev/null +++ b/test_conformance/printf/test_printf.c @@ -0,0 +1,813 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include + +#if ! defined( _WIN32) +#if ! defined( __ANDROID__ ) +#include +#endif +#include +#define streamDup(fd1) dup(fd1) +#define streamDup2(fd1,fd2) dup2(fd1,fd2) +#endif +#include +#include "test_printf.h" + +#if defined(_WIN32) +#include +#define streamDup(fd1) _dup(fd1) +#define streamDup2(fd1,fd2) _dup2(fd1,fd2) +#include "../../test_common/harness/testHarness.h" +#endif + +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/mt19937.h" +#include "../../test_common/harness/parseParameters.h" + +typedef unsigned int uint32_t; + + +//----------------------------------------- +// Static helper functions declaration +//----------------------------------------- + +//Stream helper functions + +//Associate stdout stream with the file(/tmp/tmpfile):i.e redirect stdout stream to the specific files (/tmp/tmpfile) +static int acquireOutputStream(); + +//Close the file(/tmp/tmpfile) associated with the stdout stream and disassociates it. +static void releaseOutputStream(int fd); + +//Get analysis buffer to verify the correctess of printed data +static void getAnalysisBuffer(char* analysisBuffer); + +//Kernel builder helper functions + +//Check if the test case is for kernel that has argument +static int isKernelArgument(testCase* pTestCase,size_t testId); + +//Check if the test case treats %p format for void* +static int isKernelPFormat(testCase* pTestCase,size_t testId); + +//----------------------------------------- +// Static functions declarations +//----------------------------------------- +// Make a program that uses printf for the given type/format, +static cl_program makePrintfProgram(cl_kernel *kernel_ptr, const cl_context context,const unsigned int testId,const unsigned int testNum,bool isLongSupport = true,bool is64bAddrSpace = false); + +// Creates and execute the printf test for the given device, context, type/format +static int doTest(cl_command_queue queue, cl_context context, const unsigned int testId, const unsigned int testNum, cl_device_id device,bool isLongSupport = true); + +// Check if device supports long +static bool isLongSupported(cl_device_id device_id); + +// Check if device address space is 64 bits +static bool is64bAddressSpace(cl_device_id device_id); + +//Wait until event status is CL_COMPLETE +int waitForEvent(cl_event* event); + +//----------------------------------------- +// Definitions and initializations +//----------------------------------------- + +// Tests are broken into the major test which is based on the +// src and cmp type and their corresponding vector types and +// sub tests which is for each individual test. The following +// tracks the subtests +int s_test_cnt = 0; +int s_test_fail = 0; + + +//----------------------------------------- +// Static helper functions definition +//----------------------------------------- + +//----------------------------------------- +// acquireOutputStream +//----------------------------------------- +static int acquireOutputStream() +{ + int fd = streamDup(fileno(stdout)); +#if (defined(__linux__) || defined(__APPLE__)) && (!defined( __ANDROID__ )) + freopen("/tmp/tmpfile","w",stdout); +#else + freopen("tmpfile","w",stdout); +#endif + return fd; +} + +//----------------------------------------- +// releaseOutputStream +//----------------------------------------- +static void releaseOutputStream(int fd) +{ + fflush(stdout); + streamDup2(fd,fileno(stdout)); + close(fd); +} + +//----------------------------------------- +// getAnalysisBuffer +//----------------------------------------- +static void getAnalysisBuffer(char* analysisBuffer) +{ + FILE *fp; + memset(analysisBuffer,0,ANALYSIS_BUFFER_SIZE); + +#if (defined(__linux__) || defined(__APPLE__)) && (!defined( __ANDROID__ )) + fp = fopen("/tmp/tmpfile","r"); +#else + fp = fopen("tmpfile","r"); +#endif + if(NULL == fp) + log_error("Failed to open analysis buffer ('%s')\n", strerror(errno)); + else + while(fgets(analysisBuffer,ANALYSIS_BUFFER_SIZE , fp) != NULL ); + fclose(fp); +} + +//----------------------------------------- +// isKernelArgument +//----------------------------------------- +static int isKernelArgument(testCase* pTestCase,size_t testId) +{ + return strcmp(pTestCase->_genParameters[testId].addrSpaceArgumentTypeQualifier,""); +} +//----------------------------------------- +// isKernelPFormat +//----------------------------------------- +static int isKernelPFormat(testCase* pTestCase,size_t testId) +{ + return strcmp(pTestCase->_genParameters[testId].addrSpacePAdd,""); +} + +//----------------------------------------- +// waitForEvent +//----------------------------------------- +int waitForEvent(cl_event* event) +{ + cl_int status = CL_SUCCESS; + cl_int eventStatus = CL_QUEUED; + while(eventStatus != CL_COMPLETE) + { + status = clGetEventInfo( + *event, + CL_EVENT_COMMAND_EXECUTION_STATUS, + sizeof(cl_int), + &eventStatus, + NULL); + if(status != CL_SUCCESS) + { + log_error("clGetEventInfo failed"); + return status; + } + } + + status = clReleaseEvent(*event); + if(status != CL_SUCCESS) + { + log_error("clReleaseEvent failed. (*event)"); + return status; + } + return CL_SUCCESS; +} + +//----------------------------------------- +// Static helper functions definition +//----------------------------------------- + +//----------------------------------------- +// makePrintfProgram +//----------------------------------------- +static cl_program makePrintfProgram(cl_kernel *kernel_ptr, const cl_context context,const unsigned int testId,const unsigned int testNum,bool isLongSupport,bool is64bAddrSpace) +{ + int err,i; + cl_program program; + cl_device_id devID; + char buildLog[ 1024 * 128 ]; + char testname[256] = {0}; + char addrSpaceArgument[256] = {0}; + char addrSpacePAddArgument[256] = {0}; + + //Program Source code for int,float,octal,hexadecimal,char,string + const char *sourceGen[] = { + "__kernel void ", testname, + "(void)\n", + "{\n" + " printf(\"", + allTestCase[testId]->_genParameters[testNum].genericFormat, + "\\n\",", + allTestCase[testId]->_genParameters[testNum].dataRepresentation, + ");", + "}\n" + }; + //Program Source code for vector + const char *sourceVec[] = { + "__kernel void ", testname, + "(void)\n", + "{\n", + allTestCase[testId]->_genParameters[testNum].dataType, + allTestCase[testId]->_genParameters[testNum].vectorSize, + " tmp = (", + allTestCase[testId]->_genParameters[testNum].dataType, + allTestCase[testId]->_genParameters[testNum].vectorSize, + ")", + allTestCase[testId]->_genParameters[testNum].dataRepresentation, + ";", + " printf(\"", + allTestCase[testId]->_genParameters[testNum].vectorFormatFlag, + "v", + allTestCase[testId]->_genParameters[testNum].vectorSize, + allTestCase[testId]->_genParameters[testNum].vectorFormatSpecifier, + "\\n\",", + "tmp);", + "}\n" + }; + //Program Source code for address space + const char *sourceAddrSpace[] = { + "__kernel void ", testname,"(",addrSpaceArgument, + ")\n{\n", + allTestCase[testId]->_genParameters[testNum].addrSpaceVariableTypeQualifier, + "printf(", + allTestCase[testId]->_genParameters[testNum].genericFormat, + ",", + allTestCase[testId]->_genParameters[testNum].addrSpaceParameter, + "); ", + addrSpacePAddArgument, + "\n}\n" + }; + + //Update testname + sprintf(testname,"%s%d","test",testId); + + //Update addrSpaceArgument and addrSpacePAddArgument types, based on FULL_PROFILE/EMBEDDED_PROFILE + if(allTestCase[testId]->_type == TYPE_ADDRESS_SPACE) + { + sprintf(addrSpaceArgument, "%s",allTestCase[testId]->_genParameters[testNum].addrSpaceArgumentTypeQualifier); + + sprintf(addrSpacePAddArgument,allTestCase[testId]->_genParameters[testNum].addrSpacePAdd); + } + + if (strlen(addrSpaceArgument) == 0) + sprintf(addrSpaceArgument,"void"); + + // create program based on its type + + if(allTestCase[testId]->_type == TYPE_VECTOR) + { + err = create_single_kernel_helper(context, &program, NULL, sizeof(sourceVec) / sizeof(sourceVec[0]), sourceVec, NULL); + } + else if(allTestCase[testId]->_type == TYPE_ADDRESS_SPACE) + { + err = create_single_kernel_helper(context, &program, NULL, sizeof(sourceAddrSpace) / sizeof(sourceAddrSpace[0]), sourceAddrSpace, NULL); + } + else + { + err = create_single_kernel_helper(context, &program, NULL, sizeof(sourceGen) / sizeof(sourceGen[0]), sourceGen, NULL); + } + + if (!program || err) { + log_error("create_single_kernel_helper failed\n"); + return NULL; + } + + *kernel_ptr = clCreateKernel(program, testname, &err); + if ( err ) { + log_error("clCreateKernel failed (%d)\n", err); + return NULL; + } + + return program; +} + +//----------------------------------------- +// isLongSupported +//----------------------------------------- +static bool isLongSupported(cl_device_id device_id) +{ + //profile type && device extention for long support checking + char *profileType = NULL,*devExt = NULL; + + size_t tempSize = 0; + cl_int status; + bool extSupport = true; + + // Device profile + status = clGetDeviceInfo( + device_id, + CL_DEVICE_PROFILE, + 0, + NULL, + &tempSize); + + if(status != CL_SUCCESS) + { + log_error("*** clGetDeviceInfo FAILED ***\n\n"); + return false; + } + + profileType = new char[tempSize]; + if(profileType == NULL) + { + log_error("Failed to allocate memory(profileType)"); + return false; + } + + status = clGetDeviceInfo( + device_id, + CL_DEVICE_PROFILE, + sizeof(char) * tempSize, + profileType, + NULL); + + + if(!strcmp("EMBEDDED_PROFILE",profileType)) + { + // Device extention + status = clGetDeviceInfo( + device_id, + CL_DEVICE_EXTENSIONS, + 0, + NULL, + &tempSize); + + if(status != CL_SUCCESS) + { + log_error("*** clGetDeviceInfo FAILED ***\n\n"); + return false; + } + + devExt = new char[tempSize]; + if(devExt == NULL) + { + log_error("Failed to allocate memory(devExt)"); + return false; + } + + status = clGetDeviceInfo( + device_id, + CL_DEVICE_EXTENSIONS, + sizeof(char) * tempSize, + devExt, + NULL); + + extSupport = (strstr(devExt,"cles_khr_int64") != NULL); + + delete devExt; + delete profileType; + } + return extSupport; +} +//----------------------------------------- +// is64bAddressSpace +//----------------------------------------- +static bool is64bAddressSpace(cl_device_id device_id) +{ + cl_int status; + cl_uint addrSpaceB; + + // Device profile + status = clGetDeviceInfo( + device_id, + CL_DEVICE_ADDRESS_BITS, + sizeof(cl_uint), + &addrSpaceB, + NULL); + if(status != CL_SUCCESS) + { + log_error("*** clGetDeviceInfo FAILED ***\n\n"); + return false; + } + if(addrSpaceB == 64) + return true; + else + return false; +} +//----------------------------------------- +// doTest +//----------------------------------------- +static int doTest(cl_command_queue queue, cl_context context, const unsigned int testId, const unsigned int testNum, cl_device_id device,bool isLongSupport) +{ + int err; + cl_program program; + cl_kernel kernel; + cl_mem d_out; + char _analysisBuffer[ANALYSIS_BUFFER_SIZE]; + cl_uint out32 = 0; + cl_ulong out64 = 0; + + // Define an index space (global work size) of threads for execution. + size_t globalWorkSize[1]; + + program = makePrintfProgram(&kernel, context,testId,testNum,isLongSupport,is64bAddressSpace(device)); + if (!program || !kernel) { + ++s_test_fail; + ++s_test_cnt; + return -1; + } + + //For address space test if there is kernel argument - set it + if(allTestCase[testId]->_type == TYPE_ADDRESS_SPACE ) + { + if(isKernelArgument(allTestCase[testId],testNum)) + { + int a = 2; + cl_mem d_a = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, + sizeof(int), &a, &err); + if(err!= CL_SUCCESS || d_a == NULL) { + log_error("clCreateBuffer failed\n"); + goto exit; + } + err = clSetKernelArg(kernel, 0, sizeof(cl_mem), &d_a); + if(err!= CL_SUCCESS) { + log_error("clSetKernelArg failed\n"); + goto exit; + } + } + //For address space test if %p is tested + if(isKernelPFormat(allTestCase[testId],testNum)) + { + d_out = clCreateBuffer(context, CL_MEM_READ_WRITE, + sizeof(cl_ulong), NULL, &err); + if(err!= CL_SUCCESS || d_out == NULL) { + log_error("clCreateBuffer failed\n"); + goto exit; + } + err = clSetKernelArg(kernel, 1, sizeof(cl_mem), &d_out); + if(err!= CL_SUCCESS) { + log_error("clSetKernelArg failed\n"); + goto exit; + } + } + } + + globalWorkSize[0] = 1; + cl_event ndrEvt; + err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, globalWorkSize, NULL, 0, NULL,&ndrEvt); + if (err != CL_SUCCESS) { + log_error("\n clEnqueueNDRangeKernel failed errcode:%d\n", err); + ++s_test_fail; + goto exit; + } + + fflush(stdout); + err = clFlush(queue); + if(err != CL_SUCCESS) + { + log_error("clFlush failed\n"); + goto exit; + } + //Wait until kernel finishes its execution and (thus) the output printed from the kernel + //is immidatly printed + err = waitForEvent(&ndrEvt); + + if(err != CL_SUCCESS) + { + log_error("waitforEvent failed\n"); + goto exit; + } + fflush(stdout); + + if(allTestCase[testId]->_type == TYPE_ADDRESS_SPACE && isKernelPFormat(allTestCase[testId],testNum)) + { + // Read the OpenCL output buffer (d_out) to the host output array (out) + if(!is64bAddressSpace(device))//32-bit address space + { + clEnqueueReadBuffer(queue, d_out, CL_TRUE, 0, sizeof(cl_int),&out32, + 0, NULL, NULL); + } + else //64-bit address space + { + clEnqueueReadBuffer(queue, d_out, CL_TRUE, 0, sizeof(cl_ulong),&out64, + 0, NULL, NULL); + } + } + + // + //Get the output printed from the kernel to _analysisBuffer + //and verify its correctness + getAnalysisBuffer(_analysisBuffer); + if(!is64bAddressSpace(device)) //32-bit address space + { + if(0 != verifyOutputBuffer(_analysisBuffer,allTestCase[testId],testNum,(cl_ulong) out32)) + err = ++s_test_fail; + } + else //64-bit address space + { + if(0 != verifyOutputBuffer(_analysisBuffer,allTestCase[testId],testNum,out64)) + err = ++s_test_fail; + } +exit: + if(clReleaseKernel(kernel) != CL_SUCCESS) + log_error("clReleaseKernel failed\n"); + if(clReleaseProgram(program) != CL_SUCCESS) + log_error("clReleaseProgram failed\n"); + ++s_test_cnt; + return err; +} +//----------------------------------------- +// printUsage +//----------------------------------------- +static void printUsage( void ) +{ + log_info("test_printf: [-cghw] [start_test_num] \n"); + log_info(" default is to run the full test on the default device\n"); + log_info(" start_test_num will start running from that num\n"); +} + +//----------------------------------------- +// printArch +//----------------------------------------- +static void printArch( void ) +{ + log_info( "sizeof( void*) = %d\n", (int) sizeof( void *) ); + +#if defined( __APPLE__ ) + +#if defined( __ppc__ ) + log_info( "ARCH:\tppc\n" ); +#elif defined( __ppc64__ ) + log_info( "ARCH:\tppc64\n" ); +#elif defined( __i386__ ) + log_info( "ARCH:\ti386\n" ); +#elif defined( __x86_64__ ) + log_info( "ARCH:\tx86_64\n" ); +#elif defined( __arm__ ) + log_info( "ARCH:\tarm\n" ); +#else +#error unknown arch +#endif + + int type = 0; + size_t typeSize = sizeof( type ); + sysctlbyname( "hw.cputype", &type, &typeSize, NULL, 0 ); + log_info( "cpu type:\t%d\n", type ); + typeSize = sizeof( type ); + sysctlbyname( "hw.cpusubtype", &type, &typeSize, NULL, 0 ); + log_info( "cpu subtype:\t%d\n", type ); + +#endif +} + +//----------------------------------------- +// notify_callback +//----------------------------------------- +void CL_CALLBACK notify_callback(const char *errinfo, const void *private_info, size_t cb, void *user_data) +{ + log_info( "%s\n", errinfo ); +} + + +//----------------------------------------- +// main +//----------------------------------------- +int main(int argc, const char* argv[]) { + int i; + cl_device_type device_type = CL_DEVICE_TYPE_DEFAULT; + cl_platform_id platform_id; + long test_filter_num = 0; // test number to run or 0 + const char* exec_testname = NULL; + cl_device_id device_id; + uint32_t device_frequency = 0; + uint32_t compute_devices = 0; + + + + test_start(); + + argc = parseCustomParam(argc, argv); + if (argc == -1) + { + test_finish(); + return -1; + } + + // Check the environmental to see if there is device preference + char *device_env = getenv("CL_DEVICE_TYPE"); + if (device_env != NULL) { + if( strcmp( device_env, "gpu" ) == 0 || strcmp( device_env, "CL_DEVICE_TYPE_GPU" ) == 0 ) + device_type = CL_DEVICE_TYPE_GPU; + else if( strcmp( device_env, "cpu" ) == 0 || strcmp( device_env, "CL_DEVICE_TYPE_CPU" ) == 0 ) + device_type = CL_DEVICE_TYPE_CPU; + else if( strcmp( device_env, "accelerator" ) == 0 || strcmp( device_env, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + device_type = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( device_env, "default" ) == 0 || strcmp( device_env, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + device_type = CL_DEVICE_TYPE_DEFAULT; + else + { + log_error( "Unknown CL_DEVICE_TYPE environment variable: %s.\nAborting...\n", device_env ); + abort(); + } + } + + // Determine if we want to run a particular test or if we want to + // start running from a certain point and if we want to run on cpu/gpu + // usage: test_printf [test_name] [start test num] [run_long] + // default is to run all tests on the gpu and be short + // test names are of the form printf_testId + + for (i=1; i < argc; ++i) { + const char *arg = argv[i]; + if (arg == NULL) + break; + + if (arg[0] == '-') + { + arg++; + while(*arg != '\0') + { + switch(*arg) { + case 'h': + printUsage(); + return 0; + default: + log_error( " <-- unknown flag: %c (0x%2.2x)\n)", *arg, *arg ); + printUsage(); + return 0; + } + arg++; + } + } + else { + char* t = NULL; + long num = strtol(argv[i], &t, 0); + if (t != argv[i]) + test_filter_num = num; + else if( 0 == strcmp( argv[i], "CL_DEVICE_TYPE_CPU" ) ) + device_type = CL_DEVICE_TYPE_CPU; + else if( 0 == strcmp( argv[i], "CL_DEVICE_TYPE_GPU" ) ) + device_type = CL_DEVICE_TYPE_GPU; + else if( 0 == strcmp( argv[i], "CL_DEVICE_TYPE_ACCELERATOR" ) ) + device_type = CL_DEVICE_TYPE_ACCELERATOR; + else if( 0 == strcmp( argv[i], "CL_DEVICE_TYPE_DEFAULT" ) ) + device_type = CL_DEVICE_TYPE_DEFAULT; + else { + // assume it is a test name that we want to execute + exec_testname = argv[i]; + } + } + } + + + int err; + int fd = acquireOutputStream(); + + // Get platform + err = clGetPlatformIDs(1, &platform_id, NULL); + checkErr(err,"clGetPlatformIDs failed"); + + + // Get Device information + err = clGetDeviceIDs(platform_id, device_type, 1, &device_id, 0); + checkErr(err,"clGetComputeDevices"); + + + err = clGetDeviceInfo(device_id, CL_DEVICE_TYPE, sizeof(cl_device_type), &device_type, NULL); + checkErr(err,"clGetComputeConfigInfo 1"); + + + size_t config_size = sizeof( device_frequency ); +#if MULTITHREAD + if( (err = clGetDeviceInfo(device_id, CL_DEVICE_MAX_COMPUTE_UNITS, config_size, &compute_devices, NULL )) ) +#endif + compute_devices = 1; + + config_size = sizeof(device_frequency); + if((err = clGetDeviceInfo(device_id, CL_DEVICE_MAX_CLOCK_FREQUENCY, config_size, &device_frequency, NULL ))) + device_frequency = 1; + + releaseOutputStream(fd); + + log_info( "\nCompute Device info:\n" ); + log_info( "\tProcessing with %d devices\n", compute_devices ); + log_info( "\tDevice Frequency: %d MHz\n", device_frequency ); + + + + printDeviceHeader( device_id ); + + printArch(); + + err = check_opencl_version(device_id,1,2); + if( err != CL_SUCCESS ) { + print_missing_feature(err,"printf"); + test_finish(); + return err; + } + + log_info( "Test binary built %s %s\n", __DATE__, __TIME__ ); + + fd = acquireOutputStream(); + + cl_context context = clCreateContext(NULL, 1, &device_id, notify_callback, NULL, NULL); + checkNull(context, "clCreateContext"); + + cl_command_queue queue = clCreateCommandQueueWithProperties(context, device_id, 0, NULL); + checkNull(queue, "clCreateCommandQueue"); + + // Forall types + for (int testId = 0; testId < TYPE_COUNT; ++testId) { + if (test_filter_num && (testId != test_filter_num)) { + releaseOutputStream(fd); + log_info("\n*** Skipping printf for %s ***\n",strType[testId]); + fd = acquireOutputStream(); + } + else { + releaseOutputStream(fd); + log_info("\n*** Testing printf for %s ***\n",strType[testId]); + fd = acquireOutputStream(); + //For all formats + for(unsigned int testNum = 0;testNum < allTestCase[testId]->_testNum;++testNum){ + releaseOutputStream(fd); + if(allTestCase[testId]->_type == TYPE_VECTOR) + log_info("%d)testing printf(\"%sv%s%s\",%s)\n",testNum,allTestCase[testId]->_genParameters[testNum].vectorFormatFlag,allTestCase[testId]->_genParameters[testNum].vectorSize, + allTestCase[testId]->_genParameters[testNum].vectorFormatSpecifier,allTestCase[testId]->_genParameters[testNum].dataRepresentation); + else if(allTestCase[testId]->_type == TYPE_ADDRESS_SPACE) + { + if(isKernelArgument(allTestCase[testId], testNum)) + log_info("%d)testing kernel //argument %s \n printf(%s,%s)\n",testNum,allTestCase[testId]->_genParameters[testNum].addrSpaceArgumentTypeQualifier, + allTestCase[testId]->_genParameters[testNum].genericFormat,allTestCase[testId]->_genParameters[testNum].addrSpaceParameter); + else + log_info("%d)testing kernel //variable %s \n printf(%s,%s)\n",testNum,allTestCase[testId]->_genParameters[testNum].addrSpaceVariableTypeQualifier, + allTestCase[testId]->_genParameters[testNum].genericFormat,allTestCase[testId]->_genParameters[testNum].addrSpaceParameter); + } + else + log_info("%d)testing printf(\"%s\",%s)\n",testNum,allTestCase[testId]->_genParameters[testNum].genericFormat,allTestCase[testId]->_genParameters[testNum].dataRepresentation); + fd = acquireOutputStream(); + + // Long support for varible type + if(allTestCase[testId]->_type == TYPE_VECTOR && !strcmp(allTestCase[testId]->_genParameters[testNum].dataType,"long") && !isLongSupported(device_id)) + continue; + + // Long support for address in FULL_PROFILE/EMBEDDED_PROFILE + bool isLongSupport = true; + if(allTestCase[testId]->_type == TYPE_ADDRESS_SPACE && isKernelPFormat(allTestCase[testId],testNum) && !isLongSupported(device_id)) + isLongSupport = false; + + // Perform the test + if (doTest(queue, context,testId,testNum,device_id,isLongSupport) != 0) + { + releaseOutputStream(fd); + log_error("*** FAILED ***\n\n"); + fd = acquireOutputStream(); + } + else + { + releaseOutputStream(fd); + log_info("Passed\n"); + fd = acquireOutputStream(); + } + } + } + } + + int error = clFinish(queue); + if (error) { + log_error("clFinish failed: %d\n", error); + } + + if(clReleaseCommandQueue(queue)!=CL_SUCCESS) + log_error("clReleaseCommandQueue\n"); + if(clReleaseContext(context)!= CL_SUCCESS) + log_error("clReleaseContext\n"); + + releaseOutputStream(fd); + + + if (s_test_fail == 0) { + if (s_test_cnt > 1) + log_info("PASSED %d of %d tests.\n", s_test_cnt, s_test_cnt); + else + log_info("PASSED test.\n"); + } else if (s_test_fail > 0) { + if (s_test_cnt > 1) + { + log_error("FAILED %d of %d tests.\n", s_test_fail, s_test_cnt); + log_info("PASSED %d of %d tests.\n", s_test_cnt - s_test_fail, s_test_cnt); + } + else + log_error(" FAILED test.\n"); + } + + test_finish(); + return s_test_fail; +} diff --git a/test_conformance/printf/test_printf.h b/test_conformance/printf/test_printf.h new file mode 100644 index 00000000..776ec3ef --- /dev/null +++ b/test_conformance/printf/test_printf.h @@ -0,0 +1,133 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TESTPRINTF_INCLUDED_H +#define TESTPRINTF_INCLUDED_H + +#include "../../test_common/harness/compat.h" + +#include +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +// Enable the test to be used with ATF +#if USE_ATF +// export BUILD_WITH_ATF=1 +#include +#define test_start() ATFTestStart() +#define log_info ATFLogInfo +#define log_error ATFLogError +#define test_finish() ATFTestFinish() +#else +#define test_start() +#define log_info printf +#define log_error printf +#define test_finish() +#endif // USE_ATF + +#define ANALYSIS_BUFFER_SIZE 256 + +//----------------------------------------- +// Definitions and initializations +//----------------------------------------- + +//----------------------------------------- +// Types +//----------------------------------------- +enum Type + { + TYPE_INT, + TYPE_FLOAT, + TYPE_OCTAL, + TYPE_UNSIGNED, + TYPE_HEXADEC, + TYPE_CHAR, + TYPE_STRING, + TYPE_VECTOR, + TYPE_ADDRESS_SPACE, + TYPE_COUNT +}; + +struct printDataGenParameters +{ + const char* genericFormat; + const char* dataRepresentation; + const char* vectorFormatFlag; + const char* vectorFormatSpecifier; + const char* dataType; + const char* vectorSize; + const char* addrSpaceArgumentTypeQualifier; + const char* addrSpaceVariableTypeQualifier; + const char* addrSpaceParameter; + const char* addrSpacePAdd; +}; + +//----------------------------------------- +//Test Case +//----------------------------------------- + +struct testCase +{ + unsigned int _testNum; //test number + enum Type _type; //(data)type for test + //const char** _strPrint; //auxiliary data to build the code for kernel source + const char** _correctBuffer; //look-up table for correct results for printf + struct printDataGenParameters* _genParameters; //auxiliary data to build the code for kernel source +}; + + +extern const char* strType[]; +extern testCase* allTestCase[]; + +size_t verifyOutputBuffer(char *analysisBuffer,testCase* pTestCase,size_t testId,cl_ulong pAddr = 0); + +// Helpful macros + +// The next three functions check on different return values. Returns -1 +// if the check failed +#define checkErr(err, msg) \ + if (err != CL_SUCCESS) { \ + log_error("%s failed errcode:%d\n", msg, err); \ + return -1; \ + } + +#define checkZero(val, msg) \ + if (val == 0) { \ + log_error("%s failed errcode:%d\n", msg, err); \ + return -1; \ + } + +#define checkNull(ptr, msg) \ + if (!ptr) { \ + log_error("%s failed\n", msg); \ + return -1; \ + } + +// When a helper returns a negative one, we want to return from main +// with negative one. This helper prevents me from having to write +// this multiple time +#define checkHelperErr(err) \ + if (err == -1) { \ + return err; \ + } + +#endif // TESTSPRINTF_INCLUDED_H diff --git a/test_conformance/printf/util_printf.c b/test_conformance/printf/util_printf.c new file mode 100644 index 00000000..5bd9be1a --- /dev/null +++ b/test_conformance/printf/util_printf.c @@ -0,0 +1,894 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include "test_printf.h" + + +#if defined (_WIN32) +#define strtoull _strtoi64 +#endif + +const char* strType[] = {"int","float","octal","unsigned","hexadecimal","char","string","vector","address space"}; + + + +//================================== + +// int + +//================================== + +//------------------------------------------------------ + +// [string] format | [string] int-data representation | + +//------------------------------------------------------ + +struct printDataGenParameters printIntGenParameters[] = { + + //(Minimum)Five-wide,default(right)-justified + + {"%5d","10"}, + + //(Minimum)Five-wide,left-justified + + {"%-5d","10"}, + + //(Minimum)Five-wide,default(right)-justified,zero-filled + + {"%05d","10"}, + + //(Minimum)Five-wide,default(right)-justified,with sign + + {"%+5d","10"}, + + //(Minimum)Five-wide ,left-justified,with sign + + {"%-+5d","10"}, + + //(Minimum)Five-digit(zero-filled in absent digits),default(right)-justified + + {"%.5i","100"}, + + //(Minimum)Six-wide,Five-digit(zero-filled in absent digits),default(right)-justified + + {"%6.5i","100"}, + + //0 and - flag both apper ==>0 is ignored,left-justified,capital I + + {"%-06i","100"}, + + //(Minimum)Six-wide,Five-digit(zero-filled in absent digits),default(right)-justified + + {"%06.5i","100"} + +}; + +//------------------------------------------------ + +// Lookup table - [string]int-correct buffer | + +//------------------------------------------------ + +const char *correctBufferInt[] = { + + " 10", + + "10 ", + + "00010", + + " +10", + + "+10 ", + + "00100", + + " 00100", + + "100 ", + + " 00100" + +}; + + + + + +//----------------------------------------------- + +//test case for int | + +//----------------------------------------------- + +testCase testCaseInt = { + + sizeof(correctBufferInt)/sizeof(char*), + + TYPE_INT, + + correctBufferInt, + + printIntGenParameters + +}; + + + + + +//============================================== + +// float + +//============================================== + + + +//-------------------------------------------------------- + +// [string] format | [string] float-data representation | + +//-------------------------------------------------------- + +struct printDataGenParameters printFloatGenParameters[] = { + + //Default(right)-justified + + {"%f","10.3456"}, + + //One position after the decimal,default(right)-justified + + {"%.1f","10.3456"}, + + //Two positions after the decimal,default(right)-justified + + {"%.2f","10.3456"}, + + //(Minimum)Eight-wide,three positions after the decimal,default(right)-justified + + {"%8.3f","10.3456"}, + + //(Minimum)Eight-wide,two positions after the decimal,zero-filled,default(right)-justified + + {"%08.2f","10.3456"}, + + //(Minimum)Eight-wide,two positions after the decimal,left-justified + + {"%-8.2f","10.3456"}, + + //(Minimum)Eight-wide,two positions after the decimal,with sign,default(right)-justified + + {"%+8.2f","-10.3456"}, + + //Zero positions after the decimal([floor]rounding),default(right)-justified + + {"%.0f","0.1"}, + + //Zero positions after the decimal([ceil]rounding),default(right)-justified + + {"%.0f","0.6"}, + + //Zero-filled,default positions number after the decimal,default(right)-justified + + {"%0f","0.6"}, + + //Double argument representing floating-point,used by f style,default(right)-justified + + {"%4g","12345.6789"}, + + //Double argument representing floating-point,used by e style,default(right)-justified + + {"%4.2g","12345.6789"}, + + //Double argument representing floating-point,used by f style,default(right)-justified + + {"%4G","0.0000023"}, + + //Double argument representing floating-point,used by e style,default(right)-justified + + {"%4G","0.023"}, + + //Double argument representing floating-point,with exponent,left-justified,default(right)-justified + + {"%-#20.15e","789456123.0"}, + + //Double argument representing floating-point,with exponent,left-justified,with sign,capital E,default(right)-justified + + {"%+#21.15E","789456123.0"}, + +#if ! defined( __ANDROID__ ) + + //Double argument representing floating-point,in [-]xh.hhhhpAd style + + {"%.6a","0.1"}, + + //(Minimum)Ten-wide,Double argument representing floating-point,in xh.hhhhpAd style,default(right)-justified + + {"%10.2a","9990.235"}, + +#endif + + //Infinity (1.0/0.0) + + {"%f","1.0f/0.0f"}, + + //NaN + + {"%f","sqrt(-1.0f)"}, + + //NaN + {"%f","acospi(2.0f)"} + }; +//-------------------------------------------------------- + +// Lookup table - [string]float-correct buffer | + +//-------------------------------------------------------- + +const char* correctBufferFloat[] = { + + "10.345600", + + "10.3", + + "10.35", + + " 10.346", + + "00010.35", + + "10.35 ", + + " -10.35", + + "0", + + "1", + + "0.600000", + + "12345.7", + + "1.2e+4", + + "2.3E-6", + + "0.023", + + "7.894561230000000e+8", + + "+7.894561230000000E+8", + +#if ! defined( __ANDROID__ ) + + "0x1.99999ap-4", + + "0x1.38p+13", + +#endif + + "inf", + + "-nan", + + "nan" +}; + +//--------------------------------------------------------- + +//Test case for float | + +//--------------------------------------------------------- + +testCase testCaseFloat = { + + sizeof(correctBufferFloat)/sizeof(char*), + + TYPE_FLOAT, + + correctBufferFloat, + + printFloatGenParameters + +}; + + + +//========================================================= + +// octal + +//========================================================= + + + +//--------------------------------------------------------- + +// [string] format | [string] octal-data representation | + +//--------------------------------------------------------- + +struct printDataGenParameters printOctalGenParameters[] = { + + //Default(right)-justified + + {"%o","10"}, + + //Five-digit,default(right)-justified + + {"%.5o","10"}, + + //Default(right)-justified,increase precision + + {"%#o","100000000"}, + + //(Minimum)Four-wide,Five-digit,0-flag ignored(because of precision),default(right)-justified + + {"%04.5o","10"} + +}; + +//------------------------------------------------------- + +// Lookup table - [string] octal-correct buffer | + +//------------------------------------------------------- + + + +const char* correctBufferOctal[] = { + + "12", + + "00012", + + "0575360400", + + "00012" + +}; + +//------------------------------------------------------- + +//Test case for octal | + +//------------------------------------------------------- + +testCase testCaseOctal = { + + sizeof(correctBufferOctal)/sizeof(char*), + + TYPE_OCTAL, + + correctBufferOctal, + + printOctalGenParameters + +}; + + + +//========================================================= + +// unsigned + +//========================================================= + + + +//--------------------------------------------------------- + +// [string] format | [string] unsined-data representation | + +//--------------------------------------------------------- + +struct printDataGenParameters printUnsignedGenParameters[] = { + + //Default(right)-justified + + {"%u","10"}, + + //Zero precision for zero,default(right)-justified + + {"%.0u","0"}, + +}; + +//------------------------------------------------------- + +// Lookup table - [string] octal-correct buffer | + +//------------------------------------------------------- + + + +const char* correctBufferUnsigned[] = { + + "10", + + "" + +}; + +//------------------------------------------------------- + +//Test case for octal | + +//------------------------------------------------------- + +testCase testCaseUnsigned = { + + sizeof(correctBufferUnsigned)/sizeof(char*), + + TYPE_UNSIGNED, + + correctBufferUnsigned, + + printUnsignedGenParameters + +}; + + + +//======================================================= + +// hexadecimal + +//======================================================= + + + +//-------------------------------------------------------------- + +// [string] format | [string] hexadecimal-data representation | + +//-------------------------------------------------------------- + +struct printDataGenParameters printHexadecimalGenParameters[] = { + + //Add 0x,low x,default(right)-justified + + {"%#x","0xABCDEF"}, + + //Add 0x,capital X,default(right)-justified + + {"%#X","0xABCDEF"}, + + //Not add 0x,if zero,default(right)-justified + + {"%#X","0"}, + + //(Minimum)Eight-wide,default(right)-justified + + {"%8x","399"}, + + //(Minimum)Four-wide,zero-filled,default(right)-justified + + {"%04x","399"} + +}; + +//-------------------------------------------------------------- + +// Lookup table - [string]hexadecimal-correct buffer | + +//-------------------------------------------------------------- + + + +const char* correctBufferHexadecimal[] = { + + "0xabcdef", + + "0XABCDEF", + + "0", + + " 18f", + + "018f" + +}; + +//-------------------------------------------------------------- + +//Test case for hexadecimal | + +//-------------------------------------------------------------- + +testCase testCaseHexadecimal = { + + sizeof(correctBufferHexadecimal)/sizeof(char*), + + TYPE_HEXADEC, + + correctBufferHexadecimal, + + printHexadecimalGenParameters + +}; + + + +//============================================================= + +// char + +//============================================================= + + + +//----------------------------------------------------------- + +// [string] format | [string] string-data representation | + +//----------------------------------------------------------- + +struct printDataGenParameters printCharGenParameters[] = { + + //Four-wide,zero-filled,default(right)-justified + + {"%4c","\'1\'"}, + + //Four-wide,left-justified + + {"%-4c","\'1\'"}, + + //(unsigned) int argument,default(right)-justified + + {"%c","66"} + +}; + +//--------------------------------------------------------- + +// Lookup table -[string] char-correct buffer | + +//--------------------------------------------------------- + +const char * correctBufferChar[] = { + + " 1", + + "1 ", + + "B", + +}; + + + +//---------------------------------------------------------- + +//Test case for char | + +//---------------------------------------------------------- + +testCase testCaseChar = { + + sizeof(correctBufferChar)/sizeof(char*), + + TYPE_CHAR, + + correctBufferChar, + + printCharGenParameters + +}; + + + +//========================================================== + +// string + +//========================================================== + + + +//-------------------------------------------------------- + +// [string]format | [string] string-data representation | + +//-------------------------------------------------------- + +struct printDataGenParameters printStringGenParameters[] = { + + //(Minimum)Four-wide,zero-filled,default(right)-justified + + {"%4s","\"foo\""}, + + //One-digit(precision ignored),left-justified + + {"%.1s","\"foo\""}, + + //%% specification + + {"%s","\"%%\""}, + + //null string + + {"%s","(void*)0"} + +}; + +//--------------------------------------------------------- + +// Lookup table -[string] string-correct buffer | + +//--------------------------------------------------------- + +const char * correctBufferString[] = { + + " foo", + + "f", + + "%%", + + "(null)" + +}; + +//--------------------------------------------------------- + +//Test case for string | + +//--------------------------------------------------------- + +testCase testCaseString = { + + sizeof(correctBufferString)/sizeof(char*), + + TYPE_STRING, + + correctBufferString, + + printStringGenParameters + +}; + + + +//========================================================= + +// vector + +//========================================================= + + + +//------------------------------------------------------------------------------------------------------------------- + +//[string] flag | [string] specifier | [string] type | [string] vector-data representation | [string] vector size | + +//------------------------------------------------------------------------------------------------------------------- + +struct printDataGenParameters printVectorGenParameters[]={ + + //(Minimum)Two-wide,two positions after decimal + + {NULL,"(1.0f,2.0f,3.0f,4.0f)","%2.2","hlf","float","4"}, + + //Alternative form,uchar argument + + {NULL,"(0xFA,0xFB)","%#","hhx","uchar","2"}, + + //Alternative form,ushort argument + + {NULL,"(0x1234,0x8765)","%#","hx","ushort","2"}, + + //Alternative form,uint argument + + {NULL,"(0x12345678,0x87654321)","%#","hlx","uint","2"}, + + //Alternative form,long argument + + {NULL,"(12345678,98765432)","%","ld","long","2"} + +}; + +//------------------------------------------------------------ + +// Lookup table -[string] vector-correct buffer | + +//------------------------------------------------------------ + +const char * correctBufferVector[] = { + + "1.00,2.00,3.00,4.00", + + "0xfa,0xfb", + + "0x1234,0x8765", + + "0x12345678,0x87654321", + + "12345678,98765432" + +}; + +//----------------------------------------------------------- + +//Test case for vector | + +//----------------------------------------------------------- + +testCase testCaseVector = { + + sizeof(correctBufferVector)/(sizeof(char *)), + + TYPE_VECTOR, + + correctBufferVector, + + printVectorGenParameters + +}; + + + +//================================================================== + +// address space + +//================================================================== + + + +//------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +// [string] argument type qualifier |[string] variable type qualifier + initialization | [string] format | [string] parameter |[string]%p indicator/additional code | + +//------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + + +struct printDataGenParameters printAddrSpaceGenParameters[]={ + + //Global memory region + + {"\"%d\\n\"",NULL,NULL,NULL,NULL,NULL,"__global int* x","","*x",""}, + + //Global,constant, memory region + + {"\"%d\\n\"",NULL,NULL,NULL,NULL,NULL,"constant int* x","","*x",""}, + + //Local memory region + + {"\"%+d\\n\"",NULL,NULL,NULL,NULL,NULL,"","local int x;\n x= (int)3;\n","x",""}, + + //Private memory region + + {"\"%i\\n\"",NULL,NULL,NULL,NULL,NULL,"","private int x;\n x = (int)-1;\n","x",""}, + + //Address of void * from global memory region + + {"\"%p\\n\"",NULL,NULL,NULL,NULL,NULL,"__global void* x,__global intptr_t* xAddr","","x","*xAddr = (intptr_t)x;\n"} + +}; + +//------------------------------------------------------------------------------- + +// Lookup table -[string] address space -correct buffer | + +//------------------------------------------------------------------------------- + +const char * correctAddrSpace[] = { + + "2","2","+3","-1","" + +}; + +//------------------------------------------------------------------------------- + +//Test case for address space | + +//------------------------------------------------------------------------------- + +testCase testCaseAddrSpace = { + + sizeof(correctAddrSpace)/(sizeof(char *)), + + TYPE_ADDRESS_SPACE, + + correctAddrSpace, + + printAddrSpaceGenParameters + +}; + + + +//------------------------------------------------------------------------------- + +//All Test cases | + +//------------------------------------------------------------------------------- + +testCase* allTestCase[] = {&testCaseInt,&testCaseFloat,&testCaseOctal,&testCaseUnsigned,&testCaseHexadecimal,&testCaseChar,&testCaseString,&testCaseVector,&testCaseAddrSpace}; + + +//----------------------------------------- + +// Check functions + +//----------------------------------------- + +size_t verifyOutputBuffer(char *analysisBuffer,testCase* pTestCase,size_t testId,cl_ulong pAddr) +{ + int terminatePos = strlen(analysisBuffer); + if(terminatePos > 0) + { + analysisBuffer[terminatePos - 1] = '\0'; + } + + //Convert analysis buffer to long for address space + if(pTestCase->_type == TYPE_ADDRESS_SPACE && strcmp(pTestCase->_genParameters[testId].addrSpacePAdd,"")) + + { + char analysisBufferTmp[ANALYSIS_BUFFER_SIZE]; + + if(strstr(analysisBuffer,"0x") == NULL) + // Need to prepend 0x to ASCII number before calling strtol. + strcpy(analysisBufferTmp,"0x"); + + else analysisBufferTmp[0]='\0'; + strcat(analysisBufferTmp,analysisBuffer); + if (sizeof(long) == 8) { + if(strtoul(analysisBufferTmp,NULL,0) == pAddr) return 0; + } + else { + if(strtoull(analysisBufferTmp,NULL,0) == pAddr) return 0; + } + return 1; + + } + + char* exp; + //Exponenent representation + if((exp = strstr(analysisBuffer,"E+")) != NULL || (exp = strstr(analysisBuffer,"e+")) != NULL || (exp = strstr(analysisBuffer,"E-")) != NULL || (exp = strstr(analysisBuffer,"e-")) != NULL) + { + char correctExp[3]={0}; + strncpy(correctExp,exp,2); + + + char* eCorrectBuffer = strstr((char*)pTestCase->_correctBuffer[testId],correctExp); + if(eCorrectBuffer == NULL) + return false; + + eCorrectBuffer+=2; + exp += 2; + + //Exponent always contains at least two digits + if(strlen(exp) < 2) + return false; + //Scip leading zeros in the exponent + while(*exp == '0') + ++exp; + return strcmp(eCorrectBuffer,exp); + } + if(!strcmp(pTestCase->_correctBuffer[testId],"inf")) + return strcmp(analysisBuffer,"inf")&&strcmp(analysisBuffer,"infinity")&&strcmp(analysisBuffer,"1.#INF00")&&strcmp(analysisBuffer,"Inf"); + if(!strcmp(pTestCase->_correctBuffer[testId],"nan") || !strcmp(pTestCase->_correctBuffer[testId],"-nan")) { + return strcmp(analysisBuffer,"nan")&&strcmp(analysisBuffer,"-nan")&&strcmp(analysisBuffer,"1.#IND00")&&strcmp(analysisBuffer,"-1.#IND00")&&strcmp(analysisBuffer,"NaN")&&strcmp(analysisBuffer,"nan(ind)")&&strcmp(analysisBuffer,"nan(snan)"); + } + return strcmp(analysisBuffer,pTestCase->_correctBuffer[testId]); +} + diff --git a/test_conformance/profiling/CMakeLists.txt b/test_conformance/profiling/CMakeLists.txt new file mode 100644 index 00000000..ab6ca5f9 --- /dev/null +++ b/test_conformance/profiling/CMakeLists.txt @@ -0,0 +1,23 @@ +set(MODULE_NAME PROFILING) + +set(${MODULE_NAME}_SOURCES + main.c + readArray.c + writeArray.c + readImage.c + writeImage.c + copy.c + execute.c + execute_multipass.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/typeWrappers.cpp + ../../test_common/harness/imageHelpers.cpp + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) diff --git a/test_conformance/profiling/Jamfile b/test_conformance/profiling/Jamfile new file mode 100644 index 00000000..7dad6323 --- /dev/null +++ b/test_conformance/profiling/Jamfile @@ -0,0 +1,22 @@ +project + : requirements + gcc:-xc++ + msvc:"/TP" + ; + +exe test_profiling + : copy.c + execute.c + execute_multipass.c + main.c + readArray.c + readImage.c + writeArray.c + writeImage.c + ; + +install dist + : test_profiling + : debug:$(DIST)/debug/tests/test_conformance/profiling + release:$(DIST)/release/tests/test_conformance/profiling + ; diff --git a/test_conformance/profiling/Makefile b/test_conformance/profiling/Makefile new file mode 100644 index 00000000..f1834fbc --- /dev/null +++ b/test_conformance/profiling/Makefile @@ -0,0 +1,45 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c readArray.c writeArray.c readImage.c writeImage.c copy.c execute.c execute_multipass.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/typeWrappers.cpp \ + ../../test_common/harness/imageHelpers.cpp \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/conversions.c \ + ../../test_common/harness/kernelHelpers.c + +SOURCES = $(abspath $(SRCS)) + + +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. + +FRAMEWORK = ${SOURCES} +HEADERS = +TARGET = test_profiling +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +#COMPILERFLAGS = -c -Wall -g -DUSE_LOCAL_THREADS +CC = c++ +CFLAGS = $(COMPILERFLAGS) $(RC_CFLAGS) ${USE_ATF} +CXXFLAGS= $(COMPILERFLAGS) $(RC_CFLAGS) ${USE_ATF} +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/profiling/copy.c b/test_conformance/profiling/copy.c new file mode 100644 index 00000000..9256c2e9 --- /dev/null +++ b/test_conformance/profiling/copy.c @@ -0,0 +1,869 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/conversions.h" + +//--- the code for the kernel executables +static const char *write_kernel_code = +"\n" +"__kernel void test_write(__global unsigned char *src, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(dstimg) + tid_x;\n" +" float4 color;\n" +"\n" +" indx *= 4;\n" +" color = (float4)((float)src[indx+0], (float)src[indx+1], (float)src[indx+2], (float)src[indx+3]);\n" +" color /= (float4)(255.0f, 255.0f, 255.0f, 255.0f);\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n"; + + +//--- the verify functions +static int verify_subimage( unsigned char *src, unsigned char *dst, size_t srcx, size_t srcy, + size_t dstx, size_t dsty, size_t subw, size_t subh, size_t pitch, size_t element_pitch ) +{ + size_t i, j, k; + size_t srcj, dstj; + size_t srcLoc, dstLoc; + + for( j = 0; j < subh; j++ ){ + srcj = ( j + srcy ) * pitch * element_pitch; + dstj = ( j + dsty ) * pitch * element_pitch; + for( i = 0; i < subw; i++ ){ + srcLoc = srcj + ( i + srcx ) * element_pitch; + dstLoc = dstj + ( i + dstx ) * element_pitch; + for( k = 0; k < element_pitch; k++ ){ // test each channel + if( src[srcLoc+k] != dst[dstLoc+k] ){ + return -1; + } + } + } + } + + return 0; +} + + +static int verify_copy_array( int *inptr, int *outptr, int n ) +{ + int i; + + for( i = 0; i < n; i++ ) { + if( outptr[i] != inptr[i] ) + return -1; + } + + return 0; +} + + +//----- helper functions +static cl_uchar *generate_image( int n, MTdata d ) +{ + cl_uchar *ptr = (cl_uchar *)malloc( n ); + int i; + + for( i = 0; i < n; i++ ) + ptr[i] = (cl_uchar)genrand_int32(d); + + return ptr; +} + + +static int copy_size( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements, MTdata d ) +{ + cl_mem streams[2]; + cl_event copyEvent; + cl_ulong queueStart, submitStart, writeStart, writeEnd; + cl_int *int_input_ptr, *int_output_ptr; + int err = 0; + int i; + + int_input_ptr = (cl_int*)malloc(sizeof(cl_int) * num_elements); + int_output_ptr = (cl_int*)malloc(sizeof(cl_int) * num_elements); + + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * num_elements, NULL, &err ); + if( !streams[0] ){ + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * num_elements, NULL, &err ); + if( !streams[1] ){ + log_error("clCreateBuffer failed\n"); + return -1; + } + + for (i=0; i> 30; // seed with incorrect data + } + + err = clEnqueueWriteBuffer( queue, streams[0], true, 0, sizeof(cl_int)*num_elements, (void *)int_input_ptr, 0, NULL, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clWriteArray failed" ); + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + free( (void *)int_output_ptr ); + free( (void *)int_input_ptr ); + return -1; + } + + err = clEnqueueCopyBuffer( queue, streams[0], streams[1], 0, 0, sizeof(cl_int)*num_elements, 0, NULL, ©Event ); + if( err != CL_SUCCESS ){ + print_error( err, "clCopyArray failed" ); + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + free( (void *)int_output_ptr ); + free( (void *)int_input_ptr ); + return -1; + } + + // This synchronization point is needed in order to assume the data is valid. + // Getting profiling information is not a synchronization point. + err = clWaitForEvents( 1, ©Event ); + if( err != CL_SUCCESS ) + { + clReleaseEvent(copyEvent); + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + free( (void *)int_output_ptr ); + free( (void *)int_input_ptr ); + return -1; + } + + // test profiling + while( ( err = clGetEventProfilingInfo( copyEvent, CL_PROFILING_COMMAND_QUEUED, sizeof( cl_ulong ), &queueStart, NULL ) ) == + CL_PROFILING_INFO_NOT_AVAILABLE ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(copyEvent); + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + free( (void *)int_output_ptr ); + free( (void *)int_input_ptr ); + return -1; + } + + while( ( err = clGetEventProfilingInfo( copyEvent, CL_PROFILING_COMMAND_SUBMIT, sizeof( cl_ulong ), &submitStart, NULL ) ) == + CL_PROFILING_INFO_NOT_AVAILABLE ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(copyEvent); + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + free( (void *)int_output_ptr ); + free( (void *)int_input_ptr ); + return -1; + } + + err = clGetEventProfilingInfo( copyEvent, CL_PROFILING_COMMAND_START, sizeof( cl_ulong ), &writeStart, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(copyEvent); + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + free( (void *)int_output_ptr ); + free( (void *)int_input_ptr ); + return -1; + } + + err = clGetEventProfilingInfo( copyEvent, CL_PROFILING_COMMAND_END, sizeof( cl_ulong ), &writeEnd, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(copyEvent); + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + free( (void *)int_output_ptr ); + free( (void *)int_input_ptr ); + return -1; + } + + err = clEnqueueReadBuffer( queue, streams[1], true, 0, sizeof(cl_int)*num_elements, (void *)int_output_ptr, 0, NULL, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clEnqueueReadBuffer failed" ); + clReleaseEvent(copyEvent); + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + free( (void *)int_output_ptr ); + free( (void *)int_input_ptr ); + return -1; + } + + if( verify_copy_array(int_input_ptr, int_output_ptr, num_elements) ){ + log_error( "test failed\n" ); + err = -1; + } + else{ + log_info( "test passed\n" ); + err = 0; + } + + // cleanup + clReleaseEvent(copyEvent); + clReleaseMemObject( streams[0] ); + clReleaseMemObject( streams[1] ); + free( (void *)int_output_ptr ); + free( (void *)int_input_ptr ); + + if (check_times(queueStart, submitStart, writeStart, writeEnd, device)) + err = -1; + + return err; + +} // end copy_size() + + +static int copy_partial_size( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements, cl_uint srcStart, cl_uint dstStart, int size, MTdata d ) +{ + cl_mem streams[2]; + cl_event copyEvent; + cl_ulong queueStart, submitStart, writeStart, writeEnd; + cl_int *inptr, *outptr; + int err = 0; + int i; + + inptr = (cl_int *)malloc(sizeof(cl_int) * num_elements); + outptr = (cl_int *)malloc(sizeof(cl_int) * num_elements); + + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * num_elements, NULL, &err ); + if (!streams[0]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * num_elements, NULL, &err ); + if (!streams[1]) + { + log_error("clCreateBuffer failed\n"); + return -1; + } + + for (i=0; i threads[0] ) + localThreads[0] = threads[0]; + if( localThreads[1] > threads[1] ) + localThreads[1] = threads[1]; +#endif + + inptr = (void *)generate_image( (int)num_bytes, d ); + if( ! inptr ){ + log_error("unable to allocate inptr at %d x %d\n", (int)w, (int)h ); + return -1; + } + + dst = malloc( num_bytes ); + if( ! dst ){ + free( (void *)inptr ); + log_error("unable to allocate dst at %d x %d\n", (int)w, (int)h ); + return -1; + } + + // allocate the input image + flags = (cl_mem_flags)(CL_MEM_READ_WRITE); + memobjs[0] = create_image_2d(context, flags, &image_format_desc, w, h, 0, NULL, &err); + if( memobjs[0] == (cl_mem)0 ) { + free( dst ); + free( (void *)inptr ); + log_error("unable to create Image2D\n"); + return -1; + } + + memobjs[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), num_bytes, NULL, &err ); + if( memobjs[1] == (cl_mem)0 ) { + clReleaseMemObject(memobjs[0]); + free( dst ); + free( (void *)inptr ); + log_error("unable to create array\n"); + return -1; + } + + // allocate the input image + memobjs[2] = create_image_2d(context, flags, &image_format_desc, w, h, 0, NULL, &err); + if( memobjs[2] == (cl_mem)0 ) { + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( (void *)inptr ); + log_error("unable to create Image2D\n"); + return -1; + } + + err = clEnqueueWriteBuffer( queue, memobjs[1], true, 0, num_bytes, inptr, 0, NULL, NULL ); + if( err != CL_SUCCESS ){ + log_error("clWriteArray failed\n"); + return -1; + } + + err = create_single_kernel_helper( context, &program[0], &kernel[0], 1, &write_kernel_code, "test_write" ); + if( err ){ + clReleaseMemObject( memobjs[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[2] ); + free( dst ); + free( inptr ); + return -1; + } + + err = clSetKernelArg( kernel[0], 0, sizeof( cl_mem ), (void *)&memobjs[1] ); + err |= clSetKernelArg( kernel[0], 1, sizeof( cl_mem ), (void *)&memobjs[0] ); + if (err != CL_SUCCESS){ + log_error("clSetKernelArg failed\n"); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[2] ); + free( dst ); + free( inptr ); + return -1; + } + +#ifdef USE_LOCAL_THREADS + err = clEnqueueNDRangeKernel( queue, kernel[0], 2, NULL, threads, localThreads, 0, NULL, NULL ); +#else + err = clEnqueueNDRangeKernel( queue, kernel[0], 2, NULL, threads, NULL, 0, NULL, NULL ); +#endif + if (err != CL_SUCCESS){ + print_error( err, "clEnqueueNDRangeKernel failed" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[2] ); + free( dst ); + free( inptr ); + return -1; + } + + // now do the copy + size_t srcPt[3] = { srcx, srcy, 0 }; + size_t destPt[3] = { dstx, dsty, 0 }; + size_t region[3] = { subw, subh, 1 }; + err = clEnqueueCopyImage( queue, memobjs[0], memobjs[2], srcPt, destPt, region, 0, NULL, ©Event ); + if (err != CL_SUCCESS){ + print_error( err, "clCopyImage failed" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[2] ); + free( dst ); + free( inptr ); + return -1; + } + + // This synchronization point is needed in order to assume the data is valid. + // Getting profiling information is not a synchronization point. + err = clWaitForEvents( 1, ©Event ); + if( err != CL_SUCCESS ) + { + clReleaseEvent(copyEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[2] ); + free( dst ); + free( inptr ); + return -1; + } + + // test profiling + while( ( err = clGetEventProfilingInfo( copyEvent, CL_PROFILING_COMMAND_QUEUED, sizeof( cl_ulong ), &queueStart, NULL ) ) == + CL_PROFILING_INFO_NOT_AVAILABLE ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(copyEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[2] ); + free( dst ); + free( inptr ); + return -1; + } + + while( ( err = clGetEventProfilingInfo( copyEvent, CL_PROFILING_COMMAND_SUBMIT, sizeof( cl_ulong ), &submitStart, NULL ) ) == + CL_PROFILING_INFO_NOT_AVAILABLE ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(copyEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[2] ); + free( dst ); + free( inptr ); + return -1; + } + + err = clGetEventProfilingInfo( copyEvent, CL_PROFILING_COMMAND_START, sizeof( cl_ulong ), &writeStart, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(copyEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[2] ); + free( dst ); + free( inptr ); + return -1; + } + + err = clGetEventProfilingInfo( copyEvent, CL_PROFILING_COMMAND_END, sizeof( cl_ulong ), &writeEnd, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(copyEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[2] ); + free( dst ); + free( inptr ); + return -1; + } + + size_t origin[3] = { 0, 0, 0 }; + size_t region2[3] = { w, h, 1 }; + err = clEnqueueReadImage( queue, memobjs[2], true, origin, region2, 0, 0, dst, 0, NULL, NULL ); + if (err != CL_SUCCESS){ + print_error( err, "clReadImage failed" ); + clReleaseEvent(copyEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[2] ); + free( dst ); + free( inptr ); + return -1; + } + + err = verify_subimage( (unsigned char *)inptr, (unsigned char *)dst, srcx, srcy, + dstx, dsty, subw, subh, w, 4 ); + //err = verify_image( (unsigned char *)inptr, (unsigned char *)dst, w * h * 4 ); + if( err ){ + log_error( "Image failed to verify.\n " ); + } + else{ + log_info( "Image verified.\n" ); + } + + // cleanup + clReleaseEvent(copyEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[2] ); + free( dst ); + free( inptr ); + + if (check_times(queueStart, submitStart, writeStart, writeEnd, device)) + err = -1; + + return err; + +} // end copy_image_size() + + +int copy_image( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ) +{ + int err = 0; + int i; + size_t srcx, srcy, dstx, dsty, subw, subh; + MTdata d; + + srcx = srcy = dstx = dsty = 0; + subw = subh = 256; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + d = init_genrand( gRandomSeed ); + err = copy_image_size( device, context, queue, srcx, srcy, dstx, dsty, subw, subh, d ); + if( err ){ + log_error( "testing copy image, full size\n" ); + } + else{ + log_info( "testing copy image, full size\n" ); + } + + // now test random sub images + srcx = srcy = 0; + subw = subh = 16; + dstx = dsty = 0; + err = copy_image_size( device, context, queue, srcx, srcy, dstx, dsty, subw, subh, d ); + if( err ){ + log_error( "test copy of subimage size %d,%d %d,%d %d x %d\n", (int)srcx, (int)srcy, + (int)dstx, (int)dsty, (int)subw, (int)subh ); + } + else{ + log_info( "test copy of subimage size %d,%d %d,%d %d x %d\n", (int)srcx, (int)srcy, + (int)dstx, (int)dsty, (int)subw, (int)subh ); + } + + srcx = srcy = 8; + subw = subh = 16; + dstx = dsty = 32; + err = copy_image_size( device, context, queue, srcx, srcy, dstx, dsty, subw, subh, d ); + if( err ){ + log_error( "test copy of subimage size %d,%d %d,%d %d x %d\n", (int)srcx, (int)srcy, + (int)dstx, (int)dsty, (int)subw, (int)subh ); + } + else{ + log_info( "test copy of subimage size %d,%d %d,%d %d x %d\n", (int)srcx, (int)srcy, + (int)dstx, (int)dsty, (int)subw, (int)subh ); + } + + for( i = 0; i < 16; i++ ) { + srcx = (size_t)get_random_float( 0.f, 248.f, d ); + srcy = (size_t)get_random_float( 0.f, 248.f, d ); + subw = (size_t)get_random_float( 8.f, (float)(256 - srcx), d ); + subh = (size_t)get_random_float( 8.f, (float)(256 - srcy), d ); + dstx = (size_t)get_random_float( 0.f, (float)(256 - subw), d ); + dsty = (size_t)get_random_float( 0.f, (float)(256 - subh), d ); + err = copy_image_size( device, context, queue, srcx, srcy, dstx, dsty, subw, subh, d ); + if( err ){ + log_error( "test copy of subimage size %d,%d %d,%d %d x %d\n", (int)srcx, (int)srcy, + (int)dstx, (int)dsty, (int)subw, (int)subh ); + } + else{ + log_info( "test copy of subimage size %d,%d %d,%d %d x %d\n", (int)srcx, (int)srcy, + (int)dstx, (int)dsty, (int)subw, (int)subh ); + } + } + + free_mtdata(d); + + return err; + +} // end copy_image() + + +int copy_array_to_image( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_mem memobjs[3]; + cl_image_format image_format_desc = { CL_RGBA, CL_UNORM_INT8 }; + void *inptr; + void *dst; + int err; + cl_mem_flags flags; + unsigned int num_channels = (unsigned int)get_format_channel_count( &image_format_desc ); + size_t w = 256, h = 256; + size_t element_nbytes; + size_t num_bytes; + size_t channel_nbytes = sizeof( cl_char ); + MTdata d; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + element_nbytes = channel_nbytes * num_channels; + num_bytes = w * h * element_nbytes; + d = init_genrand( gRandomSeed ); + inptr = (void *)generate_image( (int)num_bytes, d ); + free_mtdata(d); d = NULL; + if( ! inptr ){ + log_error("unable to allocate inptr at %d x %d\n", (int)w, (int)h ); + return -1; + } + + dst = malloc( num_bytes ); + if( ! dst ){ + free( inptr ); + log_error( " unable to allocate dst at %d x %d\n", (int)w, (int)h ); + return -1; + } + + // allocate the input image + flags = (cl_mem_flags)(CL_MEM_READ_WRITE); + memobjs[0] = create_image_2d( context, flags, &image_format_desc, w, h, 0, NULL, &err ); + if( memobjs[0] == (cl_mem)0 ){ + free( dst ); + free( inptr ); + log_error( " unable to create Image2D\n" ); + return -1; + } + + memobjs[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), channel_nbytes * num_channels*w*h, NULL, &err ); + if( memobjs[1] == (cl_mem)0 ) { + clReleaseMemObject( memobjs[0] ); + free( dst ); + free( inptr ); + log_error( " unable to create array: " ); + return -1; + } + + err = clEnqueueWriteBuffer( queue, memobjs[1], true, 0, num_bytes, (const void *)inptr, 0, NULL, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clWriteArray failed" ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + free( dst ); + free( inptr ); + return -1; + } + + size_t origin[3] = { 0, 0, 0 }; + size_t region[3] = { w, h, 1 }; + err = clEnqueueCopyBufferToImage( queue, memobjs[1], memobjs[0], 0, origin, region, 0, NULL, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clCopyArrayToImage failed" ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + free( dst ); + free( inptr ); + return -1; + } + + err = clEnqueueReadImage( queue, memobjs[0], true, origin, region, 0, 0, dst, 0, NULL, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clReadImage failed" ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + free( dst ); + free( inptr ); + return -1; + } + + err = verify_subimage( (cl_uchar *)inptr, (cl_uchar *)dst, 0, 0, 0, 0, w, h, w, num_channels ); + if( err ){ + log_error( " test failed: " ); + } + else{ + log_info( " test passed: " ); + } + + // cleanup + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + free( dst ); + free( inptr ); + + return err; + +} // end copy_array_to_image() diff --git a/test_conformance/profiling/execute.c b/test_conformance/profiling/execute.c new file mode 100644 index 00000000..e39d96ad --- /dev/null +++ b/test_conformance/profiling/execute.c @@ -0,0 +1,440 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/errorHelpers.h" + +#ifndef uchar +typedef unsigned char uchar; +#endif + +#undef MIN +#define MIN(x,y) ( (x) < (y) ? (x) : (y) ) + +#undef MAX +#define MAX(x,y) ( (x) > (y) ? (x) : (y) ) + +//#define CREATE_OUTPUT 1 + +extern int writePPM( const char *filename, uchar *buf, int xsize, int ysize ); + + + +//--- the code for kernel executables +static const char *image_filter_src = +"constant sampler_t sampler = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST;\n" +"\n" +"__kernel void image_filter( int n, int m, __global float *filter_weights,\n" +" read_only image2d_t src_image, write_only image2d_t dst_image )\n" +"{\n" +" int i, j;\n" +" int indx = 0;\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 filter_result = (float4)( 0.f, 0.f, 0.f, 0.f );\n" +"\n" +" for (i=-m/2; i<(m+1)/2; i++){\n" +" for (j=-n/2; j<(n+1)/2; j++){\n" +" float w = filter_weights[indx++];\n" +"\n" +" if (w != 0.0f){\n" +" filter_result += w * read_imagef(src_image, sampler,\n" +" (int2)(tid_x + j, tid_y + i));\n" +" }\n" +" }\n" +" }\n" +"\n" +" write_imagef(dst_image, (int2)(tid_x, tid_y), filter_result);\n" +"}\n"; + + +//--- equivalent non-kernel code +static void read_imagef( int x, int y, int w, int h, int nChannels, uchar *src, float *srcRgb ) +{ + // clamp the coords + int x0 = MIN( MAX( x, 0 ), w - 1 ); + int y0 = MIN( MAX( y, 0 ), h - 1 ); + + // get tine index + int indx = ( y0 * w + x0 ) * nChannels; + + // seed the return array + int i; + for( i = 0; i < nChannels; i++ ){ + srcRgb[i] = (float)src[indx+i]; + } +} // end read_imagef() + + +static void write_imagef( uchar *dst, int x, int y, int w, int h, int nChannels, float *dstRgb ) +{ + // get tine index + int indx = ( y * w + x ) * nChannels; + + // seed the return array + int i; + for( i = 0; i < nChannels; i++ ){ + dst[indx+i] = (uchar)dstRgb[i]; + } +} // end write_imagef() + + +static void basicFilterPixel( int x, int y, int n, int m, int xsize, int ysize, int nChannels, const float *filter_weights, uchar *src, uchar *dst ) +{ + int i, j, k; + int indx = 0; + float filter_result[] = { 0.f, 0.f, 0.f, 0.f }; + float srcRgb[4]; + + for( i = -m/2; i < (m+1)/2; i++ ){ + for( j = -n/2; j < (n+1)/2; j++ ){ + float w = filter_weights[indx++]; + + if( w != 0 ){ + read_imagef( x + j, y + i, xsize, ysize, nChannels, src, srcRgb ); + for( k = 0; k < nChannels; k++ ){ + filter_result[k] += w * srcRgb[k]; + } + } + } + } + + write_imagef( dst, x, y, xsize, ysize, nChannels, filter_result ); + +} // end basicFilterPixel() + + +//--- helper functions +static uchar *createImage( int elements, MTdata d) +{ + int i; + uchar *ptr = (uchar *)malloc( elements * sizeof( cl_uchar ) ); + if( ! ptr ) + return NULL; + + for( i = 0; i < elements; i++ ){ + ptr[i] = (uchar)genrand_int32(d); + } + + return ptr; + +} // end createImage() + + +static int verifyImages( uchar *ptr0, uchar *ptr1, uchar tolerance, int xsize, int ysize, int nChannels ) +{ + int x, y, z; + uchar *p0 = ptr0; + uchar *p1 = ptr1; + + for( y = 0; y < ysize; y++ ){ + for( x = 0; x < xsize; x++ ){ + for( z = 0; z < nChannels; z++ ){ + if( (uchar)abs( (int)( *p0++ - *p1++ ) ) > tolerance ){ + log_error( " images differ at x,y = %d,%d, channel = %d, %d to %d\n", x, y, z, + (int)p0[-1], (int)p1[-1] ); + return -1; + } + } + } + } + + return 0; + +} // end verifyImages() + + +static int kernelFilter( cl_device_id device, cl_context context, cl_command_queue queue, int w, int h, int nChannels, + uchar *inptr, uchar *outptr ) +{ + cl_program program[1]; + cl_kernel kernel[1]; + cl_mem memobjs[3]; + cl_image_format image_format_desc = { CL_RGBA, CL_UNORM_INT8 }; + cl_event executeEvent; + cl_ulong queueStart, submitStart, writeStart, writeEnd; + size_t threads[2]; +#ifdef USE_LOCAL_THREADS + size_t localThreads[2]; +#endif + float filter_weights[] = { .1f, .1f, .1f, .1f, .2f, .1f, .1f, .1f, .1f }; + int filter_w = 3, filter_h = 3; + int err = 0; + + // set thread dimensions + threads[0] = w; + threads[1] = h; + +#ifdef USE_LOCAL_THREADS + err = clGetDeviceConfigInfo( id, CL_DEVICE_MAX_THREAD_GROUP_SIZE, localThreads, sizeof( cl_uint ), NULL ); + test_error( err, "Unable to get thread group max size" ); + localThreads[1] = localThreads[0]; + if( localThreads[0] > threads[0] ) + localThreads[0] = threads[0]; + if( localThreads[1] > threads[1] ) + localThreads[1] = threads[1]; +#endif + + // allocate the input and output image memory objects + memobjs[0] = create_image_2d( context, (cl_mem_flags)(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR), + &image_format_desc, w, h, 0, inptr, &err ); + if( memobjs[0] == (cl_mem)0 ){ + log_error( " unable to create 2D image using create_image_2d\n" ); + return -1; + } + + memobjs[1] = create_image_2d( context, CL_MEM_WRITE_ONLY, &image_format_desc, w, h, 0, NULL, &err ); + if( memobjs[1] == (cl_mem)0 ){ + log_error( " unable to create 2D image using create_image_2d\n" ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + // allocate an array memory object to load the filter weights + memobjs[2] = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR ), + sizeof( cl_float ) * filter_w * filter_h, &filter_weights, &err ); + if( memobjs[2] == (cl_mem)0 ){ + log_error( " unable to create array using clCreateBuffer\n" ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + // create the compute program + err = create_single_kernel_helper( context, &program[0], &kernel[0], 1, &image_filter_src, "image_filter" ); + if( err ){ + clReleaseMemObject( memobjs[2] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + + // create kernel args object and set arg values. + // set the args values + err = clSetKernelArg( kernel[0], 0, sizeof( cl_int ), (void *)&filter_w ); + err |= clSetKernelArg( kernel[0], 1, sizeof( cl_int ), (void *)&filter_h ); + err |= clSetKernelArg( kernel[0], 2, sizeof( cl_mem ), (void *)&memobjs[2] ); + err |= clSetKernelArg( kernel[0], 3, sizeof( cl_mem ), (void *)&memobjs[0] ); + err |= clSetKernelArg( kernel[0], 4, sizeof( cl_mem ), (void *)&memobjs[1] ); + + if( err != CL_SUCCESS ){ + print_error( err, "clSetKernelArg failed\n" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[2] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + +#ifdef USE_LOCAL_THREADS + err = clEnqueueNDRangeKernel( queue, kernel[0], 2, NULL, threads, localThreads, NULL, 0, &executeEvent ); +#else + err = clEnqueueNDRangeKernel( queue, kernel[0], 2, NULL, threads, NULL, NULL, 0, &executeEvent ); +#endif + + if( err != CL_SUCCESS ){ + print_error( err, "clEnqueueNDRangeKernel failed\n" ); + clReleaseEvent( executeEvent ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[2] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + // This synchronization point is needed in order to assume the data is valid. + // Getting profiling information is not a synchronization point. + err = clWaitForEvents( 1, &executeEvent ); + if( err != CL_SUCCESS ) + { + clReleaseEvent( executeEvent ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[2] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + // test profiling + while( ( err = clGetEventProfilingInfo( executeEvent, CL_PROFILING_COMMAND_QUEUED, sizeof( cl_ulong ), &queueStart, NULL ) ) == + CL_PROFILING_INFO_NOT_AVAILABLE ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent( executeEvent ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[2] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + while( ( err = clGetEventProfilingInfo( executeEvent, CL_PROFILING_COMMAND_SUBMIT, sizeof( cl_ulong ), &submitStart, NULL ) ) == + CL_PROFILING_INFO_NOT_AVAILABLE ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent( executeEvent ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[2] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + err = clGetEventProfilingInfo( executeEvent, CL_PROFILING_COMMAND_START, sizeof( cl_ulong ), &writeStart, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent( executeEvent ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[2] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + err = clGetEventProfilingInfo( executeEvent, CL_PROFILING_COMMAND_END, sizeof( cl_ulong ), &writeEnd, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent( executeEvent ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[2] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + // read output image + size_t origin[3] = { 0, 0, 0 }; + size_t region[3] = { w, h, 1 }; + err = clEnqueueReadImage( queue, memobjs[1], true, origin, region, 0, 0, outptr, 0, NULL, NULL); + if( err != CL_SUCCESS ){ + print_error( err, "clReadImage failed\n" ); + clReleaseEvent( executeEvent ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[2] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + // release event, kernel, program, and memory objects + clReleaseEvent( executeEvent ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[2] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + + if (check_times(queueStart, submitStart, writeStart, writeEnd, device)) + err = -1; + + return err; + +} // end kernelFilter() + + +static int basicFilter( int w, int h, int nChannels, uchar *inptr, uchar *outptr ) +{ + const float filter_weights[] = { .1f, .1f, .1f, .1f, .2f, .1f, .1f, .1f, .1f }; + int filter_w = 3, filter_h = 3; + int x, y; + + for( y = 0; y < h; y++ ){ + for( x = 0; x < w; x++ ){ + basicFilterPixel( x, y, filter_w, filter_h, w, h, nChannels, filter_weights, inptr, outptr ); + } + } + + return 0; + +} // end of basicFilter() + + +int execute( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ) +{ + uchar *inptr; + uchar *outptr[2]; + int w = 256, h = 256; + int nChannels = 4; + int nElements = w * h * nChannels; + int err = 0; + MTdata d; + + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + d = init_genrand( gRandomSeed ); + inptr = createImage( nElements, d ); + free_mtdata( d); d = NULL; + + if( ! inptr ){ + log_error( " unable to allocate %d bytes of memory for image\n", nElements ); + return -1; + } + + outptr[0] = (uchar *)malloc( nElements * sizeof( cl_uchar ) ); + if( ! outptr[0] ){ + log_error( " unable to allocate %d bytes of memory for output image #1\n", nElements ); + free( (void *)inptr ); + return -1; + } + + outptr[1] = (uchar *)malloc( nElements * sizeof( cl_uchar ) ); + if( ! outptr[1] ){ + log_error( " unable to allocate %d bytes of memory for output image #2\n", nElements ); + free( (void *)outptr[0] ); + free( (void *)inptr ); + return -1; + } + + err = kernelFilter( device, context, queue, w, h, nChannels, inptr, outptr[0] ); + + if( ! err ){ + basicFilter( w, h, nChannels, inptr, outptr[1] ); + + // verify that the images are the same + err = verifyImages( outptr[0], outptr[1], (uchar)0x1, w, h, nChannels ); + if( err ) + log_error( " images do not match\n" ); + } + + // clean up + free( (void *)outptr[1] ); + free( (void *)outptr[0] ); + free( (void *)inptr ); + + return err; + +} // end execute() + + + diff --git a/test_conformance/profiling/execute_multipass.c b/test_conformance/profiling/execute_multipass.c new file mode 100644 index 00000000..9ca5df29 --- /dev/null +++ b/test_conformance/profiling/execute_multipass.c @@ -0,0 +1,314 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/errorHelpers.h" + +static const char *read3d_kernel_code = +"\n" +"__kernel void read3d(read_only image3d_t srcimg, __global unsigned char *dst, sampler_t sampler)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int tid_z = get_global_id(2);\n" +" int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0));\n" +" indx *= 4;\n" +" dst[indx+0] = (unsigned char)(color.x * 255.0f);\n" +" dst[indx+1] = (unsigned char)(color.y * 255.0f);\n" +" dst[indx+2] = (unsigned char)(color.z * 255.0f);\n" +" dst[indx+3] = (unsigned char)(color.w * 255.0f);\n" +"\n" +"}\n"; + + +static cl_uchar *createImage( int elements, MTdata d ) +{ + int i; + cl_uchar *ptr = (cl_uchar *)malloc( elements * sizeof( cl_uchar ) ); + if( ! ptr ) + return NULL; + + for( i = 0; i < elements; i++ ){ + ptr[i] = (cl_uchar)genrand_int32(d); + } + + return ptr; + +} // end createImage() + + +static int verifyImages( cl_uchar *ptr0, cl_uchar *ptr1, cl_uchar tolerance, int xsize, int ysize, int zsize, int nChannels ) +{ + int x, y, z, c; + cl_uchar *p0 = ptr0; + cl_uchar *p1 = ptr1; + + for( z = 0; z < zsize; z++ ){ + for( y = 0; y < ysize; y++ ){ + for( x = 0; x < xsize; x++ ){ + for( c = 0; c < nChannels; c++ ){ + if( (cl_uchar)abs( (int)( *p0++ - *p1++ ) ) > tolerance ){ + log_error( " images differ at x,y,z = %d,%d,%d channel = %d, %d to %d\n", + x, y, z, c, (int)p0[-1], (int)p1[-1] ); + return -1; + } + } + } + } + } + + return 0; + +} // end verifyImages() + + +static int run_kernel( cl_device_id device, cl_context context, cl_command_queue queue, + int w, int h, int d, int nChannels, cl_uchar *inptr, cl_uchar *outptr ) +{ + cl_program program[1]; + cl_kernel kernel[1]; + cl_mem memobjs[2]; + cl_image_format image_format_desc = { CL_RGBA, CL_UNORM_INT8 }; + cl_event executeEvent = NULL; + cl_ulong queueStart, submitStart, writeStart, writeEnd; + size_t threads[3]; + size_t localThreads[3]; + int err = 0; + + // set thread dimensions + threads[0] = w; + threads[1] = h; + threads[2] = d; + + err = clGetDeviceInfo( device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof( cl_uint ), (size_t*)localThreads, NULL ); + if (err) + { + localThreads[0] = 256; localThreads[1] = 1; localThreads[2] = 1; + err = 0; + } + if( localThreads[0] > threads[0] ) + localThreads[0] = threads[0]; + if( localThreads[1] > threads[1] ) + localThreads[1] = threads[1]; + + cl_sampler_properties properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, + CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_CLAMP_TO_EDGE, + CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, + 0 }; + cl_sampler sampler = clCreateSamplerWithProperties( context, properties, &err ); + if( err ){ + log_error( " clCreateSamplerWithProperties failed.\n" ); + return -1; + } + + // allocate the input and output image memory objects + memobjs[0] = create_image_3d( context, (cl_mem_flags)(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR), &image_format_desc, w, h, d, 0, 0, inptr, &err ); + if( memobjs[0] == (cl_mem)0 ){ + log_error( " unable to create 2D image using create_image_2d\n" ); + return -1; + } + + // allocate an array memory object to load the filter weights + memobjs[1] = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_READ_WRITE ), sizeof( cl_float ) * w*h*d*nChannels, NULL, &err ); + if( memobjs[1] == (cl_mem)0 ){ + log_error( " unable to create array using clCreateBuffer\n" ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + // create the compute program + err = create_single_kernel_helper( context, &program[0], &kernel[0], 1, &read3d_kernel_code, "read3d" ); + if( err ){ + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + + // create kernel args object and set arg values. + // set the args values + err |= clSetKernelArg( kernel[0], 0, sizeof( cl_mem ), (void *)&memobjs[0] ); + err |= clSetKernelArg( kernel[0], 1, sizeof( cl_mem ), (void *)&memobjs[1] ); + err |= clSetKernelArg(kernel[0], 2, sizeof sampler, &sampler); + + if( err != CL_SUCCESS ){ + print_error( err, "clSetKernelArg failed\n" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + err = clEnqueueNDRangeKernel( queue, kernel[0], 3, NULL, threads, localThreads, NULL, 0, &executeEvent ); + + if( err != CL_SUCCESS ){ + print_error( err, "clEnqueueNDRangeKernel failed\n" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + if (executeEvent) { + + // This synchronization point is needed in order to assume the data is valid. + // Getting profiling information is not a synchronization point. + err = clWaitForEvents( 1, &executeEvent ); + if( err != CL_SUCCESS ) + { + print_error( err, "clWaitForEvents failed\n" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + // test profiling + while( ( err = clGetEventProfilingInfo( executeEvent, CL_PROFILING_COMMAND_QUEUED, sizeof( cl_ulong ), &queueStart, NULL ) ) == CL_PROFILING_INFO_NOT_AVAILABLE ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + while( ( err = clGetEventProfilingInfo( executeEvent, CL_PROFILING_COMMAND_SUBMIT, sizeof( cl_ulong ), &submitStart, NULL ) ) == CL_PROFILING_INFO_NOT_AVAILABLE ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + err = clGetEventProfilingInfo( executeEvent, CL_PROFILING_COMMAND_START, sizeof( cl_ulong ), &writeStart, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + err = clGetEventProfilingInfo( executeEvent, CL_PROFILING_COMMAND_END, sizeof( cl_ulong ), &writeEnd, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + log_info( "Profiling info:\n" ); + log_info( "Time from queue to start of clEnqueueNDRangeKernel: %f seconds\n", (double)(writeStart - queueStart) / 1000000000000.f ); + log_info( "Time from start of clEnqueueNDRangeKernel to end: %f seconds\n", (double)(writeEnd - writeStart) / 1000000000000.f ); + } + + // read output image + err = clEnqueueReadBuffer(queue, memobjs[1], CL_TRUE, 0, w*h*d*nChannels*4, outptr, 0, NULL, NULL); + if( err != CL_SUCCESS ){ + print_error( err, "clReadImage failed\n" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + return -1; + } + + // release kernel, program, and memory objects + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject( memobjs[1] ); + clReleaseMemObject( memobjs[0] ); + + return err; + +} // end run_kernel() + + +// The main point of this test is to exercise code that causes a multipass cld launch for a single +// kernel exec at the cl level. This is done on the gpu for 3d launches, and it's also done +// to handle gdims that excede the maximums allowed by the hardware. In this case we +// use 3d to exercise the multipass events. In the future 3d may not be multpass, in which +// case we will need to ensure that we use gdims large enough to force multipass. + +int execute_multipass( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ) +{ + cl_uchar *inptr; + cl_uchar *outptr; + int w = 256, h = 128, d = 32; + int nChannels = 4; + int nElements = w * h * d * nChannels; + int err = 0; + MTdata mtData; + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + mtData = init_genrand( gRandomSeed ); + inptr = createImage( nElements, mtData ); + free_mtdata( mtData); mtData = NULL; + if( ! inptr ){ + log_error( " unable to allocate %d bytes of memory for image\n", nElements ); + return -1; + } + + outptr = (cl_uchar *)malloc( nElements * sizeof( cl_uchar ) ); + if( ! outptr ){ + log_error( " unable to allocate %d bytes of memory for output image #1\n", nElements ); + free( (void *)inptr ); + return -1; + } + + + err = run_kernel( device, context, queue, w, h, d, nChannels, inptr, outptr ); + + if( ! err ){ + // verify that the images are the same + err = verifyImages( outptr, inptr, (cl_uchar)0x1, w, h, d, nChannels ); + if( err ) + log_error( " images do not match\n" ); + } + + // clean up + free( (void *)outptr ); + free( (void *)inptr ); + + return err; + +} // end execute() + + + diff --git a/test_conformance/profiling/main.c b/test_conformance/profiling/main.c new file mode 100644 index 00000000..4c2201f7 --- /dev/null +++ b/test_conformance/profiling/main.c @@ -0,0 +1,173 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include "procs.h" +#include "../../test_common/harness/testHarness.h" + +// FIXME: To use certain functions in ../../test_common/harness/imageHelpers.h +// (for example, generate_random_image_data()), the tests are required to declare +// the following variables (): +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +bool gTestRounding = false; + +basefn basefn_list[] = { + read_int_array, + read_uint_array, + read_long_array, + read_ulong_array, + read_short_array, + read_ushort_array, + read_float_array, + read_char_array, + read_uchar_array, + read_struct_array, + write_int_array, + write_uint_array, + write_long_array, + write_ulong_array, + write_short_array, + write_ushort_array, + write_float_array, + write_char_array, + write_uchar_array, + write_struct_array, + read_float_image, + read_char_image, + read_uchar_image, + write_float_image, + write_char_image, + write_uchar_image, + copy_array, + copy_partial_array, + copy_image, + copy_array_to_image, + execute +}; + + +const char *basefn_names[] = { +"read_array_int", +"read_array_uint", +"read_array_long", +"read_array_ulong", +"read_array_short", +"read_array_ushort", +"read_array_float", +"read_array_char", +"read_array_uchar", +"read_array_struct", +"write_array_int", +"write_array_uint", +"write_array_long", +"write_array_ulong", +"write_array_short", +"write_array_ushort", +"write_array_float", +"write_array_char", +"write_array_uchar", +"write_array_struct", +"read_image_float", +"read_image_int", +"read_image_uint", +"write_image_float", +"write_image_char", +"write_image_uchar", +"copy_array", +"copy_partial_array", +"copy_image", +"copy_array_to_image", +"execute", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_streamfns = sizeof(basefn_names) / sizeof(char *); + +// FIXME: use timer resolution rather than hardcoding 1µs per tick. + +#define QUEUE_SECONDS_LIMIT 30 +#define SUBMIT_SECONDS_LIMIT 30 +#define COMMAND_SECONDS_LIMIT 30 +int check_times(cl_ulong queueStart, cl_ulong commandSubmit, cl_ulong commandStart, cl_ulong commandEnd, cl_device_id device) { + int err = 0; + + size_t profiling_resolution = 0; + err = clGetDeviceInfo(device, CL_DEVICE_PROFILING_TIMER_RESOLUTION, sizeof(profiling_resolution), &profiling_resolution, NULL); + test_error(err, "clGetDeviceInfo for CL_DEVICE_PROFILING_TIMER_RESOLUTION failed.\n"); + + log_info("CL_PROFILING_COMMAND_QUEUED: %llu CL_PROFILING_COMMAND_SUBMIT: %llu CL_PROFILING_COMMAND_START: %llu CL_PROFILING_COMMAND_END: %llu CL_DEVICE_PROFILING_TIMER_RESOLUTION: %ld\n", + queueStart, commandSubmit, commandStart, commandEnd, profiling_resolution); + + double queueTosubmitTimeS = (double)(commandSubmit - queueStart)*1e-9; + double submitToStartTimeS = (double)(commandStart - commandSubmit)*1e-9; + double startToEndTimeS = (double)(commandEnd - commandStart)*1e-9; + + log_info( "Profiling info:\n" ); + log_info( "Time from queue to submit : %fms\n", (double)(queueTosubmitTimeS) * 1000.f ); + log_info( "Time from submit to start : %fms\n", (double)(submitToStartTimeS) * 1000.f ); + log_info( "Time from start to end: %fms\n", (double)(startToEndTimeS) * 1000.f ); + + if(queueStart > commandSubmit) { + log_error("CL_PROFILING_COMMAND_QUEUED > CL_PROFILING_COMMAND_SUBMIT.\n"); + err = -1; + } + + if (commandSubmit > commandStart) { + log_error("CL_PROFILING_COMMAND_SUBMIT > CL_PROFILING_COMMAND_START.\n"); + err = -1; + } + + if (commandStart > commandEnd) { + log_error("CL_PROFILING_COMMAND_START > CL_PROFILING_COMMAND_END.\n"); + err = -1; + } + + if (queueStart == 0 && commandStart == 0 && commandEnd == 0) { + log_error("All values are 0. This is exceedingly unlikely.\n"); + err = -1; + } + + if (queueTosubmitTimeS > QUEUE_SECONDS_LIMIT) { + log_error("Time between queue and submit is too big: %fs, test limit: %fs.\n", + queueTosubmitTimeS , (double)QUEUE_SECONDS_LIMIT); + err = -1; + } + + if (submitToStartTimeS > SUBMIT_SECONDS_LIMIT) { + log_error("Time between submit and start is too big: %fs, test limit: %fs.\n", + submitToStartTimeS , (double)QUEUE_SECONDS_LIMIT); + err = -1; + } + + if (startToEndTimeS > COMMAND_SECONDS_LIMIT) { + log_error("Time between queue and start is too big: %fs, test limit: %fs.\n", + startToEndTimeS , (double)QUEUE_SECONDS_LIMIT); + err = -1; + } + return err; +} + + +int main( int argc, const char *argv[] ) +{ + return runTestHarness( argc, argv, num_streamfns, basefn_list, basefn_names, + false, false, CL_QUEUE_PROFILING_ENABLE ); +} + + diff --git a/test_conformance/profiling/procs.h b/test_conformance/profiling/procs.h new file mode 100644 index 00000000..57a7860d --- /dev/null +++ b/test_conformance/profiling/procs.h @@ -0,0 +1,65 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef __PROCS_H__ +#define __PROCS_H__ + +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/imageHelpers.h" +#include "../../test_common/harness/mt19937.h" + + +extern int check_times(cl_ulong queueStart, cl_ulong submitStart, cl_ulong commandStart, cl_ulong commandEnd, cl_device_id device); + +extern int read_int_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int read_uint_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int read_long_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int read_ulong_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int read_short_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int read_ushort_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int read_float_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int read_half_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int read_char_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int read_uchar_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int read_struct_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int write_int_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int write_uint_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int write_long_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int write_ulong_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int write_short_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int write_ushort_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int write_float_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int write_half_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int write_char_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int write_uchar_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int write_struct_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int read_float_image( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int read_char_image( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int read_uchar_image( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int write_float_image( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int write_char_image( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int write_uchar_image( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int copy_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int copy_partial_array( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int copy_image( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int copy_array_to_image( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int execute( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); +extern int test_parallel_kernels( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements ); + + +#endif // #ifndef __PROCS_H__ + + diff --git a/test_conformance/profiling/readArray.c b/test_conformance/profiling/readArray.c new file mode 100644 index 00000000..30c687ff --- /dev/null +++ b/test_conformance/profiling/readArray.c @@ -0,0 +1,997 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/testHarness.h" + +#define TEST_PRIME_INT ((1<<16)+1) +#define TEST_PRIME_UINT ((1U<<16)+1U) +#define TEST_PRIME_LONG ((1LL<<32)+1LL) +#define TEST_PRIME_ULONG ((1ULL<<32)+1ULL) +#define TEST_PRIME_SHORT ((1S<<8)+1S) +#define TEST_PRIME_FLOAT (float)3.40282346638528860e+38 +#define TEST_PRIME_HALF 119.f +#define TEST_BOOL true +#define TEST_PRIME_CHAR 0x77 + + +#ifndef ulong +typedef unsigned long ulong; +#endif + +#ifndef uchar +typedef unsigned char uchar; +#endif + +#ifndef TestStruct +typedef struct{ + int a; + float b; +} TestStruct; +#endif + + + +//--- the code for the kernel executables +static const char *stream_read_int_kernel_code[] = { +"__kernel void test_stream_read_int(__global int *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1<<16)+1);\n" +"}\n", + +"__kernel void test_stream_read_int2(__global int2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1<<16)+1);\n" +"}\n", + +"__kernel void test_stream_read_int4(__global int4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1<<16)+1);\n" +"}\n", + +"__kernel void test_stream_read_int8(__global int8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1<<16)+1);\n" +"}\n", + +"__kernel void test_stream_read_int16(__global int16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1<<16)+1);\n" +"}\n" }; + +static const char *int_kernel_name[] = { "test_stream_read_int", "test_stream_read_int2", "test_stream_read_int4", "test_stream_read_int8", "test_stream_read_int16" }; + +const char *stream_read_uint_kernel_code[] = { +"__kernel void test_stream_read_uint(__global uint *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1U<<16)+1U);\n" +"}\n", + +"__kernel void test_stream_read_uint2(__global uint2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1U<<16)+1U);\n" +"}\n", + +"__kernel void test_stream_read_uint4(__global uint4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1U<<16)+1U);\n" +"}\n", + +"__kernel void test_stream_read_uint8(__global uint8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1U<<16)+1U);\n" +"}\n", + +"__kernel void test_stream_read_uint16(__global uint16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1U<<16)+1U);\n" +"}\n" }; + +const char *uint_kernel_name[] = { "test_stream_read_uint", "test_stream_read_uint2", "test_stream_read_uint4", "test_stream_read_uint8", "test_stream_read_uint16" }; + +const char *stream_read_long_kernel_code[] = { +"__kernel void test_stream_read_long(__global long *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1L<<32)+1L);\n" +"}\n", + +"__kernel void test_stream_read_long2(__global long2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1L<<32)+1L);\n" +"}\n", + +"__kernel void test_stream_read_long4(__global long4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1L<<32)+1L);\n" +"}\n", + +"__kernel void test_stream_read_long8(__global long8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1L<<32)+1L);\n" +"}\n", + +"__kernel void test_stream_read_long16(__global long16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1L<<32)+1L);\n" +"}\n" }; + +const char *long_kernel_name[] = { "test_stream_read_long", "test_stream_read_long2", "test_stream_read_long4", "test_stream_read_long8", "test_stream_read_long16" }; + +const char *stream_read_ulong_kernel_code[] = { +"__kernel void test_stream_read_ulong(__global ulong *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1UL<<32)+1UL);\n" +"}\n", + +"__kernel void test_stream_read_ulong2(__global ulong2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1UL<<32)+1UL);\n" +"}\n", + +"__kernel void test_stream_read_ulong4(__global ulong4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1UL<<32)+1UL);\n" +"}\n", + +"__kernel void test_stream_read_ulong8(__global ulong8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1UL<<32)+1UL);\n" +"}\n", + +"__kernel void test_stream_read_ulong16(__global ulong16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = ((1UL<<32)+1UL);\n" +"}\n" }; + +const char *ulong_kernel_name[] = { "test_stream_read_ulong", "test_stream_read_ulong2", "test_stream_read_ulong4", "test_stream_read_ulong8", "test_stream_read_ulong16" }; + +const char *stream_read_short_kernel_code[] = { +"__kernel void test_stream_read_short(__global short *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (short)((1<<8)+1);\n" +"}\n", + +"__kernel void test_stream_read_short2(__global short2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (short)((1<<8)+1);\n" +"}\n", + +"__kernel void test_stream_read_short4(__global short4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (short)((1<<8)+1);\n" +"}\n", + +"__kernel void test_stream_read_short8(__global short8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (short)((1<<8)+1);\n" +"}\n", + +"__kernel void test_stream_read_short16(__global short16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (short)((1<<8)+1);\n" +"}\n" }; + +const char *short_kernel_name[] = { "test_stream_read_short", "test_stream_read_short2", "test_stream_read_short4", "test_stream_read_short8", "test_stream_read_short16" }; + + +const char *stream_read_ushort_kernel_code[] = { +"__kernel void test_stream_read_ushort(__global ushort *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (ushort)((1<<8)+1);\n" +"}\n", + +"__kernel void test_stream_read_ushort2(__global ushort2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (ushort)((1<<8)+1);\n" +"}\n", + +"__kernel void test_stream_read_ushort4(__global ushort4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (ushort)((1<<8)+1);\n" +"}\n", + +"__kernel void test_stream_read_ushort8(__global ushort8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (ushort)((1<<8)+1);\n" +"}\n", + +"__kernel void test_stream_read_ushort16(__global ushort16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (ushort)((1<<8)+1);\n" +"}\n" }; + +static const char *ushort_kernel_name[] = { "test_stream_read_ushort", "test_stream_read_ushort2", "test_stream_read_ushort4", "test_stream_read_ushort8", "test_stream_read_ushort16" }; + + +const char *stream_read_float_kernel_code[] = { +"__kernel void test_stream_read_float(__global float *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (float)3.40282346638528860e+38;\n" +"}\n", + +"__kernel void test_stream_read_float2(__global float2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (float)3.40282346638528860e+38;\n" +"}\n", + +"__kernel void test_stream_read_float4(__global float4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (float)3.40282346638528860e+38;\n" +"}\n", + +"__kernel void test_stream_read_float8(__global float8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (float)3.40282346638528860e+38;\n" +"}\n", + +"__kernel void test_stream_read_float16(__global float16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (float)3.40282346638528860e+38;\n" +"}\n" }; + +const char *float_kernel_name[] = { "test_stream_read_float", "test_stream_read_float2", "test_stream_read_float4", "test_stream_read_float8", "test_stream_read_float16" }; + + +const char *stream_read_half_kernel_code[] = { +"__kernel void test_stream_read_half(__global half *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (half)119;\n" +"}\n", + +"__kernel void test_stream_read_half2(__global half2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (half)119;\n" +"}\n", + +"__kernel void test_stream_read_half4(__global half4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (half)119;\n" +"}\n", + +"__kernel void test_stream_read_half8(__global half8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (half)119;\n" +"}\n", + +"__kernel void test_stream_read_half16(__global half16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (half)119;\n" +"}\n" }; + +const char *half_kernel_name[] = { "test_stream_read_half", "test_stream_read_half2", "test_stream_read_half4", "test_stream_read_half8", "test_stream_read_half16" }; + + +const char *stream_read_char_kernel_code[] = { +"__kernel void test_stream_read_char(__global char *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (char)'w';\n" +"}\n", + +"__kernel void test_stream_read_char2(__global char2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (char)'w';\n" +"}\n", + +"__kernel void test_stream_read_char4(__global char4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (char)'w';\n" +"}\n", + +"__kernel void test_stream_read_char8(__global char8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (char)'w';\n" +"}\n", + +"__kernel void test_stream_read_char16(__global char16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (char)'w';\n" +"}\n" }; + +const char *char_kernel_name[] = { "test_stream_read_char", "test_stream_read_char2", "test_stream_read_char4", "test_stream_read_char8", "test_stream_read_char16" }; + + +const char *stream_read_uchar_kernel_code[] = { +"__kernel void test_stream_read_uchar(__global uchar *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = 'w';\n" +"}\n", + +"__kernel void test_stream_read_uchar2(__global uchar2 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (uchar)'w';\n" +"}\n", + +"__kernel void test_stream_read_uchar4(__global uchar4 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (uchar)'w';\n" +"}\n", + +"__kernel void test_stream_read_uchar8(__global uchar8 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (uchar)'w';\n" +"}\n", + +"__kernel void test_stream_read_uchar16(__global uchar16 *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid] = (uchar)'w';\n" +"}\n" }; + +const char *uchar_kernel_name[] = { "test_stream_read_uchar", "test_stream_read_uchar2", "test_stream_read_uchar4", "test_stream_read_uchar8", "test_stream_read_uchar16" }; + + +const char *stream_read_struct_kernel_code[] = { +"typedef struct{\n" +"int a;\n" +"float b;\n" +"} TestStruct;\n" +"__kernel void test_stream_read_struct(__global TestStruct *dst)\n" +"{\n" +" int tid = get_global_id(0);\n" +"\n" +" dst[tid].a = ((1<<16)+1);\n" +" dst[tid].b = (float)3.40282346638528860e+38;\n" +"}\n" }; + +const char *struct_kernel_name[] = { "test_stream_read_struct" }; + + + +//--- the verify functions +static int verify_read_int(void *ptr, int n) +{ + int i; + int *outptr = (int *)ptr; + + for (i=0; i threads[0] ) + localThreads[0] = threads[0]; +#endif + + ptrSizes[0] = size; + ptrSizes[1] = ptrSizes[0] << 1; + ptrSizes[2] = ptrSizes[1] << 1; + ptrSizes[3] = ptrSizes[2] << 1; + ptrSizes[4] = ptrSizes[3] << 1; + for( i = 0; i < loops; i++ ){ + outptr[i] = malloc( ptrSizes[i] * num_elements ); + if( ! outptr[i] ){ + log_error( " unable to allocate %d bytes for outptr\n", (int)( ptrSizes[i] * num_elements ) ); + return -1; + } + streams[i] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), ptrSizes[i] * num_elements, NULL, &err ); + if( !streams[i] ){ + log_error( " clCreateBuffer failed\n" ); + free( outptr[i] ); + return -1; + } + err = create_single_kernel_helper( context, &program[i], &kernel[i], 1, &kernelCode[i], kernelName[i] ); + if( err ){ + log_error( " Error creating program for %s\n", type ); + clReleaseMemObject(streams[i]); + free( outptr[i] ); + return -1; + } + + err = clSetKernelArg( kernel[i], 0, sizeof( cl_mem ), (void *)&streams[i] ); + if( err != CL_SUCCESS ){ + print_error( err, "clSetKernelArg failed" ); + clReleaseProgram( program[i] ); + clReleaseKernel( kernel[i] ); + clReleaseMemObject( streams[i] ); + free( outptr[i] ); + return -1; + } + +#ifdef USE_LOCAL_THREADS + err = clEnqueueNDRangeKernel( queue, kernel[i], 1, NULL, threads, localThreads, 0, NULL, NULL ); +#else + err = clEnqueueNDRangeKernel( queue, kernel[i], 1, NULL, threads, NULL, 0, NULL, NULL ); +#endif + if( err != CL_SUCCESS ){ + print_error( err, "clEnqueueNDRangeKernel failed" ); + clReleaseKernel( kernel[i] ); + clReleaseProgram( program[i] ); + clReleaseMemObject( streams[i] ); + free( outptr[i] ); + return -1; + } + + err = clEnqueueReadBuffer( queue, streams[i], false, 0, ptrSizes[i]*num_elements, outptr[i], 0, NULL, &readEvent ); + if( err != CL_SUCCESS ){ + print_error( err, "clEnqueueReadBuffer failed" ); + clReleaseKernel( kernel[i] ); + clReleaseProgram( program[i] ); + clReleaseMemObject( streams[i] ); + free( outptr[i] ); + return -1; + } + err = clWaitForEvents( 1, &readEvent ); + if( err != CL_SUCCESS ) + { + print_error( err, "Unable to wait for event completion" ); + clReleaseKernel( kernel[i] ); + clReleaseProgram( program[i] ); + clReleaseMemObject( streams[i] ); + free( outptr[i] ); + return -1; + } + err = clGetEventProfilingInfo( readEvent, CL_PROFILING_COMMAND_QUEUED, sizeof( cl_ulong ), &queueStart, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseKernel( kernel[i] ); + clReleaseProgram( program[i] ); + clReleaseMemObject( streams[i] ); + free( outptr[i] ); + return -1; + } + + err = clGetEventProfilingInfo( readEvent, CL_PROFILING_COMMAND_SUBMIT, sizeof( cl_ulong ), &submitStart, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseKernel( kernel[i] ); + clReleaseProgram( program[i] ); + clReleaseMemObject( streams[i] ); + free( outptr[i] ); + return -1; + } + + err = clGetEventProfilingInfo( readEvent, CL_PROFILING_COMMAND_START, sizeof( cl_ulong ), &readStart, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseKernel( kernel[i] ); + clReleaseProgram( program[i] ); + clReleaseMemObject( streams[i] ); + free( outptr[i] ); + return -1; + } + + err = clGetEventProfilingInfo( readEvent, CL_PROFILING_COMMAND_END, sizeof( cl_ulong ), &readEnd, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseKernel( kernel[i] ); + clReleaseProgram( program[i] ); + clReleaseMemObject( streams[i] ); + free( outptr[i] ); + return -1; + } + + if (fn(outptr[i], num_elements*(1< threads[0] ) + localThreads[0] = threads[0]; +#endif + + output_ptr = malloc(objSize * num_elements); + if( ! output_ptr ){ + log_error( " unable to allocate %d bytes for output_ptr\n", (int)(objSize * num_elements) ); + return -1; + } + streams[0] = clCreateBuffer( device, (cl_mem_flags)(CL_MEM_READ_WRITE), objSize * num_elements, NULL ); + if( !streams[0] ){ + log_error( " clCreateBuffer failed\n" ); + free( output_ptr ); + return -1; + } + + err = create_program_and_kernel( device, stream_read_struct_kernel_code, "test_stream_read_struct", &program[0], &kernel[0]); + if( err ){ + clReleaseProgram( program[0] ); + free( output_ptr ); + return -1; + } + + err = clSetKernelArg( kernel[0], 0, sizeof( cl_mem ), (void *)&streams[0] ); + if( err != CL_SUCCESS){ + print_error( err, "clSetKernelArg failed" ); + clReleaseProgram( program[0] ); + clReleaseKernel( kernel[0] ); + clReleaseMemObject( streams[0] ); + free( output_ptr ); + return -1; + } + +#ifdef USE_LOCAL_THREADS + err = clEnqueueNDRangeKernel( queue, kernel[0], 1, NULL, threads, localThreads, 0, NULL, NULL ); +#else + err = clEnqueueNDRangeKernel( queue, kernel[0], 1, NULL, threads, NULL, 0, NULL, NULL ); +#endif + if( err != CL_SUCCESS ){ + print_error( err, "clEnqueueNDRangeKernel failed" ); + clReleaseProgram( program[0] ); + clReleaseKernel( kernel[0] ); + clReleaseMemObject( streams[0] ); + free( output_ptr ); + return -1; + } + + err = clEnqueueReadBuffer( queue, streams[0], true, 0, objSize*num_elements, (void *)output_ptr, 0, NULL, NULL ); + if( err != CL_SUCCESS){ + print_error( err, "clEnqueueReadBuffer failed" ); + clReleaseProgram( program[0] ); + clReleaseKernel( kernel[0] ); + clReleaseMemObject( streams[0] ); + free( output_ptr ); + return -1; + } + + if (verify_read_struct(output_ptr, num_elements)){ + log_error(" struct test failed\n"); + err = -1; + } + else{ + log_info(" struct test passed\n"); + err = 0; + } + + // cleanup + clReleaseProgram( program[0] ); + clReleaseKernel( kernel[0] ); + clReleaseMemObject( streams[0] ); + free( output_ptr ); + + return err; +} +*/ + + diff --git a/test_conformance/profiling/readImage.c b/test_conformance/profiling/readImage.c new file mode 100644 index 00000000..2a4069d2 --- /dev/null +++ b/test_conformance/profiling/readImage.c @@ -0,0 +1,386 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/errorHelpers.h" + +//--- the code for the kernel executables +static const char *readKernelCode[] = { +"__kernel void testWritef(__global uchar *src, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(dstimg) + tid_x;\n" +" float4 color;\n" +"\n" +" indx *= 4;\n" +" color = (float4)((float)src[indx+0], (float)src[indx+1], (float)src[indx+2], (float)src[indx+3]);\n" +" color /= (float4)(255.f, 255.f, 255.f, 255.f);\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n", + +"__kernel void testWritei(__global char *src, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(dstimg) + tid_x;\n" +" int4 color;\n" +"\n" +" indx *= 4;\n" +" color.x = (int)src[indx+0];\n" +" color.y = (int)src[indx+1];\n" +" color.z = (int)src[indx+2];\n" +" color.w = (int)src[indx+3];\n" +" write_imagei(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n", + +"__kernel void testWriteui(__global uchar *src, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(dstimg) + tid_x;\n" +" uint4 color;\n" +"\n" +" indx *= 4;\n" +" color.x = (uint)src[indx+0];\n" +" color.y = (uint)src[indx+1];\n" +" color.z = (uint)src[indx+2];\n" +" color.w = (uint)src[indx+3];\n" +" write_imageui(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n" }; + +static const char *readKernelName[] = { "testWritef", "testWritei", "testWriteui" }; + + +//--- helper functions +static cl_uchar *generateImage( int n, MTdata d ) +{ + cl_uchar *ptr = (cl_uchar *)malloc( n * sizeof( cl_uchar ) ); + int i; + + for( i = 0; i < n; i++ ){ + ptr[i] = (cl_uchar)genrand_int32( d ); + } + + return ptr; + +} + + +static char *generateSignedImage( int n, MTdata d ) +{ + char *ptr = (char *)malloc( n * sizeof( char ) ); + int i; + + for( i = 0; i < n; i++ ){ + ptr[i] = (char)genrand_int32( d ); + } + + return ptr; + +} + + +static int verifyImage( cl_uchar *image, cl_uchar *outptr, int w, int h ) +{ + int i; + + for( i = 0; i < w * h * 4; i++ ){ + if( outptr[i] != image[i] ){ + return -1; + } + } + + return 0; +} + + +//----- the test functions +int read_image( cl_device_id device, cl_context context, cl_command_queue queue, int numElements, const char *code, const char *name, + cl_image_format image_format_desc ) +{ + cl_mem memobjs[2]; + cl_program program[1]; + void *inptr; + void *dst = NULL; + cl_kernel kernel[1]; + cl_event readEvent; + cl_ulong queueStart, submitStart, readStart, readEnd; + size_t threads[2]; +#ifdef USE_LOCAL_THREADS + size_t localThreads[2]; +#endif + int err; + int w = 64, h = 64; + cl_mem_flags flags; + size_t element_nbytes; + size_t num_bytes; + size_t channel_nbytes = sizeof( cl_uchar ); + MTdata d; + + + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + + element_nbytes = channel_nbytes * get_format_channel_count( &image_format_desc ); + num_bytes = w * h * element_nbytes; + + threads[0] = (size_t)w; + threads[1] = (size_t)h; + +#ifdef USE_LOCAL_THREADS + err = clGetDeviceConfigInfo( id, CL_DEVICE_MAX_THREAD_GROUP_SIZE, localThreads, sizeof( unsigned int ), NULL ); + test_error( err, "Unable to get thread group max size" ); + localThreads[1] = localThreads[0]; + if( localThreads[0] > threads[0] ) + localThreads[0] = threads[0]; + if( localThreads[1] > threads[1] ) + localThreads[1] = threads[1]; +#endif + + d = init_genrand( gRandomSeed ); + if( image_format_desc.image_channel_data_type == CL_SIGNED_INT8 ) + inptr = (void *)generateSignedImage( w * h * 4, d ); + else + inptr = (void *)generateImage( w * h * 4, d ); + free_mtdata(d); d = NULL; + + if( ! inptr ){ + log_error("unable to allocate inptr at %d x %d\n", (int)w, (int)h ); + return -1; + } + + dst = malloc( num_bytes ); + if( ! dst ){ + free( (void *)inptr ); + log_error("unable to allocate dst at %d x %d\n", (int)w, (int)h ); + return -1; + } + + // allocate the input and output image memory objects + flags = (cl_mem_flags)(CL_MEM_READ_WRITE); + memobjs[0] = create_image_2d( context, flags, &image_format_desc, w, h, 0, NULL, &err ); + if( memobjs[0] == (cl_mem)0 ){ + free( dst ); + free( (void *)inptr ); + log_error("unable to create Image2D\n"); + return -1; + } + + memobjs[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), channel_nbytes * 4 * w * h, NULL, &err ); + if( memobjs[1] == (cl_mem)0 ){ + free( dst ); + free( (void *)inptr ); + clReleaseMemObject(memobjs[0]); + log_error("unable to create array\n"); + return -1; + } + + err = clEnqueueWriteBuffer( queue, memobjs[1], true, 0, num_bytes, inptr, 0, NULL, NULL ); + if( err != CL_SUCCESS ){ + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + log_error("clWriteArray failed\n"); + return -1; + } + + err = create_single_kernel_helper( context, &program[0], &kernel[0], 1, &code, name ); + if( err ){ + log_error( "Unable to create program and kernel\n" ); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + err = clSetKernelArg( kernel[0], 0, sizeof( cl_mem ), (void *)&memobjs[1] ); + err |= clSetKernelArg( kernel[0], 1, sizeof( cl_mem ), (void *)&memobjs[0] ); + if( err != CL_SUCCESS ){ + log_error( "clSetKernelArg failed\n" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + +#ifdef USE_LOCAL_THREADS + err = clEnqueueNDRangeKernel(queue, kernel[0], 2, NULL, threads, localThreads, 0, NULL, NULL ); +#else + err = clEnqueueNDRangeKernel(queue, kernel[0], 2, NULL, threads, NULL, 0, NULL, NULL ); +#endif + if( err != CL_SUCCESS ){ + print_error( err, "clEnqueueNDRangeKernel failed" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + size_t origin[3] = { 0, 0, 0 }; + size_t region[3] = { w, h, 1 }; + err = clEnqueueReadImage( queue, memobjs[0], false, origin, region, 0, 0, dst, 0, NULL, &readEvent ); + if( err != CL_SUCCESS ){ + print_error( err, "clReadImage2D failed" ); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + // This synchronization point is needed in order to assume the data is valid. + // Getting profiling information is not a synchronization point. + err = clWaitForEvents( 1, &readEvent ); + if( err != CL_SUCCESS ) + { + clReleaseEvent(readEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + while( ( err = clGetEventProfilingInfo( readEvent, CL_PROFILING_COMMAND_QUEUED, sizeof( cl_ulong ), &queueStart, NULL ) ) == + CL_PROFILING_INFO_NOT_AVAILABLE ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(readEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + while( ( err = clGetEventProfilingInfo( readEvent, CL_PROFILING_COMMAND_SUBMIT, sizeof( cl_ulong ), &submitStart, NULL ) ) == + CL_PROFILING_INFO_NOT_AVAILABLE ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(readEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + err = clGetEventProfilingInfo( readEvent, CL_PROFILING_COMMAND_START, sizeof( cl_ulong ), &readStart, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(readEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + err = clGetEventProfilingInfo( readEvent, CL_PROFILING_COMMAND_END, sizeof( cl_ulong ), &readEnd, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(readEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + err = verifyImage( (cl_uchar *)inptr, (cl_uchar *)dst, w, h ); + if( err ){ + log_error( "Image failed to verify.\n" ); + } + else{ + log_info( "Image verified.\n" ); + } + + clReleaseEvent(readEvent); + clReleaseKernel(kernel[0]); + clReleaseProgram(program[0]); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free(dst); + free(inptr); + + if (check_times(queueStart, submitStart, readStart, readEnd, device)) + err = -1; + + return err; + +} // end read_image() + + +int read_float_image( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + cl_image_format image_format_desc = { CL_RGBA, CL_UNORM_INT8 }; + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + // 0 to 255 for unsigned image data + return read_image( device, context, queue, numElements, readKernelCode[0], readKernelName[0], image_format_desc ); + +} + + +int read_char_image( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + cl_image_format image_format_desc = { CL_RGBA, CL_SIGNED_INT8 }; + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + // -128 to 127 for signed iamge data + return read_image( device, context, queue, numElements, readKernelCode[1], readKernelName[1], image_format_desc ); + +} + + +int read_uchar_image( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + cl_image_format image_format_desc = { CL_RGBA, CL_UNSIGNED_INT8 }; + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + // 0 to 255 for unsigned image data + return read_image( device, context, queue, numElements, readKernelCode[2], readKernelName[2], image_format_desc ); + +} + + diff --git a/test_conformance/profiling/writeArray.c b/test_conformance/profiling/writeArray.c new file mode 100644 index 00000000..23e29b62 --- /dev/null +++ b/test_conformance/profiling/writeArray.c @@ -0,0 +1,1375 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/conversions.h" + +//#define USE_LOCAL_THREADS 1 + +#ifndef uchar +typedef unsigned char uchar; +#endif + +#ifndef TestStruct +typedef struct{ + int a; + float b; +} TestStruct; +#endif + +const char *stream_write_int_kernel_code[] = { + "__kernel void test_stream_write_int(__global int *src, __global int *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_int2(__global int2 *src, __global int2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_int4(__global int4 *src, __global int4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_int8(__global int8 *src, __global int8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_int16(__global int16 *src, __global int16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *int_kernel_name[] = { "test_stream_write_int", "test_stream_write_int2", "test_stream_write_int4", "test_stream_write_int8", "test_stream_write_int16" }; + + +const char *stream_write_uint_kernel_code[] = { + "__kernel void test_stream_write_uint(__global uint *src, __global uint *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_uint2(__global uint2 *src, __global uint2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_uint4(__global uint4 *src, __global uint4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_uint8(__global uint8 *src, __global uint8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_uint16(__global uint16 *src, __global uint16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *uint_kernel_name[] = { "test_stream_write_uint", "test_stream_write_uint2", "test_stream_write_uint4", "test_stream_write_uint8", "test_stream_write_uint16" }; + + +const char *stream_write_ushort_kernel_code[] = { + "__kernel void test_stream_write_ushort(__global ushort *src, __global ushort *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_ushort2(__global ushort2 *src, __global ushort2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_ushort4(__global ushort4 *src, __global ushort4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_ushort8(__global ushort8 *src, __global ushort8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_ushort16(__global ushort16 *src, __global ushort16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *ushort_kernel_name[] = { "test_stream_write_ushort", "test_stream_write_ushort2", "test_stream_write_ushort4", "test_stream_write_ushort8", "test_stream_write_ushort16" }; + + + +const char *stream_write_short_kernel_code[] = { + "__kernel void test_stream_write_short(__global short *src, __global short *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_short2(__global short2 *src, __global short2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_short4(__global short4 *src, __global short4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_short8(__global short8 *src, __global short8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_short16(__global short16 *src, __global short16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *short_kernel_name[] = { "test_stream_write_short", "test_stream_write_short2", "test_stream_write_short4", "test_stream_write_short8", "test_stream_write_short16" }; + + +const char *stream_write_char_kernel_code[] = { + "__kernel void test_stream_write_char(__global char *src, __global char *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_char2(__global char2 *src, __global char2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_char4(__global char4 *src, __global char4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_char8(__global char8 *src, __global char8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_char16(__global char16 *src, __global char16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *char_kernel_name[] = { "test_stream_write_char", "test_stream_write_char2", "test_stream_write_char4", "test_stream_write_char8", "test_stream_write_char16" }; + + +const char *stream_write_uchar_kernel_code[] = { + "__kernel void test_stream_write_uchar(__global uchar *src, __global uchar *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_uchar2(__global uchar2 *src, __global uchar2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_uchar4(__global uchar4 *src, __global uchar4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_uchar8(__global uchar8 *src, __global uchar8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_uchar16(__global uchar16 *src, __global uchar16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *uchar_kernel_name[] = { "test_stream_write_uchar", "test_stream_write_uchar2", "test_stream_write_uchar4", "test_stream_write_uchar8", "test_stream_write_uchar16" }; + + +const char *stream_write_float_kernel_code[] = { + "__kernel void test_stream_write_float(__global float *src, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_float2(__global float2 *src, __global float2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_float4(__global float4 *src, __global float4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_float8(__global float8 *src, __global float8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_float16(__global float16 *src, __global float16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *float_kernel_name[] = { "test_stream_write_float", "test_stream_write_float2", "test_stream_write_float4", "test_stream_write_float8", "test_stream_write_float16" }; + + +const char *stream_write_half_kernel_code[] = { + "__kernel void test_stream_write_half(__global half *src, __global float *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = vload_half( tid * 2, src );\n" + "}\n", + + "__kernel void test_stream_write_half2(__global half2 *src, __global float2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = vload_half2( tid * 2, src );\n" + "}\n", + + "__kernel void test_stream_write_half4(__global half4 *src, __global float4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = vload_half4( tid * 2, src );\n" + "}\n", + + "__kernel void test_stream_write_half8(__global half8 *src, __global float8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = vload_half8( tid * 2, src );\n" + "}\n", + + "__kernel void test_stream_write_half16(__global half16 *src, __global float16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = vload_half16( tid * 2, src );\n" + "}\n" }; + +static const char *half_kernel_name[] = { "test_stream_write_half", "test_stream_write_half2", "test_stream_write_half4", "test_stream_write_half8", "test_stream_write_half16" }; + + +const char *stream_write_long_kernel_code[] = { + "__kernel void test_stream_write_long(__global long *src, __global long *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_long2(__global long2 *src, __global long2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_long4(__global long4 *src, __global long4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_long8(__global long8 *src, __global long8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_long16(__global long16 *src, __global long16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *long_kernel_name[] = { "test_stream_write_long", "test_stream_write_long2", "test_stream_write_long4", "test_stream_write_long8", "test_stream_write_long16" }; + + +const char *stream_write_ulong_kernel_code[] = { + "__kernel void test_stream_write_ulong(__global ulong *src, __global ulong *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_ulong2(__global ulong2 *src, __global ulong2 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_ulong4(__global ulong4 *src, __global ulong4 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_ulong8(__global ulong8 *src, __global ulong8 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n", + + "__kernel void test_stream_write_ulong16(__global ulong16 *src, __global ulong16 *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid] = src[tid];\n" + "}\n" }; + +static const char *ulong_kernel_name[] = { "test_stream_write_ulong", "test_stream_write_ulong2", "test_stream_write_ulong4", "test_stream_write_ulong8", "test_stream_write_ulong16" }; + + +static const char *stream_write_struct_kernel_code[] = { + "typedef struct{\n" + "int a;\n" + "float b;\n" + "} TestStruct;\n" + "__kernel void read_write_struct(__global TestStruct *src, __global TestStruct *dst)\n" + "{\n" + " int tid = get_global_id(0);\n" + "\n" + " dst[tid].a = src[tid].a;\n" + " dst[tid].b = src[tid].b;\n" + "}\n" }; + +static const char *struct_kernel_name[] = { "read_write_struct" }; + + +static int verify_write_int( void *ptr1, void *ptr2, int n ) +{ + int i; + int *inptr = (int *)ptr1; + int *outptr = (int *)ptr2; + + for (i=0; i threads[0] ) + localThreads[0] = threads[0]; +#endif + + ptrSizes[0] = size; + ptrSizes[1] = ptrSizes[0] << 1; + ptrSizes[2] = ptrSizes[1] << 1; + ptrSizes[3] = ptrSizes[2] << 1; + ptrSizes[4] = ptrSizes[3] << 1; + + loops = ( loops < 5 ? loops : 5 ); + + for( i = 0; i < loops; i++ ) + { + outPtrSizes[i] = ptrSizes[i]; + } + + for( i = 0; i < loops; i++ ){ + ii = i << 1; + streams[ii] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), ptrSizes[i] * num_elements, NULL, &err ); + if( ! streams[ii] ){ + free( outptr[i] ); + log_error( " clCreateBuffer failed\n" ); + return -1; + } + if( ! strcmp( type, "half" ) ){ + outptr[i] = malloc( outPtrSizes[i] * num_elements * 2 ); + streams[ii+1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), outPtrSizes[i] * 2 * num_elements, NULL, &err ); + } + else{ + outptr[i] = malloc( outPtrSizes[i] * num_elements ); + streams[ii+1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), outPtrSizes[i] * num_elements, NULL, &err ); + } + if( ! streams[ii+1] ){ + clReleaseMemObject(streams[ii]); + free( outptr[i] ); + log_error( " clCreateBuffer failed\n" ); + return -1; + } + + err = clEnqueueWriteBuffer( queue, streams[ii], false, 0, ptrSizes[i]*num_elements, inptr[i], 0, NULL, &writeEvent ); + if( err != CL_SUCCESS ){ + clReleaseMemObject( streams[ii] ); + clReleaseMemObject( streams[ii+1] ); + free( outptr[i] ); + print_error( err, " clWriteArray failed" ); + return -1; + } + + // This synchronization point is needed in order to assume the data is valid. + // Getting profiling information is not a synchronization point. + err = clWaitForEvents( 1, &writeEvent ); + if( err != CL_SUCCESS ) + { + print_error( err, "Unable to wait for event completion" ); + clReleaseEvent(writeEvent); + clReleaseMemObject( streams[ii] ); + clReleaseMemObject( streams[ii+1] ); + free( outptr[i] ); + return -1; + } + + // test profiling + while( ( err = clGetEventProfilingInfo( writeEvent, CL_PROFILING_COMMAND_QUEUED, sizeof( cl_ulong ), &queueStart, NULL ) ) == + CL_PROFILING_INFO_NOT_AVAILABLE ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(writeEvent); + clReleaseMemObject( streams[ii] ); + clReleaseMemObject( streams[ii+1] ); + free( outptr[i] ); + return -1; + } + + while( ( err = clGetEventProfilingInfo( writeEvent, CL_PROFILING_COMMAND_SUBMIT, sizeof( cl_ulong ), &submitStart, NULL ) ) == + CL_PROFILING_INFO_NOT_AVAILABLE ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(writeEvent); + clReleaseMemObject( streams[ii] ); + clReleaseMemObject( streams[ii+1] ); + free( outptr[i] ); + return -1; + } + + err = clGetEventProfilingInfo( writeEvent, CL_PROFILING_COMMAND_START, sizeof( cl_ulong ), &writeStart, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(writeEvent); + clReleaseMemObject( streams[ii] ); + clReleaseMemObject( streams[ii+1] ); + free( outptr[i] ); + return -1; + } + + err = clGetEventProfilingInfo( writeEvent, CL_PROFILING_COMMAND_END, sizeof( cl_ulong ), &writeEnd, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(writeEvent); + clReleaseMemObject( streams[ii] ); + clReleaseMemObject( streams[ii+1] ); + free( outptr[i] ); + return -1; + } + + + err = create_single_kernel_helper( context, &program[i], &kernel[i], 1, &kernelCode[i], kernelName[i] ); + if( err ){ + clReleaseEvent(writeEvent); + clReleaseMemObject(streams[ii]); + clReleaseMemObject(streams[ii+1]); + free( outptr[i] ); + log_error( " Error creating program for %s\n", type ); + return -1; + } + + err = clSetKernelArg( kernel[i], 0, sizeof( cl_mem ), (void *)&streams[ii] ); + err |= clSetKernelArg( kernel[i], 1, sizeof( cl_mem ), (void *)&streams[ii+1] ); + if (err != CL_SUCCESS){ + clReleaseEvent(writeEvent); + clReleaseKernel( kernel[i] ); + clReleaseProgram( program[i] ); + clReleaseMemObject( streams[ii] ); + clReleaseMemObject( streams[ii+1] ); + free( outptr[i] ); + print_error( err, " clSetKernelArg failed" ); + return -1; + } + +#ifdef USE_LOCAL_THREADS + err = clEnqueueNDRangeKernel( queue, kernel[i], 1, NULL, threads, localThreads, 0, NULL, NULL ); +#else + err = clEnqueueNDRangeKernel( queue, kernel[i], 1, NULL, threads, NULL, 0, NULL, NULL ); +#endif + if( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseEvent(writeEvent); + clReleaseKernel( kernel[i] ); + clReleaseProgram( program[i] ); + clReleaseMemObject( streams[ii] ); + clReleaseMemObject( streams[ii+1] ); + free( outptr[i] ); + return -1; + } + + if( ! strcmp( type, "half" ) ){ + err = clEnqueueReadBuffer( queue, streams[ii+1], true, 0, outPtrSizes[i]*num_elements, outptr[i], 0, NULL, NULL ); + } + else{ + err = clEnqueueReadBuffer( queue, streams[ii+1], true, 0, outPtrSizes[i]*num_elements, outptr[i], 0, NULL, NULL ); + } + if( err != CL_SUCCESS ){ + clReleaseEvent(writeEvent); + clReleaseKernel( kernel[i] ); + clReleaseProgram( program[i] ); + clReleaseMemObject( streams[ii] ); + clReleaseMemObject( streams[ii+1] ); + free( outptr[i] ); + print_error( err, " clEnqueueReadBuffer failed" ); + return -1; + } + + char *inP = (char *)inptr[i]; + char *outP = (char *)outptr[i]; + int err2 = 0; + for( size_t p = 0; p < (size_t)num_elements; p++ ) + { + if( fn( inP, outP, (int)(ptrSizes[i] / ptrSizes[0]) ) ) + { + log_error( " %s%d data failed to verify\n", type, 1< threads[0] ) + localThreads[0] = threads[0]; + #endif + + ptrSizes[0] = size; + ptrSizes[1] = ptrSizes[0] << 1; + ptrSizes[2] = ptrSizes[1] << 1; + ptrSizes[3] = ptrSizes[2] << 1; + ptrSizes[4] = ptrSizes[3] << 1; + + + loops = ( loops < 5 ? loops : 5 ); + for( i = 0; i < loops; i++ ){ + + inptr[i] = (TestStruct *)malloc(ptrSizes[i] * num_elements); + + for( j = 0; j < ptrSizes[i] * num_elements / ptrSizes[0]; j++ ){ + inptr[i][j].a = (int)random_float( -2147483648.f, 2147483647.0f ); + inptr[i][j].b = random_float( -FLT_MAX, FLT_MAX ); + } + + ii = i << 1; + streams[ii] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), ptrSizes[i] * num_elements, NULL); + if( ! streams[ii] ){ + free( outptr[i] ); + log_error( " clCreateBuffer failed\n" ); + return -1; + } + outptr[i] = malloc( ptrSizes[i] * num_elements ); + streams[ii+1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), ptrSizes[i] * num_elements, NULL); + if( ! streams[ii+1] ){ + clReleaseMemObject(streams[ii]); + free( outptr[i] ); + log_error( " clCreateBuffer failed\n" ); + return -1; + } + + err = clWriteArray(context, streams[ii], false, 0, ptrSizes[i]*num_elements, inptr[i], NULL); + if( err != CL_SUCCESS ){ + clReleaseMemObject(streams[ii]); + clReleaseMemObject(streams[ii+1]); + free( outptr[i] ); + print_error( err, " clWriteArray failed" ); + return -1; + } + + err = create_program_and_kernel( device, struct_kernel_code, "read_write_struct", &program[i], &kernel[i] ); + if( err ){ + clReleaseMemObject(streams[ii]); + clReleaseMemObject(streams[ii+1]); + free( outptr[i] ); + log_error( " Error creating program for struct\n" ); + return -1; + } + + err = clSetKernelArg( kernel[i], 0, sizeof( cl_mem ), (void *)&streams[ii] ); + err |= clSetKernelArg( kernel[i], 1, sizeof( cl_mem ), (void *)&streams[ii+1] ); + if (err != CL_SUCCESS){ + clReleaseProgram( program[i] ); + clReleaseKernel( kernel[i] ); + clReleaseMemObject( streams[ii] ); + clReleaseMemObject( streams[ii+1] ); + free( outptr[i] ); + print_error( err, " clSetKernelArg failed" ); + return -1; + } + + #ifdef USE_LOCAL_THREADS + err = clEnqueueNDRangeKernel( queue, kernel[i], 1, NULL, threads, localThreads, 0, NULL, NULL ); + #else + err = clEnqueueNDRangeKernel( queue, kernel[i], 1, NULL, threads, NULL, 0, NULL, NULL ); + #endif + if( err != CL_SUCCESS ){ + print_error( err, " clEnqueueNDRangeKernel failed" ); + clReleaseMemObject( streams[ii] ); + clReleaseMemObject( streams[ii+1] ); + clReleaseKernel( kernel[i] ); + clReleaseProgram( program[i] ); + free( outptr[i] ); + return -1; + } + + err = clEnqueueReadBuffer( queue, streams[ii+1], true, 0, ptrSizes[i]*num_elements, outptr[i], 0, NULL, NULL ); + if( err != CL_SUCCESS ){ + clReleaseMemObject( streams[ii] ); + clReleaseMemObject( streams[ii+1] ); + clReleaseKernel( kernel[i] ); + clReleaseProgram( program[i] ); + free( outptr[i] ); + print_error( err, " clEnqueueReadBuffer failed" ); + return -1; + } + + if( verify_write_struct( inptr[i], outptr[i], ptrSizes[i] * num_elements / ptrSizes[0] ) ){ + log_error( " STREAM_WRITE struct%d test failed\n", 1< +#include +#include +#include + +#include "procs.h" +#include "../../test_common/harness/testHarness.h" +#include "../../test_common/harness/errorHelpers.h" + +//--- the code for the kernel executables +static const char *readKernelCode[] = { +"__kernel void testReadf(read_only image2d_t srcimg, __global float4 *dst)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(srcimg) + tid_x;\n" +" float4 color;\n" +"\n" +" const sampler_t sampler = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST | CLK_NORMALIZED_COORDS_FALSE;\n" +" color = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y));\n" +" dst[indx].x = color.x;\n" +" dst[indx].y = color.y;\n" +" dst[indx].z = color.z;\n" +" dst[indx].w = color.w;\n" +"\n" +"}\n", + +"__kernel void testReadi(read_only image2d_t srcimg, __global uchar4 *dst)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(srcimg) + tid_x;\n" +" int4 color;\n" +"\n" +" const sampler_t sampler = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST | CLK_NORMALIZED_COORDS_FALSE;\n" +" color = read_imagei(srcimg, sampler, (int2)(tid_x, tid_y));\n" +" uchar4 dst_write;\n" +" dst_write.x = (uchar)color.x;\n" +" dst_write.y = (uchar)color.y;\n" +" dst_write.z = (uchar)color.z;\n" +" dst_write.w = (uchar)color.w;\n" +" dst[indx] = dst_write;\n" +"\n" +"}\n", + +"__kernel void testReadui(read_only image2d_t srcimg, __global uchar4 *dst)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(srcimg) + tid_x;\n" +" uint4 color;\n" +"\n" +" const sampler_t sampler = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST | CLK_NORMALIZED_COORDS_FALSE;\n" +" color = read_imageui(srcimg, sampler, (int2)(tid_x, tid_y));\n" +" uchar4 dst_write;\n" +" dst_write.x = (uchar)color.x;\n" +" dst_write.y = (uchar)color.y;\n" +" dst_write.z = (uchar)color.z;\n" +" dst_write.w = (uchar)color.w;\n" +" dst[indx] = dst_write;\n" +"\n" +"}\n", + +"__kernel void testWritef(__global uchar *src, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(dstimg) + tid_x;\n" +" float4 color;\n" +"\n" +" indx *= 4;\n" +" color = (float4)((float)src[indx+0], (float)src[indx+1], (float)src[indx+2], (float)src[indx+3]);\n" +" color /= (float4)(255.f, 255.f, 255.f, 255.f);\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n", + +"__kernel void testWritei(__global char *src, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(dstimg) + tid_x;\n" +" int4 color;\n" +"\n" +" indx *= 4;\n" +" color.x = (int)src[indx+0];\n" +" color.y = (int)src[indx+1];\n" +" color.z = (int)src[indx+2];\n" +" color.w = (int)src[indx+3];\n" +" write_imagei(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n", + +"__kernel void testWriteui(__global uchar *src, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int indx = tid_y * get_image_width(dstimg) + tid_x;\n" +" uint4 color;\n" +"\n" +" indx *= 4;\n" +" color.x = (uint)src[indx+0];\n" +" color.y = (uint)src[indx+1];\n" +" color.z = (uint)src[indx+2];\n" +" color.w = (uint)src[indx+3];\n" +" write_imageui(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n", + +"__kernel void testReadWriteff(read_only image2d_t srcimg, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 color;\n" +"\n" +" color = read_imagef(srcimg, CLK_DEFAULT_SAMPLER, (int2)(tid_x, tid_y));\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n", + +"__kernel void testReadWriteii(read_only image2d_t srcimg, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int4 color;\n" +"\n" +" color = read_imagei(srcimg, CLK_DEFAULT_SAMPLER, (int2)(tid_x, tid_y));\n" +" write_imagei(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n", + +"__kernel void testReadWriteuiui(read_only image2d_t srcimg, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" uint4 color;\n" +"\n" +" color = read_imageui(srcimg, CLK_DEFAULT_SAMPLER, (int2)(tid_x, tid_y));\n" +" write_imageui(dstimg, (int2)(tid_x, tid_y), color);\n" +"\n" +"}\n", + +"__kernel void testReadWritefi(read_only image2d_t srcimg, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 colorf;\n" +" int4 colori;\n" +"\n" +" const sampler_t sampler = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST | CLK_NORMALIZED_COORDS_FALSE;\n" +" colorf = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y));\n" +// since we are going from unsigned to signed, be sure to convert +// values greater 0.5 to negative values +" if( colorf.x >= 0.5f )\n" +" colori.x = (int)( ( colorf.x - 1.f ) * 255.f );\n" +" else\n" +" colori.x = (int)( colorf.x * 255.f );\n" +" if( colorf.y >= 0.5f )\n" +" colori.y = (int)( ( colorf.y - 1.f ) * 255.f );\n" +" else\n" +" colori.y = (int)( colorf.y * 255.f );\n" +" if( colorf.z >= 0.5f )\n" +" colori.z = (int)( ( colorf.z - 1.f ) * 255.f );\n" +" else\n" +" colori.z = (int)( colorf.z * 255.f );\n" +" if( colorf.w >= 0.5f )\n" +" colori.w = (int)( ( colorf.w - 1.f ) * 255.f );\n" +" else\n" +" colori.w = (int)( colorf.w * 255.f );\n" +" write_imagei(dstimg, (int2)(tid_x, tid_y), colori);\n" +"\n" +"}\n", + +"__kernel void testReadWritefui(read_only image2d_t srcimg, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" float4 colorf;\n" +" uint4 colorui;\n" +"\n" +" const sampler_t sampler = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST | CLK_NORMALIZED_COORDS_FALSE;\n" +" colorf = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y));\n" +" colorui.x = (uint)( colorf.x * 255.f );\n" +" colorui.y = (uint)( colorf.y * 255.f );\n" +" colorui.z = (uint)( colorf.z * 255.f );\n" +" colorui.w = (uint)( colorf.w * 255.f );\n" +" write_imageui(dstimg, (int2)(tid_x, tid_y), colorui);\n" +"\n" +"}\n", + +"__kernel void testReadWriteif(read_only image2d_t srcimg, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int4 colori;\n" +" float4 colorf;\n" +"\n" +// since we are going from signed to unsigned, we need to adjust the rgba values from +// from the signed image to add 256 to the signed image values less than 0. +" const sampler_t sampler = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST | CLK_NORMALIZED_COORDS_FALSE;\n" +" colori = read_imagei(srcimg, sampler, (int2)(tid_x, tid_y));\n" +" if( colori.x < 0 )\n" +" colorf.x = ( (float)colori.x + 256.f ) / 255.f;\n" +" else\n" +" colorf.x = (float)colori.x / 255.f;\n" +" if( colori.y < 0 )\n" +" colorf.y = ( (float)colori.y + 256.f ) / 255.f;\n" +" else\n" +" colorf.y = (float)colori.y / 255.f;\n" +" if( colori.z < 0 )\n" +" colorf.z = ( (float)colori.z + 256.f ) / 255.f;\n" +" else\n" +" colorf.z = (float)colori.z / 255.f;\n" +" if( colori.w < 0 )\n" +" colorf.w = ( (float)colori.w + 256.f ) / 255.f;\n" +" else\n" +" colorf.w = (float)colori.w / 255.f;\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), colorf);\n" +"\n" +"}\n", + +"__kernel void testReadWriteiui(read_only image2d_t srcimg, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" int4 colori;\n" +" uint4 colorui;\n" +"\n" +" const sampler_t sampler = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST | CLK_NORMALIZED_COORDS_FALSE;\n" +" colori = read_imagei(srcimg, sampler, (int2)(tid_x, tid_y));\n" +// since we are going from signed to unsigned, we need to adjust the rgba values from +// from the signed image to add 256 to the signed image values less than 0. +" if( colori.x < 0 )\n" +" colorui.x = (uint)( colori.x + 256 );\n" +" else\n" +" colorui.x = (uint)colori.x;\n" +" if( colori.y < 0 )\n" +" colorui.y = (uint)( colori.y + 256 );\n" +" else\n" +" colorui.y = (uint)colori.y;\n" +" if( colori.z < 0 )\n" +" colorui.z = (uint)( colori.z + 256 );\n" +" else\n" +" colorui.z = (uint)colori.z;\n" +" if( colori.w < 0 )\n" +" colorui.w = (uint)( colori.w + 256 );\n" +" else\n" +" colorui.w = (uint)colori.w;\n" +" write_imageui(dstimg, (int2)(tid_x, tid_y), colorui);\n" +"\n" +"}\n", + +"__kernel void testReadWriteuif(read_only image2d_t srcimg, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" uint4 colorui;\n" +" float4 colorf;\n" +"\n" +" const sampler_t sampler = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST | CLK_NORMALIZED_COORDS_FALSE;\n" +" colorui = read_imageui(srcimg, sampler, (int2)(tid_x, tid_y));\n" +" colorf.x = (float)colorui.x / 255.f;\n" +" colorf.y = (float)colorui.y / 255.f;\n" +" colorf.z = (float)colorui.z / 255.f;\n" +" colorf.w = (float)colorui.w / 255.f;\n" +" write_imagef(dstimg, (int2)(tid_x, tid_y), colorf);\n" +"\n" +"}\n", + +"__kernel void testReadWriteuii(read_only image2d_t srcimg, write_only image2d_t dstimg)\n" +"{\n" +" int tid_x = get_global_id(0);\n" +" int tid_y = get_global_id(1);\n" +" uint4 colorui;\n" +" int4 colori;\n" +"\n" +" const sampler_t sampler = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST | CLK_NORMALIZED_COORDS_FALSE;\n" +" colorui = read_imageui(srcimg, sampler, (int2)(tid_x, tid_y));\n" +// since we are going from unsigned to signed, be sure to convert +// values greater 0.5 to negative values +" if( colorui.x >= 128U )\n" +" colori.x = (int)colorui.x - 256;\n" +" else\n" +" colori.x = (int)colorui.x;\n" +" if( colorui.y >= 128U )\n" +" colori.y = (int)colorui.y - 256;\n" +" else\n" +" colori.y = (int)colorui.y;\n" +" if( colorui.z >= 128U )\n" +" colori.z = (int)colorui.z - 256;\n" +" else\n" +" colori.z = (int)colorui.z;\n" +" if( colorui.w >= 128U )\n" +" colori.w = (int)colorui.w - 256;\n" +" else\n" +" colori.w = (int)colorui.w;\n" +" write_imagei(dstimg, (int2)(tid_x, tid_y), colori);\n" +"\n" +"}\n" }; + +static const char *readKernelName[] = { "testReadf", "testReadi", "testReadui", "testWritef", "testWritei", "testWriteui", +"testReadWriteff", "testReadWriteii", "testReadWriteuiui", "testReadWritefi", +"testReadWritefui", "testReadWriteif", "testReadWriteiui", "testReadWriteuif", +"testReadWriteuii" }; + + +static cl_uchar *generateImage( int n, MTdata d ) +{ + cl_uchar *ptr = (cl_uchar *)malloc( n * sizeof( cl_uchar ) ); + int i; + + for( i = 0; i < n; i++ ){ + ptr[i] = (cl_uchar)genrand_int32(d); + } + + return ptr; + +} + + +static char *generateSignedImage( int n, MTdata d ) +{ + char *ptr = (char *)malloc( n * sizeof( char ) ); + int i; + + for( i = 0; i < n; i++ ){ + ptr[i] = (char)genrand_int32(d); + } + + return ptr; + +} + + +static int verifyImage( cl_uchar *image, cl_uchar *outptr, int w, int h ) +{ + int i; + + for( i = 0; i < w * h * 4; i++ ){ + if( outptr[i] != image[i] ){ + log_error("Image verification failed at offset %d. Actual value=%d, expected value=%d\n", i, outptr[i], image[i]); + return -1; + } + } + + return 0; +} + +static int verifyImageFloat ( cl_double *refptr, cl_float *outptr, int w, int h ) +{ + int i; + + for (i=0; i threads[0] ) + localThreads[0] = threads[0]; + if( localThreads[1] > threads[1] ) + localThreads[1] = threads[1]; +#endif + + d = init_genrand( gRandomSeed ); + if( image_format_desc.image_channel_data_type == CL_SIGNED_INT8 ) + inptr = (void *)generateSignedImage( w * h * 4, d ); + else + inptr = (void *)generateImage( w * h * 4, d ); + free_mtdata(d); d = NULL; + if( ! inptr ){ + log_error("unable to allocate inptr at %d x %d\n", (int)w, (int)h ); + return -1; + } + + dst = malloc( num_bytes ); + if( ! dst ){ + free( (void *)inptr ); + log_error("unable to allocate dst at %d x %d\n", (int)w, (int)h ); + return -1; + } + + // allocate the input and output image memory objects + flags = (cl_mem_flags)(CL_MEM_READ_WRITE); + memobjs[0] = create_image_2d( context, flags, &image_format_desc, w, h, 0, NULL, &err ); + if( memobjs[0] == (cl_mem)0 ){ + free( dst ); + free( (void *)inptr ); + log_error("unable to create Image2D\n"); + return -1; + } + + memobjs[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), channel_nbytes * 4 * w * h, NULL, &err ); + if( memobjs[1] == (cl_mem)0 ){ + free( dst ); + free( (void *)inptr ); + clReleaseMemObject(memobjs[0]); + log_error("unable to create array\n"); + return -1; + } + + size_t origin[3] = { 0, 0, 0 }; + size_t region[3] = { w, h, 1 }; + err = clEnqueueWriteImage( queue, memobjs[0], false, origin, region, 0, 0, inptr, 0, NULL, &writeEvent ); + if( err != CL_SUCCESS ){ + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + print_error(err, "clWriteImage failed"); + return -1; + } + + // This synchronization point is needed in order to assume the data is valid. + // Getting profiling information is not a synchronization point. + err = clWaitForEvents( 1, &writeEvent ); + if( err != CL_SUCCESS ) + { + print_error( err, "clWaitForEvents failed" ); + clReleaseEvent(writeEvent); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + // test profiling + while( ( err = clGetEventProfilingInfo( writeEvent, CL_PROFILING_COMMAND_QUEUED, sizeof( cl_ulong ), &queueStart, NULL ) ) == + CL_PROFILING_INFO_NOT_AVAILABLE ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(writeEvent); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + while( ( err = clGetEventProfilingInfo( writeEvent, CL_PROFILING_COMMAND_SUBMIT, sizeof( cl_ulong ), &submitStart, NULL ) ) == + CL_PROFILING_INFO_NOT_AVAILABLE ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(writeEvent); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + err = clGetEventProfilingInfo( writeEvent, CL_PROFILING_COMMAND_START, sizeof( cl_ulong ), &writeStart, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(writeEvent); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + err = clGetEventProfilingInfo( writeEvent, CL_PROFILING_COMMAND_END, sizeof( cl_ulong ), &writeEnd, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clGetEventProfilingInfo failed" ); + clReleaseEvent(writeEvent); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + err = create_single_kernel_helper( context, &program[0], &kernel[0], 1, &code, name ); + if( err ){ + log_error( "Unable to create program and kernel\n" ); + clReleaseEvent(writeEvent); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + err = clSetKernelArg( kernel[0], 0, sizeof( cl_mem ), (void *)&memobjs[0] ); + err |= clSetKernelArg( kernel[0], 1, sizeof( cl_mem ), (void *)&memobjs[1] ); + if( err != CL_SUCCESS ){ + log_error( "clSetKernelArg failed\n" ); + clReleaseEvent(writeEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + +#ifdef USE_LOCAL_THREADS + err = clEnqueueNDRangeKernel(queue, kernel[0], 2, NULL, threads, localThreads, 0, NULL, NULL ); +#else + err = clEnqueueNDRangeKernel(queue, kernel[0], 2, NULL, threads, NULL, 0, NULL, NULL ); +#endif + if( err != CL_SUCCESS ){ + print_error( err, "clEnqueueNDRangeKernel failed" ); + clReleaseEvent(writeEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + err = clEnqueueReadBuffer( queue, memobjs[1], true, 0, num_bytes, dst, 0, NULL, NULL ); + if( err != CL_SUCCESS ){ + print_error( err, "clEnqueueReadBuffer failed" ); + clReleaseEvent(writeEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + return -1; + } + + if ( readFloat ) + { + refptr = prepareReference( (cl_uchar *)inptr, w, h ); + if ( refptr ) + { + err = verifyImageFloat( refptr, (cl_float *)dst, w, h ); + free ( refptr ); + } + else + err = -1; + } + else + err = verifyImage( (cl_uchar *)inptr, (cl_uchar *)dst, w, h ); + + if( err ) + { + log_error( "Image failed to verify.\n" ); + } + else + { + log_info( "Image verified.\n" ); + } + + // cleanup + clReleaseEvent(writeEvent); + clReleaseKernel( kernel[0] ); + clReleaseProgram( program[0] ); + clReleaseMemObject(memobjs[0]); + clReleaseMemObject(memobjs[1]); + free( dst ); + free( inptr ); + + if (check_times(queueStart, submitStart, writeStart, writeEnd, device)) + err = -1; + + return err; + +} // end write_image() + + +int write_float_image( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + cl_image_format image_format_desc = { CL_RGBA, CL_UNORM_INT8 }; + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + // 0 to 255 for unsigned image data + return write_image( device, context, queue, numElements, readKernelCode[0], readKernelName[0], image_format_desc, 1 ); + +} + + +int write_char_image( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + cl_image_format image_format_desc = { CL_RGBA, CL_SIGNED_INT8 }; + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + // -128 to 127 for signed iamge data + return write_image( device, context, queue, numElements, readKernelCode[1], readKernelName[1], image_format_desc, 0 ); + +} + + +int write_uchar_image( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + cl_image_format image_format_desc = { CL_RGBA, CL_UNSIGNED_INT8 }; + PASSIVE_REQUIRE_IMAGE_SUPPORT( device ) + // 0 to 255 for unsigned image data + return write_image( device, context, queue, numElements, readKernelCode[2], readKernelName[2], image_format_desc, 0 ); + +} + + diff --git a/test_conformance/relationals/CMakeLists.txt b/test_conformance/relationals/CMakeLists.txt new file mode 100644 index 00000000..159b8e5b --- /dev/null +++ b/test_conformance/relationals/CMakeLists.txt @@ -0,0 +1,20 @@ +set(MODULE_NAME RELATIONALS) + +set(${MODULE_NAME}_SOURCES + main.c + test_relationals.cpp + test_comparisons_float.cpp + test_comparisons_double.cpp + test_shuffles.cpp + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/threadTesting.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/conversions.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) + diff --git a/test_conformance/relationals/Jamfile b/test_conformance/relationals/Jamfile new file mode 100644 index 00000000..1ef71abf --- /dev/null +++ b/test_conformance/relationals/Jamfile @@ -0,0 +1,19 @@ +project + : requirements + gcc:-xc++ + msvc:"/TP" + ; + +exe test_relationals + : main.c + test_comparisons_double.cpp + test_comparisons_float.cpp + test_relationals.cpp + test_shuffles.cpp + ; + +install dist + : test_relationals + : debug:$(DIST)/debug/tests/test_conformance/relationals + release:$(DIST)/release/tests/test_conformance/relationals + ; diff --git a/test_conformance/relationals/Makefile b/test_conformance/relationals/Makefile new file mode 100644 index 00000000..99406dc8 --- /dev/null +++ b/test_conformance/relationals/Makefile @@ -0,0 +1,46 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.c \ + test_relationals.cpp \ + test_shuffles.cpp \ + test_comparisons_double.cpp \ + test_comparisons_float.cpp \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/threadTesting.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/kernelHelpers.c \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/conversions.c + +DEFINES = + +SOURCES = $(abspath $(SRCS)) +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = $(SOURCES) +HEADERS = +TARGET = test_relationals +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE) +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/relationals/main.c b/test_conformance/relationals/main.c new file mode 100644 index 00000000..0b90fac8 --- /dev/null +++ b/test_conformance/relationals/main.c @@ -0,0 +1,100 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include "procs.h" +#include "../../test_common/harness/testHarness.h" + +#if !defined(_WIN32) +#include +#endif + +#if DENSE_PACK_VECS +const int g_vector_aligns[] = {0, 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16}; + +#else +const int g_vector_aligns[] = {0, 1, 2, 4, 4, + 8, 8, 8, 8, + 16, 16, 16, 16, + 16, 16, 16, 16}; +#endif + + +const int g_vector_allocs[] = {0, 1, 2, 4, 4, + 8, 8, 8, 8, + 16, 16, 16, 16, + 16, 16, 16, 16}; + + +basefn basefn_list[] = { + test_relational_any, + test_relational_all, + test_relational_bitselect, + test_relational_select_signed, + test_relational_select_unsigned, + + test_relational_isequal, + test_relational_isnotequal, + test_relational_isgreater, + test_relational_isgreaterequal, + test_relational_isless, + test_relational_islessequal, + test_relational_islessgreater, + + test_shuffle_copy, + test_shuffle_function_call, + test_shuffle_array_cast, + test_shuffle_built_in, + test_shuffle_built_in_dual_input +}; + +const char *basefn_names[] = { + "relational_any", + "relational_all", + "relational_bitselect", + "relational_select_signed", + "relational_select_unsigned", + + "relational_isequal", + "relational_isnotequal", + "relational_isgreater", + "relational_isgreaterequal", + "relational_isless", + "relational_islessequal", + "relational_islessgreater", + + "shuffle_copy", + "shuffle_function_call", + "shuffle_array_cast", + "shuffle_built_in", + "shuffle_built_in_dual_input", +}; + +ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0]))); + +int num_fns = sizeof(basefn_names) / sizeof(char *); + +int main(int argc, const char *argv[]) +{ + return runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false, false, 0 ); +} + + diff --git a/test_conformance/relationals/procs.h b/test_conformance/relationals/procs.h new file mode 100644 index 00000000..5ee78b8a --- /dev/null +++ b/test_conformance/relationals/procs.h @@ -0,0 +1,56 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/errorHelpers.h" +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/threadTesting.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/mt19937.h" + +// The number of errors to print out for each test in the shuffle tests +#define MAX_ERRORS_TO_PRINT 1 + +extern const int g_vector_aligns[]; +extern const int g_vector_allocs[]; + +#define DENSE_PACK_VECS 1 + +extern int create_program_and_kernel(const char *source, const char *kernel_name, cl_program *program_ret, cl_kernel *kernel_ret); + +extern int test_relational_any(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_relational_all(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_relational_bitselect(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_relational_select_signed(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_relational_select_unsigned(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_relational_isequal(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_relational_isnotequal(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_relational_isgreater(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_relational_isgreaterequal(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_relational_isless(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_relational_islessequal(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_relational_islessgreater(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + +extern int test_shuffles(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_shuffles_16(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_shuffles_dual(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_shuffle_copy(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_shuffle_function_call(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_shuffle_array_cast(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_shuffle_built_in(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_shuffle_built_in_dual_input(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); + + diff --git a/test_conformance/relationals/testBase.h b/test_conformance/relationals/testBase.h new file mode 100644 index 00000000..5073b21f --- /dev/null +++ b/test_conformance/relationals/testBase.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef _testBase_h +#define _testBase_h + +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include + +#include "procs.h" + +#endif // _testBase_h + + + diff --git a/test_conformance/relationals/test_comparisons_double.cpp b/test_conformance/relationals/test_comparisons_double.cpp new file mode 100644 index 00000000..21d4d575 --- /dev/null +++ b/test_conformance/relationals/test_comparisons_double.cpp @@ -0,0 +1,361 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" + +extern "C" { extern cl_uint gRandomSeed; }; + +#define TEST_SIZE 512 + +const char *equivTestKernelPattern_double = +"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" +"__kernel void sample_test(__global double%s *sourceA, __global double%s *sourceB, __global long%s *destValues, __global long%s *destValuesB)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( sourceA[tid], sourceB[tid] );\n" +" destValuesB[tid] = sourceA[tid] %s sourceB[tid];\n" +"\n" +"}\n"; + +const char *equivTestKernelPatternLessGreater_double = +"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" +"__kernel void sample_test(__global double%s *sourceA, __global double%s *sourceB, __global long%s *destValues, __global long%s *destValuesB)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( sourceA[tid], sourceB[tid] );\n" +" destValuesB[tid] = (sourceA[tid] < sourceB[tid]) | (sourceA[tid] > sourceB[tid]);\n" +"\n" +"}\n"; + + +const char *equivTestKernelPattern_double3 = +"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" +"__kernel void sample_test(__global double%s *sourceA, __global double%s *sourceB, __global long%s *destValues, __global long%s *destValuesB)\n" +"{\n" +" int tid = get_global_id(0);\n" +" double3 sampA = vload3(tid, (__global double *)sourceA);\n" +" double3 sampB = vload3(tid, (__global double *)sourceB);\n" +" vstore3(%s( sampA, sampB ), tid, (__global long *)destValues);\n" +" vstore3(( sampA %s sampB ), tid, (__global long *)destValuesB);\n" +"\n" +"}\n"; + +const char *equivTestKernelPatternLessGreater_double3 = +"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" +"__kernel void sample_test(__global double%s *sourceA, __global double%s *sourceB, __global long%s *destValues, __global long%s *destValuesB)\n" +"{\n" +" int tid = get_global_id(0);\n" +" double3 sampA = vload3(tid, (__global double *)sourceA);\n" +" double3 sampB = vload3(tid, (__global double *)sourceB);\n" +" vstore3(%s( sampA, sampB ), tid, (__global long *)destValues);\n" +" vstore3(( sampA < sampB ) | (sampA > sampB), tid, (__global long *)destValuesB);\n" +"\n" +"}\n"; + + +typedef bool (*equivVerifyFn)( double inDataA, double inDataB ); + +void verify_equiv_values_double( unsigned int vecSize, double *inDataA, double *inDataB, cl_long *outData, equivVerifyFn verifyFn ) +{ + unsigned int i; + cl_long trueResult; + bool result; + + trueResult = ( vecSize == 1 ) ? 1 : -1; + for( i = 0; i < vecSize; i++ ) + { + result = verifyFn( inDataA[ i ], inDataB[ i ] ); + outData[ i ] = result ? trueResult : 0; + } +} + +void generate_equiv_test_data_double( double *outData, unsigned int vecSize, bool alpha, MTdata d ) +{ + unsigned int i; + + generate_random_data( kDouble, vecSize * TEST_SIZE, d, outData ); + + // Fill the first few vectors with NAN in each vector element (or the second set if we're alpha, so we can test either case) + if( alpha ) + outData += vecSize * vecSize; + for( i = 0; i < vecSize; i++ ) + { + outData[ 0 ] = NAN; + outData += vecSize + 1; + } + // Make sure the third set is filled regardless, to test the case where both have NANs + if( !alpha ) + outData += vecSize * vecSize; + for( i = 0; i < vecSize; i++ ) + { + outData[ 0 ] = NAN; + outData += vecSize + 1; + } +} + +int test_equiv_kernel_double(cl_context context, cl_command_queue queue, const char *fnName, const char *opName, + unsigned int vecSize, equivVerifyFn verifyFn, MTdata d ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[4]; + double inDataA[TEST_SIZE * 16], inDataB[ TEST_SIZE * 16 ]; + cl_long outData[TEST_SIZE * 16], expected[16]; + int error, i, j; + size_t threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + char sizeName[4]; + + + /* Create the source */ + if( vecSize == 1 ) + sizeName[ 0 ] = 0; + else + sprintf( sizeName, "%d", vecSize ); + + if(DENSE_PACK_VECS && vecSize == 3) { + if (strcmp(fnName, "islessgreater")) { + sprintf( kernelSource, equivTestKernelPattern_double3, sizeName, sizeName, sizeName, sizeName, fnName, opName ); + } else { + sprintf( kernelSource, equivTestKernelPatternLessGreater_double3, sizeName, sizeName, sizeName, sizeName, fnName ); + } + } else { + if (strcmp(fnName, "islessgreater")) { + sprintf( kernelSource, equivTestKernelPattern_double, sizeName, sizeName, sizeName, sizeName, fnName, opName ); + } else { + sprintf( kernelSource, equivTestKernelPatternLessGreater_double, sizeName, sizeName, sizeName, sizeName, fnName ); + } + } + + /* Create kernels */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + { + return -1; + } + + /* Generate some streams */ + generate_equiv_test_data_double( inDataA, vecSize, true, d ); + generate_equiv_test_data_double( inDataB, vecSize, false, d ); + + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof( cl_double ) * vecSize * TEST_SIZE, &inDataA, &error); + if( streams[0] == NULL ) + { + print_error( error, "Creating input array A failed!\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof( cl_double ) * vecSize * TEST_SIZE, &inDataB, &error); + if( streams[1] == NULL ) + { + print_error( error, "Creating input array A failed!\n"); + return -1; + } + streams[2] = clCreateBuffer( context, CL_MEM_READ_WRITE, sizeof( cl_long ) * vecSize * TEST_SIZE, NULL, &error); + if( streams[2] == NULL ) + { + print_error( error, "Creating output array failed!\n"); + return -1; + } + streams[3] = clCreateBuffer( context, CL_MEM_READ_WRITE, sizeof( cl_long ) * vecSize * TEST_SIZE, NULL, &error); + if( streams[3] == NULL ) + { + print_error( error, "Creating output array failed!\n"); + return -1; + } + + + /* Assign streams and execute */ + error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 2, sizeof( streams[2] ), &streams[2] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 3, sizeof( streams[3] ), &streams[3] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + + /* Run the kernel */ + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[2], true, 0, sizeof( cl_long ) * TEST_SIZE * vecSize, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + /* And verify! */ + for( i = 0; i < TEST_SIZE; i++ ) + { + verify_equiv_values_double( vecSize, &inDataA[ i * vecSize ], &inDataB[ i * vecSize ], expected, verifyFn); + + for( j = 0; j < (int)vecSize; j++ ) + { + if( expected[ j ] != outData[ i * vecSize + j ] ) + { + log_error( "ERROR: Data sample %d:%d at size %d does not validate! Expected %lld, got %lld, source %f,%f\n", + i, j, vecSize, expected[ j ], outData[ i * vecSize + j ], inDataA[i*vecSize + j], inDataB[i*vecSize + j] ); + return -1; + } + } + } + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[3], true, 0, sizeof( cl_long ) * TEST_SIZE * vecSize, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + /* And verify! */ + for( i = 0; i < TEST_SIZE; i++ ) + { + verify_equiv_values_double( vecSize, &inDataA[ i * vecSize ], &inDataB[ i * vecSize ], expected, verifyFn); + + for( j = 0; j < (int)vecSize; j++ ) + { + if( expected[ j ] != outData[ i * vecSize + j ] ) + { + log_error( "ERROR: Data sample %d:%d at size %d does not validate! Expected %lld, got %lld, source %f,%f\n", + i, j, vecSize, expected[ j ], outData[ i * vecSize + j ], inDataA[i*vecSize + j], inDataB[i*vecSize + j] ); + return -1; + } + } + } + + return 0; +} + +int test_equiv_kernel_set_double(cl_device_id device, cl_context context, cl_command_queue queue, const char *fnName, const char *opName, equivVerifyFn verifyFn, MTdata d ) +{ + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 }; + unsigned int index; + int retVal = 0; + + if (!is_extension_available(device, "cl_khr_fp64")) { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + return 0; + } + log_info("Testing doubles.\n"); + + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + // Test! + if( test_equiv_kernel_double(context, queue, fnName, opName, vecSizes[ index ], verifyFn, d ) != 0 ) + { + log_error( " Vector double%d FAILED\n", vecSizes[ index ] ); + retVal = -1; + } + } + + return retVal; +} + +bool isequal_verify_fn_double( double valueA, double valueB ) +{ + if( isnan( valueA ) || isnan( valueB ) ) + return false; + return valueA == valueB; +} + +int test_relational_isequal_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + RandomSeed seed(gRandomSeed); + return test_equiv_kernel_set_double( device, context, queue, "isequal", "==", isequal_verify_fn_double, seed ); +} + +bool isnotequal_verify_fn_double( double valueA, double valueB ) +{ + if( isnan( valueA ) || isnan( valueB ) ) + return true; + return valueA != valueB; +} + +int test_relational_isnotequal_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + RandomSeed seed(gRandomSeed); + return test_equiv_kernel_set_double( device, context, queue, "isnotequal", "!=", isnotequal_verify_fn_double, seed ); +} + +bool isgreater_verify_fn_double( double valueA, double valueB ) +{ + if( isnan( valueA ) || isnan( valueB ) ) + return false; + return valueA > valueB; +} + +int test_relational_isgreater_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + RandomSeed seed(gRandomSeed); + return test_equiv_kernel_set_double( device, context, queue, "isgreater", ">", isgreater_verify_fn_double, seed ); +} + +bool isgreaterequal_verify_fn_double( double valueA, double valueB ) +{ + if( isnan( valueA ) || isnan( valueB ) ) + return false; + return valueA >= valueB; +} + +int test_relational_isgreaterequal_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + RandomSeed seed(gRandomSeed); + return test_equiv_kernel_set_double( device, context, queue, "isgreaterequal", ">=", isgreaterequal_verify_fn_double, seed ); +} + +bool isless_verify_fn_double( double valueA, double valueB ) +{ + if( isnan( valueA ) || isnan( valueB ) ) + return false; + return valueA < valueB; +} + +int test_relational_isless_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + RandomSeed seed(gRandomSeed); + return test_equiv_kernel_set_double( device, context, queue, "isless", "<", isless_verify_fn_double, seed ); +} + +bool islessequal_verify_fn_double( double valueA, double valueB ) +{ + if( isnan( valueA ) || isnan( valueB ) ) + return false; + return valueA <= valueB; +} + +int test_relational_islessequal_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + RandomSeed seed(gRandomSeed); + return test_equiv_kernel_set_double( device, context, queue, "islessequal", "<=", islessequal_verify_fn_double, seed ); +} + +bool islessgreater_verify_fn_double( double valueA, double valueB ) +{ + if( isnan( valueA ) || isnan( valueB ) ) + return false; + return ( valueA < valueB ) || ( valueA > valueB ); +} + +int test_relational_islessgreater_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + RandomSeed seed(gRandomSeed); + return test_equiv_kernel_set_double( device, context, queue, "islessgreater", "<>", islessgreater_verify_fn_double, seed ); +} + + diff --git a/test_conformance/relationals/test_comparisons_float.cpp b/test_conformance/relationals/test_comparisons_float.cpp new file mode 100644 index 00000000..76b31989 --- /dev/null +++ b/test_conformance/relationals/test_comparisons_float.cpp @@ -0,0 +1,361 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" + +extern "C" { extern cl_uint gRandomSeed;}; + +#define TEST_SIZE 512 + +const char *equivTestKernelPattern_float = +"__kernel void sample_test(__global float%s *sourceA, __global float%s *sourceB, __global int%s *destValues, __global int%s *destValuesB)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( sourceA[tid], sourceB[tid] );\n" +" destValuesB[tid] = sourceA[tid] %s sourceB[tid];\n" +"\n" +"}\n"; + +const char *equivTestKernelPatternLessGreater_float = +"__kernel void sample_test(__global float%s *sourceA, __global float%s *sourceB, __global int%s *destValues, __global int%s *destValuesB)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( sourceA[tid], sourceB[tid] );\n" +" destValuesB[tid] = (sourceA[tid] < sourceB[tid]) | (sourceA[tid] > sourceB[tid]);\n" +"\n" +"}\n"; + + +const char *equivTestKernelPattern_float3 = +"__kernel void sample_test(__global float%s *sourceA, __global float%s *sourceB, __global int%s *destValues, __global int%s *destValuesB)\n" +"{\n" +" int tid = get_global_id(0);\n" +" float3 sampA = vload3(tid, (__global float *)sourceA);\n" +" float3 sampB = vload3(tid, (__global float *)sourceB);\n" +" vstore3(%s( sampA, sampB ), tid, (__global int *)destValues);\n" +" vstore3(( sampA %s sampB ), tid, (__global int *)destValuesB);\n" +"\n" +"}\n"; + +const char *equivTestKernelPatternLessGreater_float3 = +"__kernel void sample_test(__global float%s *sourceA, __global float%s *sourceB, __global int%s *destValues, __global int%s *destValuesB)\n" +"{\n" +" int tid = get_global_id(0);\n" +" float3 sampA = vload3(tid, (__global float *)sourceA);\n" +" float3 sampB = vload3(tid, (__global float *)sourceB);\n" +" vstore3(%s( sampA, sampB ), tid, (__global int *)destValues);\n" +" vstore3(( sampA < sampB ) | (sampA > sampB), tid, (__global int *)destValuesB);\n" +"\n" +"}\n"; + +typedef bool (*equivVerifyFn)( float inDataA, float inDataB ); +extern "C" { extern int gInfNanSupport; }; + +int IsFloatInfinity(float x) +{ + return isinf(x); +} + +int IsFloatNaN(float x) +{ + return isnan(x); +} + +void verify_equiv_values_float( unsigned int vecSize, float *inDataA, float *inDataB, int *outData, equivVerifyFn verifyFn ) +{ + unsigned int i; + int trueResult; + bool result; + + trueResult = ( vecSize == 1 ) ? 1 : -1; + for( i = 0; i < vecSize; i++ ) + { + result = verifyFn( inDataA[ i ], inDataB[ i ] ); + outData[ i ] = result ? trueResult : 0; + } +} + +void generate_equiv_test_data_float( float *outData, unsigned int vecSize, bool alpha, MTdata d ) +{ + unsigned int i; + + generate_random_data( kFloat, vecSize * TEST_SIZE, d, outData ); + + // Fill the first few vectors with NAN in each vector element (or the second set if we're alpha, so we can test either case) + if( alpha ) + outData += vecSize * vecSize; + for( i = 0; i < vecSize; i++ ) + { + outData[ 0 ] = NAN; + outData += vecSize + 1; + } + // Make sure the third set is filled regardless, to test the case where both have NANs + if( !alpha ) + outData += vecSize * vecSize; + for( i = 0; i < vecSize; i++ ) + { + outData[ 0 ] = NAN; + outData += vecSize + 1; + } +} + +int test_equiv_kernel_float(cl_context context, cl_command_queue queue, const char *fnName, const char *opName, + unsigned int vecSize, equivVerifyFn verifyFn, MTdata d ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[4]; + float inDataA[TEST_SIZE * 16], inDataB[ TEST_SIZE * 16 ]; + int outData[TEST_SIZE * 16], expected[16]; + int error, i, j; + size_t threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + char sizeName[4]; + + + /* Create the source */ + if( vecSize == 1 ) + sizeName[ 0 ] = 0; + else + sprintf( sizeName, "%d", vecSize ); + + + if(DENSE_PACK_VECS && vecSize == 3) { + if (strcmp(fnName, "islessgreater")) { + sprintf( kernelSource, equivTestKernelPattern_float3, sizeName, sizeName, sizeName, sizeName, fnName, opName ); + } else { + sprintf( kernelSource, equivTestKernelPatternLessGreater_float3, sizeName, sizeName, sizeName, sizeName, fnName ); + } + } else { + if (strcmp(fnName, "islessgreater")) { + sprintf( kernelSource, equivTestKernelPattern_float, sizeName, sizeName, sizeName, sizeName, fnName, opName ); + } else { + sprintf( kernelSource, equivTestKernelPatternLessGreater_float, sizeName, sizeName, sizeName, sizeName, fnName ); + } + } + + /* Create kernels */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + { + return -1; + } + + /* Generate some streams */ + generate_equiv_test_data_float( inDataA, vecSize, true, d ); + generate_equiv_test_data_float( inDataB, vecSize, false, d ); + + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof( cl_float ) * vecSize * TEST_SIZE, &inDataA, &error); + if( streams[0] == NULL ) + { + print_error( error, "Creating input array A failed!\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof( cl_float ) * vecSize * TEST_SIZE, &inDataB, &error); + if( streams[1] == NULL ) + { + print_error( error, "Creating input array A failed!\n"); + return -1; + } + streams[2] = clCreateBuffer( context, CL_MEM_READ_WRITE, sizeof( cl_int ) * vecSize * TEST_SIZE, NULL, &error); + if( streams[2] == NULL ) + { + print_error( error, "Creating output array failed!\n"); + return -1; + } + streams[3] = clCreateBuffer( context, CL_MEM_READ_WRITE, sizeof( cl_int ) * vecSize * TEST_SIZE, NULL, &error); + if( streams[3] == NULL ) + { + print_error( error, "Creating output array failed!\n"); + return -1; + } + + + /* Assign streams and execute */ + error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 2, sizeof( streams[2] ), &streams[2] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 3, sizeof( streams[3] ), &streams[3] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + + /* Run the kernel */ + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[2], true, 0, sizeof( int ) * TEST_SIZE * vecSize, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + /* And verify! */ + for( i = 0; i < TEST_SIZE; i++ ) + { + verify_equiv_values_float( vecSize, &inDataA[ i * vecSize ], &inDataB[ i * vecSize ], expected, verifyFn); + + for( j = 0; j < (int)vecSize; j++ ) + { + if( expected[ j ] != outData[ i * vecSize + j ] ) + { + log_error( "ERROR: Data sample %d:%d at size %d does not validate! Expected %d, got %d, source %f,%f\n", + i, j, vecSize, expected[ j ], outData[ i * vecSize + j ], inDataA[i*vecSize + j], inDataB[i*vecSize + j] ); + return -1; + } + } + } + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[3], true, 0, sizeof( int ) * TEST_SIZE * vecSize, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + /* And verify! */ + int fail = 0; + for( i = 0; i < TEST_SIZE; i++ ) + { + verify_equiv_values_float( vecSize, &inDataA[ i * vecSize ], &inDataB[ i * vecSize ], expected, verifyFn); + + for( j = 0; j < (int)vecSize; j++ ) + { + if( expected[ j ] != outData[ i * vecSize + j ] ) + { + if (gInfNanSupport == 0) + { + if (IsFloatNaN(inDataA[i*vecSize + j]) || IsFloatNaN (inDataB[i*vecSize + j])) + { + fail = 0; + } + else + fail = 1; + } + if (fail) + { + log_error( "ERROR: Data sample %d:%d at size %d does not validate! Expected %d, got %d, source %f,%f\n", + i, j, vecSize, expected[ j ], outData[ i * vecSize + j ], inDataA[i*vecSize + j], inDataB[i*vecSize + j] ); + return -1; + } + } + } + } + + return 0; +} + +int test_equiv_kernel_set_float(cl_context context, cl_command_queue queue, const char *fnName, const char *opName, equivVerifyFn verifyFn, MTdata d ) +{ + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 }; + unsigned int index; + int retVal = 0; + + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + // Test! + if( test_equiv_kernel_float(context, queue, fnName, opName, vecSizes[ index ], verifyFn, d ) != 0 ) + { + log_error( " Vector float%d FAILED\n", vecSizes[ index ] ); + retVal = -1; + } + } + + return retVal; +} + +bool isequal_verify_fn_float( float valueA, float valueB ) +{ + return valueA == valueB; +} + +int test_relational_isequal_float(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + RandomSeed seed( gRandomSeed ); + return test_equiv_kernel_set_float( context, queue, "isequal", "==", isequal_verify_fn_float, seed ); +} + +bool isnotequal_verify_fn_float( float valueA, float valueB ) +{ + return valueA != valueB; +} + +int test_relational_isnotequal_float(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + RandomSeed seed( gRandomSeed ); + return test_equiv_kernel_set_float( context, queue, "isnotequal", "!=", isnotequal_verify_fn_float, seed ); +} + +bool isgreater_verify_fn_float( float valueA, float valueB ) +{ + return valueA > valueB; +} + +int test_relational_isgreater_float(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + RandomSeed seed( gRandomSeed ); + return test_equiv_kernel_set_float( context, queue, "isgreater", ">", isgreater_verify_fn_float, seed ); +} + +bool isgreaterequal_verify_fn_float( float valueA, float valueB ) +{ + return valueA >= valueB; +} + +int test_relational_isgreaterequal_float(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + RandomSeed seed( gRandomSeed ); + return test_equiv_kernel_set_float( context, queue, "isgreaterequal", ">=", isgreaterequal_verify_fn_float, seed ); +} + +bool isless_verify_fn_float( float valueA, float valueB ) +{ + return valueA < valueB; +} + +int test_relational_isless_float(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + RandomSeed seed( gRandomSeed ); + return test_equiv_kernel_set_float( context, queue, "isless", "<", isless_verify_fn_float, seed ); +} + +bool islessequal_verify_fn_float( float valueA, float valueB ) +{ + return valueA <= valueB; +} + +int test_relational_islessequal_float(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + RandomSeed seed( gRandomSeed ); + return test_equiv_kernel_set_float( context, queue, "islessequal", "<=", islessequal_verify_fn_float, seed ); +} + +bool islessgreater_verify_fn_float( float valueA, float valueB ) +{ + return ( valueA < valueB ) || ( valueA > valueB ); +} + +int test_relational_islessgreater_float(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + RandomSeed seed( gRandomSeed ); + return test_equiv_kernel_set_float( context, queue, "islessgreater", "<>", islessgreater_verify_fn_float, seed ); +} + + diff --git a/test_conformance/relationals/test_relationals.cpp b/test_conformance/relationals/test_relationals.cpp new file mode 100644 index 00000000..9542b851 --- /dev/null +++ b/test_conformance/relationals/test_relationals.cpp @@ -0,0 +1,785 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/testHarness.h" + +const char *anyAllTestKernelPattern = +"%s\n" // optional pragma +"__kernel void sample_test(__global %s%s *sourceA, __global int *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( sourceA[tid] );\n" +"\n" +"}\n"; + +const char *anyAllTestKernelPatternVload = +"%s\n" // optional pragma +"__kernel void sample_test(__global %s%s *sourceA, __global int *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s(vload3(tid, (__global %s *)sourceA));\n" // ugh, almost +"\n" +"}\n"; + +#define TEST_SIZE 512 + +extern "C" {extern cl_uint gRandomSeed;}; + +typedef int (*anyAllVerifyFn)( ExplicitType vecType, unsigned int vecSize, void *inData ); + +int test_any_all_kernel(cl_context context, cl_command_queue queue, + const char *fnName, ExplicitType vecType, + unsigned int vecSize, anyAllVerifyFn verifyFn, + MTdata d ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[2]; + cl_long inDataA[TEST_SIZE * 16], clearData[TEST_SIZE * 16]; + int outData[TEST_SIZE]; + int error, i; + size_t threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + char sizeName[4]; + + + /* Create the source */ + if( g_vector_aligns[vecSize] == 1 ) { + sizeName[ 0 ] = 0; + } else { + sprintf( sizeName, "%d", vecSize ); + } + log_info("Testing any/all on %s%s\n", + get_explicit_type_name( vecType ), sizeName); + if(DENSE_PACK_VECS && vecSize == 3) { + // anyAllTestKernelPatternVload + sprintf( kernelSource, anyAllTestKernelPatternVload, + vecType == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name( vecType ), sizeName, fnName, + get_explicit_type_name(vecType)); + } else { + sprintf( kernelSource, anyAllTestKernelPattern, + vecType == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name( vecType ), sizeName, fnName ); + } + /* Create kernels */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, + (const char **)&programPtr, + "sample_test" ) ) + { + return -1; + } + + /* Generate some streams */ + generate_random_data( vecType, TEST_SIZE * g_vector_aligns[vecSize], d, inDataA ); + memset( clearData, 0, sizeof( clearData ) ); + + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), get_explicit_type_size( vecType ) * g_vector_aligns[vecSize] * TEST_SIZE, &inDataA, &error); + if( streams[0] == NULL ) + { + print_error( error, "Creating input array A failed!\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_int) * g_vector_aligns[vecSize] * TEST_SIZE, clearData, &error ); + if( streams[1] == NULL ) + { + print_error( error, "Creating output array failed!\n"); + return -1; + } + + /* Assign streams and execute */ + error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + /* Run the kernel */ + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[1], true, 0, sizeof( int ) * TEST_SIZE, outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + /* And verify! */ + for( i = 0; i < TEST_SIZE; i++ ) + { + int expected = verifyFn( vecType, vecSize, (char *)inDataA + i * get_explicit_type_size( vecType ) * g_vector_aligns[vecSize] ); + if( expected != outData[ i ] ) + { + unsigned int *ptr = (unsigned int *)( (char *)inDataA + i * get_explicit_type_size( vecType ) * g_vector_aligns[vecSize] ); + log_error( "ERROR: Data sample %d does not validate! Expected (%d), got (%d), source 0x%08x\n", + i, expected, outData[i], *ptr ); + return -1; + } + } + + return 0; +} + +int anyVerifyFn( ExplicitType vecType, unsigned int vecSize, void *inData ) +{ + unsigned int i; + switch( vecType ) + { + case kChar: + { + char sum = 0; + char *tData = (char *)inData; + for( i = 0; i < vecSize; i++ ) + sum |= tData[ i ] & 0x80; + return (sum != 0) ? 1 : 0; + } + case kShort: + { + short sum = 0; + short *tData = (short *)inData; + for( i = 0; i < vecSize; i++ ) + sum |= tData[ i ] & 0x8000; + return (sum != 0); + } + case kInt: + { + cl_int sum = 0; + cl_int *tData = (cl_int *)inData; + for( i = 0; i < vecSize; i++ ) + sum |= tData[ i ] & (cl_int)0x80000000L; + return (sum != 0); + } + case kLong: + { + cl_long sum = 0; + cl_long *tData = (cl_long *)inData; + for( i = 0; i < vecSize; i++ ) + sum |= tData[ i ] & 0x8000000000000000LL; + return (sum != 0); + } + default: + return 0; + } +} + +int test_relational_any(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + ExplicitType vecType[] = { kChar, kShort, kInt, kLong }; + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 }; + unsigned int index, typeIndex; + int retVal = 0; + RandomSeed seed(gRandomSeed ); + + for( typeIndex = 0; typeIndex < 4; typeIndex++ ) + { + if (vecType[typeIndex] == kLong && !gHasLong) + continue; + + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + // Test! + if( test_any_all_kernel(context, queue, "any", vecType[ typeIndex ], vecSizes[ index ], anyVerifyFn, seed ) != 0 ) + { + log_error( " Vector %s%d FAILED\n", get_explicit_type_name( vecType[ typeIndex ] ), vecSizes[ index ] ); + retVal = -1; + } + } + } + + return retVal; +} + +int allVerifyFn( ExplicitType vecType, unsigned int vecSize, void *inData ) +{ + unsigned int i; + switch( vecType ) + { + case kChar: + { + char sum = 0x80; + char *tData = (char *)inData; + for( i = 0; i < vecSize; i++ ) + sum &= tData[ i ] & 0x80; + return (sum != 0) ? 1 : 0; + } + case kShort: + { + short sum = 0x8000; + short *tData = (short *)inData; + for( i = 0; i < vecSize; i++ ) + sum &= tData[ i ] & 0x8000; + return (sum != 0); + } + case kInt: + { + cl_int sum = 0x80000000L; + cl_int *tData = (cl_int *)inData; + for( i = 0; i < vecSize; i++ ) + sum &= tData[ i ] & (cl_int)0x80000000L; + return (sum != 0); + } + case kLong: + { + cl_long sum = 0x8000000000000000LL; + cl_long *tData = (cl_long *)inData; + for( i = 0; i < vecSize; i++ ) + sum &= tData[ i ] & 0x8000000000000000LL; + return (sum != 0); + } + default: + return 0; + } +} + +int test_relational_all(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + ExplicitType vecType[] = { kChar, kShort, kInt, kLong }; + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 }; + unsigned int index, typeIndex; + int retVal = 0; + RandomSeed seed(gRandomSeed ); + + + for( typeIndex = 0; typeIndex < 4; typeIndex++ ) + { + if (vecType[typeIndex] == kLong && !gHasLong) + continue; + + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + // Test! + if( test_any_all_kernel(context, queue, "all", vecType[ typeIndex ], vecSizes[ index ], allVerifyFn, seed ) != 0 ) + { + log_error( " Vector %s%d FAILED\n", get_explicit_type_name( vecType[ typeIndex ] ), vecSizes[ index ] ); + retVal = -1; + } + } + } + + return retVal; +} + +const char *selectTestKernelPattern = +"%s\n" // optional pragma +"__kernel void sample_test(__global %s%s *sourceA, __global %s%s *sourceB, __global %s%s *sourceC, __global %s%s *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" destValues[tid] = %s( sourceA[tid], sourceB[tid], sourceC[tid] );\n" +"\n" +"}\n"; + + +const char *selectTestKernelPatternVload = +"%s\n" // optional pragma +"__kernel void sample_test(__global %s%s *sourceA, __global %s%s *sourceB, __global %s%s *sourceC, __global %s%s *destValues)\n" +"{\n" +" int tid = get_global_id(0);\n" +" %s%s tmp = %s( vload3(tid, (__global %s *)sourceA), vload3(tid, (__global %s *)sourceB), vload3(tid, (__global %s *)sourceC) );\n" +" vstore3(tmp, tid, (__global %s *)destValues);\n" +"\n" +"}\n"; + +typedef void (*selectVerifyFn)( ExplicitType vecType, ExplicitType testVecType, unsigned int vecSize, void *inDataA, void *inDataB, void *inDataTest, void *outData ); + +int test_select_kernel(cl_context context, cl_command_queue queue, const char *fnName, + ExplicitType vecType, unsigned int vecSize, ExplicitType testVecType, selectVerifyFn verifyFn, MTdata d ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + clMemWrapper streams[4]; + cl_long inDataA[TEST_SIZE * 16], inDataB[ TEST_SIZE * 16 ], inDataC[ TEST_SIZE * 16 ]; + cl_long outData[TEST_SIZE * 16], expected[16]; + int error, i; + size_t threads[1], localThreads[1]; + char kernelSource[10240]; + char *programPtr; + char sizeName[4], outSizeName[4]; + unsigned int outVecSize; + + + /* Create the source */ + if( vecSize == 1 ) + sizeName[ 0 ] = 0; + else + sprintf( sizeName, "%d", vecSize ); + + outVecSize = vecSize; + + if( outVecSize == 1 ) + outSizeName[ 0 ] = 0; + else + sprintf( outSizeName, "%d", outVecSize ); + + if(DENSE_PACK_VECS && vecSize == 3) { + // anyAllTestKernelPatternVload + sprintf( kernelSource, selectTestKernelPatternVload, + (vecType == kDouble || testVecType == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name( vecType ), sizeName, + get_explicit_type_name( vecType ), sizeName, + get_explicit_type_name( testVecType ), sizeName, + get_explicit_type_name( vecType ), outSizeName, + get_explicit_type_name( vecType ), sizeName, + fnName, + get_explicit_type_name( vecType ), + get_explicit_type_name( vecType ), + get_explicit_type_name( vecType ), + get_explicit_type_name( testVecType ) ); + } else { + sprintf( kernelSource, selectTestKernelPattern, + (vecType == kDouble || testVecType == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "", + get_explicit_type_name( vecType ), sizeName, + get_explicit_type_name( vecType ), sizeName, + get_explicit_type_name( testVecType ), sizeName, + get_explicit_type_name( vecType ), outSizeName, + fnName ); + } + + /* Create kernels */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) ) + { + return -1; + } + + /* Generate some streams */ + generate_random_data( vecType, TEST_SIZE * g_vector_aligns[vecSize], d, inDataA ); + generate_random_data( vecType, TEST_SIZE * g_vector_aligns[vecSize], d, inDataB ); + generate_random_data( testVecType, TEST_SIZE * g_vector_aligns[vecSize], d, inDataC ); + + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), get_explicit_type_size( vecType ) * g_vector_aligns[vecSize] * TEST_SIZE, &inDataA, &error); + if( streams[0] == NULL ) + { + print_error( error, "Creating input array A failed!\n"); + return -1; + } + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), get_explicit_type_size( vecType ) * g_vector_aligns[vecSize] * TEST_SIZE, &inDataB, &error); + if( streams[1] == NULL ) + { + print_error( error, "Creating input array A failed!\n"); + return -1; + } + streams[2] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), get_explicit_type_size( testVecType ) * g_vector_aligns[vecSize] * TEST_SIZE, &inDataC, &error); + if( streams[2] == NULL ) + { + print_error( error, "Creating input array A failed!\n"); + return -1; + } + streams[3] = clCreateBuffer( context, CL_MEM_READ_WRITE, get_explicit_type_size( vecType ) * g_vector_aligns[outVecSize] * TEST_SIZE, NULL, &error); + if( streams[3] == NULL ) + { + print_error( error, "Creating output array failed!\n"); + return -1; + } + + /* Assign streams and execute */ + error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 1, sizeof( streams[1] ), &streams[1] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 2, sizeof( streams[2] ), &streams[2] ); + test_error( error, "Unable to set indexed kernel arguments" ); + error = clSetKernelArg( kernel, 3, sizeof( streams[3] ), &streams[3] ); + test_error( error, "Unable to set indexed kernel arguments" ); + + /* Run the kernel */ + threads[0] = TEST_SIZE; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + /* Now get the results */ + error = clEnqueueReadBuffer( queue, streams[3], true, 0, get_explicit_type_size( vecType ) * TEST_SIZE * g_vector_aligns[outVecSize], outData, 0, NULL, NULL ); + test_error( error, "Unable to read output array!" ); + + /* And verify! */ + for( i = 0; i < (int)(TEST_SIZE * g_vector_aligns[vecSize]); i++ ) + { + if(i%g_vector_aligns[vecSize] >= (int) vecSize) { + continue; + } + verifyFn( vecType, testVecType, vecSize, (char *)inDataA + i * get_explicit_type_size( vecType ), + (char *)inDataB + i * get_explicit_type_size( vecType ), + (char *)inDataC + i * get_explicit_type_size( testVecType ), + expected); + + char *outPtr = (char *)outData; + outPtr += ( i / g_vector_aligns[vecSize] ) * get_explicit_type_size( vecType ) * g_vector_aligns[outVecSize]; + outPtr += ( i % g_vector_aligns[vecSize] ) * get_explicit_type_size( vecType ); + if( memcmp( expected, outPtr, get_explicit_type_size( vecType ) ) != 0 ) + { + log_error( "ERROR: Data sample %d:%d does not validate! Expected (0x%08x), got (0x%08x) from (0x%08x) and (0x%08x) with test (0x%08x)\n", + i / g_vector_aligns[vecSize], + i % g_vector_aligns[vecSize], + *( (int *)expected ), + *( (int *)( (char *)outData + + i * get_explicit_type_size( vecType + ) ) ), + *( (int *)( (char *)inDataA + + i * get_explicit_type_size( vecType + ) ) ), + *( (int *)( (char *)inDataB + + i * get_explicit_type_size( vecType + ) ) ), + *( (int *)( (char *)inDataC + + i*get_explicit_type_size( testVecType + ) ) ) ); + int j; + log_error( "inA: " ); + unsigned char *a = (unsigned char *)( (char *)inDataA + i * get_explicit_type_size( vecType ) ); + unsigned char *b = (unsigned char *)( (char *)inDataB + i * get_explicit_type_size( vecType ) ); + unsigned char *c = (unsigned char *)( (char *)inDataC + i * get_explicit_type_size( testVecType ) ); + unsigned char *e = (unsigned char *)( expected ); + unsigned char *g = (unsigned char *)( (char *)outData + i * get_explicit_type_size( vecType ) ); + for( j = 0; j < 16; j++ ) + log_error( "0x%02x ", a[ j ] ); + log_error( "\ninB: " ); + for( j = 0; j < 16; j++ ) + log_error( "0x%02x ", b[ j ] ); + log_error( "\ninC: " ); + for( j = 0; j < 16; j++ ) + log_error( "0x%02x ", c[ j ] ); + log_error( "\nexp: " ); + for( j = 0; j < 16; j++ ) + log_error( "0x%02x ", e[ j ] ); + log_error( "\ngot: " ); + for( j = 0; j < 16; j++ ) + log_error( "0x%02x ", g[ j ] ); + return -1; + } + } + + return 0; +} + +void bitselect_verify_fn( ExplicitType vecType, ExplicitType testVecType, unsigned int vecSize, void *inDataA, void *inDataB, void *inDataTest, void *outData ) +{ + char *inA = (char *)inDataA, *inB = (char *)inDataB, *inT = (char *)inDataTest, *out = (char *)outData; + size_t i, numBytes = get_explicit_type_size( vecType ); + + // Type is meaningless, this is all bitwise! + for( i = 0; i < numBytes; i++ ) + { + out[ i ] = ( inA[ i ] & ~inT[ i ] ) | ( inB[ i ] & inT[ i ] ); + } +} + +int test_relational_bitselect(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble }; + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 }; + unsigned int index, typeIndex; + int retVal = 0; + RandomSeed seed( gRandomSeed ); + + + for( typeIndex = 0; typeIndex < 10; typeIndex++ ) + { + if ((vecType[typeIndex] == kLong || vecType[typeIndex] == kULong) && !gHasLong) + continue; + + if (vecType[typeIndex] == kDouble) + { + if(!is_extension_available(device, "cl_khr_fp64")) + { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + continue; + } + else + log_info("Testing doubles.\n"); + } + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + // Test! + if( test_select_kernel(context, queue, "bitselect", vecType[ typeIndex ], vecSizes[ index ], vecType[typeIndex], bitselect_verify_fn, seed ) != 0 ) + { + log_error( " Vector %s%d FAILED\n", get_explicit_type_name( vecType[ typeIndex ] ), vecSizes[ index ] ); + retVal = -1; + } + } + } + + return retVal; +} + +void select_signed_verify_fn( ExplicitType vecType, ExplicitType testVecType, unsigned int vecSize, void *inDataA, void *inDataB, void *inDataTest, void *outData ) +{ + bool yep = false; + if (vecSize == 1) { + switch( testVecType ) + { + case kChar: + yep = *( (char *)inDataTest ) ? true : false; + break; + case kShort: + yep = *( (short *)inDataTest ) ? true : false; + break; + case kInt: + yep = *( (int *)inDataTest ) ? true : false; + break; + case kLong: + yep = *( (cl_long *)inDataTest ) ? true : false; + break; + default: + // Should never get here + return; + } + } + else { + switch( testVecType ) + { + case kChar: + yep = *( (char *)inDataTest ) & 0x80 ? true : false; + break; + case kShort: + yep = *( (short *)inDataTest ) & 0x8000 ? true : false; + break; + case kInt: + yep = *( (int *)inDataTest ) & 0x80000000L ? true : false; + break; + case kLong: + yep = *( (cl_long *)inDataTest ) & 0x8000000000000000LL ? true : false; + break; + default: + // Should never get here + return; + } + } + memcpy( outData, ( yep ) ? inDataB : inDataA, get_explicit_type_size( vecType ) ); +} + +int test_relational_select_signed(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble }; + ExplicitType testVecType[] = { kChar, kShort, kInt, kLong, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 4, 8, 16, 0 }; + unsigned int index, typeIndex, testTypeIndex; + int retVal = 0; + RandomSeed seed( gRandomSeed ); + + for( typeIndex = 0; typeIndex < 10; typeIndex++ ) + { + if ((vecType[typeIndex] == kLong || vecType[typeIndex] == kULong) && !gHasLong) + continue; + + if (vecType[typeIndex] == kDouble) { + if(!is_extension_available(device, "cl_khr_fp64")) { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + continue; + } else { + log_info("Testing doubles.\n"); + } + } + for( testTypeIndex = 0; testVecType[ testTypeIndex ] != kNumExplicitTypes; testTypeIndex++ ) + { + if( testVecType[ testTypeIndex ] != vecType[ typeIndex ] ) + continue; + + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + // Test! + if( test_select_kernel(context, queue, "select", vecType[ typeIndex ], vecSizes[ index ], testVecType[ testTypeIndex ], select_signed_verify_fn, seed ) != 0 ) + { + log_error( " Vector %s%d, test vector %s%d FAILED\n", get_explicit_type_name( vecType[ typeIndex ] ), vecSizes[ index ], + get_explicit_type_name( testVecType[ testTypeIndex ] ), vecSizes[ index ] ); + retVal = -1; + } + } + } + } + + return retVal; +} + +void select_unsigned_verify_fn( ExplicitType vecType, ExplicitType testVecType, unsigned int vecSize, void *inDataA, void *inDataB, void *inDataTest, void *outData ) +{ + bool yep = false; + if (vecSize == 1) { + switch( testVecType ) + { + case kUChar: + yep = *( (unsigned char *)inDataTest ) ? true : false; + break; + case kUShort: + yep = *( (unsigned short *)inDataTest ) ? true : false; + break; + case kUInt: + yep = *( (unsigned int *)inDataTest ) ? true : false; + break; + case kULong: + yep = *( (cl_ulong *)inDataTest ) ? true : false; + break; + default: + // Should never get here + return; + } + } + else { + switch( testVecType ) + { + case kUChar: + yep = *( (unsigned char *)inDataTest ) & 0x80 ? true : false; + break; + case kUShort: + yep = *( (unsigned short *)inDataTest ) & 0x8000 ? true : false; + break; + case kUInt: + yep = *( (unsigned int *)inDataTest ) & 0x80000000L ? true : false; + break; + case kULong: + yep = *( (cl_ulong *)inDataTest ) & 0x8000000000000000LL ? true : false; + break; + default: + // Should never get here + return; + } + } + memcpy( outData, ( yep ) ? inDataB : inDataA, get_explicit_type_size( vecType ) ); +} + +int test_relational_select_unsigned(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble }; + ExplicitType testVecType[] = { kUChar, kUShort, kUInt, kULong, kNumExplicitTypes }; + unsigned int vecSizes[] = { 1, 2, 4, 8, 16, 0 }; + unsigned int index, typeIndex, testTypeIndex; + int retVal = 0; + RandomSeed seed(gRandomSeed); + + + for( typeIndex = 0; typeIndex < 10; typeIndex++ ) + { + if ((vecType[typeIndex] == kLong || vecType[typeIndex] == kULong) && !gHasLong) + continue; + + if (vecType[typeIndex] == kDouble) { + if(!is_extension_available(device, "cl_khr_fp64")) { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + continue; + } else { + log_info("Testing doubles.\n"); + } + } + for( testTypeIndex = 0; testVecType[ testTypeIndex ] != kNumExplicitTypes; testTypeIndex++ ) + { + if( testVecType[ testTypeIndex ] != vecType[ typeIndex ] ) + continue; + + for( index = 0; vecSizes[ index ] != 0; index++ ) + { + // Test! + if( test_select_kernel(context, queue, "select", vecType[ typeIndex ], vecSizes[ index ], testVecType[ testTypeIndex ], select_unsigned_verify_fn, seed ) != 0 ) + { + log_error( " Vector %s%d, test vector %s%d FAILED\n", get_explicit_type_name( vecType[ typeIndex ] ), vecSizes[ index ], + get_explicit_type_name( testVecType[ testTypeIndex ] ), vecSizes[ index ] ); + retVal = -1; + } + } + } + } + + return retVal; +} + + + +extern int test_relational_isequal_float(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_relational_isnotequal_float(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_relational_isgreater_float(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_relational_isgreaterequal_float(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_relational_isless_float(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_relational_islessequal_float(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_relational_islessgreater_float(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_relational_isequal_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_relational_isnotequal_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_relational_isgreater_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_relational_isgreaterequal_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_relational_isless_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_relational_islessequal_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); +extern int test_relational_islessgreater_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ); + + +int test_relational_isequal(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + int err = 0; + err |= test_relational_isequal_float( device, context, queue, numElements ); + err |= test_relational_isequal_double( device, context, queue, numElements ); + return err; +} + + +int test_relational_isnotequal(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + int err = 0; + err |= test_relational_isnotequal_float( device, context, queue, numElements ); + err |= test_relational_isnotequal_double( device, context, queue, numElements ); + return err; +} + + +int test_relational_isgreater(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + int err = 0; + err |= test_relational_isgreater_float( device, context, queue, numElements ); + err |= test_relational_isgreater_double( device, context, queue, numElements ); + return err; +} + + +int test_relational_isgreaterequal(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + int err = 0; + err |= test_relational_isgreaterequal_float( device, context, queue, numElements ); + err |= test_relational_isgreaterequal_double( device, context, queue, numElements ); + return err; +} + + +int test_relational_isless(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + int err = 0; + err |= test_relational_isless_float( device, context, queue, numElements ); + err |= test_relational_isless_double( device, context, queue, numElements ); + return err; +} + + +int test_relational_islessequal(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + int err = 0; + err |= test_relational_islessequal_float( device, context, queue, numElements ); + err |= test_relational_islessequal_double( device, context, queue, numElements ); + return err; +} + + +int test_relational_islessgreater(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) +{ + int err = 0; + err |= test_relational_islessgreater_float( device, context, queue, numElements ); + err |= test_relational_islessgreater_double( device, context, queue, numElements ); + return err; +} + + diff --git a/test_conformance/relationals/test_shuffles.cpp b/test_conformance/relationals/test_shuffles.cpp new file mode 100644 index 00000000..81465fc1 --- /dev/null +++ b/test_conformance/relationals/test_shuffles.cpp @@ -0,0 +1,932 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "testBase.h" +#include "../../test_common/harness/conversions.h" +#include "../../test_common/harness/typeWrappers.h" +#include "../../test_common/harness/testHarness.h" + +// #define USE_NEW_SYNTAX 1 +// The number of shuffles to test per test +#define NUM_TESTS 32 +// The number of times to run each combination of shuffles +#define NUM_ITERATIONS_PER_TEST 2 +#define MAX_PROGRAM_SIZE NUM_TESTS*1024 +#define PRINT_SHUFFLE_KERNEL_SOURCE 0 +#define SPEW_ORDER_DETAILS 0 + +enum ShuffleMode +{ + kNormalMode = 0, + kFunctionCallMode, + kArrayAccessMode, + kBuiltInFnMode, + kBuiltInDualInputFnMode +}; + +extern "C" { extern cl_uint gRandomSeed;}; + +static const char *shuffleKernelPattern[3] = { + "__kernel void sample_test( __global %s%s *source, __global %s%s *dest )\n" + "{\n" + " if (get_global_id(0) != 0) return;\n" + " //%s%s src1 %s, src2%s;\n",// Here's a comma... + // Above code is commented out for now, but keeping around for testing local storage options + "}\n" }; + +static const char *shuffleTempPattern = " %s%s tmp;\n"; + +static const char *clearTempPattern = " tmp = (%s%s)((%s)0);\n"; + +static const char *shuffleSinglePattern = +" tmp%s%s = source[%d]%s%s;\n" +" dest[%d] = tmp;\n" +; + +static const char * shuffleSinglePatternV3src = +" tmp%s%s = vload3(%d, source)%s%s;\n" +" dest[%d] = tmp;\n"; + +static const char * shuffleSinglePatternV3dst = +" tmp%s%s = source[%d]%s%s;\n" +" vstore3(tmp, %d, dest);\n"; + + +static const char * shuffleSinglePatternV3srcV3dst = +"tmp%s%s = vload3(%d, source)%s%s;\n" +"vstore3(tmp, %d, dest);\n"; + +static const char *shuffleFnLinePattern = "%s%s shuffle_fn( %s%s source );\n%s%s shuffle_fn( %s%s source ) { return source; }\n\n"; + +static const char *shuffleFnPattern = +" tmp%s%s = shuffle_fn( source[%d] )%s%s;\n" +" dest[%d] = tmp;\n" +; + + +static const char *shuffleFnPatternV3src = +" tmp%s%s = shuffle_fn( vload3(%d, source) )%s%s;\n" +" dest[%d] = tmp;\n" +; + + +static const char *shuffleFnPatternV3dst = +" tmp%s%s = shuffle_fn( source[%d] )%s%s;\n" +" vstore3(tmp, %d, dest);\n" +; + + +static const char *shuffleFnPatternV3srcV3dst = +" tmp%s%s = shuffle_fn(vload3(%d, source) )%s%s;\n" +" vstore3(tmp, %d, dest);\n" +; + +// shuffle() built-in function patterns +static const char *shuffleBuiltInPattern = +" {\n" +" %s%s src1 = %s;\n" +" %s%s%s mask = (%s%s%s)( %s );\n" +" tmp = shuffle( src1, mask );\n" +" %s;\n" +" }\n" +; + +// shuffle() built-in dual-input function patterns +static const char *shuffleBuiltInDualPattern = +" {\n" +" %s%s src1 = %s;\n" +" %s%s src2 = %s;\n" +" %s%s%s mask = (%s%s%s)( %s );\n" +" tmp = shuffle2( src1, src2, mask );\n" +" %s;\n" +" }\n" +; + + +typedef unsigned char ShuffleOrder[ 16 ]; + +void incrementShuffleOrder( ShuffleOrder &order, size_t orderSize, size_t orderRange ) +{ + for( size_t i = 0; i < orderSize; i++ ) + { + order[ i ]++; + if( order[ i ] < orderRange ) + return; + order[ i ] = 0; + } +} + +bool shuffleOrderContainsDuplicates( ShuffleOrder &order, size_t orderSize ) +{ + bool flags[ 16 ] = { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false }; + for( size_t i = 0; i < orderSize; i++ ) + { + if( flags[ order[ i ] ] ) + return true; + flags[ order[ i ] ] = true; + } + return false; +} + +static void shuffleVector( unsigned char *inVector, unsigned char *outVector, ShuffleOrder order, size_t vecSize, size_t typeSize, cl_uint lengthToUse ) +{ + for(size_t i = 0; i < lengthToUse; i++ ) + { + unsigned char *inPtr = inVector + typeSize *order[ i ]; + memcpy( outVector, inPtr, typeSize ); + outVector += typeSize; + } +} + +static void shuffleVector2( unsigned char *inVector, unsigned char *outVector, ShuffleOrder order, size_t vecSize, size_t typeSize, cl_uint lengthToUse ) +{ + for(size_t i = 0; i < lengthToUse; i++ ) + { + unsigned char *outPtr = outVector + typeSize *order[ i ]; + memcpy( outPtr, inVector, typeSize ); + inVector += typeSize; + } +} + +static void shuffleVectorDual( unsigned char *inVector, unsigned char *inSecondVector, unsigned char *outVector, ShuffleOrder order, size_t vecSize, size_t typeSize, cl_uint lengthToUse ) +{ + // This is tricky: the indices of each shuffle are in a range (0-srcVecSize * 2-1), + // where (srcVecSize-srcVecSize*2-1) refers to the second input. + size_t uphalfMask = (size_t)vecSize; + size_t lowerBits = (size_t)( vecSize - 1 ); + + for(size_t i = 0; i < lengthToUse; i++ ) + { + unsigned char *inPtr; +#if SPEW_ORDER_DETAILS + log_info("order[%d] is %d, or %d of %s\n", (int)i, + (int)(order[i]), + (int)(order[i] & lowerBits), + ((order[i]&uphalfMask) == 0)?"lower num":"upper num"); +#endif + if( order[ i ] & uphalfMask ) + inPtr = inSecondVector + typeSize * ( order[ i ] & lowerBits ); + else + inPtr = inVector + typeSize * ( order[ i ] & lowerBits ); + memcpy( outVector, inPtr, typeSize ); + outVector += typeSize; + } +} + + +static ShuffleOrder sNaturalOrder = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + +static int useNumbersFlip = 0; +const char *get_order_string( ShuffleOrder &order, size_t vecSize, cl_uint lengthToUse, bool byNumber, MTdata d ) +{ + // NOTE: names are only valid for hex characters (up to F) but for debugging, we use + // this to print out orders for dual inputs, which actually can be valid up to position 31 (two 16-element vectors) + // so we go ahead and fake the rest of the alphabet for those other 16 positions, so we have + // some (indirectly) meaningful output + char names[] = "0123456789abcdefghijklmnopqrstuv"; + char namesUpperCase[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV"; + char names2[] = "xyzw!!!!!!!!!!!!"; + + static char orderString[ 18 ]; + + size_t j, idx; + + // Assume we don't have to use numbers + byNumber = 0; + // Check to see + for( j = 0; j < lengthToUse; j++ ) + { + if (order[j] > 3) { + // An index is > xyzw so we need to use numbers + byNumber = 1; + break; + } + } + // If we can use numbers, do so half the time. + if (!byNumber) { + byNumber = (useNumbersFlip++)%2; + } + // Do not use xyzw for vectors whose length is not 2 or 4 per the spec. + if (vecSize != 2 || vecSize != 4 || vecSize != 3) + byNumber = 1; + + if( byNumber || vecSize > 4 ) + { + idx = 0; + // Randomly chose upper and lower case S + orderString[ idx++ ] = random_in_range(0, 1, d) ? 's' : 'S'; + for( j = 0; j < vecSize && j < lengthToUse; j++ ) { + // Randomly choose upper and lower case. + orderString[ idx++ ] = random_in_range(0, 1, d) ? names[ (int)order[ j ] ] : namesUpperCase[ (int)order[ j ] ]; + } + orderString[ idx++ ] = 0; + } + else + { + for( j = 0; j < vecSize && j < lengthToUse; j++ ) { + // Randomly choose upper and lower case. + orderString[ j ] = names2[ (int)order[ j ] ]; + } + orderString[ j ] = 0; + } + + return orderString; +} + +char * get_order_name( ExplicitType vecType, size_t inVecSize, size_t outVecSize, ShuffleOrder &inOrder, ShuffleOrder &outOrder, cl_uint lengthToUse, MTdata d, bool inUseNumerics, bool outUseNumerics ) +{ + static char orderName[ 512 ] = ""; + char inOrderStr[ 512 ], outOrderStr[ 512 ]; + + if( inVecSize == 1 ) + inOrderStr[ 0 ] = 0; + else + sprintf( inOrderStr, "%d.%s", (int)inVecSize, get_order_string( inOrder, outVecSize, lengthToUse, inUseNumerics, d ) ); + if( outVecSize == 1 ) + outOrderStr[ 0 ] = 0; + else + sprintf( outOrderStr, "%d.%s", (int)outVecSize, get_order_string( outOrder, outVecSize, lengthToUse, outUseNumerics, d ) ); + + sprintf( orderName, "order %s%s -> %s%s", + get_explicit_type_name( vecType ), inOrderStr, get_explicit_type_name( vecType ), outOrderStr ); + return orderName; +} + +void print_hex_mem_dump( const unsigned char *inDataPtr, const unsigned char * inDataPtr2, const unsigned char *expected, const unsigned char *outDataPtr, size_t inVecSize, size_t outVecSize, size_t typeSize ) +{ + char error [4096] = ""; + strcat(error, " Source: "); + for( unsigned int j = 0; j < inVecSize * typeSize; j++ ) + { + sprintf(error, "%s%s%02x ",error, ( j % typeSize ) ? "" : " ", (cl_uchar)inDataPtr[ j ] ); + } + if( inDataPtr2 != NULL ) + { + strcat(error, "\n Source 2: "); + for( unsigned int j = 0; j < inVecSize * typeSize; j++ ) + { + sprintf(error, "%s%s%02x ",error, ( j % typeSize ) ? "" : " ", (cl_uchar)inDataPtr2[ j ] ); + } + } + strcat(error, "\n Expected: " ); + for( unsigned int j = 0; j < outVecSize * typeSize; j++ ) + { + sprintf(error, "%s%s%02x ",error, ( j % typeSize ) ? "" : " ", (cl_uchar)expected[ j ] ); + } + strcat(error, "\n Actual: " ); + for( unsigned int j = 0; j < outVecSize * typeSize; j++ ) + { + sprintf(error, "%s%s%02x ",error, ( j % typeSize ) ? "" : " ", (cl_uchar)outDataPtr[ j ] ); + } + log_info("%s\n", error); +} + +void generate_shuffle_mask( char *outMaskString, size_t maskSize, const ShuffleOrder *order ) +{ + outMaskString[ 0 ] = 0; + if( order != NULL ) + { + for( size_t jj = 0; jj < maskSize; jj++ ) + { + char thisMask[ 16 ]; + sprintf( thisMask, "%s%d", ( jj == 0 ) ? "" : ", ", (*order)[ jj ] ); + strcat( outMaskString, thisMask ); + } + } + else + { + for( size_t jj = 0; jj < maskSize; jj++ ) + { + char thisMask[ 16 ]; + sprintf( thisMask, "%s%ld", ( jj == 0 ) ? "" : ", ", jj ); + strcat( outMaskString, thisMask ); + } + } +} + +static int create_shuffle_kernel( cl_context context, cl_program *outProgram, cl_kernel *outKernel, + size_t *outRealVecSize, + ExplicitType vecType, size_t inVecSize, size_t outVecSize, cl_uint *lengthToUse, bool inUseNumerics, bool outUseNumerics, + size_t numOrders, ShuffleOrder *inOrders, ShuffleOrder *outOrders, + MTdata d, ShuffleMode shuffleMode = kNormalMode ) +{ + char inOrder[18], shuffledOrder[18]; + size_t typeSize; + char kernelSource[MAX_PROGRAM_SIZE], progLine[ 10240 ]; + char *programPtr; + char inSizeName[4], outSizeName[4], outRealSizeName[4], inSizeArgName[4]; + char outSizeNameTmpVar[4]; + + + /* Create the source; note vec size is the vector length we are testing */ + if( inVecSize == 1 ) //|| (inVecSize == 3)) // just have arrays if we go with size 3 + inSizeName[ 0 ] = 0; + else + sprintf( inSizeName, "%ld", inVecSize ); + if( inVecSize == 3 ) + inSizeArgName[ 0 ] = 0; + else + strcpy( inSizeArgName, inSizeName ); + + + typeSize = get_explicit_type_size( vecType ); + + *outRealVecSize = outVecSize; + + if( outVecSize == 1 || (outVecSize == 3)) + outSizeName[ 0 ] = 0; + else + sprintf( outSizeName, "%d", (int)outVecSize ); + + if(outVecSize == 1) { + outSizeNameTmpVar[0] = 0; + } else { + sprintf(outSizeNameTmpVar, "%d", (int)outVecSize); + } + + if( *outRealVecSize == 1 || ( *outRealVecSize == 3)) + outRealSizeName[ 0 ] = 0; + else + sprintf( outRealSizeName, "%d", (int)*outRealVecSize ); + + + // Loop through and create the source for all order strings + kernelSource[ 0 ] = 0; + if (vecType == kDouble) { + strcat(kernelSource, "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"); + } + + if( shuffleMode == kFunctionCallMode ) + { + sprintf( progLine, shuffleFnLinePattern, get_explicit_type_name( vecType ), inSizeName, get_explicit_type_name( vecType ), inSizeName, + get_explicit_type_name( vecType ), inSizeName, get_explicit_type_name( vecType ), inSizeName ); + strcat(kernelSource, progLine); + } + + // We're going to play a REALLY NASTY trick here. We're going to use the inSize insert point + // to put in an entire third parameter if we need it + char inParamSizeString[ 1024 ]; + if( shuffleMode == kBuiltInDualInputFnMode ) + sprintf( inParamSizeString, "%s *secondSource, __global %s%s", inSizeArgName, get_explicit_type_name( vecType ), inSizeArgName ); + else + strcpy( inParamSizeString, inSizeArgName ); + + // These two take care of unused variable warnings + const char * src2EnableA = ( shuffleMode == kBuiltInDualInputFnMode ) ? "" : "/*"; + const char * src2EnableB = ( shuffleMode == kBuiltInDualInputFnMode ) ? "" : "*/"; + + sprintf( progLine, shuffleKernelPattern[ 0 ], get_explicit_type_name( vecType ), inParamSizeString, + get_explicit_type_name( vecType ), outRealSizeName, get_explicit_type_name( vecType ), inSizeName, + src2EnableA, src2EnableB ); + strcat(kernelSource, progLine); + if( inOrders == NULL ) + strcpy( inOrder, get_order_string( sNaturalOrder, outVecSize, (cl_uint)outVecSize, inUseNumerics, d ) ); + + sprintf( progLine, shuffleTempPattern, get_explicit_type_name( vecType ), outSizeNameTmpVar); + strcat(kernelSource, progLine); + + for( unsigned int i = 0; i < numOrders; i++ ) + { + if( inOrders != NULL ) + strcpy( inOrder, get_order_string( inOrders[ i ], outVecSize, lengthToUse[i], inUseNumerics, d ) ); + strcpy( shuffledOrder, get_order_string( outOrders[ i ], outVecSize, lengthToUse[i], outUseNumerics, d ) ); + + + sprintf( progLine, clearTempPattern, get_explicit_type_name( vecType ), outSizeName,get_explicit_type_name( vecType )); + strcat(kernelSource, progLine); + + + if( shuffleMode == kNormalMode ) + { + if(outVecSize == 3 && inVecSize == 3) { + // shuffleSinglePatternV3srcV3dst + sprintf( progLine, shuffleSinglePatternV3srcV3dst, + outVecSize > 1 ? "." : "", outVecSize > 1 ? shuffledOrder : "", (int)i, + inVecSize > 1 ? "." : "", inVecSize > 1 ? inOrder : "", (int)i ); + } else if(inVecSize == 3) { + // shuffleSinglePatternV3src + sprintf( progLine, shuffleSinglePatternV3src, + outVecSize > 1 ? "." : "", outVecSize > 1 ? shuffledOrder : "", (int)i, + inVecSize > 1 ? "." : "", inVecSize > 1 ? inOrder : "", (int)i ); + } else if(outVecSize == 3) { + // shuffleSinglePatternV3dst + sprintf( progLine, shuffleSinglePatternV3dst, + outVecSize > 1 ? "." : "", outVecSize > 1 ? shuffledOrder : "", (int)i, + inVecSize > 1 ? "." : "", inVecSize > 1 ? inOrder : "", + (int)i ); + } else { + sprintf( progLine, shuffleSinglePattern, + outVecSize > 1 ? "." : "", outVecSize > 1 ? shuffledOrder : "", (int)i, + inVecSize > 1 ? "." : "", inVecSize > 1 ? inOrder : "", (int)i ); + } + } + else if( shuffleMode == kFunctionCallMode ) + { + // log_info("About to make a shuffle line\n"); + // fflush(stdout); + if(inVecSize == 3 && outVecSize == 3) { // swap last two + sprintf( progLine, shuffleFnPatternV3srcV3dst, + outVecSize > 1 ? "." : "", outVecSize > 1 ? shuffledOrder : "", (int)i, + inVecSize > 1 ? "." : "", inVecSize > 1 ? inOrder : "", + (int)i ); + } else if(outVecSize == 3) { // swap last two + // log_info("Here\n\n"); + // fflush(stdout); + sprintf( progLine, shuffleFnPatternV3dst, + outVecSize > 1 ? "." : "", + outVecSize > 1 ? shuffledOrder : "", + (int)i, + inVecSize > 1 ? "." : "", + inVecSize > 1 ? inOrder : "", + (int)i ); + // log_info("\n%s\n", progLine); + // fflush(stdout); + } else if(inVecSize == 3) { + sprintf( progLine, shuffleFnPatternV3src, + outVecSize > 1 ? "." : "", outVecSize > 1 ? shuffledOrder : "", (int)i, + inVecSize > 1 ? "." : "", inVecSize > 1 ? inOrder : "", (int)i ); + } else { + sprintf( progLine, shuffleFnPattern, + outVecSize > 1 ? "." : "", outVecSize > 1 ? shuffledOrder : "", (int)i, + inVecSize > 1 ? "." : "", inVecSize > 1 ? inOrder : "", (int)i ); + } + } + else if( shuffleMode == kArrayAccessMode ) + { // now we want to replace inSizeName with inSizeNameShuffleFn + int vectorSizeToCastTo = 16; + cl_uint item; + for (item =0; item 1 ? "." : "", outVecSize > 1 ? shuffledOrder : "", + get_explicit_type_name( vecType ), vectorSizeToCastTo, + castVectorIndex, + vectorSizeToCastTo > 1 ? "." : "", vectorSizeToCastTo > 1 ? inOrder : ""); + strcat(kernelSource, progLine); + } + if(outVecSize == 3) { + sprintf(progLine," vstore3(tmp, %d, (__global %s *)dest);\n", + i, get_explicit_type_name( vecType )); + // probably don't need that last + // cast to (__global %s *) where %s is get_explicit_type_name( vecType) + } else { + sprintf(progLine," dest[%d] = tmp;\n", i ); + } + } + else // shuffleMode == kBuiltInFnMode or kBuiltInDualInputFnMode + { + if(inVecSize == 3 || outVecSize == 3 || + inVecSize == 1 || outVecSize == 1) { + // log_info("Skipping test for size 3\n"); + continue; + } + ExplicitType maskType = vecType; + if( maskType == kFloat ) + maskType = kUInt; + if( maskType == kDouble) { + maskType = kULong; + } + + char maskString[ 1024 ] = ""; + size_t maskSize = outVecSize;// ( shuffleMode == kBuiltInDualInputFnMode ) ? ( outVecSize << 1 ) : outVecSize; + generate_shuffle_mask( maskString, maskSize, ( outOrders != NULL ) ? &outOrders[ i ] : NULL ); + + // Set up a quick prefix, so mask gets unsigned type regardless of the input/output type + char maskPrefix[ 2 ] = "u"; + if( get_explicit_type_name( maskType )[ 0 ] == 'u' ) + maskPrefix[ 0 ] = 0; + + char progLine2[ 10240 ]; + if( shuffleMode == kBuiltInDualInputFnMode ) + { + sprintf( progLine2, shuffleBuiltInDualPattern, get_explicit_type_name( vecType ), inSizeName, + ( inVecSize == 3 ) ? "vload3( %ld, (__global %s *)source )" : "source[ %ld ]", + get_explicit_type_name( vecType ), inSizeName, + ( inVecSize == 3 ) ? "vload3( %ld, (__global %s *)secondSource )" : "secondSource[ %ld ]", + maskPrefix, get_explicit_type_name( maskType ), outSizeName, maskPrefix, get_explicit_type_name( maskType ), outSizeName, + maskString, + ( outVecSize == 3 ) ? "vstore3( tmp, %ld, (__global %s *)dest )" : "dest[ %ld ] = tmp" ); + + if( outVecSize == 3 ) + { + if( inVecSize == 3 ) + sprintf( progLine, progLine2, i, get_explicit_type_name( vecType ), i, get_explicit_type_name( vecType ), i, get_explicit_type_name( vecType ) ); + else + sprintf( progLine, progLine2, i, i, i, get_explicit_type_name( vecType ) ); + } + else + { + if( inVecSize == 3 ) + sprintf( progLine, progLine2, i, get_explicit_type_name( vecType ), i, get_explicit_type_name( vecType ), i ); + else + sprintf( progLine, progLine2, i, i, i ); + } + } + else + { + sprintf( progLine2, shuffleBuiltInPattern, get_explicit_type_name( vecType ), inSizeName, + ( inVecSize == 3 ) ? "vload3( %ld, (__global %s *)source )" : "source[ %ld ]", + maskPrefix, get_explicit_type_name( maskType ), outSizeName, maskPrefix, get_explicit_type_name( maskType ), outSizeName, + maskString, + ( outVecSize == 3 ) ? "vstore3( tmp, %ld, (__global %s *)dest )" : "dest[ %ld ] = tmp" ); + + if( outVecSize == 3 ) + { + if( inVecSize == 3 ) + sprintf( progLine, progLine2, i, get_explicit_type_name( vecType ), i, get_explicit_type_name( vecType ) ); + else + sprintf( progLine, progLine2, i, i, get_explicit_type_name( vecType ) ); + } + else + { + if( inVecSize == 3 ) + sprintf( progLine, progLine2, i, get_explicit_type_name( vecType ), i ); + else + sprintf( progLine, progLine2, i, i ); + } + } + } + + strcat( kernelSource, progLine ); + if (strlen(kernelSource) > 0.9*MAX_PROGRAM_SIZE) + log_info("WARNING: Program has grown to 90%% (%d) of the defined max program size of %d\n", (int)strlen(kernelSource), (int)MAX_PROGRAM_SIZE); + } + strcat( kernelSource, shuffleKernelPattern[ 1 ] ); + + // Print the kernel source + if (PRINT_SHUFFLE_KERNEL_SOURCE) + log_info( "Kernel:%s\n", kernelSource ); + + /* Create kernel */ + programPtr = kernelSource; + if( create_single_kernel_helper( context, outProgram, outKernel, 1, (const char **)&programPtr, "sample_test" ) ) + { + return -1; + } + return 0; +} + +int test_shuffle_dual_kernel(cl_context context, cl_command_queue queue, + ExplicitType vecType, size_t inVecSize, size_t outVecSize, cl_uint *lengthToUse, size_t numOrders, + ShuffleOrder *inOrderIdx, ShuffleOrder *outOrderIdx, bool inUseNumerics, bool outUseNumerics, MTdata d, + ShuffleMode shuffleMode = kNormalMode ) +{ + clProgramWrapper program; + clKernelWrapper kernel; + int error; + size_t threads[1], localThreads[1]; + size_t typeSize, outRealVecSize; + clMemWrapper streams[ 3 ]; + + /* Create the source */ + error = create_shuffle_kernel( context, &program, &kernel, &outRealVecSize, vecType, + inVecSize, outVecSize, lengthToUse, inUseNumerics, outUseNumerics, numOrders, inOrderIdx, outOrderIdx, + d, shuffleMode ); + if( error != 0 ) + return error; + + typeSize = get_explicit_type_size( vecType ); + +#if !(defined(_WIN32) && defined (_MSC_VER)) + cl_long inData[ inVecSize * numOrders ]; + cl_long inSecondData[ inVecSize * numOrders ]; + cl_long outData[ outRealVecSize * numOrders ]; +#else + cl_long* inData = (cl_long*)_malloca(inVecSize * numOrders * sizeof(cl_long)); + cl_long* inSecondData = (cl_long*)_malloca(inVecSize * numOrders * sizeof(cl_long)); + cl_long* outData = (cl_long*)_malloca(outRealVecSize * numOrders * sizeof(cl_long)); +#endif + memset(outData, 0, outRealVecSize * numOrders * sizeof(cl_long) ); + + generate_random_data( vecType, (unsigned int)( numOrders * inVecSize ), d, inData ); + if( shuffleMode == kBuiltInDualInputFnMode ) + generate_random_data( vecType, (unsigned int)( numOrders * inVecSize ), d, inSecondData ); + + streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), typeSize * inVecSize * numOrders, inData, &error); + test_error( error, "Unable to create input stream" ); + + streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), typeSize * outRealVecSize * numOrders, outData, &error); + test_error( error, "Unable to create output stream" ); + + int argIndex = 0; + if( shuffleMode == kBuiltInDualInputFnMode ) + { + streams[2] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), typeSize * inVecSize * numOrders, inSecondData, &error); + test_error( error, "Unable to create second input stream" ); + + error = clSetKernelArg( kernel, argIndex++, sizeof( streams[ 2 ] ), &streams[ 2 ] ); + test_error( error, "Unable to set kernel argument" ); + } + + // Set kernel arguments + error = clSetKernelArg( kernel, argIndex++, sizeof( streams[ 0 ] ), &streams[ 0 ] ); + test_error( error, "Unable to set kernel argument" ); + error = clSetKernelArg( kernel, argIndex++, sizeof( streams[ 1 ] ), &streams[ 1 ] ); + test_error( error, "Unable to set kernel argument" ); + + + /* Run the kernel */ + threads[0] = numOrders; + + error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] ); + test_error( error, "Unable to get work group size to use" ); + + error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL ); + test_error( error, "Unable to execute test kernel" ); + + + // Read the results back + error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, typeSize * numOrders * outRealVecSize, outData, 0, NULL, NULL ); + test_error( error, "Unable to read results" ); + + unsigned char *inDataPtr = (unsigned char *)inData; + unsigned char *inSecondDataPtr = (unsigned char *)inSecondData; + unsigned char *outDataPtr = (unsigned char *)outData; + int ret = 0; + int errors_printed = 0; + for( size_t i = 0; i < numOrders; i++ ) + { + unsigned char expected[ 1024 ]; + unsigned char temp[ 1024 ]; + memset(expected, 0, sizeof(expected)); + memset(temp, 0, sizeof(temp)); + if( shuffleMode == kBuiltInFnMode ) + shuffleVector( inDataPtr, expected, outOrderIdx[ i ], outVecSize, typeSize, lengthToUse[i] ); + else if( shuffleMode == kBuiltInDualInputFnMode ) + shuffleVectorDual( inDataPtr, inSecondDataPtr, expected, outOrderIdx[ i ], inVecSize, typeSize, lengthToUse[i] ); + else + { + shuffleVector( inDataPtr, temp, inOrderIdx[ i ], inVecSize, typeSize, lengthToUse[i] ); + shuffleVector2( temp, expected, outOrderIdx[ i ], outVecSize, typeSize, lengthToUse[i] ); + } + + if( memcmp( expected, outDataPtr, outVecSize * typeSize ) != 0 ) + { + log_error( " ERROR: Shuffle test %d FAILED for %s (memory hex dump follows)\n", (int)i, + get_order_name( vecType, inVecSize, outVecSize, inOrderIdx[ i ], outOrderIdx[ i ], lengthToUse[i], d, inUseNumerics, outUseNumerics ) ); + + print_hex_mem_dump( inDataPtr, ( shuffleMode == kBuiltInDualInputFnMode ) ? inSecondDataPtr : NULL, expected, outDataPtr, inVecSize, outVecSize, typeSize ); + + if( ( shuffleMode == kBuiltInFnMode ) || ( shuffleMode == kBuiltInDualInputFnMode ) ) + { + // Mask would've been different for every shuffle done, so we have to regen it to print it + char maskString[ 1024 ]; + generate_shuffle_mask( maskString, outVecSize, ( outOrderIdx != NULL ) ? &outOrderIdx[ i ] : NULL ); + log_error( " Mask: %s\n", maskString ); + } + + ret++; + errors_printed++; + if (errors_printed > MAX_ERRORS_TO_PRINT) + { + log_info("Further errors suppressed.\n"); + return ret; + } + } + inDataPtr += inVecSize * typeSize; + inSecondDataPtr += inVecSize * typeSize; + outDataPtr += outRealVecSize * typeSize; + } + + return ret; +} + +void build_random_shuffle_order( ShuffleOrder &outIndices, unsigned int length, unsigned int selectLength, bool allowRepeats, MTdata d ) +{ + char flags[ 16 ]; + + memset( flags, 0, sizeof( flags ) ); + + for( unsigned int i = 0; i < length; i++ ) + { + char selector = (char)random_in_range( 0, selectLength - 1, d ); + if( !allowRepeats ) + { + while( flags[ (int)selector ] ) + selector = (char)random_in_range( 0, selectLength - 1, d ); + flags[ (int)selector ] = true; + } + outIndices[ i ] = selector; + } +} + +class shuffleBuffer +{ +public: + + shuffleBuffer( cl_context ctx, cl_command_queue queue, ExplicitType type, size_t inSize, size_t outSize, ShuffleMode mode ) + { + mContext = ctx; + mQueue = queue; + mVecType = type; + mInVecSize = inSize; + mOutVecSize = outSize; + mShuffleMode = mode; + + mCount = 0; + + // Here's the deal with mLengthToUse[i]. + // if you have, for instance + // uchar4 dst; + // uchar8 src; + // you can do + // src.s0213 = dst.s1045; + // but you can also do + // src.s02 = dst.s10; + // which has a different effect + // The intent with these "sub lengths" is to test all such + // possibilities + // Calculate a range of sub-lengths within the vector to copy. + int i; + size_t maxSize = (mInVecSize < mOutVecSize) ? mInVecSize : mOutVecSize; + for(i=0; i 0 ) + { + err = test_shuffle_dual_kernel( mContext, mQueue, mVecType, mInVecSize, mOutVecSize, mLengthToUse, + mCount, mInOrders, mOutOrders, true, true, d, mShuffleMode ); + mCount = 0; + } + return err; + } + +protected: + cl_context mContext; + cl_command_queue mQueue; + ExplicitType mVecType; + size_t mInVecSize, mOutVecSize, mCount; + ShuffleMode mShuffleMode; + cl_uint mLengthToUse[ NUM_TESTS ]; + + ShuffleOrder mInOrders[ NUM_TESTS ], mOutOrders[ NUM_TESTS ]; +}; + + +int test_shuffle_random(cl_device_id device, cl_context context, cl_command_queue queue, ShuffleMode shuffleMode, MTdata d ) +{ + ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble }; + unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 }; + unsigned int srcIdx, dstIdx, typeIndex; + int error = 0, totalError = 0, prevTotalError = 0; + RandomSeed seed(gRandomSeed); + + for( typeIndex = 0; typeIndex < 10; typeIndex++ ) + { + //log_info( "\n\t%s... ", get_explicit_type_name( vecType[ typeIndex ] ) ); + //fflush( stdout ); + if (vecType[typeIndex] == kDouble) { + if (!is_extension_available(device, "cl_khr_fp64")) { + log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n"); + continue; + } + log_info("Testing doubles.\n"); + } + + if ((vecType[typeIndex] == kLong || vecType[typeIndex] == kULong) && !gHasLong ) + { + log_info("Long types are unsupported, skipping."); + continue; + } + + error = 0; + for( srcIdx = 0; vecSizes[ srcIdx ] != 0 /*&& error == 0*/; srcIdx++ ) + { + for( dstIdx = 0; vecSizes[ dstIdx ] != 0 /*&& error == 0*/; dstIdx++ ) + { + if( ( ( shuffleMode == kBuiltInDualInputFnMode ) || ( shuffleMode == kBuiltInFnMode ) ) && + ( ( vecSizes[ dstIdx ] & 1 ) || ( vecSizes[ srcIdx ] & 1 ) ) ) + { + // Built-in shuffle functions don't work on size 1 (scalars) or size 3 (vec3s) + continue; + } + + log_info("Testing [%s%d to %s%d]... ", get_explicit_type_name( vecType[ typeIndex ] ) , vecSizes[srcIdx], get_explicit_type_name( vecType[ typeIndex ] ) , vecSizes[dstIdx]); + shuffleBuffer buffer( context, queue, vecType[ typeIndex ], vecSizes[ srcIdx ], vecSizes[ dstIdx ], shuffleMode ); + + int numTests = NUM_TESTS*NUM_ITERATIONS_PER_TEST; + for( int i = 0; i < numTests /*&& error == 0*/; i++ ) + { + ShuffleOrder src, dst; + if( shuffleMode == kBuiltInFnMode ) + { + build_random_shuffle_order( dst, vecSizes[ dstIdx ], vecSizes[ srcIdx ], true, d ); + } + else if(shuffleMode == kBuiltInDualInputFnMode) + { + build_random_shuffle_order(dst, vecSizes[dstIdx], 2*vecSizes[srcIdx], true, d); + } + else + { + build_random_shuffle_order( src, vecSizes[ dstIdx ], vecSizes[ srcIdx ], true, d ); + build_random_shuffle_order( dst, vecSizes[ dstIdx ], vecSizes[ dstIdx ], false, d ); + } + + error = buffer.AddRun( src, dst, seed ); + if (error) + totalError++; + } + int test_error = buffer.Flush(seed); + if (test_error) + totalError++; + + if (totalError == prevTotalError) + log_info("\tPassed.\n"); + else + { + log_error("\tFAILED.\n"); + prevTotalError = totalError; + } + } + } + } + return totalError; +} + +int test_shuffle_copy(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + RandomSeed seed(gRandomSeed); + return test_shuffle_random( device, context, queue, kNormalMode, seed ); +} + +int test_shuffle_function_call(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + RandomSeed seed(gRandomSeed); + return test_shuffle_random( device, context, queue, kFunctionCallMode, seed ); +} + +int test_shuffle_array_cast(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + RandomSeed seed(gRandomSeed); + return test_shuffle_random( device, context, queue, kArrayAccessMode, seed ); +} + +int test_shuffle_built_in(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + RandomSeed seed(gRandomSeed); + return test_shuffle_random( device, context, queue, kBuiltInFnMode, seed ); +} + +int test_shuffle_built_in_dual_input(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems) +{ + RandomSeed seed(gRandomSeed); + return test_shuffle_random( device, context, queue, kBuiltInDualInputFnMode, seed ); +} + diff --git a/test_conformance/run_conformance.py b/test_conformance/run_conformance.py new file mode 100644 index 00000000..ea7f6775 --- /dev/null +++ b/test_conformance/run_conformance.py @@ -0,0 +1,357 @@ +#! /usr/bin/python + +#/****************************************************************** +#// +#// OpenCL Conformance Tests +#// +#// Copyright: (c) 2008-2009 by Apple Inc. All Rights Reserved. +#// +#******************************************************************/ + +import os, re, sys, subprocess, time, commands, tempfile, math, string + +DEBUG = 0 + +log_file_name = "opencl_conformance_results_" + time.strftime("%Y-%m-%d_%H-%M", time.localtime())+ ".log" +process_pid = 0 + +# The amount of time between printing a "." (if no output from test) or ":" (if output) +# to the screen while the tests are running. +seconds_between_status_updates = 60*60*24*7 # effectively never + +# Help info +def write_help_info() : + print("run_conformance.py test_list [CL_DEVICE_TYPE(s) to test] [partial-test-names, ...] [log=path/to/log/file/]") + print(" test_list - the .csv file containing the test names and commands to run the tests.") + print(" [partial-test-names, ...] - optional partial strings to select a subset of the tests to run.") + print(" [CL_DEVICE_TYPE(s) to test] - list of CL device types to test, default is CL_DEVICE_TYPE_DEFAULT.") + print(" [log=path/to/log/file/] - provide a path for the test log file, default is in the current directory.") + print(" (Note: spaces are not allowed in the log file path.") + + +# Get the time formatted nicely +def get_time() : + return time.strftime("%d-%b %H:%M:%S", time.localtime()) + +# Write text to the screen and the log file +def write_screen_log(text) : + global log_file + print(text) + log_file.write(text+"\n") + +# Load the tests from a csv formated file of the form name,command +def get_tests(filename, devices_to_test): + tests = [] + if (os.path.exists(filename) == False): + print("FAILED: test_list \"" + filename + "\" does not exist.") + print("") + write_help_info() + sys.exit(-1) + file = open(filename, 'r') + for line in file.readlines(): + comment = re.search("^#.*", line) + if (comment): + continue + device_specific_match = re.search("^\s*(.+?)\s*,\s*(.+?)\s*,\s*(.+?)\s*$", line) + if (device_specific_match): + if (device_specific_match.group(1) in devices_to_test): + test_path = string.replace(device_specific_match.group(3), '/', os.sep) + test_name = string.replace(device_specific_match.group(2), '/', os.sep) + tests.append((test_name, test_path)) + else: + print("Skipping " + device_specific_match.group(2) + " because " + device_specific_match.group(1) + " is not in the list of devices to test.") + continue + match = re.search("^\s*(.+?)\s*,\s*(.+?)\s*$", line) + if (match): + test_path = string.replace(match.group(2), '/', os.sep) + test_name = string.replace(match.group(1), '/', os.sep) + tests.append((test_name, test_path)) + return tests + + +def run_test_checking_output(current_directory, test_dir, log_file): + global process_pid, seconds_between_status_updates + failures_this_run = 0 + start_time = time.time() + # Create a temporary file for capturing the output from the test + (output_fd, output_name) = tempfile.mkstemp() + if ( not os.path.exists(output_name)) : + write_screen_log("\n ==> ERROR: could not create temporary file %s ." % output_name) + os.close(output_fd) + return -1 + # Execute the test + program_to_run = test_dir_without_args = test_dir.split(None, 1)[0] + if ( os.sep == '\\' ) : program_to_run += ".exe" + if (os.path.exists(current_directory + os.sep + program_to_run)) : + os.chdir(os.path.dirname(current_directory+os.sep+test_dir_without_args) ) + try: + if (DEBUG): p = subprocess.Popen("", stderr=subprocess.STDOUT, stdout=subprocess.PIPE, shell=True) + else : p = subprocess.Popen(current_directory + os.sep + test_dir, stderr=output_fd, stdout=output_fd, shell=True) + except OSError: + write_screen_log("\n ==> ERROR: failed to execute test. Failing test. : " + str(OSError)) + os.close(output_fd) + return -1 + else: + write_screen_log("\n ==> ERROR: test file (" + current_directory + os.sep + program_to_run +") does not exist. Failing test.") + os.close(output_fd) + return -1 + # Set the global pid so we can kill it if this is aborted + process_pid = p.pid + # Read one character at a time from the temporary output file while the process is running. + # When we get an end-of-line, look for errors and write the results to the log file. + # This allows us to process the file as it is being produced. + # Keep track of the state for reading + # Whether we are done, if we have more to read, and where in the file we last read + done = False + more_to_read = True + pointer = 0 + pointer_at_last_user_update = 0 + output_this_run = False + try: + read_output = open(output_name, 'r') + except IOError: + write_screen_log("\n ==> ERROR: could not open output file from test.") + os.close(output_fd) + return -1 + line = "" + while (not done or more_to_read): + os.fsync(output_fd) + # Determine if we should display some output + elapsed_time = (time.time() - start_time) + if (elapsed_time > seconds_between_status_updates): + start_time = time.time() + # If we've received output from the test since the last update, display a # + if (pointer != pointer_at_last_user_update): + sys.stdout.write(":") + else: + sys.stdout.write(".") + pointer_at_last_user_update = pointer + sys.stdout.flush() + # Check if we're done + p.poll() + if (not done and p.returncode != None): + if (p.returncode < 0): + if (not output_this_run): + print "" + output_this_run = True + write_screen_log(" ==> ERROR: test killed/crashed: " + str(p.returncode)+ ".") + done = True + # Try reading + try: + read_output.seek(pointer) + char_read = read_output.read(1) + except IOError: + time.sleep(1) + continue + # If we got a full line then process it + if (char_read == "\n"): + # Look for failures and report them as such + match = re.search(".*(FAILED|ERROR).*", line) + if (match): + if (not output_this_run): + print "" + output_this_run = True + print(" ==> " + line.replace('\n','')) + match = re.search(".*FAILED.*", line) + if (match): + failures_this_run = failures_this_run + 1 + match = re.search(".*(PASSED).*", line) + if (match): + if (not output_this_run): + print "" + output_this_run = True + print(" " + line.replace('\n','')) + # Write it to the log + log_file.write(" " + line +"\n") + log_file.flush() + line = "" + pointer = pointer + 1 + # If we are at the end of the file, then re-open it to get new data + elif (char_read == ""): + more_to_read = False + read_output.close() + time.sleep(1) + try: + os.fsync(output_fd) + read_output = open(output_name, 'r') + # See if there is more to read. This happens if the process ends and we have data left. + read_output.seek(pointer) + if (read_output.read(1) != ""): + more_to_read = True + except IOError: + write_screen_log("\n ==> ERROR: could not reopen output file from test.") + return -1 + done = True + else: + line = line + char_read + pointer = pointer + 1 + # Now we are done, so write out any remaining data in the file: + # This should only happen if the process exited with an error. + os.fsync(output_fd) + while (read_output.read(1) != ""): + log_file.write(read_output.read(1)) + # Return the total number of failures + if (p.returncode == 0 and failures_this_run > 0): + write_screen_log("\n ==> ERROR: Test returned 0, but number of FAILED lines reported is " + str(failures_this_run) +".") + return failures_this_run + return p.returncode + + +def run_tests(tests) : + global curent_directory + global process_pid + # Run the tests + failures = 0 + previous_test = None + test_number = 1 + for test in tests: + # Print the name of the test we're running and the time + (test_name, test_dir) = test + if (test_dir != previous_test): + print("========== " + test_dir) + log_file.write("========================================================================================\n") + log_file.write("========================================================================================\n") + log_file.write("(" + get_time() + ") Running Tests: " + test_dir +"\n") + log_file.write("========================================================================================\n") + log_file.write("========================================================================================\n") + previous_test = test_dir + print("("+get_time()+") BEGIN " + test_name.ljust(40) +": "), + log_file.write(" ----------------------------------------------------------------------------------------\n") + log_file.write(" (" + get_time() + ") Running Sub Test: " + test_name + "\n") + log_file.write(" ----------------------------------------------------------------------------------------\n") + log_file.flush() + sys.stdout.flush() + + # Run the test + result = 0 + start_time = time.time() + try: + process_pid = 0 + result = run_test_checking_output(current_directory, test_dir, log_file) + except KeyboardInterrupt: + # Catch an interrupt from the user + write_screen_log("\nFAILED: Execution interrupted. Killing test process, but not aborting full test run.") + os.kill(process_pid, 9) + answer = raw_input("Abort all tests? (y/n)") + if (answer.find("y") != -1): + write_screen_log("\nUser chose to abort all tests.") + log_file.close() + sys.exit(-1) + else: + write_screen_log("\nUser chose to continue with other tests. Reporting this test as failed.") + result = 1 + run_time = (time.time() - start_time) + + # Move print the finish status + if (result == 0): + print("("+get_time()+") PASSED " + test_name.ljust(40) +": (" + str(int(run_time)).rjust(3) + "s, test " + str(test_number).rjust(3) + os.sep + str(len(tests)) +")"), + else: + print("("+get_time()+") FAILED " + test_name.ljust(40) +": (" + str(int(run_time)).rjust(3) + "s, test " + str(test_number).rjust(3) + os.sep + str(len(tests)) +")"), + + test_number = test_number + 1 + log_file.write(" ----------------------------------------------------------------------------------------\n") + log_file.flush() + + print("") + if (result != 0): + log_file.write(" *******************************************************************************************\n") + log_file.write(" * ("+get_time()+") Test " + test_name + " ==> FAILED: " + str(result)+"\n") + log_file.write(" *******************************************************************************************\n") + failures = failures + 1 + else: + log_file.write(" ("+get_time()+") Test " + test_name +" passed in " + str(run_time) + "s\n") + + log_file.write(" ----------------------------------------------------------------------------------------\n") + log_file.write("\n") + return failures + + + + + +# ######################## +# Begin OpenCL conformance run script +# ######################## + +if (len(sys.argv) < 2): + write_help_info() + sys.exit(-1) + + +current_directory = os.getcwd() +# Open the log file +for arg in sys.argv: + match = re.search("log=(\S+)", arg) + if (match): + log_file_name = match.group(1).rstrip('/') + os.sep + log_file_name +try: + log_file = open(log_file_name, "w") +except IOError: + print "Could not open log file " + log_file_name + +# Determine which devices to test +device_types = ["CL_DEVICE_TYPE_DEFAULT", "CL_DEVICE_TYPE_CPU", "CL_DEVICE_TYPE_GPU", "CL_DEVICE_TYPE_ACCELERATOR", "CL_DEVICE_TYPE_ALL"] +devices_to_test = [] +for device in device_types: + if device in sys.argv[2:]: + devices_to_test.append(device) +if (len(devices_to_test) == 0): + devices_to_test = ["CL_DEVICE_TYPE_DEFAULT"] +write_screen_log("Testing on: " + str(devices_to_test)) + +# Get the tests +tests = get_tests(sys.argv[1], devices_to_test) + +# If tests are specified on the command line then run just those ones +tests_to_use = [] +num_of_patterns_to_match = 0 +for arg in sys.argv[2:]: + if arg in device_types: + continue + if re.search("log=(\S+)", arg): + continue + num_of_patterns_to_match = num_of_patterns_to_match + 1 + found_it = False + for test in tests: + (test_name, test_dir) = test + if (test_name.find(arg) != -1 or test_dir.find(arg) != -1): + found_it = True + if (test not in tests_to_use): + tests_to_use.append(test) + if (found_it == False): + print("Failed to find a test matching " + arg) +if (len(tests_to_use) == 0): + if (num_of_patterns_to_match > 0): + print("FAILED: Failed to find any tests matching the given command-line options.") + print("") + write_help_info() + sys.exit(-1) +else: + tests = tests_to_use[:] + +write_screen_log("Test execution arguments: " + str(sys.argv)) +write_screen_log("Logging to file " + log_file_name +".") +write_screen_log("Loaded tests from " + sys.argv[1] + ", total of " + str(len(tests)) + " tests selected to run:") +for (test_name, test_command) in tests: + write_screen_log(test_name.ljust(50) + " (" + test_command +")") + +# Run the tests +total_failures = 0 +for device_to_test in devices_to_test: + os.environ['CL_DEVICE_TYPE'] = device_to_test + write_screen_log("========================================================================================") + write_screen_log("========================================================================================") + write_screen_log(("Setting CL_DEVICE_TYPE to " + device_to_test).center(90)) + write_screen_log("========================================================================================") + write_screen_log("========================================================================================") + failures = run_tests(tests) + write_screen_log("========================================================================================") + if (failures == 0): + write_screen_log(">> TEST on " + device_to_test + " PASSED") + else: + write_screen_log(">> TEST on " + device_to_test + " FAILED (" + str(failures) + " FAILURES)") + write_screen_log("========================================================================================") + total_failures = total_failures + failures + +write_screen_log("("+get_time()+") Testing complete. " + str(total_failures) + " failures for " + str(len(tests)) + " tests.") +log_file.close() diff --git a/test_conformance/select/CMakeLists.txt b/test_conformance/select/CMakeLists.txt new file mode 100644 index 00000000..6f25c466 --- /dev/null +++ b/test_conformance/select/CMakeLists.txt @@ -0,0 +1,14 @@ +set(MODULE_NAME SELECT) + +set(${MODULE_NAME}_SOURCES + test_select.c + util_select.c + ../../test_common/harness/testHarness.c + ../../test_common/harness/mt19937.c + ../../test_common/harness/msvc9.c + ../../test_common/harness/kernelHelpers.c + ../../test_common/harness/errorHelpers.c + ../../test_common/harness/parseParameters.cpp +) + +include(../CMakeCommon.txt) diff --git a/test_conformance/select/Jamfile b/test_conformance/select/Jamfile new file mode 100644 index 00000000..6448048e --- /dev/null +++ b/test_conformance/select/Jamfile @@ -0,0 +1,21 @@ +project + : requirements + -/harness//harness /harness//harness +# gcc:-xc + msvc:"/TP" + ; + +exe test_select + : test_select.c + util_select.c + /harness//mt19937.c + /harness//kernelHelpers.c + /harness//errorHelpers.c + : windows:/harness//msvc9.c + ; + +install dist + : test_select + : debug:$(DIST)/debug/tests/test_conformance/select + release:$(DIST)/release/tests/test_conformance/select + ; diff --git a/test_conformance/select/Makefile b/test_conformance/select/Makefile new file mode 100644 index 00000000..c89d5ff3 --- /dev/null +++ b/test_conformance/select/Makefile @@ -0,0 +1,33 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = test_select.c util_select.c ../../test_common/harness/mt19937.c ../../test_common/harness/kernelHelpers.c ../../test_common/harness/errorHelpers.c + +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. +FRAMEWORK = $(abspath $(SRCS)) +HEADERS = test_select.h +TARGET = test_select +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Os -Wshorten-64-to-32 +CC = c++ +CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} +LIBRARIES = -framework OpenCL ${ATF} + +OBJECTS = test_select.o util_select.o mt19937.o kernelHelpers.o errorHelpers.o +TARGETOBJECT = +all: $(TARGET) + +$(OBJECTS): $(FRAMEWORK) $(HEADERS) + $(CC) $(CFLAGS) $(INCLUDE) $(FRAMEWORK) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/select/test_select.c b/test_conformance/select/test_select.c new file mode 100644 index 00000000..5eec6a3d --- /dev/null +++ b/test_conformance/select/test_select.c @@ -0,0 +1,755 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include +#include +#include +#if ! defined( _WIN32) +#if ! defined( __ANDROID__ ) +#include +#endif +#endif +#include +#include "test_select.h" + + +#include "../../test_common/harness/testHarness.h" + + +#include "../../test_common/harness/kernelHelpers.h" +#include "../../test_common/harness/mt19937.h" +#include "../../test_common/harness/parseParameters.h" + + +//----------------------------------------- +// Static functions +//----------------------------------------- + +// initialize src1 and src2 buffer with values based on stype +static void initSrcBuffer(void* src1, Type stype, MTdata); + +// initialize the valued used to compare with in the select with +// vlaues [start, count) +static void initCmpBuffer(void* cmp, Type cmptype, uint64_t start, size_t count); + +// make a program that uses select for the given stype (src/dest type), +// ctype (comparison type), veclen (vector length) +static cl_program makeSelectProgram(cl_kernel *kernel_ptr, const cl_context context, Type stype, Type ctype, size_t veclen ); + +// Creates and execute the select test for the given device, context, +// stype (source/dest type), cmptype (comparison type), using max_tg_size +// number of threads. It runs test for all the different vector lengths +// for the given stype and cmptype. +static int doTest(cl_command_queue queue, cl_context context, + Type stype, Type cmptype, cl_device_id device); + +//----------------------------------------- +// Definitions and initializations +//----------------------------------------- + +// Define the buffer size that we want to block our test with +#define BUFFER_SIZE (1024*1024) +#define KPAGESIZE 4096 + + +// When we indicate non wimpy mode, the types that are 32 bits value will +// test their entire range and 64 bits test will test the 32 bit +// range. Otherwise, we test a subset of the range +// [-min_short, min_short] +static bool s_wimpy_mode = false; + +// Tests are broken into the major test which is based on the +// src and cmp type and their corresponding vector types and +// sub tests which is for each individual test. The following +// tracks the subtests +int s_test_cnt = 0; +int s_test_fail = 0; + +//----------------------------------------- +// Static helper functions +//----------------------------------------- + +// calculates log2 for a 32 bit number +int int_log2(size_t value) { + if( 0 == value ) + return INT_MIN; + +#if defined( __GNUC__ ) + return (unsigned) (8*sizeof(size_t) - 1UL - __builtin_clzl(value)); +#else + int result = -1; + while(value) + { + result++; + value >>= 1; + } + return result; +#endif +} + + +static void initSrcBuffer(void* src1, Type stype, MTdata d) +{ + unsigned int* s1 = (unsigned int *)src1; + size_t i; + + for ( i=0 ; i < BUFFER_SIZE/sizeof(cl_int); i++) + s1[i] = genrand_int32(d); +} + +static void initCmpBuffer(void* cmp, Type cmptype, uint64_t start, size_t count) { + int i; + assert(cmptype != kfloat); + switch (type_size[cmptype]) { + case 1: { + uint8_t* ub = (uint8_t *)cmp; + for (i=0; i < count; ++i) + ub[i] = (uint8_t)start++; + break; + } + case 2: { + uint16_t* us = (uint16_t *)cmp; + for (i=0; i < count; ++i) + us[i] = (uint16_t)start++; + break; + } + case 4: { + if (!s_wimpy_mode) { + uint32_t* ui = (uint32_t *)cmp; + for (i=0; i < count; ++i) + ui[i] = (uint32_t)start++; + } + else { + // The short test doesn't iterate over the entire 32 bit space so + // we alternate between positive and negative values + int32_t* ui = (int32_t *)cmp; + int32_t sign = 1; + for (i=0; i < count; ++i, ++start) { + ui[i] = (int32_t)start*sign; + sign = sign * -1; + } + } + break; + } + case 8: { + // We don't iterate over the entire space of 64 bit so for the + // selects, we want to test positive and negative values + int64_t* ll = (int64_t *)cmp; + int64_t sign = 1; + for (i=0; i < count; ++i, ++start) { + ll[i] = start*sign; + sign = sign * -1; + } + break; + } + default: + log_error("invalid cmptype %s\n",type_name[cmptype]); + } // end switch +} + +// Make the various incarnations of the program we want to run +// stype: source and destination type for the select +// ctype: compare type +static cl_program makeSelectProgram(cl_kernel *kernel_ptr, const cl_context context, Type srctype, Type cmptype, size_t vec_len) +{ + char testname[256]; + char stypename[32]; + char ctypename[32]; + char extension[128] = ""; + int err = 0; + + int i; // generic, re-usable loop variable + + const char *source[] = { + extension, + "__kernel void ", testname, + "(__global ", stypename, " *dest, __global ", stypename, " *src1,\n __global ", + stypename, " *src2, __global ", ctypename, " *cmp)\n", + "{\n" + " size_t tid = get_global_id(0);\n" + " if( tid < get_global_size(0) )\n" + " dest[tid] = select(src1[tid], src2[tid], cmp[tid]);\n" + "}\n" + }; + + + const char *sourceV3[] = { + extension, + "__kernel void ", testname, + "(__global ", stypename, " *dest, __global ", stypename, " *src1,\n __global ", + stypename, " *src2, __global ", ctypename, " *cmp)\n", + "{\n" + " size_t tid = get_global_id(0);\n" + " size_t size = get_global_size(0);\n" + " if( tid + 1 < size ) // can't run off the end\n" + " vstore3( select( vload3(tid, src1), vload3(tid, src2), vload3(tid, cmp)), tid, dest );\n" + " else if(tid + 1 == size)\n" + " {\n" + // If the size is odd, then we have odd * 3 elements, which is an odd number of scalars in the array + // If the size is even, then we have even * 3 elements, which is an even number of scalars in the array + // 3 will never divide evenly into a power of two sized buffer, so the last vec3 will overhang by 1 or 2. + // The only even number x in power_of_two < x <= power_of_two+2 is power_of_two+2. + // The only odd number x in power_of_two < x <= power_of_two+2 is power_of_two+1. + // Therefore, odd sizes overhang the end of the array by 1, and even sizes overhang by 2. + " size_t leftovers = 1 + (size & 1);\n" + " ", stypename, "3 a, b; \n" + " ", ctypename, "3 c;\n" + " switch( leftovers ) \n" + " {\n" + " case 2:\n" + " a.y = src1[3*tid+1];\n" + " b.y = src2[3*tid+1];\n" + " c.y = cmp[3*tid+1];\n" + " // fall through \n" + " case 1:\n" + " a.x = src1[3*tid];\n" + " b.x = src2[3*tid];\n" + " c.x = cmp[3*tid];\n" + " break;\n" + " }\n" + " a = select( a, b, c );\n" + " switch( leftovers ) \n" + " {\n" + " case 2:\n" + " dest[3*tid+1] = a.y;\n" + " // fall through \n" + " case 1:\n" + " dest[3*tid] = a.x;\n" + " break;\n" + " }\n" + " }\n" + "}\n" + }; + + if (srctype == kdouble) + strcpy( extension, "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" ); + + // create type name and testname + switch( vec_len ) + { + case 1: + strncpy(stypename, type_name[srctype], sizeof(stypename)); + strncpy(ctypename, type_name[cmptype], sizeof(ctypename)); + snprintf(testname, sizeof(testname), "select_%s_%s", stypename, ctypename ); + log_info("Building %s(%s, %s, %s)\n", testname, stypename, stypename, ctypename); + break; + case 3: + strncpy(stypename, type_name[srctype], sizeof(stypename)); + strncpy(ctypename, type_name[cmptype], sizeof(ctypename)); + snprintf(testname, sizeof(testname), "select_%s3_%s3", stypename, ctypename ); + log_info("Building %s(%s3, %s3, %s3)\n", testname, stypename, stypename, ctypename); + break; + case 2: + case 4: + case 8: + case 16: + snprintf(stypename,sizeof(stypename), "%s%d", type_name[srctype],(int)vec_len); + snprintf(ctypename,sizeof(ctypename), "%s%d", type_name[cmptype],(int)vec_len); + snprintf(testname, sizeof(testname), "select_%s_%s", stypename, ctypename ); + log_info("Building %s(%s, %s, %s)\n", testname, stypename, stypename, ctypename); + break; + default: + log_error( "Unkown vector type. Aborting...\n" ); + exit(-1); + break; + } + + /* + int j; + for( j = 0; j < sizeof( source ) / sizeof( source[0] ); j++ ) + log_info( "%s", source[j] ); + */ + + // create program + cl_program program; + + if (create_single_kernel_helper(context, &program, kernel_ptr, (cl_uint)(vec_len == 3 ? sizeof(sourceV3) / sizeof(sourceV3[0]) : sizeof(source) / sizeof(source[0])), vec_len == 3 ? sourceV3 : source, testname)) + { + log_error("Failed to build program (%d)\n", err); + return NULL; + } + + return program; +} + + +#define VECTOR_SIZE_COUNT 6 + +static int doTest(cl_command_queue queue, cl_context context, Type stype, Type cmptype, cl_device_id device) +{ + int err = CL_SUCCESS; + MTdata d; + const size_t element_count[VECTOR_SIZE_COUNT] = { 1, 2, 3, 4, 8, 16 }; + cl_mem src1 = NULL; + cl_mem src2 = NULL; + cl_mem cmp = NULL; + cl_mem dest = NULL; + void *ref = NULL; + void *sref = NULL; + + cl_ulong blocks = type_size[stype] * 0x100000000ULL / BUFFER_SIZE; + size_t block_elements = BUFFER_SIZE / type_size[stype]; + size_t step = s_wimpy_mode ? 256 : 1; + cl_ulong cmp_stride = block_elements * step; + + // It is more efficient to create the tests all at once since we + // use the same test data on each of the vector sizes + int vecsize; + cl_program programs[VECTOR_SIZE_COUNT]; + cl_kernel kernels[VECTOR_SIZE_COUNT]; + + if(stype == kdouble && ! is_extension_available( device, "cl_khr_fp64" )) + { + log_info("Skipping double because cl_khr_fp64 extension is not supported.\n"); + return 0; + } + + if (gIsEmbedded) + { + if (( stype == klong || stype == kulong ) && ! is_extension_available( device, "cles_khr_int64" )) + { + log_info("Long types unsupported, skipping."); + return 0; + } + + if (( cmptype == klong || cmptype == kulong ) && ! is_extension_available( device, "cles_khr_int64" )) + { + log_info("Long types unsupported, skipping."); + return 0; + } + } + + for (vecsize = 0; vecsize < VECTOR_SIZE_COUNT; ++vecsize) + { + programs[vecsize] = makeSelectProgram(&kernels[vecsize], context, stype, cmptype, element_count[vecsize] ); + if (!programs[vecsize] || !kernels[vecsize]) { + ++s_test_fail; + return -1; + } + } + + ref = malloc( BUFFER_SIZE ); + if( NULL == ref ){ log_error("Error: could not allocate ref buffer\n" ); goto exit; } + sref = malloc( BUFFER_SIZE ); + if( NULL == sref ){ log_error("Error: could not allocate ref buffer\n" ); goto exit; } + src1 = clCreateBuffer( context, CL_MEM_READ_ONLY, BUFFER_SIZE, NULL, &err ); + if( err ) { log_error( "Error: could not allocate src1 buffer\n" ); ++s_test_fail; goto exit; } + src2 = clCreateBuffer( context, CL_MEM_READ_ONLY, BUFFER_SIZE, NULL, &err ); + if( err ) { log_error( "Error: could not allocate src2 buffer\n" ); ++s_test_fail; goto exit; } + cmp = clCreateBuffer( context, CL_MEM_READ_ONLY, BUFFER_SIZE, NULL, &err ); + if( err ) { log_error( "Error: could not allocate cmp buffer\n" ); ++s_test_fail; goto exit; } + dest = clCreateBuffer( context, CL_MEM_WRITE_ONLY, BUFFER_SIZE, NULL, &err ); + if( err ) { log_error( "Error: could not allocate dest buffer\n" ); ++s_test_fail; goto exit; } + + + // We block the test as we are running over the range of compare values + // "block the test" means "break the test into blocks" + if( type_size[stype] == 4 ) + cmp_stride = block_elements * step * (0x100000000ULL / 0x100000000ULL); + if( type_size[stype] == 8 ) + cmp_stride = block_elements * step * (0xffffffffffffffffULL / 0x100000000ULL + 1); + + log_info("Testing..."); + d = init_genrand( gRandomSeed ); + uint64_t i; + for (i=0; i < blocks; i+=step) + { + void *s1 = clEnqueueMapBuffer( queue, src1, CL_TRUE, CL_MAP_WRITE, 0, BUFFER_SIZE, 0, NULL, NULL, &err ); + if( err ){ log_error( "Error: Could not map src1" ); goto exit; } + // Setup the input data to change for each block + initSrcBuffer( s1, stype, d); + + void *s2 = clEnqueueMapBuffer( queue, src2, CL_TRUE, CL_MAP_WRITE, 0, BUFFER_SIZE, 0, NULL, NULL, &err ); + if( err ){ log_error( "Error: Could not map src2" ); goto exit; } + // Setup the input data to change for each block + initSrcBuffer( s2, stype, d); + + void *s3 = clEnqueueMapBuffer( queue, cmp, CL_TRUE, CL_MAP_WRITE, 0, BUFFER_SIZE, 0, NULL, NULL, &err ); + if( err ){ log_error( "Error: Could not map cmp" ); goto exit; } + // Setup the input data to change for each block + initCmpBuffer(s3, cmptype, i * cmp_stride, block_elements); + + // Create the reference result + Select sfunc = (cmptype == ctype[stype][0]) ? vrefSelects[stype][0] : vrefSelects[stype][1]; + (*sfunc)(ref, s1, s2, s3, block_elements); + + sfunc = (cmptype == ctype[stype][0]) ? refSelects[stype][0] : refSelects[stype][1]; + (*sfunc)(sref, s1, s2, s3, block_elements); + + if( (err = clEnqueueUnmapMemObject( queue, src1, s1, 0, NULL, NULL ))) + { log_error( "Error: coult not unmap src1\n" ); ++s_test_fail; goto exit; } + if( (err = clEnqueueUnmapMemObject( queue, src2, s2, 0, NULL, NULL ))) + { log_error( "Error: coult not unmap src2\n" ); ++s_test_fail; goto exit; } + if( (err = clEnqueueUnmapMemObject( queue, cmp, s3, 0, NULL, NULL ))) + { log_error( "Error: coult not unmap cmp\n" ); ++s_test_fail; goto exit; } + + for (vecsize = 0; vecsize < VECTOR_SIZE_COUNT; ++vecsize) + { + size_t vector_size = element_count[vecsize] * type_size[stype]; + size_t vector_count = (BUFFER_SIZE + vector_size - 1) / vector_size; + + if((err = clSetKernelArg(kernels[vecsize], 0, sizeof dest, &dest) )) + { log_error( "Error: Cannot set kernel arg dest! %d\n", err ); ++s_test_fail; goto exit; } + if((err = clSetKernelArg(kernels[vecsize], 1, sizeof src1, &src1) )) + { log_error( "Error: Cannot set kernel arg dest! %d\n", err ); ++s_test_fail; goto exit; } + if((err = clSetKernelArg(kernels[vecsize], 2, sizeof src2, &src2) )) + { log_error( "Error: Cannot set kernel arg dest! %d\n", err ); ++s_test_fail; goto exit; } + if((err = clSetKernelArg(kernels[vecsize], 3, sizeof cmp, &cmp) )) + { log_error( "Error: Cannot set kernel arg dest! %d\n", err ); ++s_test_fail; goto exit; } + + + // Wipe destination + void *d = clEnqueueMapBuffer( queue, dest, CL_TRUE, CL_MAP_WRITE, 0, BUFFER_SIZE, 0, NULL, NULL, &err ); + if( err ){ log_error( "Error: Could not map dest" ); ++s_test_fail; goto exit; } + memset( d, -1, BUFFER_SIZE ); + if( (err = clEnqueueUnmapMemObject( queue, dest, d, 0, NULL, NULL ) ) ){ log_error( "Error: Could not unmap dest" ); ++s_test_fail; goto exit; } + + err = clEnqueueNDRangeKernel(queue, kernels[vecsize], 1, NULL, &vector_count, NULL, 0, NULL, NULL); + if (err != CL_SUCCESS) { + log_error("clEnqueueNDRangeKernel failed errcode:%d\n", err); + ++s_test_fail; + goto exit; + } + + d = clEnqueueMapBuffer( queue, dest, CL_TRUE, CL_MAP_READ, 0, BUFFER_SIZE, 0, NULL, NULL, &err ); + if( err ){ log_error( "Error: Could not map dest # 2" ); ++s_test_fail; goto exit; } + + if ((*checkResults[stype])(d, vecsize == 0 ? sref : ref, block_elements, element_count[vecsize])!=0){ + log_error("vec_size:%d indx: 0x%16.16llx\n", (int)element_count[vecsize], i); + ++s_test_fail; + goto exit; + } + + if( (err = clEnqueueUnmapMemObject( queue, dest, d, 0, NULL, NULL ) ) ) + { + log_error( "Error: Could not unmap dest" ); + ++s_test_fail; + goto exit; + } + } // for vecsize + } // for i + + if (!s_wimpy_mode) + log_info(" Passed\n\n"); + else + log_info(" Wimpy Passed\n\n"); + +exit: + if( src1 ) clReleaseMemObject( src1 ); + if( src2 ) clReleaseMemObject( src2 ); + if( cmp ) clReleaseMemObject( cmp ); + if( dest) clReleaseMemObject( dest ); + if( ref ) free(ref ); + if( sref ) free(sref ); + + free_mtdata(d); + for (vecsize = 0; vecsize < VECTOR_SIZE_COUNT; vecsize++) { + clReleaseKernel(kernels[vecsize]); + clReleaseProgram(programs[vecsize]); + } + ++s_test_cnt; + return err; +} + +static void printUsage( void ) +{ + log_info("test_select: [-cghw] [test_name|start_test_num] \n"); + log_info(" default is to run the full test on the default device\n"); + log_info(" -w run in wimpy mode (smoke test)\n"); + log_info(" test_name will run only one test of that name\n"); + log_info(" start_test_num will start running from that num\n"); +} + +static void printArch( void ) +{ + log_info( "sizeof( void*) = %d\n", (int) sizeof( void *) ); + +#if defined( __APPLE__ ) + +#if defined( __ppc__ ) + log_info( "ARCH:\tppc\n" ); +#elif defined( __ppc64__ ) + log_info( "ARCH:\tppc64\n" ); +#elif defined( __i386__ ) + log_info( "ARCH:\ti386\n" ); +#elif defined( __x86_64__ ) + log_info( "ARCH:\tx86_64\n" ); +#elif defined( __arm__ ) + log_info( "ARCH:\tarm\n" ); +#else +#error unknown arch +#endif + + int type = 0; + size_t typeSize = sizeof( type ); + sysctlbyname( "hw.cputype", &type, &typeSize, NULL, 0 ); + log_info( "cpu type:\t%d\n", type ); + typeSize = sizeof( type ); + sysctlbyname( "hw.cpusubtype", &type, &typeSize, NULL, 0 ); + log_info( "cpu subtype:\t%d\n", type ); + +#endif +} + + + + +//----------------------------------------- +// main +//----------------------------------------- +int main(int argc, const char* argv[]) { + int i; + cl_device_type device_type = CL_DEVICE_TYPE_DEFAULT; + cl_platform_id platform_id; + long test_start_num = 0; // start test number + const char* exec_testname = NULL; + cl_device_id device_id; + uint32_t device_frequency = 0; + uint32_t compute_devices = 0; + + + test_start(); + + argc = parseCustomParam(argc, argv); + if (argc == -1) + { + test_finish(); + return -1; + } + + // Maybe we want turn off sleep + + // Check the environmental to see if there is device preference + char *device_env = getenv("CL_DEVICE_TYPE"); + if (device_env != NULL) { + if( strcmp( device_env, "gpu" ) == 0 || strcmp( device_env, "CL_DEVICE_TYPE_GPU" ) == 0 ) + device_type = CL_DEVICE_TYPE_GPU; + else if( strcmp( device_env, "cpu" ) == 0 || strcmp( device_env, "CL_DEVICE_TYPE_CPU" ) == 0 ) + device_type = CL_DEVICE_TYPE_CPU; + else if( strcmp( device_env, "accelerator" ) == 0 || strcmp( device_env, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 ) + device_type = CL_DEVICE_TYPE_ACCELERATOR; + else if( strcmp( device_env, "default" ) == 0 || strcmp( device_env, "CL_DEVICE_TYPE_DEFAULT" ) == 0 ) + device_type = CL_DEVICE_TYPE_DEFAULT; + else + { + log_error( "Unknown CL_DEVICE_TYPE environment variable: %s.\nAborting...\n", device_env ); + abort(); + } + } + + // Check for the wimpy mode environment variable + if (getenv("CL_WIMPY_MODE")) { + log_info("*** Detected CL_WIMPY_MODE env\n"); + s_wimpy_mode = 1; + } + + // Determine if we want to run a particular test or if we want to + // start running from a certain point and if we want to run on cpu/gpu + // usage: test_selects [test_name] [start test num] [run_long] + // default is to run all tests on the gpu and be short + // test names are of the form select_[src/dest type]_[cmp_type] + // In the long test, we run the full range for any type >= 32 bits + // and 32 bits subset for the 64 bit value. + for (i=1; i < argc; ++i) { + const char *arg = argv[i]; + if (arg == NULL) + break; + + if (arg[0] == '-') + { + arg++; + while(*arg != '\0') + { + switch(*arg) { + case 'h': + printUsage(); + return 0; + case 'w': // Wimpy mode + s_wimpy_mode = true; + break; + default: + log_error( " <-- unknown flag: %c (0x%2.2x)\n)", *arg, *arg ); + printUsage(); + return 0; + } + arg++; + } + } + else { + char* t = NULL; + long num = strtol(argv[i], &t, 0); + if (t != argv[i]) + test_start_num = num; + else if( 0 == strcmp( argv[i], "CL_DEVICE_TYPE_CPU" ) ) + device_type = CL_DEVICE_TYPE_CPU; + else if( 0 == strcmp( argv[i], "CL_DEVICE_TYPE_GPU" ) ) + device_type = CL_DEVICE_TYPE_GPU; + else if( 0 == strcmp( argv[i], "CL_DEVICE_TYPE_ACCELERATOR" ) ) + device_type = CL_DEVICE_TYPE_ACCELERATOR; + else if( 0 == strcmp( argv[i], "CL_DEVICE_TYPE_DEFAULT" ) ) + device_type = CL_DEVICE_TYPE_DEFAULT; + else if( 0 == strcmp( argv[i], "randomize" ) ) { + gRandomSeed = (cl_uint) time( NULL ); + log_info("\nRandom seed: %u.\n", gRandomSeed ); + } else { + // assume it is a test name that we want to execute + exec_testname = argv[i]; + } + } + } + + + int err; + + // Get platform + err = clGetPlatformIDs(1, &platform_id, NULL); + checkErr(err,"clGetPlatformIDs failed"); + + // Get Device information + err = clGetDeviceIDs(platform_id, device_type, 1, &device_id, 0); + checkErr(err,"clGetComputeDevices"); + + err = clGetDeviceInfo(device_id, CL_DEVICE_TYPE, sizeof(cl_device_type), &device_type, NULL); + checkErr(err,"clGetComputeConfigInfo 1"); + + size_t config_size = sizeof( device_frequency ); +#if MULTITHREAD + if( (err = clGetDeviceInfo(device_id, CL_DEVICE_MAX_COMPUTE_UNITS, config_size, &compute_devices, NULL )) ) +#endif + compute_devices = 1; + + config_size = sizeof(device_frequency); + if((err = clGetDeviceInfo(device_id, CL_DEVICE_MAX_CLOCK_FREQUENCY, config_size, &device_frequency, NULL ))) + device_frequency = 1; + + //detect whether profile of the device is embedded + char profile[1024] = ""; + if( (err = clGetDeviceInfo(device_id, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL ) ) ){} + else if( strstr(profile, "EMBEDDED_PROFILE" ) ) + { + gIsEmbedded = 1; + } + + + log_info( "\nCompute Device info:\n" ); + log_info( "\tProcessing with %d devices\n", compute_devices ); + log_info( "\tDevice Frequency: %d MHz\n", device_frequency ); + + printDeviceHeader( device_id ); + printArch(); + + log_info( "Test binary built %s %s\n", __DATE__, __TIME__ ); + if (s_wimpy_mode) { + log_info("\n"); + log_info("*** WARNING: Testing in Wimpy mode! ***\n"); + log_info("*** Wimpy mode is not sufficient to verify correctness. ***\n"); + log_info("*** It gives warm fuzzy feelings and then nevers calls. ***\n\n"); + } + + cl_context context = clCreateContext(NULL, 1, &device_id, notify_callback, NULL, NULL); + checkNull(context, "clCreateContext"); + + cl_command_queue queue = clCreateCommandQueueWithProperties(context, device_id, 0, NULL); + checkNull(queue, "clCreateCommandQueue"); + + + if (exec_testname) { + // Parse name + // Skip the first part of the name + bool success = false; + if (strncmp(exec_testname, "select_", 7) == 0) { + int i; + Type src_type = kTypeCount; + Type cmp_type = kTypeCount; + char* sptr = (char *)strchr(exec_testname, '_'); + if (sptr) { + for (++sptr, i=0; i < kTypeCount; i++) { + if (strncmp(sptr, type_name[i], strlen(type_name[i])) == 0) { + src_type = (Type)i; + break; + } + } + sptr = strchr(sptr, '_'); + if (sptr) { + for (++sptr, i=0; i < kTypeCount; i++) { + if (strncmp(sptr, type_name[i], strlen(type_name[i])) == 0) { + cmp_type = (Type)i; + break; + } + } + } + } + if (src_type != kTypeCount && cmp_type != kTypeCount) { + success = true; + log_info("Testing only select_%s_%s\n", + type_name[src_type], type_name[cmp_type]); + if (doTest(queue, context, src_type, cmp_type, device_id) != 0) + log_error("*** select_%s_%s FAILED ***\n\n", + type_name[src_type], type_name[cmp_type]); + } + } + if (!success) { + log_error("can not find test:%s", exec_testname); + return -1; + } + } + else { + int src_type, j; + int test_num; + test_num = 0; + for (src_type = 0; src_type < kTypeCount; ++src_type) { + for (j = 0; j < 2; ++j) { + Type cmp_type = ctype[src_type][j]; + if (++test_num < test_start_num) { + log_info("%d) skipping select_%s_%s\n", test_num, + type_name[src_type], type_name[cmp_type]); + } + else { + log_info("%d) Testing select_%s_%s\n", + test_num, type_name[src_type], type_name[cmp_type]); + if (doTest(queue, context, (Type)src_type, cmp_type, device_id) != 0) + log_error("*** %d) select_%s_%s FAILED ***\n\n", test_num, + type_name[src_type], type_name[cmp_type]); + } + } + } + } + + int error = clFinish(queue); + if (error) { + log_error("clFinish failed: %d\n", error); + } + + clReleaseContext(context); + clReleaseCommandQueue(queue); + + if (s_test_fail == 0) { + if (s_test_cnt > 1) + log_info("PASSED %d of %d tests.\n", s_test_cnt, s_test_cnt); + else + log_info("PASSED test.\n"); + } else if (s_test_fail > 0) { + if (s_test_cnt > 1) + log_error("FAILED %d of %d tests.\n", s_test_fail, s_test_cnt); + else + log_error("FAILED test.\n"); + } + + test_finish(); + return s_test_fail; +} diff --git a/test_conformance/select/test_select.h b/test_conformance/select/test_select.h new file mode 100644 index 00000000..a0edcf29 --- /dev/null +++ b/test_conformance/select/test_select.h @@ -0,0 +1,117 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef TESTSELECTS_INCLUDED_H +#define TESTSELECTS_INCLUDED_H + +#include "../../test_common/harness/compat.h" + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +// Enable the test to be used with ATF +#if USE_ATF +// export BUILD_WITH_ATF=1 +#include +#define test_start() ATFTestStart() +#define log_info ATFLogInfo +#define log_error ATFLogError +#define test_finish() ATFTestFinish() +#else +#define test_start() +#define log_info printf +#define log_error printf +#define test_finish() +#endif // USE_ATF + + +// Defines the set of types we support (no support for double) +typedef enum { + kuchar = 0, + kchar = 1, + kushort = 2, + kshort = 3, + kuint = 4, + kint = 5, + kfloat = 6, + kulong = 7, + klong = 8, + kdouble = 9, + kTypeCount // always goes last +} Type; + + +// Support max vector size of 16 +#define kVectorSizeCount 6 +#define kMaxVectorSize 16 + + +// Type names and their sizes in bytes +extern const char *type_name[kTypeCount]; +extern const size_t type_size[kTypeCount]; + +// Associated comparison types +extern const Type ctype[kTypeCount][2]; + +// Reference functions for the primitive (non vector) type +typedef void (*Select)(void *dest, void *src1, void *src2, void *cmp, size_t c); +extern Select refSelects[kTypeCount][2]; + +// Reference functions for the primtive type but uses the vector +// definition of true and false +extern Select vrefSelects[kTypeCount][2]; + +// Check functions for each output type +typedef size_t (*CheckResults)(void *out1, void *out2, size_t count, size_t vectorSize); +extern CheckResults checkResults[kTypeCount]; + +// Helpful macros + +// The next three functions check on different return values. Returns -1 +// if the check failed +#define checkErr(err, msg) \ + if (err != CL_SUCCESS) { \ + log_error("%s failed errcode:%d\n", msg, err); \ + return -1; \ + } + +#define checkZero(val, msg) \ + if (val == 0) { \ + log_error("%s failed errcode:%d\n", msg, err); \ + return -1; \ + } + +#define checkNull(ptr, msg) \ + if (!ptr) { \ + log_error("%s failed\n", msg); \ + return -1; \ + } + +// When a helper returns a negative one, we want to return from main +// with negative one. This helper prevents me from having to write +// this multiple time +#define checkHelperErr(err) \ + if (err == -1) { \ + return err; \ + } + + +#endif // TESTSELECTS_INCLUDED_H diff --git a/test_conformance/select/util_select.c b/test_conformance/select/util_select.c new file mode 100644 index 00000000..59a9dc82 --- /dev/null +++ b/test_conformance/select/util_select.c @@ -0,0 +1,734 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../../test_common/harness/compat.h" + +#include +#include "test_select.h" + + +//----------------------------------------- +// Definitions and initializations +//----------------------------------------- + + +const char *type_name[kTypeCount] = { + "uchar", "char", + "ushort", "short", + "uint", "int", + "float", "ulong", "long", "double" }; + +const size_t type_size[kTypeCount] = { + sizeof(cl_uchar), sizeof(cl_char), + sizeof(cl_ushort), sizeof(cl_short), + sizeof(cl_uint), sizeof(cl_int), + sizeof(cl_float), sizeof(cl_ulong), sizeof(cl_long), sizeof( cl_double ) }; + +const Type ctype[kTypeCount][2] = { + { kuchar, kchar }, // uchar + { kuchar, kchar }, // char + { kushort, kshort}, // ushort + { kushort, kshort}, // short + { kuint, kint }, // uint + { kuint, kint }, // int + { kuint, kint }, // float + { kulong, klong }, // ulong + { kulong, klong }, // long + { kulong, klong } // double +}; + + +//----------------------------------------- +// Reference functions +//----------------------------------------- + +void refselect_1i8(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_char *d, *x, *y, *m; + d = (cl_char*) dest; + x = (cl_char*) src1; + y = (cl_char*) src2; + m = (cl_char*) cmp; + for (i=0; i < count; ++i) { + d[i] = m[i] ? y[i] : x[i]; + } +} + +void refselect_1u8(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_uchar *d, *x, *y; + cl_char *m; + d = (cl_uchar*) dest; + x = (cl_uchar*) src1; + y = (cl_uchar*) src2; + m = (cl_char*) cmp; + for (i=0; i < count; ++i) { + d[i] = m[i] ? y[i] : x[i]; + } +} + +void refselect_1i16(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_short *d, *x, *y, *m; + d = (cl_short*) dest; + x = (cl_short*) src1; + y = (cl_short*) src2; + m = (cl_short*) cmp; + + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_1u16(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_ushort *d, *x, *y; + cl_short *m; + d = (cl_ushort*) dest; + x = (cl_ushort*) src1; + y = (cl_ushort*) src2; + m = (cl_short*) cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_1i32(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_int *d, *x, *y, *m; + d = (cl_int*)dest; + x = (cl_int*)src1; + y = (cl_int*)src2; + m = (cl_int*)cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_1u32(void *dest, void *src1, void *src2, void *cmp, size_t count){ + size_t i; + cl_uint *d, *x, *y; + cl_int *m; + d = (cl_uint*)dest; + x = (cl_uint*)src1; + y = (cl_uint*)src2; + m = (cl_int*)cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_1i64(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_long *d, *x, *y, *m; + d = (cl_long*) dest; + x = (cl_long*) src1; + y = (cl_long*) src2; + m = (cl_long*) cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_1u64(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_ulong *d, *x, *y; + cl_long *m; + d = (cl_ulong*) dest; + x = (cl_ulong*) src1; + y = (cl_ulong*) src2; + m = (cl_long*) cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_1i8u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_char *d, *x, *y; + cl_uchar *m; + d = (cl_char*) dest; + x = (cl_char*) src1; + y = (cl_char*) src2; + m = (cl_uchar*) cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_1u8u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_uchar *d, *x, *y, *m; + d = (cl_uchar*) dest; + x = (cl_uchar*) src1; + y = (cl_uchar*) src2; + m = (cl_uchar*) cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_1i16u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_short *d, *x, *y; + cl_ushort *m; + d = (cl_short*) dest; + x = (cl_short*) src1; + y = (cl_short*) src2; + m = (cl_ushort*) cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_1u16u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_ushort *d, *x, *y, *m; + d = (cl_ushort*) dest; + x = (cl_ushort*) src1; + y = (cl_ushort*) src2; + m = (cl_ushort*) cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_1i32u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_int *d, *x, *y; + cl_uint *m; + d = (cl_int*) dest; + x = (cl_int*) src1; + y = (cl_int*) src2; + m = (cl_uint*) cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_1u32u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_uint *d, *x, *y, *m; + d = (cl_uint*) dest; + x = (cl_uint*) src1; + y = (cl_uint*) src2; + m = (cl_uint*) cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_1i64u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_long *d, *x, *y; + cl_ulong *m; + d = (cl_long*) dest; + x = (cl_long*) src1; + y = (cl_long*) src2; + m = (cl_ulong*) cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_1u64u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_ulong *d, *x, *y, *m; + d = (cl_ulong*) dest; + x = (cl_ulong*) src1; + y = (cl_ulong*) src2; + m = (cl_ulong*) cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_ffi(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_int *d, *x, *y; + cl_int *m; + d = (cl_int*) dest; + x = (cl_int*) src1; + y = (cl_int*) src2; + m = (cl_int*) cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_ffu(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_uint *d, *x, *y; + cl_uint *m; + d = (cl_uint*) dest; + x = (cl_uint*) src1; + y = (cl_uint*) src2; + m = (cl_uint*) cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_ddi(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_long *d, *x, *y; + cl_long *m; + d = (cl_long*) dest; + x = (cl_long*) src1; + y = (cl_long*) src2; + m = (cl_long*) cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void refselect_ddu(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_long *d, *x, *y; + cl_ulong *m; + d = (cl_long*) dest; + x = (cl_long*) src1; + y = (cl_long*) src2; + m = (cl_ulong*) cmp; + for (i=0; i < count; ++i) + d[i] = m[i] ? y[i] : x[i]; +} + +void vrefselect_1i8(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_char *d, *x, *y, *m; + d = (cl_char*) dest; + x = (cl_char*) src1; + y = (cl_char*) src2; + m = (cl_char*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x80) ? y[i] : x[i]; +} + +void vrefselect_1u8(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_uchar *d, *x, *y; + cl_char *m; + d = (cl_uchar*) dest; + x = (cl_uchar*) src1; + y = (cl_uchar*) src2; + m = (cl_char*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x80) ? y[i] : x[i]; +} + +void vrefselect_1i16(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_short *d, *x, *y, *m; + d = (cl_short*) dest; + x = (cl_short*) src1; + y = (cl_short*) src2; + m = (cl_short*) cmp; + + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x8000) ? y[i] : x[i]; +} + +void vrefselect_1u16(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_ushort *d, *x, *y; + cl_short *m; + d = (cl_ushort*) dest; + x = (cl_ushort*)src1; + y = (cl_ushort*)src2; + m = (cl_short*)cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x8000) ? y[i] : x[i]; +} + +void vrefselect_1i32(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_int *d, *x, *y, *m; + d = (cl_int*) dest; + x = (cl_int*) src1; + y = (cl_int*) src2; + m = (cl_int*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x80000000) ? y[i] : x[i]; +} + +void vrefselect_1u32(void *dest, void *src1, void *src2, void *cmp, size_t count){ + size_t i; + cl_uint *d, *x, *y; + cl_int *m; + d = (cl_uint*) dest; + x = (cl_uint*) src1; + y = (cl_uint*) src2; + m = (cl_int*) cmp; + + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x80000000) ? y[i] : x[i]; +} + +void vrefselect_1i64(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_long *d, *x, *y, *m; + d = (cl_long*) dest; + x = (cl_long*) src1; + y = (cl_long*) src2; + m = (cl_long*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x8000000000000000LL) ? y[i] : x[i]; +} + +void vrefselect_1u64(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_ulong *d, *x, *y; + cl_long *m; + d = (cl_ulong*) dest; + x = (cl_ulong*) src1; + y = (cl_ulong*) src2; + m = (cl_long*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x8000000000000000LL) ? y[i] : x[i]; +} + +void vrefselect_1i8u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_char *d, *x, *y; + cl_uchar *m; + d = (cl_char*) dest; + x = (cl_char*) src1; + y = (cl_char*) src2; + m = (cl_uchar*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x80U) ? y[i] : x[i]; +} + +void vrefselect_1u8u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_uchar *d, *x, *y, *m; + d = (cl_uchar*) dest; + x = (cl_uchar*) src1; + y = (cl_uchar*) src2; + m = (cl_uchar*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x80U) ? y[i] : x[i]; +} + +void vrefselect_1i16u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_short *d, *x, *y; + cl_ushort *m; + d = (cl_short*) dest; + x = (cl_short*) src1; + y = (cl_short*) src2; + m = (cl_ushort*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x8000U) ? y[i] : x[i]; +} + +void vrefselect_1u16u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_ushort *d, *x, *y, *m; + d = (cl_ushort*) dest; + x = (cl_ushort*) src1; + y = (cl_ushort*) src2; + m = (cl_ushort*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x8000U) ? y[i] : x[i]; +} + +void vrefselect_1i32u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_int *d, *x, *y; + cl_uint *m; + d = (cl_int*) dest; + x = (cl_int*) src1; + y = (cl_int*) src2; + m = (cl_uint*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x80000000U) ? y[i] : x[i]; +} + +void vrefselect_1u32u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_uint *d, *x, *y, *m; + d = (cl_uint*) dest; + x = (cl_uint*) src1; + y = (cl_uint*) src2; + m = (cl_uint*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x80000000U) ? y[i] : x[i]; +} + +void vrefselect_1i64u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_long *d, *x, *y; + cl_ulong *m; + d = (cl_long*) dest; + x = (cl_long*) src1; + y = (cl_long*) src2; + m = (cl_ulong*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x8000000000000000ULL) ? y[i] : x[i]; +} + +void vrefselect_1u64u(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_ulong *d, *x, *y, *m; + d = (cl_ulong*) dest; + x = (cl_ulong*) src1; + y = (cl_ulong*) src2; + m = (cl_ulong*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x8000000000000000ULL) ? y[i] : x[i]; +} + +void vrefselect_ffi(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_uint *d, *x, *y; + cl_int *m; + d = (cl_uint*) dest; + x = (cl_uint*) src1; + y = (cl_uint*) src2; + m = (cl_int*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x80000000) ? y[i] : x[i]; +} + +void vrefselect_ffu(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_uint *d, *x, *y; + cl_uint *m; + d = (cl_uint*) dest; + x = (cl_uint*) src1; + y = (cl_uint*) src2; + m = (cl_uint*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x80000000U) ? y[i] : x[i]; +} + +void vrefselect_ddi(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_ulong *d, *x, *y; + cl_long *m; + d = (cl_ulong*) dest; + x = (cl_ulong*) src1; + y = (cl_ulong*) src2; + m = (cl_long*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x8000000000000000LL) ? y[i] : x[i]; +} + +void vrefselect_ddu(void *dest, void *src1, void *src2, void *cmp, size_t count) { + size_t i; + cl_ulong *d, *x, *y; + cl_ulong *m; + d = (cl_ulong*) dest; + x = (cl_ulong*) src1; + y = (cl_ulong*) src2; + m = (cl_ulong*) cmp; + for (i=0; i < count; ++i) + d[i] = (m[i] & 0x8000000000000000ULL) ? y[i] : x[i]; +} + +// Define refSelects +Select refSelects[kTypeCount][2] = { + { refselect_1u8u, refselect_1u8 }, // cl_uchar + { refselect_1i8u, refselect_1i8 }, // char + { refselect_1u16u, refselect_1u16 }, // ushort + { refselect_1i16u, refselect_1i16 }, // short + { refselect_1u32u, refselect_1u32 }, // uint + { refselect_1i32u, refselect_1i32 }, // int + { refselect_ffu, refselect_ffi }, // float + { refselect_1u64u, refselect_1u64 }, // ulong + { refselect_1i64u, refselect_1i64 }, // long + { refselect_ddu, refselect_ddi } // double +}; + +// Define vrefSelects (vector refSelects) +Select vrefSelects[kTypeCount][2] = { + { vrefselect_1u8u, vrefselect_1u8 }, // cl_uchar + { vrefselect_1i8u, vrefselect_1i8 }, // char + { vrefselect_1u16u, vrefselect_1u16 }, // ushort + { vrefselect_1i16u, vrefselect_1i16 }, // short + { vrefselect_1u32u, vrefselect_1u32 }, // uint + { vrefselect_1i32u, vrefselect_1i32 }, // int + { vrefselect_ffu, vrefselect_ffi }, // float + { vrefselect_1u64u, vrefselect_1u64 }, // ulong + { vrefselect_1i64u, vrefselect_1i64 }, // long + { vrefselect_ddu, vrefselect_ddi } // double +}; + + +//----------------------------------------- +// Check functions +//----------------------------------------- +size_t check_uchar(void *test, void *correct, size_t count, size_t vector_size) { + const cl_uchar *t = (const cl_uchar *) test; + const cl_uchar *c = (const cl_uchar *) correct; + size_t i; + + for(i = 0; i < count; i++) + if (t[i] != c[i]) { + log_error("\n(check_uchar) Error for vector size %ld found at 0x%8.8lx (of 0x%8.8lx): " + "*0x%2.2x vs 0x%2.2x\n", vector_size, i, count, c[i], t[i]); + return i + 1; + } + + return 0; +} + +size_t check_char(void *test, void *correct, size_t count, size_t vector_size) { + const cl_char *t = (const cl_char *) test; + const cl_char *c = (const cl_char *) correct; + size_t i; + + + for( i = 0; i < count; i++ ) + if( t[i] != c[i] ) { + log_error("\n(check_char) Error for vector size %ld found at 0x%8.8lx (of 0x%8.8lx): " + "*0x%2.2x vs 0x%2.2x\n", vector_size, i, count, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +size_t check_ushort(void *test, void *correct, size_t count, size_t vector_size) { + const cl_ushort *t = (const cl_ushort *) test; + const cl_ushort *c = (const cl_ushort *) correct; + size_t i; + + + for( i = 0; i < count; i++ ) + if(t[i] != c[i]) { + log_error("\n(check_ushort) Error for vector size %ld found at 0x%8.8lx (of 0x%8.8lx): " + "*0x%4.4x vs 0x%4.4x\n", vector_size, i, count, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +size_t check_short(void *test, void *correct, size_t count, size_t vector_size) { + const cl_short *t = (const cl_short *) test; + const cl_short *c = (const cl_short *) correct; + size_t i; + + + for (i = 0; i < count; i++) + if(t[i] != c[i]) { + log_error("\n(check_short) Error for vector size %ld found at 0x%8.8lx (of 0x%8.8lx): " + "*0x%8.8x vs 0x%8.8x\n", vector_size, i, count, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +size_t check_uint(void *test, void *correct, size_t count, size_t vector_size) { + const cl_uint *t = (const cl_uint *) test; + const cl_uint *c = (const cl_uint *) correct; + size_t i; + + + + for (i = 0; i < count; i++) + if(t[i] != c[i]) { + log_error("\n(check_uint) Error for vector size %ld found at 0x%8.8lx (of 0x%8.8lx): " + "*0x%8.8x vs 0x%8.8x\n", vector_size, i, count, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +size_t check_int(void *test, void *correct, size_t count, size_t vector_size) { + const cl_int *t = (const cl_int *) test; + const cl_int *c = (const cl_int *) correct; + size_t i; + + + for(i = 0; i < count; i++) + if( t[i] != c[i] ) { + + log_error("\n(check_int) Error for vector size %ld found at 0x%8.8lx (of 0x%8.8lx): " + "*0x%8.8x vs 0x%8.8x\n", vector_size, i, count, c[i], t[i]); + log_error("\n(check_int) Error for vector size %ld found at 0x%8.8lx (of 0x%8.8lx): " + "*0x%8.8x vs 0x%8.8x\n", vector_size, i+1, count,c[i+1], t[i+1]); + log_error("\n(check_int) Error for vector size %ld found at 0x%8.8lx (of 0x%8.8lx): " + "*0x%8.8x vs 0x%8.8x\n", vector_size, i+2, count,c[i+2], t[i+2]); + log_error("\n(check_int) Error for vector size %ld found at 0x%8.8lx (of 0x%8.8lx): " + "*0x%8.8x vs 0x%8.8x\n", vector_size, i+3, count,c[i+3], t[i+3]); + if(i) { + log_error("\n(check_int) Error for vector size %ld found just after 0x%8.8lx: " + "*0x%8.8x vs 0x%8.8x\n", vector_size, i-1, c[i-1], t[i-1]); + } + return i + 1; + } + + return 0; +} + +size_t check_ulong(void *test, void *correct, size_t count, size_t vector_size) { + const cl_ulong *t = (const cl_ulong *) test; + const cl_ulong *c = (const cl_ulong *) correct; + size_t i; + + + for( i = 0; i < count; i++ ) + if( t[i] != c[i] ) { + log_error("\n(check_ulong) Error for vector size %ld found at 0x%8.8lx (of 0x%8.8lx): " + "*0x%16.16llx vs 0x%16.16llx\n", vector_size, i, count, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +size_t check_long(void *test, void *correct, size_t count, size_t vector_size) { + const cl_long *t = (const cl_long *) test; + const cl_long *c = (const cl_long *) correct; + size_t i; + + + for(i = 0; i < count; i++ ) + if(t[i] != c[i]) { + log_error("\n(check_long) Error for vector size %ld found at 0x%8.8lx (of 0x%8.8lx): " + "*0x%16.16llx vs 0x%16.16llx\n", vector_size, i, count, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +size_t check_float( void *test, void *correct, size_t count, size_t vector_size ) { + const cl_uint *t = (const cl_uint *) test; + const cl_uint *c = (const cl_uint *) correct; + size_t i; + + + for( i = 0; i < count; i++ ) + /* Allow nans to be binary different */ + if ((t[i] != c[i]) && !(isnan(((float *)correct)[i]) && isnan(((float *)test)[i]))) { + log_error("\n(check_float) Error for vector size %ld found at 0x%8.8lx (of 0x%8.8lx): " + "*0x%8.8x vs 0x%8.8x\n", vector_size, i, count, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +size_t check_double( void *test, void *correct, size_t count, size_t vector_size ) { + const cl_ulong *t = (const cl_ulong *) test; + const cl_ulong *c = (const cl_ulong *) correct; + size_t i; + + + + for( i = 0; i < count; i++ ) + /* Allow nans to be binary different */ + if ((t[i] != c[i]) && !(isnan(((double *)correct)[i]) && isnan(((double *)test)[i]))) { + log_error("\n(check_double) Error for vector size %ld found at 0x%8.8lx (of 0x%8.8lx): " + "*0x%16.16llx vs 0x%16.16llx\n", vector_size, i, count, c[i], t[i] ); + return i + 1; + } + + return 0; +} + +CheckResults checkResults[kTypeCount] = { + check_uchar, check_char, check_ushort, check_short, check_uint, + check_int, check_float, check_ulong, check_long, check_double }; diff --git a/test_conformance/spir/CMakeLists.txt b/test_conformance/spir/CMakeLists.txt new file mode 100644 index 00000000..b0a3e020 --- /dev/null +++ b/test_conformance/spir/CMakeLists.txt @@ -0,0 +1,45 @@ +function (install_spir_artifacts suite_name) + install(FILES "${suite_name}.zip" DESTINATION ${CLConf_OUT_DIR}/spir) +endfunction() + +include_directories(${CLConf_SRC_DIR}/test_common) + +clconf_add_executable( + test_spir + main.cpp + datagen.cpp + run_build_test.cpp + run_services.cpp + kernelargs.cpp) + +target_link_libraries( + test_spir${CLConf_SUFFIX} + miniz${CLConf_SUFFIX} +) + +install_spir_artifacts(api) +install_spir_artifacts(atomics) +install_spir_artifacts(basic) +install_spir_artifacts(compile_and_link) +install_spir_artifacts(commonfns) +install_spir_artifacts(conversions) +install_spir_artifacts(geometrics) +install_spir_artifacts(enum_values) +install_spir_artifacts(half) +install_spir_artifacts(kernel_attributes) +install_spir_artifacts(kernel_image_methods) +install_spir_artifacts(images_kernel_read_write) +install_spir_artifacts(images_samplerlessRead) +install_spir_artifacts(integer_ops) +install_spir_artifacts(math_brute_force) +install_spir_artifacts(printf) +install_spir_artifacts(profiling) +install_spir_artifacts(relationals) +install_spir_artifacts(select) +install_spir_artifacts(sampler_enumeration) +install_spir_artifacts(vec_align) +install_spir_artifacts(vec_step) +install_spir_artifacts(binary_type) +install(FILES "khr.csv" DESTINATION ${CLConf_OUT_DIR}/spir) +#Add any other runtime directories you need here. +# end of file # diff --git a/test_conformance/spir/Makefile b/test_conformance/spir/Makefile new file mode 100644 index 00000000..377cfdd3 --- /dev/null +++ b/test_conformance/spir/Makefile @@ -0,0 +1,45 @@ +ifdef BUILD_WITH_ATF +ATF = -framework ATF +USE_ATF = -DUSE_ATF +endif + +SRCS = main.cpp datagen.cpp kernelargs.cpp run_build_test.cpp run_services.cpp \ + ../../test_common/miniz/miniz.c \ + ../../test_common/harness/testHarness.c \ + ../../test_common/harness/errorHelpers.c \ + ../../test_common/harness/typeWrappers.cpp \ + ../../test_common/harness/mt19937.c \ + ../../test_common/harness/os_helpers.c \ + ../../test_common/harness/kernelHelpers.c + +SOURCES = $(abspath $(SRCS)) + + +LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries +LIBPATH += -L. + +FRAMEWORK = ${SOURCES} +HEADERS = +TARGET = test_spir +INCLUDE = +COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 +#COMPILERFLAGS = -c -Wall -g -DUSE_LOCAL_THREADS +CC = c++ +CFLAGS = $(COMPILERFLAGS) $(RC_CFLAGS) ${USE_ATF} +CXXFLAGS= $(COMPILERFLAGS) $(RC_CFLAGS) ${USE_ATF} +LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF} + +OBJECTS := ${SOURCES:.c=.o} +OBJECTS := ${OBJECTS:.cpp=.o} + +TARGETOBJECT = +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES) + +clean: + rm -f $(TARGET) $(OBJECTS) + +.DEFAULT: + @echo The target \"$@\" does not exist in Makefile. diff --git a/test_conformance/spir/api.zip b/test_conformance/spir/api.zip new file mode 100644 index 0000000000000000000000000000000000000000..1d3f67f80ac12b2e354a6374d588792df7b7e7cd GIT binary patch literal 1089254 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%0A|jy7L}D!L##_vilM$9czfx$koPBaAtaM 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%0DJk#!fbX|W&#Ywy%C8DsQTj6-y; zj=1qlT2v2B_37Y0<(UA1UX-f;rhx#UoGi$?@3r2AkkCFGlzy$-mUJm^eryt5A; z0f*rT7%Nh)`EQ&>{%@Qy{TI$^v=Ln|vrfAZvLLW(|0_VfH%D++jUlZY1JXH=lGc+_{diJbhdOf4q6t zChc^-vrq`&z4g`$hFG3VPd$is2?k~-W-!?o)ZJH#ILNn%H!?nc*%2caR-2T0QO1=` zndm7ZS|Yr9mDX(%XY?NU_!s&gh@>gcrxe;c%e|+15>j_!C1y3J5w$|HbKgjl?oilE z$RrxDEn&;pxIan5t1MKt)}tj*W>YvfjmM`Sw?glo5mt*)zafQib)a3ul#I*j8(00h z;2NIzUhQ^1d{%MErM5S1(~rq^FcbzaVR_sN*09KR)M3=~DMKQmmmXttxL8=_{1m0R zDy_MWG2hWq z|GpbvZ~%ZG|LlHTj18S^9T-^ut)}DOCJ}ossk(xa-^24O?sS&Ju^MU*!oCAzr|=SC z#pEhdr>yaDKOR3jU6Y;2%*1=@k<^4ZC;DRqm3G1y}CdEg_o2BAOMwpd?z%Y<&?DL z=o1r7C7|A`$=qXLMJEe{vbP!iXY+Gs-fnJnBKf6sKWbLBR1uU?qOa~pSxYZ7^gF9h z-I8_z-$iGqk`UCNku4eP*rTJkZeA6moAJCAN0ITtGfeExRKWJLBERdxv?tD zZTKu@vYS}^ZHI-&E%#KMwMNI%@Q;z~*?7p+!0fi{-!`Fnfl z_b^@DGrI=@XLH|@DDD!$a-@9UYO{Sc-jyEuadPhx@P(cfo7uv6XBU%lSA&PgF?AQk zy89L*RrkYiKMm_g0&dAZv0sO0m+Dk3#b>XYe z$rusqjgoURrfBbf&9!E%95^!P*sl8B09}dNG*s= zKDp{Y-y^C_4v8i+pCB4~V?{6$6SD>gMbamP0Y`Q5YOwqgR2o^Cun{#oI4aYq{?;-p zlzvy7E8&s@4$*olRPZUP`Pkv+AK$}wyhvbX(nie3vwiP^f-wWog=Ve&nw!+xuq`0`A0pmdJ1k~=-{KLZ@oJ1!wC z8ysE042~IUGV!ycE-s9^q~$6KQjWV)ET7FFA9sBP7tsNwVRv;bt6CldCc>iA~Zf$aNo*{!skN*o}4+lT?~qJSo0G1|fD(P9(4A ztv?f{6MAe5vFA1J?_3zkt?3=o`ns&i>{}ww;a_6h3uf`03e@yYm@Hpvxog1MGAkQ~ z2}J;I=;%WME~Dj1#PV+v_|Ac26Tz<%b^{|(FB_QjA+SEs1ldDr%RK-bKO$j5zrsbAb(q4c7 zC+U#<<@HIW<{`sNRN8h^IFfOmDYeA>^)SrVw{eM!y7KDsW4SHJ;CcHs{_91Ff;|X% zy(Wp#!d#iB#Ra|C`gc*66S5vy?f>$cVrr<_HhnW8@IPY0ztVpH-|F1Uq;A29j{KAI z4d<#-253ncl43h+mqvC1fhq&mmQVc(sTQO5W`agzb@xU)_KYgU=2{=Iu~9*^<5Wc< zG&GIyN`^rM6PWMKxpzX5rC9`yVY6LS;Z8mmcW-Xn&)>mOSMS~1*XL<8apGN2zT%Jo z<7l|CKmbcS_y^EEv@sLqhi7|pO!2-JlF0@EDlTuebUrByo+9Q~^61CdDCuXJd*M^c z9E4uGH{LlG0b5O&!xeXM&%qvTaVW_ki&y{-_BAlT>TMdyG>ErKSPezyTv4k(*K~%D zU)*@|0ZNe#J5aATcFP@-` z7nbUIAaT({HCPjG67vW$XAxcFA@`+~K|u+T3cAlF(H7+_f*Bq9Fy~UnzOxYQyQoSc zW|UkFQ8}e$0LRn9_SxSO6!8}ci4e#*D z(7dfszSmJa-ckJQJhjqcl64;STzMi7H1%^P7mLRsS0MU3iI&L=64pwNUzV#+<5OL^ zm_Q!w20O&9osF_;KAQB@T*rgUzj}TAIRTpYK~9u5{4{|o02b~Z#jmd@Er+cZ9Ijs-N&fB*5+mwdWDCmaN8Rm;V5nkv0>| z%c^|;!M-#w2sVKf56C*A;%~2#tm>ud&XTN8H4iBV$f=W2a24hp1v2M@ti-!!EE+Xk zypT9IpN|0#JXYOOt8Qw~SWZ)lsP|Pke=iHxLBk?h%@toz%Vv;MaW0m@d1CRmWNj|= zMVY$?gc{uA(+U?07;>O@_{MX-blE%#mUPpZ0T7Ly(IS*|)q){}^p^Y)nDl|T!C8R9 z`odWncKaI^!33e3K>Y@6R?6HKDAv7iBZ%S;T&kQ{rc{xz zdcYp}$ihK2lr*t9Vt0#v8EKJIbsespLh`}hIpoa+*Tihir`oGO+%S3IIAL@e?$I@A9 zIc&}kRXIQF-)cJO#TIG@vKZZd^8nGDAVq!*h{Sb46M`O_1*JeH~)QUOD0% zY~N`bh^j!ky6H;1T*^x`w=Dg#6>DC zE_N$XNjdHqnlbBD-cE1!RlzeQ^4@(ru@Nn=e?k?p-`POX#Wm3wy+t4Ia&-&s76d0O z%zB2EZ5luf`kUZCwCa16D6&A0zOz&CHVPRp!3m#QZZ61^QAyvU@A$`P-gGhP!;*jD z@o!8heg}<(gCUddM_lV9EDcV{E}vRH;j}(y0`x|6*oOYOW)#Qv|@9-7Hdd5*hrU}%*Qs|7Os5O%%y8h~Eo)giZ;poGXC&H9{(Lr+6g8yy^2WJNOJ|QuXTX2|Q=K_2 zQa`>4Nbv2LVfeRH(SOv@v;Et+#goLg;pNqud{d<5a(^*(y&a<n%$u_FUbf#bXffRiTlT^E&^-$Y@BeoI$})3 zL5{-V+N>MO2!nEqAQIKUgQ3bvRMW@G$)Sd~^bhc_ClZK@e7J#ZzdGZfWUb9pnX$wE zJ_MBcJikzjl*i3lYGyO#T4A*YlBrPTJ3+x*;X{2XOcHNBEc!D3$nJ&96#PLDB84T~ zgyT?|GP>)xMnOQrx=zBH9NVxPRH57|$VRspmt!=qV^z^HM~p+mZ|_37GXO=w94P3` z>ntZaA&^KEY?InZUr2P@Q9z2=P(Qw*Ezhi<( z&~9v@EuBvt=EN9=G9|N4{##Xpcz5F%TZBYw5u4Q>_pAr~P7o5Zf3|ntehInz828{; z#1sW-mS?@hcW_j$X?*%Q;MBUiyGeL3Bd+hbqa%^^xPb021gdaipVI8g8swV$D+n_x zu&NlYEW~b136^Whqb{$HFqG%f7 zyL5johxlc+Gug=WDCu$mXu!_R)>*X4y3_$zH6Dz`v zBQ#c&60JStIUU0DOqlAEAd>3hv>v`^v!6Zd(AR1*tz(Wqloqj>`=$p271Z|01aAvzZaI`qyLJTnrWMFcv)8eU|I-^($F73iHrq*rbB{fL79mZGxu;b z-iu%U$=&u`NSte;loxQ@eWY3 zPqD*DsJIA%V@e?ng9<-qF7o8m9-Jp`p|=segn2&{ApI859T~H+w)fTIGBqF@-Mj;( z^LtsrBZU^_d!-<(#x_i~V*$}b6jUl9@O@5uc!qnxFuhGA`SOTq{n1-e4;HePu@?QH zKj;i03UjZ`An-eK*__?kQ0ohSdoepTuO8~6Cca>{Z2Uar9k-A%Q7rwOvKV%-#%L^j zs@MHvGHi&H%37H^ZWE4xwAlqazWYx>S{}X8A@Nh8d;8{DCA#O@HUnIf1fPx-59v$cU+KmE?%qkv#lIUxLp)8Wv1`*%ZU2ZOf6 zKgK#hx)tG&yxm>Hc?*!zIyi*HAeLYJmVwjXweC0~-*BTRWbqQ0%@oC_rU2hy5)z!D z(TvIff45*7wC=Exqw5rTo690T8J6vK-SzOjp-sGt+{)nEb6ijBdL$ZBdRZJApX~c~ zqn>CIAv*8gXsdud(!vZqN+rkO)+92xtLJv!P6W%jX|owtt6H&~nm@gG6@As#&%6nE z|GJ}%`w`gD<*sNYy{z`qIk0WM+-y-UpVAqV1WClLb^_0A?TQT6A)w0op|qoU{CEqsLlQ8Q#XLow)h-{U3w#zV}@rwj2-mY!mn9n(fx1HuUDzhD?QDCrrcBfD)^Uzm{T zu6dq2{~GD@`uf=F;H2fqOEFAU`sNHRE*Sm_oNEC8m}nE`7+_g`{+s^~lI;Xh6bsVh zn0IB^y>{sOb^+m_zc^!6QMzrtiZ+`9gMT{#{dl!WU?`7=9}Zhbtp3fJ+~L~G8;S`1 za*ZGo-N1tmjx@UIQ;xKl;|G>k_)Zs6$O~=UU>@LQ6%@@oXYvkG^ayYvIjImZqH^4& z=l=ScT;;xGy{dQ^VwJH7NIx{?U7LDL$~kujIUu+;f?0^cp2&UV`({ zH4*lck^grg^DvRy4uyQ zb+YIl81pd9od;fn+-dNAQrH^0tDO#JzoHQ)s|otm_Z^CpKx;B)4%+tpZjy}|Cu>Z_ zM?g7{3ev8PhQM&Z@B0PK$v40>gT0YtaXD2x-x4L1NYHA5DR_k)|5>GX!MlPcUk+G@7)g z)7!{E84OSVDwWsQ#+#W1_q6XGnC3G43pkqmq8B~l6klv*5Ngc znMpCS<{}RdtpV9$=6Wj;is|-00j6F6y24;IQg=M7TqXs6M>O(4ZBZP5yfM=zdFd2^ zUD|>zx5+2%i=alv`rXQE_esy@GDKn{mpwkERla&3)(n%VW+A}b>LEHofWp>dh4pS3 zwR2~BGZ1d2lu^M(JgW;wErG`#CmcA%b5F>vLXbo{q0R;8q17LFnf&%FFdiVxNN}-G z5v388Lrm|O4#ta*m3+o@uvd6PsE;81y*4UJtx!@=YChigZR`APQLdR0(4lSqG)Zz4&y}d^1oOh3Xa;?eBgwY$ZcebrMatd$YZbsD z*P-BOO%`aJy19Rg_Q+Y2cgAbsT}51P{Q~`aNkd1oi;(`U-hzSug+=kd)!YA&H2+-2 zHO);y2@)cJ?sV;NP1e&|uRU-QnP{2Y(Q>wjZFSw1D7zBQJdSYepKOBJA~Lp75nx7* z$Hr7L=9z@37+a?HzvlZ#;biJJ;X(xhD_6@saBkA&Z5AH_BDRSj5as~YR zD-eZ)%?|ulb!OjnP4a)O>KOm6R@Z+8&~T$`T+xJAk9Td-oD3tOQL)d@u~KxErqWk2 zO^kk3q89f!Sqo@L)IUhlS+pqWi~CR)8X4`6)H`EqrVj;q|1gKK4@3+Zj8)+cglXER z(q!D9?qV$bSeZI?+7o6vKb zVT~2U?zAHLA}vhh^J~>0phL2E_8Z2v5%3h3a?s6Z(}P*9I}8bO~#E=L&b^LRCO&*V7I8(}xwnJG$;PVuwFi zHW}J}&g5UL-VW)5LP5H~xwx-B(R;Wew5R7yOu4K=U&PzW>>dN|&hne0G|$E|4Hrg0 zo!mNHdSd(%C0uqj6-D8!oC$z=XtxeWZ5GuJfpm{$Aj_h|`99ioFikR!1sMmA{cY!D zGQAUR>w-bAa?B&UvG7+94smR^ok@0qZK*QQqDQg14@5|{poo|G{smn>dDF8}jsa%O z_kbK~(!oRLwLl!T8yC$a_!3D@9aBQiPTYXpk6e*DUJtc!FH4z&5h@#{qX z7@$MdOe!gUEJ}sPwI(N1TH%-H!ia?ft0>XrOYH4lN#l0e?Ev z+cps1%HEXAm)fuwYy`);K%{2FS|)1uidEjYB@s+(GJZI+Pnz;N9F}v%sdNdKc}pw< z!Wg;?2va4>jy0PQylC4jy|X80&9$x(+6=`x+Y}U2dUmbd3>xv##6AkfxQHiS zSbL?Vm!_Y%MnzZsqBEM~sR-B-3h|d!U_LK2#!5Y_?D3z*WO#1xHEI5m*T(bv$y=w^OwAT!ZeOnj3Ca;)Rs>tCtc2McJ5tLS{UOx0%`8q?L87eYSl?rOM=3YE zu9#I&2JzW(6<0dVfPR1avqf$UAo z$}W-CVht7koMaM&9}<=)$V;3gfjl;{j4rtX|L8HZ#lWXjz+r$kPnZCSTqHDyB%$Y7 z4zzb2Px;(0&Nq$h=#;sVIG$qd?p^dW!np4+Q|9d)iq$E$vm%um*DJI~LeD}cV?-2V zIMI-E9xyp9NLC|@h$X=U8(Lm%ed)X(n23?)B&-fZu}89lhWKzuCGUfguR0NzPIQN4 zb_XL3Ccs7c0prVQuK1I=L~{0L#grKEbDYPM=c2|qS`Z!5+7=YbCjkDD0*6+2;u zoHK3&1$r4icghNUS$wSBFPpjs%0q9{^e*$^i$~^MUqrGvTCZ9)>@~lBm_LxbmZt8# z`dRVvsb@o~L0oLVG)TV7YZ<`uC_X=!3HWDk(F{4k@l9t02T#@C6yKwdzK3cQ2)~Zz zyFEA2QV9)s!emi9-_Da9_Mfy61m>8H{fGsd8d`nLn);RF_ZN{5nRYb~1&F-$zasMg z-6Zut5_yw{;2p&G)JH06S*bV?3($bhn-3x5itB!S=+$)M ze`E5~wUePoYNV>Mdp*qq4hCJbbM{)9V*DWi0uh>5f!4lm9h<#jnd;*OEC2%;i{>hB zkP78E)atAV#HUxC4YzkmxsQEy4meed<{1~D$2Nl%jK}(u5TpxTB8>q*n*m>!0sbF4 zzxxlJulWjnmv0_3Kt!;9azJdit4Xs1>BN+c9y3AIbL>I-1%`Ol15Cmz+?$n$VHzlJ zeh_S5k4-j44ahIXJRMWA?WK(PR`-BzM`094Lj1eTz%cp_Q8oC+u{CXB4pIJ^-w>YX z55AF0bZq4VW5>b;z}*)@v&0{G1ovebS(Ay7Ed0iu>8e{={{buYr$JXbO>F)z^GWeE%Os+I$9!UIg@X| z%yTzk3;P8aJSjlKQ=jq66LS~ClzAwYt_^W!iTHx?BA_9r%p=#5O5P;ilr0&LPy$S) zT#*e%g=Z}l`Y8%ne{Nge=_w*ygJD}5+M6wkLGzjouG=4UrWUbqO(Qj-Nn0}%r=55P z#Yk6e5#NNTs*(j5z>avJUG&uIwf$JC;39tFtifX1Mf?yx9APd5-57Wja#Td4B2xW!a}v9?R2!*d^0<0ULuiC~8DPV;5c9#Q?_&V_jGD z(PM`JdRWg41Hf;oww^wUCRf{nT>14NFcLGrGFnD+^jvV|5TNmGg`8r_2nqX*bghAf zqyn?s(p)E|L~5*FeLD{&$B+lt>7c&wNT^Q(p!}(czHr7Q8FN>TMFWl2g38>L@sy9h zsF{C){UnO#&tWA^3z5lV9{;WLgsCar=0*Re^HBhuZ%KMn^8GiRFU^v{c@b@QFQljV zL+3Tx85GO@P3Lj{)OnJB*LjXVbeb1-XHV-e2M|UDEI+FSTQ%!%WbA`ZU>^Tl&T7JQINGN zU0!Gk#qP&nVtsG@UT%4kP!YMmQxJNDE-G`EUwo|=hi!(?FT>1C4KVo9%J{T_)-X9A zK+i1bYYz4c!OENjic~vbn<$I3Aw`8uN2v!=TEFTb5Tmx*6gxSgP+Zqc>#a zqZMkoHEMrZu%qC*^cw@%*(bmg;Xm!0{Bvw${#TBf`2a2kpqOFyeB@sVjeCU_R5)H# z=fMz2x&pJ%*(A<^1cNqB(HX3TqPb-F%rt>XYp1Nto#wl0Qt0+~$0Z<%qfEQ31(>#rO&L0J?=RsP7v07G57yQZ@|X$#ui^{jjDTwj-0L$`7;F%mM_XbuUC zD?VS%)ccMeZGyLc#F|55J~ z5~FU!=^8RrD{F3RVj;rs^OV%s(J0_QVVuXH(wTo^t$=@QM=WciQNh~hoDiXuRU*0| zl<{+~hp~eRD;DA6_?Ehy5&x?4Jc9aGG&E@gr+f7?v6S_m|Jry{aBDV5UKdtlM=QK` zjJ~^r0B;BqJ~$_FUNU$f3w4J)aI8A!u<#5TQ2z+Ov$+2TH1CK|%UQ98kTxi%Y;RDO zq9!*-##A)@ffC)Uurpj|5|7&`DeATNC3m?(N(4G%;A8?%C-7YcpDEcnQNX+bQg7fS zIbQ&@dmr&Kl#)MRizd5vGcOM~E_r}LtI6s4WPvrxtYevs29HauAz<~FGVRyur2&=p zU4WPl!||2450M01zf$jl#}Bm5qsyb_h-eWp6>k$2*mb~Muv>n{zd(U)Ni9Z{c};Yb z+$hQSLs-|Y4`amV7ivw^mEo0R45B#$#ME$!HBmL1CYc$-(K_Gyt8Nwq#FXhgVGV(? z3$*@~vCY+wkIj>m%|@Sw9XpsT>HZVUPN{w_oK8#PkMCh8<}y&L_S^8EH_e-)Z&o2I zWS`0c+>eOv&8655l;zW*Ip!l_nGyq>$orAvN2i-t{3Uv|hnF*i!kKo~wDR$8%E(!N z$k5?7?7|fLz_`%t)w}uhdE|iFC)cQ2y+$uY6CyX0Q!;t(tmpBSt8InFdv<>;I3YRftZv+p zJn9|dsHI+?4IsaxG_d!b$(C(tLs8#EZu2g1ifUSD@Q;aofb7_CIYH*BEm0g!y zhP3Cfcl`;+npnRAn?<@q3qnA)(;2QY)~kt3|8=_(jGoyZ97;NfD-tmSrtdRKeE3|% zO_HUCNOX$=ii7HENsesUP`m>6f;&MndKtOpf@CArK1mr{xj`=X%C54whfmys_%j;Y zkcUswLQFlIq8i5#4sj)^@m zx%onpPKT^Q@c>vB=QZmmGcI#6&s|}o{jg$IWf30Kf_cvT%HuYpqM=vlCF~D)I@UKl zt$RQ-r#aNbKol6i@wT;6^J2x_gsb(^j)b{pqCGQsEXgORtD$XYC0C$CeG}+zS#+J^ z13*&Ggj~LD&n%qid zk^=1)%nF?SCPhD}IWF2+xW&^1~M&eKQm7*kG`S`$Wn<`4~fvcZf#Gv^^FN8?^ zX>9_iQ0l_GLpTXPj#qc@FtR3kAut^T$enL*U?P)l#K=|f}^kA3mfGH zncp+=!L09}{?hl+chgcm1@H{e|B+|>ceBuc^bB<|^@CMiAq@Vwb5K*QYFTIqU?|IM z?fzy2np4)-JS(7lx^ZiZdj-wKXnF&E$2(u3>HoSf{}}O-ULBCXtIL zjMUb)$1wsbX=^}LWas1C=GNUhpai5#ik>-N-C(%~8CKbKCJl9FUU7|^Ls}W?-av>C4 z7$ju}wP5g+6*DEWdJHi|U1+RD(5^$eM~@we-nV4Fz4WMg#AVb6h#FP9CX=F6+sFpP?mVus_1Z>CaLr zCZH?I6WEG+(onXI%1?GRG5WRl1$en&Mg%%jfovj&hv*@j*Sa_-FtJ&pDrh8o_D@pkFWF+XiQgc-Z0D^X zoIT)SSv5t49mZ6+ut`t&3z8jWh%R%h0Y52Sg5xpYB2$g2Wno|e=?L^yZEM@8R6IetiPm=9u%y!#zg zMcEPC-N^#YsDWzbW;H`RnHsZo7KXXqUthW2+Tu2{Yk-5f#<7%lb|s>9DMNUc;CLm* zR22(U+0(<9kX&O!9i3li1V7=B6b~T5nfC?I5PDVh@snc;XAvD1f*0V0x)efPB&l4OH8S^)8O=L&-F{Su+({R zV5S_0{Ts}yv|bsq96;mk4|JIuC@fn~jb?xBvFRt*`KGt&4}pU@9>Q#>WZS;b>E8Nm zFpawXHV(}lYpL|S@K>q>K7etk=Z3|1^t`P2KsD-DTL7LUC|u%MhPu0?hIq2_svueiyfdR)LZ8rawi?UBVW4n;tF<-*^a8<^m@)$sNwZA0 z_c*g!5T&U&rTc?FWi|DSflm<{STLHQi8ujqS`aB2XtCwYz@L@fh+7hu%X+#rKwWSm zOV!|A6(%5Ghz7%lvj=;VHtF%4FMP-8%BbyibqJ}gEf{L;4dEJ~RL4JzG76+3tz}Yl zRaRh(evx?(G*B_6_Pq@hZ7Ep&WfI@XI6gLITHI?=CAS&iDm&1!B4)ChoreZ-sWqbo znh~GVx{QfcU_o7$uS-3Ol{JIPSR*q*z()t{<{iA#Ujsd{FNpZo|qv1sMKa02yboi4L0 zqh*Bs0h9g*=c*6T!ZbW|pF+1U9-&RwVcs-re=-T!X@j4_mMKY=g94xw^jY#KZ-P_9 zAZi@2UN#g3*(cepS6BUqZ|HOe{q_yujX!*Y*diDT<`3VXeBXZAy@SXC^kZV)5E8rI zhNH@8hCxsPe8UxSH$7k6OoHk%znY@7&;!|t!t5GGHyMB1G4K#SlsX&ZRUw@0&G&4sX9lU+9vdM*+XGxVT0zO>d$@6Pi@9C5Nj^;4?xcx*pS7YZYODO*U3 z$K(ygv&V9nQ-PI}@XY}dFv_(|j-vZIDJz>3OY=xS5pzkUg?63q2KJQJaUnN8!Ct9W zu+5mh+Olp2BJCjG<1`O`_@yD;rnp!wwA}s_fmuGi`pc|wOr{tsK|9WvkUkaHpIj z_49{AiNkFx;&_YauwFdVf|cvzwMCvlrQ_{GHm0(V{3X9n+Dm}(w5R&vjDC}6SJTU1 zHlfnL;!_0veLBSQx9E^Q;3OMvcTv%i@LAjUd>Ti)r9kU6=bMO$#>VL23KWzAmrI0| zaV>+FZ&vva1fz3vr(!3jNABAOL}Vm52;+-nysVKhHZ>&C1~Htw*oEKFO5^ff-_`&n z+edm>O8Bl$FWFmsM?72aQ&(=6HZX~4vm;FB9Do7Kb3p?t#DHfO0n}2!N=`aP8V&B{ ztRSwl8ns60^UL%TO>9b|PHIyWB{sE7>#e)TKzvu#0g~*+WXszvwd|5!oNW~+3pO5` zJZc=Nt4_E9j{-xaVS;J!H<`gbG@x;*uNu9~b%+APX2+gn0Y>USFq>hjY)UQYl-=|a zya9PBVMZM67?n%w4(ya*@m17AtxD~LVr6I#xT*MpA;v1mU4hwQMygOJh?lq9Ak0t* zoEO7eCB@L&yKH@YCBo0=MT#}KF5=4~g}oc_>-f#XdZ<@V52(DcNc`B&VnQw0*L_KV zmqTyg?(A4WdDLrJOlPrx0cdYZ!IrfYjQ|#C9n)=*z9d$C-b{uZU4|4b^}7ZDA=+&^ zGu`ZsY+Cz99GH}GbWIuN_Uv&W%WFr5i=@{u-k<1!itmYpwHz4cs@ONLmzQUXan8j! zV{!=gto;&Js7s1V+$2MMU{!*hq^{a1)^AdSpBcv}OQ0ncbNl@GCm{mO*>uXeCb@#_ zC>cyDCrreV{ECZo%?Wp%nYGp*5-CNb+Hg+r;&@ATD3@Gfq z@4a6l^ZI%rUTTbYU+EV2o)>$+)4O0B;}pVKmE&1C#jSHinTX5*_ivmh~=WW=d z)*Xka>X-+x45Mr#EFz!|FFvFly~P5jGqcVh<|DF%*%s#zw*c$DIGxdLll<`8^)0x+OQGF23v& zTYTZ=+HX80<1YoK;s*SK4$eh@(7oX!w*}HW5c(@pJ$P#9A9$!G`(9iq7NXUD+X}4O zbH>JGgHxYBwmw(}FD{aP@2e7z`?Qp4h?_P3cQ4Bi%1veE$He_8x<+6CADXeJqS>Gw zgw_r1T6spr%csqf?S%=;^G86j=cjpxPK=&E*fJR({!wqx?j1$1ivOf&jSGq0Zz#fR zA;TyOxC0k5Tf(&mnVS+|-ed|R)awt0=8z!t%+#3tuHdi~_vNR990rVmsKq9*lc^!xcUFh?{lZKu26j$u z|5zqNBpXp#9m?LobPd`(s$FM>n>U|o!K*u=b@|PScrzNYVt#Rq-F`aX?R)=Ap-{ko z!&t@7Z`XO9V#!iUEuo_g&SiptZz4k0Vh9yIGcE+g=Mm_%Xk|&@d*j~95KqO`2EB!J z%Ugr=ylek6EFXLW(G>p&4?U7DdZ9oDH>!T~-P@+Vw*0ge3Q^U*+*&SP!h{H~V&Utz z8$2N(hzN+Ka_(2FI$zS)W<7B$W9(DWy&x->#ezQ5$?2(qEAa@hGs%X#TAFqn1&!_+ zjk_fDIRy9IU%J2kQq%OIz#|d-_u0^&693=LL;v3--t-I^9}oa&UWy-Ll)z<*R-A)Y z8ByT*u#rw_b*h1-Lg?TEXnW3G_Lc9^BhO=V@aGBheasXjgS1NZ=;SY$%_#4Jc@L3? zjr*-Cvw1!A(4%KkH`K}Bens`%ntvX5(Hsve$X5!biB09eU0Kt@pZ&4vIm}Qq=X?Qn zvKYZqIIDOk3iR1=$Kgz z$yj7|IU*ZPWg{U1ZOGq|JeX>(FwivrCTmdry`9X0yC`mH8<)xwc0PjegT)6n(UH?F zZ<;|M%)z}jpMjhK&4sdO{rR2|O-bZYKtGYgwiomofbpZ|Y5(a0PYV9Fk!ZKy8=iMp?hVUa*aSL0 z>oMqc*dD@l0^T~Pi6zTC;9~>bQ*+ff2k+GSk#^WRXnE5mcJeXe1L(rcG0=D~$e=A< z`*J`)bWQc*dWvE>SH=3dl*UQZl4^1-74%eR(Vz;O-St4u2sK}3Q%*b zB7`HXR72V?fh_5#o+CBm0v+%^;CT?7}NA!)3!zIGE&d ztynTQ%>R@+De4A@0h~615KOnovB)~qSuod1RAj;`uwXm(ftOT0l|S#F#z(UsZrQf} zNCnS%k!@LFbR5Sj861N(3u9`hDyAY&(_c5-tl#LwJ~TJ%Ce)5b1cNay*m|+$efYk4 zjK#Br!tmZ?L1-?D73T0NBDANz{=r#@WAt-Xlw3mAd?YG5>$B3cza^D~Nt_v6G8Q?7 zs7kqJ@~}z=Pb##%8c?eF6D^GT#Goe-J=L})D81%3HXKGA5H_meDg0v99~l6kOQG$^ zI$Ij6*m^mdH8#jB{O#y^PXX=rVf)1S;K7h+8*o{U?;&x^ti;%}1NR)vri6!`I%g__b(?2CcmtKOGu3?`F30?!>kR8$!DjFn-F&sU@nP8i0y)DmK zbRa&0{Z8)^w9b9r+E}|ow>Q2COgc9qhVBqlk?VDL@&xSFGH=A=!kc1eO));{D3-Q4 zSOKX((TxPRV%BbV_WQ$$;}Srfxa! zb>cE7BJ0=hA?|Z&Uoz(UPGJiH5{|@A2Qq6pi5}<=ghIVb8gy%9PV-u~n?uxhyq86f zUYT4>@Jku)<*yo(3F$2L@ul~y3s7a zLz*t(ULgLcx#txK43COXqw4aoWcV)mpxYI-IKuiPd?$HUx|1^XEa;VCMn}e~=;R zl0V2$d@ya~S(f(5uHiV<8LlQIvdDzE78M%Hj~G9P@S!gC4|C1kgRY~Tj-$tqoTHpa zx2uJQI*VxBft)Z#nZ?4PLCg>vA&P5NZ@tvGM#(bE4G%@Z?h60q;)E=oV>&C;rQFm7 z1f>NNE#X-um5thlHp*{htq;xW-Lms_D5M$E@bF?GGKHF=;Z2l`m6*CFNR^c_38)dE zUgTyl-?;?LU~aN{EOQI?k}(6a6^)jq&28^v4u$V`loMchz(GbPK*5Dgw6&(eO#=GV z##91aq>v{d$+m>98%xPY6nuBN=f8gT2;AB@OTOxJ@7LeJNyZ3+r=quhwqyvVteYch zNj-yh@Cx;Bz~j`_X`!2D=yv~vKOl(!!cCl~3{ADr zdt8t$hisicz#P*2A-MMDWPDi@33NwGv=m`x;jX1V*3l9bdK=m@ONF_poBWZiV>$F`PD_H|qe*>)^*DhUrSi7(7l0deE0 zZ(dUg%+8#kMqBrXW~H(aFN7s`8<3@xzW++9ioPG28G{MYj_Sb#Z zA-b|cKgGDtGu9B8x;X0plF{{h5&TuzBw(~<`LqU$kzmgbUZZ5+2VRpg;>YC3j;-uZ z58V2C&9Q2e*vZ~+iNec=dd2k(Tb^p3Uv)^OQ?+X%&PlWN3o#Fg(#i@w&NZa_IH@*I z6wa{sT1BG~|3PC&PDB4^m^$Oto*%XB^j;hoI@_N=sUL_pHE(HbVA{&mHVLgCM_biA z-5)QWvFP>P1Fdt0oel7^Jr+@K6lD0QCqGNNsQe_!QcXmd0Q_|>T{haGxq=5xpRoi$ zL+;(rztNDs<>^Pbm%uAsh4jOz9qvW1UGeDXPi`z`5?g{iWZBdGSkO}}*9OS+86(NGStZ*_kW-mE%pgY!Mp(69 z(1l@$IE{!K6q~%Mi*Ofal+`@Bt0$gR?x+q>EtAB#*aXc)$4EVZzo`Bk+Faqr6# z)N+Z(&Vnl0$7)=RB9iTck_gxBBMcARs!P@s)+i9T$kwodVn} zaju4GMYZ_2!+6%D$=aW)eFBxz^;aNHzpoGC62dSXQ#1PxL#}Yebm7bWfH$X7wFi7$ z1HaL-9j1|$B7_!n=tG2Gb?7PW{kJ|bJ-Y|@ka_ll2PZ*pV@$esQnNtfLd!@}oUa)ATPw{(=oZW{r8E z1%EDSsPPF=yV_neHw@VZ>VBj$ZA&<=I{!ds4mC zx5!m@zxS8NJ%J>s@ZUj#zX^r@Vi*725cD6RP$=VXCm4<24PO?ypWz4J};U0rQf z7#S&JgN3})^fP*3M29oMt_6Pd>fcz{2(OZoRQ${h4~)c);9%!anK^^>aEV%0TJ)MzxnZzRuyG?KE8oGb*bu!1)*c_Cp=IR4A@ zp>;mz(UEmN=~2yc$?>BS?C{ha<^!;nc2i+p9DoXW8Vm~}rk{NAYqgfXYm4LMoRP_( zsdcpo#3D!IvClzP4aH>k-vVs4V#VHdbofN@Va7s~w--hL&l(&A)9GK5A(5$h&hG7T z_xB<~o#TO4t8F_vWxLuI>U*CM^2Q+P(E!Y$1PgL1?VKN~livUrLBtIdlEiHu3kaU( znixVBYX%+Yg7x=TcUa8NvogNUT)CF%=mlrn2X9T|ruqJ6Rve1KPAZLmIL0IeW6jzg zUmq8HbLU6;s7WsFarSUjVv-H|vWQItWKAq0MZ(f$nIV{NboRYvL z%PEeKzm0e>ktiXom1eSg$MasRube)yKfo`cgI7y!dwZ|qAFjr$I>ty%&5w62O?o(N zTeBhDgb=CKTtCV#Jrp54OfJ7L$5ago(Ao1tnHm0OLKoK==>R5VTEIkh+#67$eydgC z6SyR%p&M8NzNZ_yU__<5S~Hav*)k^$%aj>>XIj8VoS1u73sU3XB3H{Mf;?a9*P+I7 zsxE6$s)>_TyBm235_w;-7h&hr2et`nuU@Tg^(%NGR!Rn{nVgjAdAGd+2qfd>t+)bN zM8Oa{4%5@!@d3uA{WITPGxuGu>OU86TfhiAH`~#(|F1lAs4~a}t`(8#)4~DMAjys)=9K0(GKiU?5f-BzlJK1Yrww_% zq83xSQnY#LXB;*(b(6Q#wj@hrHmSml^Acv_1(hmnHo9o<9_}i|=%a@o1Ey3@Yn53;fk+MT;W4|?q#Xam{DRwgrr$El8X+LOg(jhma&S7GvC&?k&R3;1o%#n>=ck^*!#o*KX!Q zfX{_12g@;Z9e+(2?~&fNZ`QgMFcb9W_aw11&Ez}IusMRCkT;|I(!ZV4$oNK6y^w1< z2d6x;h^eOmA6({=4(0e0kut%4k7jBnN21IX?EqK?oQSvlH=PEcxCUQk`CiVk#XNXc zj1LXRHAJI(kxqJSN(rCK_~TH^`_EAQm}-oL-tv_?Bx?!?0bf()pxxqN+4*U;Q?K(i zbdWM#HlLgLn!P( z5+8Tvr-54CV+deXeb#UL6sV_K^KhDys=AU%RtG+2?}8X)PN2jy;z`SuM;Hff)RvRaXhl-?L0Fn#Tb>NDkLt*lPj-cq?4PlRnR5fnKM* z&IkOHG=UDlM?6DQK8jh(2+p$=hsJF0coWYz;)Eo*{V>Y#mRGR@y3Q{Yx=4x*8{`RM zN%)>nSj!<{uAk}V^a{QmCY`r2&P+uF?$SB^SRhV>kC&rT4{Mr-FCCN4B-trgij^O0 zdx^CH8y>Hy&~E>u}2|E}7+;w$4l(jwts0^XXd>ni>P{}p>vb-)eon&AGHAGlR}x%Eqo z6S?Xa`)ULGkDuFtM)tE!!?z`H{FA-Gpt#BdC32iY34TWV!nFB7*`UV}yLL^SW}rq% zEXDSoq$~5~*;8|OKo`i`^%5;panf8*Nn|{Q&<9O&6xZS2udwO_!&UPEUEq5v{y7WE z(m6pPEsRuUX*rG6zl!urteR?X|C{UcRh(udeA`f&H6=5>5zn0q=WJ8eol@Ftk| zh2`4NiJaI+#Cq<19%nGT3cY@MyLDc-ynN(=nGllWLW0rhLqY6jIV7=QA)nClm6goF zTe5#<0B@wxHEw&v2SIuG% zh4n>r*%8Ro&eb<(9?K8iZg8MiJ_d*XRDO!^}XYubCVzSdE*5 zlSJ#>QJJq?XQ+C9EMX6F6kl`rJr{+dA&y6BeYWy-r7X=re!2^KQ3!6$%|C)9aJ>HV zi0mCM6~rv7bn)`Q7^@0-!1szm1KU$@vQ*qK4EcE#~f~pxi5=qS3 z0%AD_N`b?}f?TPq43sP?K+#5D1XkZ%Z00UpF>DOyAx0KezJOxBy7iq%_3E~_IPM?o zLIpxe9C*Z(=r)Yw31^h1BP?LKGL=2++dA<4{UaugNO&Gh5KgphSt82&>G-#Rm%@n6 zBayGU86!$ZW5$bmQ<%v8(Y`YWV0a+(3&i65!eloCBIV*2?g`y|qS;2!WLmX`&@IKB zR+ufsa2PL_AU|lB0WXDEL(DF2i~Oy+Gg+2zW-Z;%#>aq{!b8EV_gyy~`i?*V53)qn zcZhh)*~*-v#Y83wdXu|rQ1f^JiZ5mLReQ|&Ciuza!P7%qA8j$zc#Dk+t4m2fw{l#s zruhht{n!r<&qE-AK|{7KpXBm5M#$p%!+UZbe8gDnzraCa&7s#pe;)_^De!-168cl% z&;ADjpH?OPG($_@i2DceH^erQr1AT`5UQ_JKiK8Q{LOp$;NtG%(kB;ick%swvxD6} z9IFd@V2&9Ok2|Xch8=J%B!E=$Rn1MvRVlTS;V>amRV7j^PJYa}OT}j}Z!NRNR9Z^H zhMFAR%`ke!i6nU$yLo&oXZBh1jkBcX;=si-rEru)<|*r|)h$&QXY%OM(j!H=$@nS; zrbKIiME{-P2CRKk5^l_*q+nP18rszq2YJ7lAn0e{~@dcWcrQ9f>b-|{Rl5&%ISZ9*?1otEf5RY4wU#p>} zv55E@xyj2!bacw!gocY@H4{EH1bxZ{?cTxQJ`l?j`s4$)ScgpAwgNlw2vOEX>O&#u zS6y;gkJ_*D39N=;q|pfeG$u$xIrpQ&x#2zODa|hOlRTTfK+kT}^#vqbXGO-<`H{fM zjt{6kM}tEj?vYG+Z?E-x?|OQG$8c|;Rn37sj?QTBGbpa=02&3Z$!HIgBY(<_KRmFr z_>Ege_Ix1I7?v_8U)H(ptenXSpi&@yqe&g0@sV7u{Rw!A!MC2FC{Lo@J{c8}dy8eg z{6P+YdWhq)@1L@oQLN5Snv61S27Bi1^BKT87qo3z4EEJ(Wp*+ezr;8UQB~8Er|Ykp zZZ^+%!kc0_@|WmD#&O~77i_)S@&S0zDR$co8pB&xHG{bjRu~k7h|oAke;=nA?v6}| zD7Uoyaam(f#^*U0pbN(oIg)8lZazubk>fhg3*zF9wf3x_2FuooUNfxLu>>5h*2)ko zq*m*oGguu_aE-Xg6D{}H5Vuv2R1Ei*0EQv2^G=pAw`IUF?wK7iDliw{Zu{Kl<}a{2 zhm$toRV@xqkS*{#hx}9A;eZ1w1zqz{`5mb_4hlv*RjIE4 zEo1sAP^)~>r>iY-6ClSMf#CdefRt?yvPw88Wossgz4J&Cf*Y zHum%+F?nx!&L*>jW0`;*B^dTJlTjB`mi?8$>7gZk8+&$$+%Nmct6?#nNkLpGI%D}% zx7Hlbw?6bjS9b>e^3i5xcSX!r2xhQQJKzGxKLa0pQ!Rl=a(~kx1Jxi`+Rs~f-=Yu=T@J@tNKsVa- zsk+~1b7j#YYPiLG9|@w(j^M)MgnVmGJR*7D!z5KOdrIF0l?eU0y$UOvT9D7g>aQ}B zqV&p2hw~cW1iKHhK#c1Prhircbscp2N`~-X zfI+`C{+~}S{}~2xI}-e_fI)3d7577b9|p1h{{Vyj@wx{O4^GN?whYniqfsH(fY6SP zDD~M?x*~LyZsQ#JAvh_D)>u>LXk8c`LmOW6Xhb*;(-3`5sw@oxvE2`GynKn!95IboKUh-G1wsZ zxE#`mY$1tOpLo?tGm~NRMKd$j?49iu6|Y7V>O2d5Ku_3-#+7Z~DmEuxcb)B6!gNsp zk#=R#nLqCufnCuWYmq#XWsdlOUO0~|87SozX(`=Ph90rd%ZqQ!Cr$8)#*<`>cNA&i zyN&);2_mT)?~j9>wV<~TqL~$7Ze8ydl3|8UXULphNe&RLfjn6lQ8QuRSYX>&PC3wg z8rZ>jpJgO)IUIWuhz;9xLy!xDnLc0+NAmrXb#rcx_6(S&aENi&5(>!yg&f=P6~U~KoPf=1<}w1)}PS=^O}EKG9~F~OUZ zGM8q_dg3{1V@HPzR-Z9EFi6MWft)56p>h04SifZoz3Ct#yrUmbJ5QPE9M`$>NE<%#G8e+wHl`yg*` z7E2<|PDJfH&-imS|3{GCrmTMqx~m2woRfG_i(hlQfJ>?0)Ml=$EypjL;7BM=jNm28 z)?@!Aja&VwtVmJSyzEc925-^m!%1Ht0r9tL{D^zpSsBs=sv6TAy7g*ZgOO)g9pll5 zS{;Y(4WM>)ao&1}zsR&~C@!lN$xF>%@kh*YbkVYKPRkh^tY_S(3uu5_t2>1j8`{fYDJ> zd0~dcD>H10e7nfQ@kM7|_gL!WpR^!Ix)EUpAj?<&P zIe$fd-JAMS)ip_*>Vw5Np@DO?0dqfhvhx9}_^NGXhPNd4<-UHDd}%d`gjsu#FdES= z8Bb#XC;o@+*Zqg}8RPn94P{o%0vt`-`0}4z{$|u1A`9BWUgnGXS2dMqCbW23b?-3Y zW20_S(BdVfw)>F?)=4zWN|!Hq)*vWroF9KFIMr~4uX#|7^^0#OVfO$%WYg1=d=X9G^UJA`nQ(fVn;?r*)A)uQVa<9~$ zAx^2PA*~ceu{?4-F^J~s>uqChkvP(^WvGxzygGPKebOYKq&tL9X;+XYi){2SN)X9X z{Mt518o@u|{JbClwTaFHlrby^Px@Xai(G?>x7*|a(oeW?Sq=vv(5-xPoJjuFgmL08 z#VnAx?Azk-8O(WHkXk=`qj6a$jU`RR6VqptWy;aIP&Yo+7+34=d;`v@*$_sPR6Ze# zGM?X`#1Hov$f=Ew@gH2VPVP;RrQi#OUN%NLM>#qsbxmN?jqVd)KG&z!h=99MEH6QG zAvF@th~Njkogn%?*-vI99HjLkou4l*GRuyoaZfXCPNlhP#@DC6F; zgs_FO%iJFiwI6SFGYfZ^sK{oYanj?oAW3Nrl2*0a%P_O*)4Zg#N3&D0`jyNPy^}(z zzZtE~i?ruL5Lt|0bHF|I;xPVc>LKjMdTP69w(Wzi?k&lN!wQ1Enmm7f|8o*`HN{nl z$|Gf~xvn3v_|C^6#v|H{LsRjd#LoKZFndf_C9=6EgRuGPx)0vqoBMlHT%5Oym+Oll5JS9BdjM*a11U-GO#16R#g8x zHNfn|^+N-mR-QbXP6znQ~FSgTlev`MhWzD|G?IN)-m z@_Gmr0Dhx>n#K$h_00|GRFLZ@$hhW9tiqYPr!t{1oKV}EiG$sy7d>*AxX8azH zphPLk?wl}}9v?atoTBcgUokHc5%VH#u0=vlpNeqpfa?dha^6P9=c9|&kd=hm9#JO6D=l3IQ3DvP1ESrk0+0&t zf%@|MxOyrUR-~G-r2|=1%#c*yKGvg}n^aXdCiD_L>R-Z@*1LF# z5lp4jr(fSd&Q2Vgzjb&ZXdewO`u+8kk}z}d^1ncX{*!0?^O@=|H0b;_?0?^Ske;|1 z!@p1-$N4YNpg)YVqkjgi?W~#*M_S_#8dPV`$wZ`e^bzNyNh2e0qSf1+WNZOgrEOo~ z;=lgA9u$Kxu7<)7SPxQ<`6D~-5Y6;0SwJ{M>p7K<$>Ay+mWsgD<8}SY_v()S>h5Fn zu^Nt6phBHwB$pXf@qQ)@S18W#2_zt*<}5K{Pf9lWrk(a%^~8XbOGG!zM?&Fk$XR)a zfvjve&^$gvsm1!13gWD~Oy`w)>gn2Jkg@V?di-&i3o{H^{GJvl)mJxFRK*`wsL#wu zHIiuzsfJK@id4Sg4BPkMu|(?TperE5i%A>@^ERodTS*9^gcHFb#AM$m)d$LF>>Gx( z0-PxmqB=EnW1zlOvY#)3*6F7kg(>wWKzO~MiiG*!Fa8|*;qiYcd&lTX8*N!Q?%3?u zw(X8>+qSKaZM$RJwmY_MchGnB-us?$-}gJ;KKqREtdaFM>qpg7v*xU-SG{B(+QwZH zkT__Hr{iD7+J%n=l7qQ%Z?iR%)qdHheCH8*!JNed$7MkbvN)`VczHME#_#J=AYh|B zjR8r;ebEQPcY~`7nx?SV3P6BZ7$4f$0z6aNWipx1in@d(rYKjP2=g|npd(_X3oAs)aEUaF z{Yh7|z55$Ikx%D~KL0{8A0lc8jT``@34Zb#$&hOIJO=t05 z!Ux`g?YMc}vx)au$c9WnLCY8>?G9f&)&r`nWcjF9E!kh?TAv_ql!2eOQ?rn&K?_ox zR2+0bH%hy*5J0cct+W}2Gzz&GIMnz#{4DMJ7+X))tUf0~Yf5gx@$eURDrCJUCEtS( zVHkB`xEN=L3a^_1UXXASD~ZCUctNQOdv^X2XnSRoJ$+XnqLhaBqNIDF|BS^%DJH|=m?|x~YIfTuh2ORV9^E82sx}=mVfk8pJkgd)ft15vOIF*{ zjD0=AJl1XRS#k`%hg4ef3K`pQV1H~q4-o5JR9($EZQgcnpZ^LnRS!tBCqQNKqsIB( z5UQ}GK2^%}vnWTJb95D~33Il}_y_7kWvQa@K~dD#nq?ED&8_BS8ots#HOzO5uX+v0 znHt`rK{aAGXxQC-J5sa$_{K)g)W>s5i|+&-`+lQ6ISNeXiNDiAB) z>?WLi%j3_We@zNsP+A2c^UEE)I58@#Qtml8&HuPTn19?Lw3AvVJn0R-n&to;{vRni z!;m(Qy*}LOU#T|uBAzX7DYi<>0IiAuH)y~hK9}J|QnRfK$x52^PIq0&J$U{FCsxlN z4DK^-1Y>?2`@3ZnNHY* zjnX|q1O~kz><$qjkBqFxzqOrb1{;Q3^}mBpn1VU+TShHoFHjt$={lAK`*us$Z0v@q zH|*Y9FoK?gP9z6NsIz}XPKspXF(PHtpF}J@%$2k5)ZEcV_lrWDuqOnB$3>b|4LYK` zB9(f5PrY_R^3Fvt@O2~-&Y_Lh@YDcgceB3;reZk5w*HKSyv4K)$LBAyosA~{!7Y5C zK_*uKK2ahsmCzKd0Q1wn@0!ow&E!{hP25?X^X2Aa?Dc47BHYaLNv521r~d*W{HTZ4 zdknR4s=|wy64X96QvCM4*urUuC7<%9`$DfAPTR$#1l1KAznw}Eo}qW!?!+1bsRpch zjt;fWd4<5Q9c_F}l_=ffQrVw;9jX>H5=-ZPnH+ZtS2Pil^IQ&txSPqSVUhpM>NpAV z7qS0Ec-%ih{(n+K|2PohyQJm)6A=ol6Ytf5ZfpbSX=@~{=qx|6-YkHmqGs4#z)arySkiFH#ImZ*~7i;+mhR`o}==bz0Mp% zWjQ6|&e=XVYxG+tG*Np*IKs!cqRyLdnl%*{GcsRwq;wG8`L514b9Vv(| z5~Ci~Fwv2b;XAZm!8tAb7qv#93qdEV@yxp>n^fcNWP~up|AP1k0K|`L0&^KlbTz7L z#M~zpv0bQv-)=vQ_-BnI0w8`|*nh;!%F}3^N220a#~wa>MI4FyzG-UiWt4yti@Q6R zr)J*Bge&)Iw!^Mm>Gym8hgAbJ)b=WQ$dbbes*`(|OYh*DZ~3!>vTmsD7qej?4?n^# z6;|>?0OtRQcF54i9N_tb@>LA&GFy|`9TsS?ojDy+R78>%;4%IM?j3saTf_H%>>!qP z8xRcvhq=hnUU-qlNUDIRucEA_<}={>9V&>Zc#qN5=;7`$jnG(eFpmqc6jG5H#Jle; zu`=Un?ey03g+g%cv#aW&ZlQr&IZj(Q`_%@nxj&h7MM#@9A4fk3E%^kup=R|?f4stm zFklJvWkw=TwFb5C_b#iD=cZaWX>FKUdx3eD=e=D^O+&5+$WOJGuT%p+-Rmxe3A;tI zPG{~#DPUn{Rp4jwv$pPFYCB)D{x%_2T^Ixriz@rBLe6MP`WyH_C`xHS7RS|L<&Ab4 zYYWi?RzjLN;lyH5+U(@jpUjGOqhfP5QA)#bQPQ)}aR>nO4^RNhUkPJ`=3g+Mv#212 z>^K}#^B0(Z_y^3#Yi;pFmnn5p4r7+2x2Ku^3+6S63du3*BOW2sn~vY2 z3y<6PJ^X$?ewm^GW&9MNF#pWqM>K;ijH=6!GC7gJO?H%TfbwL_(-@njJkSs;4gDbj z#j9I01~T;r<{3+gR388xjCH1@>rax{dXzG=}GS{eYHUeid$@Px>t zANIVcWFB{2TYUmvIStWKFn?$yYy z=(iS(c83$Iz$>a112f)MdA^$VfUo>NlC*~}`@Y!B%pysmIN>+|BPkCO$Eb@>*Z~ctb?+QI_x(_1ETYF;JT61{ zj7WbADq%2xzAgcqVkxn- zSWnivb8AOC#U132>rd-JC}muA;D`@NnX z7_P9bNs<2Efs%XV@RZmr`%u5G5M5Mr$>#%2l+sAY)ce!GEm~&*>2V!AA6x8so-{gM zb{`8J^GC)5k-Y6kC@A!Ej=cdK*U;OJ=?6@qpVm|g-o!*VUZ2)nUGh^Q<=A#ut>MI} z*__$+UQ_g%CS_tAYPK)!PeuypVdclmlIy>y1n@P_i3^2lluk}inr3QL)||M`U3%nj zUP;^l`BWy^9D6ZWXQ(AG{|(MFC%6KK|L5Uxe{lZaE118!LY_djL5RiBVF@5Yr7vJ4*R!6IVolkzi{Ja6b^uk{_e>11uow_M9fr*wT(hDO zqX<`A!y}EdFq}$?GyYp>jAkL&W4lO)v`gIEzvvh$z%hOh(BvvA(Uxmx=PT$C!d9K_J0EyswN ziwO&FouaIJ<;?ZvzU7_baunxx;}tE7N8nAx12tZUnN3sc0-dULb_6{7SQ3Rv>eV-m&7DPTYEC7a`Tp}%bCR8tpyF9k(K|0|Z<}=~`P!b?NPDIawDCGz5bEN9}^PF4j5rH{9 zs0~64cc3c*YiqS+E6FMG6dzk#ymytN zQ@RiQOQ$vA@1fCEab+k?sGXR-8Wt`xcb~My5r;>CN~a!AnzD@BvW1j)nGBQAEU5u- zm{VvelTuCGUgE)Z@|AJHjjS7+xl=Kpa!OiWaw77J!32{T#YfAIlTCH|7;<=Rlk-I` zUo*JER?cZv*L_nvX}>W$ks96HS7ck*og?23%)PR(hB4zi7wlGU4p3=6v;HefeD1Dly<17AqM z42R~ogu7>*8NR7$Ff zdW$5VJG=kkyH9`*jbW7wHJUerbC>yTRdP_k=V~V6e3-%t^WYK5kMWN$1W^?V7GoGC zXZY<^zEPdprvwif%8rci;UB(`0(n9h1h}{oTUuk>#Hi^g#BJEXgdD#;7u>b}!R3#< z17eG`=D3!HQBlBZCX$2A}YuaqYw-YxE`)4sG* zk{4A;=duuii8GzS&%u;Aea=*fGwWnKAu>lX?7^AxX=LJ;92K6=EvTw{0GFz87Hy|r zWqUKBfVLM+mWm8Tvk)LaPK4av*_3gVPYh~bmYiyMn_(2Q%DM)g=^1Tp8I|-g*MfiC z@s$d?g=#pmQCLbcUh$c-*3{$~twKB8^}^tC?y;kGE9o?)9Ek$kvy?{+1zU5%{q26Tlq*;knS? znB#wvL=Ms@YM6e2F4&+HH#K9xb!qbt7(bSOoeO;d{X28G{F6D_$Nt3}jMYxIgprZ7 zBkIRl29~glFc!tiQ}Wax4&j*q=Ait;99Le~Z(ZAfKRsS*Q=;ULl0cuyKzS$gz?49F zklV98w+rR1m4dRVnS6<0$(i?~E}E;i+1-1Z7LR5TXM*jWE8^wY(BoEYix|NV*kXE* zl*^}D?0xQCmdEn$qiiXCNqK^B0))O){duhsDTh)bUMyDk#Txup_u-Yl2lrBPo1^n&(9McP#}yUzNzi!txCA~Y zmw?*@hFhH9lC%N@TvOe|k~|W0&QL`4YzhJW;7;TF`|HB9IPlikf!R~F3sd;cchn#K z3*57O0v@=vys+HX^3KDDEfyz_;Wm1ZZ3FVwt9>yH&YXD|+^rM+OAOWvg7mKT?5Tv= z*fPi8FdWO!oeiC_I^($A`pC#`oUf<=$)l3wh9a4yc8}qc6Rx>Ijv*q`svVH%Hm-A^ z906$P1Mss%7iClRe@gIxtee7v4O6QeSf%Q@<|&N@=&k_GL~XK*m}g^t`L@!-D&1D8 zOA%f>eQWai@%FIJZkI048xOE|=fz7%Xee6Nq4`#z(o`jFJImfb%oHUc)?4wpXG%%e z;?a+UU^vC>dh|M1x}&>?T0-^BurA!)SFrZhYgO*6nYI>2dKRXCi8Pvtt6G(YPLSHUu33hr4lTng^l&g=wa#0o4|WQF9C+{;!yQ~=#NMp?7) zL+!2>BZ(PFdYN@-)r(UNKdWFfniQ@83k8*%P+de@4#^cbWR+0AJ%erw^q9-cY$bkF zz&lPi`&66OWj|KQa?D_dUDY32XZJXkLP@=S=@0AVZhOWse1SSAFt`E~ zkm*?}!L6OLH=RB=dXa7yTHv}Y$Cxrj6vecsD{SP=fxgXS*D+l$_qfXq1eu+|fA;od za}K5N0Xxwf_$u2(!IX&U91(2U7Vp7Ni*gqpG z!&+cQp`A3APJFTg6cR#dQ*@ac`b$W$B&uj?H=;g$tR?9(A1#wUBy z72+l{<;FEMj^jK4kL-DFAckc<@JJ$RaDXbKGZkg6AQ=;vv^MLu*(VK)N(b}VE{po^ zl6^FT$-Ii}?a$=uoGQu;^;)lrUz^!C(Q&G~u@(!=(vBp$0QD-7$1#KMok+n^ zp#)nCZnnzvn34-AW!JkQoEB!3LZOC*kR-jciDCbFWRTCUU7!a%s@c=TuHQDQvIos_ z^!rD*{0QeZFUJ<6nLKD%Z?YRza^f4>yzAQBB|WdsS{;N7f& zKaY(V;LIx4C&eOkPxUdv+gTd08a#3@jQScXI-tDa+Ue zWr}(Sr;+?g*^^)_cJpIfl7+x#U;BN2)wt!QxU`dn|LVYzi9tXDV5wjTALYn?_qPQ@1j@nsf3EW&B z;R#szki6bvxqQcM>|DFPs13W-2gpISO7U+W%7@`{mhwBouB6ZsZr7lwls$H@kAy}> zU7Mb)N{w+a8lAseMP&Gk1pf=G=r8Q??}b)Vyda=57FP5*&~3CH*VDf(`g>Cpi*zXF zX3|y{?vMuB7iiPW5x@6?QxCu_;-8hV=Fx^s`N{rU#@E5_Y!`+0_J++;yLtAr9QKii zSY+nfGSu=$(DP60GSn|dzT-;aIb2sPvUnJVud3H8)J!FwQ&)I=a1UWBvRmCKM&;LI zo23X!{Bai=*W)<9DpYG)RPq0+x+ZzUk7WSdDGjKg!2C-zxv`0(g{z72f8Y(-sQh1b zbuBs30az72X~N^zehC@^-Bh$b*M!F46l&&Yuu<@xN?Srl__E41f=@%J zQ8B#p$&jsuo>IG_hdlhJJ;0<+OZ+39; zdA2Br7*IlmQqI)>$yv3zA@n}f(;zpFc5E+s3M9!}(-BBHG5HwjdJweO1UJ#~ub#sc zw=pu1@evg^sBPqV4Ny~2JS!t06MwvopZ#va14CK&jW!gmPZg`*SXHwmj(~^0K!|FM zh{}G>H{iVXA|heM1ARbpXC;G4vCnsdnwqWy$KReG5#F+S^%tORz(0CRE#`6v*_d~E zqCgO2M87gBaxO`h|VF9 z%A#gs-|e}-w&5PIgtC(v78>8xyYw5MApi+0fmsjj@3*4sNhQ`8DKF!PqJMZUb|-jzH*Pd=cLw z{(D%2%J_jf{iAR>auY2_p8NTS1D0Q1$-G+V-8S6J7_#;2E=XA8Vm{aLPy98)s+4jI ziE7p8cO+B1LFYui&2+^h!O#GX-Jszo@Nm8>W3p`HgytcZwqHIE!hI+tT-4z)eqK6) z`M3qD_G-|Z!u@r8`C%knnlyz_`xJT=cW|#&!U5lG>=xv&+TfLnc*VGiZ&a~FJG)MpLmBl?}Esd1qc$He#lt(QL#`GECmyEnI zNgeqPI~@5_(F>?Tw`Q`b2I9uv*ZycD z9_0$`@HwAtbN-(4%ikK@HxLT^%PZfke$!l=9oBUpf`PBHSC|vuKje? zg|Z+`%#zj`-sJUaGT$iexSW;Ie01xd)NZA)UEGGokQs4S!rCMpU_woScrM%#F(&rH zS)_6KSrb@^OXINP@b%Iz6g>8FC%BLyK}B~QUAKXvW+5b%X56&Ka~RUiiN)aii<|6j z$%K84k7?_^()%Z4&s@oi1aCG1CW=E$O}2O%-9TX`rt^jKXP|6`0}y+R=9H4R&1{bo zB7dBaut+nn9b4*5yKgz68zI=|wL1!*FwK!o~X`d1|_@!U#=BcpQJ*oYrvUEW3EV2{69V7|FS*M5_#vI>)Dy{xc6!9x? zFBO+x?$U15lZ}qxhM1aOS1SVW?41cFwaI1`-M!^Yw2yFKRL(g)Ec-UJPzW;3~ zh7APKqX>X!`F{(~|6aoU3!eQh(XRf$bFIdMW-LD4d*5DwEoHL{Z5Vt4S;{Q}9a*z2 z;W~a=GewW7v{htSkahMxLP}hvijlpB^l?fEDNS=D0GDlNoDca82E7- zr(C?|g!jzkX~Jr{%o0ReB|l((=~!hkW$_R^QVQkTV^MS{hsiN(9tRg1PGflfJMvE} z;8C$IDlk;lZ}~|EJkAZ1~X!%^Au#XRtLn0Vm4pT?wq-IraY)aL5@JONwf3FK0d!eju5&G^S>owlju=Jt} zxN(l|6V^`&85&VN^9j3pI9NgT#~_Ah9$3S~+kROMfqfWF%t2fokJlL$h|R=8XN#q? z#?#r9ZW`a6JMOEHQYe}Lc1qgdF{JIsv2*`4%lZYnevs@4M?BFOk_pAE^D&g|bc)e${I&URHp1OTv2yhx99=jqMZzGek+v=eHL-h^feJMbo ztGUA|%?G?}9?Afm3!~=0brqsE`_$(@ZtzEs77|YZQx9(f3aVdVl#w&?8 zQ`2pVe08smW4%#2TN-mm%eI{m5%H}KaE}E;x0U1y23q;DrF26eA#y7BkKmyciiYTv z=V(=F-N)|EGaPnO*AzQQTSqv=VI<(PMYy4~oSMd5-KD3`qRThYb>ug^X{Uz-Tt4Xv zMVt>a&8ER#G1nhdR_BPD6gv68X}775tXX3Q;eh*Jyf5j=0~l1IW{RDShA#eK^n%>W zN;sz1_&+e3V-*mOQ2tNf*9;7XUpZ@IV)c`P^L zoJhF|JivsU66{uZqYl7mo=pn3pVj@1xOBIGyq;zDp}sIz_sMt+i3+-+`)YM%we(IH zbd^FiW+RbBoEU7P&&$N%Q=;;wnJ6kg$_w0EY@2a>)`eAnB&g%yv)k5FqP6y0-x1g2 z8TV4GH^}|kMIK7!FCXh~;XX?4;|-XJGMts18PjJT{R{W#?yw#-EYr+E*=`H=;MBqQ zu-?|C@gE31%pN=Tt^qvSIf17Hx}%az7_azJi-HD`>DOvOzc!OnWr|jggwor@7{K;? zSas_gf~;}vD=>gQAmhDuZC#>$SxP#POfz3`C}C@O8*C86uyH4#e;$`m^MRtBr>wPq zoVkDik>6bp9ybZOh6?bf85*;H*%o00uYjGaZFacHq-(36*35V0)tB`anA*%QP?2p< zX!E_P%1LKs`SofQ<|QRa|7r1)eTm9!%VFM+J^E8WPAu*H{D%Z1AnWs<+OQT?lIP(1 zdnp9t%Ki04A0CLc_TL4>Jxbr!Pk=!q2Z*9Z|NnV~{`W#5IbjnzhygaFhV})%ZDW|O zYklDR3ZzMOaGTKKIEszcg()yVcbR8)mr$&JZ^V;ro=$PEQ!Ixq!MNawsjIUKbCfLjJ+j^! z4rAPa`|VRZ=Zhxk_{dRYx3`m+M}=N*UkaD`$Pr+hc!}srJHg`fZ)v8hBVxhD03O=` z@EGBL`y2f~4X%bp%uFiEP(YwmgNrJEJ}&MsK)_&emDNCCZvd%gqwtCO;?bEG6z(Tvvo zY#UKV;V`tRaWQqpM9cua5ffX6a&bVM(c0=nFVFXI^l<7m^RFsX-qO&R?F9qKdJ+M| zR|{k$BFK8UPkFzw)RdxDSxIGO9YnA?USy4YRqv}Gu^beYZ3Hz?$Y_#X(kiKX2AevW z_)E#KJ=X)!E;*a#iX|Lt7?;ek#)PDbr9yEaFZ8iQk}!nRDE96tBRqt5_i5yNmuTL= zxjGJ5jwvE>LLAKn>M3G)=g4;S-8jJvXi*`_>(-lufC6e_Dyg^+Na_Z~O_C)d*H$`Z zyo>ytXzKGY^zFhtroX?komXxj4nm4Qld}`H(qFQZAyuNYz=6;EthOU~0 zk;c$;_P5!mZ;f3+uRoi{=w7PvScqFwg?JSjLqs@PcjL&P zUpS6%*tqT8()J%#+VtUHCFFX+*a%>`1?>&aM;qE+9yTD)7@dMQs7-h`D0U(vk|K*Y zbS;V1^ZU`^54%2}zNd97E1c0EJzNL75QTsXKTG2DlYMa=F5_)fQm0c!3|v%Qa^o(^ zkv0GJk)g!(===?i@ic5WMkBy=v<%N>JQPYxsBNu!nBSPkps@?p#%t{mnwb_+C8{Io zG>Sp29jgY`#)<`@HWauW`d$nqMZ8vaQ3d~$>pkNZpW8hFg4uyV+@G9|!F)KE@I~5> zWjO1B5ij9ZelniIZXGm1YgoCLqwh?KXfbUxsYr$}{gX9D>1aZ}PwmHtsDpKUi3l*`9*zDnO81qE2aaq`K$O zkg#lL8JuMF0#80AA79zao%kz+ddf3U_ye(!b6bMMG(18Fe@~AeLot|rxf^eWABHQA z>?RRSyA_eQOS4evyAFuIVA{}s6pSY<9h2I_^ir2?pU83^W=cOno8-yIK;}z!Pc#>! zgigGUD#&h%!uGX@E~}^{1QX4Z0d;?l0?#=Z1eYt|U-fcN4E}zK+Z2fO_OLvj;Z5)XxElouAj% zpp*BC6CS}Eu#^ZYlU!;HahbiW*kDd{+9)dYBNSyyi!33SH&GhDA1w?*Eq&~so9bnh~3-W;zw{?&7La(W=TWHn#tp#5dSB5b{Ce^YNa|wHvO+M-)v&@2tk@LEefHUY?s~R78KeabC72)r zQ^+AeVhkkE+ChLz@wSzcI6rh3UDQAdx=f&iew<$j197ivJ*un^?W1P-2Ck5+XRxi2 ziqDu7)rs8;4cDD*E}75w6aTy=#x$QqQI0?y_+4!nF&ZxQDBPWgR6j?(7JM=h@(G$R zXeK5Ygj1AAoDfG#p>mWM!A+_KJ=ct2lHvBdX=EXJr7`9gU5&sCQI3%8Gr~I6vI(c= z`sP$mrZNjmT~D(NG8_CI2av3FzPsHzJ8PeNJ-FH>0@cbxafh~VToK8Ba}eYKGfQ>= zOws~l9TKW}F2t2F7bAbG3)?iu@LmSeL`>ceX&#z&r5?vdx#Q+IL%69T1>rKH*bbh4 z!aQ@y_ciZTgMJ*ERYiUj2JN<0P20Z6-oDV;qG^)8+rshixL+}$#_#>Latx?0Kpk^( zM;-J5*5wSNrAub-xB8U@2(>ntFJ$nCgR~HH$Z3uV%n*Z|iOl1prXTH5d;*mr%C8nL zMvcFJD~mM@u@oc8dOpi6RQ#naYEhfE9Ym*2?WoS;oI6Qs>uNy0`RikS=+KarPSeKZ zV|jmVwaAv{2e<9)v}q%vlAyVDCdO&l<{D#*A($HpYsIDEp3f47Ah+b))5vBHJ81X(vNr^9N67k+Ul4foN6S3} ze;h#=Iy|ZSKgL(a8X^pXtz#wVFv|r`DrGqc2}McKP_7}TsOLn`HXu9MnR{u>Y!=xv z6?Rbet42>YuZQBEwz`fdTZ2W)E`ku{N(G6bSTzhDuz2)U;p*7<)R&!Y#bH5k_FftY z9r4-DfPH)mtoGD2$|;Bj&049(cRIIQe@L{wv`GW5FfuMRYGvWkX8RQ0d4(PAgl?{I zrhOrkQ#NcD8W?r?kmx*?+FPgzU*JdC)eBEKh}Dl#rseAEs$>!_|D2}6aH!n@8y|m? zU4l`<@FGM*TEYQo4$xv2QH@Mi6`DxK!FXuM z4Y>qbp&oaaTu@8$j@Mj;a_Qdo*_+|JNMO^}7)X!7@9@oSq6!!OOqGotZ8^rQIhxeP zZNGhA@B=j7ce2?aQ{-17htbf9zaUQox931{b_~XW}7^+ecDI^*BFZ?&59`eeW{0wD08lKyRt?;r&@1$RAi$9hD`4phI9Nr}h(b{lM< zrKE!-oC2$5Ln2BH-m^4DRcb0mYXb=MXF=S|w8hJauj_xcLsh%QF~bK(lyErJ6j{!y zCZ`C*ScEW7KSD&n-of4ez~kz(&bZcy@PD(23&=)ol@ki|-hyIMT_iSFD*tvHA1`(e zlQk9yF5*Jox4ackGpecLRzF*8$pajGF9XUE^qq#cF@Cq76}Yhi#U|Rb z&O@ZhKd2aJC35j3EU}$`Z_QMaY*t9L?Jnr6uKUHkSv*he8*|Y``l7B{q>o{Zl`-ma z&aGKI_Akm$-M9!@$(?j%h)Yv#-*&Lq=(;F%R^fNn`|TwYZ5wwfoePfpwYn^;ZI$B} zz81-Ihxay`9`zGS9 z(@GfMdTwkRn3J1$lZt%;^?;S>UJ||Ec0KtMygvUn%aVUqUp@rrBnU7dApHMH1N?iz zRIDfkA4GttBejQXx|%_^`N%Llnii+YfNG<;zZsba;tROs;vl|fx@N?GERQ#YG9h(L z4y<3czFAHiG=}XJ9xIVAWM*(?3?F7W|1td?Q!TG&w1ODYu{qs>iL4JS;@3VAv7>96`?znZukuoKk`FjvT$^q^67Qh(@ zd22P_K+LTR8fwknPM_91!AY$C{kO`Wi(SVzeE@^<02mbGFTb9Xk%6^=<~h!K{`29z z4xh@=nH>X8Ljw|kwFp22k`MP|(Ebg`x#pu%VPnfh6FKxEt=EipZzM0`p=rz}wN@}O zYLY17)7)BVFRkLKuE_PICaGEUcXUQCoNNk4U=fr=>y{?X4G4{TVWs7s2RRncLF^z;1H~~u;x8Nyh)Xi`d+ME$pYn3RZfgY?R7ZXxbo>y z$fq6FAqcb`%c{Lj8E$kEOiXs#?ryLwA0(qJsR~810?veFF3j&nvXO)OGh)0fipy$5uJs1uU zF9ZtmcF0l|S2XEXWY}fiib*rO4CC9+n&qM9aweT;BDZ90+|(#2b@_?A6&=Z)`OYlM zXN-D|Wizux7DNNxm=AmbNBh;-!^BXElaNWTF0(d6TP;U17v$*#+(SmJCtf=<(e_JM zE&`YAZJ2DQ2%kSLq>tr^3GuotJPDQHM-hE64^986CnEN!{nlQ|$>pqli|31u>O30$ zm9kVja=*HvU|#yz+=7AUR++}nxrw$2)(el+qa$SAYfoY7s@#?MyZf|0j5O|$Skbrs zGj&rj!ZHmBg(2;sDE;RTRMsBSf;NgP*0qD*>;t^dE)O6vG%Z|B`a=+C4U{;PQ&dMY zWLt1oS#y_Sy6-GpZLnM?BQsz6*;i8q-oTo)JSMvOWa<%Fn?xQ}U}%V4l^PKnLiBqP zz98GaLd(BblduaJCvKFC9iN<2md{Y^P7%@1M9_#{&8ydjV)q;yYD;0jnfdRY;R#Uu zR^4fadA=TUNmjR)4E`*aH6!u>ZZ#F;Vf6)>1+30Svm-bhQZ7 zkGynXG7Tic;jF7GSv(pi0}uyT<|6!N`$NN_#;goJm>6kmF6w8a+NJ0D-wSnCgrYLW z3s&)^mJq&C^@aHSU?%D}HWuC(6=6!m>bizA$fj=rT;p^de_pj6Z#Y>slw!b20(GMS z3&5TQU;@cU008?#K}mOwN^O}n3rRG|%OpZF+qsClh>xZ@o6s7`MW;<8--fo@YHL9e zhgn&!3rSJ+E034HZvJVGxHQAUc^Yz~B{0PRZ#>96SyQ9<;65dAgo&kNx@hfBB2fjFal& zkiPj-odknIotO~NPmWzz7%&XBbYq^%33NjRZGky+8z91{vkJ&VDwgAEa%3XQc>kna)4RT&Wa7RA9_SSmE1-wY~E@xv+%ioRFWZEHN z0ML$S-B_ngH@ayhraJGm_g&Vnl2O`Ho{d7;CNDdLo-C02d*?J&IwYlASULe1s2x} z^PyWeDo-7wuB(V=5VYtXm$+E;u@1oKDZ_g(K@D?JPr!veS)5Q0CI*GP!%}u-%ELBw zuJNqksMbh^6m5-P=s>v3l9-TO_RGF~F9Il(dv9NqQwpcGMuTPE@j$!QbZw-z7I`Y> z;v3m%$1%KH3=?)f%mcln+4UJ~6#fu$Ner#sd zYZWF4BULkIqvRG~Xe+Zx*O;E5f%-(37MF-RH%qjfjK7Puq7mg0HR|#^?u$t00Z^M! zTSZ*ev@MHypLuJKrr}9A_eRh>Eg7eMl66|*Ycy?3>WKxYix%YmUQD9j@aUH)OWxw^ zEk~x&0s)w_k-6DIU{!sx=Cpm}36l=221>XgiAxFn*eo^G#^?0WCeBya`M2Pr{jYvI zgIdO*9R9PVA-XB+@PMTP=yGx&!UF@O>gAvnfdCkciUf9HVV$-777YzE>mS0@=TVV` zx8U)%WWsV`ryixYa{}~cl1ugnI_=m}51r?%U7eoZVdM1r(0clxsC?*`Fjj?SxS_$e zq!NeBq|61I&j~-@(ZjC-8%K0jfZK3A_`192(`6+f-WKxwUH`6_liu?b=4Utl7mJ6|^8B-fQ`-+O0#oQ;IxgnEIl;98?Xb?o)>&I5%EoQulPb&3WLW)SiHZK3bs9>3F&^ zo=p_zB%nTp8TCDArq;7?8T7WlACpb(DZhR%@_7)r7iT5tw!-SJPT4TWFV<>Si2+~s z`fhhcF(341_k_AV77Tnj3Pmf8}J74tR$DMxkUwh@>1aY-#?HJ0; zyfiC11&(5!I*pFY$$p40yfJvlJA|jq5@%Ve7cHi!sz#$gSDN>qhk+u!9D&)p0kwSb9X?zE-)`CW zNm~;GRfBy{@@GFfcxLH6K9KFJ(`wCfBZyu z{A7C|X(R7_P3A%Db^$TKUCZj4sVov#;0|bzYn_;(wlmDtxs1BWsAkKVEMzz}H~{oG znuoFS*ua3Z%G%F_17i%p+^MwJbqSM@pcE&KzjiT+sF1ELiE~^x`79_ttxGE9p|Tq3 zCgFcgqM#u>$K?8nl;V=Z*JSjgzhsg1An7h#Z+}oRAqy%l7dyOI6vTkcKT0h{G&CtF z&4I#qzAwH~rS-Fh&HIwf*9^JmN8d8XJ5k{$hSIjgAoA>HR6lBx4%3Lb6Ip9v zmaYS$(`a32py3BG|7VUJo}wzwOi3| zAC$BoC&o(0?zRTqMpn#%6HwuY;Zs=>%X~;$sU(l&^EGmHOL2pW(=L_>Oz^JnXOSp5I1VGF_2bXK?2&ZWMQj`0G_k!S73xOrv|v42 z2A+o6@*Z5wjtS6#bW-#)?%0INIx}#cFk48av68D>sVibYFPW{ZX@s*5EQOFRjWxc& zIQ9t^fgDICXtO1xzLtesAf;O}bhh?p#vC|(soyRB>1K|1J@>*@qM8B0I~&gC4C0A( z5(A_M)?UB^e=;W+QlFgyW5FD;-jrvOQuP*!K;u|=B~07uHJ9m@E8ZoTHEiA>6W^UTkN-@W*66H<^`#xZMsXFkjKqUe_FMHR4oUM1s#t*rRwx?pxu&_h{Kq<!EV0^i;?;b1B>bz^u#W0pM)v`6d&hW($yyO(`DdW3 zmY;CSO^c|mYH|t(9g8ygXC+8$zxak`(vVqAi=(Q&;g_$x1pa|6eh$8+c0rStz;QyiswVFIB8G?>mBXr5c!jSMF zT86~vI(~D()%xHA&A3nX`bOycj*Va$}poqc$ha&pw>9LvSeg04cBY+~L{z(y_e<&jD z|58LZfFiR0Nf8~u0E*~B`3prn{FNe*{=XCfIFjY%CPQ06f*xoTZ>U#}7sJI&K~Ihe zL)?HKB5vq3IjXd6xjy;C=V-pRJs*N9NBB9z5xS=;o& z$|?mm(ZTn+o7}Wbeo7Y5DFvpJVU8j}2}81@T%qu;!6wjkcqx=|A)BaS$?Q#X}<_XuE z*|wtg^;h_eEVUyugg&+qb=Wn=oMdR{=(nLNR?8f~bF9eARsW>_&X@b^jG^_mgbxOy zqX!d|1%HCwEKNvyJ|Zp?5vPhXK=y5uvTLM-FRzdw+x!%7nr6c7aTU&tgSM8tDUIo5 zb=dGM{^y7LOCv=)3rTGvlazxYhq*dq{JcQFLFlbm*+G=Wy>#m>^@igjw`Y?shr?|3_-CdbtAHV^4fJk!l{eq~UC*-J*bH>Phy$7z$E!#O+4xd+ zjy*Wp9Yk|)2b3-K!7Ik!nz$c76skq8wW2&(dYy%0ztkZd8xrCI^P=ql&bSC+a$@7( zpEQtKvyq)I*8HR$STH+ptVgjL(#1?xC!61$9t9_hgNdh-a9k1B-7WrBBw}3Fd;JDt z$DS~aHxiPfxK-rQA+>jws%e39FNnE11AT0iO9t|Wd>nJjo-0O%KGvi)RXj;2 z(RpdbTQd^fcBlQ07y4hyMAM%#VfCM7!skEAgvP&@iN}906L+q6u=V9p&kpYf6JIz> zDQzzbZoHgsCrQpxKvp72Ma6A^8Qu8(^O$8BsI=rqHUvTnd~GlGvlmII++oa1uK zjQ#Xmr1;)=0X7J(`NSkk!GXPvka2=!c5cKYbSETETM}bksQrprTZ7~%%TD38?uLe< z`a869?(YQ;^%kxYM6xC{!;k~^I0=l2FxT~P)H@C2ehLdj8>LQZAsV-+eULF)UsuCC zU}PB6J#thysu5q#>mom^Xj(cv;ibkvzFDu1W8T1HV~>3M<`NRG*z3<=N|EoWnk1es zL}y_ec#@$uz}t5LA0<+aQKg@Y+h@QXk|s<)f9?o=Vqw3G ztwa>4KL=-}D&FNR{%&e&cnBW|f3cL;i&J)154fycisKo&?$`r89Ot}1&tho&BJ-(_ zLFQZ#zgXPgRl-598A9P_@ujsQPTONq+_z(8r1npl`1q?#9Ax|{6YqdB;qo74g6rSQ z#FxL937%oDnMLiSgKmoJ?pWbXOB2XFEp**8f2mqoZtNtq2HXFv%fdc%JgD ztsZnCe5pTwLohhimbGud0b0BfMrpep6*zo`;l` z%X*E6wVk+**|m-Tv+AV3GSOhHS`DdrIe0F_bQ#!>6|A&)B6m&ULg9TP%0eQ&A+z6} zJOx0-4?rCOM!2kvlnc8dGzrx#c= z!f4$%THm>g$vYM>71;tZi8g0aRMiw9t)?rvy0dzd^?fLjP}+9;9?{NEzVrC*1ew8C zx7I-7gFDYa`9Lq1h6bVSKVf0P#W^s?yg`eHv@BCY?K0h8GKHn(y^kF- zdp?oIW0-`SBJwlDq^DtXW647H7njd3atDNds*UdNZ=68z&sQMY39{}7f@Px`1Kcu@u#g^~pasCsFSo@U50S+ZIJwzP za5FcV)Ljv$-1QpQ-SUHpD9vU7=fd1)OtL>PXAYceFC5KWGb^~#q)xpZ$$zlZp@cAxK?a6%2=S8p5??^xLvrGQ~lWs}r)y|bb<=YuB~ zrkvv#`TmlM;-gISrhLki6E5@x8weizu90{$*L-uQY)joE{l|Y z@X&3f`}w?)>A)PlFMTpH1YJssT^kit`Hnmu1iEBstM*aR+C|wyvP)uXG!;J}M!uA@ zeEcC|c@mpyq<9xL$+=@5A;$VBwMFsche>pyj)#O(Ze9Ac5V6kTEJH`%{1c^l%-2XI z^ag%LVZa}r(_(@Et6A06r$I9pc@k5eR2D{qeC+1M5N{GQ{CxKAGY(=pIs%DH)ezB& z!YZd9ZF2DZE7o=Y6mYdC#EhTO9g?N;n#+p9* z^1ej7vei^^-`Q&Q4}X>VRH9qJL7|TLScGn4#Ki8v&39w--}ylj;lD7 zTNCT1yLZj$sg1}`RS?|aHO`JrzG;sv^D5Ka<4$qoN@VI;b(dQX1l5w?-__R6f_{V$ zpth<1thWDbM0Aw>q?N?*x|fnSsc4>b8`mPbmKs0Q-vUYTsf(6fJ!}*R4Qfw6^!ZS< zT+-k3^1$;d#~&qUL+dp-4-f$-VEp-(4W*Cz051c;nnYnSM`r-u0ksIu7lptlG8j6( z`~p*#;+6BdzHtPARh{i_wsJ2qB9Qz9;NP1z;Lw1+!~YJRt=wuEQhBg!s(ayH$XnAD zOvz9_LI@ApfO+z$Y|p7=UN$%Ku`rozYMTo(IXm`MP_u=$4cv2i5ds|rHmC@r5$Htz z&Zupbz<*$-qKXi?T_9RV7kzvVlZQq$AtG_i+5~vU%jZAJ2kW7#wntMJ~9(NHkDWv#A)48 zlV?X3Nz*$NX`o;!!SBV`BGzRqBZXk`sG9|xY-6RM<~E zxm!ki*HLOp5 zs?aNA(#&8cce&!3YBw#h&?I4IGg1R!2eH`$z#ReVuJNRGEQuTG`_~{q5a5R5>5J+7 z#H2aI^{U{%j6bC}+8lj^h^jowU8N6J9!k|}GtLFDa-ylLc<|sF31A1Wf?o?|V2;AF zaeWmiAwJFzib9{Q6h2^K*|Lu4W5gIdj6xWrf45rsdd6+M#_otbe|?WblkRE4uW@;H zRuZ%vGEW5I`f1sVCRF#f0jDre`hEA?M&8QV$)Q^RiEsMmd9)6vJKpe76_H&aBo>>VND*dzpU zoRR!yzu`+u=0qymKRcWATi!~L0?rIK7oB)2?Fh|Jm=ziQBBV@B^pMa(F(zVYl$+0V=Nrx2#c>2#<7pbd6TsuSF(lnf*@$N1SU*bGG<0a^8)G-x zV=pdgpoOk=Q{hJ5`aS=)qMg6cwXJK06LT+UK0l=Ai#vK+K6FUuU``SxQ>07j8^e?T zZJ8`T8+lk^&RRSa(1AVaISZ|4QC4z6m8^@>kg_tzE8xZd>(f@wt1OhUN!j`?Xl|Ck z2~H$ShhaDf^2pF`=B=W;^;-+k9*OQyQ~?1&p0t`{{U>H&0hMVi)rAo4QBW}_^4fZ# zH=R^bg*hI4I@OENV59pNt+asevfE$$J>-R*s82E}^TAQRQr4Kyj_ZGnv~{)|B{YIn zn)60RK*x^=%0|CpqMGxH8IRL_5c5=(o5$f!I*Gw2*3TQAjSOrM!G-EOx$(1srgqo1 zhLt(n&X3Uh6{K)k(!`mNxE-}X=Gc%uLTz)Y1zWMWzgo%P9N50}4Qa_`gKiJMAM9@` zE0`tz8td#J)A45^R-W9hw_S>56)BTl{r$0BFABc1*;b|{hmfM(EmgdMGh&Efhonnq z)wUsQ#9nNT_j-7lnm`C9V2rj-3$;cIf)qwNUNqkLXb{w|9IhdM1JOEL1ilbhUEC4 z&FsY8C1B=ML9hqNR&>g(Aj)nO7OPBmlKPwAOyP~_64T|; zd=<4;8iPYL-_|&qAICTFvR^l!xUZbHo_L<{GONyo5<&=VC7}d2Oh|r$2~-I2A+6k2 z8mVvQ=9XDaOBtryn2fD09Im?8@tCvn_AWWV69uCs?$me{K#i zXl^3SlCBpLA(3D{hRz4sSdb7r%H5}g9%3RY`#q!{O!U9woKaokB`2#NG@^`i3&N$er>Ml3-Q3IZ!_52vQ1UBRJ0d?!%&RI5FaGw zOd!_#=yK#pFnbPBq5dR2Le8!v{?o96fE~%|V0Qs86z3Ykpr{T*%Zu}0t1H2cim;;G z?b5pHxa~c=V5)|C3A-W`#E1H5gYO0v9Z|y_KVyf}eG$JIq3L;okk-H;Uw{Q$P?484 zMw~oDZJX5+`Z6y)r<3f887q&YyI;UTPeRxb6R36S@R7J(ysZ;&1iumpZw)fHwVNXy zbK->YAv`+Z7CvSse{p9in|o5a9{_Tq>hm_qCxc<`+ks--OpnKMoV>3zH3?sRO}SiX z$$SsGyUTUrI(By`OFCLbI_21MrA^&NaCQ1hdTeg^3U1Y1u8Mks?{+VHewJl@nRVM~ z;dSbNXJpR^Tdic@g|2Hh+70c<$W#P*A&GRJtidzO*vvz_h8?*IK`iab@45Vgjvf`c zzkvE}<7`=u7q*{+Sfj7JSblg-OTe6=Y;zN{@lfa9+}H@63&r3|`mqISrU8{~y>Y4S z)tr2>oHb;x>eST%LOz>jOQ6K%IQ@~I1LcoH%}#BN=1Q@egMudB-gwNClPfq>_>j?9 zcqKio7|E(W31W^jexQ%!zX*6Hdn`*I5l#FE8s)IpL8b7dG)$#u5JK)(uit~nWa<~h;AQK# z_(iH*iX5ImO8h(kCk0mOTTI;ZET4dy%L5c3F%=&Nu5gz?czoz>p2O@x2fNrZ9`CRs zX3SMBVq>VKxSl|GkK zg?9dolr!ZBsUD{fFsK{t_AfS?Q_SZ1;A3k#aEQ)6dJJd=AJ>e{cp;D!p3Ex#WnEci zElfR8XsH{?9KYHa*t3I&nWQdQ5+HwWwt=hP_h>L>Vk;2}_ClF)U$-=KD=F(yC+it5 zsFmDCR=n`5do88AEIh&{OFPepO)O$IK8T(3D6ECSF4)>Azvp+>3$}dQCD+6OZtPp7 zyC-2|`J}9W5UzAcYuqv*a9FsVmEoyFyk$3zGqO_FnQuZ?8xyf5A#J7VOde6bfs^C zvPc7*_n@;hdR$Ip5a>EOuYiViLsit4o^rZb_`ZF=%8t2;w@uTI6dwLy!9|PbAi!gM z<|E8CkfR2DpSvyjLz$0FTR2`g(4UZUMkj&jURJX-`OiwcCSWDL3_ZRx>@(NODTHJy z9cq^aO-tuQAp;>tRk!3kk{B!Y3FgHm`UoZ6U5|Lu=Id%AN2GRjC5edWqiw*<;7CTY zryyzkvs)X{DvlsY@M%>;leFuIy}`yHK65a+I!!)GvV_}=OsTx>b zoc>x}_@n6GI@!06F%>b`-YjJ=S5J(nf#;Rvufb_)4CANePR0UiW1a@#%fnFu_sRMI%M>iN4~~K&SyP= zxg1_{qX6-7=yX|}EwY^%PPucTWPx%~N!Wpkl5_$SzF989nnk1sgnMfL;?Cb;x>7{PF!}we*O$^eTK+)hx6enb>$r4i z*kl`gQ8=ECYNeN5H@MMctKb{svpiv3a9$HN$?2ej+Bu>8i`~F9v|y;#^hk!?%s&{; z+tz=+M5;s)6{T46+i5s>GL+<Y7(*ZM9(m)Y2p#(++QCT%|i8~ZvoFETl3 z_-rEUltkM-Vu2v+>}G@QcJbX@W|%da{M?7(mH*c)etm3z9$jz`f47ab`F(wrj<%lN?IxX^-Z zv>oc`tUVF-Sf-!^W@--v2ZA(9p zO-p+4X2Ua zm^5uTz;}%QhNI~VlhAp(Qq=-)B><8^abkhVHTs2OVHBNk`r>m2D9W1T1wM9v=Yvae zDD_yVTKvDkE!t}vNoRfGuJogImkl5LsddzMrQu3PVu$q2y&NnK16)v;qP~`E4TrTX zaNxWNTxZ@gG-WvD+^qvPHUN`Wm#xLo)9a1qK))3szH^#FI0E%Rc=wy{iJ0kn$cwP8 z(T;kutXY*nB-DMH3wNt+x=L)YO0u0*Chq9#IK4K3y5tw$9JV9N1d`UkA0i&d#E=fR z+%PtQLBa$5+SAPflO(IGNJ8e;8`ShjQma)}IFP%6?$RBX-|oQvu6DhCSP5x4IXq1P z*%b3=n0kSa{D7;CiE_HBfH}z$AZwBxJ)2&cI56T$HsPH461Rba66ai2up2Ujp*Qxd$X#Cz#np*ENUl z=XBjg)o|etv?@RJhjQ@sFXqX9|MB5{PqOQPxY?Ud;}dBUlW!;6OrPGBF|`E~2c2~s zp94R^XEA-q7uVphZU|5zj9{76jOh;xQad>5m<~E7f>Jc|5Z?>@7P}@p=)i=R>p@-l zIFC>PF#$wxw-6LOG{GaZ0gS7gy+tX@ggT`p!=tl}J&2+9J#76FH z9pc7z!zZu}MG`{~Elh~;pca1DT0G0B)}4bXH7=JaC0ewT!aSZ@_vqV?1=_?}#$tF9 zl~Y(9UaW7P(>7hCmG=7u85tD`3VS-R_1nVDJilPv%nRQ&+A%b8>}A*y1G#jKVePY@ z^v32pdF7ZW>sA#tI*BaDZ3oD@Vf>uvGClXs8xzdtS@@dahAvu`6C3K;Y(EuO(+(?_ z+_jX3ooCr?4T?IYfvd|9Lm19N2A7@Idq)Aq!^C5Xa{S;0GuE zO5d)e*kmX*Z~fAYxhpLipTo5Iz}Q;iKxw5-XuGoR#D+|>Yw{;G;3EI+AVNJbkP_4s zrr&B|K(aco7GrFrw-hTD-R%{HDmza=JaI4XGiA}nq8JNL7CGdzNcu)&I%5ryC7Tzo z(S9t7sD6RmTHG06zYt07Nng+xkdMt{UofBDrmW%9s_ho6q*r)G>vT$tyir|=y_uX` zQTjVsBG?CwPU@FGrdj;3N<*7v_mWH{OqH5Ldh-G4EBPkPoW5h^6J)Rt{bss+Ls3?Y z#OAl5W;n`C+8-2hEUs!7E*rDAmb~t2iR{ieV(b_1jG8|s>@luTf9a-xd}tcSk(a{p;%-%)Xdc-kkK~H* z%yP&7%H|rItCP;EL~GT-(wC`kRmP~;K|IZc0t5MYy;rXi?xoUt!ZdR~s%xpgmqi8x z)WL2`cvPVHSPDY0?K!bEjx?EzsO`;t@is*%*IFEL0U8^+A9VJLUNy#GxhqGBy2f+8 z{G&4>5bfuc_h!!{TfhhH8Qt*KGm!}1y;4;KNQLg_zr6j3^{STs2oTZl|0tsW-0cIB zR%sv(+Q>3vEO4OHQ`HJiwG z@<~_px@#k1()cLSA?GOqV~5%cm!Ad$E)&!()FB8FsT{{xte2qDlz0#lW@iV@BuSNqpHdM_81FGof!>Z)F8ZCXYIu;!U7m4+?LRT?Uc*4hsYEPQP zbe<%3E|`@~dsJgeGw7#EK$Zm7 zeJ|9v-$}uFB-YJ+fKM)!{co$Y&y58KjjAS8*gmwh)md7H;vnTtdUf%Xs;c>4)fo_> z2c9{yudxGAZs0t^Q}qwzAivpY0<39pwpn^~nz%rDZvtkE;2 zFvtl{60D`Rf&?;P4(=~_1e2bbeS7-_~t=6<$J_QNVb-b+x!D;W$A)5W=(|Lv&{wZ(u$!#3R_ z?QoP@oo1uqA4f}`W1=;#bG3LagSl$vZX0yab!A&9;{$hWrt87kr@iR*PkcD!s3>bf z3?-V0uqAZ?LK>sphAYwO@N#-HZ=}M<20x$!5YmoLvdb66P2Qok>f4x*rjr1V^&#ok zG;UoL#Pk~~n2|EzL0i^Z&b&FzQtVX7`<&0-gdJq zecJ+KR{r?9TB_392qSwJlX;HQTP*TL-1hb}*Aado3p&YZVlR6iU(tL1`{@OD+O6=O z<$`WGkGAF{WKIN8sO&D3S&N!rBs28Xu9G06un112JACTrxGl}avwkB#2F-zj1W_>c zw7I>vh@cdc@Zp)V{fkS7p#w=OOVw(yC!3% z!;Jn3hNdzi;=y*O4z4^$qgcW&y@i&gL>yjF_?+{im!&P=3Xq=Iy>E_UW#~C&*QB-s zZ=KAua9};pV)NNo=VOU(WixZ1=JFCPwQ>uZyn-@s5`{)wuLNm~YW6<@?k}d#mb*M> zmJB`*j=A)Hh6Os5HCBL>Pk;VBL>0ng2($9;no{bg2b)vJC#Z&S8eTuAT>5QIj@I;<>u80?UA0XxcwQpZ7h zCkO&D)hZoAx=*B7cq0^4Qkbkr<&dI7zN&}P&foG!n@TEAW5+ z{_}8ib`k*o0|($gf4?8~@8AEwScU)Yew5C?FD~R>rRQL=l~|!EVH#xDPb_ zwFbUKp(No(q5IfB+l^=!W1*8@xMUePv#aVwHaT)TVH77Q3(9 z1i)|H7z5SXoz)r&?7|hQmAzhOmrF?}8T;lpT4H3s1SidCO+c&sfU+Vve!;>WpL4EZ z`=DUOyHepBd46l%EDQ0&H9kxz^7=Y|gkj3tPbeMwvpwmz z`t5jb0ZId3_jyvGYLMut8U^@Epr#9=1r9T`MjwmZ#a>Ou>}rL3e=@AY8AJQ3~o!GURD z-b1}2`@!Jlw7==(D#z?&iX9zlMNa7@b(_()3lXr%zVI)^`12R+3t<+lxKOF!qE|Td zGL)9J;y1|!r!6r_{!CPpj^&w9A7Rd7rm=m>#@o84?Ke@@O&)Vp&Mr)5PbDL_G4U$i z7gE^;V(ehhPayT z9+4?)DlJw)WnOKzqYaWB+fOY;)4r_~!&&OQR4t%9YJ$LsP@CAqC?e z_FeW0A(yuLXoghdTm&4khCm)1PAykwz_P6F%_~uq|A&5Th zH}6YfSKboJI+lc9ZoF;ETked4yzc%!9y8t?9|+~>dL=Ui!PqMVH>qn!q*ZD6^AO|e zzC+IiD%fr^W~W|DVlPSV12YAdmVOkj5t$ze($4s+gjfm0Vf-L3ahtdPT^%RojB0Y= zv-76!5BIYpc_Fq_H!Pu@SVe4T$^%1pe1F&I0`jrnvH*=n`k!g^f77)8ZyLR-Bf$2d ze-kp*Fhi?`fQE{3CXG=?tr02vIoAO0zi6y$v608TR%*Nx8=NT4n2hyL8vTPHWoi0# z6Yy5k^N0JD&RNg^YGe#yJWRlhYi&?GVHo}~q#(Llmc@etypBzKQP}Y#dYp-=i(I6+ zx%{He{386^0tA%>x2B>_cXO?9lX8>~$>|vNMalk7z1t*fq zxY*YD&oKEaS%+=rIvi<+XpjZe_}{J^#Gqs%@O-MZe&G`;8mqauX{-HYx9I5F8~TbP zfx=}6AzUg0(O7$(_jP6#j+3(xR@b6l$McMxTS{Jl%{&vwYRW-O@(>vN+E+}I`m(|;4Bx%KKQv+)W zFEMLxt+>yMycrko+v%~5dQUvidcFxa+%Xr~=nG70K~0MR@x_AQP^n#6siI9Gm#d)S zbod?e>ZEl^#9(y$7;Dq~^1f7L-R6PHt!Iez^asw;G2<+d0}Y(BEi_V|CRx&4n6U$$ z(4KSVGk)pon=ru&IzeLG%v4JiCkH&VB1M$HlT#dcN>c*IQUsQVQ$L;g%z z$e(ks(TqkS;KjrjUxtrt-6sE8QSW!@?zcG4ceQ5nIS#I7s?Q31HD^Bvdv*KE4=gE~ zEGjn|3|QmAxBf|C3Cd@Q8EJ)jA83t zyaZc;V=iw)WikB6NqDe^eV>>u<21qeQgx$&gIAA8FY|GQH-2R*hBd0Va7lO>9{J&* z3`2X<@I)V+n2FPBhxCEAe3%br$1^jQ-%;On8Z5C$_pkeq3-TLxOFt6pPu501;TiV1@U5t765$-*O^}unw36gCm1X@BmYITQRKMzZhkb3SU zz=Jc2p$fNcg+O#JBkVUoWv*~wIHUw^*ppRjrK=_S(XcVlDwA0?K8zFAQ{-`qx~x1m z^aWq%mFF62HoP3IH`?J+d{!a+x_hrY`szxj|ulum}x zmKbB#(^IT&WT7VLY^B76N_V%*JY^m7L8PAe&nXl?_wrLXa>g;>H_;Y!X8Qw*BP~Kb zb>n`(H2Z1LoK8240%;2SZ)?#&C~OQ~r(UPacz0PZVl~Ier4Rm;_3cJ7;rIU4Abng3 zjlCTnRLWOEN|zCT7~ZeB6;>G$esgj*NSA2#nl*(=j{?p(N}aVl**PkYoAx%!DqOqH z(on1%9mQ%7y(GG~5k_{DT?KZdHUojOI?16&Gf;9ghubL8kY=+S1IT^U@OQK@b{Nfc zZolWF!8lsDp`93IjZH)Yhwd1)vwIsb&)gJaUqFA3M46<{Lj)IS)rcz2aw3Cq3RvaH zvB}B%5xXFNnOR5^ODKW_ov^4X;qM@gd%p{c@y% zrH+6|1>e6y70GBR_#l885CVYrzaL`yKQz<->E~8s@s;Nu+FW5cqMI-K?ushTL2)qBaw&wRPu$2UO^yxx- z*6I&264-^$vdG)0!uya+S2wHsVKS<@aZe`$3uPnIl)Q^jxMC}b@u4mrPGU4_$azFC zxobGiF;_FB!VIfXlov>3ioh9i{6T-&`2xCgdwIwEf!Y6SKmmv%=GLIv9Qlnx<77KRcOR;+1e>_Xs&zCtnx^;pkJk!|2Pdvrg<$R z)!JxuD|pe=TEj?PGh^qD$J-emTShr&1C|f;(m^TNh|(-4bT10fGznIdFE6_WY^&*2 zn~>WN!SqnM+x8#&Xr74`FC4KUKIx}kV#i0FahsvGWg8&&FZsK=#Ne9TXHcZ6oJ-qF zXTGGZ!7?+FcCX+rTmdnn+a1fCl%t7BA1&!D59&+R_>$nEbCEbKL7iI$>wLXY)<>^y zbw|R7bPfu%kyy434nkuFOy`HkyJ`#O0kAvDxpZGHq9}cDtX0u(eK8c*TlxSA0j73O zXV-`0Tg&o4yy&a0E{|Ip8Fa;jjuEL!MTM|Xjo~H+=@i{{ODuxqK>Z|OSd@y6Cmhus zy7rtz$e2pq0akeq7G!w{Rp@r45ljm`Nyd1glx2TS1LD3BA~tcRtIJKAhS~RA19ahV6@~?iT@<8)dO)id@Ym4o%_UFcyty;9hMV=v~HG)y6F3P zOOB=?!kdxzV%KyBU6VwO74EsWGbdsA1(uAVeFoMSB))TWVzhJXgLy|KP5Wb`!1>GG zw7@{p&uwe_z&koR%}l{UxVEv}L7=v=`A^`s#IaO;Nbr8pvSv-tW@9hKnj>RZk~NC(_g z3o2$teDl*lmfrZ6fe?0Mqeoq z4K7!!c^U~nBnM1?zVgfS!5(+ldZAs+uxW|bAD#)FD^&eOiyQ-}@*E9f33;{t(4sRw z$cLQEqN(cccVY1F1j91>-pW+GN;{zIVb5OJ`6r0qabw9g_?D9>u7qn34)=gbcZPVA zj&_hO-{dIgJMRvSlpawK6o0h7i_k2oLB4RFvvF=dQ;Oh4p=O6t);PZZ%emHu0HykW z!tVbjqW?_?|NksF{WWA`uW(qRi>1EtHapOM3Wv5#+xbBC71^wgc|6|V_C*TR#s)Y6 zUUH){+1hQD`n{HgnN=eNt3Q)(WS7WZM~HK`CcRLjh{CFr#fj$3(uFUI3zE;WljBcp z=`q#+n(cIHvBT6{sR`5-2b_CS3&a7W5C74t-k);W;aDAETbC2}V9B;5|6pqJ*;`^z z+;I?9WD;b{xJ7!C>SrVOr|luZ*}*0ST~6wsbPE~rK+_w`HB;ua`#B? z;2R_6)0QjFz1Ar#UGq{r>;OVXn2cW>ZVg^;>u>2P0JO&Ohr2K8XHAIm7oV`?k;TRheU024vv< zff3ECAZ(;s@qjqZlzGi*M4LLz)bLQF$~NnOw>+afS44IxPT4}%4MIQY*oW=;u%S;S ztkSLl-LPm))pRP>_N9c>c1!VW-j(9T5pZdc8_vcfo2JKO)90())wqYIeE32VRXVAH z+6@u!v(5fnmiTEjYD!F|_|n@dHw%nInF2gBq>iZ+oA<~$bvZXv`9pPS0gA!rB~nv1*3`5{G%(HIU6n3g#?b*-5Wi9#uE~ODi4GmQxRm zjSNKtfzg0Vk68vio3eZkwbITW3);EHBlb!El8+GL{2N>?E zz8!_nk{oqp?W$c8yJ@K@WN*!%{`(N0axh2y>v8hzbGB;!&5<|opb^cH#$%|_^95ZM zeCisb0P4;d8nXjc+^!{X#|+TXKh)g>hsML@4|T6Pf6*@lPh`@H;Ezm^KYVC_JMYf!$dW3XK95LT^lOt}DhdfVwL*$gCMonaC`Kr1e|NsE9_m z9eAh-?(}^T@b0E`s4ipnMZn?PkjT>UI;#Z%;)}r@#V<|tDe6gS0ls@;6lOvKS|X5X z^Q#$E+6-4bixvxX?1O)YnGO{C^*cwo$m}&*Z0KAB?Bx-s5x`Q!8B=RW>!<@Zu(S{)jBrBDG3um+AVo&-oGVbC zQoO1Ip#Fw*aDVR;XJr3{bRN{9Nd=I&W)Op@x~t^MV=a$yhS5coyQ_n!n@e6-!Hg2> zb|R__QmYtNCFW=6(uX=H3*##tcR>a8Y+=vAPfUf@#Jz(uCWs|=OTr1q&0hVW@pjM|Rv zVJB5kE>4-bWY4I?(-iQcYMp~RCck`TW~Atzr#ePNV#F>zkvWz^Ba=~c)8-N;mM}aL zmq+3vxtW1FwglJN*!9@LXg_~(a1Y59q=p(0Xh+vKlB^dF{PBGa8`^ak*mkgYiv8M) z9|{0*)=&_S!vbXyf_^X*YAkcM*SNUal>bUcpY9^5w$W)H+5uu+vQ3DOP*k1hRYyaF zQhz4RzLEEZwt`qsjjBDq$Aj5M7jAF@@Ek*hNj11>x$i)s0G_jUY^Q>T7^hOaxZPO~ zcRUVHqbU7)7$?D^_nM})5_Co&d}N65zzy2wCF?f)1u}GSLvpFbU!t=4G;S*-^*Qlb zcKNL}I&GQ}YTm%Oqbs*2$}5daw~n9Sb+~2ImV^%l6y>-KBx{=Xg`^fgPvTxJychT; zL6<=|U`o|ix(as>|K)mH`+fWErZ>~gzPEe)IR&?Bs!tnbGk>QHadWri6N)lLJe?mB zIsmlHP0I(-*ekQS*u<1%!D)^$iDf#J23C88_Dm^RbE01*#xmB*IfcucFz7iO()%KH zED8Fms>!VHP>j`d7M8$$1jMakre#w!_yRa3XfC(?)TBW$-OX6Jidhd=sa1YLs(Rpj z^GiLtsRm`r5;_UxRfzXn`wU{NPaCTH-#|Eu+{kMI@=^2c2g4@s7*`pj zY2Bd&F4LY#k$iBcy>FNXl-8lm;b@J?VtEU^ntG~CUoo||u&#Q|X~?JJuQISBcFG*2 z)dAXs<3_b|}_JUuOo*4YvI@EIYaDs;II@(*X`rrfSo~#H5so*p3PJ zW$r9SIskZ2U%sa81%P*|B%{)RBuzsD|6FI4tc`pEm2mKp>p_uF5(o%>aTG4;W8a7- zXk6m??9GlJr_Wv1jMg6;MqNsFfSx=Jn-aIWc^#ipNEYCX3|?VY&otOmg3M6q%?gt@ zuA!x}5Ql79y#;P6)v%FK=;~r(~fct8G8}c zkrg;16ex!3lx$;vG0|Dde_x^RlxWcyz}}2Y&gwsA9(%vx+0;{>`ViNVR$)`U8oNfI zs4Lcc*hJI44cN1u-DGY!VA~TYrXB9BHxDXEzO_#q3UoTg+l4ZS2?1vdW{ccN;d{F= z4WQOe3-Ev@tK%#e*aL^InlN0gkLI%Ae+O37|5i6aQP8(AzEfFLZ{8AHXTmLtZo27{ewTAK>Ep?=>FDNV%pD*e;#HAaf~`&1zt1tQ zJKBcmO~eraLzzK@Z+e19r_oDlf29oXLU`?rA)XDC>8v=z#qeT~wIeSHi$4074Otkx z2Q>MA0Pp{z(*I4{{=b2DO|6+|KJ|_~CYpxvUVpm!kWKt`K`EF(!!kP35s!Faz z({>7t-$q~m8kYGLObQs5Irza`fclv zjH;_tsw~#x*z#3HM7_B?jGC$ZRTEsOpzfor$v3r%by<9`HvTlkM}{=M(QsEtK+V)< z4KiNlWijp;iY-kjet>~kATeJTmlV$BuXNP$Khsedy?isfOcGixs9pGmrnZjK<=Yj~ zhsN6-`heE!AI8hG-lX~Ph-~xP;Imb-b$bm}nTgngc~DZJBkku3g2V~8?VSOagkKZ# zPB&Al#2v=mZH6EE0h95ro7b?0p<>1aPk(eF3rtSBK(C*2(Aht8e;8}P* zLy4ww5Wv9A^(f~tAnP!JSqj@ufk2EiRIsc0xf>uLBmC7`=yh6V^;%|XfLrXE*XLHZ zr;Cl{cnJDN7pxSegn;)$qQGxhfvLKO>TSo!3?^AIzZp@p^TdKI2Zgz24>iD3mw3SL zJVVV483??MvHsRX3wAP|ErW*Nqdcl^X2#KN~#dg^!Lkb zrj5Ab4+DqhIgTnb6stBxSap64>2$&c;5FZoz`|&^MMn1(^N8UF5oQNXvluaw1D|*i57*D#a z<2EY|#?#&@c`On2D(r^^NxkwNSc)pmEZx4O)S@)^H2hz@y=6?_{g(BOOL4bi#ogVC zySux)Lvgp_uEn89ad&rjcXxOC{ONV(p8K4cxn?F$awmO3(k4xKvDWwZ*=w(DjLv-- zn?C9|a06#)t+a?|Cr<#~Or<&6+hf}0c{D&+IV5M;mG3b}0sc8Yj9Y5C~)kW>M*`_3mq zQXJ+9P3d_4n=(;*4B8rc+>imZyAduTfJ|^ z%krDH$XDtv#4eaq;ArJ2Dk6nzZ5)JCH-bk-leaA^ zP8H*?1BgsaN}M{T?R-k%8HLk@MD@nC3pIAM@DqJ{{Q@*in@mZ787W(tfYJ~NI&V5) zM!F30qiK`FRh+u0EsLsY$lNDi@|WXsy#Kqtbw)$A3!O55gawI{|9={ z{de@zaV_WM1=smbFUjIKs@1Z@b-gH-;`9E0I25y*~`IZtG7Mz;5ww4Edk)tu6 zmBzFydSzl~eB!RM1W&*W4N#H9zVgj$@=YeQ`DpJSml8a4S|M;o1tYNBSC8AOpZ3wW z{mT9_|Kne8#kr|6aQ+>7|0k*b`!9q461_+LC+MB({{?zyE9a~HJM_-{zd-M2iS1N0 z6#(=;*YXQ(O-o=KE`wsy2Jn%9mG1m52(TaLKlW40vZSHGGi$P*K>e!!7kNM4|3lsx zrW^ZN#;J|eVR2Cz948rwPk%H$93updv`hdx)&%JO%~<(ZR;(@@!``o=f*JZ#)zcKm-sdBRp;xiY)cc)=5{VZ z;L^`BSM=-0oZOfhD5VlANfvE^vp+pNgH19sU}uJJE-@a@8taJQD(}l)GPLW6&uo^# z`6gekE?Zl3t_&2hB-cmw(n}2l8{Y)qJKB3$Xys2K|IvdM1lasU%9B%&N8210e7A%$P~d#^w{`r)R!xz()yyzlo>0U#Jmy^Ra)imT&2ovf4K<#d>p2$sDq4__A8$;!@aYFe*at?yh2tdsE%edW-D1 zX?ru{Li6S~OVP8QS!udgE1T3zuR;789vQZ+o+UJL&y&(!k973t@#Zk6h5GdTZA)7%rR>PLM3VM-sqIAbo_^_J zY6pQO()FUP_P+wr!3|vnO8FMf0tj;-R?%=25~%Q(6m|xM8$DcHX#LN>9g=KyDvZpy z@U-%7h0CEsxbRM(Z*t?e#uRyYWw9!4M)t*di?b%Jib;8*J@0#yKP~?}8IUQU^tQna z<+QI7H&&%SZY?{N2#Y!~@RA-d@=LF*iPvF`R%P)oY^4OJxdgOJM7uGEWP+^dwM|Ic4rT=%(;hei@0sF@{-P*e*DYUYI4ICU$gQXf?$P*!|; zwoM(T@_(0Gyp=T6D3hg#GIFwva)<&1H5)ItcZIZs4O`AVW-^t#A{k}E@6`J^{9Pj$ zV-}C!{2btgaCVdoONJ6rPWBGxfsf1o1U0P|*649*%l89Zh2_7J*$L6}lIOSwgB4xz z5@O|k2}oKM8U4NGnsD#ks6h~oeqBr)4?yp=0Q8;*K<}FF_Y*00x}qUVS0Em|r?YSxT5tc{|5ad{T+AZ!+%_iO`z(4xMV?8G~R}&u`|wb_96X zx^8u!aPMDeIp!PM{t!pB*VNwf{|Ny(@#1^b!9V8;?_4dt{CNHeT&3b)9fF^Il;YuU z67PSB=zsHuSMsq!QU2_6=InL0+}0w{2jW_1oSj0wwHo7OS=zAXi&TXAWXeEVpM8mu zzt%sWB(zdz2a3&M%00u{GrCXkOU`5vKlswuX|Pq91jh82b0_{u*B% zJ-n>9EPOFJUyKCuECA`8GzGN)j4xjUrj{qt9Mils3fr$7l~)_fB^stmI9$mM*2`_4 zRwo&|XVY;xN7|2{=gY0{+8n7y>r&w(NkxOg0Bb`p)IhVF>oH(yCL(#N zNZgA2ZOz?O#YL2_NW8rhl32LxhM=3^+zsB6>Ff7f6k|a&ME0;VSNcn>zuv665%JAU z12rZKhOR8)?IUFLmAOzrP-fl+FTgc~+1@pLdKZCEwOiZyjLQ^o>$TKe?J)vqx}GI- zLT70NO&RMgQSV(k*R!3b>3BvgY4N`f0O8(upA(-V5fFl(@jwI<<>SW7(?g4wf_cQz zZwBd0T~Z-%#RG)4CuMV?4!*`x)N~<=wxUj>K6a{Td#}zh8T?~)=%8#jJTcM?N@bLb zsP~Bi?`9e})y?Hw=%38{CRi3fHCGqnN9O%C@fHNgvg#wyz<`XC0Oiik{5uI z+A!CRK);Q6kTDy~h~nMZR6`PeWZv5byY)7v^tNrxgqHJNqEi=7cU0J(Pw2Vg_iTik zqR&pHV*64e46e7!hB@~QZ6BQ^N8dZfqE`|}Jrs&yJsNtl5*5AGkGsucK>#ne>|6d0 z)cLL~c*1h_8G}3qPUbakW=Fl^U7R#HE4#NN{s_h51pWoA+C$L=@Mqnx$qHC7r}JHM zao^f{d^GKeg+-&bMQXf4%7ebJq125-v*1`ExPANe9UZ)x>nBUb*?kZFl!tAEwE3`h zs7;CEZr&;`7Z-+bLt8V6{%?ho9T%2s&u-y}gH(3n#(h~Xwn);rCr&Dv zM@-5ax7~>?^HeM%s?@+xd%!66LrHn-eN|b)3qAiR zX$n8WUrH(??D?Uj9tAOflvGcYuz(#Umx!eKMro!lrSz*kmatcN%Z}kd?rJ$To9Jq_ zq3o&=b96HJB!r}_+^5ZOx6m*?==3jfUaRAj-y1qU58ZnyG9m4G-#D0osObSL5`<(_X}cT$lGpQw7%Rg_Ddy~F-x z@?qF4i?GYwQ${SfxHp>wA@Yguwf;KmK^10qN&q;~SYdEG0ev9ZsFq&Xh)T8{3*{Wg z3CX2(5RajB^(~j^7qP|{delJe0N@?!?BCtzNV9;G;Zep-={=`N?SBQ{bGi7NsziY{ zDzH~AN1T87H_N)5(3a8h<^x@BH3qH5V$Yd>(%m*0?GQtXd{TKC-YR*;Z(9HNAQ*<=(f|wl~_g&5}X3*A%>J{Rs~_@#OapAuW;C_0{!kqi)6ACu zYRUQSLLYODuV#SAyBy$I-9o|eS{1_zSb>W886lb0*C!AQpgM4ILDUg|K#LJPr%Kq% zNSi8u;K<2=*G1dJi>FWP!!K!p?O0)1L}+mS!*63BaZ2k$NdLqQ=EB(!7ANU7Wnr<7 zhQL*G1zmHDNSfio(&j?_=6*Ah5rpJ<<_mM0M4H4M{IKWDq$nPOISVuVu%B+nAa@>`_CuPSf%xV*%`rjRa=OppmX;0j`7qR1hN)9T1dyfl4P610 zV0-~;*w%9ebJHg9g}rSy4uf$L{>p{`GB{|q&o(h`o29)*U1!l>LpM~KzVPds-8ZsM zGk-TX0n3pdy^l+%>=jwIg}mZB3s=S;_)h%?zSn$&Ddoo$VJ9Sg;qhR$Revq56q4h8 zsgd~zy<^W_FthJg-j4~QSmeCJ6jg&SY($UuQ6GatJbsgX>W+TvnWio98twf4s}2C) zb4ORnJ@^K_%>fIgu-!_CSQQggQieAB?djB$qQ4n_)oF&w=EGy%D*2t8VsKZ_hE-}^ ztBAkzAJuqMeDyzP<;}7Rg>in~oV41RT&>E<@Gx6%>A6ov`8C?91+reS6%M(+_Y(l$ zF(eZLXptX@N*^6-h_N!KGn5m*8&{qcjG4(6Wxh&76{3xCwlp zeo^G`{;D?hZz(B1B6u0>rUu(eh@id{g&DIvt8Zl4jQjfOu|!9NsxYv*b~p?9xQCJ} z-2EysB~#OowTD`C@4DGvYA;hR)Dz=z%bwtVzGzihADPG2SH43`P@|claP=Fon@F=9TBf85Mvow3E^Dbj}6O>B|NQ@W^yfXH!4(_@y zJ?dG*1HCRki?psAiTUX62HEZTN?gDmHA(22F|Efnhk`5hBBAeVOWtLE(Bv8Dj*-VI z=@{TQrB)GeaSYR1-SKj^pKAw87Pp#E4#Q53f&u;mF#9#Z$p_EO%U1UtyLW5~rC}i9_l#zSRY}W;B?rYIbM{qi>TFl&5Vo=Uk z`7HAdT;(n;3 z@0&$9&<=JSpf~?WQ^Nd7Q<|Q*PWwJZtEjEd)VuhXds4%x*+z4A_S9L`Ok{7Jpn zJ(JEXlD`lPXY5LZGiPuwYj7=VSr9jQX3V$R!Fyeg z66t9-k_LtQ>CE=%;1pv_Ex*nsQ_qf|8x2999*ZGsecvQM5+fvT zY46+KdMN=PZN(2jUq0`}&D+&_3oBIE06GspF&bFT2`h?(KY>d&K2(yA;tv)4xk+V~ z1vLG)_b(0&;$G#-%&ZhRzfQ0rjwtgIsd+TC<{B%S)anzWy@`)qHJ9)GoN98M$vJzY z_hN|cYZC}007Fvbe+)?#zLr<(VaSzIF4A3r1BRqAy=Y7yLsFGQ7R#|8x(XZQIDnc+ zxB;Ub_<^}lTJFQ_Cx=|^%>4uiFRYK;I}tbTmkY9NXBWu`1IVV$*Rm&5^JtFkpx z5{&%OkKFq@>BoN3ys*1*+0uTm(Rc8o19_ly#HsO_lzKmK7Fj}WI^bnD>QLP#5!;Ad zyQoo4mYl8^)8m;7R`%V{`!OOzi=2CaRzqL-;b%sw0~VAnoqt>jXFWm|@JPIb`icLl z8_wA<7}bjNLNw~ArFX=F(B};OzHoq6h{Sf&DgB4OFD#$+k}0IaHdB5*xRJzDw-8mM zbf+Tr0p#AJQ3?1>VfZpiaL_GoyWW?c-_2gfD86ji>cb1PJsFV>STUCc3hpqLQ~&V)%re~i=K2P`PX1W<9$AdR9LC zBl=zkh`!Ioqr|WAC42{8+R#1?_%?&jV8W@ws9^gIlZszvfaz5KgmL)mNAY{0sOLj*8q5ebEe=+jlM&GU4!q8fHWuIZ;BY^aMn)Vg^f?(=7g1;d+zS- zb41|J&Xn8u{61EcJ})FGS@@V%agDb8e6*gh+$zY{CU3 zC*Xw0mTPJdvY|ZeGWN2o5O3Uj>AP@R=>jwaH1U&q!9{x+{>+qj&H+1j*PuLSxv$3INet5sOv3e16X%7GQ$j zs*D)c_M=VybS2nlS^_Rnv%6 zPBd_!W?(8g5TKGPIHEhAu3oBjhA7TvDKt%i;)N=TiQ1WkhaGk@D)(WI#;k zW#W>eeO*jpvkc95!OqHXjlcYENB^#%d593UMsP>L+WDZV*v71SrgJU;&pB9G<>Z7s zRsJ;WQ!xKA**y@TEn)u*@ZaGK&Wi1bY3b%1GHRD(En0TQWt&hEhqlEvx_-L%(DRYw z-r3kx)#mvw1Hw7leU5orC9u8Ai~vhdjmSljqX&yjC41ke*9p_J*cF{F&|1j`@xqST zFC)X$Vejm{bG$6_lZ8s%OI&9Kv!y>4Y~GMfT-=y~Y73D%!WBjckkYxG1`acGX@O4F zdnzch2dN+^%w$De=1iJ<-TS~sjzTfq)n~xbxvgPkoOQvTTqDMBDuzXB5D<_uV0jOM@!PBgRMtic6Jxx0FYHXoj2q!8e02?It2%+ag~Sj`3*li;wm5dUV%PAscq+KBN3NjJyu@5 zPytjsNvn$+qbi}Xgl1lpx=l`i>NDn)y+0(--v^-H)*p-)+n>T;8= zZL^fFW_52(+9<4KT1exadOagnz~eVvRPN1e2j;@yNwi5$rO4V2M7;OPkLfR4kD8{x zGTGycAM4zmCc`2kM_Pg*GF5lAq1WvrZL2*@KJA+WvN?thjisMBFBAvO!i0l}zxC#V zmr-{rXkCWAkxpHp31%$P#pe2FX=&MnT}QEB440%;AaFWTN-C(pr(Zm!IQ4px8S4;O z{Je!>0rVu)18JBZ!-N9^0-IGk(fmaO%QnlHOPjb9&_DeuN(+hh`C9ii%aiy9Qd6%= zoJ#lZ-O$iS(MMl!B_B0+r>u}O!}D?zb)51-sJ)bqtaSw&kA=~BMlI=c^n?-C4ig#} zb*7~O_}!uT0yYsPFQeBwtkKS~n)_F7f#OTR)i~$YH!Rb~ z!tbXUy)D9ck=74y#ST&M^+L)tVJfOgws8;*(Ix9+u`#BfO^fcEuhh(W@LQ?EKXV3| zvOn`f(_jzoQm>N{3o0>ZE3-wu`7C7?yy5@C7|bpBOevlplh_I|Q6XVQA!`<``^qH3 zeO?H*Z{o+HQ)(A^8AZskObRHRxz~a}JOF+}P{EkA@k%GjWZb|rjjBO2#s={BEp7Qk z7)!9rrIP-{_H z>n@t}=^{Awcvxh8L*3v?uy;)b^63h!hp*aiBhyX{^z4mV+=Hoy5NMxy5(1z95AdB5 zhJ5tyZ{Yi168hgf;gxhh>Sp-PXn1I74(dC#=2m`zuetq^P_q`T#>bGru@btmYNK+i z=ls7UR8k+KF4Z+25}#G!%aEFZRKwFGHEn%c6mwKle=2~rm_rJWent)MB_Tb}c!mU& zY<1jZUc8Q9cyDkVWV!Hq4HQCdQUN5C|3gA8u3+*ae>ChVWm*V2j$ninzTH!fnM53) zBIS5TSHHn%zXawqt>-W}tFXCRt?1G$VOQWI-=&N{ zuK1GhuN71h+>1}9hMr{wg6gm%BFlpJV!Wk|Ku+0z74@v71AgHU%V>Sh0u})?7$8BF z_-c@-=K})aMemQhYOD{q-m9Sx#?{y&ukXEc_}V{J7pY*W!uXugT5o@jEsCu6<0URZ zDYhCJzAM}<`fCDUj){+(5NZ+~5(BNm`wf}w62xFx95kogP?$zeoDND4K@?0p`3&kC zTB0LhgUC1S^v9mRcTJUKxTWp}Tfw#_-!=I|3=h;!%@vc4J47%Lm1MAXQ~2pwCqRI)&ZiB7hjG*~MOKskiQTIb z%0qu$!aNdmw3$QT2=vNopb_ydI{1`cUs+hkZC|1APwqG3OIQcE;_E!pbvltv*9jyv zR3T%ouTrcQ?THL@h;>r;scC`eSJfXniV*e@e6K`fg}M8D zp8Gh~f9YtNRr=n(8ytEDZQ288(xndSq!o6iSZ-XR&TaM!wU^q_iP|3>U85^z$T1Us z;5iJe;8dU2rdHM6ciO-zp>t^N@xNj-O|umriZZe~VctvY96@&8=}X-Q(0AH1gnrGF zz*4k~Elr1NOOPMv?#xwlzlrv+BRO^wnCAAg_BHbt=jH$O%>?coPwTMYQB)iR$O?xE zlGz33T_jHB`hl5VaRA1calqx@%uWHxce)ENpSC}JGwNT0%1~$7+bMGjKyr9I?lYK^Frq@6+!oO&>mHLk-q!(B7nC-8xk=hhIV!S< zDd@Zy{bH=!!rT-}Rahp|OM9ceW$^23gsVk*QU>|l$tE#lGmG~fjUUSq2+rp`a}QnK z*3QN24BPY$E;<=&|J-Ddl{T9o@;B(6{eOqv|2(PN0rg`7BTY0;fG4#zKbv=@TgXR~ z0R}B4v9rqCN20}kMmMdVpw>CHq4qqNbtUsU;3M`fltf)fOKXmf@#2@y5J@x$=sW0~$w$vI$N>Ufz7TjQZ#Ika%OD!$dCXs89lXqh=P zZ%W>!)t5NT1(#nbR|kuvcFe-P32Y}3IZ0B|1$xAoG+vZ!tuf7tt2A9QnGb_h7IkrerU!}z#uruG_Tokeer?O>^< zm#X^b&fp7HiYj8`-p}7j?CGKtH#RxQ_K>Oy7yO1WB_njc0$T|PwPb(9DStLeZn;Bk z8dni`8*A|3#!VA4Qto|fbq(g9lZn*+p3vdwq&3dseIA3?fA^5*2Ic_rUO<(||8Ae+TEWe0f=?PLqagm#^(LKx&~60_m=$ zn?1pr4h>sj{bKl1laqqM)_1yySA(>VNvSJ`E?lzdt97fg8B*l8*n)A9)rLv;QfE(K zBpfy{{nA5t;(GLEKkk`aGm9W|aJxhLZCO}0`;%mGlm0hevlOPIfq-DFyM0X4kzwqM zpfVK39stfUKSFy$!N~k{OcwtfbXH0>Ft3WSg-lryJItgsB}T(oDJD1EjQ3-cU)cbN zaaCRq4g7)tDpa5WeoeNE*(7(y!qmr4_TEdE18?^C)-0bD>nn$pEP`rb8eDWR)l}|M z#(Stc*4Z6whIHo*LkgRMB>dy|92xP<@=`=)hcLeh6V%WcrfySsw{>+SDso$NN}HNt z{5do>^*sumn?{N*^=)%U>RK+Uny73ANbBNFb$H`7Bf8(}Oilcas@>+}apIbyljc$g zLar^|vFeZl(n#uxtxHLJ)COh`zNbCVr`KtQb;%nuPUx)LfZ+Q?_l;R#0XmGG_`fw7 zv|^*<0@%BW?$#g~4m6{kI|#Z^#^CUGkVp*SM(zM}x`m5;h&xEJEWD8^(^_OrK2!K2 zA{y??m#+)iqAap7xUKhD)y%9QK1oxE@ORxis0y z6aK6@{-^`%lm5YM&2M(XXiM>zKzH^CEdNzC^Y6@k>ED=pqVjguDhJx`#Mse==R?NE z1J}kwrlSo`(7$)hq<<_X6#%+s5;s`$m1!&r3-6nAMH?zYm(3NlEm1}gsBkJQaUfIE z9H@-VD1MnQuV_(gQi{rkH)o=6=)~B}H^2#pJXU>ORYe@{AX_J=SduX?)>;T%2$UApuf8e)RV1A?qN5)%GU_jT*IQeDs*FRk| z?c`=`0R)VbCn`aJqM4h&BJXKer#RQgDjUjxPOz;%T{EeFI>E>c_SoFUg*}YRjvNgb z`@3^77KWZ%lV5F2}eILO0`642g0NO^WWA7yLkf zm^<~Q>yJCpEC`4KZ2)u6k_OC2b2bc5wWc5Gjb5j_$Botgbj@U`riiSb3bG}dM)A?< zTDl_ROY&klDf^8lC-YR#Mokj9m*#)%xHYdp&Hrjj1z_&@=oZd7eoMiAO(>x151p;9 zA!oM#VD1y00Ome1^Bc*DHH+RC{u3DTE@XMu&jc1qwV8Z#@+Gfj=2(XDASsS^qmU<)F;`(h+H#YMw3HM06Kv&mE!+3L5&q_z z72i+*T{9K~;vO2s5iu^PH`|3NnJa+#D6FXIN7>9lhFqvOe(N2eZ02Emtp+0`!n^zg zW<_rMYW6*=@~ma{UBBy_YH|7bk8#Wa>eJfv%&%xFla357yhdp?m;(YI%pLd-bJw*4 zi1ZhKG_u#^B2^>yk(s8(MN(%h;%LcFmmka>A=^TfKl=}JKW>dLiT=af$xhCLtWomK z9Yw+tuEVdw(s7}&$m07yL|Sw~HTgrNQ^y^g)}`ni=w&CDOJq8Bg+FS+xa9%0V7h!z z!wMn5+HymT7W#_cOWDXsTYSi|V6cAMVd1l;ynnBnsfvq*n8{Ov)^OrBj)R55RzwYO_`@U1kXaFd)4Xc5U$?wD#J1 zhEnHS)x*cI*t}sQ=qZTYxJ`Yd}mTXFYw)gx|3kF0|oriTV)zrOCrRJd!D}n^}n%%Zhnof4;6VnWZ zaEL8UB)*e}>G5y1U}qoONf=%oS8u8j7hcjzx|~vLq!-!bB@>M*b zG|a{UxPvgcAN}X);GIlU`F*f=iQ1>8ZTL3ab^*OWj zfT5{CAgmd*^a9sz&hPg($*Ii@8ptpjQ|U!$q^s|bp}{JoQIlZ#Ro53%lbTtbFDW*U zZMev5btn5-Qq9aA?g)x$jzRD{;n^dTv%hkn+4lCi$5*6!Bf5r;EZ2#P_jC7ytPD-r zJ~CwmF!f!+&|TE9OC+!*FrQA4@2%B>S zEC%j|`p!M|UO|M)#tt2-8ifuvpcM93Tkm2W=ERUBu_7G)s9iqdU`VrD{vdb}rtH+4 zj;tZzmKW+8d{A49mOmDu}Q{6_jY- z#Y$T zKZnwTWIGB63PE$r2G(VxuJVt9vP<=a1pJfJZx?_+)8BrQ#NF)=NuDgwrY-`_&)dX& zvR5D;(T_!O{ieRhU9WB&g;;u2TWN&eBpuxaq$4QC6 zFs_M}_Rb}5z?p-2MtTpLSu8-HpX@lXkL;l{=z z)FyuX+X3&pC}C0vg#`l&fYdYGXg`~7Sb zT&fWr;*u0Ka)GRyIhiZ{CvIL@OQBFo4VH<+dWgCI7pw^29jU;O!-#p{yf9t)%m9r8Af;m`_w5$ z4I|QAddCJ%MTzyIhwxNq-(RU{bTk^3`37gfZ!gEgqWue-Y`n8aF1x-QfBfs|ZE8%~QOqTPaGya@y0r~c9-|>#jy*lUAht)nW z;W}*Ig7(=JG#S(F9yl4BT9RW9C@Ew>#;cqTF6Jmm4#IEBX@lBSqdl3Q_mr8MjX2f>z4+*{DlxDh4E);e~tc zxbm}>{B0folv;4~$_()I1%qhDTu*gcvj!rMXzt*-xURzOMR~E#D!%PSDG?{ESXgry zpFva|G7@>~E$4DMojWGY@MnS&d@;;zCF@~bUj8G6?|vh)6?Iy7*nWaPkdjt0lSLf6 zBDcA|Jw}4UjtV}pgCa<>$rX)c$K>hme`jc0cSt;}b2EZLx8m#>=Z4XbW>Q0!v8Wm# zCJr^BQJW{$46Ij~ALUEa(t7Fq`I$9j5U+P>nJcZwfpjV0v(r$TtiF~Hd9as3@}eYh zjgTe9#G>FFSc+a7hEo&2$0A{-u#qGC{bEuPb&Ck2vU=ik4G7vb#?z4n3)Kf#9j| zjq4Dy_jx%Aj+TdwdjI{Rk?gK#6U6!D983N#C48#c%n0avny$L484Gw#|6am`J)KHFLjam!B`pzq6fCI;BOu?#`N)qmn0vt>&xvK z9D;>nkQ?i(r7}eEj*w9kwLg7L`6MLRmp;12FHWG>@0v{1f+(U@bVgcW4O05{dfvvf zoZJwB6O!dc&mYTzza`J%VlR2UgR(JyJMN8}C(Ub))fMv^ZqQX(yDh-A3Ra(c!P(~I z0d+|9-th8Olhdcnd|f9Nur=|=PYYC|zaGYaJ<$G2)*x25jcRT5KFbY*({nz9_=!j+T>TlH!@ejP zP%u@hybo2CCIcgB61#GX39APuu*{HAQ2wRJp)4546IwLgoWtPBl_8oNZ*Y!C2QE3zK;(tJdF7075F&Ku79IN5pi;2Xn3X5;#kZ)bB=;h1LB%I8F_=TZ;kGKXQFT*wKWSYV| zEA7$SIcIfjdi$0ja}4uh+3g46u4>qLvWXMiLA^M`%!)DqVSoA)7l(OB=Sy{}8nMKW z%W0W77mFi7r1AR4pbo75*I@fX3)sZy+P%?EZ}yOl)rD0CC2mi#mKs^6zMVPF_JZ;hRk*mjvXpr^ut2o8Z;}mA$!*Fd_RUH z$85@_^KwDe=QOLw8FNj) z;0&pGO@fQ)w?srTy3HH{y)v*8U)Q0b9ZU(Q$dSX-QVRKOHd5a2yw4C>h-a~&6EHbs z;Hws!Hh3-FhXM4^-a9}g2-*FT#qA-C_lk3%-fxY%KG1mQ63yGNx|Ri8yR~bdqFVeU zVY%-*3m_yFWLSLnwyI{%Y$mHp@L%Y>wE2u%+XG9ti^eHPt$Sl+ugLRKm`p%w z?FUY6*|lG{m{&`#ngp|aHrP%StzVa4^^@HN71{1Inw>QsU0Z}WVEGk)`e{L2Tq)g0 zn<_!|bu=lLH}v=gC74|~^Ez2Zt{K&E^LoaRM!B5O?vSZF4rg!LY`jI@O%$P{>W7~@ zIj-rZ{?W6glR2uxtz?FL;ecida(S3&yKa|*M`HAs@LF%qeAebaUV2=}&2k!_` zmO^|e!MF5Rx`1q#!J$H&l(C^+;g>Ci0QV5Di(UU}vAS5TA^W%dCCo0^Q|y!HVKH=L z$EpYnXR_x`4cxr%ahPPc(m}NFYVl0-$l$f%Oo%0e;MR$QEEr-~^R2=nrJ3OL0f!BE z)amkKls9OXV>NQRsnS-AalXHgYZ)g%%kFO=Ym!H*Dyw^U%6Z%i?x3w*HMB++O$NE@ z>oCY}O*q%he#HIq`Ip0BT$WVoZvZ#-g#rSi{O8-f|N6W8U$p)QDSJs_n_}|u?pA7D zL`i5U>1CgFGsfjQ!=b88<&~RQ71RN?(2<(^oFuJ)%0F3R$IRqWEtwr4ztdwen=p)2 zPg)N>_7r%IVVYtW+U!IZ`aL17m1#H^N?SEQj9<*>CqH;!IJ!=}c>Fj3By8JQgkEz% z{0Jy;{J}CEpqwUw?RwU)HRl9ZIq`IUwvBy>B?5mnzoUa zG40goqAMq##e2aYjyB$NiKy%LlW*1bvz8HX7AFJP8Dtv)Y*>lC4Pit-4lH^#R(h8J zykW(Tqg@;Nfgsy1q7rPsO41d~9=@}E#PG8i5Q-5oIj7z|Bp9)If9Y_Jp&nrq>eyZ%Sljp zRB~7j5eZ&B%1LdgTngv#XD*r%;F=kf`i2Hp3F^0^oZ+$}5k!73C}E3L-T^Zk_8Ap+N>k66O+D5o{nQD%#h<2E z9Y=cZx2X_gY7D$b!2(*`P%GGG3t6qc(H{&rvnx zPjp{{;hcOe!jdW3rYAei0EVRLJ}8=PxTg|9qs+z=t>Tky{=b~hG@18~Y4^j?LcWfA

YLdf6VE1-o&{m@Qb`?gWyi9hW7-tr#)QRm-Ov1qY4p6{rUpi4cy75U+_4TQia& zK*kNn=1WZaC_}fLCd^2%T%!u^0weK zr$T{y`>4l!PMgS9lqZTClY~Tzvl6(Uq>}z-oTpRCSxu5;wMc~}BlfFeWsZv|0r%AS z2tolnE^nmJNnRkHP(}#)EXj$^y!b+V>eIv2rxWG6jC%NC;CWh!I!y|X6pK2A@yjS@ z=&o~uJ@lUQ$W}cJwJZA5l7i2Aj;v~KjuD4oQRC`WLF{R41~v9h!~SECQ{a`KIGkLN zGIdeQz^a5}s=>8c4J7%Ux354Xs*f~{MSbv{<w(IFdzR?JA=vjtNccsYGzkj?%pVwtu5`^#RMm>46;GU#&NQ(B)@xv}6u1RHDmf~!Xa*E_!Zx?y zGR{3!zMex4>rPqOAN*P>Y>=;@ES)x=rVZCq75c=L)0p!kb3Jam?#s;3Feum2l2SX| z^4PA}_`I_S%PaNK9xF^sg+?|B!W*yNSDqMBoi5|%ZKUjMhjl$xqmPmPm!{xKNInh%57RCxb~!3fTDqUNP5myXwl zNk6PVb+8=m?LF`g@LXJYWo_K70{rDP7T_;ffBB2lB=2QF+g?LSNTV}%tAa0~I=yShL55^`Z=FVUKGXIyq=pLXa-o*lu4%&UKomf4? zh{?yQpbUu;5N{V>qY>3;RCzfoiRU>s&C9I`+hf8K(D8ysh?wFc`6>I$TXl`=PCAhB zTP&lv!uT&ld&t=E3XLw(P0HqzYq@e@HH>TAlaLjh&3pJ`Ca$`*^_MsGTCDC>l|~k@ z1}yz$u^SURfX9eB0-Zs1-Riwt!F0h>okBn~D))>du6_ww>jY}x!YXv(&0KzRGA5e~ z&+u+OYOQuW3y+1@vpkbj0uGjtd6^uH;o@PwA!XHM5cS=6(l9f{PL;0k1*#{sYw@44 z(HyK?O1=Dyc*;B-cw4^gl;hWTo2b4DZ$xh!FM`9JHkHZ&~ zzLR@rPj^qa2itij(Rg;`?BQzxOkVg|Vi+wSyM=-c-^P+&B)*wEN4S+=*EyyPMVAk! z)my*gT^FV~Mfir{mN$xadFn;v6f1C#D2Lv8PLN|SK~b6|7;|Nt3Uj8&>-j35bPOrl z4puO*Yl5My8ZQ2`S9FEY+?%WxXIeb35#fo*d1vjm9xF9gL;uMX2h2U@_Fm1Q&rzhd z0Jp$CtK=!eH!f)Eu}VXETll{xE;fn^I5zY>`gVHazuusT!{$Z#k^P~qZ*RpUM;G9t%I^nN@S)r$=Co+cSScCK;uxdtYEd2YZYrER|KmY) z^=kbJBX-)RdJ|RKXu0~1!!sK#K;2d&D`5f{Yw%XXx&8pbw9^19(ia85z+-A)K0HRF>IpNA$$*K0 z*|uvRj6602(T4!z7>D+_eBGsOnL(tB(n?4IJgl!%KYf<>9v~sizMf0 zSvHx&dAkQsmWmNo=!OSH>lRX~UtLRRP^A$Uzn7kWPUsgzu~@YtC41iD*bn`~V?c2a zi_H{Jt`gTtY6W?<5k%SIPW^ftymJJnpE#P$>R2Vrnm;^-K(j7Q4&X6~=Ss2A#+-!J zg-P<+iy7FNW7kOpRw7Z_^#<-7^}SG<8%t6)jwz;g;N)ffW?ge3OhwrH{5PgkVVK{R z{AtuDhp6c;x{{7aEP2&-7}D8 zv@p@$>k_m1e!hg|UF4xmiS9IG4opJwg4C{DMP9@pj*33viBpo9BUiz$0X*i}@-L6! zjG_4dID5zFO4n^&yJFk6ZQHghNyTQxP9>?>wrv{~+qP|^k~*X2+;g3^)_3;YYk#ec zwD$fR?ahzt8u!!t(>tVRME)55Jte>~{e=jvv-w_}E22*&@}F$#<*?);7RX%*Zn zl|E53o~wS@S^U8*74-1W;Ff+Hs5wg==^6u)YGJGe5qWR-JC7aaU;xLU03730&+)+_ z;1czhW6DHjw%30WGF|-_{{bdY<3rl}FCIaIhj&WcR zXFVT&f%wBQB7{X0IsnJenbI#OxV3v)JF_^FA4Q)1+fcrgg&xT#KmhCj1VGCFIK=#Y z5^PkNfDa&q<(Jvzxo=6ub6x90B+(Tf>|u0TiMZki_5CuJN;WA9eX&$sNO!12+{cm; zG&+G4AuubSr5qQh2gH$I-h1DhnkywW+wT6OLZY`2=*{)br2uA~cv0Gs?EN*ezAjM0 z-fEo3UA%#^yj+KT_C_?jWPxawGPJgLT@BNOwS^F49vN)@&nQ@#I1C4ff|hzD`Pdgh zt)2F*Um-COmAr`pfR01KRUxqv3nvhLUN?z-*%{NLFOh(3>rqXMfY9So{B4s4-=^sr ze-M!`ADTc8`q&_U#EAVAM_-*@kr+P&OVK+XMfEDGQIMMJ`nR*z(a&?;W50Vp0P_B~ zwb6g2!>>jL)&`FMLE+8jzph(8u67BJHU5O8@zBtjE+i-06l@ZlWUH_$M+ELFGii#!-R(WA&J*@5hp%uwy<=LUTL-cGNp>FnP)6Oy@OD(w| zw}cv|dPr6sC^<8Y7#A@7)NKmMK36ms=al<6(oMz?F4I)@9*fh3jC5^1Htd*08d~8j z?nJ1blEH~0OWJ!?ev|~$W0Dk7%1)s@Cjy!)wEd%G zbyfISaU5HnaOi%$|oWC#g8M@QObf!Fvb9~*ICk9rnY@syGD zr2AIvhr@Z^Gj7RUR#BrMi%+a~Be?eUJ)pU+k%{Y7q$jOm+}V;`r~H8^`k)+j+b%Wh z{TRq2Wl47&3!_G5ZgEINw~%*1w*s7rw7m$l1enMK z+>Th5BLdN>w7d%8t-Nh%T4fTkRIzY7|E1miy1#Zeo&eo-8G;9QfWR}{>X$V!J_F)Y zT)#8fO$u2ROPDXyK&L1z(8dF$tk4ad$hhS&_|x$T8V^?_F3S;G`NtzlG;7#Him1yZ z2G|DvcBFrqsVSv-hImpN8XX&k;#L#bdH*SP?Jy;Op%{U#N4<%;r%_j}x>>*=Ov_E_ zK+J@y09sno^(suN$ey|iB*$s$f|#Yc%;u7Ey~AyU++$~vf#{MzUUK9tT>kfu8SRy8 zD!l8uX^VhLgk*xengANvN%rVgjOKMd_81fT^`%BLJ%M;kk_np z8Z3h~3o(#sgZ4&{9B?~>FzPCp)lgto@mM<;^BtM85GBb1W@KV?R;B3~IQxNq(&-B@ zkMp+h9gu8AF(;q#j|HK`N^6DK!P{-7xnMhCog}8kgLXRyYa@ULY}k!tHR0wK(*he` zU8XrrDqq5293N2iSkNmn2dy5w>%->*lQQH=k3dwpbGp!S$X^oZ&hZ0%iTg#wYm=rM zu8=_qU^*XaU`&KS+O;<0dv$q3cL$mJZ?s$4IjXn=v_z5*1|lwtZ>wr82yGzU^=-+dIJfSI|u0cVcM`wHrOgHA`Y)pffXrgCwA%l(P)<0eW`|WAnkr zJHHP^*N49nX&;t*l5kb)l9HE_(%m7-{#T%MX*RAtDNh(^5q~*R0+i0ro--g_rC={C zm7hV5hZNKY=+4|?8xiq%4JjNjmzlkCT2+*Cl70Rk42Jg!H3vtG??+GfBQZWd73GyR zpJ1EwTd7$!D3LRM%(OmW?*_n{xjLZI;40}IvyWFuuxw!khCbOs)9b#`+8;VGNA@$6FkH=&l4AzXoB>j{odhEHkXY2LSJ#c1fRJFl5)L0T&fVnx{%^;xUw?rJPXQ!> z`X5Q+?{l5a|E_RaRQg}J^w8Uli!jMkUWQo`;G`QX+z5l4j;-~)X%hwjN*E^plH9I@wR@HahG+} z@#MYbS+x?UIX%o6F*U?!(TpvEKufSesQ4;oBW^ESKv~_^12X~-IWRyiq+hP@5NOv$ z$QF!x5CmR(t10ik@$s5bQ{=Q8sIOk(a0!9spm!$e6qxn-h$z!Y8kR;-!2%a$o*EPx zKm3R@;hJkQ7cf~m7#V1YD*=-012;R@N?$l4Q^iOVf0mX3NoJnH6BLZBj|kK^&~T^M z%gU~s6}67~zEHE6FrWRb`0hA|vr-@|^xH0u$LFoFVGlQVcd`Stz5+~|=hd@dU4t(X z;Q9nWm*m@zJuI+*fj-@Q@=jkIv*Db?{KLU%Q<3--KV@gz;2HFyfLZT>>nd&601*(E zltWBX0vZ|sPwgrOCP(L^lPeRM%ITIaE@N(Ak5=W$x0b13QcV^_xm$_)ZJlt ztQ{p%7M$4Y25BABv&7-8MT}jvf25hjsu*!T;bPj)RuHZ&EaBPhIy@94K{FzyGpLEG zXPCh~$>{NMQ`LB>Rlz0X7>tKoiu#8Q2t%j0DX=}jq*s65oYOU(q^a1LaUu~I8a^Op zL(Ab`h#8Y1?Unr$tD){zmXMiI7w)Ub`k8Kh1$kl`3*45@p6|qc$Dgiq zngYCv{8f9^Z9f3lHGV#P2r`;q{Eca z+q~BhdPf|uvq^NqV)zZ)l3qNkQL0;mBf|1c+7@PRm3Vj+_m!R-6uqv3Io>(bkX z-*iGB#cyk8m6{2-u|g)JIb!@V@kmR;yZ5dvlpZ^#Ak+K!BBc$!25u2(ZI>3s%^Ulr zHJ75Z%{wx?!kKJUwKa-PtZgZWO9$60>v!22>i=i%m^J~*1i7N5+y zgUw?Y!}Eu5A7Ge7dhAvtdW=VrG4>>ynzv#KoP9SHxb_e<>nGCrvG1Fk@e&H1s+B0M z%wc5Qt~Z4*T`_m!BT2BqJ(ncb)sbfk$Z{`3gJMz%v!Eumu z_ioQmpo+eri7#)ng;RDhH8{crjb`{MtL8e3!{U~!%q=1}$hkms^vr?5uZdL~^< zA$iQkb1fQ-maku49q7D3ijHA;*cftr6JepVmbP{$Hun;i_-n9l0}P4rN)kN!9s#)? zRUCM#&><{S;53vdE)Fc#3Ud5KrwE-h?aD#t72nh5ozLbGAXa%#SsR!&GJ}>*3L#oF zgZm?p5^VNp+@?~IaZ~;nE3bwGuG1JemY1HNI~_RtI<8T0_(`v7KL0d;XY}lm^&HYl z1~6IGgr{+mk1&W@8zMhouvQIdA6Jz`639z>FJv|_+z~88ZOI?Uuc|m3Z@z zO=Em5{gtD`rJmAJDu57rn3h5OD_b#r2z1yRh$23?p@E5y5hE!aD7Hfzs0BtLtEq>u z!F|5e>nGxy{AP0^yoND)NYt?1+b|zsF=+4&y&{tF4lc;gbUh0L8O>%Z?py3eW=O5U z;FFZ*OP?lF5@>gN_6|l@7#GpNKJU=*d|h|~MYt|coP;1}+AaUSf*Gf4R4npFZ+X~dn*X(s<7KlS5N6QvVR z@K;-`0}B^^UI^d}aroiRS?38lVE$BA<=8+S8fxOTQghf~M|~bf@;ZPi@6h@z`{C~L zp~=I75SyK{ZJ|P=5xiQ<+s7*u)9R#8w%;+CvI&R0_lL9%`Q-%VUUHOLD09TE`&-~T zzY~1Or|K^6MXN=0J_sCc#%S zeDf{u!_C))$;YTv{spd6xKE{?Ke56mO@)V{;zX{C-?9`A60Y#a3uf(c{$b;OO0=Pt z<)TE?a|so}h@4owlexlF%;h5@9bVNr*5VfaV;3))A;f5l^LQxbU2L*LS^L-}&sb4) z0v{%IdMb6gE=~O)Na!WYeoJUtDAL?XFA|C~g)V148Gb+H0tDl2FlUo>Vs*_rVv?pc z(5iv89*KU=!5Q`oa%3fmqlJkX#-86Dtl9YJa=vUZ+9MdZ;x;_XB;<8qDm>e|WJJrb zJxOWsUYb1iF8X_ciT=8>H$y8|r~N!z{72eHfseALN*GMDK`$MS0r&m-r(XiT!Yx{}Me_hPGxwZXZIh)k14 zv42rs>p@xjfuUs$wz?8-4wdGN(MW5%c7{Pf2MqYR%Zod(3D^T(m<|-cSVdRIKm5Rm@$ecKK8a z9uo(IF)q#nGS$^goKp_ea?yLo{fUEiU7||ThtZ$jM6teuzAxS%hl>~4d6|f!Q1-$ccJmpCIHG!tmUcl;fJjC6 zyL(?A4bhlc*y0GU`a{^Y$J<}R$pagyWNaigVX)wzr$DZ$gh=_whA&VSl(lKz-|gjb zTibP*3g@FLx+9l!rhJZ72$4Ud_OdL%Uhp@aGb_KoFe)PCZJY$(eU)!sw`B)v4G~b%*_RV~H-IJQe_MIs>iTC5afsHJ-&LDP-)?(!W*S*!8;$F#*=O|KC~X?*rQZ$2#SISqHI6 znCJ{aRW)fl`nPq?5I!dXT4|{&$7UTD%5&Ga`(%GzN4ppV(%PQbGkq8UIxs9^u#6`W zMXQJ%2(tF-YR81)^*JgkAwi zRUca^8JDr^wAZ`5oLx1lw$QkHyqi6qu!^IDMMAxN_Po^%9Lu!kChL%68i}VjwDkMS zO2WvpDA(~stjw+9#k3wckuFe)Thuy%N=y|}xu+K$ z%;7L+!gHja3{fo$OS=F84NK6yeO;-7WE@E02=*(+bMsi9lXt1qy}jT+C(XNG0UX;o zr32Z?j^ghE4)exFAQw?UypXWlje1NV_|1E$;nta^OF;lnmPAAv&+Hn{E`^AVd3#%3 z_Igz3?S_XS!%yB&Xh@3Oo531DmydV*7#_1#PGW9F?UAmBYMA$^uwNpDn^ickk~I7e zQG34<_1GNxdnMX#F3}_3N>L;eGW&Fwlo-aBu_4p@*es>=KRQPeDFUSAQWAvgJ zHrRo$y@b5R6nx4y%Rp*EDNAz3(zHw9!!`7#JhtV~mrJc$Jw+RVk)Xqfx|qZD)tK99 znckVrxVFUhwdlj2GQ7ie!5hNosXa42&WhqLXP`f9AV1fdv zPcUy#__>@X--;VQBJdz4q=9ffD5%@+?#Co2tk6fo$Ayw}xeNktZ2&cvmPjxg_tdrS zV4hQx(p|eyjHS}Od_Qj~TYQ?0&NdN>^QKZAy_)vTP({t0UVa~VJ|hbkMiE!S1bAQ4 zFAX~8r*gwcaPuP^jxGG$?HHgxFp`7eO5G<^*lt!)EJvA{to3$9aEMgh8pWD+;2Lam!I!pL7^txE=NEsF$6j@P` zWGp$2Ce&b2*uX*Qyl2jz-u7y7$TLTRQ0*18)Iwua_XV1ZcFcfAW*In&PNF7={X81-Fs*9=U zyc_cE2-e%(xPxKUYF+96s`m*$(TvWt>z%n4*XOC^jja^_6QAFGffWuo=*EI?nte10gFT);?G| zRZslDQxiKgbN;bEMcJ(Hr*kSDJs=k(AMCMJfGCz59}pT<027a z+lD+6JzMv#wMRG++~(R92BR+JV+pk}nCkWE!r$wY`{asf7E7Xy4}Zh19zXRv!W85x zTVQ~u+#PkU5nS$8=(!GANbFI!@4wZJuEp_xR0EP;E1)1p@t+2szmI&Cu@lfBM6iKZ z->$Z6bzkL)+nZ?M+Mer^XI-mJ8-r(2p>N1pMuucB**#z^5p0zZO+h>mzSMz~tGuU{ z$llofo8D2ci(^8prBcKk=>}4wthLKualCWJVr87>ajK4*CWEj z4mrhfPTIXm*aiF709e8nXzU6&BBcb}Ss?y@|3Cg*2hYU*A63%qekZ@~N9nC3nk(Hz zn-W*uv+N*R+LJF#15ImkSzUjBIqI|iv7de-zC=#*Ef0Q!vF=NEALBp->IvtBloM#RlHKF0Pw!5 z5ypt)StCc-KK2}f?Iv%NG3wJqRg(uUEzSCT$wsMS&NXD(4Z7xRl5>Z$y7>a?a)zpk z6+I1HHfx*}f_ZCZx8?xr%qB7b%JYHa`cKCgD?leiVO5qXgS5$aEua=0N0JmHWgf9V z!mE~4sLvbl`}Blr6Lrq!U;8M~j+zJiAWeJUXJ+Bx%!oxfHwA0gYShIRDH#^5)lAG+ zc#vdqly%t_4M!s^cP}n;ilE0z@)9?s@BaSOVB=8?nM|uetHac~a5`Hf#CReRO z8cxY~4=TM4Cfb0KAW4%`aF{fE_oZhn?AvZ-?cf|`ydE)Mu40&H@!5j)EW0SlDTk#5 zT9j@!=Ry0x$J>l2Q?w}roR_YIcWnCyXSbHEoYl!raXzs_d3F|_=^*FfR}jARd?ZsY z;|_L;xx)05TGIvS#;5Ap;yvY4kxd*hyn~$g87bEUJ2A~c&rx?@hOPMt2-Tdg**PF9#1^#oi0%Rdvi8|E zYW8qhOmdFk?EUGu2I6SgJhS159rAFWH#(LEIC3e{o{KPlX~jJ8bDzju+hXX?+u-$1 z7_4ItP4Hn^e&B3achdjzx4l%^P+Ivkel{XT@fk5BBddc3(UtPK=cNKVpZI#Cu}5s$ zy|w9%;)7(zQ^J|u`0~d@^hJ?%(W^r;*STQYEz7tnOXgup5H1T9`H1Y}Ts||o4T@EU zZIf=0jChL74>cfqMSC)6jEw7Cq{;lK+%l#(xB87CPsR9nui$Xkp=WlCs|zq2{_W_S zBGOAMC*9E$5_lEndto~GGtMq6N@FA)(t6c<`NI??5I(Mo^xYKJ;`Sd*M&O6+%}D|0 zzF$Ln#gatzBVr;NuklPubaUn)R@Dd*>@$Y0MvuE#Q9N$xKaO;N}0<}5d%#^R)ZnZok_kmi=P0^s`Tg(Gt=A=c3 zPX=(K+QZ_39fT;mhLMv?cVTE92ut24G8|PAOcgtI1|4L0jj{GC_=v_@Ko+cQ6@OK9 zDiOj;afUXL8-?a;u+E{Z&HjY3J%LIkX>p%6#dB4a5Yh3tcBSZ#VT&ph;w!L0f_~v; zjdMrGm%vZzpy&~kcAA8=*BVDWR2s@4ts}s6h4kd7M>P+WK~aoJYvrvJ^_gETw1|B? zK5;D*`p6RCw+v@Bj$d4=PIpn%jooRC*pTVi zio+nbXuJ=~s@0u{Y98ozm~P5RA2+QMzs`QVkv{f55d16B{g1!jc><75`yV3x?_-q> z;8ybAA>Bk78T~99;aovjsCWfJP6u(d&YJJ{GOm*ZvU3=!T7qT6zmUF&Xd06Ko%Xw8 zZbU z8lY~EOCw&{se?(UzbuL&ZF*5A>~9|QZ_*eyY@v%Z|#v$@=sj{1mI)q@%;7x z@Q+EOkK<0kZ(G#OMUD5@^-43o?a_Z?o#h``Xa0@#<63e6)~}{!&Gw{EK{hc!E)H@o zZm1L@?1TVVAA1o**jgTdP|K@BgVqM981*E!mU;j_6 ztD`|W?U-t`3|mC*dJ-FqK@Qy`j71;+iS_hv-K{nd!@)#B86oWso z-lYD|Sf2o3{VfY2@0T$bq?=oIx}B&3>rJG?#~k97r`PD#l;^saQnE872cYQ*n8Veq zJbauDuYUqsMKQ;CkV<$kH8kMA&w-00cuoRCyzwz%>DM zGVa1kO)CzEKy7+m>M2F$VF-xD=oGVxoKu<+y5o333MtEqMD%D%gIt9}+lUJuJ(dAI zmCcepmD*e)1M&`>Hk4YfKd6rOIU0l@n1pIC1XoVGvW_>J}UbO6>b?`Pt@0a(ZJ zCgTYHjrFC!ur7M*4#2ulYdZkz^#6o)`Ic}1)|Du`#*sBjcf)BN7z^GP{tN4C0IU;R z1F*hf@CVkbG=7zIYW;m#BYNZ&gvj>5P69M&*4{!WO38`OS?a_B zmgln#lAb@$`4;j#6RAZ3SkDJwJ-H8cMD&6P@j4(0zxp@U1$T-53+s{muOxiGquWBYV zN*iF2Jgq^<-EXJi+`Shs_c^*bt{a5(u3IwHnm_nIJDpWgJLmjgtYh#xE2~ET#yWg8 zftz;H$48LFud!SR(x%H-jDN*CZVy6703f-j1OK-jZ~yd5{qG}7VGI*|AR(fdC-Nm@ zVVaF~2RsoiPAEz+;WXw|l@P5l4v9)v_ODx(c$a$d5aTYt0@5%^Ko=NYo_f}20m!ui z&??Y*N`y@^k00?X2xiyE&?cO3_Q~I+&zR%xhLl^hSiHO0U~;a%YuBcFzbpoBGRQsL zmO4)o#QjW9&9&ju;h1#!*Ow!W#$9RyII9KVESmozhWsxoQUBGn!Ea-skbAJM&ZBYA z)DE^W-g}6KJ~zuw^?5$-O9jEm@W*u7oPJvq;dC7>T_s=+pmHMFPff{@;YEVCWA>)l zfq~gE*}fF36qbJLf?+%|l?WA;G3%lSCGr&9R=(zi4*{oj?zWAEwE?Lm4pJ_$C#WviH7AS0 zp^*fGj8=kQxui6eM-Lb|tUd4+fx>BjlD<(v0!hqOaf&oSk2h-{?3?;1IM)B%Q zNC<#I{lu`{sCMvZc-r5ZM{@vT0IRa|QDUmH_l6|qmZM}+{)tY^Lc2mKX^czxUL3SU zmm-KKbJzU>|SWP?V;@FX?cvwK1_1 zwi%flob4U4mZ`gD8j;ByRk}?#@D-KbQPk9mN*!>~z^xoTEY-Uf6g#1}8F~Vwi8pZ#cHw;KjGl7t*J_SW)T_Io8iAOX{)yD|md(os!$PZ2J$U`K%h41g@zw`B3%62RKdaZgCbKjhn z6$3^=`s1QE*L(Z|+b|*^qLi5@c21Wg2Bq(HB!?btJ{rO~pPo6OyoaZn!1?6J@?nqO zQNCbnwk<|Ng}Pyz6rWUSQhc0ZCL$mOItN#5TU^g6hYY6{Q%r@OI6DN-Y^{-#czFeA zZGYM>*rr90y@`+7n0C~|Ggn}=$?}F{Q2ODpJcEgrsXF?J+$_}Lu%SN;Ce~Ee2-zyF zG*q%es_G16qaa)s%o&Dj12o%gLsWo^zassudg}7mgFAotGqiF)tQ;z(VU{?UAf@Fh zwOdW9a+)_(%BmSM zeG?gQDlq|FW=WaGcHcNn58=a*eqL58~wP<079GD#mLj1$%PPl073z zTd|or(0`S5naDF25lyB*Chk-`O3I2f7FB?*rD#|WwqzNn3N=j<7>@WC)pryjiXqfd z1}Cy^y)5@>L1d3e2tP)JY+<=Kpl_?%>2xCA=(GB=Rdubbg($xfB<0k4u6!&1KF7x^A`@z{UUB z9kW*)5vN=6shc$&wL$3SdVzoqc-m!QGoaq_n@@ zTkflQZubog_Err`v={nD*u49=vo_n<@F&Ei_E09k5%Un45=3;yG-VJ%JXX3 z0JQWybsh0dxp!Z-Hp)8AmH>Yd0`;ql2R8iFL+;h5_)?hG(4bdU#j1}krpjX+RtbJG zU?g;*=WtU{-RQ>+6L!wC(@o7KTiG;~J60AyWSBi^D-?V2*??HlhM zb(Ra#Cg#-1*V{o}==7`s_zDqg7xjts%G{nqr1d-CI(#s4rwa1Fo^!!eHW`L<$0-q*R0e;OkEM^k3a!wr{0gw0@yQ74aUkcuIUes4*TD^*vkk+}Bhfz%F>gK-P_+{JhapbCgaf~}lcJkx9@dDF zEyUJ1lNJzQqGvNk9No_m^<|Q_os@CO(t^!^gi&4}#M9){;bUrQHEt~uG)1r&lQ&fM z@}tixV2^N-XxAiXG@}Hy1x$T++&-5-eyZWeSPOJzt(9|l+#o#j^s4gqduY*IA+zEz z!$Z({0@1hxN3M2)%{s-5 zdspAUYuXJYZPDdyP-xK=iLi)a(lBP>dUqyC#bTHJeqS16KwLoJ9KY8B-EsF_so9`v zka36nNc1}$9gI6`p*Rfvt`PFUdA}F(1ZQX|;iwYm<-Qn&b{$GM6RQcuZRoQ@lUy*# zH@u4)H6Rf9VxDV%IUKvz=y_otTaL`zCLVWun^wDDcZp5y zidz8K;fBvEefAfZtb7}Z3}o`29X6fuK{=UDo~xfX1^)KtSY9b9cL3ZxWb?AD`UjSx zUVeD@C^~}jD1VzmsP84MCQ{6YM3V`S$-5OUGUFm_hX6xpssjvhXFi5K2TLWvY$e=W9O12>^zGGTl-B!w`MA zdOxQWw~I64^l2fwSyK}mlwPhUAZ_>ohKRiJE2`M}ZHQWcA$$d?xfy<#O_ytKCVO3o zDBj#Of4Sp0O(?nK2{0A5l11~d^kED|k+2KFnQer3x$`%B6~9T_JSll4Q9R;AR{H7l z`EdzP?6#)HK@Lf^`gCVMt;+{bLE!>B`Z2FyCsi-`)kjU?-Q#{U>2-W6kVSQ4%E@ z9LDOh$29bZCqa`YG{tjOc)s`AxRBl*ckd_!d_`pDuZX@NpV*HVW?WACC+BF6Wf!6* zfhM(|j~9(?8;u_SR?ND8qu9^@Xb~2mMWVk;P0asM?FP`br-9r3k#m)E@K84Hzv&E^ ze@j5SIh~r+w3a9`P!Xz@97HQ)J#+GVLU}@*wT8B9$%J|k-9MItMv)mC)C$C~2DU_{ z7V4l20~S_bI>F*R1v^~HgAuiN_-sCHzI9AJz41R?t_}~H-BZJc%P`8W(VB}9sddItej^D3)vHMFzp!!yWx~Z~-qmn2oul8uu?&BvIxBR$6A7zJd2k{-Saqam2cB4wp;U&`O8n@_i zrUwPchMN!+YXAiJnKL&NM#K&jQV#b#zLP!-*W6_I9hc`cZp`H4xo2dEFe_Xuyr_9Ur%?SxYn+7bv+cXyJ0fJ zx#sIhuOBlWzF)e+-S8A96?~WFwQ}z379Dv3WjiV6pN+rcLN-{9{+5hEx>^vQ;k0Yj zKhsT<)tG+sJb0z=oJ3(kP-s_LK}{5ig}0|5e$Zrps7brf6e;|JH-_RrcM z9bfH#boTu$#;cm_^}^jG-!6mMG@butc$c33wX;R+6FUGYxX14`8$;WTRsIw<#iT_zEM;a z8=n=)`rlco^#dm{rBYGW!;Z+lSC~jIGNLn@0UPs@b&5`Kjud2Tk1A;y$7YR+kDP!u zQW`5n{L+79{4B0+WNBg(oa{=HZ0J=S;41d)0&$fKgzY5e7rXbc2e?VZ=>hXO@969n zO5hvEH5@ero88Ua?+NADOnd@Tobq@cuqC zT(T)zNX#4*ScYrD0QBftP#sRhExM9Rrc%~6t3dj0g#&AlOPiInDZa4!8{P0V75c@z zG0nRkOQ#Sf3ey<&9Mv5ncVy|uF#Qn%^H<*<)VNgf$|R~qO!)KD$Y2mWtg7N5eO`?nT0eCnj(|R7+w(boHj$x7F#soOZ`>Lp+sYH;#Zhb4X|9 z%7~`bxXYw91{$Lm?1*pK?!0T*SNn!7cxP0HL!1pNSjOGS4NwTvQ>0a+cl9}rPyhx} z=Zf8UM)bV@)Uke}%i9Xl_0DMYF^d`8?4)Td#JQMjE$SKqnT?DMqhZ#$LFIpkz!$Jp zo%Ja6_1)SV?H}d_g6OZ#R$Hl_|8f=b5^(W7TfX}ptTVRIa8*6QV5<7xM+9p8A}G}X z5F7D7BliCkU;cj*8|y<;GL+OPlxd+hke0TIj}(q5imBddO!zn_1S=rQVDE$Ra-)>c zGB4GB7ien%87=Ntjc`^yU$2Q(EFh#W5VblSJlGjWQ@K z(HLSZ%v3}l6YU^0sQp|=MyoFQsN(f4YYCat<%gd^bxvbrV&uU0_@hL=!~g@(uRH$c zE9gT5A>6#jgelY&VyQ*#kaA@7F?F3tAV|Ge(-2IFe#M)ohpe8AKv!iKQC4Bb6r-L^ zpVuS^rL4~$;G^s!fn{hL>>wLB{9OdLPImMgWbAPL%@}QZz_g8WB7yRl3Oxk=)w)k;k^VFHGhf5I}C1ks0W!2JExqGe!kcMjlouW9Kwp$uIL4EAa|Mnhm6t3S%^ z;D40c_e25E-kbHv&nuduiW5utmL&r98`@Eb7C4lp?gjT9nAc2sIh+MJ9dgVk_*nDO zvSeA=T?#6>UqwjYNF94&DY>js;zf;2&tAe(Dy#$G+hO{B&uhD-R z0NMA7OM_I-#vFN}4Q0d=9V~}o_8yg!Z@FRHz1}jJTAk<*?qGmkEf-qLzssWB`c{+i zq<)9z{qx3_-!Gtv+*GtCqQ+FN#&>d4z_&o)=u-dMw*KQJu)Llz*{>O@<!Le_ z9YY}@Kpodf6wQvq{SvAO(@HvcIM;Xy>RmM{4dL`Cb=Ky4aDxjIf(BM4Ly@w+^@E?^ zu$OI;*_a8aOa_}=t+NBw z5d_2jxfhoi$oTB)XT47Jg~QC4NN>Cr9|1(){IAbWN0Kwq&YeUwt8Sl{@!++(kzJx| ziVPM%&n1s2?};Lun58kpWkU?Eq$h7wiy+ znSXlWTpDjqzQe~jz7Jr>1;rM^DP!+zmKY#@PS4-~lL=%S5NT2hBCDu@qo(bwuu)dx zz^;=I8V)4v7My4qQH{|aRmM^!CP~C1ERLVg!{p<7^qtAK$4bPWD=T07*@2-(HQC(m z2B?HN-|%A-7E^$a59SE@+8Xx|cGZO9b6(@ne${ti!0hs(o!JU#q&jdW|N5#pH$87Uea8T$En?{^ zrcT#XVun;QkNeop=7UK&?kPrWaprkjdp5uMc?&pm(jgUgXtCW|_LrA>Gyi(KfzZCx2qWC45ZrF>xrl?Pijx4N?%Ch1<-Nj@K`>_4I5b zw(LVoJ+>}r)CQ-R;Lj$_|}NF2L=qOW;`A3uCaCNMkSO5MMC zx*Ekh@i=m7$~|((_Ucn{k=mim=qdiygCa3uxmp5$dEx#!3s;X~+wb`y9Qvpbu*#Im zr)A-OZp5{E7Ds8c2oDVG@#o9GEt-Jj@Lcu-gbN`+>E*u}cYST5$dhJU>&$K5$j0)+`x*c z(#drx&^plafGC@~TYXqBDcH}ilk5Dk=Kgs&mJb_An}L%WF8@}N{(0FT1YfPbu z0H%ZB%4i-^-j%J9(ec5?Q`ZyV<`3Z0z2&MgKp`Hf4V$j`C8a2GAOZ7xr6>nvQdWg* zX;W#b;~kZlW;=Z}C3A`VIoxp*b-BDnSzD=NX6UpX4P~{Sjt(MIlHMlPG&&Zal~7re zy`4hEkPlfnWvz_|td4(H8fH;>f$9tN2!6axm-3@Ydi2;w$2)}X6dB|>X1KvrPU`_# z5uP)NYXxkoMn!PKY3Bv%k8dX)~Y!V`IQAZfF|2c;*h`yZDy~g@i_0vEid7UxtDk-^Pw;b?-g**r6&1?^M5+=ApBhwfhUjD$pGN2O zBt#Z^#*qTh)vH+J{8UFPLF_deUJD&!gKj^a!TMsPP98DaL#csRy1_17-#*WGkTAO) zP?=5Vo|6jlzPRSPv~<)AXWmW7;#=RF_+PZV5eLT)r~WOnjFv`Xu@HKPg069{Xx z2KWw5-aQeEb0dT-nFiluzmTx3i|H#djz~AC^euSwsTLa4WMwI1s<#)_+edtxlfTsi zHa*|J0L`$EF#-xvf2uJTV;+iY=1S?4j4WNDX_;}^6%JRi9|$Bb-aY}9)7uUQ`YL++ zj+84E4WAe@q)8uE#Au6!PUo=6+N06$eivgN8Jd)UDr=?M03TSfk!SI#ISCHdEQLng zqh*Q_+c-|B?@LUprLisOul&c2UuvE_a9?Rt9D1~PxKR9!T$phXSRv^=ejI>S>P^dj z@})D^L%_}yh9N3k2)3jG_iFrxgXigumbqS{hD#>tt#uRk`!zor zzY<}pw*qAIVB1N%Q`4e;{r@ocR#A1}S+_4vu;A{&H8=r+ySux)yA#}9g1fsr1P#u{ z-QC?oxSOi(KBsHk+g;y%Ip+x;cwp?on1AN_tvMIxX`%OnoXfNwEhr)}2&C;Nee=76 z@B1jKm&$FMU(1iSVJ95jpQCs;=go$uziE2BRKNgtuBZt_#L?s_X*&&ARII$fh*omw zaO&=F&@ly*+kRcZRcoSjw5qZU2o6wY$*-UwVUbuo0nSWyJdA-f)dvtrwQn zAp_Az_Gfma!_uNz3W-|X`|qq7@{VtJ45mC!CFC9MmRt{^iCxThADa1}*UQmF?QaD= zK%c6~*t|lMyni7y9pj-p>rqL zCfRLC38#RVRC}wVzpfw<0v>n9fzL(3|M0o^uQulWx$r%6_HJ(MXy+g3JwHw&gi46R z0~c?%Ot4{J4P{1S2!DpgC+ZifIUAf${>O8n@Q>$$_@B>(u)sd45lUUdDKyDP%6z0K zByZOrgMj@z#|_U5M_^{>;>Fvw(ZFNT0zyv<+%Gp1Tm$5X)~}Gbfe?$jwnmS(k>9oC zCR!Q-^fiYcZD7*p%`AD@X72&YTYm+Zhu*PFR}JK-r|hkm?|f1)VJYY2;FS11v;f{IWuoE~7)A3a|Hy){(7yw-) z0C&1Y61rJV<~^yme3d27(sb-I(@EjQhsrUtte)>to107aQDigy8J3?SZrfIhM9)rc z)8lzRt|a%&^FDa&C@_oE?`o1mwik@!D})ACrfYfE0VtNE;z&qXMMV|}u`M~7&eJa* z`=W{*%xI%zX3Rz+WZFx*L0FR|()HnB0_?X3q}LCZk1Y^Q$;+ zTHC*}%JV7Gk7Uo{er#~l7u)ir2Tl?KnQ_&DA19%HNadIiLfav6M3wVEo9LO)qj?`$ zE-gH5x{Kr+?ee4{a&23JT``~YxZN4R)p{?5BM(ruUD`N1=aS^UG z2E2Q8n+k(g;S~PEPS9l=AcZ$5x`+Gc$wNlsIyD~p*-}X?QQ%8sQ-xLc27SL!#nNw3 zuGM~{Pp3v%_`SiEr*iC$Dt#svmlAXbX|$-U$vxyI0*0v#K?E%~mu_6iEvVs@n^=m>^4AT_}lz6aj7poDBIL||uA zmjCyO0_ams=H)5OYE0MH4Ks@qM9&4!%BBr(vG8#g48? z4K-%y&8n|c{q$!4a{kuVnI$OvQKoeYACnbbl!U%47S=Xtc`SYb`~gCb21XE}#u?k{ zUd*~6ex9hRkQAOxjK}MIyiv*|NWMO%U@S>Hg?miyA>+uQbBt=wBh|3_mbp*5maAk_ zgx#Gbbw*Zo8Q+J>&3uI}BNGotJYV}eUw-+bn#>y{L&pAS*GN+4Cj6S$5=>Wr$2N3t zTqta2AYkD_EMjiSYye3nFS1$SFadQK_5>9Ion%62)?TNA2OS+pvioy4X@Rh3ww0tX z&7}|d2T$E7Zc)AH%UDMpnF5-MXNq5PEj}WS60(fZHhXdeuGfbcGBz^2=PFHCRcVJ& z%MTN)nd+Njplcww-ZlK*G`Ji!Y5&%Y zW7AEra~47{`%|UzXp>NG#Ip$I1{k~W$}}PT#w+o8^Re;v8j*jGV#Ck<=TRUgp1~-z z^t_aP$v#&)+ubpwwPDjd_xEb9UnSj=Tr;+uVk}MbtX7e6-PUBEb;)LMXTwO!2@=L% zDT;?l3w%E}cPVt0T;)URoL=wMjyP2?%^SQpuLwp=$SN|+NCm_s!7$vs{AFiN(a5Sa z256j~fX35$fg9}p|73(t^5@IiOwH2+6n5Kno z^Ui*I+$V64`VcgY9_ufv`k|9FvZ|k`zka6$u9(P%YYyTTB5>daUJ&KZp!4O~XHWqMQoed7=S`Li`7j>B%*i?=Kq_NG5A) zIiiq;`%p-_k~EKRQSUs0!9!ah6klufzs>im^3>CeNu1>RBZ01K4SHui6IQ^*{k8M0 z^TD(G?d|n^tuZ=6Hnjl@LltPFMnkFo9Pi0p30q4zi%F|!(o+d6YeNd9@;ldteO{`r zXfG(mB`TL36FSPxJATeY5JpxUIF#4XG_hERQ9yVu>NzChN*0Y@%vFG=5$PlkFSQU? z&K2mrVZxx^QyUb}iq76fb?QW+sJRgVZeCYb(%Vw9__)b9w|Wr;>XFY9QY~$_Ak7Ct z;gM>7Yb;Tail0qJ{ZzP!YcfP+pTH4XDlFiYpT2P3BlJma4SxoMQYKMn-NBeJjI_2g z0KWr(gM5$Re=hd930cB_5SipevlGg4_ucCbEHe`_{-fm52R7dxd21zs(q4ThwfcpXiiM#k^{=k6V5%jjT0=SCYm#G?j*PQGAQ4pViVL` zH^1MDLgOY>fu$g@I$4TX@irE#(iO2GZ}jf-RRbHCX(TzFC=J}42Vo!RK1f2^76PVd z@GdZbozIp=A;KpNrc+SQCKfLyF}HiG-j3_mO}v?Q?m&!j2?dkFeF;_mf;qEiaHRl{ z@Qc>@H7+u#J%zV7Miqx6<&?=#P=9OngW)HJEi;dv(~Wz}*s(^Q#dwek;-#e5f_9Y& zRy+IInhr(M0!c{sP{bjLVwL_%_4~d3h2FLhZ|8Ckvw_LrW z*6SBNfE@I5r!M8PT-_yp4T*b^jNZy582y3$)MtfIEvloq3?y=O6FOtf( zkDjv3#t|9=XM&utaEnj*!m_qxJsL5twzyk`dO& z%=n%87$ei}+Z4WH+p#LKgG1amxETwfA)G?6iI#8!_wgjJDPRgbt<4cDH+IP7V&~eo{N5Yyz>|}H>jwZwiovnF^K@?Lp%xeUc9=|Qo$?Uv8rF+ z5a-#4eiX8djmpr=mQMkBjJZbMJC8Y*?+)24ouYNF6VkufA0uYe`Wf(%(Cp~W;(%dI zS1dEcv%xvo$iHh&Hq!{!D6PTWGrT^;o@@Ft&$jvYclpx-Z(kYDu=0SQa{kY|;icyg z*#a#a7F~Mp5an=L`&&_czAMj){?}_ys}twCp8;z=8Ktj16_K5ul1E~592E6;t^^O% z3!)PA+tDEup~JkPkMa@0jOJjT7hmb6;VY3p@csVno_b>dc^{p@J8RLk_I$58=8+sP z{!RCob{@^ha#BIEho)=0;^`j@iwwnjw*y{!O^V)!U1i3jfjJjJsdFR*r z;JlJngWH-M8fJD|=p!h>89l35+))zoZ9Xb~w0s?0lG(<@Ho0$C6_G&_OUbozWGk|l zj2=4TvHj|({2hVwDkmNu?n9~NI4MjeH5WHphoyWBD11Zdq|2~!(<2Mi{ zfL(s?ufe6KsQPl;LKSH@m#B_5`!nhgR5jffe_;6olm15$^$ztPBbIK{l@G$TCiQR$ zj3fNA`4CxxLR`}N%bX(?Ivm`DplKYmp&?eC)$+s}Bnc|gW|vRcp3cTlrYs7N$G;g_ zb#LM%TQRfwq1$llOAgF8FF3biR*$fdnyK-rz%#v;|B&p1_%XNGr$wnrWAnfxA|{U4iTf3JHE17)}pmTQ(0{$z&{Bamib~ zx|8qrOrv9vQ8!vw7&G1~-LWALU%Vxy^0^m|AwkDnH})-qm7~Kp=cz}9VpG{>;0WAS zq^s}V`wPcR-Fb0Rm-_{db6V^2L4 z>3JxwWQ~|{MOoEnjA4Rm$BKwa)q)ZfLGP9w1V{M^?%FCI#~%P0fj8%B5o(@AzG7Eci@Vc9B+*O{K_EabIuk zoA`>h#<`|DNb($r5D1@rb{=#|I(}oz--%aIBUj;YTZoO%@w!DCx&yp8eq)rQXO{u8 zgOHal?7zRvJ@oIFE5)R=JW(pX1PEjMJ_JvvRyj%=pV)FAD_40+Oq6FJM#m}o#)kE& z&{@tyxo&tUrQvCi#QHtI-Y_jZ!EWPo0C9{%{oPsh(j6t4;siAH_R`H?0*+Ktt{Q$o zSMgtQ%)4m+XEX8dIOgc<|5+R}M+|`dTR4VU_kV_C{$(Rh+693jm?}$t%w#=>JZ3uU zgx;{JBT97YC8qKFb0MVW(e?}Pi_S^lp1_Mw_eE8>WF*ck78`LNgK`8xf+1ED&Ki;0 zwY{-Kt)h5RI!|2C9PUl1Gv~n3E9kh3`y54C8GV_SA!!2_+( zejae-NV(VZEu6A0e4ZwEm@AY*VU78s*)S z@rvqSOi6GJB<84M;2woL3`5Hgdn#Xh?u-Y26ER!l6ld5C@$Xu-JIqC#d2O2axc^4G zOr|d_^x2boZDAcyZrGaV19%{_huB+U+C;<7&K|T~WwwQ}J0)BkejM!zLG`$d6n= zc^b%L65e?XIPP>t+u-?^zh+Z19`fBHAJAF+LZFcW30`_RhXGmpccPSnC zU4^i$5bJX8(#GkuQQ66%Uc<$osL}Y0_`4L9?BG&c3I;yHosw-g#`E6 zR##^%#qH2b<)#=U^85t!&yn+LKlP!43`12;#TI6lw_q_X?7ykG^<`{Iar-k8Pzzi| zZWm=qDB_4>-H=FiBT1uSC(0fY%fChz4`gXUOcd!uIoH`?kg->0G(_lkd?xd#{?$49 zkiz~YImnfPs@LP%48ugeq24TXbwz-O^CswU%$6AJb`RcLjHJHFVXy|Ef)2v-+04wf zoPzQCBcvl}i?DW~To?vsm%1 zTO)*#*N^3@dyS>kFM37K&j!BjUah*0IMvo=RZFuo{Z#_&Ye} zFVDq)bus^rW46yNMiH6cag6jIIL4?S8xAY;8JbQoGR&-fu97ayd|?D3RiiNN3Gry# z0K>56)3yPF6E`r6VYnkPBh)HVR>jFu;#ckyu%Yq`Vc+!I*ha>H}s4SX&5#bh;Z zLC};y4%^1~5J1$z-Wcl6U!N;X+LNmqy>r5k*c0O{rPBI5fwS)8U_>W`SEtGz37lrt zS+*+MvQW+W%q8sk>e`0Nkfov#Zt!8ygQZW&5Gzq26+cw9QLv89rCTKi1!0rRlhk?~ z1j1~0cpo3^(jY>{K)(8AS8A^)*{r`L?+-2i#tJS~(_O8pdpaY~uINs6sRBPsqfN=Z zvlI`Lw?5iBq*;KIgAnH!S?n7 zacTN7;pg^)W*xWsOB47Rw9*j5tN7wppaVl*X1+cpZS$)=nwUT3}nn%%LM@8XAMQ!O*+RT$hF^Abxcs*yRaMe8Sc}iP887FfvQEyx8tGgpV zv{UJ7&09GR8(}AjZ~TBd=a=#fNH&)&DRD>lq*#F+HBE zF13n&NaU?Ms}L#i94=g^J|GIU-1+QqP`k1y?kg8QBYFmnO1iDxtQ9idm(u$Jm4~JcI6Ek(?o$f^*S;y7hvP5>&?^*Lj%yTfPPXHM&A>LGVj2@=q%N z802Ule_65H)1O60XGN(8(m|?HpUb;Mm`#q$;KnhX-I?z!d8lz-_-!e;jtT||}d3fY7XIW^Cv$F0QqDV}(#av7lT zN!_?LBuB45E_690s7+D6tM%8)h@_WB4T8kHQUmOTsecW^{E7p_{$(>qpTZ|?y`w;1v>}FWq--_L0pME*HT?xM?>>(io#Bilw4LtIy8Bo*3Ui> zJu>Ja5dP+geJm?%3|aV=?Xu#OA^h;-$T;D$HQ%(DT)DPNC*d>c#$cQO zYht0~Bg$j`EoF4Jw5=EBtk)yDnsbJXTMuND!>rzL;^0YlZJFX^hAO)$u2%ljV1(bTU(<&KmhzxzaxY(P5xqF#|^^K=x$KqZBGwYF> z^q6huX1Dd!mAu7pnEq`Q6KJx}+h6d6r_esp-{LX<_G0{J3-uQslMeoW6OUnnyth;N zJ3NNvZ}FHv_pR?GbS2+;jNl(UhKzRoN2PE%3V?1*w=@r&yl{QOp08E!>EY#i#yz`Sgb_<%r$X#fF; zHiE!G-+@fJ=mA?yl})k+>&}$(_3?gdIUc>9;W6KXaK)t4;vzL z+)bK0g9|C=i__ZmielG^=Dyz{aP+c$R(R|An{}A$JMeEv!B(_75NWJAbOK$<7nx!j zBps~6Os`?lGeu6psp!%-T0I|c4CfiL14c7)Ir8SU&F}p|_S-2Q%Rr~&FkF+=e+rq5 z2uw!U^;W8HMOV%8Sh@yPLLNXW{LpRFsbolP7;v*ps}3J#<@LxlS(r~7XXwMJ<5-he zjCJJaxpv-M3Hi2YdFDFVgt+^vG`D6hiW@`r0LgWxOZI?pIp6MOtUhTJj9m*zfSE}g zf)6XQkHfwL0C~)ZV(#!4yRe|tFIwY0kg!#OTmEo7CR<-M;=o(K1BeJDKjX{dAMUO`z&g3q(e8nxbGavWjy0H`$9lR6)sLh=A`=sL z&tueh$QK-QWme2qd=I_z2&FGKDBi`C)bNly^ZhjX^!}IFayyqb@id#<8P*O>UuJvz zaPy4Yh+_0wDLxC^F55AGG5u)I4P_rT!QSSlpadY1*@o4}SlVOCd9-!0JqLu~;u>u! z;OrYwq!iCl#%O7$4K_3$TofSRq2qibm;jiyMF?FD#lEh{*`qOdrSRtGIhC-2rZl zzdx3vrHBE6jKEb2?Y_?ye(mc=s~9P&laVe)49Ysk zUS60NbX+Slzgn61$(Qe0Qde^FLOD~2$3kNcuB2MWH|C(Gm3JUB{=9=&M_W4} z{Wjg;Cnr(2Hg%lKRflZa(`VfYdb$7OAcSk>vXS8x4;!0M9EE0MuLFA`;4KqR z2P$2Lmd|n=!746M%RUy*KkmIxBuBy8XX|?X3>!NeIKpN4{B>YB&r;Lol%$q)(W5>J zGo1v0fpC5jQh8T1_qoY)0Q1aWQxt%$_n}4K5v{34j%oT>lob9_feV%YH)Uelsa2Rj zHZD}nw-9)%$X;@0cs+1LcA7Ektjv|K?QQB7bF|}C399VX+Qx+tZ1Y{D=y8Q(D53)D z9dRj%3s;dVn-OAZQS@Q7xp=pDGMkY74UPpuD}3tXG{pztHE~H0g~W;{<*GvuLlugk zjZQvAHm@%E%qa6+K6XL_%HGEc=P4682pdt@tBz>5t{L|sgiUv0T#3=dBtV8f^6Yz5 z2xRCbe7+{RCd_DqiGES42WUmah^)s`?+l&VYu@H3FA6S6O(R-UMdpJ@KY65ZUbT|d z35KjwI4FWusVQ`P6KIvf=i4!*hcSYqVGoaeua#5Z7Qi*j$lw$=3Z3T^_xvRygOTCY zr^SkI*7Dn#9v4E>IC~XT{^znz87zg&w-tJ6rf^NEgv`NDcp4@Mi9^)4yC99tcHu+NeU^?MWvO<1PVj>?Q22cp1y zj0cA)^9Vz*l}s}V|>SxU1v&Q?>u`t?2P z(KZU^+t8pisqaM)9%2kpaJMBP5<3=fX3P04G09koVfk}-8bnhP5Ogg7L#XkcP};G9 zN2uCHvD-HNcETnzy_}Ctn-=v3mO|A2-RsU==5UVlY5+#DMS;Nlm>OsMXvRDX1~XYy zr>~_QVzTZf#NTv=00}KZ7#?*gII@5nh1>qiH{qBZVJ!*cY$)M+M%|mFWds0QsCn+PjY45CpTr z*Jv179tq**Dd5{}HGPZBkg0gxW zKb^pTbTbTq*O181&>G$|XT9GkqnDQaQ?(z^ak6kGt=!MOw}{NUYX4_D@$W>2sx#*QXg~&PASY}L=pX)TK!)Z2KanYCQr$bB_oq+O zbMXI@$k1X>lu7P4@zQRyNX|CO<<1(JA06e^RVp^s_yTLm1d<1o57_Ej)V>^Wno9MB z5)a0z_Y2(oAzdv$ZA3|-k<1D+av56C?HGaxhO0gtPy|GjE15ct2TX0#0w{Zk23 zY3Y=L@%#)me>Yo<+JJ@383MYEylUpW@|~P<5Js<>qMSRHaty50m~CLwk+lMY85NU8~cH*pT2-Q0skK|-x*FhSeh#q zlWdn=r5uY|MEMw~okZbM7P71sV7MC->me*>NjVz%b*01_EEL-l!jX6#G#M*}wAL3f zrc(@2h!YzJ?%c~fc2f7Ut=}s(^P0&>pYyl(bpRc>EYSV=>ty$J^<108k?;;V#85cW zd~6EKRIm_&4qRwK->_oSr#?VgK{d)uPX@CV-muT5bmd)ra1&%VWX_erT3W3#|v2BxfRxms}N+d0lpqSoEI zk1d&!9aL;W{5PC{+ZRS#B`YB_H1CuCWEp$ebSzT785`4Vqm!M=XS)S6+TbnQG!8X=@0gv z7C0_R%z#H{jPlcjY0v7W9@&(k=9kg{Ee~_Yot;IoeDr^V(nv zOmb#mO8Nh2gS0Kpc0XZVjoYPJwil&5Z3$h00InOYaFSYFE4sW71_LtPLb!9Dp`z1= zJZ-*Y&KXPXW>%cDK_0Bivh|w#>;6Lf3KyNV;c=^ZRe74y!HQk$yxAnGoLpe!J!^sL zRk~R7?^ql&m4)z#@x4di;m7L7v?geQ)vh+J@4W4P#CDXl`-9-ge>OXl>#%# z*i{0HZXcdP5-NX@1}0=oKNWugCS)=TsfeBdF53q6qPK%W-J({95WhiSX-h&!To|aI zqYmZ5+#}EOjF9bCYK$UolF@XL4=M%YxyhH}9T&4Vi`n1kZGa~}r<2X0Wl3@{)w7cnj}bpk31o)ZSbk7=d> zjl*rgOkCUuIi~>M&>}?0c|S<)p_i}YoIw;-n90t4YxhtWKj>D?{bu{<-=DWul&qzv90D5w3=FeGmd!HdsI9LsJIM2)IJ ze3Bq6F3-29SnetQtw^*Bs2QkDlc<=90J%m{h)|$4IsTzd9F6qIV8M8VHuM``Nwxl6-!#Hf?`Z{-TCk z;&O%(s(W%{vqp}>g`PX&#b*q^Zymh7jEK#vv6*x=9Vl0(KHAZCB>v`cA>ez*At~@( zch3H66XiLzuK*jK77?7z*bf{ixN-1SnK@Ss=U~P-2Pfr#-H@u z0r)#e<}dHXfAul{3(0u8289K!Wu8Gn#s4cIW7JO!DV6a@LI$E{ZDc;_&xA}R)4vij zNY21Oc@BAuv!096WVS{`0*cBNwd{0U>7v!P21P zg9A|uw8f%-EnzBLDJUL2BecvLM0ej+ka6`gEinsdIyMBZL~H99k&LIqj+Cb?p!HW2 zg0Bb+7S0FnF(?}@FQH!8YmXU-*9^n+5uYR2%PEPUT(iOwC^PDoFH`TMmc3%V^(?@N zqu@1yT;lmOcNCCs)VWtu}uK z!6v|&QeaN-Xi?q)^2R3O3F*BaawYBc&eu!}49XIPwe-dn#km zl`y$O@xOl=BKixiRHnuq+R8~(H|r7Nt4E#0FjJjhFj@`r*PAN zux7ZP=d*^ZeIK^V*D>i<*c3H_%ULCi@fJ#7E!!{q54}0P4_e4H9xw-XZtAJllw;8v zsih2U+r*Albgjn}XIh8qAvgY1SZW+6bg%Vhgr72~YV$Jff_o=!0+Glv)&c>v zJLxT9>@CBtEuCq$fWV-(9g!Jz!9jtwF&rDfVb{x%h@1B1XtsaxR&G5mqBl)v5;xhh zB64m35`prPLfxx;ITCuU$;r#98TSmKNip;32baZ>XeUNYRx4k!bt-nXNoi$=l#^5{ zgyw#(OkqQow0k+%1j?N}8?vdubR0P1jYruy{mU3Sw4IQd_NS z&w^l?L&VJ=z2V;tpbg_UB4v{jf5ILZYbGLz7!eaM2M>e?nstBT+OCUL@IN|?#qUEF zZMMQC$20CD!M@K+!amv&>9g|v-i~JiU3q$U>D#gP(7nD6vy4ijUHHig!|sB9>P8AB#;4Bm}4s#WHlB!pc6hAOd#2LNj< zBb)pLYXig5ClqTEScD~E>s8*an?0*gKkE+J^-`x+s-JY(MTZYW!`2787 z5V>beC=&ieumD5|iS7!Svg0`?;XPJixn^F``jwovX-YJFd0->SJp44eu!*$2w~p{x zS6fF-sncyi&Wg3gI&{4A^I+~!tT$~0Y1p%Y|Bz@Wn?OmKxpEcQ4jHy%k^`+FJ=M?2 zOR6@V2=h=$5q~$xJ(a}SJsjSyk~SSCEFlI=ybqY@U+6;`dibHOKa*)FiOZC`iOyd|G{L0L2Rz|G$Guyf5d<}wUZ1$YLMiNfBZ!$ zR*Km)NpF>{y+Pk-(_f#ydw14);-d9K<^1D2lj(nFGWC8*>{l5P*TKMrYgFLEb;NsX zSs<{rY_NeYaqg>wyABx3N-a^>o<%1DkjY>-zB8F%o;90J61)-b*TwJQ)zAH>ZD6 zXSKY&5*40Ysay;(aKvgz`PM{%$*o@tsb70YhsyQbKf|4;3%-nV+81y9y?Pe%`Jn9O zK=#&j^%ZVid%iov&KbkR;F2CemHV&Yd+RDwy=%`u(@exN-K zzLbTFkiqEesXa1=!-5e`^(^so-n@>@9SHA!d(mT={xlozqM}XKhZ<&b6M25=Ru;?q z9m~ea6?}cu9**Cnmr2$tG*Xhul(sTg%JQxIA)n_?SJms0i#Vtg=Bk29D^RcFY=3QV zUy5!Vb~rXUemOWOTekuB-zae+oi_Q<;bZNOyFQLwcO9{CnHUu91gCUk4>(b85$bDX&~oVgiKit*151R9jx%s?Ftr1g$pa_?{mlsoUTumv z)3@@k?s1o_3v_dASYZ>;@Gr2AZMeN|f~m78SV{YYz$oq>mTAu%2GX8rQXD5t?&9H> z8d)FVcK3MrR!I;%I%MHLo!s~&^x1)mx~W}AR>;aZY#fg-0QdpG=9$m-i#3!}(Db)= zjT6Gvbhj^FS@aQtkKOY5e5gSPq5zaxoHN(#T%t&VIJM;Ap63%`YGfU%8EU3A=+|NNPL*@%XY`ArIhJ(0cSHRrl*N!4aHoZV( zFm1t04Q98Mylz4=7sS!IJsZ5})^NLl%llO?#=9vC0nN4tPM+P@$cDw85IkTg!%q1-@~c7*Jzr;{`R`>$J@ER#R%bq zV03(eZ7oHa{uU_33H|yG#fs2viqDc0T z{ATTuf$>D4V7K7Er>n~q%RE@M<=usmXV1o`PFYImS;K`x5?NInSizlymV|$QfM+BBQt)% z<`JI6Wkj&=5ksoZT?~(J)7mLMP*#GwNg+=-X*&_J4MjR$ z9`8e#6Q5%Ymq1BE+AP;vo(*r@tdpvfs53`+(RMlH0^)RNJY~leu|%c5UKqs3kN)>i zfb%5Iwdqlp-{Xdt@cd61IjmsIZhlcPcY-*NLaP&jx$Ize2^1@ze(XT-808Q{0~z|j z2d^Q%zB72Z6;;fp>MGk}4fgFh>4Uqo+LN#JdNlXwWi?X9{XAI4*Cxo!w%gbgdoYF* zCeSW}loZ?{ux>DMD;zlO*12Q*$)h(&IjKJb-G=5oaL}%~nJkn8ak8^>Rht!U5knj{ zzA}}el<_!HB5wVovJ4EoL%X;WDB0lC^#7FXP21OZ$-b%2PX9x)_e2Lz-X(h=5-5$g zQ-4bKPlbO-_Q9HdDNwR^sS-Fn3KQ1iWr33Ym|I{hRx2Se@!(mADl%$TJ&&q0auZMk}X3)C*SjxSV?#< zjj&6perGN%ieX$nwZer?${1fR)a#`E>IbHG`OU=9L~cfQxd)g^!8{FQL{;$4aBd&aCYWMgL^sWAe4?vp6S#2H}}}nn8U#AoBd#udY5d!hT9KK_H`Ct z^fHMMY74HxxONOsd|ar;Wk|xLPMvs}u}v}U?;nTWj1l{cNm=>LN0&R|p-a({mNVnI zJ~eU{ntaR=cZE?>k3yXRv-;jSrB6C{SaeVKE??(;Ucy`qb}r)xA~*mE71 z@Z9fpHmH~}8Z<9?*{oLh7%$|D0cAwEUvt5}fg03&6qx6dFV1~eOzzU5Fq+yxe%}Wk zLx0hzOHH<(GOTofh{j_r_e)Pjgtx7_q1Xb?;lradb3vO9^)J1AD%*%%HI7{ZZMHe< zIH_fJvF(As24sTZRL8#koq)`{WdCO)Q5ee)>?`{-ZSSDr0b)zCtwxOyrRL0hdtNAk zIc`y+-Zkm#RoB+S5h(B*PHaAhK9JnqsqITTB{e<|s~;Cg`}dMTSX&kO?*)Fo(N7N6 zeKX(N6JG=vOOXjipmeLPob{$xP46@fsyl{GqEu6P>qNhhVDr?}GKgJq6@2-NR~o6T zR2cj_Jm$;)jK|mmU!_0JR`Q>;(=Y&ejMX0rnNNT4m|VW#`s4W8GsK85YbefiL=DdB z8XDY6P0k}I_lQ*3>O*xc6RlCS^vPL<_$0v$2BG!^AB2bGsPmSXFdzO5$ZU8&tY5sY zKXhGqy6$;dt(FYbB!cy^R68r7|@#k#r)CHDlNTa7uQVT3gWA}5aIGc3yy0+K- zswnCRp`Ktxem<_)4v$h+*Ej4*;`TY?H0%?JEtx*Mh`L>do)$wXpEq2@xt$fNS!I$) zDviBNj7$aQHW^V<&VD|A(8e`@a2fH_pUiC?cv4Oc2B%Ouxb_tIKrXnpwR)O1bCxD2 zi(vfu2aYm~Olsvgg^-5)^m(y=zpNHn5k^>lGF!I`4LOSSfVI4JaGs7Y{Y$+yT718Q zN2gCN6|L0?Bwb_9012LJWgW0H@I4+A1CD?UFawEatjH?#oBZ5JqJJ0$@?KYl46G|7 zWCENpzt@$40qe>_BK7ZXkEf32@)1=exf#UrM|Yvi4|r-MKUR!+i%`=_Vv|M(*0}}f zD(DQ7$V}rWv*6;Ps0+AH84i6bMw*J2N3n)9W=%QG!Uacg5tsAWqh4) zUn$itE{AD0?ULij*_PaJplp`BddPc^$GGFTX&|~U+q!!O-brX`i9UR8%v-lyyH(<4 z#?o77pH@U==@kOOo|L6obi?OX6QxyXKi{WstTwd$fS?ah_>lJYbqf|Q>cgFXyWFJ< z?8`C)FgI#>=ABmI^E)W6)JzI7 z?Zal&*5|o45n;tZb~3xB=I+KU{4Bj9FstP*lgcd~QDDWHf99>wY}$-8{bs`BgnU;6 zVlx@|NraRjsL86>B;}AiMXlLJqgw4O{d2bSm%bE`tX^Z=(*K9HcMP($&DKBDW~E(e z+nJTNZQHhO+m*KMtV&yzMx|{Vv#aOKIo<<|k`^)~V>t5G=t)=IF zi)1TxReatyNl>TLM@zWA7^KA|YEW7aPkep$H&LP4w}1~#1;S%-QX zUhDrnJ-7Zs_tF~(y3v>fYrtVaKBwT}f6u<1=>8$gQqmwC8QbwVT+x zQYgJ$jLE{tA$`BdU4?I=<&cfxmbn5K3487oXB3m3gDx^jhq7LUl~~flc2)wiUdJXR za2;skIE4(wXr{}2#|QxP%9IsPG~oK5NwWEKaI?imWhzPm^U5yABQ`3%AIIKP;AKm; zZKPxC0={L2TA-e@U=uyIB*sm5A>=$)2j})M2@p)EEU&sNiCfb@g4RN^xOOzpVR~c< zMg(Xz?^}1}wy(+%>@gW@GRX15u{mSLhvK~BK;0=ToiKwh*S=0*PnEU5YKAkP;;V#8 zwzN8Y#{Y6FLAYj<+Vo1S3oWtkqRnBpJh#i}2q} z6B(-r$!w|TLXuCc~yH3a?Ws0rV{^zUCt#O|Vf3lSSc2?OxRf_-g{IdC{ zQv7l5|GQEwk%jaF|8edCSxTB6XMl6>Ka*-=VR0|NvPdbl%vWS=Oc>>m+*0l578Crf$hwRzb|jj~f{$`dM6&LF*H**A|F zYEp;+cFRX8V_DIpoN%8^RkfKeP-VhO{s`gNQa&zwJmy(efD3C-HAY3XDW8GHc&N9E zHdD*GWCt`V*}t)2UTgFX zC4=)qn4}%6oM1WUuHejBLJ?)azlhy4R?9VC3h}C-6ysgYlW;t-_Q5Bdt=M@0LL>6s zp<<{OCSh*{ztdufFsHVRI%ZaO8Jb(kwJQcV_b<`(U)e-~2;gnb!6#YsR;XLr1_52& zM(%CG=(|pSBUBbne``1kGm0(5k$rhE&q97WNi!u>ckQ2XaPxcoKBz3|{sdTM?TQAL z`$zMC!jy`z0G*NWw=kuUtG>krvm&y{7>Sdy^1vx*!wnI>W5W0FDvitJQ6{P=d;tU+ zK*%59-IFTMuSa^}!_9LW3$%}>cv&h-;%7KxOH&WWozK^@DvPZ$>y=^7K#|&UFRblh zKFQm@#aISFY%GFqJZSacJLIf>XP9}HlQg(&w)HH?ZO1j{Wtc-TV(BwR0#u9gWno&M z_SE!J*Y$A^#h%z7l#62gPQd0bw`JT!Y+qR-zk|#!QC?V}yn~rnINV8i=jty&b`D8( zlDWFdEV{~gEG~c8_qC&DNB2jeW;^vqA>7bMXGaglgbVWIM%gl&QKE%)-AhZMvvX9QU7>Z*>Tc>&IiU&dpKXR79n_ zou$+JDFTLD0?I`$*hZiTpj?2Rezlc@Aw6&7L2A_JAG|q-rE4 z-WyO8pvRk@hE15$=0Gtu8cjesE>A=|&w)~rDMSLS`x=u{sg-TbCS=zbFE;pLN{&;a z%c1S`Ai!i4335(+e{+{w=xXt)tPw1PDWjsPUwddg=G=_+E2JHThJ{j9mtZk~;g%p; z!Y%K}^|Rr&De1je7$j1dhhikWWa^>8iRt>?R4WBva+49~7715E1zYe(nS$3~!bFGC zfth)JO~*oH2*=|gFr`gS#BBL>@jU(5m@3-x2Abg9_JQQY2-rnn!h@ZU0C@N3AhfzO z!a#nc=2SrNboCkW{U<{0sNg-4vq2Z#_0h7{ikecZU&G8P!j=e(`R0PkK0H3tXp(QIB^GHj_SWaUrAI6K^?jrj@R!JcIcq)CxpMA}nDK*DYi} zD=(e;D~S|Ma@15KXzN3YrV_`_RUBuKqS&{kDxCwwh#NB^(#Hw0t>37)LOHlyQGr>% zWI6YZyz{_3TVJ}R5L4MWzK6Cl?*H-bS)>c+WD5x$-Kd|Rrf_C*HU+_sq>S!9a8tTv z>Vk_O8i1}m1cXY(_(Bp|DN!-oMD&KpUNWeE-}%xB<%c+?jO&Y~0b97wd^X|Ks`m-0V%80bPs$&4T@*m92;jI!M2Ug0%_IFC2$Sd^2Y(BwgzAx}CFSsf4 zDL?dd+qtFRR7<-ZlEN<)gC`~`2Or@M&O^IS;@I(pVY`?#FcC2Ea9W_`rB0Ell?skQ!FjdKbMPOHs6Q; z$b|Waa`D$^r#~i4KVa4~U{YDS367`#y6Au=5gwBPQwL?Y7tSC6a0)Z$uW!R{7YR$@ z@)SD2lM%K7eR{DPokM5p^ zv?GB50Z9XDzXJlvV= z)!O7K*x6p@xN?{is;Ek%5RNv>_NKI5gstV0PCXauOBiOAfsUr>u0go2?T1;vCe+nD zRi37U`Zc9vCVZ`dq7@O|EAg$eZ3%tu^|iJ>6upYlnev(P+IaNHz5R|Dno+OO|(BGz1Lx}*h^D<6!Mlq33&@= zls?6oE`Uhva3>v!&sMPpujVW1NA)CvSrroSBebhvCTf=A$ui_aVY?C8fFBkV?;)bf zC9w5~e&cz=x0L#pS<`5=m99zS>kZAbR=_gyXdoQNkm%mn4v-Z1$#g?p*JT0yXB6l{$;~LbcnwyrAzl42{ps zwe5|H^*3=@p+m)TvdT3GmLdGrc^}Qd)4ZkD(IVBiuPGEZhuzE`bBSRdle1C=2ak0Y zoJO7{`l00pt&xZhveO~6BJADqRNU#F2`Qzz#xhb^o+~J8qHSBPrcIOVXutA$fdH0C}XW@k~Oxr z_;94tZ2qa`sIdmx)x8qjnaC|jVc5oq+&p=mcKu~lk|6a*Q;Em8aLcws(}~Dps=Ou{ zF1kbn=c3P)HXCxq9*fusVXKb0N+J(8(Q2YRKKG<~)F9Yo2kid&9$m}iUUTBjH_dzztCQDxb5du$}YEBE&S}9N5@*8Iqo)&;Yu4b*z2qQWtrR$ zgb{YsRp@-r?xc)9oScHr$rB=4%@9PgVfLYv81??JO}uAYt1gTh-w(GvkMZN@mQiee z`A=_^gI-2KUp?hW15)3CuPyYGR<){r=C#AtT8&M1t(!i!B)!{@|1_>8RtGr}4L}S}L{EwP*#WTv zE|s9QuVy?7c2G^}LEd_FcoA_LWYHQ*%-90)2YE3eD7$K^)Wlyu{CMKdBCPv^8t@C8 zjS&><>F^V$3jw%(OB&J>IhW|6QFS@U$@xHEl|+KV2suGo)&X}~`5jdIm$lw_d!^u1 zu{#WH{9JXrSOA#+Xtb3vCNeucy4fS~|MceY?wmwAIfVg=|b^ys;`!*8W zReab7$(h-oPgg~KL!(E4=R>00M>Q5d@lo#JVr>s3)=@9%i)#f*z#eC zcR|&$8z5{hm9)_Zjw>YHDKg$fOjGV5wf_usw`MHhG16+U6ZuO=Ujj{j{Ll!Syn>2* z!2LPva-t&pV+;%^=*jxW03*4QD#3A09QVe{j)zJsucF0>XbsNcS;;e zrs<9AT-`8^ga!N%1>h!b_UqG0NUy_oA)`UKe*m2pmzf0j zWJi=+Ps{J)(U0&&jgu5u8?;dnsdrTpH<5}X!6G&Wpdgv6bGk>R;{C(2{YrCI+2^6^ zbCtKdPf8`0X0gI*F^M3gJD4De04v&~wTm1%UMWT^ja}_!jtNF9aMR@}X)kG~5N7(e zM#b`*M=epZVnp3aZ9I}-{%!znpr?6jtz$)KVIfl}st>yx!FL;m?*ffd`%5-$(F<2qEPkPff3G4&joqsk-u%hS|7PDmHqvQ1RK)#C-j`VJP-O5BFQzEkGk!>w*l z2P}TK;jfl5XAQE|2Z{M^Hq%k$0X0IY``TTUV?2slo3pnN8uf#sI--oUrm3iLG5Xe# zSF`bm<nw8Qq28HR!Wa z{5Gb0N}USAA~?+&1B54kM>8-lm%c$sU zq#UV0>N^6!4K0$I)n+rRVN0_LR~`2yFQfd{(d*wW>k!h#5t9v;f{X_=zefQt{=X46 z|E1q}r#Do-YaRdd9t))@X(Zp49MZhQ^)H90y4gy^uc)E15Q1bHfKn871f|TL`Ac8#UdU>PcDmvqU zUdBHPxWpCW%YDGML)?FhRpx&y;7pWdtg*#V@%1OS{N0uqCGDdr2V6yzwN_TCKtLBl zn{_%1&~52$=?7!co_E3taNtrZ_Q^GVDOzMX^79z5TDCV4u_M$>$e|KaTPA3#oD>Ig zsYkw`?2%BUXg4zpGY#sT``(&vuy1jg{ex0|S}OLJ||_>XswH zI(q(c)cT?pb58-`GB8}(WvP17R_$Chn`GH2*l2I+XzKhCZI0Rg$X1KZ@+4|dELdyG ztnuKBA`u7<4+Mst0?n_TAEEV`cUT+>9P%DsK91FAZ8-7ibrL8C^oR zFLbvK?tpQ5$w>fK&GH=RTSvXRS9u5G*p5*f%H#s354Hr^=7W6%g|~m9yHslj{dtV9!m9JX>Y_D0)*kLKH+m%cQ z&ow{$aeXGoy&5*S{XTLP265isfo?z=7=0V|MaM#<^GAVtf!QVc28uTk9JayMGkhGy z6S5^(tpZeW$RmoNIxy(Cb&vI=6MD*aA^oyb%cl08LX0))2v6p>n|LppdyG8nc0qKA z7K0f$y*Z9~yA8bQ>{$F+JPGI5``aHEN0JHKPA5TR&*VZpCObpZ#g`3wPN|X;nTZ;4 zcn6Xzj<~GD<1Nb1jwxQ2^)tf+M4>ECI+?VnOl8KZo_Cz7Oodbq z$Jos1H$NNEiWBIwoazaM!-pq0Sz@%QlIh5$YWIp!(83rgbL=G#vg2kg=0}1+JaY0g zi6qrG1TC27iM21)4Q+db%v)wa}#7R3=@AW?M-7=^d>Ip>^Y&^ zdGvbpMMpSA7?S4_%nFRscr+0;ZuaK%MU6Hz2QoJmaX6(k62A&?4(eX{u2If(jT0su z0Er+=y4dZm7prqShz{b1mece#iGA$@;*^r0SE zit+{x-Yb#52{d!Or;F_xl%@6gvUJzY)#JVZA^ZKGZyg%Mo75fy@bUFO!pC2$vVXuw z8YU^n5UOD(QAM@24O&2eW&cnO9x`kzMr)ekaHO}xKpcFi@Hl|PtLDhMp=8AbKaF;sNd-4$pd8&3xvv6ar$u2uUrm1U|t9_?d6b)$Z z3s5p6XgmmzYyqNZ7+<$M;lbWr@O>&tKK8i++)+ean#V%Zyoc1Wc0M@^dWh@Az`$U_ z3QB>))5Ths<WWNAG+RT45Kp|<6Nl=#n>@*U7cmB^M16_5Dd|Dj#Lw$4P zP__`nuD&SO%~sew>^vg;w(lVV=!S(l1=+Ef_%>N4Gzrm}Zg#K4{=D z^}(>rSF7!3&Uua=S~`j~A-RGsA8o)aNdT zjHA!Cf8)AA@gzv1Kr28S?DBJ-`OdkXM(&6rzs%j=@=JYPqZGP zrfOwDkwo8xLARV0m8@5ixxDCg}i3-5o0 z+S*Cf^UG~g_K*Wq7*p?7zwvPfGpPex(%%m9o6b z+|Y-5_K`^EN^P3_*se-xqor-c2XibmMofYJvt1DOo-gNH_PH#qt2B})vX#I ztCn4o?7U8z;lLwUszCf0wZ|H28A)N_0b4vNkLb`{IGVA7kiQ~|xWFJECvu|@<4xX@ z=`P9kJ6z&JA&JkV3_?oRDQQ~0YoGIwk(p|W#Etv;Ef_)4lr|47W0&m$RaZL21}!_E zbyA}u8+7Gy+~OhnvQsu7)dnF#djEP9v7oPVecp9F)EwXY@Tyy}&_S{H^kUIPjrEII zqL7RPrw8Una6q)23s4!K#SOHaY(@6VuZx*St&U1*xh!;oE_xvWJjx7Ei>H|%;G25w zZr&eb3TMMB9~D++U=+uGzDHVuJ-U0Rpnru?S#OP^bzW$GBz0*mBKCgKE3v%_4_D~sg>Ko6`X%m zR*ZfqEnI*DYcK$f|FcW_U$n;lX9(wi(j(I|*HXdcd!EbATEE-K!eY>|GyG+%NHDOx zm_QS;zE{#5QdP7VMr4?z9z{Vb@xqR5`pdZUH~O~iLw>lpVC6uX0vaJ=Qn3`JL$ZQq z0+A7kYc+x;j-{G+)}gU={ake>9K&z#Eh(z5*QG4gr#4@@s-K7Zd zBP@tvPFL-((5%bUh5E@527Wz%#&$1Nfzc~Ic6zmfc@Pc}BPLC$=WQf16~@{KBs|kj zm&f`&r9~Q2Q?VwE_p_QXFK6*6wS;ee(-r%|bb0dTwlzDH8*0~j)`H`bJz4rpGPJv_ z@^rz~JIhZCD$2eAT=va}kOHO<%0;kDBzyuIlvyy@ALU)UMt}TT^}aIguzfs8YEx-V z)N@+uTy>-&;iFp+Khk+nDxo5RlEWgP_Wsp3b;Xv%T8~7wAimbSf^ZZNb8t+`Ct#Yt zF#M=M`W~d9fH~JoAs!r$ka+^K`n~Oe{MZjhgRPz$>%n{7{ww49!}Ogao}EjAUTo`6 zae1iMU|y0p2cc29rwG|b?WLl3lb5WQl(rAG&7@?edyZo1_m@Q9 z=Bmr4Gf>Y?VVnK(gh6uBtYhBtX&>Qy&&P>*TZsTD6XNF6Vo~pkK^RUw1)al@OU#9D zVh@8XI4$4oCedi3B8F5ldkG77;~Y-b-VgUl0n#niwbrPE?yic9^x;k{8ng?H($yc>m%FL z)usJ&oLY)o#YggsnjVt+Yjcz*d=6^o}ab^X%+$ zxUop&5hjzQgsBTP2mI97hs$A6Q~4UgA@3p2rN_o$&n0Kr?vB%=j3v+u2~d2JC_sN^ z^Akj~>pGzC<-nAzc&a2S=hhIOz}<`oq<6@ibVzo*WSCZm%(zr!{x0QGE+}_+K2PtM zLgfXA1t+VE*WFSb6aV6T0wkZ8AProdlt4|2NzW^KUW^;?h7kiaUr^tk&yV>^Kf=d8 zNseqy%3SaeY(^zQ_R0gd1{Jz*amym)jpVe1(ip=ZD)5Tth=?^Iv`sDB$O7}Gmx5_#9t$jDa`~9|v}E-JCPRdwNOz9Vl-%vSID`mw=CeWL z=#<>pf^=%2#YoQj{+O6Ox0ly?H}53S@VYmB!LGH4|

@?Evpc-N^0FBE1NlNZ&rWrmX!Ah;#a+&BdC5`yVggOOne6 zDNQVw((WoreL77DX4XV3sm0)Fd1+UqAH{txh+!5w%}QLOV1y~K%5~^j_mpT;N81}t zu*E)pmK|_3kOLfueRnH1I}Pdi+Oe}+XfL*lbctoP=SFiWo-sR?Q()!SSK@5#IN+X$Ih=_3m}v8AJ{7B4up^*;5P)3^S;P)=v0r2K^G>l$VO>W zXa1@?=?Ao<-eYJ%3D6wha1<|rUgSvd3N`2Hy6)YW&-~j<1p8A8cOCL}1+WS4cm@17 z83y;^e^(oxc67PyvYN=Ae9ZrzO(J2#w*%qZk$>VzlqxYknpGlvjaFM(aF4a}Xg>9E zYiPDvJu`pgxppSTi#g6N=@kmHeEqvoAb&(5tgG@<3P2EE0$%dJYQO!xc>3!;oJmwY zOdkWPh#BZ}7^IGJwlJ=CanRTDydbUcV=MR=dO``E0ly^}g?aApUa|(6*f=xjg=bR& z*plPmW+8|b-4tc6#p-tX-|!{tHhfC})K>B7o+HR5G)wi&f9Z8Y(6m z&yQ7n1sy_-mi;w7{Opx6_r^a2Iyp1Vf#dVwnnytM6!%)|*|%~&wF3H&lJT?(3-ORnNP=h&HazE8gVyK}4bBK%dH3?+#@V3y4Wx^}626$O=njS7PRBQ^DjNq0y2-9L zdA2`aT)s`Y_1wPu9wM>lzWy!(&Qk;S=NbYg1=^x{=^YL2JQr!u8f06$pcJ0mr>a;K z-@uBr8aq}Q`*OglM(*^;kiPpSFy{K(lYcH(?3%NIwgZ6alL7H@a#~#tj97ur4CZbW< z%sE&dOoE;x4O*<2QNwclX9O?@aw6|_PWZI>aP?91f?spy{f^2QCtv-m@rSFM} z)QY$V`c>hO1?taGV%^btLz%#cWJXoio+w!E;K=7>Q5M7M3b!g}&%khPbzku{xuiiO z$F`j;8(?yy7)2H=z4nCfQ(6fUy!o@hzD7^oP_qo~s!n=#!^h`VwgB9)(zmVK--Sa2wC_b1%x&I1i@r?%AaHZf8yi-bX|M zi+oWmD0h$lbV}SwnxZ&}fECr;TmjHj#(+VyfxpVQ)U=A4;+6^^Sh#~#PiVgTSy7;lsIcmsef_|RwJDYZ^vWmIjZ>DXUn<=nuVQk+! zKhRkw%tg+?N#yBKc z$rT|Vgr|9~%QUVVT-UPeFtuOX7sGr-*7AEQ{2%rZHCp=t*kd%JNln!tkk3tS>wD*T zyZ+d9$T{t?@rb*F?D#{=8K|oigdgY79~;OX`+ZCOcg`ZwO1S|Jo|{VIg(0|#4Vm5J zu=Ba)v`)2|zYWVWrIDG6(OO6>)u1B#r?0e{4YaQRAki9MN`@ofs%T=~928JQ&ng&0 zQ^Q_$+K~sXSb!ETkh#{3dylvSDEnwFP12V@6$?Se>e?k^g@C)IpA#FuX7Cgv^n!P5UaqCkO!dsDLsbtp3 z{m{VYVBz=h1UJ=f-&i{z*~D}GYU2YQefO!UE2`(hAMM*1im?y2n11Ag9gQQ{2Y=;#^xRHI9R6n{#vke}1hJfR2b_ z6CD;}ah{|R<2jDdL$-gOiO5@Eg(m_#Z%5-BY1b;nD53E^@gjrrwiiEs+QLP);RNl} z5rpYhI_ZE4a zDX=eCN{p8H9Wy%EfC6vE2Iv4w>T>XiEN2*yH1qjp&|z9hF*lGY(x-x|EzuXk0&>I$ zSx^gMZcC42CN;^IG&v5R!s)VhXoJV|rTOiKeI|@UbAVH*VhDNx_=idPjpgsoi;@d^ z(%o|QlUm<-GS*gdYxSF}=f7L=`A6?1X0{GQ0JL8Jf3Elbzv%{M{`e#aY&`lYTxHpT zj#gH!mJQ!-?l;GPAH04ckS!;O?^gH*YXB<#^5xp;>&g~KRvnV4dyzgN+07V9g^ZHY z!ckcimAV#mNqJYcOAzqKRJQ;3E>lJ} zJ$uG~Yq|b8a^slc`We!-GfU)hSI(5Bo#wRk3&57Tl3Eavd_SjZOKf3S@1aq+7V0(p zb7juWqufjbVrdHTSzZ*R_{qX)A}~6JY)BI6*w_hhWsXTtRZXkk+aOusQ5&YGKJ3u< z5wO_v@$>iPg@-$K$ov;GkS!y4pdkj>NFbo$*^sb`%k~EK#_tu4zn6q%N?n9GgM3!V z6fvT(FL7`Rm31;w7}#-6GG%qxMzrtuSZ9@|p5?YR3W{t<7 zqpDUZTwiFh$d*7Q{}=}Wn(eNMq%h^a&@Wa&EQCrelxRP5AD5rNjA@a#W9~YLxFdUQmobB>3j<64&L`=C)Lh zy?n_-M2bFKiuufkw=C!;}=+jVf>{e-v220-^1Bc5m+$mGu>Df^qf?bm3MJ zctX5+=UZ7)how$jqO=qifwE6Z>sa;FjabUCJzRkeeVL-lO(O+5(mqkWE6 ziU(>ku~zgXN-7s#;vEd%+$GlRY&URH8E2fs2=AC+i%P1;wLhkdaX8WMAZCpz!%c`7 z?ruk*(im^ScZO=p;+#+93=zzeS2+MX*HbztbNF-fDVWHOqKz?=L8{lboSx7ji1T)) zn>pf8!jse{13?3V!;@4DvF!+&o;ip6I*_{@_05e1K9({U_qrDLi(;PWuXjTc2-7C` z*>E4%>F6N`(d;n|^zI4RSY0?qzYrQJi*aTITOiZ;#12M*y}pgcYj8xK+;1&r`T;8N zGICj#J z>GBXQD1DW0*1vzT-o-jKFLI>Y#avt+(qR*c;&^b&&X}lE?>$C*B5Yl^7g1ndV_H|% zM6U5xa`a~TNcwHECB zho@i>xs$V5Mu~xVohWm?DDvg$pw|xX9QIc|1$(XF`w~%8koQxP-=n86P2!}Q->YVj z=GeZ%6TDtz{~9-|ZTiIdICng@9>>6lsFm{byLCm_?=G`doW_x6E)#*w@^sCaMp3Ka zb6hNpZD&7EugZQ!<5qiFepy&ZBjI59d%GpZ163?}#6jL4y zh$9mJo3_tzPJiaTa?X1VnJHH}@mTe8nhl5xV9Rt(J)`JC$_kWIV}8x?fJo4Qs+=ye z^uF~L*mq({fVd;BDF;aen=}QwJFBJYV*O7)a1J+d5vM?EnLR3|yy{SLY%P+S?5))KUM^8tDX9@>qh&`j(~ zo*MrIjqeg2aY(GE6Rs0z<#N!D^Eue21(7jB~$vqyKWZ&xcSI- z0Le!G);r+b*$-nCRtb1I!-`$8iaW$Mc-A{l72(bvdx%NP6{GtU-_8tA}pAr|e_M zangeHR?R3bRlLj7xTNm9@_A8W{JNcw{q1SG+E(IBz#RRZ)lg6H&0747{7S#l>f0&i z;d#lb`y$%q$QzIv)=dheEo!t!=v$-ydg@3ZB(^~v2I7kFTG>O8s)6k36Xi+U@Z9Y- z%>2`U)ye#~m(QVL)OMlXnAsu?IF~3Ni3Gfftgwr0NnWX0YOHbRWu~9Ms69M?%E&!c z%{?1Uuk1FQ{3x`rm;Ttp`|Lm>gs>9+P0wbmFS>>l#bx?9VV+$YT;63eYvwccE6U(h z&tP0}=q5P?=O>qV#BWUcI^@mcfxxuya(FAubw4Q}&@smiLv?QkTfR2DM+V_Ee1t%L z(DpB|tnbJM!s2E5Yo}~GV(W^5!F(iyRyKS9Gw>e3A)54K8c92ZGRm6Oylb4|#&Ydw z4!aL!98B*Qq}+D#q`7Q}DdpfjsMbM3QHA1!7EWP(;JzfJ?m&`G<63O+es7Kur9Nz! zGN|@hw@GUb-*q3)7)5|ZtNQRKa2y9!GbU}M?UlhgP)H2Qf+IRw`o?fc{e1bR*kTmz|MXVoO1(Jnobl`Z{MkYeuP=q;qZ=FjprvDPR_pVKq{VYk;BRoqCc zmrdS7_x^sL#hDCP5huav#4wqMj%Pde?9#%oUGXuZ632C*+iH~PeV}$GeN4QjmZlfK z_4DuNv;UEMcwU-8e{R=J1Kxif8~A$>^w)j8|9|h-rDkd;>KU7(>*<#PqkvH}vdk&^ zL-Rj@b9HHFGvooKDN}@qQ-7To5`kgyXs@vHX#Xdpr9v|p5&$ZoYyfVl|61<-Pb>33 z(S3FR-G}+(jq!3Y$}NrRtSRlR;M|@7Ld}KLBGKWxN>#km**AfaK_P*$gyh=qMkGX3j~Gu_>if9xDkAaTDy&O!`C}*?rkiCL*Ot%_CVH)lY}$iNI9d&0Ej} z?>qJDy|zRT`#8l7O}P549B0-3QF(Iml0gxCZ?0Iwxt$$}JX@A@fL&+c5*TNIhV1>T zI3nxh${n;M&_dmX3Mo<4_}CgI+AZiB`k45VvGZiZ#1W}5@Y@ynPX@^N`YI36AbqGw zfsAZ%AeQl|dN9D=UnFe%XT?aIXp*1lK!G#ri`IB?ws>*)xM^Hl@^|sx_TL`)`N47b zdq_yria7=Z)X^Wq;%^8MIw*6aS>EY{Mb$r!C}_6ypezbm3jUn1wdkh9fPeUd%_iD; zb!#c`!r|uE@V^>G?>2ju;?DIf)|a9GsIgPl2X1T4?M-(V8>N1A&v7rY?QTiSSZZ`i zBEZDwik3?})4Wdc2)jleV90XAtaXnDN9jyAu4TlQlX=BhaU=Z!H-yu>e5uymzyg<$ z;2op*mF`|zLI5|~1vVp_l~~i+%#f3Ck?#?$eN=&)&aqP%mGh+ZOFg|3DTYM65sLmg zO~zaWd#6yG%Hk{XDPDpO>{9Q5-R}KGr#=7@6EId1)@88nd)he#303^JNnwQclodp zOuJ`2Ucgz{P?}()0flo@U?O2M9d&3(<;7O|7VpDlwhV)FcnHTw9%CiapG5R(l)5h7 zFw<_pL=zeVj(E|}?arz+?alY>v0%7-74#}%FiNGY-e74mRj16-l;y@~*~njGHkyAI zHRMqtb!^N1)nJMHTf5E-zhDA!tIl40CzB4*MJm-L^gx>PzD~dq%&}Uv#%$tf##};@ z6xEvaKq~ZFDRB$wHSSxh?0M-+3US{%Q%yvw_Y_+YcDC!1M~}iv3Grh3Sf;~rns5{@ zCug;%6;|fuQJfT+G=R z%-70u3A3GQ&Tjf88$&)tGQqnbxQ!sVL0LX+>4aR+z?ZhykA0(Psw&e`^}4&ov1#;k z71o-PyY}nS0pG%j2HXkpXOtDUcE9Y1E7`nzlGMn7mI%aUI2f124u3<1lPzJw%srs&t4xT@jz90qulJ9;GuOVWnYCK z`{6rC9U%mTHLFGsv19mHgh{exj*&a1ITtA6M3%a5%Pcx(We{I)szIX4v;@msPXtv{3}V>`g?SAXk6a}q(^e80ciUFV=J2*iY8 ztJ+-;`AcUPyF9GMT7$kU^%32~ELK{L);cT*_^Gus^-m3MOi=SJ*y6O!e7^zk28FTb#chv_v z{B{TB_i(J~o*NuuZezb`AyH2}!wOq&se~yo%WW`NkLcvkM!5%XI=?*^x4a?9xrRDd zE=KE1m`#?CjFN`fa2ZO4ohu=)CE6prYn8sB{2oKz)`eaIlcKZA8iJQ?xB9k8VXcI0 zC2b(XeI^ws5}BQ?*i|2`^s&91eS)PUcU|_~47Yn!DQKjBPA+Ob7M*)3Y97BPesx~) zl@5F5heIh!^(8Lrh(hPMvO-_X*}lri4|;`859ut*90feC!WiLj9g4bl6{goB{a90@ zNkUA_Fd>IrQ`ngwM8`-AWfntzp9YENhhvf~>zu2E+^d8|+d_|MJ*~>33->AqzC9Kq zD^07_S)1k=?~Syp&c2DSyOS`ek6-a)F3F3}DnK@?M|e+F^r||4viG>wKPuD}cQZ>? zJy7kEMvQ6P#z_4*lE!dumd$qM_<;By1NCpZ5>G=V8=xuQ0PnxPbNAo6^6%BwUkgl= z=)X6Po7zx|f-0SniqM?xVHtg@^RJ6ZEHJJ&(WFpM@GdzY$vVpGflX$jE)IfA;_W!3 zJjvHOgHP0xJ3&#?oD{x4sBoefz>42kUUl(gW(jhfB)%;DKw5LNkjaH~XhFZcXBT5FUWr ze+KOl{)O0N`cGSne~aU?b1sqaJZgpjLUMLZcnGR(z6{bvU#~US0;!MRb|1_lB7*`4 z2iO!K>GUR>S)!Y6#eAQL0~FtyIS=>&C;MHJ@bC$R>^~7X6;rEpg0o>!H(40p`tkN@ zk7>Y~I;V}>UJG<3D>6Kwa~Pl|0enN&s8hPiBS+%e+JPD!MNZ!sZL=ngBw>#2!g-2O%^`&ChD0C&1=Ty^HXCa#Qw&|2@!dQ|#FFu7FF zc_u$Li|WXoRepy>o{RS=?P9P9aX7yg^aY}b{zZ1>u%|u76PTHVUk>EqHXbwT#0DMV zS>iM%KLCuRdh3oXZw)#Ou*b+uG5bmv#M8ze3McBMdTti*^v@}VeT%?PK$JVgUlj)) zZU+qi2B-XP4~0I!<6Gbz+$}qVN1TZdNr*xt?MZ-P55joPD`h^cE`Lg$dy>L z(bTn>PoWK=D^))7jJfOVA)!U1`L=PdA^BEcAqos}y%M{f&Y?H^JG-(uL^rNpPx zR~+O9=j6I;nW#0Tliq@Z!2r=#^_%02X^hO4ZB*pWQcdI3tz3>&4(`P=@9`4Shq0WX zP}gxuJjmg=5!oU@^>rLYvX`NSN&I)v>o4>zgB=d19b&ZKhZD30@&pauOFx57N3Z;q^ zgRdD8(xpKAPE{AfYXR>%uU=7EXis6OI;}%6h^m*zeR(g*JC*bv9Hk|n#+&TvOIlHL z@3+jYek`@fib%b+~dZCe{BxVr{-cXxujyF0<%0>Rzg zT>`-!g1fs1cL;6)&P%%2-rar9?$xWls$E|dR6T#+KcnV-%`wJog4Jww1+Jyczd>yY zhobRF6-uvp#G2&8VA&W>lh92^Wr_Ef)O)I}v0yO{rJ_|jEJ|==#VON9A6t^1QK~V@ zABUcS5&{ODpOT+xb3?1j`*N=_1S2KMB4>h4E|l15k|vh8N7<^OY8bVPXU4~TRK-v# zH`{ZN^yox1C;GV9innX|H3+5is;rzh3CmH;09+e?#HBY4UJ&GKEohYs`7c_7IG zaS3#tJSkslg?S{^7xkX8PS5Pw7wX2A7bvw|1;hBXHz2M z-|5aOLLo1)2l2z37e*pF>6 zfC%WD#?Kys8)46+mP*s((P&hIHBmGj+X8&2$0cgfvFN%ngNDkA*m=E$*?R4!qR`Yb zGrsHNVVNu#2B~DHDDr-rT6Y?#%41;pZCxDjgv>%fWcj?af8zl)^7+mk2=VN=?7*<& z313C?h9km&HzOi3(*`HhvS*VmsS4s*St#UEIRu_-)?Nu5uL?pk146PB|60n`a5C;) zJ3qWP-XuGr_d0oI-GrAT$_Ke&{naqb58)SZP`c=k+Mk!B2 z4QFgIZ|(4Wifp3IAt$qqZGhQ#r~ZkN>|8)I(-r6uJ9i05QKw$^dqM;!PRTcoP7Y_@ zFoGBUW6BZSujXb%xyfGM)A~Y8q7IL-!RMq|q|K3a26XzEZ1y;uwu|F3tr3pRj`Y&| zyFwRhfG*pI?Zz;*2lF8<;!<>MfEju(ao%pQrld~alcu+jscWLCzRrMJKSLHrmn3q8 zv&S-O1*rcW^^HQ_2C9=zSQSU}?oMhxKzW#+pg*e1I9gTy!0%@5M4pVQc$xY15;tWE zeF}vkXmv-Y&t_7WCDh3HNpwQVTuGH5c)8erPfLS&$SU67R8juW%2$;wGKfZ@(1dC& z0h!)RI1%u)PPg!ocCnt-FyIoT(ErATZJCBazpYY-#!u;PDiOL@D!naIa@i<7Q!>qC z!agE7THUreY9{uKMs^eGk-`hP9208BALL?^&?5_cdYO{5?vRra$@#6}TOGz)8YhSD zcMtq_uu+#V+|^T_;gytA9(cx6LAYjD();zf86R7+ftv)%3SvVe4iuZ)o-W`;0@vdP zpsP61Cm-c1E3&8dm>mx=l~3qpz2xy|Ula<_tePI!KPD{u9*QmScNJO{hTG_A=XO#( zKRa`~8*6h^l756M457Hlhp1jlEB>hLt6$#vpfBOOSol-X_CC>4-D4f`0Rz|j^$)Mr zx1n!GrDfs`Chh?K3I5&G^Y^3P{{~A0gmnQZ5wx6PTG8*KYxOOy3;xp&MY>yt68u<6 zAO#eOVsdA3PY4!z zyb-1g1RvqF!;FIbZRr8qF|CHQXD<9l;{7nvBpE%rd+w1dG8K2;#4iw zbr>t0v6rhHzhj<5U@`o$11RembM~eBfwc-L`bO zPpipwe-B~6oD_F$_PD<#LNhN{OS{;_G}NbIf|_k#hP+3{Gv!a218emGvS;fvNkgt=Fde>zT}8`lNFe>Hv<&d>0&h#TeB>k^PzH zSr)(%Jr7BKam09*yiEPEF)eBUN92!&ok}?NF_BkYfu+f<5Pl7o_#W8;2n6^%DC$yr zt*lb@`2W~g|76v@?;z_FI0KE5&W6JqWRhubu}3^33|Sk?#7EazccPCk7=Z}`zgLz{ znHu?!U_YPZaO~MJ+Cl$F$}k5F;;VZlxy2z8aA1WN0A+733%g0kFlgqGiPcrsjyZ90 zu~}F(WRtY)7}tuHH>%jF93mWA#vvhulLDcHuJ0^%Ot*xQOJYVVl9qGind~BRJN8W%eBzPr-uy*3`Y9u%}KjNnEx9kCu3Pl?01+f3#t%w77iJ-YVj)q5R(?548z$#$cD%V^muVrx27-M6pfIP14Mr$cHm;)&a=r6?$rO6r=qlOk2C{@zxN<<4!3 zTGKI|9HP7BX1qdwY=c(25)T{YSRaf0A^kYz5%o~ z-IcYuQ)zK8Khs{+tlvNntwQnoq-|@AC=S=&`uV7CT#2)EA4}ZkY6o-l$LtJrvv~fF zX&{dPTHFdC>R6!v6Vmnl(p8s40B*A$2{p3iPELXUgK+37{d-O9GpRa$XFKZwKqEwr zy$F5n1XPkb-8vdXmjy%C4+~d@BUf{LvXy$BQKp|Kl-uvr)bexJPr@wq$x`22pG1Bn$rc?bdoD&;>EsDC#QegqhpQ9BtK z??~x8+Gf9H-R|D}QYhWINMnhHUXE8koWq|)M*4YwP$-SG$OR%|g8mOBsF3+hk%E|b zk^O;yWyhZt>aJhqxM9G%)AJ0Fd-L3H^W?M{A2rH{@Dl`3Ll%TGAfWw87~)8FJa^H? zI9s-jxIUKTvQRErdm}>WPK`O2aO?1?F%Oh3r}Fd_dY4jCqwQgC1DVVzU!*;#wQoWW zU0KxcB__v!azvQ1AUzZ(A=eXdp5a?k^&{}*-1>Fndw z$oOh?gfVu1Mp4C(t1t@2Q$@0f8<9MuK?Tf`XCh4W0a9}bF+Cl>cyBug$)A(dd>WV^qfmU> zN1P%vm*(yZOKXhFLJ;W0gV`#ad{NAsNEtnDbv-jQa(p~M;c(uC*_Y_ZH z^RExMJ4V~6A4xfuz(9X#6sC~aHEU?s=S6<%pm&%DwZ*kbbu$&sxD(6U!cuxl+-)u! zqNj<2L{-m)BKQ)^ap6R)p8&Zxe^a%(mYIeSp_)Cf0(?>L^Lf~jj)&Khr@C88nNwO* z+prffScxqTP+`I&VMX&HSOx;|6oRrBrIE1MHJNHP;?>*;&+n->i`+pigA-(F`jga; zYli&50c6!1)E*lc&)#Rzc1-iE#gw%C5~EzfJPOBN^L1p69U0?jaOwDGYQ(Krn?B)~ z`1Dx#TqUQdtvH(vkwMy@somZYOi@y#KX%t%8sg|bQkoH(kO&V|k zEoXw%C+3P_WUJ7cdzP=Bnm{ME(aU>+lMtAhq z-kMo7W(==?maTFT)E5yqG?zHfJuJ7E6pA~GH~L66sdb6VI`V}N3(k!-AMgCHdaxXmVBP^HL%acSZ7&X=af+ z+d6ts7bQp14-1!1x2`1kMVc%&t4xollrHKem6LX-4Q(^%$t!@9;x|;QwFz~X{Sc0w zlP#6zYX=Lo9~+bD59V+Bck|hGyLgAL%H1?S9zA2*veB50cubSZcLJi`)zO7!^y z8RClV5Z2FBtTsFb>7;9MKCfkrj5UG`-akysZyGHzmL-D^(CB~12$}ygMtG+if4ypj zhJ8cUKIOupzWLb25c#Rs$_89*`e6W2q=g3gX8$q7ZStD4vcR<1kN){X9AH1Ra-9A2 zW$od4=B9-u|SwBaR zGP!c4apUpw&^ixpA0R#aa5~FH!?4Tn6r<9N*hCVN zlLsb8oI0ycaftx0e-U!06KMXTj))MLbjOVrIP%Tv9U32ja0DH_MYLGhMk}9q2*2_i zg&#uZDMwi7HsG1wn1g0T%{JWX#7wG9<)+2|k-37jDe)u_E8PIez;9#`wnsL=dS?%L zH6+R@3Ght+sq7$5`4MjS;mOBW8C#$vUYj+Jp3Iw#3T`T)c!n#JO)i|w#)iZu^12|a zi#E&MD45$_Cdtfa!s<3(dL5osbAoW!CPDf(=BUL4xv)S6<`ZOsm^x;0}qXBVa>TZzDYQzjfcKeTEw>L;Q!^A}D>rmvD zn4HAJ8fRI3F%aV}XaN;GDkaHWGccpgg!eN;OYYDSxJO#@mC8VU=xCuv8y*t?39}KO z`*W@&t>?PFkcZa07VZ+<2;vvq{JqUGlFKAM-^8K^Qdhy6qHyH$rpjD;4D;Rc)n@$At|lp>vcPATAp(0R3|1!aF|-VLqK#$a=t~Yhr>0=Jo~u)nQnFv%v+^j_|TIz z=?bdk1X4{68H-4XSO{X%y{tWnJXWoqypT6}0`ame2+>j zd7Yy$XgfB;Ud~@Lzv0nT@l>w$khuB-X6ozD8iO-EyX)saMEc%@ho9B6`=3C<--YMj z&4j;qh5k>FP^&A^=~q`M6+ARL%8Cfyzk~rNoGc%^-cmKw>fvQXtaP z229>1iAou_ABE+1V;fkYsj4&w=Ap7x*}gBIAt=(0N7JFfnIsP`SWBY=`C5VT zJ(2u-t^@h#)Zv3_$(&w`ocm+oPA6_?+Um(Cl*t8n@8{|L_GyWyQFeBD1bv9iA1<&S zHZhn|ZySn7iQ~|`7fce`^Xq=Vh61wsQ!vPNuRa07+gCAKO>zFx|6@V%Q9|@ek!KTe zG~Dy2$iq9&j0kQ?7G8KEvXty=c)IUkhRb+KlTnOS^Xc>xa5)2FU_cTx!IIkab4*_?ydH; z<6n%&#}*^QF+sJLZE+p2OiNTx=h?cW##h{ z8F5VXV8eFv6S6vuTTibO9>YwKG|Qj4juQEMVplW1qn$@(T{y$HP92@AYlOj67uwsDgq$kO~HE{hH(-& z`mO%N2m{(4lTY?3i5`?wAE8_5BEN7oC*Hq7LU*Pos*mbY4#$6hggu{L5~fr^-XNjl z0-b(?ab2uHBLe^uqL@pm@2ykP1z>mSPa;i-mWo^Efjt z-9+9Xp(&T(pwSy7R7ZS+gy?*99;Ol@dxy%;#w9-&lzRY>(B^kYNK+v8Z1OKim;iu; zVE{@Hm3gHsxEf>v9Jyv{8x z_}SApTcl9uk*fJJ!dMJ9FJ@K+=ueK`OD^540{g(p4O&4SKp@n7eY9YA@%xC2qE(y?%Mnlv*B+clS{)aDY|tXOa0<@ zZ4{f}0Pm(UoFVCkaQlwm-`{az5uf6E7mVeR<8S|)5cYXf+8QB>iRasQp-~DNB)lh0 zrPm6c`ChToc4%gE3*K1i3Ju9fJ;E~T= z?8#{;S0=_#EgC>9<|HWJ4vc3t!TXPWbC0!?1Rjn}fhbtm=1?@RzNt9NJX_;-iSf|l zOk7Ko54yDlGqU?3IZJ+ccZA8fJ5NIEEK&np5(7Is8b~xesJN1y_GbfBRF;)u zwMMxr{Hz8pmhCyC%T0^ZT)-W|DLyk&wTe-|>)Q}NLVw=~_i_>#%M)TPC8GLrno;>% zC*o8;rZjg~SbC?TF3`7}5V#9vbKg=qg(X;1MV-J`glrN^I9>;#Cqpyc)5oF?1z@3r zjdek*O1VV;%bFZlor;x`o9b`~TZ1Fe8Bp@htUdfhU3I5R1SGL$6LR0a5e!;wzA+sm zR$Ze3fYY!r2bLUr^FCYcxrW6*CJ`i3k%IC@PRalz>Mk@@+p6DWMo)UDxA$AO+H6wl zy0a3uNsV!lFI_w&la7m0fsYrmtU75rx9Z$sig;Xx4XI|Z@`n3$Kv>nQo^y6?Hq-35 z*KHB1boW=9$QlM%Ltx{;qKfEej$xmwpK|n4=(gNrI-!?O&@Z1{m#JM~ono^iS-WHO zpgjtFK!Pe1JM}I*>A|0P2sRB*z>`_?x#&ju0+<+|tj9Iwm-NPWq>7yBU&8~nqAxqe zWTG*o5!z=>(^jG`)6tdqhB4Yj{0>lOt$Ck%X7}eFN)E**YRjhQn#!DRj{GeOjgP*b z0eh5xurV&(d@$32ajKf0@%fOO zUbB`?i_9!DI#Wks$;{|hdX^ETwyH_D6~pRuY8`OI2=PqiN9;&LhVW_5nJJI+`bU-9 zRCOz%xiot&Rc$s-7Z+!y(u4O!Xt*cf?Yc2hbF? zV4c4gDg11;dp~!vE)f7yua+~+WNX}6BKQEBx=d}jjJurd=8HYKC@s=dh|F%T%u%E> z??yL;{wY_2BM$bU5%?L0DO!H)kiYZr<6la#^ph=K{|O=dt3ds;Y4G>r870ux<@6O1zz&1o_BTR! z{1b?M`a!(^n}}$?fW(&BFFQ2tSiendEP)Y;a#*0k?>h{CYDJM>3PtdnLUo>IG+C~> zaNcpAyHEV)D{LDxysZ{R5O@=)>E8q@aH<98jMOizT-rM=HVo?aYW~c-V3!AtCvJ5Q%6qi_-UT z&H{nm0(1MhAuL3~o>aF-G`QzM+bGk)K8NnDmjGKK;-mpRu0$6jMsI)E9u#N~5)Xul zB@y@q1^0j=!}mY~Yh0T8?k(G@Bju1prZ*%78;RS3%m4Yh_?hJ zjzi>-=YnK8bG@r+tI#`3zo_{ka&4@b%l%ZQq<8{rcdItdZ%Ni+u)B&UNWpJKyE#1~=i*MHqN#+e$7p_*{Wnk}M=qY9qz>z-cI14|n@Sbpzo}I8FO_O-C)hN`rOpGWlDzxy)Gh*wLld>gUSOtZYRxMVSROwF+qvVAZ+j_n~u{=kEFK#RfpnTPICB6Qj0 zt7E>%={9UBZ4lRw$-x($rWi}_^8$fS%UZdTOmxPbIf5^5Dy6?n^F|1nn2}tRa+&OtVGzQT<^(cO{=nB zio&6-u$@}A;--|3Gw!~W@*`Imv zANu~^gb?*6>MkQbrK}gau1~iiGC8Q*bWCH~U1b9mRXp|_o{-KgHv3leg}56%W_E6? zT!2cZPa`~Qvim?9YF>f1KA(>Q+Cc;_W1?Vy&n-XTMD^+&IqUCyaKm4e!$i$PlV zF&Saw*}wKFpqBiGUkf)JNR zp``o%0Pm5m*nG#g7ZgZAPe~BtQU@V)E6fZD>^RoAV#o0KgEB^FU5yv%0Wq@BtnBB* znD~hFkpnkU`Fs|69zMjFvw?!>0ZL!)-Sgy*BVHrD`!o0x;L#ibcNAp;IRm5ERfEzl zAX{F>#q1or5pHj&;q5$#*iS+GirTZ!V7s*dzpgq-i! z!nqGUE-EifKe&VfCI(Q8rNT9hrn(VqN0GNC&{U`x{Kj2i`+BQEa&wd>!{38a7)##uy3iTxiN7@44_mmm7*Zp(KtJ+@(%PSE_^{Yg z(m>=XZ6j?Wq~~B|v8_7ElF4REE;ABlud>d@V3(v<4|)U7f(4XBin!Ky6&&MTt7S&q7zFtjglCp76p zZ$<77sJM}Z#umP*I_jVL%39VSTZp4%D9onaL8Dod+HdAIAf{uor}UWz!X|&S-@O|6 zOJ4mC_bDkW$vSD1Bl7NDUt?_Xxg^S9QB~ro8(x5g5SxNIzWB)CHq%bHKPv!pH9prr z17vj@>C>u%P~SK%(cAm{Y#cX>#*Pkn=YK@k|_35zONxdsz_qFa) z)){;3Lw=N`I~V)vzkSaCXWhvvptB(YY$g7kgYb9V`Df$c|I0xb!5HKA#pZv4gTHSj zjI5(LW2&cmIiQG$98r;C(;pe%;Gm#y1fYlTyZF-XDqtbuoedZYAHK7M4zb3=`^f>; z5&=9EfS}(1KddrejadoK8yr*zz(LhFIA{QXgPN1q>MN+f;NUZyjLcQxaau{K!=6!R zL2^>OFEAt$dP*>u%akhLC{ZAEM&P0m6tI^-)!fQ`b1&mP zJ{Hn@7S7x@pWEi*e}m=PT;sT2CS*jPAj#C8X$aN-#97N<%}-hv9&*InHvA0AlTHeOZ8JG4h+ z>iSu5X9rx2ICED0*~QF6G33VU*YvI+E)lr9H2TGIxl%x1pBmvNP&OE**oc<18dA^XRu+X(}%UgYPBCU zNsw8!_Q#no*8yk`34c6~!a=$J`of)Oz9NBG`%YyXgyHl)@iZY^`)NaIorxsNaT&3N zRsr=5@$ycp8hl;)jH&zHM8+-Q@DA>W@~c~6Jzi_O&&mrGC>*3Vy08hG6&o2XwtaH1 z**6g;@EUd8NDEROx)y|VsX?`mvEl^1+2l=;32zQUCVLzW+reKB!X=oMqVP93xVI_s zFys20gAf1*0owBi2cfjZhoS&IJ1fc_)o&b`OxENPBN{!HNh=Wj2C7GeBAt{6Ey!B- z4kMwC1GQB@jBnA_zou=?Yj1jgw(=p((b0HL27RW@A0t`DpbJQ<{}m274V5 zMLn5@4U7G5-K6C|a>~#5;~M^ggA>2R=M4^$OTeGWzQIA+zrexx-G9NsD3*seI2hjS ztn~&5LEqqD?6d9%yMMvKp^)F<;K~~ubf^Wu!Rebf@u{5NKsDQ_ixuw=+}6CDmw&q{ zG)ve35TCK(XzTh$e7ZwDSE|mWW1nJx_{^5Rf)8x?{6(cOW|jcyp{`V-en7-v8wu1iZZcyD5YvnO?2&WCLoaKdwCWtC%%zpSk;%RfKmj;NgaXnYzqqwnP7N z50bsP2dRT%?X1fNZsuRgm(w0oIX>UGX){kh7ln*m<=Y|J9kGH8-R(nDM$ex^aThUd`$^kB<}!Uc`y`J zz?GCU2}F=SO~E6ETpnNUFMA&@lHHLdz79fSiaujPfvyAt4E&Fw5?W-m!`b zTR`HZYVK4m0JW87q?2V)glXZc5E1B3gI=igW_U|6dcML)zaIF)1 zB$_`;Mt#?>P#fIQWX|hxe!kj>NmsQT5VlPYjZ1v2mp-9ZUJ^#`uZCiZq!{9aR>V_&{>}TvL ze>=_c;ujWA(XCtMRpE^Uxr2jqk`7!OuuVVQ%VBShcPqOcez^A^;BP$mMf*5l@_6$( zsYW^Bm>Kt_$8{$;^d@$sl2{4u(j#@^n>I*C;@wAxLsvi4Y9Tio)b5a09`pp=_1lR3_cYfl@Uel@z@ z<@h{BH45sE`d;0MW>=s4Ypcb_%yZ93N3Qv_$vV^3N|UMFURgP-bt=N4_XA5`vRNNS z25xw^OJzRc`eS|a&?Iv;Ptc~1_bd@|h$p+_MU8mfnJDDqKV$hhsl5O+f%4nTI{F&Hj!lt zd0z$%cXOtRtOFGZ;{mqG88}Xj_oekMecVuCuBG}U4TEz!F_EG=+7S5MxFN6~d!Bt& zAy(c}^a(NtxE~Mr*%R&@dMr7|A+NobJgQ1}-pj}QLMl9pd)7#N;SaCwx2I>-PxjD% zf(HMpPycWhWZd8D@%(71KefI}whRyXWM6JeB2%;GmPr7xH~-2U4`NbC{FH_uT>xZ` zO}85c2crS@=Dse9zb-F+Lxa~FF0$J7wyhaY8Gr^t_w1*RJKS~j_g9N$kU4t5ezwCP zR6syxlQ4ac>1QS?#c8&68;ZTx7*wIys?PcJLY*p84pIxq`8bhm-Ls`O*1Q|JiC=D{ z&H*O3`S0#c(wL8XagJVQui3`6fqhQ=sAg`zw$-}1rxCdXDP-DeR4nBzK zWe1?}+8HW74$`-qtF5(5!vj;D1m;U{j0;=u%*mN!Mtx@_iI0~E5ntlW`V34DOAJcO zi7DNU1oQSKM{S+GzQ)(?>85!!>F*jn6kKeC;GXeK;-s@+rzQd1ks+xs0I9+&LRgoI z&}b|NGM+JspDPI24H(HLqQ4G>ru<>#5F7~h60nJEo>%ig-F?!ZDit8*BW4qv#cbJW z+S|R&ki4&~6a*|Vyv}oYH*29Q^Rj1PFs#@uAEm<~Obw2NuRz&bvkdXk^faAn5s<=0 zYtq}dj9^sBk_{_UXZeg))Kc#X-WC|&?`z9_G_VED<3QjPDc;}6{#s!CIIJM1UA)2A z*5Kp&`U9@nB-e#^M^-|uPQEkA36e?WGKTBe`o?~` zy#m4IlpW3b?H3!=1qrfNtkS#mB?R|uBiJ_1aPLY|#V6m(5X>rZWV0Hf&a5hO6uoMR zejXdH2tPT`d${m_$o*hjlwuRRR+r{Tr1b*{I4@Hv^+=ju##x(>6#ewf{%?(9@yvynRQ`&H^~;;xPi(cPRQ z)3*AK^ThGg65>jyg0)JtE;@0*b+e7Z?HJ;yS}A6;1M1A3tAzXpHwR32wjll+fP0EWO&fJ!WXjCy4 zi-k&i#vf2w(U>;PZtfW*xnI&o+t8y=XvFSKu z3d^uQJ%~cGdLEXGCh@UQtrfrce*f@?{l(j;=vL!i@lVj;pGE5LXU4yx!FOFv`RJ7JY?<}F0DADf;0I%n!_(x9 zF}{FC@SdGr--jP-^c=1H9G)QmJte>C^DV}mHu^s>4s!fQXmE)4EnHj#9qAFjZqAKc zVK=8B9S=Z*dfz44UYnjZ4EqGT^4<<`wmy_B)O?#BCwSP529vy4*h>M$!jXxHCnV~Y zL_%sVB`6=AxAyr;0O~3W*15O~xDl`q=&#AR^Ri3py$+iL5-5iT@=k#y1@gPP56Dd; zKg-x->ziN6D$5HR(QN6?duY)ytV(9#onseWdb|`{cG6PY@H$MQv;C6#BEqDs{+z5I z#nuo_I-t!AZVhFd4wUmlj{p>#y_`}7$;-qpMoB8T;n3vhi-g&+;70PS+Q=L0VJ?Z-+|!K zOCo2M0DsRjs!u#a__23#R(CoDenzKQ|8^VKN;Q@TT z;28qao`cBCjOc4E;k!3L2d+rM)2L}1AC=G$K&uwahhEf?odT;#@u|Jf_ael8Hn*sP zKVGayZDnw15+$sn!5Zr9T8g$>3=f)g-;LJVjyQyAjq0U1XzeiuHD#JP7C#JNO||$DX;Z9#>D9D_QY4W_6$p0E1;1G_?bH zUoHwH;9W+ZC6>4n*x~pe2p_2WzL<>GzQ4*z)EaRNu(cgFOC8g5GionE4L>)>Pm|~4 zRcd4VF!D)LgL~s%s+X_WMU40sydG~L-%^ST=fz)ZD1}`psWjq2X1FGWoqoR=$z z-LadPs&%iH1+O55;UFin{b=aI4;oF$Y#hC%nLHb&6%PDTk5uP~5}SD2^t^uDr}t)b z+(asxr6@NH-1v1xFH9nhqa5&fWaW!LQL7(k*K2 z?_f&48?wQ0^wkA9@2p~7G+X76+Hy@eCzWUP7#gwQSjFl45}e3fW3mBVC5g5oTQac3 z-ek$yXZkmM2v^?B910yzSq|m(xbJxijjLR3e)@QSr)2^|tEW@kN&9r1lc>$Wm$4A< zDVC3|xD5lhbzdg5QTi}A=Z6;fF(OKMYGi>x5%T-N!yis?z6lORz5>cyCH22!g1-yS zKb!*z_R|XX*OhY>K2GBRJS=FHTwxZ-AKGq(?MO49HUVu0zd4lwMTKMH?MdKCE-!-! zz9jNt{QYl=L;XJ}4*xLSuiGR~ZGch($YO~PRqEG3UU@(Q7<&RxfEN50gOa^i>SD_& zhMW0;u#%U&v@(YBjx)s6a#ERSXBmZ}j<#5)2J_=|`qjyPTGknY@JHzISCCPKps4Dd z6vrYzQo(Q}Ahxywsy_5 zf{j|t>k>CD1*)iq21HaoL$|U*Ns%U&00UCR!yU&Mg`W22Qet$`UHaUxw-S1{AIMLc zH#UUU{P2H#^OV4}6EdVRXT#zkjGM<3_m=peIfeB>C>s)99~8m;K(1RC{_P7e2WCXs zW<;H3CoS)PxDILa<#OGSfaVwnFhSjft#`rt3aj+UyTm8AlN}sW*R4>g`u5XLO@1gL z7I#=e-2Hi)a@9Npem>+#B*GmJ&n}`De0E%D^6|_}o-`5Kct+$fLw21 z;q@^Z)P1IJ9y<tEubUy5B8<+kvl5({NYUK&Utl z$3WnxYz%0dT_L>Au_L*#5Qn5&7vJ(AUITv0ZJ zt6^BgQh70Pb|EQoeGQ7{_R443Dok&Dg?shMx6ZvOFQ08R@x^;Xg5ld-m-8j4!jeBr z1g-UwO4C^hIC1R6HgN);84ml(5m*7T^ViG2FeP8Q{|OEJB|CpV+5K1LSLB(Pjl0?cSmEcD)AdzWUsV;HN=f4ytF)%Xr6;t_47+)v@=bV6~8T;OZ>!?SA9Xahd*AS5Nzw^~BRdw=s8=l#4EHQ~lZTZ*kmB~~}y z;*P!W$&b|BwupH4Eq(fZOS(Ez`$PDd))ty>?0HpMV85bssSh@0_;?(KG4X`;- zphmwJytNXR`*!V%zz4sSo5B)ru1<$oje#c5IY%~bAzNvEWX9dq(BE5IH$^sU?&zbV=+uYk^wG#KZ~C%x1PrcW1{T|GJuPX0%3`c zpY#_y*cN={JHQ#G}sw-Vcr#B&Ja7?&NxPaQ325>dm~&OL$HY zxrQMR5?oFHVMv9Nd5f?j43hZ615hxJvVd5cAUhFpg^v>~*$?{9b&S|k@YQ8|RYe%z z1mp$$&4*k&ri)8-A((S31@{3s(4(J}ypG-#V|HsHatxXVY~q$}6@_2rayYzAmuKy( z>bcQA*7oWwWD%sSEvt=}vX9035btM9RywX`DcwqAM)c`^>WY4=gGZjbEYyT95oXNS z?Hau#F~Se_vs%e!q}bAn*E&wzyWEW;;LwJG3G>1%Y|u@Qe%%?9PG(ujXwQ!1Nom_sY{*_&C=3GNyZU=|Gc%`Axf`448nT;mhbsWcTl z64UHYSt-w|>zc|-dSmFrMJn`n;eAcmyFPC=oK$?OlAAhv=HV||(t#9ems`MX>1wr+ zCkRTemM{u4(OLT%g;olxhs(R1Gm1;ICTm?Kk;u(S#KC6SYGX?KiCN>`$VqKu@mi#C zBne|XN$I$^2d31$V_|2N0$zg0w$Qx~?`o&BP;8dkoY`EwBuqNdYR&SaQd7JoytZ{K z)(YFlXb6zcR4!u8wMKg!^qrZrAkNvTo}?>yb1f&h@TBr&qVTd6+BHPpzuKM9*#upv zz+br!E8&1}!t#RL6bRYQ3^uF2cU1`5fsi?CrZj&Y&z5x7;h+Hk!7yV{vA~lgmdQ@? zcy3aWk#C-%XXK#!syv3;6gZG@&;xbmk^3lkNQh}*#6x~QDEU4CTSzr38(m{P8(D1d zm#iw-Woy+GT*y?Av+us~1wJMQ&1-8JoF^|Q&Dl^tkN))7&n8bX2{7?F|FWRKf5~@j z=4{!AhGy-@WuARuKEaxarm4s6THUQa&JaK~S7k=17e`9~|x+YFc( zfk!V6kg0!{DE_NV{o7&iO{Vw&GBqZCK7jqBp|x3RS%!*YwceS8Y^tF2+0R*`vi7~tp4J`Rv~-rl0r3%UCZIaNp*l#wp*s2qwpBYi%2s8k_}wC!N^T|5 z*~{VMcBDrc_hT6ws|?%ebf^ZYnOT<>CE`?U^o^(kOPQ`2yHI@(Go{)nFDwavI&>hk zw0fu<*J(iI!FD|W3Q|cCzOoVnpkVqDRDJbpSWS@+S(H9+R?;>3suGk9&sk982YyZZ_h^UHHVxoa;IfBrw`-cPuKd zqkuK4aVusP$&mexsSLfQ5b0|{QTG#)i!-&${MQdj_0crZbNzh?MSWU2`x_<`5Gd_J$AKq3JWn3wxX|$BFU2c~!VGKZ266oiOb;U&> zFU}Rrp|wQlb6o7|ZH%z)n6`#zc}4T~q>rGLEoU7D@n{+AagDLVUi0FRNuUjx=?EYP z%(zl>T;IxAuH~Js!AZ3G<-2gQ31u)KQ!L|o>;-5aoME&QG8p4H9iavh2*6t?^ zXdhfX(kN>5N|-?TwCofkJh+{MpFD(z&Al+PgFha#S}^2|5O}f?$Xt3WB@Pa~WBZ9l zswt*D5BlMb)S)rNqV_;{>uD&bIW@#CoYYo;zE-Yz^g=t26+{@tjst7b2Kb1b1pj@y z^Ov6>kEa&40wraDNbxOcGH>oz;z*z)l_s-Nb3p&#t!}l6=u*vc4~=!*vwN7vR66?Y zh8x-)$;M2UYJP%_N)B0x;4Np>qfn2#_!TwA<8Z_wkJ9-|NHa_GvWAkK@2gVykp&Nj z*B{Fd-q4^7YtPm{$rb-us{Vd}{A;fG9Z}!^UvtIrYmYzP;(c#-O>qCOShb#`k%6^= zgP!rfy=bDNto4Cd4Kqu7!hFlPPSA)ub-bdXU~+oaxit*UfjTl=XBxd>K3S&XCYMke zdF;#AQS)o{G6pNX%dZGf330`SQZRg|Y`QVZNun-=CjlR}ER&qS;Pgtu1fKdTP98B_ zWxr-zJ#YMMbmUp@ZZIz@!NCq=l6jYqlvhG_A2aQ;qBDDkwG?&cF0=eI?UU{9%?9ky z-d%l`d%Ri7=~tJjhK@&gz1B`$v=vqUq_HoC1$b!TC-Qvhu3uC>#U0fuB*2R)J%aO8 zp_@;3qEkToNH}X#O?UrDc+t9OWeFKL%&@dM%Fbdf41Utk!aci!ST5d!78MoBo8xIP!QPXU`!NAJ_703QyjcJOI*@VVRJnF|$gk?SJgw~^EC{lvTiqih)|Nr*{gwS$z( zkUcz=Lt246{=v^LwBp$b7xz9JY>`7s->jyeY;F}siDHZBv+>b&J-oSPAcnLDaVbnT zVLFib%hZ4=PjO=NV6a+oFZW_+{~H#~waAZqz7zJXQn${1 zK2kd_fRtq(h@_Ng4}Eac4dSVRw{7|PKsRAj3B{Q}b!QO?nz-Py-QuTsEH6ihVslg+ zJKD-?8jseovs8%%>E(@|>$O0R%7(YlqdG~PaVf2IBO3`O9|hsJnm*@)ev;9dsEX%x zRb9LW;>9ZvXZb(GomEua3A*i(5C|IFA-KB-cX#*T?(XiE0Kwhe-Q8V-yIXLFTcoFF zy64Q9K6CH7>#X%JRz2`i_3*2`_h;?2ZoWIT9asvI2AvlJ>n`S^5^fcegVE$(Cuhl0l94H z;jp1wMUT=`qpTRxwR~V zc@Vqf?L=;u6#I^V16QN<|qtVJUu&f=4P+@9iSS`C6DiIbMd>3liwF_x*?`IHcuv@jzO~Vgk zyBs_%<0sh$l1uLDX5`S?0U!7{0F*s>KX*O;n&`amb?2zbd*lWzt^jd^W_!EOH2sRuBMReK{Ab*|GDaAOGHUzLRy}!YhfxO*sK!;PbgzF}XwYdk5lapL z&)Y$he-EC2FA6mkGy&j2N_$$J>`9z_A913eq-r6WnOk_|h)l6v&PeSzST|AIX0BTb z2c{Ek`~o=~9-<|VY+w-kW3;Nw!B52`vx1Wa zOw%dh{DC4g#DLROgx$snmhUM(~$X`Nqe3C2lw&1m~`(;g%GCFc7k z#R)HV!es6l*IkJ;owDvJLG{N&cK4GPS4DI6X94E=&~J_kl(zhrjV|+Q$b^Ml6oLmC zOa^J)m##kVA2HblJ823d?F1LOI0|2-p144NlEx@gNj}Rn|iW4E+&f^4WH*rW<YmHayRnZcQIn zF1dvip$l5p`#nw2s(yhp)lt&uX%v?OhBk=Eu)bq?Gl4&(aYy$x^T!GpTksY_B6S7rrqutQa=RDTBzi z&XqY&19c~;WS1A6MuP>aWvcp;Ptprfax#mya z>`kj+!S1>0nu&MOYid=BNIKG$J~ql5$~cJ`_t|(C*;xn|&Doydt>@E^Knly)%VSyz zZ+gx_by;lS*^_mUdgExIWXM4;Ml8dK$*fFzBOS>Wop@;&RRPU5a7iG=9}(vXBd2(E zGq&%_O91T@4Xl=ZnL4cf#D3oKy1vrnJ9mo}SnzR#Zu@1@EYIE=;;{3@+^22%=Dg2w zPi=x#`LN}zd4h4Kv1x+oF-?(eo@wa=`F1F~%O4Laz3Dy|x@(&lz@*4Wz&;s_e7YAlpe+U23BNrkfm+)|eVoYLOT#~m6 zgZLe@NKAZjQ(QdMKaCb&93zr}05Hn~z%0&x{g{8>tNqss&q6_6Vo3>&3ojlq+SIAb@_nzBt3 zJq!^Jb5p*Lp&yIL=@cOp2gu?hBH{`(YJyCb*vk4OtB=o~xL$9)_Nrg?9s`aMjDXjx z-UHdCfEfUJ>)rX%?Qv@J&g*BGt=uw+4x6-A4rMkkQL9nM-k&8uW80U`8q_c)nqo?6 z(hsKCJ%CQi^#(|H^7&ZeN=CUFiK!qkE&xqzPNqD8B-y@ z-F^zuVN3j0+Mg68x2rGAFv`jsMLnAD{UTqPxyZVyV9+A8)pR)^Nx^bS0ahop*U+ zanO}ukCkDMo#MnT8i+c+-Kle&7l%Hc$N3hmNET-eQM9S^jr2@M`77k000Y)1ec!{Z z`U=2>D3f|)z9nJBQuSI?5ZYrR-|aZ7bu}i_OV#Qz9@j0jN(Dvc;lhi0>al%)Wg)A^ z?^o4ux0hxdkP@nrEv>{mUXR6liYIf8Ia6jNT)dozpe;)_44(OV5Gka>^9iO_^M5zeddc~yEs$8WDp)3KL5FdHAvNIZGX z5+p5VPWGuR5(_rxw$=17p_Im-w#IlS=_uLWEF^e%>nVkfct<6g+Kr$@z4oOlC|u$) zLq}5JV$+pJVdRQLe^Ax&%>9G-Ez7eU{pIaND36Z>fz9^&0sD&{y3>?qVm&Rcdzc7l2lQ#QPD zO)0#Ukm#$avL(Tg&k3WLRV8Rkz+@)HPu3Ii%i=WCR~NiGb`V^F3$7_m79tSHT?(%e zq-2%1^5)&j5Y8IyguW$G)2Av)J_BYVM)IHVkBa_(z8#(qgp-Q zW;Y(eC}*WvORbk|Sv$0AYICj^jOg_0Z~t>+N!2aj8 zfHMR^z1hZm>47@vp8V+cu>Xb@r@y0R1@9MHlAcrl2`#%GzoX?8O+3oQNc<0I(f);& zzF%mW2cX4HKnbGrTiCK5Z};p2tbP&+=Jjj6Ex>R54#@i;`?lm zseI0d|E3RlzokH%lwOJzNtaBBoE-L+KBi-JW-4Q$6!)_|~!qV=p zHmeh%yl8t~e8ZN$B^szoiIaZAhNBZs2bQi^v65*$VjhTIcc5O1+BWV<7+`=_>hp~| z$W^}(HCqyLR^&N*>U;8(H@whdi@eKt?0Q{F>vip|lF=!6O`qI2sByJEb=6Ec(PgB> zcaQ<|kgLuDaoY%zE7YTY8_`ux#OkdgE8jfo(d}1d&YVI`42#Ho3%MHMLuqjhy-C-D zG4+FfbVDYi^sohRHpAKh=!b*@$9|3TJF8_;L8e#U?g{^k4T{}s*=(f3Z&#OPxQJ;k zCq6K2xM#X?b~o1vTek_=;8CnKWc1xv))V-_DeccA`*L4ZM--0FntP%>;#D4Fu&S5S zmW6(t*x^`^2Xce#2l&oa87FhYV6fK%)#hbAu z60v2~@rJ}=MWicc$~Di{L3P6&Pqvk`0qVZVt!G>0=R2q14BZk>LRl7?l>YH44bS$A zN)n2O{EIs<<=5zP%*m#FcT2%AwzT+^`=?-MUk0oTehcu4B0eQY{hHhie68(Cl&}wh z*Ffa1g_>BGGdoqq49(zh4RUU3CLV;V zqYy~8OeVAheMofjUvGuxF5{#E1K^VtfKTlIPMFdE50bZkNzYnrSTzv~bWuH(Xft+$ zvYaC{ORpr>ztdAv*K*##dg;D9;#ovR`R(LK$1i$X%Rzoe5EzQk26W}gaQ}$vbR46) z>wW8yY25>?^W%uWwRU&EK?fWY=0pbSLxTeJN(=vl0zW!+g-SxfURiI+7fX;bxn^P> zjX&`{&2=#c>fVoHk$ z@jAETDDFQ;r36xRwq%u^sK(|`DsO!J04*L8uFo}>K#%Ci8pIIS8Sfft;ExGtPf7+MkPqfn1oeXl2H zc#RA3McIc{lh1B@ZsVzu%QVITxmpjCt_v!-{XA&^x{3d62Y06CJPKTQi#Y5RX)So}_HjyAZ0@f(X{pYzO@oz)FM;A+x(qK3 z_Cu(qq!s;)PJ0fr2bG4N2uIs1F?*VKNx5L3R!hB|VAR<|+@++wIN4P4I2@%lXiOBw ze3IXh8wtZxI$%r|X88pq0;SqmaE=qGF9;BCROzHJ86F4PG|$=II5})tFMpS7Cbo@G zec{8?Qr}JuaNqLSv}UyqUlNwFp5Vl?O4*@V$2BQ+mwBG~zLSdR(y!9uNWI2d;wa^u zT7_Y!QO;Ij2msL~wL7~;8~Np5oP2Wt-pck)u5 zeyV-kgWk5BEQmIB9~iuUB`t2(xP4jPyw6#RX5Y9w%=D%FJdA_qRjA+etmkWy9-rmqD11-zw_v-iC62 z_6s2rAf&|d<_3#2o|{osGtI!==vAcJL3ze%o_dVAjlDJCQJ-zx1uP?uf$$XnGJVKE z-u!odeh&2>f|_AImewnigj6I~eHcNfVUClwZCzgd$7dOsB~sa?y)zT`EenKp4)SMV zaTwILSSVrkkH&^G?3#Vi8NKhlQKELY+wa(t7&hTpaYb4Ldwm68fUIh&x<4IR=$C2RY>eO7$ma_*5%su`cj9^>qW)VBy2lX@soU&K{@ zw*KG%T*M7gZuDgaO7v&Y20F~6;DzI00SoA0F|`l_EtWq3F!DG;^c6t?fOpe=kY?c3 zfagzqK>+ZjTy(GqNu2ea;(4%0tWzb0NPs~W`iGD7ybjZtKRUR2YA_iyPcn<35PFm?IXw=1M@{PvQ0l=jJsjN-4M9pVmk@n_MZW0i>C=bbDWRhr&$%($Vxw zeVb~LNqt|j#r>V)WB7Pwg2AqM5Q#@*5E^)5);QfqTT(2BR0BEYXQHF~bX#0;c=WzQ zovX71Zd+_PENvxRRb(XDTu)F{oX_Jwy|okT%~9w;5a#f4XW7O z?h*+@RP~71Di?z>?s~#^1cr4zV*bd)sg3+)SwV*v-sy>ki%GMwYr1Tt()g=(_Vd$f zwQ;mMO>1PPvY5_;Xb-w==Ol-bt&Edf`G)$XZ3t|YSi`=GnC(0t z_MfJ#Cy}!DBh=aj^y!oW*8I!WBy4&1CQ?C%3A1){anBe6m6GZkhznstl5Ys&SX3l@ zQGv>cj$iDflh!P2_*~n1>o;t0g(Wj?o1;BHRB)V|_T47535(@hwNk|RB6{|K#P17c^vhZgv;UT z26L^}04>gczTNSpbpaa$5N1Pw7v{ecFaOKh>{oo|mm7}MVNT2ND?fu<_b*T+6`X?5 z$v3{RRh+-D1^%bRtX}W1?fqW~Glu^cVfJ@;#x_Qm=`}o?Y^HGkw(WF)DP;AJ@HDd< z@!@7pLi@I!gG4U)OPH0EW_p@)zh7djUq}5l#g=yKl76YN+IqPeai@xutiA< z3WU`~b6nndLb0C&ZJ&A+No>NF$)dz&uU!`!cWLm#Zs>)nY2<)mA(__{xD`R1Se*F8 zQ=?$>ZL2~iLtS`^V6_k-?wuqvP>nM)$!qWUWC?t~b_I~adgG}|=Rh6Ie%tOTF&!ll zL)Ep+<(HupbF;iejEP+FOERt7#2+#iSY@(+#EgJ5%U&~X700I%1??z~>uecS`3V3{ zprZJoZ;Z#fcpq@k=Zt?)L{H*npE45iYli3PutK=mcyq(WzT3EF40qL`fyF^rx;0Y1 zHLAZAx2Ps;=3iaaZayJ;?`Q@m@<(u15d0aOIKP22t7xw9Z{WNbWU;2gsJ$;yHTu+Q z1Fc>}p1h-Q4-jStzb9tkx0je4P!g&ZEw#)$UI1ZMq-54I6&I#mEB%NCg>G2p?A*2I z99)@Bc8BGG7t}>3k8U`T*RId`Du07WhTpA175>6GK_;$=W+B(0bch~TwjApkLA$t# zJ>J|87Qb^|A9OsJ8GcNv?n90&x4ZS61dB!Z^Y(&c9)=Eb&OdBuMuspB-7ILBer8)D^_P)2|M`HdwRrtkq4U_ zM!&$R)7_D9aSpuq0H_1ai9M{PI^Uv~8X+x>H5)Plz*(5(fw%1(XEU;qF;EgZ@`)3z z1_FN%E)^pUj@~XYG*xm>wd#PwOnZP%ntu?+zqD<8(ysTX5fETet{931;5KtWodZuP zDL|Q(>HMb5=$65E!CMZ5dl~zZ7+Ori=a-~j^Gb2W8syb(oy)i=QYZ+E_TDMuX?w-9 zVnO0;+H zuST(f)+Ki3J>hTcyUR8z43K4LjBCiU7*N{v@Qu6@ zbQWD&#l#i10+HTHiyd`h=(z9gpPTd{OGXbkVx;{E)VX8a5 z>=5`5QbQSX0y)cfwL|7G*Lsh1KgJrt0HYDNTzj0q+rB5h8!|vq9f#g@KePwh*I`a_94K$$%`zX65?qC8*cO_??8 zL!n2^%I0YOLXq-L$M)6CJxd1{ie*SeoF8T1V>>hy~;zX0R+J7Adq2AGr9 zH^A)u$AB3(sUi9uFtPs?FlYPc#&3Wb{1b1_t*mK* zR=oR{%Ipm=|I5k@>#eW}P-e*gfijzoL<9OuWybg)DKnOT6dZoHwLkd*`D_nneG3p$gG8L z7u^ha-2(<_mlRYC2&jKT{7QM{a@#@jeNmr-He!9sBqjw`Q@NVpa4y1`M|FKfQRU}| zI%0Xr?gOEi5hY1?QZ@1)6DIiS`D((^1W)?#qQ1nKKx&N1Td!Gr`hCHhH0VG>6B>5p zR{D$Y?bj;cHX-6R$rfBoTxfM7>zU;3k@u&F8sC*aYM2)=!YUWiuSa~tk!>Opw~G4s z4F!LS%45=nl=|_2{1`}|M%X`E0F{6JOJ9W)d@DW_f^$LG1|j?vVk;?6y0F+& zPbne%Zip7r2$~X{kusc-6P)-7J!`Y@DyK&Cupa1Rt?(N;JF&uxoJD$u+bd1^3%&U#t)Q;MfbiEhV@m}Kq};&QQNGm(OY7N zE^z{F)86M}-sdNjQ4mczY>QGU=d}mR%B)!os(OQLmScIGe!kE&3M|}PRvd!k{7W2R z?T*ZfEB#QMnuBsRn&;?y1wbh^Ckdh*V?Q>R+Mk(Bh3XnweEv+NRS18%E8p(4X1yw< z{Snlwp6Zc8LuUY$t3j3#744!t%SD|yjLVogpgANsroiHS+;pYAe|gR9q+naPy-@RV z={24sYXBS4GMv~#E=T@QRP1=ixAuH>VS5^>HKkVidg)QcwUOu6W&hk;ugKaxg0rw- zjN23qO`eNwQv;VyY{OLaH6QVWtF#nXu+FXwJ>sautLlq31nZn!BpVXaKGQdxocGTt zy!x#^cHNhruGETk^#>e&EU8AvP^u5ApW48_&7xv0%RqZQu8V_}>93Nk=7+=Pk4pbSboBxYvPok%igkCsXZ(<*7>&X-DVpC=Ud!|EvwF7!4Gj4GTqQEJRyU-u$I9`wcGt56Voa zo^aj~^1tTsS@lQsfNJJOpC@4n#S2=p9_$lfkzMdRl3W=wd^yXfBzizKGvhbg2UukH zc3J0FHS+=|QhI=6hZ2a<42TwRY#IcJ)tCE+wnKmNJQMmp#=NFvm#vspiS>S)IWiTh zn7h+x8*@|NA>(3_1QQGirX;;G)4h*z;d&Q|4wrO&WR4JryddR=By%9+b7QHeu=Fi- zg2?tSz@*)JqaiKdEHEcLMpwkYsEFkl9DUpE%we0HlVDKH5Rc!C!C5iV<{n z_4I>4j75K6s&@^?XA%YN1mOH)VfzfYHHEOf4`Dhm$drYn>Qt%AavJozS1OEsE<=D|-1#4D$d&gN);mX%gVOT;Su`DKvd z!USC4*g+ITh?8`<@embQT0>y4cqE!d5f{0NOjCJR6OE{_^P= zVExF4l6UkElFuX${85FZ3%_60fZtwW0-7a69ZG6HAG~Gqp-N^Y%W)B!)zWU*P$q_D z*7jXTZ`N8JI#HY2t^2bc7Sy#4kY`xs6d zvZ-D_Xle7@pOWl6W=I8#h@R7>S{}peJOS3P5ywO$A5Iv=4h z^qMTRQ_xG$)vIb<482j4RmQ#}3!~SGIhfuR(NZ@K^>}#G%kv?&&hO*1D+I7XApLLM z5|2kgn+^?C!kLj3I>I;>_31h*4u!$sYW?)mn&fOPY>i&Q<3sn+Gv*ionORuDe&$>ltDt5` z;(#heztKsGtUfW6#2aA5t%+?#(;?iNbmjr4J|GK>7#C3{*}}%@zSVL|Fq{A~vt9}t z{tG@2IrS(ezPr`Qt;uyZyMt*j-6%|4ZK`w?OXquPEvQX^_4|i18$zQ|Yz0`q)t`}6 zZe91YE*g3NN|~v4*CG6+GJ6Be|FSYe_)VEf{3n^2Ivl(5Uluc2|3}J9Tmn-V4QHz# zZE1wMFgKxM^*AmkOAencr^wn|Vd-chV`{*}HKVmBFP5JW-y8w6z#nC)!eq0Xc!#GL z$DApGHCG`QAxNo`jt@mpRv`-l52>^}o0q5)67Jf2X3U&W>(KNj*=z6h#j0(V8zcRz zN1r<2j`*9c^#Qbkz&~}pB(bmlvbAhyrqOXRu6oGD%`4<;WAXQ=NgfvVskN)dX7sc7 z(i*gb?xWizS-GK6Dc%7fE1#or&LzHA5E@qjXY^LH-P3qR8bz?aB!Omtj5}DNhHC(9 zE#`|BLboo!)iTEfPdNf;s|&iGiI2D ztD3h@{A!nQbib6}d?vmt$LQ}u6_cCC4hv)r_{kHVr6P;97) z*L<_I*@#*<@O_?n>jsZ}C0z`E&&=#@?EaRSG5o8{41K)04=jIYq!gC}keRh-7(}`v z^OzCYean6!Ph>GDLgF!$ufgm)%xosQ6F7RH+IY|!-i*fe%X1tB+^Tr9w8k~ezgyb# z2*INO_WUVnh7q~nGPA^7KxSq@%y(>mz7O@%koEa>h8qA*$ALyJ!`Q6a=$9zhH*o3z zz{!praj9TkWULKQNke~(1sf_Ms{j6=GehvBi}wE2Pxr5h!wScM%^Tk&_t+l!B3)3# zEI*lFe+Mlk3v377ul0?qHtx1TV5}TZN;Jn-J$IH56?x`z|xcUm9oqw_-!c_@XMH*npDgSe&U_`~`2*}I;mKOV0BM1x`1Pqx4=p4irK$#i&?OpZKIBr&> z8op&__fA|Lzlsgbg8Aq(oBUE^URwp{x}*K|Mi%V69%3$M(%jS(g)9@ve{{5O!ps3o zisr*#6*GTh%U=mIO+cF&7B}5L+RW;2=Nws$@oM!Fh^q)$9NvT(&axJuQG&lyS2wu; zw2^pnsn(_8#NApC?!!?ioSxl?FWg(3nYCOWB_NNNd{zN$7=Gx)@jppX|CxPkdv^9T ze*gN?e%bs4*H5CKet`n8X@Ec;>n)J)#KkIT+@jh~g0WA%ECU4cxhzVRO-mM8JA8>} zWef9C^QuP?b%ye(ulg~fyJmS@2vmyh+i#r`b-y|#{E2w0VSuP`MhD+ICCqxxCvZn#%9oM4`n8!_7IT=wsI*3N$7#z6|GKCmwRlq+=r29|?*?Z!_SBh7U)ic*(L}s{zytcs!T^0{ zkA5bpKZo|o0Ox9NHq$&Kgnh`0BkE`K+|S%EONvG@%4>Eul}{M79O=48P@|+=7lhHk z6MW-O;3^@SVxxvtSwX_f8U*ahp^lC&m)C!#hnr!6{8M=&%jquNs zKBmM~*SB3Rn~p#GDzP3K{EEyXABz7Tnc<)n2c6EX>y;kO`yZ)Og^9PpC4FXuduiXs zleCyN_Mo(g(bbf*QrpA~o6BR*|63-{@a1eT5s=BB84&XyOPuf9{o>0HZq_pQi$FV% z5mG@jqUW<~=UY{aZZtq-Mvk#}ux>xuhNhct^uq-UDKUBgdXk?v?9)ZtMB=xAPYmgW zKbGu$2$HF-Z+fvV8Dp0PejJK}t0_Z!flp9?mFiFCZ6O((uK~@3`o>l5V-Qd5tD=;W zz7;bkbRImd0N49Ni1*L%icA|4Uu=#+UzPT?YS~E~ETU zbXha(@tPulojHI;5Q0C}X^qUSbal+N^{g!I?0+BfwEiCqdA@B8M)Q)UY0D3B%6}hm zY%7k!B4_=vMDx2;uu#29O3uoU6zwFH^KPC7fzfu}#-1P5iW|pm16-O3vB$$A{qH@| z5(;7@guc~5qvMCnHq?!MwyEmuyV1b<%z5g0+j4g4_UrHR(yoX_f&&E1M+lQ_Vg>(? zMgHKzl+&f?Rn`6$#%;nq_T^>;YH2C^hz{6-7PmDP&*pw@A@uffOf~at!}`?*2TcXV zOpk}w#N9VUvHl(|xP-F#z%}co-{BXAqI3O2og&Y18?+>4_ai@K+O9LU#AQl6>unqD zE}(Txt7yzAJFcY7^gT4IjQIwN^fHe{>*=nH-yjKl)AK2Yd?ke$o>KpSwcqKJaaCyD zNBw$;!5N%T0rQB&q2Ey=>$I;?V|_Rav+tzz#zhCg$YO?MD?gngDgq99+cRjX&R#VtRD}ja zMe=~W@@GU;ke?tyneyRr(sXe(lNZ2Rob2LcO+XV<70Q}*kIU2|YhLIdV4hLOz-kw! z@!%D7#IM^~3(gs*J5-%??IqXBden4%EG&?ILfWgF>iZsi9+$W@WaFI(fyU(GtNqiO z0_X7al8xlr`KMWmdwr}5-B(;aUrHEY48n3n$WalNzFgXXXU?0(UJAQNL(QWVnqw!U z)LE-`>q&4`S9Zbi>MI|f@ufs=`07-JWjUU&fg0IKPHNE~tA3=2R9ABv+^!ga_S9e1 zg)G=jHa{+=ge)w~;|z_oK_Mlqsk*WhqRssHil3Ou)@rBr%0Efc_g%@8bF6g76h-Ym zs4@J(({zSp4`>6hwFGBRufu>5eQ78l@EpZ*{42U zRdYJK(1>wGCz!?kmD%VR7<5W=h??uPWKR=yh>Z+naOfX2;gKpfB46DtfBX>BzyJJ6 zjEmP7r4{-eq$_e@?^&203$z~Yha@eR5rc`VF(k<`^A6qVzMWv3l~JS7zEb;pYK6IO z?jiJfPURE%3o<g1~-0TX9_u1ebYs)&F@27ME5pLsoHcxUgknz0>J-BB91W&803 z)r2(|P-)`ulUtJWQ~w9LI%p5Z1)(2|NV9 z_uf1S#NrB>RJ(7IUUeA+LyNUsY+W;}Wx?aJd`FVrAp>ysn?*aQ=6DU74`=$kzDQ)# zk=#5d*<){fd;0AeA58~mvB!F}JyjYyI$q8|1wrof`z!AdRJd95$)rM0(}*AGHN z6S8t^N=KC6Mw!Bt1vG0Hl*8iV7gos(hU#kIq6@l#)PBwl1)CcT>hkp__utWIl;@Gz zPy5S|Ss!Yv=Sg@FZ13$3vUY4ai_OJ5t%?|Ld8AS*`#t68VjB#?SKgqiClT`5;w5}FI5Fv^0s|X73pH6aNeuiNkXOj&2yoDm z%{l3Jk*myfZq%+$+R03G?2n85i3?6XAeZ3cXHpdJnV3sN42_h|QYKzieiqu~e%F?^ zF)2p-Nj5Je%3#;o|kwk0>yaJtK2xHYG7@C#c581tO* z=34-4#q=`*u*Cqt7C%>38ae~n8@5Kjb6x+WkhRp@xXCshpd;C9+{Q4{%fFWp)q%SC zK)4+~JI9UA!5BnLe{x zRDN2V(jm*baYyrrR5D3-d|lL=))0>|TAHwQ?Uh%VBI)xB_b#Nup-1(m7d1a9WZDdb z#j`5F7+b6jkvp43T&j;2*Tj?cA9$7&FIUZ}rm9|PAzUQ-*NQ%cU<4{=Je6h^&O{qW#EY1bQFjN3DhhI63yWy}~uEeG|@PqDS~I&CIeD z)T?)=ty>5yGe39?Cc+fL&lG}GsB8*U0b5fIKtB_K7qAJj5+)gHm2uZR?g zc*cJ7h4n&`2p9P(C$K$elWXqs6YM96>4eIPX`pJ=78ZE%gn8JngvQGFRE(i)JSx^YM15N)PIoApsB-w$>R{eT zHc8Zmf<@HjxFV3BjQR9@wm^aDo1GD}>ZoaEu%*`6AF{pfWK(!G7pO zwnlreTJB@(Sv5&7OyM@^`|+I4^Af)gQuxZkOzzp6$=$K$mts!&{=T_}6~hmQ~vYAin>X|=B^ zo0{bprsVnaAZemc0Rio2CiWfty}5oO@l0`u8fN=SArw4b0DZv(v1epVvxzCE$ckJ{ zGZ=ynb8xtwV7Qjew)AfDrEz3x3z5;ztj5(I!8;L4Uc&rm< z8iR0gX1^ZWJ)iqA4RwoQ@t|V|t-APVs;#Pd%Y`b{7nZMQM0!$lM}|RI8yC_NqDawn zgj07KPO~l5MY!s*CxzQytor4!Jz(FTdVTI-NVu&(f!(J!94pc@b<!#ZJ9W{&+?9H@p$@EZA7f!jGE6-+%(5N9FYdl>BwasfjrL3_0-Mb1wN6USb>4%(?C;ntS zOy*TYG*rq5^S+8N_s(SI&MEM%88U2asP~jqoaBxB56}YDOK7cWLLX!r(Guljig`^r zsZKgftr~-Arq5thOiQVCI}~$|uDj`AuE;kE*fk#5Hf9MIb?4^$&ZGz&7hHX1_&OzL zYE&H)&RlA%uu3GIzx`M|I9m%c~9hbP9W~0)Q)?-m!|kULLWQ>prYMYPs6VPfyVnnSgxNljr`Fa=!`7R;jp7UKV7q} ze?fvx{$ykx`y9%jp5FYZIw*o<>ttig3b_Ki&;Q=G_G@GpFwqqrXyYC-NUVU;_)gZ48^^A5hZ zL?GnzkJ3n$LjdwV4EfOu^5liQVi7pXZ@YT86yrNyzUz_zLXU?;tKB4=OZ8QEwhL;x z7rlVxub#*b?DmRiR51j~^tCBQKZBlT>b!er-7sAf%S@?yjeq&vpZ8czH7i+u5?#+W zs3lhwF234CI81!7#?urZ{247O480;qjGK;lBD#hvt;>j=Viya!^+%SzG}&`EwTs=S z5sKV$SpT4stBy#d9Iwr2mXK{m{&61MVQBIUIR9mW2|o=%nN^&x^-^Y8sKa!K6jG*~ zUMAWOM5qLP-*f9N^y-)V*Wd~>=X)n$^TdH#Kj#hiHaws;O}}D~|76U8x`c+OuFQiO zW8#2h;uLT!FkvoTT4yq$9|zrLmV^Cj=0bmzbE7u{rN14rf+hxXjnc$FE66~j&;Xl4AP<= zF0vp~7&u5Xa|`#%5X6FR%VNVZAE()pjh__X3W>=g5PjQK%cMN@_6~iqH{*5BFy*`m z?*wvEbe~`RWsCND_XuS&(Y=5#d?2UC*ic*0GGAn-qr~qAGlB1&D)e>C1I&VyY2@p4 z&(So9Y>c+<3^93+gn^wtHID_#5?6ou?ilLnV_fEWQipU2pmmDPFs0(K>maxnu9d+0 zOCJ?E(7{>5_5@8Mag_`O*@a8^{%jnIN#^jlb6@x@+6MZ!K+IG-5XLx@Vd8qEVQG7n z&2)fFo(tL;L|B@yiyQCuEp;M272r7CQFJ#?3BpeA*Y>We#rC`?vMj39BQN>rm1FWc zgkou)Hi2PvXGUDyp*ho`-Gx)pd4rkdW2x8R{R%dsDa0l`H|p z0ClSXP`Bj&fyDdwGB+ZM4hkT10{}7?4qUT_HPo-z{$mcZy)~4HYiZ`WT=b0K)7j#j zFEY55`m>gp(@%lyvW%+5h|r2M@Y{1RL$r5O833 zi#V{(tV>$>vE9F=3?c|z_m0d>nRpD$=oZ{a`X67%TS1EAf`*y~@C#rK_yr*PZ@&&l z13h~yTRP_dq144R!t#n1KOH0Fa%$tr)|zSt96O>&al{nO{<>X~x-K^7S@~Ec&G+Mq{f-}(a|{>Z8U=tH)^o8AKfcw zFXNZ5&tA7~TFxoHH6!Ri4MiY4+#?`NKp9xA0tGjb1o$aPt>iHb*(DkDF6 z@Sb4JvlH0!=LRs=9bzO&djWp&0f)8y0?Egmk_NsRV8?`rKAHmq;7JMdLb@D-#5FB;)R! z>45%5Q+h2ZT7~!I#NfW05eawqgz&~BAkUlit-_mAxNW|i-Wb~-w0-yWJ`gzvT21tP zk#TX=t>ES*mA08k|I}is`w^_bt)xeCS>&T9J6*7^(cQ!3G2mI1E#y=hJdL@HoI71W z1_iI}&(RemQ`#U^LAnJ)-tjoLkzY;7IG%2vGT$08{nTGXA4j-nnj^%vf8Fs1drVfL}@(qt+>-G<@wxE50k zvS|t*gw|#lWgDT18PR>|sp)<~(g_}98{x;P9-*riHS7s?BUi@}(GF`vgD)U>@>)BL z2=Rc3$f}pZ3JzNf5A`G5u&U3m2JCHTnh~zPF;?CsY3P%)(y*@17_Xi=1ACSVCvV8W zd3X%*7Ocss7+>^*N;ui8I4SF(3@nn}K&;PHzyA3Og*!b%4Z|Y;AscNU85{whC7LC2 z^`7t?f3U<*!VYixV}HqRA|5!y3ElXP^iyYQY}iY4l5pO3asQJUXwH5)V(oZoVTpx8 zMNSpUwmyy---`X*XGD6@g$-+Zj)cf0Tpx-?|(8g<4O z?xK@bCE`xmRdta`#7hng0#$DW>hLaJ1A~(3U*e(KzHcPGtG{Q+$TfqKF{9V`w(cO1 zu|e^nZ1Bz_!)xToGuA=Aglq69&$+bn1+~Nm-#kpW&OT2TVQjC9Da@BC-l8SHA=O&h zE(k&pnn}_hb1&f1Sk8jzc3A5NVQ12qn%qWGfce%tLrL}$`asq?xRm>2fr_O6L)$wB zSE6rSze%T)bjNnbwr$(CZQHhO+h)hM%?>+B$4=jsy&s&j-}|1k&#k&uYgMhU$%j$% z|C?iu(GUBS2RI&7QWkdBx0MKXV;t$HLV^F~ggUWariFB~fPB}Kwi)oX8fnLZ*GhDZ zSexd%f7TjlE|QaxstRX_(J@vwLBND$_DQuOQ(jVxVZjtG-HgobU{|mcZ&&fIG+Z_V z>*Ty?S%M@>4b@y9lc|e6zXFm4KZf>wzgLii360Y`!;3gU*P>4O+jR%z!2@znmj^5- zsZRL@2gc%;VCq%`q?TVw2FSXS@3(FY0K z_A>y~$no#1(Z3%=Kh)^j-GrLkMJ`W{=0xkGaYMQzs!&eUeo5MvNTa9KTP=St14!0Sn^N9oU1_HIq)hlFkldKFpueJO?P`kFiSIlccZ06HZY(%s z9V&{dgoloBrG0g}f5@EK7K37^c&cn6(czlwi=*GX=TJ}I(gE7w_mVD^y; z3@Efas^k}a@k?>@^};5a|Dr0poYE{e3W7{zqvv{I_c&C?^bZ{nrgmpn$)5KLU(__d_D) z8PlZ=dg@w%gOE+>|3p@q(;F=7+dhoU91SQ~FnNfPIA^fG_wDrQblxVzWUU00Zsdv5 z(TfNRal$1h!PYKIJR{Z{emEDQMZ)#iCmZ3*kR~H)~ty8fyT(%X0Na)uO2z42_64;{OcYsjpzcxo6 z7DWHbAG$JFunQ?k!DlM{Wl~co@`oVF9bkjD(33U5og#uMeBw}NjM;q0y_nvBn^Xn!bEub(%R#nysx-&hD-3SKXg1>qRwJYS#pq5A zZZDPt_=h6Qv-PURYVM;VH3yWK@Mk&jkPz4nwvehKWf5MiIL0ELCJE!(?qpitJBDd- zS(FUPCT#A5sOx?sza?O-#h!aOeQ|Rxs&OczN$R2FVQ>zkRDzs{=KjcGy5PGfo_fc?I^JqV>rs6$~VV?W)v zaMxsOOU?c2XHm7!VYbDf%0N-OOi#D3kHXXX8O!&O>mS#f1xiuoGej!Ed&<@Bod}T< zINWA@LJ>6`jEE0bHH7#(Z8M(wZ=bi zC{obwD(}`VKPqyHzoTsulz*W=j5VH=jfJTsKSoFBWi=uGDLT)T&T;i1Ok%GbR0?im z)M9#kANZ;c(E|8Ti-+zJ;{LGK8XmuD@@szM8nnBjS}mrk=!7h$_&m3huH5$C9geRlU!{ELvl|b^MG+k9fJ$e?h5eR> zNGpucYTl!&Q|3R9=`4cq<~22il`g?*D=)EZhU2b85)xWzJxC@-3bvzrF`y|81(B9Q zAf8JrP0WZ6r2BnJ@_R1iA&nN>%MfE-g(N8%h~XUGTU)=B@ArlIGJ_gY;2s*#c}fQY z!siJqv7m^x*O8eSDo_InChOZwli0eWiY2Y82L$T2ICV9jwO=AKToir#c#HmY?0O!D z%pzOn#V1ZKaY6@fptgZJFg9(wBIH3-dE%f?KXjcFT>zFXAc$!~Tjg)WB-6%4C^37gGIf-AZ*!`C@I7YhJmq-8TY!25{BzTrqd=J)sv8njkT|Bk-$jkRcwlLw)k&m(kQLRsVW9j##{2rc)_gfdUP2qp_i|o0~w$tDM;~1SD(#YK=c-GX%0e%y%nhilP>@_EOg6ed|uuiq|HY=hYeRFH|(d=B~&BW#w zD#NIGlN9$Yu@M)i(@Yk~eVg>wE9=P(BS`cdN9K+`6|~bqQgT6N zy~b*FEn>Tf4&f~~tp_^MZ5`}oCp1dWZum3n%I2SqDsT4@nud1{jKkQ!f0JK_ayl-Q zd(E&V-@4)(%;h~lDvJ+{!a`Cc^&ype0hN^4Q}gRlfmWY}OB3%`#XFgU;*8UBS&qaintXouUxYKkZRmnLQ#(oLz}VX*Q-36Qp4HLE)HR} z)0mUHsXJ~d<8iv*%TFV#4h(%cjJ5>W0Y{1Q&O&}*_!v#O1dFs9u*Q%k%UCr!Xs&R! zj`xD0cff-rszI$YuQ2kNM@$y#0*7#%E^i?JJV6HYoT_O68*Nyd7`k*i=%}R!FcB z3cZN%#(;tqdTQ)_W%h^P^(?jjP84u)`U~E5t!x1nMLK;bqbTvIpXYcGqpa zYWEVGtu{>8upY@jWk5FkR+4)9l@9eF8k1Zk(QGMQRLeuD;l@!T$2ImWpzRFtl0+>SvmK0mwWSZiH&B+I8yMSg2EpYZHd{SO5X7S&jnK!=A0 zVLSKiI-c({7JzaCtXVUC3z$Qrlzte1feAcf$Ch4w9&jOJP50$yfx-uA*(;2?2vk-osrN@Shcfr+s-sJoZ^^rH1HCa*hH7m+>8DiQ@}Ma~$ofr(MkF|;!;mRI^$lk7 zKeiW(!F)RQn4Pdh=q+BS|& zZDZ&lc3&=iGTXc*)G?AB=(CxlN7YpEAE^f4C0-ifOnw!a-v+F@ogJ90s|I<9xYJGA*A z>26u&WmPUCoUZ$w;(1e_O6ahq2&#*#=8xcMd)IxOx zhNDVRc)7-4`8xArisT|yMma;F8cRt~@>3-lGFy|Rsxf}@Q>_!bz8Z?QfR>}8cexq` z;zhEpfT`M8ez9!B{Du28OP~?Eel+}{TZfaHX&in@aoDno-53v+gvgJ|;u6*BqpvbH z>!o~1b+a)M3)lex8A7K(Dxy{l3waU3_cgC+f@d5*z}(DzlE}qd;{rMn24RWJd1A~O zT(x(8D+Me$7=~(5*1oByImy!sHPDHC0UO$t-6+`tzNHc663kNIXr1u)CK|oJK_7KYpbJ@t&6XO6Ch%CD-=P0j z!afM)Wt?!oIiU%;tR;0rJhLj$KCl=6A zVq){udp#7;pj2CTnI8B`DvALM3kDu8rI9i&nL=5JlLEYUQ`h}p>(`maX@>E2LTkb4 z^A~R2V#^dK)g-23gJ;Vj8kwM(*OK`Q8jBxT<8POU$k6YE z=kmtw#u+%{sg%1700y8`J0})~QI0mT_a<4s(Y5eMR6Z8y(tQ;EN=TkIr2_7xV_wlH z{p4Sp)DC%vgc0`%Lq%DH?eGD?tjcMC1e;o%fQw8dp4HurKQ9?KjS;BE?lVPQqNdyuJ64H)opNvmFxOfk+)<<4-1#iYBRRbs2xBQ!V$5Ao(R#h3 zTjZA}_&n{Chzo33ne5-bi`p z5s9?-oa4W+hj}A$F4o{oSK~}yd`nr|w*_zjmrmztz|G=Pc5HlvJl3HuWjJ`B>Jv~$ zXQR$gIxwJaiL(0^hTirw{5ed3S%|9Q8THx?2>#B1zbiRo_j)loHdyrB=`TRzuc47y z1s084iJLIRyP|Rhn3t(dj}Y4xW>aoA9@=1gdD58kydqf!dZ$^olUlO;PyYAY#Bur< z+P*{0WZ)d3-PJTC4#T+@@^tJHo`g^I@a07Qzc6Z`S4Nm*T}4m8+C~-Vxa}DGjXB)vfSQXGLt=}f2XqOJh_7(UX*u+>l8>(0$B`=n zJQ6Eq&sV=IvT1LrL0Ez)&fn&D{jj`>VM6>)YqRKr!JKKwxW7a8znT=nW&fIRc94C(Sxv4od0_r zM2Etb3c4leCb!H0a>fEeQ>P<7WDE7kvisJ}%3G5{9h7zH5!zFg?s&|4j zw8a%-EoPwr*87&swx6c0;mbHz0yZ8y<^C$phOI^4In|MNP(r>uJHbwHoM<6I-a6e) zo^1BRYLb0V@!b;L|JJGG3rf-@$4mD7oC}=Aly~tFz?pfz`yA0?MaF05)#&} zolmmMQVsG<1me>7D}L50Z7lUj!LlTmVlIEt)WKd~Ky%)g@pWUpL!8I^YAwpgB->)X zrp$r~$J;IGwf%LP1!G6RjiB41u^bP&edE`gQ(74o892e1M~{qZ&vn=Kz_|=&+|VcJ z`}KctL47PnW^;^=2?6S3`M1^Q-;Ixd=0ZPlew2+r1Aml_GoIVd^eslmGsY3MDU-Cu zSNUwbQ`YVMS1dFDMK0@uwPf*J8`J_&g@IfHnj!!^uaNvnRz7Vh9OYgclYOELOq3^-NTX#Ey%b6=g zIPfQwijMrY5KS=3EfedMmS-FR?v2&geK^CBofpI#s{P9o; zdu!IDz+ePLFOy|;AmX*vp^9|Bga4TjU93y<$1f6OW@%#UaI zt)USAOmOKMFpPSULqa93En=dvE%P)bNFL<{GCrQI?HXI@NBL0-n_pmg-NsGr{j6G3 z#v#_}hZ~1K7&}y1xd65v-N<^k7PlE2K>4p_`Zs3tH>JsKBW{!c1gPcS86Fo8!aCFf zIjDuOH?gY(cspPJJm+P_DLSGR=)15?irKU`>?(&_NSZbBQ%I~g6}cXYSs|J^Onxs~ z%K&E^$@w`}KMDJL&qgqnw><_&GVjOV<-<^2!?{&qiE>a6p>Jff^qREM8$Ge^@y5&b z#cic#Gkw*_D|{>*=Pc96(mV~BaT13d8Nnn!Vzy{&zAEUKN-w+`4}%GRUKgCYSD2uy zVgFTNs~wAyUyNLd!Ze8@IqrSa(C7va4(be@8j_ZbEgq^G{EC_&!R<`vbviSIAYw^r zSNwyrV=v|s*YX`SrrGd(Tl-dC_zbpBzsi5XHv2wAF5t@Z;ef(?OuSaB&0zWTtRDZ-yC$AOzrdDxRF*&q->7;{*E%54|oJ-@kL z9&)0n3`mrheDVu}ugwPZP9K(1Cs z|L5~yRAkLt>}a>=_Uprmty%DDlvxK}8{-j}E%N;Qh%L%JBrh+~kZEkTfFG`%fdYkOeti9v#)d3j7`tUqhfyH3oj&GV<9?=canSEATRYnw`zV$=!y zdU)xWkx*-QTwVTDa5^k{PrrMcu9nwPe18%LePy-5eTY`4tL#I?YU`(FSS(1=RrEf3 z5L-WbcgbiAFhg8YE$rp{YYA{3Az5-9U=CaXeDVLr{PVA;zrT{l5`38Ic)nQWnO>^G zQ7Nb>F;NTDtIed(f?WH|!tZvBLF>`TuN$hWuz2vsNnAV!df&282dIyMObcN}|Zh9k`F?aQ{$xwDeqdyyR zcCulAWg&$_iet-&Yya=i`ysb6@;sN40J+Tt$Su{s{bT=O=G8Y~pjT4-3Iswvu&DI$ zb#jFS0{$FZSq=30B^e0lzpY45v`42=4_l_XDjo@2rW_kFy;W31X7T65%jQ9rhG#hF zAc$v%P>F=z!~yZCjm!GX))73{05?*S-tR<58~}HmWgQJil0%~x4tu0yuLLvc_l9bA zkgsf5{{a~LE-d`g}ai5C+X<-#K4fNG8_yVMkd9;6nuIQ3T2+qU4vI%_>^?* z4-_m2c(Ui6M^P*Np#4?Y3~?F5Cd7!wDPI447cEqE>!lTe5jeXwmCJO}tS+kqe>;~p z6cvo^y!CxD%17V*fc|&-?$VM@hD#a_L8KjM%2WBaW}|Hc`UQK%4d(jg5qGQr1eTQ_ zfsZyM=`}9DGEDQxZsGhu#a{WoRH#tU3C%qS79e4n^L-_N;7qguU9gf(C=wkC3<^(pn~UfY|RC zuq_mM=GF0pY9L~GAgKIM9jbnF&ZH1+CW>mn)e<$&Z0meRpJT!M!Nl`mIMw)#;Wst| z-hN%g+Jx=MW@9Rf!C`*R7jq-NappRnnC&X9$TaV(Z^OZro9Tl9l%O;#9|nHO&3sq_`q8|e=vun$Fk94na$y60bX=~#oQq`D z_-4uSbs&C-?wiZRP^N<2aJ(aM(@xp@SgpOFt86dRsPYI$v0aHmxA1RRjA6x%?1dE* zttq0>;sF^+vn}-@G8$GGnY+lm5=X^p2frTP|C?xelRN7h&gV1qYMGCs%`?-KOw*KDVYp3|$E~@r_EDw#U9SrAm*vOP zqDAZeS7VK*LcKxLG#*z>AfCP1NAJ1vYKvc+;XiN0`wh8LDYG@6mY&mk2<$HQ0(UHB zaKP5LJRio=d#|JOMgtghIDh{oTa}f<^A+#oJ+HXJ<__4TZusRMRkeGNS82Nq=!GM2oF1H zM-&6hi`F0N0D?9#IDj(}7o=?%xjClB8jyN|lR|#udPmge$=O1=_bJ-`H&Kydq3cAi zDm<)E-L=Hehgm*Qi{Q@G$hzxUJ;m=7p{D&%#ozRVsAS1#zUYb$_^%+ZZ5_)iO@YXm z^C52$IE0(hx+WUloqdZ?KY3|KVfs?=mc?f=X9akv;vW|=L}5a6{p|G1!2G>(J7Val|S6y-E<9)NxcI?m3Q*)jWvVrn9_1 zO^D1*18*s`-uw3CMREJhXGtK~drFpLbwi3R(H~w2TVL<1UzV_G!RtL8`hC&m=qjD2x&y1EABH5GbS|}t`H?Kh8;KPFdd`^ zze&u2F8G%`OZ1Py@A82z6KdcAsy?!$pD^BdOtBQ~Jmd{>oY+zbGZ1*_irg&FOFDO0 zITsm%v*+Zvra|2$3c+Lr3v-f7wZOnx#22`$W7qUcL1?0W@&wMG+{4CTAeD9*l^5;^ z-$$?`@yM2T;TPwDgin_NXU#VVCTgf2Jx7us1sX~nBwUa}#q{R3XxZm$@ni5gn(TH+kem{$tcE;PmH*V)uSikufWFDF`jHTfTwwIR zV+HgYDzeWZUeR9N`#@1YO#z*7r(5r8{X^rd{!g{xOkCvVBd z%L>_ETz$YJq5ShCe8q~$CRA(!7{V3eGfNAq78+lo=F+$JMdvh9atpRNh`5~3M)6!l z3E`%p5WyfB1zLVUy|*G$8VAdw^w(tRu{G}geA@f@50Ld^-n2Kc2>qxE{yT7y;Xi?k z?GNb#4mCJ4rGVNefbEe=6Hr`&h&S5Q?oYA$Y+&t^ta>H#XC6mN>VgHG!T-GPmyOdv z&;fBA3Ap&1XhH*{{~gES4b|=-e~QYH`I7mN35dsj+3=*y0HTGmo^)StAUd&IPV5HjVcPtDc5GBX&uzgyKQWTQ-{PUjN0>UEV*yGwGYpXxgjts z9>1g0izGQkk_=}x0O(?MDiH3BX(&il#B6dY?Uq;6+6iOO(j{Q`#K^oPPo#PD%}VGz z;KOMoUQKC(8HTA}#~fS%(gmQ4sEu-C=XeO7Oi87GIE{v0`sb+B+-)+UniBH3Pj0de z>`q*8`mA|jzZl|*-P;qwWW!}ZvB3>>X#{(TAw2Bq(~3QJ9RNYh+zN)JbS4o7NZSK} z%7jMkuL3@A`|>YXQ`oT&G0PVmb$VLRY+K6gavqDfi>53_HDsk%K8) z!eG(3`J2YH=Wr3`TtXh+ykMECa56!M02|g||9A98_D-JU&q_*5#KRI>W?75jJW0zH zd^~IGHgeLh!c?U-kivC&?oH+Wj9Np+!Pcoqn#n(qI#PL<&g&_0BWu}GjAl&aT%DN* zVKTnx7>yU)mdNuG3)~t0%HiMw^asokKAjc42i~rRGV;dtIv*)6aTBdYLSI!fY^6N` zS3BHFz;2MET>~EXy|oncpsXfgj8Ko<`Q7E4c6YU(8J_5tNj#>ZS> z)>4F0@}+?CC-GO?Ek^rG&1@yQk@eh#;QRt=*C&#(RZxW5*LEW4|RD;u& zu*IQn1iEj+h-f-e$+>Fl2J|o`GTqqvs~`0_;L?1^zEcG~0_Y-{Ef=&)U_)+^1Ln*b zgr-z~27oS_n6*~J!TRmi<^I;5m9Y;_%*{b^EDqLTjIJx?s;-kU!ZN#(r&ezuU9(pk z2C;OS(3r%*L!z5wL~)vkNSQ%xO5&vSFqesFE~|9HSHBTiqARYGYO@Rnv-@eodb3(* z%Orz!C2;AwlMbMZMy*wU&_(8uF9X5ghgrAS;h@jy&qEViyMVX-4kWKl@fFM#<#+#t zEy`RZFDucQDQxZlBhyaapw%?ab)_UUzjXFZ~lHAdak|4&5|Y) zkYvpgGstGM7>#Ufb!63M{21OBlUhQOnLX}r+p8vPw-o)0?Xcagl3rR@M;6e(@;c$S z+0++n!L+O&-_3W+g(<$5+Fv~wD>l9=nK4vXG|7?y_IUFZ?rQ5&S>MeKs-Pk;!zcWMFINAbd~wK{!{=aF7vQ^&sbd3dH^e`- z8zaoZ@OJ;S-AH_vb7p;DyJQ16Y#!Pku%b02Yp#ib*cE}$LfCS_fD#KrLKik2el%LS zx6eB3ATwkw#wk@gS29TID0f_9Zql{a&55T2td5f=TP!1a%D1*_WYT}+qs@U>qrrw`hq3-h1-Dj%~7S*k`!D@!R5i=FVJ|cQGAP$=;?y+ z0Ae~OvL*`4P59nh^GubF2DQIM(Em>8=V3>eO8BY`@Lrpe!}$@;4#NikmK_NY86*vW z4>(B?3~MGAAx>r`m#sdCNRy4&s1O;911-uRh+d^GQ4c3p$>YU@6gfiyMF7S z2HAk*F|-H6@*O{6h1#4iYD5_%$$>Z$Ux)u9d z=I>~Ep>f4mr3QSRf!(ED2YRcB9_o!!CRGWu={)t(c2QPqMhc9f20oK&BheuhZf|rv z3)SG&6s|@x!5k111wz0VwxPM(x8FMx)dgREwUyTZ zP0X)`#++I0H>rh+LLH%H$S`TAP?99tk${-7mrh)`d!)Us@;rK@QvI9bK@kw$(JBAXYmzcbL-Foe1k9btvg;vI zfias43A3$7rMajIil#vQz7-j++)ZjVZ-v156 z_#s07dItRer9U`3Atx~vF()%eMH4~i&yqSUom^meWgy4^WDEd zs#J(^)Q9w1sRt`>E@Tuzx9%>b(1Oh}LK?*89@fBw3$JG&v}`7GKF&ZF>9wZlvw-P2 zE(}O&#vve}=_TqX^Ar$B5lS?00YD>Vl|;*UThEQx_LEo7ix)tFB__BS&43M{T9E9_u`sb+)K zD#_R~IS6k#FkfFi%9WM7XUAe;3D~fRi+&M|baYz~Q=mw*1Sd}fOJ~RnWh9rVG1?KN z$xKb;zQ?JNu{te^m)Zuz}c0&N1Iyd>nKT$J@ULR(t+?CcpDQ7=68nFmn7^C50RsiVe2~VoByFKPS~RkJn9CSEv1Zdv`~3GG4xs$6 z)nx)-`AuyYOr<*WkP=Zrqg>0K3W{(AqMtgQv>Q#OiLRpu zzW1@*CdaMb&2S)_Z;rgG=fM~j@8ywAJ`!fqN}$M8USx7b$X_SRHzFIo?JPo(cfb9v z?4Y~}EOM!Dvyi9#+F#E&)=L`-8jED#=6x|w`cQDq(?yx~c+TiUX1=0=cJWl~6@B4% zvw&*wjrJhLU%Mv=I(EE}`GfT5C>mw>hQY9gjy& zQi}D!k0MMJl-nXFuNF60S`8z20ufk~oF*Dt)Wof70gStDiWv?gCj3gwlW(wGKdnZT zOEZ#!HDFFHns+Tmua)gAJUxNW9}qLUPx+fuE#&2yqw#rM<}{5#$y&c&l_OTsPk zi&9%Acco3bs=6ft`kL5@)Zu(t0^4lUJU7$bNZZtnpB$&A>NkW+KP)7%6)2Z+DD5qzg)Btxk;+&W#eH z1b}J}Pn)uDr)f$T7gi1UFUt$3PmA2=d&bK+!%Yq2ez>JzB;-vYshKUGAIkS39tY`OnwOuyi8SUq;mk-?2H}BcoT+>}N zH5y~wjmJR8D!{x_seTwhGrrnr7F~zra9Zlko6cHEGg*~*8Il8vHi=#e=iSn6h?X6_ z;`Ulj=if-CmdTQrid+iXi6xFdQ^r1TwJl_((h!Kv3<8>u8InGOp-L>2(`vtAat${S zhU+ka@D{Xn1ywRVXc1#*7$bgRMlc(k*-4X>4+{)oYVpUzCn5yJmu~M`LziG+n}=W| zg=X|djvniWXe`;Qne45zW@V=KL5kIBJo`{BAmY7%elk{aeoIOVoH|;BK?B~rVFkDt zaa%^v0B$rsFndrm@m@TJ56~zA0FBkwI9gns$)N$bOQw(hts5vQG;;T=bK%QtmPF zm0nMp*|FUgrV0VHYujv%#GA5^rxE_r?2DbV3*%I$PeEa@Q4gBM;AY-dZ$&~WC)|B# zI<{%lPf|pXIWjjYtX11HZX7S!Sn@lnm{@N&_PlW+aQ61KQZUmaTnYApfd!j;o>Sa3 ztBxh{Y;>zFzo5H}jGen~rPI_|7BL$J0rn$VQs$Yfna^}{Eck%^ z$Zy-;)^7}NC=B@f-8oy5H-P;J+6|q;s0`RwHQZK|i;^&!vm3ho>28xBMQ3(yC(lWs z26me(W}6@r%3)h0a{*~4=a3ViO*Q+m!d;gTx6)z}U(Sr(hb3U2Pw9HunkjQIIb=K z{H?v88oi!?@zOc2mS`#dy3%-fXOwxJxc_Tm>cnGw(LMVMpk5v}KXinXe7=Jc#yauD zOB1haa1LA>Y_$iHL?P=^1rzDG%c#8)02(FK0if}?3*k@Dh@CY*Z@*BX;HCeAsLyUHO0WmZS#=8az}C|E0esY=P+WXKuw}$&?2F%f^V%$i%d?hVs8Q#^cflX|b41cl$5c z2ww*n`U87EP0m=c1@KsdMx@~-4*s$*QH8N$_2_2x_y^qj!5K+^-8bO{6|j~_d|BS-Pbau24G(qB%tFE*4)oPiTNR4mN^}b7pv6Ux1L4enKTz-kt^LB z2?TW%+ObcxA41%ZUgeDcTqO+DXu2@$ zyCzlEi}^w0wR+_hEfg3j_aqGg){cemGu8kQ1WHpzNdw>$Qc?uNmiZAURL$k6 z3o_hfQdsDZ6vBoE`C&ol?z4vdkx*N_9W{yuNz)Yq1xOR>5HVPzLs@W#xcBt^#Zil! zeJyp_LIDxtH($Zz>a)VCCO1bs7`|lz@DTMRE|Gs=#!Ff0M`eJA=n5>a+P*3u;34WO z46)8Q%={@HuQryI;am^-rC)Ms6vka`bz*`zO|M`{W9!x6lwpUp*Yq2<*iRu- zB(ElYAI(=!K`h)b-VOtDgA9bq;C9s^_%q4hpIKN>lQ1t1?%1NADQdP;N;@%6q5Zh= zP4O@`;H4z?0hm!0wLhu!lqDul;_3!~84JolFfJqsBlT-Ve#(R%?q=E@>=q5&5H@5p zPX0*Ipia0jL(7ciWYg7rjn~grUU;<@0(gkV1&6LJ2AFHy zk3{r(2&n?4DnzL)(j2vh;o)Tw~N4=kM_Oj)IZbVVgU*1E=&r!l3X*;4i|f%CTA_DGd`qE?E2EcJt3 z>X0vMQY;f}r67QtYN;RRX#xANn&bT`zH8FE-#QaQ+`yZ%M95ALV`2Uv5aIIN8ZS$mPc1?E{MT> zajsRA)#~}S)YCw-P`3Ph#)RYL7WG<8`5+A1Now=m<-HY{E|8vVB z@)r*^UY9u?&`cf>Al(6&2$1f;Lo4sHour_%NDsI@3QzrTG16BIv-eLR7rppxeKWwI zs7kylude&C@xneT&+;O-B5U+DGk~qU(gB}sHbaP0biwv`*j!ladbrbPPMu7q8@jcYBiC|!I3 z7?~Obc^f8ha2=uXgED@X1&6we$hiwA*`K@Q7Uc59zU^BVLv!Ru;GDH)u%(rBj|qHE zh`j}DI=;SX10qZT%`muMUsykWaaGm2v3Iz!d$_8f#uBU&T<@N&36Rj)YQ7{VDkkoI z3DK3~gd-jkS=ldo1GKffeo524DsrjyLku-@LF4Bb%2&6U&BpoeoA4!`Z2Ov;8|i@4 z)}3i4mW!UGw7lM#O#51TJyZR$tyB9e*spi*0EfP1ac#E%mM_qY7D`z|Y4pqtp7V^C z^fiSmMXzb-DQ@rvfs<_$0^ALjdPnjpYEZ^|n!q8%MOR>Rzx2;ozd7(w+_h@5@ zhUP?v2OvQ?vz9d615VCNLjgAG>WLWBfC3%Y8EL+pqvIZkXRk17*Vrw%pCNb@me+zz zR+9;>gccqMWkX6mZqS?IIqyBEbOJcErY7`eNCI7Zyz-5a2T=tNG=w?DD|eA*-1->x zwP$Y5BZE_q6E{x`8p#dzvz{vBBZ;q98i!1H;!sNw>DyK--%E9~Ce(ex)=(8~UP-Y~ z3kO5ZkSl~F9o*)_r#qAAX?Ag^t$}a8%r8lN)f=w`_^4OMsf)xvBxvA6f<|jAx>vCK z4t0K+en=1>jZtHqu*a+0%vuxVF*JHr(JYmu?o0#YT5MB{?>k-1i}sR~-7`{6#vap9 zu#Qsn6=2g*FJppbmPdwKrG{Yn;iIl&zo=@?#06|RII*25zeqhstO0z~TumjQ>wxqL z^r|O@Gc=XeVl8I1Ah!GE%%GpHt!w#QyCGXQxlU=7KP606gxxwv3bbGl8#AyIUFN`9 z4^Pg`=Qz5xr{pmm{a$@fEYl{*>Ts7U(BT?z>FTY z`c8Y(Jm;jfA5M4f4mo@W*`Iu-+S&;r4DK<-{5fG&P@ zU`R6s1<*x|`QBPaVhNkVT|=78%y{l^Y{tvm-Z2=T9799=2(g&>ERhyt(9j_E=?E1R z#6m@gSmOe{X`lc>YBWWzyQ&D%UuXj(^WBdgPp7UH3-;wjh&!MCJsmk8M8AV7I_Sj5 zQ^*tl;Rp(>yN1NNp7Tbx0OS0_5oD+My$5b~2wk#5U&yLZ{zG+rLF>j{x|b?SvA`07 zOM71oBx9x6Td-=p?mV;MdTdM;{BhUT8PySONZo!2X;WmIZCRe0q&RNu-I4^qNblE> zS$pj#5tUp4_kB^Z#h`hL1cZXi*r}*C$!t53y!au-?iyldy1KgwCJV#Y$M;A<5Epi% zlL_{PY3t#cXuwsiF|jx$IpFtk;6doI1xu@tLN=%x@NnpoJqvSU zUHz@}e6qWha$?ZDuefPwlw!su7Hg<6l$oKllD&9sQc5Q&nKIqBxMg%?-8o`N7hbSs z&XX5HYxVM-xfW_$s1=qrD3>=;7`JJiSU@L(YON=ek*grtB#7Phg^Y4y)==@I+e*EJ ze)3YaTJ$VcDSvgLXr)$%WP9PfaGYBI`NC(E6S1~OzV1I?hp+zQIE-yELn!k)(!gc8 z*y-(uIhTy9yGCxXoM0|aQW+P(5j4I43~&S)mkPiF96?X>qt&n#(ANvzapdEGqr-TN zL0BX6p1?nRjO79VA0zrpOIO| z)|CC>W5fdZ7=v*>e2nstr>ji&Ti+t^ZAJlWK%_?qA#5T*fIvpQTfVc+=uHFPm zt4lw8jMawomISF(SsLe_Z<`TBSx?`zB3>e%{a$SZn+LB~+sxrixINzga%DFOTPrOM zm=OPti}5dt_3uW-|2thAAY3Ops^n*`zl(_U3qwW+864;t%_Ss0SDR?IxDw!YB*>$u zjEuL2GIV6bK&{6YLJE$Q+k0jB@Ld-HjF~URjb-c64}iP}PC(wn=FP^-b$iiIfe091 zZ)Bi_LiAE#AgAM?*+Yx!PqRfv8dl3ncAF>U^}T|U55g-gix+2!98=90m4wSm^K0Ja z4IeJXE}U5=Reyksap7UA=y1UEtC&AE3=ma%*=O2T)qM4!tJCdcwlpHS*K%|qjL9k~ z!=|=Ndbw>zOp#i28H!-`X+{6=VXn$HbSOkJJUj%tx${M0swl&HbW>T3(%+z;DX2iSr22e6A4>T>MN2tU+%v&yL-cmPbm^GB` zlCW^XPyXYMqc-H~kDlp0eP(aL(HyI=2f3eyHFj3!#|6SUBV!XlsO(9}9wbNg5TczT zZrENr4d=7O4h96b`vA=eX{$GL9Yp5+6R+C&Fv!IRMP!>RpRro{m~ARgI~f3?)tqEX zF!nrKa;D<-@LTOc_3*32rE&f8fi6NYvRhz)9vmbt*@1o6hKbw-$(@h8TKz8$vv>Ig z$6Wf&2brhA=x*uLaX@b)MtlHwTSy>Y#RdZ*tQR48M-mO=eFvR|rh&{(ITpoA)AkG+ zWW1HyKBcJD*C>Vz1s>sN;lj>~BOGcpm;7R$d|^Y*&^Zk=>^2P)18#Hj=TRU$$j{3I zZ=7xw%s5Q%dmh@_?Eo8NwU!nwwGA3a<%{ns^<0LUJMB%UmtR}%eG|@X=>wPF7L_@? zUccm}`w5?pRI%VD<>CfPnaxUi2EG$szD|P)(f>o;TLtB{pj*2nSn%K^KyY_=cXtTE z-Q6L$yGw9)f_s4A?(Xgu+~G{tTD`k_?cS?<|Np5vb*i}dE+{Uz7~h!h9OD^_Uq_OI z(>~9z8tO&d71|N+d`?)9g-JgszbtvBJ$#p_;~$|5)}4NrIuhO za?};R*nyUI>9KJx-o0$e6X%ivGgQlkloQnd6u-xX2FW6E35eE;;l2Qk?-7sxWKjeH z1swF{Gqi@hH36g$RR|9Gr3d2V*qiQM#mJF;Rr(GZi(gL=@pj@>z?P{KSOD>wHGSsd zn<2ei?5xp)rF@~w*~zbMvP${uGvm~3wPaz%1JHeKUHf>mbKH@#t=?``v1g zdF<7sT|Dl{*Xuur82R)UveSWg){y@}i1D99>#xnF#n5Yr5e4kG5aTPYJoL38O$cBd z|Dhr6sUi=p4BQr*1!qyGGhwghR=7+t9X}X}?HXJ}$)?)bu=05{?`+socF7=K^C~9< zaKlu^e`ho6SEHw8*YLKfYwu~0|EM@}{YFH-{SKDvs@)8=LQMvKd=uZ--Y|*wOYVmz zDx;F}pBn~2%P7ywu!9+JMx*FPR{!iYCAM%R{?m3e>;Lkw_ZBAo!tYUt)G+;;~ zdC-hUzGdW++aR(e0pdk_BEaw5pB(`|D>g-3@J0xIZoOtVsdGPdj-kjJNxOC6d$OHz z!vIR!pv0X)>4#t1^gSEEVhgCq`|*>pB*!43+LLT99^ALmltBgjo6Q!*8#-%YU$9qj znE8|w>ITkYoRW=dHe?KHO~(SSuhrs^+vH#lFnz>IOTHADv&h8Le``-kP(^Q!(?vTk zC{RD*?06SzR|(3ky#DPQ3WNU4ziLMt{;PI$@!#9gnm{|cJ!!X)2c`%68@Y4lILZ+b zzjDWV@If+WkDS;{zF@KJbh)NN!9nj!xhuayGvgALOmd!V{ZwMyZPpK$+h_l+YLx2a z${}G&P|oUPBM9}OxX85O43G8}%?$i|-g=$&Cq@VJH>OhF6ei9vh{m^^aI+{+1lnKmFrer( zrzRl3I7J--e$aHkb9n;f7g5$Ecr9{){31D!U;GW$=sxE4nqSN_{vjCfZJ%>eHOrLu z_xz%u7R`9ZAYaA~$#n~c!*L)=5-`3CbfzX-}{7r+3ojLN&PmX*>FN_4#*Z@$YxV{}O1$%tFn6}^u7;aTOlDg=u)4eT1m z=dyO-eMUkM4m!tkeAx36Wc1bKC;sfZk8Qq&p}T+`FcwjfJEKqqn8iJOAN>KAmT&}c zHiT47I7a=*A+h47A5!9REz|TRXdb173O*h`+O*bFf91uftgHdp*kMx#02`Y+48P1c z+&DaF;#g_zx?rLC6T{%b@*;DUQf+RYk;8oIz9hMA@GB(*5yp4lEYFi`QC%A09E?Kb zhu94gf(;OGf#dH*se0lSmh@EqDtgwveF?O?1IOu(GLI%%7ran|efp83T` zM6K$YhQ^gF=L&XVebjen#Dcec(3r{BQs=F2y5U$;sXN$Zq|0)Bm1WFify**sIo-@l zscl3z7F4_*`QgwzmGjC4q4xAqHXNi9z1EL|bo@{`;d*qtKdiw$<<#bL&PgJ|v@-_g ziFIo|w^H@UAL16NOK5w~k{L2EL#IC1^gfPpXx0$N#%n-X3>JE!yVMNp_&9ckLQ}gU z^m4juxY!wCp~{U5S)tj4v~uTm8bzkI+j44V;~z%wRBP@uB{}xwBttf;a4VmW)KD9LhpM!$_s?To)upe=&zmMpU;XS(HrC+z)Zlgm-v&Hy2g_HY8(+) zHN<$Q7(7zjs=j1F>|3urG1(mU4krU=MIFnx3j}74klKk1X3`IJcN`sPW1%DK&AjEM z`MJGYvKlhC z&T_Z@G$b}3k3##Owxe19cW1>vbocL7L%Wp!O*=aJiEN*nS6C#+CI*!Z$N+^Qo$1+s z2C!xxDF3n@{iyf1cC;Z78=uNT?@6|53R#fGo-}RF6W^0j0icZkb36L^k9KsZUlvKq zNC=DpAr!kRh`lj!?9V;jnrZSdmS^G7eopTVmLU*XV@nJC;^DuwqYwX~9i5cYp2P4UT8~D^ z!2byQiAeRywbw`aJ_~q4?=ZHiHkN8CLz_|oYq8I_X~_yqW3aB?%t-pwbh}Ewbg*D% zNBxZ0fuUl5rtnr@k-U#hQ>#HdJ9K$!V5^lis2MU98P+aGVeh=Dggt^KPBtfA zDI9kdE3;Z~|NK(@iT08qU}0q2Y9I?GjP(3H3<2&ZLHRxdx4BWhqtSzxOM0vII{Kw) zjJAReoO_Z-UAI%B^TBmA4ER30j3ud`6-p=YecqAVvWe&ZJsv!kQpQJO>hXF|&DV<` zTS@29m`1Yg@rrDAU=9jISN-Bto|ZOMCzZoq2!Ng;0cuM$&@EzDD+ z8OXsNa8S}Hgbof)QI960%}O56Xz*Gk6kc&MMRAyGWzv+mTR;LmLy^on37}`lps=WE z`coyABGzeu$w}xOGk+&SR5RkE@{vnFvqHtr1_>Hd#D0Sw@lI+82U;FXA-K$yO29Tj z#}o8-@jBghx^RxPbKn7eiZy@ZI=6>=)0SGCnaD#|{9*=4+NB+MK(7u+KL>h-V6F%Sh*ahuA2wd5f?#8Mpjx+yE2+}#f3#anhR2`^s6 z1{mZRSibz;Gkg$x?HK}@#Xow6_Lg@Xhep-d!FK2*U`B5Dv~$-x%_;-`vS;`jd`U5c zjr>nji+_@=|IjM_kCJu&28b=bf@FV-E&ey4!@72yy&2#CC|M5w66m0b3bK{-dRJuH z^RMi|{O(gH(95`JS&Vc)i7JR)p0*c3k3M~plFQM~h*<`Ci&y}Ds-HdZjtUms_ z&QQ2EF939qvq-geb0Cx8iZ%uN7zbh61}C!32fi?Qb}?z4iyRR)kO96mdwjrwBkS%J zal5Ad5kB-irooVg#3Qgo+Q;Q}*Y7w|=5Bg}bE3|3O4v&0j zn6H$Pid28J`e5mB9L|RRf}s;e(Qr%Q(F)X~>6e&Z>(ML2?u0-+dIBu)rRk&W)|=OQ zbPQ0BHd6=c(G3cz{fkC~f7GK5+X|S6FC!8csH4pc?{APA%g2algbo5l)`L*lf1HId z8=>WGS#*Eq8o2K-I8|DHc_|HqeM-%$t8T=!B?Tu4;q2>p7XF&OEy$`>fH)r=hOYSexGL z-=GeU3l(1hs6&s^Z%_y8g4kBqm&lL3`oBRP)JKGVgF2Y5sCJOiu))i0*JL&S4s}2& z^7tL<5ZK;+g;X0zk<0wSbQOR)$N*4>tIb!agH!M;)S(4{I^3X|*8daKVQ02M6M#BU z{{eN#vBm|U4sZSjb?|_Hx`LghP>lO6YAyX5wGKL={OYtXxZDN(@awx$ygOapMC*h> z(xS18%|wNH&Cqchj2F(C@mCQOrCG*X520(9Jj-k}Nt98l)oKs!#ROI-8+Gftd<0)A zt2WO@{fZw(#=q8v5=VLdepP#Ql`Y(@f?5AzJNlng>#yzQpWD$9_}zcZAYz-iS_tUL zPt=6ouExi~qoP|qowT4A73V_d=6_o3$)fjY+oU{5EyQ_yE|H8q8nt3&;>fi95UoxHF9Sec zT#Hm|*EM`+K=-)tAwd9hB%NkthiMHU3qDsXBVaEk%(9e@n!$EvB27+kTQtbfFRNi4K`$0|&3sqbpYy37M--ShV>m z3cy+fZ;5$gSDJK`~c<-Ax9@R5qQZ*#pg=OAd1w`#29t>v2MUEZE%5Q(n-$duV`7*2OeBJj>$+wHn8@LD zmDGgv?A*ZP@|t4Lat(k>qYpFcOh*nOgeZkj0y5`{b9nhL2VyD+ zmMM@v+JZB4<&CES^THc;3WE3_ufWRs?38oB@$-a+} z-Hy?e_hsig~Nn$?ll(_xGi#R4g4G%d53?UABWNG8}tv=D+iDI4CuVF>J^1my* zwN^!K+S^&N>VASSGY^K4GTk!~$ zt9ieAoTWzkV_i^)u{*%A1SB!Dofi(a*bp zW}Hp2oPnF@yrTrVryZNJ>-_L{tBi%oR5HRn8wV4Si_d`q=fhEG_gq1CS=4lwn6inG zF8A+eKRkZX{{oANkFO9%Q))9!>U3=!-Cbr4Yvf{%mmEVDz0si%L?_DYj4DNBDTU3SpXM8jGe$AwuP2?3 zd(4wE?$f8EH0V~UTkGF5Q-2T2pmk1|S8^A4p=?mUt2j;$zMV}uqHs!2tQe5|A3G;~O{ znT?!Y4~~X=v&)%sGEvI1C}9Uy@Zfa3Y^IDlN3cAa^QDjw+{4*_({gB&q?|a|2J!5k z@);$r>^N$_I-uwx!#s|)ig{O2kjPDC_St2!Tl-j_DTy-Ga}4j@@Q3{LlG2tY$IQ+H zoYR8|L~ORmw6(b_gnyPiggw2RC_wW5dI|AgN#0+()qg8_QiR7#QO`-i$Y+sJ>O8vm zabNc3^J}1ki$Gu366Za9f zl^eEK#T$85yprg*wEQ5rP(^%*AenDHX+PU74#ZLsDYl%!BSyDsP<}V;5B}~|Q`F}u zqI;Ns5D!sVoLAafS=UIJU!>ZC7Nu;~@TKoUQ3cpMC_UB_8_Vwa(h%PTVv^S<&;K(e z@b)9m?u4$j0-P7D-NEREuEP!KoxdTw&-$(?etxMjcBnZ1av6#S=zV{KM=HJuXl*2w zN%GGD5XF)Ex5l^-QfI%m2`?RaPia5ei{il^&WQMwn!qj#Gfr^czF!H6hUdLmX(ieX zEpO^gpv{*G^A1Q$?kYO#`VjBF?|X|zjNJvSze-}}g1zRom;8bCS6ehb*}VfyCTziV z&O#zWQnc&9G$fV8`kw5()2|i63ytzbZ@xOCxAxL;Xyn2$ol{*#-49GT;fBr7< z3;+)Fldf>>1O#~I^Xbm{%v1Z3kE%j7or25dq*UUi?Dh|XLix(k;GftIBC1lhBTYi>_ws6VxV$mEcCP&J)@0EWfl0_G>k5OQ3aY@m8jUa753B z-(#USp%$xdP$FpN}v($#D&QGPs$;#o~JFF}>LAu87mafeivedO!UD43Y; z_^gF>pwM?Hc*6S88ebY!z79N|s@~y@B~dRgQRC?T`Wx49qq@&01@wBBh`M_5)(=zs z8JITGQ)B_$pa=E@PBa_rZ?!@tLv;iM^+TY8nK<92pbO;#4HYVScQQXoCm}d?4}w1Z zO4}&aMZ-GvBh7$eh;Q4t543%yBy%EjjZ(Yneg`Knh4aI63@y4{sG&~5|!@{eHeOpHYaJ`VCZ%t$cr2Y;RW z>a)W@e>6WyI}iIEqk22HT3Iq`S!T_(s!eyXdnAe{f`>yBm-<{UTUL#tIbP4UVZ^^` zG)k%C2|xAJc1iO+7|4i$H)jQz`WAtb87z{TkNP=<@%3!P1myG0O?9J~)R4s_5=UijgF5 z2jOWaSsVAzR(TQAdl?RYc;pV%88&NL#~KQ0;z3`-U{mJ|OFM8q{idM$RMi`#uVh=sUjq2(%`4=Zcsx0`ocqK0} zc{+D`8chxa1I+9^L%GP&-ch+sCIq4rg5{=ulXqFLJcOSKae(iHHOO|tV{zqN`+)#a zGO@Dp;SmQ76=n?cQ8&ydr=_Qp#@~h{R(4%hXOGE-pg;OiE4(X$lq!VBt3mygYTU9x zPQihh#Js3Pp661nIo&})bJfL!?Ql|JdSjD6tgZBc19K7nKfd!i&m-jbV{p_aZGKUh)H-Z~`2Ab9ZIupD=rt2^ ziVt;;X)+}Wz0DYPs8{3+33$RT)Bt6s`lozm*qB+Pcf%Y>@Pi%eLU_*8#*gEMj6+alzK_1~%4NgzdsNB;GjEXR>$L zV=>z=QDdQYB1I(IY>nFSi5-D6hTv7R(o%lHMA9S2+IL*Ru3o*GWBeYpgV-+uJ`LmLKMNK32!6Q0N?{vPv2e1?f-=gC!PpC$nwhJDSu zJ%1sG>0GzgLd^vGP;S|=r}i{0IioJRIM}OA(y#d4-#oD7)|1dhhO*bn zKK@XFU7dFCmukBGM)}aNpl*AnFuh~rU1l&}4doHM(La@njpNpaUG}xk#Pmuo{vG?( zGj1;5XuBuXWjX4-Q-P&Hw5Il+L9iz7hlz5Z%b3X9M8f+bh595GlYFG5(oia*hG23Q z!NMDI~TWmCR+7fH>QLY(*p*;Hu8yOuL zGAsh<2c}3+P69n<(o#X=>%;zQGe1!2!O_MhU~|1f$EK5J-ZyehoG{a*{Patb0cnVHHlnqK$Jxmv z5U?5OT0HxvwvezSpy3JW7$+>7g@__PVlF(Jpf03otZPJY%R{r_Z+ihO>sE%eai;==Tpj#?rhYTON^Awebq>Kz(Z=z|Ksv2# z1YRT)Q-Wjf886QXHoS?c=nYH_oAl{;!<~F|%0LwfVY!rT#xwKWTf zhe_wouGFfEPFI&x5(NhhgZfk3fkJn;8xbum$>U>;D%R^9DZkn*fuWtxq5?Eu3s=YU z1P;G@{wYbS?Hr{%3Mi-G|G9GhwU^dVv@lix1{~_e+;q7uEdk{`Y?)n}34iz8cc4AP1BN1uukq?LyAO*FJg|z7yah_CR#BV+k zF~oSd^~#FJbB?!HP!+1BGb1pZx6h3PMqo*J)AN^0U3PbUf?Avie%fT62qtLRnD=TJ zpZV(M#~ofHhjSvfSpkZ?X}LTK8`0C}_9feGGUvU84qBnmp)&@ zf>pfnb_~F)aVRYYFJ1>ngl7xF-A_h&B>m`sEpNK0b~@a*oMqt( zeZ_|gO}k@gCJCyMA7?hp5*iMA|0WIZ`y$t~LV(7AUA4`3E$zesN^LrLVFCXQ7!Svp za@K(wobh_CQEX%Zq=+Qz+wyiVLPyY#U72D>n23=Gp>p8xPVAOa^OlWern`4$5f?e> z_jN{^uC;ZE~XT6>5q2AksUgxe>hf*xQinxO1ad_ zxo%9<)Rc=4Um&39edvT~p6o|>krrF2P>t2(#Dl_?L@@$6h8e>CyhgdEWN}EkOEU1Xh zRrKpHr6p_zTs!YZ%KWab<2ImF1}ZK*uK6@CiuX`o9!Qncz09}pFf6%;M_`T^{gP+x zWv`w*o_6nMW!MfiJf6tfCYDgUTZpmf)~s>Q&LwgB_z$|c5yiD5Z% z1LI7Z>kaUckOkf#Ml5;TRF3)ycngvS=Fo0?Ml=jIj^?erM?knD-(gyFA-9Hc=_6!0 z)k9C^9b4+>O~2Fnd3~XGjuV(sM)N-AC8~G_iRT z$yJ>DoQ0Tlo;uyqY-qEH&jIwrGqgd(xZ4zUYt-%z{gIfRMSOyB6G1il@^#!0{71e9 z^!Txv?E~s1z+BhM&U-?fxSinC7Z3Ry+#r}%?FC{txw&Tj+R(5?zxQ4hJP~ALBJ>@s ze{&?G=fDtpu3o*pu_Ci$${s>}+MUaHaeWfm%9^ya$ZcMCDx&u8P#`d=%nlDW?N`?K zMuAXf&OZ-LmPt7u)d5yK0kGl>|0llluRVF%XeB(*n}+~;^X`EXpW|3RLaKCX>;4pk ztk3`H4QC{=(4qU)30(gt28311=?e{dA%5>$dVZ4P6jbqt~SW)zJLzp~~C z1=vgf!8GOHtoeT}Bw17cdq_Oo>onzaOz537KtfUctV>f5kWjRJOO}PJ2nl#b$Qok4 z`}Sib6^ec!6?+V}k+lW73b32XSbe~@Tb{med`%v1C%{`~MMR_$5RTT*29_yzO2g=8 z+_i*j9XU?YPg`!>R(8{GPMkGPhML4ce}aR9OjRI~z5zkq^U*yf8F5jnPA;ogSL$Lc z5Etbt|7a0eVMVT?LZ%W{R!$$=v{Q8-5G!R+RpfY`79?y1o$hy$TgMeI%C-YUUm1aA zx19J8(D+!Tc%WM45*D$`Ksca9_m(%Owl#o~$x%~YX-2Z^y?IxRt&-57Xlh9Jm(O}s zdrCxptfav))RC@Bic%4?Z-HUT0Yz5)tNsZyG7MAyEWUk$m&%669kwP+T7kE)#MH^g@Tv0$Ju(*zk9UVqNnRApNXtg}u7W-s)zpe(*EM z385dd*9-w`?x)-_1Ay)v2x7ws-DrQO%-v;4gB(?9I0pP@LlKTeAkz5-4~^)K--Vh! zXSaZO@j;?>)$@0TmW6DLYUe5v-9G%<%+*}P@0HMUHk00d&d-*H>eyTK@V{P~jq|Az z7;BJGvD#a7VEAI`dMnWB6YCkZHFG{X%z8)UhtG1lMRR|f8k{0wo9JMwrLn~$DZ>r$VqxNizR$0B5;LT)`j50 z&U+#8n@?c=o;M!`y~GaVnW@s$#gT@#D@VVcl) zdDd^CO~|(5AEAmyDZm|$n<9mlZw6j!7|b^6VwQxWR~3H2v?6BYR8|MyXScxzJjsty z)JD^qCoDY1y!fD)OMQ)aO49RVig4{;NXWS+>-b1;gzV>VG*;YkJ+TmD{MpHtAzO#q z%6VP-j?Qc~F2qVOv0q%Si!j+C}u6c)~(^rY4+#Hp&cSI3CvwR>=gt!2a`i zlTO{0G2<2RA;XB3zA>(S5-VQq5sDT#NJdjnk<5BKQ^7vWeG7!;O)3fW!bAV66!-&X zHOFPXv`Ax>vJdqJ^k&i`GL%Sl!G#v`HIYIVp(nG^7YP%X3-JUUiiopI!1SBNTNaL; zvTJvVxt{D9R-H8a1@vV!Hdoy+XT1-JkAs!9arrgJ{scUcV1|=?H<@9+E}t`9!(j0lAPVt|MF*tRk2W9MbVM+|HMU&8 z%eyWVQE|Aj{D!*U7NC-%yhs_Ro$cX9L;QKf{VC}UcbDE-syrDrvN3M99L&ebdmy5g z>}IgNjK6qyJ|FSm>G(cF2ld?icrjz;O?xlq&rfBbKzDgUK> z{k1W+P(%>LRKf7<@BZ<+tc#j3H%J9QLFU#>>!T_AMSuKVzWQFLDM@2Dr8Lkb%*J(w@ zDcM0*6yET{B?A;E*#HmO;^#iD0+Xq#+PaeBq!UF%lP!RAj(DvEl1KzCNzPHPZH#)22uhxGg{hu*yF;oHmKH_rWmZL?>r|C)KMln}psYJ} zMaBrb$0E^q?9{4;-#Vy<149=NPjAzLXQzCcq{e~^C}zXU0!+AAm~LB5R)%>*ZA%&p z@|Pd+`GZsJF3{b-&U6eDHx5FSm1jRI-&?R1{*;9~dU%S_if%^yxWyZe^(kI0VCxOi zHB&P&{Wa8hJ_q(_!^W|K(;gf{^>J4Hx#GysV_d;C3h`+cSyMSqKxq||(2qH+MwvO1 zoNF`udUB=g4y%?X`03@>ab5bz&#n~l%ma9BSkkd z8d5G9#x#?jHIsX+ux!~)*R#lGT+RHf(1Lf}MneiHvkld{Zli!qLC(HtZZDwhyMjrr%e7e2OD7a2%t2u#GN9WB>+N&J&Bfn3AF+H7k z|5)2bHKwLYg}*g)nGkq#o{)P!b@jDh3f&=vs_`V7TJVzMy2d!A@3X=;}isDy+wy&Z|lxxMtDTAy%*3|?n;;SrvdW5Et$k$Nyc6>EtPT5uP2 zsn1e5^xO@)CAPc9hLh&kO|i(~2l|fTt%eBbcstRW9{RJUcd$2|C*xk0$h2*^SMS_~ zReEJ)zM;jc2g)jDuJ5GTWiv>#Mhk-sQ*(CKd^-LWvc5u9LVmToCf+F?8jeIcRc_S{ zws=?miQ#9UGiAEc$7zGNa6*iheC`9R>hJ;8G?Z zkIbR=r_bOK>Yjf}-R?ckLA_F)r~#My7u%HoLc{*rp2mm&<2I$DI`l+45Rmx2*6&`H zHA~sHH?dN?&NS%|z!KIMu-Oy^5f4&mGxBg`j0BHFZu>HaE@7?-;S<(N+ zo!CNA>$k@Lo!-ba=BSjSam~#N@s~hfuB8P_LIsg$)`BQLb(Wo;%wS|3h>&1rQ|K5o z`SNZQ%Wg=V`zYBDCptvmDf;$|r>KL1f+Fy9L^s-MhvtV==R1F<*)`9QHK#sstlm98 zjyScRTBm-WY63PuWWhnWj3IzN7UFZ(XPZH~a*K%%#TGfmg{}0Fi>UoN+2Lfchu_<+crCwteEm200&RiJTRxH|$6$s>6`Zm6`H{0Zg-4Y@#5Mi+- z%ju!;f(Z29=zp%5B9J(h>{vmYTO`pqWXD5au@J`gf`X!bAGmBN>SwUb01E5hzZWH^ zg%y)U>T9!i)A1hd*STU4`gNDi7`(ve&ojrVH7BVxpVD*L8Icdob~|G$107?2+8mLQ zt7g$7;a94f-*x;f;XBOOhW$!p8~k zN^+lV_6I6Zvb8I^xw%vrj;r=*x^|8#>%O@eFAg2Kj9EsEB!APgyYwE~;tUdQ=bkf* zFBKbJq*~8lVnV=Ys@FJ5{u}`6d48~{bo0XVE6dwOhqt+Zs1OAs5Kr}huKj(`Egh!j z+u>Snj9l$PM2Hf?LD?C`uZLx~n_$gMom4?fUjEAiRiN;WGrctWqnx#=gQOy6B{=uo z7xP6q+gI{P#QkQ+9c-C!KZ?B4jm9z@cW470;r4iin+dsUX8nIn&)>YCYz<>RmZaXF zrU_nRUlHA!P(2Bb^knZW4_zt+jOr45CB)&>D;L$+`;yI%7nnZqatlC9)%Kh>4p4iON)Po#S}GO!;- zF~t&cw1D?xxs#|^&q{k5kv8ZR&;*8;Fp(u%xQ--;rD{w~Neh}5bT?Is9%mnFEWtQE z&-TRY1wul9Z#2KKt3_^Tv(sClUyV#&s1%iwRA4wRRI{Jo>YJwz>MgoC;4n|U1#;~(kH^vD=UJ6Y z?tWSfIM+19R>{gtx$Ti8zS|Idi7R9I17$2U?p3*tqa0jG2i#WbWR*joO8uqsqjhOx z8f(rgJJ<|b<{uX&_>mq@Z~kOqhk9?aUxQ(L|2MMt@4T!PAbTincX}t2=%*5lW5%m) zQZ?|955G*CqbY5+BJHU3qrPL>>5X;8dti_fFBFo+amLfN&4Xrp>0OSA4Y=vet%uTNFL z3%^W=7g_Tk8|mZeV;{a8sVG6YD}XEYnu&1e1>8)hm(-Bx7}L#@UIZ5>)OGfj=$mam zMe5$Oo88i;W`(687eT4C`jNFmF@UghPKs&UV%Efyppp!1VgeZO1KD#0+C!GlZ*Ym-=sHp z_B&5Zsw2^;z@E@|@pT)F_&jcgFdyf4)$2rKsW@JU(87_OqSgA?)X5^> zf5f{+8O|0os75zy8_b3tfwQE*oL6^)MwSLb4~&o0z`e-c9@XY3T`C|E7wsLjvt=s1 z${)&@7InTlzZ%4)qOckuf6KnVmgmoqXCuO9)FsJ~$3{b!paJ`j{lzd5~(Zbq2 zjN0h9i2TzWW$X)@gOMhRxVCf=sD*)FNexwInGZZ@2wIH3Qzp4Wc6nm4Wz*g%oYJhu zWl@q%fArM?NrA<;+jh3_3*jX;vbu=wG`kfi8=9~2TA1iJAWo=_N42Ap99C=3(vjc? zzC0$WdNv~Rn@RTdBQD3bk84RgE#OG!Seuth(ij{PZg-r>NpR=~J!t3`7_-B?VP-@% z0`!8I4Y?ixadO7uwVstuyz1BBit@!R3S&AP-#JbE#u&4fObA*hMT#)o+WOL&ioS^a zsOz$yK=$IjlwLGx7k{}k;jhSew46158k<{N?56qhe$%YKIbR9R>=)>Oc8kW? zwo2_h#NxJI#!!hn!zZ5nrcO+BshOq8?WB3mFEGL|y=XkjtXA{X8IMnFcu>!$5C0Gi zcuh-~v_S_~0OnU8Fu(snG~i#EzQ1&diPmK?}C0^a^ zN7vs*luj*8`sBOXeHU9_P9haGbl`||Xchud#hdMWRi{+vIf+nqDS1+Hn>DH*Z7I*e z{kSp{oI1$7o8*~{sJ?`Q<;bA|VOrz9C8FSoy_MkcDEkoEu+Qvzv5KFM(vFlg%y7A?)I&@6npW4ZlAema%JrkGouhwvHh4`98_OjX3j<#c z|Awsp&(8+`*>L+GBpHs2bj=^lg%w?zRiSmA?ilLFr2R3aiCwDTALiMU0FsQu>m1%o z7jV=Rb3?1Pq4M}8z=A|h@Fc&{!yE9o1y7x@7~Cd@&nava4;7UFr}}W>xZwf#F1T>> zxN$qt)J)`XTP+1&14RY7j02eh@q(~#H$G%CNxE)9C6$b5iznSZ6od;%ykF8dhtzi0$&=-?+KDzkUW=YZMdxC&ek6b{W3B_%Xp z-dLvFm!ut1-|r$~Q?2$M;r5=BWBCv|msXR7JFQu0)96BF5B3*zSz2w`n~4S7^eYa@ z9^z;I6EGCglU#ms+^38h=ifpMJ*c|1#?8J;rNPYK02CPk3+u(LhPQAxAzKrK>I&s%ognoB>u-^Yx$ZSP&xVm=X;awF1fA9~ScMw5Rmmm?5g zv7;BlLB%zQo~qyTOlneULt}d0b2kO(SI2n=EQ#TVM0y3=h}upeLyid_MmVvx^l1uP zuti{#-L>?uLp}vNPjMsFI{>yQVBu{7g0%IJ+9aZPbwMY^6(qT-uFON(%*R|-x`BGO#_ zNhQO2oxV`>z3uDKZe`zz=n(CI=#ejd_2~MR<2SaS@ZYc_*e)wbpEWq+kG{S*^G3VW zw8x=x_VLO2o(Do-6b6|Xdv7=t3mjg;qOPk*JZi@d&;c=fJ17;f0Ft#nb>3!}xj<2l zj@0ocNs2v*f?K}IeE!ZHj&n;9A8XujkcIMJt$ERm3~KirFlb6UqeW%k%eX11lJ{3v z!b4}wJkvm5j~Xi(qSL5vPs>QTOE3&Swo9H(4?B?`fe(_j+NJd$SD!p<#L72H=yy{X1&f0>%=w4 zMQs=}O21;SgfVgmgDkO?8H@~YnCot&Of2fK6IZ!TFCNpiJVuuX4{eP;CD(#nmVjiE zfc;je#R+59vfJsChMP5Q`5s~>qa+7`%r=d=z9QfJeeyf&?1FaIWg1hN1qp{KirvLP zGh$gg7AKTl+;=BxHj=W}x#20$OgzX9|r6WWtt64qeMfh_nyWu!djq}hSW^u6$^ z6a4fN%T)G#cA-OtVBTM zBrPLppv+}RTxNA7aKe^hWBcO4)VS&@?P8lu#nkR(hZi1ll-FrF?7lRg*c>58%u5-; z+V;@|#>z?#;*}rC40LL;6`oFeqD_02KaWyU7& zVB3p#BgLreW4;}#3_mWTW^F%fB>3684i9{8u|u&c`(S9$B2i`%9wu#nLPlbqD-R39kQ z?H3mJ9ug{Kdd;Ca>elQ_8_UFxx){%P*ezWKDxH)@_gy7=J<@}Y>bhXF!@9W1>D;iS zE#s3wkD}&xk^~S!H&(k9`hopUNR)3+4*9ujeDKg8<9HO4p5EqX!G+uu!5>dDDEeuU zoj<{m_vS7ljS{OPVtn!yV0d#3uZ=@+{LW7Jke(`sC2ixOyO@}#d38>+*b@$KGF zhf$*Ngrvp6>9CsOJ`V{q2eVsgjd8xG8xQrD@+Sv)5S)$5+c113m3LoTvu{gvlZqh~ z{AXEKD5`g;F1dedaeJ^x{C_|<%(GLN350p^nkFrR<1+xg!G>#r^6 ze>Ky%qF$`Wgu07@UXfSg6nkrqxyQ8u>0+XK=x1#dWE#1l^&U4X684L-FiewPPs=&X zI&HD|Hku9y;M;5z5p4SPX3FZ)24@%VAaQfZ^R0X&bJWOO&jT=oOE9&~*pKFvLn`YG z-?4sC=3`hFb*SJLs!zts?mVJPwj>T^lmM%bfBW399d2~wlNTSn^d)3gE#yzf2g5Q# zJwHIQ*MQ>#^M87CrT;&sA?&Ucjv1dyoldi3UG|p6$4D}q>rC^1SsF;f^d(k)q?47L zDkKxtl`qfx&>RBlc_hMb(7@BZ0H<$1Rql_ApPkc(L3C#3z?xF4e644|L6TED@LEsf zI(1puZQXT8=v_~B!9RGjr~C$(#eCiH{D}h_54RY*FvwmvL7yG6H)vO=8+$En7uAyM z7&aF1PEA!mKP>Tr+-#J2i%fUEBaqL%a*qQhHZIErpIJvjzk;yA9E>+mgdIBMsFYbn z=+`yREgOS?&Wptx5Wn65d2$uw#yl!Y>`3jou&(&*x3jWw5rXQavJmXGbY$elopCvG zEW`=2dIr3{oxJOUTCykdTcOAm1yI+Q11ua7^LIDgycS+iqGRa3X>SR8LM#*gy>VR@ zQKm3`w}#oD==K~sL70DC3I<_1c4w|afX;m$KgQBpW@~kIRzHx%EwSng?A1fCAoR|e zLzWj;7RSZ%QMJ*EB5iADX4zB<$}f+Of->}62uF5?p({%vsv#IEcF>=^c)M4P$VVS< zx@sYBfZ)q(W+&dQJXfnex2$EWmdBj(e+(Ndo8q2>xonFqkRlcGq z&jY`EZk*2SPs0qatP?!J`BH{B@B-#8#d7judQvv@$=!Yh{bQ2H=UPbPHl$;tz3TRd z_)J7p(n;Xj*M@PGn3=}&XX=HZb6<3tphgy;y z{tu2M_F$NExYu%*HyU$u_N`Q7L)m2n}DlHmpKmVG~$GHd<*07t(_QO)7IK&GoEp@ z!Bkh!jRKD}8!|?(iR%-i(CWz6a@Dw!<%%|r2aW0bqI4UL+})8c>yuK+$!FFh_WhjL zrRuh=*YsM)gO9!CuENfVJq~#!9J)-h3(N_sqY?q8II~sJ9apdg+^W~}<4`suYVxF- z2fGw_SDTezXvMctZg9U`ShjCMQufniH_Q;lIrN)F42$6j%+11b^)=t&wLf_G`0n|v z=p}aXHvKRa6@)b-x5dm960Wqzr!^Fim800@i%_0Q<)~6Wqbe(;z_eKzFA9U(Ne(e)V4n zF#lcisuh%?y0dkpm>khwJaQgT1v4KGmVX}&N8u@mHDChj8ulNWH~(cJ6r_2@f7d)mK=Zyj!cG27^DqF-lVbyE z-qLT)g9m9IH>*|3C;;>yfBhLD(jFCcUj1Wf$Xbcl4?FYZ&L>T9u-B1sIm)GDwo01s zIng`Hk%Fm2AWJ*Q@q+8$XTsT=8z?G|1yBG-CuQnP(IL>8sk5m?ph3!ey5h&J&D`?K zCbumdymJMv=apCa@boX(jzR?5;E@f~>$*Dmqnba$90UuT8>c;C{%q6(!*Qk*(1mk^ zq5lle%~M+L;qGvMbI@T^0O4KSN=Sek$x|Nv62V|KMzK;6eErRE$i0v7EqrYQR+%8P zN4TFf{r%)2J5U`k15goM-NhPWtUPp|d2x`4l?twwNmZ`6Ust1VMd2rj7U=s*1@E*f z@s&9|$;)R#wbZwLaUQv?(NNU=^7DHY2~N*QuQ~+V~7}b>1zEjG1}g(g>YWN#`PsyLurWu?k5Uu;;CCdJ7@{8{KO{DbSl| zgZYE*;qd%J_xKms+3iU|y7&DDEMcqM7VD%|Mq0{cBKibbdPv@H-E#+Yuf${9UWpNX z;LLsvcZ~C?z%M;#3>L>ON}!2)L2Zmy0`b`4ZAQDL#Bgi-k+>-V{ZB2Jgy;;E1{TC? z!+=$UB*)2zTf0KJv4Q92MiLg(EW9VrtX{m`&l{f0 z(aya4;@nY}?wKr}Rl$el9Bg_l)j%GyiM4&Tp$D7-v1)nyj>TUbrN0PeSbtH%5;cE;c z!{<9h41(?6`KEt?8%HlSdFOkKq3BY4Qq={&kxchZx^`+*iSww>h)g?bu8a>#Vt(nZ(p)2IoP;82cU`i+}!RnR@P@GK&=y)@p zO`D*7ckqHd)zC|)40{cpN@U}Rm;L--br0lr$zLDd6##CR1#r8}|6gA3Kigi9;a`0N z|8-E(D)_H+^_oHZAK_bmC#|K~hWSAzPv0~48auI3fta-kW#I-W!)Du6x`>m@xm558 zdbVu!+{&Ya%CMp{}=QBo~dZ%fs zI`%`*f}h{$nHolkzWM?~p3G0QHi_Yy%MUzshv>@l8oaeUFJK*M_s*FtrR6yi#FFyyXm{v4=2}4EzMSPC#52=?M;+m zdkjqS5MT#mkOm_e^)QBk0Twmd3MAEJh2*}$se2K&W%44#VSTK8X)wBIFpCO5g252LxDJ8 zdH@GZDlp31i!ck`27te!)$sS|ylIaLf;{_Xy)!SXV#JVWRtfV=Fo|k3<`QRk$z*~d zF**y%ECileea+L0%mqAj#$07ttuPxeFE~A|jyyI$ChW^5>(cSCoHEk93p;~M*!Njg zuKp2f_7tPD`N^~?$xRc1f_@1+@VOonMAUHwKwx6ITctKGu|8dC8`3Mhn-ykqq!;>? zCMQzHlfx%BiN}oEj8%LI`yT!@_m~=7+~8fR^E;txX%5B;QY*En7Q))Ak_$T1YR{_< zp#}uj!;Y*bQ2-++#z#;ULCW?m38JK}_-e^BdG0e%9aBfAeo#$rd&6{GAYJ#k=~+>d zm-b|t4=D<6D-JZuFe`pRbn%w%YckZT`_cA3?9l9KHW7&=;Zb^A4pKt>?WN2eK`(Eab{LjdEdIRI ztiId+!ZgRG;=r8oGUSnQ^n5?V=8$e{my5Bs?*oQjtai7Nr2j%!Cg+WWm2nZ zX#?Set~JZ7@ST=&o$;uPC6kKp0wg}0fU$Dvw{b3FYCJj5%y(lqX8lF(T=myfmz`RwUgaLc9E065N%l+q>f%?H6QPsbixBlOD@4bFk_qi_8bRJH! zIi#0hez73td?N!E1PT@CIOO&BMWzk>SVp ziW-Nto99dSEx_)*%Suz^==S#&7K;~q3NP9tl0O6OS6?ssnV%I*a&;Cr=!a-3f^Jzp z1#AVl0Rr1&_!2urfqkeHRJTHG@N+~OV|P*zcKhdw8+(i_K;DtUTSCsJr!B z$UtIoAG8r3{0QNJ<)W|asKibj9I-wE1h^e9bVBH3eI7~KeIS~-3(Fm<8y%`$t(6bj zg$pAGUWvIO66>#(gGNl%2Zh;R4gn*k3Z7vtytMgmMxqj;pyQwI-{3fdGklC9s}`az zf*ic^0Sh1|5|7_VGT~C*e*Bk@0Y4XBsd^(@PX`J0YaC+yiJwdt(8 zW*~93oXbC*7(MiB7{7+AOY7w_(`&hzYM!hQV<6p1>xK0+=%5BLSyHayZKapSS06dD z+pU>!?>6=Mqwg6Gwm($iCdG2~Z6QG+IEXWGEQT!>@+1vQ44gF3jpqh0o@E^)YckvL zCCqvFQ@J1&;b8~pg<4+rQhn!StS2$i4q;g<{p7KL|69Fw@qd_deJM%!rC$1?2=`n3 zlK4Lc2t5*>x)PtbF1?J^>0vd^)&+;_^B7mIB5!kMPFSxdJB%@*K_tV0_8^fHxPEV^ zZTY}+Xrq*HP2^Y_39WgxjR^I@_^-H1u^)Y6E!FGxE-)I1+>8L&-LZo?$!i!h9@tWiY-OzwXy*OrDccEBlTW9}=KCM7zcc zYx*wqjxn+qqruL6H3`DcWEE-LQNR~k1ZCkWi&s}Aw_ArwWjSh&?xxTJ*^RbPv&v|B zCMlH!g|Ak4K5yeHDbaw)O4qh6=%X8D*`X>Tbd`~olP0j%fSP3AIlJ~8P$}2_QDTsF z)1DegTp#9MUQWQ6x%5}KQRX>l=Lqp33R@`&da%E&t8<{+R{E95;cfSrqF}5GV-||-V&jSadO^|re6b@&6v-oI{ zrmD(Z1ro24-{LjA*^ebsM60mn-eY4?=-G@Oh9O(ls$k5O;dS|t7FpPY;gwYt9*-#7 z)=+%4r9HY%yzlP(_%D}jkQ<%KoR7}{+$h;!$zDO?^`A}XKeE?({--Vh479osQ1+S) z%nfi&TxkgXF1-R&FxrV8%{Bm&*;r8E9a7MDa-xt@z9<>ZUbYbEvyr+ThyrA<@wyQr zPZzJ<-hPt=Wv?YT6r4cz3RPtB!9v4wK0c(PG8d8kJt%wS2THFZb+~w0U0V#vrDCDX z5-;nbf$SA>xQyEXXZSd5OI5LXMbZ6V@@LR>|4#fk*7vWbuYVYJ{qK*k{xyjprDR@k zn{=x|c=c3Y!x&>G%3DnE_FYO?1B0o44*^7vunaS#g!DlTv#;h^Am0@*7_*e2zX+tS z%%0RiLG1oS2C>57MenNAEsXe7YwZ{{ijHhg?N%<*cRfx3V2<@sL^p~6YXImQYl~a zU?ZrB^)Cb`OjlTt%!_a3<#3v6sHI>LuBMOHiit@8!JgO<4boY$9EVCxm7F_c?P zpYo-sOo%WY-`O-2XL}GyiV+=iw!*;W8|W)52U0XCG0`Z?Ppa_yck%BZiOXZh=3EAY}K|7l>cojF@qO_?63pVb7)m6u(Lb!6Nj2 z9fg6In;SdI&{^hdadp=?NF)Q|*SpB3N;+uu0{HR_zG%*2x%U zE>H3T1s|lP#e3(Gvl>NZ9h8~~DYT|-?En#;Ci*LqI&-EcY?HdlUG$H=4q=3jJ;t~W zI7;9tVO5(@;Z4Q2IvaKaR6<_xKOY^w>Bd9RV-w4TGc(d?r$vFI{&djTO~Bs4Gd|AQ zi(y%4`2l9+yfYSD$-z0o)V96%E@^-RspJw~s7->As|%7Qo&&eiPzP3JEk8qR0l(+^ zncz~quX!r-NXuODT(;{oH9YnQFh8F6Fmm1pcl19M=*M6@SYqhYS*4ds!+9dA++df? zgK*I1T9~=a4KS8_r++r&b^0rN>MqM{uIBJ^Rh5DBk?2K(JMn#galDohvZoHyQqI`N z5j&mv4$DZwb+4QN{)e=vVTAJzzp&Wn%mk(Su%*g&tEPD}*d@>YL>aq9@O$O8+RdX= zLIkeaWmCHE8#z4QQUPHUY}*P_Sqt)J&fHfYZ5X>BH(Y@ff?;30+1bupQ_5~6*W~j+ z_Lvp;L)!CmQ?rjagi(jqmbT&BfV= zFQjrCe%!LCY)aSL@ERt;u$6MGcwt(Z(mjZ_xd=KZ_I(U=F)FYLs5To^S$|TPW=FFM zD#YIT7|#-@j*yX|=us{Jq!7%t7~cZF7+bgINC)fk#?;Rc*wA_;7aqp z0O@N5=gdRT0Fb`2$#Q^Jh72R_}a{ar*xCv=rSbk_C6@uW)z@pQo7q9>oS!|oaCd#<(3`rsjJnN&858` zT%B4#%B(FdSSnpW6rhYpMdsu|+Cl#p#xC#A;su1o(j&_GEm0Xp!nhOd8;yuT8@ zlBxh5|J-YHJcI`uVAU@d>$conK$I2h5a{^RJTjOvjEl+$fc8{J)>I$XBOk@{;a+{4 zvjVO95x^1=$z}o1yH%5(`KWg4m`p(?n_fK%O8joR+*QnFRY+II5MM=dDMO|qrCi{8)fH4B2$SA! z7uI0F&2cikC4ih(^VaZlw9HrA1PR^ZOy^Ak=ZHM4AFFSWi0Eh379XvL>It#jOmMGLyLeg# zYh<^-YP;@2*kak}5uC_wM4>1d43rynuD|x6E6QdI-q*Aah+$vr(xd-Cx%mOvDVQA& zN*a;M5?^PTySdTny}4X=QQ3f7puu%2v-jg1TlSPstT+cMEb#bL#WOs?LyJErS%8j2 ziTdFuC9yS_x8t<1+5LO@L+We{e)hd=AA3r+77tk^c0{5gF_CJq8HL==rCidGRr7&8 z9zNWH=`7y8Q=a!1?geo*7>3_=4YxH!0*w}i<>1|EhntGqa&M-W#?2BOkmv_T8;T!2 zEmSv{C_KmXe<%S<4~E~Nb~oHc@SzqEAZWhB`~i( zdrd*0Tz3lBl2vvAu|%Ls&Z18jIXW0cBGGb<4z9j+JzAhSni;(bR-;OSd*a4yp5JZ$ z7~R<+N9$^j+|?!F2Yymn4Xkh^3>0l29CD} zYJ-mo4O4Q(962Qt`akwBmG*xeFvPGqvP2&wAC`P5%1Q&T_Pn&YCdw8^jRnRGM;j%%ezd9NnsshwJ0K6(o9S-XGp12P}a1TM`TGf zzBp$fE?7+^ropkK%q)^W*wL^ujRlO5Yyz(AMw0aW=-7P#kIZdU*>-WDR&1CG-Yn9? zwwD!&tM;n}ZYYbaDBin@UdYj=YXkU?J-SH=*U;Cn^#>KBBg_%wtl>A5k9-H%V*2pV z+FjX06>Akm6$bAbuj5Voy;6H?H*D<0Joz#(80*%F)!H|=YQLJ29%v1HF<};}d~x~H z_5)vnMa)RX@uxTDt-|O2ihM)Z?TAKs+EEt0>$sB_mH}s|DC;J64>`8s2K@%1qr^){ zARK`xM6XQu+rhnBS)qBQ2a<+-{%>wh!!EecX%Nid)^&01rtcY-v?{pkEheQO zc*-XlZCAbzBH!=!*~~v(48`BWljo@ zDF)oG_Fu_f{~&w++4iP=2d!+q2>`NJknN?hLVKmQ|5hASIq3eW@lO~oTnM}Kg&o1C ztb-8qsAN~mGK9FZLo{G#OV|!Y9{*gwDe%F4Fm$t&n)j{c=dgNHSC6OytM?@CNmVF0mIRzkKT&C6if zilDLVA`!oM;>Rz!o#M%sv*Y=@dx4&bG37*OL;a|P;znjlQn)#O=-EMG-4h4d76!*5 z1i~JxVI_{PznEaRJZ<+pPIP6HaZMJA5I-US?>q52_HPZ>z6kL7l8ptLSyY?L0&Gc> zw|VzOOGA>oEDKn>3n{~~wN0fhn}%v>mgd^7G+8rAK4f~{6F+mlnAtS=5DV0ygP}D} zLi2O7SE_o0wi2B=#WEjM-hsh2*44?^^gaz48VqUSb{KP$u(8zVA=`7G?1YtkNR)5GEojxadvjJ#2mj4Rdo8AJ9f7!U9GhW|SWcG6C0R8*D4z9Qfg2+S~q*WV?&J2zj; zcSA+EW<F*HzR%mDXir(SQb{-h_?;0~@006;iuEL0eHU&8yjQQ;Tj*NDOqe2&* zbZcJQCjCR=2HT(<4JTaD>u>HIdi7gOvC zZy2!4U6Fio1!q2>88U7>by=du^Y!N7xyj1z2qI#BV9Q>ypU(e_e7`th*_NE-I~|Jr z<4I4EcD)#XXC7w1ZW$tu<2Iq+PHdKAq^ zSbV`?ms(C*PNm6UoIzG>)5$CL-o$#qHEnG7eDGdeH!_yZ{b3pM(Q&F=Y35Vnjjr@v zIO?;7a%4=ALhjZ#@ND9!1@zz>Z@ie5J#%P^TP~6 zNuc-@GN*1c3W#4}hGixEUmLxv+SChZc1VKp_@?Njl-;&=U={S!Kgf7F*-pLE#g5cb z-@kmM$8tX3gVb2lCQYbzxhBJGCgSyl%96D@jLRZ!x_vJ&@ETA)(p?PQnd~s9riISo zs2|{55u}N4Yk9Izom*zRwd>t(6+HZAFzBcSrfO(?%h-Ru4r$GT<=Z! zz2~VI(XbFJbrmxoyoZnC=;3MPn`K!{)6z4E9u$)ZOcm$yw04|%*TdR>u;Zq~=hwY( zBQO(7WHQgwL-N>1<$F7&Z02n5)?p;~#xWa-{~m3nPC3imRom@8UOoEO&bGy(WmXWD z^sbI=(?{fDRtoIqO=QnKN+CEbm)mXBv;|xq+G2`(`-+ow8}yP~`-yQoE{v zl^c+P+OBH^VJse7!;^T}tv#+XabxL)9}dEQ3OmJmsUJ7?HX^%ArTLFLDc4k|Tb3yf z%Y>GR)Lib2NhF%sFEbTjnHBhv2n6DT!FyIp@N>B|DvJC#SiN!O99nx&K>>Tsr-_{; zsWfWTSZl-St;ZCtdSK4IDZv{3<3}zjJ%3(zws0R-f*O;N)rZ_g zQb+-c*6lCFY(6LSq18sJ)kUfyMoQr&i(fL_{%}6c6o$jS1d#`%l3oXXQ0GP^8H}tL z?Sn+i!a7H0>^RRr(1VbBn+t#D=jdlt!#@u?9SOf2P_*=@RZ>|&B#nnc+rq)hOLR>G z#u#|*JcAv*v?q(9kRCittVcYwX$t8=G_LmpM((U0ePj~}+-9x&%pMqMEKxHwtg+ST zd;OXxod-TqC;I19TZ@#P&DJarwvq&*Vp;`sd1)b#pM#0E;9ADNQ?i|{=N@cdmo;NG zNpaAu$@{`VG0*f&vcPE5q*JY=A4+<%i|qE*nuJcjrt2NOrS~qd#&8hsihE(e@NnCjKO*~UVssZTM^wx!k6*W=w|~1GjdVI{)T1(;6oolG zY~rJ zoe(U~A3T)_rKDFA(-s#2+gX_-m9Oecz!!$Io`%1jiJbT>%(@2sIBFtVpfIJ+G!^91 znK~^RjGe>DDNI4Whtzct(x(%4IIJyRkD+#rjmxVK;8#jyi!LqjKabG3QrO3MpK zdZl4Fzxw&4Uu5sFA6DhB2I^@f=8e-LjDUWAMq;*(76}a^hojtfSZR|zAYT0+CGrVO zh);B&kI#u4)CKRm2^TiTy%W05PB#ja7Z=4KLQFrQ#i26xdkXkoynTuzye1m}Z`BSQAaK)&!b=G!i>K+LRT<3GYlq7L!JT&5O4E>M<(SSTjR=v6W+S zMTBCcZWDBlCgvDpeQmG%c#*hUJIfZ2mZ8BAoRcA>ww zUf)3e+Ij`T*S?K4N<6;_7|wb;Gq;jV6Xc0Gk%v=BNrCK7k1KA$RygLF#@OX;Zd0U3 zN)*VuD%bMz=~WwvLXJ(wJ=@CYULx#ZSSk!27>3x(lH*_4y6H8R!89lJ`f3%!YFLEY z$17oyp~VV)FDV)?x8C3xM^4&vsb{Mb)u*8rWwf6UFvaWb8xz$h1qIdF597#LYI&|E)y=RC~SIoEa21XFS(?{7hdt@IPy>OCfv@6$H?6 z>rbeQR&T$3J2N06B7za=B@f0{6Em)w8T33lObwf%Z2C=Abji3+zvjWsqq>Zp1*3lp z@fm;nGcK5X2p?uaN6E70)Lim_cbD|OnW@0V61yvd?_DQ2rzT*37fA@rg0*SK6OtWqyDJ=k9F)|Z}1N( z3y4ZDax05%IRo_A;$wg2oSd=ag*Mb^q3tP=`qgV=<)q?YqUs9BsJwtgfG}d}(yP!# zUQO}#J+`(MZyt9Wq;0q+Jb;oG|LpzpX!9)t>(na^Oqefqnu0>m;wwH(iJv{`-~jO* z^>fzq0*5-L_X~%=eA=IWoGj|g%ZcCsxLxk z3^s-0_LDCEG5I33T{FlGLPLx>`}>&LBB!(7}pA z=cnvN<;10jSvW4-<_d4SMQPcV&qL!^8|}h5np1k}y}8?Qy09XI$x#VME<39ZJ&it0 zJvH21qzsCYsv!x-;jdTwDJOZnC=kfF#oir!R#%ex1fsrsWk`W}-4>hrK|URh_e=U+ zsY6)}sJhjCT)PBW)P1^lkE9>feTh*>NhgzTmPYTODcRUgpe z%5tTymY>CVW*Ez=$=OoU-#{qQ69+#+VS+30#dj)wt!H@YiwalM{vo_S(g<$T$s9#4 z=4hqahD9HDeZB>bYvTikd+zjbgUN%xy`FAbxWQ^JA5RtC^ji{rq_{GS-Or9c zYs;;Q2)8STX_8I8?ardk?B_es>ZgQh%xbCOi{LDY=pM4ly^e&bKdvmM*2t4cA#Fix zB|x1SFcs1or{66vX`oj8`H;Qw2#t*ae|;j*8as8p#Jsgt9#}Y-GuqC`q!I6lOI6+OFgh}NI6k^uw2_U>En`7 z1Wj+69y|BT``m|QAb1Vv>DsI8HPdJ}lB?AADdd0WR##GQY2y!XadXz98YXrbaCa5I ze&$hSc{Ms-5?^A0uCcbi$`=fczPvh8aaXk2sSCGrOWzi@WFk4A2(FvjJ=S zqs^oE%em{H1nN-Jb6s4bA2i{UBSq?gM}?CXbkBpO?~Q4OLOvO2E)5Q z;Ya!we}=qox)JD>CxMFGq&7H6mX+mVf{YU09e%z4!4M^X!e}bKkX+~fRl0#0)Whsc zzt>^#EYbyI9x9p&OlYs>!t!DV&#x+8;zZWr_-jn%$w)%yvG&%tG)hz?Cl!lezZOE% zMHJccgk&Q%IF;V?mgS}=*WHiPtsAmxk)tJ|J?eUtz_rykFW$q)v0)cn4TZsy*1tnf z%Opm)vBrc;lw?or_5erleKFYu!xgCJgiv-u5Wj%22TX`Pt+@$4ES+Ar9 z9@Cr354ypsLQ|2vLXihe&ykHLTRNBnC(>402(laHMAs=cm_6WcA(gTl7=wi15bDbOZR|eI_lB6<_-I3vyQ8jhQLt};) zyUBd8hSNp7L$nvM#*7m1)D)KeRBS*sBru0&JSJGf&Xe?O97#z-@56_!qDtwh^Dn1H zVv0u9?+PlXIfiUkCiLAx>W^{frN2lq(G?Nf;F;@Q@OmTjME6_CzVd74XKLP>97UZ= zfqbMPbL-1*+c)GQ%B|_G?&EFxkP?iiJ;N;1lWhDgBKZAeB|R!-82ljZ)(U41~g zE5?PpT+SfFPDKv}^2uv_>~0TWs}^Cy6XNVOhmp1BZsrk1s~9B(@C+VLJ@Q?q&1X@t z6IPzEMzrNimW!4}*6HDlcR;0J_qdq2vds%M;V8FFb2D!=Lc+_Y{Q{!RXT?loIvlXNcRncF~UH>3^|Jm{WId_fd0Wr3IJ6_k4Oa=%UyWUVua5uM*cH?r`{!HT&|lrL{|OfOQ|on8 z6+q2c5i5&c<#dO8{{kn5pekT8ib}j$<}5b;KFAB#2)xzRZp3qHb31YI96kN@R`+b@ zMDr5N{p*X*>E&QFU|$im>1Q62+~SU=Y)Y_)aS%Q;W>znW<;qkLR;?%)^YzOs{=gG^s7Qm21q03;VZ zgQM2`#=ev@aJK+6@iqr|sN42tT$Ej!tD{omt0mp*58|CZHwu<+4Vp?iaOla!ozH#T zLRj$H=9PCjp;Xz|O^xU@L0`R61XxaGO7dH%4_Zuc>cU$dVg%l&-t^ngetaUKu|(5- zZ<}&T7zSNrb%EB_@BvMAqLW2u_mgSHP)nYlGNzUHH!p4Y{J}SZI?%P`(O5YqidcDT zrgh92PQz};cU1$;u}7K@0rM5*_q@hs!WcA1Wh8gvMpC>1Gm#M;@=B0zdl?&5{8OG@U&$3*a!rV2s>D;49etzr<+`}O+V{(P z3vX-U*R#~?iM=F!GM%YI76e2dD2glRu-6zeO$--0j@U6P>3FD3U9a<&b=6 z#Awl5DK{CUt%cgbNuKc;3%@(B;Ube7<5N~#U`Mjv^WPbK=kqp0k4Q?EfL{jl*CNJc zUxoa#{O2zid~IcFg;y!3m*V%z8j>}UJt)lQ?6;b)ZkuUv_-aJiO*X&ZCR%WwXkD}h zSURbAna!~iQpeg1S?G>%nVe-$+J1X>>*T<5B8Kj3UaZ-vDLPY{>^?lK--hm+S4m^| z887?5jXaMRj3tZ}>>;mz#gV#1%Mdt6Sk=WK#*5zL1-yMbKFxq5XMA-iEz#qPi*8Tu zmCg7HQd$TWwM+>@BX2i9zg!FT4u`o^qKqb5&NYjk5h~Ew=T5twS9n2TCw0X@M^KlO z=4Ysi5jOsE&4B|6G{(g1tVftrO->26nt|1%Dzi#2IZH>&t2wiA$>%dG!D<|QU9k4Z zUtEC^mS0?fGVHvA4(0XfaHqi|jzzLij0L4QiEFA)I<)KG$@=*Is8t`UsUao)YSQ{! ztNxp1{kIK$Ubs@nSVM^!sf}WvFiSk?-uBQxaRtzRa|M9a+j@qm^}lfi0>TuKh3gQC z*Z{5o)bf39HS1!;&}sTLpjC8jyC>V1ced9bUBT{Hz{XHi0ierNCP5gR*8xRT8fWRW zjnJ2=jDjp_blXC<-j>YEm9H%lr8OP0SX>qwi?U8rU$%Rg}TxGRX zqKWsI!M_U0aYBkCim6)A>v)BgV%VV$>ehk(<_df~Zjzi~8zDuqBx8~k(w;R8ktJ#*d#r1hYjl29I!4kc0+$axrQVGvfY7|(Ph2j z!CXkuXn$W^OCQkDpZL9c+XGs?wT7eO>v|CkPw}4VsLwELn-5O_DqTnzXPy4|<&b$t zWy_n-dPuMvIb&D0b-B$1#mvx!KiDdV8r+g}eTvh0fA#)^Fzf;{a$B-pvHGkC>nT|Q!_+imw1q4X z4b$wGUQwRE5&VX09{r8Ub~Kw?wqxANhVWGD2ggqnB^QS2x}We>21eJ9!|9R<#Ybh7 z9@*uE8JU;g4CwU(X}z)zvbaJu&Li}jksKc1?%%VlK6%aJMR;^GxXq_ZM7-QK#fDMm zAR6eX=B6IdGblUzQhz3P476M;&YG~EB$sUSE0*A;p}MbH5$-Oc(J|o%^(0O*KTOeH zzuaDXWm~U#8)i*QdL+@A)LE)^2z^boE{%Mm-pLUz^*zOpBw?0U_|7=H8Ex&9F3D*# zz9q(GsQ1~J>66jT>ZWmQbDm!43rgWZa5GEBC+0JwWAmkls-IIjx#){SQ&!YTvywZG z_b+~dP$IB~dGT~V(3$1b8bFP-($Tw#;1R_Z52t5f#hO=AdPtQt&`jvsvD69QDGrzK z58vX#y1230n1@@BkZQr&T-$fn?6|?tpA*44Ok+Y1>B>Ve& zG6G4-9rIrSx)LILcg|29HFH;J>1o z+v8i2fkEingavyE9EnU&3mQb%F3@^*(I%C75-D37&t#K$K0Q0{3%WHj?z?P{3{jrA z+y1%Q3byy$_m|UEkY4>~uleV6RV;dg67QuMB;Ha)b<4~c6SUb8(UTKN&fAGP&(juR zHWn6nhReBS9&;2&O;EaeFE5{3^)odyJpktl zIL-Kv1(;M8cb|QY(3nvWlpzn5?1#n)Ii>OQ_Fb#RzX)67P@wa9-+nQn?phiVw<75| zr0IF}N5QsG$=>+ORDnNC|NfuTRnTDhuNStTHd+9XE6{6Ij7b884N>TIj3AIJnim`@ z3JU;oO`NhY>$U3f{(GbeeU{>%A(zpU}BD<;KWc)=H`1Wt90v<%BFZNWx_z}@?OIS+)^eW(mZS0)7L#xkPiP{ZCMo#%NIwDx7fed8aXx*|h zhMKf6y`{(o0CKe;25POe@ntWU4-zrq3jwNtIumWI!e$(()_S(ZFMkl71N)`C4D#wy zimfqX-XEX}03g>OfGV)eP25{(9O)0#TDc6T2!L8E$G=hquDX9y1*VVib(eX5Q3awv zwbp;33fRhmYONf#RO91@Js+9{)@!iiAH$wZgNFOeqYv>ph=!z#VWuT*1XoF4b2w6GP18CF zVRw}C;XqV@TB?6g1(FJ;^0#mTU#K69cY(cjt3XW$pAPrj%lq&Z`mTsXkG+JT!HyO5 zx^@&RUNAtwdr{WT*U@UlKua>il`=NZ_TIdR;EDEfAlPI3QUMu#;KF_#cZ~F@An5n& z+C&j7bi96Yp$VaT?feWAN8z2%CRf5BssMxkkm-BWdU)V1;EzligLB&=rl|}&KN;}>f#7F^8n(Y#!m)G=xQfhSseW_}E(y{}<3b5pBmZdl( zo1jZ8txpb74hhdOqEtrs(+qvT#t%5ux?SA^F8_#j_3O-J7}O})G6pA%qmh(D@9Sv` z3sWjI6Vi-1++C$FpD3YkBMoe}}DLRzXG{^IYVRY~x#1nGHMX?^Otqy9ICS5_cA)P-l?xC@SALyjm z*^}Uzlxd9~_zg9}%qBEO1FvgKm35wg*R|=!UMt1Zv4=B~ezy=mX8yI|1-d9@P;K=7 zWvalRH1EH;)qe!6|C{E;TN(|A3!qRv{f4;yjimBtssM)YpQr+&PXC@NFb4ic9?-lW zf73j*mD&BVkDZ+zd1Y+tacPn{hhk5Ff|07i(#!itNpb7-v3xTKtZkQR;%#T)rq>1tBdjL)4l=!#qsR6ntJuhk&>Z#f{0_Se^ zz8uF(#@ZqYrOI&=xtE^p6Wf(rxS6*UNxeWzujYic*PYS;U01p}=FOpK9<_tslvJyE z!6)TLMq)?`Ow(E!lEYj;_mbXEpj)K5e6Dpi9u0S_vJWuv9GbXi{NnIV182{lht$+Y z>>RrUg`L<;HgL##N)G>H%EtY3q-!@Loq9D_G=BWUH+piZWmn9XNCcp(QsW9N1S%YB z2Y(GQobgYgI=MaqvicFMF2T7mI_ngy($()HuHmprD02Si_Ex$jm%ghxd@dHcE)CwDe#IG6=)0H-S$TSh9o`vq( zu(uqK^~4y?0{mK;zL=zbwF~MjxPL@BnqpWJI7R=HmlSzrlFjV3zf{Z9F@q*u@r=9YIO*NdijhEmesKiH$YfG!J8P(Bpj@WK(1syyZfzC=Bg9NiRhKLs~6pWgzQ{FtR z#;-8KNxp|uyUH>OYu2Y*{n9<>E|Wlz?uq`=J(j=eUijv3-7_h8!2hLSale(7Ft z+bh)+)w0CjxB(UfxmQ5AJDzYsSp9QR_@?a+#-pRqP*X_mu)}7C9B(*JPnQE zfL2Q9Af%TipEi zNxB~Gp!k6ic9usAVB<+sel-OT{;FvU^}GbP=GO7%O6ew!zL|}hy@`+A4g8NT823c} z2R#s5*aMsyynn-6urtuJ)UyR_|9>;Pz(%9^J2A|38P@OS8z%=jPE^ZVG3HVTrEi+c zg3!)0k6qx!PF&^BB7?~$_&SZh-BQL1qx5mTTW)%S&WZIKjMfz^mH#2Oj*JFfi+V2* zO%(HfAB=%(%iRkZmcrYg~^HZ;Dz7w`;e=_h}3Aj3`ErJhea5yuTp4E?E{7}%1 zxWmYCKS3M+vITsm^HT}9=_|QerI)9;Yf|oMH1ul`(4R$z&Advw69Zy?lI_gD4A4bU z7g;?@mo`HYveL1He8Fjuwy|$me2n2HkX_CQmS-D{iLElWjSF|#A&==nju(nUu<}6+ z45LPn0|J6n+$XLvk2|clpC_w)9gf(kgelS6lP+unj7=`vdEFEWXc2_?#x)+CjRT*@ zO~rdsMpy9_zVxO~WKa>da^e&$6e#O&ii3w3vfP8->3lDHBQr15|I&g0uM6raFp;$v zWdUhsDmxh{5mctVj>)ZAToRiO>B!DuG5i!}mYXwBl6|o1Y!d7^aOnyo`~$)8EKy2X zz4sLj#cqQfn?~>Dri@_ozWd2;alJY-bss!IQqM?8Pz7pVM-rt`>UHoC?+)pzozUt< z{#c|TWB@h&jgz9HJlMC-59p{8-@GYMjXso*^45)U>>iA9oOtTBak*Xo)EwnL(n(sT zERS??l+!0zZ14iBiyL)T5Epzg>bG-T$}OwD*N=8P-x~00B|z_h%5kXs*m>?)`(sZx z&-`?&e7!cJ>e|!B{4w{N-pkp|yA`)xCbBfHZkG(32HPFBi+NksRAw_P2eMBMH5rlW zAA|)fG2rRx^@SjiV|e*(b)T3Vc4tv){TeUYh4che(A1~`M5^kOSvEeD5XF1+C>;4M zw`W{gbE%#bbnAagfxL1_@&ISYm^7D3gmrg3sdnogv?`mzlXb~vHPWi*(z$AI;05nO z$3*@hpUnOfMS{(DhE9lqSn4&#I-2wcYnF}NyO#I1{Nk;2W_NMfVq-t^R0@7_8fnpD z$8Q9%lvP-=TB76Box$9M@qH+2wYb9C4w5g`>!?4XR~-qs%vyi(h;lLfIl*XztP~x` zs}B|pW0rBlDm5F|y0FzE9m{j0Uk*WpT0Y(yF-(UC=r`f(OujG z)+{lUpMeT*o{x1D>D4-KBKg1RVRly62TbXsl=i?%OKTMeb-5N=3>ryMXQwh?LU-{m zlof%WAf|gD8PM&e_TFZ#Hx;v6PEVPllzA4NP&PCw9?%xA_w6DT+;ZNh%zk=qsusYw zT2a~VxTdqoK#Z)|TFNYtVBuZEwsz;Blgu?X}Y!CI+BT1khcv4dJ|CoErpt=^UTN?<3;K3b&26qh}2=4B|-CcqO zcXxMpcXxLu!3i4N;VyFeobEoi-#*>9>Z|vwTDxlf*nc)vJT>N+W6t?aW>M${KGb*e ziq+ww=9*cwuP)bA#=dxRK1__noh^P)CEk$_>C%)BW{m=Bk|oU|L$AfzbNu@U4Xp`@ zS05!hemLd!U#etvxq#|8$<6iz80Zdlx3{c;Nn&gLqj#pBCin*xg!(-j1HA*p@@JHuR$ zn~cis+y0dlr6^`MnnWtyqikfY@9f}9;Iz|W6?vp{ht7ysD*Akl#>e#V(zPyh1x7hB z*FxzAs>!LcMeDWoamN1TeEgYohab^w;4{aV*v&*2$G=ofeke>do9jy&-*F#=PX4qi zDt?_QvrzKJGZzCqzbMANlc>Zg!Su_Cg2YK{*Sk{@Hlr>tkEkqx2T#=v=18j~Sc&L2 z-mhNG-S(C_3*|349M~R|Hnv4uaynGH>N^y7tnDsxMYdXQKYdzJ{b>h)(Uhb~Sr5}={kVaq zodq%)=Uwbj;kVHIVHNG6jFz?NmScH07VR$W$eR_tfKF`~Or*dY?o+re9tAr$W;Q%AcrK77>oe-gzshVNL&>j`yaO&tPsq0* zOTZgPp9Br@k^h*YfSk4mV3hlrd_PXNiMhVbY{ncdxlS8`^A5kWXt&B<@dIIusq#em z!i7S%MQcH`*z*YITxV5@v(K!~G=7CNy*4$`Vc!-3WD4+Y)3|W_+rh{RsC$9E&PZpsnt&pQG!7Zb&Yj2@C@K54kc4XhULowiW@n!VJ*if_ZQ>W=> zb;*9hn3Z0gh8NSJ*AL&YdUHRmX^(2{adtRO<|=7EPm5yz&Cpk-x=Jv({UJ50d23IS zyos+H#xP3#{Bmx-eC5W{*_-CDRU=-Ahtr!IVN3b;Ftd;x0>>uw?dK6wL&*$F)-l>| z8FJTD@@vfJ(O22=DQCj>zH#g4V$Q>dpZ9*={lkXn7qOTWen^=JwByl$+$r|IlSKbs z6UvQ=i-}0c36F_ThmDVs1&xnT(lf4a%hHgEiUU`jej-?1+Fr?6g}$-Agt@x7=9eqb z%8f{hPl$iil2+$4gI(PLD}I{+yDM5Uq^zIRkXv zd%FhZ9nRZkUjKM8P=xP3MG9mPg^HfW)Fcv?n$`v`niM_ys?x|AI$GXL&W%N;&W(Q> z?;nlAO0fXQ+X0Z5^nd=f|Hb{P-<4obXmwIU^W+81)acr=F`xu1oIY17CLy%$&*C*A z6x{UpApZ!5PF6TqAPXc7bEMEHe?)|)hKeQfP;L3xiSH{WPrM*|s6j3(5HhRYTAdaE zD8VB$a4roNskKDsok7NvdxMm+ksvLQ45e3|?h%lxAiN|`9Y&)*L_#%j4EC4T%=F!+ zAF7gw1e*!{3`)=2))q%+63ucNYg@_+>vGi*O?E5bfx8!_ur zKa?tY4tBoP$3i{9`|feW9!=1xf#(T5Qpk}^bbHKpT1bc4{nM2yH-Tc=um7U*n8mLY z)J;GZM?1hN=Ze+UZ&phmq-ZMh&A!saHWO@3H}6|FV%%WLwnn~7un$xp*`e;83SI~2 zCd0xC&D1MpeibQb>lN`py5pn^dBw?D+574~dcx9Q8;2?mEvy`Pj`8D{c4ue#&z??O z?;U14Cf9&Hsxm=J>=bCd+W|#i0$TBw@(Yrx)JTezA0|P~zLWISfC}c~YRgDaES-ar zEi3TZld(V@CFwB!borP+=O-31+sC3`a(L;u0~N1sFy;BStYhA3wAZB6TVsxXw{d*F z2vWjZ(00a&`_VK=V_X$2D=r+ufooi6cJEZYKq)Vt zapO^D{3k=cD58jFj3J_sX11?#b1l;y6|u4%yXm*HF52vu?pl~Q#x4y=hhvy1W#KLU z@BnG0kG;t7^toH%Zz>Lza~d{t`!FnC7tixE=Gv$&o5jgxS;G8i@0|0|PN+S9g2SSO z_qkVEO->7J5DG(4x*gMR)I0A$M(&{Jc56_MZ2^klr{Eil~ zgpQbC(ffl4MpdRHlnDO2MvaH8ob`JGwUV6m4yiGPXI&B9vCAE05nTht`w)#GwHpIqd!DxNQ4FLh#FhNiIzTl=Sz32PyZ z&{c@~d|;!KxM$}mWz~Xn{mJ*K^WL!D)%m*+jQMCyK)*8Bi}!=)@<)oz*jeTUA4KYs zaD_k?UTJkwwxL8iVe0=DZ-*u{V-_$_tqUeL%*vct6)_fD5)eFUK!jgmB<)@1}ht|R9kgb7<}9bbOHA-98NQ@n~{2+-_79r zfQkq2&#WrOF+HJDW{(i?*NeXXEfXG8&ce9wRMsQ~8nd)DaMhZr4K z0gXtO3zN#A(1sx8?tc6g>)c>V_4f0V2dv0NHzf`TcW&J;W=IBCYlrAvWa?RjopCxRqLGAIinfy5#TtZu`^hv10B4WC zaHd>v#j5rTXB6$wJ`T3+Y7mf;?x89#FhA`GIux(RB4y9`f4p;$r`;$7t7U^CGY8 zR$5_l2y)Hs0_C^y{6%L3SB*yDStdi0u_Zd|LXeeSx&g-CA)*{zUz6l3c0r}<3cv14 zo1uMR@^$}i4?amgBjpmP3Y;UTi4th@@tRvRZ}%(TInmE(lel8$;llp28{Rah}&9IVx&pBUm& zmx&-80s^VP6dXci@2Emzlu4X@|5C!Sy=FDli0iVC@qKOcM{~Ubf7n_|83gkS9?!J| z@umo=kB?&kSE8H5YYcMfV+_c+`qvuztw|>ZaA|7}vT7Vn3Tf_D*~@Z!xbGD+o^=XJ zMd-q|z+owjI>5d22sUdgD$O6%&wAyUDyJ^HLEdb-10BxWcD;kdvPQ}B+~x4n%b@oBzdAdP5n zJFU1eAe++PlzF; zG_Ov@+8(4dCW7>=4~O;d$OEm`x4=Iv+gVdP+3|+sJD%VHl^;XnIMc;esDQI{yV z&U?CEb7JZkDlKYe=UMk?hmQ3e5n%l6e)17YhrCFKtwqloJ2+agn|qK8Izp|5P~F=8 zh>C5ETIuJ{)37UwrrGRp|E-aku=?I%lK7@^>E{5M_(^Nwnu5hhq5KKeM@ID!S|P0d z_@1Ik(VyK*zLcY-tl3+e%RTuBB}pQ?d%DqlPW@JSkDKvpO0$RPlufiFlB)f%kYB$q z{3Fs{dZr9sWl8HHUQOHR3@onQIAdjwa?ggIsz|S51-$TU1;z} z1SuoYA&82h&k4AVwir2uT?qK~5*jZvwtm4F6M4GnlqCB_X|;24()PPA;_E)zo?OY& z)p20%4G@c+f% z;E#)2f9+G6%L9X}N;n=OW5CJm6B>%cn)t)4BP$OePDMEwWhOGFkE+*m89s;sI0W?4 zQOX`Yd?MmY)lAs+8~9y%K=kuYNUTmKVzSaGr9o13uP;JIFw2PC7AqwdXj!if8!u7IfGyeOvFR~kGJF1$qI zj1?S(VgjdI`nI(3$psG;aA4h3c5E3cB#mrn={Xc^a$wEU%mi1e9#Wu%q}eMXc~Q}? zNo+@_KMbjUUkg@j27}8KB`&4G9NamHN7lf`dpv4}Is4 zlM)i;D*OqVT=+Q1mI{L3oh=aV;SNaFr%83vqo?!;^0m7$HMudlILYrz6Hn%Eb!RvF z)5!8NUt^Nj5|SXncLq7JiN>UFM5MzN3NRiL>3xkA5wZq-{wR*U{iZYswN@*)1xQn& zBNCU(?gqCe4H>+}Eb=P}caF1QaVQ>KLSIwQ+$zUjs(tr${z?ufdbcL(Dn&0ss?Ln% z`dmy<+j{@iG;aN^yQ(rRSN#^tw_Xfn#nl}cP}@nuk{n;L7Ve3yN5bneB*k?n4xIaQ z9ccwYx--!NjldBKx9K5bxPBK680Y)1W{fG~I~s#tz2y^e1IKq0l8NMjz}X|)j4FM6 zorwi-oO+76lH=I5J*f}(M-6V0Xmh&MY^NOU+S0ZM&&ciD3qm+cgJ5mx&uo1j<&RR^ z!)V$Z)an6=*UUQ{UOzmCIjsC{&1!H3zltuDUrf^JDBOJ&{pm)sqLx4;r-uB&6)irs zp1NPWvE>R>kx@JKvIZ0TTC7VD9`%)7fGly4<+ev!lV&>-xx*b8KVeQixzmM8N?1ZFDI1~xu(al6fJB^w_S?qyDQvz*clPS%P z+00Eg*ZXC(vpKVeg`_chd`GID6h`a*qz8&8X<&*T`$Pe%p0a^vS@Ar~d8#+0o#bce z7(H_Rd;2ShdRvLQ!c$$wrg>=MZQ%ZOGmGvatM;_`yd!ImqNEuCuR6YLs~OW0|Tx&*(mT1ziRC#1TAmEZPckre$S!*@$46O|j+c zn-Zp92x#kpg^l>ZE_*)W77I<1d-u207&RrMz0OU74rMw~k4+UxMK<;MxyXN2xAr`x zw)>>Im|=5&LQJeS9@F zultvOI_+$%cU$!qfQo*JSD-8{Hsbry3;qCe%;n| z#JQkxYNrxM`aWO%@XId~sufUTnCpa=uq-!i1FhMDOl(WgLQgGkr)CI3TCgk>vZqbP zb3RCRM_M@3oTSL%X*OWZf7%?FJsyidhfSdc7AjG#Q*qTyi~+i_Pja{01yb1~uQB(7F;q zM{*U!H{#)K@Wq8PM-NGmMwzU`hkI>OMY3a3xRW>XWpGwKHj$D3JbWx=BVl;CI*^F+ z^?a?5Da~=3XoF&m(rNI1$FGLOx9=(e_398Yo;i*>;hIm`=rT`6RMA2$Inl!8rCBSayPjI(rIz3{~UA?~VG z%~<+lb8$gVq~H~_;NiFVmwlrKgFI4KDVX8!_Yx|Uf#A5^u}E*)NPY`F2Cg^%wDvTb zmPh|Sy?|Z9JG}2UL&r zD^UU$6fHsCTZp6<_1W4M^*>2A*({wT4uGZs08PpMon-qjoJDi_&qk_B7(7pb{Z6Be z^Tc$~nkP)gLRWMR63tl({w`|Ep4bL%${5~8SX~&z1-HfCS(8_JGoi~-koZlROd*Gv zz2+!gdkKMw4Ky(mp@@Q*NlcizDugOnS9Akom8QVl&e&t>iTm#L|3Yuga_9v8*bwUOUyYL15FZ{XUwcb1v;rN?dc9Od0s}qM71BGgE3l zeEO_#-c@gX_7a-h9vxMYy<7DU6`{B}vPgLSJC5;3#7HIXEkj%N2i^g-2n7Wg7L% z-UuL0OYq&~vikDzfzGPKqG2}lH7M@7HW{3MXavS^kq~T%z#vY{gaB5QihWqF_5>u+ zLPt5R&&_vXtT1*haO~ltQ151JNXKh<(Id>kW81T}&IK+=kqor^uQBqm41jnmav}r7 z+h#^Myr=-<7Kz^1+3>Ip@F!qb=+IkLxMCA86Bj-Zet1G*&0D$htAV2UPGRzcfm(1aDQX4Lt zI?8%ft-m{RA9)^LJwv(=Pe@_ZBtj_lN<#}0TMHl%-Elwm(?4FHJ98^!`eM`* zZ64p{KfpUatL#rt!ehV(5Tq{@`)OA%V84BJ5}b*5@}3yZ_M`Ub2GUtvZ$c)SavaK4 zmK8%`#qQZzzw)9dvl0Ui3tr6PERIWpHmlAGe{|;CO;LAyY4S5sx8$eY!EtP8`fgyL zoLnDESTxb^{@gFOs?&V!^@R&m>Gp*5l}awBo8&P^t-n>G8s`#KAzh}KK(Z#&*0dhw zOlZ(focCSSN zI~fRb`kqEbJ`Q63nz0NG+R!7O8zSRt*IF>=n${2sByzp{oUSJgDD(I?=5ZI`HnjFm zTzO$t!TJsvDhBCDBY|IlH6!a#Y$?zttRRmZis4zhs_6A}mJRXRkT*>fp(x=}17T8c zOu?-^zB(x=Xu2LeeD+n)x7bYuxBSu8SkBm5XnKCQNwf8w@6SxGACJ=T!??n&YuP3j z>Y>7A#qC^tn%otuUiW$j6Sa+nfu?2B#!F#g$Z2SBM8 z1^EQ~v#bdYa)ep^LKu)r!({V2RTlldnprhWSFajQ9LKq?9o5;XCv0abZ}oPPJ-^tq6jmP$mPI*5vll z0G~`hvugl+ny()O_;kVq@M+Nbmi>iKn&$hn;|B|kfxq)f-Q9TYcRscJjZXzix7fe) z$<#aBL-URB##?|-X2<}a3}pd68P)5uSf-->jZduCsH%)p$(l7Xf8!I;FFx(D;V}N< z)A8TKF!l;#~37 zNA_-=#qTVZpf068inc~{_a(Av+?3b$hlJ`oq~R>06yjvqlYZ!McT9`W_N`fs+ZkkKUgG(0*mPDKCKf!C8jNn+g)EnITkfgDF-<(GZk74 z%^yAsY9|M&MMEEyOt+CK=iFqH_hO3?Z;|)!6sAsIDqfufd@_Y+3iypr3_Xpie9Hiz z`Z93;;L|aU@(a38ax?Y=r^R=^_1OOL=!e>?YP0}tY~q^RX;uCX1Oa%km> z18Qx`-d4)cMQ(m$u{(9(Sqk4&dWeR?YI9oa-lzVD&8r*j?S}iEA3djX(JiY-M0opk zx7lU=Qo6an4PMwcK*T7)nN2BPBP{wl*2>#nC%4D0(>cmF8Eubnj6 zuRBb@Gx%SDFw%elbKY3(bZbtlav4jP>cNkGq{f^IeDf*=rmOVF5~bI#HzjPSYgv*k zS!-(2I4z}1L&YrnL+s}UM3gfmRu}E&TGfFnJQb2Ryj>hx8ZWG9=55OzIv(wg(P29U znCH*>T(2?|*K%oQI7Sgz?7o1*ps> z6Kq5j#thbl-{W8^aKFK=F1Bd*y#wVS?G(m>4~oDry%WO0369MF{3+X5IIYT-4XzuM z%@2;#jfMn-Hg~-OJ4{weSir|1g0r?%U&{xe&_hW4kf ztp2JXdKwhYxM4oANeU`MA1F=y67%M0SEaxLs~jl!XKRui3U3T&l9e2R{Ma%P{Sd$I z)Z@k$UCBCZsr<8J`ID|)BRM_C2czbmlHfz&#N=mvG4~z}f1&jNxTVLyAlovPl&E_2 zjZ3zJWY0>e^WJAex6#UQ_8Kmj8;hrIw&&6-9(`IB-_j5(c8kSn<>S}yy^rhG&PV$B zC4lmq5HvT~PbPT^RrVu#tgzv6-WYv)1&Mu_2lND6GHqGkC<14f&dLKN3))CAo;>W7 zwrC_-o7c1T!*tPh!)<=YdQ&1rl||nE+E-`&)fIzfp!!Axs_%|NZ5Sk1K5Qf4Al=hT z^?jL8L6c?9gY^c(Ky0KmYP~M`HiU7-h7nyS?*x~9kvqPAlvJ{0FNG0mSAB&!)~alv zeDpm|+mMv_HLxsGzlC-g#(5XkSerr`|3P#&MU+kULw`ztE#dNPPayf~fhqAedH;{% zk)$Rup-axV1qoKH4m{TT0v`vqjTN#?E?I)5t%Pq4?`iE#p!)7!qPOeYtEJlDNkzQN z31SGXIi?sWiy8A}?z$NxFjPJ9$j#mz-}aZcI7!XXYk%5;1Nq8k@a`HqH*vx^ZA}AM zwOot!bG2LPecI2ov>o_~hgX%I>o@;UdB5ns9qTKi*8o|B{{yo8mD>AvWN{c|SL16k zd(>rkO-dmPTpv0JXCn&~;S%d^Kzp{57W}BMjL~cUZ^&{`2av_>+x7je``WeZwG%gq z>o<$n-{EjUMhf0sfOv{NbU8gTTc(*X+enNZH09h1U~1@QmpSw`%wM)0gwPH$D{vUK z&Cbkxc_eo)Ivy;rv-_9kB125$S5#(ef=XGW;QWyF;^x26sJ-6~X z=nY7htsJffjl<`>qW!!mjJasc(xxhN&R*hZ^Au%-yTY0nq(bncbL{s=wHJC^bl;hz zFGZO0G-om>Q`xxS{Fl}zD(>8c-R8;~9!d8h4uwH9#k=`1k#uKoBD{&{&n`@i*x&}` zY~b^>*+7IUyyB5UafToLg4HG`!6X)0)6-^ zi17juxAPaUwYsq;LvElFwT!1h)jJr0^=UZ3po<8#JOwSRmH_EjJ#yyug)+)i$jD4y z%v+&4k*2<>yxgJBY}EqfpA}j5_)wm|Ay|tyX2xG=M5(Z=G;2-|(klDhPF|Ndw$!CF zcD2^-qP5hah5%F6wHnY%&<@($!VdJ6x?m4E_2%UwoE4RU1$*>t22VsbM z)i5#qHI^1rjv$x`BwRLpEm4jiO+n<7{n|q}}xeb^39i457&{dXs8^NF(!z364jf`gfs2lmxmuN9Ga+|R2s-$Q=wu8eMs5|`nTE2@5 z`&yiMWq63v7D`F&wm+`f-=`62O)lj&#Wkpg4zU2vUEfNISe@M4bnZY!F-3J_!DoF| zA?nO$(}FU+&JGRXrHO#eu-}cB=%y^NjALDfK1oyf*4)Zyd|c<=@rOXu_G&lKM5qo5 z!ZOyY*XnuVf;&QaV~!OwmIRSrD+ka;9oePGKFzu}awPW);O+T6Mr)sw{zjLf!)og9 zw5fD4#g9)z2 zc1gqAVukO`khI}kJFOa_yS$qSJ+C1*E&o}ysdBO)h61W>2KeCoTix=%t<_$lgNPtv zSb(YLq$T;w)Z^|b1W_oHhMvm+nTB6SGdiV{miPKX@Dn`xGJHU^Yp{tba;}zK$*8>hvy2SZe zqdgDcFAL8xOnC$?V+>ePVWC$^5;xEfVUW!2?^(U{V=Jp#LWTJoYRP~->KGkx>%@xjGgtu8Rwyzc=}I@ty8BVAVD;{=Im;(VNx zW2Y#vPTClldzXzUv^Wx-z{;LT8F@?ma0~o!JiPc1OzV4$XX~dc{D|n%qrfhnGT}sE z7tbe7j80$|&%iLaUJ2%f7I1)4s9zdr#|mKU(gW>SW{=z!5Klf}xrI{Z=Cx)Vp&%ZU6JeqcNPjVB39_YEE@h2@z8TLYU)($);q%ap*GLQ(Q!Z}04>Fq3WsgY{ z&N&&0A+EdJ7!uYW+8z?6@NSF!D683NrxDHEG zY31sNY8^lAGuBFFf}|HRmYLN7Lk5v zZy_f3>$}AFj*T+3hEwL$E8lf=zq@x_moGZEspa!pqny&mWCa$U6Fqy0pTyEpzoOWc z@gLj7Wauh4`|0iCtJ`NDxQkTw23DdgQjfP8F5z2*gAaGMJ!bsmXQ^}Vj}pFqYK|x? zVLn4%OkjJOUyT&vH5;9_#~=6!o1YETE5^8wg3`Hoh&c77NBr6BZ{P`0rYY=(%*{4 zIG|{3AXcOl9-QML)$Q*2@Uq&xo$)ti#}@3d6>d&!iisJr!2(>w4es+TK}KX1#LVtd z{d>{KU#&O&p5#$g zEJ@3*1sBduuHlAo4b?&wqYg?e%sHGhRV$gO+mR;c)jk3@8JI2%WHHGH}Bq@FBgiguiMLm|+t3Mcx?K3!a3OB-TIuF@8hZ4R!#Z`%>Q#t$mL+CxNGXQ`R3WjGF)-Z=5T} z3N&`bLxfzP9MqOBu9qLN4R2=(zz) zdW*m(1z2qUKFVgi28R@I@tD%9$6d|t04BxksXe5uAth+gw#sF(fbYa3*=Nv^&`SIe z>R(SlU23T;g5Sjv9bAN-d>wNcD)p`WZsWPS%^*>Ts+AGaU`raw57jxrTe~dYm37Fi z_(=+87|oqy^mAa+wZaa^lX3gZnxog9Rt}~l_*R6}F~Pcz!ZFlpG{Ql5QrMOsW?K9Z$H+DLz#w- zu5(4RD&%(wt(_U-$W`|d{_?A8@+I?4`xKjj?v+m;_lZrJlbPsYPsvU$bIKV)|77kk zhRaJ=H*h3Q0D&;Phm&funaaT;ZqH4fptW}jQuFmNOq6pXNw_xu zH?uLXHJm=^rAP0V&wHI5r>8Pt&V|P1z8bqU82&VI#^3uYEbSlL3orIv+al-O%Wj=F zfPF{upQ)t(eMR_><{fA;gDl|P4U+Npbav5I{_^g!K;FOQhogbO&h#~~ATR3t*KJ=! zBrw@mf9c)*cHj4}b~OHFh5dhdcT;J(+ABdGY-B{4`g+eO&A{F>WhR;i$sT*%7<$o? zy}#?iu@B8$$K2O$-%fV#onLg}IeFu~10zW4?-82W8{gADgcdRR=15a(&1sU+_Y`{{ zuco7*&$NNTk{9ZhH)!()e!HxiR#NsWbhx$o-?5^^(~ z1G2qcAd1^b>9KzLC9Lm>k`UyLhZ@$NXypl#!n74*pf*?Hq)9Ocshl{&VrO8eR)DA& zd7$V7cf0kHrj!&b*el6b%!@|itr>;+)mAkyVPScEo5X+QRl96eR41?rj@9RcFtgYqVBm10WV zu!Q^y5s#G;)An)j)C#v3WL9$^Wm@X-Hxg_#Xn(kpRNGX!x0d;Tu6T2fe4={d zWX@yg<7x`TXUr)vHoKzc9q5fHmwZ18HjH3<*P7ScS{5V1g|T!-^3eD)*}oww_e-AH zt6AbI44byf5lb6wHbBk4)uW)zzuV#A$0lq(5>g{EkkIoWr+0mc&-8IJycWVOnociZ z+f3{vciy#W!83HjrMo`hets?~2bMJY*BO9(>u$&2ZJ&J3Km62Ok%&msXWsl_IrY1q zw8a6(@E4{P@N5ERBvyw-2H#F5f7rdP>`M zbk~}Y1bW}$=E(ueT#NX2)+Z)=TxR*(S)Ah{_07^iFe!Ko2cm6310ha z-naeYTbh}6@o-J=9p``Gc+|fBa{qn1OLuK~c?BxT;~fhd#-F7g@)CLxcdkIq2^_D<2=N)JpbJ_i6Sf9QPWAU2O)n*#Munu3nOq;c)aY$Pxqx)uRNPqMMNA5yE&E3F>JXt0?0>>+z_ z+GpSXa}}Ud8w~P}lXZ4-Tj%;yQIQ2hpf+{lWD(_ZpDciuzQD_j^gqzjr70#g^9n$V zLb{;tzB63YRA986RRJzMT=9wjjNwsGvSpTLM;Q3`TPBwgBB^pezv&20 zl3gt`CZ!w``B0cnyGfb(>Rf`^c<(x$u zH5M}`0nZhJ}R&455YH(*T7xWA5+99V~CZ%l_GYknsRC1v69_<`Kf~M}?u`J@Rp4gCXa-rmSY7M8nb$Pvr{NyOFq` zX&dSzjqgQZHoca<$G^UI>WXCm29kjP?n08V5Nu5i0&*#~wcQ1JP-_~k4e{=6l|6BL2Pmmz!uid+Uy6E`-;NJbKVmVt&Cp84eg=%B}SA`sq$KeE$$R5-QV2R;eiDKmEPrFg*6C6*hVC=oCmgUq8CH zrQf@saHTCrH(O4=vXX%SVI~1#2FbwVqMNhnt`)a4U36HMQ26MPIlt)EDt#93ASION_pz{7|IDl zPKRmE_1hcu)?qN8D1b_tgJ-an0H~BFq5Gd3kfgT|Un=F;Zt_M;)vySw7Nw-&T*bu|Z6$)A97ASH241ki{dg7QI`oc*no8xS6xM^?U`;OZ>ePZ4Y{76{kVF^vW6svMPPc7cbik{5 zl)m)rKK;|k#X9%A(Our&WQbFuNd&T-XTpp!ThTQa3q6rvQ%2@RpY;tUz*CnEs>B{u*{50i-U9dZFiL{xde=sFrz zJUSR1l@4DE%2L{iV(hrLFCj1L8j&sVx3MD^S+&K5=(_)8UX3L%@#G$$vvxi6^)4&p zI?ZgM;A9&O_TiytIgi8Qd>r%X_>K|A;vBk*t$mB-Gju|*Vq3&|xz&>xZc0GxY-1*+71ytYdX#TqRSLvv{gD7S>?s;It29X`aInqfs zKirDF+a~jz@B4|eJ$9Y8chr^QJhelQ*X)Et$c=6amWYr2Fy2)dqjHdokNqYN=NRqV zJlhVj+Q&^csy_Bu$1>5eA1&qzn`VP$JrdU|4eGnC_(S|{JsSx<10(}HZ)?q z0b2YwfZFXthcXtIfst5$$9!TfQSpjtrS_ z4zN~@8N#k6-?ghr@2CAlB>QT4H?!dilcL$PTlhi+5)MBi%@?-8#F1fot8UQ^{1VC%O@j%~ph~PcFGYOF<)7>;*~% zzd=doB^L4 z0=D^QHbZ5psC`*~=;eXA4qRC)hU$D;-3$Yu6y2r!x)&@!&ijPmqx~mu8cqO80hjap z9rf2zzo2BVoo?H{XoFYtAbslDz5Ay&?!0!D*j{h385)ovjHF;( zAQ?#QbehkVj)8y5$JqBa04DlB=VMY{@-Z#Qzw$BbNajC=@~Y2t5P{o*cpyYi48P}N z_CEuI8rhZ4ML<60Ti%Bz^}|MSg;@y_`jYpIs`mQJPC+81%WRc+u+qllByvzoyR4E+ zrauN%ev>Az)F)ZBb}2N&UZ{q zQGQ$G?EX`9IG))H9ndoVL)q9jBf0%R)c4*@VY=sHX9gpB-^Wnp56U|wNF2EI!a9W8g* z6ZPlQD`2SN`6C;{-YiW1S?MJkb8_^aEpKH)?9O7aB&9^7{Kv*Fb=S%Qg%DM`*F*S*Du)^?C%pV*_aQWzh`4`l!T1gW(dZ&G#Gzn zW8&qwY(HoHt85IGS2w&duPx9d0QU}N%udc=tp7Lnj`Rd5uL1Wi zAL*sMCS2E492+53H{VWIImSma5WC^ErrBPV%kd55HUAmb$rWjp3tNU+Zm42y5~z#p z$EqkY#2D6G%4zz80&nhIK!;UtCY+1mz9FEFeM6l#O9M#WeV<7CmAnhI8@~4kl6Quv zsLWFX7M%f)u2@UtZvn*qk&RJCb}9ZX8m?hR?` zbDGLORx|mm>Uy0X9A2<;+$=I^?0iQG!iU2c>FPVBLBE%_s*w*Q?P_f$DDD^TC8_GhFQkTKy0t$`3$3)==Lg#Ns5kdd@t&dHlZZZ}a=d zr(Z;my;fm6l7YSe;>&1l?2T{WU3g2dd~u|yjplUjNdM3t7SIY1j zd1+qWPPUUtRjGeD5bPM1MC0r_Lf0e_v;rg zqI5}jN_Tg6igcrNBPksM(%ndRcY}a{ba!{RwDkFbPw%~-XYc=+b7t-rIKvyqndSFh z*JrI2^j0da#m@Po{GlSCF0c#&f8ZjzR_uB-Of!l!41WoGJqEaRnj=AS^4^3z@Q+!eF5azsc>uNVe+?*Bu zMDAn<8LHQ($9CGU9R}P3CPh9_d9nue7j)mt>wjRW!Qc;edIt&5xtz~mv0r5box7e) z6#$rbGQ;!5jdy@~XS=Tln0L>by&vdXJqiKy?i4WZs5GUg0rRdgeI$H-)ZX_htL0f| zn<;Z%%^3aWo4Iz=A78L6`n1^U3?oCMe=+Z_Hhj)Ms>DmF0_I(jJ;z6ALQcV7%)9v_ zRdH1h=)1>GIOSrRP>Zi6=)>yp=dTZH3Cg$5S~q!o_Ld@t4O{)83W;W6 z(-zZA3cBaXKU?RZTC7;-|xd$ioFqev8&LB~uic?80 zzcu_`-`)iIeS#_nj3kVVgzoph;iG=`Peq5*0mqNO2k-tg3i!{~-7mvZNltXyUmA_y z{r9oX+2zH1O0zpz(mjDT2IFFiZmn8PA01RJUx14X~t{vuwv!R-cX_<0l*p=+#yH^o%!RI_<5|k0!Is-KC ze8ht!0{o*aOIZy}h!kk}y#er!6(>dv^-3D;3B0>H_=*UCcT@m)M??ghz2cAgXx;Vy z57r(1+P1<;>&X0bs7LTlR5D*Yf#DIn14i&8SFtLD%CLf}aV1%P+u zYaQB30C-372;PMgVZ-rA%3lhqeEjaJy;K0MQ&o$f7QdzS6LKL-WW~Cv7kS=7e;&J& zBK3ozed(=-l zF*l$#%Q76}R86_%LtVvCA$MgMUDAtk!CZ&y#Ude@G>uqHJXXg+3}Zvxs`SO3+hUmR zRHWP$@z4zE>txeZu8d@K3OM0k!oRl0k=VFJCHCfeCsi)R7CO{sU!-xPx{9 zEBR=nNJA08xJat6FR5%VAmtbcY&_U^+^j0=#W#r?D*!5#^{TMKduGa5RY zduFMFcy|uVM?R@&TxY*k(UmaH9wGX2LF#4k?5Gqv?SrW z#v|i`+w2WF!2;K?Z`aNHie=FlWQm)*7!}q`v~QJn%Q^D^)cB@k_nF@xS?5PR;zdGD z`)B9wFM9M}J9lG24(M?ERXsE#AK0y|s=}|hmb$@-c2d;YGq&3^K3mQk|A;A;8jcXU ziRWMURGAW85smo--pM_JcW!?G?@*q=JMuq(cL4x+_vvEGMRDWwT@K`%PnZ6(k#N_R zByx9}Mk#Nh*~TIThhSSdo;9se>glu{ z88QdMNXvJMCKJOCU(P-RsIxKg#pJntqHr>iWMh5SRs6k(O?hG`NrVE3-k1ujy}hz~ zUNCgew^G;x5~owtnx%#Q@v&Uc=E*ck`WFp{Y^06@P;|t;mJnGt&KKVe@(M_?exUmJtg~L zcWZvpBs)uYK$EJh`SU2pto8;C{=(g9Uh_P7b{{q&p_^axaRCF%GEg4$aGZg z1%+64D@w0!f~T#T@LW%qt74~0F{y)YlJ-I-VbabU10isD|44{Da(9x#R}YE*$ld)( zl>Xki3kfcVZled@gU_%0AhfF3(I8ZM2%;5-TWPWm%wR(##K&k?TQtr5im&t5afACP|!PNIm&KAj`!-93kh+a6;s27;v1VSycyLkGk#~) z0KQg))LSQy#qbVQt6TUhEx4A*O06wZF{8MS$-7Nt?f4}HP>%(}ewBIIK)a0tj}9(L z?e~(re|{cfO~r>l`$z2Vznez>Y23vnIT_J5H|CX%k^Uhv`~Swc13zrCo18hYzN|mG zapzkadb;Pz_V83Bf*9w5yz3H9dk&(wir%@$cT77{4Bp)1$S5=u!qK0 zW9xOKD}crzs)xu7kPTt80BB4jg93oYAki{xmY8!=(V>+S8>52IFViK0R>kG^QFu+k ze|O~QdiTJB2;$QsV=rAlZTqRDAW>3RRo1X-x3}gPB~iNOSeFMQZA_k0lnf(viQc5t zfOPL8Uhc;Nb0F6?I$o*9KL5;5Y&=Y`Yd>)AD2?}Ph$MZa?{gwxv~C3oK}>IbXKYv; zD>8Q-N3z`tBvkjg>|1fDuTm!L#O-qCMOdt1Vr*ezmtj(mp|+$i9^6l%wvA?j?3gTJ zpuhkr?3@3I?LLf^PKdGSEl^-kwM{^~{1zxYx~V?p?MW!q4koOR4?gx zWfJu~WOuBa3|$7xI}WQl%N(zw#C%73BQ5R98ukw$wQ~G>9OHa$(_Y`ShQU5xB9?e) z2x@>mCoKvv?hCtq-nm2MQfT~zrtxrDw0Q^kAG5k4Cx-W0Cl%kH`iOa zS+Xj}BTHf_Bziaf%2qbeIFW4doal+V!#lX*Fn=ISmaKKP8h@hhQ ziV}|1xZ1x_! zEQ+k;Q7h0_wH3}}@x5ho@os8WkF)khTi)g~!XhYvzn-W~>F~G`&-wl#XCiWm%Eu%8 z7EAV*Ulu|R(vHP+z5nGxt7rP&pe=f$xdhsgI`Uc8|#3?PgD%=7!aVpp`(LflS4g9ZhxS$>hW)(mT`p+Y{Zb^*kl zo#^YX9pW{Fcv76|eqkQ^RUk2ILS3RYp3W7;%>(t6n7wdUbpaByr$AzMUi_tY|5pJp zB)yI^f4^7OCuh6H?9U$)vxe`8pK`K{!G`ZzUi^}n4Habz6}=3VJdk)y%sMbT$P)fc z%+g6nJSApBkRKDX>qML*!Qha8NX!D_0wiWNDd|ApDG~ySS+ED%?Q<3YGS^U1}P6Z|KyH?{{r& zd2bjyed@L=-$Kv8z*`eiX(LLf@5T<<92v{u!n1sB<)ibnFUHSI6TzyQ_L*eJ38A+t z(@Gd@%vFlp(B~}8YBXx$-$SZJj}Bn|%CwCHhNY zcwUFv5;zUdcpQ+Jg&X489N9#9$@vKZsm;OnA)4ptC0oU6wvU@%#S&b|r|8(j%KfhA zaP(-C83M)L9~p8d5hvTwtBhR^eMfkr>~ew+J)qOLL(pT9Yan>7X?1Skuq$f}0;zoB zA&Yye-jLlgJ2&bQ>fCTRmc6g>+D|O5V>8oGudZgVeO9Z@Z^kjsWd{7&2**q%o7{wby1okxL~|Vqcbex|s;=!fScgnyjET=Cq}FG95W$OSO~m+OaDt zh2%UYA*-?Y7J08ps7)H`sIa8t%NCl64!0`y_3SpLY{Qu7Wz|q)R>RqPx%FBh6)~`* zKBmlTazG7S1ynaDQOEswpfB_MYaCZKsWNco3DvhoEIr#V@J|Ay`x^b=dW~JcQ0+&% zU$^?)HFD0;qqR@0zu?>s_rK zTA@ouby@+J%q!>oQsowT9ayzwBGGM!INi1l*- z_MO~C(yUvM4cYXE%$W5CvpKHUNu^5EG*YEv=OMAfP<7H+*Ofa(isY{(h6kRdiBQG7 z5Ji{TR>Uaf6IpW%6~5mC{l&PWw~7H0vr+tI5#8jS*C{*1G2&-sf-o3_qq>Ze-y~{P z5-XS^^3l=+OwtIkLwhp=U0GqsoL9bO-C8dDYdKu9I78ASBKiWc2hVA8Q~XMLqz+s0 zbh5FRLxHy3aNfKa0^rVWv>gy)V^*48i25ki8e*Bi2SO|x{soSk=o8+u0$NZ%Bte1t zm`+pvCIoy*hV}a`omS*(2aEchPPmEzZLC054o0yT1{5Q*jKCe0OM6#I3ErC@k;T!Y zpQ2)9IFs0(?gJ|1P~3U3=}S?d)FjYpQ6*@%FJsZRz$CLgRfG9EjKWd;VSPWJ(T|%w zI_if0LP)*aiaytl_q4woce1wcdw&{te1BuyQT{aU#u7m**RpH-#v8ug%I5%d%YHV+ z-4EiVGC@B!?XeBuJF=4o#iUO~^YIRZ(%V~)$tmhnpX^$rRvC_HFGLZ%jdwnKTZ=)~ zO9c;OZIPdrdcUjaZt}!jrFhKJ*~2I0^5U3%TJgj=>2V{5)!1nE#BtPsKbOQe-aoZA z6V&6Q?qrB^Kv@grax#-!Gwv(tlt$3J)$Ir97BuNX%1t?dZb`sbll~N6|C@2QHcs|v z+>!lH#@)xoi_!Mx*%?OrMokx$3|>96_fq2>c`Gh1gL;X58b)hf%FLl$)?J$Y9LNqu zj@k)N#vS&*8h0`OV%(LY{ny4FZHn~Y8+S7Q(YV8YH15tVPl>MgFx}r26!Fr+H&-iw2{7(j{>8YXdNS^KxHEYyRhiV$E;*(&EYSI% z60ubsQU6Qo}gvwXi_68;Ty_vZ-z2oT{{sKq_vJ-TWB zEyC|&b4lY2vZ(lsUj~vN4kS;6E|_J(iUu)Ry=LNrLd~@yh{G(&JC>8haU5 zVaxnel+*+1qkV-yg9)C~gaIS3|BeG*2f9!wq@d!x%c=1KbvJU^m-W1$Ct;l!F!io7 zU*&lky&Mq*IN*0`G;e5sa=?xhHBH0Cl&KIO|AgF~0?6H|0f5~3jNH5X=%!pwWL!t) zT_&0ShTL)GG}1mIcZ=7yFth-2htaam`1T?(2<;KMvr%s;zZ;w1vl0J^+)+JyLhf1( zIg%ccJ4gVz%bxk-HmNt3D!G{rAa`45IbZi3cMg!MY3W;{e=+X(IN`gBhF3yV?AeXp zNG>V|v!oThcfEF>cqe9k^}fBZz(0VJGl&wLyStSFR@`fLM$bS{Q}Ey3w5fJUopMWG%gcTWH;7x7bi% zU8S$0n{z|!PH1?Iig}uYih4@l{=TChfhI?=U-QYigDQ!*v0nWk1N=shgQ{!}keJO^ zOJt)dO`I)m^qip{#pZCf+AISSvw1*bb~vvKH)4?%NX%-b0nQzen9Tv4JEf(F$Hc4# zl0AbdkeEH4Hawk7_)%^UqQ`j{AHtEl8fq{kWozvccc|B{{)t|t(*g3(Cp>;8ryq%8T+)(-@F^lz-m<{UB`I(rd9N_{Iv(ei;Kw`FM^yVosOEz}! zUJ*#lE+{=EW&?j-6M)35z|X`iAW9wfPl;LQqMz3UYxd};Yr?Oh1PX{!^V^~)=Z++d z>8B|DOw7`0URQqi1Vkwo5G68PK$J*-5v8ZZtP)(qci@^pHSxCe`4SKNFQRk-h!PDt ze;)!W0=w%y`0xJJ<3ljR!=~t;nY%xU(%(CG|9`v)|IFM~y!pQ|cfJ!v=T?Aq_n!vX zKD;;Au`@9@c>6z1@jh-~GO(o>uQsU+%ywH^M(v0~!+YHY+E%!3=V+1VBU9cploQ>Q zf0fC&!U`5f4l9mWXt;y)4)KxfNeyAg_@Ot9jS8iMveOw(7|AYUv^O3Q1qVG>k67hg z?{t!4n{wG>yLh^(TGZC?8p=}&)Kga)h7trQo`3!-1ficJqcPIbBsoGj=6&xv95n+A zhVlnxRYR0m!Uhq8=)%TA4bIOE1x{LP^0KNkX{XGsnxS~oWMerSZq!f>6RI#CRF3@d zCK-}Mt4(^h2z+rbIO=l2(!g!i7rT3^g&0<07R*uFk48{R3o2#4p^gw@4={t$MKDW` z3RBOYB}%*_R>kzZwxbUgb+qGwyK@`H=TEgUTK#-v8AZ$g33fQjN1F!4JEqqH%eQTH zZ?%UXDe%41Xq=BF1nde3!caE*vN+PUG`$b-E2A?Lz$dd(UQFHk+{e|9^|G57i+zBH ztRpVFib(8RMI9M6WolZVK)sXPm>zl$QLKj@3brE{gGDr&Nv^8$TJOa?h_iG?8auPy z_BHW_;V>m+f+MTB;NlyzwKb*pZe`M{JW7;MkgLc)&`Q-3pzo&BcrEL1Cq&!hO^cLq z^DSOKeAZ>H{Ol@xnh-ie&4^)(h@(j@F%3o*<~5w6=BT+W3IfbViU5CX{h1gqtK0*qDOHpm z0iWNO3+tJi1I(lfU=U)o(rqFPXQDk4zng}p+KkNM0#$_O-2AO|x5CYbBK|v>C@xHT zzgzfkBqRRMoyPSFG!T_8y*JmdwBi%M$P($aZ-pH4!*xlkDi%XkOJ$A+^6pNOjdpt`$l(yj-}baLbhl>V5`{=SsAN;@k+OsA$R?YNor1)>|K`J8w4Jl zl#l7O$Nn7L`J(RHcH0v{xoB0lq+9aXwTL)xW@gk86@vHi?uxfdZ76{4v^)FbCq<4Df*{&!Aofkg2y~Q zs-!&prCa&N*rLxK(6j$E!S?U;?C+nKzi#^e2R)mXX?!D3rg*ETD{`S1nkanAf)OCW zT_gHo@8T6KD-tCMUk&2prmu4*5n=G-n1(P??v8mfr*(yZ4i}pje$za+(-6nd%{s@C zlP$Hfj!f>0Wj!d6Kn9vTpv!9o0hVo%ZOgwzvLV}E9Z9K~Hj1t6+d99vQ&SsbaT)9= z4P~b0g3`k1$hg|T9u|6|P%n6LBh;qN89!$NE6st9#Bg>eFu~UPyiFQe2?_BCZ^h$B zJwbP?77YkX{Md>5>k`~x#MC{*3=H?M97m;O3+@ts_*vr|L`VND9WPSd^qeJW&{wU! zAmbj$km-ncH6*W8#)hY0+}zKg{9bplEG-cEJwvto8bN&aISqqa#d3rm18GSo<%}%- zM=V*B#J0^>0{HL4APW-PBW=J>--`ry_Dy&8cURQ%g^KH(rFpp%U5t_7lGdAve-kw> zVoLnAGH;vXjGQ^zND=CXZE{vC=qFJldlEHGkOrBbqUKDp;SPuz0rHTaOgFZvh3l8y zkjq%e!bVAwXU|-rmsVM*6w>jrhr4LdTQuKeD1=NDv{w)8yjAEIRgOY1DLs8QY}3!cWNacvhVt!5JPVgy$lBVd(;%OI?*yc_#h- zTuAIZd>z6@LF!<-=YU5PSW{P%6)Wn>`QfaH@Epg6>rD#|cyL~-(7a#wg4qwr*$cgI z7%?@))KvyWod$avm}YwsY&z+yn3eM5)VuL9)QxD9{eClKIx@T+t34A$3RZ?q(=_#= z2ON1?AE`g*(R`e*Qs4qN4SIE~&HBQomY)|aT4~YPfA<9^i^CwRIYDh4RhSgBCN1LO z87@Sp< z(JmAqA2n=Z(i+CA$uPR;084EOHj8DlBN51aCMd%~Y<@=X$`rVD;bjXV!q9P@&sOun ztdscB2UI4#$*}FNBG?pp-{5JVuC=_xIu^pu`DCDbGzpAK5+g7Ki5QBLn533rWx`lX zL4w~7M_Exwd0t16A_%UNWPeH?GR4b{C-g3o4*GH(RmEdu5hgWP?knYDH>5<{;&eI~ zlx;6K-Evpg7F+ox9(*9j+u>VdZve;nYO;uUXZ8=9EGyTEVR|)$#U*pJjDeuNxVS@L z78r{pA;qS|?ZoKZsMM9Xz`m9emh;n<jf+BVvw_R9;eQxm z`&Uu>`{yYz!Uog!IKuY)3gPjv9OzwW_c9CB&I(4wB_!QQel$$v_GosJHsQs4*VN0D zH6jHx#kP=qxrqfTy}1L?z`Tn*e8?FJiAyo@k~m@>{0e6BHu!Gc!Lu0xjd=OMz%L}e ziwU69YQ@ZrIBMsiBAmp_y|5!R3yGZRw5Xt zSAcb-1Y)_lI6AR4i+wRRQL=g2NU{sA`$%8?klUleCtZFys_)W&UBVy_!rK874x9fp zve`th>e3gFSR3~;q`{h++N}wrG`&MF`I(7Ego&o^E)iCYOkF`!QF-;Cd?!QoX&mS% zR;LmK6J`bzUI;c?O$4#A3L(u|j1|8L@waS@Ft&^DB+lAWtINJvAegJnDZR_PB|69G z{rVWKr7IY@MP;GF#4EH^0+U|6){0z`{(jHx!{8*4gnB^~JKdhur0NZIq~|_&{<80R z>Q8gCnehdJ{8oKCu#J~xJ!B(t3340Zd$C`XOJ?}{wlpqimxJLj*m0gsUB5fIZB~9h z##kw6F(Vi;BL|>Gwcu*T?c`8yN$WZO*N;aG6tBbOPjT?TtW`W!7Q65oGvWY@k2R$~ zvuxWQ!L6X-yi(TaEMR~SOW{S zUJn&bZ8RU6n;;F=j(M==fXWc&PPXegw-B1{`n&MOR%3TD-kFHWB#JtB2w3XcDG{Gjs#UskhK$>hzn?FR4QGrXW&rJ9Ij5S1 z$j|Y)TIZ>xMP6M?U}QBIZJ=1w7$aPe#`2Kd(AA$5D9O>kVWDAPd=}AxR~>eLk%= zM(E|4@eEEFB5etV2N|_y)+GgG&!%GAj}za>4Qt!RS5snJjP}8H+IdYa>g)|SbAc2o ziO?%@dvX)MFG*SGJyVVrguL`z?M65Ptu4A<^aP)kt; z^EuTH9lSB&<{#YZu_Vb6Q$xsol>>6-q_ZSkS_OjAf_#Gh?8+oRAVsJ;Fk)d=_ahqT z)tjuL_;bVvJd?8wE(Eb9B$uA)R}=epq}0blaZ4Y2-v`Wa5)j_g7%fuq8Msl{5NNY_ z3gQAe-y!(NPNc80Wa9rZ|pr;{;I55$P6XwQw@ZpJ>b|2E^FU2&uk8D z7i|Y^Q%+MZdA3xG0+e2dhNtq2PnL>sK&BJ@uui*;<)E?X&n$p@B`kh#NUPQ<>8Ejf z;)~Pg-#;p;RA?qHqbFeR_NkbExz~v9YQrF@5j1y9QHmOgY2d(<*mT?zZJhC0{y;Qy z>dWI!-e#YpkQV`##)$GDxz~!H$7|rlTh==TL0Wt>yc+UM=&50^0FcB4hlgre=f zzCE6fPJ?sC(VctFH}Oa2O{j>?ONlo~6@sYPyj z3tg%)Z9nu~xjq*U;{3{2Ui!5Bu0zPfab0|jVeXPLCs(`EAKQ!8`8>t!&isp9ybeRe zoL20Ys1$@$*{B>uh8+v;a#tX8xCQV6<92f*75+0KrQXlQUK&qPM11g9V^NuGg7;Y< zm3w2pyH{^W;x4{^>}kUvg{vTEk99YGZ28 z;BNO`P$sR6^1?RSJyL)3xir2QU(c}T4hTke;tQ^|tgYmAl7f|th86c!=p(c;6+a#i zxVjh3$Zy&mwtu9^-H#D2is{N$nlLJHnXq&ZupNE244skOO__^nH0urVvH2{2*bqHN zIOx1z}5vu|`i~;7^iYzUk!>>czVH(MG87y1it6F~Xp#AeXBG-OIEK z9=d>!V&j7*S6ic4x$JTy^Rypv)55fnZYrFM9k)?mo<;3A-==G4f8tCGc~cTaGD9Uy z!l+v4V(_Tjvk!6aI&c%PXy@GHRd0U8;BGie;Mv)DFnFp6O@4M9W+%yqlL*#}oSloD z&3|{0{BGeuaY47tl3J;fJiky~1CqYb(3$kBxlz19=;CVp2KgNrz=A>?I|9)iD zBGGiD)rozD@|r&MIP6Qd6?>`fdMht1;mP4^)H`o|nR#cMc~fx+5f9RSmYryww%bAd zVfq-NR7Nv7=MD)vGE@kT1-oXywjHHu`^W?sdMZTcPnkx~`(5Qngrmi+p`tP-<9Mh1g$H(hah zwTow=&bCUZIY6;Rp%>kK!=(OG@<&aP9acBXSTyddH@eaqAvytw%$&;$uhIu?*Wvg^ zrI$(xS07x@aVhU(KbP<`?k)))dbcUa(2=}ejtP999E}nEHB%k-qTX@Fiow|?=9KWYixHAdFh+w?_C5ai zCI8W{g@qfbuK?b|)xdk0=6`z({{6$aI{cBie0&%?`FYc-<8-ttaYBwlbJl&TYU&(j zqL7#qadprzgMh)s;jY`cdAL~y)mm5O7u^Y)g{6!R~MBj?4B zbVTyOO^cw=nc|Py^QuHj7Vw(f#p%W(L77pEG^XiMM}|(7h4$#7iq z>6PEd&@!V}1(QjwvX$E(OwF#N=(o)737EC1yxUy_h&-`=Adg^?NkC8tCF#i{CV zXYYP}CI2?z^1n*{|xuOVPs+*i@aR+-Hx&)F+!dK3kkE(e%tAzr{$-*6s;Ru-Qt_fD6X@z|afy)I`S zYQi01Qxz2J;WpToBpWMvB;yZ6ACo%Bp2m6srl_5TVIz)&QiKmmOdv0di)9q6>u(t4 zrkGL1%J5_<&Z`%XU*LwhsM#`YlSK-GDt3_9%5s^QWIdAcpFTF&u@fPXpX4)h%nQJW zb>oA<&#=@EwrhV4hSn#SxJZ;Rr#8bcTQ`0&qzx8IEWzD3m`;ot-3`=OOc@Ch+Ym^= z*8_i`He*9Lvcy~DVW+l#*V!oB1L3EKpvnGGa-T_FQmr?b1EX&>9a7mnun7rSvCOdB zuLq+KA6FRa76#EGyrT*_b^>(c%*zwD{_*BN_+>nu@+~-%jN;1a3Ryn5w~B;f%a2WN zLU)Zh0F1Y*Q81SMl8!cx4%XzDVcnG8$8NT4*vZRGQ+0ePKW}<`HN)x-r4!v(dmMM` z+S)ddTSp~Y+_GrPb(4Z4-@Srnvpv-JOyp3^INF=W#!>zdCr*sQCa;|(xl%TW^)5ho zFlIaD3fwY20T+Lsc0`2fR3l(fB|Z{i)XLZgr>1u@cyl7OdkE`hA^y&{8>ko;z{fmtko%-(TP9tkgq$~W|31TB?rLqbU(W8Xk{Gm$qgtfO+SO$gykK+inzM7i)M?L`|j8A#bkG|n zlXBw|RflJla-Mr?({WDn`Cm2PNEyKsP}+)l&VkVop$u5fLEI2)(&eil2(2lKw;v1 zJ7yak+Tjg`{sSS7l=EUK3i;Os166q|LKiTalOrmtT2B*`dF1a+%xUMus4JU+nzBv3 z9JK0d^*&sJzGB_?J!$U9^ewN>A-VG%PAi#mvQeg9DaM%8IT~r(kutx|LKFu6K?`fn zPU?fgHmCge7aOHa-!I;6a|B(^b7_Rhp`SdAweLbspu(9t1Ff_tESiPS-&^1eb%qTU zH?3an+J`9~zjP?VPhHaGH@F4+^XqkIQJMB{XYc;4IQ`SJ^*0!a38?S?7je>5RwLix z1SXcysThGF6pzl|=hW{9RjjSW(Ct0y^h|m&EY93Wg_0|x$QKrm+LVLjX{-|krI|^*T-pf=FT2hcIg6AJBJ1XA!%Xa&`@uH)DG`~Pj*U@@e3>z zaMNa3v2}N_*{E`bpIwT5_+aZs2L&2i+jw7t#mo4hAhcd$_sv33;{+^^WDd7W_>1*$ z#QO+9g#sskFbv5yUM3s?aCIP#&Hbg($?Lq%E$1i*I|T0&W7sL1epAdz>Ma;FgAGLSuq39&{bW zXep@{D{(JH>os9KMuxU%=3N6D&Bw3JcxsuBdI-VbSy}l{c3ds zC=Lw0NBKX%9^#iab~uIHc!yuKKjR?o!F|M%LOpSQ@WWT%@V1+%u3_DnPNtw0_pRBlY*pDaeq7-3~87>Iz6_NGmp?^PO2g${nmv1-m{S2dBp95FKCF+hR$D9o_Z0ARLa(t2}ji2&_IrXbN#VGg=>T;y|fmW_$xI}byaFdS$2tWz? z4o?zcQ|ssrFZhfHWLIR$Wgi&y*&(BrBA`!BkNR|Gi8q#G_4e!KsOM&szE2{R)j~Dp zR=jbD5%M7Kk5@1pif<`|Y-{jN_JPx>^c%YStR^SeGhzAANg zV8|aSfS3Pi_U_;4)89WQLxLZD)~5gu0zyMx9SZSpMyttKHj?b0-P7`lY75y^i57XIG15fG-d-Wl)`7=%1E+IZEJ0!tv z!y&yW)F3c(o{1_(?Rh5=^7#$8x#*rP;R3fZz0#5!ZS2b{pI7!&gUc<6ZbbG=nc(s_ zVU1w_=HaMf5?c8y2Eg!lFY4bOj{gUP^_Y}H1$n4xggSTKSp-cfghf~>C~TuUC!Y^|S5HjFY; z!{pJCcY}Jn=FLb==_|n%7J%AiPm1sE+ENw{y&ZtE&Spw=o&ZbQ<4$_T0`%R;&6#6K zc{$^PNOBi=@tfst%rHV7-3O(vvIpEbsDZr1qmt@2uh|IYZqX<9)S-C^V{(cG?p?s2 z_R&yEAeXxr;$xevGDkFGNqBHHC}{4-+Y#;3X;dV-u(m_d>4jH|mV5?V?hbI(&wAU1 zR8T%tykU%uo?||9%&w*Jan5+-%=Fp;UTvnbn&yBmljmyJL zW8W<~^6F$|XI>~#@vHSACQvCE7{iWa_)SY&;tF!^b6#k8){c$1J`_{XVjEZzzjULB zRFz(TUbRv09>}mk)QfD2w|DND)V7$aF`9(QVT6Kc##n-_`OsRu$h z$cIM9YHv?W(=)7!)703Cb#kuXZ*Lv=#xWRj*jvt8s(#zn+uZl%%_Zz%sAMqY&$Tl( z!|&ij*CL$O0$=c0FhK}N#<15FOPIz+1o%N7Vmr23Qlw3&)~pgpQuEf>{4Qhf>_yJu z*Xl94`AcI3cQ0c;5TM#zeznXr#(BkSe#T4IFMGFn16sLH^(}ypEnmYx_MXo=G6&wc zim4Mms08xN=Nm2V8OZ7f1iPqVThxX=VM~H+>@O;KZisr5xo4-mZunhAx$(SQOb5*U zxq}wg9X--wG!xI)dWHt=vbIS@s55>HFvrp(KzA~fc}WtdUdFNFn>II3+&F1aa!A8>3N@Qpb-ZYwh&H9|2`Pcbfz{De)EGK2h1;XBf0H$9;`S zBtu%s5j=cB=*??3{a)>5$?|LL3VdVj_%$yRqK}v9+fHprq|(SA6e7RkoN^5c67AEh zN0aTQU*H(?P&i!(8M6h*PxoYMp&>^n!bexgK}>Jv@2RmF!iQpON@cQn&W1{Dxif`~ zvYK**2#ufLU(_eTm0=()9&{t9(RqZ zr_y~gM;<;LuP+uFu54yNK6-@LPd9&2q>o16T_g{K=rz*TDsWRpuTx~|)-a3ea=$`e zo0`%#tCM9WfkR<;zyHfd%d@x_^>)7y0sjYS`=|HkTX6t(;`>F~_qrZvow+sLipPEXNhLtq6>sQ&C?y!6J z#$^PhI^=05H`vBCuy#GKTtUcP^{cfoHv_w^FbS-%x*tl0UVVT_r&w)d2Y12Jku7zs z6yi47;;jpu1=+ClT0q>c5bRM^J{%rCh!E9yc`lm9Jo;MY#RpaaHrDTveuI$vy6MNjdt+S5hJBlKg>r|e-^?}ErHBe|LM#^`j;7*AQ< zT7*)U=w~9OV+t2hm|kWA}X3kj^e**bS_qSHzM&AGbjP(FxChHOC%CTZ^yD zoH)T9n`v#Bj(Eu2mL$MVjE2PAj&jDMycKJ#4wopkEDyh*JCnujuaV{x ze|ty(hQPM`gW${Tw<2NNFexpAYBYAJ^nR{6AUdCuSi5|rPMcRz zTiNluViHN$(sPIac?;2&>Ne6wp?ws7c9d_sLDN;mZdUrYcH?@C>muWz(lTX9Fa* z7E=T%sH&sd2zO`s;l-D<;F=q^BoLSq_0?hY(Og;Y9n)r?-#F{2)G0K9^8_`iF({r&SbW`N-l698MD z;lFPeK&PPv>shA6ePIHIJ1;n^ZMK~d&3r&~@6ZvRy}Vp}gJa0F3s#N ze^Gmvk%tX7K<)oyQ_-Iv@&DtD^JBi?(PP;EIT0u(@mXKfW>6XJsZ7!%V&ntp6SFm%Y>}T)d*_rXswm9>0(hYhkzMpC~sbNU)Zy2=|BW{(v>pE zuJH1L1#Yaz4ne)>?+Vyq{fZX+A9kb@%-9UbRy>Wb0Sce z;oxPT=|>wU0T3Y~v~Q(?ds4{-Cpya%8K6gDPM-mLA=>A#qf*M}%)mYh2p256`|6H% z0rrC2uoT(e)Lugf47jEHEzg)%+*K}0t+K0otAVxv#>NTlDM?HHyOmh^c^|pGQj5kI zHw}1-pEJ%JY2D8uLu|?<;AQ)?qE0ZN{J1)1lH8Olc4SFybTf?Z;hS2S=Cqv)g;AY0 zw~(rHpXRt8XPh7BxB@E&VSzcWlM&~qIj+Lr=eS~?)vhC^;)wTp^K$6#v%0@zaev(7 z3PQ7F>d*@O?4Y#ScrVd1J!ucZqFXR&dImr90` zO{p${#zR`sG_=U_yojQldshH3D zeOow8b;%TOn;xh_^e7EwjrS{Qw<`1%bh~nxOG{RxTR7muXf3vBaVJm3-?0ie;5!L# z>I5trmfJQ7AFV>~z{M_}GIrln1^w1Yjd@lf+1HO&CkS zj!vM;6o$@0)Ah?4Pz%yropG_g5SCi$$myK&R0~4s3V~Pv^|PvoW)d(KO5ZaZtqlYr zXeay_+jh>af6nY-2QfZx*wTe(MSlPKL1vi z;E?xzJIss&4Qd+J%fNK0GO!f*x4N|V*QG!TmnlG(WKcoI*%8J;JWbEqjMr{TxJOD1 zG|W|$tnUJ#D+Z-CcS6hP@)uMd8;kO*BRem8fr+XuN>r(})j~wKWD+}^O$i|f&IGhL zNpYkq>}QX;Cy=%dBu>=MzOdm_X`r#FkNYwAge8ums`G6BITeWa>r^1d&2M2$U@Gwc;q9%WvdsJUZIEt38tD>gkZzIgE&=H-DM^*? z?(UH82I=k)kdkhs8{X?SW}JEE_dMf&<6Z0CaLYAoHqQ0+xQ_Guz+!xbB$<5}XyU7? zj1biipii_iA}#o$Vfzn#8}D;rW#6Coa7#_$aEm`b-<=_UepOyChSX;KmQR3jORy@f znP@XR@^r_3z6%P1jqfgGtGfS2AwYwgw`qx~ged5>Q|x8N;>%KN2`bCBywgwB^F7UU zzyX9YNZpGT+>_Vlk&6ulD3+^C4d9nUimeMa*vl7nb5J=$n)>0=SQD z{bv>8B7g%3?U~jc@D>ZIooYtV*{kN4#yovjUAYHJZim1UWyJtQ%tGHgydysuWU@7Z z)W=K?c#DC!ElQxRafF)qWjf)(hNs6C_gUKJI~*cz+!G+|xfKWShe(M|cB;JGlb^#%cFL~M7I{-8`J|HpV)#d-pW7E>ZcnUM+ zp!Tcv7D4#Dn}yI`Zv!E(!J*v=x326!D7(@H0g2)xV6tc{%uT(pK^{VD!FZ@E5$m9d z;V^gfRM{5B_-+X^uddfUlxJz_@8EO&HO)vo@Pvc|o{;}|Fz`RK>Ayc5gM+?39KFB$ zrHV-b?6u-B0_p-VHDRo=tS6Gs3pG3LEloBfdOd4g59VWWiev=^FVNhuyvo{jhSkL;Tnu2b;C5=hVRhIqAy-2a-%Uie&c20$iP0@qs^ z{x|ew(*A#Ao}b8g&Of{tZmMgl`93((i4EcZNx5HN|2Xt>Dh?$wWS}q}3shp+!i<7j#7>Z z7H}Es0i0*70+xoq%8v|2M0lT8vzktu-EaC|_AU+TDxXcStFtzxj%@4Hl*GZir!bJFq=J| zR8M(sD?B>1EHi!^zAr(#K{AH%I@i$}Jon-F{s_|^WQA$+%uzjJQlUeM(^OQOqcs{P(;0T><83dhQpty}9 zri~EKWf=y_en58w23lL?JK&=Ctz0&hc;Lfl^#WF9&ikPp&4#a+>I7&S`@ z1;!&I45x~A8$IXC%L0)NC0db3?US=Mzrf%VddDQjXZLuoaK>`f4H*p8qUkB)-?@36 zH&CY~M_tKqT~T|pW*BSN!dq7FgPW3iPi1VfQjBa$p<854guZtW9=VAdleC%jON&QS z^f}V@-)2nZ;E&7Io0Kbix<##pCe{1mwAOW2Z&2ul>N#dp45Rj`hpKnYOxQL1K^4c- zgq%kg4+FHxKXk*6R}MyzFm&IfRD@w4qaSW7oXTE1RHj7mzz9^vJ~!D#A0hCC+m_-I z*T@$%M^Mz0zTW-P3;l^{lQyk7^Yyruk!+W^g^{(N>EnqWM^==@8M7?kcqwKJXK$#Q z&Q#cmH?Q6j?jqZ7v4Wq*2*VKANvX7V>2+*lH_cuN^IaY#bLT#eljuJd&&MYD`l^Ez>t!fr2>Lr2 z*1n9p@)Nx?!@WgZ%fxZcc6`pg7CL2gTX2vH?^1W#?Xh&?6Xp%wSeicvi;zVO`#= zApzbK!3XkQ!IQ(Q!&A>ZjHywe7G9NDotW!s~vI>a1EBw+IQ%_Q`@1z~DijPk~FXg;hA zvg*YZF#b11wW8~2z)bnPBG@yKhv^k5ru*TSdCZER0^tI~bnS4I{lZH~5-5>Zq633W?;jmhR&kCn*7 zQ}6T}!{B0uUDNlLg-bOd0;F2P+9Rg!?D4F`F;-yLu_;ZygqH3P+ zT@MEAx-C_Tr$xAQfHJKM$h0Okb$o(_(*Q8Ve}XmXKB&gEjpbB({!i z@U9Uh=p!r3Adp!*nQc)Gd(s>>OZY|eBm^-W#dRA9v1X^Toc2rt8aXpWZX%+yTWu!$zlQ1sS>Am|3lWG(;qHR$p zm|ya=HSB-`?00;oJ|M`++#4)D^w16_n*aiUoDPHlri%<3u8NP&et`F5Mbz(?1LXKaquX4w7tcVAx*N2Yb%VE)Xs%kP;+`#salL74{rBhv~I6cvVoXWAnl0GY<}J<|-o zWm;*VDejL0IEj_plKYvA^78G`1V=uEcLO}T~ViSc@)oJ1;yebQYy!UpoqQewk<^HDw-7 z^ky0pL_ud~%;=H4$_U#C9$K6WwNoQ{FBz9^#gp_wUcAVz;p^z+Y=S*c>1eB zA%s{No7iCWw{F)(yPtvSluTOd)ldmwI_1T8w^MyTC8}GDeT;l)eYYY)>MeKpqeo50 zj+^!=Ge={I1|K?@`C{`my{TMG#QA_j*G1)ncmpTkuAlg}us*vC%cmmOe6;3AzFf6L z^C^1m$dBAe?OWd=^X#lHj-|M)WPKN>x1J=qPqg|iyaI>%c)#4Z8&=Ij7K<3k0?d7^ zKogeE+km9w90NYh@3Y5xk%zwi!)8ZvNwbd5p~5_ta3_Xxfw1H$3nya`&D)ak^;*TvRPr@5+dCxobh;NqDbeN?-@Hz- zl{kM6!_1-lI6W~=7OV;vJ2u2~WLR5_m(k|lNqW#V%xh*RZ?kPAJ9puN-KN%FMwpB5 z_C&2uVk8~0b$=PnM&eoXbS8iss24>c3hm*h8P@>Bspu_yU^``KtO2y0g3ukYw}FC- zzPX11T4HwqZKo)0?vdnV|5#!d5U%Y+`=nCxT3USS4c(WJk6*DLCn0aMfgJY0)c%U60z`kwK%V~=#S-LrW7d`4hEJ8pCC<*$f*(`@oed<_r!*iZ8AJa6Jm}A^GXD*I>i#EZ^Q$+ z6iW*>Vr*$fVjr^*_(Bu3$F2^Tou8a3AA!tH+QC<0qDOEke&GbE4zshO(rge&;t=+! zzNANC5Ab`Zd!Iet^T^aYY5>0!YgoUcw&Q!%Ma~}OMf#wlE8vV5p_}y03H6C8+OnKY z2$_zo$4U>s1c6V4^~i(n@b@vk7_7)5Y{(+#$P#;M)+dZk2iE&3?-1B~Zeye5!^>YG zcLlt8;t@@#*V6Ir%Zm=^Mue{%xC~JSQbnA@JB%MUBES)r$=_bp(J8HQt3G+4_=Sf_ zCK3s{Bw~ceg+j(pd#XAQxbJ#E`GmqfZ+&vZsp(ClO;LJx?W?7A$_2)Ghs3wyHU-(a zSaa(JUUJ1ttlD1_1C{Agm+5e-?yk=8WLJ8}2;lY`c><%c`n7V7hblDE zI!hvMki$@@;qDCyC7JVv)#whUVZVq~On!v-Wu4^SQ^^?-g{yEzcGJkcX4Od?6##GU zN{k8vpI)*K6#m4U0|4I413BkmfOF2%b^bG(`haXg_?Atdfoz%uvWXDoTQ-TkW`k>I zt>gN(>!jHxf(y*LVSZv)whaj~)+wU)P4oT%ZKz$%fWM13AOS(&ix zE;QscUY<&K)k{Qt3{uY9JB(N^^R`4xT2d5&TZ&4yMhlgSOjVz&!7H?~K9!&F8@5QL zaOB2FAB^U8)21xYn4+fZr?a`8yi-i3Qux$2`3Y*9Lc>ieZAb`lk)u4rjn$~XBZS5z ziJ5W3e1ZkTmd-zST^G4zU!gr2qU|M=ijWKOMpEmZq*(A>$ul6kNYiZw>NO=YGy&&) ztg+TZ0dUTn>MPT8U1f(MQq-_E!B>L$8&yi+Z|4fcd~ za(3~iqpl541{T>JF`OIxOiW}sLZN|0_Ape-vX0Zqf|rpQv?&sANEo=GVRAjMkUrk{ zRFa;+HFY<>yR!?}St)q>Y_7h5s2&Y;N-^X6DaGdFoAw(Xl7{2i@>z|q+^&7wdykzv z(&7khOuzEH$fGkE@y-=I6HEUhj{nA~i3QI}v+?}-olNF+5pV(Ms+CsOG4htc<>TEk z)}NFQ^n?`2C_euUy7|9PZ2ygJ&OJpg9uo*t2FNzgacri{a*bB-Tcc%$^X3p`WGA^Wm8*SY;Vr>uVl5iQTf6~n*5Zy$%Pb>L@ZjuJP z`%X98X|+If)32I>Uj)Rp=q4<@c_oty z@rtM8MIAb6**!Q6Sesd=0aL75Q^`OJH|EDuOg|s^BU~SkS-|LA7w3;@$p#z7MhPYgD)5_-}(;HC=WuG0KA^0G|;pB@OhJzV5o{a z*YiBK2WxCQb|PsNIL@W-`G&KfweQ2)X{5v8(N82AWdc7DqwElN4qz39Gtosq8iBo+ zhZ3Vt+=fY{tFX48nwn5ggn13IH-YY->1GlbP{vBTp_*`?&g#*EmM&22z13;gPj4nh zAGl4kl%~3iP)UHevbJjJW;~P&2|KPzd(`cKsVwqG^MlEMZ#oN89 z7r|P+*qZakkgg9AcOt|iQASr=y!hcRmG?eCH+{0`f}nfVo}PMVm-vvOz|Bid<$F1a zKilf_gflB;xkI%`m)i5$6JMg;M1hz!=S>{$bSTmh=*6rmvi^2s0B%n5nxa@VCm6LEBgqJ}OLnzw1 zk^6BbzZ(;*X~&=e?+{kJLncJe zw{-EOac+P{i2m`Xx`AGMI@_*j_KI!TUDC!yP4K;}iMO+(+EkUOg4b&jY+fJ5i7?%*1Mw&BgTcH2D8$bqVB~NL$3w}+PE=FLj0A)-X2C6i&K2) zUL7Z}pj(zfE#IsNx+=ixc-lDVGuM6fX+6$3L3~N@iFvsX!h^v=HKG%-_gxpiPxzVO$V1SxTkBU-!#q?2Xs9|GG2}7-kx==8hU2w z$9AgEX7i|~JF<8KFT?5)kJ1Uz!br>u9qfrR+iz^pUi6h_`>~5{r&3kmt`nZ=jLgR} z0juB(T<3E@o}CZXZM-(^+`^%6*R;LUbt3N^)kjxRmLm`W^2xOL+DUx|<8!SH*k z6cM7Un<#}mk2zmh+ISw-apv+E47Ma1tM_s7ZSjYtreg$kSiyG}YiV8>6oiGAz-f$s8(=xyYlB;-WI7=yFi8tVtSWIpp5 z2Gjln<@N^SJJ2IK;c#n3vghuBBrb&PMeuoR1ZBkKPfDnkhMh{>rOEG-v~wUKYFid{ zQZM+ap0uFb=?WdH%O&!rba(hzVy_qNihHSvr-o|G7^ynPWkusxR#2tH2Qsuf2RD7a zTG`x)AO*YbOFKSj&;-wik!YIGq(Jh@q8BE^f=i~2+43?`f42Sf1}?CL=L`}QYDj;E znk)|9*mlxwX^A+~Y~!}`F&VNLHWqg$`}QYgP2c6*`_P2+Z=v>DFM<>j_}f)bG~d3M%UJ?Vh+0K)+z;t>#PIF(E`TwJNVEuGq;2K^=_cq!s;XVM(o zyz*^i+Zd$MCNByTP7+elC@?-m38CYPnVe^Sy0 zlaZ=FV}ZjWaAI~J-k37`a@^-mJU#fyEEb*T&YsJ=S<&>WC-wf|&zv!Y@Tdj_(~?nN z6K228Ww&_IlZ-ZT6`<{xkoIYnQgXa3Ax|~=B!!kIk({(OdU>0d(3s(Ue>-KJa3Nr z!<)X=f*c9vtCxJowc?DI!!NI$0JkAd!$Y;GxS zx>AETlrfcmRZPT{t^3yN#96HKGR!|7mWx00b(u&E^R zq$D+g{rOY}Jz4R%VN`zuZ~o>b@Sk{-=KEQoelMN)mwzwOKr>vhaPdrT^Ddv$AV#W3^a6>&~$=<HWlAp`p&$j)hkd0qH*4o;pdZk~iM>6jl4ph(H0 zAO=euT!&7xuq~#+fHSwYzd}P!Bw~f%_N7VkTjF>!z9Qyl)X5R!1x}yD56sn5bRvjE zSWCWp)bk{dEmRozodW|;iPk4nPWQ(9%>Y9f0Pai{i^em6?o46>_NL89Kcs#k&dDnf zLlBVzzkmJ$&j7GDsZH<1oxs679{~2IYqtbXK%WkS+zX5a!WG1sG~0f-!9b%JxWoQg zOmf)Frd!0$j?n1FqX#7zGOWdHCtFzdb8V|GJ`K_#(C!Wg1Se%O$SrBu2-(M-&MqgHZNZpS$qtL2x7QFMvG_>wk z5n?U5cVh$}Rq&hav}T!m0mb{GBR*Q1_&QKA)O1b>``{|a^|{f#+V=P;Cia36&*^|RY|m@>hQWQ!j*Rlacv6;TEV#cTy>p!ItBWw%(g9Y zNZ;(umkfo%TN$B<57A^c6HoXg-L)znv)pX*0QRQmj@aa!218*KVsZ?~-rPE+;fdlf zjx-vgYQhKEn~AwK0j4jW#Bb7~@T?XMMdk0TZ6`jkPb_MtlieVxKQLDt<&3S+*X>qT zJe!GgquY)PnNjIDyNnwws!MMG?9Gy;1mnSt-HO^|6RXSv>S#AkLy0_dTj}lq<7mC^ z9HkOW>%PUu4H}VCr_m@oP94m64|u$|9~_rTT2)NfY2`TDc%MK^95?~J^`TTzhZH{Z zuv|xYJGCz0+aG-CN+ zoh=JLUB*PSOXwt5VGc}NDgDb7zSC&9EJv6y80gUC_HzF`76CmUQF((^(bIXSPb(V( z`}-G@pe1;pwhu}Ds=x{{pa2D zX$a&l?Z4&{Um1bNZ{W?}yd(ZIm;R8-C7I|rjHnSJirz|g`TQc4&;BcUvkxSd{}*`^ z@-Omc`d{Tu|G&taA$>8`D@N3Rl{aO6$eVW9|6Sg63I9iV(?2Wh;XlcnRNv*zQ95=` zia+H|2*WuT-w5j$Kjh6fkfHA01QH;5GaMvuvj31bSHA#%`uFnYujeMQzsZ}xmzTfF zn-;_N`Tr?z#{Y-B$xHuT-sJfvZyx@Wyy@{>-rSD>iRCTfZkm8tUI`a+W5bx%Cd6o(WqVmkL`+$!wkwuLZ@*5;R2fJ#$tcewd zy4^7>A@Ol~tlLQe95LBbAhG;v?=yN@m0)aO!@J$LIE1x|{6@lOk&Fz7$QC+<iO#T_P}L&YZW^c)ws zrFi8oIE#7}wP2ye|CY1!6b{1x*K$5SHVH2HkqPAJJmhF0E%&0+-Ip-{Z(h#^%tku$ zx%Mq@1@ZkUZ^k~`Y#S%Ou2gl*hHh*eO$uhCUvLq){w8ly{x^A(D4Ya5?%&Is|N9F0 z-|*(+K+gjG@8h5*F8=98Xu1PH=SM;!R+^x3&E=rEZ5x@T(u;nEFQbxfPhu$GVYJiJ zJo*gI6oEObjQW&qQ${a{GzFwDU*8v3BvcS&3VQ5Xz^o>R`?zL`8p=FXdmdjV#T&y^ zmPmsnt;9C*16a zAt8yF-~*|fe7o&wF7yU>dfjX1yyx648?hU1sj<1@0flg!V6%!~#xQTfz`=T2`8KJX z^@9s`L~{n%Gmf^3&GKBOdFFNvEe#ZdjSE~Q)wDRWOZuM{G%F`!JPa^wvD-O<>Sn>t zEl=zgT#2bekAbvz1`};Gy(Jp%%VSo8=XDKDrACFnCOiToYK+m$X1a`l*`6!V<3-$Q zwkD#_b?+%Tz1+rWhPBHV%vj7glUHJ8dV((7O2WVNER1VmBc=i3XwYVQ9M;8o%>{pB zSAx&&{Vez%S~@9Y!<#(pz*S@jP0KY4l(dD1iVKzFI3CGTBi=|iPQ=-84!&vQ4>YG$ z$!dl~fM4ja1pcx3iI=M@@A-5Fx^;q!z|*jpWsDFH6B}O*Io{SYihAZWV@`8;wbql= zg-)m>0m+8`CzT441@>9}JCGwfa*)w7WmhZ0N>@x@)vJWJP_VL&Ds~|520~5OC&o%R zI&soa&d)?1M-mwM;VcGl=2yPrX;I^g92AC`MLbrvWEr5Nq#stTi^b+KpX)pQT<7(1 z$a_YB$7HzS_SsR@F6_q?-OZb80TKTFw!B!bz_sSIo58T%jI@eTCJbgNF=5SoKEuPB z7pa+2DGL?p^HHq5<8QMneZe^m1l5x(u+E~|;S*I9^in=jF|K6ff*IW|WSJ@59^I>r zBf52@&BM9BaDYswCUV?KM|gPdoF3^>tiDMT4|VVZYV0$zXqh*I^stekfaH`T*LKoo<}8W5 z907oU?reAf1av^3eFZ=Olmka!krN^_fn~2=9E$C9U4niM?ObE>=jzuI4h|ZfNK7pF zQLC8HyQz>W3Dav|vm-fG-eeD9ER^CJeA;b>0NhQ=jCsh*T%_A*{zOzeA}yF2jWh73 zc>Wz!JD5kEeIoG z)@{0nJV4)NaVC9sMSLC#F-Xnn|7W%R42$IT&USw zj`B|o(jDd5U$7zSQ#rEYEzaOYB_>Oi7dbs;whW|SFL~YGtTl}R&`t0wd{5;0O`qa` zM1Nc@pBZJj$Q&nx@nEJEVVz)U?gpkqafh(>l9O?nex*nEH(wvG^6Kp`W;72=EtC{n ze3dI%ptkJ`sS9E%nfM^^07aPlb?cz$oi*Ksc?H=rb-dd(Rj&d48XU8)^Nu5Vs%Hd> zc!|vIQp?8Q9+*h++IhdBZvHLJ{{MrU;$_)>en3Y(N)724<(gr0Un2f(AHhMg%RWcT zvCGDsEk~8EUGyjLuSE~Q_8!7SfxUCR5s=w(Gn1dpO9xtC@TvRd2{gJ&nHH8;3FQuw z8atWP2nC{UdX@(B**?Idp7Xj+L#2a@u9YnQ6Dw*;>3{(Px$y); zxVgprE8MglWJS`nyxc=fyJLu2EF8u0nJ)q%O^h^BL>KnWHu!}UgK6%adF~w^P6_*t z-UYp{qchW_fk_|5c3l+T(_m2Q>Bo~h)*7tq&CH0~!{|%_2$;* zM4}h?N?J@4WIu{9CJXqOHKlwN? z%{~*k4Id?d%nL#?u^)1uR)H$8(6VoGLh~gH8s-7u<~ay%#{NsVSwiwZ;O3#$e}|j= z*#8P{YWySI4E=wEoB00>Hy3{kZZiFZoBhAQ%>#ztgqv)?4L7Zf{{`H9{sV5F18{Q~ z1UDU_wz%w(26>Ml4-xiHbHmMw}?ckH=zBAd0U&vV<}SP%xsmXjT6GehuaR%O4Rh<7P|$bvL( z18H^`C9km;FDiRj>&x=JmreqZO_wT#80Xg?P>lhyDFz5qX(XvX%Aao^vg@kMbISbe zr85Yc7a9{*SkrhIr9Ka(AWkvZuttM+vqr?(Jgq|~d@R|fgBn7tC)8l`tRDC|Dw+-l zWe)eah}fRLc==Ih-}W!7oIY-Un42+toL=9|&4+*G2ksc^+FOdzD8TOBQ^4HJ>EZll zZt^yWifXH{?fVr9K z7*BUC1%=QOw+tM;du#D|Z8fFM!EAf|Fk2;>2r)KDS(;myUqxPTHv*lHj12bA1Q*y_atO_g*>= zsF(hsY`6>5OJ@P~(lLJNrH9}W)?Zxa*;E+6toqub9#lYe$F`cpOji*1y_ar{G#9#} ztxPK%%y)^rEvEFvSzZZcJxD@GFVP;4VF${YR^r?Uc@{km!Bl&PAlP{hZFA5A6E(ol zdHhHB(=h)iMs!|>+A3he+YdO!33NYKLETSs;OgCaoIfX}UI_WtfH|o9sq@BKG>&%V z1E`liUYjfi^wRNy^_W1tbY{AZ2v9Gbf~BNn>DONRi&s-Z-+Jjb{tLQgwnZ-vmf*Jl zlkXJhr3-?3>2H8ux>d;tsF$t)^wNu;TVeg$OQ%P_1ohIN|Jh4dlx+czTMT#b;stu? z>!YdChyU11FL8M3Tz}!$v)|ZM2=vlrv`gP`VxHlkACpRBG<(8M0!Qz5funaoFTDiZ zs+bMvr6YuDjqlqQJ0^1RA9p(n4C0@`?1IDmUEB=QH*NY2viUog)_=y*|23EKYc2g( zp_~c(TP)H1AF*Wr`EdWZ`PW!#vKoc>TK(r-hR**nm!a~Ha~WSw|1y^m_;W5p@{hR; zw-fHzA9ES&-{&$&OmTC74=&5!<}$*6nalWlEM1a34u`=omg$oIV=<#g=Ccx;cIGu0 z^SY;}7(2~#P&AbT(IoOMnh5@gCS$6PvS`R(fsitGQq);7wgY|#c@qSonKFMSQ%hD< zImjvhz8CEAw`6()k80u9St&?U0M)k!1&-*i`jFmx3X4-|?f9btWZp*?{S=ZNL;~`3 zm%CjOVmGDvENGp|melmPlQMN#?T060y;oKBmMe|#6Y<^-+kG;);{X;pQ{#1JJB6yzSYwEnyG%&(i?xNrLPvleXpfU4)K!ytff2pYHh^R(l@DrYUvXG zvr2!~(((VOrF(;F=~JLu`sKaaV(9>B%)-DsjbCf&e15ns3P3F#3ZW((R7>Z2daQZx z^}UwP`S)6SF{qY4I&Gu}s--7@YUu%g*3#)kq|P8SQY`RW4!_nINgj3?c83z~(P7 zrVSvP{$nzOP2ias0=>h_H;os-WJY5dD4If3%YKO_U(gokw|ku5Co{fB6N=W@KAz^m zGsk!9z(<#a&$}qVN0*eAU%m!|K929nO27FHar1xQY5zOf6bb;yCK>4Lk%^0x;4oRo zG;sDPCWbDV`%VA(f?K?Wsd*ZSYkqNXU%ee5ZhGepDhS$O9NB>%)*?7@VZCMqTIu8D zAhKDFWP~s53)xh|66Pq3bCgXn=`z-f_JN>aRj;_s+4PlV7tl(F8@BV(>BhOSFCdmU zaIyP1#{H%A%kJ^o?k|f@ps(OfOjY{7A#VQVEb0FP+T=Je<$BD{zW1aHTa^13(Fyiv zjnjyc5NM?nUJ?J%N~h@h)=K}0HWS}Y`wE7mCQC*eFN zArCLT{Q&joqoc#iIlVynk0$$2`TXhuD(vt%o%ohQmylcuTgC4(wo0k=p~l}j!(drM zGwva0jz}{WO~umz6;59vR7Kv-1e8R@t^SW@lepP@FT?tVEnzR1`SOxgBwALZ^xwJ9 zeLk>}bdDl6bfw+SD)%_O!MrtR#ltseqfxD!WN1igs-Wj3t)9} z9`RhP8StU2BDGIBSC{t{hS*nr0u7Nj zdAqRBRrvQu1+j?s&jcu;H0?*!NDu_YZojsVjqETqpt8`sL4Ti{xxHQLaD!*wfb z2tzC1)|;(Rc!s6n0PM@{zP~Y>z@3iZTk;V@NPNFfAB(2k_^l{LoFV7CAfcQ5(*_|g zv5k#73JD*nDKxUu7)tr$y3Lfln2h`8IE{YrQ^YyPq?71+Q)v2v&!c$A6v&mbc5b^7!~|hEgdyH>n@(DVCMg*r5F7}E&T+jr8gGmP)mVk zHX^>wY!ne(nM&{FRZq#NY!`^O+e;bDcR~X*8_Bm5pqULU9bjf7`P-^m)PfeW$U4kr#5jb*OU|_p`V>+g}ezUmg^{bCBQW+ubZdpY_Xd`+`AlCMpQQ01Lrf$(L{-cCs$%8kB;f%vI#jX2h#9|y z$Xd?gKw41r?9eN$$!B@t2j&FL6|tc4O~ct!cm&HpKGeL^k9WM&_}gQEjLs5_%)MD& z9249fG)yAdkk;4c+BqYvW)0j_z)I2nCZmg_;29FAP*L1pp20o22yeEHzR6h{2H2*Q z`_UzylQIVbh;7OeuHiPCDVS7Z3dwKV4Ij@XX=8(Sy?7Pxu}2&hvp~SRMgZ#BG;jxO~epy z*z>8#t0=FN=#eq0=6mkklr?i1X2gu@@J=1m>i~LNd@`xZm<26JSczYlErVD=6fKi@ z3q2jX%&v=~P4}SiY4T=Fcw z$@a-$NE`<5^Knjva%lfSip%20<=VOHoLNQpr$KeEh1`c@h;g#W&-1|C*%b6i+|y2g z`mC?^lb3&4mV3|gE5A7&w3S%Kx{APCrnAZwBJ8iuG+FrPy|vmO1sGx`wlW)l-?d2o znUwx{{PErBwA*`F_8=Z%a)W%y4&PTXb9f{J!=<^J8{x3IHPP&k2JW`VAAWu8@tHiP z7GF1JFgbcdV4C{j^CMG>XI%Na3~|rIS+^O@9f{pSjCf;n z?*SvPY3)pg)Yq;R#{7I?R>I%(@SZOs)D zo45Ke8ZuPccoFvBGOfmRXz_b)mifKUyI3g2&a!DysAW-c>DS7%z`lHr9sfG1@VY8` zX8u+6$^d@Mj6Jg>#E)jI&@QC%@G!@LGc%tU~n1dlv3pSef7DK*WozU(U5gJk$L#$sN6}*oP z>3DiI;f@>7Wlj*JHt-i+t8Bi+xkra$UejiXtGKunb7th>lZtQ0pjXwvm{~p9?h`Da zTJeb2u(#QP)8ibtM`QJ{iCvb_n(JlIAnNM7X>Prt+9ZGwAAsml1e+NkWs58mF6@&Q z3}Jn{n%Ti~s+_bH&(UKhCUxXtGXH7}Cuh}%p3Hfk1W`Bom|sVcCbO_JwrtVE4SMc? z01}2RC?85iO=*Zy(87I^t9<(b&jbZZbf+&NE*nK13sy}+k7qHhAj>lM1epbeM{e}_ z=EmcxidqOM$HRWAm4qEy9alqq_-FK$T@*lrtA%m->y=Yo!_R^LPRoL)JFFMW z=K)t)P41F%D31x)OM2MSW3-$ajt@rBPUZ_HSEBDF(_ZTwNU1uu@=6R*klQPP`w~4a z*_6z=(Np9tT~?hbe7UJeYcY1H3u}s}$>=I?hsrL@_B0kxn|?DdDK($q9s>X6uSeuS z|I8+4T6v`nq*m6yOs)U^64g|+`j%QUj}{C3W5>M{O8Z$DEnisER9HTJ%5`u5Gqs*F zv3ilIALoKntH7qA-Yskt1?y=9N~V6P03UinUgSV9$t)5MiLhC{WpRH}G%{=ThLq7H zfn$ry!ns?@;%&;g)4qjyKuO{R?5R9#zE98-7-B_86y$^w7BY+?Cv%}eG7R~atgO>U z-A3v(%U+WtMV7Ntj9F9lPYK$iFHQSnCD$)2z^fKk={kGKK4U~@wmpY_B3FQ1yHper zmhoOGDGgT3E#SV*{;70kfv^|+$J`7uF+3Mx^wfkLK`@PUzbsnQ1~g@F=ULUEpeu}W z`zWPQNb$F5%a5T3V4J>r(-R?!)+!UYlLqiO>>dWhCN0Y~EE&R#`#!sq<|bMZ0Dq)M zbwC_=3;z0CEJ&qmbx0byZ+g=I_SMIcfO)2UHeEh!2JWFS-sS|}=K8luri-G=sT>D{ zq4QXN@7kv~^0H{6!!I5VL^MEnUE-YCo4!Q*VpsFX$YUl{3ld!9;T&Cg$KJyV^Pxg+ ztTxN{4W@B}_LaU`R>q%mZVN*`YJo(0 zHJ5!6iRHjFfazDp)MCZ(7Cxc-9ojJ%69zx)aZj&)A#p*5MrV2e60u7c7TZnqi`*41ixv3JS%qBg2tP zjx^PrQV6!fMEaI9QIPOZEeBhRDB#mf`%Cd`2+qhXNIZ*URlwHu!% zgu-*q+)TOzqDvNtu1~^fhaA2Bx+OTk>|En&w}P=4_9=tYv)X zrZva6CZ8L=&K5I+z>qr`d_$v1+IFfQtyc2|t7W)IhIP`{cISONlo947)jf7JO3}13D>YVqv_zs^Bcums zmx^8LCOug9h49+z;~gQ*=;N|&f4-5{(_gCHATo+$dX=65d|H1FtRfNp&j;6ke{d#; z{>RBnCfEqj$;)XiJ>$lxEPK?&c~(wztk%SR-n)Cxeskc#ncbe3U?v+=e;QCxh%`I* z3>}8J#^vEgWLUQ*af?SOIGLLb`?LR#v$u+hbIsbdAp{TZ9^BpC-QC?GxLa_y;O_1O zcY<4RcM0z9vWu+l{?@nlzq?oeW4v|7K~;^xRdZf*KF|G)LepVR@3W)rUBidHA+kNm z6Qu)kXA0Od*wPGA2*^Su*ia(6wUb!JduB$Tk|MltI_4YiGBORp``6D|5WHM&X#Zbl zgs6}&c)kI!eGI@h<$w6>|HXZs|KxX`_*z-03tCcrjCQ5Vp$HVtN6YypnUH>GjW3~A z`ct$dm4h7+NzNN(|%iW7VXWXVuAN z8sPFg*4P|xo1RtyW2>`=)hnKH2b(m~R;n}vr~`P0NU`D%_(~vfQM2o2qeq;Po`zS_ ztH}@2Ac~ZSq>s6~iYQjB(pE_iB4y#pDptfkLx_)2+4v%JMz#Irp zEEW0GU&Iw9bikecJqNka#m$~A5QGOC7$m5w>Hb^}3a-`eW5iSc)axwZIeAf7M$}#< zwmG|7b)E*g_0)}-8dgBuk)sMPlP_%x2jQW~mY1HD96}z!YySZJ4Cm_{SX9SNRYtyZ z{sE%QnnEmi%(+=q)f#LlpLJ>}MBJgGKvELh_2|W|U9{q5$|~mpP7p8vZ4@oGjksn< zv=Z&mD8cz2rS^q>Wb$W~xjwV0Zpb2ULf~vJP;#`dU2#5=>2tSV7W;VCVMAt1TDy=E z3^A8+CK?yH z-3E5cv^IAlG_oXI#$*eCwdVy*Q!8#TET<1$G`g2sKb1Z@t=C#2Hf|cvvq}qxdbF7@ zO*Ki=lG%D+9zQDGg2~6R<;LJ+MP*O&L4fOTWV>TEOjGFn)Xt0|`dSeH5eh@1dD0gWn;{y(M!ol_lY-EK#3_%OmwJeWq<|E5bN# z+glYfmUM0)(AT|%W~6`eob1>}%gXNy)>HFUd^{?hP@wwrV5MPavN5h#O`xfC6i?o$ePtC#8F<*b}M!f>2$O6j6yPMQe%a6C+0 zKcNiEni8yS=V#uk7o%KUY2;MgI=rd_%hWV`X$>m4^2?v7ORax(sH35_yzv0&o&UGc z`%gvdAL&Jty$+UJ?W{DGgssi(s;go-{(2{vdjV!&iuw{4P)WS#?SyX$R@n{gb>TjTU%6mhi>Uw&U$m|lRUilIQO2% z&c5zFbvP`oq!=#-$cY7ivl9|9hRCtFx2-#Mx0G2|?_yQoM#(XkAb$jb-3cYduXI0Jy2v_v7;tj z_zeBYrPil5Y@wdo**<|e;;2b)@o)D#pYP9G3dw3WU&S1Q59 z%12X}eeKOJ>0c=zhHblfZCk6D^E_af#t!(5v@UprI($s%bt|+SQ>9`dLPcm|IpgVg z*;rSdT2C!xl{MUL!4LFPxQk6`CX|s!ziS}B2e7^`^?zW48M>MYz@!(|Lwtrg3YE8(t+g&P<{{w-W9^hPG@9uTM%U9MK1gl3r; zB3MhK!LS~(UAQeE#|py4T6xL6o4gX$#%YS5_q~DLIRlrQo*L+JpU{?mp|wQl>NfoP zCZI%nU~D@m?v9e{DKvw-Gxo)y`y@Tp=@s4bwfWim&i<67+Tqj%X@@#xu_nN3k@TmK z)fMP+tgL4`DxQx#yvnoyJw@ek!$WcMow2t;7UzOMkXKU|j{_jv6ZSl`yL(QB@%W1C zNo;FQPirfaZGpPC8KcoqYV7==6}%M;`}navY;_+dJ{KH(GX;&wRDjKF0GJY2#h|qn zg1Ah6)x{S=9_53u*9VACO013}X|ipyE{;pgIVT90#6LrzD-7fts7AwWXPtl6ya5kjrJyPZh$Pdl z=^=lV@gTWh$mES9G8!oTK*+YjUt9GfJK-bK;bwLQ8Tkix<+yFJql<*|HLw?chEHfA zNpowVpVR3WgcxO_gkTC<3PHa{ghDug=B(#hHg7pcjgc%7up#&Qi+7fUH1WDQQ+DGr z)`v2xFVmXmtm~6a8rZ}uEPWsch2dSX`&5Ub(08AE(+3r|$dp;Z$*3J2@!V)xveg3-TyZ!3en=HAFcTiLml`~Z(Q>Mik8}BgHS2I^2#QL$&e(P_`>ThnN zq`#cZxYk`eUtFDZf33tjbbslvi7{=MSiAa5rE8d4Gf)MnbYlROF8SZD_WpgzTk(IF zy#GjfPu8(CYfB{hUGi$k9c*myZ`^nCK8WRqV?)b0#@uPl@JvmiE--0+&j+vcSt5JfIio>S&vs-ORsiiks*>l-RLXle!UlrB*|l&YpLdg1SMg%?(<6`lHWJ+s zDO4XLhSf9cqhqWU@lo>u0@9vOCbh&c!oVyj3q$jc6jw@=(V{j#M57&&`02a(l@Smps|1_)|*Xx4ub z@MQQaaAJ?0#=5}How8N?wl4`P*vp6YU`Ghs>B3W<88oKd4y#S?bsI(WMe7KI-QwqJ z8`D|Ag4L=) zlXV-p8yY9hk^;3Lf6JP8H!4BP;lG@dc%eTCM=?ilKjpPk4XB2ii{UA*?T#E^{vaoGh9 zNE4LoP4NLq2)@4Kakj*wYamO(e!H#dCVtZ-A4dbS8JM1h7DRg*$n?{s7UQ;3q?#xw zH5kpGw2$3pw1>_Jk?CjHFdN20O(!&#B+d@9mSS_A7_2bhRJp~MMIn#!r&9^x2X2EH zlW<{FF1LAjuM?qZ_RfD&Vp#9$;Yvf<#tDA3p9Q^wb;s)a;FYsIb$z?`AqnanGSUpcEBv3Z;|;#WJ)N}HKXh^vGzdq zQ*Ce9|B$Gv;Gl{6b?`Td@Sbdc`b9(mwv%iXps0z(V)DO!k~>*d-JKNVN6`i3%)# zlc;~9l$jNevm)U)iIhOkI7LjD9;3eBCmR;}5b>7*12JPd{gXtNRdSrEGubzm01`#+ zT1W#(qzoVtsh=J_fJAVOkwQ-Yi$sh&3Iq2N(&b?A#h>E6R`KF#M)Ij~zj{Y}s*3}_ zC>+<^+jD=pwi;^!#QM@c{hCt@n@gdJVVe*B&Kl#kPkbdj{FUv%DGr2;Pto_fZ%8K! zn-4e@S4oXMS(`n1m7T1V!hDayegJVJGpp9)X(SWEd^&?;T|V(y#qxqoI~a8`Llb2hWo-`d*U;tVYHdXIHboBzp!{44V$}%(Dj<6 z7xG7w57aV3Ixl43#y5IqJxg5<8D%G4zq!?mCb}bF64_MD;KlLa#egy8cdpW>G)RZ3 zl;Wp43vnv){xFXEdf;~is-2nVO}*b>)Ux5nv42Jgf;z+?(>9OmDX?%FY}F{tf>kOM z$lF>%)7Sn+>-l41`I8o2G*&)e^bB6o{brl~wu$z$xu3QKhN)mbf2Q_ut-p-(uwm*b z-a{mBD&-?!6rDMk;oZ|oksb3~A1h(gn$;i#p^2O#yNq}8D8F#D{bh}F%ST zZ-ZSsL@UTq{)uBSe6)KT28cQWAHjHJyLZwbX(qVg>(+PbkkV=J%}75c5b=|N_@r33CZc7toD-O3hXGTxUPIHp(fWLold;4osFyW zim#U8s9^tK_oa&6;b2maxN2=Lc+Ih^09$7YO81oB^nLI{U0VJcMt1qg}xpqQzLQ|84pBL9f zZ~NP3pt5!8Y$+jR<)jPAuZxhrBxO@fbt^jv8H#*~K#UaY8ENmRo%wZRO7ra04)%Om zxzj(?xxTeL=2>$a280`5biSIW^a*J{w&zX_TJepz7|Y%B@!~3udfoG!{O+voICH0e zks0%O{`D_6DK*2Tkh~v*zXiPhpEKw`l|}!)LR1`+k`$L#6dMz#jv5~$3mgAQNzb^s zqd-F@AvG?obPi{G<8Ui)8wp`|1ATjaC#YDgSMV)0DLFn4Y9=N%DK@2lBq2j1J}EU% zE-@=5_gh?65^h#pR(dj0R(h7I7NTxqs#dJ7kr}FPHZZCR5VZd+Myk1Q;12?L-w!xC zG@#u+NJ5{nRG}s-eT+UU74yXDCygp+r{;l&P3XI-^fg=}q)&WsL zu-s(4gOLE@i3j3~I`TyZs)pmHTX7tc|K>uWBywdeuH;r6R&2Vn=OIwaVm@MALtM&W zAr;V2+rQvmohQP?G}?irFo*RFuJ0>%myby9(Gfw!UxW$-iaCTn!KQR+0om^mJ?ZpW zF#DOE8weRQ5>Nql+(ooi+EIk*5vL+EKcyqlGhjNEUQ6rAWo{T`QwSJohc)H+hOh!- zP=Gj<@QI-#2C^#H)D7^T<+D~Np_`8SryY&g8dBm@@%+@ z1MWdPM3ta3%(2i4(IeH>m3dn&3=${HU|J6qUHD?M%iTrWJ!!&rIge3A_K9Eys>1{y z9<7Bm;4`pj%keb(2$PKpZq&~4_qCL&VrB03&D^;WBXQX`4U$ITmg8J83!_g_sUHPlfWiqmzkLGyCEyYqklH_>Db!;Q<3<*kX!Y;@y z#$c&`>&u@6S1Sy+N!YQsy(Drn{%hXyN`IC1)bxbd(#~UODG*~-OMKpX>EpFUjK+{0 z$bsoC`(ymfYKtKL85VZEj?!lVaoLL2Vqh2P7AYO-`IYK8-BOFnr6EQ9n_S|av?7N> zN29m&pByOPWrD5Z5RS0DKe^ed=ql14BU-E4hO(mB&ygS7O|5P`h?rzVs2MPf)b+3o zr1cHHiZ7;JHElx<9G1(Jcnr6`aBb}?b29rdI6vyAEXi$dOQbAy<0zC-SS$LcY7qkHcEC25a_MeJLuitq^4|I12;b+9m)n>Xn zNLIoAFgnxLMA9|HJktL{m>33`__Gw4w!svS0a9>SID-ne}cln#V zMDA?GPjg$9{?~(3Y2NZ>+_RTc_Py7!vy7hR6;vLF_3V!ubsvH3rQq^`e7yGkV+u#2 z{MrO_7*eam42A`jg}5m@Cva5i#WgFxQPU^L8xqvvF!#^-pD^doh!8k2!CE?I=%@{f+_)wD1g67$$S9)sb$T`FqUWQOnj@>cxn}k{C zx!NATh-Sg}zk$EU^5Pg6>RiZy3hF=KhR&EFZZ#re%LsIW2YvI^f(47U<%1I(~ ztZ#3%^l)*xl{neIICZ!jTU){5q|sx&(^W7KmiQfQ;Y+9THOdQjiPm7$2MZ8w@fC1D z(iIrNN-WU4RZad%dH4zhz1oof*uJ95QG#NRUv`+1k*NmKxP6JZzf6}WGwDhfD~&MH z6^x(h*OA#yl?3|%czP`FO0~jz#b{|t%6B*?7wqG9u(D)x9(?b^49p8+dM>C9^6z@=sQwd|rZMonYS8dO| zk$x@9#VaYkaonwe7yI#z?30B)gwTr^O!JcUNkPav!9p1s zWjs3;V}N-H{2+8hpff{k@$@^ZgWpHC*`=~uiyupoQ+8m`#B>5MOvDkuu$2$qR5Z25 z_EX_4PdX%6lRJ_v9y+&;$gKeph_&fCxcSNT5Klj{M?@ELlg^RW9qg_0Zuh<))jx!s zqK(&HD%3Z%DV=mjSXbsdq_P0FYvijiD0x4sKVf@G9Gb7@$o-jNC0}LV8Aka}hAj>$ z>i>&jj_(Y^sFxA_f+YXWu$!&YSE=@D$tLYC;x(;7byB-%q)f0gR)!;?8N?*@LYxNn zH7b!i*}=8+0diS371f*gmew}Sal$B_dc_wqgCe}d5*QTN%J>p$E&Te@+=f-AnzwCO z;*7I1mO=TnD<$>b$S)`;WF6EBX~I%z?(QnHX50b+DT|2HWibo=Zi-ZBHjq6VWY}W& z36?&uAfdq}gu|#ToO!Kj2JX$JP%w8<{YHX@0+?SNT{bzT^i{RgW_WZ+7&Nz+rAc|L z33*DM4$eRhK_l^7Ur>Q`dh;%{iIdXfHa$=mWiIL^H)g;0-S+L|jnPI8L^VV@G`Pgc z`a3mBp~=2hvZTwgw%G2*?fpej=EAvgCfc4L=4kTuK9BeVkq zx?J73gCVVjvVKw}6k{6pK}-=U3E34T@|xsK5|-}KgyJ^ZvAKC`oW$JDM;q{5A7hcX zQtw5T&=j$T!#XnzgXm*J=ye2Pa5vx4QS0^u!9P(YxYDw0{pn7kM zVnD`kRgE%$>pL>x$@s+))FA^_`@fbm{FVVKEe-_teXx5xd)#|oYkNF*nLXwR43gN8 zKavoEnD9}>fPqLS1wX>vVS~E0#^(DRz%_|inZ!_~ho=|YOr@&5JSd03#>|5Z zZ`0o=+YjlDwuy(_dBTgBb${Wo0A8%0c}@}vocN zyYJ(|Zd+>8N4-W72}x@LV6gbPtGVFNwam!J9BVOcYxW zjc)t39K>2rR(NMjjpt?emIHakqdtk_{|H=>4h2PH%;NZdrtjN_i>kJ2kf?4i+VI)_ zH8B`Vct=;}-UXr3WCPV3w(jQ32a9@$B*t?vf{Alwuu9Z~XrEp3s@Ia@Oe1D;9qu8@ zy3x*|azlMdDHCzi3XDw!d@WwuWN5b|!7r{ql?QMLl<3T`pfybcCHDn6N^zAt>x@1+ zaM+|m%y$lI4jAp$^=QT8M;S*mrr|-)*bNJQEv6>bBHv0lVOyc`0wTn5MH&8IRLCNH?L;7nb&*F%GA?Ign~ zq6|4FOdb#4qK)jAztof4mo*0z00zAeNB$Or{!%XCv8>YH7{_IJ9t?7x7Wz zVqk&F;d5TzgDqluynrMEg81P8MeXkt-vUljKRn}Lhpem2E1olltRD7sRQ%fB7$C{aIx^G2CbBRjM$t+~C# zDeVdmXa$U@_jsj|nPyjimDue`0j>^q23#G?bco1zkei^)5Yf1n<4lpqf7GZ3^ciy$ zCY7RLukcc+=LOwwM@^%YeT_bKqR#-ppbsF!$XR*`^3r1!GWJfX`H*A)23_>XiM7!n zG$>ui*%2%Ve+2KddF<=C_>RXL?B#=b3qP+Y^h11Oqr@G+A;G3Qaa%g!4ITAQ`4Cyb z=pw+WmjS%OpQ?N5peC-1yO$=90ne#?i8iX~-B7EjrAx-b5B?Jm1qI=-KI{k-J8uZe zGsCRlOL4X7vwi@Evex*1V<`Kd7~nc0`!EX5 z%bMv|e8%-4GA{1SkWYu)9#AroQ;!lYTW^{zNU)kMlASQnrhj@K7>yZw`qBMF*6K&7 z`aVd{Xiie8>S4KrYtn)Ef{5^i=)>E}aZ)dEfIHy7AC|bUO0-WO24UY`X2(j=FX4;K zc1CFC@wjb5!CKR%h`Opl3GYaYRVYPkPSmGQi2Ts{PNK?aIPVyu4tU29ZjI{gJBA8> zV<`XHpc;UoP_4Fnymkkc8-metBbZwKoLV&K4VPG)j}4}5@?P6 zunghrNy2E-P~rt@8ECsL%5{#NEpR&_s+wYbE3A$dwt@__qOcr?K!cimbnDU>Ts|}G zG0fyRh0pQR9{^Ndq*{Df2gUAkFWrd<<%(`2LUpfhYdnS3GR@_}pj!*KYz`0K<#394 zwu6`KdlCqA785s25E3T{;8@iGI?0-N1th6BxcOG zV-ysRAe^kdl!@G(rIYkZB_*$6rWh(!_g;o3!qYQ}eIoMO#?024w&nad9z)%)HFr)l zdVN_6MXkYGWQ+V!RA7@2lgIh2U7;wIqw3jX`Qz*T!sW?BBc3fz2KN~mP#c--mWwEP zIOPOL@Om}N#5E2ZmYegz;>guSqjsfuxTnCh`QtHrrl0@qUrIs*8}f(*KuLH8c;Wx& zQt00of`Pxo)R6<;!_?tgivJu`Nm6BHCMAH`8uGS!sTCFu&bl(Niqb&8;N#3T*daOf z*tTr1(wh&MYCUR&_CS^{*CQqwQhyDr2ERT$wbjUGZP+Xy*q-b{F9$~Rq|}}m7RP!1 zwiCh;tTfz21SM3WQW*-Ljm-+UjFXyVyehLUaB(rI7sa%S)$~uF_gzGON!*?k0buw2 z01(xG`n-RtfdBJs`hBS$`|H&}TM^nB4RiIhPEB}24?p<4V}y~o$d-E9h6qdNAbK(z zsbO~VJu60Cs5rNzV6*er!C-ns3eCrYd@L*m4%Enz8Uo^dbnA%NnZy0}Y)UVOvov|e zRvee{ClBwlE05E=mG(9(gI!;7=pTR|ph0t7Ks8S~0n$S~ukGfP6a*Luk>xH;GYjR( zd)4#yrmHrreqPRvP`ANfsN`^XDjDNgoT+(M5nDF9%<^*+n9q{PPj6<3{isa^gvk_3 zpY1|_r~%qf8NBb#1F(=NxIj>myC%7bcunQjW|`3h3n3)NFQKQ4=opdCjGoZw%A^74 zRZ;Mg*3v68LcN+kPzk<4N}q`$ho&gW*%qNmi}K+_qxx)Pfn#KWfJ zvC#{oWSJEcOR2!Mt5+WKB&hZP5zJL5+n@TC^|yq?{w*Qxz@|&pN*$7iobwmD*bvhW$CYvY_VondFl>K*LYr9!L;rNNXXYSQ!`{<6{uks&%{NmHk~F`(0`zIl7<8^N!%1k8woTL`RoCrEuNtB#Lp5^}wV+{}DkicV4NjArb-_K!-WqwUdQ8m8qMLE%aL~R42*|{KHS~`Nc(DSC z4O#7|Cf;(d10yw|%M$izJ^kE)7nv?|N5|;vjtOlC$I5#F)BTLW-Po8rMa*N~J^O8a7p_+I0aHuev`oGTfL7+}si$%p@ zrSVceHCKP%C-&^U^Gmfd@lNef&Vt7Jdck!G#CS{Ibka@IAS<<()&yzaYge{Q{T5_2tdsSr1*mo_m zkjr+4R#NX5xeddNUr#Do1q4-6cqj$m?z0p0QYSU>w|CQ1YUD1eX+nS%ZkVkUt$qNg zM-HKk=?09X2~k;le*x*hpbXB-T*5;8&oFo#Rp-qG2u!N;3q8R?CefaGJ2#Shq0yLM zJ7(4vk%;GDCtJ`i%shEYP#7sZ8*-Znucw%8P24LSPBupv!B$Jx>gv{y9*1+Kki@nI zED)8dI{!2%dS}&y3C34(0IS}Q{rq>V`cJjupJyhLFvoRC?-#mHbTQ))s>jB-&QUbQ zjC#M%Oa{>b!ZGF3Qg41{L5>#Z+aR7HkrE4Z9)MN)j#QXQ#=>ELX4T8y+DLK9a+FKf z-OJbYy{G20yR~2Sp^M-o)Ik0KR+0a~DriCgt3dz3DuaKq>gOM~NcH=!^%Yy9pjTn%?mbZXZUJI+$(Yj8LN&f_)U@Qd(FExc zCdS^7wwP`iQO%8>Q|k$3AaAvCNKmyfLnh_mVYs<_nc`VmGd*v|>%LmGSSO~O)iJinFOU_3$!S{2pK z7w~-uGBS@3#D~8jB;T%iIR+R&|4ZI>s+6V*K;VSIiX!@%n`zrvl&{R?ukR}8*W$p@ zGonATg%7X9JMQxNZ0=>oP|>Il(s!(98p=6JM|sj}tAtJ**hj*KzZO>OFln((#dq<;xvs)MDmarT2GGf>!?Eh^Up)DFxUd#_wym$=m`>yI5l(;LYl{;JX)Mzj` zs9Js2s1&f&E!bY_TzpUE-Iw6VX6~c-tk9T4&3^l z@|s%4BY=}yxyn(Q>B{X5fb7c6g;vWwrmWNfX+!~*+ff-m%9%JiWvp-bVVK>$1VZH{C+Yc@QfxhySb$wmxrjv zV;hUQN|!^{bK(4|;C3t%{kwC>TziP|Ln(SnE$bA??-(!(+?IJP2E>ip#rPaT$DI+8Q*P);EFt#QM zaDEMb@J7NyRhY=%H)yt&frFxe+uR2~y|&WQI|(zJN#d|1`Skbg2!!Rs9C|9ton9KW z2R^$FhQAb2bpRG1?GKF(-1sXQ>XBhUMNz?QD5}>oCfzHjEY4a&Ko0f=gM3@iBcc{$ zFhC4XO}|AUC(|1+oGv#bpT9}zTvQ%BXhQLFy%d>|^qtW3f&9DHs1< z==r~I>{}ZA;=a7lH}XoB-{COEMllsK;+a+vO`M%5q~)D`=XIuw&Ub56viKNaWeZ4xwy+A4Z7^6 z=~jBG|EbHKDx;WVkppqQ&!7U(*tZWOWtK1azBU{HjZg*xUl}K1@#oQzbWRl+jTSio;aQZu5$G37FALp)H0jz!~X#D0Y z7-H6FCdK)qMniTn6Au0>DQd4`$3vd8`U71x2k{zjExovkY6Hm@3Z71i3RGw6QIFI8 z8(j9w3vgsN2s>@(Se$_2sJ&A#kLr*SA?qhbnqLN~DYThm%@O19K`DMCY}?Ed*o+w_ zK{pmQvpWMRRl?qW5OYYr-qv?Sy*hxdUX>P>sLw{Emmdbf%tdC`Dh|-qN9<)>jQ!Eo zw`_`ts~VN?O17MQRJIqy!PqDDL!CT~Dy?Memlt2-z^dd|?(`U>S)_f_y@@Y$Hfy5K zoC@#4wfjtL-y{4o*nU-#WNt!inGA^)#AZ@3_^CNLeV$E`>m`+wFk$q4-BC;zhp`IE zqL;6|IM+({GBLRub%5pA0cts}_=G#T4!*!?^95mH!^$$$c+Mltk4WKbsja)0=X5PDcM6J;u)UVi0E6tF_%8)ds8`47A zn`NK05@w=(PRXlY#HVDcTbQacHk2Rx*O6~0i>WKCrALd}?g4Rbq8eeRzb>jI}q+Q8zgFg?FrrRs`})1b{kcB0N* z<@8S2f7YG|NG>6mRwj0cfJjv1SwkiOdkkI6kJbX2!NRl--T_c;htL4CXdIUf9dMq8H6Q^iT5|<;@=B6|Mv`fA8@q1{!1=e z<-!u_-e{yo*4-2G4mbHKJkzs`U=Ny^^Q311viN7&L6Kjq#g7s~EYwNvx~0|76f? zYMQL>6o5h3NxvCHa+x|jW@o;_t|$0U2%ql<-{X3Do}`s zLq?(BNlOWrybEuT9($sM5{?a4H0M_lq)L;Z@cKaN%|&^`tui6Y4~7cMuG=fDmW@ z{yGqWP$5HZ#FqR!Tk3l zy!rBMWyeOUF7qeUYPD8N##I81K`IQoZMNieML8HwwxSwTynDlbA zrDn@{>BNQAecxf87z0n_XPjvV@*QI2dt#G@f?ybhdvfRRIgHaq`D4^U`VlmaiGRyQ zqIbD?_&;(H;~#QS6Cf9VV+gbWc1j1h5PL6rG5OYdEMde(itKpScDnqYy{}D=_f#nIa?4ex^?U6Pf8D^h#`AH zROPI4!ql7LGJpKt^0r@KiwMS28jM}HOvxOwj;vz+4Lgm3hbDP%AAcgHb}13;3@U#k z+Sdn`%ZZ5qu85PL8==!-=bI15_^?xj4wOA%WoIi!g6e zr+)&hKOT~&pOUaQRuYA^0sev|o6k6#90eluSM0q8l*~;}iTMTLSxnQ#t>z3wwm;W3 z=|(c}R(7#__YXaYbwWhu44?Z-5>ljzy&!(%>;ng4Yqm_EI9PNce))PgN2ja(!&mtd zFAyDWqBFdTRhJDgi~4bKabE!32+RFup<% z+ugotPuYeu;vJrH-gFW**Iz+W2cou} ze7?Iqrc8=(IHiKiSf&WEx+MOJUulO!S+KG0i}!5fr~AK?Un7d0ZL~YGWZn60$}yW>F-jO!UR5F<;<;J9LR$U!$}|l-Vpg6JKD(J_T!T__)@OJvGuPKu-@ds?Y0C zn(xgwUvLJ)Dfla-*EJFA&v|9@g=TKr1w$y#sq>sGs4Pti9Ve#*ZdV~A=b^miAt*~UVG}axk_DsLHpM|?OHDB z&!Kph;&QF8f7yZ2NqBPkn{x3ltol!K(dLhJM#Ix-v@?$qU+xphM8HP2<9TXS4AqdB z=Wn}6%K%0qWAq6b>5asnh2A`?AgAq*Nr=WDcJYr%2qM5PGBo_pB;?LyX2vS|>FZs( zgEt_c-0jYOx%VeXEvgScDA08sBw!FSaQ-eASKbF9^$V4h21{|wN`OH~0q@UDujp-l4PJ&mX=s`DX5_5P*nW59))c_&3zz3wX^_;^;SI75n7HLdl$WX+A0P-yW%ZA zghGzA311!p-YxV1AKVt9OOgr4=SX{>fm8P0~!cyf{+neVNe~fqx6?g!Yz# zVy{c6jMBr5o}})57^3sk-TXcbnZh(D@qq93cqY&6i;nlZ)aIwmwAQdW-a~bI?!JBs z^059zOa8UudL?(+70)nWyft#qt3Nkoyx?9ky}t-x7v0|NVhxJSvy+`rq6ocxY^O35 zNqz?gxlmWA&b;Rw5A9N2(JysXPrXg(I(>r%ZnH9}B&nY^#_qBv!?;40q=g&#$~A7e z%zNqP>9O@F1k!9roK?$YIO-?T5%sB(PInfVT1T)q6?}=ZX8qzSKx-< zu4{~TSrwljLhMxa+xF5fnmNEY4x$G%^=*ZqTnl)hz$z5hLzpfzk@sQNhn9ZjGH2AU zMJ_>?_AFu7st?%D*fCmatFX)L%u58Nr|4c?z@dIhL-=)u0K#(mG?9lKy((%VNMk_t zNXC29p1qseoK2>PVf$!)_F+2jy5Wp) z<-WnEAq-QBEM+1Q9LD2l%J@;F`LrSYHNB#BGuNZLMH!H&J8D{Suz%qhmkDbT~VWq_MB$s*}@WLzgnA%sP>bVauSn1!SqyA~~F`#2}ctCIjy zZJF6RNb@oXaz>TMiea-R8I_WCDK7lo106)_`fC8!7k!fHnhelwg-qtHc0|vZY`{Rf zkd?i7pM{8UxaYVGu5e)TksX_X{2t1Pz%hb#F>^CB{Ggf^yt$MWo+(_Tv|Qh~eS zgttq-9i>1?Q!@Axb`o_isoGU?FgrFIOuP4~1*P51u4?`zK{=(cx;J|Eb1{$ipRC$@ zDQOzmH}f~;;{U?ce4M}sJrWYE0dxY7VL@%>`H?w zcQLKgp$uPYrP<=+c>JcHO#_xk*r3?|Bl!ssx%l@Y$N$mTpRXmaWO`WPM7qbVSuSm6*H~(Z7$AzZ zjj7niR`BlLnuelyBU6zygmQfIoCT~6O>IR#lMweWB~6Px=n*fD+bW3q$(|`)PH|?R(6VDmGVN(E_FR~V<;-!$Civ(ED9Gx ztg`_AJW(9_p}=20afEKoD|o3n9;#w}2gt{aX|8m*xsr33u|AprB9U-NZRemNrkDiL z+>i}qUy&rBSQ|sdI9({cN~I5m&v*Do%6DHMM@kYeCXq)@G4IZ6r?c<(Gk00txO{L> z`K?h5+V;p#*!)7Rqk2pD zi8Jn!w_HBgOW!|dLXF}%4oUzHRFhr2V%*r3mgZ8UQhUD**C{+Ns-czly?FzjoVl1G z;|+s8IQb%Cl_r&O)TcnP;I!nV+3lmn9eZwm>Cf?wq8r@Be#CF&8LyodcUF^ZqSVaH z?}%@spVAe5d~KP=ihG2&AePNwf=}wei~&>5uj=7Rsh0{f0UTkh7j2#5?N*NZdK8c* zEbW`;O>5z7;5Z4%9AA}noi-?9+H@Rdg`HqD>db~J>iC=gXwwa2VC~U!v*!??tv?rf4M*A?d8Qar zB~74DEK*k#(hoJjnqv>#F<-cp%aJq|By1sOO@llvgl-XT{K{RDCCcxs4gRPva#+v{ zgl9iLfTnfqc{$@73<~R^w&56V?mUFE7&Q2x32eO^%A0;Z&ZQ;YWwrUi>|p7`wFNFs z5x_3$Z5$zMjUq++?xtkF;#XyEFp2YX?sNs7hD>~Q*Eos7rHWO~jn$+v8{2kc+qRuFZqV3jY}>Zc z*tTu^{iXXJ?R(#I_Pt|#|A35vY0J_-4;r@JkDE!aK_%raz$ zxWZ5FpR-)jRV#d|K`3R3it~0^R7Dkdu<-Ss$_PP^w@0393|?#8jPCXi>38>ax4$?r z0O+Fp{iy7qKk~j^_nk6y!5fMOOl!mA=8fUz8eG4xD0i6|%lAt}=}z4z_ifQ z{adcXe?S-iTEF<;+{L-=+hy}3lj-DZttmM0Sj{PV#GhX`9V|gf79RUg#tkQD;Sz1O#hV~d=a_|6I`75s<0NM~5*|Iq1SarEEaMO6u!3#4~< zu|^l}_X~%xZ|GghySqrIdODOf&4#RMDYJS4LytR@d}f}U9a=ajaj3?W7gw#!XuHaK zqZ(PX>uwyxsk*=xhh;AjA4zC31Dqk0%?uVJC8Ubi?Yu{2W;{u#*4_;aG+|OiK+#aP zG$`)?pA8Y0UFbYBP#2ZJjA5zIN&wIxzXX1CylQF(?{d7)LV)FVecI^*?}1TD1u+3` z7{U)Y{Bauh84Bz$>F;l3$H3Pa$qk8w&u}2%_J^?kXfT_rp95Y*LGCWIcto97dH_14 z@a4N`Rs_L2O4E-#8*V%oZhRLmeqzh&_H~s*t9h>j49DJ^s2M)MNcw+N)LcM`P;BvZ zQ6qb`D1x8aU_kq7{7i+>3vS2jA(_$Bm$Y*zrCAp};#+=XoZ{b$#G%cZ>VT1k2UF>i zulq}%^!)f+F!pRAmts6letYD1TYMSm`?sbQ%=pJohlJLxjFFLTSW#f2U27W&!>S~L z&@*U5Yd)dtt3KMo80q{wQrz!fH98`3BMQ+zqh zYck{kY`F6NtA^{l&T=H6uDL&Qdf-tV2<}EnwDaa;Lp_Lda5ooX@j12)s&Tp{F0R=< z^JJLUX6QL(@1L=+ih#%-j););-J=mt~#5dIewW@gynL2+!K)WZ0Rfawk{`#aa{wy;tVY3*Mk@!iWsZSfJZX%Eg zfFT-Lm{yYE7N(+7J*1rAF>@Z4ZA5$;M5~GrvZ&VkyeOjHn>`pmTVs+qoY+rLOJi3j z>t{G=N=EvrziBLSBn-^l`38aKx(>Pw>3mQM%L*Cr$^m5)!Vh@mfCfZ_QU`-R7Ck>s zpKgG~i=Q)PuuR_HTgB)M@LIBGLi*z`)AXXmWZi3z=NKMGCmOm9tkq;@h?3i>4Kw8k8IU+=%nnF^ka>8qoo4l@{_nv z4~k=V%WMZW^=J&${6-hc0q9~1^S_{rIsX&7xac{@D)`sX#eZq2{EO~l+cVu6;Dq`& z4y67!9LO}<_T611_*Zw4?dL5eEZ~G154TUmWMPtqXk|WfqSEC3{*bpnlJ4KTi-8LP zC|v%nWm817h)+bRmN+v11d+YW*ye1 z(?^38HmA_C#%ap2G;2lnslX8@>(g(ow#7#|${n$sPhcMC2em}fzTQWSL*bn8H`PI( zje!%~wiWcCg3WvEoUVC}dJ|a&NV?s}>@H3S;?4y0jEn*|J|CNpD+Ew%sUP!7-59RPn(i#F}!PY{UijDn?qEbQo|?+g3vDRjXPwG%)+qvBvFD@5^TCxje#4+0Ic zOr+7c&o78#np7{?XJ|Z2Z=o6trJ3iMTM#q|D3MQ+52Num7!ZK z%%(ipJgYU*Cp@E*%{t^vJ?d7WEpPg+Kb{b*kWJto0P|WPJ1G%syL3*$|el?EbD9>z~pL zl|@lz%Nqv7Sw7yFyXBy)oaiI$>=^G{eG(S3cOH>Eh|1CYq<4P^tZ~PS<2OoDdRPUP zT1tBw++qjI!BoB2`na!%ZLC74hI03~qP;YYjwSZ2Ag)(?Wc{xbA`~>c=wCD!|0Gra z$z1$z>Qk7}$;=N3d#M!H+45-M?P;p?#3 zb;tw~m=E>?Y1W!v#bc$kf0>moCDOXl(Rx2_|W)>h;kpQt8dkoJ^r=L~=kk)X-Isma! zK?9orisqx{=+OE(k2~{rU^p;nnb!av?V@bhc9whrnd+mtO|n%=yB+VN)tK&um%Mxy z|8h3e+4gItgn)W+Qgx}dKws5fCE1?&h*BW6zN*f<&xO2QiGHVKIVr-eL1!^$xLuss zfHSh7pA4=sqBJkXfch~I=;A}UVe&$HzV+N5;S|lPac%CQt!3e3Ea;Toz_jTS@U>8s z+L#Q%fpP2AxAMiMO6knLdKa_e0)F3Uzr{-#g4O>5tqA~6Ar35{RV;cc4h8}M&^s<1 zM|+mlS}^r0+MM}N17$2r$kmL8sYC(tj=X_*@k(_X!OUiMY5PfOD9ebq)Rxq zsarr2hz5D84dusSezpJfj!$e5CT9h`iGLwg_?vIZk-^YC3$BDd3k(( zCl?_cgx0LIev^wAzsbc|R88A3Xw#45@8lwOd2`bs4ktc+^L8?owFal~_i34?`H2}! z0wwtICU^j7Eo`b7&vfr0=xDqhYrZ~xZ8mq9t?Xdb9X!$0Ft_)*m?s4Qt@F)3DWv~1 zX#H+3Mh~M$y@!p+J=VZg9gB|MAvg@%J!-O`b^Rmn8^aT#ooW;p?yfL`-HXE&5 zlRclqq-Xgd)i)#kX|3Ok75n-Z!NtGU`TbvOeG?0D{hpS(aQ5o*YJwwc!EsVt6eA>| zmN5nEz$~u)znml<)-qz6UI=@{M13WDUBvp^MIusWZeSqcjehJO-r@#etw-fZc}lrU zxpPT>T6P0KLlQLTq(I#9z!|Vt?{C&&IP?bJ*M}+8A^QwmNJHdM6%Ng$T-q6aeW$c` zEwBux&m*r^n=7JYN^j2#!VHy92Q4)7Ipa)JR(1?0>c^S_bnB`)0DUr=)Af+%s zJ3GmAq%IXYx^o6xBuY9QLbV;0T}rHMk$Uf#0N&}EED7_%gqF}&As%By@lX_mrd3g+ zXr~MQ*z1SqzsfXW$8%#4e84uy(0**XQ~7@QB&`dd0S-DDPx$1F2yWlQ&JPD>dluCF zN*LtkGLcT$Y6Y+pO=bZJjM4VkqX0>T;}0bz~Oe!KAO20Psy z=CRIi5*pq`Wfmd*fd&WeA4JSavmm63ep z!1~E{lw*>Kq0c5W572nzdh#@3C zrh-EjmKmz2hqvN1x@))(EPX%O$;K&Q35mLGWLYlP^)3~IH3#;M`5y5;G|L$TqySPE zN07$a=u#+RMx2=7rIFfLb+z7e8eK(uRnm8dW&N1^E$4TUX7dq_2teaU{e-W@ahNeD zrBQD}a84zIlL5pK6|hx8lq(sX34|L4BD9qwx5HsaH%J5*<@sYTO!Ib-74P^ zESpsHeZ{)qw{Bd2Cx-er-iaYVI+}~XmsyR9{R}4=%JI1!mV8Gz9-GFGYap&%VfAN9 zka1Yo0AgtWNO$D*p;%z=ESmk76!HRq7;+b26t=I-`@%LZeM{6bjghfNZ^HpWBP*%F zob8#W*9@wdh*FrUIDeJJl~+LkOVbXp76<%qG2fP1yw`XbJ?$UX?qDoWdM!k4sSgdc~iwqVruoga1Wq@vjwp|Di#2 zxc{UGw zyCjUC&6#A!52SZ=F%thfjvfT43Hhg2q=_*Ee$uZ~TTtfx)qtbP61;M5lHH2VT+|$O|;}i3&U#a3uKwyv^vW&=|KqAjj(8YYKE9q0m+9C z0^@x1E3!9+{U6B()OT#CiXKP!Z%I8~--<{WYx%pwf?{}~Zbf~_f^f+&gw9f>TO}AM zRJSbVS%(>Zql?=u#}*gY=C7d|%xf$3^kkl|;Vup`6rdP{OqOmb^*u3ltaZAcc{N<& zi#VhU65RA=8kh8q6}EXM8rN0jQ^%Z8!4i-a1U1vb!Fb%8mJ)ve)F0rXu>b%yI_lp6 zYLMkfCeNk~ZTfeBdIQVkWcA~85zIf*83vPtzrG2KzkE3&W^-2?mxMCopDGu7Qkh0k zUd*ey4RtR3RGN%h>euoDuoiaIis2R3@d!~)tj#@~Ml&-sUik-h5H6yp>@!BCCKO3LK>SxYY9tfk@QPVA@Ial`GH=I8qt{-HV4 zH}?qZvxL=bpz|!wpf&7RJ%Jz`)@T1(?>_5}hhJ9|W7?Y2#|}-zRLGwf;igDv&XKU{ z-u~&G^?f45y}zsai{#>eF7y7gwfIL-BKiJ0z*=1N?<35q47p#U8p~~Pw&`|X*3`xH zfi(&6Ic_E_9c!jC7L+J*CoLF@WlhOw(xk9uo88QZaQj+*3YQP+s*gG9DuII?+KFM) zSw9I{nljx9uNq!pFOnN7p7k}xY$piR{dq?3^7&9yJt5UyRKxbx)&BNRr-nDi zj*NeiT>O`Y$iLt%nqV3N&Z6^O%3H5btH4?u<0(y93TZduf(VJDa^@VU6oPKW5i&(f z1%2ZPUy>n~at9o-p|_Zy@NfkXnHfFM6SI&K6PTI$WQ9xwgMW$4*3uVRmS|q6yRZGi z;NUtpYjktr@I8K~ft-+mA{mG?J^~hY_|O`FwK&a%(Wlp(8E7g!gD@g= zGs7FjmVey9>)3-9vMN@=1sgZ|a|O1l(egl2cF6)R%@>r9B|$1r^8qUQBiHYEILjpYnAbv=*qM!g})9L;MB0+)p!eVYB-dz*pa|K&@bo^ zqjGJ6xQl{60j5v@!@Fl$CYA_T z))hHP^>+BNE+&D|&B3?;3AvAxkkcLQpC*U_cZRx(BifdLWqsTakj;4ZJyTnD1%_BI z>@B@FVVwEMb;tSTYVXQy!(7}g2if!O(_?#jmh8RA0L9uyZC7I4%`UH_Y(Ld-i*>^u z^K10x?BEzxQ`jAXP=oi9bEh$7V&nJV=3%q%k7XPS^*I?Z`HLId+VRg-jQ)|aASZI9 zc(B7_x*$@w&AaxuE}eN?pT`*bGH957`y^n;VG zIc;I^5wok4%K=q%-02~??{c&h$ST&cc1LALJn&PMX3HA#aqapZ$Il?XYj%N$t zCmBIH`i97oKYB6$nnLW*VvhhlZFq_RhO`>kF_P190T?&T2ISi#V%?Ug4{TF5Q-Zfa02D~6Vq~u*asR?Fc1vlR4%c>65PPVL z;+Kf^3rSNf#)cL0+(&i104zKo`&E=R7V>_LX&mK+y_HeJ&UX~3P>X6a+LJYW^|8jP zLhfh}QrfzqKsLs9B7$O?+2`jGvKgwAh$ZcGT7b|+`g5Vd+!B)yXRUk=pzNF*6n6PJn8cvDA3wF3WOKg6H!Z8p!v@z(ED*q3-%EHUo;p0q*ecGbCL14 zx%eAgZ1^9}qC)^tvhS2NfoEvccoiGkKfQxw{oP!&SGrAiqsh**;#hTGy?gqdB)jGo zF-L5Kt8xPbQv~!SpYkg#fU?#?vur#iGim-7I%3O@JeOXChcU8P{DKHD7ae^pLKv8{ zQ+1jTElx-{j*!fUHj|^t$R|K3zXY2{YeZ8PS z0h~oIB?YMsbr4zdUzM_Y-#Dw$;T)w&MP4|w=$ir)EFz^x*3jv77K^JT2O2<+XS|b( zD$&Bo`x3ocX?~wuZS>?kc)swM&#ig*V1Rt<0T-6H(eRpAndLIl5$Mtv$t0HleHIPs z!;QuZX6J$?)``PV{U4l|?uv&(k)~Ak0FVM=N`u6eSq7-oG!qVf+ zk(6l`jHXzD6M$T)U6`wz*8sdlw37=GfVZe{b?5}}7V}J70Vxi&HdpdziKi~Z?KzFL zllIU!SMI*DW$Sd>=gA>T)akp_)$Hw+TT-`FY&ji4O02JQxnB4YUkrA1im{{y-KXq) zy|!ArG)CD-*sqNd+3@IS-#}}1GwWNYl@cjc_qB(%)A-_BkqU9seLp+yU-p@eHZzbC z?U4#4%gj1)zhoQ^0ldZEDGt9MLWpz)qJ&k^fGfWMyv3z4t&l37g14!mtk@+9d(^C5 z&De)D&qbPVFyEqa!)m*1zQR3hbA$Mw*lB--YoQ2m&E;S-=BqKbyKSc1i{7nZo|71@ z#j;-+T!?2XoARrTCbQm|eO~r)nKGJwR-g6_eIkF9P2xW#C?>;YLVXd4yic2}8abAh zPoLe(&P#U(fQxfmi<37LS9!V7h23oc&KkcqE!Uqx+HLOur?%WZoiEJ#YFbG)0D=g* zb|=^0-64_QrCP&D{mXlb1C&98fr^8XV86y_S`fDOWP??&hP~{a#BeQPn>Pj^#bLfe z?mfjJX`ggkM!298UHj)7W|%qgu7pX7J zPX)S22>bnpX33qMH}th36gkXjW@F+6PtvanMO!Ck0J*A`hy@t^R>s?V9S zfs+W0)`$FjB@SiWwj2&!z*`9Ftt*%I!VEfy=(7r}_u&=GKi)##M@b;d_T0ZnF8+&L z{qM|0!Qg+Gi!*;DF19th%E;KB`+GK=wLc-sD=YZaP3zi2nrLWH=ZGw3j4FffP}9t+ z|B47`nYSL?EQX-?k}nmPhPq8IFFqk-W1xGU2XeH6UOG3Jbz2s~8X3-QfL0LFxgU5E zLr1&o0d^qr1D$|)t1VR=_-$+(`79}|J@>qO$}`wVZuwM>^PeW_chyFb7HfL%1^c&U zh>q44y5CGK4F5M3-0BjT!bsSdOVv8n%`z;NGb>@(COaYuwGgHfWYM^UKLUkDv&lEX zlZ6U+M9iKHN3ZQ`i=Y~WvMGVW5l=i zydeHZU$5Dq;z#R~Eu1zfGNcAW;0#3jL+L%Tp^=7N@uO)7e-eV9Rh3QdjG4HN3!`>S z8PY$iA}alzOKzR=y9z7lfy#3T=%#71>!)a^f%$c>E1i4Fo=?eFpc4wP!Q?B(K!PeW zmUMI(g-*2+;qt#UijQ_8!QAU0VLH1~_JBXh+l)hI&#R1=;%aL0G&Q*?n9cDi!T)L& z)^|!J{LwwHFJ~t@$jACoe6tfxmb*g>_j6>B(YW}pkK#1g9gxrPbe3L3HT;x?LAlo; zKwzl?krF3Vvv7(Bv?|va*au;ej0weyI|2`w@w<#^84nc3$c3ICoi@NZU0G`_3zp(+ z(jQ!VISsIi=tUJB4%UbpXDE4SF4EN+XYd2)Xmq!>o5T_>?5{iyG2AwaF1p-vKZ6>g zRdsfHZf1o((k97t_~VOCGx=vBVIA8@?Iq=Lg@MhTSf|$Kt4X&!EsI;D?lbv$bWASc zzjO>dLnqWq3v!6 zz2#9PCY8D#|FRs~Glu*?)P7D$K`H(mO2`>~{~)T1z!9R+nf{XKVVWNT^p=<2; zeOTO&nmrNLPwR?)z8Y`RIk_0>rRpmWXlTIYyl^QL2b+6V>ztG|^*&tDoO%(?E1cGS z#jeChe@j{eZ=cQcPHOxCGnp%QQh#s!F5^c|VwroJEz^Y?m6jo-x3ANVgSO?OONk03 z(L?0A+(Toc&(YGPDi1RjJH%zl+Rg%w-xk>La1o)16ntIcE39_ntDm_>%BSsdQ0)iC zsEjDyI(A|ka*^tZq9WZ#o8GFNys^25Ny6}%(U2;^h15mC1&0G4Dl=I3 zDmLPlUOGcY;81NHOK}+2O5bwY-=aLgBbkjsC4bWXmUX|omtnPUdvxP|E7rXnuqa4r zyGS>2{>ty*wtCW=rJcZoUJktF=P%5HapPFL>QL6ytjoNWa1V{8_2=^L2mG|1B!KY! z+d{Z zzR4yd>0wkXbZK>cCv{8w^WA|GVmN&w{b25B*Te{@21us;k?%dQM~90g->SG8?eR@c zc2?IOMx8wNoZ8R6ueDOwS6NJa_@o4!5t8@=186)Hm$X*H35BWk#zMUxcBbLgfyxk( z@h89R3uNt)|ENQhCBr% zP!8u*(SoAgRPy*uMNX6KDPdo<&^p1=7InVB3J=qI!*Z?^%PcgjEi^YZDw|D7C^`K~ zcDu7;7XfN^(~gcdmow_ZQ~3-p5OfI#=Z4-c!T14(k66X+z!0kgI?yy;m2asxDMsM&A@=WbxP7y!-u?bEXf=&U5y~zi~Zf{+4)GO z1NO_CU^1gXCiL9A+2OOPWwY?~_B59sNp(WeM@9Tsk4g{Xr)=$9(rLB1&wtrfFpfwj z)V{0)y>hRx#Fx@iW_h8)%F$W~`@HMl58w->OooFxW9ZxTtW zeGY}(45`Z@Zfcqfdqa-_63#)$A;k1}UpGV^9x6&b<3x%FyY_Ku%WtZgxC#d(%)5>8 zE=A*p;MHa0<~U$(vw|4;jYZ?q;@A8g4P^C}U0D@V^>=r$OZ#DdkEv6bWvMu?pVFKw zjksa>mCzWw=;+#h3bM|?sChsL$$k}RD2&ht@oUDEJ{lGN?9#km-?Zh zS7R&v-kHdXY($Z$$}m~}BK20H@?yoAp47q*7{N^^CqO}_M~VPykgyAZqEP?i64|#N z7Ym}Qt;lPhAtnk3I>+rsnRF7|*20J4QpxL_S4F!Asm)B28JeSl$F= z?QI|l?JAEhG2BH?kPld%PD#xMQ?n))b2cs^r)373sI%u=o>+eUuJ$k6?pw1^xtvp} zrY>jIwMvF94!5Q5!A)+(aOF?5XNs5FQw79_3QK1^WNi;@CSfaQZ0#djrs+>I&4EO4 z3;By{?Zu}QO`Iy%&{HHosdTEQJ<8kpjjQ)l`jY|{jjL}9+dEHh{&WL=y+~G426$VK z{&%&A|6Tt6{q$QJ2?z!H3gd4Ke~JyFS;HFq_owwy=2Bt(vgKOM9;bRPhbTBWu&V8$ zba=$Xst!auzVgFjdHEatkKt z5U*#EzQ$1qGSB7M4Yet@60KnH?F1w`7A1m1{pbqt*MI>Ay#(HBQ56H`nX}jz6=YfU zCKJ7rhIW&uYvV?cZdm0cMU`8|mE-)A)f!<+913V(0Ad9L0%H9C#w7h|5dL2zQEDn! zn#cpn$sRcCC0)--!6fUG6U>&zCJo6#$TTPSg&|R)>#l#4rUlkJEgIglF;Q|9LrpasPFLaKdY;D2e3@;*K<&CA<2e+KP+kEITNAw<* zz`IqkuD4iO$K45fA_A&ekNa$GcCU9%ssUf}QX#YDw_9Xqd$;4fWMY{RcOS7bxdl@H zMRFHX-bC#MULMpKGUH#uozqI5u5gIXBOu3E(z;CQhChoAKoQ^?$?#6tn|invZ)oRX z)VNkKj}j^iE0ss5Tc0jIl#)z;8(I;$iRh$8%D90rd-~bsbd_yeoS3l@)KB>xdUsjIU=#iQ|3`rqz{1u?u~R{_qH4mz{j}w3=YE-zooC<03V|(!W zjXf<=i-D0+^5ftLpD4v3P^LIwC4=f;PEN{a89tiHQ|*Y~ zE67=6M(ugdrTc8A!wHPA;^g*@S&5?}aha{a&DuVTMn(!`z`%ic{c!av+ZE8ej&Zq` z7oDStcpPqerE@T{KtQ5U!6BrA_Ar;Np+v=)UEls#(jHF<{e$52$PQMfM6DNUGhT2= zuhUNbDbU4;Y}eP%>%3w7T)Bfi840C|k4Tiij&`R5VaE}PZWjRVXcIi+D?N+`qh8Tm zzf)L!LaYrPc9XUcq;wyz27S}mOE;01ru}+*6JfH4{VHoI=IQt}Jz!MXukZWD5-f~) zcWYO0`}`*m36Sc`(*RIN&i}JQ{-@FTzsMv`<AMQ@EI#rSfd^bwhqpysMs#T#aDK2g%0(Vw7|6_IF6LUT zqM-p7-pF=7tdK5Wd&8EKcg-U)%!tmNV$=o&{Dl<`P$kY9)BAxL3;aXV60+Emu=tWN zOP#po{QkcAW#4ThrWM9lhf_>BJHbIAHYAG8%#Vs5VJ{xkr1B$?5z%By9A92{^uTJ~nYtm%8shqf0e9(>s zaMU6)>flqWjM;D9tLJGAFp5}6j*|Ode?f}73|UOt@gl_qgRDy+hOQ9BI?#U^220TY zJ|`TF<90TiVuPz5dtKiQ& z{{!V4)VKx5BR(l-jb*L{D|eM;E-I+p6dOEKO?lOW$z@HFmiA|b`{S_O1AG`@>=m57 z9tCr?t>N)6OS^JqkYNm^wqa%|^^BuIF;`0pOH_x}n5kx|Q#DKklB{Chkx&ep04Aee z2zgDTwuR{Rw@Ajr)fH4o4;@2;*Prfbky}iRl#(7-MSK_w?%`vO^HS1DUuZB~pKm}0 zZw~*vNLnjPxBFJ#g68?`c|9~8Ngh=*tm=YaaD2`=3jm0wE5r%yP0N3T#S#y`9Glt@VqVkD)=Z04O( zr4_f(3FtWBMAv_OoSYV2_w5;E>;nF+l0QXnYdss#%BgA5h;$q5pT9}N3uKZGeBmNA z(3Y!Lg{~pJWq{OeB2A$y)QIOQJt&kA2IZ#5=W4)0D1w3d5cqXxY(~V%-{7 zG%2k2oN6%QEDP-e#o%o~HP4udI4U1W)~2E#OxpO_M}Qii9Q*C+`iUvH=}IsE&N(U3 z(+{M>J!CaNZH5R|qoujyl)C+n$P6dx4reW;@}BpO_{Bcevqh0>)N6i@Co9$IL3jr5 zW#NRM1f$m~0^wDg2B&assXO!V>Q94p1TGv)6JW6301Vdj|A#s9-%r@JWCUzz`TdvUpCZH!6!k#)GWACm=nG%$ zctt1Gw6s}~nklud@i=g*zPFQIvOrLL9g&6#z%3A0m7UC(Dac@{`e^uVBnCl)PPgW& zgeBOmFtTwYOxhAA8TUd#oUk_JEdfpuTAfG98lt4o-cJ#h-$RrUwlaniYm80Rta^E#vqOEwMBh|I zSw5m;hXmP6kJfuC-D$p=vRQEPGN&pOvJjeE@Z&rOd2Ff|<=O9ve$rqok4~Rj2T4 zw`rlid(q5(oiK&uT64fTI-TN+=(risS05#MuxaYlCXF8#m->up(w|8^7d`^{DT!0b zS{=3(aBFd(3sxXV{!;8;?9($~T+Cyb`QhP^67r)8BFfgBc$le209z)L-i8w$O8i6B zwHYE9hmMWP(b9I;BU$i#_P}X7^m)GzF}2QTlD@vf4ejZEspCpVOWP_B z(AL9+e&v)mdQ={7c-QXM*@_LB+c9VMY8&51gdF1WvW<;|c<8Ac=D{J2nBFw{dRK)> z>9447z2ip`6B|F;4`f^@F|A3qQ-B(vl?3p6YF!V=@$mU01Bh&Z=SW`wgaf1OiC>M zXwPeKhji@iG(5!OR3DiRJKG&84dt981>#>KmoI(kP72Dt-K^>+QIS`rG(D3w*qBtC z|M4i=hM8zy?w95)GX=(!>W<=8Qv5(*Ut`O~kN6h{f6dQf=uw&|VbG9{$V6Aeu1SL~ zkUSUI`OMQ89$2lKY$O<-mz<_FvO!DY3e;n0s8@YPM}Yiy`)Q%1LvgOkv56Bg=_z2p zmNT1aM=2i&m(R5)d5@gPg&;1~GPVIE?c<8e+XJ^19=&NO7E`L`f?A7%)(7zs5O={1j9m)NzT;rHUz1^J9B>*PX1ZC1}iFJ zzwrYOJ`-5?1l|*xf(hCGsLb^&b)zY(U2t3mfDZ1z^WOvRoWuBBM{+>dy+MHNdLUwe zy!7{d^j7-ITpU7vcU9;u${PwW<+m-O>jIQ(^$VtcXyYK?zB>7^BuO%bf&9wx5`twd znKR<(=cdtto*er!KzTVJQy3OwfK{d$&7l!wE4F{%gMhB7#^+5P(W}TG-3ZUOzounCHtQ3xBs#oM;Q(ls3z|d+ zHvtx)H7JhUBDTybwhSjm3>)p@Q2vtF^yJ5978?Zs>d;7P*n<@+c%k!=f~OaU20OA6 zaPv8U7Q%!56_(Q{khw!=5dmf9x%c+{?d-iPC=YcBx%WzkaHf}w(SB>uOtTn^#&aW# zt@b>&QLCia?URt(cg(OZNuu)a>2px|=FCMLH|W?L43|H2JA1iAs)`@>=&4V+`Jz&t zY*F1cMteqy7KU8I$_L$9UdoVSbPI6cUR?%g#N8ooA z*eudX9a|)+D5tXyJ2Q`Ur!)&GwwR*s&(ev_Ch1csr`m|-4{xpgE;pyjdbo!mZOvY& z6=ORI4?PX%^Ai))3?4vf(NDJlC@tLQLf@xW0s!{VEP!laVL+45`{16qIHJ3_&10+> z(8nO)n>tdxq6pPrpc7=c6^4L@mpivS8I#BGSEzedSG1 zX7?owsHyoJJI~gvtZW~*{PO|VWoZ)&&!UA$KZX&oEnqZ~6 z#{s(unyRT4he3J!@$2(4M^JQ*>mUGsvTnFMf5805-1Sa9;K!i|X8@*Cl7Cw@`9Fx) zzaLBgR5ghl@BQtc=2GVCKPrYaMNjZGTW*@~w6cz%%w>FA_tj`>AQ$4Qdt4TliDL3w z=5g`bwJtZmlZK=V&jVw)5Ihr(D>Utv@LNafR5XE90OW!8Q|UPF(A9MgkH#+tSMP;X{}cN0K785~s$GTy6nq~r zd@}#X5&iGO=l{a&wN%i3PupvwqXU!&-?b_TXS<)>2rg}O;FiyZu{sd;EkYfL%)u_B zG1_iM{Lsq^OX7<+mP_xAX$|Iip1_5S-FQW6mI7!wAv*~^z9SO4V6>TqVHu$Q+_Ua< z6~;W4Yn5Yf*}mi2&s5U`Q5AQnxye92f3ap#m*9lcgWtNsA4|rcw#> z?Eqg6Z5yo6SDwd=I#X!K3nl+Y*F~GxWGVSsSa+Jy{8X{V5vKv_aT&qjbmYg%%A7S;tQEk=AyG>by>EWL zy0OefLAL(o4k9)w7ZK9`7iA;M*97e$N7OA@$ox6c4gn)iS7g+4|DK9s${*OjDAkSY zIN`mtDDViy3pY}YByVX0Yr==i<8&rYtY*`MHJckIXxJaN;`K9rm|+2y3r z5c<4G45-i>*sEcAt&-)5e8d{AKYdArRGO%FofJwMI$!@*O8wV@< zaqW!X&4o!R9&}CSI1k3Q$?gnhZ02W_FR(LdG8mRKr$9=pcb8s(lTy*sq?l0f=L_tr z`mZV`hJK#-H3#iR8EnY+WM#juY&p`cGlI=gj~~C@ldkE{JhJ^p^4ddBqgulhg{9Pz zJzh?}Lc9;o3vbjdp3yoB?T&P!Gz3$+G3mxx&JKvzF*IAQ^EC9A}9>k=XK>34ZdAt`RC8|=bY3fgWvg3;tV~w$xC#MgWWLrk7TX*QD#S; zODG9fVgeooClkdaBc9r+5@H|LG@kf_P$Dx0pyRfl`GT!$EItsY3YgPP(^ak!1vRE@ zna%Sz2+|PN#7^sf6%$aGn%)>p|26K!@Nidh?PT$)N#V|>^IhR{wX(FNI#(t_+-??FmpbYUYVsSA_M^Z(d!LV4pLbD%$RtPsJblp?fUG7R8>!qdJ{jnfGNreJG#XiS!y_=heri3 zq$N#es2FqA&uRU)GBMY1-K{6%#lRa?@{W<5hB|!7m5dd{B)B5|QS3HD0)NGC9m}I}Gk-3qDqpn5v;f>Bab?(_mqL*=ksp5PEi-6aP<4xs*V3h*B z-C(-PRoaKK2bq~h-UDl}tz|TAkyEBrqpu+}GMnZGH~fY=q^h;gwoFus2TyV8@g6Km zG#KL8+U-ne{VBO|>Wb-v{1pkfr`oF5* ze;Q=}$Qu1G^{WXNdRjetZ(ZYQ$y*5w34gAv<71z6_`m`tnR2fSD8~?z%p5Y8(+(zc zqw+ZC=OL_tfzFX1 z)B4rGUcj(G*PsY7z(9^0@PjwXSgM-IX|;@6GXk*SgM}EpEXxQ+5pitglcS{Og>`ay zbzD6`6fl^YGO%mHL!)M(NagV&g_2Un7{X!Drx9bvm0tBN-5!NE2R?f)+S#h@Erv5t%-;v^TG+&j9ycn zyLunpTxq{Lf$dhh`8BvF@ECip!6V0+(w_yGw0Jbf;vE^-i273PU0pH>Ei2?0B401# zQaV5WP8)S5>--9G8w^MrZCM_uXklmqe2qWNKMYEi}vwnxI23)F=$ z>sh$da(TeMa{Bl!Q*DjytBM^eTrgm%@V- z;}s(Biv)7Bg7~7q;s$m?^m4_r_Lk#Fa!J}sn0N~Bj-@o^aXGDa8n|~!dX6z(wriT0 zrBMs4?eTc%ne9Bq`iKpBkk`^=xkFQJn2eG2t#LxAJqE%c&SNHA$0!nkvKPRCVN~oaZ6B zm{Bn!cdK=csrs(hr6nARnovM=X|l{^jZ6DXGkhXHJaztf(s>z;*l-bp)evbHwR+6B zsdNOW3u2k;IHuK(b5#4s(pH0l4n4|>r2_@st=AfZGi>xGxDm%`Gb}4#n54dq5Jlyy z%{@53Jq@-By&p{3abpj7RHf>u zJ$CLJtHRtp43>I_{4iDg{H|ri^rPZgrhd)Yef?$30N>Y@PSaMZ5X1P1+@bK;sr;lP zYcjT4@-9%qENiI_%>8vEiQN%rjpC)(cJ~{Q`3W+G({}gW_sH6)@cG%01=84z64Xx5 z>}cG!Or%dEI;jX-PBAS~1(=hY60twj)t;=mF-CEdo*Sd$hp#M-c49iPN8X1zoK~y_ z=g}LbU0+1WoF+8YNF)3l(&}W>wiq@4JeThEhhzVX4W>}(p(_Jyuohs0|LxssAd0h60rVgvF$ohca)&d4j%^PdTi zh1{I@u`{gLBskt%AwbPkkvTz<(d=b&os`%@=)xFp$9=!_&Yy)dqUP`g%b8)0WM<`4 z7DF0LUJaRuzDkx2Eo^mAqrtgZHQ5nrfPMSQ?@hO0yZ{z17^*B2a!{s*9mMnUt97$Z zx|4$MM7oL0rEG5PY;J#O?|S)qP~ZX`mIBQ2zhC0~^Dl(IwZ=}jcNn&}s;E1$s?WLz z4+(EMMITLy88oK`&RTsZ()YE89rHCw5I#M8b5HI^V2YCx{*hjo-=M}ze6gA!M{j~H z0hL_7|BYU3u5<%@LFYmxZ+BWuInb8RcFTU|G6p0dJjU2lS?E2+0K9<_7>!JGcay!L1HGI5WmU1_@)FQ=D$ya{=iYjV z950$x!p7wjY{X{2INx1;CaMgxCCk-Og2VFUv|GRu&6bQ9jf%73f4jWrwYr+k!1-AeHAXO~rA+z#V9xoBOqKL;9FmA{5{9IU} zwo4G=D1QJ!z8}L6MV6bJDRM!QD;I$>etSeKbhSqQtS}TDv?Oi2N7(1#e_rp@_p-*B z%Zq8|O^|`|UDN{wRxOt&W7|yy`YNEp$lPWkdQjC;$ij?5gho#yDBj^*QoQzOOhMOb z@(3zy2`SCq&M7r!JyBnp4}sC9Co`t4*lEKTP|mYP*;R?VA}jE^cCqK~>6yiuFB>9b zTg%aP#0~l*ihhX1#KPb9pc$VGGAk?c*Rn5lntXzzpprpIk3*31tBXguKn53cBHAU$O4k}?*}>mC&~KH zeC*vnI`g}-JqAA3;=<#!=IaqlF(75sKwIixhJ<}MaPQxe;a zCSTDNf_zTj^hN@)hV7u6eDtO)Ii0LDJTefHbgK?Fr7Nbr30zQ#wMaOq$1p2zki9R* zvI9!bf8l|tBKEbM5%=VI z=q%k8gME+Pmhb$A19ZQObCtMb{YM%G~WU! z%{N^(-=CvBYRoHgf@{#~%ZS!2|2|wjz|zU6u^MgFc^ z2L|W)vQ;KtnC_6oD+DDu=H4(@3_ARl1D&y6Xrh=Kb&PH6wFK(~+SqaPgme_m_hDM0 z`wxb}mV##e?{&ssm7N;TsEI%a>X$Bv5{2LQ<=`s1|9qCyt{E0UJIS4dlOKQYk0dK9 z#uu?IA)13no_RK>9lYP6@UtKu6}cg8dsHa&0eZ{gEOc&xeq79pYxb1@5BYl3JsC!| zs0Yu$Z8%VyuRS)unN1Q`wH&-Ss~E1?7mq}Jw3!rZ{PbSNzl}MC5<^)^b987$gTY)R zloMQFwCBl`VLN)+3h}k$s!djF!iB;bw5dnT&%mORx)Q|hi1hv@5;HN&fyEXH;BkId zcQs^U8P}p@&c^iCB6z;Yfe9^v=8y8vju$|4{&(a4umEo6B0`TmRl5B4=YCK|ie3@IQCX;hZ8RxClA?+C=p2WaTpoPFM z!`45)l_up_Ek+^BY;#ZqI({Bp;BN508Pm!b!|ZStcRO7%q3$X}FY5p+!bIwylAJX# z0!Y`trE0gpC9YKg&H1yyitu@aG_WG9lq5{yq%S0*x$_mvbGb(J>@TWy+wdpVIs;Ve zimdLFy3jpkJ!coK=BqLV>@@C(`CIMOpCxnG{z6IFl|6y1d@FD_Zku3ndshEatrrhE z2SSyW1$aH3>*1VKp3`eKtclegw>m(> zm-7vXr_6(@>V2peI0CSJNtN9($Ve9p$r}ON8G^YSjKFhDki~E;G4TZYD-HmF2!EtL zvH_<0UlMM$!j5=E*s}aM%D#5{;CVNCo93o|TxH|~@oV-313?@Fq~JRO#NpXObg?6| z8Iue-f3jVkVjUmz!j2JbT&?5;HNmW^LAL$LPTy>e%Ai4(=N(Z;zWVo6e=+eTX7r?* z^6g4u<2lgGJ|bKQB^G6+{CCc`%$}xtDD`VQfPyp4${D!d;wl-en7`>ZB%@GCJ4}2t zl_d)~H0KMdBnW$1{0`Nr(8v$VG#`)52BR<)`&`1e`sx%1=g?1}d-CLGwo7j}f*h@m zJK>e!ItapmzSdK;KM${qn*kG!_ck>~8{)nrKYsf9PSD%;IH4aZQ18F%Yqe<|uh87= zhU8svowpP0h3H)>M}M_Bh9Ylz*NY6_>C@OR6T7BU5o0qXIJNao-^ZV~%^&#(!ly;* z`0?^{$S!OGd6fjP+=i?!uu+w8l6x)^dfG z;zhJi8De;t@XR01c%AMIOh9s^ZCOQ$7$?J^21NL*3LNMsYK>XVMgx&&t#2ot$c7kO z;A>-Y7`ZOFMDV{!j(Qu1IbpyjWiB96wV5aN6F}K9$ol4Z+L*ec@IHD?k5OF)3vpf^ zkPk4v_NZnm^yPVLuSebrHn`M1F2T2kx^EHbcOGiF`B87%Bz8%CvI62N=T$@8hOmX^ zvVrPIswcs8KFq_RCGIoN(?O6&9K0M78o5K?c={Ix`r0Ic7DBsq{hLo@dIlf+WYJnC z_t_C{ardn#YiM(%C}UFgn2SO^h1TV1P8Xs*Id$d-_7z^;@{bo}FK2*qv+&esm5~K% zY4~`O=!mwEv0j%HPR<;phjSOILhXCm;nfkT^DQEl&8tpU7+hK8bAQ#JGG+|8-;EF_ zW|)&mEpzcZs-etItHnZQ;99iF=1I5_e=iOEk~X-%XXfgCF( zPciZx2>~6luXGvtxtgP+AhN)^7^c^i^D6&%S3lb&{>pe!ZR=iafeY6hnlc5=BA&TL z4L&_dxxGW0AD(>#*T8PEeA$MlLXgx<$Yb8;C}8Lt5>fdc&%j#)HT!iPQMg{asQR%8 zRnR=qsNC%DJ8K zUJ2yv9pw6X1Gl}!kyz!%;<6*1uM?NF|I+%GAJrL<`+@F&%&q_b%iMovRRQFh^lRQp z_yK8c3J4E;2U`6kYe@P`!8NKKU;*M<`a?G}u~1II8nCKpjLxXMKXmbtD7w4Int9*l z=+QSz3I?l^>4rv2>Mi|hV4YpTu9~gxA39rg8$ElpJ!QXLfiT(($^_5U1_j~n@+AcM zO8)4Zb;ucRpcInKtnnTN@ucZf@p3Mf6+(4FFc#^4z#Fq!4Kjg{zGdf|YGJhE1RiM9 zA@DV|M#+Okqfd-Cig*$}Xs{&lQp~E1y^pK)Q08f+;pQEsF+= z^NBE62yN87iXEuLMF`8NwBcNp=;;Sbx)dk#(vc_%i%c_nbTf~avNEUNcQ>p4Sixi) zhk%60OW~e8x}1E#&!+hbwp>XI@#H84WA8L#Yn+FGSk1^ys6ZXQWpv`fiprr8XM^km zJ4A-gu8f;4u#WOQBuw4#BoyZzf!Vk%d0qabN`{%Y9B8fH(xabC9tmNqO2r*FT`=#T{5Qj_Y zk{fsX3A_{4A9y>?hW-Bam-g{S>AMFWNdql!%dQc+Kw)Z|yLw0J)o`kfwcwT33$<4k zrF$cu@vmWqT6HFF%nkW3q&h!SU1REi__e7*(|TX*zPnPOv&OtPBi3ay!)Q^!cEj0Y zK@X)Q*sA<$Vc4V#nQ)b;TwRa>6_?c2&VeQ3_09dhuRR!&3@QYr1=(0dZ~<)bTMlm2 zf)is4RBRpN7&4$*m{+lZZZuaBX$vtE0citc7mN0@iAasLfo|10%g{;nHGQ>TxsgK; z*ltz6eF;OrHD(;uoy*se^q0g$*va!mRtli#-imU|D~ddKx|QSH%*(|+pS%X&GM$~* zUjUb+@nu0Obh{}OB(y90w&MKR+QU(>Hcd{CKVD>sX8L4yc=w>iWyFK?3Ad!lte^ti zA>t58`sgv+fW_TVNsSk`JOg2YwEMbb^cK(WNL`|Rq6{Ay4~6ce7I>~N6N4w!Ov%Md zdGx;9LC#>MwY&bXc5s6+X7F}S^cz7zd!4@UTsrUQp8vP)<3el=>lJHEwNE|Q%S4#j zI3YJ$utizUG_zNC=MX}*Eddt{3*SBphn+kykhA5F;G`Si@(iIDzH5lx;kbrgN}NJc z3uOV@7=L%1c4688a>+UipA7@hDkK%|QHS7OaIA%9iv^Pq3JcZlkTVuIycwwLA4J_l zyhS~D9(DJF2~CTFxsC_TG))W6vPBwmFau8r-<-BL5YAQ^;yx)Bv9+S7e0FWc3N@lB z_cG5D@=mXD-!Tc-Y-J){EOGO&j?|R>6S)>@Tt^Erg?)=liZK({~AR$_$P>COTiM=eZn=gKTrX?6&RpSHXhe zVO5(e6HBRzJaL-Jh!mg8w~!OOi%W9a@RsTypDRJD54*0!Bg=qgD2Y|1?tMw{V{_kM z_Vxx;q@MzV6h{nlkMU|6(#rm;B_6IIWK0MgW-hYtm+T}_l&KC4aZs;i*!FUSDlUKg z%kGDt{J=_O@cTc11Gp2kK1u>ok4B&>L$g0nf^eM=h*ePe;`0PAor7TFPg2X^}=# z1rfK^nPrLBdIi6cGNmT0B|Z>IhGsOWUJ3WN!9~3nAl4Py%80UH8%%tu@tV`gV%mH zmYZT$zlk`cIATs#%5}%T^X)@$>lV@qqJdPHq4<)5(IMBY)_Y71mDM*zDWO00=tN8) zV$O4kH2R`5MPNQdN7%!XrIl7I3x9tEwH(VQKjyUpBGePp{4-bqqZHWcXxSLEIZ#FC zqG#rz;lgfe0+bjEeRmiYp|V3XGp$ug$yVUdI1pITosn!bL9`^gnfMU-J-2Ov$M=*K zIf!2+FURo%^&mt;m1bU}Ne7DJM~y4uM1QoA?#mj3E2#1=knwNaaK@45SZ4x!c1oZM zD?-I7e*7Y9DBC>A9e92!E`Ub?u(tx%F z7DIU_caVErpl#u9bnn3+Zb&CHZu?R4-o+s%UnO{k$BCl^#WH!Zi(3EL z_lG-gch2{!)P#~R{TahwBpbh(BAzPLc6}ZzMVa+UZ73@MJMo+CRZOE#<{9 z0pa^`;tUOv41+1;^~Z^a^8GUetr1l{ANDxuWS zdo?1J@7A~R_9?ng%3>;XwjCG_{$RIes)1=vT!s5t?$fNT@=MuIp1YU#=Bl^84>p!T zuF)FVKTo4+v?m>soIq;i1dmLZl3g`9$F2re(jMNRw~yqMWkVy2L)7l@=bSbxCbesp zw`^usR5>Kz+5=0ZhEg!`y`k)=?8z$gXoU5>FH59DFa_2GZFL!@r^-+b6sm8jnnEqS zQJD8EZ`_M2M}&YtyTgRZ7z`S@t-bX51qGB#Pu2A-DYNg6DG!2+VYjz%RevWJS&l_K z+uV?Gg8mm4)!MyJl~0^rT&vg0bsz9fO0%m4p%;J&C@&d)P9c5?<f3y*v z#RscssZQZ77fiNXnUz&|R!*dc*H^$A$9o+wn_Trj+pV_(Gz+EU zZfbe1{i;2oPG_;LCwC>6-@ieUSPe<+-n4-~&bR{wF?m{E&{%Ae*Mwp?ci@Htts8i<(!;IxHSXKxwYxUE)wWc4 z0=v0Va2-*=u3Eej2l(>__kWllzj2Y~8PtE*q*y(v9!vm6>nV*iZ@dRQY4X zL<5e0?FC5dzNQ6&u3d7-sa+5s@s#JeT3cM4ot`U!HPT}q(lh+<6{je$;;QH9X#JNp z(%4>K#Oz0mz&6Pbgvors8fh#qM>w+cD|(AmK(+==J=xnpKJ%d?5=*pSF7Wuf<4e}6 z^9Y34NH66cMIqIVrH&T)(^6SXpaI87_dfhBwI3gV3c~HWuAtrPe9))raE)ZoCF>!J zNBUmWAsOnHum*bJrq(6r*_R4J&0x-oxgS_9-lRjMLbSs;K_L&fOC-QE@%j_olHuzg@nld}1-Cwe`a4q~>wt`<|%jB1Ak??Coo)yBs$d;c5xt%~5^j@e= zm=Q8AB1XDjjveU9FWEx0mtWG=?BnI=g*#_v2va;Ah8gu63}SxOXcV;y)DWW2T|wR! z0*j>LM?+_pwMLsKluyk&863}SUmtje^+Y4&DMw30y?Py0wwoj}JzP&D&jfDT_Uyc_ zn|K>2rcmOYpCODJM?FPSGw&ba{$;gZz^clRvyRNa30D8_o%_FnRgKW4p z^lhg5Nq$U@h-+G5_EGSwKwYfUtxP3J!pBo1E~+d19g`4)C7R z<&lZi|IBm?L%#l;?7nC`$lc}}m0Iy52_>Qci#dT8uaiQn3G0M2ognv0RmnFj{vTK8*OfL*b^)b zIkvsz+;d+$d)VPzb2>G#Cr*b_2f0TD87JZ*dj*o(#f!nTR!3W`K4V^Hz>f%+i2OmR z;`4A2x1vHDA4}Mpx_gen@!}#24mUL-m|g#fSBtitZfG>}&EZM=q10*J(U~(KpRpqB z!S+u|iv{_Y78H2%}n(n;{6?z#!;fp(dRxJJ2I3=xS{U9M6%zFCQ{QtnTI#*P|idv`5jw3WAY z;g_gKJGcS4;VJlcU5)yz++j9m3sYh(2Z(*|8jM-tTBI<&CHfoXd>6~C(xu!Lt#*pGBUA87fq3amOS@SIPGi@;qN( z`9?xYY>>#VV)^kv-_r_c*Aa&r!s$7gWy^e8?rXInH^xD045MN--;1`KlE1lv$zq6E zQ!$#_zfF>nIWBSj99=0|Md|G*6f2c^jkAcD{RdN8baew^9 zm@}u(k1C=*t*}2YXm8(*edIOv6Lm?GQBDQ8eZ&zm{E%ib4IW2Lsd*wi^DuZ>OjdwF zzZ-(UwFSxAzH$Tlv7HA>;_b+( zab<>_qi?u-m*V;?7KM<1q771LC!Cn_0_U2wcb8jm!NyMDJNng8ZJ}68w+8aok}2$5 zLmck$w6dU<1Vau7sI&AUT5PB$uwS$I=2>?pEJ1f=N^w7+*M{X2m%D}@A%$ErRXZGI zcVo$^R|P<>nPG7iBOjjk2h4RS1aaRN-wh_DFb7$WbUA3*<{X@fuM~e2J@o>>Dk}h1 zhbbN00V zrS&fs^-B6i(c^D|)xYT6e+*V%lKj&jay)|0l755LUpi;;zk=26ZXROA0Dn1quMfig zpEgs!pj63rk&z_z)pwg%&z=B5)*kgCJlYO7pwH)WsA+H62^%-)J#atr1VT%15Q2eM z8o>QXs^LVU7>(JiUXrXUnXy;VUygYdPlpzTS$aH7ceb=7=ZZRSH-9QY99T~KF84u! zz*(l7M0|+{H>I9>w~E+!;`Ph@2$X}fghK9Z>opRu5)|~3)j7yJuH=#;r1q`+;#OCR zP+e}E1c&$P{e<>x%YzrB<0ZjCh;pde(b5izg}K?JFJSd?DeE%;R_|5!S4@6`RqPkA zTJ81%R)1&#VAX>~l(Yl@t5=ZU{tK*z@I}DfpTB_BFaWH+e2Snn$Gf$}yFJBESlk1^ zs>`$UaeElCHOe2rD)ze1BI2vf zjfJ+4`sGl{F?g^Wcw?Ir=MGV-_FB_yqsrwfwMQ}PmY&-%-PJ2U*Z{ElKE`qDbts?Z zfF+J2Hsh-Xj6LCN(}r>vmh+_TxQ!2RS5Iy=BJr;Dha@s#Oek^XVPc-p_lxFsMfdE1 zLUt_C)j}M*9U|=M3y#@kT!7RSxVXv~UI0?({!ghxFJojQHc*37-YnGCO8x^_os|T@ zs&JNe{QcE90zV#=f5HbBy|?#d`yF5&%+YkoGZ8E0VcfxX*p~r2nYya$EY-`EX%fw0 zLklrue#Mfy+PG3Vy!t?fRlE0fte;S@7E~=!w)v~Fy@~p7$4!Z8V1tW^dr-06<*=?4 zU0Uz&m->zejaT}%jhv-8%v4btYg619tma{{8ma?cz$z>NR*l9#hamt`2Y}T89aUH? zM$18gC(`1pnR^i;ry(@ofHkealP?KTjy*%OyKt0h0(L9#I<}a#=^s`Y14)pQN`%Vu zJ%Ae$b#_@O7IHP$qHVUN%7J8hdkk%xQBH@R#M%6Q3Ft}pyQNwcL(k-OHnNvUuSdNAeKG(-}ijp;4K0*Cr?`zu8Cf#6{IwaG;oBGY;4o`7%^ zm@tvr%xq~EsA^_Lm1!j4%zl{+X6E`~N!gpjk%i|~=yeAfH=kFLNaK}MBIRd>UTzYD zE%mHuGH1_kd-nPQx9QHer9m?fLx}?ZwAU~bkJbBp_^vL3x|VFb#zEVKCSXh(1Gy}t zvR~`QsT@cSqSBa^Xkc3Zc!d0y*1h;z+8$8Vze`sCq;-FftXiV}AvvHfFqWHZf_~mX z=?x#u=6vLF*48tPI+K~?YF>dC26q&PBDSYwryz@W@u?;7(S0yvtDK7Go%!d|X1X>c zeM+FYHoBpQjza;IbLqFg_4qnb1swn-GTC_t%YEI6ja!)_0y)vS{Ye1gpyyq-F)32- z)yqB>KC5rVkpPv2iNJu=;!dnvp?C5enorMbC`V z%RdKa7!XjfNT3!C>>(Zm#6s~Obu@nntOnJ0d;4l|3V({W*>X_s3^V^3MNbD%#1CSd zBB8!C^d=Q~S<9%9KQV~1stx`aSk3xF`fF0#ZZFr2u?2V3W7KW+vUSX3%?`dmKyr=Q z4AfZ!pcHy9l!E@T)A}-Sw6s~IyIzf!GW#EaRU5jV_Uz+ENhiUDdRLgdvm%ott_dxo zloWuhnqUwAM5dECcpOhID2tX+SvRar{+N=&x3W8r`wL|9>$VOFJP%#T!n!+42 zwIIE@AhPXK)#?HUZrDwAz9C(H_$56bZdSZjvWp!N^BOEbDW*w$2~0HOKZqQVC~cj&P)4M>Fi3NPFp{26`eK5dn#NE(T%@) zkDq=yIEf+Lwrv*Wb2<67l<9@6>eB0Jpp-2tRE569R&VxZks1z%u}Ij@4!WxoJR6c6 z@Hal$MuAn;X`z&N=!@ziz%-*-{*u$~U>1m~4WtKHsV+YYEfv}OqI?(cWZPDd|4Qw$ zHQA_faRhmt(Dm{Tx5%J(*n*_7Mt3W{%Xx_L2(dY!`9OwLU1yx~ZeEFtZhs<^7%puAul>+$vH_C3u=?kXrk^PnUA1)pTZo>T9`~U zCsySW_RlHa_J;L0w-k7sk-HY2v8QxrY+I(-3Uob2Y!@DtLaZjfD$-;HR1ag5Ld4G>tp zc)z6u1Xi~vEaBty<-dL8^L=_?SfqZdUhOX8@FP4upMP0A3cFl|%}_{!3Hj(v=Q;{b z%B=}-GJ}kV&zf3<-(pzZ2V)&pi8INy6;ZbDQG_qu=srVrX<%yI-E98(9WQP*N88Nv z+IM8uzShCuL&KxQUN;a}?fe~BbwPE}s9HgF-9R!uJBu-mUQ5OZZ1%6~tj~ z0sqT?53H^r%%%U`!0K1fQ)@msCRS^FFhs@ zSbYFCqs!R7cVj@sjdYTk3aZw(O-p zaCSJ2wj@l^7@j8Afxwc3WEMz%fC8oxv@tAxevMObGE)sXsU|GvRuf{zm_dgmJf$_izf!+Y(d>Gq?QcNtA6t2Pyp(Cl5POW)y~!gbJ$p8pQa!UDZe~G@V*!2Lh{_INicrBtT#_NqYR;8NtjHBIl4eQwa;Hm`pIAPpxMS+;T zm)L;83sMu5dQZ0OL}B^$qw$K6l(V=%CJCY~!h(mazbZ8MX8f~W1#HQASmKNjrV629afYzjk5%X^a zjcYj&$E~Q{_=6k=#5RK%H8!0$OU?1VDih?*VTglnnw%MRwx zmE!bhc2&P{7<~#?s)9qGRCo$HmG-x;33Zu>AL7^*m19g7KAWTHmmE%)T|n0yRhl5} z4<9T1_>qVpf-OA#&}HSrKUM3^e^;%SnEl23n6zK2b&5qXkQ>?N1MzTcP^whz=jPemuLNSO?Pn`iUJc``a`*r-`!I2ehH8;6Sm5d{a5(X*VAOx$=%}2)wJx~;5e~8)t3aldMD*Rop`l4F@-gf?# ztLpu!(aM#SAPi`j^=&ipFWWia3C8z!3(}D zB8zA#epK^=%bY^*x&?1uWRbVWz(s;xo&B&{7u-6L8|vgC@B2QDDhq3z7~c+cclawT z(WP#?{wGZDJzWy;N9`J!6v?Jb&cttb;;N$O&f@2Pc{~eIrWEye^QwQ^ru`dS_1810 zf8|vd86>6ZvHuNMb(t67H<(XAx`ouYrxO0nRsSomI@xfV`o&?8hPA_P^!BM;yZzE* zFJ0JeGb!_RrZ)IXkn7d2AeZ-{TfLA}NqiZjOd)@>oxfs}7~|@O5iL3sz#9na%S+Q4 zYSHGH)7s=q-^{?^KRE38>``gvUg1tnn2^W)=Bj8B_874Xs!~zG>np53iX>&{JrjUO zQdQ-_6q}r9#^NRU{1~$W^m)gMOR9?$PA_D|gMF@TL$ywT#$_Mcw(q|)o&Lj~w+j^uR(YO|nrTLrw3~t!ZKAk6pPlV z7>dnotYt957&K-O@e0y3^Y%LJqtI!$apVf~g{)vZJ?R74zD0uJ9=73$;mY0jR+Q7! z2Rs88!zJ%}Tl)Z`^u2v<{{i;5WtZ?>-mcCAh*aiPeKy}(T}WiTb37dmn-zI~dQH>5 z1XeZ9ul$aKK4cKyVrL?Nt-PeT?r+{*$&WjMyPE0iGU;Kos9<|wZL#czN`Stkxbz!! zu@mf*;u#9G-^3j}wsWKidx?5Ee$w`T9UCeHo%RA7Bmvkk4!{QXBmg#u4iAA1ep12W zPFOF0{X|6H0pHmAF+%li{iZhp9H~dgkS8ppqo6!?==TJi)+MxB@T|H@@3k3ZPr*5a6n0vZ^4+qua;@HlE$5m5W zF9}Xv1A3%CUTxlSMK(XKd{yRo{pCAZgqh>zW~)K)mGPw7#=V+F5-f|~3|tM%QT0kG z*qCH7uPOlnB#wl}L~T2fQ|uUJ)PVROu__5>HdV+C&aV*H;$!aw5aO!wv4vjvW~m-> z;sy?Us(+EW|IDfWvmhmFqP^$#_tPo^;u&*VpdiI$V3r;zNU7Qk1PW4w zr8-GSuhoXvl^!Dz9wKEi(S(2J@+a64$vq&uNnn=%|dQx?6r*91vgX5 zr)JwWg&?#xI}^UG9}Aku#f01#U%Au!a<*QSE}+mZwM>=LiaGac`FI>qx|V}6u!PZc z$pt9{`hZ5E7L#$k!8gnNKG-bA+y+up17ijmuO3V@pLfb=giia6BiooSK1jCn5JHme zTSXb}9vb2(uPp4RqFAInfm(bYu7|PM*{2%g8kul|jIZrK?zmUp8ETsKAuGejduUvn2&P-D z`&-)Lk1enU9y3j7Oh|A`?jg9vrr7@4SnfN?!r|@PnOU|+z1^CI8>M-X0oB~`G(k?n zLDC6zc#DwX^ppj$?9v`CnQXY@!OQ}rWrr*;5w41pg-tLMtj{-NUw;Ahp#wbiG9`~!c{o^qOVyEzz*lAtrxmFHyqj*R&0&#j-Tx4L|-(`xoLo(>T=`0%FSk2W=* zzz!xFTe>bonmxHR(Us;#<}HTcOOSY&%YW+l`{7t0rU}K|&o0aH&3VnqoGTpPz$vch$GrBzM8Dz~C)x?6RvL!U!`ohHk=2if!_T{h?;d2oyl*^Q{wwF#<#6uOeAq>0(R!>*u!%S7nI2wV#s$(rysNraZ z=ckvzYP~ydGYY$xjbN?EAfD60T8k@D4tn{1Nh&Ox`(FdATVkdLMSnA}`X{aX_x|>; zfz|N8?q$GO&cfq)}v(9oqlMt436D1>#?B{m*$-ri0D9znfS6J^lTEQB^NdY!w`@ z-~Fr-KtC&q#Eb50{%Qe0e<2i;cM+l9=zIFGvBW>W*ok%u~Uu8ts zn~NT(GL0Gt1y9p=VUQF}l>zrO<(vMmZ3#dPz>V{*%i8VlImcVP3aM|)4Tqr4D&QdO z2B4-u`0J`u^im`}wO*os9w$MG{^^_|yR)=yo|e9%Xo)7qg1%4L>V2pdbN!888gp=+ z%YhW|su2#)m%VE|Lp=A#4pKCjmN1CDG4a-iBi-5=icoZTSvMYmchBH3K+BS3C+v)tm0vWy-fdrYH3OplP{u$Pl&`KS=Ii`h&p!Af?+0~ZYB+C{I;BsCkePf z8yypY*E+BM+(%9UI8fJU-%c=`st@L+hj#>&T6>%jL_JIi(r%GikJzJ{KKb*0DDyDQKm z1E}h+F-L%^cBFm;`T8yb*q$}>s!~yEheeYQ85=W9pJBylj&r_-DM+a6qSlbeg*x-X zNITmzM&XgOJ9J`ev(C0@%UWwR)^b)VW+q4V8yVUYSWZ9$7xK4smc4Qw& zXFYVk#+_rd8sGyDP+$L%vG*9v zHk#{_ghkx9Z2zBmf~Vy60}@g9=TI2c0tu|@4vT5R1ZpA#lV7si5wCrVX@Bw_ngw|F z$Z8x&`r=#+ZGdf0+KR?LLAfZ#`u2Hl<$XEly!J9xtFBHFyD{%+En!$YmwNaS?k#;W zRfUFeGsGu%N~AMSb9-m->}Ff3(wy$l2kypU)`9C#ZoGU~%1Ax0;;&%Rc`lPqq4L5f zs5KT^BicH27DE#og7aJBo@Pu3-!H5Yl5V$_WW(?fesCW$36tu>&o7^)5s~B#ma&zX z-2|!tZqXzug%kokAjg3wL2d!Kf{f|W32xIWV9^n%N}g8c3w$H=YtgYc**>UMzPPC` zhBYynl52qob2b&TlRl%aAV)-nsl2JsjAt`Fs9D)hp)m6Fa18dA!f(l77$#hEmN_sa z84=q<8<-4`Gt%5jy=_zh3q<1P$Z>H%4dmKwYzBr_e#(<%h~Tt!Ds+GAo$x?@+vC1EI589B%D}l~To*A{pmspSWge?ND2LM)8KRR|9 z_WWLbnmKowrqITEq7%cAQFTH-$T@P}9H?R6zv;Hr$`dhQaMq8&soDwLg z79|{i7qj*QozleVHNfiSF7HdH^#7F{>U0DHSUSt z`b-PJs=p>^e>bzm$f%uCu$1rD7Q2Dp7D~ zo1Zd(OOQp2WF3jBMq3(_!|eQGL|Tzt>4=1tXaI!S4~*fMzV@c+RHLR)V!i^P&M&!$ z_+2ZNTv?~{1_<|fhHXnSj%U%y-l{1^i=Y4#wA#tOQFs`b32QKeGD~%H9}6Hs88-rn$k}$i z=T&ETbvFF``ZM_>3f|!r+fjiFc(QrJ)}rXJfd{(0eBvst1hT4^-%o$)7J1;E@esVk zRd3h9D1f-CydpWC9bNIJE)*qiCm%1ee5K)h-~h%I=>*c0ezWIvAV1jEtt-{ zFZj8^Kc+yFID<4<7y3$0@d|-ce|5 zH+xN)ga|}T16gS797MO$1IWZUN9V(Psh8Q^)`Ury#1H6}lh|A}Cpis+ia|!6edcJV59b;%{O!mzL zUvifo+CV9fdcQ=g4mObK;q;!Jc}QTFcF;vsIqKY5pay znmbo>CA<65UQ%}5a5h!=-NJj7;t(;bXG(*|^_zAKxq`|d^BmVST>Wlv;9-2I*=Xs0 z;@AS?c@8DVocS^{zMV|J7Ud?nqNvLC`@R;`E^1VmY@!Uik zw-w54fgt>}*|yeT0X!Q`tr@$%c3YB+z*jXJS%H!L-CSf-OH_{K2?tuK1Z|y@ZafeR zUT^vpe$|)krztg;uJb#FxNfg0?57dtj}$pge>vS3li!RNU;fb6$4#<`+@zlZma}E; zOsYQ*Hhd{w!+{3+MxxC0AkFHn(={{eIf7uxu@=&p(yeBhLo(6 z?-L#;-_BnqXdQU5MieUYty?>qm>RdYmb{%a{f1$ZYF*+;Y4Qu1Ca*OztKdTr$? z$->n9>s!a-HemxTbs(?GKb?>g@YlTRhk`M`GZ_0ii(F%R4&wc`GVj(FvJ2rDhE)f# z>va2SzhaRX_hF^~N8DQl)wym! zm#nSpoU`TPudj+pJ-3sKrbmw+-3bifjIhK0cPW8JAZh--D8D?Vc&wOqMo)E#_9*p8 zdbY@WVE$QfNV)zx|K-2*tNv3h?|-SQ0zR(Rz?-DkbZv_vI!3^+YUNvFc!*&Qo1}UM z9LSnx=dB|}f1x(ErR2G-@c%w&OG|u$(7&%5GWzOQB?dNQW|o}5X3Pk|=T%sZ)Ux*2 zOF4aTZ~waYFv>j=wynSi{;3@dY^B1JB0{~9obOAxq}lt85t10Bb6b8ik!`-lpx+X zt-#OBYy>8b14&`x=Pln()yfV2c5$O4!?C&ERQqh*eHt#o3(B2-zE6NbO`%;^@1y9d zH6~o|M^_kOPuMRjbY7&NT?u}`Js6DJ_<(Y$DcGR8)d#h{?U8>A1ObrXq4a&27X|C9 zB+c3OepMS_{!klMta~Yuf2$2>&zES@>%0MG^{V`wz253J_}sK!JlMdwLFLYfv(N_J zubQCC@=mtg!by%D(*^AKc*QV0te^a~e>1GA5yUN{Fo#{tU@PI?$HW1K)!_<#)@QW6 z$%QHM<}<|J_w|;n@NOZP-!y>p*e|sra~#Q!g0JVX@b@omQG;khk9rF7; z*2)1!$^pK5_p4(k+HuMY+CQAf?)>FE_6(uxo3N>!uLP|IGMiy%$~&d4g7lRnnw}c~ zzmbPp3@4lk81e7&bU(%2U(tbdY5#U{xxK$9$7le1a{9x?RUFP8=#YHj7aQ^F;;Mdi zak++2E=-O2CIK$4RO;+CBOad0@<~wfE`r<>qD53WmOz$sQxU`Km0@cnBdg(HqCq_s zNN$)eZuI-1-lGB2?%r+W7LrtEs&|@;-Q20HmcAiNY69x(X)u0{DG!8(9lavZ#($j0 zszPHjei)Q^A}G47y(cBqQK9mMZEp%+L@fV!9H3G%hOJ!fH`}Y#vCUvg82ANA1aNU3 z5}(9@11>JYtm8jiT+W#vTwDoc*2dy_D<;+|c5bXLuQIOf6eji3G)yJGkCjkRPw5S5 z_H$s?m2j-OVp!Y9x#w!}l5kP!F6wD(S4h5|#};$*Qcy>4f2VYS%; zFsvHb#f_M9p7-6gpa3SWE8V}DxZHl5xY~kWOw)xjeeb-5gf69U2Q7WGZ^Cu2cG+xk z%GqC=ZlyTkKXbl3RzA<1D%yv)88_X#mhoT~>a=7^S=Bu%WNXd6D}1{7<2-gn{Ezck zWQ}iMmf!R;qR;U%O=W!=WAUK(WVb(?OfY>4pmttZYjS2RM=dkANPRtzh4^QnL+#s~ z{%@7lKLOppBdh-uzN+|JS(OADP(IfhB_slYC+hfr4Lo_Ila-wQ9eBbMjM)-|cm6vG zpp(q*w_(*W@ztUZJ^C@OG?nf3AW1B6FWG>~|*3nZSDlxK?Hj%pO0CmqoF zh1zPCu>tiH;~Nz|JE5;YM+mAEAkID`ml+g<^$p4Y+qsP&xO_V-wn1jS$+|8l4o;Ny zwRrjH&`E1}6X=#p=QGBo8h&C)QF`S#-bb7I5I_Bh7Km(GNN$?_KI9gZOjgK;&#y18 z!V0I!W~WIvTlt?}q^t4UKGBtLf2W>U$lLP;k>Yqm*x7iIwg0e2---;(0|M9Hz<6?a zA%BMW-M?)>Rd9tic>%Itiv&ok$!nG>D5Kyq#n9X(tb)w3>i#(7uG!3`RWGVK*d_Sf z7`@zSJ=sq~1eN=K1(oULiv>sHxi!m=`zH5B$s0Fp^=aIxRhS=iVeKVYx&xLX5E~p* zu%`-FP^qg2WQfXP-&$mzrfalTP5aA{x|-*16gawTo-2&cS*L24rc@_0?GeJvitatS zko7TgO4p?3S94tu$pF5k)j-ow8z^{|Pt}Zy%jRP15fBO_s=h$#iCNQMQ%_QamI8-! zwnO>bsjdz)@V;~X5e4x6Qf}N6^WL0TkE$5ET>;$c&Kd;txwKcJSa`)M}N*ioD^p0ggbabUd`Wr>a^@-KUze&JjlS`%Hx_Y&k|S3 zc4NACQsXFi8F88p`;2KO(qd_)-5xbl&vXPv63>S%HXY4I5!tUvY0r%JQ8OJE(aK~x zA!28u4*9A<9NG2Wy6rM8_BoEa)greXq6Psw+Iec3Ux2{TSja35K5@@Gt}w#2=Xvx= zHamNp@_3Pc!vl2gI4>9Cg6Uu)rg-ovdXfv(JcJB;&oU0RSqwfkQNFEN97sJe78wYs zBlJuebBG*JlS8OmZ`xp}`Vny0D8eAf{#SE;$h(Vxuu>VKH?>4%(@$f&li z{eJQ1kc0U9>*`ErFMti}sB(JIm?puJYhJO<5u>4-8Xm?GHxp+8sV4|+OX6n*(nX{n zeriAR5#Q_=_fn?s{fydZ>N#ATHoj<|S*(S|uYLJ&7qP#;i{G0(qa-K$|BdIKN!zcsA> z6W0A}hWkI1Rf3+sUu4aWGm@Jv3O$~RXZR4nuYOr`qosEeVm8hDuv9E!(EWv2Xwr3N z870QQW&Q-8H~oCGfif5Y3j1R*jb!1fL% zAmje3tnLEJDqZ7z1Rn=|09jI?ApKKwF3PXIk@ds-_d^P|^t>&nv^fpDIiLUJAxKA{ zsA2`Ut|JfzgY!QV5*!TlEcNUGe*f<%Ezl?nlnh|-ur>}fCVh5r(hEJ>O=7YZ>{m5z z#+1XyYdUy8L7*|qOF|)!(KT{Ki02z=x>?JDTfgGbPqsBEcwTJi!{-T`R3O^l``%8# zFQAgyD)F$YEEXPeg`K<jV$~t-rV(hCjo-R9bRJd*p+N#M&6E5D3Q_=w5^815 z_J;9EW|nPyKWc4?3e>||I51|M$(C7}PW1BRPBUP&VndIwQe&eQs=nYCl`_Lz(Zw4; zD%cM;D)UEW40+Xzmqdab==VbdWijZtINVN{(3-P^S`q`Q7e_D%TUbEU z?W`fBDn8r!1qK2wO%=dBue z_ChyBiGt5;PV>fL>mvD+VlBS1mBdqB$LbK)1^w2Z@wN6hp@d-kEy>9BxF^e187*Co z`%Bz4Bbp%ZH$KX2cT}Acn;85)7!^Squ6DZ0A+olUhb^s>_DfSGP9yGzDH=y#Td%^k z@6Tvj(=$)$E)CM!wx*w893RXUNFiPAN?g>h_%yH@OPKPjhO_GJ2UOVkA3vQYJBEKb z@QKRPom`N03cKZVq+7EXVg!VjMu#+-dhmCVawURKVw{Z%sp;JacyKg`yf8Dyx4BL0MF$> zKd^2YR#@m8x?C}{t4`WR%lxPLF>OD5N?5FQBHmCaE^|Rj%c|m*F(h~V8Pcks3KSEh zq*x5q2%*4HK5uhuDZkT#t=$qP&FN;4@s{*#gP=7KB+O~V^~ry0k42W?IXq=%?O+}-nQd)tVmzK6|1M#`a&y{gGu1Hrox=xZBg5WKDjGSNkAK!Gd@yliC z68TyxJ|%e!m1e(z)BlA8>$EA@_2~HC$&<8m(JplV02h~Ug<|rV|H2I2clTyqD z#ZSQ2k|%>2Y$YA`iAX$ss;P0OvJ2Tn(>E7BlZ+_F1a{5~H|drxL-#R?RVt?$R=6J4?>$d^W?$jXC64c^>ZE zGs}-Q7qZE^v`l5&qdUC6WAv+g9=q+loeKb?&;J&T{x$9V-@u5)Y&jsJa@d(Mi=W4F z3O`Gz&hkMoi@+CuS(Eo%4sfKl%;s&?Eg@hUX%>olghatXKGB;{oerpm$FkBqNap6apjz{)x`G@n|r5#XPTY z2Rd@Rtt{&&`}wA<;!>fl&P0Pq0!gb6gQE(o6O*Hogz?bNg@U?ODyELFX_(?eW_#+G zV&2x^ll-m1U^&6~#ZV#WX&VZcsl)Q?-tWAyewcB@=1UTaol9KkgLNMN@XjeeOcXOi zBIJg(0Nu*5OgE|l2C~ypDv6IqAli2M)u-q8aqQ<3OXK?sw; zP5AW_=DhQ)^{w<#$Hr=WPEOD(A}RlPMWk;Ae;^Vbi9rbtM<5QHcL2+P?jpYO^lgwE zC~-lljmmVu0;!rSXXrjx%r<|M%7b%=mx)sd_gF#kVa5b zIO#2SIn2MBs`XPXrG8ohb0amO`Vo?zyuc}hrpMzKf=ukKaa|3;>lAlzH0R_Fic0EOr`Nsl`c>gLUQMOdaq2zCY)sc3j)Q zID+eap27|7__2{;I>vU-SzE);)@#_ss>!HP`ry@{#5z}GXW*?Slid5+H$zETVlMS1 zu0#ie?xK7*37I#H9dxCqp$E;hOWX0>E|o(bWwKm$V_)q}zNOL^LUKfbb0^u5l+q0c zd&}VD=+5KApA&dWqqHz^aO~I_#+35*YLrtfS+0&`*^LZa)7bXUQ&e$2&r>|br_vZ7 z^l@JDBDtgYYzl@=Abf7Jl$jsU^WoRvyiv0jaOac=H%fE!kO<`#foK$nAFSCir=x&w z2{12RczA^0>k;nq_{jyUrZ*0ff6GSjs{pCAVxjDuN9@{P5pSRc#d3Ibl{G7% z?(xXD406Y4rN_#s(L0zjF?5N23#pM07vECF7EdcIT|?yCEw8Qipe3>&$7b6y#1V}`0nLc~Lb7IcLy;@NhmyWXRk6lwIvnq<3s9?f z`_G2^B69aNvm?}dA?;KZ+0IJ7Xr9L=MsBN9Y4UZ1p&(zP6$@0B){bzWPqQE%FO`*) zC(aZDcOOkdduXaZ+}M$) zArqGzlT!SJV0-0oEoU1FWp@R0eR(6GP@tO|krba06Ae8bnG_$D*gF)PsvZ-clr0;V zo|qL8ogV)oJvu!l0a*u@2q}0IhN(ldA|wth0Zt!n|Cc@aI%LX6u&hdy98J)o+8DuB z*Pg@!*TVNMW_*%f(BI%Dw|9!lc6Px26n|d7BGphyG9qeOpfiVH4W&jMFEfQa*&m#cnm({kozuGc849RB4chJ_ zBexvK^C3|uYM{?K6ecI=4X-gOL$=8E;d7DJw79ZAby#y4z2Mn%A9EeEW1AW>rWQ(7 zk&Q79$qyn6qUgheQY&LJi9I&Y%X=;&$Z{7EQn4MBXyvoAh}y6e4tm4Ee@;8#gAC7QSC&A14%C1_4SJoE4$* z(rbea1N9RKcJR-~&I#aW#YeuG3)5X{m3zOLG6Lk<9YJgW;`J;a?MLpbr^<($BV3Xx zmj>|uCpf-&3wWv)p#)4HRArH2HeAU*z7vdKvZ6MQ&yt005iTTg>+Y#Ry@z)#+Fl9Y zjg>CkOv)fVJnd`##r@2=Kyav9?ldTOb!^^~peJbqdr%zhNi=^IVuo*cKRH~sry8>G zo+WG-b-5&2%XTV1an@Sku=EmLH0s+Nw6Kn#5GI@+6G1rYox%Rm8|ZP}Y2xKHi-zNp zITo4K_aymCtLBf@FxKTAp-e5^9ae~|h>kC^O`(b{Z(W6$rcsqs&BgWN8}AMM5}jj5 zFJs`zJicSMoS306FHdfNUdg5&2`gFp*#+IS2fHjOrxJkz4vGnf&DX(Zybp`HSgzQI zU@|d0+SKT~JkhsnK>5x&MJ3fNFzsOcE2}<)2cj7FJ{8=fv!k-$COc8%t%d`fg0x#v z!$!Vs_m%BdZDVhb?bc&)v}dsgxIN9z|ZZ zhMKVE9e23;F-q{eMD^&E`G`S*xE`km=xs@d#hYw>3}ivg24z_jg+^_`X7{48&7!db zQx`7v*tF03U23$A3vUw{TEcIV8grTI$A@=D@^(VZgk94;d@3|Mq*}bJPd-SGKULbY z*OsiKF|hGX$)^mF&RgbL^4T5H+bwL_G7hdC+_*oSz0nulxM>&z!^tqD65-H++eSA#vTC+kp8R}Ngt^D`-=V|9ni=z8y^W#Ep<@Eav zid5&Xva1?ytVZo6b8CzVCN3eFct=8oKS$f*M6C|Lhe}?*T>Obul1$y`zp9)q|2eMx zJ9_!Y3Vwp<)O>TO$B(&c$hB}qw6kis2~%!EvStcjh;yOpNg-PvI@y-pb6Z4DLUPhX zgLAaZ^SfNHZ{V#6Ie=@tkWz|&#kIV}8Y3;zy4PXX&91bzZ)LCTv~}!Z`Q~EvCT%HN ztr8pbmLJ?pPZ9uTFX;0Q(>7`5)3v3$G&E9%PN#b(uIduBE*aljRWpK;Vo*q@s zL30g+nt1Z-pLYg`2Dw^1AP($xHo~ch=qv$5`xQvk=PYC$lU?RFretXgy?fh5z$6+1 z@`-(8`ecm0>l6P&s5^zUE_Iqb6>4feDeT!d>9}G@0reU7Q7q(0@cJIueEdO>qgI@t zbv+1{qRJZ+-3}OVzOUk4<-I#9O%osKeBCxGphbj4eTbjH(fkN6KPbw|`d-pFhZT*l z!E_USlp>8$Vk7FHdnf8p&#!l5s&}(LYh6hFEv${m<~XgHc=C<&ZW~E1O75G%OjVS4 zLd82``0J!c=$V*ivPAu}Y(k=MDiPzts^UwXSxJhLV+a{k@_dVqb&IV@`rJ^E)ZF(zZJSUGjznRt9BC7+sEz+i0SjDdC4bk{>FU zrLW#$!j9?mB)wX8+ewyh^3_@Jo%_wPQZe~SO~#>_)TJX<8@63X#P=QTuPNW~(Rpa} z4v6AfyJi}D--T0ZE#4}WoXM9QY-&!)mzbH4)+#P4Mz_S)Q_nYQkf*&Fa<%5}LCtz> zTB&=#qvAdRaaoVN!?=Gy@ueig?MJz2lt?&H&4TZT;5;da(!e}8ljXwW`Z$ac6W+1a z>2jlS-Fx3DVs0mK=+CIAEV5U*pWX~1k<_Z4x>xRseU;r>_JoGSrPKAzmJfMPB;N?H zdOGczPTb_vB%`>JFPWtwg)p>MYQk_I!(`o0ks#o}=pZNON4n0yUyhqM_d5 zp9sa8z9+59G_v(U<*RiU?zha3IO6xA5W4rlLNWyV6%!+4##Zfl4am}3k!Wrg@sqnL z`L0&SIuGp*_)2lDoG1W2Ao zT$juRjjs78{Vc^go)7TRcI_$?Dy-?wsjSI1sz=o_B@=j>#0N>)Po-x~b#|mr^DlFM z;-~m1+TpnXKUD|#DdB&@+5R@$>uCC4N;A*Y zqox57^ST?}8L4H%Z*LWWhCwI{!ZcW0nUxgI_t>wxz^{FKfgZUF zK4N-CfA7oZ?G{DeWqtDDaz)#h|ce)bS>}3ZL-eGcs_n8WaN@tlksCi|bFO^~hTH z@EXQM%3?0?5^Ep=*G?p(MyV)feGziP4EfpXOl*`7299pDsZP$ECp>GXug)sh^qZ5< z$Mz?r$?rhQAwjEtgVm$a_( z*=Y&8^_@)#&&;-bW-&Lf@D1-KFgh8@VVIPMknpB~2LTUrMB3*rX;T*X^;75e3%$t3 zy%H$Mcfep!gnCbN7|t?6LRUgOY5o*>GC-6n>R8Rsh%uS}gQy@-!L?kkcUE+S2^`lN zT!b;Qz+O&Cd#FPW4+mF)2kOJ%p>--BxECh69^jgKBN~O;O^6mIGQgby%o#*3wQNz| z_`EoM?>yYgdJt&y)&t)3*;VP!vvD=qeRe#pm`?j7oE~`te{&-Cql53%LEcPJJFR=799>J>+L{yJUQz!essCBz*Ub}@$eo|^bQ-$U`9N>2pEixnE;`9-{qhyi z40ktk4&xer^`RF-=TemxqJ$W`J!ZGu*6)-1o=KxiEbyO7W4#|Q-lvG+d!zzCwYZ`1 zL84+WIooFRF3hNFw-)fFEbu{ZbE+vfVMpZUx#fU^!KUft+1sem^1#s&+_?4oti35+bNib} z_WUcCBm5&z3BhDyaFQ5^ngbyp4}&`XwGs>)vCF-Zvpm7{;3PaY2m7V3ospq<8ncbY zTV;0%ZX74-aXNh@%@(}$YrG$q3pb0Fm8lwx&qmQ-T~f48e|1SM57{SU@v@Y<8Ti(4 z?KCu5Fz&7neoOBosHVx}(~L|IL9OYD+Ej-)e(!IZD%7kExz`>{DxZ3aOC>9~L|Kp( z<$DwZ+t5~=b&Qm0^nABA%$Amw^{AhCT0Yl6Y9x{sVHw`lkAai)E)l3S#YPLyQpj_* z@aVLs9k~f+R>D$iZYFDv=3t$L+NjQl6!E!w!&{gxG6xmLDr$3I}NwqwhndpY%)zcGW~h2?6H2?x3>Q*Y-f;M`K%;R5z2 z#IPuoc7GS&yC}n+%Lre>cjwndrfe_+#i(zq>9D*B**XOfd#fsRynt7CH#D}t2`l{A z32xjXa{rOS`Rc|hcOVAa{!@HRk=VQM0*`zu@mQR$$spL~LZn5WP&jGPb!2UfgV=%!>@pFNRWJn^Ja!&FPR4$QQg zKOSOt4!X6NAr>TSVx11hp1iDOV@G$>&F8^+&|Pa+CHku2>@Xr%g!SSj6v#&=M6=oj zo$Jw(vS0i8vh}sI(`NfNSnMHe)Ps}@EpD+{W(p6Esq?d7pl^&cbg!1UiC|!gihd`5 z+x}?(d`}x_YX04$`9j_Px{8By3K!W0FS;zbq)?%aAmLoc6WzVoi2mfYfvM+;CY&0p zii6E)on~Eaa~){4HopbLbo|vrO-k*IgbgJ6rW8Ep~lI+-?#!>q*j z4zphcvc^bCZdM=~jq3IX^TVjIxfIC9EGIc5vW^`oDEhL_&JL)9~D#%ja`rIA05 zp_B4oZP3D{1;%h1*pA(|4A}=Kaj@up2F!6>8=oI%re@0kd=YuY7ajm#{QntWK!4*) z)$!>E%fH}D=uwR1U+_ih<)T&1j!TI6)|X*Tq4*+fpv;keD#`0iZ=M&k))Hiwl`8F1 zK2_=U9sAM>&KjYz8B>+ZY1GjOMvE$8&}ljaj?}mKRgRmz&xE&SQyec6OT$}ppio=v zjEx2%O+%0?(QYNJ<6lvk!q@hUKfHCX*S!DwX{hu0;vY=nuS@9{M5C54fWA!wpZ{h1 z`VZvgU-P#A9|gv^B+V!tLsK-J3{W(XA1%bJ6PaHyzOvwN#j`Tv}6O~Y7LLXysCcqODnGtd%QHjlufg2n+ zq)AFVPY>m}j$OFdI?U*3IwK0U>H33Ww#$Ul!(MvBT zhACM@g*CkF1UGh(acc(re05@#8x))E$X!~zOe~T9t$`F5M(5yLw)I?ahFRDq;B4nO zld!*oF~F1%HV;={YDA|R9fXcdm+$M4OUsemvEy)}EL`vJckwTHD; zD9hFj9{-vPq|jMil#2GQ)8;~6ZLhY0_85)iSKX%5%@4T?GlMX$=rqP{O9ahWR{Wtlu1-%u zcP}=NQJLus)3Z1Y=&PH(QM}_H^M{w*tR>ZP;B7_Ytgp6{5XxR9x92!qN!1oM>|((?TaJTtGGnV`sX>vUcC^q{Q$KLyJ4laP zO{#cZGSo;_H&BT@Rm3XZu!9$tt&u!&qm1yxwQ~UX4NDO9n}=p@8eKz!a;|fQfVoem z^9s|T=Z;J+#~L?IM1GxwqEfHVQ4DiI8>PaMk>t?hgUnAkE)l``9w6vZmW@~N*p^uqW3LC1s)YA|)%M8jOB4bzKtx)!{RA9_f6y7tLfEWg5h(0G61BWq_gBrTH zXdhHItQLEeio&aAf?5}+XT#;<_%?$Ku= zZ>bEz$=|Q4ZdvZfm5F)HRmqnuPJS)Lx>bDjt(Y0psY%@0*}AEC3u1|>$0bDfR^rcC zG^TJXjD?tOsz8Xm59B8w!blKd^xRo;!c}uTY^z6LrQxf1qJvZ)#U4!k8~g+;9#Qi z{t6bkXmYd3+YD))P-H?$=B$=SVifq@*@Mn{gwa;wYLPNIDg&?(W8I9e#ar zl~ve%b=kT-S+y(Vu5NMrw92{K+&2UX@Ag7Wtdu*B4mhDCDYqFv>pF~-evGGBYt1CZg@=Uh_c{%E@ z##Ui0gRk|RT)x@1Dg)%@_Fp!>cALAirn1sG7@Q`5Xq?YCGtPbFU+v-P#V|tCJYvSv zsG{p(a`2hG4LQDXI1S)?7sk}Rp;P`qYzIO}4Vly1{A?2B3R4|vTqd-D3-Qp;da||TMuUt8 z&)glM1N)_ih8lL^2Tl9Frwr_u+Xo0Y{*EyCVKx$&u-pWLCS47A_R-Oj7%3r`>L_Eo z^P1tu1OW>(W5U5QHOU?_jdL^b#d0?06;V&tYdbA^^ZV82Q&KI`2eCQou|%|?Jm)2r zk8={H%>MU`4+i$zsJZo42pgF7Y&B|=y8H_vEGq?T8p(z46=E0NxX!$aQa1xB5xbGy zq)i9VEEDGog<=gjcKd}>qv`vyesQp@6+ZM=d=>qy+Jl;Dl<8$sX#x|y3c0pN(P#LY zY*Y>Oj*k=cNJ|y1szzx%@3L_?G5VbhW~T4qG>&F_Xl@LcpwNfibwX6vrPzeJqKaxung)^X;|(ls2PsGZ%#PBXvhD`@e? zPk7@KL&h4&_LwS{H_g7r!eh#TUDCmhc@dMV^Pcy*WI>85q1P!{Kz5$v$w+a#6w^1G zCfK{$x&>aE9-T(E(I@FmZoJ*;ftyHmI{{x>9^BETJBRv?g+S6vDhpK>_4DQrb0t!V zc6fzePkaB6k^agAVYFa0QUMkS1qgZn%kuSaOziYW0Wz;1{4TmmFkEdKh%6A&_X4mqz8IOl=GNp%ok=a4Gqo+6e`1JOor-a906Z21 z@EG_1Vu=4)t^42Zx&Kh`OlcQ{mNq&%nQ;l#qU_F6O5YP{==EbH6!c?|iIwnfW)P8F z0f}?UkA$9oQSc5ifV&#WlpzlC$xwU)(UhqPpm+}Zx=;8`PQd$7J-Y{sy?ii-MRqDkI_jnTF9-Gcd)JOq=C{mBH!I zDm9;WAJyV;GFeU_n)xeM9GQV9ODbwSr7DtRGRXKwoHSUe|IBPLl(u_F`rZY~s18uD z*-%?6d-b@EdOQ$!_r`BTP}q!XBUNfL@O%7@MrQ#FHIb`T3dOA>xdmgaIRus_q_i=i z++7qwdz3G7tF6Ag2k&Pp>xL&tEXd&)kZv=!K>;M-n!C!DLVQ&ZLMjj6)ned`3HELS z1^(A5BeBP4a=1PrHeVm5mFu(BU6t!wKIv5=l65lzcW7~Xj5iXEd6!lcCChtd* zts*wtZtI~&>27TiTpMu}zWyY&q1;r6HVy90$FbD1Fl|GD(b#ivGkn7pm(H-f*y{ih zz5@WT%DF1dTPh>U`jic0$)-;RbEJ3mI~8E0i@-6rigyrK&;*hH;}FIvx+8v8zm(rc8GWcUC4DRTly^u!#rpGQUc1VE3G>8$xT?Hr8D<#rM_DJ#rN4m{ z9a2oUM`O4*V)HV3jL+%d#wyMSR`LZ0ti6?n3*(d_^clw8D-e}{M9<*FIrNbm?gE?) z{^>dI*=hZIz56Y{orF7)mnl9*IKy$tZXcnGLBGbKHlXd8VR1M+a#`U8%t7w>w1mLY z1L$Zs!X>c;+K&B&AMZ7N+mt5O&<;3Dp5sJyLa^E$c8UA=C(?q`)h8Nux5|7I+-OeJ zBei?rTd(ji@o*4NW^JYHV}iedM|c{37RRCqh9MJ<m9Pq4V9c(MIYL>1i zR&{Ij+2jblzK-4tDJpe63oR(@MB{lE9MkAR!%a#Z3)HV~gV3!5*wPw5GiMH^?fO04 z!~wt-L=XU5SmkQ@UyPp4fU|4AP(k5R-dX0<9OOV6WmCxR` zv7+jeaHP5;@TAv4T!b*ByY)a{U*Qy%xVS4E9O~>8N{IdYppEu5bp(ju{B74IiW%36V&v^6Ac6>WT}h zrme}}*DyhcJVh9uZ*?{7<^JGY-^e4}mc&dvCp(VABEBiV9W!6OiUTV%XFrVdzoAN7H;UwSY zggrZ4z9polLsIPW$o2O|^q)jl^gboqIH5{oCFiW-m`iOq6iyjKtx<@p1xXKA^9WX( zMWecDDL{FJm#j34O^<}f0&8;PyNMUWNlDy9CIuJI&Z-vc1KT4o z$M2UYp_11SC!7bo-W`H1UT5OB(`)3}#D&%q-LqJJ;W zt%gq=&VEw1$nIcsH$Em1xezn{epGbWhhb4q%sxBhIzXUiAj=)kXN&iT!a-O)0y^VT2hBUAw^n z8Ha&+_3l~t=r3@6saRp<6Y{~doKYWU{@c~U&Qd;r;;-qbBzM+x?>^EV$BM9_cNhrU z*Y7hcaExp{9FAxnGLPRsjnPU!jZiN;n^u?ZJt$+^{(1!e`}Xmbwt-nzE&<&LAS1vB z`(II)|Hotv1)ylVKDi+^C>=O-&7b_^B|s6@zZWQxK@=-{nfv~NW^!#TvT$wu6EjO@ zP``e?4*3eeC&~Z)_5OjB{<}L7Ajtf$6_HZWt8Ud0lFi9Sc`G?xkS>X$RYYH=G@4O2 z1K@M|GsHB4ps2;}6QKy}2flEk_pa=RKVn2x;Gd24KY9@$Pvy+A4UsA31jI~x^yk!N zI(OoEr$txJN+ay??7dFPfQ5$Le~M&VrQ{0;4JF99RK;s7us07`-STD3bSl>3ZbPo< zzRWCQDB9Ik8pcyo)p1-IHQ!Q*bJw(*jRmh=rgmN3a4YH*t9m!7ZXn&I;gp(3oA>Yd z3OFn$G2P4YSM9F0U5+!2G~xvd1|(2egE757NlrDqk~u~oI`Jet;vT@0q5>k)&bB@LhJxW;-l#s z$Xz7(O<ld^73Vzgw}lZQ%-uYay{ZofP~rebGbLoo!_@^ingozt zkhki?U zuFPbBbSEWWpcIsob3#ro-Z4Srk++|Mh;z?4K#+cv{1mgSTWE#Xs5DVpHC>Lnk|wG2 zHAkA41HSKQd?R=+)n!jsbV3d(S$2BP!@Yg;0tf^S%1ayHR)$}W=_1F7&DBE=N%|tm zDmYa?_!2{BV#LBYj5<+OT)_n^32__N2GfKfqOM0o=KCbi3QFi)$VmpV7Tcw@{FKE= zKJP%W=hJZEoI?IC3?jCfC`F=Z`7Y}m{6gG|JYaWC@M5s!F4A9fj4nCLXvI7Yoq7iZ zk)Um3I?s4292t*wICwYxaV%93=m#>8usWXxMl>5xxzO@m!xgOSvVGH>(pCs?vN1+>q`+2STWT|ctb;v zPmzIU@)jvZF%j->f1FFqM@owoCX*XPeWBI1Ve~MsR8Gxl#IgkwO zYGB@9hq}+0ckEVBthX>t-pV7$<=>!eeJR-yT({K_X0Rn32>a z#!#;&dJErp*9r==d^nRPasp<@I;L-+PDv8#({==>Q#mDYf<^BNWHH$8?TAR=2FDY_ z+L_=)IM(|ME^6mMcV}Qv^1ChN@SmdF_Lnov zAb$(Ym%878*MXkzNOv(12uA6jOM%wXBvXbHR{D$Wo6l=nxe__dt}eju3{+k59v&4% zdjWn2+>JatLJ|LhC0KkPYW7xD2}XGe1{7nr@?)BPDXk+}(Ozekf{L3dWB%pUD>m_X z{(((s*mej61$~%I(DgAXRmoE@CRnpSn-f~TrQ*7cU3M5evv<>!^TgjI;1QrKWc7Vz z*QHTgxP#>!H3jRfb8D>6selzp+V};Gk5x=w5s~~O@C08a(%=Bia zjn_b@g#$H*BA*uWneC^EbK7hAv%u=v?Td5xzAM2r?hrma)h<+>I5%F?ls|kgYaKbH z>49D2bnrIF(;e##r!LS`u$v3nPYY>A`|d#IP<~C=Jqfzuff^4XQn{YgmCSWu1NF7g zUaB`$EY_iSOZz>J{o{Pj&mAG0^Y2^d=J{}1J3e1OI7~yzToWS5a8pDtF*%pT4ge`S zjeOB=JkSfCwxm;5Hh3ugk(|MXYQ4TkaZLT~q|uzjlF4OhLf{;)(8O6kc#Va6@(zF| zA`JkVpx^!@H1(v20MO*tm_z|U)0ZvbRz56zM^-*2b2J&9qvu0)WMF+8p<`2u!%Br& zde^G*YXRY-G;W*!bdVit)32I-k7!7ElKpDSj8?0B$; zG2VaXgVXF?8?W~wpn!}=^dAwXe@zTSLn@)W=rF#UfV=wp(5R;bu{DUlg~@nSXNDQ6rZJ!n5ax(+j|x8Fxe(1D_hACzt1ku6*Ne}}y1qJE*^>%9n?{j>CG`ES1_7qWQ zzWF{RrBg0zZ)=%Vb8ihXJ1}IkxL_R}la663YFutg73Q%r>1zDv|~8b|ys;1S|v;_53=E7qbz(h(p6 z0$yGFd}-ka$Zwhb&kLny20jD%dFDE7&7uRqfW0YY_>}$GbE+Y>+~Re>j*($4W4%lY zCh_n%=N`f>zv7E)Z@<=@uxJgYAEk9IMfaJl3e_1tS1@+3XxobJS`ruZHK4Y=9FxFT z!t6Cw?xGfFD!r7XL}tP{j@uP4V_z`iN~I7he7=*J@awRCm{9grL!Q^67)~2hehi=w z3+tx$-@GI>AN_LPkh85B#=2Ql4%Q1gV)CMMMcl`;Ij;O6!EHokYuBdcrLt9bi?#Z( zr@=|ZpcOdlfIp0^62v%IVti_$ToywNp&0QhskeTIE z74x-W)IVa?myBwhK+3U;`X7`F4K5o#>z!{k^)&4CbxiS9I~k5!uC%%iohRjXSAx%n zGN{vLWIigq5V&b$o34q>KLWYAgI^?7k;mik;2>b{pdGUH8_4PF*}CBZ+3^_N_bB>D z8>0x**(ysM#z>ZdsB+1!R;u@j2fk$yyZ0-43sSKGrz=ZuBn6No|X-m%jGGWKbThU|S`gb2x*dbT6 z>m6Wl7+6-Lo$;I8fmY^;6EfaV4Wz{Y6L#0_C@^7be<>_JEvFn=U;3bMws+0@VN3J< z4Q78UzgeDR5~<6ahVN`~#??c*w)W!^m*-ICNWJqFw{BtZ`a&UG9{qGdK z|E%cyPuP;*YWTZC%i^!t@}DYr4yh;yy=2*cSq>b&E(ca)%~yV7%OCb$m(w%#?XIA1 zAP|59B*Bhz92_KU9f1UE?S@wVSa|fHtw};CSa~&iYI(6H3_4?+E5|%U3_!uVx1%ac zQOP7t{%Qsp=GYY}x6@hyD0mKAPSXhUl^?m%eY*h#uj&l+ZQthqN84LP<(Xz%+dzU_ zaEIW*U4w++?(PACySuvtcXxLS?(P!Y2^J){!~c+~uI{ScyKDD9#y7@$@SJiox!1Mk znsfU|dC~|yT3H;yP?rR%-^#0*DD3k_CSJq_h$AAE87}?`;PQ1;F&UQ=>k%u+CA_5U2B@$`+ z^y55@^N4F6OKge1fJU#p#;$PxU{{Jx=4^K?U*Oe(FXrkNoW*xj7uhx927`F3=u1Y)j~sQCU~+Qtmmik6F1H zmF0eZpStc$yP6mcTTwoKe}k9Rj!x0${jB?tlkD$z*}onmYRjTOr7^m~@nfpEZnO@5 z{*qCRD%1M`1<)5M0<#tV`G@!*)?pzDmAaf!5NxRAGqfF-UOWCz7B=}mkZox#ZpY*! zS87O=d7RA#*VCk23{l#OaveoIu-+dQK26wMds&HhyH>kaZKsj(T2ZPH+;y#|iMdQc zjF+x8kTlP3S5b6R4d-q%^e@SB>+P50-Z;Oj{(+3$ffej7!>5ibTCO;OU>)?0qZUWU z`k~p0XzA*z6HKtSHH?x{bwFw%=)9S7krrh!%wdfBCN(X4tLve7Lb>Eza;RK^Vg)&{ zN|rq_IFSwH9w$B`M}7xg9qD;5b%OlGfM>IoeJGCOrb6slwPj_>1=4^xYeyg8rQ6vmo%O2;yx-2X*J}XJg8Nn0y zl6Fln#iVb9Dw05RzRb!bF&%r8zt74?MiC#LO3*>xF)t=Vm*t&Q-&vj8fpv-z5#t~_ zlgH>2ZOj69L6MxJq#X9C1NY1nrYKP+pp>W(2;%~urYfmh8DI4`tMHQvD%e1 z0hy3R2$;4S0IRCXbS@42#qe1ESB96V%G=oFVP$`vIa3Z^aUA7{*mr!!?)^Bwo4cJH z3vNsQt*4uzv?cJB2PcW%XeD9{!#593ALJVhqQxNm>8q-I^wK%1mOzDdYeS;|D4OI-n0dtR;gbIUW5UEA-2a>6upL9!CI>&u{=;xulzrsol> zOF-Km2@J|_Q5T~7-6(X*RTe%4v~~f5azyi2M_^FySKHXjNbs#@_5%jxvX?MD>s+@)(KYu?F9*w=qS>j^K1fwz2Wp#oG^MpXco-TTEEc z1Z_z__yt+AvrLaXu%BA<%Q8Q1d&W!TgObM>tE4i;B}n33(R`>-ER4ftNpx2t7S@)z zTXLjOSSJ%US6~jRG|OUjo5^hFQ75%j{&DhioBZx>iOZSr^UZ1!3NB#&VfDx@wUO-C ztjTtzJf?&-l-bcb5)SBf?`p;7LB-AUF~zn#i*2X)nK#6O=18VEruwCsntl5wiek0| zmVKL||NHD1rc3etE!V~#OFFgyemda4W4)aJDwkJp9WaxezIZx0@RasG{kXAF`>n7! zjf^4|Mz!YT+vf-gb47addG^Tzh=YI}K|*GUun?d%nA1U7p3w}&y) zn`6i~1)%MGCcS8AE{DLNoWkpjmwL0Yn-H2`Ao2N_shQDr)9r-V_Y$7JCIQ0r=r4;| ze1~cK_kV}*{vu2NFA!ey9|&(g@(+Zkm#P~}$*BL2&BE-j&4Pm>-Sr=v1!u$pK$g@l zL0WP^KCtP60wz4r3%;uF#Ra*?GZU=+EP@|BYa@)9OX#k9_LSqy=j_a(7yltk14%Ek zbS)&Y2FQ~4i!7z3@BAT4e;~YsC!z5T0O2K2|3Y{uYT|3)mz_H)(65Js!_2tW(S0(`A0TvKW4v-gwSFrI8v5KMMH-z_V zy>L^;A^fihPyZLf^YE{GEHS-TcDxclQu%p6>ul(Gi0}nvJ`^~y(1>{n^iOtT4~TQL z?vVD^FU7jjW$as&7M1}Uf14dXkyszdQl~@na>IoWyGb$k^f4jZ0iT-FzATW{R&34a z=aA^pc|oYj2CRC?e3mtJ=^E z3UAB|;4`s7fvW))UE z-g)%CBx9pVa_0|TQa4ii%hOYecf*A-a*v=z-74K?An%kOss(V7liU%v*1kYYc6cw;}_afZtni9JS~wNjqhgzKVAhIDP8B0Ef9EgK!CQDW>&CfO}e;xGZ6u#hdauNZ#1q-U+wDeQKpgy)0V^V;> zs=V{yjPBa&854hvu_)hP2#+JL-91nM+`?+xMbH;Y9NlK+WxG(LxDsyiX#Q)v;5(NV z`m$Yk-7nFZ9!@}6qQSORjy1`R<{0NM{~N;V0vycn1W*xjo%SeymL{yNZE`IHOiya+4*ha$Qs;Ht37uk^53tnQbiK8?G6?L z+l6AINKbV#HmXEc&G(@YcIeW`3=S5-M{JbKF+SX~BK5sG`nU*rAMaQ`JOzy=Y;+~3bA9`lYHL$C z(1*Wecz=?n|BB%)QzDd4@kJ_4bkg)(Si*;kicSOJ*Hlpm_Gf)3$ISwBXtOc_E|aUR z6Rc)zsibKMqx{)i-+P~e9$W@P&$FmK0_MF-Td?jh^{F&%zeP9b({pNevM)hx#WH^) zK}#L?E8uY|^Vy593QB>a$Ol6b=FGAf#d;b9)5hVyn7-Ym=hggoceImjnxFob;r-vL zs{iVgA^XFGXZ*{A_cpqWULQ_E;iaJ98-cZq&HrM;`)$tF69LX>UrJT(`c?j?39nA{ zmZcfm%K|XUpd$Wel(9JvY%>6iGWLxxSF|ri8A;DNy1uro-;6TCtucU6CIT?Zgcr9u zpOz&Sb>eeCCs5dGznJhS0TZ4L2&R=dx%X=Sfho)D3a-xaP-mFkik|?(<4i78^H{Hb za+=lv>vkc^`9|;~S#&B`0ArZV7s*{sB;<}=@h6Vll@R4DoLwUv?zoWNkf5S74Q#*b z`iM^|f6wu%Dl> zBZ94vAxi>Ab6Qh`U9Z209i8W1d$oAhI%tzXAed&v04^D>7nh9iC%`2W2qvLInvBE? zxMUDGL*O4^8O&ozYxzry{fn=`syz|Ze|O2yrKwMeYqP6u zlT|;-wzN|$i?P-E)N9j=7U0a`+%@_vRMTI!U6zku+4h}fK78ynYz~yIr@l8!@Trep zsgA9Zuno|0?=QG@j17Y6S6`ps8U`R<=K#e9I%%?;i(#xNOvGi-x!`rnHe;F;dhd2e zm!XlbVf~{~$;Sleod%fJ0!B36Y)L&7t7Yi%yDgU877h(LyRxD1#)BVT#xm!(&&uw- zj9*l0<6dbHI7;rkT+m)+uT&>hX+)bhV=t|&OUN8zvP*k1FM{O|k|N8vP+;0qwi1$F zq$BSSZdk`eGZomb1vgvnmELAMEH z|8+$hd}030Nj{gZXJoDUJleEvZ=_ecbdL)FcrAx%;jT)#HS@a4NBukZfqw55-QIqU z4^8K&_NwvjTTkE|H(Lf0{&(G1(FXGXm&}2dHekZzNH1S3{aRtOw;R=A7G#8JD6pdo zZeBz3Rg15=hj3A6GCia7G^4A?uD>}D1$APKvba#6sG0QD*h!I5fq>D%0SD8TtwTVF zD*AAIr%Sk_kPTVLU_EA-R7aG;d@Xb$Z>1ev8bjRzj8hgdRE*0SB0yXu#=q7Awa+t!*i&9_f3aGYDZ{brhZ3G8iI9$s8BCbnfOkE9T| zTz}oy9%u@6{jCe{|JEt}KN%jzOQ-alU0AMYU$1SwkKFY#7dGuO9tlQ&(j5I=BfOrw#_@4G5x`iq< zN7*)(??>;TDB7ikH%;MfX-zk1=&41g=6n-9KOz(Uaauz*y2}3ic|^nT3vOU&ZJsL` z6ER&Z5GcJ1O1~K|3Odv;JIm>lK(MuY%N2f}APDlt0uSDbOwj(L=K5iB#BLcw=;TR->u zHYQuU)8A%2#57y?qxwMUBxYqO72ldWadaTfRJkvX&x^24zG-E0N)KL8S9Z z;A}!2fl!%bg|yOpAtgaYm(SdNDk!(X7YHam%<7J3om1tkRk(yTM1S`kR#?8p`;ZUy z#2UL{$i6lABx+=6@UE`OqD=>Br*Exh^>o2w4CY!ngX+f2k)h9DFyrXcgiTVrs@#zasAA;(`%Q{aMQ^Yu}gBO)5BN(}J(;jz@pJ&-46TT)}=t2s}x> zPIfB#ZY?jLtGF#OSgX5w8_k6cn^98XhRj3hwY@Kk_KdWOvd>3Ci$`t?&7_*u@Eo~Fgy}UA)U}Rhz%@DgarsVueLr^r zo6)#_XEoK{cy@7T8RF0dy6pSphvOp8VD1XU+G9d95AlyFq{L*UAx6_*Ai(l9lD^8a zuEZv(r|t)gq<&FtbKFInGn-5j$5m%^%123GXmq69P?eL?3&fixP(8+bW1;-BZBvcf zC4Uex6=nvqo!KcL`8c+d`^Pyg1uc!W+0f4eMqo#9YNs%+(liX|fiHI06b4}>^qC-b z5?wgj)S#9hH`^ZJ=uQ>)nIdhVw$&CePnpx@R12Y3%QJ31ln2y{`?1P%7^1t4Nlh~7 zdMNId%sP{!8CEBn1b6Pe!<7ge#qoN4CEhd8 z4DWlw*yV$L9+KOf0mZ}O-5$dj_-SJBGEJ;SSEj3tXKS2g8%(n2&3A*XwTESz0-iay z@`4_p$A5MCz978&1JaYfMR>0O%Oef%6O_`#Bl=ne4 zV2b`Q$uHA@H{8w7k!M=BTuWQ`GBB-ON;U5|1$EuiBoACaG@H7YLUJ#zlUlCq2 zbJ(c0eAEP91u?ejW!);~d4BaH*+ROG8N_?t!{P>e-1q8q>gqeI!TZ={8+w%jd#*M6 z)V$h)KwvYJ7eu%|GA37;T1kh~rR7Y-4)k`r38>e{oU)_|wL7{JL^f&iH>D(u)f^Q-q-PIRr=)bJY``zoH%^Sx{GlCz4 zf4T5rdxTWa6TJa~hhbpC1#eyP$C$hiOX$I#8j!;kMwCm+E@Aq!Ko5;Qy()Q!DW6J6vSY%T?l~PbenW){*WHEV#fBIDn+*@RpapDr z7Qfl>n&e+>co~mjYBdunJSI6}wCa0n#oG}Q%I>H|ICz124)Z&J4bS?Q4G$f#;jwwF zcx{FPHoWAl4Eh-%gyqQJYRU%*4`ddq-*>SBUs7u+$ zvhAYI<#TL~yOyc7D)B5ZHV%`VY(75&*t(4zh{wyXl+Mj+o(bf<1_zes+qa2NkcL`T zBdAATZ=%3o40g##D}dp}XCi>{+JtwK?il5G?q}5cJ2cH{r~qSK>T6SMuEv#f|GGGN+02SdouGB36hzD!NhB6ikBX!geZhnzR6ghc5Ioj9;ingG zFxsC?c#MCT@Tz%VyRU`SmAEWFt^$wjwe#j(=Zu5~#Syv%H~`^+dEqvIv4E_QkOAn;ZO=J89wYMnbr(^=N)Ut@j)Az0k6ZWhgGN zS(xFDOG4hE6hXG52icnt$@f|?ojFj%qG^LGC=P8gN8w=ypg`G$KX_)J=YCbg)o>K)&|>2g;CiT;e_$E;V91DeiTAr8wL;{3t>ML`xJ!)hURqkv=yZys$45m zhODWQ%e1t)!hiwQqq_gH>|RI)5j?S;)eNZmLvS)vIxY+aCq^y=>Ls9g1$UdzIc=;{ zU%~)s(ug58#+2VCgy>7O*eULDD|nKIu3>fH9@dI%G)Hr!V@E<=bRCZ-Kw#@O5{Y=d zO$#Q3XQM2F&`KrDdHY^aS#2iSjj_Rig!G3KXI1`NUm_cy=0@b~~1p6-ha?*LsY{m1POF_fFOVFeX)SGSp3 zqk1$4txiMUAa?s3{HbDE;|c!);j5Ic!IJf!FYRrGTj}&kN#l42%fYtX1~Er0@;P51 zT>t9AQ}PojOZYn%-k+4|zan_Jp}%7Bs9s|6?ivF6a&wI_PFLbY0y&+x9IrLAQ7S;@7~Dq|N;x~fi`1rbcIHv~KK{lvGLDU(z}Kt{XACG!h9fI5#WYmc zO^p_k$n`l-`pNvdLh;QbC%SbEVXwy9O%cNxOO9?{)eTd zU*y=?s`I!;OLJ|PlzOQB~3}QB}Wk@DOihfKxYpZLxaBKTLRC?|!?Yy#Ufx`1V%W@;HHXmGS%L zwfl$kYv<>m5ZhD5D{vj8cpx)=Ai#``vga$>PyR%j-95m$!e(!Lp2S%_C?s)BGVgfd zoucq|loLmjWKP$nKCR72?kK|l8hMAz^^jSEh=$u=gHLTHl4Nfkgg!fd2&8Kq`I0ki zE+cDq7CHEA4jja2hEsjOCF=y+y4rv>T!%YN8AsYq%AnA$DFzK!Cukrz>2(y*FrVJH zRf*4d9bQ8ngCDuFG-Tu0V6AFlBO)jWgd=+49ar-pL6~T}R1grL-#}9JkyGPJuRDIo z>$iE+UbiiRAjEHl3%+-q7yYIs+Lss^SGY68`rPSc=XCXPOYR=*n49E;pkgJV(mQ7{ zA$KM@){6tvbhGNU5>Jo!8x+N=&(uMKn5Mo6#6Sw30M2KIBPdgos9z~n(6F1@RY#Y! znn(0dsNUD(#>2@e)M+O9Pj#@Neh+muEDJt!yb)Jyp=!7BS~J%npKmqJUE~p!>wli3 z5U8Hqo40S@_M2A3KGs7*#XLl>Ik1?OEZ+8V@eX2jhaYLjt}1_`#5MOP_S6n79D4In zD!88Vv~-F)FD%9?S3J4IX-B`|RwJLt;BMz+3J0tPFSmi&L{i6Nu8=!!(udgqAImp~ zb`L)Pfc7S&Fn6<@EJb$KkzBmQL)Jnp!pW%??0SXx^Oo zh0dwJXVlkH#JVFujO#@#6~lun$tKkKT`fNd(dXi+p1RgR z-8?%}gw?%7)ws>kzoe>Nd0`~%ksdME48hVE3N z{LwcDI^<#urmV<`s9BMC=%naE3T+yu&h|6k?jcvwI>xt~C!sV;F^4>=qz_{Ui*3*JOJjV;Z~KIO9rx1j6f}KGa@^ z$Ho7Z{(x!2)qg?~+iv`%{AzOnXZ`Sk_&Bq{;#RpD^@9QSD})Tszg$}oy1uD}_&W#Q zZ^H6-&%1x2cmE97 zepAdLPTx8_WumU;rA4%9L!+9sc5UIhZ z5b+sodM#I7p>Am(^CALz^17b-J+f)y^FCQl6$?T(zl?Z+*^ z;mZn~=+jXsCLq&8=Fs9xfBMc3)E_XQnfCD~hRJ5wL18%|AejgC))LRmW;eBBdRYVF zQa*oYQ^3cI2qw7ax@WUp3SW=FqJBT+FZl6kaW>kd%QfM_7w5Z@l}L2%tLn_#t>*fw;zQE#d;&MwL;p%C-02)k*K@+aq$yMYqW^kj*a#T zAw`2Xgatinu>w;2$qIcU?8_9RiY>O){VufXQPr*I+P}ml`(MQ6BeMY>zCW?W9&DZ| z?M)~kE=Bp+fVk+IW^DW>F8DPs;_J!ZqgG>^Sjs-=dlNspfT!;f=C#z;s%iN8(nI_rE+0;l0CCZWYdHR0Tt^2>m29g80sjCk4Xl`3HM+SG3h3yp4`yIKb{aQ;^4|tBl!p9zm z=O8QL{=jO(qRo^}UMtRJ%-g>06e-slvJ;Jtc52s|iz4IcAAq<}^v}t@H~sM~;(-f2 z2|gJA16Hte?&K1+RJkb-vMpj+d7%}=cdEUa`rDfzfrfIeID;rV7jRqR(dMCT!$VKoJa&;qw&-2(sy$4tV0{uf;23^ zw}Rwm8E%ixdrLWuX?64016t@^xPZS!cQ4}dpI>PI&(R&yZ|IKtzeIN$O}pvrfOh`J z1KK~;%>5tG-LImxTl(EToRe1LSIvvttUv+0$_A@{6!T#GHfKp>xY<*b>~A*`H%VrI zPvdG4Ysmam*yAPSin3cR6|#qE02h3&XU7gdHspa?Z_8L*v$V0i+p^33 zl0MJ9Yt{16V>bKMdNmk`%`#l5W!@gnl(t&tS56Pl?M z{Za^=&iXku^|9L7q4@k;$E_w8@ohM2q`Tv!kucXR;C}W!>5{yH9DRc$o=grG)@yx|P*eri)B4Zpn9lF@ zx(q}_qb?klcyifRiTdyDMyCgax9d)a-ZAgr+ThCO!e*TyL*)gW!ZyHU=`3`Ky_OBICM7<(O&gB}Ev(BJ7$BLnBl>%im{E zHp#czX2_>}cIlTkR~}$tdNlQ4PS^+LWBZr+7$WUSV3brD!5{U=pbAvb9cAK@qV49n zumbCjg5P|%Ly{sofI$`elWy42XUm|&U*yh`!NMS1S-?WNlN(Oz^-5W*`8Ij?C_Q#G z5ol4Umu$)mTJ*;g@hGV$t;r~4Gmf||zAkI^-niHI*+YuRwD}6<0J*C&W-+1;%3l+h zK1kh<@>w0gZV<5O{-pNit4$;n%G#Mpebl4%LroL-fIY4Pg!`B=WF^#|DrQ=Q|ozOY97<^b%~ zLN-kTdtIT86nSb*wkhR?1}bg#i2I`S<*=|Hq@o)&&;q;5yt-ZVf&V8}oGs;sND*!g z{#>?B0!l%?LIvGMq$j&nhJ(!D8o>9~qU=(eGS6**G-g#j0&RJq>wR*eabn?ZIK4~4TWl8b-PL1f)`iz?CsP=# zYUyd;=y0h0AK8AcAQDO8dHBwRm{MNM8%M1SWi*3orD^E$ni&5OL8jtn;eGhH-71os z-O!R}c`>lD9s~oYR ziLNYQXQ#_cJMJ%dLtfl>|3RAo_Z>V_qJy7eoeay%Zk7$bN51X5zm(u5SE8tWUEm+u zbo+-kxxNwP9?O<(%-fFRZjoYNtJGREr`}umdU`E!&AmLXdbP1=3yydV^5VW*{{B|E zz7kgTs#q3HThAV=r%`3X@hQwvVZ&H14cuZtA8*6$^v9X6d8Wxt<& zf6Y;6obUKBO+I5C3&lBUlcw^Q%juNNh_wXfLxIe2ShqEWcL2K z6U}nDG41Mhxv$lwzBeXVEz4PxcD5DT#QB9%#8GK0co?a{R|C3}Vx*SF#4R&{qv{~O z%}SjQ9z_KiOn*vK!ODv5iTj*u!N>fF>Xa-|k3b$%rk>73Q=X(|-t4tXE&s#W zQ2Mb9gc`y-g>?jJ^8}Wl%Fp@rk24=KS(OPbl}%0>2gef^mn^D@%eAey!SBr`=-u&vC1oHgzXqnQMDj$Ojk1v2HbVwtQ-6W=2~ndM&| z{d;YyDHJvYw8?OHZl1@ti-mALx;K^$AxF=O9`Bnu=$#`8UIFc1iw3B#DV+P57x+k<%PM&SodMxNr9Jc$6d%Uqe_{p8Cq@kDvD;;{M z^t5dMb8|c7)Hl99f~0Cn{=Az`U^P^L(q-86PKW>=A*1~-2N`nDn#_Oezx$Im{pYvg zUv6k|1w(*Ri(E82D_Dj{b$&g$soKz+W3gQRw3gH6d)i5$m^U^{tJaaO7JdodP;}Se zJo25ia}_U9yVlvJ+q=*VLWj3hmH|8v3u1Grb=x#pVN%NUW2{~5q~VyN;JZv4MTlA@ zZ<`FLH_7-ziazv2NfoNw26$F?%=Nu_w0q(hkycLS)=q8xm%sW2-z8)U#5)3t{J*rX zIar$M+8LV}X#Y2jyhidsB2KUps zaYP~;J6FU6T_TIQ1>e}q$M~=q<)}${1A5%OcwfiV$40_iZw81^gcHcB?q*MK>a33i z86IN7G{MFsjFwV?ag9mkXPCa*pKEn`ls;JgBPlALmA=oIY zKnlVHqhvKJ)9C@6hg_LI9<(1Eq!_xuSvegEfqX_=eP`>nMgOk8p82(c90u?5s7<(z zKw7nA&7FYVwWMLZ{2K$1gQ<;o_;II@#+VmfI#2{C4ZX9wu9Nii0%kH|ok*Zl>%~`~ zu*9-1h{NwOu8m>?sr<3WAEY6Z*CE7SyZ$*0E6WtI%|%R@0qS+s|$1W%azS6I=FnY@xI@dsRWS z@8O@px>qEI0)2___mgJa_68zj^S;?dq+Kh~+!P0(^5!)AZ0I5`zWWj4v!SJWEx;P< z8sxJ<5z5NA4u)`7nb?)XL!Cqx2C3IqE-zWcrrFpi$gBPCxW&>~C1Wf9wWPLdc7^)& zN+Mc-AoZ;k@2hT_M(v(WBx+}WSn;de0#c^^#@yB9QIYwGl zR%|v8Y9lR}TNS+{{v7FW<>+7SJ-_FEd4pDv~&oo6B3%1iOr)3}a}x z4Sv!ZPQsX(OPYf+MO%IgySH0`B>(g!jhx98rY(}GqGzOpqK&!#yX`EvV7GhnnNK%e zp{L<0tobZTQg1W}VkA;E3n8Zdo(|C7Tl5o$22omy2)xN-){Ctg%`*0#ae3RF%Xjrp{@18y4wU+*>{pY4c znLJg#!nTY6$zs{Q9@CeSJQS5>?0b0GGIQMIoj zg*eMnZ;qRa|D|eZNcCN#WvqazB?GF)`AgL-RHL5W1mA;rLXnwM5aMi#u?dJ7KLibN zVx*x%zH*cjFl}81=HArvmT~vB^R{az_XWiiBriGz5KJNPObC#fXh$7^2I43)Z8 z0kRh8Zxq$Q2cd>ovXYxHPe|R#nWaZmZV>D5oV3m;U(7uO+HL zxUxHt*mC<=9^KLVHi6_$Spn~ha*2p{^r&78pCYqfiNWBa>x5zIH!5b;+Sk?E+v}Cg z1bk4|j%KUBvuHF1NolJP9Ymw>wt1)2lgF;;5zG%NFOr`u$3`k&>UQxCdL50VHitUT z{F9($sUHTIjEy`Wr`=)0tzw+V8#uMhg3FD9uuGP-v+eo@UX_`<+&iXYY&G9^MLo`E zSJo!?dtUBSOBY9@ce3Y3;iR(DT=)IVj_(a=NJ_OA8-SGmEb~U_!Qq}Z(~Z8TyIl-R4?bBzVLGxrysyFG zR^xZ9-h&Cn58ew|x}c+98GHwdi+*b5D0kgP#jmlm^x5_>to=YE^C0rT&`y}1dr#nnAvjKvR=0@U0I$ZdbO81z3wzMVPKQIOM%zyLBwI0uO zdO0!k$5O`e4`w&V8H607c(BF{?@6U)x=*L{@ef_S&bzr4EHQSP-`M4`=fe7&g|=E! z?b2rtP1BpSYH1f6e{guP=%$JP6o)p|O(u__611R6R1xreFT)VZIs`Q3d@-n94Nou4 z^3=CW*ghr;&V(eQd@qM^lqqOlnsmd}P}&|R$e)Cfq%}P)A^NH!OAd=A6~4cUm%Kj8w^_!?)xvDL3jZ)Rss@$v~kWMTyxqz73`-69is?dQ^Xw0PDw7D-YZ34ibeKl zNFFq9Zzxy0b#^D1eVa|aOm#?d_ODdyw6FH&^9UwEdzf%%tSR1v<@oWbt10_uo-u7k z32mXnat`e{#{Ic=t!!K!bxZO$b<$DZIk*IIj+;whn&>8=jf4R*s zzFDATpMO%^#B^eQjJ*u0rS<%m=)bj=BHvtK$*lhGtJnVLgY7@RQh!yieSixvL_Fqw z-DG5q3aPyRHWs)NIbvU`#Si~#^QhAEY~i}tDdn?pw(U+Jq7#A(I{<~FxRT1aY{4e? zx^DWrCcjHqv^(77cU;l}{^Sv#%2)dCq`24vUnz16Cm4_~zHNVq7Z+rm&UF!QV(}}+ zVm(r5y}%_qt|4?{uR@wNrC1MC?HHL0H&4WBevVyEj6Qu-zM*+aZSf@S-J( z%pZy(9?*6u2oMn3f0K3d7j6HqLIQtV6eaYulmrhJCG|Nw4zpO~u6Hb0DC)f(EDG-q zuZ4{4@2*^2R5QVo==YwG7SeOZJeG-9454ci&3X0syIn_Tu zAo7`XR+3Dj5^isK2V{g{A@dJ`C=|GXT9EX$M){=k?48==L=Zdlrk#fnW?r!IDT5)H zzO|$l^(4*Y?O5Yy@Midf|z86k_JKs{|#Ph_MsG7oSF|4l3SW!jvhjEf!6s^pTv(eFM}Epxh$?I$h}_ z-zcHq?&}GIZSdQN6a-%(vZ%AxtgW-Ap>&mt9;)3P($W%(A(g?owZNvIG}x+g zxi~-O1V;-j%I3n0`Y2~Rhx%r|h}sZ~)4VRCg8M2bC7H~o~NSk;g} zKl1JvDTF(4GhOzUO~xW0g>`IeJ)kVBnwB5?>$bYQ>Zhg(w>~AFAora4nRm~XlnxFC zg5hTgnhPEhUrhyJhIpZSrPP=Pziv(tYzfUwAok>F?e%4?fvs>xRG})yrxX(i5Xi!k zxsZy|Vwl>Jxm2mV?~ha$Jrj#u?Ka{e)-$a5e&1|*f;U_^;%h5Xa47ibcpG1-(w;h3 zun0ghei8}~UQa{Gs(+@3GEI55odCV z?9MxFxoI!#MnDEiP{>VXum(-)2CyF@Rp{0o5vEcBNyFzJuig^l5T@Fma!kty& zBdaNz)ipdi!xqAR9`Vky5>?zT~D0 zvNIV}XcnzB33L%l+RK)M{en9+oWBD64tG-)Phb@9^rLjkP;nY9QVUqV>?M1KzvXv| z!^>0x7yF5v01M#(f?W-4CnZQ;sh_lgxY{kn%I_PLLUyatw4kD?jL1ZI-^o$I@p5SA zvfe-qf-8)Zgdft}r+f=uFhnL%j+sf8IS4lcPZl;11{Y?=ad7%}%kPPe7-=hLBjb-n zWG2o|zyg^$4jZ^7b&D?ZB=zp{}c*#43>0vE&uCH zOM=N6Wip_CaQ{El?>|3r|4|i}Ah0&uvz`6->L-hg;%bZ|e8Blj{d#zX2I~=U;gSiY z7%Aiy8TDT?NHNWQCEV2a4L@EP#HQh<1-9fT?rj;@kEb@DSzCt&K%jI$M97&xyap-c z{FFkeX3!pVyFpNQ5qz7Dos9o-;+bFBLXOF;c;$6aE~Wq!^FE z=PoD@1aiIN8mxQ<9vCWyAlr=ss|3P_=g6hv%be6ZRkD3pC=*`$C4kO(9l<)_iFig87FGNn~<#( zUIAh_odc7X(+vFXh4Zdh9**VDo@CeDi3vU|Tw@g_zRla<;DXsK2dQ{K6*hx044bo4 zb!Pn1m4zV-68L747MZIo%qN*2Y8*OqcmVcnI-d432+Faq5G81wo9A9*Dc=G{D8B3W zk!(MEmSuX%Tl^at@-{(Y@en%{-=@Obp3%zy=vhBGJO$SA$3zk~#u>TDrk+R~L1bN? zps+h+A;Y8XXgpqFy9`Bp&m@lw+ulrJ$Q4gX&QHtlKC-wEpa^j_>a- zI3xj~IDI8d@l9iErDrQFx1ZHK5+YAHw;jVn+Pyz9#Z_A4L$aB`D_&sA4Uo?9BoKav zDE@4&*gem7CK2S{`q{9eHhC%;ER(~%ci;ikq=VvoE*LqtVPPwe@h2yxt=AGl zX!xo8oM?0h?Zb8cy?1e`JiYZRhVSLf?)g%k>mSqSBMskYf8yt4V-PG`95jnuqy<#s zYp)EI=$Un-+NjJhncbUKgKUENL7K4gP@VBfH`J*$z4sRW7i>M_v*gtRGZ77T`xeTn zmSG{6j*NJ0AJYoEDC!w-4_bOz$NVl%Q+WT&u6m=C-k~*qm!%BJZL;U!_h3Di=Urg`bL;hqO~+}k>0KSH>31jm zrTx6OsvoHM?)ai8=^r*fMJ=uqlO)J+$1qomU$K?Rp9lV-fD$Zf|4=}yxm$5hWW-2V zK^v791ypCp_@#itTT-gf?>xx2T|sX}laj`=l}HCS;$gheO;C$1Kgf=eDv^7&745vINL5%jbGHuAOM8$iebwoH_J~T-AXrkv}nnXQH9n4C9I5*Vx zU91Qa{!!r4M7`U6(+wNvTf{0`tSwU|&)@EH>j` z74YTiMou{MbtUisE(RXJ)c@7{??1nU%OYPg4_``%e`Oxx_I4_ALQTPNHu?kmo4ur1 zk|UzFW^)!_aLCT3h?D0N-%tfr9cYd$l*?I|yhoQ_)fpAl6%zeGl9gjZj*RGw#^EW^ zH>_T2T2S{82Or~7XN_2p?S#-i2r2tW(2Cjxc&M3PCNHxBG9#S;jwc8<J(#uKp zlYSJ6vHv26RyXk}H)(5XS1ZJyfF39MQcr86;Dtb_PXF{@&i+{!t&dQ;3UnF7+&oWWZ^;I}!Us1Lq+52f?t! zYm>fF`yQuPGFhxLY4~9x+|?I0*jM*D&t4b0KLxbxuNh~d_XzO=Vk(zjTUQr5k91@~ zwY@hmc?*52Nqa@AJAfD{x6-ar-kyZnmyC%HVFqc5!M~ZPx-&>B6k>Y4g1(jpA+N%j`1Bm@W`*usQ#JyX#HUaa#vuTna3 zXaOag1;uu(_|Q7eR?dLnJ!8IAs(1xPc<5&b_Xt;1mNDV4b%oXxy;+;xMECOXl)pkP zDp+T5JTRY1O&ClbCO!Aa75yJ`i@)uJ4GZek*keqjfSVAD+Z!PCZ|_ryc}|1+e_q}w zI`V-)3L!ID61TslVj{K4R&Z8+d%_Th0_IGb?Wr>!QlErt z$GS4&ovpw_`8?c6yLiUYPqLV{oY+na#O*Mkztr7fCD^Lg4pvR;6)P)S53k_{3a5N) zh>LjS+Sr%$KKS@jcbDyesj>V{)^(n+Zcyf43;TQfsbS3M2|nV0d~=C{C{TBY#$4D& zC*KS%A^v@8N zBC9~qxyI@Vo&EaMUB>+jmb*^k)AVj~JtdQ6**k9Mh6WALz&Y(d%hIA%RVxP|OaEKv z-M^Kk|Jyrtu(zcL=u1~rsZCJNKC+tVVljAWTN>n01}cs5s9!3LUwq=cTR_{=kt*DG zCEOcfEa)Mt%D8!=0V`_kT}E;u2RN)e5)?e}f~1;i-o7Tsg_)+KMz^-LYxj&3@(j8Y zCkw*+fznr*K$kg(J{XX;^Z#-7RsnG(Sl2d?0Ko&ng1fuBySux)OYq<>!QI{6CAbqD zf(D0R!99G3bk9t8|MSlD{C9Ox7gZOvYM*DXy%zbSe@zgAwwrQzYU82}B~oi0N~(qm z^E7IKu41cg+{tU}k{SzG>V(8X#v}@2$KIYadF={zPl#RS`^Mo}qAs|&*exavzloyrun zkd*qEFLbVwTVxpLLEfxDl=6lP_2WP-DV`;f>USYrBZT0-?l-+CZA+3T&4zfYCIx@^ zKt@{jeUJ$&V#Ky6075~|d$hk38E9O>llc+rzkz(j(#@a#ZAUz?BCbu7)D=NS0y}wo z^*3qKVX<2Q?3^W3#UVEApOnO6nR|6os9vU2D9*7_^;BIw=FJg7gTj*S_lw&=@2TBH`$o`&c{U97#8R~?P>UXg7=y7EPuOuVAJkQpZi7aNl8$;USVX}VBEMFC5V*~J7d0$3mE zF3sl*#%}YTCuLhDuHz~-(imybBFE>o`K(bVMNof9Q}Hip>R~*wGi%Ep2*`!9_K;8N zVo)R)luU4SJIB#xpNLbUg7xBgUbKN1>&l3(*`z^$dX=;lLa;f?UA>jq2eXtem{2TH=h@TEZzLUrxqgCWtor zFz`J^`LX5#FKo4*4D&%f7c2Je`ncJ_8Wp#m1 zcsb!Jt>=m2pcg)0wiH&3jA>Fz$gUkztA5_NK>L?6y^N6}_XfOaz!(Yje>C6y8)f>> z^J8QLJq$2E2AaOQLx9v)(t@7uR%ZA$Kw{H(%ug~x)wm!&w-q!z^w%<{B*zGgLg%oR)H}5> zvSl*dQ*TOy;$*0ZHV@KgXQE^7(Q zzWK|_KNQ=q#s<*jm*p7Ue;A|2VqAO3 zMn-jXO|*dTq&d6)Y{Vvn{0{{9k6C( zr-H(W1Tp(j3QK%;e%CTRl8MfFCoeT^2M_32`S)Tpk0@%ZS|DpEaks_~m5C`bN zMh+#IhZ@;?m{d4u_x9=4_X1CdWUI9^*uJY3lm2jz?gaTL*CN@=5ZsGuljYc1+MGOX zu38q+2_^_b9)pHARtjLjHKh3hwaAqAMDhLFI^uUAoSMTYG5H4$Vn$Fq(K@|QSo~6L zBI5Oe@pG-)m#v^qUy1k+5~?1uh4F16RLTFQ&Lf@NgKLLS#q<<(cMQR?BZO z%|0VPOE?AU>9RXLJLgdnUF$K0t?q2{sXe+2UA~=MHAs`vAO#PvBuK6YUoOJQRZjFg zP9%OFGItd)n((b3T19vm%VjUTukL@)GWI%ZT0_~duR@3XxmJ28$94bwnH0H2 zGG`o}lcKd}@*R>#H9kC_nrG-xdw<@VbXfkWYB9Sp{)S1Aze?!=M^O9ugQ zDdU;ydlM$xVM~WWqzt;5#bi~{Z)?PGti95iAeH8wrZL`)!3ZczRrlGMi;vcSiASPx zEKQAJS4;$-%~P(d9=sx%E!) zp*dKMsJyadz8qEi`qZfv$R$$GZhxun*JY9C;O{&$Yc^Sxuaeg>l+;O!O1A`*M|5LR zsY;BlxPisgyuryEei7aA}6^2+-(tt(=vhWP9B?Ef?x?MhX%$9KLOe+p+BZ))LVPAi{B%T`5INv!$98a%QkB^K@71XFP-H| zwrY_0CUHx+{%~U$*ClW*g>Z$oblPI1!i`R)8Lu!Mcv2O5Tt&MWDO5UMKed<6((!)M z))sX9_@R;ZiB@K;Am3540$pX}6%uYoHjnoiOY@H>LAhJTKyV!T`yvRMni+%V{_+Uz z!~`tS$8TMSf5~=i!DFhi2XyW8|1VwpZ$sxFb&azuPo8#x^QHQIB0jQ@jEMaox+a-^ zo1^z{bWQN<^gng2fSOqBQ~uAC%EqAkU@!FM8=Em+b~SjTrVTrhA@f`dt+W(NWVa3wa__!Z2{ zP%nM6Pzausk5AUsK78#<)Hn^YkGJ68!SWZN9&#rQ17pvG>iGGqWLw*M%zXTSP zv3--Q0?%g}(y#9lnO5OLsd65tDcO7pL(EmlLR~^?HJZ|O5I)+J5s^vX1w}6*pL^>y zShNI-kmOQQ+CT+E^FCUsP(NCfU#m)RqxW%l0+lI%3Eq3~Fd+4Or`E-*HaQcg(gN@&talsO6CVkyR-xkDAg2kwfE=-g7B+w1 zVp(@g*pdJ2pqb71(*f(YO>v>*!|k(gG`T~PK$^Xal#^&SE7kQu4q9;~JRbsRhxDW( zwF4ph(|(2H6dJv|@e5DUGgE|=Ntbt3uAjF+9|3s% zj{FF+k~#yqq!t}FqQ#aUdz7SPis@reyowD$Q0}x0Vd%)r zNLGGh>AC9MnKDtiSn^#np0WV5zA)uC97M%atutfyr7;8x)FGav!@UsZH4Z0H zw~nAq-G;ej?kf2{@G3E8gn?N*>8-_#Z&-w$OwsofvA_t<(H6qj@1L%=d|TaeP@D1! ze%Jt1Lx4`UK_p#p)a?=?1{12}AnAh4mYDVYL#P!tP3(;|{aO>+8(i+V zJWffJt2{sQWazJ6c6K1wBJNI>A3X(guyI?n>lno!zZyD`>f+6Sp*R$Mw=b#|LEssL zJ}W+$U-?kD?juaJ=GBmGCBFRp^P}b6g?CmXh zWatHJcMC4g$Ji`#svj}r-Wnssu1i*3$?<35wXs_vxR0(+e_8rVFkV;{0mCXcFs%Nk zo%g>R+5Yp?nh^QNskOctIsfIz{5P9wM`MoZFPrN6Tq0F}KjzxG*Qri^84{&jK!+J7 zY5mzjR9&%St+yE2gt|8yze}6R-HzHe4C3`iku@k@IHrP1Hp{8^MCcVXzU3w0>crv^ ziTMiw20}X(k_sEuH!_s8tylSca)lbP03m>29sZ^%^+# z{+r^LO}t`iPC)7Zuk)rq&+h+Yg>!$nYZ3+3lB5f8-DI|r8uf{4*kzbq6F=SwJ1xTR zw;Rzcdw_MiyTI*e{DKMzu}_KyZN9Lhx%M=NLiw1212IOqn!z(;>R)jwmp$IkeLZe| zXg_@^X=wR!v%1yNe^d&cl zV$)B7C>6sh74;&P$R_H@^mePTu@QCPvLUOkvdcQZa!(G9rh)Hz5hlBJ$cAT%(Ivj@Cpn|q`TH+>&MZ+#@Cm0H>}Lx(%s%w1LlY()&^~GvEyq@hQf!@M{$ouA$|si%zx2a0!^F)Gxp#I5d=f+tMZ%)uLwIg z`6kBv(+71X;Dsl=TSA+lD(?S66*=YJ{!{#vg)1eT*X`?=I-Uu(U8Xg zB+U#0xl6(AO8RJh0Nu#0cA=!VV)qzL{-V79fbI-ef|n@tuw6AG{G&ZPo@B=xIE89? zXjw69!)ZEDNR7aQbT5ti0~ulmfn3LHoQ8=hO&yCmAyoGJBBU0|8Dd)D?+`&i+R0LT zO&H?@EXDBG^C=Fct3cU>g4@gIG9J_YLD+^AP{rwNS!kjHo-AaBddx~;I9>ARnV$BP zRk50++(PWY17DvpS|-;_V&3nz0UIBY&&91@!)g{ZenkGD3f*w7$nGIfZ(=aX(Cp=!#TkkY0`-7fu|90@(JU3VwAi<9 zV>5?fbN&oqPsKvk^lU9Exh~a$78yA%9ZX?9d(ot6v^Y#dip!$_?2J4@W+LmNR9psN zXVOhB&T;>YP(TK4tu{0CUb0!_9@5DhScLAi&}^GmlU)P{Z=5yuSjKY#WoooNg;Rn! zU3Y~|1$Klm_?>8g60Stq%){FYi&wX;<09uK=S@vp?Z@|V3qRIw2xU-s04IYy3dd1B znYSdH8(jMB51iu8QO}1h$vj!ux-7MX6xO8p%=U-AmM9dABVC_ADD}(3b?-N!79K#F z{;vzCeA-^KCitw8S{#sadQ9Q9IQ-h4KzzWjF?*^eKzoDYdxVdwQBfuX$jCb8n9o z_Pde$Y}vnN`Qh_o34o?T)1~`ybG^L6QCVbbZ?*s6d|Ew=6RrANeT3q6wXn8oR399ksplsz4LC{*WR5&M^T;Rr z7H1_K0)3xwwhTupNtdS*BN-`|v9+89HY3Z1Vmq9l;iA!7l1lny5tc`Lo&r z-{gMnc}S`iI!#=4HI11XRa&~y`g1wjegoBNhTCl3XDzvhFGo|w-PFEoRAz`dLo;bS zt;@P8CFqb zVj2tWdWWtV*gI4Ro$3W&a!8)uqa#1lV97Ff*iUBj+0xDsgR|BuPUb#V3fQ92S=V}^ z!tGOKlH{#;emX3dZxJEZBuKgx(l>g09T9wq`SA`#T=ZbZJ=zW4YoBR>Tq)kX*-=%; zftZ;Fs6KFgCzR)Mw|#fbTgCLTO7l2gFUQ-18h^2h+Y|I9UtDR!BSbFJ3#qL2~B(kk%BtH}1(3^`uMxK9f}|J4)N>hzK^-Z@qe*HD~-Q`!Y? zY_(EeFyuM8s-4Gyx^wbz(}8AWrjvqH(28G0H>DGyHqyLcpIprVc7jRIl(WBbz8qqZ z1A~NF4qJODA*%??@YBE@5`a7DyJEqfjUc4bzYu-yyU+8+??0sO|3j|&iz1hkVNsa^ zid+w10ownHI~jEUC)#QK+fh8%RQ}$Yl4#!A%39g6o!*AUpqNxZ-*N*=ZES_1<3n9v z81L(F5lm)qaj8^GbMz9nq39>EY-IiF);YNM*yF(f?c9`rB8a_ZHU^+Tw>Ruc%fT)h zXZl0>O(zf;_t1HRwI;&T*=GS_mIRWGWAqUj#10i;omZ2oiLB(q99z{y*)7F#2~+2g z)H>&a=3CXR^nCLP7)q^$o2`^+m1x0VONV9KQyJ!+K?{|a5~ucyjVYpu`QzY0h;`=h zy50$G2`Y5zT30W zQKzufH?r$^rDnYT5G+7(X{w4nL$KjUhq+}8zrb? zZt`iNW1@O8Ql8XF8RiLbqYS@0&+o)!RA_{$8)df-@v{2hVw#aeX+UjRVR0-6+19)suPt zICyQ#kgF8?E%2*zV3=bEK{)e5x&y^?0p3eRxOydXSj>6_u`=!)t~UPMS=8|}?!;`F zPn$~YVLAyPg^^JTP00oMOh)ph4BPdis&Ka=pNY+J#8dVjcSXs2)5o;p#aAe4yprZ%0Nlk{qgI)*X&j-9c5k@lVPb2Xm6DC`Oo;V(Am)~53C zob2`EdVUV8Q4XjE2+LUZic35#u1en|a5}*HOtiSpmfhl;-ln;=3$I{N{k)m5I0KgW z1tgA2nkD)AA*`3lL<2&b{cI4~06#mrk`6ZYM$O8&&0e-{)} z4r=MN@ss$PzCiHqo9k+KEyd5>3-uD})!Q4+@?()h-^3>|O>@o|cKT@KhXgI8_>F-O zO`2OO?*mJ@i*ZG{bHY1=yQgd&PTdg_SLe_yxak^M7z$=q8{;*Jx8Lmk7+vzBXBE@L zgO-4vyFpf{0RSaog7e-Jd$um8&U*!fM+Nr1oPAy+JF@oe z@aj31*=Y9q-i9C#iN^)M_%6@}204Tc03D`Td60oBzQIjL;kE&Pco5R6We5`- zw%*A_yysI=b*3EZIvIU>s|jeD82f><%=m(Gd3=*a90mpb2SHZr0yIM<5?2!Q0#o|? z;`#&}yJ_{r)G&GeiXL^BgW%geKT22+OTY-vnW3M9nWwT}ig-`hgC^)F3bjg|7#eTy z$69XNo@n_psMUH| z*3SxM>=vITh%+voPR1ZSSTxCsD#!s%JBoA&b58(6B`;;-5kGjvU`S$&wRPp_*^6#_ zODjGjHo~;W$}M)VXH>XkMN*VzP$K20bAAxZFL21uf22 z9OR)Xp4I8dbff0~*n9Sed(D@*^fn~RD<7CkS%A5e`hT0z{_}wP7re=aVsDoK?^o{! zZ-ZaBz;Y=ik@~WfCywdf-0V*4JYAJ^($wABB_J*C1%~$ z&7M1~YW>ahq|JQMIC^5{Dcx6PP!?BmCa#F?Z&M9_mABqyto;c9o zMoy041)A}FLxjYT@7jU=**cfrzlN?;*tIus+5u-;#cKMOE!NK@+`GTeHveY3^)G;M zH`Ojl>-8HzAUP&MVQDrd2o=AaE?b4x7b4X#n#`vb4oD<=`UMcQ_j=ew1Ao#J=?ic2 z60RbLDM_ViY*7`+d?LsrN>m|jh-{$zxiNV|V0nD`C$`BP`c*j`{v!-D$i6%yVC0PY z1}TEM=D0UkfiZ8@wQVdigFUQAU z)i@uC>t9iofsb7KfdsuK5YxHaHC;yD8P_YE+kRG;e%GqeAu3~*#a@?<%GW>}osiKk!=>D$vaFvx<5-txi+S2AeWSP{aaO|KWDaE*KiVdZ_EhK>s3~Tj z1c%`xJ*spqO-|ICBf@q&Sn!eRN}oxrTZEhozad(j5E;wrU7=%?`BWum!Vpww8CwC7IMjm7V$6#!V%E3KlPd~%QQ-WFSZ ziYKF2C7Px*J&u0QX_gtsktU2*uL79<^L60*gl#ShRE!W5%W|F1N79qvgLBaa# zLUK)@$+|U8uQTSEQ+9s{6gAs)=1LJ}w4LWt<~Zm_;_)Qm;V_SqesTWk)&T0cYE$F} z^R$dZj)k zJOjb&3=~6Rtbqh5GllbPk|m1yLuCJ%Z6<5i?1Owz1O?%?f&k2%_%CM8n-w?bx}b)o zDhj05JQSr0ajzEYkaWmdQrjxJ#;w*y`S#UA!*guxsDeokz8WfmXy`eP%Uw#06jLvc0Eybq86K-| z^nLX_iIdkg<)~E4FretDA$Te0MVU78@n8H?RFZBcEih*0zIQk%Jj@=rHQbgo(5uK^ zIJ3yGosjEm-1JL^A%7l=_Xl>Fi|m#^*;P99+|6lyyWVjv~rG_lEJ zW~@69#3XJtGx4UF;$%=f$JbckeFJF~yNXuDc0BSeHr)$fCAbWrn;aJR@9+IPMbM!n^t)yyx6?k+KxD4{*PbUUdYYmZ zU4wyy_ge-aC}2t<_pz#&-{IB~eAJk68GnBBF(T0x9?LH~nLtMi8z5Om)tiSlV-9a+ zjCS8nag=y2(GI{|*`5;N_lFW@T>6n?<6~SXq)V&3hPp z)ph1y1DqgycG>?v-2Cs=+JAwYHYhKr@nXN?*B_dKev;r1{3=kSc?oc8qh+)fq_!vw z{%*_v9+TCQoB`L#b)h&)xP>#jIX(QmzG`Int!B)eYT>EBm7xZ?J9HwtKO@}YSDBhJ z=CbaZs337TB~dhooxPIJYWen^Lb-%eV^#T|c~d~&?J+{p)%+~h6+3g6Jo`(0)2Ccl zCbPc{H~-Wg`S%k)f5Cv%sbbcq8w*Y>wdN&yq<8p#f&sz5JWqI`;vI=WpThhf7o%TG zAVOF+w&LgI-Ps`t32Bk@3&q~k|3|txRtmZw1Cotl@K3t=8K9e#LmXShMA@Bc`BZs3 zH<}&W!P5is%7!1yXE5ShcVk-%VSo~QtGQWH9q0FltspZJ(uW_6Rv0n{W3$yEKY~@2 z;!SFZyVVHwc|d+hkEX17#(4$OW2s$Gn{3`jNn7EG{<#_{B&gohnvh=^PmeH#Vv;c0 zj$h_PmE<^#PO}nL74$v)tAedpIytOFo^h0Xw~!#{8?PzO)9ok#Kq%}I9A^l6!GB~F@0@dF7<%7cssa0ZJ+!UFYyvt0TS7> zB37G1ps@NgW1&&<(LWIy@UQHk0Fj?F{7%6_(n;Dx;cB=0*6E)CWnRt~*9N+`sGS&yToU^>HByCAaqaTjm{RI~)}f?kk@z~xQz|+Mh9Llt zS$+Gdi7;UauyVrsO`XuTF1_u=C*LZs!V-Pjm1~mpzJD$@C8`n4tw3j_XnwJA0=M0- zj9l+?G@-Z`vfDKDf*o5wK{9_rleb{b$vQiLRJULjh0`d>kINj+Sl0Vu3bRws3@2;U z#ilGHpQZ4bKp3U4=y$qFzee|EVerG2k9g{!!meA_o&E?NE#ra_Bl{DRq%qQEt!&oi z6b#RkRQ$k10ak-ej%oU3P=bz~0w$7sGIHx|dlI&T4m2%CvDD?5er$L|@-{)9u7up^ z#Ao=P{?6S=6_v9h?2h5w2DYUQ8b3z-W4~3KFBApm=vceUPwd7yuX2J{I z%zmMpTQ77oP|*GvpqrA$kK=oe3Yx8Fr><(tS8K1}9zGRLyWlw*;E-Qawiu}eVG`Q3 ze5<=HsNx@ImE{9Sz(vxj>>)FZ21`qszeO>qMOELm<$}L2&DW%eF+4A zS=ao9ZbIpi!-nu?t#nLKrPFxD{ig}--nE9PH1iwGK{(~U}NL8X@!ut_G@Dk z+9N}HY4FOHeIMA}K)BcVHj$#t%Vt()ajo)_H+%^x0&?KvY93VRee)Js^LxO_MYcoK z-nu>r?Fd@AB4y~y&m6xUCP4Lehat6tr9Va`pN^`|o|hM^ddJtKjEvl*wZ%Ce+vB09 zbl!uFu^-YZWr*+#Zj$f$&?`Mq_H*v{x;|3t+}Y-*Uvd=fT8^rYXgHC>C15q@WYtcE z(_8Skk{IWi(%qLtM4q@#0dO-y-k&2-(&HewZ_ket)}u6MuZj~}KL;jHX1^Tup5O&; zszPy(&!5%1rL&e;3YuFMGvED!n~;BmoACJx9`5?l@^tKA!byi)Y(&*?QF zhGl`O?s%eWv3eBKAaK{$?!5v{@b11xF0_|qIXBRkN-#%yGOSKrB==k*6(m=R-d?k zs0qzStv;XQS*ItcThv~#KM_felO7Ov@$3}sJ>Hj~M`nbxTdYdRw(P@Ua_{A`5M2Tr zn_@Ry&Tp-6)$J56Y7~P3vS|%&$Dj9~J{qT1c_7g(hXZso?OnS$mvsarMP>mtA;V1bczl9>)E%=a z2lpnWDas&#y|K)gDcxOq%{apy7Kd}JA>JV$!pGMkc`WXRSWaWU^AH8E+@6Brvm)uk z>`D=JqpV386zyy9jrCbChp0kJ;ISYOZ7?Uk5^SeWhG)Lj)1^HMb1Gc`J@XT4<8hK- zKtVC{4Kr8w3aUaF{$3+OdZKSYtH_3O?>MqWbg)#H5vz0V=b@CX` z&Djc$SNEHiP+(Y5f2^{2!JE7UanpYvZ~jTt{wKWIto*P2`#}R7cU)|tHjv%~WmMh# z;YZ=A#|@IUs+vCmme2x6PUQM2o1{BwT2a7xEZQLB_Kl{FmaK8j+YJ!2ZGStP>=LJO z_23D-ZX;)KBWc1R3UPy4q7D+|cNDhTBv|lk<~zb&@DM_T^$cS87;iuH`HBE#LH=Df z%%(N0K}iRvEoUCKyOP(Ox4gA~)h+^I)pLyDxWx$Y=iTg)4@<%C#9 ztA4r?nQNGM^AI-eYQ<4q@hMdC_Y&T z$rlL(dnnPU6v*qf-=no=j>nSu%)JJQ6pp?B6*nPZXZM=bAGbXZ0F^1&}`kh{DD z>ar}>Q$VhN$gRqKdWBDh1r#j7cgcy30B&eH+?;I%K3Fv0^;Pg@DrePn$H(_O`eaZK z(r+QbuLMz}M1HJN&Jc=+oJu&5LHYBrg@Ik(D}^G!6K%wRh|0^!*#eGDHm){THH$9+ zroXwPUcb1b$jMs>jC-&mP|oCD1MaA*Xs8i2#_fKih=gc(f?v%+Mu0nt(!w{a1Med~ zD9om6=gysrurXsY84BRt+{$m%+57Y^b#H>Ev`?0Ld`jex-c7VB6j|o-IoI!d&MPa6 zoIwvXTL|Pf1(##(qsW7LJslMmSBFttoCAI^EZdSP6SNp8o4#pXj8R&TvO0-kRJ7Xwj(#C=Bc z=B|{{_`6EWeH7oSahWaDY+%R za^iw_<^L_BXB^o#fJsbtjLA^FTRX>3~EUf?eEOJ5)&*$$uH~(gB_}@{cKRY-7uz2|+ z-6U7c4~g%a{+{1hM-biX$ISLbF`vS!0~&<}!ubJGCS0^~E|rTt}wcwz&4 zWm)X~7K%}Yx?=l<9kPE`5n?(1g?GS8=vQXvpCFCc)_~`?(6V1DnsV zkb1fp@NeEijxGUoGiswrvoLu2ZI^@t9$YUdTLc)>jy@5b2elnKxS9J)ZTR>8(58>!wa$QQbaLJqU5rv%i7m$yf+f|5`fj)&mJ(Np*=MZBiB z!?X1G^3ntvm7wLwL$gXu*_T)=VUTR_mCPr(;DRF;L^7zDi zFonKFn|4%I?}DGe?nT9huva@G%~ff)t$Qkaa>Xsmy{ijRL{NbUui+D&MbeUh!oD>5 z^oZ~VH$cv3Cx_t-NQF=^pxERuyNls9#A^|2e?p=m0n z(vtSA=tRBSN$mq_wvRU3y`_Q82M?bK8B-{%NEDrI=j+uNn3tPC>vZxL9GqmY<)gVA z`LWHG^5lWtONaU_fxxhU?fpR}pK+tqDwXOQQt`6YjH&(*SNZr^WUNU|vgI4*7JAY(gh?xUZrFwoou zZ=D~Iz#RkPgzzFx9)LKVB>h>OvVMt^)5Req-1+4-gLa}lA*V3)$mz(X3*rn(LY*0( z=^4}etzAhi)yNTUilw-_cvgr!!D?5o@^z50Dlra`ta*=d$9+N5W|~fcoQ;W9@Tm-f z6*0ny6Os^-6J1Tfd zr>_Ch>3!nfTK?*mOp;lak#c-Js9y&f;%8O*rQtEfH)?L5E^qJ}>6v7aACe zd`k+Wx9dp)YBG-tM@g<@OV0DJul%xZ>e$MYw)op@^H05+f17Ro$TXXFv<2)#e{^nw ziC0=u8WC#_?p~XUQ~o5YPX-RvUk-k#;Rq98&kcEz$b`|$ZJY%~L@%bqV*u+WB4SGk zZrxa8j(0WgD_5J=J9!tj8}?JLFBd#O<{f*x41V3v0Z4N`aL+mPa?eTUt=GKKn3rus zT8w%TLQu*npHreg+e8ykjF2#aSivaKpp?cGbX}U*xMfO(7o7G23b&n8HbM7 zA~V*ENFGg?H3;{2WZb$k!qoIMF^7g!qgQepbaqBgctqC&{RkrZx{ybQXjRU*)d*hC z^sTT%cnDAAi@gG0lkqbZ>Cj{McG$kl^1CHw_#$7r>Al6gy{dSNa3tOR5gVe0Ua%Zz zMVq_1%}dTAEy2}wcp1{L>DU3xqsCUee^jA->{AWZ3BvG5+lQ}$_nWna>(p_^R6ds! zGJ3cMOUe?3$NK6OZRwc^d|le8@w#`7Hyp@2qn|D2&hHxN#I+;WP@%*=f4mK-35tcxk!3lnvOH^DGWreRAy)DhX- zA7xSuj}Q=Fdie5&;85Uto6;0yXD%J)*-%(?_V#xOyjJ=5 z+Q*d6_Ay+gD3WHrvM|wjovE;+cwr!hE6u9oY)i{07}MCke<#H#aG0$3lUCf4z&0aP z?Q~n3k-{>LNtH>);ZiG69TwA3--N{~U4n73MJ|8gXe>TS-I1uk5D!JR6HR_ReiaE&oJ(Embas6w5?BkUfz#eeh1GIFayr zN6@Bus+P!uWothnAZ&3sPnC+~ZJCWyeVpdv?(oHkWOU;-v=&7U+DFgKPqL2^Pzgud z7f5RaUl3HDJWQ`Xa2G&LMTa@5HuSJiCFkBHGroSgPMKfGzsmKv zxII~P_(`GyUEz1{rsKIK5K`}Dw=Md8xb6l@gjaKXhXw9ymh?!C>?now9*u-8kyth7 zU%SiEV#gc*zIXF4lJ-B*%|ClLLt{Q@YvNOW&=}Kk>>wR(NG}oYH*?A z3CgX$eh-R>+U*s8i)ddE60-6qGy1=wn-+j~6XK)EM^J}f-c6q!fNp-xC$N<6tVR)@Mi6!haS_&Bli3>qIJmx4m?Vy zmz%=yvx4SMRm@2?!una$hn=oZj^~HziB;s9(1*)DZj(I39wTyi5Xdc}w)X~Et1@~krrvyBHz?2B z(PG(%_sM5gF?Nw~N+tb0>I&jM9L%cwK6u!22aw6TMmecST{{p=sl}YLj z?un`)wcy@bX+&7o_={DwX}>3XMWnys<_q4O%tNgf<8OJvn@Y+52i{axEA784*N-jO zjk}Cpk2#-l^zK!P7?|j%YS1qz(z*~SW z4^$`TCu()S7}AGxsO7JUUUeW%X@DKu?R6K-Tl1BNni2cj7=VQ)zB7|n;(nc4q&0P8 zFom8MYAB`)b#HTrsF&rOjea%Mm|f^BrsFo5g+P!ufDyz@l- zvlXppv4@S!kHWKhdK@yJ#Ks6RsV$bc;?GzYmJ?3yeX0YcFWybI$x<>mfNp9EsUK}m zviL)lIzx_VgmPOs_A%c@hIZtEsXFX~oo zRInsr^k=$h@lU$B4A9M>UvzWZ-1ppE_=Rqg|3)_zXcgI&0lJAxRrZT+F8@w9ArPF7 zAX}jye0u`j@@MPfYx%)#qMDEWWRcK1!RB;%A^Le^za*|JPqnrnu{4y){OvL-Var+0N_cEF8yQ`4r{cZ2&pET`%f}3opzxMAGFZJi{75}(Qr}l+KMMGG- z1TND}QZXMkG9>NU_}$tPHyz6R1Om9Tm0bbrW+MxnDYkp~ z>o`W{n7Rt0B9!6bPtZYfGR6KEftPHrZJlDCI51)&7Af$8jrg{qL{sJdW!==>{Xean z1a3yJnf^B0{Cl0~za`QSXSn?q!8xN-3q)}01zJJ_S$EWD=@oc{me0k1I!nJk`bXAX z!lx(2dSkra8nbf83}o}c7JDx7JqMbmTfr$ zM?NKcQ2b(KC!!Z+ZxGFGrSrbNa1oyeB!S${jrRK`O_3Nf^CbXtTr3~tU{5R?eyhfK z-<3lq^N9rq0E>-R6FV{M5>Qf-Dn+O&V;EPYPm^uR8E3X(;gFFq9DKn3BWD*Z5XudX zMGo@4;yX&aiu&dJ{<6LGFI2d=F?_HDAyigvL-t^fs{RwO$2I)8C7AejHtZ2+RsmRp zpWMv{d|<=CH{RCLVMzJs6MVpU*~5I%x^^cPMzX8kGMO!%Z@inmsvXyY;BaSKKjfOo zvkrF@gotjb-UFKaEQC6eCIDpm)4agy!4nKpX?j<+;PiB7Qpls4t~@J|k;CH*b$T{z_F z`pC9x;5)-vkqwSr8fiKAVZ*HLtp(VYPZCcmwvqqu?& zR93B0D9YQQp|BJjYL8FnK5o7ix9-k=#I0h1$lK}2z#Z-P;O7{uyPQLLs(W~?F8_kT zTGhGZ@1SDbLVyi-pTs#fk$yARrK%e7Zif}RH^o*%6~2v5RHNs>my3oYKW0^}GnJ_M zyT4nC%^2AV8Iuus_Pw;-s1glfk9vqy^1B^mIgYRq&)Ag|&zYP7-M(M=BdnQ?hC%JOcS7U~ ziKT!k6zX*O0}Zo#O9GD|sxolBO=v&6S zK|%g%a4Mv8@*PYe7%tqZC=cJx!#=KZJtYh1Bfzf36$6J)*CaLipK$O!|BK=>N?* zbzuHxD8}#ko5#TX&GJr`fVZfOKbVvl28Z&e{LKZd!BY0~NJeDJu1@kr#;6Td=264{ ziAiQFj+(q@k8e!czHGU5hLg7%(S5hBg$I~^k8lO>*58K&GU*;B(1`fRUS}$I_~TH& zS(9!F&uHsU>v|EE9984E&}!BME*zN@DivIZ(7ml)Gtnz>>Ztge!r|EZ93t^?3yAh$ z5lT2%&)F}Nz^W!V&)A+=Y+EPTr|bze$)vkc$-u$I0aV{>Mdd=yS;nM1`9k#gGO(7w zu&4-}m~DY}_KgC|k++5PB%c=Uw@>&=^W2S%F7^(u1=GBdDhU0L zqUN{47VG6VI`ZGhdi3E%K67LD4MNW284y9whP|W5%D%~e?tim{$usE5O^O-J1i&0F6{RpMT89~n^vdSd(=MjWQ(3g1W zxe}E+4Gik#r~b#$t2)5$2!}xOU;}Z}|dOt*|TUg+Xw*P@8Gs`;d&#G-R zulWJOkaa(HXvvP7I3HKWO~fn?xkWuDbrAG*Ik01w#4zm!EOj}a(r_)&jDDq6ZzoAV z?7o-zcK#VT?Q17f!jWHzc_?`D{5LYd{$eW z5#);mHxkSN7Bvm_Ehfmmt@#hb*TZo&8>`;>3PICV9u>j&CWB~T1)Wl(1#bk7s8 zN};zH>xfPRTt_F|TGk6WDw@0(AyuJFw+il>M?6jqPGkeQ}rNlGKM_QM@~LGwriPdV=?`QwW*qmy>=H8DjT2;|tGnk{eAm`aKU{`Y4!|MMaC ze=lbe^#IG6F~5bkzm#USi3ivGc5GAfqxIA2>5zqjg5S4;%qETL+3VyQRJGu|7M$2V zffIOg+C72Po7^PW3J4B6!w25}ncC>A?EPQ{XAQp=bC$=!a(wRORmKCKqSZdlAQwt{ zbkh{N=>7L7FjN%hGDhv)_fnuzC4AWE^3ALA?ts76GljaNeEe1HoR> zpEuEEH_UW@8*Q2eE^a>Pzb$SaAauMv{)0%!uGO(cDB=GoXIeNqe8>hqf`GG{i*iCj zR%Q-^7I4>o&zSXgQzLYLt!7>e*al32jsFCEV(a$>1+=R@wSVaW6BTh#5}Z*LLDhX0 zW|8YGIIVkEAOn3UYJaU;ls7MhS!QOAP0MVWt=V&R?cM5ssqKx`InIerP&Kw)PEv0M z{>e{83mlb;Tq#qa_ia{F26^5q5(2PMlb1qnuyk7VZIB?4p(GGxVzX*=BbXM~QQiV# zU%BUA>=PPMo@NrJibOZ1H*%0qR>h0=JPH~gzF!MXd7Vu2luIY?WtVXQSd=He>sEPk zKxIY7LQV$Xhp`Cq!%#t&-PBh0V_QK!*7Ku6M7HA)!F0R_U__`IUqcgcT=O+&nwRPf zKjv1Z_jG9oJVH-KT=?>>n8`qQ3fDgvG`~UClvSBGNBZ4x*z1Z_dL2`5(NZE0PglE? zDP0@GTf2#xyzLhpK@It@1fQA0?aN|ay$57JCTxnQ^T9BQyWBiRRod5APhjZumeSo% zZ@T)9qkzN7nHc4*SRZM)+GHcVVOwAA;k0C1`b$hd``!*%XUvdnW8|wSxh)DS_mn63 zD-m65(yM2OIwnd-edcdkae7`-PiCrDDC2W_=~5cN*v(eXm|D?Ad6{u+$ySHV(iGaE z7_V*nCOO7E0nU~(gqx(y5j1(7LYzKA(@<3E9=W!LYc@2#SFdTNZ_C-^v+P_%uKMEy zXl`NS2(eBN8Ij&EWc$Ua4Vfih?>chthQOaW4U^!K-myP8#N*qHE8rWkx>@;g(d`VG znqwwKwX!QkG$tTc1UC*pFk8Y?m4=!g)ql}OH0y&H@)BPZnW_zlI?-Kh&ZyRkL9fcg ziqMu~pyHoWjB>$e9wEa#)*PMW;9@$`WyKw~LukqT5=dU5KnGsWFQa5J@R^Qm6ql@_ zdr+LVB5wz^WfSTQxV5Q)Zz-O{r?sEzKO18b)b<{GsTQPxEOUkgIID^33Oq3rvx_v& zvsDAE=t3zctkyj06lreM!IfzAbI8TO=Iuv@ zM4x1g50ZPnHR^WYN{b$XmA4@{_BCD|z2(uZ02)imjPvC4?!i62tL&L(R&p3>i4=sA zAC-$>oa)#TOx3g8>R=*hBMmsEk72MgT>~>+Im$j0VAjjP?TmuuLSB+L=oF#~N-Sf3 z9fAnoQd;wtT;l~1=96Q;I||I(rN7t=bj2#xtlM{%-YaNyB)--51^>TBHS4qF)ZY3t ze{T`}-+1=-ikU#3nF0GVMcH!JR%bJg?6URhm?6MoW@=4TT**t~QaUN+%YL~@wcHfp zUuVx*mFqa8CMLSsp@@i1$cc#9uJwUDD;@kjS>xY|nXZHtg9m^+c@S^MUcek=MGTRY0*#?&S&4Ehme&ddJ2R1HM}mr(|;425`?JT;V59r^rq zX;33kQys$mYciw!^oIB&DSLySi#{-%Obaz26RE?;vcsZ!@~vaI5sxFoc(VUKe(qc> z$!(f`zkxChC6*3z)0;8(&QM>j>N9`3PFgC`G=bl*VU8At`4eB@QV$IR4+F4)L%@1| zQ{B0HFf}rj51F3}uX=wK>~6z((@yr$2KO;Sk>q2~ATE~OCVpFqyMHQeB^QyoYYL-U z@3M^bCb;y6ypFbw-(T_8cNxObZU`mHaZO#=WJOf7TtpjBw{&Ag z{yJuqpoYKjVAr``;LAGeT->#B%20|VXTNE{O}TP%*srh~8!K;K$?q;#r>eDMW=uI6 zjgN@o^5EnL!C^beZAFHR3Cn=rD1AE9scRzALlE(s*CK=$>Y)=6A^>TjsV$5(l%PK< z>Y~u7=ed7xS-ws6adE(miTYktxe0@?N;+r8*jhPn9>z0q}KtQO6Nr(Q~Y+oM~xnJY%m~gti1@G02v^w+lA?Xb;x0=D@fb4%41d?eVYzTTAYjK#B^< zk9Q4(PD=I*!gM`jxTFokK%`am#*wrf!ng3(&#Q1RMl*YH0{b(TB;zar)NmVYg>(CDr!_Bl&mg@6Ms+#_gP)8B4~DpKk;|pVyh%KC$6iy z3%0(03IvmbSdsNlgWmjxu zh>UTImtZLA9zm+p8fTZgW+`~uMIwI+>Fm&9VP**mHnu!OE3q9Z+2JT{IW*I_DFug$ z=;iyDqP=Npe_D@s&fl(O{sn3OT`lt)>OXghTrCC1a&k;DF4{Cev8ZYBn-3mWTZHD& zW;5PHPSi-7Y~6B=#;gwPQe-x7_gui-L0KcwK8P-@xDW-^Jj1DSYV3M(J{4jlh$2GTV!W3xS=Y!=El|T=HE7pkPY$@gn)EU1jdZ~B`V6s*3?ng-cU#1+RD!UA9vvmX#bO+vUfXv^8Kpyvyp` z#;~Qj7%WaZgA`w{J|%3|;W}8%XSNfF&yf+PC-niL+ZyUw(NoL&GEoFYxOG<%{CP9; z(uuCpHH}Ft`390xow?u(CQvMX0zL<0lxn&apcEDOD1n6=8g#Axb3brFo~>PA{o1f&R$DPAM|u+_fGqVo1h|0SQO4IvymXGc(BGti5MO{QwKZq zlTd2G0DA;yS8`pLcy&Hepd!xRDTXWXV4G0(2t$gBAp1Yz1JMw#eAw;R_d*Z}FqJ;3 z0>1839}V^y5A_+}Mk<_Kn%p2ZdvQDJd;$d;sqBCfCBAM{X-p7u@clUa<9q) zhcrSjA?9zS9>!QZ-S|!fV%mMArr`7f{J+UG7Obr|DGIy6 zr?ABR+%0&bd_|h(sW`zGckm4|aB2+G%t@IcvptbWEf`sF*}zlD!&1A_4hPGzWt!f2 z4?h+go!WwC4JO>+x}-@8(`pJOW7} zm-=>As>Xnwop^tj)$Yg+$t}BS;HV#on`?RJ6c=wJ$@miMVLH)u*(W|fd5HL!8y0=BtE@G&7Toh@dD?qrPy}y6A|1mfW*h zS}^}$27!d~9@uXa;KokaEg*4Ufoya~o@-YxaOJ$}=w4m52`w=m z7xKG8?T3*%7V~a%?~$UFfZSUiqR}@`WM-(G!Yi+3{HdOfC@~ASc&atNu0eJdl z%Mt7D`~B!NXLaa{47dpLNfT6|_sp1KzL@gl0q+sV1PC0(R(A5ZL}C1epP+?SOb9F5 zoxx8LooY%BIIU|`;L26#5TP71yWz1ePGhUIQqpZnK2bx9O!8NTO?WX)Pk}r5*xT5Z z<6=4X=aqK$t~HmP(y}+@Pp?D~zaOKjrn9d))5LYYD0Jr7b7iPK)b^+&%eQUmrswmr zF`6|$7iU=}N4*N#w(25nUY+E9)?TYNDdJhP{p$S`%z^7KwQc-_wA)(*h4(#Z?)6`= zek*OFZ=**^011`yw+Z#XOXuGvlxlPZA<4w9PA19j6=RXjN$a*B0WJNv06AQXaRfgy z${2BqEUPTt9)^*64@)zLiU0W%D;g-Tsa!)jtq5_&cH?frvW(15qJ= zAWHM>H$<^rM}Yi+sA?dhJ^~T-6!1?(r7PzJ1VHC>yGmi^1(s^NL!~QlfIh7K!hGiy zQjWzpS2)g++Z#C;pYQ^9+aujyHtt8 zXH&!rUopi-?5K!`8mET>!mx>e2;I2Uiltq9mWymh*_Ya?NIm^w# z2q9oEKfvS7^Nh;!@@nt`&sC(DMT%BIuD5JexPch z9}H&N=Ko?)%+~@6fm?y-7{FgHs9^}BxC6m}h>S>hxTqPf-JIm6UDjbw&ZZgohAEUc zOlACmDSp`9OIC|i1@^MTJ@KHOa6W8Nte_4PwrZ)@G()z_-JYELq<|IbigEOqaZ~cG z<&t!*D-`%%L$*fGVGqIp1H=m7^UDfvYB)jj7++#HTaI&}H4}4*(N#b`oVxO>YT$N{1+j4-rNSG6nVUNN5PsV1U z`RUFDsoz?=ry?mI@)@-*+HD@N1W$&^$xtyBNMPjjf^mk+ipoYp9j$nVe#T)Noh}RGqi~NBpvAI4O%*+!n&UVSQ}WiUDoz+FD=3Fn{Yd^!=$sghKb%H& zJb{>E0Ai|fQ`_Yqm}>K~24d-Hla5GhS~!Opc(~0Qfxt7BTa3nV>f`v?B|rH&&E}{^E6ECeoo;E zxexYyRS7O5vH*x{aktV&g;k{}VZP_Ns$p6;r!+*-EK`qd%$px9h*RNDx(_DYnD$2^ zWdu}h!+MTcsHQhsZ63X#%G;A>{@{I(j`8}R&Qk8{yGSzt8Epb&G}-_AcmHQ@{eSjI zOGOQ-C1p%rLX031TrN_1!LOQb)hOT9DRO6GqYNZAt0AB)GfP=(6Uf3YWJA9Bvx1Nj z?tz{zD%x`4k5>l?9Z{yS=J|AY<&lABzR!e?D-2JG-lkOcr2r=*DW3W2xb4)+v%G9zT8Nlt!=ay1ry!c)!nFpB}V99bU zcU`c7zdY+wFZv2M-P3U)bffVxcfot#s#n-xA7wF6B+ir|snUJCh6i!XXDA%{9?gsn z{iTKcQ(cfe=zKUc`d9rHa^TP4YXZkL8|`Gxg5s5(2Dl*YoR(vJT9yUneW`^dfyXy4 z=s!}N>4^dmpkj>X>7q$v30zUI=7WMAzekz4krz7*-Ut9-nn?K%W)Jn%QEe|wTO^2Q z0DYh8(d#QHgYN5!W}cM!__;wIikx=zYBjYG7eI^DY@f_xbI z6Dc;PPNtWd{OHm9rxwG_t6JoH_hj!QVpAr9lWn(2Zo5nqvwA1WXJ$d#J?be2NdiGy zi~(K*4y2sCP|?>f5uug$RIM*^7gK_}GjcQpg*!8Gqo5jmV~a*=ZW6YeDN3B4;_R)4 z11o@YUZ(UHqL{gMBFD( zbKv{dD5suYaVS!1cKJgmZnVRnIM+UGFGa1kHL4)Z_#~kD(#OD!-X?58G>TytTZ-Ly z-nBY4?^jT7egw5S!B}>k_Or$+M?rO@+i@21S6pl0fi?b9%dL3^yFH<=#=OK5O7jAXbA|vwmFcLOPG=oq}EGw@h_Pt17Vg2L+u!j5b zr5cKyR6c{_KDeWAe7(DgzI?1nn9(2Pb0Uc3xAQzL-i`xxc*a`pt-|vS(%$m!@$7M* z*`?d9*+oYFMx-P(!2T99IT!%97a>e(?HXMX4qLx;D~-sMJ#$uBzG#UiWkd7FS=#EH zSqaNhP5e8p(pTpe+7U$=?QPgNsXKOR)G(T^&T``-V8EIm1c21)dcf=4fx5WoB7qqY zWTWvY%`aJZ1MJJ5eq^8~Wiq|o==F)^U05_BDdta*D9`nNup8CM#Vd+8{M2*HgX_fu zmnyLNtcz(GIAQe?3h(I!yy!+Y4IjMvp_#Tl7*e96#AxKb8^?i_Otuw>L>)IK(idaI zn@xa|B|UXJE%w_d1j-Wp6fGY1rr(%k^gENd-e6lAi}}SLenkHHN=_C&g$pOTCeoVcK@T==V=>^=A-4 zZ&uU^M#i$G6oglu{=93)XUMnHWr|tq6W#W}HR+Ba0<)&pbqjl;V)d&<9n|;0`g1dE#&t}q7)o2hm4;~+>L*vh92}98W)G6g)^+?23YR{E;cr!~ zFo%n%`mgEN<6;A!^(HnQ>DBiotwLU$jUJ_dZmvgI&NjZk~Uv~3W(aTy3fWYOaO z1!*T0JEC)Q8~H80*-#sA=2tYfw$=t^xx;0NN4!H0$;Y2+xt9t4mpJh$D(uqGSqZKw z*<^at_Q9INYAX8E=?qlx_zWhg#E@ZN{9r>2t>cB60UtQhIjYT#eBy_x$7l07Y#Cyg zg`A=2EKRhgxe+o{h|~wNJ}*Jpv^szxQW2>SW|=2`5gMyB5uWA-JOr_>L}ppV&Kg@Z z$|Wz_KB(lH({D&oq;7Gj#FtW$6z!^s5}q~EE#SlA8{Qxpgf&2-{KTq-r^~N+@;L}$ z8shA|yen3Dj(38i#M{yiD(J@D!x@$GjN%$Jxw$7~1v62L6{(#x5fl>UHW9>OCNoh6 zE7&Kj{c1r>8>f}JysEJ-57h$bR#z_CszIi739dm-Bcknb_{Gb-;o&SY6#ZSea-_s& z&ERCfeXy@1&1#-y+Ef*y8-{psa~#VrGO0bCQ?Pbnnvq71CEFfD)k)%@7d!P%%C~-I zIPKxQYL0-E&iJ`(%kJ7vMG9r;rJ@b$;27%J$x5jJ6-?rZICkq!KXS=lPOfAAEXA^s z#~ACeJ!a|GTrtk~&4s?~8?Mh|I|@f5*L44)(wib4xjUY}wZmV5U;j(7?N6HYzf0op z?Qm3K;4R7^NG()N=$N-#l)v@E6Pu^U6Jwcyv6otfYN(KB&ZiA^wzC-!CtsshNX0Q2 zHRR;4#cNa`M$$q@;O`FldvuqA>5yi<`BQmX(J{lSV(k+_T`{wn*7Z#c)0YbvCGfhU zc7i$k6q!tSbG-`_my`H?P~3>Ca=>2(VAn5y-E39SS7mI!WNbtI>vw*8zH{7C^5FwX z`~^s2(*LA}j5>eE4F3UQHnNLlAtvmjk&~7xJa}a>ORNxa)tF>Xh`C$>usXiaDVL%h zdU|glCS#~OVyr)TBGfPUcj(d45T&`(&t?-L2}aG7_Z1Uo=KMXe2({MkjI(Y2Ex!0R zWzXZ(&UuUnU&LAZ2yiF#&YM-j2O98+#kD;1f$KCSODWg7dL^#MAwTv|UH-xWvY1O} zqoMfP{tzczxu#HQYM*BzYvbUdP_pD_JbY@mEr&;+s@X7$mPky-47fLL_~PAKK`P=j z`O7!Z4CwH1>%D2kz4A?s2W{LATka8@;w5Bp%jT-jGShzA!hNt2yP9>GV2fbLd$X1!O*E=J6$QHV0RUdTrIrO+}IEv9s^)QT z=Vnds=1d=4;(nm)Acp7RHMY;yT@-;0KSxS4C+JA#tG(UCyzO4gbQQDQV4`v0uphG= zC9|@49HagTH(NU! zVPGx^%|3ikW=nSn>$gO)(%_F^zwzRzT0pvCFXdc^T>I4_&!4ieyI}-^K9K`qB_Euj ze%+A;v<m(Wd#;(#+V)Z^-Ztbp6Ozwfo3W)p6s<@J$HKR#W)Fu*Ztj^oqpnu?$Bw z!dTKiyQ-G7Aspes9V&yo2q4s{IVCz_sMf&L$Nt^+ZR@*9jQfmo z<0@cG#|yWO$XQ1;y_UPhERov9i4Wkz=A;xZ5FeFIkb&GY5<6uht}Lk0#t{_rtDpU;!*B5UwuZ<=41|xt--plNx4_@w^V#*xBFGO-UPD9=Iet4& zy2J4Rvg8BLCvzySy(0kWdxvLJwhUIg5twv)jDb+kp1 zBRp{_JAt1iECa2FUs#N(mYt?gr7g2pvzV)kuzC746uGtd9HM8YCp)(26Q&%)Nc&Qz z45^{i;Q(S61rg8TOBL0~eLC_0#f^%Kla!c4+;|VcwNPEvh+Jn62MzAb2!~qJ0oQRV z$t0B6W4l>}eB4qD!%riT&(uz-LA3@~&kUGWK^wfMq4=j?G_R*1rs0A?2%6LU2|uFx za`ZH!!araz9F-Ne%s_%mR;?#B0yS)7|Bri07Kq-^^VmBz;F_%oN6;7AI*_qI&MulzHR?43}+kT%9tRJZ^xG# zmaTpKcm7PYLtwx0XYjMtCn&*_(U1~L-wHG7mBypynIHEMrLx^Hbc^K0p{N(4YAquu zhII190v_}hKC_N%&C@p;(>GeN-4uLxidr!`uY5bv@$(Z|;gI5B7^fQ#-*Hzor|XtI z>F$|@f!*XEgj*jz$A8<-2u-<4Hu@$yyRQ#1ac?+w?!57xEoG=nf_A!np!noB{_J9! zgK~{6?!EDcI4%#_ayet529-mLnfBqcIfVi~q;O?-%va0hd|lPW6F!c{b>hpyBA$;h zvFiptjI>7m#xL{eoi93xz--Eke2f1C6T@i)8_^gt+a~W${RP|J)||c2LOLJVV~GE z?-28bH4s2$Zf259vmqrr{MA;x<^<8|A2nxvQSB^VZH=mkkLA?Awj)&R2{%O_g2wU6pQ&W>a41`T_Rv z+*y4fMnSkzlJ4uW0d<8%=g38ZavG*DAMl;pq$1$&)!|eH;>OG}x@uBZjjRP^pw_xjD9y&AqBws0BKq$X1OL5p^ zkg`HC!_5@t@-y%AQ<*Ok?%m=y90g^{~i7L55_nARu;qr zUtjpNx)DSR{dS6n)K6BPAF>YdJ0A-(8ELp$x08wy{Ti0oD@-2F{th#n4kx`})**iZ2tKlC zxm-l^%)Re|7xJaLl>)+7G01nsOn1#q&o3?FbmR?uK@bom+t*R zT&sWRUO(z8pd4CIL02A z_s-MY+{4bp7y;+epa2hFa6^E%#MPJQ8mDFmrK(=lv-)B&Ea}3U8P=JE(vl7LA7?*T z=Zs3&fX{9tt(I4V?-BWCA89KB%_v=wsZhg8iGLuC82}4`Mlf%MKn1UCM}hIII~Zhd zXy(~Awec8Bu%fcUM+$JsLTc-uu&{a8g|*(%1rS7CpM+jU_~OXs&Bf- z<=dlC?#y=UvX@!E85CL$w%)>wKJrD2gbacy$$@xwNTS6rXa!5^@RtF#pRj-`9dIQk zIu_B9*sq5h_>B>Bagd4%LfI*P{32=Y49~CAjb*J!gD-ry!KieS(a53#YTSbogKqOk zoy5&KSa1?=_r+I*-oby!T49!`_K2O~G;~Aq7Uqe`xRQ7*L=Vt(moJ+XtEqs)Df$e; ztMxMb_?>b$cUHkF{&2zX@E#8vE31TdLOtQ8<#|NUp_oIravOQBL_vE=AU=@_ALn)v zpZNGAw6=!MJehpAK|E%40bSDAD~WrjunVz6m| z#=w}->Pe1xJ18kZLN%a4LA%U(3|z|YvpaZy&~I}iKS(md9@hrlL6DM31>M3NS|T7b zH@f^un5#d0gcujR^_0MrN}w01kOby=Uiv{3J@t>5+u$!+UFn&gXbj6w>#z}O`zIR##?y($e7b+D!YZEP1vZG>oDCY({CzN zW!Pp}a2ZNKpBj*?s?JL~jB&=)2#iA<)oG?;Sf(VLe7@$#S-p*%N87KmbRNK@w?5E2 z2%on}aGSc?&M>zgzh3endU~iR6{7k{T!F=A*GJnY(^3?XKdS7>P73@A_fE-gk$vnq z-fR#TcP#t!0o^y>Q!MkSB>B6(_d9+5v+v;;<9g|7(~?~@gc>o=4qaQ-c6C6j{O)^` z(j5*5FkL5-K;M)7-SZvx$ASPTC;YDGR&UUmKXYcS zeie;lP8~lirWn~PZ9cI0aTYN#Co-*Z>}vi!bJeSP;saw13WkdU3kpXB8nn=nm}@ta znm|m(0JJxDc<=UF0p8G|+!GeuCkX5#9lHI4T9A>1;T00!TmzA6MOK8ouz^}5-x3I| zB<5s2mh|%%>}Q)&BCw*?vyFfwqFt$vtN0yyG^!;Uchw5)m?}>;AdY}$wqPw8eK`a& zNTx;y(4(E5Rl?3wW-=#3hNRw3{t^rblR>>`=2>B2BjVFk7j$uulM2Gw8-a3nR{kK6 z1&}~!6mrp7h7n=koc$Ak4^HCXAYnBoC<4e?!*?g)566oO^ZErDAJ9rjqQ9{MXJaOxoDTO#7WlxLg z^&aW+!q)6Zg(dyAdSD9mBD%n|dSH?uf3)V#0KXo+$)B0cF zrAB|WjKBa*@Drc@Mqth(F(6&ih7_i59%Wr~iL70Pq&_xa4$;RuRIQ%q;1pyFZ1z0c z05dlnYnFb{tTf+Kp(zk~GBQ}=`~GFbV3hm-8^X2Rf4>EmNBV6l%E;?7l>cC!YV+U5Kjd9jnO2aawm11miLnwvw8 zWQm6I_VZ}kaK1bD>{Pe|T+ruYfR{wOC4L&~eZfV_iEf~UaSb$$98;+y2D_8Qi3ql? zJ;A`9RsxU9%NEAjM_{p!ZZi^_K#L)g?(x+f(qDU3MG1Q*1N#}UL(VJOG=ia|6!sj- zL~crWp7mab~gge$N$Ac&l1G_AO>uY$w(Kh)t>rz(pVoG=( zupJ0n2N%XaV7q@UCV|)#-J4|vBrj9aOjj{b`J50WPbMc1 z@m+3hPJe1JmZ!T3NkrwEgb-&^<8P4c@EpJ2)a9QH11G8U|0QZo1O|yXVTFurNnltb zy`YWx1*wjNyhYtZDpY_L_!niGvnbmYXqK%b7T0#&k@L+X(;*=_$Mq(|)id&~@f%t< zo7-&d)ug&&_6=vG;f`e}Hb}ic%C1L$3;z(Q)3b6t^FbiCKk7S{?RZJ63FoWijRG&x zmkLhm2ipvV^(MrmdmFqpreU3yo?EjDlTbJ6Gfe%HK&Cn`n>DMUXJ{3ZCl`QK?3FO~ zYgNt~`nf#d&|$)g+NcX#-M31j?+mKXNdiXVo}mC3>v{7^fdJ(mLYjYop^MHfrg-T>#gs* zMBle)r0NFEF~(*5a!I_swKL7Azwo8M29`sun%cjh29_nrm#CpP+OPY|c)M*Fo4uW%9rJy|hLf-wGNK zt`JHa(}h>aOUG0lvXyJ@hY2M1WILnfIeTqKsh4EMriUwT1Xf*SesQC6kK%slpFhKv zV9#H8SB>Fy@3Dm<8ebE+V~K#wQsuH2HOaeM5h~IB^=atGD8ko1tPv2tJ7oZE=;UxM zfK6Cc=(}>gI5E)o0HIbu-&20FU8o63eTJirTW9hvGtMQ_rt65o(V@#EeX`ZOeSpQD za8@3QMiH)D$+20{vjlclhIDyWROf8w%c0MW!IyW})%+5$$JFo*`yGqb^GMC|;(mf2 zNl<9L<)#rGG@DoE)42m**V}O=XG%|Br?!fFFAUd)Zu$4GwUlz@VJRmNWFt0377d$o z3iK>=(gnr!HsRWS^SzDZO^y+_^-qs~3Z;1Sy&f3)%D-LT`<*`j+4nS5FnQm)y#H5y zFNS8|bE?2>E&=Rcn+p?54!{wrmna5Rfu_yK3Ws5zKf1jB5=hauTXV4s*oTnMa`U4t zM^EIxU3*QrY##HVJ!|M2GDsii1n|a#WP~dK$4+EJ2thG!(3Q_Dae` zcr>X7yo(6jR8O%H@D940i0NlR^;ecLQkOgGH}fwGzz|#booV2*t;pXo6*=%68}_Vr zWS=slHdSMO?y`An^2(Ib#{_Dj9`}Hx;VY{Gi+irlPPgULw4|q}(M||^r;Wm3j}2ww z7cr=$wnDMp#3cpIL3sQ`!=Xvh-eTx-t_Kbl>j1q)hZeCVQSnlRN{n~(o9GZdg)^dc z{W%W`>JYLa*A=iwMR1eYJENdJ~$by=yx_% zh86IK1Oij2@Ud=H@%4^B!r)8l^b?K0=^iu17|z&B%yVq$IlVGuHr+c;m!B}%Auw}a zdAgQ&a5T%XMKqT6UHUNf=TaM8`aG&=ZmHBWgN;F|)=?=fc z0RqVOHvri(N#7F|m?k{G0qCkb0^f33Cb?eqsDl@ zhj&v2Z66c+X!{xZF6fLo`MU9Ql^~xGH9)GVgQ=Fd7g1%A=+r030-%a!0F;d(c(@uN zp@u4CjyHTZh5l)vdOTF<7iLg#%iXR})<_szNh-$U-hESM@hRjnCn7(N-s!(hoS@&> zcm3Qbw?addxi(1_&Uerravpu67p&EYLk9XDjT0JhWAwBWTi2Z+WKS!O$K|vt0odF% z^q|{{Ov2Y<4WoP1ZblF&J1wRRu#k=L^0viglc(*1P(!nPe1MfkMz+4o<-TrML@>q} zD_8}CT>Q6HlDIS>*XX~idv65#PrAnd14@Vsan8|kb{?bwjh&mxg6n(ki@n%=bw+CJ z>b#5WaocHC7{7YA)iTF!KJI(NKKK%o1LM*|ZW@@=SnTUK)?)yP`$=Hbur-@)XUOGAJ6H62MpI@-utrEUL-`eu7EodO^wkPvUS2Wa}yNn{25W-2MJ ztC$LCd+?GcvTwGxXLB0yPunB^&GvSIwr7E`PRKtA`$+nm?GgTFdsw84yn|+Vl`V+v zomS$qu7>XRRY2RzeY3qN!9WRx>?mrFJwGV4NA)9G7Rl>lk?SY;aB4Yu6!SuH*R^M( z%*q~ICbi0nqginTj&w33n7&@_Z3TZ1p;f_~cjD1xWRuqYQ(LieJpAg4uC_L|9V?T z5#Q$COL-ZKj0%m5k*sz|B~za27V6+6AW@mxriO+ViY9&+1_lB)G_ksVkl6rWNTyw~ zV-yva-X%YBk9S6rvJlvQMFX1?9!dASQ}-Xjsvk%J#n4~_v{HBWz&8857paf(8Oquv z9Ou)u=L=~>l1MkQCk|V*-DS(Qqdyg+#LHGQ4lEt&D+W#+^6t5RaKVSg%|}2qIJSf9 zO;xbKTa?s45S+3T4XlaWwTRqQ8nYec&-Iwr#{gFM?h=^daJD0+-l}__`81Jpf6#zf z1($o1Vb${!`Wp2hz*xEC^uT)NZa>`Jyu8B*Jtu9SW0Xg-Mg`9Om7z@_dy?k4*}eO0 z!d<)*d;vOPq+D-R^>zSkr~H(*#E#rR735BmczN^9_Hc*P)AK@DMQElrl@ugY(i}+R zXmgMReyi^Nm?H43b))#ovb7XGGCiir6i##RIOeyW+*Bm++h|_~Y7YUh`(`K%VflEd zIkkc{WcBIV4dNMHKjs(usOhL5*a^X3ADh+?o{KEWolmH?$#4-zhJ4wiT&d6rzUaY92#2dh;A|?J*f0 zz*&;W#rd^*JjueZPiSzTu<*^-Mv4w*J$u-OTQCEAROOlD+2FftDrQA^)ZjSLpjbz# zTGx4$4l@t4U<>Xlk}-aUj>iXkvcqEEoAd7ZpIY%YL-j=V3f(wZ=?Z@>aqwBbW;jsT7;@&E%?lkG!h9DsjAh<(t z3GNmkxO;F21b250?gV#tch{f^?(XjH`u<6Jrh9tkndv$BzFBMUwQ{--xN_C6s_ycL zv*V)~xh&6{l&L}kq1}!G&nDl~O3>}P9RqYv zPv$en^?9YeS1{3U3tRb++36Czc|wNY6RFjcpXX`i&9Ehuhgc~r7>@j;>Vuqlm=m+$wl4}7WS8`joc7RJqaI<)h4~` zFv6E7BD3|%4DA#Wxo(kjFEeZE=9v>}a_bsQs*GYP z^%yRlBep&)0qI`4zia5XJlDX&j-^qh+qUERnAM_8jJ^(oiOOJCX)_#KWoxVc@`t|o z-q)u>7!#n}ojGV!8(Gm*2&U`OxHJ_8UftjmfoL1aoy?)itDk>NoE$vBt5K%KdMJsB z2sA11K#-Ozw5fJ>`EL$jFfN}|C6M-<=_JZ**8Nca9AB5{x1e5TO_rt#+9~#ac6G!s zIT2GVF_q*8vx0J#Kw-{$DCL%a->-J=PE(;QDfgqxRpfMbls*f+9Jh5BZO!`3dzgFk z!$N2u6CS|!WU)W#;rPN-KzE;B#OKU0FB+glv{@$c$*ZcX55<(upnu;+_WMLilL|&jMvs?lT0Jqq7<`pd#4e;hO`N)~{ zw%2^$!UHy+pJAU+=W`(*P6sG$!fbkR!HODG07cXNA*2MSPGkH(GFUO+1wmFCJAfpk9~Tkt;g@Dsu0HH zh7Xh7=FyHOK_agQ<;k@0zsGu3C7w0(FV5YRN-OywaA3RBkrx_(tHMCf$e5sBWXmM^ zuDR_De(u4MY8;7{6fw-+D;{ih>0czNOx8cN>QCvPkDhi1X?&jwmF6ETc;CV#(Nmfq zS}!1ZGA0M=^!3(f26ZNvOHY4F8g)jf(bqM4;X=#)lC5XIAFL0&hp2vbZy-KWtMS?= zO`0Or(S)Nhej}H^c&gCB`89XQjF!0I3dnAzRuSyQ4`EzhEqAWe-KKCW3e2sr($B+H zEbyic-V>f>Uy((XSKMYAG&X}ii1r-j_k;HA-^Fbu_A^8~dNV{=c=yZ2&sdS!WiQEU zGiJAv7wzC}#;@E=kr!=?K-axviSMNzV?`55D+{*hsJ{Jlv`)z`#Wtw!Bf}A_v|N|e z4vtZqiBrRF^N1GNEVF=yu@HN%W3G4V!u8M@D5na4dIe)!$6iRS^`0h5jkim0flSHV zXlk3#JEUOYTO%^Ef+h7gsVw6&tSD&;rP#>Hi(u&=r(L}20ql2ibxo^KEY+=JXc>Md zo%%9L-o*|iUV@plypcbok-LSx$;3Mx;I!w#E)+4%aYzh4gyW+h5Cn9t%Y#3Gsb{Um zZ9cW)NjNkKlU`@ja~tF&8A>HqupUUZDItgU`v#-5J%-eBep6#?@bU4ysHNoI9{y;U zZ+~c*BoJn;vet=-??SS3oOjjyv@=D+EmyMMOry_JSvBn|sxGly6cbx_is0 zVS{+GomP#dw3Wii%ZrEDn9aEo^)l(9CiRAt?3b}I-@^C)P+>o3eEM&`Z_xq>viJ)K z`uDb{F8@gw2=}kENy_fJv0J#JAGxvk1)5LK0K+rkDkj!>vwNsEUQqO zR#o5e2bJdUc^jFlwR~lqm?M-ZlU}~vs&+Kgg%|TQdk4Zkj}`5HGWIpI{Gk{M zzxOMX{n_>Q7+t7mRTAG@*8F^|NqyV|4Ha(3r4Q59o6Bd7ax;$pk#xh}s^QAr^O~j! zTB|z2+oR7ai2R5y#Cn7%@H>>En(^|4$Y2IT)Y-W%x^-I~N@$;<_*cvK?3#sRZydO0 zuozs@F{no(n`hVK)i%Rn{b~?ak2Z}h?I!2j1trNEd@2@d;%n8XO2>qt5>e*6a*+`y zEhy8avfjZYMoIV2Dah8qN|5Q_@V3+lGjS5BYFK&i-7f7^mh-tIR+164D{y9}kDv#S z>d<3*S+3#-4%5PCt8a`y>7)FsN)tQz1cwI zHb_^)Fi)&tJP>Jjcnx4kLKnbL80U{921oC%rh{h;G0Ge4*dK1IL6jP+Y(2+(G#D12 z4&0x{N;O<^)cS8U`aSdvQz71ZPbpcw+{q`$sef1gaATBv^TKvCWG3gskB{Ztd3)Tg zO~ZB@MbS>Xd-Ug&OB}5)LOK7u-|I=gJNCT1feY;SV*gte`uEBwHz+P9A|WR{C_)uF zG)NXW)c=l-VP!*>noLxDNJ9P?-r~agQpO?#%JKr{^8AWVE>AQ2YeH;XR3!9xctUJM ze0N`TvPx8JLZ);~YJA4m$kbTePtsA!F-j4bpOTW|B9)L+GeA*5`Y3qV-r5Di(Zs&s zYRd!1_OCL6vLiCPjI8hOWVQ$ERc-AWlkS?1 z*tQ%~&sw&yL!~J1jTk_Nb6$AhR(n!_w9(yn=sf5zX5@VAVP-Ea9Q7SjDTtX;gCTuA z@UdmDsx;A*k&Vo{u%&!w+_BlD@KfDa+VR=XxtitQea~i^%9OqV`x>u3Fjd(fUb~kf zlkK~IhDd{)>y8xYoplvBt2d4{{f#>c+Mt*2Qk)lr9 zi3=ybdPH{ZsYMMN3kj5!;HrD#mO^*Ao(7eUP&`=VPB8_u3D0c{x>)pkh31gi-)2>pE+k zi8@5uqD(F>-hRMevLjK^97?fKzf}lJL65_uhQem1_g*3WN+$=Ar%KBL9gdBt$41n7 zkRgO`GZ{t%CbR)#{3`G8-hDib^2}R6b*v4Wxtdsl`{M)Y0R&cU{2DdsjXFvzGNw6N z0>|LkCwRs-2mU~aY-;Fk99c#FKo_zub}^qQXNnDx!uLo_Y$$VSl9Gg~6+E>xr4YYx%Sb_=s!vxeNc$x% z7IBpZkL%bFOgRHup{K+hlw!H5kSZ|_NmQ}HJC9q>+Z|}v%#2pz;id9htQW3yT1`h3 z{)6$3P48{{jFPgPNp|9e>tnlWEmIzM&4Ua5yc?lQ0tQ!`oCEjQ`Hwe-;f=2Nd!uC< z^_o(2N62$`NyhaRg}*Oh*S4~ozgC1hbNsB&3_k8B1imQ)VOptU(d=m_;%nd~;0y|R z=RPf^ue!)VIUH)IAT2=RvmayQ;36f+LCo9d<$joiFvlS8sY+)3o+Mgd%_eJ$p#?k` zzT@#no)!{qtM&yryY}&kb!Ch*TS-sJM}sT}DVcMfaoi$=F7q%{RrU3dnyb{7$U`#5 z_wTjNYHc~)AbA}^Nz8)gaXzm zX07A_Qtll{D?+eNtZS2mr_a9~QUEjsOe|v-%vVbQ1 z!ms@2(Y<#oZ{$0*UuC#>EPNmV>Qp6EBm`mULAYvV{u+zNumowyUtbpCTF7M-!GL`dz~kuV(w-1xUg?ovVE z=w7CB;H1cjWxlpNW`?GFBQ3*G0z$GcOQ{6Z6#L&H(`)ksfJ_bm8El@aboV!Ktp5xd z`}{vah6sSn{cn&dA^HUwQxwcO05TU7-+n>{?in&d0A${F%?8~>InzHwM*AmZ#C}1B z(&=}|L~MKraE=r5`5iJHOY&5IgA768R>3o5fcNpAAtO+gBJ}v>|bzwXAntdN*r8{1NQL3+O)0>|_cQJ#4c*@dqP?|*V+vj(~S;>kZlrtcSIKKurmqhFATxk}LxuHC>&Nh!NgoyFw_!{-!=v=_|8 zlv(S8D_@eg!J;V$U9xi-y=Ap+F9ruMSz=jYgMn*l{e#6kkK*}b+_nY-#1}RpuLv~tqB1aFY~&c6T78^4wF3RaZ+r$R zimxK(Js1cGCje5s|NA%owZ&TZpLa}eMw*PNUF~NGaxM{R_DC+^@$KFQh^$9c+4@M& znF=GM$D#)T7nU0yg?+*ql}iVqw)XKp@*~cQ-0Rzfet3$Dqt5P>5sV`c&>@;sAgzY2 ze)mWhceJo?1U!wk<$BaSbalqHbcH*#MKfQG0Roi=l1A!~1_^@w4NsieeVxjX!`7tm zEP}$6RYr(Or5ev0(bul}2=M@>vY6zh?%{ZC4Gwp9tm%MQE|RaH>OL!F^t3crB3g{G z5~584=N57ryCa z%1X64>1;w?yq*9g_COEPD4VhqIlPeb%68nj#=7*pMfOWr5WRUgZDrO@KEx>7D<#&H zw?`hq-4$P(M7M-d1qE0`!S3()1EGd=SNuVGETtz+v2lT`$_>C(q)4 zm)~B!B3BMy{hO!tu)h82X$`O9)980-nV&sP3-B~)z|$@>K)S&RgxwBIYc!%OZa9l4 z!kfzn(J@0n+2o$)3;R@_;E2Z)zq@sxxVd?%a_5@GLsjdz47uN0Ykz0dVx*C5GOpjK zevDdED3n?{S25QXw<0dRa2Zx9x9npx8&#XqHfmLI;0yd=Q3VltZ;MYL#)m#2TO|-U zBg4qc5X*FOn_}o*CDUFvXEMa#;X69EEsuWb zb#u2Z;l?dx*Gg1hM$0GLhbOrft@u02*`$}7U-RD?-YPuc4FQTs*pn=!VlO|b`Yj(f z{b8T{_G|?eJxrKRW;auF9{)lh>pO>RQLUPA{g!M>RX0PkIS+L~`UP5|?pXIj%$l2& z$|1FinX?SJFhss?5eyRm}muT6+wRse(~cq$35dFLJDZZjEtU6h=KI4>K$$CA$}=O)w;cS5Y`@)~Y{9~R5w z2F#drSj20{38~a3bgy=boKdzRcl}C-@!8MpC2`DbS7Fr6-#bvb)(l@RldGn^yO##@ zbO)coT7l!yn9Xiy-7pnGtHpdN9uIW4h z{*#>jN2ncgawr&);EWhAqQ(M_N>BeO|ubahzl0v8F+eXb- zH*Skt&POLMkL{+3pdPXEAj6TI(qJH=%kU%#OII;f$?P=~jv~?YNqL!=#k2N&mVAw~ z_5qg{{{)pa04nD{p+X&r6jS(js4VmhMLt92_-|0TqcPwv8_14$96AeuCwN9*K5KgxNu^S;}I!;;!s>1W> z5a{Rn?`7-I==I*6BSt{=>WqUgz&5WThjsa&9x5lX=(_^ZRcEa4u zUdNM!YW4! z=i4BHdk~COWuJVK*)mb*jG$u6fVxi?heY0?Y9hp!|A99;rEs?t>Kv`eO)_n$Gi0eA z+D*S@TS=I?*r1Hho@*suq(Sk1NIUY&tyD-Y9MlxD+8KwKz!m4?K^MkJ!15I4mH24% zWZkL8P~Z|dX`&t@O;JSDOKkfzF8$XZ;qT|G0Vl(3CwyU@8~D@71R6W>XEjGOSiIJ_ z4@l{8N^y_@Co9aO0GzDvmy^+_Z{Q{|5po%m=CjtyuRw}Z3{@?KQ{=c>qGS1WR3dbc zXg;>hTH1^*S8DXQv-iPH?;&H7FUXxbk7B}4`Y$`@!qu{$#FtDRH7BvF8Z=(TQ4LSH ze*(Y~N^%8&CHp5>v?okCi`ktfPBgwcW*2p8B-Q7r@jr38gZ>X=5`t4`X7Y%)k52l9j_wTbE`wLjTdraXzo-G8>R z=e3Xj9Gm?!I3sN%ul+3kY-2ycdCPzzII7dkPMB2bE{`B$5Pdzg9rfX9npRyjATyX& zz&AKtMKyVxd7S#XN3+GgvM?FfJ{905*V53P%aSvvdz!_R8OYnb7al29piCgkP>-4w zH-w)==F+uQ)zCf~b_B2&j1)Y)O`@&Je?T*I$D8|XCA$gdDzMi=;=Tpe19H9w`<+Zp%h_z$!I|Ofy`3ZzcEqIK z;hmPZKW!{#=y=zEbaU;Mp;C-SZ$~*UD>HR78XGc;+O8m&NBpuDC5)fR zS8&~h_o$LY-#Ol9o=_5%jN1ndOf5{Mfb%rz#$y%*VzyJL@ z_33=8yUcLZKqJ9r%Bn-ZIdaXc^u6nXescibk7$=kYkcFb!Q%Bga%=V4`~#~MSaOmM zx|i4wdoKJjzO)J1d3=FGqRnHY;1EL2-d!2abj$Qj4qB3R!?owIvt@L1>IQ|Pr89BA zLG#T|XiEN=Abd=-{3KD&{mzPY14d@4wBhuLe5s<}71fjq#Cm!>p3yb;F>Fhh0|?Cq ziHjR4_CkhjYKQGEksogS!MX`$#iN|a(d|W>5y($Nk@v{aWK)2{=*1_4`&eItj0_&S z%w{UATQ};KB4ZlGViNJ?p=I!me5Mk@;@y(&3$%z0Z$#!(*{67N2ASqnDvC;!XOlTR zX7bW5USO(CmwM_C=5^@rX z@h~pmRug6_HY(#A`aH@Jd0GUi(M{rY@d;>MzA2$_;8>2C$uwY~K^_?;ge_IZ1*ByFG`HemL19;Mztk%V%u(*Bm1d}~zA-H`C=L2{ zl6oIta+mlL;?y8FxPYEqr#7SG!I^$G|BcGyh%&=!rCo%mMW3-+tH?$&9P3zDFgNJh znuP(g(KL8Jo)X6wNzD7nJ%?;-HSSNj!@@g@vTcbY4&{Q#OKi4v69F_fEf>qx=QF@% zs6}?$YHtG-}D^lhMiRHZtHIO$!uN(BHmeS;%p$^Zrx!0&dlcu zkIO#A^DoHQFQ)wWG6pc^_BW=SX4?AvQO0I-B)tDv;i+VM21_E`_H^2i6Nl3GB4f}C z8vT;7)n76e^k*4cHEsMQV{6R6Rd_6|M^wffHb8}!L1Fx>!aMSn^JT6+A~@L7R+WJ3 zoliH1#Re+81E9i_^A&UkD!ka4V>LHPrIODg!&;C$UaIWQc-&H`PW#XY@I z#Yat-V0R{{9ZofG6GOpCt!!#&zFQ4w3MXz^H(iFvrv)UKDd@C~&>)fO~3*mMPrU-D-`VxXoUTz51`!pSNOQ z=Dq7n=Em*nuYpQ#>|^j6wRaz6V&{BYuXm$_-xLdc#I|QFs6El;c{IlcJDrZdUEfrrL>L}P(1^} zc-tI_rTnKg#~*{HsCCwcdnLV2RE#rJRmtxK-04SOAR&;Gh&CgOvt}*&BRk3kUKF7+ z9L@xj7M_UXpnnznJ6BNZmd0Y{f@1dY<>3IX#Q)?9_EVD-AC#It=8%5aYKyHGIqr~%Mfi@ zdY#$>a3vMP92>EO%wg<^GIqZ5x;8ealazPKU|tSGQF2Y?*h%4Dl5LDJ+fgezi*vco z>%zL*0yrS4o-*@h_$@9%9LLA1frxJx6tl!|BalIt4d~cUKT^Nfw%RGZ4YN~_`3R)& z3cpf#6y8KS>5-7B7Zi_U5GARl zat2v8QZq+C3^|nu1CNr~=XX2x**~>jSzVgYSsc+hmswx8KzbizOB|vV8}WLp2b)pJe=Lb{tlLB8MA!isQL>s_6(N)xr|{yhhu<@z56d@ ztk*Qx`!C4YUt3E3C1XFb9jDYz4=V)34~R+jNKT%kv7LzT#D;s&={0j-33zGBQ4v%k zY#zd)2@NYWk`V@HxC{J=sziZkEO3~cBuDI(WfVfr_cs{8R;h?7-+`z5>rH2t#@QXq zE5{{g;2LJr&{cEK*-L2qeJ2p0dl^TL^;;FIx_A}Mq^?p@eNaJB%ss-xqRe#Ui*yTD z{Y1Zpx2z&TJv*OmY|8DXLOQ3aFi3PRaXD?NL~Xs|!b}ro1XQu{plKF;S$NA^J1;`k z>`g$>E#{nx#OEM^dD$|WEV`mxYoLm?VDHF!>50AcLXc5eUvRi7+`v3%O9dIjf)P(j zcuRN3hZFnAYYl01E}XA?MU)2f#eNo2cZEeKq=@v$;>NO$XA>WN!gtg;Z8G4tgVW+iE5HE!p2H_37xOv)}&YwrA%>|q!=jO2~{IBdbs5|;H6*RKZk3!BNV zWWvu9HZXaq{{$`KX9;VNqqxm#pKzly4!ZVC%?HNd#;nI*)cgodKE&IbnA22w2f3bs zsp4L)TC;y|&h~hfwJ}(+p@$gFXX8)J#4wkLZq|ORdHB$)GT5|z41uEi7mFdN}jFh{m#{Di5_5zwM%Qj~(teLg$ z2i2jfs8G~{@;5(1bDUEWH&>Dm87(6-W0>6cJM4K_NPL_7Qe!nz=@Hw^`i=|bHsQ2C zXC9-sdHt*ea&}$*jPl~MPZsC8gJ+1Nb{!Cnr9>{g8Kyl%m~LdM8VDb}!2AhKze^`2 z?57>h@B^2FG#=8~{Iut2tk}r%DJ9sh0EosMenAuIz890*K-N+JMTrgFnpE30ICgx{ zE(_=#0L`>Wr`8L0jU8<6Z4+q#n&xcF1JW8lqcJeE>Q(E7(j|8`*OFnkr&rEp91k8Z z@HxA`HVR}WtWM0t&qU zkc|DcRa32>ar;lE-2R;@7hZ2TzS{hX+m*(C#_hk7u^frN$L)R;1h0w_KM2<112O2| zWQ>5Yx`sW#G*A7wdT#cx=780}8y-Qj4CPm&>{+ApPDbd7vPE$1fuX z@Ek-FsHvuA?PQ`S@qmd~s)Q@vSFV1u&fzDQ*2RJ^O?OADYw+IZM?S~xh_^s8Mn)N3 z_cLyPPR8Ov{>YT#pUIeTK+R?9l#4;4n6{GCmd+afla8;*)g4<4#%tq>%iuIehLJ`7 zA;x#~%g3=N-Zl!pgC@HGRt|hJwMRL$c24S6WZ^Nv_v@gB^t8mElQDoR4xZ1+SRcR@ zuX4&@e+%rFb;f=pl-M=xmOwK0!Dqm$GV!Ip@yl!@1^PRGHIBIFBJW||UF1h#RI~*Y z#p(#SjGMO?0akc`9wQG>xgYE4bdqS}P)Qe=myVU( zdQWPnQko9S=R4!p#c=!T)3Qz0Vy*A9@=JQAE$fdHkfWb%?7^0cQmg}ALN@Dfkvpt* zb35-y{j%{Gx4V`?-EgY|imB2}F-U=YJkz^7AiWS z+fAMt&;UB2_>_7I+q1YPt&1DS+kKdIqI%)ZNi%ajfbC9gI3uHM2A=EW9m+r&FD0a+ z$w?_7kRRr2={JrR({3&@vN*xp%M@#sOMZ2p0$QKv8}rFzGce?ds^=+%aY>nRNjyXL zE8J+GUC56AiC+K>W=!NJURQIrHLT8#T1TmGYSB%kQ<*|1Ce{* zPp-VaF2c!0x*x^l)|9W$bqNKyBGGn@j-3*){To--oJu#?AII3-+BBZ4yu*m0T@>2%qzP9@?m7fU4jFI-HlVfx))aIwF*GWt6= zoqo0{t^Vd>`My`y0HM;D6(k}>3TcX9Dp*;O(^@o;>4S>wXUS=|4lO-X}J zv0#}13bhB4MuN=)55nrn6=(MNR+`QRb0%g|tfAmN-sELhzz?6<1n{3U!hv8)&si1m zvfompbJ+~)A{6Pu1YQU`&l(3PGtm_`Ed6-8P7HaKB9=u^2_-@sM;hf?CGaJybQmB5_vpvv~H zmM)qd+n1FS66OWt1ztBFv+Ym>4|2%IfHvg?&nN!-lw)8qoEzUE%1W8>V(+(Z0U#lK_I=O%x+LTc4a6KyD|5BbR$@}Z z3E6Iz*c1I%Pvh4hZZl*GG%Zz8X6hXy_rc$StT8S z_S?*Ymuw?7{oU6lXIgtjBFIZ18q405r3Rw0AX43o`!~+S%;|^&Ivn^&<7hZ-khmYj zv6i7s@ocN>%xFM0Wr;kq_6+UpG0z|D=}0t5?g+(Ij7<@k6d!=?)0|^wDuuZpDLK#4 z*c`3733>?AI`4BdX4=nXWZfUuveAT#>_%~1tAN{zifpDSezuWjK}{h)fB*Rlp0&K~ zv}y_Rr;ia7*hU^+?#W?=qTGUh5eCw-k)l&|^t>J4BrQwU6Jc1CQ=4gtHMUcp5R2=l z2kffS>E2OaDuw_?Rg6Oy^G%C&-RDtq$GO*@Y3(i!(W005$Ef!8E-?SFGTn$h8wU{@ z*Gy&lGO%K3#J-6D&sVwZG~O_M0=||@Okzov#Qo6 z-Ir25ub%BlO~tatsTQPB;X|RoI7_3VkKcRKs04eU$Q$!wrqB~tvP=)L8z)uPW6~3? zR6~uYVeO0ho)lxcbQ8FeQy*c^ELY2~<@Z=`qe-y#37R`hLa>0ldSRYaZQ?|sE?@0b zYHdj);cJS&o5T$%eGB$RA`E0qyM$4WnWvK$F#oW8O*p|&6IXMzRpO_PB!h>GFvEd4 zyZ(K-z_%uVuc|ve*$%bG-6?cK_0t^9uvbk?cuoXw%{x8LmduP|==1?jR%2$D$iB|<(uVoU zw z?9TWEw|^0gwP(qQ{RJ8O&)c2J7`#;KD<@D1|G&_4hn8u9S|ilJhBi042Zqg2KniQq{r zGZloQfE%yJrPwkEdY_=mxL^D&p3T^dh|K?hY!F$#hR;y%uxeX=ul}wC9*`%#Gzq9EJ5O7tVq6X6l{i1>(GrefRQd^cjT(AXC+fkb;$mWhex~O8OUyO* zPN#%@o2N00m`^-=ty&RSzPgE0j*o70Si^2BYTsKGEy zk=Dcn#X?G{Z;ofdmZBj=`rAa%B=6aZF^J&EBJzT=&U6f7bd-{y9AgxnV;|l#AMHo! zGf%lchV)Qe*(A~P@`H3w^W=E)YdfIAx0GG3;2padY@aD>9u@7Z*JwUYw6b)TNeGYU zd5Z?6(wbzkQYH9Vi@tN!h6Q8P|B^1iXPg+ywz@~j^t#uvba%Q)G}`})qV;GK&j=g5 zOl~#B#2TJ6$$fGQc+ZH}?#9KUf8fAWDKrwZkQ8F09&aIeWGEOjUoEq$lPl8v;O##&2K; zt+V&9EoCrmStbqTXy)mzKHj@pZ*mR$wjh$k7{B7Lf{{qRs??|f41Fyp= zBDc_G+Rt~!kN7T>C+p}JP?2AMZKx_#(mEZRROgMiONVWVQwnc^isV02Btt@Kj`!@6X_ayesO@*h6f z*6I?|ZvaaM(-+TP+jRDARu8aU6%|0&prkG^e)%?lIsi&pt7_xPXUio3;!X|&pB2%z zRY_|joP3jEqmZ-B{03rd1T`t8dPB(5bNb7wxQsSOH0q{8;fLy!I}+2cmPl79)}=J7 zI#8r?>)OejrnN42)GWT&;^<*$mb_i#(*_MR%fTO(=pw~X=v?H370m0V%{e(#HEi56Y=(glu4IsH>G{UwJy z%dpz|1w?zkW!$}a*yty$lSVPYI3im_c*ELaSMJT*l2YiKHyk*6LR8!qjr6Uhmd-D0 z3i_8g%5W0yzd+92a6_1xzY2(a5sQ*gYKxKzJNK@bUu|!~y7k>wEn1dg{44O&FKGus zuUI7ah)_xRC?&7H;wNw8g)0fGdP*xg4@~&dsM{9|4iv}-IFugW;XbwuegNShJ{)1T zm)f{z;JT`kMXc!4_tM5SGtb;%%`bP79ZtQ|It|{O7-&Xfd8Jp zKdqH=GJ_PO2KUtDadUeDc>jJ^ltcGe?k5gzrpIv%M%6PQB%V)FwB* z=S4V!hz`2xaP%znJWvJvM8b(AFtz3-&Ix{asJ|_B_|%xlCPJG)@ap=LpP`tV_=mN~ z6J*I3RCCu^ODgG0)MdUll@uZDln)G#DfhcYLv1_Ap=cSGn5$23>iE1GHLvOwdIwWc zvt*>SlVhA$VyatLk5a2Iy#$dDaUi>MLQ3qp?)7nP^ZhvM$X=W=JGIir7`|gxs0R zn?a!UII2rIC>Aqr$2yG{?-Smil@w5e;@Me^i~$ze{{x*&q=_*WG2QDA-2H-DSV)(Kdj)E;iO=TmRM0S3WbmwryrE<6u{T^Ei) z@#I2-IE{jigLr6Pd*yEq%@xj4zn|N!FX=^>+RYPeyi}2=wJUg-GIZyjGqRMMq~nJhO3z&0UH@j_tk+(&jxkx%RPl#9iRd z$C}Ga>wRP_Wsj$vGW!^wPQ4y&(Lj9#&sF;H2>$>x&?d;{m3>1avN{LBIte^1)+P1X zwtPnrXc6>#!;n~6OoNI%zn#(k>PwRsBIeMCQ;HuW*uj3!!?RaD5wuNFUYVRpZQlaj zD&1^=PpgK}(g#8KA9okkcbs$<^1$|FmN46M>oMhx|0zD4Z+sm;BN9F^uptf%Y}~`p znR*jf5z3E$4s2%ic$ESbQBv43Qz*;4^uhQ-$9%uCThLm%m$}KUCIfa~*2T+bUmx*k zE4B{SVmIc8f!O3zw_+GpW{gN>HRDbBfkxwl3~(y2*{XKI4Np6;ux5@%Xx~_}Bw{P4 zr~y}OYhcy+Gq0yMmBsncJ30~UZUdAxs?Sym`-!NeWURA&G%<6iV7P0lid)x(57~Ib zzFsqM=~VG0Y;j9EPEw!O-(-Yju37X`HK2_)RJK5<$zD=so7C+lmTB?W?mZPAmi03{ z4}uwwk0w{#XFY};0C`vZ7Ip4^BgI|wcN_R6#}({{3t<@X?oNKC{Y=eKs>`mHWwPZF zh@LiVG1|y*`xkvQYYm*kX`$)k8W_{!9lG>Q9#wosWM<0m=Se1Y-^P|Iec4jDXyWi{ zP{2~U=pT_J`Y?}NW*g&92eO*`zSx`P&UwNvCE#Hrn7ymRJeKcUbo}f_a&NRQ6k<=Z z5HnFlRdW{uhD*M{n90`6EBd(N-~|g|Ezfm&*574vYyhS2uo(a>Fh!`vj!;|rGb>f0 zeYUvw+tWGhzY~J7Nl!*064SwNG)0nyismAUjsBl;a>7pD0Z`^r;li5|Q;Z}L))v93! z*+|3b8hVG2Wd8Qb|9MXKrHbEL5byRZ-(K<9a$js>wPj?$eX2c2t0Tp!mURo5KY)N?ijz@HxqXp@`nxApj-ShBhlXKV> zJhHnjI_NgA5h*qO1rx;LwL9&^xudbbT)w{Q{FFS#nh4H>=9oqZbhlmg6XwB@wrW3h z@2H`HA&2GUTegIlMU-IJ(9Ty%`DG)#C2g_5kt%j75CaP_{gkz>Y671%sRNMlwVDkF zpNcE>Nw<}_K24>eb>g$~Wu2J8a|q>_9Idn;nrHI<5>iK6|(WxF?wAXuDj#8wYcXU zfQ?OcW9_7RolVqj%yd!6`02>1@+FXw4!L=#_k)ANA&mg130v-$|Si z4~0PgL3dQkWEtYuG7qqHO%6PYOX5Hv+%U*26ec?3&QT2ERKZC>>$_jv$Q-a(AL;|R(QbgSHt^X>a6cKbhn#h^gC>d-2DJ91_+90FbW0b& zjpSe4n2rBCHwb|_FXD#Hu?B_~M>Sb1n(U%yZlr(uof`vSV&n7C^iMyz@$#7)*(Qw? zbIsr7S(e-$DIYE@7=CdhTXU57vim1DNbP7#X?(Ps?O>0F2FJM z8P=Spr5UTNSb>ysAHvjgyiL+{+9rpbhatWv#f)WItgo`i-$;~njs-iKmvr{Dosxiu zdsT~~23z-z_z0Vh8^?|5G_#u{`BH}|#YbVus*NfeE0-x(QTPWpws~2JW?-+MTMAn| zEH3Qo>mknY5oWQ7J^J6qx_DoQK3Syn+cvq^0TT+!A1e4!D;jfpZr;B-C_+&Az@|## zQX?tzqE>$6c7S3@zAc(u_u++j=(qIvI?LzfYD3Uu`dd?bwBoBXwN|;@;qSe!(H=B~ zCt4w_E&5e;6Mg1D|7fZ&RCDSkcgT|4^UQXgdZd7a>6&NH!sP>$x~oCG?QDg^*oE?y z+(yZa`y=G^^@D8~Na8vg@<`onhP>ho@69x{#wHN?IL5`Pr$ zN4_0o35}9n6%Fb?4bnTYUPH_S5JU$ci1yFo^w-uI%?+@0v0E4o7mcYMk1BNIX2qI{ z68We7rUQsb!o^C8-+4!{b0Z@-1(f>_M`Rh#%A?=ZY9!xS47!jJL=02R#LA%HO)2dhVZrb;h&1g(Fut0D@PzrHV=|#v_Q{X>Xw@x)4mk zKVb903){J`=I23jwAvOoWXyT!rj@=c8Uze@$1^O(lQQX(ejSuGgSOxn{EFV9Fg?t;;;_5V6DH+FVZ}iow{0Itrle&;(QJ)3?-o zX7naq)WHcb0^>6Ro#sv30+M5&d%$8$?0!gtExrNT95#}#n+n7#SUYB zOOzu9{SXrQX3SU_EZb;5s~ZHQfDf~yrd4gCKE380qgZ;ik#^9S<(ZRt=6)4jC&fwl z1P{6~$+ zQ{|$}+r3Y~MpbX631{bRe@!(1Ciy)(p<}yQV7m$%@f>H%N$75#X{j9D9NVJ%F^*V$ zx6%R1b57=HKz@Uzo|Ic9jZUP68r9K6q0ULK)nVWxcjwHeEm9SSgOa_ns!rsRhnzS6 zWyegiG*7*h+3>C|2CicpO|iERXfq(b=#3}pQ?qe>(=BFqV~?xi{_Kl)&eYPP5(>FQ zv}U@Mnk@y`yzH(J5j!~n|SguCCp#eWUA}+vxx1k_i2R#1r37>X`UD{H%EpODJS#NJrd2dX&MA zHaI@yc`_DzavDqg=Q@^3(0kevJsBYUoGu*kQ$kHM{g1qjaN2<}fyUhEH~>$>H~Erz zu!a(|*z7n|2KikJ94PCTAj)rsM32ajcy>aO{HQBeRmsfr?6~qb(HjGanFm&n>ZuKb zrcv`^8K1VQbEO04h(@C`7s*Z2=M|vELhxpr)I72j8(%c%s=+=O53wCE=q>|cJ&6xo&rF! zmgh!2II;W^m9Ae5o{oOp9TQ@Mk2QQ^F#f%awLG<9wA~=Gp#UyxLgZmJppGsk!WoUi z+t6c<9&=-lP2s*&QnSk0zRIa(lT>zXd=J&SvZRF;=I?pYRgjc{D$faKwWAPDDbS-3 zA5JO4!VTEPvWk?`2bCu(lC23+9m>#bF=YVJS0)TFHa}^CP;R_Auz;INxTzgGS%vi_ zo4tOu5{f{~NwCw4z{{`D~gT_E$OIWlfp1uSf*d z307p~zclSCGZvf2I_^QcPm`wap|Q0*t(OKf?U38cKeewn=XTVgqcpiUaQF?1tSbiV zmK;_=-*Qyg3VxrI4#~-+;U9AB=}fZJQ)@?8s@e)M0qtK{C+gyZmu zQS51y$eawHgy>Rh-&dT7T4_CXsD8nfD)W(hJBG0E`04PZbsh4h@cf`NdKqa7v+C1W z2lR@Wq(gfEJYe3}mzNI=aqx9T&dh7G%x)?Kp8bm`5e^rvmBX8aAf$=VsKB!xmOZbu z^PEIkA&^ zhS&OqN|~CjPoKCe%|1y5tx`4y}w$!dc4}wx-)sk{AxozmzZ`zX0< z#Zc-mz?;6eVJiNT3?k>UPR*CT{uzKv(i4?4iJ{}sQ~LF3hWV?7^BGTzP2oexmTmM( z!%WwFiEwZgoS+m33#2Jt-7Ld~VtW<2P7a2~+;w3Ij*`#E2b}=(Ehxl!6>`yc2S(f1 z(mjFfMVnK(ln%sZ+!ESFP?$dNO|63xhN3e<>;#fLUZH>zVSK3J+=sm|J#A6`$ccy% zkHIUiHE*|ZZxW!<-#&>m`l#S4wSV!fu;oeZYM6G}l~=myZ9k*6&f?td6y??x%@%E| z{}`nY*QZnTv{Lw&Yb?Mg(Ggo~Zl5D&BD$2bS+*9n_bP2Nx0z&fGhq3;qJjO6W6Qd# z&YdS0@DM!ElCPs}v)u}M+vs80;v-eDUp8&gVyx3FJ>@-mZ$UPCF&#;j>pbDhi`r8U zPl(=~;I!-^4V_tyVg)pk2q18JehWn@>79MBvXAWQIbp*$_c>s1fy3$L`)=`%Txsj>$;n0Q&*y%ZrgBzbD@GhVn|KgMWT7vLzKFQX})@jzst_fDj3&n0hmilz45k*plxLHzD z?Ng!4J0E=uS7;g^Tcb*1mK5&stW68$;fvBcI#B+9m@PMBH_V*^+`Ja z>XU}ry(dk9x{HDR(vd&o{f;H~h>V(@iIzzZHFD8gDuyK9IVUDRvtn{M&w0=@X9HJ_ z8yAo3JhN|xvv|%g)IGbdO&LdK`VA0cjF~tp<^ot-saQaCF*3(UzPg%44)5VWpGjhD zh9Vmn?X#cPn&NtE(nrdQNZyZF6R|IyykRhNnGH1y_`_Z@j#^X7U^$;{SgWGSrqU%l zvjb6l>XNhUL>Ym zPmopjT^HO#f5GtKnA00^2v|qQ;3r*N2S7T=H*bjdoRuDMPraT|{QEDF|=8sLOOvaJv!x z{FM1RF{m7)<~f`qTDaVY1`hAV?##1K8`}_~4b3ql)XP78B|}djsaI%_G|z`WM#6S2 zxF@P@F9XS=y#}r1_hz#>qvU$yTWbt(YQE}UadO*Ss#ovIXYD}_JX1%XuIt>k&1!Ni zeA?v+=~YnUo_~Aa9I}2tpBDcG0=3268W^LPVNtoyRID_Z**9)D)+zmBnr!#um8m-{k06Bp1GzPF2C4r z>(z1V;sSHMb{6}Y{S;(sOs>l4{5NAb35f;1pP0Xn>lh)REHebSDY0#A7oO}FpAZKz zrRuhIrJ9(23J)b<_a}c5QWL|?LHGJ}{8^ z-lDBdUT5m(!bIaD%8IMiEh->A{e?(vOPY-q>NyIC(xG5B_Uf(|I`{^G7U*?vsmTkdS1Z^{YSZdoQ@U-^clv)h-OEI2ItABfTtsm4e1AeqqJ zr4~nT_DWUl{9$6iD9wH5@G)A1lI(K`8kq8NUdm##ToUJE4$P1w#8JCoUHr4ez0zEq z!+o59j??ORKH#}CEo}>q!cRCE?{LY+{YA}EqM^FT>EialNP@~72r>NPMac+Jz>0G3;*f4aeDnh-W zZkiIlVD-JE4=8MDTC)&o4L;0JAgl<7V0AdS?DNgiRX?Tjx>Y}~$yPtH50a|gXD~pH zqtU31IMoj>2ntWC(bxefHgd~bzjD-i>sVu^DMhUnt#z?85_eEDVJ}BT7wfj>I=x-| zySRTm!>!aYwu71%i>c9#RkJ;RHnju|Tac0Kqk`ncK)j&V;ZUrSPbOcxZY{x5@P7HA z+pHfWK|iAfHu^c0!}>aPO)zPtYRfaJBbV`jwy)LGD%g1t4RdRT!j1_et)Kv48jcac z1s7hnE3y*O8{~){g!BS@lGcp#*Li22@DV|3iR9DY{Umu7y<;f=wsdD!dUTG!2N zzCoAmj{6>{UPbU5jk)zvsR55ut>|eL$*JpNj4QRJOo`^y1Q0d~n>3qeZc!_MYFM8E zp52)?^>L_)lsPIoq*!L8bEGTNnwpqxJ<>s+*+2H&i@%&shabHSJ;_^ij%VZSJ6F`|jUDew~C`#hd@RpY+$leF^}v z!2CC{`1u`y9#6PD1&2)o6nU%-5-U(!2YrxGP}ay0LNtGToSWdBo1hm{SdyJKD!~Tz zdWu;|*q$tDDp_HWawRS*hBlrynGd$j=@k21(m=?7>hjhWrNYNAO8`0@cc;vUVRy#7%BZvP$+1q2tfJ|vxF@tClqbYlqJ zXG%?R6yt6->uk9+>X@ak9p6~sG2rDO56QNvkqRu{6*DjZgWO=2SbeZvKp-a1wx|1X&W%h+0$nl ze73&~cr@#k$3;vLh8y=cu;pP{JprJF`9c{0Y@QxJ9A!@!7cH$ugq4I}h+JLI83e~2 zp2;SFtN~(SUdYAE0EmPaiBvdp=rnbHa#MuHFCjD5L3h3CPU@&BbyHob<$0>ohe#W(PruT&1b2Z(Td7~eJfPRu^6b9&EUAoq& zL;drDpw0zHaPvSI7)87O?W8o3B<@fNMxTzMwJvT3N--7Y-OZ@zOWkUb@7*=XR}c3+ zo(2;`S0D3YDK(j~YL(~DhGqOB<#~X967=L_u$SXYbitcbD{!+nRf(AK;z!q>SBl42 zUKZJRgkuQgHUiD}U61)On}e1}sNK#ncOFKLpAVfbG4FteMDP%~r-xd9!zgVFMzqgzhr{DX^<7Swi~Kf zV?I}S`7KlDkAndENv2D^nRZCLY(eYinp1Kb;ZSHOD_6Npf{n_B7-eNvyl-^nnp;OV z4rj6V0jo{g4fJF@3wtpG1x8%kW2AT|=PZwb?yH?M8#aixb61_Ks?^-*;Wts2hFe8z z@scaEjxUa}PU|*_33ymf%WyN-NxPR#dyPGoeUnBo^#l1#+S}>kDh;CvJEmx7D52(& zqLBQ6c9OcB>C1+NHQ??c`xg~roMi?Yhquo{UVwJe$4%GFj(bLgQ#qQg2!+!`Yh|h7 z3R-9_6(>J|svYRQ8!f(g@jU%5-D|1ST3BJD9Eq1(%GyN3S~y$pV~oO932hFx`$M&n z>BZ+`sMgOQEpq4I^P!h3wC|H>vLfqyW_R#Qk4v(*IFt?;l~k zoeV#4*}v3IBK$F1y78aKZhtMF_eVR)H&OdW*XhVBmCn$Tfk}g-v<9ITP$1?lYV)Xl zB6A@Y4buIyk^W49Hn=zG=`tGXbT5n)ALNSM6;<--iLq8kIxIh`E*v&KzN&$_6p(Aa z0_2+Q_BC1f&a*c!d@pXiHV!%-+~0P3bwZJV6hMIz8$js*6{4?x-d$o0^L*vO%6clB z#cnu6+p?Gr^ynac_0bbi4vRbi zg_5$DA&;xa#X&8Q;|)N(2dA-*AgvHB%n`GBDF7LPAdyy2$cg6^H9fh8%p`Wyj$?n5 z1!kLl?8PCIS}P0|V_BZ$+?d3|71do$fo(Qk$?vFs7mz%ZsL*=`4n+j~iYBi=>D>`52) zHAhiqSj)~AKzYb{4;%+>56;^j%pjW~|II$f6+DfT`` z-WsQ9qok89I$KS*)tU00tpJ~jfmbqo-|j`}le@1_Jzf)EI%`6)QMm(7`^y!W!DNTH*AO3?ssI>WRZ@PzVKbd2y zf!+I}**F!n=>9?X+nUmi8+gi@0B{*E@ad<*e*8~a`Z51+OGX~8=b(Jea_tYth4TL^w1l?lbOVT z7WdgRp7cVS=s?oSGWMb*EMRnYE6@2^TG#r;6}x%oeX$ zGzS(suiFZ&8V6$f9MfSKOfiBL0Y(WQ1;`RN{ZGuD!+S0o5MNBz&`5*JCCFW^4NS&jW}h8Xt(0GGdpM0y(5 z{#u9t2kNRAbWjH%QYBPaoIBVn5?|B=kOR2GjfT81`NROlz+VB7@Wd$CWYI56Y4x1dC6+Spr3%jfK2TY{ifmA%E_;c`9d!@zo z?mbgiT&ImNeham3mubL{bK(~shKsTXj7^Sv{aGaD2gT6y0NH8%VMR$M1zs1$xLe9N zhq5)7Na$fg7Be2pJMUd#XA$q0*cuOibiVF*&{3vij2)N2aT;{)AMBR#m`eIs7a8(yH=FLLpksq(su$WWFX@1k7c;EPrr@B^jB3#Sik@=(^wi2gsbI4(hf0 za=3>OmcLoC*17#AP?hlgCQxBQi_7jAU+^Gg*MWPg;U~b50u%$DTdK5ZzDzum8D{=R7rM}9fsJc2=d&!ggI=*xiVN}m(dVSEtMMxRV^-W zzZ9E=w(`%KdA!K6gX1JzpTZkTkP5)=6_dY@Jt>|g*J$o~?hlH7QADQNfrBIUX*CE5gS+qKecBv!MS)?DA1Ho zfz+ypu%=)y11yh8LInOH$w8&&gsfL z;2CKA5{YfwsQ;tI^&&4FX6tUlXCKIc^~Be`oi`92_3 zNpn}tp7f3s-i$iX;zmu5}NO0!iH(2+A1=% z?t3&#{6qzH(N=?VR!!>9R5tC9jzduEj62VwKG6G26CTZh1d0btiou zaSBO&A{Nr9H+`kNM_M$dRN#0>rLNs3_;7$}_G+)B5 z!XDQgB%_J%Tb1MXU|XBEWrD}1+t+O4FMrmG3M{brzEy74SUpYp&Kgq9nQ)t~^4@V^DmT?pS81r+_!~W{XR_bQ_JpNtN7>6P=t!QhwAvaVqIr?`%;Fw8H>ApCsXf z+v{KxN*3-Db$_<}88L=Y=X+t}!ODI2OHl*RPR?D;!e7JFjH2+rqHF9+;y((-F&t;W zRkQ2!S>BuxA2WKepf1%|=otCAxx!2GZbL`cNfp_EdHRU_G zK1B+RJ;!m2lm;`KsBh+WrL*29YT3mNI@b`5%dwDB^n%3Du9{OQp37bbS}c~?uyE%SKP1sF%7P?YrI9JN?_(4CuTO4^tw%-_H5-bcV`{u+D@@psMHdnp0kWt_45>s;boG`XfsV)tix2`?)PJ#*26HFQq z_BvTTvasaqBBra1UjH}n=9tRY1H?Y?>L}tR3?A7L(17dInOK?!x^$ay**dbI04ugN zA7XTE#Gac|yb`^iSFW0UYA!G5iOj2`frSVsTZOErlo`~EwsSP?7wmdfR?sJ{G$-ew zNv|C-=b~Cp3R;v(90uh|@h)X*FWZBBr`))s@UGm!Fgxi z9-!UvaH)NlbB4rK`9A(>edITIqB%FbqW~cNK%f4K^#Aw8v%gC}U9gt5hfS{G{6lu- z7DPG>9(#V{|Cj!C{xSaDC|`REni&D?8>w;xmXseB_0EIFl?EaIgY^4N2viUot%e4# zKTtMa_I!Jp;Ca}%@jY1kyYx#S{UQBrbHAnE@zGCz9w7ZCg(A9kEu^2M-B2SrQ1SrM zfBjqf`>|6NY3>YFMghv^0+4;<<_^RU)DYd{#wC*ai_s%IoO1abK9m_spyTaVdZ6pl+Cs?fk zIDv8Jnr=*(j!noP@LP9GX4*2jy7xvrp2+dwncqnuxX1mJ2BqKQ0)fWw5^0Ykfvav3 zvzWGA1AvsbzQ6#&KT>cYU;O(TKRH>c9V}GQR|ab;I+c6u7B+6ur?&#>er<=3*vp;E zgro4VM;IqM*pnm zSqT|&LC`1>QnIaTLoHvS-5DNIyc(*r2VC=c=-n46n7|*@bua?W(q^mWU7N%ecnQ*p zt)2B3&7ACs{o;X-TyX3x(SqslLMF4BewcYR3Q}t{cF{CWZ^iw^QK8@)*i%oF9vGvU z0g3}HR+wLtxYowO`oGT_;LBh^N(QoG644=Pc@>05oI0qn^VjFYU^%nX_A z!Id7WWx_O$OAALK5!}&^Q%6M1PuhyJ&KCU``!44tr{QAUsk-$E-GF7+WslF4m}r-8 zMnVe~Ape9HmqxfcI2z!S#Ui|w(=+4iWYOsJgu2t97oEXEr?o;di zaesT~ord&|u!DC}UD8iKMqc zu&!GdMr+_wF}Q3>ry?7lU_vdI^)#KCXf%vXGT{bSMVM|W(T_(GqGyIaLr`ZSH@U~EQN+tDeT2kdO^{=K?rvg z$E0YCTXQ%|)%RQef7;WK`Tkx0M=1-Tg^Qm~u&Lzoyj zSW`;y26KyQW4vv=o!&tZ^&x=ugRO-Hr;Tl;6EgKU`Re@oHHiVvYvvkmVeO91Q-qq< zCh5aDZ&c{N2`MMKKEow)4?^xI<|bL${{{JjEe3BE{l+x6(y07{tKYuQDj%~`TAO?T zSa3jkcu3_XWxQ#h{D@hor;+6Zj?TY=T*5>mdS$ekDQy0qZ&IHF3Sxn7} z(-=|JKA!3#i$v#Uv;G#B&~b36S;vOa9L&-N^-WIlIH~%+58=0H;I?6{n#C8DYIuFA1(&dhmT#hfr&gjH{9}xSO`S zs++2sW}|b368B@)0Jq`n;*G#nNMJ_%wTB12CuV4~fDR>&5{is1+)XW*8(aHj#T8*d z>IdJp_5zwDR3bH@F}_+@lB5Mj*PgFo4d+d%;g~Au)k0ExL?BWzLL8C{W5}x~!chCe z-PY|-m9;T^(x4I*kIJWtXYoz5uW`Rs+N4W?g0hVP`s!VKJJJ{g0gtd`Lr=5V!aZc0 zKj8IAhnCmrMeJ#(wxD_0`$zYbp$K2SU6@NC_-L%gGp_DGqA9;$mb8~{By4UY!Y%rVikNmfD4hRUOX$)UWX8K z*1x!jVOX=9LEeMShfxK7(%n3R8}5fZrM?W z$O<_!&DU_ODDTIqz2Km-PJ}4i=&8Kg*go90*`#HNvo8n6>ZN|+8z)rmIcT(7^aK(l z($?@v5kBYmLPjLcB*;hmQqR4EDUkT*B5Z)ZeU$}4TjbMeK$+=g3D9^MVyb0%duX4f z;30V$M1g!VF&bT#gec23mw=4+Q^;F(sD;FM3j^W3^v=t!{uD4oXus3Bjqe`9P%X=+ z^8-H)h-XYfo=7x=Pg@8-&!U3h2K?3{0zsL!96$t|^&gT^DGp=(fdTH#td_XThrP?k z)re;ff@Cr!fTQWaHq991TWj@aNl{9%n0OncHJrG3>H8>@2MOk)MS955rj|nu3H``m z12ZTt>sj>aHBnD|Fn3wz?`wM%(eR=UB#f3S!P*4eWy?zQbir;N%UsoU-dboS3&XSg z>Z=Er7DUOokXKO3AW8S2mWQ--CpkMXur40!hG^g`Xd=#!`4W?rQfI}^)Ez;^5ENw+pW#cR0 zM!AT&%t$vQec~UHMwuRsc^=_S@$l+i{h3~2En*XdxgPjmsnWL2#PIz0GsI+0eq#kzs3JrTC1$$=j zlX1B-jTB$3wt_C9QQQ%pb`xi~{p1YcY-yG?fL-( zI7Htss=hh4zT4xW;FFXE<)4gsth^Uf#R-*@fe<~0n350*+@p%I>W*}B6J{kQ7~Xh} z@nrS98g?{{kDwIUOxs-WUI~NQ>6cxc)^Jtky>qg{2}=S*ZAN)&H1KVrdNQ}dRwyrP zd8tT|n!we8l0hrt!eW9JxRS@k!Xa8xyL2Y2&Luty%btuG?6cBP*vIu-#A?XO*~MSo zrX#VaM`x)p^!x>qYv4e%nvKfAPnkliR~^g=TA0+cXhW;f2vK->{K5PuAtrLWt5Nub z^%=vEfT7nmAvIoj!7J)zt+vWw#^(PF9FXUY3KjkTZ#tW z5%+!H!;(vkzWx`kJRK=@JKEiWPGb(~vFG?5Ue${3qHWa>!UF{6TmZ0J$>TamDEZcV zJb36%SK(Ahp=^os^u*NV)-MfcXr3ZR$9gTqR|RzvdkM(SfIX)Vgq=uL7^nsZb8$@E z@bI@U>dN>*&@awgh!mc=Tf0+V<2hgLZ}4)nyQmJyI^7*-l`}%iMxbL$J#{l*sNK)M zO#^YI63H)8NA;n1#KF3O`PqHC73Is|4fp^iL(m`3fcIn zj%4VbhVc;!U0iz{l(#Q`R~wSg@jzm^LqN6@;B+yv>5;sXhx{(H5%O+PiaB)5(2Uzf zYfgis@L4&As8I0!0A1X^&ywZ>eTGhY;i1e+b070qU3w2G549eq2$r$XHdWn;^)}{C zc>7lrTJY#1y-Vn^b>Vp!&eK5nMybI`OW78l);KWM*}19bI+=-E$+SjRC{ zDiutdX&~mjnPVE_2m34ANxOoWW)!O!+rp-<*!xK|EFg7psO@Nluw22v#>@V{c zh;Re696IONZd@b`pykg~U6-Cl(4ukGSYSO{+I{@a7&pt{D)XHNz`b>dsbw@gkiWH@ zG>yAJ9H8a0XA&AD*IXPD+O31WLp_WImU9HCUS#@FR~NBdkL4XI|v zqp6WDMg!y=Sj*s&0{+xNH_PA>(&H{8=m0OxbIJ;xNbATzNqw34vJ%pT3%t=dS8aXG z;nf4tYh=sHh@R&#HoTC1meDR#KBUNCWsX(6kJQWNOl#Hsa-LKgl#1~?jp^a1KG?*{ z8_697)X^0Z4RPav@Vzz?F8Rvccu=pDLDixfEwKBsz;(l#D11GS^fH%Q&(TB2QS~f` z*CdCXHV4P2-Pe*vt^u6Tq(Kau5aqfj(Vvv+(Za)sQf3;*Owv_@!^^OZhauI%6ZOU^ zBvxl05MK{_Sxmh}WBFu_CdVK3Jgw2H%m?S-KogdD$UP173>PA(4B&|wFxgG zR=k+|NMnrBct97$Z~jRftEEZ)xIaw#>?bueEXv^_py10OXNoe1E55fzK)5}Z5RfhX zr5?8tlLSMvfY9+_=DWrf|%rP-^wlLqJk;&3s5AEE2&jGGnWA(oaC z^@A>$oz_ON5QbBa&m0jf9H3XXqZEc+(X@zb{e-7RPe4%tGklCp|RIF-f0)@r|lP9(Sl z7OZRM#$Hx)wok+MT8NL3pXKMuhlw5uzFZS7lvv~!qs(P-dT8ot+V4K}Vi#3he##&W zOC`n$Mf}OlngE)j z*qTzi(=#`*x)!5d82^_UhG%m`<+NJR`ARwbPwNNvJ}Y`Eo+nSW=?`N(ul}-HjuaAx z>VFSUqFLw0Mgqzi5PvmadEZ$?K7^{u|LYqohBc3f1@Oiig8%{|`dixTUw^}YO3453XW9N7)f9f+2wZs4)M{te zZC9HLMxgZw(9m3I6W7Z^JW-vaEg@K-t~(2?qWfec+w|Ty)I@)TOY~StYD{G6WbGeJ zt7T2a5=|uCH-~5>QQl3M=SpnMLcZFe5|P%i=62rt@Oplc?KRQ5I6`)C%M6Qyrk}%(^P< z#Ht7$+$7oaLXKCMQZ9;AY^fYvBD~R@QRb7E#jW0BM+)ipcdTdw=%qz9ls#v!Y6%TK z+~6HsXUeJ-+lxrae1-PR(jIP6tRfkj50*@dtm}U z-3FdG#4oeie+&)fIN41%>)3)9Gck8>ZGde^?n(?xrR=#AhOHcNUXt0*MI^36t?l-M z0(x($DV$eTU>oB*z$M0Hky@32=R~V?!NQo%f3dkr$1EQ7o0VQ(1V*WOkYJs}IUMnR z0`D0qpF{tV3n62|fb66Yq;4Fdt7?q?x4NJE^lb+{_6(7qrsHZGo1h{FK1+)tC(*2b zuTV6I9U9Tw{HoHgqX^c#NL){_&w=0-gWMb}-#CCC1OL#ec^{&ZYw5XhEM^O@a6@(0 z7m*?!R#5NgQQFT+@!$to03;s$~{_wFY-jl%id)-3F+VO$nw)VkfA3Z;Vrwbr1 zi0!}TOwH|gX0wxW3WwyIDs3mWS?lr;%&bd-uyqW^NrPX8kr~VslGu?Nm+2n)kxvJy--0ECOXpX_WWw)6q+9S|aZf-7-$5V0h zE_naU2#;=l?GIXkTHulKT2I(P0$Cmd*Nin?E8T_HPRswk+qo-nhtJ?Wip7GY)HQWG zXZf=rTE4G{((G71bkya>^9 zhC&};^IoRTgeNe?f_0-+OxEd8GARl&+IqC)EM3jDO5<#&O8}phRVvE~G#zkoNcV2P z^=D{g1|C`?m^8Wjm7|yp$ItbG_us>) z$XR6z#w4qlP)aj`f#tu2PM5x*s61l;iDK2=ijU3W!UhlPzSr**Q4M2J%!Eu!%-=P% z>X~PnGw%l>8hM7K%RNw(-zH$Z5*bt-IGOJ|;DS>iP#7ece~P2!27+C|p2NDfUmjAj z`Ud$!3+RE#kt;mnKn569-LVx&_SZIJ_&Kqs8crA?TXHeCGKe&RSy++L0^#|?c2*$% zGO^f3YT%II6k+`_xzfsJXbHTSc93XUQE&>ZSvVA3Tp#GBx$^~?VB}8R=cm-$tc<{% zbCOQg4fkvG%t7rb-RKRy_^ls^{I}dCT|?-#o_(oaniSwoR~_}TR!ye0d>N}OMpoO& zkV6mfDaocWbHMw9C=^Wja~Jxk+X5NMEcaI(8FRaE-Et9pjtq)N?i`+^79?BmEFP=d z7e9ebol^HhaO7)d9{wp)^1Bzb*YsG=4p8H%zoy3jy@Ie&wgC*zF*^$h4unoxEA`a| zZQNkmE(6Kb7^S7P+>R*#Cbq zhB2@VV=7S5M^xZJs>4b=%cKS$vz_p{@S1p8JK#OwyWmpg=Py@7>{me&{22(V@ENh+ z^)}%10EY{eWT1?O%@0Co8du3-#jIcDD8750ASd9hY!wysOmP_@d6uga&v_-ChC6Y3 z3S|$cU{s1OhLr66I+Mgwd4j@-hPTO~AEJ{u4#-b>j9|G!o5zlIaTZ4@sHq4c@vQ{- zVJX&jr{O>Qw#CS_1REq3tp$e*BBT?PPJM+^NYB~_tb?YcM9Z!-1hJja^zNU7?B!YBlW~Q}{rnio+vMJOwvS&rmU46d54h6Sk zslp~k5^Q(gMZe8Z`npQvuoijG8Q957X9J&Y88b$Jck0`*MOR){aBfnL-NyHMlB|IP zWM%U9Ry#zD9qsdk6%6ruOJe6Xsdy4(RZ2zkBU29wcvkZF-3wbaWpiOwk`@|pyRJ)v z*ew!4aTbmg*61rS(eD?=I(pJdn^b0ctcy^8tfeU`Sw zj5MW+MGm^6!Pij|ItuR?#KUN)W%sTIF6~1#rIM~@6-(GCd84fObS3H{9r!$_;BrE7 z94nG>Lx8T$)RT|ItrNgO?#`9VlA*;BKG4_| z6em0x7Ns)noMp?Mi-T}z%XzdMj z=M7g;(;nugg`Y1|wEf1(8wey7*5t`g_YxDQXB6oxff3Dk4cufNlx*qxLCyXUB7;pyh9TnTCjC%Ki}IglrG4Nzauv3; zm%ixyq$P!%^w}&LX?rDww9pEnfvEhEkG7RWZ?_^Lwsc4up6yZCO<8@{vm2%i!*5jkyAE&L9t4PVaT-BE0zZH%+dqtt9!p2{9F>s4d}Cv?>_ z-SGzg6i=cO*Ks!{D2H+4R#Ub`a5pd;o$tjKUVP%0#p?D;uw?Gt_fcX^Ebpn9rKxXI z$>(&C_KvMN8|mrb-x@lpJy6=NfC7LQs$N1`# zr3q3Tsjbm9z7LRRVh60LHW`_-i&(n?2A0O*9(BO4^~*baQU0eBBb$a&oo&+Tzq)-7 z3OKXhxXl{C`-Skoxc$F|kkYb75l7V-id{AyuaMO~W^F&uKunSa2QWuv8LW>}IuSk*v-CDq$NiCK*MA3NWr zW=-D}(bYI;t{?(;>JtsdJF$mSgGj0@X4CE8dfM0zVq&y_l0_ z99aGzZ|@XcS--7&Cl%YaZQHhORa~)cvtrw}Z6_7GV%w=Yv)0=Cw6)&zoxR@g=Cn3u zo8xkhaq;WVe0uNCA5Am@Z^0Y-E zO07TGvIzGbQbTPAJkdPZE7E^Ba(QR)`IkGknY3ofF(xaQZ1q?KCbpfa^w-T%K-(Ah z336aULSl4fe$WXx_cvl<83zbJd14WAIaQFsL537Nss{&<#!ELh3P5?=AqvA=^{@`X zy(Q-5f)E`{m7{Y=U~ouiaHv!>D?7t=b$DD*Q$T4Fyd!_tEH);MHmyAPRX5aSKHDLc zOX={&Lsn;6nUo{(gX zH5!%aJ<>r}2PKQFSD7`wx3tp<#a2`z7x{}Ax*oj>nxrltDcc+M4jeK0&BxHd5eI$r5rxNmS|ZZS=*62G8j(EvCAV4! ziDJ_n@jaEomtN5kAE13(zkNx_3`UXKE3Dh~W5<+)(r?Y{vg$x>oSLweJb=Ivb?u=| z3=m79)d)vRsB#wOe|@aKo*X65j8n+w&r$!i&5ztz@Lm4Mm1xc2(6!iO5!K!f4aRlw zvC4?sxa}w(z2U)lh>@hQ^fFXAZT+Z%@gOmi*3mRQBo5|VI!SKB4Sz-~aIusdDkx7M z7;dmOr~wdcbif?u35>rXavGLUdE?RRlTMdqEC+>RqSG?hHam@dFKT0fO?W${9VON& z1SQeWCE0|WXUr>{(^pBC?bzSx8o_a#3$sGT7J{g6JS7riM&SG_Vpiwqr|u}B&^0b+*E3UK?d6YUlj=usxX!~jvsyA?9E0mWqSB{h zOtE7s;5^3;0O1B>r2Nh#tYd9^gTLy`n=Fy5J^(!gfZ`Q z!PGe&%L9cE<|(zh-4<{U;}~Yc#c#Uj1NTMbfE_Mtip`A zWqz~EXB&N2)2u?up5l$G34(KYne(a=ZJw}R#83F~TMXCE^F7JuW%zAlmI)yes~9j_ zgOgYYkuCl!z9f<*gMY{Rqd9DIwu;R<;K;SA|55&9D;his^#h=vQgwT65~nV zP5R||mCbvlX)0p76X$V6L(}#lF80m*?PhzUo?{uSW_y@k8r#78uTE0Aex}}^(9)*A zMc)4;?Egw$Yd1Ma>0(t{U^Q188SB~r(f^aYmo5$EXVN<11>O&X2@BN1Wpc&dnrLXQ zun8dx>;;g(k;FI`;bpwK$i#1A7F&rBXI4)$+3gmyS?x}4S-PJ6MI&`G0Q4HOs)zhR zZ{XKKj@YaMy<*FH-T2`jG16T#WiMxnVfC!$=)VksG4dcr0Z=7jf(&Td%Zz8WlGmWcUGx^`t;;VUlL5yX+)6Y`Uv zwRD6bi}GGAGs0=c5swbBHfpm+DX>5=s-e4GrLaI{C{HwPJV&b_Yg`^Gik_eau#NX} z0Kat#`YCc=qp-i}_?`q?Ffv~NcT3HUei=_!p|cd^ByMIQh9wVJqE7OW+I{wCbexL^ z4j?_r7sBNF+LmtQ;N%RrTv&ck(}}J0Rc7|;nUMjX@AQb1sh53)B3Xm>AS7n0U1Pyt zV35uVfQO=8n+ zS))R2Qa2DnzbPT(0=Eev$pS*qleu+bt-A-)k2z(&ka1aO{=8_sTc+uPGZUE_`DQY2 z>K=^DEIy42d$0dfB*}3MJv{^6^AX5s?AcYyitmXR9#1<-|}`#36~7Dbs_9(tpYX0jdlGI9$dA;ydS069?-&kcd!GzXdl=T&JwsiT=80F@ zAvTJ!^e!NG5Nv2!;~$Uui?v$^zMi(4aI9{x+|LlV2#fT%^_#S9^y{6*G&StSJUKgF zi)4EO#>+R^i_91uH+DZVwhf!=1=g)_;KH7^4|lXI+I$H*DJ{Jp|25O>kFS#cHN(sW zAmb?jGXDR2Ea{&z{*UhcPbyySkBSf7>)ypP*P5$OXK|9kmnG5`^esXrR0 z)nL9n5}ILtS%VVjC^?L*Xg1o?bPFyST#npU^sVm*sT`v0GHr-m?Odaw{97@ds1iIM zr*h8ClZ1vP0~4puH?~13hG(VXm>BHH~s5=_G8EUepCsm)3 zn(0CYDijF`yRx6r2I5VqZLhHQb9&|xA2Y*ppfLwVU~!y$nf>V z@N-ZuE-4Jfdm!RqH1XgLIuN5fm8F4KDWsT`sClqu4mVCA$tDc9e=3vDC^|-T{OSWG zbF@qhK)gnIaZ5DJgMfW`oxGy^^<>|%2Nn&>+?NUD!-|-#HJk_yDq`GDDCqYkym);r z7YLsMk{E)`0B0Yx2lT{32$8EX@^1O7hqbc{4WNjKuk=^yjMg+1_{Y@ODnY4HYY&CD zNMFH4Or1XkCOtqBm$u4)MzwICl93uFiPgzaBefV++FVueB7k>QNm8<>KV9KVJu=P( z%Mx9EH<4_s=A!GKQ(c4veq*1v{iVlSJ<7Sw=B@P+xUgHcux+^`zVw{>&`x! zR*u}cFD$4}Q`L7BJ+)<|VA;FmsLH6N%m5Z=Vn&vu9XC+H(lG>hsBRW65Yl6e9jSTB zyxg3eV3`54JdB=m2wCM)Vg)*(YYFs=-S+u`0*NDvA9ueW=6*K=#HZBu<-wsqhMg## zM>$-Cw_nm&&5GDU-B^4vbUktWclt519?n;n(*x6=<>mLK%6A6Z5(Vl_3*#63r0@3^ zJ*XBL`%}}x`O}Q4OtN8ct$Its;s)?I=A>_@>>^yEmyW7m9ml26wHk){O2OKu5@)eq z5amYwhovk)LAm?Pa6vQO;|O4*^B=$D5`ZFir5_z?TLX&7Xu3I<6E2{LWFOjiSf0m} zp_z${iGLd`Q2Gr?W}1~jb#|;58Ycef-NtP{`g@9|kAik>RM@!IVAm(9i>Keq<->vPjC$z;45%Veka>ZAMMmX$ZLvrk>Ff3|&44O0vn0>txb=&mXgQ&bjJ~;u zd6{)3BWii;=Tv)@i?HssWWh`ulwz|H&Uy%MSfZhW&AYzOO5)K}d6gxz_Os41H!)l3 z`V<(|fab5^gGQ25?n2`ve8+Yedi0?jG@&V3Bp2rW1QF;-Jw&q$t~;zd(P@a*9DCXu zAu#@tF|sDaj4sUpv=rTnJVXy-VfE|mmr(pZk)>+lAC=!%L%CFFaazL!`w-qncqf>} z`PKWsBl6}o;gqnv<&Ku?i|dDoozIO=Ih=5>B8EY9k2w{fZ-tr=5De5> z`uc^mD^5}NG%}CJqw<}29w3xga2B2}294x;n=&+RUmUQF>T@2tv5sU%b32xbEK1h% z-@Snw9;2223{hck1#deV@ojz-RbS^hh}GQN)$NpAovr!Vc^rA^CK_YC^A{WFSG-Bc zp8(zeq~8BtO5Fd6Tqq%~B4ens1{0licM#G6RVZC$PQ&}~C6FaoS>w!#N18R&wgvQp zu`qmGsyxVi_V12$)YKPg;^>YWtg4XttPL_Y|8Pz6D7eqr8J2!r2>hPQRV1XeY@S9X_WC7izRIhcNJH(0pWy2d&ol8cAAW6aSM3u3@rNq#}szi6)q@#A-R? zo1TQN)5g`4cE6_Iv8H7E;>i}AW82$%4WV?ENSKkbDoQ=ai5Ei*$!{3!!KE_0 z?GXF?S@<#5&Jp7=-pCl}b=%l{PNXO))6F_R$zkxuB?wX6kO>jMh+2r(mwoAv*PMZw z%LO$qcYPuY7=;QP6OsdWPs&RL7dps0G7r5w`s(52Y{v2f8bIAXn#|Ffx&r^ldi#H) zuJu#bKdGzo59*4M8U~5gMFFU5_ixl~sj-uK_Z_Mkqs5Sw3iqN-w_S?>Zs{j9`)W~yN0 zvMlkqHrO0z*cN`S8GSaQ^icLGV{fbXW7xT8lKmbTTM$)-@aBXhEw~eDX=@@wZ$4sS zvw&q0`xIVPbT#i7D@OE|Pnv`!3qGLfV^<`${GHgt*b-vq@e6IaMDQPx54cg(i zQ89$ON8R$jP>DHiOA|jziMHQ8`vhh>v%5Yd7OTt17@CO^2<#EpURxxw(Xkp-iBiBC z7NFV>no&4pD9Ewp<#Tw_6Mru-<2D1F6VqqnH3N(163#_Z3p-@!>d>`lBWjzr^MWIm zH^)^*x_O0W>PutMRaDEWr5L^5!GhCZ?s@A1CTuiW6YvYaG@bMW+ggsWp-A9(@+ z%P`))h>~~a8L8IQTs4Ql78!d}4#@{qE}@Nw#dNI&>dA0KIQ?)i;-4tV@k&-5Ww}mR z_&ASFduLsjzgcR5a_dbQU?TW@1D@q>u1K$c+-PV6l zH;I*LVo9FaajOSF-M#-!-NdM6zTH36mDRoe)-cls{IAq~)%V%?Cv}PcL0ww5Qtj#g zrtaV$>IUIEmZQ+44&|8r3w5&r)FlH@*L|A8O}~cWMhT36cuedMbrt_mw+cXA-hWUx z_G(mQDVz95A%MD^|4m&_6nrx*lH7`2N60IUbvPBQ&)Gs%1d`f;0+$ohBTi>LoAAM) zZBwoaG`q~VG|_vETcgkUS%iHJw%*=;T}pG*9qn{e#YlV?zB>ptwXFGvL*SnZ{0(7R z)~+`hg|%6CUf4ff#qru#YAo|K2|Rr8>OLEmZYQWR^}uvpOnTQlNG5GB9VM#18Merg zUYM-h=rso5wAxZ63N9F;S+ zatS&lzlfezX3hoy6Gqvn^&`C(^dsF~;Z|$b*rmaj@UopFY)Qo1HkrX?ldVWzox<#8 zfc2ip7YMN4opQ6}zWuS@oBfg#+nmc4MIplnc&O$!z&wKn(5}h7&fT(ah{Z#-b`=8c zz$L|nnu~z**wwPJk{8hXq%B< zW4pWDZ>q^l8~R*Xs~UfgOkhl`Nqi?kzR&16A@?a5I=znXORNF!jz(V1L%L`X53D|? z&TP%dK>+cUCr<9DYHXBI=YxgKSCsNH!&Sdt>KGbI;gcvq{oq(1YY`vE6MpB3(#}zK zeaya=P8Ptt^lLn_4O8EF%VjOTic!4RdXrE7H6%KnN?CNTWZG3v$Rh7v#)I#z>+}He zNi&{>`ayhR3(Cjv)?F|c(BBX$kI-|ANC5DH`y}|8V<8;zxaS~`B zb~y|GQUy7Q<*oyg>#=7W`+-9;X(9yzxl5QFO@*+5a+l&hr9QTt#fC2Z;Jws#GUJ*! ziS&|8q`@f&3))2(9Upd4$Yd=f&r!dq z)yGG9)7?r+e;Qo1Gi@tI@u!)ceFjI|eF}N~s#VrFHbub*555(>41;Kl3bSXyk2cJF z*EVX{_5*SmTrKmxMPl8fv133#caM`%;OGh@pZyyc#GZIR259#nAusF~AytC80Z8d? zy4lvv<7u$%L_x8cHRvuM?QKUGG&%XGcK%IH`vQXez-UDkGS6ibUDo-=d8^Hq-w`we z6u4Nsg!L4Z&;d;SnW!J&`71Pe-?r@XF^UtC-{Ii9O>(te(I{Z$1`#%wJ`<_|);lo3 zdWV4J%Pc^?ZMEqN+0 zJ2y%)h4hA}DzD%eO87Xl^c-5K^ltY9(zhP!L5ej+HoR`1S>$m;=4IRux0+AkP%$XH z+Sq>0q$jGlA?p181^n-RiCoiZD9PUt@Bbw4f3n{HNnQ)v*+jNRcJ`%zHa$hCQ~arU zTINTr2_aL-=R}|(Y3QPu*ih?Q!YCz!0LZHpte7dy^~ZS65=W0*|D)b1 z8)R_Fs0HYukoe}cS`Q#x9-pQ&J$AgWr!xskB(-48LQ2Fi|uo525IUyY@7z)9K#bXcd>?F>^rLXrF=9(XuNKCE0Yuj zsx_r@m^;~{Mw+Air_&Ip8>GrH4pZ0tI4C;-SAShPZWPl*Fa~)wI z?9$d4WA8jq?|f%Nf>p@(?#kWoF-{upTmjAP_DWJ{)aoN+9m4qG6H}FMfnj$t%ocfS z;FBH556IGn+2VCF+E^_mG&Vibp1!c4?&*qGjx{Z=Vu!qSMaU|X?`GI@HY@GL2PJx8 z@O9Kn&uHXCZ{ zEd;8eoC_>&`n6R5&T9SL<(K(6tNu~|B!lIy0b}s8tC#bJQz%VBMFNRTm=#$G&z`^H;vW-*!FW{d2WM=GF~YI?pQ)lfI4 zRLtB?t8}PNS=7Vl(CKVkbaimjo@Du>R?f$PNBdOLjzjug+|EtAE*g3nynN0kV2k|km@}bhI1hPd$W;H56#Y%OZ!c$|(m*uN>{&|X>)93759ZGI+lDynzBJkLz;@Xo=sWn zchL`Nh>)uun@5GUpIuI~-N$Zz&zpd6dVW6pdE?b*XjqartSZ>SI%&WF&7;ONms+N{ zhJ9yIxTW>d3%vH@u#`}1?UYNzw_)c;aT+_T$};=4AKFA(6{WF|>v$=B^znm_6iE@J z9D1V3nwe08$z^2540F%s*b-02u%V|)I=v_i7V-#Xusoy2l3Ot`(j(H(hFRgmo7^qf z=jw;64HH;=sl!eez_LlhI?vQ=ZGz=!Z`p7r$x~*Mp`i5=$U9PjJ@RuHs0=SHs~f&& z{uWHkQ-OkCoLL0f&Dkco5z$S#X!;Gmj45MZ$N}|21SbS^)XLua=YXCZ3Swe4W)xR% z1Fq(3RqN;rJ&0P{?9P#KV4EqQ5NT>9CT8(vvO9l5mfG`1KnHg`E5H?t_I#n>SP3YT zH86W+ybey!`2PFAy$NC8c(7xt?dgeXa%2FJD)wvD3E-%%Zk@=~YktP+eZM)F@68Q7 z!82~~&Ai1|7Xph|4BnjVH{xp>^xgHZ0_8H>xW(u!N7hL9rRY`;0m9rELL=ug(4Gr2 zdiVP%9YMXA2GVb7nDK%JbSFOSyGcWKMREnb>aa246yU>*@SZ&Fs>?b1w(DazKmT-ak8z{cExtSB@t`ox>Xdmw-w{j5HsN|xiQakBLB0<8 zOYjDaRqsaxzeEs%=fHs`70i-U)M_(GT(U@0K;IS03AOZMlY(GqHYk#+lQpcuzYevI z`qJX!)N=7V9Jxz>N-Qca1-NqOYy}PcBJZRa)}e6M$xgN}skJy6hxD12nYNgcLGsi# z%CRYl`qI3mXF6tv(B78-hR#1Rh!*QTG2r!;3z#<6>rJQ(O}9^|P5l8vXa^E9&OZmx z!u1bA`XMe6Yu_=fW8t9#aNp0<4zpP%N+y*cCPI@hM^D9~UiqcRDA~FVbM6+vb18|>xO1LkEjz)EQp|Q&ss0Dv=1yBzAFd_TV#j1E#BaMIoZu-r9EKV zF&aW^*+2Fk1{H~JKtrioZ+hk^HlehNqq!`PCYk0qEKqB8*P%bhOnT-?E^Dy)lI%Pb zA#W5aAywBo>Gxx&snkP<+8QrTeQS(6G`U5!k*-!0^Sw7M{X(&0qF@abp?v`!}+oAkofz?%$krwc{PH?Vs+_>F+7@bX}5S@ z;cWZBtgHggn5naZy4X@;IzbVk1Fw*JU7<(_PIfDRaGK~nnN5EAB%c}oAk%CDgn7nF ztn^24ew^^B7pnhsI*X%(jf)uk5yrm}=4b2v@#UU4SIpN!Eiy{_AuluG6If?JtIB}g zRhC*i$Ey!6=#Wi)=eI>={)l(mt-}M|vseA|A{{4jhbII}m$hScOH;*Gz4y;YO_DS5 z<<3q@yU2@mLK_sgupF<6+FBHNLf)3!zZMb^O&%PwzoFv)UasbU?bZrh_y2g-UT^2F zX{`)5f{LO@EH1WneNZG)hv=Y{6GbM1g75aMKpl5ljxlG0(0ZH(oh}?o`!k%)I zucd24l{gX~!)X#tRHPeQsYFEA3YYY~sJFI3yfLUi_;)Wv|(kkznn+Amp-d^^IU zLrX07JgdvwGKabV($e)arezwD!$2Ziwi;k0!;V;`dFaXusN*R{DjgaJfBjY{SXC-_Z=#)onj95PYM^4R*ABZrdRQy zkKz#RF%?M*k}-ELB_RdRavXhcVYgk3pVm@%XaE^s4F)h#d=ghfnxr09BJ+)IU;Hrv zCJIFA)M`?f91a%u8mn`K&q{KRaKpRC%scr85jk6+M z6dx8j1@RLceJg%jKwVgbzBfhDLoKVmA{GHm(C|v2Yrc>|q;lPH!4Twq`=W{Y{1BiB z!xq#`DkcE>%eb>^;xliG2FX_ChxIYy%pUKNgNF>DbA z{a!>h9?6Q^9)MqjKlr7xoBTcWeb*!w))6p4lRR|gFrSJDLSDZD(D8cs^#B(|8C;gW z(7ILK0hmJ8WzdapDLaAAn$IaU!Rv_LBu7T&etVS}pyQ_o!nmfj$x_#_ZFb5jPO6-4 ze4%s1fbhCf14FWoB%<3!)IYK+(+tCrT8snLGF^X{IKzrxIu!GzyB58S*fgEN+fSO~ z7T)z1F^MJfYglm{;;3umVv&R_3};`%yMRL+;(ay^Ejg_aKGp9L9Q4)=2K`h<8S%o6W3QxAiY zbu3Mf{R*brqg}SgS*JjoX5iaR>Ayp-ynb&SRy5&Xx?z3Gc`sZYEjPzS((4Vw;%9AF z&(K-A(yZAtuL71Mv0lVOTmE5aEsccXa%}gp~e0 zFCMrfCLCL8f2hc=pi@FU$`{?J(HjfDr$3$p9$6cXWQ{Zk3HlRNl$n~aSy)3NY*Xkl zas8g7RM&YB%e##RJy-jqUye_?&C!cm_j!LW`Prbjp!U`X^l)fj+3Dcn>D$xctYafj2pSoE zx32ArRN*Go{s?mw3LZ*t!LinWY_Gx7*q4>JX`+tcW0v|!U`qbc@AojOn*uft${LmK z1ZNE?9lb^X5m-cy@BE{nwmshms{-ZAU1N(iY8XMkw= zvcz8Tts=bS$f+UCyb!s%5S75KZs-d7ovWEooYm4TkNY@-T*BlWdwZ49+yBQB7D$XC zYW109>B7Spt!f0P3#2ksuT^!`yg22IbW?-y{_!cx%aVm+IG43xy!MOjy1zPh>;sJz zJM0KyJ06O=t&5JgAYN26QYLnMwIsfa<`Z#6YPLNOwZO)Q`Hztn3#Q6~H%Z*iI^UO< z@@t!8nH^XM=U_h}Cim+?7XC6!ezsHnl=GwZl?B2R@P0(Mh1Ng=uX4O|(VIFjQ02Ty zAW?H&msB7lb=+)TbZKA*$$^|dRuLxijoS}ogcJDyeC%K%mKy5nEV}BfY@Kqe8NwO* zfMfNV>_Rb!32Tk=eKIw0BobvQ4}UZ^hIx5}t7EZj;8aNTa?=M;XG5%zI+S2Y8WpKb z1;^Pqe;_()R6jcSQXO)%SfOggh}XizjE)L+-@LoxZW8FDO6rz%Qu*frZJ;{Jw0mfc z;dgqu`tI9}N36P6+E2=IEoZ zS*{&`@j>PCj-`6zjyni{IQXKhWFEkewlhL|Za#efn4ytvBu_N7fs*htZsn*SHQ2Z- zh4EsIL1S4}`{H#lShMir2dR&140eS&2?nd%H-INE)wOX`xXC@C32~s#zQK%d+x~rr zDQAawrYpxNgM;iE^Sl(yQI)V(h=OD(S};bmY!T@!AsYLB0)8LC{o>kk>Zi6LI@~-) z3RWQ7>I9gN40{fAXqR*K#vAHh7g`e^leyC@=r{z)}W10*0s%CmP!w-Vwvwlz~2@ zUpC9{<>vt3DRDXI15qQr8F4*^s!Z0zUTD*5>t+9)$6YXNhMDWsk;t6k?!~kYsv)N> zkt~K`utdTsCnG#a1}2#8Kz}bv99yhtZ4*apVY}>vR?>s%h_CmHn`g8)ul#ImCQCaU ziEf~G`s#j#dAX=%QiZ+Yu)Zj0V6s2a3)r5o{f=|hW z2Ch*_3AL4_38w;=ka`m2urZL0Omy16CFN6L7FYR_7Uaq*k!hN*HJdcN@$4shz`7{i z@^p}?K2c-^gTc0lNJXB*18Wi~o*)G1&x_Cl!H~mwxMNl-u<26UD~^K21t?awCFmQl zLgFN;ejtua6yYm@c@3*4lZC+?C{<5kTeuG0fw-bSgbHdb)KU?>7=S*d4YycbsM1&V z(#K2CNkgIg+^+9yg>Zk=UDE7oh-m_160Gp|V^{n4v~X{Q+oie?P#ahrSL3jWdc#r} zb-G^A_rvt!&NVPYqLm*p7U=K@T563$uVM&4sz^nIjM+}Upf&x za+>3nGY;>m^c)J89prv~`@z#?I!w8($5nrs7gyoOeA&rK zQ{No^kl9dHXeNRMKw;>8#F=+|lgzEK`Y8yTsKcZ*r_nO<-dwLqQ{Rrh7J8r<=E6|m zG5=ap_yIWYOT)&>2fMMHI&P@`{yZ!$_ifp?=H(G_Ry6on6~s+|^Jh@xp30*h!l)Zm z9uu0686xNwA?Ciq+som{dX%juL|_s5{~eHl z_<&w@M9Bbo0JuT?G^{9Vvgm65f$rE8^VB{knw1%*M3Ca!)^YV83@RdxJb(rKBd z!Jv0ADT_X`05WPEK43geaiR-QqJC-B<)fsndlJGvN$6sO%E43hv1So#wQ%tXqVG#T zRGXkb4;e1-l>Ot zzio=h8c&Lk6(?-0Da&incbtlXM|>Ck9C+dXgeO20oP+Hkczy-#K~V;|=D6pR`t>af zp)hY_T6cy`-yFv|0n}Q7a~-*}JA&`mS&4w&>Y!y+{74PrstAE=NdIqi{j*p)3P)K%giL!2_LEmb@sAeM3xE_a3u#XVX8? zJ>ssxN)JGHnhyv7-4Qx?=q>i~4KrnK&dXkC&3=eiha>y?Hf6ae}W z8NsfT$K5FmGdevJ+P>#Lvz+Fo#HZcLT z>Yo0TUSca{6^?>5dJy>BWt6Z#0y`ATs*zeJ!ELV&6eDIdZF;|_=j{J~ft0qCYt_@Pg0JJ$yR zKzCGA0zLrUJW09$bW5MdS$LokQtr}BzaGn7UG z6+s{P;v+VX`#KQ>u0q@iuPgHfc50upz5PA7y|+bHvEj>Iy#lU`mtV6DU1A|>``?d4 zgJs!grN;KsY}4ki-^N|kkg+{eVe%9Go(9$Ip&HPVoUQd%TFnTg24-~|=6dvI?N%lk ziyl4@{#|hsH>Bsx0|xM&{+yrme^uQ7a|0kdvHwpZXy`0-k4P-e#fdEfNrPy7yL!iR zeZ+N-wzaJWQnum3uijT=?ZZy8BIt_HRAvY++bAZ3Mpl_>AO)%=xph;UlSbBhGZkUI zgeBQP-_gh2Z~9t-YE?%zkvg))0bFUAj;RwsGO~QKnt65_-jX*mdEdnI2@N){_hAH~kvFD~YIo>U2kj}0m=(VTqQ2pK)$FPDc zq`kWpGBLflDE;+8sE!Xtflt7+F9x2|*hJ9t@2{wVpfU^{P~9#78)8_0c}0Ie0aR7T z21g7PZ#2%q+QRMr>sjKK8HXi}Mx<&Iw&cEMl}W3E45;O4SV(-G2o+>`;$_ioA+ol> zI@>^Gi<$uJ{$NT0b%o-0;c{aBzBoz%kF(Gf1qvw1V>9yvK`cpL0@p4Fr8NI6oZ9P+i7dLB!q3K(+toV|9tI{dkI~fLn9kS#%zS zl0B`bJvg789os#VO}xSH6S#71^yy`!w86-lkh5#Pj7Y|51tb__wS|F;WR~upN%h9? zraxr`{1OZdBw~_nyN)+ieqT}2a?8mabsN39$r&$swtov8XbCY`L0r!G3^Gl0<4Y=} z`w`uZEo78uNjwBYQgAZ?3fpE#NSSqScY9uoH#!5vYZLg371uoPAeog06!u=3i^RB} zH92yVD@=PZB%Ukuf?ev82PLsl&zDgysi0Nen-Py-m#4E-7&Hs;z2) z?64%}_{4#)zOk>}Y@5TMgpi`*4T7SK*5_70K7|YbulRaxbid+P3uB;*l{bmZUt~s56 z{beZkEIG6S&ZIXm3KcHrvznp$G-T3^H&PLp(Ke0#~v{(b}kL5PG$HMN;Z_fIBk zUCVCW6FCf8v0^paC83T1c3iwyN) zV|$EV1Lkdg<`E4qV+`c_^H4&& zCY;2>V|OGG!IfjYX!+UmkaRpuxR#g@;P)utl;X{vlLlBUp==-(|q875YBcOy2t;xR-P{#@qR2DG)6WT zwvCf5SKlfiRNp0MY{K~;%Q>bVdy`G4ZsDg?1xymTY#BJ<(@Q<>`C5-k$z4;+_e^=b zhH7SMaO*+v>_-&L@nDHByl9g?E@Y>W>l13U8ij}!N4gD{;p`^^+$Lka@}52+{vEU& z6!62?0MOq2&!GLE|3#PqKnobb1b~)lbTYyi$KbEv*!2HW`S68J=z znp#D+vbLIVLpGv7e8nTkvRd_5A@4Rcf)><#NFr42$OYdfU(tjRXt})Vm+*o%2U+D} zGFw8c-u1P^J<@-qAN&)ve7df&^B^}dUx4(I!P$WPJs$=o&%wNuTtrR2UU!v+pFdYL zcT)ba0O{IOl$#aPQ`nr_Ud?C2U)#P~{kcicT%9!P@ku|@3xVG30%CH?)iBta|OVrb;8M^qUj?iuSu zow1A>8Cr&64i}U_6gdcPw&>qEN{CRdqdC;-Mqf9~4T^BX*x8a$kRSblKR z#q2}_%E$w{V_=c+$y9h7k<;) zov5f0{fVIA5+~-}Ot47iUFE;J6lNo3rop?sWnMu!#>LZo5P>_m;(mb?BY^M5V?;<- zhSxHm=F)*UO|oXnFHDpm5)1el>g}2qZU=yiULE)PKvx`+&TX7#H_E-Zpe;Ku ziAt~vaEUT#D_MIkMr3GvR^u3MFf$5xXC#cqpk}R%R!M`qg~zC1J;4O%#@76OSDe|G z`LG*@zqiPQTsik^tF8|T!xc@ywhti6VC{1tu;~#`B2}E!SKjuD+HCprU5(~UnOGA) zeZ$u=t+!Y+VbW7kL=7DQv)8_nNf-TCqZXjBP+MC|sfe6aY{Wm)j}W9N8jEkdqn$XT z{Z9J?$wfOtb}@17ubU3eC9eKAC^qFgHR%CqR)v?8_ zh@O%e3eACcXxbwpf@3ped@BlqBFn}J{UxvN`mJ5jDe0m+=Ylg>lRnf<;0{fm*M~MV zcsApKS`M3#^G9ePV|>N2)A}Lxk1QJvW>GC|NUn1(Xx8eL3Rn~2G0@NLG=ZoVpb!Bv zq^FG-DUplcbwC}P@Mc40tLZ%GsXo(ts?X(5$W_CbK1WIR+E#w)DNLj5j82!yT1QR2$^wSz2XxO{8M)YL zct;&5)l)|Dxf-0t?;G2Zxnta4MOW`d$zRvf)0l=rxy@Ea%?zIAu#`q1xW*_W6kjEG504#FC9zF|iYqMW?;7)SpSlEd;LBmH5 z@M0ybV%i>^DaT~k>@Y^ZglMSBrw#|`I7g1rsOh5wuk>N0$#1>AgLS^qty(^AHNX93 zqI4s^W^5M}2*?>wL2&-^Q2&w#^q=A~^;B)Y0s`9jE%|3`QD)_AjusxtJ8w;#=k}Uo z6IdfQk6g9uP0A-yPUDJw`+ZLmo1RDpBr^bK#DBCUDNo!;KyOi+*kOr6nhXxvG zJ1Cn7W~P=KF5`HPxve)QGoQPjyJp`vpMM^>hivL~0{b(l0-c0uDuMv5M*A_g zT;8_?n)lAE?st_*W4eAV2hThjs4u&{#J(2m<}k8h;-Q@U)sgaaiRY5&v+>Yhmfw%R z4G)uix~ggw*{eUCY}gA1#HRlkQTpP+CSmlhf)0eDuhXL3d=X(J_qjX{s_qm4HQv?k zL|U#u${n-GK37QfjqL~vg+WEkj$m#)**-Nx=1Zlz*?NapB9ZQ+N{~{$2J%iu;HU4Z z0AUVHO(TcTMu1POtGy3B=G`Kd6}<-U=fs=K2(^{eUR)o=b`aH7jpgl z_~La+OLSGw^i|I_Ri)ZS5pHN*4g9Vl6i{8^TY_X%sY83m0%@L|dqu~E<&%k#NAo3ExPJnUDY5!<4uQ|MOCSB0sOd3ilF4s}sP;GS?; z!&7EemBZ5^YPY$tP>WlCV)uPJ>T#L03}v$va}fv9gJO0VNJxVjkI{O-|Fl>$u4os$ z-g-;-!!h&`TA8ZB%`kRL8KFm_72*-puD4p0I^H=Gp336agI|!do35W!t?_J(FI)#d zYvrAlkK+DJ(48oI|IikXOU9PAk`4C&K`(*5Lthq0w)GX#`F2O+2!Hd!R>8#r9O{a< zD)^EbY)s$Bw}2t9H|cE4=H(ljSg#Mwk%yK(&bqnCfNfX+uWz77G<^!Rts{CnZ8 zt6~p;CR(56=f*PmR@%yB$+`67@3WKq0dqVOOBBzk^Jb$Fr4+h(MClL6w|wc}Yy8M! zzl(eAjs~)ll~(wQXJfv*Ob`lTeIxHB793ASrw|P#wN|D*o3x=@?``+qudax@1FVD0 z-Tvrtp60#k{4t4Fg%H4i24o@r4{Ap0V_AN7la#I1&9$vEP#bmPSylEIb~?~j`*#id zDxSxlu1B+tH}}=nID4z-nAqm>VlA<11g{&$e#gy{oV;G1NJsg@4xB$&#P$frUuQ;X z<3A2!@Y7fuRdpg4OLdW5cBEb_T2^wnX4BZwmUgM;I8!i>dSnsn7_M99u)|k?L^)Si ziXLIo>PLa)6N_;B83TOSkRLP`%3Pb-PCh0ALd5aAQA^L^I=&0eED^yU`Jce}C?s{7 za{~(Lqn6O{WP}OhdjcR3K8zvoJckC1z;7B@zaVn$%rv(C=mLJWWm=|Dt{^;o@3vfX z!LEI-U{#cUM3P|@(j4?N8g9*&`ML-YXA2?%qw2n#XyOW_4A(b#fq2)_*nCQP00RXB zz^Po@G*VT54_c)P*ptgJQC!wqssIFBO3j zxXw!Pxc3uk`7h8DrSHZ;A85Gv%3R%_S&ei=D^4Iy@pzneW0+IY$P)zE%`v`{bM6x- z$nyKj^L|TLVMIYsn`mqEQp+}j8&+9S=~o&VU1~1d;w8_Z71QP@eoO|gl#pRsY=z() z({Yu1_uW_&QIWX1)Yi+Soqq&{_NqwIq{I`sV@u`mWvl!x3F5dM8znu>Y0uu3wlXkm zsQS0g7+f@tno_NiCt~!-<6xseVVT#nO;h!5=0tPpJx_)hsT)a)N=%4A!n$@iVL~0q zJRKD(Nk=2CdYCDi8K7Fb4f?3KQ5#9r$J7(WSyIWWUijoZBQs_)ulNqzRPXB0W^pbZ z@Ga>8t5EXLKA@RK`vZxLRuaea$824$ep5{=Ybl=}*b+1`wwM-S+cgyf&e3+$WX{$K z^{GJDIY(D2Ioq{| zq~DzQu7fGDE=w86YtD1S;QhHtIrHt>2R9-`Eiejm$e6Vk*|VR<3v;?}!Mmv>BrEfc zblA3oC0Ocf^LURzD8{(*OwP9+rE`@Pkzsld`6VElnn|+*Ak=%J2)rgt0!@De+oj?f zrsl$|_;P*UdHRRGdjXxGXG2NnQ5AicuS;%-;$sm?`ij_y>#AU6);5vDMz3Y+$4J`0 zWW>b}@=XHX{GLy6GN*-gvD87g+<25%mad%L2@=INO{L4(kFMUyC=RsUV#Q;nk+z#( z_*wU4oZWMLi|RxctoO%w6t7Y#TYYZ=#~&kmh8vpx_NZXueoJVm_51s-_Z-A=SHnQY zG=0No4vlv=NmY*SncX5KU>kAmPcEy1&o+NwMtytV2jYj8UCN-=HIL62|2oP=_y6Zi5VG1O3HCsXom7`^oq&P<*=|8Lc@(_@a9;(${eK;{`5&n}|6VKq z$H-=p|5j4fl`eP}_44Ie9w1ttv!9mEHmNntKiq_-)1;h$R%`W9a5)vGnSLUL27lsp zmj&K%TS`dA7-IyZHQqEz{Y=K#!Fa-G0ZX~KKH;Sdm5knTb&CeHe`5alWAp8OOFxfq zW_@IY=E(*Et}DP8Yjws*6_712L=eB?x1~MXdUh%{0?uQ(QbE$H(UOOUdBUsO3tP+} z$-cA(?QHF8JQ4e`*l7E<7#w66Mb`+52DN`fG+It!zvSMe7tR*-G{fMvqivn62EM)3TE0k&87lYS#1?#R3DC@(aJ|aA6(1qQA=uP- z&6`(0eA>gWW|7EHnRn#Y`xqHZF~i;d00XI;+Fu%zJMyAnk|TJobQ?-0Q4)dZdB{J0 z5s*mjOkkJZ^`c^<#ru}L2X=CLEpw2A+C31D#kGqE(~6k$2losnOUM6pH;Fh~c?TVb z54xWQAK=Dhew#=aOa@}oT)1#8W0{hiQyo>!sh6A4kb<_RinlJq0Dn#|$!!e4jSdyS zWqN8C7d>tsWpPl3p5Xm<7lxU87r##jsTMt%TLIY+j|MF<65p=Nm72hZQ9ODV*jtST zBf<6KbH`b^e$nN&zT#YX{_UCFA+`knWjFXc=YUdQ+SnV5&V3!}m}Q*K>&>X?=3Lzq z?uXls#S83~B2tcJ%-xR}y-{wxd+wxe=A5f#ZE3a%(Bv5?XZSW5uNtyIrd7bZE2Mlg zo`vkZOmxEEaUO(Y_hU*fGBBpaqm1E?ff^7T8j|82Fg|y5TYOX8eiL2aJ33p7 z1?H?jSj}@}H0suA-BHmGH?31JBau?dSxQL-Z1_2(13Y+75F~n_Ml-`#)z8;Wf6gEm zcNjj)1$3}BI<{Q7Yy5R4HgTQnm^+{*{GP*u5hGt0Q|X+z8+!Uj%F#qQs(#Lg3kBabRDw=AD zRD6ErVCX9Q+&vXG*$%i5XUY9=mpQmFHo~J8(%MhI=8D7_bfkAKy|pZvF4a#${E?|j zUCAwP`rHm>K1*Jv_bqw1o1hSdS2(>0LDkpgVReFlLpv0a$x2YM%fAzD0^h12T4zdEEo4?&Z9P^qAud@rP^SN6lIG!rn291z{G_C3UAt?9}b! z<@(q%iS$42l zdOwFrv=&N-zV;WU*aD{BD+JCPbvpJMstM$lksfPE2a$|%wO52v>GUd?WBOz0q7;o~ z5`Kvt<;f+t51M+{!G-ANdT(vN_4Yk2ALkxl?C+<%xsinWh8kndjToT+g-`|w8~&>) zYwdfL;5(39mdgd~)|KWwe9UrQ^j_Ey21!;GZn)Ic@z5i@HyYEoM{7v%eGG3C$kA^y zBjU_Ox#wi05iJ^wGQncRFNj{PR1hKjhK!RT!=YLO5acU$HI;ah#OztPsa5PP2*u$h zjVVTL#=2`f>*BH*Je&ihU5N9?aJ{-XY(ukL8!GD@LRDI-X~sclDZpvS+qmGo7x`uC zT;CFx_F~l6cBrDGAq7}K0Rija^RM7AgW!vDWA*HyDl`mk<^mi*dr*LxcVcY7%sU5& zMW>#j-^bt@M=l5})umz18CzuQ<5#P!*qui}G7v?3=JeT+D$%G*kQbi#qgO6;2| zlf^XudpH<_81ZK2WGU~%39AAp4?{Q+p2~bK)2#Kin_FK4D7sShbJK6%?U-7|E8y#{ zx@r#@GD2is&-~yPpUH7NwU)Qs8+lpXJ&OIUhraPCw>*Nq7 z$&)9%UgNRL`jc<(f;C(Ls;^d;?j#a9nqP+C0(hc7ri6KmL8U`66k2QysS;0)6()n7*Bu_*lcBf;4i8#WwAKnBCrdy`65 zS;^(F37x`bo_WdWml~YO`l#q%L+|Ergb;;9NaB;cm&gfO7^hxt)P_CwW&TgUobipi zUw%d+7nz?4(2|OR{AMD(jE^-fjsv5*E$nkwfdMDY5$gHs;9N1{^IX|@34Gywx8@j$ zkNdbbj7T>e-If{zg`s~{4>D;Hr~hy`h`c;e_m1_O_iuK|a6b~Iui4dm#eK=XGbI3o zvAfjD+taMoAS&_<+`DdYowlHZul=E9IuHuTzKM7Cb5aYC;NJ@b+oX}6W1>np2KqHh= zbd-?{Sn+dM0@`!Ury+bGB(x^R&~LF%L*_Rpq+>mVzrW>uprEIJ(O!*eVP1jlaTzVx^>pIX@s-69do5CrU zsR4qFsK!ywBL^IQ&tW3FLPx8j;e2^exX=h4_H3LPn~&-zcJpZEGK46{RT!n{46@mn zFgk&r_vaa?x%4%%7(J!cgM6C7m@s|vEQV)!9PO9;g5HV+(up;*i#h8h{tn)l&NxMY z2Ez#s%(r8vTV(J&==!;nCRwu@euVj)>RK68>r#bX50{cn36kj7N{kq zxFq9XO_Gv_LzP&r^{MX~0gw>A;=C)4R`0U%#0;`Ml$c^W)+!Kn2JdV2VC5ucw9^ zV9Q68u=&_fUuZq45Ig47VYFMuW?OB}!`rXeRQ+@g(a*=R#)FWSb~V0h^_vzJF)Wvs6Ifz_qvTJ=Ia?C(UjS}od|Kk{vo2N1d*l! z@fpHN7)u!HVp5mI(w3y?n50~ObT_lPk5!>ve}6)+Xr>;b#2u>IL)KH&yP*g+;i$0? z1A)=JIZMkG1Fyafcgs|=VCbpDP@4ElL#u+NsJC|1;He{m3R^skSKDarlPg3u8=bVR$xul)HW0U}7-=>}s^x^{%pyHE5tK6tm71}TI(JZJ;*HO96>vN7j-)}QCHm07|en1Pn>yl?q^G=*KN_hB2_umtxCa^LTa(F zQ;`Z-;d2-U+Iz_7rhFuhUlgJJ)cQgo@mmtmz-ep?zQ4bIP3hP+O9q^3cbNN41Vdys zkZU5?tF(I>5^a+mSl@!$1agw7!PD>r+XvwUqdK@kEU5a(p_3=-}+r9$Q-8~SD7-a zg=I%AviJGSC4)I?F|#E(NfuWhs?Lb!>W`$xr;}KGRDzf-l2l{iE9-Fs%0=Y?^bb}g z(Diz~g`8H~0gcv)Pd?47{27_1Qw|6htIt#U;vVO1pZ__ZW_AJ)(afWqV4R1?g4KvF z<^#ikNXPsgRQyYpS6fu@^9RGusKttAlg;8`<%8LTN5UA!PURMhMP>YX;O?WDC$J^Y zeFBtofw!y_Z>6Zb#eCS+Xb1JN8izkiZSEhL8z&y(9_m&IGCNcL;8k_YE9{M>6HoP7 z_)+!^o_V#ZP=@S07k=p0kZzmzGMIWh7gn7)s`DAviYVHC|7xUkG`B52{;iJw?*upk z+ID~KRpKilD04dRXanfz^-B!bT}bI#07ciyZ5jNK#?)NK6#O;NRv(4`VMRzwGw7v0 zh#%wp{-A+o8pQe!D}qk_f2OFPOW`CL{d&i8V13q8?=k1G@AUjr@73weZHG4-D3E?R z5aBD90x-}@fIimtZAV$Y<&q+NY!h{Vy=>LC$)b-Ni`YfwbuL*q$fAPna#j}2x6Ibd z8kyBroh<@po5mllzk;?rTu8b1dbNfV^H<>laNci%MGNN?HIa8dsNyp=Pt|AQjc4<;h=(N;EQovr&Ce zm`T%fDDOI{Ke-zFcFbgzhTjW@qJG?XjY_Jt=QdJH05FwlFiHnIuH0JDB3qIT89ED; zv%z3JTtBvwC{^oiJfjNlzlF7~KruqnKC*l>I=|N1yKg)85HM*mE<|3c!WZ05kpc=}moeE-@X?pK zYV6Pl#zaXA_pZbsTjaUml@+yKSNjYAwc2W1r9 z8M$G)C!2fwi<9UqEbFy4o59fvE-dJ9qCO9>sP!Qd&71vnEU&F?Zeob{LN;;V>ynD1 zRhRetiaUTEQE5NNBg}VO0BLFzO5{(6`b5=yqAi!Wh|A@FI4gRwYww2lS^MSi0&+!3 z+TNV$z1xCGIugYvx6{$QP}VfPN{i^gCw#A(V*1ONZpb33XEGkv&uLh8`fYR->({HU zoycqt6%!9NM57TU=s*u+B064lIav;PuVZGL{7q~gnYr2?jMZ}SxZ)LqS2h1(4XWcg zYu2Hij^b8_mS;h@L&TAovm@3jto*rQGlJX85I)@Zv-nl*i%mO)oH^8^*GW8nUfyQE zk}G$t4#1h%3z(Lj>-KPwMh-j2^dhDu@<72;@_Gxf*rfMevR8 zvQtI`4O){Rfx!iv8CRVy>A0CFGBul z^59b?L>$++=|)}U>ppLw>&AN)*oB90laIQUiuuB`5}VkGMxtp6*Gy~-+E<1o!rKV8~t(@L}YIx*N!S@kUS{>;yuHl6vGG>@#t&0*^GjB`U2 zTK=zp$sm6fZY}zIDgEz58UMzSj{P4}df@-Hl*SRV9{qbi`o9ywsH>uDGp~l$dQQ5$ zu)9`32D>np4WdlIHP&n)l_}!1f2*u$OC_Tf2&qK5`3NNadzQ^GGjVt*Cp8RCRP`xU z3O#amu(Kko(o#96R2Z3Bn@tvqCgp;(4a7zqJ ziyB+=A3l|g`pZmCl)0;V2)AHdOO6z|k{{N8nJJl!(E=o7A5pc-=qS7LoN&zf4F#zi zzg*$1Dy>FH4~~lGL>^jO3pmImZQ=T0&*u)FVFs!NM-!Rf1!dC6v>#D?bPQVB3tAnc zRa+{57lh-=jM|q7>O-EKr!hRU?bfKT?`lRP+!4lu@Zu^6>a`69IEb_~L9gV2RHjgP zEC0L#Hw2sAr;+X^Ob6)!fg*`trn8Hsw~MW{N!8k2IN|a%y<0;Ul-)U8Q!hp_rII@= z@1?~LFCRbutWJBRP?-u42l&zNzwamm;qm9DnW-;I7^+^zPhXgjkW>U866`IneokZs z7O`-(sHY--AP8#{_a4RsFSG2S3!7-?;2`|vM;DD+aYIbI3}VK{z+YB-%-fdReQux4 zvx~33M89|~yho(uFf@)H7eaNnhHIB{ub$@|fH^;(pRp>(P6UFTRDt%)K>9*=Kzb(q zsY?OPzkb8PWqU< z40%jJ1W`him@a_Tvn>*hrhQ8Hn#uH8X2j{9dNSO+I6(-U@0EcSgarwpNRIrLH6{}% zCLi8y7JQb+x8i<9fw0awc}$hxzi=Vljse&CphT=6BvHNWhvRzit>mTp>S8`^@)Ar?Yb+j{lr5g3kFGhvFI+IFZ{z>N#~o!;jZj$$K;PiMkD+OX*9s z=FB9X=+N!3?xgt^1sq1omADF=W4dMK7jTPhTDN<2YBuo!W!;>@;WZ|W3GUS|JR?f@ z8xbbn=nd7$LFcjL;3pK+V-ZXMx!lt4>FgC3>E=Vxw<}F^>hn?LS{}Q)CyY$GK2zFx z#R=D{7rEx@Zu_EJCE!AosW=)%BrY)ectRaWuWly-5GrB=C-ttUvzsVV(@KJl3sd_T zJKd`{Te*uj+i4$)fvt<=RKqb)f}3kW!M3eNQ$Iwv{BtI1QQ&E+Yg}T+>s$~_n9d0- z)**F2)$;6}a>ZV!pykZRPYI4BCh=?s8MExjmE@?!4I%Uiu94Z{QF3M0CHRoWxXwhT z{WSg<_~HO{8hVkP56+tDzwsZ54)W_i?W zM_`OO(mFeUAzcXh4@0^vPR)nq?$06Qbjpr!w4Tz!Wgbm`q5wmRLO36nK-w4H1Fj7z z$sd`7i`rpb;X>K*;Z0z zAsj!KQmff=W1UbEk460}$?nZ-#2DAYmz*=sihc%^69G12AHpjYPBpdolgnS!Y<)d- zSnEw!c&EB0L(b(5SnGD$L-QUJ&J52bptq``e?eM9m+~;x zg`h%?$6bav6upjHpi3y8DIZ;7{Hp~eaZsxoODsPj@k?-~$`Zg(4LIha20zG-hzs0V z)eEeYgsc?t#6@i_NYrH7w#@b%jW+rb)pYYoq15c7twA`=Mo+|kGBB~YEO(aZ@0n_g zhY~W-6u@;-_R)cVITB^ru$1RFM>MwAEMnpxgw;X#z!rq|8Z3bpGEMW6D`g;4<59fS zP_Ke$z$}LX65yM(;lu%@-_SAG#4y>!(%7ZwnzUSEy1N~(8uQ7novyx$6HTeq_ALMy zjkFxM{%p=eAZMM5mnX6AeJ?Us1UUz^^;j*N(|W5hD9bPh1tey{TBw#cmSWRpK&4L^ zgO?cI>K(H>STk1c*Rqyf_Q;%Vq-!wZ^6|F;96ecolW(Coii<|Dsq@&huC;reIUBZ% zWpu_~e`vojhGbSZiJuul_Amu*lXqoY<{pKf@2{&=r}I^TCKI%$JMrX0lAzuk)lM;} zLBUpwMWj|lxd&wJY5FO-VDAf4WQB6AhswFaxq{PO^7~v%0#BFis-pU!1gL|*GDPPR zsMiq61cg(dK6#^v6w!9vWke=D`pmImwrxL|ubq@&`Aq(n2N!@31tpA3f8!}a$)m7w z-H_RETkhY88@K~-)W>15yrHRu5Jf@A?~ntEt@!x*K@x=NAqf|f5rWH@w4H#>0CB?=D2E}shU>?pO@S`O+r`-ti8lUKTPwI-j~>jOvioW5C;FIMBc$n`pI z8}~ia!=CdLOjx883p*Y>$OOwF$U064mG~Zu+J($pzR6575hL4;$MJgBvHuxFBAm}aWftR3NVlmxA>ONW( zx%vetbg+y4b|Rgc+oaeHICIJ$-Wy&i5tvD`%fs_ zou}M)vV3%%&lSWAb(MP^gz%_(J)&+R}_776pQ z@Z%2skcttxM3Zx2G1dW!{f z2Dj;myQ==ZG|u#Q+bm0gOKsNfB?$cT`O>RF*Pq?m`y5z;rCl&IE00TCh0Weq>$lve zX4`?Gh0Ti{L1ouR$9~t&DaJJBazAqVM(>AG=xkl%X`~QpWsL1dSz2G;VgK2W?k<^9 z{d*Dp?^6-~Mnp&amx#{z`Ttr(YqW<={k@3(j~uSQ&oTdNmJih&tB=Kh%bKCr-BKFk zf~@P={9YK+JSBkzn!KZ&4kPt!#p=VLvSpp`B$1_65_kW%jyK*!n2gX^Z;66f{O;L_ z81^^4OgW*7q9h_>;)su?lotvuIs~vMJss=wn~i_?(N|Zw-nmbD>=c`<)=Ym2K?cGF zApmK*)fk(Et>@P2f{UdEnKhW`L2hw4+jdI6u90O3Y8?zHc7ay4Z9Ac@nPxMWOPR%< z%ae+FU7NTY@G$L{Dr`xvdNd@G)l&h6QY;$o-mzG=ONC9?q*@~_Pz(rGAoIcI=?EZ;A%;MSYT9+t$-K#(3FPHt z9Dx|}J%1az5NgsowM{IoO>DVUs)otQCAhoQ^&(SQZs%c*y*Lq_O6+K~ml*%R^bp>E zNgN`v(QK9`$yDF-)HC@fd7Q;DRmS6*`oeq4JqQ*Qm#N@O!h?$oHFefs35Xr)rOj?# zwY(YSe#h6W=We-X$9lJ%h0<&`2zA4#Kg9 z1pUjLsqM4&s@GOdESD|hM@}*>=e7d2KI1U?sD6<_>y_-F@^_z+ehrP5L_`CJI3OkL zoe9T=G>V3=M|D)rm%b!AGMQ1oIpG~pBN8wjDB~lM5b=i-9|?|lY_Qd_ur@d|?dvjs zv<2b1p(N#!oQs*vum^?f!@UkBNo)}3PKM{*8C}09aL~N^7HSppy@+kkm-0L7Y`;}} z8V|)eL=X{p?S6b$G#c$2ALNCp^;%9cQPoZJJMXOKyBX+5<%iFq^dHfLb<~!!^xkbn zyIsNzW(#a8xedmdFI@E?IAj*nSH>#SE&VQkPG=gbbCWcHBoW$&IF;*th z2R2hWL;+*CNk9(rVsX#UmW@5yyX=RVZr-Fe^yJvWUuy?6oiglBrKjnZOE%r8Rg_oT z)!j-VmmQ7C`i)N8^vNL13%@`KZ8r#P=0EJ{it-l>Kr@nc8`GK`+bFsw!(=hE zr;qxgqMfdwS@!S`%Cb^8`(GM*ePnKUwCp?lk!(n09H)}w8}9P0^v06jN7H4g>|V99 z=Y&W%Fgj65vs_2DDB0eMp5xIiRYiaGYBFL(W{XC$c`o^G5ixCnq}mo6<$x)J2*5^R zl*X@mwK-ZnN7SJlfW+z`9^2$s4>hIeP!c1$T_MzbaX)Z&Aef$KChKg|+r`?Y72?}H z5+sFt{SAEammjULy31Fy&XU9Y$tU*Icm_ka#aQNo#?f4YCqWW0t%8ojnk?+DqWJVo z64-L4m#D#>xlNRpL_JiGf;Z|F5=PcF8F5j^ZQxMjrL}kwL@prGQs`jS|*(;swwS@Z8j^nW1q z-wt*B1EKec-Io7bgq~>8(k?cr{%;UE`6JO+x*(c(?>`Y5v@kb@gq#rdPYCVW?>PSG zxw`ZA_q_Dn>eiF%v|cn`S*C^~fxxPU8K~E~4;qZE;}LbuO0{auQ-^-l#o1JgdYwS! zY3UpH&b@|Faqf{dx2m#yys)W})OMf5-Fwik+0Dr>XU@i&iRr3KO(0z|`^AVG6LO8h zYcItW(r3Up88Ccw(P>rct)ScHDct2uAAVCIgjB| z)8)uEG>?;F_?F8A=;?J~?E|`898P2I!-D=4CvlO-L3?7|hf0tQ+u!qK^WMQighQp}+-jfmuuiIUv2Tk;H*y*=cBPW9e;UYwc3COp^g#gzMdw zYFpyZ^PaCHDfMEkA4SiR9_i}I%O9se*itl^hJ8Y6K8NBngh)n!m%ovq3q)589_#es$F@z09s zg}sD^ep^+0Z}^AYuWHNpBg&q5c75q|{KIAc5?uDygURuUct#iCi8XepAIo zMjY_3-vqbs`VF-Hh;EUF;tXl1@$k_OyXM!;^Qtbf~_OBQvVrM$#ZZ{izUKK-vjoc0Jz>QcR+~>Su z)`R0Gh>nfw4=7J4kLzP{Yr~euV|w&4dY5Pc>G3FpOEA-?0^P{>5QBbTq&zma zOWyA1s={2q7Lt4L@&R6iCcujjJAJbq_Mwp9zCckkSVbggyzZ^mwO@tlg5{q5fJzYx zy+h#%hC=J6=oi&|qZ89HwC+v%i=)W^j-=;7GGtK0} z2$P``>*O{mZ2NG@j#41<-}G5fB~Sd8CTd9Y!9xiDcFum4H{f z2=$Rzs0P>6^vn#6Gtm%=s&=wb2$l8=m%4{DOy$veIGt=-Cg9KyMPzi+RO<9Eg`2Q* z>WCIP*aZeG{8YUB#mkkOOEt&)K)uXpjtWD?fM}#Rn+1QG#&`?-V;te>q$l;X`=w2> zGi*`CVk}g1Llw~0b0dmD>QrB}SWu!LAX44jM+9H8^N=*sweZbyQm<4M=IBh0fkKp& z`;oMw-8OTedDCLG_Jh!DB~7;b7xMZQ^TDXjkNpO{JR<)1e_&KDGv^BWN}BI0Cb7;= z-z~p!$bFR@fYG%(hJVJWo*=Tt-;3zKF#3Nx)X^CJUm{xb|G9|%Jne+70X#%E0pwZH z{{PPioegarY)tiCOr2fmZ7uEeZ4Ev2olFf)^et@-%}w?r8@G29s*RyvV@L{n)FRNQBLn+Got-7;O#%=^ zo-=$OH{>!*_t`M$$0!zV2$sWKi;}LvYFG;_&gi&$NppKR;dz|vJj2=Nec5x2pTx;o zlt?maiza9S3a1o8D1rShDDaWtsIx&%c7`)kAoyYjtyY8P?=>lpOZhz~DI-Wk_Xj@7 zdgQs5yJqA7^}`8KU$@rb2KaEpZ{r(_4aU^4c!_Tjgi0LaLg6bC;qqUQeL0eB@t9!9 z5xHhaCfv=-iw5iI`@(y-nNfnHmypK0k&TbD;j~yb6gUeKyx+sIJFZb2$s2+qMhzzJ zvPdi8Er%c#RAptS+PD$EgT{zz-4Y_RDYiPdV;QB6^!W8MO!nbGUdrt}UQ=|?IgK46 zbVDjWH~+*2?}0-Kp*l4Nd430Z2yv80gHlO%5e*Cm=c5#OC_%!w7Y&>M@=-`nJZjZ) z)~=b*E=a}h@4W2pW_4R7B&|n&Ls4l58iL{jVF=*<0J-J5GDMH94>)axnFe8?T|-1& z87$D|Cu+C72EkF6m3MQS_a-j@}kA&Sw2? zIDI9XejbfTPXqKRe@Z4|rH~%us!`F~4e*<>PLfx~Y{x3zQF##yIT zDwwW`$*$DrMLeQ$Hp*>NZ13k7?koWzSDUPXfkB3N;@hhAd+=#Jfg*XrHl2eRj%RqDV;S(inF`pE?MZ?;x3#LNzq(=dJ6m zs==LSu$}x6e8m*e<2G=mDk*H#6vvf~)Ms|lm86(8Na76!3Zv6r1Kk6^y6y$G$2PHS z@R|DDSm!x1aq4M~Z5Ldkb6NIM7Ep@X35LJ+uD1qlz&s>->$0w55TyJp@n=pLGP9<$ zPPKfe%W;+G+>gt_*-DgYt!_q?pM??98`K8ssU^X3RWCd92J3`zLHwamXImRB*<7Vz zD7;auxpNX>xPLI1W6T^nGB1%)oO9J6E6&TCeW-+Dt+j@4j;!} z5fYZIJjYD+n#d7l>y%D)4X%O3cF01@xSln}9D%LEnNTG>oh-%d5_A(j>~Idn#oL-Ael+X`LDeM><5Wvh+sTa(;3I^8aX9$-a517>|J1_so|2;}~qLGc?<~eKXwH#av_h z+RZACc#Dw;1*x>Lc6B$|W}NGhuO{OzrV3d^tvbF#Fn^h>OL>%diL_1sNUh38crpNI zeOs)25OEaD`Ep$J67s2EbgHW5D&kT|CeK1r2}4`kd;6^=w6eYS#Q)FLELRx|uO3hm zEdGy6!oRyF{C!Dq_|KA{ZH+Y+S;tRpgVbJ5c2G>%OABKAcw@&X=6W?lV148^(;}=4eV_9l^xmCh>xiNMKaK z{MR%yXCpr@j0$USaB-3^F$@=-c8|qq#�TRR`qn2J110d)hNXgUyB!E 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 literal 0 HcmV?d00001 diff --git a/test_conformance/spir/atomics.zip b/test_conformance/spir/atomics.zip new file mode 100644 index 0000000000000000000000000000000000000000..6c0673f99c6dcb2ee95b2d4f63ab52d1331ec267 GIT binary patch literal 159717 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%0DVN=qEr>m1nB83`1aqIZbRE^b!Sl1OYBuSs!a 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 L;94NdtKj}0-|tB| literal 0 HcmV?d00001 diff --git a/test_conformance/spir/basic.zip b/test_conformance/spir/basic.zip new file mode 100644 index 0000000000000000000000000000000000000000..d60636fb319ee08b4e462be13a5e9888b0e907a7 GIT binary patch literal 2583318 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�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%0Aw@TZ3PWSECLF zKPuiw=V+}hLe*T8)O?cZv-ZAux|7G!kR#yFVZso~%tj!;0V8GVp=Bb%@`DD@jwKQ$ z7?QCmKON70|Gp~ybt!D8wQQP;FSCEBH=@4a_VE~Z=SwR4In?eLai(Ja=8zC5Zig7x z00MpYt%q4>#HWH^cgRI0qO&E*X3T+GV7*3#HAOm1gCPz}3>DEQc#;NaTq5XaX@Su=9JBAGYFgu`PkgqD&;qJ=Z=}koVSf7t{a`l?W!;qhw#a#@>QHXGByTFy_>nb5jK$3U2+4nP)u2Qm+ zNBVBZUA4-KU*BS%m%p*Sbfs`J_$*en*=1i8&3yL3ydD6s+HS$OL8m}T4OsE zKm=O{5WzD2Z#|cP*TDV{q$EpGP%e-Oi?618k0%X-vzFCSJ|HZvj017V%RpX&)jFlw zI&J9FHgA;$GHeL8sAk*Kd;6Cp5{I@FpphgDhmHdS_gkLgoVtKDPZI;rNl+samX2tO zy3K{3OF6gT{-@3M7j1DSqNFt#+w4{!h41s0i*{x=p5uS&NLUEMeoV{|W$hN$IuAz8 z{gvtSU2(4mkm&<#Hl>?)xU~KsnLen7R6CQW^LdO%-3~$+=ZaRnY(bUoJ$uyc)b>d= zHw?ZLj{4Pp*Da0a2HG*6l*;LWmG;*Q4i}J{QIIeXyxo4kM`E(?o=9)W7otcqk5J+G zJWQ6ACQ|otZ+mC!Td@ZUR=ugC3ujC6Y9n{XJWYKgFnT&c3CrAmSrva`iwbp({H-SD zj{+9?kj)DcFfFzQ5Jk5C)s0x&*_!=5)aOr2%>U37^Ir=|fCl#1vqrHAu#i-R1}r2A z)0dK08S9wXBg})Z5VbBw_y+)f%Tycsnm74&jX10?w$xJMEBV!?ZE=9ug|zb<)-yb# z;J>EDQMs!aN3M30${T-$`b+~teOiyVJR^&5LQx>~Lje+46<|dmpoZNT59MEQ%(~b) zGz*PR9WVLHg2kCXONQum;|#4aaRQa|)ahdri!jqMHRpayF7{Y*WS3Ryg$~l?r)LYq zd`JWAmMqXf7PXi#oV=ie>yL=QA& zJX;l=eJmHn2spdiT57eM?x+Z6u8;C#1;peUGB)?jQl9i>7S-q3UE7_4`OnqK6(C12 za4Hb>;bGwZANJn)I}(1|_KwrBopi^x(Xs7{ZL@=pZCf219ot67b~?7%(OcR3x#v7* z-*d(tXaD?;QQyCyYK&Q*wdR_WD&?_>s$w8YGb?)uvs*!0jvb0I1;NS>7Qb`Lu&)uK zT8wuAEJ^w$ENub!5eJTnsbcS_9;anC#lNF>vut9Oyhu_*_7bL%{&XeTFRq;sYkdJG z`-FE(kYlaGg1gBHEdgMAevFW2u;BcF)4%&J5*l2up*$|BOQ@ywj6#AeKqu4DVhcUW zWlsa$B`06>C6ycBN$FN%HO}poXop4a~*El-HeXpg(dGVLy!X%1Mllk;;v9 z&tbOnC%I^nhCcHrR#ff5pNkGzth@8Bpn|q~F$$TTWEY?^(BZOnqG-#FvO&?0n*Xy= z(zsaAbGD8bwTx)gl}FD(j) zyjMyr)5+F(22P7J6Z&N#-6y5iBtMB`?ApQnPRy23CxUs3B|Z-XLv0)xVTWFtV^m!Q zTO4&sbme)w_!dA+UinTZ<$>f4a4GRv%w_P=&gL|n>BqK#R^zcz8OlpP0#q&*oP{>7 z?CrQ5X?tdp7YniTtdbgJu~*bWTjl(|U!EH~R@T;;D&QI#Khbwyd~T>YtnG_DPb?+H zxABtZ?v2wskC(IGN5tLD5I5OzS+w1 z7_Jg8AaN1&D?eU!V_7{kZfagG0@1qY*96&_sbf4CeY<*T)GV}4CHZn3A8fOYlJS^s z16bl+tU$-h{Yl|StjCKTha_g)BzCY~>p=k=7kjWeP)zuIM^3mURyb}(LPMn(?Cm!N zj*IaOwoNlP5dyuO|EOKvqQM$qWqJF{C81~TA9G_@#+08$9rhNPFp*n*Dxxog>#d7+ z=|7;!1}7~nhA`dFv{lajGXX|t?XpW@;gF0CzfHoJmWzg0ipDW z5B+E0cG3-hT;?h4*})JUxSjNZgt(-r=r8%<`RQAFh14?Z<>fNe5Nf}Uzy@MIPc@ey z>Fw?r1Z$jXCFgf&;zz`A2-~CXl6t@|Dhrm<4#n*0C^ox3TyC952*L}c{=^K*-l*%h z&{Lt5`eZrT-qZ@GwfNN1{vkR)e0p^c)#^z^S$SYPSxQ+2D1R!Q8aw(T^_#65zm-0< zl{^$@8`dV<5T3@{jcaK*%|%)m@Mn!N@Z8ZeTh_i;y}{i)9u^T*M>}731dh|4=bSO?827&z4^3r>$Hq*KkwV0(g=!^5*n}L#3|=r3`}2f$SsV# zu_FiuReX=xCS%2WJ|`sy73Lg})SJc42bDkSY7Or7%4dBQGrk1D@aayj=_(OpP^Z>p zPQHiL+38Qgb>u>9S3w2k3rlrxFw_HOra`c>j#rhlE0FyO%?TAIIqXiC_`ozgrb)xj z6Bx;9BNXT2mkUVA5XNaK+*#-_F|1z(%cKIP;3&xA(zWCbTlF+Xek#+$$2O-v-CQcg z{{z)Tdd!Tp4!AS643zS6b(5`s>vI=!gwz#!O_WtK3ulGGPiJg^JP|ok3|V>60NCVXaSW zLA)|LMo(iBjkPG6`IKs7(CT4TRQu03*_ZQ+A0FpJEZD+LiJTxDoFJbvFo0Oeh~=Fs z-td!glxAPKB^?lrr58^tk#cjd(mEh284SoJlGqEM2a|NLtg@)#n*XVCm(p_OY%*?0 zYl*4q0@-?NwiAnrE)62#r%AbW2}`wcUR>RdTI;?&yd_mzN}=Eb|DifGK-GzD8_vwL zKixgkLkFtP@!4g>fhOM-Oot$xiK?HbuJ65{v6z027P=eVr0IagTWuC*oM6ijGd3Ug zGM3U>T^fw6Y|W-L=;)Na16&oW=xxwf3T<>$37(ll)21gT8()p-pm{a@JA_k2isxG1 z19d7zgkf^LMmpd5BPL_*?almZa*ncj?>r*k-1Nf=IDLA&1qg(tf|_&?KzTRt79*n$ zXVA=J$jsxz4O=0waj-R1H^jG)52E{#C(AEbD1c3hw##PQ|Dp|8l}P#Gu%M2DJ9@`Ds;-XbCP&--*1}3A92i=96Lqy9G687>lu$1+O6pn0Zi1)8<;(4C30TpPe!q z4@jgG&^U%qD6R!W$g*+{d5|b(N^T!KXtZQqJnz{}+;HT;Q`kETeAz^+8dTtrJ zDWGF9jQW7oL0pip9`#|T7X|W3OPh0#Vh120B&Xc}dhQ!o=~^2F%FZRC%GT4uOhA?u z{T|aQi;}S5Ls8fP-9^ba*YZ5I$Zr$*g~>86vN5VWi>V|ZWn89i!D_BiH2v(Fsm+;> zPb@)sot;OE;X`=p;mQktUoY>D9nS)Vrvzu$w1KHL!)wLdc+Wu0bwwRHoVAOjV*n^T zvC&TZNa&+Y(ZhqMwahV|Il_$*e{!8mrz=n4Oq-Ba3xo-rewcZy`!VxZ#ID0j+bu(K zRb5{gMp*PDmGqE6doX%Az+;kR04*m#VAU^MZ z%o13VF7`%~=FLTRnJT3?G?tvesj7;a{?okjqnh4W8^?q>SpS%~m2mAuLd!b$noL0G zJFLDbR1}Roi>CA_(=?mSaLG|vNn2WEIf@RR+N^R(m;;g6Gdv5n1vrk>oAgzz{n(&k ziP@;UOn)fKk|Y`$?5C|5tuPc`E(Du&TKSb3{#W23ro%QU;YHAgDVAdU`?W59>+rQH z{yI2HJG47kQ@xLfCfPoEJ@))Y=;YQQE?)JD3l<;ZFf=;T9{II>Ksy6%+Z0h{UIH2; zxlybZG8^V&Gh}QZuqr!2a6irVI`Aw4SlWKUE75}fp?9rtJsEM-y*U6h; zHJx`p4Tn8&G$vjn>e0;$gdd6~mHro%0XH{gC&jRI@^)}SF)D*nwni_8>-bJVmiq!L zwYqWp#|4*QH+y~gLnoV$dp{$3wxS=JGJOowkTbQKHWE{GIlo;Qv)x6qABWT|8OXF8 zcI;!ADgvFcfzAEv3?LNKwSqr}VMVAr7n6bBkd}<0P*`4pfs3X>o$>NHH~=MEJ{4x` zOxRD#@qLx;ax(mAd1BKAO)aNbo?`P3+1jceJlp9L(C8lVh``Ln);c~&4II3F@{m}R z;z$}LdPWtEuu>kIC*dj4f?Y5bA? z1B*)hAL%~Bk71m36+q;I86yFHee||Ns!2brI*0IYU2H6iH{ogfYe|$B6O90Xb{w?@;|MJ(s zM&+MT^Mx^;$-su}!fIlhMNL+H#^f(LaH6Z7utDFd9ut5KnZO)CRA7Ud-9H*KRX-Xs zfrS%LXlBQaoV6C#R0e@eCg!oFL}$p%EJYZx)?vW-A5-Qv-E*FYc3_u@$3dp+=KQpu z0}g06HaLiF1bRQ{M?rSeSd0~PH7aIOzNHyw*xuEt3XDs0FZmL3vDLw`r%JTI2=K^d z_iz>g=5t!RT|$&Z(tOblIFz@jt6EbLKP;JG7%~WAW{WjcQDJq!Kw{;A02$i3pG|)Mowcu`QLa z{)pANSUE18^WonSt!sN2&qkG|;Xjb4Lvi1oOu@e@iW@G1at|Ju1T+$v<+~qls&E5Kw$Di-Q&!Gnb zT&}#+4!uPn&U^{Df66eCc3@8D1Z9nFW@beW7Iv>zX(DaJ`Ypb1Xzn=73(`1iuxQI> zRh`*XnX>EZRUN@#+)h#VI@*TViWZ)0n^=VZQA6WGBc}l0Wed+NCHiUM<^!@(z`qu? z$gzzerETKaKl{Y{OK5mS!=dWfi&IJFeKOqfONLt<$Ox}-(3)I(3%KhEagkSbro0VXiT_3_@)3c?eX zZfl8u#8NO8L>qc5RZ{#olB8n-VZofe#U%))N}+_xt2pPdgr=yP2UN@&?*7q{IYrFW zS0$!2*buL%am}DRO#s&>GnXC!lY(344+yqOVNpv73*p%t%*g8b1G9if2z*h;&ZVbHG{1J?r6JaCZI!{U9$a{;hvFm?K# z6T*D3Bum{l@4iUy0oskSb66;>zX6>VMOkmlv#F zK5ndnD%wkE4+j~|5jj*hT`SX8xWfdXb*{^D@WXw??GAV-;Xk1qmRhBrQgb8#n@CJ_ zS{JmTo_|hYHb@(if}ni2?u~mu%c|Nvf=_$d64TRCLeA2IPc{FV*+dW0Tf(hNz1g8rKq;aGrsNmhAyfJv#fRV7ES)H7`p_A2-^5-ie8UL! zoA5y(ppT!(tJ;gAzUg}}Mf?ioKt~>Dy12S&H()VQ^#2Y}*h{JViXTv>BR5xPjVUxR zVZ{OmAKpM4aTI}4shHNaM*Zk;JdQwX|NUFsN>0UBNr-PAshp&QU#Cy6ZIHTWa?CV1 ztSf?}WIJOly%?U;iYs;j-F7uSXM#&P0ZT2vI^}yXv23-#jg^tNlhds~2^AwW5<(-W zR?~kv*{g=+GUwDXu)aTDI-NgSR+@Ee2TBZY22W)l=r8+sG7JgH5hkeBM7JzBnyzXs z8&5M3s|5{4?A1A8*BlVt+E0xEz127wO69Ua2N2bAA&^%JCUYt*N*==t8xFl7oWl`H zc$>C;CeZW)Q;RsI93Y1i=`9xAr)Q%Cy1%5xQ5K@V;rlK^&thA*BN^+cGL zzobxk5|(s7h1=_G9bljs^;>;>l=kc=rX#alwAjcEuq9La$KusH$jh`uJ03f050GVQ z+-8pAKbzth+BoB{-hx_cB)^-Hxg*iNh$QZwIS|`oS(ieE-o4$Jy@rrcpi%!yhrLX| zj6WX*x|AJDo*#43j#8w!c{R~3NgL-*rawp1o#jS!<+43(Gj&*ZZ5>`lAicpPhmJr)iFA^--JY3;1J|IOkbB%!L7v zn>{=;%{c7o`pRh5BSBGuC8&L8_)C$8u38*sz>X4!Cg)H=6;fuJ)3im98Vv?!N|8_+ z_Dx$}Y8)iV^JWvC_1f@l=n``WM^Y)fyj}{FpivLL!PG zx?OfHG13v9^k1BXJ6@tD`14l_%@Aq|o#{W+9r_cT{7Mn>^IFCfj_9Yz%ykaDB470A>@1109ii_taY0supbaL20<>e@xo=jxigQwG5Q2a=^&?bTZ zO`LbxS@U-`<>S%Nf8a~TCvXZmCIWkaJ$Lz)=pq5_90@t$p7v=nQ1-+L4(#dKu(3$n z*zAv|Jjgj0Ik7wOw-lrqB9XN&t-!-MJniZhm<3m^FsANz1dFy|pXX4#$?=0`p#%d3g9mKV+48xc-$_Mi zbYAf<>E!UxVQB?&j6H0G41S|vjgd@g`Ngl>q3O~&A99YNr=wJ9?3IuuYosvZiv*?i zTtBQaU|wo6T!DRP>EGw~Bk26!4zlj;jeiKyet_U5of^c_(Eg zlB(t~S!u95V2 zBjDwUiCAo6CvN|??KJ&s+ercZaqlg_iT|U)BwD>R}NlqNGiV zvw@1UYJYj%lF2B#CsaN9h{DUn|p7wxjDfn;{ zs6+!~%bvfnrMB)LuHOIx!@NX+_@4vYODB#McfVzm+?4Bf`dUT3w+CQrF)uYS+&b{= zVz-BJOnGxI0dTkt^tH=T`6zJgtqyf4c0q`qo?(Xl53N^X7#pxz1`9y0EFCDni74DJ zG{1v%^Ja3@4MJ7l>LlF@my|?-T26KAfTZfGZV>yi9K?Ep@F~*zwD4IU?7bGbF-E8w z5>L52qRcNuk+>uRs8)@0LXs;4V&Ew`pt3 zGRe-|r#+ju`sF{f1D3@$#&L|YjuZ}Ex&6vK{Tljd1(e2FH_cGuyKJ5y8c#|W7Y|O9 zv|kg!9eq0$xZO)f$HbnwFW`{Tj8n6fV3h~I(z?AyX&#OGI2Z2IYzsj;#(cWd{2tY) z9>T6nY9@T_BBf(dbbHbEE2vw-TQ!oM^8`8;iWVYxZ>(|2LvHF@qFY80EVV zz^cvYZ0stDS+h?ln5%@ zBVay{k#Q~biCeTOb+jV-EtHcM4Jn;eY-wI%v{{pxTKa8(q}9k!Ep)|+@i+5pR^v_B zE8vPC-%Ww8(svYV&D6|K zu^unG1&I$+0&+BN89R|H?x^g$x&E1mb%cb(WW@-(pN;(aM|tsNn@hI61<5j19XPZe zISe`=d2>Cx=xjnuZ+nY0A`DJ~4|{1EiFpr*eT+fv$xMgLmyipw&I1+H+)9tAm6uIu z9GN4&&kYDW`;8?p4E&QVrFemC8U9bU!~n9T%Kycde*a|4k^f-JpugBs^uMsBD3C4Z zKVc6LICt{y&H-KIrtP__GBThWb_%OP`>42*b_$;BBxQ>IL;5AR+n}vWBecP|rf&D6 zzuSA?odICfrz)Ztk8ru`GHrv`AuoN7 zXIn9GkoB^E@^+Ri(NEW4lBC0WzL=bv!Q_{pS8%rDqZZDQsrquuhwX!N8t9pdv>gzS(K+c)P%K1d z%TbafTxQ3NczQNqK(=H8vSm{E|6$9rX!Y_5V-++qAX~yhHgeqlgDpD>pP2yE&b3UY zIf$K5ms`BYliaYiGmWtI^V%7{EM$AyO^O+#4Q~Z9>iad!pria5)qAfZ#RoU6tuo&B z`AsBLp%V;HGOV8`RuP8>>CsxvZH^^()-&4);b^u0-jmq|R2bE<-GzUjE&rDEV*pf_ zkN2+%^MBYfU2E>W2UPT;=2N5=l+vp>tTY|F!16rY5Z= z2My{hj@imEJh}Pt=U`)8II>8_BDtuGRF_X_IDN1ZjlagTl=FuhGo0RUvYk3F+TPzc zohI2B<2-xnjxPgj50wb!kdVtcojZ%7_K2{G99j1Iz1x(vlMT&x@VE~> z9Z=M2sp&SGyA$`-%Kj{HkI0yegK_GkuJ8n8wZ1{bLzI((Tq;Z+)PCZXJ@pE&QX>JV zf$><6p#HI&^8s7>1a?miB48iOzuB*>(tsSY@9Gwdb07G!&9(2v*IC>rqotCQ{He@~ zyLX(eL<_^1&Y&UIQcf;H!(5??g0_euxIs+y{2KOmjIy0Aad%on&=b`BsIsv_Q%saF z(4Hz*>{|RK8Df2m+rW#g!tT;r<;-hYo?l1M2HKyTW(_Cs8+T~dSSB>9wc~cd()D`$0NqOCdIC>s?YM`G+x)Zd!UTs`<+Q3f!K50P2F}lKhwHwmSi!f-Q z=UL!$4oi?}S4@++34af*Zi!rt{V0gJNCv6DXml<3_$pYZYWA1C@e?*Y{Ou&@0dh6l zgS*&U?-=VTvenAOjTq@T0(+u^B*o-}vP^6TiPL8Oy9gY^r#d2c(q zTGXE;tEHhqPx~fqgd6w_9r7Lj8(tz)AaZlqx6%Y`(%SVfLE8I5-vPX zX5W2D_75*-vKnQOP^To1bt*7gjhjdiZ&hNzXliSqoU?Z>9jfHT)ma%w_v$luB+LKq z-c>0sE_)2|64?s%6MRp!DaT7C0|Ac)BU?JsNx`Sd!eGrM(n-_>kUYstq$@NWV-NK^s$? zvO4n<+_7BOS|J=o&9HOUQ=1zze&gGSYuoOgD3ao|;hcTo3QCa}y1xS)TM=f3bPaAX zl}fAw8yn^hp@6nvltu}`LcP7e&(}B?&7t>jIi9MWpH8qp^E}zsr}L_LtU@c#1Vo*Z z@@5d21`gK9OgAikC*gFr6m*Q__?z=g$%Qr!?JrN%HJqKJerYSv(&O$oe>tykxxXGu zy@t9s?QF9 zO_c?2l*iv7Ev{9?W&=?dN*HSVtV$nj35(>;JyGtcmUGh>z8>4Gl44t?!plWF+Cn&| zow2Lu?8D`KEc2>$g%Pq6d$W=aIoVT@4OrtW=iq-$!%I_Oa@k&H98qF=gs;g>y}ojn zJ#?~|+sO`eYp9EX>m0BM0Lz8^q>3M-N=nVSPr4@5fl$Kf1(bo z)EGcb&Z14JR_6;_>KL3!4oSHgU4Z`V4v_NH_9rM6iva_3)uAgp5Y#?+}aO1Q7h!A1iZRH`BcAvV?Po1 zB}fd*;1#g&Qqk%-J(_*=nhT!juexoB-s>;3k6OWf<$2HkY9nC?X$T60L+C!|?x1Ldp;v_13#k=h;ch1-^8gn6uReGDN;57AZ&osle9Sgw$JGM zjJ%=o^C7R{y+uN(bL4MvOCMHR##m7Ji+_7@`L}4F|G`OXqw?2SIc4KR`v1AObOtUi zL!!mgZ0v%1TmLEjqQaEQinp9m<(e4tQrA{y=m#i;NP3u3- zlGG0MmK$KsOU%OdT~4nyK!i%XAxEG`unfLrOt9Kabdo`?NhUcw!3 z^KvMMFf^iG4)&E7FOUa;i%UwY?@!0K*Yg8=N)f=tC4PHzW?P96D6NBDtfOe*$Kq0@ zeZfC5d)1O;@>D3j0SdUdY&`0W1un=W~#$29SbeO&dZ>?iy5({b%urRW!Im8DpF0+7(OMUoST4zL39TjH1 z3rEKVbR_-TmHBXNa4QxN*~{3+I602GaufNKy4@SwiBZ0eL0U>a`Y8>T_8r^l4qvxn zYCb}=b-0Kef_kBYLW|%6U{4owP2H0g3z}lvq0ge?NiW{a<)2M0EA41*^B_d0^!(DX zn*8zUUxO!OsvSN4y4*30S<9sw%B5V&8tDZu^8yn=!&Ln4NyG=1!{yW)Uwk?C;M}kN zh_w@8so`4JID0eHA=kR7W|sazZY1q{uOnUyfzn-)cSOn{YJ#()hmO7Lsq1*_i;p*e zG^A^GLjjj`EzG_>$!(oI}*=+~H zWtp9Gs)4Qw%~z>!7H-Ndx8~K|@&~R^N#3#>`u6K48Q0p#+>jipqmhk%)tsbgNNJ>E z>htz9It|9!$&V3Q&SU-bXbq+Yy{dn-=*)JYE4H=7u3|MEhv?GnhaO7FNX{Q?eBC%{ z`6S5NTeCgN3^+D&`tb0s_F3C=q18TJd0Dr^%v>~{%HcXi2m`K=11MpKu+p}NKx?$< zriLM6Y34RNNI;F{4-%{ z2nlJ)%;0x*jWQW}c?rVWa<;ui2eJSTO`4C32A%F5J=)oHCaI;j-FX^t21mh1FJp~h zya!-D)-d*5mK5gd$c4~90`<+z3y)xxmn~@Qnc=?A2lYAs7)zcR@w7o#{9%~*Jvv4Y zMI-zG<;9rVks(v@>RfzS16Ec}Y?uq3h)XmM4(jvm0Y>?&=moI3jPOfjJPMYSF@3-P z4IKTo;HMs_>^Er7$1lcpba`*pB~sm#*7;6ng2jXW9BkX)bW9C#FTDd+Fqt!^B>sSH zqcoLBq2LAO&cQ(+2~pG`Tc-YArwMt*-Q019p{!Fj!Pw%dJpU7&NqwaEExX{Bp#WbJ zWb+FNBH0RfhOIXqO~+eYvgfUO8&`4Pc?8=N?Y#)lN}H%G@6c{<>Eu$5t>8?#S9*)>bhY#v&PKJ)>iI z*n4yOhEHxWd6|DI=LOBAum~u(lga$T-HyKCVbrcnatyPLysKba2KsbZI zR`LGqq?v0JZ7jSZ(_nHhyA*Xn*@C-W5I`)}AXXAGE2FVBf0;GL6-=)>%H(Ey8|t>qNaGr4 zWC!jn&j-xU8dIJpcrP|Cp8rw3oE;avsfY}+rVr9>l@Ndr(#`5D{L?YUz*n`eh;>CS zI6F0Kj4H9lh3jh`8P}lP4<;!K5e$3>*&leh%7fz`LYwyU%TwyhAXeK%B;c`)&!a%>GJRY^uATi2M_W zb1g2EXOWyG_=Ddvw?b;FAGSQ;b8?K4itBI~dGfea$uij)rk`R>xCxsNQvnN=YJ?>u ze{@$%GNfDuPTQ7cN#Yj zld7dqw3(hSMUf-LEvK*Kc~^mu1{K$!eg=l!t^OXCOG4BIyur8_4U|!ajx)_auu_W( zKBHcvA=uhY4g~K`9htvOc7O7b|8?FN zwce9HiDYk<*?^suSLh*P`m^l7QpAyih~QSLiHg*97S$NKec0V3kch`B1%8Fg#6PKU z)`17bhhhrbzshjw#lu6Gaw@QbbBh+S-Whtq8A6k*x+0WuKd)awVyya;u8_Xr?PkK%X(=m07lKMGLy9GQFmR?iOV!(^xE4_p{J(tVZuX zcocHj%m@aYx`;UP#``P~@_ZTTN{sy>E#0KtyV!J%*vc-Dg44QQ-GJTNt3Vg5#aRtG zeNk^i*^C}n)IK8!rI5Wbeyn* zqf;b)^350Zk!Q=dQTz-Ge-TLc9P*3erBAWR2@jRKrdqnReLRUHJXHr?qI(20H-PUD zDTr{G}6ol{GxF#2}|dr{yGE3Qd>fS-$CX zjuO_@E-HMBUI_LS)%hig#k7YbX7+m!BKnu{SK!clHX&m=^oI|FFkjB)mO?Q807`rx zI+yJpiH{5~kM8S+vA^Z@Z&7Bn-mu7`C3DZOB78CiOWk!B0>A)t=4kPml;jF5rZVnB zSRZEd+ipw_>th#G65n^cnfq9iKt&gJBHk}?6>0~j2Ap?gpsm!y6+*aj&iB-c{1o@b zGEkPUDwW`#cFcOZ%ALAzYO_P4UOS>~fmie%a)+fq+Hhv;Cf!6qv1EuJW|~?43$$m%ER+ct4Kn4jcZPzx3-T)x z1Qdlr?Xz_+jR_*JnV%3(e?tiYLcjltJ3O=^ohhTgVVqq{Lmj$&3cbd+tvH`j&fzPT z9Rzc#Zt;it)MJ($YE3%k`5RB-^UzF>4e?5K({LE+vI|XD2CUzK(lB~Y2;Tvao96T= zq#L0wpU^lzi&25Jl=!%|ZU2$%&0JP#o^+8`{-GZ*a`Lxe(hp0lVYUM2zmJvwCCKN$ zb;SM`tejaT{Qt4?|BaOmK;>@;H_N>KOZorzR^|W9@&N#c$sg}u2Fm~EQsy=1XJO1o zA!gEI)m~pt leCY;u)nx(-!dS-+&nwC%`OI&@9C!N!4d|n>kM@I=Z?lZIx_N>h^ zDO>~{un)7Jh<@-VN^Hz{q(z8CBgDaZrE>7c&eCb}HEWai;I>m44Ub@P3uNs#DB)cx z=ogS`*v?drrrA_vKxm1f4ixsG|r}VX4 zOQcSKa&`z=MQwWL247zTX#oTVEC?yEug_hGgzW1RKA)Wk!3L=kM7ZqSru`fCCqjr! z74T}Pi2*J^SnGY@rKcPx$bbrA|A^YM+&2ku13Z&4NQ7S9qAb)u15Bno$X;+V&870^ zg^fu8-Kpo?TFj4xPIm~aH>hyf>#50SMu_W<|wFYpFAoF-9^WMw^=UcZ#gD+9cxk5W$Va8K?t z;6%LcBsHDeCE;O8Nt7!a(TksfjFwp;0)I**-Y4z|*H55Xn!%HaP)Y{4Dg0<*)_(T+ z35|Z$|8^}xK9#0C-SB3-IC$|u&QQ}DsJBTs#gJAX)@(acj8y&Sym_)T-DO7OkyV&p z1b;$5f%wo-U)4(;9NY=1D9QpFqR;@qK}>mipR(~~j$(V2?=A(g+GM)<0-1M0IV$K- zLwBKCQI(@K(}lXcqwIHVZ4@puX7%SNhW65fs(?;{Q8(55HcJ)Y+k3_4Jx8}%n^*ga zn5YxbYur&?UF!a|p#7(!oD8)O!t_H&SxLa>psvI^owKMXM3bnXL^Rz!Mx-VgQ}s-o zCJ^soN)C%%8!D|DqsaP=TtK#rX97O)U zl59+76vy~SaRs-A%&)bAf4GvorwP~h;@0QHHFSKm@vh8by15^vpF2#d5lK!PLAy4{ zTWImLpx_I3ZPX9kEU-7i-5&b64>HU2No#jE=ZfDkSva$NtA&!P!3O&6RcH8p6>tq`le$E)&E04s(r?(-E&#S6w z=fxDmwPjXU*2W{+x{iF~FP`tbiqmzoEmU&LUDEw7h~n>fa@g`H$E!j{M3!461H*JV zukfR4Vy#!&irsNs0M8z>+p$QoSQ=bM;~$&aM#y$aHfizgeRIv1m4gWFnrnHXeuzP9 zU4080fsJf~t}Xn5s~7}^MEuA8Lm;S~O~gTFf(G}tEiHiK6lqi7(%ZYNbq0TA4J3eD zjYwP(>-SqckM)maRt=6}L!Q2~G^V*BH^wPe&I_yAwKv!%r93a2CxvAc_vt@MlYg_s zbOYsu5@G50J5XMnfo9l$OJ4r+!kPo6<>UQd@?!H3FYIeh(?7hh^`kb6N{r@=EuM#( zaCK*N4ajS-6M>~+bVU7WhmQ)K$t}rRRMcr$q;UM0vxD@%Ls-6zvBw+Ge$-)#vPLtB z3HSl!rT9Z$CQ6l!+qfQhC%F#Xvu}Pp{BWvD3X?gq2O)O@k+AV_xF)hOl_#$S-hsOan%eV0E6OSg&BV&Q;uKdyl3&`n7KMtSa%uk zkWDX2SW=+^OaRQPG?k)0wl@J-hAGv*7ezv-U_LbX+Z>HDpELe^EHUX>!y zY*v`h{QQr9rlagpDPk#uid6EkUQ-ToStH1?B-cLV_rhDpdyZ6Lfcr3a`*U%S~ zN_L5S<4pn6F8;JLnL1ti##b|quicW3Xr z!x_s`GCEu@L0!$WHe)f+ipMwcaA^q(6zJtZw=8I&B_>3tRuj=;feQs^xxZjYAA~_e zf=7&aC0w>-p0u|dQauX?CXd`^taOX)KBm0m&L1O`C_GlwE=#}y`ty3}WV}1fFlD*Y zlWE{et*tdC`JYQ>+ZgPeE9`6vArFCB;i{ArM}qh$o}aL3w=(G$=op|=@DIx9VG3Z; z@9ZI1u1fI;0f^poVc+5n?OZO-2-$dYKHrzcoRlo%z^k@Hy?WjXd zokHyK`VD^}HHhuSJumoXQMmki(ex?9;{|%d^53uDEquSIi+Y=s*Yf8T*~FHEFf=AMn_q`B-x zQG=W^VQ$jZUl@@|dmac|J49N8j9Bs##rC%E%TFb=qO~Q0(-^NX|K4#P+fQrgoru?95K($x2&Y zg8?Al*YKP$2>6tQaJP{ z;YUkP4ka+87iPzg9E{Jbe}0lx4rIC)MKEBuf!Oz>JG{Z{{Tj)*`V1T<@8)@02Tf&H z?=VhI`y;PmOrIYioR9hY+b+xzG2Uswier-u6@7!##S^8UI++t86^mB;#F2cKA<;Zt zPK)hhiKDnz5N1(nh*w*h!1kO*EQhwT?LGFeymBXeCb0Af{km3$gRh_mr!?=ZsS^S(_BB?o(o5-GcV)_O#RBs29NwFGo}+pv z7Zlk1Ceh`Xy31gdD**XxjQS+(6kt(bzvrI-sJ$D{c= zohjQWdT(U8X42&!=kJn7TMo)`2+IbgYgCvBF=4c$?$Zx4#jh69bkBO zw)+R-D15+&?})RdbBB2jP--0`AP+@_=?5y?rRv-=CfwANq|_F+R!18zsU6zFhfWlz zmUSko@L4mJZ^<7*?25~TX?Mjfw^Rh6HdlY2A_=&xd@ih%8l@(?(Hvn*re&xJ!pP9q zH*=v<+~wlTcqd6Ph}9s-*aiO?vVs9l`B@hcM6!Bgu?X)S%rzFMHEGDFu>5V$sDIa* z55&xcP6ej|ZZ4aFu2`o3b=b_`^MC#ukolLJOJ~IY{^U}-?eBdgX#H%9@ekFid7xua z0|2FxBvwr1Hr>jy&%wGQh{X9P#t`g-pSyMEH&Yp^LK^qDL5V7NRzKN(Zt+(7zHY&0 zO@660rso&uy8Tl`jC@d^iK))F#mY9R$S}^7kY1b)G15rP^ip`4#d!^Coe~$8s@j|t z8_vz)We(41h-7@&TGis?-ZI5ioo`o-j6Q;F1O34r^cUMD9q``r@kWKGZ1mJ5if1Th z1ErPY0sT-T5QQfq);s7krqgMzEzuQc{^1slJ&zuhQFM1GM|8668POfE|BDmBy)d}< zt6xM;`YW9-$ODd01+b5#<;{!$=ZP@;KP|BzeI&o`9j>1K+FG*zuf7u}b2~@pzb63w z50xY~e`PUz5a!+;Z>f60nWg|Zlo8d$mEyh?u#yD0w~YI3TAQ3ZYr_aD1d6t(RDIZu zK^lx>WM1)caLJDKW}jOa$O`Y5OCl4M4>ZMMs|ajk7PmFo{^Q{C07#e@u9I9B_WHQF9igNf2HM zXeIohwAf(LBcSTw4b+O02`Q|#^5oxfb5gDC+eFIYhcccJK7$*`fF+%xkSUW&?Ecxi z8x@=>l6(l`C05my%8x5RSEaxV#k?TV+1SU^(vp~JdVSWHir6h19h4bZCTuKU*#Elg zXnWLKA)4AS=-%uZMBvnd%mCTTO$L|_Qypb8jNvQMfiA>Ygjx( zZ+dB2p$Iq!0Jb7ye4K1K&=VWaSP?E@Fvi>q_$)aIRt*b_l2@vfqS_yd|5;gim5gpn zXiWTcbvCqGu%`}rnSSEEkS5uI&m7|G*n(;sWAg?>U(S$DRdU71~iI1uJ(BQ z-Rhs^+u(0fMR5tx0(4*Hz5AVl=M{ab^INuVSlSyppejY{D^&}cioZp*kUhN2fVSO+ z3OO>6`Z1e_45nKIS1i)vFgmdeXC0MKH*b5aYW(i4pi;lfA9PHqLzSwTjo+>~v+rEp zt=KV~7gcd3EY6rfO=V~=*3rxBP^jgVdo4%F&h9SubVKr+OxfX0ymTeZydGuXwxTMY z51MDIag2_r6#hnrLT zq`v4Q-c^JcpJ`04ruJuZ8_r6a$vvaP2t8|)(rk%I6e@hv3FF}1T49siEO5+OtS-w% z?D4{I=sI)0-?5R@*YDxJg^~V?Ux9v|)MnsRFo6GZH<4j>506?9dD?gZb<_Houv^&qUBhx5~NIbmc3XumprR`8|PlGhxVBbOZB>@ZgE-+pP~xk zO{dsELBM4x@3*AjVj?0NvW)gjr(VT9%z>3OEP66TnK`2RP{8#9UCdm-AHL&3fzY-= zw9DYfY;=g9>^vN1zG6tq9|K+@`SK$aUfFxw7^+^eg57^irHS`ThBo&`#=0=i*nyOl zWd~0n(Ui$NM0P420^`vwk{=5UV-SIir(pCH$}l(f;E{6Z6WTXMoRDb)rK;P5OMM2V zh^d%uV@w(|zd+FUCcWF<@9gp9*N#-Pet<7M!OnnS;% z5(#o50snM=IWSy>;T>6aHJkXJh6y%iKjM8{<)13T95!!tw8*9+U&>NSVlLJ9pXOY= zMMAbQ7uMFA0Hyh~bBK9sB*eNgUkI9xRdUT#9U*ya5 ztLP)_r5+!EbCC(-NvV`3&6QY^{UY$&MwmTGB8n(t&L|RJJ&WFwS1JaZ%=tyGmXbA+ z`U2zTKzh@5boWaShCEHaSUlrHkVWnAb?Z-de0o~8HXeeSrijcIyOe4?2hiXv{M(`| zAZzG0@m7>h(f-Vo+fcmz*mE97JDU&wJxg$sr<^Y=`rFHIq**_x=TB6n|KMf=E~ogw zfXP^x6OUM$!7k+AeTCP>a!u-)?|3zDZ{YtZG@mBfaS3I-kH3TFe_Ck%&YF$@&ip+8 z!kYgmG)>btFEol8pM^#he-I>AiE7Q(@SBViZ6q`g>e?W-C4`C+Oj>gaMpSG|p4kqf zsm?y4-n47f+VZZ*&rtU0Qq;a5I7_i{$Ak4GiS#qI-nJBVe@iCefAj!o$!{GT@8zyy zRiL`%F@OR!z>PqGG;%R{Sb5!yFDMAo%ei~Lz-m%n&F!y0Rw9%IR|*nOKPI-Q0UOp) zQ!mAv%iYkhGTJ*s&3(VuX0k)mef9CZlY&zYlt%$VNx-<$*25p+Zw=2*4YII=!^Io< zdc#<-1&Rj-EQt<8#5Fv@L_y=;wXkdoM$`|6YMWfi zfceqNe zEo;BZH|Bc7VixX%N~{8Apy+)WIz}rmT~do}{8^D*kWF}`;1c`w@R_BeKEU#h19mHl z(;t>QY6`Pd&AyN`g@FDrL0h&s=dDAGQJeb%IS7U*pJx@1g!hYG*qaludPy~UJLUc- zLIp{gJvQSp(u5)~q2hF8bt(U)xma*V#yC|rst!Jwqgj7d^(Q>2To1TJ5`Fs2h$NjT z+jTewvV|myvmDQB7WV1Af#%y^4=TV0Y^L(CX`>wlCK`$-Jt~13> z4l>-R(b#yk72zK1R|6}~-Xeslhc8f2-jR?nyg4PP|dSLT&o82Y?jP68(6BI zGwNyyo(4Yl&`!(@j!Y%Qs|K!EBKisHDb?Jo44TT2#a2R^e1lf)Rd)=NwwlhvtkI1m z%tVcYDK}ox0@(8NB#88_n4}j;%iP$chfbmWY|`VIV#9s~2KaOvEo!+Lo=(Z(Ue3fW z$OJc2-Vu<N*9(l3w+l=EX@ zVP>iCv-~H)TyRSUcovboTm#{Kp%+_n1xsMre2GCaoZ8mlTUgP1Z5)T*JG*UyTA=fw*8~3kIwJjlBaBjuX{k;x22b9XZSNOIFaIJ&<;$5 zxerLPdKb)-r1k`1JX-cp2z?^PAiPYNb$^VwWU8v%DDXBj)J}r1c%_b0FWpwK2^yBB z%T*}po(4ZBpK5Cumj(}<#4A-z6rpl^au*krz5Z;Io9#LJ66j_{OC)kBM)b-xtgt14 z?GCG_wi``yT^F^k;s8}pL7&Cq+nnAjeh8(H>u**EBldMq=Xx5q);+*uhay>?r4=^tS|Bq_(iJIK^$ghk5)Eon#=Ksth^WRwWmle!^8%!dv z7|evk@9019Lk<>idl#IWs;7Ur44|8p)1q3Yo0Zpf|Aq6XO`qljCSp*PxBB+_umh!^ zT@&BYm{uG-)HcXX^5^#~4nX?l7eM;uDP^ggD@?YAIa8SCD&CbwisTiN;ho!rI#3>K zm#+|PO##PJ; zDBC*M2^9?tF_WXpZ&=Uz_v2>V*XCL#iYWD;-?t-0G7L@qGP94G$5TAhHwv(sGP|4F zS*?t?hL#&??>cFnEiJce&{tc$VeX0(33yc!{dl&cUu5zZiTuk_JeH^BYj8uOR|s_4 zo!IOq6P$=TX#2I;t`^YpfE4gN9yosjpG`S|@D6s-yb+q3+(>K!|KrPP1Y8BU^GQcP z-<+-f$I{uqeK~(|{AdDh0iWkzZUTRi&K4eYX#Nd3%i-WC5Z|C0$m@LrwwG1RKJ|ZN zJazPQ0P8H>nvRZ7GkWDR7MsOSfOU2k&*DU?XeXIviTMx-o`kh%c!=#bKPj#`dSXL& z5AxzOq>T3na1{WAl(kW0bW~x0I)#7+lt_c400GHvN42m4sLOylXMCa2nQvD;B9M*z za*n3Bo~mb_f(3j;&pKO3BjdYna~;`8@#3AMbL8ASJ8i90L_t}3{+N>h1hsG}91!t5 z32>Mtnb#{p?-BUoZX|IKt*+8w&UdaD?g~1p3Hnhx4q3R9jaSRz#S6#~@lyu$dKsZV zhfxXR8qddimLeFFpw#;C3KpqxE7Jh`pUJ&<8sb^h**@yQ6M_(%ik3X2MtN^MbAOk( zNsI!U`_mOaJ{FF%r9R|gjZw^J6lS4TjXu6s7O-vbAd>%AXIH?-k9naTMm#6r2=izX zR|#0rB`5!8pi~Vi$m~b^U_@HZFg`}_j_40|3qU}bz_Ei?H!Di7dlJ-x+ThCB^$i|S zIWv*Soiw@)E%$YwskJq)0|^p9rgS9@7hxZ%}I?)D7K$B41D zMi?MK6n6Z6K5MQWL(bfSnJ6c zvDLKK0kO*{BMI zfI9IKo`#)>ny2ifUlct_Zn39cizuRxP!aQd!iAE%6aAQF9nY{7H}d2I8+dXMBZMv*_vdfIm>e(n6b;L4i@YFjb$+8LA? z(mt|8%Cp-4;uwU|Gc|Y4mmIU_nK}4>s!v z+FM?s!WdCw?E*;=bQd9Fis!n)B&m+EpcyG%Q#Haljn_9mlkn$l$GXq(PQYUo#7Xo; z2sSy@WBh^o_E2x4?Anrg`A6wHQ-?pt`yATUE%0?`VYX6F@+GQz>Lz3V5ym#U_b@77 z@dyJ|>YK@)9$oX7L9K_Y(14EWpXJToCS8l+dgS@3xwR zFKfBAAD5VfM>hlqgT^>G`lK3KstEJce5M@G>^GHk5c-u?6DYq#D|Wo;sQX%SR=gY{ zm?5p6-c!Dd+Lprw!YAIN_NJE5w0QBCbb$e@TLXz+U%8Y3VLOl8GH-t zTisy`2)LB;c<_tQ>QvXULTxGRwNAbY%v`T)so^Cr_nh^~Rg1*PBz3QDlc^pjl_S?q zoTlwb`Hs}u#Z@ycRJpWp4)cxg9HSzqHQVf0`Z7dMz6rSsp7x73TD2dYdH)^6oJBTxz0u<-H z!zM+x!opgO=okA+BNeMyf0$%#PiDzan3RWD;5A3}`qEUH!za`7z}aslDXkjejy4zM z&D+}jx^f;na~{369(^yX5G0zd`+=H6fpYCQfuMnmDBgbB7x_K}+r|8#t2>kAvJ*}* zi8W{}UR137&ha>Mvr5L879xD5_Sh=(deGuysojhdH0 zJ-MyzyIw(J1;;mu74g=r{zGb$Q1`D&2ThnT8Bpr;RIn{(3x|5atDeQd%>~Q1?hU`5 zR^lOQ@rwn9R6HI#sM#-NSAdiVZLe?FKuXyA8KUwg*sX36K1><^@MJsZ!EAwqYjC#G z2Xm|_A?tnLBAwCbT5bfp!Y5X96k#@Ffw6&r>Nz2@ z>aJ4IQHRa$NWo7iglm_VyIh!+fhVeYa~AjJ5Ll9ij1$xR26fS-bz9Orb=>wJlPjLlE^dSNDSyqQO@dQbxJ{IbTQ z$n%1l1V^ac35)vU$E;1DEvU-S$MokE(YGRnPW5jb3(H@37YPOfz49vh#<}zK1}bI^ z^`G|01SqyU$Uc^%9#_K!ftVNJJ9l;Md|ZI+;iXa+r;!)GGAp>-v3c0V_G-la7#xD@ z7sd1wti)qS@|YbR0ZMQeM&5;v*t$fpezIWPLfQQVR+o=nWqwGL=k_PZEvlbV?+=5F z%Z?YiB*uk6ou`rM3zn&L&0_96&jFQmKfUU?Mrf3`I4Jn+h{GlTN##g7Nf|m}r9hdk-g;#Jb z2_Y39*LJ0hdktoip~d)I^Jk9Tu~ExQrR?k$c8HFSEYdj^@eRo%jfAL^7~NBn4JB4#lv&uAi_tJwl6Kqk>y+F*r5Vn zb`^_$(5B*TlN`xC)0U|TE)b_`=<%CY`}oNc^KmdY)M0KIBp-}|oym9<_&a1M8<=MB zlo))+Rx>b)6X5f!d(N_*3VJ2hda=9~RN1BM0d=7XG@$==lr$aXkD?dSWeD7f-UJ`1 zP7^UocC>Eec8%$WU0#O?lGMIc*{Pyut4hbJ<6x;d+hAa)4M=~8s+=W~N)0txYJI?r z-04kT(C>0CXV-^8KyG)U7V6$|^7uF+5_AMTs8Fp_duS$p1(B^PcXBVstdwbas4DD- z$22)hv>ks#=~eEOLieVfEsc$MCJF&E6aHfm=DZK5k-f=sl>3^RN6yUcdH=8UdCWPN z_NkX00MO_EY^dh%CFd{j`ET&%Us|2t*ygH`9q2T2k6W8c@&yE1HXmBBh@zn)Noy_0#E`h3Dj85~(v#df072y6V|^ zzMgXn>`TZ{*7&C~PPhH{zh=iI${pAPx3oVHqJ0uSq{++*;4DblS<_ngb*yPDoI!SN z;{O(R0zx@zkh`-;E2*p;{tY~+SE;*vulRLl`J;C?SPmoPb4kqA-la+c6?$mAD zwaFk}2r?laJ+7|gy6h&}uF`xtJ6aL4p69`tBLir&;m*c=pnt=opsw^V=JQ|VfAxUd z0B<+P$mcWkf5@JHaR8|SZUUd@UvC3yzJQ4*w64FkI|1ye19*l0WY0K6_)qp!k1~~= zNoRfxqdy&Pgj)(!F<#NIy50f%8+(2xp6u#P%qPh0(EI6yZ9Y>Oz}T<+7_*x;y?pwash?w&IiB(r9m22Xtyn)9i_q!i|A7hF=}T} zjH_IGsC%22w;U?ea?4?i$^_rs+=+~#*nSnt$Je?{HnToSF>)@iZ{?h~i3u5c2KoUf0sPH%Rgd{d9#t8^f!enTSoS)SA=o~N>MB{wl0A6X2 zR9qeSa00iU3;g=Q9Z8!^has^*KOaADOJj6kti5xxu8}!kveM`scoxoASHaM!wMYyO zdOA7e!izQp+p*5~1ChlWw_|(}=vN))t(tN6`8Z@1xBFm%OgjdWJeme(@5urd%Otcz zl2#IC%qmbPfAG(QFC4*4P58Ef5N|#V1F`n-#_$pq&^Sk6doKBa58{yuzgqrpxTl@< z^)LywZo3N?wQp$2IL7gE2}@qcx6u_1s24!H6~Bm?5=*6?K@VcIi#9A~+ylMr~0Tw;b-6TFSF1rL(c z+#S$B(BfPY&~jOGPe^_hpnr2$o?K=1`MRPKX$$yi<|1cPVqD|xx;3=VEg1N1$6G1; zhpf=+wrN_}PhNJcS7OD`KxQTrTBGHY!cgr^OlxsXD&O;>1tAzGxQh1pu*KG8rnLec zjtt-sG_-=q@qhm^m^H@c&YZcHMnSx&WPTQP{A!ieKXY5eJ!F01T%~LD)E6o!wQWl0 zm(fqyd^INlK+kCLZcMrSgln*xA|yv~bo7Vgse$1Pd2aU0huj|S*tpUNZ;m$w6}~(Q zKgCE&P_bDE>2PY4E>!3d?6@dvIA&`)?K!ZcQRk{t=MTYChzP~yYz3KTL>~>m8q1>| zM*sEid~&C|0>1IZIUK3|rme>q9XX4Trt}C4C8D)LEHcPR$ZbK_!`P|#=6ZB^i$ zXRgV{TWPDuRR2jGJ+IS4g9fd8F-1gZVG?eVNifV0dUfJg*SUWN6c0^P5&$rZ2 zY`frMFT2S9`F+!f6Z0i4zjd|J=)CUKeZ|}x;#A*gW_X;biTkUa*NBlCJC^z;j<)C6 zPENP++=cQ}RZwgYA3MI4u7GdK?Ro$^XNp@I$)YIYM65|;k#N*YP5Tpt{1Hx=F2}-Bo*(8a zw0DgVTy%IaiCL?CVQ4bLL-LUJnT^7f9xwYSxv^`?3zd=W@mUdVpXJhDoum!HbMU;h z`8gROr&uCXm{U;!A*fY>$%(lH@W%dO@-|}e)}(l{jx#&*@vlD{^{_sPy41ZYwe}pi zxD8XZz8#|}6y)VT8ms!jq|Vn#Y({8xY_s{W&j^pbNOOMoG2T9>vQY?qt-W>h*vWI^ zWxwxSgNj4@;dgD#@JHGKrl@d+eK&v|T_|gW^B_rybSsfPw+XaT+r~w<9;A!^R%EA` zp;OU@1-R0vJG-U2WR*&fTHjgq4n_Suv4ZWu`9~uA4V6{um=B}o8NHBk%<)2Z&RfHc zJ8{lf>-Hym9!PyS#OHJQkpXd!%gd&zC{;1CTJip{1rwDI!u0y~m%OtMK(T4w&zS@N&(ZTQ zIv@)`q4_-jT5SFqJ+rm`9eSSq4Lw8u59oQT`PLInt)s;1?;2<^=5(PSBe={^y>)ri zae3ss`RKdVRvv`xfWr(_MG8d43oir^0zvy*g;~e(6YG*vM$vgABk0B#rsb!em))w; zlE-$)NCwm8$)IJhbBj+tA8-TbTRUYDW}4b%#8Hf@yUi%gyK}&k_u#+-txVIRhmR|a zy7Pri=?1ou(u0&11-wDNFb1HhbR&QQ#Un%>CR^g3G>tt>L^(~bANB&saq!2-89}{8FZt%hoS=gi|W}tHK&^@Q~bC(WUj#V)< zDQ)xKOv!jGumdWItABo`2cE|0UP@cE@9W*p{I3^(PMcsR2XL`!Kqk`op~9lEh- zWAz?*7@|Q`6fuTP(0AZ3v1KgNNgYo2+StE5f$5z`G(n~z7$b-x@xF(WWr}EtYh|)} zbRS$Pmp>{U;6KmM8r#zp;hs$UI?NYIG)zIB!-O;{>19 zU|qdAa(4`H4Atm+9rsxS_A}+&suI$*vGaAdB{c2fQ(iPa#8a*!X}a^k{NRd+gZ31R z5PaBu=lHBR_koU29JpIJLTjS4h3u}u4cT!?`VEIw^2*CN@kvi<-#mZ!UKS_kL+mQ( zaAOnAGEj-|5nsP{5W{bs9IT1>qzJh;^fip@iPwMp`Q?!C6nuJ+$A+1$>1?$#DH;`K zGbf298`uC*xJWH2P2!M#QvW5I9qaP$w<>`>LrPx6h(S}BZrRCGwgrIT9=s^0m6*zx=GJih8RZ z9e;{R>;s3CSYNf>!LFteG(n;jG@0HAw|4xB=5BcJF~ZR~Fy?rDTS?qG64eO0Xt`%R z5tCROcma{`05)R?YYWclHYcy|3_#Bo1=5267vA_JaB@-RcO^Lw57!5MM9y!0dHe;} zuhP%uL20>|0qXa0M#70t_P|?k&}4qH-9w2t)!*uJCZ9RdU3zoj=C~<;)5-5(TU*CB zJV;gg)~bBd&NjNO>iG+L;s!^bQvuM^A|=NHfSyBYniU|X$5E+wbzZ4^g~FwUQx4KH z#6vHEtaylleEDxNK2V-!r3G9p*xiKW*UDT{dvS2_M1&qY`5e2@{cN=cH`m)qOStV> zgM>i4*+iS)Can4FNiPbG!?m^|A}+tdbV3fmbh$gJtqBpEZ^%JoUOGR`G}>F;0uyo| zghP@E91le?hxri|@nSA=OlxD~WOCBc%QBhs&$5*41Z^3h-obhoQ{3f7l9rzotj%^c zj#E`L%b#m9o@i<_C{j(;h7l6*Z@z5)zTGx}O8LIQ=H*1fc6s;w6PS2KW915ml!)glWCodqA#ZrI;l~|0Xv>iI@4L&6k*nDuH(6aY|@#_kCz5x)Pq5~@+jo| zBO9O7^zF+ctu~GKdc1Ee`I0)9_d=9Lp|-2kNoLP`^*S z2vA+_pWHFeb2N=?habPT-gRdZ)9~8;KK?Ri^V#{FQ0XB2?0o)*?Dfsj@3p7k=Y)Sl1~0YqW`M6}h8vr5HFM+N7aCi3SjD!cnP%M(=tkZ|x0; zHZf-d(Hy+k)<`b4BHVO!oA|G26O{joHmRE_(~bFzHUTBgDey;u#-XdGY$WJYAo=(n8>>BkPJyR` zel~df=FpzTENR>iDLFQ{i2Rty8N!8jZv!7<4TfpJ{hB!jbfM|#(XnlK{ywFFawFdP zm#63^zDVs*%XP7KW3Kd6hGUH>8iWqH=(s_HbTzKQ^pnO#v1T}i)Gqj@2s1>cgJ|?}tb%1e z{pNNTn>d0_jE`9^7yMnfZAaO!#ziaTfZISSH&D3FCwpqa_>Wg^IKte@f}2%U1?{0% z%ODk%JmqM#nThMUgbm{nxtKqTcv-7B80$zUD(2&_@1qo3+04~AMHI9)l`nZRe6~ID z0>nzhMG&^cZXWr9w_qz4@I@gMv*rJrJ>zf!4ghUWI%%~vk88vVIM1KW7v~QnDJlN5 z6gLo~(oq=m*OF8hD%Uc`N*f~ZvU){$8U*nN80KenQqdV%-j>4;oq)clErWwqYCumN z>`t`%z=$3uC+ZQXwPRA$%8u#cy$QU!mMH1%H`9cUeJ$`#c%%t5jkS=4Qoyt=ltZG{ zFW3fqf%aNhQF;Nbtq|@?Emk(8#}*{o#(davPLqjgEMz&x2L;B5NyefKP0~x$tGC@{ zFH)Ip>oXU%POeY*1WZ4*BHg04OvrHghW}a&?3Nm&+<->)ln_}~K?}TH zK`ivageeWo16roQBCc{_D=W9<8LL=rAnr^bNCK3x?PY>Ig=}Cs#+zkd7#2%bg+;~5 zYmWOkCbO>HVY(4%rNq6j;a8w6Mv1Nzx-qRKFrf^;j3&xqoL#_TiET5qLN8Z|Xgl0} zLU{J&DUFBfAeuGE`oyfUk!3=pqH}baaQ1PIr?&D)-lcV8-IP(5^cs_>=%qVVE-AtK%6Nj#(HbInb*+j}+hKIM(-jDv``F?y@KU#_mHB|q8 zv0nlt7T?JF@glZPP7_(-5sFHqq>V;0ECAWr9Th_#e@bl01Wdj7s1Nw>ypDIW`NO(i ztYy!rDq+3v{IdOeeh?xYW9Zx&=v*Q;EUPJJl4#=e$5_X+BG78gL@g*gJG=1Xa>--X`~<+KCU@D4!vGtl*KonAKxy>q_ssROpAH8O zfb9*q)k172GYg=*g!=%m29CU*gM&i?A!CpEEYP%+EW0!I>Q%K1D8nq#nJqABh^ z)+hcKj_giBE2HCkW5p9LI{jg!0B`&oNe!!PK;N?sNW&t{z<)KLQIU@Vd+t|#mEiZS zBk2w_mM5=Pza)mv7fg8l_Gyyv&0oc(Lmti%>1XNa(u<+gg~_mEct%J%zf-?JA`Y~I_%&S3v@`234A$PQ3w zKF_}vn}32&b%n}VcTGUwa~MHsPAA;Hng+$Svaa766->4r-P^nN$G+*q1ikp~FonWJKUjQ#PXE`!xV3kNw#z=NI7f!cTP!}Gy zI?+Y#x4^+Y$}Odl*XKiN${7)nu2F#%61cNL&vS~8%mOTTM*g;+k`bz+2P}7fkP?NV z)g(ax%?huamHD*#h3)=YVJ67P^kEZ|uY7LSofxti)bdUV2@#T^I+u>m5al6W3t z2V-a^#m#EWeaE-!iY5EYa*!j0SSIEMj&SCA3D_j{Xuj6u>FhprqgX= zN+n^kMBdGHVths@9N1ViBJN=oN5!NS@_FmddZ7f|KE54JHKE92vv8GG$k6wFIeGaK zUjNNVRv7mlJ&8jN2GCq|0~BQxZlbth4)L0kk}9J`>Lym9%4JdY2FxMI{8l-Ut*xp* z(`w3sJliWY)^Ddw|SfgzkMPyCv zInPZl`d5}>V%F(IR_1OEJCWoyaz^vz;HAYvADc66IRPTFHYXY}LBi8Ub~xZ|9<~yh zSdol(ZCl5plgHrCA8k%4pYiw0JUGHEeP5@|AxO-->L~(~O6p0Blr@SUDQdGkGsb(` zx?C$etY$u~$6BGpgWl}|KgDUEI!Y*GIhdVZMK;C9puNPS8xV%0`t$}Ii|tDH6G8O` zpc_@>+}rbUMc^>=Tb0eecJo!znEDN|~8lU}f+)X5t=S5$P8HnIV9{g6Ugjs9(I z%D!Xm!Bi;jH3Mi`)@}ywo)w!LL|X`Z65Dfmov+P#V#L_VMF;Vw-h)t#>vCeJ?l;%Imz& z(+}A`QmoBVosB5$V#xE&G2^U=m8Y9(p6ak5e(?2w8=uxK&Z(*lHM+WJx!&MMtulud z%p9alF?c49>%7Z`_5Y5$V=9;tnfjHjYn~J{#en;;#Otdlxd2vY^aS&cQJILREI}vr~CaRbB!Aca!yA+cP}aor;WV>55o4bczC>com?V+^uQr z_OEc|qYl|EQ?Irwy}>B$o*#d~oKFPp&qf;kzd+D`atUewzw6GwAgHS-%>R#||DO=_ zv;X<+H^=nt-`8;dgTd&3_=Ns9?a%*S!YM4gOa{bj{xk|{w0(A}F{aB6j;m|%EyU1l z$Yrq0SVl2%MJ~+sNpDWkhz!3G`Y;+Xu{tA6!=Cd6?Big8T)<Khr6;cQ9$x` z6!5n2#E>=~`~Y_sL{5{Bg*Oy%qbKb>=6nta2OIFw0gzoF5A8^IlID*+J%t;tpJ{Hb z*viqh4KbH@Sk$I~_p9i!2DF6!YgsK5WZbF#jY7P0Qsk)Bd)caO20!CVKmCU&X=d5? zkl$Pa%d|eJ^p1!nGZ;jTO+AM^1I=H)*0!=#RBgHy*?`7&DvM}<26U+4h67%6@d|;CT9inNOV+o)z|sGvqmcow0pYBX8PA-!Bd^#8^g;e}#Tq8Pa*Rn= zor{mQyKEsG$(P10-Mr%JfVqiHe+dMSgi!r%rp0N-K60@-U&~l3ie{IjS90cu`y;-B zXDpR5!ZuK4oEXuFxQEc9ygdd^I>%;8Rv#V@wK}%(E(T!e_HqtsH=!my+!RiEop^^F z4u_-yZBcmVA$pU#X@4icb)JF0Jf06uCKs<(w8lD{9JgLdg5I;PMh!V^FtsyIe*sP- zHFV*_xhfK%2cmY@p3{ThsOqDylE5pcSABejefiDTyZf_&nx|5-iPqpgGeQq0-bJ7; zha|OZ*soz*ktppJ;;TNqjV68&dj?*Ds~=$-5?~_O`!1&&+404{8tG4|G}2wdn}#jF z#!?J>3h?iS+nkP%J#xw*nf-=dC=rT8jAD->yi>WhMKAsv1;12LaMAmhCT{$)srR*) z-|LRQ+u^R;B{=M`m6FD6fCW1nH_b!5l#jO6%cT2oM)xt_!3B7_#;R|uZzbMz9eLE2 z-jUGOP0LwyLW5=lM0jix(v8)Fu32$bzLQ)e=(5=Nu%lRFNd5q<-n3%y+odXG7Utuu zfHv)S@_tn!Z99+6#)^*xFPu;tUn_pDtfnDd#Hp&VtITnhC8R3&mW!ssUo+-oF~Y@1 zCmXdcFzw3b*Gmt-T$oQMLKwZMn^z3vtoFI>IiXg(eC0ByJ|ePwTA^Pwr60@=7ynD( zCOGv+5^Q$bFnFPnVX$_SOz#Vyaw04+0~^%n2so-&FWv$Cb#-W-L&>wDva;sFn=i)> znVewtRL-dzS!}I3ftIK@am7AXmj9fx(f$UKLIv(R+}JByMcgPTV`vv`ywP)P<;fSc z`dZi*wh&WSf<37-lP=C!J%iPfXuj$izIuWwR!@K?5bTFCEJ4^XC0fQ0_yk!hkuR|% znsOlFsmY}R??3OslJ|GHuuYUmWPure7#a@`0I}c#Gx}qSl>BneG^3*8CNV*8oNiI@ z&s+>;pEqUS&@dr@@(bJN09a~AAs`EyHWEokhikA$JDh?U>`XC55NOZ(q?H`61q@TZ zp-`%;AapKaQy@A{DVx|1`PXoJz-5o0YRR1C!oGr*)frl%OrFX6^CdYsIbM_a!Mbft zozZ$^tE(hYvOWYvKmJk?C}_3~!`QPQ^fTV0_gIC#+cN%kZI-t=F=M8rl+Qsr8a7EB$*ewL)sqLVtV1g}Z;}je&A&kP3%HJGtCLY& zF}XX?JqrdL8_G%0MC9uh3PhxL4L5q=#%Ag{ za)Br@jh4M5%btXSwFVK$BDZ`-;}uf*Icr`NQ2#NHvV!etLbuM-(vburTFAMUoYhMU z6CW?n1XSI%av^XsFyAq0@2h1BzPP;qQ84(vHX{m3s-89WuYU(?AT6zc&Ti-2PuvG9}_M#|%b|T~CFHVFE6gx8a zP&4i?FGW7Ruf#JYqONi@?S$we+`9or?|AZjR_L)h+FoiceBce$frQPr9a^Rsi&q7e zgQrzND%*|bEt%fyue|H@bQM2Ec#$*^vDBLHcf(#L)L)|13rjP$#`{fz)8J8-q)ci< zn~M%Upqqbvlgeq+K6SV=p|`NiBlZt40Ln*DGpP8$YE--ZBRRkoH?eLNzx|_z-8hC{ zOBOspned%;$v=-wOf57orDHuUo$1aj=a!IX$>Uhhe>djMp%|hF2g=czoBgN{U}GC~ zgfGME`JupP2X7rgPM?~zI=$c6w>#zsn7%MiCL}jK#-R_%uOp(HAzv}FFNP!)ET3Je0YOFxlxvWLmkv@bO{3t6m%FZLy z%?EPCll~>&5me$CEwy=to6V}DAD-IS-!|Dgeyp*bqi!Tck|-k=v>qWr()T(yYcC?C zlg@u-a_gmx8}WW9hMs(Yd(O+*nK2N6C zX+u;2$2B+j8%MC>XFia|m+^T2g;I`MMpe{u1kJshM&L!sy)a19b^H~p_k^lr_cDIh z`+zE=@!T7pxz^*$==^w00UT6bA@xCx+h@>=+!QVldYy|ttm|;G!E~(Ja27HPX_J-l z5Krk8Y`WE^Rw3+KCWZcXE8-|*ih4%xh!ChRfI8C&3vlMn1fr>;A~Aj#ZzNZ_xO&2}5MJ|K;^s{H7zB)$vb=rL+yz8I+-5r) zqvi8;jne9@c1aa=5L+54xOKbYAUG4G+q@nbZTnVQ22Tz{rb`Il!Ul4|ZMW3|V7E$z zCaL3-8p9kbcDbI5Ex$PWEC7WuZ15UUur+wqI>dPL3!Nr`|mv z{{)R4s|ucjKSbtX706_5#BHS~cdL*E$x0oNf3kQO?q0_Otnbdt2Cs=6zNrPsKY2+n z$1LTjOzd-q=;Hia{>cSkwzdd9Q|u!Id^6W!O2vFw zXKzPVfCFW{Dk9qNmMCCemxK?V%PCe2W$zTH6IG}6iC=3QCWCZA7&&yf7J+mhSL0-U>f`X)!Jd4km+{g?g3tAzm zAv`jQ2>e-Z_XQXOzq#zK=ZCWzZeRp!RywY>9^Lo&SZ4EPrsB{B)sgiy*YJLFhqJ#& zYyNPV;_uo54A**Bf4f#J5d&H`1155%0>%ZZ0qdB~{-Q^?k8vXd+N?AP#CJ0@$JwcP1^!1Fp zaa2OS)XCd$})Wi9*#|L7JAQSCoxFn_~rU!e|Mo}K+Q#_{e{odf!RHF z5Sq@&F!zgO>31%OF)FVZcvivGWQ*E`7;alRF08TNlBY@lix5>sY`-xq%cusv{1l84 zd<^upn*BJnxj1KB%XvRI=r-w?;>G4><6*@mHGCgsDtwdf&;=B}GTJc_6S78OY=%sL| zIJC$!V`X8^usik$RyzEiYxMo3$lEYeh_UNQO;^ZdnT-aJwXDsigVTAot&eAeUj{l@4B z7ilj%%{cj;LB9^LE3RvG`H;~G$_;j@Q1ZL3G9?eVciak zx<50?ekY6_YwC{yRSq#QQIbZ|(D7MwR^R}rWou~>R?weU=1Q!IcdK$rZjc|7cf%-5 zWau~lANJlUI`ekj-i&RdV%tf@wr#6oqhi~x*tYGYVkZ^bHY)13zP)#^uUD_N|D)G& zA3SF{$#}+i=WjmuoYy_Zj(Y^P5Ep7`L_H`BY)HmrN?bls*By4PL;6Te*C{fbT@b8o zvjDGRC#O%icBI4CKkK15f6legj!ga(!BV4PACIFA)rykLfxUoKg?SMqU`{!DOD4W{ zGGTSJ|8U|$A``RL)|q&BN*TfvIg0`7rJ`v{cr8;`l z7P=AFy0#2?$yHM{QQ!@Cw;5TJIM66p-)E9!tso{mWM|GrQ0&*#ED-_?*AFU*qmG@o zk1HFxGYEwJFFBe%nX|g^7Sg^yBvxl@FZR9*&tm2v%F1}NdQLo{=~h#KW8bM0(kWtd z7k$WBTDxkB>-4=%5q$sQi|{`9FkQ%K$|Jr1dyiVp9z)rNGOt@w^&;cYx9bJoc*)h{ z@%Mq$?eL;?^OePnZn-ZzuK_830oB-0fa4q?-t?k*oWveC2^+z^>vlR-qH0pV71PgH zizyYStfX$R!fS}h8;XXpZyz3u?HvKXzIhvU%=M+1QGX}+J*D&|@G6YZ!YMe=@$wd0 zulkruodVYVu+R47qrp5ij8Hqu{iiqfPl4fE8x-TV87gEMYVco~`zgc)41Bzw*(dKp z(DdBO`#P_niRpCgXobq}HJ)p`uQ!uJV_<|3CwQT%9Q>#@x2ojrlPzpkfJTt}$KNU( ze|Bu%?_Yv}0tTCZkhTBo6Xw5Fn*Vl~|8~dbe>u$eyuXy@dp)tu6U?`ABie19cxL@q zYGOmJH%Wz-WoF|{?5Kd-mWifD4TVh6aHbzjbnLJ!mgOsm+N{k{PZp@7UwN8NwtPTV50U1EF=dqNmVWC$e#e<8! zez#pYM{_9FYAsn6WZ27il$Hgq_gjiYr%{5PXfrL-lbzbO45d|8&Vem3RdLCwiN%v5 zl&Td1_5-u9fJDNPG(6Hj_TV*fA+IG;pe6hi`He~_fHX4-mcU`h$G~>VWYu6b-mNSMaz2>X)VY?J+$6*#UpV zQ>B&_y_b(@pRxQ*)Bf_tFUi}@#aeYX^>dZ zGPO^U)zLU`7ldFvO3klNA@@7qD;w$x^nr*uvHaRq@{pDQ#qrMU>=|R0`Oh{KXv2g7 z5CY!}d9_RR;whZkwDbF0+xCeczc^0SV}ex&hq zLH&rxj|Vr`3E4w7LDNUay5$PlEl(3;vsTttRNupHi8@uBoapd5aLH&@TG1m^G10DW z@s4NTSJ7=L4~ag_@Ht@fUG-D+?#prIti%bgaE-se#hW9M)izYdwzdta(pugRY{%>p z+G$yBHq&{mFp^tjlvl%%r)esR23b)fv6-8pR5NUwbya!kt?4{bxpFR-eu!0=HyXS^ zQp6>_WV{W<*!7p|4zXjCM=2#jbQugxg96@#yXh5L&{7VBKA9Ccl~nUcm*E|g`t`Mx zrgSs^BaH8O3@scIZbi9&!@q2sfcY1cIU^M0zX zlTluBq(s?^>Zz;6ZdXZv-3K35Ac9s}3@`J_&Q~8sX&M8N^FS zs~w4d7vbPm`8}oL&$T;CM!Yi=%o7tH=i4vM6Je-vKg5|k!%2z8ofPPBfRU~~*LSiJ zPoD_d%sLPv?7H$b?lYhjPb6=m5Fe_7{yACOnMx9izKe7$*%?|2DHIQH{7c~xSPrk^ zABK=7d^bm`?n>h~rn}Cay~@7uO5T(0H$F`YHVi$FJ^0~fjyea^ZOxOkgI%Gnw{5pA zxajVV%MZ@0k5CG^t{3s0mCVkfe1-XhS8ABDPi@ z9y`dPGosiuf-&D_(tVn0)6p5G7~1K|45EMN%HZn9PlxfHAu50o%HX#_QO}SBy{g-M5vld)v() znnoh*kLyJG>^eR;DzE5JcQVh!;}3J*+yYAodhF3pHr1Gp2eSRpJBtnwHH0dz?)j&A zX4n3A)IZ$XjsKJ3{5OL0H^ccaj7^hLo!kH;Qr1~bEA)zFh>0OIHX#fOF*rL!ketQt zUy0h5KZ)95MFnZ%!G4pCyAHSMZgHevI?|g1a^VoP92nY?d1`YS0_Pr0t}#{M22SjjOh1*SP<~u9Y%dCCoS(C3M(V zv!Jg33huy^_a{&b{MGRh46h~70S!JFOM}q@4xESEo2xVGC2@#Kvy!?B{1@8oEynok zTm7JE-Qd|SJ%itS171snKOgO$+Xuk}{d0_TB*q)(lC6R%Lj7=;vhe5oG5HtD_xJ!m zMa)3^_Nrdb`{*g72@SA&ZW=z*f?i3ZQe?X?bQ#jJ=kJ#^Ofa4mAwnp9D+X)Gd?OV9 zcm?<~$V|I;5dYJy`QtbL*N*MKx|F{mg#J7M{EKG*Q~ASBxHX@6Rrt`l^-S_()hHt)fZs7=(GGe3&bV&aC{+Dl1(gaAsM%!hC2 zB4!eb27qW2G9X+Hh&G`)q`ComHQiTt@10NGR~syf6KP@~y-<)qbs0c9K)oQ(#Pk>4 z`A|J7erNZuoO+{kV1^OtJr%1|`jc!Im>D3ga@heP#15wGvZEodeUP=YvaoJL_Z06LuA z<~Un;UOJszSGVOGN{kAwig9h)-<6K`&GNkn&nz70*1YZ`@C)l;EY<~mt#d*XV^njS zfUL;lx%idj329piTcb%P<(e0N&*1q4+1wZe5;$nYnL%wINmF5%WDr;|5>F!OAjwQ# zWuTX5rbJW1atZ}Lzo3^O}cY4;C`JzB-TM?;*=&mZv4S%?-B0yy|B%ihksjWDb6f*dY$xY{RXM00>1Cp@kPRoCEZ z*JzS0i_6+r0_+EC0b>3!Y2f3|F(~({`QQi0vPqmG;aZSHVr)xi1e`k@X21Jn$bC9u z$I38gxE#tdFN+5SIX*=#ztJu>0S1dO_&HI`CiHJ~=YlNT+j(d>y?HoDsg`7ywT~PZ zQ1Ozxge*yfn>6Gk8!ScJN+a4dgN+gAbyp zzk?J$?Tb5Idd}BYyJCfjbd43c5&@rfGfdZkSz5jv2oRagfNMubvA>51loJEr5Lg!{ z_ra9q5e(}X8ALS+AU=Yt$sI8Mc7*LA3=Y@Cyeo<4Uj&N@wk;OQogc}@fV8`$3Pr;r zQpIz@loS~w843?qbOnC|$y=u0501yLpp^^ zm^xM-%-Z*0g#qAC8M^zEz7-3$((7IH#qFcrgmK(EHKfl4-vlnk#CB;2pA{Ml>6;KW z-FGJc);C3_-}V@Kb&#F@EUT5O=yUouZ+LZEI0=C4ZG-*@^K0R6n)%(k?3ycYPp{Xt zU%$OxiQM0>)N|rFG1YZ>RaHLrL*l;Y7L}uB`wTZUqIvRb>|{F6j6aKNe!aJ*wShlg znXJ~dbd_iXsS$ORd`ix`ipQ|1g5)wqvB=_BE{u(xj+56?1J6zwKKDQr6S< z*;qti{RA88VONo(Yab_y{3aVU9RW+SiIlJ%gqA7M zj1b9xVT5G<8zZ!N^!i^IA@+3K*>PYjF`&4ncmbe4RnF4s8B^IXwa9Sdd7nXsoK&*W z#qh_a@2WIl&F{?GX_QLI5(^a#k>^h14WJ$ay;?Oq>RXJMvPm?j#C>50UN}+#iLne(ZK{t8`b&$z#*{gISEiEV2{3)L6yOEGO3k% zo&{ilVs%CA0Lk{QKDwM{u;W=E6r#bRAn*QY|AMHW?c;(+6pq>eX!(S_7 zd$U{X_+URMdVl6;;%v|hYJ>E*Sd}swcVkhkT18)Ekks0U$Qc`xevJ6@N{ow1zS(NA zWB1M@l=|_L)k4nZrrWqS&7F5->S*D(PX&_`#ieWAknX}gTMo4<(bv_WnJPU6 zBR$Y)A)zrdnY4MzL9siIz*J;@!c4!}EXfjZOdra+Coz?)+G3-U;b`&ew{swo4fl<4 za{S{dxH!fW95)+>5Q|>2ciR3qpNys55Gw#Dwy6BBTOVxW*s#`R?G$HYUr^D|_%HnH@5ytm{2}0yMs8oNaY>PuZ4hv!BVs``36kGsnP1VUU=>$NN@-noI1Md0 zj4#pBJ&lXLbkX+hZ}=5OriSbY{_IF}y0=4OUQ&kuXbuDScp6O+1=_EPFE*#qsUkl* zD{kg&^U8i%O2H8Qd`n0`p|$17)40O)SuC&m%tyBQQ|HllfsM6jtwLmq2LK0b zTHNK+anBCp$9jF)MufJWi$ou{Y5z!j6q0C&9~+xV>m)MN44^+lOA&-e^rC~GnU0l{ zJr+pLDJ=)(Um35l)~HYN+I+Uy>^0fcBYXayNSE4@@>Z{ zB;Y_bLjN>gdb}p5POZC@ZYLY-m}_?GzDAa1%nD8!G8y(aT5$zxJ?uoh_)qyu_fIo@ z1AefpH`O;g>!tB!xJiLK0!Yk>GAxgx5iJ3M=}*aLnodxZYu+9kg-Qh|G>E#bG8GKp z19T>s3Vf_VP`QJ}U9LzIi@cMV#<^W(w*(LoU5SXEb9kDd=2GXKOtwpQ@H<84C*r3* z4{CjC2L!N1?cY7wRN~-Y7rFq;IzZ6&tJGJ{OrxZ@SYz!hzT1_yYaI>HL{@ zdR5RmQvmGeFM$30U)QGmYu)*q`&9aWtIj{U&m=aJf3So`$u!^{OgpMzcDI-i0Bcji zf=Anro-VV!V~MIIo)-GlMsaAdBW0)al)3;cAy-RHR|VeW-)JBO72m*?hJF09%Db8L zb*$4voWbf_s<*Tf+DN=>?#mY~8?t+AXn6w-Y9{nYgJeetvt|kz-S)*S=;yxze`n7J zcu#Q9=bdw4t@=Q_B(_j25k`~{6ntIZO9JvYqTQg$l%k~s*3in<;azra2K#u1Yv!I& zN2Jg5;S0lD#Ej>xPsj$ARVBOG0Di)ifvBY*WckFa0< zWAFJlgwVfjasJ(VQlm#UZX^?fLXIlVD#GU73;4%ZNlc`@4q$K}VmQ!2L5(-hVIY!! z6Rpo>ktV_;iga>O6#t7SXgcviGm=Im8fS4BD>egw*LGFhK&~BZJiWGEy?XIqbzONr zMWL}2r2sMZ0Slay0$~Ex!gWhT9tsGC=@a)hwbRFF*Heq7mF`|uIgUiM4%64ohFY0& z3VoNXY-TL_x>T?fW$h?|ve-l=QL3TEwvES_87&~GKny7W*3}As4Quc7YW&w*24eVUscr$xpG3HJkQXbdE7OiJbR)CeP48T|9>lM^T!}0N* zw0|j*APEg_Uv(~yUDDW>O7}z`Akh}KZ|P1&Lp&8`X-~SSyMif_sUcuzX#Do6_%VE{vDmB$&c(Q!3f zjN@TOd+qp-_q4!*JB6gm8l3ByOtWNr)Rsnd{AA2~8aRfB!0VrVWp^I&dxx&Y^%09X zM)I7x4+-g1TdC&-=CdQL{*lQhS{A*5o_`j+2n! zM!xb@@%@Hii71YtbyiGUl2dx>S%I^0XOyk_Ws{*d zW$Q;6%@b?#Pq3^tbmcFLMS4SDC=43~nw+#atrTr76{8=ipSJmvN)!36Td8q z)C4e%7f;kXIDOfZpi~);Vr(I^CuT8c&BcMIw3Dl8wQ!g&sQu<9dGD%mZH;+2s%jAU zfKMxdm1Q`S73Wv*3;SM7V+L_h*yNmJXBjo9H8qM?aCoF)>e{hG_cube4`bZ8!kKV& zA+$!jK{cYSb1iqL(mM!|rS`3X>2T>oiSBRaS*DZL>^$edzArsACsK?p86~*1Gr`~E z3Vi#qVO;}Bo3?{r4D83v2CPl`0ykj`<{2gOpP(d=CVtFVfIb2lp;T;NVtv2%@@GN5 zN9eU>ItRdO1xX;z)xca0(dFEA#Xmu*?yZ6lhDI9mwT4Hn3LMw_5DGvoR-+dlmdTue zIsyw|5uBq3OK}h=r=O_HN7E=LlUawyVHLmQb@G%NhWZvm{8stg?Sx6{xVfdiHa5ID zs9HG->pA0-!qJpi#YOa4Ww4NUhPWu=`dCy3 zH;t`<{qc%Z9?`>nD=n*O&q58hYd+x5oEaVTk< zRGhc`+6Qt}7|fTgALlPTJ*>p;=P&0vsg$UjkK8(WliH}i{7i2lh%o~tHgN;_O9eaV zY{AN0qy`)07NLJM-W)k#`rTV8dv=Rn>t)!rWT9!2!Nb(ECs_sqdV)mnC8oRE6eTE9 zaKpiOm@h8AQB&<3dWT6qr;zhzupKqs{m&A+G`0(d_&V6Bgw}fBA|*#gV~2Lu>-HKt zzTQopOj;nLTwl*vkKH7bf*$f&;}6*kJb~W3BmI9U&Yv=;hB4hV`hV&@|HcveKUX>b zcux$vnLpl>m=v-!ulX;8ZN^YtP#eEBHj|m+uYdr9X1w*$yadf8T5|1_C1>e|ufN{S ze!!}aHHXxheuQx~$K?l~9L7S-SOWks)n?Rd2M@3BfEs7#^lSH(r<==sf1xIPFBphl zc_MW@#gy@Yjc19??8W*TNsOHgT=7W$TLhO6pZJc2hO?v=x(x zKj;dyv0d`oT(Hy27g>MyGab2UQbMzz0V@dAoPsiA5^>)n@l8W@UsggD{&w62zPAIS zD)bX31#pC@r7e?9#syby5-1@jRq0XY=&JeGYj*P=L<+zgN0pL93g{I{NAN9m23o1X zyj9d!$YDKAqnAKLS}vX}-zs-UQpDsJ-|svIU-E1br=pPD>(5iQ`G z{TiN$A#XJ1_a*G*kH*Zh?R5q191p#OFSw9X0plO9LH&kF(!4=r?Tdx3O}~sU7Rc8K z3&04?EHSQ%O2rgiO6~CfSYL|{Eh#hsqoa#D5Lv?3<;#bPcM56*=gi!5F zMGk(twjd&gh)k;005C$fv)+vUCA5VXBqFP*8OpHxbFd(di&OxN(3r86kfYnkFSpwy zTmVKWERX>oEf$mUa3E)&q!7wtV+ur)e%T6-CYgy?iKFu~fEZI+@(;pRh9XQz*1J@{ z&1l|@x!swQ>}HGuXa@QZMyQhnURn>j;*2=tEg!jtyL62;x8j06Qa1{V8G28n<;JCf zh{e>8eG$HI4ttPwmm}&0y|H*!m9RNB*v88W>Y_IP!WR!N=$ZZ7gV)TMTlRL#(~T}n zW7jBWQX}FldlUa~dsQa)@FJbV+sTmG{BoloJnFJF5U%U4FQ^w6{qbxUOd|`e?!1Vo z=IgX%zFS7qQ!8XG}>gI=lM7EvwkO>OoS)OD62pFE*Q z$F`7KHT}}pXa-#^?agqq`~9oOrJMMjIV1_7N^0+`5v4vrR)h^J5&M zm4e)GZnG^C z1}W|nTpXEe(O!CbyeW*)WKqA0Q}phfoUmwD>0mnIQ~3FUIW0MtmmP62NTYSpYkA`Y z4AjA_x#)ZeN<+%tV&`6R;>)3uKe3ZbYM#YTu}m)Bm0lJ4iDu4}tZz&;+6zfw5V<(h z=$ZLNM^-LzG=4aEY+x_x)$mlceZ%~=rclo{g`qFO1yR&YluAbz{Na10X`YnzUzw zHRd}=A6|%WCP$l~@b{`P!;D;}%Xz|28G?|sg z14mS$sgcLPdv<>R{yI|Gylwp+@!Z9U`fWQb#O%7OvoWV+|H?{fXlTEjat(#M!edn@;)4xF>&V-B zSrJX>%@t!F=0aQYkA%Nrls+C6R7hNYCKringYe=!9z5r%`nPD6q7?OW;4EF?ycpEs zByTG`8Fik^DyY2$OwH#Txr|{ey`V~4SKSRZ(Que`isvkbzm_UARQTqls_tE`CZ`WN z&GOj@O+c3c5hDIh^_WcUQLu}+qKA9&snW?3=u15MTfXy;3xyYWgP{CRUFiRVD)cWZ zo&V%Q0aT&C%|IQY)r56cY%2nu-J*p3sgaEg>n~rrI?T6>!)WGsU20Y9A*6?m=ABAa z>}Uy_v$Rt1ROE~Jf_smtar~R=2n=i9iZlSB~6Q9*e@;=giU zL!o`cz8W@|mNk)1646xGwN6gK>g>aIPT19d8RYM9@WeVEAon@?>^qNYUeIpbo)*4< zNH*J2Z*|(3`Q&Sd_MD0(L4vwuMv8GmcaPLN`Z6pe(%TcT3;I~b9|6m88$1(HHZr(* zQJoapy;-`$7`tu4cmZX1j`xp`f(F1x!Q4`qEyRC10{t6IND=TX@aO#VgS3k0pWWU3 z-kT{)o^}>P#5Qiy@&1APN(6ur=vpL9l(neQ@H#>BGE+E{62P-GwdRoP zzXBelN$2gQe^f+q>I)9TQ3c4b5M<>#U}tc*3`1TXu3x=wT)lN~aUO9W;lmC^Srh?9 z*#pI~q5@z-5+Mw8g==;(x6(nan=?~4Qkc*pWjG&~)GbEnzvk%cz#O`W^$Tew=P*st zC|(-d{hMqp%A3hS!!gFoJ>GbWSsW;#rILWc@=_aty0MR1_yVS-qW}$kkZfkmPt4!) zK!{2LG{C(e#}6k%M*Ve(zJ$ET!Djuq*Hj7Pd^U;hfu^mhkd`ls2^qAqn8D$I-5`hT zM@(b6LOs-0C8}m~wp-lMSJ1q)T21$JW4z3a3Lb)KUE(f6SBGW=UW8W`_Va)d=q-L> zH%i%-pzm>J;1M33cneTvyolwS1f75FcIP#D3~T#J^HAvJHHoz}*x6gycnB+?%&9L? zN3`}Pkp*oLwB2cMX?wM>z6t46gpXu>rF8!>*Hi;tXHhgoH@%wijF;xw_zL-8%RF1>PYSH^ROhN`+w&4PXM{K+ z;@YK@?FN^nu?rtBqf=x;i`Ep=m99h4yD)`oSiTX&Y&zw8lbonPfm&7`Ts9 zkLLb#=L=A;nXdHd$*{>pJ$3=K`OJW zNcu&(WCyhIj_54iek^z2B)Kz4w# z3K6QsW+BerH+l#a<;*0(2D7tPkGX2SwL)yTQnwxcBy&Yu8(+p2r-fo1=m}4)M@4`S z1%x_r)S_2JzgI_G83E?SiJOPTXYbC@s1{)Oso^2uzaHfen^mk93%*QB2n;Qw8M6=7 z+TicWQO!})GPY28@o@MuR${|d*hMk48a~PW@u3p;YBJBxn8l-_22FbamJnQ)!A#X3 zABuJFA+rom>TNQ|QCGMZL@GdzM*%+8Io}z85L*{*eh!bxxDZiFVFQ*zuY?qYi+2)6 zx4F*+Xy z0i5lMNmTU2^GpYm^A`xodwO8#ekvL++x|;o86))dNzkVpI(y=nO^9XL5MEI2y>IJ5 z8&L!FmHF6uzrsHSAl^~pwb>Y}%hl{*v`fA03MY5Pa9jzSvgl9HdTsZPqi}VJo4)-X zICTP6Wuuaq;js|z?59*+9;OMxp?@|%&7Fpul(Q0O!(^!0y$btO;;3m=;&}bR(;;ux z%0tI_^m04(>t}P%i+N5BUV!?i&r2h{xoO+EIplL)>GNDj(RjG8CBGDIn&cWCB>zQX zbFs$&O^p`=A-%Uk&}L5X(+#lQwIs|@{}>I$q-kt*c$z0yxzzPD3sYQ-(G?_jW+J`^ z=T>GQz=txc1!nV}r<$AZ51jGVn?RlTt<7~M=$Q?bqA7aY zG5LGY^_@a$lsR-$1ZH<#ndadN7D`Wj*_vQ+WNBYDWi(Dw z{9yM8q@25LE9pp~+w;Z5C2ukqSNQKr({uV|QC<^DnRKu{_}1~ED;bfAkbXeFTih(f z<)nTEH5dN2?m0;fLB2kJLHvj0bOIy?a-6Re;Xn1Ee?tlx1LWq<`De*dMFgx;!TPgG z1>i$f%K@ny8dYWVdeDVNfaFv}1X(D`q?y&34q_ElgM$Om>8)dV%yd#wqZ4!KQ>>9r z8@mL}7OhIo@WvmAT&#uP1Sj9-q0;I4+T3(Q{s4upp1Pkrd!D+kx;j?B*-B7A8Xy4+ zED3=C0~v6=bkYoz4*eaS6+$$*`Fd!MG37|1{5d6UkkGMIh9kvEJ``(;&CT3#roh=b@wXp zOzJ|~N>uPK`BDRLB5gbV$UWpMJ;if+_opE+bzTMQf}{klv}ib72^c{2a_k-}Sw0J2 z3{rw-L#P`KIbQ2Bym95ZRsC%s-4jtaum#TOC=sh82#~)errNE&FJA(UwK&)E`FUi1 zLj|jq&T9g0j1kEo^xG(dDNq&{FNx{Sq<%=)7pE9yD4FuM*gh@%XJrWcCR|^oqR85w(o-90WBwdhpxu@O?y?sDs)4}S=knfTgUd|0My$UL&zP;H zaR%u(@8lvHv&(#0NAIY0#A_SDWLU^e?f zkrky##@#q1S{ztfEg^<$QJH;W5^rUoo|y^oiO+#a*6Xn)Ulf3S1r1_JfYH~s&2T}j zA;cTm`-0)R>+L52d%H+#nSS=rD0LgyuH1ZojbS)mi{p~a*o|sa{+3;fy~i{!61gIt z!EH=OZ!=evO(n1N>^^v6gsW1y7OoaF%LQ|pHQ8#*!$6BLTkK<~N1^Q1^7Bh99q%w& zPKk7@#yG|UQhpb{N-QzUYvn55KzgBcL$l@@=0YP1CJkJpI>j^f=W(vGH}_YY`tv|i z{YOD1CysJ_N6E_UF{f~`=FQ2=`+9ib=A~$M;9+A!!#ruaQU<5m2X5#bQcv^*8WpAl#THi^vCq=rMu%z`N!Sx}tuN9a7k85k$m zjrN}rXaY1J^X1QMvRXr|!di1u(lBwnVE8?(SC>^iG)P z&Tim`eREXkR*w&(?`TMK_Rd~y@v*1VGDSKOUpjw zN1#trM!wf1w!#PI{iN8TxqFoAMSN=(j29wOI3D6NS5uo!)k7|*)$-R{KbvURRI!Pt zrDEJjP0@}!cU2-(K#$vHXcvOXqa)U3^o;Hh?eoG~>6q~@3>iz7%IpGOY|gGJ8CL{G zaDgQL4k@5FgTWM4ygq!v{fG4YF`!o|x_kez0sVh4h5m)t`6mMk zU<&>J2K0Y7pnp1_VHa)R_5qzw6F>&{e{JIatI6~~P(liT4}m}DpFRfu2PO2L+X5gx zs8eb*0vex?sK!)N*NV+P{zEQW_T<(qn&VLere9&kexcY{)a6pjlfsT-2-j&dIu)mT zUx&g5qs%dagoQA&6~p(l8qWX&)_J#ia#IXk96YYyO#vF8ynuBob}k;Dyx_pSXrMqo ziC-9jfo_f=@yd=G1znj!l@44Pbp{WyZ0n=E+t=x-O-{LZpa&nNrjW z5t3KKO+;OA;BbNux;DDfccAjYhKzvRza6#!HK!Q0@QF@K`$Uoipr^RwK2W5~17SD< zS2+T)=V~S!?T;d|H%ynf>q<4U#K>9WJF&sj%fVbu?p88oP|r;*;opWCJr5V8y0@J@2QIuCX+t*zdC zmt5rHy_AC1ga(V2(%68v+DD>6%?w4eZroFpOnlftiY={c#$BbYMW#A_01pGlzX)l< zSq@8ro?8FC*!ECSaaN{w;Qr8dcj|Fo4gpyk;_V+1qcmEFn4)-V$!+FCPeTWS8_iiU zxr{x2T>Mi3=rdvD0xNi9$t0gHy}7 zgZNR4Ryanr>o`!vY{8wG_Zem_hAqF)oS(xImf2z2-X3wJz0@Qx+;-1qg>7P~#9EDc zGE)c$M}hyr7#}*)48J&h*9m2FSde61tj`JUSNsb1LHs&FT+G+PpXdp%hR_LukV@LkyAF$=F&*h4E+@5*Plwd2x`BnuHqve!&TU&(4jhh#Hb06P;YAC>o&&{t}Z-+;jyx^0?xpck zjfd~JvMkX`7-}~TRDAK5H%q2p#BwsIvggM_sz7lZHA%K97MD6~D5=V^9~5P|tSJ+7 zp!Z)NzGne9>8IktS$ABj=pzu4ePT#wtuTK{2|=4fu9ygr!jWq)NtUHTA#f*csnV$$ zEHa8zj%vxEAA;vDY@wS&t~#$4XTAu>T^JkYaYzK6o2|VkMgP2I`Uq}^(J&8sc&KH< zTXGRT*a{Z9_LN1JOvJYsA;L3665VMfwpvFcq;4e65(=s{+RG}AO!ywVUoGsqPDC@N zDIy9R&*F0%7Mqz2i!rg^sZ<+l!Bm-0N(d|E$Tuj6V93d7M;@zTByo-o|A~X{ zsW`A@j=3rFa`*`D=rtuG&>r1uxK_fo8$c3m4(lMM( z<43QO8`s^M#*6oAfTB13#rndihYg7E$D?9~JD=fq6S{2i<3x)Ql97C5o~SrjH1;Wx z5wb5toYL_$X25f)$rh%LE)$R3*ng3d9;?#D5cpN6n7K%K&_YJdZ_cgvZ= zq_;fdGmHy_M^aOn|N7JZiZU&W<(C~f#ys5AI*jG)(RluS+TskEur*I(?i~vs%ss_I z3LU{Azn<1y6UAR%XzP>N25Hh=EyXS3kd3b)Q=gH)95jeq{2T-5ZDI|~gSvgyl$R?B zAXp1u8Z@sFeVW|60Q<cL^=)ZfNTD1~uT>&`uSmV<={`C)#ND@a8!$GpB+9C_4STMI8 zf7Lo?B1{aY(%9J{FpaoaIOVb6xF_iM<1BvQ!G#(agK@}B@o8G3A2GS$ zd1a-_pjNad^p7;I!-L1ui|%gARS?Q4HUT4GDim#8+D=*K72#XG_8s`GaI~@8XzgkrnZ*Q zB%Qu8ba=b~Ng0vHcdxx_&lfU9QTEWQx7_U;!Wn;#hk%>}+F;gcaYbz#E;bba2=dFlj+Ub5>QIW zMptGI)_?6<@At2w$l4KhsOL~I>aW(UsT6mpsG(H=e*S3XP#b*mV@WY+!ug`F5eYLN z+Q_acG1;*$kbhU|sUg5{DtMH=fwCG!e-fbVewv{{yn}rP72z+r^bMo<)%JWSuetw0mB3l$HL_kq zl)@_HV{Owl9}q#DF-u-97XVM@>`Ay*GkpqI`rbaV)0=YU>LL&1f6h(oA~mj{z+M#> zopwOJFlTU{q{f#Q_Wd}1lf|h?NgPKz!Jze*GpFSUd53vI^tXd2-nowKQsAn$5QY=%ExALcALa#MzEK@QZJ_kFr+VY z5iT%H5y@EO8T3*|ymPPYFH9Lc`b~c6?6MQj;Us)UDHwe0D0fmj^u<(e!2HykclF^!^=7YY65=u0-gMP0zbs~~;3~YF-~5pkw#k%0Er6`F+fK7z zS1Yur<5hO?r&u4E8k6kVvMxCWYhy0}PYp?_90Qg_V>NiOospkxVjE+|VE5p|N3#JOR8@6SgW<2^hKq1b61Ns=*mH5D;SmGMC{cpSqvBEQpaBaODI${A6lfkfZARg}?QSuM(IK z58bySvDd9^uR!*e(8u#@zDZw$&NfxDxBE4_5OQZx2|1>p4Uib3Of7H+q(?8C!5S5L zv16SLL3FctG$mg0vzRZ|BA0hviJ1%L6sQB4Ouq6=YZkyC@@a~EClZm%t7s?|Z^lSR zfuUL3IP}meClDFL87_|G^>gW3a3%6&syL>FS6j0!=J{O_~(B0BV8n_sDS zb&5wDqkN#$YI^=DLmQl9aX=23Ud{qCw2VMsfQ$^CEQ}ePO`V+e&1~rnoxa-|>l@qI zf7kz)PUUYA+JE6wnv{6u2N=;Z&-8D|O(?MEIREbmt%npUg$BIqUlH1#y;Vz5$si4l zH-~OdzE?a!9S6D>AZ;?O+I5X{(qJ)3W8gZ1g?jwl?^SFfVjQFLm28iG@a3F>KHgm? zT-B&ZbL~b}eUl`=&h>85zp3Fl#Sq!B$hDE#j#m4ygu5I{I@Qcq@Xu znzK|x`{S=(bAKY5nR|^FiNgBuU2cdrt&BssRpb1g7Iz!So@@9Jk7@@R+>;aC%uD4A zq%ww{QI_&*4tS%bSqO8BNs&Dud(d-h`kL~<4j=p-1hcQ6#4F)%O5X-h`j7 zr}V1h340dJ$gp;Bu}H7<))WjaJX`dU{smej?m4n4l?J-E9U*DFlQa-vu{5VjbfR{q zQa=;z%**cfzc{q(fANBNpVpmfaGoY2egI7*02wrf3xEL`z`h|j>^F|dQxzHgxTQ}> zZlg=UU?}X=w%ElGEA7Ctq(~V}o^>x$`~faWrif6te`<@$qGv55^hS0rrJf_ri4u^M zn*<4j_Xx+GTgo^V{`1;%s(>XFDtKbepEuy0+Ye5+7aAGJp>|q^HZQV#m1-kgjt0$X z$p_Lc^3a50;B>)23%b`owm5lJ6b;r!Lkq4{-ybw)!^f6iT^DM#WZ&5R@!Cdiq9y(3 ziYU;UUfT8qyIgbtWeFUp-<~DYN(`4ZCw*ZVh=pY{Ud39WxIV486;Oq01lDVu2eJ?) z>VhZMoF%bVG^ov`a2N(V`y&wq-W&}2S1*Ws;h0CFXsJSUYSe|`$p+XA^IsgwRgqyU zB~xb^b!SqikDlv@7Vb??^Y3tvJ({jde@W!_Zzea2I|A^ZW#WesJ$eAi&l67{I zv?}^9*}#NiWP%cKMc}tEO0DkBkJYf20)gp}+^scPU)2pzQgvg9!=ccxIMGm%*aT?a!QZbreNW#+dP}m61hjv$R#3^{&+=Bv2Y!b!3l?4M@G#)ra?o;ueYccn( zDL(Eo-7Xph?DmoJPSO)6)h9k5cr^wKv|s5Dx1ewH?lbaGS_DuK&Rz;Uv@ks7#o%V? zzw0$%<4GvP%sp#+W(}wzl1-aQ)HU6&Zq}}8Sx6WMJI< zN!N}daKw9z6jHsACoHve<;Qk~5pE+(?;gTlkd;}|B(mEUxbFqUqrs{0PHtVd`Ux3= z_0&|E3u&6k%1R>JC1C~bS1SBT`$Uig1uq4?kRFIWm+x+OihUH%QY}BF6ZU2LqK?v_ z(RNF&LeycZ#R)0ZJ7j$RJ1q51*k*-@dNQq;wQ<8FP)kVDfMvP7pcb`AiPv|0o|c~_ z*QEzOTQM{kL*N7|x5Xn7&aV;*NJy|^4?=h{){L%dWSJO0*DsE?7UsuZE`Fft=cbNCCW&TWY1Hw3n+Bn-NF6;$UDZ;{9Ce4{Bg_4$5yJc(*R@~|4 zui!0%0Rjp@&~`t9@$q~?vT=ekx@LX<@`LPYOza?`k6|Fr2t+ZL<%5 zHs8GsF`l++YLIG&{D8}K!f#xPo{H3v)^b)HTSd*I(GWLGNhv%w@`J$(Aa+)aTsqBP zCmMcHSP&)KW5#gN8(lUw+VTTXDSw;TO82wX_d~N-OohI5h8*eD?OPmUt|a0jsP{WU zg#KToy;W4*ZIZXWahKrk?yf-s!QBb&?(V^z;O*z^mpO>Qgf7ea?vumb1sz;mts}iveaV$ELO#=1)4A~^y*jX zm1pbHN5Qv!(wutOd&>OfHLUN;sS5hX=%G)An5xNOKQSR`+Re~OBIwr+RK`4UqnAY@ zv&oa&@thPwmCwTvL-EbBX2cRxO!fxV75hTOW zK)#SX$&e}c#}Nq{&`PELtQ8F~C835BuJ}~K1qC{*L~QXAHRp`;a!GP}v6mOTR}u1` zeNs}&Y0JMPIlccZ!hhPgvfc8wWMLE*rFh9h}SfmqX4-99M5*qG_m9i^ulKcCdosO=hxH==WvpjrD9H#d2O!iYl+ z<}1G3wMpFh2cpg`k79G?LD-}*9Ezj!uN^@@umb6`Q-EUvD^TSBp#uGbH|>Dc=i~d= z3iOX*=Bsekv`0sLxXS9eLfre&t9+w7xLUQJ;n`%yv(v23P!07|ATE$9jh=R>6l$r|u9Cvc4U+PUSu^|0BN zM)gh~h33nI1Q_85y#xW=>>$~jA>j)5l6*=^o$GOwNbV2A{22sA^ZVM_ODUv(KEQbN z&Ok&#sEE6P$#20dWb|xSByClhOgU8T-os;LhpGTv1QxKHo7C(#9SXCS)pLm6HSlR4 z-p>Hy9&?@$3?$H(0~7!al}a6S)qjt%6PrMQiMGeUNSm!&+oipGLftdk;0yYNxxx`u zsMt+j4e)gxSBVI4U^^EQo^o)to1Slc<~ryq?PNJu6e_AtY!LS9nu}{^(?kibKy5Xu|-|8S%et$WU2xJu%d0;A7nT)c)u)ZZ) z59L1P3!U(169$uY7O#N%Ng88f)_trM9M)2X>ZoRVpg4iNegbznzP^kdC#A=6ud8eo z8NSVw5gEI*%6))YyGl}5gJ()V;m3{bc}$SfErrs1uZL%)I=F0MaJ&LglyV4MS2mse zxjir$GqAB>3Tj~XRFgD8zkUzeX7c_MoS-K)p&cmwKCqI({l-x5m{fn;PhmffxqI_< zom-x80Aq*T%JXH`U!SATU%rFAFj*ecrFb>r)a~odzPOaHw#*H5voXQ*?~96kEY9*Y zSeiIREqi@DU9M_|YeJRPgSI=e-Ls(YQ;Gk@zUrZY_qg;fbWt0wN9G z+&8}GL9^xUwiQaHgwtq31A4Rs8d_P+F4G-^deBWXf;)-W9I9a9kI#2P zY04F%)E6+8m&Ir4^F5^Nwky@#H)t4C8jWDlsc)U%+D0v7gK|SpF!Qg|)VTGX<2gpc ztRNJ1_t(L675e5iQmmL~3ruU_Vj=P8a+qdLj?tr<+Dp@MRJii|13B?6xn1 zI>Hyaj}aw2GQxerxPgalyOj^&hmIg363Rg`b4n)f!Ax`#Lw%MQp{C1CPXNBQtLdRS zK>B-Rvp)HEPlNFu4+p%q3s&&&jnju+3^7iDPWJy|hjkg529p!7W^G^gP}MtfI%tG* zfQod-EWuk$U8h!O9S!W<^^Cliv8Uh^H-_91kgHS= zzbfY>CG=!Fg;63*7?r1xL~F!C=l@2H;f;2nx0JPogtr+@SEJ31rf?o}bG@FhiEhQY z5?dr%a9$$A17g%AWW$?A&i)e$tTaMrA5mKielRf$Gw*s8!ab%BvZ@T@q_DGCZa!x| zC{fj)a6Cw@v2v8+t^5y_yBW=sAPLuZ@zvlh#PW_S9DP2ljoQvb^Ed0~S;>yGxrOk5R7kO>FU-^|QvK_9jEED5K29ZctGil9GD{rOM44>D3d${z3V~uld5c zg=L^ysPn=+w1SC0+ec5dcn9skAc)%-n3iBGGL(1xPEcv^CkD%FED@pBE+g7fgh9%{ zVDZo;7nPI8SC!33qCHJTBD{{(VQ^1MT*p!{Lul3hOJUXTr~&N2%ar2NnoAXtU>zqb z-*=r@@il#@r`cD(Lhms!_CWaSA5XIaAjc!=zYcz*6o2;d5A8bY9}S=A>^H7n7q%Up zI90_TiQ!Ru{aScpT-0mqrso~a%iO)+KL#K|JfW{hYtxm26D`B6$-)KZAYp+gq7nZ2 zT!@C&8c;*EPeV-{uPH?U-!n&p@O&wq zF4vxL{ORm|Y3=hN4L|{#Rtv5&S&L7+fgxdik?(Q-5`pPjbUhX;Hj5eSVLVb_Z=^+8 zIkN9l=osRFf9Di*HM0w8716x#U;P15Dqe zID9x+r&^ry7mbG10rkJ7=bCN9@(<+cb+~aBm$IhaH!1THU0m3Mz5q<4oTc0-{}PIB z1~w6Pm1%7sO~ePrvj5L9_AeSDO<@1<@%>8=Vf+`0z3WiZtXYok&@d`V`HYO+fV{>p zZ)Zh|#d`2oJ@A8>^as+u<;vo{3ZXPd*?uT!a7g?U??n_@G2H6Y%gIs{n3~+G(fG&`6cbb4n)NR1)vy^Mh9txur zT0x2XADXk;Uhuguu_Ga-BMuPPy9MR`^Lb=VqPPro5lU>%KgA2g6=(L2nc@41$f=UR zhypd{VckSCmhPeX8Num(U|HJjmtB6(c|*1%2Cx4FpbO@)G>?s`{=I{*apL&Jeq-Nx z3?s>Fp26Ws(yk6eo`{SowgNmF<2D`_@J_dUzz{Lq&Z0!T%$nCGX#5~2j;T%Op3p(C zO$&$KdDa^HCFa-I07%R|+ghr&4Mj1OIh`0zddh>v!3x}uP`_&fMP> zMN04DqTDt^fzxvnQ*ULyv>tb6J`P(4PQprFUMUeGX9fc?9R#oJlmlQI&F%RTku z&dYKLB!{1A&3mrH&`)TLzELjs%uHh+nlgIziuC<*);c}aLCg&VR5w|nWt)s3zIgk_ zG&he1z)#ldz%$BkIkboU=|i&~mnksNIq2P69)?JsmEDyqk1{ABdNQSZzeQl|4>xZe zY292FQIelI;C4I3LDyKl8lmPh-NFm{HyEVXn7Z>-=}1w>UxWZ@`T_{mpT$}-CtZ2g zB9I8t8IBp57e+boV$iu+JVZN2M{+EtbDstCGw{@eu2V6gnALK5!_dP0U-brDQy` zVS6Ks*n&^<<9W*m++$Y@fVlJ_u}K>ueHI=b(N>auHhYzau3C>%ZRtqI&#;}r1$UW> z+zbmFggG;jX4@MyFcJ5k*geAU5}RaOWSStLVD?pO>~5H~!fmsDk522JF~5lykyzTP z+$G(x7VG@nMD7wfD`Msir6yoH8Wrf|DBBS+>l&D$dRL&5N|!}egWWYS$~Kyc1E;te zFdxsPLSfJKz{WWxc0B3G%5&7N`{yopdNto^)0{>C*+G?hi0eeZ${{@dvzhV*o|=q? ziZS9{j#>kzfM%NP3j1rP$^nSFb%?`w86vN8fa;x&-!1Q$3r-SA@ry)InOS46%55c1 zL1)-ZAf@ipgu9Y6eF@G%$qV;Gue7@&_0K81- z9L~HK8=@1^_|6{`nPgveSdPh3sir>nO`PW3{nqlfWnvVph?)+kt zz%8i7bFJSpsbncP_l&Y*KT^UkcF53wTSw#^=9!f# zMhm0|M86}!%$Gs97`thGqu%?~q}Wm^-!}4tjg$B;vtgIocVl1%o3~ZNO7Q_o1+#rr zl7$&DAN{c9=@U&?W;znL#SURv5YL1FX9Z*-Lwh~wi@dy(xupx@mFw%D@XJVpY_ykV z-Swnh*vhsSZxZ|C4NxbS${eOYF=MWx={1$g*YQz~z+Vid!8kEg|86jPl^)CR*Y)b0 z5-r|`pHA-CUpZOmTLr({UzDM?>2^I2dn4m8zTWM|FZU1C*ry~JTp-YnQ^Q$MPo;oV z-8?47w-VfXjh}xrs6@AXVu*0!I=#Umpl413r5CV@CD72;NB(8DsD;^S#Z**}ItlJh z(epmOMZS~vV%64PzOc?i zzR9GVxqJT-muQ_3U^>z-0@PURI%v@w39Eo*j__3@2O)iu)Ql>K4fr+);|fmg5TG3Gb68N2q0jH*M2 znQ71!FozBRCZWHzC9RByK@Ur@^4neoh!ems71;^63j+5kgmM6+(}DVm z^Y#Lazra`aLrnz1ZER3$QmkhyI}JBc!nv(9Ub(zLeg#Pz+Q1_ikTNXf90MvkFP8|q zgIztNmWmbELeHY9SJAEd=c;6;bj)*r;g65SgeVA?!iwd+w}yxENt4TszT!10y^Tv7 z68mFn9`dSk5C?nRMf39ERe8RP6>YaB{*jBos+kbCovd4gpyr0w+DTv9E7j6$kEnpg zq2S-lL=_MD2!AsZO)96PaPu%b-tI{M3?buuPI$39SP!9K@H2IMC*7Blip2}5Gr#iS zECw!wIBz@i%hqiU#&W0YI6+B&EQIhv|F|D7TF^SaJppLg?t-^47%!+1AM^e?;&ST; z{faCSnrVCf>j!3YLtE$gS8>GI@Kx@1r)oY|yRhyF;-9aVJPJHX+r&cW1ZMZB-)doX zlid`KeSLLmV|G^pX+g~Vl8t;(xw{{3IQ|swgQy(5_@o!gDzu6z9E`we!Afe9RG$ z%yHYlnvup_Y*FbH*<0L;NV!&Eq>VUFAcRYmLX&Ra`G~fKRd6T#(oQh=DAh&$Nz=!d zIV(?!q^410fhmuhP+o?}5o#jMn)HOZxOFxkxD2uu#(J-{TCtC>VS($ra9LTn-U&qYq<}r z^)Yy}gjtADj%h_rkI!(Bs2xy~^~>wGV_^MVLbn6L%$OW=Fzl7W3b}CL;=^EgpY;7e zN=-=B1^a2d*D&+v1NZ?C!A8|bEq<=gLp5ZWsn_}sam&!~ipzW`D1oRPR{enjzA3%B zwreQgFRcRdsm~C*ZAF?RYUqOsr5`KM@ciq)ZD0K%4(OEsr8*#{oQ@_g0i}Hw<@{~k zOp0~2x=WS^vNuQ0>R00ebLo5JF0wDlPFGSnqWE6g&eM#ra&i{F z8&b<FxEPQ#L9rP{9oAu}BGO2Bk3+4op6>T+D7AyuvpdgfYx2oVwpWDm~Ubx}$V$ zl8jV?^u`g!GfV#X*Hp=_*B&AV3hcsck~*1xKX96aNHDgbE~ z1xU01BPr|OX_kfIFEIOWXy`v+R>x-m;!9j3QfBCX2eT2!6m#fT1I1*NhgqI+p0XB+ zXc6EPb7r4Ii9I|*2Os)Iux3#Xt6*=Qckvkf)JDpGf!j~23`nU<#QN>5>ggzm8y6xF zVH9SNlN&jhkC<+oCqmNO6-`iTjou z5Z`Pnxg<;_75px5BxS%Ume>rm?e7b*?zffLOfg|witCS=EU(u9Z2;tYtH7FQ*rqad zWd%+vOwRA>+*?z$&wtogABRwHG9=W@`GO-M1Rwm&d+!S`={b}mIDZ5;h)_EHSPEOF z<*iE-;`E&xY$o@Lq5o$e(F*J%h`!zKWBu=G_Ag>1Jzx*<@%?Kb@sEwt!sxYGhl`2| z^@86v^eoEK3`id|yGasVQ=#{Fv(aEA55XvqW*y2fDbiI&{3q$?kDV0g(!+`1_R2fr(vhT(Rlq53HZv#6)gX~OqdC#XfPY@%GM*NG)&=L?B;NX(6^ zikFzsg5q-2L42V->~XiT?REYLKei)R^W@WQ)2Qyf3%wI>3&EOE0@Ojh4{Aw1>2FQ& zHjf|rAEb?)CNa{ymI$9+C+=d<=Lm|MQLI4|(Bl!o`EA25?=m2bbvP)2Eb|rN7S=*l zj$&jpdZz$swhT7Td&SwXk7zSF0*vU?+J%XCLt2(`R^5+{gZW~Ct{Y}(bo%%IqggsG z%H|+adc;O+*L)d*KijDl_wkt z{}Vkv75l;{+{0Kz#&O4<&c3od`kc#PZ`6swv-8L=?G-=5~karTkix}gVPlQ$%b@~Gx9L^@9NWk zKHYi%eh-haZl`@D^w9C6OF809wI-rd-JN$&JD`C>no>9T34Z@c4REm8H z*D?-@{d3b+4!{HsP@hf;0HbY7$xC_C!MhH>^cirP-S)4Rkg zCb60-$L+xULa9#~wn<9#g~|F0CBiaZKUrh0^V;_M9D+_no-4qGwi{#c2Ne#xUQ?bO z^ejqu{<|=&chYn&UWT&j2=|kPzd|5fk z6EjZc=iUhG#uM!2gcXj&PpKnjt>{O0B#);cdjxz%jE8P78cNdgMlN1+;euNJa ztMOVr&dI>@dYD`6`HnXS{$~LUTjti!tt`iKE|X8r$+9?7ggWSu=axSub(C%og9Gzm zf4>yhqQ5F`EJwN}yzQQ=4Y_vkKTUfB{FC2&uI%aF6|5qQ3YR_mAeRzgIwDP_Lzdjn zMkT%>c?g(1&^63U)`KRixDelb;4J$pP_%27h(BJ+2JOgZSsA9o!4=OF%2i1cfb4Z} zk>nur<}x$8RH|8ci_vAK;vAi+MS-FY#TRb9u@ONgjtA*H^m?4_d;2TOp-x+ROk^(5 zEMag=YTRcf{7xy!d%(e^4;zK&4<-#cCM$YH45aQ|!-)S`)FANg2-0i1CmW}nB0zU0#3^8389 zUT|pDqfij?$FD}>51Lh5RtM7kZoh!pQ0?DnwkvY=eAMP&X*O4T$m-xLIQUl}&4Pu# zm@P+}W$d=0EEgp&T|C@uehBt}wxf*&Au-4XMF0vkAPxiN5&*c_M!GvfOxg2C5F(M= z3Ue!zn){lH(*uQWGr*HosAK?x;vNnf>mclr%JKR#Q&$3n}$E zP9DWd9+W6pXBHCNL}>aAoS*S4UKSbD<7i^Pz;qYVV+`o($DZjgdIpU6L{A7POsI}& zcuz3?f%aK%d=%U2gyjM-w$QM0Wn5~#uYAg%kafV zc_!%kXT}3{)NicU6MXgTU{#iI@kp#C38(xapB=Ft`$Kl5A)q0aHvyC#X$94^)EPRO z79U8;#IBz?UeB*DQ==w#OP_r&@S>)U+q2^!*Eu~%$X?4tY#$slUtHy4F;$8<_k$U) zjcE+oHe=-|Jdi9@1Dn=Br5tvqF6+dT*dP{Ln?c1O@~09y^LAu(ZSStwcrfM>a)?n? zo;oaq)U5lX2EC3Kw;FAWQ8>8!`Rnio*n~cblIqDRG9&E?>NIVV;^%Zbe4yYx?$(|} z?9pe_rK_GSM^bm*ux_3z9FZ!Vk307iWId#?}#>Eg0qx`$?XUndG)ayUQ#}T7+#V1HVUKSvPZ^whX2%M?aA}}0-V>h?uwqt@o0rX&+7hRwgQ)c9VmVP&^0JVe zL#S5t?xLlx#b&Ew+=?kF2*X|QbnIc3{}P66%SPrG$h5bhR@Z%kR;Bhs5UbV(`j47O zm(7IS@WdJ9k9Emr<>KQ2i9TtPN(WhoxNTU%P+QaZ?4n2P_7tZS<)-6UftW;#iRuNJ zBI4iVi0PI99S3-ZROs0W+MHj_yj{zQ#*MTiu-hJ=ZR+@YLOz7=g5_{V=0SDWJv-b# z$eLqe2=A%<5PH7AdVUr1w;K;eNWGK@rGB|f!taP@#l@2~KmzzM_G(9JOVFA3UXbsg z6&U*#UxdIvd&O!l@D`LR5(Qa1`Ef4l+vm$fnQiRg9AkA8A}p${f@Go z9WJxgtQj#sZB>El=rJW8j<&STU{B_6p%4GOID>93*Y-2WiS1#=t~cX4HyLi68~k=X zJEW<9gBDcRaSif`1zWBN)dSzb{f*KFgp`%nPj>kxXM`&e3I)mLdo>Tddhu@9cL{u|H23E}{G*5V>75kq@3 z_4wvJu4%L!ob|5{s~^Kzl<1Pq{{zncC+pF_!J&V}S$ufH49{r={bg@ofB)e^%Q>7y zcJdL9qQ|X?S(zf*-3U1e*-5?!vWJWX8tNn%Y10`aEaBT*WSMiZIhX=+1|9T+I}xN0 zoNWie_GhSN5sA3OP)b{wn5E5e?C=zcQHDgnNAOTnS2je zLDang&SskkCL0ypkRXmumKRMUY_~Jpz!3gI{bwKXkuh#Lr=-OG-{b6G1WEr*#Mt;h zaJI0i@NQF6vqpSvL&J!lsfCEeg1E86w|iNY$z=RhKLX!S6dz*0!OGI}-{9=>2hIkI z&$k4jy904nmSBa2!__7VsWIIV_$)s4DuWTsjR0=52=>`<~uCm%k?2mBte`Y z7EV#?A7ZT!;byoBcl#0-?wZrfFc!^9fPwAp7EGr}#3(sDEJZDCSH|99>|!6+N&x|b zDM{1%S^K$@Dgj)?0T4JHkp?p5d!s?nd)VT;^2r!PtrO!N>iGc#Q&A8Oq+9WbH3<_I z=9GUkcAp=UZI7W!v$6SCfNJcRntwW*FDUUB;uYyjvoA<3Fqe$Jzt3x{$7xv)0=!9A zztGej20M)u#)YIp0CeNC&&JBJkD*{Xt?&TmYWbNfdnUE5G0zSKoqq1c9w0hSwP+g< z)f6Z{uZS9eqF&-RYdrJXI_qRy>q{c52@eyN&)?MwWK>9MII?VyFl{rf)6XJ~&AuP}4S^GBIJXn4->NX&8SV1m`v= zw5pR)$k)K!aI$=D1^78r=YK|-T1|Hn z(L%mqX3p6(VBMaLIQGSk|>NAx1$z>MLn=2ENL#T*!A8t4c>w=OFMBsq+jd+^M6z zV)XEg9Ndyy@uDw}&Ns(CCyH+n{wdv%rmuGxY>YFvGHqmMl>sfN)Y`(Ibym`-DRgXO zUa&Z;$DllTF%csC3Ow=WK_Et`oPT(?oDE371!Gs*f|!c=31hdE9M7-8iPlToRHS+i z%q|^TI>mLLr%v-K%wYL#M24HJtIvarRDZ+k*n1dGeYPl?>FbBO9Hrn=D{W|=dwws$ z<>ImS_)LAwv#Q`!Ubnw|h}k46C%?*6VYzp55Vf)s4xDbOhoN??#Tnq!ycxjnxczyv~9&tB$KsVth-VV{866>i!QqxTrWE?GUb+aJ_4#u@8C6)U<0`)ceUWI^KwMHc9?Ht=;K z|FmCJMNXdkNJTmB>H}xHClHicD%Q11^aH+^f0%n;>R}UFFK1zOgl~shMS}Lzo}vrO zCZ+00=kmTh*Lmt@to}KWwad|CwZ&%=4^4Lc=AQ_ z`Yyj7_Y2mh{n`4n{nPKyPA>e60ym*!4_twc=6egQ!Eqs+;C@gzr6g}NrdA{f1Dm)Q z%|-A>g`b6S+9wUwWF?U?|nHWG@A-T*aG3zem`u(5lG7bZjtcDJ__jC&N7*=tO&&iVYbsqlA3fpna>4 z7Sy=L_?D&ebu3UR&@N_hEd1tWRs{mJC_se81?kv;=Z2Do9G4ZNG7en#o?R*c$g>hq zLg$Q6GO3 zeFuHT1M!D1zCtAcz77s(?;US!f<-9`GVf)JphppkYzC$2t*zKsWuTfX?N1q}uQ-*i z!&;)}UoNUC9L5=(|0!GyM|&;LN*Lw4g7S|tH23~K`MvWd^Zn&;T@wzKV15)NloT+m zK}7@rj0XzLR{%wQVX9$apI<@xNwc#_My5mWm0Qth!IQvPqlDM;q%NuQ8wEcD_fnAc?8+0JRm#vyXD`cR>qiy4xQxUSm-iu&DDaxx?6qrpD5jb9F zvqY=vejMk&HeDU6cCjf(t2KN%*JiBwokC#tdyKF6K&@S_Di$Mt-{yKrLApLp^YE_1 zgPhHpbs$;iOq)RKxwiH$-_Fz==gSpI@#Q|wVE&?Io2wbiTW`jK74bo@TD zhl>$Jqj2e{ixAM+o;`n~K+km>rm`@BiR)P`@3e}I5WB85JS7`Zm-Y>P^336uHi{|S zL_GG-)AfPcBHtoho_^vgtL_4Co*rh_-+hJ&eIWQ90(22g?HSvi#D*BH4GcAgdr z!ekT*jr1LjZ&`7A3qWxaMYa9fjfi>lcbkzJh_+~xhYC47(_7}nX=*m-@{-UJeKSco3q*M>yJ}Iy$KECri^O-K!rJGHw@(Wd{Xw;KgN5i`HN%T=WxrJsp4s_q zoU?`JXcRJPY)$m3lT<%f*&&RnH3x4Te8qKf(3mk>xuAEQ=OjI$4K+cA6`gnexd;fpRAx24&=c8DonK%$qp z;lti8W-+Vm6clY4K@ZJ9%??u|Ituie3l?rvL^Q~XJI`I2+lhqaL9vqDEcNKRqmUt` zi8)d+y-s8q98s;ZLA$& z7dmdE34%;+@3Z}z(+SQ4y8+l)!`G)<#qw%fbq4Vxp_F#A$#r->wPi8c$+`m84Bj4^ zC_d$eG)h^{Q}NH1dpyDKW?Xu*Pt(O=A5i;}9a7xCKnk*T4TM@UY9eQYXg+%Sch=-k z@(E`_%JZ6H?XfC0iKK&*kixUhZx%W$%A*Dwx zieVi?#p|=L`_kMr-MQz2RHlr>BU;7Psw3(_PLXjsMq$?|mQ>cn>*t+KXfON@`)9kl zsqPTXg>J;y-|)?(A}+a!TL1-uUAZcr5B2Rw4%Wd-uC%r_-(Yn3-$DOLMITH%Yq}Nl ze_-1GBvShS$s7O2h!#II)Dek?2EGkRULLu{$y%eYwTNtG5bgbsLFBg$h&&AV+pSBe=6&3=NAZ&+E!tq<^Gc4sB(p(s%WIw%#oso zrufYqEL4QrR01YdOXC{CO{4G&T!#4#43KHR0+}}TpG=zoWZHwExG^Bp;&cN3#OzTW?{|~0E|6p1pxPSilKCYh9E&b+t1sXCw zwwC@!x6l7RVE?CcNg4Po{_*|G)A&Cf8C4CoRaNrU;`&uDSSiQ^q2=N$tDXJ>>>5lI zTr$9=rHx?oh{o<+Rks1PdJB=-7%SEw_F!_G<0NBC3`|W)^}P%h(@=r1+%IA0VyQ&- zVUrtc)-3BfHdEXW>la=R8LsDT>`XJb7I?nY1b|rrSm4&u@nwiJCf*WdU=&GhZBh2& zK*VhSihFNg1%U|P)-)q~;IL$nXt|Y^syQ7SJzNRgU>cuW!0&b5*coBy`S`z5Dp=Are0p zq*fw-pSQz#F!Kce9K$?&ymJrHeDZ00!@q^Mx#_pm*&)9*$*OO8#9+pk^32{CX5v<1 z18oAfRnV_u$ik%iP7ur?=%@aW8T_aQ1NRWj$%v=^gMnry$0y^n3qgg-aA+FdusZ5E zZ8^d)bc6iD=;8_r&;dr_>&IWl<&4u+4xou-iy{1CrL9{DDJ~gd^#4eJYbH>0c+&7e zb!YH=4K1p#$qP#6;ZoI|G6zEzrj=Z@Jr?1EAh@fYO1`2pVhLYjeWE_>+3klDLaMzi z+L_o*VC)e)6bXFJ<`g#>n*ixD+HbWdj@SKqL!ajX;Mw`c6XK@q5BM$zu>D*aSB}Mg zg-_;^f##b0LmKg?&7i}S^I>Pc>V|Y_jj!&ngYkvDh<-~_X#^WM=3t?GVk52W!q*j{^=uLwk+3>4 z`z_gwg%Ka9TFo8maL4Fw0tZ>R^uh8d=o8?}uw}^(0#_~FJ0Uym>ja6ED9kaj7}Nnl zf2#%{QsZGt=RGVhlq@Rm0Ic>KTo0AhGu*>1=J)mQJim8WK~&+C5QfG&%I^c*+yiI4 zdgc>oOmE%y8dH9x%#9R$t3;dxIVJJjQLtbf@J>cn}7<}!D2Vi|^ECQjvQV2k-=1zU>jWb%xhFk;-XWIX-ng^`xC zb$+BnLkMF{nf9|7J94`|^9eVWo4V*xGU%o;0y@@idWB76~x*uy;OW2`Bi1wH1m zWkvX;PZcSqpzFb`Ds<&>!}z@EHR}3FyI>%PHWCH^^sZ9Nv#gp}Xkx zsqSya#@iup_?9!N4R|Ea3XSVPmLX<9&midASf$nrBS;X6M7pgcHH@36R|1!5p*XVhjw7><{}2Y1f}Lj&*qV0dH{rJ1XvYG0F*iZf8Ou&IWBb!4D#cO78O$oFXE20=PIUvD zQPDbzW?=-W6!y81_}5ry?pl-@h#=0qCQ_;G_pqvTvoS>QDmB%C1ih=LzdWCI151rW zd;8{xT^?v6_+OTqe}sxnfo107`!A*D@6_r&y|#LOp9G3QeTLDWBh>!ch@Sr28eC|B zqllsZTt9}wA&0bP_2(q(AkB7_GF7r*?z)6RVk=^)rn4D3y8AEcLy@)OkuB@9(_tPwy8m@2^uGOX4B6rDTBhT>#NJ1qdb}2G+Km_9B6Ja*K{g zlC1-;iA+EwCACjr@kp}l0LOD+5TFoOgh9hmMfFodyREl)6nEn!&Zrcxtj4XP+%Ef&J91FO+#f~Z>w?bCO`SAy*?n0A5SdgSxuEe#~KKSRFr zaBc_hHhOj^Ct2{Eptpfh^kzVrbweX0gv8We(wo3=OSTRrX86~G>z6~GOH7Eg(s@W_ zz2%$dmO~<+mhCr<;l=L>V#%WdhC_I@tjdt)o>Q-h%PT-EElsx?Yo_)v`74If{p#oZ z8=jeq354~8?6SLgw9VN5T)GGZi_RY18oIzO!hmEbru0QO#Hdq(+qGusdpw=oUN1cD zE8mc5Xgg);67W`u!O#u7MT{mFki;UzNjQYSF*A;uM9iNHXCSgVh_bXC6Q^`LqO{_Z z#H__h*RI3?&zv1hlM1mFmWJbUjocVs-6G=pA?GpGxQZcJ(A)hy;n(dU{#5YizSuE- zun%IZYOf7BZXT);F20c~nN-k}s5pB#A=OJ~CQZiBi-$9NHw|I|;M9G?_Cq|O{p}p= zb#vk(8?_=lt=R>XR|L8ZHlz}s>f&qdP+RSm3iSn9g8X0`kvjLpNSH?Ao~r&&D@}VI zoa`W7Lwx@73Vgk$=@5fe7cbN4>^32x5*ma_}kL5ZvlXi`DF6x*wU{eZGAd54C1kvVwP9nO}m>d?n zHF=*zIq?Dnc}M2ZJqA%$luFO+Eq_4pFMJ)85uQX>dF}w&cP^XGaZ0{KZz(!m?-(r$ zOT7AeF9*550J2}dAiOdVun#-_#N!BUqi=|h(Wn*bT(WYlQ66Qmh9){U(L!Ru{ELZL zEv3BYC*q>Hp{BM~dbaa&wQTqD9o<<3O{)gco0%B>sgwRBXr$t8d%@Ala(Dg<^<6Ik ztC3~i=BI2s@OT9|MIQ99Pg#}GGal}%@GCr9`C=DES(`9rB)v2=7nl>I zhAmi(h~2?#jb~hPoWFqTMBa~S;BA!jx>g9fK+5(}a3+mKZ(L^&>iK6Z(?H4 z7YZdiu;s2N5B|KJws0M{bkfKFtuEE2&4N(Sh4PpI$C!xam=}8%0XFKbEIAuB(%K!6 zuIk~Q7}JNSyQNjK1fD&4;OoJuum#;&R@%|tR-WOtcrCklq_xP*{kT)`EA&k0*FG+; z#OYOPrY5MI<#`IDwY=1n*UjBBdMn~+di&Vw5$SE%rWiDa3*We1>f{((eBE%|D(`oa z$NJLNGbhP~-b!5mUDKiKxQyfPa-Y^DV4jQB_4y0s$DV?P9?j+6zG|FmDG)!RB*IG? zqvCzb>b8y@lM-;c!cOf0T!ZIhJQ!|CL12-6sxl?uG##GSa{gH$~u&1!lDm3p( zD>MhsUJTO1}KN0}`18@EkAO1IR^Iztz|80EOggVGP;&E5085keV zSofR+#)s3vF~-dJ!-ze6A`g(}2JmK4mTZCX;cL)JU$v1^;JkGLIB#A4m-w*OM|{|F zCy#ClZjs<>}|2KFAdwDFi)!%JvMZQ^9ZTGq}o%7u!RlAZaI} zkFsUhp0eK06=C9LN=XRv$5hw_8=>Rd(8Y^D3jQU26+DiespeV;ig$_Px+c35oZz2c zzga@=%QK_;tF}Ma8DdLj^dH&bwR$#gONdV6V2i8Cnd;8DSSRo6+!CH;V+S9J*hb+H48tENh;}Kduvx_PXfZ~%<6zwQKfK%Fb+@h z;^}ZS!z=TYia&I~;`%u6I3RV#R_C2*Va-5&;|G`e0Ci4N9Ue4JYUH4LF%Z7hsQ@cL zxAY_FWaNDwRa0chp#@^?dfpTDixau)7DY%wN`(N`Jk+IDSQ;a})C9XxQjv!;wzmqR zLhEQ&*jK56^j7bURyY`On9%|NbPh%%z~TK`sTj_`H1fGhFfo z#hZEAQOPlA^r9n~<8&z;^NALuvsoQuxM}MQ>L&<0qM(Lre!%8VZn85e!h(1o!?V&U zo9Ez_WIcwS44J_LG4LoV){+~NUBO6Cy#`Y2SO^pSarpx=2kI<1!m_tvILyk9@QJfH zDqH21XmRupSwe6A%oFaO$WBm!Z2pIqA250r=eWvQWavG5SgB-9yjTZnwTpo(pMhX8 z?2DbMkXL0u$37Ka#u@zI>n3TY*D~^>Yzq0=`>obMG9*FilH$A;tvd zil`3r$EZ~Zeo8@B>}K&tV{M-pgrg_zEr*0eTfuzl2H$q_P+z!D@vdXyXMVB}mXpB2 z427iHCAtgFo11=12NUMsU(NWeABYg(Vx9%=)%l$86BJh)eQnNiI2)&Byb3xsmQZKz z<#A$LEbI8k@-BcihQZD3Yxcl&EV2ipSoXIWN1ih|-ze}eh>Beijn8JzF?IE6@Xhs0 zByJPWl9+^0tU&)i_Wmi#(yh(fg~PUO+s??a zZQHhO+qP|H*tV_AFf%eTkbB0eRbQ=ocm4a{^&ano(b_zn?K$Yjgnv9QGgW6c@s4I^M+xvJ=GyoGvRqlvC|>B&}to5~WRdQlL-3 zB6*!f23m$qJZ2LtRTS==dyp)>{BCIKui@x#G3(px4HqiuEmRb5)T0i`EH(>COD}II zWc1wuY6k(B%Zo82ZrDRtz#~rPoj=Vh3F-I5az~Nf$7CRs27L1kcxdH zJMr#7GNYcg_^|kzJYw!*yywfAU7&a*AE|+XdlX4|N`@#3WR0xXw|-NUad71b5Q1I` zMpOn~L9-PO5s>X8wUucOZ-X-TKzjOw_t;D5ks6}6DOkCe$leIxxD&hLb1YEx6C8c- z0G&bok=koGg5K8?CL=kh(=?UyR~rp=2p)$AD{H|lj9eVGU@30>Hkcnr%I1@w=UHr`&zN zxN64Uprsk<)9^SQUWvS_`QA~JOJl;9Sye0llCIWgKdxPl+vin<(dQ^PgCHmNWkr;+ zJ0EKvdOfr;!%(JEq1-XL>7Y5+M~g*0==yy+Z$vDcD)@|}RCn%ubka34+J-22&0LB% zrCoANzf6mV&O;tk&Ym=jdl4__*|kA=dI3@!+*#e;5~G^~5Uej152)Ze_*3vg$sR|CZ5K&ZU+9V>G z54RTh&}WCz;?ZQQMlxq=YprFPIo2`oYyiTXzT=o!EhB}6p}k~`B7UmR<&o|TQrlGb zpS9QCz1O}!-Z!%{p%5!5KoEcwhHU75aG>dM#>EuBWwaA}r2Wn=W4v|~%_Jt(k*_+} zNwr5=@sTrreClQBlbmE{T4@+$-pfCB$QdN7y1b}S=o8W)dw`FgxJtlqkAWfzFxr8? zL7x%6;qu#u*vLAr?oTw|^%d{~c_4uxpa2PQjq55Ak$oJ+t}Sqb*eBzx4A>S zIbE-(i*W?58UGPJkyJpY3rmH*x5Av_BdxZ{SQ>It)7E67MNPgAhn`MCY9ll^tTzps zNtBp_POu`C9`7m)qJv60dxh25%On589 z3Q;LNaQS2P@Ro^PVG`RMV#y(CV_}pHCUKL+*j!{!@(0;ZAlq4oY|!h$&@f81M^QL@ z_(FBZ$57B-t6@LLbql0pqSmLFp(%^t9#zwl{MEg<{n{-SEq6$R>SG-dap=oVbYC1y zMCA2)$GZ~9Xl-I>j?iNHU_EZ-GXtC+86_xt+Yo2d4p>n1KZH+6;*>RimC4O=*+@77RT3ZE zXO{48PVoijFFxHj@mLH6Gx)MKoub)x$ee_d%ygp# zv>;auVpV4bf5xs_g%*;l$}gY9BpH6w#JA0pcugo;%Ph<|n+vnK^^2jZyvB=##R6%! zH%O?cw_K6DaZqM#22pz86Z%mD5wi`OpPD!~C8!ux5l!|UTEkofV1!hlxpBQP+i(VFiG z$k{<0k+!GTKk~eK`wzH&!x_X216sLp#gD`;9r4@@v$M%Bza$KL7a(_`?FdInVN=$} zE_RV#nPDy}#4qQ#NR0yhgcGOKtq?O(a}7=9^o^2Yp$0Bq^78alq^ZwMhvd$=)hZM2 z<>UHN2r^>V(}DM9Lfz4Ad}4JtmleO*MY)7f9)K%O23bma(E6;7{8RpLi}QE+TD*pR zZ|R8Ko5v5YJ#XziJT9-x7tXW24`FBWFV^&LA8JsSciPI{+zS&e#VQ22npJ-OIv&Q# zm7>inT%H$3=zh;tX}CFYUXwEQ+lX}E(Oe7}+%l3O&e6V6!-i+QOLoBO?g-t2cH0yr zN_8%}1a74z6}=3Ol$TOaN?^KdDP3Dm#tyDAC3#dDhJGLg z-Jw%_H&t`BmM@RAQ2j%Qe#PiC2z~KZ%wJn7V3qead!y)+vDMPq9=e#SNgrzB^Lq!Tfn>u z6(!&WA}dt0xZ+j+@!6U z7(e4*u%8i4l!-~1%;RQeED|-HsZmjMa)LTCbZT(IVnA`@c?CzK$;B2_!~H=M22}eS zr%Uzv#vh?0)S5LkrC{o4_xBi6uWwDmrj5fFhYXAX@2m;B;q9-XZ`Xf7FN1D=8O#TG z$C-O8mLdwrdS{2(0e>bm{ceT^E^dQ4a4`%Fc1ccSHlqXK`8nc##d}b~t`e;t7dFFA z={EcdXn#XcQ!C39Llgq6K9U5v8*zO_bI+bTD}vrI&T&x(K|aouTlX@YQ8zo^4|FD@d8R}>H`sW z6kvd`jDh;?i-Ayqm_T>tOE*j7n`pUAzLjMkAWuskm{F~7Rp%xtl@(^&LnXWqp(_D-NIdWYY0Ee9<`-S0Cak3PLr8Ze zyy5$b54<4qE-=oYl++7`c2AeJs1&0v`u~u+bu;Fx9 z&_&?d3uOO>t{ACrLwwWkpM2gf_W#~(2Q$WNq>vWyeuoAf@MhJMW>Or0>>pO23T01Tf z&nQ^q;7n+da}p!(&&&UQb?j0l3Df6`%*Tz-TR8+RW2j$rPhLrd7i^l;vm2SI zKOU=AxD(EOLC=LXbu5mn2=XV1swQ#RP?=>yEnQ{~!Jrob^-#Q3QF%lHA-=WvwE@^6 z5uIf1+fv*gS_hhRLTOWl^%C#ZITMOpZD+rXIX5F|1#FEG+22Jne5`nUpiz1(!X`gm z?@rSYn}57GFU!D|qXl5F$rDdEr>|_a6}DF&M)&q?1e*oxDt(hSayt2`e?MgxenQId zf>CjktY;WtrXBUF3RL?uEy>zX+ zYiMgSR93YsP~r}#7I__^j(NJ48Lvh&ukL+BNM<;Km-rA(Qf3*s+-2} zy)NOh#y0iiBCr~?P;D)L$2DlnBK@CusayYMs3YQ_zM1QQncjw07^3ChXM4X9qeu>| zV!Vz~Dd@m`fMcbRXesCsN}s(1+R@;yfx) z@0S$A+*B|(;>0S6A=^|Gc}Yfyy)5NLa9J#h5<@AsH;0f-(DY3#oq5BK?lYA5jg&PM z)sKE~K1NATW`2D&Rkz)i()8xn&NBVB=|*L{PTpsg8vh-A?Y)WFf3rZ3`COitFfBiB zsy*qDJoe3ZrnO-M3?E@V3pD$+KnsS`*$_5p&!SrP>rMKY&OLHi0bQP&nRGW8SgTj0 zAhn=I<%`x9@Wz+E%P#50ky0vJuYfEJQoGOyS;0dD@*aEQ>&j5tOtmAjKpZE1+3jdY z1%VurYt0DR)n$Vqf1*S$k+H90Wd!qg>O7*D3cXo@5{mP=o>`^v1!bL53Kw!q(()bA zGd-k556ZxlNlr0h@Cy+0WFlTh&9;=9n*{ETnAIKv`c7G^zqT{K)U3@JjW=V}W@4hL zQkLC&#`tB%t%vaO9PEHO<`2(mLmPpZOKcNIienHr5mudrOz!5>D9G}0Nt5|>Bt&9C zz7W1dKr-WD__iU6SP-H)2(|6LHUbr%M}S2D8PlC z6#H%PxJt3WrR$-TN_T0HM-0WemBIYz9H2x*FIW^-QwzR{ErYFw#Z>lZ_etV@q;l@Y zdh1Z0&pd!;?0&O_aXla7bO_U8D4<41cuUG&S~gTF%*72#u~g<3={i zR+?F*BF~RG$4kDb<1hJpJqBz!G|HVa}lO^r#<=ok3lGTPqM)c@mAk1k}Tx)vu ztjL(xv&AGm@B_cYEOCTE!I4kx?&Zzb)uvsd9+GA@LA9s5Kx<65#^(y-1|FZZINFG% z)D!J&YTple3hDBA#;>|f_E-<~n7-nRM)B;SV~w!yBI5H+K5>8y@nJ98^gGQq$O=#j*kthG&{ z*y2?ia8qm;lURmuxj27}H;GNm5O@WeOzp0BaYWmCxAPu$oabJyxzBc9tqg_S*-?P( z9D$HH7XeM&8UcRuwO>pK4(*W=G{fBD#GA+jGm1_LshlU)oawKOq%kwe=Kw}2nVBXg zCfRSc%|MiNGEwDLECh4~)142yB?CCcAb1!c5s7GRpgoy;?finXlY|}op@4D?xsTXK z{(j-l>KdTV;F=Z?2iueU80^~3>DG~DL{{APy8(6bUbDT(H-gB$%~@f|3AvT-o^D^J zvAMeIu-4Lsw%J#|(r3|}Wn~!^Aj@F<>z_k7sKfh7`~1+jI)DPD2%fLQq;@rT!sYlJ zL;+cXa(CDcRnG9KBH@N0;U_m-x~x7OB--BnRb<|>WpUt<58r2bG`65|rGTUE`L`~LFX2qyJ+Z3`D4vOGh6cvjwXySq3QX>vFE{%COD^>PupO}RFUAUGzi;@>&8;- zu~*kyVtn8!>^eb3r^;&jh-O`>9i2%A+pW-dTdmi8Lsi&?B74eSDGn@|@~uj&sLD(^ zyFn(brVnogZ>U4yC>hfFx=g)qM_eO*;Ep?$%m}H1+-{XYIuT8A!kttHEZM1Pw=k|) zGw9ZR7jiEs;5k;id!cq_`c*_W8p)X0NIe0oyfm5PFi@^5(z<;XrGhw_=TJ~20I!Jc zu3zl3i4wy25VdibAo&+urpF-J?r~9Fffs!5!6i{P&mgN?VOgiM;)PfS``LO9i6Ww_ z=j?%w&aQ!iaE$JEvJhU9XuLDeQ3Q_i*z_gqS$sn{eva1Q_Ma#Sp6AANDBzV%>pJ}L z^R%qU-3cRPy@aF`k~VnJ$jV&8Mmc0=HcBDouF^uDH`C}9qy%~-M*KSCDk1@wto(BLW)6d%TpPNUs55~U^^x17=cVb+KloQH1UiM& zk=%z$&k&e9ZF_Wv4@B0Kq8}Ick1W}#ekP2VzICmSWR(OdT^*4&nPO56tytbsz5Y1H zEPw8Cblxj;1Jip~_SehqMDR6l55B1Z2V@Lu$^KD&7d-EmIS0o6^-)m5KC;w){hJf| zG4;7-xOi;!sT#q%D=*Z+Psjbert|xR{NQ{_8nv_sPpo~3>FwA+pwl8L{ZTfnWXWBA zNclWF5t#l_Q(#_EM~d2hv<+Ikg&jXG&m=qpgak?wa&ObH_OD35w@)~_I$mDyKK;?C5Yd&-4%A%$W&W@H(Z6ZtACM{ce^;4*DM3wP|35`G zJf)GSntvDB>@l~Iq*4gc$*g|q^M1bc26G&0JqEo@wHR=uH~{CfsdK$#_ofh|xS`#OiVn2{ zstx}j+2DCI;O+fH2{yMq$2F zrEL661*zKr)Yi?Aw?#xn6QZRsvVPW}az)=mI*%&YLQ#ym*fEnWDNq^5e7-TQB(5bi zv6JIfXd;($x1TZT_zVCBtY1HPp8*zf7nTC4!3hJh;eb43(IS9>=!6(usJ2{(YEU>b zOZjIV?$U>yl8$RgPuv_0V?Ma#Z%CVmJMknXb<&7yxn_$M5bD|=lF?Qy9Xd2Lc9&L) z@uP?&6i9#rqPgn98(he$pUAy-VKnfN>6plA$1x)a!DLK807;J+q(>RV4i%5H@!;gc#laz4sv4A^!m`2i-zi@*b`gD>373D#6d)JTkmO-wj4s>}ve^h}xy@e_nVIr|r8MtEB z6cS;KZXimoTZ~z!hgaMLd5EUA>du=5#!3imaq7@H*kjhL42qG(G?!!M$uaWfYD2M$ zA1tknI>Y*&wQvP^?r|3IDN?~~8Q_4|w;3O=xulC4JQz${v2u*E{a)~;3h-AnX^S5= zdti%FLx-P(Flfa9J*=H9U@#T|r2jer@&FwY(1_XryDNWa8)#Q`V~iCvN_g8ShecAu z7yGnFn~Wp%&$q@S&%=xz<{BIk$9X5n3MZCEb+y=ri_+;8M=~}-f!GTCU<`7Ur)SIX zb8X44R4$__(#T=W|>9f)v}IKJ}32 zZcQWvq@JNRFO4;5+$o^@&5ybEk0ViJL-e0s=g1<{U^|(Pi|t1ybDha&#{Sb64ps^k zANx}2%FZ+$P3g1mQEKK=Wv=(c)_rLiD=;3BRDj@-XdAIwm1G3m$%^8EH=x`#QoN%MzYE>ZP~NK zaJ(jMjEx96zcJe0AF+h<6JtGhsP9b+4VOsNUfzT^F1qA3v|)eup$evgU7z$r9P_WJ zWO5y(hT=6LL+oM2acUjagZh=q)u=}#)(^XM|EPIPRQDPq{<@!l>zrRu6dK_TY}B6b zAplK~9Vt#T5QY_P7$*SkSwlh)x;{=MgB(9SY$u)bb&wY~vb*3!m+WZP$`ki;(3(o$ z)t+hXMh4r|%BR924n(C(k>{p~b#J(rC?|un1Fw|RQUxg%(N(B{G{vTOaM^|HVJqXM zw<}0d>&mgrg=r6ajG^9!jiOFpgCH~h4EwjKmJ#Qo1vnzn zM4l==G}hNFc?D5EY)TS>oN<|m*hl#Rp1oG%v#8eFn76z7G`x`J%I zcx@`e*>gEQ*pS}B8m>e*^ce}ir^kAhZmBdXvgUXVFzL>Z(g|R3xUi;1;9lLH%;LJO zodXh*Lj7t=x0?NlfW-sgbT;KcXLgRds0QBy%vyka5WXfGMv$IX*moWIz`6h0< zOIf-*cOW*oF2SqS7Nv^(ER7`}VGUIo-LNQ~E(Olk!a|Z6*cWlfS)u0GdXsLtqR5&h zRXV_HAefX(!RYTIZk=h(VvWBEo^@*(Dr2pp5^IXq^IzwnGQIq1IbYrDq$#~~-G>5~PK|;KD@?WUOWj3fdRBm&OuGvQLos%xsu-}T{j(i^)QJ7~9 z(f2YRP;=90=P}KpUiThaBYxi<8`XdiVcf}vqj56cMZa|?@uh8Pa=#-@fAt6buQ~H) zMXKA8*~6#W{ClMNk8Gs>cO|KnHGq;-CARNOY5CYNrft3_;)5-}k{dclFk*?#0Il15 zENhEGii*`J!Yt-mwisp+Kc-K+WR0bXZS^Q=ZT+M#5Ly>oj|{-fIlm=$|_BB z;9=tUn8cCgGwSAN7*A74yU?nFX4@30nEFEC(G*vCf9dTSz)AwUC3w??U+4CvEMV8S z?XhRvm~U24lKi=KUB`Q;Vg5*C3pTsTK)Ly%muD@S>xU1yBJ6OjS;rbEt}9aTMGqvI zP3wW;1x3~ur1*~J1<+cv^(Y{%D#Kn#j`;?3;1-=4rq*BA%ZJ?$(WR%BKF{2qevX$t z2$T&-uZ-00I#Hu|Hb;j~95rv-t63vzoU1jQhAeG&;n%{@JqF0Ogpro89Cd1#@^dhN z!6xis>1IWx(a3W`=Yvc>@GUY-(v^M7(HgAHWH2U*CV(|d%&2*PH_P@I0cp)sKpQ10;~{#ti>q9xk~3UzV%H=s z8Yi)MtKC$nyL}}iY@2$fHGM8-F$uqf>R}sEdek-qQVQTbjS1lVA8SA~7QwHc99ZLSc0s zM$i3)NR;;|zTD8bp?VewP9YAWjI@tdSn>0GH*UwGB;(^N4aM6GSsVoPfuJ?3&3Rz0 zDv)UBhv%w)kp)TBsG_r-Ki4{G;DJj>ed3IHSvZf84*llKm6o@L)2YUQAf(J*o?9`k+_Yu1M(|gI)(w5XzBqbn!$WLcfnY93B$9ISj@q!WE7G{vt(i(YQ20K_p3sIR)-6& zB&VaH(;^<@U(YBAM44>AZ*UjPbB~{FnSd&8FhEyVBu}`9b;EJ2FT&w^)f7<^eV|)z zMd&07E)XW^KTWz-q8_s8cr73)FON_Q;i$RLsaohA__I_4rOGum;rLk7b$5QTr++se zdbI>~whT`ia2FSatdOwS*-^KgI#_Rm|3*pvEW5UP94+tnG_wDF>qOFp=e&s4QszS}9uUE*@ zZl;0o$D^Yv*I}b{e$ph%0`O+@Hb+0C{$Z0KgJ>f)`kbX4Ajrq|h=JPD}ms)1E4w8`(K(< zy9f$!RcslFS-K?4EUYg%c`8o99#>}SE;{4{BreF>gR&{>@>6#owXWJ&f90Oo_m4x~ zsgsbh+9u3B9yhog%UROgvw=FY7jiMhVFPnH{sj5bKEM@~CImy5#Wo6}m&*^&XnbH| zDTZ;OWj(+iTGTam-q=y+pjvm^=0hcA@aJ;uie!F>LVm;0+HVhn<&)yXyRF}0l zFjHU*LAK(*$n^i~2JqQAvyfdT^!jf*n*T^O`u|Zm^FKM7YVb4w-mC!dCOTc6qp0!V zDTcPli0R)K03$)g>ZDNaBQ0Av0B@Q(nk)e_jqsg6Aaik+qW)9=8v*+Nm!a9`ea-!! zhUOQ5q1iD6Xi1j=rT{X4@G4YxRUkA?cNoW;Ar8}KVhqhLGyuGvmx#&;6ZR1fm`*%) zE+wzz9_=hssaIO*UL_t^Se*`4Os?peS}VPfCX!Mh0S^c_^P@GmkaXK3^U{OW%!P*2 zSR6UlxA*{SNPxB|2FeIM&EcjXP+b`0=cC*gGn&78mNLtDZh6=NX0`m3|AVaMTC}Z^ zE5&+{9BG4OcUzUibgU?WDf$_7p8B&wk5ktN6Fp`kOmtI-dn>!A;AH`R=zxyug@cWQ zC%T)UC)0*+0}qN%Y&mXaDHR}t6zny316nXf4zUjzA+iX3RXrlXh=++Pt1ksRFxf}~ zQ|dZ34&jKaKMYVo*0_e2+{4RnEiPr0F0*(E~{wQZ0|TH|7R zkk&Ls-|Wq39u10Zl<{++gxS|e$-E+K+(?mWQl%Vf2GuAY3h}7qu$si0IBjer;IReL z2@yIzZP&i_2S+$LZ?1%c5$-a+kTFy0df*u6=) zQJN$eF_jR@g__1Oqw=z8^26m+Z?XF!!}krY_o(u2@Hd^tv$u5XnsRi>vhmzKo0}I$ zn^#sxL!HbTKK1u9c95+J*{~P%uw?Y=rPe-;hy^TWG!llSVGDLgManl&sPG_W_8RM3 zmDhsRL#aY_mu8s6wbT1#?Ok!wo%=s}&>!{~hI}Ho&+E7bzLYjJpySpTU-y2;V~P&1 ztXpr>%4k4!IS(ZEw~^|W$K}X%b`=ekiWWkUN^dhe(@tGeQFZqS z=`|AIbUNp^p^MwDvYIrMHp{$c%b&V>ma^A6`T7*~>bHUKuNAN7IFj#1O4o;%enT-* ze{)P&T_5s9u|5x!-DJ>zN1;K`k0Z0NA{`S1b4bMK zhTW{KmJU)G)M>-Wi?=|u>Ig`Cg|m-HX#XS(2KyVwh{ z)WHvup5bEP3lIvFB0K;?6H{XoL0yoyxifA>`TZ7~1yZ3>!(W0Iq?Caaft-Ue@ z&aZ4Jb4fVv`$06`rj_5vU`C%(+vk4FBqMefDx&M=-5Yr-mUOb00n!T$gqcqYG^bb1 zi>-M*Tc_zEbYC52NuqTN4m)ZOak^lNnO`9WttJ$P^yoq*9U&W_cm^XB!;SF##;|Tx5)x?J~yMf%uydWQi`6fMx zTjrszbG*4STHpaJ^&}7pcGjS>KlvJ&m(9qQfe|ri4N`l^^sN(18dyT`A#7)o_YAB$ zNEKV}qBp092~2rz@4tlRvsT81IpzA#zin#%BeuvEFxdP&|Ieo8U#O|YHqNAG5GJ+I zRxdy<18emuG;CoR2UJx4Q##VoqN25cb)Ou|Ld^`~64q?v?9num|3;cf|9?qS=#w;& ze+!16cK}E;P~6N~u0f~B^e@tMDAiRO=g2|Ac{6Dvi)Y+P$gq{+B=<_G3UunGQq{~x z2$xYYZEx4+#1c+22u1?}&I+{+sHW_M%rCrHDHuT>3Lw>${0Kco1cp@X7sLS)f!vUm z1@SVceLhy|gUy6apCi>&@v6}MexIJCtwIDD@MiwYCni^^7S#V?ocmr%_Ar{N$T3Nsr%W>;M-bf87_xPf0)?w zEBkf2qmn(gBK+_SM#mcL#eafk+mYfGF;4F%Xzs$=Vywq}f@Uq|>OuoH05mI@T5qqH z2fIHb^elXy!T*ZTL!e|L1c0Xe-=Nv*R`WKfrajDoxLU(*{GXs{@)u}606-H}9x&gm z{Tnn50H9e~+dKyJ3krNf4k`_zd5u z$=8F3Rz9IpwY?& zCZ%@zp&gga-rkv=>F_7?u5S*0gvH33-ML|K>4jUWNk#7?GSeav6GV=gWM)RWI2Q;t8O8!g284~J@-Y*Tc~10e=x+eS2(az z#Z&GLs|SO+aAdL9XvI>a{eMo3*1WN3T63s(E%UA3TP_v|^P43iUZ6kwH1U2b@#{UT zV*DW{!H)u1q$MAD4Kc^9G6;s|;21oGTi*}0qTZegm!oqq?+^&$-*F}2pY}75KpotQ0NIID=&csHRA(xzdr$l@!9({|_k*GF*Dn9(Ddi~XAJIN?0! zmeL>~RqX7!GiWbU9wWs2@56{j!@?-Mlt#mFvk4hwk($j|2V>`^14Zp;uqvqWb*RjU z3?>wV!XKK5cT_=^!gF)Lp|gSrdknY{lWvk4;I=Y(wA*$KLuFzb?wb@@Acy*iZMoyf z*l6#>FRJ-A={&@8L#3E-%-~l!ASH&vV@jc?CxPYh=mpcFX{tf?v1Qp?&TI4jtG)>w zOxbQ+*gozuE(uW~t9!n=Z3L0FTi^Y)T=slyRr7u=ujwPieRDq1G=v5@T3R!UhseW$ zb(Syd61uSWPZrqonUmm)^w#;1uBv(ZzSNWaH1vB5^RaZ!?-0^lMaFdS;lxzR`Jypu zfDn>)k{WVmLdO>)((H}$fTj`gc0j$uCP7%yMry=aGb!15cC%AX${w6%H-P*_O|CSq z&#cuK(c*$8Ld>OimMR6ZJ zcZjo5Ed&wp%oYNGG?CCDtCYW_b#HVML!H+DD``q+^1%K3r1{@ciT=mpm`1rFCZybp z`VQy~$uJjTnE#J7|DQ>-4R8Tit!HQWyZ|@=wwnI;JI()OH+*68h$Mncn2R+&%nSiu$=NC>UU7NL^p2RglZ%bWhg+5ET$RGZHB-eAWBQllgE zyCMJ?LBe+c1%UlBs{N7so2gGk;H09Pi^0b?he>qetEOo>h7-K5QE>cZ;wh{t`5kvz z%%Mj+jc>(ZTzSPgYlA~$N!8p^Ic}T~05w4cz*;-tZ=V2v0oq3oMnkK3e1C#N*E}CWGW5Uj^m(~>vahhjisc8UtIz4K76RqXy(6abiiwiKB{AQ7@f!J2Sksrx z#ByECK*gBYEEF>ZV3LL4mm*zu#x$;s3^oJT=!HWmrZbzWI~hTaEuM1O0|{AxR}6B- z6=#8T(|lBWAjHZPKhBWZO?#5C_C(r?W9aR6Yhyixc7E@HQg~1Oq7qdyy+gd&;G1DD zqdn&^69gzVJylqpt!jotBZZUL3Xw3;@}e7XGKXcLWKS3CbL zoaI-H)BZaq3@&-VoJMx_!;XSLETR*LSpXUFA_5ryg_7v(4H&|jZ*_=vO}i&YrhF=06?K&FbSOui6?3u=B3~;%iZ`xu~Y`8c5LAe_tM?qLQ;gAnw9j~fQGvml-z{!A93q;yx@)7TqJpvC@E1wu-C(ZNg*IPZL>KsEuc`Kt1~S<~)o4Dm zln$SGw6p8G7)$IsraHE8`7kqEjfCjT+Y(e3Kx*7`g*O;(zTJ55z54b&_ullno3nwB zu3!PJAp;FFz?1+1Vf16#PH`JV+|z=Y1pXvC98D{OVO4$W)y{2dLOT*{ToA_?j|#ny zY5{pjx@U{$p==t6G_ATwFIaGzSoO2-`w#+A3WDJVBB>a`53nbC$(`GOkm}z|+lR~Z zA%DSK&Ick0`FyA$s(@*d9!>R1@KI=!j~gZFUN7EOaK6OQxTP+t8 z4OUE)>bU@9B3U+Jlx3e_0U{QLUc(&Dinb}Wa$k(P^zb2eL;0QI^uBm8_bH&*Xx(?~0TDiKb+x;266l+QIV$9m+ zqT2ZYU7XtIB6ze-82I(vIVN_07psr&$uBDMRCX>1Zzg`1s9)0iqu2i^cqXZ!g&&vz z9&1c6&rRT~70nJgu4;2JQ6?u}he7v{5!-N14CsxMWs_#=;R{?m;SsNu&Sc?`dHU7h zL&{?XB548NUvd6)(1y)9pR`{@iei=BxuKJhY`u4LgyRI!CyIk z0l9T(stjskOPfQrrng}Zs2!6<$!~k(CB5Rm7advnHd{Q#XeXD$WLX?jmtCICjv+p@ zshK`&yXYFO%b~hmHr{{8#(dPixlX}-(NMJVZUG9vHe04g%|AtZm)RoR^JZ6eEGB^o zU(Y|9lEa<~F<9r0eiU&oRc{0{fyGwgCP#I|aT3O{Vo=|d8-sN(Bj-Ba-ef*qg>@yH zPy32BlIk0yv|wSdiT`VX-5l4Goy{L!cziIbw|1cDT2dRxe}`6 z>nm2P#S>O3?u`mi<*-ZDZ7ze%!8U81hN|QVCZ&yr44$Zn6m_?`w!~Y#1&-Z|hCbym z&C-Ke-6S0RJ$yR>^bHk6;>`@G4;}Rp_|B8(>Oy1FQfgbeJhx2wB+I!c$xdu-WCz>AX3nPRd2eNfwjI5^`_^a1kQYS)5ry zz-nP882;uAM`9=&597GMvUr0$HoK3+|W)sin z*VsP+=0}L+4!WJVp4pG;b!Z2IfQ+k)<^HKTXfU}^;~_>Wb3k6oxXZNcC)1G*^eILUBAEqRoY~PjhnB0H0fLEm2;Zw~A^e6xQ{C_H4q7X&1<~w|ie2*C$Zc506zHHJ9-#-t^?YGOhdM+`WX3 zr7?zY=b zmS0ETIc=Eog(^yYg!$imDE-m8X>y5)xrXSm(WDqilkft!Xi_o!u8&z!f+3EfNYs8v z9H{j=q>AxUS1m%G=%&CXT2l>}gYrYqeaEENf9o0|H*9<1Rp&z3`eBnek8?NK9v;Wo zKaU1-ulI0v1Nx$wZDQ7)kr-JI=kqb*)bS8d)gW68{0d0>f6{G8`|i**z23y*c$^$L8FJs`wtL3iC zf*&fD#7tdL6b81JnCq42xDO*wb(Rw1MBW#_ZOJpm7v-hwwQAkAu-{e}X`z13zNN~n z$G|OO%fd*D+ohbc#G)poqeg)aDKG^P&gK=8^ZpXkbdC@NLp7v27%UJ(lz*YFq`*#XF z?yqwKL>;h#T)JxefRaRKELdbipc6(-rqpH3ZwETME=i)s(wP_Y)I*_6 zY$bpcp*|e&zf**47@u>UuRHr*y8)%M*RAt~%t{dbP>4X4;Xpn>{X)M;?R3QrRWxV@ zonvzO@@+JuxP)o>l&+M}?&x!sq=DuXv4$rXm+`8bTej7rN9Nysu1y$UrC?< zm$8BiqPUihPPOquuwTgM4S>*bGXcY*|JuK7J>lK2WFe+Sz*vFpKdu1HFDi3Tc8}!0 zHr_htrgeavo&N}rP*g%83{8-E_C_1~QD4|(B%g3yOmPFQ0MP^iz&#|ymq4=vrzS}= ziEx1U1}|1|K;fIU8#<#VUz^&TB`hG~HU!i5%kT+a$M~|nk|&t?V$?InUGnS@ZBcay z!)%gj&NhkM?;@W%GZ7tl3;BKQdzLocCZBh7;@qy7!}Mr?zZv#~cIdGTlGc}<#}p>lG%kN zL~nF~65+84`xVq6c|ZYr@z@+ra3G6@W}h8i?Do+1_u&`dbt})a1xXNZl{kJ0i81KQ z_7In>5tNez;Ov0~NWs1&ODCooKML{?%=Z4!$5r^i&-(J~*x{3F$bo5s`yQ`h& zW44h?EzIZauFx{g7{Y8uIZqirEtRx~jn+qQu3dC;hD(Ckxt2;S2)IfM!E6c+H!_n6 z2Sr3*1#s)3S-N{(+FxZBBz7@(-=bXvsSYnowKSXXD{Zvl4$2KQI6R_8)^gpzu0?=fI8PLT^DzEcemi~?(XjH5D4z>?!nz1 zf&_PWcY=Gc0O3y7T2*`1K2^8Q-tE))8?o>??gNanGlL9zlzpFuy@=9t4H5x`O=qpwt1>eLk@jcQ3DNA;40LS z2jtATJGmePus6J@!qRwu5o3Gm)pmA~xYXXO4MkLYo39|X+Bs#?%Hk!^cejBz63ATX zW@6OA`}F;$1o-8=16Ct+d(+uZ&*G@CcB=dS=q$}O4*n8|vXa)W0&d|JKa;i#@FY^XB9G=b5AC^>Lm>p!m--VddI@ ztJl>ipW}52SOD&zCN&r%ZABJWzZKzO{g0V5(E{7*DU`KJ&2+q>oEnQ%Si{hkAS)u1 zQ5har<`Rvqe84p6%^GN`lfK^0wqL)Q4FFG- z4^3^+nansL`STMuT$-^W3fc$|lJF;MkWSw0^Yzh;A6Q#FNG3Gk z+^8viBNX(o@7AoDF9$2>C3~%_(X3G1$i=6=YHP*G#sq?RN!VypRN~(R$zC_HzR+gL zwqz~Wj^h@jo{ijZi^ijiqjHD5jx|Lr4u#zB(dmqM2Mxpl2lJoN8rP$ay?Y8y#q;{Qn#pj&UWz!)87o?5biY)-y`+VM5sQ; zTY~@wu=){g^z;>e?lupbfpw&zm&J(6-LO3N3Xu8mZ;3J7G!jh&oBcgCv`StRTD$b| zacgxgEoPhjq{{%{iTd~!NDHe*_L?660U(HE3gGf}Wf8zaj4B|~QbJl9BM78~Ho z91L^sm;s_7J};S&y6BXhopMrp z559@KutL9TX$)~8z$dL6R{v=v%PMR5eMmG(pUyl4W`zad$+;d)*QQiCGC>LYBF2|Z zHL0|6`Sf1q#mQ~-<}Nc&msRygUVYeXKw{{|)vtDEa&9RnJ z==N-ULj_O=*}9de4{_Q_IzcMS^)<6ZaIj&vd488#pO$mTzjya?O}Ji5YWf{W&4Fd_ zt;0W{v}KzV=YsKgNbL?!D-KA$LYNt3?Ew)aRZcdLp&KTvSAe zR$JDw7Fo|(N+nk;_QYdU5R|8Vb=MVtzM%90cFOZ}ANG!(1gu|BhKPXxcM!UW3BqU;G+Rh9?!a zE*G7>yi?fH+fO|br!yaxU$$$V{6}T$eo8sr2wSZP`g-S{lOQtXp1(A2E9@g49)gc? z-VXO!jvhLH@8^cS{r0)y>-^Pu9I-Q2LjU93E_C$li1tQjGc&lybwDTcu>dD6=8F-X z8A}(G;=2Z(hrG=mTjiuCA*s|xYmV@MW=Bkr?XpyL_rFYeyyWT8NTIP7 zx=Mv}y1tgO@Eki)Qd7^_z_rJfGO8JC0?Ua_$ARab)V$1gi@4h3BS+Agc+H9L!Ip7Cw}1jM~sQE7A2y6jmxVy6RfE1Fa%m_2J@ zCqpb|5XZf9aBX|YZ7ORRraD6sIPlJIzZV3e?;)d98Z^_iVQZ*O2l+7KRzC++dWW<= zi==|SSg_c`gZgL=eCTZTuKCh1=$~AwHuL82%t9cS;opu5vmA?l@&W@FGJx#5ss*$j zf1Wa$&;)ax7>%!Wc+=7@L%zbJ&ytZn-z1P`dbk&d4TM$RPW<$bUj!c%>SI8D zdJfopS^{39|D~QS;6L&=XVCuuq5nwO)>}=r9;o9U74^2qr>5sFG(N(5Y%N#7u^K zQFO=jflig+VBQh%kOLcH9Qrr|V4+GcV%9l^W`yaVSmk zYn!8DGT!5Rcg2mMS-6l7&Sr$7nXpzXB3#x%qoA`6m+1hH(x zuW$!$KA`#5g3&!NDr+Xn4QxC9Mytz%wIl`B1U;HCC5@wVFw2#F;L1;T^R#lRI+5hr zK4C$oATKl1QN18r?_I3iDBAI=3#0HHfN_%tu2U!*E~^T7ak|lvQ)qlaZ|mqB;(%2psbztaST0XD2WYS5>T-V}#U+ceJkAF0p(<~!0T*^h>WMbS zwEX-kRr^!uyX^o2Pfw;D0J^ z0@#8ahpw26;R$5z+(ebQx~h1gsHyJIFT+TCU*F>y-#Ho?(R!XGDsbyV8LHaR1XXA6 zf_?{)+{DA=r&=1VM5`n=#U}gUms@a8iR+D?xLO)!|K2e#6}dBWborF>MqezSHgS3& zvgAwOU50*(dWx&J$Vgp){-9(>v!p6b0Q&=?EPE=CB2NPml0(ngatb0p(JQA|${jJp zR0U==T+Kd!9G-k*ev}gZM!>7MwOTh};p=EB8LmTXb_90AxV?@kDfhEp?avYpb3sbN zyCK=1{i5fg+`r31VXAt=+1QOI%gaP*pxxr5*o2UqjymT$+@6U$IvHP(>DJKr@p}-TZm^X(9fpon`*LKXjIhJN zGcj8^k)GMOKbnc~OBe0kT^gzZU9% ze0&HBur1ZP*3!`Ig)&d$mfWssdBhjuY)O-6FTdo{jR{30QBj+4gw`$$W67i_@W;uV zp_bQvx*f(dnDle$zP!+R#>ZFmc$`(Q^&nL&T;w{O-JN%)}7DOnWinDb)Na;TujJ@S z>vK$*$+5|fVEtOdiyvEWmh5XSk+~k8JZjaw^=hPlIMD?WjD~G))`LV-2X`j@{y8n^ zImb|+pM8aNXD+ps9<)+Fxf3Tt>ut!dPbbc03WcZDT9#~^zm-mL>NkEAdnQqfK?>?m z#rfS`)9J1tZ^R%&Qs>gt{NBXy@CEW8bEOY3S1S8FIsYS3^Y6@+zd+Ll0GS`(KY^y* zUw1%#X6EOdy=qm}0iaoqHz31rAWYF z0aQ2t2-ISH1Zqj&fZW03CYH`E+C}eBp2}e^FPS?`xz_6pEU%MR6M4H`#f)2=YN%%m zRqv}?qLfqETz35XM*FL6Z`0HAUPs| zH_d)jH|05?k0bFnKu>%znMoOPC78!MD*=JpEU74%1?TEhx6HEx+=c3h6EH@btJ9Pp_QNqCe<~MLhiZ4d&#%>P}tXR%6=ln=!Z*eXkCRYs{fg%jlo=+ z`^eK~mou{8U9L=YsIU~50P?ih9@ggP$$&g9{@?PnY=AuNgu3?NB0-gwNw2BxKH_F5 z%9kmUHFlKw5n7{%qWI;c3<;>eRH|VO7;H3Rpmd`9$rzG5Bp4JvDUvIU@y3 zrrhk4=EFHWEZsUI%_d|tH?@buKA^T3h*zLulo`?)d>4VwVsE+>PG2+acIhGWpzRU~ z=t%ZmTWn8k4Q_6Xdb9N#^CNW*b~Dd2^!oW%H{-o$h_`E!H)F=)@g0e-`>$!7&&zcRl9Ug31zgjkUDU8l=rv1<;8We zh*^qHIjNJ>X+F2%BK#vL=;BE*c2fOg_9|U=m*qojEN|Cab$SQQNL24#+?S+ zoG+jQ616-ZiCTE4|47s#HU7+I*{0)^()&u09kqV;N20bxsEw3)*zN0IiQ0~PaFIU~ zwVj^OVZ4WylYm4mM%L63@<*bU7LcfYG#>Cl;gK*N0Go=(B9D-Y!rBcx_2}(uEdeBI z5gCv_6160NM6DF!4N;&K=nactK1+Om>-evNh8PreA=;!Pm{#2Lx^mq3%zvsV2QJ1^ri^Uthkc-;w(1bBkJo#(S^ z5LRHl8r9`zJ72eER!)=6M!yrCMqc=MUxPE?9w?@1CPyAMP*5J>)w|>*>m#am^4r`l zW;5gaNu`>L8ZOlAdX=9VhH&fkv_5zgUp@G; z%YdyK7xCbYY``+lFG)wE3zv#Aio-H+jxG)k3EqOJUUn~&wZ+mUuslMra46U^(&q`& zzEzJBXQR@>`h&67u9tWEs;i=v$=+)^m>q=@rFZ{^_{XUE*laSS43vFrHfI1($@s5q zHvd4F|BWg66#5y_vd;`|C`>7_m6zgy3y6r74NU}(spYaqtix&7?bMLo@rTus>_`Us z_Tug~?^Yk7_ChPay4R%@K=e2FmXs=v>f;L9^0YJXAa%6|3s%x_4_n(oR3$BP94v8k zlYGc%EiaSY2Lot=jC&bP z!FIwLF)iC~T9g*hj17B5v0%P5-=ADFut(F$j~MIGkhc}Yqd#i$nlFRb+@f#&K-5Aw z&+S@)@`}_S$cy7~pbjx@7o) zl(s0_+WNk8G^$bV01<7o%y}mODN{eQvxS&}VQw{${}-hE&;kw1fd5Ws0(H;h&|=Kadj8rD;jUfQ|em3OL*8gq8)4YQo*f z*$ zwA8~zyEs5PuCrpH(#1dp*cNExIq+{yxqD0oYe8GDs;hORUL2gNRTu5>)a6om4#K$E z6FbTtL@TX=BBG!;q^C8;7_A~DRzSOo3p*5U`UJZl`&MsFy95TT+kId>80%{CS-T24 z&}r)YbQ6G;GL_}2l1(ptU#yz15&=xP_kx0sUrdq!pQv<;1BlWR(^mIc<2Ws8#xo_( zip2E+{U*;}RRYPV9--1vW9_u|U$jIf)~5+r^p0@ztaI$HB!ZKEf7=1#7fE6ttW;sHbAQ7>m@+AL zrA>O4L5u{);McbE@{Fbrw>qG*iGEQNqP$ll@6O@Y{@DC2t4&j{yya8+vcw^jt-f@w z`HUC*dJ^k*&Fg0*{{7(>Xzy;At7VvXpgwGaR_MyBA!qt2ESlE16hu9k@y;O;M>4J7 z+vI)klO%92PQPzXA*#AzZD_z}Dvxu60CJ!`BlKJCq7Yo zDxmv6!8tmzGp7TyUa0OhROLfW)hP)Zz?+@|)khR6Y#cTEi^4HhB$`h&O{hJX(~nA> zd4h1h^ILGXom8l}FhL1z(Wg=rex{;>r8XsHZ%0pM&1Nl5QlLTcdyu?ZYa=NqjiQ$V zSQWaFI1b`Bo5#dmZ(j&b@D(=v<@tX^WI>IH_cxe`zE(;+ADz`O__GxkqLh=Z zATumMZI))zCQ|S=#EY=^Az}49iR)~TA*mh@c!ps8l9qkUoR&G_oqIuemOyA%dIQ6t z4_0`&>F4(jMdNSTaiQ6@FIlV$?hoWu-*q8IV1-J0$_5v(jkyv#hDVwxDlLRY;Vl9&U<)btdb7;z|G zs4?u=ie+OrY}Q*0)FOICS6;uN2kG)ABEr3sL@YBdFsHhEHKO^RlY+=qv0JU$=h1bw z8i<$N7M{p_-PP;rV(`FzJH3Xe0)eR_Pv%c354$FsFWB2vU36h;dWCSsvM(}zKWV*7 zx$Vuz`Yb=*V8sKb;*$I6>n$G(nt86A8#s);AFjxj_qM-4jJ58T%~*6G%52KQ>5J#zeG*ne1o z<{ZF@KCD0=O^tt*EC1#MG6f8lkMEy{%U|}{j|C>cKKo};lkM1=PQc|Apaf8>Dw;1~ zF>;Bb-`i%!13z#8fMxyPz;fabux$AYEOF-%h*?b5fD`GR0FHB6)AjL-_HDi^o)0B} zm%+X4b&W7oj~oV2AO#K?5RiF3p(~ZZ+`Wss^JrBkC|#PPFUcplsZ|wo%ufn4ghh4n!w;NiR}Yq>9bG_E(+JSi{A#wgN#Xb`SEL19!G-ZT zD|P?iWRbq<8nTx9y#5Pq7;CHx{MMP3ohj0Z6A?GU4padgc_uOpmC?#)X9ikc-p7fXoB7ON7-F9lNw#TbgaT-6wtJ z;-l~(w+IO{X{zK7^Pck}UiBAgQ6cWaOd(mn65I(5im@c2VIt^-FaVm)=&{@BsM(uw2N(5}3NM|WoO0J?gZ;}kRbEG`YR)Y_K`bsyQ7 zOj4I9;zoKeQ2i$)QVdw9H~`e2%`HfhwkH`xiL=IH9eg2URPWxy2Ee{&h|Llauh>IWY2)(o4s_Ukp&d!WXAnX&gL2SO%0f%hctz~)+Qbuu_ zg3=i&v9^z7@`45Hd^YY9jy5JQS(h6wGT}eL5A!Y+(NBIsVxt#^gN(QUHV($%V?;Hv zo?QcrGKv(0_sF9dBGDBMpBqTeSh1Ia82}qLmZEG9oHw0gsy3|7`4)LPd4_NVk$n;XWf|342Sx!42?Be7VBm_VEG|LXvD)B>ex{>W-Dv;exsI|s1e)NuW zetor8e~4It3kOv|FlDgh&LdbqBXuQ~S9|si>&AazY8Q(smW51Q(s+(e_=_-~facF7 zSAY{}*No&xZ%DL6+laskF@ZQ^wSX@Kl`BMphntmy>Nl+k8e1c0y zv~XXsIX4oWvb4uwQ%s+^$ z1G?h(s^3Ii?#w<4Fi*bU>rw!xE;oHMS}tR%4G#TuU8lXRq-u_5Gz=c#yEb13G^2Yq z>t&K&K;q!XT@Xszg~x0BawH9WrUiK;0Zq+2=|uonGFSk(@|RZ5$*4l-PFo_ijQ6)r z!9%?)Mdqh|LoqJ1eFrv)Qj!m@w2r*!;{D)CQb8ZfH%uGD0k zRWt3axrt7rZmCKco5Cy~&(DBDX`kR-Lj$2Q+Hv6d64U4Lwt{y2>MITWI5 znev^S9MIG>1Bnm+ao>T)F$JRmMl<(^fsPoe83Jit zzGfUj)PaF`rXq5xUONl;%=8|<{eH5>sx1;?1Y;ehCb!Kq)q0+${X;+-`iFoPKO%Ty zgeYgWsIKWioQ7tO6BytF(qx3g27cQ8SXOr0p|OQvX)+>*g6P}%aCb(*lSZKemX*@b zHB|rSvhou(qPDD){!@Rvs`%oR^nUd7MuOqz?S%c4619pi9QT zk!1~UA$&s=m#DfuWIwegYQJ1+qeAlPK!~g!q`?t!!vNPGWXV5?^+A?Ac7Kp125aP) zXNMP?2(lz}Bw+OKOgMns()Zfy1OikkQG9_wG7SMwuv57}7_7i{WI&ZW*(ufs35WFO zjpYQCXe#m?^syZH4o5tE6n#Zt&9+e$n?r7npDWar9r4c#BlPP7b2OmN_uC6qAA0(O z2eL|vZ9%bg2$K>^xH&oDAd9icW6z z>?x}>#+8Qq$dGA@n7f{`O0Q`q);U_dgF;;@16Q zs47PjtS#_E0C<2R!qi4=0x-lUILWn^6WsDh--L$;({Vj=5ZI#UaaWFA%LEW@&kLQq zOPpEAShSzx7i)Wu*o1wR^@1vKD8!n2_$%awab!l50=x-Rma!FIT-$qlLMsvO2Z6wz zTeVK3m;TVs!s{GjXwEs#6{+**OTMnscUc@p7Cq3lkS%_xeHPw`*K?aD!Ce|7Y%6x( zbOP0WF5|J^_=F2R9*cZaOSqd`S=)0OqbUNqlpHHvlxP^%u1V^eYg;3U<329zw#q1C z2sMmd<%BAzn2&yjW_(P`wB^A6Dd)2c;mV=Jg|o<%ie?iM|6xC($BmWp(?IleMQ}$t z#v2I&?5$|XbSUQxk?dZh`D;A+67Ftp+<^Yv^(WN&BeqvP_F4LL2YUme;WJ5WqjJ7F z%Lfq6Z^$%P6{On(9b`BL>}@zH?$nw{&5$iZc`Qw9o-xIjt_Q7+w=YfLq^b-Tk|(BJ zT%o%9D`j%LwPkb-c+)ITX;#-FiiODhu{#P-McI)%E>yzanLU^j!r@11Hr}D`X{f5Z z3d7e>F(?_ZPI1$cuAJW z)|KQ+0P^Lew?qwj)wyz@sHPw-fB^-9lx**?h7`5`JqW$Wly z-+AMx{QDBm_F#M~|HA%s0Z!>rCbNl6#PP86&}6lHjisCnVtY5&2U!{e$g+zMa077N zFyv3Nocxn41^*yRi4U^WMj2`ZkR?7zH98enP-<{v))?ysedMG{XDjQ&fm`BeqG@9G zbSEE4>eTv>PFG=p*1^irVVBa4SvyV2a6O!x4FB;-1g4=Z@j=eDc{T_(b;sZ@=WdaS zEMkvB1mh$2E)FAn*?ZS|tiyO}N7HxF;zOvQxZ)qOw^25{EIL^cO!o5__b z1G_&`vSng2N2PG2C2RiO`zZVB{qp^t??@LFwY?ez*f9ri(>VbGaMKy?XOR7U>5%WG zGeJhBjhTm-OX8E2G+<$w=1RT3K*Jg`qH9H9(89~L%)6d=u2Jr#(JpFLF}7N_Eu8Wh zj2q6!i3~b*90(~-e+8^fJaPRMjPH}g`6VX=-m3Sl!-5|ez%`p`1%!luU=DaKenz<5 zijK$3Fmjmrlw-8HNb)nZsz?sLqRmY%D(Y-Ei&d`aSf_4E!3|EC0kt{MH%CUh8*3?R zakVy8Q9!;*cNlzFBZsv{@e>bC0elB1CmGR6mHTtcvyo6wV;SgDYTp|7HY9pCrqftG ziZLt_$I5OCP!*FP9K-cxLS1jjI);D}rhgkbg$>AzRTw-}UOt36gdsXSE|OsX2@L7H zhD1rNynI?_(aovL?SbpI6exn>*rS2+?_jhTt`&*_T0PC@_Dy3}>Jl@ve;_T9iDW?R7v`AZxJyMQ~NVL`fZRW%#mzpCO4?qQB)P6+|(PeN>B% zj4N_zECeVsPM885V6M6w>;@m9ApT=~CG z7D_mU7Q%KCyagNwGEiKR6^^IIV5RuP+JoNA5Mh)oEj(vaQGYBf)iUb3lYet+BN^SU z7yJsBS|-f#TPwVZCQ)?ED4e!GjiL@!jRX#xi9SMRSDJh!r~1CTqvGt&ppk0S zHT#9Ec)GgHNCOTlr8V%@rZ<_O@K%@c(74r@v1CO`8bbpXamhZg8ADS85|`O2f|a=~ z2JtN6BGOi^fvb>J8Y5!slP$(pofEvesWH~-5mQ_wY7hW7}O z?nMDZzV~On+0HsjpZG$={DO8^r4xvZ*ZHp?l{;9Uogy8%jcS?7h<+ihLCm(~YsCVh z##yC#Au2OwbaOxe)S+kENE0hE{ zUZ3(&lD~`s9x!uOovkkV#C{s65tcm47hR?L6F!7z&UbFg)c7We8hCEY@_O3pe{-zm za23z#0^4jp-1zqNoQWn={_BQcYDr7l{Wst1XO)%2m?3-v?Pq}MO_p22+!Am74`Ge!=PHHH9;9YLnZ64%M1yY zhy@P7X0AYNwaX0cRrD;^n1{!q;Oap<)gk6Crd+I7cQr_ZOd;TR=G9e}MZ9NyleMbn zw9BSYPY+xE=UrcG&Hu2>)&@5U0I#0d6#a0{m!QGQ2S4IHs4#ZXOjL6nZaHG3mgkl@ z(E5^-kweL@)lhbco=+jg5gU;LIG%aBy;c6rO}dG$lYG+QdqzhcZeaP*-wGHXyGqoq ztc`ycDgSr%&woM6Ie6;-hm`-nNcpj>)KH6(_;^n?1iUBzOSM?Q^7tR#pZ{T3`Eg47 zaAIx{Unn8PqypRX|>B!<$D5h8dv7cx6Vvk)cdxmQm6v$QsV;a7Yp zf(IXeU900?`VXaB+8>^8jI9o)C`Q3$`kZ#QF}o>+LD3EKgC52RGXcV{RBbULBMN4y zv^EbUvRT+%q}Y0{gk;x*(3=klBX(NivsFr-lR&K}NJOXBFBRhcxF#5CKr;we%1FC-aW}5#53X6?Vxw{inNO=%C_b6*H9*$h&$AE@mZ{vdM1IXE z$cN*}zuCwZuY?Yw`KuS|0YP@dwjxV`Xsl}Efn+OKZ@ z#?nu20XL{T?k`>|KaW_XR+7BMhKfiLu}b6=OGcm>;ljO2D9DbxBiptaR$ICFOOM>7 z-&8z@dw&sl1qa*!wK4j}$LyGF?nAD=LHzY0nTqt+e3U@kUu9VqI~LXTwNo zO7j@)BwD=%$&kKNZ%Rk2(-X;IwlC(cUL$e}M&>PaFRJfcU*qISQR>T=Hz$n~EfFop zHWLm$VnzKEz%@DQ!ox9+5;PVJu^1Juwb~Vh&@x%j(z%!AhfUKH+&5^2=~s%NsaJ|Z zEW}w<45k!$^lyCI!S13{I6F)=hzM!X*pbsv<86uw(?I2k6#^>J2A&aKg6s|yns%=Q zcCR+T$dyTO@i%YUtrp=K^7$58tLJ3(K+|$O3$d+cdv07?)}JrN2iB`QV?v&#!7@Lc z<2f|m)`i042Vr5Lp2M^{&!9tu+=k=btl|dwv=?*D#x-&Nun8)r7|M8 zZKbM}r5>VBSrXYY3mYwiquGU?C`Usj9)v#s_EclskW0`y!yyd)T`Rdz-g84jBAe=f zFqcb)+&$ct{to+Koy92&J$45Hb&PF7m{|53CX?;xK{fvt@C84=j3VQO=9Zxg?lue| zEym_tAG_wv>lXV4!seLREO(wE{y_wnr)i|UEJm^ioY>{AJzrRB>n^>|3)lh0VbY2h6qRSa;DslrQ?DRD zoW^x3B{0+pWkI$H6WofwiQv}w;g0KWnvfCDW7FQowZCm!HE{GCwFq7Bhn|&=SALa^ z3PNNJ^{gUyZfEONt<>`5pgzM>dz}{O?_$jSoLoSO>L)K+4g(^{@$J7^WZ`F)XoO6y>2-Ni`>K=>M`%SyQ zNmi80j=LYI7TrMX@3^UVZ|sZ)jKVB_4Vdx2*n=woOThs$l`L%qRidUoO_$iVQ5q5m zg3mXnf2N$v1tAXfN8ke*kDr>Zi9b186QykI7b3d^fBEuR{N5txq}P#6%ML7tWN1S^ z5@ar2rG_y1R}z|$@~~*un7`kOa|%QB_N1<7p=Wm;o~{Aulx+GVB0@l0efWTv=~pYG zb`jpDP!L>*yjBR$taeiSOEs_2<#n`s!4s36d?ecjAzR(F4a)qu!RoIXtYJj<<-H|H zwuX6#*kv}MUy*DVLakf&7d8%^DZ3o1xK#U)d8{3V}(T zY=W2O#H;cW%NPWKi)S`gw3+pM|44uaSs*?IldVw6$_Di#4$#jPM&ip%{B}0c(>KP8 zYKwEh$SNwW2Yp-w9z%F5i+LzMcB^|x8SwJn!jc0V*mf!eu3!2J;lGnI1_le_b zi{7QS_dlXYxb0H3c9N5UX9BlW(2}w-t^*N0Jj^)Ab&zZ8I>fR(l)$q%92?^@0r}_G zH3hhZ1F#U&xwvSv`Cx|2f>2%MLhBAAYWr!CPAmPf6;*p-@`LkEgQ}`d0jj*8X&F|MzXKnt23PxUA?X^J zAV5|vqndiy$v^*QwDyX)LR0ZP{3JhEnDG<3>-H$)rG->;Trj{5_-+cdqqdlUdG+_#YFGr`PkP*d_Eh7#i{Ik`ceP;)*~E`SU&^dVY|2z0Z-U+CiZ?Hp;qR^D5}8sW%;Bqdo4Z=Et&1E+$J4i$ z_5q)bgvmm>jJ0M;J=2K8ww_m=7h3+hoFYp;4eS7q)i8Z@nNEGmy&bcoO=$U>Tly zvrq14Qlh7J?!;WTGYzzC97w={6VMIgy?l(pULbQ+9~MI~g}>)La(U<+0q^bu3u$Zl zBU7>7_?mWeCAuMlX92DYN}WdPFaYLIC?L5Qg0ig3x}YeB0fvJ6g3i_|G^Pvw)+*0i zmd0F5EMTK1YPd<`rL4=`2?j&cLrgQVNQOIvJiHLN*o=Md(45n62Lo4^P{8uU_gh02 zLp!6s?wz6SpuEZDTRpl&^rAvhT5I<{)f4ZppKHiFimUkeU@2B#&gOAR&(E8W?hg7ts@$2G2I#>9jRYABCfAZ$`Ow$eBuE&)0+-0-he%yD zTbVXKmQWdtdITV*Ii5Hi@$NK-*o99=89dJ+!4P!be*bjSL>x|IgA}m890LSnKmCir z*uM*Z{+kqLbD{ts7mGA_^h;$U_?%3HI}8B{96A967gV^Ewf#R2np|Q@B)|Z=mNLIP zJKcX%Ut#T~Mi&quXtVE(aNDAXY15to)t}v$oC?uECa`_J6|t^*N%Yid1 zM%BC})evX;wQ1E&{K}o>S9PHV(s@pZ0<#GVljfwUdfm?->bMLVRuH$&#y7@zun>;o z4{-SH0XSy;#Nfzsf%U;1R|+9HZj{k82y_llc#isy)nyZ4_)8BDz=8giTl$x7 zXWBa0TQITz12t6vsilwapOZ_ff4(n&B$v|Gbv}|yo7!YOjH$zTaeMZJ#zvEL{LCAv zD%Z?)&S}%lDV}_qS;!8*fB2P9S$|plfX^Bv2qtFoOvifhw2==@nBqU&{X2Pf>?t zQd*ESbbX6Vr}AIdM9g9DI13WnZ0#Z$rl^w)v@Cj)OxdV46)DS(o$hBq0n1BiQ6R_N z2^&y4^wG61>}up9MzQhHBgfxxjKpB)r9l3U@m;FJ#WXrv5~-f&iqUJE^1CEH zUXat5vq=zKWoGSY_(V%XO0)pWY^oXS4vd>;rM@D~dJpq)H;$V1VMgT`*s{fvy-~p3 z8AFBiq0Q7D!?&CWVGw9OIgDZZQWG=8CB;}aR_+JYPc!?|DadO6+f_Z*x|;MM#D^F! z&=G7pGiA;wF${1qW%XMj88MnHsynynn4~T1A&c{XKkVy=F#uY%jT}8mHktg*w4K$E z?nYJ^!>vbj8jIveVJx!312&9-S7mkVXLHKEDkdVv#M!u|UO+UKxGGk(&I8-5GB(r# zLK8j)YF0Ua@{@%q?#RlLhd4Z^;$4CcM{_|YXjIitVZ0#WiV~Zbz4S6CgEd5KI@q~u z=4o;H1&nARfryx2f@^XV&_AaT>`ya+Qz=X`NQQd!;RR7`Q3&_Arq1nGS2vYz51lR( zeY@7^bX_#d8qFV~+Xmxa6NM^GYh_=l=t7w-L&j`O;H#fV3%Nlto&5!1sc+o>Am4<9mU{HRes`MNckPd?! z=OaoeC98(&!}{*t<97~^jSs&VyT)#w--}U6eQbsyR9lT++TsHyQLy{oMbcRc;kzPn zy*3Hh2XZXwBIGSU_;ueCeu{*mjbDyVB4k3!y!=`CHAliro{$gKt1)l9Bskv_l=htc z@TMnHUv5iG&bP!;mK>k)*~&Qc#~sQUF1~p><|>R%IXk=!O(_Bdj8A4@jsINf6e2{b zK?C(PSf28itnvw4Tqqe~=FvPU>tHo_N`6%-3DYP)x2UTOPP4rw+f>W)-}>VxPr#K2 zUzM2468RmYuG;or)aGz6pNPL7Xlpja$$qJfbuTc2T*~Xm!L9$nTGbmuExKZlumrYA z*m5q3=PV26Q(@ zST8lPWk9r4#~IUQk^bNoq;SEdD=>1zn|FHWQ(=VOjPPBqXgD+qwgl+_T4ekeSrirs z{)JNXaqmIGDatY;3I}9lN@-J?fzStRN+xXKx*fnp6aOQkFcV}0=%`j`Y%#k`Uave6 zyWUKk`ZaqNeu$^nENl7c88)?o-rbw@T@fzAiPt>_6LhS#Ky|)Ug zdrP-?ad&qK?!n!IyDi*Z6Et`T?hxGF-5r9vyK8WFCwH;;?$i79?YeckpYOwbSZ`GQ zs~F#Jj`@v&6c3}+t=YtIUqML`RXLvz|8nlWjP`P{XJi730>6)ZH+1G1R(T1a;EuSj zb$rE1`u6v&n0BDxe9#>4ga-=Fe_WsWKZ5fYaGC+d=KcJu;QY0MnV-0xkg%eyt@)#& zwf?BnfIf-~PV5;C?%3?|$5ulx)@41Ugm8vgMScL5NiD5r63@)|xPfm09y|HWqE)vS+_CW}nkuSV^SIvS@5%+`v$@qT#!!`r2!K8H`w#x*^&qxuI8sYEiyX3@ynv+18R!SbGs^@uT7VHQC^zZdg`GIbG%;xJoj^dT`wG!4 zFnpII860ncz61j8(Q<3m(NOp;@d z<$$uXhBZ+`7joR+g0#clHowHdAX>+iqZXXEBl1DSZ6EhFe~07*2NQ_NH8(4fWuMCOZmzgw z9WQ=Ad$4XMbfJ))Bi1^qqC*ZyxU+DSx5hl|My=1AAW%h(rDfzTZdkYc?)+oy3$a?^ zHe&v)d3Ku*MMgks?DAz%Hh}mrATDCBQY_~!23Q1x#4CLDoxwPlNB2+<)0|GtdBtGTp zO?jo7B+4mAvm&KpQ3itbx(G7M+7E>H7NxaPj_0LP8i@A)>a|D$g+&d;VMkk$gMFiZ zmSo%V5A_O_<;pRttiH1AcE{w;Ciuy}%c6VeCs(`MGp{?pmr=Wqt3l<;X$G@zbXS4J z@#)Zymvk02!(2c?-DUB5`OuC3=w(DJU?pQ(Sl^p4ply>HkzTNpo+ow!{b5+O*X2OT zo>(k|8I3zArx#*48iz83h75aK>akm>3z`*jIOOv9(`*D>G7M|hw_&;PAk^~TecYQ} zj?sOK8^5|w}fKQYt1@inQ)jHg?5l)S!lXP)>9 zYcCoSd~PM$$?Y3kyi79spg$XT>xcoX+@&0Rzmsv3qAf?N0uSn!KY10O9AdxJ!SnT% zOWmnGa~cmQ%(p%7WMX@Eq!UNzxtZaZ>uJ>k66^K&olj*UA4M8A5FMF&(rPB}@l*<9 zzleWB^EI+&LQfMm^`p-~y)Z!t3YnPTvFSVEt4AEfX{UTEFJr-U)C@EVHdUO`@*RDo zrHj(r`|M?{2Nghg3ja5^FlHlk^m~im$vcw z$2$KA&5b&FtK25iC3y!ABVj2hD z)%l67E&MSypIfucx*T!=BlL)W2g}F$V2*X=vw%W{pr8L zW>a%*E;eT;zX`U$N=Q#Aqc9&Cp(r$BxL(%?gSlLz8mj!)Gz&*rV4 zXJh47HCj=d!0JG(L|#aBfcz6b-(SwcQ$psyhtB`U1t;$x15T{rt-?VEWfm zW`6!(VY7Lsdhfx1{1;TS3BbJ>NOCPFO4-_n(D-ICU3j?en)1mbaA3n3mXjS_0jY_7 z1*7~>!B#wrIfvSZ(>+IfNmw{F5XtNWc90(d80-Q88`gZ<*b;$?@p5nAw^Twfq**_} zK)Qv`Zop`ES4nxe_z(Py1{aRhiy;479MGvw4DX-nNcK%>K(ovZAyc*e6#1sS;{ zJA7W)_$XLtWmoZ@i`)^j)S)2D#aF*a?VMR(C7sqdPs$o6lu&#kSY+Cl);w3P3o+IjO%mW$rx+UcsSnnyygu@(T#WYizzBF`u ze;8_wr<~d2vuzPF_3c(wv7+VwfPbcbAz}9-1XG<7v9~TJ!Y$y8iJL zaRmDPPPx?mQ}n#?lpXFY0xuigaUFkoO8T!Tidvkg3c92Uy|vI4&DwcIL04XJ8azy~hLIRhkf`a}Z%v;-q<(|z)<20l1nE!n+@Rdgp;OL3bF7|x*3;5%}>$B^|_@j{*JL2vw( z_Q5T)O$imAsf9Vy;UuI|mxw^0#pd^I1mE_|xkBc#hk4J8sn{e=)BWz^`ec*sWt-n& z$3;%5Ah}ASVAWO>I+6ZGnSeE_XIi@N29_?rDUG+gOt;`PtLe~0OFCRnyb{0PIyCes z4R-s&2N^6__Ny@su;u$KcDfV0X1x<*6{cP9Ei^aG1hg#dueHU{`w7Vu@W81yZ)7y# zhO$IJDqb{15S~yCraW8xunrUd7<2uW^zayeCGEzkIO!Crh=Y)yM>CQFHM)^0t{&UO zv<$GE#!{)wBO=A*IutL~pm=1{H0u>0T^C5u{B@n(Oq|G&A*mdO37I1=aB75N5R?S> zsGisPweXjWXzI-CNyMs~Awt{38{|J_=lxCX@S}`9@?Q}8ALY&dLw5dRP&=UHyq|xS z9koBZPV(~?rrp2BmxwK&S;ZIioPe;ut4_%aE^u4ZKBbQia7T6YN5*+TDG~KdNpF^; zj3%B)xTEtW@)DaKjbl8wv(;oasaUk-UZ(h@4Q#4Mr5WwY?(MVpxyR4@)^o4(wbFFd zCq!wGr%xc%c+}BgAW1OaG}`SO87OHIVwwy1Km2qMFQFG@T2eYwVUn&sS6UP`so>Es zpphSOmSvKL#|d8>@f=1F-F2b|;_Vw&#*>C z6n=BUqa#MnD4mQEYEad*aHW1AE(3H3QN)Bqf=?!Gv*>UU0#t&yg7+bq6c&GBJr|T0=m09THhKLz~iD%uAt4&cHT^2apH1)b-RU z$MK2U>}2$~koZZGEVQ>{#uGjuP;3;0P(vgqe5J}K_ggW`NM*Pr&7+4ekESrL#`uAe z4(>&loK1_!Hc|^WA)U0udVo>rgbGrB5e*~xE32t~>veu_`xSaurB(V=&w0zvS;@;q z;&ZACbRI99W5g$trmpZi4x1MlVSy`iqW%$W^DPjN8;FC#uDM9oS9{+%j z(%1twvf%nq;^Vq5&C{FABsLVPrin>hmrKbLxls@dE&rk?0<7fvNr90I`eDl-?!E2= z8_8;Nb(tiSHX76ULQL~4#^wIE`Pzp|)cv2I^Io5S(h5wjJ8e!jtA+H0)AT26_wF%! zc+*?qS$}-Sb(E>=$|rWPq@oM5Fk%~RdB8(FH>|EfDhmy?-dADT&qUJ}2|sM(Y7MAe zJz*Khfk$#kP?7zPV(Y4~!ZfXKH-i*LdB1pr5A7t%xK`utrI2ce|0ud7+i!jVH)eTi zT)(hF$;aeD95B2tacC!A_sXal`So$gl|lb>i}Udzg+%|b>j-4O{;Fy-up*l~0uxF% zQ}SE899`9sH(+f<9>p`35UQSVygZ5^HFg7i>i(0{SEzzj`$vf{e<}~7R|h=V4MNr8 zD^PhNk>MW1C4tHV=FQ7!3mwYpw9I)~XB?LkAwW2?xuvq6fiq%U*(&c zSK1PPN;4VZOP$P8UZ@1tdXhx5fJ~Vl8lE=aueJv*f$HU+vJXRi#Uy}y$s#&dNa)^0j{Z7&u-9#nF0{AOCPkA9bkbW*SCLhKZ!j}#@?UWF8rrivwv#O-!Syw z0MEZ*XdJtf54B`4#v%?1PyP@^4c^Hg+nYa)322MZNUmN_cMc#SJdC%b&1^)V!eGb1_A*wjdUijI3F(DX6NMXh0e5{od?Qyk@&9l@BmArV z%{MZGflJLh^uRgjq4eJW-E|V~l1IP; zvtNA&v_KWv&%8JhenxqBf4`oA`Q-bI(7U56)@3y57F3J^dts~?=;L*$u-#qmN#SHf z%VPPZwenZ>=Z{w0qv%}tvL4;M&wqo^YTz_LxT~P_Uqk5Ml7Zxblfe7=*J>DrZ(?k+vORuT0%j8oD? zKQL}q8I&YIYaZqkWM0uB&5PcarUC)3$Q<9*=ORHU5g1T83=k9~2XicG8VSFH&Cx96 zP(%GxeeQY__1aNvdQw|=MGCmdF|!})M%nl@Zt=nOLzb6mfoNjYXNW(_FKP{A)iPh* zi?{bL)$qkOdymF_jb5)Re}P^zl1jtoxy-gS+j`q6K?76*=T0^SzR1@U5-{~O0w;lf zT5t`_0MebD2gZ=OW~G(wfv*rBXVJ!wK=zEPdER?ZL^N!)K}tD{ohO^9iPHIac-(G= zOiHLQ@Vt<`S-9^)a49Z6+zG0_L0|@al%yP_TMK?{UhPI>6x=SWBmEc?BGuRfp%;VF zkp8I(o26?{Hg6wHBOezvhtZZj4i*hM*p~0hC>Z(V_E6)7jSxGuo$e(k4H#Uq>R?PF)PgixhXvX)IWrIRGJr)_Y5Q}68KWSb(cXALtj%^l$ZWT0H(3T* z_x#gW?bI+N!XM)YG}TRUBlmRh{7Zzdwnsmz3MO(NB@2mgl|^xHg^ZtygjS5z@0Td9 zF|8d6vVjmfp!QUqLSOb21yz_?>Z{z>T+_4+uoERyr|K#h8P!EK#x{;#S>e=TAxvhxYAPZ|hiZrcV>$wq`~DkQ$^v{K!Gpf-AEKplqbfwUUs%tMS1$ z)YYKpyw6k=<5F9PvjytjG`DlqYnB@OM;;*tT)QH}gEN zphzr2yU#o?yUos*#^Iz#>pP+@-G!^6x_*$sxEDaxi>(9HtdmB*iWjL0e zefagHgP8#9^u6&cB=fu*haaEbk|RRzV)DUX6f^d60bl>f1cWk0#Eu)QDc&|d84 z4|4?FA8pZ`JJP+gAK08Qag0QQnFV^%qUwAQ(jW3YVVX?In1A8k?;smLpg2uGh{A#O z=5lxr%JKzr$dySguRcHYfd%b6cnPiUPT?-%4eXe0+Yun4S|4r2rZ+*u746Hc9<7r) z2Pj8x4E}ojFowkmXaz5|avqWZwa@GwSbOkn7F$7|*RfDhpB#cs;@oNbC^-C!6aJbs z2!36be>OQggqeZ*_D4Q&6tLdfMTEx!-b{NXP4Q+_^J2c#DXixO2PCd)NG{#?E>t4O z)8kjaUTG0s4t*^gzxz3N;Uvb)26gVm+`-9asN1q>(8ARA>*#)HcK5#gVaI;}n=f}l z4~*D6Xmf!=T>&eOubpCx_%QkEm-(7qz}9e5hVZ!`;a*(Wy0wxp@X77fm=+Yz9S}lo z82MxPIg*)$$ zzL}FdMRG4t9le86O^qT-ryYoa8C)SAUWcz?ou@5FN>-;K%+JFH{+UMB)XqpcM;#w1 zv_vCUTQ~7o>7uGI#+Cflq3~6D4tCLgfkY$RKBc#OkGW;pb|6F>9)2&L!w`){(- z3X~n(san5(IHCVBg#Ilv$Pg$w@8@4-N9`N1aFgKM|AtV%Um*KM47E2UFEFWM=KZV0 zdez2)ITetQhD-AfbKn%UAO2Z-awJ)BDVT?wWRF`lcs?q zfB_g63~!P$UB~zQ5>w~Xwb-~^I{I;TbijzBq~y$?@zw@R+E*D7#NhyQOi1~Yv=&j< zKKJ)q3KSG;hryrOzhQz&A?p-Dgm?y1)jt&KtWbFD2fR!oJoADdCGYZTW4~jJ0+ZNncD=lpUOOXL1rW=5E)?9QUowr|5E;PMllV_{g&f6u@&)^#8WEVV zKtWAfi zH9{pr$G>;@jVi`NYwc?GnNy5zLpp_uwt)FSxk^HiJ1DMB-N;K=AHMlrHMj3_M76j^ zwe%*gdF89{qD|dCI}zj6k%?+q7z@Dcg@@j>%iI1`NvPC{<%O>|?&j&B^qFJoJ@Vc- zL%OJ+v~ryg>B#oe-x%c_u4<9CR+wGwNs1e&Bm1lcuC1R+4QJ!epqexttUZUEo9kx{t`U68~(|PAPB?eG=tVNiKNYIdq zgk+;1*1jnE8R7eSmIwhjyRl81hg)=j$|JRH9QkcS^7;Ooo_kj5ZfCaRFK1Q(%m{N$g8^8%S*SuA5cL+_qtlNppiIwM-2STVq7{h5=vzpCW2oORwfe;Gy z7lf|tI3iA<#LTP1(6M&X^Y$f=>`JJqkAfK=g<$zNkB%tGv@Xu7nEU~uNvtTg(8*AT ztdA&PM#Q%*O!#~RgLg!~ME4UbMw1XaZ;Aqpz<>}MTT}gc`w%P${efR-6?GDKF|89F zuq_WJk7}K=8K3@wq&m4j(ze_|YFn?Rx;TpQkXz2dG+%{SdU`<(RGz5bfp*u9>4Ni! zgYmCcrH8ZR5hDaB*!@Y}0DIEei_VE@7%zaUl`Jyti-{QK!?>P<G%({47x9usbRP@UJH+r-kI&V5i?gU7%>jL zUd6tTB3OA^p3H6FfYEzl{jFbfP`C?}op`|(8gwGO!ij$9dvQ@`)>29w zu>4Q4iivK|CYumi9E0lIKEu?vwTFj~nQjzmC4;cx(*hi?4&L#=wY3E{dZxxF7Oi58 zYRbeI?`d@95L?5??dH-|Ia)i>rd_vt0c?H+M&oDSl!*2qGumnlup>QK^KS?>tP3Tl zjF5#1QOZ}>1kEj@MDqG|4!zaSrtDfy6*1aZtgJtMs^aOD#q?m=3ndigb96wIv%eV! zZ7oZg+PkWV`@B+omVy9R$o%#<-FY`c?Go#LQvbIA`oHpn{tfK>3xKK`!T+u71X#HV z)%sWEW)NJ-r{I90mi_y)46i8CiXrMF!$MQ=$g&=QeNlZ45=yIHWeJgcc?&Sqv^W-Z zQR5!=uH~&?#J=8En*~;K*Yjrt`LocTQmV80jSK7d4K8=ku62#37~It8E+dgzpJuAY zWtkKwHq0l=Te^hQ}k#RnVFMW{|{zPU-zqNF~zh(G=;KSIWjT$c5(3imxZTj=; z5wyfUw92s7Hjv8+yB8v;r>c;R$8R5ba|vmJkht3Ig3*?--YpP!aISI)gFu{ zJ@=@eBx%pqXOYmaz*Rm8EtN?EeNdV_G7}|r>^ZZvR;Z70jxnZ|?nC1a zmF|`?JTV$8C(M_82qXxxgNrL+jSc#EE zV?@UkKwo&s8yxQpqFC1qean7B2_}VLQvwm<8cbKC22KLx9%hhUiU^O(uSdlcyeXI+ z2C%?MfL6-K?(UCCATLhsk4eC>F}^4iu~M2KAQMsZq`xdtT1_ybQiBRKNZkb+13!^i z6{?K4mzpAaS?ze2^Z8LsS3?dLP#gbkf`2H(p$KCGCYT4W6v03ZBQShs8lN1nFJ_xd zyn)xLD8p3>o)pw~lm*&4;a|152LiAK{;<~q@~4y2)xqnK>OBqH6OQLMhZ8S4=}oB< z)_)>sd+=lR>L3~s5J8=Q4{?DA+6j>XM9_dwRa8I(mCpmt0r{Bk2+A2B@{XW3+y>w* z7O=lkD?f{}L+goNF3@}cBIvR9JA$4jQ|(K&4Js!=>>S=j%UxS7^y~x5E zw%}(o`^O}}p1@ zthD()k9Oe5{2^_I-Q(K#jfgEWFz>Y9^OnmUz&4XmxIaWfrTw*fzJ3 zS#~sHN4}IFcc-V+%L_|&=OeM!+t4^FajcD@W9SV)1ZA5txMSX%m-JH+JeieON1Ew% z4R*d_e;)+$bu}=7g8)_L5HD>51TJt8D2=bxIb@e03%hqr$d&CtvDBz+r=8BUT!;)U zxW_)=L_7*iZ;8KsdUIKGxq6$!|rQ*K;0r;4AHj zn7f*@^R7*-guRHjD?|E1M28G-cR)C9SN8FMG3*9=r5>!bW4L6ZRt4hRsa4q4uljcD z?4<3jszb1>Re)=!Wrj1bCugnTGL`voM;9k|-^a9qw~B<>Q?ip&7$ig={o+Sb9XfU7 z42^!Datn2NfU&nE7aW z#<3<2A{URR0&k!v_`JXs3GjK^sBrMTN`_R0yK9L-5~yP%EEzAG9bdgX!Ap8LA%BO39n- z-3MK1(>Mi`m5k*QK=uNC?ECHOcn+`68edCvwS|E`sLqoQ*E@oS0TC2>U6yPX7l@$z zeF)H@6rnUoW%rA@P{rUSG(n4iYJ_BQfImnkdoF z@PGgswDt)&37o%A0zmqd68^&i)q`pg5U~bu^GWB<4isbzy{TOVr_1p`+MWnUUm3-@dlE>zkVKjXPOF<+gREgI> z19h7Ssu6(FJS?4aN%U12k)U~`iPX`wLCzo7woYQ%sKr_)Bus`4w5{(EP?3Ob=n0kB)pJP4Ft?nun7dt!9~xLtm22 z-VPv!5~`c;tzNoZ-0ok!H}1VUGVg)>d6pi5T7e%2f)EO#$fo>$@rmA{;b*U4sH#j) z;V4)BA=5#)hF*?oNo`AwNuj2m)<&2`J)LO=qwv@AK6d^CVt>b+o@q+9l>iolvYHcQ zOPTpLFcaMxBwDoG0xU*EdHMxKU;@@glmORAj^hz|mKc=T-^UCN1O~eK8t8&rx0;-{ z{c-Ubq|aaLWFFRyO;156uE+p8$)E>IRXZgYSEJR<6IbW7b*CIZc2Ux+baPnMXE*9z zEPLD2TY`x8#m4z-_E^(ZFpI$&jX2Hs*&b&-?=WIk=q3tX4O?zNYs9yWF+uAIF0H`N zV4wKIY+()90SLJJ`Hhlg>tV~3f*lM#*$H3fAwD99&544$SeDWHsHtf1vl)El=~=v) zsy@t(ohb(L=M%)=_>=aV@B0D>`Y$!T-j`26{){5F2XLd{4E5$|8-h(p!mLPtSX4l4UjE3E!UKS-H#lt4I|exp&9YD zHigw^lOh+}7ut|7D3*R@xC)OqCm+p$bczveA@Jb=^5-WYf382sd&pe=!JqjYQSQ4$ z&Pt+yg23&p2jhp$wv9n7*_WHkoVAFG#T%l4v9 z?F97^^8@cquAEO_o+vx?0_WniJwEIa_2)Uc*j1S}*`!y*EG29ZJiOuv&~6q=y>#FU z+ETnh^jb(7JZf?3GX(2X7y6|=dis~?Bq}}HQCa2eJWz|RI&U`agp!6nuva8qpxZ;6 zkPt;boGJ?W86AUp)(8RSdqP-rDAFr_ORSMx+7ImDT5h~egdsa|5OX=X=)Qb34t3b$ zsCFApAdW~Xz#9|jU&XR?I+93RUK&PCNrI`C?*R0)YL=D3mlkX-KmLM$r0Po`F~&nN zueVRIZr`&oITRjuh@nCG5b@c%5-1Nmb;dbMuK`bEqAjR}cFuksKSdk;UK;3QFY(;{ zmQMZ3?yLsFsZ5FU6qlfB*6OS7T2vBtG_Re@B7xGX-R5cQQ|VxQ>vOH)rtwAeT+&4) zUzn46TK{wsuI!1Yv}1G}rLFc9svfbQ!@srm`nl)nt?F!VGA&hpg9|ClC9(hWK%Rn& zVVWKYpy{m3xA(#jbOQmD+*`C$!gyLfi%YK16IbT20E5s;nlrs@h?}CJ&VCQ8x|zxb zH7Q?-@s*Zdw-?PHpU^UFjGYf$axf4~BN^1}P-Xc~2tgyCl9Or)1_(kdHP8nrH^Bpf^(>vM^P|MlOjE&t7LxSueQ7Om9kFgcouK z;}@>T4bWZ&(Dd(P_I!2}c70nY)di?}OCje%kj@#SrKkAQfD$oCIoS@TX`^c+=as4> zmna7Wl&_MW-C_GQwomI-XF5R*G4k@AO*f$S!f`YfsMtbC$S?E}ist?W{kK`85(#QP z=O<#=3ru<T86E=d!L5!T#nColzcpBMi&nYnnVh#Q;}55swh8Y0*2o4LI_{o(<^dLM59;eX zi@zkQVUzyi&mbUw8Uj`4NvcSu&5Pv=0R#T8Vge!4xTnS0*|v$z-$H5!pyHOqsqQqD z-L%><#&`*dT0NEws=0p%&mn9{Z$q@_)T-K`R+RW>^MQVzn3OSpT{x>mS0y z^r!Gx|0z5J)Q{YeI=V*4`HVWu+l#L?cnmxeLkw@p$(ag^p;#r|l@O`QJ=9c6NFYOs zKdXDb-1&z`M<)3{tfE<3x7I^!u|jJ`TxzI z^}tzxRMh$S8kjNozLfJHzm5Lq4yYP%40u2PG78xK6*u&n4GgetSEtqh;wKG{6ApZi zWwwc}{-ervXurQ4y0&-{9y3PVPg89fc!p4|AN1tf2?=aa=sPWaHYWDj`Qhy0S;qb! zbu{P(*-~@S$+dHg?_E-Zf${a+`|IxpsN=d$xlQb>k@k*syg;=Mj51~^ivG#;RIE1)4Pb88cnhq z{F}Iwk^LkT)Y#yiektc*HiScGT7DBUps@^r2nnvxk5segpjiGsjBq}3iugw}PzcY~2DnrC;#sFuqb`MGWHSJyhcYYxPdS7JclVQT}?KyBzafTkU%?&^%q+obO zKPw)N&zqByPWw16(Fm11E6K? zSWG5dA8+^|qqy`f7+)Wrbt-);iY$gEn%x-;tT8SgQS!{^SAr#ai;GV|cm7JdQ zx=CBnTdI47Pp7{wdXXZ=dIUG=P8!R1nmP4Gx7mc0_B)G>Uw?sEpv@vZE~_JEH~5t* zn*eOvmdzLAu_cX}bHZCYbFw(2LW-58<$b;*hX(uV0@_o9qA$?^_)!6^Ow-9{1dkau zLHtW#yM`VJ@rO%^+lT0c2XK`87oynO=Jh3uI;u%Xzp@Vp$~vcX+@KOEm%nw5UN*u% zvH4t2XlYgL36zz?2~|#iLk33J21vvYTKCEIhI28j&&N8qQ9WBt)cb2gw!0vP&k!#k zR#^)moD$@zaauS>x++oOvqRTE)Ff;cve$Dle59!XU(fBgDXS0VA*Mx`gls336RJcC za#^jjt_a9d;_93J)g+!f9jwD+mXK^9m1_yiMylhx?NDd2-a8_X@nl6&# zv5tv6G!b;AU|r8MOtqbEI<8ZV{qP$%V*MJ&b;y8;5tDaORc?xStft(bmb&4?KbZYYz%R~FPfsm(-Ew&4>VvFBm-`k>jPqfb*EW*1M?3?%1i0A|~9x1|RE zt%2ljqq%GVTRZ)2mOP=Mu88K0Spm0)c`Mz2HeOVrijU%nX+#P>sQUr&Z1aKVeB{TblqwlB&vd zMi|W&@no~*jYj1R8pfGoRWQLp5A1Tdkycx?Ey+jj7Mge!btEh z(yZC*N8f7b!Q+u?YVbU5sh`g*-iVGYcX)Bh=y3OyJ2|l-b-OP&OTW6P>|Iy)JbNif zV}&=mlmy@ZeDHK~-_WDpzmvm45)_GOO88Yqs3~0wK!BZ78L^;fHox`#9g@xU+riiH zbdXT~Y{oH^%lt@CrPoEt=Z$mpV+P-B<5CO3Y^TyWN<7GdTU=#y6$}PJ5RECzd9Hhd zZqW=Vq+29$xRlVk<+pLj=vaG6lcKE^u{N<#PD3i>6ZQv{hOSP=gfPWl&0rpH z_f83+lZm$IQ1{O|G{Uo8IL#pBLS9WO0@uk|v-*i=9BV@(3n5)k*VzAjZrcfz7v~YM zkM}@%as4ml<*(Pa7C>ovKmRXzftS@*dylYPnRYm5U?>Z3SXbs)GSPHvs;lema1GU7 zs)1OGsh9ky-7jLeV>+9F1s7>cNCqF$Usu398m&2&(>pq;+zSPpicbmywbJz^O#aB= zQ>+|c;SA`}So81S>5d)0TYo>EH}4-Ies{w~_Tk0@S#^P%1O*wo=s&p%Yx!6kF1A?(4Z;~pu<_(Jw3maUtVjioj*^__8i{U zzz$5+MOzGhO^oAZ6eC5dvA=}ESN1kL9`&D#V8fRU4!3y$DhyaEeO@{#s%=mI+|kaV zCg^;Ym~T<($34}l?dO5jIe{W*n_w`LsZzqClTJ#R7y2LKq!uV0KSZLCUCaW$vf9F2 z(hBm8Mn(l3vSBTQPkXaO=x?2EozUYNXg4$80%JWaLlXb6T%e-A<$;@nNOPI-3l1HmF$_LzkT%GK-}yh zf2$%Qo=5uzvR$!Z?83g#iYFHdA=-tKixP;T_8h9vnPBzwI~wPn6CD+CbM-6m|B$2L zJOI)_bx82NZZkjvliF%du2;56xUQ7*+V%5%{Cbx^KBN~C;wVsHj-4#lkxvO(s4H<* zmvSi5okr1Sx9PNeQIjF_gF2m4465Gc%VMfmM*i*O$~y(aeE{5Q*GvEz48wR@hM!PXHk(30W}0O@G&Jl<1)&`G{p@VkFC9GG8^8| z&2#x4^oEa>q(H>enA~FHteW0gj;QGW;`>T)_@5W`z&*y-r5%y37q!qp+)O3PJ zuH>L8*dpH32?6Aq8D#hfcAcQ;+E4bBgul8Ra`mg=DZg%Ek`4<5?GOH5k1i&^$!~q= zdhK8oM%n!|0!jklBp1%|(%|4)f|hsp!q#l82k&8h#iZ1eq9 z?cYO%{tds>EC25RTke0!ul@5;?YDt?%uiDO8X7P59UcPDgu<&|7#=}9D730pHBQI_ z#HEZutBGe@h=8k|L4yaBk0JH_8CAmU`qBFO=Pi-P5dL))i-0fJgSWBMsd}YrE>J(~ zUodgpsNN(^OvIrc!zqLE$-YXf{3yf?9)a!qZa)gs$!R_@>4tg$8 zW~NmGXC|C}zJA`<8cxhPXin5#ZL36QOU_L{uJdgv+*%|nh~uwH6i3S`-^_vb)*=px zrOhri(cg~;c3jHt^S^_EVdbvN#e=*zEao3g=|Oo4$W7=5Cu&3@Tz4#%bo7+ZZxzF; z%Ni}I>Cu~D5(u~aJi-3?J>K(clfy@lk$|_$HbBW||4%ZW94$UOIQ>0XNC~L;@8@4s z{~w;_Yu2BuoytI{1V!YL)C)_QPbj;=gb+9DO3q@`3=2Q}ungu~Wnyi4y9HHY@mt8e zK?F|(YrjQ|N>j%*e^j+U?r=MawT$}X+KUB5xXj|B7rUrE(|x+*S^Ljx;BKeK8N148 zlNMMf4m9ws3TP9E&+di9YH~WHl6MHm!cmlcTg;qPHyh^f9@@mRXlnsV4ru#wS*o~1 za%%?7z99kUJ;eZ-n1YHCk(|Eik`AHFLn8uZUo>uz4@G^pKKee_QS_bX6#aXVwNMHf zVZXs|pM9W7H(@}9XlIwhjZl@mg1_;R9RzGQG_Fu->)i>rF5=VolqY9p2ueGc#vm9b zSx`viRe&LqArIFDECrP*$3AsV;kJ?8^eQ*KEz=Pye^ht=fCFuyh`QJJ4|aY^iAC%+>~&IV+{Q$Op9q6h}7XBfgQ zJ5D zjKm+y?`Qohibq9fKJdygS+t6B_nQYKC$lTp^E6LKSUve}mu+{iM%>7JxKBB#8g>RH z!*zYwyiLbo;e0t|GeDRWWUML!Ct)9>vea2Y-D4<3B}dKA)U43Pv9N40edcSsHZv{& zsWtw*7&8_fjyl)QB2V5?)z77`N;ipWtwgh{fhn2LDIM8zSR5~tz~SM*oqD&9HP!Ac zXTv5}+h5W+zgW=dpzsFGC*al)&qk5VY)~K1eFucXY`f z;XH1kW05w*c#}zEoQO?!-ucH<=|Z-FC^s1YeO!k+PXW;D{X=2Gmf5)x^Q?Q+8GlT zWve-i8*u$TZ2qCV6?2DRZqBZc&3yOEcdHG5hv|y4FQtL4@j;j8!?iSt?jMs@oO=pz zj`bRn9`PYkAMyRK%ruyR54F;?Ck9du#i7?Wb5g;a(!ni3i3&pkxz&;7_ZsGk;yJlW zs_h_+VkE|zrGzG$!$0M?Tw+l}wXvp!lPOWx?oR=J|E{<2b3 zeMO-p4_r5!^g{8;ZNzb+r96P#24#5+)40+US(T&Aq=@~M^4U%N=fLDR>rGGuLOsoq z6tQ1%7>?gX8QI$+?X9DazteutXt-i3qbq`G4(s$WRNyr5ITfkGlLBgPX5l&04lm2GC~^NJESF>sGAs;=to9TvItR2Z+RE@6FWbG1U*pb! zm(QB%BHkjl#17?&9f7=|wl>8He{{D;G?f!gASDJni@Y~}{7-QZeiSov7oGkc> zK;(GKBwvUoI}Ska3@{rl1)D_W<)28Lf3@QF7~KQ=*^F{lOu)qOe1h>juF`(j#-62yv`u;I@g{d<)DdrkKH-JNJiPy4(`18uL%nbZYy%N>f>|U3s6q0lb*Bc zniqAg8@}URjNyGq#?vC{-AsdB*=8HzWgjLNy3RDMoTXVH^|Xi8PN|SOB(w~mlYL3G zhcDY`W549O_t;LAQhwFq?b;n;_ut%6jEXZyB1A1;u4z>}TEawYZ)2RC^RMFb*MjG(C{TRPXbZ6{Tj`35Lzh60wBV~x)x^5%s40syZ3vmiVXTE8 z8*QwchqG%m<8Ts^^V!oav7DW!hOiJBOe=&7?7x_w9~>a|*KrB8yme zuzXiHq#{hc+y{SpZ35ENV(;dWIBWn!@QYUV1TFo-_%^CG(Lt4dAM`?^Hk{t7;zf92 zuod5Bl~=XUO2$X9X#1L}zO%~@P{g%-!L#Zlw}>YaNOy7`{f8`da0YT5CQ-=6tRK?s zAy()1#0`-i`CC#N_u$^Jj=y;WPDZMLP2 z6D+txaCdhP?hxGF-66QUySux)ySoz{f;+)NKcwF7dRO&Y{T)@?-^TR|9uCHR&N1g0 z+i*~N9(JD})QeVdO7Aj&N*U|}G?VL&sa#8$3@v!P=3obAp!Z%_FZY_zTbLocB#&Y< z#F4p7t`(=ytbP#YhSwV!k+FsR6ioA*m z;D|E-!Sha*Ro+!8nm(^h%N$5^&RfaE#<`+GMpVkyxDORc#ZVB$bPzI_`Xsw)pz^Rf z*wC@T9ByIKr?G-Xr%){n*sVRfs%w;^R4q=jIx}o;tdrI+sOnomWpSK!Pvsd&Y5d|a zqsZ8PRg3ERMKrkIlr4(aC1+FQ4BiJWxCebC3!-3l_(agp2=$u}gJ$?HjYb1ayI;-u zcBW9U_*p8dXI#SP*cJZ*$Bl53${4Wpo>?-2Y`;pE8hUP;h-T*A)`qM&-Glf1i=E?? z`yb*I(R}Uuzx+Ul(eJIqvkLARhGq!prBa=0OT5Zfw{zieXN}uA^;D*kNXRX@4eRUg zp_lZ8#{9%+z>}wow3f9HP#{b_yYZX-DLUp2LWEUt44~;|gm+ADWe&8mp4)Ud`qDQ| z6jb0#k(?JHn%kzU&3nBm=jUkQ-cLy~{aFua-Xl~J@rYZ;;N!};5D&E4SN5s-@N5iE zan8P=Yg`&w;D{mXW{99IY4+o3&$S8VW9^sPJSFO3+bxU0t{4Ys)ze`0!5VCKI7m8r zB0A}Oy|*=;5^6Vr4HWhe$(7yBQ^95snS?B-64evfJ$|EChXV!(a>VChVKSeFbcuJ? zEU%=5=hD0SZ)t>=c{w%y3=L3#YmGkoPQoF>O~1l$G>C0&QLbGF78@XiIV~`%dD-fg z9t;VR;seki`pV0&6G5q^NmIRG{vSqj!{7k<3H=%E>_Z)S9QmET#VC~h2=g&7-_G$9 zCxv4|0MKj*DlVfw@=Q@pKQ z0Iktwj6Gy8m3g64mTCHGATuj|W2VgNr=G0c;}#g2nAAlc#6{F@d&tBjKL)iozdQ`B z1yXW992r*{ha7E$G%Q7bMtJQe+*eDAu3D>~_BX=k!)l#-YLHAl2SRmkH(w18&W#G* z>i3tNd`lOhP8XYBA{xIyRVl=!KMp zq*9IX+CzhlGIH?UEo#JIe1!bh7>VINDc1<%{Tib+nk8FU^3l&rNr}jd3D!6|x&7EY zx^@tIUk+k5W|z)&rgv5#Gelw9Y}mKpakIPJ^)Amt=o?OjX!@o^OXC)^`|jTKsJCL zA#i$Khk3|Z10VBN) zQS*nL6WwB)qJ4YnY&EPmgot+N3$X$t6U6F-6htUXvx0o=AVo-h=wO)M$fq8}RZzzb zS9=t=kD^XYSa9yO@6S&b6WulJB;iVh3EN?U+S&$g>DkFG)Jd*t8~flj-Vk-CSI*rr zf6{KRaPeTVY^Sd+>B{c(O6+XrXJ~-V;UFcvSqXF(lnF9uscmDd=NN|~g!zZNepPvr ze7AsG+zkXYbxwxjUUwlG)cG%>#C?+CZei(&b@}Jd^5Jt@zA=P-45B}%^xsOm{qwW@ zEpO<5aytLdspp@bZjD;8^-cw+ZTh5>1c_8D9bwx^WoF|uvRdJ9nnn4qXi2TV^#laU z;{rJhN&soMCS|LDHnpZC`k|Cv+1F^Z;9G6=b zhJDQmfL*G@hPfwo5c$V80?IYpfUzpiH zpS*Sn^VHPhuyTIS{w7;HADx7l?o*-$XVIod16Rv1(J9(zO!g)HH6R~*H`bBWQK%i2 zl?YT?$4^yHi_LPT-`Eh=LA0nUN=hp;MS?|OZxOv0S+N$`J)?*CfrQdKE^LTFm2}i1 zBjqV@!w_}#Ev0_Q&%aj6tKkdD6EGK;7qBY9iy3~mac|D@4 zOUIjw7MCad;SQd+O!esUQP)0KvP_jSe<{<9&3#!Ej2H@O*V|oq;Wim^-25bcWQX9V;9TbnmX zVPrcNk;oTeD41Tyg9|w8jdcgt%h&}6NlqTl1aorEAE&eD;Zv7J&|P{BZgYtKc|Xu* zkqz8q@$-9k>hs%1&>9lW9ds2rHW6uHnIt*$+iK*w5Heln^0|Q@tVqQz>ZWw%uQpUn1KF7 zC%nmR`A$Wltx31?LlqobGN&In-9guY?VF??E<7v2FB%u6p+Fz*!#Mc5fWhlKeT`=$ z{0c^~2nnb@iAlB%NTWwkK#cn!T5?{?Hi5Z%L<=q{E1-a`;n+8@r5deLqBf26(?SfS z`L0()ILI!u-48*_rlLS3KmX8%eD_{E#`7HQnlW*$ulMF2`QQYyO9&e1U!@&TbC=*4 zBxT&8Ctvdy0!Mw~#oZDCHQnH|G9k`G#%nUQPMKMK&dz$(xuzkr&pc|GXKXe{UKa4@lk2bXpLcxa=cjuO0{-Yp^1O0l0JHvqy zLx7s@3$iamwktjL4*aN;6j3|phMhKs(V0G|IB+Kr;FYv^Dqm-Tqq=Vq9-KBm*_;r~Ij>E| z9nNpi2|y&eTE1f!YsPx>Ni~fw0LK;9pIN-sN&aL7kb1O`&<0#%5b?W1?G3P)@bg>c zSUFk1xKKLd+Y)wKAmS&||8igR;dU;62Qhs6YnkRh6Pdr@(*z*=AMan_^PlT9{}36~ z*d~uc^D=$v1$IiKCQsDa8Z{KA!=x2P{gBisKS97@Cm%Isx>6`XDnq3+43lY@8tgc8 zQv!V-#%~DJNHa3V$qeTb!*R!pEiB=t&W$XOtyaKEr^8hH3znbE;euT-yHHqi32M)1o|{XZ3(G~Ji7S=t5q#(b%El{UMIZ&!}K?-EdtnC z0WiOUS*%WXfeq4kp>@Xv}cEnGpJ7QYGwe~}Bf%3zd(TZ0BsE~!?jKzTJ) z^@R~Q^;V@c%OuBsy1`wT*G-Eu>bBx!L+U+-pUU>HQ(J*JlUsH~Kyg`U$=(`3Nno9l z?RpL@md?+7Rgc{#Cb-qaO+a?#aMmz=q(lQ#Zd+Oa`MX*{!p{&05#?M#3HXd{Dg3!@ zu`dYUvOtf@e&$>%Ff_FsnMtMCSVDT%^`6AloYZA31UcpKwZwUBxHl`w{{uhI@2@8xi(8@&K4o22A|Wutdg74`&UQHn91E8&zv(thte?qVBM`T zVA^`!swAs}N}wEYt2lBrjuEIjHb~)ep__?SPvv@{Hv8&^4Xqg-thnf56d~)uV#+61 zg{ZR}Y>sN_ngmbhr!j4UR!o~8IO!hWt?@okI zFN^HFj?)&Qt8?*~#L8}6Z{{4nDo;$2LTJt(P>V~cAe+J(^ai;;7t4dOcIZpOU(o2p zoT$^5q0nz!bi7=N5Q(~fSEJauRJLQ3_~gQoQPT?3qzpQ6)9t$Ct;!s`pud#w!)`=^ zvFg|Fz>2qo!?O`@XRTJe?4uAlfd0}En)qva-PmB_Yaxg~AOh`-maD$mb zRB6>k@P>h_TVYFiAn`zBnEQtzTnnlJ>tKwy8xe6g*4POXg{Yt!xY`iA?XK7ijslgb+9c9?suSTO4j2=tm2#cu&#)&9)MoXtz zL^mD;PjJmQip_Nuzktov{aR2-nnXg@8-8^qwiKgQ8>~|+f|-wa(%8}U3i%LAZ`31c zSf$1$T!~TMw#d82O>pa@R5{2e%XL0)x!Mh+vrRAr$j@&SmN@lK)Xi_jLHF97>@sgV zu4x;|3Bl?$An#^|u0Al~2o*OM_$$s?P~sZj0o!Pk9ZlY*+~63LAbc%JTX5u!o~2?! z(vTk@?@A}Uh-Y`D5|-M94P7U`9-$QZEp)zNy81E?ZXODG6#5MaoiTMg_g6m9HNLN& z|MWC);FNFFW!xj#L3%;OoO96%`Xzn4Za6ZlGsjnCKx^lmGa_fK+A6wYM8JM}1Ev`U zZKq=l#rbvuAsi%Uk~#BqIJa8~SR!v-9mK0HMR$YUsKT?^9+}%)^o_G*PqfEZE(g!r z1C_4n96C=!f-iiv6{>YV(0TJ|Rkg+6zKyrlypB;Q4%TNs&5E-q_B$0#u^1()lxO3_ zOz=tmq~k-0a_w&OJ{x#&smeUx2+m;pJ=eKy%zad(XAa?wb4E^vn?|Ck2pnqsO17hM zesbi0X}iiVDsL$)e+tQWw9cOXaqX9}Ve9+0ub2%*@5_Qbg zIP4lNI&~y}-RI|j!A#c<@uiPd+O2;#)Alc(`5R^ax4vhs44_OU^R&7JYE?Waf#v`B zo}7iD$p1X$)cDh-67Mv9xyAGH<$v-$dpgLirvG=OEjnk(A=usGV%2Gj48PbZakF1K zWEEcG)}8u!6VtEAgX*3Uu4@%SA||Vt>AU?J$9)+y${S`-JBD0#`Y23bcDn~Kp5|Wm zup~if>NMsdkgQBzI68wJLo*SyQ+118mcYEW!IQ3*3R|VBtF{g*3ElUz;d8>7e%3!} zLVlO64W_->2ImlqhveAY>@0Wh(bj#jb9f9P7)~4^#iwB%qCbwQiy}z)hid{-B0+u- z3jM?Rv{bl!lna+%(O^MIg315~MA{1Q{%yUv86f}0w_8X5Ib;4UPDl+P{U7gN<^M0n ze9QeCV>s1Vd4XNG8_2 z3<;CLnlDmvYpaJv!p@&Gp-hji%S?x@*69(j5Bb+L0>-z@1;z%VhuoYg-7)}_<=lu_ zS)-5BsK@lk%G(2S;tPZ=4U%V$$r|Tyx+<9EHBz+Wj+IIwmASrBl&v|ke-l)CxPSNw zX%K>xFb0HxPh$zH2|8-!?N^oThh_qcjkBtMV^hEfj)MZSW(IUfP$^A?IHOd#(P`$z zhSa>lTkRNSCK^0*&K7ITQnD9izLG#5iI=CrOq9?cgPZVFxRw{8%v7kdc$r4X1sV+< zo}{I@D(>rB2h%Yj^TehO$rZm1BCZqPUq5-OwgrhzrJKKbD?dri^;4Cj7Ca=KrKSme zX%+!HzoVVl(s{daP;$kCK-dx}4;R_kPzo+jQc5$8^Y?9rLI;61|ZL{hCE8SrQ%bqUv9$lp<)T?A(jXP5C zW=aYHSzrlhqpd`&nI2|M4&zEiN1 zfWd{F>orC4g((K+Q!;y7MN@AHVV(l4Mk3n6qUnva|4p6w1s(4b3stw~R@uSWoYb;< z6fqnp>N0hhp8rjdtk+_)<5CXykt7xjg-Bl5d4ZvD=M}#JizT(MGneI*Ph_VYk^lOy z8mL~Irf+1?Pbi4R`Y9xoQKYCE@wA}wjRNN1#1WN^+qUe*cz5D|*i!P@QHDEQ$B3xT~C^&uPX5_H-| z`nQFgOrFCZfoYZ!;bh{mOse^)v-Ry~+8?BY4VToW`Y77{Va%sl;(&Id+sa~&Hft3x zNV4u9a`b)s?pmdr8OtIJ`(_bS#Gm96Yg4~}$&)Q2Ya)!+{>~<{K~#II9FZ~rU`(-H zU$uxcib+4+YY!%H^N^SPuM^=gsS#H(@4m?`c)fZ;vLD*ttI#FHi;!rOPzSx1g5%QC zf9xaeth#J~90_`D6S6Kqjf$CQA{6Gp`y?VQ$PJsUO+SF*XbX)H43{azG6w@1U7V1! zA)Tb+cL^;?Tcy#I@w@zDZ^0L`l#66Lcr)(-#l`d>(FXZA91jf%9xq?#OuPBLfz!f> z4&{!uk3HQ5s6ipBI8d zVSGAXLDH^ak-?>yuiiCz84Y5REkV>sW@nOg5T2QUT_{WBQa9^xLn)7(pwm29h@3+> zRbr21<&&pzrRpuDjw+Kv#~I5e>hwcTM0PQ|2w&&kSGIBu^5tir?ZlIQr8H*XX~r3< zm+kFd4#E*MqOEb?3N3spr^<#JiQ_ovA+uf%^wzctdi+u9E~_mq%0Y0GaLsWq{W*t$ zp*ShZyP$4qq&{z2WmX_4vF>&)r~3j^C0)s|WqYl5YOvmkd-#72GW!4`1Mkf|5A~PB z`R_C4-@=0|00Q&z{#9iD&&kGLjOqKqn3Vd|+pvL*YhBRCE7ZS zu1-#wE<7s8XrOM1W}NYJLtnKhw=e*4C?iZhIH&0)xFWxm8ZOHaBya2hebMYotmN7XXZI+>ZWERuVRfcCDZ+IonL9?i4v zk`5?JEI@r{%rXc4tz_#wWs?VkNhUa8rpfI{C$Wths_P*Rn;s9O?!Ifkxln_s?Kyx#0b2!xN)(wxR6aXCC! zJs&9Q0s5kAbx5+qMq_d82=^MzlI&+l@fxo&&HWirqv?dwxt+9EN_^qGn-<-9?g3Kc z99i5tTwmBf-xmz06!cq6o-ZGH^;wfNa(&@QJHF_BQgGsH=sJPE53#X%D6s!8I{Yr& zh=(2?>6%qY7@8{LqMB^Qh`hD3m$l~nSmUSnl9ns@aCS7p0LXLcnp()FZ@?%A|EN(3 zO+gdoxe41t^NTflq}|vm=UDZi{5jlbo&2Q`D}vgk{cf0W{3X?|8dEFEa;*fXDG+Wz z$X_*OX=c9`FwJCbh(2MdX$|{Lu7IKs-A?ozBhH4T<~&u%hbka4iyFmSY`|U=QihVx zS_qhCCb61*(^e|nx*jL9e3fw1_@a_zlxq6MZM0IFQbQ>cIhOAA7G z5l*otZnmnub3J7BF%M_yMT4`v6R3o}*y%S$;azQ`Ij_?}bfOed%bQb`D5W`|M6hC# zkfx*vOH{LN$cp)KJ8r|7_>ws`=LcD0Ccmp3vVux%J-_>cwwtBgk!8g)jZ{Ja2vO}M zhX>YYwwo3_t0RTn>qEZYpNH7NWPAz`XxS2o%y)Nsi}lN)a)`)>≠vmp=uh@HkZE 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

Q>(AS7tunfyUqY*vPUqSC@&Qge*!m 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 z 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
ZFN!0+ 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
  • Fs7DvB`x09siJ8)O*G{3omvKz%jfbwpt_c;pk^(m##gd+Zn%!jaL&{N6w~F*+_q3#gAz+3Sb^wz%`$8`wFpt zuQLHnZb-b7#>u5hVt2xg*Q1Cu6%wF!H;#$4U=m@#5AErKC>$Lc*$P&g5Q<-+8|l1h z$RqEtHyJgVF01QJsC>RA^?Jzrt(>L#&8es)(v|a4UbqPh2*mN88s}S*= z$m6f2uD`u~x&dSO>H$1Y2r!0y|D7@Xr`opwjNte4KgY1l`xq|d-|Sg%4Pn)~I6MQ= ztru`0HYSX@g`6`gD`nA~rd#VtsG@2Y`PM{iN?Q=5JW~+E{1sKDfe;dOqh3;|)-R9Il!ynQ2fPfZvaqg0` z8pzpXxm)Y*5~wS-D#&1D)1tKkZfLlglndx&)Uhq0jFt6FjZ;Y&dK2Y3vF9-yHkngM zue68qjFU>?lE7refNFRNKP3)IS;?6&aZnup3aCCH&E?4Fv@`~P<*Xp#^&U zR!K|buoCc^<{!sm2nYLJqrYa8i%}xDPp-8H)ycA|mfeG!AJd%TFgK&dm{wN9s9*X! zn4#-WY@-1%AaL_n!CD%SrsWN|HqU;9^&Lx}4GvF5$Q%%mlQ5xdaOz364LocJ z|1f6}1$k8JB(KA8p=cn`Qx6h)D>gFdLj;I2^I4x}7$E@~R)l*(*jedUH1$b&8{ zXLcW_nZ3M@jRY=(+X~dJ&QIk2{9HW=5p3*Jj_TqxYX!r&s~Ci1^GU|+viM@Uqc6eI zfGBP~%h6qD(_IhVc|-whS4rCTEwr`QIl6vrnr(l|acLxq+MH@chs>-c_o`7Gml^dS zE=P4b)5+jnrIWx7pa}u%>Fv-}yk9OtY{nS~w8t;e)aLQ~9fCKHW0= zH*eQmab~TAX;W-Ihx{@0BY6Qjv*8eWYBD0`;Zs05Fr&&6CQs( z0Jo7Dg|3LEG_twnV9)xkK9XRHd&!I9+=tx9hJ)y7Jda&5TV_6CX?!U46K~B@f~_Lf z^afNbS-vN|)0R*sib7g3;AS)H&PD7IBB}%JXBeBlcN^cpXeUc3ULHBUgwJgh?A?5b z)^7>&WYup8dGcexHox+yI|#;6OO^LC+lDQX*?Jqpi1*9^dYiwItIAEQAy6PMI+FRo z3OY5!>bD(z)uLl2F=V)Fe?vJ93UCfq2MBFxH|XyxZBzMeb!Q`}beHKpQ2_`SFT)ms zLLp3kVqKCJii?pTSIpV2a+7VtaZDf2iL2RcUnK!656f^=mLi9a$)4{_Easd&ZI~5( zAgXnZD7E@4iA`#o4JlRlZMNQwOD0pFo!@jaO{($a=Q9v&(q!imO09+}8|$zgkKT4= zD1r-!<(jDpEJuQDM@QrLp*#pl+WkY^Z+r*9bXS9v(2tnz+%5GdJ>#RZy|;xRHbCd` zB&l-yuo7w&T$wpVPLE0K`DmOgGql&f60)Qkt-_TB1AEGHGFiY1`5>I&-W|^QwuQpML;h*k*UT6 zzJ6xRGSRc2P2f7+)vn(Onb4)938BUK3w)emTH|sObj3?k6$YNlvsMKI9pVuda%p`&;r>W=*Lrh-GoDw*_7zSEMC$wv9VIQXuJ2VZy!p`k<(wDnv7W=ZrzH0> zXb~`9pv!?n^(vCX&zIbWB>k3G4pS({ZA8Cc5FkDF2TA}J1j+yH1>x_)q5nW9+x%BaWW^4= zHev8o%r^)O1DOD&n%agUFGi-bjVnn;KaTe7>ncQspAqwzm6igt@fIHf5Hp+ZwTv(1 zkD+Q^qi^I@$t{{}I!L?btSY(Zq=l2c3B30uxL*-EiHD>2q=fJW6|;*LbNlP4->-sOKM zs+IecKulzVdjUIN^?!i=Go4&|a{fgB;D4h3-QuXfNB;#UyZG>1+WWlK4p(mFi+S_T ziw&*p&hz~r21}c{Zp8vVqtH?xdoYhgc(q253Kqiyks_#k6Zz3?YEG@8t6KX@bZJbJ zTnYU{sV&bN!Vy1+k_ekM`0w=at_1emr`KNEpiO@uP+i0Rvt{QPV&pFcF?G#_P%N$-P`9~vG7h>JniNcO_9WjR`A}C!fbPi zG{k?C(C!Pv)`qSo5Xja=MGXP$ZO~R)VH_VW9Fy~9{!sTY?FZ;c@m&iZ8+eL^z8&Ot zzcG^W0@}zH0d4+EjvLf&1?b&dq)_RIJO)H>1nXUXl9KCFsAzeO7D}3DmAJ8Kla`+xY97){*LW*Y#SZh zw%M_5+qP{d9XsiCY<0};*tXx@GxI;wGiRpGoO-{Ws^_WNU-$lS-E05uwbm6Wi!shV zd@Y+s*3mAAdciWd3=YkiGzVxdy_uNn^B8r|blv^t`&o3tD`Kr(OJsyQe9b(4fvE)k zMT!A0mIa^H{6Q3ZIKY9&UuhWTPjujrEuIJdBzyoC7#=oL}8_`wtq}BMpp@032KhQtk zxs^KYU(kP`_7l}>4%xWPil<${(Tw)@sK?3hpM*}<{fZ1jbEaV5%YUte%H149Pn16< z*lmAsqCs0d8NBteLcg79V=S3Za{qN}CDqBe%CJ|Zz1-GhY zX$Guh{=2wNWF#JVJhi9}H{f!0x&HqL`cIz-g!n7^_lFSrOD&V)@a8}Fp$vR5a+u|e(<$^#;!88~^;j3}5 zfHnC*T9s!~o#jW=w=||$g%Ea;%A5iI@@^;*CzmAeuP6#0jjFtf5KtGja4M0Qy({f9PKbfd1bJ0q7ro^b&ynn}uuR zxThWe3;qA{2cUnWz`vq@P{H5mpW!d)KXGQy9~glC@jH_0@)9o)WqLx$A3UXAsW~?8ZTS=QdB-+E9>(j?OJEjDC(-of8v)s1_uFzNG{y{g}veck8)W zb{NC`8?GFr$Jv#(*nLc;37F}+Wh@NnR-f6_IU^5J(2J_F$$9U{Y#N)%j0$auu#v)y z=NU;l%Mqc-uHt^_v3`kfqqqm_4u=bZ({qAsQ+Fga+h4e*@_xyQwfleaJS`pVGDx%- zj*Z@*EK=6ltvF?U1*Y>e?k7+)CewPC7Hz>zQ@3tAof81by%Y39Id5J&XMCX$9dcIV z5K93+24`;m)OW#A=yn%&aVAJCoi``QKi-bFE=hIU>OhgS9zuBF%XKL2R2`IL9Deb- ztFm-Bp8&CT!S*^z{7xA3lk}2;);DQL+Vd&s;Dl*ReSOkwy`wf(eJJDJaG8;qiKnp% z?dEJ60uFhIF_FMt=^@7$^l3Q&5Zae~KL9Ha$(8$>x5vYEDC=l8S0k_onBHo7wn6Wa-r0bu@SYkrpBf5a+qJ8x&58Zj9 z_#<~xV7^)R6J+cn@O}#h5j$rmZPgya6c!6MR33DctzU0(2(WY&z^FeoJPq{EoT`K+ zy6f8U*vg(qb0B|K=uRg-$l3kk$_%nQv5R|bnjHIMF{p%&LI}Pad#_iaA1%LoTeQN6 z(;4HQEWZ|&OwAd;guS=G(H#|V=r3b`S6@IaKhN$-x@lOiD(G$px-H--&kuu#RKPcH zlZRv=^+;2V=2vtR;%;t3pSF{;HQi)7E(&O>ku9olG$|50`GBPI>@Oi9B^!l?j(z8#w z2z@o&t{>8)Bht?p&GIj5J~X1ai_(>K_H)rA8phF|6ObL+X1Fz?R`G6sE^V$woM3b! zZalVJ-qiV5FLilbweYsR_Uri!$P+Z-LeSN=vVl_cDZhGAuoY!NRz5h!p+`#$0GV46 zTfd37Ag%ecR&E~SDg=9xGY}-BAMeP$xeCEt7c4Z>*Dr><9N06U*XLqx2IAS|qK0c1 zw%#pnRDfa++S|dq$!NA#!9uy#T=!@f<$$03H;;O9`r^U=3jO~>y7XTN+J8uwDkv03 zxq~7KjKJ)o(Bk4e(OV$-4SyCC8cQkKXm7q3q>3NL)qx~JUxS3Vf+VP|86J2@2SY1c zdyngg*F5zi--5U6#_5v~lv@*+T_{Jn+6^%P)a?IMO78j<9$+l1y<~x_pPBfmYT~^= ze`>V0;CXafP{1Ape{GC;8hL-Bk(UeGVJz*+dR+6z*7qjBG2;gwkNUq-@_)ojRRBlK z@AsdN8P$JQ^8aVz0hoB4V_oNC)UF2i8p-#++bc(^fXu{0hlZd!Y&FB(x(WLUa17Qo zTJ@aw#e&L?fOSi92nf%nE3fw(P|~*SIMBui8&=6YC)VYK5EXN9WP7ay^|SBnc$>n0S6#)hLg*lDQvh7N1W`hA(d?GSAUPYKHv0paL$c zi&M4pHPQljjd7|3kj^5i%wvd*eS*4u>NgSTsWa)D_hgSjEQ5weu((u55VcvQ%fKRM-v}ahsjQH)!G;ym&XJd=@ZJ zP~ZVJmuy}mQ_!~f*DYH7wL-c&IW5@G65=xKjsEN;H`^Y275oLY7k`n3xzcZ2$0x_> ztGAk8i}4&gW)KChsmr~O!#>eD{c1nq|2r({28>w2ouPgB|BZ>~kCdq?V7&f*|9Qmz zP08~Q4~%=}r2mS)bB&o>lpxFiiwrVaxW~>^LB@PEhmlye0IERwu?pNHP=jZuG1rj- z`&3uyy{szrhO8Q(#CnYATbzJa!a`WQPZDW}Z);Aa!4mnHAEzlEUtHDcc0Q5qwLjI( zyrb`U;|b?KP7IU`%7O$6bUce#6v}W)W|5X{Zqq}%UAJTsNiOwlVHdni;rd05i=$B0 zNX@+SSSyDv$3?Q+VA~$d>c@+gzGT7qWNBl|D0Ly2jusFSuL25jMNYhKrOh%|ACXJmI4SGh##M0QPDca+=waH_ z41%E+-sl`S2=k1`Y5_iqQ^{atU#enLT=sBjN;Aav)5x@e6c;?>=90GqYa5!`UFcO6&FdvI$`QM-1c!f>g ztWDlduRSYGw9k;d(k_Kg-86E1Emu7sg+#D*xqir?Nq&%D0L-EwQo^R^1n0uD20DOZqo>zjjV+ zIz+H$VZz=)`LTiyu+nOD-ZrBhSgc z3Fmeh66Y){k3;$FT^Ouii$DLw7CZDSR@Beps|Lxt%e{{1eObM6i@d9>q6Nj$?oW+y zlC%uC`%3k1gZ?2#w8DeHhxM0Wto_ z1D*TED^?uR1Lh9!ZUmcML0=MVz4;TspF*%GD7#$yuM6ci$|55XOde7s4S*F6>N0;> z;Xrn6h?f7H^gWH(9cMou#$%%f&SQ)ekmH}6L$QjeCnr@K*b=?a$FtnCW^X;Y@F564 z?|M5yyg$!cnkcNtC^4pPxRrkNa-v^qIh%b=HG&L)+@jj*PFkIv1a0uj!nUtwNiw~!vOP6X{7ZN83TtQ zq2}D83pQkWDXFh2Rvsto%d%^;E|-`2;iP^L4;Dmc;TzXt*+C%vN}^88KQxX1Zi(rc zvX*%Q1g?IY@&BE3$=c4yz*^79+`#eAO_xf5ul)P{rz6Hh+3znm$7d;e0_0>r z?6=G#*d%ZxhL8+p5(wsG&Cp1-`}Q|ezy@_TeKrp^A8zBSEJyz*A0^(9P4gR-3JOG zPyE66Flsj=i;^(|T!#%c8o?ERc_eP)?R(%RD}vPpx?KC(?GpYLBpZRX{=!X;RkfrjS8p4bIM;z$IfSzS<1f6eTwJYO9c`E7@V8|X-;~Lk)Nu~HA#$m*J(zkXqJbpc#&7;PLc;>ro!~VH=p086j15GtFC>*o{0~A&mqNi z*z_ZaQ^`6xvnsT&vx2a!SZ?myc6cl5p6$BL2(sTljyVl2v(xc*jmoD9(G60ou$++U zgHP}3qko!WyJS3%Zs3m*F&+i6)=TDQN+f^%WR{p3#Vo15j#ql#URUOQlaeie>Kug^ zxQvF;ZQBG1#*+<2(_cKj5RAZ#mIN~=5}4@z#;fZW#*h-+3?IFD4l{-7L2*SP%`;Y^ z&XjFd)%#UgUf;oSph*Nb2qdwM0lAU$&O?D|z|wcjf_|0^TFohfj>-BByj~16mC;ZV zUYl$<);ixCWRcWJw(r@j@YQo4O%T}YqzL#V-Dnt)v8;IPI*$cMr%w5d2r*{Y|AWYd zN?QjZ0DHW_lol0jk@;BtdUlFCA|sop0f{L0yHuZGs=JVIfajE?jKk_deB)~OSP{vz z-uo}-Tz9x8#I3lQRU;4LX$yjV1BuS1T1~z*E_eD?0}xgwQM^T(V_}50G=on6=Z@L? zbjUo=)nU?lLZmhOPAc9n4$Ojhrcp2r0#BGqc`ox|37&^r1!>(ai1d?L0@Cr;7T`-b z*mijCW^`}zF9&-huzO`=-(&19lR8Q<)cLtWex*&5CsFYEsG#nk`*yF3ZDKRgK&CYy zA8rNe;^^y@HrOQ8W_z!3xdJPcAasmxnrU;MZon=(JMfz^vt_-639pk2hBcK&itd=< z`r4D)a-?pa`eA2(4zABva-0*j_vK%6&t#a|94?Nc^T~3+1C>S723F`@rg)P%hWR$P zVH&-kdU138XG6?y@%}~KFb4}D-p&8>x%xLpjtO9<{(k>?uB!ZXu6EOOH`Xjwsr+TG z;`m9p{@VYZy7vqU8A_&_Ceuo$3$45ZVgVaCXx;hlUlnAGmbGmCI!hn3h1gmz3-8ya zKxqJvGQ2GW^|=&JXuq@(^>1_4pmQBCSGz9`0BeK+)<{j8QLkuh|8XWD6<=&ZAb*?7 zUhfhNIt!1W!0O7QH1Guz@U~vc3mX(?m+)pi6WMsx4$Ch;^Q#*!D%3+Weq50Ru6}pF z*FW;KnbWt9&l(Ywp2>$4fYw$eh}V{Q0@uXP>$P%AeApumJf<1((|7)v@-gjLMxg|iM+#ISu}aM zIQsZ!%#6ccyLCHLQcmF*f!J*{O4(B6K(w z9inmMGD2-wEv4a_e>k2X+}I&(ONMGlppcMW4TwhDXZHA;8c-GuuR2WN2+76*1yOJ; zu%4qkmb(8i?7}HCZR8%N9a>w->0#_-c1VxAQV-2^8PjOD!#F3o+F8eF$#nkyNl>d))C5)z35mnD1 z#}UhY{2kvIIirM=sB>(Y>5leN6tlSWU`A2YMXb_8cH6{JTf$W&9(}zI61P#|aEMEQ ze-^5N2_~r`GS}#*>Cxy$2kOz2^Q#UlUn`|$12bneGy8}U&hVd_+XiCwxmzgO5D0Ai zp@XAHHDFcRAbr1kNNUw|u-)t*$vJYv)aHTPIs1oWQpEMviBe9A4{=d+veBp@SA z4P=$}!K(eJ`z{RGpso+AV!$SpTR_=CONZ#xo0!Qp%C}VR6!H%#G`N~fmz9zP3x=9X zGo(a=b)pT0`7+5M9r#INXu~3g>k{qb$?)eC@->{1H05qSIjT8*;$(imeS)1j2p1Q) z0s012V=;-$DR)B%DV$m4ySMsnzR#x}5u^Ny)uDoQ`UCDFx=R&Cz&^4h zE$jea^8yE(mN&Otjxp?YgTU-3t*n-X`-0|~e%V@&GXgCgroeu|YkSnkO!f+{WByAHuq5(YIAq+d?<|XTApNId7-Y;N!_Pti;1LW_}Dr{4)02pmx0Y)2= ze^Z|F4|?_wAO62kvpRA0zkT?jZn@h-LYT$|LI+5{HKQ-iC4-TM zJ1;(ZtdI#ZA#4mB#lV4d(f%YoHJn4iEwxTLXEW7V9IA}*5L-NPEU@};b&rshFQ z>-vSSm*?~)qdJLN5*)`6X^lXHh}QRO*B|KUx2kW4kJi8co2vhJRrG)V75>QA{=4Q! zWjmQ9am=3gf+c>tTDy{d*QRFh6-I;lU;6^9dp1$krlhIu#@5XBCSn_q8n94w<1Oz& zeTNO|Ly&y5r7^}QC}z~;I0Rp4ll7G&h%BQW#(zi|Fe_Idj-(#0>qIblJ6&Alb{;&u zp0^*I(=P7XdBXTJZ~{qyaD4{{vhL--RnKKCdwKzL*6F9D5K&EmQq_8w=#;Ndv%*Tz zAV1_1?N(@)|FYDyL2i1N(rEWWnexqwTV`$d?8-blgGOJnP9EAH^C1!HSC+*)V_CTT zWh>p$B}RC!@;9N6sF!JAM1O;g=Vuo*wuJLbppTQt2&B+Kg=kf4izi}YXxXM28M4Fu zGI-$3N+h`x5D4(J%BbmaAJZq3H*W7VS*_mIO4FPrurCVO56^wP*6wb&_szY0@{g!X zKRYxHNVngnmRObt@jae)qNhwdF*F@ViF=?sRx4 zP~W4`4e;1B&S%ED=Orw$4S)Si8W6L5P`q529BU7SKG^9k@`UBeVQiaf?z#eCqTQ291ECJ{fwg~v9%6)R@!drs>ZAGG_ZT%WbnZ_@N$7i{#QB0b%Wb$A+>(C zh3a(k;y~^2{F8<3Q0&Q%7yP!6s&3S**H-pB|dH%8oYE8Z+VQ zlEto}fkSpm++o#sH;bX-UzBsraHVHGYVYF=&cx>qW)kIE48`4G60_y*y#yPCiaK3M zv2Gg-+_D%FETc6}PBtb7NnjI?K|}ezcLoLDFLxp2-TzK0ef{vAh zeEkyS7FSeaj^8PIR@0lI>_ilK0z`ln547Osj+i>DrUM7B4^EC;w{}#?(4S$sE z0FozXIdN5ZWA>$7-za#A!-Q??M}6=0=S>_~QsW#WYvjSbvyd3?cczh4%=rj2%#|~c zzLbHaDDWmJCJ|{CPxCZ`mw*E5Rd0KvAP8qWU^I<}goSFLX@29`ZrXyuyiIA&b2n(8 z~7L$AF&*25d5+qsdB{ii`)4{Ck z9WFH+5#oqV`K%(XEkRMTEmdKMB|DtSIDBXHxwnu??4Xm9YCyRu+wr3u zErEX-{e%p9t{|xB{)(`m;rhl~>-T31!|%?=6*h|#%)cr6|7@oIP0;_F1x7k5Hh^WH zfQ@Vn-Dxe^n^Fs|EgKn97HNug8&5HFh)pt%HklDIB0h0!F!I* zw489%GW$XFf)x*J9|%lHa5WBN<(MJtGqBPZPSC64r!j9^&W)w=Oyc5Pg5``PxhP!) zQ=vFCZdp>Pjdx`Om17gz zePz0{4UrABd05spbc8;3V5;dAU)Iz8l`X1{LS&nrdj*YnZM_(h(|jcHjHn@qh<8M= z{|+YVqzLfPoRp|x;`#{cYUXwJZGkL0>Ls8wD#7jRPeiufXgqN@4T_X&w9${U{3h#5N8OLnIv zoty2xNEbF5^uLxnC^7nK>8H!%Ad!RbTI(jK4`IV4!6&QiBw9QBV0;kH&?jyT8ZZ6y zsWHq4Euf!K!#%`<@n%7~R4`WOWlyY&=AcozkDus8ij`e_p>N9$gmrMw2_3JwlO31>56xT($;tK%|5kHW z-7wUeSjjrb8ksB(`5O_2qnRf%K%vF z7q3A9ZC(Otjlikv^xDVN+CmX_0ybJUg+MkSv$%sm>9QBQO zc32fz*P0>$ZJl>07eerhAp_}CkC5tT|9PEu5N7(v_z-C-PU2#$w%tHFTT$8~o;1ZT zyUA(hgPd|6{!6dM5!^IlDCLiI%1l;ZF2Z#MxiXw?dN-QKj?-4Ai%?4q?rWL}G8!c2 zZYV+LOW5DUW3Dv=na0C6LbWKKTj0hvbBCy^aIJJ~Rp!z)s}2~{y1)0Lv-DS7m=GS5 zW_D!-jJFB33G`FYvtAQ4iWVFPS-~1_6LacW}gcF`R*ft#=u&kj{v zo<;KdScAO0-hLA^G@X9SJMh04me_rykY01XQktAdn#?ecVk4`b95t_$n(Zxla6ibDzH_4UE;bf z^EYMwAr+6PbY;^^;k%(5>ynT7mfGuIn&I1tNKi> z|MR)?N5b~sYy$m%=gwPxYg5{sc8%6;i`5gOan;t>V+f^|mR2T>nR!kfvkA44?FJ59 zaFJf)&bRM{Y~v~Q!36K-De2fTRM_k-ZOcDmU7{&{2hu~3$CeC3R~e19nRcey#jw`b zUvdw!A2#AqGLlED`$%+hjZtmd2j@5!}lt7s`2ObfuVY>Xp z%P_dHNeh8O=ZMb?0RK-D;0x`caa_fEXtxmY8E_)*laZ@CL?-#IsjJ#hnI#sc{=~4m z&_Qvt;gU|y8j~yYOEFnoR1Kgq$){K2HgXweXKvuQI7QWEmGlXyWMyO=?_=gT7}i@s zwW1Ni^xHFAzY>PXI4-skmVs2x;ATIOXTpO)kTkq}nw{Ee4G0VC2lEZ-U1Z#HKs|%X zKX0J2EhLj^(u!~e6EkL(?gl)t(k19{%P)albP?eSlj_j|@kO9tr-@euVdl_l@)s$K4}e9I&|tUecib1qP}rh68&3l9Mvx=c6J_h0nK(bP=Hc+cM&Vbw;Wx~c1Q)?atFqL3fD3o zp_bOnuQ@xNn$!X-*-2%hXYkCPjsp=c3%3OV0s(Avc4R7M4R^G`Y z+EN5f>E$&`*E45=FJ+@CaUsFwu^MP9*H3Y(m&a^w?T$C}Ph_dI@Q-w5i6uGKD~#Ij zwQY`4hDUNr6|Tz9ZAVE1CLA^jyv}_q)l5bTZ@H>`#lJu)RPb$fg77ggq}76#8`67r zV|&(%b0TM$T^!?x%u_94zqt7vTtjqs=xuZmW%;rQ{fyd$U%p);@n}Wq*oyvId5TAN#Q;6eZ>Kb*ci@!5gM@#t-ktNM$KWivP*<&N+X4v^X@E? zLwhq%1iBh0Rl`$JbW=)YiLrC9vZs*kq564|c&k$XqJHnFxCEodzG1Dqb<@Y>^}!*&#h#C?o8wuFtn^6NDH{!O}~to9Z#i=pbqv``baxjhr?fqkfbX5ft+ zTAv@&;8taK6gbo6EY!qxTYS3%7IxmjR*{2D6yHy6%X!;mCueHmi@9*>*$*gEVb@r5 zZW)#b_YtgoPycz&wuGh=NR*BfWKV)5k{SD}6pI!n(h3o5eCM(w#WhQJ$EP6pc&r+a zmlr$8VQ&vFz@6&FVlv6y+SeYbs42V^{?6W%^iBsbj(OMN&&b_B0DU1@^tSIqI}peB zW~FD}Z%fJnWTZN*7eA1u+`N2sC}c~{bo zW~i3Me2G9Z`GajAT*@P;R$qDCCch1>nsARhGZ1(3ENRigDAn!^^HqfaKY{s;I#wwm-?c47 zF)JQ>lKzzRi6DVrPj9*e4Q0yT=!B8g(~~=5S8%AEZD?%*g$&ruAla)6?GE0Foc{D6Lp;|!WE*`6CEEKsjY-u8zi`2u8G7yl&kQw0E?msH;8$g zl7VZ98{n}hnMVofW*CvCS)!li@ZW2$m8hqpf^n*ojbLZecnYa$9ml0zv~DtBYN?P# zECSMP2zN~%XfnxCvXTfn01_dI0l!jE?`Y3Vs>Jd-IC4TK6rmJK?Op=D>}6iX!x(IX z0;;3t8{I9Pseip%zu3V$r*B?`JH;;#zR^kCTyymZxq4SI@N&5oy*99GatMbm_^1 zGFqH6x~iB5YkLEfDG_}FXbfz90=gH(5mQfMsX|SOrYDcJMH% zd;~tsAW3wJ21Y7@n9FNN)GZ{UY^eYm+fjSlB{o-Gy2Fm zi3@~nf)>l0;+?sIi$Gdx;nuFKL)GXoGZ8#w#~MpHLs{;Z^;Y0xTlKTYtLtCEG>yNG zR0Gw_r90nd#g}6D&(>8vUxNDO+jXcI#8V13o(AtMO|MpqJg)DQF`y^?{I(i$F#S$8YuyA+(-aO5d)wiCJ+D^Dnu@2tpLyV#3DT|dWBl~- zb^?BHc0aVChuog3H|zNl`+Y9nU~XZyk2sbx?seJw$5WjCkODm~Upu`z&OW-doTQJa zcG#VZt8ap^t)PtW?D-h3pr)`G#t{wE>3SeL*V(J^SW<*$LHGPw<^bJ**WT)?4#I=hCHCF2!yOFTdvptnh%8)h9t5XcA1>zWGZ&a@x9e!ZuFL-;{c+2fIR(?(2{M2C`=}1(S=XdYpM0 zCDaOvpbv_e2jlR4lk(K)7ZBUN=r~R{;Gw}OQHvgU3GQn6>>5G@T|LZ4HkeWz9V}c& zx_L%2CSNyK;Or#QxF$COCLM*}5B-Yx`3zIk{6s^^DdmR~=<+0zAX9Oc<*G-?_%nE8EXev%0AdR~Ovqv(kK;#4`)@UUyRT_*0o`>V=_zi6fj588l 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

    FuJ#z5(wc{ao3{(J-ICme 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

    NI#nGZTyU?aq!aL2L1;>=OXm^nwpf4p*4cyR1 zU$eFnt)6{2L~#9?IMG{s?UpxJ=bi zcJ<&bJhDwgfOSUsC4b$?+P8Lsk*2qG;JXk;PPNoPVC8;_Y^uAs)T|IBBT?0}TWFrB z1OaU=vfuh9Z`=m?ud9SEV5ODWr=a?;RtbL!8JhyD?ECv`rB(O++bSWiwQ0Xw)2QaB zw;r79F4CV@36ZZsPvH_=f2h& zIY~bcPHpOzj@qB|9d3C0AKp*%-1j`;`#ff68`vnr2tzo z_gM{fp^E0C#>sx}1@uP-)e)6uGD!}NjFb+A3dz!P1qxi7k=9_2CCOZvgXA>=vIvwX zaTJv=3cMg{(v?sF*@b)isPsqzB4;U0e5!y@`PS4&s3WC7_yDoc(hG+wl~g>z(=^TH z>}V1vvQ+d+jiwQ(#d63u2Y#leLlc&(+(npn9;_4xHvJW z6O+OnW!^UgAS+D_^AWXf9R&Dma3B79Lh~@KmXWbkhyDA~;rF5ao+vl`zQl{SG5~4{ zs7W1t!qY(dL;J=qWjE=;O*=F8#Jt>nK8SuibW7Yo9fh{>b@IS9*w022QGU~$Po+gJ z`Wu&xrTD@TRqVHCEq(#IZC}A)yW$>66q;M~@TvW8t6_NjeL@sf!+gK|{1i<(weUIa z#w1Si*Rg@F>ju4Do+-kj$2Qd@c`0za$%Lg(xO;<@5IxJI=$|K-%QcTC^Jqw*QnnWT zm~qqjMJf1|cjc*Un+$eS`uKxG4l+J!%ScE(>Ydw~RO3`(m&5`~_I~IHU#QTykJ2R0 zs5j$|y^0=ld~4(}L;`&WG{@W-=Cdre?C7$4hxr3SA?v!dWTu1>vkA&emF~RA))*RG z)k5d-m$aVm1dLgm%-GGOS88s0K-SxIP1XTdiRXk#m}@FmX@jc!b4N~_J+Dum zkl>)$6+y2bOkL}sAmTP^Z_o63l1#5q%vB4l7}T2F)IWh`ZhlG`)LOFcK^kr6cOp|b zRS=-#kh4$e$cg$;aV?PAmZeE7+#m3nt>#dWPlP_A5YWl48%Z97W^N2(DR zE51#h^g{jHD&Z1uS}JROLdnJ=735Iviq&DvteR?0-va8ovcoS`8>(;$yx~A)nsZ1O z@bg$?b=d0k3f;txNy*9`J#EKx^nI1U^u9`n1PB0E3Dl@aj(=VywD$A@R|y-rl##$y zf{6Yfs{}v7!OwrJ5)^=|1pPdBb(ud_35eVSKy2Fj;nF1dm6A9iWhOh~i&kiRdXam* z83p$AX6mjTI4j=HuL3xQn5KaRLhqN0)SSc&t~c(H=C{wo^fCg|5n@MSz2^qkcjgwa zL9bM1BYwPGPUY|}Bt!x|Q2Y3gq@aE7SB4q*i?qgH$H!vBEs9HY?ql^TGNYw%Yldk# z#)DX+MS4Fl8#&+^^xDa55WU5?a#H9hMo_|9<)u zBMU9>zmoTV$_i@&KREC2uOFTN

    Tqi*?z|dkV2yLWN?m)5#+GBA3~OrA=A-H+3%s zCAI_E2tSfoLidMLh?Ep&O|jp~vH3l-hE>`uxaGTbzXi++-@o{6cUoA?b0NTjC_;nu zLEZ>MgOrIQ!E5F;?E@508-{&kk=1R><7>V}^x7jOc!%75{D)I03Fs7RSDD7CC=r6E zS;p(iGE%It&XtzevXGTVWw!!}FGPs~ua7~W_`px-AGwxg<=zIsBb{=)GGOZd}VzQA6L=a?QUq?pgeo})k5RX6`?Zh(M2 zwm77h@6Zs!6KdTyY|vZ%-((Xza^|K(n@8Xm&q!VA3v*1uqi4WtC2+TUh) z{Nv7&L(7gxm+~>SjH78XW7fr(ze}xuE7Sr57)bL6U#P9Pe#AK|CSMZy7pD-^A5Njo zcc+jy5;V{$)NSbe>b3PhP9dVrh6`}1qp0n#=K{CaAsKWSc?b`A$bGy{l$6XHj!h%m zs&KTtB@3B<91+5UoMG=}0IllQa9TaGvdv5# zp#>rl#(Q5ZPzO1HJ8GnVR@#1GrL}JaNqxtq{jZ%ue@X{i1FP)&`)j5Bhf@grZ}Prs z6e#bPZo!A8GJsAYt0&-yn!AE1be&bF^&N_wD#Wl^!obkOn^8HAnV3+lo>~WZMz3$WP_nQ{GiCpZTL3%Jjh)*nM0aTuKx5b1uh)NJ{q4d@)iq+ z`999JrweBm4%z>Zvgf%_>F#(<7FiLFz%7%18v)K-Tm?i7fJ6iC487-FEy$QZB~XY6v2Ge%Sg*kOY* z;L8tkz@R*tr05&nW*(ym9}6ssO#M!jSAs`J7P82U7Notd>024baNZg+4tNGVbbdx} zH6e2~kJv9y412lM%}jac_>_LQ!}+Zk>5g>0H9`?+_4C_h=FCYn70<5bg~OGB%xvq& zN%?S|vV4cbqaYe{)_&k^2Cpj;xo3Hl`}Hx1)MSF|`Z_okz(Y^0M>Lzc#6j5$OI@ zj-mF+UeqjG8gF=zLp#9=9fQYI($lQH8f!qo&ddVCxiSDw!ZU?Uu~ebZvUWkN{kFzH zyd>XoA+OA8zhya3ueAOP7XO zibsrGz!GjiP-sms&IcvFm+Xpoj=Hs+^5bOjhwd~6ngPf21FLC%YF08tq>forX$Kb} z&l~-dG1#F}hZiSmj*gqbc0#N+ONaK22c48hnQs;x8T*-q7~j7!?VI(5_^ACRMAx0e zf&uAC3X=uo)v)i>q&o#~s9#y{XJO{E;~{W-ic=e<2$R4L@`EuPpHEzE@K#kLdWmV~ zqHM82r>bn`YsO0C9D)hm`e8X{S^0FkxSI)hJ!gLHolMX4&ocb3?~^nn z82&4L|1W{yeJ#eOk zEm%wh{OD}Kxz&u@xz`SyB86kI!!@(pcpD|HFi51qx0+&#>v59UiNssCtZxle>rPcz zN&C~w*|-=@9L#2n#xb-svBi+Z;tWHRl#Gs;A4stU(?>mVm+GRo@f`A8@Bk5=PhanS zR@(RMB*FWvU_g#R5F$Z9%<7C^t1WD`wUfS7apa_Y;7IwrPZ@MN$obWlz9CnAJ;=1W zMX}sQb%|5$R6`=YI-|SG9BsF{uVH+?CI5H)trwx}7fJ#U+LekyVRJIGA=Kc~*T8LO znKYp|`0|>}XS|jRa2k+OOAzVN+RXy`lJzGuyq0Vv(R4UU(lu5o>MBG?0`g7_m$6T_ z*rO1|IS2_2aQuajK5~P<*(5MXnAAWF2bGDK+@t_lp>d4ZG$A61k3R|o-hehN9>{e59Jcu%BSUN;+nJxi7#!SV8% z$so;%DEWw7a&I1LW? zGOKH7i+Oe=!X|_kE+j%(-x#J@063K&Q|;H{2!pF*DHPHRz|s$Ut^+ukDMgVjOCF~5 zk&r3%o9g6OP2Dlc&pcm*>QF!ZAIjb`D6ci!+J@jBB)DsE5AG1$-GjSJg1fs*aCf)x zAPMg7?k>SCkZ-YfzukNHce+lWDsF21qaG;cJ=dILT;sayC8krP_mRSE2!5|*=GTH= zitJZHEX}>bo5|~2L^C+4QB^Q#x1cqr#rtOyZ?9O#7^M@|aG0$vNxkc%G1b+w%B%%# zJ{-UU z5%%+FA|dzKJ(68vNv&EpQm28hOq^D<*~f9!{vzEOl{{k>q0!=Nj$e-!>FL>pMHbI8 z;jOD>Z98jD?DJH&ExopSCs7f4shGrHDo7EtaN3m#xJM3(DS}HOlbkK=Kn)31@#LMg zev<$$TAFiY2LiJ*MfulWkI(off~03yB_v~`0A!Caa<=qVW~|`W=lFYJxeICqeIr%< zT@`h67k^bN z#iRL)1PLx&jEdiiA~|;y?I}FkG&!5Wo*`x(re~F$TQ1X$*N)=L9D0Y z%1c|P-D974D9@&oXW5W?*neaaRI?|Ta|tRzz|X(PLa{=rdHwziY3+4l|ABl45)EkS zKm8wy>pvtvMnE_Jdj7qmf0bdX;`^L7wpX2=*=n=$xK@6){`4FBqA6GN5VyKrR$Qqz zKmbyunlD>ut#v{_uybjKYP1fiZcN4KGLi)o{}iy*O?{U zh@${6(%C9!q(fcQvcZKscAI(j#@WvYTh_X^#pWdj0XJXtv}@0GF7XA_0^>h{;J^q@ zZkTf%mC9J4x)OeW-#={N&=G|;T@rpqdb$IH{w@ja3qN4DR6=ibo2{T~!;9|6L?qc8 zm2_qL zgM7Xmbw`jC^RV0K`Vb_y^_EyfuZ=3~?vj(G%F0&xi-hQ@LI!7gk0LEFt-tWaLJ@*M z=HgB50pajMB5~?e*ED#$SUevcxtFR!SMrlqSKaCEDuTs$Wygl66kz{B1PzyXKqb74 z_v4&GbO%D`5Ay*cs1*=8uMm2REp7Rt^ab1(#*I8QSVw!?R_w6qOTNgyt{_4so6Dzh zxI|at4+??-V-xXAGb%0HK$Z++RB7NHtt>q4UL&TAHK^JdgF*Bar34Y({HIjmErst12?u9@|E{N~(@ z8D4!W>-e4Kj%ue}k*lEBTZ6i-a1 zJ_nYAW;Q5E(NGmGoKMzr_M%K45WYft*mor^TX+|P#IxX)D|ShDl)Kw`_-vVbG+*(e zK)A)wYwnKQ^>lm*dF96`IF4)O+0y8=goY1>oA1{~g`jv7V`sUS?VD~|joYag(U=NO zzO!DlS!Io+=5AXrTz(AB`l;F1oh(Enf&&$&>fJ=ayj@tVysJ#@PGUre^3@F6-5@&4 zV5A=BF1-6k_&eFO#v8V_lD-~uViy9t1Ly0B4y_#tF~QsIk(|y zLl-4AYh&^;Ud{Vk4jo`DO8gA;a&vWa%*3%=}(( zi=SF^KqCjr8D}iTAK1NNrr$3brFxN1r(-tl7A{#dRL`;g#INrTLOQ_}hU<Nt`X44Zqp4KN&RE3^lLbp~BXL;x z%p>6JZ)zw>Wuw*!79Z80zJ}v5{&Ma;>~Jj=bGR_z&)QJ$6zDkIC9vTTseZZN?_a^{ zU*ozbc|`G=823NQ8G`#Q0j9urrdTeRNx4;xdye>2j>KN1{-w~C1=ltsN(HAO0DCLP zF6x5d+x~5&A<`sKOVgeTkM@P6?DN=TxrKUfY}(r7VqAGOj(MJ~&YAV+CX&;S3S}_W zRv+X7*vC8n-o0-Wnkq&C0-je95BdKh^#8M+{fo~3e;UrqwIg>Czg>I6SYP;n=z3_V z;|b1zH62R>LqbY!@66l*!ic&_mhSMOKL2AfPXkQmmzrazTI@3kD)tRTv$sxpL4e3# zg#rID$A$EzpSD73irGq5(KE2VzE5D_suXvEeH?mMEn4~pJop}uq|&lhq`5kr!XcC` zlHQw^VU{KA2F_ZyeD`l2-q*?e{C&{SZ=iGM1TL5VO{)Za)W0}*|MOg4=GDRbETq3V zwE7MZP*qu>et7ZylA~SHP<5&bt=XLTP2iJ&p%9xf93;H3Hv0Tjm#R(jSCT+%qoqT% zCc2_l(brut%hcN~Y!-1uW*dy6u<1UMR|l_N6lurb9lU*1wzw)_8L?o3h(~@HU<&?( z*b6U>?DTdj6YPBn@v&uXg5Sib1Sa>2@1$&~;Iu=lCTD0Gqr}*6>w-xqYrKxgIxQo9 z=t56Rxh#KiUSY`;iO*3)5JbfdgN@a;aLa|d`(0L)|h1H9s?gOp;g@cK`H zr_nCf!eO4fXvLwcAxqycag=;8Jz-HE8KWicz1h~Q%^R?TrcXk@h8D}eQap%k!K1u< zf{-$%IB2IAY1#X(FG>4z?XXWpdj^?V>3+{++VSN}n3|HGZrcH!jxgEyKspS{2k~I7 zu|&J)qN%y_;%PvVfmm90`%JusBE-b4sA*$7xXs8SvL3Y+)Hb0?o1D4-ztjFcm_SV zNXv^~hEU5%lbqsvE;?)v&`s<(c(CqQ(OIs(C}|BbKsh5YNTR!Nh*UY=CM$O~WqfS^ zWN;@j5oo+!N|2j#=xo`K-%0fYFMB}-!PAD9!X=1ND>TA{ia`x+JA^i;S=$~I_$+l$ z`R;aF_%3zBTW3RBL_X+KDs^S6Y58M*<&YC!--=uvEBI}R-?vPYXv)PwY@TV$%3MOn z9g6g}{eon!@Ow+&fOZKInlE4TN$oO{(z-ufX-tF)mtD(1FFerI2jVB3WS;CTlGmdd zoi)(R(pWX>XluC{{RC|tf_Ze`v<=i6>g;G-c*bXr)^)Qve2d{^odAcy&FP2mdS_1z z&qaSC@`LQ|YXCv@X#awYZ)RM{QGM@CW$(OSS$A124%`>=j%wy4wy#)vkXMgsn62+siJas>s)~nV`!y+TESD5! z18i?%tX96fqHP%$dOd1}Fn}(Awr%(-aqOPR!T^UG0j_4kKXsqp`jQ!Ez{NhQpM zWARYYSD89>qY;uSV)^d0uhVT@q^x97gw7GD<|@uS!l0K`4?&jSXW1#0(fSNCQd{y< zTN+!FcH%<<_Y)oW4?l{LsC-&^y>#KU;$kq@y)KP43^nSS#nz@I;FpTgma3Y%3@m8C zvMi$az$TldZ$SC^r3PiX4l>FuWM_ztA_mz-1+5O8W$>p*zgoijO2H)A2Y{bOgBY<< zc>5P6=<77TRW+Ih7iirz{`>0skIwx+&f;zU7>hjT6gQ-J*g@$|dVnw|u3`ERj)a3+ zo3OAcGp%k=&d8d$qcroVp>ivMQ21T7`Ba`Aai7$}Oge)I<`#M>%#@n|XC#tn=B-eY zqNpx5hb2z(S5c$0qA|xl|32S7@43_Z9ba+r2Y#1+K`?uvH@@x)ucS_wgP`2U@k+M` zLa0@1++@+v(RV{ynZN2qgjz)`@zj<{ot#Jv+xH27jM`IvTv?}#G;PF*zQ|}JO7P_ueTruP0 z`B6`o16RnNBOb$QZZV(Ph1{_C^Gtx=w}^PehbQ(rAe$d6xIjy=M(Eq2sCSYW$_9gIEaTvM=DHcpUI!Z8;%c zkbr<%6Vc5mnO*4B*iHWI==ie2UD*@r_3J=JM}%*DKxZnS!Em5*x$Z)G?2j7Dbq~j5 zGD}aM_OOMAQ+`I-^){jTNDkxz1(6`lBJz<`*GT--^2qB4Z5KG%iH~a^*&j7FM)7BV zP=F#yPT=!ua+vioq#bF-MGZTlLtjimCmGhw3>nNrO##DEsesgxNgNHA#LYK;6vWWF z%++Wv@A<$H-sI%DS_G2S4C$=`LW}{Es?~PpeN)G?h<8q)k6ktruDl?6G+R*W>WA)g zxr?IxrY5cq6JA;uF;+~{>9@mdW&Luvx$9(Kbi0HouA5Q`Z5>Y^xIhgzsabL4 ztiJlDhuJD>RAGAY5?dhx>e4oxm-(e`0KZZH$Wos~F^I@vr`!L{A7})(u0mYKQpO|| zb-E)vi&=^YcOQi-ZCaXb(Iyk#HVdt}58>hXEctCk54s#(mA6B*>5HmeQ7mIuMV?JI z7^jY|1vQh;`4u+gE4T@bavG!4ZIXy~xN)ahKwQ1U(n->Gx=7*dmn_GbydYjb0Eirb z_7K{a@L75X9iQZzM8YsK{GyM;SLIBiD$0Sl7_)(RpvEdG02|LZPo3`#o)4beJk}tV z0U6A+e0DUaL_45~Zz8^an%KK}3jmSPC1D0n17%Yr>p2oe6sz)NfD(Jv#zpx@i6tsi ztp2$`#`AKL=b8m&o@_G>Z%Zi?MOa3Jd?1L;4%1iMh{>!X zUxpg(w}E9O4$NJ z!D`nWe?Fu0ak{%|_!E$11V-8kvVF71!>>po)D6G8+Ax)KH`_G#-fLgpUp zv!5Z_+&J0EKG{`4GM_Drt+tQd-cW z_pcX~R|1bdX?Q%%e}BLH#i08i`8)s26Q0-m29g>Ttky;7n)t+vnoO!v-QG2%l#r(h zta=f+i=^2K-}|%zN>2L`mtmv_!BowI3Owx(%4SU$KTPON3P^ekD8_Kimfp*ty{>v; zR&VvN#M;`P`NsLq&mV5wviEH&bxwi-FPJ18*q0b^32-p04VW7&A8SccB>1vCcR@6j zl!01dzDuD9d2Omj~pZVG%?_WTW}B& zme`}wNqDgx6mAVCqFYkm20${=PRo;+2?~B1|J0Wj1-tv%7XH%@TIc&aKHDuw(V0Zz6L}p;eqsF%U40Zo-ah1f8RDwuYd1 zK2ChVItoJe^rGwyA|w#v(U?KV#OeKYwE8d$8ZIwPM%p?`Fy)k)tS5%VVoFoBmUsQe^1nn_!YltZY7fuWDHJVz;c z*46Up(b4n<(Ve->)~=dUdV{rWtel+dGh;@%a7MYegl>rgEQ!gXbOLNKjX{ANWFKgg z;Ngu{bTYw-1t0bi&$Y#2>o`p%ouN@&w#V9}tmgH6H(uSX}9&W3(@%AoOH1&@~gvpEh3jd_CzDkG_qWc139}1 zQ5-j9Jv^Ig4{;|ip(UZ075XxUu7f;Qlgclf^XOx{NL?A_K3%hyj45H1bcFN#^P^@; zL7a{Rx^(2}#Lt~vW&1(1W)x`4Tx+&k3hWZTqy?7l(@=+5l*-2X4C?gQ)<AX+DX`i?-_P<#9CL zp*GIr7oAuC7rQpifCu6QpV*2+yc1%W&&*)Xse(b^xh*bg%aKLew{=TGc$Mz>AyD6Q zt4eSOGWvGwa$4iGgFC;>x@{j@q7SW-f{I(^{&1UQ=UMu(LqfNkA#h3ot!aKa$12p0 zPI?OtS+pn-M>xrygl?0`8&``slCy$$v9ZkG-9yP3RM{f3$I8a)?wb>j*dop^EEwj$ zt3^`COn!f~(6oX4Fk~0}Y5-$|w8S5(PoII`6h^LgoE;Rkfs~_RPSuu-mt<(5cL*V@~Gg;BE@lu!f`RU0gQhYwFJNVN0eyGVh185P6*llSPXJPNqoG@y4 z$a8(Nsl#SFYaM~mEglhLs0-q|DR^vsv`~;mT=K}OB2ruaG7}MBT&{K_nv;MTJf*N2 z(b6gu%tTQZfO=3^61P^?zS(wI?PXdW8gOE}*x4gDLmnJa$VYl1lrVp1D_(P{xauuw zxnC`yfiIBBDw&6p(51RQ#kh7Z!+eK;hheA5phW8dPr@MP1W- zBHb-5EzczOozm2rK!K&f4>}pttY3d^)_F5oOY~#MkK&k>z$f$=6i42N*n+AfNI~E3 zGMvVrSJ!#&GCZ=Q!q(Z|gWqd_`Q}NZ1cLbrb1L{ON?PHT#=T7{Qufbrtklq|5aGAH zEd7jNQ;g9hl&55qXlc2Vbjv>LIHvI7u~lBv`e%jE^lVvC?!a5VQ9z^?UbUrkpW%EQ1N{TDUqnnFoCP1yC(6OIs zgF166+CBlq2H%KIsPP>IL1$DMr)q!WZgzCBpqPyZ%uLXFTHij0?Lla)0kOdh@`d}% zZ6gUDp1fDAZVO=`uB>V0;Q+U^-v^4=-<{C9qS1J*HTM>E9)7NX-AwS32o#=Z<3c`o zY$IlJ+d(Lq_lE7YuX;-QjsF}H`$lYc7PJe6*3r@GZBje*Bgo`fk5B~rK}$*_0&oYk z(PoQ`#*(J|)J=(ZIi5@LG;Ej*&HUJL?k>+`JG&YhKVQd4UfBxw{@Hk`jAyRoD|4)o z;^h~vWYtdSC;MNrbKSY8yXMRJwpjg5!leeQyVhm`AjTf|LUU~hzW6d+1DT;#zeJZ$ z4YoO44ya#ew-Fi_+A~PY`+df#F}ZlvBdFb@TNLa%%{@d;+3Jl%jd7%4r5ibZwOSPC zAZKU)z@!F&cEZ25Z4theKR-Z7C9$DvPcFBpPkrVhoGv4 z3cF#WF*Z7u#wyhk*Pz`4ijnJpVOi0NBd?F*JzZ3zAWGEuehrlW=e02dlzZ4(%{ST= zy}8e^T6pVMx0m45Cokm5+xG#ysd0k8Nkdk%Hw_Md5vcy)X;nQU6R+P9YW$9782LkG zVNZmI=M(tK5SQ<7@KUb@wL;kx8FQ+<9U-ZVkPE8j0vu@#V?TV`dt&<+*%tgCHuA3L zSTd)NyYaIZt2K&mJu>#H9x#2by=@{vO}43>nwM&e-17+`=Q9}$N{yWt%T+rYT`Aqm zK{=?7)&$X9e$}IpaTmDR@6_1>TxYo7ntCDOvlPTpt#XJBZ+Vn_@GGCX6S4 zvT4C$WWhEf95A56;vo0OQFyYDxbc3f1XoUGi&bpV`wg$mSn>R#w>?4EjbvNw&6p*a z0e7W8)-&kxv6BAgsq?Wl_jkWq@e$&`?y}dHibZZTelXxJ`!81le{tge$5^jFhgOA! z#i#UldNsDHb|6fHZI~W}*21K@#`YwkIeL>bm=m((@L)PWL7_(j;4W)%`7oSG5=htA zFil~tDdQ3r-}~oV1+(!OwjuCVfnFRXvW3F&SuTn+D+Az1XI-_81DJ^n4{M#HU_H3+ z4ya%~vB-&FU^EjDBFmk1rWEu_tv|j9V<@Vn3^kck^sfrJ+l8G%8bnMW(FDk>=9$;1 zv(rL8-yWj)57E2JzZ)4ET1CHr8o#Kt~7WB_ca9VfOL~Rs6yS>8fP=vh&Hw^lAJ$Fu?eZ5NaM`A*0=&r)9_7#t+7a zNf)ZG>EZRY9tCgAx* za14A;eTmbVQ@qRAS$z{XujunGRMn4$Q*tZ9PY*jZV%^$_!4X8&yBFpxS!haKpz9o_ zRm#KVnAF(p^KA7bIU|krIVMHd&6pCR;3-Npc9h1N zl8n=l^f&CedSB_JYf3UT^BC_+S+$Gm0>A$QP+eN=UhA=D9J)!%Kv-Q+gDFEbPHtEP zL=Uwc*7XOGY~VF0hXYxY9bXXG3E+w7R@0HQeTy|!E3h6)VRuQ?g&JZgA1YF3$2o(r zocvWLxHfK})%2xf7}yC=Bd|=n?ZrwNM>_^fP?{nL zccR$nWjjJC_>dhEe^a)YmMdgWK_4M$YLEa1R`nTNlpn~V_+NJdiMQOOf9wPre%@wd z0Xu;)9MQpkO#|MWpUq^m=k0dmUfjP59(v@l%&LY2VJ;Q7LGtm@;n&ixpHGmIO0GAY zrB=6-V-k&pH%j+3z~7$f4y_aDR*p_*P8rcWL>I75!994Dg+C_8wXoEcKXt3&7QYd_ z$+-vl(9P;YFgE;^<@t*6dH>K${(smB{KbCj09-|{=ik*ls`{@x0fA=`c?-t7H7#ec zvr77$Lx_Lu1e#eS2Ih{s?X^D+7cm1v8{!7tJuR(os(AAxC|*p`JepmYX7<{MC=7>0 zN_Za;MGPbV+zBkaC*vQn`Ew`mGWL1w!K)L%_;B$xUY2^ezwt!?GJd;Xa}%wF84>4v zOa`TSOq}Z-R4^!;)Ca5@rkvWrAAJ|N%Nl|Y_l_{X6)8_zTOBC$T;EK?K!`@IO@m!I zs-BA)c4g24v5BSNf`0BM7!vdi4N8F*BLWAD$&S#{3$f;|Q$G1G2*ltUk;q{0wm9Yo zXm7{@Xzw@W&*rR6C%aW6wiK z)(#h{?dHe?{**BhgUGg%Lk0fi^7^z=Qq$((;`Zm_l|au+?2pB3AFz0Rk*85ho-#o0 zt81b1P14_Vpqj<%PABA{G@|plCWqf(7i~yjE2=co9MwgxMiGp`LD(WOvpT{|8V_e> zabJYr8IYP3N6zjuf${r@JMfdxa$7X2j25$U<-%2ND0{U46{jW!B{R&bWFIF?*>grR zvZaBi$-7&Vi+WtLI7Gn2jBcry+^P8fV_#l-7}LNG{gN_+jnMc`{79&ug!<=PSN5BZ zjj$gi5crB9_Xe0Z+p<`9V zJA|h`VPGl10;0vY1eOBq{pa!*eVr9H2%f{nYA2D#Bceql=@u$-8Ek^t+CMpi2)V8s zVfh+1q7kz8-@Wi&<3hIQbx4kK*t~oxzH^Oti#0X#KcVKk${EOzs!t>5*{)+#mgl;} zmE~_zmc}pS73lflT@d@$6R_j}Yu8j#HDz97Q4)4{Rw37p0Xoutwx^mFw-2LqRB0g$ z-@L&1j4<2!p>I&Zopy#44&}Y zIv#(M3I8Cb|4C%1Iip%5sLU2(E46T`tlHMj?M+GH8#e*5tW-};<7jSj*QGfLmCbk2 zo;tB4!iph|B=Vf^5-4^H!AIK_OjMWI?OKcnSSmaE!DMcFVZ9b2t z1HEe>J)U+g4>=_7=lBvxhMoN0yX+Z%?=Y|pk1sjG@JA*F&F+1u&UPf0Z0G5{;b{^z z7R(itJ7j2o?gY+K*E~4MEFypPExJ;n9H?Sh;v#?0k=Insr@M;IH)_o_ZAr`ez3A}W zuzN{1#}mbqxEutb=kWsdufFzmC!noI5ESv>?*#tlxc#3Zy8gBkKwjX8IW%lLa~6_B{^^pEt-JP{NsoF;bh?#0TkQ40uIwLjMh&w zh7bL;yn8^352E-pD)N}z%b=dztgl)n`~y7Iw+G*_T|6OI>lzUdpy`neUE#QoYEkJ| zO)0Kbeb+DD{ueBN3vj^@W?LiwA0$10vD#__m&@z<_X|elpG)U|^zX}6VhfKDTTrXQ zg)TOB2C**EX-|r`sM2C0$$~k=^z1+`?@HOIqZuqo1oNpgoHnMiZl1A&rgR)zAZPFh zjtCITYw-u)VRLV+RIw-FZzP>4+0_|ZFir+AU+gJxfTV-Z$JFp_Wu>-4nhW@JAW_9s z!<-}3JXg>Q@PeAq1L=k5sgDcGFx@iS>omuXo8^5lRIDdGXbse~_R>P-HB8|p&>Bhr zt8H8;cx@8qFeG*izu0M1B9F@VUDxMukmno%_2#puD?%80{J=!J-DMu`pyBxVc*4L7&+7 z=NI_gViut5-jsCmM#a|;@N`WJS&vAcO)+rQ}x z1^o)qS!`(qL_Ie7GwH~$E?b*x-TDo%IWK_6AECqzESoW2m(2(#j>_%4bJyI=I7S!w zA%8M-@_Kz8IR+t+h69o(N0f!I)d;p zI?01F-Q-p(4bi8~(Jl?q1QNeR8IDVyM18C}<7@ja2ej{6?ePlh7AeWp6^(|fVmDE_=h9}v>3C=RVseRF zq*PK^Q|aH@OamzyZqbW9GbiQ|pS`h}1oiP*Xcl7p#m_iGxb?Lq%pFNaD+DJK8Eq^X z+o3Tsfw@h!b(s%X$u7Pdt(YrSHdb2hE&S>&JDTb}zsTCKKH7Ax3G~32S{5WeLs8}+E#E{bz^_))5q&J~MPOKNZxHpwhtLuRXHD~Bk zM^m=u#%HWJ3$~TF=`iItTKHb+J^=kU?f;yyCA z_QJABx#P#_{{C==Mc4MUFIK)i?{wq8lRzhs<$k@qS%$*jfW_bWtKp$%9O&OAg?KI% zH$n0l(eOb3E`LH_n6m@)@3W_IQLwBeKV_UMz+lH2de5WB=JpPe2Nesg#iwu%eOL5M z+-!y=bWj&(Zyac&l)?SA6n?D=Bpp--q%8gZ*DcZwR9D7B3A6u0`~DYutqo9FU(df+ zSJgj5wmcI>HgDG=Dx;6u5tl6Q6}N3>3pMP&+kn!U=8v*lV_;t;J-H2-;b8&(?FR#n z>Q4bgrhbRD(g8bMrl|1dgroO9uy zcpf$Rfo)Vkg587?zV2Kn5CWpI7cVb$;ag|fDB;lY$`fz6AE;p7I2X_G7d3?(&b59h zbWJI1%rDiZz{M@Tg$#8MD2CfhN{0ZZBUV+BG%J7qOl)h~6vqCMX)j!%y&Wn#yIB*kHU|s6BgcRn z8i*>0|Oj5je{0a6<3OL1$>tkFxt+Ze7Q3Hp7bn2U`q1vntDPDq@Dm% zk{{veAT&JzUqV{U9+9g2LU|=F+OdHJF&+g{S}~%f&+sV(km(jV-#tnqP;YQUuq)TD z)#S#qHS?3OYsZ_OEwx%u0|4P_uH&&R1}IriYD@vY!bI zVh5LbZmKp=bLU}0va%c_y1;}hC+skSjk;b!H`Kdw`Hzj8 zyy7`f+iPR#G0&n1q2uxyywY>ya0JC5szoORfChXIRC;@9?_kgLx2!w<}WlZLmbPG9p_OB{ zCC8Q?kR?H+Zd77~(jD(v#7~pBd6FenHbd|qa!LdP;|X_#37yK~O>Q3Qj^b6Hkt(_E zRL_yjy{*JeGDeyxMDXBQuAqSS9cou~o?cSRz zBICUa1rL=uev5jHFA3O7Obp9h0lF{SsRXlx`%2YE~` znWJNMas~?tUnMd67 z6BS+qa&6@}&=a4rTCbH-4U(ua;n$IVFK&_=@B%G3w#3)yrT=jb{~_skA^m{Od~A;6 z)S@-H&Z0<`UD2lC-~H*D6{9NmJ4@uN!s#% zGJNoB`(VXfMGp=9^3kJ${|FA|P3Nw27!*Tmfajqq%3 zXKVJ?z+6q>c6mMje!~FrqE|`21wVuA6vzrmw;|uIYT2d!k81zx|aWL5jXn_+T^SmyYnf`HLk*_z0(FgOZ{eU;X#M5Xu}qk&(r<@81^ zF`rQzPPbRjpU+=9f1kgc1Khw5lw8uKVD~DJzAS?NXkda+o^O3_%;qWzB!lO1#=|*h zF-tx3JNf=QXuDq!@jK4t;_u@R!_tFe;Df=VSX{79 zI;443H6dM6(e>NGmJ?)Q(+0#yLpImm#0W!phi@4k;=KwVLq@+yo4{e+3X=fFjJx_@ zgRsAkn5LG4uWv7kb*)b7hUv{YzI(E5g^}@*lVX21zH{j5hi~WczwJfM#S(De4qXnr z&jHt;58{kVaOklT@|+C8-?N5_IHvRYiTh_{IF^PL#-IK(grNh$Jh8@ zI-R&0o`vQdI=~u(M+opip=$)iy24|bGuD*s(G=}NhxU`g!dE-zH_EEeVVapASmDKr z(1xMl6TWBQ1`(vd0T)c^hva3l&8f<#e)188ppOMu!jA^BIss%N64B7D(ZMh=UbQaM z3SN@*3{}0Xes_({6|HHI%t=0nMXI0i^0EiCT!7bEQery(6TT@sHGlLZj@M zAKnX>NJb;jvWm5brK7R3c-hIR`@Kk$*JFrAdp$*`V0&CbAJ(UTUlV}%bjhG6ZKjATpS=bdfFxmH2d+>-wHXqwQxCDIZ%QMv&ay1aQUXqld7@|b) z@s#oyuFj+kd*Ef3wKP-eu?GFBDu2+b%D!v8PoP`J+vj8Gf$_IRKuIXJcH$A%O?1^N z_$u{QveY+-(TNGiwL~`6Puq!ovIm_9p}`XNIsW zUr79C`Y?ta;}qXZ=*s&K#Vt}a=nY#m^s_U1A;Z{gLA^zjDkAZV2}o+Pa95Tsu+1z4 zqc(YJsNn}3;sHq8BUwZNlpcq>my*iy%+Wt87kOw&@9{V=k6J}q>V2{Q?!hcnV}g7nrbBkR@zgw8)0igI3EMWK9^dzeytfo z6UCyZpYm7THgrm64(T;5*$h_4Y0L8)G1))*z4#P;ux8b%SHEPZ!yNiC%an|Hcxar+ z*225pq3f=X(PzEn;piHszZ#*xhM>?)DwKm8TGD$4`JcM`hNN|~2#nAi} zAZ50>voV&h2&Cd0e+*YZJ5hlk4yh!C?@<%hVLIxO^?^n|N_IKAUx-Xc0 zx_h0ENM%I^_XL%mz6S%M0YgT3>0IN-ym0%LB&In(28a0QH51a0M^^SrU|MBqyn^+Ke< zZZ7x?H!}`*BY}7C#T>YF0Ru;MQQF%@J93dR8fB}L^)utMSpXOlRUFR zamNdG!{VPaQFuD%sz|M;6X%EUfjB@d{a|@nz4fy#D|kT{k0tuh(a@YmgXi=uDl<=w z96bxHmAiqCjvu{rI0`fm%13#EN6YD8zehTwG6GNaeSbJz#0g zmI7xJn9e&A;k+g#EtQr5H%gB-Yj`3cq>}S$egKx^U$Vys-NEtWJmRM}&XJW_aQ&Xa zT!C{ImldDWnA_g-2+G2nAOZW=NLWqy-|Zz|FuEgcmh5L!>Af}EbDbeo&)&eBQZ98o^#hNBP=m&{q@y58q(Oz zcF+^!4rQm&o5knf_Ma2K7<*Rxt*7kBJGQCw)wp~%n*QpMPU%m?>vL;Cz?DQ=el3l` zzppe>RBHm$#HMl}1TrrH#N%zEw&7-9?Sc@uNtEBTCL(o+${n$Bu;RAZbLV(*h(x=X zi$g3ai$*KfW{kPIN*fM|$raI1D(!fFWW}A3QQY}O$0cS_#JVFBa?%7kmC8-I`}Saj zzn;0%Zaae_Oc)$8c5LmWO`6F)nkd1OMmo(f8!64cStjA6>Y6z;hpN}LVZxtN>j8C0 zgnTmorYW{B`5Q`L%iHlzh0&L&q27*iT&hYlxf^b=yll3byn2I&0?dLc# z%5cU%^rKGK%&G_y_x}oHO^yn{&2&x@xQ~bU$_PsqW4O@$2KxNreH32-u~6&5cT*fs zoF%r7;uCw@heh!H@C7g5by);dmxj=HIKOOBvs2x0?PRw;G9*tgwHCW@af+AcaCm5!PHMPiZW)*ks zQGVDXkEi&l1C;O(riSKcPFo4O~ zB!cseO;AN+E=dSpJr>Ud|D05(^$e{{S)6a_(lna7sq@i~>V&=PWPts&-OoCDrRX%O z6jOJ1fA(<|u-R&xbOx{NuEb5N!{CMTq-4^ofpTNX!)iD45g& z-_d+n6Q}824{pni2Jz8vL?YJlQr_X1=%Q(>ljx29MXvwa+v_baYyLkB=KqGtdHukD zaohgK*8ZP)xdlL8uGJneAuUi%5$d(7B&!XRcC1~Zk2d~;g83{&(9mFE;|KwL>7?$x<|cea>1W0Q&R ztNaG6#+&}_8!(zl2$9)!&H61$I88HN`p|*qL`e?wp7jQ(K|bMSixEtc<3#AvveLG( z4mW+S;_|Ft@87TITv-QeT8J%cc#g2BipJ+iLJ4x=)?&ZamaLWezCE~K(w^iP65d9l zWJC5_WP4r^^1I~e(A{xa0n2GF_(f~kB&qg7v5}U8hGqWU z8%Yhz;{1a9kPV*MlyZrAcLVadkU#}(jy;sRcKoL^?CU1M>KMMY#y&M2`%QpyKQVzG z!lyNWS0DdGjtKcmx$ofI@vx|4LGA(3xIM@;UFKY?j1&8`%1azlLILChp&|TYT`VCSIT|zOsmu@<-YbO zK)JVRZi1Bx=_TO1OF)u{OCp8gCwTvkPeVlNo^J+mm_voLCDr96bhzc<;7j$)wA!ere>!a&m%*%#7b%3VOsy5OLw+| z!U8kj_2*hb4i7>2XXsn7L06>utYQ;Cy6Z#D)u&mWuW6at_$zy$xSX@1*=dp+I0Bbu z!AyyADzu|RH7kOP)IJ}I3m7>=Kgt?qz1O^4&SSeUr$~p7#?eb7-3DavrF|TzO8f9L zzyPWI{M}lrq;dq@kzV->P4j%Xs_ISiqmPPA&`k3R<57mfPZzoOjutmELVOZ5wzr06 z?WYqUlt)jdoRBrn0@WHU0J>~<*IYeLG4l}Xu0?D|_a0aK9fxn*YFWc!VpOoWug1Xk zXQeM@mtvU~d71}JjN2sxC>Fnj^!#C==!c-rol~eH79I>Apb&0ZHNDsT*QtiJyqv zrOPfNW`VriNjkk9ATM{H!rVKon`qZf%XK$WJ%_bJ1h;?^VFtDEJH82GoXiMjpf}M{ zyY0jO$J{#xSH7j~!(qp^ZQHhO+wK@0r(<+%+jcs(ZFJOO$4MvYygTQdnK@@r&rH?- z!~0=X?XSP8UH7`yeTkUxm-w2HPuNCrnq)-{c`3<9t?;1|`zhwb)R8FG_F1*iJf*pV z&kJuIN4bO#Taz;C!X6lf=bw?i z+9z2R3EZB!Ihxn2tqMl<{jTZ|>vphjpsrSSHa}s4L+n%=U|Y;ko3V5O#@pv0v+AM{ z4HFI?Gbo~=#xdk%&Y<=B_(8G|FQSJ-45? zy1dnOu0yqgLP54k zEvK0eN0r;-?kHBmRnbs5hmxdOu!ob4+{Y`pQo8wwFBJ$#1vOrf&KESy10&;&lE}%u zmY&0!FbS$z5q^zan+7KEFDNg$tf@dwD&;@HNK}swM%sX-FgC+UCsC5(+>rfVF4RIe zC9W12H!^ndp)YP^N}RHnBS53#QyDVnSR|_w0du}5IT(1d$%BGJ8^$c#ui&6Y>4{^CKmjb>cvlauZbX?dS*R8^kfmzYL zt8eb-YSCRo#c7ecn#Vntr)$?`ITl3i;j=)QrjT?97beW!1(3R53`CZx2CPlH4kMPy zZc&&L5CdS=7Bkwx!B|%dd*}hRPii8%YjqSQX>c-3jikA#6AG&*oNO-}jCkjUf(UoU zjuBafbaJ87t#*2A8}c*=_0Ag;2ykNv6fB9ua6jL>i$lO?ZgpNw+~;dY7|6)o`Swj{ zCc;2@@jqM_ig`jA#mVa=N~|SmvGHZ)LNwNon>plq5k1i##R%1)d*R=880&HfgD)2y zyol)P1fQY_DO7m!nqjtlFN)c1NZv&n{xOUqfEY>b+!oTBk+QG4Z{Rs99W~K{h+H-d z(ZyZr0EM=kAub%+HZz2M?h~UmGOLlr3*kv2Q(1ct+CL8=pQr8PdSp2AIdNE7r=RFs z*}@XndUc`PTkN98Vlj>k8W#yx18u<*u?h(mUuB3N#*v$|9r5w9lO5_2_TENpg!lYR z$-zR6#^s95`qh1yj?XgkZ55O``3SDke2epKJk)yvW~0u@$TRH~ir9u75r&rXbx}&l zrXA$48LTD2u(Q=BEI)&i)G5px{4(ZFkQUM4-HAVX^;@;ubHQ54LmVIR6 zMC^Y9KWBI12jOS%D~ z5)WDit_+ME4w>$f0gK6mF5o9LQ0Z?T(j4gJnFlx$iU~pFjn!J~Q;|d>E~B2F=FyII z{x|Ht+-A5!I9b>e_O@?H4!E#b`9A%vgRD05!@@~HFM0sA4b||9E;IS%NX_6)92v&s z01>M(`Q?7N88pJy1j+-TESFfUvN3MN@2kBuduLCxU~(&m#J-6K(L;kUYd12uuEdEY>zT^o$CZ*C(uL)Vl9|WdOO&D}ST6-W-|Wujoe50roOAF0Ni(>6z!%JrFpC z&BW%kd>@p#W8vjAu%-;XSOTA!kM*h-o=4LZUr5Hc^*mO9{Tev*t=9Fcy*6I84i=;j z>Xd&xJ6SfhRO<%Ccfl6@X7D(`}v3;n5{kYq!eqLH;b;_S%@3y(kCl5J0ut5REkDUXff*U|wb z+`|b8&?^mF)0y2lrSItZDDTfp=b|)xWtRI^^b92NGCAXyxRSSC6I13m#wz*J-C8-I z)>Krh#UN+9BL!WFHZ;zqpCZ(e>ZyMWZ>23@JW3`@Z>F@<0;oDU7tGxxnfG9=n$}nL zWV1&5kW(5Hjru>A0W_W)bD;$D14d$`znG4?H3~kbIBa`Abmu&Lf9`&`uwkZnn==IR z=>-KkR|n+>GK6~}3MikB#xnYnTDg38BdpmZsa%bmZTT?nel7P}N+rKE-h?csBGqLU z)I^$JhP{41JjQkbCpkoILl6Vc@(o-PDjgL_GEbb0H!mI)-y0-H<4cTS01H@z-2NxU zPtah9ATedYnh>tOMQY_++a$bdSO`K)C=p`&Hnzk4mX!7++vOm5eUx~`AwuEdTi^pi z;UO0!AqD|1(DNJ#alQp{xa0P)<=zg=Qe%>l$BdwP9Y$bKZR4T7e)o>SzP^}OjfD6N z&vh00+65Sv7IF1;Q+Rx4Z$A7k?hg3vXll61ls{id;@4F!mt8K zilC1|BsAFuT|7Nr?w)Lm_37)r@cR0A9TSdFl>^#CLdx!dLm5d(!Z#B~+D;jJ(fhYz#l(3R(G8*NJ9*&xT1;p7gK10ETNofL zYwRrJ_NeyJq(2+R4(i6L1!=ZTphL;nxJAQECM~jV(*xjFW{OeiWa7;FYXHZ@&rp4x zPwLZQ4JM?YzWVdfcOTMBx8M+*aics)9T zH`aTXAnm9`&~CVc++Cj~#!t?KX5~eASK{ERYbv_pHMYi7=Hc~OoG8K=X3@95({!^q zh8MRWfZfG$#c$z4pG+5WSWNOHm~Zxwzcy-RNZ#Q2M#9#$?(Q4oar+daUvX)*1lc7K z^3$zL*G~y8y-F@533WDAn&*!(nz6s!Z;@YKGFh`1WkOQMT9>Z!y0RAGMpIF&McoY$ zN54t#xt|Z<%H`&GS{8ybi)tCjuo^GPLBslz_ZuogsFdHtd`MirS)jvARoA(K-4xF@6OpD8~eR%zO4%eegd#b;(^oR!UZ*Jsk*dKuX2 z(zmXu2Z<-UW>vFlMfkywYmSavuPT=c3fi-W9;ne5$8GZ7sKM2?=VM@s-3pP7TaL>ijr+B=#F$z5sMOGm%f+Y)5g)i z@-#pk#X*2(ivju>f7}(PPrG40AnVCeDcA~9fn&sJyc`5P`ll)>7Mk)%$@=Z801~yC zO4_c18ZE!u(K1XStpbpkjFMEo*6m2Zkr|k1nDN1%mJ`_-YG{6CcKC-k(aCK|9Pwgh z0f0e;5QHY$DTVh(bEKs!otQhf8kWbn{g9UmEiURB^Q!q7@_y|*2ec3gy157~dYsNm z6(I{@OC28TJrrj}oe%i~&yw*+TU$FpzkPBHGY|ElP)^8AU_Q%{uCvT#3S88yddHmu z{>~z7hbzc1-M$;I`zPvapj_>&$6m&*iCsyo@lKI%Rs0L^p9?9X3X<8`!>&G1Y(b-O znmM^+IxOr~DF)0J!LrC`SR_}|(-vvZblaFMpRJ^MD{RcMC#UUb5dOdr$c0x6Qg~T)$Oq>Xv zbjzi+ganMwPZJEZgvNFle3lW>qs;B13ANQh#if&~{?w-2&y$XZGZ!Ij^AHj=L7r<{ zcfnu|59yuwDjzBdvVV1-^PNNH2p}2RlWM?TKWXINvOw{_Im-Pi%*Kjgl!z#MK3O*E zK=hSyjP#IU+Ip$oB!iAtvlUV9OY8!I!_&=1JHDhL#x3-EjChsg3y5XPQBAoFXf*E8N}S!6RVVkV!VbW_ z1|$_It1!qWZo``3G}(9KQZ`s*X+$%C(3c#*RWKoO-1YTGxXT|d`p~esei##;s|ViV zwPuS5NXnX{GZ{I68Zw=3?!2opier*#=r zAyshbdTjH|RkiqLY zvcua&pwQeKC6SvL!HZ9+<+Dw5xO+N2N=Z)}tIw;4+rc*%2mBOj11?|d`*9cqW?ispdFwl~Z+<)-dK7MKsGEEa$8EKE;#K$_&+6ZVm%{jj9tbW_0tQyvdN8j;d`$yU>Uu zXAJFb2Gr;`C>z++`oe&yzPlIqR4=3Rhgj?|b1HjBp1YPSuszw-OD+_OWvr&+h0Xq- z+WBusf3@en%lp#>JWBr;65&t&+;=bYzwtBc{i90jUrB_~s zaR7-B8?3m_c!5ywi~D@f`8$cQ)HS7^>AsuwJBiQ*AQ4;=yniDRM*koY1mL|l{;u*L zH0pUL5h%2@d)fhU&}Ll=5dabaP?dYxVGJMM^~(`a2y2&<%3ap+M&UQM{AinC4df%c+&J2eVrF4PKXMu<36781;AQ2Xj5i%cN{~!^} zekTzw0VKl4H`tVOw%8Dy!@dlg+Z*sZ;ehr-^w!Vbo<3>K1Xx-8&e(VLHr}EA% z%gcMXeiRsU7j}R5(?1FhtZ@;Jm#MITIU!PZDnQ`*cJ9CRI&%~R%y&CPR2BGJm6lDe zi3xq)RM-Lwh^L9r>`Hkn{5~E)=wD*X$_qANjNg;h*O4%NDvL5H+~Nx^A?7Fe?coMl zl+sd(-Xo=hS8HGjZG2j%HfQwO1-+6>^U4CC^cNk9gLOzlOB?##s7u>$oHz?oW-?emSo~Ql7MD6*yMpf zKadZ8Da?Ytr;qeW@cK(jSP@BAr1hT0}F>w9Zdar<&oT)hGMxGVl zA7`hozQhhUco6?{Dpr>?2O4o9aE{?EO_T!x(3Jb9{ndM>j~>TQE0X_#MEH|a_dkXD zsC}}0ClOe!=+9-gyzA0r?z(8LDohoxnocC;_O2_MVve!R6dyoUHVfesS*zr_cZ4c5v85jQ0SCNh1RJ!;i}Q!99`Uzsy3Yfv7H@&%EC+U z?GE>8bA^rBQQ${;Fre8Ia55l&wc~)^lP^nAreTTI4xD7r*n z=*6dMAJV)eJi7{t+jM8t6fWRLXk53jQ{$-~Vu!@(zJnxy@hku(79@WL2~SE+3}?*t z2pHpmamR2u*?KDtUVnY^pu-}xOB`~HI?A8p((%z-A(6}%uk`;|!8g@as<4?IopbV7%+ zkirz)iLfvy81bOQ zLRzEB9b&oq^V}-@b%VM|GS=5?rmZzfn}@{el4k`UkMpD3Yr0E@%!#EF9^dK%86d!O zVlZv>WgSI*k}X(>++-2gVSfLkEcX=bG1{^kk5X6SW9kF+Oi9@0^iMvJ?Qq3O_v5E* zB0q!R%cR~5^>L3ePJ4&Aj?ihHFbUm$1JX~#M@|4d?PlRH0_i@8Q=fkFQwY^ME4M&0j90E>1(R|v% z5Y}^ZaMy0z?-{4$xOG z{Rg4DWWIYk0=$)-9xRIsvehy|Z{6XIahBmPXQG)|)(uN43Y^y%={_sMlP;)NRk1-? zl0-ufjYDAG{f#TQb!lP3aFm7GZ=!LNhiP2lYfHF*J_Z-y&=ivZfk98~4;PoR*g1eJ266g|ctyMO_uH68c2r6t?_@LJO5?gX{5<~h2X$AL*t#~q|($^$0KB-@bh4mws zgz=qHV$nX|gj`3W?@6@3bcU>;DE=}MwZc`v8WOfC87xLh+|R|TvRUiCvmQC7?I@j~ zN2x}4TH1<}N)w+EFZtkNv*w4E@j+y$bcNHNO<^4;cxFxLsu}C-I>E#_IhyJLBl(-> zn9>dUH6(VOA_DY22{ytOU7Uhr@IJ2`eX}BqS$i5@?n>s)!?e1j?5&NsPSsIum8xV{SFY;0uoi`2AC9Jvb$f9?H&o1?d|h+R z^}z5Uu1W`YNc?lG+B=272O*08UZeHjQV4(X?EV|1`&SC#Pc6Bw`G0H4wSvy~sN3&w zx2PgWBmtKljWwjMv`d^>3;D^#`z-WTE=b@MJ4&hD`|0J%`Zyf&utVKUdihm13d2he0#4>T17_y21lF87stD*sEC&+_%rWBQ=kXbCvE=T~yV#*zRn}oL5)qCP;Lc@nY|gQpbrS25!*s6YmR@*yP_ck*=aRDcy?7&PCMN3_t0Ck z1naGm3{+9)&S#=Uc8dE6Q2xiT)a7#0HZgnqlhQV^C@H`A{)j$_R4cUUVnjX_5iYI5 zxq(>KkMVVZ_0j>v@8F+no6tG%|YmfYL-mRyWKT5@Hq^@@J91K*~;x8&C8XoD5?@5N+4%|aKBNXLT` zz$HfDR}zuE;FpIT;85f0$~L=BC$6{^1CagIZ}OnrS@H1oXN0EV4+uG1?N_p0waKW9 z3140f=H}7wev=1r8z~ux1LQ&IcXjHn`ZDkGpsc+JXM&R>6@mtUJjk{7^6GE$AZ~y> z=pyzvc@R@9KptfGq0MH$(#&*$?b`FFg^!TPhWp+_gr<2mPX7`eyzhlV>n}L9tqGv~<%-8yCWlSK(XY zWzk@F6b8}!R83a8Zso--N-(e70<%!Z$`_woqC@98AoAfYWZ;r396a=^ya(1w5b9oK z582czEDN#90w6&EM-hPR!x6J+6mLeD#F*+O=Zkz;k;M!cPEu3`pR?LOTbkV)jXnWx+1&BJ3u(VmMh? zV-B{jYNoi*90Q_o-_YlyCclPoz=dz6zsrNf0T$lh!tU1dC=kS@}T{Hk_QnLeMN2hPLh_&2KmlcZ(fTDzCQ2P?Uxia{H*J#`8`N}*-Xd3PLJ zpmX14!QglQJnycc-^u6-2U;~EF}VF{@1tsNR!hsEz6SJIcdBd|_qu6NpDbjhrJn|v zrcT#OM8Rg0`*rSqt8z2n_bA+8+lKo3W-CVe*adf=9pWcd|6KG$zb6IKHLf4R&jkM% zwC@o-kShr7{|mDJlZp2~X7KzK*=PNR>`H+*6DTpRWCEFKTJR);n0YXY z$+n-itJ`$xoGR&O#k}GXsnL#}UwmSLZ~$mxD7OU9tMi2k9h*)CYj|AxRA~G)2j*9`|UT zRz;Ty0C~_Ez{Q(KS=5UgCFayZK-1ILFJCV6HT{Ae;Ntc9u7vv4=Ch>)z{NY1pI(8f zkKu36f#gbA(OIGxABKtfjf1@Af(Fuu)F?6E zPLZs6=I@v+r5d^w8{sE|17V#y{`h=nzT7*=kM_aT-7?b;a5v9=oeCek*C)S~4LRuq zZ7?}cF*BcFKG8mraMk4DH^(DDi|UKKY7wG?m(PeJU+Xj6V&>M-X|9=K!?90+Eiar{ z+??rVw_Tuel|FMh$2SmQOA&BKTYtZ+5)mR%jwxXe4IG*;i)LxIgVO0|skmyNL{v!P z?AK}_u6U-_k%_`v1VqYRx?Mk;)=q!DEbv@ry!6vP85gX{UhdXtFpISthk#)Ba2QDK zkaDB`ioeY4elu}J%7bK5!cBX(U=s6^Mo!SEbb~AAbG~cHq5S#U_gtxWiII*yq^fw= z5EQy>i3iEB!P6X`i+t7liKF<-gm6^bGEu|Gxht~T-J#CwHq9LHee#W2wh46RQ7UnU zY01qQVO8s@Naoc?VFj35uRH|=KBbW|LxguT@5QBVR&-q(5D!@b#}V2jUIdQdmQ`7! zHBAOwED&1`$tCFs$yJKyVJRP({4;WR!b=XG8)nW1g$rdb2(hdvmg$qIn9GMg*sg%}8NXfn|Y;NE;ho z&*x~7-l5N}P8-JQ&1{gpO(J`CEGq}#!zJ=1k<3*ufmTIgqAuC772u4iGj5Pt~c9~D~qC=n7IFw))ZMbQA%L8LbWMmr1gw(YO}&)=M;(ESrGxWd z8gl<5w)d4qvB34KG0<3Zb~pT1uG_(bdQN~0vnNb9Sxsl3kXZD2^rMWqQPg+xLOST? z^mAz#jTZ8bG;^zw`bJ4u8TPP@@Rz#53Oh-YRFQs6qTs|UrpXt}&^R+Ef=kzM5Qi=A zt?kX{mu&t^iBE1}j1o3Lk6^%pn=-&qK)I;=mX51Y-OGlG5dr$M{Q&PwMX2z zZpckMf+@Crq_fszNmR(QR%79)W)#K=>H zkEb=>m6#R;Jw=?GLL@%tLSNto_ty9SiK(RM!?w5{LmU#h7X#~O1|f|JCAwY5Psr|u zkcT)ujks(Jh{v7H*Q<#c#SJRr9-u6K-1Wr_DF{l;I<^x)Iv02vtUeE7OQ06k7BltQ zp5Ly=GXJuF`vSvZ7rKrZWV&Sjm^&C(Fj_~t>Ok9FU>E#a{^P^Zw^@9WwO5Oru%mXu z6V96Wo8h)^Nc6d)9kI*>R^z4pl~&lTrZ||^*d7#jc+H}_vAQckonF~}pT;Y4et2w! zlz9sD-~F&8ByMUIz7AT-i!&o`^o_N`nw?&SeXt$W30K4S9@vRlIr#GK>Wz9@Gnxve zWhy%;>tfGf7f8~?C~~d4-HPhRPS(B$vUE+b?zDNi(s650YttBgir%;abI(5TY41(% zf4(QM+7eiNzBoLXp4*pA*l2eN>BHDK@dVa!HKHMDYp_g#qRtKAq|it+`Q9EL=frFp zBO>#CYjdBqswZo%e_%Ctw+fYO%eWPd^%ez7{M69uxoGS$DkD=KU4d+LF!7hVqJT(z z8QI1@^3*8t`_RuMp!1DR7e1on+;Em@D5Tqv-e0s?_Oj5j?wm=YO@t4A#rKz?i zl?&s5O>G66bGltL*oz|)lzYOG$IXz}`2J)t+d)-eeJgL+A4Ry$goc2!T*Dsd6=iuR ztWt+m)$M)NWlGn%!glk7({exmbmJ2*kT(AVY4sa+fx^Ktyzu=<4m4%Sh8aRn6>Ms5W4sJ&|UUY zD0uHV!+L!$SdC(-Bo%2pYCS&~gw#PfBxjCQ@*C_3<9kE?cn_gv!=Cx5X*3}NDB&(|M3~s`C@nMnoED;k!sG^2iGpO z)wQ1Fu2d>Rv-U8O3ns&+u@T6svGl3(WB&1T z`qO#U=2fT&-Ag1mUf%ug%96^!OGFFg*(!r5;i|)Kg|3{&7%Oo9M%s z8`1eZ*^IrwX3NXZG#jDLlWTM3p}&I3b?2Q5!x2+Jd_inepLqo9kQTL_31 zra=o+j?)%w28CiT)$_(%QoE^>qgy2KSz#?w%}1p~e#$kDu3Cu5XBA_O&Zn#&Ey%sD z#YR>`^PRwkLKbhZxR}WFKAf7^bn+hXY{2(tFatWyM~wpoV(&!=XZ5)lqv2WfsIb#S zpLbBQvX(lqc-HI`xxim)Gx4bCEoXAG)>+4Kw*+?)v8Sl0VS~Vl?<}_7Zd>3ouLL6# zDnSCGvvm~_{N9&@#tbF!ija&UW>83q1#QCei@{a^7#fJbD7$i7yQVDn9)Y^zRKge$ z-Po$Pwv2|qFmkZnQ3CW>MSj*fs9XOFk*T;ZUv}Pxhp?a9@l<`NlnuAU2O$g4GT_{w zKA#U_p+EBtc6q^Ltwh7(9w|IN-MJlv;NLQS?c?9Kg#K=UIGU=wJs8hOv)B*f#Tz2o z#JiFs48l(e3%61fZwURpAdZpM(7mAVdT8|^y1@pgXo=G5p32j%;1Zhz{Kv!t7gZju zm=rG5_@0ouvR_1)uclxeYmk08t&!)f38TL&q}8xv_&w~n^)F{YX)YL+l;X+UdG%(! zbNAz3%5(=XuPx!8!6g=$vQdU(Zt_LE?1@c9dvIPv$`+=I*OV>u7;SBJt0ikuR+&w5j2BtWINr=y030 z`pDb6K_JYALO$&a7=}ev)T~ct=#gJG*r*GWzQ3s`U$2` zo&{iZY0RNfojoL6#QP_8mdZmiz4-eFe}nEwQE}yz;Cx1HX$#j+PCL}w$I~!_>!!{{ zz??97Bo}-EJHFbykg`-MP*Y_j^Ge z2(tV&broH_tE^M9P9`0c$e4HwGK=}V=@1y+5%In^mT`UxZfso14_uQUwTH(VlcQP$ zOkb)q;PPI`3bVN z2&A1bUxE-=!XfflS;!atxO#r=5@wAikzUTGW`^2iJoX1B*K=GSf4bA>>~qg*d-1gt z6R<6FcBK_teF;jFfwUc5ltKxni2VRZ;j7^sJha zY%v~L+qkxaj5Fjs;$+-YAN;0Mt{=IL*y$^w%Mjm^rrXFQF_DMwsJ|bU;e*pHQe^Y@ z&Hd;oD`q*|Ts1Rn4URm=L%u1Z5EN^$ops0@>)dnBZb^)Esy_DiAOl&^<|zk$aGfyV+d{co zKDLQ=U~)be<(*^3s93U*ry`AMT*7Q1c^J#ai70+#_~@EZiCXJ3f~T{?kyj%v zsja6(F75cyIg}M@nYxA}mUiU7dNd%NHRtZXG$k$!TX*902Z0b!2deXeCsScF-0?&W zY$KkBe!yv5KS^a77S-F{c^EDuwops%TT_cm@%R%_{I1AByQHCp1>8BJ|3zfaZ=d`p zU+;gGo0pY%1d@U<}OG3I+oH9pSx2 zcXuf*g9rv-HEVId5*rS zuzL@wR>3^B5Pi@TBj-KlsdsnVoon1R)c|E~ie`sW2X!ioBo!#m26SLKP#|brKz^8n{U1miTMr5Q9IaKZ-UGHDXV*H2E?P-dY<{DHlUYc*iNNocxcdIc4avv_wSh4NC!pG|6q;Xp?OYie3sjSOJ#b&P

    UOT?=Bh^let>IYnxRXioC2i51PZ$ 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%0Ac=0wS{cDHEkak+oa$A*k#XjPE`TB|?>FpB-L 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

    b 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 E-zz%kB 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 CK6f1e literal 0 HcmV?d00001 diff --git a/test_conformance/spir/binary_type.zip b/test_conformance/spir/binary_type.zip new file mode 100644 index 0000000000000000000000000000000000000000..97479034692738da185641fce29f999fa1ae6478 GIT binary patch literal 2777 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 TX=uNHmzr|9D2#Fn004dmU$OF* literal 0 HcmV?d00001 diff --git a/test_conformance/spir/commonfns.zip b/test_conformance/spir/commonfns.zip new file mode 100644 index 0000000000000000000000000000000000000000..3774af11e3224b9b6c0c8e152669703ad130955a GIT binary patch literal 321005 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

    >TPe4W|gIAFiias@NJtj4^LJ+zZF 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

    ~0W}>vzGjg>Zr6+u6gf2aYXV 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 z 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 literal 0 HcmV?d00001 diff --git a/test_conformance/spir/conversions.zip b/test_conformance/spir/conversions.zip new file mode 100644 index 0000000000000000000000000000000000000000..8929b62a26771783a84be3cf58059378a112272c GIT binary patch literal 6386745 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

    &m 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 z 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%0D2)@^9XyBlE6+&5p3xQnXi4 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� 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

    W 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®?sPIjcZQYQ=#bjOOavDL9=HNB(`wM1i`2W%5E|-VEVG?pT{P zx-(s^+ddVfb1665Ji%|5LwcSBERP5*j@_v0=(N}oUiNgXL`G=vG2LWVCRuI_6CQMy z1QQdbtLDz6oix$}nh4Mkc-*A5{G|7z-@CP2!^V0uBYER+2}(@j5lq}5DgH>V#8Mf? zjHuBXqNKmhb|Fh$qi_?KLZWje+5IHGrK8pLMhaZ(hIqJcYS@GethA2Bh?DlCm8w=n z9sEPQs7H<`3@C3sjuD~-7#5&h5200V^AAqg^rZEnrUbC=P%H$UCimIo4c(kg0Eh2j zAQTS{Vv-0!W$qmheg^mwEY|>JzBv+CBeL;2WDzv}G}@#uD=v#GpV@^t`tYV+q@qhX zRQVU{Vi5_Mb0yGIWAi~nj15di2CB;7OZ9*w(2s)F?ZmV7*)-QRJGLwcqtO z3zcCOtU#JD>dkKknLCl$*p5NQv$X&dtXKZlGJ&VQ@)nT_cpgW6u4T0iF zea~O?Pmx30c*f$F^!WE~LoH133}}IXJALT-%xmGgm*o*#@QbL6m#^CkrieRz2&)4;4EN^?>` z%_C_t954$|(F$dwB%W|rT1av*OH6&wV-#?$Mj1;xf(rAelRMy}p)x|NL4t2c9{%6F zi>UwRU3AIsLn+{K7)pbeSW%g zJ-KHIy&Kf;>*vImC4icaQ)$S()8NCzG@V~A;o%%A!LZPfwjqgH7|`s4h)RELg6tc! z`*p~2KhOHzmJo#JC?AJ94G;#XrYQdHmQ{_?E(_!w=+^JsB(9J$uU0NZ5TBWXeyZ+i zQl1`Md5RG{$G~mK8RI~BS}jHb&lzNML$uyiVS^Sm$5+)kI+&gu9xKh2U`1LbDL3v{ zEZclaZGPtqMi7hSR3U829NhiNx%V&cVjcL0cTqj^Pu|5-T=!H7HsbT&yM%#tt*B@7 z_b5|2K^vu@f-cyO{3+KlO0=>sFI%R*>`FU$JaFm$lK>+voaa{K6GGt6%vGw3x`30g zrAzksh0~U1Bzt?Wg*;8>pA3Dwr!BQun(JK>fAcObMN`vPLV3a8qv>vnj*&yIiI{d9 zBl+_432PiGck`rDrq}1O))qLqbaQ!lY|}Lt6((rzw)?tiNv~1;-MeVesD7x}?ImlQ z6%Oz&qQlRke0Udg`vfB^#GUs3;azN}<#ARs#`|@#`(ErZ(nXPlazc=9*z;sQqtJHWeGTb_{hpyC~q+10h`v3KFLZxo_> z-3MiLXZ)1`IxWm13ynbGC*pk#AN5()o1LrnM!CXXS~eZGwkvV}n7;!mGrhTv7ypsg zUE!G&ZddOQ_!@^(LpG-@$!?<1h!Q<2H!lrc%rF%MNO8CAO`X1wZ#ER>mX!PAUJV8; z_H5>8p$a(s3TpWdhyG)`;=#k;XRke318H$L7Rb!4+F^_OIhvzzrE3*<39$F$OR27L z#n&jKMlHr=YVBubqUI#Ck-Z3F9&UC^w;FRJ0cR?s6t2{j9%FK$OxJax9(ui`CmF&P zk~OSc)vA->WsWksQn^@yJ6`}5?BpReyC%LH9OINdG+7T$_N3LbXQLZX$sG(|j6Q&O zk%yXV6cZy-C5n@)PG=h-vHW^0FC|h80 zh((O2CoKr2jIoFgIe}y_)aRQH0@$kA%nQBBpW8!<<3n!pH=kh{KKHK|TEC&bUDfkH zFW_lJFW=k-q8oFmt>ja*A*^+Nco$1MeM48^KfH_6wQ*G!{U6>%OjEEdF@Sdw%P7!N zAXz2HCJ(&i2;ag3&x#)Ss{nQ}@MDWb%Hi8RgeRiesM*5vx(u3~wt0%c*yF(y`hQM~ z{SEh%e~}gP&usj+vH5?zX8fpn0LJFls(0P2P_e+MLm3B1SO9)65NEsk*erCVqAWEq z=RG4~D*t5cVO;`kv=m+VKXm2F3fh$MA%4W>`y)e7o49a~Llp+R zXP3@wH!jlM&o5rqT_0ARDSj>TmjnNh762L&X5fJa z8scTXjrY)%f*Y4B$$2Uns$|I^992eCW@}gYxoD?obtRAN3WmDok(bj^cNCOGne4ex zI<(LtuFF?&oCYnOvOgn&z%UCmG$oG(?3avJBZwmWFm-1(b}p{Z&xgNV1O|k>t%x*Q z!*~EJV0A^w?JN8i6qPuO06qNr_H9H4*bRameFiRVtOsEzi$(RPq}T?BF78C>`f&h@ zXB0c@?%p#NMFh$#)Y zzR>Df|H$*AzH$pl*-?Wo-N2amvn()xYJE~ja|T3jHX-2#pjs1A1QlAeH%rE`;@oeB zS5hR`3>5LW1IY|sXXMq`yw2@}cqoR#jd-2iV(7M~M2NMjlU{ABEq48zHARy5scYBGOgTwkwiXGotG85W?0RGk+y=N^pj<;Q{BI z{4C{jAt-V~g~`n@;SBPqi+Wp^oMWp$r&dmq*<_l*!t5ESF;4<$Ex4(5(Q^k=}{V zR4Hq}=~6w;rQ+SS;WwF>X`01oUo3Rv5??gjVA8P|Y_g}d)uuW(Rzqo6l2Bpk?qePg z!X%5~k`W*3y;5)AsL)i)-L@t-W9$CH=+4vhY7Ggs!832$pb?VJ4fAag5r&GSYe6hKcnyr`F*#Zvsr4D7aL;=%URpRMjq_%GLO} z2-|_EK9uwd)E%?wbIE>l^_un)@PVXyHZ*1lTmPWV$y2$x2RDoT@Tsxjq9zL6Y5zV$ z%AA3OLZ0RnJna6V&@wv8s8rIUi11Z|cZ2b~6Iq(UPQR0RxFn-5!Zj|f zV@=$dRqQwk*NoyziLP_PJ*;|gsaYl$ceVyLZ+W@Iua;>=9g$oK92;%=tLc%LiEIMq z^_BQ%)B;caf2%Zg-Mw~$qn)coi+rVGRu1CgFfDH$MTMs%95_IH$Pi0TOxDzGxfXEb zE$zmJRc*5|fxC}rMKb4k1Q)b&9TxK!#T73P< z1}9y=DG`1@Rt5H9rVRl|EYHjM-1NRBcnDDeLEND(&MWY%6u2Z?R@a)euZt#;zxD=K zxhapm>?70$xSZuSyWr0sj&IFxe@eo7chl42zn9+rOYh=8lkoqTnH9Vx&;gzp%gBzJ zjD^o=9GhzDBLG$T`eJ|~rKmSF3B-id>t}$f97iga(o%OXFuHDao?Jcmpa%g!_&?V8 ztxtQHbA(O*EhG<5l?LJO+C}O$o?WK zte|kO0WbUKACR8&wmd8*ISK)`FYsoQ`R&obOi0jp5$ITx zD>9{IjJHC;A7bBvcjIeG^7N$e!V>9INV!21ULxTw)1u8bR2A)07kmezF#)hh zM=@<2MnazZ(4X(yYE{-4UKN#*riLIda(E#sa=l{8$WEfR^Cug}5i54~j95{G+_x~$ z?5q8>-zqXKpcFQWj;pi8j0V;hC|PdFMept2mQ(}Z5PH6(IvxspKBYycOV?o2DrkLR z_EPm^e196DxS`yM>v8i5K_~TZiB_`{MHJ~2&1Q_K$X5{AJsgGYI9!Z@n$2f5?_^tj zpL6}WFT~qUWeSNU=IPM|D@@SeF;Nv)O?8uCsw~eW7oOvFUF}(O@y2~DtakIGz)Jda z!QeHm^`q)rX5B&9sagzX_~FIyEmVify4Piky61ipD$H|#mh!1mw{Ga-+4tALejVb* zp_OgaN0iph*^S%c5s@V;-{SfgDsONoqnj3PjMF`W*8R}EwqyHnXlTs+OcBO!`Dkl4 zQHbEEg?qJ7cl^q+Ey%f4i3@8IHRSM~%cE4NOD80&m2WwtlmR_71_2m|p2@-ICki&f zG5jS(fy3Ggi$pHw8oH9>rh@mQM*9))G^2Sb%sUy_GnQT21FlB;X|&X(5o1>UR2hc+DB)?3Z^{_# zJE-R0j29WUYABjhqT7>_MHIlj7N2-W1-~OKMUIXyWMOODoplbW!&4FuKG#B@O>&md zuqPTn*VXJNjp7+>Ptags`M$<}vioZCmREd7Qy=JXY;5e17-NC0ESGo17z)XtZ?7>O z#sGYX)^m_OQ?>N2JHF~R9t?RoO1$e*{64+n9sYVh;M1PkRw{7jetUA=RV*26cZ95a zvG4T0an7my1NKN^`#H?!w8!nY)O-pM4JoL%AiDE_lu16FKRu(?VB1K)k)9Jh4lY|7 z0IOFU+p}JQ3LsUFI&t5(=Q9{}5~~xSE}Fgn39E;&&+l3Qs6_t-@#5bD@!tmJ|M5cc zKNK(^P!M|ADx#3Q2)t0d2E&tRk!guGtnwrst*j6q3YfvMJVsT=$*A)kgIazMwt->Y zR3Z|jd1n3vC%}TatX89%ILM4C1^G!Rp=wo?3~jBpT7fCjN5G(rsMvD%XOWy_25A$b zu5rkRdC_lA#N|F$8d+nD9oS;_0(v?23BL-OCjKpUC!d-v|DmZyRQ1 z(SJd_Xr=w%K|lTpi_-iJXi0z35nr<@~LjPeAlf*$)>*HpcTa*+a@cDp6 zCG)Jbo{5=^`8?~(>Mj4UrS1FuQ|BEeTQjkM%1;89FHVPiL8S_ls=i&FT#@E(@nI)~V8J)$T4W9}v$02Jjs z_56um2fv3jCzUvgHotuw;j^s6new4X2#@moQYs$bCp{oEnKB zN^3`z4-&=4Z%poJUA;ZM}a$kc!Zs3IhyciCBIR z96nJ_QG#`ZWhJ1cfa64Xz;Pl&eZ9+y;ye)qK?nO;sg-5IYmPo#)l>*m4O(4b0ep$n zMgf6&#)cf=DQ3J9<6)rZC7}i)3rEo#j))}$r*mz^=()Ms(BK0qaeINe>A9Kfc+-Ld zyj~c&n`9uHBq6=Bh&?}8i^lVE&`gdt=&rX3!gQFV?Pi~RS2bycg(CDmAG~|0h@b=XW`GL4tbaQwW4L_$7*ThZn$I z%?qRPi>hG@7QN(tSfhdhuc046yvTi-33Go+i1&#Vx(^fHR=BkZLZ@|+mz%Yy^ALc7 zl30HWSMgS}K@vQm*>8)&1`E(XpjoIol+c?9TZo1~ohO@*EJDYQP#@f;mgq;%w>_D2 zvDDFv2v7vv)m#AXYJluhjbT7gR35=0Ju3w+!n{d1d7G5`T~&0^?OTD?I4-P#%&Sio1@Tq(>rP=X^*~69HMNSAl+O>o`%dF5YeP)SJon`)RBd_2 zsrXU$WhRw!JW_x+_eA6O(RFWbBD681`uFuW&DJg1Em#is4Lpb9%67Xwjp9eu*L(jM z?t@mhCf8Z^3+lru)n5?xO1bo3ADD7BpwmlxzX4IGkv5ryp4r1{v6l^cB;$V#Sg;J% z=+Os7`t*l+(S@YA8Go>`r`fDG=Yq1l*(JeDQ9;M_d7f?a+ugKY{OnCV9&nkWjIavK}n?34&EhG*HzVojpzY|V*~ zVgLUD?1{^N=PQ826|0K>5HD6yr10#!YZ`sC@1Z{U{7vPZwxdUR;Hya3p2MldlhXu5i zmE{LCgGL2StA~@*WLOb;dxK5fJb?yf zsQ3DG1IGmbZI(1n4yFN(B}A!Nx0wqrP%jomP+-G1>((4KVxKEx+gX0qutLn{5f^SHshN+^jmjaY_4r_)YXgoHEqdMQ@TG>g>a|+t^mFIwH z<&j!SyP6jLIU|5vtskm2n=K_jJoatoG|Go;q2u1tDG@0_Hxv2(jUFW~-^ve+)FA#z zIL{ez1_;7^g)_O0zL(trU23KtSX~?xszP-xR{3KWG7Cp+(mORm$92WA z74&Akl=SfAfFx|gfXI}ci}pimoNg3%PRo=aRAP2Xega3PDrvw$_xRbn_!)B5oK`mR zmsb23RgR_Be1FrHr9klRAL8oj>sqAc`U!U2uSwF=xh79K2C zn4z6C$ks@MAETlQ~|EiL2&*#OJi zGf2A%Y}fi%EHUfgmgsz#-$&qHW-WQi!87(Q!+3$~#jC_<0}0!<+MAd)GLaneFQfXt z@&XfSo)R`&Ut9x4nyB&FFU(3G#k>uVKF7Kqp!PUIdIyom+8aSUkSfq5-6NDpYUH}z zu8RmQ1=F<_Ds4$!I?-m{3hH`;I7Rw7)c$x2&EC(M6H1?C$e`DfsCBnECX+1cawBDgfOJm`^5#KvkiU@2X1xxBwf`5Fo7T~zZx>5+K7 zOs+f;pOQImtxfW1-%*OqZ0&aN3QE~A$rk;~%%ifnE&Mlkuk%S2C{U;nbj7mX^J;Dh z<}bvKu`RIPlLi5*t!iLQ0d7(s7k3V}YCvq(=Tz%`#AbN2i_!uad6(RuaeKYqUz`7O z7y7?bFLDEV9dMwRoKY8-UHQo1q}y36qTsx0yx_dMhnXt;`f@XiyjQKM3BI8_YtL)# zqWZPR(YTy_!%mUEJwjr4s3c`bN-h$t#_fEN{U+=PS^lx1_5*CFdp!x!&b5 zyAp3rBe~N&|8$EOl%oUm7uAba+W#dPAbyRkq~j<_0;l0yF}cGC z?DLC4>#CE4K4Q_6U2V$wy4;4+O1&T*%4GXCF&T7*T9Q)Y?YMw((<4U=$QlEXnSwbU zk7<5fKV4X?`Jp?})|cJt>@0X&IanTu?fHeG&^vIVI77xl5D;a*Bn7Qy#0V3R>_9VG zUtGh0uW|z6fS-L4M|dtyog5>&8~?{|p5t}mI4u|;8K#|^&_Kd!Td;`Ro@m)C%>|<8 zVCws*&phk{e9}lTN4QLMC8AV(Ydlg;@Pw4{#M`^{9tBW``bSPbEihTX$=e% z0M~Vi%#jsV32O5@(~j52MjMJS;8j}y^`b)5hkDVsX)rQ=!L}>gQCwwKf6ySzUo`M< z>cs*Y%g+GJKA(#f5GTfmdU1T2oE!sA_;=}~rN5=5Oy+4i5K_&{N)aAFy=a<~lP4U4 z#J$2=x%*vA(r%OAc$1!CfL<)|h4TCKQAL~9v~k1yLV@pv0=0^xIPJdP`4MaBIdBh9 zY{T(DdP|v4awP4=tU-mxLt?OJj<7F2(V-{JR!kqRU)>>7aEGa_w+eJZ@v11pP4=o<_V`N|s($tA}~2@nK!W z+h&1C{?*C=uG*#z!WNj|46S>QBEpy$@MO@!^8k6zIFbta8OHt0J@9HBHs#mW_+}LS zg!HX4{u@*LukC?+CvxGS#RF65KLnOa?&0|0XS<(aS~<2? z4I72ndxpbZzR6R{hZL|J%hqM|0NjiCq~d78iwym#^d96jlZ6F2@#nSZPz;${(IWKg z=Q7A@E&T$EVT%A)<&+H{X&zaU)CQ*js>M@@tazd(*NLs#f z$=GXs90w1SD`pe#SVPQe=$a>>8!G*4hPrmkAc_7HFrF~z_MN@oR26fvwXmh?T5iXJ zV!$o4K&zkQ+vD4xih%hKum&F(>%X90{I`7k-^c8KQ!jD>&`DM@cVLanR%3uS9!vwL zzo@j__2Ufud^=FyAkKghC54tF98V;w-uIC$hFI_QuKH(E1YLcM0!*I%Kho~9E6+4r z7dGw=!QFy8!5u zd4TA*ZplLvDTL&zRefOlK^PAVOHX?3YCY6H`|+QBq)%(t+|JUB?qiZ5NOHj0QK>%I zKvnoJy7^}$qP~j-M%Wsk742#|1XZj^c~1~5fC6B{eH@a!$?ZVpp_K^uYZZfx&G!PzQ+a2EP$Fle4wpAHziHlo}lW6 zrzexXwo(EZ3qe))Vya3e@iDq4_9t;*e?BO**%wHEEkSadkziWGo?ngwzq(e{%*Ta) z+9@=SJjRA}$j$RbAJ(KzXTd>F`@jVmj@^B)N^jH(QTy1JC}>C`o_>w(t_VoNZLz_< zMCVw`fHbUlaTvczzhn*5CpSN^IMe8B%3{&Gq234ZAZk8ddcndyb5shtZg4H9X}BwBYF`>%>{CivdoZZ~~!o z6v5_v`l2MXy+w~rgR`hQs^3y9f;P?qFJfs5M0)QuBVn^t$5O4DEUr>y_8|*+r|6=6u%qBKH`0xGqY2Lr-np2;ig|l78-lqy z!^z-6D-at_e91j4a813DV$%%d6{^Em}EFbmUZon|=rGH=p`7)Qd--(8W9v7WU^a5dgr_bO5GfM(6MJK(t< z?0gwW%UH%oFUL;sd1EA?(D?=9iv>FHeZ$#KCsLfUJ4*FjPv9$>FIby}lzr#!{?ucQ zk6p#`x1%3_vE>8sqRsFwFGf4FZ%m{A+h#qTwfL<+pS0S4t98Y^tM4}be4W`$N_mYb z|A~F+1Su=h?(1S9G>n*()xk2|o~mCNO;Wn6Fg#nRgoAp#?J6f#-BFXB;*q-yF_Uym zMZH}NVy^fRcib-ss0zx$P6uuQ)w?JphVvnAAZ2cL4ybZDJ2rik0zOz}0)~s)rkj^6 zJA#+NNrYd0ZEXMkrfo!y9aQ^|51xNHIQ=hO>_2zzy>HflqZ;0q?4rfil@ZZ~FhFp6 zVA=?!viL-h=nfPqcFUF-tBIiDy{B~sog$trpCD{a<|rd%6ceN73yQ-e5QSU?3~+NuEQUCPG`GmlhNiKkzW3ZTG%b)wu!>3v%`84v zQj%ik9X#l8w3BpQH-n|6ZH!OedMdP@PTh0LBExTvbUTDVb+k>nMF3kXhMNjrma zTG^su6+dVO!y|moUV##gsV-MtTWxJ=W@}WVD(Y*W7;GM^<{**QCAs6EWTY?X!wq+} zOTwV$>+wokrqq{G!2krO5jg|igVW1Mfo3?#D)u`w_8=-oBx4;wEtlBh-^%8ZJ?t~$V*jjC1Y!SNj+ctt(YKc7W+924GgG_KPe z?~XdoiM>622qPa8k8e(QH5<=w_L&^WmrP}BC9g0*&m9e7NugZxCinVc8)B=9xE9rq zm&@Q2jh^n-#Y~Hf0Fx(vaQ3M`_FHm+@1iS{8K*0$U1D2~($7=kb3-MpibrGRTYg28 z)-Q8A6!4G;bGv#6|VRyRyO>b_kN3+rRZn%CUh z(YAgKrC6mbqHfm7KiBP2EZlNNwdWWvU-makJF0cVZi#}(6r0;GI9l0cpoW_gt zjwzc8{h%ensbEJvT>gv24yU%<;Cr5J&{15bQ`c#rHIL!p<-)-w&l=Mwd0T#tbrF;C zq10|*p)bb4WY|5vD>LLwZzSd$~!IZra70yx{*cU$}$_&68G|~Y2bO-PCLs(;Tz8@ zQApxFoy58rHGa(z&gUytjEBKsp?Qw`rPMDP4An6c1%?W$^GHJYYS(7(te7~qJb)Fe z3e;#|A#ta~inMg}YGf2RO9u~O**Zmt&kLc~z@7ky3r^JL%lq}RRB*#|ja68wIE`Cp z>%nArCpZCxo9u*A#{U8-!g~?h3RP=NCuc`Ad{g~yntOvAOT%g zclv2djOJN%!$YPB6-8yskVaZvG4b+o!={&PvdCt##+H6fJicJQFRjrL z1lC>2Rxg|S5*df#c9yA982aLv#jrDvz}G?FGVI0p8#2-Xd62e!SAb3{lg48|zz>9! z2%H^q0C;t%LiS|Pv|mnDX(&Bt`Nmv>DW{S9eUg&z6wWMdw}BaZ1yietwIpR8-cd>e z7e`oVY}cO%Krj9TxsI$EzuaN>E(j(Spa%89eqn{quA3f~$LdENDYhJM>JhP|z!c`r zfy~CeJSxR2cq9=To+usAhcY&xlxv-GWy%SO;4tfexS_b#3?MI^Q{(IramiJ;s2H?u zzcydDhe7%%a;h>o6VWS6$%g?4-A>H%G4FP}suS-H5sJV)FzHmKgO}e4)Ew~48prTM z$WpT8Y{r%$z@qUB0x8k=Smx*eUN&6ecX}}^fX9tJ7;aXxlA*K1*~{~M+O33)=S+)? zz9LF%%MQfi5A@;-QF&YFn)UEUeW^~^I7V^*yBsjUJ@#=PqZK?EYh`>UB0t~n^kTyZ zfL@H0$*cv?i#gux++e1Lfeq8yVCR5W=3)x_(2(hcdo8(T#QBzZ!r<|qq~eKjDoA1i zIMO@tiS>$uI^m=6=0Q;9mjfJzxgJan#Yi1kOR$_ zHRIR+MlUA8pLm4w;Lr0U9)5S*iu&~;gO@tRO9JNx-l=iG@Be#-n(Eg|vxS@l@yDnt z6`mG%e8+rE?vHlH_V?# z&M_L`SH+a1a7tmAmG0$F98{C+Y84>v5Yf)&JiHc(zyuj|0rcVxI&)pCRu`EBLUEAh z=%`4b5xcoG#pvNl=4LTC?S}C977cvD+9#6}_``HFV)YOxMze(JO*W>u71TJJ!rhgt zPX>Y=W0V$lykN7MzUgDp1MH;~u~D$4WEc<0d1n|ykea7o!VDs0<0s!k)WorfusbU; zhz4PR9&1S4W?5OXep3rYBR}|O-7lj5U#3tk0 za5&#i3n|@6YAScX#ie=ttdyE`n2Hp>+c=F>&JB@Sy4MU(MXn$Ogs8DN^SI`S?ylfg z3KCfRPYVH@Ic(Pk&;IRlR?L6YO^t9rvykBrlzSMi&#t!oOT4K{$Qqg?a z5BM$u?Pg}LvBK4u1dta6)GN1~rOehs&#~?z>VahQLS0Ah?ef~>ap)Bmr$06@JT<#~ z8piIioBOv{>c1f`{wq!W z`QOvjEopStW#wgmOjDbWTyu$j4cdkEby*$wQ!FSAvvvR%MvNH)R_ZRrn}4j-5pG|;$}SQn zS@-4#@FC6vR_d^pyZ`e_z2o!BHS~{_`Y(U-{LAv{3e7~7uGy!m= zfSAZfKo9HhpFE$?^}Hk?n2szNxy+-8<| zQju;S!vGafETH_|I-VdKyb$yYgxn2Km5wR=`N43ba3KROK;h9UwV5>g_k9<0$1+1m z*29!@b)}4%lOtbAw#z{>Tz+J3*oEAz*qJh*sL>ydlB7NV^4eZG1rsMI$3KOo)+(*B zia#(Tc5_RR;Y?hj?p%?=199lgfFcW#&gAc}JEIf237Yc!Qs5Q`)*>-}Mv4rF^fKu) zk|YQstP*>0hw?I+JU>SJGee`JwMx_6SG09v2zJB(qm9D1U@<9wHWn?49ZF&=he6&e zG6=*$RwR`O8PJ)h?FL4E0V24J3^A2hl|L^hP7f6vjRBoo&_2G9Ps#d)@O942`%slx zvYZ0~(=@OQiSSMMvL6sTR7`UFEOdRhflXr;#mha zgl@3`67hBU7LpgejQ82Sk;W-8dn%pQY9z0e@`$jrmftuhWD&WFueBd__$SbBy~A!K zzfA{Ktk`g3ODli$7OQToNh}FA`Z2tost4(D;sVRYT6-7isFf3cm(W5#j+Uw;uCXFS zwf0FQt!!*Rea?foZ(O7)Pcl(2pla^z@_36BExd|NepR@aX|5ZOOeGT@H{K7}NMnY% z#0grgUP22`*rZaw0%z$_oeJCVLj#*R zSJt(PEyGl`OG=U&^oN~=Z-@iB7bFsjz*V%rBI=*PHVf$TdLfkI#jiq-X52MT`_(EI z4CmAw4Qw}59~2&%)^l5@;j@90?@_AGJvkj|3*19ZI=epF`g}|9&X-4onaw-^egNSBl7kR-LlV=XG&%O|&=u_}Ug(^Xiz00x@#<0&NwZWD znrEgv%^+6e+jzOXWT^-i3?0_BrmxfYhU#aH?YRO($(>b`s%3=(A@dnEXNc=`KX`vr zn;+}KJfV9N=uD%4@>MGUC`QM=tJzIJ{^%Amo|CPIFzL-W>yf;ye__9^HqwW-V!V)O zD!&Up8i&CRJqpU|_cp<#rI&Q#g7Wgv&N+Z8HhH9hPOs%^*|O@Qyi)b6>%3)5hWzaZ zGh$i5e9f_q7LST;oBnFODpKvMMHXj+SCe-&?pO_aaXrKs%c@GmtFdWeYAI0h^blT| z^J3@C);lgXGw><-XZ1j>T_rr`Bw8^ELj+G8?(D8uez=4+8VdH^( z<^T%gyg>)bd|^&n`oM==>$ucnHUk1@(L?2ex2AdeX(}MgoFkUO0 zZ^aS=m0%N{v0=~AouN2&=xN;wj9ZltPoF->W~0GmHh6Br0;Y_YHFyZT`))lJBS@gG zhP^o<)$MQ-HLWF1&lA_hYw(SLtlO&BQJU6{06#p$#X8ISeqRh@MY9N?_kZ@i_dg;} z+y1WLQWl6H00MXU(iZz%?^3|@$EJ8-b3&~>wF!o@IBk{b9kQ$5?lL$%jIQe`s{B`} zP!Ze!)=OJ7O1^G?U@B6QF@~r?D2p`wZ@}E&qMedI*BO8Z@_ZmEyv2cf(;E*YaR+6y?4r?fMGvWNJdwx~; z{mMm$H;RDTk*{gI;3qR(VK**HcoY|%AT|wKBaR~L>kz;5-t}k19U6(X&7l<~tH1(l z#rkU|rCl*Ab6d#utp1F)Z1VK&^p7Q9;bBKrGwB?d`o7mcXK}k$N{;Uh+OxRQf62U- ze*-aZD1AvQqT-OpsfW{YCgrn|e2djHzA7w9J`4^_DPa)x7!^)(Ev-2#H1cdlzmpvK zSTvF$6HsyXF`qXrpRP#)T$Ds(n8BX$8Y!d5jLtly^O{@dy(~|?pBsx=$}uGf>Pm9M z2MOlO3g>ImGCg6*i=YkCdB_*^%lzxcU+^=Pt}`Nm59*`b32bYM2ca;iqaQV2NuJbl zo%!&gzvvO3ghI7)22}9Z2T5ND3wn1YY^N{zZENIgqV3Z_f7eSm_Rzz`jLJ}I4gyyZ z-yMETR~wfbk?#qvx$FwC;(lFqXp>8?l9Is$iMu8pJ;LL1Z7pv`EY_fLq~Pxw{h2h> zYV_6l+4GXIdkvfJ2i!`DhSI?*%hlHbt>kqkR~}LPt&%5h4u$#A&n2#Ph9N?y%J@hT z+as4QfWvopbFp%W(n?Sp21vc z&bx}4a;gl$cOd0big|9o)&+%AhG1$ZvM)$Ef>gge*93j!&cccOiDIP~4rf5N(r z>|^s@u=G-W1|3Mz6)IVeO^fXPwd+eufG1dO<0ei~( z+nKWe2cR-QMr6tQtvd|Muzfg-r)BC_DNl-wn-zahPnIIM>r)#bBf>n<&|R&69eWNR zQQ+|TJtOk<&l!<)#;4`Koe}wcYW^Xc{eL`SL;~M<@_XA9z(_zKn#wsq!}puaMiA(& zYDuI0=i2?RzPyGum#_ccmnXH`Gu^IDTm6lNduG}|xS;N{xkCbqZH-;LN@3i5O!0E2 zuwh1yG8W*7k;);#F2e5f;-bf^hBPFU$Qy+3z&bwYWN{KHWFRffA-SaZuQ1(rl5wtL z;!W}CK;oOj4}z#aXGA#jQQsN?KO%p_WVF`#7diG{Ub6pq@SeG_9p&<4s{RMydZ(4~ z+W?H(TR5MDu9G?O0j#MSlkC8;d z_~-SGS`WloM9PE$O7!9G)u**<8IfQcrrn=K=hM;}EKBa;Dn(RkIElXbz+CA%q~G3(LayYh zg}MnnV+ldjr3biHd{lu1)+-Fr#G0=zI#|Z4ePUvlWf){HTuE+h(M%{i#wUXrrhkZ8 zy%WvvexB!-J-u(7zWtCL1!XUQM^sGnPL9d4F2|2z>{I*5u6ur`*dh=nbod|%=h}xF ztI7ooxxD!!`-+mB<%1L3+~-kt4c0J57N&iX&KCx6I)F1 z;s?o4yi6#eC}@N{U4iB{PY2hhgGZ;|T0l}48u!1a*#c`cPh{uQhzIeg*4j2=#Ie;c ze76%z2Anc7&!6N2zI}RA*4)l4HWa9(GHYbQ@;5?*+Qo4hS|=GHhVWdxuqB?%_aD%6 zeFlyoKDXwCJkN1Trx~|M@N1_3G=VbT?BS0Kmt%jyid|b1pz!)V&eADimG*3lb}k_# z=6+;vbh!`8o#dsvPR$*@BuXl^{v+OUd}c;O6#=ti%f+B`b)#@27$n@}wc#vfi02oq zDI=ty{=RV^_Hw^WCj}P0aP{NCb_|p~*tN@%*;wgX{XBfbS+k5i>(4K$(}tGukE2yu zxVE95vHISvD&m-xu+RDRbcfUeA$%N*_)7_IGHv1(^QK2#q`ED?m_goZpZO9d4wiPI z+^37Q63q5-ed`VfGth7Qyg+fkhFZ5SmiP&^Egqs}3$qFy08jpwxQ%Vv<- z-=j!!ytO{#!ATa5yfW0X5uenMMAwvcmKtU6Cs&1(j^&zbYyf>kU_gJZ9Z~XcBsL0r ztWj(^(GJkMF*9&-5|~&QIF!EK$D_?1faQT0WX!8%$a`A(pvk^pY(CqcUxao`)P<>t znRf|Fl!H&ZVVK*&x{&5PgIPN-g8G~<8w&S&LM7r!-&c4KR-_X-To#KiB&$6~Wnu0K z#Uep@R4wzWS^y#X$ze3{iWkU(s<2krK8(EXJahV~pr zl;;cO0{d8O2&Z*kX0k278$)iSUPTMGnX~7SBaojJk&DXR{LLGa#Efg|Zi!CNsrr=d z!ix-()a145#_u&8N(g!31Y2;>g;5S!2u4y<@M+u>pEK`CQQL`p><(=h8$@|M3rhXB zYsQGyL8I)4xI%pQ63=`QE$4-3L3z(WU0Xk=Zl0SLgZRJ{{8XD9)nY*o%;63s<5V7M8wTG3jsuQHYR_YD z91woA;M{8YJezpBcHpj2BJ;}sNt~(5@#RnNG=%)r(arzZvj6(0zJK1Y{O2|M-%LiE z1tCnXjbhr3X(MbIVJF$(m!6+snrn%0zmtr@Gw77w4b9XlPGnAJq@DtWjHi2_w37qJ znr;HaXpQm>dSgauk}+pKivUPQs!_Hu_sm!y%T~?K7oLgh7thR}JQMaNwF5SoVnASk zJsTNR76hmvm*7Svv!*cEiB(IB?K@QT$~6m_+m>(?KO42xwz`JTce*WB$*07l!qNuX zn(D86tiCjiZe_aS3X{xODRra9$S8HpK&F$OpTMA~rFN*RB6&m>8UQ6peZHXr{fs@! zZF3(0B4dtRZq=41(9jsaBHi*bGMpKxFG5QW$_+9yogtxcLNL(0H~I&uI%FvS{@v}`%_@Rc_Td6W;N7}8X*Gu?7b;F z&Bjx(B>ZPW0Lj<^b;G{N@J=$WL!B`H&;yW+#@*9!bOw$z~s2v@ySL*xF za=~B*s>#LEb;Ige|6wIUBnY-hH^Ofuqf9gzINn!^x4wC`Zr;YZd@!K{8V~>e6Pius zj$?8So&slaHx~^@rLQ|LR~%)pZt+^9Z46d(Is!)~3d%2bNxW8uCV3|x;Swm9-?W}- zhp2miQEzy#97p5{03>5_ehzdA7X`dUcI60)M5@6Z=hyp`{M*r-Uhty^fyR^UGn0BO z|1)XjC)If)y!gAFDg|s?3C|jHn#-qaqlhE2jx6J3Oc9GoyXJZ#MjQKlHhNxSAY>|H2hXo6DH?0^g)uVUT1-6(pgngbZ$?!-pbY| z4gwSB?IAG3pDlNHA!7GX@?nj_eXTNzYYCjh9k!sgUI*7Q&I9Bog>WFeqdWZURNgM8 z4K!5_GOjt_94c%tdKgz?HmDCkGAayxi}c9ZNae7u3?qA>tcJq^X$E}m(+QP1hmq>U zRXCGek|f$4M-Y)10L^aAD75Y`$xElBRsgh)DnZ^x&#aBekF4H>BsRbceJYa1Q{NP2 zx+Roq=e^R_4HO({9hJMEIr<>&ydsF_C@Vw5ZZvisyn=5AP5$YqIn@%X>`1>@bj}6A zhVu-LY>ZM%B34F0J0I@V-V+x;bi??58c09U`f`#{8#r$nDr~F!2p=?60yrG z8F2JiKnGTY+2@`A+W`*)h7{?qb)xXgz4o6x=hv@*UyS=z`^u~_?dlC6TtKccEKL9$ zC>vXgVcvFCMYhqbn0y~P!N;b2cAn|T`QBDhBJeF>oL*K6B4~cGq0mfpJIsPqqUUA= zSKA_lrQ1)r(}b9HGlP;uY|Any>@GjOAuQ{fdXm9KPwIYjKUhQxILAxF;_SaPtB-kQ1&631w}QDDwxX& zWfOF<_;qMe?~eOg*zfV|V>UnV99u}AG%xdz90q0J&^3U2rWcCtMlKbF9TJDnfse3Lzq_lB`#c7Wd%F`06{{aW7le@RRiEn5Q&N@{k7bma&=& zQ{2LE3t0#aBvb|qH^Nh%Ed_W6aEJVHx*-qrC~N-=DhJh1sfn9%*k^pgGqjLE8oNy5 zvw+}h?JEL)x_C!#h(YA$UZAA#Dcr)npv+7KCq|UT#;Wt9_*h}4~xCk7W5#`$Z~EI+%wEL`TPkO&H&`~LS%r`~ zt9h2x>)ejLV>z%7LBk!Xcot^smD;}AX%HTkI+q)esJSN80^>@hdr!% z*(bh>_R?y!@lD#;@@v~aA3h4G8^|vJM(5uU8UHvs|MR*H5E*|<*6k){>YtyrCzO({ zYHRRH#yLueusB#5td!+KABog}twwz?NoVew@{?8FvUU%{(5lr+Am}B?ANwVM-e{R( z_tGWEhiMjUXGxd##6$*VzE@{1+F;n9p}>qRGY-hqtzW0_ckJ^J@bWtL2>zDH4oeom z0@9^@)NQ&eXDeFI)5FHySCp&i(A4NF;bSMoc1nC0KlIp^^v@BqSgkG86J0xF4J~kb z^!cK!=I6-JsNro&%)6OFNhnq|0Of;T--0RYj^!8#vwirn*i!PL2iy|rvoN<6L^jGL zwz-o^G9qHh#6q|zGL0~5sGikGN-`bidbf+YKonqh>J4IBrHU<);MeqTRERIRC)H(+ zBLcgAX7mW<*7^dMFdPP&yIRI?qPhGD_-RGY`-@klhS$2+VXbm0?4-ZfB2JJeesBcG z7#;*dXpzGC;O19zr2INmO)$jAQEoqfPt-wZ3|3g};$?UVQn*cn- zq-!$20e2aK$T~t_DkR-%Dd$coi)w9*L7^J`y@p>qZzs|A?ssCiS`K>Wnz#{-#S}32 z;V*m)CvU`#vItaFKVhC;@sE^u@B=<`=q5mZ-en8g6`(z_xF@Y0Cp{-*i=uTIKq%_W zM<2W4@omwV97{XY0N0Ysfdwg0fDqNQfkNob5sDtJj}%+ykz^Mobs`?4aj=!hI1c0k zJJQQkmy}b0yRAw~y_$Rja;wgEC!D;d6#uAhjIP;y-S8_4`p$Tn1?N*nT@~B@Qk?du znW3?9nt1;>ei_zGukrcb@9bwC-E?;?$G^%Gs);! zp;V*N4q$}JhZcGpbui4jqkVh+iu9#|sH9$N87A0&G&&n^TF0@_MU-jfrdiQ5#(9Ty zA8NBL77w_;RtNPv@(>nDx>zO25L-fxB9FT96PrOscpEoHwFvWkb9fh@R=%wM`BF)% z>lg|DPsW*n7Z&kXlE9X%qGjT9;VhC>`c0PrF7M)T(0;|l;GEE)Dd&>OyDyXul9H-u;5&W*b;)d ze+Jz_$$m2|&i!IVQZ&BHA}pEaya^K-AUY9CaX3C(unTmfL%NnCD^%F z=ra!2^j=1B?C(McslwPf%3J7vlG2eCMx=jQ=x1|H=#Zzk((IUelLz z_AbJ-{uV6x_Ipj=s5-!!hC5`Gc7p6pvQJOHGxHOa)526Qy4N6 z&nRZGvUvANZ)lSEwK}KYns}Uy#ER|Ch-qcrN~Mkn@+_(ksrGaDKX~*2FB&N=s1yR^ zTriDA$S|k`T7WKg?HR_3;RRcb<`I0YTzR_*1tkq_K5lqzfhSCFc$&S8e7DPF9?im86}F47gJ z$?3@sMu21q%Q3KQj~Xf{3|j?791(W|LglHLPE#rOCfRq`m!9T8ybhidmNFH(=4PZ*gT_k8iVUAE)s$G7-Znpu^tc=Ii!$& zCFxma?~}&mEAXY~8{iDG@-A-82fJpY3%YF}n8ZN2UU*xGh^2+>t1gIW-p)zd4^UnY zC~VsY)nLT)j2};$0G`oU2{z3cMYz#oU1m6vf`~pgFSq^*ZQ&s*ReE|lL%VZ!xWSl;*PDsG+#dx_3FS=2S zyV5#3?98PfVOx?q#qiPmQPyqx0jSuegg&Bh zJ0?Sz|Mr%KoZXj*`}!6XEO)OECoD`)puN^Oevzl6OeHA}O z<#Rr0^Q|)zrUpz{c8a3IcNW0$4J}&eIguMRQIga!ftG)Sdt3iC^u^{Q?*^*B&riM| z=Qg`pkc$Fty=C}Q+JNId4Pt|r)Jo2trLS$CaJ4$4;lM8;*U1LqjROqs-2i83UOu6; zf7kJTdaq=Vxi*HA$SPCn*kgv8wEV~l)|I+a9bz^%hI1=VcQ=XbN;;Dp$yLTBz_uu$ ztg0K`yaXzPt6#^w9dsn^qYdd0iMIKY#Q3h#HIX@Z;Of3CF32`;UXjyb(en=Xw3Ul@mU9)=yM{2l2YH$0$#B-0;I zK!TRR*E&mN-0}l=ekfgToXSu?6X`dR5i%H@|3xH@n&>OWrrr!?PXW9AVlEBfi)C0c z^8klIGO9V)E8mFXgQsAR`p*6WHqN|@bcvbHo87LqI^f@C=a&dRMXrUKg%3lmteQd3 zM`1}5`#71iXBrdk3YpXdEbKo$Oz>XJvhmEV0__94wSv5u9SS4o0O3TG=MU~QSuJQS z#pu_hk#k2n)xrvLNmxki;k|_CRbfcj%kur?O^K&%=k8iY!x<#0r1{qykAJ%N`6Zl< zI|Eq5|Axr;KQr^cE#d!ozxaJ-%I1uG7j5-@?`)E+S^lK$?jK;U1Vesd>buPgG%ux7KV0;gbyBsp$Q|8e&`@$>Q8I^ zb2GIH$-5^S8(Wu*GGpH+HF`3^%d8&zCoj@$Db z@~YKLmYWN!jTBa}`_%cG*#u`*h0-qc({e0mIQl;fzsK=_v;Av%foJj6wJHQ%^syo% zuypFe;YPtiKGFb{`?vMCG?$U%3P$IFLXtjLhxOq+6z&H3XyPT}W;aB3xv zFB;&=ncU18p0rlY$W*6avc2!$@5E9>0H8E3K|DG|adY0q&n)li~<}qZ; zhVXQ;K{?;HHI%eCpZui@rnLrxCB1b}%KjAVG8qJ580k)3C_?U4F8~>nUGu<)xz_74 z=OkqbTD8eDg{$eKMKT1kDwL=6c=?zbLWFJrjP4horQa9@L-mE3l#r==SSYF+EK}eM zmpI8X%sY&J;|GLj_XUaelokM^7pQn#t~NDZ1v1|tW(WaBXTC24_6_Y4a&G_RchXWF zbK2sE_B3!-OrMtv@YQWBNA^1b_9;%=J7uXP>Uqw@w9>G_-E9p1F^q1MocJqQWLzERPo?Hk3|J(BrV z_ev;m3QQyG{KcVS*Wn5L1vw0lpuTLG_4&)rSt4XHJQR0O7a7$CX|JDxq-m1sDV;A3 zwUV6*@vl|Oih7`xKMMtFQp7yz6NpbBp;I-1QCk+B#pl>x4@O3UtGY za|sxdI~n_o3lwh1DxAlox@U5WfQSjziPUT!1iQ_gNb(TiTesY96cN^Bb!vs@MsNa`m~YM%KT)1C#gX4dF}pHk@buptFk1fuDJ!Yr?IK{172RW1&7sx z7B{cE1Q-OninJIkRwFiVIcrx<7e$=c*_r31EwBA^VFiU4@U4jwg7faD+vN9v@}@i; z_+L5mZVul|c;FBCg!YdQ5P**A<#n~nUT}*(^}{E#dFscRHS%Oe*ni^RU_kM2^T#D( zbu^}3*;KFJ4FPmF)w}pEelPwp{OeD%vx-sI?r#Q6{y97Uuzvrq<$wPG(Vx0sgCMmO zIRk`)aur;l1pPU|kb6o2xo)cCy_|#2KY)z6E>NTc6zh0MTH|sa%O4q;q?F8l2N~yy z=VF<2#Z%SIZz6{Ej7%skj`#p~4eZVSXOM9OE*w4|@KbUD4g~ZU zAH!|`Z$L)>%mr!&noBorS{ha&H36nm^P~nyWVTUVwVGTF2)L9KA~V=&0^{$U7vd*1 zX#zb2#%3Sjy)8fEsr~9Pq;<^i>SNSGeA$6IXvb`0t z2 z5mNp)j}gX=OAqQdkMSe!mo5QFI3j?@XqiE4nW42tRX@B9@EGSRI?51me-!@iF&eyk zj2QjH^i`D##|c%1mGE(l!(o~Hz-&1tr7Z4@O0&sTsP>_V1354vs15uoBin-KQ7$5B& zowe$;v%ksVJ;leh`ZILzWvrIaSx*g07cI@Wjol7ASDGM%@j^e2*sPWrgiX-aCH@Qmsd_*LHZ2S5;p|q{$m?b#(fUZ)R1oR~9^A zXBRlMoiKx&DYm=kgE$M}YrRWEVpSC>2IEw689tqnx161tR%U&9=7 zzQBeolb{~ySOLtjvC+qu`vosUaeQ+;GNJ*i+1s1(_{E`<& zW`&~;T?FW!_{d6I+V}k>k)f?0614zGC)|r0`#}hipD1rZJ9_=op{zUqi=OzJ078Ay zHzyO6k#Bu0TtEB9jT%3ot!l-0!3ABZGGL?Ee4{RH-H`|Y$0Eo6X!CC<0F8Z zb3meJin~;dKfEHT!p2sN@iL&B4Q@kv5b`iJF-82yle`Dx`)9q=KxWQC?35 z3IH;yU_yXadCy9G@VR3Ysth>fi4RK~#y-nm(hdWFj854!d*JT!W}?{IURq_L-s^9D zks8!odJn z>2XevA%L{Ll)?NopfbUGt-p9#G64A@+{^O;lIAC;Vgd-BW!scxn70Ihv-von#QMrNOw(8kpl%5amjI?GPaJ$xi(-_mflx|;Y7xq8_G)BBauu5)Jv*&&q z=fViW`MOf8s)3*w5FketA!IvtaN3l`<64FdKi_QjqYpX_7T+`SA$`eDzV%?S>-#UN zlH)Tl;C4AOh(IzUsg&50f_hqGeugkl&E^9Qa(VynOo`$gkMNW5| zqn^Mji(`F@p}bcUYEmUv|?TZTSB=xZ$~kjSFu%$Khm(T z84I~)OzSSFb?H)`hUEzxZC!O>b=0kdlQr$g_ryEe#pV^LJjYNUhz{9&Dm(mt=i`fz#UIGyEfOrRzyP zf$}Vw_O*#fd&;z8dR^)zqzJAbx~Wq?TyMOX=eF$LJ&ikkrB3J(J?5f2*_~kglSV&n z!re>EE_&`G1feW5{;Jc0B<@ZSz*Qc2-xmknjdRUl_Ywk{PIonvrX?BE|1Gg z^DL8Zf$X@|?(_{Lo%K2%h5LWY&LVOUZsk6{r6l#_icg2+#Wvw(y=;dtoR zQ1(%Kcxe(}6qdVi>4p7i4Yir9f2xLW#rFlIFQhb3r-M|unc+LiPn zkBsI6e27yWgmo#Pf~I*(;aH+D-IxUl3UOBjwY|AU5Rw&9Xd4Jbswq_CU;sYtC6_w< zb8U{y-OuG!?-GRP8*o;+-L=<^tZJ@vCr9ouXsUXXr-iZ2%1kpT{#h*P=ccL4P{2La zH|BHIm%5%71E387b@*Sj3d@L_t${zM^hkg{6Q5OZSwAipmS@dU;a;OcI@+Y6JOosL z%OYt>f^Weu7Q2Y*Wb%Dmu4%~VxQ7-xb3alAJLabUv&JY<;~@PvHOBuLi2rS2{x2Hi zV*Fp$7)w!9^4LkJ63XHQEb0SPB8pa(E52std%kOo$8UJP#SC}>it{zsB!M6^t zZY6xj>9kGD^u~`_4UVWnU=7irP0_436%eY5%8(O{NLTVHyC( z_^(otvugX2G&c~R85E#de@;ShAWIgtLq2w(>`Pu&#(Pq$M|Hs~4w{^L1 z>jFmsX#@f3?gr^@5RmTf?v_TnySux)k?!tR>6UId56-z_yY|_8&Ffs(`D?uh#&7U_ z?s0!4WfJRyz?rP@xd6eO68PTf*fB~>u8!bzF+6_grzatUi;M9Zx%y^R9*Udih)hOi zA3?8J<49?1<$~D<`67qoCppFjT9eY9e}eJ#QLEgfMJ>x*KE!%ya=ppUyOFS!aM6@2 zj4p(jDibN!S`{ukrp{J@n5HvOtz1puU>+7j``h@W{_jTbnrz!>=aVlzT{d}&a7Mv{={#m?&k}w|e2<^^K<@+p{ zc7&Z&pR-jO?qUov-h}((iZh|+CUa;TA5FnVeY=v01Q%%DkhCeP~#U#Zb-3xcUul=%N5+cx> z@T4ngldr$Tic>D=`%xz$I;%h~X1tFiLsaa5!BOCo>PciR+cD^qi7;*DeW3_$~d@bIFH%C7~qgpeFwQxA!s}N6K(Nt~fDpn1dZkKIBk={-O z3*gw`R63m2@AepS&rioACXokmR>z0jOjI$%GaFg^=Od1>4%gwil5o9S-@A9T`_eaz z^=>gBflT!QflKb)Zh1)5ayw z8&4O5=k!ZDrR*#7heq2opG)lE2bd_XgWe~eiU;Vm^u+AoeVL3=l!HZi%B z81n^}LHE;DFMn>WW;$J=@{Jdqyxg4IxZaMRn7tmn}fAG>Kg8isnxGmrs&RRIboH#z5o!m^I z;1|w1-dQc9x@nGZwBrQ24Mms zzgr{;(p63zY@iG=KXIwvhfVQ~myd8G)5Cqu-_)q;NjbDpnhQhd1Fl5S*7EW=$;{-W zV_Df7M(@(0&b~{qfY;9MD?(Thi;EFvydzXbVd33cX%2`={2;L!&}UsHh^o<1`5~1R zNLQCICoXLgZlrw2Qubu-eDC8y1W=uIuz z4<|D|#5IxC%KYqFjZertp5HJ!vCHicfi97*9pg~Fz^9*Tk3pcFQpfW4D&25><~M1@ zCN0N`!A)!pc2ngo;lDgah8K@fT^wjKoyj>1|I=ec*ZF1wc#K?sc#Pd$lZ|wl-d`lu z*v&-k3?&{1THQAndJJs&q`0i3u3`4sxEu;HHQyC^hseipS!PLrLkRY^OKOg&S_*#B zOJzd^_+3;Wf&Ox$@<Zn+@LUc^y}4Mksg0JQtjigVrSKj``Y07&MzmJw%o14Hn_- zG5z5&=1`z9LW#6_U;BPL(FXuWK}8(He6Hpez+;q?m718H%h>Fvr(;pNY)NZM(tXc$ z>aF&uf&>RjN`P5N0yVqo>s~q`!cp3xzBcX2q2Mqq9hXtkoT6*_Upz*U)R)mnsK2)` zY;Uer;4SeUTeesIVx_T*9l44KIsQWMT>4Lsk#<|$^Y0!b!EYWT*DsH8n#Rn`6SB~c zlPv>Zs_MmK+=-*4IinX}rHp*L(EOcwCqE0XD21Q$K@gxC2bH?5L=pgx@vZWihi21= zEDZBmY>1obi^oW6u2D_>r^op5m&Z6v_79H{0q_`Ar8#4;#g5P1Yi_;sZQ%KmPaQ=l zCPT(;M>h~*s<*bL(5Z!tYGryE)0wVm-DS8KV$ ziKz>vh|7$JD(%VGp`iMwnElEA+*3#S6Euyv0PI`cBi`{3UG12jMmHS}wQyb-1~Y1o zUf5NLTe?MEQ8=Y}91AysD~4bgf!wm-XAaAZlWig-7iERiC0Zx00wx3QWhN-}I~fO7 z|25Yz`QV577gN`NpN;?9-ux%W`0~*Fg@yu~KU-juoD(dI58FGizqo|j@^_Arawvtj zI^xGD{Nx^5Z-B*1fd~-6dEprKsb#6z2#a&e@`R1#;Yrm*l8QJ?u(!6?Vj@e;3MYgc zCqQM2Bq$i$UwO|NPHVBJ;|<)4{A6>reUqv1RumrEEOsg^QT}-JVHN`Rp_In`*=R+8 z=R+;1ht1V*2-#sQIsISc7_I-qG5&{R{13-S_#ck({|m>c`2UGxT%;j&{o6yrzsWKF zeG>jJJM-@xW1ox~bbcSARj7`*_!O>BRqij2QJjRi zF11rXz%g1+GZXF-wyLX3{iGlj!SmTxu)rZc-`WvIC_9Rxi0Q(6$6xlNOIrCbA(N?- zMXKwIBr6@6$2ZiB`i$E<1P5ee|F%k=R|1ZKVM1Hj81Mn7cJkS8kPvu;jL2TS9Gt+; zY-!WIy1xKy+QJqM9fSMbp{q&YFyz36^Uk-moy&1G9BCo=F(Fny_NDkg`!ii=T*fz< z3KBe>(M*UK`uC(<;qN{}BObAanW!ntpQBF0fS}dt@vUrKv9TNUy8j4sckNUuwM>30 zri2E{_nam(!RBRH_!Q%s@;>jK-|s-p2ie8|H{EU4IAKl7U9_I_Qpax(TNP$4gyTj+ z+qG)GO;8grmfRW{VK)y$5}MCtVV>^UzH#Ip^yraxKI*iZvI^#df=|@mm6@Rhj!)3( zwciDh^mNnPD1!^6UCH+)+o}w#8hr?7;9@{6GHBZ_4^X8pJa-u_^LCM#LgtLU6YRi+ z7Y}Yr(;?Su>q;q5k2lvR4Za)fzZz=4e=fu|85KxYO?&;R;Z|?$0XXP38Ao4;BjR{B zxtg%|-mR+j@!Kf;<>Cej>n5s?=4mA~d{S?>$E2qqtfOthXEjbjTmw|M=4EaLbn;~h zy1MQ4Eufv$ynXvEge%iv`He1H#hn`isDQ`~sqCmw(KbBm*C5c)>4(K$|IUNKWMTmc z8ZA4HK^h@@6WSJIZL4hSj=PX@czR@ie5B39-QiF6Rt4VTu~@P~T%SBtbuf3zZ2Xv* zraz1=PwYz=m>&ZkBa_*ZfvCZVoEsAXWUqplkmkqncH|6qdSa^qb_pA2AGNvTb_m8{ zwteAb_C6EncMd!S>etfOY@=zf9TG}1j87H_kb`$;Gf_P7WUg&z4suSQewA6XnKBi) z4Vc6q&CtKS90(V{vBR;x47yqvQRG(oP;cW$?8g~AXV>^+0exJ#hE-s=akzEYROl*i z2Pw}3KSMyZy_k1#YWT45e;ld~U2f9Duo>#FAxhpB#Xj2OP|NUv8rHnd^EZz1aDTk=FLI234#a<2l>giF z#6J@mEtUUT`H^|74}6?#b|$+!DZ{tlV?F0yOQ|KHJVBpwPc?T8luHti*}=;q5fpF5P%8fF*^LNe?wsm2E85sBFAX`*EvRjJosl? zjO1^$7}wu8Ms$;wDhGxy^-jxi6N#YL{ndR!Q<_70;^wWq}c#$3a%d2J*8>GKP zYqubRV7u+dfLzmm4uk$4CB!;s1X>0CfsT*}=X?CxaxI@y_Yr#6yg4f|Un5Ok+|sN? zP_Ab55?TYw#W!--=x(93^>6_nM29l(xzA^Eln5+`Z0*d{LYW9yW_@q6Z7T?@&5+Q>kj4@DGlx0wB2R*;MrmLF6y0}=|M zjXZl?9F|{Cm7~Gd!E$TAORNYSzKolIwlq}ZXEs>8UPh#Bu`JdPywc!+oR7DNju5+% z-i+O^2?$HuFYrEnqxY@#fz77YQ=nFspal!81e*4W+Ir{9iI6CTq5Xz2{)6xGp3l~7Hwn{01Kv|kfV+L2 zaf?AqqDE=xfW&P(1VPVy(ujM;ghpk7KN*`@c56wgWAHe>8+y`;@a_p6n!@(2U=CLG zAZX4R2b8n4$VHtigR_#qQ*?^traS4?W_yky+g&*CYWeOkmU~WihSF{@@7`cL>cTYh?sHZ-z*>5Pi>OCzrda61$%a4v3r>5M8$20EiejKr{|a?AGS2i=(gjuG`d zT(~^Za7TArXB)!rdrtgK%Qy@W=+mpn8;zl#mM?Ht7DIPv$KS^ zPkErmHwbEs%R+$Nweya~*4D_l-~jiWyBhnC(Kc>uxZ~h!MS+(S45J;4G|fc2BW!&_ zEJKk_Vu?FO#yhJ3$B02g>j`j->^@CW0LN%#TTZpj_KRcm0@BbkAQ>qRGLF?F$7Kr6 z?^*?hNFQZ%@%S%7{Rh~1pL?axWlS0NSfnBJ-R&0O7)`pvd!r-I zwb)h;o$uR(xY&o;v*uLo^S`$XU!-K&IrKn#DNusX13w4by=Ee?i9B|>oj1u`QR1I1 zyokQ>1oN$F(vmYdZ8j>hDp{zWwH4JNk4KjULsLaO|MvUgN!^V87n}C}F*EQcsyh4{;bF6l4P0*Nd?6*85S<*HI(68R0`Oq>Oi& zIVb_YpTQ*9hxG#jz1CJBtKq)B59s*&^c^Jm1m%SG){Z@4%_#J4r#_skX(vz4y?GiJ=G?-12dr)`h+ z>jhe*1}RPnh<|s85`GE@wN~4dA`(o zFJ0Cmd2a=#Hm>Bfj)+=bF`@akkuU7{EhNsZWq-$uaBcV`EQfGiTtf@q%?C7CGuC#0 zgube@MnE@il-04^I$RlA^ox^)p-Oib)KqSA>cXzv0j+JlO8$)<(A$DTk( zU}WE6-4QKRCw$EipL34=Da+2{+c=1Gh2WUs;5ksVCzyWyt7tF#nS(d3CO5s|WoU-8 zxRFtAO_kJt}%jl?Dia2sY%b1G;$O;@+e!@1^fZ7}48lXd|q=$E3s!IltbplI(C z15mU__vrJ`yCdJd7rG(>eu3^4s*5(0+i0-fBmq;)CwWZ{% z14+|5daV*YMw2{b6DxX00l5YBl(3znpQ~pmc1;m zKZa)N%h1evV%(vEE=P@0`l znWLyHu5^R)K5ry{QU`5}llW%&4a5&U-xdXRUi5mo28w|un~S)s7P2{f*!H5N#!8wr z)EPHUOaz_LVq_bSNr3{I_Kcbn4X>7%6q2Pq`L@V`!bSCvHMUk`s{u6aX>lu=dMs7yRUr@DR=CalF*Sc_ zjH-af=>CVs7zi}&DZ-X5nm&(|lw;EuJ|qDjOy&;(#MTTHOpvDt`t-^L>P2I$2Qt4QX)URpiDo! z>P;iAh}5P(6m(I@7X`h6BW5Z8EQ)|l@YFG4*Dd(R22D_u83mv*zBF7niZP6K5mGEF zmQG?Qe6`siV^J8MlhH}Xh8k>6t}W8v_4#NTlZVkAYNB_(XvK!3t!i(D0C_^q2@>W) z&qijBw+OsXe;@a`1aa|@nWuS{JIbNlo5u0@U5 ze=%cV)Jq>M6l@sKn{jJj%$TY7Yej##1S%&<4SVWtvjWTUYkwES%@(C?W0kDjQQkr@fX_g|6mwk|`_{&D209^oi0Ai$coVSU z@j;m~?5eu;5O=?SNBCeUe~u}#!xCO@9{chUlj&?ocpU`?qVgEHq=}7rd6h|RTn>nv zuk0^(5LKQA0>@}}F;_VtPkw=OQaVfQ+cT+6Kh;5+ov8v-%xjti;yLiHCg!zNZI>|$ zxH%YKlj+~q%Q}C4w%-sG{UQOq)6u#UJ;knJ91BXz4yu(&Pnlysv~KgxRXxv1yqQ(p zLgB+t&D&ZP7EA+6ea++#2jzGd4CFPI3t8friQ+Qbpvfc1CmfhORL#V!+P>-igp#6% z0v|(Ya(1y%IRt)0Vz{v1C{H2R%poxqL~qN9yxSRIYjdnhQy(z>;BvHDYN#@0xGXwq zLrV+)(fXt8;o(nF(dkP(7LzimTk)ukxA6IDSEJ7ynwhl`WVSl*CNx$~@vd_oc%rlz z>CR;g7b?`E_wuo`U^`AEOSbJh5M9!;muVb}vl5Uv(z4GBcaODcAuzi|oxPGAcaPa- zNCO`*h&4JN2|O`j@;_{Kq$FX=7_K3TEi+}zPfpk|Hj*eL#1xzPftIrJ0@~r2!rQgr z_;HM(>7+AP8N<1XkmV$FP&!Xx|b)@&Op zV`$1xRf65hm59XF9~O;=uTfSQd&@4Xh*;361ijRk0F}0|Vpliq4=&CoNb>H14e2w>J8G_d{j!bdw=)3Jvhm-jg zB|rL8bMIpNx^K|v;ut??4jAAzrB&|czuQvE{=|}!kOMwU189sAIzmWO){lV3SncYE zEd@Fc&wTP3qjuW_YurQA!VVNd%OFu?Rc8c}pyx_@VWi5W&tfkQ> zW@c!+?S8%0nJxGR$B_CA-*chvQWnz#xicXc<0IpHWkZy2jar4^XwQ>J<_-l}m zfyaffPn(_j7i`F~toSTcMorh%C4l7b21V!7=(4y3-4^ z5ES`-1IyNiH1WaICP7{xp~bu56zNL5+x)YN)ULxdeP`@=V2v>vL=YLoIOk0!7)Yrw z4_eXvh$5b2QBvRbMlkE5bXL(EQifxIgN4|=O_{s5$xIT{VYxzB+2xo*bk*_78l8#- z>`b?JP4T_{ey(+UXrwkOjMtk-vly>RdcnNc2T?|aW#cXc23Up4`kcBT+Hhw~bL^CG z5W;~-bx1Zu4L?jo86CQEj8O0u#Nc^o2Xg=^g!zMX~H)p>g;)tL!mLzmM&{PjCs zy9==?8Tcvj+c$C(CtteBcr|d|0PRX30Wx0Alu$sa^^W2gO_?Ay`p-j{^QoZ~;#a7Z zsrR(8L^-evJ_`O2U5O9;u3WWRT_awYDOE!(*u3DaxdY5!wU?`h7&Fw=|IMyGtnv!`OM+W;j&I}3Uhv5@x#zh+?z$sMAX zm(-KqP+~hy=Ga@wv%f?%ri2;EyzEkG>mE&+Z1%xqqdc#P%_{qF(qplw>s#jnjC@R} zscjdZCYJuu-1@jVR&!E$lTImlyy_bRK(kN}X*oDNqbi#LHuIOOlI@{@a*dTU0&`j|^S>PYt?WvFEG0t}@4b(3*hfvrL z$LAJ<(?9s{P&qg|xgAXJ#<`cNW%Oa8sGihly-!!CsY~BgP+vP;zGj|ZoHp#;jPYiC z^YrAb9RsZT2XWZj?lB`%cdOVZ>OA6j{-{-&z3WU}^{+aNZtmG9;d#^8kJV~oa8V&O zs>KY(v5Jg1ZUkxY6G5OR#f$l0I7X}042IgQcHQ&ys_U7)E+_qzT#(@--2b{tLQ8jl z`^(XfKUc|rdeQ#Bt=2CbBiH|pW6b}ZV^m#}CAueDJ48qemvLJlp|=%sF!=SN&Ch6( z4`w7-M;9i&TTAuL*CF;GAE{3!>x2txurb~|FARnYAx_MwsEdVHTY~#BZv)CZ+Y>CK zhSUh8)D6-$QaK0NvWEyb8K~ga{$}L7ch9qda~G9`{WGNIH;!>D?!m6^udddA7svjW z5^MRtC#OX!uGicHoes-u@9CJTt(n!{VU|dxCpK{2eeeT77`N~IMA;!RN5`td_hh7 zGA@%5r@+2t#UA8dPTc@}uo2gAFx@-~W~*_e@1xPrNTD~QCA_FHskv$tNSUlb)jNcM zO`=|XR`^l58~-iyl?zTlYV<-tB%;QfNe+BRzg``t3w!9(Sb9qfBF9wGr11-)@fa3| z87@p`mV&|kLN&J0YQZh@TtoB3FOR0XamX#~?y^IliN8vzU`{_#ll^psSf;$+eg>tT zm?2DV)u#wPhl+bzuuR zO+?U%)QNloOLS0Vfi2*wUcepj7_;;#ZnZY8v^(wVf3PsLAm}AveGk<*R{;g(5_xSV z3+G(qugE$O70q4BX46l~m>c9C6w=|4oevbf zkF-RF^&*Cvp~Gg=?*#-kmuZ%lJ#eL27&b4#oI`VL-`(Qns8&V2W!;wyZ|$G`bZDVL zx_M??FagaIJ8+MF78ljv9r3ZY^_um}Qus13#}ayz9`jcDD}G68fVzae6>C%ac%1xs zV>W#_C-gMii^nL6KF!+QXG6(j#e{z^Ys%T&d%1cCc56cU&ZKJ@n@j{Lqk&lhA~Y~w zh3my*EV` zPk#|)wAT9jc>G@$YoJq4?d7n+F&S@nJO$evz0f%td67KWCqZyI?F z)9pmH3rTmluenZ~*MJ#0Z7RMxg#-d-08%LMG9ArDaA6hG8}#Eup!b&iVX7fzG%_h> zDaIY&FiO}SfY&*smd~Ooj6_+~1r#4H3%YMzRDsA8Un_Q&wl&%jaCd5r5{g>;zT)+J z+DDUCH8zNX-S{ad@0gd`$;pfiO8|cWLdFL?Jh(<3_e7q>1fN2B_kQG`F}Gqvk`w7u zGj4x(K~|$4NJ1fR!rtrmIh$XPT*9Vpm}1QV9>GX(^iPnnY4PDF2sM9kEZoa?QZCJrzood%|8V#b0Q*c~P*j;w>9zTY5ZMxiW7_`GgSSdz)E zZ4?ScY5ROrJmpxrlm+HtkJB#b&aB9W;NptsxbVDpG$mu75G;&2x19#Md6rq(^iMc`*}bWhgijOJ1U0!d|4oT78@qm%Vgc7>9Zcoqbr&Oa7u3bmr{tY?<{S>7Dl0R8G=S zar`N~YjuA-Vi{ZuJLVkl)R9EB z;Mct@669(EAM{dT6Y%*3RrBW@;t1*wZAM3vhl4<8EI z%u)ZI?BmuW15`k{m%G$1wu=sk@8$wS^8FwL+u7^{N0h=l>J#_y)&xrRtwQ2-&Mmx* zpRD?6=ZPiZEF#k>w<`mQBFJ!}n=*{y8xs9v%6+lD=**!Dp*8iw`dZ_mJx(s|>#3Qi z)o?*rUzf3I1duZ7up6h(k6B7g|CZVA6~p(&WmCaw&?pvVhG3k41kQ62*X}? zF(gW_H@Ult)5H?Si56(ed9(e7%PA)!!{~(wr+)6v)j94y9p7e}yW}03L*4A@=_+4& z1hrp^l^@^!m@8ltSz^D|(b(uTjpsQTW+Z1fhT-JdW;OL93V%3_+ROv__fk6PlJ;1Az>rDFWUfJ`>0~ah93! zTP&_Qtf%PwOL0g1 zAH8{>FbL0Dc- zs@T~y!dK|a(h2Xoz;FU>HAwk4FtwMG?XSf9kv=h8LvkBQje*qe;}7!d_^2--#tgMK zbv$`}(VCgP^z7qm{BM_PS#+AUzX&n{zZxc%_8(~e?GEezfQmY$#8sWYwfUR;3D5d9IVfPJeq%8=s>x_quK_ zGs*wHcyb+fR9+5%&)J*wF5&MJG*@yl=soWi-kft>eP%wcdj*>8jka0m3|F1QHay>5 zXLv5Re$Q_9RGOtJ#6DjBdrX9s)$R5#$3*@%G5_Z^`)@IkBMn#VKS0I<8;wpzo8%9F zMC-Qk&{h8yt@~2@Qu?pG+;SYuy#4jDij3ak>u(?><%m~WjDYJZ=xYmq zR2sz&qYOcH-^~pr2%EwWKmlmfok5zr*#+;SWm~VPp2~*0$ z@KsP>+u2r1$kc zbUDg~0I#gRq9<=6>BWcdO8(3m9E&krCxjkrD9<4-gsaTsTmE ziHsaaB`+dlHsy=Rm|~pCzcUcNzki8sTYS8CMKI>sI9CkjQ~AE#*N)Q%BJSjk!%(iV0zH7WEOlI!_;j2)K4vea6!DJ7OeTd_uD zQE|phzJEOus7cp%RC$bk))PtHF~l$E!_$5=`3r4p&jlH+Y9u?ho6gCtm_*~Qg`TgN zlxClfeu<1sZ?$Sjc}&D!M8@-9B4big8J$S$h#(7x!lHF|Yn3{TYyIU0!&Z5Jmm-{T zu185OMWYzFE0WR>-8sEu;@C7JE>r)y$J~p^Xh_m6+4o6q^{~>P6O$Fs_w`i$*mK?$ z%tzCX2~;8%!e|xFy&Gze)eEyVd(qCZo`s^;J%4^B`9y8*?`OD;Qb_LiK_7XcL3NY_ z7iP&h-&S(jcU6e)(z4sN5~@{t5;CT4V-t6>d9%?X3wxa|u#GSgu*xMe960DZyHbn8 ziKHuOu-GiCzQf71w4KQU0cY@(A~}g2Ts^(+5rK3v zZG>bn&#_bl+VXbA)10(jhBxc5oCl;<&tqx~F4bdIdBx+|W-PZ}O|rJXi@1M%66yD5 zH)&f74K z;85wDf}9HISY{w?hE?~^B&)Xg9t!4F)o>tN#g^MHHoDxq^TKP2kHoDW%Gb^^Zy?fJ z%)YzEDrvR4m9L!TdhEz9W?XCBX7)aAbBMoyjQ*+z0LbW?GVu#!1P2LGg)KL0a6j&Z ztHwDuh_L+7t}DJBgF`ui_>;63&niQNwBCNJiJ4W=T;-~*oH=1^e@P!)+2r}R&wiea ztbuCDXXTZFTj)fYEza!S5cYw<A6CJLh0pY2!dnF1m+eO}&cW_5TIO|q5!9WKb5>xr%TysiBqK>_ey2Ry`qfMAuq;kqH%_T@ zV}Hcp_(h<=Mm*iLUbkWCt?0eF2jDFeRR^SJu`*Rp^ zM;+ANun(b^aFi#dhVQjBhj4s?z1a633Crd0=90qRu%QX=d^2M-G=NHY;6h#8UUO?` zO=*~!&-LdiOr>O=N29(;IE0RN9j=)1%G&qHVp%+br^1tUAI(Fuj%Y1>(0E|GFZ4#_QSm({t0 zi)5EY_yG$i@7khu6IN;SLRr8(x|R~*&4mGwaZz(|3ji7U%@hHU5lp-JR_+gw5qPKR zMRVoM)QC1QO3f-YSxHfox;P(nG-!-TG>PQ$XM?Ja7DEt?K%6EcU|W@dNF>4sd2z#>cY74%{a|0+)A** z*a0QO;*cx7BX_0*>w*fGD@0z)Oa`tws=LQ718+FGa~S%ffs*xPHfS*-W=xtqqY#*$ zvQ8+elZY=#trt>J{+O=kpoCu65}MR05Kod$2exLj_$VKgvvCXxS^U@EmP;Eu zGT~P+}hnvvBD{ zX&rj+ylm92;dO)`#3pGOWHqK0aK3=!HrMPbOGlt)coZ6+$81}tRKm*B^I$1843N>8v2%U@0agw zdM|8y2W5W_o7l=<$rQC8h#BsL5Nk*=)aM!;_l#|GCEQA-?R?ehxU$%2QC0I;?(SgY ztFYW#dY&8Qg6^>|?j=wR6tI2>N79at| z!*>y}v8)J!J?2cDsmrc6zgJ!75OcqSs8)#n(slV;zv_3ZRPtuvW8VvV{%_~#{yrf8 z=QaB`ka1&t1z*JCw#GiG4=E1&J^!;8|7+C-VxJ>FYMT-2&RU_N42$ETIE|pR^jz8j z#{AWlKA4(H^n`Zps=QG95!UD=a3tL&vciz*H&M5SHh@?gWsz{u@Q+TAWAm#U2|_5Z zOb}iUeGoAaUi>>g&t7!1U}Kr-*}9xy5S6$B@<}98;IL8D1ao%jwY>va>@ohnNW9>_0TN9{c$S5a_{!W&+4trDlf~fZ$IIL(HGW4x%Hgy znO-NBN&6AJZaeJmh`Tmje8`z35N(JHdR{(cyrW^hd0{!?m?BCn*@|$VFOr-c^p19)Xo#yCEFIvf{uN(H;lo)7K{Vk_l3BG;?SyF(oe(pMv(XBS)x#HCRA?T zge|IcmAQ>e9ABF^$xRI|7gNRv;Kq)sUc$&Ya-UDdDtN*bWk{%8lB(a;Mx_N+XMB*) zzxnEP+CW?Zd;e+TT7Q9Boa-a{pkDNwzT9p;6KPQQqj=>hteW{~j&b6$op2%=nUFWD zpb!o`C8KEePSr~&DhUqKOL9JvMdQ?$1I1iN-l>dQsJBqA7DFB2#7~>LEyxMaJg3lQ zuAk(tNkOIuGv3{1#61_eEe+5JEh2e5R`c^5KpRp)ShARnUnhU_QafYM>&9UHDju*J zeP6g~u~Q!GkdK+>Q{4jO(lrmWjuBXB-=g2Zdb8~4!%3-8$m1Ey<6%uYZNXnZ5WjpfI zY~*LUBMRyuM=rV}U6QDRhB9M-{I;^Lm2#;73~N-W*(fTsW#Y!wl5%tgf_M~uq}m@* zy6_1gO1E_tJBlo8X{B&z<_>8eVzRH8%HFqE{h=;Zv4XwOK+=g;oazy0!S4rwzsyJ*g(&yV9v80p7zZ5%3)suT zecEpl{b^abY<`rbaLc!Bu3W(tB;8Te>A3T_kr}mw1DdU?y5ufD+3wdwCqvEm>KIhL z#&&7KzDgP`l`-k|6Ts*pn+E^y|!5$ueL`#-dtFkLQ!LFmf1YIPe{CfBMjNHMufBNfh z+5eKg9{TS@#y`73fRjg^%#hy=nEID)kY5JO-`=uKQwClA?Quy{uzyU`OTsTR@?{mZ zsx;4qu*D-N#G3&IjO>D#vAwVj>m)11r&*|jz?6DYL=`2u5(#2LTtV3s&gq*skeF(p zJoi3(M_xxD(47pvWUnD@rIiJsS#)JrfTPE^FGr7ePvead9{R=*54vlZzXfKn9Udov z-;5XK{NFC2{`W;j_di5Nv-@8nBMKlgmfzD!q~?c;sxJ4{Hw1~lK|YOulQ@jTiv|KB z=BuF-SC%c37@XE5A^7=WiB$e*JdjrrNp%O+Gok|zfj>k(QZ9Q1O6w#gf82HrpzBMy z_PG9s0>e$?I_M2*Ef4O+J?0G!!i&u6%&M=g{#KbR%r+^Vr-->*3>t zU(#j;cU30Cv|BPm#tI!e&lD7tl}--^PIv@f0bf6B-N=YQT;(dqK_Q~(3pCVQS{fal zoXciDP@b%j(pH3NTn#{#_Hh#tlgpNlM9Cn&6*1Vl|4hg0Po%WNWpoq9RHsrX?;_oWWAf*R_nPo6;@9FhEhh+(f zDRQ?v2#<~`s!)Cf+5ciw+dsLl-D}3@X0}^J$>e(2zU>c)jLvhz56Sto@ywr`lVDy% z#$l{I!(Srf+myg)oBM*rRb6H8N5zHfYia3st_aCJkqTI7NLr$SKI{wgdxM*4=wn~3 z*yFC#ms0Lim9+;kJ$|^TXz3188aze|#y|RMVqp2SA+kn#!}C;3vXQVly|xQKyZ9VF zfo)h53R@MJ?}0OdaO!EG`9a{>9KKyvzcl9Apv z;d_^MLEO_Rxz!PKlWv9KzU=5*w}aD~-tvGC^A`s_+$DvBEzr)cNNOLaL+A|?@5Hhj z3yGihW1av`EQdBPX)n>aJ_UUaapyI}jWqAdl(Up653Tsoj;l{4DS@i*Tdaq$s7i*+KQH|jeWuy)K7tJ6b~c$QQl{UJ5do8n7;uo6p8 z*Cv?RwN{BZAF{OU)!G*w@S2F?$s(vxg~+j23l#@%Mcx`+VL@1vlF(>l!7hzO#yO;C zi^^s|YV8W?TJYJqLyB3B_3GjDJkQW&*I=3g%|LWfmwMKr;ras)L+3GY6in{&Aq?2In$qYn(V z23tK`nL^6(o#vD(^v+La(YYp;r{4f{qwyT>d0=+_1(FeXkof!I%KyA@10>_GUQ!Jn z$(M9pHMEAKYtw4t-#D21whc;j+gG0E#=0S3QTn+@Lvy2n7FPYMnNcvI`rjc;Haw^d zF~Y#^_53|X@{)W^?a?t2qEL+UNur%4gF?P#{LL|38ee|%r)9c*e&;Ao9Wwi zZ>~Ygn8926`eEOJ>J8G*%R`BJrwN197S0lT4M~&~qo4)E%PdBo3X3mDV<6fDf@Z!s zO+Ijvw}XI?-`N-0fZYB;zF1lRsLzjzYf+#9m#N027d9!_#w>1BN{=dIWj$|Lngw1q ze2s`FIpi-DRR9x|CCjje8pZ#imb4c*gKPl3^3S_|oSMF}%Q(Vs0hvAV%OX0o;WHmG zKAx!L@it5N>PRva7xoBvCpqS zd}x49|2bx-fNWdER-YytDT4rp3zjrcFJZ;ppf{$i35Sp}B~}SYv$W7gK(?;eQ#I!xPg;u%-T^5yIYLpFnCpnrY58z;??Pu&)MpjY{!dsG3 zBhu0}JeOOul!IDV9PebS&XWda+fH-msm(HhENL2Q*A-)Li?K3phvjR1giBA|b9Ff$_} zg&)$-5??r&cPx^nJsYh<%lcLD&W1Niq=K$kY&B&_*`Oi=%Rj_+A_m4dmP&Xgf%eR= zf@>b4KuH{oP454p>@1k-%(Jb3AUFx`?(Xg$+}$O(2M_KN+}+*X-GaM2!5tDb_e!NpuwHEk2+v3i$x~g$b+dYNETLg0`g#VRJdT;lmbiDtkN&O0 z_Uk2BKhDfQ6|ZzXE$G$YZb?l)7Jj5+=y;haa$$mpJwtnz|kXh5KTX&l-U?RDelyfu7vuko<;6AJcfaZpk zinI&U5pB$*>^0_gewsDhOv7^6VyaP5^+~w=le1*33_bj z_73K@HV*WT#tx2pzyHJW4-Sl;y`$S-MlyO!W2@kJpC#yOOtw)gtM0nBfila8%+|Ej zH%3_7hLA{e-@%Vzz}h&_8JNTR`ysAw^q?+|8D2s%hUFju(Y>+;JJC{*_rhSOw`};cvuXJ0H&${0@!;#NC0^VTOLK` z(}~j5ImeE(bRiPwBr__F`IK9R_3Z2PSvQeZUE6t#ROdPTVo%p#tI`x#TIt`2jH-E- zSr}=b$I-G$%$NY#zIAMH$~KxRr2-uF&{aB=dig%@#{gf2aR6LHWmOCD_F|CAd-FR) z0Vkh?7Lr&8w>1^43UOJpl@c06%yTv43Y8Lz!-^N$s6BrwnS%WEU2_znd87puxEHZi zKaMSUM*boPyMY|LabsJT_3IL08KjsG77wS7n-d2!?3fkn0yb}&FfNA?CnC4b{XP7z zAACTPm?0rwyXE@}=Pl1Eb>%9XO`Y}5wi+D^f8jRxVeC~yc5MpZilxE)-CUGl4yds0 z9tI$g5f=z#B>oM^h=%Wm^&61U9BaC*-2se50JW+UpTyeh}a!8)oT`GVbf@-C@2Z;>N>i)@q|wRmqDQVu0{ z($hK;^(*&XWZRa(LlDVMOdeO4(!Zw2F!)0-ReA57%pp=z?C_ejKURTs(KrdQh=bJ4 zaZ`0*#yzlnaS5YNsUdg8t~u}+@O&|Q(6SHAvvD8R0=Lf0vq7mpVN&@KyYi)*^xk-F zA61g2QDOtL?-ZD)k11rX7_-s}ymO&7pEx_v5>m6-Pjiss#m>AwFtO*d!E!c&I;+d~`Sw%gO-;R&8;fF-2GuY} zEv6-Ik_ZD}j@cfFgMS z9sdSqtn_wKqh20+cvpS|Kh;tJ6n7HahB87O4DlP0G4k4h(d#X21c6 za{%5C3kXNpTNGOvtC{gR3kp3k@2s@Bn6vWzb5qO=G+b6syCg zQW|Ap;Nl5wkr@x340s_rguf9PXKzvVae_a*ok=%Dcta<$I#L;! z<4hw@P$w{KQJL-JFfKl9W#oZ;LY4QP+I34_llroBRBuPvgVPj`VlFh#vp;q@!Lc8J z<@-8W3v<3XaaU@xP&N_okIzREgpy-F+f%aEN$v#6?yymRaQyffDRbZRIrwrVOpVU= zuFK8}8AxILV4>38qP?=!D=h|m_2O1oM zv5V`1xZSzHvItlV<-PN)DwA2367dgr#MA!sWt1@lPWBs6CjSP7@qc9Uzs=ommp}~f zQPho3wk~Q%^#LcY;5w<{w5S<5mT5ZfFER|758&E~s6~+}`YS*Z`u>XU&rr52Wj+M{ zWVYCF8mncdod*!%SB4n|p`lvoI!q-$9~0R!gj!OqwZ{eNes-6xJJ+ncyQlM(gG_hc zPY;!WUJB8!D|} z(|z)1ApFD+FMztuI(J^N8+Bt&zXVyq)*$_y$;l3m=s>NZSg$OJjhkaqYW^ymM-WE z=auCNnp;25VJ}BkmQX>+tFazK<27Tqf%PL2JP5r&me#t|qe?kuG;r=d$|+I+r6e7u`mYfO~LMlp^$`PhAUpQq4*U~&qzI|l8 z8F`a#hJzk&;(cc7!I2o!O?7eB-qE*QFO7mQq=KkN@NY#zZ6rx2r+K;5q8t!L&K!MX z4WD5vu=Dvzj?H~j<&+HH-^__cKwoeAWYQmJiCt^dwA(H#QxtTxU-jMyjZ&K@xtzq)l__RA>^nrF=1+>(S8Tla! zC!UJgN+63fjBUu+?-*PeQM;&$ZT`rNf7Ue?yLwf$W=gb(<6?YVnGqN%bC0 z_Fnkx(zj+b;GrihYc^J#N$~{vBB^JJ{oXAB5DgEp=RbbQ?ZeS~Ez!!?S5Hj4qSP{A zyO)YMotcFDF2InA9UzTvi!=eUj7W|{*~ClAmRPFHtgiYhx4?zv>OiK5Kdxz7D|+#Z zDX{cmNR*dGnFizmL@w)crub5d>ZVx$H_`*i^Xrf10P5miwg*8(&ZhV0HeTT)TG{(E zbCh3oV~gDbL+=qf!i6&(4*QJB^9rZuJ+zf_brLM2O+`Iil$}Llm}fbtxb1>+c_o{@ z1f3_AmG2X_7LH*D93oEw9H6>Fm=o;sp%)P>Fr?kFZ^+IS-laAj37!6;aqlg*`_?~T zMt2U~lSy!jaUBQi^AeYnC_KkD(`U@Qe?;QmtE!tj%&HVXP2aj50Bip1{y-D^mp3}-o`S&1q^0{OyyUTSr9E6WMm-uoFZ1B9T^mJeIs_u zC8xpU#9{LhHSy_#eNrh%*$)4|?|2c%Hw50M?C-#j_U{dq|1x9$ubIeywEO{Q>@7j` z2spy&oI?~mzo~3E!T##j-?@uD|H@rtau$c>wP1TyC}1+1LQ6S|HfV9x&2e!2!8Sz!5e7oZ*Ujg{+PG_ ztAX1XnEFvt!{95xKMR#c$w64YVW#P^Gq*Vso_KCqjb*?Yt1~79e<$ z^T0LhD)XxIj^qA1HwKIVcqYZ(7eEAp&pQ~59u{JhoXid(PB1^lua%IMYRn($`r1(2 zXHIkFISLyi=Uh;jo2^gl5@E_T@gogc) z!VR&D=L_3}fi2HanoayL%e?95`fp%gqDj*e zF^agzl(U-9G{&}$sd>ji9)ZXFP? z9a2%TAi$rlCF1#^e-gvPk>(U(L&W&D+BQ4(`I6w&_7O1cv)otI0e_ZS1q&QJkD=|2 z^Dg6&@0PATg(YJPIDj#qFn93sCz!`pCp>6NH*QAEy!Jx^nD4A2^@3QlYznFlqg%k+ z=t>R2xu&K|3yQsg<6!S5_nu?nQDY^d0I^hY-aLn`m0vmCD*d;x%@y{%?W%;dFaf~c z3sLIMBw9=Fp!UxUov&G??kBxB4_3dV`pW%v#2N3Bn%3>BT@Ztk)BSPJ4U)pgq(d?1 zEvr<$KC^nNUrSDz1_@7!uEj1z$gFex=ij=p2|IKc#eHTSs5s*^Ym-+L2s!FjbG+kpolA@8d$6hm^EA_9R=JF)}%G zmpNX3NoPrtq5~F9prp;$5p)W^#;YNx8~Vl*#MO_+S2D(KSjReOy0 z6U#thVDK=&eaU?^C@}M`rK$*R`lrczX2L$9*zuxd?LtRYg-3R0*B%4V_ z0f&3vby;FjAfKkhz6(a-LwpX%P4elHFv@eIxM0y)Udz_K&hUA0ZjbTd-WKK;Yddr> zOobhC(g-@XhbLrcN=n&D2u;L@V#0EPVfY^W3=N+G*-FmRKqc=kPVP=^*qrt$QfrQh zR?)vUc}Ht|1TBASOV>=r?&MhynE$Nc)B!p75RRk_khXk$Ixl=@U2%26ikq6dXaWC3 zh|M0lj-B;{oykA9(u}t?zmgfDHwf9KC6=TIKU3O!mpq~n>`m+8jmHY2KO?e^`bcwd zS~~KRsldU_D)>cMiUzqZ4dg35AL%x3Q{41G<@?2;htLOfLot?t>kqXu-CXpm-v9nS zNSxY26#)hDZ;%)NRS^I4JpE7dVtbKmCy%#2v8QV%h8hY?gsN)Y9PO}DXXS3QE0_no523q$JR8jsS$is;}<~ zB2*KH8Du*|3ix(llB#p22)9un0TEv+K8RqtI16d4GoXL`OrI({r+hQ8ooZH}WWx-K zw+q!qIY2oH?X;P?7nzSJf_1LEu#(#+4&rl6Ehva1DDJ%j{B54k z0>Mm}jw9WVST!WV=|&hU2uvFiS(yObE`du-aq7g6&?vhQ`a$t?h(GYJeXqdnmucYd z>{)RYxVe_u*x+|r4aHr`c*HLWAo*qhCn~We?B<4>1-saJ8|WJQ$lCT+M6QVQwKl zd0NFZH)l-ed3`O&nwm4LzcykZbjw%(vwe}67R2hL_#Ee>HjyR!Ehc--Bkm%El7_iu z$H@3n=vM8f<2`G0GjT)ZfFi}gx#BmZZ^*%X8j8GDTR3f$IG#9&I+C&#YxSVEIKyrr|2SCVj?A9##$UoC2BNGEHDCn$qpBL z5aqxSd1feanM=|q$sRyU;T220KIPK0PN#q6o!gXQPP5sUZOo-Gw9SJuQAZif73@lw zpQN@$c8AhJ;u9i2HL*p%PCIvLnM7}z`e|}gX7FqhN?VxX(fCP5^%XtyGPG}knmr`3 zyOKXA|8VC!<6In4@VhCw@3OW4h??NsD4!f~qdbpddyJ}c8+r1F$vy%04e=@DpLwg( zv~M6z3$wnW zME#H;$~T@(L^Vf(5A=7EWr^;L*ULQ#MUeC={`g%aMMgr6b?!UjkHeJ{5iToov@@$W z2Udka3DsJt2FK z{_l#|gY>$Y3!IjBf!|+V!y4H-eX=rUqWhPb`G2*E{0H=6zD#*e4Xyd9{Lij5$@Ny= zbG{833+l@v0sHXnb&%;joNq;*NW{#_JT&Vk^GKG(ius~;qRJFnRQ`=KNV2SvwWU@G zP9$YX)1^JSnHJbQ%gi@Hr@Hg4DjsyQ&(l3 z_g+SPKKMtgc>h18{H*kVy#V+){Ec!xx4+I_^cKff!||4wXkRjNL3cXQn4~GuWLl`5 ztz^9$fdMD1FitwZ zSwRxAQfk3sb<3)n?Hd1RLyA3PJ<=r$*ztOI@3nFFTz@sZ3h@CT%mkS0a|34NG!U+X|EtMkC0LL@5Gb!#|9}XJ^0#WP+V1`&_(^RVNZ52SV z?#UVcU6z9`A%TNf!HMHEAG@^MD_U{6B_#8E3}ID7bI6X+S(6E;Y5fIfi6=4WG?*kg z1lZ4dk_EZ$PUodXdauKEldd0o3bl~({y5iz`c-(J3pVC%EmUJyI6&X-=@ zr3I2_^FgTW7}C>%upci+1FU?$Z9#JD)u783;Gs_7aI;y zLvlxC%AKTu3l9SpL(7A|J6jMLiTysFx)MgY`ps}wZHSb&;h0Fx{9B6oQjwp3?6yD~K>-cBP@%*|I^4OCFaMV%n`QP_{9n8>yoJLF65Wm|d~hjV@vr1p zmJrUI6L8>8mQ3sE?u?`mEmJa5wl>g{+2nYy7c(kD?91}6*3aWPbVX;O3H=`ny z4~B$N$_5hB_*k&4+2HBYtQ=wBXY`3AwzB!saXBy|Q0S_Zh#sVzSDKFd^8p@uD>mUH zcbvxK6Tv>3z=rDBw`9D;uBK>;ON=GX4S`stJ?qYRB&|@Tj}1)458|&L$%LyxazXfU zX0B?S_M~|pV+vBLZ+Nj!-v}o;qMB3H9gN(lv#?8o7y~(dc|r$9zs%M!r`G1%1?@9# z)OWKJx%082t?oVASo#%G;(f&dwuh7oAnSdHmkFc^Npy7<{rOm@M_RpDYvqzs&e)sQ zTT-m!^X|FYWvxg90(ib`p^JWGbzUEH+`Hje9Y;kq%L#P_$Esy4H50+=?Aom59gf)0 zn-^QD=dV!O4Ri0qrnP3@oN!?p_Fu_bYV|?U}(JtHmsd7b7 zkt7dUPG-9(yu zB3q1FWZiG5V9ltp${;P=A3VbT`^#WnL2g|Il*7N_vHll1{LiDZb-bN4vKr2y-fCXe z)On=}8$4&LYQH0<38bu*xx`AQfJ~|eq10zBA*uKl($q$?92!QomGjcusI(pUHT-;? zp?!Q41H06hty&@6BPd2I#sS)~1WtMMAk>_n_&XciOm80RJFkn5i;F9-yNx!kmQ&n3 z2!JkxkJ}LNsq>*dgd}dr;<)SwDQKLw*F~G1ODHM5?r*{CtW`PZsdA1q$EF^qdJy=y z^O8{sGp+94;lHSi>CbJjQE<|d+-jCZMMT0O@Ge_O&It(tj#h!L&ut&GRd?Kt_#+O5 znGuhndRCKNaM{{t5?PN{Lz5YB`+84M^m@XMfpU=A4j zI&=%cH6l})iAdWCw-9PXK%*|qRj&l1rqVQ!yVwPL3lD{VABet_)X61+2RWCGo+;fE zjk~R{dM^MA>FR-xKJ1Iq-!z9Q+2ex_mkVIkz>w|%<|sr!ENsYVZ18l}cr;hSsW5*W zIyjg+*bGO)E)6}SOUBDXoc2)l`16qQFYf445qvV4@*h_(kdVs()s;8mF8J2?A;HY6 zq#fWR$PKYg*0woK8aMHkozZoe^2|o{@p+45DmSER(T}M;>H$$EVS<)y)TKcVQCln{ z7+~Ot)+u6$BmDk-2Y<8`yti{z=^)#j*~kY^b>_3F$%2&Ct5q`G2W)X->5Uxzvsv`; zG3C_z5NCXsvF6f}l{^#7O;CM7pGD03ANAdtc)b~!y%$$}%b!J$i7hIxI z(%NL`@8@cRwW&%EKFoFGx~b%c;wj49x(0fo;-H|qw|!wW?Z9M>a!B+r;+E9@apZ2S z_QL;@o3^2lG-&{2-LMU@;Tc$~w6_>B_9>MUce-lmdbYEl__0SN$?ZBGI_OzwirTSE ze~HHN5&V^raOvBGi1l!~M@Y);(Z!>(xy;9Rf)~~6vH0J*pFGC1;P#zUHLgiRb#KsR zSl;7?@rkiY6qBK!ng)8Um_P1ap8IkirE(g|7b0E}b-vIZCW7 zhLEg6k?c~_`7&a6_XP9)ynQx4{=#{5WepyrL7w2kWEh!71!XwFuXdMEP5oFfM%&~> zbVVCGC^ughD2s+M9_j?#!F(YVF=nnw8ulgG+J+_I+^)UCd^J1qPLqa>bn}VHOT`B! z6Kv(xM)Fa)#_w&p&ZYOuUA1$JlbI*&X(=*?KNK}WcCLRBykh;Gx>)ubb#XCQ)rfki zfVouI)G;d5v~rTUBcV1C%rtT@Ru(S^Qh!ripbo0ItA3YC?tGf#CJvdEeMXvIi)=Y} zo*9P4SW0o)4+Er+%Tn#ue6#AfiOY$hnJR@KS2i9xysc3rm^~;!uT%} z^Z&VJek%$2&B-Ae9DOM72m>!@CLc_&U2|*^mPUQD|F&iR!&r^gH_9z$AF_RhH+_%t zZBPe^SV?*PJ?dLYh{(7SDUYZ!v=VHf>?n?EeIk>NORxIKOgp7vLW$!D zY9~lx#jr`2BTo;DOBBMF(<4Se#VNRkxRpE%_ovtve)t7^h96<=tw3WnJo_7T(e?Dh zzdsbOvl~n~z=z@q902%>s4=&{3SG1o*8;AXB`P^^(Ar#qO3`OlC{-*IIZMB@Q%+v3*{g993S!YnFcFnOyaAwD6Aq; zMkVe9L|LVGe?}Zr#yZ^}y;7Zb?FXG`mZv$YAl>9dfL&rN0tmovHui&LCj)ti38jjL zgU+s6yz%hme1C&1{X9XVc9PbUvT>%MC_8=`kJ5^x^i<+l$BD|W<$3`Fp^}qq5V_2i zISF*CIl$P)es3FWjv{QcP1M`zA%y>B!7KEtjS0jE8vA4+3 zs5x}du9r8gF$G9RK*k4iC|MH&Xe0Ub@*c7R+l+bybQN1C;dH*C44lhLPf$HxXvmfC z-2|^SS0SEHX%0s4@^E!ixIrCQArbl4(BQ!xU#_8c^)a?%?A&^%jD!1z1ZIOWGpWlAkdv{txtpmE? zxC*>V?iW1&R=Rhil?7>iz}{J`Z{0epuTAC)$Fo*Hrg z<(Rt8mj6z;$vjUigp2fJpfmY$c!bxvudeZ=_f9Gfvt%JcG(#b6P|tK-TUOtV7lbf{o9vGCG(`W^%VR&N6s99Vl zrm>p)>?r5)n^v~lyt;?ef{AeL5|FY@5=);KI5oOOt7N5)2RIDHKZQ@sMcO%;-4$*- z(Jt%GzcU=uM2^5NY!(vvVd_kI?9R*fC~9_Vq^zA;eJHejiKbvUs+6rQ6%+Mo*H|?L zZKxvNaZ%K!W`x|_K8_aK){2WHpV>?;7uSm{T25)#ojB=A^=rEo zaaP*rA=nA#Mw&H@bj~qTPF;4glCMNj`7dmh9L_=817H)?CSw-jnkO+G82GU0&0ZW& z0)6$UU+1>%9Rd&g;ucoSCqm398TqoB@05qz$JVH36Ua;9H9x$38QKmM_6N?)1?rF^ z{FL^qQmT|R$IB_X?udn9<0Dhey&s|73_Zmaqgb?yqqa7;0!*szW_w%CdM#VNA55a= zEl)hdzhd3*Ju^S>PNb5$oYF_!c(UC>Q+D`z; z6Wwq-OxChXi)3cUs^{hvTytA}CNrA>0YCRb>OWzke0sRWlzEpLMy30UFWLfmlNt-G z{A%*%PZgvi=2KtZw##n|gug3<|7BkON5h^qJ+E=chAy99l3fWcxYABYQj|eX^tJya zm}$`qaO#snC>l;|48JrWp}kwsY80)Kk_n-cDs$NSjk$=A0sB$WPJ@BYL~3Zp#NQgC zDG1~ozQ>`}=>5&^#zE)r{iB(8>4tUWHpdcx0bs`-xuXCafI@`+JqBMxVF(?m&gvIc zvS=08Qbk(3!b!QNVQbTQHs4BGwvyz^cMTN@8IU9$23xHB8o-LZ-uTjNTP`kZjWHsL zsc(R6Aw4Gy1l81`B!l#|k7q3b%+cS1`~>?Y)^}Vjsg>_rUkDVG?F0orONB^$3tZ2s z)AZq3W!`hoGI4hAr*9pw@nV}gT;UjODx7nxgyLF*fGsiM&WvM!a1#0})>omY-Ske1YmO}pCix`)4GNsO z9!8_=bFaXL=RC_tv8FpI>ysac$d|V-OV+Tm`t-MYii)z5!JHTl+q(R!UVh~1SWyA2 z9dObE$!U&Iq(4xIRuCf0-IJ9Z4rZs_}dhD(m3RcBzlbo zYQ|f){bkp(TdH0_TCK&P&PsizPIwJIBQTLT)by48V-;9%#MB+dVPd~vK=>hJXr9t` zO*BWLUniavk9p)O_He3$#7WCb%jjIGtiz^Yh3PzI#=fj-2c>x}957)Uj~yuy+Q;if zY2G=IW^x))(k+N`Qx}FC?fLquz(1Wzo2r=wBAs<)xN#i@L@v@FE;nFs<4xHN)k{^% z57_TI7d<>hBSyAmd^!V1{cXUkQ*t0{iB=~ycKKPEM;iN z`TlN3J%mx5@GYfg?q)XhS(d~5Z;@@D&_vibelFn$!_mhUykPT9-K^lH!WOolGd;Ln-xXKNg-ttlonhktXI}2FtxB%PB-ZPRMtS zI^FNiy2!n}^BTN@n+{5J+PXdl@vSmaBlk2V*OnqaIL%n{Am8F8RNI^xc@dK{{#K<@_oagn+y>a`csa&1dJe(AgrL# z@FZ4Lxlu_2ZO7vUz8mTnkr(h?KO z5J@&vOUH&0gO-N)d6mHdMO}VKr05#nk`V~J5Ez}JuR+|5)-r65&!Um$eDU2$+oa$= zsyEVTFxV(oV$xK1`!5f$I97Zlr zR+EJx%|e8S5f0#kJp#L_TWOq-n7$P&2(MIs2!TRPEcpuCx%hG5OUv*0u*a4Q;DR|* zZA_O<3D8~u(v5&DfC|V)TW47DSW}uhpQ*FHMaD{5$tA{iJ*(+JY|I;R@BN;z+~|gF zzSfXa(Xp5Ep|r*IArNZb46dOYRHM#?h;=KIl31d86bkS)GYD+TP2IWyVrNN*h0XYR znu!gHm?#pu?816gS{3$DwB9LAZWO9=$h@JmkvWrL$e#Sf3c_A#HFB0+ti9Fk*q8inDZgj|~Tg>IPJK9sWao7#~=&0rmR={VYHY zV^P;c?-o=iT!|wG_)ir(xP1L7_~01dLim7R2Hr4m&07pi``2M7YUqnqbX7^3Xg`j5 zFE1aKjM-)NX>UO&8;D5t;RZs#Q1~TWY!UJ!E7zC|1rK9T)ARZvHNzvGL4}!Hsw==M z&%lCW*c%G+G&H)mvL=xI9PHxQsj#w6d@eQxs~!riujOhFe&U!{p9T6@@RvFBP)#jq zRrH~5dIrs8cI$mh7eVJHzW1qN->tM;)7~!$&Xxzi(vClCuW;;b(G!K+gTs5*C()<2 zq_D7C)V zTuZw4>t4H_W*-TP?bfEnPE;;D&HFGXfC0CXy-t24{+NFliX55WFSEPk0na|W`u%ZT zY?E#VR^x$3Y7=hiV110=M}q?U<(jd8#yTWftZHfdqOs6R+Tn_G)@sgiZfrcMISr;+Q2{J2lRQ7g5_6M&&|{FLWl64hD70%v>XnF-b!!Wrp!5t)}xb% z#eUWvBKQ6IYcYVCk`pO_c&ElxM5{njW=Ew0m^vggjGFkSxkov=rrhD}_El7+!@R&2 z<;Dfzpra4>h^c(fP32i8ei7M0w<*@F(qpV_K<&^Go~|{Jb>0~`qLp7|bkxVU9~lMo zIHD7cA;D?vF|?JzjSLJocxa=Gv{A7VPNx5w%ioQTVKz;RPv;PxrbDj8kIry$R`piA znq7e;yNs+0xMF!hFeN(}LaLlCHefijn@ejJvz&6k#@s5DT6=Mepr%{d_2|X+6*gF6 z$IC|pxq_6U|9EH}pOiI{LRZ-Gtf~`8#;QZ04L+Sfpe;^JQEtHsMeS+JCPUAPTlQ|V zQ#e8e^1Sm&?Q|yWY*mc}Ncih`)VUmTr8^ zX7;EgO9L@m81-$m5)9~|8GMRN21l{wGo%7$8$^Se;|4Am7nBEfFtN$*OAD;|`k-14iNTM6D zwb+Tx{~?nkzssaX_*+67bHz#Hn8YYlAup)j02=|3ibe?;-J>cj{O2Xmm~rQsb?3SX zEYahwO78en2naC)F!Y1Tg9DaA@Gz|TwkXY9j+WUTB_gD)r(-^}-~Q@^T21TfWSmiRCg0OlU6|gZYTq3WJ*QmN#np+g;;X zq}9EcVPXd$B8mmhd#?CH&cIuBOiO80A4OMj-sxb6d5GjdRa6sy&IgogzBZeYSrOwku7e;3MA zPoPjXjN0IIudD>;&xOYOaAHtz=Rm1;Mg>1h%YREH#3wT>w{k-P{{bLcQ9zqrsLn+z z4nPNE*d6fuVrG5kXinv{9p%lqRgrE36iRoD--J>icrpe*56gmUUgXA*+q8cBR8$HT zL!{vcV=6MIb@p)tpn>_p3cR5*40*UdfwjkaI$TVk6+I{dfiRC zgkB3Jc6QIWfL?>MU%~66jRf&~N>fT<6Ya;8HU4t1D8Zjy^O#`4X2oT8xFS7I4o*AX zGL=fJOk+oxF~=i!PY?P6{th?5pbH6f=DfPTP09@m!F|~PpHtgmI0p4BrTvV##7^iRN;w8p z%Km>-N>Zr^!#|XA@*hf>@urj-9mWN=Xg4k(4#N78zcAzP+o(L-#4o;fQ1S~j>+~4M z1C=uGO(`?aS|etFN@;RL%(q|phf?a+ju_l3C6aa#V8zhBefmuh=0kXUmM#iFDycs5!TCh1< zR9=0)6kXMA(pi;X2 zrj)mTQcB;T&nti1>HOErJrKaZ|L;6=lYj1@|Jj(wsBu3QjkjauBH+O}IBcFpMuDON zFMMax(2tcnVNaSY_WKfA3XWP+DzK8`QoS%p3c2W8RY=lg{4+E4uv;H|)PO z=KX;;$Sx{hT-EA!^_5x#WoC^$jkNxvA=PdT=?`X7MArLMlgN+`#D@6_DVR!W+1iae zH(f(c8=H?Sdtvy~rM@KR6f`SqlMQ^c8m_IkF-+^JFz|Ua+~@o#Sjc|BcffnVbK$UY zl?fll>MAS;_$&?TW1$S05AZ<(f)&Rp9Yi+@vyZXmr2P69h>TlQz1mmBSfyx-R1yhP z^ad!88f9+WEw$LcKBT53d5W}b=)f{d%G`-q`E@0W{RUS2YM}x)G#=ls?q_$(_|Qml z_QJzv1OzJ{0j3CaJsWD(7m;I=RI^}-nlZz}j7iV7LZ~pTilkYy_4o!O6-64DK9Vjg zWERsgC#@2Dk^_GFE;%!(UzXwf%s^MkVITwsL37MO2L}ZT7!P6bqJZT z0_;)Xc5&;L=kX|TA-qrX2Z_CnWF>N~LOw!?w%95GcXHga@s=y!#DCU3(v4KqkwQ@Z z$YuV4iB-pBUv&L}yk=6xuBbh&Zf>zqY_l|#)v{_ZrL4uYaC~JH>REcAoOgf9ZI&3J*o|M-C&OOfkYDifiJ0@Fc+>k+8wNy&*_$T=ya?$<=H~+!OiZrf!M{ z!>e33p4ctXYI}~y+^+Mn#S^RI^U(D4@4tQ)i9b8P{%XFH0AM$_9{WWdz2gE`sCIet z$}OvKY#gec4Ccu0Le%X^|17u5>}J9@fpcYvPP(EY#xZ!&HDAibZRVp}^t}-_IDTpr zIyl|$D&+gQ5k0tcOub`#ij&y|SA0>(Hm-eZ>f=W@3|JF;m9CVOGCLqyabiU!i*0Jk zfux#jUOw8wEKsHhT??e4j<=h{5g7mq1J z9~xXYU%0dL_?nvBcO%ge6FSi;xgdrjCer!0BJarJyNBybI+luBOr$ljk+$bQUuWF2NYQIUja5C<$RDkCiSgRX?eS{03~9IK+<4Sx z3X97becg;?4t@X&^Tbz@dl1<~E7sEAz=|`|>VYS#H{kZ@<>E&08|MO~n!nPWCIfvC zr)$ehQM&lK6ZlNX2Cow(QhQbDk|WhUrnuif4(jyt$iK?QNb%W|8%)aFNq8?L3SI8gUL`1l+~jv!Pek^8l^Dz=);C7!CEx$ERidI+z&{nrKLp zSuw{sg>P*n-}5v9*VDs)REm1t@l0lnXLi~UfIv|KrUGsRpaDzaUJT05F|1}K=E`J85|U~a6CnIB%hGA)(R@scY$w2JH>cDOuJ=O_VI`CQ3&{IGNLhSA!MXy z`;EwUGLE$oh^2z~jFZ8bwUQYIGr(hdS^dH#%Vt+T+FB97RcOZRtEd~|`-WO(-|QuN zK?kB425?C3t?$vlBE>woy!Ol9Dbr^M>s0fDJcIW4c>J`6fP?%wPpu#f9YXIqmF1(0 zjw1?kd^wfm7|(Wtx?|$hKbz-RyI-=AA==SuluK&a{T! zze~PylG}k~@{qn1uF`n~p!!bvu@MAfbwQ=jb@#Fz@BsF{U&kw}L5VO6Rn6))TxMg7 z<;rsrN?#sjZNi7BJ*m~Mw!K~^G>NC{mB)Zz{e(mSkP%Ejm7YNy)N2d(?GBQ!MPtJn zdJ(&BtBIOk-Dxp)Eg|s0q@q2;P@59=y}3Qbo=1$Jv@ zdAmvR7`^g_r2V2$YkgQ6`{%Aa$Ef`}y5K{2p)N!qSW)V9C=&=)q~OZNv#W(YP)@7~ z;jCmTVsalOLaXKtmYI!#F$x(ei-+lm&Rj>#@?8|E7Jbu2*)I}*als(SzQNnXSziRlJsBY4cIjS+5T*??Isw@-tW%j2&kLAP`4EEq@ zA+Y`_l-^_zNvmVCf*3 zxjCh3tS)TatjuGAGOmR*fO{`Ooj5;bZe5%h!2;&LDab8*c?l8J|5Qw%W!3C+{!t?> z%>as&o1`4*!3zu#t|v^h=XHKM*r{O;{m^1NY$5@&u*(1MQVEfGR{ppB9sfUB@jo?n zw0-x+ILw_UB;i8I=oLo5nj;MPQrvd5y+3mPZ~hL=jD)-QM})GC?)?W!={PRtenN^m z=B*8*;Huwc5~a@FMOYUv;L_ZT=rOO6O+fH~+xKI3s z4&%jF)p`ob1bokb4~Wo%1o{Ah&~m+Rm{O9UfVC`g+ zg9bYyV272qvEc03Va5-|{01$L5NLWA`35bwx9i?PJY?--G@>b0b&jk&#aUmYY$)l= zlN(Co_GBOD@Uh-3%Fj=ahjU=q@8{(K-ZlNB{fJMu)Rs0{JJ$ytJ3gXldNK!F&$F@!q~IBf6yCP0=`(D4 zX3_o%ju1c(Ae-t@Y}XFa%348_)I-EV>q!1Z2s=liQ`k^Li^GOALkXp^1%bItDa{F7 z32l-jr@0Ord)BgHAT&&4yj8@wO=A3r5du%GPeH=2dqPTLcHYNsWFh)8foL!*{nY2Q z?bYQerjX6d-U)``d0-Y~XY%q@gs;q0E%#I+%UPx{!v%tQzf$Wg^@{xc=Q&b0oKN_v za}>8NB8v*sh6iY%GCBEclM~zxF6qb2B3>1-l5nlF zd9l6_sbs~K+6MQfbBw7+Wa*Y;wjk1K%_J2t8@uG5#>!#4REN3UqS?Ec^PO0ucko}Hx8!y*W7dFO){NSPiANtz**Nx{UB<`}$z4s&hGm&bySa55*Ql~o zGwV$`>AjpJO{kbDlrTCpSUy2 zh6}5634`9csNY6w`I-1$M799yfsb0uwdk>1;w6v4XW&>x*5dhywl4bcn!j=@?6~xW z>aTa+nB|@pnHl5N@4nUUXOB~m2&>`&@0vN#>@}dp{O0x<ErHC0UB)< z{=L6REO-0MV8wV_V5=x_uzu0Vio|naFLv|Svc3zRSQuoTp{#x5$45!?xSqsqRrzZ!+B>z%0z->06_7pos2AjNk_$fxZUtm)F<&QuqA| z2iovBu5I%O^8+$Q*0Zwi z>zZ>nl1PSG$*c_aXtD+D6|Z1Ba)LpG?T|*p|F-&|^axKj z=6cpR5Y!VBsQ#ct@>4^miYjF_&n0L>vg3vrCKu&rNLdWvrBEm7hDwR;-}<-v4Tknc zHUmuYK7xb8`Lw(XU$33BWwm#5ndQsIXE|s`kQ+QaouiL+r>;5_{n#lEJHN*1fC^e~ zFIN-XNlv9jv&8fQ!{cC}@ZCjBJ|B0k%ievm7=nJDrSB6w8M8Q>vJ>l4trCJOB<$GH zBZmdiVGqQa+ts6oeU7w);3#fQs;+i%(my@8(wM77jNwJ5s~Xqdvj;9~eismD90_Gv z8o9{!8=kbPN`?|k!E`cYXuQfFlmnhrC*cw?TrN#C_i6q}O5=gpC$C!Hlke1RNlX23 z9^%T#^W|lSG24NRVlM9TG{+z;E#m|z%aiWR8?N~SG+}!VxV@qVGRi&ZpWgIpd0zS} zj%+mRhqXd|)R+KBrOE2WJ)N|AY+530{Ro#{`>Y%zgCeGrBA8qL%}4DsTn6%PU?vzI zygNw){Mtwi`iS3%mvRC)Gd-~(lW67YrqDIkH-+9ec5gTww)tnx!>z{a8F4Mj3p5f+ z%hE?Oung6@(7o{%MWV4#3selFfprBK%YjJy-obeN_wQK`$kH^^JL`~LPOG#7R-NSU zijUvJw1=t(iGxF+dL!vB{m!+V4n<;8^_S>Aw{Hw|c(c z2)8jbr^Pn^eb2(ibmy{O1V?raU#j8n-Os}64c&3u{KWCA)$(tOn02J2@Q8I z-@!5@w_=+&drxv_9LN28-U!lTb-ubw0zAi&OlsR8OJses3YhV-2St5P49S&G*h#n# zf-ceY)yDQvE9p3r==k-HJlkW+AcZVT%+FvaO`=YX$wYse0*m3?&{AhWRvPXL^a4?3 zHR*2s7^h~OZ%(X)E!4};C;y~t8PMgRCay-z_J?xE#m5xXVF`)HNR=F>7Hz6(MMtX` zo#`|?jjf=3LBHQ$m)MX9(132)q-mjcTzd3V#ul~4s(G}6s3WX9vIP_yzbIFPBGU63 zTMt*g_hb&w@1P*L!)x8pH*h29dqRh67ZJ#h8DFV?UE9WmR#54hNTS3O2nrWCys;+Y*L zy@K3;fe7VQK%Ke05b_%AZnK9!qH5%cYA<6z^(D9ygQ{NnYaXP#?w#{L-mCvruK4eA z)BhWgy50HNLZ;2}Ma57Pg9<(CGz?(n zFNGlY5E2Dc1#+s4KND*Rnrq(*V2>P4#QW7_7E3}`f}jgEmm*hQ!2W9D%zU3Y1obh& z?>3xB-~iI#fMASWB0@LmAz^a;ZOyB|Bx%HGkrXETA3jiQW(ZAR01*~pHmRIE_(r)kkC=JPv)&P zz5@lP+RZW+037uwZ^{CqHVgw69mYbK%}Hr_=WbNLl|S*;r@l|@rR!OJwcPUC9^sQy<8%3zxDnx881X_%U*2Ls*< z>@gAfgW-Y!h{GaP1MD5M0iAii1qu9z0kvV@V%PG9Jjp^kRC23yeHJ^rH(rdPopGiD zRESatTHHTjI;O3{FklGW+Xo%VA{@|idLj#TiNXkg&}KniBJx1yE(*g47|PVO*}J-L zpB;&mDC3>-5?0wnYCGqEE*NITDTFIV>j2fi54Qk3bg~<80Lpwk7m5RTl7@;#2E?1im zjnPij3EH@nW~OIudW^Qw=t@0%^n#;bSx@FyoDuKpM3he~?AJD8@g^H3_pVWV=> zPTZe`&tXtt>e%AfoR*kZCo+lHbZ?x)fV0|~Zflf^Li0KM@%X0K>C&+W?q9H)&7VjO zTMD;q0-Kj350fO=@))~4dM<1qYs_THrq2@s_^l4nH8uKqfVjql+KrTa`{U3~O3F{E zYOdP!Cc~l;$Lu+{K1G^#^d5-{iQ+isuibsuqf#kxsL$Wqq!=|a+Ske#Nvj=`#`Kz{ zLMcDergA2$atAtC<@W9o?H%EhEB16hlG{nSLHVtNsHz`SadY~~=?uf#q8)rRy$Ee) z4wCM*OOj@fMUv11EQot+Dnz1%WP8VhcVg6E8<8rZ z_I+UJH=kTj=4{Q+H~26ONVzV@+-ph$PNc&wYV*QrYVMehd!VK`jsj6#?{(!Fy2n0M z4ju(pPM8mGg6noA@4wT1g?-%Gb8Mth=2q@PR7GWc+V1?n_{x=Pt{&(zX<2SWn5c8j zQHnCbx-MpSVy2Y@1A2(e@tsy#x5(%=ayKbtELzrH^H`&OT4>pViUImZKL@ zb`>kPL-)Z08Lh>ZO0g5$$A7uTussy4eeBmCHN^jTO8)!1_5X;3;PRZ?lw)SL;;DXK z=`$bUpIKow_e>8kvOs)an(BjtB!bL89atC_t8726Ob~(37|!jh2i`Uay#()mV-Rem zm1KfUHJd9Yv|jow6bLms*9W$FOk~*B_K)P8HvkiQ?m0=fQ>i8nBm@gIzz%N#1av$N zVmMCbC45TDGke5c5;si4DM(zz(;;iLV);TA<&$d8!U40VeXOy{dahNZkzS;OGAv?g z#6*pCbQe`L*glI&0_l?f~Bq)vQ{)2RQ^MlD$53eFNohpFu)|*5J#Om|^X! zI04HxP9Pu%BFGh)uTKXb68kOK5*2M>g0?(UTZ5{hZ+rQ9r=YrnCK%C65yoPpB4uMh=kbuS0v=~tV&HOT4^x)XZo#vKqSQW+S$C+8A-~=eLHA&x>);8tFJ{e(PDK~~|p*OMo#3>k;Rnd6%T6gD;5)l<{36Ka0i!Hq& zVy4nhXJjvIOH&Gl0VG1wX@1uFC#-pt{^Dxjdq-uNoNf9vHy&OyHoHhUAe>kUN^WRj zMusCMXv#l>nStz2CjL`|)P;KzrDgf>M{w6U@R3Yd+N3->#*s{D%ddiW;2W?02U9=V zeeygr+>Rr$j>Y&lhTe%?8YYHO1}ZL9lbFY)VLY3{w%;wzh9y{cTB}_966^3m71;FT zudKqVcIeR2XdNl~=mu-_38old>j!i_8R?@y4Nnqb*ih@nZtQwLA9-EGqQFsdwY(*B zlIxcQDCk1miJ+Ewtvp)3r0piR?bZgjB5j*oB^_fqXaEZLLZh8~d}24afz#PYz%ysX zey~aBaDbO4My4+rPWMNX~i- zt3vSH`g2?+WgWN_maKx^P|$bXzySFrF0?P`K(F9}G~odB-K6v$O)}#NaBHPRLK-d7 zkKAA4hm-=qJNoGnODE zLVOh8+`!xN+uFG%oAPQ*j>FH5+Z)_|SgEq;HN1lV^Vxc1D7d)@5VigV`2B76-M=^# z|5uL3pX@up)!J=JI8RW_iJUVign+qN5P_kXYk8~jAKP^agf{0yo9*5>Wx`Gs=p{wu zooL{qBt|B@eV~;5CG$=30+m%4r#NaWoP4)Poq(nU@MuFp`5Xo9_H}&S|>{EH@fGEMO3laT+KNWqW8VN`H~wcK?`V0q;E=3-_?i zsr%1=8@WJOiXVZHkHGccKU)92#PvTJ!dj0B`*7{%lK3Q(#kmoezY^ZSlYg0?A2+IQ z&nAs*CQWG+d#vkgSo@t=&QNp+y%lNB)^us0ZfByYTdh`1j7u0TU285N#RcZ9zmme&Qa)8r%`O>|M?DIS;e1i5 zTk}w{MlCM=BqNN!rZTUzQ7g^(UE6!Tih|i~R9_)+kpT^pN!Anr2`3*|F2~my0s$?2 zC{Z8RJ-9N{-jpB!1S~3&`03WYOhUQ&X+oc<^Cs7Crx76$s&O@duz_Hy2KJ#JIbMzF^RtG&Zs)@{Psx`aRnZ}v zY+R!pwojfn2;hz*&nP%I+pU^J&%_9u%QCv49vOBBV8xGG;mAKi`Li(La`j}I>z$p< zj}MMi=1TEmY*JL4_A1ltfztt;;CyO{7#_7cyDIzyw))kQTd|ZwXFaBcll=B#KVOR4 zTZN^@67@7L%^%?WRhR&UqIGTkNNq?T=F5|$rHkeEoT+uMpFo^1dSbx699t>HSe<0f zS~8pza%1Z02hd~x7c{epAw<)QcGI3;(SeOVxM>BYEKIvDqv14-P%8EzdJ%Ptr5K3R zOfJ{qOaaW8({~QxghT({nTcva|Oo^;%9TrtXq zAbtB~&|(=a~Tp2&A~ z2QWpM+kF=18{BO+ITm##Y3LKfe%_Ul%vP;sUn-4SJ#z5^$ur^9AV1nOqdk~0-0x>9 zzB3C%PcKuZfz&)Nlss)!%H1Lk(Z#{IP96gC_`+A-m|4tuK3Wd)qAVgFDl%JqEjLtO~AUdyNe?yn28%OARa-2-tzW(6(jT^&cy z1JA0Pm%jL7Bw3L)&Fv&|U-~jO&pfM4U#}++uRB$lju}i?zaLdkTHymh>JY%4Y)tQr6m=n5xudG zp$T*rjlwr6h04{9)N;)H$)DYDW!$=hUNUoe0iCvSE-o5luyC1~urM>ch22^%g-!(E zm<2Uj-F-SecmDyvd%T>v|KMsRb|1|L@lyrL#%1|L3Y3lVs#m@DlSc4FLGf0a3?KR7yBOSJ^J;}n}2;jqz8YU)-{u;O75FQ{fA#;u_lI;fX0p)7>w zCRmgJzY2Ya#fJQ9XbOoU=U>=cP{{Y3{~2Qbl#I2nj}TN~@yW5b%}Fgdsd&l_4bG*z zoA8jh>c-$@M%8neHyhu+w^tscS^#IP7+=mVaL_eN3Qm}?13L2?IRJVD0VS6Z^hSQd z)`N(Wy{FN$wldw^kQZSoA0fisVxXgy-fGqlR=)QJO^Plja?-8g_v|jEGtJwyL1tLE z88og2odB2p!S=w;uC`W&X12}Y#`p7~0Za#}*3D%A7j#QJ_jKm+M!g^LWcT#8_PFUSHBZ-P z9atM`=Qd~362>xOWbH+aA+$6oG#Hal8%sRp$np}s8nv5(0ht_VtDTGap5$d>?k2E; zA1}g8KV>YPPXj5MU~^nje>(SV4(zH@{(VT8cg)gJK|V*0WNCvk7V2gu2N;)Y2fl#FSYiLpLcsF}`fPh&vOY%R73gGj0#i5FuL4FqIC zE}bIkQs|n^#W~ZE%xP(rhyv8q3WP4^cXpC4b}S){wFhkAsE#wjaVG}(ec2>8Wa2~A zymh|p*BuF?b4(uL?+lBc6o%numIZr#UH7Q(ku|!qPx7+70kQukH2NG$if=LxUH(>? z$h||9rEWh`yARn)(L(%PqhjBqg*4YfA{$Tn7_;s0CsRhFkzJ59A~@T&neb(z6N$#} zXP;Z(<_I`Y^MO?wrCjhVduCk}>Y*fU-aOKSNSoP5%|bI+4t56I#%nt_h&$N_ zCrAEwGGX4`VQbD-eMV(xmVujEVX$;Lcj2HyE7&p(#9mV^lalM!{@{XX%jXsBBv8?~ zh3l97p_$uF?C3iRAM@u^uJr2}cNxTYE@D}~P9LnLp3^h4&V_-~2*n6&SJzJOI_V$` zyuKB`PRl@RCZEZRCKd${{wR%`%FW>)jY!6ENQpcQI+C5;!3uwgJZ|KA7ee+GTzoc$59KKh@a4~qn} z7?fec@Fq{8eMJ;}SMf+Kd3QFavSjFTf>LHhe|Mn*`b4>d`km_Bn(xP@$OA}=6~u&? ztBPe#%7MJ0Pz7~Lzp?dJQoQaY2a%+{Cr{B97FS`34g&|$zaCP42!B}Y5CV8S>RU;YKc z-1yIa&al^}AjbB%XQ$`J{wq(XC%{LbgP+xILWb)dcOL|&@=ZY32IZkT{b^G(j~LRSz1xD_uA4(^0g0IK6e1grVE<0_s8^Hv1u&~ z>DMwyAl$a&1pd>4`9#VygpsryT-oK zOz4uw1MMd;eHe-twW6HMxk0H?OaWhNjn>}GU7ApmE_J9juJ8Hfl3EDT@?({cu;X;Z z#a=nviq;c`xtQ7lmfSecdD_|TIRN@EwwImT+KxVX)sZLRRLW=Z_BB3#SJ8_Ol(P$H ztW3j5S2Ftj>aNJW121r<<>rO=)~q&VlKr|Ju(UQ*5<0hHUmzCUh4;fE33Ubh1{j@2 zG8vXaA2B9Jj%%ecufCqK#1vv3leUCR%8FJCbzLRKEK3fb%B4%Wy)>Q7Im1L|cU3}L z+Z`x#6T$(w8Qo!K{DwYV?-@QwFvGC|W-de~S?AgS&MU89eh5%v>8t1Br|7YBJ~>>W zuEHb{58t+vA5gC+Ij);1?-U|4M^dXwL&Xy@lTdL;^EUduD-F zrQsi(L4q+&lU$9i?qma3>e})M*h3ihoqRA-WW2(fgTYLZ98KDyVQf`PmADk9AI^U| zQ@{0DwaMc&O+;gZAV-i;pTJ_fw->j=7F*&tlk<0PZ6*z;3p=R3z+M9PNP{Ko1zFEE zFgn>_xL3Y@p|*`{%OHh+ELrt&s4UKmQHUVlp$%D4w&!P#s@U27v4>kL2hCIW!er>L z7&wvPEoGMj;~o;)+!^AsF|YC%_j@oAU1~3LpMDYZhNx0%BDH_bRBw`CMX{PEkyqGs z>WlXGRC0#rNJ>}#rijOUy6}79i^@2J8lYl6GY19<8zQe0w+Ze9lRJPxQMx#DU=3^| zvu{m~_~zZc5NyR_v=O?0PZV}FDdH{Td~14d@yEK}#>UI6#+l5bW&?6W!(eIm;yHp~ zV)t(Hd${ktf#fyrx5WdlupRmZpab3* z8cIU^X9t|?>~oZs-WO;-G3l)n+6N24o=ud8f01KZ9n8gREG}{XKILe(ZcK>j3 z>3Fl6~o(q zu*iyz4+0``>USw2~&2;`9b?JA8~#UupIbQc-`qe4e}dDXj^GaWUcEPL5-tlgCswL2lE` zVNCCY2o#AETx{poVsD@WO>XZ#(YzhN(_gEwh3(1u19D)iv6cX4<8+h6kUC#&#Vf6Z zZCu)@oT$*#H!*EGi+$o7q90eGg69?NIBe1Yg<=c!5^Bk3cay+mG7?dMLU9~99$A!p zX*=*()M!7mA~6fYM@L)?yXd7r#$h?J;7^h1)b4up%hhj_CBO~o&WJ7!Njzps z&7Xtz+<1RSb#>66U_r+Jp>shao->&l-L2iDqPWYJRxA`}NrqJYYDWrzJ_B(TQ(w=o zX}s)QvUF3fzvv)8=27J{b#q5`yQiA&qdv%Y;?Zg1P_t)*`f!KBp@gaCvt6|WU)8|O z^Bpv5qw{6`Vmbz|5%`y=#_`2!;T`j@*5J*hX=|W4^X+e?r;XP(4Gj7OZHGBgg{-T3 zE>qTE0917%e_MbJ$f|gP?`3_QZncW z2U2|X8>b?LwIHDNsH9HGK$?P`N#}Fv6zKk2hwx%))DS2VgIyisM9zUrA1MgnchRN4 zO8?pVHrWOs?==$pc%J-4%lnJ0q2kH+IiDw~ncu7n1^Z~&3c zs#k!p*;+p!G@*n~FKsG5Y}P2BMpIHg*+;9bpT&)hfzU)H_T(}lN zdrWF*rUf`XwOl{)1U_~DJA|Q!wfpYFR>#MFU-m3Nc zRfv!n4$UQ?A4T9aC7r0p-`oXemMZ|rWNZ16QHGC`Hrl6{^bV;pjA7E1Pk(N$%yahfo{b+wh&L52LRqg z$H@e&E}TGH+}Q&o!RD{dHg?zBv0DpRoqoEex7BdD1Pnr+^zjms?&doIz%KkOdQCtMggViePX6vZg zELV6CEcK38C%g^5Q+9cUDZ-%ZEDpx9`UzC5ovw(9uH@p$5lY;vCY(M*(?bdIs%Zt) zM3^>3Ueg6yk>%smB0$}-4C2*lq@2fcvGDf9>ier7AydC-XBa-ZHqs47_Ve#*K_qYl z#@tx~kHP*QvF!Q5XSBRY%>CuCLZ|)tk6U4Vs1D+y6)y3vb!m~&8p9R~q?D`T79#C! z2XVh*^V#Qi6XFXkzi#I@5bn|mf8$$T=3RCL;HrtGd9sIF6Z{TYqCZFRjlL&5M*h%_ zt~GsKVM%qFz#F*`wQVq`&1B%O5_DSb!(+L@>cy(^{8ud=kZ;;F=U2y9Q_u?DGSC%a(+MmXf-`ZT}>WGCe}ddhD>Z7AA!S1F#gVWUD6X~VCI zYWm@%ScCr3X24_#(zuTu{(MsQmV(sg88AtN{;`?`Deub?=>&#Mnj%BLH)Z~( zp0&uGmjkuJ(Tl#R{{RIQl6l`MF0~-CZZ)e6m~?2;24~*GD@XQS4HIT#mD&PMEmn}x z(pJF6S9ba{k|bb2)Ufh-2qaLLE0eqv%lP?c8xD;cYZbpBYY6JNSZ~+{Bh>t}Q##0b z@_2c2Ce^1-FQLetRlN2Zq=(anq=59VmOlp09*wSr=XWG~y2l4IVtmHyz1q;1;s$v0 z<@1@(2N$6`3k(y1luAKGrxDMPs;J@6$*F7NDEEwMze8Mp3yVuDajOBd@Z-VnKbwXBez*S1EEHj)+g8xT0L;SkrC?*4 zVe3&fbcW+XzLY088!=Pi@l-7fra&G>)afhBe&3E#s`<)w!GY9hbut8Yp{jX-eJi-T5<68*~X};gJLjt|aJ5 zZo;NAB3ZSAzrkT(An;y5q@SMZ;uCuUu^jk&iy!P0vYIFZ2z(el4WcCA@d&EJhq3}y z&~QW`&Kw7lJvux%LZ6Rpl-1TaTYfq_IhTDr`Bf&UHVsr>v44wN@)Zw@{|?x!CAK;c zRCEUM(05U53Ma#cF$%<=VrJlpXOy28Rf=yaVxzaE62pv*Ibvk&QDS;rg|67vT#555k&J`RfBp_?O|rfmnJs{RY_Fn)$ws@oOGmZ_pJ@){blR5D7K#_~bL7;!(GW3I zI|OF8C5nHZfTEtJ={xuvzhaEJgZU?V?WEM=U9v}C#w^C_ z2#Px?wR^e3*5A>5zhWxcnGIh>Fm51tlc!38za~r_B61gj>VmW3Hjp@6L3s97v>vMz zg<5+iN>%K#eIWRB%O6KaHY92y&fJCz9&^LKy(vyRmwXW~9R>!;K+v;F;;UqZS(BL` z!?b|vPiv)cp)DW%xug#AOa^st#>@8`;f3&kO&}W6BM6goD(6?c@!*`GOre{!K4w@N zGL$2yryYsKS7`RQy87f0N*^}Ulkvk0b0Uo>2nO@SncwJ433Oy%bR|ZyuUHKQHl}DT zEj!_hgFbO&5z0C$iId=?DV51w5sI!;#f@scnxz{C$i+_y=K!Ak;_sn%j^pkPV#Mp) zMsb>zN)?Jwk)@jYP6H_nJ#&#;6e@5k^Qv(k zGOtKAzfajcnT621TUlhg8TRrda{Sg%+%B~Zr={Vk%yOw=^}h0De^xiV0=)@@ZDuKK zlc~TNzC-sx8`l;jTL$%732$$}t$GHG>9Dv6am(4*pf+EBM!)0{j}-C~0v6@cwt3GO+I3v)?u|Y4vRdVt4Xw%Y>Y` zc@Ndn20P(LBU269V>N+hGg6Qfp%(gBIaB89U69A*i_&C~c>E1lt3t24CsNh%7Cgh2@Y z!bd?za@BfWQ1I#JwaZE@^kGO4!VK1&H+`YloDbk?ZC^6#AAt}Q7^|Y^_tnge+ADU< zQNjqWo#Wp1Z9il49q^|wo{HvC_@7^g?2oU*?m@`6G~%T4T20|aHrzx=A?>ghg`$`G zP1&Z=3Q-o7Ze#=xz-gxf)mwg z#gONZm@~KhO>#9XOPoZ4;Xt;KOFTQ}-aLW)!j~aC*@?oU>g>jV2M7A$*RfCbJ2oWY zK3T*EY+&Fl2wG8>*-YEb#EfPOMGq3t_RHwP0D>S$n8lBg5y;Vf*^@A2aW&-{%j_++ z_D;@uA72Gt(kh!9ZI(aKAaU{G3LXG72+I9a&6OgKlfs7$(Gvivwx5yz0}Uc#4nTwC zrnO@HkpzL>`m$(ZKNJq$hxxWgWofUe2&gYA`iUg@Qfd3&%d!b7B`p_-9ZF_GORO3+ z%fo${!hArAT2?F2eEX4paAVaWzdWgVY{}FOUy4T4GHQQk@D}7AafSonvNjyRH9K*D zv?7@DnGChLOqR^~OjC6;5Z~~mIY@5N3y9oc^oL>A&`|>*r<3|JCQ{;>$ThES0}e0z zPt5Mxvg?P0w&=|6JkEL9?ga8dcnXeg@!yCo*a<0IIA0V7oCy2KtfZH_Om-gfKFF-k z@6o1aM}*QFGC+k{d^lUa@$Y0;b)Q{GC-9&S&W4>LD(yDf_BE3C`ic={egep>CxQuA zfMAIeK1w^B4aFSN@KC@>uB7X10k6P!8&$^nm#Qn*8a-Cs+mN7k3{zFD-x-S6!o(on z;DWLRSP=?Q+IEr1gBVo4CpV3kRF|cr!KGRqMZjDv#2T;YkXOTtY=5eTl;Kyd1ReT|$NZI!AP^MiR?u@tC}bEB+7y z43fiLqa}}vMAua$yQ{S-hC&_Vw8zz(U~{)P?kvJ^_DWxg&Ucl{cy@TATa*dT?VOo# zwT}Y@5HnFmF1*9q(up^rI_S7b0R2U~ozsjXLQ!qD1VNr1VkQ^&p61EAw`P^Ckz?~Y==w;Oz5-Rs$XMhVaVnSJMQZ;U8~RYh5?^rcrxkR zhy;_~?f$gtPQvLalD5wHsst%n8ny3Xp-xz5PHFFKJP63-% zQ7vJ%VGLV~9hddv+pzw@XH7-G@|b;cnM<a+uZ!;Z$lbIlHbq& zWMlsCnfQNh%z&AQ!P|7|@o|lY!)iBlZCFn!LA+tqbFoCXS@m`jhXfPHc?xjp4g&y_ znw*cNs&%hjmSUmL2Df4gSR&5A(~xrSz=K_c6(GBXL;VT!p>6!Wl2_Bb#Qx$)HZuID zjoC%?EI1DIm*FQM>p374Aivv#fVija#@tfLac0&mf-NJ#phAtRr+Tt-OVuS=vr|Q> zyoqxC)&-VEYlq5&$lLw9;9(0xJ!ERmGLJ&V*`7zncu;L>Agnoy1b$;fr9{wynxf*i zjBBBhCAr#Ab`u~ykS&%44k}o1QRS?8>3+nu$Rg5pkHzVHR^DBMK#!>^$}9Qc^4XnK z9DLLv&ddtVL3nC2&~pZUyhJBmVp)77LF3+GIW?TvY*JLqv|vEM-c0Rfh>X{^^I{yY z6n=^rk3H7^E3ko~ig(C2VtuV=5({>K6EU+J<;L?D1OQnb@(tyLtqT!=tkwt$YRH4O z6ir@~puxU4fO2=YKB@IXR*QN~{!Su^Ne`Y!jR#@4i+XZB-na z3PFH*8F|^`&dm$ZXHe?UR%>PZrU zSZlhFZ)-j|a_y1%9#WET>XbLpQxrzbZU{6WM${Xiij75m{ldUZh$j|GjD>N6RtqM% zFfC=1*=C;3ox&$Qj(y;11AsJhnP%H2Hbfw4yC|+05>w+$b;ahdP2(m(B~dXr4oquB zS_yr-*72sh1Z>Pdj1NeIThf88Vr~`2o)WhBQnQ#Gpv}+3gx+JPbT7W(LA0W0t_*)g zhI#Ds6Xo{%!V&@Qm3tnGaj-`>P(JKWG@^ZRWb4Ud?y#a_5cz zH}5I>bEW}3Ou(0+x;)$3Jg$~RuTp~;lezJUOnHq#!=(I~`0=L5!E!TTCa|(HMlI*@ zct>Va=sl_O&xl)Bl*YtWdnOxV6KzS#Run7J;{9mo)4yBb4<3=6nM85-4r_&Ys7sR9 z=LCOrC>EYw!Xo2NC<~~IzyoL?aYE~K^0vZ!p>*+v38Mf+e!)#)D8zhX@@ zM7;z{iQ{y~_a(YHE3GDoVrreCY&l)NKqnDRRJ*U~|8TA+dN$DKZkT@WJ%Uf0WRDet z-Z)c(eY#W^9ZgLEo0fq3M`uwQd2eFezMV6d( za%QKutz#yS@fSv4^a9B0m+N20d)lYg$*yVl#wov67k?miMKJ61ou`g8Vs6sCRLVF5 z$yG%^vpQWR_)8=gE3DKRrZ25~5oIAr`2`+0P$E{T5^S&D@57!J%UXHwd8%4d`-nD5 zf~wK{H6K@?ba?w8ZO(tIsi-~P4du@d*qonxI(qs4;t`)L{lg=Elyk7IDGAXs;WZ|O zMSRuD?*)-}iud~wMPyJLhj3mAE!gHm@M1)YM8iQ$Sx}NMqFV-|(wH>Ua#T?BeLj;I z*x8&=>en~&MQ0-B4uIZ8+!U}mr9{*@4<_PRp4kp6R1X_$>;6vMjsf2PK#Chj!jjL&QOC6iq1WJZRz^x z-Z)MR`JZckGSsU4Gws29-!{qPL+Ckg0rblo7U&5Bo)QR%>Q_wY0?s|^1ukddgtGuK z_Ja8^CEUAR))2GugY3a8qoS!p{2uP;5td~Woni$Ga#dI`rDc8+dF+69UWxp<5u}7a zt_hIX!yFm#nc;;5Y>y%Q?}jhf;YqRIQVB0H;QbJOuM&M1A<=-}9x4`oumx!(b!@}X=NEbgmv|(JctFeLsUXBI1jGN)P=rKWr^p?Y zgyA>TU~6)6wK+WNQ78fXXeiQAM`>T=f}(vi6i5GPC`O11<-dS(2{@?<19~?^#MJMH z`YBzC5auD6LYjTG8m1iW^aMmYfQDkUh_0NXO|0Bj-R#>{jY+DTBo6%)(rF}GCO(@{ zF(Yf)@W}1z7yI71u{6qj!{xrSC$d!U1~O#VDTuh1>|7gLHNPe)v%7(kLnGtxvSg?Om({yH~&Bs z`kH!o;xJcdQmHI-rT-3I-`f6lK$q8xXSu$d0~v$s!2SrtghOI!2<6Fp)arl%cA=q* z`x+~c4V3hlVs)u2&fID48E>}jRI zEg#q@IM*g-&G^uKnXxO7X66gk9b=_VGQQxx>4$*E0T3XD$0oH}o{QSk12{kV z(1fi)2Ko`U;r(9?gI%z?2x zB_lmD3EuBB?ns(nV`dimyMZjZwE(qLnnr#Bu9eA#X|q@0g3wAUm~TVKqor zK55K`-KXw0tAu|gTw2J)LfY{Gb2aY6MSjpjz>gfZ4c-Mm73Do9@dReU>3L>) z@Ix0J$hgCbf`>jhR31|MEGj$B5!+2n=!Jo0XEvCJ*%s3qk^>w9h;^t=(pLV^)}d(_ z%K_9BcjqmW+sXYB0X0Pm7793fgoVDmPYN9|?Sz!M1mk8vafl1N9vGi5fCN_bv8Gk3 z3(+cr(1G3NB0#67Hjbc6Eu4`gyxm81SJ$~;?Olz=QQ@ygu!_iQrax(v;iAaJv-fSAm=vG1yOW9~=6PGx903Nh_7_5Xa1c){Z+{S~0%_3PY7E$*2hZ6{P24=Y($e7F~s7vW|vyb|Yp&Xz~# z26t2SAzbTMF*fj(hqCJLVk+hJcmZXQd|IA1Wc;yT6Mn^n83}D{Ku|$C6FX>{QUZFG#+E6bF@_O#&$oCvbK%dMw9zEG9h?j*g*^)!AQ%2BlWf z6Z4vshGbS){j^wCs|@1Ve403PxEIv7{0!;dMQIs+rZBC)Eun70FcCcimbM2bxiwGr ziAj!rLTjXU*8bWGo=YOuQ~TGN-!OK#z= zNkWSldz`8`Acc9GdS?vNi33_3Sxkdm7U~u_Rdugi#+g#wyvfz#iVMvYhGrgNf$Hu0 zWL3!xO~B4kd2m7GDUYjA?sZZwq&mrX1Z(BL8ON$KTU3H3#tkUX<5u51a2H+LY#o8;Ii35}X!8sy`lXdyYEX8$7079Q&=k+Sb;hQ5w_ zn}y}0_1Nt+?TqD^CB(NifvV*`=7@v_lgk5Xi9BBne76emEwz&VIf_y?+*Pc)SZ%%dFZ~ED+TECs9CYf08ahN}6_VuG{HfGN$|(^A0M{F# zTCb@gDQzSpY*1L80+G)trB=qU1&tcs@7xbW4DI;Taona2&QGi>g@&YwVnrsU;0Eo> zHIefib~dhTwtuvJvcSa+YO;N ztN|C8V88{&CepphCI|mn3JQ(Xeiq*nJ;RJ~#-;q3KHlX%TGK#~R??SRLaeO#Szjuy z`1MP&?=-wOmEf3l{p0=vS?$?jb+;p(2j>@q0%SG_ z^TA^c=fx=JG?zxsv}kG67a%-pL^qST?Hg1Y$0p4+hpR2onGs*p`)dCp?7OtIjb%xcsSay|E%8 zo%8z_yS$dWh>)FRs&3flEdAApFI$A;Afg8tq;H_@2@h5jGK7uHvl9kxk#~iMX_UC2b zcDcU0Gy#xaoX&V9*D& ztA4E(4&x)M0t_5hFO|}>x(?9*1BWl31MsHcdqGvhFkvu^u4T8-vPpAVf*x3=KR|lP zB;^`?;%alUS;?H$*;LWY#D2>$SS;&CGORYv&aOSBBZjRrEB`3b%x0)dHaKSp8c#as zO!v^d9RVmW@6kitb<937u^nV)Mhd6U;`!LeS9K%`hXI{{eHSWYZpWXmxUG6Qmz*Po z8Q(2(F83Rvji`=D8p%bpXJbUMW0c$5LF`67l(+XDgB)sL!9VtYyrFKrdvAlMY2=O+ zvgx_Kpn!bV-}0vFGS`JOJetaNS4>Z}3965Et>LZC`IE8j#(L0}ih_!|lnxQQ!i#s& zTFaPzDNZmvuh8^fs$?&vt{_a2_+UL~SEJ9Ydb2f_-gDo;qb+ zpzyY{h=zN-?9KMiKPq;EYKh`2TW}0*z#hagIBkq<@_$A@)?dPp0Ct>E_ET<_Qf@Z1 zsc1E7beS%V>W-A9k$Q1eQc>n2k#eEG>2WRWQ^2BXvyxxHg`(nPj3V)mS1S-bE7%<_ zT#t`IA51n(psHLtP^{u205!%C+K`U)<0i(B97MP+h|}87cjCHcukoxb*76S@%>0>E zQp6)L?x!1Gg;SGgY`)>PCdgO+oc9alIw!%`{5gz$MA*!|ik`MPd}LlmnP)CW5MA~H z`^UghJZ_euFE}tcwU!>sog5}K*1>E2o4|WBN(lSL3FhE<=;$Ky2%IU;cyZDci6g(A z8Tip4>4I9GIrzLI<;xn#Pa{ltDL2P(pVx3QeDGmyj&!ddZM$|67kgiBnR7j40IN6f z$JnL0SHIPWzmE$6nSVXBa z4bZY|OnYbnKrzXb>VAOS6Sz&#jI*jS)IpHFTHnda)U^6ylK{tpwhL`q8Pl_oKA-Z8 z6OY@fH9<5^4+GQ(qH&d;pn_SxtcUFZH8DA^O7ANU6<}5eYjO8o$wC4Sk}Onup;!p4 zc_2lrYX<3yh42i2^P&$w(P$uCKu)bK7^5lw+>R2Hu7?U}!0F>&y5TOMMbUUJb;bv< zlL*k>9I)Y^dUlXb45RNm-uqbHM}YYvTeo*8?llR%AI<|j9Oylcd}N||h)aHR_Vp3;*A~VYj7#g;dWNi@yG7cq27x~Aa0K5pyKyi~fs zX$o4s9}rcpS9y=bbpQ6W8=>qCt{*d@_ONH|xj3v7Rx66hsM>X8d8<7_-mi~x&zp5W zJWC)Ta+_8#V^+#a5^0vxJrpOFj`H|J`#rSbVZe8u-L98!!#PgU)oPM&W5fb~L}^pp zJUXhiKtGz9qTJ~oY`?)(2LOzRQa@q7{2rNjr0#nA?15o!6o{9!?YX}Z1^+NP@Mi2b zHNr4Fclie}vX5o0ZLG!%lChos0Y+6&QP9 zU-)e^`c$h&rutBv*okh4v5{LL`KF8l`VJXrq96@kT4c>OF5Vvz`FXFkF+8ER0B5ND zUDc6wa1-h@p4Mq{cvEEO>&4MqJE=F&t8|PZ*_Ixe^L4?rmLHtOjYNH64y_&I1 zfd-KPwMLIi+k!kcMZ2}kYC4J;4`3 z+o(r~z&HGKd0dr7rd~PX)q$Xn@&4<$E~5MZ=MQK8%T|tm;Nm}#=Kmp*`o9F}_H9mB2l*33 zWV|q$9YQF$Q$(TPCGA#!>R$dukd6;`kFv}zNXLttV-QDJqY*AGX~Sy!9?qV$?WjWm zNTfz%Wl=qDG^*)nR61=t8bqGUBxZ1wSR#VwBT1mO3$*bmVL7-@j>1K9t{sOvjgKCak&I5E?JyF9M`t!|ua)~0LZAEfy&<(&NW4McBC z6lGj*K#}7A+d!0ThnpQR|63eXLnk3^s+v$d+((U|pBSTMd#xi=oW)fW^=b_06QEwV z0V)2Ul$JI`T!Z;%|Ax9hMT&=cpcmy`ZYK+}Eg2!O`%e5tfnTE5 zyCf^#xPkfJp9$z5MrIFf*`}c(cV{(Y(H;%6FLT_0xc38UVb2={EXU2O8GeQg<%<^W zVub|no=^3dV!{)Ge#3``?(c#99~_1d49=+1?zYmHn3!L&=pi`uwQU%xJr$cc zL$cGn52c24*XmtNGPw0|CDVIh8T(LDXTqw<5KYmO1RmS5mRuQ>F2Ek&PH83v`NsL)nnym=Is!)?=8NJEqpNVI@+uP2rn8`0 zai3V`C0|rdC_#r1+1tg2JI?1UHhsK~l0hfzA_DHz(SzE)d~&&v%PTNn$;gsjJjpm; z3FWvb`w4UWQua}es6C?Sw)x#|CDCmv79g}tqKz{_-|6FUs_G*^E{|A`Nf}QludUX_ zy=bk?%pFvTGA_X$7kIT7P`XJ9C--ZN*17jTU>|XQ;XiaxK2w#?Z=nHaww^QQv_?E|U@USCT8z1U$Xr3bUU0%;pqriA20yP+OKK`@h#9iXmZ(DFK4bJB zotQEKO=vJEbWgnG>RL(Rgy>z0g`WtUl*Qbx0cv^6jOI4N|Qo~kPc+PtH7|YRtLbHSKYOvUmU~h&&UgL%8Q1A@qzX`Ml z0W&-hN5Bm4C}9|r{7)~|mFuMa)?HRKP`0qXqW5R%5E=%E8nL?3OtbT#C+Agat|UNDWt3v@ z;DTJy&8#8whQ97=&S1^l~Bxp43?%fYp zF^BV;HLkxWUJV^>_trOFi|*?e+A^4FP(n<}ejWUQ!G_20ppal%?Wj~)K`o0Joo1NO zy}(8}RiGksHA5hfF}`h*XotyBlXQ66YE+GSz4@{uFp@{K&p&~}?X%+*%oWf9CODMn zFKRE8PJzcEek}R?QiE!5Cjb*1Q;4Z3mXzi|nuhbY4k#aae1P5{n%*s_%t@V_+xNm} z6>LA=oayhwpQLBv193&lD)1e1HBsq(wKCq^>nSY<`#%4UK4{QI1y8mMMb_$q*S%i9 zn|#HbnhYVm`1iUE*5gsCGB~d@xW3=FmsUglDobN>rgK{q&#jibv2`8xvK}6s^LO_e z%~*FtfIKaIi66U#9S7-9)7+o@t*yQzT+7*d(fg9`gW7yjU<*#cnd%h_#?F|_2{XL^gV_OGIC7F@(mfdJsb)CpAazB?nx}*DSv1B?uISKio;1j9T3Y*d<`c-R zDz6*Az{D;=r$%PdO~T~-1fS_Vvcr{1pXZ0M&3MhwZ%e{)>4}OqV{Pp!VI8ZtV}aJY z)?pS;j@BhIi?A$(8MEdD#&Zup&Pl04ES(zkO)qw~P%xD92UylvdfC9%J&sp{;~Grp z5gblHkRFLash~jx&f|db*#P;bZanKm_x{9IdCM8JHI+?QArZOqj|2tgcZ;!=-ep2e zgb{gy%dqfvjsaER+GH%)QwTWKb@t7~Zyeo-I8%33amQcD)|12gdmK)2`j}|i6azTV zoQ+*gzDY(BJ3e~DG~Mh=&WX1x)ktGRRt$YEac_ zvITseuA#a3CEAT=@oL$yMWe73<6`#8hSpLcFm_PlcTwrPlgH5Y8b=$r&yULaPJ{Bj z3|T8FtPs9Op>VTeLkiygdSK){7zu(+etb%+<8jUJ`CaB4C|f+0jSjKv6(v0eF9`n% zo5)OW+l2tSy$(2kZJhVtt<(QQnBLz-YE*y$#P3r-CtM;p=2*_*3j)8XTrk0I?j<0q zn!3F_IPWtn2+<+)WiwsfqV6`9kb7|C(&yPODt?YfT8^TOTJXu~PrKrX9VwTH63iS_ zppGOwc}2beYbSkF%OwP|ya~0H*1ms<62}y35m+wEuiqH5kWeqz5WYh?UqST_6l44c z&K<4fe-?Sdf*LaQH4pLp>zDZQ5#ji!I_%G8&0i4fbq!7R?Pv`Q z|F^ggE6X_%OdfKxjK$5BTyTX`uyl~qXd?ClK{zu~a>^PBW0*bJQ7@VcwLmK0TlrU( zNYX~l;ux#1XVK=oa`}Wx(sP5%17&84@kOV3@Pt8#2KWM#5-_G7Msj7+*apu07L>(z z_E#Hk9nrd5nYz_?bWsC4pqmPbKPDeF|{d$zQ?nNH+p(lYNb&EoYR(|Ik1sR$SGVE zr3pQ3zhN6APxLx`;PS0-Y=#ZPQQ`WzfM|A?tm+bOgCV64(kH2)4igeoYKur?3s4IK zH{{{+ig2%t&HOfn+^GtMj)Hx7uvRhTB&r92tq=A*85$)Oog?G9f$NG@Jy{z@y$;4e zuPO9ig&7$|L|l<^RL7mw>v)6SGN};rDp)=xrqCP&gr`Nf~%W7W-jvkOkxd~uONFkMaj3# zuI7UD)dXZ%ZDM`^!g(k_G4^1RNLPZin!1vv3R?nO3`5=-23`&P zb}pIa@we`yXTRxB=KU~1&kV0(WJ83y>VKsK3NRA zCD^P7@#?YO@cgm}&rO-+pPPRd`)i91Z{}bF-}>sj@bPUzM+7hPcN@#mPq2G443AYS zeidxsMG$h4Wu?37H?)OWc7G;Z1;d*x++h&X+rc+ut4^N+Hdml|lb~zwQKYOr_fs>l z|Io9h=Vlro?%bPiM&RTqB|VydLG>D&{0>?8_Xdzj(%(+bjokkW4EAs&UM$8T_n9s@H&A=go@;-K5CX|V2)byh-v zjnd^tntnex+@-_Ffn9_FWS<=v&d`$i$Wg@jI7V3|NJBZhUnV&?m{HAOW+{ZNuQW%1 zy>ug+f2AxN`tBO*Yhi(= zHMT1En?q|(DoaBP$5#8I3?gT>B4G3>)PzJa(14{$7S^Vzla`DTIuw#Q^h2I_*HNsY zE}y0Uir>EP#p6P{J_b--+$!Lc`0sVR9F+u1e?*BtB>Vq>k^dXP*0e+sMaARYwcRy# zk_KTj>O4p0dx4rIBcT`!ZD>LvP%xE#5kD5qL=`q8iNPnVE;G$+R4-0hEPM&Mm0$6Z zQ_4*$3pvbJK4%N7KqV|e%tOd^6of6|(t?twMw?M57U(m79M5b$%4+3wcFL&Q$BP2u zn+MXv*7rpRs`=VYul5p1oNvP-*Vx3AhFIGlmsOzUVr*4=dkj3@0LKA#Qco z^iIl9W%tM(OL6pjO>fZjGA%;(i@hriw8l4}gzZgKa5u<8y2TQPv;T!sW`CkmHJ63g`CioptWBR`?V+6m0 zC`FzHL89WKFE}v=LF~y{1&(~M-Mennf4`0i{$PWx`H6|+(xO7xyqKO@+Pe83LfnyrYp5@->zI27APFO2c|+;gjcMzibGT4 z3Ul%TbPrRO!?B-kvC0BatwS?9kHJJNNlSln=B=-zhofIDvlcr~ zR8-IU5lTH{ziBm8nH02>w>{;DYPqUrHYG_%-)kJ?q@wTCp=)l*^>{C z7gs#73}g(3v7!Wj_Q(Xhxozi&K7yWX=Qz}8mqE7mD=k~W+E2hdbek6@9tcb!Ze|a0 zxs_n5Jnmq1fpwvMMEdyE)&4J+KmSJ_I{ zi8?-(DjCi;k`pVhJFPID4BoXcpD;}Qutv-E=`CU?y(zPpijM27eD-@u;y$U9F2tb~ zM`N9fG~`%I=r1~^ANmNhXW=HZK7=j5CCqM}(H72B56dP0(r3&um`_eahG}P=fHr)z zd^jRV+*v=h<*_aBl^bN=zral_>OfwH0Dr$0W=<;Sr_RK4$0cLfy=BrR?HseP7F@2w zJY`=lKPKiA5<4GH-gI1u6OzmiGULvqoc5PI5b3g(GK0T=#h;qJicg|nDxgCwYnzif{cH=5o@rpM= z3_2a1Da@Rz@iBMNM-2}#KfpGg*8H}kd?dbHq&gYj(Ciyi(h|J>+ifS7t!_ji3`qoqB(SXgcOHiZ*pR46*S_2Zi}lU7 zPOiuaJ?7_gl500QCEI7e{oV9oziA&GDQo=`42TCB=#&981_Wqy8peMxebLypIIhg5 zjT9QC@ryDkb@vQL&T3&3!0VAxw)DO1cyjl(DJ{w%mWj3ti-3yV8BR+j@o{3nghtX8 zVEQlvQaUb=0%=W*!w{#J;o_evEg()A3W^XJfCdF3*2I&i-=->e5?wsC3t7?r}A=Q0| z@#ouP6?Ddh$07L6ILb?LjIjNkB5spypmG~GvY!z0o*2|o7s|FLmJPR&kC%~g^kOf6 zZAcU$N)iwA`k3%#+vVIBoct&1n_q%j%pa$RUkj&CB7*I7E*5fa(OT39CQQ7JFf>z5Na;NvDe{&kjS+s?SY+@C`0&X$1+WTmTPdp-gxIZ+DRX|)V_bq$gc z=$#Jw;*(pnOya%>3!V^>Hxcu+o=Y4JWlv57a77+`SbCGBj!{?oj^Y zb%~vqM)kP$33@zv;V7%&y5w8P>qPe{+s9jbwDOoDVlaYay%;E)p-^6ExEGD%h3QAn zWV_=eHVco%U8K#hY22Kx>8eMtX>WydxttU7PrbS`CxXu~1k;WHw6@RSZR();p>XL~BeSV4Rf*S>kv7EL%sy9w@OH*c3kdAXbY!}c_*2z9mkFA*Z zPJG#tP7`4AW+ENaDAZ^4GI&TG;2FXTs2+HJL!=$JmTK36)zEIHY^Psd4E@%Crc$>d zZE-$}^?3qQ9y5*{PBpZXTF zB6eJ#@%5V#ld|7$&I~W&LQ!VOuIy{}Z^B#kWkB^Qh7b*LDoQ&)Im}`BvN7O?fi>KHB>og1m!xD>T-t+vMRdy(FZ> zHmQ%=j_Tpi3O8iy9uqEXLsUyLXLWTx9WRGNFZIa7mUh~utSkGwF($9#kbv?T&#Aig zKKh83!U`GJ)`j5SgV^K3)L;QsdhBxj?L%eqdID5NrCN2t|L zCN6;%$ePv_)cTY<+vH`OGfKMU<^WI2dl(zY5Q#}`(B%EH%hKlrvsxb#en>bU+{iGB zm^4bWQmDOUMTblo4nJ^9F;gMjIp7?jj#qQn(kc@r4S8-Pk!wvh!jdsgVtHYofi{WVJJTr5>`%Rz7T3VP?8M_^5jJT=%1>_sh9MV+iff`A#dWHnE<3 zC(b>+Y`Bd4mK6!V`T4zpwmd;jA_YA#G6ijyuYA0Wa!Qff_I~m~0@Cm1_P%HisWwMd zU*adPF6}IU-hSLHd!oo}(?9Ym2*^tWvtx$uUIMA`^za1N>Gq^q&M?w(9e9G4JSE5&l)b6A~e%8HOgUV5Ob^2LqEp7_~URiztr~h)y~D@~Swm!Yj>ZBE~nb|Kaqlx8hK?aN^uEfd9wH z_~y?#_9%5J`t0ej_EXkNvaOvBkbBJS>8*TPUwl5XyLX69jJ>VsYcF=(y7WWF3HwE| zyvs-B`Xcg&Z>^<@m#f2>eni!ZA3Ad9(4&5lN-@@S(UN*TbaNYxD=Vw+y8sZJ$eaX( zcHzFo7^-9v?fJdKs3#M+U!S^^fLk%dv*W-wdZe=B)PAScOwS6@WF`5whjm&eYi}hr zcUv6kkwMHFzt1Ji;}mla-eMF%rqTB&0KL0V0S zouws$W7kFGO~dhxco$^U(&OU}ZK3g`RfXs1q{5FAkp!0wLfRIEEx#9P!<{`i3=9d9oBG5_oLh_ip%R~b)+l2ou)aakYdb{B`HsiB-^ zyjQI_eNdr7ta}03iVkgFTd`|&TL|U&r^dUl7@rC?gcrd&p!d^1htY0_T$jlJQ%!u8%lb`To(w*a6vAw8HjJm9; zeFl2xut*u~OEde0n?$%N{Ce>FF8@84Bh25QjY4LYKSpJmAJMfyx+1rh((F9v zc}u!6oQ=EXt%cP*gTe-6g;sn?lVnIR?vhnKtWVAnP`h!+M3ZA4i}MRhzEG)_1_uWv(OnaAe zsXE3*D(Pw%KB~+&gCBL;$ZHx<>FK)X->-?3NBP8evzf6H>M@)t$F@~|Zx`n^pi<^9 zk1W#TN=GC}6|}%}UZt^}o|4v0Chw}kc z547z9xdHXa|L%(|o9b}gV@FxrZYz?UCJ!GscG@G~Kz7%-Y8QDyw)AgYvE)>pop#Hs z6mnFV=%$`Ao*afwVbyFaCMybn1gC+XTmhorqe}!4p|hY_MCy2DwXQZEhy`JQ{VvsU z3gpw<5hP(>yVqAz+i?2>q~Fazq46smiJ}q_lAf%xuLwbUXGg5;?cmq#j*Hnl7JD>) zNk^P{|Jl-%0@yN%In)TJzGKpZ{At3s;Y?>ae7#++2&o=mNRq+06KI${WY25+Dnr@%r9 zxq~=AK#VNEIm8nST`t5lD>Dq%C?5P1v7{vB|GOSm;p`3k{J-#u`jZtcpQyD-q&&5njn0J*oZ)!~aId zZ=VwMAfie7skS8uc4vXs?bdoAZq1Z39x`7^hJ)KhaV5!OrXX!aKT0j19!-~BTCR>; zs%C4aMuqcbT{DuhpU_xNArD1@1ZS3|Zikk2l);#aKfu>85AYIcXVF&pd*Qy4KeqS1>Rb#$atx+4_ z21UX;QVHF191h3=p?a6i$g}o|)?I^#$INyYW&0d)7Q;&CvA3s+H8kp09Tx||xOvOD z^MUtj<*4R^jN-5G+7kh&jS_&T$!?)n*$$!kV&#D#3RL zI}``Dsvl_8;o~F`Z0OC~aDrItz9TQ5^!QoB_mx{)06dY#$Ydely`9RfO~TYHXG0gJ zt2^>XXu9s6TP26=>{iBbp$Bq=wjb!8z8eaCx4soL%Ph~ER@3ed$&9X&mbuhCVjPP z4odN)30|?SuIeXXsct0oGmNKl;TYor|6i{FFqd}ZN&o`>$%OvDAmD%I!B$GTe?$P@ zmwa-!Id>c8GXwVtWW#WTFRIjWG$T&&C6#*Z6{gH-j4q#y?d( zVt5kR)`;>$v{%xCqXtDtP$*ADR0k=-ju&@Ur`1>b2c0IrEwo+OU0!({aduxhcikA=Lo49FM7>VPg|K^k@lq*{4Ga6 zzoWGAQLNRnaRL|PUU~87H=1MEPLxz=>!uJA{$N0iepx8X*G=-7`-jQL?DD zxeSE6!Z1M0yDSUGqcp`qjfpI(@lY!9hIO@hOo?Q1BQmSjpus*RcQqQ{f0@gIo?*Z@ zde1`)U>`nj_Q-*mDQ$*8&#Gf_Fd2-2ML6{zyPo9d+?REl+-lna$=QC*n&^RotgV%M zO$o9EP6kfp%Jyxcm=uEua={dZFt4M}@byRk^Y2ncZEK^wtKHe6c|HmJ$vVE-X~^1^ z%{LQ}Qa2Ko0B%oDwW|+IZLgM4+u!efVCUPVP)0%@OXN&%KYAyJ29AhXJePy=JJmx0;F1$*Yqi`=ePF+jOdjG+mX+QjTB4ap z;cb;CQK6Zi5;jmQ3iFDaMz~c_g52|}1>?AUUZ;$-7g`U_s{(&~DD8UvENN$c$RJ}a z@+ob8Nm>3~`O0fHrIz}@a469CTgo^KrU1P)e+!?mDx=)LHV5^v@GD-#N?}$G>UnbC z#(BrF#Ljvl;*eJvpW{#ShGvKjErOE4X%$b4pLB|B}~96(_;JhF(C~?;-~Y}JImopc`P2H zshE(bZU#j=Zh*VV$8Y={=6dUvO7CJSEn7t8KN>v{wS$g&Zc{ zHamzpILE4RlANHNQ9X|BQE#itO{wpQe|Pn;VlRapOIc*7M+0goVt&07r!}Mh9EOQ1 zuea=*)?6PsVwbG6-N)MBDH#&Jg^tWD7rw=sjM2&;k>(9N-&z4hxwyKLiXqLWjSv{D3oyJ}l@~ z{j%xs@Xk;a{Y~D~<@C~TDs!(+&Ku540{4uO##&+D;-M0FVRnso{n25w z(@a(RT|GuxD;(ey45pt`l&w3?gw1*Gr07yOD;;`*@2(Zc0cx5xs=1|i51hlEgNS5x zuU)){PfwGvMb8O7o;63Tj-De=mzC07mD5~!?t9WHZM<&ml6EcE_4@bB4Xf3Sh%Z>It8u)gJ90zZiB( z7IV30R4?ekF*u^1PBzT4pekwHo?-~S5+WrD$f`5LDV@Pl?irbsw@%a15Djc~7byJR z2ToAdFcL86LVRk;^B#yFUUCfz#qMqgk)wzp4*$hMY1Z>wDN#ybITGye3fituZ|t5a zgkRe_8J+*O6bR`*qM8l375>;Q{>n!%v;Ir0SPBQw2fp^z6J}{cJJ(<(Y88ZdAYorG z-lxIsqW3$<43%yV?@pLM4H=Eqi>A~ef4FMHpgrN(ZZJ5m`g0D*a9_Q(tNP zDE&(v4IKQkWr@Y*On`fQ+!!ICSOtyD>ES;kvrLe8`LJ;~V2I$?fO3$kJ9=WwI5~y( zQ6oeVErkYA?VSXfMMQ|;U{#?wpku=s1AzJ92p=@9eL2=aShbc!Z`DPOQ_17g6S-&_D1zM?CTI zWAWFK8Z7Z@z#+Y+6Kb%An1h#7zAHZg2ZFs-Lqupzt0RkaV;DHzHu?I%h9YHkho~1r z%ANx2VZAsu$ff9yJVwLAEemyJl5ENkmHB>TDx>Ep?QbPryLu@5{Z0e#Ym^v#S7!Hi z(+AsNRTVGySraWGuAZXx8F;qi#N=dj?Unj4rTx3oE(?1}&nEKn-B65fEGLr2K3^zq z8%?v&ffwkx+3w!RX^WgOP5XV)+w4jzU5PY~=a!^Z@rWbNyM5Za@^M2lQNFg<@)ev( zPnlUS+JbU)Ky+TrcU|lD!}3pr)?d>ISmy4?Y8rTw{!uoKpChi5lh%>77!Vbl*k^up z9KV*lU4uGiwLt{E*eOQ8L1308X#TGI%)qtWMem;rM1416l2QYsB&s!5J_|Mqn#6Q?jKG1a4h>7cs16+O=V zw_P#`Ao+~HK?)K6nsJr(?Oe8S#>xEyFA|NCTH{{0Bl<;t%TtySHo} zqQ9MH?CG0$^spd1(SDhd4KBxFtWH&dhnl0R`l4J~V2_JuU?;?N z`X+LO3#~fjuwdJ4Azz}G&}DJ!O1#1 z4?h{RYE+_47kR$bx`$G{$)-ji%B@y3`$cDXGVSY&Gumk{cG0hyMCGe0=m&CGWX|Tv zrgWC75;-jKK`vz2hu+CC;63ylZ^2V!$G+p*$;o}X$l437Ac_8P=Rz=5sUrbwV5K#R zc?^4RM=!CidDBlPN}($wEfg=)xCsVYtgQ1p|{`l2EgTmT`oEp?CM+xRl*0; z>O{Mi9v7!2gXD+eo1RWPxh#SM|p*p!~sbHtpMTLzQvgyJ@}e^lGW;yahG^GjZHp-I_APX6HBlAl>_EAQ;Po}cK- zpHHU`iBNe7d|x2LMFtlNCt z=bwfo=Et2-uG}is3(3Vmx^$(Ec? z>rLu|O*{?n>#b3N(EMTKJ$j0_P$oYt7H~xfAjB~MjX1$jr5I@I8)MpY@3zVp2EAmAltNs4^V65K5X)j=Gi{S;KQ83d1#lc9nzqyhdV7h|6e{^-2{cvG zQ^~5`I3dTfsH;x)R#HvVtXZc?bx)KuI?jFk1rPgM3#K$yC9f5RZt)a`o33>QnrE_U zGIWu|(_vPXt&&4&&CV4cZy9TbhRpoMrK{Z-6I|UAkJ%aR)$ya!VOq&?%Kg~oVA4Y* zz?6*i5E?KgJ4|V$4?o}fwGnS6`kkDDG5U&;6jXM9#1HOe3HI;?q{!HoyVqpNclF&# zIYk@QEhB)Jl$9LjB!Ljq2H@y`j2y;&mLsMIgg1Ud9CPp%^zPOepGhgB#U!jbgl#n{181?v`@a3I zPyF-b*jX=|^{!#MbC44p@4sLEt;_qX%9qYu012J}9J0Sag#U2Bf1<(v$sxf#{l_8k z4IciVBAdn1)dUR{{^pQKFZ(Zt#OtWMWxYouztghGi?#NC2{Q|Z=#kU+U%0c^3S%Ki zEVEdpGn%B^#z&=fMah%#HO+itSor=Wi%t93`U0!1=D#&PaTSn8#fTn5Fnwe;NL?vt z4f9gm4^n!wTidg!8~@sQ#e5RZRH@Ru z($rnlXumebQdVyJ>KIz)EZl@7Twh2YKYGoCMgsk~21K9FnhGXDXIQbQkLw<=nv{WA zuGg<8IKV&-1iRa4&7#VQkjcDg&5a>igD6|R82KR-7culcUL`VZB4rCbNCC7$112?| zDvRyg@z7LA%Qg!L?kJgn6_@BPJD)@Z)gI`{xz#bv?A-ZnaZQmE%uW?F$*ZDJ0(np@gNcR)Z+nB6lVj(68OjtOs<|p! z`@j~&qIOEGG%W$ep5A;H37VSsS3VJ*O6?C4pApQ)=&z#CzYzd-V}CP?lG4D2`#ztL z>pygOGKn_RiEUuuWXe-R+yMKD}se4N)dK10f0MD7@x=elZXnIjclm(Qb<;)oyl0$;lxl|fnqr7YR zr@*B&X&y4Dw9tKaJfZT5ps8Y?^yqZJt&;%Oca#}g9!=A!FIGxp0q2=)3EfZ_nfLEN z9jb(5GOx*BTJvTTfk-U!{0Dr}U2>@l&{w?^HsS>|$)<)knr8I0x1WHtXnTL*cJ%ce zAa?Z4eS)~v3VdMYjIoPJ(9VIFe6+ATGEHobteF@-qR>9dq;l^V7yCu6+!pC-Yf5NL z&Sj2NOKeQ-Yq995Ei!o%(Zq~?=`@a-K-0fc1QTRR7gmQt?)`}Oi(B! zFhC#E-{B{q^%{s5s+0Uqp1G%zHW9k$I^(9e9ut4cp{;@+mgs=t{PS1cJ1bo{l=}w4 zbf4r;Lda-oo)z&Zo*WELRl?Q5H{1?YMnZuV=qvDThT0!>0$G*w8Al^@scH3Gu6%Xt zrc=;XD}L?@)-C4O8S&gJYC|pOtyCQ@>ef%H-alHqL|Q6#zU5Y`U1tb7(nN%(`)^@$ z?b*4{PG>zhX`!tuwd${5&*H+nj^8|&GbLq>YVdg5-xDE36C%iNRrb8WI?*a^GfpDX zGX5mxBYvZ^cK>nJ+X!xV-HTgM;zBq^igH_Ba?KAtSGT&-m{Z?AM^igz+_Y47CI)rs zLU<{-=s>mSKO?gy~xFGlfB#~wmp(~D~{;nsS zB2{de1-~oag2A%)Xn5L)b(ehmB|-HPBD&=s>#+y4+eFYLd=)@Y-Q7Lf6Xf$(xV&c$ zk8Z5aiRa}0t`89)Z0Q@h3!Y2GO;hD>5V}s5=@-hhv9i}Pd`QRMECf1qvcH@ik22k- z)s}9TpOQwDJA^J~E|1ACc>h&GeuC3E{^L9T!2&>mVHTF|_%3{-8 z8(3rKsMZyI)@f1-x7(-LY_^_8rFFfPx3tAjQ?iAUs^QMxaI*OiPP$XE{F+jUAz8Ko z?TOgj$E1J7G;D<5I~JU8GWz8Ljst;16vY9ohgj`c-n!~~Tu|$DmI~$|g*lBF#mqZ&dcWL`+nv0t?Q7 zQRE_jNFGF%Fb~g!-U^PTu_j3e3{n0o%r4>5%xvl0WN-?X=VG-o%UH*nqe6N5{J0O5 z7Vi+4vJG^J;lk8aI?I_D|U+7Fvb472=)%ycYvfb(KimG1J^&!^NOE`PQ9-$*p?Mi zxX(oEa2T7Z%szj9k>yKg$G>A_pSp_7=SH@lMs5E**;rI~pmU7zQoe96Go|`!M!Hm} za?m;0(Y~rFQ!ni}40)@YhDeh7mW|u1NrGX1G#?|h!H4b?l~xwHi^xet)y|DCjhj-t zVAx78a|cI3w`Vdw{cQN+Gv&u>G8F=dL!^p=DKi!3Yk^}F$wsYpBzh+6D6Cd~=AijXp*E+x(u+F&u4o%-1Lc_!M>Os!=9H4iu z5n_RT<#=s38VqSl-hmxFJdkk$#i?1wIh?4^#G3erR$iNgG|6o7(z5F?dQ6XO$#nSY zJm?|nb&z<2EaqxgRU^__dPrMPA9k86;NI@-9?mp_U$vZLGJ7y}Jx~i}Qn5#2>$Qan z<2iPGIi-|#H>J(>=kSUT8;%Prxl;MT3(k#B<$!4piH_NVR2cut-t24jr&hkPYAF5` zN|7ep*H_$mMJhIJsJ9k0cQ4U2f;Md$F1MD4x)kx7phpY>6}b`#)&jZ9mCy?0rtCHb zS0$Q!a8Sj9t?uZgXo$sJix>N}sesUVmId#%ZBJ3bl2s12?Jp6n27!mCgVFU0rMBv~n2Jck)+me^=LsRz^7dQ!D+=Tt2ii zUHaxjE5iU<2`^9T=6aCzhgOdKp_LK6oUp~{7-Vne|XCO%~kXNkvqQb zjJx`8uKGBa`5(h&cXm}loU5&?&1kL6aqAeH%);-m3H^MM?q`7djIu5buI75m!yjby zERg}FX6rR#_9|e**#&bfyxQW)t)4<_EKHx`7m7z%LlGU#$A8*C#)nhui<1O~K?1p) zPVMK_1e-iI7M438(QX<15O=)+`>ni|Ke`EYVw)$_d;QCH3rvDMn z*X5(9UI@ zbHQ3{86u?Wd;=qFt<{>yoQkdr;}8(x17T7{L%@)DfRZi$j2oPmG-r0M_tn-BUbo-X z@8`k=*_=-TY(N4qjy;e-8bSCNmCq}gtXH*jjhBhw$s0Dcs&$9(>!x0*v+fDkWiGa& zos(T94NYaw_j8~0Szn7~)NbOf(i)Q+<)h@onE|njhZSIoL1IJ*GkRM(#$%7)`WtM; zfwO^jY3JIU#(K?p20T;10>*w9WZIwIEmm~8P8z-%%E^*ZEj0}62A4O@xT@x@XC3&k zSQ4*Iz>l=H07N4-Q&svC-AI`1pKmo;}$z zy_q}hl+MTN8QV%NL=vTxJ37`ti5+RXVR8d2a}ZjN`sG>|Gnk4u2;32n=9aYdC(hRo z4T^#2D(Fka(h3r~OZs_8&Tj{l&8F!1Q7a6X&zykUGSbiO979ucDIq-7#xjRddb_fW zF%bCt9p{B)2!+M%)99w{89LQ^2qk(V=Bdks*D8O)MD*`AN_y|l#z~`ItH!oAG3I6o z6XDr1>J2{GT&1E&HPzq`Z@f5C7MmCsS}kJO81q{ZmO*SQ*a+mzIg+EYZ9^zmE8p(e zEpiI*e$94*#2=NegBdXjqW%u&KtyX)0I`D)M#7wCEqbfi&ykpy`tDn3Tlr4U@0BHd zOX>1OELQk9Py*0T`ULWGME*cIJkIkh%iv{z(~oy_LyFt1AjX)-nR*)MmPy(6+{SMc z*Uz{LEEBY%TkspBh%}SEkNbCjaA>jgOi4Gc z(==OSahv@ogAyb-D{hc?X!F^vS!e16b-%gpKleR(66ASvo;l&= zKxXz{3d1`hIa$z!#2A1?zsY=i%DRUkpo1*ZKaiSs6j7q!CD%Bw!k2+9_)2bfBU6m6 zG&faIw-dTQWriiUS1=j{zI;oM@D;-rM-_`sio08#hnCcQtjb#{!JA3hUv1TacAmk? zN#1Ld6Zz01$C=Jd?BKrRKE$Jx+|Px&q?(3orXQzo*hNGDo>QiV?w6uoVUCe@9vqCT z9KY@d&DREB+D`eJfJ2!VD6vUvfL@H4=b=A-?Yn7~n0~@DuV`oyC3$Z}cA2;%z<-Vh zod_M!CSM?mX-n*TuCnGxIqCwLLL|HDFuRbJjI~!RR)ILg8r@gG+NfUX&E|4nS=?s+ z)r1g_HI<);V3Uge?RP_D*K?OMzC)Lqb|>jw#S6L7_Ln++G|IbjXRkdy)Bv`MTD59x zvufq)STEa)GLXEn^3bu&kZBR;5G^ySTpm4Jf8p>VVuhEx1HAB zd!Gwi>Rev=%QhPz>c3iRmLse7>3>-3|4=Lc7kizgZ8NWiF)Uw2UO8DS%`MUU*-cvk zKX5+<4Iq|ImaP&YA+=#CyfhaIi>g%8b93t?`wMVz+H9T`@T&O5CIl+77RFkG&ovQ+ zW#y$tFyKPxL`fAafbfYxSrbG9E`*{M&C%6W)|J2Co72=!M{lHN4y1rMa3G^3FfE`S zuiru6#-?>GU-^i2t@(@MM=HUUTUFmBO9YxNHcKFzMV3=o(?KR02ce%b^HVzIF|NT_;;j=Eza4%ri-Jn-Sjvv8R4uc-Cp~Qh+ zk5m>E;EU}uoCra{_&B}5b~g+dLB2E}->OLWm&}~4>&LAX$15^)8R@HW+s{>?Jy;)D zlavH%%f%N#cqmHuQ7`TlfkjQhJIgf}`=n!cK-4Ika0^t|scC0^hunYwfoD@G*xpRC z+Gh0e{S@uuIszxdAw72R#`sYL9vBS{?)qA>XW}XO9f@|W$z1L#T~ogjtbgU2b;=V% z_t8S#-Q^Jix%Fm>%a%41>!Nm|y~2MeJ##ghneNQAf{^T@4)3bQjKhp>DvP1IU90K6 zeZUZKKi6x;aV@`6J>sh|>6E91hnKn?IYLavF>{zD$63tlR%f=`V7)7GL;R4c8@}vTl6-y*p7#8b4>VkI7eygnujfs=_fT)=ImPsO(syR z`u1-wRP%3IlYk|IJPNefO3^1OLD90q={h4`fpX9d;y*U7>>sBL4Z>Sdo2No)ZgH28 zi(S!uc#V3^vj=OB z<>^a|6NLWkf`V;vrw&4E7G)0X7*GGkrpz;lwp= zlAZU#rTiz1UdBS2J#zDy!i>Uv+KR_${h9detd>jDekk!yt$YdARAgp#3D&U7gJmjj zK|kIw^mNfeT1^CVRe6}#sc18^)pSB2o+*M}aRHClfKd?Rk*Fs5JEAXoZtb_oTZN$yIIHyk0hpD50kkvjC<(>|H8jk_dUW)S6oQ=+;;J9t1oL_>_= zx3KOL>2AeG`yBoTK~Xjg7ih9)0fCxF=nwMPt8s zbd=mN0-v}Uo}`+0-ZjG8LIhk)u9e%q9r^MjL%=2L=;qI0H?7jXkOFZr7=xN6o$9jP zN2yG!mjU3uf_?hUe*cq&R7ujdsgp$2!{%QSOuHt)pMQpx_jl2eQ!X}=ucB=%Ep!}v zFOL+_$I+^*OpTxY#bj3k`yPGNW~>9AzeBeD(_#J>qy0amIQ|Sa|K9+=(bdqQraw{~ z&8oe z$wk%Ssl+OKUc#ev6+&Ie{Eemb1`N3q{9taO(Z@?vyCF zlGz(ra6hIazV}?%S$UWpgIpqyzvMX7c}E?-1I~{R%;j&aEC0i5|834sRt8%f1@Aqk zH}f83NVCuDr;$=Ck`jz0Hbvf=o`i&mR>^??R$&$5fx_oej6nZ6F*dihV#h_ef#b~GB6uI^&5at%oo9(xJt}@wg&4znR z)Bv!{EfY`!G8q8`kV-y!=tSxT^cb>LdF%aG8X+7NODm0oqAvuCr0zPiTtq7MU82Id z6!w=k$8@P2&JWoHiv6BgKLU%547eC=GwBH=9Rk4xg1Xi)6xJwB(_!}ZmG2gcf)xN; z2eA;zWr53Vcx zW#19|mS?qwk1|a1^WO6KB1kXSW2v7W33F8<5mpz@VI#8>MLB`ZSJ;Cb*uGYarcpRZ{ucLjxU=lsfC3J zNuQk=QU-VhD>{Pu1MNimGVsU&l#8qv9O*R((HbYzyjyMIAzcwWNZxQLnB(%==>4cv zm{7Qv9fwqrj3UIe&L@<*!005X<)~<6R#aZ4iu2^XTd6m%B2l>CrI+&-QRe${PY`mu zKP;b*GJqosBy-b$&9qpUt0zo2`MqalcSbV|(5$RN)44?(A0|$ayLc-3->ffq=ZgpG zLF2q1|Q+g-aYPvCfbcl+MzXgCSEoN zHc^~F$tg*D`4CkFfOUz%Yw*2JIZ3~DqRmkC*) zMPW`Cj(2!TO&3<|GL5i*Ro`;dpXE#b=F!~+nAE<7CHi!T@kzw9Q{L2OcC?BeI`0Qz z62iSUlqxmJnXWlwo?5s02pC_u=&92-5eQPwyU}kj^*7U*QoO{5<``19rYm1bz@`?? zjBX%}h%bfLx1LqhAPYGtm)wLth;uqg6G4O39g{TMaP>;rJ44uw9B%}Z?$!)!d}nfFw9SIYR1ZFS`C(K|sXQx7ycUd#UZ1rU2I=f(hUu#8 zMcDnW(bdLpg0X)$EEHkk!fS_!dr{zcd=~20yxRemKNt0s$F8?(+tnt0o$LUv zs(j}jsn`6=>Ucy4=$U3ly5G^A0|A|v%wqwBUkb2N3&+2sZa7PKee&pAq%I62^$4=j z)nPO>j@#5x^rK_w1ktb!iKa<)yWARIrmx|b39Gr5AaBg(A9oZ(K73D~@I_-tW z8b7#=zQPqU2GSAz*2a*L7vry*M6;$>{i2)viKJ3pqvZel5WtZQ|SJE;E)^a;jwc5wr{5yVveGE9IbuA@3`v!AK*X%SS2 zv0L32zjZ8Gaa%G0fxB2L1p5&&k(eyW%r*u6rMn4twaFqsg0?`7qo>=yB%WP_h3G!I zoj(fi|6@)3_pTa%|H)_rwhq4TCf#2?ptW5RHM@7ZFtb|L^(hDtJbuUu=Caim%c+;2bU|ekDW|`y4s3!!$D^8J-P*y?rwC(@qs5aP7Xrr> zG!uarqDg7d^>I9Z(iK;VF+jvd!a@{x1)@N#t`gI$I>U}vTLMJfej`ajoqnydkU@-a zQ6%H7`BJknrz=LSxV900H9_0?=nwKDM>(hWcB}Z035ZtjixRdNmc7QO~$G1o7iVJ+* zb^f+aeJky-4`qCDZk}uj*xY!R_)JQPduTut(GIHN2?2pKCJ1cZ)(&WOww!}54d4y8 zK&OydA56&juChfCV8@I$P*oOPA1USCj|eNPDUB%#ae#=~B_{Hpg@!i_F$ckyiYhUkeCLOTvaeOrPUCWkcV zrsVAtjP;U-$XbrNuWR=U?H$?yc%V3M-UFo9!jP7JGd(Z6zh4x$=)?NmZe^N0hn7SZ z^tjDu?~1yK)m_IX?VJiqDUOr6(NMJm>sDl`B$`u)X&HLZPxOr6LVu?G@@K7Z7Eei> zFpcr;VT6{8r!;?8S|T2~?B+qU6I7Nlj}`Bu)i;e5w~cPLm3+(b(#jIeFP zv&*e#*qKuv!DmzfBeyc@HxaWcBnW9c&kORgh@P{rO>?*@L0+y22+rR)npcDoh>?E*sYBnd5#m&kW?4oCkR8Vt01SE?n3i z;;xkh9TuVSumjy|7ZvyUr*2?#@O)`zM|IF+%P;i6drba2th}(${;C@Osdm?zULbzC zA4w%R`W^Ywx!PNmM_&>rA<{)rKG!`$t%<@xm_x6j>JTO#rQMT6p0gf(Ka@9r@FA#A zTA*{*x+A1M38LtlvP_-R5^?_F40WZ9>XjP@k*4$IL_JbVF^qUMjTOjOj{^mtWGUbV z{_6%*962O)rlj>1NxENRg$T6zc1pw4s+MtrS|MZj6w_~g3zyh1I@P15@@kbp?Oeoy z1M}RhSL(allcwik!%UfIanb%VuSOV1EU3f%pl#?5xW|1?VR}NYe0SdorSXUQ1o>8_`C2 zWAm|=g+~!@pfjHKH?V&l%~qjS+U5b2aU1ab-EqTzX9E9+#<_oQoi8;1Pd7%URkPi& zH~u48bn<~P5%0jLTkJ2NuZeqfvT@esmnnbj9BfHRH$y~FwXt40j-vX};+mA%W_(u4 zATK|{g*SyDQpA?N@CzcXi7hvJzOP%5B(ND0sNr-FFrgM4wW}%o>VQ}2pLc}rdjIOd z6`XrKzU3!!{nyvr`e7M_bpwS!?}kHQney~ z3LSri3|7q4LaUIG-3@$K>N}-|5dq0Ld`8SfY5L6~jFrjz*f&zzuPB&vl{V1*hI1|n zuA*(9iHs%M=ImnR>b1t-6xtrAR;%oW+oyfEAAP%WAAPT0EqH<68ze}9Ak#Vdd?W>Y0VJHuvEtr_6#^Nt!T;wTJ-%|!iww)O5h{9@U_E?GhGj4Re*D{1UJ1_n9<7g0jl*g-92Q(qV{&^ZQA_HTY z9%6a@P)kvt7%&UCECGH=KiuLKrr7pdIhqonXbxisupPk3_8u4O-T<;JGS_R-$t+!& zJQOI1#*tq+^vn#Klv>u0RJZHunzr-mEZbEJLAbFyX2_>PZsq}U|C_<0lPNp9?(`wV z_V@Jr6+b-lE7}gOi`q@GGy`b7^{2ebV*~r>dVH|`(~t`FIE#!t@CXT?!wFD746NPR1g%w2Pmfn z$UWdP7%qDN5~F(-t`d?T8n}cviT;l7n)of3VPTA<#?3itz_;X8evKK<%`=NPx2Dp{ zroLAt=5e|KIraI>fQCf;Q|maSF|Cuj1YC9sG44jzzSL1;(7DabgZ2ytnPKNvTW0%r z-ViWoXx47;74N-sCx&Fy@b8mq91dD*Nmgn_8S92gi3Mu(>a4DLc65r)+r30(IwS9@ zjAZb^`+SNqF{AMaQJ|C);}-KcYlEO=c;b`tSlCF@P$@5g2URu1)R$Jy8XXjB3o^Jr z*v$DCZXjo*MXea6v$K6_X>ojYs2eJkE#&c>7NlkaAfer?NCmP{smP=U4wMF6bADx& zwM-xni_T{+RZORkHp@sYI&&?fjwVaCh?6X5UEO0VeeeEVelkqk2a9_3loir(21RA+ zCsGRKSKu5iQE91bJ+zl|%ZXa%CGt4L1LryA_%u!~vsqN>ljCrQB%dvcm*c09kH@sq zs*$he7`lKYTnT1j!hiT6hjY521;{~Xlt=+`&{nenzpbI}OT#TO^K$f&xw@mp;$r8(o@X9a z7yIqG;sf(39?-vGxa9q?rw_kf?b`^nfR#XaYj}xN-CQWkWpCyYdoN3uEdA3>Am1AC z7@<0hJW-b1=^?1Jy3GI5d-(^2k0hST)d~9a_P-tvf|fITT>xFg066FWR2TofakfqR zh(_ZK=e~U@aX8vsbgLMdZOntFXW^_Nbg@mfj(kU2DZd2cLarA1tetNO-PANbkxbo= zlzD#WA?RcHl}i}Scx9rg%b`}oj7uD5Vld5=(ex7=dT}<n=xtH%eB|oFDul}qZ7SF>Xz_UAtS+!A2r;fy7j~)YQ{kVfIA~#X1p@3^yfl6;(C^gdCj-Ns(Q-PRYf@}gA{c&)o zlQEAE{xF@r)+0e2hqc1X+WUpVD2;ANv{nC0RmB1qxUnvSo6Z{nN%whmdqXA{$Z;^x zOFhGw@VSioma&1*z$0P^S5C+;wV+uV7-)tsI1Bp*B+xH5AK!GOH8j@SYnt3WX{}a6 zz10WCt({Xnb$YBWyA{5EtuuseqT(Sky7|gWG-C+HObkpjr1pBusL~^iHX6gI(PX8n zB|%FMV-P$nu(7|E+0JtMhA?MN|Gc0&$sF_ozUYd~&YTBQo$DH0!RkhlUcT(Ev;0zB zX+Iapu?Cu|kej=B4|jKG*3|9p^{r|Bn{6#B_*QlIPU9QX*jBplea5mE@+yh;otFHk zN>Xlb-=x=(I=i8bCsDs{97ThQ&tmU*FqBUCb!eO$B*WtSL6)3`0f1+LQ=Q>{sn{4W(nJ0HP5-!5B;fA_7%`Bh+s4N@rMUY=tHBURd6Y z>Nox~Dq()J(m_Xq6Sodh&aUORl5UVlueU(1G-s_+O)2XGcJgzRk2OAvj z^eSh%WWI5>PAf(hNs**ADnL+q5Q^PB~cYq4n2gg4yLZ+J$yxjwsAD8gcceC+iUN7X*ilZ+v=n@owQvh z;o9HEUg9|B9Nk`EHL;?rS9!!JK7G5Oh_Z9yZF~+_VP0AU6#ZL#qqz10 zLJeX>5x%&rE)e3TMkQib8tOhT*pxHxQlEIOTN{>$n{)gjjWwsCn^tw?mk0(w+>2P> zK1klXh)w*O)N{o$*{OX@9j{IZRlo2f%4<&4R1k)ti`eY3uCe#pqv7Vh(xxQxuN`A2 ziFx}vcRgB8JwP0h8jQ?G-fS(`=aKqX!)Z@FXe_v0=lrDy)f07iw_BQ95P{JGL8#=_ zX4E^c&r~rMutkMThzxfNbH`Q|CD?7JHi7^U(lVp^P zvTLIX%g34&t>TOjah2Li%>rhsu)QTkv(uQ$f{hJtp(RGtHHo93(giZW#b|U*Fze|;4p@~-mv zfCJ;Bk@WArivI_cP<*fsR~Oobu$Tlw8*)Xhns4JaCs@LeQi5|_MV?!?lyoI88x zlvLI=R&@$jsLk{eqlz9BNGC95aQ7k{-^}nN1JR&?!0$-+0B8J_r z%xEI~tbhf=`e`)|8`6Yq9=>~1OA+`oTWGYki4~bRYeC(w8h|IXZv;aa5H5Iqk{+9T zi)5b;ry`i;{?kJv!5g*J4(HDr(#;+?@8w1HGCBcxM~0*TUbgUP&R0-yILTipN~OJ@ z24YXo<$LlV!vM|x@*&|h?7%Oc9KlhXuVYiQ$=L;&+(m4*9xjm`t;}wT!=G)2`ACaO zmDnbFOTUJZRCI*s65*=Un2m&uVk}C&C;<93M9z#EY_U}v12XgwdJtm498;|;ESF2s zg`=W^B_Xe_s^$V2xL)LE(|S(V#O0cX zGh=jh=q?;QIElD#Za1l3-pfJnh!=O$-l5nh!%!sQz)VTY$ zZnXU$uw}$#VGSwWH)eAN0$Ypf^m)#O5_EqKD-n4XO@X|~i#8RWs+6^varBIWqE+u* znlzgFwZWXoe2UT2h8ceaZdFf!KyrelMHUI{h-w=5+Z#UBDCs<}8v2^Vod1+#(M5bY zCP5nQR*ya?HJ`W$xFZWYTL$jzkl377*eoOW?whsMs&z~h!mb-q{2u8gqEV;#ov&P* zM(SX6{3-uC59cU~?%^og=v_85F-u|nec8yCX0|oWt`vN`IB}Kc&Qn=AIf)VGqi=7N%!g$U)l_7h@F~8mTVmZ9h zOWNYYO7Qo~Si!lkj>^I~gssxQvH7sn`R_f%;`=#!f5Bvrzbo31t8+X8B zI4Uj>>XF+=;c>CqS_}EgP8x4xdwE|<8z*WNRO{x7y! z<-ZYyR?t?z@`0Ht}cd;3q@{7 z-3++*=Wot3#;3;>OG_Z(901o8q)34>^~4{18jAEUFjtquq%iCsBi7iv&FV2b?=FN<9*gG0 zkp0>6HJSaoqHhSM0uvrkv~gQimv z8hlcB(y=5KKK-Tma!&wri+`Cy_W%;}0H%{^-x}XnI}94x6GJ1Sp_Y(1^<&;%Ruud_O*jLf*$1Jaz+p-t$*u z3ajJIKZ!!I`$WplZ8-1sqJI#DinI(~RQ^GlPW9gn&5A^5TmB1C7}59kK@{4Jz9lVk z=c^XPeS_SV^m%$GZ03BR9IlW7=@K?!`H4O5@04=`Id0q+0=$ge$BO(x6fPj1&b4}_ zg`YZ#@>_;Qn7x{)#OBQIUF=pIN~6;R^~wBKqEK57Kokmn5QV*IH8>wcp%gN__w=7c z;XL9B`KhmuLPb|?ZtnOpLADQzi!78Br+5d# zgREVjQjRO?b*Ix9wOHnGBh}p@KgYf0unc@qH_IH&2}a$->17dq@{x*( zbp*rS$%^1~x+0@G5nVb}oy1c5mapSTt}?DZSCgZ(t3tPhP0mZF*vmev!0+LQnaTRC zMV`V3>Nw7s!P;beaoS(OwmH@Y`ofiPpVm&XXFDvvvtwURkI{xUIS)La^5Wb??LjBY zb8tyzKJlQgl17{e;YIkW7^!id>(DUDJA_Uk4OfI{n!M9prgOL$IR_Hm{=!pcx)#Zq zSda6cG{BoS)am>|{#$l1Ka=RWmcX;cvUkfJW zX4jUC%$p|5FP%hVJ6mY;)4iZ%Ad$EsIGv-B9zLHdhiKO&U3h8RFb)LH;tgx z$o41pK@~pIR$$oKqDCUU5)pEEyy^CJg+rMlyNrWe>D+Czh zRlxIi>V`f>tA7Ct|Lu7Be*gWl}8;TBJx1w^3xHh2in(hA)W!>vrmgnIQQxU{4Ft7Aop ze1LZuJc5A(qByra|YiNcP4FQ?6bYuyKV3sP8Ka17|%UaWLz4F8nehuIg^2 z53zspg{U8VA>}{#LYi=87(%HOHe+R!Zxgl0_#%J}g3cWsFB|{ZAn3jAK0SPNm`w&` z1n|a+5CCud!OgICT+yCBVjrgf8v9!;y_0LVs{E_P3m+|f%_a1+>}p%0mtI+Ev!m%3 zDW*bC)J2s$ndc->q7QRqsQM>WKDZgMp71Rbq~p$pF0G)ScipA7lb>s$*j&^^crJhf z#5z)JhpdLHUy1p+GJS< z6NiWc0cuP)RK!!*-^4VkiNwH3*oLjFXV3BndjPfyCMBZG-xf45o^r?}6BF5ZLE%Uu za!}8nML|RhM>NUXQ6>aoj3dg&VGNAo?4NsHExND&epaN0>+$f})7AH!Dhyd8(pO4K zu?QzEND(zQT;u8U!)FzZ-i&x4GGi5fFA&meevt-bmg35POqq%L0P9RlxIYFdI|xYT zeD`Ifle6~jxk`~_ZO2qP+%LgpTj%Nti`);B$4}MlY?i$Y3zqH>lMp>%##}w_8EY-NTMi4(dt)|89gT^W=pdPt1<20xkq}b#88YYA|mg6 zs7m{O!D@gZ3cUP?J?TCoG2+E;UC0B?wwYBD#pf>CPcPf)r!B;Ipb(C_X z025i4a10mZY1fb>p%?iC?*#kteao_SF0=~h--rR@q%CPdsg^A`fq+G;_yV+QBQL<^ zSwV%zEHpJk@H%B@mWOIvY}obLE=GgT8Bh4E@!{4_f?pVm&5Q1&p`h(=>c$qu zNNJpwvLFyWhnbYT+1%2vDX#l$xv^SIg#Fe}4n44tz(Y9bO~Uz%NGt&5%mn3Vh3-b? zmEDxf`haaoMy_!PHtuRDELU;nqU8e^J?pHDqK!9gcfx!yGr}Lt3=R+9lLxuxX`I@z z&IdD7cP%#>0BH)*fgCU#k}(S9*#!6>h`aNwr=0c)XMHMphnr2IFC{If!w4tmyegrH{>vYX=wU_C;}Uiea=<9_G3ahXdSU&;s7(_jDM)f^u0 z5=p(we@0y2d)O7BMbE}^1JP^c9oO?Z?kNlvif=Dt%gaCuI#8kjZrjnT8v5PsmmjVL zP+l(r{NklC|Lz^yV8yMeJiC^@8S>MoBOo%6*Ltpjvjdr*OP3wS@L1Lv_)l959Fgd< z-V5H(jxT>XJ4C#GtIz(!MgNDI`R{G?e`O8-n`XNG-!=2{Pt7buHF|*fhh}E3(u7ll zBCtwl)>3{|IMe_%SzO_MVbt6D2yR^6zHU5rUbP<`)jP`}0}+4B6FxL^sQ|zl`W#cA zK4JkhQ#m8p()vR)-}AH!-7Q~BB>V&a(9BL&THNUB1%PJuo#mHpVcL>>6?1+xu}a7+ zBap0Fh6+IJ9A(UVoPD-}9ZG!v*2GCYKn)luApR@_1q>9lnlQfOhRGdUH)qKbq{$be zjz0@HMahtWxLAW8&zG!_04~H$_JhEm6JxOh8j1|6prh}I!GNr$VI!Qng**WHeo3Re zL=23iZTNBd^|PsNaBpB%8iZF$q9MeU7PA&v(s0UznJI7sV@yxIdFVgTrn?1Q62ljiJ|(lG(0)ipjto_ zE%Ws1{baXhY5)oQHL-RrJGm6^x+f~Zxw zzI`h8a1_Ri>kktE-CSn3>_y-L&HcuiGy8cBueX7_!Lhb0GuzJWhFILDp6{jF^3cq) zzhT-Bz#39MpAQQ^BqXLwG8d>RPa*x{c`3$G4gW$$^e`P!L-a`4FcwedX(8lCP6>}4 zp+TNH>doYnS>`EpBa1Vp8vqS=YKO2@7H0}^uN|VJRw{*%z*;M4)Faz5gQ<3tlS}f5 zvdxxWP(*iTQA+pA9Dy$RhY*@x@s1LP-eIXfaH9g@6-1d6T0;Ij!!#DZQ;}U^x;E#! z&4$~?=mr(@u)49oas?qJ8{Uegct8;F}) zvo5Sg(x4%_s9;BHYc}Y|Kq)z~$U?uM?3keJE=<|WKXBOcTc5Mf%c#{%d``jcYpc*$ z-f8%ySW((qlTDjq>;DTwWaXkO3{5ZaR@1}f^ru|i0&wL_Eyyg}mg!D*0x;qjoCi5% zEEKCU>Wxg%A&CGjjYOq3m8;YSj*)zsNq%Yi>hVbMiws z9j+<)xcKt%r;SQ^Y(h*mb0Q{7S>QNnRiFtpXF}u2H zh>|Xpeo||(me|1^kAE9EFhelQj>t$0a!OA^+lNcm?TZC~4ex4HsXk!Ck>=QwKVd@@ zFYLM(q)K@4s_xm@XNBGGBQM@oSNz@Y1|==OUxW0XpS`PId+wd2_nNNzyRJrFAtv}~ zl&?9}4R5;w(SqZ|aJ!D~_|V_3u5s75fdqmG5vw-)a}NK|O>;RmEq&9(R+2w-vjL!+ zJ2DYVRawU9f9fXFhit7=WMc0qH7z6^B~!#ZB8jA zd;bs9&F=Y)6G4P^J(Sg}fQsW1C%O1!m8*QhmcRrzku4fVkff2)3D%$J(uVWxl@H62 zRfPa*fEWRY%hlXTK|`qSMN3JQBLdC-$CF}q=x=|v0frr6``j;ob=^8=aBt;+69nf! zxWN2lqvHQs>+ydopXnn!k*~bm%X&q5>m!@`;ZfzN^O-SI2l#2F)3qOa?Lzblla&+_ zEMyaFoxB{;muof$;Qgqiq<;!i+L>x&#E^J80)M`G=59zLCgc$4x8M6OTuWYUj!`wbrCu_V2Y*g%8FvSb0h zlUNgBnpdQd6@1b`AEgXG`sY-i#L+B|m;UfADnz6jFX2=g;TWjGn&{rCjs~6qH^7*H-1Dsr6-lqaU>Ho442?xVx2vH2tp?t<> z{)~0}%~krw{=H*5Pjmmvm~iNoabH;}YKfm|LA3;U3AHzL4^lD;{Tbin0Ly289gC{; zbR*2t)ulCsfi((z>mUdqM1b-08%+@)@oSA(mmZNi!zJ0sjG_=oc$%KfwSOZ>=Ern>4bKkc6oZ?u7 zV;cR-mUp1}J@+1YoX7Yi8q?qm%|i5-=3{Q%5w4Ei*LEJ0ZK8Ac*Pji?nfzjUof@FT zz^o)?<}wU(g*l%~zua1tN^2-&MMT-9wVyS=@34bWYM9rkeuj5FsxfeDypd;bW*I#A z{WD2q%c7yT_jasG#aOWXCk70()yg5_nEmq7e)yOvdx{i<&vv!QLT>;U!S@|WR+Iq6 zyicO2wi&|BY5=xe!l*6efpjJV;Qu2NbQ~3_Bvu>n3(C3U;G!ihm%u+yGT#m zXgxAni;Q&Mr-+w#1GSe-5i4!-$J2;U=<6geGL#v9@Ge5bI17DR7 z>7TzSc|@a_iA6u@2t}`JG!l8UjrQvZw3Jk6=|*$$kIgW#^GiOfMXG9Prc9CaFu`d3 z^g|J_Xq(O_<$3OWGUlzU6RV(-w^P(!r>8D-C4?oou!nKSMwb)L%7gEBZD`%^ zJg6EpUpX9&wZaMhdZ7><>dOUTZ^yw~gUjA_wCm7!{X_wF30l)VZ>2d9g z6;OF}tpK3dT$M#*56#!z=`QYqmoO(Lk|&SgdHWO*@N3%$wq(u+I|JF3-WMMmclD~Y zNod-S^{+j5C9~r0EdWI%_E3L2_4O7aad$8s55mzeuwNQ=t7uD2 zYHC~2k0m;g#M2^*X{Bsa(*bpNNSPOAACZnRmr(Sfnsi&=-a4VrCpe4@=*Ay)cbhtC zYNB=QL%j0Q1nYF}-7mb|M=viMS5MBd)48o@c|aITzyfeT1>k{JBJemgUR&ACZJ29e zCy!hmt>ix|+Og-H#jmP$Uh$kn*26B5^)0C_%_uq7$T+J^cTp=J#5llCARgvKECh3? z3rNhE0hX(Fj*>8VX&RTot;Yir9jwH#Xf?()i$9-D&jkhf`#^h$e1%aJ$MCV)w94s* z<255IUqvvS_KL&9Dy6U*qbJ5^cUZ^S#u?X?ZF=cP@yCk z!f;kl3|WD%JW+%Ytj)+b>)yBP-t0{UY#tl!lv^t~?S#7^O-}D2b6+X&tZQid`kBb= z*N~Br=NOnbA_iB`_`R@DuMAq+Knipr3A- z&aZb215&U?yfqa9m#6u}k~7yEO-`&K4x`@Evm3n-L<6l$r>8NWL%m)SUidrW=&u}4 zv45S<{2as9d$Hf!$Uaav>v+fDlfV zl)VsNDh{<;JWlgs`8EW}F+*BhU)9i^Uf%66>bsmB!JFL^EezOlLrGq#9*aaTmQwJS1&36I>Xt;!R|I!rgLh&9 z7$uR;S+#?X%6A}8=ka8JuU76o9lkh?xDo1THjbGRn|!Ru(xD&*qEf`nY0rHxU0XeM z&*ezP$ljQ%l>Acx1zytc@kv;4eHaQt`CrKMRK2O9DcBeEB9(}mqB~VS99%qnVvdndosI+SG zr9*|Hoh(7W-ZWL@CeEhoVC+}s{A#gek(Z}7wLe6XkK>%I z?L-z21mfT+PVi1yXk5pm`ES}+jU2gDZ%8*gz~lYws?x)BZIc5rc2}J zF3mS%n@4flfQ-(CU?OMR(E-F#N3=Sqg6&rbT8QAt{Mif!Y_B zGoTXMu3o3^3X!!!JLNc;!f;iCN@cyiNu|7 z{Ll4oE#d~a=RcZJU&6X*-P_wioFQ;FQC)U|$RL=&3jjw22pQ{lXM6+V9jPP?WLfQ+ z-DKePblGm>MT zJA+pu_}+l?f}XtO4hWmeIi4R+7%hbbxd#x&fPDpP#;<-wU(XAfPraKGLX{NG!@D9R zyJi`uJ$ZcN+?YzjO9?SjjBe-50)D4w=P_w^p@2o)^#z2c5~>;II}YqPc#3>Cw)Oh0 zE^%CN$Be+>#XAH5|7_AS-BXL;7xR5#gk?Z}7Bef1e16*v*Vx!gwR|ZYL1pI;DyD914LK7@_ubqz?BK%DTC8 zwY_3?uIe-0?bJoInXGsISrJ?0A?T&aPx74qgixii{ z$6^#Y_y2MBR#A0!*|zq=9fG^NyK8Wl;O_2j!QI^*0>Rzg-Q5Wi9D+OHU#VUD{8eAu zZJ)1BYwyLp;EIbe`|7ig{v0WPl}Hh4sioT3!@l5Z`O&m_i}OxqGuzPA&$v#i!IV|= zywyif*{W(!M~;k{rHREyV=v8)S)AGNqc$JDLB8PhCO3gMB6DLoQ>Xh-FR%l@`5T$t z*!X+oywBisE(1AMV4oLN?Oe<1an=@(Vf#To^XccdRK^GBtO3_XKJYu~*!HYK`N{VN zL{J||+9rEN3uFT5MXhOnXwO`&TSdxm^KGDx1&Ur$WZj0+jNyX?@y}}7<4c*7jgw=&>>}Ob!O9|RV@`W;9;@dCGQYd)0ZF}66bcz8aBdQ1aWsdHjqUBD z7Hoq(7L0cZUzg#bUzum;MA`IL{PJx#W21q=TgO}i$Jgci+;K;cAIFp9{hQbQiPP1> z(Lu0T>895YtLhWg+khi(h4tsVqlfQF0uIBAubq$APgRc_S-E4?D0?&0PJ&k?G5Ak< z3%qXougE)9BCdc%Y?AI9`Q7Z&n(%bj_pyka^A2G;d{j>%;k&%kPxeA&q;mY0zJ#aN zIC@V4Y#I$a39qSa1{LoJ|9(MSzaeO~0f*wBhrIuEDE?mrw2Hp0GLWJ24tCVvwe4-4 z(J^Z44%d2>KL)`IY2C5eoS)vSc0@3nvG!jATH`kzE4{6|j7@XJ8Q5-L<0-smv>~hZ z%MYW1L6=yp?1{Y~X7X71e`KPAhI5ojN1KzJ{f>Bdo_%_5a|9o`vNJX)VEyA^0Zu9a zD?qRKU7z9>jJJG8MYgRKe_5oW_IS8e(SwIVysbK~d}1v0hRTw#LkCUP`YA6By7Jb! z_viBUgPJgI;T6`5?Br^+1hUm35XA^B7Q{w3HSL0at_S#(6_!gyWLzA(ET+s6474R< zPypQ?=MoBfe_yGZzBfnU4|%d;72EUZp)tvCNw#HR@9Wt=45-mnW!5T+R|{r7s|Jjc z!EnzB;E14JLK$JOF&rtA>7;T4n47o-VyY`d{XNU&{R#T2KOA@|wyx-2?|dgfX+hZ9hLMCa?!>jx{@kGsVQyg8K`{y{=in+W_Gs< z>Bm8QUY~6cXcN=b<83M-34}mxO~ufe87_I%GoBQWp)=kZiyT&5+(iQ{ub@1_K`|El=`ADc=d~6ZR+2L{S~Zk`|QEQ0_L0qw^+9nzojETqBk76%FnVU z1=ebM`yjENcu!SQ9XC6tNhn*!BdtAKC_cz>fZbG z9hfXXl@H1bO;ml!>k;AMFq(Z;h4c2sdl@LtQwuP>hjHJQuYjpl62hzTZGp8N`st9W z>q@WWo>S)S`%lD?7K=_zhx$u|hJBlXyGXo#tV5W5b)KA_)fqtn-B;x*&Qj%VV2F`7 zL`O`&I$CXy-NqdzOhy^8E=!)YiH(P+X0o1k6kF5yx>`gK!4304B6aTM7+%C%#AQ=2 zC<+HBX>9EbMc{W(kt1}ifWUd)bv^#B6>||HFX;K-2@SN7v$Mq`XhvIGL7`3URZF{SgYMd z-}SiLjxzA=9CSy!xPB;`KEY-aIe0*%)^Ae+9dJvTh&aDN9p-4Z?m$2E7->q5qt`}% z)HuY>@oiV+7f#T+T>rvv1#7c3>)5kC1${;1a*(dFGpFsh$m%oAZT1Tfr>+aBemHrR zbHC<~x#O6}jY)-pX_lLs952Evq8K?zk(ws^A$u}keNy0nOp)k($=Rcp(ng=N^qM!m z-|R55;h})>4?LDwBGRi76`S<_9^$sB&Mxriqi8qoqtG;CoP+uEFYdE;6wd5_s-XW% zHU5i&9?&^ab@hM)fPlwWRs+CaQvra##GzyU5{H(;1jeD4{xuF=RyFwx<(fFU**o}1 z84KUtF<3=eQ=@%p0z&PFG{v7dbbXZuFb*BGKdfX`4va%jHu3{AAM1_r%TP+yawP1- zxC_H24Li5{%u_EY;QijPNJ2#fvWT#_2j|_XDu**c_t22ON-MzB$HPDBIQ0Afs-Ty3 zRcim!>O0rJ6NuJT(Y8UAK*Jxgj!R;1uyzOnvu=<9h@~iT29V%V_CHX3TAXb!CX^>E zN3}pB4mc+pjG$HO>BqSWlOaXB4zLMU6nFu!7d~5r;7cT+D~ZAhOA=XuNkxqhgnViu z44v3Saqb@))J}?-CMJ_ z_6{IBI7!&s!pk^-JIPuieCgAO z$wZ9&@Xe4BDZ)|8J1wMu$Q;&5uiK<*&7j2(LLz!7(!HYeU<> z?|JCUE#Eam{1N6%j(Z|NZ`wzWrdaYiSVR%|7Yyo8h|M!&Q0l_9ePWZq@xoU}Kn+pJ zg*nUxIgOPsc_+Z1U!Fv=-N?C1y;uicpX4P*Tgp7u){+pEuDM@LP2|Q5du|15{ma<6 z>qZIH$<=&2EK|7i2mOOo_B!tSW|obmpn&p%rE8RmK>G;aMg8We!;16-rA}%T7O763 zDfg@)HSDHJD6d7~49*UB*1P1TRG$I<`G@&vUZOX1=7CTS9~X&VYP<-~>Mz&WBmDhD zU41{Bw6oRAO(cs@a{`aqE*9Or48d{WY9_V!Cm*gw*dWWN=9Rp0-s(XcbFx>9*sUeK zttF+4=ZPQ!^f_6K9P>F+L7rbGzab`NGk$LjB-e){!YQ{@h7>K|Ey24}n&-x*BSCNG zpt$!A$+>8h$V_~osiCK&k7UM0qi^U(X`(KUy}Q;^>}ZT`RDLBMm=dRhTEm-=HZ&}B z?lOmk6K~DJo-i5Y+X5C*70o<941x-HCOw9zxJOI6j=a3px(i`YC{*_lpigp!Bfc9G z`jD(51XVd0076ekImA%U7y3RgSe;E-xZm4jJ0sIp+-b|mG`rEY!QO2#6lpWHr#>TMGp*2DB0E6hp@a=V3yGS zX*r-Op;jMvWNU6jTXTRLw)Ehb)>S%;H{v`U^5)Sq-wYh0xB# zskzr4U0xDw5_Obx$%KdJ-$e@YPG@l0V8Ia0alDlpk^O8GdWOOdOW%AG*j`4&PQE0k zL3-t9t9|6R{tEYgDL+u-4DU6-(`F^%OxZfO>Ge#%5u18Ap>0E$YuK}CvC7hTZ7p}! zpy0c*ESS?SW=gmujh+u?t&)Tz(N=lTLfW*X0Vh<&ajD-d$G7_}S_()q@U@6J;b%^e z;quI<6jO@v)Rp)7YU~|r-{+(Hep?sUB)ps5Emk(inEO`_7g;WR!~{@S|H(}M-L%I) zXXXE{t9AdWt8MMQVIRFNtK2m1nzv=xC36-FSq~~4&C6~oB_3y!uZHEBziL7tx(du$_)oIwjiqWw!2JmxO;A2DgqA9f zd7N|mHk))M)Z19drh7z#0qLy6I6e^W2Fa_6&J>}B0;y8iEAAADCUnbVY?^(5U33(9 zVo)hYFPF)ano5I4GePB_QHVwm0FG>2m=P%D*@RR#*?t2|c*GIG+Y$ARvu+4u#jgzW_yZ$t9%6jNin5Sak7Jg@`EB?T#G-m$9YRcd6$@o z+b9qZe1+if-e-d@)5cIFJ~S!PzPPLfjqVp9V#yA)bi9>y?q{0tGOklPM=#pq+^Ty1 ze#jpYYm66LfcH9=Sdf1a6k<#s^W$@&jv8gE$-=y&JX=^{J>SaqWH1sKZ*Z46SHkoj zGtZ#4eT&-pqGFV5DW^x})`QW&Q5uJ|G}QEbD7>vUgU)hpG{`c1fF%xpd#bQ~H)+%d z?agbP5s`lMHIEHg78mwpw7n2K&D}Y)>0l& z$UJl$OIYM8ahlR}H2=K*RiqK~X3E?l^Jafr?u`aGF;gAOp6gq0CC2779hV)p63{P{ zJvTfpZ=1f}whjyYtjArddAp09nE zpP1wuX&bPO$tmVvTitd(yWUVsxh__pwHk0#p1g8q1;mZ6Gy46ojX()@sc3EcJRN@{Y%CLI?fVeJL zGSI6@iez^^YUSWlWA99Vl^nrj_+mS*`+oEM7p2`L`XT?H<~;r}G5>Eu``>aN;eWBJ zhe^#DbQq}7cD8u`JLi#E*={Q7?pVJ~B0#Wb(j$e67I|7xAj6wy2x3>S<46>4#eqNz zua#Q6sY&C)T3e@bx{b_|T9y`r@L7dA#~k+eU@Pm;!Q-n%w2XQH)u%Wi!0|!On6Obu zT+Vbf5@Gwt4{(J~{d1ORxjI{ynnA`X6opAAmu4&KPGS0d7S`%%Zj@qGJa$Hj-BEnyQI$?>3uDHuuTb zW|`8t#(?$Gde%YR*}NxK4Cq3?#FD6g8>=3iTXLj&Jig zK3)WEyhG79JQ?Vi6c3T%Y;J~_=m}q>Cw@mEYo;Y|AONo%)VYmiAueBC*$P5@r zUXJWruz~!nri&%ZpFs#(?Ojk8-gMvsk+5M3kHKxmkZ zab;fxnHp(syvyUY89Zqz<-0i%ROvb4jT4qOw-U?x;UCc><2$P@`RLu%Hfll4Iv-K1 zl(jf5UcGW|o>o!p?{8n>vS0`+^c%D6$k$T(&u-loT%-4GrtNrsGXIGjv$WAVjgtP%k9X2EWm@SR7-Exwaj_sVpEgG$!S7Ju zO#(yhp_j4e>NDk??jdDj7nkxNQ3sA%Q(c!t8gJbsC&7d z)+cydQ-t5EK)o|5dhjWxAs`L&absiq4OrpHh-P{X@dEGd!=NhcDb8;9@1tnyD{6}; z8cea{gWQS+YzFJ#KN_@5>?!3mWv@h+KW#sO5o}GI{dOsk@NCQ!wtnN7bv+=?SGzry zht25)$9Yc_uJGJ~C#t?i&pV>6b`VXhY3)yArr)vPDG{}nHO`T7{}#N(U1uj&d%%K^ z=}^p~e5rLS0}e65`+YE$-0)F#?vyT%nNC|d(3D}pSE}-rdV#sPZgP#@6X8%J&oPxn zxj?JoviNH$JLU^JV@>7A+yEcV4>1D%1E$aFE(L)xUeUI>JXiv$K5s@r?$XBs`IjXJ zr+HKbi81Zk{S30CS8XXXH6U@k_rx6922j!E)1|WnV}p3aTpX}rB|av|ijS6!1j4*h zVU_~Ae*9yISEjIXmD=+zhr!e7C8*Xff#w2CR1p zceWbNBB+v){Vpn`S(`Z#I9DRxp%4Tsm5-Y))~f7Hk|gj6?~1u za6v2<#X41ApPV_WnC)h{4k@zI!M?KLH#zzTKW$qv+4qWzyWvYadtd7;-Pm0CTk??4akb17ZH|avVEp<$)N5U(l$zR4JI@Zlk(5I)h)|pa32dXAmUelf;~utMM`Cqdp^XKWZ1xX8K66c-n*R8GwDp8F zV+b=JG^NpSPEG<9GNSuD)M>9j$Fzh+6+pD>$KqVxR~@Lq_2`0re4Ig8K(anIf^-nG zMNE`jT0sxo3ve%ne_qXdWQkKrFdvkG3oC4Zg9>-&gkYZOQ?j=oe9U0MX3Eem*Il~- z0M}z&L>~{)fyp0%Z>w5y^^)G^(atVy{lMfG+|A*`s$5of?*tG5K7>Xse>hqi{u)?+ z19$GOw4Gjg;yiAGosx&R3*Jmrf-uMO$Cw}>=V$a6$fBcCcy115NO2O-Nf@I=EH0ON zxr=Ztw(IL+qe?h4&!nJ5$f>h9u?{`&u8TQWe)3#j-rD%09m#F{%QU{ki+WSsR>T9{5B`qI2@dcM`rbAJ>Ep_{De|%>%^6 zZ7Us*s(PjsB88&Rzd1y68LoMe7wvyUoQ@Ky;P^-`)_$1!7$d-*&<|4u^ddZ*p z=lzxG0#dVttwoJK(HIO&a1({V29`6!pg0oY9k;9*zk?|ewQ`g-Yp+B^~JX*VDd%h=foZEqV z$9FIRhdeD1MD&D2-1}77gLYccnpHX$vou*T`tTO(_89B!f8KzLZ$=tx`jodw(vi$$ z%G8IiC*rXm=h>LJ@V+am;AFuavHZlJ-(`-jIKh2K6ftcC8sjTp_%quM@>9!Gy@InT zCl^Uy+SU)5^w1hMdgVg)^1A5~t;GJmN{ucmjrx;Rnbt2S)aogoaG(3?mZ|GZKXZ8~ zH@c-xV_j+{1)6efeU+>H&Ai0|9F^U(06`m(VFd)SRf zfS5V_0c%D~8tzv`(Kx_86Sew>4Kljz;sA-8Ax^+d)mL8xkIfpS z`V785%33`5(1GU^x_=Iti|K+K&fiP4=$>d@fk(DQncW@5hEcz8cJLHJ&RWeP#!9O$ z6tm|G8UbzVcQ8T~^W_T0L$0p2!@m)(nIFa@!K;HO&$&&awiyVeeQJbt?; z-yGqZ^Qm($QfHf;xkrCoYn4&^oaJuyZtojjUJWRr9ENjh!Abo_%NXXMVP@XCEbd{6 zFUYvS8h*xV$XhR4lc(MYG|FMbv*9`Ul zXk!1jw*Ikg*h>L}fnijjAqD#xuEZ!?3a8A97xM^;4tbdwb+~jhy0we=PlrveaoMFhU^`wjr3t=rg`BDf5ly2M zYRt9x?5fR+w=Z8{Cu0EPkTNVF#*2xYs#2*I7@}_Dyj3T~deYQ=dGlKp5o8Vy@{ziR z{P+I_Q#3c{2=LbU6B+!w{i&{hFGa2UZ`X$2w*iutd%f8Z!gQTkY%Ah3s6dKz*A2o| z-%8WyPbhM5DX9#s^eqk(HabU7eT)lc!&kbjk$M;0#=4a4U z@UUn=@-8PjlooFVy(%)EU+hL~BkvcY(BalBLZxsBv3o8gK-6;#`^%SZa}{kRXNpKe z>P%^@X1BpT6}I)h%PNSVb+PTfd7AdnX7x3rcS?}=;+8H}EiZmh$%=Fw#EIX*o%XPh zJcdM6ewRRr&HX6A1DYNW4VCB+A2z75xMgfeCHs;94og9NGBj2|cGqSIjqC9=jKX+e&{C4P?rcr+Z8M(LXuDCEimex7{09pt)vxVdArx6Vp7_%_rl+K1L48F=UIwQ95c z$D}a{vw4J~uGc71*-rjJu%kb>A$P1|_5eS&8!|^XAdtrh>i)0_yo2zec zQnH9AyNcg!d8~8Xw2nii#st=qo{_7rCPgsY_49A|ZoLDvWSAf@3*|#83Iw6UlCE;( z?MbY=h}m=8wMtkj7ftbQRoa2#bOcsQst6l{|Dg~Y_ZG=O4R%qVfg(>_MPrse;>G?n ziBoygX}IwdGd^bPPd@j}=_#*CxMy2GXx?O_Rp+W}IO!E!!!+=_8^s)*MB8c8tkY+m zNbQ*Pk<|&kWo(Sayi2z!<34D2PSf0|bPT>jW`3W!Eym}~o9^kfFFq&}RqTf20 zL|lvF+ac}rdm5Rw#L3!C)^g(lOO7oMqw3Bmhk^y&f?HH!AKn?x4Q+l=8cuKxbZA@)I%7N|Z4;gyzWH6AR3Pclj>~hM9XD6?$fKWj0**;9Ve%NdDzmwU^IeP7CXz0RM0;`ot>o3|%IY zt?VVTg#5@R!dj~~^w$TD`q&5Wli2;H)_nx*)r9(8D~$#*UarzZx2o?`+uk@=uCBEY z$F6<*a#8pFWtB|UA+Kc2twE0Tm$SwPuR@8_svZn~E!{=!IfmS3ON2TnxyQRF`F(FA zI@E@1|InwMKekLv?B&Jy71Wi+(v{JraZY@PBq7!EMcQ8(E~4c@CG)^}N%sFTFaLL$ zt^0p!^MDy^eD^RHjRUP;LYR66PDGi@!pnmGnFh_pZ1gHx?UOnmy(z10 z)Atb9A(mmxolMiF!&m(wsVMVI#xBfOdq&k@?HSMCmC3aC_Hrvw`zG$adybxc@@C#& z_-6Pyyk7()08BtCFjAcm3}7|XmudAXhW)!hWr4QrcXVVUcWgCl#k_OOWBK9>HoK@< zdM(ltUY)u5x-&(wY-^1tMIx)VU0tRy)%zJTbGj(8VDKzZu^c1%; zh5}8L->|AlG)x}E7DR@UnR$*oWzjhQr9Yj>YkxKy{#RZ=H^K33lz!{bl;h7Kq|qXO zSgrz27zuhsL^}(DStg><$2qPO1>t7~*I0^z5g0HkAvpp>%3WwU;AyHVxPRHk(Av$1 z)+#5Z0r&8}%6Ns|3B-Q5J0vnqvGP2j37inaYO%y3*fRz2yjaJWpSyL{1CzVvIT+LtC(Ce;ynVQWktj`moKX)IDn?4y@Vf^ z(&O!*WSh6MTncVH>VW+7JbD}*$7QHpKv22#!d|txc5OD^cg*UEeQ0yaKCcC*niPSB zyJA-~@AF>z5E^SiMQ0iRjmV3!BNw7ijKke8M|T~(&*iB6F?*}YPnIh11`drQELrR` z>vE#E8J1@m0h4hDG&1~d@kmh~xy8PWd)AKS$3)l40o2F$19fDZEBmqLQ!V|&GHwg9 zp}Ch^j@>oG*WZJ_(j-(^I>l1twU2Sb-6Q3zMLp>w(&SM%2ApZx@!#1h-?&9;jvc23 zzM$eYB$~@>WIPKDeDQrH+>|dYuX88laU{DhsLQeQm_CG|}>OW$^9T(oaZ zSg9E;9p}}1tDJ%G3CrI>0*jeV3+_bpV&*ETu|f*=gYE`*+4qzcXhug(P_TG)2g)TZwuNmp|Y&yN4D!Q z6Les=xnvO3ciqTt&N6Elmf3CBUTY2>XR~IPqB&shxzU-R2*%GgQ|4b}g=!-iu~qS>g36iF3g)7t4* zG5dQf3T9F`7kiOry~xd&47UNsVG>EAgijPiG0wtCj_47EW8kZ}AO8^ijVZZy>t$v+ zzqx%}**fyT?FYB|z;E6g)2)83tud>s+m*p@{rXe*8A)0@Wjr@uoJ?#O?c6#gJz_Ya zlHIpEoLy!7IB^hPK7EJeuUJ~9$e_$?OMnF6upztOfBs!5Ru!XG_F_)yezJX3lu;T2 z0WL~d1N#g~FZ!*CbHJ^zx$s$ahZ2XuJ>-}!XRD^>uLcF5;CR?~VEXz$>7)Lq)chAu z`+w}x`={>yulV&~zc3vdtrW2&i3M>u-LqyA(9_=3{Q`_%W0GpDPJiuSwRF|mRwfIh z+P*~2QBeB2NzUvfa=uMNsnIc9NcJnDqGx$ zAfzIlQjB8kUpDuAo)(Llj&X?~yyN{s03aoh#Q?=kw&_U~MV=hEhk}12sjmLW`;)(R z`XBPwt-2}Tqri*gPyYJvy@=ZVU2x(*U|<4mJXKxBVQ%qXMw+N)eW)^(8LTB~xg85c zPMet?;#s~G<5!eRt4L{iWrb$*R4IpZ#N8L{8CtOgms_rD-i3 zDlvujQ7nKku))}%zKJY#Wn3*S#0g^m`tIrsJkmR#LA+&;S=FzWH zDlxao48k_7n&VjeV`>rW6_45d{K(}cjmt(G`Z^1>_e(}86|z0l$fi0Lw5fF(+LXhT z!6$r);IFm-v?Am(|6Y^58f=356Ag`AvxtzEUS@ zDO;!-HArU{%G*el4f;X7bWzE7-KC)x`$}v&w?EO z@N7PIQG{m%BVOP(0N@`*opk{}T3~aC##D#2o@S4`*es~V#%p%6R=g2=Y$(Ka{5R^F zJtaYG751rkby8~$j}vCJUe<7n5vrKxP~Z+DaVJr)a3Dpg+%sgDf_f|2@8dE?zTUt} z@O!=6PeMoV->k;J<>0f5Cu?RcYRt*REQnusAgFrH#=Yf{=1Jndy>JND)tKHIY0?V* z%vTP=f57IvHP7x&*kJo<#y|?cfX(UL88YT{=aNm(j6619QiB?n93OeFX2|~m51~>F zS0D$YM*VI)&Z}hF8+iW|JeF+z#RVmnd5zzV>={AFV9Z+&xK4VcabrfHuQt|+xknio zh@x1h+wGs}q?=?t6EPh@M$Wkrs?Fi`@z5Wp*&6SUN&UnGV1zyB@z)vMN9r_T0C9|9 zow-g`C?BaAIeGr(Lt!I0J$K9f(wdcPWoYJ#COml(y83K$>&%?xMK7(8VkEs} z`lV^fhC-e(G{f+81VApG{d?T(j<&<+L#AmWQ>9}Q zzqkDbZTcx=Kdvw9VJGRKg2#+wa+2(##bvN@IyNz)*>573;M5M7IFW`Pg?c#v6Y#`j z!Yd5zOeLP?I(m|0tmy{AM3j6ludn2nJ2S(`eQ{Ua4+NxzF{a54C`lBrYQS|yGiN~G zNc7)So1gfiMxOU>JI4;6`V={7I*cG!OzIhkFULlIa*CQ$sJcVq%ULbbOg7-gcc^(ePMzT}p>fkEvX6x4mhV+b#accHwP+9CYOWsUsaDoyC32dL1vL$CbCF zma6I@2sg(J{B-(KSr0aDltMN=2Oz-I}y4U84WxwYIvBs1ACx15GFO2V(z#Ecr#+z6-8B&FsOA zOz2Cr1|jPrX$(=hB^eH9eO!kCl>%d09vz6Fk7zU+zOR#q<<&|Hj+;QL80zo*YlC8h zPNS~&=pNtMmkAaa{YrWD&WGEHMgwqqN#i25mFP>WDgmperVbzl%$ZDae$3lJhx0X z>YSyl*>aA+^+y%wgvJlqFtEmAYTHl~BRGraFkdRj@_w^A%%hQP#vJBXCk;$Hd-R>T zeHF-iz4y%Z&K7G`v!AVGWNGPap$d?BmsO1z47V^*Se$QH* zP6}p~RL5Mwmi30Mz->8aNUr+H`s-;7rNSOg7CRb0X->+QBP_un4#r>jjf_O-EWZhY zMoc1i*V=g#f0R04xG_f6JQ>>Q6!{N3v0?%q;=CZfx%AxS)5KRM3d|aN7>RI$+K_5m zDE@V{vu{%9n&LdtPY#df`CQiF5(x7a3mS_y05NmO_b)Z@7fOyJWasuF?_l#11eUIy zmm5CEO!=XkwVbf89;M)E_wJTl2kMstEI8r9Kd0Rv#0pjr!W{gw@b1J6k>LKEtYOxg z*3Q?@Z?qO!DooTTC#**pZlysON4f(OZ>iL-sWQV}-(Wq(kUFSqDw%v3hAJ(77fU#T zRG@9d&PQGpA6n*q_0$9Sbb_j6>KLn5(DW#5?$*q31%OC6@+@M2dXxq9Btr6-zS9|- zMAV7JqIGs#tI^8V)F=jhwt0d)0vBIk-&{kt{O!P}J+D+$ZI(2!b;up|vj)qVw83%R zuq~Lq_ZwcS@kMH5N=6Lxh}>B<+OKy3U!j|^+8)q{cibBw8Bs0ipei16OL1B%!sVK39{t;KC$4VBapDm;(OZL+EH7GsW5^)DaoQ|E}lRHwin)5jQJNBA)OzvJu;ZN#t~TR z9Nj(XE{t|t1;NqF3;ia??kAg#z2|0PS z2V^JCAe=Ac#>tqcN-LlR=nGIvz#N=r+0Pk1eJpQS2m6b7WnM=kMe*tK1m%8o7c26_XiTmOx+9(&j)i z*#LYN6j?IRr&NHnUPrM(wW}!4eeC+)QZk(+mxewa^;ddgDU~eCe-)(x)$I{ntzT4kVTsXzT?@sL4=5js!IC)KmWX(t>Q(dEiU;M8|0j6jFy$Y3 zA~Fo%R0#}NgeN@*7c^|WEasV(SZ?3W0E5a7tIAE=vrd@5Ufg_UrJY{B!cl%)z4y|5 zI&GA|I^BaxG|uhLuA`E2HzPZ(fpH^=;xY#)omIz&aH1t=Of)G-s|yB#-Db<2S?^SI4d3uM6T`B-+$pun}o z1}*f{e1E>w)ll#wNuWMN*o@ZU{FL)oR3*+n?Iz5`orE*Uspg!`@d{_iDSOZR*wV2L zDfW{G*j7-AC!8(&mjmqu+mjEc)dQLa$3xf=frE6@?}L2yg5}4^=t$e?&`tT&W(yy>NtMlfiDbA`&)7KUM3Vs$!eluGq1mTzQ`0s?x5HGCx*wQa zI_N992Q1{mpOyqTuA_e1WB|dxKxIC@2o^}Q83b3dWbiDYR9m;qUZ?bc{Sge;!{D>{(mojT#6*JvqM0p=eqD2R#wmUkTeS#WlUBakR-OVv>VXPp-!{mW&hw zjELw(!Zh4{PB<8MnjGPxl(EeFkhkUlWe4>Fr1JLd`7b4Wki#ANjX+fm_}gywzs$t{ zU044fdLo}`S4US!b;sz1F5{N0TxMl0HPNS65L{&ymsh3DX!?Pn^!VidF#QicF(BB*+0a?==`(Z;n4`R!xyait%ghN2mY4G{=bcCXnb+*c z+{ev*2eVWzQ2z!Lz@icRpD zRBEj@C*j8Cc7Cx=>{OD`G9XHSv;lXdvfd3W46$tvChJ4S0ib(TpbFW2KTt)9HjbNX zqTG*7t|cx)cASLvhrGr)Q&k=Qt>h{9PEOFr_*H9B)qMojD)(1OCB+YL=9Df8sbWFS zfH{n^rSnoBb#41lpgBj|SIb1#zpQdz40G)M*-waTA3e9p-S-xQ8^A`)i6`HOj5|2o zdBX`C+W$oGX-o)quLA{7s_!!=JTX|C+ObR@G3lSv2D(~HT(uqH)+$4j;b2kLLCi%P zE{9I9+NIyO!N_D}XC}2lAH&Md2r#>;{BU+3{`BZNmJ>^rKjy=CYT1qc$jp{6KzyPA zE)bvC6yz*L<2`^Mr{}1`lUcyyEddfzSsMZhyUEKTwP@8bB)W7PX8v=!%&GwmTy zHa#h!z3^8D%BxqB;PQiJA%cs*OF@BwIp)Hou%r9*^tLFL;oy5O+G&@7smDsqMb!sfpr8UwZe&Bf-rsOIspwjnaV# zqo-{K-E#kzF+8i;dqlF2EFj_YF>kK zXo3~CU2}&#mSJ=umG)1{CU6%gH5MV>J_nP+2Z3-U0IEp5d&&2Vp^*1P?apLiS-7dpK>m3%h6;(wNhVysF@koQFUa$6T06lWwK@-j0Z zfi$~IadA=q5>vFUZHmw~!P0PapQmRjz!9+!0CjSF-A2)(?EqL=vj^?{cF@HhR;9mo zz@tR#EE{)Gywf<`;FyK{>4_+rc$*rxkMMj7hc|)I(gTIJ`haBzImfW__U;Aq-=h&J z6t>Oz|B+w)e}?0~i0A*&um0b}vu$MoGqvS;{?m?JlXlC<)<}oczUcj@QADZsEmH2h z#JkpsFKC&k9Yxv=ItCDyqSfT)qD?O1RxWBOSM~QQ8VgcKWsNgJqn@nU$l)}$&IQ*< zOt!krxZh1Zg3=o}%>i2Xi3bI>pUK}1q*CVi^ge`U7*BCtu3dte=F+;}9UlI|Pc)n3 z87TOt^YZuN*LHuOpD2m@ho5MucUSG6hGVnHDpOAXd#?W(jQLN^UNbDVv$Nl7)ohds zH5hq>pb?82gWjeX&T7?Dm>+s^@hH}wT64&*hLI=>rI;F(X>?(@9lktkQ@!6e?_cew z=WhSqZSA@9*!?SaB+J)`5+vLbKon{V>DTg+K#!AaK|p_j|%Q#PP$I<6o+Hw%8= z@Y#kAHIu#?iZa6t(Q3EsSig9noET!xNPpb5lUunQ z2wncphI3ob^Lc|l9`oH4w>W202O$gpcfQe_?Yn8BPp6mFw5^Xn)9~TuGOq7gWR7mS ziC}X)cEhizJ8vh+fL$xDrxi(|gx6162L?@e*l9Hs2c^h}ZdYYC%HwB5*2CnFPfe3P zR$JosO-fmwMoZ!!nUoJ`JUimZCV50*F-+?e=t3ivD=D+=F;b>fR)h8@%U|z5ly+F} zSVPydK~m*o6I%%zKcu|3r|o3xIgNlX&#rTMqgUO}7<&&w?9t!{@kILU{gOpr*@>X4 zCkhblq?{-k)(zd}?BA#C;S+1c?YXD;=iPw&?^Z*<>>jSkI(8MlLG0-TK_Kd-Ar|AP zl!ano9UjyU4Ww)d>UW`4co>-{s8IZPH6tfMf;{k5LR1(n07QdQj{@O|=j%t<`1T5u$m|YAeF=J-QXW-2HUtCPu8?3hdM?+IkXw z?79v!QGa>Nx=oQ+NMQz_Bc(pu6skUpn7c=zE*rm%v^Rd4&3?2>_c!P5loxE{vccn;5<@hwI1@x8Mt*fOuSrG9sF2wmh6xoDaj-TpZ(tJ~?+C=|P{S8@Yn zCr(F#JU^mYc|$CG5#sNmaPd8hCgJTFcgte04sK!2mGctC!VdJ=|Lg?z4|ZZXDgSbt z>`;(Ya~7>4keyhay^^xn7B7C4_c~SkX4d)J;AyvG>K-bw#sBH{%j;!X7LR_!MgFg% zo9C{Ztf3zx3ZrxVv@TF6XX*vm~ zs=jlGoCRhZQqqMU6o1e4)}-^d)36)JJv%$&*I&5jZ8c+Xr~JT;9Nd4u4HJtnf&3Ez#6v4Qr!QfCffb_YnQP83|X0_8=eBapW6Tc5@T92-!p+cza0eQA1}*h{F3?n4(Rs~8X_MC`hIS|UNKXx zy>njFs=1y%zsu#luP{Gs_cxyjywaN}+l-kD;?~dbuHqV>k2KS_RO#wtAkr$K4`&&k z|0<|0hbOXDCYh2pQsK^2N;JbdL%tDn7x+P<%@F;{fS1)RPVaa(K-Bbw0)y+Ng{7{1 z{wI-GJXj$L=YWY~wSRS)Kc}%n+~|hV@=?KsPkRlpGRZsCcU+M+sdxG8tBl+4{11h- zKSbGR{;Ybzg$re}?0eHx0Y?g>0d)2aeMZYm~@cZBj@4GF!Xzi#a z+3^u82!H;6l-*@iUJH^gU|fPjaDq#4cXxMpcXyZI4#C~s-6aHfcMI+i+ydN>bf4*& z+*v)R7auJC@V9nRyXt);x-8otZmTb>eZdY3-7RYQGBdo`skzoG(K#1BGm#;P>fK+Y1_)RcF^f zqPCs8PAEkz8*anBx%W{DUJ23n?8K+;EF-r**pua_{Q8*1 zdaK3H9kN}!y{`wNSypk*0f+!3QKWIY8RgCMAw!xKWXen;r2PI89Xy}elK$bkSGuYB zam-2N2N3k{SUsLEQk)3Vj-GOwi&unqS;O*A!E5=Mi?r3gK>xEcW{4TL76CftzmFvT zRT=+Vqx^qQnb9C2?d38G0`Mzy0`RZI(i?&YihfHl&6WNEJD&IUtmYY?Z9$HBWLP-+ ziVZVxn#}#zvbSC(qzA8;l+sEkwCF~IzZ&iBM9SSStgA5Qk!FreV+%Uf-EEhQbFLSWMQ}TbTc~t z7&G^am9o|Xo)UjwNwoQG;ush*GAJuS1A$WX%`3lu|B;aLSE}ABt~ZS8Mb%U-q3B{b zR^8m`0}*-tdKI@^WUR9zo*f`HiJX3v&YHi5$`P`%ogw|yB-H*{PY<~_WZdt05rL{H zDP;m_(20J4swnc?{`VSvzPq0O&I@+^7VVAqRK1ITr0U^T$95R9g5U$X<>&Wq`Lhu1 zDdpQ#Ji*;zYFV3NT8X`8R&Jj}hE;ruNag*4x?USk@*j4pZWxT9E``i1biA+}FdiI@`{(cOOEpX|UiV9g+zb zqrYdVEICT~aMtu}IBf}+flhVez{2&&0EQ_IuQZ^ZBx@WWkCzbpq@7(5dUBvV0W4Sy zfJwB3a=ETS$DDn7jLN^p7FA`Hs9gDZh~@5VcuEn2q88&V^sCZMX_Q((~vVVjAhA-(r=l-x( zVH!zNWI~eF?R}3b;MQFu0Q3FulvmIYq}=k1cMi*T?d?)aJiT`m>FAYpw92D`7p}h9 zB&*}JR!4AY(1dGY$H#JELI=}ivp#lbzjJ3;bvG8olS1!4n+zm;Eo_Pql5+Pa<|Cif zIrF!36`rqEvQW+gBeS+{GI&znGULmK!g!6bM5b0ZwCoP*xsE*HkbUU;J>`s6sSaOG7EM7Vhd*Ulw#I0gHF^;6+mh2w2_8|!232~WSQ zQH6T(BU886p9VxV+Qj@D2~3HoR;Ocs0n6_ z(wLKD6x{m+xndy+NasoEo!Af@RmazoQtIZc$q%BFmvczFTSx8e7GHZNmT?*b84LC? zES5!yo)K(T533dz(1+yji%K*6(d!cC--DypM-4PUwAF9V)25nN@N454t=iRhqM;|u zIL;IG9xzV1P?#n_pIi%Q>BuE*BdX>jS=R`s@&(s{-H2&8wBl)xoPu0qRnM^Pl2mU&;*n2ZwdqWm zTxCg$TTZ}GBp5fIMg`X&3ZxJR`HvXTIA3V{=dvMlS;c%3|({niVfY8Es`3 zqF~L(bR{azm&-tMwCmX@<{Vkt8hedN(BUCS*c;RA1;6RzUMF?C0z7gcIS+D*k(Uon zB!xxfY)jCPvLhEkyQXKKl6A>qKrO`lUc}kH@mq~ypHJI~^aA4)c7+K0ZR>(yxxFG{J{K8WLf`{$impF!9TB~zRkqC^@6%&O!hjiDmuy!5t;W! zxu42`y2!Tn|IGTFD0CU|Tz&EwlSCE4#r76apMU1l2|zA8+SFz2mhPeYYl5RiHJeaH_vJ_`SF zRX16!1FU2UxgoQumHfx!H^HizIl(loOo#=Wq=co5hPPq&g`Ns2hT>prORUu>J+9tI z(^csMnYr&~V$o0z$w(rZ4yt1CpW=x!PcwF9j2el?qH@lfbEc)tj&Bz%?xOELqm5Ck zyqp`Ok)|fM96Hm0T2nnd*GP|usWprN9OrM?YRIcEopY%mFs4VT(-X*NDx!Uw@8%G|XIfpDQ ziTKW0*~P#@c#EJUIArP}?URW$0Xrw2S`H*m zRSAoXgRGPadoAaQ?l@P0J9p@^sqHYDk6cEj#?hz3xY2E@_!qNFtxEWdcEP(0(p8Y3 zjoyaOvn)6}nE8{u=w#78a(!*=0DfFVz2e86RcOijQEw@7rjtK3M#I337DYC}X}BCH z8#om<=%cvLWKuc)rQl**_F1<8{v7wo`|4rRt2 zS<;l(RebBaZ|eE_oMxtMc{_XXN6d#vVXJKcpmqNHgyKKy;@@qYr{32y{%oAp1Pv8t zmiRBb)64!^&lo(R6s;YTg1kLI5}}l$#JDN6}Rr_k-lzj4w4gl5E^N zp;#hA03Z~R-s7kzLp%TY7oyr!;q*Tv6m4|>R>lY53ejp-1f$D~NygHUlPMvAgP_Ro zDPPP+|Fib&a2O0Mxz+N+tWEsBQ-y$7j#t8sA(q3jTruGc*8<+WkJK=qqK{PxHcA93 zX&0V-fK44mv6Q&YD}etDpD zkt8n*&bB|?L{gSCajTe84*9ehSTER?3px^aMXgeh?Fpl4oSj~UKez`XEMEr5Y{+um zpvnc8!@OeMfdyWlCrhRB#5;@_H|F_JI||=G${u>Z9yp{wc>^1EnDQ#~iqPg}V1TK{i1?XyIW*gxR<;mP zih1uX0D|I$OZHqiDf6syiA%J7-p00K{QT;@G#7Kd^Xulzu0ojB(AQ)$2XZl;?b3G%tmo}U zaStaFF7tTCCzV^V6&OXAHyrnds6KZ_*za^eE_kL=Iv~F0R~( z98^T5y$-sF5wM>tE~Q2%pY)%#Hhh@%CLp~x6Ce`JXw9iMDIb7K7#2^pG!somG%_TOl8Uzqna09R(u@*q%~byrjNx|CH&=-Jl(j6T22<`&$w4g2 zHW-W@Oc4TEc57Y7k%h%|X_K2cjo;!2b3%&G0Wu|%!-VP(NdiGDU;L=ghZSG@RR+&Z z4Q+f;o)i*F3XLI!VX&7`ipQKlGxf7mjUUVF=1D1~46~N=&ctA<9kDkOOFw|nFcFX< z{GLE1BzI-LpQHr76N*}iB7y)y@xv!^LC86%p4Bk_3yy>Qp=UV7QMh7@9t1qZ{5Cym z&mRirix8t<21$H3o`0@Hg%nqO%o{jY3 zbn3oi28><8AuaFivww<|ThP1J=WAM5JA`@pyMllOyj1{SdAJjHm2+OKfeyAMk#(_3 zTU~V5J9sX1l*2u5OB>_|_EY7Qus`0edBl2N2+;vIAP=_KRQ(n?bh- zVt8PM2WQR)n|`7|^nHfji++?Xb78O9x z!jk;NAzYzX$gRvPLsOc4FPs$qBe6$TXEP-S0kRn!2g>DXB%2pJxeL-}r2L5ryw7Yp zws*tB$7i0!w`)0nY`RwP!oB}sz2>33ua92KSdFgR?uUAv>wQ0)R(7i zMS3w}cjk7|a)`;B(hh`<)920Gp-P|lsjnJ!woXdv*ObzG<;+}?)aGZuXd~euYrPA@ zA$QRf1yoMnUv{Nn=yg9Cpp*T7GD!Y{3=IlDqUDvJ5Qyi)-pAY_8!ufoKbDzbL8<># zT*_&D+!B)ZVaap^+c%#zc`gGcbGTY^opx7i-ZmjmT0wb3dyF&vQ$JH9Mtw}|CZxDb zPUA)6L-AL=$TZ1S82VMIZ#)Klv{xbhh_q+N9u&@EN(Jy?-uzSy_|s2}mAsZA){g9} zjehj#H{Oa^33>dbvawH!3T&Zp!1R3*p92>rnu$HkS7ouDt5>QZA`v!J&gGk@k6S`@ zYDLO~lEp-QQT0$7W5to5Uf0ox!&z#Fqk>gSo?|xZdaBxB%3;^{PA_q%$1+~lw-$+( zf^Dirow4@GJdXXr2k9>tPUrN~fLCS=S<#eQ?Nlt0M>?%lfm~ZH-t#E?StAxaZ*+Yi zFfoJ(l53UUo(r}!s=twt2)6KjH|G6v+MQ~R;<=%&jSq^a6@sd+4yc=czeX9nY7Tg*0H7lzb!?gUJ zfp7$QE8#Ca)VaFqIS-bi2GSPDx|-pfE(yCdJIeue^N$g2g6BBRf4UR>XZ*+iy4LYO z&Jh1pV6sFf+W$c)qW=}Gw<4hRcieJj9M@=ye9xw63&-ogirIolG^Ef#2IE}1jNfp1 zcZ`U_^M^kDpHQGcnH`MmVpIf6-qgb!X?+o_7!UGUUa!2^J@3QnZ2g~qMC*M#SV(RL zOlAH)p=hJ~_rgEk$JOt1nQCfp&2tymAPyJ+0>jc9f`lM~SiroP)FXB*bP1{$r#&o^ zM54L!{ZM1a!LFaOYT9uNG#hOQFqa9=iC9U&Tur1xwdYTwilB!Hl*{BV!6x!i-+y+& z9J(35b)9_X>OKJcERGpWZ@b6=3Pl2n?d6&R29lUUfLHe2pTOdXwDP_tAr$%anIUl* z4&BrEu4ck9?51zY!!mw&L0)UK?MV-R(7N-5q5YI@)%I z{_Bne($zBVc}S$NvWr&XqLctG*z(7ZO(I}`6K19uz-(cp#f__)Ps+ALP0C0uZp*05 zTGcWrTTne)&Q-r5UcEPLob^a8YhxkR6;FzSBoAjvw^I7CXCGTfRcn)>C?UTBsk<`f z;rOk-%QSV6s*?rOsuQFViudsKw-P4pfF68`0R5c7n}z0GFFG`OV4+8x6HI*D0xgm@ zw*$;dLIZHhJmBD1I6Kq5iyCCMFkYkCtbyzV zq_fFLD9|`d=cHg#;@wb`=yKB_?ly|34mC=)YMqU{Vj*LcW|Zjf*l<_2Ck@du40qgk zeu69PH|;V}Un5xi{Db?qp%@M@6iE}GyJtBE6aHZ+j(ffvVN!4JM%VzrP*hCX_$9*~ z18$;RFi99Q#5FW~LgiAmdlb?l;E`C!%86;jiwrN-cza4Em&1y72rv|{?1n>srDJv0 z2L5FzBBUDGxTK!c|I1KhM|d6#csCRY0fwTGI{+L`Y$j{v$t~gQm2@@ktP0!+V)8E; zq(AIT_MLgt?>{x^?^pP_Q#@DFdSE`8zr}gc#KI-tA-t=5raf=GZJE?BePx!scOV_? zbM)i1i`Cbo@yZNzOBBn~KAW)xVcRFn^Nf!fXnsH~r$M`g3ai3CqKlQiZSyV(QFc%m zR}S&T_BM2pOrbW|(EODS;3-Z5HaqKb zO3@tR@|{Zm7)LfbV%8n7@j(TYkjI(|B!XZ`HLcJ20ISV8qo9k+2_Xqrt=otD@g{%^ zh-zk08JXl)EwG{bo*Haw;Zmr{#tO1*Y^@s1svNjSq+>^Np_3BH9y$8XATRhn&Q}@a zW4UX)8415SN+fmeLVi<)QoInrA{i+N;k`d)AMx5`UM~53+B&D{^5`{e53|BczFnGlvW9W7@d$kGt25qMdoq5i zdADY_|Ogm9D_#XTc1TR!@&|UFSsU497=s zU2A4(&8K)_OOq1jVJ+x2NR#_VEqb4~^spCLiK^>9G`k*ky}ngksP98dR!ad%7VqS2 zKk&b0*A<^?*#vT~ntB%0k3Z~O8=Oo&4@VT2>;Ep5pMiM=aVu zXh=KDn06lYlsxjCG{Yb@vgTyP&D$ybRVw36?rG-x+D{jBomjwRCHFn!9-|vbsBJCl z(mOw^-f5L1Ep&G^ZxQGvp&u49c{^sV;yPiJr;9wr7E5UcGTC9*sfC~Y4i z9y<2I_2SpxQ^@rKr7A{Se`A3i@N4jU)n%tB3&iIsgabgWguF7##pqXMe%b;_D&*6D zO9P~O2o9~y5iS}pwC;2TtC4Oc>hHpyV!|u1fBO}-#LyXXwPGWsVH<6yEg;Vy9CAMK zv<4l3P49o0VL0W9{nl`>6J9zW?r8jDaI&N)j%YHP>%99#Cw`}No09NtWl=|&rc1xA zQ3BVBb-bDZa3f#r((roIcAF!3AR1{MDsOUgI$%o5V{51kq=Y&MV*LDWE8?(XawrCH zQrp5@4z~<}e#paH^mEcCM0LbT+fA3(RDI^U^Qq;2hMU)7Yu45Ja~e_keSPjfT>|+> zvHWkd?Ee3ahWWRtdTBW9j#~~z|20IpaSuT=k02z51$nIqqU z&E}JF(fJa`$ap82k+!t8dBruKl36?{)=pGTz zvniOP5=k6@zBTvNnSfGMoiQ_7g*nlbG%Y!k7T>~Qak7HrP3lMc z*s#L|1iQVcj3xamtfZ^u$^op$fjBqmW2>P(A+kN=t#XcT_EsirDFLOpXekEg3q3yX zRilfDRD`~t=H-o;7^YleusPctbVzXGy?6U*ausg=1dxZ4-xu25BTdlyE*|rmd$f$G5M>zmFumVgfx0&_u%Br zwEc$g108Pofr-tRkwVYP6_`Ku7zTdj1eEys66C=#q%;M%GwXJ7@%jM+Z1Soph1Jqw zJY;g0R~RxnLdyOOE?jW4Z2m(aMZfzA2Jxh{b&ItdixcV2lhr&6Y7G9%N%^t7NP%A`9eR*Tk~rK507_|Z-@Kz*8>nv7eGI+b%1|L0f|Q^_^mq77vb z3Y@awp6)yzk>^i zc}w6n-BUqXTdpw{G;H0A8V^5jW!e6&$Bc7H4lI5oLc~I`&eQKI0qykRx{f+)A=0In!#b<-%5NvCW#hH;ytHEPQI z{mxDl3lG?XM3TC=q$|~Tfj@_{L17dv2u)u*XQ2*4NNu~68DX9bbz(PEvh{m8;U%h~ zn>aCtz&__VxvC<=IvY{)!9ALe8I>bN*gPh-H2oKxOE!K{jSTgJK+>1;d}@e;R~H;CF4?S zMn21LThZF%-B!Gl#XDL_&EezL$Z?>^8WLIX`;|^{`#HjV_}9Cw=rIMb6_Z*vkfXTw zEg}ncCJ=EjgJ0r(98du((?^KTu}&H`V=8MhcAWzJS;3|@lP#zAnV-xbrZYwIFK_{} zF65qL`rbi!PfT{~PEnPqcFf>;$E?Dek_#%LZ4^Qa}Hopr|uV#29U^(N^hj7gxn7l4xgN0k-!TVa#pd~A*U0~>G-!j1t zov)E|c-eah`CUbKtry$@%-3-4Zv3DwE1UmwNl*)}?EF8o75`Ne|Bq(+uNZ&OgCx(+ zdzBP`t=I{`$)|SxKYd@JX{P>6TH<^PoS8~(ADC(;F@0s4YTkNg6E^O0;D*nYqLN7v zL2qRuiKnJQMW1O1;jHdOSJXFs^u0lm*b{Jdj>X@Unehye6(=s9GcN$W^q$OSqa08m zGho;NG6e#(kdF{-$>VBr+b*#jyg!=;)z}(X!gM0*9JB;@6UTHEUIT|J4c1&B!sr$PZs6-d31EG{7u@QwrSiKS zyr$e-G!#%x=%$=BM&P?Qd;19G@A*LeTBP)a~NrUO89iC#pI$YH65E zlJU*rv>SlVCiwjmoz>~d*C|r%PXk6EHKda903rGLfp7&HZC0hWWS_QZ5k`;ix2-tm zY7u_lht26Z4Gv{gxP18fZYv6Cs>%6JPI8GTW3A4&Y(-_N-kwvQoB(FlNL>PkHad%p zYwIYRms@UKb)#k0hzz}=Qi~b;oZ_!{zfM#$_D`UCy%x-Qju;Q9e$5lVK{ua^^q*JH zLIT{`=M%l37bUvNPlyf@wwVlUML6N)f?%*N5~Y#Udp1SKgOluo2(r3G=wSP~Av#pC z*C2qnQ7wg3{}9q0K^!ibZ~QS@AnC9AXTGn zqD`*=d3J>njVF6oHh4USdEc^Y3C{eU)_OM;#o2DE8mwc4fXOi4VW|4SGl8#|jdFDd z^Nh}S+_dY0==(?c>VvY%ZVTRT{>$#Ocrvdpag)ymjyhKYM34d8SK&&A@@2JfcM%f2 z2X(kD9nL>&W}F5MM#j_6$sRfN9alyt)!%K!Y_9fhY3N|R8u)N6Cr)(ldPOo)i8~~D zgmCY-h|28|C(blnU=sq-P086oQr+`_At$p=>QSbZz!1XD6iVSh_b)m(Q-dAG@!(fl zxu%13U780y1S+(dkv`C~-FPqxg z(`&OuO_MQiZEn1)>tjZmS|*YlI84^Z%e0uwJU!t<0QT%E9Lhk|cMBd_VH5tm7=oBS zE~9Ati}oLzSql zdNmZ0mvPcn)eMK;RgoCQHRuN*tONU`@XGHIMLgutI$_kyc*Ti(*foMg7(go$ow)Ql z!xv0PY%oJKVh5UfHzp>ObVL5wsuLiEe!kbz0V;Z@gpnizzyRa;P@JpKs?e;2m6PZyJifpTz6Qgcc zjg%fF1_n$UN;vvXl1f6I-x{XEpVFStyY3~ZmoG{d*ekB<{+u>Acjo>4PaEj}&sO|j z=hFW?H|+f1vO2_nXLU3LZ2SJ#7Io>T$qSq#0+}Yyz5~S!99MG?{Sqpi_2WGd%93zX zky^hJr7DHrThz>1ft4J4T;i*Dff>~$sNk*yp$>+OHgp>)EHYz0lQDxzcO;=|KaGI> zM0h{Cn_0zD0>V0s*Ap|GxH0%A0@5_JSb^kJAM*$n^@C9Q zSGr32V7%w4NH!m<+Cn(<6s&_t`soyvKtL!pAnpkd!0?iVvmWr=b02t5IBo#GblWr9 zs2PABP=TiSffIm%l6KG`j=O62N~|raroEJqOcqL*=0%RhlCv!->+uTD^sD3-3#M($ z&8)OL8wqI^jCrpZ=M63_QfAHCMNsk=h6$6vR&RjJekMl)j||A~eemy{ysW3#`|vR= zcg}FT1_&s^J*qLyLI0k=tnSVUqt}TIbCKFMX5i4SB{Tk*4{t9n4~HZmR>Y;GRnc~} zbh5$ngdnWl!D$HZC`ObeTA&)m1CmI$EqQ6w=K=8yyh7H$6MBh^&p=Clb0=p~c4dPN zONwtsA^;Tn(4HTU#qK_eoMtK84^-u_cL4SFRN(^f`L0k3{>2S_7)J7dMok>3dcTVR zl~x=&P_Tx0G^C{vc&BbL zbg;WgLT)_M2zVj9JL{kgFt5R*Xj7_10clg?YqPY~dHMNu^}UDHFIl_OQXjN`Orfy0 z=^4L)pGtl8In{$97kcg=<}6y1SKRi9>rQ8p0*8eZdbRn&tG7eO5v3S}>Kj&mRhTlU z5fiz`xe=;MS;(&OqYWS6;%K+!(IiC3fhwkd;E58SI%d>I?e zbFqSQ)k27!Nn7Y4AXG*+cMry8ai-S? z4rgXD%?8r5tcn!Qy`n;o1wG07T+8JX9XCs+_S{yh$Lx6B)b`94d*I}8Zs7UBe1s_j zStW3~EAMy6IMG@11_Tr~C$b=ut7AsLE_~%*Db*M#hXqRXq@_1--4yAf0!b+|3|TfZ z!|4vWY1nn_$>uy!vk92?l^=D966mHFkS)4C+dh#PnbY#-ciM;#?_WyIF3XKKN?nJ} zaM>^(B&Ha;_q3*9URHmcukP=iV4qs&!c2|H7j+L*Y?2j-0h5xOWd^oRKe0a3_a{YuhEo5$HHCl5 zd9H5){Ol)q?bDD|i%m8YJSyI$sgP)vn-(#Wl(B}a*rW$H`PNt|;kIzEEbY>@FGlik zW@*ymb#R^O*u%?Xv;LEcxcqQX)5WVC^1`BeVixao>Xm0QuUTqY`9gPvMkkMtY@vjZ zIl3-&$X3*%yb9ir!+A-&RhYxP(22fshKHv^qgy+?C|?DbuHZ8Tef8={AgfbB5X+h> zQwPSg67~KBqjez`;4JZv43D(0@r5IRQu+63ML=Ku4~F*Nx7FH8zEUWF^X$UKuJ4%_ zRWtfuEjvNA9|A}qIYg<6tr6r=SlVlO^%&JpaQ>>4O{y(<(hKCiu`l`>rm(&(tPCzuCYxceO#j|_%^TxB!reoL%9=DHv%Q>ZK)>6J{niUz7yhX%>oHa@G1p+MU~i3 z=T-y(CFad$%ze0lm-u1vK`CfSe{K^X*cP%KKRX7YR*|0CgNNmWyFkhCTxP><3`n2= zcj?Aphx2bx^6H*|=zf|siIfG`zHK8wbiY+O=u4nzD19IlalqjMV{vyCC{g2c3Wco^ z5G9bDyA2yL0&xyExpj8n7a9zVINtl=@-yen&KP)Lj>9jY;%tY0;g{*JxS#<9g`XsH za*37FIM`DHeGp&`KoP)~k^^6G-hW%9psKi~0eq?xHTFMVd~kO^TQLqn{#M>tEl#3D zF0=KyB>X<;;~py4Zte@TaQ$TE?&U7Umtj)xn@Ccm>8V8Cv|*;{TGzAK5(ywfm^z<%9lMV(7=w7!H1I$tzc z0EfNO>#P`U+N~dl)8gr;39QVQ3fAvK)V({>JjbNMFu5qGXst0`u>8aw}3e3+|z>$BKjH-{Y~z3eJc__f6li(vECK z)0x_sT+bM8UPo*3T-y~?u2UvHf_1CWWJ@Kr;p*s+@Vn=&9N#_6QzEze$0ol!(3qdW zAE&giJ`I3Dyrha;gTJWr=^#^d(JE>E7)p?{=buW&_FZU-l)P(M;7K$WkKnvg7?++- znrzDGF&~NcWVtGbq6pR;EKC~Rj?O0b6n#|Rf%DX8kTy=Alw@A4r{2+6O_)`gGKhWw zKX7p2Y5*i?hll7m<+pV3sqMB19d_@%_pljJ$I$F75C zG$LQGrKYn~;^U#gb`IIJ9?k(v$z9LPfz4#I8xcX9*>=^tD^;i;{aDH)+@fsQ368~U zwM862$2ao2do)`K0d)OQ8jEvFCf7OyNnz}4eEeQ!jVX&eIeDvXjB7Gn3rt-p&uWtg zv~&Qh5%>mzxr2%Bcl05T{cUf`!T~>tpEi3l^_#@iGBu~)4|FW;R69*rSKxh}>>3G+|P~THyIEAYj2H@Gj&We^0Y^ZR8b8|27R&tYTnyu|~_K69q1PH;~{h6$`+6kLPo^=yo8Uh_f_P4A$tV%rS9U z=zQ7AXbHt$ri$;dV%5;zbOX4phavZnlT5zT6V6Jv0>V%%-odMtIRAIvk1 zKoMdvdH9}07xoEzYiJWCD}^cW>(`E`nWac44npu7yMjfI?4~golR9&ehVcyXbv|sI z+odpEw0A8`g}BM!Us_l!KnvT~6c80MOhvP_n+r@oQuPMpdo-ILV@BcXKuY1o2)%mV z`p!(GED88`ve|f*G0?OUk(U$AN{{K71sdWGAH>O=Y^kL?tq{3G5bM%*Q#Fas9wWBz zvb>%zc#1C-7#}~P-m1TAVb8q-RsYn&R5dZ#81T=<8YvVi*MDna6N_tZ@tWg{m3zyQ zOpohy^e1?JuQqHP9{@-JUI-Uxh&|MTE&`m=OG?RT)FO51P?eW^a=RCJEGSFBy3x0P zz>13~1F)nmz3EW4zvyFd_nmw>re|?h#PXzH5f3@8!Q`;nop{403;|l0cwSV-IR(DW zwXyE*h>e4gKW+PPGM)6M#Y(ZTq>^E(Y$I7vzIv^TGM(w{nW|mk%xo3bEUv%*&Zk*} z=Q_KaBs2R2ol3P@V(@FPwzD?1XT>&e4a2PFR7b3_+KyeS;^F{i()BE_5^1t0X0mFl z{;7DJksSc6xCMX}?eaPjJ%X*Xj-fM0xmMSIybyYTl|YKOJ{?4qm=)rFtc96{^0L{x z*8DO^^n{;2T>k>0EGlFMQ=ET?kAoc~$f#2XR3gf>@*$6?V7(=_tUX@u`4KsYbb-c_ zqfS6nY4!_q$3sxw&yx0Mm6kpC!wt_&>dAK=?8I%-WO9zXDBP3hM&8<_+@%cp*H3zO zb&uoz(sAzwCOg9@ig!#A{-2m4kl9oacjDlqdierk`P9+@83Kdt^;f075n$wP&+?uQ zA4*Ic_SEg@t=6)my%k6f#XHNZlq;3D)z?2(1UDb;otpqn^?#D}@mFR1_gysrQ~bA; zvApqzTGPKO;{#HBEwZDbZQr-LZG`2RxJZSke5X%m!I9CV(uWLWg%$ZwlqBk=EUcRK zPd%?^=EeH@6(3^fR5!h$?ih%*e3*nUj~FPfFlPAbhm{d!{Ti)Y7ujEsB$f= zoWdnnRLyK*3gPe6yyEkIDap{ecC0i$=;j?iRj z5j_lf%MNdS0ZgR9o=3nE9RCMGqmK2}Gq|8DqSH1#>@0QtD4l9aZQp>9QgZIl6 zD}nc6(%nkp;wFDD0C?Fl!->|+wc?tpoC08q&vvlVzcIy2wi`D6-q&dkEvbPdF|LSpZAXdFb6zjNSsf!!L@O z{#_iKdDo9KedZGYaLEly`K zYS+eM1%!_mM3o_+I%XX6lP&L*QO?2tbk$sPI<)HbAAex$q1n@Iw`ANHWE(cI9=N74 zoaoz-tUWok^n;I0YCt?3e5DTR|p$Z4j8J&&-2>v6h{%!a|o6t-W~#=F@uIB6;SFpl^uN z2z6@+u`O@+XBUz8>iC1rwQWu}+U=^JjaMwnPoMD)A9V!J60jDYs$Zi4p@|Sb1U2UPTo-sx$~OCp{{e zDzIgso+N`gvaGvfs#0*DR4|?qd}do_rgWkC5Mm2>#9dJ;$54s)aAlvj5G=ft%{Jli^vcfAJX}ro^UiND_4K7|LgcM{xp&9MLS5wz{6XoLU~+ zKZnRhn`Y#zB;GsDrp(Jr)F1~;9*`c^Mh==k#Dv`Nv&5T1!j)BpP9e#Np79@M`w=%1Lr5B$|TJF7eAWE@mgQUqh^_LEY0OaA^xrQNE_;g+Z9N|SJI zD$5b>O$ZRHP zeO~lYQl*kWrLcBV_QG^ypQto65tO(OT{XZxK!st=g|Odwr?qTv{&#hxtkZO_elz#| zV=wLqI>+cgo>c$c4QjfN;DA(VSGGUS79EacBj1DZR`@U1t;>J>aJzV9GgWAp+F&er zW?Mc*%#OBqSSo`4AU!`m-KaBG8%U>K1#T*oXeVO!o{X1w2}s6+1|;KI%MQ5RU%QIvTZvt1CR35I zcvTZB#pwR4S#wX^M52OR91Dv%MBMI-&YHi`3hz@g@#h)dU`MF}*bs3=i_e6aD5yB+ z2EJAdzCz{30b!oB6Bgd@`FNcd2i_a^8~5vrBqkR>iGheHfI=}K=Yaff55G*W*k*#C z>2S~LaaM)LuQ~@?MBJrkLDh?%amci6O9j*p>#b-mPqkI%GxRUY_N2^ba38;h-7B`>S0!tS4@| zNLVH>%P>fY8M`6i-l3FP+R9s+%G;`nM2)Q)*TjxGm$PtC$e$i(nhK?LA4AwNMz=wc zDmua;xf^(cm?75yL8=```X9exhnj@|V1_7TW?go`wg)IYRcMGnd84Fq7jahK<%QNa zzY3~r<9jGRcZjbZA|Z~Zm}KSU9E!u?uB)aE+p;Gob9xw$lZ1c?4A-#^!t(xlhtfKc zl=`w)#U|HD!>=TLTU1tQc4}25k!Al`hdxVrHy6_0=(M4X+Ut;0vMat15GOyTHi^0t zxI(9hpHFtT>>sZKaag|P(hM4H@Q|;FowV%Y@WwuW)!01@u{rh$`|NOoN3v}mPSZ-h zt>%UUAz;S_w|R0^cy)K8Fv~v8^3|}wX12sN|CyHcRwx&(evTyAV>_RQ{m>VvQ;iU} z{m3ARkg&r?hc2T;c5|o(hW*-V&MVLqJ^U1jjB~GX42|_=*j9N&U$&Wal5*WPs1gQi zH_*_LKE{kT;iSUX%pBz2TWB=YAmtxJn(tX@KAe65t|c)iYO$(N2FN6Ei%-BlMU zOL?FrZ^eP}aA1c!?hgq|5PG&qh`3l;<>Jnl@og z0$qvR78rddTLq920lT*Pv4?L%{P9TWj`7}#ZyPTmFHm(yFwiR2PU zzpmu|#eKOj3id-!l3f8Nkj+gBCtp`A!c(WOXUt_9$OejB*-pYg?4aPIpNB~RbC{B1 zBnz^mI;p)eRYt4o9Lm`OYE>p`@LG~mbAGJXH_Hs2WprCF+~?b!g@J>(5+dB@3*8Oh z$|Vnh#mnvb&D(_oM%Tt=vPOfLr~PMET8gL(r8Cdm7RM@I-`0&V%MA1*tG-5=lZru) zmJJ9C;F9@4Z|s$zc=$?s`NE@AuD0=;FR?=;I5_wOPp-_NizoOyQS0nB2w3G6v=B!G2^2QAM< zt80P`g*I7VgIP+dpcCW(;Im?q$tfpzEosh0iaLn8RR52+y9%lU+uBBrgy8N3cXxLJ z1cJLe!QI{6A-EIV-8HyFaF^gtaEE`9bocJvU!VQ${?DmX#lNB--ec*7b7qs$o=|=p9pO`qGan3hE0=mhH+TA!v3ujedvkcfeZwAb$rA~r zBLN14`;&D6e$pwt<`R)=k(OptlP=8eal}!wnDv~ZnzS(8gu?sA^W-a@iPP?+Q!hEt`k zY6yM>ZyyLhk(WNKQXek%jM7Y62%&0lK2jin_h!e9aGaE^(~)sYcbN1KEhNC6xmJ0x z(IMB_Cnk+(kR+DGDCA@#6cdCr7XRQV{oV`x5V$i9rj`u)TdiNE7R13ryj`FGu$>v}jE@R$ZDR+sF=U+F6! zi2+;nxBH33$&_x$*1o|*Ks_(UwUux8@4~jGFcb!0ioQ@PIRlRVO6FE|LKg``7r^W~ z%HCqJRu+45@z)_-*WDasub84pi^wacI6K8(P@3uDTUdT1(KEcd##Mrv&o*7u3Bi~q z!r?RF+~tws{GeO_HPeRXK$Hr5le&YwvnDr^{+MqPbcZ#G5Nnqdb)94onJmem-xvBW z@QE*vFa9mkH*N5s7u+k-T!GvVgUVzP5~A8Yx%h8`T8`vZm*R9tu%yx*(>Rmvk~Q>- z`f1N~5yxw$@q`~;d?}knADyj1;K0^JkxmZINvrGcM5n+yIg`IgJ6Z8A)l6I^hPji* zikqB6N%CHNRz8~M^H!tWkk(Y-mE0hlYuDLlSIumV*F$5blUyFV6gdPuK!@RYzRkF{Ue(Wo!V7|lz1KfwKAS4a(kV>gjYqXq&)?<8-8 ziC{`2$_1vRaqA@Nc6suooQ+&sNWg_q5P;A|H_lGAoCLa!&RygSgDKj$LA@lr{KZV*7D66YLhX{ZXXpkua>__B^b0Z2m`B zz6-Zrn3=geK%uQ9Ltn5JsoVi5wBPg$`d3n$SOPx>s`U|#DhKc+64j4Y*TgrNn{;x< zTQnmqFlJid&Z!h&E2;W%*Ux2?EZEpE6==)D*Bud}8|3Y}__`Cu8qdI8Y$2mzUV@<~ zH^|e;jL3s`Ju%U(K6eHX-a*K~PY%^{Xb^`v9ta@jMZ+pzTahewa52Or4>EbYRTP&n z4mI4ALX3Q~zV07I4s?Jh$%{Ui?mxwy&Y&sI;L%$CDa^d7*kllr#zqoa@AjE*_wxL? zaNFQ^PFjtIj>s3ztNG^ZxliidEI_wc&U`7ia^`T;PW4oxx-7QxvVN#Gcd4*_p<0Ny zd3MupM}`IG39dopDXEQg4Jb%!not8Wy^^(>(Ry}k0i0D#UrOOD89qiw8R$8pAs~3P zVr?DPAj^t71zHGND0UyVk6&t>AWbN7wybIV^*JLr43x${a~1!XqJP@F{@cY7z=`(1 z;`qNIFHM(Z^?*43@n;+_TVHn_b2?3CW~Di$_$-KGbrU>RK+b#e8KWt?x!T?=0lF05 zK82zaQ2Q~i~QnjMUA-;+iNVZ5KfifI8e{82ln^Q|i?a~Ut z_IeA(I~HC57wKJGmlw?-VN%c`JYaJ~>*3jp6OhN_{5<|g9ygOc!2f5iqV+#@6^s5i zS5YP}o0z6eQcx;=mO?1C|6bkvT1I6$}f(3e2o4tt%1ig<3-eQk!tvkr3TB=t$u+u>(IsY1uIZqgg8 z&BRDxwqXOSQKj!C##t&ZaQIx^SFQ4HKdoau1XNsiO7X+} z0L0BhJ%-W7Pwj%bpr2>C6zAC@P1+jgnIZ!~=7AW$T{h7Gm%3peB31%_(qJ5~xEiYf zWb$}5J(g2O7n9>v5&>u(gHt;>Q`yiNb}Y2s?$7zH;pxDPxuz+)nIC2=Zzprey%mFv zMJOWbeTD0E7+Mj&cKu`(KNM&yw-Woz57M;(SViJ1t>K@nBGzxL;!?^?<5gb1NzUz4 zvnkJ>$TMBEbS^Bghnx5ORI^QcYec5)wn0!pqljxsRfbofZ}DWnw{rjD_-BUg^dv@|PS?k-Pm4Sh%@DguN0?l3 z_h@5PTON3=>R&IYT}r&^ia&LNpKTHdKo-x#dC5q&R17&73C#(GepWx~2K2aiJ*?+o zr-^r6ptz&>?}D9c^N*qa2;ybT^l$7*HgXvzW7(WTx*UzuC*5H0n_#=RWPsrG;cIIC$&*wtgbQj5zl?TsrR&p$MsH}}nmqVJxT77&YLe`-jk5A`<7?Bu~gquC@DE^vpzCu zmP3Yd;`(%6I;a_5-vgKgX3N9loVTMD6a!91karltD9zzHKQU1oUDKPK@5aTM%}8sk z8>9p5h~pB7gaF(q_6NkPt4N$SoGcCc$gO?uP`*VSMt1wTrgiY-aYBZVvSst_&8K2s zij$!s)Hz{gR!uJ`97$K^${2NFa=lz#h4K#klY0S2Hg)Nx@}}5qGe%9P59N(1<#;TO zq&($mz&6X{?C6s@lOM)fDRFH(!L4>`@LevOSj-<>Xc6{VpFn|hByEwy=Q}CfA zO3mW993*Q98#aOUEEBS?x^VOxD@XOh^IJUe-Zy9n828e!!E>|-6UQ_Zj%+E1Y2&l2 ztab}_JtyLvm6Lys;M(6ki(ftS|K3&nV_g1k0o+3Z*$BHovz<49E3*Y^ig4}%;3|R} zg8gz8+ld=zn)tpZ0|GckNIuQL662I@nX+NS3bq%*Gd&=HQybc0+B{bEzG~*1?qN1` z49C&M$#ja*=3W>#8W9j$S##b-cUe#!Jwua;`#Ov8^t-m?N`&L~$gyUrvHK(#bBfp4c_b2+xXnS5F-sp2Qhee&^4ndO=#E=|NH zRAhpCc^9y(?K&XoVi2%z2T0%-fCLV$@@4)tfmbj~Uu+Fufb4CeW=+6%&uV8Q5gH?Wh@r;L4x92aQj_W;rmW<(M|eaH#a^O-fC^l83uSngxortrS_BuMJ2JVd$4I1GtKJ1nt@YSFr-* z`uWvWWc%eRe#nFGp3DNiuKyAH@geusRg~iBgCq46y1>5r7I3l~3?s5Kh#2a_V-dp99-ibu=~zmx84{*$)^% zsABD!dMSquS3uL^bMwKM?RlzoaKl5-j_UMxiZ~-p8q-F?>4Qc*N9NqsKEvSCsz7&0 zqf1!}ji|Bf&H!A+iRq}|S649^;3_TwTt&%0TtyqJ%2N7QSCJ6lD%QVHFQ!6|VOY&? z`dTomI!RHtWt8Gg%#-5O*S>W-qT@!7C3=QMdkS?e1Ve95S8_!&xFnDG!H83zErQLu zS3?{3y{Le_UhW~VIX|=g-p>v&(`9ZphDbTm1UWLA6T2zQiTFJ`u+BVJOn)#X{5n35@%OFu|-7h@NSN z;#t0#;ozml*{0&!3h{VP!l7Zke&-YL#q5-AmKzxi=gfJx&KB8u$=M;s*(mdDh%jKa zFm1JQx1j+;3wn`WAIA{I1Sft7vnZ{i(-vsxNhPnMIySTEB3Tey@@icmvTg?8 z3>>fc?E|MXqsmmudWyBW;#Kx3Xd8(`hIwWD}vd+>Zu4jP*HTRy3+-o4nWY#%^V?0~$=io%H_DRw7{S09VrtinYWzoASm zfKG@mB`$z6wBM1gomaFzwP#y!i=P2|+$4QDh9|pgK8LA}905o#uA1OxlQx-U zyV}MF`+53-{is0L*st9C&>>n4!I9T7Z!Vp>z13}2L1azF?!VB&CH42u*XP-S7-SpjYuYX@Md@9_!{%5k{ zpN8UpPS$_OiW_lPC)a4rCxi`7ZT3toCe>Z}G89#Kl?=jV&3L_|^NbqdkRK_+Jx6Gs z8lA+FrTjeD%! zaG%<(x~&@30?G8k@QnI&Mb7PE)fhg|#Bp#= zsPRu-5P@ZKVS}nS8Tp-WY*y+LyJdA{{L7Mi#P#X-d^)487wNdoP9Lvns^JTXwAhn; z1RaATnu^!RF+w(4q=^MFgHOe*$w435=zU?f)O7Gc!C_uMSt_e6@HSU_*z31U2LeY~ zerBuRwVbyBR&RQVL86j-JJP9w2rmSvyS{drc_N&JX$15t8BEF-dK)23NXaJE2cWWe z<+XYOfjUwLYl?I2#wc6|vSD@{mD)3lIM~C3LaE9!fuS@ynWq#^*@qMz?7~YAYa+9d zQb6Q9M}1*HC%Wq4`;mL?P~cU3$k6|8U+v&2RRIWZh&Vjf)w;ASwJunoXb&c@9f9Kc;i;6!2 zEQ^-1A<`>(A*^gBHOonvBOh?D@V#jm$(7b}BRxOPOSWrl=W2@K$@gZT^LAeRT;seQ zm!``%DtY`=$lup5S;SK6kmi_IVbOs*|8ToDNUvG^t1|@#Du^fW@$n8bj6+wYw&UU( zS+lo-^hxFW%v#HY{*>&I%@qDz0a@D41df#mJ_N`xfXn2};M@RjVAj<2e$2FUe`KjS zd(47_`h%ujeIxx5kkFoab&@BLAipV+Cru3kreTH>Rlsm;S3b^^;=S-0(NpT^*`Ekn z9z7L0Qi>~hN>ed&HdPJ|z`ukr( z*LW8_f5>*_$vnB-UITM3mNwOuyKdr)jykY34RhB4WJPTg4$jCaA9#Q}+eGS=WCM^D z&E9-f>3uMRS8uN$uFL+glZL$@-eK}_C)N=Z|Azp%U~8IN9 zESPfJ)Zm*c&3DDaqDqH?G%}M+pXiHG>kmIs@=m_5wGO@JX+uBWG8kEn0oC5;4G8M{ z$=!8+PWVk$y#EifqO9$xW#w;YFaO>8we|mx%3-63+)S~JnX!cJs?Jm(Lo z>MHJ-rePGR%NX`2>ts$!jYt@)4xC+#WbD;qy2%$+n(wZow_mO7DWN)N{;JWhp4pw$yN<{RA23S``4Hg82;mySD`c-oP`UzvuXJmTgth!P`u zo79J8{YLZyTfy$yVB5&DvM2Ie`H&da1a4uj|5Kh6T>7d~5#}C`IPs^r!$%~(e zf8mNm(H1^KGohB2^%c-}H1mBfiRL)tb|q zktJIdpBPT|A9FG?F>Z)zTQcd`IPuaX+ewIU_GkMV;){p)hax05d;3Ssb$U5?w?%b? zRiARaXpmB&G%w}fEKm&~5{2L8A?+odHGghSKrBKMh6SVMNuhh@J9sO|r&m}K3U6TLoo~-*!~Ro0nV5fDVi{KNL-FKOzN^>mw!Yljg2nZpw6fz!a2uHqDZrsHb-p4d4d&_2ED3ml#8al z?=Tg`<&TMa>WXuhc7a7{U@24x3T z9oOa(N;+KxH=|uU7ngp%Nh6mPfGa`?THKp_;@g6gs7+s1#TO}~lM@D``;?=@|124x zMyI2ORk%CnKX!_kGcZO|#bX#jwQnJ{C5Manf$r<-1VR(k9$$35C=LP7?1K4KnN58V zmFz37*g6+K3BVQiG9N55k3XJ1DB7heCJuGp;C=2+X}5i-dKb`_DAAvR_NY3(iN}iP z^#Fa_c)2wd3lDD9F|&9pbe;ex5Lx4e0}<87n;W{9MtT`PV&y#c2nn*RI%pmwiH#gJ13X5_VY&)^N~&)Plch`)grwX{zn zBi`^&0`bGB`2d=&F?r}GepD4?t*MVOb4i(f-l}I5j1cxJR{!K^(pCUz_1T2A4r|1X zDs`#8UYW8!aNmPaRUg_a0L-t-jhksqn~H#V-t6sH?^PkJJ)ZFP_kPDehegdCb1abr!T>pNl5juqjRzHrT z_F@bgeX!s$wY(*My@#&crLexK$5BWn}nX#6V#d=-#sMz0pbP z=U?7hOlf95ct()R)VeG#Nzo64gDE;BwKU?#)Z!Z^SJgj~nMAEPY0AIRTv;vzW2gnE z{lbe^a)@)ZFL~;DGa@J1pt)o|3g52mw4#4!5Z=b~a;_M){k9sie!VIUMkSQ>dJ*H{ zi_276(M8y@07vOpW1{d!9u$Qw-cO^pg|d+mLqYPk%Roe$?yRRH_t>ANlI=2>MDj_C zgsD8nrD+m_U8tVaLsVq5!I8N(INj`oWJ$BiR?qHwV7N_;%luPP<(?Bw8X z+t%o8L`{<}$M|l5V+$S~(daZhQtRiZRog`3FZ1pzrXW&!nzP@{u9 zk!rLFM4heiYS;4p0Yf23HsuN~A!O~JD96uwJSUu|k}o)_?`9#396#)G(lu2>-UM%@ zoV7Ws+Bzy|&_6fQHkK|f@rn?faz-UE@)4Rtx|i5Rh>q2cC0{ifxx)z;<4m;ihRJ7` zXyBl3_MJ?+@)ZBevk3m=53hd~@(uqK{YOb{0KUF!RDZ3^7W2Hh8_y5=G0*{}!`fu6|p!ltDr z&6+qBo%F+xzYi&3;x@Oe+Z8xi_CS1L3jJ_udKlXdZ(5*iDy`^)$4eN*@}yWlMkV|p z-Zxet{1SI_wmh_X>Is&qfbHtK_kDe|Vd+SkSR3AD==aqzH+#IS7$~OK6-$RG$9wR957Bx;`_}(#3H$dc`KJv1x9=GLEkpmsj#>HxU1a+MT`ViK{C9LwL*AoK zp+1ZwAv$89b}PIvp*{wyO%^Qe2zxt!KhHrSsRhutC!WXJ1%_W-JLnHs!agwP{keqw zUHs?L2Y&(XXKa+&!rTWnIpN=zumL^R*kAu1T@(~#a(PYC|2?{B{eO)vg1n-O{31if z4Q5f4LIcfB@RfXLLvcw4DfRd&2~B>pn#q!mOg)tz^z;$myA8iS9fG5&i%aYV>!)Do zqsbfU*y(;_Cw^GpSiMQ3U#2~MIsrUlym?&ReX@&E7G0@+2OP}|6z#{F1qOtYgAS+Q zu{DT9v4iLP;q9mP(y8y;!6WPHsEItY znSJx`?4-3WRVwhYb!u=AC%jpVjOZe&PSpoKUYrb0mjGh42TSG6xW0h!$p_;YK^EIj zLaXl*A7CpR(xnZtV&D5!U2mmk#6C=F%UrO!4ocJP4061C63@_(-D}Mx+~g6MKaE2B z8c5NJGsgla!j=>L+|K5VS3|Dr9Edk3}^e)Guf^QR||a~E>7j@j0zq2 zM(pDWUFx8GkeLoKd5|!mis(by`Dzw6H-6AkQ*t3y%miF@BIv9(=&QLXu0n}3SNBk* z<5<4I2JfaHt_jgYCUkDz26l}bT>f#UMDA*|GAj0gTC0EbVu@OL3RTpIvGE~QL+Au{ zi0AV%8)eW0qX2WyuyM-~y4Nb&X|?k5v`UPv81ov^=v=QPMN#db<#o0Sg@@<62G%R7 zUB;|kyXj*T2jh*24C_nWviVxEFR-c`g}rIGh&$%f*_oWgXp&olQ+L^R+%6duoTIUB z#8Y*Bao?gx*vYcDnKRGx#Br(8wAs>Yndv=2_!wXs`Q zPd8& zyP#>t7o|t$>X-HU@KbjW4JpGQz zEGLcY;RZ-rkRKwyp2S4k0DtQsatK+pyi}vhrz#Jx($w$~>ke}=0&{x5`vL2Vm#KQu zam9(#aDnnrRHFAOA2XcEDs5GR=D@LY*Yq|1uC&|fOQUUv%R_&W8z1*Wc+KdX{V~`s z74nE1*YaKzG=7Af#wJ7*=!;`xeM$*X;bgxrNlT+Vx2{x@{pyxX-L^1oM&t#nPLHr` zkh5khLwydB#l;suJ(2OhH10i8Kn4H)yqg*b8%W>E($T=y&IC}0 zOlNOkXRrP17xus1#%bHy|2`G}mlXZ)=Aum1S6OwPKzMcTXVF)4(Jz8TvvdqzBGH=U zoocxH;(5d0n2YFjc!sm({tCp%4WCrQRmC9oU@S-9Yy>6WwKu>7x;8zujX$*hEcZV> zJKJx81M!xH1PO@ND-@?HHj7xfQ+nTw^BKh4FKU*=-OFLSY~tUO1^W_qlh z0tq!z6lVl;bY*JL#IoF*xD%KP=)-gh68~x5RWDZfX4J&Rdo>IS9YG`E9vdzo<_(rv zjId*o{!0TEbUla!efiM5X*}s9JqErN4QSUZkaq=F+|l9gU-`YBRcSCvINm3Mi@fSE z28r3(%LV+(a;C|Fe(BcMqMm%jd}gQ3k8fQ-WV%6)#Jhmu^z3j)}*T&PM;k>w}YE6WshCjB|;Tchb!sn}9FT-VyK!?FK$ zI12R)sXM>V>VldLe?yO%b3f%7_mwHw_=!2+BBvNlZVDRo7rAHw`)}l;eo+6k$M59g z=R*2l=8R4KNaqZ_>rzQbuHBBkY%?6_OXNq25SIiaEO;@-t)Ca*rkb8zF<=J~ z1x^^d3gu6r2ET0D=EiD9FNc&m#wEiqdO~B3`sWK+mFZfUMd@}f%Uzvn?Tn$+V1*Ze zP4%KtVYAa(e5@;!qrtI`jt4K}tv?^qIvkZ?nH=$cIbiQSq!p(7EFR5}6tz^7JJmI@+ zGzf4F5fhHK)V#SV;zm#;cA-fUIi{5D2VKVOMVZ%Z^X_I9W;uue#|z8o#7?F?Oax8n zx60*Wv|eYz7o!$kim0bQ%9=_aKo)zB{ADm7rFJu-H6YWewy&svl!Yp=d~tI?32xew zMjq)AMjL532nd>LI2%{iLZx@seXEi8DS>3|PB4+nY(gz+C7HZ`ZK@8!s8z`QN9N+M zx%j8t{I@;T|1mfJjk!p6P{Q9XSu^u?UpLdR#UbO%^dIIT5flvvk!dcITuwu=FTh-! zd^H#2+rZwBHROgz@hh0ALqu2;>}zm5xACHVM1?}IyIzOkFF5(kjgnB92Y9-u$Q*)h zMgJp*GvLvS`F#>bS0^ur+g~2J&wUM<{b%N)^?z$FdYL0DVtYMRX*J+FDJy;GFW-&? zUce)2f+bEr9I0dD|D3J(yfEE!*b@-Vf3I)P7rxa@)k4dB*7H<#8)V{>^!(*hXlI{} z@tgrGvQ037(BPz@c_`sD2f8Hw?J8o@=Jv{N`{@Jk8sMH1aQdtTXyM%e>ahn>3B&~8 z2BkspXlCwf^2{e}vSk(p4mR%U@lC5H+%rV7ZkMZ5XjW;abxkAJzs$wbS94LBr1h7% zX!b925for9iX&n0#8s&USzjWWr`qY2`oj3(Acxj^0`o0iNAO%ki3<{I7nei>3UDd`UaNWom8mjUQQ*hKQN2IOihEU zrP0yRpllk-&oJ||@@!xE4|1QGd81qf$xs1o{}gAH_e0WWg`$B9xtP~PjPH+g`gK8G z1Vy=|2o@<#O$BJ$04vhmNJ4_;HF@F%IB*O$_sA7Wlh{{|Hy_K4<(L!$On0&S56gI2 zRNFk(YGrRtJz{ZTy6(N8cHb=GAGis-Tj@;cdBC$Ryhjg=VmIU-Q#ZLcblJ@9cR|$) zr*%yu0~tdSmoC^x_nBoDEKT_MP2f#S6an18&stO+O3?b5N**bP80dPI;r&F z%5@BX`im1^l>#A}ZI3~y3KUYJ3t&Z>R)N~}_${qDCf{lohl!ydGND~F zU)p(Z(A)0M=Av-XL-N0wi%jwoQ(+9d5Lc4XNW@Anvv4oWDB%-!Cc6qF49M1zNoQdj zh#bU}EiDFCB%}Cs_%=(WpAQ9TgPp(wg&V{DH)f zNfar`z3?%TyAYjA8KN=bhJC|w@C~FvVB;ZKWC#l~>hOZtsLSd(hoW6V19n{L+>+gU z_4@Uc=y&B9%e$YPSZ5hXTPh&NwLdR;%;2eesgP(){>cBPMBO;v$%)q2Bk5BCd&1Df zV`4n+%2^I!QM^oV=&Xwtz`X;o!!XUH4OlWeIBb2$A_d^3SBnsC$hXoe5X8v^^?V2u zo``E-HtG$o+pC)SBOCd|6%=Zt^FBk~Cn|1uLQYgKF4T3^v`kS?$Qv}zDry#&&`lmb?~TP=7HnH;zkn-9`V z_s8F!7Uv-Nb0~02SNc7A-dPmStdB-o)^&`KoI_>+v%h^&1>L$jcXn5H%2;?c7yH}i z0OlfL`>VNF``7P|H%0HX{+YS>$ISfCp&Ibm`>!)Iui^KZdHlc6OdN&>&_NWxh|W^Y z)CCD41i|2xywQ0S;X*sw6#gG=MD%^bEw5W09_^VA?Kd7bt?rH)oxm8gKss2CK!6)N zBKJy_sfUd0XKx=N5NU$k^ehAmSjD=m6fFoHT{y^Wf~AGUJlXM}Xm-1?5+xS#wiOSt zvefzaK9mZ-#6^n11Dpq=t4HN`sdYLC89vhAv84~+SX6kQLYu1=pXwT^?LYpIT}pcu z7u!`=xi_n{eK2yua32P}+j_p$n7H)GR7H(;jSdIU_bT(@<$mGfH9$IvS?^Twhgi^ghCc!cRT)Gy*Gl!~h zUXDkyi?YU>oRe#LD4I3)5|pVzix{S=mqM7}*TXFG3_j5NN-nC7A(6%~P*?WBtI4rV zUY4a<&>C_Lerp)I{0Ps3Tsa=k_R?ogQ^bMJ8LJ)FoH_WqQzMePUEJD|rk0Oq1UjZcNc3B%wob8*CO%^eud-ZB8j=Wxu^o5P!R;EgS4cA~alRGzT+& zLYpIsK4f1ZJQcH^e&#+&rRN8#@`>A@4)|P}oCc}Iy29hF5~1WxwIU^KS!>RK6R`u1 z4AC1aa-{Y{YfVt?zUhO>2L>+J62G**Qk$x;^OUhytzL)g8-RhiH7uj|s^0PofQ>ALiP)fn=7 z=>9wCeCc1IyYM&YoO3w!FVMN%v=()G3jjKY7!?OdfzwbW0bM$uV98uX;wStnf0>Ji zqL?c^_@;3bP4C%buIsU0JnP(;lTXb%H?*()c+l=ll?y+^UL0}}m^5W|0 z4?0HyFfqPe=KHQUJ<^>V^uT^d;e?=)+M+Q!FK@6BbWt$H`<73PE&rB=DZ_uIVSE9a z*wB)*6hIT3g?ZhZ?h+Z#0eKDxcFgFl#i1_zO%qc=kPfK7r_Hwhn0veTo4M%Wj`3

    <%HvBXfBj3H6i*?&HZ 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≫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ÃG^|BDC=vedVVqz(`%Ht_^+nOx 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πALeI#p(q?t-eOW? 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

    qI3$GTs@=K?5-aMHD}yJk^RQz){93 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

    N`(^QHT{FFOgt-<= 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

    pF$Zl9n=>HYQ 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

    nqm)-1ADJ&L}J|MX+e-*MwjVW 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 z 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%0D+D6CS4wuURZ(qN^_9U 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


    ^KrXX9wgaUxl1fS}K6?Iabof(sdYDCKQQ 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�TD|MRx;bOq(zCW?b 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 z5_o041``%0D`iwjhtnS`N>NNpyIoaF0+RDlGhyN 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� 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 z zHNRb`0N(Fl3C@|JLgu7|`lPb1j9R_3l&2(s2C8cw{{F^mtH4h;vIK6Do0y~w8ZcuU z)L6L{M^G6WK}J(+BK)klfM8=?e9-65dB(p;`J%zPxn+k7$oBcA3Y>27>2y>_X2NJ0VO`d^{HXNZBNwOAV9Vt) z_u+hLG$b$ZJXuAOr>=2RviFtZNM6b`J1B&IMDxYC;ppuZ7u zw;_MzK(tX2VmU&Cy&e|qcT`u7C*~aBjz)>$cq5c{mbzRTtD1$_e#CCB@(Ws;VZR_G zhGS;D(kZ&!DUYyQld`jS)RwtWo$E0)=g6Pzv_jTo0%Z%-5&8JbavJo?w!v}6b*Gkr zbodF);;T+yB{9Fl4^x&OObraFEnmBzJww^>n+8ae5;oZPE71BNx8v^j?MK*$SBY`d z8!=q2-FvAqxY{7yIe%Y+boS}*3;FBze`sLmW|_!c_DQZtf9VE51D&(zp;}@ZGf*Fw zz&+T4Ep`S!H1HA%Ye8Q9q(N_N@AKeye>ShH*kx!YubWd!23F47@WkNvzhH9>kTK z8IO??)u|b$+Y|&ZypP=V=i`&EF;O^&r~S5=1_BZ1s6OI=Hg%b~km8Qm&OW507O8EC zNEJ(d<9uaBInWQEGT0?I7q!F9ZbB}8r0C*Wmwe&S0;%eGFE`IA!M~1xCET9G|A|le z|B2)M+dkz9wgp2AA~+t-fAT5wePO1kAoHM9FD%?m1jO;e4@8{RkWHk>f=B%+3mno> z?y!s!e_v?%Fk^aq2KJ^+Vgs@9r=lX6fdPEV2Y>S^cl`hRlp}9X$cq6&|LZT>CjQNy zW)r|MP)ikX3~c7x@No5n(Q%DkYu9Z{rSDb1C?P^LiIhYPZif z{hV>XexG5~NT%k7?C0|dXedwnnuW}r{GGj4-Z-#fEFjc_@(7SVA(VDf z%;59p@MEfrYe$aqRAX@v4jaCU%Dw{}=#4S4-Yi2)PVk78T z#QgbJiQki+MVwO~sJxZ;tw?cbqu{0JDTh2ebPp-BuN2jmF3rYCV z{KU4W5gW`qU`&0(`T@&xH5R?34z z#J_|a-$5c*=rLA=DNbht01F5y9vUH48Sa}bo8CUU;g!Pmu7vOH{){72S}pZ*^yBr8 z_IJ4X84De(scy=4;WI{opzpA)f0&bRFv0a?+&G9I(Cm6_vgDTJ*N#TYq$y}ut9F+b z(sUbFg96c6o-GA#SCfXJ!?0cK`k_dHEdM6!Ld`T&L=sNJ_vbuP#x4)yE-q>Ct zD;@x(oMe6wjrn-^7}o&HGR0QGBCu=Asf$@PE?GO@hheK1!jV`!1aQqoTJ#&j9NrH;EL`B9q_4eYg6 zmi4`9b>y#-0h2lX*R@jF`Z0q%c0e#MJC05*V&w>B?g@zsMK)1XSzafR zF*SzCicL(12HA$FG#%zB2@hfEV7Ce}bi^7@^H*KGj?|f8V8VADp^dSKjA6p~c3!pHYW-F&JlR@uHbf)zB=Rxssq=K#%UsFx zmD{i@;8`0Xjw8CRUFJ{5PqpB6H1;}4OS#`G$nOc?A*!_`j}Rv#&Ivjo7Y{tYAnBVq zo=`;=AgMBBL}`M~?0@g9#dp9fc`GPw2R>r7_^l+l5y|N}MoKdSFLdvvGjoIE-H-hZ# zZEKaK(Rxx=Kd_>~{Iy2xb!zlkVkGpY;bD`Q7VUv@%c~t02y@p!eUxc_-&6=i zRl0J%A2LNHE zf6m(H-RHaKyXVX}M9Tu|DF*s1UPGg|T8*s$dK`ZW>LCIT9 zjFR>cPq1WUKRlS)fU|DIYd6{Cy%q~8*#@)=%c=ixq;sES*Aj`#iHGIlRwBlNslot7 zf~uHbuO7Ppvl}YnYnzi22d;Io8+x@e6B3l9FmnSr34?Ax7s||j@|0VF*(sl1huj^g zutK1)B&Sut@|T%6v0i;Bfmh~3d7+ntZ~c;-gnfj}F*KiTk>S(y5wS)#N^6=Novil{ z_T)-sQSiN`HrKga=Yvp|vz`g4T1id%a3jdE?|jQ zEuiO{Y76$L3ORssmV&@*X&Ugjb15?sm|QIS6w55rxSg-GOKozwq0Q}HTfh`m_u_Wi z;qkLodAg~ZDFuN(%8yd6>y%XPLI(sn__P*DjE_^-M<7o+GPUHGq`!M>@Bl2KDXI02 zW*gdBW~Ry$?r9^KI!p7mlDb$=v~~~Yj`$kbA`;S|=u|N=o8gjzc)0uq>0=tj8IvO3 z#D>M5EF2@M@do+n9eN8GGC_LbPr-G$%d$rd5LR*WL4q2$AR8nnT|{2xFM9CDFaBO( zT;q=SZl;g(no2rcwze^onzFvbR;;${fZT^&;#^byr_f^vbPkHvz z%9*#_S4fZ{;!7U9^m={XuRWF%s}vpd?339^9o1r^dyR%(6OQ_Xl>jIWp8CM`21VKv z9<}9Xxt6+Q4tyAOUGTl~u9)3hiGy`~+0VX^06(A^Eu!}wk-!bv7|+Dc8kp}V3dO>L z&%wLb62X0uD}*;%InhD=SrUvy?y?sp;65n>%1xa9BCX@R@js{bv(nQMSjH)l_t0TZ zn4<&g!SCp&Vp8{0Z&8C!*zRfihLxwSVl*Uc-Lph-TGLkowvTz+;|!1{gU*S(AjTDZ zMKBCap=GiaXT!=cCI|6|FfaOh0ShY#SYL(Renj^`JG&KFPoBY>Pie?>O5W0o-1}CM z<(jcWeip}33uz5#UQ140_O=>JHwyEao5R2R1YB3~>CjjCPt|F=UUrsTmTqpz2Y2(i zxMJUq+ta5xoEw|HeN(&}FN-Z2kMoD>T;=)1glr1bL(l0OJK^7@Ie!v;EPWT0?X_DB zm2q}VsD~HK>0Z+i#|Nxf2??K&R6~}`Nb({nSc+VBX^xr=ZNEN_ri-+PIA=BZ{wckD z&H1qT(eC_LJrI8r#s6#X`_HX+D!dZa+sPrcjsMl~{0E+*fx~lsWf*og-gz&OOghk> z3H!RE20Kw)?YImx2@TTXC&g?zPP={O4GVctN|~fhLVOOu3Cm z80_w`%D4M{&?6bp$?neQKb1PcIZ@4){cY#*S7hJ$-)ngWK?&MIC84b_G3T{J7AZ0Bo0YH|C!LN}KlY$h^Ctp{Na}V;68&B>s?LHB1UPe7&(E|je$z|SS3J#c5@JLs2>L~ zm077r$I_0O34F+P604Q9t#?MASm&J^N5$1F%T!l~CZwbf$5TO+nXkEn_gSixXp6>d z(xK!qP2&ORAxmI|Ts1r(Xp+*A7)j12+{F1jYf36C2Rh=Yx##yvS~ZiI)Bdpa?KOTd zz<*`VsKpiJ0>2(gDFg6E80In2rJ-tIoGQ5aTzOeDbz?I>9q{J%-LX57o&d5CnX94S zjwjgL3)qjPZ@0JC>bS!v71g={nSOTlDKsI@^C`x(lpK;1lah_fey@TuWu?8FgnJDJ zHURrWC>47JMaV5SBL_2j0?u$J;AtN&bg>xq{JhD>@47??ZpV2am=F_}M-~-GWsgBY zMWA0CX$KuwG)^5$Ci8m34E+m=c-2HH56@6)G8TIJ6JxRRncE`5qf?GY`6`yu-=&;%YW2xNCKtO?qIANSx zN!Q*FLq2M&&oSN0+bPL<5547j7fL8d%&St9tJf92T3hp++8A4?pR&1sCHOyJARbHJ zqR_-5=B62msg=KSj0J=fS<)%7a;UJ5D17~7IU^yv=Ij`%?8{WVQ(Ch`yF|WINzo^F zu6)^P;^m=25U!RyUyIntRDeU|i!8x1?6%3r(`A*PB%}ekJ>EdtC4;dMtw7_V+UIg< zH=52rR7zzY|1A&*owoapN35jOe4oy8?tE^M_&nqF1;pjbt4 z{R3jRaVtcZRWHOHCV7Ibw&aa{_3VoPBoMP0yFEM0po!JfjiR*iKjFn{r< z8;o!C(eN&tfsw3s6ldde#^V8|dJkpvfUuR;mZmoL3eqn%+z&6@7J4Mq7#xiZW{BB{ zY3N>qG|MzRMoU^?G*B&-6xU2*pd@H*stA4FN_^;*!q~9YLYA`qg3Pz0nUSNHJxe`S z{p}imp9;_QP+OpFq))D#Ztxt3MI@s4LMo8yS$Xa-`@fx;9CbeH2D4_ock8&{=-vl^ zXW{v-?$|p`u#=BP!0Y>tFl}r5rR>f}_KVF)C-E8U?%UPgnYgCh+HUzO&!NX0FI{~G zWKY!1RRM>L0c~)^aQK5V9th9a+Alnl_|h3ENu#~3&*8; z8xP$KquXkUVT(mPhY(GqxIj%!MCVB~5e#H1vw+$D-7ehmVHa)}Zk<#H%1{B$L2$?c z1FFG#w`+M*)>5n28)r?QF7I2oQ_^XabiAuEHfN~KURoPYH5D$OYU%D+S*fY!9a@sd zPbjh6Tmq_priPavpcp6xNdkM01Uj&*j0TB}oJ}Z&isJ46$v()ZO&GKq5=w##l$f%l z-CP~PH+$A{BU z6(qw#b}4Vhc{6b?LqWcAoraEjV@B3BE8azqo{Q}I!NWU+jz*9jGAi>hOs&!5OL|A6 zb3Wz5Y%m;L<9ave=ta$fW6b#?Gxqu5-3%{Oy8ya5Jbj=vYy+1=QCWUkYo3%kyq*e0 zJDLj$E@9p*2ULaLbo=R29wci!=?Z#;W~ViqGO!NXk}va=t{!f!D)V|$OlQ^A9^%hC z`HbtmG-)%PnC!RGw4NpR(c>+Qf<`)645dvru-mVIwR2i=_sa}p1rHSe++bqgH#I{^ z|1q%7Nz6aIxG7cJ?CB(Z2CDApkp8*!`}s&FV%psX^VNLs~OvZx}=NSWa)=VrIeWa1ub zMCFQe1xEjB@x!-I$@IOt3$oPigv^s_<_TBU6q3)D5xPotK=94mNY@f+1_85yHdiNMBSCIaSH7lG$RZZK zELE}D1kYO08Ry4^!}QN7YMaJ$%>{Hqf9VZhTH)XkaZUP;@&gw%Av|t+ zd@N68kCt1>UMf!pL4XH~E~F^Imfiq?5%n@yudSIe@Cmx}FsleuVS5PB&S7Nusu|Xc z|2z-L>Jz%;@h)JiXohY6X41y-uP+0NB8i1)z{}tR&G}dEg3kYzN7!0LM}|ZdwF>~B z6e^ylT4=1X&Qwx!Uk>&sE0QRmPx?&(EP4;_grX?~mG)Wc(OQxs(}V+JzDW!QHYg0WLK@mKy6Hf5eVG5SMcAhR zfBx=P_`S}m$T?($CIgmu8CDG3*+z$w76IbeJRZpj1)hBZ5jZun5&}BkDyz0sOaw;$ zZ01Li{#hG=q+bVBbo4pWgL<*PFUbkPF9D~_dbIn^B5uFAaUoYQ7ZyaE@wsBwo2QEd z#1em~0g|1Q@E-aPe48vo;6LzfCWm*Ai>KG+!TW{qSRGFpfGWDXnEp>0gSs)u%u29( z`V%4T-d`TMTsRYSKz=xJ=ra#Z$a^Y+ybFmO7c!l~vRGEhc<2DNaRJ&+tqL0z6SxSY zW{UMznb)w3gVTaOXcns6Fz4Am2@~pzpSDht%Q2vyGuI87E^=59MZdbx&GIk*z_0S~ zwc_b6oESn5?L}}3S9@hpJk5{9Aoy~Nfb`TTS^k!!oXu>Gk+-^rJs8&ZR{qf5q2>2F zSaV)Yl-%P=vT&g@*kP7n3xBDLb@FxBFf=TsGlLc@y(X%0%3Ii)X>0?+l7jB1enNNg zZ^&=V8=pt}H?fxq{C~swSDa7Aiij#1Nr6vJCl=+i z;L8WOX!W$@E=jMOVUB@Ym`3|mp6%*#)9}Fl(gyM;Z2&&X&y#JP(~kC79q5$)PnS6^ zv!%Y<38fN>pK_^awQyd9YJV+N^2iP5L(}4`R!kixu{$+e3~H8pb#&w1E%o>VAJ7eb zufbjp7*Kq8(tj>oETR9sL>D$v1}B=RTnjPcQod@cpq_f?=RhNBJybe%IFGII8?HA0 zDn8c0B~5LpHXhfh4W*4A z+tC#vEXTRmc0#2p{Y0B>R^bqy&m9}A%rC3l&gx=QRO+2U)F`S92`6RzKB^n4vcXFe zQ+StD+TaJXA}<;H{yFDPDTO_eE4*b|JN~iZ8fTTgaRj+8{aa|wBqSebjb}snI>eYj zOha^=*y;_!o)bd;Dmy!kFo4V%=OX>ZP!L;ZLb5txZjM*@)vD|ST=mr|+M@85Gnr4b z^hK*vlOtZ$(d)XlVb^?%gSgAKp*e)0`|^51)O4CcyqXY?Vy->#8N;A6tQz$!+mZxG z%wi@{eKN{1P*XwDs&Y)1>1n>$T59| zo~F@n-6^3zgi+>L^5C#NPUVG zkWoB$(1&#Fe?=32YU~%Js`{X}4gE8_lI|bu${(x$!md1t8mNYV_6sKlG8XnAgaAU# zLx70LUQ-eYNGPpnBZgL_xEe9UyR<0JE=5|a9yuW@QZgZ4gac1pG`R);*2{U{l}*j= zHm)D0(j+HF(fUXm2L@*eByp203S?ju;ssz=@-65}bAoF87rXMOUUOZ-#8NXHifADU z5g1KwN)ELZthjNm0*MjRH=Djuu^W+?hI;4EHl+JEF2766-$t=V2S>I;(;Nce0UaDR zuuqTpz-fRE4hjQb7J&RQv^`>2KTh5s$mLvc8OWpF*(2ge&lSVoJldb59{5uZ@a><3 z3q_+m#rOx&-iR4A<9~b;NBa>qRfU(i!A0GeKU_aO$|G*%%9+t)a3ZZFB=7-Sb9#F`8N7QrdXj{9@hKnK5T2=VI{n@knYGC2F2ZI&I| z)Ag&e2_RtWUMR3)g6|bM#L#GPzDv9vJ6{Lx#P@yRE6s?4_HeQL=-x(T7u}`sF`Cm( zXk&4ozO?Jlzar1`j&yho7qy2o<^VWe$=YoVf-D5{+G_Jyi!0SA1Q)u0;48a>HvYg@ zdX7EzGIfznJWDJuO$^5Gwd9ADwWKxZSf{@R=`PZ+rybl@(B`Z2PK`Bzi#CNOiF)1E z2tb#oeRCK1k|*gXWhe_SrLb^MFWY{w24J!qpaM)`-q0mlvf1FWf0)8D1nbe~wV@B1 zMB2dBIr}qTJ9XJNwcsH)I+jM8W9()Inp@mmA<+V9B*@6h2p0;A zo`v;B_d!>Kr$8@LaKndp$Lm)IBkq`ms~bm$o_X|r`EW7)x*W8j%7gd-o-hI2BhDt= z`6AF&a3t0A*rm4Jd*DR_L z-7541$Ts^I{`u624Kg|2l2P2!+CL>}^93D645QX6!lS5(+`Lq-?vUYE_P=0XQzTZd z^aDI$VX9GQLilo*tkSlO%dK&R&2~XI)WWtLR57mRY>rs6?NY{YJTke)182bibdTqRa3$~{fyAnOcHT)FPyK2;lPphq zGQbm7NfpdSTuTf$-EEtk5Q~mAHBlhnoyW^EZ`8Kbq&{-CS^lQgxXziW-tD>-+hFMW z#z9UnM&L^>gsp z0^^07@5ww1X%K0?TJ?Wgb3av7mVDIDeW?6jS_1!j&fkx1#~*%(!h50d*5;WSW}9|T zNR}7BlfELV`~e?7t4~u$Z+=6|as$Snq_x;Fbp~KgU8L3ao$nyS!!4ZYUl@I+3I$l# zm4v9{T8)DUH6&;V*0$M?^h*RLc#A3ZIQIGX`2d7s$4$p6&!`QeX?sneDQch@*g8T4 zK=Fo;Va_(FmXx!I?9!s15?JH&)hKiPQJ=lP%~ZYK+;V_Z=B5mG6zUH)Rebt{mat28 zFl(&+a#E#&vj+*M0q$7QxL+Z_K*)<}fDoMdA0as9o6}ewfYMXKg>Vj3O=~qL)9Uj~ zl}g>|!V#w+43T=i38N> z00!OAXRwM6e;xX$oV2cmcNC#qzyI5PL#SkY`Ft()f)<~@1|Q>hiS*P2>tZ3 znZ~P>@%`ZgKLd!t9eQ~M6&YBkR;fZ`@Xj;mI>?}_|MurkfXpV$4p4Nz+PpK@>S#Yt z!sA#wrj8Gwh=^yO&%|VjUtu$4*%0CEDX=Q?X{MTFLSfqL05-i5?@rP~^G2T461{nG zo+1g|fP%|wmO24oqM<^4;tnk8hvMPv#XFnsq~=@-NiONMjZ4Ml9tg`vYZf*tOjYyh zQ|*$ueO>#8Em|o16|wp6dK77HIdahJ z(*!b9#DcK>c?4|Xy}#gPMlr#B+S&E1%{D@3mg$bfa!e;@X+N{~oNKMYNTb)4Z$5|O z=}t!VEE{+!AWLLbuP?={XVvGHf2W*<_s8+7H+B0lI57~$K47Ln%Ri2NPMX5Sk!p|E z8GDA}$-7M@coG@*(LV}Yttzs;{;QZRS8j^4oN;mhbEPob@vvA&v`%4l;PCY97c^iE zJkSqmaXW;q{^0%Vdz48-4{Jv9mLwqaVau#7Q(g@W@bNvEv|VtQhhBbPdh`-LMUavv zok3J%A3#B0v8P0%%(h=Bj!P;x-;YOHvax|73I>gg^)nd*6w&22{z|iH6LeV^j^C>W z`Q1%Qhh*Ztu9mGvEZ5I%MvaB!;&?=NsX!yw5;MeCj;t*w>;y*P-ZDY_&13Wvi`vnr zI`^Y5o1vE!=`b17eZhWh3_G}-soyndoCU(Q7ixQj5`sAioJ;sWLr=H`9WKyd3&T4y zVl}~t{KU%hTrSrESrEpqg1+$kVS_D=X*&c6eE^bh3G!4p%29tL;oROm+oe`~+kR3J z=+Sj6fcSXm@f1LjrNRH)wDqZNJ-qYTnGNWUD%1SQSK|4`bM1K+y({3`rC2|I`=lj5 zt92sgQTPC-yi#`A*mrJT0O(qBo>89b^R-evB;hXP<5#h83q>FkQUjeqK9HkEs-7={ z!?%*JnJlR+(K+{&ogB0^Pv`rx|9<|b+=rr;8tq33-3Pz;Ka$4(eFFaP``AYs4l+EY z#>EA+^a03($il=h{|T5Z7LbM`FjrlaQ>GRLSs~xrYC8OuS)sV@6#oQTs%X;8x=nJ# zA_^$5#|DJ^6U3y@6j1?jIOGN1^}w0Cd?_;-X~Oaq7T3KjE=RMyDb9>5kYey(I^aNQ zMChnMKrT7im=(OX^5yX5hfhH;VKFYYL>e|qnS9hUli*P>*y15oOX-sRTiZ`XWx|8V z>Rh*BIduCksv>C%czEHFD@BeH$hho4pYt?PfT?*Zsg?9`eImLx>O2{P;R=C~f>$El zkMCndPip7O=J@i7z`}D|3VzOFN0|%ds;z2%@=#&o?<@NT$io4XCGMgg&xoSUH>*o< ziDeO3SMABTaVvPZe@2v-2qZ)IvWYnOO7ZkG=-RQZ*1j8_Y=DsiVzVt0anOjg+)|`l z80zOIoecJD1V;ZjwTZdqhyrY!LoWYd1jxgI#rUVKp{X@_syBHqHA`34FMl8-_+2)F zK;4+{sHmtIKJsuKEqXm;>3}?(7xIsrc0eA^XD*)7k1oWV!a~OLn>(8=KQ95{3!tPk z-7CIRCw3ae^&x#c>g90kW*@H@P-34O1o8a=SC(YeL8ly*%A?3c^LNIIq7D#*0=-w5 zmz>ydI=8iQ>&w$NRiA~El4>b9JdUYlS&p3vZI}Im4JWiM!uY0iId>VXsMIJHGg!uQ z+h6L{ljkt!M*UpIDcmi*J z3u+fZA4}ux>__o{n!P%|ypR*?Y#j=I(Y@%aeKz;U0*L!ZCJvyFQzZ<*lVEx;CPfd> z<)PPu>JLJ~8wgTgSyJ#_ zy#^pB+@k+Oj8BMN9*>HX|Mp-M1jF%yK1aE5;ITyb)<;Rd zs7|I>cNWtnO}I2fm=NMAGz%%)1zf?^qJ_NYRWsOv*`fp6jQg>Vm+lKwxs?nL4#}8U z!PfKnE49)4p?md5P}qv<;ZXRrhB(8D+sQload5Bb_&LHF(kD})vCH@K{fp}!0x!Y1 z?;Ee~bHnj%Gk*U4a=^{l1y51k(l1W{*4Ug3DDfz!x#9c!K+&AIvy`}D%h&}nfn1O^ zL=M?Zp$f5Xu`CYvOssLbqLyOw?0s6Abi~*6&i_Fk<&UV5|DzS~|6>^bAKIC%C;#U{ zy3pR3@5Y@%fc_5N-XWK}N%+}F>AgVJykG}aP10)Zgd^23ITf?QJehk^E*W?cqEQpM zWsrzQ+IGFRM#iT*=m0kPuRseA`br|WNME{>@?4*{E`T$$w_7*fr+FGu;oE#Qt|9() z1&qIGhM5g`4V(a81Am2V?EDXV-2WAh^Oe9+$Muz*>Nv=BO~%%)kW4eDg9qWW#^R1Y zjVozfa9MfDcfm>Fq+zZhowbasrSD!1|GI1=8kRsbswoDMzwAQun4e#Zl+1;sp4(so z8*rdzhn=Y#+PmB9rze2d2_V_~se=Gv&4E$@>0@{p)I7mR zCvno69pf-a5Ua?><_U>soWs}9DIJ5)VH+H)!a?6|#XaqHT9f7FdK_f}sTy3IeAoD1 z$Acw*HSbRP3BDXyA%_7AH1IoF7#XH`R-T#sD$<0JaFN&m5+4xk_M$pf*e#z~Xk8f% z5|}gqWWTzI9~m1f!85KJ0Bo2AQ>&8Lr?kbnbdQz8@7#b-k-#E|s+DvD9w?~jM)xV0 zXRAj2VWhF2zVnHF0|8S2lFyzqCwMs}S->z?z)!qe!V^$R_sx+KegpnM93rg?b=xn% zo^wE0fO+pX4Uf9IOO?%O!s^`4BF1iIW~~;loIVdA7FSDHIE)(sZZ8i6h{gFp?x5Ee z4M&Y)!U*t1B0pdNd~xUiUtG=}b-_NwOuvyJ@9#9d(*#uZAQJ4SADZT7Y1Ul!=rtqI zm@CBV92=ObxmFlPgU|4?C{4%hmW4gR9`67?r#ICpZ01QsV@6AZ_N+DRVkt{5LL&?M zM)jx3*L50K+BU90LD?U9JUa_?*sSxPCb`($Wu135pLBXj`nEJVZ|*gcDPaj!V9qpq zImn$v!Mj1=ov%t|l*fKZEb6@UIMkY5L3CD_{W!U?%$hh%{dv7xG_rfjO7%4SD+dE` z1D(aEf0{*|W;HR{v$ErW<~^i6PxN|!_ixtNW0J0x19EP*r#F59!0RW9Vbc-=_hb~B ziDoA`^Oqh-em2JL6o1W~CUe6TN(Ont4x~^1b%es3xo)+LIxZochE;rqP~0audJN^9 zc&U4kK6jXNm%G#ImWLWnA$2ZiY38`m8=lx6^^I{s z-G?Jr2iDSzROM?`!=i=R2Q0f~Y+@Y_yi4+467) zk&(kgRUYp#MdnxvhJER(t6k@&U1oU~uml)c3oRq+c}AqFjKtKcK-tn9cUG&k#!era z^#$FR#;Y^-Ej8ftHSBtP~QYv2wyPrR8J_Cz@0 zfMz<>!&^}q>2G~LDtWJNpOI!{ezSH`hjLkd4KX(S0d(WO)svF02|ST4!Sk6Qr=pD~ zezi5QD4B+O#_n*hViGq#H8x1={UnQaNdW7i#lf=v$_wk^(a}-_Io--eYx$>LL!rAt z_uX;%3S2|$2OkEnCTKEr`w z=%1Nzwi>hEl0)Y<23d=opz1SC*dzoyY+s#Bt@=01EP3I&=C`&pl6h z8;OkqP3*G0fwbtJw$@cwr*7FyW*eth5T8ogD}n&p<6!SY-|p zbo!&w=q=$aBc#!WC*yhjzGL4#`?@OwA)M_lJ?rBj=7%{C3^<4pc+aTcwQ^Bej~0DB zDi#5*BbHVxNYp*Pnu|0XM>Y5~!#2j9T1M7fl-t3jK9fw>c}f<3Q{|A7K-IR_e|_Qr zIEbO60S;mmLZ2;*3b}|Q;-?jOFm}8wtRz%II7>nO0Kgn2ji@S5ZA}GkjL$V_Ay8vp zT8tuKAna{Tu&@$KDNJd!iK*c&p_}sl4&vxA<3XU24Y~nKR4s>hR{Rx;0c(SuA2mG~d^@9vC zOO((91L){vEy^?$n~as5{*)6w2uKODcB~VPWgyUVI?u zL9|NCfeKTP(&I|U_m7E&zr@Ubai`V$5bX`{;jS1nY*HN=qL(j*)*`Ucn4VT6-3Ba3 zhnoWWjQE}BDmpEfY>pPkk!}OSB517jhBtrffZ&z}_WMTjfcXIBhPkR;ondvcjCcaL z1_6=eu!>*#H28Knrk#dumDji*b#WTg$(6Vt&n>nUVv5%&g)Sy~dKC}g`=8i-e?$-2 z^~EHl#B~{>a@wfhhIGBY_p~>>e3Ct-2U5ileoW0CcpvqWtlkVQseWpJBt8w}!!)y& zo*Xz)Aamkz!x(lQ%W01~ce;qu-CXRgc#6yobd%{cTzWG|=92tEr<%xoKioB@b!UNZ zPq7`#ON&3M75!CBIqg%L_8GaUxW|?R3ohRGEGbUppa|$cw9vew*^V!7<;Fry#8{cS zdNj+GAg0r_P_){rYz^}2RMwJ4?3N*8VPs@&P`e-LJM_9y$;PCWh{R#Z276idxQ+x0 z$6Rakmu(#GdkEL2o-T$vww zG_z$e_h){P7PT5aBOvcI0N`qvd8YGajk*`fGSa$Q{Y1mK`E+Kwvx)qZ`=3aDnwI+P z8vKr)U%-#d)Ur4NGLx{LUoc3=UGZf?+bX)3hcPaBWuvD1B?Ql25189UGsg(2?t&UslyvYmhJH*m}36Q+gV&Ie3h= z%%AP!(H`BhUiI+%0$!*S&J8dDN-%-M1y4@V zP%DF_B279lZatDE$3&>3{w(A~MHaHuALqXc2!fDchnGcrpPL-#|BQ`~;RBN9S@LjBu6em_|C84= zsY5c0)KKpKqwOu2@>;YkS|nI-cZU$%-QC?ixVtA7@jb^4gOTwI8gTsq1(I za>2|AB0R<04*_6^;%50?;4*|llqx3Rfs!*ge(E4d&^YHvnbOvs3MSYCOJpF=(8b3Y zc)oPaHG+y~$28p^*j_jLcB}zf=D6Ql=A^zCVnE9*-#X8SZ1tp@5>azAJ6r4vDC{x| z8Ep`yEjN@r_&{C&caw7E`~oSZ4T{^ZW6Zmm8Ph}g=x9(J&0Jw;Y(3!@h+457G}O`q zuKnGp#}P3~EYWA8Ktlwz^Tf_Ga&Awk^ZA>!Q(5?yA?{X>^w&kSFKw4&F6pn3Jq+nh zN0aV1qhhXf{aGf(es@dBsqF8%pv7^vF7=J{6tRScpgYA3Zv5;?=-wsTHwVifXw4un zdpsCUxYp1=qc<2TRJ9d1kSH<~U!aH5D(X5biu4S^>LI7;PS+CB4C_einT`h|=9FLX zT6gW9yiGnusqq(-G+=+fN#l!1^G zz>xd6RV>M|h29SC*A=WCqJ_d~5s-O*_;&emGQPCev2enf`pTnUN5gIKMT1B6Yrir& zAY~R3bW18!dk!gy1?8B50SCph4j`2rV!T8{5kGPx0iTzqTzAx9rzc*8ML)|5)Aq%y zwm1{BX|n(?R!=Hv!?v{FcZkkt)jqaeFI4b9!E0zN7YOkCs^z5Ue}0up;!vXD9Y|3* zvzP3i$6e5}9OsZS%Q-7k?<#28g4a;cyD(gA(*1M0!8}~~Hr3Q3+P)&734h;n!V$Yd z+IGh4`*p<_6Sj@ykk$;_iC-^`m=%QyJ?(aaZd89s+QJRS{jtYTiMqQbl85{43rT~V z(ZM=NLnw8Dnz`lZH?ceL^G~%e6&;YAmPWBuVa>7QCJqRFg|f+ad5~xQq$5b& z+Mk{qP^{Jr!uC+^knrHY=fd(iq8Go3%n%<#TP*5N9@`cyc~_Q;^k!;bBUlNUisE$o zoL5-(PE0{H)M+;ylzx{djNK`{C+v8Z-rcvV80VG_T!?myGHv8)wd?GB;pt_b(72wM z&4qeb;3LLGP@o=pLEmzQ#HaLtkXa6uqlbL0=3=khu7kTcbb9m?a^Hk5EAslctRotb zbsP+9T>mW3g&!vmcJs2Mia4?xVyk+08u?c�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

    !UcYw%D?fXdPj^%RhZTXUYU|oXHGqG_Nl{CoC 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®L=M(-8WuvT{*0X!*Af%O-p3DYj=UUUt8_a8sS|E8Yu$00 zH7dH$-8E2fJGslh&M2iqM5FZD*CDTzOrIa4`+@5gpUiifwtxbT)YVbB&x#MDozzk< zRb?{(NJTIB0Wvsh+*V@~Tm3a9>*N&MMzlQ2$~oP&OY# zt7taK(S$;6?pX}z99;ymNY7q*G3FZxf=uY=OAsg;jO?vLgS~y^i?&832p}cr{xQmtfC87&7FPWsun(2> z8g6>22Xep=tJ+V9@KNeMYoj5hHHo-JfYNv@$ai?0v2NSyRD_HO*-%q~pTC_W0{kNa zDC=wVG88pYAw=d`@M|^@rimdrln>5#7-yzvih?Vb_KSCpVd=7}n$zkg=`^RV$LH-) zb!c?!l(RWDLx26$1!_1@8q@n4k2CHWdSsBlCOAZybfWWz-DmlM)nY)7=7Q|U=&gVa z=X;Hd57C(FXpE#%b5&6}CzG2h+DFD!rS?)W={;px;j3!H%qCv*u*Q+fwSGx#Eyz92 z_SzM_YiKcxPqWP!TN;ip2Wse`NIZRefEv0-@QeC?YUsw`&bEOfddHxBl&a_D5E55g z2yR!h$CqRfS5NrTt#xP1Q)x7>Xv6rZi0Fl5Fgy!;0o7VlMLb z!#>JNR+H1un@B+PWhj-fnsE zZJq0<28mE9qkV1!o*; zz>VP|7X)nPLxM!NDMZnga0CY5OomP1y2G;Gw9|mcsp7W&uS`w;Bkk)yxV1ko)&8?- z_&*2X|1%9A{$(2Sj4p0BoJb@=#_68IIbj|0i*jBmY1;?H6Z0DvbHm7g%If{iXn7iV;9?e%ZmBJD5gylvlc@u#pfamUTYrh#rf7# zg;bmJbT{7d`DNiYegCQ>Ea|8gN+4R8%L+6HzG09nhmTKHN*~WBU~~-I-3$V^;Mkd% zFNB^7C-@&m&Q-}|*y22ug-J#9p3m%sYHE!`J6}|-4<8r&8EB{n-O9pgpt*g56oxR4 zW#SOatYLbD^PkEr!3-+3LM97t2C>d=dpdp2y#zgH7(ULZJTdG7SvPgRisB)7q(Oq0^l|HFBzDw6wwH zKe6m9c`QZ^;>d(CAYxGQ8*ge)W{5X}SZ$Yzq?{-WJMM-_UHtGR}B^ad0 zMv*GHGEL12^_v&NlBZugpPP`|DD_6&S31=<)0g`2=PyC7Zwzh~n7)HRoC=%G2HdX-3iD#mL7Fe0Iu_qf*6-=#p#Gq=r+I~FBeIKb zKb!qwue)_ojkV-tGcblT=J9Hfjeqet(sc7s@Qsm*S3zRl_JpkSi zh6_0FGMn_&EUG1=0(S6-Gv}U>^;>`Aukht@?G~_}+ZT{~MmR-LHNc4UZMM8z4_mUv zLb9s~#Fr;gE~?klMT@$aSA9dbLxQ--0M0|Lg_V8o2lYL$dx%~KdZ4Y+SlJHuU!ueQd(|3O;i%nK| zYnu;ZOCcsYZ3w$`wsbgE>?BXX4Bk#MjvOfR#U3~b~r8b zG232LP-rucR2}Tn8*oh{wV?=^Alvy~ooS|QjMb|V$DmP$T8NFO!yM^;oTW7Tv%8b>ZUL^;+jYz^(l`GyO+8{FmJO zZ`Un;!h#V4*%G=}ghh8zXvfiBlF;EZ0}`S_oN9Z+UE8Ifj~ zmN>O4VaCUr#58m%awxF8n9&W22vo=N3#Z>M5i5_NGMd(!AZFJSWTDMOHNUCEY$xYx z1AD5k7jL^11NoV1g#`8XWNDOt-1;(omZuHhwd?Vpr^4^fB_MxA+i{|O+@UfG&Jf+C3JaNec67hn56^Dr^@=m3`OfW_RCSZ zYO6%MdMNWFSkLtOO*bdYriG?e`lTv zu*;_}H?Vm!Sb2$JnRZ;)+j-@wdOufSN4@m>iSvo{Du%laQog+O3t|djHc;HuLi3)o zzn_rvmezWF?;P}Ebf`3>uyWgSr^u@6-Z}p9ow{$mb{jOmbv3^e?<}zAD{!fJXq+h} zpq&6%A4zy8nr$*AwpNG5HGwHJZpj5HSI&p&15tk1|k$pdGDL2YD zNsq(c+%tD7EhVacaOBMSc}r0iV?pgl*=fKF+!tptg=~0p%yfsSL91UZ*c+UbO>&}@ zD|U`77MYIiF08Bbx<0CHH6qO#y{}P&!oPU@G03y;&hC9^n<(;SVceA$7x@m&67pW- zZk7)1N0p-*I{5O>87}5;gO(~_?*KQ@X(3`BfjyInByZ4a64fksMoo|_UAIt5^p_WG z!*l7kPKv#ee40umA4Xxnw0rB}R|5(=O2l@NS^DJ|>pFPyxG!q@Z(uy3qoTTd>;)Pi z*}91DKY0h$;@Zk%UjSDlIx9r`CO9$iCScrIXRq=de+cE*E+g}{;%o5j^R;H)`L~6H z4ZPvcg=pl4sJrbB*;<`9*{Fw(2*Ay{nVr6FizFc?J6?-&e`}UYBBl;nr~! z79qasFZF*$U^1a*q0|PC`Z^@VJ=nL{%j)qs>%qS=oJk7+QC+{n23K*`DEf(Xx3v!oB`lwZQRQ7Yo@f4iJPu0J=1W zMFg;@-pAvV*r-~5l+lW&@TZAkoSa%Fpmm+AyLyBup7b?pQ8i0L2zIUvDn z2JjOz5<^b4HX~Hn!;B1$)j${`ch)r`lltBliKhqOicTGvh)Z&od0Mdbf;OF;e)`SE{}|yhlb2A-CD6h%LMeuD*c7^c|7G+t$fT&q8Kk2|k#vH^VRPls3{W&_(Bk%u zBO;c=er%XuHJ~W&@!Hm70AS?(ZHzbE>sd@#1g9FQ#P+%m+*V(!Y*)g*A{N4{T&ZUf zzp5bBTywCltf{0^uablmn4i$R6BuYfQqyfUotYxVoi3t#31@h#Rpdoo(w$X6JyAxD zzx<&K^N`e=B>=e|w;WmVEll85-3A!4$)1sE-K9iMx!v4w|H##DB&wv}Ly_SLw9Xq-7^o5uFF|+Vbe%3wO_me!gz*+Q+*)SPh&>O5GjS(a6=N*-5qJ-yA{ z;?DL>4%{MG_<(!O(p7jNawWSQ;}OD@VPgW9<8>yu;F+D_hLDAj0SBcfM zJWeKm`G2sh*L5ES&=UmBAVsXFPI<&%C|!Q=OgYpCR2gC8%+Rh#k7i^}$!z*6Ra6}Y?a zxiCQLKwRGZv@w;DQ~Bbl-1^+y7&tXLY1R2?gk7h^Sh}O&cmhGrsMd$ilrV;CPK>wpU-1wCOAVs zb+>DBuTrr4)4P>8rr}SPvq^!GXlPhxb#hy2_#`vA+t|`jK~S7LB*iEvd{F!qur;P-ZmISHTM= zyGo-tZVJKRnN-2j;G9PT3Pf4{{?Gf{t-61DHQsWH_jPS-b9+FOFEBXzqUm+9;z$P8 z8zZ6%XnqK!q}fSx2xAaiKU3*v(9^dKuzTn{^)Swwd?OyDJIXU3AJ>$sA<@7}89}N` z_%x0E4S{7R8)AwY`J0Esh2!S!KO~}F>qd1$gsBpMFUEjR`E)U0fSVbxxBYAle46>=clJJPp(@g%CfOVI^8i-?>4h?IwkxC1$jSSk<(ZkJ~STTwz^Ax319#az5 z-@=fR0T^I_mLu69|5+(oc9w`;sFKVdaPROOXu*yZjFI%iBY)b`{na$emdnycqXD(Y zL;;cdDzk^Y!UiN*PSXqf-H4zTv`c%WV-l9ggsnF)L;^1C4N&Z~K7Lv~<2CYU$^B{A zN7f;~h_AtxV0bSd(p8YAqwJ2WwB55yZWkA0_4$z<08o5x?YU`H=!Ub%#pe z%Y^=ce0V~GwHBw}oPgIy!90I>zWCl-e9J2z!xq;gH#IfwfFa^wMe|TdVswr8bSrtq zvH8Hah?Qu>98e%CfTt8fH31!h`KC?Vdi?fPgqNZ~mt}9nh5{x?eOWdj~YBdq;`0V&&J# zRCSH-y%`H`gt^(08j)(5gY{t=p)5=A-++Q(miMTm*qkO%#CP_CxPJa1$Qd1CMEM{1 z#P*^HP;1ZXwG1ZJ<08|H5%Md>21!z9tkkn)>I)=Yy^z-TW!l88+sPt9IF|nP@u&qqG}! zrl#PO`1LW&kcQ%0a9LsSYUh<}-PJovgGh5x6B=V=4sK>xaKg|g2D4n`{$|0DsZ4&i zF<#6YPhv&G4Ao+XmvL{)ZNf%G=!u0r ziWHm#yeeY6^ykl9^d_2_uj;i@k>W1h;$*rbfvi|BtjWB5xkb&{kWt39FLQm!cHXMD zcE~lz77nlJQ(QAgC#k5LccERN-J3KCO;254ylYjZjA9#t1R_vXshQbx2*ju~(|Qx7`rUI*%BciHmK4sU~4PJFi=g0d$j?n&52m zW)X>h)+k~@$r`rN{Qlb$<(@3k{O6hbLhh}H?zz#yQYu471^+irsCa{PBt)d1PD#!d zhvwH)v&$D)QA)4RM>N=664<4neF#QMx$cNZB zpe{f7T3=j5?(1MM-LB%S?&mFULG2t`6F=|Vb8G~5G;(Y7eJ}l%M}e(14GICQ1y4y;lr-zOwnh| z`B`x@{a7`c@Dkk4L<=@_Zu{Q{W1St)a0wiYSpScM@qdfJf3WL#L)q{ChoksQ+fhXqcaA41P>I%ZU{SJ<|#Q8I2G}a$o#bCrj92EAq9DxMJ)e>bMlJ5gq;6qKK;T z_5u1aU9B0@cE#fJV*6^s5(FWJwLW^5T*AS^l@Se~T>cWv&-ox_8MVpK+pKy3?_dd0 z81o8yKFu$Fd6t17rSiefia$+YUwCtT1z+ZAJ8&>{eUmRBSBWvt!h3x{cJ!$~V8B8^ zpU#qw{i*s*tLg+`J+^w1t0{(Ndlj#=SNTj6bO!E6}Wp25F8__Zzzf?1RP z%9xNLV!s^74)qAZTSIo!TvbySmLLKwlc}Q+*rTT(RRIr^=h}@pwV{CF-w$Qi#yd8X^zTEXvByGn|wdi zDV>qv#d4Q!@Ucm%t8pS`5#upFyVdMOLx+G|(7zm`;(=SFS{6*C zc)!`~S>rjo_E5%(VlWE{C!0C~?&7M}?o5}}{W$|0(Stl&nn$c#sN89k*8Ou_b)X)a zb!>q{ijEzwuPdt1j}j%^QToS3LIZt^!ZRe^SEfOe^=)!Y_l7~h>*pQBGK!Eg^I#v{ z8(h4kcuvGyUTVygUMTN9<1VO|^zCi{9*c-C+70A#NbNK!0fOg`%l^^Xo>~Zqg?gps zJ%)B9s%V`{rsMPqd4CsnSpm6e(_+0&DBZOxCw8mZBcKuIPLqca`zx16WhDP8P0D0k z{7S$n=<{b~ChC}Tkd2MjpgNAMdb#kzaGEvr84RSw=&(kyLoLpM)~^$)8<{$N6B+zY zi$!sbv}WgVMpbVY*(#09KN<4M!q-kQGaG8vd5SzdVT!Fhtt!)~bxd8FvJTr_RCA{C z2!vkAq^nt*Z|#$Of@urXus!l+!*{x#0+nS6FXUp1vl(VIu;uqOcnI%phwtXt8V4L- zRYM+5kx9BID{FK-#Jrcy5y(lS0C;$Q9lM`ZAk98Rj{x354p^q9qc%g!4E&6yeXP~; z+^3{v9{oq#jT!^%;lHM&4mqS4G5qy93%;;tRmu~;V(C9F0^@D&s&pfn&A4>7pXpQq+8HP*!v;%I~ze2pb$%VgMq)#2xrkz zq3k>;PK$7PwVhfc2!PE)`ug2V2Nb1%kR!<>dipcYz~9Mu8C(Az9iKzz`yauavxh<9N z69~X|$ypnTh7rQTu6yq?kW=w6j-E@lYy_$ghKInMbIZ~yh0r@fSz|o`y-mWxG>0fh zM+DboPRR|x8n*rQMaAKD&{=g&Zse2AXsO#hg&vzpj4|Py5|j&Q*wreJr~~eC<+Ui1 z7vk_#0RD!<{yvjnrGbFubS;h<b zLR3Wotl}?mTqnkd3MiMDSIlPJ$8gf%UQA&~?!Yf}M{0lScj9VG(v=QWFA?pnKIdgn zzy{s}#Ghu#KN@&3p$XaBLjD)gq!TfOzy_Y42NuN@p75%{KO1;-#Y;$6F;FmhrInSX zTFU%n!gqVeUj+qe`@H5^5x4lke#VvxdYVecuz%6x`}*uKlo9n|t{jLF(ficIG+39C zbB;Rv&@D~N-qC1eOLN*m0VX#~ua|!lt-l?oye#h%#vVHo{)Xq7-dTQnT_=ob92Wlf*jj9_)ctFzNZH zfv3&(`@A@rB|)hE#CA255jVc8cv-8=o!^Sz!q}Gnr+9}IhkmNws>4uggTkbHBfU%G z^sVqDdS4LBe2&VV_H#x@>{#(~VvTXYGx_jUp6cs%RDWK#uC%omMdvW_wb-PWj1Kzp}IR0&r+GUF2s0HPU#YovfICbOH zSH&X9223W`tdPTD1ooGfV$JlHAuw?ZQ|X4G^6qNAnE1rkY%d3P2jD7B(vY%{-7)(_ zVx?^Zgr7dEE(7+j3l?1(XJdBjL+4H-`avVpGi>~MXu-;fBZfJ5+?mYKi@6?Pv*ga9 zrmXLwL0k==)v)7u#AA-Pu>|M-lVAUKSD27)c1VJjhl&knhGkmT%daJ^xx?WNdjxgM zkH3^Jsz7%fCV>O<53KnAVPO8xL0d;f&uZ=qR#(6I6tIjp4L!R6gZRC4^#_Jj>OabO zjYNs`6`p1*eY1$F5C{oH)4p>*aCy1VS4`9i^Y~>(^py#x*??ud>9F6WWhEjd5Nrw| z3N&UQkwTD)4U!^fcz?=xzKkq5;QV>QKbY8&ogSZD8aWr2P?$@ckB=yPIKOf4#2joXhC%gDpQ`Z{ALg!MT%jvJR|1 zB<6l*Xy=82THWr>xziBz0G9C#2;H$1`h48j5MOnG{`yhEX}c7)7lTy12$90%j5qt` z(-0uvM;Q)&(0~vw1juc(L{D0(VyM>9(V%VUr733|p|yOhYEA%ree9$lPcBgZp06*- zH%vRqcwLiyl88Q$BTr1L?s3eF)=e8~He~j_@dtT>Aa%PgAdo>!Ayu<|ZB4b1=UTk; z^C1XVt&&qSDg3k|SZ5Zb@#u4^p=bjzY=3QEVaeZSIX#`%heqxcvBV3!4{G(yn}DKB zDsRJCK(OL)8s<9X*pOo4#N;$tFQSDOPt90kn>8OzPfZ1P>{Z~d-t^>e(1RVd%Rzkj zz(*WbA`}js*P=uiD2OJVWkP&i(;2DwJhBpcj%vD&3NwJlcd4pd) zpv~bY{pPHsu^2n1dAgzCGb6}EpQ}_g09?DoVsAYcOLdk!* z>B(&4{}!l3#E{xy>hey|YN{=PTU{p8BraQLzUz(7oX?WSmeoz`YeLy8?zxqt2McPj znNw4(vkX)7=Cm9V;;eQ?J()DF>5FDDY2TQkPdIdzT({e8cY-<2%&?rF@)^jA_-c@N2nGi_a`!$iwc&(ziauXoZP>K{5T)NKurPxul6^V;EfUg&7*cn)1jrj4Xp z6xouN2yREbGE&OfBV#=?Yki<~PM1}uf?ET^=j{hp`H}nkapZIZQb**}AejC;{z8MS zXGdnY?Tik+#ir%l1m+qG%_X_)>GhY5>)XWyNOLEWN(8ft+2+$kPsJAH0igV7Y(P*o zd>=RY3*mx+&d5*t;79scr~dC?pn2J-BJDPq#2hXKD->*M*1p@XCF>dO5^N(s{_jej zhMmNw2QX;X0dL0tG->`z^!~SJ)BmXD0neu24Mx`u3>baFhEd}0;e+9<7HQEwHprkk zl2~s|f{!L^9R|ND1v#j~8gHm45NscOFH=J?Zavsp@HZRT-(d|N)CTtQ4odW+tRdt7 zK#b?_zA2I6{jBj(l$tp&?gQ}nNCAs^9WG{+pD&-*(*9yF`JRfG|EGNN=QZSi@Du-D zIq#n=i@CM~S()~>#@wPi6vnUOD)k0zSh*Y?tGIVdqFh)uDUo#y%{qae<%knK z%ywKs^LD{5`zw;(@|$wsQ;30eCUreBhKeeFspu%XqHvsk6M-N5QB@e&>_m(O#Nc-F zk$N_asMIpiU3!ZhvevW`^Eikgsm~l_Vj3@>=%Q6K8A&rGg|UvaC0!Nrz}LZ9K zdhyBsA7^L5R9Ay8>kWb676|Ua-QC^Y-Q6{~1b25Qz{cGj65QS0HMoAuHp~StE*S{^Qs-vwK{-N|JP|J5IHX8Z;dF*L-dYM#ENNGbkDXJ2)G*EeFAwwuLsNPJTSe@;V zZNGaZdU)zzCIEWG`0fAcfS;>B;B7KJI7vGn46 zCdr;@%`P`l>1Cm%PlMq-?{#2RdtMnx{i32|U#ODqj&`latS(Uphq6maHp<|=lythp z!-Z;aNwV05p1WQ12yfn!X==Wzst)c|1*v7AFT@n>SO4^I^r2s7;a6lI2M(j083NMh z6_{W!)?Z0dH(%Thfrrp%ND@SZXO|fFFToFBj&WGmr6FZ@E6g3V+0DN6bNUCikiC3D zOZI!>{_khC*ss&^iI*n(+|Z3W{is*$+M6H7@%<;Ir@pC z;uG#vEXVU#f3ZqmI%WCDxqzd?9h{&NQyrn`#;I7Tp;k+mlHZgkR`G4A`7tj?hkPf# zikt++7>*;7d8A=3yb;YndzV0f_dnEX~ujt)9=#Jwk8zmuQPK~BdDG#EfY>*b> zT#a9U6R(?9gg(gYegGgyF>2J0I!%k7?5K)}dwwnS%_U8VZdDP012vNg^-83v?d(UL z#w{wBo<|Z;Is1t;Wcrkdg8(ENpqUa2(dq^Nf7;e@A+w!sI*O%L)+l>*PMT0;M2n^B9Nn z%Gkmq)`O#!d}=9%dR9ov5v8*qyPW&s9BJ_-W;B)$Xy(| zy=N+0k;yrSc9zw;^ypMSz(!yjY4H;-^wYixX(@8M{>Gqd3uF7uqpZM~hw~zbideE{ z6T0W)?ZP17czehRVPF~qXgeGxENX*1fG5=APirwB0}F5n+iXdu!iYgkRMn;*hQ1gn zZON}A#hx8?f@^L^cS$T@9f@Bz(Hn9y#`f?IcPasnJ1Gk>C|dZ;?+4V(poYeLzkTO8 zvkvxo8#&IqZtJ{S6&{1>L5!#&hw)nf8_5C}B$mF!6Sw3<7o_I)pWMP7kg+T*flzx?z>H$HIuM{w;yZcayS3mzZ z$-?IrbO(eIyTqDQYX zOV1&ffxb=ct;w&CHtimshBqHZQ-mnDB>m2$^3S9FN1rK*n&l`*Id3?%JLBZ9q=gSq z`U0XKINj;JZ2fR6<*(*Cs8%&e9kn~SE`M}!10Y;V;?Uq)@M0* zBD!g?^32OGVIfQEL5X-*Y++b)hQE)Lf|dwBLx2KqN8rRnP3BB2cO_cU zy_|UrGm3Fk9S-QV_AVj8PhEFDj^m3zUIEgCQBo7&~@EBR+@E)d3TkWh|^?G#TGRIRs5)aH0V^_ zhNfA@3q0vqNiXBF~<^w%#F4JSj$RnkBqhI2fHvSC=2#C9M9e`}9BHcJ(7lI+lE zgW=DNIh@WDrpC`{%qeYI)N5RG-sQ_rcdbz=meK>R?U5G+nASM4ML+jNGQ-A~$c*9r zjC$3r!|J2yYh!x8?$7COQ{7&!G|+Yzb7OX#0&e~uem7@ws{v%c&w8DPD%G^q?Voem zFK7JSzSqNS8h$UqKi&44Q-BkwltWZIulL<0L#Tx<_`=&Z{&fmlwa^ZB3i&M#V#l@3 z(!)KIiY33cc)RHGOE#%bvR#C6_V3m1|NTWzX+7lm&%KXo(2w?Cx66OLHH5 zm|07xZ~A*HH{JD!J|=tLy8jaA$O~aBFK*UjK#EHETTA9lb1-Y?!9ZYl{=5%s1bDtaCH${Kk zf&lYp9Ql9;$ot6a@O?X~1h{FtrG;w_6TDFuQ&xY%e;VVE-F9C;;1+CM+6Y>KCez|& zx~p0>g$yHoaml9bz(OxQxwx8Z@hS@<>9s=zBwMhM`ET?eQ$t6U{1&q{R>P(={KjIt z|K(;WFz|u}2@v{7n+b${SCHxUolOheib+_ovhKJFQdI2FvHoy0UlPPoaygIj#KSH{ zu^XwvCW=6jEx93-|9ZD8jM6BtyonR~!Iy±+r^Ti$hI6a((2;lGV`wok-%0FT7M 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

    Z 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 z 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

    G>G|wA z%wzX8UN-1r@;GOab)HA~&fw$&TMbz80iBP3KXHwa3T1yy4ll19SJgg-j4VoCyBN!nS{yVY^03Fl)kKvh>V) z+#kqu+xYnHJJ#*<>N(06`Cy)J`I-l~sOfp14L|`n&8B56hb2TZArf{y^a%#aHc{TS z*-MhN8dx{yR=d$9^7AUvWeJ!*um_lCjBJ;8coy+2$Fdh#5swRQ6>68WZxX&T<%E+n z{ah35DV=x>Z-4OIWFK#WU!5nK=$Xe_@;sWa?yM6@SNp2RNj<&3Nr66%h$Ki{G(kF$ z@?tjhDo@4w&6z#-6jsNH!hGY^??8W4WyfdZ+d%3?qoK=Iq?g6nQ-{~EoK=o=?%faR zz*$&^d+D3N46Q(P2TlRK677r`NMa=ig=oQOwda+&mnMT8Hdvif*wuT%mCPrX&cc-W zKIe+7uM+KMwW8BFCKPfc?}k-(E8^a$^5(E+t49~P*gFp~9%L%XFCtISsmpWG#8Y2+ zHaW_hH={I=1!AFP?XCq zRk%dMGV5|t0jvl@`SvuAY6jRw4|{wFejKq!TT2kgzc9(!O)WI17d1GA%;3nK&XmUi zcOqEyeGjXFF}w8QDG~-#fL8P~FG+oUl$A-Eey>ZBEXssJ<$+E;s?Cg1bb;|L$jR}S ztWWqmJc@7O1>maKR-9|uY%5X+I*S$Xz>0L1lcos^?bLw~D_oo!gLAiNXWlgF!!aJ;+n=W29X2HD|BF4ef78GJ+d2PJ|IWR&y#W9?AkT76$1sFY z#@%Q-v7Wt=(1)%IAuC)q#Zd+tHG$r4@gUUcHgYwd-JA14c&nz)9!EAA(t_=U*+dJ7 zbNdpYwU-ydW5m!kDJ%Y5yTMJa6YA}J=CXd3y$|%ydu?}Idd&u-WFW*aAZ1wK1t0;^ z*FP;^vG7hoQ*6mP1luR^jF)D@v}jo<9U!T)wc_&7h`PMY*r3$( zpEv}t!rGmCdS_-ZkVrWSAq9Z7t5FMaS&C41an*$PUvUd)_lC&EgprQSd1M@;OBXq$ zmXx(73ORDdp|~Yw4JOjW9TeEz7&88%eFs`X!DP!ZyXsCZksm1cb;2v z@85WCzj5AqZhAnT+x7qO+|>Ky(;E}Bk%R<+Sj%`f-WKvg0U*|rkyoZTBVUl81s;gC zbe}f-ARsY~rImk*t}=wVR17muneY!=mugfH*C;F zOhgovp=mc1Ia5Y;YO6464t>^~Ivg%#tkWj>4)W9^%fRxRHB>7j(~U6;^Ps$la|4W& zZjCwL@@@Rp&2z%fM3p%CLj3+gwG;)iBZby&9*FE8(S{4GSmIK$J5*Z!)+ z0o3{DHxyaM#1TBW_WAdoFP#-ECoCm)^L|UG?^o4{>p8fhTEuY0a2BN20t6wV=zBM?ha$TNu239UO6g~nO7(L|Nm)|32mQahnrg$qwdOLk5 zF;1nydUQhtOqogTsEk3wLvC)Q#^{3nLA6|x;gOrC{L0B1;^!_A9zxqV-gH8phHrI0 zkrV{zO!wlu*FT-{K24*!cnRGJb2hv>(6;^UcGoe`@@4ERe|(R_^L59E=dCl%6%((* z*>=xg&!5)K$)E1~9X3eWK?n*|z5>(6KX8vXpQiPYgxdKwE3GXU9fRd(hB6o9pk9bM zxYKs9ghZ}MhmgPLkfJ?B%d%8j(pxQEwv%&ObW-TFqbd^oSqH<+X-NKywDG^_;D0d1 zU;o(s6@3zVH5ytmBA$;hAgSpc_NEJgh`)ga?xAr*!Yy+;n1|WxqDoX~fhCqtWlj%? z9WqE!mgyhj)XonET82MtkqUsA&|jTNG=lX{h%;$k)d6>ZKLGO-z1@#$QlFQRLgfw~ zrN;i5HXcsr{CArxa+>P%U(np%Ki*&3i2yP?|9~4wWj8Z>b+o<1jcPF8qHKS8YID|6 zEX(An^A;XHiZup?bHy=}hrh9^qoO?-<2E#MfE#^6rRnRUvNs_mQyIXPb+rJyz)UTRNz8@6=VHsV5EZWBlTa_9Wbk-AfckM0(T!73KEuu;SKC(BQ6a^ECB46X87Bs%fUTQY%43no zx*`GvL>41}u+-6XzZdGNptpNX*z_g2p8tk(>w3qzsf7b^Za9>%(nUegbDx>tac;1* zpSv(x^3bo*5IIJWLDOa#ve@2nZfZ9yR8Wwt`2v1I@B3#xc8;FGZxe1KW35inN07i8 z9Y3%@B4k@3NjM2Ckko4AisvDZSGZ8Y0+)WpfH=2=tpIQ(u3lkA7WD$$fqdY38YsNQ z#`Be46U=TM-voIA?7&MwrzEh1P1^t)vIwL2(>(w1Fa@_#Q zLc~SwC2<2Y79H|!qW}ml+u%?BF|80Cgx^9ua33b6I!Jo~W{xFaBPox!8nkOzjB7<( z_BsmZuy>QQmPV+ifGxTxV+}>~6X0@L0Gv1EV7Xnifo<^?>Q&wwgtV1oS*zIki~kV4 zcC&;^My=4a)wAcweg3^5`#5eLF7qj5r=LWDfpduQO4=bs-%Kt_bc<(9(0OdvBu+<9 zU#qvL0&XiF)0c!T=F@nUw@{TL60xMPfjfYFKSxHgGo)cE4GI^(suq{t{wx;S$qFey)~6hF8`C1I38uDprmY^ zke;S8W@BoKUA;&y7m1fIWHH}ns;VZqsrY ziXL@BJp90y1bb(2syERifg>`j+4bz{)vs2qi69Mrt5!NhX&CT(vi{KVEG317^-ht#<=VP;gF#^H1Y*sNcvv36-mtx?9S^oH72CoaJm+nvZv(AFv&*+id zSa4e%MCyLgtM)A#z3Cksvi+L(2Ou;XkfL>>Wq(=wl(g z7#+5ZCzk0>1h}B^HJ{nx7rxxd3(BjPX!m(e(tfbmjh-%?Rc4C16%03yW-P3_fYDg- zI_Y*61ANU&u;?Z{+OvB!NLYGmPO)FQZbS*GbK!WAiV?7x7^A2!X6seE`Br}D0ht5+ zGV6G8j`E%Ans^4feYX3e$&rr&A`w_-D`weC%nz*Ke+xYI8MtnoVUZEE&R4$@jV|;b zM>{6Ta>x&xe$mH5Hv8VX(#eHbU^>@4L6GR&t+Gb_@cO1=&vXs-sZt(P4lsJ^I2tqc zHp6E!QAJiy`RS28+;0u7b%^k>DlHYOB&0{bYab(;cC%WF>+EBj-skZ?dQrOHQEU}i zcL#45R6wAcdR1vzGv;fHDMtZd!;d1Hu4`*Bo_D(COXeB+C*5Nrif6rvb@tTz=B(E>DX zoc78kT@rZp>1sqG(S_>EB?KP7RkNE?89Tbs)|vV+y|yeB-R3jh*$P;SN+owck2q5s zOMR&@K^gwM{qrWQx&DB5Hp{O225ilPZN!W&WunNme+9rN_>0a2#YNX#ez5{B8j4w& zn*!j1Qp~rjsU1n7cKUGY&B5iJR_q-cT1>cCDgp1#uv^NmOI$yqcx=a3^R{(Mp1!tj zADd6WsO*KpS(B_r^wuKDKW4l{#`F10ZHdU0pP3?W!nAuC`CMub`e^T|Fc%-hQ$Jwv zqtILUOwf$qR8=Q;Woy=qyK^fn+e(|;n9UW?Um9eU5yV-|k82u^?H5P!i>-Rlq%#7&YbVS6DC}v^vg9($5CesyYmE`pb zzUS2Nr8WiAk#5=ie>Su5=SF1z1<&oD;`c9B_J1wTwZnojBL_bTtr-nvYKB$blaUO2 zX+`(N3e|Xg`4^sBiwltFhVjmGQyHYyC=>(o+`hi^-1b!MO+IU#XlLDa+CBvTKr+0r zzd{sBc=xgWBadQI#{Ze;b`KC+ehuSOArI61;od`Tq#>*h;wCx;I zeK1=;JI+_5a3`IIMfPI_jo1?bE!443nVG0y!lewP!(2b5xPqFfLm-l5N6 zAVSnFgK{Xym@cH7(FjjY8haXamBkrZd<>8uEDdJLdAJH2CiV zOUgHVo_^I86##fR=tuTr$t+nxa)lM_AdorIsZu5eh+37^^`NiS$?X z<%pMA#S>4nV2L$h`|=;BfU}mku=Ue>))NxF_s}vB?C!77ip6Y@Mb(j9)aia}GK7pV zq0f>~iE>C0%KoZ6Y;sWYv4Nn6aN~%r_pRF(@VOzLQ<$Vrny9!QGYXc@lD*rq=!m_N ze3y~0Sch&2pMD8Vdx)%<`bS;E?I5$9m1uZ)0}rRWv|aT=tK8ZGb}R7)#9D6$>Bmu- zAHYdV#xt}ZmmJwnDr;18*Ue1WCa;D2ieL`Jd0F|)rwDtqd=J11#Wf5t73@`f8cbq9 zbas*CaQa}9bogV8S%_4oqEPMrISQ>MBL3F0;NoYTSGQAPT@eU;9!?l(P7tyD*W2uf zIv+o;`n=X}KShhh6*N}sunGIqzMNFya%|fLlgcicB!7=5rWW3wFbp ztM0tisi&$Qq8(?WWo`M=!f{J9Mn_q0AFYbuGUA+!-N4M*62)2D`nq##dda=+;m4hD z=tF6tCPeyRL#9^7oW(L69U^SDPbYUBhT0%vH5_Rqn++)q1Qj*J@hB}@#x*o&3^J9C1Ln8U`+3De81 zA~wjUFWg8u<}=Fx-R--e>o&gr!!IJM_r*sC_zD1THv;7Zw*!pHn zdKw(jA1YA_+2d>zftA>{Ih0s!k3y}@>|U)z$?p4GpTw=WolZ2+6I@gLL| zjid@j1R*@u71*O`>0vU+^F{HFZN@5RnluMX*M~y2UAlJR^|fNUF|os5>i z-MT7-+C?}N+|V<#0XIPK8uvZCqJpU|h=mIirJ{oKFEO_$j6fgyEdiD9C~3`f)8!g$ zU-0)7X^b%kyFhCky32JSXIOEnBCGW+IM*cASEE_m+h`Qv&N>QhrFqjyhA0X)#YUl0 zUIQ1**WFH^@X0;qd9{!IGsu?&xtraTW?OE4pIcAwJ)4O5X`LQGA!SwGt+5i?xv%l| zzbw_N4LRtyS#Sk!wZ_VGpXmfwVgPY&hZRt{+W41=_?w+5&@Z0hQ`t?`e3V#OZ+_D5UQSzmeUsFDx2V?x)*1xVIM9O*5pR9K}fRda~nxDRtPX1Ubu{4a2m%Y76t#ScLey{1dqu8Z)=a4C40 zEy{x5Afx>@g~u-+@g&~j<{1YL+CCg2bonhYtG|`8cgNwcgXyeR;SwNo}TX-f3>bWD9-7SJ>vtrn;!-&&GEPnJHOv ziB(Mux zzyFS#zyGOICi&5R?cfBuQ^fO(5#pMzTrXpr)`-&bNV^+tB+m;n>n9WxzxsrTIso#3 zGC2OcmVBPuSA?pW!BRFk=e9*9os<;rj zQ?ZzzurP?XY^TaDsypY%a|8@X2%g|y;bMTkWC{3fd+W;1Wye6hE}KP|x50q#QcYf+5b8YU()>&zOYtlnt72)x^a#0-yK zg*U;%BNY)QPE~X#0CY<*59g^x?31ShAi}2CE@{_pol;xCt7qbXH1qBIpPg`>?Lyyw zL34X|!hci7|6qkj|2LZ3zS$om673@YLUZE<(%b-l(A;+GT$H>er@kDO{e$M#ARdM5 zLchFuhlf||@G-T*OA9=ADB-Wu+=it&$^Rky%zrJr;OuJlmy2>bwrCRQ_yaL+TcamD zPC=hI%sB&T2!&UJOCp@|stCz)Dav$clIjTEs3NFnez}Y2t4;E_YZf<^!99ds2HFZK z36u%U0E^OUb6gR05yeh?7>+}j;(OYHHwUOI5 zXTLX|QxX@HToDy~>TjT9zR(605d4kFhT1%GNILEt?uI&iyR(K*7)3>txtI}o z#SiAnah~$Du9u?iqp-w@&{#04EIg#5?AF_TvYD2c!;=)g2iw}n9#2dHhINZ8*W$504o5{Nv&0e`5$N#S+@p0Bt?s_LgY z9VFX8i;LYP=xRmk6TPJokfN2H5ux77MA58)y3#|XKDSgb`uHTP3OI9%@+vnK zzrlf!(Q1hZt_cqKerN)Ua%r|Y$IWB6cEb$0apa4$9-Y3;jP>j57%}MGn_Lx+In-s; zK%jpWMwXGM!%C4CN5mTHr;-559<1uF# zM{7maXs&)P90%Cv*MuCtc`g&Cv?FU43H)GTpzy{^g7_hF!AG2AU%2j4Z}VE|_$u&B z**c<#*mdc%nP^nTe^b22k@O&>L__rLox|WEa=0~ zUc=@w!lZ7ZUqd@9?z0pU8~T9WZxJo`WSzVBlQc0GK&x^CL;n643Wtf_55^#KBf9lf zRH>4B6jSEP!*YXuwRonMwAi_DR;J$5j7^*IpxKOB=3v_PSJX3`;|bK4kaY2WnUr;I zUj*(|7|IEDy!y55F_w3v>eg&?oP|{-*^YcsykV)SqKVShH0H|4P>2L(bWY|4rwfqYov%s;qlE~FmWu8b*H?Iw-paYb$lvsd|&>dLTsjk zHv9?L`9w(kFVyj$7-QxCRL2bfL?XSlml(G}DtAm=o}IYd@U-+qJY5Wao;FExHHHhV z2nC>yM2KplxN8RZ22FIkq=cpQYiN6*cj2-8nkGLAM)INZ6lai#8*K>u#`*=qRuM(a z*et%OPiA*9KTM=~x}HZ3SFG<+1Cek6O(-BF0t2z-r(l)8%<3>WrKVC0OXy^-+K^S8 zg`mEW7gtR<&Yp%d%PeBdE-K9IuHB1?M$}|@i079-U9#m1Xx_^eQVtxU#Dn3p0e!n= zrS$Ke#2RzP63@;vi$uZtVjyfQJb-LtvQb=R%;~DXEZ^qL6Rl5|Euq2gLJ`03)|p_x z;IAtz7{)ZO$~1gzrHs!x=uT76ezX=@m`cn&w07*yt&5r8GzrVhAd`4x6_|YMBRR zFxT(Lp+c7f)_f}0s;^I-LU?TgMNhH`lOFc$A`WXPpWm?&ig$GZO=4ww#OP5%id`s) z+cVS#ceBNlTpYQBjS|FNpAc9)?=8fOrep9b5XP*5| z6eCIp>F&s^^Xlu5v(Omj*4&>G5PUFw5^?XC)3D?>!u&eQxf*|Bel?NFvKH2uEI(%CtPumSfy>UfeiZEWtA3zDTsy=(6qW1baz=s*Th}3g7Qc zB#yX|^F7Z**R23?C#=+d;Tt!&(x|={i|$&H!2tD~st9z@ljkEDeKY68BO@UyE+V~| zv2`KycwE)U@}}tj0(>&*cc-ZzNTTxOR#C$Jj+MWD0ee|(p*eX~SBu~2vkfdMAM6Oj z69onLD&-GbegwxL2ZO#Y6#(Qg-lUWM9iCY~eM|^~W*3MvL$QX|!XoBQ^gQ z>wOu^KY4^NzdIwulNB%hVP-J!Ft$MvkfkGi)X|P8M=%Znr>!N~JaTr`U>Cs8(E+gA zcF@Tp&$7^Mhg~x;xeNK=3x8x44ND@dVpNvWFPjH$Bw|G15Rkfzh%Jz(AFx`^vQEim|sXTg-t(>7(f9hl1`ZPbso>X){7HS&M zraQ=c_Eu?XQMNBa{&)s!QRub3Lg_13(|uy;WAWDI_=LW(K-=Mcp_2o)@vQ=8OAo>o zluzyv;cfv~-Yf$0>soM)NFb}hjAuRRnw2edxVF$PkZ5jysdy(rTm-x8UMt)D5^Hso zxBj1ogR*8obME8mA9BE#Ujt=40oAew!22&Cc0R4~|8#m-SN;BO`-UsiUjD;6`rBbgBxXi z_`Mhfa|V!MX(GXluQ$2gNuJiv)dkfW=l!iicS1-QTP!B>5`Ne#wbIG9XY4 zsPR$_6Y>jt(HBJ`JU5UUYieJP7`O?ja8Mc`h>?oTYFfh>aTW5lVG*d7fgo+ob)?7> zkvji+6(9uTMgq$y73Z?oMGh(GRj!;Nj&>uC0Pj`KRVN1a%wHAPGWWfLpBi*sr>NISAuI>|0`{ zzCJ0rUJzY@Z``89t2h|*T(EoKKm<<2f{l$H8$Tk10w0Yq={#VD)ARFX6a)k#YYOKN zUsH*_)A9tPF}pf_H3xO5nyCZ{PyK%xL=~u5$1OIyy@mfCtWU-a-E1xZx8L2Ny=+0*1ADfIjv( zNZn3FJ-lLJUA>((o7D31eGUudG$a<)&I=388bHTw7NN?GLG1jI^ z0PVpzk(pPljW(RYYkP4oBizg2&D<*;EWkM)PSKjf@TTR$vAPiw`l^ToB`(w#CuTtZGg?6* zhs`3@xsbz?$>>Frs%K=SA;1X9QF{^&WT)+-c2%$!c^FTkg?DttFx5z&icnFNFTGJ( z#AQ*gx^bDWMX+DT^H0h3U*^fc?lI(Y&l0US<4kplq|susVf0AJFs(4I%aWVp z!Ut1%&qL&`U7UYZBRGyoQ@jVxGEMy{)#S&N5Zskl=x`_(kL`8$PV40ncpcX*Q3Hg7 zrW&n!((Cg-REs5h9YF@-&x zDNp*7FDp-Ld06KnNvizd)g5k-I<)%1D$s((7 z-^Y#7uXFgk^BBSe`4a47Ye7euy=oC(Ru;7`bRgyL15@#Di*h>Uvx1=e5(uXZ1kFRU zjF_;u-%$)>myTy6S!K+d5vtKu0sjU+EKtF&5cDx5)bi%y%>bJ=p>uUW*W|y5?e1rhy=lm&w~YAXeBakt^?pZIiK*I zHb8*l?s{e16vVF-21qyx)B;EVzVqt)oV}c2gOYg5s$40VVS?(`PmAa?^h36$hoIiC zGgZ!PUG@jQ|McJf$Nz66mz z{9cZQ7a1S<85PUX$LnT$BIb?WLSJ3B!9ge3N>Y^6o*peSOC*8c*Z_S=RP&&Tnpv!d zT1&yHIp6Z+Jj7g*F5qQ!bM@Sa<}YM7pN)^U%LndSIAD$XD1ga_6t@L87PBhnH7h{? zGA|EwA@%#s1`qqD{e*>&EcYZCw$yiMJole-2p={`aYxrw1F_Yjb+3d`wQFIy_v=H1i<7Hc5BXr({3HTsP8>jq(& zz!2PjN7Q0rW;Qon{+4{K`%Kdzj_~!-5B%bTn?QM2H%yGvI1X}nR}J+#mf+&T!R$I3 z&X%${bIMcpV%%Gh&S74L-@U+!%6@*K-asR7%x6|0l$2=|1fZIct7p~rGmP|1sGM9| zlM}b|FTM{6Es?v1$(;fTErGk>?4QR9<01TS%G6RgU^kcOT7Nc@=VQ!GiOte~q(`Tx z1*165_e}@4s!#*avq! zZJK~<$Ap4?(~-7Gga z)X>>Q#3jZ!tnGt_72_MsDK09G;%Lls4`(Z-AFWVlFTLU5I>vA|;1BBQZiattyz zPF8s=^VPkev;(yC1kag6pm%IbVMI&R!SxjW2)VBcrurw0R@sTk;W|rm*9iuVZCqzO zIpRwhw~s?!sTNwPN#ibX=xP-o6*i^Xjs4`6i>Oslw)=aq#0;^Z*%TW!mqJLVPM2vFI$pWJEKK=p20mn0v8O6bfVYU4-L)bmssmy%A!eyHZJ;NNisc+U;(zdlC z-x2y{FVrSC21)W~myQm0SG8|kc262}Zo;RcSqK&PfI-dQm7EcC9_r1tc){_(W6L5_ z*M>(Gw%aEZOM%>>8$TtxscU(^qjCIovipT~(R1tRJfd@P+EMcHWbJ)2Cir=?LtHS6 zpj0hpitR@U_?zXS*BvYHbYVh3)7j#~Mtb{<#Y6_SIoo+Xg#$D@Boy9zDc0_pE9$J{ z24^+=l!_L?qwY)^>_Ir2D7fly&)+9&$?zh)0ANR;eZc!~95ei<#r)?+IzZq*jP$f< zk?=PsDz4yAB9>BNq^pK@-{#h`%8Jl@S2@wcS?B#1Q`08oCnX|Iv8!{xLx<=;b9~`( z=3fXx&hIS3SzFP{OqYniEGJgZs7UrX7*SV@MgJ&LO=2q)Q)fz+P_?EHA_#NPDH1Z0 zL}H=H`1qqBO!PwiSbgJy5A?%>QG?1Vt|3caaaQXw0~zbGqW$h|%M;lGy z8Uim|kGV5dCK$3d+P3xf%eVWZ<0HrM9H2bDj7mU3#z3)wG_jyS_qmW_w0ax|VMdb0 z)xRTXWbtW~RMNwKbs-mPoVN?L|B=p`DxM{*D77rNsfwLQPD3PBF5;AjKTy`ZFt&)# zp#{`Rq!ImKx<<)}GT{{H`Z-=fey}$PHHN_l6Ci(rE5g)V1yrV7;E_EMr3a8{hUemK z%b|vJ6x#^;8r3LlM zV&Nh2-(1u$u=C}5`cX{u3c%dgA>l@jQNqEAU!KMt`lAgr?4HW?>H>$v`6t%|LtT2o z+}|)nMTzbmpKmN|bZB)HHLG{NM07TByF?B{pAK|WkS7%aj-&x-W0BhHucyc?T_}ri zjYdpEv*Pr*VDG_UF8;lZ_%vltQb%_nSle|(x(+f^vKmJLP~nz(9g@T8CLyv2zz`a7 z{nFTc{Bu+)W!4Gtd!f-&DCd@*7P~}2=K?rqZSX<1wQDI>PsUbFvzAFqOl`e#KW=2_ zewp_d^x?W@6?;Mzgm9J|a>1+vzDToCt=-4oA8cCi|M zSLR7T>i@F5HEQPY1KSl;g`4dh?Hu`)^#MXAWuO6afaIv{j;}WZh}_WN&@FouED0!bAN$@q6lpszrHue zW0D7(g%^!gWXXa$PnB*u8y#9y3ie$;-L=IuWMGw@K2V6IJ_9%>FHg*X!sCwMR(DY& zBO&Y5cxiG#`(S|&6jhGW0n>@5m7KpRxg5ROk)zTYt3x_M+jOI70mu@k2W^c=5QtPw z)7(K&L>UREZe?q4!WIMi4$lhm%=>bxGrO@vbJ_Acc(6B#=`Rs{QpT5nmyt7dBdw>D z)gt`9GZa1t_KCey)I)6tQlX>+&tPw|#Z+Y$)68ga*Fdy2{(LuAP+P`6vYmbQOhQDT@ zys^ZXClqyry-0U`F-)b#YIkN5@3W3Ph_8l%ga6q*qiccw9k9QQ+@9@_b}oy1Q3SuC ztpO;MxK6a;O9X?O-`3N6?&ZDSXqAkj;;+7B;8)%8ZxFB2X*8Am>c;wF>1}_kW^#73 zvK4k3GI$0~AluRS#C0<(qtz_s@5J-XmhfCJ=!W6F$nL|c9!Otd=*=_6LCsx=(j2{d z!mjDvn~pJSTSMS?bf{5>`xhHt&Pld{rpo)G3!@^=8~laSVXn0u!oQb3fx`0PB!Kii z{x7BPfA-JT%6gyD$N!h~wRJ6opm&|wP~#AIwfbpAG>%)thCv%_xb@2H&>BS1_&4s! zOUDndTtBbl6^uqSU7ixRN7<0Ae|m8v_2VAEpRC)Sy+` zm5tHwZdD2w=9avs+fps5H0B(G+EGC#j!Yw-Q17FrMI$R#@E^)2wzF%5$0!iym1#th zZrZZS@KgpKrKXZo@l8xT7RjQcCMu**5SxvH#8$RffD$h18)et*xXaUm>mgq*e1shX za42}#kB(z;IJgkIi-e;%uz{{^JXwJpsK5~cVS;B=JHJ3dS_;>B)7>$8i^t1BGlz? zFlKLn4>3QlmKrNYd zSS0GBWd)O^JJtoMJ>{ivovz)~){mE0nlKp=Vq@YJ=OmoIty{L>7jr}PpLX^;jTw!l zue6bQ4hbCGo-NH@NcdnwSZrTz?dWRY2z-zAVx2t%KN69KvDmgNi5+7p)`nL;8;sg9 ze3*du2%h6}nX`0f8a5}~ABES*aGfLLC6WY&hZ`$r=Ncr`303^^;^l@I@x0i7Pu2bW zQK}VnPc2*{11g+ymk@Txz2`fd&DsFSd?+tBRx{AL8FJ>mJ*ZyK%ERN`N%|;o<@pz= z9tEjg-%GyB`Y;+snk5>Y27DIkc5=fs`{Yf!*zZlAw3i`RihR4<;pLPzMEt9>LuvLJ|LsIOOp)Iey4$xivRe(_xP```Xj**!eKa)I0JH zdb-;9Xpd!s|E*I@cP$SsgUwud+bCOiyd0T$c*fGEU5_SXDk0&iz5>KOi#h{sBs%sy zbf~d{IH^un9MFBRN+E4lUgkrtqisjnh+=6@^2yWsf?|Vl*ex<&{2&}SF9G3NT#2!cE1=9X(J zR@dMVz6E2&_v!_Ob~pn3`Zl4%Np~o?(rjU*hj>n|K9x;{Ba+JrCr$5dA)N z9A|PMiB*1B_y$9ppUT$LCf zakk>8E!J-izY8=U@eCRu^?8Mh^Zr+I|LJkABxdL4)k`+QjBseYT%z_^j%M-Pe8`w7 zyUFjBr5pEMHEbo_#pzuz@>c&CxR8WzN%%ZfZUVdv|F-x0XKwhPcIj~cf4g*LRCBDR zH3^_IC^v)RUO+>d`x`Mf2DSUU?cbs>7SOF#91Vd z#?nvnku;LYzfPkrt$I0SEqmw~z|SNdTci~$=$g}8$HIohr!9FI`}Zor92l23j~N8rdLj}pccJ1kK2$Oy;7`|%v5G>>Y))zpCq#xrv|5`@KzVi5WzAE4^GXf%@S z(KR-BdNPFKMcAFs^O=0v8T)p?;%&cjgWw{12`aH$heJo@n#Rjcks0Q8ewtRM@t=u< zze>ebUerBz8!o6x2J{~*!h%nE*x<`=^# zO%M8Ze`96}y|$oTfCX3J9h1kp245%q8XZ{KA>XPyZQ58b!gN_}vzh2s8yPRvpGHalPHIALF;0)im22N%%-+wpio2%M�z`&E- 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ŠmD#U&8&8%qJ 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 z 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

    PMDoRTR=@ye$u;m}zO~#t>g+WaR#lBCRJj z@f(zXlMM&r6H~!JG~$VuPk()5cPeQ>T7Qox4iNQTJeoX5^IR5T#lu&i?sR_Un2tOK zA*IK9=0?FrtF$$h&T!#ceE)=xB*N>sTF-{STQsa(qO ztO0UT_V-=z1P?5ieH6Og5DEO9%K$f~08e++$cW)Qy}8qGUh|Dz2?BU$cXY>O9X!^( zxX{!#z;m3MH|NmvoYvaT;kYXF#ToHAMuC_pj|kfb!=@pSoUcC@zMkhR^D66C(xgXY zGHD&qA8KTx#&q<#dqcnG;j@;70I^4$tvW5>mRoVQ$SnLwLQeKO584Y+b)%wO`PRm1 zGN;vhfMPhZ6f12ZM<*%jFVD@B(&5GY*1i+*8}M$tb(%nl=A^%pb1RzRB4!Ev#rw%| zQL4(1!LZD5Xv|%ocbfAORBfUP!Q7Zbs=)pv)5MjfE8il>kP};u4gA^s?c`|*#&bK( ziwd6OgxWav_2Hdh8@r`1dso8Sib3NR!*lTI`T4VVu&lC1{`A zr+JHpL0iPL2O!tCe61FCx2*33D2=VQ`#aqHJm{}j2!kHo2kUfio9{=JCeOPsPS?k)v!F>+b?F}+aZ19R0xm;nR|x_VPsU=vUtv1Dje_4=AO$x*HhuX z#Q~GeQQ*Hy>au?3nG&Uv03w%#&~S0w3|gPi@Kmz}i% z*j{}`wwU$32Fv)vvr^90vF-5tR?nL^-Ry++Q+K|IGc&vf< zPfABfPVJ)IR%VA4c~%r7Mgri?DpVa{#O{>ap2j&>R*8O51l7 z(jFA?g&x(hE7}vXa2$LIfI4ux3c0I?UgPdp-i`@MJ&Xk`LzBoe-zJIN(*frP0#v=4 z8-S{ZwXjRFo6$29~mi%l^gbFUQWT zQM6j8*psg^iH=ov5O)z=DR+hAI48*Nzy~FP*hnsc!L73-+h0Ong?fU`9JEjM>F>(9 zT0<@%d3PpWTd(NIT;oI~OlpTtf!th`f$HK!Lrv_#u#9g+F==+=_kX&E$a|zJYfhHL zrX77M&X#fmPDX^yq6Zgkq>xicD3 zeVvlJSKCGsZ_(Z}|B_;X6I=JIl*R?)E-BN+utx8vsjsad-%K&m>R>37nN4ksC^+|E zHVO|bd188@PB!j#QZD>AgztQww?9LLZ-8X(r?x2ZC~|WAo0WSgj`+WUi@PcK-Www! z>Hvn)+IhcdOs(LJ^y-1IF#>$IL3bFla3_puyi>lVo|%fc@eJPCgv5kbB*)k7o>(xb zVj046^9|P@Wy0cCBx{v$C<1#v`e4%>dpr%g8^8Ik=99&K9{us+kDyRODo$-CT(C1;=bhW6~!-<58y$;Sy2sbWz3IWl*?UC zzHc-pHPr=zzQj`q@bExoH0Mm3Y}l^qc`!dC$|JZ1UF0RR)zbKDc;=M(H1FTtg#M4( z_}}Kz|Kshz|8o->o~_+4w-4euh2Uco8oAm&?uHnVr|F-9F(hK-ZpDS!QuOYQ_-lJ! zE)ZM#REF(2N7jC$FF`?=t<3=yRx?n5DN~p7#Sk}MTQB~MSl?N@^6G~_&FN2nQ@IBJ z=MhWF_+)rIp!)wESI_m|boKrW2eqK%F|e?*GD%OgSq4PrV~RTJ7Si~usPV>r;kt#K z#;Y9&!c<+l3b(n7RoAF-fZ-ePq%OMxMbc9V%jcu7MHUnOnxY$~J|O3_k$`W89`&la z$Ds+xg!{N2Xg7AvyU(-F^TF!1s6hjPas&17!fk*8g-k%U87N~-38h9AvubRE6Qh9V z{9v&u8Wv=^9G&mk15zxT2|cLSn+@MB>nB{Q_IKir`BBz_oiBV$W#%KPdGny4s~@v*B1Y8 zag!l_JY6F}WEUtqStA%}*9tZYA?MeiII#U2_aGs2Ckz5}2l!XfG)^k{K0!)ZBV%A}&P^_s<<>xo=D{-q zSiQ%M!tx+M7U~@am{&Z57=NS~pC)Esj1>mtnS2;QA29YlRidyO~33Q?M?({yk zZ!9S_^zLovf*uP$8rx-8dXrQMcb|poX0o(G8N5n6xYx6^1P%KCD-?88~J6aqz#zBXGMp;Dc6Z&5HzQ$hsqUKiJ=9To9jFp)I zNAn#=>DKb-*Lb9JVSNrP3iw;D&B9Ub2?f4gHp3UP&tB8gcNd-yUT@eW%LN0c82nBQ zR9bszZ(bl;6O8H%dpXK&!}4?-Uuoqfyh2Vgx*wni+V06RibZEyoPmvA%b|m!XCM5OO0g0k9VN%E9Z|k z(|1e_nbq?GRgY3PMdQ;|R%`gJjDA8e-=U>y$s}@G2pQa)6Z}dW>4?F(5Qumskl;Rl zZ=;hbRM6ZVv#h$wOSQ}#jb^?>gyiTl!%SG1*+tRkyBWt2 zPQ)y!a)TkkQ=KS}lz~*93C~uTS%)93RvTU00cOFiSCoE>g-8=pLEj#0JClLvlH~7@ zFFII)pn3!Fq)vVkbyr$Vkt~8#cTm`l3uZ(o&0dSmiiaKQ!dx+X4ORousNtc`5W%6j zmR!(TYg{*;U&r{j#YlX*I7S(C*1eDYuIy2A&N9cXv{pTaI7eqX7U=x?$>Ld~evicE zS-mr5cDi*o_Ozj5hCHeR^bouM9BtD2)A8oLoGJu=GW~`^Z6%weA0std()RZ5&9XT; z2IC|@$fO}y(7av@nCTb^i&Wuwi7V&bPZ_Lt*{L1C-S45lj7iYkopb)Ks`nqo?_V^& z|42r*piBEo*U(Tq2D9Qwg9iXaXkqJQf?k0jB!Y!sfuDR6fMkgP8E_0^o@c1@jh6qV z>dhEGfeK1M3lPI#^s)b!s+VbyF>Rn%2p9?M10vwk_FMP2abr1b)CEE4DS`O66hR4q zvOarE$U81JO4ja9u{bD$c~%pOYWyOky=y!)%sve1*(oqX=46;o(4JOUOTn9qqiNqI z4P`F3ZKO`P9T75umB0WjWuOD~6vq1j>HZ4l2JRc|{}4sFG0cO|h0+v20fS|!BKGgA zSok}6)1F{XFIAN}6JKD(UOZtmRUsgtvCw`6^WwLtk=2??acEY{F(89H-rBJ7AqPAa zp4S1AFrh{JA0lyH0H_`t&J0kL^a9}0T?G0Es&_tV-4%Y!pM)9uRimaen%sVA1B@|h z_#-N_coXo+O+)wD`TXv3t$SN8&~)WF%-z}jBpaB_ni-ITyjdEDX-99^t7%#K0t;y_ zXM}FnTnfm2<2s}l-{26c)dl3f(U{+1lOFGTAY@gK+y!| zCmPli^Tl?zET*XbW(Xa4rNvnzl*C6h^Qn`a^O;UIGZ{tA-$SXoDc8BAP}FQIDDGZx zH$=7$QO|4L-KMj!`R7D8EtcZ`X>o0UW=IuU(o53TNkg!c3m^&8baSBFn`i`qP~W*A z0WWi_#rMSzJ;EMyi^5|?LsUt0r0<*6m7A#q&1#(-7sg<|+LN+KHC}>YX&f>8jyIB$ zwzS=L?e~s7Dv=k%mK^Pi?)U3`lS5#s(-Dw-(dQ=R=b8&XXgbq{Q*^hr+$E$!rIXI2 z%@g~Qoux|D2rlQu@N?8|8=Upi4V?4qa%s!i`Oo6eZ6_g`4)e4L(LSa=6ti!8ugyAx zxi8&!3fxNG09cPLc4$^=7o79GL~9T{jYDrr>$TkU#8I*-TQ;99-bwEyKs3Ix$_(@F zyBqycl>6lDP-Np~5UQ=@h65>JB|Io}&prrL$zRYk)r$EcQ z9j*vc)%A;=8x(4m|0vG84T>7fkqTkG6G&>#%wN0n+~CWaC_l5Ekp}!z8Ec7AXs2|P z4UFK@rmNZn^J*WFW!MM%iO1{sk>dYh=PQ%1ZajHxs<$-!(-M86`R@a)I_cTt#` z(d6iFJZb~g6<{>(qZ)ks(?n{>>$>h_28BE{jy0jF<{e)r(3y{4ilPSL`ujIF;$l}I zraDYa*QL@)rHcK3U5SL9?%P%~YY!GfNiCs&VIhPga|Qf)tiQe*U&O}rzQ%;wUJR4i zGFIGQiXN}sI;EK6QCO<&K@S(yc?fhyX-xBGmU{@yy@_NwzQ*ai>OYrB)Y&qxMc7Mc zDM_PKRpENFp%?(g?LOgLF|DwGWqQtLpt(1^-)%`#)yC{V%E>G(gp(^l)MmzSy$x zJol>|OQZ$J!oe{|^#`;6mbBO?`dZrGX?>V~zAFAHjDULTO7C_bO z{zKJkgq;UHc+kZC4^_|g{_HP5oU~*)a|NKk{X43j>%Xh&S$wE^ym@#9H*h=TbH15izhI#EUTKKjp9=KFJD6|r`i&l%Ue=XUFWuZUhuZJj!xn*ktvSBxl7 zpoK`h1FGktG&$y?!r~?1WNkO0B3edr%laz?y$A#E%7>z2AI!RPF?olp3lpg%n$(w| zdDN=2Zu-12Go0YCq2I9pQ-svn!Yy#{`n-m}STU|f(BYDCF7Bg4}UP|yP3rA{3tgN|vjMU3Me z?)jJKZnhyVm;|P4b{Umx-nE~PWjpfUSx?~n#Dx&=3p0)P;c1;&?k=PP$;(K;5zz?* zz0(0jxc6h4;^Eo`KAQx*@Ccgw4TixX zVp^e{l>Y2LsqdfLW^n2L=F>bOx3EWD`>HEgAzX_rx{d65`gNQ1%8H-XAc)UGpECj~ zBi+?d5)Pf{d(O>|ukXJLI>x3#O`e*QGpsRje<74tlKf!Ztcqpp?@8c+rsA6QY0!`% zJ(eHDB#I508s_bWqa2h~%1AdZLr<}rsG0Oo-?9rM=IuY&N4oKm=Q(1x%XETDr|rzG zLErZ*JWvZd+E;B$nyU~xbjc(*%QCX&9oyhRvnklE-Pp};z_xAv{oMSUp(QPpe7p#h z6}yFACi|HsTifPo9`TK!g8k;Jf<>7}Iu{6UV`BgsZO*=pJvb8i4Ru6<&@4TEAIIo@ zj$s%TT*%;24n;crhTwe^!{Zj}Y*)im99fMsNd4F1SL)zgEzE_aq=|G@HL$zSx`^9kLlBcRNubZPrDQ}e1olw@(WJ|RuiBV?6 zy!+;ei|bZH70>lU7)O;f!Q7y7Qg}>;eV|ezuuT3{%hh)q?Nns&P3|U=IWLua0yIf5 zDb6f^cEH_r3(~TVW|B_kt*X+i(-ksGR!8k+cA~?V^}lWU??EpLJ%x&zsb=(8+#i68b8!-!FEd~KJIqnSt z^jrFc-)nb1AuLB&c$O7*$Y;qz+#y-Orp~t@1*X*3kLBBJ!c2(+P0A9HVn4HNz3ml} zmU^FSv5tu53%lF+%V&h5RtUfD35M)$wS@Kxx4eb@m7-=tQ#vM*cKtLQmLxp2S za})=T9P)V^Mh`t+n5cwfeE^XV{erkn{O^(=8(r~DMfN880(Q^^t9xnbbK6@tYxm1C zEv?4S{`o2!z8@OWDo+{LX?+K#88w{-5^_a$u zEFxxK-u^ywb)L}m(&vhcVhhhNlt0Z&FPD49bG#7|3Ke6P&StY@wj_Or*!dChFfDBu z8?>=lWYjm3#c;B%PIQEhsvxf&$^}&`(Iw3D`dq-pVUU4J z-a%(Iw2(r0MOr%P|Dou`F}^!@kY{Spbg034K8kbUA5$1E_w_bw3R?sUIv}hk@{}68 zacaHim24btuJ_fCZVT>paptKMsOU0$z`t(#sTbjld%(u$xUDT!?J6`{CB32|n?(uisynpnJ|E(kb zpN78w(=zfOZXQ_7Z3xo)YUw|gk(=$P(yA1LWzNLSXt3Dw0+I9D$yrt@=3_vD0Rz`;Q15N0d5}AA8ua%;SF#foh{D)>gM?iRl2nO?E}AmFZ<%J zZk`@mV_8E^03L}}6h~#$YQ3Y5pXz>O{AnPKV0DtQcywg7$6)0&(-=^XpQ&O{6ok%3BW1%6%NLEd0IvmGBHnx~mtIS&8) zly|R*b<#x#FCz-fgU^2tb+SjmYN#jyi+!=>!YqCp$q#_@)({tVy+HwR9vT47dw@DY z*#u%VR1C$+1w3W|IM4Y5&Rb4uA>I0b^YBqd#V!H)aAaq9KX#3rX9S#t{}av=05263 zI@YB><=C6iXu4_!vJX}HY~{~0>!^C>!`}5aKFS|n3Z`cP18m>-+f3)`qUkVTP)a~DdRiCa+Zow7?qd(*&#APux+TWO(oY*hbd<^BW z5+~*~RU~oTG>GmLLQ;-=-V)=i4uJEtNlsor;Jj4;oL3@u1uGHQHRX+YxAZ5R7dyMZ z#*%*g%~Oiz;zkh5flor;`RSe-pas{kh6Fha714cyH2=wMw%zM(!zvR1h_aO6G+2M} z8e$31GAMjb1YWjmJY#dGd;dO)=;cquZ`Eaq`M+ z<;4jqM}PVlCw`pj?3HDs5*1>%aSV+QI1jn-*<==v^~feg?VHSS7wd&|NeDS7@K@mhOJLJ<9 zL^~7n?8wGRRVQz(I_85NznXLi7 zYSqg+O)u1Z$-~Vng0=lLLxhW{5XwqPG*vQydf( zp^BV?@FeTo<)q+yb|77sm^xsc-do*QnMa!xlGHXajnERma&??n>vVN=jn=1w5G{Z_5{jzsF% zEPJU5r@CphtmAB=UG}-E@ou`jxLN5qqv`btPx+2SDFxm#5twX>qVrYKgi(iQ<+~Xb zP@xRCrm$2OxU4Gn9Qo3=ulnNaS9T0kRsOFxUX-6J8r z>M1Xd{5o^-C%IIZ8w11BLt4J+{Q5}D6M_8pTG{b4s$#3MHFe}V1*wj`f+6ZPQ}z-z zN2wmto@DF|AC+6#Ll=IaeB@&z-=Gb(H-5Q<|NgyyG-_eyKMTj~`GicYONwDz*K3lIB+pHli{|a%Gv(ef9U) zp7ko{!2>IQCV~KTdpv}XPsb?L$8C$ZYqPg1+cnkZr*<9hETD5DaWeuDIL zXSYZn#ZvfQBshOwYyj*Uf#)ZZif@vm4?*pIlJfP=^fCAZ)fa(kWVK^X#YelXPmx-c zpjUM$d!vE`-V$&x>KHQoM@F~>Lt&?YZaIO6Nv*#h%XH>WkXO;j?sY9Mea!Ow;8M-%lI( zd>MSjj||U|=To0x7vrEs*-t>gww(KP^e#w>;p#6Sfd;%xf-m+U{hFCpK%>DrmJXYQ zS3IJ;viWO)w{70~P6+PCMZZDnT)*Gl5X<fYS#vBY*RbpjemJAEJU@c7Y1jY}CdX2>Z@ zEKH(H3ZHl$VEK7$w<(}b+@sf?h%QsKxKNrjWA3~9`EW}WCr#ImaHv>mb37g0ZF z_DsV^-H}6m&e16R0p}4Nny4)+<%m8}TK>!u2f%qJh+`p3Q&jSh2;gES$@V-CFMh#$p~)OjF4?zxV&;2yJ`MO#bh0NciYZ5bycu93}Q6cPuhNumH(0KxL=B0}tfa+q@;piz~c)YgnGUmqXI+Ac> z#rXvY57?W#2LusF2jQtx=ano!ZKp8KLsR$JZ8@f&@;k8Rsve8nUYx0q? z@bYFrMo3b*=jAPsYVI}j?=(pU_S7U6T9haf_F|AM5RYBi4?52lWcz0QU@_4V3~Cyd`sOK;iDdS?;*3`gcVH1%)iidq?Cw*t;HVul=y^BVGFlLL%AeeHJ0wQYfZS>X4tLRd!h7LXE_<#H~TKs+MmL8&X7 zN?fv>_z~X@V3?w^$wyTn^MRK1J{ubjU9_7R4Pg4ypwf694#f1>+I)|NdXRZzimNH? zy_=wLo8h#!X)~;J`AJlhea}2hdRifNOJ_z$n^ZfG2r%H!MH)t^0DVT<$wrhG1m%g5R*40O6&soosMm7tx8Ky?qcTm;Yj`Re z^>Gi+^P(GQ(6i6Zj1hgMWGD4)f3r@mJGNb@#9Rv{E=Zdd>|uMSYwDYbL^rjAFN8>~ z2u$ffdo9=#PIo0L0&KbQ;@1w34WRsgq`hTOoQW204FN*%;10pv-912XcMI4y7<-o=jmO$_j;D@`8?O9*tW#PJ_0A~CMbp^ zO_~)%g-)05zG8R!WEp9mri00w)sU*Fb*Z4jyc@-}^RBG4ZU4m#r%Lc>Y&;8nN<7o3 z%2$t@yyqB4G#A&69l~oCKFbd_QhPo-j{H5dEHNo=(zW7ItETa*V?%0QSj=Rj>_k%@ zPYur}Nl=dprdL~IP79v_-lSxK3o8=U>SnXTa?Y$Ka}hOmS(O*{CKUMlDi2sDUz$SH zTVYg9(O^}Zy@H~m-miAcXCN+IQmYbjg={UKb8&X^dp(YTh1V&h)zr7e9min-H}>G+ zD7QLcEt!Q8for?CGDZrGtR@UJ?ms7wzaH7~+$;nUNwLB;_X#=@*2;~KFOD@e5%|0O z)JVLb-X1fWi|Rpk_(}DsAch*ERCDn|^Uje2ab{dCY7mbx8t}#>+-7ZzxXpO${C+p* zf$IU^Y^At}h}sEJx^QDMfoEAFM2s~J!n~XFmVu9e0OmYB#`)MIyoxeGsQHSZ$si3G zYt&1tT#it_b(7o5NjOu~M$>TxZ(MHT!eF=(JNNm^QyS7o&2*E_=FFz%%JbW5n*lcy z%2&H8p>;zpx2vSH{?oPV+vsgXAl7IprgwFo!Mi%|)&=M&zpeD>lj9(%%q8T7wn+=0 zeORa-{#WELc#k|G@RkE2m!}};b0JHD$FUuac`Y-5!8p(zPzCpwK%AL~2Fm|qb^P~P ziofg5(|R{b^Zchf50(}Ua5JWd0uV~)|M(7ZpqZ31fk0?flTQ`KlTK}Z?ypuutk^BE z4`NIJmqhtdm(l%4Sw1Mm7GV#i1zmw2u!c{WPS{EB0b6f)_FCFg>-t^#`W?smgKcDQ z%Ka?w2P=OdUU+RUP$20r&4bG4g|vk9;lg9gLJ04&vDm~z{rN|?I*ISeiproZn&xq) zW5{!jiuOnWF!95dj|23+g^&fiB^?h3oQ*L;F&k+gz4)&c{JciQhao?O$$4h)3wCdg ze-|hz*8hNR#-~W%3&cy{@gnLBJk5hg!Nx}NrHST0fUy@(KG|>>zWx27qO3H)#R1C;wkEH zD+|4+JreBdru=}eX-B%MQ+9aRrx(`DN0a*@LqM=qTz3inw++GykP9nikVZp&Mc_a> zqOjFt0NBQ?G<*(O60=?uR99ZPGnGXC~4_S2r;O(GaWJk3o`LKgt zzGk)wmWemjVwA~{ZIx3wc}uTCTU3*X z0l7?8JA-}{l(2X+L1!4&ocOmNg(|TkuB|TO$SlkWkMY~srZS&nmcGZeuFgm*Ru7VT z4wK*Z44JXye{yEBQiknsec)6Z#n1*3e}6_Gq#M7{*WrCvI7U%#)jh5yuo;n-jjnbSf^gPx)W+3!nsjg zX;9xfQPC*dv8VN)TNHfEmMKkaQC5L>vQ*6Jie%0j&q;{`H6}_I)#I4Qe-%W{AW1Qg z{u(vvMUfr7{g8Q7L8fCKRu~5528REs%^JA*H4#y)P(ZBmCsDnzn1qO|Daq0aoVN{y zz^asVqOv}-_^JLSTuU*R;=>oQ)0)}nh6sW`+xQxK2_|;@JwT`o-zuueyrO zy)ua{#UxmgY&)FaOLNV;c4PoD(G9Ex6LzJc5B znPmjAk$N3|G%;f|qn0;uhlRQ7jzkbj{02iYzu{%rN}b02YYI%}_*XZ!%eFzg7Ml}(kIUmNE=UIj9-gq_~MZz6LMZDKJ z4}M_~+&AcS76uraB6h7*qXkw8v$TV@Wd)$aE9Rc-ep(VY`Fh+mg55+maEo)Z+{OXiGkd53#5dm(s!t+DpRa z-kLx&O_t;_Fx7@O2lZuY{X?FI{JT7lQyn&Io29w&|6861Ab3rPHbBF_VS#NVY+ z|Jx&?FRx)Xt%%einzlC46fy0PUdoDR(Lxp*W%7*$0Z@xdO`fHwx2==UxuF*pC^4Jn z$ILS=%^%C=|AX_VfZs%%xKT-gF*#4lBW*FnVMz(Cd>2lLVzwS{|2a~2$x=_j>Drfr zZpx>t=6#R-s|&7u&BmzCo@gLY1)zgSHE#^SY>I={=)Tyg>Pqvq!N%L6DU0E;phm9Z0Wt>E6%EMlpj-+h zCz6=Cm{#)Dw_?acX_pcfzNN72n(0V!(kk!@l zcToY8XdS}HAdmXLlBmfRxfbdlbA>d7GF=VQzJreM}Um2#CN-=BKiAW*al%^M#pguEGo6!U3mZx z=S*x!hZ)ne=42&VKuF+JX3$wcHl?Gr(`sZ44ILSmOOR1R66?Us#au~k>8Y1;;ob%0z{mWnHqYo->#o=0kQY6bwD zQOWEQ9lh2idBcC5Ll~>=&B(`J?JII;?^wSmcjzQ5KkSfo!lO>AYSM0@olGZlh+R4C ze?Ym^30B=kj1cSY8jAez*pL12{SGi2OkVdvMwD$RlTPjKCcF+q-XNi6IFUwIzWG(Y zIkiaI9d;HR+dj{Jf?n1M^4^~MnS}k7knKxOzA0#fSauRtl-^AIGQbtJgb2g*q&p}e ze(5gCkweH8=0KP$X?Rvd847mgw$g^5GnI6XjFGXk;Ho)1TI1Z?I`8sr@k?AuQe&3C z#_otCRCT?vJzL-WM10aKN*S_+j0gnqnnw$iosXEK-X1es)P-vfamoVD#5 zv10Tf*wESXHlTeSRECCR^bB_zAvHRMSUe_h6Z$7_QLTH-;Bu+(abbEs=M-CcZfP>+ z+%ao}rBl=jrzo@+MFoFf!uE}(g*JHJA*bccFRn+c54TgRKpA1NIf2(y%a=&1Fm*xo zTdONTHNKxj_gCxeeRTZAFujs;sE62e3&vIq$zm-~n_n>>CcqJ^(a0{}$PBl-*8k$B z?C!c>sbum3KH+hRpN`^Y0q?F>g~LsfY7Vq;gdjT&^cEj#B#Fs%mOSWSfSXC4rw;uE zFJ$`58a!(90lRe789$)-c)!Efe&rf&hZ_F4t?BhIfW%u%;@31l_WcuK-oLZ&e{X^H z<$rIWSk`og;;K|SSfH!O2d}Y%2qvi!rTWc( z?!@4Jf^v9@+5j(9B`L)pPRxvo05l!11uh9*mRV2E+87$|sY>5<9Yd&Lc=bGE-`Vs0 zJi|3}-+h(eBbfjgO$IoN#}dp0h?mMmyKGl(9&1udsBxL57(uU8ab6pb8d~U3v;HY& zEj?>lBAvaUv!LD3P%FHFWJy;h$P;t~D#?CTanoFxy_eak8( zqv;!3n4k?}H30MCZ@V?nsJCYoong|F{Bq9}Ehk$pqosuT4wnNjgZg%+bNdpAH-l^l98+vk39KZuSu# z41tVWrc9AE%2q1^)+m4GCxQW9YPc5_w5slZ3G)t?ZYM`iWm6S7AAQ=I-OmaTNvfFM zg?U0lA#7+AzX|ia4F!Gw5ayM+*?|)MLij_NClgD4_%C4|&RJ5)6zcaO&t8pUgA5C7 z@ecrD9y5lK^(r6(yPTv&l{!7N6F&EungfJ+_2b!e@4~!7PQ7FJy}$sx)Krp?{dI=% zR!T882kYJ0RO(@DKRSmoeYXAjI93Pdevgrv9dVHLy~tsJFwflTdOR<002m<5s~y}7 zbE78`wzIlUvTXqf^G)T3%aZ|GfEi71qX-GNx~q!t zNvO`QK5N&6mi&nby?$3ya3cFvuwu`M(K$x6gTgqHLKH5SD?_G`VVHc_t&0Z|h3^ksLzu3naN_By0tWBNPQ|MhFnya93Srh7y9od%ffYutP zKTO975QvU){LsqVR(lX1(!snIBmF?&ZX+E-grv8V<--8Iphrd_9F-ouPHOjzu=vQQ zC4wU)>=lG*VEO43{=w|iM|cVUC&arP`1ZSloRbkq*QLCpum0jl(`Tg6f!bfT3Ff^v zAtcNNi@EZaZECeUVs)jimLRFtoYbbdNbCxkRz-RO$H-TnZss~caGA!;7&VJP8oBZM z<+It(Ccwe&L1FBPFKfmm$p>hZ%C6CsOD~iTIU%W!5huvi zV^_yof2PFzg+>PcsU+`@5d4o3w^#j8!QKf92pBY~tO5x1DFFz`Je&`(LR@_ukLwmBm&sG=RTL z^0)z#JOQe!i~lRhvq!{0LZ$q!6@&3?%z4h+U+H4{#8WOTcilW~$?{h*G&`nN$oqlt zdp+kr*k=4qN#5@PABof6jqRw!rK=3+MUnu zxX-U%GuFAJ)_5F*k1B#cY%qQVLZ|luT*49G!*`WLnor+zGpVgR;Xui8Kr-!Oc~mg` zV23){7j;c4r(rO)dkQ&DZ9Jz^6jz8n2Q9LRwd9~HpLB@m6ZS90iUWPJ12WnW=>xLR zy}*aw+*q$N7YpvfqL*hE!D9UIgICi%zhJB()&ngJZ38gui^uidLYpRM%K*YH5%$ z84Xg@ikfHctAHT&zFA1ji))L6xBk4>>kga;C@&5bZ}eewrxyI0^ma&=^rQ3hlw@^K zLxeMvC3m|8?>#7CP=T9mI_5AgG#$p{RL1%k(lI9*FlF5bCNsPx7Kcz=#&zF<;cgAr4bwCvrrWbz0r+Gr+PFRV%s5+V->WqcNsq zUk_E%wH(BY3O1W&gD0oG$Ss+mCDY`U;m^_mk0AEuR@F1y1dg0bfWXWeYEWEmYEooY zgVn6nitvT0T~80E`5+#v*+}nfe?Y;1u-S;7`O8qd=Hht_WcnO@F&TxqKb|m`T1%BB zz>>#4%&C7EPnUIEmJBufEd47pjYQ&c*Y8z4%GJl3A>*K_>MgZ>Ctq$>uv6(a*d{RG zfMpn4bJ11&w)sJ25Mda}@0tPU%v)GaxcJCQLw}Sedt9u*Ct!KY_CgQ>K`L%V1k(Vp z`cSz%f|s417QRl=pWYz>xb)62Eec^+XwNL7QbjRwv}ceEyzmT}b{zXcqhtGnxMgmE z4|y}~eo(c;$_Fk4i6PQSyehg<=+Uo0*tCvD0@v2@u8U2Q^kvMCF`R;Zzruil^87hX z0c9eh%s53s{phF6nLt3ZA5!^gN6G9$-`fn%Xg^gpqED}nlUQM-gpweJ2)zzgG(n{w zb3U&iAxEm7We#Hg(rJ2q_$LZ7@Mhe_;mCuk}_d#SjN1s5ct=NlZtyfedu6UI*s{&poR%^x7VQN5C#5 z`uoIF0nL6Lp)@1Y(id~aflLK8{NWb&AG0Z{d+!t9dO`+gLu~Um`Xh_@PJCtMj&J+} zMwjLq@nNnib*`3GE$e4H+?|w_pPZG-n`aj}*9{(x?LAHGrJj(0aEfZdj^ef&F!BP| zCIiTUN@jE{4{=^&yb{S&V7@aUS{K1?t zv?O3Aoh4R6*IKi2x!i$<;TzY^edmr&DbG&M@${bL4#ONE*6a^n(3pIHAHHB7yQEJG zZy~-5LoCnOd_~S?Mm8;B-LeyovPWhci;DQPEN?t_;1I`DZ?U3TkYr+e4pvMa>q(F{ zVZ`wjF}K?Z2d@hj8wlf?aNDb@Rr zdhnNKTv76P)1~j$^a#ef52~NPAh?AQeefITciQ?)>#h=;s(B3aB;(QB+mYoa?w#OQ zr;l{&q%BqX94+O+MBQ1J%Kah910F~0hXwGKcFPVt)Dyswmow20aO8FCIeu^muEGT~ z8V~?D^1|L=YZc1IyCZLg0Dn4P z`!`1(l&1?8@~;s5WowjW#X89wA@Cd=-I5j+)a=k73LWb?!Y_q?6&AnLpBZGb6#c-x@0634mxm5BD zGv=;;#{=f%_ET{g(XLrG#yCz@CRfr!N(Kvk+eIZ#uAAm4(}j_Ib;uaguP z4*e{MW@FF>S}I|E1g&5Xx={IYh);HU70Pv_hRm^JbN&}dPkPv9K}aj=7BNFWAi0UU zJ}+4zBOn_$52|~rl;U1^msTlGZ$&IW+;B4=%?V00uVYvQN(8jxS(H9NXzv*wJ{dnA zEQGE(8%RYjw20^S;a**DnL*HxpdSjcxXV*w4#%Qi>L-F;QZ$_S@SZ`K7*ZM=ijkY* z#FiA!%)t-73q*+k0@3o)nEdi`wYn+9>cass2;8s9CK^E;E{EWO}TDzaAd zp~W1LS>L0^LhB*h$og_S`Q>P>;(he-5vXe!MgrQ%%WGW}skQNGDQo|0PBEHhbfmW~ z%Wq~c+WCAL9`q9X$SVWWiwKOJc@t6w)#gapquuDUIr|0@(wV8#j*2B_bcJj&;T%3y zm8c&BT8hAaJVzYxxiIW*R2V|D#5_uNG->yY0z`ccO-li28V4MH>%sPYogZ+O_7h5^ zl)P|xvOmg`kc*$r8>G&gEUyPMkGEx~EKYd1D)qF22l(w~HZmqHYm_szit|vNiqn`c zGr)SGTF>E0g6UNDb3Rjul z-^ErGtJ>f~y5gIyBn4`|P>gJP9AN4DGtCD?Cg_1l=mbNT>S|ZJ;p5l!ue8cn)gO7| z!$t9$2&!I15zZ@m%)!}TqYQ_~Be0i*A~{~__x^GO-87S4@lO?bfcXD=XTlnPY(B)q z{<|XY8L?HlKL)u`4=kQ?m{B^)b9mtfPBVFQ4p0Jwo8XXAj*F6;YW=eD{r~EoRFP*! zjQi2vyEi-RhkpG@?Xi@<1C#MVTLcW~aGw_t|6DE*TC;@>VFr;2#ipFakg{qa_Q(dK z!4ApB)HRuer+ft!WqgJ!a#9t4AGP5OWTu8tjWSL+L7>H2s5!d zS=DqH?U368y4PmnE^f|dMd9^nJfT$lq!^n(S@4|}v6AE17;|wJ?3jX96lkGw<&FW} zdb9_6e&iG7$(tu5b$pW6+apEfXm27>YoCq^-ADoE;4c(h@VmRLll#PvkMVaL^9#pg zr-8yiT%@1ZNGC_(7m_B|bc6WN8wubSaEYuaSY2}k69dr%KVonvZsED)2v&+fB7Ef%Qv9)SD^C1Rlj8VG1iO*)oSEiXZ#p8U=>3A`a|B zgYD$_P4XHt*o`>sNpGmsHx9t5op_}7SRW-b)FURGQ3-i)un1fpgS|as z8DeZLF0(ld^hGo#7usN+U1HYyr_iuVs*f~qE7@9SN*P^Z)J`*UHr!GfgNbQ~gO*7#4ET%q zn0qNPvby-IR@~BTqk^M=B7gQGcb(B#Ekx<-B~0bkQ_= z(lkehVf3GsfJn7hH3-3YEiUsoPgNeh|w-6?8&!7JSsi;nuFYQpBO& zgxvf9lBmI0^M=$Q=-5%u&Iin$=Kb&~V?b6h^m!Qmo;K9@q8ptli=jn=q!y8_Ay-@< zMii#YZh;yRT?qnRVd-z)=3j=q6g?G-lr5GUKG)AQ%CJGVy;z$`d6Llpta zD+`>3YXJC_tP0sZtMk&<^{cCh@H|t70@&cHkYKZrYk@#c>TE=bogn?D^W01y7QPdgLH znzpc2xCalSlLUW;7kaBP>Lj$w0vl=AzFIuxt=eE0XAUk<6}Bf(_KWu? z%ODoVHFrv4$GgKXXu&+aq929~aEVCRIM#Eb#jnE*3V@!NBE}pR3;UxBZDoG%VX>K~xS9xweZm6c#^UPvEL*X5 z#wMiYt6ZtZ3{%%H8d}Qz8&4PLW~BT?)>Q;}R3*2&RPQ)I{b^jdWArRhqmHKCPb zJ(it*uph5@GEMAIzfQ4s>NKfNV2<^PFS)>`dRIFu>(+ZV_t6fMSO_L#D&vk_eP9CC5*C$sSSo|y=h>d`S<;68=VFQNt z%4-z7B*sn|8}i@+fSp4jnK^CM`i!AW&4MOJxpmBSac|tz>FO1&3y_}g(b*K;PA&qW zdY~+uk8tBhTPuxMGiPvl3S*GwyZjR|*Nhyfu=YGuUAgKVvh3UKx%bJ1K5Yn z1D4j)m;F?cqzo7Pv(?t|0aBuKuzl~X0{ciPH1(xn?=KY;->c&38~#|NPy%5A=~`Mi z=-b#DTUyxC*y-EaY5o2WyWb8bv}|?k{tc1*@6(CDvUawp&E<_gP&`L%UzUIHJ1j2+ z!yBgaC^q2MK@WZ}AQR#qVxE?=oFqOL(M{ul*7&V>IG}*10pOWN(+wNxMH3L`@YmTB zCcs_H)aNMl`10O7yw7$14q98T*+wqLv=x&8--~<%+T8cX0;&S$noznZHkNG`?wy%| z8}iwi`(U3e>0B~8th~F&*NvrT^6hx$BqJw9BVIyC#=ZAmO|wS)yuvTmL}K~ZL=|ha zK#VpV6feAL@F(dMH2rMo?H@cwW|Hh~Y-Xej=53szRHOsoPC!OKD;IO9ca{Z)VyO0g zKUsinPfo#%ZhnG?W@g|AJCGd%*x^*SB`$Qu#Zj=h$&}Y%Q6wLvEe5OlDX>GoRl@dY za-5vTa@&>HhIVrEVguWC0<8*Eg$6DpDXi*fccP9H$dp)q+Ddl3h3=9BKN0@81el_| z`UA8hKRrd$m8vS^Y5*P$n);#b1G&qi#}x&5)T)H1GzQ(42%C+6$W6%kz?|f~@4hqZq4WM(5BfaN; zAZ>IUjz#IG>>1_#%3nqNHoORJWv2wI}HG9SNrWUEn2ll zwiDxap;vGzscI&6ws4&x-9pM;c=YPp9n+pgSkL(}5~~_3-}ZObjs^0`-1~#+_5*;m ztAfbKvavXc(s+D}qkwMjmUg81&@f87&GJkNVC}YDEbzv#?+$T>?BvFN1vNR=1+&g; zfN@a|o<^z8PRNnew-C-h#Vk{cgJa+uH)p2W9HFEinaIkN>ouZPJakfK{4%y=%?Rob zt#)d=pO153FXig`oVXku8yRXi8i2WOaombNKXzE3T;@PGHu_*E3eHlxZ^6-ns_}E5 zNYQ4K(m^{FWU#?C<Y0H_@lGXSWg_zkt|*`_eX zb)pakASCI8XP1*$@rZ{UZ11SuB$)qr(Z}>jY!e!mj9vC``r$fa8noDSuGxif4(W%4 zs6g(K*$M44uv2B2V#bDB>VeWxgpwHJ3 zY+s(T1Ut{a72JZ2cFYUZD>V*RSj=~*JS8_>4(BHx->NujtX94`J6qNutfxxmRl~3A ze~b0zqqv<_1d`5%Z29H@wJ)e|tek5k1}$Inxq*urB{aGf?ECshVsX@~Qr8 zq}zGPb?|VWJ<2gB`d_uu&|~h!O@M3!{Rjl~&$97ZBz6XqxpV}%SGlDUl>02ORM zMblJJYAMSx<9lC>nZIb2?$VwXv4^Ojza2J zxb^Vf2sf~qr$!W8vgZRf3{cm*2B(7-Jkuo&ne+?3;_fQB8Rirv>vFZ7q$b4~&OK7` zYHdtbl9neKAris0Y?Kg7?||L(zX7{9s7O>Kr7yzJFs_|#z7IDFkNh1Z zc~s@>m_MyJ&>|D!>jDV^w5!qqO6iv+p|vqev=>p2lw@hJLO?q~#X7QC`i_K4nwHDj zeqy9>HWP6>Jy;<7#zfU~hVYsZs;BiQY_RJfD4fVHK6nIO8OKC#0uLMP@SIIFLZvk} zG+%dWRv#Enk+&BJ7AZ|ZVA3) zN-?sWj_1{gaoG&P`UV0D?>G7N83&xh;FwQq+DHV&>dP zOC?=gO;F&R`e2aO8tv?{WY7^p_hWQ%B=O0i;;v5$>0uOV@Ur@FWXA!$i`2kaWtbcp^1*a150So3}6 z5^7`YWlDaK0RX$wmghGzB{Y|KzB_851~uN8U+IrLOykN;W@(r(Nw~!$S7%nTW|@nY ztPIjn?l_CbF|F4V^Q4Z>dgB~5jRMM1DFkFUXe{T7_X=(H5n7L(np)`7^8 zo6}=2msz;5bNt>gr{4u=9F6>xyYSoxf^A1}Ee)$rYB=uEHo>?*Pqf#aIRYApzluS+ zP?~|cy5f9rAq%&l0Q9rd9w>nU@VkAl%@FBp{gwj+%OEJBM86LWXKE5xetO|XWx;y2 zTMJwy3Tsx3qxmW0Tc;utP2`lApPZrV#6?D-B39Q$=5D)f`;HZRC*wqzG^5BpC7Gm* zQV<#n>OR_*NwGo|LwNcNHD=>HRwJ&8B94DU;u6n=c7QyAWE@iQ%+dq8#Hc4ELtQ$@^yix7xRtq2&0X z*!+zrxMJ(s*8Btzr74(kbhtJQlcoj%d-K4OPdI@wx`{JQ@UC3(qW709<#5I2N>21Ayz&(JFP|Apd~t#*4e!Gy!m(9r1%Ar_wCf zMSFfNVMl=~YVg?f1sG07Kk8beeihID z{KSV2Iw0-&={KV8YeIwDeAD%IH&sQjy)nv4WPbRQcQD=O)sx8N-+?;XQ0l%o$}BPB z_ugST7fEY@0+vQV>5y~gKHK@jLA5es=aC3d9|X{j2TBkSkkA3RJ2GzSbc_R;+`N_d z#$XAjO0l9%$N2DqU;>m4)c6b;484LYpN5#e8lSRK^?eDTeWIB{N44M}HGC{3p=JP~ zt`vxrSIha6$VeDr<`32vRF??ilMYJQpCuS`nO*QZg42{hj9c^Z!*<-Kl!0NuRpLJqA>?_OBA%MbtPsHjx8*y2Wa(%D^MS zq0Twrdi}N9_+dUQ_3$|&!B&3;FP(CQzIM9cKr86W{oL6+Hc4u?m<LPL9tG7>m!f719fzUfbNNX5>}%^4V{z2v){-O zVd>w1IzaaXkgdg-x-&JlpNk za~QCOJkNf{{B$WUQUxWJewB->E$QWY1?*nb&hx{kxL-a97d)SvBmkD9-;XlqGBs#T zE%C35rwvZo0-1B=XnJSl$RFBjbh$4AHeh?IO;{g|rqEFWK9_(h)zi`uq(MUBpktlV zy_XQzdzZD}H#}?|?j+896tlFKyQ{slPk5!GScjNiwD^W|S+r3FEoldSX*R0#p>OsF zJR#dQ=^;tQYv;~Kfphwq7q+aU>GkX5PUPQ#I)(!7{b>utC4FJ5wV4Zr)aOePrZg)^ zi&iU07{kw!Y+(Cd8)ut}A0)El1}Zfjj659&Ohm2A1r;hfPv6R{1`C^YJ`>ftK1yi z&kXjIQFS3u=ZG)BW%LcUQw%_lY!yABA5sfjCKc7L&JZ9boY>;nC``_2UuI?C%1OXm z3t-&@rB-fe^rdG5T8Jskf|OxO=M0c4^YGUQDlB1%jhZZkh{KKW4|&m3?n~+~Tz&)@ z$-r~RLfR2W4!0fk+S_-=7{RK-xRL8!bO&3rGH&Cu0Kb3>oH`Y6=Lxk&&8&nKKQ*^u zQAs!8eTQz31cLqUHZlzyXSQW1;Fiq5B6 zXZklp7diGDR2puENhX%W{bU*kY!XMst>w*lNaR#I49&8CW8jvQTWt`-<4TGZMO9yS_G`&7DBp-!DZ+A?-u(Y211{1$pe@Iv*Ne!O(y>EygC>Om$# z=f@_dY^JybFuPL89$ZO%5Hd??Bhw}h@9|;9=f~EF{;g_yN*s#T_?gPxYX<0M`m7du zI#809cdmG@E0}Z#cFw2!{9^#QMensrr$_u34qN^7u^J99tQw=TuP`Amx7f2IMNlsF z%|y<}ZQ8JdqZfL^Z4)65W^}72G#AC5bR=e@7j?!mMPET>XsPh$-}v$E$>Ut;s7uF{ zkNIm{I3|rffeykc?P>TlHV)j9mH^xNJ6R4acOEHoTN3Eah2d95 zlW?}i>RwT~*#(ZU<*ylk%_I0o0ayT5j5s-_eMy^{IaPjjxyO1G-Kf!97{(!BZ2Qr0 zfzy(qe0eFVJt5;xp}CVyJ@%UNvyGdG9krtNUKq{42@eUIr)E;AAZ`d?XNd%)}|jY1%{X$ zClzkv%RovUBU*&rL4*N!w?xI<){4arRo=h2`pczRwZd%1djav^A9H^n1^;8r{V(;y z8l!xWALsyMu6wrQ{qWdEce@ipwDdCVM=>b#G=E>mMr`$HRnf$NPFHXSO2?3FnF zK?$JR&r7BieytnNpd6QreP`d>ByXDhY$nSkoP7 z?}aM3-aL;cj)fU_mQ()n(Y9i!0+Rs=KLJR1ioZ3%|4nL6!VFOu31|5@ESTlkKBfTE z*}Tn~x5Doy!qoRz!TNSSh)*HQSSj7!^uZ%QCc;5m&6v*7)AJ=HT%&vxD!vF8I|d8@+j{vy3Sdq9Q3S zO?7GMKM}}0=o0KqxjjUzUq$AhuDNIS7d~*Ky1qAYQTIa-3O~9t}^K#bi`IkWl*xXsl~}4&3yjB zdE7vWwD8cISlL3w@|k!My>ZuXTy}He@WT@s2*{{=Vo2al)&~Lyv{wo$GMi6$1mGt& zlq9%=1J>Bka4p0`8i+ozE7rFWq3o(H{8TD1o-W1lB_5L|_qion3eXBP`8>$yfzh09 z@fWqVi3&OBE~wN*t$PthnahO ze6QKhvIH!rIDI2@gx`~9}x}-#2?K?T}4D)(ND9}*i&1}Yeo`ArbVxO zf@F0&)J&AgsvO-DQbYH^*13<-_0y$`btZk79g-Q=sgpa2Esk(fCM&4#7anALKr;22 z2dQ@!O%Pf+cPXE4FANW&Z=CvelCVD#F@kKr*a*fDF%AyEg9)S649jXp5O9!m${sy) zb-em|7h!$v*ZK)oOA!(g^{ z7?6Apc*LCNNea>9(81m%g$X(UHwO;j=JwbH znqQRDib`6M1b&%P=Bkq45ykW=o8hi1!#(@`Br)1zrPVT<4}oobt!f?vs?R#IA?q^3w0t`HV*eqj8-X)9fIu=Ryt&4e5nA|{JAb~9anSkHh6siW z5!%;}HqHlP0-e|a(cUZNkfmydN{s-aT)b-IHlQ-+ro8%CGVO=KiD%wSOdPf?ZNg7? zcz|I;N`$yFgvlKra5v_Djr5ygLyob){JW?Gb^bos#Qsl!VWYKKAVpS71Y%v^u{cGg zWz!04VjzTZiZ}AuKrEVR&)uZPZGR1&pH=N}!sl~|`^Qm;GQ}Aj)WHDXkvk>Sg1|@*mX<=(hp|__~L0>>Ne+@@Q5+qItG!O77w5 zL*}#nWQQjG5SV{N3yc-J^~X&}o?)P>C+Iep&V;O92a0e}VkDjvtcUb5&B`N@Z7*8U zK<8~zj6`jpAook0z9HPFFKZ4|6|yb617gtV-uQy(g-_vaI^)8KWGZunr8g%%b0-yn zf0-)#g~oioroxs}3JOo`T-kmfB-%wiOR;8#DaD0SZXR-G3ag%;EMGfF=34N{sl%39 zYMyQh4`iLnBOA9!;)uOtkP8{rq`FDkm24?`$T4c={;Lbk|*;$(6UpC8dcmaHwDdgh-PYXoH+=txVhd7c96Bb@DwBYw>!F6SUd_-f# z7nWkv7EyFVP;L1p?Md`m#;wL@$%X|VP1+M*iRE)JuKt$g;3FRsHT`2(9CNbj%!0*E z8AI+I7({$uOWN`+Z4b4pnPWm3REEcsvwf^Ism@#gibH%Y^Qu8|pJkzZzc#+{L@oXsfxz`}#y&uFP+{ZxspszrP5NwwzEC~A8LbO*A@cQH%a z5n{!(#pO3HD#itLqfggtLi1J}TSYj^emAoKy9bmxK$Hg1Yruos1+knE>XrxE-s0?- zI&h(L$o5Hih~0_+&cbf~G6Ghl9hF%FrrQF*AKBj@0smvT{ck(m@ZWa0LXN)Yzl2Hb z4m4e2WCbxoznGX+#Y00hyPguuF}t^uxaZL94*-iH!0qNR7BpEYrVx?GZ=zuZ6-03h z@P;0U;aJY6SMDE_{p+S7BS~2baMR#=cMm1uIoNt>nlIqKF3sR*>hb4bXZv4hyISt;ckx=%LObCHjg`xyJi3u z7^zpARuL-=6F{I4Kt)05NWegf*>C}-+|`k>%XR7kSLpcPEJ^1SE_V)ZKhG=funMr{ zs0#?ij#ZV{W!t~Z$9|K`tKBjXv@ec5Gpd6BUbMIFQvtr!FG1`AUF zi*kr0eMNuC%4@O~ggL6srT?y5LuDwbT-Tv63_{QXq5<$5x*AV4u2hYS$R|0^XIUFj_9_Y+xL#|7^GiAIyULnznoIpC5Ee3C zA0&v0uUPCCUhohCEqF?)SwsV!zs|+`q@f{VeT!%VMSr^@Ifv4PL}WO7ADq69Efyxq zOBiZ?N{PW*FCJO>N+pecufee(n-!=D-*7V&MBAAU!4N<_F6J| zP7X|{hH4Y86MWkgYv1NZxCg8IF4b4=RVIolfCC^3>y=M%WZ?%AbKsrb1{|A+FD#4B zrg0mxxe}g(QW@(JHYWJ9(wOUAZWr>#4maTvp~S_TWuRLQc3IYQHsa!!^J4n9m~jSN zKJe@l4e%T$`snBymbIc6-c;|hGeoF|o)fMOQ+xz}BX2zs+r2bvl-`n>>s8BKON;^I zoLkAmKcQ?R4qhRW7+DZ#pwLUZK6_|uaaER*epz(l5$Phsf=#y;pB_{&Qsq=)Nu-yW zN|Ux*I1osvDu;AtB~O}_VSUGJwP;JFmqL8KpyP?9-y}Sy?+f6UJ}J4HJklSI?!gti z26a=3?ieTRhG%+dNzp*7k9cpoP7WD#q@1v^c86MN#WaAeN>fElRu?KeTg7jwk**mmHq%IZrD7Ds+N=A93}??GQLP)8%G@Faw`)m_FPZb=3z3D=z(!7LAM!!9h}c zFpx8Cmf$0Aj5DLR0pF1c)qaO2dZ}q7aje$;0X8yQXYXm z-4xP?+Mq3q;jar|nk|;g24W_bg4yS3tfrw?qTh0h$NGyW_P^(c9d$;tieG%9C9lk^ zJmu*R+Qi$C1|ScTa8yh%RnA;Ga4a&sBU83ouQUDG@Mz~${fF%5w1cbByali*&0Plos(?s5MaCI_&{eHw<6wb=qaS|61Gm|QjWuReqcnh{jh^?${o z(f>CNjf~f}mNfL^H!<`hcqBPShfob{@v3+<3!3mF5Cy)gWiUb*^G>F)z>ogrmM2&T zs5GWLwr&9zUfUT6!4CUTsSv-|fPucT_yYK0io0If`{DmnfNDaPWecfUa6;mYl>8CFTnNP)JrgNWiwO|XNEQ8o zQorhBV|*vZCy9adeJ(FM-#52eiQXNjd4NdFr)VJBZw}H0c*Y;ehP}qholgo`4(W7X zh+LU~+XX`+NAn=D&tZ4HRgK({zCL!;Qv!1kuLQ#}eaqni1||9YrBzDTZSMpK#X0d( zVq|SEF>Q5>cA{OdBtSKA;bEa9;4O>x5<&kU*;V!bCgQ71bS{`SpCHGO-WtQBoEqA>WZrw>AAaJadQ_6Al9uli!5XsBnORT`#COBkk^|Z!J2z3 zq}cUzaCa9@tbI;AsIR0)6{~dFOc_wu(a_!-SnX8SFV3(|@2b@2_vGGUtHptxQe)iN zyBq~iTzvtSktQ&GL3Xr0+vSzT%=ZOdWtT_4lMD0l_oz<-UF%T7NhONshC$l&8E=;T)jJ+T8fJSaz1z^&duDrHez?RDWcvk4f3_TH-0!}g$D;7Wth?{C zM8A^EobTjWTPKg zQ1?ji5b7r6+#mZkrhlrP{g8etCUq}Gh&BA2C-6R0$|D&TB}F7&QW}tmS>*ihLWyon z{$>Klriard@R3-Jd;-o(Gjh@^`cp-sB$rTqfJ9_l7n=rsKq$a9WSN71cVBZQG&}wZ zbIYXJVKreEZeb~!f1B-M8F^y%Yj5ma|DcrN_dKbi&vliFhYy0xmARRxI`=`FaNF*H zh|wVcn*$_bQ#Y1XhPQvpR_#vb+rJZ$0g#ASXx<`N<-jF0VNYW$ut!35nu})GrSF(; z@c2nlq3(c0WdAD>V}~})6evFv(F+eHRYB!=Nvz^F@9l3dTlgWK&;QGn?q7-cKTN&< z)k>F6S^zo;b&U;nust1~WE2u( z;QXYKAqo5yG4Lmmh#tFm9v-55Wbx*s7+9Gn4}bgr=>w*r2x;#Ig#9NMP5sa2`Ts2x zx80ZNqN1xh)VKwW$<6CbK=b`#>4BHHk7}(ib~>>iCdqz&sH(6--MzcK#<^= zTtY~noow;8tt|{-ia;+K-%X*fgfTyCFo>|kn|SEDN9Z5-=zauTEnY&*SK*qBAL9l4mF#qk4ARpQP7aDW^6!N zVo|yzS9}UPSthQFa8c zyv|00U4QZEt$;j06%iqFcc0+#!TA2(lW7Oo0rA`xhnzM)LWV6vz)NFqPJD- zyNKcc5{z%nex!^3(E97M6|EHo4I8STj}lvGsKeRJ%MtK#>Rg}*&YvDBKXXv2Z28%^ zaa53yffCG)?yzeOP07=SI#`91k2C>g#CIbXcICd^0s_9_FE6%<}?yU zR98H)GRlv$oRDY{(w!bUZ0LR*>0z1OsgyM&DLTj>5*}^hINj_e2TYCV#WeH__Owo; z;vb;LgH+eS{!;_w{JSRB%Ed$F{X8No>(F}@!>$P?HYO|iEY4-)OzEqx$=eB2i=JI4 zPtT4=4$MagC;Pn=>^x@D#AoHLiUC?TDN*!dzKF!$W$niHy@T4}maZgSJ$l#RQ?6XS zTgP*m4i}wYz2!S5WPG%5%O9ic@bxhkM6!yYKg5$1|BA&yUaBv;4!CG}# zPiw(m7t-7CIa||U*lj>OUiF7)v^E`=^cQ75AtWh9)`O+}CZ9x{%YJK`GI@h00@$gy zdN>qDRNGY!d^^mvaj3#-AEWXvR?+W-#N(Jd6|6md0V*}0B^B;smh6XA1Kja|X-?A1 zj$;c;>L-35qexr&;N^iJ#W_#R3l;mmd;R4{^V@)G`U2~SRVoL4|6R&#*=~kt1zd-T zN^m(Z7w5{XZooe~;yA*%lz;;Xu1_W|Nqy*>d^lX=Zcgl5aSd_DS!E+M%tF5#MftB# zs^Z3x?mSt9`4rU2OgXL}`Rh(d9GQ9^;)+Q*s#h{W=SbKXL2vP1`$#!HB6CQMnGNYh zNJHa@O(G-Hv%e>($!C$|HDZLf<2fo4JQhCmp6|q;ul0ZTlkTUKHK*9LCscXxZ9kaj zT%JmlmA|O(?>1FNiM;6`S34d1Xr8RpzsbeU1lhO82$Oe>Gc}n*+&|G&mILMRpIuRJ zQF|IMCV<_aUaqJX>SceG1gnGq*fVU(5UYp9|D63m)?~yiZ{m9BEIlwl8##3QY{mTB z)?*VGZnY1PlAnjY|I3v8@0Y*-feya}cR{*rY5AJPT67{ad-k03Zt$*Mtoez{8{_Eo zP^*n&t0kF!VsNpPR;@_sl@6Y!fKDCVCU4uJx6m_4G!1dl{t&%3swj+k2)@Y-=ZM$~ z|JAK#X++wqx2+?ut?k?Pqc?}>$*c})S)hnApzp)3IS@bzc>tX?ccXDb<&UPS>xeO# z3mO6n$+dYchV{IrOnfWvrm7BKx`w0$=Bpo?NT_ATTM4Bwz4frhP+lsWn90VsqDT#x zKxBMe7$EAD< z)~%Efo#4$IQbPy)PXla6WajcXxp!Ko;`1J501Bb@eY2n|p)X)Kh8q|6L1z*2svg+U zg~Y~|=RTLqYHrr#6wd~l2!VYN+4%`pTbt89-G_+LjI8HQ24hFb2AK!&W{AZ21`*r| z>fs@L{!0I*%raeNnWeQ&)j0Ln8hEny3`ts-@BzHkmM?7h6CaNL#D}5L=COv-a7q8d zhyT3>rYf@1<*O`?(Wd>03k|!QyP~*f=DOZws)FoYyi z+a=xK;!%FfO4^xLm>hqnl%#!;TP;4p^HXgq-iIw!GmgZFubBubdr{CQ%Fac8h`riQ z@z>>kiyS5E1nxcqhrJ{B1dCf6b z8KKFt2ve+K=u?h&%bX7{wtacd9v8#+Vj0ZBBs7- z?&Mua{`{EGy1V#VLI6aA#hCXR$_zZ04CIe*>H0V|38(ldtK2K zCQB4D$$(1rToOetBmVV8%QuNXP0OJ7tlG+(Y;$D^jTd&@moIUi`C1=)>MuK9(Gr6! zC}+Z$8g^Xs>K3+I1I*tNd1MQ39}{qprp4B7azgEp1Xabtm z&c5Nkw_`PaZ8tikmvG$skL!oSIF%}Kmr-%6x_m8(MW8(5#PNjR&~!~duDs=M(etHr ze_P+e^TtC0?8^gvpR@9La6gu#cU=AbhYhG@mx>m5r^nxpd?iH2XlwqxCno!!XJu0x zdq*05ga7%!_j4)omQ!p?`?v*TfYy3p4UFcUaPDUb3XmsRkP2o1{zY9)T45jx4=qA@ zHcd|Tb`NJ!GYR4IL2vsy9A`8yCFNrYn3L&-uv5e7gJPVa;w1~^i2i>RbEDu~&_7im zfDnIuQg7f~GdlOBX6ma&`lspAqx}0#AWp5)Zgum+0P0O4fPG*gnWb#CDeq6_Vx^9_>b35>P=lcYY-J> zUx4%T##f~b_PMI2uE3ruK$jjRI?>uJS};_$BoncWx7t36m9ZXECoEex$SC(3+3z4z zb|(VwASuGbb8a@}ZjBAQrr($Egm9Up{i)n*L66r1{1`W|lXGAw!#vPe8!s!^VBr_p z0OQp;ULY6zvCzMuHxUuNZm7oonDw`zrBfC3tH!p|Fwh&m?Pw0*6KcKf@ z0Q9B@xryBWAJ7}Zw;Eu?%IMw(lYc>P!2gEcmR60PVRu8ox|se2y%ECAV1Q=(lJ^`H zVd0N6U(}lJjJFphB-Lw}@AvrcX6L5_Dy)D)UdUMtuNK}&_XqG6fd)4)l5Bcrw5NL6 z^%b-S%}h(BI|9tU5n1VB4#R4@`X`s+qb|fQaPSK~?>zlgDGT8-iSFh^(;<%E3EUQI zwrNP_h5`yhD>&YKPaIWFHOxbcuhvW2*$KwyyN^N|(KGAi1Q!U!LFtbh!C@t^pRu6UX zVxHNH+kij$iRq462ud@0pS#}#Ti<(Vs*d~1IHQe2+6kw$M4>J*2+Nl?toU_JBZ?GY zO`-x=lZXp5C(WZ72NG#^2f7FAjr%KY%puWs*W5Z;;up6<9d5m~=6WYjTGyvWz|pSN zM9LSg{NI>mb^EL9cT_H5^cr-te^?5%!WNsW5qS(_xQpf@bkNGWFqZLHF8ISWCKTYp ztoNjAmH*TplMNR;h58iCiJ6n<|3C;S=bv3p&6D6nL<^&V2DjXN3_IM(p)aE&k)ISB zk2=vEl#-ZtY;%Ld5piFsRqFPQ5%C$ft#Mnb+iTCM?fl(w7({PoCSHI=3r6WJ#fm_g zhE!A(0b&;s&0c?^x2@c1F2MCE^W*U6vY5L|^QIIM!*Ky(8KZ|dL zV@`ku^bf8;<#WkJff{Sk`J?XZr8V|FZXrCb|7#eLaQ zI6+nsJ;PpdV|f2tB5KK_%hvvTd+^T_@xLF5KSAJ6e0ZfkVYdJP>?XHRc+k{7$XrXnlfsj<6caj{$G9%(V`@r{&t`{Yk~A1om?(#T znZJsD9X;#tgO!(y{gM5O{pyzckqf}OsasvIlfe9ZL;*S$b_1MuocAHzDR~;I$>Pn@ zHGbKH;b|n5(a=}SzPMqa7C&p5IyEs5KWjXX^;j&3U7~DA1E*sdd3V>DjT6Q#4 z&zRO1vkd^x0g7(>DyxC+)aCbUMW?0ntIJc}fNbqz2ZIz98QHKa5c)(l_448ECa{y- za{^v}7!M}R)*>d{31D?lR0VQZp6p6lU-C%uq-M;&lRafRSmNB>Z4}39YUepC6s^Mj zE$A@hZj1@rJXoOrrk%#EUF&I(egXCv5t8$puRj6NP@Hk5FQN9FN53f>h}bkWys&OI zXp}Cf4ES+Wk2mh;FBb|!XLm-9&UB7K7Pnn5;jImfcJer|CVhZRZc6M^CI>KYA|05l zoaMaq3C>%Q8v3;+!~X(n!Y}$l7tj>Q&a6Vy30NQyAQCC$wiao{wv$HvdJ>}iuER0a zv55%uRO0JG3wks1j6qt8VUAMlFr}1j!hj zg5AB(c2Zw6%D#DSdRjeVnf^};c=&b0d*u?NY)R1Rlep#OzFm08p(W=WdZD8p)ION6r9pDvuu$+Qw}6F$OqCd5eVOg zET(k%Ei*YPICx|MEb!_@3`gUP0H}qd7Y;L3I$UXk9`zXYON1R{ zv*GR~o4;N1<$P5CO%58oGJpj>Hvy$>E)NjhqPOaaGKj=esaJKLJn;$m4RHl~Y%PA< zj>9FHyU6BFbPf#JjtAt<9H_i|Oax%vmf6&$%m8>wgzRslvR^RO;V|GT0h~>T8cKTs zhVZ2mwSop4&boXQ?M4==qAb!od!o{8;!^8S?03vkqLJZEpxdH{ORunh(gA1G_(>Jr zM2T-1mKn0l15{tgza6Gz+oHxJZ^_3SYXD?&9BuIglvsLq-vj4d<^Gb%8J?3-&qdc# z&kQG$9^%?q*%F6e0=sibOFtW;8VR{`g=^hi%W0O3;4JQOw8@+u9L{OV)aH?!mOqjT zDAV4-^}mmDQ-B_Oz^(nx^GaA`OQ+L}w&&v4jv`5<~T zO`E<>#-Rb$^$~-q(4k~#o-Ve?RczzIEbFpI+;8D@G!Thbt-Rda$h6I7{wG%+ID^fZ zwba0TTw5MNjC#-rLDBTJDo>!#O->7Yp}bAsAn{xdKLsj`D(CwvDDuPx4KWlZ5BYdF|(|g z2PJKBIYSlXcWotyXlD>YR)}#XgwJK{j;Wnc%aw8}C`0BE7YuXhW`E*sQ#E3DT}iWQ zw~Y|Iu?T?4x4+L_6zMAHvdw=;B=z+DBUgZHbGOKQ$?`u>^)6;3s%e0j-v=y-|L2(h z$7GwR24L`I4P~!wZG9~39b_3r;t4Vst5O!WOxPkCqL4Cs0G4R>4XxjWNFq|_VIX^M zxsYmpZK0Ge;1TD4>F-64t+euXWWpmzZIM1dZekEFI99f0S)q8Vt;<9<%iN@S1Qb3T zaZWpI-P%PjCcRIJg3t*A<-lQm+L1!J(aT;o;*#&jQkNcJ!DLtx$j$HSrvLayXz6$6 zG~7s*uNBPPU0Pg}U9FO0o*iz%#4!u|a7|EB{4v>O-0(zH^V9wU^degt0h}5bn~01) z{Sld!Jbx*R2q`aBkFVK-Xh?kY<+3m4B@)bu@>L0>);d#|{lU`z!bLWvG%)r`Q+JA3gj& z*iq=;;gj|e(9xlGT~rH5cE5HP4%M>Vwdw(Zm;CV?_#(1r8{rR(LN&Vl@KAMevAJc@ zXw}m>J-Y7ExQ;EYtMcNPs9MLM3qKUs$`g{Ay;qa|5V|sdHSnp6lga<8&PC$lvrhST*FGey z>F-blDoK5dx=);2PB=z=?6Vlnmyy;O@!v>tb$$z)wB~Q$kkik7a2&9Yt8wnl|LD&*#V@30kg}TJ{Eb%j9CMlVlIq4EIEh?#5Mga6dwLL1^>vQ=tKnl<*?N8(>=}lj3by1o@j=}yD%5xw=aB-&m^wBaqZL?2H%EQg}8_?wm-k7oTbDy70ZS<+)`{A zZJ>{*-m>*Skf)oCE`{z6ZYbJzU#)LKr&+K4C5!Xi2TFU2yO@~_!I<4e@+6_0N#!ho zGCxvo@Hfw6G-teSO<{&2CH*zh5UmM%mkoE%CW=E;`NvY&g(DZoa9q4$#8(KQMq(tn z5X9wnG%1xOf5hEe&kDNgm|uKQ>^x`N$T@%rIq2uvtYNdBObgl9akESFcz_w53;gjtB=h^o^j=2AkeX|=I zn#_)J@#jO)JE}%1lp0LpHb{*y6I znWxBod!!yfZCS*Q1JiN`ys)X@0K;Hak`d8Oy+&rC#aHRVW7&J*Adl(8*41G^0N%#1 zD3k&vKN9j9?6rAqbwVWCkWAR}P{BwyRl$S4VGK!Eqe03~FmQ=L!E#X0RJm)JMl%S1 z3#0Ai#`r2iWEy#0P2F>i%f^lGy^omP%&gPF_XW6e8(c&mkZvn0vfMejJU`cC1f>SP zTR%_LqTjXU;9-my<*vn9!XW(wKbGbXJpN8}T9>_$B4WijHdc@AV3ko_= z{MpfOce{X;y@Ld3DpmT@x~wIKQnDRUh<{@ftdT{Uk^bdMz6CkntNHG{+VlsPz(+=N zXZ6e(K(vW<`?$dXh&JDPCbFI*ldw3WL1}XNr@26-z`gl6b&M3jfa#f({_ifM5SoU; z?ViOI(OSl%j>iIfX_I#r8^3RtV8>bJtpfN2hK$=zS&Sxw7F+bxWr`f9utr@3v%!Wf zc2@Stqlw@N7s9vH?HDK?f`qzZqV8=&8vw3kg0uV%>b2}Yacjm69-9l+(w&2*KGUTL zL{?Sl@*=P9YJGsQ84iUCURDjL((Z!U66ZqmY6IHQ#~3JHT<1Twk;KONgP5C75Sq)f z5|%0N63;hhj?xx$uCvZcT{Zm&0e@J6o!2;d1x zw(0K)+(IZ`I9XR_zbSEa=woHNzi>T%5z*GnNAX`;;2*VLxN zsPoiQeZ1GSO9cRxaTC?ew~+6@lZ5smbfjszG1a_@@yo|oEC}m$HD)W}Iw`zVJn%)W8Cc}uWReDG;%cck)J7AX>Ls~T-uc>!0*E$)(#?vSm_=)c zg+%L9`e1=5_UM%~RS`C)xasJVBz89ikoyshqigcLDbcmGUJRB=b}FnWWy9*?BankF z8);NiHT&vsJ>8ZpJ!-_Gor3@ik@jkhI;Oi(~o@qtQ~eZ_48A`C&uP&^dhjHQK7A`UurV=@PPcp8qDf-lF;J_Kf|la zESd17DEvj<*`vLO@*`JuD>&V?YW@iCKaYKR!qdr4|9F)Be<-&9LXh$IQMN5Os{kc-jQ|la%36PxHP|1=2<23h zh8_g8IG_JRe$B@eSq0li zjK<5%p;L3cqCHMxf_Za<_jkpnq~-XWrXc0FdUjP6NNt8?9+okhP!^scBC9y9vf0f6 z9={RMpa_Pck{`k!=qV{x38w`MZ*r=!j!RQ`PGIClK9UU8?#*Epn`Ys zw|g!j=%$D7f1|^W_DG{}Q<_*Yxetgfv$)~phEjO2E?g0A9hlVZNS@EQ-9)4>y8b|%b3(y+1$Tc5en>SkpA(wE=nTD*|XmAHAGIThRr2blw zPAZ;{mulic74GJ&cXCk9m4pQ)vXY8BZkJs+Q9JMU-~a&;;X#860pQpAo!MSh#O3$D z@(aVS9GEI|XCxW?VB5G#qjHjlk+y$1S*JM_y=HJ4Hh-Fzs8qg_Q0~Y3_Lin!;!6G& zx}uFf)w_(r!{HIzS@f<0N}Vb-au zfts4F3U;b{adSMas-F0db3j|V^`-l-Lfphs4)9YLDXzE@N+WZ#s5VA?W4(mf#(-PP zQj03VW(M=_s7JQ0MO-E$rc54`>`+(|Dw-4;q965z(s3MbIWv-5lnNG}b9Q2EiqB%a z78^=rPE*iRVp1+0$0N{DsYsm-Gv}=pvIxFAqqkM=~T7)%PFvABqMEPYKp-?{*vr5X@(PeOq<*&rofQb)`8bH;YNIWEr zQmNC5MJB=t#3S8WRlCznlD(3iiEs04vhNe>_{dahb@{N``%-PbO>Td^ZG$v!C=cg$ z&Q#m57}oO|{Q@cu}czO|k9ssMg%WJK>@{F-zWJ_lvD z^7#{2Q*95gAnw2THAX)Gzs3a8|1W;67TC+>c=vn(iNjRUDPNF80>cGcn2;{vOAKYt z@0g;cT|hmVRjWGF_DH>dN0Yb&fM07f3Al_X!ZHJU@61oDj26gFEn1Q!P48)>9jR5H zj(_yQ>U@qW-mA6ivXNZe9=Pb1zjQ6t`$#X1N{4LGnV~)q=$d@0B5-fo-SfW^&i?|W zAti6V*6(vb5RnQI>0w_H$=*{OZiWUb8ZwmyaSfqmShv@i=frwi-o%5$q1Z3=Dtd`p zJ5~R8`Gw!94QeJJ^A`R$nfKq1umEaJ6w3tNCtlMtpPd$Ma)X`LZ0dL+IH ztb#CWW0uO`h;U`q5`P9x*o>C>vRfymFl(y1qojWHFZ_PC-Ks|>#M6&N8e}g}xpDn+4j%o?N%l(_Z6Lu-2*~=}ENhWo4jzQx zjY!;Up4Rgu;wcJUfDl_;P(FM}zA2`=(EnxDzI`%lnJ`!!Dy+^` z))xtDb-Rm4`<0os8t@rC&H!dDA@0+6`7dS-TP75u+K<@_Fu1C^pO_`|z=oI>n@O$@ z#ic2VPs8R+`-0bwyV$>#$?JqbZxgG0GHZ6<;Y|&NoacGN&y2-l8;7`w)!t8g!TD1v z>dN_`7P=?0@1BGo;|7N~x4pY+DH!nvxZWDaa}zu{@q?Xg8@B1wZPLG~k9I2f%{vmf z1hyG4zaA9fqTHVWl27QZNS~~Y{LQch3u5lKlko_*+p4$JTQ}JIzVkPRbBrnbXaf~4 z3h%AAu!oSmx91+k2Aq@W{l|g43&80gQ9#le{~6C|)Oy-ODJOM+k zgjQjx2$EAHZzZjQi}3&o9DQAqY35in?a_(5Fjv7I$EJ=&^b#?%)%HPFD6EsJW=T7` zmBhiisP$>3<`=hSUaK2=7lq~8T?CLnL!hgk>vc0f%1=V})#v!f^|PGc<>%dma&bZW zL0O4!zTp8r6A7X4Z^@2ALD{gqIXD1ljY3FfT~9R5i(svdLbn||WQ1Ex*s2u|(XoUl zwwxU^6whQAkbQi_m&OhL9bW;ZYztL2VBucW)WHv^@H@-HwpDSCkNBBvlpI42QfH* zh?qe8H|=@{PhQirMy!P|Im$?3RsZeO!iG2)@Syy5H4`f8KsV=+8D0rX=~&OomE-< zKn;v4C;~NeomEo`9l|^__!xG&O?NUW?`@PB4ZWEny?XoMeVaLTI9!z21+C=6>~d_L z`%Ju-%eptoir~P52;?ej`6aB9B%}TM!+%;d9*}-&l4aZ@K0Dtf#qx)kIc9sX50P5~ z{DFynZ2g3|4#F|4aQkj@!QW+mHQ#Drv@!8$m>lAirSSXrU<2-obdmO33GjY!u~84$`13r%1_x& zt`5FU6-Kt)kAzl*nKs$akKfK%$=oxPzsRqW-`yNq(a6&{EXcQrSru5+&C!@j7I*c> z7x0|f?|Lz1>e@7a6V@jTK~d%X^M%AeB-QjJKPOm`=&nz-n_iWvhXo%RH?RG7jWN@s z#zKnPp&yUAZN%ECNcDmWVf=cbW*&p(YRMaLfNR|%rMg-p`WmSVNVHPo0K`K~QI?|! zUqo5tph$r_1jcm_<}us$jkm3jx9zLP_79$`O?IvPM=B;Dd=MZCa|j`zpI?rBV^3vp zkPXX|EKGk$3>;SuwuxuGwop&BhG&?Nn?zWY)SSXq7Ji}Da84{sI<0l-b1Woo0hd0$ zvl1A^x8sba;wuLRqJu$3&l`8i$xz2<$$h?sJ_v#UtQ3PVmo7ZdQ#wztR@A-zN78 zjyyL^Mff<)l|dA6lgiItqH`tz?EMA=_7$w5NBTr)V*D=H(JG?z7+qSJnLFZ8Fc~7f zWGD~0n0cBi9WBl7wze(v#RwIh7?ouU6(P-@vhdj{(wpuKsim zT0A|fwmZ_d-?V}a@z_O`dcD-LWYwTOIU!%J6-`SY5d;142lI8 z2@!i`epTx9VV+BJAK;Nd8wn)&Ik*apXFkCpd!|6n>1>M>8cWn9#yTaG$A(d)5%Lt> zIdt!oFT6WqO*i2qU45kU4J%`j2Dw4ItY*&6;RP~{2fu*`F3vHYVvw+vu1v+Xnd9MR z(opfY`K$|-itMM*lM5al2UqI|)zF=8k_BM9gJDXiC9cb))XpTlA)w!c7s3V9q&SUF z^?e^xL*_tbjkUbb(mQ^l$|dfRj9$j!devX22ZTU#@c)nifDD?s+96PkdaTLNKPIh@ z4M}%OYnlDr)73tI%RpjuZjnMj2LAqMOWA*jr~SVf2#m(9` zRp-{1&X1Sw?JJiLpRIO>*5NBvQy{=qvEl@rI1td;3}}91_7Bog7V2eyp&(>FUEFDr z^Vv=$;5MN}TCR$1SxlsmwqAhu5&ExnKs_cZr#Q!Mf0* zq#{X(=rZq-Rm($#rofPxpafY=pgjcI3XxS4p1MCPDlno5Td-uxmCiasiM~a9u;-#W z#*^ds#%>l65rN%&ukloh&vqmJ3XAV`@N6r{UdFE>?(G2f@JG)k`$kUIjlHU6W(pg^ zvKuVA2v96;N0;x_)B6t9g-|Z31GC$naxT_O1O1Q>Bn6Hx-fPWxE&`lZ1(>kf+ghBR zj4BtyFsi%0S63`ng|z%sy6CQ0$V_%Y@701pH&6bk{Lu-my8d~DvSB9+wH z<>lv?t)`*_(r5b7&1+!|aE);s%eX&esg+!swvf!Ut^^m6llpL2b+CV&GL!n?=q<3F z>_O-Fm1K=K^^3iaCdq=ba#p6?Ncv0>m%Gg{&oxFZ=S*2C7YyBUmx}y1HJZ zcGn-oD(nx?!&H$V0wVqQs{N0|AEoRz^fX10!}+fUe%UZYLj#%HmpN0o<-t2SNO1{o zKhT>fUi`&>#~|In&ew6JQifs_gS@`|tcqP?iVI2$%GTFWmK2m~2E^bAjAd3;%4Ay6 zkrXN0=^U{5@;szRWf<|t>Y}5L;n@Z(@!mYyJwR2oF6W(okEn}wn9{yC5j%U-345M}RO%GS7s-Q? zQpiqCFp-{0j0d38@Tg^vU=Gke>9p4j(TmVyo0XwW>eLJ;#VxkVT7>Zj$pw0{_2Nw% ztyrtAy6OA+@&HPqjuY$DiPhj);{%AoFTPhy4}7ah3o8uL!wv01iLCJETUotvCfM!G zmV(=Is+C8fJv1Q`hzW?Rkl=^-!SODz69$_2^*!|C+^B;-Q0emPTRK*j=Z1K)z+wYIY zrLPw0De3<#7yKZi`Ea$XcS`ta03DnZO1jE6f*&RuloH_--`NE-HKDSRf~-> zPN__LZ!DvN@f;OtHNX^zNf56P;`)cskF5??i-#Qc*(a*UtfjbCK@a1a>D#lvEohe% zl&1dqt-(L>wMqSTXbT7Nt8>QXX?Sbr7Y%o)=!^wf?;JmtjqK&76hg2D$nz~RzPlY| zMy+zF?4`H_H6?3dGYVyE5(;mEy%#sb1FnP3_{rC_0ct%+alYX#Z@H{GSUZ{;{F$U+8gRVX^I5YqNO6 z#JW4B>62U>!aPcY(SOruwz4tNH1y4Qu4k4>90G7V!Dhv)e+=mBFqZLX zni67yz79L8VKWvfeR39XqYwR-M+@Zr=?>YqS&v>@M_osIxWy?QRkMlyB`igIP5kvym+S}_63L3vaJGsTW55)}Hq&-1jJaQAdOAd6Mr%A2GbL;GVC znAgC2(pU@H#Za~0`u6#2P+jXYw zXan9+RXBo}eKtWiZZN1d8y%U?T<4g!LoT=z@Y=9|4a$Rk40`=qFx;J3ffKnY9gG+y z+e?1UFsRo`Prr&hXALdP3;1#WP=&LelOy2c*0{hRl1Do_Uha?#F5e@5NhvSR7e95fT%_!I8ENPKdL-JPhf{n)5Y#b_ogAXCa zep-WeToDJnwD$vD(Z^Is(yy}KmUL~*R0xVUU8c^37+92t^?Z%;2{a%mcZTG)6-iqg zIvnSyKkq*hL68=)||czjR;iAei2ywtc=t0{{2_*1ous2;^px95dMz{U;1L@E_i(Cp;mZ0&o89#L zI6%*qOdYSI_<`AClO~Z`RX)-Dc6gF-;w#Qm$gpF?nVa9WHx%^39pI0<3hPJh-;3&E z3n`1IAEec$H@=^FssjReeCu{|*+k~-rD{tT6rt@>rO&dazG0#v?9hyMyCW+f48RV? zZJm*mIT_@1qS0~Z%jwb+pN3W}H*A@WK{@+0NAyNAny)|SQ13KHgIO`|PEqy-9mdgq zSyq8kfpJx+m@cq7y7mV6jj9`cs+%Igun10r0{XcLmneH92~Sy##l{?>DqD%Hk4LH( zZWD@+z#UOM!2amrav6u*TH{j3!OU{{CuuS@ee5?2x^y=)@ZoZ$3b_SJ8q${!z7vCU zjUuUc*b0Anim+Z5J2#BFpi)@v*ViJ$u@kp7{rV8~aEu1@#*vgXvV8Oxv*UYqG@ z=PPV%Jst88vKGbc{u`$W;!z{jq*H65SGhl0qSB)oZ$=!Fzi}Fbb<4WKOWC>8Z5egG zca6pDB)C{>A~L!X($`5vir93x^=uTU$W9ewBc7w73FIe?Rf)$Y?t4WJIV{!!PH24M z5bHBQFM;lhyXzw#>6Yoot+<}FoAz6^@uKxgtCHAGZJSBLQJeGcn+$zeaBDy_?O(9& z{~{az`%SLaziS!Za*p_`kG3dg^P2CKXMTgm!|p-=vJv%Fl%m{#r-yo#+QCrG&)?6} zioUtQ)?$guB?>Q+Cy6Dkk|#nB&+ctUU*d}yl$~VqAicrb_mb54DEw9Ll#7fXLLHw6 zw{Fv)2e){SPOS>fR!l&67C>}SH@vVwDdP4UlmknNtg?swMoyDT!DEUV2aBwRZGDH;erjV2sUgGzCm=~+!IMA1IYc?M@eEB@&ut*}Ufi_0&#O^c1L`#6jSj`g`#Y@^KG@ zJo*RoOR(q&k?8L z{aGypj5}wA%5DrV869oh&Pqhk6@#ChHHEHy_^K$6V>0;Z{4wOqxf}%pXNhN`EnExMy;S+!4lqF=!N50f~q(@D1UgiuX;? zWnurR90v-SvW1PmWQ#ERE~Hke(5lj_EgWu_ z3GwMSY9==tm#a-jVeC3qQJ%?XuH;8?eBu}-%Hj+UmPNTi(?hL=Kb4Pit5gwytwiP`l9#zRPIWo=h*kv$!uaWH)IptJ*+TFq(~Xec`IC z{bhw+e0=p>Z}4{2k1uxZ|7$k)*X+YD?HrDwD7RAjbno1UWx4bN@D_t=x zKZwsGa9lkA0wi~)U>FLu5&Nm1ZrH_L5dYw;EK|_b2&eN4WyT@*Cnu=Uq zXXV#NyE7Ao!P^O}|8m}93Gk%Debo(pzOEKuOy$-#_SS|h>dnQRLikAdHg<}1EaxSf zX4`EjeXh8v39fmKw9X{zl*RM$mu&>*sjZVwzd|nH{0CS2|HtClKQk=+tbyxcfDw8S zdkVpx4fn&nB860+QtKy@$nSFky1L|`6-0->+{g^e(qbm35hhAVpHaH*Q9dSJmhng^ z1r~CodeH0v2W*|;I?riEPM=`>esP7!8BP}`O#jK=+21T^PYj0x9_lx0rFadBHm6kY%)yb z{mb$a%fYF$jaybnR!iA4nej8<+O%!5Ua}rO&A03iYr9SbKFsn!U`9YO`ouAyKqJ%e z!4{L8wIgh(nzlUj5egxap%MYtR=P3Paa@z}6BL?N4G67`GtUF93kt(ZZMP;dr7TaU zdP!5a_d==%z zsS!j=kz}OSZXPr;B6;WK6=;zZb)G2&7NNp2CWRJZq0c?ZK`6u>Djxu~L3n6w`ner<>ePX9f zx-L5_4V)(2UvvrS6%H1?SVFoDMYVILw%n;AA$?yD={$fW&Cy<>>XnCney6NebJ^5> zVbQqf@>CTkST}C%d`)r@Hy9gIP-{V-g8BnhDD|8~xR1Fm$XsOo~ouTD`<7yO%uUfeQrBuMWGfTtMbDzeVw(eaFfc(T-+ds~P zMJ3vcypq^6<;hCNAXmbVng6FHDTQGn0WD?s@=`2o~^z-UKv^d!qf9jnLTeR29TqD z-rxFCbvNm7=Ap=0Pd$u8lMjm8E9=;Q1m$H+Rq<=UUvmUb(iH4MzDNFP;nalYub?`q zFx#ewlCYM_vnw2Ue4 zL6Zpi^#UmX?0x!f|0me{*J2m2T=sYDO*!tiZ+IvQqMu4972`h1A63wjrVclYzZMhF zrDHEiGa%YCnTZ>e4b;TZwvu3xF_8<*BqmJQ=i7gfEma@eF0ksfPGu|H@)KR-#kTU#YX8g z=tlA zjEJ8$Be%2$>K(zsHz{#9@QY6^1~-`Ak|Q^gd|(fgiW3`aOpA2?jZ@r$1Q~8hvXl{t zlO2%9W9KCGIz-)pqpIr_!TTk}o}D{BkQk(|yJ7@_1_yrUB|#_}aO*WX97}TBvd!^z zDkkKe1c$B59)Llekn#4qbPrQWj|vHJ?iYWpl`>kWW?yZs9b=LXB;nsk#8Il5iJu0u^r9!C3KJ5kzgI~1MkFfYr) zP+hqcuAyI0A9+qpi#2`}p{TYmbmTkHT`~`U2RaWzNpo}nzz>vu{({S{s&Vto%wjB< zZ;p2Lt~0-xD@fI5>5d&SxH&`HXCiMByQKhyy`%s-t&*PkGRzw)Ds5|M6Bz(Mkz!OY zGDZgC`~E(Akf>Y8V=KoM^IuU~V=MG;Ai7%_F*BB z41b(ttfcv?bzIR4TTamVXK%4NGaty9NS4mzRMBDf!w~bjgNtOC2rTd3afK%-5em$0 zQUvdLWg2~4a)h$#muoD|9{~6ToHQIn&c;oo9TNYb{(5TFmj<_tgm@Z$b9WkhATxh> zGOyip$FyOu;h=s>^B#|U0h(otx*(L#S!pJ-YE3N@fl?w#vC$kvI?1shGoR7g*{nHf zn6->>G)qCu03UuUh(^8`am!X2v!Qp4iypAk`4}+VxUmlI_B>77O0g}{c#}xcNjx2W zox-NN5n)k}9*y+frlt$l!l*H27H50__d5ngKrb_|1u}yV(J6sfg2Rz5&5=!E^Y@Ni zsou<02N_K*eL=vgfivS#%jO@W$KBTc%+_P9Kf6V938fF_m+r3TnMsDS-tTWqdsUZ7 zaF#*4C-bKCSo?``4xgU{yo7~I^dU|HAWtfLHH5V4ZtuO?e!pX zd&5eE9Nms@8c3#v+sy$JlMd!@ABq8Nn-Lcq8rJ{aQA}*rI#UIJIuIa7=U+!l{{6*_ zY=0P78UIIW)=KenXIM>E^t9c@Y6o|1-Wk78q|n81Omktt`;3_~ub7YR=dVnLX`}pe zJxf!P^9$Ujz5%VIceR8V75RtW6e9T-P{F2&0y;2s!f+_UifUk!DDb5oc&Myd(y?FU z4}j^#f9;a3$99-Zf&B4<0U9sH8v+JOpN8&bCAU&HP7b$V`8f(^tsT~?Q1n_&FVrx6 zzKhky&#Gc)(Q2t^XlZ>&HY~?{VFH)Q!3of{$FK(3;*vn(bLC|rzj=*&0C%Nmg%d8AjUAN(q?{eoyuHnVQ`>`xGFFDheotp} zroC>~P&(KiJzR#}P^Oa6)p`#_U1C-M$j}jX^nv8!8vtfMj;}7-3>wCW2*CRe^$Lx6 z4jE*As^)ZqHhTkn)MOy2WvpqQpqeR*&h+mbo&Qh9vYNfmi4@s)X&ZCyA} zpUiR=_wL96+=Q(gCojxX_#yQcJ6G4gSA^qMZ;U!D0MdNg6eR$8rz4ajH&~EoL8*{* zpTQhk#>9&JK{k^V?RKv=LXFDo+Wp$(yQ3}$@#cHyA8z4FxjqG?DX%qA?uYnSzSK#KlzuQrmhv|0*>N`_H_L~gGUFx0A{e*f z-c8N2umKs(lhp3;;qQ3&AhuB^dwF9SqAsI(yuWCzoZ>-t-Q80a!*QsQ30wn67?#Bf0(l~+v?d6w5Z;g z+ZJ)4^eCDf*CZd;Wb%Av)2UVEImo>^L^;6NL{hHLFLdsAW!C628aShYO?=ykb52pf zq#L#s1oJzLE5`EX<#|(ZdJanX&1=anvVSL|-gW~=fbP(D$6_B!3XNpXUZn8@(MA2* z*-y>nlx&4-5h{qNRlL6Efn-M}%GLT-TR(_@v~3JYl5_s6B%NBAAl;51s^kL4!&0lO zhmi$O_9&*Kl)l6-w4i;K4W~7X@p>cs;KG!EbQd)_PeSAf+q<`F-tQL~ps8m9$ivsG zQ+_V!3d+heqsni^V4xjB46 z!v&cXGo~5mYWnzs_4eJQrIgVb{0O8OsuOPnMG_02v8jsqIpc2O&0Z|C^!C=X*%#6sO&g*5xK&`A0 z{RonIl9%5TN?Ee40f1x~026<0Vl@5I&@SiWsH7?5B_?Pl>&w4ZFr_F*1S6lf z0)vZDSY3|MS+0t#)#vFiTh*d^zLEXuTjeZm^%F`^3^K8{t{3>K7>riF!~83pb9Xo4 zm0;Cl{oB~$OBgSIRP**U1x~eq6-}v)q8*8ECvO-=xWMZ^Hbm~!VKDI!KOOX&{8Cj2 z;OW97C~>@wM-7e3q2(z{U;XP?0tZ!`MP;Ou~_(t#hU;; zK`3rO5_x1#J;=fQ@26W&pyvuTgf^?P3dtls@{1{U)AOfwX$4&z3<#83kRK=%Juk)S zb1DfO1$I}^=je%1PYUrkFnM)T*Ns*yr*Gc#G4Tj*|?>6z*Hp z(=U*E2;v)$MR-~x{aP>#qh^H~Juh4KGyzx)AmjLBw?-ZI_K8KL5c2+u7yuSQwHJg& z;_OlyR%HvUir^+P$Zd{>mC^0Vi-u2z(>cdM!^T=5VfXQouFz6)miy5gn)>9GMl#@3 za=Y+(q^izVKj44!$6BJ;lfxb1T^MG)h`(o#9m0%BL}J38TnsziWXUbGKDdV*+%h8L z+yl6{R1w^pv2>2w9wO|6-qyt)qIk_{vXR%eFP}Y!W~=%)E()qKWL5yUNYkH!Doe4u z;JGZ+>(~2=TvGU3Nf83asQ>%QgqK5y_mM@p#j;%Du*!Nk+)RW*3E_=K-xl4(}bmJBX(fY>T%DX(ZD6V+K7J}3qwIa zY$EjUakmWp~tW@^)-;#2a-A>+0*A~xF9~LT{}mq z8C#OOxS&9`aQ}^qq&qgju7+n``ac0&96@qnDrHUjtxp=&92%m6Q`_A#xgg>aV)FG# zOPo~{DxX*q~2?x5*c82vYA z=^HemQLBt;BqtG_&_2EPwkYdp~N~>1FGv z!!bC#0~qBF@2yO7=^otIH|T7rc0Q~ZxWMtK0BwE8(!BC0te@Y03EG?sMFh%|_>cO z*KMLfY(79ME(6YgG6DE6vG@-<_@7L4KXtG_KL*%V+ZGp$ll(CP5^lK6HX$VJ34+jT zahr8SI`!$vucLKM$eCGIpy`3!LRq|t#kUb}C{ou<^zauv z`F`nfRCiiT8e7`L){B;!IZEw_l$48%NKgc*f(R{rDTIc?jQ5=?(Y`fEflZHRJYN-F z4t23|!e(4rakR0Xc?g(S8v4o)KDe!e5Cc2I?&Q$yR?}Lez zt-jO0*UW%>zrT$_7#Z2gj$7DSm(*-$JbvQ7SKGa*g-Hi`9)0_+#l}8WF?H1Uy*o}Q z-E08hNZb(XbzXcDRKpxzLG_9BN{YkBZodi#j6#}{cJkx%y`7A$$1SKeZBO6tvFt z!;**&Nq;g6%pKEG36`~1ww(N6l}$I@FlgAX@BAuR=ES3TMfqX{C+@ET3Pd$$VZgsl zfI`XyHK?2GAoM44k3`Uhzt7&{wDU(|DN^Z!e{TJ?1z5KON%tvyqp)F`SpLuI)bBh9 z$}(gUl;9}#WFm|AwfaZ9V!F&x2m_EjA2xvmk9}m)3dI9z{dV>N(%@ta! zr`oHh>ub~v;^G_D*9RLd>CTkCnJq8*kNzm6_9Qf+FY4lM*e^WI(a9`tHeodS+eL?R zKy3)q6NpIG5YQGI0ztbH-`7nY99OuDN`k=QKDK{GRhafDwiaEJF>BVWi_% z9JI0VsonPX%6nK{s#_sp^0*(7p0x6NG;jS>J!V`U_1&WT)m2HOvKS{gr5=#?1n#Hm zd!3-SAyb`GCS1~)SUA%O24NV=Y(I2dlW%U+sydnoetD1Y@i366G5qY2_0Gr#7}aukHc`D6DT6>Vp~%Gv#Lq=GM~ zBDr@@DIB3~X!(NaVbkW322}NnYrOB|?>~jOAMjgcoa1~p+|>NAlF_u9x!Lo5m!w09 z3HCO9u32QNwR>(5oa@$Uqj=8|ym6F)?K7`ecT$TT)e!+ybaLaU5smd`CBJ5%9IX3T zL|%K4>5}lgK9=@!L$t(jme6$bNv?!PT=|6Qew5W_-D9Wf({1g8tJ7f|zUt6`_3(0q z^c_!A59WH++sm71h{gDecJ57Y-ryiC)tYEro<&*l*S{9QcxK4kRM`h`e$_eE7KI+` zG6v2P1_R+m*s>6DgEg~ZIXp*S;) zy@FN+bC&SetG@9xz+OIpiJu1G{}B`awPgNeBC#k&R!YiGvI!d&SNX-YO80(zymEY= zTO>k!4eC&7OXw9mj0!alxwxaJSOs-yC*ojd%QwPX3h_(#$K9hMoTurX0aWn{9BbLW z5#_j>U8;7j+1dE}LHo>~TZ6E5lfRiSnI}7#Zzj~Nd%!Dz_2j^P-2*`=fqbQI^?QS| z0ZDJ}r1C1PlsD#d`K1mp;bG26#nLr0r4_unQmQ30i$%%vDD7Djvq8|dHEB32+JVB# zEBC2ek#3BBB;VWdfKV;wfpY-%2A0&oU3xiAdX8Y^IKoBZ9gZKjo3$XySo4gfLsZSj zg4M^+SFK~#n=Kt{fhhH z5wq{^HimJllh*y5Uh@uoAxQ4BGV%Bae;N(o7{K!=C$Pf>~w z@cKTs-^D$|uMO@9QG@sOh5+=(B-L5Q-9^S7URL6_e3DDXr$1+Ff^{fe!)wX;kNKZa zlnQTC7k|QN!)cC4W?6RzK=Hb0Q4XjGVY(6#=^QNHV#3Ik&bMX!6N(lz)_RO#!`B$iaM0{OUFtPuNA=L7R^mcQ^2G6r~hpN8cYBKG$qR-K19W<&uiLiE+zbD!1iS&TKbEgazNZ`&D|04T0P z-SIhd)A6%PMq8^q^HD=p1`kz;z0cUaBS_oy4--OjZknitXTL=7;!6g%E8kpMmG2i+ zE50ae=`to$rR5qJL!rXPa`gr??wDp(*W3=hpcgIT?rBi$s(EI{^(~gXz92f}Nu#>3 zY=pr&c*#^I?>`4*tcJPyE*c-iaPT2;^@~S#vm*MZx%uSN{63z_!UN zH0smSCCa#eh4qjMz10xKQ{RQLhN8z#gz(1?sL60dlb>fW-v?PTyI_ux%qvNJKKY%5 zUE1v@a0??2BUIz4yzNF>1r=4AO>QQ75l+i3r2tY$S<&x8<5lDOVOaB~`ZAGj6;w3p z&bxz(&_YT#s56;s4H;E9a04O>xm73C<`|!!JvzhyFnWZ%s@mbOO zjp3WwV9yLCZO{c32(?Piyl^T*^8cDS94j^KV4!yTtzrWkjefkT_lnrrf?>wsgb0A5 z`NAWW29Xl&$*4s1Clt52(lm--GX4)J=Cdp||5r`LzqW_{H=+3N_3}T?jbn8B=@Hc} z>Vox#1ZqF$#$+l8Rm{l4smP5$hP0y> z$u?Mdw#XReZW^FD0}$~ZHlZ#7Gt$6uYr z>ubJIs3N!5NN-o(gbZN})AZvT;+H2du(=xw`8QW8P|8S%pA3?nimLD}c@H_ujJ$r! zc*%Ikc;E!o5#1QqjmmQ10wtpYnZ2mT00RvP<1eeern1V+l^uPZl@8K%AyL%UBdN?r zKT^bOOxH-yuAEXWfxSx$Ux{PJ3Zu^Q6rDn~%R*wRoZ#fc!)lT$h#@Iv2g(ttV1tCD zmNueffP0G=AzWTg?g^gp4HcvT;tW-_SIg{gghg-*v3)|MdG3wlZ6ZXNdwzp;Qf53N z$?%LJ^|Zj&g!8c-IFBY!?k%K7XRKO7G?{Ahd@!t!w3l537e!LSbSA{>+sRBUr0L_6WkIf+NCU+YUD$8aUWaYIb|5a557 zPqml-CVz(wF4^21FW01@;q*)|cqu7q`vHZz_06JPBdbf>`D;iEw;T+ZhR;RG@}KIL zZZ@Scz?@a}8#g-v4;oEqn`cFXdMq!&M3<`W>dY$DEGR9guSk-di0RH7bJWpS2dsR( zh3Qtx9&g$v7SP)qW&{ylE~h`nz~%mfaI}zfa@A*c3slWPcXoReNR$T(yutH~1{V7tS1OIsg9r`jg<))eQIORCs)0pmK$`u9A zg2NwY%Z^=H2+u^{QKsLby{dGslLBv`#rp~O^bm;&zf`tl=vA_we$(7ijL`^36uyL4 zI*cjAwOAOFY5bfW2KBKEK{`%3w6I+huRn|6tka}*m+T)?`@yZEJTTBZCXsC)6E#z> zy=8@uhpleMbhCYCef0$`g1%ZfI&Umq<*vN$$|hIzwzZG$`x#sqUIOHw7Fr^tLo35U zkaMkR{~iu}6QiQ{FvX9dR9fh#hK!Ac6Wsuc2Xt=FBsuHD<^g=*qE($-Fl0OV;A8~9 zU|Hkl47qji6_4KstAPh_Ww1ACT%Lu$UQLbfswZ)j(uk)mmc5BCs56?F&6W*& zCj!>!1h8H#g1zRM?~%=7v1@G(xtT_t6-iX?GOO(9RCvl+gv$#9k?hB+IGJnow+V_? zP~jU6d?lf{Yw5a^p+XzCkl=M|Lvu9jyYhop_}OGxjkPk?mc;ECzhr}2C=WnvDSR!Y znX~xXQe5Z_E0!(%I)S4KJ!TYVzDR8Wa!=($V}?AGMQwB#s@Vime8{4OzGa^|&VfkV zif^*=G{!Qn%8^$dwrc4=f|b855)CU2w)18CvCSM zugPcv^!pUnvA>XdH9ZNisuMtP!!ELsu2yKj`4~$k@B}@FUoRRSDrxOiUL-)DzUsdJ zWg1{;;cQk0K;dT=R4CTY~(+b(gJ1y4K`+ZEco}(R)0s~ zQHIkOZ6xb*xIK$p_D0IJAMY_tBDG07(Y5eoq>-?;kzz5GnkAv}3UM0iM%Lpe5UcRZ z6XL1(JpYJ7m!W7*9w6Q?K&`-NM!-PVQ=<3iJ|>a~rgKihcRz&reZ&eV8IV;q!JdVZ z-dZQ{a;RaHv34=7g|&yxEBa7n+lh~$Ic%X)r}i2ng9giI%}JmpFo36WRM0^Jf0EUr zVuXAM@8_JI$QlZo3-#%v`D*o*QOp?CRRr{PlUy=+yMApv=_eRHP?H|q zlONpK9{{QJOKs8{Yg{g~;h;;YFKG!0u?7G~n8+Hn-oCY!i##5brF&*dB;(DjB!#bb zs9Ca^)M|HR8W(aFM2rqKAkn5{Vxf2_15x!)8Q1;T#K^7QEJ02zX~Hyr(8CmWDg97I zvcPhPtTb{IwOfID4n$@Eo&JL)Uw^@La_5%%izafj;Apx<;}=$>wb9k1z?YUl$U|>1T-vwk)ltiAnfxN%XH{ zYLOkwPFv279XGP%o~eP7Oc^=blI$7P3Liiglocop(0bD6#ecYNZ*4)dt8e^q4KaZ$Um9Nr-ewRi{3#IIP-yq=T znTK>O^Kmn^ZW$a9bFS_{)1c|d3m%pHQeWWSbn6UrJ2PV^4nF|&VpdoH3 ze=j+cmPDy7=sH-{8(9gi=?_F5u8Fe9eLhM{k=LY{8Kj@{Ls5oMKHI$pRo7_bycn3vc5p%BKAq?+Mzg}4n= zwDC#9K-qX#BW?dO@zBPcfRHj8qT=LC2IB&@m~ll|b@U=OXCy7D-a}uF*el>8vEKSb z4RK=hd4`-Xsdb^7X?a+FsS=FV;KJ5Z@~EL9XCTXtsb@HMN6El<0DBk+cWF~Pxnbc8 zV&P9!W3%@jkCBzYJhuFDVJy7cE&jREpgO;i3crxc1!bFY-V&S@s`r+=-_`GF*C0+|Rq?UBF5jHF%P_|$2W`>xse4@@J5z%VfWqg2A379Y zlT~^M_NmUNw~=-=JsHsIlR$XF=yCuwEPv)VR*dBF1JF>_@Ni!1w(>m?`=8KIB10w9 z889Et2b_Ox`Te`({hKiS2f_PK%837NlmM*2dHlNkgWtCO-5E7oh~x-MqPl)+02imD ztpd(yaPQ+i@TeP*Q5M%P*g`eVNvoBR#aP4;OOlBbDlqn-DTL3sz=Z$amfd%xi5tLL z#tKyWI|ap`83Yi!@|z2;i2mr6Xff$h_gno9&(VeT_+OUb@NyDqA_0(J13>;i8GZll z<^BWDuNNS*2gmzHf8!|A1zlRZTpZwigL~brXNpU;O74@jP;a!!N!QycAL0-DyX99W zAF~aWQX!l~3E=px*Ch3ED*hSjNF*alX^d^3tJ!UCr*bcAf0;h@@@)eU*)#d( z{m|i}vU*1Ej^t~D2o$Ib(Ff#9iGFU2+MEW)+j`ROxq|cA9O3>RoT{-My%=XlZ$uWqgf=;&SmBAdVeNgXx39hdYuSI+=nZsPnDtP zo)Drk7W`&lec`=C%PE4qe`h^HdZY`a>Zl97#NSUBc=g4(UvR8(bsIAwk*xGFYuR9W zU~MSKb2*=riCdbQ?j#KZ^^;kl^glZfzyoDj0X3gL5GM)4M)xv}J*j0bQg(XyP-cdC z3;g9w=2zO{+OPYX`N(HHc{;x;e}|gwtedax5M0;{y*Y zX|cP0cjnNA5*6`wLRxh1QnV&MB9UMEx&!e}&y4PwCK_dUV@AdnZBjXIp2W@~2*bE8 z5b3s(Qv`m0*X>7i6vnUer7e~-j_xLZ4EMSKWBUr_XXsRT}Rz$mUcajbb9(Iq8P6UTnIOpQLf z0n^aF*NDJY-2e+d#enxltgGJ2<4q^$H{Ba_{|eN$&R6`E$O!vc4)0;&sJaPT(!yAN zH#G&kx|C#V5yBXDA~!=+$t-)RAIHey2Ycc?vTE)TdEexM^YF<_w86>QX)osYxca?TmbEF@L?wI>Gma1$ zQlYc73DG9PHEhlQ;aA>1=QdN?&R3)!R;syNj{@srqf?*Si^P0=^m?e9nCG!_C%*Ce zePiD0&ztF9bup=?k3E^ZvxxoGcw4Y+rl{(o^6c?X(Vyw>cP`W;S?`aQ%Ttq=xDy1F zc0|!QPLoL*;a8@CABnVIfKZ0~E6*&PBjc$=QIIUHn&s}$u+yOJg?$5$uoDP$s71j? zu@0OP&1k6Hl3w@=qov~$>CPNIU;k3D**;T45d+}e=lA{pgm?d1)mkh4-|{Z_lXnXL zigy}K|CD!l|9|CO0AEH8*t%G@SJ@};s=1L|twG#ReicQ3EcJI{m~MEdTR`0Uf;x-p z(L>l*Q+bSa0n_uYekr8~xk{C|7tt#Mh06hgRR@$u(Bb0n17l@5FY)rUdAZ;Jsh|G^ z2Z(3H&sxB9X!b=0ID7*W65$*f3dh!U&R%g=ah-~MdDfi)>ALP_@Kjr0gzE9YXJr`n z4ooD0S;f4-x~B1=dhwfKBH+G)BhWJ1h7?^&Ix16b5Ps2s-@`pja=%&22;@s zeBlRHx}m3U$)~-Eu7~XyCfmLoQTn(0z_x;QK>rHAq}h29eJVuYBM51~)1uMAtHT_QJH^+iY#Q^D zwmv@6=4yy1VRO2*72n~{iFXbs@Oa4?1p0Z;uhHO!B)&5sys4hwdNyW`y8h-f4``6k zFU}Otv7pnrLiZtmmtDSbzjIdd>MvSHH&4#^MS0P~&f2FYi+JX8WdpHE67mM#G2Gv_ z;_AZFhQkoFYtZRFT=KR~=@M6qR6^DH==V`J_9gouc6W(8Eo?k5)zUF-A9fr;P^t;R zFpKS|#LvsiE(g+`C`P&4#wcnp`qi4#QeL{JNF6Cw89P;ZVhqC9s*a+<-8fMneo7O{ z!ZGP2h5I75fIbWtH3Y@NF1f%NiAiW_N}kKPv^SP9mBfaO*~YOCmu#0zRO^~*Vbs)m zKy8fyb4W8OWdO7=Ws)0-fp%4=6P=<;@Z~+A;5g+w<4*xB4j~NHKoH%|4@3!K35?T%W1?6wyR%; ze*e&2IW6OWJ>^4SN&h3O-r{o7TqXBJg^gCYH!~gG`k=ZmlKb1olkWaema|tJyHAV@ zE4JqcCMS)>@PclJctWPUmgi07w&LOR{EvAj_g(qjLZ7$w@Y*82cMZ1N8;=lXv9B3J z#1QLs1xW_4xZ5AblE6S;YICUD(r|b4M-YShu(0Wr+WUhK1hfzd2%jNILl;M4yK93v zwMnreB(nB-V~!1HjS8S&aPa?Hvo5&E9s3#HPzX5xiOKix8t)&p>pwF${OtY;!iXSv z2}r7l(!L`2oYi7FaU}ra8@Spa&_C82X+o3v<3t5+cj7n<#&>>cB_3p`&`C&+QD&GI zgUW|KJ%wW6g=ie?(rew%H33U4SS&j zx9s@uliHF8CbLiF`e|06`!A8#`2Ef9aeZTrqD^qZ{ zxuzXfMxxi!(gwRh=4aj{&*jZ~7C^!RyuRNuhIJ!ZfO^4z=2CzGq3Oa$ety@Z_w~8* z!z${P2!zj0c5K-QJj?%Wp{C0vA4>QYWvZ!?Ew}y7;wrpl|>G)zYU`H8#5Dvo&HM6 zr?mJgS}a!_){qpyE1ZUJc+BLGMJ(mS*`jAxOdi%hm~O-*;mxFI$#in%kmKsyM}IH5 zGg@a?3=0Pvf$tWz9K^n1;O=XY5Yj<$#>{V3PLW-0Hy3@07ls)n;CYx4Ab<3uTiz&V z+mVoN2|p+R1W+j)?r`&Xc5t=)wyW?0*xHEv?ZfS?+XaQw&r43apAQ4*kSD*mF$6RM z?JBsDmLFSo8%4GVL&$-A2nb>8F`h#@T4ZUt>i~IypaE9a1~x?Y()v(4?plbO8pQ9P zpX|GcMtzdTdp(M?b0z1b6-Yj$-g0|dl#Js15a%EmSq}G5@RlL)S~oPGi}QQWic7_Q zdKGKdo&t&};hE^yYECbSVC>A>-u*Q@P4>_X*Mw=~r&%_oI;fvXIE?%Qd?GzaYT$pV z+@|%#Qr7U$M8(-vON-@~BFjK)yRjN~u5f;QsneIUZeq|>r!th|8By?vqgw5eL#!fj zCowaJI+$PGp&&69hmeq;YqF_~c)b3|J5ZZfOj-^HwGMgO&3OW3rqAdwIHWUP2=I4G z9wo1BM^3$3g0k}H`4a<12}rBr90q8sJh?@hw+&aL-z`Z_H%sq_S$RZ_69E$NZ#ca2-1k#?dgeV|};77sqc2Lr{Ln(Cz7I>_@Dca8czM0L4Q1f~ltU8x= zWFHrLovhDC)se5dz|EumJp`5MuqE=1{7*|kb#}k|<5>m`M2;5bHOk`6tiJ%V$|!DF z*w^!PPgh==6d>4X9}3ambbfH{PTm`G5d%W|ewRE2j8~}Ir`_K|7Ww`=^Sq6I3&a7K z_i0A>pEB>?DOg)8BtXh8JjG>$3yvsh)QR7eN-sow=8t8)pmX1M=@i4$ka_E{DHiRz zK5#Q@Xh|59TZXuO7SBHcj0mSQqysslY`o2oGpyyuQmV*@W3>s*D$=bItt)4}N#|aS z8lRzL>o>fYmrw1Jj+c&Avxy)5LZAplKskkx{NO-lLhzA|8TJV%?GlaS?n$Au9;ZWO z0Xw(+f#(UFlL`|YtA!0QtsB9OQ43k%!*fh8Hi0%wUo`c@=3vJ1O#@rL#(}ke0}{I} zjN{+dL%jnVQ1r>Ol-{A>lI&EZ)zZ>XA4#ypzwFi6H#S~vXk|8N^T^nD~ z=qk?bldW-LR^NhTUKg0a%1lFHe6UL#D;l12Dq1$`8ui0X7DTj{@;^UbDr2_G#g~x^ z&wlJjx1LXQNy+2Kz3-`E!9gcrLraWS!-(2?DejXhBDN{EX_ti}fYc|wqg2?D`-RmkSD3644VwCN4L#lX3iMF5k2C@d=0oK*D zZ!si3#jGKq9@tQMTvwVNNKdZI-*w1^<2lSC+ZB0{j;pLK-IN}e7g)_m_`WU&?lNy1 zXFcCua`@S6-SO+9XP!E^KruR#*+f6(Yi;zalZ)PBKp}8MT}1=OU5)pK{v&7aI&G)Z ztbTJ4!$=}d@Gfs}ZCLuK9r+I_b&n&9cP~bYZYXA)kKI6BBvHhZK3{d1Oyp>iJ_e}4 zmmsYgp2ON1hzWGuLkMVH25OPJ))4hFIpe(N??EdGbExowq@eys$vN}LWv7j%@?z5( z;THn(o6pUJJEI@bt=*;B)ngiHN8mKs12mh%@A3ELVVdK1gL%QQJq(wU2| zQvo8lXi;yWjo-wR)N%9aq+oi(@HjZ3dQCWDgMY(C5!$18+gi9DDu{IA%ugaasjAQK zE3O0IRtui8n77eH`?(vZwq%=%)J|IL&3iG~4x$Bo)jCXVFeW8R_&Jsqf_cSeL_OCp z(TnQWI>4rdQrr=G;OwzsJdR4cymaxU#rm7csPK77igowh^PO5-+dK344BNIl>Sb$r zL9R8H&t8H{@+Ec)EvlvL$f_gUi~lH9zjM)^EzM3$5l(uWw+OS`^28xjl@4MG;vV8$ zG}YL*h|CA-G4P2Pb^TQ7XeQgP~E#&C& zNQl?0Qn6={?gK}W=*cn>G13C_4nc0ICjWhfnt^vOR6Q|2==TAD^=q37#=wPm z4^EM4HZd$~LN;%98CzBSzn3Me09m*)L4nBpq0yD>PBrJa$hmQBu7CAe%8|aUUTsqO zi|-)vgUjGEXA%+|2#Dc7RI~qOL;g>ifB#p{W%=Db+R*Q=0!vC7)+kr~5u2x>=WbJl z8f4_}K2u12<~=h>SLRHbHdjgIj4t_np>&dEick7dhq?CW)NeUrp3QSo?EWP2pnh2u)M|&)J2_=R^-;p_McF>{Wi)ecBYFyz7g=z!>1a%V z;&%n0p=n)2Fa>7Haa8>bSO1aN=HBG);6Q;ssPl_v<$`N1>&a%8&f8l2Zd@NBilMqM z{$D#cMHY_zP)YXC$Z`_zC3~ghBpt3r+9IEC4SBXCJjmchUwZ-G+t*`6dLNaovZ8G{ z2pp_~O-J17?57iyX$Yk}nA<@8PBa5U^?TpIJRPkUFar)4`|)oOy;JADc|-i;MFKc~ ztT5oxwkVjAj4dHN7UAwMa1vIgcQ$ygC%Tt#k!AGw?kOn=sSEmXBGv7q(Wx)>vjz9j zstX6BhB4{_;Br3u&)E14R(MV3wU%$!fZV0j5ZF_}9YZKQ#BltoI_r&^*krsHIN`*M z+@fPSUEx_3M+6$AArJ7Zbz(HoZ(s}<{3p86izg){wRf7dM@(F%+k0#l6qJ)NJerKA z%hkiC*k>mvQdt)fpO5m@9Vbe}kB@>N-++blp;s#VHn(^{aG1Kf2Y2cGE=9$zY(V*# z`dz*}%5&nJG4vxfFqX-yyD{o_EHQf|s?C?Oo%Okk#4eOx7^7(VQyG$@e9n-qqnx4n z25PRjx{lUg01S#_e}xCJNg6^-v$?;cUF0SUQP(&B1$l?jeY&LOGC^1FKt-ZN;hz0U zQ;i{&?x|O5Gjhsuf`8=KT!KXGKi5BV>5+l2wXnzy!P z=q+XfsY#7HUkZ~Jxg!v?V%S%drhN&NLc^u1?}-N6(GNGn_ZaMy&e>nr3%yIQN|&!l z3uSiRseuYPbHHQV-!AMr^XBa&I}t!KgmELeOTH>JG-Z%a@596rRB>L`h(0S2qR`rV z_xABWi$o2Z%LyZCF<`kewj761jW8=&XD$^ny=`8ToGd!t0Fn3V8hJ+k9)S+fxbKur z4zR`VBw@7l_FCrCW8+C$(NpbGGD!od^x{)7ci+W%X6!6o8lpr#E*HzT(V(ANL z#Kp678qJwz9|5agG}|#?VTcG6qv&8>U73QJh1)eK+7%Jmv@1;qg3NFX_M0z~D>$OHZ(lvn zSV@cHu^Z5BS`C47s)%F}g^Nr^cU6^|V_P}_-z63VNv)@-SWL)+JaY++%4(3@`*xCB ziS@580&wCZ8o&y#Rs9^T_hNTu1&C>l-LK7|+c&1<=^Bj~Se8Fdy@ z?X>!+tmqkh1);*?H;WzG4eBmJP#jOD3$#b?K$J_yKg98#E;0Ctz1=d7+~(n{ks~J& z;{Ok4?-*U_f~J4Rsiab|ZQFJ#wr$%LyJFi$#kMM{IH}mSZM-|DyXW6?W>(KR?^@5! z%Gcz>Z(aL-E{ycYGtGyfR9LJElpCX9R2+G$)KHYv!U_tw2fMX{Lzp?)xzT)KKu%;X zdLbddfJ9rRdfIyjt%@(DiBk&)E)9MSG4w%xC%fjr>A)*YYB#z|BX~N`s_*bTjsDNT4+JLFx(sS4^$tqrRyi z?>K@k$_%5kpkV(NwwzcxCO+HPL+~9hul(fKeChXd;gKX~<3p*%0P>ELdE$(lxTwzH zp4BkfHjPICyevkcNWA<3-NOX>*mk5Vd&tDpq?uq2MKOc0iJ71l_j=zNqYj?+;!bOc zg@{XHtZfMdg6nl%h}a74QZ&i3YV`)37v-B3dIOMvBPCb zjNRK9)d3LkxEIk7yFm<-c3b*aWNraP5EJuv>yx+&;KlGEyMn&!*EO(3b1cLkLP+BF zg=SlljjiV6fo6x9e-N=`MRdaWV2w~-XmS7|j-U+ggNWkM4k#Z)l*Y4HGM^nCPgo6^ z>X6cj8c3v-n2h;CAPzcpVdh#7`|It4h-_ZZG%e)OW|K z>hdR53H&5cKWuHz^2cyY*F$0(9(WuHDgqv~<29l-Jif2bRRf4fy+LcGPn%jOqTkSm znO%~jW9ZK$Q1?N^f)656fzr8-nWe|jm9Ck4XckF&m02MQ>j6qd{`*&douR9(Vu1MF z1bqJLSO0$r#Q#eI3w-wHhX)7b)O@~8iWCZoIgxV)1>-Z92*ERya4l}_4Y#_JKb@OH z;k0(%kF|?iPiZ1u8+#!^w*ey_X*1l5`)nEES)lxlydT zEB_i$D05N{G@_25w5}3@6AqeEFQq5_gc&dEb9oQpcYycPHM95_$ZRKINYEhC|I|zz z+IFvsS8v1A?eO{C9`3bI4)$)B)AqmrJ4nZA>^`E*AD0lizo?i0a$HSQ3QH6j$8eiv zVYD(p1crK?HYN;?kS3-P9%~4WTqJLXrUJ~mFa=qjf^v{GFt{uaoU2^E+(q({pEB%( zH1eV3NjR2Iqs9cm!5o=H8d)BhfQwsUhI@ry?irzwDXPzs*<){fg~{}6bOonPNJHNl z2!;}9GKwA_6vz(DtIuu-t+BaOURrrBf(oQ{J2lNS{-_5dt8}6|+VT{*bV{y*fz?EH zF0nINpheEF}cu;lz2+%(G1ADiq?Lx z>O7T#J%n=&Tod{M69-D1-Qd&Rg!NEO3;R(0=EL{g;?>*tyhl9&DTpR&*Ut+ksJ0jC z5J%v}ou@^B4TRE~4)D_N*(UTH&psbsTUYck>F@J0cgI>T8T;!cKsGszUj^ zMXPFRsaz1>hw^f$>G5Pia+Kb9?JJ0?D`ULH#Vmbvbt`Q^eq8t+Jkjt{OdSGU*zJPl zio-0CYn!O4@~5I5-@8;pN39Yrhi1JQ(`w|T$G!VuhWVNrUe^`nmd7DG^YO4 zB#v1-Z`+9;%NdS@Bf$w;8s*tdJ+K#H5o_FX!E#+Gn*V=)#^R*JUmpipeQ@_{j+ zKRGq8jlsQ8JKl*!R~iP|%O*D&?Wxy)Ui!gz-4G>)oy*}+xH_IjLnS4NuzrWJycxz- zivuxR^%v&JsUJ;9<9kQ|9OBU`kB$AWpO!e$zafz9l>Jvj_S@TJ5rIigA-IIAPChl#oNF|20T5Dy`Y7B|=6g%MPXb`I9+zW#)xuC5KF| zkj-#wUYB7KHj8}A6Qs|k^&(?#dFYY_qC_7<*M?R+*#n452OX}%2-G~{HzUo!Xe4-T z0X9fHrjVR9yPkqX&oHYft08u-cPHC`GKvTIm~_N(zcXYh^`S9jhgce-MRGWM-XnR< z!p*}+;#G6G83>$NU=E}G(4WA0rc?RLKs!RvHrLe>rfg&VVU?l>GPF$6*JwJ5a|1XH z1jaN|7dd2*#Xh*#<@?h;kEcDKTQ=?|oDJ3S_}=v_cjma9$+A~FT^(-Jh0exYU1hKy zRd0Q)EYme_*qStHR~XN*Jq+KRICkE^PQ}RJy0j@ZIp%uL_l2Q=NRE8Dn*7?#lre-m zrf_knSUQKm4FxPQCJ_#Fl?Zi;mC@K2Q4Npeb>%M&PP|yKI!eo2sk(I@|J2n!_{#6y z2teaUule6bw=L+mZ(~`V+M!QHr`S0${mF{>NbC9L3dzN`h(hXgEaRovj-n%s-SERf zRk0HSWh)qXEzXfyFTrj&EO)~SZZ}e!8Dma-f^@{u(#uj!2vL*v>E_L=33`W%pLk3H z#f7fnrab&ri6MqV-h3unL~_w`m;1*TWbG0O zve`HD0cnO9IK?HJSSi3V$X#n7@Rv=bM7pNdb3mTqc?|9KMkyk0`C#!*Ykytlff-np zsqT1$)*e1PX74e}y7SF0pnk4RX zIE_R>ug;J66ZgE+plT*aWL~ox!XJ z!hn9X)ShPs_a7g8To;3ZdbP=oMuX`2H$J*Q3Rj2IXep(je(;gH1?IYv2r*l8;)9RU z06qo=L?a$`@Ypy2_?U@h768>u{S#L>X9E$u%Aw1 zByb&DAuXRFe1{$59*vsaV!L)1n$yj#CvgH7zreo0rpLBrmpv4=h2pr>dySgIBHv-` z{>|T`)>u#-t6`QjA;fTPcO{PO!BfQxAJ<_TN)^CI$v`Zqkjk9k04x~7lKBjJbCPU= zbRtd0@lo#O^$iDTUWlF6K*t<1a77gdo**rw5i{0dp^Rwv85Q$y?xfntfJPuiaXu+*8+}eG6yoa&TX<;ud0sT7p7R74$iF_GP*2R zXx$C>{)I=hF5N%yXnXKaJQl~c8T}KFbpM7&Qve>5mC;IU!Wq7lRFy2?c<7FOwLQRG zfv(nl`_m;^yp9U=kN&aqowR`xa&DZZZ@?M3rBm&p=T)X!ti`%jE4rC30 z{~tBJfAtUii!ru;(0{w%(u%1K7L}noWi>|06W*MlJ_wzd?;BWXy^T4E8P%*@*i;Gr zGW>N3Ce4D8^j4U452T>7F`Im!=xi{ih{`PGF*-r`S9vqJK)Jw^3p4p^J5YgB(S&h! z%BtTdi(HNq86B>BXA37+h{d2evcSGBDc~4DzMuyL!C_tX1EF70v~`^2H|KGNl=f3Y zKA(bUC+oMBG&~+U2o)|Zlu%UhcnT8P_fOk?Zsi_#Oo=GFJyp!57?JviGPbyxg8Nu={g;EcM=Ah?6wx+PkD0w?($RN60R?%XzyDqH|=b0>g$ zQ*rqLA}90*(=Z6^mSOJ6zEDHdO7(iU5&!s%FaDjxmZhSR?&rmMI`6$DLsOp*VLXE` z>n>;nCuy)9Wsyk=3BJ-synsh&FDvUVRIn@#O9=Yqp2j{75Nfj|fQ+>lZD^ct13V3? z7UBJX8i%>H22E7#?(ror1qF>Tz$w|>KH4|2sb)mH1z?P@*JB*G5uL~Zav{je%w@2K zoVKWR`ewuLPOSzH_o!hRPN)sYv9YZ$P5q*rCaNI%$gxS7Ze24;A6(r?E6^V&e#hwX ze&ZL1K<8)qBgdA3dB%-W{%+(zQ`ONkfK;{YqaK!~JdAqBYVkBvez{bXf|p z%L~P{AF=58J)Up)JQO$dgo>c!J))Vo1~OOPDLDibX)74mUQXIwlR7qq!=P#^QCg=_ z#zol2zl{2J0T{2SUOefEsBkr*BmvZ7;=XlIK>X1n+)~H5%*_?MK(;Yh`!>aqil z568wdm{#KE7ffE~pIE3zy8IPI^*&rB1uzXDs$E+4TMFg}Iw|U*sN=9GS-UBT#Ex^r zD^^Tnq;PLTC?r!16Z78oG{0Nv_C|Rd4rmaV3}-LZj480-m@I{g9Gw!1PC-nc4-WeB z;?+Ny+J@8Bs(HrJwBs2kEzLNN$Il~y=FOAbK^y3b-Q)=SPFN$vvYWPfGEWYn&{9f$ z*8l2)nUwL}W86x8uwoack@X!yxP@(`gJPbKHy{1K(PjWJw^K)&D&+Og!e zLf5l>8@q=ZV^P7{W0`-DGF+@0KC;i|C}9@Oo2`BQwxU|CR~7cFv?|9sI+E+UMLUog zb~fU<)OImCUm75cOS?>yPL*TTcHuhxAJuM~YbgyXB*+ndy~H_EvC{51mTF(hVZk=X zbu*yRnPD=zR&pFTJT&EkqAlJa;;$HK25MELH_n|?928-J zv*d3@z2tF}qM@G_FPhFNfm)z?t;vzbhkP2!f@-q)A{TAeOwnz~nSN+ef8mmHxWhEf ztoxJ3Sb9YVNofxM3tOv|-Qj-iga?M4ma)Chu92D|WW~QIX^lZAzdJcxc8I7+*5G!sedz~6E_Z;xmVWOX{{U&a(=V@ zbCZMH(!D}GfQui7vA@a1|3eig{LydoOLmlnjr4LQ{h#^XU_3y+ce!4EFnkue)z}eq z6(W3GTvbIpFOtr1*TTToimBc56`%1dqvWN~;^%n8f$waQ36tWfWg%j*1)Wy4okp|6 zcLJ@B3MLK7={{MGS?{mA9QWKDtZnV1hd>9)Ksh)@0uVqOKuW$on` z$5AGw*HV3jtbV+y`fcR^E;0%QEvZ#elu>XN#y0n)Hi2v7?o$wMTX-!SnN2xR1;ym7 zee%WhvJCL8o)S(1Ilf?W!b!>mrNAbS9AqB_$r0_WB|4&R^a>f|aF~rY>c>lhfy4w6 zs90a;S4H-x?HPhp?<`in0`adPof8t(Y{FYyJcnOmZO9g*L6~>MWkXI3 zhP(k)zurAhZzq7~&U=P6ysmBU^mW2U(+-#}%L|I6P@eiuPr8=}g!KGKooqLWetNsx zr2G(%Cm4Dmf6ygrpb;&tsAX!m1^BQ=4#{=t ze57#O%~@6jIJ^5Qimoe)z<#YjGogL3aR6`UUN~C#4mp0!=Q|+d8#F`S8s6W@aM|m- zQ1!2juj-M+FS7FO)8BZTn36mW-H;U4afNSU=1s(uyS_`|tF*Pc3Y|+QX{u>Hcd1=h z4Ds^rdApMhb6UT2VIPQr=Z)B=*(a-q?nPcs*2Wzp)ZWFm3lh}cC4ONKl1Fo}vuTKmp>zzJQZFYfKdLB=VQP}qskR{j%?md3JpwC- z30x7?f+$EqX*vg@zyl$h<<~3-Q@jx;OxTfcM-SfTC9vA68f z|3R^y+NJBQUrcLywt9*{^iBKyIq5Ev^mRpLy0C5Fv^SE8Xjios*i0lt%hLs64so>C zv^W>uS1@rsQSq0LH33YVj(Io?8piq#=x^Ub^aHUQQ6)m%V3B<~+t6CF-)izto@ZVt zXf3&1hdmkZRquaVxl~`0YIg(Z;c~#|uaw+;xGVk~aQojB@t@2U|7dimSMMs`v0SXV+lE?z4I@>+fEh^*PT!{dME67xN(i@PA}J{_5%c z|5wg!Obd{6L+8Tm;q6mKv7QeZPO_r-}SMU9HFsP6$`>|@$O4D{b}Zp#vH2WD2n z8AvrQ$P|Wsp*G;fsSUM01s?0j$0sf;Jog?x=hxi#&#TXC>eivUx5R)^9-t6k*brbK zw*!Cg-sB`V^ZbY(^g5_PgYoKDf)zIk>Crz>H0hA$;1zSr*09l$#D@4WET zOI(w?-CFXj899f>3S&vklz=~SZXh2yH<}*yD`cE1V(d5OKXPurKXPs&HQbu>ywqcK zS)T~h;QGOgbrjhJ0|ljFEP*;M1_edp;fK5%yk#ufQdKD-gv?G2&Bk4%SFqXFv42>%w8}52ppvVSfM%PaQZMNm z9L+W)pKH`hetJD}3%~PMOrI*-H#iEXG|+H!=e$Jth`AxdzVMtNKIi~qZp8_BnA@7Y z?W(YlX)WJsIc=EYc2&pKE9)mbC9Mw*thpKzN#~qy&dm*EbEW~24@ijIVrb0MpXKh? z$Z^Dx*KbH-&THzE1W#}8%C6{7P(s$yz{;A73OOeLN5yc~Y#E#3(P!_|O0l*L7+J^S zE=&A@XUWZ&a96Ge6%OpuElutAvUpdvx^MwSVhY$2w2URb3icg&3q{F@{}S>#&EgtBS!qwKo_w`6k(dUu^1TR3yHCvgEWFk#Xj7 zD4OcKbsGN?)jYJLwI9O7+y8nLIEF5(A`KpnN>UV>Lvh9y4Iv%g$Yu*!mR{SXP>zjY zV`?{Rk|CQ$dLfDHoMHEd&kzYwMih6{+~01-1pO0Wkk=ehyNWQh7|v3vFN{8N>zTsB zo{eP0ekGT-W@2y2Dsr(8nt>2HT{K7LGm-szJdVpUsK7O%q|qIDQe;HlMJC5ZA(cLQ zA_Be?UcAG5dy>{FM8Ozrt(K>)~`=boB2tuVx=eAhIh8e%?m~NsPPR_YoIRAPDurMBRxfM}^%Iz^kz6gpxJm zUMBrY-7~uv;{e_sNY>QYR-~#{!Ce*5KK=2UmYs zInlw{OU6yvUOP&Ue!LwI|1(Ud0Xvy$W5lmtEsM;8{_ZS54mZ+$zB2=2bs}oPS$W5a z6sq)*prM!;!8bsYgQ_~j6LU?l64zk^gkp0BD_y zwuw!UD2MkTL`HI+JH4@PFJLL}N*vlHD!rnK&@nY8K0vhhn?P(u@Xtn~u}SXKt9GC# zc9=e)#-oO>@_SazdAY}Tqfs&pv(f>+0`fTt!0O-5orsM5Y6U`!yEM3{oL5F^5CGBM zcc}Wk2Zp8IMUDjHJdCZM@gB{ zX8Q_`Zgyrw+hu*<5Eq{Bb3`}VVoKd?q1O3&*hC+JIZmv1;wT)a^a)2QGwQU>GvAVy zCa0HWEU2W*4-eO;`?C0pGm!=E?gV^Dm^pgY8|I)A;uy!kWpm1}&t6!6-@j)&2j^zf z&&+|zH6_q~mjHMsicc^COqg<8;Ac+5oUYFfh+UuBI1TEH!R|c1Wry1)^}b1TF7|pX zx#<$M!8i6PY{i(YRXq37xW?Bq{%9?^5jeo=w~~9Fbp9kuPS2gImNiFPZcfM8SD|7s zvkv>}TwMhRo51gbU2Cxrxk3J_U&7l+^o_Wkh@`` zMs^-28LWrVA(MgXEN>9ziph@(Wemph!yhzcvxmc}Vo38-9Bk}cr16fCMB`uy_hX8% zij2w}2((%;Y6CqlYx+IA^{cAM2Z6(ku~qlV^#xT=i>|6*RK3Hy_L+LFn|j(gftKZ*htOv8SG{7VWC zMiqz048G(kwY)hnTWuSq(6t9hLtU8lc4}RTu<2z2cTTGMbo~$ExsrUwxUfag>Ml5! z$Ztc^{O_TYz(>gD^Q)P2w4}_|Rw@JExthi~${9jY7}^iK0wy}G4o}7U1rFXIl~Ex1 z-c{@`b6C%-=GQrz;;Q%#p4#n9sxB089}Yh|kUviso8sZstv=hm!vfj#4T)xO|ENH| zzTm2x{p2f;dbu-Oo1dY?Ql797FVuhJx_ID}Km|-J>>~_y)nIQ_kY}!;8#$0yYwCzM z0yCs()Bx!S`#*Nt?;;5kKk6C&jz9Q+S zr5t8X_#a6(g#VCqTgcVEsjd4TNw*kQQ-O~np1yN@{vo(P=l2DCS_rc7gf-jTonNg|M4XkLrcL!3R?!ov_ zKZ}dKFKi_uP9bb-F@J{_s=N{!dyxkpx(l{HpM~j9cFn%`I)8Ti_~~`tvU0>N3k*L4 ztOxCw0|q1)%4<+^CuurfJu%44oc&wmM`oc>!|a7fbYFd9^LUDue9_MpVU4>)w)(ja z`O1q1#d9$w7Q7N72P2UQH3z8-T72>92@s%A4MlA9jEG#R;L8~#rN*+gToBe9RAKIZ z9_=Q5Nc906PVd3 zBL!*16IqsZmnwjrBFxVcSMnm>&JpM*#1PRV+0U#C>E7S4?tnRo;r)nzParHbTeXkD z6F|-Lg5$~}Hlsp9#s#iR2FCcc(n(z+ipKZ(iUr2lFE+RTZUa1x@)nW3YtC0o11*+> zup5gjXaxy*$iW=w;ak8^R8@xA$#+z0OdEi>TfazjE>M<`FxP3lTF+QWVwQ)wiWC@uWFN;SRq*C$m3g zL9S7xTw#0F>1ik*_(P`2K#I7@5eSC8CCaQTcf2-*cro`x8K+pGajkYNUN=GV&TPa% z)6rk#!s);t`T%z*(eqqPx}l^Idw*YN$l(p~WHI1y0vWbKa?yzSW}br-f4wPUS-$pt;&m?SgsU2uxp6CW{~Lm(Ij4sxq`Mo7Qfn$=-|x_0?k!)1 zcRW==@UdCWV)39yZgHb#rx?Pn3L1PLgn|`Cu&^ zwk7|>v!A8y$VSFA-8;;xEzOzuX3X5Qu1FO7S#iAIN^ofyD?2<`=dxSmOLRHqMJL2> z6l{bIFIa?#5!@8CL(xIhg8-7?VqBi(4ME^F@EdEC{q9&0>X4gL5QpE8y}KWN2bCNb zIEorYx5oK$%g~neyv1foLjPZ(ZwP!1Fb8cgT8SID!^WATGg=Zg9fIbusEaQ0>v4`v zeYZ4Xz0qs58E;>$ed;gmABNj1BBQI;%&@&zbZ$4KTP)s%7mHwX1eC&AX{U{O?#p$*NF{dbun&cotZ!N=DhQZm6esV<}JVWd4&7#{x2aM_qMSz*7>CZn^=?JC^|+@A6rm!J@{1#p20aO3OmI-guld4pR*aHmAn zR39)PcS8Wea45 zMUT;y)#obvBy`NvnVX9nm%_T~hl6ZmC&n;6MY11DSbb(YhI=C`pO&N!%x)8=-MNNj z_8YbBHL3`(_3LDgFKNpL>f*&+Wk&ZTGcG6`@C3t8nudA}ugK&% z#1KJo3@8m{ThdE-Oc}?SM5nrX+@id9{NS#NutnEL(p8W-&;5!Nd-J$U-~~k9HGPCNV@QwF2I_5I=<5?Lz?!>Jm6Lk0!}8fRSH0kZBTX@_MJ8R4Hn-R?C~FJ*_Mi#oakEvN zHhN7IqYrt6=9Waw z5Nl?m9NGiH&(Bqvy$WLjblN!gMzrFF&{P7t5G}}HBy0UP>e~YD^s=IP@X=cG7u#$X zHe;qJ$AcXvds~z)KR{>s-nRw&*$y}y2alo0T1}VP)r4W@H{>;MrtOg9bcJzJ>1g)5 z{fx5IW~F{Cwmu;`kByA)qAJME1p-ds9Uxj;@IRY3{5WEDL>l?=C^aNSE>c^_0J0)BIrIndXbE?V2^Z*OJQH zgLTVGcVXN_wpV+*`AZetoX%;2%A3}yzKy56EBs7{yzb}L7#VQyE|_u7^5FH!Z(o2| z212UZrP--4M{5{6sGMu(uA<Xdo zd+d7olery20rrV@rtMC7r8_uXxk&^x}H)vh; zScXLCfR9FZR$nkvP!Kyc)YpXJQt7Z3n9`-aZ zc-2e&8sfimpI(8auk>$fVduX#RQ#`b`ohBdk9m5*U=i9|ou7q#^euUsVKg;(^rHTi z={|bTHFFqADf~E2XdUr~1+S9qj@Wi?=uV(x zkuR}8ItCD8!*}@{M}}6$F9We;C05FwLf}?rVEOMkQfTdyc9aIBPhy1B zmb! zxdm7qE>Apbxu9_969F)Yx7==HWglF0(x5BbnXAtk1SAQ%@DgKOK2w~C^3Nr6S>x=; z6IojICgalyBb)=jhfI+=X-Upezp_m{cCeVmHta}v>yb1DQGwIXaFNnxBJV_+$Y7XcKzsBYYX0r@M+EAADHQzeZZmC zRM%OoZrfJz{Q~OuN~{g6?K(d`-NxIBJ4M2q`??K#>T$E2WliUer=X0 zsPpb<^X|#>5;WI+ZGt*FT&|1KAm4cJ!6^!f`;lOO#(fhe9Hv^p(d&W!9q|B_s%QS2 zh}~B?#9UNO&?AbZL5`xG-WP!lfmpj{b~=}8R~-Lx)y?+MMfq-I+|ai_X=c#h!6CYl zp><%TGD4-j-D7woUB{LVG=LqA_ZKgo>8HdFygb)nwzX1@jSE(mo$qk7(jHc9Q!7&X zy~fd}lmi5`=QTKAmYDt0B^-ZMl;|zqS3EUh%jCS2!%t!bJ_8lkSj% zKXb06W-x7A7ByuKxs79wdPk#v+v~(zrAdS4b}Tc~P)NzcOO^RrQJw4`0JslCO|o=c zD~!644n&$RYLT&_l;6D{io&tf=j1`5^1$Rmv0cOIp@tQ8y+{d&kczYO?u&U&rL<=4 z?bSI?3ptB|+jMs0+}b4vG#>VRU+y8TK)&-l9{Q}Y|5-ozUeO_2n|7k*ibIqrTh=jL zsB!y57Wz0oaPz(~Y7C+|^`;f&QavkV;>ww=c4Z7-`O`^T$(La-f)>@dXGI5MuzY+} zmk~8B^fv>`Jjs&u*+rA749w~k7_~~sxgQG7WqOwo+tKiAZ(azivk_Dtp2Rl5RXCo$ zY$drIC^!RPsIR$s;A7ulQ%L)Us~Uzsw^Pul=)jLuEPKzi#WC!ctfdaMDy@%umb(nh zXH2w=Z^ciLfMNwH2O`2Y5F1ufb!I-qEK`lAR&gooI+E@`kg9ml>`NS_Gi8}bM{|su zW>B>h)XURXh6TIrh+bo2s4Gl@e%YjAr_O`qCPhbkE!i-^HPke^OU6m_eDMr$6mf#1 zcU6i54Gu3kFgZi6318&X3cZfm$;W6~rU*@^w$nz{mh9ON+5g&sh>h*bW2o&NKkve!>B=(Z9J))QQGOTJNpfz9G25gUN$=ey_NIC*>&{!Asa47&5AOYzg8Tc6 z5|js7J)m9n{_N@JrToQVRmD50(1w!h;(42QTfIs9{WMuRKm4&${Qby=IkEfB7wI`r zIopWfQkU@TmM=+x>gQt-%xdfKNQ;5Xux24XUwQVNTMi$h#;Mo8Ket*>46HFgr-nOe zh8+CQ^76^A_Z=R9d+^_J`Ti4%|0ab0*MqPCVBHv5_}*_tKgrylU^R>k;c;dMDS*Il zrzt$lmF)*DSd;DAC_K-{LD`9A>-isGS@KM&RlGlw5iZnFraw8s!p zOd+ary*hPFx=UMpnN}Xg3@zoTDy?j%h@MZTX+I(hzsYiFCYE<1HGpzq2#Cp12loZ@ zlFaw5o)oSGI({H>;z@S^V`PW_5o50f=?n5$DnZiHS}C8GQ3ugP`*Dq)+p0_*~-nB9z8*HPnR zH5z@9S%kp%pq41pS(I}G+Tlu{aS1z0=Q@pzZGysa{spMB%+9@I?H{Zz%)dKP$|ka< zCCVJy(KapA{q4q7UO!gVteswq5r3H0A~zH^$c)8E0=gF(W8Qz)6Demcd1e}R%hVfL zzSe+|JXNIr5<`aFKYlJ!6e?$}q?BHtqH6V(SBa6p-5#Zw`z}Sp0V!;JRGkM7;}KT! zHWx$1n@{L;`kMon5Y86#51cg4+7bB|-xhewX3sf%A)Imr3|uycW{R)ZqTJ5aq1K@% zI(_?64SiKQ3kt4O;Cmqzq#02fuXaZ0ce1TR+W7BCxvxqr=Cf-V^DALxZK)aM9~Hi} zsriIV2F<_q1DZO&HLzH*L#=sNjN3Wvv-K{B8~)U_mY(H9JCb=?r&DLAY|#Mneu}}K z@VfuK3%PG)S%v2VHpOvjU=I6&`3HexlG4|@EV~J zBnJK!PGoR?EKa|-&`p~M^D`yhLpV#WW$6KSL0Lc40m5={I-hURl z{|R~Kg)B`pRZwOq(kZmLBw~~7Q%U!j$(=uGDnsXk-~!KLh62Q)|it@#DZ3 z1osT2Vtr`^N+J-tV%%iV2IOpQ-o3^--uLJCTkdZbPKG{=TtXl~1p+wmAV62YAt8o& zYiJRq4O)ktl;KGycE!T#`x0UKw8`qV6PJ3N5~s-JS$36Yli2nypK62VUyWkdG+~p8 z!=e@!sM}Hm#3lPc4c1ByJ@IIw&a~n1}#*8P#>wrVyM@kBiHXE@$Vp zFmZcXO^WJnj|$re*e^ZCw#hJk46yGm;+=|ubLS7v$r>*IFfl)~a{GwWLu?T!T3RC+-G?waoVL)`y}WRfc2W;_5DuMmUe<{Yt6qsmpMarMz?~A zh3+g?Z?y0UEjzd7bsZ_~h-A*uskNYMt2gg(XQ;$g9-2#_(Is8qYUjo-_XYKdZg#6g z`w@1nWY>$N!-zQK=`E;dViLR#zKu*A8@@y^mv5r586vKrx}NcPS{#Iv)D0Z9`1 zgt@5)lZKs}0Wku=UTV?@_Lx-dlmCUiydSFo?9sO){ulOSv;c43c;L;FwE@`MwaIrX z?E-;q$Lgp@Cq&&m_BO zhUwj|y>%NKE;30-vUZXvhG^T=Bf`e??}T3Yl<)8LDQfB*vhDNycAC=%_Kw+%Z)pM8 zYpak**HO1!fxJ3pZb&R}-;;4S+NlsUJw*Vx8w^WU>(Mb-oo6Zoj_miwj0>hy+p)@T zs5ouY5*wdTTrJ{U6bX$pJ|~ukj4}~866#^VrK+CLt-{PQ?|WCO@v*Fo9`Ur9Qy6Fc zgmYU_KY7wI!iAd^29&3l8TZ?436X5)C9B#GBSp7xxT^e)<*3+4AX+#1fy>-GjAvBB zgDGocTmq^^&>*cC49gLQ$GC5BizbU@RPw4!*}MG}cFKU+XHfCk+$w$SOvH0eN%G|= zNZL7BK`(S6a#Lw$FSu8z+O3L3`<{!|YX6Rrb+hA0+$ti9I(%;c zEOz^Se;JK_ul>b1R>Sx0wl0jX(OA%L7S`o&Epo0a&-z0>`a_8z7t_CX)Xtux>3F#f zH9f8m6oIrt6hkIxd)#raFBX4LgXTzKyPz@CD^lm~pb%;rlxy8mBBe%GqW~()qsaw3 zX_H{EXh)BaCe`E~jn1rVcrR(x_XjfKkN=eCHJM>+{xIkM9c#lssP}&;*|9(JYG9MR zF+M4bu4;n~Tgf5R?ti#*7uy6c*QNb~^jf$8gKLnNUKp0E=g#vjkFdW268x1?1I8F3;FAA^upPc!%Sv55;wPZruA* zu|)*CbZ$HV>I(oJ`&Z-2&VS9GYy8jQ;m51KJ$J|16rJSsWi3NdXu<7YbDW8LLYk}8 zj?3B2Uy{_w4242MS@2dR3=C`w4qa5WpbD*^LI%luTj5?9=<#IwlJfHD^$CZH#+@@i zix}}~0Ad*$maZK4E$40%*Sz`Gk?@6mzy{ zTuuN4e^gc&c}yCGdCjNo10p9JiKPHHD={-+Y{2%WaCn9U(&n7!&Pz7mRNC4I0qd8g+T+6E-}+phRQjX-oV-~Nhe zvgb9#B3yzukyC%JCS*;G(hV8-D=_yH_!L&~H{=WT^;FMOKaWoRJ_GGo=qZ;NMK;o0x6TrOkn_C#{M`YDnFF zLoKm^AzWYg(cmC3rY>d+#GefHdFw~bZHTmz8H|U~Lu;YjIPvTp4+yytxCJ>zB^DMD zr6gC7*=2a~Ug6v!V*vVt+-aAf<(#F#^2KxG!RFb5Y$6X!Z-bM`gV1SSsYYK8{tA;U3Z`xQ4yZ?Na209r+)%`fbq$$_f9?6C(*o4~|r={hZF{^II)H4w}42c|=uq?VG*pX_{>$R-B@J;2C zX}=g}FtVQlGsfatNE{4@aRYeMlEtxpF^)-MP)Z~5I2e|l zS}tm)l@uJd%^=yAL4<3vZ08oK6@_k8dL}5az1Iobd^X~hJ#&g(CM{eQvjMbP^3rHl zVl=UmkVqRMa;D7*Pt$3k{g&+gUfmDxTp7C1pWwn-ZCLrQdCZx&DnYeJ&z z|H+)G&c8@Jk;nDIsB&vHr!`qI6Q-2R*SiO4Lt6&7;j{+*rco$c(P13ucMY6-E}6<) zCEhyGx6kZBl>N_3mjrlFtOc)=mcF={upB~f=;u>E4Iv)vv4gqy9t?~#pIT0IcwKQ$ z3}VzpvhbfBW!i@I_dR9WqL_?OIZUX25_(KumR?ScGGQ6bAudrDi(skCCgQ)N7HdnI zBa8*U^EE?C{;t!()!TEB%9fb%FGU*{rU5><7Id}pT>u;IqHrMNpF=`r&74}3q4)Z# z?uRHrkNLqTEO7@#?ZVw+Zuc(%k0RN7QVZ&XWCaXs5zdQHO8uxki~oXdMOzt zI#L05_A+OetNU^ss_VV7kN2{r&tr#=!!kvYoMu^#J6@*>=L;yhrsgw#nIcw>Oq8Hz z%AdVC9uT86U<3lmJD2tU=0!@lGMPEmklRvnS96|8XmbRaHx}ibrS<32EsYZxaWa5? zAL~1Rn|=RT(Hj3TNrCQjy^EE8ygQSUHL{y#c_JoY_OhUXR`@un!Zz~%k@l8Rd9GR3 zE)bmH7CdMmxVyW%ySrO(f=eJc!7aE3cXxMpcbDMb!>+3C>fJTEcAYcE3xmJ>xmc`w zu6Zrr$}U4nmQVuhn@Ij{LrOoV1F(;>Hb9{kT*#=uVg>5upV>FdG3QK!7X3Ui*AZv=%{bbOMO4IQ%bcp1;0$CKN~<79U>40m;>?tK ze3wNABuPI6XJlLY45HKM35pPJR)B&qZ_eP!C1AUc4pAa}yM*@Mip|bzCdO90@PsmE z@$+`;#AWO!mhdnYPi-;*kAC-LkQ;HA{S+3;C-wm;ixk<-4fi2+d=GQfJs|CNwS4WP z$5)PhzjrWfW`Xl+Q$6%6DDecu9It4KhPZwrlc2GGy|7}kFMo@6ZW#S1Yr zC6`+2%}&l&(;@JEGpv<0>_jOlEaQ~zj|a5OPoT{#I^)ar!_LU@ef8+;4K1ofpjUa= z3{`K~GHDQp1uJ;f&1Ua&E_B@YGCkH)ed;SZP0rHb;JnWAUhSp%l$86_`YocxpKf?~ zVcyY(rH{T!d>5>=G0W{lue6!O-p0FUmU*`h}4{ZU9kaJe7k{7lU4A1v*+CiP{Cd*yh+2xp*@*rj# zADV&Gt$8Tis_ldyrm1si+S!|@l*G|w*I@(4`aF|P+#YO)Z0<`Fztt8!WoMaUa%CW@ z3Eo?#yd0Ad?DRiUI3yDhxb+|4Ch2}WlWp9jmXB8eHR z-YRVy%IT!GoP`siwy6%+q5Vu=YW?8xRSR=K;Op`}$y}*LVv?5NCi!!o!7r0(eenS* zVg`=8DY5-PLR4GU9xh507oO4#_@hK^O-rXL!%L;>EPQIag%PUUJ0gMJUMfP? zT>G6nyfM{QoY`Bu(Ob<{J`bb(>NxrEn}n&>XUG) zP#OxD^>1PVSXLvyaa%tgYy@{AAcnx)PE7XO9xR`03w(12uQzGgg&T4C*z${v2jIWUWs30zk3zp+c>76JK2+MK@`a1U3k#i&45B@3@QRi2V_ zP%r}y9pcT0wV76n;wh-QI3DIHeo{5hNxBRiK^DUuS!ut5{m&g{<9yZho0;N2+S2~7 z*zUiKD|7%`S|p*fuTNdLih!OXS69Jk!UQIq@T<|1Akf7yvFeUvf`1jF^VaJ7_rtS6 zVe?S-KuYu-ZVsft9~s|6e7-7DU)|3?xcGM@*8yTRD=FBHkoLwZl2z@XCB*&TBzLt0 zGYHZXeWTtb_ka4;>i6`U;{mk41=Rj(p|A6QCDa%hl$BsW-hJ+#QGWaSQz+S5NmmSz zX!5d#va6om?B)g0ET%Bg*KTJa*10$hNY$ovx9OFpAXY79hK9s`jS(s)ds9^4n1872 zfr82;JL%=F_*e%^bWWhZm zaJp7`nsv5DMNDMsX^F6LalhQ3U15bWFv?khv zm$^avb#9k7OwuoFk~}QJosOV10x7UrL4uzan6qN%B=yvykJu$F{Wx5a`r$EsSAB<`z#fq)C9J1fo2tky{NNts z8cq$#^=w)FyFr2TBtIt*nRJ1PeOT z>zo4H(H^$^_#N%aX0e;xilP1NoN*uTG&RR{8%aacy{ZkzbsbVrL#m+9Vva7e1DyEj zw}b&pjxv)~^k)=Y=B{YoPt7rG0dkZN!v=a9Tv(|7B)A6{lM6xBLlOk7QO;WXX^%1L zj0G&5NfBTG-|^83sKu4{jmRn3;Dh`0K7y8}MOR{YzzQ3eHrT<#K8<$WAnQK+ti!9^ z#2K?F@GTkMvl-m$+-3~#MJ&6=aN^DK5?+U=tLg0jE{$*eGWhUON2#N1wX{rv=`586gXUh z$4X>QtNBUvn6O=&6he(xD=TazSvFTLioH0*t5|-FQigd^Hk3RBTvo`YJIsA)jbF+m zg12`QT-4WfP|xjerMSl#VlxUhw4}{YzC&}lavLn31vf!*1E0wOs~Rxadj`7#H|;O^ zHLQ{kyWn#Ug)(w>h5?kdCnos?z`0cx3B6E$VUl;HaZr9hMmy{F^5?qBuQSZ?NdW$S|9`^Y|2^6Q_>)ou@K;Bj3U}w=0T)5} zMN=~@50OX9-u}d_ZYhB`CbRN_ZaHBbrL!MJTJxorEHAf5)1XRAn&1mvUYeDDDE*AF zCV>`JLUbfu7oGhm6qb2gtb!pyT`+`0ec-1iO?~UT{l(LXO`F1O{O_$Kn67;o5UK4l zK!xwmm^ge#x`b{o{*osY*@ieB7|RC^dMrcpN&UEX$`G?Is=O0D@exIdF}O_GcE9=| z)}^Mi)6*TSQ!zcrEsKs6M(LjsX_rE7}expUO zvj>XaMhDwm&2kr=Fmqz#RBjPiVjef@#wDr#@ zD>q%m^a2pr0U(eohAl*n*j+l?N8&g%3=}2O3GTp3anU>rQG0Na_GZL;pyV(fCvDjM z>)=uRci8EKpHxl^acDpM1P#YCd=p0P)KjPfvnvy{3J@T?_jVsb%Yj;RjAGATh9ip1 z17;r-79ZM2*t-}kYQyjGqJ z=COwcdmA9?PJg8|^Qq!0m>rJX^|loxBbpP`>x6tNuJ}@E;il5`V=mn=sfOq9avubj z8@8`kuN_Z{SugN#s6p;OL&ON28tEL9NI{a!40XeHlS?rzO};Z zSL|BD`(onek>{qs2m!9@_3Sp?Y7rAfM#^YW-PR(EVV4L zrbdrozB+p-l*lQ^$P;%Sld=lZ?I#u=&x7z4vNcBQKmI1gub28Is7y7cj1M12ftpC> z1It`#F&TOgv0-J{;Q^f==SF=2h3$8t_zgQw!&1=aN+wLB0t<&oQYj^PcH1`#Tc8I! z0~Ya^3~SOici=4T2i67LyX^Ca_qd0Cf?b{Y>3A*+fv)>Ge9VLVy6Ks|>9BV5Si}cz78Bt)`F9`fk6?l(+ zacXf4dI-JQ^<&@TGq&Ut2PqAtb%Bz0DjIiO(sNp&>aF*Hj7WY&Q3@dZ_dY;I#Jt!P zVh~$TgxThdR>v~n>1_6%uK)7PSmGT2a7-@#(1pI}ON}xAt`-%mcsul=KU=b6CBye^ zV#Jxv6|cI=zT<*oX$am~>cyM3-UZEt#PWrkIb_KBYHgp+(yMclKjtaT0w4ENtPjKe16{;A+ma2E9-Fm+!8V`EN4)b;c;G zAZJ#Z9R!tjIL(Zwhv4v$H8=!FscY5IVk&>WYm%S-Zd03BfBh=2iZz28q>}-$h<}Ai zcqJS2`jgw%$kF~*i0?IIoVJlz{bik?bg*!XjBOLylO`)AfY>B!iTKL{xGrWLTBV3$ z%*Uqv*)_-5eDWTiq}oMK#^2Hl0(`DZHKh2oU7Ht`@$4%KDy*a94a9?mSv+jhu))C_ z1uzIbAM*p>iQxvWA>5v5gdQ<~t`PAvn+_$f7_)-Tn7(P)Os)hoHHOArW3GQKlwz|h z=XcMjWy*g=WOL^x77Zx*s&kh4y+OkCYVhiQ60Z4@NYOoA)#YKP7+yS|G@4;7s3_s* z>_HSWa)oqIiR372SpfDTx^A&*EsSc|mmzcU{F15P#IlVpO+HZ?p9JCM%>_GcG#xa$ z`n~(U|Gy`r~{{t!8e?#!!4Z8mjQMO__>d+)NsL`5d zyKD>Ut5Omt4Y-Iu!PPoC0(COUA#7MxBp0^0l=r|2cfp1FejM=+2rB#yg4myuVmB@R zfZ$Z^`l4RxaaVVXt%T)@%kuLnaG87ev zOb?U2xN-w_xJ)2X`=udZNfFTlFyFS8_7_teATQ^mERgKAUaeLdEfmVm*eNK>)87-< zW6FdaR^Ey!AtTf=CScQj9J1pNDk3vg>lB-ba&&L{EHcciMyhDfz_MV(w14i9`IJ3I z`#!9K5Z~PpHqxmhT7HAE?z~dl{Xn~sfV?l&jt(K%EhHj$Gx$C3)mD@4Pth%;HHbYs zT=!JF_kfd)-xe2Pf8ztgxLsZ6;pqaf&rNB{Wx4rs3*qMIdQA2mbw2btF-|RN((vsq zYwmlzu3nqs0rIcBx_7bk7#Mg0FwFrWEZusG2pH4Lf!ACh?ru~e!CE<`;pEq$j1KqN zEfq}^yGO*IfRlt*Z%DKauj#a$&&nqTN-r8i&BMRsOyWQY4gwhdWlHWwV* zDwmAPi>0A>CuruK+Q{ZP8&plL8*!lDS@q^|ZcG}(AA9<7=Vmz`cCF>|pfwZW(sypO z$utVEOQe+-xAI zw99EGJlzFngPhDMAWS`LjuyjW3g#g<{hbEj;N`3Q9M+CvkWLC@vdvT?;nW`-G}Ti@ zJr4D?NgJoGCt`m&CnyaIB_zIXfGAgF6A{P|XWPYC_VTL>*L<&@Z7v?AZFhiQ-_IEL z%^1Ua^y*qPTsQ_I+?<_*pqsTCRlz;PA2lOE=Gxq7icKLh7z0#i9iHc z*;waQ?HRL1AgkfPXHqGxUE)_El`^EQSqoC6zkhWgm0XjY=*!QT>!;u(9qpCIM*kg> zGgsLY5;ZktiFa*pI^d*ZPpInL@phrs$0G%(4?*n`drGCY^YnMz3peyZh(fhf>Y9xr{}N1FaXmD`yZbv3#%$ZH6W9lHjp1 zHQ@HFN8i;AjCcL`cP4dG|Cyrg9~}IroI=;Xs9^Y0ix_#!Te0r65isul1x1^<$!(PpKn{DJ3LO;)tLu5PKD(?!#EPT#_4!=}C2*zy?a zQKDAt5=f+o%W6sXbflTm(4CCnFHEAoY(>AZS^bkka`l=EhZF zMYZ1s1iEj*oD2EgDjE4^hVTrrMMH{cHfEfz5)Qr4r8P-%%x`Bv~iT;#?%u$-CGZg9fj}UFm|~K}3Y)96!|0>>LW*j)zp%KY2oTM967< zrm%n!Wy+F+Q#J*YiBjOKrz<{|@2!WHggJCi40}2L1_Qkl+*{i#_^uy1elxVg_lp#Y zC7GTN=P>~iU|$H!xPJgyfUg$Bz3$UPgtM>6Y?SQC0`YDn1%hW6v9`zI{24e1Ss=<8 zG4&h2J{(td5Ta2PB(U7kSf6UISk(+}u728{8Cg`ukgmn{^2}ltQoPLL(M07Vw!C56=CEDIBJSmF z2QEhrdz=Y-j*s0Ns-PW?M&X%dFLRJe%P`dOkpoIMo99!`_2AkqN<^!5og}B5sI#!e zZ|&#i6+7xtDwB+qUpQqS-!qsuZPfQg(K9&O?+PXlCscdIdTL)wR;;~$#Q*+<^cNH% z^~3Pydi^{yM(}h+`AUM=3|T5h_Mz3F_wD#K#3e>?%Nfzx4wJfy2WP%|bTvC>Vb;?- zqE%4F>iPgbks}g?T&jb07LuoqE~f#Sm$q}1TrZ*MJ2KFf0UxS!-oe+{`;ut&FvdRr zAmb$cRn*bNMH?3L(VOIrOx5eA9t39G?H+{keQu(MrG_B^Z4y!flU?p0PW&75>2)l>2|%P_t`-~UZMe?RG8h0lgZ}CLZ7SsU$+Hz+HdM#lI1f7 z4$r!iEcpc|N2op|rHGx*c)C}JAH%IvI9~S;UH7NEKwwg`W#ZdUEKmq*D-}eLTcA#P zF@I&$7J3Y*t% z&7ndwtCX|H2$)Mn8KX)}X%gzVtWa9EI~kaokOXz!91bTD*TQ$hRtX26qt&})c;dp? z!0hZmZofT-kY+x|5~+f1({$?pNSf6RWz^Q>qRMGi!F`#tYmUV6O7O%OLy z7MDf^$(u$bVtj^)qe*M*!dq;p3j7O^MgaI?qFc|ZH$)plBLu4TT=pkBUw;4oB2ApiLwFw{J z^>+jN#0cmU9=4I$oW>H1mJ|4R`e!_O+JSbF`#)VC-$BIGyjdsyy0Pt_>G<#FVC#RP zqpQ^>UQ==1BOP<49TuIfIp*W9F(Vw|S1W8mPW^0{pC@`pc?L~O?oDz#mDhbl0o7rR z1l>|FdAxN0MMrfp96jHpoUgym1^xG&V2lq38pgcV9MkXE&+e-iV&`taLAlHab4?uOC-2nKM^KB+BwkoFdMSD-N-vR#>vCTe zWsn0+7r$GCeh^dKLo@D8uGkmK zBKL5{IibI%JblEFGNpX2V1TnX89*OpW7cIEw_A@o7b+s8of(IOVz-Z~y~xlhxYGWv zN^?lbxG>0RZ$h6b$&uv7?T8xK#GG+c9s16j%QzCDMJm|Em9k!Kg2%a^-;|bOSiS>I z{s)SpN46gp^}5mEvivda{YqRl4l0GWLIGbuX1gpA>$!o0yNA(3Za_1QHKWkBGhSsv zqz9h|rQoVqj3}G64AGgXk|n|=Pku`Zv1Mz#0O0#2(uKoNdu@6cLO}A}3GH zEyxS13KR1xV|Rftmx;$>Mu^E`8U=i)8Fgn3BtMX-tGq=d$FWulZy6cY^U9@WKh$1z zD0S}!3-ZkKo)RYb-pYn)-NbUjq}aF@U0S3bY=vDiWo?Fm!7qG}XCi_}Y$~e>d~SO6 z4@;T}L(N^!kL@lvepc|>+Zir1mE_QE==V8xe;TT31NVsTb>?Wey*fSdG;t(h|eqEzg6I;nD6BCL)3Z2>+B%?A_CiVWtH<(sq{0nZ%IdO;(wdf6y_iwy-0F73j#WW&|Gs2n9_rL+5^fB* zwF$^|0dx1)USV@s;1Z8TZh`nd$Z=jS1u(cRXw`X_w?-ZCUru&8FGArPb)0~6^-<{DL?p2mMof18W|)< z2;eB{YDZ}Lox-{f!xzL(6!*~`3k-+V`Hq5Uc*|WNz#j%|?n%$b5Bed5jzR7&kb)%dQT{l`|cr4$jJYwjc}{s<7xi*Q9y<&q)Dr)STJ4|MfW(keC574zM!0A3W2u{JFC~za!HfY)T)8cuEPuz zImk?2EmRiM48a2mw_aoRlR9!L?%1EABXpJ=4=vZVNGPFSv9n*-7(wOth0QShm^;UR zp6f_KABDakm`c>X`Yq@aXf&1_<9! z;(cYWd3NaLLC?ycidz;R`z_hxl@2@J}u-&dZmV0SE%_460QWUA>CmV2aM1(rXt-RjoORafDgCAFnSu`2?UL zLg+%k)4)(nMMqD*-&82WeID|RN$||$xOJINgHG64s>vJ7q z^X&5nYq_uCC|se?Xw8%z#=@?kAIj{6*FFnlVhP4jHujs3IP(_cp(1-|SUyof5+ssFhioloRh!si6>iT(Eve(;qrOp~;2MkB}VUw&J2>DIP( z^iTv~m#qPg>qZE>soT%E4$*xgVRHDJo>crNpxm;$LzCQO%8J8=;e+<9vhU$hT4MRP zU_TNloKqkoeppE;J}ANwZw#K=HIE)VI?Vf)Pf=zgfX#osy?#AMA({<;MBLUgvs}UB zTBq;Sax-tSpzi!gda@DW`Z_&RI<`C`CR>tT=EsZh?5%G8rEt4HE5nN5p4B_;=+Ua> z{qJZQ3hySSG7X@{XAFiCL`9paqAC8dvyeWN)WX%GWbuguQ?f6Wxm_&NM?T^Uw~S$R z7UM{DW^0j+<1rpyN~4h#OhLQLpA~KmHdiNg0382%yV*a%@&BHs|DkXL;CMVt(+v?z zHEJXEnJ1(gNh4{V+?x*uMSLZXU|gk08abZm>p$QKyy-0FDG698El6WuAm1d3yomKA z3j=VR{u>;dCkx!_3HeW;BusHbMMbIrwI#RX?&$D}y~j_^5@g>BSdcF0cd#HJr2E7{ zr5W`M$ryObnm#({%=qJnL)6KRcw93|>pZr0qJ^Mav z3=f-;q1^$FWWgl-K$MHy0^UB;UOrg>y|-#iZsF74;dnuH<+-x>{2-8b_08n&MN%GI za^k1iXY+_2_z5%0oeDoezS*XR4><=jB=u~9!q?I|Y4@9ZDo6`w+`7r%5QqqsTy(KE z19_q=J`ueY-B<%fH|P3%^EPJ>5AgHw{S`os4brm=7*5;%sl3pSKOAoV1CWWt0x*EX ztrKv#rNI_+wg8_a&fHnR;YLz^mfCdM4QlmPbTj;i!;Kby^VcPr%VU3L$R9;FKXk9r zVD)f_7Aat-YU#=``hzjSh5ADQhnuBSP2r{6X1JG6Pg)z`a4UL#4>;UZ75T!?CKzm} zXl>B90%=*t%($vZmEZW-`QLopT~BY?!DDf?&gF8bG?+DRNc*{0WegPENdIp>zNGz) zkDvdEkIJ3n^?&Ch%O8Ba=}m^KJQ6T{fU56|LTowr9*r{YZ({F4jUIN(0=<0*0Odx; zm?^J@*qy#TLVgT{=8n$Wc5(03J$zn*BcQYs_KQXH#PyApx#Z<5+kXH0WuOEco{O{5 zDBMdUtv>!|;uLyS7ka+BJG*3t%Y@?J`IrIlvEgE?SmN>Te2o7aA4dQ_9=`EW{cn8i zxOn5^at%dmyWRyv-lj`(>(-p9S6?}WpnwnG{#M}E03=u>eIytT2$IoAEv^qo29y{| z3HKz__foE&d77=-D7uUN$;&VM*g{J_{T+{CHjdvdmqE`p_K2(bA!x)appePy$ve=6 zU9mopHDueyWfy-V96;CJsoqV_n2!7v!d+IIKZ!8l$cDPWc~&^qA1Mj&k$w%|1qa|G zydiQQ{FuH|e`#Q1xGlg(FMy9Y3!I-gd#7(GR9mt|a338<;oZKibsg6B2$s2RRQidg zhnz=)O`u=fog@20H!9N(a}4D7@AjiYe9F(Tv9_atA^^Eee^aAT;!&5(~do zK4RqDMy2QHS2-n$&mdjRXFDv9pbGj6oqZXvhwX<#^X%*r6sa@*tZmOI?rOitMO}Fp z)JV8x9#V`GC4$7w$@c0z_{(gix8K&5dDeQEdN#s_DMO8tGvB5qkNe?xh1Z!GhcO)c z0B9VMKktiPE2ng(MJM3A%sC-`thUe82f00)oB>kR~Zxj*k-rY z&O*xI*J2unrnz@oc&_2-XFZbfu>z51ntXbVxpb3cIbG!|&p-HRVg*~!uJUI-I`|&V z|7SI4|Ha3DGfV%gnzO&^aAVYt9p+$13M5Hn2WrkN)m?ZSndu%_fbeiWGl+#J9R*P& zbct?aw(H}@IdY?S*j~b`E@yQ(zRR8Q$e*TTq!Im#Jm3$&Uw63K{7uO5?-tG4N`Ei> z6)mscSwY99a){%U?;`kt+s{&g^yp6z(>@!)3%NvKiA6jrG>JjgiQ+K6iGEUBAX$`(~dG@Vti)5q02;3n?5^{&OV zYDh8_!PgrCWDyy|2o&UUTo57A+d>*?}TE#S+lM(f%#O7<|Hu55g-KQ(Pna9S2Eu0t z%H~<^0&~;Z)^n;^dKB97YEn?*UHDEGcv#uVDRj+U$0$bD9!E0nlL|k0{W3f=R{gr= z3gwv`K*^Arx1q?IS}W%RYC&51+{K@3RDfRJyHjL{IoNfDysKaGd)Dp(sgFyFUQlH> zXvm4OW{}AVxAX1y&^sZP~H|Ymnxpa5&(1K8aIvz_}mLZchCfm|uFd0VL zumFjxre}1|X1LXb|A(q=g)t7z@=s7g8Jfqa-7gjU!l58-eMCg|z&~Sh6)BWDZ}QG> z$4pf0@K>W+>f{A`?^#s!-eoUmoS(}p)TC`e`hYOGl;(iP+NlR|hwydj8r8=rX+tiW z>s&c2I7ZBfd>LWpSyH?3uXI_qMW7g&P%E|KjXB4pp0`A~Sd=td+S(dzS(XfVk1!YU zXlc9jJyY6dprIs#b?7$Ptob3V&5TBev#cak!!ibt8w0nPk>BAw*k>f)9B#kqLQPpn z>(c}Fq20gKj}rM=%z!Fl9AZ_v6;U5`kC@V;XvuW-`D(=4gI@pCUlb_KjSjcKnedgO z-t^e5(9pBV`(fjsO=DJ$&@IUF6_-u=R_2RSv9G&SmozB;?1B`lL60l36l+FW)_u4Q z^)%IR*|8xNDr{VCk5P;!d7q|Tv z4FAn69A_(qYKq&JF`1*fc)1MF&^?Y*t_w~I!3d`Y=@Cj8WxnykprS=hKaveqOta!i zT>wF&xk%eZQ3t7#>Vzo>)1+&--ejS327B@Ya~E=N2>l5X3uC-Yl+{4OiJJxF^w7=H z+SOC*-N9MI-dx{l6oDNF2qYSanW%cyI}ma{0*9YZikg0A3KKKCS7E+3x@C>?La9e+ z`^4pQ5V0V?T|F@zXr`%}oy9Zb9dy}l(n?p_rz3JKpYD#oLi02uH1J(bMYjb3&q4eZT=fjnwc*L%89lh zGcjLVij~Z%m<|=CLkToLtmy%QO?N={z8S_{RmH$P%L8eK1{2TJ-{WDHJdS>pk}J3R z(yQKSUz`5hIrwjt3wS%B&y8I}0F~YFf{9A}C5GEEgF3;^1YHE6&y$RUdJ>jY8U=oez{ogY^ z2?tS%&lqQ>Z7}PSGS8`52h3@0IYub2Q6BX^Cqzx6M9d6C3c|dm3kS0!mp29Icz7msYk_EXD>xCbW4Kk;^ zA&*c{Ix2uPatFk1P%~hTj6F_RXgB<#)*taJ;kMU77J%20Qm{i9cvkQ)a;B^+A@R!* zblRRay}N6Un(7&L)4_2!AshTq2&d1_Q?J*n6RoR78B1o|cRBV|)ww$-8Hlc*Pw`$3 za5S%mXEb`Q|IWju{>qj6pSuD)Ab25)0YD#wN~qiKV?YHVR|Z=ThjTwx8o)nEc{0K1 z5n+4Yp*F4o>O}HD{5iUOs0ePlx^JG?tfau5{;n)6TxSl?-f;AF&gXvy5wxzn%>Of6 z+uwQkZ)V>=NRLYqQb)YjqITf1E_)dSB_U?x(q8 zzS-K63-A!0wyG;h8L<+(We;nuY%(=Fy49oUNqfH+7?SF`BQv^CD*SveUhp0&$E+^? zX(Ee-Xq5dIhXjS;zEGXtl%DlG@7q1JvkT{G`eRGmom=|j^QqTaN$tYgH3=n=mMVNw1544OnFuy!Z*sdq<3Ow`u@FtO9BKBWVi8lnat&54dLT2FU#s2= z(3@B6irFdLknP66FhETbMOvWzhpp}Xo2`welkEu{&(svJ75ood+w7aI&AgRMdyav8 zWHbYsXdYGs!dOL{TngOZ`MoAc<4F3 z%GmKK5N@xhPi2bsyAgGTE_{d;<9J`SIYRuE7X%>@zFaKO$ax`$j44&Jf^p)#nTvj> zc7rw%S0wtsBUg(*Nljm2=T70Wj-TFGFx}oZw~pz8NHxo-LQzoR814Y-MLd38F#Ma?oGE4VCxx@dC;Qr^OlP2k10q;MzI_%jX^ zs6UY{eQeO2G^fb!=feQI2gw;Yg{6@aBKmz%O9ElXTG}4?7fJYy!CuRyhLN5Z6y@dD zXp@2LXXc{Tw);)Ia2JRy*%q@29TyAM>%+hTcQIipN?NJ0*0CmteG0!8AH+uRR=BLN zGpfzUzTbIBydQ&G;I*i9@T;%}Vu}eg%4&zbB(0D3xjAc6KC(Dp6TocBWugMQHjl^5 zK9Go8K8+eTSnFFtTt9U%gT1xIj#ypo2SMaV3hd zGcR(nMiDRaTOqhTceK4fu?+*(9DDX^u^Meg4VIyOm(oXDb%SK+9|k;EX6@Bh9w#oD z%{0%HJ&Q0KF0f}y-@@&uz`X}@A{j>sNb)B5+|(5Ct9~R}ix5V!es=RhmrQq%az2O+ z+wB(T{;uwxlEWbvltVyPzzzAS4rLm&ENaoDK#((HQ}nn&Y^Em`Qr*HQUIMy4+8-Wk zkN|f21u{=M?=~Ckr02?^+}&Gor3fuakVTLVzt&yfhu|3dh{P4-8ME?MVNbmHb~M$5 zw8+MIN`Yy)!EM3>L2|f12ld(Ve0FRC&)F-P)#nFm47~S4Dz41y?|~lCmm62g!AS4> z7OVY&M(^jA?QdZo%D-I1n$^qeJ=AzB%Oujhw)U{POl4r~h%#`uW2tM<40)g0tbn!y zJ`5*g)vB#jCHA5yHN&pJqPqEUtq@8u5}~y$@Cyxg2DMqX{9++P`GKirC$+XdD~0@Z`%jm?8x}$g9s)=SK+WYBAED%Oth2Q7(_e^;>}dl;+!~!AQ>l0 zHu%{fujtcMG$2OYaKFdC_mrWVzLy?rSu^sK_X%_#9hC34Gv9lVegT4g%HM;PA4}uu zb9;xfKe~}grx(ZTSllwi8yp#TVjD@sLpBt#ylolTN7vuF65GED1%B(|05RL997)VS(tylexZmO@N$Dua z94>+j4ArZM)Q96sWaOOk6Y4@PjA;Ae&+J^Fr3dbpUi`}VhR*W&Nqn4NmMTp z0U;9vUKXWRw#+6&OFCVM6sW>!V0U9+9RR#-j)1pKfgBIe5_hcV0N%C}ghs`7sXDxr zUwPiuQ0V7=M4E{H)_uv@4GKHXVEemtNQetzsyIT0RU6RvwrYx;99>E*2w;%Hs|Jui zH(I75V;aIZ2vc7qZknfED2v73KTN!cP9&cs*LV125o#@bai*+mnAgn?d*q#<(x`3| znL%XHX||hs{`Q{uDCnnPi%K3RK7?P_IxE@ zL)(PfuBiJO-ZNy#LagqvV>lF_uwYwAjn`tC?}E}D6!}8Tj|=V8DT8ceOK|-ma{^zi zm_;@_uHL@G71mhWZnrwD_4T#HJjlCKjx+X+e#d{O-}T{1!9%ue6YV4ohoIte13W@xeGtDZnkg)tH|)OKs2EYlk;;7 zQ0SPL>oRNHUy+sLa;y|gY{l|5d_jz{E)T&o)nGUO8Gv-I{ySyJ` zTqtzZ3#;|0SHINShfU~nIZ`;L$>0sphC?_gxNm z<(X<6-pi%O!nnTk^CHxMIr?3r!Hw^iCLQ~;%$LdJ&u$N;8Ts(KY^3d>Z0sR_&=23+ zv=$9S?ju}dW$^;NOcAcUSjn#qff-IKGnQ_2P?T)mZ1DTP(XaRq`c*Z2H+q=2uAB^H z7oGbP{pOpJYg~bV#9yyD`v?90X{`NM@!|hJ2DfB0^0%S(3Yne@p=P*GxBj@$miR}> zLJ6qc&d5(BEo3#BLt~CREgLHdg z|BpU~!r1XRtM@m3)v`gC{)GsIMJ0kE(jm%t0;3P0W}ZfJMbg*?uKbj7Q}+#br(UPP zH=T^WVx27t5F!o`DPmk8&{85yK)?Jut4VL(*hoV|c7Jm^Poi?vgsoQAfa5dQC#iI{ zDFgecS?w9>6KPsiO3$tBBNXMn;FJ(B^HtV#e9U|aF_hykeuZ$XHAwE<>eRRpyY`BP3YZCte(nR#%QLVt+a2&$k$jjFvRa`qKAKR zaL$OyIN&=G%I7$4hNp$H=p~L>F7Ky}MD^G1UXOaRv5RlnEuPb(&CCHq zmO=FbycLqYDesZv?M{@}<&xWLxY(k|1iXpDfIbM5u#A0K)OSS4!o8$hn-*ul=hC9k z7{Noef2eqmCY;UplVe7-!k_}~t{zo*FlkA%UyC=#PrZ=}#8~uEZcQ9@OT#z^DH0_oU zpscXRWQ^x?RMe`E?^V165h%Me(?0xu6qAd7MAF!a(vJK#U`x79F8u)bW;U?-^$Fwzwe+HM*F8O$t4R2v569@&UihK&} z_!-k7^I)@~MRmf{;K;hPbLKS*Fg5ogY zAzCC4SVaCdk2;O-WJyL)hV55WoU?(Xgu+})kv4#6G%MXIH` zy8qr)-#*=gb+F)U!r&gydgn9m%ZZw@Dn_KfKigcw1^3)ziWo79Fx#3&m=@%L^<4r< zW8B5U*d7+0(E?spwPeVw4uHRCwG{Wno`T3~fG+T&y{$ZJdl<}nFktzy2VW?+DhvDF zU2yp()%7+UALk4l@7eBtT_@xO|62K}eXGH~r0MIz3-Gl1(oxeu7{Vo&#`@H+FgxkNl73N%&BCs>GeBzICDFDF@syZz)uq0c`LRGBM z0lGXE-tRa*+ar^g@&a6Gjy-qQpXP?7*x(sVi~!`%!k0>g$WHr zTR-=Dt7*|{pJlHe*}8K{m`)3tGS#{Ie&l@B(lpyyU%YN5y~HfmXf1?F4zTx$GmIsz~q>s;-zV&ki3ullAZcPY~0(L4a0*{7S{~s$4W0|9_-n zGnYdi_j&(!u06`t@*$5!*Y_U=qOmY#!_OvJKg}jC#|ifibCJWY71iA^eh9MLu;0F{ z4$xf$7cet6c`i%#gp*Mavby76ja_yk9+gI))3RGGC&1Cav|8TyDz&vZ$m~7?1s%_` zUVJv7=fB^8?CFIMNo5BwSb|eM?3;7pZp$Hv}T?tE5ji-s$qY%WO+;)jN;?VRc9bps>%lY zJAAN>#*eS>_V2R~=<&5=v&1(e#yB_0u@&a0k2UM9%nDCGjE|u%bX(oXcd#m{I;X5> z#&xBe^L)`h@*q6E_#%H=GrYs0!n zQ=b3OrC^ieaD3|0)o{3` zw$0M}W`%23W4mzc?7Dfo^4xZgEvvb!pe>KSrc{YfN3L7JF8gA<>;)T9BA~nz1kFCa zARZlrKDM3U&_vG|iy&Z7Yc5C0t1KZNBbf!pcE^ZSU_8fwaowu9sMBrZ%mYprD`3u1mP4b+wid zT=!uX+<)%6*BRwGxG!|luewo1y}L&?6K0d`J;R%?Z~MH~wgukb?_Ka+^YM0G@M!R~ zdfoZS$#&M|%vfd(2sl?EY@Ob>1re~@z^n$(-^PGexnEZ{3B*FZP}&mgIpQkoi{)m_$UIOT^t-B;Mw>HU#4DJ>N3_ zu?q!%GJ^yx74VJ96*YDn;AM`TH^+XgMP6Z<+OpdN%$)+*{MC%z1Z@7wag*r3v7M6w znC1bkfbPr2eMFQF`ydlB3`zF@kve{czi<8umXs(cNFwPxJyxvrmMA6Cw}bwnv>qLJ)QR$#LPTs+GC@3{=O~xMOrJkkV4b%VpQ-G-lY8 zuD^GgQlJ$-3=z1PI&3#%E$8aQ+Kb25-D>*kJhUwTkqoS?r(?YzqmQSrItoa3(Sesu+rZXZuL0EzX-R8 z)&>KQ&i=6i0O3Y&qw3*Z(w44geK*)@{R+xL1N%PriyW5Zrz{{u;K@t{!Of=ubgs=+ zj}xCh#tePbjDvu2htURc#1eJam}Pu-h{>BX$e-cGI_q0PdR#6i6P~pKsB~17=!h71 zfglM=&m6jmNJHP{hR5v#Vr9Q*Q?RhT$t?D(gtf*$)qG!3_=Y1SBMbth#vZUXP`3A7;TjNxF{P8IThSF zdYz#2MAU0{qw7icOfjeH3Bm~6T5KLvY$G0dOOw>fIOHI|+$Unq!YExl=Fe!+W8R+J zPu@hm4pykVO1|nprhz*5Po(t9d$V?kYV*Em@6VXOX!^b zcr}2XTne7Kh5@g1g2rc$O#@l8mV#+o*-l7S4cUM@f$$pYHgaS)eU6)^)((5?xSSr= zW`M$oeo&7v`R|tTkt3VYTYuW0F9-fdDE{t5xc5I4N`(C{2siQCg-1=YcSQJ?mf?3m zp>+%0@T=GuS}C2GvkKHeEEbYJUzxav=ktDy*s`Ap&eLx!UA&t6I!$(;w%5A-fxgJw z`-vC&w=Lg4*ANG|!aqs4=>P~foL_|7#@gDNps#`9KW!&@? z9Y5%bJQzJ`_-;RT3s`J(K0B!5GV)@T1-cUkitKhH00Y|2frp9z@>v2IRzAPWLkJ~* zY-b?Yq360DNP)P1o!~?-U(hhR2>XJnc=+)0z0kqa5peOq4_aT-q-skt)^6I*2uRF@ zz>!(jj8G8RLfgTW;V)t3H8thBVBknBjNymCvP3!}-)L0Uc?D5oB?F@@{I`6lzB3?^ zc5jIGDMGnHqGQh@6DFmVy>q2ZYUJJ|S%ZxAQjkBP2@M1X?6r-+fZp+Xd)b0LsApP7 zdac`2#jm@Coq|B|LANn1lmxP?M)4YD@_jv{^TrDm@GvF^*RSjceWu{=-jmm?qz40M z-xuo)cG$Z*96OlJnJy&e(e^ar4LBIBE;OUM@MkgPyX zsWS4a#Yg=~FH-*nY+0IF;_~zG5%9#Y9$*=1wjNE+$+wY+jjzU7=ZJ>M&hY&Q3Mfro zI{@MqrXVsTN|@~4Zsl#`k!X$LOIQoOX)>Bc$Qj7RnNxQreT-74w4_GF@|5m0ng2*x z?%H_Y#glT%JC#XhIj!Y*#0rz_-?*Es-d=3h%=1WghMGAJ0sew<4&gyB&$4c?9oTn2 z2M{niz0v5Bia&9VDBkzPT4sBmLc3{HEZ9%AVA?5E+>r|5K?R4#kmbC%?S}}|FvThu zOJ&B!a^TX4s^PbUa0%3MBqgYXd6h^P$vh=7yFhjmJ$8Dh@nvm}D3 z)IwR|I6MzLYpSpaTdY3KD{Emrp;6=DyxAzGJW1oEgg^PV@UXTTNz|R6zUDZ!THY!g zkUF%zx;ZeO)Jhp{0Y`zaILbLP7)y!BSwm7K8Avmj=}7Zg&92phTyZw>@tfUAj}3VV zJnpW;5MvnrMPkXqb6F1~T5<5FVnAb1bT^IPSg5$RS|_CpPki4BrlH1eZaR6Xeo9Wu zBus%zYSt|VcT-#zyp8`As}MdXD#c404|<8`W3E8_nobrIh}E{PQ1C81sGHZjWut0$ z#0(~MLtwyt^?V`HYEhhg8!9vSjx2!%t~H?(pk8YT+)R3Tr`0x&ljp{K-_gM(o4vW( zZmc*}#2j#3R+pm;nWxznNo_Obay(WYuS{Of<(aF#2>jY_bK1`v<{De8%Vct!D9D4tTYW0U$K7~ZVPm}0K-iw4=DCice)R!Q#7%nkG#H2czh9kO;i(v@p}~E zS0Ts?M;pb)i=otZurQGwnZ31WtY{rM7Q7LT_Lo0YMzYy#Nksf@nfI?|-hZETEo1+l zdC&zm*4EZpon1@ip!HXJ@aUqob-&BJB{0Zj{!jNhF^f~x8k+d!(C~iXQ&3ov@p;pQ zVM&;!eu^N_AAIc@zy$dd2$% zrnt41A>>p!ao-R(=pmoJkFhX;*q8>G`-GYniei4bPW5ox1-YBSK`}1mvgcAofK^`j zTfkGvtsE#n+(Avk{k2oQ-_hFW0#a|74}aLIP1G5rX&uzvpfbakU3JiNgx?EjJq?5h z!}o4X`lesE0s27>uHT6-O1O`Hk44EbusG^)P;(}>#*If1vNdTNHvsLSJORXZXsx?TXW$4HJ#R;;f-#5&1(3)=RExE-v*G!@0XMiat=y7r03$a(SL z1PR3aJ@zPZX#~_V8YPxQev7@AU$M7S)QnR6ApN&Zuf_*6*|$xvX5tdf>D%k=&l$jQ zuC5s&)^S~g#OsGUZMdx!{#sCK*_7v%Zj)utv$RUG*-(N?>UF$NNfv~KuG^ddw-N&{ zp={JNo|R=DW6=$pgJS|1{BYw3!4d9&qw-D%odqC#L&INj#OotrL@G3}^gyh4ci zj4uk&Xr+C=nGhG)Z5a=YnoR7x|4r+NbV?l|4fn4u& zQ-j_0U_~Jo{VtBqAIpG0Zbl^jHN@@jqu%dk+5ZGx{I3wVZ>-|Y>;UWHtRcwOpxlt> zi94|WSOb#GTzd|v@Zz&P#2Da#HHpntTTa-Cdy#V5S9~WEWS-+2%h5ly|CkIP)Vy_I z{&~a=aCv`jYZrjHy|umbK5wG9x3%$?C0yUQRm|p*(I|gb5EXv_4#rkstxj2t(5nb@5UVl(C8REOTyZ;^DjBV2d%7^46;-u`MHXS?idCxA zhKxWJ+=icQE()jSl;gMQvH2a0?Tk`bb_LFry1gSOh@mQAgfiYeJau8-lDQu>SVtFp ztH;D~o!KP825*K08tiS2Ulp^PKR_WH(wtn$|)6O?x=J}R+olFoCIVRI{yFZ6+i zU;6cvIfiR)U5&;_8N#^es5ymu(^SB-jjn>Dp4L=nJV?K@S@F3{Yrj_1o|lhsM;1uG zuf@MHAN8t@ia;B5$GqSa;kApIM<48BcD3$F@&i_v9XJBN*gfEm%lRgqS2TDYmaUZ# z$>Ncrh2C&f*{H>aVfk?v8{%cEU#;xE!t^5RBU;GzC+z!)Y^US_LqOTP7%CHs?@d5x zsUE*5xm~mHsecKQ8>fEgVkqRTk6+r*A$iw>>)r#N)^Q{^vR9@UcB(Uj{bE^AWDTRe zN%AB+^fEkZJubX?i_2(Mr4s~3fCpjc7Mkob-bX<%XqZMr<4^=#_Xzxl=s4PdPFSDs ze#C|Hf|;QB7wI-ybP&&?`#E|QTv(D&cyM?hx?~jCw;{8-Zy*L$V?lU%nU zYXB31D;^g))I$rqkWsL4{4`BD>OQ`&hW2ooE8lcj#r~LzH#U0E%Y_Uc{wo*bqm#nwQku@;SQ)NWhNtnh zF{eZ3=1uUSiF@zJr^kCWH^+W#K3w;M{cjvU1Uc1n6-XQAba_&Z6M%t))JC)%7p~$& z$}tNg7yBNZC;KJOEmrj3zZYK5fH{{|4^q_Ie;Mi^P=1Dg7Cl3w{JlRVA*-|XbVc68_@TgL)zM|%2N)IMxcZ+(V_um%)!{f zWFiR*j3lC3@=!VW(|P#LEuyN=ZawuK|Z|oCHbaaM|4q4l5L12RP5tl*mEdOu%trO^DjRl z;p70zX3Al{W27dfj?%^P@GBpRWs2<&h!yP--~poQDOoI_m~_rah&#jHMSSWa7jab6 zV9wvZXC3+s6gSlVqQ&%K@fh z2h-n3H=pDdS#A2Sc+ddSt>_?ANPYo(%*16xdEX@1?35cGAX=7C5cIbhYzd2)reILJ zwi~J&Wl%7o0rMTcs+f#@sT)B2GLFbKf%%%1T|%WPW!#OwZ&Y@yAFVcUGOD_$0U(OJr|d(~$yYPg zJ*tG55svV-egB@GB5RaGXYJf5ru-Ec<9M6Iuqriy**C;&C)ckiEae}u1FB~z zzwbT^NOhl`Z2KD8v506F41il*JTN8!dc^wEZ1)R5n@Yb>EPqJIV`QGp`@q7{9`9^o zAb;t6K)&fji`HNsNWAMZCux(wCuxrLl1j`b%$PyWwmb+MGGt0LAI1JDBXYeQt3E|R z{xUK)+_1K4#NGhOjm~1*vMo|x8wXH%3TGN36`d~FEvWgLU zK&mLMsZGq@T{?hyHTA*dBNGS=@ml5&TWFK@x!$Y_)Q8on8qpwL_wVp-TZUx;8W4ZTn^|Ndi5DPDpeEJCh)wbGxY;`{9$@3>k#;Y0nuYs;`yrrH7=!GK5ed z>7Q*ogy6tQ?>SI63L3>5%*D`D&udmB@}_whd5_4;H;f!i2r5st$a$nq)8;t_8Fd;X ztoi1daF;?bDsbeB(V7acZq+boAUt?h(yvLB0?*>3G+~m!BeSx`%&mT6#;wBu2A+hc5NXAO?wohZzaAY(P~;15Qy2;Jl40hm8jCs7`PUo$ z-beQEe@%D$M;88W=>3l?y}$D>{;KXKzI$19eFEmoVhuox7ZXu@ z5WO9Z#amlo8t^C1#ZN8yigA;(BhsE#FG2tH(i%u~(y{?D|L1i#z@`1kgj@_4n4YHqypa|xpQ^rO ziG|*ve&TTai;Y@U=!ZTS-(HLw8V8seKLOu`;|SZmSc>kG-4#F?Fd*quZ`<~|4~Cws zvVkCmfCz|j08b@5WuXU@&~xU;jZ)>$xrqZxMB)%oMR)wi5T*&7wTaRg@|BGVuSWCg zu35xBkt$qorw|r*ZC7|t`_LcCdv_WV6&NZp5evx$<_En*lY5y?tMCM79JJL!{3 zi^EQ+C~>5WaMnaAQEprcd}zNOUU6=2Fz}^~j?B9(=Rhr|XV?ekiTAGiGF{qm`UcY1 zk=~sMRt2PPA0Tb1IUi#t_5uU|%WBYsRtpJ!&mb^F2GVua_6~-7CVB;m-rYIB$rr%C z$rp;hZ7{6hcMXl7*J^CVROWw21vI{s^Y|j&p%X1(f=$;~74FjJ@4cI#*A-aVIl?`u z-Xyc_xAr)op|cFQKknh^AfT?zpzJg^!O5bkrIi3h^W0K%(vB@9TWouFhXOu41h=KQAH;XNVCyBOIbn>ug@%whQT3+JPjjqRRWP0f zeSw5a)O%guYmHtAk)?m*-Gq;WLIgl=8UVJD){u#}5LS zsE`#TEcJ5J72`hGl6x>|f&3jb+X>v%f z*W8}{bBKYtT!bmtDn1Nmq>J<4dncvQjpr(gG>zox?3GUcOwxz{v3WXHF#{BKpHQ_F7)98gu9r>4AjJv zf347!z>sMxi(X@ze#>1n5p050hSMT46xY;GTMhM=Ch|6XC21>VZ3=KcPeIrsJ{PwO zxz8JA4?;3up0_6M$)zlzt5fM$ym8(P18C!%nKEbB_bE1tyP+d{VOgrNXXZy@K*@2Q;jd*07~ zeW-q?(eA92f7PJqi+;rI{>KyDa5U)JJU|xydFt)=S@_>)-hX7_SNq|%m9PM>IZn0wDG6*?L@jnnLr@VjcCW=(vS!6L%0V~@tSo7wE{=tH7MCg}v~JoOyof5N z0&WZ``Sjbi--j3g;VuOZ{j||x2;Mom?n`t5!+}M5H*=vXJBOE_;?N$)QrQ5o%ce@EdV(MC>kVE>0odi+ z7B9*zXw?Puv2#%yp!)Z%uVyp1Ko*3aFgs2EgC%x|S-QTPHjpO>T8~!y;2J6QDYDA( zgOZr7Bh$!U{}>3ETBj!rMdy(TMouyFiM-~u*-_{eN5e1)_?KFAULgZ%<%1}%A6e>c zEoUl@DY&qXi$4P&I9fIuP~6FHhoo9I(7F(~%-K?HvE##zC4+eia_pCgbqv>#0n{67 zXV&*|HxgT*Ea|Ic;nzeLA~G-t_8HRLnlRG>|KjhlbvlPh56RjaGZCEob=*l?Gq;!9 z0l8z&6S*iDzP`j08GiBMAH_>7kwgq>YqC};euA?tQ$Oy$zWZ)GBZKK?iL~E5njt*$ zs~x>IN=vHBSTMjbNpB2y7*gzoTUeXd@Hgv?9Acj>gq%COK<3Kv{1VZen;O2x-m3c@ zo2|F}EVU!c?(zoxu(9AnOZnbrksVDsl}_r^_}h0K5TDaV!1jNtjsC` zFrWw*H_IjzL_3_eIe`p^IH}!1>icSQ5Z5%y7NW>Bfl+ybK2vey(U_=1SAR!teW^f; zZ$XZ0_YYwo4O$MNM>knFL=n%}X=~Ju*k1-A=dEs?q0EV>hQ8Oon_;aYQ<<7m~JH!9mAvg%=Kc!{SoYmDR>* z@rZeHFYLv~g589$u}g{OuJmp`d`o0%IQ$;x1Z-2KO)g2(^}unIb}{5SpqY449@MfY zLxG|&bCmEaleAL`{FGowGJXLE0@R>+YT3zm{rQbXGYPZS_iOYl`QP)Bc~tlAFX8`n zG;C(`Qv7S|+dt#*cVq8=T;ToP*!x%6HzwL^LJ>eiL*(`si3P|$_1$jxHBJmq>@MBW zWh@|;_Cyp!%5(f_>oI-on4z#)Rgkqv?Re|MTpd&HoGgX4f=R z8gd;?Y9_{u;-roVfQ=lL|eu=fNU(@_vxh$-LzgS1fP?FG|P$|qt~%^ zTS&}ci^N_&HC%oOV=%QIRK>Th8lL*pQ$hWY?whpA4I45j|5qS>OcoGGAYE`b-Q3eq zV)|uzW2`dcZ|rp~KBcS!(zkv|%HJ+ar!bAN>d@pHzE@Y}ebLD?DNb?Yl2l50y8a+z z=GLdM_2d94?(@tE^zllW%zLDB0OfsOl$1kTtfSbcg~&q$+n&46t9|P7ddEDJCB?WQ z#HyhMA}8VD!t$6A&L8SI0p^jtTtG1?xmuUxY?Oj%fl+K?dxNBr!Zx}=nNbWdJ$P}S zub!SPiZ*Uwx0Ve%fyeQxQ3+j}2tMc`0{Al}yRP3tV$8a+E=A~B4iWB00gr?=`L)Pp7;a=kX(N$+P8D`BpVG?7C?` z@BuS$W1iW)=t1%a!#m63HH_wPu$M9Wz<*M)*sn-v&e?ani_W^s&Kh*j;*W%|38#>GV1q!{5v%!rNjKyD#Qtk2Er z!)5#P#Rowz;g3Zw>i)gc#rNXR7II#}SqbiO=mCKGKVA%ojz~x=GmJnTs*)w%EG_>vSFLnR{b)7Rj0C6~g9Ltxi#l-uFNtk~#YABTI8K{`)3`ezI)zQMMYYvB=&0>aC!LC(-%?8gImM`M$mK!@A5 z)=FH?-U+72SVc@s@)hne5|U&tOqm1^@OeS={R-##-7$U2%w$;UcWVhLj4DOS0OHu~ z`430EH+Oq`f6aaSXA1sLQ}4gIZ)(5Xw}QB+kZ(Y5{ z&pgxJGu%(YXRN`XfbfC85*302@Jq}${4$l6m`ihHCS@F1&&&%^ttck#Cx4n zXJn>CDtFgL+*9Es3u#i8>9IVcnAyc#FF?^zs*n7>i97mzAj|LJH-qts>rX?N0|r9H z0zC}RH_g|xxti;qqRQGlh@zE9Z}40FFZhii9&3XBH~6hUtqTCZ)%=3rR&|Kq;I~PO z-{7}u0Q?qI$$;nP3HaCV$kN+TX!x0}<+g*{3{N4JYC`}A4uIc!H^E_W&bL}*asz+C zZ@O>r+xy?(x0|C42mt(6(Y3U;Sl3pg;htB2<#NN}YHodu27uqf{uO@9Fv$1~e#3o( z-+26yT!0ZzP<%~WRAuear!Il^cd7{R?4;`9vM0#L24;tEx=!;GE5b8?VXB|NF=YL2 z<($2X73;pq-ItWvGxmEV$$@wjq9d7%bq=jWN31B87_YYt(Z#g2v*JFfa#>G5C+nVV zYo}KoSP{ZhVy2wdN+hsU+Cw@i3hm8^eV6hia1mku?C0y1W*Z{NCm8mF0jeEZ&{!CQ za6=ay0Kbvp8Wo@FFF94YKXADzRd_5&SL~s3v|VUxS5Z=3p41W@Zh$sGjGkm=D<7di ziKj4mdr};Nqc00-KE4*FgkC@jRmcEKB^-oA9*7NkO{KF`nnT_=@ZSbajJ5#aw|)FT zl&yl$i9NJd>8uz(-k6C4w3RlW244+`U+`O+^TBD$fPHMMbbb-*D%=+ZPV|X2$I~G4 zPgO424yNiYk<;OfSLzM=fZqWeu1|NjO%FuiX5@4SFyNNg8JIhDJkpW{KbMRwZPOH* z$^l^JU7B(7ZSJiFjxAAhBNfR=T`G!Fz>8r|sW(ylAr!6+u+;>mWhxq`$Y8qSglVmp=c)ePivv zDg3AV2HX7tjb{e?PxnpI+?sR&??1V3d~g1xQ_Z0T$K8R1Sttet8%|S_rHi=ZcA0tp zxYqcWwI}xglV-Zt?Zt2XojbS5Sm}U5hwlC9xt*Qc27rI*??Cl)k+cT4!|m=VbQVZf z0mmt!!EUQn5?4g8)8&1X?TMmOJ) zd)%n>9+TNvxp>v{Wu5G{(ot{w!^&Er)8g1)gWqia0{rGBiLHd=^(>&HHh#o_5Met* z{Xt=C0Iu(6^V9;qLFIeZg4YjWSt0?`etEPSrg9DO)Y^l^Yw<4vE7i4}aeScy2}v&u zHG)x!B*-}oiII7uV9O&bSbYO86C<~u7(YMQ-8P-MpIzR!o;})*8_8%*BLk(z0%u|x zdE)?8qPBfdv|mb=J5`Z`?PIF`P}TNPD@!5$5K^AjZW%L-R+1(5+|2DYKA^46QiH^E z^lDfjTkx#RAJb8M+{I&sF-9z2mk*#ud$P!7*2)j*WA;so6>_K81zfPpP6V+Jl}9Yg zmeCoxi^b;6qIW@*2O`Ta&H;>1WVi-}QI-z4DKl(zy|{Nn?C6G+0;`*{lNsq{z=Dov zNf*Kk5uvh_xbW|L4WbvA;lNvdWa@bIw^4pMEb;x!HvwlmfgSjcrl+&@kQFr0=k6fk zqZiI*!Nh)uPz3TX`7M%tql*1X?FRzXuF`Oddji{Sxn;e&f$f>W#gfrUGAMavmS@)| zD%Gk)-zwcxSpB{Jg|itqlH*@>yj_`p8+WAvTMlR|zxkfD3kWJrZF6*L8mH`m z7M8&e#}g2lvM4J8s2e;pVTh=tC-Sv-O>>xeo=znKa3K3Q9^Mbfp;NS8(^9o=^{b`( z8ffIFD2d*Rmhi6pMI3q`jM_`sRiyrT06#|j_op8Nj$|l z5^LxP{TvQZ&_jq)mrNc>WjW$kPq=YQmoMXV@anHZaq=#>l?iws??uS_Rp2FKq~LnQ z&W8hWs%*faru^gBlxvQZ{YxV-*h=<1rBjLCSM-+E?8l(}lg(YfT@!WQk&$MH2F=51 zVcWLo@?EbO{JwxB%~^b9Bf?Ia79zER-Agj8hj569vScV_DNCD3WN=gL*YjS^*E-?Z z>~^Y@lIA#FG@<6$n520ow#b#T`)%2jedx_M_$}mW;FJy&ou0E0&vv3|ICwWvH<(It zaFB-~3jiAlH#fDht6sEF8nTg1Kl#aigV6KN;GdniEGkNyEJBaIXbv4kh?}n)zNuS( zx0FZY$|HieQ|tOobFg?0XB(=ZEsgxlZn^)a&Jy7Q)WK{LYCU1VUF{-nqoE5P0KYkN zTu3Wlf1RdN8_0pX$O4s^XV10KAOyN7Y&MLeoRzz$t+T1rY;OX`ECrkppK;uz&bM)rEhgOGguN~L>d$Yg6Myz!=)2C@3V#8}Xa5IkWRW{X= zPY)YnP#y_Qkt!VR)3I~7cWm9aW~E?Xv6L3HmWI+AD2DY(p)~Aj<9Rzo$cWM25fD6x zRW*(a`eDOMRnr#ImFQTzOXZDwNYs90td#rX@vj^%X60Xl-+rHt|I;A+ukhPg%Srj# zY4^-Pmtm-@#QZ`;n58(l$SX{k+Hdk(=A&%YFBj8|@VN?tuq^w+H<7aQsvl;RGl3Iw z%mjwauND|Akpl|@mXFy*I-yjO2k_@Tb053p-Q&q%b-!p%2O=PN$IsLU!U3eq^q^b$ z;>S{UtSmR$7gLQeshV9rMHz7mUI^E8lG}%tolNb*vf5VE)Rtu)lUtGD&cUyE;0gPo zjP8gJoy$0BoKSp1>RqO&m(+WTve;_H0NYIls&O){P8?PgW+LfI^DWl-B8kQ4t)YwN z8p8K%g0@BaHN-fReu8ktWq1n$pDee!O6_DZw}@y+3%OFM9%>Y>`3vpSOG5(#0FKYj zo*2j`B4o0@;1LJ=40K>XuQT^%%#DK12`N1ANg*`eH-Yb<`UY~22|hW%n(*S=HZYs& zCRhEL^Ppl;-kNX^`ZkgNIRpHsqW*bdZ4%h-m)Ln1G^bkRdu)BXwCvvc$KP{veNaL; zFrYWvft0oTh3Lvux{`Ux0VNJFZYZQb-xDp#K}`p%%3h*OU4rb_=n5R$oy=*gZKO7K zt*17iIq;mbAEV&8VB--k zXn1f^;31i)ZBGKBwY(L8%Lx<#;?Vr_=$mjd5ezf39t4?3zv-fW8HB(95wv&!AtZT4; z%SZcYtRXg~l~&xB+BL4S8&Zk?i!QZ(TgeGPjQ3UVzdW#Uj3cj5ym@vZ;!0JG3QFOH-~D z0aXyz`!sSK3T0^mTp({5KE=OymY=(t`0-pp5SGaA{THaF&b^o#4dNPll5Hu|6hb0v zy8$PTQ{a;_7*}F(yxm%kZ>!{=dGRsi|(#%n{vc6>PChHuuZ}OXy=rBNjD~J1FuV$1fXau)> zFH5Bl-4Uh7&VE4poBReFxeSosobqozrDFd01jU@STMYth8cs3tv3t1ORH@nvzFmc> zLEXL;=jo1tfzZ7{bKRbD`ockNTmt7XFmQ<1F`_L4?oKL zA1#%ydYK`g0wecj9iZR^Ok@KIHnUFaX|2jjO9HcB)8i+yjz(_RB+XI=-2)u($y0DQ zrx~Q-mYD^zidxm0=R!E*5tQQ1JGryv7e1Ldh}yDGvQtUULLL>)=0_u{sUWjiRsi5P z`4sMH3}nAB+WhZ#?!J+?5eOg72DyR4+#u{^RfV9~)a6$)Kuh2;?$op%Uc6Ss_!we+ zJsHmaQ2&6q4Se?3;5VB;55N7kDx8PkFyVG8!b#y)bgQm;=RF9zC~xuY`D+$rv(+iM zg~S|V7ZS3RMq~sXA-Z}ai_>tL0pwt)X#vxd>dk?qSEI`jOD=Iw<3|j=zSW^XCWQl_ z!5iO3doz$tfD`IE?wWC#dYgK=27upg0r1;10Dcqt1-}X7GnhP*K%%GF)(Davi} zmbI^Bb1aW3NP(W(gE_|*vn*ci5{uM@#RY~4&$(S%uBna%P<;z+Z}jA5I87ZO6u0St z`HEK;z&_DPA(aKSm1JCa9OdE5VNp05He1 zyd=m``U5EP+KR5vq?s9#ZcG-@Ge*U@{Voqx_{J%fT1xaW5`l_z>$!D;7OElwxvfmt zI^(CUZc5wMa>Ebt-{iMu3=r%FNBCdzo4lXrFW5-t@A6w7Kz`#AxMF{k-;Uzz-4p8F z=Nlx-m=;>Zwbyx_R{`={@?-Sxt-z0JJug;PpP zy*wVL9K%8NiquriVl_71Fs+|2Kz_sgseuxo{&9-fD3JyCQNT?F;+wEF>g45_4L?dV zLbAVZ+yoz)2Lf`JTXw;0QuGO>Ok34%>oMng)C(jX<2EwAN9>#YCNNe>7R^D=+(DNy zQ9|C8{ZKd8QM>eoR-X?)s~;f0iOT#YzXgM!le(n&Py@THiobvl^rmj$(Jc*2LF48N}HG8i=1GDEo_;&Q=LR| zgEK{~)}%j#9yj_)YvWy?=<5({+g9o^Zzf*g2nVjnyEM7<(YYQfRG&N!oSH5&6qn01 z9ip;qE@ar}Z_9l_FL5WtvzvuRN8zp}>oNq*re^Q$Gz3F*kkC$ajFyQSjp~P%Uh!zI z>%7PDfEfrx8uM1*NVJcJw;vF}!>1B-4Z5ttr~|*^_GFT9P6pf_kD#UMU*(=$7jp;$ z4U_olA=$}-hxehGmTd~PA=-hwV04$GYE zgXedv&pG#FZ}8i&(#eML*=teBVq#-OlyYhM%`f;(s>nU>Za*u-GUG1exqj}sR}}Ln zahm*-ld0zHTPIqMGEix=NoH2L5`8UTJPryXU^YA@cs zUvTGSb(~#5k@YUS_(KWi>%7HAvRTe3UEA5$Wg;hg;N#f5VDSEnL!%M`gpiu~Tc zb)r#=q%3?6vnipK%KIoXK!>vP?pi#GuTZsy!Y&7*jwo9$ct4q&f(kytukbl&Ka_Z< z)8u9(t;u+7C8>!EufidM1q4A3SQo>H9}!5G>mi76+4!_HUrB71B~__6)V=n>u4Gq| zT!sbRbqtG}p?J(YuouQ#V9ax59`WpX5#247RiWUZpN)9vdS1~TbsrW|NB~`tJ}@&oK{nC*MnMpa zvd$%4o62W^*N}1%DwzBHAhpI`d7}*ww!Ka?60|%F;PzTjplfMsc>nX~k3GMYqS3e^ zfmT8yo{;#PVyntRqjf<86CHQ?G!C;gEi3s0O3}O;k11Emg*{hop=1X(%_%Z_Z%uHS z;!~D-gwIQ8k+IIUZw`q*e6`yEMaGS( z$O5Ur)ZBQ*;F}Myfsa0y17yqwc?kFRgK6qd{StcSk5_`$b(wK#YKz+4pB1h)BOUz! zGG;3`*VD#Yl^P#U%u+oa@38K$e16H zzXc>kv&36K-YZi!bz#VB4gvzQ=vnOqCyW!xOpJ3Yw)L@QQj2LVp!B#k=q(`6KC>Z0 zvCpt$IZC_U<_K9)w|{Qlifn~7U3}4Un6Ev?QDVzog$>5C#W7E%bd6mfJY?+^qPzdm z>LV5}a;NCM4<&8$lM*1miQtbk4eSBrH)4@~E8g{mADVc)VB12FdmZ1nM_L8~UAKuM zU=lL9d+tpHPk4D`)<-6_jFb#k%p(RN;bma1kXH=|w}=Sv6>O3MA4Bnu!X$gkP*!_Q zp=wmJ?;!h{6!uoNQi>Vuh+6W;d44m}e`b*DLVVESuUCokUlil-z&zK6)LR zsgR$V=NhwG8&BecfBBw2^If0Q;RpF6xi|WE+FOq*_5Y8(y9&xX-PT1l81b2501b25raCg_>?(S~E-NX5l*>kR*z2{l0d)KMGt4?(l7vwTG591r(c%L66 zs6-xmn+}c>!c3>tUOoay3O(l1ct@I($xx=`k>uCX%I5xV78_MIM$|ncB@*p~!PiA6 zeT>8TWrbR}ZgRc3WjHCm)WEjk4-d_v{3wI}S}DZ80`hmm^nX0A__tCBg+>fH;`4%G z4sc=O{<@HNCzhWeuq;=blZYDa!tu&Ut%x+g?4Voa(m20!eP zxJ7a%>wDrw2u`M}+wn7hszFnB4a6R`aM;3Jet{_^Pi|EGgoYJtqtJ+k82Qxw_1S5?0e2Xw zU=|7po2!|yclm@!IOyh`m%<_m57fk*JPyhk?~DCb_-=~pFo=k_ZR-O_`=>X=*yqVU zL>6zxL}p`sWIOr;)H=#)&%{5!*l+OMfj52wR_}1|AfmjH`n?~|v;_~NyHtDok5ww0 z#2?36I!B&15S(%3J$UyKV$x`X!gvamlMm6X1?bw-8H3ymC$Px*WGj)djc+GVDdsWA zJurcPI4RNav;aT2JUQ%Y0Q+fmsM)03{>r?>L-O5#1h8yoB00t=KPOLjd`|#l=8B&f z%5*VaMd@t;ydp7?UhD`>=0Qsbup{6ViEwNCLSY|zAj|FiZtYOTz@_{maz+%H(%Ag% zqclmQkVg#qz`T=va=A_)%_wL~J|uCUkx^ibFFu8^IDdWR`#Eik&7j-0f(`7VeZenD zaz~9OY|CPt-${#eJrk(aVswR z!&G+JG-_B%*7XOi?Kp*lIJAngHD)P3oA2VkVMnuM)JNV6a9Wm?asYPpqqU6H>wrV& zie;0@wYtQ3NO|pc`PEnQ^-B0WzO&(`u(*rpK2eV?u>1~JwfpsUbn z(y=LzcN25aC#?)D8>LwawAyUkqLUI&INVv2%-yJV4lQf;Xt1hYtRoo+z&fG<%e4cn zqa#owH>>A9pO~bGEz4kra-bWH&J$UWpmEA6ZI~mvC3BR{5$2PV+GVDQ_o^OB6sHmH zGU4G`Fcy059W)6K0#cekmr*G#I;%Bg3e73}Kkc`qO%_iEPTNliWQkuwn0bAnU#z1+ z$?4Z)vS-N*G0BoDxa({&?zI)?JO<0lqH>>v=Wx#s?3O$)JT$TB}0Q-;!1wqG9;>lD1Rs|_WH{kna9bymg_6br{$~o5CI&HYgR(9gI(dHV7CCz`-KHo zhZZrWGbbTtpV`Zs8K*JN+xmN3dJy_-Meh^3jt`%&PFqYUAu^OOtak~w1#13bzl|nf zM_d5b(R)O|IzoyIoYftNC|vw>s0-L{t%+{p-J(`|h`^VN&qse4h$~?qk6((@|GfS7 zuQdE0#^KmsyMkW1{hYe$?IjJ1^6xoIaHhB3z_LJvwyX7&7-q!M{k1uvN+QV!_#`GR zgH)d%rqwuolOjLzr+CNLolsS}hMHC8>oYi$$UFWd;V60wXO&5J|DZ6_6j{KnET26_ zTz=ln?k-(i&f%YX$U?pS3JP+>2v-RL(li!;NBz_l|0Y?<-r&kb^lcr3Mw%7zhy%2} zNBmRs3_%7Bf?-XCq@sG=P2evHlWOmr>qPrS!j$&QE3TV>hDitf=ZV13ELsrPts+{5-SS@Xz-6)oP>Fajl>YJ}uGbTgpu^P-==Nyz{9UM? zHECAh$@Sbt#CxPGSk$fbHryA0gxTS}ta=YoAx=!E`&^``Z$&e|Na4AMS=Za}we3|C z2-_O5TSxZjyNxxdX|QBGCg^UNB6QI#NdxHUPt{@X~bWphV1<)G1=asT0AUZVV2R zTdi>{0+mz1u#sZqj>@jt~UUN>A*lqw|Yy5^)#dunr=>0zm&fFxC{dX zVj;ZIOCTB*zXYNT5Qy(z0I1_BYSYLhLfz9CgcB(a8Q5}R9W67h3Yo6|@4{%%?^+qyL=T7QNL z(VI_0PmWj32YXlgZ2xHPTGGog2ML^)(Q zMN#+xs6RVI#T|&X?O>CZ(v*lJwi}G-`N`3(3oWkX4`l13yI62h-J`!4!^xhV!i2yVvQbE@7Z_3Q6vP+D zaC~i1TeHRC2b}`L=J;L!Bw_)SNo?i^f3`Q1A-Ba``Iw0*RJoHG`3T%YKqAsdK6&Wh z)Qi_a=8Ll~A+HIhE!&f**aL}pK98N!W-Y6pVm;*_Tk~J|o4r?_M~kRH+qmtq_@?36 zxSrLMd%dvD?x~#4e6mq#GRCAA1u2QMjF*vKz|liQ5&ahESU4xZz7d;mCkBkl3R8jP z6neWkkvtc~F-o}R@NqZJI)@_l_{=b8kN`~*LGEcPS{a3OJu_JqnHzUYJk<2ATB;{K zsn2D9Y?63g0=fFv^tay<@ptp@pSZTbn+?_>uG}+#2_cHoZxK3MWl;F-+Cmk$wwR$M z7*ICpH`&g#kKpo43SNs%PAz@dP4V6rny zoNKGGI|W&~=dTXGiX;q%|1kZgeYJ7=Yxp_cbY%p@ocI$ zZN90Zu<{0(DChxN^Opm!PJcr$;8c##WkVpPI*M=f#c+zPV9(4otHFZb3S<$SHHuKz zmaq)gd~3BFtg3JdbKe1-#_ZyLPWa+S}Z|mKlf3A0Bc-uR!hf}aKX%f0nq%e`T3t4xotrZ%3Q#(XNt&|uV_O{-lf8zg2 ztm0h}?{bl429{;T^19gN127BwN)pYHlzVESp44_8lh{AK>5YHZ;i(QGaJ(@X#{Kv6 zhR?BdQh#+8{?q!KhB+E=;LscXi#jU*{yA)32J~D!GJY(;7k@e;o9caX{jhkZh{DtP2I z8}jeiPaC(XMNovdYGB^FflvVZd3EdSTSM4n+sNly`|T{2T+E6luaLG8&5f)!XUJn< zExZDO9M@n)aehqmMl6STO17D9Tv;d|affnqWqd2&t}>9Uoqz=d-4dY_;NKiDaC~~d zu2m{uAz%i5W7FHP`MKYSz@`Mzc9L%?JUsu}e_rh!Q;Agw67Hu8_8A2@R|hVez#OxD z_`HgVnkn!Tc5>DjCoD=fNe|cBZfdnY+mD^bYS9nqcX0}wV-Qe?gM<(>a|f-iaQGn7 zB456d9&QscmHs%XU?h%meJdCc6FD{U(F+yQgV6_J$wN07>6%Qp4Na`vM!BtgrV03| zR5A6VSW!M7SZJV;Mg3mYz#u_IMwM<29p5F4s-WEs#!sG)JRF%22@{XW_XW%uk?9Co z%6POq85{tm&x|9!EOWc-_Ma<}!0gSeFVYHI*qwy69F4uMVh3$$x@EA~wQSW(KjLlK z(hs7vkug}uP#q^?V@MzEPCIQ!fau8ifKk|!SRqZXsRX;A3CA}gao0^Bn z+79dz3YJs9RT8y%BaQiR0ziK9yAZ8D3C(ST#V%RJ4OWF~&Zvy;zF+Fd*na(x)!|C2 zyXT8f!oqLKU1O>2?oYA7;(k>E@3bg~;eLd5q1zzv=0@`T?R!LskKiJ{ve+ST!e37U zZ=k1Ha0cyz6+Lnn`6m%pxs?~@XcL!y0!>+qUX+;+E>AxQ61ptbt~^4VeO*|KGJO-j zXRa!PI4iXG^Y+yC*~cG!b$&GWtrEQiVZ2d_27?O8-_t+F zs0i7|E9`QSI3EvO)QatrL9Zu>$)!53=&tOvgz-n}T#0(q0+I+t`yqaee!-$4wxBh7 z!?o)im9BBSvX*Ms1ZRd_H|&jPlf=Ch;X~aGg|J)RS;F=RT3fPeZR`Bm$S{THaLuge z!^kwd=SnX214Uk9j%wI!{Op+LalZGV%vvuuZvSGA-835CxhJ{ltNiI+P}~pQqp94A zOZg6Y5wl4=UC!jk)u1>VUJ4;De6rlv@16Xu+C7Fx^7Kyj{eX^DvbXj>8J_>}z&IBZ zO0ncGUj6i){hcuy?o1%GMS;LM zin61W0>3;QUFJ{YIJR(Nj?C(uK!0eWCKnKDWZ>#I?!!2?I08)8Jd4v#I+vZ%&ardz z53SFTZ!%wf=j`)k2Kg@b*#0>=Vwr21pHE}eS_Li3DONE~WqIEhby0JN%j~ji&b2D7 z@{nbUW4cvW{!8*%9a-ah=-CcD18&Y_JO>%{3eq{FSKb{ZHqd)Z#ic^Rr&BDNh04!w zqh5c2BTwH@ohezBRXz=n-D9^9!0Kc~lcL%QD>)<5qn#PxHhY^uPk~r@=}6saVs4MX zHsU4?Gu-v$@=oS`kliqQ`@49s6#7dk+d5GE{ymzk@;dzM>wZFr?V4+UhE*YP5VW(- zW70z#!B3CHUf(+cMSh?_T#*qKm?%_@Pv+|;~+5C!(Sx@kgPd|~nJ2|<6OIHEzTpdIhUTmS)P z7({x5Dl0ve^mst15i#bROuMJ(gRR?X?#!9i6cg&U7>jwWZwj>e_0zhr+_|x=s2*_K zETTuhWA%LqBh2eQ(I+@G+S;~<;5nP#g{FJhu#g<8FdS~l{4>w-PAOz@j33>N-w$`H z!}(m6gbRFzFIp>7{e0{Vyaz)DM-J}v-NQ&~a+Ly<#j2=~0&{GKwxiEJrV;#C8h4el;E`)w9vDw%fFkCNy2$!yUJw)OJ_8>OR;e z7{|^5V<`8gHt_VCFl0|xyRETT)CS7=X$*AbBf)U~9wmACo)gCK_SNoZ8);VeI1bI7 zFsgBDb=tbapV|k~BKX1|fU94n7B{nGY#Zoc2TX7{P*GOL9SD`UZFRODY~E*D~!|;7zc9 z3Pbj6llXbkd}}ou(eq@Hs}sK<`)sOS>Ur^~$Eh5aUYQSa_ev$(-mgcywAkMY zKeCuIl}(EFYX9gv9j-5%Z(+Vp*Ot)vmf|b&zxwdd)|ae*_0;#bRQ#VtVJ2V{Mh8aW zV@3nVib#v@m_YZLEi_-EsI3#sU?&cBI`BmfE5krbO;qt>E>37wqLj%2QRARry%HuB zvklUaBK$jpcxSI(n^iOsHnK4`vik}a<*9&}Iy1t6hMxkbzCJ8Ku>_2kfZvORjPOfB zp7`;Hr*N{1T-u4ho%;Sc3(5LV`)|Lx;(zDAK>!w#;cYn*)(qgkHCVU+{#z!@Bv~~$ z3=UBaBP<)ehp$F<(5xTQ7o;i-*2F{zw&b26H5DOboAb&@113n)3@K|f_L*CQm#+91 z|E+D5Yxnu_p7$o5po!!vseB_d)DgVlJz|*N z&b=nq`Qq@1(kPp)*$$6LYO0Sn3zi|$nry4y+G-X{N&PkK&3qUsxU#MktC$!uU1$L) zJTg6dE=313&muJJ1hb99lw>nT{?F3p5%ttScp`YpWL%h2U(n|cyvrKlRmSJ^T{YUa zbJ%4#bWcpzP3yNvHs$0k!!Hg}3n(96!0m_(Vz+MFF9&Hf8|c);1F9z?eAxDXo=rb( z7R_(w7Za56vl&I~8gglVS2$*&Bnp_&Lz=-`!u`ILw{Ymb6l>qd{^5n7@Lm+_BA?$ER)Oa(|&F~szC_y zpjWF+khQzK8W|*sF%s!mvas;wmqxcw2v%|@3HCTgv{8sHSy~nQo-)Rk$GlF%xlQ4$ z`RcX%^o=pS4dquc{dx8`spOkHg=iY`>0v}|*InpPU z$^iV^)n%wfquIKdt6W+AW;PP@R=D<=xIZsCIyQw&&!fy3R)C=qXW2M+#QTYz?T=Ig z_fuL6boV>YRh}QwkzU^e$;1<8)X_uO{Y>RHo-r?HOb_XBBhrZBWS?f%GA^RsDi0yf z+dSLt)VCHGbaHx{PO!2#QtD4vQO%jHZgcR{elRvRKUqEjw@&EmV1mzrMk&SV7raii z^Du~`AK{LnQC1F72_Af7v)};%-`Zd~Ittg{_+(vbd`sU5`{KxxuZ5z3z;g~+=ME>& z#~!zwVam7+5!_=2X};!t#86X|IHwPjl6f!vFNM0(;QgMn0zLEXa&RM4W<>`ND% zHBw5X$;IrL21OY%C{opGQfn9^*V;A2Zv{srrPc?uxs1216QCykr3R6G^og*<^N3;)1}a*V z(vZFm(&|Ke#CYav;^5gTwK)1cIUCWDY0kYG=USha)6o#FiQ)TNxz@IuAk+w8npqJZ zaCCJ9oDopuwuS1ZW;WP}7z|6dWPUA7WdSaw$(KztO2@HPK8IgnWEWT6z0THIrvJElm5CWA$36@?L7n;HIWj8Kf*IsCB)aA z&zs-`ak|b*wd{H7D--Zcm0_5+nPmvq)8Bu3?osuGl~d1!tx-OGZlg1zE1bVHi5F3t zjxQddS_Dx_5jB~nDH=fZb~lPyNzdUily%kLM))Ky8ZCx!Ty?o($jxlNzsJY3yxx~8 z85t8aq=9#b5yRCVg`nN-dRILBIwWBj{5*jyx4@ffhb011dazd25^CUpnP0Uy4aYL? zvURxrHHXZ40Pl}JJ5L6tFvx+<=<~$xW^)$U&yNcIMKqk-1-(iMOeMy$sWTUeaVOUH zP=E!8gm%dfSa4{UM1TdSyGPQ5*Bvo;5mi`}hfsOh4x5H-O%jl@Z~Rjt1Bt!Dg1ZLm zOx;f5hw`XZfkqs$U7reOXh4ZJ=NM8`4|jpqn`gLhEtjGLg)J<34YAK*N1s+fOmS_1l#b|8JW=uC6#@IFyzK zgKJ36-}`>L%GcG`isMy%9yE9wr9)j4NyT$_M2Uxcx#l$>0`c1yRCQ$IX-9b{NL10| zAEJ~1Z1nK&gXNawHR&sHsbpxQT&c?|;z zUS?c%-q@mvRA9z63F7h#0`4B7vSYv$0`ELS_BdXuf=8>|LOmJUKMoJ#fGD$*`>ln3 zzpo)(!4FV`3e(wY+WY0g9iu^$k!-@6{CmXIPi`MRnG zhDo0Zu5tLZ7xkeXTDND76}unWERA^w?*)d_`_f{CKzw|@@>@w}`i)0APYPen_kve@ z2_PA;xGyqXu;puJPs22FM4J2s{|i*@7V*;Jk3m(-f`!VaJY|(6Oh=wg5Xyj?@$&=UkA*N*U)UkW0V6hoXs4F zH{_YA6HOhqtAAkSau%>CX>Ww8blEB08RjRsk z0(2er9VA$=%+nvQFS#>jDN=2%DxBP}FkL{6K@ImLzk7mp^%QS7!9w~try@)0fNm(* zBa(moiUzd6=Q4cZTz?CS_~9c6c2#h9Nl}P~s%qW45*&c}JpVB>rwk|ik>whKs)Ews zJ6@=$jT|zKKqs24%-29RzO=;9ira}8%Fnw%#l!o=+8|LjC#DvD5I#)Wz`ULK7DUMk zrquCMWsQnds=^vGXrK~EMbTE1gT1travxc5QQI)(`Ww((N;;;^;Z2@ew)!3to zd`V!k5JkZ~>l%8qH|QlHZ8HKUz^&fUtw zM3Tp7da537B__8ITk~6f#<#5Nm|TFVPfEmdAJ2Ml7MtB?#kfb45a#x!px<@LtPDln zsh_XcvmicIzoEbptCXoyrxq@1irc~LO*qerV^ZJb*hjE&Bg3py4Hv`NoEKwrI@_!+ z-7izORVRgmu+53ltTj$Gw1okx;SbJvrn9blVvB7=#CnkfEAZ-su_}TNNUdu~3LA)+=_Vwwd%c$i; z4rq1Ua~hOQdc%GFitw^WYB4M;1zZQES0M-7i-&)!>wh+V(A${2XUXkV$^o z{Js0*Vg%VvZ=O-}bR-Ubli{RZWVk-*oh0p&Y;5I-(H?Wby_@!*&R<6uX0`!NB?x@KahFJ&5Vs~&kdmPad3jVxvsPS50e2R2_)gvuOw^)lJL9&hNjEY zd(9s^XeT$^1fL=G6c%V2r2+kC1q zswFX^q%eq+Ae7_z!C)O?CQ6WW*CB<}FVLfE`F5vQbI}F_( z609OU-lEyJx0B*k3Yia4dS-oO{Bpt{bxA?gD%B2r59ZYV29V+WS4i;~zXQKDDeKxC z9B$0a*Oa_BgXDckZLVc=8V-h=>wA&mqM1J;_C(ine2D{Uf~6)IKFL^N0R?F-m!#Am z(TEo$VJF$kvv;WCW|1;xgCQ!+ESGmAsE?AS%IKHW`S5&z@8y)N*_AJ%V?dyy2oxz4DCh<)R@kxP+_<+it zC_D$=3^y;e*+)05hG+_`i7mQd&9lh5bA4TZ&DVBhAH6ZRL?$IlUC6}^OdKL6mVP`6 zc~*1NSGlLTkRRvwY=r+9&nJtj%5MlEG_)V~8i^bvR;P_F(%Pz2-eiuElEBMZja)6k zc2JvO9t;c(H!9kk$10WFO9~9COW8X8+uTl-PKdd02vmO~9GOQ&L zn&}xL<|uK%a3r8Uv>ya5NJ9pQa_^cnop>ASbM;{f=$5#gnFlfO(K?ICMhb+`H*AP;oV*iy2vEC{fkrrx-DHpo?r%>`@2wr z@#0(f4!3f=u&V)N7KM+p#$^@dNyh!ElG$6*i*x305uK{*Ep{jsh#Bv zn(kO=zTs0P%=ZS|jFqM6B_&RSPa!{fGk5XmDqkQhV+-S+lhw%Solw?Sr2JsVnsIS_ zg8TO?fKSKeT7Qj(`&SzNZt(q2&)C9#XJi00T+7QVHsh)<-H{TNFLSSqxm61SON5Jv z9B}Wu^XnDcfXPngWjL2#RB&tU9&qE}xkNGp8t@@^v-KAZM+m%NQwL}`IM9QhXlEy! z5wDC*)rK06GDqWJen$X+{X@_bQVG-iH5v~1ul)rY?u7uYqvOMJZD_$Crai2!{Vwe_ z2tN;tCIdhtR;H(9m{iHvcU;%V6W>pod3jBRY_d% zMHM`n;e#3R*HX5)TbwB*})fxqe{FlqOpdfPr z+OLZ_jRyO|2a-%LT!@A6Y2QdWR7NaEf=_^SIOm!iRbA&-ZQ z;%s+TpN~}0$kPwWnM|Uj6J2W5ZzIg(;h2=TxY|+03Vl+i7L_}@rdlwVF(?>9XK)d? z0U8eb0^*Cdg0l(ybzR5LSL?zz1WmUCX7*U}_gs5nodkTq?EAfj}(bV7v9*r3O;8~GRj782H?pgTaralGCZ_SeRTN@ky=(4CBke%9wV z`KXF|n3Q4ZJ0{bVss8hpP#ir$7WdmIopV|T73#fo2UXqLF?w^!lJp#^l$6k6wUpDS zXnGcGk$$r6HuXB0ZpG4}8ZBdn z!D<2~oG2Hu{?(-^%kmK|&L|cAZgA;ou$lC@f%Z76{P1ip-j4nPD*-`p&(!DK_G4Pj-!DibIbsW+#+?PT9~# zq(yj6fwlB>{NnH~QJ&_`zU9_>+>PBOj&GV2mn)c&1Ov;ZVHN5;QoZk)f1MND*4~vm zH^qh!JLYy@8`Z=?NFqDr`GbPr^`E0g)J94~UkIQ}$ro|`CH}&AF8uZyUgsVEt zi$w0(r}*5OuipCcZqS=-(VsCpNR!o2jH;N*T8{@&T7jdB>?#C1(>m?y`@0)6SS`SUc~@3Zi~pL+jE!~K?p0F&8r^Z}sZG#v$N ztAArM_4Nd-2`dajqsS6#-{i2_08D0;VMF83wE(6geK;wgJKf@G{ZmD#{TEKq5EeuA z1txhk|1jeD2y7?WAmT;K5szcHm5b(4msL0Z!|)*h$?(<#2MI1GkN^SU8G{q9$+O^6 zZ%Q>`{7RHLmCjuGf#M;Xqpw=x&1gTDy4NpZnBTaD1lvh$ z{!UCg$-9+c4;Lf6!O!SuAjE3S_bs+{$2uwAIuZNMw$qCZ$4)ts1=w)?T+v?$C|+zh zu05F!BEFa3>S&713AN_=8!NO-g(JkjMsw8mTAp%#E}8RsG2;1vHnSi%U$r|bMD92O z6f@T*Mr=Kki7d*`M#$sg%s|^C8JiOoACk8=0o(@ttoZ@ayN539Ciiyj56kcu-QUo> z1y!sWzy?mafAr*=DhIq~@cL#Uwv)K58w(<^0QWVE35v!}ir-$*B3-Ml$W7+jztQ}b z-0PTrL|<^) z_0S*nI@S}B->gd@eH~%X0g#NJ<};49RzJ*K)yp&wGF3x@eY9Pg^3|~7y6HaMZxZv7(r_lVCT?!@VZT^j`hepE-Af^N~@RPWJu-NDA{2*blWyix9>0VhKja5Aj? zpd9J5tM4Km<1;?M#g&u};Ckbf7aT!46zvnp)9>!*zEc!o@sJVYKA1Oeu@wD{X- zg)18>{778e%yNW+1llfj5@k$t4NBQ3n=e+T_Q`wVhgWqJ^Y_OppYc4b(&>ZiBOhG2 z&dWkBTX=J2yeB-BzCG1Pz*kN})auBn=^-kz;?_ZZ^Fl`qbIHfZctkUS+V_anaB~SJ11GZLG#DUbE#Y~y5SHgokREMo!+pS8-8a^zY}__iG`pO#v}^{e#Kh? znJG|tnux}tg?c-{%21U&+E;W)_SH0}?s>5?KF1Pk3&@EAW$F7G@?Y~;FIz}BvfFY# zEUE4G{}G2P^?>(&xoH3jU_k!#H(tLDhyT;y`ycwt#&>=lHT>!?d*6t>)at?_e7S+g z^-*#~s2*B|iaynE=U0DO%Fem8x)>NS*2E@(HS#5yTpnSw)7T>S7uli+6_8+^Bya*O z&iGC;tKqRUr*HeJUPX7$4T3Gkx^^5Tt^c0+2Q;N`(*DwydanOFI9#))=}xA0rN~iV zKu4*H7<0@~^lhHc(bCd)OF#1Wsi9Po)jx4*?(+V@B2~-36I!-r3_dXK4+!shVUg+` zW8e2k%p}#WnU=F3hS;B^OmH{hJGHs3>^||e-MAck96N9-w&7BN^gx5e3W7y~05UQZ zM z&^1d=B2z~PvCIMM`k0CtUm|sXIA$e$u2EF-!gNhW&MBr(XP)WO-Tf>qCFEHI3{ccY zy-ywGl+FBb;%;kuiKhid0a`Ze_^u%N&&=0mMDnOWZ#^s@-uR z)+=eFnB6zN#QnG)R;f&u65AQcEJ!bmo$>*r((kAg9>90Pop{?h`gg^4_qX23Dq1_C% zM-EP$xC0zU-1Sz!k!!zN-fcAZ$S7jOORfw@38`tX#)sKRewl`nLsa=&h>BQC^BT&x z92%t=%M@WE6De|e-%L;YDvz!lz=j*hCt$f;z#F?xZi7zpiUw>r2$B@J@?Nle;M4zB z_|~nj*Rg6kkD<>dLHjOhc%=0bE#4V)x@Y@rCtX1Ccr|GseZ$qw@|NVg3f0^amQ`3! z#fsNs%Qk#ya!Mc1M7qOVmThG@y2tLa2JEt)tnCHxaDCCpIdK9~F%d~@&^;;UbR0;& z4MN&WfltR58QZBYfhx6WZ8DlJ3?00!NzOUR-D__!VzVu@3@XZz$O0v_z5JjO4$TGD zG9!xAIIs&laN&0j*L+T_=$WqS_%O|pq9`lHY>^H(O%D_}6PYo84Dl--9N{PhSZ)lR zA}e#W(%945$!JLpqf_zl2Gb=0iINI=JEeux>c#jpOeQ7VnAQd#;dI;Lv|x1yD_x$i zy{V>gc~DUSs(h4VNZ5zX8W|kc{+HCkR*nUcPl1d0Ry@sGZ^X;W#vo9zDx=~^o^vJ2 zjF>EHr$S7pLLMXpnj-ZcSijJ1um(&j1Q3Qtw11n_rbbfoA~F$ZiLl)(8$KwdnBy-k z7U_&zWR}%XG8M+rwzpiLDPuNA@K9+gS9i-qeS9QilYv*oLDC#%Z^`CAogur}J*H^u zsx3vKOThTb%k@an_gx2@1=f?_T!d+G(A>V>^T*=GBowG1z3eysV8ij& zzk&S$r?EQlcm!H6@z;phsyy$l}oaM(lp%)u2j`U}k9@+Ck2FF>XyPc~q~IV@nN0ybQ$#7!%T*|Ou()3M9fo14cK;JBe-_E_S{ zG6Uok1%%Sa_021gSReyUM;DnZNxG$5?m$s;ud$-yxaS+_1tw`LbmZqcrCSz6Ov7V= zdtQ8c6oi_ple>aoqvk(!Cb!%L`0*I$dcr5*V9NT2FP$fF9qPn6_ zT}xRnD*!#TVKHAs2B?9u+s6)XXxz-SA57ke{e9-E?0fQzH9|^t$jQVpm6LRASo65vQ75tU_1#QM@{!q z@8_HfkbtFcK$!L32@9|W5dXCXa8lsJMiG zauJm+b5B$?4;*mkDG79SZl@EnbIZ@4=Jpes*pbeF6@A+K1_jXLr_+XnuS2{uVFB=Xqc2NCZF!(s-#fEc~NR>%>;o-AX ztGWXtCnt-J?7vp&Qr|6l) z$Q3r8H{J1W#t!l>2kutmOUWs`pO<|Um4u{9O z>rW|jGk}I8dcM31%4=^r;b1d=x)<-9FPRC?L1Nc|`U4FIDzEYHG#vLZ&wr-jY^)b= z6e@^Zd`%sJ&;JL1`24RL^|s@$oj3e527fo~{^|1u(-#`*o`+TTui zJ4E-e?at9K)caTdLBmJc{$Ou2z}?oO_Q=n*s`K z;1Za2=oUW_;^InvCiZ-dQ{`xhCL^{G?tp}5>~vDEWjCO!kPaA|C8w`|)iDGmfscOT~NJ#bGu5 zK{rM5w2d?hJGMK15Fy8)9Uw84d*O}tCSZ2_19*8s(swH?K^&rG;NqcUH_j7uLBi0$ z_>JCc*p;5aS?b?vX~#Q{T9;J4C`(R9@vt+B%5k}+1!Y4~)W6rCqCPAfG{g;!u#Jxa z&~V@S+p!#KyCbPh-a*v9S&yJMe0zQL3^%HH2gEIO=`Yg8-0%^!LfQPVm zJZLXf`mv|^#x-GQsvIS}L9|TqP@$7a_RuEeSU9sTMQcYxSn>|MYHMQIwm{A}q>gIe z^jOtJfL+?4@Mkq+Le@|rO`@Y|t8wnP6XZ6_>C`&YV;_=YP9cqkh*9=X?JyNBCZ!w} z<+{wFIB)uOeHHj22T~_9e!e-f`$y*iTE07KzJ@G~cCp~=A_{zaL)meh9Sx!2_}j-3 z#?@d<#(47@tOqGiE6F+OGg7Qg8Wh2`hS!CV+Oo9f2z1S;2^`tQJ(11r^os^c6UN<8^t&H>Z&uS30mXHNt)|CrBgxunvW4!yto~=q%?flCj+~i0U*^ zC{F9rDUIid95Jj`+2itkM${2v7w%5;U9CSxE~lwNby`nKIIeJiJo?BOdaVsjEju~` zMQ0RUIw36D){c3fK1H%baG402PQ_8`rUo)yi=&v-i+ps=5`t}*p*e$DZ6n02f7Mx` zz{$EfUJ8275bV51QEOJx=yz8Lr(oz!H!yiSU;u$rNtbObOhE9IoIu?qZtTiza~5`; zOOf!?nEPk;#oKVw^fD|+gSO`D#T(3r29{LXYo~X~l3SiD6>*D`x+)qrNd~K!kDb~F&`>MvqOo0&awJCc8J78)#@z=z|=N5EurGtso(1<2z?M;M*0*i za)bnb#GTNHtoel!py5El;DuN+)&syt_oKrKD0ca8JVsqscAIx64dt|1j9)?bfs9G- z0dA&zIREQnKFeXsCS|28lXv9Cb+P$04g(SQU`kC(>^T)MN_r4^xlJ6bwbKq3k?=Kk zWl+^|kUIE7`GfaHnJn>lfRMb*3SxRW`{nb*J1QxI*AaZ8+uhkTiM{?lVqJRoaW=SS zQ#tofF#}<2dEnr)eu+v7$IyOkK5H2tOh4miPqVXUt0GcmnXAd2{cy|+{`olh;rlFS z9((r}1=24AJ(GH`&dR}u6&!!J9c6wbgRZi}CmX59h>--b7>ty5lVykW;wcB14Y z`0gN2ES7~l`zcERwuPQE9Db{E49id0_2suxRkaVRP1UV+<=TZAy)8vs9rtrSfSif> zz(7?%nbZ4n2c`o;Q?`*2a`{eea<@xAv|BJh0d(|DCITS+_=~d1G4U~Y^8;n(^oxc^ zaTudPG?&9B8a7TbQ&=7`-a;xLX&~MKLvU_QoB<-0=KcHK=80B$%a?q_Y!&iw6x)w# zI~aF#EwWU;wyW)FyzF|IhErLd1}+C~I*OH@P;?{v)f~i^8jC+CMKFn*5UY;ck>BO+ z#jFLQ+!M;VlG;EM(Yc0g%vIMjkcJn1YnzRhNI`Rqsa+RYaQ)=&k(XpT(MM-14<@nPV0`sw-m1^Qhe@&7~HT?N&- zuIa)aK#<@Xf;$9vcXxO9-~@LG?(Xgy+$BJ8cXxMp2=))=T)n#2+`YT!+EstmN7Xpv zh?{4;-}BzrSs%#ixaWvH@8Db9W4e!eD7~m}i*br|C(e+%o3(?P3_R9m^1BS@Y0lOc z^2C+9pM7v_OnX7SS?A%aZgXtiI@@1g04LEB_@wLwfca`S>#dPON&j^aXQ+iqmt}gw zJ6bovoJNA#xf4kRJI88;%;Z?KvbVGnv$VGPXqkS`TrSChJ`7?H0{Y&R=lB@;1%%5u zG1DUjdv&_I(P(2}PLg#*@fySXb}b~i zbR=?NxwokAFq}*pBb%UN&lvTRW{f8RPKb)Dw^|y$^H`*iQ*MaS!>H+2*j>iH3uCUa z>X<18N8a)*$XA+vSfv3CK_?lpAS)0y7U-bDwj~n2S79UsupXy!Y1XvT_Roe83$cU| z>mK|*ftGNT8Zm*Y9k~TV=g6s3^mHX z-hariFYQls<(Y4$A&Uma>h}z5$%A0fuF#_WbDo>mzwvlU$j?8zu#=}tPQ?E zJ{he2r5ge)H?gYrAEzdNPd{?|`!w92_=Vv%^FoR?WY}l5^i@6zAbtU|w6!4S#Yc`@ zU~NWXO4(Z&EFte_Dd^Hfp;6V1*=ycNjwdD@vzm{Dr<^6f6QxpC3)RdNIt4-Cn>zp> z#bl1W!YB8HRKOV7W5MLUH@3oPayGI8T#RlRJ_3AJ0%YUp^T7i)@P7wy*3h1aE61gl zGGwXxJBZpd3zN<^!)KZg*rv~O2q-1ws2ExfRhH6vbL$!ne_h*i6fWyX7c;-XQJf@S zwuBJ(B_#r2&X^PN85b$JLWdiU%d=B82Qj|e7q;Q9)z-5}(zw&Ez(3U;1*lHDFQl08 zEI~v|a>Xe%i9Y7|7T8+J^0&pgTK+k{sSrs^E|)(T5V@vY+vz@G@(C29O2J(TRDSu% zAbit^^a9pJw#I$ubH3(V1cI>v5K; zskkEaE&iYu3B+hcsq*x;;`G+~G-1i0$~o<4z4KWj9Ap)vb5?wEf&m?*p~}j*;jR_e zDXAxLcjEnBq0=Pem+#s@{Njt$a%Wj8D^?}~q8HYu9_@;?wZZ|?5YFf6#>kUdi5b>Y zlXn>|cBt3cG<5>)Fs)Z?O){dEVt=JG6q_#iYQtj3ev0DTn5d3+Ugd+Ayl8n|sTMA~ zGKUH4YRF{Rq2T;UAr@57Vg4%94t;@|8;eL3rvB2zRo+eJ271UVbnf|jtqyQ^!W7j5 zt!u;IhJoq>laOv2HI3$$Ozqi2zGc>l)HAFq##J>8&xq+XtSfKcD(YZ3jJbZ4=D|E7 zi2S2nnzN4CBZ+AW?3Ch13F{&g?tqF8?F(_}3JIH3U)i5FOCmrSZZ`Z54?QI@JJCcm z$)a0VMFid8Mk3e2y2&B9Ky~USI-`A$ezXALr59JmxLc>>?L?x~Q+J{H1v95oU?8Df zytyG(yzii1fBMU9ni#vQ(@wV`ilnt0y_24%M@Z+Eq|{-?2haID@m9@>LWlsK%86l^ z7x~U}5>Whu+K*!CIL$6pE4_)p``cmk8g^J`EpRYrV92^^4{IiztmyOP1dOd=*>E1d+dO&({p=5p@xJG1cCD?{Ewv ziSYsnA5V-8vW1b(kOYfq`8%g+(O;knt_{6=ROcjKW>S)^iD1$ez_ zu_oSMUL&xGShp$aUR%EEj2_hX%>_6&%3waK-g;Y`YiitjTQ+328n19X_npQiM7P3m zi4`GsXj8b8%ypmdyI=r}kD?p1V_NkTF@)Ntknkv3+Xn+s^fkdJkPdW}2z8RA(M!!_ z>EMbh*qtQLCUqX|33iFgQk<__SMs{ykSRoDvU zU$W6>3WMkp=mL%W2Mh;afMk8Q0W&=EX_#V;k@=L{~mD6a+1zL!jQw`#d zw#47FQELjAjrD(KV@0LQdo~uW?>Y9CRr&(6k*q&&yCDTO_JgztfT?&^AiOn=p{ALF$(4zb>M;?R+a33U$$xiKMR^|BIRPAPQNB6^Rex$j+Zu!hul;fKlA4tMAz1 z41DZ6W=Q?oICn;0>{+eYzOMp1B0|*3A?)eC_Ih%utaUP4Pf;33XTikLe?{jG0$uP6 zc8ct((;g{xt=V)1*{s#)U)eo6wFep!)eL1cqk_7>|$md8>$j#ABo8!R(*$xZf~!Wk132DZd{jenn>7;ZyUg zQ)dx*6Je(~G|%lXajZu?d{u@eZ!IGYUyV#0jZ!#ob+nAA$>ETxMW3l_sk1DI*81V$;%GZe z!&HNDZiT^q(lwGeCp~b_NUdw#6)DxdaQDa6If#JfK|liVS4#73oopoJZPGM2$m?qa zPsT3Wj9Vo;<3&H@y3K7Iz?KWvy^vvh#4DVi*k*8o>TuQvvLyRTB6Ed7q5h=pOo;!D zIU!^BxL$BY_Sq_YIBUZ$qTfqiL)14hcnVoojbuN>sLH6*OlD~A$HC4n(mjC_0znv< zBN6{``t=8noxPtHzg@$2nEH2@&izOljgNz;up849C3>nY?e}(&UJ-w+p&&G$`3{qF z)ev;mqYA0oB>Gvv5*Dj!(^(N^5u_1m+RMoDF0XDVK>P!STZA217zo1HA=HGtmdD-l zn8~|q3M?v`c1YrvM|YYF+zIw0`~4JrCSPfd79B<2)Y-kw5oAUo@5U(NY}>4^QDr2f zp5!nm9PcRB9hQlc{w6%4a$iI;jYWbE)A=pyIPjXs>$UUuM!EBmMT7NvCB~AuWrnwN zZTCP&>6^Xa@>J=YVczW)_4eK->zRWR{~7#&5Qp%?i^AfMDqJr?(IJp8szF=<5i7=N zL--s;op`&rB9z>3a1K zxhA&$du0*-93B6cNjl=c*{k@&g#!h;aG%cCdZ20k+^g96kG+b~_q_@o0%2B##01=b zxNv8Rzd(R4T$b03>7OoK+JCN9R7$R;=5TuZ7wW#0@4d}K+~x+1dRo-~<&|QZkpwl6SQryzvKPIgPt#L+AQj4>jkbAD){ z>2?#hxSibnEm5B%uc)Kxp+ICS+_;9~;F{i=9A0A2QRp|lw=7Ql5fcswA!%X(`~yg9 zP(Sy-375+`!ID+yFyU{p!SKOvCEzKTRA=P%yb7v%LaBHVh<8*D;!XVakajReIv~OJ z_)hZEoN^t&B=0DavM%F682{o>JeP@et&N%Ci2b&~2!em!7E{bdns zx^F7A+*_B*h?5BuZO!=3!p%*UilGO0zl}D|-2hoQ)8#Kf7A}4&<>5IzuH|PsDS5PG z{w9llYgHvN7;G*k6hT%5!C1IM#>W|NH&^P)ysjaX$(UMjXR1C?g0J+p8-=|tc$;)6 zwV%fuv9_`8IeWq}YVeNIyrX$hSCJQW1>9b79VHBC1^f;ukRZu=qn@{-Q*Y{0yX6%Z zR0=3txs01vFdmUAYGzEg_KAatcQwn$Tni3ODi1@GQX(f5 ztspDw_m|%4x|3|1D7w`#+a0>p8E+A?RpOR9PLu=!HGF>Pmasi4o7oWbaD||*V9>CQ z)5{`{xWd@iuDX!fZXi_9Wk$NT--V^PEMw7|-2D)i4N1l*j})eqTvQ8I$6|?`L`rS= zn0~vR7bgk-l|H_WsJ+MFlB8in-e28XmDho3Js2Srw`hSZ_=SHm0vSXnNnL0w-SMcn zBaBi_;WN5m_{jt<=M7AxrTRem?#-OjI)qSj$Hr!DlQ~&G+$&x2xt8e1zRgfrcSN7S zDB~tfRc){(b)9QZEyiwh!Jl6P$C=_^a?3I=Qb8pY*%YXkBl~|ohBcI`)%~Vex;yaS z#=plTi0EcUSvzWN*fxzztEt$fN;c9|X47z8P2`0Kw0ePpZ;u*@_cWOKK$VC_sG_JA)gVxak+Ni3CG zQY5~Ut0BUKuO0S~$zJ#=S@UC|WM%Q?GKJ^lcV&D?$bmKSBx^XiakD1!Uxpk%F2Ck) zcm*GBF-|jmd(}3U9#KJ&o5P1gZ?UvF{IT;@xA$&f<*6QR`8tZSuK`O#LHM3S7ACF3 z+Hu-GD;>+5{;L4(?w9h-OM`CCpS)YFNdTOXIdY`R;j(MxI^hKlCYAWMRL=6PE>;Ie z8DNj_(_gMzpvyiHzH{<_ABg*BEdITz_)jhq@y`>3Ke$W{ejt}gOpKgwU7}>lWBx_h zjJVh;*i}gYhDDvsw!mr#GBkI{IyX3~SXvoXU72#u)}KmfN(5g>-v8vnR6cGaFlY&3 zW{iy@D*WsCT8jJLNgJbczj+)w8xDXQ8c^p)B?bmC$_v8&@;rr1G*)_0Gjt4{btcxr zF)yZNfpnl~Hg~M?BZ_8PwHVHX*_c__gb7*o;ewk#X}CFTAerNbF%z44rWm2P%^cu6 zW?MZ7pPDJ5pwHz{M=?$;4w$&*7r0=T0C0Sm%OUt5j0xr`Gp*_CR|NopwN zd4mkChd{VQf;sI(U$7??un(HQ91eaNU0KaUp}@R#;cY*k%AuZuYmN!ZRO63~nZM1* z6nS7*dz8=DH@Wn&%Za&_4elnFhfo;%+N`JlSldzU-P9V$mLx&-y?kghrN@IKB z)BEsw69A0Hr?d#$$P_60B)AmWo7?qayin_q6B<%(Zv=LdYLpy)2ehy@qAgLcYFTMF z%+bwaa?2kx32RNp&6AjqAT+fzlAIoy|A>#}{1#>9U{BWIhM*WQoV4a;ElP*f>+)EoN|1>eI)I)v1S zxDY>Yo1m?dWE1oD&ta@>NcL`x8aJq6hm*kI$@Py2NKOFRHs%nRX7Q=@@~|{o>l_JS zaPHYxr{Wp^#1%mYGkQc8`TOZoXL1|0^+Pr1mlk=#U&jn#V(GPO9DCokq4&`Gnh}YB zxd{JKMx^-3&YZ2Sez6f={*2c3fvaL^&^Ch?RHm^a=fk#*d>~FRU$+T^R^*Q}z$shh zBTWT{VLgEkV_y-Lgtv+coVzqg0XcR_tQDET+B3VRF_nfRmX*81LQMZDLB374+kz&u zF{ckpGtIWlT$y--a$p|X{m)0n$x?k|;{^o_Rp71=vk3(U)sAf`_odviQxj@G5Qx(X z112L5mzE(g84cc(F$9>5VyzE0_N<+~#2z5;VkVy`GU@1yIdXGxAU~YgEMdDvqxXk8{fw1G9;8vC9CO^_KFOl#nmx-oMPL~<8wgQbTX)X_BFg0jfPQm`TO z{7nIL_zKSit#itC+;kv=?BTwr{UuQ@`qgyo; z_Wa^CcwGzDfmowR=qF3%t1xkK^E#C^`IQg0m!q(CVpv{TC@NYz+@Q67CknnE$yTPPK~MsNDCI!KhNVvBE(*A1Y>=@U*}Cs_e(ssM@73YH&e>{s z$IAVYuLBA|m=9(E;6rNBtJ5gt^hRRaQi=?2_*7=m|5X7T zDoJ*Q-5~5Cy4}V6%dh*7&sd5R>!2@w&nB6IwwtrgCDwchwZKlWHjZFFuf?bRXzMxp2R2n&)vr#FUd^u|xv2XRdmUnYVQDxrt7*)pP|uY$>|clD)N+Mx~Bev8Zwn^X{NU zE#4Im$Zt5CjdP@^U-yJcmpWj)Or4FwkNWJ`rkk-POZnYWD%#HrPSu8I?&gA`-#AOk zsbVH4y^TU}e8xD)eX&3Ld!aCKcDqK*nGuVpp!`hyDKo;p#OE{=`joCV zAv3%ZzsfFNyWM^j@T4jBq?)2>&YN$F<4wn>xyRaw4!UoCU}48*xU|Auo9=zmSlF#1 zNkk5sk+eR|vTja`R~A>^?W>tq;$DJ&TpBjJ|U4nKt$Avy#!aa(;=}bmbz&OX+Fi565Ey|yGfPvn2t=b@X%(l zriTHef!J^EvdVbza|1+yhBeYh;Ueyjov(J-xWq)K_h% z&{2$=rY-2>o;a zq?Hdhx&s`1IAo_w%l4@W{w;B%!;`??G~qvb(-3HX&u^6L<}L%z{w%$UPCV!z9wqIh zW>m{~nd2(hbJ=e1;HJ^fOq~1f$JP~BN8WB0Q^<1M&*x`PUas6n4|KK<>k*tx05(Kf z$UBNu^%&K7uewf306Bs%mr$(5;dCYTis*$n!-P`jg#)d4MgVf|xty;{1~x{CS;q8i zUUl)2>lslBk851ny#kZ5cVwhAqsj)w80$MkwjZBWylXmmk4hOj_Pz?kieaI5lFPTo>58(D8d zUOa<{)@1p{(!^2~?bevMS@|*z>l@d8`rGyJ^@_dSX=L*{EHQuw2_Phd(DS}?=CgV9 z%~Ep831eE1gEBM*GIR%x<1i%?ahj?ji{ym9kl#4|$Fd}5s`-+{2f^DeNP?QKjdCAJ zJL7RByHL#$0%B8DFnrNypw7Z1dtvhv zs-7HbsUaWI8s{pTdd>+Va__e~8VMX#35#C*;5*)cIc)SE?HEJtkiE0(V>E8Z7&k}K zs}!fj!YAf}=El1vxU@6Usj9Dog`9_T#&D^<@q2Zt$?`aR{L)I9Yu4uH$-IhDMWKOH+bv@lG*k$q4=I4 z2dn~dj2biM86xBu(+V!ULmYcF=P24QZ)L}@FX1^XMLsP>XJ7Nr$S%Eybm&Z36jI~# zS5acD7jd#S;a?_1q|%E6_z}(>FGY9hOn0K(Tx5CAPYqOa6NN;uC#hN;y<2vz6;x=I zRcBWtJc`s{EzVnYeknr3%92};Td2;}6=4`OBqd+m3wmS0e%KJB29|yN2<(Q6oH`f% zJ^ZbxZn4TqU8tdqTw^7)_4`R<$q9sV*d=}TeC>=MySd(P;V7zAawq0p@|g{y#HEp; zXnko}D~=Kn)j@~Irew!mbu zX*^A(s?D)-Nq7qZ1L1J~oAyqV4y_LE8{^$BmE9DEi|hHFV$-G(n+LZB+pMdLR@DgI zW@qaNtE}d{OzKyU{ekI$41_eyM(@YA%Nr+){nePspxRqma(0WSSEI?`4 zAhSlr$v3XFFCN+5txn_x7b`2uzW%%aLDU!icAm&^W~cGvv`ICkH;*%v6asEZ7I(V+ z-rK)?=?|B(;{5ltIJbW&!T-x>8`1WTWcWYvt?3V?s|A-o5EF*!BvyS!7Q3rpyIhs- z@(Ead_838IYa)(Rt9ALJTEJeE5H^Ku4{buxGAZ{?Any|yxL}*7M0MCKDz1yrsb4oh z@Fhfu6EqQ4odLDDqCk2X6G6iEif6Wb?Z zxK9%nDZ%Dcc|$MtS3TE47O8+2VJPg3r*&u+TRiD+VZzYx;lAG4HQ=*5t1ygxR}r10 zIrev1M+y`|+KeZF4#x zgkKPNM0sc}pj3XM=Q{wOY+HoJiTOf;XNbcM&vfG~j$(V9LxG zs_HMRGF`mR_??KY5)8sQ`8Gb8O?XdGH$>2ijghb}J|G`^aE@H-YBIMhVTCc=+JCq2 z^&JM=a~|?rl9X^{yF3Fmxx*l&G#OzoS2m)&@SB3_Md+F<&mMMI^)@@{`lt-Jxu^Hz zh9?|Nv5l|Ky`POh{u}s>z~D_|6iw*_@n!!Wc8KEW;SUTao_RX%85@6-{jd`xR(Aru zG@6Rm!EX~o`s0mRY(E@%(Vcby9U?N&Wd&D&7->mWo6zh&BM2%RAe1rfXAQwRA8q4o&mhW9*f(z1}bJp`&}Sdn&@ zdJQ{v?3Q{*P|P-5f0D(21>~NtqitA?Hr4b)c9C8Ty}FzFVWul?@(by0WKn2MgqwUf z6DWQa`N1=s!XR*~o-@_5OV&n-W>0!MW;s^i)`)I!%eXctu;z%F;lZ=3JI*WkWm`^@ zVz1?3H4?tL_9*viNe!&}v>iuiWsW9!+Q;BAkt=44s%W7loQ%LxPz8=Y<< zN$8(Nz&!{^aF-~-58Js2pM-xC)PTEv>-8B7l4WI6^>qe#O7^nbRDF;n^!(wkb+fi< z9v{SpH(Ipr)K7b#}Y3Da;$3n%ET5D3XBAd4iL zT2=`Yq9yRoBE99}Ub+cUw3l=CJ7xn}q`2zF2#-7LS)~7tMM}(uwEg#ljQ^5}|MSHA z-)V8y$Q0fm%s$rHRT0fODTHDcYkI~0sRp4MaYhII$dv|G>^3>TRKz1FEm8|V@_7~x z;3>VML5lvS0jBYUb=J7whq?n0>+yntXb>^*oOcCy&O4Hk(z<!ZLdtjbS-qrR*gtwtTK{PA{v*kU2?8zGE0Ck0a}2(!|bpbT+ov+&)f#UZ;C( z5SqQ%6d{yNy^kvB>nS0O{m@zth%RO(`QADDnZn_-Xl8DW_$>ljbxtGU7Sz4v>YiJT zFQ?6joU%7dpdL-43e_=i;#H)Y>ukd0tK2N58OEY%3-&xC}V zOL@P1P<<@Ss%VA%pM^eP6jLH@qD~GYAptvfGy;0-*MQG%{XbH1e(XIJ$M@Uu3*z(N zQxW;kRDAwtDpI?B0Iz~ZI)(Bx8?Vm)L=}JzDx}uq+eBH{%;{Lbb=lv+drrPuG2}7p z2un8*oBCNU@_dp-Vm6sGUZ{7twGejg@b->@F4%4pX6L#lP;U{E-(1ynyFB#;Ue?~w z`ay5CZrO=wbPSb6%Wk;>AKT#CdU^6YP>U;Ja$kXlNo-p$IUmpuIA}!ie8YyJu%i|D zfn77~mv`lE%PxTInPEV>KjNZUTyA1_#t2!%`wKj>{oKzvtPoUmogy_6wdKICFwQS` zr4kWI_)Ws(B6ZD`{)h|3xW7iKA}j-1>FM>VGYC^lZu0{e9>k`<*c;42Kx($@16x-!3UvR62^Av(G8lHV`x zUZqoJ*)!QbGQG#**gs;?d-y#T#Va-cj73#vqTw~zXz;f+n5FC$^mqhGJ8ubi$PlRD zKp~8f>uz1^5a(;hT8?F@ROOe%G+;8maVVEsZ&PRTogfJJkk8^@~@zDH~%PWZGZuF+zoXEM-byw@J==^>^G_LO2JCn+fT$LL2AR69hk2AedQxVPA{ zY-#pmr$pA8C~$wrAdFeK7>WBJFa=j^L<8__g7vg+I(@}>MH=|dDLL65A08q0LoaZ% z&x_e0;nDQv^UqOZ!q!-|Laq?^^Dyd{#X>Tus#ZT~TdW)h?;_)de8$Fi6BV2x%s!{L z5%*pG5_PK3a3+y@`e{hA&h*sS(_(Eob)u0l0@1C*=2g{R){VC`L#vcq9^C8EA9E5; z>C&CF?vys={^WV`(stvpa*(V8ZAs=n{-yf*KFp#o%HwVa4v~*z_Th!0DeZmfAr20} z^x3epRJ&_Gw=#7Kfdgj7o#2|3si1C%O~{NeP<7|y*MEc9-yApDqREdVo34CI87P-VJFxz10U z7f3B$q5J=LEH0EehOz{B&hdVY`tL5i{S!uFWKdT62mqt#nN@!Oadd$JfP9E9s{nj> zN(2D3mHx5yP;f6$xxXe6BusOw1FR3CYtGgTrLM-K`|4Yf=B@WsorsZ`%(vvr*E*tQ zdYd?~GVAzJa%9SS?80!7jPYf&tDGd?u&=3yt}DD52hV&@v`DN0uP;N95mk1~bIg70 zDIIu!B>f(@QM9>J5#Y}Z_$?7X0ReT zV}x)HH)B{7yMDbYocldLY}{_WM;%kTC3q_o$>bzUN|sRzER(oPdmn{ALvoab7CvqM>|3BF!D4k990j!E;QQnue><}4$LE+2 z!v3gMaNL322U>BpjVj_K;$BV_qeGe(cG(6DR1#n{H%G+uGvcstl6W6j7B$;lQSLxF z2oZCLC&!T%no2uH5s{GQbui$`K5B*e`H2%A5D@|wg3${ff_;eT4~Pi|no4z7Pqcy0 zI#vCc{yBuJ=k4eg9ngV={HUXN26o$@YV=ws6jAY&yfcmySWEFD@Ph)QZ( z;rVerVpX5`oo>jFHhR4K2$bX;viNS}E=_rr#aYqQ=|*fceb|n>mu9E&9gD-q*0-k_ zrtc8mU0g(U?}EK9^joL=CP|R;xdz$q4I5!VfmfgwwN7I5@OP9+{LalB&|Dzt>=8|*0JVhE^q>7{vjecoJPS^8BtO_vrRKc{ep2taA=U(@R zRN)9?f?f)s6qjYT)+mfbsp%TGjOPwDd3XNtBC>RSVOvn2%;ogLvyLB)hP(;^>GMMo zsH)P7t6uV_p$_HYA~r#ZFImVEqY=Co?^c}FyA>B|@{LBLZNqHL7-xTC&;+IZ^x58@ zFtUy~H*z?$?I4^Lhd$m<|r zm;zTlZqpMjm+}B*!xJ9q=7&zQ^Hfwc^+b?FL` zgowmEuAWCzp;K!GBaHDdxJpBKduFmq_=6Y8{SUo?iwYQB0{ z?RJeNz=h(h0V13YwBlU2WhfeoD7%3`XyN7I0;d~~r;j;|UdG$-U-sO}8(SIQ4+s98 zHQ;|H;@=&F|KKyXAc8DMXg((J`qq8WU|&G;A}$c~0e;Uh<26@|mk{G`K)JF3Vk&UQ z!SOUR30FQ8X$tWOGi1WA*+ZD3F=>P|62T(m0>^tG#avoY@=rbo;qroA|78tWC(BJT z8zlG$KnHi74GXBk^|mQ~jVJrIU}%(|Z+#Gj; zbUEBN6$*iu9ZqCzA|Xt@Oa{EqvJtICp=!t{)u4Qvb4<{%xN~wjL~K{ENz&$e#bU5+ zXego&`^PL+g%l5d{jkbubxT17Y1%Z7D-`9Gu#+(pNh6 z3apMMF$#)GS6XS>RWZAKvjP0#XUf@(Xzrfach0|FK_2s>e=h0V-!2zp(MXxo6|@s%a+LrRk(U6en#K(jydIjt5>n!Xj-EKR5;QHWUXSz#aaGG( zhXV;$WHAr#PR$nWgqPCm&pQX56HvnDh&s;73v z^#mg5lg93L@5lhuX2?8c_~qSB`o|Z4>;gUAAkH}ZuO6c}4UFvLDSnH16QJW<7kTc& ziasXR=+ctViZ?{lgT-if3N~_+9dk%670x=5?BhL6msDxTJB7ZpuN}_^F@c|ym^yPs z379s&zJiYkOx`qRkrxjTf9&7K4jIQ(WSv_1a||y2HHzMphkGV5@jeENF8nbDbGynP z1I4&2FNw3-;azrBo_*7uYcp%x0jKmAb$!oRy64Wh>O}x+oK7Pl&oIiRdi&Ye#8$L? zXdlm{I{s!_;(H0;7#!)ZhuYI+4fHdCW3aTt$3MqlMX*Fokl~15?_)3;)tcTjJT&T26_Y9eYT&i(q8gZO$M8UIj?{&R~D>||m+reJ%Gq2p& z68E(4n=U(~?|)3UXHJS|f$mejq>Fkn)gc0&4!9K)cz_29-$eHVPY3YORz^@P!$w|f z1mk3NENv=+&%pL7BoV?^DvXXR3YuxEfyKhJIer_lsy@_@2gv?`^jqk@`wsd8H+y&M`{~!-UY?omvQeWvPidJSeo+GWFlRsr0Ql&h zdf7Yn$At2nr1{w*TR_jf4HRp5Fcn_g8L_s)_|*tMo!*#l`%&5`G^IC6LA1g2UO*$2IuPG zkX(Be^@-Cq*(yh@f`tk;ZNRLkK)C(mLXLu?d-`U4)ANPYaBUIKABVlED(rUpyI-Kd zt_mSvv}niMnBdw*Cpdq3?(m=tSG4gvf;LC_WPU!G{EGYomsR{XU~=jJ!)h&<{z3ns^abMX5Q>jJu9t2m17g2q_d6wfMFC=`pk& z^~O5KRNM}>P!nISvWjXio~9#Xz(XN;QeO;CLG|B=8>OHiCUJxFm|Ig1pcWvOA<1Uz_Qyj+2?9+pT~WcUf#X1y)CzXVCSrWymlX4q%Ael7@5z@s3oC#N>$px)us5c%km1sOrlKtakkUc6kNu0RNc+@ zq#~SnrlTKzYoD3e1=Q;kG2&yHs3D-`=Ts}YoH}pc##@Ak@up|SVCCvDbzm^OKD`#5 zxVE`*ROsYaauBP`7){AXq$5`0fpTUn!k5C1TOy<)S>)4sS zIf$d?XQ#`dVa@ri4}1bmg&ae1(F)wOU0h24>MF=6H9WVRkFo}TQ0@l?HlZ4brLRi zBBxK~-6&~8ZICv(Bjhom5qmy*gmY|F&M$osB_sZDYlnr6@~leEqsJ!G*X#oc+=pF8JE4iRqHjMF7`Tc|J#Jer z73VLH4r1)eH%0D(`jc?M&)b!a*;?*f^&g5GfFegXEx?9Ah6m`x9lO3eaWx;lBik-y zs18e2`NygTTZY6a%pOY_(R3w(AOoE^sK+IB2FoV4q8}oL{Eu(Kye*g2x`(K&3g8x1Jbhf8hn|fzmv>&Q2eCmB6;*9x66Z=MBRRkzv z!50J)dy@%4w0$S&M4kmM(rLnT)>dAh((PZzE6456533hVyr<&;u+V^L2nRkWz<@B` z0qx^dD)CY6A@sB{e=t`Z3C#p@l7^>4{e+XcIm{%QM4p;*mZH3}MpE~&atlg}yu9KxxyCa=e&f2P*-09l-c}JkWX#LMp71 z2PiY42^OJxU5u>-*$CkRFij0V9uTBU35kB_Whwl$L)_DKRps~aOZC;Tx;q9B=9UO{ zpp|83+s#!C1FoF`4hVMr!oLqmbLUCa_6|GxU{{H9C!)^_V_TK}5*(<5*Usr`P6vIN zk#Z8%WleUI3xLBo2Eeh^3m;kr7e(WY~8o4}_pm=D1_yG!6*ujS>iWVa8}{yv z`(&>fH=m-SH5{v@tKOfz^79>Q?WK_MiZ$VIKUw*kU{k?Di_LsrfH z?NNF1?_AwhvI&}&E=tSo7mh$z>Z~#}n+Kii!M8MsV zunTx$9d;`Fn8-W6%Ja>Y4V!D#F!MR7C9t&B^fkfkq>-B&CLX1-pT)$me#}sYL^Zbw z%4tws9H^?uYrs)TVl*M8&XC&IGAUS}W{)eY8!T#4Ww&7MMd?e?n~WXcLSyQGNvzIx z9eh11*E9Cp!RkE<*;En1TaX^~cZCLSJecGhlf}4FsbL@~_mwA-w1yyjiU`rs>?4=u z-h&vd%VqXd7)KFlA5_pb4NTybP~>FFToF?QN}1+yg?Bi1sJvgtge+*%nFi!qhm}(M zBTfoxCZBm^PYbK8IBMUSIGGd0@yZ{|380b-*03amEO^+M{@ki9gVgU#oaYStRN)^? zoMI!RItGx5i>=cnB!n?=$OD5sfALt=A1@NVeiBZ)`bDc7o#(s8<+*(tzX>k9easr3 z)f%bN2cPf*j+F!tPum5%>0Tyb^Wyb9Fs6H{u-+M=0(3(l-2=$P&DH+F#C-&iED|{D zP&0NSOXv{P^omLFy zkq$PR%cp<0NA3S$;{Lk<_n)i01b=1X@E7kUwmQ;2Ao%vLx&jv-*hJwMV%ff+7m)Nu z)J|b4+%Ouink5w1g2x~nK0+O^7RDw`1DQCfibOr8ZhZ)VuoIApgB}MmabubNl8_PW zJ37~I`e7WCU0>I~J^=ppAX^kwPc;rW-~N3j4w&$NZ<*Iv$x2L9^)nBB2pP-ep2+kK z$G3{+zC=_8OebbM`yKUE*`@o|3v8OeQ2I4t&3;+!XV2S|l z3jh$GjRjGcmG()DRXwL z?Jy~!dW@n8U*18shcx_}9as|o1vuf7M*w0%P|-fpMLvgBg!)rQcLzob^dP|j?0SBb z#G{(I1ql}<7!rKw2;BNvlh2JE6DV++&kv)On@o_41WvLS+4aR;5ym%RayPFq8l^W$ z#^q&&B-7m$w55FFbhCmDez8}#jsFI$c^r^Ie=x;oNrm<*Banp`<&}BSgOBUFuLldi zkd1(0`dcd)PA9aJpXi3bu*By0;%IJjwyj&i9rNe!_@B;fPUFESY{8x~q2rQfz_tgS zmBaoa+3Iytyp8I@+V}P}T{jGp_dN$=W%~Or_ ziyU(T?r*s^Q-is!8}mE0p`I1N&)MiwBg&j{`iGBfFCR%V6xvx5T+-~XCd&Q%yb(BE z#sZ?ZARN+JhuYBhJdoK;naA?6zEa)R9AR;jDu27OFi<2~Kg7q~%U6$hZcKMbO4{du zIyB+I+IO;{(Ro0gE!Rz-dy~89z;0L!l}c|PVn9%Ho28)}QU4a&>T)?=84iIpNl7|g zB+%KXd8nu_xvDMsvh7<4r@w8QdU9FH^I4wxb&{WJ2r=!WK_W3Od+;J`j5Z+)nU(xO z0b6yk7t?A}JgH)QnWlkhgBST3RTLCfyZBj{=1_H0fd|zBqBQHk0u~;La)dWE5+_&8 zFj6Z{Po%sxBjU0cc7SYH(yd`)pnsLVl9;fw%It&PwYj0f>xSX z0huZXj!=~c_#AhVxCfDmb>{u>P?=mZxe~T(Djox5U?vJY2b27);E*`{y7Bhrdgbt5 z*xdxOY-^_Ctxh!d(c@s8wV$)+qse}i8O>TyIgOdjVzCLj#S}Dd!`3vORATaExPJA! zans7spEV`I8Uz+)ew{rQXU@gAe1p8t2IZEOe7@02JX3^DmAe%<3|>TN!#xOvA87dg zEE~IUi&A9#l{7(VJ#5+&!Z!00RR^V|MirB=zqFVk;Kk5pI4k+N|2FSNpvb_r@p?&i zMyK~!``aq-GLahl)39^l-C_wx=gu~G=G8ofiW9=*nXbpBz&J$}5f0iEIan)8vHS(zhVD|le81BDh-~T+`0<-U3LFOr-E-Kr-1J!npS(cbrOO2!#=1f zp(Ioe65@W(SArfqMmHIBh=b8KAdGR(bq>7TyKW!Vi>YgZ2Dk|WL?f8<18W@+x#_Z> zW`5$EjgkB?{}#g5YgSU09J6wA5f{OpsA&fys#0QZq;wrp8hBNR0{SD(eYNt-SM6OJ zew7J&TpZR>lW1boLO^tmJT3$>Bl#eTKK3i5c7d%sz8@TYKybGPAU;@CnRIyC2~Iq8 zNQC`EhYdZy@&YpSFndJ+(*a)=u{o3l34clfGi%q{q>mm(qsP=pvz*tY|NQtp%*1E7 zb~gA`mV>*C`HW|I&bQ(DVBGARMSY+$kc`igXy;9oGahx0>vJJQ&|cf=^W~&o5D$pL zeXsa(GA#i7?(Q1g-GaNjyE`OU@Z3qZ zoV8Y+I(x5Ml_x3>Op0psf6PAGH`;!UOS1_>y37WIA5-c6XyO8V_DBGL!kKbfpc(xP z8ce4q0z2c`Q<{m zr>vZ@2JAi6d!7sDORvv&kR^Hgb}ieF>A&WxdJ?UB5Ao=(qVrV=NPE)HBI~rHU#_P= zR3WwLGdo4X&#y^mz^hxFt6OC4&f0{Yh$$Ersy?q*wVeM{+5Q1ljX`BBv0WXPyhc1N z**pK053CKHF=00H>v5ujVXT7VAOd0o<5w#Rz3Lw)y?#yg5Mi2((3DQ5-JKF)s*07L!W8(A5U*WzYm1D;7vUVIcj|1$6^l z%=GFBy|MeKWx3Wr=!IEZ?^I<50aua*Dsw*gs!LeRtKp~1TCm%Fxh9po=*2d);n89D z((FMkunRI{D%(_;NI+u5DS6tNxq~9Xe zk+LQD9uax<0o6DyofLCUGf`eE;xrw-n!T)6$ER}Su#*@uMsAbunfxsGE*r>~v{sNK z9#$MaUvDLKt$cR6`edet`?5ON8b@X3f+@4;VB$MkJ{etLpLNY0R616GK~Kw*Wsrt6 zgPm+~w>p9x+H;vq8TFV@hM0d9uuQ>WD6GI03W=6LMh74`{oWIH>L&OzSSzwi(F9oo zo4uO2jkmaGY6qJSSbv`UdQg!p{~iSQ@AUh_3d6A0(O=*18~qi6!|V_-oHB+DBk?ml z%jxssm|AzoGbX$W)&VZ5(W(CfK<*YjB5;5s!_fZu8-jaJ`T{9aKYCzrvVsU@!Tt)t zrJ#SN1v?oBAUK=?qRAg=t1I40JglNbJdf4;e=+V(&FN?U9s~zG+TVcS6oIMsIr|{d zqqz;hkDALHeIeb=z#1Q6Yg98! z6mPE6NJ_eQEB$H%8Z1b;NJe*K$W7mbwtNt6?lKTsNP9TTbD)MWnqe+Pg7^5AoOfM5iLeoMw-jZs$>(!IqbEg^Fmf&#|*yD<(2N*)w6RzR3l+KiWnKLt7YcZ9~ z7s1}JNWgi`hDlrOVvro;!>IlzC0-OPe+c|T^y#I*x{;4_I>X!y8R-wHIy} zUXzqIs>*?IM;qDBPho-PMmceB5X*=~ugB^q%MT?SOxXl_8JvBGKnH|2?^t}iQ$PQp z&B-?isau~=FWncTdgbrVK1`hV#p_X6CdbK-HP;x+E-`1j<8v2EELggMuv*Ywn+Kj} zc&d<99!0m}!L!nQe=loOR`iBsU<&Wdv9i^XSypE#Ne5%lLh1;^?-a%?3746{g4-e` zTxA?MbdlHOwj>H!-q)_wiDIuS=3ij2MytU3kvPJgRv)pG#k;+}b1$QZ7s5`Cj%XI- zwQiJ!n{ssY| zt6iR`9*Nb5;Y&RaL3qqNI?(w85CZV$#HuOuJ3*Lyk$tuRKA ziF$t~LYtlS|4f>$CL*Ht42o0&mn#o-8_~RD5-gT9#TdV~jd*!WlobkZEFkDeh!MO% zFIW9wps0m*JYwGHc~K&DWK&GZIPZ4*^q2CQIW@P3SN-_Ehv5F0h5z@I`!5LY+1FvD zZFOB}CvvJ>4|p0aMF&w?ez)BKzUOV1Qe7gq=AH$QqUX%jN$%=X-cY_L3p znTXw^)o>j&5^5B{q>oM4pJJ5bkWDFt*Jtb#%u^^5W5oe90rOqFHUVGo5h0oEyO2S4 zQsaOaCWG692tc~)72SUGl37w2p4DU+%$;3F%^l9>UBEL;-Hn9*N;W)eF&0o!Ue;b+ zQ7^?jKmLv2Ye{%JHz&~AOcfW`ZAmEcnVkRx;vv>9yN=~!0>aKB%k}9{laQO`TgPC| zeycG}UE!jp9h3M3HZ*w%mpp0-%_+jLxG7T}gK|j!VbS-aa%{bE0T8~ZRZ-9C;Ba|-s#~TQEJ$288lJ}h z9!%yF&#kV4f_!Mt?lyj4E3trsqHdS{c7pgZ6euqg_Z!j%AVM=7B|JG4~CDn*(5fL6+WQ`}<< zU@;972=Ac@OZr+Lb(AZYGO)mQes{o|j+G@a+vooP`IW2*9?IDsSc}kMKL3isaBHM9z zvX4bN@2Wy*e6SYyXuZvwzg#&xmu&N;gDwm4=%OhztZ=y6wZzj*qa%7I%jmFvXE#5_ zn{ygYTwJdcLOeElp^F4y;4T6lUFh?#X-S^Hg`1BjaI}utfR=1jIAPb1?TZVvwFqsD zO@b>KJ-SIy5E-<)cBkUoq)8i&OS&>rg}lU7bXF&B{hYcN7(Np_ zo?1vc2M>25(wmC3go<+V`Re8*CeV2fD>dJ$`-XJgS!2Iu9`-2?tzzx`0)1ZOD@ldv zhZQS$nK1NXnYZg|y(F6W7OmzAGie*+2h^217>A&{D6`0y*TPUd7yCy8z(@Ur91iZe zLGSJhX?CI&hUh{f`e`>CfBVv)RwCzA!Z`Tn)0cwSDRPrtIf1 zLciYPYRLl=Qo z@N@M7!{BpuOtld5T6&@1c+Bs=Zd8hcKH>HG>v?W&E9vOpW8nTL4*xLr{%rnJ&wsPB;GpOD|Hr_wI><8uHYx_8UX?6a|rrx z0m-FoH%sU1k~6)xtsHrdH79nTQ{AqxxWOxc)SIXUWyizP&Pce$R#GVp%*R!qGEPA8JD+2eWTE&l0JrzLU zD7Z!d1THk4g>!bN_o+vj8HcPR)BGLIjVqTNGv6+jyXe-98RsMvG}M;~-pA8i$&2Yi zKl5b&cI;Co;AnSSBhJ58MB4oafPC^5k>Rpg<3nkX983)T0|`csRxV@ypWO zbFJoMeglH*Eti{x&nadU+G3cO;Kxx(oZm;g2Lr(HTPL}PQC(1p0UYgOoe96f80Ar2 zb$p|xZkI=Hpw~at-XJ%-d*H>`psMa({)~K@r%bVt2?v2vfANt(^4wCA1NNvADDo&0UCf7ofn6uaC8R_EdC)yz4ADdtkBl z>K_~*SdypDn8SZ0xz7OXq2}Ca+Y%Lx5lf)C_6mxI>!*i{lCXG5>*@mGQY~5Dk{d}t56jO^SU1EqUH+0^ zz?oAF)JX$fM!HHOxnhj{^_9=WP<7`t#rK6NN7q)o=Bb)LEg{Z}l5-culOZP~K-f5E zjm)(L0&q^SYs3^|iCZ`4`5og9-u98CG)#L^-DyvG3b;(v(-JavZ~w^MQ(x0p;TWDQ zEsT!?*S5{ZK|<=*L&Fail!5n%;e_kJI;GK$JYfc10~2I34#Qm&bpe?(THp*%6$6S< z$_)=6C0aa;8^vUtw6;q&a^?L_@Y@n&0OMYuvVMB4qB|x1QorImYUQ_4be-LVf#+jQ zCy7Fe80Lup8qECp;%GLMs)(SnFaUx3a;$;AQIhl%X5rFx!AzpCO!1B^s&#mcU!r^` zr=_TlL9daXn_j<2U+ZBX70Io?y5ViX96@uNXQq7#M&`K~q0Y@)@k*9OH-2&cew=Aq zgtny;pnAK)b(k9y*TeGF7wSjL_0A>D8*Rui3lDYB73*6;hCMe!OLqvsMJ|{I1%ld!Ax~V(#LVSq_k`1;BgqBsX8D0Fn6qL-y|E%R{zNu>c(|0Z8z!*_ zR$hCaFodRi%eh|x@xcg(VNgzamsJwG*xX*lMzt@vIjGc-My8)KH5`gS2Pt0n_Wlbf z3VW}xjZAlr3@0m{=N6_;gJk75*`J_$!LJ4!@oxhz*pJNH^JmDlE&g`vCVseZ6j~%P zIN~c6@6CrV2!(sDthUC}+T!ADQ8}APIMGgQa~83-Z3os`{VNs~{*{7Pd-L<5`V#)s z;Wq{E{E4~0JGW2{jFBWaL;tS^+|)k}IQOOB2HaUSaF2JyCmK}LmB{I!7*4qrJE3Ep znaW`_35TLH$eqM*AHQsr{(e@v-u0Hh=#YKs#C*DI;!g$~=AR6>0aiyDuic>8fzPS| z!eX3vKZ`WcA5hF8qU674V6~8T!@xrG+#9x#9KBPl$C_?{rz-IIs(L+qgXB(MIe3(S zeECYjUu0v*BQrLMnx4a8)Tvp>U~@QZVeuap!fUCE&4fuf;1L+J}}eIkWsF-8no*RrW0d(oJ`c3MVguc)0Cb zz=6jX033MlDwhofp)^F(1K1KS)#X!~Huxf)v}J2Kjx<8>y^o1HGE-EAnG1u|Q6JMI zGywxHBX6PRw*hBCa4lgnq@-g!B_+} z1Co)?JLPyefzJ0XCHdOj5n$^M$t-3g5HEvF2i^;^3X*iQZxYzat>z(v)De{XzuGWv zM-xQmYrii(9>3VXidU@oek}nw@KKl7-2NFOZm$k}<-2R+Ak-zfcwM*_kDq2JK>Z$tmEl2}$xFfnQ>%GX5 z6U)r9CTv3xEzP9u-h6luZUVquKxb$-{rq{<_}EdFzE;Moh~)hoh)V@Ej2L8Ne4;B) z;C+yKM7vPSZ0!+f`i?8sh@BH-0$HOef~Sk3;z>?|6$bq_woYq@8yMm^pN!$hjc{)J!IK;7rzm>abD-( z-#uin2wV=u>v}HP{;o+$gD8ilF*qsF)tuNVN54j5595<-cm-cq_M9Xw2pew-1Sl1- zotwWo%8KtYdC#S#@r&PblG1(YOtTd6&y(&jHb!#|FzNoc2;A%Q8QM7MTN*Jl=o|ds zx71$GHeTQ0Suye%wXN&C?}gVorhlinGss}svjSR8?lFn-BPQhe^ zemz#XjqF))wWf|cfv7)wM9OEhOiqg?Rw9>)g+wyV%93RemwoVs?kYXjS4tLejy=ZR zGJ#8KJA|e5-aP_f-*bR!-nY>4Aikd0LOy*slCh?WGi(L0qQ0vcdDQc0g{@wWansy6 z^-zbYLV`VYXC-E3mTMGvH2XR?F?~=r6jJ7wErq0t`=vOBu*=vWtcRtDpxr`f&2Zs6 zvT|$L*{92A&yOFP)2fRMqSKmL@g z$lV+9uvE&R)cb8q$TuS%l%ctPB!&SWyJo9oxk)7J6>Y1~kdP!Unq7J)JUx<+!CO!W z-N~x5fJPprjl8X3WPUGZHgvzcA$BB@>;YJyk*7pfBK^Av1XA)A3>@a%2#-gS%dPck z-SVdG1*V%pp>t0-+T#3sBMOsp;8t=n+s}upE6iIiCqf(#cY@?_CZ0oy_|A?uQ!>-Z z4H4=bF6^(oJqvrUa{JVD@gO0p$@fQ_vZeBf8C^mgaMn;yk3;-#K@So&oD&Q|_PVCc z9~bwpB0jzgAMaWyn&?Nh-dnM*=~J{XY|^ZnSE3Z#pigT&Ov*jIxpt_SbXpUVIC_lwG(7M3L^d?>j0_~Q(8#b z`=qM$la%HUYx|C+NahrI(he;=IA_A@Np^A?%RJ;;1n-36gh$QHlEq41*V6>Mv$QNL zx2J!>S5CG#rD~)=Ni}{CdHYoMB)jhb<;*pld3myc{@|wi&g#5ru7uBL8YXBhc7fW- zY_p2kshQ#@)6mKgWAIH*fPH+1%h5#(tI6Q1`DbdZ7dgVdz#+#aUCdkecx`7$MVT|z zdIWqv-+UlN}l7sm^sF`^MWVvhrzP zWZ4vxejVd}B*&7w594}c$^H_$Dsw@7Ezu<;hf=JO!aWoB0#yxe@|`>YDogpx5O zQAmj4W{Qq|nBD^z*Q0`zdO{tp@Gwnl?vgjrp><(Vn%yyH<;dWy#>cj;?0MIB*P>thuvuUb}&kDL764f|uI$HBc_zH)Ka zW=vd!JX8&%3)7bb!n@Ac8N8KG>cvUzX4jjV_uc*?!l|%*Z|Cv3+X#=DE0{7CU2>`y z%L4*-3l4IAC2aN8Q{V6IM&!pyPRh0G_m=VIKv@H)d zEl`0k+?x!hTN7y^-L{#-xOkO@NI$w#vX@|h%{6(tbGA6YXK~{uN+ne#n})U=c5)x$ zG(*TmhQE%$EDm!6ukE}D|0R(5=WP5>L-1d+ainQh^Sx9AS!)%djcV{SHh63|_j3@vISh3p2tvl@ASmGW_GjmGqtqff{0_cJ$)FtAT78r)N{R_ zfSMVpuAiMFcmft$g#acV4HSxa^O)TU4eR~t6iRN42}Wa%bz9%Ih4S7 zKA2m229vpmyd~Nn-u)iFxBuJ2d&HoprrW_;0rc%ui_r@-VWyd^c(pry1$J2bN$~U%x{M%nmCNo+dxzo3nf2$F<3X70n7s{Af8K9V z4|X+mog_h5y5{X-iwAH(JO+<H3#&-qSl{(LN zV<)Qm?vrzqVxxBVr%xl8Bx%A)Naf$jQrwdZ*0H@Ao5XVVwD*gl&2DfjTMd9uUBv^K z_%%ary{h8Kfd!41_k2rlB`Muddaxo*eU4B_ZA zGh33iEWCWpGPB2_Z^@CBlow*OplmwWUsZx)=GrV>j(RR}A#PM#YGe`$Tvm(83q=k? zuu`4z$YM10I1BwA;*l5aL%MubckU2!qx5ac3B=+G{jgPZGQGg@eu z81-pZHpPg=M1z#-pbf)+x!Az)!G-_t_-}tq$Nw}N|H*&*_$U9Z`q(&ZrJ}4fDEC+9 zzx}t75gzfDsJJntA4k|!K~|~6s!D5g+9!SZk}zW|6v^UBu%%ywObkJ(aK)RaGO8jq zj2v;~dk8QJ&YX7ri(9g3(ninmKM&G>HI5MI#;u7_ zh(xrrkpXRY;_ZL`|zNIkM>@}`$0mxCu zD{^$UGiA5p2mo+#e?pEXegzGa4Dls*1x^PCAEcZ)Ss+t{0f+YEHBy&BMiwF!BGEW_+XFNwP{CRo^CcOK#m%pX!8q8?)PKP zsfCZ%H}FJmKbN4}z44qunLANl-cI$rS!~MF$pZj5izJxGJcx>=uJyND4rrjSI}?hl zy(w>}EXcqHf&a61p}lsow#-=H_vr%3&EnT8Js#30mveXpeU;EI{BU(U{-^|(suAf2 zk+LHfJ?8$?ToZW^k2h1}3ds#&>TEXbyhOxL>~z7cTK;XyG190mcPo|nOQi`#j4Oe! z09@!R0EasR2uHmi)~C>BXbz+R;Rsv6%@*fAy>2+|Do53&TlKQ2Y3;PAI66osX>3s% z+2GpqVN<&Gh`n2o+l(XQDp`S!k04Jx{GF9)J3|}QooH@l?BTP;A}t&rOvL9(1#E0I znJ-^_0}rk0`-~)4)eB48$yXSi$lLvC5$sYPk7O^IA>W5%=Civ6OnW&Jz2`4 z2m06cxt7LNr}&bLg+~s~4+R6PaqsVVJl-ZCdNgmv4Joa_>mA&h1+0H0QEi|!a=?fS zpDOh)Kslz0vA;Z>gdXU}T)p-@?Toww^Y6n-t_gy5p8^25G@Gwb0Xmhofmjc@pEo2S z1SU<;qB(gS_tcu==r!e%_YLZH+38vk9bN&r+0K6faKl{#)HmY*07teN5&0W{i~SA2 zallr5on7#C4juVLnZQ5v3c!&kS(LrVn-L&tkbacp)k{bpi0hhmGtpLP&=I9#jB1fw z~)lf0uggUq)JI(*(-@p+W036xNY`C|#cI6{@f(^349tgNV8C&jZKs660=6JsL zp4}9c&walxXI(Rsn+?j?kH)wA-YdXA#j-zB4t5C($>F9}>X2+rIcz;}D8s-Z37{H=2V zuto+q)4)`@KN55REz%hYX_sVSUq^fCwjJW_FqhJy9r94KLzf-hw;(SNaWTbPz{pV- zT-^;WZlYAN6uS)e&ewj6^s?DBp>k6=>!rx&!v9hxthQZ@kXxSXWQJ4APZ! zfWPCi-uoRk6E$~A!7P@pvg(`E>&!QALfSQQe^%DMmxm!`g?-V``y|Clh#{nr+qjk) zUoN5Q|1t@=WS2vGL$9SbNM(KZws3@b*FW7_o7};=$X_sOvXDY3_cFnGgCPIrvFb)B znNU{V9-425-r?6)-~_X+=x0TA&wYPI=Sv%bid{#amZ35TCteThA=KwGhWA<7Ns0-z z{t3W0#U+_#H#wtoW$8R|aoR5R{&cTEmXd{lF`)c>2Cl9CvqnR{kt9K!%w(zmzQb%3 z>E8BI4l+_Cz5C%8kspb7q(CI540}*Nw5z7w)agthz_h*33Br2V7U~oa5LmRqdX2=R zPjzYKT1v@SsCBzc>p!s%`1(+F=X-H8)(3F`6SKQZ9A|8vaG~jWGoqr<)E}pbyh|}y zplgG?DRxQ=w1v9j@I-2gJWtYAG%kJF@en%Siq$fLx_l^J+MYlnh!#@|(QL^XC*vFM z@zTgS@vdE!9jj%U1A$=Bs)B3ZJDUV8M2RJ4l!_*@6|n?F32|Yu5YBn&@pRtd3nMn3 zZIXpmTP}a`dC@yo@F|S+?M+1}6xLGfDeDL z@juMWe{Oq_Z^4iyy$l)SfDi_xH~79*j_S|wzuO+xn*Y`IASpwOl_NenG@(>JNpDPB z3mOx3Z%*dyTb;NE6rh0TS+HQ&xtl>|2U5imZ$eC5I#F}7APz)L-Z(VXJ^fnF*1oQ4 zwJB%+^LesWoHbrGFa`g&(A(<+npyu>GqBGGJXL%jCKCqAA8Vri5$**p=0QGc&Kiwo zdC^2Fw6&V-9Fta6hulZQG!k{y+?0hOZHva&^AACT*h3njKH<-w6uK9`>x+D*&Cehu z6^+$c8(vOTrd=VLZcAd;e02TUeBrS%0UVk?}EWG=PK zd^Q=@;=|$8Fu0C$fdcLgk@Sljjwp}vW}o5*if8)1e5=OS6ew;#4k z(F|>9mpsItM(YR0U(V@W;pCoqk6>fg=t3gWN<3JX7&pB?el`&zKR=SN33lWe@&*JW zc*%4_+2Cu9L2p1nF2A^`xVW*tNLV(mc1ily=5p2m3H{yj3|>J&BeV}c+{`Y@H^Jpc ze4M?c+RRR;Vfay0rWh!1P_T1qf1OFPibH;n1NgK-*Jszk1x-ziBQQIt_WSw7_bMrb z)_72WW@OKemX&2Dl~iey_*tEiZ5;L1fy)Rd8+lFu`~DQcPQU0%q-rbf$IVkD4W4Xo zpbX}ix^!dDsDk}Q-JB!%7BO05D%7$xY-9=|i%G;%Bf@}p{015y>XN3I`!5`434IQs zyh8@G$NpYqaQ%+d>jn){CWl^~yi)8AO9FnvXV{ABSz+jJS<{s2$5HXllDP^mJPwB;3$`S(~^_q0STDEW+y7+O{n4o`c&QK+`kfr_l2yPp*?k97sg^Xq(gioPP$ zgDq5PI9)5anKF&8MqrL1Vj|j(u935RGAdY+b{O*Vv42E6O2#_wNS3N=d*fhSsd1ec zl2X0wTGo;t5tMQxIHS(}amLxN*2~e>a%qU}ORY;^k~&@cDCSxuGws>2=D5KEs#op; z#Vw4!&4=r35#I?blo(EvR?l~nLm2e5Qj&UN&bTV+fubf2bh~p7P@1hiXt}FIm*2gG z>eF^8eLz_8Hw0iQH%ky&0q4!duqjba8*-T%aNdMihRl1u8OKhrsyvmH5!|Hse{>+% zpj|;8@cJToo9bG23%7i`SXArl5gFaz)grHZ=JcpnH#DZMdJ|^6q=Ocs{A-g|D|jxF z#)5P{H2~FaRF-SOAWsOi(4B$Md26PSU32K3AVnU4^HzZ_rC#Jg4LEOs|8(BIVkW1M&j153J3 z9I|N>MW--#ni;o-BiX3qWr|s9<@c7?Asn9OBsvgJo4x7!YBA${0^XznZsOqc2E(CP z&3muQuKmd;o*QKzc$bp#^KT4{-&(!8V031FwdZ@~iTYTS?md08do=2M`cfjf1X4$q z!Ru**GH+iNbRjJa+<~U)plyu#wJd~9-ZqViL(SGc1f2^ii8C2<$PWO>g`x+Q=3zDB zlWOum9M8Qlu$l{aw!8lq&gd6}m(1Uh-u{q_|6vr42XfH_dtf7(1uO1u9SFu7sf$^p zUsb1d)-z%x{FddT)=R4bja|7XUuhL%O?RTI?Nb-Sti)`}eS*VdMoC}fZ~Y};4SK>* zU}c6|LWARDXOC6piPY= z6h=b#F^fP$q-n{0i0!WANiH7eK*3sucrXn-i=E#uq(x9RH}EgWt=Mf6+YU9^z;wJ% zFANATy|IeRkr>f}BN6mR0bzTXhXU2h521sc-zq%hCgy=w;FQCSu}g*&i1Ne`J*Kcfv@4IO}7*U#=0u0wvnd2k+!xRwybaGJn*gl=Mp_U!{&W0WA<0p z&_2R4vnKJ*U4k=P1#4IqJ|xTj)R!riB46!LOA}K|j|#I?TJ21{XhL|P2}0MzO699Z zFV5Y534L2FGv6#Tgef|#5$j;D2cRGCo#5qvnwPwB2zd6CF@ri3_Ie}6#Uq@KYsrtn zdpoq~?yZ?0L8b3s2!Bvsps8of)ojym-V*8P8=@&~qWKz)@GJ-6OB@JP-qF9KQSl=X zjrJ1ySPDQiVmylV{UaLLHGfBAIV}-hV`N773(SJraSr&ptXUl0jrhk_YI$nt*~|;) znCIBb1mlI=>8IL>r-Z1K@aY};M=Fggd>^jO9SE(sEmlOL*3G&vz}+Yd>az_b8fxM4 zP6EwxUhihQI&|Z6G57;$xCwh88Xe|`N9$7e;~rmjk;tdn80Wp15=`B4_D2cp59u*j z4A_3CDdXTFvz&kzI5@@^oPn7<9!?&H#;GHjTy(0cA?WJC+lZ#Dlpo`bqx~Zqo#FLm zfoS{!lC?rg%4vefk8XMZr;1*%_l}GQu`wf%;&(LKL1~uyfalip?`}N@n43i4Jqg;L z?vmAYLTDxEQ87<`k3?8NErHF>*k{|IU{x$*AGIjBlQOtx98N{a;woYl&t=buzL8mYsFTbONA(S{lOKB8Qz1=S^2%o8y&1AG? zgCqhu&J4%PW`P9$;OM~R7Zm`~+fUN>7D%O##_U6NcAY)Iww!*kpUYNL%Jez2;y~V_0RiZYyhYtG={n2PqGZ z3z}f))(CXFJ7q-&mn*w$wLiJ9qz@3BrnQRMLfuL8B*v|Z2O|i13I4ci(RlcjKres$ z7MFH7Ypktun{>fZTs!&d*A3C1N5-i{Hj}?2z5P2H|1c5%pY;%b+_0Ga=OsG99~-|n zEY5k2gROx}be6v_(WTDxiyjdI(%YP9_LWTA{$U?Bc)rMK6o`|rvj{vy4NY5kVokODGP8Vo6SV(&s~ep^SBWEbh?|*mRO6gyK^0RDR2#~D> zP$m#!XzfYW>v|(W4Mv0Eh$Kfg@FEPfUfQ2DCKx-Go7y=#wha&C>G8wF@ z^LApkUN?FlQw9RX5-RUAb0HHt<>xN3KzgvYX&AhD32^&TZT5l=4G6F=1}?fa5NjW@ zc(``=9wA;LBo562GX-B97D6~5`#qGfvV+tQBRh2ndb>hTQNV-R?oLsQx?p-ufU0Ld zKBV8yo8Y#u7s@}Jx4{P4aqFyf>5RIMN8e8!?2o^)_icei)-$TXn$Z&Mf09aTZCkwO za^^ZD1odb+1GXxjC%u(kw<;cRqO3hRAiKhd5aPU=TXrixGnNT?b>5*X-=0}ukBM2V_;Jm>z_+5w= zZF_vY%VBC~>qQ>f5@5lSRO+`Bt2rH}N~Arj-B8rzc3+S=BM(6&covW4d~^6UgLKeO z@Q_I$k1tx@B2y?fz^=;$u6Ug5id%&LrNcZhC+pqpIJ#VY0>h)E59Y7JQ!b$OtmOU0 z%z0Q{*!U#t!gpZ;rgdGgAgymJU5&$A(S9~gKPqI_*G3s2rM3bVD|H;re>o0kd@YkI zp`mNL_{HwAUg&nn$sA>DaAkUXTxM)0><~j@U5~btDRWrt?+={XLAaAfD|fv&jNCT+OkU$=7`KNoyK%mFjB}39X_icqBZNSi8jh`LM1kjo zS!8iip2xXlC5A15yn?FM+O}7k@`PKQ)eXZU!7hy{@tqVTTq1cvh%fa%OB9rpWJ9Ah zGz}h0hkO|!nswn1zp|U=Xw8xwDA+ca|3am4~7&TAK zJ4RwBlkUk#!?N73>J8_0pX`9LdFEZyyTF2UfQC%6?_$)AAxp{P<9l4}xD{0H+iKgO zWguklz3@s-mAA8@Q9%xNNkw--PGu-BR;Ub{H%8Fqrsxduyo{Eum{kaU{{E|`4aS#L zeKJ9FB+@})uSiHgA_Bd1-AK5Wqyi%PjaLwA@5$!iC()5Ip!Y}AXu_Uo>E_oq-LDGNl#2v(TOB>djlAku??@r9@ zj7uvdz_=8`fKe5*?l6pSmGeHr@bTrR?tE~)1LE(*w;kohf#a9Hmgfy$3DIPpj4Lxz z8-8zB%_#}EIQZQ;R#6ORuZ#CIUXZ^GXDAq}VGb2ikfSX+q^WCkm7A^8)u#D5F->7l z>BLyGe=`>nR#ny`V|=vuQ5CcW;W_N5ONTR;X@4+dcl^b0wqJQYMZQ?*OMy6+D+|11 z8H|AQhWy)k`!-K9oP}t@>e!dKF@-*}=!X05EgUwsobOK=fVrey4p7@F9dl54yoohu z`kwbJo6Yvfu^l-X5~*eY5VV)p!bM^UNM0rCRpzhEWqF6^NQt%(uF`~NeWBJeTbnyW z&ig#l3hF3rNv~cH2;i#9dWUQ)q&G})C{fw|Gn%JrJW+zM4Rn&!0@WF1&HfYB{1qR| zh9Vxf`--5IQLqybe}RK=j{SltUtJ&`!Y6lOuvj$<lKw#XCJfEeL>(4`=xkWrqh-pmj!1|6jBFYamaSQh)mzxw`G3laz#kBK@sFlwz0Rr z=Jl=6UmGFKz|8JL+vfDkQEcl6^#~RJowdck;n zy`s8A*Y%w-D4ZIIUUq{en-UP>M?ZzVjA&uUG~{ZDNz>-T(zNE@caX9< z=8K@I%|Dq}iYHoQ@!;75t!HWZ4fBSBudQeJv%a;aG{RcL=-PY1z&S5Pq$%=Sl@mp0 zMP{pXI90ljqe(schLg;M?2OABEjSf6v`;G4H8xEt3m(ohp39y%{JVAsBnz^rSFTO( zDT`$_fYQadHx<~x;ZV3@rrW61m$=aLQExt3HFy6!s7VBI{!zIVgiO!q9KtQQV#L5< zZd0K3EUFi%!{r!M;2BX8>x|&lh|9Sz6F4i=TQPj0qnT9ar9mz-S(t147(-#sAvVpV z3GyJmIoV6x4EyT52@p_NEo-u*<_EMS(GRZJ9wfT8QczYC_Y=EsY}V=)tPnip>a%Ow zHK0FTVsNS4EzRsi36~PF&YrE`x1EokSI=f3JIv6WOZR1j<5}@`R!;EHuH&|P znx+6{=%p4;S16wIb-T-0QiK#ppxb7!GG??_*lQBfmy9G(X&VtU$<<;bCV3$H7+sk} zM&^{k(jvx+Imes!s8%4mPK>vfTwh3# zY8Cne^Tr39^e)!CGH(=x5n5ci~9;jH;=SV+?&BrE|a)7F|pvE{$V*A-PK54wSNa-5g&32`tC8|4jEt zuQ+9-g!9dY0AbdLPyp#9yzaDpRu|VYtm*;pJYhx;fqRC-Kl0HdOBCf`~}n@Ma?&Csuc47KOR&@JcGi$Keyc+*=p zRV?vw|GW%k3H`^GVcL>m=Zs%Tadq@Na<~cUE&*hOaJUOsm!%R(#;E~6?mF<|b${0gMJ4@oW}OLBw15t~gj zFOjb|Aw2Mg2WVD}=Lq5PzE?DHGpijH7ncQvQqOsog47Z2aVrsJed(#uyEryzgKz4sxgs1)kx*TVP8$c-sk%P=5yERzuQ}d6X^!op~)%M$rNTg zO6v*@;e*`xrk=un8iwbBY4yh&6KbP8Emf0dlzS02toaRlepK1gDp!qq);!&}hq5f! z8bn+u*uH-LwvOmfWACCrrz0Ve*u{I(GRw8a&oc(yT%neelAcCTGN?W&E*gRB%ZuO9*RL z(P*eWFE!3gP_7-lM48thwU`;cjHxxD8`9uN%|B0f_NF5KN5M$y#1iEXahaB%?(MNl zu~UfwWfVJAj7??wb?nq0dMJgK4wl-()Y3L~g_+Rl?g@pm#K@KHnqN7vPqnD0e*)b< zG{QE{r7_P`jf`_I{WAXeUN$idp-nN5BXGML=tmwS$?VGOVYqcz$ZtrT8#-?-C~liZ zP)8`zNjTZzpeG)S*s@=M*NlhY@iVqgVm|a^w+KZmW#V^hduVcFiGSMW9&iVGe>9xqP-l0W#cmw|xE&{svwd@=RCa$D zUX2(*5wX&~fKf1-q?Cqr!rSulmrnBlM!Ao#hVg49#Q#tJ{fGHh$;J}R2;1k;#G|tH z1o(_|+F)VTsQ2L4Yd}}vRNmb1*wg)4nH9%esFluvNod)+>_l$bXT>RJ%KsXi2*#|3 zm4(DmpY_?dI^Ut#fdnRy7`HZ*Hd?C4fzDg~yBE&@wtMsA+SU7si~Ba9-PfbCC*^tW z1E{SQ7zhp%2sOwjX!lP|NAYdM7Zt`DbcGa5=BgO-g-Kbb@Js{>17_1G1{$o!LMz%c z)9c?V#aP+L+6i-y!(WWmh-bZKip{($!pQ|2G5-;OD>%(UpY1N0S~4eEdWw-DW z7LyzEW8|XNoXi|t@11Af7}%?iRAK;g0|2l#kL&}0c>T*@!Mor907eQ&C8iXU z8qROZlaV;xOA51!5EpSui}GZ_&FX#%4m3b)D9ELg>EWjXAaJ0)d#2%P+v)}}2g|8v z3k7G3fVEO(!)#Oi(}tL^2Q&Dkjzd&_&cx?|7{6ego1)Da;3xvn&y7?G4PsI&c~&b0 z^RVnsfo%;uZjl4v)_c4}B&zwaDFHQvXYdAlWbVBcS7GWi=iSB;i4xI(dS5|du73Sx zG}YO*#49hLr?1qZA=<6&YKlu_XAcE1QNu^3sd8|Upa2H0!4`KP7xM|tm3a0BZU4)k?YTzd3mc2Fx(WW?E_E4iq2Abu> zQroMw?-`88P>#oDZt{rnR8ET)shWt&lE_~f=pa(o0tgC|*ii%?E6g|Ix$rSg4G`xOspH`gH2lB^}`enJiNSx2V3g7n!C%i=Qi7pU5Fg9(AcV1@~4 z_ji-OxOaq6up*?3tiHy3<$-tju6Pn_g+0bbludEa-Li5fb6JNJUX-}t)Do0y>;FUQ zb+@_m3+zciUY`9Z7%0V{#TGr1*kL1409RF!OSr*WTi_8jB^S?d`ZugPD;!aoqDKOG z8k%XhpEpyfV|W~M0wt~9k)oe@H-GQ-SqhV5{Wd}Op4DMeBArOKqP^NBDct9l!-Flc zt24<=l3wRVwo#AKD9W9eUQCM6M9-kpi)y$f=T*_$Ak?nhq$w(hX_VcH&TwAv>`2mx zpK1s!r!i`zVW%;yBcSly!;)RvRQE)gIqJAl<%wpWLz2T6!P9m5CC#T_eJz`++l4wU z1>1h4NbpQ&t5$lQSpmWEw8hdwy)CMWRu=24l8;Yoxa@2~S30G;Diyf6M97sBySOdu zM4fFPsBez~mwBl`lJf)#U|>5SDNIt-nq~^wR0{ps&6bMY1}gQl#lss-{<^lO!ibfpVa4%8@Eb9~HSz}o zGaq2%SKM}dp|kUbNP*Hyjn%h{%GcKrnT_jg;J6lhIvARwRyz?=S0Yrww|xqbh$0L=yvj{_k< zfY@x^7lz*=-IdgBhF((| zGWcN{R7&4mRuK-YAiiga+<@s+W_z#Y!Nrenp0GMdxvHZ2>UKv)y#fc zDoA(d`f?1J4W&=U2X-Hj^hFlgR0{${I!Vj+(p7`SP0ANRCrP#Fss|%s^aj#2XuJT4 zQG?!8YH->#z{b?}Gw4rzT6bB7FEjB@+0R)YRhR467PSNC7_&h3NI=SY9$&zLc7MP> zNsVj8UzvhiFzUsC&6;ow3ueA(vx&`1*`O;o09jD#Cn{g#Dd||u;7!Rpp3=zbm|rAy z=PR!8Af{GpPkfP>lm^Zb_Eq^bSdq`I=6`uYN(s3w>kEO+2#q*#)Y#90O67FRV|4Yh zJpv5o2C7i=rHTYY5gdfZSO%&(AaJ@L?Dop%YarC2gs#T9yu6-|F37`n7K~>eFg}tX ziLYS_vTV5E92m~gHzD3FqI=rsg7YY3Z+@n3emk(cV}R5}ftO(K-dZL@>iE>la*Pwf z|3?yx_tS`na`5O%8(8#TLM<|2B2Z+QZq6TN9) zJC5plKW|Y#k)cc#pz7BY5|{s@55neKZyoMvX>;x2SD+is>Myp8F7t2_cQNb%d|p-~ zwl*0rrB1LhgWJPHfRtQ|gUgQw5!gLE>o(fPi9O5$eT>WiJNfL)q}GD-=DEl$?|Yb5 zjr0;`h9`lk43$Qd0=oje)cPaaFE=w1WoHpm$&8Z=c{c+nv9#vTyl+vPs9Q0JaJ<+~ z;evdEk{1|3TL8xzc?9{Eeh5iYan#b-(Qr7_abH#{g`q~(*OM=JCdwA=`#z%eq?U|u zf+8N?AnU+H%v=u{{mT+4iS%Tz&+?lSv@L3md+(rCacM4b?#xidws%TduOd&`qg9x{ z6Un{%tF#h-?`wC}6`bnEA5DKlglh$_Qu?jfZJ_$w5#}u3zcC>7z)BG6keugWn#Z1E zqRfeEPnqGl^+ty}MH>CppukS#5LJzSPuW{Xq^m3br9oLmwX_rpj-eaD#E37w^kOXx zjRy0(;$beNg2zx*IM*RKs5g92tBRg8D^vhZ7NbyPyFg_7I)M=($3UVH93>A;8PxS0 zfrg9qzIjTO01SI-vBl6{U1Qmfs}psX?A0?OL1%4z@u4pZuO~V4v!=9WY#pZ1^mjA~ zp%LU94Ov9Don8vjc*L-|1j8PIa>ld}%xwlG*7eCcp+V!R5&^0gW#X*-(7UO7&|@&o z^#RyR@&a`;<`J~*gaCKbE&{ELB593$0`}VY3A?bg>QNjaJdIP6w!=kCNo6vJ;Qi`M zo$3WbPhP~Rlk1l{CIQ#wDB-BwFyhBo^KF>BycsW++=7PjVzkVu9?7VVq(V;^;(7rt zZ1F&A9GttZH-~5saPv3fFqSCx@`giGv+uUThq|O>Qakq(Ba<=p1R6Bc7cbXY6c{2M zKW;6L21l0Xjno$9w9~(iUZ=bGUf$s(9)mUB9edz6KNx()Cg(GyvS=5sQTeD0^FYwT1hw66l{fSRK5Bt<($ zKvJ&n(=5W85ykU&u*Yz?qf-Rs?B#;#DC9NT~ z?pZzsup2Fp*}TxhU^^Vbqrtf36ZINsqsc^A`N6(9N<;PneG|Ot;@`87lJt<5oyVRC^)Izd%@wBNnL8lU>YHbhw2CRG zGew>4!o8(YIpqTL-b-|QDMe~8f-Xc!>nQo1@RcB(xJv*U2>gkvhu@N*0Gu!ac|u_+ z(H`vQVvKw!`;Qf@#tuP+94<~;n$ji&VS6$RjL zIr>JHJ82cXsGh|4Wvdu}0oV^COiJLqKtk?CQ?IFr9tp4_6rV8KVK?h-QJ1KPn?W$EG9= zWTa6gXJPY4W5O6FThus*J0A2RK5gZ)G`2!r9cMZ46OQN!fnctSo#vMc&kzK{xHi&= z+k^)}FkJkoy`VX&ol;DG08K6()A6XvkFK9rBN^bO)T=YM>-&wJy0A~PT=ognc{rEn zaJKOFMlj+nfsnCJXM=2ghX(|QmH&LkA-NNtFyFn=?_TDroxn#KxP5KkeHx_^Q^n;V zF3Cykz%&#!^C>pdJw?UT`N&gauO(-E8H(f(bL$cfBWG%SXgRG&L3ug_Iw7|+JJb2s z@9B3)UD7#h;!ArhdGC`0oagWdzEr)bnKFhaWByjsXMJnJfilzRqIxoCv(k8?2)st+7H>FGouH?Tg za&qo5?gdK;$mS;DLNI+&e*QEwvlO!(7`8hcnMu8R27K|%pKd=n;_*Za?MCtI#Nwdc zhub6=%Qqa$w^plL*dzpH$CZ+a%Hq3yVRbJ`wpE0^j5%;oybLb5&zOu-w`l~~l0_vf zqCXB-5(}+Jb8+oHIAXQ6jSgnE;O2tcIVu)Ck*YFIJvU3<(~? zTs-9Rb)YpIu4P@f9N4x)8awx$fqek~$a5$GUf~{ggh!t=P9w717`t)!bzn&p-lws> z>qnX;lvs?NVv%Vt;6LJWGJv=ogP~Ef&Dfx>q-buzS@spOv6+o{KB5e9U*eB2x)m%l z4&>Z|#_?i^%&B&0K5r7Cd-U)$Ay(EDSgqGdHV{a%wNjOww|L_D*IwO36)rwC9~RMj zrk^;GR9bO41nE6-rukcM2Qu+YSA^aNdp8|wESb-AHQ5~5=!_GU^)G!(#*zn!?@v|O zpu4xxRxSKvZ%?IbOJ+=vW7Iz_Dap_S)H)?e@Uoq#gL?Z|vq@{_Q<7A~Iu zh|J+Rqt-JVj7@KciW)}BDJ$49{b-I^0#ZiMQHI*SO;_pi=5cCK-3>o#SdJRJEx}i* z@c*>#%?1 z=Ilun`znQ$f0n5Km|+ar>sKr+i;65zJuLlHf|wLxGVHR#CI~MaG+iQ(feaQoRQT&* zMJVQeWV3aA#s!G^s>_(5MzqVdj@Zd=zlv9X)9mZv!8`uNWHx5!rd}nW^hpX73Q9v^XppzSG*L+-<$emNc0F?P)zQUuIhhB z6bwj+YXQ=83dU>}y<&4@-(RM_vxLV;DI}DBBETZx;#Qm`X7|gv z11+d6+-CVpcCHqXor~zBET00DG7SRB!z+G)0*dkDwa&S4auQakA|5X7H`X0{G**ey zWmxV;s+UM&sPB_Xu%J?Dd7Ay1mb;+zwZ;C-Mm1ij^?P+FWxEL_y-8X$k%W8|D1VS< zJwEwpAfX89)}WN~IMkhAlkuQSD7zr;TVpwYqF_B71tW~DCt|s0KpSgb*MXX6`{%$K zgal9p69cb=TqQ*P7nCi9x#ffwEj=_4Ie}w!)yb9cK>4AJBco>8tXB4*TV_L^_SMe= z6kMk(jrv@jYq0y!`k5%CnD>b*VEd*8%i}%kK%{fM`ffl@%M5Ic^7o@CT=S@%Eix(C zfZx$7Y6rZYiwf>2hCGGW`FPwmh{5f-?;}vMV{(b30-+qxsVMLbT5;X3;tEGdV@af6 zZaASg!3dXK1aonX1jk}OO+e8nOCTk*NJlm+B#9%no)6ejhvlJ$R;336`B66niYJZB z^Zgi-u-km4sG1$4Du==BlgNSJ>rxvuBSDSIhsRChG&{@7NRpJ&h-G)D@$D-2MIcr) zT&gvFneg|Wtcq#eJ8&zh6@*-G(8U0#I^NNC{R+y=)Y{m-*<*#-9I{V!26)uo8 z^w107i+-QLyvRGpim%}0C+JHyM3jmsTw)|LP2*e&eho(M;05T}ehP~8zg6swZ#1m< z9@@WRe$eOON$c$&)9H8Q5bZGK0cGPTG@N;35};oJ9hSJ^d6gu*)6_<3T={(%aln31 z17%=ITk|U+p4S2dTkiBA9=uyFz&Q*F>P9XsZ@Z*F8u*K!H9$|Ih4p^h-S61p0c>-{ zKLHfi0fTL8#bLL*3brtpJK>4}w|~&X&%O8TsWd)s%Q|CmH{h z<6(e{1r<^Xo+=oA9pUbX(bw1Qy)0c~t$;!RW( zI*5Gn4JYGqN;+v!l3cQuAdyH58>Zf(86^Z3?3x6}c6}=I`u9S5mGGyZ(>*o!iO#<( z3+D+y2ln{>o{A({w&E24D!%-uRQ%s1_1}hy|1Byi{Ua4;|350u{y#xQKO1VQ-=`vi z#m4KW04m}!fpMc3RcDEo7bQP0c4gMhbbN(r09~~iXaP}ggo=;YNciVuOzzSKE|2eC z1yzc;~;YDc}Qzg?;&*Wf{f5Nel#t?Z^nl>x5#N3HxTRDSCVUO-7PT+8DLNH zv|d48s)}3UPm@1Noc4K#ElTPVP{RTiuFyxHAO##rl6b76f1$7MXmigiMYy~(?QS;926B#TjNZ!Ft9fT=1-Y=L3FZ|taw-2h>3$&M}D?;(*+ND@OY=tWP;CM1en} zpjBx&)QquIn5gnxo~S!zXHe6jTkh0dvIO#g402Xet!*?l5qy0PImAlJA#lA*Gh9YA zZ~3bY%Yyyg_t($jfN{C2{ktnsrmm`N3sFVewwK=%U3}{$CG6@R>I_~N!PRQXkI${o zYA)rKU0M$I^S9KV%Io%s-%Rt9N!pE|ox+@}@*ADo5WWc(EW~OItTI#7d9|z}VNp!C z4?T4ADltsz|5hAEtQyO|RAmk-(VR_A#EWXL$``t4u7|^9r+xp2YlBT;y7kB9xe4%Q z`15-4Z&dU@+1~g#J$KV1fK7V-t#7#3^z(l=vz2f59iOD*=5i(XB3i-0b*q>US?m$s zgmOHlmZDO2JBKd~Tl4Q4bu5SSbgGXyJ`{MuLwb0iFOKl@fpEbN;)5I%#A;psqlys%~!$7#EG>DD!tW zehSVY8em>2ITzD-Z53(pO??E%!8EQx|FLEar_No(s*S=Ip_clTIgl^ubuhysiAI}- zA(BXx(GY`apR(Jua2hI(2Giht4%Tm^b;5h&*=PNrW8=Q#d#X3L5AY2*wcz zDCjrI^9WykL8uT`OUoHR4lHJt(J&yJErWUZM!mMJn`)@#lX=+rwc2xRsq%C!+- zNV31vG8WL7V~0m+Q~@TI*o^@h>W-&RU#yv9i@MqCg0pacw(%c75u``|F45mzXfKQp%`#QLmlJP)jhOVw^3;oHlBAwP#Q^=XL;ki$wy2C9 z4f+eFJo7wNs7~C&6~@w+F9uE_T$~eF(C>xO~Vb^NPv?07Wk#D^pk5}8xuwXPwq4bte^QiS`GesA> zhHAWdE>K16O2{160bS!J?8QcXXEDSd&XQHvi|Z0x8lG&89t|j!xTd~c1jjeMu}FI2 z$V-wis2sFgzafW)^YTe*=f38`#Qxgzwx!}RQ@M}9M^=d zf@WiH#!3Y$D5|0DPu|4x3S%V((;pjN-(>+;-OZEpQ_NHsCZ?JfmrD(_@QI%$Zb+j# z(XPX5UMh#Ept?0u2(5X!_#`0yyk()i9M1(jTdtMXswP=s3_n-g7i`*2$CHB$$;|3J z1*H)7-cmx~QO7)@q+V?8HwOtN<^7x(Px!&G*5kL@axuZ59CYvNb6dNQjM~niv#m;> zBy{+2>V#*L+;eqZPo%)5%y3*vj9*RaPKFHbU2Q=L!e2l4bUjH7@YW5=e9Z%Ir1_ag zn^pcws?M2Nj<34VXXEl6%Yk}=J$}f*fU9T;0lt3M{~ne5Cv}$ycrMNF%`L+4Pif%j z(pn`&gZm{t90R0TymI!mp!mQ?ei1M^M4(KnM*$F%=?S6DM=fqrzzxY^7M; zQOoj-hUkOqct4$b&D4QriLhv4?5nzLJCev-F^!fVR{@JloF%s699V=$5cyk1*=vbd zITYJz1Bq$q&}n*)9e3qs6)}35j&Gj!=T&_tmIq`7$Rh=SW}=A$SfQ`@Ro)LPopg4b zR;oqka~Yc6D!R7RX&zR4IB~#u`Dzj8bls|9(I_2!k$XT1R)XufqHj)A1_{u!cMp@a zGgg3=$_7;+(6I45tjpz!V0jrU|F!6+(o!>{bMvMLl^!3u`N#Lie<+zqyw|gD10eFl zi1r^K@?S{g1aE0%Gn|3!={&XNtJS|Sa`V3#2`<7k*wRc={aTa6usup|(?z&u3a8nY z%d(!p_emqk6{`o|ln#?=>}OCJNufi3LAqBvc!O~-kK7nS+p72ZJ@*8l zrWoMIST%ARgvkK@_6@+uFMnYqA>{A}BLlEn3g0pSj7^xFwdDF2Ci# zh#qPn@Ikd&rSt(;I7AUHy5Jb*OfqtjGhcT=Y*39in9vJFi{dwN>5G%HdbKv{Pc>n zYa)${857}RiKc5u0V#V));Hm%We^BjKAy~5;b#a5C^`RFMPOn@9+j5ZLPPGnI(LhK z?#k0i8Yez zaVDeZ1z;mNFt#uB7q$l9;QLi2IW14QV{y0@UDr%IP>uGdS1OlB*<#`7DbgPUSIX^2 z>oJ_B6ZmYbUqyYiZX}HLNDkjU2Z_RX#AR|D6;JR{H$I00(;V8>_QxkR<*m!}xOTD5 zr#_(3*3Np9wWUuLX&l{0_^9ME$`HZDzmIU-DC9ZmwoRX=2 z!l+8$bds6lE5#P|PYPW|l4Bl>YA?}0%*f+Sv~CLJ^>pm5&s;GcJmTLGuigqaqI(*o z`I-!E3ZNu!R{1lhI%m8!hQh*t&Fy!ruheopY;i>0uClch_(!qGv=mKdD*o^&p@o~| z@c7k(IT{Y#b%`DkhFP2mPR2)3XFGZ#%4UZ0(52qEz`18Y1 z$gj_DSEfp*Pot;H@yAueWn&^Ub`_Z-7@MMPhHW8;4U{i(TRgMsaQw}ryA+oDe2qw= zCHywg@MbwX?(o4e0m zw!{)MJnFKR0+6?30V1Eu3|@IxN72i1@EYeIPSRnGLjJS=u4s-OPWMZ3^^4CJBHz>~LNBY7JK zM0@1q3YpglFM`>Id-4&`4G<)c!eXBw4mAZHgMDYn1YGP%7Hl`wqa*%gN=vb*SMS7&H5L_^v*FxUwxu zy;*pWq(;(wb&#kRbi#Fb5HoiSr~9(W3s5;B1HtZtD(&m!5_Yg=>=%(V?HNkaE;Hbr zIfH7$#+xoP@bQnO5DamTny2NfK1@Zz&`(p#1CtrAQWi#=)<*d)hsz#5QWiPV@t?f% z(;JU`qb$@GbepZ_=m>AD4$7adX}za&G9xYMEJLAg!@^4L!J|L5lT_cI!`LeP7A!{O zlnQ(^_`yL9OKxCCgfFMu4+xx`9AO^M%>#zTT#|fFa#)pmv83L!2pfbs_i{e{Y=rlS z1O!e@XEpm{i4D@O@kL8(E8AFyD&E!B41Sxz)^ory(-egJP2=akQ+W30tc6-kJm1QZ z0BVfg{rN6+a2ckRK%Uq92Pl}S41Ot?yTY8gcFhdZfQ`ilGUotljNk1kbnyPQQ*Y z=uB6oC&#c@EwNOdJb$xpEVY4fiM)i$S%{zQp*UK7xW?mns+-lQm-zvK?=)+w==aHr zy8bX{oTIj1srOcS{&QB-kg?7|*bMKSofK@w0cDz! zSC1@*8&0`QAmKxzMM5Mv~dCrZOvqN$TCMM&yV!kNUp&Cs=31Y(TGMKkpO<#M9r->TDSb zZFU%^nOB=l#%;p}sR#4o*Pg}pYq)f>QAVv%wTHp^d}QGy1!q)TsKg@4%F0w_+b_pc z=eVwd<*1Zff2nAn#JqXD6b%{o5zGzkG)81MyE-*xdaA6cxkeG!Ui6<}@PF6DfKvBACg~sP$vmp=*UgU%WqxAYgakzB zRzw(+9?Rsamgv;p%C&q>QwJE@4eLlb=l9CmV@*#gn?AyK!}jvuUCVaG#Oe_pWP4S~ zrz2@(ovE6zG7?`Y);K6CTvqm00d?+x>CV-U>CUs1hdzD~gcu?M=NV{yPP|>jtf;Ncm(x}B3^sz0NU-3hixlwfgfUl^vV6ixrD=WcZ&o2idr{aTiHegU^L%0ZIC>H~TQimJuVEu)1vLHkiKMu1 z;%rtk?-{eSG`}1N3bVy9rpFg=%y^z61h_J1vlbAHj);tq&tZ5GpQsGZHxAlzCnM#F zoK>K`g}R4QCaVJ5X?YVXWjIES=L(b>q$=V!6w9bz2PG=Z!c3Chc%-buoaZGFjqQM* zWF}7{c5xe`a%1YglGdS%WZoszN!Y&m&e{a~jLIM9@y{4$z+?Nyypf$!1h~?a@L*5d zN#4|EEn@iYwu){Kr%Em!pnBPEG1I@EareamMkXB{FqbL`n4QedK(}Q7NH7h`OG}POx^DtMYlE9AZV{%g=0)` zLh9PtmiQxQ^a#_ivL*jxZifJhreWlPfYQEYs1S}s)=1IeedDC9P!iOiaH7;sQH{1D zmg(2ORM%DrR)@FZdbr~oU;(S0zt@i+bxkoNX8TR*DbiiW4bX^80)954+Yd5D6>#_p z&&90`9WaPhT`7}YUEK6g--dRLCsNmkG3BdbT8>B%0X)gRxm!J%ARLxPe#76JV#Xps z9vg)%0pmqP&F#g4o|id{#hIG(4J9P=DLp7M1E&Iu=-<|abat_F-i4qZ4rHIB2FJEWpoIM+;^4I$l0+>@CoX_=sZ?~2Zj2aWq}th2KXJTvvw(r0AX z=45%;(DpckH8-f6t4W$|3?c@#*&4wb@TtbD zd!=X4z)RAb>k_pLch0nZ0j2b=PQmyiype~|H0zpzoT9KJ5d@izl*4d{!4 zO(;-i<`k+0Jshvt2Hf0Qc2DqpU}(T<_*W~pIFZ%Z+Lr0eWWi6Sf)0I6^)xsPfr2&> z70}Mdq(MMJr^NB){emj7c^P@crI@XJa-|Gc+XbdDcKtJc)3Lk~ygvq?MMKwJbMF(p zmTSA#uTIl1Fmhf&w!#tDaQq@AUO|H|q?&M)HcK%4q&jNJMBUc{@iB{=Eke`T5s5s6 zyQ3o{USCAd0k1335)(L2wV@I00ori(Z}m0l`3Y?(AsiUj+q_UzRoe_~rz+Kj6G1~5 z*YR1xz~w^1TtoWHSo?F_j~8vEt&n}`j*ssLO81>vTz+r#pV-+G~ z|M(h8NoS!%C_+~sahS2AMFaj}pGY1&Fm}oEhv!iacYAKX>bZ?tK2qK^-)ma);u@DV zY1C;X(HnZoiooNI_gG=qHjs45D)u>e_rB+6 zHnGQYpYU*+J*&KDu+rTY(NOj#ju@Y7R|tntQr`IpCN3v>a7r4fDmTc}HaZ|k(Yh@0qj5%3@bQYzCdC;2aO{9vBteTuN zGSAuI>3>m1C~bq{pWvmr)+$}nlx@%8pk?n<+L0}BWg5?WUsx8(om~!+5jV4uK63}+ zgSF>I^gec~wf5+E?bY>jqnfESUPi6BkF<*<4yU>2cKk*^W6dAj|XSo*4}bMtPJiVG{T;_U_`m2IK5f{jr3ddw7I z)GfFfA!=g7^^?oxWH>E*dKZrrwDussGuQxlQzwDH&pLQ5;VbMCh6#BVj{b#> zA*iP6hQSu$Xong9#YTL0`ogu0t*(OK;6hRvdp-`M)|g^S!ayd27DqZ^0OrqK zMgZl6%%hso$N3uEK~rj0{OxlE6rxzu!8NNb$w(6@nRBAngb2c@Xxw)PBQa*vP+?9C zPu$-NI_QG1^@-B8STHJLQBLFEn@qRQKuSmlADUVJVB;`MK%AF4fpyqLC4*s3JO(?Z z?@{8yGIobI_8lU+gJdA&>$mgur6`(m=N45MFT* zg&`~})zsC`bpS72y82OrbIPw@Ul&afAukM1q!cCpI^g^(Fj1{$Lg*O<(98}9D{tqE z$pcv-OhwVB+<}B!t{b}Z@;``Bho%dbIGnmX5ONkO2iym-qn}Jm8Gw zDZ7Y-AW?Z1cncn+t(sE+2auz82=bzrT_<^+6fAqEpDW+1XGY$pPIfIzggmOoWe(f5 zY}4xrvGeTz430T?D_!kXch}8wg;c*7()z_ zX-H`#)tpv>YsMJG1Ub#u^)d05 z(Uo*GsvuPwooh;G?``BW{=sG&G#%4L4Z1Gcp)U}R9zD0?%vV$_VjuT;tk<6e4opMi z1y*DsmeJQI+F3kj`c=;9WY_6uS6YsJ)d!k#I-@S_D6WS<6p+-87X4Xc>ex-zaXJ`` z@Js+aN^J|_+uRVxjB{wp3W?FyDsZ5hv(+$h+{A=|DDB=E!sedrLu46@0I9C&YT z@674+xGEUrNHpe*GA=RfJXnhrRjBNoUB$Ba>s}y1+LC9gDlfyTKezd85@_nfjh9{^ z0PxrVec<$T-D$5u{!Xjr6U#&#bQLaGVlhCc>B(&!ZedeWr{i)u9&A;pJ+>6_inIJE zy;_^9Cq%w2FU4*B>u5QWwK?y^t4}8V$Wqp%d?Uol*7(H1#%XveV}>y5l;gmXl-6ed z)@u7lcGH$N+&wkLg#lbH5j$~b2oB+I^i_JgX}MUM$!96JC_e9+&LxmGc)*<9LFW$; z>d+fQ;O5`2KO8^W*{S5);}aGyxmT=a>x6aY#Yy)QLc8*W-;1L)fo{AZXeI2)_L%h~ z7IdY4whLOsqE$AR+6=X58ZM*dZ#|#CmTs#)@s(lfm2zl6`8;P}QE=Uz#PbRHwyiAJ zIqta5Tny{Fl(b*n-zVu+BuV4O7A7X^MBfc3+MR*qU>~Y%xk(?Gciuz)D!AkXI=Vr$ zGikL~oy9al)ikrrU%yF0kP#Ds$@%0=Q6IWMr5IaS$-EG}oQ4Z%Zk)U>k@`q6zr4S~ z{5>AIE7_+06CcH2@%T6L_@DHz*^K?IJa$tbtlv%!r9LnLEZhYdw+jOL*SNd-UGD(i z<4CFfK$YAOM-@%tD(!?b3CEP;aY>QXBbD#6fC{!D6WK+OhmWOF#o46M6sR=$F0|P(hjGm0b8xvxp z5O){_KQR?1!jmYK_!~b9ta6xuZtZ{EMA|04jsw>2CLGukTe-nIIZ%OGfFQ4cfLf>I zZdANX=xTr4-188~*)F)u zIAY_Ye*0Kc>CdJcFkyOyxPd9n>ztqfEy*#l`Axrq;PP{29S z@ArBWs;>9W*e-vpIRUH``=mSpAnpJw1>iRF$C^|3HAuHvkAD-z>`J;yGqFR6?@NCy zmuApo%N~e+42dek;{$A@kg|nBJh%FV;!aaPN6ktCq=y2YSD2Tq>dw$}rx1(B{W_fu z6IUr!yr0q@vg=MJ23PzNlO@}_;Nn2xN&j_4Kl4P?z@iW6=cHx#kh#lia3FLa+)H{#|L7C@v zE)(=@nAdv-$IDk0XU_g{vSG5P;fd=LuV5ZKGcm15)YhYA}!az%nc#Q zHBt&b3mK9z6>Z9X+B?kWR6Ub^iYvc+c(}2arPRernM)10@CnB~H>8s_RmL4&AEGrX z7tefJg`+S@Uid9YfhrlnZLiI;fGyV!FIAI_u$u2$z6%xEuIGxqaUQzo=ASD7&wv3C zuatS)N(T{kAYG2;2(*-7Cuo3~0%BchQ&7|M^KV<|pp62UDyNndd3T*bHk>CBn@BL4 z0879=hf0Q+QrAyRGaE{a_V2E|m=5QAdS7;{t7wtxWI3aAWo#*%RGDoQGU_k$AD{J? zl&7&27Wz-?Em*eISpjB>(5B>t4g~o2ZU1YF)mqA)J!WCCNrFxjIK;Ye+LW59i5Qwm zvMbq0o)yhaZ8Tnxn>c@`93q%nRu77B?VB)uf?=VIXpv%G>F+1%!8QwJN8Pec?;inygLB9qeeHi%A^$fT|CK`40t|Ja;2P~{T$s8- zp)nXZxPq3v2;>J%{v~^%pm3A~$X?`;Mi!%>8e@ZW$;|Y*s^{f6r#}Tm7yn#g-X=O? z`XhWHI#{4ETdELf9(Zygp1Z$A3OtPVxUhbzOBj=_E8v`$fQwM6Z;h_ zGN^$1ltW3kYL^TBxcG9%>C93k{MLm%Xh5x+|QnW3nLb zym#OfBy@eqa9wRpdW6H+i#rBh&{H?9P^tPp(?;yyWI`Jc$}b5^-K9#{I-m!#a|FX$Mx@6ghgFM~>)#1oDk{Pi2=k;zJ;Z^zYphI)3v9#l8EuAFxcDusO*TF zgJ>y_Ih;9|h~eG$d?fH9hJ5H?zr{?@8aWU=%&m(z%5zjPO!RTg8EIc&RCzX(C~DN| zJG%zq6SciO6SkyJ*_B_`G(omG?gH!TL(r5Kqa&+3D~SNiAK>~aDB-`xQ1rGxJJdYH zshgL+YFLE_mm6tX5n3qeKu-Vo&Y@<+X~Grl#*2D;g2IY;#lDL2d8x7qZd1mVszu&$ zt+WLTxg_{p5OqPZp}2uz%Y4+FVc;pki3By#75Yi$l0JIPoI=P$74_yzzy;#X_us(L zP*13A!^^2;i)g8L{&_PW1;q>@XTbYWl8!lSA&##5vT&^_clr$DLUGX~P3vM3tIkQs ztd?nnmBIFwqZC~~cB<`G#j1ez@xoO}>Y`oKisBO0cC;JSQ;LEp0cEh$m4ys8$nzJk z_dbc2$KLpA(p9P%wBWydB%{$X-JiCy0Y+oXO1)pMwLZqLEH3r+H-FGkqOigK^(nkE zJW!zS2wotFZY8J8XMGK)yEOBNEJ*Bnl>If5yV8UFgXMr37VtF z4KrI$zX3m7`{62m3594*=`E*`C0FQwWr}3Zp&d}u#gUG)ef=>9O&uu_%MM~~RV`HOy z4ZoJ1p9SBjyFsKyflDJ@8?|3W3!Su#xdRfjfyIcGRR#@BYu}uEW(xIlb)A19sj0wN zQvWEdsvyD;$SCy)^Rg+hj=vTY=H&?E1ckxi&HmlSLB_SOk9XF(Q*;l0Nh2|feGRuTy)TN%Q7pn%Io%{p$Rx7zse!Re zp6%W;rJND$Xv<%EE>pI!`4L3WUkD4x__tOTP+%shq=@H49?qg@UDKg*?85!{gNg0MTv zT$-trY6t>>Q4jS~@DU!+XY8Ah;i4}9%DDGCOqIMhKc=C<7pP~<&;XM|T&&>khco2j zSmItc2S;+KS3C?sU@YF)Z9h;6_TDZ8=%j*UPql^nO50Nr8wU5=ny*%NXJ{cXi(}p( zBq$27cltElpa#-D<=%J&dYz-+u+wYMe4P;h77CFD0jw3*dhu)2k!w(lO?m`)jpTME z<<&1)4`zBC-=kfE@wiwa%u#~wXGk6%4=3VON?i#Qo~)0#w_b8q$sq*lAQjEWN=Q7! zJUx(U?6S40j#xR=3Avu4Y^N&UNebFieVg$94UXrH!{4W~VXkX_k0y-l^SCw2HW@OkXA+ zypFiK_xDngM_WzcMzjp*kuY}=*Oilces$TQ%R4zlD^d|w z?ylVWd+vQJu|!+}^hXKH8pf+41OC+7)k&ukG^`wjs+o(_*EI@Fhn=RE7kfG!+W;aW zdgI>6YAp6|o8+(a=5~9QlF8w}(L{`;bf>meR)LJGbWZ7uwMOs1Ins!&W&MzqKED~H zjQ-A3NdwK|o?O7{sAxRMG#i}GxkZsqJ4gm&g3kWP=Db8q#)qYsQPoYtQo20t*#4gT^e#a>vL#*&IySuSNW81(&<0ATIc7;uTY~g<4_TzZSiR zlGt3ajY~X7lm$8?S0^NT}Jy)0Z*Q>H~U$u)Iwk zOG}LiZaUPN8#El7!Jh7rIqAYio0rNv^iR!PboeixHrZ`;iI>*dix47{`3_KDU4HLL zb51K4NBU!q61o${*C48EgJ<%2BG|WvsE3ZzceN9CDBV4&%!4XWMBIPWT)f1~#!x{K zH)+*%42T%-<0K&>b|)konD35ZoUYQy$Bqz%Uv{jJhEJ9@szG#gDgX1O;p1F@TP`4m zf3@85A7c1FTVm_~5<}R6+CRkbTm2f?w0F{Z7tXZQk&Tuv>O%2j*GvFLj0$Rk5*7f- zNk~}TvS_tQLgI^7o6xVODO{XNO74`B5Uu{n5Fqn|40a!7C1o%~FTqU?+OUwl;gxSM z?e+5L@+!jvZ!B34o)iQW8RSCnT?i9ekNf=Dy_#FrU%6 z=?3tTo29H1EO3lfS<&GEE#$j(kEUU~qt@3fwnz<=x4+Z~fQY~W$=%l?00*=XM&wg4 z;g6#xY*)(gH!Tc)(?WGsa$5bR;EdHCgShiYLS?D66L*6V4yYU{#Mg+k%o zN+kt?2WNZY0#9Qz&|<Z-uaDn_}re%>_CMAbB#+twd!ALh|GdxCHgp zdyP(dHeED>TsdNe1Y1S4iN-CHobK->;x$ol3nQlE0D)pZakJ>)%xv#C8bwy zJ?K60Kru!vfk&dRb7`7g+zXo#vu)h<8dD|?l_D0uc~|{(UZsUv>R*oGTVBYgqS>tH zGq3lV0X-D*ko)mTjopX$^4%GxekStG3-31SolP!I`|tqbw~I1GKBB-jT5TrPbSKS$ zp(^OdPmjk9Gw*)1?&Z{1UpR~1d#JV3Qr6H(5x}ziZ0D$L>~g!VH;;?0&J_+;n8VBv z#?PS!^e|nGFSn@7JjY6_hw)J7zl3C zKHLA;+S(DQ1E*z3b)MzY`Qx>lL^UQyN=Vs66aPtyk#K6&<*XAG&_ha_(L;=R=RLDt zix$t;ao9&3eII@}EPIktAVt9;)xo<@+a5n*EYu8%tkFKx0R;s>LK&2!745s7!{Bsg!vpA)M-Ri@4WPm} zWyysKNR)YS=-$qG`_nl4gbu+p#y}-|vUJcY+%hk)#V?27m2!TBx7eGj!w2;6kVRaH zQ5*^3s{3@3&Hu-AK&?w~S7cnOGhaM6G zde|9*JYA%bj}ajn-vabB;Kr&CY7*`q>-@RM9ab02u`j;7*?XOyD9AV;K6sd?>B0!{`qjeuu<|)KN2!bDs57 z&FG_W9N)9opEVEK#&=%ok=nMGI$ubag^-j@0qXH3B%*0+-3;sfR*Q6wCv?b}UkyKK zOFDxu9Lq|~Rsay8v;7KcG=ffV8%1XuRc@Q8xo3X`?dIii+6;+V8Q&r-^-+V`#0{4)FlJT)FPcHGK2;JCq~IcO8U;pdenZf% zLtjeH!Cig_8c~`Rs7&%qdDL0Uh`0Pl0>iq`R0{( zKcR;p;M;;V+Oz%nY9W?Fmv^x72Q6-c3gReTF6&vB+>X4{%fnfrzF0@EoEQTE{WlLa+Tkx6Wn{!9AjtAqa_WK$R}ZW^pf^N zjqGD)!JKB1YWR|QzFIV({pF2@I92oc+jZRz-aA){E1^h1q{wccF0 zdUiHrlf4lrMf<|MDI0#_>GEfS0pH@&#k=GBl9ydSG~Av<*9%Xiy*C&CYA}O~#%qIY zz5L65-_p;!;i(ik$N218(6+U9kfB=iH@Y33v(y#)rYIj;@eoAT`1>}vW7lAC`^oO^ zUt)I#URv|h98A!Lvavenadropbi0T7lFvn7{!Z+1NWS4=V z1>^&CmQ*Cegls=378L zBTxMLfS95QtJE)nn<#k%^wR*xV$W5jJD)>h2_>WZZe|Epdf3G%f(Y?iR*S6K7V)x)Z z-De=9%7%*@wW;!9TW}hhp-=bu%-#2yg;WRXIrwwSS}PqI@1PJ4=@L1t#>nSBm1^6o zaqR>_yAZ+~1C6=&jvqb?CmcY*x7$L0+uS*I9lzx3*mHf8!ZtZ|7eyk__mm(LaKE#_ zKolYfu$aA0lZcn74<7nzU}9E^l;$0J4o)doH8*)m?8BVe$^}PjZOd(oESG6u^NZ$x z7?o{Q_%k0CpH5yCdNl`-3UY({;uPG4$kN!q-XWa#sRi$g-?JKS z7CLDM)jK`iD`Giy>q~GQe9x$D@VvxvhBG4}_`(AZ?g9wm5Fmu1TaQUHfm2B9JDmbJ zH*We6*aLM!J~%g*41RFiHY%Uiuyla4Oj+0WYv1rXmuey;x zES~TeV^qC70H~9b>HGAu53TYOHN=d*PE;DR*{a(HVw~dU*`1@8x0+XH6ssUh=0}hinyX^OCEy=3%Wj^RXtXa|v8j zqXo!OXjhWY)fb%k%S_w`O`7K&IBEeW(%3g~KUa|#+$y@bcK9j|V^#S(81QU`GO_57 zk$=fz!g!#R2U(W)`Fu>VrAiHgy^5)PX(RTUK1-i@COdRVXckhw^_qz%E9MYiCAiJi zPl{0y`DK@FUM{eQU9DwpZSPa&-W{#7)IQ9M;)-3_ILv_3kO#x2#BnPqw|=#U=PaKu zMP^a=z1ei$y>tc!s5eF}#!Wy@q%En1r%pCniyq-;&ez|4H$s2azA%S-5>GX|_%v z(W!t7_ZUYpibVT(js%xqyeva<6rh0JuUL?4hpW4-Q}ulR9xmA+`YWg&Pi*WH508Ej zVZQy4upEc#szHjTX2o7)VroPctQl$FvkD8{`!9CQX03tLMy8N1WZlFbi;uC_BipE` zMwrZfWSt@84%7{h5f$(Idee|6kMH2RJSt(@Zi{{#tHhklQl%)~_6SX32W}!A%U{O~ z3p_%}mWdU4<$fRD`!>&PRiUby-wQt+(e4&KUM8Qw{ktzdv*GLPY3JTC&qw{kEtv>yj#r>uu5A+XQCAl4 zgCSp~8`lU>LGq<0)g1>O^3o^Z)v40I3pd<<)e_%jlGN5QsQz#mX*xEpVTjv3?!6;%))?2?idM>-Ohlb zVd48_lz^~rcfli$VQ_-~3h}@jyP_9E@xA;2f@T1Y1P&6J1r;IZO^q4MhC-x}<_7+h1kA&>V6Vo@%X-i>r7VctSkU7#L26t#lQU9keexToAb z1<+TZ!5(nFd~dnoi&l^a4xqu_s;o^lZk@Dz;d&hJK2LUAN({K3+Gac>e4<~Dy)uE)kCP3Co8@Gs<^-n@(gWe9*M@XK(46P z$AtS)Fm$~+8DTQ%w0s;^1HyYi8uY{7rCd*p@N7Ji`XWlDci6s$J0*<+|SFB zy$hVER~}z7!}+BJI+FR1HhI%qE8^3mKK;VBPfB(?B5Vwm&TUmHre$7-_9;$-J~(Z< z>G>{2lc7QzgSWaEqpHLuRS3SkW@afC4!QcBMOpHp3%cAc zn!01)JV&o{^Y4!ZX3)j9^SS8>Dt$cIROyMI`bp+g2G~%l#<(+Ekc-S?eR6bHC{_l3 z=@b~V8RGX7y7j1Ty=Z>M51r{DW2I`bUNcAj0E{~JFztru`j<#E6&iMKj@){R)c{zX z8^>%nUY(rboD#-nF zq1fX&1hP?njZCnZQ8?%5q|6F(zzgUC^C6k~*F)D_{9L(cgy&JJ)iToQPK<5yM(5?y zX^g~$=%CxonxjI4g1yzLgR-e`(T&I3L4$klsPz{r&&T+s!*oKQGJ++}_%#d4ht1g& z%&_UDe6#DZ%?U!<@Wmy>xStVMkz33%7W|Pu)Si)%ao`Gc;qGBL3ygBbp(SLIGj@SD zqHJvFzhry^_A}#%bfLt>O2%cd4<|mUG#z>9n8uY~sfbh|q;eAU$ z{AVioKRe$4QbAuwX|{tAOW2XCe(x2=&zk1f^*fd^GEONBtl4A`p)q;1aAxV! z9UBRylP!ycPoE@?-sZi3QbEla8)-WgqaJ>vjOjtF=~R!mdUvn2z1B0{J%SdJXW;T{ zqxL+3(7XO2?LuJ}eqaIz%e{%F5N(24i`A_yoCG*ZKpC`0!!s z;nEO<@X3lLX!X=anLlhmu?H99=qM&ovr`NT$eb~Nlb1Q@FxB?@8z~Gf&`y3W)u0&+CxLa6kFGmwpJb%zI(PC z>f{$9&x#Ar#e-kixDET;AIwT7ATu+lJKgR}fY16Uzd1EshtxHA-a0fCs$Gcx!Y8^m zabX{j^=B~FSl>H3u3(gjUjYETo*1?bnjYb|w+*!P3F|RkD$19&4L|8y6~_V9AJ(_POlG+|C#B_629yAOFywi( zb+vO?*kccNo5P^4_A1NsL8zht3AJ6wJF+kM&ZtIt#X2E_8J6jZTo}UgBF)w*lS7UD+Mtt6==T3f&&xT5bK#!Y;hQ5S$%~WPs!ZIilXc0^QY!w`AEt{4ICk zwI5G``Wn?h1B7w5e=O_^GzSNm7qr>w`@~vJQw6oYR-{s)(DkMy-AQ#o32Dnb1(c7N z1*WYZ7_1(20VUjnli?dogFa*vZ5CB$>BoO;ljU<8dhcbkcC_8{exLbV$7XG{--CNG zuaYbQIXFo)@w7agLwpE9nw2#_HG3TWQt-rjul$SB*WT}8@fs&ea@=Cd_XPLbc7%Ui zflb&3bVCnVY!JQSJcPZV)MA&c6j~@hXgP#oByN!tJz80`2(Er!0vW2KsY}V18#}%M z?!dy+WtY(`e)CC}nMxxQ7Zl8K7k(eBPWF5HoPEqh(IJ$mv%TF9UW^-I4y?{Gjs}z@ zk|q>YlA+i3btjPZ!>V^joK%miP!9&>PVx-;wmEtCri6CVXjRBsZ5?ER{y6 zK`M`w*46H#isDFcS*$H?sZ<{aS8M81q=*StUZYmHH9yv-RY+|VvWUp9=ZYJ63Fl2R zbMvSWOj!Dq4+Can#H21vK zd#5!RJ=HRgfX!v}?5>A0nd-Rh%jyQZ`GKXN(E&qKD9k383EJ2|bBNj)8$Lu^Vw`G2 zVj_`8?`5kkcx}#jzxKflG7F$yZrJ-9a?-e22Awwh_no~c?(HFB%`n5Wyv`o}Y09xP zq^|NtW&Uedd^Z0HzpkkbA3nieOG`hWKjF)p@l9Dyh@xftgI{L`E%-U0cBkcVirz(f zZhy5aDw#$)^`DGy?gx$cNyc)2GrmELTZBN|feE6m2`H;~Ti^2eHgxTk_twrnB|Rq785acFxI@`yH%`OhIE6*RJBgj%dcRMBk4$ZDJ5sMNuy85m7~+ei!U6!*r=1 zFF_F^--j#vMsJFfgM$j>Q~Y88hEU(tNxbQG2HLXyP~ya{0Lig0|5F#dr>}L37#v*C z(>44`0c@*f15ZLA6ZaiJZVFafsiX&m`hq3U*ZTQd-w8O6Su^#Z;+e4xh`TnIjlRz- z!b+b7hkQA)V7Fd~)V#x1ZQ|v7QeH5CNk>vG;UAq5-auzWRn{(T+#dME_}ij1&T(06 z7rA}EjprsMjdjZX)$x1%Xmp-2v`y9-z5JnBI>vI(ayPNlG~Um#eg?IOv6Q<;JGuwl zy2XpGSKe+di;7z5&>bbIbw@t3)vk`?E7eD~z{pplQ`Zcb!$QuJA-M0 z&iwK=p~arCvVC5y8|c}2WJ)tusUlR^(riv>#$IOz++=#MK69?$4jF|jWWlUk?tg^b zLml`GWw2G3NZx2mbWlwKBP!09D?*CFl4o*`WArDR>w8Y{wmG5O#&C+u?K;nM=Zw})G`(Mg%!1dSy_U=+jYq!6gmET2 z^L&;Kv@%3KO1tb$jd4%BV7~6++cW_^yx_NFT0e?{bQkO z)&r^})B!3$ZnBhe2Cr)dPnqsUkcP$ALcV~-}8hMLx0i|g{94~plvANWM zwYU$5wAQ=j7Y?#Aw2rxAC3O{cRYh2~U}z$*KtTkT+eb}Tm!XM}zStC_R|^iH|Hq_q{G9isIN z*ctXZ5)n zoexyy2LVTPfIm-9pU}P6yU2IvUP8IS-;vhI_ViI6cgEZ4$hDYCl)EN7dXVA?4enTPKB(rFd@XC}V_@!-uOXm8=1%*#HQrxJpy94A~T+pkQ^-3+eH`ZX_>CfL4r^-C-khQLcM!@1IX;r zOyjo{wP7xWGMdR@>}Ff{0&%%ns%sY8$-+)3ytaCk$oG(d1`6J~easKv&imYpp3yp_ zqP;aZmi3TN`>Q_RG2uYsq;-T3yQ)AqQly9P%==oiXRiECsI5`DQLSs)#*)u8vxks# zb8+uk&O~0s%08L)#A&3Z>~k&~v4=Hi0ng^bGP?5N>6XnKy$(kHmKd?3SudB6VWCMo zm)$P#3I-r}7DhiuFK1eL`7{Vd>gr{Mf3Pt!EW*2I2QX65)A>>!iV-(kf*%IP&=v?H zdXOEpa+(^c--`zsyt?t%!KnBU9}sy(I~-J)Iwf(HIUFb62ZTAn5x$q zw7h;_N*-NeR^2EVFNE&xkK%t|^}IaU%|FR}HN#o==B-(ra|76UiFE*lajEv%bDtPG zSuZ*g^FZ|%v&<=v?<k1_wgO(aNif^zrpL~yOk&N ze`pB9;z;9U+^tcw=Xd03dVVt9`!l>QPzb&6uV)(mA%XvtY54D)?*B)4osomO7AAO3 z^iVIk74xpz>S@E15yRul`|oP+m`oy?+2l{?}yh-$%UG^t{GxYr1?)^mYfD`qB|3+6zGq;IZDnlbuQ( z`5~UGFpvwNrM3DB?CV#yXf=KS@Ve+GnlibaV8;ENgQ(;>w8Su@PJOt)!Ry{Nn1EOF z!)7SM4P0%n?6tqu0j1q~YL-@Uy91?Ya3I%(2m_!X_xt|s7qGjelli%p-!P569eg5- zC8X2NE~aE1hDGao<>%2ZKIU7?%NmLv5lHIsT{b7uOnH3NSBjr!#m-<^9Rc8VeL&TS zk24aINyZYI(WGH%iKuLvg!#!WfuK>#tc$XAP6r zJ3nDiKEh&7AbW`3OOl1XQ1fdjQWV(g3N>?MihX>d?CHc9q}=2%&_H zE{pVD9)5?ADaZ)!U6t}sRg4v$65Yu3EH(YEwUX3HaA1p;~?m_N+7?uxcDgpguc?o{_yyQs`+etAlvZ9WLgw_ zR0IPiyhjC$)=)JTa+HbCgB8L(#W5;>z}H%aDQ|h)JY?|Fg{<@ zYIwkAN6Dtt?WHZnWwc=%@S7Am89cgHv5Q7QK*8H>EG9{#JR&jWEE6HfhZKNqg}@*< zCFO)R7tTtk>B%M0yY^Qo4s(r?aMz_M7C5IoVqd4^4lYo!o?xS#BLGY$y6svPne4&< z#sg}xul(GL1dE8TgkSvUN~dQI(e#_|bZt<-1Ic_>KM z`Bq6iCNPx!Qk?J=ydcoJXsJ}ini_ArN3gF;uUU=Li9)G4mtHncnowkcER$_lfA9L3 z7wuHZXKnE#!k6*Qnh=SEo@~nXN1^^XVa)TVVs~TC~RRogew@7nE4*( z&@IQi$%4o{Lt^tP;&_BW{9QEoUD&A{#BSnF!KtPxc0v%qW`+3}>UL7!N-Lc7av6qk=^YVlC8VqX- z%?iDQmKNF^x{EJ2Tku^slba-|R30nUUx+TBG%K2)jn-@}DaPp;a8;`Vz4{~D>^)FH zD5jRf*IBzfk@Q%f>Vt+rDb*izAZb_7Q5CUasRGdJ4xseN(T|=OSG*UP`d3h7w6-0SEt`xR0!&(BUx-qHc0)Fwq`(NP z14K-%A({Sf1_l}ojQJ5^%^X%}AwF>21vEskl7w3hwTii1Bp-&F z=DmzU*R&v&i~UZeW2AR2H2^!z2vRtqhYuDINPc0A)z7Z5i0b-Kv!K8b!co4A2f*v% zE4Vqu(A2cyh#FBtq(oazI-|LeDyL=Rf4+B~Ju6^aH_F&6Zud%TX zN?gEI80zgqEUXR4;vIX9O;oDdjd*OH=ip_nC zP4%j>dk4@S3Bc>b*Xc7G%xpy$^G1eiFizkDyxEK=Gn~z*-ETDGo|CefMAO%M*U{R5 z4a1*bO$}`%kA(+92>dyC$THrCk$mKsFpeaXWlW7J<<6{4<4;b?K0RQeMmSVdOP@49 zHJvSqB|plVsdbg;(bD%73yz*&|whs}u z$H43N`?L(5$ZFH)B?_jKR_Y{1*R>M`y?yqd1`YepVH7HMNtp7DqPJ9&%e^|7DMFI> zl-y@ie0D`+G55|8%AK#oK2WgvOglcB3we|+$1wTnhZVS39ClI*u@(c8tWG}#EZK#KK6K0F$FgJ-%=EOU-W_#ge|57Q+4j0pX3)^rF61Q6WmiL$3pi!fax!w`fn`tV0=J|*wZ_Au`bcXbwqQAU&CLRoYYtg_ zTrc`cvFsh4%|dbW9h`zD(|kGZLQ@mG>Or?5Rq-Xi&=XH@dA30GJ}e7G7QLR-NL*n_ zWf)U4xaB)YE#~S9itZStartG`?TUqH36c~EDN12fy-HSHWSNkJHJ%@k``=F0?-!cj zmX%2@5ti-*n2fGF--L39IPvS7P+luON|v~=DSDF(-PpNtrYN}Rd=0Wfph}4e+RJ1w z`}8K1)lIY2p+dip3bq?*;>->{mF^%m)YA|Y9e8>id^C97|JfN)OJbn2l5fzdOwg!z-G+QLs8iVgwr!VVuY$D-eN?C_mdMCD662iGX#OaM=Ub>kZVF@QS6J11 zh3VrF@}&bV`;6BMQGkTd507+?G7y(ml3=8377Ff(hW`2K6&&<|864|r_;&4I|CW&Y zAf@8JPgDN=#GH-Ze@3rE1`n@+&D{c@fs7sM5xW4Fil($rB{Wl=MUu*sAX-Kuh?K&x z`t;+|Ny5d~xWejGmaQKasTjmQwVy{nY%9fyNd+KlA^)&FDZrtIB<5X%zrp_YuI?@r@>{sFv&6|A;5EP%bsJD2XbZz)@*_xC%?z zf<55TVYx*p8O&Sl{iG7V$c3H8GENaqS~w4yB~-=*f`%a!L;l_F3jJdNWWT-;(>9j~ zUf#{CmSUmQkEI~=#Xwij_j8`ax~a1ph=pG5@48eVK7K8%X7ZMr%zMuS8uq)`;zVlo zBvtgM)&g4s>curNu}U??qegk^-da+Rdurtx-)YKaQu_JmawYf%!8=E&Dms|&-=KzQ z!7eM6PBskmkiJ_uR8oXA;Uz&~7kYdS13yCe%xf~@5Bz5I*BWrzekpmxZSxWVd%Z2D z31A#)9ztRAQi>?zUAc{^@o|Wi-CtY2NKRWP4xo_xxT8bbK_H)eB%VZIEZUU`+5<~k zrh%5y$?uyYl_n4Eetn*w+n$8!Q6KGoqcln7N|_dBPHda7{r*}zf4GZYA6OcTHW78P zA-!D_17kWQE+?B#eI{vB(y6IPgP=q8sdAq%cwpzQNF)4(uS<~0ViK`--;jlq@PoJ$ zL%DS;MeA^rTWJHt(Y?pQprg)v=d_Z5qs$Gy-;M<6bJIo$;eC~5Qp(=awJR3kPay1+ zPfhrIvW36UUP!aocFqIviwzR}k5ml^biK<5?p!FFcU(L zI;Es%;Kwg`#Ohiq_Ts;sN;8k_9ad@Pakp3GM!;L?n1g!`vX_ltT$=So^Ysv7`~bf) zLC47i!Bzl3nzTH*0Z0=kcxGQ5l;w)Sm@oTs{Un&7ovd#<0BKr>Xhc?CgFM70e_sCd zfR=~Ac%Up(T>eDSWWHhvHxRKIB3YRp<$jrHt*SWb1a;ENaXRoL3MrQ36YnW2?b6r} zSsRI#)FvY|D^-KZ-|6hHF=jZ4>VdSXjGS9ox18Zy9I4{eQ9b@=3!CmTIEy=*E^s*{ z`$ijVf$xW8xxb~JCk~kWmZnnQ)g_>_qXo?b^^}fw$O2Z^O+2Z;YTxB$JH-Vn@tNe* zEA_@Y+E?pPm)tDF@iFQfSH19+T6X0vLfkQfomN*W8P1N2!JGyUxRA3-UhdKlmHenb z^aUVIjW0ee4uw7~d}Eo*qa88u-uEiZA1}o%=y*I=f2&!Kc842BBqo}o!OxFpw0Msb z)vltwJUBNW=N>&H>Se>u_+2@?;p?d4|AwyvRmi>KtT{@eAAzCGq-qEf4|m4I_UW;u z1N}R`E|s;tW)!&?m5$@qaeef5O-O zSr$`>6t~#;CyI-SWO()5@;4G#j2KQcfhIskVTSzmPNIHOBVTJL9+;Q1z9A^uMIg0@nQhgvl`a+ z5vlZEsFkf`jZopy^E#mDy$YD3vGLOz)zb(JZBuo2DZW{YJ>0ipf-eP-#Sefip50Vw zV@6^7ug#NJ{f%EYF^FHs-0qDE@aum4Z1(%qfc^cOUc45>uE8HHUKR%?hWiIY0nOTJ@s3_ zUC(3lm+1ho=gSoi%*Oi*Or#KZGc~={x^P| zl&=cFultpm-pw!=n&ZS6LI+=yt7db$y%xHZp8NaYW1!o&B6J!cN1(L2r)vhMzGv z!)3ft`ShpsL2@Uk_FwN^`!8wyCm;R)1HUeIAEPFI(RZNVvkuwAw<=-hxAZNB*u1X6 z#9((`MpVCq5EV}ly*pPaE6CCOjs*V*X(Tcr~J zcmVwBwX|YxA;n;DWQqFysuTfv;!9`Q<)j#_*gM}yvXf1p4R5N zJNC)?!b=WHAQKGa1POKu1mtl-8Ue%GBovuK)k$LqGEm-?QYYPzbgTi|$vWlQZ|?BN z@D;j6x1_9w>?CwV5BgXu?Y;wtD>AmSX`SpliqRTLQfN6G5QQHVY#{GpWsN8qB45HY zz!n*Stx;WDr%$fW;jlu6_wy=D2`NS=9dn%aA7#n{yQ65|*`g)ME_&)cZa9RTSP7Xx&1OXB)<|YoEuz$V+br9 zhqq~MN31%sk8t>&GfG1lJ2kVUeM}^z-9t%0Grg(}R;eyLOnm!L=6Gr=upx!U2n?$HJSWub~ z_L0f(j3hxL%MX1e7aloUA3VY&$Mw49B#(v6kaT)KuQ%R()jL-Io?+t1VF9!J(K!zl zlNR+P#?me@FJo!*S1wzpQU_Vx5lVcm@JW*m#UeeGp0x`dr7Zs!S-mgGgYUhn$Zj1h z>;Dk{U}~nc{7pdo*_3_2Ey#+Vr{&0u3eg*zcP>yf6Cuuml7eHNnmV6ABi)kp-_eXj zsQuF3`gx`;$b)_w0y(7~I_R)RBBUb!kQBoDtFTr#j$x*7mqchpPrffj$OAG{J}&ZYhhqG51xuGZhDh-_ zvO5}tNsP43O=b*al@gaE24(u_QDs^40#jWpipI16d5~*~K1e%q=@g>0|GG2(l=hwYB0 zs;l)|&4L=UPT5t_pAB^nj#{QKv8PnqRIsOa7%qGfwJ*r3I$za`YM}Dwdl`032s$W1 z52JqVAq8h(xf@~+K5bQ2Zg2XX1@P)P3>pTCN@++l;DI5Y?rq;nn5^qPwiI{z!ttNbv^omxpuDP7{oU5IM$B%TLI_gI~ zT(A6pMw#BR_>;E)F8QzV>;6k3{}+!OXZtVwI(UHbiJ!FzX#!OZNz?NpI0;v8LxXKa zuZBf31~G*}Gex$Y)mySe#@-M6IUz5-?{}9KPN*e-_$*_LFff7Z!eY#g=f_Q!q5$x9 zMjja{#9x}c|G?MXU){FsHT7G3$K=2V(S-zABE~QR0dbg&!lSt#L7|W<+#gB_hv~5K z$#4ECp>2k_{{wq2T(cyzd`7(lo`NO*IhdkxC~<-BV@NL^;l;l_(oe8zXVblI~iTOM>K?Q;@S^_o-+0m2HKgXF6S$iQ9Pn?MAVZP z_&<6hA+=ddO@EH;kwMmqDBqeg9?py0mu(zTl0W{fD3xkdw63%SA1bw&edAg2{Yq*` zT`P@QYWkLM8k5h2MoQ0S)uWDf{UsQfHT*QjmYeupgesR*)B#$THuYj&5X&?Jvr^St z{3|mt*rah}fXG|ZIcIa6%N9z>&*kI{SD zqxZ!EK{AJFK5&?}c`{54qK{I4b2Jch*~i3t&=9Yu*`9ZFw@mfH&soa+{aaC}PUja_ z2O-|kCt*nPjU2cZfM17b+?b}I1GxmPdnqf#JZ90|YLYh2qVkkgihrK$C#6iPNxh8F z?-l4+pYo;j2FCrQ3b|j`CYZR)-mEYYD(64LaP}rzYm%pMW!u_1suUNuK@h)h$u-rA6T`Zg5i3r-g zjwR%d3z-i30yLNZuE}=WL#1c#Or5@#;A_f4 zt#*{U{plK#9zq=}9C#G`HGG|o-oIBrVXfjNfoqEAeQB_^pYDn&t7G+@hS7xs$z_Qt zHn}u0*IRM8`kHVRhI}jxE)I)72SKX+STv=x44^hi2pMx=iMFU-h>IJNY>D(NDN3== zaRB%_77pr1LjYg*Io+mz)v@FDmT%m#W4-MxeKg}vR32;t9aI3qNdOLHKp6817bu^Q zvNV=yItZc^$ry{pw8)!J^_0n5aPhAUOmfImEH56V;@8vuPO=X_O?WpT)K-8sHiRx~ zILT;39zi2m1_Q#`jEYQD$24Vy+}FwL)S6-UFwGHNh-9w-1rqUPNA$u<=hBy@!;B?B zp9~E(&dquAJu=KJV=1VU)DJ5W3iu&wgvH921W<_ZAj0&@ARdWK{<*zhEf6m!jQeH5 zYq~GWw=o>IV~;AhS&tg~pGAcUGu{Ym_~voWR_v!UhNOPPAQ# z9JV6WC5c9520G@Lz1TGOrp1lyGk|R33)(%_3p)Z=KO~8VZ%~6xl>#>|HrhZPO;dez zlzDc#uM1W?0Tb$QpDS)VoXWpCOip@82}@GYO_J~&@POE-{mSbD-w4@`njLmVx%n7$ z-^Z{{AIy8L&7*!D_JUrgNk6topMEelR#H{`e@MHl zs5-YTTfh+9-QC^Y3GPmC2yVe0f&?eHySux)ySuwvf_v^FM{C!)r_QcwZL!*FyzxM1 zF#j?8cO2Wb*v#TJ&T{z8jTR$y&_1z%^?EeL5|(LMCd^eUyAk~EuICN;C|u|hSZfql zi~vj>I&D8IRi}xZ$S1nPPtEq3KsECvb;t3l1G0jZ1x4|o^ZZ^@B+`1wJd>9SMcr@- zn)1Vl`WoWpJVnl?6Rs&u=@ZSpNG{1~tGITl@i|X8|ea{!}d4=V#Pc?}>P<)9AN~6%(lpYiA{vMo1Y+XOLDl7D3E^2RGly>9l4LRra{oUAN|jTD(3NR=iU}83$IbBCnWEo2Y(7VHF;`-@B$TS2Ym&V z)}X{3w~1afj#?0Ie3$d#yr0EB)7@QTJqK0e9k0Uz;B|ToXSf%Hi$Jds0KCprBK2-N z&V;DITECY09j{xk4v_%hb;6CmBIB59zP|QD6xULqVoa{Hcpa>a8oCg?KHT39mJFAr zw2w|28@IA_N}*_hd&E9GHfNGYvb1(AdBQw4Md<;z97>nxKg9O@8aDv}0@oNy*Bg(p zRoagdG6+RLFWoTgRo1TnjY9N{MDDZP9-3MXq|zb74js93AQ-;+DOocU?g=09$F?=k zYW#;tK8#r1i*HR zK#=L(iKTSw*olrr{nqLLY-eP|fLLEh+(Lv>OZ7mAHCSP{#&To`4~0SbI{hL4A>XAN z0J*>9BXAZ!QR9R1(E|lSngIqBPeQgcnmx?0)08JN#UG63Kmx#8-I91+3n<2UgJk6JAlK3+MXg(dgJaSINbH?C&IuJg1~7Uh4)(H;R=Fdy9ef@O@c>bOBy(;$q6fBgPY0}A+)wMqb{@C<<1@7t#dAABZv0%l#_?G=sVm=2)Km7$V`Y(neOaQtI7&l{nBV*niruZx^Dnr zn+3iBw7O6n;X@q5d0DkYX|1qqXjSf;WRr=4SF&ucnuh_t)I0v3EcbHo}UX7 zS6`O9m^NpTpguRH6k0OX)GtVJ&do(K_2}-G_`2~C z25dbyunOJ4GtqA3&aXVaaJ`N98 zd7euvqr=_=bxmBQ$>w_RrhRLrPeiKmSOh^GbZJl)87+5xC;{rcicO69$$E3zM#00M z4CWT$J)Nd5gFyDDFoMdUe`|HDbGkKAQ%1fiTu2(V>gv1nUtx!w0X4g73rP#W?P=Kw zN-Bqay5Y2*pU$}JMYBIFs#~y;2>XlT)t}^X>wuwX>}WP@fs3yhKv&rHE&J>!s*dQ( z709A&lUyT@sxQUBY6kTtxD9%^^r*r;Zc?J(LAlsJ^yz2FY7P95$9Kka{zX^~8&ql# zQ<68%eaQ&3P0|~4Pp}oG6Om8ktvwyHK6wZx&ENpg>TGYWY3m0*A1WoRbYUrt!qy+> zMZaQr(CRu^cM2wGdJ7tZX%C5s1-_(ysL$xG`?;p8lGX02jjtfjP_i0FY&oa@J${DNZ6>dRlWI_@&25P(*9?0hMSMMATX*__H{Ct-K6 zXElp)kxuOVyet9=*{$Ua3I*4;KHT^y#2fp{eZptG2u!RX z&4k@b?fZpB@uV_0Es(5{P)VXD;;M^;zSdbstgP$Qwbj>OO~UU-z>#cv|MdviNLrqz z9gyztS55xRa>RdFF#*u&zRZeYcCebCu^*h(VdZUsx6&zl)x}UT=98ky%|sBP4Gm;E z&(?veQxKt%QPr_Zj9Gnv*9_zxij)&lu3?%Zm<7i%e5@{pFD@w)3S;UkfhID21!CoA zhF&LUs&1`9`|jj*(e9Dyanas-Ke4N71JLOpoPd%7ITgTxii8B1)PF_u*en?srD#Q* z8qB5G*9@3Ed@k&(OLU7!`qoX%e)CC$cZ4s!u{ok_%b9>(WikCbQBp)cnzX7o zum1ObZcH`4BQ|aHK+KYeu^Mh3Rrv@zdx2eDQA(N}%-l6CJ2XS17-ikcD6R zI#8!6kdchE*(d030WW&mc+IUUm*}=C$1~qx5Lb3Uy?j1tKVS(t##Oy%By?%FP#Agv z_L&jO(0t~V(&rFy`i>>(4p!QtTgjD3(Eqo;l-jDSCWY+%a>~G)pR1ZY*$NK=uAxMt z95Fe?E;FCR6DQI?nmP!#5kl>Og(>LvgX+pnL%8a!ov@y(?#g6bE~v1Xh@-C1xyPzC z!-N8chQ7%v5fQ$|t?^u;tKjFEYYLx10N7|l?MbS=I?>a)$fjP9-}kl9De9oJtFEdS zIqirj5xv5sVJ?;pbc^%hwCBBxGY(q-OZT{yo>Sa4%@JA<1g&%Pakd&*@j@*)IA?PT ztF6Svi@+%(tcFB`e6c?QBH`KVz8eBNO?8_RgaCBANa7dV(Q?i)0)dV~w&YHv49^Y) zw({c4nM{MTLDe1NB;eYFu=Sl#7rUamU8r7pd{2fskF(sVJJH#dm(oS;=suSk|DoC5 zmASL^l(YY%qJA5)KwYW1>&T>BK_VTXcvb!D_tN$ZV;j&RU++~nE5Qqxk!R9o0kR-J z5l|7~cbzVKGG%A|>v`M+d$NgY=YHU({dlKLd_v<-ba_H{gz2kGs2>p~+SJ;4MC>twYKVC|Sr9-u|#5xskgg+jY zNZLsAA94pc^C#X^?q!n1*#b&8opf%jMN-!k?N+{y7rSdQa}6dRm6UR+DQ(8sHJZ8i z+41jdkCElaxBYB(J#r&Ro3@=42HRK!JO*t4&^AfrYc~M_L;MQ4{GmPf%j8n7DNGuD zPpeNy`3~-qmcM9phmHun`=A2ZyS-teQb|JQT-N2R_O(e9UrO0O7Lks2UQy$XO%=;f`$9I)HD@JksrQ>>$8dFh`+4HI?5eYD1UC1EUg!3? zOD179(2Q2ZCZk^~k{-=V1oWN>Qo&Pl{1sMkKy8%i0XZI!ko|ON75dIfQnVLW) zpgD}1q!a^9VZQj^k}@@E6%@A))-8(Q^;?0FVUfVp|0gN=TVxFkT=Z$^79N}LFFY>* zZyP+3YVF<1Kwq;!x>)*_O&TvDE1(oq!55M0lhlAk$4B`V!2J$atPY`o=EsMC6)g=8KznRnUb(8`rt!P8wZ=AO!*1IL8Bcb*flo z^lpG%z06c!6T@#kE@9-w#k^ad(mVQ4Gz_03GvTS!S3M=9$-X0bU`SNE~lNnmzfdOF&0y6TGYbCH4+aV~X$hFyXZ7aQ~ zCh;3^984xrW+EHt=mw0^d3HR9r876L>}_*4UpMbjehPqw1Rja>k)Of2E1PFV$ z>EP^{J`JsUL%Ql_Trc#r4aL(NH>%2>uKy=4qeO_neU}}3f6^!Jewm5npX|z~a(inO z&ZeE;YH>X$Auds6!6G^|SoxHWau8A?;DhZug+x$a2PU>u+pnLCu0`VThMAk`oq4O) z?pqP~r?$$V#jzd;A;m?XYy>CKWxXGce4%BLyQVgaA>5n`y6_!q zF+Mbe^nBNPu_#BqlR2Gs&|HMkPrQ${&(xuxY`)?W2T7E#b?|HG9gBqCjep423GY?* za%OJ-^6~5U-W_G_^IKXE5<&Er)d@=wdp(5>is4r(E?iP#LTqGX(g_654a~~}%RvmHtvcv?;twF+%G+fo zykIi9Li=i(`&<)o=+u)?`wLD2M>@krEZHt5HT3hXR0KL~$5s=E+7#0hhcR#QFT_Gn z5Lz*ci=vn0b;EdQg=33pC5>FM4rw73Eh!FUx8qnYwFTn1hb$BQ+De+kI2irH0yo`Q zaQD1QTb^(^Bug}1&$z^xhhM7*XCeVs9nZ*J7@t>1*D-M$%+V_K#J6@)b=2ck(Y+iO zSk)ZfzDF~$TX!XcLFg}yqKnA)+y>45;>6(ai0!>Z7VuLpSPv4ur&N*WLJfCHDd*@T z(sf5Ap-%~Ijbzz2AF;E4Z7`6SmK`)kSm5X~+pNEo@9uWZQg3HwR`NG1nelDpw$?l@ zUasNgn&P#v$X|_AJsrv);^1kmYI-kkG+8a~6=m=C!r^Rs-BTe$6SnU^;ITB}{Alm7 zF|UF5;WngIU#I^{jZF(xyAjK!WV24+S8F#7Px(Pdif_j$ROO4XT7spp)q0Dmrw!KQ zm|F>5@V{`2hK9?x|2HcX|Glc>U!Dp7^X%;Mr|CMD`BKz$++d-Y(X=WsOiK;tPDe}q zn{za9%Zvq}qMzM)!JNcZUUZ_DcfH#n+yea$0GPw&H_TCU@CTUVC3^RJ$Nyq}{=3ig z?(S)NsAUr7yD%TT9tBZ;D)e3%ox&6SMRulnHzugVo_kfNc<1;O<36ksQ6pjESQJn`Dz zDm&ceE~3ktx$(^BRFzg`UZvVdB?FtWN6NX1Nmqf?~ z(goDCjTx-K(3U)gZi4|~Iez}QhKiGJCBh`xR(;uNhZgzCxYJqyUfoEN?F$vZ@HL{2 zzL_HUXak$P*?O!c9oakYtg+|dpy@qa=+(ki_0ziFtF*L%8--t;>zH*@%3k>q&QR`J z)&Es{!JPkqo9QW8V9L2Zmcls^6Y_x z@fRu=zV=<20k;FeC*ri-WO4k5tgOlFv2|ZBMSW=eA^|k!=ylZPLNi^P>&>Ypudt;F zk)~+YRP#gfucv(8u3NFVY0BG_FqseAMShPsj1FM0nfT_t zYkOMAh+c;8vdtMd;P^}M!L>eujnP-WH4YLv{lURj zEFcK+TY!rSXX0!+$dh9AORM%HnQkWPC__ko0iJ;Q+0S4r1w-ll^AZmi_8RjMoy_s2 zpy>(IosIAwX@BB7jy{q*nu~R_Sgnx>EbA2&7f)(KK7wUO62nN#6Xl7gG;q5wlU!=d zcILTR9#r@y-5{n8O{R+9A{`L%x`~kZ50E}`Tz+$dxJF$jp4GIseK`&Vn?T(X?pjj= z@Xpj-zJASmg7gJ!+7STWITv`IhbjbT(g9B_hv=X|jKz;WpQ%m?AP ze9$IoLBp>S%}ab&6-ebc=gnz+ClS7!$z-ZYiK0aIGPv4tOdpsvc!)uG^+KH<44a^_5}zuTJkj)LDwHSKIw>2I#*><^MQ9zhlq*i3uAp?HL}W;ppvi z9$>P7tQ0l*PN(trtR%2Z*AIazpo5&DJDB-o9p1Or{I(UOu@a8ul_Xne_gWpGB_$yq zwp?HrhB-SDl=AqOtUR29>rQpZyv_i$T5w%*9r6wCf3ksL1m_zv zQAQM5>VaFj>W`kRD?KZvf{E-jfg0{O@duCq%P#zyUN|kOi9@~^ikg4T2x-ifyK4Ju zCaDWe9v#v$i_l#|bo=0*{L7Vv$2x~iuUwaZn~{s}nO)S0D^7`(zO^xPf*xvr;V$kJ}Ym%^*o7O7*+T z%@6sLZnqo*ib9pil;1FBXe_=ca2X&iNB(76$^+7JqV;=WX^mcECJ=2+9yWU1jsq*g zG+H3Kan%>`YySnl<_)C}PYUz^>C;;7l;Lqno&$n?vz*h+Y5tRGPY?}7`hk|DHFc-? zn0ZHFRVLul@}TEIT9+(oGcZ7VM$lH-O!R|Zwj}a+%e?X&7*(b^UO5qvo4`0lVJ z0gR42_WHq|seJpl_6%3FAuGA&nsLgA49C>SmV)IdX|%~yV@WAE335OLgF)7m>YO|{ z6TcXv9i*8p z@blEN)ARBRR=XJ){Y$K>OiVGEW+QILo3-KkRXC3m$f!+8=y*9yxuM7|KG0VQ8xpU< zx(V#Bl|QtwD?emOVcgo7p?BJvg){jL#B*y{xl4!T8^Xh6Njg%o1ut%A}9ZenuTZrvLM_oweS7r|tgr0R4ZW?Id#gHx8Mx5Fe9l9Qr7_)I<4R z@;qR2Eh`z#Zs(u{;c#LJw_qo)>QU3U;0y5_y`UDIe+k%3nQ$My<wVy zb!=^Zahu@!bvSr!JITlHv4a74zNiM|<0t{)59IUp=G(U!`EnQ$zoZJ*bwvN6Ypxh# zx}SD{#X6)FYY8i&7A5nzBJ3;b($SM^SI^_MRj(R}ODaDYWYJR<$M5NrgrsH)z=R(+ zXCMj7SfgpWxb1^05|Jka!6Aszm?MsW6bSWGM8VQ)nABjI;GYrMn-@(XnExLGhl|4dImi|nzcxXA{Bo6O_Xw?VzDoeJ_b z{&{dbKR#RfT&VcW-S)KB=FRPr*$qslu@j~-OF4#L1}yn>uNaD|7s{xZ@Ay&n4uY&7nZV6EBw8?Lf|RHy4^ ziKh>1mTr|rWpf=>yE}hDM@39IWon09Td$idrvm)*FKp*)Z3HE>MV$$^!KMVp!`QAj z6ZVX<@2j##{SW?5ZB}<$7Qz&p&I(#s=9(10=t$Og_pu3r@Krc!eMVMGL8OP#UShz+i6=B$)3|~b6%%uw(_DhziT#1BX&y>) z+iKYj4!4bOyzU*1SDDn3?9V(qZdYqbqYT)TUEoo(sWv0;bL*-SrhAzFlaOuePXx=d zFp}4#Z?WR({S}v@2h*QbMO4rlH51Or`CYA5Zl0LsxUQ0L912m(lVja8n6BUwPJ~#> zUd#hm3V!an2d?y^DdDizA4cUq$RB*IyE~EegRQTXF?L-WvX%-vxOcUn2(VIKZV#SJ z4n^*Cr!TiwgQnGQWr_=1dYR&Z^cZLvmL>cJlKna-I#bXtQ0j)L+{nVEfpf7|^SMz( z1ikNQ0WUq?KvO%*rX`WNEz7LMaquDJlrfV_-R+^#zTS?!@a@M5id}#AOQncG{Y`tn zaJ@rzqC<-lF+{!b8ai;;Fw_wT8)&DyEJoot4iS}qT&Zr{F?$%vXw_j}Pd&vHFf}Y44zN#dgK;Lf=#!{fTm{g$kDQ&tuM0uxdIS9)I zen7KzUHgsq-LczsYdXYF<$Em60PSJ`667ud5dsqAf9m>te7NA2^HD}Er2?vFZy8rI zI^kgsFU!)u!BR;psX_&ttR%2)2#${G zys}HY?JaKZPQO?!^n%nflkepZFKU~7V%IPfzM|*%;+JVOG58Em*7Z`|UnLzod}diV zi@eMFkfCgJnq7S^Qp+mez{}vnj}G!Psgpy?KbW434tEOJUzG_I6;hatU!cB~Zo1Fpooo zDlQ~e?67yA|C(%(9?hJYTR>H4hO-HP6@Uh$Ul}0%)byY%0O<#&W|VB@uE5Z~p$ref zn>IOIFR|qlZTZtS!+BzHj5cs=I?h(1eQV}zJBCu?BUm;yQyIJ$T`G(PK3C+n9ai9= zF%3&fKijyfX2S|~`^F;t^NGH z*56ml>Id)$Hzkx$B}*Jmn#9Gt6pzX_3KjfTVe8}3NqSQvR_qnhC)$d`9C>41LgT%p z55sF`LV^3`RV7=gqM79aCTPEpp%6I`n_)pEW1QQpL8-DGc;%~eF|7@s2)CN^8)tNR zUj^4L-TDpjBA0ysUV{8-G-tgpXd*0lL%WAc9N)q4BCjW%tN4(LWb<>e9Bc1Lrcsd< zwtR(Ykq%(D?4z;=JlFSM1``7o44JG$3Ov#(frH^^1^s4Tk%i7POYF((?~EM-RFUc8 zoR!o!G6Rl4WkoF@0Ap97$j}V62VgyYxaC*s?oC+lcTd>KDJ*-_wGPe`iiUhKb=Rle zs0#YQo(fvcd!@e@z%+(uHp5>h`|U&gqEy2!bT~m^5I|Q0OxR+iF4E`L+q*CT2H@!I zZD)(E&yGl!h`$%|lHtm>>CvkT8^ekR!kSH{DKCyf94KyB6^@9BS2@%G=?x_^1e?*GWvkys%+ zH4t7A@g?~18&bRRz0!Js$CgGirff5U_z*Jy)`p=c0c*n(8H3Ug;hTH9fQmOd3t5oy z&ha0AIQH1&f{*?4Y#m^}{m=G>0br91jxnaUbY+`yyAHxpORuht3qY;wsp&}q`L-nR zTdh-iLDBmBuGZ<_Oaj!pYpI21hrg(GHHfvCfh|A6-#!X0F(+Sx5I|9kWLR@g{P{HC z6@IRS!~0&~`DJpQarZ-my^DmT+xs!cLH|0SvL4j~_e2-UvSk&pRq>Wv_?H4tfSL|- zZBg;ntsSUkTpbZXHXP!-=4HTE1iVt~`dns4_WTeiyi5?RyvuXfz(~Wc6qU~Xt&de7 zhk*$lh~VT^jnbr5^D_ajaU{N3C5xBtAq-Ik9C{N~kYJ;r{BKR^EjLX9C zyVm6U8mG8E)n-rfm~fPkH3$ju#(x;o#}8oZEKxm~ezpf6sr3N2x)CdL=$DewFt}*e z=@i=(8|$_&i1CdT*R(w?rdjAH9j;K$n|cKu*@bwnl|erzAfIV` z^B}CcmP{XG-A0g`d|O$BkIBuwJ$JMP=5+P)RT`mCk?uEWGlx zxmqMHJ!c=2l2E|RFdzr z;-;zB`g_-HL!f3$Wn1&yx?Z`-j)wNmD9A}M3 zr0IPd%A7M)%I?Q=w$DumP{G!T!42otm^bXgnbKYZkkd8y9@!M1X1-u96T4n>26B@< zrTio&fc;eXI%VmP4-VfX^p$?XN|aURvcUJaxo%}l<&ZSkpxZHUJK zJ5!H3TN=R?d2GwfVf*kioQ2-T&R?4l**0i)GAK&pGXI`O zYyvQwpAhzg7p=&9=g+A+pu&ygQ#%@A0;*GuVnI%Mo8SI$dBU`d#XTMHU;dwC>;5SP z|NX4{o`NW*zf-Uue-XrjZ{gI<)TtOM@H?k|K$*9ozG1AD-pHE~U5-XWR9wzYWUA$H zHBI$IDp7%*i6x5Am=L;S>UQdDFXYEv+l%)UOlCg7wS?7wuIg{M2`9d=2V9_Y%iO$f zJ@m}H*9~H6r;GxEeP`>gvOs|pLhvz}JgqZ{R-}(x1{?rvUA~f<1Awh#T-V&;EVK)D zO#jW+63b*0MzCYRLmfP97~TC zJgU#a!-PAG2tMdPPn?TJA2Nt?EC!2$w=kH@PvL8r! z=jv02UFs%7lM;1=`hiF;9R?B^5iWl4lw6wZMP!a@)zEiya0I+OYv;HlbLEFlQymtq znta07O!M~s`gE*=@spQtyR}tj7@H?xkGT3_8l}jm5OG>=DyiX{D4R`n8$XaIJ8iIz z^r&@WP7}vkb+?^(b*_0!y(Q$-5cJ}dV1UOU+0e;%crM+$mu&MMxBMCH557ge^se{rXY> zE9Xl-Y3WU8wqRtH9Xs?xqZDs-LXLh`@xr{?JqBdd5;k_=A_~TP$!!N3mmT-l6>kp7X`(Z zthZg#I$Akb4s+{JE+4?LBt=;x_EHY)9TSLJ=M&Hu7fU$c?DB70#|-TXfkS!VauqF! zP00eT2~2Key(bh)nN=wjEYs&oWKSCuXaLpjdW!2MSWcP%oIE%t#1!u5nZqu$iS-mM z_n6&fj&JHXW+BM{*!?b-dlM5eUaO4=iuRAH>tuV8p_OH~y#l9;mj=Jb@=K8$KHrPa zA_CwthHq7S*HZ6nU6&vZtb6=l*gBva3hGsvTpWKvBnpMXyw3o(Zaw_f9Pex$w@sVhU)Z{S09$umvp=?{ z3$KO90=t3E#obl?+rj_F)+tSE zISpOqhfjs8P~ye*@+1Sc!O2Zn08=l4Vuwo*2rlC~sN zUziW4CX#JDaEA;>FVu~9n}6MjXgK&o*2~%278Lz;C*nUBn*cxI-&f`S{ZfS0U&FqV z?+Jg+u3f74yS62a*;98v$ofo#b8Ev3%SWT#URy1LQAiSLMyromYz}ngx*_Av*!-Uj zWO$Z)V)_}!6TEDz>%$nuU}O7=G|;iZEqdzgB<}i~?#q<}SNGdD`7W>DGB%%i@89fN zW;&BGfg+HArbxuHfPlUTGr+24I*-LXt7@m;!XgEr*EJ4*L{>7{`8#VkMNWl<&!w<7B19ySA>DX6P8d19npIc>_J;5c)z} zbm72=*;6iW5`==-=}icD0)Engx)TTj#Yx#i$c(O1swJ-07-9V-euZ&o8e=cK zyc&mC?la3B8C5f(aUX6Nn4LEyO=lN>;|hhLtTzw2A+3x%D%lSPk-A*m0xN@$<607v z5LtSCzD+c&oZKPreh0nhE-k?Cc)pr~>LQ}4OQq?tG{ZEdW-YgGb5*;BJx*CQ`Q!t% z0-=}1gdy*aM&OogvU%5vrh{&(BkR0p_?p)H!!o8b-eW(d*A`DdDboov!UI;C+>3lT zbFP}pYPIqBp0pD-Xw3FUC5o=biFi@$R}(5mdb|k9kI?YW-;2L^ju;zTOd8`Iwy-2F zqvbw*OvqgNVzSFt++$?~ZW^Q7LqUtC2n4|uE7mhL=YJl~42z}sRr>F^3ZcM;>= zNp0v3Z&HnkfB9Kv;GcPodEr(xD`Q7jTw1e+``F@0Ue>wmMV~?2zcW08gZ27V&O63X zt@Zd?xZSo03{YR6g#}NRmE{K_fg7-ibxhY8J;xAm>i{|%M`Lvrw*e|sDSXOmo=S`G z&D}UeN3K@9AY+lThzIo|5Dp#fLGbfpf=X}{OO56E8IsGeN=8Q%Lo?+}Vp9wZ@jB8B z?Lwi>g31CjT5+1%3OR9u$`U_%^?2(>6LPT)-J6tyVXSSwPowt2a+%eKUjW0yc@jZt z6<~N&l*x0QUDKE17UKe{7<_~??7o!u$EH-gnD9q}-F_d!|A?>XDKN>uRpr1n$=`!j zLxbD8Q6YAh*)t(B3y}&2ebx)c&af+lPgfk}tz$w!ufIY{c_t3G66sNlD3HGEQRmNh zP$N=nX9@`pXs~aJ)BrmXh;j~IALWEwWPUo8>=37f6mU^%{wev3 zB7XKXzHp>#GLt1&gm-qTrfJYVt6Kl(R;d-iMvGK~SIcF6qw~q?-TFqnw|#S@_36}0 z&4!(YVq3!oBJMH`J;TV2w6yYQK0?DA74BK4O%07fQn~BAz*S$(Nq-RJVMyNB!KBnSVq*EKncZO983)=N!9# zPQ`ye0{*E9&`4H{5C!W^n(f*h|dBD8mNo?rbpqH>Y3IpE2*?LjhtA<3Q0AaLf#poSu9|e z^*q?t37aLKPeF50VOEJ6r?hYriWyBz4=yc#Zap?c(vCcmv>TWX2=!@(NpOX$#=nd6 z4wa8*wn70PM~aR(0xM%&OHDK$GXj@lw3M6}@WxL>;impDeW0qn2s;c z#nH-VhjqOHb2GF&3k*hC3VThA(~e^P3_sx8#1I^>_c>E~Kfb!45+s%hot*DGvMUtQ zIc1P}s=C58>df_rBNRa64m8{yeNL6U_OvtxZos^(gB~6?Jf{(ui$fM8AF<|pl=3u zqJZThfx~HH*o#bzK(?_%%AL*Zr6fNVeCpPe-XLEMtB(SWn{14?HaBkk2UOe>WaZ_j zxY?dFzS#Oqu9)UAdK?u5o~3!-be5uv{bMJM_{-1cT#WD#;#mT~ba>l2Cab95M>I`@ zc@(xHtviAqE`EVj+LsLCwsM2jtsgM-9Au*Y8veR6R7v`1Nc2h~BybpU(08|~byO=Z zJ9QcTmHwC!?A7GBO8n|Zs)Jsi|4XGTKpXz2~Mp6oU;;*GnMV3;amv{6}+pfcDwx1SaD(5-aq12#VN6nMR zH7S0`N3=ROc`In{Za*c}@EbRd^U&EhF;{$b01o2aRo9XxpI?6*|B4S&VjO)gj<0x2 zILW_Pb#0yD>Ca-6$mQHF9B?KOu=3YrT=|fiXh#&8@I4xkjEf13R>-J#x!C7}o+?q9 z6F>Q|d(fRyNS2dGAYVyrKd+6J0nHOg@C;oT;yzhot>2PvlAxlQH95YUp2{olrsuO| z>-KP$>3cF#jCN1zF&m1|{!YfVg{3OjAM#UK?HZGqo>rS9#_; z%Um+F=d90&&|Mnp+dZDCpw=X8csd3po~^%D{LsO!1kY;W+@Z2TpZK0fUhs)q$&hWu zPly!-P1fhzkpeYRrMMCCGlDT}c#-^>=YdD(Qqog~`OW9_!^zG6dJYWFPNDGUS-XD( z<3CNr|7z9Y|H|5h)WxZdFk>S&M`b8?MQ1U%b-eU@Ahef{PMP0MLks@IiS612AGBA$ zT7X@50-OcE=1xo!Fcz6&o4u9J|Dh-2bqYZ`3h+1J&#`v4|2bJyy+7L2$-PY2Oz8k5GtUo z5ABRbZAOzLtEe*V`!%Fec+^BCj#rVbzA~|McFB$+$?o;ZQ+4t4919HzA>g}btshH9 zwn_sugysQL@!la|`>oC#h;S+qpgN^TCjwNvFWHCnbu=nnfiixA%!_d)kh?(-N$*}K^ zY1++i)y@zZ-uYd%Bbmf+eR<-!;mU%wol5j+cMlF1?N@p*}z3Ca;TE~ShqUrJLfFTd#L0t zT6TQe^}Z+kSM0+SKstq5WEi;X0(k;RC!LDv4Js;YWVN#awTPXWf@I6WKwtprq+bA9 znQa|bqEsLHb7oQNU~l3PIu`X|nqMM^iGt={Lg0r2-NwnFs*Z`crxp22w(~~CGuQCO zWT*RJMQbQypUHU(jJ3{0*96&eC^mN`|4*kUzHW-1k0`hg4of7^?T~D~i=+>O{w%*$ zJ30P%a|wWIw+>M4MwXLpj*Q!{G$7hF39sGvcRw`KQ^Vk~V%=Z)iu)%-NJxfSK?fMo zE-SEof0`I~mbQNLp0g5r^vzZ)^eGs9G4Fe6zY#E>#9oRg^&raAiak15ujcjMY5Zj0 zwh8)*-+hQYfj9-o3s+G2$gR^obm9e9F>I5=^%e^29b{Eaip9C4%YaVWOc-;3#nKnM zugVl*Fa%&pV?S|L~S9H0HPpHohu6>p1uW#J;w&Uet zZdky12+)q$(umr}rcUvsjDB_FNwH>b&_(5DGR%M>Vbmlj6aH$E5SY|oF|uPQnbPGI z0$pC_T`f;oGLUm%MR5Vm_J+KRa4Sa3dcgy*b|i7aE~a809K+5IWTMy=e`oF99BimC zMf0~G&ex{ZR0bp0S-p2QO19X&)qkBv@E6RbJhsOfQppx}Fstzm9cG zvPQ0-dW zsNHYo!aAUC$(&X@?$HA0Sm*b;xq1E=^Wys3Q}KU275LA4B>s_o|I_qqW%j=P`)D>{ zbvZsRo7${mQ0LnublP%pDeSaOgVBTFUCd+vNG2H#pv;%UM-YK0(2dY5Tkf?6msoZK@$0=u; z^;+NGf)zYfKU(3LoF(?<3z(#@H60M>Qw$ZM3-gsG)PVBj^!29=l=9EQ1)_b*ff&~f z>`3*2y}MU|1tFlm5Fuqn#g~!=Ln1jr)u~-kZA1N-B_T;BWF{jbW0=|}bw+p7$kCIC z$05$O@02}Uq7ah4x_^VrOS&ZI3WWHe|E|}zs+QX$$P=VO0G}-U;5OLlTpI|n>cECX}_c7D&LWx04nbp3Ml+F}gpf18lFuO!chdarV z=f2oB`(ag`bzX;`TbzJGiRFGD?6!!fT9w=uahds!buJp0$@$cLLjOA<^zdelX1%A7 z%oErz-b+WdO`54N)$&dba<2>;ch-;NsdBG${)!DpbD2L*q{W=sM>FPTjK|+>t_Yw$ zB1NQZ59#fCDPjs0p?xqRa{P2853T{F{18*@j}w{*kwzPph8uuLeE`QoV(X`7PPN3s%QJieWd3 zFaxNQFf>Z6ISVQB5(S8MF(nR!f~_F=N9x{p%$S_-}v!*I$Gq4$vFw0 zm}})Kev{{PZ_X3+ulc5Xkss-PQb4^IAhm9s(bhAkvo#EYbSvM`wwgktUa-S+V0;(S z#E0ROw|nPy-@3Tlkg-xZ*T@02Sn9fHMTdTd@<36@x7xlre0JPKM^?L^7U9;Y8g?l$ zx}nuY#K3u%u_9StS(7};B3C~&D;^!B##b>Vk9qc0AzRHh@P=5p@~$N6m7%7CQe6oK{{Z- z*vl<+S)l!tI@_Y9;p|gdJY%~bk+T{d!xbgAwb?4&O^F@$Y#n#kmc7w-sia98T;!>zh(yjwClhOY!PVa=8* ztpulEc>j3t8x3iK{JzoK0Qh1A!UZz4v354LcQCiHc3^Ncc5u}D%QqbV`s82FLEll& z-tlh%_&-d!;~$|vFu{UNy$W9bNKEez82iKj)ITGIW6HF%ZYACwK1zCdh_c>9 z8li4)i&!DVUKkKMMRKrbS|V07lzuiJr{M=E6=p(O4J$@(eWnw@lBwY9DGDsa2AZp4 zhWZfkgH}(v`}oy$N${}H*82X}K6ZJ5--Vuq>mQDPfg~ZB|Ga5u`+qR)c4z9l60pUa zszMt5$X~Z|rMZvxg0ck6>~>i7%|{0k|AE>e>Lh$Byz0e_GkY>Lp%Yb#ro{}?AFioe z{+ybuRm=1nwHu2%9&VoWob<@J=em5XTS4ZyAqDcn0y<&Bivj`qJ`Dk)dPr-&6C6{) zk&y^C>za#4QScj6_MP}C-hD2PEyf4 zgAADO&hoP^`M@5fq|qD|fk~L7tu78zf?gQ&xKm3_sDdxh$%Bq7CR7wB6aLVz9J9m- z7SyseRrSze8uZ%JI9TMBg|(l>01e@Yh$B7H%8GltyTYK@s~Bv#!G#&1i-9W&Zo!YS z<6D?xI|VBqU7e@By4>1O>ta|q7YKjPPhxWx23UOnZ7|G?jk)@bHDTO8R$sB4xtO;h zFWhi3VHtW&%~F2zCdx?%tUlmeTV#BFA9PLLRlC}J=>!4NiYb6>w!CLbI zar6P8+DX=w4G{&v+&7M+Gz1v<;f7^7{9rq&t@amxiwOF1ebKD5FsgN0s%&_vN~>PC zXm}=d*RK(JN8JOI+F&->RFB2SLtrRiQ1r$8*(HQSBoj0U*7nD6lQ=R2K($*WjF9=x zM`Wi02GKh9Q^j!2g!Gg?j}{|>!n8;={h%YZB~jVbDP@)Gwk229RE8>A#9q+7ZhB&EB%LAtxUyBh&HFRnOi?Qfs` zowa9PXLR&GXRi0=dGF`?;j9IUUNv;#qvNi3<45dq5dCPZ7s;SZiH@j%wK~SDJHS;} z6J>}4RJ*zgJx zQT-}QK^3#$3%()R6IFF`^`cMCb=tUBo0N7#cSS>Y)Y>p~8rD)QCx(>?=+ej;?}|T$ zk|T=xl2v<67LbW%wC!mabQp)`-I-?KB7Xtn3rq4&K&h%(pHJAlNUEMjil1dSED49? zuS&|WBFm3SAtRSZWEy}czmA+-8kWCpaE~duu@t0>paZZbQIu;!A^Y$a95<q-W1Og@Ir-H|3k z&xaIjC#hb9Sd9gfl`Et>TtGm#<;jk5SW$Sl_fmQ=_X zoRFw752ovoDdxM-vbZ*^+2BE~+b62)eS&@rafsT%e>wCJ;-?M$=ce6XL-K!}hkxCM z`@^)W5Bbfs3sU`jG&7M+;FhSAzu9a3ATWq)2Ye%o8Z|22j$cMeI+pn1!)~xJZ28Cl zi!(n#KvNqV6^`B6Q3-rG!$G&VS)f39#&VQV=dVpo0gz`NU@77Pj^LR6i$35WA;hH~&by9*o0+0!tWo(lS(2 zGlOa>6^k^OnhpYa39ctQIyGEQ4G)fU?}vmQBxPI}?0%pQ@qnLwb-LMSsziFevR8tB zb{|w}*aHF6u9bNUQ&w^e4gDZ@jUN&h3ytq8kbVKcKSK{dlk_pU@%)}J0>enRdEOvA z*c?aYf2ZhTS)C(z$;tN+wj6sQ9Xfa~zpJAzwmQ{bUTJF8Hq#COehNEWG?=Aj_b!?9 z6bClMUJBMi9v;=4QC+p(l=-r_%SiQnC8$OuJp&`wAP6(n{Hl7nH3^&rSLq2H*}~5t zsQ*l<7hKh?+;(IW@U(YB8|%9`%@P1z5j}pZuCW!_;pdu+3H7ic@OIEO);KN~RvE5? zekoXcj%*8gJvo2DS8^l~s%;;@NOwJJ4|l{zX(2JaopYeE211U&!1{AZYIrS7?cUzq znM~7ztw#s(BPyMP_~?q@I{r0guV$AAUm9a?XzNI5>rBR4=IdUiEEzJcqWlP`-0}`I zS^RLQ>yMy$ir3+Sp5rWv9ag_$67E+_F11q!H9W01sJ_JH@UNJZ4iDhB;}TkylFMV4 zmdV67ianG$K+bDO$ilatj*+I-^wq-GepB5ML3*I?Z${wEcjqfO_~4awViGIMK5PkV zKOoLivlaFE>FrdCF9+P-Gn1!LtSx^%%&DT zOXRd zRb=XJvdy@DcNcl@+>=;cax~17yf0r@i}_SL!`nJke40Re%CT^>Q?m7CK< zwEW9fF^rn_mzQ4pf7aV({a>PX-r^W0m||U!@@&5E$yf^sGL6xQ~? zj$U{}NL2$7S4z}WS$h;_kw%y55ipH5zQRaTI$(*17?EtEAcn#WT#w68!2^SV&FG63 zXMd!p5`AUjDe;T7%XRpvsh&BIxd4HFPdW<*r2>YmlWche0lInz5K=6@j_hs zSI7XYUDJT*s~v-!h3}m!3}n++dX89^?C%H|YU;!-%kO)BSM9+)eQU9tI9bTVnt4&r?0sbvm*hO;nSlO z7FEvM*e|^k34JCc=qI5O%SkSy837_C5avdS?AEnTGns9eL~tB8 z+cwZTz?RD2DMGrXD3DVEd%P|Eo0O1BoigOJSsiZ8kJHAtUzYBCR-NW$!+W7B{8DVt z*?(HM??Ts;wTpxCI(CXP{bXyORXE_ob5eL=?KIxK;wyuqf8RH)c5dN$E|R1r9gRu5 z6)VY?O!Jt^8!Z;lqVcdVoVlG-&g813<;amhnY59a@g-Qa@7m)D=^RydPR(U4Ytvv* z#+EX=in>)wd}C1Qyamg7HAjLI2WVHSw_=+G@Fx9{!ydQx(|0d;Q@soKoD3%Y;FTn@ zg0%OX>C`ztNvH4b6IHQ&nNaZGr>3W zTkBP?ghj2xy+e}Pb+`!I6zr=#?Dli!J5adL{etOgQ z{zY%1Gm|Y;v*i@8H8)}rNG2lmFQ%E94Y3b*W2TdvO6CeKb>_YJJw?+WHcxhshLrQF4X$rZxY zUmhk>8~eqN#%X4C8Z|OWF<>w!fW!NrWaFMM3@7m`ONJH-xz7isRv^ZHzN*a~p#^vS zSLIGd3EQL%$jN`!+V+>6{Lf?dAIOoxCd=Fq-FGn5-*YlSlmr!L8j&LGuQ?fM358fE zf%&3;{v{`;$fRR`WT78g_-grP))Gp{`yQQ%$;Yfge95gVOf*g^>VG2FNi<~sP&l4d+oza_mEB9N*? zAcreXTUqx;gH<+R#XV#iZQ{3}Ooo#Eng;}B%ET}K^VN(0NecL%x=P_tBj00xL3a{7 z&!3cos6xyLRJP)@pb6Cwgq@CwTp6+vULE-speca^(A}5VOig5CL9}&M7WUZ2LETs| z&!9~~kGEqHzH;8+^NRqcMp7pgG8S}aG6DLsY8^oRD8)wck7ed zUs(zJ_pD6)YgShM%1V>}k(Jl+80ws|Dc?VpsZZunBk9&4fP<-9yar{=v73r8hp{_$ zqc~LCjO}1`&*uh*OaC3ZOFhrfoZRDhEH59{E1^OS7(tWOyt*aX60BSc7x6?~C&aGX z8*R9PPD%-mB;ouz#k!2Nvfa!*qZ)qwljUfq!OE9&L~#T@)b13L;~UJOm@+AV+K`y%`V=aXT@&X^9*rkCh?R9E(;?!JV7$(zqX6Meh<}vLY;d{s5vpZd5IvH+7zA26JA7TPrTg`=@g2dL>kuwVUH}~dqQh8s z2;-BWFIvh1X`aJMB1!rEb@j{vjD=wJBRQN~tlUYdO$-N&j^!#ptW>)Zr~?rgC;^l; zOGY!yRE*ROThNhaEN6$|>IX*qIKDn<0}lf+tI!^)FUN*Uy489`VIjHHA9uUo?drP_ z5QX{J8+c5H9=}~Mbe)-Aa?S$&KG^^8XC}uuGg(=fh8e1D*E`93aJHAMw26zb89l`RAQ&e`e)hM(uyQnf&iM+s-Tf^~Bz)m$9F(N^^hjakv>q7!Q-& z2qcAsT&H5*t+qyX=}LJNo`ykhm}D`gjscB|xc@*>3t~Wfd6Hm78(P}Zkv^?R4Z>0k zuy-WCv3Gp9yy=&U>~#;%&OWS@0=M)f{{lkm(24mJ0PlpC#))_T;2{40t8n6vH^Oi1 z-K&tVv{jL{EHvI`?CZUSt#-%1yeNz zArUAOPz4tkqML^jQ%h$Fr$dcXRCZ>GNPoeBGUJou+{|xQsWLeo;<39~N#rtc>_g=70@`L`0Z5DC?wgaP&r_+P|){?dZD&_W5Nohi{mCHm8+#ZSH`2T9`oIqF)(9T4AGFBN)>H zW_66hO+aQd2=}8SyI16f7~K9=$|g!%f5L>+H46AQ&5KRIQ=w_*)4f7_(R0#(qk`Lh zv&5sI@IJU3Hx%2Z%qy<0d|AZ#ZSlVS2f*}@9nAo7Ak0k70*@E!7O5t|rNO=4$IA(rY(6oC@4;NY$(9?TzGj2&?RMW*Pluf5e|3)w zXOr7@EVXwhnl!w(Y`i*b(EiNeH1VnC#EC9VX)SZ#%`` z@Y;2XQ(x1k$4@M@r7B7IYj|_D>T#YMiQIYks)wSl9#FTozYC$<`4X0B#=0VL{2ase zb*PJ5^Y&i2(o}Y6e%WkXmCm@=9Oe7~h80;q{vp)ob7(Fen91|nSzmKVV#t3Kl=`HXU`9tvGwIXLpiJ28Jr@oB6vnTw>;=p<+r zoOKpdx7v&gOrzoQRTKq{%!)VjHq7hvNp@dR&yx;6&Tn>>f-fNmLOhrSJh9Z_iH;Mq zZG~osN3x900lrNe6wL_%ory_?Jq^*fwk#A z0Yx;#`SGa?MmcFD$$2s+si_{VscV97ctNLvLt)cN;3rkgNW-+I_C4VHre4^){MW{u z-PQZ(H3Fjcg!q-PhNI4vc3oMT5L2jcN@33eN32qU(N}{QEZrRZcjy~Sily1jga$OS z*Y$N*;$9ya@0y5A9*QJfd@oC|7vlKVdUtpGGqLVaD!D2`$|t#O@bH?6>C{4t6+}p= zy}DtxM&*ZQ5z0O@Neh^pCvq)}TlU#g0sZTAC3NfE*-Kq@=$6>LYSDlJxKC%_)y6as zKELIRaI#8P#$;gWo-@cV%Xj0rNed2H8N;&!%GtjC>&Hnttxf+DAQS(Yb7%br1^T~C z$v_Fu;(M%K`mQb_XcKT``0i|nNg22F=#2SS@M6yEIn(*^CCRTA177#YsfJNOGsjvK z!9m-9WSTy_^O9pBHCH~*SO`&320q3H5TdW4um4Woq1@&_9dd&giC3r>hAgwzW-SrM#TiH$>c?xexIRPsuSN!E&u(7RLm#nMwAg(FR4P{v=;3!H=^6l9I*8HO2O&U6%O$gWK zXSOU%+#*1@Dvqb&k+%-@{_$KO*vl6XrZ3D4rn|^6nf1Wj76YWryN{#}aH;`-D(;UtTv7RL6Wr`nIDR3Mt@Z=-j?lF)6J7t{fJhs1ldh$$ClR2{wN^^yU+JTzrPg+M9%7(YE5iA<@J*r}@vG^Bm#o;!L|1 zL&C{6oGrVuR=QN0ms(G|Y>FlH(^Go$&`C$>~8oP5xu)Lj>W?dtv${C@805;xBeLMFE1TTJxD5 z^+-mB2_F49-yF9G1#Nip>grz45+yy5;PZ+V)b7@g5WEV*ix_{UXszy_2V6_PHLOok z(1u*F(Ydsgu#1^~?>sEcJ1cizRq4R42Te^|;Z$K$Ka5ii*Hr zvfXh&C(dV&XrRQn%;6&o-sk7)o!5UK{AH^+o`Zq#|7WtD^?xthG5?pcod!h?j(N(S ziuIe6xTkkEr#KZdb(<#*s}HW)BBTU;Vd(upr!`Q3#A?{1l*<%rmA^ECoi7gtP zZ93zLQc&6mqal3zta}}qq5E#?2fG|g9NjAkPqgQ}BcS<+Hn(+W)+(sluJr7cRv86 z>){V}?^G=1P!2yiKlRQ^t97``p)(vHv(%Yk4rwMj^ZWj7?5fH;RZAKIy)9TtD2-V~ho@zeqN1hS- zj2`9AXFH>{Z4vE?&my8+%9Rrn7X)h3UOL1eakIR2{)8-f!?DwN^iD+aM|qkmP0N7% zF-7M%{p1vcPYkuG8LX;U3FB0)&-?RlM~NS&<2oVK&FrEiVC$nwV&S&yUYjxbnHnUv z8R9Eh{TsKV@bTX;GLU=EY+}A%?g6___ybb%-baOGc+`H(x>Xex@R5;&sA*fQzby>t* zVN}i*q?__=dcj_GIJjIF6#;vXp6=Q@r4h_W`M7Gq3ZfV3w{$;!1VyflK>4=zPOsv? zos}DXM*;+T{FXwX86zAn)%@#(a%M%o1>bFj6v4N*)XQ_bYj==;Pdz*cYl3hf_5K-b z_kUCGKhM1X3fnDovx=h{1c2+SYQATTxh5;novO5W%F_Jar5@#tvMHMB6HV_*GQ3v$ zJLpOA0(xd;RUq3Cf1v$!7vp!(^WFZ4c*TrW!b=zNE%&M2>TMe0@9k^kU|vuMURWS< zzB*V8ZbqpItbJdpCeh`;a;K5gk4wLQDsl0dCN{sDDK3q$-11UiWA6sr7-=jn#rvyQpP5&s#Ya_+_RRD1C}m2)oKv=<|* z>pydcu9>paQG~o9ktfErGE@WKi|U!nmw6Mth+8TD!~zZ#=YL92>CZ#ade`Ii?G#n;tzr$chRY*PeC(KC4u)?GS+_+mWAGM-CkV zhUrAGJn!bRe0=)&JAGixAx&lx0Maw|chb|Rf(uthkM9Pal88K~6E~E@CW3&vtwV-< znO09a0=R>>!@CfG;slRe67jv-eW;+pZr>h!Z@nD&!7Xpq6lMFyp9!T|f3W0Zbb%>8 z7+mEeI$U3;c^)3ABwCmt^Yd{dN5PYdd;=C-`gKGW#{=6&?wVijN9oI&>FAkYy&Nj^ zN3ANo>7OX7d;`t)qlManSaPG9HJI89)jB+ws=5luiUUlF{jyFGAT8VF&!yX>!Z9$URg{Tgw>dx0phtsu*rv=J*E$itsRl@H@pVLTdUvnO&LshOq zw!Hsn>w9rP6GQRVCB}glm|9VkCqszWU23`ho>F;wO43IxSbJ&k$z#d4Ykl} z=vk$rQno&(Q`BM7ZGbx*=v})EJQNLbeyfBRr$k;HFVZ9qg@+gARvs#(V>=Xfj~YC4 zP7#WcD&8Pq#g6o@c0d30frsuq8MXy24?ky}}dKyttuL;&pFmAn=p3J$@ zTfafA6cPYUOkJjywuJ4=rf#eIyewu;?YA4yU)Psu_=bLfiRjm^1 zG&50PC-!Dqn#qkqi`6`DtbS|}bK5smts&AhxeVW*c z|Gq-yVSBK<&z9Jtd)gZESxfAc;UFYu2F5M-YEx-b3 zUW)@dD8MNNnjOO7zFDNbG_U1fC38Qw-)xaQxTl4Y#r^d`C=A+@lJBB;gGA<+ri1yh@3kY?|dDv@Q- zd^+g&>hrrw0dwgo*t&nDPiU#RMusTi)c~dNFhFryT2ph7TuB;aa2UH=<~w+DT1p>b z9(z;8XsQ2f8SCe~lDU8xXNWEkIZt|@f6j3AYS!bj7{Ke?t< zU%CGT+fn=n*zWURVY}N30JgI*OiGH_|1h=i3%0Wk=&Fu$4o?JNyM6$+OQufNIMgju zx@)Xp1KKtbXHfyz&fpK&&f;&d-PT`WyAA-hGlf_Ge#~i@uVY8$ug4j$LZgg#?n{Yr zsHbJ0K5MOx^&y|dFn)TzfYUbg@@q`vxu#uq5-}gg^lw}f4g9JX5k>E;PZ-jdzhJxZ-(fq?9405_(?{L|Ze%0TN~zKiJVct?rxPDUX7-{E zc?e#p4*95`IAc{JlLWkt>4Gs`1ZfUk5p3C|IrE7Y$6b2I0%@s~<&euqeqNTDN1X!yqJx%uul&O}C!-XD$@NL^k zo{3bnpSEe!_>YK$2iwToxsq&b!Vvvx)@rnG$H7?GOFDQ0+uK)_*o&}b!6)2_N*;g1jXBGOhqA)p zb?suNd5|k!g;oa%GWbK#$~qDY$57E9;o49higv>59ak zN%@}#VQnSd7Xq~HF9aw6+aZ=1!X*EK?Rq0&3^#L@nQ1|1#KlC!VQ7cRc343nX@&5& zG7zCiafICYaV$c&^%e0Hl-2#P3<8zW1xJ2Bj@`uw?6U?1E&G*JtL?73JFcF3+%7LW z?w%L2Im37%0t6@o$L|EF+-<>c1n6Iq(g`3y|B{pd0s4DVj{o1Jv}0$X2}l1Q1n3s! z3jyl=8v)wEll)s!^8TKbR4+++{F0RBCO}g5T8m&A{+X1qFG*RkSOp|yOy0uLF9LM* zO7eo&&pJ1=3<1?0Pk0sd-Y30zPUmJDryOStnXiIg768rZk*s^lHjtNATew=*TkQu%juxg1MdK%ARKfBW^( z%_PxlbANZ>b{_M-2UhE>CZ?Mmd@e6p}tN>_+a`!O2+MMHj*IkI=l&jZ~K+ zyF~4Tl4g4R9K527NXiCQswn96pYWNSdW(*X(h0UZO#TSVshzO_O%^V^wA>#{YiSEM zb;s|MQYnh-_iDA@v$yXo*ZP1a_f#2}-jt(b&@7G=eCpTt+p9ut@x+6nvPBdu!mS*9 z61r%z;SfY=!TUhAJLHsHU{7v)g4$HI+KwIGdg|jCk_#rfN|m&O*0|@BoAs2rl!t^Y z@+={Gmb7y3KIKe2fMAlSMb3qxcJi}uVo zWO)zf&Ci1_>hFm9ol88fmG)$a^KnJ#)DrUc>z|94-n@@*!6tFrxM4wnA8&v zmcK@nCY`bF+LbDP+_e*bmheE%@CAPf%jlP|yaB@U@b|EMuc|%xm$1a%RrnQ_AsZP4 z_iNSut~+RV`~b^w19Ju%0M(;TKofXnU8ew;zJ?3COoNp7`wLvhj|eZ0I}iYfA&*<5Zc z`lW#K+Kyy!J-jW0D*zPGjPZ(^lIw)yFhBtf#aiH77`qs8m5q`E*{AJ2{rY{`>lEEX zGR7Wc3ftiO!SG+h(&3M=Q~<(K5(rDqs^7x$@FgtiXi_dIR>+{P8!GF47{HNCRpF7Uoe38N; z@$jL|P?q@R9=s>8^GLm?j}p1;MpGJ?>`aajjH2>D*o(mUcX#;_K=k;21Z7l?T8K-> z#1|B{WWy+k+V+3Q+7WE(W8Rvh-#-$_mCzM>lXOvZFsM760Q9x8i4=aljYk!)Om}Bw zG)?U%6dyAL0bFP+w2u~{WU_uXz)JyvvNQvZbqd&$SO?mQ?7t3ea*mk8Aj-Z%rg@!J z>EUVjQ3(@{l_{QaEK3~5!=F>CM?EfxiX@N2RX~l!&NEJlcncF1o@^yB58N-tCv%Eg zvX?yQCq||xKj-0!(dokp{M_r0-}s$KfV|h+%ykGOawDeGX2cCdsyF0%AolGQxdYw; zuKx9bD^TMmq;7rn1=`EUz_YwSThpz7ir{R1J4Z|XBAxOm*s25r=OpSjWr1;y<%1%w zhQF;z9A%rxfzShM68eC2YCOF(f5z=~rcps?1#?}Cq0B0-mGP~$#w0>Tztxln5z8`#QaA7WTH8(0m3O-wS6%0Y9l$vu@;qM8}UKN0`<$$J`~gYOH`Zx9X9 zn|&)79r5BJHCjFZe!{;TM&^kR>O zZg)+~pQL*Dh~+UhWa9%P)#x10pF4Uf>oeQU;oOe=XN#}+ymb2ae%el$zCIB4a4I0X zauzY98=&izGzpLxJwLKd;xRGETL`V%2fw`+DzKOvyv8ic*0}XeU6hq@C!=K37bi2L zsyB?)#$!ZaYU>Xb+Il)Az|*v@xEy!q+JMEy&|Q-_?V9gqWjy9|W?`YYZphJ*KZp?1 zVOs|WjZhZcXnsD-%8+UOEMSxpQ5h@=>{^dD+)#dy=P3ie2(l4s{3HS86*G05sVBk( zE&E)Y^*VPg8mtL;AvmJfM^ETLG@1+kye)X7PNAdP(nYp~k83NWUH5WUvJCI04c-)H zlw&;2mnNe@{kV&&KP&L_wID{oK?mrdeJ^x%|FClc?9Nbd7HfR|J&~L(mp*inxk2qh z>>Hb*QTAC>{d2-HcOrb3PUr;1dJ{$eL(0JLbWN{AT;h+asSK7m-v~9+Ww%q(JTBb4 zC9&_2#>`>a1E?u7d=anIVhnZW~!;qzeurz{mWrg3oYrE0ovF z{Z_}Vu|bR$(woZV?@cnOac?jQ&AZO(*8-fobe7xkVoRxqh#pvzRwHMfN0VQF&TY_=W*hX-jAM1c znQjB*=iaOS8=rc+1OK(*hEeBH;ND)!ZOUcZ=I4S-F!*+8co2U=L>Lf|#dE}fqE_o{ zdrOzv((__6sZ+}Af#Jr<0Mgo=cITNjxGMV|h=C~;ty!%nmkMGf=@#1Y?JsR_atoq6 zQ7fPyJ|jqeVFkp`Qg{RYT|Ik|H(#iA4op7Ty6Dp0YyD)|A~cLF7)BCv~9G*OIV`pOL#9K<^6~^ z)|Im!2u?kvpeNkTIfEDc(o$i0^K=vN)GC{Wk*~mCEX-7xJD~iA*f~?CSwrn~KcUF4 zwCf;lDhB4RO833GjKS{&wGfoz>Oon69V&9ZT)zhae#|E{4IU0hkmi-;jv}DvxC9Wp z)z4{QG_?R?hZb$e95J~~dOV;uPF*s|IXmPa35wOxaE5-6DwV=;CZ!`k6^f?9RT}JWw8sdR#rLMOR22g5DSw?)T z&)m-&!p%(Qi4+BnhPzizt}x?U6jjQTV4HF%^V2upX(tMYrw_Z5+m6jdP5EmI4)(|^ zsq$}Mgo1CT5l*E`u6HA^wE~mHDhp(+8jFUW@^EQphcwe8bLd`xr3pM2vVK%MAUu zK+Bfs`+eTcpZb9!UCbNN(7kF~!P!Tq+GXCEXU}s9y~N+79c5LfGRFuVDLsSf0L;%! zNbIMcH>zDcYc(gmPTttn>6uwy+cUYSGzRwQ!8(;I?wX{|jaHB_L+C^Nau;-~Yd`jJ z=GKr!vrgL+;uU_iXUSEpg>~9hlpmGRMfPC5ix0Zx5GNb8CVi{3?<-SH~f zFd2oI;h={1gksngk8;c^$eZS+uc9GVZM+Y`o~SBJ@5T0wSj!K@zxyTBP>Ktqt z#i3+vcmSB6bX#LD=BGFU?r=s*YQwiqx*fT4tX-o1UKFj?}L6 zYhyNZY$sU>pqG&%MJNlRT*EQ_1BW)HqBKL3g6Ol=(x$4DUu&Vw?|!??W4Uyq~xQkc|b4)s%{j^d*pzbN8ZP{Y8xm+^}D0VzrZ9gl`x5u(`o%ukt z)yhJf4LC*N8&tPw!&E@!au8i5HM=hzQr{_L+LOI6lKvDNW!Pl}%G{Np5aP_^z^S#G zxTR^Wsrb-*>fRDrFIeXkH1fRK_V=UZLE2~0|7Je^pKRT~-y!}tY#oHY9SStoT$A8t z8*HAR-||F#!Iv2h8sOo2}C^gzS0wdib(L{7)_>{$V%$=kfT( zZqii7>XluTl+CECtCOoJudQv5MSQT<4>QfNucIx4{%EiJl`ex+Z0yxU{OpXOsp&ke zM$F+C=yh<@*YIS<0>fek#wsd;k&&;*B8}dtzD<`zdSlpyh{B!cOSCt9+&0Rw`~3KW zyXBYN6av^y*a7w+6p>|> z!qG+MIK(g#WSwHH9X2|Nt5`u2o$K!x)L31 zLIWOIFsxG59tXHMUYq`_i=vFVA0Gd@TQ4a5eKqNOEjFN?Kn+E}hqpNjh1cdN~n8gb?be0-rX%R)A3Js|Ta?7GW+34WkBy_g6`7d$L zhADMB4{)qf%%ZG6qRh<>ktrxcHw6`AC6|ZS40{M!9&B+Tm~oM4&-Qx`irqRp_Xvn* z{dAcl@F5eW$Qxk{Q&7nD(|b4YV@P?4uKw~_{r2O%V$wnyM4?KjIZ@|r$8#)Cp6aLW zX|^v5Jl+oD=<52(9>odaxA8*Xk}o+MFrcrn8!*^*Pu7};hZOp7rJ*6GL+FlA>4LtX zDIpc2bS|u6R^F%YL|wkZPtbSLs^u(F*O*<(HZr%IIRA+-r;7*)k=};O){(D=_$BK~ z)CbS62>5=OuZ|X3b6Ba7U;!VAr;;OGR?Kn&c5j@tAf})_NzTJ~Q6y+`4eIx1Nk9L% z8Vh^I9#~xXD_dv&i>-sF@W_`~kPeEq;ry)s!qz3C3Ji+%0c_p2RX)Jh*>xWjys&i( z(y)}j*t!&etrOmfl2cYviYx!c)_v9&zB&Ndx|`qGx=EKb#tZ4+*gA3lg^cs9_x=l= z=nBcqHK)JWx(~%SKTH9(uIU$Br=tO|bWVy*J%yuG)?1OhD@ObMm`;BrZ-kqxKt>HKGK`*(h&H z563ovCM`pnN9i;woK5Vr@TG-(D}0&-b-$p_Xi?8vR3u;^(0#tN_`&^yf3c0hNdNV} zlvvVX6nFk}wa)rau=78UzkgBd2>%2-&jGM==3l^0{}-_HuWH@*_Rk@bNj;VYM3M;~ z-t}Nl=4(n#(o&D?&2&-P%p7%wazPrDEL+ierrC`=-=A|Y*+nczJx=q3tzm)?;!J@P zfe<3P>y>XQE`rI^=ME0Dz0$vM3(uAlbz4G7FY>#=VRZdUr<(Zoz{S*A*)%nlEq15{ zj}R8VRiU0xzE-L`ckUk86Lw(%LAjz00R#4g8^DS?MfY4N_hF2!2^B~-%ke=-FXAvI zZLdp&ggwp;vHIV$j}%?JA(mHXU*b=e;KyA5km*AFwt}gKKPeh&kXUA;g@4|$TgF6y zdnts0@Og*d>u^Wki00}5?a2I#`_oc@&dI!*$02PY9>pWw9G*`LP1pCzyLT_JQQf7I zC)@@X*F26-D&3wa=o`i{OdoBRm*1t4TBK?(b2hnHV*uyVMY6+?CU%HwTJ5GMb`-oJ z69zA9!kFz_c?%~BpI_9v4}Yk2^1swNr7Gr6waqdh?!Us%$Q;G+Hjw(_UfT7hpKL#a zTFC3Y{2Ca%?HSWlShU{&1aH!V?J@WI9mOccEAWp5UE@hYLQW8i+~Y~Ny|pl!R7Y@8 zZyx!ZK2AQN%yO%Fo~KDW5}3+W=}l_e9ZozFqZE(7|deLjr4K0U5QE9}LxI6&Ga+J4sVV z`p6h3G>eaLG&sKx&_TxXsgU9A2oEshan`-9l=7zuO1FP&sBYWrK&~_&`H*9KJ!MT^ zgowN27i)y_+)q+Ue0xhgD3;GiRVX!AEQ!EGz{y7J;*On%>q-OPpg0geWXdCp)lDX8 zpN_3^&MtI3=44AEbi58zAf2?}NG11(X~(N#cU>*uzo4DV$ZcgvPy7Dzfx9NTr?%kN zPOykLKT}<)sUmbSasVZ;JOOTX;Lo_W75}^9jpI@{=s?9c!a!f@!l(DVgQ*Y0-_!&imECEuEk& zkvrhaJ%jyy!0jEeqWkA+-5=@qm-F9$ zJKw%T=wJX^+;|jD&U&jq@M|NJ3-nQip{ol+ODrJ}p2(oSV_;bDSpBv)LTb|$-!0TY zMayBS6+81)@oWBwga|>k#6-V0MVDJL$&b*A`0cZ*BkWKQPv7rJ34r0jorv~@3G8q- z+Q|`D29Mbz>d@m^_oRFlSf5x-`j?P*>V&XM0>;}lV7z7e2Y2NDfm-*Q*W@0;QwBNZ zQapPZexQH~hd%FHWB3FfjFW8fpm0NOjyzo1osE|5xuhj|SlZRN4EHXKNi!Kq2&0N{ z5pMN};62nE)m`2*Z=@tjgOP?Fq*_GHrH6RJ4Z6Rvb@uE`umD>J4fIP8;VXfF6pn+F z^o$-ebrF#+&)LdgkT_B*)!^FXl1tU8vX2zty=#5Q$ij!wb+z*bys^4W7;qur(RYtn zS54`BglSh+m31DMZ|reD3L5W8e)qutkd^)z=AXgP8X>7f`1)Mi0U=lK8;*aZx4&#o z{W?Dk!h#+Y_UrA5oju?=FfLHW7bS>MW!o)Xum;6xkQEmo(oY~043!Y<`OVifQX-N-oE$&ay1WZ$0aQ~G#PG(t%oCOJH##~W-K#`K0L$>U(#Qhl{wO#NI)&B;{6d)oeHKeQ3g$Z7Rw8ac$bg-V$!jrowQVT)3< zBsQ_U8THD1Kttu3BO@aj`tJ|vtoY=XZXASXsXrnLe@^f^kLIKK(M-Hh`w+u02I`}8FODia z$cyCl)6hP^=CcnH#peIv?5=|9O4oG(LkPhgg1fuBCAhl;4ess|+&#FvTX1)W;2zxF z5;XW3q`TMd?!9WQ-KT0^KovLKyyF}H{QmdhIE=$M?hI??o{EF%@`k#@2$(^`X) z-JSQ8A}J=k3^s1ms>+M)o5R-``gAY7mWVzRu|@bfev0~|(IbJ$Sem@|IhNI*`)G`^ zVmxxacB^511s^IAhNnc5P>`^zrT9(0dr0cQzUZA9H-G4zKnzL(F_`rVWE2sB3It?! z-$#CW?^-P~C!V)c#87oMPeIIL9YG5~TF8w6cu#4r<&A$xo zfqSE@xx|=<)hd;eP<)~bBum6v`W2#6%D22uj&l&LCFWBTC~S#0NTMzvwZZe1f^8vZ z*koo-;USQoNYm9{nwc{ug7wHP8GS&B48^|-NuBJMNI~yO5!4H|R?X7g$$O3pQ4rzA zX0xKXd*Zy&WI&9Qamgn?puc1HB8{Wis)7!fSjGf?HypI@uZb3Iv8Ly$%64fJ_rNBsdwjpu)t)+0es%A`#ZR$` z<4(z5Y7PR8C=FVoKRywk0i37#_c@SgZA2qY}B*cgziwgJ;_z^e3(He(9a9O z-Ov<-koa~)fr7FPJF(l0W4~H@r(AK2%8Eu4^-Uo|m=I+Jif~W5>IdF*#L}!}i2xg{;tvnGy4$X$@Mv_fJdLdS@lFM`y+TVfoHUX^ngzUgQeh`#^wz=(Y`cu>m56;Tyc5 z_6`)Y(6A>BB-qfQ)ATnk!Vmr8GnAAwk?5|@4qkMyenuEN>sjn?Wh6ZD@ECd!6ghSX z$>YjSS)|eDj+(YMc5{x2utMzk(IUcL;iXYxS#LluaQbM8+Yf4Aw;FKrUiH3S$giy; zz?c-WGHl5Df!5U+$4Zm}m-*fWK_&Z!&(S}fuKJNn80Ih|NtT0%0o5N&9KQ*+)@x$M z%zsgot5I{#g?IE?L&;Em#7267>BvHyLgRB_l$Q(N;jI@0ACpuCmdvboX=XHWs7rm_ zqmjoJwPiUwkc4&48_<)tKb{hRB;+~ym4u1El5h~r;S@+hyq6^8dZ6EMyO#n?Gg~u$H|;H*L{yR@hg^DG=xW3C%ha1r)DG%YH*&u=(?A6~*IEWDw=?pw2neCn+Dq5YZ_Har}bH*nj8()Ya z<4paXt>gYPTgMs?uyseMYAT$V!Zze7adq74dbV6xmKzqzSy7s(A{+%VU%&e&7v~s- z%Zy?$x?4v`kQa@UV~>!5Wx&Ttg9|8h(6q6E2XO(##SYyqqjYUQ-!8$-ya&BQ0p9zo zs*0M&yL2EMw3BgV-Yr9qb-li9(nZ89x>pFsz9wJKg7h2wpj2*&ueHS2+@xhT9W46s zGke2;Rp?70XJX#AZyb_6!`t3R!m@`~?ki@1RQhNMtiUlGfJm%=3^oA+*gD-mvvo7v zT)}@~>-H&M*t)3S*t)N*v;bRYJxz0vvZnhNw$3e?Z0$?SPWoG8X-B7R;>Xq(w(jFt zo872xV0PpY~2#t>7Dd%Y@O;aw(iLC*w%T-;V*0*-W1Jj{x7x;xA=qHA{p^-Y#nW* zb_a5?Ipqsm7Y49(!*oZQb8I1A=Sl8~dl31SGz#ddbNM*e;EBqSO5v1iA9@MLIqDNO zDW#1)sWS(B-INWYh@*Thfv1i;qCZnf0?nXOv`*gCLZY#s05A8eh*Z)_dszu3BYnXTCNC~6}%sSJRFi8^On^XjKjV5A725pA^i!?4#Q2uIE-CVu#xt%v*L7Bd(bxn@1me zr%roBSDUWlUgPC8pseZU>ErXM{KUg8eU&AFc9p;ig+f#uVIDU&V^Vh-j5ypY#H>TW z6)Vwu^fuY#WHP)8^eO~w{L@*nRPkBz8~Qodrw6#dhN3r957|Fg>;4>y|9JxbyIQ9U zsCD2hkL#O0My8@IS{hHu1l2!u8)>Ty1EWck>Io*Sez!bRJlFjQPYhrr!*x?=AJ_HF zF?GW+$U@|6Xjoup{B^fJABWkVX%r6D54*nr_K&YbYowkNZ zmdLGmJEm}WI@FuT5i1(Ap7j<4+T#F&-~>laKnKSoG(*c&l_Cl*|1FXz-1u&JMS%qD zfK2qxEDF-=;pn`wg~_)OlhI<>#^s=o+rA9ljI&CC_td=%KTfHNX%2erDn<&y` zxp=Y=U+M4sro3UXkvHbaHssK8uoC#L#pss|6Ib=_y{XoHU$joZ^F-xe*C7bj$Q*$u zC$IwF(|P5l#o!G)gO)`PdJp&V)5@31W)BC)`~6*~VreiukN2y~crBEhuj}=mNlDT3 zV3Yg+jSfa{2mRZgf~(D7J_2%)tQ#u6ThiOJ zG57eD7r6)s#+5X!XTbAJci(B&@&eNh&a699NR7!9}LE94%nDjnGWk*&=!1058k+xa>OS#F{mlq9nIEb>xiS?VxB zpqbOxbS$2=W!MU|VE&6O2J7f<(7U?oUb@1CEyZzjRHbxi)h)6xXifBQb@_TigP7my z;IA7?9jIhK4kl_N9}H_AfJdLgmY`!#$w*R}XF#itQkSFX0(enaQ2E8!d_^GkqC~sO z+A@(Q?Yd>5A)9%6CqL)u;=$8<(}*B!y{`aX#CBFYxKYx09s!PX9A~1J0&g z;6PaWkYruM80cbBlGG2xBIe8xU?!!MSU}(82o?*q;zftxaKtdOWb?`2jNE8fF#?=K7c~>f_WY{l^4Ig6d>(~_N#G`(L*}c<*B(O`2jr{n`<7aP zGNn-}AfaB&P&{-tG(n`+qZ8@Q6F+Cy4j-Pu-dst6je6BBg8cO%;K!I#5erPl|BS73 z`#-aF)>7EOA;^7DyXvW1n*j50-Nkd`;X$EE|KcHafzKEXwE^<# zjtBgWF|2MHKN(^TO_^DelE95w9vSr2qLoNs7GRU7F{q|2p{(Gl`{@nZt@i@65?fw4 z=Z9aMbNdaK*1|_=R1iWa5Q7=WJfQ0AvQunJO;p?SLl=w2xcKHwJ5|mY0sl0*(PI9X zeID}|i#e_Tsg0w(#&ovX#hL$Tot*C7!E2R|sFI*WvH=kBB{ z7!pVFktRCtCb(*LI-Sx{RuR2$&SOc*h?F{^PT`{iOs|YHxbuc~ebwt=ev^zP|T+6&HTRfcXiVjFM@G5b+)R^b5Or zfe1BdUlaU1`H{Y_ZBq?xN`=;E>CJp$HBFT09-&!4+7u`Sn5sB8t=rf1vj5JjaI|I_T z1fGu*FH___I#RXiqrr3UWI~ovXY;L6r0!h0s0GZO%SxvC{1oiwJ{iz|y&LO+7i+(J zF0;nG5)9PN1a0OU4q_a>nF6*QjP=4yuN`_T2^nczkinn!&w>WS3P%|B(H^WeI6(d0 zZZxWXhlhUBwqi7r+|84B>e6pKA{Rqd0-rjoN~WTCH(GnYR9EasX~xqn^CMJl3S0#BLOD zi^yhgnH_wJT}nK3F>iSv=~*e1D6~A-ANuN+UHGmGxI_J$vpPx`tI&~$OdI;}E zb+5g+F~%FwjR{wL<=4PS?2yDK#tAoXbTvPH45F%>y)ky;n#fC8LkvjHdvkbOa}y9( z_NiCKW?cyQ@+e<#@Z0X~FL%u?X*Kwt=9t>bY98EfU2!XpLK`ej;N!&yAN(D7 z#H* z%KBy3!5;Ylc3lu222)1W-p+k#GTX44c-*3vFw5a~;k}5;{P zDlt~Lz4e=75y33*T`1*eDZ9W-dP4Eak6<7^s|GlOC*hieT^v`CTJ%Od*~n}LSVC!2 z{22}9$#VNqX>s%HvZ6?3B8oZ9V`yQqlSN@wSY5$9;{li@$%EA|aOdtNyt2Tr_=^$J zYaTY3*f@Cim>-g5qvVe}G)T>CQ-%;30W;vyUE_4J!@f_Lm3G;gE6(v%(1J#JO@G}0 zaZQkjH^cwu7Y@?%clg$#a?FYCO@*m|<@FVIDdi z?i)@Z0`mue2>kI55r{y-s405AQE%*6MinyNKxmgYNGBM6rb{2>FOJ0LR*LZ9lsL(>*r;VhBgLEZ{Yblcq-3*d@HmC9=SEbwA? zim%&9oy??rNt)>fcu)p&4) ztTsV?7B?s@uVy!GusjaKhort7U4pknBQd0Qo~=c3{;w5>`jy$l7blFFmEHSyP4xm5M*ABJ zRJiOsNt>@Yyt2&kTbwd1|XjA5}Z3iku_w-iI)%R^D zZ#eIskhPF)i4jyvqP-OJ&MI^kr3_!}&SlBh3r(-MvwpKX(Vbs!^m5>E?iGf^+TFp;wW0 zMBv}n0n*3BwEwwX_eTW&Y1aLB2nW!E*3EzjKH)(K^q|!?ezxk14TfdJ)MFs|9IjRC z;v7rWXv@ibHcswlBaTzGy-uJRU?Bs8o^3obG_DjO7af1R@|#`9jC2p!b?!g^W!Fi= zftYdQ7Mm9>VSu#AUkSCO&Wh#%kYR@ZXH*9*x6h85{zdlFxi&Cttw zgaawq02WCA#`+P`wzEc;L&ujGm~_9Ko@%YEyi@}V2Dvv3VYleBOL6$5e?!m9D~kgf zBaHfZwaZ!~+TbHJx>NAD$@E9y7o(7Wq7$j}N0@RaDcc)P+k@>h>b_szP8mtBJ|?t% z-TvGkv$BZsXgH6N6}`jzZf~7;Mkcz?m5nl~rNhyul5Q7!TL&ZEuR=aEo>cSPS<9fb zWn0^p-MY9~D!lz;y~*5acqR2g;@-&O5u}I3R2lEyOu^-`fd6As_Ef;hTHh)%FES2G zr;o8do%pffV6c@R2M=imWH2!m$AoDp*$`?DIV~t!VmyQ`91@$^inHsH;oW6HV44xMT2qo-f+vg>4ti7m9VNsqE{98G z?Seml;+${0s4niDvarcKXY5k{%n zHa3A(yCpRzuC5>z*g(FK6;&G~7Z0WlTbm?;UV!=FNZglzFSxU zy0RL5v*b3=%T!}4SKoSLGM~!M25LjpM)dFnX&3Bg$wmXK66m{tsWU2*9lGS;Zn=zZ zWZVjaNLwG5P6H4Up&KP17hbX{uSV)G<|3AAR|#j9`Fyv;3p7KWGPl@&Jq|d1OSS#a z?YcjQQ_Ei8h%|ymePo;_`|LCAoXf^UyEQ$^z;61e?9 z5B82X2h0wn)9UiQ*N&@XsEO*7V?Rtah+29f)g5yG z^nluU?Rzw-n>CtLF?2IIaqRAq8VS@QCa@Y-0T0?OfO5+euAf?T9K!vm_Pbpdp`n`n zbsn(mpsDE~5SQVE@^e3^AU9iH~@B?EyeG4-IjnY3&V?D z*UGewGA=fOigZZ6@s9k(uCodIW!J?Wf~V+`^Pu=V8U;tV?g#>QoedC_U68%3^WX4& z@W_9&>moY&e%W=-R5WMDTB{2!Rf;b;nHkIO)Nhq!`)aA`IVQ&L7x9U5b60t8f9z<+ z1FVU0F<|OjP1I2Mpd(I>O(oSwaI!kn@gjI@Gr#Sno3}WK+ZhXC{`rVzZsojnsj8I= zbf{b7!<~QUGb0}aF07({U0ZTXuN*yL8|*^lf?3Pr!H4oGZHH4lcuM}v*s~mM_Dtq&T_pP zI^H5dpXV1@0&-&d<2q2mpN{q14fr3t)>+kSWE80ty$^Qzk$xjSRmSN=7wkPx^pl;& z&_~Zzw01hE@=<1jTP5x%Z~{Y>LNXZ|hzwc0CjF zhkz?4pYzim>&0m~fltd^&0hg_9Vt&@$+-AzLl>wFj!xNw@ieQSbIwk~)y{#`tsjN^ zQbh#!f-A2(LO{#xM~AwQM?N0INKB7(OpkKKF5&aY5)oXf-I5$enj`^eMVd*(w^);} zWJs}3Zrgn|3K~Z-B+nHEFo|Bj_JnSFQr%>}7i6yJ-)5yOB_ye+8irrM2OU*NX~r&; zu}>)z;+3Ih$C=TWxnPhix0^)?TC9g!z~N#w3CI+i$z^f0*lz3O3P^B{&sCZF>L^oV zP$0uyRA}@oCzVCv!BLigoV0+Y4riRnF=-BG$7K(UDL@^Yz^MOmQBP*DCKgDXpOINl zKKQYYF!~Kkbevou8K1RzBUKV2ZJVPA%mgNH)_GM8W__X99BSe>Q$#|Ye9xJ=7w7V>+`ZhjA|5< z%k`C+{L53VHhBeG>3!z@kGX#2?9-9{j<(j<3l0^{TOYct%?J9?lOi6g19*d4R$J?! zykQQ|wi+TTk9(ZqIx03KK&awDopq_5hon#gU{L42eL%DKhavO*WqcL^#wTN}kDnHl z7R z#Jkn$8xWS9Jp;nZ_d_Qp;;3CbnqHlq^qYsf&-jq*V=s2yn)~0XCARS)^;>^GPx-&^ z7Q6lb*>&s4U|}^dd7EH)aN^V`*nNP>B!t{>>!YGTwB9+}yZ2-^FV3=8Qh`K$NXk}O6GqIK5<@}=yi zut9d_*i;|KcMd|2tgD;#7F9z?S#K>-CZUcTu*7`@-+-_b%?A2>6)CbqWr{4zuGX-D z%QF--eboM)*ZDmk5lP&1=*3?c!81D~4OTBi`^=DfOKoHEvMPeaMvKW9ROwkICJ{OWjGz#F*Y2( z32N+pejK;BslL=HNv!3!`?e`$sH7eVdmddR9Ecd7DNa!>g<4G^Zh8?-(#y93Zy*kd zL5It>Ko+-m(q32G0gj2DTlZ@yzbKm@{xFy8Ck-@ z1_SUdA=FszOGrgndsNyVQ!w$ ztf!#)#6A=S<@M-L*YD6+wK1Q|DjGR1U7WJE=CzrQV!r>XDOx-FA+XqD_Pj1;ZBh&z z1nn@Zurh?xTKVAiQ$8=Bf+@#We`G>)v)Dwm z-e>jXLp!Xll#ujpG3S#5Ov}VqTD68{U9ZpKNlsin2sH=0nqC$gb4OyL!S_s&i27DL zJ<-JuITn&e%T0zGJ+Ut(#lV!^bjG>IJ8+74I>809stA&Wn*)^aWWC^ZeFODzhgm5_ z<`~NU4(@iW`69CrCp433`uMYpfJ{iZsL0G81T@spP$GHE$x$GZO^N+U?)Q?Z{n6 zaA4Ybe6H&C+B}w9w5>|DzTcWxqO60mJ23@bePCSpDc&Zf1FG^Ro#!}A*KQR4x|bmn z8-@VP5px8;rx- zv+RV0;B%h}3V|x0=vLB~+KD02b8Q}md^;(0};P4W!p#neRokjI(cSpX>yP1V(i=BSivv6vw(n_= zo$TANXgaAsnq93brF6ih4ESve#UL&XQp$!LA)tRE=@JH&LH-_%E~Ea#3#2`1^68*^ z`qfPJ<@Z*~PX$~~)G~A=!-WvT5GHnn((vB~&GEJz+y>4r=_s+U1*Sz+^Xm7y$4+K# zc$GE3n23iIm{FmTC%%d3=|$k#&^gG?W!1O0vSZV(B;*qv+O$`?Jt1)&$Q5tV_#*MB z8I{OAWY@+xcGmZbV86x=kUqIoQBJdl_fY#6I4B#hoR{x3PG9-Zn&w;NJouU$;_s3X6Mynvf?y(C0l+$FYrVf7G>ut6QU_oy_9Q zVIhxs+f_x6Mw9Buk|#9mT6>{4(-ylbFu19s&tj5ndn}lGJklcPGEBpPg`9JsPnNqgk#rnEF8nodFqh%$9gGUBf$`Hlxri=dxzIru$tM3@7uP0O{t$=FTi?| z?Dbxer^2L-cS3-Ce7lXa|Ftt5?c*2$x~BmJ{!VsUR6tSreC75P%R;s)OCWB+XN;#HDNy_|{Iu3y#Ys+|ikkQ&{X@U|BfoYzBd(d%-Ia~> z@Z^Gc{KaG2z#7*RtQG;n6m|3(V|=-KyXv_HRyjzP0Pgu)e4R0MWw&-YQ`vAOEO_P( zgKz5K4j9dGz@}Q|p@92Rj1u!9wb}f@s?u~wX|qwqD~p7`3q~V>#(Do-ulrY6{%P3$ zcl#Kle{MCdb@{B_M~|eYR|B|b1ZwUkfL>R&-gorUJOKeTPe{VUcPpEWnQjnWhI8JA zl%P>nPx1b)*BKFCzvy)viKoBobp>eNSSn=iJ25kM%qcnSab)l(Zb>zl9-mv^zpN=I zs#yQ^^aVGklCBAup8uI%=k|xx^q+T>|EOjAO|SD7hNT&!BSFI#(t<1}cr#1?NO#S%tfG=*WJ10Yz8Oe0W$HN$Lh6W|y!S77onTf( z%4>GS8P6<-etD?M6kd1Z)8v|)v1QCs>Gt6RkbQaJiJX2VU|RYQo}aGAv})SPZW&m`wOfJ(lA zM$~3hjgHB#{M+Pww3I)mcDzDTVV&7x)eqX5)FLP$Az78=$4GmMRC!L8VW(gPW&X?U zc${XY@TLtmF*cEM_c3Kv<>Fx{;57o4@mg1=O2p8EnZIAL&t2Akz0_GE$ciS7n@)Cl z4kvE*O(UaBx>D$Y)#c9ANC0({gY%Cb??)tm!zJ??!PCaIX~-| zDxjZNV>CL6Qm=GUSre~Llke^0i(aP>@hNGFOzki#&Ph5)0ltWLZHEZZ>!{1WsO29R zXC6r6GvnopEf<19)KIc2!l$-WYbBl@Vy?w7xgJF zW!KQ^*WW5@J}(J~>3gkIR$MoqfT(X5lvSm1##)qy^pNlFWZa1`vN z9aZUOe^#^%2~v0LyochcChLlSEu>+S5=8x?*Wogl7Gw~m7OFGJ$nbkauj@hc0aFep zdglSERB|x{<#vwx8x{hsu%8(V6~KlS$#k~r47kPY(}xMF&%DM%V@M5Fm~v4j0Kfgn zRccG6{)u?R;d`=aO2vNj%k&OI1$45ddU&et)?lY+qDohwX$^vPXwSe=`WLnRxE`Jz zy}Disx@ofov>}tb+QXmb9jwv@9uLPoYYf*@ma-S7BmrYKhxE z0h(Qc-M=)u9p@d^?;n!^%`UfAB=8yo{=&zkQ}fM>W(PbA7>*v4E#>R+uF%lN2UZnr zqoK6gV2&Q1|2{ZdPGD2NoG|<|&F)_r`CrE7ziW0n3fTL-5G9yj$xPl2W9OSx8tKRC z+*eMZ&nTP6zs8cNcMSCBs!cw0{Pb>?g)~>-Q_*z}A*yt$4P;5qmy$U&!rl@p%77Ql zE+OXx?C{hV!0aAx?47-yA9&g?)GW^}0nAPo!0bMQtATiba)<`o$<#m=3Jd*G+>r&j z?_^jS7T(+B_i821uq~_Z%|4b#`r<@Rah2-vyqMa3VNVB1;ach(nQd(2u2frCC_o$!TBaZ>)g7gMe^Ax>TJA@_Ru|npv z2d=>y(~77Wi5Ve9iT^b^V)@(ie-@#`7Z_K6~Ts-Z4xRZ`~`6*6~1N*{>R7 z?Ie>9Y=MfN5lPvc*Yy3LNrO-3ePq};6Dxs6~1rvfRNJy?ch{QYQnZe--^rQ9B3 zmOP2lBmwq#wylzC+&oo)owixKz_+noRU;qIT6iLpk$yx`h?c0pYY!XS{C%DBc=AoZ z0f`Fr@CKq00keVdJ{Q~rkl0ELS!c{x9DCC4G{)`Ki3Sh)4r(`&>WY}lC+6*#Uc9_F zlUkJ5QK4rL!kHO)ebQV46n7LGUj8<9<o+_9Z5VO?E6x z$`(Z3Ww03I6O1YKP-#~ar<20uHHbqi{`A!t?Sl!cp^ObJGwf-WibI~0N67BrRrEA& za)g~{Y+;aNY6DIXElpFx0k(wQKulT|dafo@!vp{^c>>MjQ*<4~)0(MdIrr0l4g4C{ z(;r%@n-nwS-5adc=nXpsR`}ZK*4?E%qnKF{mr;^T%c3W>1%^%bfVcvaviJ2T(my5N zT3m&=^pIXIY!Q#?S%neif<+KN1)A5l?GrcbhVPB08fbX1Xy2rF7|^XU3 z2g19Vd<)!$2yWWwP#X(Q{=^UKvs#!-#X|1eqy^OJa#fZ$mX1CygH)d%3kNgg8?3

    0I!+8Yb{i)rttlnlgYKl?bL@d8 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�n!h}zkVHp> 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�QA;OYv3 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Î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

    Zys`M9P+V7LKAtO9G>ROXUsi5OwWOco$8|WB1 zo~65Z8`^XsDR(%R6eDcD$daCT!%jD0Q4n2OeV!7Wh%VYH`{~@~fXyYmNY6krVJRI)dxNT``P?#2JoWlYxKnY&-PIrs z!sSNaJ1%2XSbDY;TmV5!lrSz`@|a5!IH%XjYT^hH?{%2sf2pc=3spua9U<3UWPWjWSO(d8ESEXA7_Qw3nKSRY0kt5GO1J z-N9b(7n=gTv&r8g|MbaOgi)BM)eh zq)ddLHmi_#zu=)>_UoJBIdL-*lGRQaW^*pf8u3Z!yA=%d4<7-ZYq1Iw&FJcg6pm?~ zgF&$D>9<&wLVeLF9Awx70$pd_0oAZ^d}Ll;SHQB?gYK-sNA%JD4 z8~gmcRTCQ(ak3EJpHO~|V<7gUipD?YYz2gdS+4E&b}4{*ad_*{scUPvh)`G52uWQ| ziY2y+&2+QlH0jY@HL|eo``@n1I0J+{_Q+}~Z>?C`fx__eO~PCer^!k?3W~n{o_E7O zvHcpDdL>-%BbZOx>s+r$7n29MvI6DwwO|7sc^#ne-HNtjphx-x5l249 z+7DO^)HbPFd@aDxv|KZNU6SP)N4cRk3??IJ3rCi{qm-XQoXdgMl|72o?`E{Dg~a9= zqh@egiB~H6X8Hyg@EIF?rpsHSHt%U`X)?Wuw>^xDl}i0mZ`}6$5rq4EEz72Xp;VUY zb&JOHO|${&^6OYK{2Vqu)G87{u!C2>-znqB9Tx^)<48k2nuL&TTa&Ay^FnKf(4-+J zpCwDW!>oTPsb&jm-VYw&Em|AiX!;zO*YPiv zBItiMj^L)whX;(;5;UfqBpt9wWYym$s=jHeWa>{Q%@SI7^p?>O@IIvm?u&r&Is+zc zY9KQ|Or{;^yjT~cK}nUng$9pPQu$H?4lk3zP;LfSD?f0Yo~J(+TkC9oUfaeVB@|*nThp-(uql;gmqi{+JuEl-4HW(QZ&q(Mj(XO& zsIm2Ej_Dy*_~o;eIC$IcH9wViI+CXGyxjXNgngfXP}3aCAY~h!m7)OQ&73{eSjCW@ z>KJl@^ee~}_Ej90`x!#2#sJ$Esb`SE^*TiO3uX%X-Q)doKGOYU=>}93(inA!kZYA$ z^BC)}$tK`;L_$D|vq};#;fNRBaHfXp*XR#@Pnp(c@CyC|O9!(w*K4Bh?zsw6L#tGD z!N%(b1o&qH4NzgNPeF7T5X4}BkTJrnp*e~${NzyB}c$p4YH ze+uLOCt>>sxfW^UZwlYofEYo_9{Cm+stt&Kb#=Co{=>Pq4i4treEUu47A|K%k*7bG z00|_k9yTzDBwo~^+GkC;-bxlSn$8CyQuOj;edf^Pv7SE`nLQYDA7pea;2YjoMwkbs z{Jk?IQ(QINhca4STFYH{=%a-6{B*h_O`}3ax=%Ign>R`kDhfMAt^43lr9Vzb>#2TR zlbIwUfo}LAht#si9l!nQ8u}3VmCj0rA0l4>a1H&Ja-BbZi9fB|{$Dh{j?(|oYfA`Q zN?PU(xYySMty62&?VX6u9XCiSup>+uus6O~rzw1N;Lpc?bl@|#pN&8E#SS&bTeAV^ zweJ|)m&0;oS( zA*eP`FUD)1{vGrUo?ni?wK>kdNO(GPp40^4F&x#sBYgqN1lU@xIU3DF1g>WD#$aQ& z=fOEp-u#1gm=n8)8FO}_sq`w!nGy)ma1|NEqiF*Fq`?)nZ*viTABwR1xZ0?n{R`JN zFk_`wPEX!A#XLU2wx13ga$hZ$w~$bDOIb_rnhPC zHcn?aLu9qcFPZ35fd3-+ph^!pe+S=C9fY(DQy#Cg=u|=1`JbGCZk=R&O6)a=dRqo| zUJid=G^5d19L*DM&NBlCxR~rZAYxOC`hzZD0Yi-0LyDov3s8L(JfDDxdP%9?vkKQt z<*|*U)T1H}v!`WVHrGB~)5WlvF|Y!)o6fv~&DDwSE9vq$hjty_4c(N^czH~gbZz;Y zG+iCKQl@EernUCTIa%%{t`hsC@9zS2@7m9A=7{jTO||bez?k^wL#5H}Rt4QxM|pXr zdQdOirDfJPiA@oVIohmNQ3o(TFI^kc#icEr<3%bMoZ}PT;EkoJ?LVIs;9NZI#$1w8tFEAfTvCworHM>~c#fAl0q*&zw1YHmoPDG+ zrp*5Q&R!|29?*r)9b!9FG=%w-BhsidSzEaobHtQ0c^UU zVzaBdI92&XU%C#md0X@t7A7fE@UpD{Yc^}&^?Te#Zl;sFpY&N=T&|c zMEC9O%0^FjFP*>t{CW68e8MVIXCIw0N+Ky=11b<8wogQK#_FJ*Fkp7%!M1}@zZ!SEnfosKvjk9O z-~iz-G+0AbJz<7$kDP-k9t3p(L7ML>JP;vh!niJ=mLW*VH1%wu!o)THs8OY?f}An` z%LpPuHpAe4(LX?AxDR11%u1_nGennfkz7ccvz7&bubSOJ{k)9fImgi2nqmoTnS<*Z zV!#1e$3)))7znXj81X02!mkGy9RsyL;C)5~lrUU_4JbhYe=YpEHxuj3NA{yPvwsI{ z*-$S5#p$EHY%;>_m--V|bL-MM$?}=K0rT*8@z{JYT>%kpDWi3qgT-~n<0jD6J_A7> zlZpvk^0sUTL~o})UI z*cq7Q#Z0jV^TJYW3}a#|EfEjG_$0T<{TDsY>x1%?LOP{gtczY0w>tu(;{6w5wqzFA z4yt8m25CXWco~%sI*X3!niBFW7M5)>?bBuN5GNs=oP;O)Lb}M$B5Md)IZE0)iE88h zpUg;7lgW$6CJ)-eExs_?g2;ZRm@Ona__5B0R-2DF^lc*$_|)EU!@t3CT;opJG9yJJ zEP-{$XcTo)ydb3vTTkOqC^(n5Hpq0wRuLjG~Ztth$L~a8!0aX`zDb2!^ zI9wEg;%xCav`L;d)T!X*rX9-)g;iDF!I5#r7Zjz- zkMG#^CvS>wcQ8pV3Wyq()b!%PaKiL$rK&9?*(%vnGz^a8(v7=xCEsVPd>hF!RY)Zh zUz4fR*doh`SLJ1jGdrrm>ENFZSy`-tt++bRE2YS*6r2Udh#zRPFXi(XxqRJ@r-Ao zS`+L9QX;*ixdN}aPT^-v_zq)6O2JOnhNA37?qn$IdYVdA)>TQYjJ{pm=7z}RS@-(_ z9@HyR48e>0Sg~B9m1(y1Z@QX`wScX?{r4}E$Pp$D4U(Qt4>M}#@G}PzJVTh{L5;fN zM#Ki62HX(dLIN2?S^DI@wVj$KLvFxq8Dwx?Ph}WK+=tssJqA%hcWm*pWwwa(DLfWs z(3|dEIOwjN@blK0JjQi*HojNb_iUusO-v~w>cf+%CTyGzyB&?B;`l*3&BJxq{BZwT zg+Q=)uR{2kDda231q6n}fAoo->|(|MS9a-*70!O247En;eM<{-y7GEcakXz5+G?VhilAHf_WYGuXG<%*5E1 zL7pS9R~iL8w|e2#5j|4oSKtRpjrq~1b9>Zh1?`2E_ztBYT?e}mlM(YNk5(6#=70_M z@oQwk39C6SNtJ~05O$Q6D^=~JG|zqtof%=vr_ark!|cq+cz|?{4>61Zz5dLf(>e8k zJ1CYQss;&g2YoEu{*^oEPaC&#fcxj;{M#M$w?(iQ!J5W>&!lqEnx=gtVl7O&J0l`z zU9Y6Rz~bpCm*F;{=!so>dMXK-W?K4Wi+9dE>Bj-`D)wSAvq-TK3{0(Y^^x%1kxUJ& zJa2ljA&4ZKF*vU+mTx;ByI@^2mv4Ywu+5upRSG6cd7xfsptzRf03@JVFuv55qf~PG z>UgB$YuNxjg#=Ri*@)QXh7%bftCH_H(SLFIE5A7H!AacXVs&NDpc+O zR}jIdkfeM8FcD<;{%;TWDk;t`4KNX$qgNrsUdJOAbk)NXx0a|5m;zsOidSUWuEKi> z`HR?P6z(X2Z|)i}$pNRh6Ly6pp$O{?S==vx@|UovxJ z)w0y0Q?ilr9-rz|*=uuPD`O4l5i0lfx8tmkr@33u?SP~ZL)b#=D0oAAYxfueJk*^z z>>v9WLv4L)xuV;$QXxSepZd`#oB5;J7E&Pt4aRN_F9FYY!!j=3Yd*>u`fP6T0x*n& zZX!T~rstp_VBOX@{@Q6{Te+R9aLruY*!U?IQXk~KAncqU{mjFg_+rrnwGB-X0G3Lc4!+1Ei-abzl5>Pj1d#a6-P60{? zk$83;g9QRT1y^LyN-f*;FQn}d!qec%UB@W)>_U8Q$>&K$9dAt;a!wZEQBnEF;F_P_l>0%c| zX4VqqVqU+DsXZn73t^CD1syn|zms)a_buiDOdUFL8-sS#=%w6pN0$+6P2<3G!m@V~4fDgBO}<)JQzD+>3GW%3z(bhrlLD^i2mARCYGcF${dI~JHS3(2lX{&@D6tfY4SZp)p;vAy*BU=cynnH2e2 zmaJwbzXNBiBYqLVq*28L(SX?KQ3PZQ^ZgS{(RT{KHp;I`{G7aBFGeU5qeoXSuHHFH z7&GH?rY48xPaZ<93CVUwDjc*ZUp(w!C~6%gl(9q5J*H}_iA@Jg^h9kgsFz~E`%N}C z4aOJB#;LUTlt;JUVAAlv^XNuQ&D!{a%2Px-;{uBv2K@iZ`6ir2~CI;0Z{o;Snc9WhG@%Hzv-j6fZlJhNA@A zN!~aV$JV|0c)LU6{kFea&B3zppz5+48|z%tGP5Uo&N7I8G0WTWTz>3;zBwKdVbbn2 zcymJsgn6s>>E;yS{;G)*esD@IM$6x!pv=AN^teEWP3NgR`N1~_QPiya;>oGy*YmL6 zCk@NPk)nt-l44zNqn}-R!-6Lj=C`w(a+86dv2sKXvsVp8xM9!x-&BCmBwwpv>6Llu zeRxT;Msafkaah-Z z6)3>Js9}NfqCl(xmh&x&?46`Ae@mn|#))hlPyTl_-{gcBg)CvsY4&UsoFL;o<%txP zB8=pHf~Nhb`h`~Ia*x5;`fL^|K@=C^6jG7(PrQlJq$W`?!on!x%F_vw zKNn>=dPXKoLK~viB`>)5TKKJv7ZiyrR+?SnaQGUsM6QY6genHSQi-KrFY=M*6onh{ z?g*@Y@kK2#T!h{USht{ry@{~M=ri_r$f3AG+TOwOoKV_J%d)>fXC&2<`iJ7=&&jbW z1mgoRSXGQ&>)c)I9j%&{@%@`6dqYcBm=<`wu;rbRG>|Pt%hm2A z@l}tdS{)=A3DMG|E~v{-AG_k8-P?4ov!(9W*XktpCK2Mmj#7G|fyxd+(mWY!f3@yG z4Vbh@X4a%7EZygjx?g9$*NyBvwlNM*=E;A`X@(fy2(Fy8nz(6p_1Lm~Sbq|6g8zX} zd(3_;5*md%Ec0!+sR(h>-WN|+blU}Gnxpr$@llT`8z#tUQ+0i#AL*W9nmuiT*?x%G zoqX%vn@o0}N16+1rV~?MEGx39cQCVO9IA$ynxn<7U3yMzXVo;eLRf zc9*C6F@Nv&iPTeV%^anx1{EfK`Az6iJIMKbh<$q^n?`XaG&N=OLwS;) z_9P&PA@5tFq?-fH$@Klf*wdEVlbndiyJ(qA1H#LT_CoIL@t*M*zLLe+MIl~z3Ap6Q z->SJoLDcyNsp0dZGd&Ym;w)a++$5W}oyLw}b~NWV*^i%%iUgfU>ts*c*X`u%FHi_e z3O91ak6AA6vNBV|ef)g`@Az@jqgn-4g+s{t2~%28}ss z7))s4_=cXG1jc4>3r2yJIr_?pIQ5Cq-WG2`Xly+pcYVFzZPe@MHK<}Tflesp0n6v` zXYuTyG}8{vd6?BC`z_7JBpCrpHT(Tf#WNq4f9SxJTs7crK_elkKLe9rZ>I2gESJ0Cjo&^eyVcG_p!Yx<>g#$(27x{fhT?-m6})(HqH z%-J6nXf@autCGton*!mwZ1|udGrX`_Dt8_whZ{5!RC_|Bj$D$BCLL@%D1Z2kyOKmz zkL5{KAbjv0PmH^)nTbR0}zcU$;>$a|}xI-_h0cLO1~1b24` z4#C~sfe!Eq->R(m+c|XiG=eNcf)7<}a z`vSicNXj|@xCToF2&4u&1^K-JjkJk3{e)HtLvL&j%Q^U%CJ&k+xOaWJyl}6B$=h_+ zH?-C_6;|=;zjV);u8#T_zG9JA;XS9LXv9qG!uN-{$O5Q&duUrn$MnYVu*vkxXxu+%S1fV<~GCJDp0vFo5nSADu?k&04*{!sW^ zB~i~KBLOX(`5nJh*_$Ih{s_9WV6?1D z;c}Rc^TM9QQ}@BSULYsu`2#hd^`&ZiJ*=k6KBqQfoG%U9Woiyb&r{T#5LHh7W%(@} zt&pd~Y>$9<`h5wb!KfCimvb}En+F-cWlG){Y6C4v9WwtIT36M#XVnA!QmYeOcG z!;=cJg$F~YdBhp!9%kOn)G#h!SP|7zU1!#`7n@g#=Je3n@?b)2Q+C{|GSYg{pgXGq z*MWZC**G7^GLnAk^kxh8=AN4&Lyoo+Xe|dmIcUgwC z*!}l9g&D}L!nVpAaV$DK~& zvs)>vIzTO#Mv(h-wWAkwBJ-YstJd_HxOSoy~I9A+& zPfgDqI_`R|K%jpnF=u`0+?4? zSjxE%$)oDBi3J?lLLWVyy)^-C_Cq^EQOZ&!QvM!qmvb{;=Zb>8cfY)F*Yg<+vwV+x ze(lJrNM6pQg}gxQB!`$@ihLRiXvX7Ze_47`2PxhZ)l6GwW;6Y1p7bHSn?E(r%o+;^ zKi3h2eS)3rdkIe=DZW&H!YVSSAOf+lp%kAD6Rj3%7(TP=#6sYVNz7EFZw68`UZ@=w zfFSz3o&R+KbqGWy$&9V@E_1%)PhHP%D=uN@2?p_h!2JJrFYbSB$^tGGpVqdrF3{s# zIukJ5h6qPbhqq{5_38@K75_!5pB5VU@Y9Qrf}lXFVRacTOrVB3cGSYal$-(hqUzNP zd{GsEGLOc1fn+jLQwK+5>VwB!M*8AxH6+y5{I}xjIpMyhn8tl62?gJ!LIjlcK!<<; zuqP4h`t|4H>$F9bf5CsY9^Do10+I6u+=Zov#B1f008XTIq#?MLP7P8G|-zntU}fM~p~D zj?s{ZTrC?X^eO0guP-NIT~;5V`^!#v zpkB)^8m@$7KR{bsRda%JTOEjgOr5SG2IZvu{i{MnRr6d6_^Hv=3qY;y?3sPU$Hp=je;(G9@R#bRdW! zp%s_p7b%8szqh`(GO_v)QuEJwEx?EwRFhu8*yTV0su1v(D8|+HF$s{z=WYCEORye( zzRa&>#4cGH(yEnj+~s&-qJlagDX(;I?WU6zz|n85##=ZGThNxI;m^z3KTSwFTw~&P zqXd7K4kzjninD5gLN3+Jji|5>jq1kbx=HLg>vUUwv>_LeUQool%YZyTMtEjeSRMRM zDy@HqwSpD1K=Gq|@Fgu=RR$RbY71JNrV&{MV|Sge84;qWhllKBH;0#Ku@H*>D*XGF zp774D6kAWtAbrN7!xyvUjT_-EnSM5;?T0oE&LDrIn;aKANeUA@ajU~dm5BxO%&^bb zNY^&8@lTW|6t_bU;Cj9aw9O$9YQjMZZ>e8tVtNJ9a}KUAb!CaMWm7+%{<_q8EZ30^ zG~y}Iu;^xUEKw+-G~5F%f+=Ks#clLjGJ9YzX~q4VT!mF33}f~E*qHH&CpI2e&g0n9 zSDXCg(D%*mAc9XFtd;&iaMKy|v+$SPC+4Cov`xnpzm`HjcArMoUkyl(TDQbX0nD~^ z{B?cr6Vb|NpIULLh3155rh5JBU_UXUTy_c9HSb=QZ5b$gCCaCh?~-Ho;VC=L#8=IK zCzZeIV?w&7DEVm2&yrGo-h{)+$O=XHF3=xmx)H!_vMx`{#Ou-PL z_PN->qsm3~>aGm2W|-m2&VbU`V!g*(b^;9SRFE>p?kkNiRVdoIVW=UYpq?*DW>fs2 zmsFDQ(OrdQG#TC)lA89ypq+ZqT-HTzULD_W>L2)IN8Nu!#?<0(76XoJK*4UJpHm6p zlzFic&i9BYUfZj@Vw8+A|1JCoe%h5iwaQ*{*a|aVH99C5xc?T<`)L8-6ga3gwjmmP zz1Q(2yx5zAmpao!flCgu!YdSCo;@q$QHRe@1s`Ai>1`$Jxo>{`@i4Z2b5Vqx?0l3)4kM*q}^>(CF`GCeYxjPi2n)r|KDx7 zeK9;TmehaF@mJq)j`#XL$nn{)PzOp;em44@9C`up#|U z>&u2*GOyULoMO$0csS76qQF*vp(p!AG(6qH519-Ayomm< zP5vLgTty&+`hETxME$AkY5YUkV+&OFI4#4J8IdG58=MeV8;YzVsKSWx-uX@ z&7zv?ZNI3DZhtXZKR_jP7*nU$4s#+`f8f^OOVo)%0x+17%6ENHe9@JG!p}379LA&2 z=~nFEd-Y$M03i72t}eaYepQY+>jJ!&mR!>N_1UC|;qJoNQly_h`*rmg0N(-Ud zjHfk`vk86bZCkNU{5ID)go^(lD4uX!2Z<&}jkP|CRZMu!cZ&jjg54 z*1<9FR|$L+&!z`O4)k4+ zgi}Cwkt1;>z2HU@a5uSt_>Pt8>|i4i+{eRgHw+pOQc#@Q2muI8{+5-3xV;MDBah=2 zq@jmg2RJWv`u@AgFFt6VH+mdB!%E8rk8+!0#~g5DnLy^+3FSG*Z7qhzDq8+kd+Hc^ zZ0qPH5eH?$^Q-ilou#`OK$MomzGNEAv5koKqx~M$eIkD?^rmW33+DM9$EGGmJ774Z zlywU?`~*MjA)u<$KU3<9G-E`-<3p}m+7}fJ@7kC?n&x;SIyr+WaqVnFZ;(X=r1bAD zhaqW!9Vq9dhLg$c=4}oQw090_(tVdh0(snA_j>uzcXh9ecHcyO3gLPIxq zHiHk2ZqJA_^b^cHTd7xE+a{^Qz?E6>=Df)qlC*~g)T~!B{IN4bUX)_W6jv1y@vv@- zA*DT8QeT8qf((l9)QhWSQld(ea0QaKw%~sYd$?T`IIt&I>dYC9PGxOxBbt5-dvKDp zQ>I7vnf>D}Zhdx|p6MMlat6RW>nCyjKa!px3(!G#VsdHPl2#0TWX6P_N{wsa$e#zX zUHD6r4|gy3sb)tn>_p}b*yJ}vnOkd%bDMDmtVxc5F z{1Q*DM=DthlKY2%8?)>(jd4VOK_<&d@1?Bn3rbt&TJNaLf$vMY_?xCnVh>DxED$}N z;OGzygk}+Tm5wt)rozQ8!P#xE@e!P3?q`)3SW{D-*mw4~2qkNkNBG>TMIcWqzpv*@ zvjsau8s=dVNBGtyhivX??dkjRY7JCP=Taa{4dlpsF!sJiHIX7ilAR-oGtlc+O2$*} zCqqsIY*8K>?~R+zd2+bw$C}o`CD}6)nx#X^vE8Pp?3^-^9_lY+422XE0bH6bER|YA zq6l@_+*0+bJnYf)XtTf7JrBd1%X9P4eDwq;G~TO|;xONMh&55*rj35B1^xU% z*fK{4RQH4tl^~dIy{04s)jb*)UTl@$p?g;16;*<^AmHZoou+V74RSqounFgh702NL z4<;w8{I5IgxqXWTSYs8d`}OY4rc_=NbZQ>+kc=^;PM=l#~BI zZ}hFZB&%(y_)7a+zFLU%$s7n_IR-7M!949#U~^mG{xCrr!qHCK`#JmUQH){$xbP;0hx?^t^>Zizi_1N=E7gwLmCY} z>Ul#iu>mer*OSku(UY$3PRotpgZrI;LdsOsFppxM>Fn)%d;t(t_Cf7gmyRH&FL97= zFc2u;=kYMfV>8Y$_K{-y)&r$bYPJD!{mtE3!mKf&*`VHUIrzy?335_g)fOf^$v!on zwJXF~v1S#uy1CfOOOto(ke6<1%-8`^5r>iWa~LeLbju-`RGD2UYs)w(547{eqy~KJ z`;p~-PX;85uB_{VGf`V5@5z9UGci*lbHt*#jk%CsUVa17wKc6CyEF|+2sKIdij1ai zyf@gc08Tpmb8=Nu@LPaE8d=vM9b;HHYD^N-ChQ1NkAu<7YO${03_1uW=C;`P?Q5%3 z4EWTk;H{z0IoYlx%?0b)-1?QSR1Kq&qdnpZM@3b6v*g?8A>b0tJ4AQ}sF)Iu=E~JV zNC;X1xf27y+z}RBrdV|<1OB^>ek`b|kHuEiP}{RVBz_der@*AsCU4z1uRNKSZtfSK zIo0WOn>C?*Zepm&8aj9uQ*h$DEN=vN%cv@XcpAz10%{6((w&VExDHi^vKn$UlkTM+ zFmDKblnT8ESkwEuEHUf&D@yLubZ`5IDYSQ9LG@%kj@-_c9yRXHQ@L+|nIdt`!)h8d!SE>I%g+4BCrE*!L{3;4s=(LWDH5eHceMg)BAG?r`Z0kN%#0? z%2q=;J$@`av#;jvFNgYI3#dfSEdKbo<7v-pG`VkwFJ&%Q;+K4cO;4m=Lc1PLd;TC$ zRy;g)H?PgS_u-YD*E6K%J+-Z>dW$CLv`Wa+ZnzPF3g&?}`;*@&4q_X{7S(8+SHIWD zxo^5VF!{GT;!-Q(Z$;X6N{$f4+($+1oW@I|dYu+ZQZ~EC{;C5HDhv~aH=!PR?g+hU z9>XjhrHBMo4~CLpEVZ{wbMh;JiXT<97%;i;)17SiEP{xUB*6 zjg4la)1~NMw~q*aFTuZ=e&V8l*niUK|AS9g;a?Qse^B`RgHQMWqmBOW{GEp>7EUx^ zqp$ftILU16Or3Nc48Q4{=-U0cAot&d>T4-^TOb3SWLlN?Pup(JhTt4dpFbNKF+|sa zi4SlzH7p<0g?@d}&kjAsF-YZGvMO5^yJ&H87}bM6zz-)YOb|BL8@v!*!N*u~q#di- zNFO3Gk-~0(0@=iA(h<7Rg8OdkdhfdKet!MBvhR7mYTr`RnF+iO7KfRD-QB z7_w|ps+7|!N_nY6Kd~^nCV;qCX3VgvuuYVt=Q(7|kl#effK!8mQA5SSPz@Qev{q%wHav4h`geoFf zmLhZcOJK9pybHr*@ZHdW$#|bwbC^t|jVSACv6(SB&gf1T=aXshW)ib~eVuK$Zj&E< zHwsP=vX|gguT()w9EW<%nmdC#J>HgX6WSdY2JFQpZ9t1l73(CzI06?AZCVjVgG9n90k%ZWc(WDfFdWfGcONB&NzT!LYwN2zht+ z(!?ht!y9#5C(~NC=`Lx~xc8?%R)#@jUedsfY;)J!s;y}cE;lTqO^+%p*|6xTUXA$Q z@K6^ncaI}@6lR7UR6gP*k(Q&4#41nh-Y}8Ail_D?`~Y6D-Bs9kcinI57&83f@J=JT z_!6D0lg+xc<#Zx9Gf24w`Bs;u`yf+?lN{1ZXv?(9?Xv1=-xF54_=)VYc4qeM=(WBLtd zdA654DVH|nJ#tetNHwXpzp8i=TH_06k!9UjUU^g3ljp%fnf5g0+4g^(5G{?H=C0Kn ze#dDQjhU*0DfN1*lMAPDMTw}ImG*5D4ELW0w^MTvqn+OIqzl|~PfS%B!7hcVi*_~^ z_eDpq(d?ai@XTz}KrzLXTZ_V~!*?EJH>&BynUlZ@)@)Ga+1%0jMt6b*g(T_ogllTQ z1K(|$Ja|}{pVEV-mO@6`UcF%^C59a%f|y~7a&+lK-f*3@*GOXT?)}ui+3YbzhUu=l zA=>1=j{m-tc)MoiDc>Bv4m2hrgrujdFSXilohQk{xC`*+Y4T3HXmj<@&$D9PVzjhs z_%Oc8mE73P_j<#hOpdbCGvQr-&Ab!!11pGAle_^~#mas~uq>~s$u7ni(kLoP82dV> z{?e19o5gL}H->6zqw4#q3bZ(;ziq>d^G?0N^hC4Z!~M2=c`o@RiusaPgH>)L@GiUGVnd+{Ly8ER`vS%4ZSB3 zD_k`TBRA>#S0(*L3+gSFrAtqq7O9yQ%tFiQ!p#NxFEN6#I!QP_M6=<SDFevG(0U3KP z?(VzHQeIxD*8cJx!nnrgj{FPqXA3tiO;)krpScDs3s1X zQC5p9=*q`Cf8=8~ReD8J88!Oy9rLTorzcd?yrX={geeNLtuXCor53OAzTO-;YJ~QL zs_jZeE1uaPIlL>Spq7sU=Rtz2C?_U6B8s=48}r<(#+cvj{Pq92z1L3*0Lv8Nl<2M<%HO5i%vU$4DZDIZf%A;Kfs+`n}ZXwL}AVR63(qww;Itz#c6 zhG8kJl&_rubFsR6NTby;#%XzRCv-OI${2M__YR}0-yuKMnC(^gv+vPh4TVnZhSAz= zSuf_=r@M5@x|Q?jR$xmXih^PneF)0&(VbmKgu^HtU8Vy+It~0LZmbNIbj4;~Az1_~ zcwnL+zfWB;0xHNXhyQ6d3Jbe%)X_snU+H3x8U8U!zX}~*GR>~^@#RMxjm;>-&L&Bt z{U|pY=f2%2<9M{1PD(I5R1N+?LvPu68Liv^jWiQG9-RR@vA|m}S8e>yI^F2bCPkK~_M;#S%3+#)@aK0;u={tt{I&qdnCG806$b$e^ENwTzr4__a z%mi=6V75+T}*e%Ch4FP36EdPU(_n)fpA1eQUk*}{6#UR_m2OH?@ z)fcB4TPN5fN0?B>;7~dnQBo7xFD{#Y7CkWr*y`LiZw4u)aN$jBbDQ{T#(tC)h^mz>nx-Uo3xalMGCUhnA4@pNMy5)D*04UV}*BU@J~ zbyHjcNobB>X?L1ewWJ~_Ll52cJCJ4Ak*}mpz>FjJM+^XS`1kM0iY6dw@p$)YlvQ)p|w3%T{yYG(Y?Q*ZUG4NmAO)Xa$;zbp;uv};BD_- z`-tI;Z(ONioeXb$f{)?{wa%j0ycmaF>)T=wqtyvFuLXY8=H<#5?9XCtH4RRI3D_>0 z&jAUlHF^dS-$}12=s0=1!Ei7?8BUnUp^d1z9S|;bQ3ccp#?!ceCvCL((GJ;_S7t%6 zuI|}@mS1Pn^cI)p>Vw4?dbGT%;&#~PsvcUyXdW&oH?%&-oL@Q%(W|sr%UL96t#644 z&TW(70c)?VK16+Y$>H60hbTAL)wAp&@cOR2Shb zPD8(QN?==CoMAk;9=6mAGf5(y;~q2`L6g9ueFMtCg2`w z3hh{`J7M_NEob`1y=~8J&>_B?_#>UQa@{Y4G20u9h8Kmz4pwa@+{zUF1M}+}97TKA z^bRBi;+zeYK)f7k8iy+ZXOWPgOAN7iBa&p)p4->cy;SyI=ClIRahpIU&8=b5H_EKV z4JgtiD7K_!YKwAk&ZR^^vm8N%L@z%@cE~qUy&Rtm&?S52F?8@T zOp&yDvvJk0BFl{uDjb_qlo|Tlv_s3uvPu(fxR2@P7#)wAsilmSNb&S*@iI+DZ4v7v z>Ap3JPm(f2#~34vqR78^cQs85^hZxAD02EAD~-sK_DV+=O1uVl32e&=qE=8t3qTnV zAj*4@z`z&uqLYn>+@m#yw8CEF?(t+V%wn3r2eD&c_z}=Ti6qx3x`Fy|m9@`1x5dG> zwW&qq`-e_o)3fLGiYFFl%Cqja zOH&#m--L8=M+DfGs=iM<-#c!b+1V~9hVp*n(e_|?f07|&=R z&O^A`LTr5zJSo%K%3Q7!e{&U>6eL3}zITNdY5M9nj;rIQ@v&GWvWMpueYF@|(hk*E zj%$h2Td9W3N#E#JsUEAmu9}a^{T+E(>9(t1LId}XkhiOOi*+>D#{Z5{DVUm%{U(j- zX`?@Q8j&V|6xL8n_uI4z?}A9^A+Fa~fFs8Z&Mn{9`znDbVh((0fF4-Ew|BTQ zC)hHMw?7gU+JKdoah#>#e>465bEW;;SYQCGvcJ!NtF(VjO`F$t7u7hcXlTh5b*>k9 z0E-2+&ui#?i}f{aV0;B@G|4>C+i7-@HXL=Z~KBg~&0YIH)+bJAA}8BI(_3w90ycR{N>`Wx<8 zWh8B7qPkJ<0n^phQS%5ZgYUlmJ1Hqj0Y(h5o;+7q=%A*6&D3$cP%5VzKlB7={j-*3qodx*4$YvTXN`|=kEN;Q<}J& z+gYG(>l;TeVn+Qjg8MBym?w)k!oloOefhqk^%V%nae23!7w-}B11)eJ=(j$I;D=TD z4uk=>B@2Dbk>r`O5?oe}AkJwZu@7oHCp<%ow}*YS=YJFYlSO;Z9eW>ZnG3+j?c9qfIW1p8 z+ZBZO^L|?F<;UcE1Hf!JFn__s`2SG6^au ziYxdMdsFW4STFYoE4ZGTXPkVMX6iN6`3y2ANt6+8RBjA=tH7DPsP>cn zGUuSPhWE?#S%+N*2&QK`YN2IP$^7_yp2+d!45f$d@!lmbFcHx7gLbhzT=_>wWySZE zyfd;YZV-b92m-GU9tE^(jc&L1V^4uc{jI2lm67 z%w!x*0$dbpM3w^>MikY3B&@YE9&Ev%uHB%&MV$V^2c|MmTold81 z@1F%7oh`?7z)-ywLL%61+5nC#kGHm+Tz#op_fAd@b90mTe8gc~Jxq$n;LP3jK)VV1u0OA|pSR1XJf+3}bmTyMIJ*590bL>w8@e;k zkvL0XQ${1Efqb)x)VCjji^!v$oKvprme?iI>LVnyN{3I@mU3gi7yeKY3|PZh3ENj^ z#?>EUcy<6r_ABE8s7!v@`f!-k2@q~?5HDoPUT@}}5VW{G5!RgpKFs|Dt-`z-WBH6~ zu}|sHWTfO%MUhW(Dl#Fb`T4usffMq9h<#ZcnUq6NMm{oh!S&cZfMJJRk>_XfjUIQ} zgc^}JF7LvaCTy^rK=Um!eRe2ewp|$=30_<;`oP8Z>BA-R*7BRDIj*7W4MG& z^W#x+7aV|BH{y2{ZU3c?S|T_&D&uVhDt=OO2LGHFd!I&e=U|qt#QS{6-2Mk(4 zSSI%1&HRbzFN`ykMtnt67G|7DURtmc50@Nm_Y;a<;wM4H$Y73o>me=#WOvk;YfjHX za~zvBh;YVI<4hST*E>j(tCz8jVMm~nuj)$cNyWKIN(kU5x!<~-8?J5h#Y2|%x;1np zEJeo%`&8bu>_Q9iCU?qhvyW{$iJCg;o@K`rMU2?{(qXaBs9>2olKZC$Ex&rtDhA&_ z_7TwG$!&Q?Y=Lwh@X~x-ZeA?@oEgzXFms{N^b|Bf&$kUyPHo`eG#910oANjtL`}Kp zR_I2i>6u_yfu3AyaVrqiyoY=iQTrE6Md2xN^pp5_*%JR*!IRVu<>7h$E4{WNWJ3REcX6X;OVecV&|F zg~oT;PZAhbGD4QM6@}J$%CdcGW2oj!hAD%rk)owu!%IjZhTXbD#L@b%NlaCtbZS+K2-y?z&%=>Y+%8vs;lfv}*;a+S((LLa z;Z8?JpMr`#KRvF+OvHa&!W~9r`lEyo`N9^-`Ix|ePj-Ou!WQ}>(wUM?ZIz=I< zP|@R~{ZhVpTJ>x7YO;@uUzkxi<1a^pldVjc=PsMwfbNd)8#u-PJA?ZD5)kPMlK8(V zE&sf8{`XzGmP)oJKn=EclBV7KPFri;r!PP0Nqqx+HmG@6qLqt4{+#NrluYA5?;xh=>l&I9q>2D3A1~pJ{zu zvT|>`f9|*kHvR7FtL|Kl1nYZ{02yMyL91FeC?LMuSD41Lf@Ued!2HxW2BTWUKPhc0 zN~5R$ly%P=Stk3n6ha@dP@i&0_2@L> zSl?g!NejkAw6-jbjK(1qw*VRPY|Z^6hOsSss6Hn(mNeDsnvv~3JIq=*?7|rq#tL!p zqf^E@$|eX!>m()`f@Cr=<|<uaJn_Tcn2b9-U*iFZN85ACrl@qW`~=Q2%$^1jV&|_CmQ?2HiG#Xg z?m=-7;9Q8`|3T#Qk2^^r#czF@uBD>8MguJfN?ML7)&7Q>#r`UJCvYo5%;wYFjxQ zgoc7n5@XdP->5c~N!jXII`CKhP^t$pPwQxOFrhp7C4IavdzkkM8q(R zAF@Ij?7GKa2<-1<}GmPIx1+OX_!-fiqsgqr+jXnzE&U&J_H z4G-&wrccBv+Du7|*G6Y&+{P$!-F|pdHfucUT8K-+XVW4$2Q!mVhToO*rMZ~Z1PLl$ zT^)YTTcHH2b970@Ow+r=jCsQQi8j)^s#|uAF~@^QVg%xtMTQ?d#L;buC#|9-$?#m3 zO7vMhMRDFZ@TsW<&+Nk{wlIGwoQr&^j8OP#2 z_6rZttn~)hn~6-O{f9vO7TV<6-Xx%-;ca-NEN(Q zILXCAv1z|NAQp!Y*S@W5AqOLvWo)|Pn@#n<7`6(ANLVu?R_3(tHmk1~wx4d3yCI^w zjHthho0Oezif>vFPo-&VjHIk#Ods_xN_i>9+sGnDIAHBa*dm95R)LIHJIe}$42rAmgx$5r-@52yD@9e>VA1REJ{r^Hv9-nh$VNC`wI8>`udykZ|XOP zjRAXl*8gKq{}0yPe~I|pt-ART1D?71#7r&xiM$kqh-8xd;6rH#)wM2`((PKp&(OjV zcUKpCm~)mh7BM{~Z~CTcdk`&PHc4h5{feD8XV^{<$Z{oYdHZ-zF~9COIK)c4@BpGd zJI^sS97j2iqSH~S(IK9eP1UZ{7%b~4SJW)$$Tg~Om3I_Mp!yEledobP^c3a9*o+~x z?6;&QOwDv=pWbPu6+#)xO!?4|sSEz>Rxqi{h^cYj(;!dfDG{t``)p9eH8yj&U$(d5 zXPT5^C8#$=XUR`TZL6ZrWw50{q82fU=2Qg7n+98C|3N<- zf;6AFm%f%w;Jaxs{i+fc?_ezZs=HS1#@$}~`t{21-k$q>pxr9UWwi`k2Lps}W&(f- z&_VXNNZyU7j%v_R0xIKUC+Dc*zmnbbuxfW|?D3S_Mk&BOi4^1ruWqa!DHe?;9)5AL zOkl4;op^Sz)K6h>D*Qmo9}WUwsY@l{(?Tf`AmMua(2yiVs~n5doRjGWdkVn^-zEOh zXDoWXs;@|I31V{da~>3=WT=Hi=MZoFEQ!dgQWt2;B-eIf9hzBeO73*XwC9C>HZJrh zqg(!-wXAW~ctNq2%MnEuiLAj|-5;O;s)5|L$qXcI+#Yw0%QgM(=Nve%zWGYz44;$Q ztr#G~--u<3TFt%S(LTzc+*19Rt9T^jmfb_ITY@9v5f7&QzH7=)hD2I00p($HktN`h_DTzcZ3OPv}Wq*Cw#5#Cx*`k zrZF?$_HR_0p<}#%n$NZRhdzHuAJL+=ZS{HmL~w>0Vi?n8T@LQPqyo~cNsuVC1xX^; zTS-){*)Caxy$ss_6r!04*O_EDGE}_iz;t-P9F6PFW1JmYg(qpR zWb7Ey@H!H%DdXUxaQa$j$wiE@Kny#_CpCHj6NJgSIatDI*1sW=stg zcvoINP4dwqc=;i}K;;AcmGu&QKUk3Rp{QLE-jwg~EN&hKPmnb!5uE|95-BVXVvywZ zhBQbqi0*GC8v`Bi94F7@u5KJ+&L)Y+{4@K7Xb<-;4;b3aNy@Z9c5uU7x{x{RtY&8O zFYOY~s;GwRT*lJd*w0O6hSPFHFxE^->X!HLGrWs3tI*W774-?dw-P#?JHs^>Z%3SI z-wW&`1|RY~%zWFMJg=wWXSZ-%87nnc>+O#!J;>Y8_z}(8XjXNLjXA-~ndjOeM$d); zeG8&hGOMWQW1JICrZXA! z(9{qd$mOVOex%A?lN!3$-jbf;(?XeXgx#x{Z9I={Zkn0J&Qxphrv<>>G`$?Q|l)M!ZtSAqtYR3e|7Q zZv~|Mgtb`;i@`tsLis5x?5)gb(O^-xEA5XM{k@SBP3P*eq|@uQ#{|VEbHTDP)W4!+ zvqFCsAi?nfUA`v59+iyLR1xG3x}%5&qaOrRp>$Gf)L>+%?JqEaB0S+2%NQ@Gi_yU71qb0-{0Cj%9SXm8I;+5}YY$y2K|yeA&{w z@{8yf;<`L&(0t%euo%2SkM*hm4m!XG6)Q*PMvj&?b+eS1T-l+K(tTQuf)ANvzjOGxTM7mRhNK*CTfH1iWI-pK4UdTNNoW+`u8^7yCSzPW2E2G|0 zZ1bclCdb~%M^HAOXU!88uYdCzE9^|kFEYx)u05<2gq_ArdkYcGVwqHlyYZ39 zQ(Jb^_VB-lQME>$yMAV<>~iLxz3iaspc_9Ay#T>EHm!{;9Ls}`YjG;>=9!IoN>4T( ze74%M(qf?M5Wx^>oXH57z?=G}3Pku-% zG2i@|2g}Ke`dwD~0GtD@I6l-7KEacDW=Q{BiKV=!OEL8E^_5rRy1%|B+zTGv`Rd5? z@^@rHN#@maAE{TmpI6IxuYf>^diZgj^Wsq1+8d>s9g*0M1gcInnk=IOjoKS#MK31d z2^X7)qFaTAsPoIKRh;#-jaO|NfIuMX<;Q0m>HHZvo`{2@*t$V8W7Si*2BDofb~yD` z@;0%q`jsz8&b7neR(t(v80e6~`z3&sA29ex!$6J%LFh~5g%tW&b_FY^#en9W__?F2 zIJSQaMkKJ}u4V-ZCMD1A+GLoBqrp%ByAY>PYKal{-Gih5FO;8t0Ru*j3}?9mIz>y^ znEA_SZVz*+6$X^$1EFQ;kaQlaqB1=DUMD;9Ax7g`wq^`M^8uNaVL=S3uj(LDt<9tu z4SjU>Xmh9<^&{ewh+UDz`$La0O!^4&J-}5op7lm2b5LW5(-nir`A(8Wk|PSs*-iwesJ_w~ zB#TE?Ma(2sd&LEe_n8aKqt$cNw*^g=@h=3#QH%mBEf1C(dj5mItQQ##+m+g#D)7py zdb6aqV3r#rUq7*fND^Q0MVOgL%8RnxPH-PtfmV|EfO;eJM*7jQ1U@TQKE9Et=fKt$ z1R%ux*eW9K{@>S|B*>)O< zc0i2h%h2p_{pON%fWxj8M!`KC-B3Jm49jUQ;~WoNU1$^t!;;2Kb1No)+oa@AXhseV zP=JAU+>qYgldsBs1^;{X{XG%D8%&A~{0Ef(9~{2_qRIVd(GNdnv_y-ej^L5V*Nn)1 zD6}HZ9eXCZ+rNu`YVFraVn7Rfx#MeE2$jbp2tA*Cwv*7A)gmQdX4IJl9#NR**?0j_ z+;BKht&LHiGc&(QZ57KMpU}sy)kHp_! z_1t#K9ExxHjVRde3ot$HF)7`z6?JZ7o;naNyl=$~f6rfjQSrCthunRe5~%q(UlwR= zlf`=4{X_E80KB5?mz6DGfwRDGU%u4*vp_<_idKOY zc*SZ)0vx)yda|T1QsrkV5|4vDo{hVo)Ph@5^uO;YTNU-T;g;Q5FOvoXQ}nHeDvRVF z+dXIq5@Mnu_C~q^7>Yr^X94-&ca(M#MU&Q<*M$A~wY%4SoA=qJ%Pw{qhz|*u@LPF*rqL@>U!`fRvvJz+rL=<6PHCuvBfqJRVI4LG<2H%Bl>3Oy^ixVfTW$)_GISLLrz>>TuI%UM=c44 z_6xM{$`62G8#AM5EVZ3#|`#Joc^{tbvax#*v~Ox8oRhF`DvM0TzV(d z#17+@+?$PiYHl2YSjl%3;a<$adzW2<7@PQ|uu+g8Q4Q5CCV+qPLrDz|(XYTZi?>}%}?0wd6eb(BHZVn>RFM{{k>BSnJWWw3u8kZysSbn&UFVkvo=EG&z z0sfdfgF#x}JyiH`;Q{?dCF^`RE@X8{+VV>7(|c$ds^+p*0mX;Rh0a*d z2f?P~Mw$jk8Bup2#;tsUn^)Ffx-XS{1)Ind*`_?AJ?n z1+EKF8Wm7sxlDTEbVac>C1o;Cv5sv#UspKOYCSnGB&jUMwV&Qvjaa^ZIs!0gv`xAA zPLtwm6Eq}78sJ88+Ki>9gI4jpLk@BDG(byl1G! ztIw90e(A2Xx|AX`wkpY2S*g2SroYlG!mkov3CE}>;fH#3pww5# zY~YJ9GcA~-|IXzHf*LCVo6cV=Cwc+1)}wd2^52mIe+dIy0p{%I`+sKbKgofS8Qn@u z9YQKbb}MO{>ZD#FGsTadbHwWCFXo@n&$o#7*)g=mH02Blz^H}(gnlOGu7{)5rDV** zo%wg5miRw#NWr@(1*1)5A{nat8}_N?peF*%<)7ev-?hlqh*FmnE<-V3mU!y3YG28)5<$Ql$u;JKjfG-wCvVu$Kt zDQZ%5Oip)H9+vxSWMP>-^{pR2kZ+ZuC%!W=;BT4k7q`TbyyaD3U5%Jv0pb8aC>o)F z%HnN;(V=1Xnp z@8&d#EYc3auyr_Lxzz6Cquv3aA24HjEv)lZ0Q7_4?NDAYS!s}V-PLKTo;idg>FIRP z%2a$!4S;?eu@OCDG*Nsw0hbHEwawF+7cPeQhu^Chtasx*LleIi+KTz5@6a!XKQ7xtu$0P<&rj=f(yTGe``* z*c#B~sO+^D12R88s8T3zh(y=0fJ50Ht-m~~M}F+_*yRDBpWOIsKBJDEn3GJpXYxsL zNa`BBY^1H=b&dsXin9mkE?%LW`LAD^hG%`~M_Ar*soVEiAC%oCE_Y;Yyymx1#pTJP zswj>#O6zEH>!?DzIECezOxcz08ZZ_;wCPQ}LhQ1q2Vr@kiMIL!2{ZM-8yJO^=iwFA zQ4MgU6_CjR;?dR4qR8DtwzKscBgDXqPQQfKM$7!Jksj*@GDT>$#sr05KnM@(1}a3( z!oVW`C=wskohS=9k1GAqY`VhDm(+s!rKu8n5+&uuV-rPXn@`ogw~`5+BG*=t*5HHr z{`4(V+geL(#JGeHze&D@%@3=I6(e(2w^@?@)S}IfROi`e1z%lDJZqr>*~tdL{LDJ~ zR!Vl#5;)BWuT6}RAc`0fNl)|$!q)ZxYP12&564K@baOm6s@E_9pZ1nbYzyqj>W_}x z7iW$&15`BiNaTthb+mx2|})74p!d%B+=U>da+ zIFhN`(+jw1%XsK?xN<9gwVW7_0WP3_GCykP*0CLb4j0(J+c&>nh15UIE_0deDT-x& z(<#y6)s9L(50bCihSg?^dHcfqoNIi2y7j~*S+?Gy*u@TDexPlcPRa`2Tg7$Zx8}hV zwl9NPZrx;PlK>%ri+1A@O}y>M=BF1$c+iq0x-=I(hvkG-~SHEZd@Y)k$%6lm5e-5k+%>`rwOFSFl3*QK3}Bzb5$mmc!1zZw;Ngw&IP`DG0S@}VKtKQD ze=a}{*!KZ40FUpH6fTk=py#L&p_RhTQZ}L^ZO9av9P6rl3BYq7dIW}48E-!~f1Br_ z{9^>58I}Y0GXkIihydh$nL5mA9lD2hzxYf5y#4VU9=Eps5eL&ag+Ox3E8SJCcHh}CJPpPPg{$N^cJ3-c{2e}=(gpOYa{K*%PH+d&}C-~GBBH!HKBg(ic2*b z6P0m>-R#s}W1&ipA13BJgQ-GJKH5jgagxFxZ=iqwjXtTL$lUEFet;VA2dDw6|K^(S zf2jczdlw@c)4%3~KaU#!tHZ`BUZ1s}{JNK(mkXYkbU4$!wwCN-RtDF0JvNW=d`&Z! zpr)_&xe@1~A}sMuK^I9|=PQnoYED@5DltW52@?aUUx*&!u%1(;$--j+WvOLNh0cPOV4GPXv#S?XOnWm`dzETP z4cJlTApS-cg~0w;mK74gS0mjH6%oswoO|JDs(1X;U7!O%xQd`PAUD=ybfPEg!b=f1 ziu}Q+@8Jq<6P_%D_i0Q6A?@OI2KIpQHHXFv=q@E=tyVI z{t3Hf2Z}6`ZKLecPU+`<)=#3J3IyDV$vejcHoe6n&NSiQv91RdQqo-(Um;_M1|oXe zBxiWgCWQm>yrubsTa||8XyIT_IsLpX-aN)t2~EPx`6v0NL(zq`PsUsw(61PU)G0Go z!nLPh$}*u6%vnKMs@HY<%?9HV{R*G%LKD*o#+zLP{Brijhv@y@uq(TV_dL|1j?Zdg zyiDFDP3}C_PjsrRv>njcBbTnK%4G?H znG(5ePRTwS4_SAXEVp3HfUzl(jXkkC$;{V;z<{jE>DT^9OKxjGTfCIuwfaq zG~U9zA;bEqY`9d8j%ticgjN%0|K}`n0;fH(G|8lJ8V0dcUK_)o2iiV@aDFS8NbExJ z7#+8i7G!eee!n*-b@K?CUtb$%JTDsLSl&6vf?FW@;WFn3ZJM?9$*n`m)Vp-!2cfO( z#)}5@S2xEy_qsrg@f3`C8^}^UK;h{iHbLofIBqm_WU^IIh83!AvZKF+4A?WY9)-6< z)Q2%wR14=3#d1P+brWM4=ja%JX(Qixh+kXe^xfk&D%<-_-;`N&PJn47$4ZzhRypIu z^X6E$!|ah!LfU1EQ*@Owy0RcQynkbAUP)3J+N7GkU-3ExAR{L#;TUY}jTn=YK^0j? z^bxD^t7HO-hy4CNp+B#M={_}yN&+Ty{J%G$|1&$_2$;~H@1JDEe?^LI89Fgm*EfXl znjN&YVM0ygbq$QHi5@^}(}#4IlLKCA`!W@o@hZnsBHH)S8SLhD&`^H7wX(L<4A7=d z#t_gqp-KuzlSDbvG8bj_yrwTO>onAqHBPfnGij7% zxz);NRS7Njet!7kF~FJ@^1}cWzUS+bbsmtjvPKukcCL9%WjJJ?rb)>W^$Ed}AB+kR zZXJ*U*b{4Em-qOB@0t6t16bd^gv?jeKm1Wv#Qnb12B3O`NOo*6H(-6^rE~+(VLx!{ zfO8WqdG?s(n&c)>R3r%5YEP+x%DOUWoE4C(p*Ft?ocI0a?PyW&%c@gg4|HqX(p}$q zN4OS!NvdW~X!oyT_rFZKmcxjRw!D{xx!j*=mL_gD#r0_&mBT`WxYD!eA&Lq!@s0z( z41vIAh+?}=tn-bhcLGb{k#-MlN%T2G9O#%*jRrgler$W`vRR_5-U zMYeTP-FQN#$YRa53yf)^VC?|Z_MjmtEt(0^GRW(R+k8iRAU@blbt_B$nVZxRQA7() zEu2?)2NKkXA;7JvW$4EgQ?)Rl-Pm2MiM)&GkhZNI*Mp*bRO4H>IcprLZZZk0Nr|?| zeo2pdqlD6|hh|NjCmxF7Z;3$UCKX&8zohob?})Q|I+;B3-x0Y+Zt2&Rb27%QE}YwB zGUu+;?s3I4OA@OGQkR1*scpCnOwE`lfZ3Th%zlocuGdsa91`2>u>Y}byDuEMZG)<< z7n+b>DE{#v^T>SJT-aoK$0RI1%TYPq2^PmfIhQjV8`bKN|J z>&?*??Rt0mh5me=(SFCI2*0@bROtyMxVg$cu5<+!>WLw?c*6a=x86q-^My+^*?GPY zG^vPFD>iI5I)NVv*ZXs79rb=`ICc4JB>4w#Y95ORuiS;1izYO=LMPDgkrO+!(RQ0B zg#`QW@soxEkg#_O#FvGm%`dJZ_z5*!Zkji8T5qZIldU7`xK9HiI`6wYCgb}>0Ru)n zDGB#M)WevWimY(?v-zVIvuQ$KxF9+oEbT!X7|0>_ceW6tARDr8g}$?15mM!X;d`&N zA7pL?H?XuF9#x$f>Pufuh=eYiDX_q~pMN)*>)+*F|MN39#})tRJ!eFmN3;Asbr_{c zn#l|Ya7YZA3`5o7cW6l&Fn~>3Ee`5z>nHHIy>ua<_SJg1eYE>{Vs;%o(x^gUW;akM`#yXJ?C_3q_=b^Oru%4|R1ln~lvD^U#D;F!>seET3+T?Jzs>yg5R zfcT}n=CA7yym(TLTWE74k)r@ZotRD%vNE4)(V-#S!cG55T@W{ozBT4X(A+VM$?vGy zBtLRD4ES`o9(R_L4;Biaq)aQE^VZbrBVH^`Zc}_W8QC{bB#Vj1WR)>)hV1FntNBsu zraL*fuwU^$WkYf~g+403VP(RYJPRtyI?{=9NuZMk!qD*7mgi3cBA?r6Vho@-xB*Dg z|F8Vv|Nfi)i|F`Q|E2$j;IYzF1g)Ig(bVYQg2&@O{wsJ~+=K6o3b|jw5*%r9cRlOX z!lBEPKYDB&6S87ALpqhP__yToHy#NC+{a6Mi|n7WKXMdkE*R@Jc1f#N=Gu1XzY-pQ$sX$f zHrnU=r>$lSxO9(Vj`<$T?G@tcrrxVraIW>`w}=i*i6z}YGAN|2fwq2uWq~r6S{4+FfvZoweC z`K#!?M7zL#n513Wo%05l1C%)na>cf%Zf7&H*aTU_z>eUEbm6R+Yf*Xr zO=1Xsxg<^s7+#}v9%F~8H7P7w;i7q}LRKsQUrnNf)Ys*boX)p7w> zVh-11vJWB-%_x^a2;SZ#0}*cGSNO01GAY``?*3%$WPX2MX9N&_-~^^MkD*$opD5=QGAv zFE7q36AoqN#Mb^Au~2ZFj-&<3x^~q;lDnSi;kdtB8En{g?IW~P=eYV_VJ~cV-sZe+ z)$X_)9^D}U`#afs|MWuLuyB4m1?zaH>O6vfHtT8xj84HAwjl&l7tjpV+wR4lx`YPY z2J#X8har%9P+qM}rH>P~+akj2wf>D6!Zlljf_ImT$wNKBNTA#rX=P|9))}VBh4iE7 zTgR19h9QaS7LR#EYlANriUTi4no2lj1${(D+YmCq91V$wUuk3(f9Q|(%$>Q{JCb>-cB>OG}hP-gPFXoWZ33PSGy<-E_^3Yulg7k!Wm}L)$3CLqx0rt=Or&iN{giuC=!5M3i&iDP#R(Wb}@riJ=z+214?EMv?57Vz$2`U*-WSc%}j@1Pv9 zN4$G&4oD|EK$@EfmugGD0S_AsKz|-3PKwvBZ6nWK#u1dSyg(Fg!MjLk0Cyn}QQdy$ z8qW*-4b|X-;ca&?;R2m7+mKL_#3I{3hG;9{IL?XS#y5M^8mw*U>#peC^U%=9=b%;+x)Wf?}9*5uF0Do@YD(BqAusqizs ze6clN2fnqPpZ^q$qXBs?P4^37v%e*(C|+G7JLT@zCvF^LtIi_1$b;(TuYpceO8DS- zHD(Z7_~JCXk;yHd)|+Kv&*XaBCSP;W`zftoOXIqHtxY3Y^+GWV>MO1-@*Vp`;_ha2 zx#-%B4qFH8W+)89#%mrZzQmC>3C%@pe61xRzc@zccC1+6$CO$P3nsoe!sd2_s>-s@nT?M6r6(2goZRM70c) zc&3YHkMoc(c4V*v0aot^@Bb2@%x7F_sQ_Lu0i9AM-&hjVbZs4bT$ z9G#E7T+R5~Y1#&l8ntcGQ0vUEsVq8z(djxdH8~GjBH1~-=9cl7owlm z^AMr#eRDU+Dj>(!Rf2~}(#M;?%<-hOAwu%%8PNhO)h%(PA3=0~u}gVX8$?mt3Rk#< z*MFn2?G#d!QG91nWyAIK;8DSsONuFOxR}5NR=yjNk&)e-1i1kg#{ZVU7*mhT#4C6P zb&kkDEOY4alL9|u6q4DYmZfQ#6@H{0W#AmlF`mNQV`oZaV;zW-qWyJ{$c<8~uWdWT zy=;i1oD{V;$?@XeuopcvN^-o$AcbVF!q9YH)uQ;^vhkF!0doN}yrozf&0WFm&5?Wyn+TQ7iFLNwvLf{du_;!+w6RiaBsFm!$59UunfhsXO^+_~w z00hPV57zk)LGkskCdR+`j|@0hY}d~S7yQUK2&`*EA-qE+aAJqohBmT5NSGPP77n9C zG=qk9n$JOLUPz=Ok{@@t(LZ>6h9xVfZ%sRgF1y3yG093V z-&4OU2(o+i{uFB4&MX-yRN34=;whidVx@ffA4t>nimq~Fgn&_&5+$SvzvO}5Q}1_v zyB9&@6LG%e=~5j8rrfcc@q&1}Al|+GF~fcO)FJFAuoSh=L$>D+eVSwg{NE85f4f+sa z)iRCiErKG;nhCq$sVgysM zuVnbz1fQ2}hX*U%f)gvf5)(rpI=@{jR#pk(Akd>pej)&#>0BE9$6SrfSWdJ53s)bv zw0(mKx&t-gmh1$PRMgT-I(22@08JobBed9Y*fZJgTgMVfgx7GbvfY_Vw);x+l<#@F zTR6P{0;2|Ds0$9$@<=JZ!V(a}B7MYBl%W$HhnI2cW)QppsH;BowE-_v#bN-w079gVccdadAZ({e(7qFoq7mgIDn%`UWf~g|ehtJx)7?Xlc${J~=`T$_u9132 zDzilv+>nqcqun2vULF6FzyLUmmeMV)P1jCz8`&c?lz{^np%Toc%M@uOgncrnM7U`s z5Q%N%&<1lpaW+P&!Qv&?GI6zeG9=K~9hfi7I1@jDirYB7|C$a_y0Z$k{8up7xVc9E zdCU94>jA2D3j|Ziuewm?%23V(U#_aSqlUAhd<>M!NMLAg(;?4nglE!PoIJU^jKO!s z>!o-Of8$QOVUrcMQBBtNA@DG)MOiZ1|~xm6B1yKqTnOj4WdM7q?5!3^FeisXi#rOM!8SKBi>B6+TP`OLB~HHhPOlS z1V?%A5MNA|Ufk~0;odNW@#LMsofa+JlxFQ${7``4<+R&OG=LR0pZ!X$g%!J)D2cWkeX*Gt2Zklr2EBCBsZp^2-RjTws%W39m)-rW z7dO;_Yrmn;zBSzC`)SWhplr-h@7@t57bLrD5hP>Kg<1YwgdyWPv`nJT>Qg38odL>+;6B@y6a0KtESmwg<=k7 zK-I0kbjjDi9>@&;+xxovLnnPR>Z#w8kv~k7QOaObtkP-h$t*p0_lLI8#c$DnlZWbc zs1MgaP1Y9MFCHs~=Jnp*{DmIK)y1kW$Kk)lyk zJrIQ(QlYC}!16Ai{#IC&%fE4nIVm8iAPO80sjZ4hNE@*?M#}SwnS6+X? z%hx!j%S3_{c^uiP!fO_}fMILL2jj^e{8fUcuL|6-;iN?m#O{eKCdM=bgjtldDON(P9OVKgT9x31S%`Sn5CH5Gdbr%q8Qi<(I zq@q1u|F}`Mc|fB3BKiC9#|W|+#X2I2I|Pv}Kh+F6Q~AMU(ISXKwlH#H+d*Wbo#q3* zhY-aSM?k|W^v#a;x&UyiZSG?kpvqp#)N8`An2T1!$i-=Eam(f)!8i5`JHz}Wd_#0 zfL1BIJcdAg#@utn_RcT0XvAbqsRL7~EzG2@h8FFsOsNg4jOcNud}*StwB+le(GI8KB8$l!S9uV(R=TR#vx1dzMG z|Cs>F!9KBSJEb4}NbndFkbj(oe0zrc`nLZ(t>)^bn{*QOM&9t7=9y1MluPyXQTX-xpHcKA0)5^kDS3 zmW?+P0&H+g0_+erhLsf}t07zHDX!E8IH(YF4r{F%QM9I76I2D>O`5U%K)Q+=___tb zDP*OkJRw6Fy&H=G7F2f+Vg+PeK--!HZ>a|^{cRUkcACl*@D9E3*)5U-%>nVBGtw@) z8umYMhHO!=^sfPFEg1n*^R<%~ngVM-2kgnOeCUm)LN?P?HVz^@r~qGNYGpT23qsLv zYvUXj!WE!+QP!-51L>f$`jd%r0e3j-A*SX1pUTR?t{Vt{Qj8ij1bWAq*dbT$+h0wsdkoOZ}fPs|n*RH8mv9C#s zMMuhp@zm&Sa350$@8ohn4ELNxfITL#c40HupOfs2jpVnM>k~Jd`;dC{<(~X+qz9=l zxu=gFNZpHHaKz=%hY ze9$p(@jPro-n|MQSG!Y?R(~Qa&zYEF5JwJRd?K_-r&)jo=sqTGz|=dXCvr!a`syK4XUT!z0ypFht#|BDmP|AWh5i=&Nz zOPf`GB|mSPOu&2;XbDSfuv67ZqpoX?FeGC>p@jU;E`!B^k(5ee2=xE!GWf1Qe(ug#Ciyyt%m66I#_0TY$r38QZcJ;-w>vs%)|xKVB74IZ0Hk zw5}_s&P-W1AcsblmGQ15h`0?(lmhY`4KSs@B05BBR^QE+FY=wiyIHBL z-IU}dPBixz(b>SL{>oZF8=c)7udb_|kaYum5;411^jdK|S z?d_dE5aT9xO^>qyn-Fc{dVg~E4=%%boh(a@(o1M!e8Oxb?ic4BJ~0*FkaN3Pn(%bK zVhMDn$Nb@(fW^rSPPaZ?=W^kIvHjvXQC`;dh{raQUG-aDiR7^cixH#2!Ql7tvp!O>SP zw>yi|yQ{j<@hqE0G5HNtyPH6;{FWQuP^~u~A&XQuZjq@3;A3XPEQc-M9|;brvaDPs zTxP31A}z=>gwP&_Z13yrV~?-#5igx@Aq(B(zVjb#^V)X&GEFt2+cxnJm6@#ez27C5 zB?$3~vJgwLSU<_UDwls&eGFxx>c&QXE(lRy7uTrH*xY`0BUsUJBv@IJL)@5|JXPu^ zScB(L`oLA+6k&OMO&@J}W+KiOn489-?JnZQIJ4<*U++My@oHc0q<7^OcvKcFW+_Q! z8@BkZG0QQQtWzLsxxf>iUi>3SVEKc@3d>~DaE`}}J!WPI$qL^@n%HBX0r~m5Cs`&Z zQ~HQGg4oR}!e9GtKw!e0>=zJcF+ zxfak~KdmFb7_Q5YUzr0z6?;U&^buqq4kJSyB$-a$gK;jAY|u8)nWNL(!X-#@Z;9>!op6AlOz#%ul%C)c)chH8Zwu7)?bIs26P`)HAws+3~Q z=MoQK=f&uJ)tTJlU3V8BpveZ`vq!BRKvKQ2k|nPCiLZqBwPJK;=?B$ZdQqj}91Lp* zz-2I81Go%N0GEMC`-6|@nxnuYa#k9Pd))@T@?ZA z6f=^)+~s7}RdX<>Pfmi9uUk$l0&VdpyNR+Wc{YufBu3ZGZJFZGk@Cd7bo~wl>h82f zL6tB!>mik$25&-T-F9FGS7>4bw6yyn*13X=-UZ=}^>qk*-VI}5m=$3BRs7dx9CE5@ z;q`F*{=%AmY6rh3l?0A|%VqdWJlYU2j6dIh^Oa_iyR{!+`IgisSug&NF2mi5HRoCx zz-5T>`-{t9V=0bF6pP6WXkrr^Brxm?{*utz>b6c^bH2ZR=(FjSeRA;IMwrgViifx+0uP zck(-E>@W~ak0Ub>4N@Oyi>}6H&4y5q%w6R^g{;R49Qb9-&qYM|=O5rTQt`WI$5Mx;Z#Sh9~KQrj~|cWh;s+wK!|SbIh%?bQhnzc6<91nwzdP&%Oj@<`ZtSlip}g zxgs-nC0U5TA5M5=e>~#|i}4mkwfW5n5Gw;?XF`AY0J3Oq9YV_8vwJH1)9hC!i63(J z*(1#8W_4kl*k5@?W%BQ{Xxr=Sw0s^Epf?T@K=dpT1Dcl$c=<*bDZzObm}an~!#GD+ zcoDD&7BaXjhzoYXqE3PuUmZr=Sq9cFm`sJlB#sEbrF6*VZPM6Yy*eYr6}+yf$qjp?XnJh<2J#T#Udb1HynU64!TI0G|!`pai69E_t(HdwdURN^uH*| z=lL?P=R(T)BCxW+fS!4HMv|A0;}Tui9?*4)Gq+5~WmID9--zhYBsVuhhd!WM_$y2b zqQ5#WOqxWPY*(1e-Yhm){BA%>PIhks=a2y{gH-#=ayauv?K9I5NJ4u@3TQtfUK)cu?D@?UJk8hUkqM1yN9-WIu zq9Y1d>5uKJ@kq&W@W+bS{=MtiXK!T)CuKRE2E#_;ZMfzLUTOJ)%Vz*iMahpop zjvc4kQFJ#ZMG<=y!E@y;DQy-&V^pY~;0z_r`hDorW%Mq9)gVy_JThU7GfTT#HI*Auje312rw!co#x#l8sXhW)Sp7{=bw{f7%S~ADojT|CY`057Fs=@hACTMW>fA z+lXB9%PJC`iOY-IPyQKON>et7MYW)+%xZV8^<`#ObjNLP{JmN zVKSvgtaYvNUV3dlcKqUfT+gTujaZwZ0r~?1EPy{9fcrOS>HP5gLE+;GKO}b%QUXMu0$t|@N`@(+2^A8cwa>_X`_MK5K(_0Dm0j}=> zKXUZI1@NP92zzW;lA|QtZ?JHyMRnez6LZSw?(`Xbp%j4RPJrCeZfGJ;om?tAmxc%X zd4k(t<27m)e5ol9!_M!#$ozqE4VfV{qe(EsWW>FVrkJpe%r+R83O4S0Eg4mov-`Lh zwK=_B1MX2H_sWjmd8ZZLCD>`cMGEah`A$R-+(Hkpm*1#&ElW3nmJNq{^}B~5r2I&< zi5>FNIJUx&)W=MzIx|tnd~CVGPwg2_k1!HU)!`6VUjUC&+m{6fy5X!-TC4fz@qU+1y?VnSx(T0ef(i194S<&3wL1W zX$@lRn#jdC4ewfq+g35skv*73IT2-@*Utfw6(4Q`u@sL7vUzv8#l;MhnI9bTNAvZ#vWrwB&#&FI9l$ zQ%&S?udXhKzUTyEIC%N2=}|P}<-8p0LC%zCHi=-~YOJx0q3Ie-09=T0t)iVE0ha@> z2CMjbFvaoINuHt9XT@a*%<(gfXT=2t> zL&bQ?P>;21r`R)+DN5%{rX&;h5GO1mMShWEm6X#+sz<{!#Kf-Z!&-F`yE-2uX0vyg z8oV@t5-WP6$n=Tf5*zaQq)j%pVYVHahKrGyPYqD%g}ID3k4FE_I$sCLo+4nkvZw19 zjaEit+tQY$;VTiaRE^HI&>88pmYH5{=ox z?G`k81^9IEt|XqB+(GSEH$(PyBZ+?<^&ZUZc~;CWTSh+9mEdE$33*VUwoA?iE3QpQ zs>>m0UMli^L8O5R53SypTD$bstq9gCON^Ge<1ifklJIu@_AmYfL!< zyYH z^40%MFyg*?ANPoel^Z3`jN@&}AWj|61c< z$j%+9cBo+bup3@Nrx$=Tc@zfU;TtvPqqBRFKX%8qrqEeeQCDJBXhQ{va%<(2X#~fp z9b-SEyj6YIq=YVm2dW6JB!^H)7IOXq9>*85|5U)hQ;uoX?|Fi_)P*<)glh_<0smxb zUG9|Tqj)#4!uO?*u2y~FaNZl~ceoF0Vl~pI?Q0z^4xV|t$M{FGeGG*GtWT@$reu|) zj+;3|SrB;Ba9!+pek#6rL~fJ^**7O_<*9hpqf~VW7uryn-*qVp4?*(ssj%?DS$_^0 z5@>n5UkgPe16DaYBJ%}xp_k^~UnUqiRjEG67MgaepDPErU5z%iM+>t86uYKf$I$BO zZ0=?`WM2t3`s+({N6ngBZy{LC(F+3=C(R%wE_nTppq`>{D5STEfEr5>KA>aup*YL{ zNE&GtK@rCGOTE>*jXSVExNc<5Y@?dp74b6ejf;=#3cP~_S*db+z5rE+DV(ToWFtex z7R-L;q+_L`I?1rpqAiXfr&}!~_&GpNY~zZTqm&&4yLw%wLk>a2jZK;mPZlvPyb3e; zoFAMRE_g#5rQ(}Til0m-pnDdiT(BH1tF}*(K1v8;aq9#&^2R=!mV)OA!X!$ZJ6hVO z%moMa_qFpVrX;yi=9eRR#G4B&-&9}yLqv$A8|TvV9pk(=`dheCyt?sG`h#OUeC zaaTb#0Z;K^>4D8W7`OvsWN{BKImDUwBmSjvRI2wZu>`1DjhlC? zJ*yhCnk){Js&VZ`y_56;uu|mb_tNj=R7Z`muu~dbeS$?#f=l13H`XM#4S9#PRqU%D zql0C|`|e`&oXKqhgXMJmrWR?zyl2TT`Cq0qKd;O3*; zq|~1iX`p*Pp*%+<+iX*#0~4gR%ys%YLaC!Wfnn|@WS77CdUyV)UBVGw${;uY7!X9{ zJS4J{KUmuy^%&e|KxkE-r^OCM-z~*FJgZXx5+`p_4+9H>f>drI>irZHqAr7Ie-jkh zr&aXyjLELvg{}`&u#N~txRNfS1fPOJiA~-GASfJvPOTN-+)IdJn4|n=VvlPKt4Vej z;07PbrZoCVG1h2z>oE4MG{vr=YGgJz(9va(QvHjvx;Frw?$E)^Yt-Ox&rfX&+S;9WUQqqeGBI^Rp zCC*rqlHX?aLZyKhh{jc%0OAWxkvK!2|G3Mhi*g8O9)mstA@yXf_c=|82`)pw=EvY^ z-yRbvs7~t{^a1?JpQ1bN)4rV zu)j~{Pd%|8e=+v&VN3szz5bUmh}utVN#xP@Kd_~hQ2@4t^;c|(a0Xv%Z&R4;cqgV~ z7Y{$em*XF>rQ%O)X%B!cZT=lwdjIKfJ{$x#^uB8yma@1&3Jue^0SI4{$nKQMcG6w= zkF6CAdbvr@lY>OKNaf-pWhH!uAjIE0F1=z(37!;$hMhPEf~m(D5`@~|o8p^s!r;s2 zJKeC7^BtFs0aZ-H43H$$Luba9D}Bv+|& zd<|VzJ6=dqM;caCeKI1;c)YIRdm6naoE`HnB8K)Dpo)ov)>$N_Fvg$x>v{Z_lvaYv zHp-oGz_+l+&c`R;3jnpmtc~1#v) z#WLbm*_HPUa+@>3Bcq0P%%qyoP-Z8cpZGf|hW%xajO!7dWxd2AMtpZd1VJj091Tdx z!qm{ehLrfrmHV^41{=lMJMJZv>guRpjt>SDFh?bL4(3g{6b{)6iO)#L>^5O=doQMX z!;~jEEi8ieXuoL=HW*_v0;nQT{nCKenU65AE|VFQnh37S8~33=g_!}irTCJR{x9Bx zXaz#W@1S0WLSydD40F99Ry!rd;P>A`JTt9d`)I0nhk>^X72Qy67xOxp>AK|e^a%9h zoZZz?_pNN8)V+>oj+47_fzlzKEf$0fIa7*4as7{n~-X6CCotU`` zc1bU)HbLE_4D&JmX~i;_mX7yT zaHnXl;y9W&a#R|Ixlp5^QoZTRYR|BDASVm9@?1DI5(L0i1ggX39_5ar{9`c$xiwQ~ zl+H^B2x~gmOuD^3Ka=v-km9dg4P??(kY4N?jp4>MY%{rc@a+ANtDz;tW{51b2oRWS z)y0#Iw}xoJx2A38soj>u^5XU1B)ldi_X!~S^{L-W=Ak2Mn9MFsmYva5TC`c%cA&Ja z&||iSx2WKtex5QJ+tG}y0mo;-dU9`WL*940V%$Gv7Tvv8&Qw?|k*Qem#rmZUvk7r- z{Dl<;eq8vXOh~C{QL`%tP3CE#<$TJ8Ol9~|s?v_EEPJ&4Ror+Yqh9vQken>Z%0iF_ zwVW(!k+K;?uuI?7YS&P>sliF4E)QiayAccyZcvNg8>XhwA{y%v!H*`Rs}88Q{^5rA zys&q$hjuhvn@K@z-SJQ&qKW|w>nErVr_baai3vLTM!K=Hl97PQmuo@mUIWaJ&d`kF zz`<=l`+3{&PmzkrSxcZzDkH`N<5b%o_@=bMPNN*KvgBxWwoYCoEFvIH`ugV-mg)7F zt>247?Uq;wZuo}GlKRoA+7`Ti<%YR~^8t%u?)bp_iroabIzA!i5b?_HjIn{d#2nw4 z^=&VJ%{~>Fe;K-lQ6CN6eqsvY8@+1e=!|&FQsUQ)dM>@Dac&gT!>&CFD69P$;^LZj zE=czbLg*8)!`rE0vlvObz-~A%uaQ`CZOL9lTU-lR1+=cLNpjJ+tA615F10|Jxct6j zwd}H2rpI(oKM3}U>A7qxmR-hY>C({Zv-Uk-CBOMBLUXpk_^{O7(58LC&9Df}s^hN` zrq&!cOcDi!(=~Q{pIwk!=vFHip!3_vTu^pv-pA{5OVq? zRc!U%XiQi**IDQWk1g-5HHwbZ{#BT4dmaSW!pazDN|rz($-CSPog%^Wk+@thtkZqW zN+D0pb%IN6ip6%msst^<(V3U6h3Lgd7cXeK5CoFy>n|*hd0k#;9g5$7xdQuGCh!94 z7g+(b*zG@>#eW)`8~}6pTyof;sQTZ276jnN}DK7JhIPZ#aXRRVT>Gyg8;}n5lH|ri}eAs7>q8& z!{))7!F*Pd_~274U`W=a*+6X(ep*keIAhnPTExtX(Ko~8Z1@>|*=hkKHmZ^d z5)wzyXoLaZH*)2rbS$MeTB{@O8RBP*Kd#@d2oN-4Pkt@kSnDI^wYq)}!H-Bj8gqxN zoKH!=e8_jHK$7@BTWcX2g%=9SVUElt!{*gMh6Y(p*mu|%JzjkoVTsstv4JUw(_9TQ zfFW@=?q0<%%yP}^!!b+JQx@~01mWq(E#a{%q`a!kakPhUMx4%~TgLuo{iT00a0eZf zyX%RQLjIg6H0MrF6S7^q7KO8P?8gD36=Sc=UhaiO(DOpWZG~xysw6GW^_e1|rfu06 zpS%|NH8U|WnaKctu+gmngPLz3fNq6Wf5HSffw7p+1C#U$mUu-Ud`^X-YB5n}3QmtX z2FyOCf^w5oGKWZY>Ja11Pe><`v*#7_`-CMn2_(L!r#B|^H80MK5?7NVw2AdHlK{sV zDF`svbQ)*K0dD1&M0>)*6?7d>%_Rz><)}Vwh&w~JzA1edE_DVYW-ZYpLs9GC0=VG7 zFg&P+b&V+6-}jO;JpLw79uoSieTLEsxnOy0TXb+vcVHXGP)_l+));)4HP}vSO8ZDN z_&;$vq$aSAJ3yLZ709CQYAE+X!(^Zm6&7}&-NcqDL(_PY{oRsub$HI^L=7TaOBy@u zqwGX;lac4O659vmB&FwBvwc1twI$wU^OF}O&RQyrL+u^cPb;NnMI8@$y%dnSu#Mn1 z)d|7{*BSk=Exr$PT4Bxb?2$S1p*xpCz%rwTGa9Tauy;&zXB(dkft%y)^8!6KJQ;6{( z+Ne}G8@lCWs}ZY273PsAW77>wAwZ(uUbVzaAI_6NI4$hINr<<` z76pPt@x_)7d@2^6R_`}eh_WI*HV#QRnpmWQ?6jl z4m)tS)OW^9$1L5~q#DCj9&lq(xGmy}8&#P%-1%^u)p)t-&=GNE2?atbEbXKi*o zzTwTp0h9^KQK0?Gy$@yLY2A~9z*9J3ZVLJLfJ+paJuiTOn3Vl~`&|aa@U`ug|MkWq z{!@^Kbx54EOakme`3CAz9#czQ@#6)0g)|uQDP>Uo*Sid(lO)sVH)mfP)?%MM?-AV5 z{0J!JWInPWCu%D~TXuLH^a#&$LpAt8v)ii*_c`Es8FJHb8;mPHj3B!fn_0i2En0* zz4U{RBjqOuNd`y9-exE&M2z#Q}-{EM;yAVA+uTIFn?ISrxB<6{?Ah~jj0 z*gBZKPydC)^=47a_ zFcp&>BD&I-gM+7R#2#1Jb4%e@nJaQUoHyysPJdV6-oE^5$Q9{=Z_L!{Wbz2)AQ07;}fGuY?B2?&2RlMXB3Yt8W>Waa9t?Ok@0Xtr;u)m+g=DWW$5h!lv)Gf9dtwqhsA!R0HeY*Vp47cSyPvx$9AYdLbrvz4W;JVP<&XW&agO?o zANMrMA=jjC^F+G@^GosJvmmW-nWE0Ucbvxx{xqiM1ItJ^hfY{KUgy{#!4ElCTHpR3 z+#CDaRcDd11X2$fM2hbnEobZ<9NV|8n(^kAHLH!*ylMh2x1YKpFCB96w;ZwEo-|VX#guasC^JyX=H#hN6gQeFZCBU^ zTC46OXN?~DzHc|I8D1wv?jcb7@CDEhUO`xaaZJ}ihYrB<67&HIyu*HD_hB%{%M*4C zO7u*K(a+RVPJd^Zdo=T zu$Gw)+H+gsEjYH@MEE-_A4UdRD(u+S?^aa8`gS&NRRueaLf-j&O&hg3AA3Mn z#J#QGmipH)zU#dy1aswOY~YVcE}6-%;Ric;tpG z_I_NJ??Kp6QHLf7B<&RQvepij^zV^M^KUSbKd=Lb#EGt6kN1`0qpdj4B$Wa2V21I@bUh){ox;C1b$b* zA^@TOxig~;1}piQQ;)BdR=q|TfKUrHY(IoR7+NvUHGw_LqjWh8^i?q{tIyIzn8RWJ z`sjWDbnFDV06KQkjP*Z7QSJ^E3myxFjrg>>uIK;hZhH0E_?x>)M)fRN7~=a7B+!Zt zcqtH2+trV^Ao8})8Wnk?RVA^0)f_PFX)_4vLVf5-w~32CWs`8I>kXWmFW!MorX%dK)h6H}uhBmKq$ouBNOCLOgV8b^=Q!TrvKT^lX) zT&t;LUi0jP0Vsgr1-6XPJBOEIthTgK1azjq_#@6>{YcDKw~Eoj2fqCZDx*G*^Fsq` z90Gt)S26UgaQCcqd=x;)cghZrRXoyhCjw<(yr(EpkbH;{%sV>r@;=`nKFy*iuyl0_ zs4(1qAk=6d2zAf{Dzn9flpDUEJ6?D$lX1lucB~XURF~-=3>v1hjV*#)x*3+Be24+- zE84ii#ZTPDv^(cKJ%CNKpma=qydW3mU|jvkapok{!dIw;C*5~wzP}<$ELl4x&O2?TiGmU*NIu zBZQr+8(Rhx7=lvC3!J1F){tRQdec*%q?!h{tYB%7t~4*|`UNCzVPw~2ksKKf!f3%Y zGcbTTQ;1Cr`o99Awh0XTwIm$z&1&j7bBY}37*{AV9K$Afr~dA&Txdht9n%P7zI| z%ZP>^*iFA|kRNEWQ11|>xEZh&Repg)il8*WrmOEK28Bv@&rWrTMaY|o?@)e4LCEph zl1l#weP!GiKqwAt4Cu@XrgLz0jgF7;NR2^j6(cV`Mh8_`I4y_m50F7RJ?Yoz!(abG zc&X428do~aIYH6~wv_J#laZ7sembN-+FJhYgbE-D-$w-&3~FPz{feQrCEV%-7m zUx-K=-ntx-TdupSx^ys>Ds{8DEZiL}Zem6=%j0=_;_807fg$O+&-NolW)X-|D2mRj zmY(PPEx)Q#%L8)v6q0*c+SfZLab7hon>mkW0V1#=gOES#6JO#9l_b5p&vE$cWpH~Q ziUf4oYLDfX%GzVf{-8>z|LH=^=CS68dyp`?ymtUqa`)4`dr$?Z`@2ZzRc1H-2+l?w zC@Z*B`%C_aei!ef!+M!^^o!S+hDr~ECauGjU6i1n@atb1 z&ps3gF>Xt!LBQU?3V+&!+B&)oSWfEXslMBq{Nk)V$lrjkcH-iL6ql1r0R18!JuX$fy=ocp{6OQcOw}9*SBaANqr+tL%sVaGxlkPWU3pbU(^0yuq8z z4bUIlb(uoyk3K?}#sPMwAh^BvX#GBe>r!v{u^+W(G=LB$uh9*^aK@h@f|^&!Q{sj_ z8-HoV{-7gv&v_Dl0V5+KV%KgORjbbw^r5cN+s@zoZ z!^oJH?fj-6v%*;D7^$EfjJ>v;TUAb7vov~8uauBW&jvAC=frc47ZLrl!~sxJiU~a3 zD~|z8A)6OO1t!ZAbiU9^o~Q`h-x}}&6HNg8$xo5y1Dm$4qBmN7nUQUY4kj88F|5}w zINc4U`*M=MGRn`2XrCRiERW>c&PwwuO?X0CN~0I_&TosNdm~<>x6Ch;-Qkr2)Zo;d zrbVtk7kZtwpR9 zHaGVUKJ6&XKw^sCMVPS%0!9E-Mi=^8Zzx|a1rJ8RP^F=9qXY0X>sUl7cTNpko*FKl zNq|fl0-^8R+p5QTI)kw~5~C^Reuxjlga*@I#buR4=JyPq*AP| zu2)Z@C!X4xR)zNyq?XCDK8BD$8K0xDP_1l63l_)rs#g^-*#b|0;878wH z%T)$^W{fW(m{Da1$f?KLWkQimsK|&e(S5WS1Vj;Gv@`1}dHf<&iLfpw8Q0(nGDfIy za_1#kvST}q~sKCyGF(oZ7yp42PKDZltm0G&no zq5JlFckN+5j|eBf3$vJ*B^eKlhVS@|({1qfoh(Ty=8`3*5Q(VEm~mbGW7hQOkD_ZiCnv5aIAx4Hy9Vlcj8j=NH9jPAD3>v zQ~B1mj;%wg$NR`>z*+FTF8yT~F~Z&;X%+mTxeCaEQE+@HtRR*jsi!||Ao2irT6?>3 z)2I8U;$90V6@a34$*Q(fx$A~&y%V& z3Z>BkWErC)vq;(yTapue%^-QKh$+P9@%{0PYmX4?x-*)GJAuT>?M@D%z4wc^NMP4w$hWuw-R$f)N!yHduCGFMsTi4Fh(P!+1r-a5Y2D=UX5#?5gh4Ns#NE#$w&T)$hwHwr|xBzi(R+mvjTzEKQ4d^4-e4hM!*9<-%x^rx z`BYT09O%;^%4`5XK&T2kVv4tqoL8+?p$q= z0%+Z=%GV#XNQHE_nUDuL9%09HCx=(DO~nFW$fE<>y6 zWSR^?5Bs-tL;t0h=?AXHt^nW73Hs&~@3u5E@WQ2_i>N$n6(xp2BUj4#Qxprwz@yMS zfeD%BfoXJ%6F_WheJOcxGgB!Bwq2`|zDb!Y-~j}pf6;xVFB4M< zN8$i68Q|gl`i#ZaF`OKldu$JF1l*8u5dcghAhs$B)p+>f9PP6NE*+wRgcfYhFO*4~ zAXPnj!ooq6;r^<qvCs#9D z?yU^CFT--rh0RtIY+M6vgGvuH!=EPceMCba4a_vNoC(eGYcsCm=g6%}a3Fffim`6| z6H+HA$T4qZM4l-GOfmzJZJn>rF;ASq3p>mB%;6suBuk&DO%WyaU$va?X z1Gmt20pbt}a|$#$ReH?F1sP$k-|1VbscJw}l%rp!3`zo&0Ro_2^ZXNIR&o}|C`{!} zMdJ=`L1aU?W2KVzO;fI{Zr$J9iqdmekF}mcT}Q- z+5S(NMq!-b$VSXE2E7uz!EBN?NbGQYKEM1Euy%L}FUbNWe~9FJ~Orvy-MO^>m+@#f4{fo913bM&i}Qk7-xUVKH#1p(yw>y&J{dS zZ@ri;L;woNN=Hh_AzUwgg|$u{5z{fa5nraQAngsY|C ze=dU9)mO=}!Ki?VtpHkZ@}j>+2-EJ6j~}PjCJ=txaoc|`XaWATx3;ju zZa(3;m|wh|`m!FJS*`o+vfsds@>dw+0HLZ@C>6W>*`xG#-#EY5>>VnE7&I-GOr?cT z2k?ptBxkvRrAll9rLyE4SKOcGRU=D>b>%`?z@lmsq2CmLf&ACl{W$u+ z{+68CJP+7iG1eu}#CEp{K+jhyU1*!@txYhkqYVK38l-zMF2N_P-te zhYMp}g5Zoidu#RUIF@vRi8;eXTFzNz!%{6Yk{t}a1Y^NzTz`rNxaw@8sf_1Oc2*Qo6o5U(vqlniZDZ{{ z`*7p%@$I7R(ffi`bH~*T3sjw-Uq0 ztVgy@_NUrPNl!(Lcq&5A2#ohBrPrg1f8ig<4XE^d#0@=%ks-+n6(7oKAInCI2%i_a zLZm5m>+ieP*7w_YEAjNF5j3S0A{LDFO;hz)5_JmJVHUG z^*nMxaZ+EPbM$@aP~pr>74_Uip5CdLGyXNsSs6r-bF71f%;y^|Am@f}xmUyUC+Q!e z0R%)h11RO)j?m^dFClC+Zvog zD(bNr7KqLJ;#O8Tkj@gf+cm_JKz4qP$(gX8%wldUa2IEu@X#ojkv9^C`Ll*@(b~Kn z)i=O3WF{NB@zp+udE8Y%>9!hr17$k~+`R_%+{R=`A($~jClAMl6`_T+dk~%Cts72r za-;#(hn?IPbI_4Zs`{w$mPcXU@)qOfWhRk`usZD_skgF4!=)*r`ptLI8N^peZ>)fS z-JlDrc7x(c_UA538zzbDYa@ctinyqpsm01F;qN;kuoL?m8*X2vaF6om0-23xwo4n6 z;g*~t2%p#T+ls&u< zr9-p!^y{m2neK>P&-~8SFc1IDfg3yZqrK^DJ?^SBG;>n}qqXXGL)Gg~6|NKI4T`p+rMh^rlp-!%4I8&i7jtY*xG^<6mG6sj+Ba z$g!+~zI__Wha0PZA~|AqQ~XhPEjq<(M;EdV`lO(>JiW_FGqfYgiP@XsVJyH$rO&4# z>+)vbjQt^{b>aAsUlo>EY)UEPG0HV4s-p_zr4-e~vU63%j8aw_<9^bBk=4sDK^Aho>)sORr;OEhoatrA;R4^{J|vfW?#rYTj>jFz5Yy#~j+Sv{ zBICi~1oPujf7N*3LT-R)fcrPmV9W+YZ|+lWBnpZO`G(xzW}%MJ)`Y`_CGaiL2<|ZyK~=41vg@ zPK3UnaF6K;Ku-tx{_A7)VLLKIUkjr9PgH}yAkqKAb@czL8eCWZLp7lNAF6?XmVrh< zFyHvc1YS1C!_yDssHcg{Wi)rR=OUbPrnF$0yYb)+!oV~=7OUavXTn0bhef$+FFEkfnWlocRNFFN`?d%) zl?7yZ0jfa~Id1W`_lIgA{v_kV4NwhM13{?K(Br;q15|^ydAiXF{SVdPqEF+rc9HEl zRP+zkfZZN3)(2w|_lE|D6yqSPE5$fH)xBP-S%jX1G(xiwLk-NWAgGJ_IL423%y9&` z<^Qf4{81b2C;>Ee@Jo^^GuZ$&`kT3ZPASEQ?PwN9g~j_DKs9)u>-(E(KpFG^J78!6yE*EZwB`hyfhYbR4LUCwyF_U)3x-EAw zc-~h!Cr^=^i+3>Ye&jfN5_-Zf)IyT(xuis2iYt}B%fCTk+l}_28o*s2;2?tDLE7@3 zu#wZ=*(LJYuv}R_>O^h{5MmqK#;t9TTwcb%b1W(h!S!2%%2ZSr z$~xS!!uouu2HyT^V&)&JLE?jcsuUDJHQ0;Sv>&Gz!>VuMvw(lq;@SUD4aSXI&zYoJ z7yJ7Usc6ANxLbt)&C#Y|L4^kx{%*0K4-EQ|H6fc>X+Rw4#K-$X1p)Uqe1oBFg$Kmb zI;IW0k|x^vjq+@#&>8wP&l1*`$yP*7)_T+UjyCvli?Uo*B=(;4Yj18X)Jyf>Vh8z! zTZ{-CZGI`#FBs{}%Pt$pobq>e>T3M%_WP1#Tl``LAQc#!b$1<( zaCEos7v*iX%lP!tdY|@a;G>M`ESId|u+LMdY%tEZg}of&v)Y1k6Z6OTerk`gNB39R z*kF3^r_}ByI~x7DFRZlEz}c=U_mf2>{5HGB7GFG@g~@M1Xp*63ruebV(UzQe@G-ca z+edhlHTWvGyd>5D04{LV+$fg}+78~*A6dp_{>b8%H=Hi4piRY{KW(U4%-on*IM7(E ze+l|25hq&}@nu6D8H52^ca9nydC8u1_wF-cc%!J>tBq2qpzI^BY?k?j1_YovhUS`;L>lscMv z+}z&?L*k|OQEU2Rz*16-G&0WEF%WAmnlBoz2#J);(ectb?AvO_<2%n(*VN_n`t7d~ z%ewFub5BcM_bSV9<}S~U21O{Z*WLTBjuc^1Okiin1~FFZG2QEIA2>S0T11dYm? zapx8&B`aJPr~;g3+<0mx3)VZPg{q3pKYuaE784YgD*@$)s-glyOcru5Le6#vS%o1! zl$MOvYDsy+S$PCFWtqW&ngszDTh`HeMHtVucEbqz8w5}mEi04YO23G3o>h=2KzSpL zLB8ztRk{QLzYZr3B=$@FivJ3se7nJk_;Zslppm39j?a0>ONDN1Chk2%|7#n`dgn9} z>O)Mfc9hwY_;#XWLeKu#(lr~u8|FNo$SPdv-Z(|F_>f8j8YFk3(+64|d)*T`XAh#o?w$EKgVf~XkI1~8R zXD%5<)Xlq1)qN9J@ue1+D0b;rduI`%Ptvb=X{h04#Q-&5@}$Oz(I#;8Z>R&ze9QI)?F zd1MqNkxm*_eRYd-obGUb275b~N03WQ1FokJ0t+x#wCQl2p(kBGxsovNSHSjrR>qe7 zUe~jaTF{Jerbi`%F`RTwcKq~}8)&=GWZb2kGfdy?NT($~7eq`2~eumDK zB>+M16a?0Sau1XLgV7jRn4{??IWfa zY1va>^rq}i1abEuYJebZg`b+#&MmPIF0$C0Dw3`gRj~gFSHT-qS*MkpFy_87nWpKR ziVo*d1>`XGV182mJ%4YDI>pULhBM!eAs0rCOwGEp6mQA{o2UqDzG2fnRU=JP zWwQP5?y*QW=EHq^##wZES7@`kvnR%6s`0*TQ=ki{?{+d;^m3kRer75xWx6v0*W`JU zIGYl}@xt~8wdjPkrZZR<6o~jfV-G16OfZ&Y6xcs0-elopupkW0m%@D>+U}v?Ek5Wf z^wsb%v!we~m_(GHNE^qh8+~5@TX*g#4QE;CV!)(0R>=`#Jbwd( z#@f8U=1_d}N)t^Fh5bifqrZU9|E^g2?_Q(czj%%6mh!)uYlYDDog*L&hW_C-njyUy zMMG$r#2t+{kxX99-9~88FOKGGRn=A%KD|fQO=xbtOHG)^+gow^hZ+YzKm=t6}H%s@LVEufLuE);9>tNHdwi6fd&Bi z%=2ykn1euyI(S7*5EclBu*bmAnr&_^AbX7i@f!n9_(-tUqo=;L*>~w{ z;aucUj-g;MrG9OExBy=>Wp`p>{xz{BT*q{gM=}h%QTm;ZWxT|%)|Ypvnw0AN-&)}0 zxG$|z2%APyX{mVmLY-Ok@UmvPbmG)HG2oUG>84r5z)BLB1&GMVp8yYd3M_`%YpazL*zCTUadvcDr4fT|A4v*9#cJLU9Nb2KJDc8DE5A z4lNgadu23^f-t>5n{|hz4&ium+Q>?0JtXuMsimmi+|Kgio|eZyxRYM`jBI|F34O53 zUj<7$SpCtPgFPWi`Nhl*3Vi{`ILkJ)X!l32d2n_{UP)T-Dal=wNT%hQ zBjW;TlV=gz*OO2QA9{44{3)Uz)^(*aDfi84&?QK>N|DjG!8o1z@wylo+2wVZnNfMh zAl3VHk~GCEe4e46lm@&qG!3MBp0~(^hl>4HnH-;>Q0zsj%)Nd1$p9OI2goua71@1GT$FdH3ozMk5ONapE(>yS;K#Waem^ zGb6jQLw9PIZy`qWM5lkLsu{v*DFMgX+{1|y=0miZua1V$c1CodFgom=rY3>JY!^$K zj43uv;}(hq@eH&=)28W6_`Ed&VmjB4$G;Iy4dFo{U5K|=#o`p#(czfrHQ(n|*$>9W zDcFJ;d!nPNOo8MAt)@!8h<$yG4&)v}d;ud=G-=-bMZt|#q@`9JD_xBtuNvP`Ib>l$ zt`B099l061hWqY}U{y!7d;R4dBlC5(jmqfgk!GP^t~{2DKl8V6hKJdv~;fZ1qbp6{{LntK@w%;ODodg?tKOG#Dld(z7YuXY?+ z|KSL)P!Ugdi6?N96bc&0Vb@JSDwmCsA4vxHNT)!?h6}@Mg8Z%~yJLqhRF^sIZYh_7 zKpl$=|2cYf^QFeu`lH4VuhGvY7}j8b*J!5<3E(yQ_S!%8;WhG5>ETc%u{(yF387z{ zrjR@aR)A-+{b4D}4i})jPyb(cI3G*HBWwopf8;g#C)oL46;1zTX)q4||JZA^SoQy_ z*Qf#T$ud75s38Dcbm;-a@PF52VQ%wJq_aF=UHEwa+sg3w4%4EPjoD~lLlxs=L*7zPwL)IvFwC3^GqX{|Uc9~w!Vjv`6)fYtG*Z39WH zV@Ufz(&!_D6-X zO}bOoVkizXfzsAwr+}s^hb}VK*y&@dsW1D^Lcu<8q*0_(ZjrperlMgCqRF_iqnub* zEx}}Mys{I=!51eOpQ{e$2itT5%#UfFFBW)x)^oI)YWL)@j9Ae;{X6%;n-F}f65g*V zR9Dl6b{3CUP>Uu83~3EU1k5<>JOJ38!K6Twnjd3(tCuA%ex;2;6c^a%)soEI^*)w) z+3oC$UP}my5Qcu`c86MkE}&t0=G@bcBbR045Y8DU@7#WNU83Dnu!KwH=YZy*mb1(5OSX3)MT2IPURa&40ovvux0yMY9!s z+0^E5?oH8NZdra#*J_BaZG-75^1rS)dVkSN@rPG_@;3U7mFc);?27U!rmBzkQ;?f) zQ(rjKAQ>#GwTIz1hOzRqPe+2Lq~QnS7Iku0*|}!jwZDASGZy+$c7GYBix)f`mU^&t z*o>EUg-w^p;53zFt-w}fhnBx8lb)p~SA>BQrSP{`jAWOXas|p^2q>2}aLu#hda&c( zh>c{c_^>GRSyU^|_m3AZZ||wv>4@?)_6=lysVMLn8OecEnuOoqzJQ-KL_pPWi44aX z^iFq+XCo+WY^-YHtL-a-&6NF)!=iQK$L@9_%Rh0r*Rxt?1v1)Y^*fXGOCzTPb$Pa= z1(|pHT%`wH1+TSI3};iqPv@R`9Oh>~>J0Fn$unQlErAx6c||-bDXdw_cawK5r7pyU z$(KeL8A?GMOGxFm`{duZJ5V_X&AaY0`2!r}GdpR8CR7#2C6a7-alSh?jw#z*X@)0&S1P@&m(6`{Suj`PNX%pTiHgJ#neCDT^Njenzb1YC+PnIZ2w+br$4Gi z{)r7X%vHuPf_3 zlxC6|VO`Zj*{sjj?qiH_jM6c*(cU}W5Mli>1B>tjh|m^YZI2*{hv^@!NU$ zvxosOe(nB)@%yJ0$p|odKi+>eelaGCXj@w3iWXK^6d2#W?}1FBQQmH#BPCBNOR+hV zS;~i{A3w!|kX08As4S&Y-+;Clo0BlpFoLtMzw`|xBhMn{2O57&-)qJwDJsD9Wp|Zf z7yi=r$a(2Lb;}Fr+vI#qrH$+GzydlH0ut+RA_N7BjnFw_%iP`-vPRd|*dVzXg=Q9S zN`7kGC|ZlxzlckJJys}+Q(BOas90PS15`=3PLe8~W-Rr(MdkYta(s^}jQw1y3{3d7 zivx1}Uji4<4N^~IE}3RaO$LYN^rbMvJ{;7j z)@hmF{HkryBPKtLzUey)5{Y$X4(USx-6|*O5#7_b+l&R0)td46J0gT<_>Lr%@V?1N z9}?PDp$kt5Kh2E+_>>xDKeVq?gTO~?P+8~QhEd(B=b4hLWqte`<{?#Imj}OEMVhXc z=$F9og@BdwKwc-fG=u3U;JFZk!l^Ig2GVjZhrzOFRWo#Wxwt%^?KqSP<7In`>uBM3 z3~zr*HqcE#o>kx)|B;Gr>!QD(;}*maj$@LCTOuHLF|#YM+DH zK%8=!Q3M>(Mb?&_Yw6`YFB)D?JSx&if;-^NMcmKniAs|# z5FG`QRO=0f_J?hB8-TKeYtPMH3$`r3mfo(#jp z@}99R!^(Qgi%ORiPvCmCr94LYnq4oi;A=^8*67Yu!5%b_)MqonpSaQCsV(>}u?mXQ z6q{>8Jnx*YVOCh}c*E!KMMmmvlt50BIA27N);#DL5zrzq?xe(gvWUCHJSTp@F$K%n zSTOSD`NA6J)Qi)c*%iNhuhE+(GrOd+Hx`+;!)RD%&(%L3+?Zf8fAhh*^x!Ehe6i`+4yeE(JkniGrWgNOqldLzT&d>&r`-IbvEr=CA9{6 z3bJI#rCAPh%9tUkcQajst_S64g8pJ1Sz&%Hqyy?9n*DF4&NWX}_P93$Lq-$$a`Pq0 z0I)e}%5ENMZ+q`iab6IcyF_6g1OPVYm65Y?))O=Y{W#%~gfS|6wx=T93ZnU3ANxCu ze}bIBn$Q~^?T98hj?RQ*goQ#l$tPk42PRd!wg9jBj&;Pu|IPLDdH$%8$+?`8BS}9? zZJIf@j=S-i0v4hwaTJ+T%ZPl=g4w;zljoSuO#eYn&tcUPJ&tg|)K2f`NA2tIGNxX= z6Hi{5Nn0PoBl_RRQ`#}M_#GCJ%lK-Wbo_Pjg?0Fw`hi8MzkU-aNZ<-xr9J5Y-8tlg zr2lxdN!uwY9gp2_I$XEf@o!|8eIT<};8BsdiCTA!UgxQr1!l|mt^CMa@GDi36&6C7 z0B+xfhZw#bq)>HDRjdJ4oG9z@DV=%O)gZVA)j7ZOsM$Jjv?6(-Dl3u-wN15(XSJ3`_u%62S8aWT5Y8 zZbUV8wR13c(RVV|{o8T)FL=WLb{PJkn)zY>K{f01Cz%2AR+SAv ziKwkJhj*M**VABy-(0=?f$M%=K6`qQaoOLUF@PWEW+r;*BEr$VHNx+pDTntsev!O~ zR^D@RNte*t@OzB*yawP2J`oJ;8-`3Pr2-#y?5p256>~a6mc3KynaKxsX6| z(A3za?Rt}h=g|4x$N4msWt1w(II#%aoZ6ak`}r&JgeT5X65bu<-AyaS$ff0snL?n=v z|J%!XGqT~5`rht2z<|(Zr!}3l!WUZJ2gN-j59WcC9E~WZVV+0A;sE;zkDGS1dxc1~ z^}gSo|2!;IjNYKy(1TJ@j*fZ;We7oR+pivpVCWI*EgQ)x7Zi_UBFEmgmfiaqeG$}- zFUrHvtOhA5l5zmq|An*c4s!VzlPalK&lmQ-wv+(7_O%xk{X8P?9rh$-Fwwxiz!mUV z7tE*2-+bWAnH_^-z+ZA+za`4WGD+Yro{Zt71*d4 zDC8Lp#_CG+1%baS@-v0=@nSo?I+6Rb*cA+noPgx#Xgn_JbIz?&cErHA%4(oMgJUna zzI2Bw?NGqQvo~&Cxdkrd)eo&O!JMQ-7~xCk^amI;$^9%gn1DzyStXfNxW}D6C!15+ zhHdzMpfpCD4M(hcR8D+yi2I^>lS8y?ybbDH&?d9r2@N*>mqDe6JWZXpseH)W?-GqY z0pi6O35#UX+PxOyPDKD?QsfgTM02Lb@wr!_k+eXDUE2{rZ&Dp(X z_v-%F{ElP1d)dmyGoE{#=XGDM4|W@?0&;=U(~eUxDS?|H37xHQ{@g<)OEgml6 zq+|!#)+6F>N=8EX_rhb+Cu5ifM%=0F7Yg#VCQj4|HZS&{*}Vt{+_wbzhk7qrvAe`!9Xd=}pw?dp=XaI~P zj5O4mxM+S|zOW@h6+5hAo0-z8+R`#nr*swVg0MTM%@G-)oc-c8LaSclX@R>k5)PkL5IDwv z*^|!-X@M80VIp=MckS2B43Pk94(oHUiyP30ip$e-R^$5f1+qpE&~h@~KmG(cxL)$~ zVF;P=%^Wjuh0qxh!u0wGMLr z;oGVC59l{1l(wT%v>k1O(A8U^kViC-QQP=p<3AQ|RVz22ZK?h;=c0c0+Kk#vK4Yt5 z9ufUD2Gu)u?DA$2LHv9@;V?UPr=50y9ZfxZIZL%S(y?g$8gt}3No*?+p_=~yTXRmV z8`f32ib#In@1ugAoN$g~I@K|5T8gIEcuJx=f-?qhd^AM_Ucl}BB7I9yfeS1;LXP`A z=D0Z@-YGJ1O(inP(=C2OmU3At{E!s{&iwS_D!nwGtg2_F)5wS-Bm&`+ZOecY+*A^jOE|?xN`K{i7oRY+)RkIX^sVIB+HeCC;saija!FK! zFia$>RZ(Y9Xb`tZV`Y)b<9rpTp-?^HPOH|c%iZyK;pWotiOm)P_d&a_h2kG4)d+<8 zddz4!S%~}QryH!qvYS=yjTsEYE&^H&d~H#dI(j(ab?aZ6gY+#$p172@DI;=7P>A(f zhUZWePdZt+4h0s~cnXwIm#+-+Rrz44T7;+d;kx}BH(Gpq-zj-QuA$DbJP+0$(l0zR zB#nM>hQSA6Mg#809@p|Jyc4bg0+*|@GpDTcenilogD$siHHI+g0r)GBke}>Z9Ju{a z{ft{wviAdwO`w1zGXmBa>R_wcdy-kJ>|^HwSLZ@ot%`X71|Z2yW6`Ot7XXy$1qdvd zDuiONgJAUYq-Vc?A#y>vC{5iif!F%Ny5|@sVO<2_d0-%^}_h|M4Nr8 zC+Wwv{{~5~<^!fdRr{;qZM(yvb(V4jMx{unOK~f`fw4tHFHCfV^#Wg{V#b^crv0M{ z%9Kfga7|aYTK?W?5bQBRT7ZZcND#Au@!1&|3*&bpgM}|aheh_rXV68gRe7SQa}vq{ zdY-EVb0_T-p?6l@ZUlF2xgKo7=ocG3?glR%A1~r`zn@utvXIum*$v!!P28HeJ$S^G zS*zO#17BvAc~Oey2}S|uqKAEG{+Pw1*6QG{IG22*D){CbIj%jF@asT_BqWHm<12D8 zr{$thW0lk!>Sb_bs+>H<%gS@G^B5Lu@@iwl5HD{l_)Y8ADF020?)JMEUd#)(u!nl4 z9f8lJIMsrM_a>eDk)PdTh0!Ewibfq5`pEI-g!R|Q!C2A&WzH;d%q(0oGBc^GX67SQ zjO?qG``K>_QFpa1)BG0bB>edW{AsE1=)|}v>&M@ZD*RzP|;0H zeL`5YkLt#}+15FIeC6g%>Pbp5uP$?dMsjfVAP*q$1w;A87%;il-^=eD5#yDZ^rg@U zTGTCtN*SvIB?ZENAb2QQI!$rmtmVf5w1p781-9R6CZ40xu?lkNp$#rv>OjS6Cmgnw zQEzD4KzsvHN=4^~wMXp*W=eDMRGe$#A;!0HtVsm>1kS6{ufaxKylI%m_`+8O+`RA< zSRNsPU{~#US;iqjQ^vuKu|gz>S@gDrKAYfx)HVAQ33z)K3M}{`@d`+_Ep$t)cj?TeN}Fn6burxZ>ln^2w(BK4IkkNu|0 zXM&p1&Bw~QB3!4*43zV5RP#9~7Ptm$vR^GiBig!_V(IOu!2Yy~B8r0R6`wt_5>NVx z#K5;0L6=)#euf>I-F>a-J3a1n@;LTHhfn_G5a^Yl*x6g!D!N_T#I)zDGwoj*3`Q5C z90y0%oijnRzt6;GZFHAKsSy);o5@p5ouAlbohnX)wg;fR?#m03>u#bo?5lk#usGXM zU#xTG1C@aKfI^*qM8u`V=_>zwh8dHcsiYS$BQOAF1d{)IM);TJ=l@6*Y9aw6g7EWm zXiTL92zWjxw4j(kkT9g6N+f$szd7bvDq8ya<|GcKtmA$7rm3{!-r=$y+>8JR)m;Z6 zw$`IHULQ><8iT`2lDSgM?7A8C)eW$R^IDh*uJa&W;$4yimXeg^$LbFG*h;ndveSFY zu?lm`)DUVJFya%QCl7wduuqL6pXFEhlKcag5IjcuII`}Da>cK86~*hiU}`fZmp-QP z2yNvXL=Maikq8bc}i60fXf;phs ztq0vo+URB4YIue`955v4%~g0eFDVLgl18TVBb!Kbc}cUzi^eCvFaQ38-t<2Re8YY7 zS)=@l3j!X<1Rbc@llHyaEeLU+j>|?i=T5RT*PMTA(QP@6Dt!x^Iy>sZk=$Bxd`<9 zITG!Ou(pSKKk96nerS6-X6aH{SLVKimU5ZC0k6Oo{!pl!5i5HfGW&PH(;WeEAwQxBNE zep~6Hdt)sJHjs&OWK^XLQ?SEh@Ts~mxiP>GT=PLLTV)=D3&u^i1CBo{L7=Atv8Vef zicg)^d4-mn^PEeA(`;cg@)J`^E@Ryrr!Yg@rxQ80lUWF3;*r}Um{B(7FTtG@Eka8n zR%#DBUsT19zZJ)EHcIg59m(@w|4?&5C6H1XELTpw-ohBQwb&+RoQ!=q>r+(8&>PmN zI}RfHWI-|KOOLr<6ZX^HWiUF`%m#Xwz}edBv(}sUn{ud!FtSu0|3SU>!)nLqvs~8> zgfY=b`u#Bhx-=qAbQSPe!k!`bMXZ zjaKF_?nJ8>s_9bH7s0epsx-q47Ddl-NXgjFKa|sCEYB>X?xKTSW(D4RJAT~UK%K}O z8H(dAoeB|Cn%qJi!7qEqmtL})Ew3-%frQwiPq9C9J<^L*lTQB0HijfoU0j|X@C8(k z*N;_-)GIOF(7%@6I-52p$TxLWARoFaR6tY}~6gPoB&3iG+ zT@#J%{^d4e+4;^-f$@nH9p;8+)14k?r&6`)Ve(SvV(Fu1NMcHlT+!7Yk4^Y%jCs%= zJhM>5;vV)l4HtP^TAwIqg5+>+0VSn)bI?bQj}=^_r5eO-NF4z~Oz8?Ed@^LO^i@=! zpYQ_M(nDlAq_gt0xQm&89B37JJ*J4tU#4yapI;_?L&_03F#W~ik!!1VtDMh%j!mN| z8dKTeA7=W603_@a@LlV;(?Jm*9>a6GwLBU*0xrMPo4!o%ehQdORi`Bm`w(0F2UgqL z8LbN42@DbZPVLcbToHfo)y@C;^zt5E*0d}ag#?TM!hip0{c{BP?>%jnsLHtBiyLm* zn&*%-IqTMUk|`5lv8#o(GxTeBoNLldCxmuSh-V*Q1-dHzyUqO;8+JljrBa>^-n#1T zqF)8jh-Y7Oati$CjJo?jXhlaSzRKHHkLVI1_q&kw6n3n6ZXA5SIPg4of9QC?6})a$ zhvX*!@o5YKh5_m_|7svGYRBu(S~_HI!H2S-j8+mse*3DTpi^agYk?jtmx2HJ3L2Bl5{9M8e2DsexAeKRyLSy3Cnl7p-3 z7h-@n2-2t)3Mz2%n6d9TzFEBV^nvs%^7?tqym>S)4 zOrrye=1C#PK0~=qO^i{suZIH3U7x?k6$}cijglblqvqp z3{qYwkyNf@8g`dFbx!l#-Ed9FH|Hf%kw7+wJG%)S`-+J}s!6oz; zDYtRq0m^Mm_7S~4_JinGueLgc=c8`P@>PnTJTnL^3)(biml7T8v7G@KP|JBo_`uXM zO@4cwZZcvL-)3NQ)oUzvekddIB&a!&2~6gX4Epb>V!4rv=@^Yv6&#*yToNPPwDfM@ zsL$J2zgS~r$!v#Nf-kK!0tGMA@@Dis2myy|if`Ac&r@adOqzELnNKjTfR%9!Vqlea zD6c>YHWtsYrq)sfjHk#i$Lo&gp9x*g7C>?r>>K%kK%77b-b3r%uo0z|J)$}FC!&?- z9j!3s)Dq0z0~a{OHyJ0$8@QLJh$99U7|+*w1dFio#wD1X_g@CkX8Om`c69OknomR= zuy6D3($>h-n4G@NVx~{*Gy&T&QQ3^Vac3R`r@4M0ZoKR26|1CxS@;~Gkw0kf*oI#c z2Gy|TI7g(v9#k{Yjj)bOXdU;+gIqPuA&sfHmxSubrKuDhFhU;hgq1^ITJDdJcj-Z_ zTXo&i!|h6$0WhU&Zw-lEV#KFsrSI^RuiGz{}C_||ib&Wqqf ziOiFECLj6YcT6{>?hY_?*61HsKZ`eE26hk=u&X57b08?tWI+`};?MKbzpTr1E%9_S zO#p(BfvtXk-jtrq*s~1oshN0d)D@HTVwIbYFh1|ZGp3LHwEGDQi)K5kYhq^xcD)-5 zv6-8_HvK!T=GvcS0tF~|C=2AQp+Y$x8Mdcx&^B#7YEN_bNaw@j^HWphg_epfzVIdF z7SEGZzG-VYl(@o6jZd$L#jyN4xo=8}cMn>#??d z+vu55`+di^^E9+^N)6hX93GnvXw=;IyU|=(`Stdf-Q2%x*HBsdu>U>?_)AFnJ(2Mr zQW;iCR??qUKk&Y*LksRUIp*D~m8$O~0Gt(6ar+Fik~ZSx*z3oOUYK|~^zYTCt7k!L z01|MVy!8hOsIg2gIYGp!KN>Y8 z_!4KfD>lnbNJXFtETAQjpYW?zMuC-eLxZbv$WRV3U{zF2-bkNCW1VyJuy2X!IVB0P zS`s2>h8U6TPnk!bj|10`PeN{dR#4HSzw{|h-YO16D=8L|MG_$O0;7|7C7$fG@Q@tx zLvq@ta_ubZ+B{v;l|%jj#=h&H{sKyk{kfJ51io7TXsc${PKma^`;GnBDF@iJ>m2s8 zmZ=WznaLCobD?1v&Ue7`9#MwNeZX?H+F4@}h5PYy4Kx2SH(p>jSPku=Cij}@)Nbp` zm$_RG;o9K-tV}=Pa==L6RHKiN0-W!m)!C*iAq{amo@zCL&&_F;$nWG+Tdnu=G zI}QA-h$i+eAu-pY-Ail8#uv>L;DxGWkD)UbH2Bl>) zCZ-{^!*A9-`JG9GMK_u@DYq_!5X0pXzcMwm@`kR!IEv|tSh=d8E^K-6@rs3>v(oP_ zwHSoy4k~tDde>qoF{ATd@uaC|V{4hqj^i*KYH40s8g;t}*sJ&aKG}46Q&AFJeeL$8 z%Jal${sEQLcqSvES>&f2y}6)1OV@J$>m?2BEx9XE%(rpYnODC}`#Q^KkkXz}paXM` zFaD5XO<`oW+)UNWxfJ2fojogzi&*ScW(^tffMen(=izWQVBIGycKCs$Hs8G9+~Nkhvx;u>P_kPTvZ1zTAe{B1}(nq2mY|Y zdJMhY@Hv9R>(kbfY$Vfi6yn_lDNbhRt*p?e7&HZpZ6swMv_?U(0hwzr7hOb$B|o2v znFd|&MVKy3`=xZBjBj8d&+1(m_O+w@u5l_J37@rCC{gRTskKWheyNz_!Zh{e)0NaK zRG*FqHpytF)?pc-Si2h!DT`E)pfN6SqOr;L$d8`AW-$50)Tg3Q>vZ*_48f9@B9eQ%CIL4w$e+1U-v?|t7j%^A(ZF=}u{##k zAS#Q&w$f)E@-dbW|8N*YMfb7*#BmE!=&~EdK>^;OMqwh>z_nJB#4JK1l{h6iMdY<; zdPA?u9Qnrs^eJ)}OX=8?rrCN1*s@F#hS`=?+{{9G0SmcR0QQ%65|H3}8uOb3{QOM< zP5~r90zd+;-${V4g$&4FNI;DF4uAyw{DTCXy^{c;2-Q9S2{`>t0+!!NfUgE}I{F2U zsZ!^7aj6lqYQNZdHbXqY*z}grCrPij$CM>Gb1D$H_y|5Xl65-?ymMT-Hadc;$6Lzp z8S>5ajDCYaAB$^x4ck6Cv44JTS)nQsCt&w6B}t$*8F$pEpa-;-E)B4k6_3}uxo(W4 z!f5WuZPWuuK(TK=K3Wxk1gxO_D+zc{Cws~rR#N_b67ZL7vK`>yegFNNH1v;yH|dL; zl;*|v08Y*JGY#qive-4h)lj;t#{Yl=vnN^GWGBRcbKfv z>d*a;BF6bZWCC>{K#Z1T$UdnO^>ABPbEs;WavU$<8%UJqLwtJAyhuQ{lAv7>Lsb># z)U%GaIR~W>LP*AfA;s-$&YZ;1@GC=2PT8HCz5SZAsV5o!bDfD^5TrQ8YR};?*U+SlW%3!`^ z3LQ4pYP&mFLulC<bwieT;FYAxVk55 zZq`W3JVp9(dm^@kJOw)X(_MwCqK$nfz%y{VDY1kVCe?jpE`uLm9E097IXRn*XNu%-bpjeac7t8}Y z+h^hA#jZ04yGj>!IUF7gW|3N88pBfW`?7P+c?t<(@}}AqX)zhg837s6g>^~!IqahQ*!jR`p7@3D+Nj{8Qt$wnFtO-Kn-kDl8$z6evm~ zL|OJjHXI8DO9$8u_F+u*;k^xOMOXdpmzZ2{gi(_PmqxAFr^jj_eOmZg5?f+~zJ1=( zTMn*UNYQKA{aJhcsw}Z!bRCjO)VDg&(x3tc!n)FhGE^t`TDCji8hDdf;Crkl5!k64 z%AiDU+2Fur3>MCGAR-!TiI(XMMl`alMJ(nc?@d-H4Q9>LW3o6}A}8*%F(?VE^280jy8dPjDCm@KI)HWFHTT_t3VJVi;$f%DS|C zhU0G#KyEsujzjDRQM?t{65&%ZWdv*WY;fSUyNbu>q1U+Htj|yXD>F>?<6=`~R*8^P z;ZmI4^h_isQ)j@W#}KXePMfiKjT1xq_U1bXxa9Z^0$hczwRIf82(4?j7G-f$LpL@78T45D8ckAQaOLZTxp z6qBmR%)~Yp;TQyQ%KgFe>5jAWkwDzKRCPrp4N%4QO@+6x&M!<5aCJ5H~6|`o?G<9yoA~$ z%OT__F$5I~oIF@7)dTw*)tS`4nnLg4f@O3ep8p3^=r3_(MZi1i{rA7#Q~zcPeQCqz zV;y7Wuw^17`=V)UWTvJ10BP<0RfKc`Y!(Ad6LnF?-l%Nf(bBB8?;obnAOZcCf6fPg zqJZe%C;$b#De2+82lN5pw*q=VFH-1wcqGBQOi+O01wbi5fZ}@sAxbCGK8dG=7u&QG zLYJ9`?(Mnl#vybTHVkg%AaL~34Nd@?y9o2UA$`W16~gjY zln6;=Z`FZ=jE8rB)nb@D!xw#Coqmg3qgsS;pIyArUk7@aE~bdQ{~$k|97~5%Jjt+N zjn9Q8)~}I#8kT2`aR&g^IvPE>-|gz71U#nze`9$|Z+Tm36|cb*ym7GG5MiyOrOaeI>Y=ZDIw+hu0tYQKrSo5{>DY;b3YA27Zs)Hp`4UNSa z?5kcSY4)U`s92u)_v-zFyjQqyZPqVU~iNu4b zyFQKaE2qu0?USxw>pL;d-0cVY9e9u$(%TYm2AYMCCn&_8S5l@OXNwCIl#}X{<1$KY zYFt6zrXuO~5;#ELG{3Zr?6`6jhTpczXYnYlwVEicq{A!mdszTVGxJ!Kb208(*%3$aV)Hg2&ZEN|@bu9c% zR7L5L7U~R(2itD1THfh5T@gOfXTc&tv@TO2h0cT=H_FPL`6qB6NYX>Is(HB{r*);H7(`rbt3?Ai58N= z%yJnBx)z)((cp4$s_+U_WN-k#bLodAzB|yRh(P<)jw|itk1*H69z?J$f3p2t?EP)} zmMq-S7;S6`hrSskS+Q}iId_z^kQQZFAa8!%GB3-dk@C)znRVG{ZAUv_j1^WYs|mH# zycuJ_>&XTi!98UZ!)vE%p*NP`;q4`3*m=j^-*DF~Fp80e@3E2fm#vM9xZi*@o` zur$2J7o9 z?dn84S2E7fOpZTbJ~%%tsp~8*fGW-}f7v>rVl6~)3WwW>jY`tymR3cfzIPC{#d_af zlvaLF)FH0wS>h}{qWJtkvSQmZqQH}(SSD4qLSN4q`ECk*Nwv62yMCV!%!rUvj^^*r2Y*Q+|Cdm~KL~7r*oEoII{LBY){3@BxD;s% zU_6NbYNbGQq!mDGz=xtK{At|LN}!t7Zt>j|DkS!vvw9y7etk?cK7Ja+sEP-eLi+$y z$XGmvAPydoLVn)^@oox@woL-^$FJ>^o}2EQ59O?SBiUd-(!qd4d>{b*mHLl4Z`VwT za5I!7W#&($L`EV+h4UmAP4>qb;0wF~PCn&|X&+_s+DpAY`*WL95?F7?YxujMrkcq& zWJYC~h`sNRHV2CCRY3+04iF9{CC>DK8?E!3%|eAQDU5wVZM*=c0-`VjV&(Um9|$CF zt-$1Hvm*r4BaaU*4Ld6$4xRGJ@TkLeB$OqWCN?Ygg=QK8MzT$(f&7lcr{Ak`HncH% z^TCxe_&dN9nx8Rr>GlZ;w@3M9#eyU?3{EiUB09bD^)leb)CG3MGu(S|ysB~0vlWvM zE*PI;1xu_=O^La36hpi|2=!!((u+1Sl!b2zU5rPz9um8HG<$=6MIeu7%4fX+=EmYX z;GwZ7P%)i;{?=aWd=5hcap`#8nV;)QrLh~FjQL=ndyUF{O3JOEFnfYDOuX;yh6Yg$ zLv%(-HIu3TWjq6M5>%dn1}0RyaAS#h_#m1IP~r^p(G=S7!s7c+&jYw3q;KdItewFD z+Z-nbk`*KP5olH$Jbp{N=m=nsx)Xr&S5(5l*S|)5rv(wCzQUO%3=R_ENR;j=4cc7a ztv6bP4`Eu)i1ulR-gALJg0vVl6=mmXU#jP%oh{VaMxYJpQnuQf3EPiDw(|ENNqmp!gL5VOMT=hY9=7FN6 z(1H00slnDHRr$jA3tNJl@TxzIf7YA;ak-QJQLd{O!kkwC@8RS^;x@0cdU~e4LgDIa znyz?q+&$xk7w#_Q(bIb4730E6Z@_O~oKx3d`jx?J-74t~j7p)zDqXL*;uGspJ~_&X zHEHp3y!BjFT7Jp0nR)EOy0pS)`msavj?}v=ZR?J>owl8JOnNXd9$G}UzK_iESk`QZ z*0@3pcVGTLnkiwMMlebjC)!oPIpiKBoIHFrn+JuA&g`*FJ{( zyqiLuWIr6#mkH&y40f}O_L9s*{9<&BVOR#L^7r3#t%Nnwq*K6G@1?6PdsN~i(jb2{ z7CmPa1S)^yemZ&b-)CICXYg;h&lQ-D(CAi)lTM?D810ZtdoEy+kdje>;b;I12s5u* zB?67_1A_0QaevG+U_b~13BxW z4%GCCAhm@ZfOxg^=}UF#RSa-hxMdp3$ei@jsNy5lIOYJIO2Mx2H$Kfm+YcP=8fNo| z1&%w=r5RLXvwlVfGp*qj^u!hZ09UgSxjLccEXT_GbdBMs^6MeE+2D;(XONut5WV-TLq93h{A32&ML4XvQmD-b{Z+{~hoHH(F4LD7 zrE`M8C1MusXg^@pGOtG!b$VD1Dcmox^0!HpI>NGMgQXwC+8&C2%$dQ%FAj!`TL zty+5iqL(HKe}Xl?ZOLOYY!%Gs(UK|nK@pr(G};?-gT00WS|#D%7Z>HX@aO+OxI+Ju zK>iQ+U+t)Wb%nIhLtyd1@lf!f)VH>UG0L>-Efj5Az4>gi`TulZ7AC5EbzShEf4D+|09Q!;4_C-z*Ysapq0PVS*?UI_^~Ll( zaMqs#bj3G5{MkP2kL08ynHefRmu zDBK9O6XLC)iQ3=}ZW*kMlk7e9LJwGTDhSJuznz3JXKeA{glqx>0RnXnM%-@Sa%WgY z`%%~E9>WiVcUNu&zb@-`ueC~ZU{R6EP2|Nf#z_NM0rQCp}e(WQ`Z2?@6&Yqz8G9>o%Hx(!d+FKXCrx_!{J10AIO zCi(Tr{){B&*SdQLUzcRLT+5GY^*#-ZiACiCik5}BMs!z*jpuMvZqtEU!_|-&T1sOf z6!t-u-Jf{bKvC2c3N2hz3lH(vCHy|>TV!DhV7v{cMsw@v?YY-2TH%n;riEF89r8cy zaj(=>Z%1Eb$lI(hN1gAnsf$UU7GFfWt>ypZ=#eeD7L`uLf%=55NUgGRP6h4_lMbblXc(1gvMu9b6$yY z(UKE5mW%94oFhJ99-1Mqrs)z&vYW#J0G)Dd}v=SuL?^uZk1u)}NMCaK}P%Q0!jaUZuauh%wK8k!g)_{In_wrR;lGcu|+m zSoM_ns;*AV(M%hYUXtuaTySn|KYBkp(Sj)GLT70cl+izh7nlyy7+Vb*uz8KA#euFs z@%`8?rkyJVaTym3aY=r5!UGKuvNMX|t4^q@Q!x;j-l`QlHA?B?`T0^i~j zQ|lDOPG^V&oCTu4d>ZM{&BqL{)yD5fL|2gdX{*JztHVRY3ik-#yD{R`sn=8cGqtlP z)l-47LA*J!+f2%p*!n|P!Ff}a`HP0-;e+aJC{3VD0&1fDMrW%|yAevz%Os;(9VEI; zk3O%r?QMAsrysZIQzk!;ZuLzh|M(7EiF%-$WnRo{Fb&M&sWvyE7*BdW7(Rg^FO|UC zAotzJ5Ho*52Lkj%UTadGQ`1nMY&7M2wOik>Rm-4UD|%8xRC1tCZ24z7tRv&8G09J& z-*~!=j7%R76QHGxs+v*E*r!)T^VGMiAy{9v*J)E%o@Q0aPwqzDrl)4X2(G!G-jFJ_LM9%M9nP}62Q5S^vR+xjj8EepT zklF$gSmUi5&ROpxh;3B3G8;!Q2+OBD7iMp;+Jsul-_h=M<|v(`<~6^fYErIKpxI5e zZ(PbvPQ>tHD25KG^8^W&TGnRzp?&JFG30lkz=n+O$N)Ho|4vETKab%*&7%K; z6#jV(V@?DlI@sh$mNhl((Y*NV`c0q%pFt8^DszQnan_+L`59A!7j&VVVPa^TRCXcW z4$e>mQpkZ;^jm7_~nX*?P`(bNre9JcL}Dtw0ob5Z>@q{S*g(V=1?i1HALlE}#1H;C3J{wgNv zAM{0tp4sr_fEj^In1KxSz3fz!L-%zt=hIkzbbs7|hPrmVQP1jQ(lvfC@mCp{bg5HH zZoFLQc7kfA#jN$^8Z|g(rKX`OO8EN<0rK1K?s>|q;+QdH43(R z?qY)(>a1aEW!kK#L4C+aCoG!}GiDR!4MPm#PD%aIP%GrG_Sa8nEl$LLc(&^2cPR*OD zo?F{OM&Digx*}R5i^<`RbwJh}nH~DFI|8PMBXH&@PUev5*f4&`(tHY4xp<>)o?Ip7 zcjvWq-w**-soW?*7=ZUZ9@USYJS(dHKX@Ar2cROcqhR>$7U)$(A7}j#!f=1 z_XQ(~7Djr_kF><9)K`csbJ3S;1JeDZcU^+LT`~EZUqE3sqt3S6JcfdBt@{k}Y)-xvfExVwpKcOAI z(IdBYHr|?PyhU`_NSh3&+>(i7SETdOicQ=A&<*5*b2hwUo*QX?EBX)Y$9%8|%kLg* zO6RCa2Jko?n;*FMMc&+=^oX{-SJqZ%AqceliKFxyvbKI1>_l;qk6+zz+Je=9QlM!@GJG)ZJVR~ zavE(uYxEj7qT1O%=lEr=b^4USkR>;KY9b@PCog_sS31bB_SR;c$NiSYqM^)n`NcAz z7isdAZ&SHjftv<2mpHl^mX|$)4epD@uYc=GAeJpA83K@nzq9Z3&-3^%IpqIf*8JXg z3SbL=bR|UlI`WH0TjK$8$TWf~gtCTqt!3xZfhw;TcgTsgfE+T9CwZ$qAcqWol#?D0 zp@S4bpUwq|`4UXsFBRdfQ73@Tv7TOt!UwCnd_$ON_w|>D&`m9iM7v-`egDuCRNQTU z>za`Zzn-;`Ow}3B?s(w z8buYe4zTa^<+p!?f~hGfPS*E(-|6RpK|>)kK(ic<8C&GC$!2!c_AH&0X;W*t*Qxj5}EUokaZfKLl1E$2+7+K z-II;SSU>yCEr*FpLybTi@MtqMly2os4waoasLFT%PdeyChwc_Ia|aE!H>d3-Wa;7f zw-L7&u1>_cj&JsNtlhiCHDy%C&+VKsw2^=K|rrZ1;dMP*MDF*NFqasQvP_ zCV!Y!pIq#9P8uK#b z+|rRN@p5AwtPZ#p&P{`FLZ>H0KND*wRAU>qb{miCN*&W!e(~q4Hjv^t3WxZ`Lg9(l z?cgj;eRL|?c6)d(YW(4PHZZ&jtq|8@Wr4c+=@%6n)C;389XzN}+?mRhbKMUKAM&6djLa!5N3qs;a zsGT*%F*tBih`)tk1l%cHgJP+fuN$>2Iaa^6s9oA}w4qLE4jP7-Ex7;Ywa-9eZSLmT zQZFrQR-ekDeRZeNZ_>aTlHmg|k;p>EO+@_p-TV_hQWCVL#dqp=VYG|qJZYHkAxnFD zN`*&~>(7V58l~0YQ|j$}bcVeO<28ha@~T?-bknQPTkwl((cwpIRLLp=g*Etam#&3Y zmKc~x#{$cd>`UMFr1PJb6(#En@jdz@$Bllbh#^~YgpGGeU~4Y$`e$vhy3VXGQZw&joP&Su0o?(1Z_NFxbv>cp5jnrWCL}k3m2%2hh zvk{GA+O^<5n-tYzv?^3}#bS!3ns&7b^kcIin&jW+u`Ha_)ZkgPs++c^Lem?6RCeC8 zz;9q<>th%x1$gQsjG;sS)hLN+N#gfPmhpo!0@ ze4_zSQ}PWl`zIv>u-E*vw$n0KYF7out>MuhF{LGnAavyo(pv7|RHxT6sQ8148xW8Xe54y{Qgq267wa0L~B%>Wi?e*%h;K4W`EQR{`{W zY}h#dX+-_!*zkAH-~a!q!Ai;f-2mnLr--Bh5Rqtpi%8ZLbTx=dYMd3(R;Mvb#I@BRVAgUbER2R-9b;p`Pk~+3 zOPY$VcK9*k92oc+3m&QxLA@8_r^<5y7H|s#<=21>QAyWfNe_N8QLH|1RhVW)yYA6y z$h>4Ce2**ch4oOUhw32hQ$_dwBCe}fpG%Hvf4lP0Z*~JRZ?qvlKUAJaZS&ZLm-Tm7 zvhO?V@|t$hN4RdQ6~O?K$<9eMW3&$wv=8+3Ng7Ia8%4YQdk&Z~T7PsTXv8bp;Ua`> z;|G5B3Vp`=#x-K*c8Z(QyDf*<4U`B7dl7T2FwvH_gl@F}?=#x@X(d@tH4^u8?Ls|h zR|5gpD;i$leDC)(nWK=O>r+4TLXc{4P#Ng64*_^cnr&y;=IcsUV!oIgDN#9-l2`h^ z-)qEYQ|jujSv3cw;UVv-D$^1GBGRF-(Li}S@U-0C*a(TN(H9wQDfvM|^pylU%+EHp z01@ds0-&h!B(ydI$*9~N?eiu_JE(rj zjrE$FlMCQo(GU=hoJ>?Ntkvd7IG#^&j-BZ9AUG!h-5f7z(=Xi7pO_Vh`3;D(>IO*f zO?vff7hQh{X(><<%`mG9iQp)n?hDm~Hm9y=K35GdDK3FFmo8|ID;&rGsi@nN+!%Fk zS@MTl#WUfdAA|I>MumM4&cG^$b}2?T2)1VyD8QYu3%X4-5D9gy6rgKh7lH+l22bp) z(HrlY9mMNLM;M*#vhIa@SAOY(t6?-RAi&D$K{Vcs14NK%WsOJmFJC3dB&T|$98091 zStgeVn1#Ov8m=VQT91IMMrho%l-v2N4tt3uxIyOxzdgNW+x4{`m1TFUuu`@diL2iY zms?XdA3vAZWEIJ!-nruMet6ptH+)W^X7QHb?(@UT8gU>&%zN~}&+_qS=B@Grdke?Q z`iLBrErUu&_8dsSqxr)SxDzsX8O094R!Ws>%%^akFZvLI~hv9j^%d>AKS*Qu7{oTJg}$S|jpK{!tfRq|##jc1Y* zmDoD0j{U^|G>dsNcc8{%+^=?$Bb7^g+~NyS{$C1lDf!K7niQ@qlID*@V*Lm%*vOtr zL|)KFdn64Yb!89tTUT+P(6dLQXG<3qem)mET)+()T^PNqNbW|+0)MDTK<_FNj@){C z#=HlynJD$lYExcqwANa?F*99EyiViY88eG&iRw&jO9{k)R&hAr#xy@bMFI}SKy&EU z99$spj{SEP>6HB&^t+1mclH+jaTET(=7m2%gL{WQX)38ae`#E^mdk$t4GcNH6PZ`x znIZJJJY3-doRky=8<@iWum=m>;C$JVS0*8t6{3Gk3!O~58}EsQP5h3UN zSN$cHEDsQo-hcl~M*1VIV8y^w@JFZek#&i+<@6p%YlEV`jg4J3bES~?k2f_=(gC~)H9v9& ziv9diy@aXk_U>46aDdaP&lKAR$}}wEE#jlLnCtd*vlVd=sla!9AeP$Hk6r92H1QH& zUy#iwDb~8vcPVc*hdQG@5h;P#CxCnu`Hj@IiDuWrGH7uSh?3#^iCY^c9(q%!s^ctK zeOYNo?&H)X_jI4tE%^=su@Ml#<)Rm0&$v>L=;!kLb=0m$4Q~jG-saG6w!Mtm(dfs+ zkMt=E!h-T>7cjv=B->?nOVdzXoc(zl%5SMv8$Fu9)8m5PXpM~W_Js*-5=(f|ZWdq{ z;esUx6svht2Z8HD0=*`RYnQfYjjOtBfWLt)%L6<#Wd$l9sGgGBYdKx|$&CZ{&Fnt_ zB{Hr>`01QFp2ExweqYlzTp`+S4{KxJyMN2R)ZDXx{YWW9spid#1d;1SN+J@ z56zcf77?$1&2d}jW9r}5WN%fDeO#WKv~$P3OP!30@1?IgbP0P_svf01zX{y{&FzfI zKq=o+LX1id)a;(wOoj6#y*+yLQRwgSOhiF!s( z_o>}+H1g|QeedCqWC&$I>JqC`N&~}r=%vzAtma|KL5+MP|@EPCGWb#E!YT?Hz~&WT;#Fi>$ zo$Dj?v+oWtvFh{Ot?RS?*?sja_vQa%?Jbz{+_J502=2k%-QC^Y-GjTkySuwXaF^h2 z!5xBIfZ!0E0N+D)_vyX6`_$?F>aBY2KM+!Dtue>E#;|7#+X5e)3~mBsdbm%Ctxptu ztnUzS_bX-=CDbl~p4roE7bUO!aX49^vV!NYn^R{qTB-{)XoJ*)-dow^I-t>TqZDmx z0CUY^FpykGHn|*($|^Asc24m@vt$`_^~vmvyJ4K$_c7H;kH;uAhDSy`)OwuXC6ArF zlfL_ABl;|B^2D@~A<5-vw#m|Bq@|vJuKFkwL{?%C)i{d5mpP*9rU+*fimV6$)$$tV zGgxvSP(qwZG%EPl)rv!o4bY05_WlGilTlsgZ%H&KU+>zegS(`Pjzta?kFiR6d&h@C z0P)_50TiU}VzF;!nG{^Kqm^@~OO#>+ngNcjeVQ_xr2^>8u}fBm$9&nZ#_P_Jmhq^h zZfE^B1%@^Q!x31G?D>-;ga7Mj@}@?gFyp? zfW&_|hC00-;)_b-R5k2SIhhF`~~=L^SqO_e~$#<2?+b5g>(T0*L8!Ln;> z0{965*Grf!yb#%^wZ3kd%XU|t1n{vVd}gxGi-LC$vxtIbg$26fN@-x|!uEnfTK9cn zL8{;|!wBBBVk-;m7l6J>pS-P~UU?n&UCV$<g7|-}ino2Q&C=3oT%r4)1aV5lhFgua?lg&F>5ggy(5M&(@%MQzwMJo>Im3x}8nmG&>y-r0+r;mXQw zE=5&$&?5XP2F>D`&6>EZXr-|gs;8N{hsbu<-H@xA5w1MvKSdr~!!0+pzq%n@b_jdN zp`4jF#1>BwyCSRcqSV1Plktz3S?qShPt)9Dai90_s99DOFcXV@>5 zNqSXEpIcUHQ+K|4Q>IH8Bu2`^2R}wb-#mP3IpSw6by?8K=GtB6`)DzeB}~&XKAZn= zWKX(!w&P>#`vv8U?Ye`v(+vN@%8=|ss(r;We8y_W>-E~?Y7xn?>Nif^+1wbA<&6au z@5N>g)+8GI`!xO1@(di89J-!_Vp}!{bO()TAMm_sDPPwega*K=s&CBZZ&MB9pFX)e z5A}q7j%A1Xv69y#>5ljowY#%+{(B+ohP@3fveAFbdq;!8bDKbS?LlzU| zc>X18;knWVlMwJr^Q^x~fA{wj|8JDsm7S(?E3(9td-nOKmSae$Sz;Q>YOtIKfD(gp z3iXO4n#wQ@=N)EEg98Il{n1@cj<4G=EF=;KI_^_aJb`?|r! zUdDLrNpvyO0;KQ@EKf!OD7s(M_#8V>CkQQkRCTC4X zSwchZIKOWqZ^36^a-&+cu2}QUdbO4kqvID^(ykuRtyt1JtkYsbVPf_5aHX8GYo~WK z*?yzZ`lbA9!}t^Pn3$rZ;|RP6?!u>-lhQ<~@5fP7ue?jcN*h>Wocw#+E5F)T_SA7u z`s1Z8<^MT+NCp+S^Swox?LP=8eShfx1y24qk63^)ApZ_0|5J%_dXzFJI|5tRnbtL%D1 zth)gMh^)8V?A*OQ8Q-0O#^GMi$wcR&LLHMY;s&J~pB2GriV!cmbn)(#h>64$A*6LWq-Xlt>Yw}KGN*XH|D^f@Z|sX!T*;I<#%)7yo@8w!VyeYi?SZSEZ(`MpPwUb z<^Pd6@GY@Zdi)P_KtA9DP_LMK5#J=IGI%*MBI*;Lpn{qn1)U=C1$%v@57+@;xrcw5 z!qMOum!#g2*$R;Z!ya6L{ksEZU3$&Azh5F?^Qg8vA!{Ej=P z#rlUuSK)?5x7He1ICV&X=@d7Tkq~Gi+A;$nI4Ah8 zmME-`6dlG;8Pdb>x|$!6M?iMj(?NoT(vSMVokfCCAI>R(_#?x3XqFLo^zel`ux4v) z&y$^UdUm3OHL!cTV2@)9&QQjR+h4qGs}$?@KWw9y5WQAHnciWfKR5OGZnk1NqKl|EZ?pH6=Rn^R39SyC z@QkEyKG#TZGK2oT4lMzFA3p=jrij4L{}f;jO#aCn@Ie!d{Vq;f13j`zs&)%Kg@xS|I-{WdN&7-Oji3$fBrTHa{KXD>PoVm zL;L+ECGkZsv*D7YxH@L(aN9d(`CuO{UW)&{IdH2s z0ME4kk))+RIp~FU94K$vuu<|9l;q9XBHB#d`oXev@xAJSIBz1P0eOaH$Kf1`Dt9!8eEQPg$WF*5Dc5mXb@jG zuMZnKHjdBtHK396l&=>(=~rm(r~xN&cX|+EXW#Ta?JLh%K{ZO_{t@iAijOK`H0__b ztW6c=*;nygzM=uW$CcJ=luT6NNtW9VeO3F+AP-}m@lnl;X3@Zab-})G6HuY-s1?-l zy1GpB;CmsjpH;<9cLF-#XG)~FH|Dlk*-r92R=FjES$np^q8(ulJ6oEx`@O3}{B^Xc z@9w=qnYBBNFclZH39^&>F6gR@Q9$~a=4&2E$~C@huoy}cy5II?+Y57-CYim4NEE+w zZsvm~od}TVvRGzqDHi=Gi0ptU`;gI4T4n~5kZI2+87@kH!5Ev*t4>McbD7iow}HD0 zeL>+&8bp;_Tq%j;?0U_2XUt1!b6FUVb2@NVV>Yq89*v3b$eQ4zTIF&CR!B>1RaPisi z6hyF(`UYNUOj>Ohgo|m6;I%`kHzhJkFO(N&2=;0_3cc=Jt*Rr8_t-FPt&(pe1|Kwd zIsiA;NS7>{S?tjX04cY6GDO}FGS;9$bnK?D1w7^hcd#5p80Am_!b(?k%NaW6xI5-L z-q(tTJn|CL)TVTq9R3GV9&+FSK*|_$07%&x04bOLsCP1k2SCanKr}+*U4!?{{|8bY z8H94wZ5LdNM7fA3UU!@Q06HU;&}DancAul@=U+%RWqI$UF_zQFM3yRTJuC6;33plX zB=tS5^m57@)<-Q89p*GnG;=C9E9uKOCR0ledjW@ms?MbRVKQoF)9d)acmH|<4$!Eb7MjO}~cF`Niram94Di@O{uoBg}G`L%r znO1UNaq<)q@6R5*1zF08e5u0m#3BN5(V;p#>uhmb+7=l>A2nafdZ6XLEw^-ov|Ya` z*ZiReJ~XhcO~#*PCB6;vRDCu@USRCG1}^N}fwh{X&B_!xjI-|Tq+8nibPvf;8@sV* zsC&_ntL8~!9&HSwHmdS^s=n?*B_E%zZE3QQahJK$8iXZX)t-|7c|H=`cc?WoGq-qH zHIm!HvY&E>OB)baYMmCvJ5jgcu(a3jO>o3kZ!f=)5s+ygro|XbG4c*7=h#cwajKQ1 zA7U*i0YK&O-=Oj%&)XlMa`B~TJC?PbKG2{HUY^uW*dL%Wv&SpJN8O^3yze1ts)eAm zoib@-P5M8hUj&7N%_Kg@P@bgf*iWXb=8a=PwC0?;sg$Py0!wQz5U|9nw7a3PtWAOv zwL_Ct^Cpf%1FgEJv7SAiiZ$~N1!H&YrX*VO%9Vbm4GGh%Uj5)pRdW3FFxv^G*o?P3_kl%%#Uqk#L4DeExzS59l55O;b4IIzbU zf7&eoru<~Irnlcw{f;T?b`%ST`c8|E$f&c|l?4zDCB_Vq7KW^DDB@-fl+o^%vS zGrG`wf9=91UntwT#<1Lwc>Nh$yw*4Fkl&3B{4yeInz-v|m$Sb}QN9y~gW9ofA>v#k z^b2WhOxzO8RQ=+t2)WdlN+6BUOr^Hy`d;>M3o~|nb37TsSM+|I=tDAkC7Fekzi`g- zL`>nrb?; zbPTd4??wT4Qb5I97hk^;+cR%Z>9ok!U)_PUzqtce5q?@RRF3VOvZTJIy`6h{JbSHg z>jp0^e<+5&-lqwGVyIX*eOC;sdqp0_Qpf?Lo>6@Gfd8G*)z^dZ@bj(h9CS1ur2+sh8GF{DSD5}+19{ntyu zI036f_Jw*IV9LWEIAQ+#6lDkbl)8ugL~3r^tQHf?KR_~Hh1RwmBP)ixjN@)}AX z`-v9lex{5%vc*!dFC(7jV_6t#ZYskPrf3Lx#|oZk4(xFNytfZwh~QeGc?aUHfSC|e z4jj7=iM}z3{|b{cc9{7$*<|toADm zq58u}W_Y211zgy53oe!*&9js>r2W9NBjzwoF~_bKJ5oj4!j@4M3eRqb-5ZE(Dbn$a}#Uj9rD=Ocq+bkGH`FaC%ukJ? z2+Iw#t;Z%bMieUA%_gU2=a7{)iMk=}>vl9P=(+Kp9jxN&V2`_qaHfIW0`<&~_AwWP zKDmNtl^0Sbm@bsYxhl|FpnZk<5~43U)z z#FsW~>V8TBPz$v@Y-y=CAdj+IcP3h{s?>3_4VBI{?Kj%>1D`brWDbI#GBo*TlN3G6C|7FM!vu zUKhI2ltPgOk2vecI?ZH{iHuH0gG%UNioyVt7dCwLpaIxn?oQP>N=pH0JNXCXQq zpJWK}@b?SexeF zA2@r2Tp!(9m6D5YsrqV6^ga@i(Fhn7fI6E<=D9z{_imIBa1rFa`)JD0S}s6s(L3p13p$SM$}laGp( z4B;u0iL1l6vPg23<4p`qDN7xAlWbqtrbni-Y7YxY%+)>+1QfA+_y`k_4C&5u1>2IA zBq59jIpnJo5 z1q+`T^{G!6@!FWn(?2I<=~~o2?#iBi?0wEYO2AmP5%Vz8X%fiyf!#uI(6EF3?qyKV z9qO5Fj?c24EY`)?6eaYW4_sP_dZ6xgsP2`fE={Z4dC%$L;d0uLA-^qp+Ed&bh%y8S zH468_)O+N_bKJ#?UB2ORXNn6+!wZ3`5&)DNTsEO=C^(_d{RCRDIskj51cVwPqnyVx z^Vs)656(y-z1ZEO-{s8aihN|Yb9wNfIhfW&PAT7arBhPs+T$`@Q~EC8kFc3B4Pcg` zivmDqC4PQ$f~jzQE(@6eg|D#FVEMAQKj{2eCh7!8HJZ?38PUniPVK}akE0&HvC^g| z+cN0FS#1P9^PRgmSfLA-T51fq75&C*&>|o0`XvMT$5Zem#XQ1AGrU_doq-dI?^Xcq zLCHMItFqox_`pwiz&hu-s2A+f0ox(uerXJ+9~kVnWxWl`*6TOI<=^X^u|OsrFQ%if zHnViQr z&fvSsi*}X~sD+|B#?{%_%%kF@?C{z)RB|)rV{G4B645ESq@?60*T`(gh})W_N>2Q> zGt)Q*Yx(Hg_F2AIBMI2&WYVo# z@FQk{13w||e-ar>ZnF6bPEBq-3_xiIFZS~rg*pNi1pEd*&9IoRUAxq6>M_yusOB|c zB3led)LlO}StyvxXhd@o?k~JeVoD=0p=!-WdS8aYTeFSS^6b`?;IP4=TUbW~g3fk= zWU=kV70B*Yi$XBR>3eU>;B`P;hLHH>hyB#pjHcf&fU$$SY>w)QbL3cxz+_^Ub)^D@ zGsq$YP|KJL%TcbPybT`yTf}wZuxjLumSW1sSq=?JbaXR;DMtOFRn>$<*8W(4Dl>Zy zwK)E+8(%oF!!vGuL;%4o>u0@2{a|~7psxuan6W^K&xDc*Q>si}M5O5GyA1JHY;4PCYD&IGHO54f>f?D`ixEf61mi&7 zA#SiWt6B)Z6}NyF@Tm1Y3YzBGbnIWtZsJKkX8|a|a!Bn%~|>TkqTf z#sAR&;bd;-_?Oz`|AjpGJ1_TsUFn^NiPCy%Yg2_9XQGgNmZ-dM@!!Te+eYvuu@a2Y zF0_DADvRhS38|<&7z;NVra3eI{Fm0`=-<7aP}X9f-HyV?*GJlPQLgs00n0?3)6eVo z-s?uqr02(sK$~em`KL<(JV3qBD>ME(I9Xy?#>S$mc_hIp2jfxAqaCz5iZ;2;@)o!x z)R8idEu@17eLRae*ocdJ2oX1pu3V9<{~{pgVdL!|2s@d9f72L9UKHz)gfn zT+|Vm>BY9er)i_r5Yrz{o3NLu;Vay{-THb5VWg>&SWbGG+$taPFv;XYy%#|JsWyi~ z)*dfYIgYKwd~$a7&P{xGQrItv{V%ZY=VYXAVDi*uszNN@>4j zj&Fgngobn&5_XE9SC7CF>(C*_u`m{ zXyGpk-N`A<*~d9OS)}o)5;f#jWeQXV#|m_F%-8%OvOosy6tV}{jnvL003FI=_)G_f z=DVx37Fnc3%>r-;-fNKNCbnK>*B7g5Ul;E1dyLQ6YcffMr{{hF-9N1DEz3ZS1cl~s zf4R)kdwZfxO-6QFqZWT%^$}Y+=mIg)1^5i+s^K=oP_!Sky>JxoT4K zQm~B)OOKX>P?KVtZU7h8lV1? zC&~T<2%eR#?)H%Ez62IuIR;79ahXm8mueVmS)QEIa){MSpLV`gtY=PQa(cnOs*dZ) z*$plRLlRnIOz<3YWm%gGR*&lKPa)Lr48n?vKo1MxEO!5|&f>osNLxyg6Sa7nniQ?Y)e-ac+}JuPJbGO=pp-H`bV0?;@U z1iwo8X%Y?ZcZo6v>Lm`*ssZ?XDr5ChHr+JTCzvoWhh+ub7Ue`f;n-X!^lE<*z2LUG z6O7);B5YDfcrUNc-zCaV`ytRBA15|1pCAny(SCv+iI^SmU^Uh&G4A48*rv=i9LJ0&Yy_YIw@ZC`E;5=F z%114r+NObWz60AlgKCvr=}y9q&H%Sbxo)VN#@a-F$;@1wyLY$bBbB!Np|8{s_917N zQnM}zrWN$)z$e3@5rcWCM0G&Vg=6f&HO-m5`rzVv!7wm0MqwGlvOc4Ics350H!E@D z@P~15qKC6)BhRBpIR~bpS>dr_?NeE7j%0&4?WsbMDU0T1rL8WJuIp{;rX5m;9tHQj zDEO-MhYUt19#b0Dso<5ic+;`U3@ef@85_(3t!a5zpA7C@)h%Zp-3$dfy$pqO5f$E4 z6*uOw%&vyUnwJ?>7;dio4$yWHbA>)OB-g^5EZt{y`QQbpT2B?CTFHYYmIJvDkG@fJ z70OE(=rcM<3(mn@ESJtcus5-=;fR7YN0t1f*Q~Qk)`^e1-sz z6=QB5Kt=+h_V-T{9NXI5WUTkk6G595dU+lbEk7!zji+CQ80%$PGlwa)O?XVt#XFEs zT&gU7=~f+Yo4ae1G%}7SQl0ut z;EEGxEn46A+}x+$lOSjLJxv+*xPGI+e4wV2ao9?&$*du`Ip`+e+wVU}3wu4~^ceoR z9Y(AkjrdyA)s6R^jVLB&^Z>a<>EO+;yc&EViXe*zIC*I#-t6i{yC9uM^tka?>@OQR z$xxbfdcTw-Ivi?p+R0@*T*+(|ivU9H#9FT?+F#+^&#!f5PxchGCwx}{R1!#Y-G;-x zi70a(^GaTpztm*>1ZN4p#@TL2mHi624lOJ%6H0I!^7Z6it`qw*mY<$iey5=Xwp(Pg zNMrB`ML-FB?!Iqr0~@^0>Fl30gw(n`%R9i#0a#P|zs5O#ej+(nDyjssKRL7u0|v97dm!h%hqi=f7El2SgHe? za9hxzi|A81*>&3Qr;WFNDSjCYOXN%)V5F>|*^&YO!L}lZH-*DjrIxmOQiqc>j{mbj zg{B85y9~og;$_AbX8Vcj_@>A2A6o0(c4$P&<;4TsUY`KB*Z-A&^!wlGPYCmSKGeU- zh_X?!lR-Aa@RN?yvl!n{tw3vabyLZvBW@#NBrws_Rv85d2^d>xYk=-62F$F+AaQ8BQ>dh^+khCJXFUVH2>4! z$sw1!?LFk`Vz6t@u3QJ(!y|rAFfK%EoFK1aQ;v|RnOKWVK3@+<+|QMA3aY77Lo*Z? zZUubj?K5Rc_$J~=*M>3#F6M@km|4KDIY!AU8N)|LZ!NuJI1-HKtB+LVw3H%|_+VA* z2t5`5@E-j7WKEj+YG_!ySQ7e-KZ)C^9rAGxK@pHHQ-_F%tx2a*)-B43URthYjq{%Jx=3Zh*f zA9A^ezg1_&8k;={d1J&`+4N-+gEMQB%XUdW2!kNW^aZn&Pc$isu|Zw?)B3u*qI<^A zOY>#;rk{#&QHQI9mYnzSQ{26{KlZ#Gn;IidHlQDOxhk8+n|K*RkyRltVf`wAIKj2r*(K}v_|{m1^dS5}8xw5Rbgeo5 z>?HdwnO87Ln(z@aHvghk4JXGc?Lz! zS({M#%}U@tN_k5<-!^7ZKJH5@+yv+7H;va@jJA)LD zX|bl3;lQE2#WRQ&s~R0tB%?T1ynUA;Cwe8)YN^5VUW}zJ9!!DYaitF_*&zzrC?XJS zF&>$tdHwhVyP57}y}OeHw>kC64XB$Y9REfHe7x?#5j^yA*fwM(&T=KLW8c@2NVdg- zgwW?d7wW$R8` zsBlLXz1P*acttCY{;D?P>vO>uCVF?OnkU67$lz)C-Kv zT|;bqx$fL<|OB;wK6*V>!Z z*Z`M3{C^z3@7%&F#gAWfe{&uFl+TnkVO8vuj_|kQwXU=<%R?*`A!O?9bvuS$^fkx^PEv?QvmvS?IxOA#^U?{%n`~#z}b$!VZmk_Kb znpirciMKTuz;-bFtL^Y!rQo#bWPSHQ8wBk?j{!7hiw3xIACHJX3?nb0=+)*^SI8R@ zs!GC_&+p;0|ID;uT9YiXiLaSaNmzaAj9lGq?+owbSRJi&2G?gys8D7{h!9Ra!6bn? zZU%@DHB9ibPEzz&Y&Ef$#{zf!FCx|_UM!Ixsb3u8l92i0j z*pZ?vkFjz6V>9_du9$+@e0{6tDG4%l#Lg(hHePWclOHhAB@GY#8<#uIg_>!clg{Wc z)c2NwN|qOdJ6B8)zw84k*iTKvoFVp;fa~KCab<;14fKcM8I*J#{LHxo%5T>Z>5y>N zfc%=Su>LuMPOk!j=(0{if|YxP5J?YxHUxIzJ7k_jQ@sc}lY(1wf4}7g;CF3VZlVS# zwWqJm?XXVx;Ldliuar=QLhV2@5&7&c`G|>Uuecdr{KHAg7^;zvPRR3VkInI-3Rjy`Y zq^XUYW0!SXYKPt4I7d^U$J1z?{;aJxTdaTA{yW#Zmj9X&07r0Q;iF}bG!S`5?P{FYQRJw*nFehRFe2J=qYnY=-HE%ee1rV|6d_{i`doHuH@EiX~?bE`-_ z@CHtko)SX&rPPfOyWc@|liBi^!;^QMg_rjrQ#=h-UzB|HAD+TC_8NaG)tykWo-~fm zkVc6Ci~Ouw4%C})0ol3rK#)|yR z_@WXW(ZTXXCsT4clcT3*DZjo=7=b`*oEM(%Gindl&I?O++yI0Q)XHW9XxSr6cFaIf zxWGW(u03Bh2TZbhTPOXTN1BF7^mxbMck}U{)T|;wWer;_x%9m|+VbsCN-q~G3p|mm zyy$jlIBG~u*aeZG1Bd6-+CVb#bIsdgO50jIIkg-F+Xp_2*s;p6>O~9A-E;uQOkU(& zAXra?cN~B`RZ@}=hS-`M%4{AVBuzs^ftGDQEW|6sCVrN9hVOIZ9ngsBj;`=!Z!Q3D zqBlCEJx7qvQr#^#InFXUE`?+|dWxYMtLpQ#9;#HR4bKk0Ow+BGDvW=-^gtL-mCCmp z;)p_Q#?L9^U*`g`hZV%;SmBHI6#f5|V_aM6-Mq1qJFIrwN zOBNk&g-~5zC8?N9+8R90tVwNI?)h^F(ptJ%uD!M#ZbUw?&rt~50NZZKyg9|KehC6c z+)vE&KT@=p&FQjBIsS@Vtcd7{DnL)BoJ*(B6?lI<<2Ttrh zAjHE?Wucote(OcsJdaH#wC)ut(?}xRxkdX#PR2WvC0CK%5G(?h+ulZ^)RHDws%-Hw z4VPTMkp&HF$?(&tkOR`16Pi%Y67+k8a1!`-HF-%;o@PH#<>wdf<4LH3}JD8 zl4I)Sz>cXW$`tav0J%0(5>C1`ig`1P664GZ`i{l#*89?1Br@!Ke-{{bH%l4;{&NW) zc@2pSvqH9u_B?!S~UTEe_5fk^!yr)@JUT-y6_B?yN6>J1c%5HRkniAoG88XZ?v})&xj~_wS$PU4NGh zYj|CAOZVqAQ-R`c&E^mJ;{mn>O@ke&oD4CQM@Z|5-_%H=0KIG1rRlAyXz;p5a{C~8 zGFkZsU*Ab)1OUlgAB#9o6Ga@FuJ#JJvWEEwjcw1n=#(A2er{fPocs7rU*vY&x4px5 zY?i>`V?Z-EOakyg8gX%(hRIfR7c1# zA@9e_m~cCSo6CC{tm85cXOG3Q(`9^5;QXx4E^M#`yxUoWXoyNjr=~q9#)$>AVNO7S zgC620c2#5AS*gvjqq|r8?1*m-B7zY0Y~;=zBrPZAkv8ZRIA@J);0Bv!YEaJ{`mE!Q z;5c(;MM?L|9rj}X5^vu)S=y=y@T&x*dt*{Q1$MTxxuqmQyJtLSCTqkSlEemsIru3k z`3Bg~^^;3w`j(2M)?LoPtMpQbo8uOXctwD*+7ztSzH_H|EuM8w*`Zxuzu%6-p7N?-8~v(A zs`IBso;u1Z;xU+h$wv${csNL2s?J70)Pd&knW@d9`3l==Vkay*=57Eo-61Py=mTr5 z2Mv-3`GN>Y_6+GR@09)Q{gTF5qS}IqkO@WQwDLEqj;A-xWyxJAsI(FP&AnisDg6C6 zO0PKy`k^05gag7E2CKZiKOv5>Sr56XuKd+6JA#F&coc|nuAw*OLH(Gykz2%+yIcoZ z)?rfK4%lvzT5AXKSjOV4@w>kln(dv~4*v)-esnJTg(ghDf21w*sFT=z7RwV@mJ30n zGeza+)*q(Xn(iOBLi@>W9GU>F(Vh=Dj_?E21Sfk2LlAzRuTQ$I-K=2cG>~v*OvlYv3Jl?%LvoguirImX}g2D08a_dNPTB0p$FE zpRy*XET9d7Y`8zy$#;N;Ka+Ul1amjB4Tv=S63ezViGpsr{ER88yQ+t-x&O^A_A^qiGb&*%H`I#eiw)J`wKn)e*eU#~WJZuE%7x zOq9fQ8=CUwPIfhUmC*PqSgL02^6^f|A3##X)Q1wRzMlV7Sz%WDRb(l}j+Cli`Ynf9 zCf#^Ig%^U(=-L;IE1hu8>O1z7DPJawZhoe5`~GHEI-gR7O+~t_(!x_^Y#&1FXQn;y zR4u(SgzLwc`qGQ#c?@Z#?X4^Je;lvvG$g4;itT zCJZ)ljgp863f_l>x>jp^4UA%}BOs(*quTzI(ieCIvQ>%5c01|SbLg@4K9Onj%H!@J z_FXIn7KjJRKQ9PC0jk5$Gw<~dmnFW1ZYXTmN1CgOHv%WVR>LmUrf-}!vgnrDU`N6;9$qUTEt~)=2v)*_1d}3`hzx=tY`fE(!|#iV zf7Ta$g*w9)0Ph9H0s`4rr>Rt)JL?+VF$p4sL@r3r*FN=Tu7Zc-`g&$M6A?Y@s$@il zd;^J@@ae7^B7iPzs0d?Kp+S&d)y8HAJ2pMzBr5eA63WS(KU53<2!j&XwFR<-A*AeAvmO4r`>hRZLgv- z4wx)m#ioInrveZ_P&T$Gw*|oRZPh7@*T$Hnjh>=S&MX=_624yVU*{B~*;WJ;CJc&yLX~ z3)0qo@U!bcU_BkKPY%5TI5?7|Vi^jT@jfcj<$iGxFq+{Csk^>1n<9jNhDQJ3UFQZr zkRFr>cYBHfZTIV_D=W0cv^+=d_LPEm8mo4&?CLZTamgLn&|j)?*r$3pI)V$m=R`tbOYQ@j))!v%4tz9_~{6$(=vcwV7c+@}#avtMTa}>~8NYV)~LY zv-PaM^ye{+?5||?E!6N%81*o~wia!^ue!o(3~gr9XA@SV0Hk!6rn3l}MCP|VmsFDT zgohi+d^@Yng|%PRH~c20GAeXpXD}ES648g+&sZyylefqB_sIo(2p29twHX%FhwQE{ zbI&@z3^8Ffg(UI9kFspSChOU;o|D)6PxWP-YOBNPxGL|}i=rDX7#H4n=ie~N%9@ss zJO4-lb!ld0i5l><)xP`@y=#W!wng)FSxsAqmkf!UC_rKOj?L zhV5A6*<|Ke1#e!jX&85L;A=%vUkN{n4Wi~PgLY1WVC=2klsQv>N;=BVV?tBi2V=4I zHtKC=Odc3^+6P!TsK{)XX{JHmBkgdqAF&Hv;s_iGBX+>MVmds@x*j~!9|8D+2+M8R zVD4OhZp9!6RZ2xoo*5kCw5N`^#dgR-PTA4vW3#3DG(hSv3vlqw;2AI^T%|`=2QSkr) z$wDjRXaqavay_aGN|=E`sk0K{bWKD@bXE^irDnNG4=j&)2Caa4yvG#cW%y%@ZAGa} zbzX5yJ)_vJ?8syNX7t-%ft^U-Sx__GsODK5`(n($x_kJK_uC$h6bl+gRPCnuq-LBfeWb28YuXSE3EBsx522hV z0S|vpfL%cPpDfh;1#A8{FWP^4_zTgR2v8XqeX3lDp=$Wx5IFP$exprMd(dxW*|Z?* zC3kDytdKr77k8KdH#te^0;aGp}*Qn2-3i}kvSK08^1 zNxhFFi%>6X2DC1hGQ77gyZmllrsi2bRIwoXsChqo2vT_Qo?)a|JZZ9F8GhE=k!^8p z@Sb5rP8PBNQ$;9m1`F6bl0I|Mz#3@y0?06$r{)H+Jcl1i$^dk#eHjb?dD3+CFQfuu z!}QC4Wf}YlY*qwZPVe8pUQqvP8ANN6v=wUirn)aPfz7wVzxLT=&=P!;VF1+o{Qdbq zoEpoYy2Q|rKOTBz^lQhEAMyl)(fS*XK`6@O%8CLO|36rTuK!^bM!L|ftYZP5LBiiX z1MTggCph$06eVinG3sYhK~;;IPK7w{nWOp6RHGm2TA|^NvLQO!l@zs`ibWsI2i$Yy zRVBP!^UJYZ_9Tphb4CRu6)M35fUB86KgJ4N1KNFjpx2}s!}y80lx#4s*qbguD1po< zfm#H8JtSrE7T1HkHJDI>>pn(9XVSJf5t`VKignrm*^IK75UPL^$&rQwN31)Z@+jmu z88q#t-)-LqfxD9Q7~5s+O;b@FxVZtLR;a%0a-DgUxqCgXpL zVy{#4cVjFg4{T8^JCYe!gKQcnzf%L|Mim^&#XSwrw}n^*!+m%XiUhHV%g3cz16#7wCKX7HODF)vYHI6y$bit(N)R`g!p|dgiJ}v}@1dt4 zfY4K+V&0LeOls|1?0h^m6cqgoOQRqXFLxZDmppBM98bo=LkWbBS#iHT1J-B4{mAD^ zgi7c|Hp1jDKes^*H`Fb~{n2w%q8Lm`OLorh`wLd(!PTL$ZJ=UtF8FG)_HVuv?N9u= z11;@=nw9^|@opK&CLt^SwhXlVDDTKF5ND=z%}4g|(t5uLE?l4McCt_4pY3(*n~Q^R zr?SLoQmYQ{kd50r{bFhn*||Smu@vK!-{~<;MgV)a3<&AR-Js3Wc;laAI1^b)idE-d ziPBxF9L%Bs^=f7t1efBVEnLt|F)dkwYhO44kN<44w4!~?p4V;>{vW5zj<;S`DS5f; zA)dOOBYpTOMVrvCWl?Tj<6cr!7LCU)_4n*-N|A1U9fL2Y;4@9y-LWi^onU(PBxe<~0+g!)kh$-J`6cxmKnE`=<5cJ=O72 zMe!jnZ$u~3%Gjo&QRF77l~kz`TA(i24|u_axgOpmjb9`i$h6suQje@525`*=(U{7^ak61^5lBfd_W!0`?G%0|RS>Kf0?=x?!4m%gC~`Y2 zG`iFpvsh71ElXaSsN(vAOsV*$l>zHo$=$rvGmvI=`A}0#?ub)uzeu-C*FN^ zJ8Oz!ZLfG{YzU%{rbJ)UKaW1zs$gQ;C)yI5iw|3Hmop_&dZtH9Gd#a02{6Y&@r0hA zyWKu5>9R-@v;R2XWn^`P`{*f49Gl#R>1zcHG;|08NR|+$^?rC1Y^uaO;~MMQ`>wWX z#kcwY@%ENMd2Z>p=!XY)2=49{+}+*X-QC@SL-644?h-7xyC=A7aLfHz-TR!iy7#WV zy6&x8^-g~A3#y(u$9RUs5P*tI$GBZuPy~M-Y<>9@38`6!|9MN?Q>F5;R}TNSZHAE5 zU@7FuvoT977+9{h0Q0M&3;2yy6s1_cm#cMpoimgCqg>7Czsl7b-pkc?$$gj<=PpqG zC|3iAtOX@H`|yu)wM@h*C65kBvJ`{foOC`~xky$Uwahb@L2f?Ty2 z9{~X@S3{-FTE&XOu=Bd&+OAFQKtc-OoI~_QkQ$Umye`igN#t(FNS&99b0MI`YdW$g zFB>_!?f>)&A3;QIJV)^BumSSeEAe>2%EtO$4^409g{iRu^vq{|C&uv%*lt-91WVfL z>#Kt#%$=E@*JwIysHO@Zb{1S!CjVZpcF>3EGzu(Nqbl)1A^|4JVZk%%sKddx_d)1u zJvNe&RNx>c_h|Ccq1z?`gHKO@!Kb8Gp|ApL+kM_T`jWp@A4GU`^|M3*XBW$RWR-aV4u&J~1-y7CG(|4uk+j%l(nqMT_1f1MB;n6OAclKkz1~(+=@3m!; zm{PlI!jdW>eHtMpYh`O$&w#$i4%Ah*pI+uoAj7TR%ZAn;9`$$Jx^H-|SW6%6ja?KK z7&pDb0^x^)CVeXim@?fv2)HhnypmLNj8r3+{VZJ!YP*2RY|Ud6IZ7)`Rq=B<1KK{# zC5^@M1hD?%vaV~SAvkPYN{`9!RYpM@)X(#!x(jLZ(smU)H9g#BzY@-g z_Pt`wv3Y<{9~rT3x6iy`dpP)GciQ)otz2mRLLx!Fi@p-9ZK6im0sN!hgm8IGj->tz z(CubI{KGBWY~zSE&O_om7n%Vdm42VfUJWag468Yb<0ssv1ef{A{J;VW@4k`@r~zFR z|DJ6&>JC2+RWB0BrgWI=#>+4!P2E97%;W_@cmf|_^66;TjEoZYmy_$yAYx&#Te3^I{A-XB))VuKa@-**OxkA$B8 z(azv6?&kmIG5jykL0AwgUTXQ{a(ug@DzGZS>VFp+-SZI=Bw=S%5?H@r{)^7Yjlq7Z zwZq>*GQYR8sehn3L^8}u**=Op->Jp&YCcQ3DJq~oi!}u-pCP%8U61nm#B@V*)^FQ) z1b1{R4NW!0o;=tE$A&1*9F9P(;vG03#O~QYDp04W-yx_(a~Aqpz-~Tq9i9GJX4DM4 zw49LB4v2xImdW2Gwfp_inSL$yK_4p>LQNbYbw zKpmiH3)H6@tOglaZ&x=u9CA4`8*v%`6EdW8y*XS-L05!uG~2{734eZhhYX6qE%$x3 zG}^k}=CjYY3t#>pz(&xG4)eOtbB&Mzu*`sYJT%~z+a>_)7H29GRiY_~lKvzCf-N+C zR0r%@khf$l)$mAB`zgXmw@gXDin@ATs|dwnM*_ZNq=;90MkKk}kC3@1wm6rxbP+5! zNDU7(B3+=~1SQ)Oa*ZaxKPM5l%@6Yr$iN9Orv!Ww^m7zc#aLL5^ii3{3}M8HhG~ay zZXj~4of7Lb2B#YaHzi^fqZWfl?P4z4JLJseJn6GoP<#!%pvPVbJPq1lnzdOXEg1{( zrp?R~pkD%wXZgAJpcd$F46v;cUX#Br(K&fJo%+$20dj7vAP;Vvr!bPPK#Nium*mwD zkQJS)B+t++s?Y*N^emoys`+%DC$4RIQ@IL+9(`r*%~|>Yt+L z(n>;FpA$JyioXNfuwHO8@mjUxS$W+eX$_z9C=5WXk!IzPP|hHV7j%xU*8#V+iMgz% z)KSMKNBuj8=a1u{U#3wbCxx>FtZ;!zNE##7H^ReTx@(9kM;2B?6c(Go3VvVKzy^chll`ehv#(hC1JEq%< zYxP*_=q!oFLQE67LZC6h_Pam$z0c}`T&iupcepjEyF~@Xi8axUN_JrMX#Dm<_4#Wi zQAz1b2b0rk8LiWzp1jxNC(IwCS7*qZ?=mAGW&p~Jwz_pUWL@6Aj5A`9iH6&)=5_20 zW3#5o0E}p=*2b5pr@CSy&sa zRCUrybRtiPe_#f+t$GOe-%T}wcdwf{-OOutdQ{2qe6k-5-S)J9G$|?ixDLhUtekMO zPo@xxDL<@)IC);2^!t-%Y%P5F`fgKjMmmuL)dG)Qd^MoGR;fm5ExefuL^+EyD^f&u z+4VWR>EJeN7a@0$5Tu!ElZ*MCpG*>vzakCKZsdyD82Hp%sXaRLRT^FfB+p65Kok># zv9xYN$JKA!Vf~@3Su6#W+XHC^%9)K#o5EP@EX=w&+t)@Gzbj#eenQo0e|~>BiJbcL_B zr&0R=o+EUks#5ewin91+|0jgl&Fg-EUqzprlI=+e_3c7y9$!s;b0Iy06*aycoCS=` zCJL=;i7h@7RI4>GV&WJcuq#**3;0qpts^pM9B1e)<^;)7U%>iB*=oJb~oN72`>-y7Mr^;@75M(`(>=sLv=Bl2E2MJDi;Gj4<%=T_3~ zf_KKO6zK zS|v>zD@z*-7y;NcFg!!CTa;{_%E1{}V*Q&8eL{+fS$wdvm7S1=zZXny7B!iz3n87> z_^v420Q5Z|Rgw9O%4}hM<%S3F%c(w>#{`(b5pM&}=`9ZoNX7L+aotb0BWww<1Q+F8 zv4$Q^Bgtu~lUL5QjSzEU@AQCgT9d+~yzI^3gg186qN2Ww$~e2~8Hrkp#60ujL&@Spv!L$1KF_7>G0U9kEsRw#p%O}ujWmJ~ zp09wG?}Z%7n`>6o86wfBj#^H~_MEpnld4JvvQ?7y&Y_sl4|Mk$MtoIID}w9ts0}D} z!zn?wbg%(mWl`r)9Fb5cx1l1_WGf~?Z_z(p%(-leis706qOa!+`^=EMs4{5YWcGRREo`kFo_=PvP z`oxpLDX>`-0R@sTWz2#=_PKiKNbM7aG;9@)>SEz38?q_<{AJH`Oo-Z^-3R{Xp~a;H z`xc+yoIf1)gxH+k?p0iZIyx*%<&bqYh;l<{&N{N;W@Yz}qA4xxWT=n@0RJ6xFBtKFa~(s<(Y27rh~Yku&p& zxP2fNuarn9*OE3}!lDTnOd)r^jSVYXp?UTqV;eA4iB51 z^o-&E(m3y#NM!2)*8dS~_>0T=zj+V;D{L_Q{Qt4kXlU{Occ~FQPvjNGKivuco6p(R z*uv21&-Kh&zzggB{L7`KtKw_%ZcnIbThEL;+4wFddqze+7|V>7NS(Nk_5=cuZ+EsSnMdAnbQHd*?3Qca{w8&xa1*+xc+2@jPFdOWGc zB1o=~8ZVp#lsGkXbjh3W(*73)m7Z9cmMrg(Q*YoloQmXK9qSdPZE1r?IAx0!L)eNh zDY5FBooDE3GT-kxksCaYorPVHO9hnFscAoH7cXjw`WqE>mnjM-1Ey z5OqgI={kPA?B(0dT{;l*sbxXv0ACLOs%d3;c0Rkhk=&$2Bi8x+rL+E%n`jSoU}cpHt=)@K!MiNv zCJT5m8BnEHMON`vT?#ry(;P07UN4SI@WS*_Ulv{lp~JUe`jB#5KgvD8bE5Jm|CB%G zFzUKDIyPXX>^-MmzBS0z{p?0KFAAnQvzc(H9X!Jaak|P7ZEiKB%ht$7?>wkIr_U56 zb{Cu4rmJueb9w=B>l;bufpzPUgWyJOP{U5^z63w!Cf;{963>^uZvqvgG6s1;$I$TA z7(;p7G*;8joF4Y{M}RJE>F=BRN3;SA+4-Q{2-~PBiiglfKdwT4!)?s#7icK{Eq0j$ z_Dx3HN%T2#oWdGsC}7w4W>tins^}h;_b1~uGi`}WY3Tlic*BvJ4-T?wN-d&k7r#4Q zs0+XCd(WneP@T)`Y&`Qlj})eY5S?5z2u* zDuHfi(qBDf$bxdo6h2|K#Ibc(q~qN8`pn67SICdyrXN}37b-Z>W^8D8Kq)eelfI_6 zUnO8?=QfpfuAuuFdaMJ3Z|A==!=cAV=#cqt39+{b1*Y)Y-fY|bl2(+x{LczYWRNd)MDo)Sptn7B>L^^0ivll2lb z4@a@;c`Kj4IBC5)!_w4d(^w) zk*uHI@_FnBf9@QNo8`r1q`w}g?lS5N#P_F!!KepZ65TZp6UiHwPoS#Xc`|$GHCw;& zmh;k`UGD z2(BB4LR6XS0p2O78XIh0{bx_}y9P=0WtNN-ICpJ;bj{zNyZ`hh*Z^nl`}w!IYipyV z{*e!p{_7fOYSecr3PLp7j3V;J4X6)UJ|old5d{46bXYD6F4C+;RYl(i1bc<>SXxpD zCQ@h>I;y0j%brgWV-zyNSYuACwy_&NO7IuYXjWFIr_W^t&uPiiPXX-++4oz%Q@$5< z8p`YoLIB7Q0Pqd!9uPpKF#pH-oAicVIX>kQe(8`a8XoHUnyfHrlbw@Dc~N25K$y14w)2umDBFFh&8aEGE!_b@x=*nM&sd zAly1DYWvXjIRJV<7d2p!#80=VKxDz?^Jxt(3`rU+h2|00!BH9^&#uXxwE#}Ks^-VM z!7pktz-qF3Tt2YEC>3hKUf$qpeEUaHUw5JXbNCSkD6qo#)faex=|Kl*f*S@lN?uD? z-UZ;sRZOl?MDI=%^KM!^aQPza40_oxXgPiVhgmLvKu!VeMtZ;l6}=m2?h^d#u%I%X zjcm^+^cxZ=*(GY)>J42W=TNU^B^v6kAFsYRSe@noT2WUcQ71};zHdPLxdpQJ8kXl6 z!&|d*<+#rz`a3^wEQ$v-@)<|4Wrc={HC6EeMD0Qd#FdJ51+M^__YfW)k39(5wbHmc zlspIz=&@2Ft6>dQL_+wF8Yck_BFFl=#Bz5Ei3-!GC~)0U^~pTmimy0lcCmxFT{%C> zEgBtZ%dgJk(38yeE+ijqfN5x&p6G@O*=#iOUSBwye2A$o5+q4a?sa7FJ~!4+tHX1@ z@h$X;ts;#QZyrl53G4=249NG!f)&q18_t(wE+Sab2Fo5@96=;MWJh&tBkihg^TPy% zSGNAlhhX{!*Q{JShQ7^-ZM1H?74OJX`caN0LpWJAX0Mu?-iuS5q41Cfu4`RLpDB_6 z1elWN@Pll!#6nQOHm8Min=SH0^3g|&2}|Xx%GklL>m;+sG;z-K9}d!8RO&L??FAR% z>%Ho;`;Vm(;;td7OlBD)HR2OqjdEc;~P!ygkfz!93qs@oBY#0JPDP%eubA>nmL}1w_ zMQdKE!wz~OvEV@IrY_;&paA`1r`48*mFugw){|Xq+y_r|-z8B3=hRp<@B^44OqrmI zv{`5J-tK_i3?kEoI5QWLyclJj9fe^IY@3MiXyrxQR3S+7k)_0R)xIL)Nv+$JXvYs- zSu*Rd83)Wu9}%&Pboxu%3`fh&g>iP)-HRQESz>22nQ1L)EBAk;s&yLV$K|0XJ-7vS z5B>b!2HF+PQi%ESDNj231!|QJ`uVv6!s@8Vvb|?pD8<>Q@h!e6)hX>$v={PyA^3_H zH6g*&Se!&;Sg9)J>pSWvu=8;L_8cr*ZN-}PpZwm)GE?qLTR^RrQ`Da-4 z!SP?5w#9WvU5DDFBaL_^3LsaQXSMoYe$zFr^;U!bRLlV>+e0>C-}Y|NbE=A)zwAG+ z-_Q#piAaY2LGDdmd`#JJS1iqqPR3zipSQ1m;ql`&J9>$pC#%{^mu?O3Oj2BSAut%1 z7!{njutCYe2W>N_KISGB*$0uIlOAp*8z^TjAol=OEz%>VWJ{gWNxzkB=swQS)p9_9i^rKmZ) zc4y|l`VmH`YKL%(!kyHxg+y7O9=3Rj=T^vAIkOi3Ffm8|+GPWpn8D7y@ktr)YAzTo z2=HYSa}_Gi80+aR6T9C{%m}69wv|V19RpU%fdgDc3iJ`(iQ{sfTf_ECt~E?;35aCQ zwBf=srS(26RE28>P@e4$%e7j%*7p5Qtn}XFVM=u`PK^0R<9zMi8yG#ew)4PhwSTcB z1l#nE!U69qjlZ#8_~S42Cl~Yo026Fg3}sN&as8L{E@GS4@swIXftG}NLt@FOwb@ye z8agA%r@YMPfHkNZxJZ`XMu=Xw$d1`?ZbyF!@yVhSfe|P=9`0f4s{@j0RFQpo%2@p*P40Y1T1zx>@4EStW zPW#iJqV0ei;_X!~bVXBv9~Ve2-e}cx*h?QbN*hp~KDio?xy5l=vQBi;TU12noq0?u z&oE`+k0ZNm^#*nb&`NGa1BI7Vjh0E-733}gnbHRU-!uF^Q+pq6a z8FNF;B-k1|evrPBQEK_l{dIa^sIzej+-n;5B)^H==yO)F@`o+12cl^ND2alnTwrQE zL1u&@sp;#s3j9_AI6b8~Kw!^91IasSyJE+~pL^3^#)rLjg#Pz2TRn~fG7G-c4lgY| zPHLStD?ajW3AZG^^v<<%#;Np?ozGowpaAcqLW6NyrcpiMvPfSjJR7vz4RF+-4G|*Mcul z!Lz}1diz~KKRXYW(a8&PgNKWC;HU6HafU_GkZ2ey4u6l-|JDD4RuUip8~h zq|T(VdBA?Y=BuloZ|s7}__4ED^5%8dY{KUiRH^6PFTzgjdq!-qcG~nOAA`elWUm$m z;X_cwGL@NzIy;U!(l)f+inq&koz}=379%w#rZmN+EHhnJuce0TevhS36^B@nG!qe6 zO^9y}kFne*?OJ8i_DHg{jS7J_ZE0j|=C{D%p|n!Bai zqKEl+@TGfRl>xV{QAla&pmRmS8R6@T9-p>QE-#rn%~?xzLFVx?IvL_S8tMCQRL+Xv z=1kR+E$T8nO`RvFm*6ZgaK7v~r5(>z1iJ_cMK}(P8hz2qdsNjlW==?@9{m;#pdQ*>@`mw0Z$c zGyjfGVb!MKh3O z6$1@004nwEO;DYfe_{h$ATD@6|AGx{Rs3yG zRo{oLcT00e$7~Ru&Pg&ea}wRrC;!Su*w^pNG6h+{+HC&T$u=HRw{)DOY8o z1S+PC3^&C!ux$;*oOr99zHmE81fCvNlWT~avUb#f3AxvOp{KaJ^SSfF`^OaUXV<;& z)DcQ?3^ia=9H4N=BmfG~fZ(S!;@TfBpmQppyv9dSRvo>B0eh0;F4-V<>@IOZP%axJOD=O)Ki-)o_y9glRiPvnRn9MHl(l{5yyfE5OF zo6um4ab?o@h+W&EWawAq4*V>O=21wza^l}h73!lvc(R@u-X|_HCvnO^@Ym88@cVib zLMkiBE@I7r+5Bfi0C0nFr%ZfCl`{WQbO{Q8T@@9qvvyl*CMsGt+z~Fx0)(ds_;&6v zBEg!gxLt{IEZYbkk;G*=euNGsEMsZ6?~G zy=^l1e0Rve4Y$N{vpddWjL?rBfy{Nmh7sV%?Tg=X z&Ta?c@q++50rsx@;3H$~ZR3i#^P*y^s4BOK6N0M=KgIsX>*~~2U6o13-6_$%S5nOz zlu;3laMvA;VVq=JTNw%V@A=I>CUjp_SGv1VIq!cr&@1hNeQxCibvZj%H#)B&1G<&h zC8o>|gOU4r2OL%~)w#8r=tdFm)eVXG2}~Zd9KJ*PmE_!CYzN!!N0!nhoHz>>Z>2`O z6;DmeZy{Gjv2bx)L6&HEF)RDg3I7;AW)QzohVwNJ%Qm`MYPe}cRDaf*!W8m}%emNp z*kmQRF*ZbkU-oRJ6FYE_?VKyk5rRv?(lTh8tGvV3rgyMj7pt1X)F%D;ZJiCZ1@>CM zYoH61i2^BVUut^34lvvX%0z?oOc+S)hZ4~i^g^nj$4bLTLpjMj8m;NLNISQn7r&~c zXf0%gH?a!7RP5ujQ8<=3wGy_qf1q@#wZkj~O%hX9YTMUzR8hL1?55;9LETDQ&=!_( z*iPWo{AHf`xE8H2-uN|>B|+NJI_BE+Dn3eYTTBqQEr%2XW&jSC6%`haboiiaAUewj zV9U}bTW|i-J4f)94#gedDUF2aqMtyyIs%-!#4Wc}|4<$caeDcLozD};II0WNraCxj z90C^EJ}OLrT_cFDA4GU1&oQPf=#NZinQ2C1=&}>pj&~TGvkJuke3m4ZM_;p-fBD;a zqCVRFiqq%d!JJ|xBtiT&BKiDyywGr4I`Zk^fx5f)F|>|Nv-Hegj-j4h-v!UIGtPzg+shO7HcRX`VE$4x2bY;tK_9dFu4r=SZ$~ z!|XdXe^hbO+$IHAHb%eGmbW-J_Oe(Lb~P;58mHHl)~szeiFh6GFTz=mM!(LN-FkVQ zbb^O{uS=UNhc05tkJwn!#3tDfnly$+Jx zCL6VMo>49fj&kxvh?B6LG(GDY828lj-+=;H&o(0QnQ^F7r4uC`S zL*s|qgbRUa*on9?5{6NFp;y<52Jn({Rm_5%jzaqg6^c`e%OY7s>NKQ%0rrxXI_zQe z)QEHT!($a!()uA!@5zTF(TX_0^K^jNlD` zdD!TUb#crfpCx=Vx7I-7lvi@w0UOoZ)QK?W(S!B_9)}Ng=+M*basWK6kU4^`7S8*p zOVczOF(baa(9~A(sV-osO*AnHk`s&5~z>G7$H`}I17j135;Kq zk8B*$Q2eDf`U_;-9u?v{(TUCZ7Zn6V0{*KuFknP#5#OdSS_EC8I$?zDO?y9*$@bf^ zm_yZQvWyCUi!=6?7WVpw4?PXcaK^ZFG2(YasJ6lcI!kVx6lXUoy8;{0y6$AcQ>oeM zjVJU%aB~nH=Mm!S^K)}pUJ3rJvriCl6jc^mYeO-&<-{OM>e$Vcik7083IE9GM$))iMK7egA! zFq$Sq*?TL)s-Juloq^7|K;jFKKll*NsNLo*)7X*`Q$gmy|{0ygoG#Mehdc7U`m+tiqiq^ygTZGE@+O6m9;_MQJd~BGr-0hiS^uKO= z%r=VPeCgDIUiOah=_RQf)8ccf*zV)VDx})%HCo4ph_`d{bF|3sv~_)-0`NA*0(59m zU^TZ1NfibdG>z&avOz~-E4Rn;w`mK;Yd<$s%FOxbS;>mhL6?~ln@>2=g<72PnA7i8 z6B2&=c75%{syYM z%BIPApG0_fKWDb8p_!kPNA3|TzHh9@1wh+($)!GB7G_qILLqf_Jqg9ndL?>@GZ@ zww{+czMwlk{j8xGicyu7+>F7|`nyV@AL@b}MQi@#bJxTDT~{JO^Xp5~hU-?NB(vYQ zc-*=w9|9ipQLh|-B1ZdXtFf@qs)$~$YX`aR&aA{2 z@eIg)^~)W8SsZ@G^(lwQxmCJGaH|ixc|%D;*XhP?y4EkaL7iUhTtUD(T0<(CHK zEi-Kc)C*g_G3!=5sI9F>_;I*Jw;adBWKh!c2IK5;77WHptf*scl2*4M@ZtQn@aDb~ zTjb=^Ara)YP|@Z6={opTwtoXBu?)|a8PkZV!sEER@=7oUCh4afIFHqzX_ohngrU?> z0uUh0BJiJ#)PKJG|HqO9MK77nOZAIAVKowfkO4|G0E+^CXIk#iYkr`38r*2XjHuF)PfGIo zIygAj(-#?n6d9(vtcJyNrysKf9G1FS1o*?HC2`kOXG|0G z8h5qw3Htyguo7yZafrg?&D`$#k$W`=kC)u%5Hsbug71eYKB&rYxGPzm9YRu;P2jp9>rb!qBO@VxiMfx2|l+~M&7ajoC z0jM8pVzsdn{LHp{@_HHs`*S+!@M4n>WEbPpnTVp?-6{!l`L6dT1e86lxQ`5)-;6=` zbWb`dKlEi_1u$hRe*O$bJhQIPq`$eZ*1CL^9jvOJHK?I5p_5P6EBN@Do0>fi4HejhHI;@y@7iU8ym%5{Nrnv+9L7 z{qNt^G_1EFm2#@CLD%%&Xtvfdy+qMxXD zeW+D^df$Hj7WmMp;iM?eGuJN+M2iv&8)`d}*l~xCwPhu~J3nO!Sdz6|NxrX3s_Vw6 zY?!2T&yCAAAFE}wZD4DY8uB61?sj!Pu`@hU%1=t|=9}VKSm^`iZL+^64EM(iB=Jk{ z+UWV>ThwT<>hH3pYS@nEx0xtnee$hvA|JBV#*Rr^Z>>JtsiQM zl^2olBr>0{)8dQT&ncrITi}P#nIbN(|MfMPIn1uFz=ZU55iWf^L~I5_ z4^mT!ILXo%ghdrRe6zul^jELK?$nk+W=Hjpu=xF4P}~um0vjbGLx%OS4p>98s!K}a zeo^HTQEK~NZZ+{Y{dwmP1MJZts#Y%|ZQm-ccz1`+_xp4AxcT6W%TBYGkr zoAvYlC?7BUJreoXL~e?fmNMY%;VRfrZOFfIO0|+ll5@d30R;#mAQ});8&A`|gm=aB zjLZsQrP>RMzLG89h!$%db2kXdGuEjQty+$JZj@Cg8kq6Ikl-mjX5JwGstVfacltU)6FR(L>JB^@*9tPd6X|jlU*R(FG$=kdvz zw2Gxqb4y1)XtCV;{bxn%dk_)4lh(q2#QOiqi2OgY{`NMgra*B}*XHdHU{Z!fi!P9e z!h@Dx%`4XJaCilCk>ppo>Yqkzbf$fO;TspQ^`5Lc8mlR57-PuFRKT7G1Bs}6!G2ra zly+K<$X-*TLRXt0Q0tGh1)oN?iPoB-*$(99{Pp)#h z#?dxIuzIr38g9{9RKk+ejfYxGFk0az?M z3ACFNKl7R5Hu5h&Qt;_oZhK&0=8T%yV<19Zeq{Z5nH~?=O#1Gv$pabVX=B>p4*Yx@ z=DFTUs3rEH>INfFdE=Y}DfPmSKo7DgPhaGyd@YSY*j&EZ07If^C9M}6c`XRh*+;V3 zY$H)R6-frT%MUa#pM@KSX2VoqC>TBVr7`1$rE?(>;8YN@SSF5aY3}j5%cMT;-as+j3sx2*7l2y4a#y}?Y|@Z7A;#-3NWRnF} zi3X2?<{XGED6x;yaebAG5V z^?VLlD{eL^sO^87oH-ep6H1kWVt@&y)J@;t_`%_k>#SOGjnt%)FHr zx70_e$vqdT^YFV=8tpNF*e(uCms^^2g@E+8r1z>s&F&$pBane&#K9H$>er}xdsGL> zgS|}x@$OSp$x9&?{1r1wv73G1-oZydB`)OhqeO@%K7N!U^D4)(ma2I7=)V3b zbI>Lr?GH1k%?v&Cwd1iPWTS+mqRk3(y*aYel}GX3c{3qlmHcZn5D=XHcG|zjs$Pt+ z9S+y|h06YUd;FEPPK#8^VOFM+IXgWKTz$VH7qF1BL z7tL!mtoGs8SE)LDwpx7m5l*jm5qGPE6u}m@bon+89xvPreCP^wfM+=Ix$^*h(-|ejGc25%f>|d*L&aYJ7aWKUdLMGeiS*YnY-M>#OVlN88tuNwTKCY2-+@~qGNFtUbCi!U#3`B=s|8V zAeTgPp;lm{2T@h9FFy69cntfAMNlnPOPDfE?IoODSmM|kEMQfIq!2p0hW4 zrw-8poxnon3*&$ffLcgDjb(?v6k+W`m8>ID6jc?eOBg&L>tC@+UZ3-2Exe4&6|CAa zVS$sKZ4AY$|G~O4Ux;8iWG^H6%v{O5QvEY<#cBbF?^VNxDvc2uLjr-q@4u$KfX0Ln zt}J_J{XZaqy|exp*C(Go0a<_X8D*UC0;K)?qY$r{6Ac}FJU2ydcp&S~r-|wk*nFK`2?a2?*jokW?T;DKWDNY@EbtUG)``e!* z&db@08=K0tcM0$-`-1rBe{Q+;qvN!0@J+Ua!!}}35T|%FPl2Sj>-Vi{>*?}`hA$wf z*XBW~bZ$M#DWyA*3v>OhLg04`>xI19#R z9U0~d;~wK)eTrf0<4U1W zQ~I^hFw^ge^kMRqTd$+f9>b#Sjw}q(v}6&XJWQ}qF$17r(6d3AX-$cUxwfS45qB~C z9#6r}qTBR@_P_c9@hMS6X*@eV=I)544uf_yo&<3&LAH9>>JaNwJ9ZY$`R%-xIqa_O z|I)YL?o$nd<(VceqsgFFlT{%OpVB*&^w776IrtWV_q(V4!S+xHY-*7o6YV?((@LdZ zEtIRg%>P``9o2&qg7l$-&=cIJjCP~NYww;yA(-`85!p|Klt6__Pw1J3{MaGWaZvYF z77jUZ(PyF1|7F1bmEg=)33tqBFe%DM^r}OR?m;|pP zWLM3&DJ<8;ug3~xiLw(Ym{y;tc;|&B7f6y(gwf>C0EHM|HUrrUGsSy9Ut|6i8dO82 zu)Q}L{B73%FFxbHAqM(~&$#`MLW6?$h@$F$69aw!cQH_jw1pE_)s?=@4C!RjlFkkg z8C-bA_bgv*>R(*~Wp3c1TGrtSuFy$03&ool?gFNEbK6B7g;uD4Xn_zSCMC^Efa#%)H(8W54IXm+Qg&Dz$6^5`?#XjD}m5o%*Tijs;XU*)ZN2`)=(w(6kH8lYqx0a1x@T@R(do5Q^!SpR zosH&58zn98S;rq0&cOo%&*4iR(*IoV!5<}_=Ln&_ajd&>ys=E()GM(`u^UrWhg12b zXKvZNP|1`^Y+FJD1MyelHR|csu!7Vq+%s8y$liN>r;QMBOCs4=qM-(xG6xI7GcFZ0 zJHOrJM!46v6(;Y01Sw?^IY0fDcb)gESd(*9N=+RuNa(3~FuGW4En7;hv(+8)mUZb- z5h>91n)Alff|G%Jz}lxSBXc3^^h;DWK95bBD^|_kVQA4oiO%2{lCev#DGxp)hU|?@ zEMHzp{MnoHHV{IGBF^u;`XfLn3o(dvA(dkiV{P@+BB^e_;+=|YGHumaS8BF#udzJ> z1G?kgUkA<-y?~rQP1!}saAJ-EMS)kRe5Ck`?DpJpmJpFGAr5Sb<+!;n)6Y?b}p8u8=6Lm4S>1MC~2p@M`i zNdyyQYL$9x-tV+R{VMZ=%<^hm0#AZi$%fo&Uo#Pv0vWyE2jWxk0a^GaaS z$tpo%Jjpg=qgg7i4A`qxh`6qJ_gEk(C~3ovqv1ODKu|C{`ifSkMw;?7KUBk*5JdYH zRhsq@u!`Z7b9#C6t_7k;e&0%e;X6z~Q8XISCOag)hc7Smn(y4In6}zLP$%8Gh&&qVBK${jtjc^?RybENv~OyRE*R(8T2U4$WxOMvW{G6a)f6 zfk2FUAvfIZY5vcMzReb>aWjHZRX;z)rvrhcyK-1IW9aJR0s&gqRu`ehfqP@}J(;u1 zNh=!I&*Jvetq5S=JVc?2tp!{cG@a`-Avb`%! z1RS{UU6g-I4)h=Rih)Z3;J{VVO|W)vGFk?e41CRP9=Ov&PBFu{MO=TYHI3##mDNVF zNo}R6(s9fxn>8_!PDx=rATaBf!Sf&YC>n4HojcrB;*#TWiulrUrLfeK8TU2L z2{mYMp^;bx*9=IVHJ}{G&PI(CZZHz>Yxz3Ta>QQ7!dZz@iA^fZJ1_uI=uyLhD$Np- zMnZlE29-adF-3&StKNYD9wCH5z`L(_$<~72kSjJf7)LDs4`5&xb7G-`h3BZ)5&aGf zXp5McvCO_o5pz86Gv#XbgrdbZA#^;yo=m1aD``y$gmfeAE1-8@p#nzbpg6m^12vTr zQsw@T0};L15`3Gbe+9~c{tFm>U+Vb1&3c|GYmvq z{BA&G(Q|GU8oICv{Pq@<#-a~>h4l1z-B-x}kwk+Y)a_|*f&KDL&Hl9GP7 zR?=a!q%Z#mFj%`)e+LG-{>v3pIET_eU{Ik}W6Mj@ISBO+V6cX)A9N8^y7#K;;}G!! zbw~Ie7~qU)4dR-qp4BGcoe%rSjkE0PvO9LiGhJ0UN?(kJ~()toLD=%TW`n zFG)cM?xHNqO^l{j#*FUNG>e|jnJsS);x#W{cjk__vQJNVsK9{z&i}*PJAZe&Wox`) zMHSn&ZQB)8Y};1Ftk||~Cl%YaZL3mszuCLb>D}GujMII`9e0d({R8h0bFODS^O>KW zCXD6SG__(u_Q>Pn*@o?zaW|GFoa10w6v5NSp30*Oos<`-5OSB$+yfL=#VpLsI8u5yEDH|Ed zLV%SplSXVKmF&Z+{lavuVc72W`#%0^<$<$-fN>dWp4sjSgZP`f{Jh!^Lg>${ zB22MjW&FWv592N=UyvA$qp(2>{N}b;yljRq8T;{&7v0w_5=!xgP zV*l>H(S57`MYb?AUUUSzdQtmJW_-}Dom7JDvsCV+L+(rEF}=WS?F!O+on zF3V5cEMZ1U_2WSr;}-BA^FSpsk%Uy_&_IeX;a5M-ZeKqh|y%mRI!f0_ri(m_@@kA3>~U{X1l|bZ1YewJ;ff*3w*@C()^Y zwqZWQ2T%(T#X^a#>_yP$#Ppb%E~XKaTZcFS#N@+_t(QyA?km^sEAAt_h?thXGT;^p zV1WZ>UmhR}kx(J*5uZz4m>=MA zwm=nuCNY52U|tqTRf2Y=&Cdhk%z%0~1VrXhRwv;~KoqbS6rs5oAkgz_64ob!072mE z72VolZt9Q>zt{XD;C9-CA6yKMs9Qa0UW#Et(v25lJHB~p)#S^RpPC1*FVQ;M$=&L_ z6SeJLWOp$L-Z<8A2f06UFcld;QFKfNtTM(PL+zCukhS-=jQKqYf_8Q7@BZNKb3>1Q z5;W9ks_}5ve>nZ%>ws!_18mBR_VIim6))X5BuB+h{emgTuAVWsjy#71+C;NXYlxWo zm-*y+K=cF!nK=m7;Eom-t=C#Wu6Gg$oemFQY2(&+>;t_%7M5y2onCj%l^p))yXxcja+URb_T6U}u|Vl&NtTN=}^!v`JiB>G!H^stS&Z z*OGSFtEOFEUN>FR(V)5AOotBiwyoR7%FM9iS)Gjnk&P5eGbglluv51B!CnijNO*lZ z^IaQ%4!+w84xCo@DTQvCAEP|mp#u${k(fRi%*f%mQi#`;Nvj_i>pXxLcJ!A&dK}|h zAPdRz7~|a7ro^S?`6#VxvhTCYLakN5SXzh6pQNJpHsVY|vm#R}q1eb;4A*YHM9#D9 zSL4Pk4o)~L2}K@nF_3I9Mrr{_$yVVQ8)@2MNAOV@M`3$*!Q@xQVGt;39qFV=UjqAi zM0uLxr+xYpL$J4WBx8v2PKEp# zW3X!6t~c>I43`Uafc9;_tO;8wXx`^bZbU*l298b5d^vSS7TWM_fU{`X?iA})ShRt$ zdT-y!F)}%l*G;!xs>UECmM8DmpUS_I*I^|)e@b`xYK6?+eRF~AtSCo!zRvZ!l;yaB zd$~5f1jVW&>WV>T1<(jRRpwx$!%C%bx0`~$ah8R;2g;?5fyHMyiU5&6^^a#6zz(9zxA!jBDYNkP1t}m7av*{8Mc>ar0(4&XsypU% zQ46LD2Z@~^)ddvsU&?Cb(=u<pgkWbN6*f83;#J49 z!h=C9$D$;FJwOAA)S$ls4=SiN0qukx)l`P5X;T_OqMns})BDYc0AeQuD!{j&j6QE{ z`RHV53jNxNP}D)FlV!&*7xSGf+!b2uX&4C8YpLM5A>orfLeYR`ro;;=UW3#H&#YA=0aNe2c=Qh- z9YG0hA;MLpq6Mpy>vJGm<5&VLrUm0j|9i~3$9o+X5D*Q-GEZ^WwoADS$YOHIzLKOu~bj8A5e8rf$-WI=^qcZOI3-{kCeo=WUIE%I6tYT|f0C z7+oFlV-0)7u7b*{EFnRA*}9{K{1uinKbEf{#*xxqk@%gK)TdWk2~E+ft{l!4>;^Wn z312q7SE#Q>niZkY<%-6}T*us9j}RScUna0aE*6IEmW%owS;ACtR~*fpNhmyXHP+mb z=L=Q`YF=@EnL_euN>Y~G>=1`Xi6n2@cz3aOyu?sP*Wq|#f7Ft}q!U8dBa*I(41V;9 zl=B>+2U|gwQ>ke>B<4V(emKY-?UO1eG2MdoSwvl+!xwcSPGp4zHAUx)(X|%UpRI=Y zmnD7NT-Q}d2{8FT;E~q*|2oK_so2ikm2p&|=Q__QfhYRM_DiC1aEj zZ>P5-b{S?bFc(inkyH)|g(pet2nb6Fk7)J@%gq=_`LdC;4F+_T^6o0!+La!KzxFF* zMxA`(EguSe^@-*?X9DASWt=Or%%XC91YhY#0?g2o%O>8Wbm7~`(&%X~+;@J#zgB(; z`l>(4U{bcvTMpXGJ`_9l4X2aSQ(!SeBm4+njH@p$WcxF9XEqVOqL~AgC|wTZ2xhpK zL9EalqY_HRMq>hj@MLs6B_3&A%&`BRyqg1`pBX5DH=gk|j|zgE2ZvjiL7z(WL!Q!69@W|EUEjA@ z+ra^#N8YzO?9Y&nSUVHm4kEf&{aQl zcLFQqZJuVc0d%$EY>f*ORs4Yt>ywQkwu-qbLtX2M1$pu)JfC-Q+8~D1Cop3IZ}g6D z9UPx^%zuOYqjzg9xUF^tQ!=T3K-$$Poaw( zQ7D!3C>2z@uUP`P2O&6|hwXeKD3ZTYP-ZJ?f;zSUt^&>B;!zC_?AT@Ebg8^y;J-sZinw`#{XuD1K~gDPk#^$Dz(8QfQlG&u>$XS9hL1Pal~#H8uO-Ss**f zPrh7wVBkQ$1{`0$4S+jhnSVuSghe+dl>M4pH}C7Ud^y*MqDEInYoDj0T0P%fW|2-^ zN#$3D;rz@}m{5!)tJ!$bH=}Pt13@ZS4zLs&P9X)x!4yg2uh*H~I*A;9W$X_>aEEp0 zdgBiRbC`nZA@48QG@@a0PZHtVMurfK2OIcTEk6p1;D)b-HbGBE+Bu~NC`!TL7RBZh z=xy03JSxL;2~P}7fm*n#iL@a)!p_O2f;gzhW^pv>Qb8nqetLVx^V{P6{@9r7UHm*( z<@_tSdULQ1=(12j9_4~9FOIoXjpR$Ud|Nx%xiU)PbRZ1DS{w& z%k>ihy70;pV>ZFUTByKm4cid1ysVBm2R|!uO8-0Qfl!a9f6;@`ih+6iLN7tS-`>HV zN#8pLXX1v}m{kiX0C+GF%q%AyOf+P$@7tBKdfYprr?XgIDy@Bx1(VljN zzY8DYUX65NZHQDl2)33}8djg=CVq=;wHeCaU?|P$ycqgBPKh7wIs;ef+je7~w}O)@ zwrlc6d<=WxyD>vyVP~C^%f)Xc8>DAs5KS!LSC_Mwm^ye%6^?2v94b2^5T3`3wvC;3(@X4!?-ffC-*Osp!y+Hw8Q@GrCP2Jh;Z&y4IlM* znUiHAR;d>D$zWfr&TCzl&zj_@Zoi@Sr%zmlJr!l~o<~vkmGceYg^PaFQ>z3WY~wTh zQy_G|YcO}|t$C_Gl~{O&P4L{t9$RRa>_h@!acQNV9WA`M6=nYOMilR;9$;~)kgA_I zE?{x#lpbJlDF|S3sVQRm6a^jVgRI7bvzYTjNz_bPxl?Y}A$O}e!!kxJJ6RlA>_$AC zO{xL*ETt08rI$qvb^ap4?XfM^=QOfqUUvV;ro6FL&q$)R7>R{wu;z8y)K3SnP>#Z4 zaGa699mo^|x|pPDi}1V#q9%+BQinjAGJ5Ll;s%oEAr??DuDfZ@dmA^hy;J6~ULR}$1DcS0;)Z&WO|h+=XkTpBtM@|Z2u9`{O*_|_Xd|=`X#U>E;>U}o`5?hHvj@P;r3_kTx@oO0~iKn zx!t~4-9;SRGM}Q8Ca22n38Dve?miu3-WcS^;!>+l26u|DH$jVp)RLE5(Z|AtSmFoD zisiIjChg0;9HS+X4KC(YE2fjyQGDLzsUl`VFh;BdTOe?-%A`Ni&i;Z({@6tn-xHfk z{WsC@@0Q-bX@>tDhxP|;CK|6ZztUB;q<+BC6`YYSb{}X%fI!EyB*v*qsIE4;A2e2m zS(_5NiR|*#PgT8Mc@TdgwNM-52EN|BsOp61&8n8LKk_+++ zOwb`AQTFEI2Mh&*llWuBfUJ(BmQ+vcLrNIU#Xri)& z2#>3?03A5GR-O|{;8$@k`mCY0^x8|qS^JQNS)IETyj=u>4G-F0gS}*kxlzQ?N552KJBHquzCkE5P^hd?WVANBV(B9v=bbNe3j3 zzo>-Aax$3=Wad@;M1hAg5|>zXS~afwzLJd>1Y98i@O4KTOjEu(8ugt4rNqaBAJA#4 zE`B$ zMi<$%!@CJNh1H(OD$eYqiAkJ==B07dNmSKVv18Ub78k|`6c-q~q?FiNrnr`qp8Zpd zhu>Tb2=lWHhO?PYLkO7+$>%#SJu0~Ut*y~)Zr2RLR}tk2GwQmX4Y?f-eiv)y4~wJJ z+94imS}(mf**g3}zKcoCikKzmDS`+!Zy^0*V!k??^XvJTZ2TZ5!@mK2NGowxCuHAE z(}Attuq#b(bWFJD#5DTGCgOx7$jrIJOs*+0m>kT5r|nQBAxjcNoOci^I4d=e9AhsN zjCaL9xsgR%w!MHZ#7QKfjW}-3uhp+QAbvY5B_6cU&!yfTgfUY5q$MXE#i==v)&8cH ztA28ISC?p8!t2_a;{-WId#Y{(VIIp;AOO<)h z_H9(vdJKDhvn=ZFYpwEu=+F8_s1(B#mxP@0+T}rpu8D`OgNm`espys)JJqL zd=~neei8T6C>vG67NA~*{HP7#DQ6gqn3vPzz_)m!JSbt%kqZej7}eq@E^O@5ca``7 z&B4{MR2I2n5aYHaR*7)w-^TE{9|^atfA2^~T&xyK?eAU@=h|PM9yZRQn%T=fkHC7_ zzb)?D`oZ({VoK2(g5_(3Nj&WR;^!w)6C&vgP;9VU!YN zDLBU%yirN>Yw(%l-d4wye(Ew5dRDxKPha<0IAuwFRDZM`3G(b+-#kPmA1)Nglo>Z+ zs9(`Y>ROFyyFj2Es=#ipVt-A86j`Kv^%A(pHNH$phC6Xwfx|LjzhxvY_F@kVB^rT` z7h0utiFvOKf=!=@d;L5%qOqdHwjcUNE`Amtxe`=m>(Kt1+Hm^q_uqBGhsluO>j(K? zY~+8ZS^Xt*EDz8KALn0mg7+WIY77_9teyy2QFz+QOXfuDL7gZScN;^XC6BmqZ{p``h#l&KPNX`yVijD4}hKRB+IOF_xZ&bmL2wZV{sXFM9vtV$MuKQISC zC8l1RkT?luH(EeJMC)i*YZUawG1)+PL`3 zca`6)kdF%Zq9pSye;Q0@;=%ryaJ$jEaT~YOsoIRPqFy^|sFaxRr?w4#p=cgBXMh+L z1r^UzqX6DZ-$vd%V!|foU>jCV)!r=B5!JT|)hpymUnj>D>hF#9Dd#ej=oI6$qpFrM z9C(BK)Z8nWgRAE$*Z`@}h{C;yILPHb4x34N@bmN-@QqrOqN+r75mZ-9YVRC?=p1&D zp^pENj;m;qPDs?%E6=oo8BL>0mq}uLn>DQQRYjPM0&LeNHCf15xm^W1+%*<_i7ltI z{$d0l(>e842);cXp}-5_Q5Qjn^{SAN+-U+IsO290KqyOS4g2Yq?Fw5Qe1Qxbx^2gu z6W$OcAg}{J1f&t2Pn*I?jh2V&kXMmMe{n04VeZ6Vq5jt=5%_qPGkLaCrB5b2z4xcL z(n|}v-@PeX{neJxD(=jqnJF5D=OwK*3oc`vYUCaE)J#F~WtGK(pk+_K#2c4z`h=wz zj)broFy_nE?^k0!>=C5aBA)uV!Y-l?y09(VLbc~fEF=^|7U4Kp*(hke{7$e$c?l#! z6Zf6e@7!tj$-c`@8~Qx%707uq!>@Quj`b!r@xX1dkd43Q@61h_tj!f_xFL3uqvU{> zqy@WPFoh!F20lFh`;fA0tK_N>r9lM&Hh*GG*!6te$!OvNk{O#m>l$TCKXrx0F@&}Y z+w_w4H5p26N;pbQhVol8Vzgqv)_1i-HowjZY2OTKL}tcaijUMWqXAtZ4#=rx#_3tY zDN}irUD=pcRnnsnjtbG!=i99G1}i}q881Pv%f z3wB7vX=-C~GMW+1v%EmOqbjC2nI88KASR7MA$+w$N75ZwgpJ%B2tkF7I#n-uZ&UMf zX@^8jXeJuWP``Tn&tyZYiB!CCEaF+rjf36-i}Ij_IYf%`W6^gZ>T9&D(@Zq`AeBl% ze+4dpwrJ@2B_dSrr18%EYkjVurS+}Yc4E;IJu*DjbVM&y_g9bi0ES~%>q9Tg?};X7 z<^!`Z%6l(p-PKOV`)DI-EBhQoiw@c+Lgi&K!E^}Q3mpbT9{^?&aslL;Sx?F}?JH}L zD}fhstl_chD8C%%J8(6n!t2EgJMInarc-t2ysLouk0}oMpU=#ZIoq^-`Ww0B_KY%b zIK;(OdwVa!e75RwdsX#(qsRH>*4s#Fa}hrVWdu6q94A&vrv|0Ea?Vg*Zr(n%ASS@=4snYUj90g+0m4;YY?i06d8XA>GHtg1LsS zDPoY(ricYK@$6Xiq(eG82jD43 z0Ks5P`h#H5;U*B1n7xBXKZ6y|3W^6vApgpJ(+7?K>>r9}y5Kxq`1x|H0gSe7B^>)$O=(y}KXfAe ziMQL}Y^9&ufFRg8LH{D!<0oS+fM8%ni_8ttZ;eA+txNT1@gX8JFLE*bC)p>&xf1%`J56op)v3p1{Y)RmZPez{+DR(=blv+a z6wt_XwP8G2XKundCvvsd@+qfK5sFSF25OfI?3T+y^4+njfs<0B6SJCoE@64&lQWr< zND}Wk^sFI$-X}FLw*1$LfUT+RIVi6zZBRD$DPRMx0C}?O&KQB+W~65)F=uEq`kFL) z<}}CeY?Bs~wcx?GR|${5Vra`6V976_js~4djC##wi_ZhD&kA2V2M$F8c|MiD2|qF( z4cZE`x$aP&rqS*+z!jHG21->Goxe++G1yK}5Dq;iFeja&hfkD=J|NuTc~KEp^Mvj= z0(i*i>RwTPU<=XVw)qq(B)a$Y<>rM zg=v*Ca1Rpc=HuAY(0Zzja4xWlJD^3j>9Ta-4~QATb|P2Ei9y}HRECW{%x%M$k(4^F zi;5_!@?0@$o_t8NuRgBNiTsvL#QZj|C)k_bJ65O;hxS}-J>H!z14g74weUQcs#De) z-)^EMuE^Ja!fPLuBmEjpjvnj03IMPO&~hgmN!&cdPT2z#PHGkRl%SgDw*z~P1x90b zFA~Ozv8{l)huj7e6C9~aEr*#RsLp9uR|i39Wlz|0ItOc^S+Bb9?~YP+KtThAbj-aY z*t&+i*O`bgUD#2bf8+V6#yO$3y^gX3M0qMmWvgMM)Lnn;&js|;$78n<(lN<0U`naQ zrTpL;g{2w~B1wg@srEM)JJ^9kR2o+91ElA5sgoIOIxJ&J=%390oI_@3$440h-1OQ0 z&71x|#E}1oTkJo<34{ub1uXgoe+2)DL;lkgAff=60+wwJf4l0-18~Sif5jo|qf`TE z$ZESno&tZG0$bSIO&_Mf@7u@kZx8vBsmfy&j5S&6aaC%GYv+#?*Yj9p7-PUZL2UtXu$04>Rgbln68(2_pDX8%r0`bz{^7toGA&cC#zKQH`$ z7z5q{3;yCu$aX2_4nJ53NOe315`$U*Lq(JP9YlZ&zd4Nme7`pT{^?@s9AaObu{pZQ zv*8MZ(hxqK4lQ9K0$?EqBy+*{=t$T?#6MrB!u;0`Hvb!i?0LoOB9~PJ3#6q8oCB{R z00&^|z_EOB=t&a7Vi7T(5dFIRC8?a2g&4mHa_|-BO|;Y7w}eH-QWmyNO1xBwe1?=* z);~AqF)@#le1!=E+en-lFjkZTG%Z*j4bm@0;7$cT#T&3h&4fQp5w+S7|BSu**D){Igc*PO;fTfV}=GbPfy|69+(-PJDQn!9-ga%_aF?x*OkzlpUKz|A^JX@I{kO5 zStG^F(f-0iYk7s@kBIf;f`WL9A(_pNzm)DEWoi3MnSt+!6WzygbFF0yVPB`@ zlJa@+W`-g{8qMSz-Ij?xqQbgNOn8hU$pUbU(!Rl<{61xSLZX@-hH|QLHvNqvFFVM- z9--tIwp%N3lMs}ao?ApS@Ps_ypefy+URCVbPZzyR8M?tZb0qjqux~8dLhfXzXIck~j@X7t}oWg+T0m6qw879W@99(@lqNP z+mqyP&qN-ugb{viT`|rXYmUUqYbma&9jerhtbHS=xzkDQl9t(RCd(@ED#CIX-5EDV z*8*Xu4AT2!9HEIZ+>VC&{gxg`OY&ykMfdAlhTb?&!B`gH?^C8Ni_B?LaqalW`!Yy>u><18QdNp zLlgTa32i-%mm>kx7dT6bnZOtS=yhOSyCU|9KsXDtixgWfMo86pjR%7k?{7RFcOlahV+@fPtdk&<~+ zO?@Ld6s!}gLZ?jYXN6728bFM6X-Q3_V!f1AYf@NrA$0M>904qUC;$@ptSO0+Lxw~v z=*DvgmUI;FqMOAI7H)AXzuW}@29%)yS_6D*Nrf#vf5CeUkr*Hd$=u^6qGNFZEA1bk za!X5lEOG(3EHdYP;u6V+@Y`a`0q0G`XC$n5FxpCVM|9^P@JQVh9t97(%oF6r)JNRX z=G>NE5rrSajnE5L+a7>XbERJN_UAs?S6MsbTMNMl4qS@DjnLQrJczy53yySG=f#WE zBj3-^h4!i4AZ0AdJr}s0s(p5N8Ci27CY*(0qw7XQ;&^*_Z z01b~Oh46qM9-RJZlAdC%!sHX~BYqVIYw2ZwY1j#@dHm@o5&T5fQaMg#PFPl?Vmazj zr!!4D@~!Q4#0pQC#fO$5%pER5Dvl+zN#uja5RPidGYexROyOQd@&#C22KdI}t{+G9 z{odGJDakVBVcEBFA&5k_eWab6VinxM*0zmX4d)V&r$gQccB4H_6S%_*fEt`hf*1R| zOPXU=zX_?)P5CN6-iKwuCzp9!ibqhUATD8Qv9d_=^8Ac8zPG>bV$%(Icij3eH~GSL zWK%cnF1?)fL_jw_uJGJ3?DQwxNTY*`S1crulspIe$DqKs@$Wu7d*a?pH!7I*Fl zi`BY>wqo=60tX zcd0ETGthK%BT(C_!3Tf&64Ee`C=M1Fi?h|(_bMh&U_k6ln!a8fqx1cz z?#$W63?|RV5M(q1bl45#D$9(bliTx5J^1AQji;}g#4UseOY{+@0U^A$NJRFO_D}DG zo+g!k#lAV^5S&tY_4^)~<#B^7WHr-y(oBecUZiisyN!zVRGDQhh{asTyCAeR_A+0x z8|Op7AHMW~-(dr5=FVZQKMqxa4!d%Hd!9Aw^ihx2dgaAV)vL1B=2wcah@2tc%PY)W zo9hmm^ckl4cGg)YU)KoOVsbSI%v$!s6Rgn`_q&7m#fG7cS!@$Fz~@sb2_@gt;%Jw= zWMgkm=Xbkw-+iytd(s9~P8DJ%PEVWc46gDopl$sLD&1m~TgE83eT)O#CyKwTj|oN9 zP-wzcVp&Lgb0^D-1|9dBnOEhFCnVG@u5^?Um8H_zWebezX3H15yk#6)O?YWFGpzMw z0olZ%YL+h)vZFwGpg~&KhbI$IHDy1+|Nb=d!731Ja~2u+53GTI2q*s!x8Q%Y27U;X zf0jUKg4>{~MJ1$0Ag|-t`06Sbtnz;KfS6PVm?HA@AZz=_DIzV65QUCBshhSz{z|bw z^+Gmy&3Oy@6i3&$uAKvCOGUB;CcqF8d{O~5+W}oWFSKJhR>+}TA{j`m^LIXc1aHw) zje}O<*Ocb`;AJ?k(P7T52f{pw+lhi0lK@bJ`wy*fJSwE6`UKnzuY(x&fhYi&1F!N`Tr9;%bH-uj$&=Um0I9G9{}-uH^qn7I zWCNsvqvMtHhg9(XuNk8Cw=VaJ45#cx5IbOC0b~Zhj|4(SO83tS(nvPSk+e2P2?@>A zYAUw8?8eu7?z@U3mPHQr{OYfmY4fa+sBDcA$?)7>s|Kq|eudU;i#^8#+;Ks1IU_*6 zSQ@hY0<UP}ZoF|+_ih5h4T7NK^I@1lCK-UbnRrKX_%M<$ z+#fB*=)RBEo}ZFF)G_T>U0rysriyZA!btBlnCMuZ5BSE)3zK9W?n&Lu3 z517y=jZtH>;{M|O9%VI`rsP_A(@--6E#-lmp*8e0ZeP`0VbUcQ$XmFqoipkO*W$Kz z>dAIvadn3+ie&n2)hCc+hga<*?==~_UHK|u)%K=>~fFvvK zxfg+1RWqRiZw&f-MR5 z%=LZ;pLj0?f=C_QdM|{}8015mIpM^|HCw|;-7gJWPHShhAXDc$rO#whU{;zhD81K- zYr9gOksE51sh++-YV#73SH5mxpoeTz2fl>D4Yh@9o-2$GwI>pj?D)l3-91(v>ve`@ z-noFO(Yw>lV{jex{T8147e~O9)H9M2luIKmhyh!Gy!5la1i_6iDc}{X1B`_o-3uWPcmrI-HWxSqcyZ6j_+6rwteY}Pn^6iEGComg>kLI^ z5{|I%;h#!&g1sYsRZcA6I`5Vy--qS7eSU4udhI#TGTrmgiY*u7cdA;Fo>WF=%hxQi zRc3DbC#4h94}Oi{Zrc3GyaB99Y$p`ie1I41kS<}S!12)j!|c9QNOo`-qWD0=8NY7T z!8nw@?LwvvRLL8YtVLC_d=iJp1l+hmcKsXgh`3YFVs3o1GO;N76SHwaQuhxj zI^-X@gKQBO=g;V+x7AK?1r)8G>=uxymbj?Ml9^T47I&>=iwZ*3#!fKIk$loF-uEkS zktm}vT)xTyS}@No)l9%DJb&F>`mw#}S)UvS9t`{Z*r4L^1%$*AWQ_#RqF27zlbN; zM4v>!_llCsSg^#xmlTy~uj$@$*L`&llq9}7A?+Y@tbJ5x?9&6p0Q;I)RSVcl*kilS zvIDPk9_|D{?G*&|#c2v>5Ev&>BtX2`M^?*{cj&4xlVCO8&#v*tmjLFF1O?Py>cu7W z=}PV4)CX@t$T@&i&^9}RqxSb^yQL*I6XzfkAu_MXf?^!@*>28e^{;xsuO*CdF`GKz z{LX{%L&wA=*1|lGxw<<1`!&)QE-Qlc3^+VJPFPM6Kq}msnKG}s%eYNZRx~VmH9_!$ zLDGldh2`SXP+=_@-;tai40urZ<45EgOu)MIe?brN07!+;r%|~VET=)A&Z|^XG%qqW zFSK=N8)YIki}w!}9Fx@|MerJ5dqYW^Iy)l(!QFj33Z} z4fzEUp23`~rgS{$0vi<+6fUW4w& z>iAzRzBWm;=se@RcODI-PqvW+nP$ywe zL@w@x6_K@+T6yBZ`y0)BWhwo&dRmL=5PDrWW!f`mxf=puor~7YMWr~m;qju$Ww5iR zkVg6qY9HmBCR>wa)lYyoOL7y_k4^_78(~dj_C|Ka&j^oI(#qkyUffMT6U`xXa9BhO z8y+2PBg8A$GXdqvIIl!{?hHNI4DQOzj8y_v{H_Ar~zMw>E~3_ z%$rQhO5E?+Q;n38b3Vx0$i{uEn#^h9@R#P$8sq(>J3Q>uxc9{TY=xw2Ak{OuC@L^+ za(zPLgMlRR(*-GeV))f>7mN5e4{^5)_3rndO!3u}zcn=Guo;31i$u!E%s1F@C@`B< z;EOF^w6j*u`E*Y7FO+#sxeo=I@EyWXh>movR- z_f3%xhw$KtFjY6;gV7d=*B#g1^;Yg_LfR|sp)8Z7ErnGt_dlr#66YP7ek_sZga~aX z`QAjOVWyqfY8hxQ8-RV8lIVsK&O-;_e?9NPNrP?UGvRrBxX!WEYb#l-#H zy`5nWPv^VU6RCbRWN!yt&Gjzl?WgHd_?1H2PSvuwkx}%?@DHgl+RqcL#vTul3J-D& zNS-u_Z-Wd?00v9*+~bp!FqCV-f#S~hI%lqU6)#@BeL({1qNx^-yH)B0~xLH-Y^!1kw9Xg?JE zZ>g}6CsTR5PKbMSQ9#%Pn$7Gm;_4kr5w{LlVq{el8i3R@Z1%B=Q;yN4fbp zH1VyZXqmNhHEVXqsk}eI|6MA4unV3lND9dT?aB(^Dp34igH~3yHl}~&9xDTy)yMg# zhNZ3i=i63e@}{)rWoIIlsI4W8fke>=cqHYl1wX>*qWJ*-sm!83mT8_jjABXH89Iu# zX_Z7$8*NeMxYLM%-CPB~mKCKXS1*o!DsdZ)b)X#a92_7j_r_5iL6o%)Xji;P?%8}t z7bA=q$lWFVK!NT+p}lFEBFE$p^smK1$6|pl!TP2YMxekXD`M+2N3l! zXw!d1u2a$Xp3{hrQTiI)=-!`5b)>;#7}qdF#Hif{1c)1a1|s|p021G`sEi7`o$7Kd zl2mMhNIloV-t#kb!8`+HD1v+eetGy>qJaJ`uq`d#I=Ap=O9YO}Tt>)ICpoxT!jK1V z4;@_#XK?%Dc2(9k)LUG~`7PZoMb0|S<@fDODIC&x|2LM)$DAVy@kbH6dld3^;+DSf zc6|_jUCP>BZNv`Ekam40%3*r#33_d9HLAuOk#hQB7->s%r{Nz47u1Sc3Q}PlkP*9b z@QOZu;*|*j!fA3aM8q_|j_u91Ndp`9Sn_BM6ee^Uj(}Q}LcnIo*OZ$>RCxpz{d%Tg zeSOvaFW1&ot=hz$vHF}SxVMA8`2R8#Rnwwmbj+P~rZpdLDIE0o({at!YGgMZtE z3elMQ=GI-e!Bb{B=q0|t=P@v)V8W%!Sf;ujcx=q%F(8>vRBkY2Q^_B6-GjeZ_T0mEex(7Cg{1}ezz=Xy0WpcH9u7|?R57_u|#x1YRU5$9n>cm$o7 z5%=0i;L)o94nqmuS}B;!yKH`woYFvCL$bhdm^c*YG}PrBvZ|_qr#AdT!@V-50lvE;CJTZ&WG zyEVTnYx@)G8YvyovNkr2q&XAigU5qR!iYHPoQ~+G7{_rEmyC*W*TGu_%|+r?6W^6g z!)IqQ4YtGt`ThNOrC(IW<3$zzrdcj8?l&ivqq)qij@tblg!IJe zu%Vrp_y&Cpyg7?|v%n;A$UcoMU+ou$Z{v$1X;1VvF{Jpiao}*)Mts!1ck&#!3TQJ1 z*ED&|lz#TaJNknTZo+fi!G?_J2g z)slA@$unlBKecxyucbsz1FxZ59n#2Fa)Z@2#IWaqCHA>XdqM!idk}p#n<9*PxO`un zSDO}6ZOnEx4ou1!xr}_PPBTbSffw zS2jirX=$KpIFxF?=2y$z?ZTVC*t;LZ1F;gQl8?l)+kaGu|2A`E0w}^C=YK22=#xQ7 zj<)8BDz=tms?WfHLJVr&h(A1}(%6@h%d9C#Y8I^c1)63i2`!?ES#=x2W@J{*M9tvy znpQ77y5=Y(VLzkxXZr~Ap&=GS4a6{$u_nhh%H5IHDfcPB&{6A^`&H|Z71YL@B=EB` zm~Vj+%pwrb><#FKI=alB@>eEJ5 zRI1}Tv2tz2#41kgDAm!^PoM#VwH!%cU!{N)Zzyg+NBb2iiTq7}_gEVaUq&GdSJ3GF z9^5l0__SSt=KFb^ezZbn2JbY_gBhX&!=yt{FxH0mDA^67;@ppBS_u5vCMkTHtt-74 zEZ*1ZG6)TI(#0(R&US|CYz4o%Q${Se&cA4+&^ z5PA`4E_$Hys?_7vI+?niZGgq6>e7I~a8ZXvlnNHsxGrV*4iII@Lo*gXyq8+I5$>aB4QYhFKQo$HepBPf<8VUwk< zYThN?24^@E(pgNp9@5KXnop^e3F=SER#d|TW6P*Wkc;PWtzJtsx%Dmgf-PO=n|O#a zuCvfE>HnSOJ3nI?zYBAjT3FuWDcVErAtJQrcd6r)* z$|bKG^^{+6+`Arqw%#_n;INt&F+zw7`;w5%cMbv$$3l9yayV)4ri0OT<5H4dXzA3E zQd(dof8x4i*N-e2+>w063bvCdFq*H#`&~s4qHyXeyYS}!#0@7WKZ0f7N$1ny)kG;bTPs0Q7!t^ zndA}||JZo=5=ZoUBVq4zV-=GQZ&9?7_M)-cqk^J1Dsz@ONk2EZe%k(so(NSGI|?>u z6SNS|_<*U>bx^aNJWRau`(CzeV z{=OyKL!3h05NW$MR$anp@$e8HY_fq@;Ao#^>*Kp)a$3!5PpSWhwYLh&D_ys?ad&rj z_XKyB;O_1OcXx;21PJaPB)Ge~y9S5gmj5N){jIFEd)4k;^;f;~AXS`X9z4&y?=h}1 zDyUOT8daedP~Y27W5*ssN&wo&kF7dTkDqu7eC)qh4>4I#BlF-s_O2943<8*Cb`yD3 zOueB4>WNY8DdrPq7R2pCV(AQ4`#K305l1@BTINNc?gOx4#B%F6@z_FnZ6aKaC<>#W zpZo|!p>2@9h&oW1xUGt`e4D~jt3twVrte!1+c*h0wW%)HAkKswB~)Jx=8zmqkFS0- zjVn7yKw+zO?fKTXiHTbs0=i)jN8p&}%j;eRbjfdXdU_f8zRC9BJE4`fG(V4xu^r*W z2KZGYrimRg%=+VN8k-F3kCk_^&rMG|_YD(fAFb)V{!BsJ+Z+R$T)P7e ze&AG=H^{i4Skm<$le%5r3m~QYl#wF6k?mDFM6x_Pd-L^R-Ms(vom7fnR^f${Zej|`YT+{tql^vK*rSjt{ijgZ)7(Veq&hB7F1myQU#rt4 zt8(2ct&tH7(-G}LH?hs7GnSZb4QwRzfL`y5v$R!%3#q67NJ1TVP-YzhXbu0U7x~Yx zh`ZQ{p=j7Kz_Ykt802!5tjP>NjlpzZN9?F+~6(kEZ86?Fz;N8g&@a z4_IVvyXY$t7ZKm~UR#LciZA&Dybw;NdqAuR-NegeGM{nHn z$UYQnA^saY_sgDi-~!MbhByKD7a*9g>HOi_fT8SqfiaL59gx7$f*%P`r`V$Wm)i`^ zK(??j8sQEisxmr^l#+NvP4&KY66uav771nQYeSR3{8C%1HZmcL0UQkt?7j5})1y85 zo*IK0Hv*{u2y!5lMd=krAzX8?{2JW0g_gAgN%4cM+Aumq?P@UNDK%a>_N^{#q zX67R^s<7aMQsMhaBcdC=8d!Xs6l=``&y`=2(7{Yof$&G+P_!3oN47YRV}1{10jvB}8Eqak6@h1Xstdh9{~6yL6CsXKW6Jcrf@pKq#sqh)=<~ zX0nU~$224+z~vjmF?U0qGAlLYzX`|`|Ad7_5~h{BCOD$E=9117MMAZ!e;`8pVOAb9 zJiH6oc^R*~+V?iMOveBrwlaPZ{E~zw_Hr)T1CPnCL1$GHoj%0;lX)&k!<$l0?tlYO zr_xCDI2fhjy__?yxa*d2qLh5Z!LB3MKGsBPKH*aLBw5AU?JT71P+fv#)dd%tq(#4vZam?aE@5i(_GLPLrz5!#;&HE-f&ull}Qz$q| zT$XkREay5Ct(MKBpWE4UwTy!rK+oJus45b zSaXEqhk}7Tk%y0&i3$sN1SWeWC23Dd?9}bT=#(XfGuK(PmK-iF?i|2oj2Yblx2NtR zUb_*De7@-8aoUpgf%YZbyWmre)Nr5^Z=eOMCobblMbJ{8bwoLhYBq)i>iD1^t6r{Y zst{YK+_-Jbt)ra{-XH^G#X7%SU5x=qJX#6q(cP^BcYUdERJnM``qIw4Vyit5EA~1n zl3SQ`-l}#Zxu2wFC-=GXbdgOf+B|xyNNIbIw<`8E{=44<=|_R+h5L7KHD^Tnv7Phv zh%zVPz*5^2S3mKJlYg31)a4Q>J?4<^-5xyFI&H>?Fmo;Wjtl zu`sJHXOp`p?dV+2*}-|cTfv2r1I>waD6j?nepM|E$ZGgE&G!vnPS>z1`OBj8zlNj! zbpro6K3D@rhqvcH#s`}}_c;I0qompDRPoEB)MW#xOluGgE|`H?0%&JiA{=8*HVW13 zQvi>Wvz3gfk8)$Gi$U*OII7MYzTB%UoS}gsJ{iZtM}Z3nN0qtV8b8GdwxK-WJK#O= zUI%!TW(;Mct@42~1cBnfX0yS7f$0tLB^4SYW3SeG}Gn4EXYOW>e zK#eoC85P+gk8u{*!t-!WKf=rf zaf*7#($O^znWE1ifS)Yrp(+tHdNB4dp8Bwno8D1*B&|yggAYl0349RK==D`YxL34a zA8~-pO=TwV`i?h06LN#MjnML~;5K5yb@K^m%TXV4Tm4<&WxwneUHF4~`&s06=r)#K zWZ;_p=xL|dq@NDXkKP&v_WeMJ69%*&#_G|8E0-5~Dp)4RJvu@!cEh`N@Z2jD^bmPvaqnkPM z-9qrT+J9gW1*k@xczSGjAr6i)-z#5-7!&`s!aV=l+?tkQCGAA*Xo4oqMP*x z^|c1IAYC;jh6SIusp^vLNNUMe=lapH>0BllJC{NlbD6EcwG!voqcEkU1$i~pS!U5- zTa)A9S*;Aph@0}BX2QGXTy0Dd@B`feccayDrUO)iH5(ZgD;Z6A#kEa_5qbNCWy(lHdq0~8p7jx;CU{MRi`2hFTS(rpWH;Y z9fbv^Y+I0Pb!ZnNWWj^2netK9t9+~FZ3D=RB+bacdR zVYx~@&8fwB(5BrO$=&I|Yd^lz?L~BG`u-bT`lx`-Hzg(BkYX`Z|u%V-i@a)t@*QH+mErP}V+?{s(38eAGOXv_cFq?F9`X%n?!zD0E*n3`q(ZYN9HN8$)IA$$BhFo@{{fRud ztN{;XY4{KFnGX5H)^nk?$gq*_hz2^$jZP3qcM{LUkqgrFr83QrVgX0_(vfwWrO1N9 z{5}R6m_KbN;+556q(Z=jN zn15*9_YRD9H?~VZCg!~cTRpeg3q@?(PUz+oLy10i9#+fu3q`tu|z5?ApY3Z@=drG_NtU4qR z6+xp3pNsqDQ99l)On7H!R{v#4GcMw~!KRobKe3@4TXw{FFU8uMJ2jbROiGjE-P~Y0 zY|`bx3NCdbg$dA<|F+h}ZB4yob^d>PlvEE$OZowG!#`?J_~S7CZEX1a28DmdFAu)) z%NsL)$1iJNkp2Rg`~DtaCcA{GpT{6QMxpo~Y11@v=GVPi+NI?w{Y!d?cylRUqb_)5MXEsl_WmJ;2wMpG3YUMtnx+}8LB>^$93qt8lLj2Wp0_gk?k-0 zlFF`e$=A(-mV)LQ z(G=Kk(Nf`UZK4Ji+M%zVFEvgQQP_p_!{V~qBlN4y0Ii(=qn-sO*-MQzmh(<1Kq}8? z*$&gdWA3lp>G>{?^Cp$M+NP9z%gg|151i*e_zv3cGCa$@whIM81+ahx)_Q=jf%NIU zs{Jm>Qp9l4j0;K#p)EPksUmL~4Hhv+@5LDv1!C^rIUpj9cy0Hf(W3(HCpJA6{{qX#D;DDIGm6PW% zS?JpiOKNk7f|m5@a&@eJzAr~WSQ^3rDCK$9VIoRWxVVN>FWCe3%TPhJ6Az%xrX~+S zccN>dlzv;M@(?!SO%XvKN9GyDVVsS*Kvp1S&UP9~T|qA2Sib zb5np{(wrh~6q>h`u102yVLXgm@>75^8DpOW9`uiG-H!Zcw3Un?N)ihXd=!oD=Ujka zX@WQ(pO}1^b+oMM$DTXTe!WD%bX>g(8}WniF5Hc;4Y<@H`5>#Or~mA8h$LFQgswD@ zkbm98qo6FaNo)|T-V&$()d~lv{3JYLCpFfNg}br~Q>i&mn zDr=~caOYZ$2;z{fh=0C(0_!jwYprO;;rKQ~ww2L?RNaho{<3%hA9;oNNaRD)A}`e$ zY&akJ{FE`a>|E3pg{-J{b-&i9gA4bNZwH;2jz@IDtHULPB4HVzYN6h8H8b=L+(7}E z^`uPXCg})?o#nb}?z9eDKff}>_X?xv;Q@1{fSx;RC%+V(*n_qq<;8+u-yy#kJBIDt zF5=AU5l{~_ujMXKpD7ux&295F9`X@+d|ssP!jrqXh%4zprFyB**bp})pg(^%cx#8< zdX{fyXjR#F*kt_OI2*v&P5i~!edYWX)#Gtib8jei*#g?}rRxCoo}~r)#9RZU*9+o{ z>}Dtt;PR2({DIxaB(GE}M?n7W;w#f9$5l`=M=VI5H{>Jhyovo*+KylVp56-}@7AGsk-!fmJz) z&kj_f2XwuscyP!qp32i{xtnRFijUtf>DEd`Erq?Dna~>^Yt9(Ty(jZDfZh42}Y92z`qZ7Exea|E)4YPPl9M}(xCp{>5Co*S-jj|nqh zqH!nWqa_p^78sN<>E_vNGb9yfmtk*T+micHdbpA`Grm4Ftv(*+x!SM|e?q%&e1ZSh zQsylLb;d-C2o`X_zCq0Y_<;R$B=|2Os5Z*pzgjC>);(Uf&xT>@Rw{JWm{_rgY*aKX zFg@B3IHvXSMT&k-jtLHeS#vLn%U(3QXvaeg9}==s6wV3WLQWwI-i3y^&`WDzXv1}Z zLtCst5+bN#(_!&nwBZ;iZLB{1i7|Vhoi%-}3D@!<2ci@OqVk}Y2Ln=vr#yO>VaOtp z7gWrA6B#fJ-=|oCz_~tLavW*>0<%J-kXM;xiL=Lkdjo$JwjO7@ov7L7%A0N>Uysli zQf}l<1&zZFG?=3j1l)}jCPTJaQ}nSl?&HIc0MdDDve%$nP=KU>1r8(w%#IGvQd)t? zsl$vF#DpIuK3j%Q7=qp<2svd6g#T+NBV}16%vK9|&Bf2+Cm;fHBX)q0)7W1Td;U9vY~3vIN!j1POS?fU~>i z@E{7bsS3)gPv0JyD&)j!=e#;{5C!W7y#Jv}hy+nYD2`ONS^oe|hp}F7D^Q}sNn)@R zxzdm1@&ker#6ur7BZN5_Z6IRVX!!JU+H+a;fJ(T~b7f=zdu{AJXOh;t;loOy>jZ2u z*L=~GxdbEot75US@+D`!OOEsCY@H;>=w??tgJ*kz7wvn$mJr<6k@e#H-H+tUJNs=6 zK85Iz=(dy@VbhvDU$407oAbbq6uxG(n@{xn<1#qVv>$n7WJo5* zK8@JP@5;oq3MOsHd}`DTh{P&C0FE9rBj@L?2?eZH{OPB0JLem~{U%InzJs|S0aD_M zz&Ji9Wq?OW*F8s;KZ6v6&0N7c)f7Hz)sW*bh4$^o=aYBYj)M&ssw+{LV54P;&8n2@ ziBV;DFyK_nRDbS(PQ|bNT6(+>W`!d;hX6TTSwN>yV-dt`(idm+`k6I8!lA%psMg~` zl#(L>-GxB3I+!jw@H1P3fM9^}c=%rVz0u*!{dn%}_0GY&_n8A{pwG5KZq$%J)Yl_6 z#(I$2zp61@C&Jt&Dh$Ve$7@ofFNLkC?^0gu&*5D&AMg|BguHkHyAA7!lKO1Rrs2ab zcUBMyTPLs-^o^lsKDf^raK`>rdS8dqNP2%ocyk`szH!yF5VbS?pgDDMo;H|xQ&!48 zBi5^r?Z!o|vv@UpXqSUZsD;__L#JH!TQs8%vPTEF<>X{Cku^GS1)SWCYBev!wQD!g z@N-1zjMPUB@boAmx6hhS7I*5R=E|T^rSC|B1W}xlMA{_d4J)LYpgAiui{n|&M)-Y_ zd2@1rD2*yr+QQ8@zN$798Ku8ekhgV!ZA6nNvJWTp!v$+Q6Vu4%4o~cDHimUMPO!ii zQH(I)ju)qkkPqQ=Bgx8_S!?nqDVM0~IbEOEa3mcqOqM=ia}Vq;^kuc0QX;3z`}_9m z{p+lKqY}1gkr~GTU;O{5PWkPN|KB*~zxkB?=N$9bH;(!3lmCBm%uZd1zd&Y1um1uv zZ=+jQutUsq%1on|IecCt2yU8#_;5r0E47IEEwu>U#4^b&;@U&^4#$xDg7~dXITVmu z6fa491EV!~7G%(4XkXceAZ?_6n+)G%=(DFUFt&C#F*Q0A+^}NYyXU-o|MPd6?k&2A z&ov74tsmhZ_4vHKtKU%O|I&}}*Q)9_v0$xDIRns;0Nz-qXvi=BhSTxCPg(r`M=Y?G zTrV*BLo6r~KnBt$wJ!ePIG!koBO;R2u7{MUf)P0~I|xZ%ZfFrK+wam|f`n2JyC9rJg3#~JsDbpPLV4*H(6`pH#5~idvJzIQ54b#g zQXp#({5-K|@rAjm6W-u|VYC#exF2 zbJnY)$3+#=FP%RYG4n~lsUr?9)RA1jwqCKGRPR(mRef)`G$w#0Up8{ zS^;cgg~?*k>cAsIyNF)CwZjE0B>zU~@5O?7Ey3eI#Daw1#DcoQ-^2o&gP1Ud*ck5Z z-HdaGGgDI*eW;=rj6vm}`$}t$#ZOSP1=ZEp<}2feQJEPrcHi(R4-`wGzgUKl960R4 z75pIkSl(O+zP2uy1p z$Qrtp1H5hCqD~FJN}jwYLt12%wC1D50hz{)+AS;Jg&~h-{X{EMqxe)Y$%F)mpSD7w z7M`x<^o?9M%jY6Fd?6BN}v&l-Sm30bo-B@FUol1Cyo~g}FvX zv0oTJa>TAd-Wz`6pWJb$v+KqDF&X^sfgAwR^*pK5n-10BEmb1ThR`+Zb6J}zOi0$T z9(|$*dgk-zHLS5r)8I{4T#HCJm9h87SY)9tA5*vN>DDaX3b4aP@QeqLbT#G~s`l2k%ud<)y3p8)d4GnewebADg(puJ8-C5!*wk1Eil zw!dPAy2)!t#pfb4aw|t`@ zfLr{psMCKm8vI5y|JQ({KPqZ|QwvTtY5U1Ptp==UY8euSRXb@CuPl<*h#JqxEMS0Z zp|*K%R#Y;hKjby{*1?j#8gPux-o(=13d*qe#+%rK!Bg-2fhp96ayJ4n1;FlwdxLZ1 z{Aul+hkkxGNE5D;6AVZ}09*c(3FAOX|F(N4v#V1J)Sk^VBs zA}}xI45IP1y1_svfvI#Ju93;GY56O{2)pDmV=rTBB_?3?k_=1~R6zwI&l;XgjF;sG zGZIN1+R=&4qXGXwX&nnp07R(_q%7ofx?ISjBF^YxdMW_btxScSl)NG*CXxe;`;Z0U zlw;2&ldB;J3h1!qCDP|F1MaFPwpt{ytJBLuk9!ITSom&}pO{kK3+ZH>DENGr??;P{ z*#_sy6oI|nrN*GoYok74a2pn>V_Ws;McGb>#0TlZ6yyAvX&h^BB0e>C>*$rr=Y5Pl zpiK>bU=?8$5`M9O`2*guq5&VEO-(9zDQO+>D@an5rWt>VYOP~&8R{j!;JMXPoXSm% z*!ifAcE^-)#kzVLQMMXjNmdV`d=j3tiZd{S*w=l-_BvKar0@INWRy_gsX%2xoG(BEt6|VULv>n!eV_ zY`{RDBZ@b^2OK?d@X)b%8S3su5zII}mtA87jKu2hMH5Wu2Zr*KIe23CAyB|68p9_Z zQ&%+{rS5`7hi1m7hxHZ`9yyCRjia#qvtt*#k*YU?72c+5?S?{ut{7ErM?1ecUXAT5 zmw9y(yp%1jqN+Db87@ra1E1B&!S@7H?<`2pkPc4LC7(j6F}-BO8uNjoAFG3TRPAvC zlv_m6jKxI${8j^$vb{#;Ga^<)?OOvAl+z~j^KwRnxH~wJW`wP z<)}=v7i4qPqDMWdI#jqdOsRKF^XQI|X2AAedI_1`G8c14^8reWGNq1YKKMe^#gXIu zBUBZE<+rUTvCic4+F*{C8s~RcYsrM|EGv~d)5O9Z2f0RtWw>e|=5lb1PQDlG8;p#k zZFCp$G1L1Tx8zDQJ2S3ro<*Zt&VD?{vRspRb&SoA-mHHwzY*#8YDB>*X>Vtjxf@MY zvK5Ml&b?|O0*GIJrWqa;w#&JSl{wfTj2Yn@O@#Cjy&EP0 zNyIFpu#oZ-&U`l}TO@vN%>G64O)R)QEv6&GY%Ir>mL}U%1BeB(^eRVlb;dr;{>+#( zJ0D!$fMzM6T=2fe&9$B51bvPFELH2dam@b5y$FAN4*w<={Cxz{zx5)BV$)1H86B#I z!~g0CY-e7mE}gtu=@^8|ot z4u;>|0jLFr_HSyz)E{cW^KchHEoho_aqidRql|uW_znAhQwvy|0=)iD4x`_oW<`Kf z@b>%ZQD*g z3sb{a4A8aAvdy^I0lEv6kqxAd_^{Vk@2)J3c;#~`fYe=~FEd%;oB>xB2#T;hhB6r< zl7{3@mRK(nCWzo?dys~LMD^NBP>UXQ-WI2d0tq_2kcuNjN%*}NLMEtl=(*8ZfaXD1 z2XBMnVkKm9T&(T~mG5ZVu=^;w z2wlQ-XUJr-RZ1k%sV|4fsc%pnX^@C#ga*4S2QOfUg&`>q==13p)3^nx$!VXk7J#OY zKU`W!SaXWu3n#)Dvb+=?Od4NAnnE+j7kY1}H1^(bL-$BT0JD|xAbUb?m~_ofyxZA~ zPm{{rAxd+o<}6S&LA56ui!(u!-;!NM_&NbqwZ}e%STbRUxmN9qo%X^ujCvbwp=q84aG8ZFZ5WC zAVIS14Uej0_qf-*KC{MYDY3%|qwME*Ac^6dFVE7n-2YTafqo|Tr$+$wPB7v+{PyX` zm%0IS7JSm!C-^&)5J|N`bDKrYB0f)J*5$qZHo6YIaF?|E7u)q0jB^{~LXe~_kw$zL z_>PB2+ZMPsu%oFZPLH|*I+l@7tTpTlfOdpd^JzUc>3BzKhh&;&WJ+gAv0*q?W<_J?cN%N#F42R$YO=@Hm76FK3l1q= z7zq&@nTs!E9E^t2GSrK64v3pSBu|pV@IwFwBhlXdgb2ax_R->YiBbmnBdomU&fTNv zjX~NcP;>+LK8aSvI=e4W)~Pk0DN&L@r{!+H24BMnVZ5lk_zzP*-Aenzh_7egY6hFX zizSok@rUQ9pn2NcM=s-}4$X-0!7w47^8 zJflzf202v9^v;9ud5nHt5HTo&e-c$Jt~c1uaCkPB7&FjM)hh_qbCK=^-Dq6=Dv)*qBB@N4<2CG*kOYa%x(A(0h5W za8=Tvn@qUThC2lb%XWinwyk-(92wKjCGAbz7Bj^#uHra93J?)^=g7K|G>KRPPEaqz z?7l+*U^?J`t+?Lg1cmT}?!U<9e>5}vhBg}mPT#lZf1JSo=JCvl!LV)7qU|Mon;DAf zYY2<=xfTRR7sX8@C1&4dh86O&TTnaa=q3{WQvT#W97gvwfD|NY+!<`c!P@uTaMV|C zLj!-<$m(j-T5k2}?&?A7LF>fR>Rr~4b)))%!a5e9acH182x@r{AgWMAoXO0F-8fZb z1v@OHAQSci!z74@`~(GS`Wgg@3Sp79T!nJ$q}g{>cJUuIbsD1MOX}8d%qvCL-T8dh zz1rSrF~H&muRy_19V%a@b0^%ax-G*20tVpnoJaQUzBD2N+XMp_Am3f6vZBswevD^5 z4(UcR?S__9u;s^23JE>w_2ili?EMbqZ`@1o6eM;VkiAom5HufbgIs3$dFQG%^*s_w zhnyWHTDLJd$E?K1D58&Q!1t>5T?5sjoU>SnZ5{-t#{y3=wS-MeNw?{Y>%9mdtLGw! z15>)J!?-)S;2<}wUi^aw;yY9uk&$iovpXU$lYUA#H~mutFgL=Wa&MHv?ReEKLshb7 zq1(CR)z#4=Ao8s`mo7X^r*j6=(;;W{26_CTM1X zeY$ib23cKc-4AgCN$8LDr#&Ucd?;5AOg-^(rcY%_naGR=AxrgV z*TLR;H|QE{KX>$$a)eob&ul^&-YGy)z2_1_Pn&26l+vrO{wFa|wx z{HjaYq80Usv$SSA-xho0GHFDt#D-cYSh#=S_gE?Im?6LmgPVtcS{fJx#*I^>F1UDqJBT@YL6lEcAE};qMPP~itb3e)iB8{fP zT$Jx#7?R`jff|ARq9VcPkVv)$5y1fSb${8sk6-8NrBdTLyrzZcvcGd1gPC@?y#^n89@Y!<(Gn;>cz zt8}cCssOFLB3zps6&Vctb(_B z;jPKeFydJvq%ZurnpmHKL3v2FBr`;P3q5_&K-t&ki9MTui0kppFqZO9^%Y+vM)vm9 zPC#2mZB&-)>%8n6(rVBEQ^UGB1#)^Es6PSPd4Ox|0!3HE?SG&N-zR5k|4$a9e`A~f z=4<$$vdw|N*k;eizhj$!4GjReIr8t}<~J_E3cw{G0Jwz0Rns>vLB(i+N3kGW;H^vz zQl#;ZGPNB?UJF2(+CfIsZqHkp+L;WD1;?Tg9|0Cex$4C7LbW#BuQIjKstkB4+yqz~ zHM7S|8I1&qq&{KzjZMy0WPe!=RYp3zwqXQl&tCX zbx$jW$o2W;2;wvf@HFb_BO6#Ktvvkau2^IGVtZ*edLlx0dwP0h9d=g<8M9FUR@ZFI z{B11ijZ27+K^j=x4`V3I>@+oA&LL%RBs_3Z=uL3Uy5l|IId=q9|HbykKlL*lJS-m5%)|8#M7woa39QS& zt^-k!k5A7zmG0BZy?j>)zEO~~Rd^=Q+F>PJE+;K5++8a=!d!>%tFFRVo8Hlw+tv!4 zcV)g2wKHjRq^39UL3|u0s)VkkGny`R!?)DvCbYO!y?0<*?u!~Q+*#Mn_xiX(CX+fi zCkT)mJjmB!2I8piGRkopR6m)dXws$JQu5`QvR{L8vwul4WxHn7_->RnzD)fc`vX>k zYu6c+SAFt6Z%6lW`WYny^jGP)hB;9DPg99I74|I|)*G-&M(QNFAJsT&&jZ!h9mO)#!mxkseVx%{TYWuY7FKGPCxxACECZ zojI%(JmQq*^z7PuXXC>qjPKw3dBkr>f^QG}v(i6AA`$21?4QmehZY>aUJY`o&I>?GMqd~RsQ@@~- zz!2~N&OwUMj$a22Svd~JXNvNqR^L;}7G;mPp#7 zabhCQdeSB2|2=39Ng{+!cX17TrQ6m4VX}kRnXx{tu2>wU6j$Lkn~z_-C-PlEd12gS z5ZmgZcV0YtleK?Dhm|In(u(hMw{?q89}$*E`gYH{_y%5!W!TF3LPvumY{&PTs;oF@ zX5Pj&!`&*KqOU8Oc6sWQ({A7z;09}hMAF&wy0BzZMMBW$vOB(r*2zEhF^)xmL$~W@ z4$g+I`)*#>NGk55ju(4vn&NXtH>+Vg=B+@Nym?C|Kb^GOQ0gVm3O9Tat$2rR#&wfhUjxFrCo& zKuuwKwe6aPE1ntmZr&Y;U3H99#kHq|5WDR@+&fHuriR*PCTI{0xwwWNdnwOu& zabG4LH85QjLxI+|{OC!n_lR8jS#4RXd!oMxgUnF~J?95hkT`MaLpsPWKz$ZjEDyvV z6kJP!aikSLP>o@zNYtF(nkw2YNNSSCW6y4MnqwEmB7cS4eLpRl%&1h1yAh0J~jTQ~OQs6PIwz*;mYRKM~zj&W@+|onsY* zTMjAX5sFU9TbE*88&UG7 zt{9IiPtSJFPuvoVngj4+Bak*G5!-PKILo*X5$SVNuI`q6)E^EH^*&uef@JPeyMGWT zw6+L5C0SLbe8ysroVrS_GhEDr7R5Tx>aGl#d&bYwj8gh)a6}_a&!MQs`G}ltmT=|C zlL@8d(8y<$Ovz7;LK%1>Bf@$#g*Wq+75X+c7{7EOh5}#=tBNe5sajora`w7&Oe$)T z@U_a}=e3Lxl@%>aBjU!Km2=u0Jn3QP{V3@S zVk-3?eEOY%noA9|a8Ia$7?5%1s)K`0sb0hm{O3>wWmogClc-8jG*oUh5(Ml!b8C-O zR0_e_Qr@%U7a}0?XpoS$(T*uJiR9cgS>^BVV28y`D*WJaUX16AOZ*~js=K?Z$C7sN z{(+(KD)g$l!kWnv=b{onA^oXsU+{xy)dG*{idUbOZHjkghB}3|S=9UEpe0f1fiHmavnk+l=z06qANCD zhMZ#LHzCX99D)nBt8-k~-qLp|l;-&u{U!N+l(kqB0+)~=^+*GCNPJcI+BEU>`JDCqt7rV5E4H15IAQtbZ zc*RLSPnqAfUEIw#lA~(*JkA?-cnpzY-_uga*l(a!q%)Ai?Y9r?>~<&13j4a;c^$R? ze3=?4Wbz$ox8WYH5XZrdA0xIF9sT)JNg92T0tDL~rMNtnXkwfDn=+?+1e@_a9w&Fk zCpLE?@k^Acq<5-9nmAQ!JUHhH$9@VFLsK2&`)w1M?q=%B9q$s?++*F;@QI);^ni_w zC1Jj|nwIdf`>cIVB&6%vpQ>>p69I0qwMR z7vhF-W-bjZ-iZN9nz4RHA-=)RF~~j1W9*}GB)%LRiT(V)`hniWh=271-L+9x4dHz* zLI=`D0VX=n0hBT5<9aDno#irz&q{_l^kffKQH>>GSjHoMem}Q`HJ5Tdjj5O~=8A2+6iyer?d=J&G03iS7`!!d#uQ@zV-qf`lle zl~6?_$k;RSfFfWKqLMR}3156924eP8PGS?p%1C(apw>;6@Sv|OK!L#XY-7%$uBxJQ zb)wDH-uceg^iBM{k}ZedB!F-hopgag&(Ij6@%MPYWdUorhOF#X8<~kbYaz@#=|7XA zXl*VIc51AE=wwPxtCa`%;c69dP!T_7wAQe@2BO2b#Xo&gW}+2^#smJk%^)Z56Jx`% zijBsmqv}tmf178f5BwQvdK?Ml6x?(UZ|N!n$hjsUo5{rTIy%?-$KoSo2NN&=6BjwZ z)Fpz8Y4;;4->i2d-i7(8hO3H3L*FH^ewL>c_Ml&a4s5$f`=u*24K37j9TD<~k3f^& zx>g2jXedi5-6HQ+E>VX5B!kJ)PVoAZWZrFt&ga6R5~`&lhDkfSZ+M=OuHaLZyZ}S3 zu6UeXXz_lgr<-dk|I~yhz)(xdomGtY4j1h)-gHJn`WdD{X6vqEQB$m4V5`G)H#Wen zKVk@y$Dl3`*I9fLGi%t0rUtAy|GTD^-0o^+kBMUT|R1YIfl3j8U^Q$ zrtU9Lsqbgkq8mapBhdXeNUO#18a^0I%k{E1=Kj(n9wN;2CsNBmw=Ijef?RPCPS2K# z)Yj>HQkB<^2gnd2eShkOeir4&dwj6U+uPrRnOdANX6n=3Xz{iu%q@fA|D04w$i;MN zRtv8i+lj!g8{7cId`_N?KF<~7_gxq{juPL`nZ}nz${D4jqSNrM*#qOzFzWnUP%^^% zai69F$DIFFfCyzy_v;_e5X?V;xuYvvIc4EQ9)q1qf@4N-3)rULq4_nNSN(` z7-CD`oLnC@no4Ec7E^4t+8fbp7qO-Wqn-a4BNqPbYF^%+(xJynmQd8UolRaOJnVF;%pF?1 z4OI&nP5r(cAkZRGRrk^QSi<=wFKx)d+5Eo8I=y5kmc9W^RveHw(GAF(h$8%q@T;tO zYyGXPImPu0p!o91{mWDPUHkbG{?HrSP=pMG#tRn*1Qf9u3Jyi*ucac zxNcV!qn7gyLMj%h=yC@EOsfu;A5EC3_dg1Q48xI7j05NzV zhea9^pn3&!Vv_BaSOa&8AqdA@;yGnS-|kzmIFJhl&`zC$gy9q+|`mWQ-h>ic({kurRfvkvfQsMn1h)cz`A_khD{ty>1ez4SV=P5csQ-K`gwkC{^vpZqE;p zQ8RS#zRH^RQtY7vq!r)&R{YILDMd5AQ*gtrYa=R4^osfHFz{{8<87&mVeDu$TlY(@ zqw16v`OQ$yAJEsF<|Ra&bX2aCQfKB`+9=$t%Z}fiMhjcgvWrYPViuj=5kY*9l676J z7&-cW4Bh-8uc2bYm-zwbJkn4HUHu?W_d_D!7~X0_Z{;5+JUjpe5Ovo0a-T!-DNN?% z2l-~xA2U+T20a-JnTt{l2ERB&Kq{~tkf4G3zn`CqegL=DV!hK@CdnVew$Pza2cf)e zP_83R`RTi@65%C*9Es^y*e813+@AbQd8NSH7MC3h>3oO0mfEsmx}vvHe1ESFzJGVY zm(1^H^s4#l7kY=c?LF3i8Atx<%wC}IOs@Lctg$k-JJ1rcCciJ-Wy3Y&fGp{x z7;xz#Y!BOzEK@1F!b2_F)%|r}^5X+;UN6W2SLoJ>KyZOUtG%u9Lvl0Pr;=H;zna{VFR;q{b2>!?sUy>IamOeuwHZXXv;e8ipK_c)?&1 z_so)`W+n%I+ocMx8md0w3S?1N()}Q^b83pxbjC3fV?ET;(>1)P%WQj0Cez7+-+q3_ z(#q8n9W<(Dz^IMlZtw-D1h5k&6l0R17VmXDiR+-xd}S<g=`?xbsn}Fi~24j3LO(S(%m4>B!^Ah*{(u-H5IqXd4C>ST6{J#8b$tI~G$c zc!%QjxrXQitPM^m=T32?#Bp{AX1hI^wF!aQeG|V+yT4b<&J&~ccp0WuJZy(quF^cM z*22VmHiY!^C0Ki%(aNCR3usZr$Oah00>x6gne2AUQ3y^_HN6O6cT;JgNcAJ6? zJajg@OzNWtb}tFkt{#cj43_Elz|Jm9IC63sa=7EA>2ce$S-iy*V_v9oDxG^&@-Ce)Snd#~2ZhWc!yW~8;OaN7aztYpB zOaA#EB+m_izEzwF@&-se1`_y>k;5M}&uW0x*T?&(^_Pu`pEa^Nu3uMTp8w@VzMNLo z*>}sQ5W2-uX-XEyE*-1T-jldiQj}`82uZjp{G_zzyeU1GG5taO*HHl_*<>2+sMb3K zj2vgUQ*7a+e%3-peLw3~%P@ZI_?8wo8s*dbn~U4mpAWCz{0|)u8@y$-9@a<1VHZfqt)hhEsy(H{a&2Wxm=Eo(!xp^cA{d3 zL2asf^69IpdtvNNGB^oTT0Ia&tg0x`K&(cINZ;(Fq8IZqG`fg*;kw-0w=;5q zPhA$DfD%9~+1ZnrDqfck)5Uur4|>DQmpunlL#cRn2(;m{K}VU?lxzr;$H1`SDayqs zLGG~VWtw}Rnw2;121xT*cm{u2m{Od131lp?2$qkSge@jlBf-G=o3eDl{7~FJS9}qH z@y!+IIM&^*dbZ@Zh7h5Tc;0n~2#kW^o~BUkOOlx{$~@%!afcGu;fI}~$3 zbJVU>VFC=cud=7gy4tj9b}eR`$BQem;55axm6NxLgn8_H_P%|L#dj1 zg^%K>XkZs1@n4D;g z!-r&cDV=82vY>3z8nBoxZXvaLoySyj{Jtsl=?l{sXV%Prfl0+Jz$i&C%pd2-ti*w_ z5wgOJ#~S1`k_+Z2^y6SY#{80#+^K|cJp_f}xHGm(p)=gglV-dP9SC_tN}9WY?t3MB!AmuBCC^twEPD4(4oa6%MJqZ_Fg-VCbaFPklty7( zGpVg3`F$qkjA$eS{8l&rzMSa-lvuyTq9Y7IiB^u_&szel~U; zrwA97X^VHzX;}X%b&IP*7jiBr^`VWB|uOYVZBB*Drj0 zGZ`T?bSpngy%lL9O*1Aa3Y5jN8Zbl|EP5pWm2OmZ3H>F2V({9W1b9n4J4{+ee3_;O z#zY0qJ}L;n1UOpz7EdymOA_BH)y{B`KvOKD8fbmKF~up`AZdiBEblcgXvLnL8>O~V zUmOLmzGjFv8D&Y%W`aZffVRIp_Bc4_OIbx)j!rufPM^t*^nlFViJsr zH9#_5X9Sw#q`~W-3Z5CquJIO!*|cBk($j7n$;hUGCrzn^-Pcf~5#_T1k%SF^q2;^S z{#}V^8UB=oEBMfq{p|I7QRf8^;5-QT8&AOfhq*fHxv64z>UTYIMSAi%Ucz?raOj4q z<dPiLcO5fII%x(Xg-%Kll{~aSKT37!Y7+y3WvaOgv6b2U< zX2%w=rt$a65D}M{a^?oB_5UXM&<%!8n14H$iFB%_Hgcdqm-C;M!=Xp)HS6dMAB=L#Tt921ii z^K^>=Yx4fJ0cWFKw6ZMX?uc%%c=#-wG2(&;5Zcyw1Ydu`IpQ+NSC3~U?;Sij)kh1# zm#%JXu~XE(BNsZvZQt+D{?+v^JCmaI=eK7*i)b=g3(4`IDpYu$nfu>z)5q`l?!hD% zalg-?vMsDORu*5Pe)Fdm{ZgS5`+Rk58{vGY^^8Nans$nIc}XqKOSf^p*JM;&l(u=X zqub{02E%;84iVqMHZ-?>m8feq|Cxj_Yh~cLf_p)Xj$~HDMUw5f>FH4F z_EP=kph6{mt`cGSWHTRNJT;P&iC51&lQRaqLl(BVeMMEE%AQ2Qji2YrBnqD9x8Iyk zW>W?wWtlAo;avr3UO?xy6~@ojLGWa|+fPq(&rDt>O71HkLUi`hv@tvHpgwOjfWI_J zEmc^G7|7}92a>+p?0eSq2K;+3K&`l2Ks$1YO2XXa>U0IRQ6vD?3nqxRGk2FjBrNxo zv>d{2cJxd65iLT`V1ty410u5o=)?|LlSH{fS%N&Fo%tX&V?^1}&2||mHg>ad?m@$( z(u(?W9(_S>ntFMEM<)TjIHyU$&3P$HRE8T76_eif?njREcKfB)$tQAO8La4HY|;L( z3T-4=fii0y-c*H>q^w4ShT5otCuA{JZrxGM8|vJL%#s4cV3h#Bk$+M^^NbaCeFQo4 z00@NtV?Oa;5Wqi3p#NmD)s>f(?iE1nc&5g4mz*J*_e8Yxyxo#L8b=N`Cv!NerEZJQ zMtg6ov+3AlyZz}NbJR6m*Nd7T=%{q!BgoQxwZIj5Oe`Xrxbuw6{0r}|G6vsD|I=u% z>&SHg0|Xdt)XI1Jy*okuBfSyubdGesEwXB1D-YmL^;1*#_CPH zf9M!C%#`C3KLQtUQ&E+wssng3J(p@UGMo-gEy|PO>WIa48qX>eoo?@ZSR4WQYzr;B zju(x(nQn%DQ3@Q_zT z^w-#I)AW5Ifn)qe#LFW=946^h$i&Q0MU=j55nHZh1QiTi%nFVY-lx~^nV-jLH}Hu$ z%cxouklIIUHJSEiJ%Mh-*4wA>Q1x&`xpAf@=(fv^BC?+M(>18OcwtYV^8i`~uDV)P zkh?2GJ2*pK1C_JX;b?}F`W(EYu5D>bwtC)3*Xm*j!0#khOaneq6-qb>m_BkFfDEzj zaPamaA4#f|*j$n5P%H-wdMf@wHJl6B@HDzI33SHWS>|egSx5^r$k=-jX3J<94>|u< z4Mhc9rupDck_R_SPoI7=0CWDz6`8!oBVfz?;17;iy$FpX4$ELlZswEp3Ctd*Df_&u z`@(_P+yBBJBm}o^B7j@+<7tiC)yvrL89$WdTFAMP3r!Tb%GtMSBX$^no&8aF8ppzk zM(EYx5qu87taeb91S>5N=k7DRkkB@W4PTvNw&0=2pTJ^p&&~A*cN2FHpc4)9hgoKD z+rH8&|MsD7Oj0WZ=%4Fv6cOdM8BIFLgBsm(E*Lzs1Kt^JVF#&EW=b{ffMs}=o7+Sk z&)-q(kbfJ2Xybsch>g;A?yr`=tMEz2QzPAEs6PngrZ+xdH9x&JjL1)%39iF;o1n-I zDY~`T_YiVypyCYg@heMZWbLe8|)U%nyU^eF5ICLu2q}=3jmG7GGd=S?H(7MTd%I z>-1;W8u!H>KhM_>7(ej$ZE0OFFKH>=hoE_V?@P*C5-tS8wa|n3?TD-$X;?%U&~+hJ zv!8DbMq$SkUKJN!mcZ0QQOUHd)yuB5n_b03P=OnRm3I&b^<_Jwg$RiqzV|f-VFmg~ zHVD?U?32#`)@?V=Pbuk%&?i@uIUPnkdi-0oo>%+?wMZv4Nyms*?pRvcZq9Xsxb;($f_z`WyMe~YtpTQwYSyLpPuTUq#?fG5%Ks!XE_CmVoN}@&2U(|1SiB zyUldKv5shb%{hYhzY+*xe?}l+{+|ehvp*vcD*lu}Sf%`C^S=@Zh+e!9q=I>$fHhM>k*Nz*9WV4;+?_&BLZRYF9d>M3vBl1ANtk_GXe!ENL0aFje(#79scCtxT{_R z%ZKas(Cv#C?S_g*T&cT6DvmTth#Zj4Iat=ePD^1JG()|W|s~Q)5 zYLhuYhWuep5v%3UQKF!hZJ=T74SA7CTft?@AG_s%Z(BcTgT>HCu<{?>AXEP94bU)F z9e@wDRe>7j^m9;qt?LCe^`|T6i_ZL94@$AU&=iaZhuj+!o*kkNMa9`e)M26nKTp_C z)zF0Jn4~kAhI-@i2$L`j_|(whx<)>#%yE;1>hGzyZ2kb(>K{H07@^;0V{#~{wJHRW zVEUXE`V+MhiLoiyZgyPeY^mLHyAYfXjE?GNl>{9%6fWcv)}|XdNZCy55ABarRNa^b z<;SgYYffwhU}vz(E}FHI=VupDoU;HoU!CuUH>?{N{jF5h6XG426r1phyK=Ka+g3VtEgmsZ>Fu60E5_4g?_xHXs)W`2c z==4Cc5%EVZzNC-xdwHIogo5}8Cl|!6jBcItt(`v=ucvFE$1b;h=-z;$AFUoi@iv@7 zA6Rh)g_9&&2jNp&xw~hw)?4|Y5lYW9^c<_1_|9{SkWa}_e(97t(`aywPdPFFVo~;F z7Tt8*ReN}&*5uzj-sa}`DZS-`M*}3JmlVRCmz+^?W;dHGN8DNh_QScvu4OL1(nZo% zxI@pzDI^)HImt`RkdgYiUvg~{`Bu_!Sp(j+fezS_PkM|j43O)L#7`FXSbm19pu;-C zKR!aw7#^hPJFJmi@}y)L_H7KQ#Dl{`a;3>kD82BkP-cY*@`3-eQ{s_2(hX*L#5bDV z`|~eBW6?cMrIJoFw%BrudXP3>pYh|BJWxH?B%NQ+b?3gK7d z;7+xl4v(g>T4kf=?pCdOk3*w+U)D9e*2;8%_H@JDyO3A`mP#b5p2UJpSTHyBQ-ux| zx&wL`u?vE5^xnG?OCvndS5AIs-k^`BgKk;cpVjFXh%kI7MRw0_76V2bBr6XzXCKZI zD^AU<6aq=#+(Evq)Y$BOAPN}}_POF98%E1bsaL0DF4ur{5Q;v2pc<5|G%CMCOO<$X zhd`P$Dzf%a5hQxGpZ@n2gJlk7hbsu@%fN7;DLn}y@6Z)K>HowaC`$ehgP@7?ZyAJW zW%?Rf(x*GI`5hfzvvC_#ybc}tJTWQo?^NIY5cDornPAltJAwW_6n`)Xk$MVDL;n?n z@DIt(e=-vPkD}q>Eu7p%5(Kn@NhR0dv@5vp(??ue_l~nVAg(PO5Z4CUY7B^L`;atj z|Dz7t`tyJ@yrN>k?}k2^3Pn-5yjhismQ;PJ~R!#9$UId0j=x9J?THYKKg?a z`rjnB0XPI16aa@%AYN6!e?g@RgSYKk;QRRpx;F4u2}Lu74%+Ejf2^=-9N zS#N*DrHtk9gHgJTu?K%NIF;+o{#pvEB#5KYI+{^f>#?RLhvn-BcF;|xXzpl#c=Y|N z68f^kZPFOs)Eo^6UkXUURfzx;s2U1>uB=l(l6amecWH|Hx(u3mzlCeB!&AXD%sUWd{_14sr!n6JLzj&wib*(h?WTuff&eeT&Vj! zr8PYio1K(%{>pma=G0FZfU$T1&=SaFKe(!@3`ACk*Nfa9YYc8Hp22CDmC#@d)J zD+&nCTe~m-@W2|`SOWkL@wMNgrU9RZC?zWZco5TDO=%kl2j`je5u{2<`T!3W4jANA z{Jo}s2M@0^%GLfZkQPM%@PIpO8SVTx@ZfDs6>&mx+-r1t{JI9VH-!>fNvtbijq3w1 zs4;EzOK1r7K^;SBzZ7tMv=A+96zcIM2XK7kuEzI`k(miyQHtisNahq8msGQ6tIX_A)v_b_&-7o-4MIAEKO{l-m4>RtZCn3+AH zAfDZM-h`upb6(Mb72f%g82NLNb@&aF-I!rTH%h;;Ztjf(U6-+-DjvjB7U9ARH@i1G zS6%i1E>_cMJd3r@X^pYUv1i;!j&y1K7voulLoFnnviqA+am=nBu^soGJ>yNBzty7c z5N_!pPJsEyM|%@<#Gl+ASf(Fmk=Ip%P_5Ij(hs6(wYM5oX0YSeJHK|@d35PZLoMU0 zof&|nV^pIRBH~)>eERJTl8#m#54b*h0JG*J!~q&fkK7pz+Mz0lWC$;lDQrB#vGB;M zq9LHgiB5t!@Nw8|q^u*vqrMC|#XqgvpFV}O_@(yiafE#A+4lDcjV9;`x5?LK23+dT zH#UK%o8+vpIB-yudkL?jsiAic9`)9`yuZWI(xpS0%LJ`C14y??0%?`M6KGc(N}~IL z`FyGx=U{v~dW4uLtbPXig4zeio7$s9^E2fuVSA%;EML5(JDKzzE@v7^I!jzQo>K`w zI)g)T8>kHwr|Mtw7Rqqda+!|B0GC_D#whWrg^!K064W~fA9u5s9NX)`!qiS0FJ5n4 zQv{E`@A6-8XxXb0q=Ga10tsFBwI>^t1l=FedMD5BbkohG5q&(4j`O`e-Zx_TcgL?h z!CZ^4sp>gHJurZ2LBvl58Ss3GRKZ$;es2aK-^GZv=p8iex7$5%amTNN>~a(3?H_(F zBKK94MiQ7l+YiQ>ZjG?~@~W^v`=~Lo|EbVlVTrExYv6~2l0kVZg9l6DyNoXJa2Ot6 zr1@)0Y1+B6VuR-_tMnysBU#MGSaI?J6{nG<)$i-m#J?a2N|0l#EpxYR293o(B8U&3 z;RU_S@V`4j`hy(W41gX!-v5puv>LXib-`h!NjL!~NJ3`~M_q^&=4_3x1_ncH%(~i$ z=CW&v=-eToE4Ii&0l!jN1YjCiL9&C@Pyqhb zIm@AuAO6)Dd(inN;ubVH0C!cNY_Kg3&@Rs*`c;kiaTd2cd^=o7!4#-|qTq~Hgr2l1 zfzSI?Kov(EMn(1DG8tHfxsbN}QxLGX%_KWZnamS-ldTcxqDSbn1^BZ$i$E4kbI9g7 zqhz+@AOe0HgD^HoV^p8M;P!E0S4Ycj7i()AS3No-I6!{)#aJLSJZF<}9Z+?n7@Hh@ zRR}slWo$7cTNNGK?Rl9B5JtZZ*Psr3%mEE4Lpx9xKU5b_R+pw_cKk)@;c>TOlAh63 z*8qrIFwVzJB{mXU8yy{yzy2QaOT-x9NpSBeA~uV5@zH!@y?u68y}1-#n% z0yv4nV4V)LiB({D-Y~9bE%xs?c6g$S>1V7E#$$1l%X3xZ^YfxT%jtSQqq)vRsA+F&k(K-Q1M8S8g?}W~w*P4O_^vnO_){Oyk3E?|Y*|WXA6~Hs zOt`fbAB=)Ua67P5ih&h;w>DxSYLUDxN_6kno;SVj7^8Ez#+)FRA%p28_)q77svb_uTNB=y$^f$$xIF&83E6N_OYxijXFG+TCotkC(ron zjD@#(h3CE$*VH1#^37|)8+NTJi_1F&}1Y>0VxsB8^Xpe0e59J99hcRheV4HM< zp%$^jzNp)SuHN6PjE;d z(9FtlovdG(%qvFuiqfm4;71j5cZBRg*WQa~nEEu8q=stV#<8SD9(n34MfvvP;!|XY znGuNl48v1`<7sM!1io5sNXo1ZiBFjgcZ3HL$7K3!$)q(y3~|SKXNSy+tcYz$_9C`4 zN&hI3{9Hclm{BBNc#ICJG=EwQN!sIzck5zU@rrlOLvX3sC!9&KxFXwo{er{T`fYq< z>MPDbf~usrs)i;wE6-IlagJ)ssSy23&8zI*s?DZf_q=Y0Mu5(5UaZu5-Q{-ILR{M7 zGe4$idfQc|7j3&u%GDY6w^6h>mA7`$pXxX{Vo>#-b2X_?hhHpLfnCE1aNZ$BTD~xn z)83A_ppajIs16luo(rO;RqH(?uf%h!1v_0>vBwlXMZ)UWA$2^eay{^_9yf`J?6&oC z>UL&dV)nXAOn(unVUZK~q28Q^vdfMFZsu|q%J!xDDi@)U-AmrHkIzct>=`p)B^ zq1@J>G3{{Xw12Rz%p#${8Hf@*^?55QQ&w1C^!X2G`5ypchB1WozdJ$t2TAmwhqe8~ z36eqh|K$^;3+?}>CrBUM1Dg|gCaT%TlWLvI_GP!Kw-FKuctDVRn&VxZdCsX4U^U%R~l&H~oS9FsUGg$XY`HO3TD6a9gshzvTz z`_S#D*Ti3(|IW+pV-$hy1;PB81V9;qvcc5GI(L<|#k9zY%VaP_3Fjw39@&2UidT!~ zp=kV~vLbApxI(cwM_Fn)ia<#;7X8aWt|96=$q38C;nd!Hi7PWOE?W-NAEa@F;roh& zMGoZlxCke|Ub(sv;H%um^vH)SJx-<-9xoTZod5re)d5arT2zy>Ae zd=F%~0Mea_6f9Ru9F9+r$fF{Tum2GlUKQl`zNEEELtbY33S^CSvHx2c=`GQqya?)) zvp37d?kb{^ZR@lD6&8aX?rARLp3KNad`gV)0#f&6AEWW(#0AHJg8|=B*Q6{V-I)sR zX`>jjg?vgz^g-6DYhLoiUSgmtpHESKM0Sp9Y!Eq zg%XPd*luByRl^gWvxJ$`GgKW+6deMmEQW(k7v(H0kc{A?E_O|+yAp(C3f!|k0IM|f z=EI(6(G{+!orMO$xOMQ+nS@BO5b;7Ee>*flZKNUP#WUx}yWqd>uRIr?-;q*Mk}L$h zw6a@vc7n1reJe<3TekuD`x(vpEai?e&AER)S;SaZToi62Yw!0W)`-D7eJh*%yxm4% z=^m4L8FeiV;hu$iYFis!FlJOPInUre%;w%=aHVm>?Hxvj$9WCGxz8i}lBCQRhR8`? z*}heCqtM4ew7j{OVTceZNz*$lK+QU=5Yd=hv1bY9XH2?ul!%fQBW%^^JD$cQ=%ixk zYsqe^R9IvlNUQP)L$=ymrp&EXfl+mV)Y())am zZ?VSz+1>7T?GV$FP0)t+OHLSgvZG#?`j6iu68EqRCjQVV^aB_aGSe#K#tQssEdBaY zC0(|b!P6UZmIhlHUmoP*(#)sVZ%&_v>s7}cBVUz7trtYcNx}Y2y$4RA8K%FgFuzO$8%uo_o+au~3ig zvZ*kcyHA>ehR3*#1@`-%_`2QqKDHwb^3!k$O3%s*Hnf1|C&AVa0O{Td{aZ=R6`aBj z6Lr%VZPCJ{C%f5}VoK!=D4Ee5UV6-E7(0OXJ5qGUy1XmP>v~OnStH6_iE3vmRg}b(0qeqYFvqb;4wMoK3KQeg8$z{=--hUSJYicg zbsRc}a-eT1!C=d^C|OO&WmD{kQ9JR+^B5>PL)!?z4qpVwOPNCs%llq&afz@&shkI< zaT?_(6puYhb!ls1s|OUQtPiX8n!OlfEU^#~BwwIHE|r&E*yC4Lp-R^kz88T@lanOD zT0u$E04&Ehg@5yarmiBDz8!A0<+fG5FO!{5Y zzTccdkW){wS_e2Vz*UQ;;UY3RHB@Y`TPk+f)Mp=C)1F}zy&TB~-__wNG^&+da744? zN;M5nl)*eia|qjDZWhy(l%K|w3C({N$ChCEOi&8;X!YJ0nF@S5^8WWt)(5%pEsUK2 z7f@n9^kM&TiT&FJk_Di=e!PDvv436AoF{(B!wBK19Xr;6CjiQmE*-5^(?vY%I0m&} zG22OFI~io@X^j*TtgCkrdgEyYM&mR5zw=xsYWg^x$!Z~-eCU-RrYW^uXcN|H2M z;o53f>D1C-CGXlS@|C>_!YF1LmeVmRpSISP27_d-fjKj`+ZF7AMgIep#Aoq1;xl(7 zsjsfQK$c6ExdPh+sQXM%lP?gX5xLw739urY5-%{TF~A^QSWm-G<1VF+PhHu$r58Gw zJwhC4voF0?V&qRC>=TtX30ipt%SC`%`_rl%wTpT4FyD}r zQfo&-1Nq@P?naqsXP|>oa`rH82ssIz7amk2jom7r{7O~h%m-eyjBp)bzJI>sm-VY|E>&>C?| zu7(gi>c1whv_6(=Zio=bim?3-Fz68+FB)3zfnmp;L+t}fbyC2;Q}77Jm5(io(hyvP zIwiff>BbO#jxyi;5}27X1*1ss9@Qftw1k25LRDXt{&`emkRzheiendZ!WFJF>kUsk z_ZoukOixic`+74xO`Ng)sD~xXQxiBmMLhQNdZmT!A*La|B*a5JJC@_LqM~g1Ks5x- z#PQGjIR2j2Y zLT~IDbNuuiC?!0}P350)vl0ceZI6XE|gba~4FSCmfkjzRM{oPVsdm z;i;%CDQq%euud#38U%;tz20f<>v>e}TvZ1UL3}axkr+?$Unc{f1dk+rQ?`VR_6Uqp z;uY&Cm7Gs)+gzA0pku3SO`In(ub@B0KXwJJk5a$e8~7d6kRoX_+5lI5c89zw;Atc< z6#w9aLzk5FJn+mb)8{t#=he++NAiCfQq8iz0?lI9iXok9tdKc!JLRlsT6}4Ax}spd zela!uoD&4>#bcbl=c)&z$vr}^HlZOp!IZ=p6Kq+;+{j^w<)m=~xu=n3PsZ$^FiNr5 zA6V5~-QUh~LlMk7X2dWlF1sX*jhrw_SKhT#HpRB>wHH!XHp$kk&`EkGdG+Edi4ug@0_XY5@m@P&uW^h1jnLR zC7j2cih5e8AwHCMa5*pZv!(lX8)TM6_Alq4FKq)QE1 zayA}$buKIK3-o?=>^@F6y}eO0eoLUQ6iaH9xK}Y?0-o`^CeR91uwJEPtst3}Hc@Y~ zYL%IxU}*=vs#^0FB0CaRQFU##-1i#-jiSD64UPFLDI=3s*skn4C_fT~Kh@S*sW;}3 zEy=94&deW}C)TG69P_%1YqG;EB)4iBLEWUfk^+=^5@Uy+dt?K{$#q9 zjjn<3VSp8R@a>PXNerOVMTFt+8u(gD!6Fw18J5tji})^wg4iEHy4k@k?NM|zYyhPe zNLj=3GdLk0Mtz@QL*>k~o-*2O-&D$Q*7Ow1hJg&}eUmv*tx9un88dumS7k!(O)yjb zn}9Meb$L9i-Y7y!XeZXp2{t#&^Nt2`h=lH!-G_k!g1{kZ{nL@5vOi`oe>kH)3vJ#* z0NTxmsNhcyum0s5|3QrWZ(`JR|0XGbNPysNZc}T_!TVf)@;gsV>l6eX*M4ak9HZ4% zay>@kTKpuAO~C5WU?+PD&(^vn)zkvpNFcpH8a+^(DZSrB0b3|-K-ILKaX_H{2bo-0 zS(IOMiyLOe-TwNa&quFu+Pr+|@KPi5Q6>i6vVsNjmVg5T^4I#+W#8MB)LyJB!-^wk zsJMJUHT=XitzL=Ppsmjvrk$r!Cq%E_LWWPHlHA#Hr~P% z2X-z6R5~3x7%(IhmX8@jo|$`Zx`IV_8?4Zh_=FJk1&9!cd=6-iz}Klmq?C_?MoXO^ zNz|S?Z4b5KUIRBq>^$Ko@UMuQRzfK?`r)Y*B{g}IIW$mm9g8vzMJM&1Tc9J>+pjNW6Q;*KR1p1G+_!mX z65kUGgCF2Pe}2QJWbE{FF{-^|b)}5RpXdc=VX7}SJF=Je-Wxim z#hIvwOrtPBVP*c+V!5E?Ml4C6u#wU@rz?b6c$?I^yY3t0e0;BH&6W=tWFU2i$O)=Recc_<1 zdp_Aa)$S;+rYoZRnvv-`E(-^dYMU%d?84(vu$T?Jat>xCM-BXqZLG$^a&+WjbcRsJ z$;iZXC=z8+?P@O4Zpm4rhpBoRBTo%>6~mK?+Eygm*iBDi6-?CcJw;mBX3eVjb@~8c z-nJ~mb))hJ2UP}yS1q+$z20a!(?M~F#-}Q><5jGAYYi72;Z3^fLFUrqe9Okw85zDg zq)vrCUWk@r;%hr^uB8}MWb16|ZpL8F97H=Iu#$@2`Q<0n2ih}?ZB8V6Qkpz1C*}s1 zTZIk?_x>WjMjeinlP}hS=reJmg2k_0$!9j;ms>iSc0Hjmo>fsCsjTTkRqG&Uo*^I# zpRS6utsl<4w9$Ih9ScjL@=W&R<%DD*C49bzy;&l#Ike^=6A9!j>1>U0S zh5KAn8*I7qS`+dSPD`m+_*|4T8T-GHHet|2JW3x~hM5KYh(Eni}nB>d^`CYD1s8gBXCZ zmA2BJrN<=cQ+#DyOHy1r7(d&&8rlg{g+D-C3?1Lkk20NMxS?{XBd z9ZX-rX%P}>%ZQ668U|-_gWd3J=mK$_s`0bxQm(UfgI?uHvAF|FqdMeD@L4pXV%{BF zPlis57Z0OtDjkvJR1QcsNJBWscP$Hx7RcRgKSdA9eQ1mtLPeY0cfs=_0gx_(@%V?P zxzSP9O9aWXlR>~nUo2keu605~2Pw*Rrts4g`M5(Miz2-|GZC7id=V>~r^buy%S7&4 zT!LF9TtM`v23-GAJ5@0wA6`456@d``PTk&nzGR(k-iQc6D_)Kl@M@1Ki`p^fXV~47-8L zpWfu9C?qWyAdDo}aC$~2?Xx0oAT?%JzYSwb)ARa+xWglz14RK!t&&snN2zVl7hK!N zU9eR=Zf`a;lV1jsVgqb7FR?+IgVM|idY_B&2rUzS2(^3fp3W*ghq+M2!asvewfx3v za1}d2_d6nUk9pc(LGg58rnM-n3&gKsR=aB;aVoglNl^6xHb@!PoQLq5_n>9|VGMsf zBy{JhGMT@z(*g49c&jUqu&L{TP~{r$Gd||Fm!Y=;JVYyPJl1ahx&Vhb^TKqw)33l^ z4|`vOwN8jG(a^x*T-u5?(2ET*NrwcR+~@!Dg^KJ+r*;O+6kPXu?Gs@iSHV#SPJh8x^m-RsOSwk=prW$;oMU87=v zm_1X8`*GaRsDQw6L!Q>YC`xOeu;YXe@%&xrD}pmQSet>GVf6ACF%l?r$uK{f=^@M* z>t2fKC8}PEEOUh9fn3#^6h~S?spso_w;gp+@0sf2EDt%gLuP#9t%Yl27hdl0>T7tF zw^vTp=ciYO;=rF^dn(oV;4y1e2p78iS;n^pu3{qfXjH47)byZ+RSheJ6}GdR5OYGA z?Wsf$@;u|r;^(MsxYQ(4H^|}}qoas9*@9Mt4{cOr;owqjI7qU=OXl{9;pri3ghd zI4oEvSKx&5Z8d6b;M;h%Q@BRS6WSumu3!2UVbC47G>MdJ;@t&9%sI^y?XQ>AT3xGgsMOiUBK87lR0!=NxJU zxbC+xUzClcH-9`%gHLd;(BHS$>fJV9#skD2>#<80=+G+)z8;+LO31DwT}7sjVUiv>7tZ zlhm}_&e7E3=%`zb0V08Hr--mZT4-8n9ch3_VA)oRX$RM$LDQaJCe^_xEaG)rLpW5} zIGuT-etVF_K_eFFeadFDOtH`I=flSH&&xxf3!lx0b0XauHE7B76$kR$D&g z>TwLthB~0Gmu`?JF-IX!gpw*2aA_n-%zboAfCbF=g3&$>h!^I;-0f%2m1wTl%VgI4 zL2gRbkhin)Z$2`b{VoV4pPjP=$JeIKCQElkdk$H}X4pJCC|vuCa__0WfSeKQ}!)-L333=JUyv#Gde^F9%s>`0@nb=VNqD_ERjV$soVf*vo`xmcYIV>ud9j!FP?L@p8P2qPsk~8T2tl^1#)H2o4qm-aV+aHEftx$A(fY9-K`}% zo9f%KmVK^Z&^3|iyx7=!rInH+pU(rnGoa=CL5x5?UsCK@->(xvudw6>=DHd%slaig z2m#&%91MAC6>T4BAY**ekn$Ax>AO-CJDP(0-VhD}L&?uXZQdjjv%I|u^wd;H8{{(Q zfm2>c$rH!YOjS4PqV9xab$oHxC}uPqv`24{U5r% zYK%3o%?jTaF@?!&A_GRH9!y5Hd{MEUzq%MGu2(O!3}7~It?*4ZI`Hiw4VWhnqE$TZ zd%xveVPSIv@v!hE4<0~ma3&6-|Awu>0?~Hf>iQ|JN`}3m#YgaM9c%Cg*YEqca@5}# zoM&=LAtrctC4hm$G&QR|f%t(6yiiXJUn+#wcj*wEeM`)Y@Wrm{e2^_K=|)A#hg0gJ zfCL=V&sjN`@tY`F*Y>APF!=g869gL%jZSTb>zT{V^mB}mUtfO*!n%!j{+2%U@abuI zdu&NJu_IEg40+hF<DPD)VY0L)%+8j*tuvpD{h;SDsatZc0qV)3 zekW95i86n?Y@fU*QV>pL0=e}{gg{uKJw<*0kY=5HKO}CkIv+fb+>dXn>jPb)Xeq7C zY0@{}PEoVf zUpi+F?AbL7ODq07N!3>kjxN5AB@CBgTiU`p*vyG&A$&ut<{yKnJI7|{D z{S?RwC-{K@))wRp(m2jBjoug!H_8-^lifacEDr$FA%M8}rxS+}e>xsft^k^g66zc*Zjflz!TEVB~LE834!5vH`Zn0x*n+l;OS=HTA`!W&b$353f z3f4#Jt9tEOCUmU2BFFE@*0aFbL3$Nk#<;ZH_h5YV{oVn%(D|*FPhXDs!IU6@2P1(5 zIEoqD5(gH5m(32Q5m}mq6&1Dj9x2M!8vYsCQrsiN~DRjM{eo5;({}SKbW`2h@bmQ+>6-H-300)wfBZRbOX6+uHkocN4ev} z>bsHlzKkqCCe}$)mn21+-*dWK?5~h=BUiWI`>7aaj)XD{9Spzn82Z{G{4Rz^a(L>1 zjI@5s3(5A!pb7e%i)6igu)K16!v%EFL@YFCqN{_FR7JSC^;id=?XMX5=6DDs#l0n~ zjG>~zw+0o1jhbD@7KvDZ9fPS>xttcqIi6VF7Xe>_f!>4pOHOP+`u?_0ze}I;xrZ)* zwQqX!p|dP&2ev79Eb6Qj%&Zy2#$VDYn0P!mGE7o5H4hz|`nu=d<;O$R*FR|KRVRf%h>J(gwre^&wcor(`7;8HA$I1 zTxCMKwD+?saGXYmphut$iv~LiO<8R|1Mi&ucnGV~1JfSSDRe?XPFfe#V}opOx91Q~ zrVa-5LY72jx`S;rXT>|mNfoEnU_A0B!CFkdQi4j^AiU<)hHLjFiYxWihL!<4ZG8;n zoA}L7mJK5$nNsM=rT)ZvwFjLTCbylZ692c*u$Fj}=)SwKV&Br#vK(}c8=SQE%Yp+9 zDWCTAer`fxkt3V%P`T6kIkuzfD6k3zB~^K%?5uI7rmddlH`_*Iu8A@6)V6WxX!wfc zX%!r>ZkftWN{6<-Se|EPl_qU{&1G*uC}eH z<+l`*7N*I-$v5}GvuSb*F+IIf@Ma@vo$(6@5T`vetxywe=k?*;^Sv|U%;v+&G9BWa zl@`Oar;iZ@2WQ4OxHZZTj(ecka2pe`FcO5E;_(rB&;x$8i8ZusN$f*$2xdbWp=`C^ zDgAdNh#naN^^c2ON&{S41-qH!HBGb7>)^PogompG2fe(upqvqJ{hvNN-tK+sF_7rH zQ_mgaQ_Bp=saTzn)7G#I#Ql7wq%dX2!uRt^j&*qBrv2@_f9}qAzmhz8BdudM?d5p9 zbFrofq4UAFfv!=HxvlvGrR90J@(c6=zuYTT1Z@I0X*QN)``0%ICUrD8-d5>KN?$c# zy5z6SUeM?EKidiB^t{(%z*T~N$|?>-pQ#2Bi7%?O>7K7m;pZfi|8BV9%^iMtjLxZ+ zOZLv2H)z)p(J7~R)gNp2W6HI1LVd8x_aaNMaxrtgHyQ?d>g;_e!&PW%mwMS+-aN{* zR+U>`S8qxfV&!){2o7qMvZ9hTZUCi|M{?hO{6mfY0100$R;fP#f+IkP{GWh?e~=-6 z`PT~V5;Jbu%YYbk=^IWMLWCtOG_UOd?-Q`$NhwNkJ%Y9_AsXky=3D2At<1+I%m3sJBmnNIUwi-~ zt+qszdjd!9f#j{7>Ru=1-p(y?zN;;7xB#h2zZii=yMK3IF}`13XnG$-@KbYl8M@9; z^FhUXghyQ@E?X2>fD^k06H$vICunfH=3T*yavv6rQ#gA`@HJvU{{Lg{ouVuM)^y>O zRK=;-W~E}=s-%*NZQHhO+qUhBZM$OIKC5>3>HXikcYl5M-8V+&7`a(Dzl&$S?|kG9 z@YXX0=m%?QQ70C|!@*FNkr4ymwvfu(bD6PviDDGRv_3rtsNiY^DuvB5N%<(rnKUF| z?Rnw0y_GC?YW)NT$bd+*@4+*CqPiJDxpm~Lih3Gq=uXVEAa(`8oZ^?lxi2F$q6$5i zrbF0ur4@hNjy@?E?q;*+)B#`~-m#;T;RN^cGr|(+$<(*oIJoQ_uY50IW^Q_pZ*QD- z8Xp6zK7UC^QHzze!+{gu&Lk*$MRCi>PupYShKn52Im#1}222v<;^wfea3s#D7hJ9Z zT*uN09!l%fIGhXow!SuU^L=9IPeH=`l_=b$o+YNVPUud&p_-l1w zQh9)EbpRL~#79*!j0$1X6pT8znnvX37+EAl zukLugGQ{bkt6;>-#pCpda%_n!k>}DrSKI=D|@@uCH3B#pGYr-^gAM{34#MafWacsFmRjt4-hua`o*c&o+6`Y{^ z*f6bOATvp-{e)rpgk6b+daALjj%OEM5u0D$){Hl~$zePE^EL;Q(WMBOR z_ggzS?`zYQ9JN^r4o?!pFBu6hm2b+3ezjs>hE;G|jMqU35AMch{1DkC&|ld@b)Y7; z;hLFxF~sgK0CjfAz8&qNoKXjxtp6)H-2nvJ1R@kV;(vof_>1Y-5O^{DIsd#q{4?kP2%;ajJg5Jp&ig##+LQPrsr^6^o z*r=+QsbH|)7@OYTIE11I!EJa}C&>sRPWA`(3-$xx`jGjM?p8UU*jY&mV50%$qb~;0 z1^mJSQnfpaiS6~`-(1Y?r|$eoy?;`T(x0P&^hVwS0o+?Ao==2z7(O5t72FlJ zsS=+ScU^f!I5l6K_(|H10%7|FY$-9gog2i1d+Oi-zV#{T?08nv7C+mUW+}`2lVNZK z`?3ZWxM1@+vZxp6wkjTuC|?u|c#Kag&h1z2Ebu@7m7$_3P100mYG_h7ly}$B4vm(1 zB#pCqqi%lufHENevad}Q<|e581a@vGg9l>f+D4D5_f!BO4WK2=#m%O-02?(uw{^w? zbQn?vx23Po5L0BKE1jN_Q}PXin>?@L3IdX(8NcW|_Wy}!vQEGXyk~L%~=OG= zF|?4_DT|<)HRZZ~eFM2b&6a|Iz=LlA>x9nsl^{tC>0AkNNdyp%|BCQ@1@<4fk zf#nS6h3V!~OLoq=Q{01CXl`JuhAb77d`X&oAGhHK^{?^um{7-A=X?tq+0F9N5M`8J z(xjmu>(tTW>FaV{-M#9U;R@<2TuAgpd-9HYOu9Iumg#jCKUQI-$_K<*JSZp~`z@1) zu_Z*Tm?*!(9cup?chh*4WQRR`%3!*{+v|v;^mRF0yjr2f{?g0Rd$o@JniMxy0n3SO z2yc?2CcG~lm?2in*paAsOepd$6!*|t0v0KYb7xZxPfqg4CnZpgX-Ha_JkNwhpBAzW%YrG@+2$$@TI)tY(0t`c#RUY6S5yX#sOG;4W`}T*e^{~EJc_LARtYaj~%~M{VR`b9_aHDQew6F+z z2gyc*-W_LZ;l1OU#A(ntt)-3oHvGVTt;rtaFt$GWgVASQ*u|AlLxj*{n_YG#W7M5bH1J5 z0hbp}wZ(0Q1DK9gq{s3XY5fW<%FTPK^?}j&iP~__xZde4cFz^Ka;t=)>Q?;=KR{gDl7d`~ow(hJsL?egz`vCsb54#wA@ zHUAw7;U7%K|H32ij}(GW4z}(V#F8>XsK7~laI|R1Y{B-X323f!&2F2MQ2`zbH~Uz3 zq_$XjxK+;FZjS^ftP`$VFiKFJV@m8=zB#wxXFa5=j}8Ka9V~~j0qJ=BB1gw-scUy& z0kEM-wdAz(8ILy6yWuy^#-*H9rNMMIp<}hz&Sv>-iqY7mQs^twjlWX}e1!KymE$`DsLfWW}9ou2x_Xf)-Yi{v*jI{d)SZg{1$kv4{B zZCv|V#}q-IJw8Jk)=ixJn0L~h%32jB7>_q&;g%Y)0N+r`b> z+QW;-MP|g0&8ZQ3;$BpW`c zCnfF1eFmN6B3Qg8_7*fS>4V^{hXpW2=qiyUn!gPXUYM8oj<^>7m0h@k7;P|52Ew2i z;!|$BrZi<)oWAi-^0GVzENtelk2IbyFkv29{-&*H;M(i*1buL}r)hFii%=e(_rY!v z)V#Bjw;&9~K^vcOrua6L5jJzQ>G~dcA}`4ZHYwu-p$=`j2^gkM#A#^QlD!4dFoXtt zolVY;f%2e)23blh&pUP(gNlpL0C?^B2U7A%qJk}UF2%kMLd_@k`xa67K{MA3u9U$M z5%@fSCZ7=J&#QWc^5PcCEf>J8sx$w)f>o2FZi3%-XvT9lILVNh9P!I{z^1^L_~cFA zyJmBb2){7#ruGbE`XbYW>F#i2w3W4T%ILtd~SQ&(LlLz-|u2eqT_I0g{gI= zRb)qH1&fB|$1sq+_8X-<5s(vmcewP6 zt&Mj8oYcB_mLbC;#W1|~K4f+wWcWTrijfyF4C^{Gu32qB9P7G@p>r(8fXru*8*O2n zKaNqhVU-KhL?zhVcxsOh706h_n2}wegcx+ZO$nV(LCuxXoZ*BeN83`gQDf0(3|Xpa zI~HK>=%pPY>4_SERVsHA(V9P(PI*h=E_8dR-L)>gAz{!}zmP9*Pq^YMfZa@0=`~!; zT^wpVx?5|Peb~l!CdiBjD2O!NRv>vW<)!{8-ES?I*!{$P#VEYy5F6%-^s!PD^huPk z8=M0fM=u>cRgdMyxi472^m5W)Appq(m)%glNxW*z=&*pqqfJ~lVHsO^q;=n{cXQNE zXP$Ynj)QE^JtOW~;5)OHY=rDJrQhQZE!x{NA5UJ`<7`@xJ2AFkUy*axKsPOF5{3S1 zQ@FT>#N7%FASJV4rm$2Ws@UtnM}roUW|GT$S3codEBL#%3ZZ!D;kIu*7XwiYD;{S0 zqEs^BYIg6K5$#o^^tm4F0&@O!*>{93gE^lF`yin3hx~3e<{tCpDHpzpjp*bYiXzkj zrE>!PeqG^@`swAG?Z8T{fWjJ4arGqz3+742?=-bGKby^boLole+4DD?5|l4(1$lq8LG!PTu$SkC%fcd7FPY1DSM-0h zL6~Pg=0UlQH5N>SVJr_Fo03;0fO156&!?!qm9pOff7J&4nd`wxA^HBDx&AL!;Qy)A z?C*1ZeUh7%PmAw^BlYhEd<@!V>Iz_3jCQnr%RNYXQ`B)(G-l*wUkD@Vcf#ol75F96S>Qr=*VfpXLr?$Ki<}N*YTY*M&RZNs zo>L zSV)fVZo7)#U_}9J-4V)S#TAbI$Ro;Q!fDw2RZNp1Wg*}$ zfrup`;2e1kv%T9^$W7>b3-RrC=8*O*rn`W-blAWr9+1@7Y1Y9lK2{vaONjQ@Fvodv z))sVWLikhh9#6`?f%H?jFM>Mi577DqP&U-?_hdPfp9F{aG~k}&s+EAXYkceT&|zgp z=)ln)Sc1H;y?n5{H{Us`i1RD-;v?U`HXhB6F0ubjr~DP?!S!2~H}jiDa(K<_%-c6_ zbcE^q+2lrF17<6BE_`oKO0+(W36m4Fgvl^6&;5MdY<)kbxAA*IZ}H|7aEA7%RK#4# zJtU-rs?Ll!j!304Vb@b+p@VHIQ{3=5%J)9;OP+DFyTLEpXsR;;Qt+N56H81=a$|ej zqjD_cVE%|-t!8mfr%~*G()8oZ#PzRG7iUU#4ZeV}We2@Q1-653hDndV+`3!)Zz3KD z+AeKcWQ?VL#r@vHo!Sr~*(Sm};VwmET;is&yB=FxTws|HFAl13Oq2kXmGA&PwT4<@ zTo*1ZVK@D3=posci$UWmWO*#dEy`MzObMo2Y;!`L{H9bK z{NHpFVpKM51|+6Jgv=0yM5pdCEulD!r)S&Zb(n_q{cGnjtB^)v^6T2o438QLG(DPE zT%&fS&$H(-hk)KEYkh0Vsb)yi503kxI6?6PO4=t;9PGzRyhJSKQSZ51Rl*%TEFi~Qumkxuk?SL4l4MLxRi^GO$Go;f%d;+tO@92gtYfcng!#4!b}@=Y zc7fc{m&F25%E7MK)(hQS~gsvSM;&qKhLUSt>SU~IF_B$Zzipy z(?9H+%7vV7ZUkDm@1iE`3+YE^a_Om-aV)=H53;DOMi0;x1+wcxQVL2ldNBzO)mGzQ zILP=UEl$2{c<^pY@m>saV`n96D*)U>L9%a8_<(~w%DeUEic~qKNk@1oLuNNl<1`T2wkdH>~xqjk-BiUo~Gqg~SRPc1amKov9`_{UdGtlYS8f7h(JJ&i2{qCM_8n;(wvgS;F1RB+^3s*d2Hqs`1dMX;(|NUNis=Wk1^t1a4c0h3`~e(&^prv=)4Dd7tOo zs?f9d*ZGF0-sxrLOOf2zW@P7}@&ailysTE)RJ~&YXCIZRJ z#)?s#@#c5v7!2&(F728vR*Xpm^Kj@HNHWu_B;rNRdOUBh9&1!JK zi721?7b9x8){s%0!-wLrZ_FEGilqcP=ap`)xtz4Xd^vz4=^`z3*p-90Vk=6Yi-ETt zInZG^Ac!wGw?woE0yff%nPTDQy)FPvxdcb(haqfn_xwuzlqD^6S91c_F<}tA*nu8d zdz2f=h(8fSOu7w+^21@k_FrOGL`~&VSs_RYzW`cs=g(U6KCZAYY?}gTT9)$A9|rs4 zG^Z<$sx~@W3@=s%5bWdhooY8?U+iXso`-}6Km9t6F$qh3sBOH##_i=fBi{^LW~TSJ z-Y%OE^c^L)G;!Bykl<5X_0Pj~HfkDLkeGix_R8)^n%n43hQhZaF7XI138bgKg&JkX z_N^$t#~TRmKk}F3-jd&RKqG6XJW+0_Ag2@m<={Dj7*$uhiQ9*-qRYWQW{avVGRnv& zX%tfO+2%9Sx9z6S^ce{npGVBnw@=EqLnSc}P?VYlB=#PxEx_bNb+N=2zCKo9=9t4u zG~R=*?a7n0rD_Nb3^`!*B- zKIxPWXDqQT+O-T^AwdP3*ZcHaqsn=~Y@B@=79)g=@ExRo@U)&$D2S^rwZ5cb|QK_tdG>+Uur&2_#79eDYVjyI3fiAJqT)w4w!?CS1- zpKPWnA4mHAl}*Rrxvf547aOl>CEcAd5`4ZYLs)pD&gdiP4W6V5p3E!f7zR-=wVapB zO-^5iDfYZB<4Ch8m07N?VmTJ7=@-olr-9@8psBCr(NvUQgq48KpSfXwW5V@T@O@3V ztPJ;nL~Hn~_ViESPnE*+@z?*9{`?z|`~Tf6@PB#IGwO~4>Lzq^<(SnrwBu9wF&a7v zvsLF+n6$4$q3;-$!&DO`Hl{0oKzDUxy8=_3V*y`cKQ^%?f^;H>F$UkVu~Fv>;TYzA zFnxJ&wxQ=A&~1*g13H#=Z@Dj8fbaJ=>2@2PG&IZx@}DkSJ_8hn0QmrK=*M2ahAcL_ zS_#|Q?iE_7G9_RUtnso4r*o~!@v%}%kG|hR?v#Zr3sVXUMc%;5DVnB+!EM@QdanDR zwr(^oIiFbd4+w9h$Wk5xyVzP;s9Lgjzq7q~GG#uvLN&p6m_c|D@Ly29ac|hBCqu&y1p&_oA&I$`^^5b1Gl0XoHC@N@>3HpWzJE_X47~msw!N9lF-90P zbFh;Sm0A`P0eqRLB}-&%^3*eG09`oUlNFR$ZS58TrMgdGi4dtfbCoEq=^HSSlQ#@< zI^M*#Q9Sf%J0zX+3>5mXV2HNq4s`C318HcQbH>I&!9~2j>NbJ(yZ#zqfTZqsdTu&e zPk&;O;r5wz&4$A~r7E0i(UTwLnPY+X$08ZG5hTp)Z!-pD+;A4rBkV_dxb_>O5hNu$ zhPtY&&@an#tGT?P_$)gbUU#l}x@7en(?)1++uQfS7}CEr&Q7fdSjJT5Eyx%r;+7lZ zE{eLy48Np8SZ-_bGh0lp(G=qeGlQ|_lwLZ89deK58bGS8o@f4EfY*!cwinGVjJ0Qh zR7g;Wg^}3?Dch>odMVD*-W>28Rk8D>4qV1-qiPAitC_QbsT*XdGGrIQsGA2VzE8}# zD|C6q`N&;C$`UxG4_igvmeIUD0jGM4SXfd#X_z`kxB49z)0&x2A#npf9xlS1L4>x} z_bT0qeW6eA2`@N|RLqP@uZt*|?6Vn;*oeQPT-^6JXI1!5R-ccYX6KY4xUur1;#3qz zuLh>j&DMzd-)er(&N@sDqV|DJYIYwWE;jHcw2JV_K0rcr0Abe{c2e03etkhp>ZD5S zu!Mj+bzw86ScJs27&-9dn5ZrM`2@+8;YR`23VGChY7tex5({QSW#lCn$i)+gATZbI z!y4IZKV%t&ezF|2>cSn8sm?|Bt1yl?AhtP$$nfU6%KI28@0F&C%SxIQbI+wvNa^EK zyIS``&~o7HJxUV~nY>hP?}}8n(nQ}iWrR3D7~8(@^9x4Pd#<(_Ik%kWc;a?>FXm{p zG zRDgVy9w~z~CA^zbcq3Rx!ZF2qTDko2?U8-Tcp}q94FS%Ing4pSM%x*KBKlK+iRn)k z>`~qd1`B$PpDiOVck*Vd1LY+Yb9|cIn+vDr0&92K%9I;1i)$d_D}RYs_%rE4@H<4e z0rfqQKz+~u7O(JMv+rMg01E$|MU{x`hVG$55W08^1);S#;^*i3rWud-*#u1Za}2_& z1oc2ZNeTMZrbJn>o61rOE2rPU3;pC!Mb@|>k zl$gRuP8vzp`nbpxpY;;vjA&$z7goO`_bs5f(Wuo9OIeuhA(#(G@DLKCn9_v*K^F!hcI0ZtQ(viK!>`bwmprJo2mHRrGA1usRQ+?{~{dpU+e{caRaLZKg^%=&lEFoEsztz>3YwuI-|Vk z&}~xiI8&8b)W^UN&QDlq@JJYzO=4*Df2$X!cYyjFDi8*wn78K3)iz*(S|0H*{jI3} zIqDRB8#Qq#6G)o`Oc6BQm2a@hjrj35 z&m$#GzM~96s31iqOq4f9~q-p}<21c2TX0=npTtypY zQ@i0Hv+r6!6VdHLIl5nfIdDm8LFQ6ojl65r?(jU9KL~7o6+oVb8{z@K>94WG4fIXl zWeK19U|L2VY+X~vhy8tEM{ap4gmY4(>p?g4Bax+&#zI|V{aZt+V42zO zd_+r`qP{lw13P&qNr51aKdFrt0(q5ATiWS%OyOj}5Tv-5D-xD7IN=#dfbog4>pFy4o3r@8@B480#0_iX?!pH58X(*+!0&Q~G+b4HeKAXt` zn@5@=!kHuL3%ZEW9CkI(ZHj`??RW8o-2=$NXh4hHJ>hVJKp0zk3?QiVww~3U#S`e& zre00*4v=q|o3caNGsqM%2Crg{b`G>@+ZwIDnFl@(kDZGyxzp5f4xUTZ6b?GxFfSyJ zL9S1;n?0@FPwtmqUd4e^O$|S-t?7`X(b)!(SK1}ta8sO&>Uw@E^2)QdVr+ZJAZ~kI zM82)4H~gBrdh)B;+hLAj&i-bn|0Wvk&hk!xC=?A;*) z>*OkMv3wz+d;z!56|+*wqU!Cio8}|J-;lp*7@cVp%9Su*qU8wZ7HZb-$nzr14oZS2 zKLzm{7WCei%y!b#|1-QM*C+ZXbxq9 z=`EnL=kY1`)fe?6F*d7ddz^o->dxAVjA20E`J{Y^3*3oE-=}|~_JtB)q{X3U z4{4&V(0qUk{DRN$TUY;0-Vhf`WmL#9nR%khLSIl5T*&=_^oU&KGPyW~TG)vv9>Z>K z!l5^#;K$=tzUua`gDP{h4oVL~B7xS`t|87f+0v!mz@NU=)S zV-2Y3W57)9yPJ@L^73afOWt07A$G5sb!pVHdvzM4kl-6VZO!#+NuIIY7V5qCHjMa!nDS5^Gkz(S7PL8Q!FIvL8RC{+s$WJ9&A`S_LvH=Tom zJumi5vXw}LzEVX&W}OW~Nyv0{(=u0@oKO0T*ktz$(i?+w;oD!L=X!y#>#muR%m9R4 z_kRm^|8q641VZkg^UtuW@E?&sZy-u5u1=@}&};K(r6>3pQLQlxjfIPput?jgZ+gwt zc@DEFq`=6Z`akYq&5SVx1E}FY%AUtwO#9Iud`lA(zc0jrIrQd)g$g>&Z00B-USll} z$KbX9QAh02nf2ni>Gm)&Kx$>O3xI_JMBkPAAONZnd6bLKnbJ_35@TI=F!_Z#TZCi_ zkh0d$Nz(iq85z|4=aeu=MifgnDlK9Lm>g2p`CSqQiu!Aj`a5GDgB@}Kr2J(_0CIDK zH@>mhZ3d7Y4h8Aq4WKSg+oDWCGCN{?AV@cMY)&cP}2>*DG6){+uyF<+^%m z^;&2l^)dS#zkKTZ288CfC2PV$RQq+HPNLzCCp}ako=qEyC<9g|U!|erwIDw~5z~*M zz_Uhbub(M5Wql0wb{ShWANIk67ycXk zZWE$!MG#74eTqRu({e=tzXTOnkwKbXs4m_o4?F<-1HUp!HFamc+b%Z3v|805Q1!99 zi*7Ffif&h=_*@V9FC%3r7B%m+)KyZ!Eq2%mpt#pizwEA%&Dq6H5j}s$+-S~I&L6<` zfXmMD8M^Z3lc~(B`=*X}aZQv~^25rgC_0Q)jF=RMe0ER|I-qpyb|rs8y9m=+=O{n< zkwrG(Bp`pS3G@f=a^|{6eLgX5iY$=OOP4vv5vvo#JeYc)b9!t~Rkr>808`tZ`q)9B z7KsQ3K|}1}iFXzR$H>t`Dgneb6ApC^tD*fPUS(he+PXDVdS3@l=h#xmyi&)U!iDs3 z1nwst#yNZmt1$m@!6S>=wFwfV*HOdHZp`nq0!p`ys9hD@4sDt&w(>z>T379fJBh^?oTZ0aAR;9Xgi0sie+UxV=-e~7@;-hdqmmz^?@b6X{xK~Yqu{a%SI z_>#AkN*?2aQRzMe8ke!{s1B93GD1UPxB#gX$~KBwXL3Ww_36k*z2QY9#)ZKA7(Hb` zc@)JcJirWGh_fhW)Go56!d$+lsv2!lFEF`jJ7_C7p;_ryk|>jNkvFdp;`R+m=P5z< zTkvwag{KiUKe!iN1iJ3Gn4lI}woaU0{9Oc#`^}pw?=#0A(IdMhpHM-?;~9l!-Wmze zE_=D}M$iFQWGL|4t9vZ-&Y_)&*>H5E!dN5gv3pc+L@;xgJzSnF_lYOCRf?rqj-KjqDwXUiaGvk#n&4|wA_3I;+UD+pzz(a7RJlHP~3N$MzJl#7riaWnL8m_7WzkHUY}gmMC9|5o6d01jLe z{x|pRf2;}r;1*W&> zdvvlB>g`!V$@?@W{;$h#hRMzog~@&>U1HZ5ZE-RrGA9f{#3#wpJQ$SuowgzBN)Z;m zQ>mvz2Er^@eWmhnIcPnxFI^7^J?$ZC3Ifp~uCz%8Ie7W%EA)`9&!clN3@fA-Q%h_S zfKjSh=GgsY6Di#bt76}qOr^0M`>wM@r)ym+jNUW_`4c?|HRe%gqGOSoKy%}Td-A2T z>%eJp_Mjv{{I#+lTZGDNJ zEe8Ij3di&cdO8&jVHI?x6&Rbizr^b^sf`B;jj?g@n5A~JNsQ$|qyZH;$b?h@>CVtu z=*Sb5>Aywgndf+?JYh+qK_!g=OP?()S}OSJx**sUc#wRpIZ?tWSeIUiuBU=CT+2YM z2_kHMD*M$FOMW%~?u&8qP5-%Gw99@SeU$^N9I5FoK!yC<{yHgU^3#KN#tKmeTHt8tJUv&oQjvaF| zrhHZp1kw+ub?SS=9R-Y38>`7ZKTuV?RtlPviRq)$%(U6qGJR~VnlV%`sKyJ1( zy|ddxgEI0tDU4llKvjOdibQpP&g2*61m^oPkCnAtAGLrS)5G}oB-Yf9=f3`C>ouBG z1AupYp0BGCIV6WPexX4Py*}qz(n^`ytmSVP(uw*GU8y$0i z_KD{t`qrButp$%6N^gr!34ZIQl2olhlkRQADGYhzDMcR*M{gpo6?NMD3^IMIk_eA< zC)8qp-zu>3)78Ova0gE*-YTegd!1v0cc{t#NfP$Vm}PMG&St`!^~<_p(0*zl90@Jr z4VLXR|Jvwq9oBVJx;wkrK8}C-^`mnRGsnhnNHM3B@4k1l-Q)AmKNa7|#5aSd86{;`9>Nw}Bgj9HIM0ekblzxB;1IX1ZmZB}~)vK4h8GB|A}F+6DP4hVp=(xH<}jz*4NuOOOhpQI&&!`&mnBnu{nO$kF1ud79csOgJ#vg;#~!?dcdK(uwSkFC~%&+B_r(Up3D z$PxK$zCa|nmX^S+JLJM>)5p)n0z>#=gU65%5@>Bpot08=!>1eEiyUGigaN)q7h5?A ziHQZy_Qqu7`!4UwCwKhrS;6;a02g}dAE57BP<;tZ6Wr70&Sxk6n5+g}IaBt=o1B42 zAd*X-4Vpm|2i(1AYpp$k5`5$a?*VFXo8k*%kIU$v35dsMfxlM4oIr_5&JM(W*Ag`@ zQ#Q!)y&fT7x8jw71OyNSO>g*<2!get=gSffhqRvi%YwjYpZPkR5H$S<|v5E zD%@-8n{=FoyH|JqvSWu%p1e&Q^=3k>5@iEvNqOy{=_Vl4Rymdh zMu)ynK=|*+jX(rGcimtvu`GfW*jmvk{a7! zh>BTwJ~<1RXP$ z(f#3(8_+%@RH%M(gCaGO<#!v1t`_Z2-@YK$^%bi{fVN5dNEFTbJ} z8CQqf?weHBuOy3^c@_-=D_91oO$P8Mbj0J=wNiakUyV>1IRjfL#e)oOgk8~_?2Tm9%LO%ezyWFm2y2|VyN4)z~%M6+TxMJ_WDHy(aYX9>7|Y3Hem zrKz9ow_xsQBHn##HXNy9FC@Dt8rHLsAj(ZKEieO)x%bpQ+_qacD3x66f`l5;gkuj4 z{$K<43WiWCRK)2}Vx{L2kIbyIyHs2li(I1US`l$Dh}Zm-V#q#=d&jmXlQVwX*qY-& zc!q2rv2!rZZ_7|iP)$luJ>YZw)+v(FNmPcvKSr3sj-@5hzL7GzzscNNp7&#iO$i(X zWP%N@=zYAVuTff8TwXP<7E@pbt0;f^3FG&T-BJg}!jCOX5I2UTy6v7!>BnB!Mo|S} zY+N(%p9`%v%2h?6_s(#u+?P7qn121L`PCwJ?4u|=R{b0rON?dCyINy%r4$Po;Z;W| zKNjFef66oy)rE(S6VL?4?#CBTF^ypqVZwx0eGPIj*tl3kV$#$h7=}w04W;x0N^vm)|^qKu^=w0M@0vH z6Gj_I=+-U35EnJ{!O?u|{ynvLl&Q6%<|k7(;ndm2<&qW`9q^nnXjNY=&P(lt&;+N{ z1yj0NTCuk4@@{W6o6_@|`QYh-h^_H@z0Clqh}L7={T9Dk26fnfF~-xsA=KS~Wc~gN zoN}#d2+A2+>V@Q;E1?jXy5KupuFqwN1T$P)5Z*K6rD^wQRd>#QPMG%Y8>_RzpW0?ZvWRVu0K15?WaBT58#eb`2W0P{Dax}Uv!o^MDhRW zJPx>cLXCp1#RjD=be5j+oAD!v$PSj)UuLPJw{KIcO;Z>6XiF1PlS$u6d+21fvne)c zNgB#ZEPD~5+SE)eI|yAg8>sc8c#e*w{u9B0gf7%Eh)_|dWwBkCitxp+76aJ+hJoNo*^Ai znK;62LD#1LD)Y7td@2F;Z(zcgK-whE;3Pc9Iyy&Tj%PW)NhTv6c9B(>#c2bdxAKB*uy$(r_YN(0yoPRLBHeH=i4m;wH2a!HDK*j`7(%L4^S6 z)1cYjudNocDffrj&a;hIbpB~uY*pp;BDv0N=0&#(-e4vr5h2F?+`44Q^kIUsVR`QP zmZu6i+sPB@HhR_363FiWC*K2LZ$KwY`Q%{6wRtclO+7+}_o)$`73|5h?zbT^OF3mP zz@22~Wk21Vcw7g4`D(~rFTj&0X}eFduUeCF0p71%-(=@_W?+6kLbgn`zV*B2dUBiT zckl(fthjA)S=By%V1PDw^fi_v$FL=yi7Re!c=c@&S&okp!i=PBaAPDXv(&IA>#uf0 zl3*Upv;qm~)^8I-ORS0n0Wz^z?oJ5VXvH}shp$Y;*W=Kf_z7q39^c0z6-qzPf9r?8 z=#{e8H>q*U?#0FBc%Pr3*1PLb6_Xd2fOjv?Y%oUKzIER!AP?Jz?jy*kF_vs&a>3zIDL~i zeU&(^S8@?7OzpDBzec_dM*Sp$sI@hm>-USiDoSurCgRM_e*`XhKrmu?DiO=0F#CO0 zU~=%tOp+hQg;T1Wu5l-iad5I*)6rtndI<6k`DlGB`byo^DRDhZ|4UTGfLS?D3>pV9 zyPdG*i%|=f`?fyw{)4q9nUiwp)7_d*=uNowhKRu%=9tp>(MIvg>d3jr!4S>n9h(Pb zLFSiIsgpnMWP34gRHeyQDu-QFl`b_4rke`TUCM5da ziKgyy{0^0Tw7>e|U0W`D)I&8xXGdvDge}WZ%NplDXt)9$ohw>Nl}JvyyDX)3I?kt3 z=L2Ks1O1fod+$oh@9?>o_Sz7YXb+49gGO*|SezgyI{*wxW8zu} zkyneVOM9TJU}Q4wYQcMZ@q2SqoQVffy@RAaP7o(PQ@8HHl1GwYgyS-puw{mIi~mhI zVH`_jFK0B~gq6+PHwL&Mti0TTAHb+n=F6Ol-rP5p`0IGR`cb6N`|Z}OAlMe;udTns zQ`$91&Sj0S4P%<4aFD`KYPJbs4A#JPP9EWv3o^my#ozu5OV&T2m8+NAB8efC_q?YP<)l*w& zKxvXcQF}{l%L`?zRX2!e$v}^A6vmZSIxa`k;eM84?xF&1@6hy|KeuFO^N_dwPQIF9 z?H{G9URGP%=<@9={GwCmxs=qs@7(;D8Q7u;c_~kqoQQzp$p{bKhCvu0s7PWM2Z}_+9xj%k} zGHgb&T7P|glLYEloxk~%S5?KT3H#^`aa4j$6fkHcv4yvRwy};@pVL2)(wlBs7YD$C zvyBcr+aqjORDd55Aby>L031*r0FPF}-M^o|s-HhRLl#=X5PU0f?Ou=6w8BA_>J)ilPxX#BvCl-uA=e8EpE z6_d5NIlEjPO&aE6;l^p=k`!NP*rfrKogZ;XVt*v2%1H43G1m-uw+NmfCg7@wm^w!V zBHDmS!hBppL<=x+(@t4uPj4_BQ3MA}^wqBv8R$~4+w5e~f|L@TEoBhdNR`AsuxELW zdQH%U=Xtedi~> zmZbEA<(1!4^g$-*H4L_|v}a;T$qq(1=h$+Vqt95~fPkDZ>EcGYxr6@cL4JvFH}>Ad zJ!soi7D>}1F~i-WqIl3w#Kp0LKOc3Em^=!0t9V?`t<5I(q@_Ry%Uuek9OjD_dC}=> ztp7fWbtWitB46J+kxn_~RXz7Jwsjw|C4|$(J;vs#tm?6Z^1Zv(Ozk<3r8sNEGE~^Y zZ&^ZaZGp+iWxHNuXRM@r3AyX&mlc-eM!6guKD{m>KK|up+n(~!*u__uO#r^L`a(jl z?|01)n~FUqqbKu=f!}u|4xEBgLWg>;$BsT6i8&&1xBf}Yi0~M%YDitHVq^6F*ZO3B z4T1rm@lC}c(+y;Gqd3n#$-uyt(6C|U6v50<*^f=Z1fYLqoO6#=y&O?VDAO!0q5t^0 z5v1tM-sWP(bs^_DpWV#?CzK>;@hxCwD%^p=y=cJXeS2%*cLWJ{Sm$faNy^V36&Q1q<+0fJ>hfkuCPC*OdERup-&pLD!39X`DpYebPVOL zB*m%x;0EtXOX3&chd}OwcR?x1y*8Jz*~n=ZrI_G|=j=V!Dz~-}soj^if6MP<`K-jF z8#F9wt41SILA`e{KTGL9N}9e!)lzN&ndxKh)w%N0(YJu#a4%L)T<#HD2RVKB7F!`V zw1+vkAe$+BL0;K+6HK^|^GL|HO>mBKcaO5)!+MQ zm>|cQnp5?)7hjh*eg8%qfaZS_REs3Mchy16;hjU zbo=$WWO=d6q=%!#5g^_vel_R0oHl6W#kM|9hMU>d%2e@a7%b^Dr#qIu7@M}Wxr|BA zTM!j>*|65q6N=iRQP+ ztE%k&s*vL6AMb$(i5_dEsJ=gM?`>6-j=zr>5c~adb3QbhQs3+n`kUlwW)P)Y*WP}? zM6f360{p<k0PfE`t zZt$m#rBxb~$EmP8pJGr_+*UfZK$c+QyoUJ31J8gO=75C zYm!?@|1ZwzlhKNZz;h&yT^k_nuoW+Fsmw-`p=~jCQsc@5BIs z|A)A@461X@x^|J^?(XjH?ykWJ?he5ng1b8ecX#)Ny9Osgg9i`(Ep~Umy?dYjPQP7s zs?LwQYW)pWna`MWjxjHB5M`S_qF*sML$KtG(7zmUNXh{h52my4;FCu() z^uW45ezF>`xJKdHKoZ4H+{%kSh*8KC6%}{PP_7XUyUKokdr9@7#~S~ReUK2zzrsZ9 zlS@y6Ew~yJ+$PFOaS*rkg#BFIw=nN4VJ}kT`)5<&kxgDBCfM0SHX20_Qm{^jIxGmQ zRbYQm98+0|SFGXc;TqEgq|h&YL8v+uB%|0Xc1aInVLHDv+UKx!R?PuhcHv{jF?m%| zA_Z3>Daa{eu_O2+2ayBP!Jvig-_X2luJT&IEmml-9)K_5)bV!a7m!sOo%-W?0g;Xi zYdysA$Fyc?@rGrDj%go_z6+6`IN6A_?o(`YC{(O}yYqx)aa(q3^1?@7A}jN%wGe8y zTwkO4itgyynWCz-1x7o`8F{G;P_a3TC6PrY!1j+#uv3=4^RO2JuEqU~O{~`{2NfR|r8mdp>1@y59Zwc2Ol=(w)P|yu^?T=reJ-5s zd{bv}&P#E&C6(DMspx!S&Z!0MXSvfUD7#b$v+MnxInN|KH@FXC?At7pokW;7C3z!# zCkAwz>wq)glV6N8&D73p`5BisiYFOa+6OM8Y&c7kZB-bH0;$ijln#7l5~-wuCq_nC zs^P!34#NA?XJjWyvOKw!W9U;nDPJ<%=^F!3(K7c>of~1yX~yY0_cYAx+SR(NuiP(H zx(02Q7}`aT5O*qRIZo{ns1m z`yhVQBW`eV?X03OT$_PHbJ8H;T2o*nylSn!dQ-u>t0&B0K8okmAaM7FQm2-*qTMN5 z@X|Y&*viH#K6R0)+KIVkS(bXKE!Tm~I&P(*pNC z%!nydG)C**@(aIVxdhy5tU3K+HNI!qa1z(&J%Q8sPes79R3ST0r?G0A-X{6~xdFC!Q0gza$|^ zv)owo+wsj}>mfXGYc{iYCXFI+tXv9O6NL+_1_`U4pZbjEHt2fwn%4X~4AF-Oi-Ujs z4tlpd{r0juf5|0s4%#-z?x6%_Ob((CP?#5&E;1;ygXt|o#qikeW zi}orRpN1(@EXxQtF*P)?!6fM`7f*5J;dzH)l~HYhqn9rXTi|>66ig|^{CDW7Y4cyD zL2+2mypA1K{63h1;4cVy_m<0QSNQkp>T7Ty2RYKEqEBdc?h1I&AC%ZG1wi4Lq2Ya- zSl=V$Jdc-3`P5i3<8shwJ*#KNUoUC>%nn^FyxOj;#Z7IzEZ*dYd}2Ao`(?l=_g7c< zu@785QG5>JsUet+yWwcM+D3leG;_t11ZjGoG6P}@6>~4tNigJTgBEdM^HIH`W#74M zNP9}7GaWGcEX!~_cZ%xiRD4kY4pDddBt%nBT`UE(JY5Q7(=h$;Lps7rFwevJ!}0_T z`3qlkjRbZswZ80tF7yyet1l2}d2)5CPTcXl1TcMd2BT=2U&P|;0Hyt*14}(Cc>K7C zf!n(B@$m}JXNuvAiAaG<%vdFU&>>i1!ZH_Xa^S0kp*dnxO; zotjI8d=g&d#i_31u(+Ni!WYOXs`Vsi*vrAM@9TI@(R{wa@b@2UR_Ip2TU0XR1QfKq zPKL_(IcK)=JFV4R9;itkM{K(wbH$7}Ebjz`S=YrYL3;$}$kLl)x~YDtRf6VcJeoA_ z$L;^+)Vz=Gz|-yR`^zh_M_@8qDxD1S(e0}s>tr-}h7*$oDN!AO3*D(TBil^o*#j!7 zStKMF*;*mI%S_Z9*d_SBcL|)_s757MH}Ed_<_FhI^6(4JGG1Gidy6%^?JeWaSuRLA zKZ;Kex-PSk-Wv3ynlGXlLv#$_n|okR3_}pB7oHymZ~O6N%!m8-t|omFzefC=C-g!E zdY%Rc^`4gHDKb6<)Yi%X6l9Pdl1&|RRwW_Na640fH}p92DQQhz|l!q4j{;OEL0dSGr(GTiNa6Nj-83tye}qFE9|7cbG}mP&vBY6-~D<*G5sNnWd{2a_{Fu%XfQLTz|s)Jw%Y#MQEJocQIJN`SBJiPnib5$847YWgFKu`Yy3+ zymr)AfAc)m>5=@^^YqSAmouK7tdk_cPP%9 z@#fBti6WX4qirfp`8%;FotO%fs%t2Li~STCCbvB$$e>@naE?C~fN zd%PCP9?ZiYjUp2Fx=fv7>4iWdCq1a}f*cqPNFFvP zdEGUduB3h?U}7qbT;z-~#5zmmRfR2zC~=L+>QtoblV z6jB^@m1||6aGWU-8RbeSVFYgl>`}Y6E@9H0A%7!J6-TJg1tbd>gKvQ^VZxAo5~u;B zqfFcRw8XlPd%AA$kR5u*EqxdSF9&-6tvPL^%>1$-TF&gR5OCJOjC22xp3QNes7?r@q(?&&9Cu z{vd!Q1;`{ijU?0O+6jYv-q_oboCYK?LSBlQh_-h*xq0rMz8^VN%?6@-)_-;mhlBFp zZ<1q-$t93V0lM1aFj8`jI`OV0#T9bp$fMHVjJJ&Shw=0d?gc2jYc3dy0c!5G^d!A3B&aa@CS z9E)m(HXg<+;?feoV%I8X6_y{vOtX(=m@pTqT@V^)vTn%W=Iz?{{Z>rGc3_Q#h<@?N zoa50N_cJrF9afO1f-OY_7|%0fGEc?>cKBJuaLtndpOTJiO3%$(!Y;0US!ng}O+WF6 z6FKUKhV_5E3-Qg@7-uG9QKW+Iug-ElDcJ}C>ue64U(NbLNBwC=iv5we@_94lH9;cn zgGoXczN9&(waFirOV2VFsA+_v?Vm0oJCP6=PM-8~1=gp0flT)YZ{p1g-7R?&QEh=58 zoB_g*^N~Q^43Lr3r4XlBR$lP42XMWbADkI`OfYCurDxEpc_TRX%3wmLzeBka@aRykgJPf-0MF) zluUV^c%_*BwxUEeS@!Fyt31EWlzGDwdU5T#iMqbX_0#Q&RG38y1#KBkB7x!1UBKTe zOrlmSf$)`b7U^ZjK;AZ65u5^5a4x>9X{>&A?2zzO(X8`d!LSwi4XNj(ZRh_9ugX?P zCobv;Lowr1*KpqQZC@g>6%KwBqlRk4kZksd&?Zp1EZZH4oG_IzmgrsVvK?; z*jD5ZIXeUa{Z4*s`?4%)hT-Zct+C)i32Q`>8GFL%X*_srxhS@hC5$&p(=8vJcsuSR zADwb3TdJ92OYl+x1J9AExFoA!fGA9(>}(&87CWS(8|lAGzt#(NMuaSQ33qaKe7(7X z5)kI|vmSkIq@cj*qf?r&ShiLipgs_tc6r>;02bl*EHb-cnn(~$Q<|vQU*X39;60>2 z;K$f~aNB7`I~X*wd*NCrNS_O?ocVVK!JSmteqxM~YWxrU7}<)cuHc|H7z@NQ9s^>C zap8P}th@`$;B=k`OIego%%{~IIy}UNGC;IT%0%^J=`A3vvZY6W(K*h3UT(5rhS&$o zq|P;owfCmZfb2u``mq$lJSLbG$yGueJeuO}r_5{`yPhBHiX!ky5T%!mgeD1;BMW;l zY#Q^f{a!5BUy-8=U(A~>wn_Xy{R}C?0y8&ara6s+A)#1n4I`LX9p2DTxIfCicIkP# z30uvrr-1eUK6IY4L;?F&SmlR4GNCW8aPt`KM}Zqj!pX#R;h6oyj_cvk+?>@my>v_{ zXQ>%rjqlyJW50<6dZh_;dkb|`Lu{oA+s5goicUXj9czi7Mr>4iwvt7zWP-xGCLDK| zeC+_{Co1^!&>^P=UXy>(P<^;9OikdlF>ZC`{rr3XY-VoHHnWPOTKV@ECB1RON`2dX zQ74cyvpg_dS=i4h90`rvdsD5RHmIS=QMP0jmV;``AOwd4!}pDQrg2WBw)`S{+BsQ; zWZU*i(~qMWF1Ie3pC)lB2ST+YKhY;NCL1xzP2W??z1CC?iR8~P;qL~&CL`YzlJr4o zfkG-tVYZAQ&V_16I8iE?`*e8b+OKKm{IFiP%BiI4_|kvv(`R@e8QI&tA|zo;6I9Kt z+ouaf1m;s7&R|+s7%yz-&bp$iaw(u}V4)_2p`J$LnyI2^zW11F@SWwV#R$Ne+HA4G z2kSE!-Ny8UbMFTd02+tyRZ@<*B=MPc(F7Q)}ffB7)ffJImTo3;tZr}bv{`8W!J zF}eN;q&EwNXlagB!~C+-j638a){^$(6Wq3ERwCIo#Z|oGPIx=R+(uoL7}Sqj3h+#` zfNiQeDg5OUCmaV;gpXEN$Yiy%ze8mJDvo@iC{T;geZi0)IaYA}=UaM#P0?A(gL^Ii z=IMh?kKeX=$Tphqnal`OqOQZM-_lXL-yCWCuQp_?w;{rx7U<6TlQ3_xAb_sy_zB@8 z(&O5UpNLO39IlVAk^Y~9ORt|FRvum}-@}2VE zSQ*d415b~)GPsr`bRu-qI{C8C3f$nz_JVyQhjHp^{*0)3-xRD2iSoSzkXL~3Kjj|& zQGfrGj{Y~)u)mx_`X>Pyxik_;K<0iYAmja=fK2CFiau%*I~_pN*pMHhniQvbX5_oL zfrQMnIlYE8{uwO_4j!d?3h;IhE0Ruerd3r;E~Ig`iB5?ATMfl!s&`5?WFNay*rP0cj!6~GFF#q~SCKpgnV`A>=PKmN&o z3O(xqr%>e@ir=wttxGB2U}Uvu=^-HjPlnO5bT-PFNYHXkS@Hk?OFYeHm!d zhzLsMte!&Zr%+gnqEFJLDMU{wx{E^$1t6H?#8N2Gc|6_s4}RxQFFo!v(?t%r=pfmcAOW{0!0?@N1R-|K<8mq*m+UC+bv$v!iU!GM z8JhnlCh0xgnOM4j>~ficszPDcaQ$sSHk+D)KennZyGQFlw%QVBLVDeFay+@^A_%b* z877o59!)BY2mdX4GuOhoV+5CYX3k!((DTI|Q<3hIVjqq1i%@=WI_ok!{F_z7#Dt`aiqTSF?yAZ@0>RY>tD!AM%tOtv!u zdN6-pH&S&huZ~|Uct8<|>CyGp_3Obi8zf6`_+NdG|cby zQGo|IZaThNolF8R#4Ii{i4FFZwFE>d_E`AB?>HJ{s{kN6l}cX26< zHF8J1Shp$3$vi+9Sua9!YE!RhenN@USYUONZRgTubt8R1BbV6J*UBbw+bf5zQ7mt+6b6m3RBb-^etTp1X2_h5eD1&Sm6E!_4o5>w#be;6w)RQm@bDEe#7!d51ja z7E`x1g3*tEgQq?Cr0$)WAwWd5b<~?#WN*>bXmln6?%FAxGih0xxVEaHi*Ok~>`!^= z&1f7!S+^jFdq*7d0nbv#G1^nnG-8#3422EWD$Jj@Y6`0yZy%Bt>jKmFsPL?&0&j2X+r$TbmF&uT2blWXB^(02wh$|Gw0a-Tjr z|L5M-3r~UEMa+RU?ZATkGFwY^eF)e%1v{=XJb5ILdbK{_ZhCt0T6ICZarR7WNG0cD z;dl3!4=9md$#7dosim?j?TOD_7*7ewxsAqCBuhlDWzk96A88vr71e}dBk^1Ex(?F2 z(@0$vS3TAJVjRn(qoR4zs)?k$a|jr1tzXpDgz(FwqK+x;QhA0aB{-3y?xwC8XSi<_ zwPlwybfOMX6zH`t71>QF&QpIqkqdcN1`F+x0n(&>h9roe9K3Wpeq1+yuzK$2*WYPXIguSn_2#a) z{Q@7^!IJuVPV~6HGr0si8~M&a4&p{b!?x#M+i@s|z&Km5Qn1JZ2AvUtEHbxKK$bNs z+jef)3DWJ;vQ;PCia*V{jdE7fRpLRRMOxa8NGXu#!Xm2$T{*mE0P3Lit^W)#001kk zc6U=A1+dbZ{x_BO@7mr0SY_YeUn{M;gZxKL^xhXS2dfG1+JR4V_Z^tW!%)#k>2h?{ zCnt39Xa_nkU!KsS6fIIM*S<6@0v(yZkB28eI+5UL>$t+mMT@io4VhKNAMix+O#mn+ z@|9mQx$W>#h1%M^PtaGVd=Im|FD{<9cn-JRbAy!hxU4~b%Yp@TjJ%&f!T?@6JudvD z(IX?Wq#G+^oXJ5kF5CSaMPO7RbIe`h1}J-kZB%WQQNLhsE)zGoT}iDgng7YvU!~e< zLd{}I#6K*jVOQdhmQ~+~UvT0<9anyxzTB#hs}7EI zUtLu!u#npiCmIh$E_>wiV%ii}E#-llCL?m%$GeXT*lsY!(ek8O=e_QITgq!4cX26R zyfH&o3A|$4G|K-N924PE34b@Y>d z0yHJ@`OsL+hZ|2rXdKH?QGYNu?Dt=7*+za3$IpL1fYkK}*44J*J{JqFb@f7&qE*Cd z2%jqP*&my&H{M&INC}YbhXrY(?Q`S@thcEBcOS7^$fInxj6DQFUfkrv!>W>OlF;8z zoxVncQzxVp^lUD}Il_HY6%M>t5y~rHY>D(OuI*)GJXETgm9ef<;^M_3lfG`+pnCyS zqWC;=Y2>iWolt8Na4cWbu=O9+QXH*5R~BZ!vL>SNP8=b%oH$E*@yifZkX&J8sR*Tc z8T^W3RtE1Ry!VpG2banDUWw8H6@2DIQWUIbcb6c)3+*u12F14VJ>A<;^U>RQT6oJH z?gNhy9}{gljfyputOjQfHMaZ%pKke?TpQric(plm%qg!YNg~@e%U>z$pdfV& znW4ovnBxPg5ZwyCCp_JL6`(6kl4l%{mu8=OXgIiQpc8Hkt8~Ps%bY?2;YlO2FA4V@ zoROPK)Ga1FBn>?F$)z~oM~9B*%KH@VOSt4H;#-l&YonQ4s#bb>Ty1oA5mOdThI8%c za$7X%g^R&sEas_jg~up~rz;y`?X}%Sck>LbZ%IY8aYs+x@dP9~yBQN@)+f2c0eoSVw&;7=lvihD+ifd^RPJ0ggK4R1Nl4D$%%%mS&U?wZoJPFwgBH#`G%eBmuK zr5R9rx#9fs?3VbCbL`GMG8g7@k<8hh3=`{*rksEuVpy5DRw1n%cL&=Fd=v`~Z%%5L`# zYbNmBtDCIm6{qE;CH{_FPKuLyP?7ijP>~hdzf}Kh(0rHpL9Ls-@3&5ufsf)pV37Z= zcmJgD|Bc%H7lohlPYyD%BE~;B$TENDAk*)^bC4;t5J~{^zX?^R88?!HoJ1~zS%#jp z+vR0!by~i%K>h(SV8M2U;WIa(j*L_1;d`R;6y*3I*6K$6k%RFJY7(%GY~>n95bEnp zA0bv$K5`KwM^;n77+76_T6>Q0PlwO@?0)6bEAu}%$p0&O|EIX}JJ0RkFx`M4WLq>> z^tYDoyPEFv^YKVG$Lce`_H>lkd{Z-qJ1;Z)5=$sbM3cO%@L|&xH(MJEu(P$ZgHKI; zs95B3a0}>UrfuS-{Y83CjB-Ii3ST}bWW6Ax;+sW>2#LSwV+^|p@L%Xn7$F>=UwRbxw0;;u56DyFYSh->-|Xaz@ZIX5tiUH?kGPy9 zm;=UKbmNJKdC}$Lei+6g?PtJNv809-sf{v9H;YuTN63gju;k_nVIQ;tW?Q_P zrY8Kq>+B!qRFh?btWM{Bg}zG>)XGSsBa@!r8j!lc#-v7yXyKU*jt)UMlB1+?`5(W)RpnJ8FmL zibf@U4nJ`;!atwea~otZ8|d{m2%90@kINb0inR@(0^`bt8&DVHR+c=tmu_9VXZyb3 zGc|lxsDs{vszPpEr8$PK-wJP*CKn2;&Pf3v0@KHc96#qFz364#Qxe=4YX@8zUm-7G z3hm4+PhJ!?(;Y&~er%d`)#h%mPqms@+H{+dYjX_Xq_~2!o%Y#o_N_-487nF=a);|` z^A}RRjqb=9v7Qh+7Oal78d-Yx?uB@bu(!I38^=-rWVAxv*z>a7B9BM2tc)Y-A7bD3 z_(0QKylf0+KMaK>;)#hYMC=XA*z0Dqy_#_-IH!oo)Hiz1i85mPH)zF<=!`4pM%{Bi zbYmY^?%k_)Rp#Drq_xBqZn17LtC)V>ne6Rq?)RpUouO<(13e=F7s$#-qG&2qITHuh z6=7t3Upr5TOtX-`I^hLziiJR5RK^AKn8+HRw`4vANouLKyR+wYXXn=r0)p=(&FyGK zW~7er5U}M!I7u=^7n)-iJWW8)I1UFjq^^U3kCCdWJi4Xhij(+o9w491&3sd*2j4Dt z+Qfhcyt)qWM8^;m98I_^hVMul+VH!)YNra~EmJkS;d|$EMLF$CWP<6wvZJr8F>Y`S zY`T#hjs3}kVG59f?CKffC>W;6v+FU>4twpo3hhKdMRD6{E$#=T00z^*_gz^JOV-%dfGHXB45-vmNXTg{N{p{;_{eF6LA!| zl`6tki+j{q2Xa@=Xva+_FXqi(Q+?Kc`1vLTzT1F-)!jKI-?Vlq?y<}9gZ(}~@muhY zpK;@S1)hQ>ljPA$G`keqv^~&*+WmgZbZ{F2<_z;C=!XCv^nuse#I`@5Tk%KnLp(S9 z9<>XD#|M2hj$6M6y1eJ1$Q{*hL7m>#ar>2P`fq2y68b~f4t2!yK&_L7V|)M_iXwE+ z`D>KVjk1nM+44$(q}rn?y(Xp9nUiwiW`pA(90Kgr`}OtDuP!6*$AT>rs=C#uQ^|hi z?iXq9n+Z$!)f#uEvbl6~w#FTTct`PsOmocap<li#QO$1%Ro{{SKXuWRz(8-f3u`RDKFr|po= zEhjcph~7!a4?i5yx&w71mEFJ5)sX9{?#2CRnfzioiKOjdVlR#P>i7o= zIiq5A4=JrVIUzRBM4Hng+p3UR2H$Nw-2Z2b`zHG8{w5G9v;8*|viAl3r<+t2guYT% z5VaRbVknTkeyrP6ze&pYP}_zIbL9igGz%jMuf0Nzo;-bf95rpp(F!oM5<6uL?Fn1i zIW6A$Buy-wO*6}Z5-S3P7}g{!X&BrlkUinr0aIu>QmMDl890?vE(Qo#JBkOao3KDI z(LNP$kdwSx+WLL$HOP203Nk-S`=>!;k*_aW%KJq1NmIpnxB!+|MC^D)fD9BiAgmsd z!gtcc5!7U0Mdgwr`1z~Pss-QYqzF~|90@22c{G9|nRx$}I4ne9?>2hBM!mKWeRl&( z)De8RyWt%38&udM`)5D$+Ekt@b5gf-0inJ%lz10cuq;E;DPlf>;vzWsO0kMN^ci~| zA$H%nPH0GTA)Jkr=CW!vcF~;0_mpO5O>CLI+qGwg-iJ%6-n510B*ZE!J$dHPKy&0UbCI%E$8>E!wF(LeqUAjhF%b)Utj(Ho|K< zeR!pev}PHOSR3Z?3}=mgT6#tGQT^En4)Ua*WOx|diJ7;dW+ttE^1%MsfAVzgtE{Dd zjZPT69!%W6?XAr+zU3NRyj|>Y((uR7VM;N)4b!=iA>+U)iB*el5QVZmEOdagM>#7O z?j%BJ6VFG}sh(9Kxj}&I1pfjh)|r)2?{S8$S!fSWLr-FAVd-#6D(FC*ivPR2iPntR zPp&dmg7mCU-J|s5&wk~Zx}7ES5&Tv=c_YG@v0dd*`;E$6=W*PKA@Ux1-R>b6>QQf2 z8~gS6TEs-D9Uz3MBk7WXZR3tw^Lj;2DWL2qAh2@9{!9C zrc8($3^vSr%R1Xz7x*2ulzo>Kg4@V4yz52MkG^v__ry*8RAXI_C}?uvZQ|&Kbhw2 zSg<%2LuaohP4r#P+xF7Ewdo$HSGb;Ou?TcwU5CZmmNjYXoqi{J#TxlNrR^X7na5y>35t@s0W}df#^W>*^9yly~tPpHHtexcZ64ZQR{U zOiM&dHqEe`os?1P0ai2sCJ}vgIwAgiP*L}`2LjNq%?|nj{*{t9@3E34GPyS!^ z3ICE#{x`DOHLm|1g)9!t4Ez&?{PK=M7Ad0edL@aXU8 zS~304KUpL2yM|#`Irv|#68@ApRsr@J@9(bzE;T#LkHF>igQa3()`s`TMuuaBR4vy) znyqDC)T}mgE;lzoLJgjaLHaV%PF}Hs%{56|k&HLl#9mFZN~E;vQ(+K^Q;>G3iOfe? z>Y=5ovT*4yEgv0mKQX*IIv);ORfjp}UT-;ny>GvG`sy4PG`7J`4Z=+U0&?;V92hyq z6<}7qt`=ajPmFgxAQ6$TFP81lr+V!WkUz)Z4P};!uKJi&lu7BC<9sd1V^Nmz%3P)8 z@XIdLv%JEWl*cHGhD>I*2vj&$k{%S`rb>_Y%j1g1+QFPZfz=_LeSOS-?l%T9sG}-U z0PN)nr;OR782FBB*02e*{g7&Q#~Ox`VSRcO`%*v-F_r7QQ+J!xY5p#!lbW^rgw*ly z7G?z^o~!D(R$9EBuY=@dw7Sg)$t{ZT=|OT_ z9NE(|p&bQyLV-rtL9On(RP?39g%<;Bi?a?qnq!@#7@E#=)B)&}))U31qew_=N(ltq zl(eNM6`|aR zjY2=7ymor@0;TP9J=xMF_@5H2%?CGv zjOdi`$#5ei$l>wAy{!n@98`frRXTJ76r?V+6I@Szg*WlrsiS8uaZ&skfn_^BaNq#D zUKe2^iG6D9OL!N64ykYons|n5WR(V5PEOp*38@~DA*?8NFlK~ZEZoeh6Z`; z7Qvgaq*&b4Xm`iELlW~QzjMC@*!>RZY}|hGA}MB&Y-$9PFp*hZDd_@3*Y8|2Qs&Ae1Tn4; z-yZ*-b97i-5`mdN(*C88cf0h`TLOkO`Gy*+Yk^D&c(&2(fd}u7j7G?2P-mb*2v-@0 z%DKeFWjA}26}U>MF95C*Hn9p37*~1JjZz%zzkI`X7PPts5$;A

  • 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¤u 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
    1mcKxrQTQlXoz-5$Q5aSg9=-VVq1se`cp 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

    KQb`j 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 + } +} + +KernelArgGenerator* DataGenerator::getArgGenerator( const KernelArgInfo& argInfo ) +{ + //try to match the full type first + ArgGeneratorsMap::iterator i = m_argGenerators.find(argInfo.getTypeName()); + ArgGeneratorsMap::iterator e = m_argGenerators.end(); + + if( i != e ) + { + return i->second; + } + // search for the proper prefix of the type + for(i = m_argGenerators.begin(); i != e; ++i) + { + if( 0 == argInfo.getTypeName().find(i->first)) + { + return i->second; + } + } + throw Exceptions::TestError(std::string("Can't find the generator for the type ") + + argInfo.getTypeName() + " for argument " + argInfo.getName() + "\n"); +} + +void DataGenerator::setArgGenerator(const KernelArgInfo& argInfo, + KernelArgGenerator* pGen) +{ + m_argGenerators[argInfo.getTypeName()] = pGen; +} + +float get_random_float(float low, float high, MTdata d) +{ + float t = (float)((double)genrand_int32(d) / (double)0xFFFFFFFF); + return (1.0f - t) * low + t * high; +} + +double get_random_double(double low, double high, MTdata d) +{ + cl_ulong u = (cl_ulong) genrand_int32(d) | ((cl_ulong) genrand_int32(d) << 32 ); + double t = (double) u * MAKE_HEX_DOUBLE( 0x1.0p-64, 0x1, -64); + return (1.0f - t) * low + t * high; +} + +size_t get_random_size_t(size_t low, size_t high, MTdata d) +{ + enum { N = sizeof(size_t)/sizeof(int) }; + + union { + int word[N]; + size_t size; + } u; + + for (unsigned i=0; i != N; ++i) { + u.word[i] = genrand_int32(d); + } + + assert(low <= high && "Invalid random number range specified"); + size_t range = high - low; + + return (range) ? low + ((u.size - low) % range) : low; +} + +size_t get_random_int32(int low, int high, MTdata d) +{ + int v = genrand_int32(d); + + assert(low <= high && "Invalid random number range specified"); + size_t range = high - low; + + return (range) ? low + ((v - low) % range) : low; +} + +/* + * KernelArgGeneratorSampler + */ +KernelArgGeneratorSampler::KernelArgGeneratorSampler(bool isBuffer, + size_t vectorSize, + int minValue, + int maxValue) { + initToDefaults(); +} + +void KernelArgGeneratorSampler::initToDefaults() { + m_normalized = false; + m_addressingMode = CL_ADDRESS_NONE; + m_filterMode = CL_FILTER_NEAREST; +} + +KernelArgGeneratorSampler::KernelArgGeneratorSampler() { + initToDefaults(); + +} + +void KernelArgGeneratorSampler::setNormalized(cl_bool isNormalized) +{ + m_normalized = isNormalized; +} + +void KernelArgGeneratorSampler::setAddressingMode(cl_addressing_mode mode) +{ + m_addressingMode = mode; +} + +void KernelArgGeneratorSampler::setFiterMode(cl_filter_mode mode) +{ + m_filterMode = mode; +} + + +/* + * SamplerValuesGenerator. + */ + +/* + * Static fields initialization. + */ +cl_bool SamplerValuesGenerator::coordNormalizations[] = {CL_TRUE, CL_FALSE}; + +cl_filter_mode SamplerValuesGenerator::filterModes[] = { + CL_FILTER_NEAREST, + CL_FILTER_LINEAR +}; + +cl_addressing_mode SamplerValuesGenerator::addressingModes[] = { + CL_ADDRESS_NONE, + CL_ADDRESS_CLAMP, + CL_ADDRESS_CLAMP_TO_EDGE, + CL_ADDRESS_REPEAT, + CL_ADDRESS_MIRRORED_REPEAT +}; + +const size_t NUM_NORM_MODES = + sizeof(SamplerValuesGenerator::coordNormalizations)/sizeof(cl_bool); + +const size_t NUM_FILTER_MODES = + sizeof(SamplerValuesGenerator::filterModes)/sizeof(cl_filter_mode); + +const size_t NUM_ADDR_MODES = + sizeof(SamplerValuesGenerator::addressingModes)/sizeof(cl_addressing_mode); + +SamplerValuesGenerator::iterator SamplerValuesGenerator::end() +{ + return iterator(NUM_NORM_MODES-1, NUM_FILTER_MODES-1, NUM_ADDR_MODES-1); +} + +/* + * A constructor for generating an 'end iterator'. + */ +SamplerValuesGenerator::iterator::iterator(size_t norm, size_t filter, + size_t addressing): + m_normIndex(norm), m_filterIndex(filter), m_addressingModeIndex(addressing){} + +/* + * A constructor for generating a 'begin iterator'. + */ +SamplerValuesGenerator::iterator::iterator(): + m_normIndex(0), m_filterIndex(0), m_addressingModeIndex(0){} + +SamplerValuesGenerator::iterator& SamplerValuesGenerator::iterator::operator ++() +{ + if (incrementIndex(m_normIndex, NUM_NORM_MODES)) return *this; + if (incrementIndex(m_filterIndex, NUM_FILTER_MODES)) return *this; + if (incrementIndex(m_addressingModeIndex, NUM_ADDR_MODES)) return *this; + + assert(false && "incrementing end iterator!"); + return *this; +} + +bool SamplerValuesGenerator::iterator::incrementIndex(size_t &i, + const size_t limit) +{ + i = (i+1) % limit; + return i != 0; +} + +bool SamplerValuesGenerator::iterator::operator == (const iterator& other) const +{ + return m_normIndex == other.m_normIndex && + m_filterIndex == other.m_filterIndex && + m_addressingModeIndex == other.m_addressingModeIndex; +} + +bool SamplerValuesGenerator::iterator::operator != (const iterator& other) const +{ + return !(*this == other); +} + +cl_bool SamplerValuesGenerator::iterator::getNormalized() const +{ + assert(m_normIndex < NUM_NORM_MODES && "illegal index"); + return coordNormalizations[m_normIndex]; +} + +cl_filter_mode SamplerValuesGenerator::iterator::getFilterMode() const +{ + assert(m_filterIndex < NUM_FILTER_MODES && "illegal index"); + return filterModes[m_filterIndex]; +} + +cl_addressing_mode SamplerValuesGenerator::iterator::getAddressingMode() const +{ + assert(m_addressingModeIndex < NUM_ADDR_MODES && "illegal index"); + return addressingModes[m_addressingModeIndex]; +} + +unsigned SamplerValuesGenerator::iterator::toBitmap() const +{ + unsigned norm, filter, addressingModes; + switch (getNormalized()) + { + case CL_TRUE: + norm = 8; + break; + case CL_FALSE: + norm = 0; + break; + default: + assert(0 && "invalid normalize value"); + } + + switch (getFilterMode()) + { + case CL_FILTER_NEAREST: + filter = 0; + break; + case CL_FILTER_LINEAR: + filter = 16; + break; + default: + assert(0 && "invalid filter value"); + } + + switch(getAddressingMode()) + { + case CL_ADDRESS_NONE: + addressingModes = 0; + break; + case CL_ADDRESS_CLAMP: + addressingModes = 1; + break; + case CL_ADDRESS_CLAMP_TO_EDGE: + addressingModes = 2; + break; + case CL_ADDRESS_REPEAT: + addressingModes = 3; + break; + case CL_ADDRESS_MIRRORED_REPEAT: + addressingModes = 4; + break; + default: + assert(0 && "invalid filter value"); + } + + return norm | filter | addressingModes; +} + +std::string SamplerValuesGenerator::iterator::toString() const +{ + std::string ret("("); + + switch (getNormalized()) + { + case CL_TRUE: + ret.append("Normalized | "); + break; + case CL_FALSE: + ret.append("Not Normalized | "); + break; + default: + assert(0 && "invalid normalize value"); + } + + switch (getFilterMode()) + { + case CL_FILTER_NEAREST: + ret.append("Filter Nearest | "); + break; + case CL_FILTER_LINEAR: + ret.append("Filter Linear | "); + break; + default: + assert(0 && "invalid filter value"); + } + + switch(getAddressingMode()) + { + case CL_ADDRESS_NONE: + ret.append("Address None"); + break; + case CL_ADDRESS_CLAMP: + ret.append("Address clamp"); + break; + case CL_ADDRESS_CLAMP_TO_EDGE: + ret.append("Address clamp to edge"); + break; + case CL_ADDRESS_REPEAT: + ret.append("Address repeat"); + break; + case CL_ADDRESS_MIRRORED_REPEAT: + ret.append("Address mirrored repeat"); + break; + default: + assert(0 && "invalid filter value"); + } + + ret.append(")"); + return ret; +} + +/* + * ImageValuesGenerator. + */ + +/* + * Static fields initialization. + */ +const char* ImageValuesGenerator::imageTypes[] = { + "image1d_array_float", + "image1d_array_int", + "image1d_array_uint", + "image1d_buffer_float", + "image1d_buffer_int", + "image1d_buffer_uint", + "image1d_float", + "image1d_int", + "image1d_uint", + "image2d_array_float", + "image2d_array_int", + "image2d_array_uint", + "image2d_float", + "image2d_int", + "image2d_uint", + "image3d_float", + "image3d_int", + "image3d_uint" +}; + +cl_channel_order ImageValuesGenerator::channelOrders[] = { + CL_A, + CL_R, + CL_Rx, + CL_RG, + CL_RGx, + CL_RA, + CL_RGB, + CL_RGBx, + CL_RGBA, + CL_ARGB, + CL_BGRA, + CL_INTENSITY, + CL_LUMINANCE, + CL_DEPTH, + CL_DEPTH_STENCIL +}; + +const size_t NUM_CHANNEL_ORDERS = sizeof(ImageValuesGenerator::channelOrders)/sizeof(ImageValuesGenerator::channelOrders[0]); +const size_t NUM_IMG_TYS = sizeof(ImageValuesGenerator::imageTypes)/sizeof(ImageValuesGenerator::imageTypes[0]); + +ImageValuesGenerator::iterator ImageValuesGenerator::begin() +{ + return ImageValuesGenerator::iterator(this); +} + +ImageValuesGenerator::iterator ImageValuesGenerator::end() +{ + return ImageValuesGenerator::iterator(0); +} +/* + * Class Iterator + */ +ImageValuesGenerator::iterator::iterator(ImageValuesGenerator *pParent): + m_parent(pParent), m_channelIndex(0), m_imgTyIndex(0) +{ +} + +/* + * Initializes an 'end' iterator. + */ +ImageValuesGenerator::iterator::iterator(int): + m_parent(NULL), + m_channelIndex(NUM_CHANNEL_ORDERS), + m_imgTyIndex(NUM_IMG_TYS) {} + +ImageValuesGenerator::iterator& ImageValuesGenerator::iterator::operator ++() +{ + assert(m_channelIndex < NUM_CHANNEL_ORDERS && m_imgTyIndex < NUM_IMG_TYS && + "Attempt to increment an end iterator"); + + ImageValuesGenerator::iterator endIter = iterator(0); + // Incrementing untill we find the next legal combination, or we reach the + // end value. + while (incrementIndex(m_channelIndex,NUM_CHANNEL_ORDERS)) + if (isLegalCombination()) + return *this; + + // We have reach to this line because last increment caused an 'oveflow' + // in data channel order index. + if (incrementIndex(m_imgTyIndex, NUM_IMG_TYS)) + // In case this combination is not legal, we go on to the next legal + // combo. + return isLegalCombination() ? *this : ++(*this); + + *this = endIter; + return *this; +} + +bool ImageValuesGenerator::iterator::operator == ( + const ImageValuesGenerator::iterator& o) const +{ + return m_channelIndex == o.m_channelIndex && + m_imgTyIndex == o.m_imgTyIndex; +} + +bool ImageValuesGenerator::iterator::operator != ( + const ImageValuesGenerator::iterator& o) const +{ + return !(*this == o); +} + +std::string ImageValuesGenerator::iterator::getDataTypeName() const +{ + assert(m_imgTyIndex < NUM_IMG_TYS && "image type index is out of bound"); + + std::string tyName(imageTypes[m_imgTyIndex]); + // Find the last '_' and remove it (the suffix is _). + size_t pos = tyName.find_last_of('_'); + assert (std::string::npos != pos && "no under score in type name?"); + tyName = tyName.erase(0, pos+1); + return tyName; +} + +int ImageValuesGenerator::iterator::getOpenCLChannelOrder() const +{ + assert(m_channelIndex < NUM_CHANNEL_ORDERS && "channel index out of bound"); + return channelOrders[m_channelIndex]; +} + +int ImageValuesGenerator::iterator::getSPIRChannelOrder() const +{ + return getOpenCLChannelOrder(); +} + +std::string ImageValuesGenerator::iterator::getImageTypeName() const +{ + assert(m_imgTyIndex < NUM_IMG_TYS && "image type index is out of bound"); + + std::string tyName = imageTypes[m_imgTyIndex]; + // Find the last '_' and remove it (the suffix is _). + size_t pos = tyName.find_last_of('_'); + assert (std::string::npos != pos && "no under score in type name?"); + tyName = tyName.erase(pos, tyName.size() - pos); + + return tyName; +} + +std::string ImageValuesGenerator::iterator::getImageGeneratorName() const +{ + assert(m_imgTyIndex < NUM_IMG_TYS && "image type index is out of bound"); + return imageTypes[m_imgTyIndex]; +} + +std::string ImageValuesGenerator::iterator::getBaseImageGeneratorName() const +{ + assert(m_imgTyIndex < NUM_IMG_TYS && "image type index is out of bound"); + std::string tyName = getImageTypeName(); + tyName.append("_t"); + return tyName; +} + +int ImageValuesGenerator::iterator::getDataType() const +{ + assert(m_imgTyIndex < NUM_IMG_TYS && "image type index is out of bound"); + std::string tyName = getDataTypeName(); + + if ("int" == tyName) + return SPIR_CLK_SIGNED_INT32; + if ("uint" == tyName) + return SPIR_CLK_UNSIGNED_INT32; + if ("float" == tyName) + return SPIR_CLK_FLOAT; + assert (false && "unkown image data type"); + return -1; +} + +std::string ImageValuesGenerator::iterator::toString() const +{ + if (*this == m_parent->end()) + return "End iterator"; + + // Sanity. + assert(m_imgTyIndex < NUM_IMG_TYS && "image type index is out of bound"); + assert(m_channelIndex < NUM_CHANNEL_ORDERS && "channel index out of bound"); + + std::string str = imageTypes[m_imgTyIndex]; + str.append("_"); + + switch (channelOrders[m_channelIndex]) + { + case CL_R: + str.append("cl_r"); + break; + case CL_A: + str.append("cl_a"); + break; + case CL_RG: + str.append("cl_rg"); + break; + case CL_RA: + str.append("cl_ra"); + break; + case CL_RGB: + str.append("cl_rgb"); + break; + case CL_RGBA: + str.append("cl_rgba"); + break; + case CL_BGRA: + str.append("cl_bgra"); + break; + case CL_ARGB: + str.append("cl_argb"); + break; + case CL_INTENSITY: + str.append("cl_intensity"); + break; + case CL_LUMINANCE: + str.append("cl_luminace"); + break; + case CL_Rx: + str.append("cl_Rx"); + break; + case CL_RGx: + str.append("cl_RGx"); + break; + case CL_RGBx: + str.append("cl_RGBx"); + break; + case CL_DEPTH: + str.append("cl_depth"); + break; + case CL_DEPTH_STENCIL: + str.append( "cl_depth_stencil"); + break; + default: + assert(false && "Invalid channel order"); + str.append(""); + break; + } + + return str; +} + +bool ImageValuesGenerator::iterator::incrementIndex(size_t& index, + size_t arrSize) +{ + index = (index + 1) % arrSize; + return index != 0; +} + +bool ImageValuesGenerator::iterator::isLegalCombination() const +{ + cl_channel_order corder = channelOrders[m_channelIndex]; + std::string strImgTy(imageTypes[m_imgTyIndex]); + + if (corder == CL_INTENSITY || corder == CL_LUMINANCE) + { + return getDataTypeName() == std::string("float"); + } + + if (corder == CL_DEPTH) + return false; + + if (corder == CL_RGBx || corder == CL_RGB // Can only be applied for int unorms. + || corder == CL_ARGB || corder == CL_BGRA) // Can only be applied for int8. + return false; + + return true; +} + diff --git a/test_conformance/spir/datagen.h b/test_conformance/spir/datagen.h new file mode 100644 index 00000000..3b8ba5b8 --- /dev/null +++ b/test_conformance/spir/datagen.h @@ -0,0 +1,1066 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef __DATAGEN_H +#define __DATAGEN_H + +#include "../../test_common/harness/compat.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "../../test_common/harness/mt19937.h" + +#include "exceptions.h" +#include "kernelargs.h" + +// ESINNS is a short name for EXPLICIT_SPECIALIZATION_IN_NON_NAMESPACE_SCOPE + +#undef ESINNS + +#ifdef __GNUC__ + +#define ESINNS +#define ESINNS_PREF() inline +#define ESINNS_POST() RandomGenerator:: + +#else + +#define ESINNS_PREF() +#define ESINNS_POST() + +#endif + +#define MAX_WORK_DIM 3 +#define GLOBAL_WORK_SIZE (((CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE / sizeof(cl_double) / 16) / 2) * 2) // max buffer size = CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE / sizeof(double16) + +// SPIR definitions for image channel data types (Section 2.1.3.2). +#define SPIR_CLK_SNORM_INT8 0x10D0 +#define SPIR_CLK_SNORM_INT16 0x10D1 +#define SPIR_CLK_UNORM_INT8 0x10D2 +#define SPIR_CLK_UNORM_INT16 0x10D3 +#define SPIR_CLK_UNORM_SHORT_565 0x10D4 +#define SPIR_CLK_UNORM_SHORT_555 0x10D5 +#define SPIR_CLK_UNORM_SHORT_101010 0x10D6 +#define SPIR_CLK_SIGNED_INT8 0x10D7 +#define SPIR_CLK_SIGNED_INT16 0x10D8 +#define SPIR_CLK_SIGNED_INT32 0x10D9 +#define SPIR_CLK_UNSIGNED_INT8 0x10DA +#define SPIR_CLK_UNSIGNED_INT16 0x10DB +#define SPIR_CLK_UNSIGNED_INT32 0x10DC +#define SPIR_CLK_HALF_FLOAT 0x10DD +#define SPIR_CLK_FLOAT 0x10DE +#define SPIR_CLK_UNORM_INT24 0x10DF + +#define NUM_IMG_FORMATS 64 + +double get_random_double(double low, double high, MTdata d); +float get_random_float(float low, float high, MTdata d); +size_t get_random_size_t(size_t low, size_t high, MTdata d); + +/** + Simple container for the work size information + */ +class WorkSizeInfo +{ +public: + /** + Returns the flat global size + */ + size_t getGlobalWorkSize() const; +public: + cl_uint work_dim; + size_t global_work_offset[MAX_WORK_DIM]; + size_t global_work_size[MAX_WORK_DIM]; + size_t local_work_size[MAX_WORK_DIM]; +}; + +/** + Generates various types of random numbers + */ +class RandomGenerator +{ +public: + RandomGenerator():m_d(NULL) + { + init(0); + } + + ~RandomGenerator() + { + if( NULL != m_d ) + free_mtdata(m_d); + } + + void init(cl_uint seed) + { + m_d = init_genrand( seed ); + } + + template T getNext(T low, T high) + { + assert(false && "Not implemented"); + return T(); + } + +#ifdef ESINNS + +private: + MTdata m_d; +}; + +#endif + +template<> ESINNS_PREF() bool ESINNS_POST()getNext(bool low, bool high) +{ + return (bool)get_random_size_t((size_t)low, (size_t)high, m_d); +} + +template<> ESINNS_PREF() cl_char ESINNS_POST()getNext(cl_char low, cl_char high) +{ + return (cl_char)get_random_size_t((size_t)low, (size_t)high, m_d); +} + +template<> ESINNS_PREF() cl_double ESINNS_POST()getNext(cl_double low, cl_double high) +{ + return get_random_double(low, high, m_d); +} + +template<> ESINNS_PREF() cl_float ESINNS_POST()getNext(cl_float low, cl_float high) +{ + return get_random_float(low, high, m_d); +} + +template<> ESINNS_PREF() cl_int ESINNS_POST()getNext(cl_int low, cl_int high) +{ + return (cl_int)get_random_size_t((size_t)low, (size_t)high, m_d); +} + +template<> ESINNS_PREF() cl_long ESINNS_POST()getNext(cl_long low, cl_long high) +{ + return (cl_long)get_random_size_t((size_t)low, (size_t)high, m_d); +} + +template<> ESINNS_PREF() cl_short ESINNS_POST()getNext(cl_short low, cl_short high) +{ + return (cl_short)get_random_size_t((size_t)low, (size_t)high, m_d); +} + +template<> ESINNS_PREF() cl_uchar ESINNS_POST()getNext(cl_uchar low, cl_uchar high) +{ + return (cl_uchar)get_random_size_t((size_t)low, (size_t)high, m_d); +} + +template<> ESINNS_PREF() cl_uint ESINNS_POST()getNext(cl_uint low, cl_uint high) +{ + return (cl_uint)get_random_size_t((size_t)low, (size_t)high, m_d); +} + +template<> ESINNS_PREF() cl_ulong ESINNS_POST()getNext(cl_ulong low, cl_ulong high) +{ + return (cl_ulong)get_random_size_t((size_t)low, (size_t)high, m_d); +} + +template<> ESINNS_PREF() cl_ushort ESINNS_POST()getNext(cl_ushort low, cl_ushort high) +{ + return (cl_ushort)get_random_size_t((size_t)low, (size_t)high, m_d); +} + +#ifndef ESINNS + +private: + MTdata m_d; +}; + +#endif + +extern RandomGenerator gRG; + +/** + Base class for kernel argument generator + */ +class KernelArgGenerator +{ +protected: + KernelArgGenerator() + {} + +public: + virtual KernelArg* generate( cl_context context, + const WorkSizeInfo& ws, + const KernelArgInfo& argInfo, + const KernelArg* refArg, + const cl_kernel kernel, + const cl_device_id device ) = 0; + virtual ~KernelArgGenerator() {} +}; + +/** + Mock: 'Not implemented' version of the kernel argument generator - used for the still unsupported types + */ +class KernelArgGeneratorNI: public KernelArgGenerator +{ +public: + KernelArgGeneratorNI( bool isBuffer, size_t vectorSize, int minValue, int maxValue ) + {} + + KernelArg* generate( cl_context context, + const WorkSizeInfo& ws, + const KernelArgInfo& argInfo, + const KernelArg* refArg, + const cl_kernel kernel, + const cl_device_id device ) + { + //assert(false && "Not implemented"); + throw Exceptions::TestError("KernelArgGenerator is not implemented\n"); + } +}; + +/** + Kernel argument generator for images + */ +class KernelArgGeneratorImage: public KernelArgGenerator +{ +public: + KernelArgGeneratorImage(bool isBuffer, size_t vectorSize, char minValue, char maxValue) : + m_isBuffer(isBuffer), + m_vectorSize(vectorSize), + m_minValue(minValue), + m_maxValue(maxValue) + { + m_format.image_channel_order = CL_RGBA; + + m_desc.image_width = 32; + m_desc.image_height = 1; + m_desc.image_depth = 1; + m_desc.image_array_size = 1; + m_desc.num_mip_levels = 0; + m_desc.num_samples = 0; + m_desc.buffer = NULL; + } + + bool isValidChannelOrder(cl_context context, cl_channel_order order) const + { + cl_mem_flags flags = CL_MEM_COPY_HOST_PTR; + cl_uint actualNumFormats = 0; + cl_image_format imgFormat = m_format; + imgFormat.image_channel_order = order; + + cl_int error = clGetSupportedImageFormats( + context, + flags, + m_desc.image_type, + 0, + NULL, + &actualNumFormats); + if (CL_SUCCESS != error) + throw Exceptions::TestError("clGetSupportedImageFormats failed\n", error); + + std::auto_ptr supportedFormats(new cl_image_format[actualNumFormats]); + error = clGetSupportedImageFormats( + context, + flags, + m_desc.image_type, + actualNumFormats, + supportedFormats.get(), + NULL); + if (CL_SUCCESS != error) + throw Exceptions::TestError("clGetSupportedImageFormats failed\n", error); + + for (size_t i=0; igetBuffer(), allocSize ); + } + + return new KernelArgImage(context, argInfo, pBuffer, allocSize, mem_flags, m_format, m_desc); + } + +protected: + KernelArgGeneratorImage() + {} + + void fillBuffer( cl_char * ptr, size_t nelem) + { + for( size_t i = 0; i < nelem; ++i ) + { + ptr[i] = gRG.getNext(m_minValue, m_maxValue); + } + } + +protected: + bool m_isBuffer; + size_t m_vectorSize; + cl_char m_minValue; + cl_char m_maxValue; + cl_image_format m_format; + cl_image_desc m_desc; +}; + +/** + Kernel argument generator for image1d_array + */ +template class KernelArgGeneratorImage1dArray: public KernelArgGeneratorImage +{ +public: + KernelArgGeneratorImage1dArray( bool isBuffer, size_t vectorSize, char minValue, char maxValue ): + KernelArgGeneratorImage(isBuffer, vectorSize, minValue, maxValue) + { + m_desc.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY; + m_format.image_channel_data_type = channel_type; + + m_desc.image_row_pitch = m_desc.image_width*4*4; //RGBA channel size * sizeof (cl_int) + m_desc.image_slice_pitch = m_desc.image_height * m_desc.image_row_pitch; + + } +}; + +/** + Kernel argument generator for image1d_buffer + */ +template class KernelArgGeneratorImage1dBuffer: public KernelArgGeneratorImage +{ +public: + KernelArgGeneratorImage1dBuffer( bool isBuffer, size_t vectorSize, char minValue, char maxValue ) : + KernelArgGeneratorImage(isBuffer, vectorSize, minValue, maxValue) + { + m_desc.image_type = CL_MEM_OBJECT_IMAGE1D_BUFFER; + m_format.image_channel_data_type = channel_type; + + m_desc.image_row_pitch = m_desc.image_width*4*4; //RGBA channel size * sizeof (cl_int) + // http://www.khronos.org/registry/cl/specs/opencl-1.2.pdf 5.2.2; + // Slice pitch of 1d images should be zero. + m_desc.image_slice_pitch = 0; + } +}; + +/** + Kernel argument generator for image1d + */ +template class KernelArgGeneratorImage1d: public KernelArgGeneratorImage +{ +public: + KernelArgGeneratorImage1d( bool isBuffer, size_t vectorSize, char minValue, char maxValue ) : + KernelArgGeneratorImage(isBuffer, vectorSize, minValue, maxValue) + { + m_desc.image_type = CL_MEM_OBJECT_IMAGE1D; + m_format.image_channel_data_type = channel_type; + + m_desc.image_row_pitch = m_desc.image_width*4*4; //RGBA channel size * sizeof (cl_int) + // http://www.khronos.org/registry/cl/specs/opencl-1.2.pdf + // '5.3.1.2 image descriptor': Slice pitch is not applicable for one- + // dimensional images. + m_desc.image_slice_pitch = 0; + } +}; + +/** + Kernel argument generator for image2d_array + */ +template class KernelArgGeneratorImage2dArray: public KernelArgGeneratorImage +{ +public: + KernelArgGeneratorImage2dArray( bool isBuffer, size_t vectorSize, char minValue, char maxValue ) : + KernelArgGeneratorImage(isBuffer, vectorSize, minValue, maxValue) + { + m_desc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; + m_format.image_channel_data_type = channel_type; + + m_desc.image_height = 32; + m_desc.image_array_size = 8; + m_desc.image_row_pitch = m_desc.image_width*4*4; //RGBA channel size * sizeof (cl_int) + m_desc.image_slice_pitch = m_desc.image_height * m_desc.image_row_pitch; + } +}; + +/** + Kernel argument generator for image2d + */ +template class KernelArgGeneratorImage2d: public KernelArgGeneratorImage +{ +public: + KernelArgGeneratorImage2d( bool isBuffer, size_t vectorSize, char minValue, char maxValue ) : + KernelArgGeneratorImage(isBuffer, vectorSize, minValue, maxValue) + { + m_desc.image_type = CL_MEM_OBJECT_IMAGE2D; + m_format.image_channel_data_type = channel_type; + + m_desc.image_height = 32; + m_desc.image_row_pitch = m_desc.image_width*4*4; //RGBA channel size * sizeof (cl_int) + // http://www.khronos.org/registry/cl/specs/opencl-1.2.pdf + // '5.3.1.2 image descriptor': Slice pitch is not applicable for two- + // dimensional images. + m_desc.image_slice_pitch = 0; + } +}; + +/** + Kernel argument generator for image3d + */ +template class KernelArgGeneratorImage3d: public KernelArgGeneratorImage +{ +public: + KernelArgGeneratorImage3d( bool isBuffer, size_t vectorSize, char minValue, char maxValue ) : + KernelArgGeneratorImage(isBuffer, vectorSize, minValue, maxValue) + { + m_desc.image_type = CL_MEM_OBJECT_IMAGE3D; + m_format.image_channel_data_type = channel_type; + + m_desc.image_height = 32; + m_desc.image_depth = 8; + m_desc.image_row_pitch = m_desc.image_width*4*4; //RGBA channel size * sizeof (cl_int) + m_desc.image_slice_pitch = m_desc.image_height * m_desc.image_row_pitch; + } +}; + +/** + Kernel argument generator for samplers + */ +class KernelArgGeneratorSampler: public KernelArgGenerator +{ +public: + KernelArgGeneratorSampler(bool isBuffer, size_t vectorSize, int minValue, int maxValue); + + KernelArgGeneratorSampler(); + + /* + * Sampler property setters. + */ + void setNormalized(cl_bool); + void setAddressingMode(cl_addressing_mode); + void setFiterMode(cl_filter_mode); + + KernelArg* generate(cl_context context, + const WorkSizeInfo& ws, + const KernelArgInfo& argInfo, + const KernelArg* refArg, + const cl_kernel kernel, + const cl_device_id device) + { + return new KernelArgSampler(context, m_normalized, m_addressingMode, m_filterMode); + } +private: + void initToDefaults(); + + cl_bool m_normalized; + cl_addressing_mode m_addressingMode; + cl_filter_mode m_filterMode; +}; + +/* + * Generates all the possible values for image samplers. + */ +class SamplerValuesGenerator +{ +public: + class iterator { + friend class SamplerValuesGenerator; + + size_t m_normIndex, m_filterIndex, m_addressingModeIndex; + + iterator(size_t norm, size_t filter, size_t addressing); + + bool incrementIndex(size_t &i, const size_t limit); + public: + iterator(); + + /* + * Moves the iterator to the next sampler value. + */ + iterator& operator ++(); + + bool operator == (const iterator& other) const; + + bool operator != (const iterator& other) const; + + cl_bool getNormalized() const; + + cl_filter_mode getFilterMode() const; + + cl_addressing_mode getAddressingMode() const; + + /* + * Converts the value of the sampler to a bitmask representation. + */ + unsigned toBitmap() const; + + /* + * Retruns a string representation of the sampler. + */ + std::string toString() const; + }; + + iterator begin() { return iterator(); } + + iterator end(); + + static cl_bool coordNormalizations[]; + static cl_filter_mode filterModes[]; + static cl_addressing_mode addressingModes[]; +}; + +typedef struct struct_type { + cl_float float4d[4]; + cl_int intd; +} typedef_struct_type; + +typedef struct { + cl_int width; + cl_int channelType; + cl_int channelOrder; + cl_int expectedChannelType; + cl_int expectedChannelOrder; + } image_kernel_data; + +typedef struct testStruct { + cl_double vec[16]; + } testStruct; + +typedef struct { + cl_uint workDim; + cl_uint globalSize[3]; + cl_uint globalID[3]; + cl_uint localSize[3]; + cl_uint localID[3]; + cl_uint numGroups[3]; + cl_uint groupID[3]; + } work_item_data; + +/** + Kernel argument generator for structure "struct_type" + + Kernel argument generator for structure "image_kernel_data" + + Kernel argument generator for structure "testStruct" + Since there are many "testStruct", we define it to have maximum space + Also the alignment is done following the "worst" case + + Kernel argument generator for structure "work_item_data" + */ + + template class KernelStructTypeArgGenerator: public KernelArgGenerator + { + + public: + KernelStructTypeArgGenerator( bool isBuffer, size_t vectorSize, cl_int minValue, cl_int maxValue ): + m_isBuffer(isBuffer), + m_vectorSize(vectorSize), + m_alignment(0), + m_size(0) + {} + + KernelArg* generate( cl_context context, + const WorkSizeInfo& ws, + const KernelArgInfo& argInfo, + const KernelArg* refArg, + const cl_kernel kernel, + const cl_device_id device ) + { + T *pStruct = NULL; + + calcSizeAndAlignment(pStruct); + size_t size = m_size; + + if( m_isBuffer ) + { + cl_kernel_arg_address_qualifier addrQ = argInfo.getAddressQualifier(); + + if( CL_KERNEL_ARG_ADDRESS_CONSTANT == addrQ ) + { + if ( (CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE/m_size)*m_size < m_size ) + size=(CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE/m_size)*m_size; + } + + if( CL_KERNEL_ARG_ADDRESS_GLOBAL == addrQ || + CL_KERNEL_ARG_ADDRESS_CONSTANT == addrQ ) + { + size_t no_e = ws.getGlobalWorkSize(); + size = no_e * m_size; + pStruct = (T *)align_malloc(size, m_alignment); + if (NULL == pStruct) + { + throwExceptions(pStruct); + } + assert( (size_t)pStruct % m_alignment == 0 ); + if (NULL == refArg) + { + fillBuffer(pStruct, no_e); + } + else { + memcpy(pStruct, refArg->getBuffer(), size); + } + } + return new KernelArgBuffer( context, argInfo, (void*)pStruct, size); + } + else { + pStruct = (T *)align_malloc(m_size, m_alignment); + if (NULL == pStruct) + { + throwExceptions(pStruct); + } + assert( (size_t)pStruct % m_alignment == 0 ); + if (NULL == refArg) + { + fillBuffer(pStruct, 1); + } + else { + memcpy(pStruct, refArg->getBuffer(), m_size); + } + + return new KernelArg( argInfo, (void*)pStruct, m_size); + } + } + private: + + std::string getTypeString(typedef_struct_type *pStruct) + { + return "typedef_struct_type"; + } + + std::string getTypeString(image_kernel_data *pStruct) + { + return "image_kernel_data"; + } + + std::string getTypeString(testStruct *pStruct) + { + return "testStruct"; + } + + std::string getTypeString(work_item_data *pStruct) + { + return "work_item_data"; + } + + void throwExceptions(T * pStruct) + { + std::string str = "align_malloc failed for " ; + if (m_isBuffer) + str += "array of " ; + str += getTypeString(pStruct) ; + throw Exceptions::TestError(str, 1); + } + + void fillBuffer( typedef_struct_type *pStruct, size_t no_e ) + { + for (size_t e = 0; e < no_e; ++e) + { + for( size_t i = 0; i < 4; ++i ) + { + pStruct[e].float4d[i] = gRG.getNext(-0x01000000, 0x01000000); + } + pStruct[e].intd = gRG.getNext(0, 0x7fffffff); + } + } + + void fillBuffer( image_kernel_data *pStruct, size_t no_e ) + { + for (size_t e = 0; e < no_e; ++e) + { + pStruct[e].width = gRG.getNext(0, 0x7fffffff); + pStruct[e].channelType = gRG.getNext(0, 0x7fffffff); + pStruct[e].channelOrder = gRG.getNext(0, 0x7fffffff); + pStruct[e].expectedChannelType = gRG.getNext(0, 0x7fffffff); + pStruct[e].expectedChannelOrder = gRG.getNext(0, 0x7fffffff); + } + } + + void fillBuffer( testStruct *pStruct, size_t no_e ) + { + for (size_t e = 0; e < no_e; ++e) + { + for( size_t i = 0; i < 16; ++i ) + { + pStruct[e].vec[i] = gRG.getNext(-0x01000000, 0x01000000); + } + } + } + + void fillBuffer( work_item_data *pStruct, size_t no_e ) + { + for (size_t e = 0; e < no_e; ++e) + { + memset(&pStruct[e], 0, sizeof(work_item_data)); + } + } + + // structure alignment is derived from the size of the larger field in it + // size of the structure is the size of the largest field multiple by the number of fields + + void calcSizeAndAlignment(typedef_struct_type *pStruct) + { + m_alignment = sizeof(cl_float) * 4; + m_size = m_alignment * 2 ; + } + + void calcSizeAndAlignment(image_kernel_data *pStruct) + { + m_alignment = sizeof(cl_int); + m_size = sizeof(image_kernel_data) ; + } + + void calcSizeAndAlignment(testStruct *pStruct) + { + m_alignment = sizeof(cl_double) * 16; + m_size = m_alignment; + } + + void calcSizeAndAlignment(work_item_data *pStruct) + { + m_alignment = sizeof(cl_uint); + m_size = sizeof(work_item_data); + } + + private: + bool m_isBuffer; + size_t m_vectorSize; + int m_alignment; + size_t m_size; +}; + +/** + Kernel argument generator for the simple scalar and vector types + */ +template class KernelArgGeneratorT: public KernelArgGenerator +{ +public: + KernelArgGeneratorT( bool isBuffer, size_t vectorSize, T minValue, T maxValue ): + m_isBuffer(isBuffer), + m_vectorSize(vectorSize), + m_minValue(minValue), + m_maxValue(maxValue) + {} + + KernelArg* generate( cl_context context, + const WorkSizeInfo& ws, + const KernelArgInfo& argInfo, + const KernelArg* refArg, + const cl_kernel kernel, + const cl_device_id device ) + { + T* pBuffer = NULL; + size_t size = 0; + int alignment, error; + cl_ulong totalDeviceLocalMem; + cl_ulong localMemUsedByKernel; + cl_uint numArgs, numLocalArgs = 0; + KernelArgInfo kernel_arg_info; + + error = CL_SUCCESS; + + // take care of 3-elements vector's alignment issue: + // if 3-elements vector - the alignment is 4-elements + if (m_vectorSize == 3) + alignment = sizeof(T) * 4; + else + alignment = sizeof(T) * m_vectorSize; + + // gather information about the kernel and device + clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(totalDeviceLocalMem), &totalDeviceLocalMem, NULL); + clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_LOCAL_MEM_SIZE, sizeof(localMemUsedByKernel), &localMemUsedByKernel, NULL); + clGetKernelInfo(kernel, CL_KERNEL_NUM_ARGS, sizeof(numArgs), &numArgs, NULL); + + // Calculate the number of local memory arguments + for (cl_uint i = 0; i < numArgs; i ++) + { + error = clGetKernelArgInfo( kernel, i, CL_KERNEL_ARG_ADDRESS_QUALIFIER, sizeof(cl_kernel_arg_address_qualifier), kernel_arg_info.getAddressQualifierRef(), &size); + if( error != CL_SUCCESS ) + { + throw Exceptions::TestError("Unable to get argument address qualifier\n", error); + } + + if(kernel_arg_info.getAddressQualifier() == CL_KERNEL_ARG_ADDRESS_LOCAL) + { + numLocalArgs ++; + } + } + + // reduce the amount of local memory by the amount the kernel + implementation uses + totalDeviceLocalMem -= localMemUsedByKernel; + + if( m_isBuffer ) + { + cl_kernel_arg_address_qualifier addrQ = argInfo.getAddressQualifier(); + + // decide about the buffer size - take into account the alignment and padding + size = ws.getGlobalWorkSize() * alignment; + + // reduce the size of the buffer for local memory + if (numLocalArgs && + size > floor(static_cast(totalDeviceLocalMem / numLocalArgs)) && + addrQ == CL_KERNEL_ARG_ADDRESS_LOCAL) + { + size = floor(static_cast(totalDeviceLocalMem / numLocalArgs)); + } + + if( CL_KERNEL_ARG_ADDRESS_CONSTANT == addrQ ) + { + if ( CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE < size ) + size = CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE; + } + + if( CL_KERNEL_ARG_ADDRESS_GLOBAL == addrQ || + CL_KERNEL_ARG_ADDRESS_CONSTANT == addrQ ) + { + pBuffer = (T *)align_malloc(size, alignment); + if (NULL == pBuffer) + { + throw Exceptions::TestError("align_malloc failed for array buffer\n", 1); + } + assert( (size_t)pBuffer % alignment == 0 ); + if (NULL == refArg) + { + fillBuffer(pBuffer, size / sizeof(T)); + } + else { + memcpy(pBuffer, refArg->getBuffer(), size); + } + } + return new KernelArgBuffer( context, argInfo, (void*)pBuffer, size); + } + else + { + if (m_vectorSize == 3) + size = sizeof(T) * 4; + else + size = sizeof(T) * m_vectorSize; + + pBuffer = (T *)align_malloc(size, alignment); + if (NULL == pBuffer) + { + throw Exceptions::TestError("align_malloc failed for pBuffer\n", 1); + } + assert( (size_t)pBuffer % alignment == 0 ); + if (NULL == refArg) + { + fillBuffer(pBuffer, m_vectorSize); + } + else { + memcpy(pBuffer, refArg->getBuffer(), size); + } + return new KernelArg( argInfo, (void*)pBuffer, size); + } + } +private: + void fillBuffer( T* buffer, size_t nelem) + { + for( size_t i = 0; i < nelem; ++i ) + { + buffer[i] = gRG.getNext(m_minValue, m_maxValue); + } + } + +private: + bool m_isBuffer; + size_t m_vectorSize; + T m_minValue; + T m_maxValue; +}; + +/** + General facade for the kernel arguments generation functionality. + */ +class DataGenerator +{ +public: + static DataGenerator* getInstance(); + + ~DataGenerator(); + + KernelArg* generateKernelArg(cl_context context, + const KernelArgInfo& argInfo, + const WorkSizeInfo& ws, + const KernelArg* refArg, + const cl_kernel kernel, + const cl_device_id device) + { + KernelArgGenerator* pArgGenerator = getArgGenerator(argInfo); + return pArgGenerator->generate(context, ws, argInfo, refArg, kernel, device); + } + + /* + * Gets the generator associated to the given key. + */ + KernelArgGenerator* getArgGenerator(const KernelArgInfo& argInfo); + + /* + * Sets the entry associated to the given key, with the given prototype + * generator. + */ + void setArgGenerator(const KernelArgInfo& key, KernelArgGenerator* gen); + +private: + DataGenerator(); + + static DataGenerator *Instance; + + typedef std::map ArgGeneratorsMap; + ArgGeneratorsMap m_argGenerators; +}; + +class ImageValuesGenerator +{ +public: + class iterator + { + friend class ImageValuesGenerator; + public: + /* + * Iterator operators. + */ + iterator& operator ++(); + bool operator == (const iterator&) const; + bool operator != (const iterator&) const; + /* + * Returns the name of the basic image type (e.g., image2d_t). + */ + std::string getImageTypeName() const; + + /* + * Returns the name of the genrator that generates images of this type + * (e.g., imaget2d_float). + */ + std::string getImageGeneratorName() const; + + /* + * Returns the name of the genrator that generates images of the 'base' + * type (e.g., imaget2d_t). + */ + std::string getBaseImageGeneratorName() const; + + /* + * Returns the OpenCL enumeration for the channel order of the image + * object this iterator creates. + */ + int getOpenCLChannelOrder() const; + + /* + * Returns the SPIR enumeration for the channel order of the image + * object this iterator creates. + */ + int getSPIRChannelOrder() const; + + /* + * Returns the data type of the image object this iterator creates. (e.g., + * cl_float, cl_int). + */ + int getDataType() const; + + /* + * Returns the data type of the image object this iterator creates. (e.g., + * float, int), in string format. + */ + std::string getDataTypeName() const; + + std::string toString() const; + private: + /* + * Constructor for creating a 'begin' iterator. + */ + iterator(ImageValuesGenerator*); + /* + * Constructor for creating an 'end' iterator. + */ + iterator(int); + /* + * Increments the given argument up to the given limit. + * In case the new value reaches the limit, the index is reset to hold zero. + * Returns: true if the value of the index was incremented, false if it was reset + * to zero. + */ + bool incrementIndex(size_t& index, size_t limit); + + /* + * Returns true is the index combination of this iterator is legal, + * or false otherwise. + */ + bool isLegalCombination() const; + + ImageValuesGenerator* m_parent; + size_t m_channelIndex, m_imgTyIndex; + }; //End iterator. + + iterator begin(); + iterator end(); + + static cl_channel_order channelOrders[]; + static const char* imageTypes[]; +private: + WorkSizeInfo m_wsInfo; +}; + +#endif diff --git a/test_conformance/spir/enum_values.zip b/test_conformance/spir/enum_values.zip new file mode 100644 index 0000000000000000000000000000000000000000..8e30f52d7cb2c317b0ab83a2c35de9595a5bc089 GIT binary patch literal 10746 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 literal 0 HcmV?d00001 diff --git a/test_conformance/spir/exceptions.h b/test_conformance/spir/exceptions.h new file mode 100644 index 00000000..61215102 --- /dev/null +++ b/test_conformance/spir/exceptions.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2017 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef __EXCEPTIONS_H +#define __EXCEPTIONS_H + +#include +#include "../../test_common/miniz/miniz.h" + +namespace Exceptions +{ + /** + Exception thrown on error in command line parameters + */ + class CmdLineError : public std::runtime_error + { + public: + CmdLineError (const std::string& msg): std::runtime_error(msg){} + }; + + /** + Exception thrown on error in test run + */ + class TestError : public std::runtime_error + { + public: + TestError (const std::string& msg, int errorCode = 1): std::runtime_error(msg), m_errorCode(errorCode){} + + int getErrorCode() const { return m_errorCode; } + private: + int m_errorCode; + }; + + class ArchiveError : public std::runtime_error + { + public: + ArchiveError(int errCode): std::runtime_error(mz_error(errCode)){} + }; +} + +#endif diff --git a/test_conformance/spir/geometrics.zip b/test_conformance/spir/geometrics.zip new file mode 100644 index 0000000000000000000000000000000000000000..73a5dd378fe8f0238b440ffdcd7d51b6776ec6b7 GIT binary patch literal 157176 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

    |f(u zyp-k8kwW`~J6M z{lC=N|1(AF|1Z{0YwamxO6Q>5Ao%C&s4<2{kQTd`6JZz%bbcgPnd3G?N_fyNo7$+4 z0A*>@N+wr?^M*0#lWx$W$2uU;?|gF4etP%0>a5;~`_5_!6bl73-v^Nc=#l0i1ZVKo z9jNFWM6PfNiLlZq$31u~gnR)vjp^mfYx;uaSov+JX)|3<3ih@ zqXJlSzC~$M5qFmSm;8;$LTHX3U@J4ozZI<$5@b<&>S&Y3D4{HMko>GJ_rkb+Z8JH9 z@Deq&XzrY#@4V9lh+BIDW*24jdifAQcn&?esQ31WIP7Cr3=AaOt^#==l%ZR*IrQLw z1yq2TwMpPB3_P|z6jn*QYHo{5Q;Um>d*yr`@KjZ7%2JiiVGU@xRdzzWq#^{Mk%;^R zqwWq4son6UH(i$;5DD1)ejUbTmqQ>`r+Oj*AJIzFf&ylir^z95o3>PO?}wuB_9 ztCK#Lhh-Q>PREiD{*}vDT3UUXjEt6{*IMPUZz&CfC}L)SJHe@L^2<)o*YJwFIO3tN z5~g0z!glg4(e%hPEAD%?5z--G?NpECo|B#XgseFAoqzGNJC>KmgY=kPaEqT& z7a0=CQZz;amTX|N1(P_pI;5Rv#%0A|VOiGK){0|ErTMHX!9zU4D5*kf2pjq`;u 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 z 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

    %zAoR| zSFCs>y<{t@^fAkqFH6Cqoh&i2=@cmeG@BVnlDT}3-{gl8D(H}uZ=t2$5HgK{kR;I_ z2@%k@0n1V~RSeG%W0uE#?f_3O$;zs$Z{ZbgU6FMee#iq!E~x>MIt>21q~VJfGu;(c zY(iPCla2Di7zhTAj4n<{;2ZP^C{u4i*)EIAwsGG4$WJ}~#Mli2RudFHKL8ZwYupxq3WvH)-Hq1td4uOc$P_*OqJtk7A5x0@7_4{K8yf25YP-i(ZEhufPxMHTXH2>+Ea_ zS6`<`W>~~p3oy$+7U=WhP;2G+V=RYB7d)&}F@Cyz9yCn27p_qQ6Da@w88$w?I zF9kG-AH(0(rqJC%h-F1LXUoWuR8h^P)N(tM7QO8xR3E~lzm)P8kHU(p@bM~mxCu+a^Cn>Pl$ zTI;CgCVSEUSW qAHZ#yorOa>Ua}dqvb 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 literal 0 HcmV?d00001 diff --git a/test_conformance/spir/half.zip b/test_conformance/spir/half.zip new file mode 100644 index 0000000000000000000000000000000000000000..f0d3e8ff3d10d8770eae3db1ac8a1b6a14b7dd57 GIT binary patch literal 1270366 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ℜ=saWR3?eq$hqiPea`pS_64!;cB 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�*led4jw0Zg2hI?Zu+x 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%0A#a~8l9!g);4#jezZ7pPJ<)a%Y1sZd)M4 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 z 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∈53SToi48=2alX-XaJNI~ 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�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 z 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�o5Ez5(eX}t8>#JS& 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

    y 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 M=4OwF7GeMUKSaoHmjD0& literal 0 HcmV?d00001 diff --git a/test_conformance/spir/images_kernel_read_write.zip b/test_conformance/spir/images_kernel_read_write.zip new file mode 100644 index 0000000000000000000000000000000000000000..65fa872870ae89229844d41238247014a0772e1f GIT binary patch literal 164635 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

    BvVh4%c=NY3@SJ+$0eU| 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

    5F?^I( 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 E09=ysv;Y7A literal 0 HcmV?d00001 diff --git a/test_conformance/spir/integer_ops.zip b/test_conformance/spir/integer_ops.zip new file mode 100644 index 0000000000000000000000000000000000000000..e93df165ce1556dd8c6f154a6e612dd5e9478072 GIT binary patch literal 2517236 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%0DYR&vi0_QQE+=^t%N)tI(t(6|6VdhyA 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 z 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%0DZ*6~h_o44XA(gr|X5SA!xQIT0 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%0AlIh@4~f^Q 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𝔶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

    0HcyRn`aKb{NPX$qa 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¾ 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

    G||^G!$+a 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¥g?w{GhWU1VK}RvFu_=A5ui_8pFSd2`O_ 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%0DsCtY;jHJQ{ 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

    h;vRwQ;neGS7;kqSL9Eke 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

    $66C0c0Md4Andifj|t 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

    GacO)AM3TURR(TlzgWqmuX<_(h(8&K1 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

    ICV-qlP7Nfytvu_^Gn))=QG99WT3VU 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%0Ary=V`Eg&=dW!)NhK683Tz?B;VI-4Iho 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 z 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%0D0YNctQ2G#2j@8PBFJ?E7wmzIPgf-6Eowc; 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%0A;X%3;i1H9vHa4lo`_O@5Q)$zyJ6q3 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%0D4&a4?mhGIZ@J|y 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